]> git.proxmox.com Git - proxmox-backup.git/blob - www/datastore/DataStoreListSummary.js
ui: datastore summary handle non-existent values
[proxmox-backup.git] / www / datastore / DataStoreListSummary.js
1 // Summary Panel for a single datastore in overview
2 Ext.define('PBS.datastore.DataStoreListSummary', {
3 extend: 'Ext.panel.Panel',
4 alias: 'widget.pbsDataStoreListSummary',
5 mixins: ['Proxmox.Mixin.CBind'],
6
7 cbind: {
8 title: '{datastore}',
9 },
10
11 referenceHolder: true,
12 bodyPadding: 10,
13
14 layout: {
15 type: 'hbox',
16 align: 'stretch',
17 },
18
19 viewModel: {
20 data: {
21 full: "N/A",
22 stillbad: 0,
23 deduplication: 1.0,
24 error: "",
25 maintenance: '',
26 },
27 },
28 setTasks: function(taskdata, since) {
29 let me = this;
30 me.down('pbsTaskSummary').updateTasks(taskdata, since);
31 },
32
33 setStatus: function(statusData) {
34 let me = this;
35 let vm = me.getViewModel();
36
37 if (statusData.error !== undefined) {
38 Proxmox.Utils.API2Request({
39 url: `/config/datastore/${statusData.store}`,
40 success: (response) => {
41 const config = response.result.data;
42 if (config['maintenance-mode']) {
43 const [_type, msg] = PBS.Utils.parseMaintenanceMode(config['maintenance-mode']);
44 vm.set('maintenance', `${gettext('Datastore is in maintenance mode')}${msg ? ': ' + msg : ''}`);
45 }
46 },
47 });
48 vm.set('error', statusData.error);
49 return;
50 } else {
51 vm.set('error', "");
52 vm.set('maintenance', '');
53 }
54
55 let usagetext;
56 let usage;
57
58 if (Object.hasOwn(statusData, 'avail') && Object.hasOwn(statusData, 'used')) {
59 let total = statusData.avail + statusData.used;
60 usage = statusData.used / total;
61 usagetext = Ext.String.format(gettext('{0} of {1}'),
62 Proxmox.Utils.format_size(statusData.used, true),
63 Proxmox.Utils.format_size(total, true),
64 );
65 } else {
66 usagetext = Ext.String.format(gettext('{0} of {1}'), 0, 0);
67 usage = 0;
68 }
69
70 let usagePanel = me.lookup('usage');
71 usagePanel.updateValue(usage, usagetext);
72
73 let estimate = PBS.Utils.render_estimate(statusData['estimated-full-date'], null, { data: statusData });
74
75 vm.set('full', estimate);
76 vm.set('deduplication', PBS.Utils.calculate_dedup_factor(statusData['gc-status']).toFixed(2));
77 vm.set('stillbad', statusData['gc-status']['still-bad']);
78
79 let last = 0;
80 let time = statusData['history-start'];
81 let delta = statusData['history-delta'];
82 let data = statusData.history.map((val) => {
83 if (val === null) {
84 val = last;
85 } else {
86 last = val;
87 }
88 let entry = {
89 time: time*1000, // js Dates are ms since epoch
90 val,
91 };
92
93 time += delta;
94 return entry;
95 });
96
97 me.lookup('historychart').setData(data);
98 },
99
100 items: [
101 {
102 xtype: 'container',
103 layout: {
104 type: 'vbox',
105 align: 'stretch',
106 },
107
108 width: 375,
109 padding: '5 25 5 5',
110
111 defaults: {
112 padding: 2,
113 },
114
115 items: [
116 {
117 xtype: 'box',
118 hidden: true,
119 tpl: [
120 '<center>',
121 `<h3>${gettext("Error")}</h3>`,
122 '<i class="fa fa-5x fa-exclamation-circle critical"></i>',
123 '<br /><br/>',
124 '{text}',
125 '</center>',
126 ],
127 bind: {
128 visible: '{error && !maintenance}',
129 data: {
130 text: '{error}',
131 },
132 },
133 },
134 {
135 xtype: 'box',
136 hidden: true,
137 tpl: [
138 '<center>',
139 `<h3>${gettext("Maintenance mode")}</h3>`,
140 '<i class="fa fa-5x fa-wrench"></i>',
141 '<br /><br/>',
142 '{text}',
143 '</center>',
144 ],
145 bind: {
146 visible: '{maintenance}',
147 data: {
148 text: '{maintenance}',
149 },
150 },
151 },
152 {
153 xtype: 'proxmoxGauge',
154 warningThreshold: 0.8,
155 criticalThreshold: 0.95,
156 flex: 1,
157 reference: 'usage',
158 bind: {
159 visible: '{!error}',
160 },
161 },
162 {
163 xtype: 'pmxInfoWidget',
164 iconCls: 'fa fa-fw fa-line-chart',
165 title: gettext('Estimated Full'),
166 printBar: false,
167 bind: {
168 data: {
169 text: '{full}',
170 },
171 visible: '{!error}',
172 },
173 },
174 {
175 xtype: 'pmxInfoWidget',
176 iconCls: 'fa fa-fw fa-compress',
177 title: gettext('Deduplication Factor'),
178 printBar: false,
179 bind: {
180 data: {
181 text: '{deduplication}',
182 },
183 visible: '{!error}',
184 },
185 },
186 {
187 xtype: 'pmxInfoWidget',
188 iconCls: 'fa critical fa-fw fa-exclamation-triangle',
189 title: gettext('Bad Chunks'),
190 printBar: false,
191 hidden: true,
192 bind: {
193 data: {
194 text: '{stillbad}',
195 },
196 visible: '{stillbad}',
197 },
198 },
199 ],
200 },
201 {
202 xtype: 'container',
203 layout: {
204 type: 'vbox',
205 align: 'stretch',
206 },
207
208 flex: 1,
209
210 items: [
211 {
212 padding: 5,
213 xtype: 'pbsUsageChart',
214 reference: 'historychart',
215 title: gettext('Usage History'),
216 height: 100,
217 bind: {
218 visible: '{!error}',
219 },
220 },
221 {
222 xtype: 'container',
223 flex: 1,
224 layout: {
225 type: 'vbox',
226 align: 'stretch',
227 },
228
229 defaults: {
230 padding: 5,
231 },
232
233 items: [
234 {
235 xtype: 'label',
236 text: gettext('Task Summary')
237 + ` (${Ext.String.format(gettext('{0} days'), 30)})`,
238 },
239 {
240 xtype: 'pbsTaskSummary',
241 border: false,
242 header: false,
243 subPanelModal: true,
244 flex: 2,
245 bodyPadding: 0,
246 minHeight: 0,
247 cbind: {
248 datastore: '{datastore}',
249 },
250 },
251 ],
252 },
253 ],
254 },
255 ],
256 });