Signed-off-by: Lukas Wagner <l.wag...@proxmox.com>
---

Notes:
    Changes since v3:
      - Show warnings only if 'never' is selected
      - Also show a warning for disabled package update notifications
      - Some code style touch ups
      - Added some comments

 www/manager6/Makefile                 |   1 +
 www/manager6/dc/Config.js             |  12 ++
 www/manager6/dc/NotificationEvents.js | 277 ++++++++++++++++++++++++++
 3 files changed, 290 insertions(+)
 create mode 100644 www/manager6/dc/NotificationEvents.js

diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index 5ea4e4a2..59a5d8a7 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -159,6 +159,7 @@ JSSRC=                                                      
\
        dc/Health.js                                    \
        dc/Log.js                                       \
        dc/NodeView.js                                  \
+       dc/NotificationEvents.js                        \
        dc/OptionView.js                                \
        dc/PermissionView.js                            \
        dc/PoolEdit.js                                  \
diff --git a/www/manager6/dc/Config.js b/www/manager6/dc/Config.js
index 04ed04f0..aa025c8d 100644
--- a/www/manager6/dc/Config.js
+++ b/www/manager6/dc/Config.js
@@ -317,6 +317,18 @@ Ext.define('PVE.dc.Config', {
            );
        }
 
+       if (caps.dc['Sys.Audit']) {
+           me.items.push(
+               {
+                   xtype: 'pveNotificationEvents',
+                   title: gettext('Notifications'),
+                   onlineHelp: 'notification_events',
+                   iconCls: 'fa fa-bell-o',
+                   itemId: 'notifications',
+               },
+           );
+       }
+
        if (caps.dc['Sys.Audit']) {
            me.items.push({
                xtype: 'pveDcSupport',
diff --git a/www/manager6/dc/NotificationEvents.js 
b/www/manager6/dc/NotificationEvents.js
new file mode 100644
index 00000000..d233c70b
--- /dev/null
+++ b/www/manager6/dc/NotificationEvents.js
@@ -0,0 +1,277 @@
+Ext.define('PVE.dc.NotificationEventsPolicySelector', {
+    alias: ['widget.pveNotificationEventsPolicySelector'],
+    extend: 'Proxmox.form.KVComboBox',
+    deleteEmpty: false,
+    value: '__default__',
+
+    config: {
+       warningRef: null,
+       warnIfValIs: null,
+    },
+
+    listeners: {
+       change: function(field, newValue) {
+           let me = this;
+           if (!me.warningRef && !me.warnIfValIs) {
+               return;
+           }
+
+           let warningField = field.nextSibling(
+               `displayfield[reference=${me.warningRef}]`
+           );
+           warningField.setVisible(newValue === me.warnIfValIs);
+       },
+    },
+});
+
+Ext.define('PVE.dc.NotificationEventDisabledWarning', {
+    alias: ['widget.pveNotificationEventDisabledWarning'],
+    extend: 'Ext.form.field.Display',
+    userCls: 'pmx-hint',
+    hidden: true,
+    value: gettext('Disabling notifications is not ' +
+        'recommended for production systems!'),
+});
+
+Ext.define('PVE.dc.NotificationEventsTargetSelector', {
+    alias: ['widget.pveNotificationEventsTargetSelector'],
+    extend: 'PVE.form.NotificationTargetSelector',
+    fieldLabel: gettext('Notification Target'),
+    allowBlank: true,
+    editable: true,
+    autoSelect: false,
+    deleteEmpty: false,
+    emptyText: `${Proxmox.Utils.defaultText} (${gettext("mail-to-root")})`,
+});
+
+Ext.define('PVE.dc.NotificationEvents', {
+    extend: 'Proxmox.grid.ObjectGrid',
+    alias: ['widget.pveNotificationEvents'],
+
+    // Taken from OptionView.js, but adapted slightly.
+    // The modified version allows us to have multiple rows in the ObjectGrid
+    // for the same underlying property (notify).
+    // Every setting is eventually stored as a property string in the
+    // notify key of datacenter.cfg.
+    // When updating 'notify', all properties that were already set
+    // also have to be submitted, even if they were not modified.
+    // This means that we need to save the old value somewhere.
+    addInputPanelRow: function(name, propertyName, text, opts) {
+       let me = this;
+
+       opts = opts || {};
+       me.rows = me.rows || {};
+
+       me.rows[name] = {
+           required: true,
+           defaultValue: opts.defaultValue,
+           header: text,
+           renderer: opts.renderer,
+           name: propertyName,
+           editor: {
+               xtype: 'proxmoxWindowEdit',
+               width: opts.width || 400,
+               subject: text,
+               onlineHelp: opts.onlineHelp,
+               fieldDefaults: {
+                   labelWidth: opts.labelWidth || 150,
+               },
+               setValues: function(values) {
+                   let value = values[propertyName];
+
+                   if (opts.parseBeforeSet) {
+                       value = PVE.Parser.parsePropertyString(value);
+                   }
+
+                   Ext.Array.each(this.query('inputpanel'), function(panel) {
+                       panel.setValues(value);
+
+                       // Save the original value
+                       panel.originalValue = {
+                           ...value,
+                       };
+                   });
+               },
+               url: opts.url,
+               items: [{
+                   xtype: 'inputpanel',
+                   onGetValues: function(values) {
+                       let fields = this.config.items.map(field => 
field.name).filter(n => n);
+
+                       // Restore old, unchanged values
+                       for (const [key, value] of 
Object.entries(this.originalValue)) {
+                           if (!fields.includes(key)) {
+                               values[key] = value;
+                           }
+                       }
+
+                       let value = {};
+                       if (Object.keys(values).length > 0) {
+                           value[propertyName] = 
PVE.Parser.printPropertyString(values);
+                       } else {
+                           Proxmox.Utils.assemble_field_data(value, { 
'delete': propertyName });
+                       }
+
+                       return value;
+                   },
+                   items: opts.items,
+               }],
+           },
+       };
+    },
+
+    initComponent: function() {
+       let me = this;
+
+       // Helper function for rendering the property
+       // Needed since the actual value is always stored in the 'notify' 
property
+       let render_value = (store, target_key, mode_key, default_val) => {
+           let value = store.getById('notify')?.get('value') ?? {};
+           let target = value[target_key] ?? gettext('mail-to-root');
+           let template;
+
+           switch (value[mode_key]) {
+               case 'always':
+                   template = gettext('Always, notify via target \'{0}\'');
+                   break;
+               case 'never':
+                   template = gettext('Never');
+                   break;
+               case 'auto':
+                   template = gettext('Automatically, notify via target 
\'{0}\'');
+                   break;
+               default:
+                   template = gettext('{1} ({2}), notify via target \'{0}\'');
+                   break;
+           }
+
+           return Ext.String.format(template, target, 
Proxmox.Utils.defaultText, default_val);
+       };
+
+       me.addInputPanelRow('fencing', 'notify', gettext('Node Fencing'), {
+           renderer: (value, metaData, record, rowIndex, colIndex, store) =>
+               render_value(store, 'target-fencing', 'fencing', 
gettext('Always')),
+           url: "/api2/extjs/cluster/options",
+           items: [
+               {
+                   xtype: 'pveNotificationEventsPolicySelector',
+                   name: 'fencing',
+                   fieldLabel: gettext('Notify'),
+                   comboItems: [
+                       ['__default__', `${Proxmox.Utils.defaultText} 
(${gettext('Always')})`],
+                       ['always', gettext('Always')],
+                       ['never', gettext('Never')],
+                   ],
+                   warningRef: 'warning',
+                   warnIfValIs: 'never',
+               },
+               {
+                   xtype: 'pveNotificationEventsTargetSelector',
+                   name: 'target-fencing',
+               },
+               {
+                   xtype: 'pveNotificationEventDisabledWarning',
+                   reference: 'warning'
+               },
+           ],
+       });
+
+       me.addInputPanelRow('replication', 'notify', gettext('Replication'), {
+           renderer: (value, metaData, record, rowIndex, colIndex, store) =>
+               render_value(store, 'target-replication', 'replication', 
gettext('Always')),
+           url: "/api2/extjs/cluster/options",
+           items: [
+               {
+                   xtype: 'pveNotificationEventsPolicySelector',
+                   name: 'replication',
+                   fieldLabel: gettext('Notify'),
+                   comboItems: [
+                       ['__default__', `${Proxmox.Utils.defaultText} 
(${gettext('Always')})`],
+                       ['always', gettext('Always')],
+                       ['never', gettext('Never')],
+                   ],
+                   warningRef: 'warning',
+                   warnIfValIs: 'never',
+               },
+               {
+                   xtype: 'pveNotificationEventsTargetSelector',
+                   name: 'target-replication',
+               },
+               {
+                   xtype: 'pveNotificationEventDisabledWarning',
+                   reference: 'warning'
+               },
+           ],
+       });
+
+       me.addInputPanelRow('updates', 'notify', gettext('Package Updates'), {
+           renderer: (value, metaData, record, rowIndex, colIndex, store) =>
+               render_value(
+                   store,
+                   'target-package-updates',
+                   'package-updates',
+                   gettext('Automatically')
+               ),
+           url: "/api2/extjs/cluster/options",
+           items: [
+               {
+                   xtype: 'pveNotificationEventsPolicySelector',
+                   name: 'package-updates',
+                   fieldLabel: gettext('Notify'),
+                   comboItems: [
+                       [
+                           '__default__',
+                           `${Proxmox.Utils.defaultText} 
(${gettext('Automatically')})`
+                       ],
+                       ['auto', gettext('Automatically')],
+                       ['always', gettext('Always')],
+                       ['never', gettext('Never')],
+                   ],
+                   warningRef: 'warning',
+                   warnIfValIs: 'never',
+               },
+               {
+                   xtype: 'pveNotificationEventsTargetSelector',
+                   name: 'target-package-updates',
+               },
+               {
+                   xtype: 'pveNotificationEventDisabledWarning',
+                   reference: 'warning'
+               },
+           ],
+       });
+
+       // Hack: Also load the notify property to make it accessible
+       // for our render functions.
+       me.rows.notify = {
+           visible: false,
+       };
+
+       me.selModel = Ext.create('Ext.selection.RowModel', {});
+
+       Ext.apply(me, {
+           tbar: [{
+               text: gettext('Edit'),
+               xtype: 'proxmoxButton',
+               disabled: true,
+               handler: () => me.run_editor(),
+               selModel: me.selModel,
+           }],
+           url: "/api2/json/cluster/options",
+           editorConfig: {
+               url: "/api2/extjs/cluster/options",
+           },
+           interval: 5000,
+           cwidth1: 200,
+           listeners: {
+               itemdblclick: me.run_editor,
+           },
+       });
+
+       me.callParent();
+
+       me.on('activate', me.rstore.startUpdate);
+       me.on('destroy', me.rstore.stopUpdate);
+       me.on('deactivate', me.rstore.stopUpdate);
+    },
+});
-- 
2.39.2



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

Reply via email to