]>
git.proxmox.com Git - proxmox-widget-toolkit.git/blob - src/panel/RRDChart.js
1 Ext
.define('Proxmox.chart.axis.segmenter.NumericBase2', {
2 extend
: 'Ext.chart.axis.segmenter.Numeric',
3 alias
: 'segmenter.numericBase2',
5 // derived from the original numeric segmenter but using 2 instead of 10 as base
6 preferredStep: function(min
, estStepSize
) {
7 // Getting an order of magnitude of the estStepSize with a common logarithm.
8 let order
= Math
.floor(Math
.log2(estStepSize
));
9 let scale
= Math
.pow(2, order
);
13 // FIXME: below is not useful when using base 2 instead of base 10, we could
14 // just directly set estStepSize to 2
15 if (estStepSize
<= 1) {
17 } else if (estStepSize
< 2) {
22 // When passed estStepSize is less than 1, its order of magnitude
23 // is equal to -number_of_leading_zeros in the estStepSize.
24 fixes
: -order
, // Number of fractional digits.
32 * Wraps the provided estimated step size of a range without altering it into a step size object.
34 * @param {*} min The start point of range.
35 * @param {*} estStepSize The estimated step size.
36 * @return {Object} Return the step size by an object of step x unit.
37 * @return {Number} return.step The step count of units.
38 * @return {Object} return.unit The unit.
40 // derived from the original numeric segmenter but using 2 instead of 10 as base
41 exactStep: function(min
, estStepSize
) {
42 let order
= Math
.floor(Math
.log2(estStepSize
));
43 let scale
= Math
.pow(2, order
);
47 // add one decimal point if estStepSize is not a multiple of scale
48 fixes
: -order
+ (estStepSize
% scale
=== 0 ? 0 : 1),
56 Ext
.define('Proxmox.widget.RRDChart', {
57 extend
: 'Ext.chart.CartesianChart',
58 alias
: 'widget.proxmoxRRDChart',
60 unit
: undefined, // bytes, bytespersecond, percent
65 xclass
: 'Ext.app.ViewController',
67 init: function(view
) {
68 this.powerOfTwo
= view
.powerOfTwo
;
71 convertToUnits: function(value
) {
72 let units
= ['', 'k', 'M', 'G', 'T', 'P'];
75 if (value
< 0.1) format
+= '#';
76 const baseValue
= this.powerOfTwo
? 1024 : 1000;
77 while (value
>= baseValue
&& si
< units
.length
-1) {
78 value
= value
/ baseValue
;
82 // javascript floating point weirdness
83 value
= Ext
.Number
.correctFloat(value
);
85 // limit decimal points
86 value
= Ext
.util
.Format
.number(value
, format
);
89 if (this.powerOfTwo
) unit
+= 'i';
91 return `${value.toString()} ${unit}`;
94 leftAxisRenderer: function(axis
, label
, layoutContext
) {
96 return me
.convertToUnits(label
);
99 onSeriesTooltipRender: function(tooltip
, record
, item
) {
100 let view
= this.getView();
103 if (view
.unit
=== 'percent') {
105 } else if (view
.unit
=== 'bytes') {
107 } else if (view
.unit
=== 'bytespersecond') {
111 let prefix
= item
.field
;
112 if (view
.fieldTitles
&& view
.fieldTitles
[view
.fields
.indexOf(item
.field
)]) {
113 prefix
= view
.fieldTitles
[view
.fields
.indexOf(item
.field
)];
115 let v
= this.convertToUnits(record
.get(item
.field
));
116 let t
= new Date(record
.get('time'));
117 tooltip
.setHtml(`${prefix}: ${v}${suffix}<br>${t}`);
120 onAfterAnimation: function(chart
, eopts
) {
121 // if the undo button is disabled, disable our tool
122 let ourUndoZoomButton
= chart
.header
.tools
[0];
123 let undoButton
= chart
.interactions
[0].getUndoButton();
124 ourUndoZoomButton
.setDisabled(undoButton
.isDisabled());
140 animationend
: 'onAfterAnimation',
143 constructor: function(config
) {
146 let segmenter
= config
.powerOfTwo
? 'numericBase2' : 'numeric';
152 renderer
: 'leftAxisRenderer',
163 me
.callParent([config
]);
166 initComponent: function() {
170 throw "cannot work without store";
174 throw "cannot work without fields";
179 // add correct label for left axis
181 if (me
.unit
=== 'percent') {
183 } else if (me
.unit
=== 'bytes') {
185 } else if (me
.unit
=== 'bytespersecond') {
186 axisTitle
= "Bytes/s";
187 } else if (me
.fieldTitles
&& me
.fieldTitles
.length
=== 1) {
188 axisTitle
= me
.fieldTitles
[0];
189 } else if (me
.fields
.length
=== 1) {
190 axisTitle
= me
.fields
[0];
193 me
.axes
[0].setTitle(axisTitle
);
197 if (me
.header
&& me
.legend
) {
198 me
.header
.padding
= '4 9 4';
199 me
.header
.add(me
.legend
);
206 tooltip
: gettext('Undo Zoom'),
207 handler: function() {
208 let undoButton
= me
.interactions
[0].getUndoButton();
209 if (undoButton
.handler
) {
210 undoButton
.handler();
216 // add a series for each field we get
217 me
.fields
.forEach(function(item
, index
) {
219 if (me
.fieldTitles
&& me
.fieldTitles
[index
]) {
220 title
= me
.fieldTitles
[index
];
222 me
.addSeries(Ext
.apply(
247 renderer
: 'onSeriesTooltipRender',
254 // enable animation after the store is loaded
255 me
.store
.onAfter('load', function() {
256 me
.setAnimation(true);
257 }, this, { single
: true });