2019-06-04 13:17:19 +02:00
|
|
|
import {
|
|
|
|
Position,
|
|
|
|
Size,
|
|
|
|
AnyObject,
|
|
|
|
WithModuleProps,
|
2019-08-02 12:24:47 +02:00
|
|
|
ItemMeta,
|
2019-08-14 14:31:41 +02:00
|
|
|
LinkedVisualConsoleProps,
|
|
|
|
WithAgentProps
|
2019-06-04 13:17:19 +02:00
|
|
|
} from "./lib/types";
|
2019-02-11 13:43:04 +01:00
|
|
|
import {
|
|
|
|
sizePropsDecoder,
|
|
|
|
positionPropsDecoder,
|
|
|
|
parseIntOr,
|
2019-03-08 12:51:03 +01:00
|
|
|
parseBoolean,
|
2019-04-24 15:58:33 +02:00
|
|
|
notEmptyStringOr,
|
|
|
|
replaceMacros,
|
|
|
|
humanDate,
|
2019-06-11 15:27:06 +02:00
|
|
|
humanTime,
|
|
|
|
addMovementListener,
|
2019-06-17 12:22:55 +02:00
|
|
|
debounce,
|
2019-07-12 14:00:24 +02:00
|
|
|
addResizementListener,
|
2019-07-29 11:33:11 +02:00
|
|
|
t,
|
2019-08-05 12:58:25 +02:00
|
|
|
helpTip,
|
2019-08-19 12:32:38 +02:00
|
|
|
periodSelector,
|
|
|
|
autocompleteInput
|
2019-02-11 13:43:04 +01:00
|
|
|
} from "./lib";
|
2019-06-04 13:17:19 +02:00
|
|
|
import TypedEvent, { Listener, Disposable } from "./lib/TypedEvent";
|
2019-07-12 14:00:24 +02:00
|
|
|
import { FormContainer, InputGroup } from "./Form";
|
2019-08-01 11:50:00 +02:00
|
|
|
|
|
|
|
import {
|
|
|
|
faCircleNotch,
|
|
|
|
faExclamationCircle
|
|
|
|
} from "@fortawesome/free-solid-svg-icons";
|
|
|
|
import fontAwesomeIcon from "./lib/FontAwesomeIcon";
|
2019-02-11 13:43:04 +01:00
|
|
|
|
2019-02-18 17:23:57 +01:00
|
|
|
// Enum: https://www.typescriptlang.org/docs/handbook/enums.html.
|
2019-03-08 12:51:03 +01:00
|
|
|
export const enum ItemType {
|
2019-02-18 17:23:57 +01:00
|
|
|
STATIC_GRAPH = 0,
|
|
|
|
MODULE_GRAPH = 1,
|
|
|
|
SIMPLE_VALUE = 2,
|
|
|
|
PERCENTILE_BAR = 3,
|
|
|
|
LABEL = 4,
|
|
|
|
ICON = 5,
|
|
|
|
SIMPLE_VALUE_MAX = 6,
|
|
|
|
SIMPLE_VALUE_MIN = 7,
|
|
|
|
SIMPLE_VALUE_AVG = 8,
|
|
|
|
PERCENTILE_BUBBLE = 9,
|
|
|
|
SERVICE = 10,
|
|
|
|
GROUP_ITEM = 11,
|
|
|
|
BOX_ITEM = 12,
|
|
|
|
LINE_ITEM = 13,
|
|
|
|
AUTO_SLA_GRAPH = 14,
|
|
|
|
CIRCULAR_PROGRESS_BAR = 15,
|
|
|
|
CIRCULAR_INTERIOR_PROGRESS_BAR = 16,
|
|
|
|
DONUT_GRAPH = 17,
|
|
|
|
BARS_GRAPH = 18,
|
|
|
|
CLOCK = 19,
|
|
|
|
COLOR_CLOUD = 20
|
|
|
|
}
|
|
|
|
|
2019-02-11 13:43:04 +01:00
|
|
|
// Base item properties. This interface should be extended by the item implementations.
|
2019-03-08 12:51:03 +01:00
|
|
|
export interface ItemProps extends Position, Size {
|
2019-02-11 13:43:04 +01:00
|
|
|
readonly id: number;
|
2019-03-08 12:51:03 +01:00
|
|
|
readonly type: ItemType;
|
2019-02-11 13:43:04 +01:00
|
|
|
label: string | null;
|
2019-02-18 17:23:57 +01:00
|
|
|
labelPosition: "up" | "right" | "down" | "left";
|
2019-02-11 13:43:04 +01:00
|
|
|
isLinkEnabled: boolean;
|
2019-04-09 16:07:40 +02:00
|
|
|
link: string | null;
|
2019-02-11 13:43:04 +01:00
|
|
|
isOnTop: boolean;
|
|
|
|
parentId: number | null;
|
|
|
|
aclGroupId: number | null;
|
2019-08-05 12:58:25 +02:00
|
|
|
cacheExpiration: number | null;
|
2019-02-11 13:43:04 +01:00
|
|
|
}
|
|
|
|
|
2019-07-12 14:00:24 +02:00
|
|
|
export interface ItemClickEvent {
|
|
|
|
item: VisualConsoleItem<ItemProps>;
|
2019-04-10 11:54:24 +02:00
|
|
|
nativeEvent: Event;
|
2019-02-26 17:05:30 +01:00
|
|
|
}
|
2019-02-18 17:23:57 +01:00
|
|
|
|
2019-04-08 16:36:58 +02:00
|
|
|
// FIXME: Fix type compatibility.
|
2019-07-25 17:58:37 +02:00
|
|
|
export interface ItemRemoveEvent {
|
2019-04-08 16:36:58 +02:00
|
|
|
// data: Props;
|
2019-07-25 17:58:37 +02:00
|
|
|
item: VisualConsoleItem<ItemProps>;
|
2019-04-08 16:36:58 +02:00
|
|
|
}
|
|
|
|
|
2019-06-11 17:27:22 +02:00
|
|
|
export interface ItemMovedEvent {
|
2019-06-11 16:44:19 +02:00
|
|
|
item: VisualConsoleItem<ItemProps>;
|
2019-06-11 17:27:22 +02:00
|
|
|
prevPosition: Position;
|
|
|
|
newPosition: Position;
|
2019-06-11 16:44:19 +02:00
|
|
|
}
|
|
|
|
|
2019-06-17 12:22:55 +02:00
|
|
|
export interface ItemResizedEvent {
|
|
|
|
item: VisualConsoleItem<ItemProps>;
|
|
|
|
prevSize: Size;
|
|
|
|
newSize: Size;
|
|
|
|
}
|
|
|
|
|
2019-07-30 11:20:03 +02:00
|
|
|
export interface ItemSelectionChangedEvent {
|
|
|
|
selected: boolean;
|
|
|
|
}
|
|
|
|
|
2019-07-12 14:00:24 +02:00
|
|
|
// TODO: Document
|
2019-07-29 11:33:11 +02:00
|
|
|
class LinkInputGroup extends InputGroup<Partial<ItemProps>> {
|
|
|
|
protected createContent(): HTMLElement | HTMLElement[] {
|
2019-09-26 15:26:00 +02:00
|
|
|
const generalDiv = document.createElement("div");
|
|
|
|
generalDiv.className = "div-input-group";
|
|
|
|
|
2019-07-29 11:33:11 +02:00
|
|
|
const linkLabel = document.createElement("label");
|
|
|
|
linkLabel.textContent = t("Link enabled");
|
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
const linkInputLabel = document.createElement("label");
|
|
|
|
linkInputLabel.className = "p-switch";
|
|
|
|
linkInputLabel.htmlFor = "checkbox-link";
|
|
|
|
|
2019-07-29 11:33:11 +02:00
|
|
|
const linkInputChkbx = document.createElement("input");
|
2019-09-26 15:26:00 +02:00
|
|
|
linkInputChkbx.id = "checkbox-link";
|
|
|
|
linkInputChkbx.className = "checkbox-link";
|
2019-07-29 11:33:11 +02:00
|
|
|
linkInputChkbx.type = "checkbox";
|
|
|
|
linkInputChkbx.name = "checkbox-enable-link";
|
|
|
|
linkInputChkbx.value = "1";
|
|
|
|
linkInputChkbx.checked =
|
|
|
|
this.currentData.isLinkEnabled || this.initialData.isLinkEnabled || false;
|
|
|
|
linkInputChkbx.addEventListener("change", e =>
|
|
|
|
this.updateData({
|
|
|
|
isLinkEnabled: (e.target as HTMLInputElement).checked
|
|
|
|
})
|
|
|
|
);
|
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
const spanInputLabel = document.createElement("span");
|
|
|
|
spanInputLabel.className = "p-slider";
|
|
|
|
|
|
|
|
linkInputLabel.appendChild(linkInputChkbx);
|
|
|
|
linkInputLabel.appendChild(spanInputLabel);
|
|
|
|
|
|
|
|
generalDiv.appendChild(linkLabel);
|
|
|
|
generalDiv.appendChild(linkInputLabel);
|
|
|
|
|
|
|
|
return generalDiv;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: Document
|
|
|
|
class AdvancedOptionsInputGroup extends InputGroup<Partial<ItemProps>> {
|
|
|
|
protected createContent(): HTMLElement | HTMLElement[] {
|
|
|
|
const generalDiv = document.createElement("div");
|
|
|
|
generalDiv.className = "div-input-group";
|
|
|
|
|
|
|
|
const h3 = document.createElement("h3");
|
|
|
|
h3.textContent = t("Advanced Options");
|
2019-07-29 11:33:11 +02:00
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
generalDiv.appendChild(h3);
|
2019-07-29 11:33:11 +02:00
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
return generalDiv;
|
2019-07-29 11:33:11 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: Document
|
|
|
|
class OnTopInputGroup extends InputGroup<Partial<ItemProps>> {
|
|
|
|
protected createContent(): HTMLElement | HTMLElement[] {
|
2019-09-26 15:26:00 +02:00
|
|
|
const generalDiv = document.createElement("div");
|
|
|
|
generalDiv.className = "div-input-group";
|
|
|
|
|
2019-07-29 11:33:11 +02:00
|
|
|
const onTopLabel = document.createElement("label");
|
|
|
|
onTopLabel.textContent = t("Show on top");
|
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
onTopLabel.appendChild(
|
|
|
|
helpTip(
|
|
|
|
t(
|
|
|
|
"It allows the element to be superimposed to the rest of items of the visual console"
|
|
|
|
)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
2019-07-29 11:33:11 +02:00
|
|
|
const onTopInputChkbx = document.createElement("input");
|
2019-09-26 15:26:00 +02:00
|
|
|
onTopInputChkbx.id = "checkbox-on-top";
|
|
|
|
onTopInputChkbx.className = "checkbox-on-top";
|
2019-07-29 11:33:11 +02:00
|
|
|
onTopInputChkbx.type = "checkbox";
|
|
|
|
onTopInputChkbx.name = "checkbox-show-on-top";
|
|
|
|
onTopInputChkbx.value = "1";
|
|
|
|
onTopInputChkbx.checked =
|
|
|
|
this.currentData.isOnTop || this.initialData.isOnTop || false;
|
|
|
|
onTopInputChkbx.addEventListener("change", e =>
|
|
|
|
this.updateData({
|
|
|
|
isOnTop: (e.target as HTMLInputElement).checked
|
|
|
|
})
|
|
|
|
);
|
|
|
|
|
|
|
|
const onTopInputLabel = document.createElement("label");
|
2019-09-26 15:26:00 +02:00
|
|
|
onTopInputLabel.className = "p-switch";
|
|
|
|
onTopInputLabel.htmlFor = "checkbox-on-top";
|
2019-07-29 11:33:11 +02:00
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
const spanInputLabel = document.createElement("span");
|
|
|
|
spanInputLabel.className = "p-slider";
|
|
|
|
|
|
|
|
onTopInputLabel.appendChild(onTopInputChkbx);
|
|
|
|
onTopInputLabel.appendChild(spanInputLabel);
|
2019-07-29 11:33:11 +02:00
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
generalDiv.appendChild(onTopLabel);
|
|
|
|
generalDiv.appendChild(onTopInputLabel);
|
|
|
|
|
|
|
|
return generalDiv;
|
2019-07-29 11:33:11 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: Document
|
|
|
|
class PositionInputGroup extends InputGroup<Partial<ItemProps>> {
|
2019-07-12 14:00:24 +02:00
|
|
|
protected createContent(): HTMLElement | HTMLElement[] {
|
2019-09-26 15:26:00 +02:00
|
|
|
const generalDiv = document.createElement("div");
|
|
|
|
generalDiv.className = "div-input-group";
|
2019-07-12 14:00:24 +02:00
|
|
|
const positionLabel = document.createElement("label");
|
|
|
|
positionLabel.textContent = t("Position");
|
|
|
|
|
|
|
|
const positionInputX = document.createElement("input");
|
|
|
|
positionInputX.type = "number";
|
|
|
|
positionInputX.min = "0";
|
|
|
|
positionInputX.required = true;
|
|
|
|
positionInputX.value = `${this.currentData.x || this.initialData.x || 0}`;
|
|
|
|
positionInputX.addEventListener("change", e =>
|
|
|
|
this.updateData({
|
|
|
|
x: parseIntOr((e.target as HTMLInputElement).value, 0)
|
|
|
|
})
|
|
|
|
);
|
|
|
|
|
|
|
|
const positionInputY = document.createElement("input");
|
|
|
|
positionInputY.type = "number";
|
|
|
|
positionInputY.min = "0";
|
|
|
|
positionInputY.required = true;
|
|
|
|
positionInputY.value = `${this.currentData.y || this.initialData.y || 0}`;
|
|
|
|
positionInputY.addEventListener("change", e =>
|
|
|
|
this.updateData({
|
|
|
|
y: parseIntOr((e.target as HTMLInputElement).value, 0)
|
|
|
|
})
|
|
|
|
);
|
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
generalDiv.appendChild(positionLabel);
|
|
|
|
generalDiv.appendChild(positionInputX);
|
|
|
|
generalDiv.appendChild(positionInputY);
|
2019-07-12 14:00:24 +02:00
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
return generalDiv;
|
2019-07-12 14:00:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-29 11:33:11 +02:00
|
|
|
// TODO: Document
|
|
|
|
class SizeInputGroup extends InputGroup<Partial<ItemProps>> {
|
|
|
|
protected createContent(): HTMLElement | HTMLElement[] {
|
2019-09-26 15:26:00 +02:00
|
|
|
const generalDiv = document.createElement("div");
|
|
|
|
generalDiv.className = "div-input-group";
|
2019-07-29 11:33:11 +02:00
|
|
|
const sizeLabel = document.createElement("label");
|
|
|
|
sizeLabel.textContent = t("Size");
|
|
|
|
|
|
|
|
const sizeInputWidth = document.createElement("input");
|
|
|
|
sizeInputWidth.type = "number";
|
|
|
|
sizeInputWidth.min = "0";
|
|
|
|
sizeInputWidth.required = true;
|
|
|
|
sizeInputWidth.value = `${this.currentData.width ||
|
|
|
|
this.initialData.width ||
|
|
|
|
0}`;
|
|
|
|
sizeInputWidth.addEventListener("change", e =>
|
|
|
|
this.updateData({
|
|
|
|
width: parseIntOr((e.target as HTMLInputElement).value, 0)
|
|
|
|
})
|
|
|
|
);
|
|
|
|
|
|
|
|
const sizeInputHeight = document.createElement("input");
|
|
|
|
sizeInputHeight.type = "number";
|
|
|
|
sizeInputHeight.min = "0";
|
|
|
|
sizeInputHeight.required = true;
|
|
|
|
sizeInputHeight.value = `${this.currentData.height ||
|
|
|
|
this.initialData.height ||
|
|
|
|
0}`;
|
|
|
|
sizeInputHeight.addEventListener("change", e =>
|
|
|
|
this.updateData({
|
|
|
|
height: parseIntOr((e.target as HTMLInputElement).value, 0)
|
|
|
|
})
|
|
|
|
);
|
|
|
|
|
|
|
|
sizeLabel.appendChild(
|
|
|
|
helpTip(
|
|
|
|
t(
|
|
|
|
"In order to use the original image file size, set width and height to 0."
|
|
|
|
)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
generalDiv.appendChild(sizeLabel);
|
|
|
|
generalDiv.appendChild(sizeInputWidth);
|
|
|
|
generalDiv.appendChild(sizeInputHeight);
|
|
|
|
|
|
|
|
return generalDiv;
|
2019-07-29 11:33:11 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-23 19:16:36 +02:00
|
|
|
// TODO: Document
|
|
|
|
class LabelInputGroup extends InputGroup<Partial<ItemProps>> {
|
|
|
|
protected createContent(): HTMLElement | HTMLElement[] {
|
2019-09-26 15:26:00 +02:00
|
|
|
const generalDiv = document.createElement("div");
|
|
|
|
generalDiv.className = "div-input-group";
|
2019-09-23 19:16:36 +02:00
|
|
|
const label = document.createElement("label");
|
|
|
|
label.textContent = t("Label");
|
|
|
|
|
|
|
|
//TODO: help.
|
|
|
|
label.appendChild(helpTip(t("add help")));
|
|
|
|
|
|
|
|
const labelInput = document.createElement("textarea");
|
|
|
|
labelInput.id = "tinyMCE_editor";
|
|
|
|
|
|
|
|
labelInput.value = `${this.currentData.label ||
|
|
|
|
this.initialData.label ||
|
|
|
|
""}`;
|
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
generalDiv.appendChild(label);
|
|
|
|
generalDiv.appendChild(labelInput);
|
2019-09-23 19:16:36 +02:00
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
return generalDiv;
|
2019-09-23 19:16:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-30 14:58:01 +02:00
|
|
|
/**
|
2019-07-31 11:03:13 +02:00
|
|
|
* Class to add item to the general items form
|
2019-08-06 15:01:27 +02:00
|
|
|
* This item consists of a label and a Parent select.
|
2019-07-31 11:03:13 +02:00
|
|
|
* Parent is stored in the parentId property
|
2019-07-30 14:58:01 +02:00
|
|
|
*/
|
|
|
|
class ParentInputGroup extends InputGroup<Partial<ItemProps>> {
|
|
|
|
protected createContent(): HTMLElement | HTMLElement[] {
|
2019-09-26 15:26:00 +02:00
|
|
|
const generalDiv = document.createElement("div");
|
|
|
|
generalDiv.className = "div-input-group";
|
|
|
|
|
2019-07-30 14:58:01 +02:00
|
|
|
const parentLabel = document.createElement("label");
|
|
|
|
parentLabel.textContent = t("Parent");
|
|
|
|
|
|
|
|
const parentSelect = document.createElement("select");
|
|
|
|
parentSelect.required = true;
|
|
|
|
|
|
|
|
this.requestData("parent", { id: this.initialData.id }, (error, data) => {
|
|
|
|
const optionElement = document.createElement("option");
|
|
|
|
optionElement.value = "0";
|
|
|
|
optionElement.textContent = t("None");
|
|
|
|
parentSelect.appendChild(optionElement);
|
|
|
|
|
|
|
|
if (data instanceof Array) {
|
|
|
|
data.forEach(option => {
|
|
|
|
const optionElement = document.createElement("option");
|
|
|
|
optionElement.value = option.value;
|
|
|
|
optionElement.textContent = option.text;
|
|
|
|
parentSelect.appendChild(optionElement);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
parentSelect.addEventListener("change", event => {
|
|
|
|
this.updateData({
|
|
|
|
parentId: parseIntOr((event.target as HTMLSelectElement).value, 0)
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
parentSelect.value = `${this.currentData.parentId ||
|
|
|
|
this.initialData.parentId ||
|
|
|
|
0}`;
|
|
|
|
});
|
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
generalDiv.appendChild(parentLabel);
|
|
|
|
generalDiv.appendChild(parentSelect);
|
2019-07-30 14:58:01 +02:00
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
return generalDiv;
|
2019-07-30 14:58:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-31 11:03:13 +02:00
|
|
|
/**
|
|
|
|
* Class to add item to the general items form
|
2019-08-06 15:01:27 +02:00
|
|
|
* This item consists of a label and a Acl Group type select.
|
2019-08-02 12:24:47 +02:00
|
|
|
* Acl is stored in the aclGroupId property
|
2019-07-31 11:03:13 +02:00
|
|
|
*/
|
|
|
|
class AclGroupInputGroup extends InputGroup<Partial<ItemProps>> {
|
|
|
|
protected createContent(): HTMLElement | HTMLElement[] {
|
2019-09-26 15:26:00 +02:00
|
|
|
const generalDiv = document.createElement("div");
|
|
|
|
generalDiv.className = "div-input-group";
|
|
|
|
|
2019-07-31 11:03:13 +02:00
|
|
|
const aclGroupLabel = document.createElement("label");
|
|
|
|
aclGroupLabel.textContent = t("Restrict access to group");
|
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
generalDiv.appendChild(aclGroupLabel);
|
|
|
|
|
2019-08-01 11:50:00 +02:00
|
|
|
const spinner = fontAwesomeIcon(faCircleNotch, t("Spinner"), {
|
|
|
|
size: "small",
|
|
|
|
spin: true
|
|
|
|
});
|
|
|
|
aclGroupLabel.appendChild(spinner);
|
2019-07-31 11:03:13 +02:00
|
|
|
|
|
|
|
this.requestData("acl-group", {}, (error, data) => {
|
|
|
|
// Remove Spinner.
|
2019-08-01 11:50:00 +02:00
|
|
|
spinner.remove();
|
|
|
|
|
2019-07-31 11:03:13 +02:00
|
|
|
if (error) {
|
2019-08-01 11:50:00 +02:00
|
|
|
aclGroupLabel.appendChild(
|
|
|
|
fontAwesomeIcon(faExclamationCircle, t("Error"), {
|
|
|
|
size: "small",
|
|
|
|
color: "#e63c52"
|
|
|
|
})
|
|
|
|
);
|
2019-07-31 11:03:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (data instanceof Array) {
|
|
|
|
const aclGroupSelect = document.createElement("select");
|
|
|
|
aclGroupSelect.required = true;
|
|
|
|
|
|
|
|
data.forEach(option => {
|
|
|
|
const optionElement = document.createElement("option");
|
|
|
|
optionElement.value = option.value;
|
|
|
|
// Dangerous because injection sql.
|
|
|
|
// Use textContent for innerHTML.
|
|
|
|
// Here it is used to show the depth of the groups.
|
|
|
|
optionElement.innerHTML = option.text;
|
|
|
|
aclGroupSelect.appendChild(optionElement);
|
|
|
|
});
|
|
|
|
|
|
|
|
aclGroupSelect.addEventListener("change", event => {
|
|
|
|
this.updateData({
|
|
|
|
aclGroupId: parseIntOr((event.target as HTMLSelectElement).value, 0)
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
aclGroupSelect.value = `${this.currentData.aclGroupId ||
|
|
|
|
this.initialData.aclGroupId ||
|
|
|
|
0}`;
|
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
generalDiv.appendChild(aclGroupSelect);
|
2019-07-31 11:03:13 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
return generalDiv;
|
2019-07-31 11:03:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-05 12:58:25 +02:00
|
|
|
// TODO: Document
|
|
|
|
class CacheExpirationInputGroup extends InputGroup<Partial<ItemProps>> {
|
|
|
|
protected createContent(): HTMLElement | HTMLElement[] {
|
2019-09-26 15:26:00 +02:00
|
|
|
const generalDiv = document.createElement("div");
|
|
|
|
generalDiv.className = "div-input-group";
|
|
|
|
|
2019-08-05 12:58:25 +02:00
|
|
|
const periodLabel = document.createElement("label");
|
|
|
|
periodLabel.textContent = t("Cache expiration");
|
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
generalDiv.appendChild(periodLabel);
|
|
|
|
|
2019-08-05 12:58:25 +02:00
|
|
|
const periodControl = periodSelector(
|
|
|
|
this.currentData.cacheExpiration || this.initialData.cacheExpiration || 0,
|
|
|
|
{ text: t("No cache"), value: 0 },
|
|
|
|
[
|
|
|
|
{ text: t("10 seconds"), value: 10 },
|
|
|
|
{ text: t("30 seconds"), value: 30 },
|
|
|
|
{ text: t("60 seconds"), value: 60 },
|
|
|
|
{ text: t("5 minutes"), value: 300 },
|
|
|
|
{ text: t("15 minutes"), value: 900 },
|
|
|
|
{ text: t("30 minutes"), value: 1800 },
|
|
|
|
{ text: t("1 hour"), value: 3600 }
|
|
|
|
],
|
|
|
|
value => this.updateData({ cacheExpiration: value })
|
|
|
|
);
|
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
generalDiv.appendChild(periodControl);
|
2019-08-05 12:58:25 +02:00
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
return generalDiv;
|
2019-08-05 12:58:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-02 12:24:47 +02:00
|
|
|
/**
|
|
|
|
* Class to add item to the general items form
|
2019-08-06 15:01:27 +02:00
|
|
|
* This item consists of a label and a Link console type select.
|
2019-08-02 12:24:47 +02:00
|
|
|
* Parent is stored in the parentId property
|
|
|
|
*/
|
|
|
|
export class LinkConsoleInputGroup extends InputGroup<
|
|
|
|
Partial<ItemProps & LinkedVisualConsoleProps>
|
|
|
|
> {
|
|
|
|
protected createContent(): HTMLElement | HTMLElement[] {
|
|
|
|
// Create div container.
|
|
|
|
const container = document.createElement("div");
|
2019-09-26 15:26:00 +02:00
|
|
|
container.className = "div-input-group ";
|
2019-08-02 12:24:47 +02:00
|
|
|
const lvcTypeContainer = document.createElement("div");
|
2019-09-26 15:26:00 +02:00
|
|
|
lvcTypeContainer.className = "div-input-group-inside";
|
2019-08-02 12:24:47 +02:00
|
|
|
|
|
|
|
// Create Principal element label - select.
|
|
|
|
const linkConsoleLabel = document.createElement("label");
|
|
|
|
linkConsoleLabel.textContent = t("Linked visual console ");
|
|
|
|
|
|
|
|
// Create element Spinner.
|
|
|
|
const spinner = fontAwesomeIcon(faCircleNotch, t("Spinner"), {
|
|
|
|
size: "small",
|
|
|
|
spin: true
|
|
|
|
});
|
|
|
|
linkConsoleLabel.appendChild(spinner);
|
|
|
|
|
|
|
|
// Init request
|
|
|
|
this.requestData("link-console", {}, (error, data) => {
|
|
|
|
// Remove Spinner.
|
|
|
|
spinner.remove();
|
|
|
|
|
|
|
|
// Check errors.
|
|
|
|
if (error) {
|
|
|
|
// Add img error.
|
|
|
|
linkConsoleLabel.appendChild(
|
|
|
|
fontAwesomeIcon(faExclamationCircle, t("Error"), {
|
|
|
|
size: "small",
|
|
|
|
color: "#e63c52"
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2019-08-06 15:01:27 +02:00
|
|
|
// Create principal element select
|
|
|
|
const linkConsoleSelect = document.createElement("select");
|
|
|
|
linkConsoleSelect.required = true;
|
2019-08-02 12:24:47 +02:00
|
|
|
|
2019-08-06 15:01:27 +02:00
|
|
|
// Default option principal select.
|
|
|
|
const defaultOptionElement = document.createElement("option");
|
|
|
|
defaultOptionElement.value = "0";
|
|
|
|
defaultOptionElement.textContent = t("none");
|
|
|
|
linkConsoleSelect.appendChild(defaultOptionElement);
|
2019-08-02 12:24:47 +02:00
|
|
|
|
2019-08-06 15:01:27 +02:00
|
|
|
// Check data is array
|
|
|
|
if (data instanceof Array) {
|
2019-08-02 12:24:47 +02:00
|
|
|
// Create other options for principal select.
|
|
|
|
data.forEach(option => {
|
|
|
|
let id = option.id;
|
|
|
|
// Check if metaconsole save id|nodeID.
|
|
|
|
if (option.nodeId) {
|
|
|
|
id = `${option.id}|${option.nodeId}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create option
|
|
|
|
const optionElement = document.createElement("option");
|
|
|
|
optionElement.value = id;
|
|
|
|
optionElement.textContent = option.name;
|
|
|
|
linkConsoleSelect.appendChild(optionElement);
|
|
|
|
});
|
|
|
|
|
|
|
|
// Set values.
|
|
|
|
// Principal values .
|
|
|
|
// Convert current data to string if meta id|idNode or only id if node.
|
|
|
|
let currentValue: string | undefined;
|
|
|
|
if (typeof this.currentData.linkedLayoutId !== "undefined") {
|
|
|
|
currentValue =
|
|
|
|
typeof this.currentData.linkedLayoutNodeId !== "undefined" &&
|
|
|
|
this.currentData.linkedLayoutNodeId !== 0
|
|
|
|
? `${this.currentData.linkedLayoutId}|${
|
|
|
|
this.currentData.linkedLayoutNodeId
|
|
|
|
}`
|
|
|
|
: `${this.currentData.linkedLayoutId}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Convert Initial data to string if meta id|idNode or only id if node.
|
|
|
|
let initialValue: string | undefined;
|
|
|
|
if (typeof this.initialData.linkedLayoutId !== "undefined") {
|
|
|
|
initialValue =
|
|
|
|
typeof this.initialData.linkedLayoutNodeId !== "undefined" &&
|
|
|
|
this.initialData.linkedLayoutNodeId !== 0
|
|
|
|
? `${this.initialData.linkedLayoutId}|${
|
|
|
|
this.initialData.linkedLayoutNodeId
|
|
|
|
}`
|
|
|
|
: `${this.initialData.linkedLayoutId}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
linkConsoleSelect.value = `${currentValue || initialValue || 0}`;
|
|
|
|
|
|
|
|
// Listener event change select principal.
|
|
|
|
linkConsoleSelect.addEventListener("change", event => {
|
|
|
|
// Convert value to insert data.
|
|
|
|
const linkedLayoutExtract = (event.target as HTMLSelectElement).value.split(
|
|
|
|
"|"
|
|
|
|
);
|
|
|
|
|
|
|
|
let linkedLayoutNodeId = 0;
|
|
|
|
let linkedLayoutId = 0;
|
|
|
|
if (linkedLayoutExtract instanceof Array) {
|
|
|
|
linkedLayoutId = parseIntOr(linkedLayoutExtract[0], 0);
|
|
|
|
linkedLayoutNodeId = parseIntOr(linkedLayoutExtract[1], 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update data element.
|
|
|
|
this.updateData({
|
|
|
|
linkedLayoutId: linkedLayoutId,
|
|
|
|
linkedLayoutNodeId: linkedLayoutNodeId,
|
|
|
|
linkedLayoutStatusType: "default"
|
|
|
|
});
|
|
|
|
|
|
|
|
// Add containerType to container.
|
|
|
|
lvcTypeContainer.childNodes.forEach(n => n.remove());
|
|
|
|
lvcTypeContainer.appendChild(
|
|
|
|
this.getLinkedVisualConsoleTypeSelector(linkedLayoutId)
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
// Add weight warning field.
|
|
|
|
container.appendChild(linkConsoleLabel);
|
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
// Add principal select to label.
|
|
|
|
container.appendChild(linkConsoleSelect);
|
|
|
|
|
2019-08-02 12:24:47 +02:00
|
|
|
// Add containerType to container.
|
|
|
|
lvcTypeContainer.appendChild(
|
|
|
|
this.getLinkedVisualConsoleTypeSelector(
|
|
|
|
parseIntOr(this.initialData.linkedLayoutId, 0)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
container.appendChild(lvcTypeContainer);
|
2019-08-06 15:01:27 +02:00
|
|
|
} else {
|
|
|
|
// Add principal select to label.
|
|
|
|
container.appendChild(linkConsoleLabel);
|
2019-09-26 15:26:00 +02:00
|
|
|
container.appendChild(linkConsoleSelect);
|
2019-08-02 12:24:47 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return container;
|
|
|
|
}
|
|
|
|
|
|
|
|
private getLinkedVisualConsoleTypeSelector = (
|
|
|
|
linkedLayoutId: number
|
|
|
|
): HTMLElement => {
|
|
|
|
// Create div container Type.
|
|
|
|
const containerType = document.createElement("div");
|
|
|
|
|
|
|
|
const lvcTypeContainerChild = document.createElement("div");
|
|
|
|
|
|
|
|
// Check id visual console for show label type.
|
|
|
|
if (linkedLayoutId === 0) return containerType;
|
|
|
|
|
|
|
|
// Select type link console appears when selecting a visual console
|
|
|
|
// from the main select.
|
|
|
|
// Label type link.
|
|
|
|
const typeLinkConsoleLabel = document.createElement("label");
|
|
|
|
typeLinkConsoleLabel.textContent = t(
|
|
|
|
"Type of the status calculation of the linked visual console"
|
|
|
|
);
|
|
|
|
|
|
|
|
// Select type link.
|
|
|
|
const typeLinkConsoleSelect = document.createElement("select");
|
|
|
|
typeLinkConsoleSelect.required = false;
|
|
|
|
|
|
|
|
// Array types for Linked. default | weight | service.
|
|
|
|
const arrayTypeLinked = [
|
|
|
|
{ value: "default", text: t("By default") },
|
|
|
|
{ value: "weight", text: t("By status weight") },
|
|
|
|
{ value: "service", text: t("By critical elements") }
|
|
|
|
];
|
|
|
|
|
|
|
|
// Create options select type link.
|
|
|
|
arrayTypeLinked.forEach(option => {
|
|
|
|
const typeOptionElement = document.createElement("option");
|
|
|
|
typeOptionElement.value = option.value;
|
|
|
|
typeOptionElement.textContent = option.text;
|
|
|
|
typeLinkConsoleSelect.appendChild(typeOptionElement);
|
|
|
|
});
|
|
|
|
|
|
|
|
// Set values undef is default.
|
|
|
|
let value: LinkedVisualConsoleProps["linkedLayoutStatusType"];
|
|
|
|
value =
|
|
|
|
typeof this.currentData.linkedLayoutStatusType === "undefined"
|
|
|
|
? typeof this.initialData.linkedLayoutStatusType === "undefined"
|
|
|
|
? "default"
|
|
|
|
: this.initialData.linkedLayoutStatusType
|
|
|
|
: this.currentData.linkedLayoutStatusType;
|
|
|
|
|
|
|
|
typeLinkConsoleSelect.value = value;
|
|
|
|
|
|
|
|
// Add type link.
|
|
|
|
containerType.appendChild(typeLinkConsoleLabel);
|
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
// Add select type link.
|
|
|
|
containerType.appendChild(typeLinkConsoleSelect);
|
|
|
|
|
2019-08-02 12:24:47 +02:00
|
|
|
switch (value) {
|
|
|
|
case "weight":
|
|
|
|
// Add Chil container with weight.
|
|
|
|
lvcTypeContainerChild.appendChild(
|
|
|
|
this.getLinkedVisualConsoleTypeWeihtInput()
|
|
|
|
);
|
|
|
|
break;
|
|
|
|
case "service":
|
|
|
|
// Add Chil container with weight.
|
|
|
|
lvcTypeContainerChild.appendChild(
|
|
|
|
this.getLinkedVisualConsoleTypeServiceInput()
|
|
|
|
);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add types.
|
|
|
|
containerType.appendChild(lvcTypeContainerChild);
|
|
|
|
|
|
|
|
// Listener event change select type link.
|
|
|
|
typeLinkConsoleSelect.addEventListener("change", event => {
|
|
|
|
// Convert value to insert data.
|
|
|
|
let value = (event.target as HTMLSelectElement).value;
|
|
|
|
let linkedLayoutStatusType: LinkedVisualConsoleProps["linkedLayoutStatusType"] =
|
|
|
|
value !== "weight" && value !== "service" ? "default" : value;
|
|
|
|
|
|
|
|
lvcTypeContainerChild.childNodes.forEach(n => n.remove());
|
|
|
|
|
|
|
|
switch (linkedLayoutStatusType) {
|
|
|
|
case "weight":
|
|
|
|
// Update data element.
|
|
|
|
this.updateData({
|
|
|
|
linkedLayoutStatusType,
|
|
|
|
linkedLayoutStatusTypeWeight: 0
|
|
|
|
});
|
|
|
|
|
|
|
|
// Add Chil container with weight.
|
|
|
|
lvcTypeContainerChild.appendChild(
|
|
|
|
this.getLinkedVisualConsoleTypeWeihtInput()
|
|
|
|
);
|
|
|
|
break;
|
|
|
|
case "service":
|
|
|
|
// Update data element.
|
|
|
|
this.updateData({
|
|
|
|
linkedLayoutStatusType,
|
|
|
|
linkedLayoutStatusTypeWarningThreshold: 0,
|
|
|
|
linkedLayoutStatusTypeCriticalThreshold: 0
|
|
|
|
});
|
|
|
|
|
|
|
|
// Add Chil container with weight.
|
|
|
|
lvcTypeContainerChild.appendChild(
|
|
|
|
this.getLinkedVisualConsoleTypeServiceInput()
|
|
|
|
);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
// Update data element.
|
|
|
|
this.updateData({
|
|
|
|
linkedLayoutStatusType
|
|
|
|
});
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return containerType;
|
|
|
|
};
|
|
|
|
|
|
|
|
private getLinkedVisualConsoleTypeWeihtInput = (): HTMLElement => {
|
|
|
|
// Crete div container child type.
|
|
|
|
const containerChildType = document.createElement("div");
|
|
|
|
|
|
|
|
// Input selected type = weight.
|
|
|
|
// from the select type.
|
|
|
|
// Label.
|
|
|
|
const weightLabel = document.createElement("label");
|
|
|
|
weightLabel.textContent = t("Linked visual console weight");
|
|
|
|
|
|
|
|
// Input.
|
|
|
|
const weightInput = document.createElement("input");
|
|
|
|
weightInput.type = "number";
|
|
|
|
weightInput.min = "0";
|
|
|
|
weightInput.required = true;
|
|
|
|
|
|
|
|
let currentValueWeight: number | undefined;
|
|
|
|
if (this.currentData.linkedLayoutStatusType === "weight") {
|
|
|
|
currentValueWeight = this.currentData.linkedLayoutStatusTypeWeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
let initialValueWeight: number | undefined;
|
|
|
|
if (this.initialData.linkedLayoutStatusType === "weight") {
|
|
|
|
initialValueWeight = this.initialData.linkedLayoutStatusTypeWeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
weightInput.value = `${currentValueWeight || initialValueWeight || 0}`;
|
|
|
|
|
|
|
|
weightInput.addEventListener("change", e =>
|
|
|
|
this.updateData({
|
|
|
|
linkedLayoutStatusTypeWeight: parseIntOr(
|
|
|
|
(e.target as HTMLInputElement).value,
|
|
|
|
0
|
|
|
|
)
|
|
|
|
})
|
|
|
|
);
|
|
|
|
|
|
|
|
// Add label weight.
|
|
|
|
containerChildType.appendChild(weightLabel);
|
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
// Add input weight.
|
|
|
|
containerChildType.appendChild(weightInput);
|
2019-08-02 12:24:47 +02:00
|
|
|
return containerChildType;
|
|
|
|
};
|
|
|
|
|
|
|
|
private getLinkedVisualConsoleTypeServiceInput = (): HTMLElement => {
|
|
|
|
// Crete div container child type.
|
|
|
|
const containerChildType = document.createElement("div");
|
|
|
|
|
|
|
|
// Input selected type = services.
|
|
|
|
// from the select type.
|
|
|
|
// Label.
|
|
|
|
const criticalWeightLabel = document.createElement("label");
|
|
|
|
criticalWeightLabel.textContent = t("Critical weight");
|
|
|
|
|
|
|
|
//Input.
|
|
|
|
const criticalWeightInput = document.createElement("input");
|
|
|
|
criticalWeightInput.type = "number";
|
|
|
|
criticalWeightInput.min = "0";
|
|
|
|
criticalWeightInput.required = true;
|
|
|
|
|
|
|
|
let currentValueCritical: number | undefined;
|
|
|
|
if (this.currentData.linkedLayoutStatusType === "service") {
|
|
|
|
currentValueCritical = this.currentData
|
|
|
|
.linkedLayoutStatusTypeCriticalThreshold;
|
|
|
|
}
|
|
|
|
|
|
|
|
let initialValueCritical: number | undefined;
|
|
|
|
if (this.initialData.linkedLayoutStatusType === "service") {
|
|
|
|
initialValueCritical = this.initialData
|
|
|
|
.linkedLayoutStatusTypeCriticalThreshold;
|
|
|
|
}
|
|
|
|
|
|
|
|
criticalWeightInput.value = `${currentValueCritical ||
|
|
|
|
initialValueCritical ||
|
|
|
|
0}`;
|
|
|
|
|
|
|
|
criticalWeightInput.addEventListener("change", e =>
|
|
|
|
this.updateData({
|
|
|
|
linkedLayoutStatusTypeCriticalThreshold: parseIntOr(
|
|
|
|
(e.target as HTMLInputElement).value,
|
|
|
|
0
|
|
|
|
)
|
|
|
|
})
|
|
|
|
);
|
|
|
|
|
|
|
|
// Input selected type = services.
|
|
|
|
// from the select type.
|
|
|
|
// Label.
|
|
|
|
const warningWeightLabel = document.createElement("label");
|
|
|
|
warningWeightLabel.textContent = t("Warning weight");
|
|
|
|
|
|
|
|
//Input.
|
|
|
|
const warningWeightInput = document.createElement("input");
|
|
|
|
warningWeightInput.type = "number";
|
|
|
|
warningWeightInput.min = "0";
|
|
|
|
warningWeightInput.required = true;
|
|
|
|
|
|
|
|
let currentValueWarning: number | undefined;
|
|
|
|
if (this.currentData.linkedLayoutStatusType === "service") {
|
|
|
|
currentValueWarning = this.currentData
|
|
|
|
.linkedLayoutStatusTypeWarningThreshold;
|
|
|
|
}
|
|
|
|
|
|
|
|
let initialValueWarning: number | undefined;
|
|
|
|
if (this.initialData.linkedLayoutStatusType === "service") {
|
|
|
|
initialValueWarning = this.initialData
|
|
|
|
.linkedLayoutStatusTypeWarningThreshold;
|
|
|
|
}
|
|
|
|
|
|
|
|
warningWeightInput.value = `${currentValueWarning ||
|
|
|
|
initialValueWarning ||
|
|
|
|
0}`;
|
|
|
|
|
|
|
|
warningWeightInput.addEventListener("change", e =>
|
|
|
|
this.updateData({
|
|
|
|
linkedLayoutStatusTypeWarningThreshold: parseIntOr(
|
|
|
|
(e.target as HTMLInputElement).value,
|
|
|
|
0
|
|
|
|
)
|
|
|
|
})
|
|
|
|
);
|
|
|
|
|
|
|
|
// Add label warning field.
|
|
|
|
containerChildType.appendChild(warningWeightLabel);
|
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
// Add input weight warning.
|
|
|
|
containerChildType.appendChild(warningWeightInput);
|
2019-08-02 12:24:47 +02:00
|
|
|
|
|
|
|
// Add label weight critical.
|
|
|
|
containerChildType.appendChild(criticalWeightLabel);
|
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
// Add input crital weight.
|
|
|
|
containerChildType.appendChild(criticalWeightInput);
|
|
|
|
|
2019-08-02 12:24:47 +02:00
|
|
|
return containerChildType;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2019-08-07 14:33:35 +02:00
|
|
|
interface ImageInputGroupProps {
|
|
|
|
imageSrc: string | null;
|
|
|
|
image: string | null;
|
|
|
|
}
|
|
|
|
|
2019-08-05 14:58:27 +02:00
|
|
|
/**
|
|
|
|
* Class to add item to the static Graph item form
|
2019-08-06 15:01:27 +02:00
|
|
|
* This item consists of a label and a Image select.
|
2019-08-05 14:58:27 +02:00
|
|
|
* Show Last Value is stored in the showLastValueTooltip property
|
|
|
|
*/
|
2019-08-07 14:33:35 +02:00
|
|
|
export class ImageInputGroup extends InputGroup<
|
|
|
|
Partial<ImageInputGroupProps> & {
|
|
|
|
imageKey: keyof ImageInputGroupProps;
|
|
|
|
showStatusImg?: boolean;
|
|
|
|
}
|
|
|
|
> {
|
2019-08-05 14:58:27 +02:00
|
|
|
protected createContent(): HTMLElement | HTMLElement[] {
|
2019-09-26 15:26:00 +02:00
|
|
|
const generalDiv = document.createElement("div");
|
|
|
|
generalDiv.className = "div-input-group";
|
|
|
|
|
2019-08-07 14:33:35 +02:00
|
|
|
const imageKey = this.initialData.imageKey;
|
2019-08-05 14:58:27 +02:00
|
|
|
const imageLabel = document.createElement("label");
|
|
|
|
imageLabel.textContent = t("Image");
|
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
generalDiv.appendChild(imageLabel);
|
|
|
|
|
2019-08-05 14:58:27 +02:00
|
|
|
const divImage = document.createElement("div");
|
|
|
|
|
|
|
|
// Create element Spinner.
|
|
|
|
const spinner = fontAwesomeIcon(faCircleNotch, t("Spinner"), {
|
|
|
|
size: "small",
|
|
|
|
spin: true
|
|
|
|
});
|
2019-09-26 15:26:00 +02:00
|
|
|
generalDiv.appendChild(spinner);
|
2019-08-05 14:58:27 +02:00
|
|
|
|
|
|
|
// Init request
|
|
|
|
this.requestData("image-console", {}, (error, data) => {
|
|
|
|
// Remove Spinner.
|
|
|
|
spinner.remove();
|
|
|
|
|
|
|
|
// Check errors.
|
|
|
|
if (error) {
|
|
|
|
// Add img error.
|
2019-09-26 15:26:00 +02:00
|
|
|
generalDiv.appendChild(
|
2019-08-05 14:58:27 +02:00
|
|
|
fontAwesomeIcon(faExclamationCircle, t("Error"), {
|
|
|
|
size: "small",
|
|
|
|
color: "#e63c52"
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (data instanceof Array) {
|
|
|
|
const labelSelect = document.createElement("select");
|
|
|
|
labelSelect.required = true;
|
|
|
|
|
|
|
|
data.forEach(option => {
|
|
|
|
const optionElement = document.createElement("option");
|
|
|
|
optionElement.value = option.name;
|
|
|
|
optionElement.textContent = option.name;
|
|
|
|
labelSelect.appendChild(optionElement);
|
|
|
|
});
|
|
|
|
|
|
|
|
labelSelect.addEventListener("change", event => {
|
|
|
|
const imageSrc = (event.target as HTMLSelectElement).value;
|
2019-08-07 14:33:35 +02:00
|
|
|
this.updateData({ [imageKey]: imageSrc });
|
2019-08-05 14:58:27 +02:00
|
|
|
|
|
|
|
if (imageSrc != null) {
|
|
|
|
const imageItem = data.find(item => item.name === imageSrc);
|
2019-08-07 14:33:35 +02:00
|
|
|
this.getImage(imageItem, divImage);
|
2019-08-05 14:58:27 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2019-08-07 14:33:35 +02:00
|
|
|
const valueImage = `${this.currentData[imageKey] ||
|
|
|
|
this.initialData[imageKey] ||
|
2019-08-05 14:58:27 +02:00
|
|
|
null}`;
|
|
|
|
|
|
|
|
labelSelect.value = valueImage;
|
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
generalDiv.appendChild(labelSelect);
|
2019-08-05 14:58:27 +02:00
|
|
|
|
|
|
|
if (valueImage != null) {
|
|
|
|
const imageItem = data.find(item => item.name === valueImage);
|
2019-09-26 15:26:00 +02:00
|
|
|
generalDiv.appendChild(this.getImage(imageItem, divImage));
|
2019-08-05 14:58:27 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
return generalDiv;
|
2019-08-05 14:58:27 +02:00
|
|
|
}
|
2019-08-07 14:33:35 +02:00
|
|
|
|
|
|
|
private getImage(
|
|
|
|
imageItem: HTMLImageElement,
|
|
|
|
divImage: HTMLElement
|
|
|
|
): HTMLElement {
|
|
|
|
if (imageItem) {
|
|
|
|
const deleteImg = divImage.querySelectorAll(".img-vc-elements");
|
|
|
|
deleteImg.forEach(value => {
|
|
|
|
divImage.removeChild(value);
|
|
|
|
});
|
|
|
|
|
|
|
|
if (this.initialData.showStatusImg) {
|
|
|
|
const imageTypes = ["", "_bad", "_ok", "_warning"];
|
|
|
|
imageTypes.forEach(value => {
|
|
|
|
const imagePaint = document.createElement("img");
|
|
|
|
imagePaint.alt = t("Image VC");
|
|
|
|
imagePaint.style.width = "40px";
|
|
|
|
imagePaint.style.height = "40px";
|
|
|
|
imagePaint.className = "img-vc-elements";
|
|
|
|
imagePaint.src = `${imageItem.src}${value}.png`;
|
|
|
|
divImage.appendChild(imagePaint);
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
const imagePaint = document.createElement("img");
|
|
|
|
imagePaint.alt = t("Image VC");
|
|
|
|
imagePaint.style.width = "40px";
|
|
|
|
imagePaint.style.height = "40px";
|
|
|
|
imagePaint.className = "img-vc-elements";
|
|
|
|
imagePaint.src = `${imageItem.src}.png`;
|
|
|
|
divImage.appendChild(imagePaint);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return divImage;
|
|
|
|
}
|
2019-08-05 14:58:27 +02:00
|
|
|
}
|
|
|
|
|
2019-08-19 12:32:38 +02:00
|
|
|
interface AgentAutocompleteData {
|
|
|
|
metaconsoleId?: number | null;
|
|
|
|
agentId: number;
|
|
|
|
agentName: string | null;
|
|
|
|
agentAlias: string | null;
|
|
|
|
agentDescription: string | null;
|
|
|
|
agentAddress: string | null;
|
2019-09-19 17:47:41 +02:00
|
|
|
type: number | null;
|
2019-08-19 12:32:38 +02:00
|
|
|
}
|
|
|
|
|
2019-08-14 14:31:41 +02:00
|
|
|
/**
|
|
|
|
* Class to add item to the general items form
|
|
|
|
* This item consists of a label and agent select.
|
|
|
|
* Agent and module is stored in the property
|
|
|
|
*/
|
2019-08-22 10:11:06 +02:00
|
|
|
export class AgentModuleInputGroup extends InputGroup<
|
2019-09-19 17:47:41 +02:00
|
|
|
Partial<ItemProps & WithModuleProps>
|
2019-08-22 10:11:06 +02:00
|
|
|
> {
|
2019-08-14 14:31:41 +02:00
|
|
|
protected createContent(): HTMLElement | HTMLElement[] {
|
2019-09-26 15:26:00 +02:00
|
|
|
const generalDivAutocomplete = document.createElement("div");
|
|
|
|
generalDivAutocomplete.className = "div-input-group-autocomplete-agent";
|
|
|
|
|
|
|
|
const generalDiv = document.createElement("div");
|
|
|
|
generalDiv.className = "div-input-group";
|
|
|
|
|
2019-08-14 14:31:41 +02:00
|
|
|
const agentLabel = document.createElement("label");
|
|
|
|
agentLabel.textContent = t("Agent");
|
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
generalDiv.appendChild(agentLabel);
|
|
|
|
|
2019-08-14 14:31:41 +02:00
|
|
|
const agentInput = document.createElement("input");
|
|
|
|
agentInput.type = "text";
|
|
|
|
agentInput.required = true;
|
2019-08-19 12:32:38 +02:00
|
|
|
agentInput.className = "autocomplete-agent";
|
2019-08-22 10:11:06 +02:00
|
|
|
agentInput.value = `${this.currentData.agentId ||
|
|
|
|
this.initialData.agentId ||
|
|
|
|
0}`;
|
2019-08-14 14:31:41 +02:00
|
|
|
|
2019-08-19 12:32:38 +02:00
|
|
|
const handleDataRequested = (
|
|
|
|
value: string,
|
|
|
|
done: (data: AgentAutocompleteData[]) => void
|
|
|
|
) => {
|
|
|
|
this.requestData("autocomplete-agent", { value }, (error, data) => {
|
2019-08-22 10:11:06 +02:00
|
|
|
// Remove Item agentModule.
|
|
|
|
const deleteAgentModuleItem = document.getElementById(
|
|
|
|
"select-autocomplete-agent-module"
|
|
|
|
);
|
|
|
|
if (deleteAgentModuleItem) {
|
|
|
|
deleteAgentModuleItem.remove();
|
|
|
|
}
|
|
|
|
|
2019-08-19 12:32:38 +02:00
|
|
|
if (error) {
|
|
|
|
done([]);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (data instanceof Array) {
|
|
|
|
done(
|
|
|
|
data.reduce((prev: AgentAutocompleteData[], current: AnyObject) => {
|
|
|
|
if (typeof current === "object" && current !== null) {
|
|
|
|
const agentId = parseIntOr(current.id, null);
|
|
|
|
if (agentId !== null) {
|
|
|
|
prev.push({
|
|
|
|
agentId,
|
|
|
|
agentName: notEmptyStringOr(current.name, null),
|
|
|
|
agentAlias: notEmptyStringOr(current.alias, null),
|
|
|
|
agentAddress: notEmptyStringOr(current.ip, null),
|
|
|
|
agentDescription: notEmptyStringOr(
|
|
|
|
current.agentDescription,
|
|
|
|
null
|
|
|
|
),
|
2019-09-19 17:47:41 +02:00
|
|
|
metaconsoleId: parseIntOr(current.metaconsoleId, null),
|
|
|
|
type: parseIntOr(this.initialData.type, null)
|
2019-08-19 12:32:38 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return prev;
|
|
|
|
}, [])
|
|
|
|
);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
const renderListItem = (item: AgentAutocompleteData) => {
|
|
|
|
const listItem = document.createElement("div");
|
|
|
|
listItem.textContent = item.agentAddress
|
|
|
|
? `${item.agentAlias} - ${item.agentAddress}`
|
|
|
|
: item.agentAlias;
|
|
|
|
return listItem;
|
|
|
|
};
|
|
|
|
|
|
|
|
const handleSelected = (item: AgentAutocompleteData): string => {
|
2019-09-19 13:45:13 +02:00
|
|
|
this.updateData({
|
|
|
|
agentId: item.agentId,
|
|
|
|
metaconsoleId: item.metaconsoleId
|
|
|
|
});
|
2019-08-14 14:31:41 +02:00
|
|
|
|
2019-08-19 12:32:38 +02:00
|
|
|
const selectedItem = item.agentAddress
|
|
|
|
? `${item.agentAlias} - ${item.agentAddress}`
|
|
|
|
: item.agentAlias;
|
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
generalDivAutocomplete.appendChild(this.agentModuleInput(item));
|
2019-08-22 10:11:06 +02:00
|
|
|
|
2019-08-19 12:32:38 +02:00
|
|
|
return `${selectedItem || ""}`;
|
|
|
|
};
|
|
|
|
|
2019-08-22 10:11:06 +02:00
|
|
|
const initialAutocompleteInput = this.initialData.agentAddress
|
|
|
|
? `${this.initialData.agentAlias} - ${this.initialData.agentAddress}`
|
|
|
|
: this.initialData.agentAlias;
|
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
generalDiv.appendChild(
|
2019-08-22 10:11:06 +02:00
|
|
|
autocompleteInput(
|
|
|
|
notEmptyStringOr(initialAutocompleteInput, null),
|
|
|
|
handleDataRequested,
|
|
|
|
renderListItem,
|
|
|
|
handleSelected
|
|
|
|
)
|
2019-08-19 12:32:38 +02:00
|
|
|
);
|
2019-08-14 14:31:41 +02:00
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
generalDivAutocomplete.appendChild(generalDiv);
|
|
|
|
|
2019-08-22 10:11:06 +02:00
|
|
|
const initialAgentId = parseIntOr(this.initialData.agentId, null);
|
|
|
|
if (initialAgentId !== null) {
|
2019-09-26 15:26:00 +02:00
|
|
|
generalDivAutocomplete.appendChild(
|
2019-08-22 10:11:06 +02:00
|
|
|
this.agentModuleInput({
|
|
|
|
agentId: initialAgentId,
|
|
|
|
agentName: notEmptyStringOr(this.initialData.agentName, null),
|
|
|
|
agentAlias: notEmptyStringOr(this.initialData.agentAlias, null),
|
|
|
|
agentAddress: notEmptyStringOr(this.initialData.agentAddress, null),
|
|
|
|
agentDescription: notEmptyStringOr(
|
|
|
|
this.initialData.agentDescription,
|
|
|
|
null
|
|
|
|
),
|
2019-09-19 17:47:41 +02:00
|
|
|
metaconsoleId: parseIntOr(this.initialData.metaconsoleId, null),
|
|
|
|
type: parseIntOr(this.initialData.type, null)
|
2019-08-22 10:11:06 +02:00
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
return generalDivAutocomplete;
|
2019-08-14 14:31:41 +02:00
|
|
|
}
|
|
|
|
|
2019-08-19 12:32:38 +02:00
|
|
|
private agentModuleInput(item: AgentAutocompleteData): HTMLElement {
|
2019-08-22 10:11:06 +02:00
|
|
|
// Remove Item agentModule.
|
|
|
|
const deleteAgentModuleItem = document.getElementById(
|
|
|
|
"select-autocomplete-agent-module"
|
|
|
|
);
|
|
|
|
if (deleteAgentModuleItem) {
|
|
|
|
deleteAgentModuleItem.remove();
|
|
|
|
}
|
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
const generalDiv = document.createElement("div");
|
|
|
|
generalDiv.id = "select-autocomplete-agent-module";
|
|
|
|
generalDiv.className = "div-input-group";
|
|
|
|
|
2019-08-19 12:32:38 +02:00
|
|
|
const agentModuleLabel = document.createElement("label");
|
|
|
|
agentModuleLabel.textContent = t("Module");
|
2019-08-14 14:31:41 +02:00
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
generalDiv.appendChild(agentModuleLabel);
|
|
|
|
|
2019-08-19 12:32:38 +02:00
|
|
|
// Create element Spinner.
|
2019-08-14 14:31:41 +02:00
|
|
|
const spinner = fontAwesomeIcon(faCircleNotch, t("Spinner"), {
|
|
|
|
size: "small",
|
|
|
|
spin: true
|
|
|
|
});
|
2019-08-19 12:32:38 +02:00
|
|
|
agentModuleLabel.appendChild(spinner);
|
2019-08-14 14:31:41 +02:00
|
|
|
|
2019-08-22 10:11:06 +02:00
|
|
|
// Init request.
|
|
|
|
this.requestData("autocomplete-module", { ...item }, (error, data) => {
|
2019-08-14 14:31:41 +02:00
|
|
|
// Remove Spinner.
|
2019-08-19 12:32:38 +02:00
|
|
|
spinner.remove();
|
2019-08-14 14:31:41 +02:00
|
|
|
|
2019-08-19 12:32:38 +02:00
|
|
|
// Check errors.
|
2019-08-14 14:31:41 +02:00
|
|
|
if (error) {
|
2019-08-19 12:32:38 +02:00
|
|
|
// Add img error.
|
|
|
|
agentModuleLabel.appendChild(
|
2019-08-14 14:31:41 +02:00
|
|
|
fontAwesomeIcon(faExclamationCircle, t("Error"), {
|
|
|
|
size: "small",
|
|
|
|
color: "#e63c52"
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (data instanceof Array) {
|
2019-08-19 12:32:38 +02:00
|
|
|
const agentModuleSelect = document.createElement("select");
|
|
|
|
agentModuleSelect.required = true;
|
|
|
|
|
|
|
|
data.forEach(option => {
|
|
|
|
const optionElement = document.createElement("option");
|
2019-08-22 10:11:06 +02:00
|
|
|
optionElement.value = option.moduleId;
|
|
|
|
optionElement.textContent = option.moduleName;
|
2019-08-19 12:32:38 +02:00
|
|
|
agentModuleSelect.appendChild(optionElement);
|
|
|
|
});
|
|
|
|
|
2019-08-22 10:11:06 +02:00
|
|
|
agentModuleSelect.addEventListener("change", event => {
|
|
|
|
this.updateData({
|
|
|
|
moduleId: parseIntOr((event.target as HTMLSelectElement).value, 0)
|
|
|
|
});
|
2019-08-19 12:32:38 +02:00
|
|
|
});
|
|
|
|
|
2019-08-22 10:11:06 +02:00
|
|
|
agentModuleSelect.value = `${this.currentData.moduleId ||
|
|
|
|
this.initialData.moduleId ||
|
|
|
|
0}`;
|
2019-08-19 12:32:38 +02:00
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
generalDiv.appendChild(agentModuleSelect);
|
2019-08-14 14:31:41 +02:00
|
|
|
}
|
|
|
|
});
|
2019-08-19 12:32:38 +02:00
|
|
|
|
2019-09-26 15:26:00 +02:00
|
|
|
return generalDiv;
|
2019-08-14 14:31:41 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-18 17:23:57 +01:00
|
|
|
/**
|
2019-07-29 11:33:11 +02:00
|
|
|
* Extract a valid enum value from a raw label position value.
|
2019-02-18 17:23:57 +01:00
|
|
|
* @param labelPosition Raw value.
|
|
|
|
*/
|
2019-02-26 17:05:30 +01:00
|
|
|
const parseLabelPosition = (
|
2019-05-16 11:03:11 +02:00
|
|
|
labelPosition: unknown
|
2019-03-08 12:51:03 +01:00
|
|
|
): ItemProps["labelPosition"] => {
|
2019-02-18 17:23:57 +01:00
|
|
|
switch (labelPosition) {
|
|
|
|
case "up":
|
|
|
|
case "right":
|
|
|
|
case "down":
|
|
|
|
case "left":
|
|
|
|
return labelPosition;
|
|
|
|
default:
|
|
|
|
return "down";
|
|
|
|
}
|
2019-02-11 13:43:04 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Build a valid typed object from a raw object.
|
|
|
|
* This will allow us to ensure the type safety.
|
|
|
|
*
|
|
|
|
* @param data Raw object.
|
2019-02-11 17:35:16 +01:00
|
|
|
* @return An object representing the item props.
|
2019-02-11 13:43:04 +01:00
|
|
|
* @throws Will throw a TypeError if some property
|
|
|
|
* is missing from the raw object or have an invalid type.
|
|
|
|
*/
|
2019-06-04 13:17:19 +02:00
|
|
|
export function itemBasePropsDecoder(data: AnyObject): ItemProps | never {
|
2019-02-11 13:43:04 +01:00
|
|
|
if (data.id == null || isNaN(parseInt(data.id))) {
|
|
|
|
throw new TypeError("invalid id.");
|
|
|
|
}
|
|
|
|
if (data.type == null || isNaN(parseInt(data.type))) {
|
|
|
|
throw new TypeError("invalid type.");
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
id: parseInt(data.id),
|
|
|
|
type: parseInt(data.type),
|
2019-03-08 12:51:03 +01:00
|
|
|
label: notEmptyStringOr(data.label, null),
|
2019-02-18 17:23:57 +01:00
|
|
|
labelPosition: parseLabelPosition(data.labelPosition),
|
2019-02-11 13:43:04 +01:00
|
|
|
isLinkEnabled: parseBoolean(data.isLinkEnabled),
|
2019-04-09 16:07:40 +02:00
|
|
|
link: notEmptyStringOr(data.link, null),
|
2019-02-11 13:43:04 +01:00
|
|
|
isOnTop: parseBoolean(data.isOnTop),
|
|
|
|
parentId: parseIntOr(data.parentId, null),
|
|
|
|
aclGroupId: parseIntOr(data.aclGroupId, null),
|
2019-08-05 12:58:25 +02:00
|
|
|
cacheExpiration: parseIntOr(data.cacheExpiration, null),
|
2019-02-11 13:43:04 +01:00
|
|
|
...sizePropsDecoder(data), // Object spread. It will merge the properties of the two objects.
|
|
|
|
...positionPropsDecoder(data) // Object spread. It will merge the properties of the two objects.
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2019-09-27 15:44:39 +02:00
|
|
|
//TODO: Document
|
|
|
|
export function titleItem(id: number): string {
|
|
|
|
let title = "";
|
|
|
|
switch (id) {
|
|
|
|
case ItemType.STATIC_GRAPH:
|
|
|
|
title = t("Static image");
|
|
|
|
break;
|
|
|
|
case ItemType.MODULE_GRAPH:
|
|
|
|
title = t("Module graph");
|
|
|
|
break;
|
|
|
|
case ItemType.SIMPLE_VALUE:
|
|
|
|
title = t("Simple value");
|
|
|
|
break;
|
|
|
|
case ItemType.PERCENTILE_BAR:
|
|
|
|
title = t("Percentile item");
|
|
|
|
break;
|
|
|
|
case ItemType.LABEL:
|
|
|
|
title = t("Label");
|
|
|
|
break;
|
|
|
|
case ItemType.ICON:
|
|
|
|
title = t("Icon");
|
|
|
|
break;
|
|
|
|
case ItemType.SIMPLE_VALUE_MAX:
|
|
|
|
title = t("Simple value");
|
|
|
|
break;
|
|
|
|
case ItemType.SIMPLE_VALUE_MIN:
|
|
|
|
title = t("Simple value");
|
|
|
|
break;
|
|
|
|
case ItemType.SIMPLE_VALUE_AVG:
|
|
|
|
title = t("Simple value");
|
|
|
|
break;
|
|
|
|
case ItemType.PERCENTILE_BUBBLE:
|
|
|
|
title = t("Percentile item");
|
|
|
|
break;
|
|
|
|
case ItemType.SERVICE:
|
|
|
|
title = t("Service");
|
|
|
|
break;
|
|
|
|
case ItemType.GROUP_ITEM:
|
|
|
|
title = t("Group");
|
|
|
|
break;
|
|
|
|
case ItemType.BOX_ITEM:
|
|
|
|
title = t("Box");
|
|
|
|
break;
|
|
|
|
case ItemType.LINE_ITEM:
|
|
|
|
title = t("Line");
|
|
|
|
break;
|
|
|
|
case ItemType.AUTO_SLA_GRAPH:
|
|
|
|
title = t("Auto SLA graph");
|
|
|
|
break;
|
|
|
|
case ItemType.CIRCULAR_PROGRESS_BAR:
|
|
|
|
title = t("Percentile item");
|
|
|
|
break;
|
|
|
|
case ItemType.CIRCULAR_INTERIOR_PROGRESS_BAR:
|
|
|
|
title = t("Percentile item");
|
|
|
|
break;
|
|
|
|
case ItemType.DONUT_GRAPH:
|
|
|
|
title = t("Serialized pie graph");
|
|
|
|
break;
|
|
|
|
case ItemType.BARS_GRAPH:
|
|
|
|
title = t("Bars graph");
|
|
|
|
break;
|
|
|
|
case ItemType.CLOCK:
|
|
|
|
title = t("Clock");
|
|
|
|
break;
|
|
|
|
case ItemType.COLOR_CLOUD:
|
|
|
|
title = t("Color cloud");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
title = t("Item");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return title;
|
|
|
|
}
|
|
|
|
|
2019-03-28 17:59:35 +01:00
|
|
|
/**
|
|
|
|
* Base class of the visual console items. Should be extended to use its capabilities.
|
|
|
|
*/
|
2019-03-08 12:51:03 +01:00
|
|
|
abstract class VisualConsoleItem<Props extends ItemProps> {
|
2019-02-11 13:43:04 +01:00
|
|
|
// Properties of the item.
|
2019-03-08 12:51:03 +01:00
|
|
|
private itemProps: Props;
|
2019-06-04 13:17:19 +02:00
|
|
|
// Metadata of the item.
|
|
|
|
private _metadata: ItemMeta;
|
2019-02-18 17:23:57 +01:00
|
|
|
// Reference to the DOM element which will contain the item.
|
2019-07-02 12:37:10 +02:00
|
|
|
public elementRef: HTMLElement = document.createElement("div");
|
|
|
|
public labelElementRef: HTMLElement = document.createElement("div");
|
2019-02-18 17:23:57 +01:00
|
|
|
// Reference to the DOM element which will contain the view of the item which extends this class.
|
2019-07-02 12:37:10 +02:00
|
|
|
protected childElementRef: HTMLElement = document.createElement("div");
|
2019-02-11 13:43:04 +01:00
|
|
|
// Event manager for click events.
|
2019-07-12 14:00:24 +02:00
|
|
|
private readonly clickEventManager = new TypedEvent<ItemClickEvent>();
|
|
|
|
// Event manager for double click events.
|
|
|
|
private readonly dblClickEventManager = new TypedEvent<ItemClickEvent>();
|
2019-06-11 16:44:19 +02:00
|
|
|
// Event manager for moved events.
|
|
|
|
private readonly movedEventManager = new TypedEvent<ItemMovedEvent>();
|
2019-08-14 11:52:19 +02:00
|
|
|
// Event manager for stopped movement events.
|
|
|
|
private readonly movementFinishedEventManager = new TypedEvent<
|
|
|
|
ItemMovedEvent
|
|
|
|
>();
|
2019-06-17 12:22:55 +02:00
|
|
|
// Event manager for resized events.
|
|
|
|
private readonly resizedEventManager = new TypedEvent<ItemResizedEvent>();
|
2019-08-14 11:52:19 +02:00
|
|
|
// Event manager for resize finished events.
|
|
|
|
private readonly resizeFinishedEventManager = new TypedEvent<
|
|
|
|
ItemResizedEvent
|
|
|
|
>();
|
2019-04-09 18:21:49 +02:00
|
|
|
// Event manager for remove events.
|
2019-07-25 17:58:37 +02:00
|
|
|
private readonly removeEventManager = new TypedEvent<ItemRemoveEvent>();
|
2019-07-30 11:20:03 +02:00
|
|
|
// Event manager for selection change events.
|
|
|
|
private readonly selectionChangedEventManager = new TypedEvent<
|
|
|
|
ItemSelectionChangedEvent
|
|
|
|
>();
|
2019-02-11 13:43:04 +01:00
|
|
|
// List of references to clean the event listeners.
|
|
|
|
private readonly disposables: Disposable[] = [];
|
|
|
|
|
2019-06-11 15:27:06 +02:00
|
|
|
// This function will only run the 2nd arg function after the time
|
|
|
|
// of the first arg have passed after its last execution.
|
|
|
|
private debouncedMovementSave = debounce(
|
|
|
|
500, // ms.
|
|
|
|
(x: Position["x"], y: Position["y"]) => {
|
2019-07-12 14:00:24 +02:00
|
|
|
// Update the metadata information.
|
|
|
|
// Don't use the .meta property cause we don't need DOM updates.
|
|
|
|
this._metadata.isBeingMoved = false;
|
|
|
|
|
2019-06-11 17:27:22 +02:00
|
|
|
const prevPosition = {
|
|
|
|
x: this.props.x,
|
|
|
|
y: this.props.y
|
|
|
|
};
|
|
|
|
const newPosition = {
|
|
|
|
x: x,
|
|
|
|
y: y
|
|
|
|
};
|
2019-06-17 12:22:55 +02:00
|
|
|
|
|
|
|
if (!this.positionChanged(prevPosition, newPosition)) return;
|
|
|
|
|
2019-06-11 15:27:06 +02:00
|
|
|
// Save the new position to the props.
|
|
|
|
this.move(x, y);
|
2019-06-11 16:44:19 +02:00
|
|
|
// Emit the movement event.
|
2019-08-14 11:52:19 +02:00
|
|
|
this.movementFinishedEventManager.emit({
|
2019-06-11 17:27:22 +02:00
|
|
|
item: this,
|
|
|
|
prevPosition: prevPosition,
|
|
|
|
newPosition: newPosition
|
|
|
|
});
|
2019-06-11 15:27:06 +02:00
|
|
|
}
|
|
|
|
);
|
|
|
|
// This property will store the function
|
|
|
|
// to clean the movement listener.
|
|
|
|
private removeMovement: Function | null = null;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Start the movement funtionality.
|
|
|
|
* @param element Element to move inside its container.
|
|
|
|
*/
|
|
|
|
private initMovementListener(element: HTMLElement): void {
|
|
|
|
this.removeMovement = addMovementListener(
|
|
|
|
element,
|
|
|
|
(x: Position["x"], y: Position["y"]) => {
|
2019-08-14 11:52:19 +02:00
|
|
|
const prevPosition = {
|
|
|
|
x: this.props.x,
|
|
|
|
y: this.props.y
|
|
|
|
};
|
|
|
|
const newPosition = { x, y };
|
|
|
|
|
|
|
|
if (!this.positionChanged(prevPosition, newPosition)) return;
|
|
|
|
|
2019-07-12 14:00:24 +02:00
|
|
|
// Update the metadata information.
|
|
|
|
// Don't use the .meta property cause we don't need DOM updates.
|
|
|
|
this._metadata.isBeingMoved = true;
|
2019-06-11 15:27:06 +02:00
|
|
|
// Move the DOM element.
|
|
|
|
this.moveElement(x, y);
|
2019-08-14 11:52:19 +02:00
|
|
|
// Emit the movement event.
|
|
|
|
this.movedEventManager.emit({
|
|
|
|
item: this,
|
|
|
|
prevPosition: prevPosition,
|
|
|
|
newPosition: newPosition
|
|
|
|
});
|
2019-06-11 15:27:06 +02:00
|
|
|
// Run the save function.
|
|
|
|
this.debouncedMovementSave(x, y);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* Stop the movement fun
|
|
|
|
*/
|
|
|
|
private stopMovementListener(): void {
|
|
|
|
if (this.removeMovement) {
|
|
|
|
this.removeMovement();
|
|
|
|
this.removeMovement = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-17 12:22:55 +02:00
|
|
|
// This function will only run the 2nd arg function after the time
|
|
|
|
// of the first arg have passed after its last execution.
|
|
|
|
private debouncedResizementSave = debounce(
|
|
|
|
500, // ms.
|
|
|
|
(width: Size["width"], height: Size["height"]) => {
|
2019-07-12 14:00:24 +02:00
|
|
|
// Update the metadata information.
|
|
|
|
// Don't use the .meta property cause we don't need DOM updates.
|
|
|
|
this._metadata.isBeingResized = false;
|
|
|
|
|
2019-06-17 12:22:55 +02:00
|
|
|
const prevSize = {
|
|
|
|
width: this.props.width,
|
|
|
|
height: this.props.height
|
|
|
|
};
|
2019-08-14 11:52:19 +02:00
|
|
|
const newSize = { width, height };
|
2019-06-17 12:22:55 +02:00
|
|
|
|
|
|
|
if (!this.sizeChanged(prevSize, newSize)) return;
|
|
|
|
|
|
|
|
// Save the new position to the props.
|
|
|
|
this.resize(width, height);
|
2019-08-14 11:52:19 +02:00
|
|
|
|
|
|
|
// Emit the resize finished event.
|
|
|
|
this.resizeFinishedEventManager.emit({
|
2019-06-17 12:22:55 +02:00
|
|
|
item: this,
|
|
|
|
prevSize: prevSize,
|
|
|
|
newSize: newSize
|
|
|
|
});
|
|
|
|
}
|
|
|
|
);
|
|
|
|
// This property will store the function
|
|
|
|
// to clean the resizement listener.
|
|
|
|
private removeResizement: Function | null = null;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Start the resizement funtionality.
|
|
|
|
* @param element Element to move inside its container.
|
|
|
|
*/
|
2019-06-26 11:33:45 +02:00
|
|
|
protected initResizementListener(element: HTMLElement): void {
|
2019-06-17 12:22:55 +02:00
|
|
|
this.removeResizement = addResizementListener(
|
|
|
|
element,
|
|
|
|
(width: Size["width"], height: Size["height"]) => {
|
2019-07-12 14:00:24 +02:00
|
|
|
// Update the metadata information.
|
|
|
|
// Don't use the .meta property cause we don't need DOM updates.
|
|
|
|
this._metadata.isBeingResized = true;
|
|
|
|
|
2019-06-20 11:27:08 +02:00
|
|
|
// The label it's outside the item's size, so we need
|
|
|
|
// to get rid of its size to get the real size of the
|
|
|
|
// item's content.
|
|
|
|
if (this.props.label && this.props.label.length > 0) {
|
|
|
|
const {
|
|
|
|
width: labelWidth,
|
|
|
|
height: labelHeight
|
|
|
|
} = this.labelElementRef.getBoundingClientRect();
|
|
|
|
|
|
|
|
switch (this.props.labelPosition) {
|
|
|
|
case "up":
|
|
|
|
case "down":
|
|
|
|
height -= labelHeight;
|
|
|
|
break;
|
|
|
|
case "left":
|
|
|
|
case "right":
|
|
|
|
width -= labelWidth;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-14 11:52:19 +02:00
|
|
|
const prevSize = {
|
|
|
|
width: this.props.width,
|
|
|
|
height: this.props.height
|
|
|
|
};
|
|
|
|
const newSize = { width, height };
|
|
|
|
|
|
|
|
if (!this.sizeChanged(prevSize, newSize)) return;
|
|
|
|
|
2019-06-17 12:22:55 +02:00
|
|
|
// Move the DOM element.
|
|
|
|
this.resizeElement(width, height);
|
2019-08-14 11:52:19 +02:00
|
|
|
// Emit the resizement event.
|
|
|
|
this.resizedEventManager.emit({
|
|
|
|
item: this,
|
|
|
|
prevSize,
|
|
|
|
newSize
|
|
|
|
});
|
2019-06-17 12:22:55 +02:00
|
|
|
// Run the save function.
|
|
|
|
this.debouncedResizementSave(width, height);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* Stop the resizement functionality.
|
|
|
|
*/
|
|
|
|
private stopResizementListener(): void {
|
|
|
|
if (this.removeResizement) {
|
|
|
|
this.removeResizement();
|
|
|
|
this.removeResizement = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-11 13:43:04 +01:00
|
|
|
/**
|
|
|
|
* To create a new element which will be inside the item box.
|
|
|
|
* @return Item.
|
|
|
|
*/
|
2019-04-15 17:00:06 +02:00
|
|
|
protected abstract createDomElement(): HTMLElement;
|
2019-02-11 13:43:04 +01:00
|
|
|
|
2019-07-02 12:37:10 +02:00
|
|
|
public constructor(
|
|
|
|
props: Props,
|
|
|
|
metadata: ItemMeta,
|
|
|
|
deferInit: boolean = false
|
|
|
|
) {
|
2019-01-30 12:06:35 +01:00
|
|
|
this.itemProps = props;
|
2019-06-04 13:17:19 +02:00
|
|
|
this._metadata = metadata;
|
2019-02-11 13:43:04 +01:00
|
|
|
|
2019-07-02 12:37:10 +02:00
|
|
|
if (!deferInit) this.init();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* To create and append the DOM elements.
|
|
|
|
*/
|
|
|
|
protected init(): void {
|
2019-02-11 13:43:04 +01:00
|
|
|
/*
|
|
|
|
* Get a HTMLElement which represents the container box
|
|
|
|
* of the Visual Console item. This element will manage
|
|
|
|
* all the common things like click events, show a border
|
|
|
|
* when hovered, etc.
|
|
|
|
*/
|
2019-02-18 17:23:57 +01:00
|
|
|
this.elementRef = this.createContainerDomElement();
|
2019-04-04 18:47:02 +02:00
|
|
|
this.labelElementRef = this.createLabelDomElement();
|
2019-02-11 13:43:04 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Get a HTMLElement which represents the custom view
|
|
|
|
* of the Visual Console item. This element will be
|
|
|
|
* different depending on the item implementation.
|
|
|
|
*/
|
2019-02-18 17:23:57 +01:00
|
|
|
this.childElementRef = this.createDomElement();
|
2019-02-11 13:43:04 +01:00
|
|
|
|
2019-02-18 17:23:57 +01:00
|
|
|
// Insert the elements into the container.
|
2019-07-29 11:33:11 +02:00
|
|
|
this.elementRef.appendChild(this.childElementRef);
|
|
|
|
this.elementRef.appendChild(this.labelElementRef);
|
2019-03-29 11:54:01 +01:00
|
|
|
|
|
|
|
// Resize element.
|
2019-07-02 12:37:10 +02:00
|
|
|
this.resizeElement(this.itemProps.width, this.itemProps.height);
|
2019-03-29 11:54:01 +01:00
|
|
|
// Set label position.
|
2019-07-02 12:37:10 +02:00
|
|
|
this.changeLabelPosition(this.itemProps.labelPosition);
|
2019-02-11 13:43:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* To create a new box for the visual console item.
|
|
|
|
* @return Item box.
|
|
|
|
*/
|
2019-02-18 17:23:57 +01:00
|
|
|
private createContainerDomElement(): HTMLElement {
|
2019-04-09 16:07:40 +02:00
|
|
|
let box;
|
|
|
|
if (this.props.isLinkEnabled) {
|
2019-06-11 15:27:06 +02:00
|
|
|
box = document.createElement("a") as HTMLAnchorElement;
|
2019-04-09 16:07:40 +02:00
|
|
|
if (this.props.link) box.href = this.props.link;
|
|
|
|
} else {
|
2019-06-11 15:27:06 +02:00
|
|
|
box = document.createElement("div") as HTMLDivElement;
|
2019-04-09 16:07:40 +02:00
|
|
|
}
|
|
|
|
|
2019-02-11 13:43:04 +01:00
|
|
|
box.className = "visual-console-item";
|
2019-08-09 15:19:35 +02:00
|
|
|
if (this.props.isOnTop) {
|
|
|
|
box.classList.add("is-on-top");
|
|
|
|
}
|
2019-02-18 17:23:57 +01:00
|
|
|
box.style.left = `${this.props.x}px`;
|
|
|
|
box.style.top = `${this.props.y}px`;
|
2019-07-12 14:00:24 +02:00
|
|
|
|
|
|
|
// Init the click listeners.
|
|
|
|
box.addEventListener("dblclick", e => {
|
|
|
|
if (!this.meta.isBeingMoved && !this.meta.isBeingResized) {
|
|
|
|
this.dblClickEventManager.emit({
|
|
|
|
item: this,
|
|
|
|
nativeEvent: e
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
2019-06-04 13:17:19 +02:00
|
|
|
box.addEventListener("click", e => {
|
2019-06-04 17:21:54 +02:00
|
|
|
if (this.meta.editMode) {
|
|
|
|
e.preventDefault();
|
|
|
|
e.stopPropagation();
|
2019-07-12 14:00:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!this.meta.isBeingMoved && !this.meta.isBeingResized) {
|
|
|
|
this.clickEventManager.emit({
|
|
|
|
item: this,
|
|
|
|
nativeEvent: e
|
|
|
|
});
|
2019-06-04 17:21:54 +02:00
|
|
|
}
|
2019-06-04 13:17:19 +02:00
|
|
|
});
|
2019-03-28 17:59:35 +01:00
|
|
|
|
2019-06-11 15:27:06 +02:00
|
|
|
// Metadata state.
|
|
|
|
if (this.meta.editMode) {
|
|
|
|
box.classList.add("is-editing");
|
|
|
|
// Init the movement listener.
|
|
|
|
this.initMovementListener(box);
|
2019-06-17 12:22:55 +02:00
|
|
|
// Init the resizement listener.
|
|
|
|
this.initResizementListener(box);
|
2019-06-11 15:27:06 +02:00
|
|
|
}
|
|
|
|
if (this.meta.isFetching) {
|
|
|
|
box.classList.add("is-fetching");
|
|
|
|
}
|
|
|
|
if (this.meta.isUpdating) {
|
|
|
|
box.classList.add("is-updating");
|
|
|
|
}
|
2019-07-12 14:00:24 +02:00
|
|
|
if (this.meta.isSelected) {
|
|
|
|
box.classList.add("is-selected");
|
|
|
|
}
|
2019-06-11 15:27:06 +02:00
|
|
|
|
2019-02-11 13:43:04 +01:00
|
|
|
return box;
|
2019-01-30 12:06:35 +01:00
|
|
|
}
|
|
|
|
|
2019-04-04 18:47:02 +02:00
|
|
|
/**
|
|
|
|
* To create a new label for the visual console item.
|
|
|
|
* @return Item label.
|
|
|
|
*/
|
|
|
|
protected createLabelDomElement(): HTMLElement {
|
|
|
|
const element = document.createElement("div");
|
|
|
|
element.className = "visual-console-item-label";
|
|
|
|
// Add the label if it exists.
|
2019-04-24 15:58:33 +02:00
|
|
|
const label = this.getLabelWithMacrosReplaced();
|
|
|
|
if (label.length > 0) {
|
2019-04-24 12:43:37 +02:00
|
|
|
// Ugly table we need to use to replicate the legacy style.
|
|
|
|
const table = document.createElement("table");
|
|
|
|
const row = document.createElement("tr");
|
|
|
|
const emptyRow1 = document.createElement("tr");
|
|
|
|
const emptyRow2 = document.createElement("tr");
|
|
|
|
const cell = document.createElement("td");
|
|
|
|
|
2019-04-24 15:58:33 +02:00
|
|
|
cell.innerHTML = label;
|
2019-07-29 11:33:11 +02:00
|
|
|
row.appendChild(cell);
|
|
|
|
table.appendChild(emptyRow1);
|
|
|
|
table.appendChild(row);
|
|
|
|
table.appendChild(emptyRow2);
|
2019-04-24 16:57:20 +02:00
|
|
|
table.style.textAlign = "center";
|
2019-04-24 12:43:37 +02:00
|
|
|
|
2019-04-25 09:13:06 +02:00
|
|
|
// Change the table size depending on its position.
|
|
|
|
switch (this.props.labelPosition) {
|
|
|
|
case "up":
|
|
|
|
case "down":
|
|
|
|
if (this.props.width > 0) {
|
|
|
|
table.style.width = `${this.props.width}px`;
|
|
|
|
table.style.height = null;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case "left":
|
|
|
|
case "right":
|
|
|
|
if (this.props.height > 0) {
|
|
|
|
table.style.width = null;
|
|
|
|
table.style.height = `${this.props.height}px`;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2019-04-24 12:43:37 +02:00
|
|
|
// element.innerHTML = this.props.label;
|
2019-07-29 11:33:11 +02:00
|
|
|
element.appendChild(table);
|
2019-04-04 18:47:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return element;
|
|
|
|
}
|
|
|
|
|
2019-04-24 15:58:33 +02:00
|
|
|
/**
|
|
|
|
* Return the label stored into the props with some macros replaced.
|
|
|
|
*/
|
|
|
|
protected getLabelWithMacrosReplaced(): string {
|
|
|
|
// We assert that the props may have some needed properties.
|
|
|
|
const props = this.props as Partial<WithModuleProps>;
|
|
|
|
|
|
|
|
return replaceMacros(
|
|
|
|
[
|
|
|
|
{
|
|
|
|
macro: "_date_",
|
|
|
|
value: humanDate(new Date())
|
|
|
|
},
|
|
|
|
{
|
|
|
|
macro: "_time_",
|
|
|
|
value: humanTime(new Date())
|
|
|
|
},
|
|
|
|
{
|
|
|
|
macro: "_agent_",
|
|
|
|
value: props.agentAlias != null ? props.agentAlias : ""
|
|
|
|
},
|
|
|
|
{
|
|
|
|
macro: "_agentdescription_",
|
|
|
|
value: props.agentDescription != null ? props.agentDescription : ""
|
|
|
|
},
|
|
|
|
{
|
|
|
|
macro: "_address_",
|
|
|
|
value: props.agentAddress != null ? props.agentAddress : ""
|
|
|
|
},
|
|
|
|
{
|
|
|
|
macro: "_module_",
|
|
|
|
value: props.moduleName != null ? props.moduleName : ""
|
|
|
|
},
|
|
|
|
{
|
|
|
|
macro: "_moduledescription_",
|
|
|
|
value: props.moduleDescription != null ? props.moduleDescription : ""
|
|
|
|
}
|
|
|
|
],
|
|
|
|
this.props.label || ""
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2019-04-17 12:32:08 +02:00
|
|
|
/**
|
|
|
|
* To update the content element.
|
|
|
|
* @return Item.
|
|
|
|
*/
|
|
|
|
protected updateDomElement(element: HTMLElement): void {
|
|
|
|
element.innerHTML = this.createDomElement().innerHTML;
|
|
|
|
}
|
|
|
|
|
2019-02-11 13:43:04 +01:00
|
|
|
/**
|
|
|
|
* Public accessor of the `props` property.
|
|
|
|
* @return Properties.
|
|
|
|
*/
|
2019-03-08 12:51:03 +01:00
|
|
|
public get props(): Props {
|
2019-04-11 10:04:35 +02:00
|
|
|
return { ...this.itemProps }; // Return a copy.
|
2019-01-30 12:06:35 +01:00
|
|
|
}
|
2019-02-11 13:43:04 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Public setter of the `props` property.
|
|
|
|
* If the new props are different enough than the
|
|
|
|
* stored props, a render would be fired.
|
|
|
|
* @param newProps
|
|
|
|
*/
|
2019-03-08 12:51:03 +01:00
|
|
|
public set props(newProps: Props) {
|
2019-07-02 12:37:10 +02:00
|
|
|
this.setProps(newProps);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Clasic and protected version of the setter of the `props` property.
|
|
|
|
* Useful to override it from children classes.
|
|
|
|
* @param newProps
|
|
|
|
*/
|
|
|
|
protected setProps(newProps: Props) {
|
2019-02-11 13:43:04 +01:00
|
|
|
const prevProps = this.props;
|
|
|
|
// Update the internal props.
|
|
|
|
this.itemProps = newProps;
|
|
|
|
|
|
|
|
// From this point, things which rely on this.props can access to the changes.
|
|
|
|
|
|
|
|
// Check if we should re-render.
|
2019-06-04 13:17:19 +02:00
|
|
|
if (this.shouldBeUpdated(prevProps, newProps))
|
|
|
|
this.render(prevProps, this._metadata);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Public accessor of the `meta` property.
|
|
|
|
* @return Properties.
|
|
|
|
*/
|
|
|
|
public get meta(): ItemMeta {
|
|
|
|
return { ...this._metadata }; // Return a copy.
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Public setter of the `meta` property.
|
|
|
|
* If the new meta are different enough than the
|
|
|
|
* stored meta, a render would be fired.
|
|
|
|
* @param newProps
|
|
|
|
*/
|
|
|
|
public set meta(newMetadata: ItemMeta) {
|
2019-06-24 18:39:40 +02:00
|
|
|
this.setMeta(newMetadata);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-07-16 16:24:08 +02:00
|
|
|
* Classic version of the setter of the `meta` property.
|
2019-06-24 18:39:40 +02:00
|
|
|
* Useful to override it from children classes.
|
|
|
|
* @param newProps
|
|
|
|
*/
|
2019-07-16 16:24:08 +02:00
|
|
|
public setMeta(newMetadata: Partial<ItemMeta>): void {
|
2019-06-04 13:17:19 +02:00
|
|
|
const prevMetadata = this._metadata;
|
|
|
|
// Update the internal meta.
|
2019-07-16 16:24:08 +02:00
|
|
|
this._metadata = {
|
|
|
|
...prevMetadata,
|
|
|
|
...newMetadata
|
|
|
|
};
|
2019-06-04 13:17:19 +02:00
|
|
|
|
2019-07-30 11:20:03 +02:00
|
|
|
if (
|
|
|
|
typeof newMetadata.isSelected !== "undefined" &&
|
|
|
|
prevMetadata.isSelected !== newMetadata.isSelected
|
|
|
|
) {
|
|
|
|
this.selectionChangedEventManager.emit({
|
|
|
|
selected: newMetadata.isSelected
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-06-04 13:17:19 +02:00
|
|
|
// From this point, things which rely on this.props can access to the changes.
|
|
|
|
|
|
|
|
// Check if we should re-render.
|
|
|
|
// if (this.shouldBeUpdated(prevMetadata, newMetadata))
|
|
|
|
this.render(this.itemProps, prevMetadata);
|
2019-02-11 13:43:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* To compare the previous and the new props and returns a boolean value
|
|
|
|
* in case the difference is meaningfull enough to perform DOM changes.
|
|
|
|
*
|
|
|
|
* Here, the only comparision is done by reference.
|
|
|
|
*
|
|
|
|
* Override this function to perform a different comparision depending on the item needs.
|
|
|
|
*
|
2019-03-19 10:09:18 +01:00
|
|
|
* @param prevProps
|
2019-02-11 13:43:04 +01:00
|
|
|
* @param newProps
|
|
|
|
* @return Whether the difference is meaningful enough to perform DOM changes or not.
|
|
|
|
*/
|
2019-03-19 10:09:18 +01:00
|
|
|
protected shouldBeUpdated(prevProps: Props, newProps: Props): boolean {
|
|
|
|
return prevProps !== newProps;
|
2019-02-11 13:43:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* To recreate or update the HTMLElement which represents the item into the DOM.
|
2019-02-18 17:23:57 +01:00
|
|
|
* @param prevProps If exists it will be used to only perform DOM updates instead of a full replace.
|
2019-02-11 13:43:04 +01:00
|
|
|
*/
|
2019-06-04 13:17:19 +02:00
|
|
|
public render(
|
|
|
|
prevProps: Props | null = null,
|
|
|
|
prevMeta: ItemMeta | null = null
|
|
|
|
): void {
|
2019-04-17 12:32:08 +02:00
|
|
|
this.updateDomElement(this.childElementRef);
|
2019-03-29 11:54:01 +01:00
|
|
|
|
2019-02-11 13:43:04 +01:00
|
|
|
// Move box.
|
2019-03-19 10:09:18 +01:00
|
|
|
if (!prevProps || this.positionChanged(prevProps, this.props)) {
|
|
|
|
this.moveElement(this.props.x, this.props.y);
|
2019-02-11 13:43:04 +01:00
|
|
|
}
|
|
|
|
// Resize box.
|
2019-03-19 10:09:18 +01:00
|
|
|
if (!prevProps || this.sizeChanged(prevProps, this.props)) {
|
|
|
|
this.resizeElement(this.props.width, this.props.height);
|
2019-02-11 13:43:04 +01:00
|
|
|
}
|
2019-03-28 17:59:35 +01:00
|
|
|
// Change label.
|
2019-04-24 15:58:33 +02:00
|
|
|
const oldLabelHtml = this.labelElementRef.innerHTML;
|
|
|
|
const newLabelHtml = this.createLabelDomElement().innerHTML;
|
|
|
|
if (oldLabelHtml !== newLabelHtml) {
|
|
|
|
this.labelElementRef.innerHTML = newLabelHtml;
|
|
|
|
}
|
|
|
|
// Change label position.
|
|
|
|
if (!prevProps || prevProps.labelPosition !== this.props.labelPosition) {
|
|
|
|
this.changeLabelPosition(this.props.labelPosition);
|
2019-03-29 11:54:01 +01:00
|
|
|
}
|
2019-08-09 15:19:35 +02:00
|
|
|
//Change z-index class is-on-top
|
|
|
|
if (!prevProps || prevProps.isOnTop !== this.props.isOnTop) {
|
|
|
|
if (this.props.isOnTop) {
|
|
|
|
this.elementRef.classList.add("is-on-top");
|
|
|
|
} else {
|
|
|
|
this.elementRef.classList.remove("is-on-top");
|
|
|
|
}
|
|
|
|
}
|
2019-04-09 16:07:40 +02:00
|
|
|
// Change link.
|
|
|
|
if (
|
|
|
|
prevProps &&
|
|
|
|
(prevProps.isLinkEnabled !== this.props.isLinkEnabled ||
|
|
|
|
(this.props.isLinkEnabled && prevProps.link !== this.props.link))
|
|
|
|
) {
|
|
|
|
const container = this.createContainerDomElement();
|
2019-04-29 10:56:06 +02:00
|
|
|
// Add the children of the old element.
|
2019-04-09 16:07:40 +02:00
|
|
|
container.innerHTML = this.elementRef.innerHTML;
|
2019-04-29 10:56:06 +02:00
|
|
|
// Copy the attributes.
|
|
|
|
const attrs = this.elementRef.attributes;
|
|
|
|
for (let i = 0; i < attrs.length; i++) {
|
|
|
|
if (attrs[i].nodeName !== "id") {
|
|
|
|
container.setAttributeNode(attrs[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Replace the reference.
|
2019-04-09 16:07:40 +02:00
|
|
|
if (this.elementRef.parentNode !== null) {
|
|
|
|
this.elementRef.parentNode.replaceChild(container, this.elementRef);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Changed the reference to the main element. It's ugly, but needed.
|
|
|
|
this.elementRef = container;
|
|
|
|
}
|
2019-06-04 13:17:19 +02:00
|
|
|
|
|
|
|
// Change metadata related things.
|
|
|
|
if (!prevMeta || prevMeta.editMode !== this.meta.editMode) {
|
|
|
|
if (this.meta.editMode) {
|
|
|
|
this.elementRef.classList.add("is-editing");
|
2019-06-11 15:27:06 +02:00
|
|
|
this.initMovementListener(this.elementRef);
|
2019-06-17 12:22:55 +02:00
|
|
|
this.initResizementListener(this.elementRef);
|
2019-06-04 13:17:19 +02:00
|
|
|
} else {
|
|
|
|
this.elementRef.classList.remove("is-editing");
|
2019-06-11 15:27:06 +02:00
|
|
|
this.stopMovementListener();
|
2019-06-17 12:22:55 +02:00
|
|
|
this.stopResizementListener();
|
2019-06-04 13:17:19 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!prevMeta || prevMeta.isFetching !== this.meta.isFetching) {
|
|
|
|
if (this.meta.isFetching) {
|
|
|
|
this.elementRef.classList.add("is-fetching");
|
|
|
|
} else {
|
|
|
|
this.elementRef.classList.remove("is-fetching");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!prevMeta || prevMeta.isUpdating !== this.meta.isUpdating) {
|
|
|
|
if (this.meta.isUpdating) {
|
|
|
|
this.elementRef.classList.add("is-updating");
|
2019-07-12 11:00:11 +02:00
|
|
|
|
|
|
|
const divParent = document.createElement("div");
|
|
|
|
divParent.className = "div-visual-console-spinner";
|
|
|
|
const divSpinner = document.createElement("div");
|
|
|
|
divSpinner.className = "visual-console-spinner";
|
|
|
|
divParent.appendChild(divSpinner);
|
|
|
|
this.elementRef.appendChild(divParent);
|
2019-06-04 13:17:19 +02:00
|
|
|
} else {
|
|
|
|
this.elementRef.classList.remove("is-updating");
|
2019-07-12 11:00:11 +02:00
|
|
|
|
|
|
|
const div = this.elementRef.querySelector(
|
|
|
|
".div-visual-console-spinner"
|
|
|
|
);
|
|
|
|
if (div !== null) {
|
|
|
|
const parent = div.parentElement;
|
|
|
|
if (parent !== null) {
|
|
|
|
parent.removeChild(div);
|
|
|
|
}
|
|
|
|
}
|
2019-06-04 13:17:19 +02:00
|
|
|
}
|
|
|
|
}
|
2019-07-12 14:00:24 +02:00
|
|
|
if (!prevMeta || prevMeta.isSelected !== this.meta.isSelected) {
|
|
|
|
if (this.meta.isSelected) {
|
|
|
|
this.elementRef.classList.add("is-selected");
|
|
|
|
} else {
|
|
|
|
this.elementRef.classList.remove("is-selected");
|
|
|
|
}
|
|
|
|
}
|
2019-02-11 13:43:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* To remove the event listeners and the elements from the DOM.
|
|
|
|
*/
|
2019-02-26 17:05:30 +01:00
|
|
|
public remove(): void {
|
2019-04-08 16:36:58 +02:00
|
|
|
// Call the remove event.
|
2019-07-25 17:58:37 +02:00
|
|
|
this.removeEventManager.emit({ item: this });
|
2019-02-11 13:43:04 +01:00
|
|
|
// Event listeners.
|
2019-04-08 16:36:58 +02:00
|
|
|
this.disposables.forEach(disposable => {
|
|
|
|
try {
|
|
|
|
disposable.dispose();
|
|
|
|
} catch (ignored) {} // eslint-disable-line no-empty
|
|
|
|
});
|
2019-02-11 13:43:04 +01:00
|
|
|
// VisualConsoleItem DOM element.
|
2019-02-18 17:23:57 +01:00
|
|
|
this.elementRef.remove();
|
2019-02-11 13:43:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-03-19 10:09:18 +01:00
|
|
|
* Compare the previous and the new position and return
|
|
|
|
* a boolean value in case the position changed.
|
|
|
|
* @param prevPosition
|
|
|
|
* @param newPosition
|
|
|
|
* @return Whether the position changed or not.
|
|
|
|
*/
|
|
|
|
protected positionChanged(
|
|
|
|
prevPosition: Position,
|
|
|
|
newPosition: Position
|
|
|
|
): boolean {
|
|
|
|
return prevPosition.x !== newPosition.x || prevPosition.y !== newPosition.y;
|
|
|
|
}
|
|
|
|
|
2019-03-29 11:54:01 +01:00
|
|
|
/**
|
|
|
|
* Move the label around the item content.
|
|
|
|
* @param position Label position.
|
|
|
|
*/
|
|
|
|
protected changeLabelPosition(position: Props["labelPosition"]): void {
|
|
|
|
switch (position) {
|
|
|
|
case "up":
|
|
|
|
this.elementRef.style.flexDirection = "column-reverse";
|
|
|
|
break;
|
|
|
|
case "left":
|
|
|
|
this.elementRef.style.flexDirection = "row-reverse";
|
|
|
|
break;
|
|
|
|
case "right":
|
|
|
|
this.elementRef.style.flexDirection = "row";
|
|
|
|
break;
|
|
|
|
case "down":
|
|
|
|
default:
|
|
|
|
this.elementRef.style.flexDirection = "column";
|
|
|
|
break;
|
|
|
|
}
|
2019-04-24 14:36:59 +02:00
|
|
|
|
|
|
|
// Ugly table to show the label as its legacy counterpart.
|
|
|
|
const tables = this.labelElementRef.getElementsByTagName("table");
|
|
|
|
const table = tables.length > 0 ? tables.item(0) : null;
|
2019-04-25 09:13:06 +02:00
|
|
|
// Change the table size depending on its position.
|
2019-04-24 14:36:59 +02:00
|
|
|
if (table) {
|
|
|
|
switch (this.props.labelPosition) {
|
|
|
|
case "up":
|
|
|
|
case "down":
|
|
|
|
if (this.props.width > 0) {
|
|
|
|
table.style.width = `${this.props.width}px`;
|
|
|
|
table.style.height = null;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case "left":
|
|
|
|
case "right":
|
|
|
|
if (this.props.height > 0) {
|
|
|
|
table.style.width = null;
|
|
|
|
table.style.height = `${this.props.height}px`;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2019-03-29 11:54:01 +01:00
|
|
|
}
|
|
|
|
|
2019-03-19 10:09:18 +01:00
|
|
|
/**
|
|
|
|
* Move the DOM container.
|
2019-02-11 13:43:04 +01:00
|
|
|
* @param x Horizontal axis position.
|
|
|
|
* @param y Vertical axis position.
|
|
|
|
*/
|
2019-03-19 10:09:18 +01:00
|
|
|
protected moveElement(x: number, y: number): void {
|
2019-02-18 17:23:57 +01:00
|
|
|
this.elementRef.style.left = `${x}px`;
|
|
|
|
this.elementRef.style.top = `${y}px`;
|
2019-02-11 13:43:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-03-19 10:09:18 +01:00
|
|
|
* Update the position into the properties and move the DOM container.
|
|
|
|
* @param x Horizontal axis position.
|
|
|
|
* @param y Vertical axis position.
|
2019-02-11 13:43:04 +01:00
|
|
|
*/
|
2019-03-19 10:09:18 +01:00
|
|
|
public move(x: number, y: number): void {
|
|
|
|
this.moveElement(x, y);
|
|
|
|
this.itemProps = {
|
|
|
|
...this.props, // Object spread: http://es6-features.org/#SpreadOperator
|
|
|
|
x,
|
|
|
|
y
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Compare the previous and the new size and return
|
|
|
|
* a boolean value in case the size changed.
|
|
|
|
* @param prevSize
|
|
|
|
* @param newSize
|
|
|
|
* @return Whether the size changed or not.
|
|
|
|
*/
|
|
|
|
protected sizeChanged(prevSize: Size, newSize: Size): boolean {
|
|
|
|
return (
|
|
|
|
prevSize.width !== newSize.width || prevSize.height !== newSize.height
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-03-28 17:59:35 +01:00
|
|
|
* Resize the DOM content container.
|
2019-03-19 10:09:18 +01:00
|
|
|
* @param width
|
|
|
|
* @param height
|
|
|
|
*/
|
|
|
|
protected resizeElement(width: number, height: number): void {
|
2019-03-29 11:54:01 +01:00
|
|
|
// The most valuable size is the content size.
|
2019-04-08 12:54:29 +02:00
|
|
|
this.childElementRef.style.width = width > 0 ? `${width}px` : null;
|
|
|
|
this.childElementRef.style.height = height > 0 ? `${height}px` : null;
|
2019-06-24 18:24:01 +02:00
|
|
|
|
|
|
|
if (this.props.label && this.props.label.length > 0) {
|
|
|
|
// Ugly table to show the label as its legacy counterpart.
|
|
|
|
const tables = this.labelElementRef.getElementsByTagName("table");
|
|
|
|
const table = tables.length > 0 ? tables.item(0) : null;
|
|
|
|
|
|
|
|
if (table) {
|
|
|
|
switch (this.props.labelPosition) {
|
|
|
|
case "up":
|
|
|
|
case "down":
|
|
|
|
table.style.width = width > 0 ? `${width}px` : null;
|
|
|
|
break;
|
|
|
|
case "left":
|
|
|
|
case "right":
|
|
|
|
table.style.height = height > 0 ? `${height}px` : null;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-02-11 13:43:04 +01:00
|
|
|
}
|
|
|
|
|
2019-03-19 10:09:18 +01:00
|
|
|
/**
|
|
|
|
* Update the size into the properties and resize the DOM container.
|
|
|
|
* @param width
|
|
|
|
* @param height
|
|
|
|
*/
|
|
|
|
public resize(width: number, height: number): void {
|
|
|
|
this.resizeElement(width, height);
|
|
|
|
this.itemProps = {
|
|
|
|
...this.props, // Object spread: http://es6-features.org/#SpreadOperator
|
|
|
|
width,
|
|
|
|
height
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2019-02-11 13:43:04 +01:00
|
|
|
/**
|
|
|
|
* To add an event handler to the click of the linked visual console elements.
|
|
|
|
* @param listener Function which is going to be executed when a linked console is clicked.
|
|
|
|
*/
|
2019-07-12 14:00:24 +02:00
|
|
|
public onClick(listener: Listener<ItemClickEvent>): Disposable {
|
2019-02-11 13:43:04 +01:00
|
|
|
/*
|
|
|
|
* The '.on' function returns a function which will clean the event
|
|
|
|
* listener when executed. We store all the 'dispose' functions to
|
|
|
|
* call them when the item should be cleared.
|
|
|
|
*/
|
2019-04-08 16:36:58 +02:00
|
|
|
const disposable = this.clickEventManager.on(listener);
|
|
|
|
this.disposables.push(disposable);
|
|
|
|
|
|
|
|
return disposable;
|
|
|
|
}
|
|
|
|
|
2019-07-12 14:00:24 +02:00
|
|
|
/**
|
|
|
|
* To add an event handler to the double click of the linked visual console elements.
|
|
|
|
* @param listener Function which is going to be executed when a linked console is double clicked.
|
|
|
|
*/
|
|
|
|
public onDblClick(listener: Listener<ItemClickEvent>): Disposable {
|
|
|
|
/*
|
|
|
|
* The '.on' function returns a function which will clean the event
|
|
|
|
* listener when executed. We store all the 'dispose' functions to
|
|
|
|
* call them when the item should be cleared.
|
|
|
|
*/
|
|
|
|
const disposable = this.dblClickEventManager.on(listener);
|
|
|
|
this.disposables.push(disposable);
|
|
|
|
|
|
|
|
return disposable;
|
|
|
|
}
|
|
|
|
|
2019-06-11 16:44:19 +02:00
|
|
|
/**
|
|
|
|
* To add an event handler to the movement of visual console elements.
|
|
|
|
* @param listener Function which is going to be executed when a linked console is moved.
|
|
|
|
*/
|
|
|
|
public onMoved(listener: Listener<ItemMovedEvent>): Disposable {
|
|
|
|
/*
|
|
|
|
* The '.on' function returns a function which will clean the event
|
|
|
|
* listener when executed. We store all the 'dispose' functions to
|
|
|
|
* call them when the item should be cleared.
|
|
|
|
*/
|
|
|
|
const disposable = this.movedEventManager.on(listener);
|
|
|
|
this.disposables.push(disposable);
|
|
|
|
|
|
|
|
return disposable;
|
|
|
|
}
|
|
|
|
|
2019-08-14 11:52:19 +02:00
|
|
|
/**
|
|
|
|
* To add an event handler to the movement stopped of visual console elements.
|
|
|
|
* @param listener Function which is going to be executed when a linked console's movement is finished.
|
|
|
|
*/
|
|
|
|
public onMovementFinished(listener: Listener<ItemMovedEvent>): Disposable {
|
|
|
|
/*
|
|
|
|
* The '.on' function returns a function which will clean the event
|
|
|
|
* listener when executed. We store all the 'dispose' functions to
|
|
|
|
* call them when the item should be cleared.
|
|
|
|
*/
|
|
|
|
const disposable = this.movementFinishedEventManager.on(listener);
|
|
|
|
this.disposables.push(disposable);
|
|
|
|
|
|
|
|
return disposable;
|
|
|
|
}
|
|
|
|
|
2019-06-17 12:22:55 +02:00
|
|
|
/**
|
|
|
|
* To add an event handler to the resizement of visual console elements.
|
|
|
|
* @param listener Function which is going to be executed when a linked console is moved.
|
|
|
|
*/
|
|
|
|
public onResized(listener: Listener<ItemResizedEvent>): Disposable {
|
|
|
|
/*
|
|
|
|
* The '.on' function returns a function which will clean the event
|
|
|
|
* listener when executed. We store all the 'dispose' functions to
|
|
|
|
* call them when the item should be cleared.
|
|
|
|
*/
|
|
|
|
const disposable = this.resizedEventManager.on(listener);
|
|
|
|
this.disposables.push(disposable);
|
|
|
|
|
|
|
|
return disposable;
|
|
|
|
}
|
|
|
|
|
2019-08-14 11:52:19 +02:00
|
|
|
/**
|
|
|
|
* To add an event handler to the resizement finish of visual console elements.
|
|
|
|
* @param listener Function which is going to be executed when a linked console is finished resizing.
|
|
|
|
*/
|
|
|
|
public onResizeFinished(listener: Listener<ItemResizedEvent>): Disposable {
|
|
|
|
/*
|
|
|
|
* The '.on' function returns a function which will clean the event
|
|
|
|
* listener when executed. We store all the 'dispose' functions to
|
|
|
|
* call them when the item should be cleared.
|
|
|
|
*/
|
|
|
|
const disposable = this.resizeFinishedEventManager.on(listener);
|
|
|
|
this.disposables.push(disposable);
|
|
|
|
|
|
|
|
return disposable;
|
|
|
|
}
|
|
|
|
|
2019-04-08 16:36:58 +02:00
|
|
|
/**
|
|
|
|
* To add an event handler to the removal of the item.
|
|
|
|
* @param listener Function which is going to be executed when a item is removed.
|
|
|
|
*/
|
2019-07-25 17:58:37 +02:00
|
|
|
public onRemove(listener: Listener<ItemRemoveEvent>): Disposable {
|
2019-04-08 16:36:58 +02:00
|
|
|
/*
|
|
|
|
* The '.on' function returns a function which will clean the event
|
|
|
|
* listener when executed. We store all the 'dispose' functions to
|
|
|
|
* call them when the item should be cleared.
|
|
|
|
*/
|
|
|
|
const disposable = this.removeEventManager.on(listener);
|
|
|
|
this.disposables.push(disposable);
|
|
|
|
|
|
|
|
return disposable;
|
2019-02-11 13:43:04 +01:00
|
|
|
}
|
2019-07-29 11:33:11 +02:00
|
|
|
|
2019-07-30 11:20:03 +02:00
|
|
|
/**
|
|
|
|
* To add an event handler to item selection.
|
|
|
|
* @param listener Function which is going to be executed when a item is removed.
|
|
|
|
*/
|
2019-08-08 11:05:21 +02:00
|
|
|
public onSelectionChanged(
|
2019-07-30 11:20:03 +02:00
|
|
|
listener: Listener<ItemSelectionChangedEvent>
|
|
|
|
): Disposable {
|
|
|
|
/*
|
|
|
|
* The '.on' function returns a function which will clean the event
|
|
|
|
* listener when executed. We store all the 'dispose' functions to
|
|
|
|
* call them when the item should be cleared.
|
|
|
|
*/
|
|
|
|
const disposable = this.selectionChangedEventManager.on(listener);
|
|
|
|
this.disposables.push(disposable);
|
|
|
|
|
|
|
|
return disposable;
|
|
|
|
}
|
|
|
|
|
2019-07-29 11:33:11 +02:00
|
|
|
// TODO: Document
|
|
|
|
public getFormContainer(): FormContainer {
|
2019-07-30 09:33:15 +02:00
|
|
|
return new FormContainer(
|
2019-09-27 15:44:39 +02:00
|
|
|
titleItem(this.props.type),
|
2019-07-30 09:33:15 +02:00
|
|
|
[
|
|
|
|
new SizeInputGroup("size", this.props),
|
2019-09-26 15:26:00 +02:00
|
|
|
new LabelInputGroup("label", this.props),
|
2019-07-30 09:33:15 +02:00
|
|
|
new LinkInputGroup("link", this.props),
|
2019-07-30 14:58:01 +02:00
|
|
|
new OnTopInputGroup("show-on-top", this.props),
|
2019-09-26 15:26:00 +02:00
|
|
|
new AdvancedOptionsInputGroup("advanced-options", this.props),
|
|
|
|
new PositionInputGroup("position", this.props),
|
2019-07-31 11:03:13 +02:00
|
|
|
new ParentInputGroup("parent", this.props),
|
2019-08-05 12:58:25 +02:00
|
|
|
new AclGroupInputGroup("acl-group", this.props),
|
|
|
|
new CacheExpirationInputGroup("cache-expiration", this.props)
|
2019-07-30 09:33:15 +02:00
|
|
|
],
|
2019-08-05 12:58:25 +02:00
|
|
|
[
|
|
|
|
"size",
|
2019-09-26 15:26:00 +02:00
|
|
|
"label",
|
2019-08-05 12:58:25 +02:00
|
|
|
"link",
|
|
|
|
"show-on-top",
|
2019-09-26 15:26:00 +02:00
|
|
|
"advanced-options",
|
|
|
|
"position",
|
2019-08-05 12:58:25 +02:00
|
|
|
"parent",
|
|
|
|
"acl-group",
|
|
|
|
"cache-expiration"
|
|
|
|
]
|
2019-07-30 09:33:15 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
//return VisualConsoleItem.getFormContainer(this.props);
|
2019-07-29 11:33:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: Document
|
|
|
|
public static getFormContainer(props: Partial<ItemProps>): FormContainer {
|
|
|
|
return new FormContainer(
|
|
|
|
t("Item"),
|
|
|
|
[
|
|
|
|
new SizeInputGroup("size", props),
|
2019-09-26 15:26:00 +02:00
|
|
|
new LabelInputGroup("label", props),
|
2019-07-29 11:33:11 +02:00
|
|
|
new LinkInputGroup("link", props),
|
2019-07-30 14:58:01 +02:00
|
|
|
new OnTopInputGroup("show-on-top", props),
|
2019-09-26 15:26:00 +02:00
|
|
|
new AdvancedOptionsInputGroup("advanced-options", props),
|
|
|
|
new PositionInputGroup("position", props),
|
2019-07-31 11:03:13 +02:00
|
|
|
new ParentInputGroup("parent", props),
|
2019-08-05 12:58:25 +02:00
|
|
|
new AclGroupInputGroup("acl-group", props),
|
|
|
|
new CacheExpirationInputGroup("cache-expiration", props)
|
2019-07-29 11:33:11 +02:00
|
|
|
],
|
2019-08-05 12:58:25 +02:00
|
|
|
[
|
|
|
|
"size",
|
2019-09-26 15:26:00 +02:00
|
|
|
"label",
|
2019-08-05 12:58:25 +02:00
|
|
|
"link",
|
|
|
|
"show-on-top",
|
2019-09-26 15:26:00 +02:00
|
|
|
"advanced-options",
|
|
|
|
"position",
|
2019-08-05 12:58:25 +02:00
|
|
|
"parent",
|
|
|
|
"acl-group",
|
|
|
|
"cache-expiration"
|
|
|
|
]
|
2019-07-29 11:33:11 +02:00
|
|
|
);
|
|
|
|
}
|
2019-01-30 12:06:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
export default VisualConsoleItem;
|