UNPKG

globular_admin

Version:
670 lines (559 loc) 25.1 kB
import { Panel } from './panel'; import { randomUUID } from './utility'; /** * That represent a single configuration information ex. * Domain -> globular3.globular.app */ export class ConfigurationLine { protected id: string; // The panel inside where the line is display protected panel: ConfigurationPanel; // Must the name in the IConfig. private name: string; // The div that contain the line. private _content: any; public get content(): any { return this._content; } public set content(value: any) { this._content = value; } // The div that display non-editable values. protected valueDiv: any; // The div that play editable values. protected valueEditor: any; private _label: any; public get label(): any { return this._label; } public set label(value: any) { this._label = value; } getValueEditor(): any { return this.valueEditor; } constructor(panel: ConfigurationPanel, name: string, label: string, content: any) { this.id = randomUUID() this.name = name; this.content = content; this.panel = panel; // Name will be use if no label was given. if (label == undefined) { label = this.name } // Now I will create the part label of the interface. this.content = content.appendElement({ "tag": "div", "class": "row" }).down() this.label = this.content.appendElement({ "tag": "div", "class": "col s12 m4", "style": "height: 100%", "innerHtml": label }).down() } // Return the configuration values. public getValue(): any { return this.panel.config[this.name] } // Set the configuration values. public setValue(v: any) { this.panel.config[this.name] = v } /** * Set the value of the configuration with the value contain in the editor. */ public set() { this.setValue(this.valueEditor.getValue()) this.valueDiv.setValue(this.valueEditor.getValue()) } /** * Reset the value of the configuration with it initial value. */ public reset() { this.valueEditor.setValue(this.getValue()) this.valueDiv.setValue(this.getValue()) } /** * Non editable mode */ lock() { this.valueEditor.element.style.display = "none" this.valueDiv.element.style.display = "" } /** * Editable mode. */ unlock() { if(this.valueEditor!=undefined){ this.valueEditor.element.style.display = "" this.valueDiv.element.style.display = "none" } } /** * Hide the line */ hide() { this.content.element.style.display = "none"; } /** * Show the line. */ show() { this.content.element.style.display = ""; } } export class ConfigurationEnum extends ConfigurationLine { constructor(panel: ConfigurationPanel, name: string, options: Array<string>, label: string, content: any, numericIndex: boolean) { super(panel, name, label, content); let value = this.getValue() if (value == null) { return } // Set the value div. this.valueDiv = this.content.appendElement({ "tag": "div", "id": this.id + "_" + name + "_div", class: "col s12 m8", "innerHtml": value.toString() }).down() // Set the value editor. this.valueEditor = this.content.appendElement({ "tag": "select", "id": this.id + "_" + name + "_select", "style": "display: none;", class: "browser-default col s12 m8" }).down() this.valueEditor.isNumeric = numericIndex; let i: number; for (i = 0; i < options.length; i++) { if (!numericIndex) { this.valueEditor.appendElement({ tag: "option", value: options[i], innerHtml: options[i] }).down() } else { this.valueEditor.appendElement({ tag: "option", value: i, innerHtml: options[i] }).down() } } M.FormSelect.init(this.valueEditor.element) if (numericIndex == true) { this.valueEditor.element.selectedIndex = value } else { this.valueEditor.element.selectedIndex = options.indexOf(value) } this.valueEditor.element.onchange = () => { // set the value in the interface. let value = this.valueEditor.getValue() this.valueDiv.setValue(value) this.panel.hasChange() } // Return the value of the input. this.valueEditor.getValue = () => { let value = this.valueEditor.element.value if (this.valueEditor.isNumeric == true) { value = parseInt(value) } return value } // Return the value of the input. this.valueEditor.setValue = function (v: any) { this.element.value = v } // Return the value of the input. this.valueDiv.setValue = function (v: any) { this.element.innerHTML = v } } } export class ConfigurationTextLine extends ConfigurationLine { constructor(panel: ConfigurationPanel, name: string, label: string, content: any, type?: string, step?: number, min?: number, max?: number) { super(panel, name, label, content); let value = this.getValue() if (value == null) { return } // Type can be any type that input box can support. if (type == undefined) { type = "text" } if (value == undefined) { return } // Set the value div. this.valueDiv = this.content.appendElement({ "tag": "div", "id": this.id + "_div", "class": "col s12 m8", "innerHtml": value.toString() }).down() // Set the value editor. this.valueEditor = this.content.appendElement({ "tag": "input", "id": this.id + "_input", "style": "display: none;", "class": "col s12 m8", "type": type, "value": value }).down() this.valueEditor.element.onchange = () => { // set the value in the interface. this.valueDiv.setValue(this.valueEditor.getValue()) this.panel.hasChange() } // Return the value of the input. this.valueEditor.getValue = function () { if (type == "number") { return parseFloat(this.element.value) } return this.element.value } // Return the value of the input. this.valueEditor.setValue = function (v: any) { this.element.value = v } // Return the value of the input. this.valueDiv.setValue = function (v: any) { this.element.innerHTML = v } } } export class ConfigurationLongTextLine extends ConfigurationLine { constructor(panel: ConfigurationPanel, name: string, label: string, content: any) { super(panel, name, label, content); let value = this.getValue() if (value == null) { return } if (value == undefined) { return } // Set the value div. this.valueDiv = this.content.appendElement({ tag: "div", "id": this.id + "_div", class: "col s12 m8", innerHtml: value.toString() }).down() // Set the value editor. this.valueEditor = this.content.appendElement({ tag: "textarea", "id": this.id + "_input", style: "display: none; padding: 5px; height: 100px;", rows:"9", type:"text", class: "col s12 m8", innerHtml: value }).down() this.valueEditor.element.onchange = () => { // set the value in the interface. this.valueDiv.setValue(this.valueEditor.getValue()) this.panel.hasChange() } // Return the value of the input. this.valueEditor.getValue = function () { return this.element.value } // Return the value of the input. this.valueEditor.setValue = function (v: any) { this.element.value = v } // Return the value of the input. this.valueDiv.setValue = function (v: any) { this.element.innerHTML = v } } } export class ConfigurationToggleLine extends ConfigurationLine { constructor(panel: ConfigurationPanel, name: string, label: string, content: any, labels: Array<string>) { super(panel, name, label, content); let value = this.getValue() if (value == null) { return } // Set the value div. this.valueDiv = this.content.appendElement({ "tag": "div", "id": this.id + "_" + name + "_div", "class": "col s12 m8", "innerHtml": value.toString() }).down() // Set the value editor. this.valueEditor = this.content .appendElement({ "tag": "div", "class": "switch col s12 m8", "style": "display: none;" }).down() let uuid = randomUUID() this.valueEditor.appendElement({ "tag": "label" }).down() .appendElement({ "tag": "span", "innerHtml": labels[1] }) .appendElement({ "tag": "input", "id": uuid, "type": "checkbox" }) .appendElement({ "tag": "span", "class": "lever" }) .appendElement({ "tag": "span", "innerHtml": labels[0] }) if (value == true) { this.valueEditor.getChildById(uuid).element.click() } this.valueEditor.element.onchange = () => { // set the value in the interface. this.valueDiv.setValue(this.valueEditor.getValue()) this.panel.hasChange() } // Return the value of the input. this.valueEditor.getValue = function () { return this.getChildById(uuid).element.checked } // Return the value of the input. this.valueEditor.setValue = function (v: any) { this.getChildById(uuid).element.checked = v } // Return the value of the input. this.valueDiv.setValue = function (v: any) { this.element.innerHTML = v } } } /** * That class implement multiple options single choice configuration line. */ export class ConfigurationMultipleOptionsSingleChoiceLine extends ConfigurationLine { constructor(panel: ConfigurationPanel, name: string, options: Array<string>, label: string, content: any) { super(panel, name, label, content); this.valueDiv = this.content.appendElement({ "tag": "div", "id": this.id + "_" + name + "_div", "class": "col s12 m8", "innerHtml": this.getValue() }).down() this.valueEditor = this.content.appendElement({ "tag": "div", "class": "col s12 m8", "style": "display: none; justify-content: flex-start;" }).down() // Set the choice from options... for (var i = 0; i < options.length; i++) { this.valueEditor .appendElement({ "tag": "label", "id": this.id + "_" + options[i] + "_label", "style": "padding-right: 15px;" }).down() .appendElement({ "tag": "input", "id": this.id + "_" + options[i] + "_input", "name": this.id + "_" + name + "_group", "type": "radio" }) .appendElement({ "tag": "span", "innerHtml": options[i] }).up() let input = this.content.getChildById(this.id + "_" + options[i] + "_input") input.element.onchange = () => { // set the value in the interface. this.valueDiv.setValue(this.valueEditor.getValue()) this.panel.hasChange() } } // Return the value of the input. this.valueEditor.getValue = () => { // That function will return the actual checked value. for (var i = 0; i < options.length; i++) { let input = this.valueEditor.getChildById(this.id + "_" + options[i] + "_input") if (input.element.checked == true) { return options[i] } } } // Return the value of the input. this.valueEditor.setValue = (v: any) => { for (var i = 0; i < options.length; i++) { let input = this.content.getChildById(this.id + "_" + options[i] + "_input") input.element.checked = false } let input = this.valueEditor.getChildById(this.id + "_" +v + "_input") input.element.checked = true; } // Return the value of the input. this.valueDiv.setValue = function (v: any) { this.element.innerHTML = v } // Set the value of the editor... this.valueEditor.setValue(this.getValue()) } } /** * Use to display a liste of string values in a configuration. */ export class ConfigurationStringListLine extends ConfigurationLine { constructor(panel: ConfigurationPanel, name: string, label: string, content: any) { super(panel, name, label, content); // The value div. this.valueDiv = this.content.appendElement({ "tag": "ul", "id": this.id + "_" + name + "_div", "class": "collection col s12 m8" }).down() // The editor div. this.valueEditor = this.content.appendElement({ "tag": "div", "id": this.id + "_" + name + "_editor", "class": "col s12 m8", "style": "display: none; padding: 0px; margin: 0px; position: relative;" }).down() // Return the value of the input. this.valueEditor.getValue = () => { let inputs = document.getElementsByName(this.id + "_" + name + "_group") let values = new Array<string>() for (var i = 0; i < inputs.length; i++) { values.push((<any>inputs[i]).value) } return values; } // Return the value of the input. this.valueEditor.setValue = (values: any) => { if (values == undefined) { return; } let appendEditor = (index: number, value: string) => { let li = ul.appendElement({ "tag": "li", "class": "collection-item", "style": "padding: 0px;" }).down() let removeBtn = li.appendElement({ "tag": "label", "id": this.id + "_" + index + "_label", "style": "display: flex; align-items: center;" }).down() .appendElement({ "tag": "input", "id": this.id + "_" + index + "_input", "name": this.id + "_" + name + "_group", "type": "text", "value": value }) .appendElement({ "tag": "i", "class": "tiny material-icons", "innerHtml": "remove", "style": "z-index: 10;" }).down() removeBtn.element.onmouseover = () => { removeBtn.element.style.cursor = "pointer" } removeBtn.element.onmouseout = () => { removeBtn.element.style.cursor = "default" } removeBtn.element.onclick = () => { this.panel.hasChange() li.element.parentNode.removeChild(li.element) } let input = this.content.getChildById(this.id + "_" + index + "_input") input.element.onchange = () => { // set the value in the interface. this.valueDiv.setValue(this.valueEditor.getValue()) this.panel.hasChange() } } this.valueEditor.removeAllChilds() let newLineBtn = this.valueEditor.appendElement({ "tag": "i", "class": "tiny material-icons", "innerHtml": "add_circle_outline", "style": "position: absolute; top: 12px; left: 4px; z-index: 10;" }).down() newLineBtn.element.onmouseover = () => { newLineBtn.element.style.cursor = "pointer" } newLineBtn.element.onmouseout = () => { newLineBtn.element.style.cursor = "default" } // Here I will set the list of control to edit the values. var ul = this.valueEditor.appendElement({ "tag": "ul", "id": this.id + "_" + name + "_editor", "class": "collection", "style": "padding: 15px;" }).down() // Apppend values. for (var i = 0; i < values.length; i++) { appendEditor(i, values[i]) } newLineBtn.element.onclick = () => { // append a new line element. appendEditor(this.getValue().length, "") this.valueEditor.getChildById(this.id + "_" + this.getValue().length + "_input").element.focus() this.panel.hasChange() } } // Return the value of the input. this.valueDiv.setValue = (values: any) => { if (values == undefined) { return; } // Clear the content. this.valueDiv.removeAllChilds() // Apppend values. for (var i = 0; i < values.length; i++) { this.valueDiv.appendElement({ "tag": "li", "class": "collection-item", "id": this.id + "_" + name + "_div_" + i, "innerHtml": values[i] }) } } // Set the actual configuration values. this.valueDiv.setValue(this.getValue()) this.valueEditor.setValue(this.getValue()) } } /** * That class will contain the general server information. */ export class ConfigurationPanel extends Panel { public config: any; public content: any; public btnGroup: any; private saveBtn: any; private cancelBtn: any; private configurationLines: Array<ConfigurationLine> constructor(config: any, title: string, id: string) { super(id); // Keep a pointer to the config. this.config = config; // Keep textual control this.configurationLines = new Array<ConfigurationLine>() // Display general information. this.div.appendElement({ "tag": "div", "class": "row configuration_panel" }).down() .appendElement({ "tag": "div", "class": "col s12 /*m10 offset-m1*/" }).down() .appendElement({ "tag": "div", "class": "card" }).down() .appendElement({ "tag": "div", "class": "card-content" }).down() .appendElement({ "tag": "span", "class": "card-title", "style": "font-size: medium; font-weight: inherit;", "innerHtml": title }) .appendElement({ "tag": "div", "id": "content" }) // The action buttons. .appendElement({ "tag": "div", "class": "card-action", "id": "btn_group", "style": "text-align: right; display: none;" }).down() .appendElement({ "tag": "a", "id": "save_btn", "href": "javascript:void(0)", "class": "waves-effect waves-light btn disabled", "innerHtml": "Save" }) .appendElement({ "tag": "a", "id": "cancel_btn", "href": "javascript:void(0)", "class": "waves-effect waves-light btn disabled", "innerHtml": "Cancel" }) // The save button this.saveBtn = this.div.getChildById("save_btn") this.saveBtn.element.onclick = () => { this.save() } // The cancel button this.cancelBtn = this.div.getChildById("cancel_btn") this.cancelBtn.element.onclick = () => { this.cancel() } // The group of button. this.btnGroup = this.div.getChildById("btn_group") // get the content. this.content = this.div.getChildById("content") } /** * * @param name * @param label */ appendEmptyConfig(name: string, label?: string): any { let configLine = new ConfigurationLine(this, name, label, this.content) return configLine; } /** * Append the textual configuration * @param name The name of the property in the configuration object. * @param label The value to display as label. */ appendTextualConfig(name: string, label?: string, type?: string, step?: number, min?: number, max?: number): any { let configLine = new ConfigurationTextLine(this, name, label, this.content, type, step, min, max) this.configurationLines.push(configLine) return configLine } /** * Append the textual configuarion. * @param name The name of the field in the config. * @param label The name to display beside the text area. */ appendLongTextualConfig(name: string, label?: string): any { let configLine = new ConfigurationLongTextLine(this, name, label, this.content) this.configurationLines.push(configLine) return configLine } /** * Append a boolean configuration (on/off true/false male/female...) * @param name The name of the property * @param labels The labels to display beside the switch * @param label Alternative property name in case the property name is a compose name. */ appendBooleanConfig(name: string, labels: Array<string>, label?: string): any { let configLine = new ConfigurationToggleLine(this, name, label, this.content, labels) this.configurationLines.push(configLine) return configLine } /** * Append a multiple line configuration * @param name The name of the configuration * @param label The display name */ appendStringListConfig(name: string, label?: string): any { let configLine = new ConfigurationStringListLine(this, name, label, this.content) this.configurationLines.push(configLine) return configLine } /** * Append multiple options single choice configuration line. * @param name The name of the configuration to display * @param options The list of possible values. * @param label The name to display in the interface. */ appendMultipleOptionsSingleChoiceConfig(name: string, options: Array<string>, label?: string): any { let configLine = new ConfigurationMultipleOptionsSingleChoiceLine(this, name, options, label, this.content) this.configurationLines.push(configLine) return configLine } appendEnumConfig(name: string, options: Array<string>, numericalIndex: boolean, label?: string) { let configLine = new ConfigurationEnum(this, name, options, label, this.content, numericalIndex) this.configurationLines.push(configLine) return configLine } // create control... onlogin(data: any) { if (this.config == undefined) { return // nothing that we can do here. } super.onlogin(data) // set the config with the full values. if (data.Services != undefined) { this.config = data.Services[this.config.Id] } else { this.config = data } if (this.config != undefined) { // Display textual input for (var i = 0; i < this.configurationLines.length; i++) { this.configurationLines[i].unlock() } this.btnGroup.element.style.display = "" } else { this.close() // disconnect listners. this.config = null; console.log(this.id, " has null config!") } } onlogout() { if (this.config == undefined) { return // nothing that we can do here. } super.onlogout() // display values. for (var i = 0; i < this.configurationLines.length; i++) { this.configurationLines[i].lock() } this.btnGroup.element.style.display = "none" this.cancel() } // That function is the same for all configuration panels. save() { for (var i = 0; i < this.configurationLines.length; i++) { this.configurationLines[i].set() } this.cancelBtn.element.classList.add("disabled") this.saveBtn.element.classList.add("disabled") } // must be overide by each panel. cancel() { for (var i = 0; i < this.configurationLines.length; i++) { this.configurationLines[i].reset() } this.cancelBtn.element.classList.add("disabled") this.saveBtn.element.classList.add("disabled") } hasChange() { this.btnGroup.element.style.display = "" // display it if is not visible. this.cancelBtn.element.classList.remove("disabled") this.saveBtn.element.classList.remove("disabled") } }