const Module = require('./module'); const Tpl = require('./gui.xml').default; const kebabToCamel = require('vn/string-util').kebabToCamel; const routes = require('../../import').routes; require('./gui.scss'); module.exports = new Class({ Extends: Vn.Component, Properties: { conn: { type: Db.Connection ,set(x) { this.link({_conn: x}, {'loading-changed': this._onConnLoadChange }); } ,get() { return this._conn; } } } ,forms: {} ,activeForm: null ,activeCss: null ,requestedForm: null ,menuShown: false ,menuOptions: {} ,choosedOption: null ,_shown: false ,_scrollTimeout: null ,_navbarVisible: true ,initialize(props) { this.loadTemplateFromString(Tpl); this.loadingCount = 0; this.$.background.onclick = function() {}; this.$.leftPanel.addEventListener('click', function(event) { event.stopPropagation(); }); Vn.Component.prototype.initialize.call(this, props); } ,async show() { if (this._shown) return; this._shown = true; this.doc.body.appendChild(this.node); Htk.Toast.pushTop(this.$.formHolder); const resultSet = await this._conn.execQuery( 'SELECT id, name, nickname FROM account.myUser;' +'SELECT defaultForm FROM config;' +'SELECT url FROM imageConfig;' +'SELECT dbproduccion FROM vn.config;' +'SELECT productionDomain, testDomain FROM config;' ); // Retrieving the user name this.user = resultSet.fetchObject(); Vn.Node.setText(this.$.userName, this.user.nickname); // Retrieving configuration parameters Vn.Config.defaultForm = resultSet.fetchValue(); Vn.Config.imageUrl = resultSet.fetchValue(); // Retrieving configuration parameters const isTesting = !resultSet.fetchValue(); if (isTesting) { this.$.devInfo.style.display = 'block'; this.$.version.textContent = Vn.Cookie.get('vnVersion'); } // Retrieving configuration parameters const res = resultSet.fetchObject(); if (res && res.testDomain) { let linkText, linkField; if (location.host != res.productionDomain) { linkText = 'Old website'; linkField = 'productionDomain'; } else { linkText = 'Test the new website'; linkField = 'testDomain'; } Vn.Node.setText(this.$.testLink, _(linkText)); this.$.testLink.href = '//'+ res.get(linkField); this.$.testLink.style.display = 'block'; } else this.$.testLink.style.display = 'none'; await this.loadMenu(); if (Vn.isMobile()) { this._onScrollHandler = this._onScroll.bind(this); window.addEventListener('scroll', this._onScrollHandler ); } await this.supplantInit(); this.formParam = new Vn.Param({ lot: this.hash, name: 'form', }); this.formParam.on('changed', this._onFormChange, this); await this._onFormChange(); if (!localStorage.getItem('hederaCookies')) { localStorage.setItem('hederaCookies', true); Htk.Toast.showWarning(_('By using this site you accept cookies')); } } ,async hide() { if (!this._shown) return; this._shown = false; if (Vn.isMobile()) window.removeEventListener('scroll', this._onScrollHandler); Htk.Toast.popTop(); if (this.formParam) { this.formParam.unref(); this.formParam = null; } await this.closeForm(); this.hideMenu(); Vn.Node.remove(this.node); } ,async logout() { await this.onLogoutClick(); } ,async onLogoutClick() { try { if (!localStorage.getItem('hederaGuest')) this._conn.close(); } finally { this.emit('logout'); } } ,_onConnLoadChange(conn, isLoading) { if (isLoading) this.loaderPush(); else this.loaderPop(); } ,async loadMenu() { const resultSet = await this._conn.execQuery('SELECT * FROM myMenu'); // Retrieving menu sections var res = resultSet.fetchData(); var sectionMap = {}; let i = 0; for (const row of res) { var parent = row.parentFk; if (!sectionMap[parent]) sectionMap[parent] = []; sectionMap[parent].push(i++); } Vn.Node.removeChilds(this.$.mainMenu); this.createMenu(res, sectionMap, null, this.$.mainMenu); } //++++++++++++++++++++++++++++++++++++++++++++++++++++++ Menu ,createMenu(res, sectionMap, parent, ul) { var sections = sectionMap[parent]; if (!sections) return; for (var i = 0; i < sections.length; i++) { res.row = sections[i]; const row = res[sections[i]]; var li = this.createElement('li'); ul.appendChild(li); var text = this.createTextNode(_(row.description)); var a = this.createElement('a'); if (row.path) { a.href = this.hash.make({form: row.path}); this.menuOptions[row.path] = a; } a.appendChild(text); li.appendChild(a); var formId = row.id; if (sectionMap[formId]) { var submenu = this.createElement('ul'); submenu.className = 'submenu'; li.appendChild(submenu); li.addEventListener('mouseover', this._onLiMouseHover.bind(this, submenu, a)); li.addEventListener('mouseout', this._onLiMouseOut.bind(this)); this.createMenu(res, sectionMap, formId, submenu); } } } ,_onLiMouseHover(submenu, parent) { if (this.menuShown) return; this.hideSubmenu(); this.activeSubmenu = submenu; var rect = parent.getBoundingClientRect(); Vn.Node.addClass(submenu, 'popup'); submenu.style.left = rect.right +'px'; submenu.style.top = rect.top +'px'; } ,_onLiMouseOut() { this.timeout = setTimeout(this.hideSubmenu.bind(this), 160); } ,hideSubmenu() { var submenu = this.activeSubmenu; if (submenu) { Vn.Node.removeClass(submenu, 'popup'); submenu.style.left = ''; submenu.style.top = ''; clearTimeout(this.timeout); this.activeSubmenu = null; this.timeout = 0; } } ,onMenuClick(event) { event.stopPropagation(); this.showMenu(); } ,showMenu() { this.showBackground(); Vn.Node.addClass(this.$.leftPanel, 'show'); this.menuShown = true; this.hideMenuCallback = this.hideMenu.bind(this); this.doc.addEventListener('click', this.hideMenuCallback); } ,hideMenu() { if (!this.menuShown) return; this.hideBackground(); Vn.Node.removeClass(this.$.leftPanel, 'show'); this.menuShown = false; this.doc.removeEventListener('click', this.hideMenuCallback); this.hideMenuCallback = null; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++ Navigation bar ,_onScroll() { if (this._scrollTimeout === null) this._scrollTimeout = setTimeout( this._scrollTimeoutFunc.bind(this), 150); } ,_scrollTimeoutFunc() { if (!this._shown) return; var navbar = this.$.topBar; var yOffset = Vn.Browser.getPageYOffset(); var showNavbar = this._lastYOffset > yOffset || yOffset < navbar.offsetHeight; if (showNavbar !== this._navbarVisible) { if (showNavbar) var translateY = 0; else var translateY = -navbar.offsetHeight; navbar.style.transform = 'translateZ(0) translateY('+ translateY +'px)'; } this._navbarVisible = showNavbar; this._lastYOffset = yOffset; this._scrollTimeout = null; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++ Background ,showBackground() { Vn.Node.addClass(this.$.background, 'show'); } ,hideBackground() { Vn.Node.removeClass(this.$.background, 'show'); } //++++++++++++++++++++++++++++++++++++++++++++++++++++++ Spinner ,loaderPush() { this.loadingCount++; if (this.loadingCount == 1) this.$.loader.start(); } ,loaderPop() { if (this.loadingCount == 0) return; this.loadingCount--; if (this.loadingCount == 0) this.$.loader.stop(); } //++++++++++++++++++++++++++++++++++++++++++++++++++++++ Forms ,async _onFormChange() { var formPath = this.formParam.value; if (!formPath) formPath = Vn.Config.defaultForm; this.hideMenu(); await this.closeForm(); this.requestedForm = formPath; if (!formPath) return; this.loaderPush(); const newChoosedOption = this.menuOptions[formPath]; if (newChoosedOption) { Vn.Node.addClass(newChoosedOption, 'selected'); this.choosedOption = newChoosedOption; } await Vn.Locale.load(`forms/${formPath}`); let FormKlass; try { FormKlass = (await this.importForm(formPath)).default; } catch (err) { this.loaderPop(); console.log(err); return Htk.Toast.showError(_('Error loading form') +`: ${err.message}`); } this.loaderPop(); if (!this._shown) return; this.activeForm = new FormKlass(this); await this.activeForm.open(); } ,async importForm(path) { const states = path.split('/'); let importFn = routes; for (let i = 0; i < states.length && importFn; i++) importFn = importFn[kebabToCamel(states[i])]; if (!importFn) throw new Error(`Route '${path}' does not exist`); return importFn(); } ,setForm(form) { const holder = this.$.formHolder; Vn.Node.removeChilds(holder); if (form) { holder.appendChild(form); holder.classList.add('move-start'); setTimeout(() => this._onSetFormTimeout(), 10); } } ,_onSetFormTimeout() { const holder = this.$.formHolder; holder.classList.remove('move-start'); holder.classList.add('move-end'); holder.addEventListener('transitionend', () => holder.classList.remove('move-end'), {once: true} ); } ,setTitle(title) { Vn.Node.removeChilds(this.$.title); if (title) this.$.title.appendChild(title); } ,setActions(actions) { Vn.Node.removeChilds(this.$.actionBar); if (actions) this.$.actionBar.appendChild(actions); } ,async closeForm() { if (this.activeForm) { Vn.Node.removeClass(this.$.formHolder, 'show'); await this.activeForm.close(); this.activeForm._destroy(); this.activeForm = null; } if (this.activeCss) { Vn.excludeCss(this.activeCss); this.activeCss = null; } if (this.choosedOption) { Vn.Node.removeClass(this.choosedOption, 'selected'); this.choosedOption = null; } } //++++++++++++++++++++++++++++++++++++++++++++++++++++++ Reports ,async openReport(reportName, lot) { try { this.loaderPush(); const module = new Module('reports', reportName); await module.load(); const report = new module.klass(module, this); report.open(lot); } catch(err) { Htk.Toast.showError(_('Error loading report')); } finally { this.loaderPop(); } } //++++++++++++++++++++++++++++++++++++++++++++++++++++++ Supplant /** * Supplants another user. * * @param {String} supplantUser The user name */ ,async supplantUser(supplantUser) { const json = await this._conn.send('client/supplant', {supplantUser}); this._conn.token = json; sessionStorage.setItem('supplantUser', supplantUser); const resultSet = await this._conn.execQuery( 'SELECT nickname FROM account.myUser'); const userName = resultSet.fetchValue(); Vn.Node.setText(this.$.supplanted, userName); this.$.supplant.classList.toggle('show', true); await this.loadMenu(); } /* * Ends the user supplanting and restores the original login. */ ,async onSupplantExitClick() { this._conn.post('Accounts/logout'); this._conn.fetchToken(); sessionStorage.removeItem('supplantUser'); this.$.supplant.classList.toggle('show', false); await this.loadMenu(); this._onFormChange(); } ,async supplantInit() { var user = sessionStorage.getItem('supplantUser'); if (user == null) return; await this.supplantUser(user); } //++++++++++++++++++++++++++++++++++++++++++++++++++++++ Destroy ,_destroy() { this.hide(); Vn.Component.prototype.initialize.call(this); } });