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)
1,254 lines (1,038 loc) • 52.7 kB
text/typescript
//import { SetEmailResponse } from "globular-web-client/admin/admin_pb";
import { ClearAllLogRqst, DeleteLogRqst, DeleteLogRsp, GetLogRqst, GetLogRsp, LogInfo, Occurence } from "globular-web-client/log/log_pb";
import { Account } from "./Account";
import { Application } from "./Application";
import { ApplicationView } from "./ApplicationView";
import { RoleManager } from "./components/Role"
import { GroupManager } from "./components/Group"
import { ImageCropperSetting, SettingsMenu, SettingsPanel, ComplexSetting, EmailSetting, StringSetting, RadioGroupSetting, OnOffSetting, NumberSetting, ActionSetting, VideoConversionErrorsManager, VideoConversionLogsManager, PasswordSetting } from "./components/Settings";
import { Model } from "./Model";
import "@polymer/iron-icons/maps-icons";
import "@polymer/iron-icons/social-icons";
import "@polymer/iron-icons/hardware-icons";
import "@polymer/iron-icons/notification-icons";
import { ApplicationManager } from "./components/Applications";
import { PeersManager } from "./components/Peers";
import { OrganizationManager } from "./components/Organization";
import { AccountManager, ExternalAccountManager } from "./components/Account";
import { StartProcessVideoRequest, StopProcessVideoRequest, IsProcessVideoRequest, SetVideoConversionRequest, SetVideoStreamConversionRequest, SetStartVideoConversionHourRequest, SetMaximumVideoConversionDelayRequest, VideoConversionError, GetVideoConversionErrorsRequest, GetVideoConversionErrorsResponse, ClearVideoConversionErrorRequest, ClearVideoConversionErrorsRequest, VideoConversionLog, ClearVideoConversionLogsRequest, ClearVideoConversionLogsResponse, ClearVideoConversionErrorResponse, ClearVideoConversionErrorsResponse, GetVideoConversionLogsRequest, GetVideoConversionLogsResponse } from "globular-web-client/file/file_pb";
import { GetServiceConfigurationByIdRequest } from "globular-web-client/config_manager/config_pb";
import { PermissionsManager, ResourcesPermissionsManager } from "./components/Permissions";
export class Settings {
protected settingsMenu: SettingsMenu;
protected settingsPanel: SettingsPanel;
// That will create a new setting page.
constructor(settingsMenu: SettingsMenu, settingsPanel: SettingsPanel) {
this.settingsMenu = settingsMenu;
this.settingsPanel = settingsPanel;
}
// Those functions must be impletmented.
public load() {
}
public save() {
}
}
/**
* Model for user settings.
*/
export class UserSettings extends Settings {
private account: any;
// This is where the setting is display.
constructor(account: Account, settingsMenu: SettingsMenu, settingsPanel: SettingsPanel) {
super(settingsMenu, settingsPanel);
this.account = account
// Create the settings menu and panel here
this.settingsMenu.appendSettingsMenuItem("account-box", "User");
// Create General informations setting's
let userSettingsPage = <any>settingsPanel.appendSettingsPage("User");
// Create general user settings ...
let generalSettings = userSettingsPage.appendSettings("General", "Those information's can be view by other's user's");
// The profile picture.
let userPictureSetting = new ComplexSetting("Picture", "Change profile picture.")
generalSettings.addSetting(userPictureSetting)
// Here I will append the image cropper in order for the user to change it profile
// picture.
let imageCropperSettings = new ImageCropperSetting("Picture", "Change the user picture", account.id, account.profilePicture)
userPictureSetting.addSetting(imageCropperSettings)
// The user name.
let userNameSetting = new ComplexSetting("Name", "Change the user name")
// Set the user setting complex content.
let firstNameSetting = new StringSetting("First Name", "Enter your first name here.")
firstNameSetting.setValue(account.firstName)
userNameSetting.addSetting(firstNameSetting)
let lastNameSetting = new StringSetting("Last Name", "Enter your Last name here.")
lastNameSetting.setValue(account.lastName)
userNameSetting.addSetting(lastNameSetting)
let middleNameSetting = new StringSetting("Middle Name", "Enter middle letter/name")
middleNameSetting.setValue(account.middleName)
userNameSetting.addSetting(middleNameSetting)
generalSettings.addSetting(userNameSetting)
// Change the password.
let userPasswordSetting = new ComplexSetting("Password", "Change account password")
generalSettings.addSetting(userPasswordSetting)
let passowrdSetting = new PasswordSetting("Password", "Change account password")
userPasswordSetting.addSetting(passowrdSetting)
generalSettings.addSetting(userPasswordSetting)
// The user email address.
let userEmailSetting = new EmailSetting("Email", "Change the user email")
userEmailSetting.setValue(account.email)
generalSettings.addSetting(userEmailSetting)
// The set the application mode...
let displayModeSelector = new RadioGroupSetting("Theme", "Ligth mode or dark mode")
displayModeSelector.setChoices(["light", "dark"])
displayModeSelector.onSelect = (value) => {
if (localStorage.getItem(account.id) != null) {
let theme = localStorage.getItem(account.id + "_theme")
let html = document.querySelector("html")
if (theme != null) {
if (theme != value) {
displayModeSelector.setValue(value)
localStorage.setItem(account.id + "_theme", value)
localStorage.setItem("globular_theme", value)
html.setAttribute("theme", value)
}
} else {
localStorage.setItem(account.id + "_theme", value)
localStorage.setItem("globular_theme", value)
html.setAttribute("theme", value)
}
} else {
localStorage.setItem(account.id + "_theme", value)
localStorage.setItem("globular_theme", value)
html.setAttribute("theme", value)
}
}
let theme = localStorage.getItem(account.id + "_theme")
let html = document.querySelector("html")
if (theme != null) {
displayModeSelector.setValue(theme)
html.setAttribute("theme", theme)
} else if (html.getAttribute("theme") != null) {
displayModeSelector.setValue(html.getAttribute("theme"))
} else {
displayModeSelector.setValue("light")
}
generalSettings.addSetting(displayModeSelector)
Application.eventHub.subscribe("save_settings_evt",
(uuid: string) => {
},
(needSave: boolean) => {
if (needSave) {
// set the change.
account.firstName = firstNameSetting.getValue();
account.lastName = lastNameSetting.getValue();
account.middleName = middleNameSetting.getValue();
account.profilePicture = imageCropperSettings.getValue();
account.save(
() => {
imageCropperSettings.setValue(account.profilePicture)
},
(err: any) => {
console.log(err)
})
} else {
// revert the change.
firstNameSetting.setValue(account.firstName)
lastNameSetting.setValue(account.lastName)
middleNameSetting.setValue(account.middleName)
imageCropperSettings.setValue(account.profilePicture)
}
}, true)
}
}
/**
* Model to save application settings.
*/
export class RoleSettings extends Settings {
roleManager: RoleManager;
// The application.
constructor(settingsMenu: SettingsMenu, settingsPanel: SettingsPanel) {
super(settingsMenu, settingsPanel);
settingsMenu.appendSettingsMenuItem("notification:enhanced-encryption", "Roles");
let roleSettingPage = <any>settingsPanel.appendSettingsPage("Roles");
// Append a title.
let html = `
<style>
.title {
font-size: 1.25rem;
text-transform: uppercase;
color: var(--cr-primary-text-color);
font-weight: 400;
letter-spacing: .25px;
margin-bottom: 12px;
margin-top: var(--cr-section-vertical-margin);
outline: none;
padding-bottom: 4px;
padding-left: 8px;
padding-top: 16px;
}
.subtitle{
font-size: 1rem;
text-align: left;
padding-bottom: 35px;
}
</style>
<div class="title">
Roles
</div>
<span class="subtitle" style="font-size: 1rem;">roles are defines in package.json </span>
`
// Display the file explorer...
roleSettingPage.appendChild(document.createRange().createContextualFragment(html));
this.roleManager = new RoleManager()
roleSettingPage.appendChild(this.roleManager)
}
}
/**
* Model to save application settings.
*/
export class GroupSettings extends Settings {
groupManager: GroupManager;
// The application.
constructor(settingsMenu: SettingsMenu, settingsPanel: SettingsPanel) {
super(settingsMenu, settingsPanel);
settingsMenu.appendSettingsMenuItem("social:people", "Groups");
let groupSettingPage = <any>settingsPanel.appendSettingsPage("Groups");
// Append a title.
let html = `
<style>
.title {
font-size: 1.25rem;
text-transform: uppercase;
color: var(--cr-primary-text-color);
font-weight: 400;
letter-spacing: .25px;
margin-bottom: 12px;
margin-top: var(--cr-section-vertical-margin);
outline: none;
padding-bottom: 4px;
padding-left: 8px;
padding-top: 16px;
}
.subtitle{
font-size: 1rem;
text-align: left;
padding-bottom: 15px;
}
</style>
<div class="title">
Groups
</div>
<span class="subtitle" style="font-size: 1rem;">groups are use to manage ressource access like files.</span>
`
// Display the file explorer...
groupSettingPage.appendChild(document.createRange().createContextualFragment(html));
this.groupManager = new GroupManager()
groupSettingPage.appendChild(this.groupManager)
}
}
export class OrganizationSettings extends Settings {
organizationManager: OrganizationManager;
// The application.
constructor(settingsMenu: SettingsMenu, settingsPanel: SettingsPanel) {
super(settingsMenu, settingsPanel);
settingsMenu.appendSettingsMenuItem("social:domain", "Organizations");
let organizationSettingPage = <any>settingsPanel.appendSettingsPage("Organizations");
// Append a title.
let html = `
<style>
.title {
font-size: 1.25rem;
text-transform: uppercase;
color: var(--cr-primary-text-color);
font-weight: 400;
letter-spacing: .25px;
margin-bottom: 12px;
margin-top: var(--cr-section-vertical-margin);
outline: none;
padding-bottom: 4px;
padding-left: 8px;
padding-top: 16px;
}
.subtitle{
font-size: 1rem;
text-align: left;
padding-bottom: 35px;
}
</style>
<div class="title">
Organizations
</div>
<span class="subtitle" style="font-size: 1rem;">Aggregation of accouts, groups, roles and applications used to manage permissions</span>
`
// Display the file explorer...
organizationSettingPage.appendChild(document.createRange().createContextualFragment(html));
this.organizationManager = new OrganizationManager()
organizationSettingPage.appendChild(this.organizationManager)
}
}
export class ApplicationsSettings extends Settings {
applicationManager: ApplicationManager;
// The application.
constructor(settingsMenu: SettingsMenu, settingsPanel: SettingsPanel) {
super(settingsMenu, settingsPanel);
settingsMenu.appendSettingsMenuItem("icons:settings-applications", "Applications");
let applicationsSettingPage = <any>settingsPanel.appendSettingsPage("Applications");
// Append a title.
let html = `
<div class="title">
Applications
</div>
<div class="subtitle-div">
<span class="subtitle" style="font-size: 1rem; flex-grow: 1;">Manage applications</span>
<paper-icon-button id="install-application-btn" icon="add" title="install application"> </paper-icon-button>
</div>
`
// Display the file explorer...
applicationsSettingPage.appendChild(document.createRange().createContextualFragment(html));
this.applicationManager = new ApplicationManager()
applicationsSettingPage.appendChild(this.applicationManager)
// Here is to code to get the list of available applications from the package manager.
let installApplicationBtn = applicationsSettingPage.querySelector("#install-application-btn")
// Install application
installApplicationBtn.onclick = () => {
// So here I will get the list of availble package from the pacakage manager.
// Get all package infos from that localisation.
}
}
}
export class PeersSettings extends Settings {
peersManager: PeersManager;
// The application.
constructor(settingsMenu: SettingsMenu, settingsPanel: SettingsPanel) {
super(settingsMenu, settingsPanel);
settingsMenu.appendSettingsMenuItem("hardware:computer", "Peers");
let peersSettingPage = <any>settingsPanel.appendSettingsPage("Peers");
// Append a title.
let html = `
<style>
.title {
font-size: 1.25rem;
text-transform: uppercase;
color: var(--cr-primary-text-color);
font-weight: 400;
letter-spacing: .25px;
margin-bottom: 12px;
margin-top: var(--cr-section-vertical-margin);
outline: none;
padding-bottom: 4px;
padding-left: 8px;
padding-top: 16px;
}
.subtitle{
font-size: 1rem;
text-align: left;
padding-bottom: 15px;
}
</style>
<div class="title">
Peers
</div>
<span class="subtitle" style="font-size: 1rem;">Manage peers permissions</span>
`
// Display the file explorer...
peersSettingPage.appendChild(document.createRange().createContextualFragment(html));
this.peersManager = new PeersManager()
peersSettingPage.appendChild(this.peersManager)
}
}
/**
* Model to save application settings.
*/
export class ResourcesPermissionsSettings extends Settings {
// The application.
constructor(settingsMenu: SettingsMenu, settingsPanel: SettingsPanel) {
super(settingsMenu, settingsPanel);
settingsMenu.appendSettingsMenuItem("icons:lock", "Permissions");
let groupSettingPage = <any>settingsPanel.appendSettingsPage("Permissions");
// Append a title.
let html = `
<style>
.title {
font-size: 1.25rem;
text-transform: uppercase;
color: var(--cr-primary-text-color);
font-weight: 400;
letter-spacing: .25px;
margin-bottom: 12px;
margin-top: var(--cr-section-vertical-margin);
outline: none;
padding-bottom: 4px;
padding-left: 8px;
padding-top: 16px;
}
.subtitle{
font-size: 1rem;
text-align: left;
padding-bottom: 35px;
}
</style>
<div class="title">
Resources Permissions
</div>
<span class="subtitle" style="font-size: 1rem;">Manage resources permissions ex: blog, group, file, application...</span>
`
// Display the file explorer...
groupSettingPage.appendChild(document.createRange().createContextualFragment(html));
groupSettingPage.appendChild(new ResourcesPermissionsManager())
}
}
// Return the list of conversion errors
function getConversionErrors(callback: (errors: Array<VideoConversionError>) => void) {
let rqst = new GetVideoConversionErrorsRequest
Model.globular.fileService.getVideoConversionErrors(rqst, {
token: localStorage.getItem("user_token"),
application: Model.application,
domain: Model.domain,
address: Model.address
}).then((rsp: GetVideoConversionErrorsResponse) => {
callback(rsp.getErrorsList())
}).catch(err => {
ApplicationView.displayMessage(err, 3000)
})
}
function getConversionLogs(callback: (errors: Array<VideoConversionLog>) => void) {
let rqst = new GetVideoConversionLogsRequest
Model.globular.fileService.getVideoConversionLogs(rqst, {
token: localStorage.getItem("user_token"),
application: Model.application,
domain: Model.domain,
address: Model.address
}).then((rsp: GetVideoConversionLogsResponse) => {
callback(rsp.getLogsList())
}).catch(err => {
ApplicationView.displayMessage(err, 3000)
})
}
/**
* Model to manage users account settings.
*/
export class VideoSettings extends Settings {
private needSave: boolean;
private config: any;
// The application.
constructor(settingsMenu: SettingsMenu, settingsPanel: SettingsPanel) {
super(settingsMenu, settingsPanel);
settingsMenu.appendSettingsMenuItem("maps:local-movies", "Video");
let viedoSettingPage = <any>settingsPanel.appendSettingsPage("Video");
// Create general user settings ...
let conversionSettings = viedoSettingPage.appendSettings("Conversion", "Video Conversion settings");
// Enable/Disable video conversion.
let enableConversionSetting = new OnOffSetting("convert to MP4", "enable/disable automatic video conversion")
enableConversionSetting.setValue(true)
conversionSettings.addSetting(enableConversionSetting)
let enableStreamConversionSetting = new OnOffSetting("convert MP4 to HLS", "enable/disable automatic video stream conversion")
enableStreamConversionSetting.setValue(true)
conversionSettings.addSetting(enableStreamConversionSetting)
let startConversionHour = new NumberSetting("start conversion hour", "The conversion will begin at this hour")
startConversionHour.setValue("00:00")
startConversionHour.getElement().setAttribute("type", "time")
startConversionHour.getElement().setAttribute("max", "24:00")
startConversionHour.getElement().setAttribute("min", "00:00")
conversionSettings.addSetting(startConversionHour)
let maxConversionDelay = new NumberSetting("maximum conversion delay", "Maximum conversion runing time, stop processing new file past this delay (in hours)")
maxConversionDelay.setValue("08:00")
maxConversionDelay.getElement().setAttribute("type", "time")
maxConversionDelay.getElement().setAttribute("max", "24:00")
maxConversionDelay.getElement().setAttribute("min", "00:00")
conversionSettings.addSetting(maxConversionDelay)
let fileServerConfig = Model.globular.getConfigs("file.FileService")[0]
let rqst_ = new GetServiceConfigurationByIdRequest
rqst_.setId(fileServerConfig.Id)
Model.globular.configurationService.getServiceConfigurationById(rqst_, {
token: localStorage.getItem("user_token"),
application: Model.application,
domain: Model.domain,
address: Model.address
}).then(rsp => {
let configStr = rsp.getConfig()
this.config = JSON.parse(configStr)
enableConversionSetting.setValue(this.config.AutomaticVideoConversion)
enableStreamConversionSetting.setValue(this.config.AutomaticStreamConversion)
startConversionHour.setValue(this.config.StartVideoConversionHour)
maxConversionDelay.setValue(this.config.MaximumVideoConversionDelay)
}).catch(err => {
ApplicationView.displayMessage(err, 3000)
})
enableConversionSetting.onchange = () => {
// this.conversionSettings.KeepAlive = keepAlive.getValue()
let conversion = enableConversionSetting.getValue()
if (conversion) {
enableStreamConversionSetting.style.display = "flex"
startConversionHour.style.display = "flex"
maxConversionDelay.style.display = "flex"
} else {
enableStreamConversionSetting.style.display = "none"
startConversionHour.style.display = "none"
maxConversionDelay.style.display = "none"
}
// keep in local value
this.config.AutomaticVideoConversion = conversion
this.needSave = true
}
// The stream conversion setting.
enableStreamConversionSetting.onchange = () => {
// this.conversionSettings.KeepAlive = keepAlive.getValue()
let conversion = enableStreamConversionSetting.getValue()
// keep in local value
this.config.AutomaticStreamConversion = conversion
this.needSave = true
}
startConversionHour.onchange = () => {
// this.conversionSettings.KeepAlive = keepAlive.getValue()
let value = startConversionHour.getValue()
// keep in local value
this.config.StartVideoConversionHour = value
this.needSave = true
}
maxConversionDelay.onchange = () => {
// this.conversionSettings.KeepAlive = keepAlive.getValue()
let value = maxConversionDelay.getValue()
// keep in local value
this.config.MaximumVideoConversionDelay = value
this.needSave = true
}
// The convert button will start video processing...
let startConvertVideoAction = new ActionSetting("Start", "Convert video to MP4 or HLS", () => {
// Application.globular.ldapService.
let rqst = new StartProcessVideoRequest
Model.globular.fileService.startProcessVideo(rqst, {
token: localStorage.getItem("user_token"),
application: Model.application,
domain: Model.domain,
address: Model.address
}).then(rsp => {
stopConvertVideoAction.style.display = "flex"
startConvertVideoAction.style.display = "none"
ApplicationView.displayMessage("video conversion is running...", 3500)
}).catch(err => {
ApplicationView.displayMessage(err, 3000)
})
})
conversionSettings.addSetting(startConvertVideoAction)
// The convert button will start video processing...
let stopConvertVideoAction = new ActionSetting("Stop", "Stop video conversion...", () => {
// Application.globular.ldapService.
let rqst = new StopProcessVideoRequest
Model.globular.fileService.stopProcessVideo(rqst, {
token: localStorage.getItem("user_token"),
application: Model.application,
domain: Model.domain,
address: Model.address
}).then(rsp => {
stopConvertVideoAction.style.display = "none"
startConvertVideoAction.style.display = "flex"
ApplicationView.displayMessage("video conversion is stopped...", 3500)
}).catch(err => {
ApplicationView.displayMessage(err, 3000)
})
})
conversionSettings.addSetting(stopConvertVideoAction)
let rqst = new IsProcessVideoRequest
Model.globular.fileService.isProcessVideo(rqst, {
token: localStorage.getItem("user_token"),
application: Model.application,
domain: Model.domain,
address: Model.address
}).then(rsp => {
if (rsp.getIsprocessvideo()) {
stopConvertVideoAction.style.display = "flex"
startConvertVideoAction.style.display = "none"
} else {
stopConvertVideoAction.style.display = "none"
startConvertVideoAction.style.display = "flex"
}
}).catch(err => {
ApplicationView.displayMessage(err, 3000)
})
// Need save...
Application.eventHub.subscribe("save_settings_evt",
(uuid: string) => {
},
() => {
if (this.needSave) {
this.saveSetConversion(enableConversionSetting.getValue())
this.saveSetStreamConversion(enableStreamConversionSetting.getValue())
this.saveMaxConversionDelay(maxConversionDelay.getValue())
this.saveStartConversionHour(startConversionHour.getValue())
}
})
//////////////////// Now the convertion log's info to make it interface interactive.
let conversionLogsSettings = viedoSettingPage.appendSettings("Logs", "Convertion activity summary")
let videoConversionLogsManager = new VideoConversionLogsManager(this.clearVideoConversionLogs, this.refreshVideoConversionLogs)
conversionLogsSettings.addSetting(videoConversionLogsManager)
getConversionLogs(logs => {
videoConversionLogsManager.setLogs(logs)
Model.getGlobules().forEach(g => {
// I will now listen for conversion event...
g.eventHub.subscribe("conversion_log_event", uuid => { }, evt => {
let obj = JSON.parse(evt)
let log = new VideoConversionLog()
log.setLogTime(obj.logTime)
log.setPath(obj.path)
log.setStatus(obj.status)
log.setMsg(obj.msg)
videoConversionLogsManager.setLog(log)
}, false)
})
})
//////////////////// Now the conversion error //////////////////
// Create general user settings ...
let conversionErrorsSettings = viedoSettingPage.appendSettings("Errors", "List of conversion errors");
// Here I will create the interface to display the list of errors and remove error from the list to.
let videoConversionErrorsManager = new VideoConversionErrorsManager(this.deletVideoConversionError, this.clearVideoConversionErrors, this.refreshVideoConversionErrors)
conversionErrorsSettings.addSetting(videoConversionErrorsManager)
getConversionErrors(errors => {
videoConversionErrorsManager.setErrors(errors)
Model.getGlobules().forEach(g => {
// I will now listen for conversion event...
g.eventHub.subscribe("conversion_log_error", uuid => { }, evt => {
let obj = JSON.parse(evt)
let err = new VideoConversionError
err.setError(obj.error)
err.setPath(obj.path)
videoConversionErrorsManager.setError(err)
}, false)
})
})
}
refreshVideoConversionLogs(callback: (logs: Array<VideoConversionLog>) => void) {
getConversionLogs(logs => {
callback(logs)
})
}
clearVideoConversionLogs() {
let rqst = new ClearVideoConversionLogsRequest
Model.globular.fileService.clearVideoConversionLogs(rqst, {
token: localStorage.getItem("user_token"),
application: Model.application,
domain: Model.domain,
address: Model.address
}).then((rsp: ClearVideoConversionLogsResponse) => {
ApplicationView.displayMessage("log clear", 3000)
}).catch(err => {
ApplicationView.displayMessage(err, 3000)
})
}
deletVideoConversionError(err: VideoConversionError) {
let rqst = new ClearVideoConversionErrorRequest
rqst.setPath(err.getPath())
Model.globular.fileService.clearVideoConversionError(rqst, {
token: localStorage.getItem("user_token"),
application: Model.application,
domain: Model.domain,
address: Model.address
}).then((rsp: ClearVideoConversionErrorResponse) => {
ApplicationView.displayMessage("error was deleted, you can try to convert the video again", 3000)
}).catch(err => {
ApplicationView.displayMessage(err, 3000)
})
}
refreshVideoConversionErrors(callback: (errors: Array<VideoConversionError>) => void) {
getConversionErrors(errors => {
callback(errors)
})
}
clearVideoConversionErrors() {
let rqst = new ClearVideoConversionErrorsRequest
Model.globular.fileService.clearVideoConversionErrors(rqst, {
token: localStorage.getItem("user_token"),
application: Model.application,
domain: Model.domain,
address: Model.address
}).then((rsp: ClearVideoConversionErrorsResponse) => {
ApplicationView.displayMessage("all video convesion are deleted, file in that list will not be convert", 3000)
}).catch(err => {
ApplicationView.displayMessage(err, 3000)
})
}
// Set|Reset automatic conversion.
saveSetConversion(value: boolean) {
// Set video Conversion parameter...
let rqst = new SetVideoConversionRequest;
rqst.setValue(value);
Model.globular.fileService.setVideoConversion(rqst, {
token: localStorage.getItem("user_token"),
application: Model.application,
domain: Model.domain,
address: Model.address
}).then(() => {
}).catch(err => {
ApplicationView.displayMessage(err, 3000)
})
}
// Set|Reset automatic steam conversion.
saveSetStreamConversion(value: boolean) {
// Set video Conversion parameter...
let rqst = new SetVideoStreamConversionRequest;
rqst.setValue(value);
Model.globular.fileService.setVideoStreamConversion(rqst, {
token: localStorage.getItem("user_token"),
application: Model.application,
domain: Model.domain,
address: Model.address
}).then(() => {
}).catch(err => {
ApplicationView.displayMessage(err, 3000)
})
}
// Set|Reset start conversion time.
saveStartConversionHour(value: string) {
// Set video Conversion parameter...
let rqst = new SetStartVideoConversionHourRequest;
rqst.setValue(value);
Model.globular.fileService.setStartVideoConversionHour(rqst, {
token: localStorage.getItem("user_token"),
application: Model.application,
domain: Model.domain,
address: Model.address
}).then(() => {
}).catch(err => {
ApplicationView.displayMessage(err, 3000)
})
}
// Set|Reset maximum conversion delay.
saveMaxConversionDelay(value: string) {
// Set video Conversion parameter...
let rqst = new SetMaximumVideoConversionDelayRequest;
rqst.setValue(value);
Model.globular.fileService.setMaximumVideoConversionDelay(rqst, {
token: localStorage.getItem("user_token"),
application: Model.application,
domain: Model.domain,
address: Model.address
}).then(() => {
}).catch(err => {
ApplicationView.displayMessage(err, 3000)
})
}
}
/**
* Model to manage users account settings.
*/
export class UsersSettings extends Settings {
localAccountManager: AccountManager;
externalAccountManager: ExternalAccountManager;
// The application.
constructor(settingsMenu: SettingsMenu, settingsPanel: SettingsPanel) {
super(settingsMenu, settingsPanel);
settingsMenu.appendSettingsMenuItem("social:people", "Accounts");
let accountSettingPage = <any>settingsPanel.appendSettingsPage("Accounts");
// Append a title.
let html = `
<style>
.title {
font-size: 1.25rem;
text-transform: uppercase;
color: var(--cr-primary-text-color);
font-weight: 400;
letter-spacing: .25px;
margin-bottom: 12px;
margin-top: var(--cr-section-vertical-margin);
outline: none;
padding-bottom: 4px;
padding-left: 8px;
padding-top: 16px;
}
.subtitle{
font-size: 1rem;
text-align: left;
padding-bottom: 35px;
}
</style>
<div class="title">
Accounts
</div>
<span class="subtitle" style="font-size: 1rem;">Manage local accounts</span>
`
// Display the file explorer...
accountSettingPage.appendChild(document.createRange().createContextualFragment(html));
this.localAccountManager = new AccountManager()
accountSettingPage.appendChild(this.localAccountManager)
// Now the external account use to display account not managed by the server but that can access ressources via
// peer connections.
this.externalAccountManager = new ExternalAccountManager()
accountSettingPage.appendChild(this.externalAccountManager)
}
}
/**
* Model to save application settings.
*/
export class LogSettings extends Settings {
private infos: Array<LogInfo>
private table: any;
private header: any;
private errorCheckBox: any;
private warningCheckBox: any;
private infoCheckBox: any;
// The application.
constructor(settingsMenu: SettingsMenu, settingsPanel: SettingsPanel) {
super(settingsMenu, settingsPanel);
this.infos = new Array<LogInfo>();
settingsMenu.appendSettingsMenuItem("error", "Logs");
let logSettingPage = <any>settingsPanel.appendSettingsPage("Logs");
// Append a title.
let html = `
<style>
.title {
position: relative;
display: flex;
font-size: 1.25rem;
text-transform: uppercase;
color: var(--cr-primary-text-color);
font-weight: 400;
letter-spacing: .25px;
margin-bottom: 12px;
margin-top: var(--cr-section-vertical-margin);
outline: none;
padding-bottom: 4px;
padding-left: 8px;
padding-top: 16px;
}
.title div{
padding-right: 25px;
}
.title span{
padding-left: 4px;
padding-right: 10px;
}
.warning{
--iron-icon-fill-color: var(--google-yellow-700);
}
.error{
--iron-icon-fill-color: var(--error-color);
}
.info{
--iron-icon-fill-color: var(--google-blue-700);
}
paper-checkbox {
align-self: center;
--paper-checkbox-size: 1rem;
padding-bottom: 2px;
}
</style>
<div class="title ">
<div style="display: flex; display: flex;flex-grow: 1;align-items: center;">
<div>
<iron-icon icon="error" class="error"></iron-icon icon>
<span>Errors</span>
<paper-checkbox id="error_log_checkbox" checked></paper-checkbox>
</div>
<div>
<iron-icon icon="warning" class="warning"></iron-icon icon>
<span>Warnings</span>
<paper-checkbox id="warning_log_checkbox" ></paper-checkbox>
</div>
<div>
<iron-icon icon="info" class="info"></iron-icon icon>
<span>Infos</span>
<paper-checkbox id="info_log_checkbox"></paper-checkbox>
</div>
</div>
<paper-button title="delete diplayed logs." style="align-self: flex-end; font-size: 1rem;">CLEAR</paper-button>
</div>
`
logSettingPage.appendChild(document.createRange().createContextualFragment(html));
this.errorCheckBox = <any>logSettingPage.querySelector("#error_log_checkbox");
this.warningCheckBox = <any>logSettingPage.querySelector("#warning_log_checkbox");
this.infoCheckBox = <any>logSettingPage.querySelector("#info_log_checkbox");
this.infoCheckBox.onclick = this.warningCheckBox.onclick = this.errorCheckBox.onclick = () => {
this.table.clear(); // remove all values...
if (this.errorCheckBox.checked) {
this.getLogs("/error/*",
(infos: Array<LogInfo>) => {
this.setInfos(infos)
this.getLogs("/fatal/*",
(infos: Array<LogInfo>) => {
this.setInfos(infos)
},
(err: any) => {
ApplicationView.displayMessage(err, 3000)
})
},
(err: any) => {
ApplicationView.displayMessage(err, 3000)
})
}
if (this.warningCheckBox.checked) {
this.getLogs("/warning/*",
(infos: Array<LogInfo>) => {
this.setInfos(infos)
},
(err: any) => {
ApplicationView.displayMessage(err, 3000)
})
}
if (this.infoCheckBox.checked) {
this.getLogs("/info/*",
(infos: Array<LogInfo>) => {
this.setInfos(infos)
this.getLogs("/debug/*",
(infos: Array<LogInfo>) => {
this.setInfos(infos)
this.getLogs("/trace/*",
(infos: Array<LogInfo>) => {
this.setInfos(infos)
},
(err: any) => {
ApplicationView.displayMessage(err, 3000)
})
},
(err: any) => {
ApplicationView.displayMessage(err, 3000)
})
},
(err: any) => {
ApplicationView.displayMessage(err, 3000)
})
}
}
logSettingPage.querySelector("paper-button").onclick = () => {
let data = this.table.getFilteredData();
if (data.length < this.table.data.length) {
let deleteRows = (index: number) => {
let index_ = parseInt(data[index].index)
this.deleteLog(this.infos[index_],
() => {
// remove the data at given index.
this.table.deleteRow(index_)
index += 1
if (index < data.length) {
deleteRows(index)
}
},
(err: any) => {
ApplicationView.displayMessage(err, 3000);
})
}
let index = 0
deleteRows(index)
} else {
// Remove error/fatal logs.
if (this.errorCheckBox.checked) {
this.clearLogs("/error/" + Application.application + "/*", () => {
this.table.clear();
}, (err: any) => { ApplicationView.displayMessage(err, 300) })
this.clearLogs("/fatal/" + Application.application + "/*", () => {
this.table.clear();
}, (err: any) => { ApplicationView.displayMessage(err, 300) })
}
// Remove warnings
if (this.warningCheckBox.checked) {
this.clearLogs("/warning/" + Application.application + "/*", () => {
this.table.clear();
}, (err: any) => { ApplicationView.displayMessage(err, 300) })
}
// Remove debug, info and tace.
if (this.infoCheckBox.checked) {
this.clearLogs("/info/" + Application.application + "/*", () => {
this.table.clear();
}, (err: any) => { ApplicationView.displayMessage(err, 300) })
this.clearLogs("/debug/" + Application.application + "/*", () => {
this.table.clear();
}, (err: any) => { ApplicationView.displayMessage(err, 300) })
this.clearLogs("/trace/" + Application.application + "/*", () => {
this.table.clear();
}, (err: any) => { ApplicationView.displayMessage(err, 300) })
}
}
}
// Now I will get the
this.table = <any>(document.createElement("table-element"));
// Create the header element.
this.header = <any>(document.createElement("table-header-element"))
this.header.fixed = true;
this.table.appendChild(this.header)
this.table.rowheight = 120
this.table.style.width = "1150px"
this.table.style.maxHeight = "820px";
let titles = ["Level", "Occurences", "Method", "Detail"]
titles.forEach(title => {
const headerCell = <any>(document.createElement("table-header-cell-element"))
headerCell.innerHTML = `<table-sorter-element></table-sorter-element><div>${title}</div> <table-filter-element></table-filter-element>`
// Now I will set the way I will display the values.
if (title == "Occurences") {
headerCell.width = 320;
headerCell.onrender = (div: any, occurences: Array<Occurence>, row: number, column: number) => {
if (occurences != undefined) {
div.style.justifySelf = "flex-start"
div.style.display = "flex"
div.style.alignItems = "center"
div.parentNode.style.position = "relative"
// Display the list of occurrences as needed..
div.innerHTML = `
<div style="position: absolute; top: 0px; left: 0px; bottom: 0px; right: 0px;">
<div style="display: flex;">
<div style="display: flex; width: 32px; height: 32px; justify-content: center; align-items: center;position: relative;">
<iron-icon id="collapse-btn" icon="unfold-less" --iron-icon-fill-color:var(--palette-text-primary);"></iron-icon>
<paper-ripple class="circle" recenters=""></paper-ripple>
</div>
<div style="flex-grow: 1;">
${occurences.length}
</div>
</div>
<iron-collapse class="permissions" id="collapse-panel" style="display: flex; flex-direction: column; margin: 5px;">
</iron-collapse>
</div>
`
let collapse_btn = div.querySelector("#collapse-btn")
let collapse_panel = div.querySelector("#collapse-panel")
collapse_btn.onclick = () => {
if (!collapse_panel.opened) {
collapse_btn.icon = "unfold-more"
} else {
collapse_btn.icon = "unfold-less"
}
collapse_panel.toggle();
}
let range = document.createRange()
occurences.sort((a: Occurence, b: Occurence) => { return b.getDate() - a.getDate() })
// Now I will set the occurence infromations...
occurences.forEach(o => {
let html = `
<div style="display: flex; padding: 2px;">
<div>${new Date(o.getDate() * 1000).toLocaleString()} </div>
<div style="padding-left: 10px;">${o.getUserid() + " " + o.getApplication()}</div>
</div>
`
collapse_panel.appendChild(range.createContextualFragment(html))
})
}
}
} else if (title == "Level") {
headerCell.width = 100;
} else if (title == "Method") {
headerCell.width = 360;
} else if (title == "Detail") {
headerCell.width = 380;
}
this.header.appendChild(headerCell)
})
logSettingPage.appendChild(this.table);
this.table.data = [];
this.getLogs("/error/*",
(infos: Array<LogInfo>) => {
this.setInfos(infos)
},
(err: any) => {
ApplicationView.displayMessage(err, 3000)
})
}
setInfos(infos: Array<LogInfo>) {
// Here I will transform the the info to fit into the table.
infos.forEach((info: LogInfo) => {
let level = ""
if (info.getLevel() == 0) {
level = "fatal"
} else if (info.getLevel() == 1) {
level = "error"
} else if (info.getLevel() == 2) {
level = "warning"
} else if (info.getLevel() == 3) {
level = "info"
} else if (info.getLevel() == 4) {
level = "debug"
} else if (info.getLevel() == 5) {
level = "trace"
}
this.infos.push(info) //k