// Imports import * as Auth from "/services/auth/auth.js"; import * as results from "/services/election/calculate-election-generic.js"; import * as PartyModel from "/services/model/party-model.js"; import * as Scroller from "/services/common/scroller.js"; export async function mount(where, round) { const resultComponent = new ResultComponent(round); await resultComponent.mount(where); await resultComponent.calculateResults(); resultComponent.displayResults(); } class ResultComponent { constructor(round) { this.round = round; this.PartyModel = PartyModel.getPartyModel(); } async mount(where) { this.PartyModel.current_user = await Auth.GetUser(); const mountpoint = where; document.getElementById(mountpoint).innerHTML = /* HTML */ ` <div class="tabs is-boxed is-toggle is-fullwidth"> <ul> <li id="areas" class="is-active"> <a> <span>Circonscriptions</span> </a> </li> <li id="sections"> <a> <span>Villes</span> </a> </li> </ul> </div> <div class="control filter"> <label class="radio"> <input type="radio" name="filter" value="partial" checked /> Partiel </label> <label class="radio"> <input type="radio" name="filter" value="completed" /> Complété </label> <label class="radio"> <input type="radio" name="filter" value="validated" /> Validé </label> </div> <div class="columns"> <div class="column is-half"> <div id="map-section" class="card-no-hover"> <header class="card-header"> <p class="card-header-title"> Carte </p> <button id="zoom-map" class="button is-success"> <span class="icon is-small"> <i class="fas fa-search"></i> </span> </button> </header> <div class="card-content"> <div id="round-list" class="content"> La carte du tour </div> </div> </div> </div> <div class="column"> <div id="news-flow-section" class="card-no-hover"> <header class="card-header"> <p class="card-header-title"> Actualités </p> <button id="zoom-news-flow" class="button is-success"> <span class="icon is-small"> <i class="fas fa-search"></i> </span> </button> </header> <div class="card-content"> <div id="news-flow" class="content"> Flux d'actualité </div> </div> </div> <div id="results-section" class="card-no-hover" "> <header class="card-header"> <p class="card-header-title"> Résultats </p> <button id="zoom-results" class="button is-success"> <span class="icon is-small"> <i class="fas fa-search"></i> </span> </button> </header> <div class="card-content"> <div id="detailed-results" class="content"> <div class="control select"> <select id="select-areas" class="input"></select> </div> <div class="control select"> <select id="select-sections" class="input"></select> </div> <div id="zone-results"></div> <div id="zone-detaileds-results" style="display:none"></div> </div> </div> </div> </div> `; this.calculator = await results.mountCalculator(this.round); this.handleDom(); document.getElementById("areas").click(); } resultFlowTemplate(zone) { return /* HTML */ `<div class="card-list card-no-hover"> <div class="card-content"> <div id="flow-content-${zone.ID}" class="content"> <h5 class="title is-5">${zone.Name}</h5> </div> </div> </div>`; } progressBarTemplate(candidateList, color) { return /* HTML */ `<div class="progressBar"> <div class="progressBarValue" style="background-color : ${color}; width : ${candidateList.Percentage}%" > ${candidateList.Name + " (" + (candidateList.VoiceNumber != null ? candidateList.VoiceNumber + " votes soit : " : "") + candidateList.Percentage + "%)"} </div> </div>`; } showWarningResults(text) { return /* HTML */ `<br /> <article class="message is-warning"> <div class="message-header"> <p>Warning</p> </div> <div class="message-body"> ${text} </div> </article>`; } handleDom() { let resultHandler = this; document.getElementById("areas").addEventListener("click", function () { resultHandler.zone = "areas"; resultHandler.calculateResults(); resultHandler.displayResults(); document.getElementById("sections").setAttribute("class", ""); document.getElementById("areas").setAttribute("class", "is-active"); }); document.getElementById("sections").addEventListener("click", function () { resultHandler.zone = "sections"; resultHandler.calculateResults(); resultHandler.displayResults(); document.getElementById("areas").setAttribute("class", ""); document.getElementById("sections").setAttribute("class", "is-active"); }); document.getElementById("zoom-map").addEventListener("click", function () { resultHandler.zoomMap(); }); document .getElementById("zoom-news-flow") .addEventListener("click", function () { resultHandler.zoomNewsFlow(); }); document .getElementById("zoom-results") .addEventListener("click", function () { resultHandler.zoomResults(); }); let radioButtons = document.getElementsByName("filter"); for (var i = 0; i < radioButtons.length; i++) { radioButtons[i].addEventListener("click", async (e) => { await this.calculateResults(); this.displayResults(); }); } document.addEventListener( "input", function __listener(event) { if (event.target.id == "select-areas") { if (event.target.value != 0) { let area = resultHandler.results.areasResults.find( (area) => area.ID == event.target.value ); if (resultHandler.zone === "areas") resultHandler.displayZoneResults(area); else if (resultHandler.zone === "sections") { resultHandler.refreshSections(area); resultHandler.displayZoneResults(area.Sections[0]); } } } else if (event.target.id == "select-sections") { let area = resultHandler.results.areasResults.find( (area) => area.ID == document.getElementById("select-areas").value ); let section = area.Sections.find( (section) => section.ID == event.target.value ); resultHandler.displayZoneResults(section); } }, false ); } zoomMap() { let resultHandler = this; document.getElementById("map-section").parentElement.className = "column is-full"; document.getElementById("zoom-map").addEventListener("click", function () { resultHandler.unZoom(); }); } zoomNewsFlow() { let resultHandler = this; document.getElementById("news-flow-section").parentElement.className = "column is-full"; document.getElementById("news-flow-section").style.height = "70vh"; document.getElementById("map-section").parentElement.className = "column"; document.getElementById("map-section").parentElement.style.display = "none"; document.getElementById("results-section").style.display = "none"; document .getElementById("zoom-news-flow") .addEventListener("click", function () { resultHandler.unZoom(); }); } zoomResults() { let resultHandler = this; document.getElementById("results-section").parentElement.className = "column is-full"; document.getElementById("results-section").style.height = "70vh"; document.getElementById("map-section").parentElement.className = "column"; document.getElementById("map-section").parentElement.style.display = "none"; document.getElementById("news-flow-section").style.display = "none"; document .getElementById("zoom-results") .addEventListener("click", function () { resultHandler.unZoom(); }); document.getElementById("zone-detaileds-results").style.display = "block"; } unZoom() { document.getElementById("map-section").parentElement.className = "column is-half"; document.getElementById("news-flow-section").style.height = "45vh"; document.getElementById("results-section").style.height = "25vh"; document.getElementById("news-flow-section").parentElement.className = "column is-half"; document.getElementById("map-section").parentElement.style.display = "block"; document.getElementById("results-section").style.display = "block"; document.getElementById("news-flow-section").style.display = "block"; document.getElementById("zone-detaileds-results").style.display = "none"; this.handleDom(); } async calculateResults() { this.filter = document.querySelector('input[name="filter"]:checked').value; this.results = await this.calculator.calculateResults(this.filter); } displayResults() { document.getElementById("news-flow").innerHTML = ""; if (this.zone === "areas") { this.displayFlowAreas(); this.displayAreasResults(); } else if (this.zone === "sections") { this.displayFlowSections(); this.displaySectionsResults(); } Scroller.scrollInit("news-flow"); } async displayFlowAreas() { this.results.areasResults.sort(function (a, b) { return b.DateCompletion - a.DateCompletion; }); for (let j in this.results.areasResults) { let area = this.results.areasResults[j]; if (area.status === this.filter) { document.getElementById( "news-flow" ).innerHTML += this.resultFlowTemplate(area); for (let i in area.candidateLists) { let party = await this.PartyModel.getParty( area.candidateLists[i].PartyID ); document.getElementById( "flow-content-" + area.ID ).innerHTML += await this.progressBarTemplate( area.candidateLists[i], party.Color ); } } } } async displayFlowSections() { let sections = []; this.results.areasResults.forEach((area) => { sections = sections.concat(area.Sections); }); sections.sort(function (a, b) { return b.DateCompletion - a.DateCompletion; }); for (let j in sections) { let section = sections[j]; if (section.status === this.filter) { document.getElementById( "news-flow" ).innerHTML += this.resultFlowTemplate(section); for (let i in section.candidateLists) { let party = await this.PartyModel.getParty( section.candidateLists[i].PartyID ); document.getElementById( "flow-content-" + section.ID ).innerHTML += await this.progressBarTemplate( section.candidateLists[i], party.Color ); } } } } displayRoundResults() { document.getElementById( "detailed-results" ).innerHTML = `<h5 class="title is-5">Résultats détaillés du tour</h5>`; for (let i in this.results.roundResults) { document.getElementById( "detailed-results" ).innerHTML += this.progressBarTemplate( this.results.roundResults[i], this.results.roundResults[i].Color ); } } displayAreasResults() { let selectAreas = document.getElementById("select-areas"); document.getElementById("select-sections").parentNode.style.display = "none"; for (let i = selectAreas.options.length - 1; i >= 0; i--) { selectAreas.remove(i); } this.results.areasResults.forEach((area) => { let el = document.createElement("option"); el.textContent = area.Name; el.value = area.ID; selectAreas.appendChild(el); }); this.displayZoneResults(this.results.areasResults[0]); } displaySectionsResults() { let selectAreas = document.getElementById("select-areas"); document.getElementById("select-sections").parentNode.style.display = "block"; for (let i = selectAreas.options.length - 1; i >= 0; i--) { selectAreas.remove(i); } this.results.areasResults.forEach((area) => { let el = document.createElement("option"); el.textContent = area.Name; el.value = area.ID; selectAreas.appendChild(el); }); this.refreshSections(this.results.areasResults[0]); this.displayZoneResults(this.results.areasResults[0].Sections[0]); } async displayZoneResults(zone) { if (zone.status !== this.filter) { console.log(zone); if (zone.status == "no_results") { document.getElementById( "zone-results" ).innerHTML = this.showWarningResults( "Aucun résultats n'ont étaient saisis sur cette zone" ); } else if (zone.status == "incompleted") { document.getElementById( "zone-results" ).innerHTML = this.showWarningResults( "Les résultats pour cette zone ne sont pas complets" ); } else if (zone.status == "not validated") { document.getElementById( "zone-results" ).innerHTML = this.showWarningResults( "Les résultats pour cette zone n'ont pas étaient validés" ); } document.getElementById("zone-detaileds-results").innerHTML = ""; } else { document.getElementById("zone-results").innerHTML = '<br/><h5 class="title is-5">Résultats</h5>'; for (let i in zone.candidateLists) { let party = await this.PartyModel.getParty( zone.candidateLists[i].PartyID ); document.getElementById( "zone-results" ).innerHTML += this.progressBarTemplate( zone.candidateLists[i], party.Color ); } this.displayZoneDetailedResults(zone); } } displayZoneDetailedResults(zone) { document.getElementById("zone-detaileds-results").innerHTML = '<br/><h5 class="title is-5">Statistiques</h5>'; if (this.filter === "partial") document.getElementById( "zone-detaileds-results" ).innerHTML += this.progressBarTemplate( { Name: "Pourcentage de saisie", Percentage: zone.stats.PercentageConsiderated, VoiceNumber: null, }, "grey" ); document.getElementById( "zone-detaileds-results" ).innerHTML += this.progressBarTemplate( { Name: "Abstention", Percentage: zone.stats.Abstention, VoiceNumber: null, }, "grey" ); document.getElementById( "zone-detaileds-results" ).innerHTML += this.progressBarTemplate( { Name: "Votes blancs", Percentage: zone.stats.BlankPercentage, VoiceNumber: zone.stats.BlankVoiceNumber, }, "grey" ); document.getElementById( "zone-detaileds-results" ).innerHTML += this.progressBarTemplate( { Name: "Votes nuls", Percentage: zone.stats.NullVotePercentage, VoiceNumber: zone.stats.NullVoteVoiceNumber, }, "grey" ); } refreshSections(area) { let selectSections = document.getElementById("select-sections"); selectSections.parentNode.style.display = "block"; for (let i = selectSections.options.length - 1; i >= 0; i--) { selectSections.remove(i); } for (let i in area.Sections) { let el = document.createElement("option"); el.textContent = area.Sections[i].Name; el.value = area.Sections[i].ID; selectSections.appendChild(el); } } }