From 5c93b7a49268443808df64370272872659f241b3 Mon Sep 17 00:00:00 2001 From: haim kastner Date: Tue, 21 Jan 2020 20:07:53 +0200 Subject: [PATCH] Add Button for overall turn off #100 At the lite dashboard --- frontend/src/light-app/index.css | 33 +++++++ frontend/src/light-app/index.html | 29 +++++- frontend/src/light-app/index.js | 148 ++++++++++++++++++++---------- 3 files changed, 163 insertions(+), 47 deletions(-) diff --git a/frontend/src/light-app/index.css b/frontend/src/light-app/index.css index 7608589e..a6de4849 100644 --- a/frontend/src/light-app/index.css +++ b/frontend/src/light-app/index.css @@ -9,6 +9,39 @@ body { text-align: center; } +.hide { + display: none; +} + +.power-off-container { + position: absolute; + margin: 0; + padding: 0; +} + +#power-on { + cursor: pointer; + fill: #6dbdb9; + color: #6dbdb9; +} + +.power-on-text { + font-size: xx-small; + text-align: center; + margin: 0; + padding: 0; +} + +#power-off { + fill: #737471; + color: #737471; +} + +#power-sync { + fill: #737471; + color: #737471; +} + .dashboard-link { color: rgb(155, 155, 232); font-family: helvetica; diff --git a/frontend/src/light-app/index.html b/frontend/src/light-app/index.html index 949c88fb..bc6befbe 100644 --- a/frontend/src/light-app/index.html +++ b/frontend/src/light-app/index.html @@ -9,8 +9,35 @@ +
+
+

Turn Off All

+ + + + +
+
+
+ + + + +
+
+
+ + + + +
+
+
- Click here to move to the full dashboard version + Full dashboard

Welcome To Casanet Lite Dashboard

diff --git a/frontend/src/light-app/index.js b/frontend/src/light-app/index.js index 3289c2e7..3a2a9948 100644 --- a/frontend/src/light-app/index.js +++ b/frontend/src/light-app/index.js @@ -1,16 +1,19 @@ /** Get the environments */ let environments = { - API_URL: "http://127.0.0.1:3000/API", - DASHBOARD_DOMAIN: "" + API_URL: 'http://127.0.0.1:3000/API', + DASHBOARD_DOMAIN: '', }; +/** Flag to know if the 'power off' syncing */ +let isSync = false; + let domainAlert = () => { if (document.baseURI.includes(environments.DASHBOARD_DOMAIN)) { return; } const result = confirm( - `The address of the service has changed and you will soon get off the air, please move to our new address!\n\n${environments.DASHBOARD_DOMAIN}\n\nPress 'OK' to move the new home` + `The address of the service has changed and you will soon get off the air, please move to our new address!\n\n${environments.DASHBOARD_DOMAIN}\n\nPress 'OK' to move the new home`, ); if (!result) { return; @@ -28,13 +31,13 @@ let fetchEnvironments = () => { } if (xmlhttp.status === 401 || xmlhttp.status === 403) { - alert("GET ENVIRONMENTS FAIL"); + alert('GET ENVIRONMENTS FAIL'); return; } getMinionsFail(xmlhttp.responseText); }; - xmlhttp.open("GET", "/light-app/environments.json", false); + xmlhttp.open('GET', '/light-app/environments.json', false); xmlhttp.send(); }; @@ -45,40 +48,43 @@ fetchEnvironments(); * Redirect to auth page. */ let accessFail = () => { - alert("ACCESS FORBIDDEN, redirecting to auth page..."); - window.location.href = "/#/login"; + alert('ACCESS FORBIDDEN, redirecting to auth page...'); + window.location.href = '/#/login'; }; let getMinionsFail = msg => { if (confirm(`GET MINIONS FAIL: \n${msg},\n\n\nPress "OK" to retry`)) { - patchMinions(); + petchMinions(); } }; /** * Generate HTML button for given minion * @param {*} minion A minion - * @returns A DOM button object for the given minion + * @returns A DOM button object for the given minion */ let generateMinionButton = minion => { /** Create button element */ - const minionButton = document.createElement("a"); + const minionButton = document.createElement('a'); /** Insert name */ minionButton.innerText = minion.name; try { /** Set correct class for current status */ - minionButton.className = `button button--ghost button--ghost--${ - minion.minionStatus[minion.minionType].status - }`; + minionButton.className = `button button--ghost button--ghost--${minion.minionStatus[minion.minionType].status}`; + + if (!isSync && minion.minionStatus[minion.minionType].status === 'on') { + // In case the minion status are 'on' allow 'power-all-off' button + setViewPowerOn(); + } if (!minion.isProperlyCommunicated) { minionButton.className = `button button--ghost button--ghost--err`; } } catch (error) { minion.minionStatus[minion.minionType] = { - status: "off" + status: 'off', }; minionButton.className = `button button--ghost button--ghost--err`; } @@ -104,28 +110,34 @@ let generateMinions = minions => { }); const rooms = minions.reduce((rooms, minion) => { - minion.room = minion.room ? minion.room : ""; + minion.room = minion.room ? minion.room : ''; rooms[minion.room] = rooms[minion.room] ? rooms[minion.room] : []; rooms[minion.room].push(minion); return rooms; }, {}); /** Get the list holder element */ - const welcomeElement = document.getElementById("welcome-message"); - welcomeElement.innerHTML = ""; + const welcomeElement = document.getElementById('welcome-message'); + welcomeElement.innerHTML = ''; /** Get the list holder element */ - const listElement = document.getElementById("minions-container"); + const listElement = document.getElementById('minions-container'); /** Set list empty */ - listElement.innerHTML = ""; + listElement.innerHTML = ''; + + if (!isSync) { + // If the power off not currently sync, set power off, + // and in case any of the minion status are 'on' then call to 'setViewPowerOn()' + setViewPowerOff(); + } for (const [roomName, roomMinions] of Object.entries(rooms)) { - const roomDiv = document.createElement("div"); - roomDiv.className = "room"; + const roomDiv = document.createElement('div'); + roomDiv.className = 'room'; - const roomTitle = document.createElement("h3"); - roomTitle.className = "room-name"; + const roomTitle = document.createElement('h3'); + roomTitle.className = 'room-name'; roomTitle.innerText = roomName; roomDiv.appendChild(roomTitle); @@ -140,7 +152,7 @@ let generateMinions = minions => { }; /** Get minions from server */ -let patchMinions = () => { +let petchMinions = () => { // compatible with IE7+, Firefox, Chrome, Opera, Safari const xmlhttp = new XMLHttpRequest(); xmlhttp.withCredentials = true; @@ -157,21 +169,21 @@ let patchMinions = () => { getMinionsFail(xmlhttp.responseText); }; - xmlhttp.open("GET", `${environments.API_URL}/minions`, true); + xmlhttp.open('GET', `${environments.API_URL}/minions`, true); xmlhttp.send(); }; /** Toggle minion status on click */ let buttonClicked = (element, minion) => { - if (minion.sync) { + if (minion.sync || isSync) { return; } + minion.sync = true; - element.className = element.className + " button--slicein--sync"; + element.className = element.className + ' button--slicein--sync'; const setStatus = JSON.parse(JSON.stringify(minion.minionStatus)); - setStatus[minion.minionType].status = - setStatus[minion.minionType].status === "on" ? "off" : "on"; + setStatus[minion.minionType].status = setStatus[minion.minionType].status === 'on' ? 'off' : 'on'; // compatible with IE7+, Firefox, Chrome, Opera, Safari const xmlhttp = new XMLHttpRequest(); @@ -183,51 +195,95 @@ let buttonClicked = (element, minion) => { } if (xmlhttp.status === 204) { - patchMinions(); + petchMinions(); return; } - element.className = `button button--ghost button--ghost--${ - minion.minionStatus[minion.minionType].status - }`; + element.className = `button button--ghost button--ghost--${minion.minionStatus[minion.minionType].status}`; if (xmlhttp.status === 401 || xmlhttp.status === 403) { accessFail(); } }; - xmlhttp.open( - "PUT", - `${environments.API_URL}/minions/${minion.minionId}`, - true - ); - xmlhttp.setRequestHeader("Content-type", "application/json; charset=utf-8"); + xmlhttp.open('PUT', `${environments.API_URL}/minions/${minion.minionId}`, true); + xmlhttp.setRequestHeader('Content-type', 'application/json; charset=utf-8'); xmlhttp.send(JSON.stringify(setStatus)); }; +let setViewPowerOn = () => { + const powerOnContainer = document.getElementById('power-on'); + const powerOffContainer = document.getElementById('power-off'); + const powerSyncContainer = document.getElementById('power-sync'); + + powerOnContainer.className = ''; + powerOffContainer.className = 'hide'; + powerSyncContainer.className = 'hide'; +}; + +let setViewPowerOff = () => { + const powerOnContainer = document.getElementById('power-on'); + const powerOffContainer = document.getElementById('power-off'); + const powerSyncContainer = document.getElementById('power-sync'); + + powerOnContainer.className = 'hide'; + powerOffContainer.className = ''; + powerSyncContainer.className = 'hide'; +}; + +let setViewPowerSync = () => { + const powerOnContainer = document.getElementById('power-on'); + const powerOffContainer = document.getElementById('power-off'); + const powerSyncContainer = document.getElementById('power-sync'); + + powerOnContainer.className = 'hide'; + powerOffContainer.className = 'hide'; + powerSyncContainer.className = ''; +}; + +let powerAllOff = () => { + isSync = true; + + // Mark view as sync + setViewPowerSync(); + + const xmlhttp = new XMLHttpRequest(); + xmlhttp.onload = () => { + if (xmlhttp.readyState === 4 && xmlhttp.status == 204) { + isSync = false; + petchMinions(); + return; + } + + alert('POWER OFF FAIL'); + }; + xmlhttp.open('PUT', `${environments.API_URL}/minions/power-off`, true); + xmlhttp.send(); +}; + /** On start. get and generate minions */ -patchMinions(); +petchMinions(); /** SSE */ var evtSource = new EventSource(`${environments.API_URL}/feed/minions`, { - withCredentials: true + withCredentials: true, }); evtSource.onmessage = e => { if (e.data === '"init"') { return; } - patchMinions(); + petchMinions(); }; /** PWA */ -if (localStorage.getItem("use-sw") === "true" && "serviceWorker" in navigator) { +if (localStorage.getItem('use-sw') === 'true' && 'serviceWorker' in navigator) { navigator.serviceWorker - .register("/light-app/service-worker.js") + .register('/light-app/service-worker.js') .then(function(registration) { - console.log("Registration successful, scope is:", registration.scope); + console.log('Registration successful, scope is:', registration.scope); }) .catch(function(error) { - console.warn("Service worker registration failed, error:", error); + console.warn('Service worker registration failed, error:', error); }); }