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)
673 lines (570 loc) • 29 kB
JavaScript
import '@polymer/iron-icons/iron-icons.js';
import { Model } from '../Model';
import { AddOrganizationAccountRqst, AddOrganizationApplicationRqst, AddOrganizationGroupRqst, AddOrganizationRoleRqst, Application, CreateOrganizationRqst, DeleteOrganizationRqst, GetOrganizationsRqst, GetPeersRqst, Organization, RemoveOrganizationAccountRqst, RemoveOrganizationApplicationRqst, RemoveOrganizationGroupRqst, RemoveOrganizationRoleRqst } from 'globular-web-client/resource/resource_pb';
import { ApplicationView } from '../ApplicationView';
import { SearchableAccountList, SearchableApplicationList, SearchableGroupList, SearchableRoleList } from './List.js'
import { Account } from '../Account';
import * as ApplicationTs from '../Application';
import { getAllGroups, getAllRoles } from 'globular-web-client/api';
export function getAllOrganizations(callback, errorCallback, globule) {
if(globule == null){
globule = Model.globular
}
let rqst = new GetOrganizationsRqst
rqst.setQuery("{}")
let organizations = [];
let stream = globule.resourceService.getOrganizations(rqst, { domain: Model.domain,address: Model.address, application: Model.application, token: localStorage.getItem("user_token") });
// Get the stream and set event on it...
stream.on("data", (rsp) => {
organizations = organizations.concat(rsp.getOrganizationsList());
});
stream.on("status", (status) => {
if (status.code == 0) {
callback(organizations);
} else {
errorCallback({ message: status.details });
}
});
}
export function getOrganizationById(id, callback, errorCallback){
let o_ = null
getAllOrganizations(organizations=>{
organizations.forEach(o=>{
if(o.getId() == id){
o_ = o
}
if(o_ == undefined){
if(o.getId() + "@" + o.getDomain() == id){
o_ = o
}
}
})
if(o_ != null){
callback(o_)
return
}
errorCallback("no organization found with id " + id)
}, errorCallback)
}
export class OrganizationManager 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-organization-btn{
top: -42px;
right: 0px;
position: absolute;
}
#container{
display: flex;
flex-direction: column;
position: relative;
}
.card-content {
min-width: 680px;
padding: 0px;
}
(max-width: 800px) {
.card-content{
min-width: 580px;
}
}
(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-organization-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 displayOrganizations = () => {
content.innerHTML = ""
// Here I will get the list of all Organizations.
getAllOrganizations(
(Organizations) => {
Organizations.forEach(o => {
if (o.getId() != "admin" && o.getId() != "guest") {
let panel = new OrganizationPanel(o)
content.appendChild(panel)
}
})
}, err => { ApplicationView.displayMessage(err, 3000) })
}
// call once
displayOrganizations()
Model.eventHub.subscribe("refresh_organization_evt", uuid => { }, evt => {
displayOrganizations()
}, true)
let createOrganizationBtn = this.shadowRoot.querySelector("#create-organization-btn")
createOrganizationBtn.onclick = () => {
let html = `
<style>
paper-card{
background-color: var(--palette-background-paper);
color: var(--palette-text-primary);
}
#create-organization-panel{
position: absolute;
right: 0px;
top: 0px;
z-index: 1;
background-color: var(--palette-background-paper);
}
#create-organization-panel .card-content{
min-width: 200px;
padding: 0px 10px 0px 10px;
display: flex;
flex-direction: column;
}
</style>
<paper-card id="create-organization-panel">
<div style="display: flex; align-items: center;">
<div style="flex-grow: 1; padding: 5px;">
Create Organization
</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-organization-panel")
let input = null
if (panel == undefined) {
container.appendChild(document.createRange().createContextualFragment(html))
panel = container.querySelector("#create-organization-panel")
let closeBtn = panel.querySelector("#cancel-btn")
closeBtn.onclick = () => {
panel.parentNode.removeChild(panel)
}
input = panel.querySelector("paper-input")
let createOrganizationButton = panel.querySelector("paper-button")
// Create a new Organization.
createOrganizationButton.onclick = () => {
let OrganizationId = input.value;
if (OrganizationId.length == 0) {
ApplicationView.displayMessage("No Organization name was given!", 3000)
setTimeout(() => {
input.focus()
}, 100)
return
}
let rqst = new CreateOrganizationRqst()
let organization = new Organization()
organization.setId(OrganizationId)
organization.setName(OrganizationId)
organization.setDomain(Model.domain)
rqst.setOrganization(organization)
Model.globular.resourceService.createOrganization(rqst, { domain: Model.domain,address: Model.address, application: Model.application, token: localStorage.getItem("user_token") })
.then(rsp => {
ApplicationView.displayMessage("Organization " + OrganizationId + " was created!", 3000)
panel.parentNode.removeChild(panel)
displayOrganizations()
}).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-organization-manager', OrganizationManager)
export class OrganizationPanel extends HTMLElement {
// attributes.
// Create the applicaiton view.
constructor(o) {
super()
// Set the shadow dom.
this.attachShadow({ mode: 'open' });
// Keep Organization informations.
this.organization = o;
// 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;
}
#collapse-panel{
display: flex;
flex-direction: column;
width: 100%;
}
img, iron-icon{
margin: 8px;
}
paper-tabs {
/* custom CSS property */
--paper-tabs-selection-bar-color: var(--palette-primary-main);
color: var(--palette-text-primary);
--paper-tab-ink: var(--palette-action-disabled);
}
</style>
<div id="container">
<div class="header">
<paper-icon-button id="delete-organization-btn" icon="delete"></paper-icon-button>
<span class="title">${this.organization.getName() + "@" + this.organization.getDomain()}</span>
<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" >
<paper-tabs selected="0">
<paper-tab id="organization-accounts-tab">Accounts</paper-tab>
<paper-tab id="organization-applications-tab">Applications</paper-tab>
<paper-tab id="organization-roles-tab">Roles</paper-tab>
<paper-tab id="organization-groups-tab">Groups</paper-tab>
</paper-tabs>
<div id="content">
</div>
</iron-collapse>
</div>
`
let togglePanel = this.shadowRoot.querySelector("#collapse-panel")
let content = this.shadowRoot.querySelector("#content")
this.hideBtn = this.shadowRoot.querySelector("#hide-btn")
this.accountsList = null
this.rolesList = null
this.applicationsList = null
this.groupsList = null
this.shadowRoot.querySelector("#organization-applications-tab").onclick = () => {
if (this.accountsList != undefined)
this.accountsList.style.display = "none"
if (this.rolesList != undefined)
this.rolesList.style.display = "none"
if (this.applicationsList != undefined)
this.applicationsList.style.display = ""
if (this.groupsList != undefined)
this.groupsList.style.display = "none"
}
this.shadowRoot.querySelector("#organization-accounts-tab").onclick = () => {
if (this.accountsList != undefined)
this.accountsList.style.display = ""
if (this.rolesList != undefined)
this.rolesList.style.display = "none"
if (this.applicationsList != undefined)
this.applicationsList.style.display = "none"
if (this.groupsList != undefined)
this.groupsList.style.display = "none"
}
this.shadowRoot.querySelector("#organization-groups-tab").onclick = () => {
if (this.accountsList != undefined)
this.accountsList.style.display = "none"
if (this.rolesList != undefined)
this.rolesList.style.display = "none"
if (this.applicationsList != undefined)
this.applicationsList.style.display = "none"
if (this.groupsList != undefined)
this.groupsList.style.display = ""
}
this.shadowRoot.querySelector("#organization-roles-tab").onclick = () => {
if (this.accountsList != undefined)
this.accountsList.style.display = "none"
if (this.rolesList != undefined)
this.rolesList.style.display = ""
if (this.applicationsList != undefined)
this.applicationsList.style.display = "none"
if (this.groupsList != undefined)
this.groupsList.style.display = "none"
}
let deleteBtn = this.shadowRoot.querySelector("#delete-organization-btn")
deleteBtn.onclick = () => {
this.onDeleteOrganization(o)
}
// Account list.
Account.getAccounts("{}",
accounts => {
// I will get the account object whit the given id.
let list = []
this.organization.getAccountsList().forEach(accountId => {
let a_ = accounts.find(a => a.getId() + "@" + a.getDomain() === accountId);
if (a_ != undefined) {
list.push(a_)
}
})
this.accountsList = new SearchableAccountList("Accounts", list, a => {
this.accountsList.removeItem(a)
let rqst = new RemoveOrganizationAccountRqst
rqst.setOrganizationid(o.getId() + "@" + o.getDomain())
rqst.setAccountid(a.getId() + "@" + a.getDomain())
Model.globular.resourceService.removeOrganizationAccount(rqst, { domain: Model.domain, address: Model.address, application: Model.application, token: localStorage.getItem("user_token") })
.then(rsp => {
this.accountsList.removeItem(a)
ApplicationView.displayMessage("Account " + a.getId() + "@" + a.getDomain() + " was removed from Organization " + o.getName() + "@" + o.getDomain(), 3000)
}).catch(err => {
this.accountsList.appendItem(a) // set it back
ApplicationView.displayMessage(err, 3000)
})
},
a => {
let rqst = new AddOrganizationAccountRqst
rqst.setOrganizationid(o.getId() + "@" + o.getDomain())
rqst.setAccountid(a.getId() + "@" + a.getDomain())
Model.globular.resourceService.addOrganizationAccount(rqst, { domain: Model.domain, address: Model.address, application: Model.application, token: localStorage.getItem("user_token") })
.then(rsp => {
this.accountsList.appendItem(a)
ApplicationView.displayMessage("Account " + a.getId() + "@" + a.getDomain() + " has now Organization " + o.getName() + "@" + o.getDomain(), 3000)
}).catch(err => {
this.accountsList.removeItem(a)
ApplicationView.displayMessage(err, 3000)
})
})
content.appendChild(this.accountsList)
}, err => {
ApplicationView.displayMessage(err, 3000)
})
// The applications list.
ApplicationTs.Application.getAllApplicationInfo(
applications => {
// I will get the account object whit the given id.
let list = []
this.organization.getApplicationsList().forEach(applicationId => {
let a_ = applications.find(a => a.getId() + "@" + a.getDomain() === applicationId);
if (a_ != undefined) {
list.push(a_)
}
})
this.applicationsList = new SearchableApplicationList("Applications", list, a => {
this.applicationsList.removeItem(a)
let rqst = new RemoveOrganizationApplicationRqst
rqst.setOrganizationid(o.getId() + "@" + o.getDomain())
rqst.setApplicationid(a.getId() + "@" + a.getDomain())
Model.globular.resourceService.removeOrganizationApplication(rqst, { domain: Model.domain, address: Model.address, application: Model.application, token: localStorage.getItem("user_token") })
.then(rsp => {
this.applicationsList.removeItem(a)
ApplicationView.displayMessage("Application " + a.getAlias() + "@" + a.getDomain() + " was removed from Organization " + o.getName() + "@" + o.getDomain(), 3000)
}).catch(err => {
this.applicationsList.appendItem(a) // set it back
ApplicationView.displayMessage(err, 3000)
})
},
a => {
let rqst = new AddOrganizationApplicationRqst
rqst.setOrganizationid(o.getId() + "@" + o.getDomain())
rqst.setApplicationid(a.getId() + "@" + a.getDomain())
Model.globular.resourceService.addOrganizationApplication(rqst, { domain: Model.domain, address: Model.address, application: Model.application, token: localStorage.getItem("user_token") })
.then(rsp => {
this.applicationsList.appendItem(a)
ApplicationView.displayMessage("Application " + a.getAlias() + "@" + a.getDomain() + " has now Organization " + o.getName() + "@" + o.getDomain(), 3000)
}).catch(err => {
this.applicationsList.removeItem(a)
ApplicationView.displayMessage(err, 3000)
})
})
content.appendChild(this.applicationsList)
}, err => {
ApplicationView.displayMessage(err, 3000)
})
// The role list.
getAllRoles(Model.globular,
roles => {
// I will get the account object whit the given id.
let list = []
this.organization.getRolesList().forEach(roleId => {
let r_ = roles.find(r => r.getId() + "@" + r.getDomain() === roleId);
if (r_ != undefined) {
list.push(r_)
}
})
this.rolesList = new SearchableRoleList("Roles", list,
r => {
this.rolesList.removeItem(r)
let rqst = new RemoveOrganizationRoleRqst
rqst.setOrganizationid(o.getId() + "@" + o.getDomain())
rqst.setRoleid(r.getId() + "@" + r.getDomain())
Model.globular.resourceService.removeOrganizationRole(rqst, { domain: Model.domain, address: Model.address, application: Model.application, token: localStorage.getItem("user_token") })
.then(rsp => {
this.rolesList.removeItem(r)
ApplicationView.displayMessage("Role " + r.getName() + "@" + r.getDomain() + " was removed from Organization " + o.getName() + "@" + o.getDomain(), 3000)
}).catch(err => {
this.rolesList.appendItem(r) // set it back
ApplicationView.displayMessage(err, 3000)
})
},
r => {
let rqst = new AddOrganizationRoleRqst
rqst.setOrganizationid(o.getId() + "@" + o.getDomain())
rqst.setRoleid(r.getId() + "@" + r.getDomain())
Model.globular.resourceService.addOrganizationRole(rqst, { domain: Model.domain, address: Model.address, application: Model.application, token: localStorage.getItem("user_token") })
.then(rsp => {
this.rolesList.appendItem(r)
ApplicationView.displayMessage("Role " + r.getName() + "@" + r.getDomain() + " has now Organization " + o.getName() + "@" + o.getDomain(), 3000)
}).catch(err => {
this.rolesList.removeItem(r)
ApplicationView.displayMessage(err, 3000)
})
})
content.appendChild(this.rolesList)
}, err => {
ApplicationView.displayMessage(err, 3000)
})
// The applications list.
getAllGroups(Model.globular,
groups => {
// I will get the account object whit the given id.
let list = []
this.organization.getGroupsList().forEach(groupId => {
let g_ = groups.find(g => g.getId() + "@" + g.getDomain() === groupId);
if (g_ != undefined) {
list.push(g_)
}
})
this.groupsList = new SearchableGroupList("Groups", list,
g => {
this.groupsList.removeItem(g)
let rqst = new RemoveOrganizationGroupRqst
rqst.setOrganizationid(o.getId() + "@" + o.getDomain())
rqst.setGroupid(g.getId() + "@" + g.getDomain())
Model.globular.resourceService.removeOrganizationGroup(rqst, { domain: Model.domain, address: Model.address, application: Model.application, token: localStorage.getItem("user_token") })
.then(rsp => {
this.groupsList.removeItem(g)
ApplicationView.displayMessage("Group " + g.getName() + "@" + g.getDomain() + " was removed from Organization " + o.getName() + "@" + o.getDomain(), 3000)
}).catch(err => {
this.groupsList.appendItem(g) // set it back
ApplicationView.displayMessage(err, 3000)
})
},
g => {
let rqst = new AddOrganizationGroupRqst
rqst.setOrganizationid(o.getId() + "@" + o.getDomain())
rqst.setGroupid(g.getId() + "@" + g.getDomain())
Model.globular.resourceService.addOrganizationGroup(rqst, { domain: Model.domain, address: Model.address, application: Model.application, token: localStorage.getItem("user_token") })
.then(rsp => {
this.groupsList.appendItem(g)
ApplicationView.displayMessage("Group " + g.getName() + "@" + g.getDomain() + " has now Organization " + o.getName() + "@" + o.getDomain(), 3000)
}).catch(err => {
this.groupsList.removeItem(g)
ApplicationView.displayMessage(err, 3000)
})
})
content.appendChild(this.groupsList)
}, err => {
ApplicationView.displayMessage(err, 3000)
})
// give the focus to the input.
this.hideBtn.onclick = () => {
let button = this.shadowRoot.querySelector("#hide-btn")
if (button && togglePanel) {
if (!togglePanel.opened) {
button.icon = "unfold-more"
} else {
button.icon = "unfold-less"
}
togglePanel.toggle();
}
}
}
onDeleteOrganization(o) {
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;
}
</style>
<div id="yes-no-contact-delete-box">
<div>Your about to delete the Organization ${o.getName() + "@" + o.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 DeleteOrganizationRqst
rqst.setOrganization(o.getId() + "@" + o.getDomain())
Model.globular.resourceService.deleteOrganization(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>Organization named " +
o.getName() +
" was deleted!</div>",
3000
);
Model.eventHub.publish("refresh_organization_evt", {}, true)
toast.dismiss();
}).catch(e => {
ApplicationView.displayMessage(e, 3000)
toast.dismiss();
})
}
noBtn.onclick = () => {
toast.dismiss();
}
}
connectedCallback(){
this.shadowRoot.querySelector("#organization-accounts-tab").click()
}
}
customElements.define('globular-organization-panel', OrganizationPanel)