]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/storage/Base.js
ui: storage: base: allow adding extra tab panels
[pve-manager.git] / www / manager6 / storage / Base.js
1 Ext.define('PVE.panel.StorageBase', {
2 extend: 'Proxmox.panel.InputPanel',
3 controller: 'storageEdit',
4
5 type: '',
6
7 onGetValues: function(values) {
8 var me = this;
9
10 if (me.isCreate) {
11 values.type = me.type;
12 } else {
13 delete values.storage;
14 }
15
16 values.disable = values.enable ? 0 : 1;
17 delete values.enable;
18
19 return values;
20 },
21
22 initComponent : function() {
23 var me = this;
24
25 me.column1.unshift({
26 xtype: me.isCreate ? 'textfield' : 'displayfield',
27 name: 'storage',
28 value: me.storageId || '',
29 fieldLabel: 'ID',
30 vtype: 'StorageId',
31 allowBlank: false
32 });
33
34 me.column2 = me.column2 || [];
35 me.column2.unshift(
36 {
37 xtype: 'pveNodeSelector',
38 name: 'nodes',
39 disabled: me.storageId === 'local',
40 fieldLabel: gettext('Nodes'),
41 emptyText: gettext('All') + ' (' + gettext('No restrictions') +')',
42 multiSelect: true,
43 autoSelect: false
44 },
45 {
46 xtype: 'proxmoxcheckbox',
47 name: 'enable',
48 checked: true,
49 uncheckedValue: 0,
50 fieldLabel: gettext('Enable')
51 }
52 );
53
54 me.callParent();
55 }
56 });
57
58 Ext.define('PVE.panel.StoragePruneInputPanel', {
59 extend: 'Proxmox.panel.PruneInputPanel',
60 xtype: 'pveStoragePruneInputPanel',
61 mixins: ['Proxmox.Mixin.CBind'],
62
63 onlineHelp: 'vzdump_retention',
64
65 keepLastEmptyText: gettext('1'),
66
67 onGetValues: function(formValues) {
68 delete formValues.delete;
69 let retention = PVE.Parser.printPropertyString(formValues)
70 if (retention === '') {
71 if (this.isCreate) {
72 return {};
73 }
74 // always delete old 'maxfiles' on edit, we map it to keep-last on window load
75 return {
76 delete: ['prune-backups','maxfiles'],
77 };
78 }
79 let options = { 'prune-backups': retention };
80 if (!this.isCreate) {
81 options.delete = 'maxfiles';
82 }
83 return options;
84 },
85
86 updateComponents: function() {
87 let panel = this;
88
89 let keepAll = panel.down('proxmoxcheckbox[name=keep-all]').getValue();
90 let anyValue = false;
91 panel.query('pmxPruneKeepField').forEach(field => {
92 anyValue = anyValue || field.getValue() !== null;
93 field.setDisabled(keepAll);
94 });
95 panel.down('component[name=no-keeps-hint]').setHidden(anyValue || keepAll);
96 },
97
98 listeners: {
99 afterrender: function(panel) {
100 if (panel.needMask) {
101 panel.down('component[name=no-keeps-hint]').setHtml('');
102 panel.mask(
103 gettext('Backup content type not available for this storage.'),
104 );
105 } else if (panel.isCreate) {
106 panel.down('proxmoxcheckbox[name=keep-all]').setValue(true);
107 }
108 panel.down('component[name=pbs-hint]').setHidden(!panel.isPBS);
109
110 panel.query('pmxPruneKeepField').forEach(field => {
111 field.on('change', panel.updateComponents, panel);
112 });
113 panel.updateComponents();
114 },
115 },
116
117 columnT: {
118 xtype: 'proxmoxcheckbox',
119 name: 'keep-all',
120 boxLabel: gettext('Keep all backups'),
121 listeners: {
122 change: function(field, newValue) {
123 let panel = field.up('pveStoragePruneInputPanel');
124 panel.updateComponents();
125 },
126 },
127 },
128
129 columnB: [
130 {
131 xtype: 'component',
132 userCls: 'pmx-hint',
133 name: 'no-keeps-hint',
134 hidden: true,
135 padding: '5 1',
136 html: gettext('Without any keep option, the nodes vzdump.conf or `keep-last 1` is used as fallback for backup jobs'),
137 },
138 {
139 xtype: 'component',
140 userCls: 'pmx-hint',
141 name: 'pbs-hint',
142 hidden: true,
143 padding: '5 1',
144 html: gettext("It's preferred to configure backup retention directly on the Proxmox Backup Server."),
145 },
146 ],
147 });
148
149 Ext.define('PVE.storage.BaseEdit', {
150 extend: 'Proxmox.window.Edit',
151
152 apiCallDone: function(success, response, options) {
153 let me = this;
154 if (typeof me.ipanel.apiCallDone === "function") {
155 me.ipanel.apiCallDone(success, response, options);
156 }
157 },
158
159 initComponent : function() {
160 var me = this;
161
162 me.isCreate = !me.storageId;
163
164 if (me.isCreate) {
165 me.url = '/api2/extjs/storage';
166 me.method = 'POST';
167 } else {
168 me.url = '/api2/extjs/storage/' + me.storageId;
169 me.method = 'PUT';
170 }
171
172 me.ipanel = Ext.create(me.paneltype, {
173 title: gettext('General'),
174 type: me.type,
175 isCreate: me.isCreate,
176 storageId: me.storageId
177 });
178
179 Ext.apply(me, {
180 subject: PVE.Utils.format_storage_type(me.type),
181 isAdd: true,
182 bodyPadding: 0,
183 items: {
184 xtype: 'tabpanel',
185 region: 'center',
186 layout: 'fit',
187 bodyPadding: 10,
188 items: [
189 me.ipanel,
190 {
191 xtype: 'pveStoragePruneInputPanel',
192 title: gettext('Backup Retention'),
193 isCreate: me.isCreate,
194 isPBS: me.ipanel.isPBS,
195 },
196 ],
197 },
198 });
199
200 if (me.ipanel.extraTabs) {
201 me.ipanel.extraTabs.forEach(panel => {
202 panel.isCreate = me.isCreate;
203 me.items.items.push(panel);
204 });
205 }
206
207 me.callParent();
208
209 let contentTypeField = me.ipanel.down('pveContentTypeSelector');
210 if (contentTypeField && !contentTypeField.cts.includes('backup')) {
211 // cannot mask now, not fully rendered until activated
212 me.down('pmxPruneInputPanel').needMask = true;
213 }
214
215 if (!me.isCreate) {
216 me.load({
217 success: function(response, options) {
218 var values = response.result.data;
219 var ctypes = values.content || '';
220
221 values.content = ctypes.split(',');
222
223 if (values.nodes) {
224 values.nodes = values.nodes.split(',');
225 }
226 values.enable = values.disable ? 0 : 1;
227 if (values['prune-backups']) {
228 let retention = PVE.Parser.parsePropertyString(values['prune-backups']);
229 delete values['prune-backups'];
230 Object.assign(values, retention);
231 } else if (values.maxfiles !== undefined) {
232 if (values.maxfiles > 0) {
233 values['keep-last'] = values.maxfiles;
234 }
235 delete values.maxfiles;
236 }
237
238 me.query('inputpanel').forEach(panel => {
239 panel.setValues(values);
240 });
241 }
242 });
243 }
244 }
245 });