Newer
Older
// Imports
import * as Auth from "/services/auth/auth.js";
import * as Common from "/services/common/common.js";
import * as Messages from "/services/messages/messages.js";
import * as AreaModel from "/services/model/area-model.js";
import * as PartyModel from "/services/model/party-model.js";
import * as CandidateListModel from "/services/model/candidateList-model.js";
import * as CandidateModel from "/services/model/candidate-model.js";
import * as ElectionModel from "/services/model/election-model.js";
import * as RoundModel from "/services/model/round-model.js";
import { Delete } from "/services/common/delete.js";
// DOM elements
export async function mount(where, parent) {
const candidateListComponent = new CandidateList(parent);
await candidateListComponent.mount(where);
return candidateListComponent;
}
class CandidateList {
constructor(parent) {
this.method = null;
this.parent = parent;
this.AreaModel = AreaModel.getAreaModel();
this.PartyModel = PartyModel.getPartyModel();
this.CandidateListModel = CandidateListModel.getCandidateListModel();
this.CandidateModel = CandidateModel.getCandidateModel();
this.ElectionModel = ElectionModel.getElectionModel();
this.RoundModel = RoundModel.getRoundModel();
this.AreaModel.current_user = await Auth.GetUser();
this.PartyModel.current_user = await Auth.GetUser();
this.CandidateListModel.current_user = await Auth.GetUser();
this.CandidateModel.current_user = await Auth.GetUser();
this.ElectionModel.current_user = await Auth.GetUser();
this.RoundModel.current_user = await Auth.GetUser();
const mountpoint = where;
document.getElementById(mountpoint).innerHTML = /* HTML */ `
<header id="dropdown-candidate-lists" class="card-header clickable">
<p id="candidate-list-title" class="card-header-title">
Liste des candidats par circonscription
<i class="fas fa-2x fa-caret-down"></i>
<div id="candidate-lists-dropdown-content" class="columns card-content">
<h5 class="title is-5">
Circonscriptions
</h5>
<div class="field">
<p class="control has-icons-right">
<input
id="area-search"
class="input"
placeholder="Rechercher une circonscription"
/>
<span class="icon is-small is-right">
<i class="fas fa-search"></i>
</span>
</p>
</div>
<nav class="level">
<div class="level-left">
<h5 class="title is-5">
Listes
</h5>
</div>
<div class="level-right">
<button
id="candidate-list-clone"
class="button large-button is-primary"
title="Importer une liste"
>
<span class="icon is-small">
<i class="fas fa-download"></i>
</span>
</button>
<button
id="candidate-list-new"
class="button large-button is-success"
title="Ajouter une liste"
>
<span class="icon is-small">
<i class="fas fa-plus"></i>
</span>
</button>
</div>
</nav>
<div class="field">
<p class="control has-icons-right">
<input
id="list-search"
class="input"
placeholder="Rechercher une liste"
/>
<span class="icon is-small is-right">
<i class="fas fa-search"></i>
</span>
</p>
</div>
<div id="candidate-lists-list"></div>
</div>
<div id="candidate-list" class="card-no-hover"></div>
this.mountModalClone("candidateList-clone-modal");
areaTemplate(area) {
return /* HTML */ `<div class="card card-list">
<div id="areas-area-${area.ID}" class="card-content clickable">
<div class="content">
<nav class="level">
<div class="level-left">
${area.Name} (Nombre de siège : ${area.SeatNumber})
</div>
</nav>
</div>
</div>
</div>`;
}
candidateListTemplate(candidateList) {
return /* HTML */ `<div class="card card-list">
<div
id="candidateLists-candidateList-${candidateList.ID}"
>
<div class="content">
<nav class="level">
<div
id="candidateLists-candidateList-desc-${candidateList.ID}"
class="level-left"
>
${candidateList.Name}
</div>
<div class="level-right">
<a
id="candidateLists-candidateList-edit-${candidateList.ID}"
class="button is-link is-small"
title="Modifier"
>
<span class="icon is-small">
<i class="fas fa-pen"></i>
</span>
</a>
<a
id="candidateLists-candidateList-delete-${candidateList.ID}"
class="button is-danger is-small"
title="Supprimer"
>
<span class="icon is-small">
<i class="fas fa-trash"></i>
</span>
</a>
</div>
</nav>
</div>
</div>
</div>`;
}
candidateListToCloneTemplate(candidateList) {
return /* HTML */ `<div class="card card-list">
<div
id="candidateLists-candidateListToClone-${candidateList.ID}"
class="card-content clickable"
>
<div class="content">
<nav class="level">
<div
id="candidateLists-candidateList-desc-${candidateList.ID}"
class="level-left"
>
${candidateList.Name}
</div>
</nav>
</div>
</div>
</div>`;
}
mountModal(where) {
const mountpoint = where;
document.getElementById(mountpoint).innerHTML = /* HTML */ `
<div class="modal-background"></div>
<div class="modal-card" id="candidateList-modal-card">
<header class="modal-card-head">
<p class="modal-card-title">Ajout/modification d'une liste</p>
<button
class="delete"
aria-label="close"
id="candidateList-modal-close"
></button>
</header>
<section class="modal-card-body">
<div class="field">
<div class="control">
<input
class="input"
id="candidateList-modal-id"
disabled
/>
</div>
</div>
<div class="field">
<label>Name</label>
<div class="control">
<input class="input" type="text" id="candidateList-modal-name" />
</div>
</div>
<div class="field">
<label>Parti</label><br />
<div class="control select">
<select name="party" id="candidateList-modal-party"></select>
</div>
</div>
</section>
<footer class="modal-card-foot">
<button id="candidateList-modal-save" class="button is-success">
Sauvegarder
</button>
<button id="candidateList-modal-cancel" class="button">
Annuler
</button>
</footer>
</div>
`;
}
mountModalClone(where) {
const mountpoint = where;
document.getElementById(mountpoint).innerHTML = /* HTML */ `
<div class="modal-background"></div>
<div class="modal-card" id="candidateList-clone-modal-card">
<header class="modal-card-head">
<p class="modal-card-title">Importer une liste</p>
<button
class="delete"
aria-label="close"
id="candidateList-clone-modal-close"
></button>
</header>
<section id="candidateLists-toclone" class="modal-card-body"></section>
</div>
`;
}
async displayCandidates() {
document.getElementById("candidate-list").innerHTML = /* HTML */ `<div
class="table-container"
>
<table class="table is-bordered is-narrow is-fullwidth">
<thead>
<tr class="is-selected">
<th hidden>Id</th>
<th>Nom complet</th>
<th>Rang</th>
<th>Conseiller communautaire</th>
<th>Date de naissance</th>
<th>Incompatibilité potentielle</th>
<th>Refusé</th>
<th>Supprimé</th>
<th>Actions</th>
</tr>
</thead>
<tbody id="candidates"></tbody>
</table>
</div> `;
let candidates = await this.updateCandidates();
candidates.sort(function (a, b) {
return a.Rank > b.Rank;
});
const markup = candidates
.map((candidate) => this.candidateTemplate(candidate))
.join("");
document.getElementById("candidates").innerHTML = markup;
let newRank = 1;
candidates.forEach((candidate) => {
if (candidate.Rank >= newRank) newRank = candidate.Rank + 1;
});
CommunityCounseller: false,
Birthdate: "2000-01-01",
PotentialIncompatibility: false,
Refused: false,
Removed: false,
};
document.getElementById("candidates").innerHTML += this.candidateTemplate(
);
document
.getElementById(`candidates-candidate-edit-0`)
.addEventListener("click", function () {
candidateListHandler.method = "POST";
candidateListHandler.saveCandidate(newCandidate.ID);
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
});
document.getElementById(`candidates-candidate-delete-0`).remove();
let candidateListHandler = this;
candidates.map((candidate) => {
document
.getElementById(`candidates-candidate-edit-${candidate.ID}`)
.addEventListener("click", function () {
candidateListHandler.method = "PUT";
candidateListHandler.saveCandidate(candidate.ID);
});
document
.getElementById(`candidates-candidate-delete-${candidate.ID}`)
.addEventListener("click", function () {
new Delete(() => {
candidateListHandler.deleteCandidate(candidate);
});
});
});
}
candidateTemplate(candidate) {
return /* HTML */ `
<tr id="candidates-candidate-${candidate.ID}">
<td hidden>
<input
class="input"
type="number"
id="${candidate.ID}-candidate-id"
value="${candidate.ID}"
disabled
/>
</td>
<td>
<input
class="input"
type="text"
id="${candidate.ID}-candidate-fullname"
value="${candidate.FullName}"
/>
</td>
<td>
<input
class="input"
type="number"
id="${candidate.ID}-candidate-rank"
value="${candidate.Rank}"
/>
</td>
<td>
<input
type="checkbox"
id="${candidate.ID}-candidate-community-counseller"
${candidate.CommunityCounseller ? "checked" : ""}
/>
</td>
<td>
<input
class="input"
type="date"
id="${candidate.ID}-candidate-birthdate"
value="${candidate.Birthdate}"
/>
</td>
<td>
<input
type="checkbox"
id="${candidate.ID}-candidate-potential-incompatibility"
${candidate.PotentialIncompatibility ? "checked" : ""}
/>
</td>
<td>
<input
type="checkbox"
id="${candidate.ID}-candidate-refused"
${candidate.Refused ? "checked" : ""}
/>
</td>
<td>
<input
type="checkbox"
id="${candidate.ID}-candidate-removed"
${candidate.Removed ? "checked" : ""}
/>
</td>
<td>
<a
id="candidates-candidate-edit-${candidate.ID}"
class="button is-success is-small"
>
<span class="icon is-small">
<i class="fas fa-check"></i>
</span>
</a>
<a
id="candidates-candidate-delete-${candidate.ID}"
class="button is-danger is-small"
<i class="fas fa-trash"></i>
</span>
</a>
</td>
</tr>
`;
}
handleDom() {
let candidateListHandler = this;
document
.getElementById(`candidate-list-new`)
.addEventListener("click", function () {
candidateListHandler.newCandidateList();
});
document
.getElementById(`candidate-list-clone`)
.addEventListener("click", function () {
candidateListHandler.cloneCandidateListModal();
});
document
.getElementById(`candidateList-modal-close`)
.addEventListener("click", function () {
Common.toggleModal("candidateList-modal", "candidateList-modal-card");
});
document
.getElementById(`candidateList-modal-cancel`)
.addEventListener("click", function () {
Common.toggleModal("candidateList-modal", "candidateList-modal-card");
});
document
.getElementById(`candidateList-clone-modal-close`)
.addEventListener("click", function () {
Common.toggleModal(
"candidateList-clone-modal",
"candidateList-clone-modal-card"
);
});
document
.getElementById(`candidateList-modal-save`)
.addEventListener("click", async function () {
if (
document.getElementById("candidateList-modal-party").value === "0"
) {
Messages.Show("is-danger", "Veuillez sélectionner un parti.");
return;
}
await candidateListHandler.saveCandidateList();
});
document.getElementById("area-search").addEventListener("keyup", (e) => {
this.displayAreas();
});
document.getElementById("list-search").addEventListener("keyup", (e) => {
this.displayCandidateLists();
});
document.getElementById("areas-round").innerHTML = /* HTML */ ``;
let candidateListHandler = this;
let areas = await this.updateAreas();
const markup = areas.map((area) => this.areaTemplate(area)).join("");
document.getElementById("areas-round").innerHTML += markup;
areas.map((area) => {
document
.getElementById(`areas-area-${area.ID}`)
.addEventListener("click", async function () {
await candidateListHandler.activateArea(area);
await candidateListHandler.displayCandidateLists();
});
});
}
async updateAreas() {
let candidateListHandler = this;
let areas = await this.AreaModel.getAreas();
return area.ElectionID == candidateListHandler.round.ElectionID;
});
return areas.filter((area) =>
area.Name.toLowerCase().includes(
document.getElementById("area-search").value.toLowerCase()
)
);
async activateArea(areaToActivate) {
this.area = areaToActivate;
let areas = await this.updateAreas();
areas.forEach((area) => {
document
.getElementById(`areas-area-${area.ID}`)
.classList.remove("active-card");
});
document
.getElementById(`areas-area-${areaToActivate.ID}`)
.classList.add("active-card");
}
async activateCandidateList(candidateListToActivate) {
this.candidateList = candidateListToActivate;
let candidateLists = await this.updateCandidateLists();
candidateLists.forEach((candidateList) => {
document
.getElementById(`candidateLists-candidateList-${candidateList.ID}`)
.classList.remove("active-card");
});
document
.getElementById(
`candidateLists-candidateList-${candidateListToActivate.ID}`
)
async displayCandidateLists() {
let candidateListHandler = this;
let candidateLists = await this.updateCandidateLists();
document.getElementById("candidate-lists-list").innerHTML = /* HTML */ ``;
const markup = candidateLists
.map((candidateList) => this.candidateListTemplate(candidateList))
.join("");
document.getElementById("candidate-lists-list").innerHTML += markup;
candidateLists.map(async (candidateList) => {
let party = await this.PartyModel.getParty(candidateList.PartyID);
document.getElementById(
`candidateLists-candidateList-desc-${candidateList.ID}`
).innerHTML += "(" + party.Name + ")";
document
.getElementById(`candidateLists-candidateList-edit-${candidateList.ID}`)
.addEventListener("click", function () {
candidateListHandler.editCandidateList(candidateList);
});
document
.getElementById(
`candidateLists-candidateList-delete-${candidateList.ID}`
)
.addEventListener("click", function () {
new Delete(() => {
candidateListHandler.deleteCandidateList(candidateList);
});
});
document
.getElementById(`candidateLists-candidateList-${candidateList.ID}`)
.addEventListener("click", async function () {
await candidateListHandler.activateCandidateList(candidateList);
await candidateListHandler.displayCandidates();
});
document.getElementById(`candidate-list-new`).removeAttribute("disabled");
document.getElementById(`candidate-list-clone`).removeAttribute("disabled");
}
async updateCandidateLists() {
let candidateListHandler = this;
let candidateLists = await this.CandidateListModel.getCandidateLists();
candidateLists = candidateLists.filter(function (candidateList) {
return (
candidateList.AreaID == candidateListHandler.area.ID &&
candidateList.RoundID == candidateListHandler.round.ID
);
return candidateLists.filter((candidateList) =>
candidateList.Name.toLowerCase().includes(
document.getElementById("list-search").value.toLowerCase()
)
);
async updateCandidates() {
let candidateListHandler = this;
let candidates = await this.CandidateModel.getCandidates();
return candidates.filter(function (candidate) {
return candidate.CandidateListID == candidateListHandler.candidateList.ID;
});
}
async newCandidateList() {
this.method = "POST";
await this.refreshParties();
document.getElementById("candidateList-modal-id").value = null;
document.getElementById("candidateList-modal-party").value = null;
document.getElementById("candidateList-modal-name").value = null;
Common.toggleModal("candidateList-modal", "candidateList-modal-card");
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
async cloneCandidateListModal() {
let election = await this.ElectionModel.getElection(this.area.ID);
let rounds = await this.RoundModel.getRounds();
rounds = rounds.filter((round) => round.ElectionID == election.ID);
let roundsID = [];
rounds.forEach((round) => {
if (this.round.ID !== round.ID) roundsID.push(round.ID);
});
let candidateLists = await this.CandidateListModel.getCandidateLists();
candidateLists = candidateLists.filter(
(candidateList) =>
candidateList.AreaID == this.area.ID &&
roundsID.includes(candidateList.RoundID)
);
Common.toggleModal(
"candidateList-clone-modal",
"candidateList-clone-modal-card"
);
const markup = candidateLists
.map((candidateList) => this.candidateListToCloneTemplate(candidateList))
.join("");
document.getElementById("candidateLists-toclone").innerHTML = markup;
candidateLists.map((candidateList) => {
document
.getElementById(
`candidateLists-candidateListToClone-${candidateList.ID}`
)
.addEventListener("click", async () => {
this.cloneCandidateList(candidateList);
Common.toggleModal(
"candidateList-clone-modal",
"candidateList-clone-modal-card"
);
});
});
}
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
async editCandidateList(candidateList) {
this.method = "PUT";
await this.refreshParties();
document.getElementById("candidateList-modal-id").value = candidateList.ID;
document.getElementById("candidateList-modal-party").value =
candidateList.PartyID;
document.getElementById("candidateList-modal-name").value =
candidateList.Name;
Common.toggleModal("candidateList-modal", "candidateList-modal-card");
}
async refreshParties() {
let selectParties = document.getElementById("candidateList-modal-party");
let parties = await this.PartyModel.getParties();
for (let i = selectParties.options.length - 1; i >= 0; i--) {
selectParties.remove(i);
}
let el = document.createElement("option");
el.textContent = "Veuillez sélectionner un parti";
el.value = 0;
selectParties.appendChild(el);
parties.forEach((party) => {
el = document.createElement("option");
el.textContent = party.Name;
el.value = party.ID;
selectParties.appendChild(el);
});
}
async saveCandidateList() {
if (this.method == "POST")
document.getElementById("candidateList-modal-id").value = null;
if (
this.CandidateListModel.checkInputs(
this.method,
parseInt(document.getElementById("candidateList-modal-id").value),
document.getElementById("candidateList-modal-name").value,
parseInt(document.getElementById("candidateList-modal-party").value)
)
) {
let candidateList = await this.CandidateListModel.saveCandidateList(
this.method,
parseInt(document.getElementById("candidateList-modal-id").value),
document.getElementById("candidateList-modal-name").value,
parseInt(document.getElementById("candidateList-modal-party").value),
this.round.ID,
this.area.ID
);
await this.displayCandidateLists();
Common.toggleModal("candidateList-modal", "candidateList-modal-card");
this.activateCandidateList(candidateList);
return candidateList;
}
async deleteCandidateList(candidateList) {
await this.CandidateListModel.deleteCandidateList(candidateList.ID);
await this.displayCandidateLists();
this.emptyCandidate();
this.displayCandidateLists();
}
async saveCandidate(candidateID) {
let candidate = await this.CandidateModel.saveCandidate(
this.method,
candidateID,
this.candidateList.ID,
document.getElementById(candidateID + "-candidate-fullname").value,
parseInt(document.getElementById(candidateID + "-candidate-rank").value),
document.getElementById(candidateID + "-candidate-community-counseller")
.checked,
document.getElementById(candidateID + "-candidate-birthdate").value,
document.getElementById(
candidateID + "-candidate-potential-incompatibility"
).checked,
document.getElementById(candidateID + "-candidate-refused").checked,
document.getElementById(candidateID + "-candidate-removed").checked
);
await this.displayCandidates();
return candidate;
}
async deleteCandidate(candidate) {
await this.CandidateModel.deleteCandidate(candidate.ID);
await this.displayCandidates();
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
async cloneCandidateList(candidateList) {
console.log(candidateList);
let candidateListCloned = await this.CandidateListModel.saveCandidateList(
"POST",
null,
candidateList.Name,
candidateList.PartyID,
this.round.ID,
this.area.ID
);
for (let i in candidateList.Candidates) {
await this.CandidateModel.saveCandidate(
"POST",
null,
candidateListCloned.ID,
candidateList.Candidates[i].FullName,
candidateList.Candidates[i].Rank,
candidateList.Candidates[i].CommunityCounseller,
candidateList.Candidates[i].Birthdate,
candidateList.Candidates[i].PotentialIncompatibility,
candidateList.Candidates[i].Refused,
candidateList.Candidates[i].Removed
);
}
await this.displayCandidateLists();
this.activateCandidateList(candidateListCloned);
return candidateListCloned;
}
emptyCandidateList() {
this.area = null;
document.getElementById("candidate-lists-list").innerHTML = "";
document
.getElementById(`candidate-list-new`)
.setAttribute("disabled", "true");
document
.getElementById(`candidate-list-clone`)
.setAttribute("disabled", "true");
this.candidateList = null;
document.getElementById("candidate-list").innerHTML = "";
}