diff --git a/truthinquiry/static/css/admin_ui.css b/truthinquiry/static/css/admin_ui.css index db69d63..9edba05 100644 --- a/truthinquiry/static/css/admin_ui.css +++ b/truthinquiry/static/css/admin_ui.css @@ -9,10 +9,12 @@ } :root { + --admin-black-color: #000000; --admin-grey-color: #5A5656; --admin-red-color: #FF0000; --admin-white-color: #FFFFFF; - --adming-yellow-color: #FFC800; + --adming-yellow-color: #D6A851; + --alert-dialog-background-color: #000000DF; --body-margin: 0.375em; font-family: "Roboto Mono", sans-serif; } @@ -25,6 +27,15 @@ a, body { color: var(--admin-white-color); } +a:focus, a:hover { + background-color: var(--admin-white-color); + color: var(--admin-grey-color) !important; +} + +a:focus > .action_icon, .action_button:focus > .action_icon, a:hover > .action_icon, .action_button:hover > .action_icon { + fill: var(--admin-grey-color); +} + a:visited { color: unset; } @@ -33,9 +44,24 @@ body { margin: var(--body-margin); } -button, input { +button { + align-items: center; + border-radius: 1em; + cursor: pointer; + display: flex; + justify-content: center; +} + +button, input, select { + background-color: transparent; + border-color: var(--admin-white-color); + border-style: solid; + border-width: 0.125em; + color: var(--admin-white-color); font-family: "Roboto Mono", sans-serif; font-size: 1em; + margin: 1em; + padding: 0.25em; } header { @@ -56,20 +82,74 @@ header a { text-decoration: none; } -header a:hover { - background-color: var(--admin-white-color); - color: var(--admin-grey-color); -} - html { background-color: var(--admin-grey-color); margin: 0; } +noscript dialog { + align-items: center; + background-color: var(--admin-grey-color); + border-color: var(--admin-white-color); + border-radius: 1em; + display: flex; + flex-direction: column; + flex-wrap: nowrap; + justify-content: center; + left: 50%; + overflow: auto; + padding: 2em; + position: fixed; + text-align: center; + top: 50%; + transform: translate(-50%, -50%); + z-index: 2; +} + svg { fill: var(--admin-white-color); } +.action_button:focus, .action_button:hover { + background-color: var(--admin-white-color); + color: var(--admin-grey-color); +} + +.action_icon { + height: 2em; + transition-property: fill !important; + width: 2em; +} + +.alert_dialog_background { + background-color: var(--alert-dialog-background-color); + display: block; + height: 100vh; + left: 0; + position: fixed; + top: 0; + width: 100vw; + z-index: 1; +} + +.alert_dialog_bottom_link { + font-size: 1.125em; + padding: 0.25em; + text-decoration: underline; +} + +.alert_dialog_msg { + font-size: 1.25em; +} + +.alert_dialog_msg, .alert_dialog_title { + margin: 1em; +} + +.alert_dialog_title { + font-size: 1.75em; +} + .page_category { font-size: 2em; } @@ -102,30 +182,3 @@ svg { transition-duration: 0.25s; transition-timing-function: linear; } - -#places>section { - border: thin solid red; - padding: 5px; - margin-top: 20px; -} - -#section>input{ - width: 100%; -} - -.questionTypeTag{ - border: thin solid red; - margin-top: 20px; -} -.questionTypeTag input{ - width: 100%; -} - -.questionType{ - border: thin solid red; - margin-top: 20px; -} -.question input{ - width: 100%; - margin: 10px; -} diff --git a/truthinquiry/static/css/admin_ui_home.css b/truthinquiry/static/css/admin_ui_home.css index 24d3dec..427e1c7 100644 --- a/truthinquiry/static/css/admin_ui_home.css +++ b/truthinquiry/static/css/admin_ui_home.css @@ -1,13 +1,3 @@ -.add_npc_icon { - height: 2em; - transition-property: fill; - width: 2em; -} - -.add_npc_icon:hover { - transition-property: fill; -} - .add_npc_link { align-items: center; border-color: var(--admin-white-color); @@ -24,26 +14,22 @@ padding: 0.25em; } -.add_npc_link:hover { - background-color: var(--admin-white-color); - color: var(--admin-grey-color); -} - -.add_npc_link:hover > .add_npc_icon { - fill: var(--admin-grey-color); -} - .character_item { font-size: 1.5em; list-style-type: none; - margin: 1em; + margin: 0.5em; } .character_item a { + padding: 0.25em; text-decoration: underline; text-decoration-color: var(--admin-white-color); } +.character_item a:hover { + text-decoration-color: var(--admin-grey-color); +} + .character_list { align-content: center; align-items: center; diff --git a/truthinquiry/static/css/admin_ui_login.css b/truthinquiry/static/css/admin_ui_login.css index 1bd1fd0..191cac5 100644 --- a/truthinquiry/static/css/admin_ui_login.css +++ b/truthinquiry/static/css/admin_ui_login.css @@ -31,3 +31,9 @@ input { flex-direction: row; justify-content: center; } + +#login_input_button { + cursor: pointer; + border-radius: 1em; + padding: 0.25em; +} diff --git a/truthinquiry/static/css/admin_ui_npc.css b/truthinquiry/static/css/admin_ui_npc.css index b20e796..25a8b78 100644 --- a/truthinquiry/static/css/admin_ui_npc.css +++ b/truthinquiry/static/css/admin_ui_npc.css @@ -1,55 +1,36 @@ -button { - display: flex; +img[alt] { + font-size: 1em; } -button, input { - background-color: transparent; - border-color: var(--admin-white-color); - border-style: solid; - border-width: 0.125em; - color: var(--admin-white-color); - margin: 1em; - padding: 0.25em; +img[alt], .info_item, .section_title { + text-align: center; } input[type="text"] { width: 20em; } -.action_buttons, .answer_groups { - align-content: center; - display: flex; - flex-wrap: wrap; - justify-content: center; -} - -.action_button { - align-items: center; - border-radius: 1em; - cursor: pointer; - display: flex; - flex-direction: row; - justify-content: center; - padding: 0.25em; -} - -.action_button:hover { +option { background-color: var(--admin-white-color); - color: var(--admin-grey-color); + color: var(--admin-black-color); } -.action_button:hover > .action_icon { - fill: var(--admin-grey-color); +.action_buttons, .answer_groups, .reaction, #add_reactions { + flex-wrap: wrap; } -.action_icon { - height: 2em; - transition-property: fill; - width: 2em; +.action_buttons, .answer_group, .answer_groups, .reaction, #add_reactions { + display: flex; + justify-content: center; } -.character_image { - width: 15em; +.answer_group, .reaction, #add_reactions { + align-items: center; + flex-direction: column; +} + +.character_image, .reaction_image { + width: 20em; } .character_image, #npc_name { @@ -65,8 +46,8 @@ input[type="text"] { font-size: 1.25em; } -.info_item, .section_title { - text-align: center; +.reaction, #add_reactions { + align-content: center; } .section_title { diff --git a/truthinquiry/static/css/admin_ui_places.css b/truthinquiry/static/css/admin_ui_places.css new file mode 100644 index 0000000..1b6d55a --- /dev/null +++ b/truthinquiry/static/css/admin_ui_places.css @@ -0,0 +1,16 @@ +.place { + align-content: center; + align-items: center; + display: flex; + flex-wrap: wrap; + justify-content: center; +} + +.place_input { + flex-grow: 1; +} + +#add_place, #save_changes { + margin-left: auto; + margin-right: auto; +} diff --git a/truthinquiry/static/css/admin_ui_questions.css b/truthinquiry/static/css/admin_ui_questions.css new file mode 100644 index 0000000..9e8da1d --- /dev/null +++ b/truthinquiry/static/css/admin_ui_questions.css @@ -0,0 +1,32 @@ +.add_question_btn, #save_changes { + margin-left: auto; + margin-right: auto; +} + +.delete_question_btn, .question_input { + margin: 1em; +} + +.question { + align-content: center; + align-items: center; + display: flex; + flex-wrap: wrap; + justify-content: center; +} + +.question_input { + flex-grow: 1; +} + +.question_type { + border-color: var(--admin-white-color); + border-radius: 1em; + border-style: solid; + margin: 1em; +} + +.question_type_title { + font-size: 1.5em; + text-align: center; +} diff --git a/truthinquiry/static/css/admin_ui_traits.css b/truthinquiry/static/css/admin_ui_traits.css new file mode 100644 index 0000000..9e98772 --- /dev/null +++ b/truthinquiry/static/css/admin_ui_traits.css @@ -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; +} diff --git a/truthinquiry/static/js/admin.js b/truthinquiry/static/js/admin.js deleted file mode 100644 index e452a1f..0000000 --- a/truthinquiry/static/js/admin.js +++ /dev/null @@ -1,89 +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"}) -} - - - -//functions for questions.html - - - - -function addInputQuestions(button){ - let questionTypeContent = button.parentNode.querySelector(".questionTypeContent"); - let newQuestion = questionTypeContent.querySelector(".question").cloneNode(true); - newQuestion.id = ""; - newQuestion.querySelector("input").value = ""; - questionTypeContent.appendChild(newQuestion); -} - -function deleteInputQuestions(buttonNode){ - let placeNode = buttonNode.parentNode; - placeNode.parentNode.removeChild(placeNode); -} - -function saveFormQuestions(){ - let data = []; - - for(let questionTypeNode of allQuestions.querySelectorAll(".questionType")){ - let questionsJson = []; - let questionTypeJson = {"questions": questionsJson}; - data.push(questionTypeJson); - - for(let questionNode of questionTypeNode.querySelectorAll("input")){ - questionsJson.push({"text": questionNode.value}) - } - } - - makeAPIRequest("admin/setQuestions", {"questions": data, "lang": "FR"}, {"content": "json"}) -} diff --git a/truthinquiry/static/js/admin_npc.js b/truthinquiry/static/js/admin_npc.js index b495208..eede6a8 100644 --- a/truthinquiry/static/js/admin_npc.js +++ b/truthinquiry/static/js/admin_npc.js @@ -1,5 +1,5 @@ -const reactionsDelta = {} +const reactionsDelta = {}; async function createOrUpdateNpc() { const data = {}; @@ -9,7 +9,7 @@ async function createOrUpdateNpc() { const allAnswersJson = []; data["allAnswers"] = allAnswersJson; - for (let answerTypeNode of document.querySelector(".answer_groups").children) { + for (const answerTypeNode of document.querySelector(".answer_groups").children) { const answersJson = []; const answerTypeJson = {"answers": answersJson}; allAnswersJson.push(answerTypeJson); @@ -20,35 +20,33 @@ async function createOrUpdateNpc() { } await makeAPIRequest("admin/setNpc", {"npc": data, "lang": "FR"}, {"content": "json"}); - await uploadReactionsDelta(); alert("Opération effectuée avec succès"); } async function uploadReactionsDelta() { - let requests = []; + const requests = []; + const npcId = document.querySelector("#npc_id").value; - - for(const [traitId, reactionNode] of Object.entries(reactionsDelta)){ + for (const [traitId, reactionNode] of Object.entries(reactionsDelta)) { const formData = new FormData(); - formData.append("npc_id", npc_id.value); + formData.append("npc_id", npcId); formData.append("trait_id", traitId); - if(reactionNode === null) formData.append("file", "null"); - else{ - const file = reactionNode.querySelector(".img_input").files[0] + if (reactionNode === null) { + formData.append("file", "null"); + } else { + const file = reactionNode.querySelector(".img_input").files[0]; formData.append("file", file ? file : ""); } requests.push(makeAPIRequest("admin/setReaction", formData, {"content": "form"})); } - for(request of requests){ + for (const request of requests) { await request; } - - } async function deleteNpc() { @@ -62,51 +60,141 @@ async function deleteNpc() { document.location = "/admin"; } -function changeReaction(inputNode){ - const parentNode = inputNode.parentNode; +function changeImageReaction(imageInputElement) { + const parentNode = imageInputElement.parentNode; const imgNode = parentNode.querySelector('img'); const traitId = parentNode.querySelector('.trait_id').value; const reader = new FileReader(); - reader.onload = (e)=>{ - imgNode.src = e.target.result - } - reader.readAsDataURL(inputNode.files[0]); + reader.addEventListener("load", event => { + imgNode.src = event.target.result + }); + reader.readAsDataURL(imageInputElement.files[0]); reactionsDelta[traitId] = parentNode; } -function deleteReaction(node){ - const reactionNode = node.parentNode; +function deleteImageReaction(reactionDeletionButton) { + if (!confirm("Voulez-vous vraiment supprimer l'image de cette réaction ?")) { + return; + } + + const reactionNode = reactionDeletionButton.parentNode; const traitId = reactionNode.querySelector(".trait_id").value; - const reactionName = reactionNode.querySelector("p").innerText; + const reactionName = reactionNode.querySelector(".reaction_name").innerText; reactionNode.parentNode.removeChild(reactionNode); const option = document.createElement("option"); - option.value = traitId - option.innerText = reactionName + option.value = traitId; + option.innerText = reactionName; - reactions_to_add.appendChild(option); + const addReactionsSelectorElement = document.getElementById("add_reactions_selector"); + if (addReactionsSelectorElement === null) { + // No add_reactions_selector element, this should never happen + // Do nothing in this case + return; + } + + addReactionsSelectorElement.appendChild(option); reactionsDelta[traitId] = null; } -function addReaction(selectNode){ - const selectedOptionNode = selectNode.selectedOptions[0]; +function addReaction(addReactionsSelectorElement) { + const selectedOptionNode = addReactionsSelectorElement.selectedOptions[0]; const traitId = selectedOptionNode.value; const reactionName = selectedOptionNode.innerText; - selectNode.removeChild(selectedOptionNode); + addReactionsSelectorElement.removeChild(selectedOptionNode); - const newReaction = reactions.querySelector("div").cloneNode(true); - newReaction.querySelector("img").src = ""; - newReaction.querySelector(".img_input").value = null; - newReaction.querySelector(".trait_id").value = traitId - newReaction.querySelector("p").innerText = reactionName - - reactions.appendChild(newReaction); + const newReactionElement = document.createElement("section"); + newReactionElement.classList.add("reaction"); - reactionsDelta[traitId] = newReaction; -} \ No newline at end of file + const reactionNameElement = document.createElement("h3"); + reactionNameElement.classList.add("reaction_name"); + reactionNameElement.textContent = reactionName; + + newReactionElement.appendChild(reactionNameElement); + + const imageElement = document.createElement("img"); + imageElement.classList.add("reaction_image"); + imageElement.setAttribute("alt", "Image d'une réaction d'un personnage"); + imageElement.src = "/static/images/no_photography_white.svg"; + + newReactionElement.appendChild(imageElement); + + const imageInputElement = document.createElement("input"); + imageInputElement.classList.add("img_input"); + imageInputElement.setAttribute("type", "file"); + imageInputElement.setAttribute("accept", "image/png, image/jpg, image/jpeg"); + imageInputElement.addEventListener("change", () => changeImageReaction(imageInputElement)); + + newReactionElement.appendChild(imageInputElement); + + const traitIdInputElement = document.createElement("input"); + traitIdInputElement.classList.add("trait_id"); + traitIdInputElement.setAttribute("type", "hidden"); + traitIdInputElement.setAttribute("value", traitId); + + newReactionElement.appendChild(traitIdInputElement); + + const buttonElement = document.createElement("button"); + buttonElement.classList.add("delete_question_btn", "action_button", "short_color_transition"); + buttonElement.setAttribute("title", "Cliquez ici pour supprimer l'image de cette réaction"); + buttonElement.addEventListener("click", () => deleteImageReaction(buttonElement)); + + 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 l'image de la réaction")); + + newReactionElement.appendChild(buttonElement); + + const reactionsElement = document.getElementById("reactions"); + if (reactionsElement === null) { + // No add_reactions_selector element, this should never happen + // Do nothing in this case + return; + } + + reactionsElement.appendChild(newReactionElement); + + reactionsDelta[traitId] = newReactionElement; +} + +function setListenersToImageInputs() { + for (const imageInput of document.getElementsByClassName("img_input")) { + imageInput.addEventListener("change", () => changeImageReaction(imageInput)); + } +} + +function setListenersToImageReactionsRemovalButtons() { + for (const imageReactionRemovalButton of document.getElementsByClassName("delete_image_reaction_btn")) { + imageReactionRemovalButton.addEventListener("click", () => deleteImageReaction(imageReactionRemovalButton)); + } +} + +function setListenersToAddReactionsSelector() { + const addReactionsSelectorElement = document.getElementById("add_reactions_selector"); + if (addReactionsSelectorElement === null) { + // No add_reactions_selector element, this should never happen + // Do nothing in this case + return; + } + + addReactionsSelectorElement.addEventListener("change", () => addReaction(addReactionsSelectorElement)); +} + +setListenersToImageReactionsRemovalButtons(); +setListenersToImageInputs(); +setListenersToAddReactionsSelector(); diff --git a/truthinquiry/static/js/admin_places.js b/truthinquiry/static/js/admin_places.js new file mode 100644 index 0000000..c536e98 --- /dev/null +++ b/truthinquiry/static/js/admin_places.js @@ -0,0 +1,95 @@ +function addPlace() { + const placeElement = document.createElement("div"); + placeElement.classList.add("place"); + + const inputElement = document.createElement("input"); + inputElement.classList.add("place_input"); + inputElement.setAttribute("type", "text"); + inputElement.setAttribute("id", ""); + + placeElement.appendChild(inputElement); + + const buttonElement = document.createElement("button"); + buttonElement.classList.add("delete_place_btn", "action_button", "short_color_transition"); + buttonElement.setAttribute("title", "Cliquez ici pour supprimer ce lieu"); + + 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 le lieu")); + buttonElement.addEventListener("click", () => deletePlace(buttonElement)); + + placeElement.appendChild(buttonElement); + + const placesElement = document.getElementById("places"); + if (placesElement === null) { + // No places element, this should never happen + // Do nothing in this case + return; + } + + placesElement.appendChild(placeElement); +} + +function deletePlace(placeRemoveButton) { + if (!confirm("Voulez-vous vraiement supprimer ce lieu ?")) { + return; + } + + const placeElement = placeRemoveButton.parentNode; + placeElement.parentNode.removeChild(placeElement); +} + +function saveChanges() { + const data = []; + for (const section of document.getElementsByClassName("place")) { + const place = {}; + place["id"] = section.id; + place["name"] = section.querySelector("input").value; + data.push(place); + } + + makeAPIRequest("admin/setPlaces", {"places": data, "lang": "FR"}, {"content": "json"}).then(() => { + alert("Opération effectuée avec succès"); + }); +} + +function setListenersToPlaceAdditionButton() { + const addPlaceButton = document.getElementById("add_place"); + if (addPlaceButton === null) { + // There is no add_place button, this should never happen + // Do nothing in this case + return; + } + + addPlaceButton.addEventListener("click", addPlace); +} + +function setListenersToPlaceDeletionButtons() { + for (const deletePlaceButton of document.getElementsByClassName("delete_place_btn")) { + deletePlaceButton.addEventListener("click", () => deletePlace(deletePlaceButton)); + }; +} + +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); +} + +setListenersToPlaceDeletionButtons(); +setListenersToPlaceAdditionButton(); +setListenersToSaveChangesButton(); diff --git a/truthinquiry/static/js/admin_questions.js b/truthinquiry/static/js/admin_questions.js new file mode 100644 index 0000000..19807c7 --- /dev/null +++ b/truthinquiry/static/js/admin_questions.js @@ -0,0 +1,95 @@ +function addQuestion(questionAddButton) { + const questionElement = document.createElement("div"); + questionElement.classList.add("question"); + + const inputElement = document.createElement("input"); + inputElement.classList.add("question_input"); + inputElement.setAttribute("type", "text"); + + questionElement.appendChild(inputElement); + + const buttonElement = document.createElement("button"); + buttonElement.classList.add("delete_question_btn", "action_button", "short_color_transition"); + buttonElement.setAttribute("title", "Cliquez ici pour supprimer cette question"); + + 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 question")); + buttonElement.addEventListener("click", () => deleteQuestion(buttonElement)); + + questionElement.appendChild(buttonElement); + + const questionTypeListElements = questionAddButton.parentNode.getElementsByClassName("question_type_list"); + if (questionTypeListElements.length == 0) { + // No question_type_list element, this should never happen + // Do nothing in this case + return; + } + + // There should be at most one question_type_list element per question type + questionTypeListElements[0].appendChild(questionElement); +} + +function deleteQuestion(questionRemoveButton) { + if (!confirm("Voulez-vous vraiement supprimer ce lieu ?")) { + return; + } + + const questionElement = questionRemoveButton.parentNode; + questionElement.parentNode.removeChild(questionElement); +} + +function saveChanges() { + const data = []; + + for (const questionTypeNode of document.getElementsByClassName("question_type")) { + const questionsJson = []; + + for (const questionNode of questionTypeNode.querySelectorAll( + ".question_type_list .question .question_input")) { + questionsJson.push({"text": questionNode.value}); + } + + const questionTypeJson = {"questions": questionsJson}; + data.push(questionTypeJson); + } + + makeAPIRequest("admin/setQuestions", {"questions": data, "lang": "FR"}, {"content": "json"}).then(() => { + alert("Opération effectuée avec succès"); + }) +} + +function setListenersToQuestionAdditionButtons() { + for (const deleteQuestionButton of document.getElementsByClassName("add_question_btn")) { + deleteQuestionButton.addEventListener("click", () => addQuestion(deleteQuestionButton)); + }; +} + +function setListenersToQuestionDeletionButtons() { + for (const deleteQuestionButton of document.getElementsByClassName("delete_question_btn")) { + deleteQuestionButton.addEventListener("click", () => deleteQuestion(deleteQuestionButton)); + }; +} + +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); +} + +setListenersToQuestionAdditionButtons(); +setListenersToQuestionDeletionButtons(); +setListenersToSaveChangesButton(); diff --git a/truthinquiry/static/js/admin_traits.js b/truthinquiry/static/js/admin_traits.js new file mode 100644 index 0000000..ef8a592 --- /dev/null +++ b/truthinquiry/static/js/admin_traits.js @@ -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(); diff --git a/truthinquiry/templates/admin/auth.html b/truthinquiry/templates/admin/auth.html index d8849bb..c7c1c7f 100644 --- a/truthinquiry/templates/admin/auth.html +++ b/truthinquiry/templates/admin/auth.html @@ -22,7 +22,12 @@ - + {% if failed %}

Mot de passe invalide !

diff --git a/truthinquiry/templates/admin/index.html b/truthinquiry/templates/admin/index.html index 2ce2a50..de264c4 100644 --- a/truthinquiry/templates/admin/index.html +++ b/truthinquiry/templates/admin/index.html @@ -29,12 +29,12 @@ - + Nouveau personnage diff --git a/truthinquiry/templates/admin/npc.html b/truthinquiry/templates/admin/npc.html index b34edd7..2f8a2cf 100644 --- a/truthinquiry/templates/admin/npc.html +++ b/truthinquiry/templates/admin/npc.html @@ -26,37 +26,41 @@

Truth Inquiry - Interface d'administration

{{'Gestion' if npc.get('id') else 'Ajout'}} d'un personnage

Cliquez sur les champs pour éditer les informations. Dans les réponses aux questions lors de l'interrogation, utilisez « {NPC} » pour faire référence au nom d'un personnage et « {SALLE} » pour faire référence au nom d'une salle.

-
+

Informations sur le personnage

- +

Nom du personnage

Image du personnage

{{'Image du personnage' + (' ' + npc.get('name') if npc.get('name') else '')}}
-
-

Réactions

- - {%for reaction in npc.get("reactions") or []%} -
-

{{reaction.get('name')}}

- - - - -
- {%endfor%} -
- - + + +
{%endfor%} - - -
+
+
+

Réactions à ajouter

+ +
+

Réponses aux questions lors de l'interrogation

{%for answer_type in npc.get("answers") or []%} @@ -95,7 +99,8 @@

JavaScript nécessaire

-

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 ajouter ou gérer un personnage.

+

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 ajouter ou gérer un personnage.

+
Se déconnecter de l'interface d'administration du jeu diff --git a/truthinquiry/templates/admin/places.html b/truthinquiry/templates/admin/places.html index 2b091b9..9cdc800 100644 --- a/truthinquiry/templates/admin/places.html +++ b/truthinquiry/templates/admin/places.html @@ -1,26 +1,65 @@ - Places - - - + Truth Inquiry - Gestion des lieux + + + + + + + + + + + - go Back
- - -
+
+ Accueil + Gestion des questions + Gestion des lieux + Gestion des réactions + Déconnexion +
+

Truth Inquiry - Interface d'administration

+

Gestion des lieux

+

Cliquez sur les champs pour éditer les lieux.

+
{%for place in places%} -
- - -
+
+ + +
{%endfor%} -
- - - +
+ + + + + diff --git a/truthinquiry/templates/admin/questions.html b/truthinquiry/templates/admin/questions.html index 0059d0e..98e45f3 100644 --- a/truthinquiry/templates/admin/questions.html +++ b/truthinquiry/templates/admin/questions.html @@ -1,34 +1,70 @@ - Admin Page - - - + Truth Inquiry - Gestion des questions + + + + + + + + + + + - - go Back
- -
- {%for questionType in questions%} -
-
- {%for question in questionType["questions"]%} -
- - -
- {%endfor%} -
- +
+ Accueil + Gestion des questions + Gestion des lieux + Gestion des réactions + Déconnexion +
+

Truth Inquiry - Interface d'administration

+

Gestion des questions

+

Cliquez sur les champs pour éditer les questions.

+ {%for questionType in questions%} +
+

Type de question {{loop.index0}}

+
+ {%for question in questionType["questions"]%} +
+ + +
+ {%endfor%}
- {%endfor%} +
- -
- - + {%endfor%} + + + + diff --git a/truthinquiry/templates/admin/traits.html b/truthinquiry/templates/admin/traits.html index a4e2bb0..e693c71 100644 --- a/truthinquiry/templates/admin/traits.html +++ b/truthinquiry/templates/admin/traits.html @@ -1,29 +1,72 @@ - Traits - - - + Truth Inquiry - Gestion des réactions + + + + + + + + + + + - go Back
- -
+
+ Accueil + Gestion des questions + Gestion des lieux + Gestion des réactions + Déconnexion +
+

Truth Inquiry - Interface d'administration

+

Gestion des réactions

+

Cliquez sur les champs pour éditer les informations. Les images des émotions sont disponibles par personnage dans leur page de gestion dédiée.

+
{%for trait in traits%} -
-

Name:

- -

Description:

- - -
+
+
+

Nom de la réaction :

+ +
+
+

Description de la réaction :

+ +
+ +
{%endfor%} -
- - - -

Images are viewable in the npc views

+
+ + + + + - \ No newline at end of file +