From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <d.csapak@proxmox.com>
Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68])
 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
 key-exchange X25519 server-signature RSA-PSS (2048 bits))
 (No client certificate requested)
 by lists.proxmox.com (Postfix) with ESMTPS id BB7A899778
 for <pve-devel@lists.proxmox.com>; Thu, 16 Nov 2023 12:58:25 +0100 (CET)
Received: from firstgate.proxmox.com (localhost [127.0.0.1])
 by firstgate.proxmox.com (Proxmox) with ESMTP id A3E6312855
 for <pve-devel@lists.proxmox.com>; Thu, 16 Nov 2023 12:57:55 +0100 (CET)
Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com
 [94.136.29.106])
 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
 key-exchange X25519 server-signature RSA-PSS (2048 bits))
 (No client certificate requested)
 by firstgate.proxmox.com (Proxmox) with ESMTPS
 for <pve-devel@lists.proxmox.com>; Thu, 16 Nov 2023 12:57:55 +0100 (CET)
Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1])
 by proxmox-new.maurer-it.com (Proxmox) with ESMTP id C89D243814
 for <pve-devel@lists.proxmox.com>; Thu, 16 Nov 2023 12:57:54 +0100 (CET)
From: Dominik Csapak <d.csapak@proxmox.com>
To: pve-devel@lists.proxmox.com
Date: Thu, 16 Nov 2023 12:57:52 +0100
Message-Id: <20231116115753.4129153-2-d.csapak@proxmox.com>
X-Mailer: git-send-email 2.30.2
In-Reply-To: <20231116115753.4129153-1-d.csapak@proxmox.com>
References: <20231114130000.565122-1-l.wagner@proxmox.com>
 <20231116115753.4129153-1-d.csapak@proxmox.com>
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
X-SPAM-LEVEL: Spam detection results:  0
 AWL 0.017 Adjusted score from AWL reputation of From: address
 BAYES_00                 -1.9 Bayes spam probability is 0 to 1%
 DMARC_MISSING             0.1 Missing DMARC policy
 KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment
 SPF_HELO_NONE           0.001 SPF: HELO does not publish an SPF Record
 SPF_PASS               -0.001 SPF: sender matches SPF record
 T_SCC_BODY_TEXT_LINE    -0.01 -
Subject: [pve-devel] [PATCH widget-toolkit 1/2] notification matcher:
 improve handling empty and invalid values
X-BeenThere: pve-devel@lists.proxmox.com
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: Proxmox VE development discussion <pve-devel.lists.proxmox.com>
List-Unsubscribe: <https://lists.proxmox.com/cgi-bin/mailman/options/pve-devel>, 
 <mailto:pve-devel-request@lists.proxmox.com?subject=unsubscribe>
List-Archive: <http://lists.proxmox.com/pipermail/pve-devel/>
List-Post: <mailto:pve-devel@lists.proxmox.com>
List-Help: <mailto:pve-devel-request@lists.proxmox.com?subject=help>
List-Subscribe: <https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel>, 
 <mailto:pve-devel-request@lists.proxmox.com?subject=subscribe>
X-List-Received-Date: Thu, 16 Nov 2023 11:58:25 -0000

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 src/window/NotificationMatcherEdit.js | 84 ++++++++++++++++++++++++++-
 1 file changed, 81 insertions(+), 3 deletions(-)

diff --git a/src/window/NotificationMatcherEdit.js b/src/window/NotificationMatcherEdit.js
index c0dfa34..0f29203 100644
--- a/src/window/NotificationMatcherEdit.js
+++ b/src/window/NotificationMatcherEdit.js
@@ -288,6 +288,35 @@ Ext.define('Proxmox.panel.NotificationRulesEditPanel', {
     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,
@@ -569,20 +598,32 @@ Ext.define('Proxmox.panel.NotificationMatchRuleTree', {
 
 	switch (type) {
 	    case 'match-severity': {
-		let v = data.value.join(', ');
+		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 += ' critical';
+		}
 	    } 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-cube';
+		if (!field || !value) {
+		    iconCls += ' critical';
+		}
 	    } 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 += ' critical';
+		}
 	    } break;
 	    case 'mode':
 		if (data.value === 'all') {
@@ -628,6 +669,15 @@ Ext.define('Proxmox.panel.NotificationMatchRuleTree', {
 	    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) {
@@ -647,6 +697,14 @@ Ext.define('Proxmox.panel.NotificationMatchRuleTree', {
 	    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) {
@@ -684,6 +742,14 @@ Ext.define('Proxmox.panel.NotificationMatchRuleTree', {
 	    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;
@@ -712,10 +778,14 @@ Ext.define('Proxmox.panel.NotificationMatchRuleTree', {
 
 		switch (type) {
 		    case 'match-field':
-			matchFieldStmts.push(`${data.type}:${data.field}=${data.value}`);
+			matchFieldStmts.push(`${data.type}:${data.field ?? ''}=${data.value ?? ''}`);
 			break;
 		    case 'match-severity':
-			matchSeverityStmts.push(data.value.join(','));
+			if (Ext.isArray(data.value)) {
+			    matchSeverityStmts.push(data.value.join(','));
+			} else {
+			    matchSeverityStmts.push(data.value);
+			}
 			break;
 		    case 'match-calendar':
 			matchCalendarStmts.push(data.value);
@@ -780,6 +850,9 @@ Ext.define('Proxmox.panel.NotificationMatchRuleTree', {
 		node.remove(true);
 	    }
 
+	    if (!value) {
+		return;
+	    }
 	    let records = value.map(parseMatchField);
 
 	    let rootNode = treeStore.getRootNode();
@@ -979,6 +1052,7 @@ Ext.define('Proxmox.panel.NotificationMatchRuleSettings', {
 	    isFormField: false,
 	    allowBlank: false,
 	    submitValue: false,
+	    field: 'type',
 
 	    bind: {
 		hidden: '{!typeIsMatchField}',
@@ -999,6 +1073,7 @@ Ext.define('Proxmox.panel.NotificationMatchRuleSettings', {
 	    allowBlank: false,
 	    editable: true,
 	    displayField: 'key',
+	    field: 'field',
 	    bind: {
 		hidden: '{!typeIsMatchField}',
 		disabled: '{!typeIsMatchField}',
@@ -1017,6 +1092,7 @@ Ext.define('Proxmox.panel.NotificationMatchRuleSettings', {
 	    isFormField: false,
 	    submitValue: false,
 	    allowBlank: false,
+	    field: 'value',
 	    bind: {
 		hidden: '{!typeIsMatchField}',
 		disabled: '{!typeIsMatchField}',
@@ -1029,6 +1105,7 @@ Ext.define('Proxmox.panel.NotificationMatchRuleSettings', {
 	    isFormField: false,
 	    allowBlank: true,
 	    multiSelect: true,
+	    field: 'value',
 
 	    bind: {
 		value: '{matchSeverityValue}',
@@ -1050,6 +1127,7 @@ Ext.define('Proxmox.panel.NotificationMatchRuleSettings', {
 	    allowBlank: false,
 	    editable: true,
 	    displayField: 'key',
+	    field: 'value',
 
 	    bind: {
 		value: '{matchCalendarValue}',
-- 
2.30.2