]> git.proxmox.com Git - proxmox-widget-toolkit.git/blob - panel/RRDChart.js
rrd charts: render 3 decimal points for small values
[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 tooltip.setHtml(prefix + ': ' + this.convertToUnits(record.get(item.field)) + suffix +
52 '<br>' + new Date(record.get('time')));
53 },
54
55 onAfterAnimation: function(chart, eopts) {
56 // if the undobuton is disabled,
57 // disable our tool
58
59 var ourUndoZoomButton = chart.tools[0];
60 var undoButton = chart.interactions[0].getUndoButton();
61 ourUndoZoomButton.setDisabled(undoButton.isDisabled());
62 }
63 },
64
65 width: 770,
66 height: 300,
67 animation: false,
68 interactions: [{
69 type: 'crosszoom'
70 }],
71 axes: [{
72 type: 'numeric',
73 position: 'left',
74 grid: true,
75 renderer: 'leftAxisRenderer',
76 //renderer: function(axis, label) { return label; },
77 minimum: 0
78 }, {
79 type: 'time',
80 position: 'bottom',
81 grid: true,
82 fields: ['time']
83 }],
84 legend: {
85 docked: 'bottom'
86 },
87 listeners: {
88 animationend: 'onAfterAnimation'
89 },
90
91
92 initComponent: function() {
93 var me = this;
94 var series = {};
95
96 if (!me.store) {
97 throw "cannot work without store";
98 }
99
100 if (!me.fields) {
101 throw "cannot work without fields";
102 }
103
104 me.callParent();
105
106 // add correct label for left axis
107 var axisTitle = "";
108 if (me.unit === 'percent') {
109 axisTitle = "%";
110 } else if (me.unit === 'bytes') {
111 axisTitle = "Bytes";
112 } else if (me.unit === 'bytespersecond') {
113 axisTitle = "Bytes/s";
114 } else if (me.fieldTitles && me.fieldTitles.length === 1) {
115 axisTitle = me.fieldTitles[0];
116 } else if (me.fields.length === 1) {
117 axisTitle = me.fields[0];
118 }
119
120 me.axes[0].setTitle(axisTitle);
121
122 if (!me.noTool) {
123 me.addTool([{
124 type: 'minus',
125 disabled: true,
126 tooltip: gettext('Undo Zoom'),
127 handler: function(){
128 var undoButton = me.interactions[0].getUndoButton();
129 if (undoButton.handler) {
130 undoButton.handler();
131 }
132 }
133 },{
134 type: 'restore',
135 tooltip: gettext('Toggle Legend'),
136 handler: function(){
137 if (me.legend) {
138 me.legend.setVisible(!me.legend.isVisible());
139 }
140 }
141 }]);
142 }
143
144 // add a series for each field we get
145 me.fields.forEach(function(item, index){
146 var title = item;
147 if (me.fieldTitles && me.fieldTitles[index]) {
148 title = me.fieldTitles[index];
149 }
150 me.addSeries(Ext.apply(
151 {
152 type: 'line',
153 xField: 'time',
154 yField: item,
155 title: title,
156 fill: true,
157 style: {
158 lineWidth: 1.5,
159 opacity: 0.60
160 },
161 marker: {
162 opacity: 0,
163 scaling: 0.01,
164 fx: {
165 duration: 200,
166 easing: 'easeOut'
167 }
168 },
169 highlightCfg: {
170 opacity: 1,
171 scaling: 1.5
172 },
173 tooltip: {
174 trackMouse: true,
175 renderer: 'onSeriesTooltipRender'
176 }
177 },
178 me.seriesConfig
179 ));
180 });
181
182 // enable animation after the store is loaded
183 me.store.onAfter('load', function() {
184 me.setAnimation(true);
185 }, this, {single: true});
186 }
187 });