proxmox-backup/www/datastore/OptionView.js
Thomas Lamprecht 5e778d983a ui: datastore tuning options: increase width and rework labels
This was getting cramped, and while it might be actually even nicer to
got to more verbose style like we use for advanced settings of backup
jobs in Proxmox VE, with actual sentences describing the options basic
effects and rationale.

But this is way quicker to do and adds already a bit more rationale,
and we can always do more later on when there's less release time
pressure.

Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
2025-04-05 17:40:10 +02:00

315 lines
7.7 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: 'legacy-sendmail',
header: gettext('Notification mode'),
renderer: function(value) {
if (value === 'notification-system') {
return gettext('Notification system');
} else {
return gettext('Email (legacy)');
}
},
editor: {
xtype: 'pbsNotifyOptionEdit',
},
},
"notify": {
required: true,
header: gettext('Notify'),
renderer: (value) => {
let notify = PBS.Utils.parsePropertyString(value);
let res = [];
for (const k of ['Verify', 'Sync', 'GC', 'Prune']) {
let fallback = k === 'Prune' ? 'Error' : 'Always';
let v = Ext.String.capitalize(notify[k.toLowerCase()]) || fallback;
res.push(`${k}=${v}`);
}
return res.join(', ');
},
editor: {
xtype: 'pbsNotifyOptionEdit',
},
},
"notify-user": {
required: true,
defaultValue: 'root@pam',
header: gettext('Notify User'),
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 chache)'),
minValue: 0,
maxValue: 8 * 1024 * 1024,
deleteEmpty: true,
step: 1024,
},
],
},
},
},
},
});