public inbox for pbs-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Lukas Wagner <l.wagner@proxmox.com>
To: pbs-devel@lists.proxmox.com
Subject: [pbs-devel] [PATCH proxmox-backup 2/2] web ui: notification: remove matcher overiddes
Date: Mon, 11 Nov 2024 13:56:19 +0100	[thread overview]
Message-ID: <20241111125619.193930-2-l.wagner@proxmox.com> (raw)
In-Reply-To: <20241111125619.193930-1-l.wagner@proxmox.com>

These were put in place so that initial release of the new
notification system for Proxmox Backup Server can already include
improved notification matchers, which at that time have not been yet
merged into proxmox-widget-toolkit.

In the meanwhile, the changes have been merged an released in
proxmox-widget-toolkit 4.2.4, hence we can remove the override.

Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
---
 www/Makefile                              |    1 -
 www/window/NotificationMatcherOverride.js | 1105 ---------------------
 2 files changed, 1106 deletions(-)
 delete mode 100644 www/window/NotificationMatcherOverride.js

diff --git a/www/Makefile b/www/Makefile
index 609a0ba6..f86cbb4d 100644
--- a/www/Makefile
+++ b/www/Makefile
@@ -77,7 +77,6 @@ JSSRC=							\
 	window/NamespaceEdit.js				\
 	window/MaintenanceOptions.js			\
 	window/NotesEdit.js				\
-	window/NotificationMatcherOverride.js		\
 	window/RemoteEdit.js				\
 	window/TrafficControlEdit.js			\
 	window/NotifyOptions.js				\
