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)
469 lines (386 loc) • 15.9 kB
JavaScript
// I will made use of polymer instead of materialyze for the main
// layout because materialyse dosen't react to well with the shadow doom.
import '@polymer/iron-icons/iron-icons.js';
import '@polymer/paper-icon-button/paper-icon-button.js';
import '@polymer/paper-input/paper-input.js';
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-checkbox/paper-checkbox.js';
import { Model } from '../Model';
import { ApplicationView } from '../ApplicationView';
import { Account } from '../Account';
import { Notification, NotificationType } from '../Notification';
import { Application } from '../Application';
/**
* Login/Register functionality.
*/
export class Login extends HTMLElement {
// attributes.
// Create the applicaiton view.
constructor() {
super()
// Set the shadow dom.
this.attachShadow({ mode: 'open' });
this.loginBox = new LoginBox()
this.registerBox = new RegisterBox()
}
getWorkspace() {
return document.getElementById("workspace")
}
// The connection callback.
connectedCallback() {
// Innitialisation of the layout.
this.shadowRoot.innerHTML = `
<style>
#login_div span:hover{
cursor:pointer;
}
#login_div {
display: flex;
}
#login_div:hover{
cursor: pointer;
}
paper-button {
font-size: 1rem;
}
</style>
<span id="login_div">
<paper-button id="register_btn">register</paper-button>
<paper-button id="login_btn">login</paper-button>
</span>
`
// The login panel.
this.shadowRoot.getElementById("login_btn").onclick = () => {
if (this.registerBox.parentNode != undefined) {
this.registerBox.parentNode.removeChild(this.registerBox)
}
// Append the login box in the workspace.
this.getWorkspace().appendChild(this.loginBox)
}
this.shadowRoot.getElementById("register_btn").onclick = () => {
if (this.loginBox.parentNode != undefined) {
this.loginBox.parentNode.removeChild(this.loginBox)
}
// Append the login box in the workspace.
this.getWorkspace().appendChild(this.registerBox)
}
this.loginDiv = this.shadowRoot.getElementById("login_div")
this.registerBtn = this.shadowRoot.getElementById("register_btn")
this.loginBtn = this.shadowRoot.getElementById("login_btn")
}
init() {
// Here I will connect the event listener's
}
}
customElements.define('globular-login', Login)
/**
* Login box
*/
export class LoginBox extends HTMLElement {
// attributes.
// Create the applicaiton view.
constructor() {
super()
// Set the shadow dom.
this.attachShadow({ mode: 'open' });
}
// The connection callback.
connectedCallback() {
// Innitialisation of the layout.
this.shadowRoot.innerHTML = `
<style>
paper-card{
background-color: var(--palette-background-paper);
color: var(--palette-text-primary);
font-size: 1rem;
}
paper-input iron-icon{
margin-right: 10px;
}
paper-card,
globular-login-box {
margin-left: auto;
margin-right: auto;
margin-bottom: 20px;
}
#login_box{
z-index: 1000;
min-width: 340px;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: var(--palette-background-paper);
color: var(--palette-text-primary);
}
#login_box .card-actions {
display: flex;
justify-content: flex-end;
}
#login_box paper-checkbox {
margin: 20px 0px 10px 2px;
}
.card-title {
font-size: 1.25rem;
text-transform: uppercase;
font-weight: 400;
letter-spacing: .25px;
outline: none;
position: fixed;
top: -50px;
}
.card-actions {
font-size: 1rem;
}
.card-content {
display: flex;
flex-direction: column;
}
paper-button {
font-size: 1rem;
}
.card-subtitle {
letter-spacing: .01428571em;
font-family: Roboto, Arial, sans-serif;
font-size: 1.125rem;
font-weight: 400;
line-height: 1.25rem;
hyphens: auto;
word-break: break-word;
word-wrap: break-word;
}
#reset-password-lnk{
font-size: 1rem;
align-self: flex-end;
}
#reset-password-lnk:hover{
text-decoration: underline;
cursor: pointer;
}
</style>
<paper-card id="login_box">
<h2 class="card-title">LOGIN</h2>
<div class="card-content">
<paper-input id="user_input" label="user/email">
<iron-icon icon="account-circle" slot="prefix"></iron-icon>
</paper-input>
<paper-input id="pwd_input" type="password" label="password">
<iron-icon icon="lock" slot="prefix"></iron-icon>
</paper-input>
<paper-checkbox id="remember_me">Remember me</paper-checkbox>
<span id="reset-password-lnk">Forgot password?</span>
</div>
<div class="card-actions">
<paper-button id="login_btn">login</paper-button>
<paper-button id="cancel_btn">cancel</paper-button>
</div>
</paper-card>
`
// give the focus to the input.
let userInput = this.shadowRoot.getElementById("user_input")
setTimeout(() => {
userInput.focus()
}, 100)
let passwordInput = this.shadowRoot.getElementById("pwd_input")
let cancelBtn = this.shadowRoot.getElementById("cancel_btn")
let loginBtn = this.shadowRoot.getElementById("login_btn")
let remeberMeBtn = this.shadowRoot.getElementById("remember_me")
// remove the login box from the layout
cancelBtn.onclick = () => {
this.parentNode.removeChild(this)
userInput.value = ""
passwordInput.value = ""
}
loginBtn.onclick = (evt) => {
evt.stopPropagation()
// Get the user id and pwd.
let userId = userInput.value
let pwd = passwordInput.value
this.parentNode.removeChild(this)
// so here I will throw a event.
Model.eventHub.publish("login_event_", { userId: userId, pwd: pwd }, true)
}
passwordInput.onkeyup = (evt) => {
if (evt.key == "Enter") {
loginBtn.click();
}
}
this.shadowRoot.querySelector("#reset-password-lnk").onclick = () => {
if (userInput.value.length == 0) {
userInput.focus()
ApplicationView.displayMessage("Please enter your user id or email and click again", 3500)
return
}
Account.getAccount(userInput.value, account => {
Account.getAccount("sa", sa => {
let notification = new Notification(
Model.getGlobule(sa.domain).config.Mac,
account.id + "@" + account.domain,
NotificationType.User,
sa.id + "@" + sa.domain,
`
<div style="display: flex; flex-direction: column;">
<p>
User ${account.name} (id: ${account.id + "@" + account.domain}) forgot it password.
<br>Can you change it password and send it new password at <a href="mailto:${account.email}">${account.email}</a>
</p>
</div>`
);
// Send the notification.
Application.sendNotifications(
notification,
() => {
ApplicationView.displayMessage(`<p>Notification was sent to the system administrator.</br>An email answer will be sent to you soon at address ${account.email}.</br>You can also contact the administrator directly at <a href="mailto:${sa.email}">${sa.email}</a></p>`, 15000)
},
err => {
ApplicationView.displayMessage(err, 3000);
}
);
}, err => { })
}, err => {
ApplicationView.displayMessage(err, 3000)
userInput.value = ""
userInput.focus()
})
}
// And you remember me, with a lot of rum!
if (localStorage.getItem("remember_me") != undefined) {
if (localStorage.getItem("remember_me") != undefined) {
remeberMeBtn.checked = localStorage.getItem("remember_me") == "true";
} else {
remeberMeBtn.checked = false
}
}
remeberMeBtn.onchange = () => {
localStorage.setItem("remember_me", remeberMeBtn.checked)
if (remeberMeBtn.checked == false) {
localStorage.removeItem("remember_me")
}
}
}
}
customElements.define('globular-login-box', LoginBox)
/**
* Register box
*/
export class RegisterBox extends HTMLElement {
// attributes.
// Create the applicaiton view.
constructor() {
super()
// Set the shadow dom.
this.attachShadow({ mode: 'open' });
}
// The connection callback.
connectedCallback() {
// Innitialisation of the layout.
this.shadowRoot.innerHTML = `
<style>
paper-card{
background-color: var(--palette-background-paper);
color: var(--palette-text-primary);
}
paper-input iron-icon{
margin-right: 10px;
}
paper-card,
globular-register-box {
margin-left: auto;
margin-right: auto;
margin-bottom: 20px;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: var(--palette-background-paper);
color: var(--palette-text-primary);
}
#register_box{
z-index: 1000;
min-width: 340px;
}
#register_box .card-actions {
display: flex;
justify-content: flex-end;
}
.card-title {
font-size: 1.25rem;
text-transform: uppercase;
font-weight: 400;
letter-spacing: .25px;
outline: none;
position: fixed;
top: -50px;
}
.card-actions {
font-size: 1rem;
}
paper-button {
font-size: 1rem;
}
.card-subtitle {
letter-spacing: .01428571em;
font-family: Roboto, Arial, sans-serif;
font-size: 1.125rem;
font-weight: 400;
line-height: 1.25rem;
hyphens: auto;
word-break: break-word;
word-wrap: break-word;
}
</style>
<paper-card id="register_box">
<h2 class="card-title">REGISTER</h2>
<div class="card-content">
<paper-input id="user_input" label="user">
<iron-icon icon="account-circle" slot="prefix"></iron-icon>
</paper-input>
<paper-input id="email_input" label="email">
<iron-icon icon="mail" slot="prefix"></iron-icon>
</paper-input>
<paper-input id="pwd_input" type="password" label="password">
<iron-icon icon="lock" slot="prefix"></iron-icon>
</paper-input>
<paper-input id="retype_pwd_input" type="password" label="retype password">
<iron-icon icon="lock" slot="prefix"></iron-icon>
</paper-input>
</div>
<div class="card-actions">
<paper-button id="register_btn">register</paper-button>
<paper-button id="cancel_btn">cancel</paper-button>
</div>
</paper-card>
`
let cancelBtn = this.shadowRoot.getElementById("cancel_btn")
let registerBtn = this.shadowRoot.getElementById("register_btn")
let userInput = this.shadowRoot.getElementById("user_input")
setTimeout(() => {
userInput.focus()
userInput.setSelectionRange(0, userInput.value.length)
}, 100)
let emailInput = this.shadowRoot.getElementById("email_input")
let passwordInput = this.shadowRoot.getElementById("pwd_input")
let retypePasswordInput = this.shadowRoot.getElementById("retype_pwd_input")
// remove the login box from the layout
cancelBtn.onclick = () => {
this.parentNode.removeChild(this)
userInput.value = ""
passwordInput.value = ""
retypePasswordInput.value = ""
emailInput.value = ""
}
// Register an new user.
registerBtn.onclick = () => {
let userId = userInput.value
let pwd = passwordInput.value
let repwd = retypePasswordInput.value
let email = emailInput.value
let domain = Model.domain
this.parentNode.removeChild(this)
// so here I will throw a event.
Model.eventHub.publish("register_event_", { userId: userId, email: email, pwd: pwd, repwd: repwd, domain: domain }, true)
}
}
}
customElements.define('globular-register-box', RegisterBox)