]>
git.proxmox.com Git - proxmox-backup.git/blob - www/DataStoreContent.js
1 Ext
.define('pbs-data-store-snapshots', {
2 extend
: 'Ext.data.Model',
9 dateFormat
: 'timestamp'
13 { name
: 'size', type
: 'int', allowNull
: true, },
17 calculate: function(data
) {
27 data
.files
.forEach(file
=> {
28 if (file
.filename
=== 'index.json.blob') return; // is never encrypted
29 let mode
= PBS
.Utils
.cryptmap
.indexOf(file
['crypt-mode']);
31 crypt
[file
['crypt-mode']]++;
36 return PBS
.Utils
.calculateCryptMode(crypt
);
42 Ext
.define('PBS.DataStoreContent', {
43 extend
: 'Ext.tree.Panel',
44 alias
: 'widget.pbsDataStoreContent',
48 title
: gettext('Content'),
51 xclass
: 'Ext.app.ViewController',
53 init: function(view
) {
54 if (!view
.datastore
) {
55 throw "no datastore specified";
58 this.store
= Ext
.create('Ext.data.Store', {
59 model
: 'pbs-data-store-snapshots',
60 groupField
: 'backup-group',
62 this.store
.on('load', this.onLoad
, this);
64 view
.getStore().setSorters([
69 Proxmox
.Utils
.monStoreErrors(view
, this.store
);
70 this.reload(); // initial load
74 let view
= this.getView();
76 if (!view
.store
|| !this.store
) {
77 console
.warn('cannot reload, no store(s)');
81 let url
= `/api2/json/admin/datastore/${view.datastore}/snapshots`;
84 timeout
: 300*1000, // 5 minutes, we should make that api call faster
91 getRecordGroups: function(records
) {
94 for (const item
of records
) {
95 var btype
= item
.data
["backup-type"];
96 let group
= btype
+ "/" + item
.data
["backup-id"];
98 if (groups
[group
] !== undefined) {
103 if (btype
=== 'vm') {
105 } else if (btype
=== 'ct') {
107 } else if (btype
=== 'host') {
110 console
.warn(`got unknown backup-type '${btype}'`);
111 continue; // FIXME: auto render? what do?
117 iconCls
: "fa " + cls
,
119 backup_type
: item
.data
["backup-type"],
120 backup_id
: item
.data
["backup-id"],
128 onLoad: function(store
, records
, success
, operation
) {
129 let view
= this.getView();
132 Proxmox
.Utils
.setErrorMask(view
, Proxmox
.Utils
.getResponseErrorMessage(operation
.getError()));
136 let groups
= this.getRecordGroups(records
);
138 for (const item
of records
) {
139 let group
= item
.data
["backup-type"] + "/" + item
.data
["backup-id"];
140 let children
= groups
[group
].children
;
142 let data
= item
.data
;
144 data
.text
= group
+ '/' + PBS
.Utils
.render_datetime_utc(data
["backup-time"]);
146 data
.cls
= 'no-leaf-icons';
152 for (const [_key
, group
] of Object
.entries(groups
)) {
160 for (const item
of group
.children
) {
161 crypt
[PBS
.Utils
.cryptmap
[item
['crypt-mode']]]++;
162 if (item
["backup-time"] > last_backup
&& item
.size
!== null) {
163 last_backup
= item
["backup-time"];
164 group
["backup-time"] = last_backup
;
165 group
.files
= item
.files
;
166 group
.size
= item
.size
;
167 group
.owner
= item
.owner
;
171 group
.count
= group
.children
.length
;
172 crypt
.count
= group
.count
;
173 group
['crypt-mode'] = PBS
.Utils
.calculateCryptMode(crypt
);
174 children
.push(group
);
181 Proxmox
.Utils
.setErrorMask(view
, false);
184 onPrune: function() {
185 var view
= this.getView();
187 let rec
= view
.selModel
.getSelection()[0];
188 if (!(rec
&& rec
.data
)) return;
190 if (data
.leaf
) return;
192 if (!view
.datastore
) return;
194 let win
= Ext
.create('PBS.DataStorePrune', {
195 datastore
: view
.datastore
,
196 backup_type
: data
.backup_type
,
197 backup_id
: data
.backup_id
,
199 win
.on('destroy', this.reload
, this);
203 onVerify: function() {
204 var view
= this.getView();
206 if (!view
.datastore
) return;
208 let rec
= view
.selModel
.getSelection()[0];
209 if (!(rec
&& rec
.data
)) return;
216 "backup-type": data
["backup-type"],
217 "backup-id": data
["backup-id"],
218 "backup-time": (data
['backup-time'].getTime()/1000).toFixed(0),
222 "backup-type": data
.backup_type
,
223 "backup-id": data
.backup_id
,
227 Proxmox
.Utils
.API2Request({
229 url
: `/admin/datastore/${view.datastore}/verify`,
231 failure: function(response
) {
232 Ext
.Msg
.alert(gettext('Error'), response
.htmlStatus
);
234 success: function(response
, options
) {
235 Ext
.create('Proxmox.window.TaskViewer', {
236 upid
: response
.result
.data
,
242 onForget: function() {
243 var view
= this.getView();
245 let rec
= view
.selModel
.getSelection()[0];
246 if (!(rec
&& rec
.data
)) return;
248 if (!data
.leaf
) return;
250 if (!view
.datastore
) return;
254 Proxmox
.Utils
.API2Request({
256 "backup-type": data
["backup-type"],
257 "backup-id": data
["backup-id"],
258 "backup-time": (data
['backup-time'].getTime()/1000).toFixed(0),
260 url
: `/admin/datastore/${view.datastore}/snapshots`,
263 failure: function(response
, opts
) {
264 Ext
.Msg
.alert(gettext('Error'), response
.htmlStatus
);
266 callback
: this.reload
.bind(this),
270 openBackupFileDownloader: function() {
272 let view
= me
.getView();
274 let rec
= view
.selModel
.getSelection()[0];
275 if (!(rec
&& rec
.data
)) return;
278 Ext
.create('PBS.window.BackupFileDownloader', {
279 baseurl
: `/api2/json/admin/datastore/${view.datastore}`,
281 'backup-id': data
['backup-id'],
282 'backup-type': data
['backup-type'],
283 'backup-time': (data
['backup-time'].getTime()/1000).toFixed(0),
289 openPxarBrowser: function() {
291 let view
= me
.getView();
293 let rec
= view
.selModel
.getSelection()[0];
294 if (!(rec
&& rec
.data
)) return;
297 let encrypted
= false;
298 data
.files
.forEach(file
=> {
299 if (file
.filename
=== 'catalog.pcat1.didx' && file
['crypt-mode'] === 'encrypt') {
306 gettext('Cannot open Catalog'),
307 gettext('Only unencrypted Backups can be opened on the server. Please use the client with the decryption key instead.'),
312 let id
= data
['backup-id'];
313 let time
= data
['backup-time'];
314 let type
= data
['backup-type'];
315 let timetext
= PBS
.Utils
.render_datetime_utc(data
["backup-time"]);
317 Ext
.create('PBS.window.FileBrowser', {
318 title
: `${type}/${id}/${timetext}`,
319 datastore
: view
.datastore
,
321 'backup-time': (time
.getTime()/1000).toFixed(0),
330 header
: gettext("Backup Group"),
336 header
: gettext('Backup Time'),
338 dataIndex
: 'backup-time',
339 format
: 'Y-m-d H:i:s',
343 header
: gettext("Size"),
346 renderer
: (v
, meta
, record
) => {
347 if (v
=== undefined || v
=== null) {
348 meta
.tdCls
= "x-grid-row-loading";
351 return Proxmox
.Utils
.format_size(v
);
355 xtype
: 'numbercolumn',
357 header
: gettext("Count"),
362 header
: gettext("Owner"),
367 header
: gettext('Encrypted'),
368 dataIndex
: 'crypt-mode',
369 renderer
: value
=> PBS
.Utils
.cryptText
[value
] || Proxmox
.Utils
.unknownText
,
372 header
: gettext("Files"),
375 renderer: function(files
) {
376 return files
.map((file
) => {
379 let mode
= PBS
.Utils
.cryptmap
.indexOf(file
['crypt-mode']);
380 let iconCls
= PBS
.Utils
.cryptIconCls
[mode
] || '';
381 if (iconCls
!== '') {
382 icon
= `<i class="fa fa-${iconCls}"></i> `;
385 size
= ` (${Proxmox.Utils.format_size(file.size)})`;
387 return `${icon}${file.filename}${size}`;
396 text
: gettext('Reload'),
397 iconCls
: 'fa fa-refresh',
402 xtype
: 'proxmoxButton',
403 text
: gettext('Verify'),
405 parentXType
: 'pbsDataStoreContent',
406 enableFn
: (rec
) => !!rec
.data
&& rec
.data
.size
!== null,
410 xtype
: 'proxmoxButton',
411 text
: gettext('Prune'),
413 parentXType
: 'pbsDataStoreContent',
414 enableFn
: (rec
) => !rec
.data
.leaf
,
418 xtype
: 'proxmoxButton',
419 text
: gettext('Forget'),
421 parentXType
: 'pbsDataStoreContent',
424 confirmMsg: function(record
) {
425 //console.log(record);
426 let name
= record
.data
.text
;
427 return Ext
.String
.format(gettext('Are you sure you want to remove snapshot {0}'), `'${name}'`);
429 enableFn
: (rec
) => !!rec
.data
.leaf
&& rec
.data
.size
!== null,
433 xtype
: 'proxmoxButton',
434 text
: gettext('Download Files'),
436 parentXType
: 'pbsDataStoreContent',
437 handler
: 'openBackupFileDownloader',
438 enableFn
: (rec
) => !!rec
.data
.leaf
&& rec
.data
.size
!== null,
441 xtype
: "proxmoxButton",
442 text
: gettext('PXAR File Browser'),
444 handler
: 'openPxarBrowser',
445 parentXType
: 'pbsDataStoreContent',
446 enableFn: function(record
) {
447 return !!record
.data
.leaf
&& record
.size
!== null && record
.data
.files
.some(el
=> el
.filename
.endsWith('pxar.didx'));