diff --git a/www/window/NotificationMatcherOverride.js b/www/window/NotificationMatcherOverride.js
deleted file mode 100644
index bc7b7c1d..00000000
--- a/www/window/NotificationMatcherOverride.js
+++ /dev/null
@@ -1,1105 +0,0 @@
-// Override some components from widget toolkit.
-// This was done so that we can already use the improved UI for editing
-// match rules without waiting for the needed API calls in PVE to be merged
-//
-// This can and *should* be removed once these changes have landed in
-// widget toolkit:
-// https://lists.proxmox.com/pipermail/pve-devel/2024-April/063539.html
-
-
-Ext.define('pbs-notification-fields', {
-    extend: 'Ext.data.Model',
-    fields: ['name', 'description'],
-    idProperty: 'name',
-});
-
-Ext.define('pbs-notification-field-values', {
-    extend: 'Ext.data.Model',
-    fields: ['value', 'comment', 'field'],
-    idProperty: 'value',
-});
-
-Ext.define('PBS.panel.NotificationRulesEditPanel', {
-    override: 'Proxmox.panel.NotificationRulesEditPanel',
-    extend: 'Proxmox.panel.InputPanel',
-    xtype: 'pmxNotificationMatchRulesEditPanel',
-    mixins: ['Proxmox.Mixin.CBind'],
-
-    controller: {
-	xclass: 'Ext.app.ViewController',
-
-	// we want to also set the empty value, but 'bind' does not do that so
-	// we have to set it then (and only then) to get the correct value in
-	// the tree
-	control: {
-	    'field': {
-		change: function(cmp) {
-		    let me = this;
-		    let vm = me.getViewModel();
-		    if (cmp.field) {
-			let record = vm.get('selectedRecord');
-			if (!record) {
-			    return;
-			}
-			let data = Ext.apply({}, record.get('data'));
-			let value = cmp.getValue();
-			// only update if the value is empty (or empty array)
-			if (!value || !value.length) {
-			    data[cmp.field] = value;
-			    record.set({ data });
-			}
-		    }
-		},
-	    },
-	},
-    },
-
-    viewModel: {
-	data: {
-	    selectedRecord: null,
-	    matchFieldType: 'exact',
-	    matchFieldField: '',
-	    matchFieldValue: '',
-	    rootMode: 'all',
-	},
-
-	formulas: {
-	    nodeType: {
-		get: function(get) {
-		    let record = get('selectedRecord');
-		    return record?.get('type');
-		},
-		set: function(value) {
-		    let me = this;
-		    let record = me.get('selectedRecord');
-
-		    let data;
-
-		    switch (value) {
-			case 'match-severity':
-			    data = {
-				value: ['info', 'notice', 'warning', 'error', 'unknown'],
-			    };
-			    break;
-			case 'match-field':
-			    data = {
-				type: 'exact',
-				field: '',
-				value: '',
-			    };
-			    break;
-			case 'match-calendar':
-			    data = {
-				value: '',
-			    };
-			    break;
-		    }
-
-		    let node = {
-			type: value,
-			data,
-		    };
-		    record.set(node);
-		},
-	    },
-	    showMatchingMode: function(get) {
-		let record = get('selectedRecord');
-		if (!record) {
-		    return false;
-		}
-		return record.isRoot();
-	    },
-	    showMatcherType: function(get) {
-		let record = get('selectedRecord');
-		if (!record) {
-		    return false;
-		}
-		return !record.isRoot();
-	    },
-
-	    rootMode: {
-		bind: {
-		    bindTo: '{selectedRecord}',
-		    deep: true,
-		},
-		set: function(value) {
-		    let me = this;
-		    let record = me.get('selectedRecord');
-		    let currentData = record.get('data');
-		    let invert = false;
-		    if (value.startsWith('not')) {
-			value = value.substring(3);
-			invert = true;
-		    }
-		    record.set({
-			data: {
-			    ...currentData,
-			    value,
-			    invert,
-			},
-		    });
-		},
-		get: function(record) {
-		    let prefix = record?.get('data').invert ? 'not' : '';
-		    return prefix + record?.get('data')?.value;
-		},
-	    },
-	},
-    },
-
-    column1: [
-	{
-	    xtype: 'pbsNotificationMatchRuleTree',
-	    cbind: {
-		isCreate: '{isCreate}',
-	    },
-	},
-    ],
-    column2: [
-	{
-	    xtype: 'pbsNotificationMatchRuleSettings',
-	    cbind: {
-		baseUrl: '{baseUrl}',
-	    },
-	},
-
-    ],
-
-    onGetValues: function(values) {
-	let me = this;
-
-	let deleteArrayIfEmpty = (field) => {
-	    if (Ext.isArray(values[field])) {
-		if (values[field].length === 0) {
-		    delete values[field];
-		    if (!me.isCreate) {
-			Proxmox.Utils.assemble_field_data(values, { 'delete': field });
-		    }
-		}
-	    }
-	};
-	deleteArrayIfEmpty('match-field');
-	deleteArrayIfEmpty('match-severity');
-	deleteArrayIfEmpty('match-calendar');
-
-	return values;
-    },
-});
-
-Ext.define('PBS.panel.NotificationMatchRuleTree', {
-    extend: 'Ext.panel.Panel',
-    xtype: 'pbsNotificationMatchRuleTree',
-    mixins: ['Proxmox.Mixin.CBind'],
-    border: false,
-
-    getNodeTextAndIcon: function(type, data) {
-	let text;
-	let iconCls;
-
-	switch (type) {
-	    case 'match-severity': {
-		let v = data.value;
-		if (Ext.isArray(data.value)) {
-		    v = data.value.join(', ');
-		}
-		text = Ext.String.format(gettext("Match severity: {0}"), v);
-		iconCls = 'fa fa-exclamation';
-		if (!v) {
-		    iconCls += ' internal-error';
-		}
-	    } break;
-	    case 'match-field': {
-		let field = data.field;
-		let value = data.value;
-		text = Ext.String.format(gettext("Match field: {0}={1}"), field, value);
-		iconCls = 'fa fa-square-o';
-		if (!field || !value || (Ext.isArray(value) && !value.length)) {
-		    iconCls += ' internal-error';
-		}
-	    } break;
-	    case 'match-calendar': {
-		let v = data.value;
-		text = Ext.String.format(gettext("Match calendar: {0}"), v);
-		iconCls = 'fa fa-calendar-o';
-		if (!v || !v.length) {
-		    iconCls += ' internal-error';
-		}
-	    } break;
-	    case 'mode':
-		if (data.value === 'all') {
-		    text = gettext("All");
-		} else if (data.value === 'any') {
-		    text = gettext("Any");
-		}
-		if (data.invert) {
-		    text = `!${text}`;
-		}
-		iconCls = 'fa fa-filter';
-
-		break;
-	}
-
-	return [text, iconCls];
-    },
-
-    initComponent: function() {
-	let me = this;
-
-	let treeStore = Ext.create('Ext.data.TreeStore', {
-	    root: {
-		expanded: true,
-		expandable: false,
-		text: '',
-		type: 'mode',
-		data: {
-		    value: 'all',
-		    invert: false,
-		},
-		children: [],
-		iconCls: 'fa fa-filter',
-	    },
-	});
-
-	let realMatchFields = Ext.create({
-	    xtype: 'hiddenfield',
-	    setValue: function(value) {
-		this.value = value;
-		this.checkChange();
-	    },
-	    getValue: function() {
-		return this.value;
-	    },
-	    getErrors: function() {
-		for (const matcher of this.value ?? []) {
-		    let matches = matcher.match(/^([^:]+):([^=]+)=(.+)$/);
-		    if (!matches) {
-			return [""]; // fake error for validation
-		    }
-		}
-		return [];
-	    },
-	    getSubmitValue: function() {
-		let value = this.value;
-		if (!value) {
-		    value = [];
-		}
-		return value;
-	    },
-	    name: 'match-field',
-	});
-
-	let realMatchSeverity = Ext.create({
-	    xtype: 'hiddenfield',
-	    setValue: function(value) {
-		this.value = value;
-		this.checkChange();
-	    },
-	    getValue: function() {
-		return this.value;
-	    },
-	    getErrors: function() {
-		for (const severities of this.value ?? []) {
-		    if (!severities) {
-			return [""]; // fake error for validation
-		    }
-		}
-		return [];
-	    },
-	    getSubmitValue: function() {
-		let value = this.value;
-		if (!value) {
-		    value = [];
-		}
-		return value;
-	    },
-	    name: 'match-severity',
-	});
-
-	let realMode = Ext.create({
-	    xtype: 'hiddenfield',
-	    name: 'mode',
-	    setValue: function(value) {
-		this.value = value;
-		this.checkChange();
-	    },
-	    getValue: function() {
-		return this.value;
-	    },
-	    getSubmitValue: function() {
-		let value = this.value;
-		return value;
-	    },
-	});
-
-	let realMatchCalendar = Ext.create({
-	    xtype: 'hiddenfield',
-	    name: 'match-calendar',
-
-	    setValue: function(value) {
-		this.value = value;
-		this.checkChange();
-	    },
-	    getValue: function() {
-		return this.value;
-	    },
-	    getErrors: function() {
-		for (const timespan of this.value ?? []) {
-		    if (!timespan) {
-			return [""]; // fake error for validation
-		    }
-		}
-		return [];
-	    },
-	    getSubmitValue: function() {
-		let value = this.value;
-		return value;
-	    },
-	});
-
-	let realInvertMatch = Ext.create({
-	    xtype: 'proxmoxcheckbox',
-	    name: 'invert-match',
-	    hidden: true,
-	    deleteEmpty: !me.isCreate,
-	});
-
-	let storeChanged = function(store) {
-	    store.suspendEvent('datachanged');
-
-	    let matchFieldStmts = [];
-	    let matchSeverityStmts = [];
-	    let matchCalendarStmts = [];
-	    let modeStmt = 'all';
-	    let invertMatchStmt = false;
-
-	    store.each(function(model) {
-		let type = model.get('type');
-		let data = model.get('data');
-
-		switch (type) {
-		    case 'match-field':
-			matchFieldStmts.push(`${data.type}:${data.field ?? ''}=${data.value ?? ''}`);
-			break;
-		    case 'match-severity':
-			if (Ext.isArray(data.value)) {
-			    matchSeverityStmts.push(data.value.join(','));
-			} else {
-			    matchSeverityStmts.push(data.value);
-			}
-			break;
-		    case 'match-calendar':
-			matchCalendarStmts.push(data.value);
-			break;
-		    case 'mode':
-			modeStmt = data.value;
-			invertMatchStmt = data.invert;
-			break;
-		}
-
-		let [text, iconCls] = me.getNodeTextAndIcon(type, data);
-		model.set({
-		    text,
-		    iconCls,
-		});
-	    });
-
-	    realMatchFields.suspendEvent('change');
-	    realMatchFields.setValue(matchFieldStmts);
-	    realMatchFields.resumeEvent('change');
-
-	    realMatchCalendar.suspendEvent('change');
-	    realMatchCalendar.setValue(matchCalendarStmts);
-	    realMatchCalendar.resumeEvent('change');
-
-	    realMode.suspendEvent('change');
-	    realMode.setValue(modeStmt);
-	    realMode.resumeEvent('change');
-
-	    realInvertMatch.suspendEvent('change');
-	    realInvertMatch.setValue(invertMatchStmt);
-	    realInvertMatch.resumeEvent('change');
-
-	    realMatchSeverity.suspendEvent('change');
-	    realMatchSeverity.setValue(matchSeverityStmts);
-	    realMatchSeverity.resumeEvent('change');
-
-	    store.resumeEvent('datachanged');
-	};
-
-	realMatchFields.addListener('change', function(field, value) {
-	    let parseMatchField = function(filter) {
-		let [, type, matchedField, matchedValue] =
-		    filter.match(/^(?:(regex|exact):)?([A-Za-z0-9_][A-Za-z0-9._-]*)=(.+)$/);
-		if (type === undefined) {
-		    type = "exact";
-		}
-
-		if (type === 'exact') {
-		    matchedValue = matchedValue.split(',');
-		}
-
-		return {
-		    type: 'match-field',
-		    data: {
-			type,
-			field: matchedField,
-			value: matchedValue,
-		    },
-		    leaf: true,
-		};
-	    };
-
-	    for (let node of treeStore.queryBy(
-		record => record.get('type') === 'match-field',
-	    ).getRange()) {
-		node.remove(true);
-	    }
-
-	    if (!value) {
-		return;
-	    }
-	    let records = value.map(parseMatchField);
-
-	    let rootNode = treeStore.getRootNode();
-
-	    for (let record of records) {
-		rootNode.appendChild(record);
-	    }
-	});
-
-	realMatchSeverity.addListener('change', function(field, value) {
-	    let parseSeverity = function(severities) {
-		return {
-		    type: 'match-severity',
-		    data: {
-			value: severities.split(','),
-		    },
-		    leaf: true,
-		};
-	    };
-
-	    for (let node of treeStore.queryBy(
-		record => record.get('type') === 'match-severity').getRange()) {
-		node.remove(true);
-	    }
-
-	    let records = value.map(parseSeverity);
-	    let rootNode = treeStore.getRootNode();
-
-	    for (let record of records) {
-		rootNode.appendChild(record);
-	    }
-	});
-
-	realMatchCalendar.addListener('change', function(field, value) {
-	    let parseCalendar = function(timespan) {
-		return {
-		    type: 'match-calendar',
-		    data: {
-			value: timespan,
-		    },
-		    leaf: true,
-		};
-	    };
-
-	    for (let node of treeStore.queryBy(
-		record => record.get('type') === 'match-calendar').getRange()) {
-		node.remove(true);
-	    }
-
-	    let records = value.map(parseCalendar);
-	    let rootNode = treeStore.getRootNode();
-
-	    for (let record of records) {
-		rootNode.appendChild(record);
-	    }
-	});
-
-	realMode.addListener('change', function(field, value) {
-	    let data = treeStore.getRootNode().get('data');
-	    treeStore.getRootNode().set('data', {
-		...data,
-		value,
-	    });
-	});
-
-	realInvertMatch.addListener('change', function(field, value) {
-	    let data = treeStore.getRootNode().get('data');
-	    treeStore.getRootNode().set('data', {
-		...data,
-		invert: value,
-	    });
-	});
-
-	treeStore.addListener('datachanged', storeChanged);
-
-	let treePanel = Ext.create({
-	    xtype: 'treepanel',
-	    store: treeStore,
-	    minHeight: 300,
-	    maxHeight: 300,
-	    scrollable: true,
-
-	    bind: {
-		selection: '{selectedRecord}',
-	    },
-	});
-
-	let addNode = function() {
-	    let node = {
-		type: 'match-field',
-		data: {
-		    type: 'exact',
-		    field: '',
-		    value: '',
-		},
-		leaf: true,
-	    };
-	    treeStore.getRootNode().appendChild(node);
-	    treePanel.setSelection(treeStore.getRootNode().lastChild);
-	};
-
-	let deleteNode = function() {
-	    let selection = treePanel.getSelection();
-	    for (let selected of selection) {
-		if (!selected.isRoot()) {
-		    selected.remove(true);
-		}
-	    }
-	};
-
-	Ext.apply(me, {
-	    items: [
-		realMatchFields,
-		realMode,
-		realMatchSeverity,
-		realInvertMatch,
-		realMatchCalendar,
-		treePanel,
-		{
-		    xtype: 'button',
-		    margin: '5 5 5 0',
-		    text: gettext('Add'),
-		    iconCls: 'fa fa-plus-circle',
-		    handler: addNode,
-		},
-		{
-		    xtype: 'button',
-		    margin: '5 5 5 0',
-		    text: gettext('Remove'),
-		    iconCls: 'fa fa-minus-circle',
-		    handler: deleteNode,
-		},
-	    ],
-	});
-	me.callParent();
-    },
-});
-
-Ext.define('PBS.panel.NotificationMatchRuleSettings', {
-    extend: 'Ext.panel.Panel',
-    xtype: 'pbsNotificationMatchRuleSettings',
-    mixins: ['Proxmox.Mixin.CBind'],
-    border: false,
-    layout: 'anchor',
-
-    items: [
-	{
-	    xtype: 'proxmoxKVComboBox',
-	    name: 'mode',
-	    fieldLabel: gettext('Match if'),
-	    allowBlank: false,
-	    isFormField: false,
-
-	    matchFieldWidth: false,
-
-	    comboItems: [
-		['all', gettext('All rules match')],
-		['any', gettext('Any rule matches')],
-		['notall', gettext('At least one rule does not match')],
-		['notany', gettext('No rule matches')],
-	    ],
-	    // Hide initially to avoid glitches when opening the window
-	    hidden: true,
-	    bind: {
-		hidden: '{!showMatchingMode}',
-		disabled: '{!showMatchingMode}',
-		value: '{rootMode}',
-	    },
-	},
-	{
-	    xtype: 'proxmoxKVComboBox',
-	    fieldLabel: gettext('Node type'),
-	    isFormField: false,
-	    allowBlank: false,
-	    // Hide initially to avoid glitches when opening the window
-	    hidden: true,
-	    bind: {
-		value: '{nodeType}',
-		hidden: '{!showMatcherType}',
-		disabled: '{!showMatcherType}',
-	    },
-
-	    comboItems: [
-		['match-field', gettext('Match Field')],
-		['match-severity', gettext('Match Severity')],
-		['match-calendar', gettext('Match Calendar')],
-	    ],
-	},
-	{
-	    xtype: 'pbsNotificationMatchFieldSettings',
-	    cbind: {
-		baseUrl: '{baseUrl}',
-	    },
-	},
-	{
-	    xtype: 'pbsNotificationMatchSeveritySettings',
-	},
-	{
-	    xtype: 'pbsNotificationMatchCalendarSettings',
-	},
-    ],
-});
-
-Ext.define('PBS.panel.MatchCalendarSettings', {
-    extend: 'Ext.panel.Panel',
-    xtype: 'pbsNotificationMatchCalendarSettings',
-    border: false,
-    layout: 'anchor',
-    // Hide initially to avoid glitches when opening the window
-    hidden: true,
-    bind: {
-	hidden: '{!typeIsMatchCalendar}',
-    },
-    viewModel: {
-	// parent is set in `initComponents`
-	formulas: {
-	    typeIsMatchCalendar: {
-		bind: {
-		    bindTo: '{selectedRecord}',
-		    deep: true,
-		},
-		get: function(record) {
-		    return record?.get('type') === 'match-calendar';
-		},
-	    },
-
-	    matchCalendarValue: {
-		bind: {
-		    bindTo: '{selectedRecord}',
-		    deep: true,
-		},
-		set: function(value) {
-		    let me = this;
-		    let record = me.get('selectedRecord');
-		    let currentData = record.get('data');
-		    record.set({
-			data: {
-			    ...currentData,
-			    value: value,
-			},
-		    });
-		},
-		get: function(record) {
-		    return record?.get('data')?.value;
-		},
-	    },
-	},
-    },
-    items: [
-	{
-	    xtype: 'proxmoxKVComboBox',
-	    fieldLabel: gettext('Timespan to match'),
-	    isFormField: false,
-	    allowBlank: false,
-	    editable: true,
-	    displayField: 'key',
-	    field: 'value',
-	    bind: {
-		value: '{matchCalendarValue}',
-		disabled: '{!typeIsMatchCalender}',
-	    },
-
-	    comboItems: [
-		['mon 8-12', ''],
-		['tue..fri,sun 0:00-23:59', ''],
-	    ],
-	},
-    ],
-
-    initComponent: function() {
-	let me = this;
-	Ext.apply(me.viewModel, {
-	    parent: me.up('pmxNotificationMatchRulesEditPanel').getViewModel(),
-	});
-	me.callParent();
-    },
-});
-
-Ext.define('PBS.panel.MatchSeveritySettings', {
-    extend: 'Ext.panel.Panel',
-    xtype: 'pbsNotificationMatchSeveritySettings',
-    border: false,
-    layout: 'anchor',
-    // Hide initially to avoid glitches when opening the window
-    hidden: true,
-    bind: {
-	hidden: '{!typeIsMatchSeverity}',
-    },
-    viewModel: {
-	// parent is set in `initComponents`
-	formulas: {
-	    typeIsMatchSeverity: {
-		bind: {
-		    bindTo: '{selectedRecord}',
-		    deep: true,
-		},
-		get: function(record) {
-		    return record?.get('type') === 'match-severity';
-		},
-	    },
-	    matchSeverityValue: {
-		bind: {
-		    bindTo: '{selectedRecord}',
-		    deep: true,
-		},
-		set: function(value) {
-		    let record = this.get('selectedRecord');
-		    let currentData = record.get('data');
-		    record.set({
-			data: {
-			    ...currentData,
-			    value: value,
-			},
-		    });
-		},
-		get: function(record) {
-		    return record?.get('data')?.value;
-		},
-	    },
-	},
-    },
-    items: [
-	{
-	    xtype: 'proxmoxKVComboBox',
-	    fieldLabel: gettext('Severities to match'),
-	    isFormField: false,
-	    allowBlank: true,
-	    multiSelect: true,
-	    field: 'value',
-	    // Hide initially to avoid glitches when opening the window
-	    hidden: true,
-	    bind: {
-		value: '{matchSeverityValue}',
-		hidden: '{!typeIsMatchSeverity}',
-		disabled: '{!typeIsMatchSeverity}',
-	    },
-
-	    comboItems: [
-		['info', gettext('Info')],
-		['notice', gettext('Notice')],
-		['warning', gettext('Warning')],
-		['error', gettext('Error')],
-		['unknown', gettext('Unknown')],
-	    ],
-	},
-    ],
-
-    initComponent: function() {
-	let me = this;
-	Ext.apply(me.viewModel, {
-	    parent: me.up('pmxNotificationMatchRulesEditPanel').getViewModel(),
-	});
-	me.callParent();
-    },
-});
-
-Ext.define('PBS.panel.MatchFieldSettings', {
-    extend: 'Ext.panel.Panel',
-    xtype: 'pbsNotificationMatchFieldSettings',
-    border: false,
-    layout: 'anchor',
-    // Hide initially to avoid glitches when opening the window
-    hidden: true,
-    bind: {
-	hidden: '{!typeIsMatchField}',
-    },
-    controller: {
-	xclass: 'Ext.app.ViewController',
-
-	control: {
-	    'field[reference=fieldSelector]': {
-		change: function(field) {
-		    let view = this.getView();
-		    let valueField = view.down('field[reference=valueSelector]');
-		    let store = valueField.getStore();
-		    let val = field.getValue();
-
-		    if (val) {
-			store.setFilters([
-			    {
-				property: 'field',
-				value: val,
-			    },
-			]);
-		    }
-		},
-	    },
-	},
-    },
-    viewModel: {
-	// parent is set in `initComponents`
-	formulas: {
-	    typeIsMatchField: {
-		bind: {
-		    bindTo: '{selectedRecord}',
-		    deep: true,
-		},
-		get: function(record) {
-		    return record?.get('type') === 'match-field';
-		},
-	    },
-	    isRegex: function(get) {
-		return get('matchFieldType') === 'regex';
-	    },
-	    matchFieldType: {
-		bind: {
-		    bindTo: '{selectedRecord}',
-		    deep: true,
-		},
-		set: function(value) {
-		    let record = this.get('selectedRecord');
-		    let currentData = record.get('data');
-
-		    let newValue = [];
-
-		    // Build equivalent regular expression if switching
-		    // to 'regex' mode
-		    if (value === 'regex') {
-			let regexVal = "^";
-			if (currentData.value) {
-			    regexVal += `(${currentData.value.join('|')})`;
-			}
-			regexVal += "$";
-			newValue.push(regexVal);
-		    }
-
-		    record.set({
-			data: {
-			    ...currentData,
-			    type: value,
-			    value: newValue,
-			},
-		    });
-		},
-		get: function(record) {
-		    return record?.get('data')?.type;
-		},
-	    },
-	    matchFieldField: {
-		bind: {
-		    bindTo: '{selectedRecord}',
-		    deep: true,
-		},
-		set: function(value) {
-		    let record = this.get('selectedRecord');
-		    let currentData = record.get('data');
-
-		    record.set({
-			data: {
-			    ...currentData,
-			    field: value,
-			    // Reset value if field changes
-			    value: [],
-			},
-		    });
-		},
-		get: function(record) {
-		    return record?.get('data')?.field;
-		},
-	    },
-	    matchFieldValue: {
-		bind: {
-		    bindTo: '{selectedRecord}',
-		    deep: true,
-		},
-		set: function(value) {
-		    let record = this.get('selectedRecord');
-		    let currentData = record.get('data');
-		    record.set({
-			data: {
-			    ...currentData,
-			    value: value,
-			},
-		    });
-		},
-		get: function(record) {
-		    return record?.get('data')?.value;
-		},
-	    },
-	},
-    },
-
-    initComponent: function() {
-	let me = this;
-
-	let store = Ext.create('Ext.data.Store', {
-	    model: 'pbs-notification-fields',
-	    autoLoad: true,
-	    proxy: {
-		type: 'proxmox',
-		url: `/api2/json/${me.baseUrl}/matcher-fields`,
-	    },
-	    listeners: {
-		'load': function() {
-		    this.each(function(record) {
-			record.set({
-			    description:
-				Proxmox.Utils.formatNotificationFieldName(
-				    record.get('name'),
-				),
-			});
-		    });
-
-		    // Commit changes so that the description field is not marked
-		    // as dirty
-		    this.commitChanges();
-		},
-	    },
-	});
-
-	let valueStore = Ext.create('Ext.data.Store', {
-	    model: 'pbs-notification-field-values',
-	    autoLoad: true,
-	    proxy: {
-		type: 'proxmox',
-
-		url: `/api2/json/${me.baseUrl}/matcher-field-values`,
-	    },
-	    listeners: {
-		'load': function() {
-		    this.each(function(record) {
-			if (record.get('field') === 'type') {
-			    record.set({
-				comment:
-				    Proxmox.Utils.formatNotificationFieldValue(
-					record.get('value'),
-				    ),
-			    });
-			}
-		    }, this, true);
-
-		    // Commit changes so that the description field is not marked
-		    // as dirty
-		    this.commitChanges();
-		},
-	    },
-	});
-
-	Ext.apply(me.viewModel, {
-	    parent: me.up('pmxNotificationMatchRulesEditPanel').getViewModel(),
-	});
-	Ext.apply(me, {
-	    items: [
-		{
-		    fieldLabel: gettext('Match Type'),
-		    xtype: 'proxmoxKVComboBox',
-		    reference: 'type',
-		    isFormField: false,
-		    allowBlank: false,
-		    submitValue: false,
-		    field: 'type',
-
-		    bind: {
-			value: '{matchFieldType}',
-		    },
-
-		    comboItems: [
-			['exact', gettext('Exact')],
-			['regex', gettext('Regex')],
-		    ],
-		},
-		{
-		    fieldLabel: gettext('Field'),
-		    reference: 'fieldSelector',
-		    xtype: 'proxmoxComboGrid',
-		    isFormField: false,
-		    submitValue: false,
-		    allowBlank: false,
-		    editable: false,
-		    store: store,
-		    queryMode: 'local',
-		    valueField: 'name',
-		    displayField: 'description',
-		    field: 'field',
-		    bind: {
-			value: '{matchFieldField}',
-		    },
-		    listConfig: {
-			columns: [
-			    {
-				header: gettext('Description'),
-				dataIndex: 'description',
-				flex: 2,
-			    },
-			    {
-				header: gettext('Field Name'),
-				dataIndex: 'name',
-				flex: 1,
-			    },
-			],
-		    },
-		},
-		{
-		    fieldLabel: gettext('Value'),
-		    reference: 'valueSelector',
-		    xtype: 'proxmoxComboGrid',
-		    autoSelect: false,
-		    editable: false,
-		    isFormField: false,
-		    submitValue: false,
-		    allowBlank: false,
-		    showClearTrigger: true,
-		    field: 'value',
-		    store: valueStore,
-		    valueField: 'value',
-		    displayField: 'value',
-		    notFoundIsValid: false,
-		    multiSelect: true,
-		    bind: {
-			value: '{matchFieldValue}',
-			hidden: '{isRegex}',
-		    },
-		    listConfig: {
-			columns: [
-			    {
-				header: gettext('Value'),
-				dataIndex: 'value',
-				flex: 1,
-			    },
-			    {
-				header: gettext('Comment'),
-				dataIndex: 'comment',
-				flex: 2,
-			    },
-			],
-		    },
-		},
-		{
-		    fieldLabel: gettext('Regex'),
-		    xtype: 'proxmoxtextfield',
-		    editable: true,
-		    isFormField: false,
-		    submitValue: false,
-		    allowBlank: false,
-		    field: 'value',
-		    bind: {
-			value: '{matchFieldValue}',
-			hidden: '{!isRegex}',
-		    },
-		},
-	    ],
-	});
-	me.callParent();
-    },
-});
-- 
2.39.5



_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel


      reply	other threads:[~2024-11-11 12:57 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-11-11 12:56 [pbs-devel] [PATCH proxmox-backup 1/2] d/control: bump proxmox-widget-toolkit dependency Lukas Wagner
2024-11-11 12:56 ` Lukas Wagner [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20241111125619.193930-2-l.wagner@proxmox.com \
    --to=l.wagner@proxmox.com \
    --cc=pbs-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal