Add navigation menu to all pages + change routes.

To achieve that, this PR
- converts static/index.html ("console") and graph to templates
- moved the handlebars template to separated file to avoid escaping issues

Route changes:
/status -> /
/static -> /console
/static/graph.html -> /graph
pull/118/head
Johannes 'fish' Ziemke 2013-04-02 19:14:02 +02:00
parent fed467ede0
commit 1a3fb459e0
9 changed files with 131 additions and 90 deletions

26
web/handler.go Normal file
View File

@ -0,0 +1,26 @@
// Copyright 2013 Prometheus Team
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package web
import (
"net/http"
)
func graphHandler(w http.ResponseWriter, r *http.Request) {
executeTemplate(w, "graph", nil)
}
func consoleHandler(w http.ResponseWriter, r *http.Request) {
executeTemplate(w, "console", nil)
}

View File

@ -2,8 +2,8 @@ body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 14px; font-size: 14px;
line-height: 20px; line-height: 20px;
color: #333333; color: #333;
background-color: #eee; background-color: #f2f2f2;
margin: 0px; margin: 0px;
padding: 0px; padding: 0px;
} }
@ -49,3 +49,15 @@ input[name=end_input], input[name=range_input] {
margin-left: -4px; margin-left: -4px;
margin-right: -4px; margin-right: -4px;
} }
#navigation {
font-size: 20pt;
background-color: #333;
color: #F2F2F2;
line-height: 120%;
}
#navigation a { padding-right: 1em; text-decoration: none }
#navigation a:visited { color: #F2F2F2 }
#navigation a:active { color: #F60 }
#navigation a:hover { color: #06C }

View File

@ -20,6 +20,7 @@
var Prometheus = Prometheus || {}; var Prometheus = Prometheus || {};
var graphs = []; var graphs = [];
var graphTemplate;
Prometheus.Graph = function(element, options) { Prometheus.Graph = function(element, options) {
this.el = element; this.el = element;
@ -57,9 +58,8 @@ Prometheus.Graph.prototype.initialize = function() {
self.options['stacked_checked'] = self.options['stacked'] ? "checked" : ""; self.options['stacked_checked'] = self.options['stacked'] ? "checked" : "";
// Draw graph controls and container from Handlebars template. // Draw graph controls and container from Handlebars template.
var source = $("#graph_template").html();
var template = Handlebars.compile(source); var graphHtml = graphTemplate(self.options);
var graphHtml = template(self.options);
self.el.append(graphHtml); self.el.append(graphHtml);
// Get references to all the interesting elements in the graph container and // Get references to all the interesting elements in the graph container and
@ -428,15 +428,22 @@ function init() {
cache: false cache: false
}); });
var options = parseGraphOptionsFromUrl(); $.ajax({
if (options.length == 0) { url: "/static/js/graph_template.handlebar",
options.push({}); success: function(data) {
} console.log("got template")
for (var i = 0; i < options.length; i++) { console.log(data)
addGraph(options[i]); graphTemplate = Handlebars.compile(data);
} var options = parseGraphOptionsFromUrl();
if (options.length == 0) {
$("#add_graph").click(function() { addGraph({}); }); options.push({});
}
for (var i = 0; i < options.length; i++) {
addGraph(options[i]);
}
$("#add_graph").click(function() { addGraph({}); });
}
})
} }
$(init); $(init);

View File

@ -0,0 +1,42 @@
<div id="graph_wrapper{{id}}">
<div class="grouping_box">
<form action="/api/query_range" method="GET" class="query_form">
<div class="head">
<div class="expr">
<input placeholder="Expression" type="text" name="expr" id="expr{{id}}" size="80" value="{{expr}}">
<select name="insert_metric">
<option value="">- Insert Metric -</option>
</select>
</div>
<div class="config">
<label for="range_input{{id}}">Range:</label>
<input type="button" value="-" name="dec_range">
<input type="text" name="range_input" id="range_input{{id}}" size="2" value="{{range_input}}" >
<input type="hidden" name="range">
<input type="button" value="+" name="inc_range">
<input type="button" value="&larr;" name="dec_end">
<input placeholder="Until" type="text" name="end_input" id="end{{id}}" size="16" value="{{end }}">
<input type="button" value="&rarr;" name="inc_end">
<input type="hidden" name="end">
<input placeholder="Resolution (s)" type="text" name="step_input" id="step_input{{id}}" value ="{{step_input}}" size="10">
<input type="hidden" name="step">
<span class="opts">
<input type="checkbox" name="stacked" id="stacked{{id}}" {{stacked_checked}}>
<label for="stacked{{id}}">Stacked</label>
<input type="submit" value="Graph" name="submit">
</span>
</div>
</div>
<div class="eval_stats"></div>
</form>
<img src="img/ajax-loader.gif" class="spinner" alt="ajax_spinner">
</div>
<div class="grouping_box">
<div class="graph_container">
<div class="graph"></div>
<div class="legend"></div>
</div>
</div>
</div>

View File

@ -4,10 +4,16 @@
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Prometheus</title> <title>Prometheus</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<link type="text/css" rel="stylesheet" href="static/css/prometheus.css"> <link type="text/css" rel="stylesheet" href="/static/css/prometheus.css">
{{template "head" .}}
</head> </head>
<body> <body>
<div id="navigation">
<a href="/console">Console</a>
<a href="/graph">Graph</a>
<a href="/">Status</a>
</div>
{{template "content" .}} {{template "content" .}}
</body> </body>
</html> </html>

View File

@ -1,15 +1,8 @@
<!DOCTYPE html> {{define "head"}}
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Prometheus Expression Browser</title>
<link type="text/css" rel="stylesheet" href="css/prometheus.css">
<link type="text/css" rel="stylesheet" href="css/graph.css">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="js/exprBrowser.js"></script> <script src="js/exprBrowser.js"></script>
</head> {{end}}
<body> {{define "content"}}
<div class="grouping_box"> <div class="grouping_box">
<form action="/api/query" method="GET" id="queryForm"> <form action="/api/query" method="GET" id="queryForm">
<label for="expr">Expression:</label> <label for="expr">Expression:</label>
@ -23,5 +16,4 @@
<div id="result"></div> <div id="result"></div>
</pre> </pre>
</div> </div>
</body> {{end}}
</html>

View File

@ -1,17 +1,12 @@
<!DOCTYPE html> {{define "head"}}
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Prometheus Expression Browser</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.9.1/jquery-ui.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.9.1/jquery-ui.min.js"></script>
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.9.1/themes/base/jquery-ui.css" /> <link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.9.1/themes/base/jquery-ui.css" />
<link type="text/css" rel="stylesheet" href="css/prometheus.css"> <link type="text/css" rel="stylesheet" href="/static/css/prometheus.css">
<link type="text/css" rel="stylesheet" href="css/graph.css"> <link type="text/css" rel="stylesheet" href="/static/css/graph.css">
<script src="vendor/jquery-simple-datetimepicker/jquery.simple-dtpicker.js"></script> <script src="/static/vendor/jquery-simple-datetimepicker/jquery.simple-dtpicker.js"></script>
<link type="text/css" rel="stylesheet" href="vendor/jquery-simple-datetimepicker/jquery.simple-dtpicker.css"> <link type="text/css" rel="stylesheet" href="/static/vendor/jquery-simple-datetimepicker/jquery.simple-dtpicker.css">
<!-- copy all these CSSen/JSen to our own location --> <!-- copy all these CSSen/JSen to our own location -->
<link type="text/css" rel="stylesheet" href="http://code.shutterstock.com/rickshaw/rickshaw.min.css"> <link type="text/css" rel="stylesheet" href="http://code.shutterstock.com/rickshaw/rickshaw.min.css">
@ -19,61 +14,17 @@
<script src="http://code.shutterstock.com/rickshaw/vendor/d3.layout.min.js"></script> <script src="http://code.shutterstock.com/rickshaw/vendor/d3.layout.min.js"></script>
<script src="http://code.shutterstock.com/rickshaw/rickshaw.min.js"></script> <script src="http://code.shutterstock.com/rickshaw/rickshaw.min.js"></script>
<script src="vendor/js/handlebars.js"></script> <script src="/static/vendor/js/handlebars.js"></script>
<script src="vendor/js/jquery.selection.js"></script> <script src="/static/vendor/js/jquery.selection.js"></script>
<script src="vendor/js/jquery.hotkeys.js"></script> <script src="/static/vendor/js/jquery.hotkeys.js"></script>
<script src="js/graph.js"></script> <script src="/static/js/graph.js"></script>
<script id="graph_template" type="text/x-handlebars-template"> <script id="graph_template" type="text/x-handlebars-template"></script>
<div id="graph_wrapper{{id}}"> {{end}}
<div class="grouping_box">
<form action="/api/query_range" method="GET" class="query_form">
<div class="head">
<div class="expr">
<input placeholder="Expression" type="text" name="expr" id="expr{{id}}" size="80" value="{{expr}}">
<select name="insert_metric">
<option value="">- Insert Metric -</option>
</select>
</div>
<div class="config">
<label for="range_input{{id}}">Range:</label>
<input type="button" value="-" name="dec_range">
<input type="text" name="range_input" id="range_input{{id}}" size="2" value="{{range_input}}">
<input type="hidden" name="range">
<input type="button" value="+" name="inc_range">
<input type="button" value="&larr;" name="dec_end">
<input placeholder="Until" type="text" name="end_input" id="end{{id}}" size="16" value="{{end}}">
<input type="button" value="&rarr;" name="inc_end">
<input type="hidden" name="end">
<input placeholder="Resolution (s)" type="text" name="step_input" id="step_input{{id}}" value="{{step_input}}" size="10">
<input type="hidden" name="step">
<span class="opts">
<input type="checkbox" name="stacked" id="stacked{{id}}" {{stacked_checked}}>
<label for="stacked{{id}}">Stacked</label>
<input type="submit" value="Graph" name="submit">
</span>
</div>
</div>
<div class="eval_stats"></div>
</form>
<img src="img/ajax-loader.gif" class="spinner" alt="ajax_spinner">
</div>
<div class="grouping_box">
<div class="graph_container">
<div class="graph"></div>
<div class="legend"></div>
</div>
</div>
</div>
</script>
</head>
<body> {{define "content"}}
<div id="graph_container"> <div id="graph_container">
</div> </div>
<div><input type="button" value="Add Graph" id="add_graph"></div> <div><input type="button" value="Add Graph" id="add_graph"></div>
</body> {{end}}
</html>

View File

@ -1,3 +1,5 @@
{{define "head"}}<!-- nix -->{{end}}
{{define "content"}} {{define "content"}}
<h2>Status</h2> <h2>Status</h2>
<div class="grouping_box"> <div class="grouping_box">

View File

@ -36,7 +36,10 @@ func StartServing(appState *appstate.ApplicationState) {
gorest.RegisterService(api.NewMetricsService(appState)) gorest.RegisterService(api.NewMetricsService(appState))
exporter := registry.DefaultRegistry.YieldExporter() exporter := registry.DefaultRegistry.YieldExporter()
http.Handle("/status", &StatusHandler{appState: appState}) http.Handle("/", &StatusHandler{appState: appState})
http.HandleFunc("/graph", graphHandler)
http.HandleFunc("/console", consoleHandler)
http.Handle("/api/", gorest.Handle()) http.Handle("/api/", gorest.Handle())
http.Handle("/metrics.json", exporter) http.Handle("/metrics.json", exporter)
if *useLocalAssets { if *useLocalAssets {