]>
git.proxmox.com Git - proxmox-widget-toolkit.git/blob - src/panel/RRDChart.js
1 // override the download server url globally, for privacy reasons
2 Ext
.draw
.Container
.prototype.defaultDownloadServerUrl
= "-";
4 Ext
.define('Proxmox.chart.axis.segmenter.NumericBase2', {
5 extend
: 'Ext.chart.axis.segmenter.Numeric',
6 alias
: 'segmenter.numericBase2',
8 // derived from the original numeric segmenter but using 2 instead of 10 as base
9 preferredStep: function(min
, estStepSize
) {
10 // Getting an order of magnitude of the estStepSize with a common logarithm.
11 let order
= Math
.floor(Math
.log2(estStepSize
));
12 let scale
= Math
.pow(2, order
);
16 // FIXME: below is not useful when using base 2 instead of base 10, we could
17 // just directly set estStepSize to 2
18 if (estStepSize
<= 1) {
20 } else if (estStepSize
< 2) {
25 // When passed estStepSize is less than 1, its order of magnitude
26 // is equal to -number_of_leading_zeros in the estStepSize.
27 fixes
: -order
, // Number of fractional digits.
35 * Wraps the provided estimated step size of a range without altering it into a step size object.
37 * @param {*} min The start point of range.
38 * @param {*} estStepSize The estimated step size.
39 * @return {Object} Return the step size by an object of step x unit.
40 * @return {Number} return.step The step count of units.
41 * @return {Object} return.unit The unit.
43 // derived from the original numeric segmenter but using 2 instead of 10 as base
44 exactStep: function(min
, estStepSize
) {
45 let order
= Math
.floor(Math
.log2(estStepSize
));
46 let scale
= Math
.pow(2, order
);
50 // add one decimal point if estStepSize is not a multiple of scale
51 fixes
: -order
+ (estStepSize
% scale
=== 0 ? 0 : 1),
59 Ext
.define('Proxmox.widget.RRDChart', {
60 extend
: 'Ext.chart.CartesianChart',
61 alias
: 'widget.proxmoxRRDChart',
63 unit
: undefined, // bytes, bytespersecond, percent
67 // set to empty string to suppress warning in debug mode
68 downloadServerUrl
: '-',
71 xclass
: 'Ext.app.ViewController',
73 init: function(view
) {
74 this.powerOfTwo
= view
.powerOfTwo
;
77 convertToUnits: function(value
) {
78 let units
= ['', 'k', 'M', 'G', 'T', 'P'];
81 if (value
< 0.1) format
+= '#';
82 const baseValue
= this.powerOfTwo
? 1024 : 1000;
83 while (value
>= baseValue
&& si
< units
.length
-1) {
84 value
= value
/ baseValue
;
88 // javascript floating point weirdness
89 value
= Ext
.Number
.correctFloat(value
);
91 // limit decimal points
92 value
= Ext
.util
.Format
.number(value
, format
);
95 if (this.powerOfTwo
) unit
+= 'i';
97 return `${value.toString()} ${unit}`;
100 leftAxisRenderer: function(axis
, label
, layoutContext
) {
102 return me
.convertToUnits(label
);
105 onSeriesTooltipRender: function(tooltip
, record
, item
) {
106 let view
= this.getView();
109 if (view
.unit
=== 'percent') {
111 } else if (view
.unit
=== 'bytes') {
113 } else if (view
.unit
=== 'bytespersecond') {
117 let prefix
= item
.field
;
118 if (view
.fieldTitles
&& view
.fieldTitles
[view
.fields
.indexOf(item
.field
)]) {
119 prefix
= view
.fieldTitles
[view
.fields
.indexOf(item
.field
)];
121 let v
= this.convertToUnits(record
.get(item
.field
));
122 let t
= new Date(record
.get('time'));
123 tooltip
.setHtml(`${prefix}: ${v}${suffix}<br>${t}`);
126 onAfterAnimation: function(chart
, eopts
) {
127 if (!chart
.header
|| !chart
.header
.tools
) {
130 // if the undo button is disabled, disable our tool
131 let ourUndoZoomButton
= chart
.header
.tools
[0];
132 let undoButton
= chart
.interactions
[0].getUndoButton();
133 ourUndoZoomButton
.setDisabled(undoButton
.isDisabled());
151 fn
: 'onAfterAnimation',
158 constructor: function(config
) {
161 let segmenter
= config
.powerOfTwo
? 'numericBase2' : 'numeric';
167 renderer
: 'leftAxisRenderer',
178 me
.callParent([config
]);
181 initComponent: function() {
185 throw "cannot work without store";
189 throw "cannot work without fields";
194 // add correct label for left axis
196 if (me
.unit
=== 'percent') {
198 } else if (me
.unit
=== 'bytes') {
200 } else if (me
.unit
=== 'bytespersecond') {
201 axisTitle
= "Bytes/s";
202 } else if (me
.fieldTitles
&& me
.fieldTitles
.length
=== 1) {
203 axisTitle
= me
.fieldTitles
[0];
204 } else if (me
.fields
.length
=== 1) {
205 axisTitle
= me
.fields
[0];
208 me
.axes
[0].setTitle(axisTitle
);
212 if (me
.header
&& me
.legend
) {
213 me
.header
.padding
= '4 9 4';
214 me
.header
.add(me
.legend
);
215 me
.legend
= undefined;
222 tooltip
: gettext('Undo Zoom'),
223 handler: function() {
224 let undoButton
= me
.interactions
[0].getUndoButton();
225 if (undoButton
.handler
) {
226 undoButton
.handler();
232 // add a series for each field we get
233 me
.fields
.forEach(function(item
, index
) {
235 if (me
.fieldTitles
&& me
.fieldTitles
[index
]) {
236 title
= me
.fieldTitles
[index
];
238 me
.addSeries(Ext
.apply(
259 renderer
: 'onSeriesTooltipRender',
266 // enable animation after the store is loaded
267 me
.store
.onAfter('load', function() {
272 }, this, { single
: true });