Ext.define('pbs-prune-list', { extend: 'Ext.data.Model', fields: [ 'backup-type', 'backup-id', { name: 'backup-time', type: 'date', dateFormat: 'timestamp', }, ], }); Ext.define('PBS.PruneKeepInput', { extend: 'Proxmox.form.field.Integer', alias: 'widget.pbsPruneKeepInput', allowBlank: true, minValue: 1, listeners: { change: function(field, newValue, oldValue) { if (newValue !== this.originalValue) { this.triggers.clear.setVisible(true); } }, }, triggers: { clear: { cls: 'pmx-clear-trigger', weight: -1, hidden: true, handler: function() { this.triggers.clear.setVisible(false); this.setValue(this.originalValue); }, }, }, }); Ext.define('PBS.Datastore.PruneInputPanel', { extend: 'Proxmox.panel.InputPanel', alias: 'widget.pbsDataStorePruneInputPanel', mixins: ['Proxmox.Mixin.CBind'], onGetValues: function(values) { var me = this; values["backup-type"] = me.backup_type; values["backup-id"] = me.backup_id; return values; }, controller: { xclass: 'Ext.app.ViewController', init: function(view) { if (!view.url) { throw "no url specified"; } if (!view.backup_type) { throw "no backup_type specified"; } if (!view.backup_id) { throw "no backup_id specified"; } this.reload(); // initial load }, reload: function() { var view = this.getView(); // helper to allow showing why a backup is kept let addKeepReasons = function(backups, params) { const rules = [ 'keep-last', 'keep-hourly', 'keep-daily', 'keep-weekly', 'keep-monthly', 'keep-yearly', 'keep-all', // when all keep options are not set ]; let counter = {}; backups.sort(function(a, b) { return a["backup-time"] < b["backup-time"]; }); let ruleIndex = -1; let nextRule = function() { let rule; do { ruleIndex++; rule = rules[ruleIndex]; } while (!params[rule] && rule !== 'keep-all'); counter[rule] = 0; return rule; }; let rule = nextRule(); for (let backup of backups) { if (backup.keep) { counter[rule]++; if (rule !== 'keep-all') { backup.keepReason = rule + ': ' + counter[rule]; if (counter[rule] >= params[rule]) { rule = nextRule(); } } else { backup.keepReason = rule; } } } }; let params = view.getValues(); params["dry-run"] = true; Proxmox.Utils.API2Request({ url: view.url, method: "POST", params: params, callback: function() { // for easy breakpoint setting }, failure: function(response, opts) { Ext.Msg.alert(gettext('Error'), response.htmlStatus); }, success: function(response, options) { var data = response.result.data; addKeepReasons(data, params); view.prune_store.setData(data); }, }); }, control: { field: { change: 'reload' }, }, }, column1: [ { xtype: 'pbsPruneKeepInput', name: 'keep-last', fieldLabel: gettext('keep-last'), }, { xtype: 'pbsPruneKeepInput', name: 'keep-hourly', fieldLabel: gettext('keep-hourly'), }, { xtype: 'pbsPruneKeepInput', name: 'keep-daily', fieldLabel: gettext('keep-daily'), }, { xtype: 'pbsPruneKeepInput', name: 'keep-weekly', fieldLabel: gettext('keep-weekly'), }, { xtype: 'pbsPruneKeepInput', name: 'keep-monthly', fieldLabel: gettext('keep-monthly'), }, { xtype: 'pbsPruneKeepInput', name: 'keep-yearly', fieldLabel: gettext('keep-yearly'), }, ], initComponent: function() { var me = this; me.prune_store = Ext.create('Ext.data.Store', { model: 'pbs-prune-list', sorters: { property: 'backup-time', direction: 'DESC' }, }); me.column2 = [ { xtype: 'grid', height: 200, store: me.prune_store, columns: [ { header: gettext('Backup Time'), sortable: true, dataIndex: 'backup-time', renderer: function(value, metaData, record) { let text = Ext.Date.format(value, 'Y-m-d H:i:s'); if (record.data.keep) { return text; } else { return '