globular-mvc
Version:
Generic template to create web-application that made use of globular as backend and materialize as css (wrap in web-component's)
515 lines (429 loc) • 22 kB
text/typescript
import { Settings } from "./Settings"
import { SettingsMenu, SettingsPanel, ComplexSetting, ActionSetting, OnOffSetting, ReadOnlyStringSetting, StringListSetting, NumberSetting, ConnectionsSetting } from "./components/Settings"
import { ApplicationView } from "./ApplicationView";
import * as servicesManager from "globular-web-client/services_manager/services_manager_pb"
import { Model } from "./Model";
import { Application } from "./Application";
import { SynchronizeRequest } from "globular-web-client/ldap/ldap_pb";
export class ServicesSettings extends Settings {
private services: any
private servicesSettings: Array<ServiceSetting>
constructor(settingsMenu: SettingsMenu, settingsPanel: SettingsPanel) {
super(settingsMenu, settingsPanel);
Model.globular.eventHub.subscribe("save_settings_evt", uuid => { }, evt => {
this.save()
}, true)
// Init the service configuration...
this.getServicesConfiguration(
(services: any) => {
this.init(services, settingsMenu, settingsPanel)
// refresh service states...
setInterval(() => {
this.getServicesConfiguration(
(services: any) => {
// refresh service states...
services.forEach((service: any) => {
if (this.services[service.Id] != undefined) {
// So here I will update the service state...
this.setServiceState(service)
}
})
}, (err: any) => {
console.log(err)
})
}, 10000)
}, (err: any) => {
console.log(err)
})
}
save() {
this.servicesSettings.forEach(s => {
if(s !=undefined){
s.save()
}
})
}
// Init the configuration interface...
init(services: any, settingsMenu: SettingsMenu, settingsPanel: SettingsPanel) {
this.services = {}
this.servicesSettings = new Array<ServiceSetting>()
// Range use to create fragment.
let range = document.createRange()
// Create the settings menu and panel here
settingsMenu.appendSettingsMenuItem("settings", "Services");
// Create General informations setting's
let serverSettingsPage = <any>settingsPanel.appendSettingsPage("Services");
// Append a title.
let html = `
<div class="title">
Services
</div>
<div class="subtitle-div">
<span class="subtitle" style="font-size: 1rem; flex-grow: 1">Manage services</span>
<paper-icon-button icon="add"> </paper-icon-button>
</div>
`
serverSettingsPage.appendChild(document.createRange().createContextualFragment(html));
// Create installed services ...
let servicesSettings = serverSettingsPage.appendSettings("", `Installed gRPC service instances( ${Object.keys(services).length})`);
for (var s in services) {
let service = services[s]
if (service.Name != undefined) {
let serviceSetting = new ComplexSetting(service.Name.split(".")[0], "")
serviceSetting.getDescription = () => {
return "gRpc service settings"
}
/** So here I will append into the description div controls to stop/start the serivce */
let serviceToolBar = `
<div style="display: flex; padding-left: 25px; align-items: center;">
<div style="width: 28px; height: 28px; display: none;">
<paper-spinner id="service-spinner-${service.Id}"></paper-spinner>
</div>
<paper-icon-button icon="av:play-arrow" id="start-service-btn-${service.Id}">
Start
</paper-icon-button>
<paper-icon-button style="padding-rigth: 15px;" icon="av:stop" id="stop-service-btn-${service.Id}">
Stop
</paper-icon-button>
<div style="display: flex; align-items: center; width: 100%; padding-left: 15px;">
<span class="setting-name" style="/*flex-basis: 55px;*/ ">Status: </span>
<span id="service-state-${service.Id}" style="width: 100%"></span>
<span style="padding-left: 10px; color: var(--palette-error-main);" id="service-last-error-${service.Id}">
</div>
</div>
`
let div = <any>serviceSetting.getDescriptionDiv()
div.appendChild(range.createContextualFragment(serviceToolBar))
let s: ServiceSetting
if (service.Name == "ldap.LdapService") {
s = new LdapServiceSetting(service, serviceSetting)
} else if (service.Name == "slq.SqlService") {
s = new SqlServiceSetting(service, serviceSetting)
} else if (service.Name == "persistence.PersistenceService") {
s = new PersistenceServiceSetting(service, serviceSetting)
} else if (service.Name == "dns.DnsService") {
s = new DnsServiceSetting(service, serviceSetting)
} else {
s = new ServiceSetting(service, serviceSetting)
}
this.servicesSettings.push(s)
// Now I will set the actions
let startServiceBtn = div.querySelector("#start-service-btn-" + service.Id)
let stopServiceBtn = div.querySelector("#stop-service-btn-" + service.Id)
let spinner = div.querySelector("#service-spinner-" + service.Id)
if (service.State == "running") {
startServiceBtn.style.display = "none"
stopServiceBtn.style.display = "block"
} else {
startServiceBtn.style.display = "block"
stopServiceBtn.style.display = "none"
}
/** Start service */
startServiceBtn.onclick = () => {
spinner.setAttribute("active", "")
spinner.parentNode.style.display = "block"
startServiceBtn.style.display = "none"
stopServiceBtn.style.display = "none"
let rqst = new servicesManager.StartServiceInstanceRequest
rqst.setServiceId(service.Id)
Model.globular.servicesManagerService.startServiceInstance(rqst, {
token: localStorage.getItem("user_token"),
application: Model.application,
domain: Model.domain,
address: Model.address
}).then(() => {
}).catch((err: any) => {
spinner.parentNode.style.display = "none"
startServiceBtn.style.display = "block"
stopServiceBtn.style.display = "none"
spinner.removeAttribute("active")
ApplicationView.displayMessage(err, 3000)
})
}
/** Stop service instance */
stopServiceBtn.onclick = () => {
let rqst = new servicesManager.StopServiceInstanceRequest
rqst.setServiceId(service.Id)
spinner.setAttribute("active", "")
startServiceBtn.style.display = "none"
stopServiceBtn.style.display = "none"
spinner.parentNode.style.display = "block"
Model.globular.servicesManagerService.stopServiceInstance(rqst, {
token: localStorage.getItem("user_token"),
application: Model.application,
domain: Model.domain,
address: Model.address
}).then(() => {
}).catch((err: any) => {
startServiceBtn.style.display = "none"
stopServiceBtn.style.display = "block"
spinner.parentNode.style.display = "none"
spinner.removeAttribute("active")
ApplicationView.displayMessage(err, 3000)
})
}
servicesSettings.addSetting(serviceSetting)
this.services[service.Id] = div
this.setServiceState(service)
}
}
}
// Set the service state in the interface.
setServiceState(service: any) {
let stateSpan = this.services[service.Id].querySelector("#service-state-" + service.Id)
if (stateSpan.innerHTML == service.State) {
return
}
let startServiceBtn = this.services[service.Id].querySelector("#start-service-btn-" + service.Id)
let stopServiceBtn = this.services[service.Id].querySelector("#stop-service-btn-" + service.Id)
let spinner = this.services[service.Id].querySelector("#service-spinner-" + service.Id)
stateSpan.innerHTML = service.State
stateSpan.style.color = "var(--palette-text-primary)"
startServiceBtn.style.display = "block"
stopServiceBtn.style.display = "none"
let lastErrorSpan = this.services[service.Id].querySelector("#service-last-error-" + service.Id)
lastErrorSpan.innerHTML = ""
if (service.State == "failed") {
lastErrorSpan.innerHTML = "(" + service.last_error + ")"
stateSpan.style.color = "var(--palette-error-main)"
ApplicationView.displayMessage("Service " + service.Name + ":" + service.Id + " failed with error " + service.last_error, 3000)
} else if (service.State == "running") {
startServiceBtn.style.display = "none"
stopServiceBtn.style.display = "block"
stateSpan.style.color = "var(--palette-success-main)"
} else if (service.State == "killed") {
stateSpan.style.color = "var(--palette-error-main)"
} else if (service.State == "starting") {
stateSpan.style.color = "var(--palette-warning-main)"
startServiceBtn.style.display = "none"
stopServiceBtn.style.display = "none"
spinner.parentNode.style.display = "block"
spinner.setAttribute("active", "")
}
if (service.State != "starting") {
spinner.parentNode.style.display = "none"
spinner.removeAttribute("active")
}
}
getServicesConfiguration(successCallback: (services: any) => void, errorCallback: (services: any) => void) {
let rqst = new servicesManager.GetServicesConfigurationRequest
Model.globular.servicesManagerService.getServicesConfiguration(rqst, {
token: localStorage.getItem("user_token"),
application: Model.application,
domain: Model.domain,
address: Model.address
}).then((rsp: servicesManager.GetServicesConfigurationResponse) => {
let services = []
for (var i = 0; i < rsp.getServicesList().length; i++) {
let service = rsp.getServicesList()[i].toJavaScript()
services.push(service)
}
successCallback(services)
})
.catch((err: any) => {
console.log(err)
})
}
}
export class ServiceSetting {
protected service: any;
protected needSave: boolean;
constructor(service: any, serviceSetting: any) {
this.service = service;
this.needSave = false;
// Now The actions...
let updateServiceAction = new ActionSetting("Update", "Update service to the last version", () => {
console.log("update service call")
})
serviceSetting.addSetting(updateServiceAction)
let uninstallServiceAction = new ActionSetting("Uninstall", "Uninstall the service", () => {
console.log("uninstall services")
})
serviceSetting.addSetting(uninstallServiceAction)
// Here I will display the non editable informations...
let descriptionSetting = new ReadOnlyStringSetting("Description", "")
descriptionSetting.setValue(service.Description)
serviceSetting.addSetting(descriptionSetting)
let nameSetting = new ReadOnlyStringSetting("Name", "gRpc Service Name")
nameSetting.setValue(service.Name)
serviceSetting.addSetting(nameSetting)
let idSetting = new ReadOnlyStringSetting("Id", "The serivce instance id")
idSetting.setValue(service.Id)
serviceSetting.addSetting(idSetting)
let macSetting = new ReadOnlyStringSetting("MAC Address", "The Globular server MAC addresse")
macSetting.setValue(service.Mac)
serviceSetting.addSetting(macSetting)
let publisherIdSetting = new ReadOnlyStringSetting("Publisher", "The creator (organization or user) of that service")
publisherIdSetting.setValue(service.PublisherId)
serviceSetting.addSetting(publisherIdSetting)
let versionSetting = new ReadOnlyStringSetting("Version", "The Globular server version number")
versionSetting.setValue(service.Version)
serviceSetting.addSetting(versionSetting)
let tlsSetting = new ReadOnlyStringSetting("TLS", "Does the service use secure socket...")
tlsSetting.setValue(service.TLS)
serviceSetting.addSetting(tlsSetting)
let portSetting = new NumberSetting("Port", "The gRpc service port number")
portSetting.setValue(service.Port)
serviceSetting.addSetting(portSetting)
portSetting.onchange = () => {
this.service.Port = parseInt(portSetting.getValue())
this.needSave = true
}
let proxySetting = new NumberSetting("Proxy", "The gRpc proxy port number")
proxySetting.setValue(service.Proxy)
serviceSetting.addSetting(proxySetting)
proxySetting.onchange = () => {
this.service.Proxy = parseInt(proxySetting.getValue())
this.needSave = true
}
let keepAlive = new OnOffSetting("Keep Alive", "Restart service automaticaly if it fail")
keepAlive.setValue(service.KeepAlive)
serviceSetting.addSetting(keepAlive)
keepAlive.onchange = () => {
this.service.KeepAlive = keepAlive.getValue()
this.needSave = true
}
let keepUpToDate = new OnOffSetting("Keep Up to Date", "Automaticaly update to last service version")
keepUpToDate.setValue(service.KeepUpToDate)
serviceSetting.addSetting(keepAlive)
keepUpToDate.onchange = () => {
this.service.KeepUpToDate = keepUpToDate.getValue()
this.needSave = true
}
let allowedAllOrigins = new OnOffSetting("Allow All Origins", "all origins are allowed")
allowedAllOrigins.setValue(service.AllowAllOrigins)
serviceSetting.addSetting(allowedAllOrigins)
allowedAllOrigins.onchange = () => {
this.service.AllowAllOrigins = allowedAllOrigins.getValue()
this.needSave = true
}
let corsOriginsSettings_ = new ComplexSetting("Allowed Origins", "List of allowed Cross-origin")
let corsOriginsSettings = new StringListSetting("Allowed Origins", "List of allowed Cross-origin")
if (serviceSetting.AllowedOrigins != undefined) {
if (serviceSetting.AllowedOrigins.length > 0) {
if (service.AllowedOrigins.indexOf(",") > 0) {
let allowedOrigins = service.AllowedOrigins.split(",")
corsOriginsSettings.setValues(allowedOrigins)
corsOriginsSettings.onchange = () => {
let allowedOrigins = corsOriginsSettings.getValues()
service.AllowedOrigins = ""
for (var i = 0; i < allowedOrigins.length; i++) {
service.AllowedOrigins += allowedOrigins[i]
if (i < allowedOrigins.length - 1) {
service.AllowedOrigins += " ,"
}
}
this.needSave = true
}
}
}
}
if (!service.AllowAllOrigins) {
allowedAllOrigins.setAttribute("title", "all origins are allowed")
} else {
corsOriginsSettings_.style.display = "none"
}
allowedAllOrigins.getElement().onchange = () => {
let toggle = <any>(allowedAllOrigins.getElement())
if (!toggle.checked) {
toggle.setAttribute("title", "select allowed origin...")
corsOriginsSettings_.style.display = "flex"
} else {
toggle.setAttribute("title", "all origins are allowed")
corsOriginsSettings_.style.display = "none"
}
}
corsOriginsSettings_.addSetting(corsOriginsSettings)
serviceSetting.addSetting(corsOriginsSettings_)
}
save() {
if (!this.needSave) {
return
}
console.log("save service ", this.service)
let rqst = new servicesManager.SaveServiceConfigRequest()
rqst.setConfig(JSON.stringify(this.service))
Model.globular.servicesManagerService.saveServiceConfig(rqst, {
token: localStorage.getItem("user_token"),
application: Model.application,
domain: Model.domain,
address: Model.address
}).then(rsp => {
// ApplicationView.displayMessage(err, 3000)
console.log("service was saved! ", this.service)
}).catch(err => {
ApplicationView.displayMessage(err, 3000)
})
}
}
// Now specific settings...
// LDAP
export class LdapServiceSetting extends ServiceSetting {
constructor(service: any, serviceSetting: any) {
super(service, serviceSetting)
// The connection settings.
let connectionsSettings_ = new ComplexSetting("Connections", `LDAP connections (${Object.keys(service.Connections).length})`)
let connectionsSetting = new ConnectionsSetting(service.Connections)
connectionsSetting.onCreateConnection = ()=>{
// Create a new connection setting...
console.log("create a new LDAP connection here...")
connectionsSetting.addConnectionSetting("new_connection", {Id: "new_connection", Name:"new_connection", Host:"localhost", User:"", Password:"", Port:389})
}
connectionsSettings_.addSetting(connectionsSetting)
serviceSetting.addSetting(connectionsSettings_)
let syncLdap = new ActionSetting("Sync", "synchronize ldap and globular account and groups", () => {
// Application.globular.ldapService.
let rqst = new SynchronizeRequest
Application.globular.ldapService.synchronize(rqst, {
token: localStorage.getItem("user_token"),
application: Model.application,
domain: Model.domain,
address: Model.address
}).then(rsp => {
// ApplicationView.displayMessage(err, 3000)
console.log("synchronization start...", this.service)
}).catch(err => {
ApplicationView.displayMessage(err, 3000)
})
})
// Append the synch button
serviceSetting.addSetting(syncLdap)
}
}
// SQL
export class SqlServiceSetting extends ServiceSetting {
constructor(service: any, serviceSetting: any) {
super(service, serviceSetting)
}
}
// Persistence
export class PersistenceServiceSetting extends ServiceSetting {
constructor(service: any, serviceSetting: any) {
super(service, serviceSetting)
}
}
// DNS
export class DnsServiceSetting extends ServiceSetting {
constructor(service: any, serviceSetting: any) {
super(service, serviceSetting)
// There is the service specific settings.
let domains = new StringListSetting("Domains", "List of domains managed by the dns")
if (service["Domains"] != undefined) {
domains.setValues(service["Domains"])
}
let dnsPortSetting = new NumberSetting("DNS port number", "Enter the DNS port number")
dnsPortSetting.setValue(service["DnsPort"])
dnsPortSetting.onchange = () => {
service["DnsPort"]= parseInt(dnsPortSetting.getValue())
this.needSave = true
}
serviceSetting.addSetting(dnsPortSetting)
// on change event.
domains.onchange = () => {
service["Domains"]= domains.getValues()
this.needSave = true
}
// Append the synch button
serviceSetting.addSetting(domains)
}
}