]> git.proxmox.com Git - proxmox-widget-toolkit.git/blob - panel/RRDChart.js
rrd charts: add legend to header for better space usage
[proxmox-widget-toolkit.git] / panel / RRDChart.js
1 Ext.define('Proxmox.widget.RRDChart', {
2 extend: 'Ext.chart.CartesianChart',
3 alias: 'widget.proxmoxRRDChart',
4
5 unit: undefined, // bytes, bytespersecond, percent
6
7 controller: {
8 xclass: 'Ext.app.ViewController',
9
10 convertToUnits: function(value) {
11 var units = ['', 'k','M','G','T', 'P'];
12 var si = 0;
13 let format = '0.##';
14 if (value < 0.1) format += '#';
15 while(value >= 1000 && si < (units.length -1)){
16 value = value / 1000;
17 si++;
18 }
19
20 // javascript floating point weirdness
21 value = Ext.Number.correctFloat(value);
22
23 // limit decimal points
24 value = Ext.util.Format.number(value, format);
25
26 return value.toString() + " " + units[si];
27 },
28
29 leftAxisRenderer: function(axis, label, layoutContext) {
30 var me = this;
31 return me.convertToUnits(label);
32 },
33
34 onSeriesTooltipRender: function(tooltip, record, item) {
35 var me = this.getView();
36
37 var suffix = '';
38
39 if (me.unit === 'percent') {
40 suffix = '%';
41 } else if (me.unit === 'bytes') {
42 suffix = 'B';
43 } else if (me.unit === 'bytespersecond') {
44 suffix = 'B/s';
45 }
46
47 var prefix = item.field;
48 if (me.fieldTitles && me.fieldTitles[me.fields.indexOf(item.field)]) {
49 prefix = me.fieldTitles[me.fields.indexOf(item.field)];
50 }
51 let v = this.convertToUnits(record.get(item.field));
52 let t = new Date(record.get('time'));
53 tooltip.setHtml(`${prefix}: ${v}${suffix}<br>${t}`);
54 },
55
56 onAfterAnimation: function(chart, eopts) {
57 // if the undo button is disabled, disable our tool
58 var ourUndoZoomButton = chart.header.tools[0];
59 var undoButton = chart.interactions[0].getUndoButton();
60 ourUndoZoomButton.setDisabled(undoButton.isDisabled());
61 }
62 },
63
64 width: 770,
65 height: 300,
66 animation: false,
67 interactions: [
68 {
69 type: 'crosszoom'
70 },
71 ],
72 legend: {
73 padding: 0,
74 },
75 axes: [
76 {
77 type: 'numeric',
78 position: 'left',
79 grid: true,
80 renderer: 'leftAxisRenderer',
81 minimum: 0
82 },
83 {
84 type: 'time',
85 position: 'bottom',
86 grid: true,
87 fields: ['time']
88 },
89 ],
90 listeners: {
91 animationend: 'onAfterAnimation'
92 },
93
94 initComponent: function() {
95 var me = this;
96 var series = {};
97
98 if (!me.store) {
99 throw "cannot work without store";
100 }
101
102 if (!me.fields) {
103 throw "cannot work without fields";
104 }
105
106 me.callParent();
107
108 // add correct label for left axis
109 var axisTitle = "";
110 if (me.unit === 'percent') {
111 axisTitle = "%";
112 } else if (me.unit === 'bytes') {
113 axisTitle = "Bytes";
114 } else if (me.unit === 'bytespersecond') {
115 axisTitle = "Bytes/s";
116 } else if (me.fieldTitles && me.fieldTitles.length === 1) {
117 axisTitle = me.fieldTitles[0];
118 } else if (me.fields.length === 1) {
119 axisTitle = me.fields[0];
120 }
121
122 me.axes[0].setTitle(axisTitle);
123
124 me.updateHeader();
125 me.header.padding = '4 9 4';
126 me.header.add(me.legend);
127
128 if (!me.noTool) {
129 me.addTool({
130 type: 'minus',
131 disabled: true,
132 tooltip: gettext('Undo Zoom'),
133 handler: function(){
134 var undoButton = me.interactions[0].getUndoButton();
135 if (undoButton.handler) {
136 undoButton.handler();
137 }
138 }
139 });
140 }
141
142 // add a series for each field we get
143 me.fields.forEach(function(item, index){
144 var title = item;
145 if (me.fieldTitles && me.fieldTitles[index]) {
146 title = me.fieldTitles[index];
147 }
148 me.addSeries(Ext.apply(
149 {
150 type: 'line',
151 xField: 'time',
152 yField: item,
153 title: title,
154 fill: true,
155 style: {
156 lineWidth: 1.5,
157 opacity: 0.60
158 },
159 marker: {
160 opacity: 0,
161 scaling: 0.01,
162 fx: {
163 duration: 200,
164 easing: 'easeOut'
165 }
166 },
167 highlightCfg: {
168 opacity: 1,
169 scaling: 1.5
170 },
171 tooltip: {
172 trackMouse: true,
173 renderer: 'onSeriesTooltipRender'
174 }
175 },
176 me.seriesConfig
177 ));
178 });
179
180 // enable animation after the store is loaded
181 me.store.onAfter('load', function() {
182 me.setAnimation(true);
183 }, this, {single: true});
184 }
185 });