Skip to content

Commit 3e6d055

Browse files
Erwin Dondorperwindon
Erwin Dondorp
authored andcommitted
use new menus
1 parent 879ee79 commit 3e6d055

29 files changed

+412
-321
lines changed

saltgui/static/scripts/Character.js

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export class Character {
2525
Character.WHITE_RIGHT_POINTING_TRIANGLE = "\u25B7";
2626
Character.BLACK_RIGHT_POINTING_POINTER = "\u25BA";
2727
Character.WHITE_DOWN_POINTING_TRIANGLE = "\u25BD";
28+
Character.WHITE_CIRCLE = "\u25CB";
2829
Character.BLACK_CIRCLE = "\u25CF";
2930
Character.GEAR = "\u2699";
3031
Character.WARNING_SIGN = "\u26A0" + Character._VARIATION_SELECTOR_16;

saltgui/static/scripts/CommandBox.js

+11-10
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import {Character} from "./Character.js";
44
import {Documentation} from "./Documentation.js";
5-
import {DropDownMenu} from "./DropDown.js";
5+
import {DropDownMenuCmd} from "./DropDownCmd.js";
66
import {Output} from "./output/Output.js";
77
import {ParseCommandLine} from "./ParseCommandLine.js";
88
import {Router} from "./Router.js";
@@ -18,14 +18,15 @@ export class CommandBox {
1818
this.api = pApi;
1919

2020
const cmdbox = document.getElementById("cmd-box");
21-
this.cmdmenu = new DropDownMenu(cmdbox);
21+
this.cmdmenu = new DropDownMenuCmd(cmdbox);
2222

23-
this.documentation = new Documentation(this.router, this);
2423
this._registerCommandBoxEventListeners();
2524

2625
RunType.createMenu();
2726
TargetType.createMenu();
2827

28+
this.documentation = new Documentation(pRouter, this);
29+
2930
const manualRun = document.getElementById("popup-run-command");
3031
Utils.addTableHelp(manualRun, "Click for help", "bottom-center");
3132
const helpButton = manualRun.querySelector("#help");
@@ -58,7 +59,7 @@ export class CommandBox {
5859
CommandBox.templateCatMenu.setTitle("");
5960
return;
6061
}
61-
const menu = new DropDownMenu(titleElement);
62+
const menu = new DropDownMenuCmd(titleElement);
6263
menu.setTitle("");
6364
menu.menuButton.classList.add("small-button-left");
6465
CommandBox.templateCatMenu = menu;
@@ -70,7 +71,7 @@ export class CommandBox {
7071
}
7172
categories.unshift(null);
7273
for (const category of categories) {
73-
menu.addMenuItem(
74+
menu.addMenuItemCmd(
7475
() => CommandBox._templateCatMenuItemTitle(category),
7576
() => {
7677
CommandBox.templateTmplMenu._templateCategory = category;
@@ -115,7 +116,7 @@ export class CommandBox {
115116
CommandBox.templateTmplMenu._templateCategory = null;
116117
return;
117118
}
118-
const menu = new DropDownMenu(titleElement);
119+
const menu = new DropDownMenuCmd(titleElement);
119120
menu.menuButton.classList.add("small-button-left");
120121
CommandBox.templateTmplMenu = menu;
121122
CommandBox.templateTmplMenu._templateCategory = null;
@@ -127,7 +128,7 @@ export class CommandBox {
127128
if (!description) {
128129
description = "(" + key + ")";
129130
}
130-
menu.addMenuItem(
131+
menu.addMenuItemCmd(
131132
() => CommandBox._templateTmplMenuItemTitle(template),
132133
() => {
133134
CommandBox._applyTemplate(template);
@@ -264,7 +265,7 @@ export class CommandBox {
264265
TargetType.setTargetType(targetType);
265266
} else {
266267
// not in the template, revert to default
267-
TargetType.setTargetTypeDefault();
268+
TargetType.setTargetType(null);
268269
}
269270

270271
if (template.target) {
@@ -325,7 +326,7 @@ export class CommandBox {
325326
const commandField = document.getElementById("command");
326327
const commandValue = commandField.value;
327328

328-
const targetType = TargetType.menuTargetType._value;
329+
const targetType = TargetType.menuTargetType.getValue();
329330

330331
const patWhitespaceAll = /\s/g;
331332
const commandValueNoTabs = commandValue.replace(patWhitespaceAll, " ");
@@ -479,7 +480,7 @@ export class CommandBox {
479480

480481
// reset to default, so that its value is initially hidden
481482
RunType.setRunTypeDefault();
482-
TargetType.setTargetTypeDefault();
483+
TargetType.setTargetType(null);
483484

484485
if (Router.currentPage) {
485486
Router.currentPage.refreshPage();

saltgui/static/scripts/Documentation.js

+10-10
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,23 @@ export class Documentation {
1717
this.router = pRouter;
1818
this.commandbox = pCommandBox;
1919

20-
pCommandBox.cmdmenu.addMenuItem(
20+
Documentation.DOCUMENTATION_URL = "https://docs.saltstack.com/en/latest/ref/";
21+
Documentation.EXTERNAL_LINK = Character.NO_BREAK_SPACE + Character.EXTERNAL_LINK_IMG;
22+
23+
Documentation.PROVIDERS = { };
24+
25+
pCommandBox.cmdmenu.addMenuItemCmd(
2126
() => Documentation._manualRunMenuSysDocPrepare(),
2227
() => this._manualRunMenuSysDocRun());
23-
pCommandBox.cmdmenu.addMenuItem(
28+
pCommandBox.cmdmenu.addMenuItemCmd(
2429
() => Documentation._manualRunMenuHtmlDocPrepare(),
2530
() => Documentation._manualRunMenuHtmlDocRun());
26-
pCommandBox.cmdmenu.addMenuItem(
31+
pCommandBox.cmdmenu.addMenuItemCmd(
2732
() => Documentation._manualRunMenuBeaconNamePrepare(),
2833
() => Documentation._manualRunMenuBeaconNameRun());
29-
pCommandBox.cmdmenu.addMenuItem(
34+
pCommandBox.cmdmenu.addMenuItemCmd(
3035
() => Documentation._manualRunMenuCustomHelpPrepare(),
3136
() => Documentation._manualRunMenuCustomHelpRun());
32-
33-
Documentation.DOCUMENTATION_URL = "https://docs.saltstack.com/en/latest/ref/";
34-
Documentation.EXTERNAL_LINK = Character.NO_BREAK_SPACE + Character.EXTERNAL_LINK_IMG;
35-
36-
Documentation.PROVIDERS = { };
3737
}
3838

3939
// INTERNAL DOCUMENTATION
@@ -120,7 +120,7 @@ export class Documentation {
120120
dummyCommand = "sys.doc " + cmd;
121121
}
122122

123-
const targetType = TargetType.menuTargetType._value;
123+
const targetType = TargetType.menuTargetType.getValue();
124124

125125
const func = this.commandbox.getRunParams(targetType, target, docCommand, true, false);
126126
if (func === null) {

saltgui/static/scripts/DropDown.js

+38-30
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {Utils} from "./Utils.js";
1010
// a) sets the title using pMenuItem.innerText = "xyz"
1111
// b) arranges the visibility using pMenuItem.style.display = true/false
1212
// 2: the callback function
13-
// called when the menu item is selected: (pClickEvent) => { ... }
13+
// called when the menu item is selected: () => { ... }
1414
// all menu items are re-validated when the menu pops up
1515
// when all menu items are invisible, the menu-button must be made invisible
1616
// since this can happen at any time, this cannot be done when the menu is shown
@@ -20,6 +20,8 @@ import {Utils} from "./Utils.js";
2020
// the menu. when at least one item is visible, the menu is visible
2121
// remember to call verifyApp() when that is potentially the case
2222

23+
// superclass for DropDownMenuRadio, DropDownMenuCheckBox and DropDownMenuCmd
24+
2325
export class DropDownMenu {
2426

2527
// Creates an empty dropdown menu
@@ -87,10 +89,10 @@ export class DropDownMenu {
8789
continue;
8890
}
8991

90-
const verifyCallBack = chld.verifyCallBack;
91-
if (verifyCallBack) {
92-
const title = verifyCallBack(chld);
93-
if (title === null) {
92+
const titleCallBack = chld._titleCallBack;
93+
if (titleCallBack) {
94+
const title = titleCallBack.bind(this)(chld);
95+
if (!title) {
9496
chld.style.display = "none";
9597
continue;
9698
}
@@ -106,6 +108,7 @@ export class DropDownMenu {
106108
itemsBeforeSeparator += 1;
107109
}
108110
}
111+
109112
// hide the menu when it has no visible menu-items
110113
const displayVisible = this.menuDropdown.tagName === "TD" ? "table-cell" : "inline-block";
111114
const displayInvisible = "none";
@@ -125,25 +128,49 @@ export class DropDownMenu {
125128
// function is called each time the menu opens
126129
// This allows dynamic menuitem titles (use menuitem.innerText)
127130
// or visibility (use menuitem.style.display = "none"/"inline-block")
128-
addMenuItem (pTitle, pCallBack, pValue) {
131+
addMenuItem (pValue, pTitle, pSystemCallBack, pUserCallBack) {
132+
129133
const button = Utils.createDiv("run-command-button", "...");
130-
if (pValue) {
131-
button._value = pValue;
132-
}
134+
135+
button._value = pValue;
136+
133137
if (typeof pTitle === "string") {
134138
button.innerText = DropDownMenu._sanitizeMenuItemTitle(pTitle);
135139
} else {
136-
button.verifyCallBack = pTitle;
140+
button._titleCallBack = pTitle;
137141
}
142+
138143
button.addEventListener("click", (pClickEvent) => {
144+
145+
// hide the menu
139146
pClickEvent.target.parentElement.style.display = "none";
147+
148+
// "show" the menu again after a short delay
149+
// but because the mouse is no longer hovering it,
150+
// it will actually remain invisible
140151
window.setTimeout(() => {
141152
pClickEvent.target.parentElement.style.display = "";
142153
}, 500);
143-
this._callback(pClickEvent, pCallBack, pValue);
154+
155+
this._value = pValue;
156+
157+
if (pSystemCallBack) {
158+
pSystemCallBack.bind(this)(pClickEvent.target);
159+
}
160+
161+
if (pUserCallBack) {
162+
pUserCallBack.bind(this)(pClickEvent.target);
163+
}
164+
165+
// all menu items may have become invisible
166+
this.verifyAll();
167+
144168
pClickEvent.stopPropagation();
145169
});
170+
146171
this.menuDropdownContent.appendChild(button);
172+
173+
// the menu might have become populated enough to get visible
147174
this.verifyAll();
148175
return button;
149176
}
@@ -157,11 +184,6 @@ export class DropDownMenu {
157184
this.menuDropdownContent.appendChild(div);
158185
}
159186

160-
_callback (pClickEvent, pCallBack, pValue) {
161-
this._value = pValue;
162-
pCallBack(pClickEvent);
163-
}
164-
165187
setTitle (pTitle) {
166188
// Setting the title implies that we are interested
167189
// in the menu values, rather than their actions.
@@ -172,18 +194,4 @@ export class DropDownMenu {
172194
pTitle += Character.GEAR;
173195
this.menuButton.innerText = DropDownMenu._sanitizeMenuItemTitle(pTitle);
174196
}
175-
176-
__showMenu () {
177-
this.menuDropdown.style.display = "inline-block";
178-
}
179-
180-
__hideMenu () {
181-
this.menuDropdown.style.display = "none";
182-
}
183-
184-
clearMenu () {
185-
while (this.menuDropdownContent.firstChild) {
186-
this.menuDropdownContent.removeChild(this.menuDropdownContent.firstChild);
187-
}
188-
}
189197
}
+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/* global */
2+
3+
import {Character} from "./Character.js";
4+
import {DropDownMenu} from "./DropDown.js";
5+
6+
export class DropDownMenuCheckBox extends DropDownMenu {
7+
8+
static _menuItemTitleCallBack (pMenuItem) {
9+
let prefix = "";
10+
if (pMenuItem._selected === true) {
11+
prefix = Character.HEAVY_CHECK_MARK + Character.NO_BREAK_SPACE;
12+
}
13+
return prefix + pMenuItem._title;
14+
}
15+
16+
static _menuItemActionCallBack (pMenuItem) {
17+
pMenuItem._selected = !pMenuItem._selected;
18+
}
19+
20+
addMenuItemCheckBox (pValue, pTitle, pUserCallBack) {
21+
const menuItem = super.addMenuItem(
22+
pValue,
23+
DropDownMenuCheckBox._menuItemTitleCallBack,
24+
DropDownMenuCheckBox._menuItemActionCallBack,
25+
pUserCallBack);
26+
menuItem._title = pTitle;
27+
return menuItem;
28+
}
29+
30+
isSet (pValue) {
31+
for (const menuItem of this.menuDropdownContent.childNodes) {
32+
if (menuItem._selected === true && menuItem._value === pValue) {
33+
return true;
34+
}
35+
}
36+
return false;
37+
}
38+
}

saltgui/static/scripts/DropDownCmd.js

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/* global */
2+
3+
import {DropDownMenu} from "./DropDown.js";
4+
5+
export class DropDownMenuCmd extends DropDownMenu {
6+
7+
addMenuItemCmd (pTitle, pUserCallBack) {
8+
return super.addMenuItem(
9+
null,
10+
pTitle,
11+
pUserCallBack
12+
);
13+
}
14+
}
+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/* global */
2+
3+
import {Character} from "./Character.js";
4+
import {DropDownMenu} from "./DropDown.js";
5+
6+
export class DropDownMenuRadio extends DropDownMenu {
7+
constructor (pParentElement) {
8+
super(pParentElement);
9+
this._value = null;
10+
this._defaultValue = null;
11+
}
12+
13+
getValue () {
14+
if (this._value === null) {
15+
return this._defaultValue;
16+
}
17+
return this._value;
18+
}
19+
20+
setValue (pValue) {
21+
this._value = pValue;
22+
}
23+
24+
setDefaultValue (pDefaultValue) {
25+
this._defaultValue = pDefaultValue;
26+
}
27+
28+
_menuItemTitleCallBack (pMenuItem) {
29+
let title;
30+
if (!pMenuItem._title) {
31+
title = "...";
32+
} else if (typeof pMenuItem._title === "string") {
33+
title = pMenuItem._title;
34+
} else {
35+
title = pMenuItem._title.bind(this)(pMenuItem);
36+
}
37+
38+
if (title === null) {
39+
// menu item will be hidden
40+
} else if (pMenuItem._value === this._value) {
41+
title = Character.BLACK_CIRCLE + Character.NO_BREAK_SPACE + title;
42+
} else if (this._value === null && pMenuItem._value === this._defaultValue) {
43+
title = Character.WHITE_CIRCLE + Character.NO_BREAK_SPACE + title;
44+
}
45+
return title;
46+
}
47+
48+
_menuItemActionCallBack (pMenuItem) {
49+
this._value = pMenuItem._value;
50+
let menuTitle = pMenuItem._title;
51+
if (menuTitle && typeof menuTitle !== "string") {
52+
menuTitle = menuTitle.bind(this)(pMenuItem);
53+
}
54+
this.setTitle(menuTitle);
55+
}
56+
57+
addMenuItemRadio (pValue, pTitle, pUserCallBack) {
58+
const menuItem = super.addMenuItem(
59+
pValue,
60+
this._menuItemTitleCallBack,
61+
this._menuItemActionCallBack,
62+
pUserCallBack);
63+
menuItem._value = pValue;
64+
menuItem._title = pTitle;
65+
return menuItem;
66+
}
67+
}

saltgui/static/scripts/ParseCommandLine.js

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
/* global */
2+
13
// Function to parse a commandline
24
// The line is broken into individual tokens
35
// Each token that is recognized as a JS type will get that type

0 commit comments

Comments
 (0)