[pve-devel] [PATCH v3 proxmox-widget-toolkit 63/66] notification: add gui for notification groups

Dominik Csapak d.csapak at proxmox.com
Wed Jul 19 15:32:50 CEST 2023


comments inline

On 7/17/23 17:00, Lukas Wagner wrote:
> Signed-off-by: Lukas Wagner <l.wagner at proxmox.com>
> ---
>   src/Makefile                            |   1 +
>   src/Schema.js                           |   5 +
>   src/panel/NotificationGroupEditPanel.js | 177 ++++++++++++++++++++++++
>   src/window/EndpointEditBase.js          |   6 +-
>   4 files changed, 188 insertions(+), 1 deletion(-)
>   create mode 100644 src/panel/NotificationGroupEditPanel.js
> 
> diff --git a/src/Makefile b/src/Makefile
> index 2e620e3..829081d 100644
> --- a/src/Makefile
> +++ b/src/Makefile
> @@ -61,6 +61,7 @@ JSSRC=					\
>   	panel/LogView.js		\
>   	panel/NodeInfoRepoStatus.js	\
>   	panel/NotificationConfigView.js	\
> +	panel/NotificationGroupEditPanel.js	\
>   	panel/JournalView.js		\
>   	panel/PermissionView.js		\
>   	panel/PruneKeepPanel.js		\
> diff --git a/src/Schema.js b/src/Schema.js
> index 37ecd88..a7ffdf8 100644
> --- a/src/Schema.js
> +++ b/src/Schema.js
> @@ -48,6 +48,11 @@ Ext.define('Proxmox.Schema', { // a singleton
>   	    ipanel: 'pmxGotifyEditPanel',
>   	    iconCls: 'fa-bell-o',
>   	},
> +	group: {
> +	    name: gettext('Notification Group'),
> +	    ipanel: 'pmxNotificationGroupEditPanel',
> +	    iconCls: 'fa-bell-o',
> +	},
>       },
>   
>       pxarFileTypes: {
> diff --git a/src/panel/NotificationGroupEditPanel.js b/src/panel/NotificationGroupEditPanel.js
> new file mode 100644
> index 0000000..0a7a469
> --- /dev/null
> +++ b/src/panel/NotificationGroupEditPanel.js
> @@ -0,0 +1,177 @@
> +Ext.define('Proxmox.panel.NotificationGroupEditPanel', {
> +    extend: 'Proxmox.panel.InputPanel',
> +    xtype: 'pmxNotificationGroupEditPanel',
> +    mixins: ['Proxmox.Mixin.CBind'],
> +
> +    type: 'group',
> +
> +    columnT: [
> +	{
> +	    xtype: 'pmxDisplayEditField',
> +	    name: 'name',
> +	    cbind: {
> +		value: '{name}',
> +		editable: '{isCreate}',
> +	    },
> +	    fieldLabel: gettext('Group Name'),
> +	    allowBlank: false,
> +	},
> +	{
> +	    xtype: 'pmxNotificationEndpointSelector',
> +	    name: 'endpoint',
> +	    allowBlank: false,
> +	},
> +    ],
> +
> +    column1: [],
> +
> +    column2: [],
> +
> +    columnB: [
> +	{
> +	    xtype: 'proxmoxtextfield',
> +	    name: 'comment',
> +	    fieldLabel: gettext('Comment'),
> +	    cbind: {
> +		deleteEmpty: '{!isCreate}',
> +	    },
> +	},
> +    ],
> +});
> +
> +Ext.define('Proxmox.form.NotificationEndpointSelector', {
> +    extend: 'Ext.grid.Panel',
> +    alias: 'widget.pmxNotificationEndpointSelector',
> +
> +    mixins: {
> +	field: 'Ext.form.field.Field',
> +    },

when implementing the field mixin you have to (quote from the extjs docs)

---8<---
You will also need to make sure that initField is called during the component's initialization.
--->8---

so you normally need a (small) initComponent that calls that
(otherwise you can have some strange effects when using the field)

> +
> +    allowBlank: true,
> +    selectAll: false,
> +    isFormField: true,
> +
> +    store: {
> +	autoLoad: true,
> +	model: 'proxmox-notification-endpoints',
> +	sorters: 'name',
> +	filters: item => item.data.type !== 'group',
> +    },
> +
> +    columns: [
> +	{
> +	    header: gettext('Endpoint Name'),
> +	    dataIndex: 'name',
> +	    flex: 1,
> +	},
> +	{
> +	    header: gettext('Type'),
> +	    dataIndex: 'type',
> +	    flex: 1,
> +	},
> +	{
> +	    header: gettext('Comment'),
> +	    dataIndex: 'comment',
> +	    flex: 3,
> +	},
> +    ],
> +
> +    selModel: {
> +	selType: 'checkboxmodel',
> +	mode: 'SIMPLE',
> +    },
> +
> +    checkChangeEvents: [
> +	'selectionchange',
> +	'change',
> +    ],
> +
> +    listeners: {
> +	selectionchange: function() {
> +	    // to trigger validity and error checks
> +	    this.checkChange();
> +	},
> +    },
> +
> +    getSubmitData: function() {
> +	let me = this;
> +	let res = {};
> +	res[me.name] = me.getValue();
> +	return res;
> +    },
> +
> +    getValue: function() {
> +	let me = this;
> +	if (me.savedValue !== undefined) {
> +	    return me.savedValue;
> +	}
> +	let sm = me.getSelectionModel();
> +	let selection = sm.getSelection();
> +	let values = [];
> +	selection.forEach(function(item) {
> +	    values.push(item.data.name);
> +	});
> +	return values;

could also be:

return (sm.getSelection() ?? []).map(item => item.data.name);

> +    },
> +
> +    setValueSelection: function(value) {
> +	let me = this;
> +
> +	let store = me.getStore();
> +
> +	let notFound = [];
> +	let selection = value.map(item => {
> +	    let found = store.findRecord('name', item, 0, false, true, true);
> +	    if (!found) {
> +		notFound.push(item);
> +	    }
> +	    return found;
> +	}).filter(r => r);
> +
> +	for (const name of notFound) {
> +	    let rec = store.add({
> +		name,
> +		type: '-',
> +		comment: gettext('Included endpoint does not exist!'),
> +	    });
> +	    selection.push(rec[0]);
> +	}
> +
> +	let sm = me.getSelectionModel();
> +	if (selection.length) {
> +	    sm.select(selection);
> +	} else {
> +	    sm.deselectAll();
> +	}
> +	// to correctly trigger invalid class
> +	me.getErrors();
> +    },
> +
> +    setValue: function(value) {
> +	let me = this;
> +
> +	let store = me.getStore();
> +	if (!store.isLoaded()) {
> +	    me.savedValue = value;
> +	    store.on('load', function() {
> +		me.setValueSelection(value);
> +		delete me.savedValue;
> +	    }, { single: true });
> +	} else {
> +	    me.setValueSelection(value);
> +	}
> +	return me.mixins.field.setValue.call(me, value);
> +    },
> +
> +    getErrors: function(value) {
> +	let me = this;
> +	if (!me.isDisabled() && me.allowBlank === false &&
> +	    me.getSelectionModel().getCount() === 0) {
> +	    me.addBodyCls(['x-form-trigger-wrap-default', 'x-form-trigger-wrap-invalid']);
> +	    return [gettext('No endpoint selected')];
> +	}
> +
> +	me.removeBodyCls(['x-form-trigger-wrap-default', 'x-form-trigger-wrap-invalid']);
> +	return [];
> +    },
> +});
> diff --git a/src/window/EndpointEditBase.js b/src/window/EndpointEditBase.js
> index 81e5951..bcf6879 100644
> --- a/src/window/EndpointEditBase.js
> +++ b/src/window/EndpointEditBase.js
> @@ -16,7 +16,11 @@ Ext.define('Proxmox.window.EndpointEditBase', {
>   	    throw "baseUrl not set";
>   	}
>   
> -	me.url = `/api2/extjs${me.baseUrl}/endpoints/${me.type}`;
> +	if (me.type === 'group') {
> +	    me.url = `/api2/extjs${me.baseUrl}/groups`;
> +	} else {
> +	    me.url = `/api2/extjs${me.baseUrl}/endpoints/${me.type}`;
> +	}
>   
>   	if (me.isCreate) {
>   	    me.method = 'POST';






More information about the pve-devel mailing list