Commit
+804 -0 +/-3 browse
1 | diff --git a/main.go b/main.go |
2 | index 6d90470..1c08906 100644 |
3 | --- a/main.go |
4 | +++ b/main.go |
5 | @@ -10,6 +10,7 @@ import ( |
6 | "net/http" |
7 | "net/url" |
8 | "os" |
9 | + "path/filepath" |
10 | "sort" |
11 | "strconv" |
12 | "strings" |
13 | @@ -300,6 +301,17 @@ func main() { |
14 | registerExtension(router, "svg", "image/svg+xml") |
15 | registerExtension(router, "png", "image/png") |
16 | |
17 | + staticDir := os.Getenv("CHARTSRV_STATICDIR") |
18 | + if staticDir == "" { |
19 | + staticDir = "static" |
20 | + } |
21 | + |
22 | + router.Get("/*", func(w http.ResponseWriter, r *http.Request) { |
23 | + workDir, _ := os.Getwd() |
24 | + fs := http.FileServer(http.Dir(filepath.Join(workDir, staticDir))) |
25 | + fs.ServeHTTP(w, r) |
26 | + }) |
27 | + |
28 | addr := ":8142" |
29 | if len(os.Args) > 2 { |
30 | addr = os.Args[2] |
31 | diff --git a/static/base.css b/static/base.css |
32 | new file mode 100644 |
33 | index 0000000..b964f4d |
34 | --- /dev/null |
35 | +++ b/static/base.css |
36 | @@ -0,0 +1,540 @@ |
37 | + * { |
38 | + box-sizing: border-box; } |
39 | + |
40 | + html { |
41 | + line-height: 1.15; |
42 | + -webkit-text-size-adjust: 100%; } |
43 | + |
44 | + body { |
45 | + margin: 0; } |
46 | + |
47 | + main { |
48 | + display: block; } |
49 | + |
50 | + h1 { |
51 | + font-size: 2em; |
52 | + margin: 0.67em 0; } |
53 | + |
54 | + hr { |
55 | + box-sizing: content-box; |
56 | + height: 0; |
57 | + overflow: visible; } |
58 | + |
59 | + pre { |
60 | + font-family: monospace, monospace; |
61 | + font-size: 1em; } |
62 | + |
63 | + a { |
64 | + background-color: transparent; } |
65 | + |
66 | + abbr[title] { |
67 | + border-bottom: none; |
68 | + text-decoration: underline; |
69 | + text-decoration: underline dotted; } |
70 | + |
71 | + b, |
72 | + strong { |
73 | + font-weight: bolder; } |
74 | + |
75 | + code, |
76 | + kbd, |
77 | + samp { |
78 | + font-family: monospace, monospace; |
79 | + font-size: 1em; } |
80 | + |
81 | + small { |
82 | + font-size: 80%; } |
83 | + |
84 | + sub, |
85 | + sup { |
86 | + font-size: 75%; |
87 | + line-height: 0; |
88 | + position: relative; |
89 | + vertical-align: baseline; } |
90 | + |
91 | + sub { |
92 | + bottom: -0.25em; } |
93 | + |
94 | + sup { |
95 | + top: -0.5em; } |
96 | + |
97 | + img { |
98 | + border-style: none; } |
99 | + |
100 | + button, |
101 | + input, |
102 | + optgroup, |
103 | + select, |
104 | + textarea { |
105 | + font-family: inherit; |
106 | + font-size: 100%; |
107 | + line-height: 1.15; |
108 | + margin: 0; } |
109 | + |
110 | + button, |
111 | + input { |
112 | + overflow: visible; } |
113 | + |
114 | + button, |
115 | + select { |
116 | + text-transform: none; } |
117 | + |
118 | + button, |
119 | + [type="button"], |
120 | + [type="reset"], |
121 | + [type="submit"] { |
122 | + -webkit-appearance: button; } |
123 | + |
124 | + button::-moz-focus-inner, |
125 | + [type="button"]::-moz-focus-inner, |
126 | + [type="reset"]::-moz-focus-inner, |
127 | + [type="submit"]::-moz-focus-inner { |
128 | + border-style: none; |
129 | + padding: 0; } |
130 | + |
131 | + button:-moz-focusring, |
132 | + [type="button"]:-moz-focusring, |
133 | + [type="reset"]:-moz-focusring, |
134 | + [type="submit"]:-moz-focusring { |
135 | + outline: 1px dotted ButtonText; } |
136 | + |
137 | + fieldset { |
138 | + padding: 0.35em 0.75em 0.625em; } |
139 | + |
140 | + legend { |
141 | + box-sizing: border-box; |
142 | + color: inherit; |
143 | + display: table; |
144 | + max-width: 100%; |
145 | + padding: 0; |
146 | + white-space: normal; } |
147 | + |
148 | + progress { |
149 | + vertical-align: baseline; } |
150 | + |
151 | + textarea { |
152 | + overflow: auto; } |
153 | + |
154 | + [type="checkbox"], |
155 | + [type="radio"] { |
156 | + box-sizing: border-box; |
157 | + padding: 0; } |
158 | + |
159 | + [type="number"]::-webkit-inner-spin-button, |
160 | + [type="number"]::-webkit-outer-spin-button { |
161 | + height: auto; } |
162 | + |
163 | + [type="search"] { |
164 | + -webkit-appearance: textfield; |
165 | + outline-offset: -2px; } |
166 | + |
167 | + [type="search"]::-webkit-search-decoration { |
168 | + -webkit-appearance: none; } |
169 | + |
170 | + ::-webkit-file-upload-button { |
171 | + -webkit-appearance: button; |
172 | + font: inherit; } |
173 | + |
174 | + details { |
175 | + display: block; } |
176 | + |
177 | + summary { |
178 | + display: list-item; } |
179 | + |
180 | + template { |
181 | + display: none; } |
182 | + |
183 | + [hidden] { |
184 | + display: none; } |
185 | + |
186 | + @media (prefers-color-scheme: dark) { |
187 | + html { |
188 | + background: #212529; |
189 | + color: #fff; } } |
190 | + |
191 | + body { |
192 | + font-family: sans-serif; |
193 | + padding-bottom: 1rem; } |
194 | + |
195 | + main, .main { |
196 | + max-width: 1140px; |
197 | + margin: 0 auto; } |
198 | + |
199 | + table.grid { |
200 | + width: 100%; |
201 | + border-collapse: collapse; |
202 | + margin: 0 -1rem; } |
203 | + table.grid td { |
204 | + vertical-align: top; |
205 | + padding: 0 1rem; |
206 | + width: 8.3333333333%; } |
207 | + table.grid td[colspan="1"] { |
208 | + width: 8.3333333333%; } |
209 | + table.grid td[colspan="2"] { |
210 | + width: 16.6666666667%; } |
211 | + table.grid td[colspan="3"] { |
212 | + width: 25%; } |
213 | + table.grid td[colspan="4"] { |
214 | + width: 33.3333333333%; } |
215 | + table.grid td[colspan="5"] { |
216 | + width: 41.6666666667%; } |
217 | + table.grid td[colspan="6"] { |
218 | + width: 50%; } |
219 | + table.grid td[colspan="7"] { |
220 | + width: 58.3333333333%; } |
221 | + table.grid td[colspan="8"] { |
222 | + width: 66.6666666667%; } |
223 | + table.grid td[colspan="9"] { |
224 | + width: 75%; } |
225 | + table.grid td[colspan="10"] { |
226 | + width: 83.3333333333%; } |
227 | + table.grid td[colspan="11"] { |
228 | + width: 91.6666666667%; } |
229 | + table.grid td[colspan="12"] { |
230 | + width: 100%; } |
231 | + @supports (display: flex) { |
232 | + table.grid { |
233 | + display: flex; } |
234 | + table.grid tbody { |
235 | + display: flex; |
236 | + flex-grow: 1; |
237 | + flex-direction: column; } |
238 | + table.grid tr { |
239 | + display: flex; } |
240 | + table.grid td { |
241 | + display: block; } } |
242 | + |
243 | + .dl, article dl { |
244 | + text-align: left; |
245 | + margin-left: 0; } |
246 | + |
247 | + .dt, article dt { |
248 | + font-weight: normal; |
249 | + padding: 0; } |
250 | + |
251 | + .blockquote, article blockquote { |
252 | + margin-left: -1rem; |
253 | + margin-left: calc(-4px - 1rem); |
254 | + padding-left: 1rem; |
255 | + border-left: solid 4px #ced4da; } |
256 | + @media (prefers-color-scheme: dark) { |
257 | + .blockquote, article blockquote { |
258 | + border-left: solid 4px #6c757d; } } |
259 | + .figure, article figure { |
260 | + margin: 0; } |
261 | + .figure img, article figure img { |
262 | + display: block; |
263 | + max-width: 80%; |
264 | + margin: 0 auto; } |
265 | + .figure figcaption, article figure figcaption { |
266 | + display: block; |
267 | + text-align: center; |
268 | + margin: 0 auto; |
269 | + font-size: 0.9rem; |
270 | + max-width: 70%; } |
271 | + |
272 | + .aside, article aside { |
273 | + float: right; |
274 | + max-width: 40%; |
275 | + padding-left: 1rem; |
276 | + margin-left: 1rem; |
277 | + border-left: solid 4px #ced4da; } |
278 | + @media (prefers-color-scheme: dark) { |
279 | + .aside, article aside { |
280 | + border-left: solid 4px #6c757d; } } |
281 | + .pre, article pre { |
282 | + background: #e9ecef; |
283 | + margin: 0 -1rem; |
284 | + padding: 1rem; } |
285 | + @media (prefers-color-scheme: dark) { |
286 | + .pre, article pre { |
287 | + background: #131618; } } |
288 | + .table, article table { |
289 | + width: 100%; |
290 | + border-collapse: collapse; } |
291 | + .table th, article table th { |
292 | + text-align: left; |
293 | + border-bottom: solid 1px #131618; } |
294 | + @media (prefers-color-scheme: dark) { |
295 | + .table th, article table th { |
296 | + border-bottom: solid 1px #fff; } } |
297 | + a, .link, .tabs h1 a, .tabs h2 a, .tabs h3 a, .tabs h4 a, .tabs h5 a { |
298 | + color: #007bff; } |
299 | + a:hover, .link:hover, .tabs h1 a:hover, .tabs h2 a:hover, .tabs h3 a:hover, .tabs h4 a:hover, .tabs h5 a:hover { |
300 | + text-decoration: none; } |
301 | + a:active, .link:active, .tabs h1 a:active, .tabs h2 a:active, .tabs h3 a:active, .tabs h4 a:active, .tabs h5 a:active { |
302 | + color: #0062cc; } |
303 | + a:visited, .link:visited, .tabs h1 a:visited, .tabs h2 a:visited, .tabs h3 a:visited, .tabs h4 a:visited, .tabs h5 a:visited { |
304 | + color: #004a99; } |
305 | + @media (prefers-color-scheme: dark) { |
306 | + a, .link, .tabs h1 a, .tabs h2 a, .tabs h3 a, .tabs h4 a, .tabs h5 a { |
307 | + color: #3395ff; } |
308 | + a:active, .link:active, .tabs h1 a:active, .tabs h2 a:active, .tabs h3 a:active, .tabs h4 a:active, .tabs h5 a:active { |
309 | + color: #006fe6; } |
310 | + a:visited, .link:visited, .tabs h1 a:visited, .tabs h2 a:visited, .tabs h3 a:visited, .tabs h4 a:visited, .tabs h5 a:visited { |
311 | + color: #006fe6; } } |
312 | + h1 small { |
313 | + font-size: 1.2rem; } |
314 | + |
315 | + del { |
316 | + color: inherit; } |
317 | + |
318 | + hr { |
319 | + border: #ced4da solid 1px; } |
320 | + @media (prefers-color-scheme: dark) { |
321 | + hr { |
322 | + border: #6c757d solid 1px; } } |
323 | + .align-center { |
324 | + text-align: center; } |
325 | + |
326 | + .align-left { |
327 | + text-align: left; } |
328 | + |
329 | + .align-right { |
330 | + text-align: right; } |
331 | + |
332 | + .block { |
333 | + display: block !important; } |
334 | + |
335 | + .inline { |
336 | + display: inline !important; } |
337 | + |
338 | + .float-left { |
339 | + float: left; } |
340 | + |
341 | + .float-right { |
342 | + float: right; } |
343 | + |
344 | + .text-info { |
345 | + color: #17a2b8; } |
346 | + |
347 | + .text-success { |
348 | + color: #28a745; } |
349 | + |
350 | + .text-danger { |
351 | + color: #dc3545; } |
352 | + |
353 | + .text-muted, form .help, input[disabled] + label { |
354 | + color: #343a40; } |
355 | + @media (prefers-color-scheme: dark) { |
356 | + .text-muted, form .help, input[disabled] + label { |
357 | + color: #adb5bd; } } |
358 | + .alert { |
359 | + padding: 0.5rem; |
360 | + border: 1px solid transparent; |
361 | + margin-bottom: 1rem; } |
362 | + |
363 | + .alert-danger { |
364 | + background: #f8d7da; |
365 | + color: #842029; |
366 | + border-color: #f5c6cb; } |
367 | + |
368 | + .btn, button { |
369 | + display: inline-block; |
370 | + padding: .1rem .75rem; |
371 | + background: #e9ecef; |
372 | + border: #343a40 1px solid; |
373 | + font-size: 0.9rem; |
374 | + font-weight: 400; |
375 | + line-height: 1.5; |
376 | + cursor: pointer; |
377 | + color: #131618; |
378 | + border-radius: 0; |
379 | + transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out; } |
380 | + .btn:hover, button:hover { |
381 | + text-decoration: none; |
382 | + background: #f8f9fa; |
383 | + color: #131618; } |
384 | + @media (prefers-color-scheme: dark) { |
385 | + .btn, button { |
386 | + background: #212529; |
387 | + color: #fff; |
388 | + border: #495057 1px solid; } |
389 | + .btn:hover, button:hover { |
390 | + background: #131618; |
391 | + color: #fff; } } |
392 | + .btn-primary { |
393 | + border: #001933 1px solid; |
394 | + background: #007bff; |
395 | + color: #fff; } |
396 | + .btn-primary:hover { |
397 | + background: #0069d9; |
398 | + color: #fff; } |
399 | + @media (prefers-color-scheme: dark) { |
400 | + .btn-primary { |
401 | + background: #0062cc; |
402 | + color: #fff; |
403 | + border: #001933 1px solid; } |
404 | + .btn-primary:hover { |
405 | + background: #0069d9; |
406 | + color: #fff; } } |
407 | + a.btn { |
408 | + text-decoration: none; |
409 | + color: #131618; } |
410 | + @media (prefers-color-scheme: dark) { |
411 | + a.btn { |
412 | + color: #fff; } } |
413 | + a.btn-primary { |
414 | + color: #fff; } |
415 | + @media (prefers-color-scheme: dark) { |
416 | + a.btn-primary { |
417 | + color: #fff; } } |
418 | + .btn.block, button.block { |
419 | + margin-bottom: 0.5rem; } |
420 | + |
421 | + .form-field, .form-checkbox { |
422 | + margin-top: 1rem; } |
423 | + |
424 | + label { |
425 | + display: block; } |
426 | + |
427 | + input, textarea, select { |
428 | + display: block; |
429 | + width: 100%; |
430 | + border: 1px solid #888; |
431 | + padding: .375rem; |
432 | + font-size: 1rem; |
433 | + line-height: 1.5; |
434 | + background-color: #fff; |
435 | + background-clip: padding-box; |
436 | + transition: border-color .15s ease-in-out,box-shadow .15s ease-in-out; |
437 | + border-radius: 0; } |
438 | + input:focus, textarea:focus, select:focus { |
439 | + outline: 0; |
440 | + border-color: #80bdff; |
441 | + box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } |
442 | + @media (prefers-color-scheme: dark) { |
443 | + input, textarea, select { |
444 | + background: #131618; |
445 | + color: #fff; |
446 | + border-color: #6c757d; } |
447 | + input:active, input:focus, textarea:active, textarea:focus, select:active, select:focus { |
448 | + background: #212529; |
449 | + color: #fff; } |
450 | + input[disabled], input[readonly], textarea[disabled], textarea[readonly], select[disabled], select[readonly] { |
451 | + background: #212529; |
452 | + color: #ced4da; } } |
453 | + .has-error input, .has-error textarea, .has-error select { |
454 | + border-color: #dc3545; } |
455 | + |
456 | + .has-error .error { |
457 | + color: #dc3545; } |
458 | + |
459 | + tr:first-child td .form-field:first-child { |
460 | + margin-top: 0; } |
461 | + |
462 | + button { |
463 | + display: block; } |
464 | + |
465 | + button.block { |
466 | + width: 100%; } |
467 | + |
468 | + .form-checkbox input[type="checkbox"], |
469 | + .form-checkbox input[type="radio"] { |
470 | + float: left; |
471 | + width: 1em; |
472 | + height: 1em; |
473 | + margin-top: 0.1rem; |
474 | + margin-right: 0.25rem; |
475 | + vertical-align: top; } |
476 | + |
477 | + .form-checkbox label { |
478 | + display: inline-block; } |
479 | + |
480 | + .form-checkbox.inline { |
481 | + display: inline-block !important; |
482 | + margin-right: 1rem; } |
483 | + |
484 | + fieldset { |
485 | + border: none; |
486 | + padding: 0; |
487 | + margin-top: 1rem; } |
488 | + |
489 | + .inset, .infobox { |
490 | + background: #f8f9fa; |
491 | + padding: 1rem; } |
492 | + @media (prefers-color-scheme: dark) { |
493 | + .inset, .infobox { |
494 | + background: #131618; } } |
495 | + .infobox header { |
496 | + margin-bottom: 1rem; } |
497 | + |
498 | + .infobox :not(header) { |
499 | + margin: 0; } |
500 | + |
501 | + nav, .nav { |
502 | + max-width: 1140px; |
503 | + margin: 1rem auto; } |
504 | + nav ul, .nav ul { |
505 | + display: inline; |
506 | + margin: 0 -0.5rem; |
507 | + padding-left: 0; } |
508 | + nav li, .nav li { |
509 | + display: inline; |
510 | + margin: 0 0.5rem; } |
511 | + nav a, nav a:visited, .nav a, .nav a:visited { |
512 | + color: #131618; } |
513 | + @media (prefers-color-scheme: dark) { |
514 | + nav a, nav a:visited, .nav a, .nav a:visited { |
515 | + color: #fff; } } |
516 | + nav .active a, nav .active a:visited, .nav .active a, .nav .active a:visited { |
517 | + color: #007bff; } |
518 | + @media (prefers-color-scheme: dark) { |
519 | + nav .active a, nav .active a:visited, .nav .active a, .nav .active a:visited { |
520 | + color: #3395ff; } } |
521 | + nav .brand a, .nav .brand a { |
522 | + text-decoration: none; } |
523 | + nav .right, .nav .right { |
524 | + float: right; } |
525 | + |
526 | + .tabs:not(.tabs-aside) { |
527 | + border-bottom: solid 3px #ced4da; } |
528 | + @media (prefers-color-scheme: dark) { |
529 | + .tabs:not(.tabs-aside) { |
530 | + border-bottom: solid 3px #131618; } } |
531 | + .tabs nav { |
532 | + margin: 0 auto; |
533 | + position: relative; } |
534 | + |
535 | + .tabs h1, .tabs h2, .tabs h3, .tabs h4, .tabs h5 { |
536 | + display: inline; |
537 | + margin-right: 1rem; |
538 | + font-weight: normal; } |
539 | + |
540 | + .tabs ul { |
541 | + display: inline; |
542 | + margin: 0 -0.5rem; |
543 | + padding-left: 0; |
544 | + position: absolute; |
545 | + bottom: 0; } |
546 | + |
547 | + .tabs li { |
548 | + display: inline; |
549 | + margin: 0; } |
550 | + .tabs li a { |
551 | + padding: 0 1rem; } |
552 | + .tabs li.active, .tabs li:hover { |
553 | + background: #ced4da; } |
554 | + @media (prefers-color-scheme: dark) { |
555 | + .tabs li.active, .tabs li:hover { |
556 | + background: #131618; } } |
557 | + .tabs li.active a, .tabs li:hover a { |
558 | + color: #131618; } |
559 | + @media (prefers-color-scheme: dark) { |
560 | + .tabs li.active a, .tabs li:hover a { |
561 | + color: #fff; } } |
562 | + .tabs a { |
563 | + text-decoration: none; } |
564 | + |
565 | + .tabs aside { |
566 | + background: #ced4da; |
567 | + padding: 0.2rem 0; } |
568 | + @media (prefers-color-scheme: dark) { |
569 | + .tabs aside { |
570 | + background: #131618; } } |
571 | + .tabs aside p { |
572 | + margin: 0 auto; |
573 | + max-width: 1140px; } |
574 | + |
575 | + header + main { |
576 | + margin-top: 1rem; } |
577 | diff --git a/static/index.html b/static/index.html |
578 | new file mode 100644 |
579 | index 0000000..e1e6bcf |
580 | --- /dev/null |
581 | +++ b/static/index.html |
582 | @@ -0,0 +1,252 @@ |
583 | + <!doctype html> |
584 | + <html lang="en"> |
585 | + <meta charset="utf-8" /> |
586 | + <title>Chartsrv</title> |
587 | + <link rel="stylesheet" href="base.css" /> |
588 | + <style> |
589 | + #preview, #alert { max-width: 100%; margin-top: 0.25em; } |
590 | + </style> |
591 | + <main> |
592 | + <form> |
593 | + <table class="grid"> |
594 | + <tr> |
595 | + <td colspan="2"></td> |
596 | + <td colspan="10"> |
597 | + <h1>Chartsrv</h1> |
598 | + <p> |
599 | + Web service which renders SVG plots from Prometheus data. |
600 | + <a href="https://sr.ht/~sircmpwn/chartsrv/">See on SourceHut.</a> |
601 | + </p> |
602 | + <noscript> |
603 | + <p class="text-danger">Please enable JavaScript to use this tool.</p> |
604 | + </noscript> |
605 | + </td> |
606 | + <td colspan="2"></td> |
607 | + </tr> |
608 | + <tr> |
609 | + <td colspan="3"></td> |
610 | + <td colspan="4"> |
611 | + <div class="form-field"> |
612 | + <label for="instance"> |
613 | + Chartsrv instance <span class="text-danger">*</span> |
614 | + </label> |
615 | + <input type="text" id="instance" placeholder="metrics.sr.ht:8142" /> |
616 | + </div> |
617 | + </td> |
618 | + <td colspan="2"> |
619 | + <div class="form-field"> |
620 | + <label for="format">Format</label> |
621 | + <select id="format"> |
622 | + <option>svg</option> |
623 | + <option>png</option> |
624 | + </select> |
625 | + </div> |
626 | + </td> |
627 | + <td colspan="3"></td> |
628 | + </tr> |
629 | + <tr> |
630 | + <td colspan="3"></td> |
631 | + <td colspan="6"> |
632 | + <div class="form-field"> |
633 | + <label for="query">Query <span class="text-danger">*</span></label> |
634 | + <input type="text" id="query" |
635 | + value="avg_over_time(node_load15[1h])" /> |
636 | + </div> |
637 | + <div class="form-checkbox"> |
638 | + <input type="checkbox" id="stacked" /> |
639 | + <label for="stacked" class="checkbox">Stacked</label> |
640 | + </div> |
641 | + </td> |
642 | + <td colspan="3"></td> |
643 | + </tr> |
644 | + <tr> |
645 | + <td colspan="3"></td> |
646 | + <td colspan="2"> |
647 | + <div class="form-field"> |
648 | + <label for="since">Time from</label> |
649 | + <input type="text" id="since" placeholder="24h" /> |
650 | + </div> |
651 | + </td> |
652 | + <td colspan="2"> |
653 | + <div class="form-field"> |
654 | + <label for="until">Time to</label> |
655 | + <input type="text" id="until" /> |
656 | + </div> |
657 | + </td> |
658 | + <td colspan="2"> |
659 | + <div class="form-field"> |
660 | + <label for="step">Step</label> |
661 | + <input type="number" id="step" /> |
662 | + </div> |
663 | + </td> |
664 | + <td colspan="3"></td> |
665 | + </tr> |
666 | + <tr> |
667 | + <td colspan="3"></td> |
668 | + <td colspan="6"> |
669 | + <span class="help"> |
670 | + Time fields are relative to present and use |
671 | + <a href="https://godocs.io/time#ParseDuration">duration strings</a>. |
672 | + <em>Step</em> is in seconds. |
673 | + </span> |
674 | + </td> |
675 | + <td colspan="3"></td> |
676 | + </tr> |
677 | + <tr> |
678 | + <td colspan="3"></td> |
679 | + <td colspan="3"> |
680 | + <div class="form-field"> |
681 | + <label for="min">Y min</label> |
682 | + <input type="number" id="min" /> |
683 | + </div> |
684 | + </td> |
685 | + <td colspan="3"> |
686 | + <div class="form-field"> |
687 | + <label for="max">Y max</label> |
688 | + <input type="number" id="max" /> |
689 | + </div> |
690 | + </td> |
691 | + <td colspan="3"></td> |
692 | + </tr> |
693 | + <tr> |
694 | + <td colspan="3"></td> |
695 | + <td colspan="3"> |
696 | + <div class="form-field"> |
697 | + <label for="title">Title</label> |
698 | + <input type="text" id="title" /> |
699 | + </div> |
700 | + </td> |
701 | + <td colspan="3"> |
702 | + <div class="form-field"> |
703 | + <label for="label">Label</label> |
704 | + <input type="text" id="label" placeholder="{{.instance}}" |
705 | + value="{{.instance}}" /> |
706 | + </div> |
707 | + </td> |
708 | + <td colspan="3"></td> |
709 | + </tr> |
710 | + <tr> |
711 | + <td colspan="3"></td> |
712 | + <td colspan="6"> |
713 | + <span class="help"> |
714 | + <em>Label</em> accepts a |
715 | + <a href="https://godocs.io/text/template">template</a>. |
716 | + All Prometheus labels are available. |
717 | + </span> |
718 | + </td> |
719 | + <td colspan="3"></td> |
720 | + </tr> |
721 | + <tr> |
722 | + <td colspan="3"></td> |
723 | + <td colspan="3"> |
724 | + <div class="form-field"> |
725 | + <label for="width">Width</label> |
726 | + <input type="number" id="width" min="0" placeholder="12" /> |
727 | + </div> |
728 | + </td> |
729 | + <td colspan="3"> |
730 | + <div class="form-field"> |
731 | + <label for="height">Height</label> |
732 | + <input type="number" id="height" min="0" placeholder="6" /> |
733 | + </div> |
734 | + </td> |
735 | + <td colspan="3"></td> |
736 | + </tr> |
737 | + <tr> |
738 | + <td colspan="3"></td> |
739 | + <td colspan="6"> |
740 | + <span class="help"> |
741 | + Dimensions are in inches. DPI is fixed at 96. |
742 | + </span> |
743 | + </td> |
744 | + <td colspan="3"></td> |
745 | + </tr> |
746 | + <tr> |
747 | + <td colspan="3"></td> |
748 | + <td colspan="6"> |
749 | + <div class="form-field"> |
750 | + <label for="url">Chart URL</label> |
751 | + <input type="text" id="url" disabled /> |
752 | + </div> |
753 | + </td> |
754 | + <td colspan="3"></td> |
755 | + </tr> |
756 | + <tr> |
757 | + <td colspan="3"></td> |
758 | + <td colspan="6"> |
759 | + <div class="form-field"> |
760 | + <label for="preview">Chart preview</label> |
761 | + <div id="alert" class="alert alert-danger" style="display: none"> |
762 | + Loading preview failed. Are the parameters correct? |
763 | + </div> |
764 | + <img id="preview" alt="" /> |
765 | + </div> |
766 | + </td> |
767 | + <td colspan="3"></td> |
768 | + </tr> |
769 | + </table> |
770 | + </form> |
771 | + </main> |
772 | + |
773 | + <script> |
774 | + function getValue(id) { |
775 | + var el = document.getElementById(id); |
776 | + |
777 | + if (el.type === "checkbox") { |
778 | + return el.checked ? id : ""; |
779 | + } |
780 | + |
781 | + return el.value; |
782 | + } |
783 | + |
784 | + function updateChart() { |
785 | + var src = getValue("instance"); |
786 | + |
787 | + if (!/^[a-z]+\:\/{2}/.test(src)) { |
788 | + src = "http://" + src; |
789 | + } |
790 | + if (src[src.length - 1] !== "/") { src += "/"; } |
791 | + |
792 | + src += "chart." + getValue("format") + "?"; |
793 | + |
794 | + var params = ["query", "title", "stacked", "since", "until", "width", |
795 | + "height", "step", "min", "max", "label"]; |
796 | + var first = true; |
797 | + for (var i = 0; i < params.length; ++i) { |
798 | + var value = getValue(params[i]); |
799 | + if (value !== "") { |
800 | + if (!first) { src += "&"; } |
801 | + first = false; |
802 | + |
803 | + src += params[i] + "=" + encodeURIComponent(getValue(params[i])); |
804 | + } |
805 | + } |
806 | + |
807 | + document.getElementById("url").value = src; |
808 | + document.getElementById("preview").src = src; |
809 | + } |
810 | + |
811 | + function showAlert() { |
812 | + document.getElementById("alert").style.display = ""; |
813 | + } |
814 | + |
815 | + function hideAlert() { |
816 | + document.getElementById("alert").style.display = "none"; |
817 | + } |
818 | + |
819 | + var instInp = document.getElementById("instance"); |
820 | + if (instInp.value === "") { |
821 | + instInp.value = window.location.protocol + "//" + window.location.host; |
822 | + } |
823 | + |
824 | + var inputs = document.getElementsByTagName("input"); |
825 | + for (var i = 0; i < inputs.length; ++i) { |
826 | + inputs[i].onchange = updateChart; |
827 | + } |
828 | + document.getElementById("format").onchange = updateChart; |
829 | + |
830 | + document.getElementById("preview").onerror = showAlert; |
831 | + document.getElementById("preview").onload = hideAlert; |
832 | + |
833 | + updateChart(); |
834 | + </script> |