Skip to content

Commit 51116eb

Browse files
committed
Feature: New plugin/event param type: "System Menu", pre-populated with various xyOps internal system list items.
1 parent 72279f5 commit 51116eb

4 files changed

Lines changed: 178 additions & 4 deletions

File tree

docs/plugins.md

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1068,6 +1068,46 @@ Finally, you can define groups of items in the menu by including an object with
10681068
}
10691069
```
10701070

1071+
### System Menu
1072+
1073+
A "system menu" is a dynamically populated menu, similar to a [Bucket Menu](#bucket-menu), but the menu items are pulled from xyOps itself. This is useful when a Plugin needs the user to select an existing xyOps object, such as an event, category, server, server group, plugin, user, role, web hook or monitor.
1074+
1075+
When you add your parameter and select the "System Menu" field type, you will need to select the internal xyOps list to use for the menu. The menu is populated automatically from the current system data, and xyOps adds a `(None)` item at the top so no item is selected by default.
1076+
1077+
When the user selects an item, the selected item's ID is stored in [Job.params](data.md#job-params) and passed to the Plugin. For example, if you define a parameter with ID `custom_event`, point it at the Events system list, and the user selects an event with ID `emp6dulft42zjevn8`, the Plugin would receive this:
1078+
1079+
```json
1080+
{
1081+
"custom_event": "emp6dulft42zjevn8"
1082+
}
1083+
```
1084+
1085+
Most system menus store the selected item's normal `id` property. The Users menu is a special case, and stores the selected user's `username`.
1086+
1087+
The following system lists are available:
1088+
1089+
| List | Stored Value |
1090+
|------|--------------|
1091+
| Alerts | Alert ID |
1092+
| Algorithms | Target algorithm ID |
1093+
| Buckets | Bucket ID |
1094+
| Categories | Category ID |
1095+
| Channels | Channel ID |
1096+
| Events | Event ID |
1097+
| Groups | Server group ID |
1098+
| Monitors | Monitor ID |
1099+
| Plugins | Plugin ID |
1100+
| Roles | Role ID |
1101+
| Servers | Server ID |
1102+
| Tags | Tag ID |
1103+
| Targets | Server group ID or server ID |
1104+
| Users | Username |
1105+
| Web Hooks | Web Hook ID |
1106+
1107+
The "Targets" menu is a combined list which includes both server groups and individual servers, arranged into menu sections. This is handy for Plugin parameters that should accept either kind of job target. The Algorithms menu contains the built-in event target selection algorithms, such as Random.
1108+
1109+
API Keys and Secrets are intentionally not offered as system menu sources.
1110+
10711111
### Checkbox
10721112

10731113
A checkbox is displayed with a label, and the "checked" state is stored as a Boolean parameter value (`true` or `false`).
@@ -1342,4 +1382,3 @@ To use a pre-existing Docker image such as `ubuntu`, you can set the launch comm
13421382
## Plugin Marketplace
13431383

13441384
xyOps has an integrated Plugin Marketplace, so you can expand the app's feature set by leveraging Plugins published both by PixlCore (the makers of xyOps), as well as the developer community. For more on this, please see the [Marketplace Guide](marketplace.md).
1345-

htdocs/js/pages/Base.class.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2660,6 +2660,11 @@ Page.Base = class Base extends Page {
26602660
else html += self.getNiceBucket(param.bucket_id);
26612661
break;
26622662

2663+
case 'system':
2664+
html += '<i class="link mdi mdi-' + elem_icon + '" onClick="$P().copyPluginParamValue(this)" title="Copy to Clipboard">&nbsp;</i>';
2665+
html += '<span class="data_value">' + encode_entities( elem_value.toString() || '(None)' ) + '</span>';
2666+
break;
2667+
26632668
case 'toolset':
26642669
if (!param.data) param.data = {};
26652670
if (!param.data.tools) param.data.tools = [];

htdocs/js/pages/PageUtils.class.js

Lines changed: 131 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2669,6 +2669,11 @@ Page.PageUtils = class PageUtils extends Page.Base {
26692669
}
26702670
break;
26712671

2672+
case 'system':
2673+
elem_value = (param.id in params) ? params[param.id] : '';
2674+
html += self.getFormMenuSingle({ id: elem_id, value: elem_value, options: self.getSystemMenuItems(param.list_id), disabled: elem_dis, title: param.title });
2675+
break;
2676+
26722677
case 'toolset':
26732678
var data = param.data || { tools: [] };
26742679
if (!data.tools) data.tools = [];
@@ -3719,6 +3724,11 @@ Page.PageUtils = class PageUtils extends Page.Base {
37193724
else html += self.getNiceBucket( param.bucket_id );
37203725
break;
37213726

3727+
case 'system':
3728+
html += '<i class="mdi mdi-' + elem_icon + '">&nbsp;</i>';
3729+
html += strip_html( elem_value.toString() || '(None)' );
3730+
break;
3731+
37223732
case 'toolset':
37233733
html += '<i class="mdi mdi-' + elem_icon + '">&nbsp;</i>';
37243734
var tool = find_object( param.data.tools, { id: elem_value } );
@@ -4529,6 +4539,10 @@ Page.PageUtils = class PageUtils extends Page.Base {
45294539
pairs.push([ self.getNiceBucket(param.bucket_id) ]);
45304540
break;
45314541

4542+
case 'system':
4543+
pairs.push([ self.getNiceSystemList(param.list_id) ]);
4544+
break;
4545+
45324546
case 'toolset':
45334547
if (param.data && param.data.tools && param.data.tools.length) pairs.push([ commify(param.data.tools.length) + " tools in set" ]);
45344548
else pairs.push([ "(No tools in set)" ]);
@@ -4582,7 +4596,7 @@ Page.PageUtils = class PageUtils extends Page.Base {
45824596
var old_param = param;
45834597

45844598
// prepare control type menu
4585-
var ctypes = (this.controlTypes || ['checkbox', 'code', 'json', 'hidden', 'select', 'bucket', 'text', 'textarea']).map (function(key) {
4599+
var ctypes = (this.controlTypes || ['checkbox', 'code', 'json', 'hidden', 'select', 'bucket', 'system', 'text', 'textarea']).map (function(key) {
45864600
return {
45874601
id: key,
45884602
title: config.ui.control_type_labels[key],
@@ -4735,6 +4749,7 @@ Page.PageUtils = class PageUtils extends Page.Base {
47354749
caption: 'Enter JSON data describing the toolset. [Learn More](#Docs/plugins/toolset)'
47364750
});
47374751

4752+
// bucket menu
47384753
html += this.getFormRow({
47394754
id: 'd_epa_bucket_id',
47404755
label: 'Storage Bucket:',
@@ -4760,6 +4775,20 @@ Page.PageUtils = class PageUtils extends Page.Base {
47604775
caption: 'Optionally enter a `dot.delimited.path` to the array within the bucket data record. If omitted, the array should be at the top-level of the bucket data.'
47614776
});
47624777

4778+
// system menu
4779+
html += this.getFormRow({
4780+
id: 'd_epa_list_id',
4781+
label: 'System Menu:',
4782+
content: this.getFormMenuSingle({
4783+
id: 'fe_epa_list_id',
4784+
title: 'Select System List',
4785+
options: this.getSystemListMenuItems(),
4786+
value: param.list_id || '',
4787+
default_icon: ''
4788+
}),
4789+
caption: 'Select an internal list of items to populate the system menu. No item will be selected by default. [Learn More](#Docs/plugins/system-menu)'
4790+
});
4791+
47634792
// caption
47644793
html += this.getFormRow({
47654794
label: 'Caption:',
@@ -4869,6 +4898,11 @@ Page.PageUtils = class PageUtils extends Page.Base {
48694898
delete param.required;
48704899
break;
48714900

4901+
case 'system':
4902+
param.list_id = $('#fe_epa_list_id').val();
4903+
delete param.required;
4904+
break;
4905+
48724906
case 'hidden':
48734907
param.value = $('#fe_epa_value_hidden').val();
48744908
delete param.required;
@@ -4904,12 +4938,13 @@ Page.PageUtils = class PageUtils extends Page.Base {
49044938
} ); // Dialog.confirm
49054939

49064940
var change_param_type = function(new_type) {
4907-
$('#d_epa_value_text, #d_epa_value_textarea, #d_epa_value_code, #d_epa_value_json, #d_epa_value_checkbox, #d_epa_value_select, #d_epa_value_hidden, #d_epa_value_toolset, #d_epa_bucket_id, #d_epa_bucket_path').hide();
4941+
$('#d_epa_value_text, #d_epa_value_textarea, #d_epa_value_code, #d_epa_value_json, #d_epa_value_checkbox, #d_epa_value_select, #d_epa_value_hidden, #d_epa_value_toolset, #d_epa_bucket_id, #d_epa_bucket_path, #d_epa_list_id').hide();
49084942
$('#d_epa_value_' + new_type).show();
49094943
$('#d_epa_required').toggle( !!new_type.match(/^(text|textarea|code)$/) );
49104944
$('#d_epa_text_variant').toggle( !!new_type.match(/^(text)$/) );
49114945
$('#d_epa_locked').toggle( !new_type.match(/^(toolset)$/) );
49124946
$('#d_epa_bucket_id, #d_epa_bucket_path').toggle( !!new_type.match(/^(bucket)$/) );
4947+
$('#d_epa_list_id').toggle( !!new_type.match(/^(system)$/) );
49134948
Dialog.autoResize();
49144949
}; // change_action_type
49154950

@@ -4921,7 +4956,7 @@ Page.PageUtils = class PageUtils extends Page.Base {
49214956

49224957
if (idx == -1) $('#fe_epa_id').focus();
49234958

4924-
SingleSelect.init( $('#fe_epa_type, #fe_epa_text_variant, #fe_epa_bucket_id') );
4959+
SingleSelect.init( $('#fe_epa_type, #fe_epa_text_variant, #fe_epa_bucket_id, #fe_epa_list_id') );
49254960
Dialog.autoResize();
49264961
}
49274962

@@ -4951,6 +4986,94 @@ Page.PageUtils = class PageUtils extends Page.Base {
49514986
});
49524987
}
49534988

4989+
getNiceSystemList(list_id) {
4990+
// get formatted list title with icon
4991+
var item = find_object( this.getSystemListMenuItems(), { id: list_id } );
4992+
if (!item) return '(None)';
4993+
4994+
var html = '<span class="nowrap" title="' + encode_attrib_entities(item.title) + '">';
4995+
var icon = '<i class="mdi mdi-' + item.icon + '"></i>';
4996+
4997+
html += icon + item.title;
4998+
html += '</span>';
4999+
5000+
return html;
5001+
}
5002+
5003+
getSystemListMenuItems() {
5004+
// get menu of all lists (excluding a few)
5005+
var items = config.ui.list_list.filter( function(item) {
5006+
return !item.id.match(/^(api_keys|secrets)$/);
5007+
} );
5008+
5009+
items = items.concat([
5010+
{
5011+
"id": "servers",
5012+
"title": "Servers",
5013+
"icon": "router-network"
5014+
},
5015+
{
5016+
"id": "groups",
5017+
"title": "Groups",
5018+
"icon": "server-network"
5019+
},
5020+
{
5021+
"id": "targets",
5022+
"title": "Targets",
5023+
"icon": "lan"
5024+
},
5025+
{
5026+
"id": "algos",
5027+
"title": "Algorithms",
5028+
"icon": "dice-5-outline"
5029+
}
5030+
]);
5031+
5032+
sort_by( items, 'title' );
5033+
return items;
5034+
}
5035+
5036+
getSystemMenuItems(list_id) {
5037+
// get items for menu given list id
5038+
var items = [];
5039+
var list_def = find_object( config.ui.list_list, { id: list_id } );
5040+
5041+
switch (list_id) {
5042+
case 'events':
5043+
items = this.getCategorizedEvents();
5044+
break;
5045+
5046+
case 'servers':
5047+
items = this.getCategorizedServers(true);
5048+
break;
5049+
5050+
case 'targets':
5051+
items = [].concat(
5052+
this.buildOptGroup(app.groups, "Groups:", 'server-network'),
5053+
this.buildServerOptGroup("Servers:", 'router-network')
5054+
);
5055+
break;
5056+
5057+
case 'algos':
5058+
items = config.ui.event_target_algo_menu;
5059+
break;
5060+
5061+
case 'users':
5062+
items = app.users.map( function(user) { return { id: user.username, title: user.full_name, icon: user.icon || 'account' }; } );
5063+
break;
5064+
5065+
default:
5066+
if (list_def && app[list_id]) {
5067+
items = app[list_id].map( function(item) { return { id: item.id, title: item.title, icon: list_def.icon }; } );
5068+
}
5069+
else items = app[list_id] || [];
5070+
break;
5071+
}
5072+
5073+
items.unshift({ "id": "", "title": "(None)" });
5074+
return items;
5075+
}
5076+
49545077
deleteParam(idx) {
49555078
// delete selected param
49565079
this.params.splice( idx, 1 );
@@ -5179,6 +5302,11 @@ Page.PageUtils = class PageUtils extends Page.Base {
51795302
}
51805303
break;
51815304

5305+
case 'system':
5306+
elem_value = (param.id in params) ? params[param.id] : '';
5307+
html += self.getFormMenuSingle({ id: elem_id, value: elem_value, options: self.getSystemMenuItems(param.list_id), disabled: elem_dis, title: param.title });
5308+
break;
5309+
51825310
} // switch type
51835311

51845312
if (param.caption) html += '<div class="info_caption">' + inline_marked( strip_html(param.caption) ) + '</div>';

internal/ui.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,6 +1042,7 @@
10421042
"checkbox": "Checkbox",
10431043
"select": "Menu",
10441044
"bucket": "Bucket Menu",
1045+
"system": "System Menu",
10451046
"hidden": "Hidden",
10461047
"toolset": "Toolset"
10471048
},
@@ -1054,6 +1055,7 @@
10541055
"checkbox": "checkbox-marked-outline",
10551056
"select": "form-dropdown",
10561057
"bucket": "pail-outline",
1058+
"system": "list-box-outline",
10571059
"hidden": "eye-off-outline",
10581060
"toolset": "tools"
10591061
},

0 commit comments

Comments
 (0)