]>
git.proxmox.com Git - proxmox-widget-toolkit.git/blob - src/panel/RRDChart.js
49b3ad236871ee65f5cbf4f780219df4208508cf
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
64 // set to empty string to suppress warning in debug mode
65 downloadServerUrl
: '-',
68 xclass
: 'Ext.app.ViewController',
70 init: function(view
) {
71 this.powerOfTwo
= view
.powerOfTwo
;
74 convertToUnits: function(value
) {
75 let units
= ['', 'k', 'M', 'G', 'T', 'P'];
78 if (value
< 0.1) format
+= '#';
79 const baseValue
= this.powerOfTwo
? 1024 : 1000;
80 while (value
>= baseValue
&& si
< units
.length
-1) {
81 value
= value
/ baseValue
;
85 // javascript floating point weirdness
86 value
= Ext
.Number
.correctFloat(value
);
88 // limit decimal points
89 value
= Ext
.util
.Format
.number(value
, format
);
92 if (this.powerOfTwo
) unit
+= 'i';
94 return `${value.toString()} ${unit}`;
97 leftAxisRenderer: function(axis
, label
, layoutContext
) {
99 return me
.convertToUnits(label
);
102 onSeriesTooltipRender: function(tooltip
, record
, item
) {
103 let view
= this.getView();
106 if (view
.unit
=== 'percent') {
108 } else if (view
.unit
=== 'bytes') {
110 } else if (view
.unit
=== 'bytespersecond') {
114 let prefix
= item
.field
;
115 if (view
.fieldTitles
&& view
.fieldTitles
[view
.fields
.indexOf(item
.field
)]) {
116 prefix
= view
.fieldTitles
[view
.fields
.indexOf(item
.field
)];
118 let v
= this.convertToUnits(record
.get(item
.field
));
119 let t
= new Date(record
.get('time'));
120 tooltip
.setHtml(`${prefix}: ${v}${suffix}<br>${t}`);
123 onAfterAnimation: function(chart
, eopts
) {
124 // if the undo button is disabled, disable our tool
125 let ourUndoZoomButton
= chart
.header
.tools
[0];
126 let undoButton
= chart
.interactions
[0].getUndoButton();
127 ourUndoZoomButton
.setDisabled(undoButton
.isDisabled());
143 animationend
: 'onAfterAnimation',
146 constructor: function(config
) {
149 let segmenter
= config
.powerOfTwo
? 'numericBase2' : 'numeric';
155 renderer
: 'leftAxisRenderer',
166 me
.callParent([config
]);
169 initComponent: function() {
173 throw "cannot work without store";
177 throw "cannot work without fields";
182 // add correct label for left axis
184 if (me
.unit
=== 'percent') {
186 } else if (me
.unit
=== 'bytes') {
188 } else if (me
.unit
=== 'bytespersecond') {
189 axisTitle
= "Bytes/s";
190 } else if (me
.fieldTitles
&& me
.fieldTitles
.length
=== 1) {
191 axisTitle
= me
.fieldTitles
[0];
192 } else if (me
.fields
.length
=== 1) {
193 axisTitle
= me
.fields
[0];
196 me
.axes
[0].setTitle(axisTitle
);
200 if (me
.header
&& me
.legend
) {
201 me
.header
.padding
= '4 9 4';
202 me
.header
.add(me
.legend
);
209 tooltip
: gettext('Undo Zoom'),
210 handler: function() {
211 let undoButton
= me
.interactions
[0].getUndoButton();
212 if (undoButton
.handler
) {
213 undoButton
.handler();
219 // add a series for each field we get
220 me
.fields
.forEach(function(item
, index
) {
222 if (me
.fieldTitles
&& me
.fieldTitles
[index
]) {
223 title
= me
.fieldTitles
[index
];
225 me
.addSeries(Ext
.apply(
250 renderer
: 'onSeriesTooltipRender',
257 // enable animation after the store is loaded
258 me
.store
.onAfter('load', function() {
259 me
.setAnimation(true);
260 }, this, { single
: true });