]> git.proxmox.com Git - proxmox-backup.git/blob - www/datastore/Prune.js
Makefile: drop outdated comment
[proxmox-backup.git] / www / datastore / Prune.js
1 Ext.define('pbs-prune-list', {
2 extend: 'Ext.data.Model',
3 fields: [
4 'backup-type',
5 'backup-id',
6 {
7 name: 'backup-time',
8 type: 'date',
9 dateFormat: 'timestamp',
10 },
11 ],
12 });
13
14 Ext.define('PBS.PruneKeepInput', {
15 extend: 'Proxmox.form.field.Integer',
16 alias: 'widget.pbsPruneKeepInput',
17
18 allowBlank: true,
19 minValue: 1,
20
21 listeners: {
22 change: function(field, newValue, oldValue) {
23 if (newValue !== this.originalValue) {
24 this.triggers.clear.setVisible(true);
25 }
26 },
27 },
28 triggers: {
29 clear: {
30 cls: 'pmx-clear-trigger',
31 weight: -1,
32 hidden: true,
33 handler: function() {
34 this.triggers.clear.setVisible(false);
35 this.setValue(this.originalValue);
36 },
37 },
38 },
39
40 });
41
42 Ext.define('PBS.Datastore.PruneInputPanel', {
43 extend: 'Proxmox.panel.InputPanel',
44 alias: 'widget.pbsDataStorePruneInputPanel',
45 mixins: ['Proxmox.Mixin.CBind'],
46
47 onGetValues: function(values) {
48 var me = this;
49
50 values["backup-type"] = me.backup_type;
51 values["backup-id"] = me.backup_id;
52 if (me.ns && me.ns !== '') {
53 values.ns = me.ns;
54 }
55 values["use-task"] = true;
56 return values;
57 },
58
59 controller: {
60 xclass: 'Ext.app.ViewController',
61
62 init: function(view) {
63 if (!view.url) {
64 throw "no url specified";
65 }
66 if (!view.backup_type) {
67 throw "no backup_type specified";
68 }
69 if (!view.backup_id) {
70 throw "no backup_id specified";
71 }
72
73 this.reload(); // initial load
74 },
75
76 reload: function() {
77 var view = this.getView();
78
79 // helper to allow showing why a backup is kept
80 let addKeepReasons = function(backups, params) {
81 const rules = [
82 'keep-last',
83 'keep-hourly',
84 'keep-daily',
85 'keep-weekly',
86 'keep-monthly',
87 'keep-yearly',
88 'keep-all', // when all keep options are not set
89 ];
90 let counter = {};
91
92 backups.sort(function(a, b) {
93 return b["backup-time"] - a["backup-time"];
94 });
95
96 let ruleIndex = -1;
97 let nextRule = function() {
98 let rule;
99 do {
100 ruleIndex++;
101 rule = rules[ruleIndex];
102 } while (!params[rule] && rule !== 'keep-all');
103 counter[rule] = 0;
104 return rule;
105 };
106
107 let rule = nextRule();
108 for (let backup of backups) {
109 if (backup.keep) {
110 if (backup.protected) {
111 backup.keepReason = 'protected';
112 continue;
113 }
114 counter[rule]++;
115 if (rule !== 'keep-all') {
116 backup.keepReason = rule + ': ' + counter[rule];
117 if (counter[rule] >= params[rule]) {
118 rule = nextRule();
119 }
120 } else {
121 backup.keepReason = rule;
122 }
123 }
124 }
125 };
126
127 let params = view.getValues();
128 params["dry-run"] = true;
129 if (view.ns && view.ns !== '') {
130 params.ns = view.ns;
131 }
132
133 Proxmox.Utils.API2Request({
134 url: view.url,
135 method: "POST",
136 params: params,
137 callback: function() {
138 // for easy breakpoint setting
139 },
140 failure: response => Ext.Msg.alert(gettext('Error'), response.htmlStatus),
141 success: function(response, options) {
142 let data = response.result.data;
143 addKeepReasons(data, params);
144 view.prune_store.setData(data);
145 },
146 });
147 },
148
149 control: {
150 field: { change: 'reload' },
151 },
152 },
153
154 column1: [
155 {
156 xtype: 'pbsPruneKeepInput',
157 name: 'keep-last',
158 fieldLabel: gettext('keep-last'),
159 },
160 {
161 xtype: 'pbsPruneKeepInput',
162 name: 'keep-hourly',
163 fieldLabel: gettext('keep-hourly'),
164 },
165 {
166 xtype: 'pbsPruneKeepInput',
167 name: 'keep-daily',
168 fieldLabel: gettext('keep-daily'),
169 },
170 {
171 xtype: 'pbsPruneKeepInput',
172 name: 'keep-weekly',
173 fieldLabel: gettext('keep-weekly'),
174 },
175 {
176 xtype: 'pbsPruneKeepInput',
177 name: 'keep-monthly',
178 fieldLabel: gettext('keep-monthly'),
179 },
180 {
181 xtype: 'pbsPruneKeepInput',
182 name: 'keep-yearly',
183 fieldLabel: gettext('keep-yearly'),
184 },
185 ],
186
187
188 initComponent: function() {
189 var me = this;
190
191 me.prune_store = Ext.create('Ext.data.Store', {
192 model: 'pbs-prune-list',
193 sorters: { property: 'backup-time', direction: 'DESC' },
194 });
195
196 me.column2 = [
197 {
198 xtype: 'grid',
199 height: 200,
200 store: me.prune_store,
201 columns: [
202 {
203 header: gettext('Backup Time'),
204 sortable: true,
205 dataIndex: 'backup-time',
206 renderer: function(value, metaData, record) {
207 let text = Ext.Date.format(value, 'Y-m-d H:i:s');
208 if (record.data.keep) {
209 return text;
210 } else {
211 return '<div style="text-decoration: line-through;">'+ text +'</div>';
212 }
213 },
214 flex: 1,
215 },
216 {
217 text: 'Keep (reason)',
218 dataIndex: 'keep',
219 renderer: function(value, metaData, record) {
220 if (record.data.keep) {
221 return 'true (' + record.data.keepReason + ')';
222 } else {
223 return 'false';
224 }
225 },
226 flex: 1,
227 },
228 ],
229 },
230 ];
231
232 me.callParent();
233 },
234 });
235
236 Ext.define('PBS.DataStorePrune', {
237 extend: 'Proxmox.window.Edit',
238
239 onlineHelp: 'maintenance_pruning',
240
241 method: 'POST',
242 submitText: "Prune",
243
244 isCreate: true,
245
246 fieldDefaults: { labelWidth: 130 },
247
248 initComponent: function() {
249 var me = this;
250
251 if (!me.datastore) {
252 throw "no datastore specified";
253 }
254 if (!me.backup_type) {
255 throw "no backup_type specified";
256 }
257 if (!me.backup_id) {
258 throw "no backup_id specified";
259 }
260
261 let ns = me.ns && me.ns !== '' ? `${me.ns} ` : '';
262
263 Ext.apply(me, {
264 url: '/api2/extjs/admin/datastore/' + me.datastore + "/prune",
265 title: `Prune Group '${me.backup_type}/${me.backup_id}' on '${me.datastore}:${ns}'`,
266 items: [{
267 xtype: 'pbsDataStorePruneInputPanel',
268 url: '/api2/extjs/admin/datastore/' + me.datastore + "/prune",
269 ns: me.ns,
270 backup_type: me.backup_type,
271 backup_id: me.backup_id,
272 }],
273 });
274
275 me.callParent();
276 },
277 });