UNPKG

globular_admin

Version:
912 lines (827 loc) 30.7 kB
import * as M from "materialize-css"; import "materialize-css/sass/materialize.scss"; import { globular, authenticate, eventHub } from "./backend"; import { GeneralInfoPanel } from "./generalInfoPanel"; import { SearchServicesPanel } from "./searchServicesPanel"; import { ServicePanel } from "./servicePanel"; import { RolePanel } from "./rolePanel"; import { randomUUID, fireResize } from "./utility"; import { createElement } from './element.js' import { SqlServicePanel } from "./services/sqlServicePanel"; import { SmtpServicePanel } from "./services/smtpServicePanel"; import { LdapServicePanel } from "./services/ldapServicePanel"; import { PersistenceServicePanel } from "./services/persistenceServicePanel"; import { FileServicePanel } from './services/fileServicePanel'; import { PlcServerConfigPanel } from './services/plcServerConfigPanel'; import { PlcExporterConfigPanel } from "./services/plcExporterConfigPanel"; import { PlcLinkConfigPanel } from "./services/plcLinkConfigPanel"; import { PeerManager } from "./peersPanel"; import { DnsServicePanel } from "./services/dnsServicePanel"; import { AccountManager } from "./accountPanel"; import { FileManager } from "./filePanel"; import { RessourceManager } from "./ressourcePanel"; import { ApplicationManager } from "./applicationPanel"; import { LogManager } from "./logPanel"; import { Account } from "globular-web-client/lib/ressource/ressource_pb"; import { ServiceManager } from "./servicesPanel"; export class MainPage { private div: any; // The outer most div. private container: any; private loginLnk: any; private logoutLnk: any; private searchLnk: any; private homeLnk: any; private sideLoginLnk: any; private sideLogoutLnk: any; private sideSearchLnk: any; private sideHomeLnk: any; private searchInput: any; // The general information panel. private generalInfoPanel: GeneralInfoPanel; private searchServicesPanel: SearchServicesPanel; private rolePanel: RolePanel; private accountsManager: AccountManager; private filesManager: FileManager; private ressourcesManager: RessourceManager; private applicationsManager: ApplicationManager; private logsManager: LogManager; private peersManager: PeerManager; private servicesManager: ServiceManager; private servicesPanel: Map<string, ServicePanel>; constructor() { // Here I will create the main container. this.div = createElement(null, { tag: "div", style: "position: relative" }); document.body.appendChild(this.div.element); this.servicesPanel = new Map<string, ServicePanel>(); eventHub.subscribe( "install_service_event", (uuid: string) => { //console.log("install_service_event", uuid); }, (evt: any) => { this.showGeneralInfo() }, true ); eventHub.subscribe( "uninstall_service_event", (uuid: string) => { //console.log("uninstall_service_event", uuid); }, (evt: any) => { // close the listeners. this.servicesPanel.get(evt).close() // remove the panel. let deleted = this.servicesPanel.delete(evt) // refresh the services. if(deleted){ this.showGeneralInfo() } }, true ); ////////////////////////////// Navigation ////////////////////////////// // Now Will create the navbar. let navBar = this.div .appendElement({ tag: "div", class: "navbar-fixed" }) .down() .appendElement({ tag: "nav" }) .down(); // The mobile nav menu.. this.div .appendElement({ tag: "ul", class: "sidenav", id: "slide-out" }) .down() .appendElement({ tag: "li", id: "home-side-lnk" }) .down() .appendElement({ tag: "a", href: "javascript:void(0)", class: "waves-effect", innerHtml: "Home" }) .up() .appendElement({ tag: "li", id: "search-side-lnk", style: "display: none;" }) .down() .appendElement({ tag: "a", href: "javascript:void(0)", class: "waves-effect", innerHtml: "Search" }) .up() .appendElement({ tag: "li", id: "login-side-lnk" }) .down() .appendElement({ tag: "a", href: "javascript:void(0)", class: "waves-effect", innerHtml: "Login" }) .up() .appendElement({ tag: "li", id: "logout-side-lnk", style: "display: none;" }) .down() .appendElement({ tag: "a", href: "javascript:void(0)", class: "waves-effect", innerHtml: "Logout" }) .up(); var elem = document.querySelector(".sidenav"); var instance = M.Sidenav.init(elem, { inDuration: 350, outDuration: 350, edge: "left" }); ////////////////////////////// Login ////////////////////////////// // The large menu...indigo darken-4 this.loginLnk = navBar .appendElement({ tag: "div", class: "nav-wrapper indigo darken-4", style: "display: flex;" }) .down() //.appendElement({ "tag": "a", "id": "logo_btn", "class": "flow-text", "innerHtml": "Globular" }) .appendElement({ tag: "ul", class: "left" }) .down() .appendElement({ tag: "li", id: "slide-out-li" }) .down() .appendElement({ tag: "a", href: "javascript:void(0)", "data-target": "slide-out", class: "sidenav-trigger" }) .down() .appendElement({ tag: "i", class: "hamburger material-icons hide-on-large-only", innerHtml: "menu" }) .up() .up() .up() .appendElement({ tag: "div", style: "flex-grow:1; display: flex; justify-content: flex-end;" }) .down() .appendElement({ tag: "div", class: "input-field", style: "max-width: 430px;" }) .down() .appendElement({ tag: "input", type: "search", id: "search_input", autocomplete: "off" }) .appendElement({ tag: "label", class: "label-icon", for: "search_input" }) .down() .appendElement({ tag: "i", class: "material-icons", innerHtml: "search" }) .up() .appendElement({ tag: "i", class: "material-icons", innerHtml: "close" }) .up() .up() .appendElement({ tag: "ul", id: "nav-mobile", class: "right hide-on-med-and-down" }) .down() .appendElement({ tag: "li", id: "Home" }) .down() .appendElement({ tag: "a", href: "javascript:void(0)", class: "waves-effect waves-light", innerHtml: "Home" }) .up() .appendElement({ tag: "li", id: "Search", style: "display: none;" }) .down() .appendElement({ tag: "a", href: "javascript:void(0)", class: "waves-effect waves-light", innerHtml: "Search" }) .up() .appendElement({ tag: "li", id: "Logout", style: "display: none;" }) .down() .appendElement({ tag: "a", href: "javascript:void(0)", class: "waves-effect waves-light", innerHtml: "Logout" }) .up() .appendElement({ tag: "li" }) .down() .appendElement({ tag: "a", id: "login", href: "javascript:void(0)", class: "waves-effect waves-light", innerHtml: "Login" }) .down(); this.logoutLnk = navBar.getChildById("Logout"); this.searchLnk = navBar.getChildById("Search"); this.homeLnk = navBar.getChildById("Home"); this.sideLoginLnk = this.div.getChildById("login-side-lnk"); this.sideLogoutLnk = this.div.getChildById("logout-side-lnk"); this.sideSearchLnk = this.div.getChildById("search-side-lnk"); this.sideHomeLnk = this.div.getChildById("home-side-lnk"); ////////////////////////////// General informations ////////////////////////////// // This will be the workspace... this.container = this.div .appendElement({ tag: "div", class: "container" }) .down(); this.showSearchServicePanel(); // must be call once to initialyse it this.showGeneralInfo(); // Set the search input action. this.searchInput = navBar.getChildById("search_input"); this.searchInput.element.onkeyup = (evt: any) => { if (evt.keyCode == 13) { this.showSearchServicePanel(); let keywords = this.searchInput.element.value.split(" "); this.searchInput.element.value = ""; this.searchServicesPanel.search(keywords); this.searchLnk.element.style.display = ""; this.sideSearchLnk.element.style.display = ""; } }; ////////////////////////////// connect event ////////////////////////////// // Show general info. this.homeLnk.element.onclick = () => { this.showGeneralInfo(); }; // Show search results. this.searchLnk.element.onclick = () => { this.showSearchServicePanel(); }; // Show login this.loginLnk.element.onclick = () => { this.showLogin(); }; // Publish logout event. this.logoutLnk.element.onclick = () => { eventHub.publish("onlogout", {}, true); // return the full config... M.toast({ html: "Bye Bye!!" }); this.logoutLnk.element.style.display = "none"; this.loginLnk.element.style.display = ""; this.sideLogoutLnk.element.style.display = "none"; this.sideLoginLnk.element.style.display = ""; } // Show the login dialog this.sideLoginLnk.element.onclick = () => { instance.close(); this.loginLnk.element.click(); }; this.sideSearchLnk.element.onclick = () => { instance.close(); }; this.sideHomeLnk.element.onclick = () => { instance.close(); }; } login(email: string, password: string) { authenticate( email, password, (tokenInfo: any) => { M.toast({ html: "You are now logged in as Administrator." }); this.logoutLnk.element.style.display = ""; this.loginLnk.element.style.display = "none"; this.sideLogoutLnk.element.style.display = ""; this.sideLoginLnk.element.style.display = "none"; }, (error: any) => { M.toast({ html: "login fail!" }); } ); } /** * Display the login dialog. */ showLogin() { // Create the dialog only if is not already exist. if (document.getElementById("login-dialog") != null) { document.getElementById("email").focus(); return; } // Here I will create the login dialog. let loginDialog = createElement(null, { tag: "div", id: "login-dialog", style: "position: fixed; top: 0px; left: 0px; right: 0px; bottom: 0px; background-color: rgba(0.0, 0.0, 0.0, 0.5); z-index: 10;" }); loginDialog.element.innerHTML = `<div class="col s12 z-depth-6 card-panel" style="position: absolute; margin:auto; top: 57px; left: 0px; right: 0px; bottom: 0px;"> <form class="login-form"> <div class="row"> </div> <div class="row"> <div class="input-field col s12"> <i class="material-icons prefix indigo-text text-darken-3">mail_outline</i> <input class="validate" id="email" type="email"> <label for="email" data-error="wrong" data-success="right">Email</label> </div> </div> <div class="row"> <div class="input-field col s12"> <i class="material-icons prefix indigo-text text-darken-3">lock_outline</i> <input id="password" type="password"> <label for="password">Password</label> </div> </div> <div class="row"> <div class="input-field col s12"> <a id="login-lnk" href="javascript:void(0)" class="btn waves-effect waves-light col s12 indigo darken-3">Login</a> </div> </div> </form>`; document.body.appendChild(loginDialog.element); document.getElementById("email").focus(); // TODO implement the login event here. this.loginLnk.element.onclick = () => { if (document.getElementById("login-dialog") == null) { this.showLogin(); } else { this.login( (<HTMLInputElement>document.getElementById("email")).value, (<HTMLInputElement>document.getElementById("password")).value ); loginDialog.element.parentNode.removeChild(loginDialog.element); } }; document.getElementById("email").onkeyup = (evt: any) => { if (evt.keyCode == 27) { loginDialog.element.parentNode.removeChild(loginDialog.element); } }; document.getElementById("password").onkeyup = (evt: any) => { if (evt.keyCode == 27) { loginDialog.element.parentNode.removeChild(loginDialog.element); } else if (evt.keyCode == 13) { this.login( (<HTMLInputElement>document.getElementById("email")).value, (<HTMLInputElement>document.getElementById("password")).value ); loginDialog.element.parentNode.removeChild(loginDialog.element); } }; document.getElementById("login-lnk").onclick = (evt: any) => { this.login( (<HTMLInputElement>document.getElementById("email")).value, (<HTMLInputElement>document.getElementById("password")).value ); loginDialog.element.parentNode.removeChild(loginDialog.element); }; } showGeneralInfo() { this.container.removeAllChilds(); // Show the tabs... this.container .appendElement({ tag: "div", class: "col hide-on-med-and-down m3 l2", style: "position: fixed; left: 20px; top: 55px" }) .down() .appendElement({ tag: "ul", id: "main_tabs", class: "section table-of-contents" }) .down() .appendElement({ tag: "li", class: "tab col s2" }) .down() .appendElement({ tag: "a", id: "main_tabs_tab_0", class: "grey-text text-darken-3", href: "javascript:void(0)", innerHtml: "Server" }) .up() .appendElement({ tag: "li", class: "tab col s2" }) .down() .appendElement({ tag: "a", id: "main_tabs_tab_1", class: "grey-text text-darken-3", href: "javascript:void(0)", innerHtml: "Accounts" }) .up() .appendElement({ tag: "li", class: "tab col s1" }) .down() .appendElement({ tag: "a", id: "main_tabs_tab_2", class: "grey-text text-darken-3", href: "javascript:void(0)", innerHtml: "Roles" }) .up() .appendElement({ tag: "li", class: "tab col s1" }) .down() .appendElement({ tag: "a", id: "main_tabs_tab_3", class: "grey-text text-darken-3", href: "javascript:void(0)", innerHtml: "Peers" }) .up() .appendElement({ tag: "li", class: "tab col s2" }) .down() .appendElement({ tag: "a", id: "main_tabs_tab_4", class: "grey-text text-darken-4", href: "javascript:void(0)", innerHtml: "Applications" }) .up() .appendElement({ tag: "li", class: "tab col s2" }) .down() .appendElement({ tag: "a", id: "main_tabs_tab_5", class: "grey-text text-darken-4", href: "javascript:void(0)", innerHtml: "Services" }) .up() .appendElement({ tag: "li", class: "tab col s1" }) .down() .appendElement({ tag: "a", id: "main_tabs_tab_6", class: "grey-text text-darken-4", href: "javascript:void(0)", innerHtml: "Files" }) .up() .appendElement({ tag: "li", class: "tab col s2" }) .down() .appendElement({ tag: "a", id: "main_tabs_tab_7", class: "grey-text text-darken-4", href: "javascript:void(0)", innerHtml: "Ressources" }) .up() .appendElement({ tag: "li", class: "tab col s1" }) .down() .appendElement({ tag: "a", id: "main_tabs_tab_8", class: "grey-text text-darken-3", href: "javascript:void(0)", innerHtml: "Logs" }) // Initialyse various panels. if (this.generalInfoPanel == null) { this.generalInfoPanel = new GeneralInfoPanel(globular.config); }else{ this.generalInfoPanel.refresh() } if (this.rolePanel == null) { this.rolePanel = new RolePanel(randomUUID()); }else{ this.rolePanel.refresh() } if (this.filesManager == null) { this.filesManager = new FileManager(randomUUID()); }else{ this.filesManager.refresh() } if (this.ressourcesManager == null) { this.ressourcesManager = new RessourceManager(); }else{ this.ressourcesManager.refresh() } if (this.accountsManager == null) { this.accountsManager = new AccountManager(randomUUID()); }else{ this.accountsManager.refresh() } if (this.logsManager == null) { this.logsManager = new LogManager(randomUUID()); }else{ this.logsManager.refresh() } if (this.applicationsManager == null) { this.applicationsManager = new ApplicationManager(randomUUID()); }else{ this.applicationsManager.refresh() } if (this.servicesManager == null){ this.servicesManager = new ServiceManager(randomUUID()); }else{ this.servicesManager.refresh() } if (this.peersManager == null) { this.peersManager = new PeerManager(randomUUID()); }else{ this.peersManager.refresh() } // Set tabs. let tab_0_content = this.container.appendElement({ tag: "div" }).down(); this.generalInfoPanel.setParent(tab_0_content); this.showServicesPanel(tab_0_content); // The tab content. let tab_1_content = this.container .appendElement({ tag: "div", style: "display: none" }) .down(); this.accountsManager.setParent(tab_1_content); let tab_2_content = this.container .appendElement({ tag: "div", style: "display: none" }) .down(); this.rolePanel.setParent(tab_2_content); let tab_3_content = this.container .appendElement({ tag: "div", style: "display: none" }) .down(); this.peersManager.setParent(tab_3_content); let tab_4_content = this.container .appendElement({ tag: "div", style: "display: none" }) .down(); this.applicationsManager.setParent(tab_4_content); let tab_5_content = this.container .appendElement({ tag: "div", style: "display: none" }) .down(); this.servicesManager.setParent(tab_5_content); let tab_6_content = this.container .appendElement({ tag: "div", style: "display: none" }) .down(); this.filesManager.setParent(tab_6_content); let tab_7_content = this.container .appendElement({ tag: "div", style: "display: none" }) .down(); this.ressourcesManager.setParent(tab_7_content); let tab_8_content = this.container .appendElement({ tag: "div", style: "display: none" }) .down(); this.logsManager.setParent(tab_8_content); // Init the materialyse tabs. M.Tabs.init(document.getElementById("main_tabs")); // hide and show tab content. this.container.getChildById("main_tabs_tab_0").element.onclick = () => { tab_0_content.element.style.display = ""; tab_1_content.element.style.display = "none"; tab_2_content.element.style.display = "none"; tab_3_content.element.style.display = "none"; tab_4_content.element.style.display = "none"; tab_5_content.element.style.display = "none"; tab_6_content.element.style.display = "none"; tab_7_content.element.style.display = "none"; tab_8_content.element.style.display = "none"; }; this.container.getChildById("main_tabs_tab_1").element.onclick = () => { tab_0_content.element.style.display = "none"; tab_1_content.element.style.display = ""; tab_2_content.element.style.display = "none"; tab_3_content.element.style.display = "none"; tab_4_content.element.style.display = "none"; tab_5_content.element.style.display = "none"; tab_6_content.element.style.display = "none"; tab_7_content.element.style.display = "none"; tab_8_content.element.style.display = "none"; }; this.container.getChildById("main_tabs_tab_2").element.onclick = () => { tab_0_content.element.style.display = "none"; tab_1_content.element.style.display = "none"; tab_2_content.element.style.display = ""; tab_3_content.element.style.display = "none"; tab_4_content.element.style.display = "none"; tab_5_content.element.style.display = "none"; tab_6_content.element.style.display = "none"; tab_7_content.element.style.display = "none"; tab_8_content.element.style.display = "none"; }; this.container.getChildById("main_tabs_tab_3").element.onclick = () => { tab_0_content.element.style.display = "none"; tab_1_content.element.style.display = "none"; tab_2_content.element.style.display = "none"; tab_3_content.element.style.display = ""; tab_4_content.element.style.display = "none"; tab_5_content.element.style.display = "none"; tab_6_content.element.style.display = "none"; tab_7_content.element.style.display = "none"; tab_8_content.element.style.display = "none"; }; this.container.getChildById("main_tabs_tab_4").element.onclick = () => { tab_0_content.element.style.display = "none"; tab_1_content.element.style.display = "none"; tab_2_content.element.style.display = "none"; tab_3_content.element.style.display = "none"; tab_4_content.element.style.display = ""; tab_5_content.element.style.display = "none"; tab_6_content.element.style.display = "none"; tab_7_content.element.style.display = "none"; tab_8_content.element.style.display = "none"; }; this.container.getChildById("main_tabs_tab_5").element.onclick = () => { tab_0_content.element.style.display = "none"; tab_1_content.element.style.display = "none"; tab_2_content.element.style.display = "none"; tab_3_content.element.style.display = "none"; tab_4_content.element.style.display = "none"; tab_5_content.element.style.display = ""; tab_6_content.element.style.display = "none"; tab_7_content.element.style.display = "none"; tab_8_content.element.style.display = "none"; }; this.container.getChildById("main_tabs_tab_6").element.onclick = () => { tab_0_content.element.style.display = "none"; tab_1_content.element.style.display = "none"; tab_2_content.element.style.display = "none"; tab_3_content.element.style.display = "none"; tab_4_content.element.style.display = "none"; tab_5_content.element.style.display = "none"; tab_6_content.element.style.display = ""; tab_7_content.element.style.display = "none"; tab_8_content.element.style.display = "none"; }; this.container.getChildById("main_tabs_tab_7").element.onclick = () => { tab_0_content.element.style.display = "none"; tab_1_content.element.style.display = "none"; tab_2_content.element.style.display = "none"; tab_3_content.element.style.display = "none"; tab_4_content.element.style.display = "none"; tab_5_content.element.style.display = "none"; tab_6_content.element.style.display = "none"; tab_7_content.element.style.display = ""; tab_8_content.element.style.display = "none"; }; this.container.getChildById("main_tabs_tab_8").element.onclick = () => { tab_0_content.element.style.display = "none"; tab_1_content.element.style.display = "none"; tab_2_content.element.style.display = "none"; tab_3_content.element.style.display = "none"; tab_4_content.element.style.display = "none"; tab_5_content.element.style.display = "none"; tab_6_content.element.style.display = "none"; tab_7_content.element.style.display = "none"; tab_8_content.element.style.display = ""; }; // add resize handler window.addEventListener("resize", () => { let mainTabs = this.container.getChildById("main_tabs"); let sideNav = this.div.getChildById("slide-out") if (document.body.offsetWidth < 992) { for (var id in mainTabs.childs) { let li = mainTabs.childs[id] sideNav.appendElement(li) } } else { for (var id in sideNav.childs) { let li = sideNav.childs[id] if (li.element.classList.contains("tab")) { mainTabs.appendElement(li) } } } }); // fire resize event... fireResize() } showServicesPanel(container: any) { // The tab div... let div = container .appendElement({ tag: "div", class: "row", style: "margin-bottom: 5px; padding-left: 10px; font-size: medium;", innerHtml: "Installed services" }) .appendElement({ tag: "div", class: "row" }) .down() .appendElement({ id: "service_tabs", tag: "div", class: "col s12 /*m10 offset-m1*/" }) .down() .appendElement({ tag: "ul", id: "services_list", class: "collapsible" }) .down(); for (var key in globular.config.Services) { if (globular.config.Services[key].PublisherId != null) { let title = key.replace("_", " "); let servicePanel: ServicePanel; if (!this.servicesPanel.has(key)) { // Here I will instantiate the correct service configuration interface. if (globular.config.Services[key].Name == "sql_server") { servicePanel = new SqlServicePanel( globular.config.Services[key], key, title ); } else if (globular.config.Services[key].Name == "smtp_server") { servicePanel = new SmtpServicePanel( globular.config.Services[key], key, title ); } else if (globular.config.Services[key].Name == "ldap_server") { servicePanel = new LdapServicePanel( globular.config.Services[key], key, title ); } else if (globular.config.Services[key].Name == "persistence_server") { servicePanel = new PersistenceServicePanel( globular.config.Services[key], key, title ); } else if (globular.config.Services[key].Name == "file_server") { servicePanel = new FileServicePanel( globular.config.Services[key], key, title ); } else if (globular.config.Services[key].Name == "dns_server") { servicePanel = new DnsServicePanel( globular.config.Services[key], key, title ); } else if (globular.config.Services[key].Name.startsWith("plc_server_")) { servicePanel = new PlcServerConfigPanel( globular.config.Services[key], key, title ); } else if (globular.config.Services[key].Name.startsWith("plc_exporter")) { servicePanel = new PlcExporterConfigPanel( globular.config.Services[key], key, title ); } else if (globular.config.Services[key].Name.startsWith("plc_link")) { servicePanel = new PlcLinkConfigPanel( globular.config.Services[key], key, title ); } else { servicePanel = new ServicePanel( globular.config.Services[key], key, title ); } servicePanel.btnGroup.element.style.display = "none"; // set for further use this.servicesPanel.set(key, servicePanel); }else{ servicePanel = this.servicesPanel.get(key) servicePanel.refresh() } // Here I will create the tab... let panel = div .appendElement({ tag: "li" }) .down() .appendElement({ tag: "div", class: "collapsible-header", style: "display: flex; align-items: center;" }) .down() .appendElement({ tag: "span", class: "col s6", innerHtml: title }) .appendElement({ tag: "span", id: key + "_state", class: "col s6 right-align", innerHtml: globular.config.Services[key].State, }) .appendElement(servicePanel.actionBtnGroup) .up() .appendElement({ tag: "div", class: "collapsible-body" }) .down(); panel.appendElement(servicePanel.content); panel.appendElement(servicePanel.btnGroup); servicePanel.setStateDiv(div.getChildById(key + "_state")); } } // initialyse the tab component. M.Collapsible.init(document.getElementById("services_list")); } showSearchServicePanel() { this.container.removeAllChilds(); // set the general info panel if it not exist. if (this.searchServicesPanel == null) { this.searchServicesPanel = new SearchServicesPanel(); } this.searchServicesPanel.setParent(this.container); } }