[Client] Improve traits management admin page
- Fix HTML, improve style of the feature and add its dedicated CSS file; - Improve admin traits' JavaScript and fix addition of a trait where there is no one already present; - Remove unneeded admin.js file, as all its functions have been improved and split into separate files.
This commit is contained in:
parent
0707dce218
commit
68c62b5e03
17
truthinquiry/static/css/admin_ui_traits.css
Normal file
17
truthinquiry/static/css/admin_ui_traits.css
Normal file
@ -0,0 +1,17 @@
|
||||
.delete_trait_btn, #add_trait, #save_changes {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.trait_description_container, .trait_name_container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.trait_description_input, .trait_name_input {
|
||||
width: 30em;
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
//functions for places.html
|
||||
|
||||
function addInputPlaces(){
|
||||
let newPlace = places.lastElementChild.cloneNode(true);
|
||||
newPlace.id = "";
|
||||
newPlace.querySelector("input").value = "";
|
||||
places.appendChild(newPlace);
|
||||
}
|
||||
|
||||
function deleteInputPlaces(buttonNode){
|
||||
let placeNode = buttonNode.parentNode;
|
||||
placeNode.parentNode.removeChild(placeNode);
|
||||
}
|
||||
|
||||
function saveFormPlaces(){
|
||||
let data = [];
|
||||
for(let section of places.querySelectorAll("section")){
|
||||
let place = {};
|
||||
place["id"] = section.id
|
||||
place["name"] = section.querySelector("input").value
|
||||
data.push(place);
|
||||
}
|
||||
makeAPIRequest("admin/setPlaces", {"places": data, "lang": "FR"}, {"content": "json"})
|
||||
}
|
||||
|
||||
|
||||
//functions for traits.html
|
||||
|
||||
|
||||
function addInputTraits(){
|
||||
let newTrait = traits.lastElementChild.cloneNode(true);
|
||||
newTrait.id = "";
|
||||
newTrait.querySelector(".name_input").value = "";
|
||||
newTrait.querySelector(".desc_input").value = "";
|
||||
traits.appendChild(newTrait);
|
||||
}
|
||||
|
||||
function deleteInputTraits(buttonNode){
|
||||
let traitNode = buttonNode.parentNode;
|
||||
traitNode.parentNode.removeChild(traitNode);
|
||||
}
|
||||
|
||||
function saveFormTraits(){
|
||||
let data = [];
|
||||
for(let section of traits.querySelectorAll("section")){
|
||||
let trait = {};
|
||||
trait["id"] = section.id
|
||||
trait["name"] = section.querySelector(".name_input").value
|
||||
trait["desc"] = section.querySelector(".desc_input").value
|
||||
data.push(trait);
|
||||
}
|
||||
makeAPIRequest("admin/setTraits", {"traits": data, "lang": "FR"}, {"content": "json"})
|
||||
}
|
127
truthinquiry/static/js/admin_traits.js
Normal file
127
truthinquiry/static/js/admin_traits.js
Normal file
@ -0,0 +1,127 @@
|
||||
function addTrait() {
|
||||
const traitElement = document.createElement("div");
|
||||
traitElement.classList.add("trait");
|
||||
traitElement.setAttribute("data-id", "");
|
||||
|
||||
const traitNameContainerElement = document.createElement("div");
|
||||
traitNameContainerElement.classList.add("trait_name_container");
|
||||
|
||||
const traitNameTitleElement = document.createElement("h3");
|
||||
traitNameTitleElement.classList.add("trait_name");
|
||||
traitNameTitleElement.appendChild(document.createTextNode("Nom de la réaction\u00A0:"));
|
||||
|
||||
traitNameContainerElement.appendChild(traitNameTitleElement);
|
||||
|
||||
const traitNameInputElement = document.createElement("input");
|
||||
traitNameInputElement.classList.add("trait_name_input");
|
||||
traitNameInputElement.setAttribute("type", "text");
|
||||
traitNameInputElement.setAttribute("value", "");
|
||||
|
||||
traitNameContainerElement.appendChild(traitNameInputElement);
|
||||
|
||||
traitElement.appendChild(traitNameContainerElement);
|
||||
|
||||
const traitDescriptionElement = document.createElement("div");
|
||||
traitDescriptionElement.classList.add("trait_description_container");
|
||||
|
||||
const traitDescriptionTitleElement = document.createElement("h3");
|
||||
traitDescriptionTitleElement.classList.add("trait_description");
|
||||
traitDescriptionTitleElement.appendChild(document.createTextNode("Description de la réaction\u00A0:"));
|
||||
|
||||
traitDescriptionElement.appendChild(traitDescriptionTitleElement);
|
||||
|
||||
const traitDescriptionInputElement = document.createElement("input");
|
||||
traitDescriptionInputElement.classList.add("trait_description_input");
|
||||
traitDescriptionInputElement.setAttribute("type", "text");
|
||||
traitDescriptionInputElement.setAttribute("value", "");
|
||||
|
||||
traitDescriptionElement.appendChild(traitDescriptionInputElement);
|
||||
|
||||
traitElement.appendChild(traitDescriptionElement);
|
||||
|
||||
const buttonElement = document.createElement("button");
|
||||
buttonElement.classList.add("delete_trait_btn", "action_button", "short_color_transition");
|
||||
buttonElement.setAttribute("title", "Cliquez ici pour supprimer cette réaction");
|
||||
|
||||
const svgElement = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
||||
svgElement.classList.add("action_icon", "short_color_transition");
|
||||
svgElement.setAttribute("viewBox", "0 0 48 48");
|
||||
|
||||
const pathElement = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
||||
pathElement.setAttribute("d",
|
||||
"M12.45 38.7 9.3 35.55 20.85 24 9.3 12.5l3.15-3.2L24 20.8 35.55 9.3l3.15 3.2L27.2 24l11.5 11.55-3.15 3.15L24 27.2Z");
|
||||
|
||||
svgElement.appendChild(pathElement);
|
||||
|
||||
buttonElement.appendChild(svgElement);
|
||||
buttonElement.appendChild(document.createTextNode("Supprimer la réaction"));
|
||||
buttonElement.addEventListener("click", () => deleteTrait(buttonElement));
|
||||
|
||||
traitElement.appendChild(buttonElement);
|
||||
|
||||
const traitsElement = document.getElementById("traits");
|
||||
if (traitsElement === null) {
|
||||
// No places element, this should never happen
|
||||
// Do nothing in this case
|
||||
return;
|
||||
}
|
||||
|
||||
traitsElement.appendChild(traitElement);
|
||||
}
|
||||
|
||||
function deleteTrait(traitDeletionButton) {
|
||||
if (!confirm("Voulez-vous vraiement supprimer cette réaction ?")) {
|
||||
return;
|
||||
}
|
||||
|
||||
const traitNode = traitDeletionButton.parentNode;
|
||||
traitNode.parentNode.removeChild(traitNode);
|
||||
}
|
||||
|
||||
function saveChanges() {
|
||||
const data = [];
|
||||
|
||||
for (const traitElement of document.getElementsByClassName("trait")) {
|
||||
const trait = {};
|
||||
trait["id"] = traitElement.getAttribute("data-id");
|
||||
trait["name"] = traitElement.querySelector(".trait_name_input").value;
|
||||
trait["desc"] = traitElement.querySelector(".trait_description_input").value;
|
||||
data.push(trait);
|
||||
}
|
||||
|
||||
makeAPIRequest("admin/setTraits", {"traits": data, "lang": "FR"}, {"content": "json"}).then(() => {
|
||||
alert("Opération effectuée avec succès");
|
||||
});
|
||||
}
|
||||
|
||||
function setListenersToTraitDeletionButtons() {
|
||||
for (const deleteTraitButton of document.getElementsByClassName("delete_trait_btn")) {
|
||||
deleteTraitButton.addEventListener("click", () => deleteTrait(deleteTraitButton));
|
||||
};
|
||||
}
|
||||
|
||||
function setListenersToTraitAdditionButton() {
|
||||
const addTraitButton = document.getElementById("add_trait");
|
||||
if (addTraitButton === null) {
|
||||
// There is no add_place button, this should never happen
|
||||
// Do nothing in this case
|
||||
return;
|
||||
}
|
||||
|
||||
addTraitButton.addEventListener("click", addTrait);
|
||||
}
|
||||
|
||||
function setListenersToSaveChangesButton() {
|
||||
const saveChangesButton = document.getElementById("save_changes");
|
||||
if (saveChangesButton === null) {
|
||||
// There is no save_changes button, this should never happen
|
||||
// Do nothing in this case
|
||||
return;
|
||||
}
|
||||
|
||||
saveChangesButton.addEventListener("click", saveChanges);
|
||||
}
|
||||
|
||||
setListenersToTraitDeletionButtons();
|
||||
setListenersToTraitAdditionButton();
|
||||
setListenersToSaveChangesButton();
|
@ -1,29 +1,71 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<title>Traits</title>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" href="admin_ui.css">
|
||||
<script src="/static/js/api.js"></script>
|
||||
<script src="/static/js/admin.js"></script>
|
||||
<title>Truth Inquiry - Gestion des réactions</title>
|
||||
<link rel="stylesheet" href="/static/css/admin_ui.css">
|
||||
<link rel="stylesheet" href="/static/css/admin_ui_traits.css">
|
||||
<link rel="icon" href="/static/images/favicon/favicon_32.png" type="image/png" sizes="32x32">
|
||||
<link rel="icon" href="/static/images/favicon/favicon_64.png" type="image/png" sizes="64x64">
|
||||
<link rel="icon" href="/static/images/favicon/favicon_96.png" type="image/png" sizes="96x96">
|
||||
<link rel="icon" href="/static/images/favicon/favicon_128.png" type="image/png" sizes="128x128">
|
||||
<link rel="icon" href="/static/images/favicon/favicon_192.png" type="image/png" sizes="192x192">
|
||||
<link rel="icon" href="/static/images/favicon/favicon_256.png" type="image/png" sizes="256x256">
|
||||
<link rel="icon" href="/static/images/favicon/favicon_256.png" type="image/png" sizes="512x512">
|
||||
<meta name="color-scheme" content="dark light">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
</head>
|
||||
<body>
|
||||
<a href="/admin"> go Back </a> <br>
|
||||
|
||||
<section id="traits">
|
||||
<header>
|
||||
<a class="short_color_transition" href="/admin" title="Cliquez ici pour revenir à l'accueil de l'interface d'administration du jeu">Accueil</a>
|
||||
<a class="short_color_transition" href="/admin/questions" title="Cliquez ici pour gérer les questions du jeu">Gestion des questions</a>
|
||||
<a class="short_color_transition" href="/admin/places" title="Cliquez ici pour gérer les lieux du jeu">Gestion des lieux</a>
|
||||
<a class="short_color_transition" href="/admin/traits" title="Cliquez ici pour gérer les réactions du jeu">Gestion des réactions</a>
|
||||
<a class="short_color_transition" href="/api/v1/admin/logout" title="Cliquez ici pour vous déconnecter de l'interface d'administration du jeu">Déconnexion</a>
|
||||
</header>
|
||||
<h1 class="page_title">Truth Inquiry - Interface d'administration</h1>
|
||||
<h2 class="page_category">Gestion des réactions</h2>
|
||||
<p class="page_description">Cliquez sur les champs pour éditer les informations. Les images des émotions sont disponibles par personnage dans leur page de gestion dédiée.</p>
|
||||
<div id="traits">
|
||||
{%for trait in traits%}
|
||||
<section id="{{trait['id']}}">
|
||||
<p> Name: </p>
|
||||
<input class="name_input" value="{{trait['name']}}">
|
||||
<p> Description: </p>
|
||||
<input class="desc_input" value="{{trait['desc']}}">
|
||||
<button onclick="deleteInputTraits(this)">Delete trait</button>
|
||||
</section>
|
||||
<div data-id="{{trait['id']}}" class="trait">
|
||||
<div class="trait_name_container">
|
||||
<h3 class="trait_name">Nom de la réaction :</h3>
|
||||
<input type="text" class="trait_name_input" value="{{trait['name']}}">
|
||||
</div>
|
||||
<div class="trait_description_container">
|
||||
<h3 class="trait_description">Description de la réaction :</h3>
|
||||
<input type="text" class="trait_description_input" value="{{trait['desc']}}">
|
||||
</div>
|
||||
<button class="delete_trait_btn action_button short_color_transition">
|
||||
<svg class="action_icon short_color_transition" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 48 48">
|
||||
<path d="M12.45 38.7 9.3 35.55 20.85 24 9.3 12.5l3.15-3.2L24 20.8 35.55 9.3l3.15 3.2L27.2 24l11.5 11.55-3.15 3.15L24 27.2Z"/>
|
||||
</svg>
|
||||
Supprimer la réaction
|
||||
</button>
|
||||
</div>
|
||||
{%endfor%}
|
||||
</section>
|
||||
<button onclick="addInputTraits()">Add new</button>
|
||||
<button onclick="saveFormTraits()">Save changes</button>
|
||||
|
||||
<p>Images are viewable in the npc views</p>
|
||||
</div>
|
||||
<button id="add_trait" class="action_button short_color_transition">
|
||||
<svg class="action_icon short_color_transition" xmlns="http://www.w3.org/2000/svg" viewBox="0 96 960 960">
|
||||
<path d="M435 871V622H185v-91h250V281h91v250h250v91H526v249h-91Z"/>
|
||||
</svg>
|
||||
Ajouter une nouvelle réaction
|
||||
</button>
|
||||
<button id="save_changes" class="action_button short_color_transition">
|
||||
<svg class="action_icon short_color_transition" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 48 48">
|
||||
<path d="M18.9 36.75 6.65 24.5l3.3-3.3 8.95 9L38 11.1l3.3 3.25Z"/>
|
||||
</svg>
|
||||
Sauvegarder les changements
|
||||
</button>
|
||||
<noscript>
|
||||
<div class="alert_dialog_background"></div>
|
||||
<dialog>
|
||||
<h3 class="alert_dialog_title">JavaScript nécessaire</h3>
|
||||
<p class="alert_dialog_msg unsupported_browser_msg">Désolé, mais JavaScript est nécessaire pour faire fonctionner cette page. Veuillez l'activer dans votre navigateur ou en utiliser un qui le supporte afin de pouvoir gérer les émotions.</p>
|
||||
</dialog>
|
||||
</noscript>
|
||||
<script src="/static/js/api.js"></script>
|
||||
<script src="/static/js/admin_traits.js"></script>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user