mirror of
https://git.proxmox.com/git/proxmox-widget-toolkit
synced 2025-06-27 10:24:07 +00:00
notification: matcher: match-field: show known fields/values
These changes introduce combogrid pickers for the 'field' and 'value' form elements for 'match-field' match rules. The 'field' picker shows a list of all known metadata fields, while the 'value' picker shows a list of all known values, filtered depending on the current value of 'field'. The list of known fields/values is retrieved from new API endpoints. Some values are marked 'internal' by the backend. This means that the 'value' field was not user-created (counter example: backup job IDs) and can therefore be used as a base for translations. Signed-off-by: Lukas Wagner <l.wagner@proxmox.com> Tested-by: Maximiliano Sandoval <m.sandoval@proxmox.com> Reviewed-by: Max Carrara <m.carrara@proxmox.com>
This commit is contained in:
parent
1ed4b715bc
commit
043ce82954
@ -15,3 +15,15 @@ Ext.define('proxmox-notification-matchers', {
|
|||||||
},
|
},
|
||||||
idProperty: 'name',
|
idProperty: 'name',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Ext.define('proxmox-notification-fields', {
|
||||||
|
extend: 'Ext.data.Model',
|
||||||
|
fields: ['name', 'description'],
|
||||||
|
idProperty: 'name',
|
||||||
|
});
|
||||||
|
|
||||||
|
Ext.define('proxmox-notification-field-values', {
|
||||||
|
extend: 'Ext.data.Model',
|
||||||
|
fields: ['value', 'comment', 'field'],
|
||||||
|
idProperty: 'value',
|
||||||
|
});
|
||||||
|
@ -79,7 +79,7 @@ Ext.define('Proxmox.window.NotificationMatcherEdit', {
|
|||||||
labelWidth: 120,
|
labelWidth: 120,
|
||||||
},
|
},
|
||||||
|
|
||||||
width: 700,
|
width: 800,
|
||||||
|
|
||||||
initComponent: function() {
|
initComponent: function() {
|
||||||
let me = this;
|
let me = this;
|
||||||
@ -416,10 +416,22 @@ Ext.define('Proxmox.panel.NotificationRulesEditPanel', {
|
|||||||
let me = this;
|
let me = this;
|
||||||
let record = me.get('selectedRecord');
|
let record = me.get('selectedRecord');
|
||||||
let currentData = record.get('data');
|
let currentData = record.get('data');
|
||||||
|
|
||||||
|
let newValue = [];
|
||||||
|
|
||||||
|
// Build equivalent regular expression if switching
|
||||||
|
// to 'regex' mode
|
||||||
|
if (value === 'regex') {
|
||||||
|
let regexVal = "^(";
|
||||||
|
regexVal += currentData.value.join('|') + ")$";
|
||||||
|
newValue.push(regexVal);
|
||||||
|
}
|
||||||
|
|
||||||
record.set({
|
record.set({
|
||||||
data: {
|
data: {
|
||||||
...currentData,
|
...currentData,
|
||||||
type: value,
|
type: value,
|
||||||
|
value: newValue,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -441,6 +453,8 @@ Ext.define('Proxmox.panel.NotificationRulesEditPanel', {
|
|||||||
data: {
|
data: {
|
||||||
...currentData,
|
...currentData,
|
||||||
field: value,
|
field: value,
|
||||||
|
// Reset value if field changes
|
||||||
|
value: [],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -549,6 +563,9 @@ Ext.define('Proxmox.panel.NotificationRulesEditPanel', {
|
|||||||
column2: [
|
column2: [
|
||||||
{
|
{
|
||||||
xtype: 'pmxNotificationMatchRuleSettings',
|
xtype: 'pmxNotificationMatchRuleSettings',
|
||||||
|
cbind: {
|
||||||
|
baseUrl: '{baseUrl}',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
],
|
],
|
||||||
@ -601,7 +618,7 @@ Ext.define('Proxmox.panel.NotificationMatchRuleTree', {
|
|||||||
let value = data.value;
|
let value = data.value;
|
||||||
text = Ext.String.format(gettext("Match field: {0}={1}"), field, value);
|
text = Ext.String.format(gettext("Match field: {0}={1}"), field, value);
|
||||||
iconCls = 'fa fa-square-o';
|
iconCls = 'fa fa-square-o';
|
||||||
if (!field || !value) {
|
if (!field || !value || (Ext.isArray(value) && !value.length)) {
|
||||||
iconCls += ' internal-error';
|
iconCls += ' internal-error';
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@ -821,6 +838,11 @@ Ext.define('Proxmox.panel.NotificationMatchRuleTree', {
|
|||||||
if (type === undefined) {
|
if (type === undefined) {
|
||||||
type = "exact";
|
type = "exact";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type === 'exact') {
|
||||||
|
matchedValue = matchedValue.split(',');
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'match-field',
|
type: 'match-field',
|
||||||
data: {
|
data: {
|
||||||
@ -982,7 +1004,9 @@ Ext.define('Proxmox.panel.NotificationMatchRuleTree', {
|
|||||||
Ext.define('Proxmox.panel.NotificationMatchRuleSettings', {
|
Ext.define('Proxmox.panel.NotificationMatchRuleSettings', {
|
||||||
extend: 'Ext.panel.Panel',
|
extend: 'Ext.panel.Panel',
|
||||||
xtype: 'pmxNotificationMatchRuleSettings',
|
xtype: 'pmxNotificationMatchRuleSettings',
|
||||||
|
mixins: ['Proxmox.Mixin.CBind'],
|
||||||
border: false,
|
border: false,
|
||||||
|
layout: 'anchor',
|
||||||
|
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
@ -1000,6 +1024,8 @@ Ext.define('Proxmox.panel.NotificationMatchRuleSettings', {
|
|||||||
['notall', gettext('At least one rule does not match')],
|
['notall', gettext('At least one rule does not match')],
|
||||||
['notany', gettext('No rule matches')],
|
['notany', gettext('No rule matches')],
|
||||||
],
|
],
|
||||||
|
// Hide initially to avoid glitches when opening the window
|
||||||
|
hidden: true,
|
||||||
bind: {
|
bind: {
|
||||||
hidden: '{!showMatchingMode}',
|
hidden: '{!showMatchingMode}',
|
||||||
disabled: '{!showMatchingMode}',
|
disabled: '{!showMatchingMode}',
|
||||||
@ -1011,7 +1037,8 @@ Ext.define('Proxmox.panel.NotificationMatchRuleSettings', {
|
|||||||
fieldLabel: gettext('Node type'),
|
fieldLabel: gettext('Node type'),
|
||||||
isFormField: false,
|
isFormField: false,
|
||||||
allowBlank: false,
|
allowBlank: false,
|
||||||
|
// Hide initially to avoid glitches when opening the window
|
||||||
|
hidden: true,
|
||||||
bind: {
|
bind: {
|
||||||
value: '{nodeType}',
|
value: '{nodeType}',
|
||||||
hidden: '{!showMatcherType}',
|
hidden: '{!showMatcherType}',
|
||||||
@ -1025,57 +1052,9 @@ Ext.define('Proxmox.panel.NotificationMatchRuleSettings', {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fieldLabel: gettext('Match Type'),
|
xtype: 'pmxNotificationMatchFieldSettings',
|
||||||
xtype: 'proxmoxKVComboBox',
|
cbind: {
|
||||||
reference: 'type',
|
baseUrl: '{baseUrl}',
|
||||||
isFormField: false,
|
|
||||||
allowBlank: false,
|
|
||||||
submitValue: false,
|
|
||||||
field: 'type',
|
|
||||||
|
|
||||||
bind: {
|
|
||||||
hidden: '{!typeIsMatchField}',
|
|
||||||
disabled: '{!typeIsMatchField}',
|
|
||||||
value: '{matchFieldType}',
|
|
||||||
},
|
|
||||||
|
|
||||||
comboItems: [
|
|
||||||
['exact', gettext('Exact')],
|
|
||||||
['regex', gettext('Regex')],
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldLabel: gettext('Field'),
|
|
||||||
xtype: 'proxmoxKVComboBox',
|
|
||||||
isFormField: false,
|
|
||||||
submitValue: false,
|
|
||||||
allowBlank: false,
|
|
||||||
editable: true,
|
|
||||||
displayField: 'key',
|
|
||||||
field: 'field',
|
|
||||||
bind: {
|
|
||||||
hidden: '{!typeIsMatchField}',
|
|
||||||
disabled: '{!typeIsMatchField}',
|
|
||||||
value: '{matchFieldField}',
|
|
||||||
},
|
|
||||||
// TODO: Once we have a 'notification registry', we should
|
|
||||||
// retrive those via an API call.
|
|
||||||
comboItems: [
|
|
||||||
['type', ''],
|
|
||||||
['hostname', ''],
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldLabel: gettext('Value'),
|
|
||||||
xtype: 'textfield',
|
|
||||||
isFormField: false,
|
|
||||||
submitValue: false,
|
|
||||||
allowBlank: false,
|
|
||||||
field: 'value',
|
|
||||||
bind: {
|
|
||||||
hidden: '{!typeIsMatchField}',
|
|
||||||
disabled: '{!typeIsMatchField}',
|
|
||||||
value: '{matchFieldValue}',
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1085,7 +1064,8 @@ Ext.define('Proxmox.panel.NotificationMatchRuleSettings', {
|
|||||||
allowBlank: true,
|
allowBlank: true,
|
||||||
multiSelect: true,
|
multiSelect: true,
|
||||||
field: 'value',
|
field: 'value',
|
||||||
|
// Hide initially to avoid glitches when opening the window
|
||||||
|
hidden: true,
|
||||||
bind: {
|
bind: {
|
||||||
value: '{matchSeverityValue}',
|
value: '{matchSeverityValue}',
|
||||||
hidden: '{!typeIsMatchSeverity}',
|
hidden: '{!typeIsMatchSeverity}',
|
||||||
@ -1108,7 +1088,8 @@ Ext.define('Proxmox.panel.NotificationMatchRuleSettings', {
|
|||||||
editable: true,
|
editable: true,
|
||||||
displayField: 'key',
|
displayField: 'key',
|
||||||
field: 'value',
|
field: 'value',
|
||||||
|
// Hide initially to avoid glitches when opening the window
|
||||||
|
hidden: true,
|
||||||
bind: {
|
bind: {
|
||||||
value: '{matchCalendarValue}',
|
value: '{matchCalendarValue}',
|
||||||
hidden: '{!typeIsMatchCalendar}',
|
hidden: '{!typeIsMatchCalendar}',
|
||||||
@ -1122,3 +1103,207 @@ Ext.define('Proxmox.panel.NotificationMatchRuleSettings', {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Ext.define('Proxmox.panel.MatchFieldSettings', {
|
||||||
|
extend: 'Ext.panel.Panel',
|
||||||
|
xtype: 'pmxNotificationMatchFieldSettings',
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
initComponent: function() {
|
||||||
|
let me = this;
|
||||||
|
|
||||||
|
let store = Ext.create('Ext.data.Store', {
|
||||||
|
model: 'proxmox-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: 'proxmox-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: Ext.create('Ext.app.ViewModel', {
|
||||||
|
parent: me.up('pmxNotificationMatchRulesEditPanel').getViewModel(),
|
||||||
|
formulas: {
|
||||||
|
isRegex: function(get) {
|
||||||
|
return get('matchFieldType') === 'regex';
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
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();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user