From e3161f306eff1f3536ccd1eb22a3ef6fa4b4a717 Mon Sep 17 00:00:00 2001 From: Smith Date: Mon, 9 May 2022 21:53:01 +0200 Subject: [PATCH] gs.name; gs.timezoneOffset; ref --- index.html | 293 ++++++++++++++++++++++++------------------------- src/watcher.ts | 5 +- 2 files changed, 144 insertions(+), 154 deletions(-) diff --git a/index.html b/index.html index cb1e02e..75303b8 100644 --- a/index.html +++ b/index.html @@ -36,7 +36,6 @@ padding: 0; font-family: 'Roboto', Helvetica, Arial, sans-serif; } - body { background-color: #000; background-position: top center; @@ -47,61 +46,48 @@ background-size: cover; background-image: url('https://i.imgur.com/lTly23N.png'); } - body>nav { background-color: rgba(0, 0, 0, 0.75); } - .navbar-brand img { width: 40px; height: 40px; } - body>nav button[data-api] { margin-right: 1rem; } - #spinner { zoom: 2; opacity: 0.7; } - #protected-section>div>div { background-color: rgba(245, 250, 255, 0.75); } - #config-form h3.card_title>label { font-weight: 900; } - #config-form h3>label { margin-right: 1rem; } - #config-form div[data-schemaid="root"]>div.card-body>div>div { margin-bottom: 3rem; } - #config-form div[data-schemaid="root"]>div.card-body>div>div:last-child { margin-bottom: inherit; } - #config-form button { vertical-align: top; } - #config-form input[type=checkbox] { vertical-align: middle; zoom: 2; cursor: pointer; margin-right: 0.25rem !important; } - #config-form .btn-group { display: inline-flex !important; margin-bottom: 0.25rem; } - #config-form .btn-group button { margin-left: 1px; margin-right: 1px; @@ -110,31 +96,27 @@ border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; } - #config-form .btn-group.je-object__controls { margin: 0 0 0.75rem 0; } - footer>a>svg { fill: #c6cbd1; } - #save-config { background-color: rgba(15, 20, 25, 0.9); } - #save-config ._load_btn { display: none; } - #save-config .loading ._load_btn { display: inherit; } - #save-config .loading ._save_btn { display: none; } - + #F5-btn { + cursor: pointer; + } @@ -189,7 +171,7 @@ Refresh the page to login...
- F5 + F5
@@ -233,45 +215,30 @@ await setRandomBg().catch(() => { }); setInterval(setRandomBg, 60000); + let unsavedChanges = false; + const confirmText = 'You have unsaved changes! Are you sure you want to navigate away?'; + $(window).on('beforeunload', e => { + if (unsavedChanges) return confirmText; + else { + e.preventDefault(); + return false; + } + }); + $('#logout').click(e => { + e.preventDefault(); + if(!unsavedChanges || (unsavedChanges && confirm(confirmText))) logout(); + }); + + activateMenu(); + $('body > nav > ul > li > a').click(e => { + e.preventDefault(); + activateMenu(e.currentTarget); + }); + $('#top-menu').removeClass('invisible'); $('body > footer').removeClass('d-none'); - let unsavedChanges = false; - const leaving = ev => { - if (unsavedChanges) { - const confirmText = 'You have unsaved changes! Are you sure you want to navigate away?'; - if (ev) return confirmText; - else return confirm(confirmText); - } - - if (!ev) return true; - }; - - $(window).on('beforeunload', leaving); - $('#logout').click(async e => { - e.preventDefault(); - if (await leaving()) logout(); - }); - - let initMenu = id('top-menu-configuration'); - if (document.location.hash.length > 1) { - const hashTargetMenu = id('top-menu-' + document.location.hash.slice(1)); - if (hashTargetMenu) { - initMenu = hashTargetMenu; - } - } else if (window.localStorage.getItem('active.menu')) { - const stateTargetMenu = id('top-menu-' + window.localStorage.getItem('active.menu').slice(1)); - if (stateTargetMenu) { - initMenu = stateTargetMenu; - } - } - menu(initMenu); - - $('body > nav > ul > li > a').click(e => { - e.preventDefault(); - menu(e.currentTarget); - }); - + // Configuration const gswConfig = await fetchApi('GET', 'config'); if (gswConfig && gswConfig.config) { configEditor = new JSONEditor(id('config-form'), { @@ -299,20 +266,6 @@ "disable_array_delete_all_rows": 1, "disable_array_delete_last_row": 1, "prompt_before_delete": 1, - "lib_aceeditor": 0, - "lib_autocomplete": 0, - "lib_sceditor": 0, - "lib_simplemde": 1, - "lib_select2": 1, - "lib_selectize": 0, - "lib_choices": 0, - "lib_flatpickr": 1, - "lib_signaturepad": 0, - "lib_mathjs": 0, - "lib_cleavejs": 0, - "lib_jodit": 0, - "lib_jquery": 0, - "lib_dompurify": 1, "schema": { "title": "Configuration", "type": "array", @@ -324,11 +277,19 @@ "title": "Game Server", "type": "object", "required": [ + "name", + "type", "host", - "port", - "type" + "port" ], "properties": { + "name": { + "title": "Name", + "type": "string", + "options": { + "grid_columns": 12 + } + }, "type": { "title": "Gamedig type", "description": "Look for the GameDig Type ID in the games list.", @@ -385,10 +346,13 @@ "grid_columns": 12 } }, - "serverTimezone": { - "title": "Time zone of the server [NOT IMPLEMENTED]", + "timezoneOffset": { + "title": "Time zone offset of the server [NOT IMPLEMENTED]", "default": "Europe/London", - "type": "string", + "type": "number", + "minimum": -24, + "maximum": 24, + "format": "range", "options": { "grid_columns": 6, "grid_break": true @@ -444,7 +408,7 @@ } }, "format": "grid", - "headerTemplate": "{{ self.type }}:{{ self.host }}:{{ self.port }}" + "headerTemplate": "{{#self.name}}{{self.name}}{{/self.name}}{{^self.name}}{{self.type}}:{{self.host}}:{{self.port}}{{/self.name}}" } }, startval: gswConfig.config @@ -457,60 +421,17 @@ $('#spinner').addClass('d-none'); $('#protected-section').removeClass('d-none'); - const button_holder = configEditor.root.theme.getHeaderButtonHolder(); - const exportBtn = configEditor.root.getButton('Export', 'save', 'Export As JSON File'); - button_holder.appendChild(exportBtn); - configEditor.root.header.parentNode.insertBefore(button_holder, configEditor.root.header.nextSibling); - exportBtn.addEventListener('click', e => { - e.preventDefault(); - const dt = (new Date()).toISOString().slice(0, 19).replace(/\D/g, ''); - const filename = dt + '-gsw.config.json'; - const blob = new Blob([JSON.stringify(configEditor.getValue(), null, 2)], { - type: 'application/json;charset=utf-8' - }); + addExportButton(); - if (window.navigator && window.navigator.msSaveOrOpenBlob) { - window.navigator.msSaveOrOpenBlob(blob, filename); - } else { - const a = document.createElement('a'); - a.download = filename; - a.href = URL.createObjectURL(blob); - a.dataset.downloadurl = ['text/plain', a.download, a.href].join(':'); - - a.dispatchEvent(new MouseEvent('click', { - 'view': window, - 'bubbles': true, - 'cancelable': false - })); - } - }, false); - - const getFormVals = () => { - const formItems = $('#config-form .tab-pane:not([style*="display: none"]) input, #config-form .tab-pane:not([style*="display: none"]) textarea, #config-form .tab-pane:not([style*="display: none"]) select').toArray(); - return JSON.stringify(formItems.map(e => { - if (e.type === 'checkbox') { - return e.checked ? e.value : undefined; - } - return e.value; - })); - } - - let formCurrVal = getFormVals(); let editorCurrVal = configEditor.getValue(); + let formCurrVal = actualFormValues(); - const checkForChanges = () => { - if (formCurrVal !== getFormVals()) { - unsavedChanges = true; - $('#save-config').removeClass('d-none'); - $('#save-config').removeClass('animate__fadeOutDown'); - } else { - unsavedChanges = false; - $('#save-config').addClass('animate__fadeOutDown'); - } - }; - - $('#config-form input, #config-form textarea').keyup(checkForChanges); - configEditor.on('change', checkForChanges); + $('#config-form input, #config-form textarea').keyup(() => { + unsavedChanges = checkForChanges(formCurrVal); + }); + configEditor.on('change', () => { + unsavedChanges = checkForChanges(formCurrVal); + }); $('#save-config-submit').click(async e => { e.preventDefault(); @@ -525,7 +446,7 @@ const res = await fetchApi('POST', 'config', configEditor.getValue()); if (res && res.message) { editorCurrVal = configEditor.getValue(); - formCurrVal = getFormVals(); + formCurrVal = actualFormValues(); $('#save-config').addClass('animate__fadeOutDown'); notif('success', '✔️ Changes saved succesfully.', undefined, undefined, 2); } else { @@ -545,26 +466,80 @@ $('#save-config').addClass('animate__fadeOutDown'); }); }); - - $('button[data-api]').click(async e => { - e.preventDefault(); - const endpoint = e.currentTarget.dataset.api; - - if (confirm('Sure you want to call `' + endpoint + '`?')) { - const res = await fetchApi('GET', endpoint); - if (res && res.message) { - notif('success', res.message, undefined, undefined, 3); - } else { - notif('danger', (res ? res.error : undefined), undefined, undefined, 3); - } - } - }); } else { notif('danger', '⚠️ Error while loading config.'); } + + // Flush data + $('button[data-api]').click(async e => { + e.preventDefault(); + const endpoint = e.currentTarget.dataset.api; + + if (confirm('Are you sure you want to call `' + endpoint + '`?')) { + const res = await fetchApi('GET', endpoint); + if (res && res.message) { + notif('success', res.message, undefined, undefined, 3); + } else { + notif('danger', (res ? res.error : undefined), undefined, undefined, 3); + } + } + }); } }); + // NOTE: sadly configEditor.getValue() can not be trusted when the + // change event originates from a keypress event + function actualFormValues() { + const formItems = $('#config-form .tab-pane:not([style*="display: none"]) input, #config-form .tab-pane:not([style*="display: none"]) textarea, #config-form .tab-pane:not([style*="display: none"]) select').toArray(); + return JSON.stringify(formItems.map(e => { + if (e.type === 'checkbox') { + return e.checked ? e.value : undefined; + } + return e.value; + })); + } + + function checkForChanges(formCurrVal) { + if (formCurrVal !== actualFormValues()) { + $('#save-config').removeClass('d-none'); + $('#save-config').removeClass('animate__fadeOutDown'); + return true; + } else { + $('#save-config').addClass('animate__fadeOutDown'); + return false; + } + }; + + function addExportButton() { + const button_holder = configEditor.root.theme.getHeaderButtonHolder(); + const exportBtn = configEditor.root.getButton('Export', 'save', 'Export As JSON File'); + button_holder.appendChild(exportBtn); + configEditor.root.header.parentNode.insertBefore(button_holder, configEditor.root.header.nextSibling); + exportBtn.addEventListener('click', e => { + e.preventDefault(); + const dt = (new Date()).toISOString().slice(0, 19).replace(/\D/g, ''); + const filename = dt + '-gsw.config.json'; + const blob = new Blob([JSON.stringify(configEditor.getValue(), null, 2)], { + type: 'application/json;charset=utf-8' + }); + + if (window.navigator && window.navigator.msSaveOrOpenBlob) { + window.navigator.msSaveOrOpenBlob(blob, filename); + } else { + const a = document.createElement('a'); + a.download = filename; + a.href = URL.createObjectURL(blob); + a.dataset.downloadurl = ['text/plain', a.download, a.href].join(':'); + + a.dispatchEvent(new MouseEvent('click', { + 'view': window, + 'bubbles': true, + 'cancelable': false + })); + } + }, false); + } + function logout() { $('#save-config').addClass('animate__fadeOutDown'); $('#top-menu').addClass('invisible'); @@ -625,18 +600,32 @@ return el; } - function menu(activate) { - const target = activate.getAttribute('href'); + function activateMenu(target) { + if (!target) { + target = id('top-menu-configuration'); + if (document.location.hash.length > 1) { + const hashTargetMenu = id('top-menu-' + document.location.hash.slice(1)); + if (hashTargetMenu) { + target = hashTargetMenu; + } + } else if (window.localStorage.getItem('active.menu')) { + const stateTargetMenu = id('top-menu-' + window.localStorage.getItem('active.menu').slice(1)); + if (stateTargetMenu) { + target = stateTargetMenu; + } + } + } + const menu = target.getAttribute('href'); const menuItems = q('#top-menu > ul > li > a'); for (const a of menuItems) { const at = a.getAttribute('href'); - if (at === target) { + if (at === menu) { $(at).removeClass('d-none'); $(a).addClass('active'); - window.history.replaceState(null, null, document.location.pathname + target); - window.localStorage.setItem('active.menu', target); + window.history.replaceState(null, null, document.location.pathname + menu); + window.localStorage.setItem('active.menu', menu); } else { $(at).addClass('d-none'); $(a).removeClass('active'); @@ -710,7 +699,8 @@ if (ans) window.localStorage.setItem('btoken', await generateBearerToken(ans)); else window.localStorage.removeItem('btoken', null); } else { - + const hint = '
API Close the tab to re-enable dialog boxes.'; + $('#bye > h3').html($('#bye > h3').html() + hint); } return window.localStorage.getItem('btoken'); @@ -732,9 +722,8 @@ 'https://i.imgur.com/gQD3xfo.png', 'https://i.imgur.com/iKTfM8z.png' ]; + const bgImg = new Image(); - - bgImg.src = bgs[Math.floor(Math.random() * bgs.length)]; return new Promise((resolve, reject) => { diff --git a/src/watcher.ts b/src/watcher.ts index 4ce0548..72e00f2 100644 --- a/src/watcher.ts +++ b/src/watcher.ts @@ -19,13 +19,14 @@ interface TelegramConfig { } export interface GameServerConfig { + name: string; + type: Type; host: string; port: number; - type: Type; appId?: number;//0 updateIntervalMinutes?: number;//5 graphHistoryHours?: number;//12 - serverTimezone?: string;//Europe/London + timezoneOffset?: number;//0 discord?: DiscordConfig[], telegram?: TelegramConfig[]; }