vigigraph / vigigraph / public / js / graph.js @ 74c804dc
History | View | Annotate | Download (15.6 KB)
1 | 8f6567c2 | Francois POIROTTE | var refresh_delay = 30; |
---|---|---|---|
2 | var graphs = [];
|
||
3 | |||
4 | var old_fragment = ''; |
||
5 | var skip_detection = 0; |
||
6 | |||
7 | |||
8 | 7c9baa43 | Francois POIROTTE | var Graph = new Class({ |
9 | Implements: [Events, Options],
|
||
10 | |||
11 | options: {
|
||
12 | // Les valeurs par défaut sont assignées dans reset().
|
||
13 | duration: 86400, |
||
14 | start: null, |
||
15 | autoRefresh: 0, |
||
16 | refreshDelay: null, |
||
17 | left: null, |
||
18 | top: null |
||
19 | }, |
||
20 | |||
21 | initialize: function (options, host, graph) { |
||
22 | this.setOptions(options);
|
||
23 | this.host = host;
|
||
24 | this.graph = graph;
|
||
25 | this.refreshTimer = null; |
||
26 | 8f6567c2 | Francois POIROTTE | this.destroyed = false; |
27 | 7c9baa43 | Francois POIROTTE | |
28 | new Request.JSON({
|
||
29 | c1b9f1da | Francois POIROTTE | url: app_path + 'rpc/startTime', |
30 | 7c9baa43 | Francois POIROTTE | onSuccess: function (data) { |
31 | this.startTime = data.starttime;
|
||
32 | }.bind(this)
|
||
33 | }).get({'host': this.host}); |
||
34 | |||
35 | var toolbar = new Jx.Toolbar({position:'top'}); |
||
36 | var periods = [
|
||
37 | [_('Last 12 hours'), 12], |
||
38 | [_('Last 24 hours'), 24], |
||
39 | [_('Last 48 hours'), 48], |
||
40 | [_('Last 7 days'), 7*24], |
||
41 | [_('Last 14 days'), 14*24], |
||
42 | [_('Last 3 months'), 3*30*24], |
||
43 | [_('Last 6 months'), 6*30*24], |
||
44 | [_('Last year'), 365*24] |
||
45 | ]; |
||
46 | |||
47 | var timeframe = new Jx.Menu({ |
||
48 | label: _("Timeframe"), |
||
49 | image: app_path + 'images/history.png', |
||
50 | tooltip: _("Timeframe menu") |
||
51 | }); |
||
52 | |||
53 | periods.each(function (period) {
|
||
54 | var menuItem = new Jx.Menu.Item({ |
||
55 | label: period[0] |
||
56 | }); |
||
57 | menuItem.options.period = period[1] * 60 * 60; |
||
58 | menuItem.addEvent('click', function () { |
||
59 | d84abf55 | Francois POIROTTE | this[0].options.start = null; |
60 | 7c9baa43 | Francois POIROTTE | this[0].options.duration = this[1].options.period; |
61 | this[0].updateGraph(); |
||
62 | }.bind([this, menuItem]));
|
||
63 | timeframe.add(menuItem); |
||
64 | }, this);
|
||
65 | |||
66 | ae613bf9 | Aurelien BOMPARD | // Indicateur d'alerte en cas d'erreur
|
67 | var alert_msg = _(
|
||
68 | 'Could not load the graph for "%(graph)s" on "%(host)s". ' +
|
||
69 | 'Make sure VigiRRD is running and receives performance data.'
|
||
70 | ); |
||
71 | // Le pattern donné à substitute permet de garder une syntaxe
|
||
72 | // cohérente avec Python (facilite le travail des traducteurs).
|
||
73 | alert_msg = alert_msg.substitute({ |
||
74 | 'graph': this.graph, |
||
75 | 'host': this.host |
||
76 | }, (/\\?%\(([^()]+)\)s/g));
|
||
77 | this.alert_indicator = new Element("img"); |
||
78 | this.alert_indicator.addClass("alert-indicator"); |
||
79 | this.alert_indicator.setProperty("src", app_path + 'images/messagebox_warning.png'); |
||
80 | this.alert_indicator.setProperty("title", alert_msg); |
||
81 | |||
82 | 7c9baa43 | Francois POIROTTE | this.indicators = new Jx.Menu({ |
83 | label: _("Export to CSV"), |
||
84 | image: app_path + 'images/document-export.png', |
||
85 | f4a2fb8f | Francois POIROTTE | tooltip: _("Export the content of this graph to CSV") |
86 | b02623ff | Francois POIROTTE | }); |
87 | 7c9baa43 | Francois POIROTTE | |
88 | new Request.JSON({
|
||
89 | url: app_path + 'rpc/getIndicators', |
||
90 | onSuccess: function (data) { |
||
91 | data.items.each(function (item) {
|
||
92 | this.indicators.add(new Jx.Menu.Item({ |
||
93 | 726122aa | Aurelien BOMPARD | name: item[0], |
94 | label: item[1], |
||
95 | 7c9baa43 | Francois POIROTTE | onClick: this.exportCSV.bind(this), |
96 | indicator: true |
||
97 | })); |
||
98 | }, this);
|
||
99 | |||
100 | this.indicators.add(new Jx.Menu.Item({ |
||
101 | label: _('All'), |
||
102 | onClick: this.exportCSV.bind(this), |
||
103 | indicator: false |
||
104 | })); |
||
105 | }.bind(this)
|
||
106 | }).get({ |
||
107 | 'host': this.host, |
||
108 | 'graph': this.graph |
||
109 | }); |
||
110 | |||
111 | this.refresh_button = new Jx.Button({ |
||
112 | image: app_path + 'images/refresh.png', |
||
113 | 89829224 | Francois POIROTTE | tooltip: _("Automatically refresh the graph"), |
114 | 7c9baa43 | Francois POIROTTE | toggle: true, |
115 | onDown: function() { |
||
116 | // On s'assure qu'il n'y a pas déjà un timer lancé.
|
||
117 | if ($chk(this.refreshTimer)) |
||
118 | return;
|
||
119 | var delay =
|
||
120 | this.options.refreshDelay ||
|
||
121 | window.refresh_delay; |
||
122 | this.refreshTimer =
|
||
123 | this.updateGraph.periodical(delay * 1000, this); |
||
124 | this.options.autoRefresh = 1; |
||
125 | 8f6567c2 | Francois POIROTTE | window.updateURI(); |
126 | 7c9baa43 | Francois POIROTTE | }.bind(this),
|
127 | onUp: function() { |
||
128 | clearInterval(this.refreshTimer);
|
||
129 | this.options.autoRefresh = 0; |
||
130 | 8f6567c2 | Francois POIROTTE | window.updateURI(); |
131 | 7c9baa43 | Francois POIROTTE | }.bind(this)
|
132 | }); |
||
133 | |||
134 | ce020707 | Francois POIROTTE | this.zoom_in = new Jx.Button({ |
135 | image: app_path + 'images/zoom-in.png', |
||
136 | tooltip: _("Zoom in"), |
||
137 | onClick: function() { |
||
138 | this.updateZoom(0.5); |
||
139 | }.bind(this)
|
||
140 | }); |
||
141 | |||
142 | this.zoom_out = new Jx.Button({ |
||
143 | image: app_path + 'images/zoom-out.png', |
||
144 | tooltip: _("Zoom out"), |
||
145 | onClick: function() { |
||
146 | this.updateZoom(2); |
||
147 | }.bind(this)
|
||
148 | }); |
||
149 | |||
150 | 7c9baa43 | Francois POIROTTE | toolbar.add( |
151 | this.refresh_button,
|
||
152 | timeframe, |
||
153 | new Jx.Button({
|
||
154 | image: app_path + 'images/start.png', |
||
155 | tooltip: _("Graph start"), |
||
156 | onClick: function() { |
||
157 | this.options.start = this.startTime; |
||
158 | this.updateGraph();
|
||
159 | }.bind(this)
|
||
160 | }), |
||
161 | new Jx.Button({
|
||
162 | image: app_path + 'images/previous.png', |
||
163 | tooltip: _("Previous section"), |
||
164 | onClick: function() { |
||
165 | 308d836a | Francois POIROTTE | this.options.start =
|
166 | this.getStartTime() -
|
||
167 | this.options.duration;
|
||
168 | 7c9baa43 | Francois POIROTTE | this.updateGraph();
|
169 | }.bind(this)
|
||
170 | }), |
||
171 | new Jx.Button({
|
||
172 | image: app_path + 'images/next.png', |
||
173 | tooltip: _("Next section"), |
||
174 | onClick: function() { |
||
175 | 308d836a | Francois POIROTTE | this.options.start =
|
176 | this.getStartTime() +
|
||
177 | this.options.duration;
|
||
178 | 7c9baa43 | Francois POIROTTE | this.updateGraph();
|
179 | }.bind(this)
|
||
180 | }), |
||
181 | new Jx.Button({
|
||
182 | image: app_path + 'images/end.png', |
||
183 | tooltip: _("Graph end"), |
||
184 | onClick: function() { |
||
185 | this.options.start = null; |
||
186 | this.updateGraph();
|
||
187 | }.bind(this)
|
||
188 | }), |
||
189 | ce020707 | Francois POIROTTE | this.zoom_in,
|
190 | this.zoom_out,
|
||
191 | 7c9baa43 | Francois POIROTTE | this.indicators,
|
192 | new Jx.Button({
|
||
193 | image: app_path + 'images/document-print-small.png', |
||
194 | tooltip: _("Print graph"), |
||
195 | onClick: this.print.bind(this) |
||
196 | }) |
||
197 | ); |
||
198 | |||
199 | var label = _("Graph for \"%(graph)s\" on \"%(host)s\""); |
||
200 | // Le pattern donné à substitute permet de garder une syntaxe
|
||
201 | // cohérente avec Python (facilite le travail des traducteurs).
|
||
202 | label = label.substitute({ |
||
203 | 'graph': this.graph, |
||
204 | 'host': this.host |
||
205 | }, (/\\?%\(([^()]+)\)s/g));
|
||
206 | |||
207 | this.graph_window = new Jx.Dialog({ |
||
208 | label: label,
|
||
209 | modal: false, |
||
210 | move: true, |
||
211 | close: true, |
||
212 | horizontal: this.options.left + ' left', |
||
213 | vertical: this.options.top + ' top', |
||
214 | width: 575, |
||
215 | height: 75, |
||
216 | toolbars: [toolbar]
|
||
217 | }); |
||
218 | |||
219 | ae613bf9 | Aurelien BOMPARD | this.alert_indicator.inject(this.graph_window.content.parentNode); |
220 | |||
221 | // mise à jour
|
||
222 | 7c9baa43 | Francois POIROTTE | this.updateGraph();
|
223 | this.graph_window.open();
|
||
224 | |||
225 | b02623ff | Francois POIROTTE | this.refresh_button.setActive(parseInt(this.options.autoRefresh, 10)); |
226 | 7c9baa43 | Francois POIROTTE | |
227 | 8f6567c2 | Francois POIROTTE | var onClose = function () { |
228 | if (this.destroyed) return; |
||
229 | this.destroyed = true; |
||
230 | this.graph_window.domObj.dispose();
|
||
231 | window.graphs.erase(this);
|
||
232 | window.updateURI(); |
||
233 | }; |
||
234 | |||
235 | this.graph_window.addEvent('close', onClose.bind(this)); |
||
236 | 7c9baa43 | Francois POIROTTE | // sizeChange est déclenché à la fois après un redimensionnement
|
237 | // et après un déplacement. Ce cas est mal documenté dans JxLib.
|
||
238 | this.graph_window.addEvent('sizeChange', this.dialogMoved.bind(this)); |
||
239 | |||
240 | // Simule un déplacement de la fenêtre,
|
||
241 | // pour mettre à jour les coordonnées.
|
||
242 | this.dialogMoved();
|
||
243 | 8f6567c2 | Francois POIROTTE | window.graphs.push(this);
|
244 | return this; |
||
245 | }, |
||
246 | |||
247 | destroy: function () { |
||
248 | this.graph_window.close();
|
||
249 | 7c9baa43 | Francois POIROTTE | }, |
250 | |||
251 | dialogMoved: function () { |
||
252 | // Repris de l'API interne de JxLib (création du Drag).
|
||
253 | this.options.left = parseInt(this.graph_window.domObj.style.left, 10); |
||
254 | this.options.top = parseInt(this.graph_window.domObj.style.top, 10); |
||
255 | 8f6567c2 | Francois POIROTTE | window.updateURI(); |
256 | 7c9baa43 | Francois POIROTTE | }, |
257 | |||
258 | ce020707 | Francois POIROTTE | updateZoom: function (factor) { |
259 | b02623ff | Francois POIROTTE | this.options.duration = parseInt(this.options.duration, 10) * factor; |
260 | ce020707 | Francois POIROTTE | // Période minimale d'affichage : 1 minute.
|
261 | if (this.options.duration < 60) |
||
262 | this.options.duration = 60; |
||
263 | // On (dés)active le bouton de zoom en avant au besoin.
|
||
264 | this.zoom_in.setEnabled(this.options.duration != 60); |
||
265 | this.updateGraph();
|
||
266 | }, |
||
267 | |||
268 | 89829224 | Francois POIROTTE | getStartTime: function () { |
269 | ce020707 | Francois POIROTTE | var start = this.options.start; |
270 | 74c804dc | Aurelien BOMPARD | if (start === null) |
271 | 89829224 | Francois POIROTTE | // @TODO: cette heure est en localtime a priori.
|
272 | ce020707 | Francois POIROTTE | start = (new Date() / 1000).toInt() - this.options.duration; |
273 | if (start < 0) |
||
274 | return 0; |
||
275 | return start;
|
||
276 | 89829224 | Francois POIROTTE | }, |
277 | |||
278 | 7c9baa43 | Francois POIROTTE | exportCSV: function (menuItem) { |
279 | var uri = new URI(app_path + 'vigirrd/' + |
||
280 | encodeURIComponent(this.host) + '/export'); |
||
281 | |||
282 | 89829224 | Francois POIROTTE | var start = this.getStartTime(); |
283 | 7c9baa43 | Francois POIROTTE | |
284 | uri.setData({ |
||
285 | host: this.host, |
||
286 | graphtemplate: this.graph, |
||
287 | start: start,
|
||
288 | end: start + this.options.duration, |
||
289 | nocache: (new Date() / 1) |
||
290 | b02623ff | Francois POIROTTE | }); |
291 | 7c9baa43 | Francois POIROTTE | |
292 | if (menuItem.options.indicator)
|
||
293 | 726122aa | Aurelien BOMPARD | uri.setData({ds: menuItem.options.name}, true); |
294 | 7c9baa43 | Francois POIROTTE | |
295 | window.open(uri.toString()); |
||
296 | }, |
||
297 | |||
298 | 89829224 | Francois POIROTTE | // Cette fonction est aussi utilisée dans print.js
|
299 | // pour gérer l'impression globale.
|
||
300 | getPrintParams: function () { |
||
301 | var img = this.graph_window.content.getElement('img'); |
||
302 | var img_uri = new URI(img.src); |
||
303 | var params = img_uri.getData();
|
||
304 | return {
|
||
305 | host: params.host,
|
||
306 | start: params.start,
|
||
307 | duration: params.duration,
|
||
308 | graph: params.graphtemplate,
|
||
309 | nocache: params.nocache
|
||
310 | b02623ff | Francois POIROTTE | }; |
311 | 89829224 | Francois POIROTTE | }, |
312 | |||
313 | 7c9baa43 | Francois POIROTTE | print: function () { |
314 | var uri = new URI(app_path + 'rpc/graphsList'); |
||
315 | 89829224 | Francois POIROTTE | uri.setData({graphs: [this.getPrintParams()]}); |
316 | 7c9baa43 | Francois POIROTTE | var print_window = window.open(uri.toString());
|
317 | 627cd13b | Francois POIROTTE | print_window.onload = function () { |
318 | this.print();
|
||
319 | }.bind(print_window); |
||
320 | 7c9baa43 | Francois POIROTTE | }, |
321 | |||
322 | updateGraph: function () { |
||
323 | var uri = new URI(app_path + 'vigirrd/' + |
||
324 | encodeURIComponent(this.host) + '/graph.png'); |
||
325 | |||
326 | 89829224 | Francois POIROTTE | var start = this.getStartTime(); |
327 | 7c9baa43 | Francois POIROTTE | |
328 | uri.setData({ |
||
329 | host: this.host, |
||
330 | start: start,
|
||
331 | duration: this.options.duration, |
||
332 | graphtemplate: this.graph, |
||
333 | // Permet d'empêcher la mise en cache du graphe.
|
||
334 | // Nécessaire car le graphe évolue dynamiquement au fil de l'eau.
|
||
335 | nocache: (new Date() / 1) |
||
336 | }); |
||
337 | // On génère dynamiquement une balise "img" pour charger le graphe.
|
||
338 | this.graph_window.setContent(
|
||
339 | '<img src="' + uri.toString() + '"/' + '>'); |
||
340 | var img = this.graph_window.content.getElement('img'); |
||
341 | img.addEvent('load', function () { |
||
342 | this[0].graph_window.resize( |
||
343 | this[1].width + 25, |
||
344 | this[1].height + 88 |
||
345 | ); |
||
346 | ae613bf9 | Aurelien BOMPARD | this[0].hideAlert(); |
347 | 7c9baa43 | Francois POIROTTE | }.bind([this, img]));
|
348 | img.addEvent('error', function () { |
||
349 | ae613bf9 | Aurelien BOMPARD | // if (this.refreshTimer) clearInterval(this.refreshTimer);
|
350 | this.showAlert();
|
||
351 | //this.graph_window.close();
|
||
352 | 7c9baa43 | Francois POIROTTE | }.bind(this));
|
353 | ae613bf9 | Aurelien BOMPARD | }, |
354 | |||
355 | showAlert: function() { |
||
356 | this.alert_indicator.setStyle("display", "block"); |
||
357 | b02623ff | Francois POIROTTE | var zindex = parseInt(this.graph_window.domObj.getStyle("z-index"), 10) + 1; |
358 | ae613bf9 | Aurelien BOMPARD | this.alert_indicator.setStyle("z-index", zindex); |
359 | return;
|
||
360 | }, |
||
361 | |||
362 | hideAlert: function() { |
||
363 | this.alert_indicator.setStyle("display", "none"); |
||
364 | 7c9baa43 | Francois POIROTTE | } |
365 | }); |
||
366 | |||
367 | 8f6567c2 | Francois POIROTTE | var updateURI = function () { |
368 | var graphs_uri = [];
|
||
369 | var uri = new URI(); |
||
370 | 7c9baa43 | Francois POIROTTE | |
371 | 8f6567c2 | Francois POIROTTE | // Section critique.
|
372 | window.skip_detection++; |
||
373 | uri.set('fragment', ''); |
||
374 | |||
375 | window.graphs.each(function (graph) {
|
||
376 | var props = new Hash(graph.options); |
||
377 | props.extend({host: graph.host, graph: graph.graph}); |
||
378 | this.push(props.toQueryString());
|
||
379 | }, graphs_uri); |
||
380 | |||
381 | uri.setData({'graphs': graphs_uri, safety: 1}, false, 'fragment'); |
||
382 | uri.go(); |
||
383 | window.old_fragment = uri.toString(); |
||
384 | |||
385 | // Fin de section critique.
|
||
386 | window.skip_detection--; |
||
387 | }; |
||
388 | |||
389 | var update_visible_graphs = function (new_fragment) { |
||
390 | 7c9baa43 | Francois POIROTTE | // On réouvre les graphes précédemment chargés.
|
391 | 8f6567c2 | Francois POIROTTE | var new_graphs = [];
|
392 | var qs = new Hash(new_fragment.get('fragment').parseQueryString()); |
||
393 | 7c9baa43 | Francois POIROTTE | if (qs.has('graphs')) { |
394 | 8f6567c2 | Francois POIROTTE | new_graphs = (new Hash(qs.get('graphs'))).getValues(); |
395 | 7c9baa43 | Francois POIROTTE | } |
396 | |||
397 | 8f6567c2 | Francois POIROTTE | // Section critique.
|
398 | window.skip_detection++; |
||
399 | |||
400 | var prev_graphs = window.graphs;
|
||
401 | window.graphs = []; |
||
402 | prev_graphs.each(function (graph) { graph.destroy(); });
|
||
403 | |||
404 | new_graphs.each(function (graph) {
|
||
405 | 7c9baa43 | Francois POIROTTE | var uri = new URI('?' + graph); |
406 | var qs = new Hash(uri.getData()); |
||
407 | if (qs.has('host') && qs.has('graph')) { |
||
408 | var options = new Hash(); |
||
409 | var params = [
|
||
410 | 'start',
|
||
411 | 'duration',
|
||
412 | 'left',
|
||
413 | 'top',
|
||
414 | 'autoRefresh',
|
||
415 | 'refreshDelay'
|
||
416 | ]; |
||
417 | |||
418 | params.each(function (param) {
|
||
419 | if (this[0].has(param)) |
||
420 | this[1].set(param, this[0].get(param)); |
||
421 | }, [qs, options]); |
||
422 | |||
423 | new Graph(
|
||
424 | options.getClean(), |
||
425 | qs.get('host'),
|
||
426 | qs.get('graph')
|
||
427 | ); |
||
428 | } |
||
429 | }); |
||
430 | |||
431 | 8f6567c2 | Francois POIROTTE | window.updateURI(); |
432 | |||
433 | // Fin de section critique.
|
||
434 | window.skip_detection--; |
||
435 | |||
436 | if (window.graphs.length == 1) { |
||
437 | new Request.JSON({
|
||
438 | url: app_path + 'rpc/selectHostAndGraph', |
||
439 | onSuccess: function (results) { |
||
440 | window.toolbar.host_picker.setItem(results.idhost, this[0]); |
||
441 | window.toolbar.graph_picker.idselection = results.idgraph; |
||
442 | window.toolbar.graph_picker.setLabel(this[1]); |
||
443 | }.bind([ |
||
444 | window.graphs[0].host,
|
||
445 | window.graphs[0].graph
|
||
446 | ]) |
||
447 | }).get({ |
||
448 | host: window.graphs[0].host, |
||
449 | graph: window.graphs[0].graph |
||
450 | }); |
||
451 | } |
||
452 | b02623ff | Francois POIROTTE | }; |
453 | 8f6567c2 | Francois POIROTTE | |
454 | var hash_change_detector = function() { |
||
455 | var new_fragment;
|
||
456 | |||
457 | // Pour les moments où on a besoin de mettre à jour
|
||
458 | // volontairement l'URI (à l'ouverture d'un graphe).
|
||
459 | if (window.skip_detection) return; |
||
460 | |||
461 | // Force mootools à analyser l'URL courante de nouveau,
|
||
462 | // ce qui mettra à jour la partie "fragment" de l'URI.
|
||
463 | URI.base = new URI(
|
||
464 | document.getElements('base[href]', true).getLast(), |
||
465 | {base: document.location}
|
||
466 | ); |
||
467 | |||
468 | new_fragment = new URI();
|
||
469 | if (old_fragment.toString() != new_fragment.toString()) {
|
||
470 | update_visible_graphs(new_fragment, old_fragment); |
||
471 | } |
||
472 | }; |
||
473 | |||
474 | if ('onhashchange' in window) { |
||
475 | window.onhashchange = hash_change_detector; |
||
476 | } else {
|
||
477 | hash_change_detector.periodical(100);
|
||
478 | } |
||
479 | |||
480 | window.addEvent('load', function () { |
||
481 | new Request.JSON({
|
||
482 | url: app_path + 'rpc/tempoDelayRefresh', |
||
483 | onSuccess: function (data) { |
||
484 | window.refresh_delay = data.delay; |
||
485 | } |
||
486 | }).get(); |
||
487 | |||
488 | hash_change_detector(); |
||
489 | 7c9baa43 | Francois POIROTTE | }); |