forked from proxmox-mirrors/proxmox-backup

Even if the notification mode is set to 'notification-system', the datastore options grid still shows the keys for 'Notify' and 'Notify User', which have no effect in this mode: Notification: [Use global notification settings] Notify: [Prune: Default(always), etc...] Notify User: [root@pam] This is quite confusing. Unfortunately, it seems be quite hard to dynamically disable/hide rows in the grid panel used in this view. For that reason these rows are removed completely for now. The options are still visible when opening the edit window for the 'Notification' row. While this slightly worsens UX in some cases (information is hidden), it improves clarity by reducing ambiguity, which is also a vital part of good UX. Signed-off-by: Lukas Wagner <l.wagner@proxmox.com> Link: https://lore.proxmox.com/20250623141315.288681-10-l.wagner@proxmox.com
297 lines
10 KiB
JavaScript
297 lines
10 KiB
JavaScript
Ext.define('PBS.window.SafeDatastoreDestroy', {
|
|
extend: 'Proxmox.window.SafeDestroy',
|
|
xtype: 'pbsDatastoreSafeDestroy',
|
|
mixins: ['Proxmox.Mixin.CBind'],
|
|
|
|
cbind: {
|
|
url: `/config/datastore/{datastore}`,
|
|
item: (get) => ({ id: get('datastore') }),
|
|
},
|
|
viewModel: {
|
|
data: {
|
|
destroyData: 0,
|
|
keepJobConfigs: 0,
|
|
},
|
|
formulas: {
|
|
destroyNote: (get) =>
|
|
get('destroyData')
|
|
? gettext('All backup snapshots and their data will be permanently destroyed!')
|
|
: gettext('Configuration change only, no data will be deleted.'),
|
|
destroyNoteCls: (get) => (get('destroyData') ? 'pmx-hint' : ''),
|
|
},
|
|
},
|
|
|
|
autoShow: true,
|
|
taskName: 'delete-datastore',
|
|
|
|
apiCallDone: function (success) {
|
|
if (success) {
|
|
let navtree = Ext.ComponentQuery.query('navigationtree')[0];
|
|
navtree.rstore.load();
|
|
let mainview = Ext.ComponentQuery.query('mainview')[0];
|
|
mainview.getController().redirectTo('pbsDataStores');
|
|
}
|
|
},
|
|
|
|
getParams: function () {
|
|
let viewModel = this.getViewModel();
|
|
|
|
let params = {
|
|
'destroy-data': viewModel.get('destroyData'),
|
|
'keep-job-configs': viewModel.get('keepJobConfigs'),
|
|
};
|
|
return `?${Ext.Object.toQueryString(params)}`;
|
|
},
|
|
additionalItems: [
|
|
{
|
|
xtype: 'proxmoxcheckbox',
|
|
name: 'destroy-data',
|
|
boxLabel: gettext('Destroy all data (dangerous!)'),
|
|
defaultValue: false,
|
|
bind: {
|
|
value: '{destroyData}',
|
|
},
|
|
},
|
|
{
|
|
xtype: 'proxmoxcheckbox',
|
|
name: 'keep-job-configs',
|
|
boxLabel: gettext('Keep configured jobs and permissions'),
|
|
defaultValue: false,
|
|
bind: {
|
|
value: '{keepJobConfigs}',
|
|
},
|
|
},
|
|
{
|
|
xtype: 'component',
|
|
reference: 'noteCmp',
|
|
bind: {
|
|
html: '{destroyNote}',
|
|
userCls: '{destroyNoteCls}',
|
|
},
|
|
},
|
|
],
|
|
});
|
|
|
|
Ext.define('PBS.Datastore.Options', {
|
|
extend: 'Proxmox.grid.ObjectGrid',
|
|
xtype: 'pbsDatastoreOptionView',
|
|
mixins: ['Proxmox.Mixin.CBind'],
|
|
|
|
cbindData: function (initial) {
|
|
let me = this;
|
|
|
|
me.maintenanceActiveTasks = {
|
|
read: 0,
|
|
write: 0,
|
|
};
|
|
me.datastore = encodeURIComponent(me.datastore);
|
|
me.url = `/api2/json/config/datastore/${me.datastore}`;
|
|
me.editorConfig = {
|
|
url: `/api2/extjs/config/datastore/${me.datastore}`,
|
|
datastore: me.datastore,
|
|
};
|
|
return {};
|
|
},
|
|
|
|
controller: {
|
|
xclass: 'Ext.app.ViewController',
|
|
|
|
init: function (view) {
|
|
let me = this;
|
|
|
|
me.activeOperationsRstore = Ext.create('Proxmox.data.ObjectStore', {
|
|
url: `/api2/json/admin/datastore/${view.datastore}/active-operations`,
|
|
interval: 3000,
|
|
});
|
|
me.activeOperationsRstore.startUpdate();
|
|
|
|
view.mon(me.activeOperationsRstore, 'load', (store, data, success) => {
|
|
let activeTasks = me.getView().maintenanceActiveTasks;
|
|
activeTasks.read = data?.[0]?.data.value ?? 0;
|
|
activeTasks.write = data?.[1]?.data.value ?? 0;
|
|
});
|
|
},
|
|
|
|
edit: function () {
|
|
this.getView().run_editor();
|
|
},
|
|
|
|
removeDatastore: function () {
|
|
let me = this;
|
|
Ext.create('PBS.window.SafeDatastoreDestroy', {
|
|
datastore: me.getView().datastore,
|
|
});
|
|
},
|
|
|
|
stopUpdates: function () {
|
|
let me = this;
|
|
let view = me.getView();
|
|
|
|
view.rstore.stopUpdate();
|
|
me.activeOperationsRstore.stopUpdate();
|
|
},
|
|
startUpdates: function () {
|
|
let me = this;
|
|
let view = me.getView();
|
|
|
|
view.rstore.startUpdate();
|
|
me.activeOperationsRstore.startUpdate();
|
|
},
|
|
},
|
|
|
|
tbar: [
|
|
{
|
|
xtype: 'proxmoxButton',
|
|
text: gettext('Edit'),
|
|
disabled: true,
|
|
handler: 'edit',
|
|
},
|
|
'->',
|
|
{
|
|
xtype: 'proxmoxButton',
|
|
selModel: null,
|
|
iconCls: 'fa fa-trash-o',
|
|
text: gettext('Remove Datastore'),
|
|
handler: 'removeDatastore',
|
|
},
|
|
],
|
|
|
|
listeners: {
|
|
activate: 'startUpdates',
|
|
beforedestroy: 'stopUpdates',
|
|
deactivate: 'stopUpdates',
|
|
itemdblclick: 'edit',
|
|
},
|
|
|
|
rows: {
|
|
'notification-mode': {
|
|
required: true,
|
|
defaultValue: 'notification-system',
|
|
header: gettext('Notifications'),
|
|
renderer: function (value) {
|
|
if (value === 'notification-system') {
|
|
return gettext('Use global settings');
|
|
} else {
|
|
return gettext('Use sendmail to send an email (legacy)');
|
|
}
|
|
},
|
|
editor: {
|
|
xtype: 'pbsNotifyOptionEdit',
|
|
},
|
|
},
|
|
'verify-new': {
|
|
required: true,
|
|
header: gettext('Verify New Snapshots'),
|
|
defaultValue: false,
|
|
renderer: Proxmox.Utils.format_boolean,
|
|
editor: {
|
|
xtype: 'proxmoxWindowEdit',
|
|
title: gettext('Verify New'),
|
|
width: 350,
|
|
items: {
|
|
xtype: 'proxmoxcheckbox',
|
|
name: 'verify-new',
|
|
boxLabel: gettext('Verify new backups immediately after completion'),
|
|
defaultValue: false,
|
|
deleteDefaultValue: true,
|
|
deleteEmpty: true,
|
|
},
|
|
},
|
|
},
|
|
'maintenance-mode': {
|
|
required: true,
|
|
header: gettext('Maintenance mode'),
|
|
renderer: function (v) {
|
|
return PBS.Utils.renderMaintenance(v, this.maintenanceActiveTasks);
|
|
},
|
|
editor: {
|
|
xtype: 'pbsMaintenanceOptionEdit',
|
|
},
|
|
},
|
|
tuning: {
|
|
required: true,
|
|
header: gettext('Tuning Options'),
|
|
renderer: (v) => PBS.Utils.render_tuning_options(PBS.Utils.parsePropertyString(v)),
|
|
editor: {
|
|
xtype: 'proxmoxWindowEdit',
|
|
title: gettext('Tuning Options'),
|
|
onlineHelp: 'datastore_tuning_options',
|
|
width: 500,
|
|
items: {
|
|
xtype: 'inputpanel',
|
|
onGetValues: function (values) {
|
|
if (!Ext.isArray(values.delete ?? [])) {
|
|
values.delete = [values.delete];
|
|
}
|
|
for (const k of values.delete ?? []) {
|
|
delete values[k];
|
|
}
|
|
delete values.delete;
|
|
let tuning = PBS.Utils.printPropertyString(values);
|
|
if (!tuning) {
|
|
return { delete: 'tuning' };
|
|
}
|
|
return { tuning };
|
|
},
|
|
onSetValues: (values) => PBS.Utils.parsePropertyString(values?.tuning),
|
|
items: [
|
|
{
|
|
xtype: 'proxmoxKVComboBox',
|
|
name: 'chunk-order',
|
|
fieldLabel: gettext('Chunk Iteration Order'),
|
|
labelWidth: 200,
|
|
comboItems: Object.entries(PBS.Utils.tuningOptions['chunk-order']),
|
|
deleteEmpty: true,
|
|
value: '__default__',
|
|
},
|
|
{
|
|
xtype: 'proxmoxKVComboBox',
|
|
name: 'sync-level',
|
|
fieldLabel: gettext('Data Sync Level'),
|
|
labelWidth: 200,
|
|
comboItems: Object.entries(PBS.Utils.tuningOptions['sync-level']),
|
|
deleteEmpty: true,
|
|
value: '__default__',
|
|
},
|
|
{
|
|
xtype: 'proxmoxcheckbox',
|
|
name: 'gc-atime-safety-check',
|
|
fieldLabel: gettext('GC Access-Time Support Check'),
|
|
labelWidth: 200,
|
|
autoEl: {
|
|
tag: 'div',
|
|
'data-qtip': gettext(
|
|
'Ensure underlying storage honors access time updates',
|
|
),
|
|
},
|
|
value: 1,
|
|
uncheckedValue: 0,
|
|
defaultValue: 1,
|
|
deleteDefaultValue: true,
|
|
},
|
|
{
|
|
xtype: 'proxmoxintegerfield',
|
|
name: 'gc-atime-cutoff',
|
|
fieldLabel: gettext('GC Access-Time Cutoff (minutes)'),
|
|
labelWidth: 200,
|
|
emptyText: gettext('1445 (24 hours 5 minutes)'),
|
|
deleteEmpty: true,
|
|
},
|
|
{
|
|
xtype: 'proxmoxintegerfield',
|
|
name: 'gc-cache-capacity',
|
|
fieldLabel: gettext('GC Cache Capacity (# chunks)'),
|
|
labelWidth: 200,
|
|
emptyText: gettext('1048576 (0 disables cache)'),
|
|
minValue: 0,
|
|
maxValue: 8 * 1024 * 1024,
|
|
deleteEmpty: true,
|
|
step: 1024,
|
|
},
|
|
],
|
|
},
|
|
},
|
|
},
|
|
},
|
|
});
|