Newer
Older
"use strict";
import Luci from './luci.js';
import Antifurto from './antifurto.js';
import { showAlert, makeElementBounce } from "./alerts.js";
// import Api, { setScenarioStatus, recordScenario, saveScenario } from "./api.js";
// JSON templeate for scenario
const scenarioTemplate = {
"nome": "",
/**
* the div where everything related to the Scenari is stored
*/
static scenariContainer = document.getElementById('scenariContainer');
/**
* this is the select element where to add all the scenarios
*/
static addNameHere = document.getElementById('p');
/**
* contains the toggle that is currently active
*/
/**
* the array where all of the user's scenari are stored
*/
Scenari.scenariContainer = document.getElementById('scenariContainer');
Scenari.addNameHere = document.getElementById('p');
Scenari.antifurtoModalLauncherListener();
/**
* sets up the listener for the button in the top of the page
* i'm also leaving here what I haven't yet implemented
*/
const scenariBtn = document.getElementById('mainButtonContainer').children[1];
scenariBtn.addEventListener('click', () => {
Scenari.toggleContainer(true);
Luci.toggleContainer(false);
Antifurto.toggleContainer(false);
}, false);
const registerBtn = document.getElementById('scenari-registra');
registerBtn.addEventListener('click', event => {
event.preventDefault();
// TODO choose how to register the scenario
}, false);
/**
* used for the antitheft button (ON/OFF): before opening the connected modal, change its text then open it
* @see Scenari.antifurtoModalSubmitListener
*/
static antifurtoModalLauncherListener() {
const antifurtoBtn = document.getElementById('scenari-stato-antifurto');
const okBtn = document.getElementById('attiva-antifurto-btn');
const modalBody = document.querySelector('#antifurto-modal .modal-body');
const modalLauncher = document.getElementById('lancia-antifurto-modal');
const registerBtn = document.getElementById('scenari-registra');
if (registerBtn.innerText !== "Registra") {//sto registrando
showAlert("Attenzione", "Stai registrando uno scenario, termina la registrazione per attivare l'antifurto.", false);
if (Scenari.scenariBucket.length === 0) {
showAlert('Nessun scenario disponibile', 'Registrare uno o più scenari per poter attivarne uno', false);
// make the registerBtn bounce for 3 seconds
const registerBtn = document.getElementById('scenari-registra');
makeElementBounce(registerBtn);
const children = modalBody.children;
// p, p
/*
<p>Stai per abilitare l'antifurto.</p>
<p>Vuoi continuare?</p>
*/
if (antifurtoBtn.innerText === 'ON') {
// the antitheft is on
children[0].innerText = "Stai per disabilitare l'antifurto.";
okBtn.innerText = 'Disattiva';
} else {
// the antitheft is off
children[0].innerText = "Stai per abilitare l'antifurto.";
okBtn.innerText = 'Attiva';
}
// launch the modal
modalLauncher.click();
// related: Scenari.antifurtoModalSubmitListener();
/**
* sets up various listeners for the modals
* @see Scenari.attivaScenarioModal
* @see Scenari.registraModal
* @see Scenari.antifurtoModalSubmitListener
*/
static anyModalListener() {
Scenari.anteprimaModal();
Scenari.attivaScenarioModal();
Scenari.registraModal();
Scenari.antifurtoModalSubmitListener();
}
/**
* listens to the submit button in the modal for the antitheft and activates/deactivates the antitheft
* this modal is shown when the user clicks on the antitheft button
* @see Scenari.antifurtoModalLauncherListener
*/
static antifurtoModalSubmitListener() {
const antifurtoOkBtn = document.getElementById('attiva-antifurto-btn');
const closeBtn = document.querySelector('#antifurto-modal .btn.btn-danger');
const antifurtoBtn = document.getElementById('scenari-stato-antifurto');
antifurtoOkBtn.addEventListener('click', () => {
// close modal
closeBtn.click();
// switch the antitheft status button
const isActivatingAntitheft = antifurtoBtn.innerText === 'OFF';
// Scenari.toggleAntifurto(isActivatingAntitheft);
if (isActivatingAntitheft)
Scenari.activateRandomScenario();
else
Scenari.deactivateActiveScenario();//cannot use toggleScenario because I don't have the scenarioID
// Antifurto.activate(isActivatingAntitheft) already taken care of
/**
* listens for the submit of the anteprima modal
*/
static anteprimaModal() {
const anterprimaModal = document.getElementById('anteprima-modal');
const okBtn = anterprimaModal.querySelector('#anteprima-scenari-btn');
const modalBody = anterprimaModal.querySelector('.modal-body');
const closeBtn = anterprimaModal.querySelector('.btn.btn-danger');
okBtn.addEventListener('click', () => {//activate the scenario
// close the modal
closeBtn.click();
// get the scenario from the modal body
const scenarioID = modalBody.querySelector('.invisible').innerText;
// find the scenario's row on the page
// const scenarioRow = scenarioTable.querySelector(`#${scenarioName}`);
// const toggle = scenarioTable.querySelector(`#${scenarioName} .toggle-button`);
Scenari.toggleScenario(scenarioID, okBtn.innerText === 'Attiva');
}, false);
}
/**
* listenes for the submit button in the modal for activating/deactivating a scenario when chosen from the toggles
* @see scenariToggleListener
*/
static attivaScenarioModal() {
const modalBtn = document.getElementById('attiva-scenari-btn');
const closeBtn = document.querySelector('#attiva-scenari-modal .btn.btn-danger');
modalBtn.addEventListener('click', () => {
// close the modal by clicking on the close button
closeBtn.click();
// I have to get to the toggle and activate it from the value of the select
const scenarioID = Scenari.addNameHere.value;
const toggle = document.querySelector(`#${scenarioID} .toggle-button`);
// const isActivatingNewScenario = ;
// Scenari.toggleToggle(toggle,isActivatingNewScenario);
// Scenari.toggleAntifurto(isActivatingNewScenario);
Scenari.toggleScenario(scenarioID, toggle !== Scenari.scenarioAttivoToggle);
/**
* this is for the button "registra"/"termina" and the related modals
* @see Scenari.registraBtnListener
* @see Scenari.submitRecordModalListener
* @see Scenari.endRecordingListener
*/
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
static registraModal() {
const scenariModal = document.getElementById('scenari-modal');
const registraBtn = document.getElementById('scenari-registra');
const okBtn = scenariModal.querySelector('.btn.btn-info');
const modalBody = scenariModal.querySelector('.modal-body');
const htmlForModalBody = `<p>Stai per attivare la registrazione dei comandi.</p>
<p>Dal momento in cui premerai sul bottone azzurro, inizierai a registrare tutte le interazioni con le tue luci.</p>
<p>Inoltre disabiliterai eventuali scenari attivi.</p>
<p>Una volta che sarai soddisfatto del risultato, torna su questa pagina per terminare la registrazione.</p>
<p>Inizare la registrazione?</p>`
const modalLauncher = document.getElementById('registra-modal-launcer');
// const okBtn = scenariModal.querySelector('.btn.btn-info');
// const registraBtn = document.getElementById('scenari-registra');
const closeScenariModalBtn = scenariModal.querySelector('.btn.btn-danger');
const endRecordingModalLauncher = document.getElementById('termina-registrazione-launcher');
const endRecordingForm = document.getElementById('termina-registrazione-form');
// const modalBody = scenariModal.querySelector('.modal-body');
// htmlForModalBody = ...
const closeRecordingBtn = document.getElementById('termina-registrazione-modal').querySelector('.btn.btn-danger');
const campoNome = document.getElementById('nome-nuovo-scenario');
Scenari.registraBtnListener(registraBtn, okBtn, modalBody, htmlForModalBody, modalLauncher);
Scenari.submitRecordModalListener(okBtn, registraBtn, closeScenariModalBtn, endRecordingModalLauncher);
Scenari.endRecordingListener(endRecordingForm, modalBody, htmlForModalBody, closeRecordingBtn, campoNome);
/**
* listens for the actual "registra"/"termina" button on the page and edits the related modal accordingly
* @param {HTMLButtonElement} registraBtn the button on the page
* @param {HTMLButtonElement} okBtn the submit button in the modal
* @param {HTMLElement} modalBody the body of the modal which is to be changed
* @param {string} htmlForModalBody a string containing the html to be inserted in the modal body
* @param {HTMLButtonElement} modalLauncher the button which launches the modal
* @see Scenari.registraModal
*/
static registraBtnListener(registraBtn, okBtn, modalBody, htmlForModalBody, modalLauncher) {
registraBtn.addEventListener('click', () => {
const isAboutToRecord = registraBtn.innerText === 'Registra';
// change text of okBtn
okBtn.innerText = isAboutToRecord ? 'Registra' : 'Termina';
// change inner text of the modal
if (isAboutToRecord) {
modalBody.innerHTML = htmlForModalBody;
} else {
modalBody.innerHTML = `
<p>Stai per terminare la registrazione dei comandi.</p>
<p>Terminare la registrazione?</p>`;
// related: Scenari.submitRecordModalListener
/**
* listens for the submit of the modal which is launched when the user clicks on the "registra"/"termina" button
* @param {HTMLButtonElement} okBtn the submit button in the modal
* @param {HTMLButtonElement} registraBtn the button on the page (to understand if the user is about to record or not)
* @param {HTMLButtonElement} closeScenariModalBtn the button used to close the modal
* @param {HTMLButtonElement} endRecordingModalLauncher the button which launches the next modal (used if the user has finished recording)
* @see Scenari.registraModal
*/
static submitRecordModalListener(okBtn, registraBtn, closeScenariModalBtn, endRecordingModalLauncher) {
okBtn.addEventListener('click', () => {
const isAboutToRecord = registraBtn.innerText === 'Registra';
// close modal
closeScenariModalBtn.click();
// get the current time
// const timeBegin = new Date();
// if the user ended the recording, show another modal to ask for the name of the scenario
if (isAboutToRecord) {
registraBtn.innerText = 'Termina';
// HERE server send a note to start recording
Api.recordScenario(true);
Scenari.deactivateActiveScenario();
} else {
registraBtn.innerText = 'Registra';
// HERE server send a note to stop recording
Api.recordScenario(false);
// related: Scenari.endRecordingListener
/**
* listens for the submit of the modal which is launched when the user is done recording a scenario
* @param {HTMLFormElement} endRecordingForm the form used to submit the name of the scenario
* @param {HTMLElement} modalBody the body of the modal which is to be changed
* @param {string} htmlForModalBody a string containing the html to be inserted in the modal body
* @param {HTMLButtonElement} closeRecordingBtn the button used to close the modal
* @param {HTMLInputElement} campoNome the input field used to insert the name of the scenario by the user
* @see Scenari.registraModal
* @see Scenari.mostraNuovoScenario
*/
static endRecordingListener(endRecordingForm, modalBody, htmlForModalBody, closeRecordingBtn, campoNome) {
endRecordingForm.addEventListener('submit', event => {
// reset the other modal and button
modalBody.innerHTML = htmlForModalBody;
// close the modal
closeRecordingBtn.click();
const name = campoNome.value;
const scenario = Scenari.createScenarioFromName(name)
Scenari.mostraNuovoScenario(scenario);
// clear the field for the next use
campoNome.value = '';
// TODO server send a note to save the scenario
/**
* takes care of launching a modal to preview the actions of the chosen scenario; it also listens for the submit of the launched modal
* @param {HTMLButtonElement} anteprimaBtn the button used to launch the modal
* @param {scenarioTemplate} scenario the JSON scenario to be previewed
* @see Scenari.correctlySetToggle
*/
static anteprimaListener(anteprimaBtn, scenario) {
const scenarioID = scenario.id;
const anterprimaModal = document.getElementById('anteprima-modal');
const modalBody = anterprimaModal.querySelector('.modal-body');
const modalLauncher = document.getElementById('anteprima-modal-launcher');
const okBtn = anterprimaModal.querySelector('#anteprima-scenari-btn');
const scenarioTable = document.getElementById('table-row-scenari');
const registerBtn = document.getElementById('scenari-registra');
anteprimaBtn.addEventListener('click', () => {
if (registerBtn.innerText !== "Registra") {//sto registrando
showAlert("Attenzione", "Stai registrando uno scenario, termina la registrazione per mostrare l'anteprima.", false);
return;
}
// TODO server get the scenario's data
// show the scenario in the modal (choose how to display it)
modalBody.innerHTML = `
<p>${scenario.nome}</p>
<p>${scenario.data}</p>
<span class='invisible'>${scenarioID}</span>`;//FIXME remove this test (be sure to keep the last span as is)
// if the scenario is already active, change the okBtn text
// to find if it's active, find the relative toggle
// and check if it's active
// const scenarioRow = scenarioTable.querySelector(`#${name}`);
const toggle = scenarioTable.querySelector(`#${scenarioID} .toggle-button`);
okBtn.innerText = toggle.classList.contains('active') ? 'Disattiva' : 'Attiva';
// launch the modal
modalLauncher.click();
}, false);
// utilility functions
/**
* displays the given scenario on the screen (below every other one) and hooks up the listeners; then it increments the index
* @param {scenarioTemplate} scenario the JSON scenario to be displayed
* @see Scenari.createScenarioRow
* @see Scenari.anteprimaListener
* @see scenariToggleListener
*/
const row = Scenari.createScenarioRow(scenario);
const scenarioID = scenario.id;
const tableBody = document.getElementById('table-row-scenari');
tableBody.appendChild(row);
const anteprimaBtn = row.querySelector('.badge.rounded-pill');
Scenari.anteprimaListener(anteprimaBtn, scenario);
// add the name of the scenario as option in the select of the modal
const option = document.createElement('option');
option.value = scenarioID;
option.innerText = scenario.nome;
Scenari.addNameHere.appendChild(option);
const toggle = row.querySelector('.toggle-button');
scenariToggleListener(toggle, scenarioID);
/**
* creates a table entry for the given scenario and returns it
* @param {scenarioTemplate} scenario the JSON scenario to be displayed
* @returns {HTMLTableRowElement} the row containing the given scenario
*/
static createScenarioRow(scenario) {
const row = document.createElement('tr');
row.id = scenario.id;
row.innerHTML = `
<th scope="row">${scenario.nome.trim()}</th>
<td>
<span>${scenario.data}</span>
</td>
<td>
<h5>
<span class="badge rounded-pill bg-secondary">anteprima</span>
</h5>
</td>
<td>
<div class="switch-container no-box-sizing">
<div id="toggle-${scenario.id}" class="toggle-button no-box-sizing">
<div class="inner-circle no-box-sizing"></div>
</div>
</div>
<span id="launch-modal-${scenario.id}" data-bs-toggle="modal" data-bs-target="#attiva-scenari-modal"></span>
</td>`;
// the span is used by the toggle to launch the modal
return row;
/**
* changes the antifurto button to the given state
* @param {Boolean} activating true if the antitheft is being activated, false otherwise
* @param {Boolean} fromAntifurto usually false or undefined; true only if the function is called from the scenari
static correctlySetAntifurto(activating, fromAntifurto = false) {
if (fromAntifurto !== true)
Antifurto.activate(activating, true);
const antifurtoBtn = document.getElementById('scenari-stato-antifurto');
if (activating) {
return;
antifurtoBtn.innerText = 'ON';
antifurtoBtn.classList.remove('btn-danger');
antifurtoBtn.classList.add('btn-success');
} else {
return;
antifurtoBtn.innerText = 'OFF';
antifurtoBtn.classList.remove('btn-success');
antifurtoBtn.classList.add('btn-danger');
}
}
/**
* turns off the active scenario if there is one; useful if you don't have the scenarioID
*/
static deactivateActiveScenario() {
if (Scenari.scenarioAttivoToggle == null)
return;
// Scenari.scenarioAttivoToggle.classList.remove('active');
// Scenari.scenarioAttivoToggle = null;
const toggleID = Scenari.scenarioAttivoToggle.id;
const scenarioID = toggleID.substring(toggleID.indexOf('-') + 1);
Scenari.toggleScenario(scenarioID, false);
}
/**
* activates/deactivates the scenario with the given name
* @param {string} scenarioID the ID of the scenario to be activated/deactivated
* @param {Boolean} activating true if the scenario should be activated, false otherwise
*/
static toggleScenario(scenarioID, activating) {
// find the scenario's row on the page
const scenarioRow = document.getElementById(`${scenarioID}`);
const toggle = scenarioRow.querySelector('.toggle-button');
Scenari.correctlySetToggle(toggle);
Scenari.correctlySetAntifurto(activating);
// if (activating) {
// // TODO server deactivate the scenario
// }
}
/**
* takes care of activating or deactivating the scenario's toggle based on the given boolean
* @param {HTMLElement} toggle the toggle to be activated or deactivated
* @see Scenari.correctlySetAntifurto
*/
static correctlySetToggle(toggle) {
const isActivatingNewScenario = toggle !== Scenari.scenarioAttivoToggle;
Scenari.scenarioAttivoToggle?.classList.remove('active');
if (isActivatingNewScenario) {
toggle.classList.add('active');
Scenari.scenarioAttivoToggle = toggle;
} else {
toggle.classList.remove('active');
Scenari.scenarioAttivoToggle = null;
}
/**
* activates a random scenario from the ones available
*/
static activateRandomScenario() {
if (Scenari.scenariBucket.length === 0) {
showAlert('Nessun scenario disponibile', 'Registrare uno o più scenari per poter attivarne uno', false);
// make the registerBtn bounce for 3 seconds
const registerBtn = document.getElementById('scenari-registra');
makeElementBounce(registerBtn);
return;
}
const randomIndex = Math.floor(Math.random() * Scenari.index);
const scenarioID = `scenario-${randomIndex}`;
// const table = document.getElementById('table-row-scenari');
// // enable a random scenario
// const randomScenario = table.children[Math.floor(Math.random() * table.children.length)];
// const scenarioID = randomScenario.id;
Scenari.toggleScenario(scenarioID, true);
}
/**
* creates the scenario and updates index
* @param {string} scenarioName the string of the scenario to create
* @returns {scenarioTemplate} the JSON scenario
*/
static createScenarioFromName(scenarioName) {
const scenario = Object.assign({}, scenarioTemplate);
scenario.nome = scenarioName;
scenario.data = new Date().toLocaleDateString();// assign at scenario.data the string YYYY/MM/DD from the current date
scenario.id = `scenario-${Scenari.index}`;
Scenari.index++;
static impostaAntifurtoDaServer() {
// HERE server get antifurto status and set it correctly in the page
const statoAntifurto = Api.getAntifurtoStatus();
Scenari.correctlySetAntifurto(statoAntifurto);
}
/**
* fills the table with the scenarios available for the user in the server
* @see Scenari.mostraNuovoScenario
*/
static fillTable() {
// TODO server get all scenarios
const scenari = [];
for (const scenario of scenari) {
Scenari.mostraNuovoScenario(scenario)
// TODO if scenario is active, change the toggle to active
// also set Scenari.scenarioAttivoToggle to its toggle
}
}
/**
* toggle the visibility of the scenari container
* @param {Boolean} visible true if the container should be shown, false otherwise
Scenari.scenariContainer.classList.remove('invisible');
// make the register button bounce
const registerBtn = document.getElementById('scenari-registra');
makeElementBounce(registerBtn);
}