]>
git.proxmox.com Git - pve-manager.git/blob - www/manager6/window/BulkAction.js
1 Ext
.define('PVE.window.BulkAction', {
2 extend
: 'Ext.window.Window',
13 // the action to set, currently there are: `startall`, `migrateall`, `stopall`
16 submit: function(params
) {
19 Proxmox
.Utils
.API2Request({
21 url
: `/nodes/${me.nodename}/${me.action}`,
24 failure
: response
=> Ext
.Msg
.alert('Error', response
.htmlStatus
),
25 success: function({ result
}, options
) {
26 Ext
.create('Proxmox.window.TaskViewer', {
30 destroy
: () => me
.close(),
38 initComponent: function() {
42 throw "no node name specified";
45 throw "no action specified";
48 throw "no button text specified";
51 throw "no title specified";
55 if (me
.action
=== 'migrateall') {
58 xtype
: 'fieldcontainer',
62 xtype
: 'pveNodeSelector',
64 disallowedNodes
: [me
.nodename
],
65 fieldLabel
: gettext('Target node'),
68 onlineValidator
: true,
72 xtype
: 'proxmoxintegerfield',
77 fieldLabel
: gettext('Parallel jobs'),
83 xtype
: 'fieldcontainer',
86 xtype
: 'proxmoxcheckbox',
87 fieldLabel
: gettext('Allow local disk migration'),
88 name
: 'with-local-disks',
97 xtype
: 'displayfield',
99 value
: 'Warning: Running CTs will be migrated in Restart Mode.',
100 hidden
: true, // only visible if running container chosen
105 } else if (me
.action
=== 'startall') {
107 xtype
: 'hiddenfield',
111 } else if (me
.action
=== 'stopall') {
113 xtype
: 'fieldcontainer',
116 xtype
: 'proxmoxcheckbox',
119 fieldLabel
: gettext('Force Stop'),
120 boxLabel
: gettext('Force stop guest if shutdown times out.'),
126 xtype
: 'proxmoxintegerfield',
128 fieldLabel
: gettext('Timeout (s)'),
139 let refreshLxcWarning = function(vmids
, records
) {
140 let showWarning
= records
.some(
141 item
=> vmids
.includes(item
.data
.vmid
) && item
.data
.type
=== 'lxc' && item
.data
.status
=== 'running',
143 me
.down('#lxcwarning').setVisible(showWarning
);
146 let defaultStatus
= me
.action
=== 'migrateall' ? '' : me
.action
=== 'startall' ? 'stopped' : 'running';
152 PVE
.data
.ResourceStore
.each((rec
) => {
153 if (['qemu', 'lxc'].indexOf(rec
.data
.type
) !== -1) {
154 statusMap
[rec
.data
.status
] = true;
156 if (rec
.data
.type
=== 'pool') {
157 poolMap
[rec
.data
.pool
] = true;
159 if (rec
.data
.hastate
!== "") {
160 haMap
[rec
.data
.hastate
] = true;
162 if (rec
.data
.tags
!== "") {
163 rec
.data
.tags
.split(/[,; ]/).forEach((tag
) => {
171 let statusList
= Object
.keys(statusMap
).map(key
=> [key
, key
]);
172 statusList
.unshift(['', gettext('All')]);
173 let poolList
= Object
.keys(poolMap
).map(key
=> [key
, key
]);
174 let tagList
= Object
.keys(tagMap
).map(key
=> ({ value
: key
}));
175 let haList
= Object
.keys(haMap
).map(key
=> [key
, key
]);
177 let clearFilters = function() {
178 me
.down('#namefilter').setValue('');
179 ['name', 'status', 'pool', 'type', 'hastate', 'includetag', 'excludetag', 'vmid'].forEach((filter
) => {
180 me
.down(`#${filter}filter`).setValue('');
184 let filterChange = function() {
185 let nameValue
= me
.down('#namefilter').getValue();
188 if (nameValue
!== '') {
192 let arrayFiltersData
= [];
193 ['pool', 'hastate'].forEach((filter
) => {
194 let selected
= me
.down(`#${filter}filter`).getValue() ?? [];
195 if (selected
.length
) {
197 arrayFiltersData
.push([filter
, [...selected
]]);
201 let singleFiltersData
= [];
202 ['status', 'type'].forEach((filter
) => {
203 let selected
= me
.down(`#${filter}filter`).getValue() ?? '';
204 if (selected
.length
) {
206 singleFiltersData
.push([filter
, selected
]);
210 let includeTags
= me
.down('#includetagfilter').getValue() ?? [];
211 if (includeTags
.length
) {
214 let excludeTags
= me
.down('#excludetagfilter').getValue() ?? [];
215 if (excludeTags
.length
) {
219 let fieldSet
= me
.down('#filters');
220 let clearBtn
= me
.down('#clearBtn');
222 fieldSet
.setTitle(Ext
.String
.format(gettext('Filters ({0})'), filterCount
));
223 clearBtn
.setDisabled(false);
225 fieldSet
.setTitle(gettext('Filters'));
226 clearBtn
.setDisabled(true);
229 let filterFn = function(value
) {
230 let name
= value
.data
.name
.toLowerCase().indexOf(nameValue
.toLowerCase()) !== -1;
231 let arrayFilters
= arrayFiltersData
.every(([filter
, selected
]) =>
232 !selected
.length
|| selected
.indexOf(value
.data
[filter
]) !== -1);
233 let singleFilters
= singleFiltersData
.every(([filter
, selected
]) =>
234 !selected
.length
|| value
.data
[filter
].indexOf(selected
) !== -1);
235 let tags
= value
.data
.tags
.split(/[;, ]/).filter(t
=> !!t
);
236 let includeFilter
= !includeTags
.length
|| tags
.some(tag
=> includeTags
.indexOf(tag
) !== -1);
237 let excludeFilter
= !excludeTags
.length
|| tags
.every(tag
=> excludeTags
.indexOf(tag
) === -1);
239 return name
&& arrayFilters
&& singleFilters
&& includeFilter
&& excludeFilter
;
241 let vmselector
= me
.down('#vms');
242 vmselector
.getStore().setFilters({
246 vmselector
.checkChange();
247 if (me
.action
=== 'migrateall') {
248 let records
= vmselector
.getSelection();
249 refreshLxcWarning(vmselector
.getValue(), records
);
257 title
: gettext('Filters'),
270 change
: filterChange
,
276 fieldLabel
: gettext("Name"),
277 itemId
: 'namefilter',
282 itemId
: 'statusfilter',
283 fieldLabel
: gettext("Status"),
284 emptyText
: gettext('All'),
286 value
: defaultStatus
,
291 itemId
: 'poolfilter',
292 fieldLabel
: gettext("Pool"),
293 emptyText
: gettext('All'),
310 change
: filterChange
,
317 itemId
: 'typefilter',
318 fieldLabel
: gettext("Type"),
319 emptyText
: gettext('All'),
323 ['', gettext('All')],
324 ['lxc', gettext('CT')],
325 ['qemu', gettext('VM')],
329 xtype
: 'proxmoxComboGrid',
330 itemId
: 'includetagfilter',
331 fieldLabel
: gettext("Include Tags"),
332 emptyText
: gettext('All'),
336 displayField
: 'value',
338 userCls
: 'proxmox-tags-full',
344 PVE
.Utils
.renderTags(value
, PVE
.UIOptions
.tagOverrides
),
352 change
: filterChange
,
356 xtype
: 'proxmoxComboGrid',
357 itemId
: 'excludetagfilter',
358 fieldLabel
: gettext("Exclude Tags"),
359 emptyText
: gettext('None'),
363 displayField
: 'value',
365 userCls
: 'proxmox-tags-full',
371 PVE
.Utils
.renderTags(value
, PVE
.UIOptions
.tagOverrides
),
379 change
: filterChange
,
394 change
: filterChange
,
401 itemId
: 'hastatefilter',
402 fieldLabel
: gettext("HA status"),
403 emptyText
: gettext('All'),
408 change
: filterChange
,
421 text
: gettext('Clear Filters'),
423 handler
: clearFilters
,
441 nodename
: me
.nodename
,
443 selectionchange: function(vmselector
, records
) {
444 if (me
.action
=== 'migrateall') {
445 let vmids
= me
.down('#vms').getValue();
446 refreshLxcWarning(vmids
, records
);
452 me
.formPanel
= Ext
.create('Ext.form.Panel', {
465 let form
= me
.formPanel
.getForm();
467 let submitBtn
= Ext
.create('Ext.Button', {
469 handler: function() {
471 me
.submit(form
.getValues());
476 items
: [me
.formPanel
],
477 buttons
: [submitBtn
],
482 form
.on('validitychange', function() {
483 let valid
= form
.isValid();
484 submitBtn
.setDisabled(!valid
);