UNPKG

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)

569 lines (472 loc) 22.5 kB
import '@polymer/iron-icons/iron-icons.js'; import { Model } from '../Model'; import { AddAccountRoleRqst, AddRoleActionsRqst, CreateRoleRqst, DeleteRoleRqst, RemoveRoleActionRqst, Role, RemoveAccountRoleRqst } from 'globular-web-client/resource/resource_pb'; import { getAllRoles } from 'globular-web-client/api'; import { Application } from '../Application'; import { ApplicationView } from '../ApplicationView'; import { SearchableAccountList, SearchableList } from './List.js' import { GetAllActionsRequest } from 'globular-web-client/services_manager/services_manager_pb'; import { Account } from '../Account'; // Return a role with a given id. export function getRoleById(id, callback, errorCallback) { let r_ = null getAllRoles(Model.globular, roles => { roles.forEach(r => { if (r.getId() == id) { r_ = r } if (r_ == null) { if (r.getId() + "@" + r.getDomain() == id) { r_ = r } } }) if (r_ != null) { callback(r_) return } errorCallback("no role found with id " + id) }, errorCallback) } export class RoleManager extends HTMLElement { // attributes. // Create the applicaiton view. constructor() { super() // Set the shadow dom. this.attachShadow({ mode: 'open' }); // Innitialisation of the layout. this.shadowRoot.innerHTML = ` <style> paper-card{ background-color: var(--palette-background-paper); color: var(--palette-text-primary); } #create-role-btn{ top: -42px; right: 0px; position: absolute; } #container{ display: flex; flex-direction: column; position: relative; } .card-content { min-width: 728px; font-size: 1rem; padding: 0px; } @media (max-width: 800px) { .card-content{ min-width: 580px; } } @media (max-width: 600px) { .card-content{ min-width: 380px; } } </style> <div id="container"> <paper-card> <div class="card-content"> </div> </paper-card> <paper-icon-button icon="add" id="create-role-btn"></paper-icon-button> </div> ` // give the focus to the input. let content = this.shadowRoot.querySelector(".card-content") // give the focus to the input. let container = this.shadowRoot.querySelector("#container") let displayRoles = () => { content.innerHTML = "" // Here I will get the list of all roles. getAllRoles(Application.globular, (roles) => { roles.forEach(r => { if (r.getId() != "admin" && r.getId() != "guest") { let panel = new RolePanel(r) content.appendChild(panel) } }) }, err => { ApplicationView.displayMessage(err, 3000) }) } // call once displayRoles() Model.eventHub.subscribe("refresh_role_evt", uuid => { }, evt => { displayRoles() }, true) let createRoleBtn = this.shadowRoot.querySelector("#create-role-btn") createRoleBtn.onclick = () => { let html = ` <style> paper-card{ background-color: var(--palette-background-paper); color: var(--palette-text-primary); } #create-role-panel{ position: absolute; right: 0px; top: 0px; z-index: 1; background-color: var(--palette-background-paper); } #create-role-panel .card-content{ min-width: 200px; padding: 0px 10px 0px 10px; display: flex; flex-direction: column; } </style> <paper-card id="create-role-panel"> <div style="display: flex; align-items: center;"> <div style="flex-grow: 1; padding: 5px;"> Create Role </div> <paper-icon-button id="cancel-btn" icon="close"></paper-icon-button> </div> <div class="card-content"> <paper-input></paper-input> <paper-button style="align-self: end;">Create</paper-button> </div> </paper-card> ` let panel = container.querySelector("#create-role-panel") let input = null if (panel == undefined) { container.appendChild(document.createRange().createContextualFragment(html)) panel = container.querySelector("#create-role-panel") let closeBtn = panel.querySelector("#cancel-btn") closeBtn.onclick = () => { panel.parentNode.removeChild(panel) } input = panel.querySelector("paper-input") let createRoleButton = panel.querySelector("paper-button") // Create a new role. createRoleButton.onclick = () => { let roleId = input.value; if (roleId.length == 0) { ApplicationView.displayMessage("No role name was given!", 3000) setTimeout(() => { input.focus() }, 100) return } let createRoleRqst = new CreateRoleRqst let role = new Role role.setId(roleId) role.setName(roleId) role.setDomain(Model.domain) createRoleRqst.setRole(role) Model.globular.resourceService.createRole(createRoleRqst, { domain: Model.domain, address: Model.address, application: Model.application, token: localStorage.getItem("user_token") }) .then(rsp => { ApplicationView.displayMessage("Role " + roleId + "@" + Model.domain + " was created!", 3000) panel.parentNode.removeChild(panel) displayRoles() }).catch(err => { ApplicationView.displayMessage(err, 3000) setTimeout(() => { input.focus() }, 100) }) } } else { input = panel.querySelector("paper-input") } setTimeout(() => { input.focus() }, 100) } } // The connection callback. connectedCallback() { } } customElements.define('globular-role-manager', RoleManager) export class RolePanel extends HTMLElement { // attributes. // Create the applicaiton view. constructor(role) { super() // Set the shadow dom. this.attachShadow({ mode: 'open' }); // Keep group informations. this.role_ = role; // Innitialisation of the layout. this.shadowRoot.innerHTML = ` <style> #container{ display: flex; flex-direction: column; align-items: center; border-bottom: 1px solid var(--palette-background-default); background-color: var(--palette-background-paper); } #content{ padding: 15px; background-color: var(--palette-background-paper); color: var(--palette-text-primary); } .header{ display: flex; align-items: center; width: 100%; transition: background 0.2s ease,padding 0.8s linear; background-color: var(--palette-background-paper); } .header:hover{ -webkit-filter: invert(10%); filter: invert(10%); } .title{ flex-grow: 1; margin: 8px; font-size: 1.1rem; } img, iron-icon{ margin: 8px; } #collapse-panel{ display: flex; flex-direction: column; width: 100%; } #delete-role-btn{ font-size: .85rem; max-height: 32px; } </style> <div id="container"> <div class="header"> <span class="title">${role.getName() + "@" + role.getDomain()}</span> <paper-button id="delete-role-btn">Delete</paper-button> <div style="display: flex; width: 32px; height: 32px; justify-content: center; align-items: center;position: relative;"> <iron-icon id="hide-btn" icon="unfold-less" style="flex-grow: 1; --iron-icon-fill-color:var(--palette-text-primary);" icon="add"></iron-icon> <paper-ripple class="circle" recenters=""></paper-ripple> </div> </div> <iron-collapse id="collapse-panel" > </iron-collapse> </div> ` let content = this.shadowRoot.querySelector("#collapse-panel") this.hideBtn = this.shadowRoot.querySelector("#hide-btn") let deleteBtn = this.shadowRoot.querySelector("#delete-role-btn") deleteBtn.onclick = () => { this.onDeleteRole(role) } // Here I will create the searchable actions list. let actionsList = new SearchableList("Actions", role.getActionsList(), (action) => { // remove action... let removeActionRqst = new RemoveRoleActionRqst removeActionRqst.setAction(action) removeActionRqst.setRoleid(role.getId() + "@" + role.getDomain()) Model.globular.resourceService.removeRoleAction(removeActionRqst, { domain: Model.domain, address: Model.address, application: Model.application, token: localStorage.getItem("user_token") }) .then(rsp => { actionsList.removeItem(action) ApplicationView.displayMessage("Action " + action + " was removed from role " + role.getId() + "@" + role.getDomain(), 3000) }).catch(err => { ApplicationView.displayMessage(err, 3000) }) }, (action) => { ApplicationView.displayMessage("Action " + action + " was added to role " + role.getId() + "@" + role.getDomain(), 3000) }, (actions) => { // Now I will get the list of all actions install on the server. let getAllActionsRqst = new GetAllActionsRequest Model.globular.servicesManagerService.getAllActions(getAllActionsRqst, { domain: Model.domain, address: Model.address, application: Model.application, token: localStorage.getItem("user_token") }) .then(rsp => { let actions_ = rsp.getActionsList() actions.forEach(a => { actions_.splice(actions_.indexOf(a), 1); }); // sort the array. actions_.sort() let html = ` <style> #add-role-action-panel{ position: absolute; right: 0px; z-index: 1; } .card-content{ overflow-y: auto; min-width: 400px; max-height: 260px; overflow-y: auto; } paper-card{ background-color: var(--palette-background-paper); color: var(--palette-text-primary); } </style> <paper-card id="add-role-action-panel"> <div style="display: flex; align-items: center;"> <div style="flex-grow: 1; padding: 5px;"> Add Action </div> <paper-icon-button id="cancel-btn" icon="close"></paper-icon-button> </div> <div class="card-content"> <div></div> </div> </paper-card> ` let headerDiv = actionsList.getHeader() let panel = headerDiv.querySelector("#add-role-action-panel") if (panel == undefined) { headerDiv.appendChild(document.createRange().createContextualFragment(html)) panel = headerDiv.querySelector("#add-role-action-panel") panel.style.top = (headerDiv.offsetHeight / 2) + 14 + "px"; let closeBtn = panel.querySelector("#cancel-btn") closeBtn.onclick = () => { panel.parentNode.removeChild(panel) } actions_.forEach(a => { let html = ` <div class="item-div" style=""> <span style="flex-grow: 1;">${a}</span> <paper-icon-button id="add-action-btn" icon="add" role="button" tabindex="0" aria-disabled="false"></paper-icon-button> </div> ` let content = panel.querySelector(".card-content") content.appendChild(document.createRange().createContextualFragment(html)) let actionDiv = content.children[content.children.length - 1] let actionAddBtn = actionDiv.children[1] actionAddBtn.onclick = () => { let rqst = new AddRoleActionsRqst rqst.setRoleid(role.getId() + "@" + role.getDomain()) rqst.setActionsList([a]) Model.globular.resourceService.addRoleActions(rqst, { domain: Model.domain, address: Model.address, application: Model.application, token: localStorage.getItem("user_token") }) .then(rsp => { actionDiv.parentNode.removeChild(actionDiv) actionsList.appendItem(a) // call the onadditem.f actionsList.onadditem(a) }).catch(err => { ApplicationView.displayMessage(err, 3000) }) } }) } }).catch(err => { ApplicationView.displayMessage(err, 3000) }) }) content.appendChild(actionsList) // Now the account list. Account.getAccounts("{}", accounts => { // I will get the account object whit the given id. let list = [] this.role_.getMembersList().forEach(accountId => { let a_ = accounts.find(a => a.getId() + "@" + a.getDomain() === accountId); if (a_ != undefined) { list.push(a_) } }) let accountsList = new SearchableAccountList("Accounts", list, a => { accountsList.removeItem(a) let rqst = new RemoveAccountRoleRqst rqst.setRoleid(role.getId() + "@" + role.getDomain()) rqst.setAccountid(a.getId() + "@" + a.getDomain()) Model.globular.resourceService.removeAccountRole(rqst, { domain: Model.domain, address: Model.address, application: Model.application, token: localStorage.getItem("user_token") }) .then(rsp => { accountsList.removeItem(a) ApplicationView.displayMessage("Account " + a.getId() + "@" + a.getDomain() + " was removed from role " + role.getId() + "@" + role.getDomain(), 3000) }).catch(err => { accountsList.appendItem(a) // set it back ApplicationView.displayMessage(err, 3000) }) }, a => { let rqst = new AddAccountRoleRqst rqst.setRoleid(role.getId() + "@" + role.getDomain()) rqst.setAccountid(a.getId() + "@" + a.getDomain()) Model.globular.resourceService.addAccountRole(rqst, { domain: Model.domain, address: Model.address, application: Model.application, token: localStorage.getItem("user_token") }) .then(rsp => { accountsList.appendItem(a) ApplicationView.displayMessage("Account " + a.getId() + "@" + a.getDomain() + " has now role " + role.getId() + "@" + role.getDomain(), 3000) }).catch(err => { accountsList.removeItem(a) ApplicationView.displayMessage(err, 3000) }) }) content.appendChild(accountsList) }, err => { ApplicationView.displayMessage(err, 3000) }) // give the focus to the input. this.hideBtn.onclick = () => { let button = this.shadowRoot.querySelector("#hide-btn") if (button && content) { if (!content.opened) { button.icon = "unfold-more" } else { button.icon = "unfold-less" } content.toggle(); } } } onDeleteRole(role) { let toast = ApplicationView.displayMessage( ` <style> #yes-no-contact-delete-box{ display: flex; flex-direction: column; } #yes-no-contact-delete-box globular-contact-card{ padding-bottom: 10px; } #yes-no-contact-delete-box div{ display: flex; padding-bottom: 10px; } paper-button{ font-size: .85rem; height: 32px; } </style> <div id="yes-no-contact-delete-box"> <div>Your about to delete the role ${role.getName() + "@" + role.getDomain()}</div> <div>Is it what you want to do? </div> <div style="justify-content: flex-end;"> <paper-button id="yes-delete-contact">Yes</paper-button> <paper-button id="no-delete-contact">No</paper-button> </div> </div> `, 15000 // 15 sec... ); let yesBtn = document.querySelector("#yes-delete-contact") let noBtn = document.querySelector("#no-delete-contact") // On yes yesBtn.onclick = () => { let rqst = new DeleteRoleRqst rqst.setRoleid(role.getId() + "@" + role.getDomain()) Model.globular.resourceService.deleteRole(rqst, { domain: Model.domain, address: Model.address, application: Model.application, token: localStorage.getItem("user_token") }).then((rsp) => { ApplicationView.displayMessage( "<iron-icon icon='communication:message' style='margin-right: 10px;'></iron-icon><div>Role named " + role.getName() + " was deleted!</div>", 3000 ); Model.eventHub.publish("refresh_role_evt", {}, true) toast.dismiss(); }).catch(e => { ApplicationView.displayMessage(e, 3000) toast.dismiss(); }) } noBtn.onclick = () => { toast.dismiss(); } } } customElements.define('globular-role-panel', RolePanel)