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)

279 lines (229 loc) 9.48 kB
import { Account } from "../Account" import { Model } from "../Model" import "@polymer/iron-icons/device-icons"; import "@polymer/iron-icon/iron-icon.js"; import '@polymer/paper-toggle-button/paper-toggle-button.js'; import { ApplicationView } from "../ApplicationView"; import { v4 as uuidv4 } from "uuid"; // This variables are for the active user. let accountId = "" let away = false; // does not want to be see let timeout = null; // use it to make the event less anoying... let sessionTime = null; // When the applicaiton lost focus away state will be set to the logged user. document.addEventListener('visibilitychange', function () { if (accountId.length > 0 && !away) { if (document.visibilityState == 'hidden') { timeout = setTimeout(() => { Account.getAccount(accountId, a => { Model.eventHub.publish(`__session_state_${a.id + "@" + a.domain}_change_event__`, { _id: a.id + "@" + a.domain, state: 2, lastStateTime: new Date() }, true) }, err => console.log(err)) }, 30 * 1000) } else { Account.getAccount(accountId, a => { Model.eventHub.publish(`__session_state_${a.id + "@" + a.domain}_change_event__`, { _id: a.id + "@" + a.domain, state: 0, lastStateTime: sessionTime }, true) if (timeout != undefined) { clearTimeout(timeout) } }, err => console.log(err)) } } }); window.addEventListener('beforeunload', function (e) { // the absence of a returnValue property on the event will guarantee the browser unload happens Account.getAccount(accountId, a => { Model.eventHub.publish(`__session_state_${a.id + "@" + a.domain}_change_event__`, { _id: a.id + "@" + a.domain, state: 1, lastStateTime: new Date() }, true) }, err => console.log(err)) delete e['returnValue']; }); /** * Display the session state of a particular accout... */ export class SessionState extends HTMLElement { // Create the applicaiton view. constructor(account) { super() // Set the shadow dom. this.attachShadow({ mode: 'open' }); this.account = account; this.interval = null; let sessionStateId = "_" + uuidv4(); let sessionTimerId = "_" + uuidv4(); this.sessionChangeListener = "" // Innitialisation of the layout. this.shadowRoot.innerHTML = ` <style> .session-state-panel{ display: flex; flex-direction: row; background-color: var(--palette-background-paper); color: var(--palette-text-primary); --iron-icon-fill-color: var(--palette-text-primary); align-items: center; font-size: .85rem; } .session-state-panel span{ padding-left: 10px; color: var(--palette-text-accent); } #session-state-timer{ flex-grow: 1; } .session-state-panel paper-toggle-button{ padding-left: 16px; font-size: .85rem; } paper-toggle-button { --paper-toggle-button-label-color: var(--palette-text-accent); } paper-card h1 { font-size: 1.65rem; } </style> <div class="session-state-panel"> <iron-icon icon="device:access-time" style="padding-left: 8px;"></iron-icon> <div style="flex-grow: 1;"> <span id="${sessionStateId}"></span> <span id="${sessionTimerId}"></span> </div> <paper-toggle-button title="Appear away to other's" noink></paper-toggle-button> </div> ` this.ico = this.shadowRoot.querySelector("iron-icon") this.away = this.shadowRoot.querySelector("paper-toggle-button") this.stateName = this.shadowRoot.querySelector("#" + sessionStateId) this.lastStateTime = this.shadowRoot.querySelector("#" + sessionTimerId) this.id = "_" + uuidv4(); // Set the away button... if (this.hasAttribute("editable")) { this.away.onchange = () => { let session = {} session._id = this.account.session._id; if (this.away.checked) { // Here I will set the user session... session.state = 2; session.lastStateTime = new Date(); this.stateName.innerHTML = "Away" away = true; } else { session.state = 0; session.lastStateTime = sessionTime; // set back the session time. away = false; this.stateName.innerHTML = "Online" } // local event. Model.eventHub.publish(`__session_state_${this.account.id + "@" + this.account.domain}_change_event__`, session, true) } } else { this.away.parentNode.removeChild(this.away); } // The account can be the actual object or a string... if (this.hasAttribute("account")) { let accountId = this.getAttribute("account") Account.getAccount(accountId, (val) => { this.account = val; this.init(); }, (err) => { ApplicationView.displayMessage(err, 3000) }) } } /** * Initialyse the session panel values. */ init() { // if no account was define simply return without init session... if (!this.account) { setTimeout(() => { if (this.hasAttribute("account")) { let accountId = this.getAttribute("account") Account.getAccount(accountId, (val) => { this.account = val; this.init(); }, (err) => { ApplicationView.displayMessage(err, 3000) }) } }, 1000) return } if (!this.account.session) { setTimeout(() => { if (this.hasAttribute("account")) { let accountId = this.getAttribute("account") Account.getAccount(accountId, (val) => { this.account = val; this.init(); }, (err) => { ApplicationView.displayMessage(err, 3000) }) } }, 1000) return } // unsubscribe first. let globule = Model.getGlobule(this.account.domain) if (this.hasAttribute("editable")) { sessionTime = this.account.session.lastStateTime; } globule.eventHub.subscribe(`session_state_${this.account.id + "@" + this.account.domain}_change_event`, (uuid) => { this.sessionChangeListener = uuid; }, (evt) => { // Set the value here... let obj = JSON.parse(evt) this.account.session.lastStateTime_ = new Date(obj.lastStateTime * 1000) this.account.session.state_ = obj.state }, false, this) // Start display time at each second... this.interval = setInterval(() => { this.displayDelay() }, 500) } displayDelay() { if (this.account.session == undefined) { this.style.display = "none" return } this.style.display = "" let lastStateTime = this.account.session.lastStateTime_ let state = this.account.session.state_ if (state == 0) { this.stateName.innerHTML = "Online" } else if (state == 1) { this.stateName.innerHTML = "Offline" } else { this.stateName.innerHTML = "Away" } let delay = Math.floor((Date.now() - lastStateTime.getTime()) / 1000); if (delay < 60) { this.lastStateTime.innerHTML = delay + " seconds ago" } else if (delay < 60 * 60) { this.lastStateTime.innerHTML = Math.floor(delay / (60)) + " minutes ago" } else if (delay < 60 * 60 * 24) { this.lastStateTime.innerHTML = Math.floor(delay / (60 * 60)) + " hours ago" } else { this.lastStateTime.innerHTML = Math.floor(delay / (60 * 60 * 24)) + " days ago" } } // The connection callback. connectedCallback() { // When the element is put in the dom. this.init(); } // Disconnect the element from the view. disconnectedCallback() { // it can affect it values. if (this.interval != undefined) { clearInterval(this.interval); } if (this.sessionChangeListener.length > 0) { if (this.account.session) { if (Model.getGlobule(this.account.domain)) Model.getGlobule(this.account.domain).eventHub.unSubscribe(`session_state_${this.account.id + "@" + this.account.domain}_change_event`, this.sessionChangeListener) } } } } customElements.define('globular-session-state', SessionState)