Spaces:
Sleeping
Sleeping
| <html lang="fr"> | |
| <head> | |
| <meta charset="UTF-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1" /> | |
| <title>3GPP/ETSI Document Indexer Main Menu</title> | |
| <style> | |
| body { | |
| font-family: "Montserrat", sans-serif; | |
| background: #fafafa; | |
| margin: 24px; | |
| color: #1f2937; | |
| } | |
| h1 { | |
| font-size: 1.8rem; | |
| margin-bottom: 24px; | |
| } | |
| .row { | |
| display: flex; | |
| gap: 24px; | |
| margin-bottom: 24px; | |
| } | |
| .column { | |
| flex: 1; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 12px; | |
| } | |
| button { | |
| background-color: #6c63ff; | |
| color: white; | |
| font-weight: 600; | |
| font-size: 1rem; | |
| padding: 10px 14px; | |
| border: none; | |
| border-radius: 0.6em; | |
| cursor: pointer; | |
| box-shadow: 0 2px 8px rgb(31 41 55 / 8%); | |
| transition: background-color 0.2s ease; | |
| } | |
| button:hover { | |
| background-color: #5753d6; | |
| } | |
| button:disabled { | |
| cursor: default; | |
| background-color: #778191; | |
| } | |
| select { | |
| padding: 10px 14px; | |
| border-radius: 0.6em; | |
| border: none; | |
| box-shadow: 0 2px 8px rgb(31 41 55 / 8%); | |
| font-size: 1rem; | |
| color: #374151; | |
| background: #f3f4f6; | |
| appearance: none; | |
| cursor: pointer; | |
| } | |
| select:focus { | |
| outline: none; | |
| box-shadow: 0 0 0 2px #6c63ff; | |
| background: white; | |
| } | |
| select:hover { | |
| background: #e5e7eb; | |
| } | |
| select:disabled { | |
| cursor: default; | |
| } | |
| .dropdown-content { | |
| position: absolute; /* ou fixed si tu veux */ | |
| z-index: 9999; /* un nombre élevé pour être sûr que c'est au dessus */ | |
| background-color: white; /* pour que ce soit bien visible */ | |
| border: 1px solid #ccc; | |
| /* autres styles que tu avais déjà */ | |
| border-radius: 0.6em; | |
| box-shadow: 0 2px 8px rgb(31 41 55 / 8%); | |
| padding: 10px; | |
| max-height: 55vh; | |
| overflow-y: auto; | |
| } | |
| #dropbtn { | |
| background: #f3f4f6; | |
| color: #374151; | |
| font-size: 1rem; | |
| font-family: "Montserrat", sans-serif; /* même font que body */ | |
| padding: 10px 14px; | |
| border-radius: 0.6em; | |
| font-weight: normal; | |
| border: none; | |
| box-shadow: 0 2px 8px rgb(31 41 55 / 8%); | |
| cursor: pointer; | |
| width: 100%; | |
| text-align: left; | |
| appearance: none; /* supprime les styles natives du bouton */ | |
| user-select: none; | |
| transition: background-color 0.2s ease; | |
| display: inline-block; | |
| } | |
| #dropbtn:hover { | |
| background: #e5e7eb; | |
| } | |
| #dropbtn:disabled { | |
| cursor: default; | |
| } | |
| #dropbtn:focus { | |
| outline: none; | |
| box-shadow: 0 0 0 2px #6c63ff; | |
| background: white; | |
| } | |
| option { | |
| background: white; | |
| } | |
| textarea { | |
| width: 100%; | |
| min-height: 450px; | |
| border-radius: 0.6em; | |
| border: none; | |
| box-shadow: 0 2px 6px rgb(31 41 55 / 12%); | |
| padding: 12px; | |
| font-family: monospace, monospace; | |
| font-size: 0.95rem; | |
| color: #1f2937; | |
| resize: vertical; | |
| background: white; | |
| } | |
| textarea[readonly] { | |
| background: #e5e7eb; | |
| cursor: default; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <h1>📄 3GPP/ETSI Document/Specification Indexer Main Menu</h1> | |
| <div class="row" id="r1"> | |
| <div class="column"> | |
| <button id="tdocs-btn">Re-index TDocs</button> | |
| <button id="spec-3gpp-btn">Re-index 3GPP Specifications</button> | |
| </div> | |
| <div class="column"> | |
| <select id="tdocs-wg-option" aria-label="Options Working Group TDocs"> | |
| <option value="ALL" selected>Index all working groups</option> | |
| <option value="SA0">SP</option> | |
| <option value="SA1">SA1</option> | |
| <option value="SA2">SA2</option> | |
| <option value="SA3">SA3</option> | |
| <option value="SA4">SA4</option> | |
| <option value="SA5">SA5</option> | |
| <option value="SA6">SA6</option> | |
| <option value="CT0">CP</option> | |
| <option value="CT1">CT1</option> | |
| <option value="CT2">CT2</option> | |
| <option value="CT3">CT3</option> | |
| <option value="CT4">CT4</option> | |
| <option value="CT5">CT5</option> | |
| <option value="CT6">CT6</option> | |
| <option value="RAN0">RP</option> | |
| <option value="RAN1">RAN1</option> | |
| <option value="RAN2">RAN2</option> | |
| <option value="RAN3">RAN3</option> | |
| <option value="RAN4">RAN4</option> | |
| <option value="RAN5">RAN5</option> | |
| <option value="RAN6">RAN6</option> | |
| </select> | |
| </div> | |
| <div class="column"> | |
| <div class="dropdown"> | |
| <button id="dropbtn" disabled="disabled">Index all meetings</button> | |
| <div id="dropdownContent" class="dropdown-content" style="display:none;"> | |
| <label style="display:none;"><input type="checkbox" checked value="ALL">Index all meetings</label> | |
| </div> | |
| </div> | |
| <button id="spec-etsi-btn">Re-index ETSI Specifications</button> | |
| </div> | |
| </div> | |
| <textarea id="output" readonly placeholder="Output..." aria-label="Output console"></textarea> | |
| <script type="module"> | |
| const output = document.getElementById('output'); | |
| let selectedMeetings = []; | |
| let currentURL = null; | |
| function toggleDropdown() { | |
| const dropdown = document.getElementById("dropdownContent"); | |
| dropdown.style.display = (dropdown.style.display === "none") ? "block" : "none"; | |
| } | |
| document.getElementById('dropbtn').addEventListener('click', ()=>{toggleDropdown()}) | |
| document.addEventListener('mousedown', (e)=>{ | |
| if(document.getElementById("dropdownContent").style.display == "block" && e.target.className != "dropdown-content" && e.target.tagName != "INPUT" && e.target.tagName != "LABEL"){ | |
| document.getElementById("dropdownContent").style.display = "none"; | |
| } | |
| }) | |
| function logMessage(msg, reset){ | |
| if(reset){ | |
| output.value = msg + "\n"; | |
| }; | |
| output.value += msg + '\n'; | |
| output.scrollTop = output.scrollHeight; | |
| } | |
| document.getElementById('tdocs-wg-option').addEventListener('change', async (e) => { | |
| let wg = e.target.value; | |
| const dropdownContent = document.getElementById('dropdownContent'); | |
| const dropbtn = document.getElementById('dropbtn'); | |
| if (wg != "ALL") { | |
| dropdownContent.innerHTML = '<label style="display:none;"><input type="checkbox" checked value="ALL">Index all meetings</label>'; | |
| const response = await fetch(`/get_meetings/${wg}`, { method: "GET" }); | |
| const responseJson = await response.json(); | |
| const meetings = responseJson.meetings; | |
| currentURL = responseJson.url; | |
| for (const meet of meetings) { | |
| const label = document.createElement('label'); | |
| const checkbox = document.createElement('input'); | |
| checkbox.type = "checkbox"; | |
| checkbox.value = meet; | |
| label.appendChild(checkbox); | |
| label.appendChild(document.createTextNode(meet)); | |
| dropdownContent.appendChild(label); | |
| dropdownContent.appendChild(document.createElement('br')); | |
| } | |
| dropbtn.removeAttribute('disabled'); | |
| // après création, ajoute les listeners de gestion sur chaque checkbox | |
| initCheckboxListeners(); | |
| // Initialise l'état initial | |
| updateDropbtnLabel(); | |
| } else { | |
| dropdownContent.innerHTML = '<label style="display:none;"><input type="checkbox" checked value="ALL">Index all meetings</label>'; | |
| dropbtn.setAttribute('disabled', 'true'); | |
| dropbtn.textContent = "Index all meetings"; | |
| } | |
| }); | |
| function disableButtons(){ | |
| document.getElementById("spec-3gpp-btn").setAttribute('disabled', 'disabled') | |
| document.getElementById("spec-etsi-btn").setAttribute('disabled', 'disabled') | |
| document.getElementById("tdocs-btn").setAttribute('disabled', 'disabled') | |
| } | |
| function enableButtons(){ | |
| document.getElementById("spec-3gpp-btn").removeAttribute('disabled') | |
| document.getElementById("spec-etsi-btn").removeAttribute('disabled') | |
| document.getElementById("tdocs-btn").removeAttribute('disabled') | |
| } | |
| function initCheckboxListeners() { | |
| const dropdownContent = document.getElementById('dropdownContent'); | |
| const dropbtn = document.getElementById('dropbtn'); | |
| function updateState() { | |
| const checkboxes = dropdownContent.querySelectorAll('input[type="checkbox"]'); | |
| const allCheckbox = dropdownContent.querySelector('input[value="ALL"]'); | |
| const checkedBoxes = Array.from(checkboxes).filter(cb => cb.checked && cb !== allCheckbox); | |
| if (checkedBoxes.length === 0) { | |
| allCheckbox.checked = true; | |
| dropbtn.textContent = "Index all meetings"; | |
| selectedMeetings = ["ALL"]; | |
| } else { | |
| if (allCheckbox.checked) { | |
| allCheckbox.checked = false; // décocher ALL si autre(s) cochée(s) | |
| } | |
| if (checkedBoxes.length === 1) { | |
| dropbtn.textContent = checkedBoxes[0].value; | |
| } else { | |
| dropbtn.textContent = `${checkedBoxes.length} meetings sélectionnés`; | |
| } | |
| selectedMeetings = checkedBoxes.map(cb => cb.value); | |
| } | |
| console.log(selectedMeetings); | |
| console.log(currentURL); | |
| } | |
| const checkboxes = dropdownContent.querySelectorAll('input[type="checkbox"]'); | |
| checkboxes.forEach(cb => cb.addEventListener('change', updateState)); | |
| updateState(); // mise à jour initiale | |
| } | |
| function updateDropbtnLabel() { | |
| const dropdownContent = document.getElementById('dropdownContent'); | |
| const checkboxes = dropdownContent.querySelectorAll('input[type="checkbox"]'); | |
| const allCheckbox = dropdownContent.querySelector('input[value="ALL"]'); | |
| const dropbtn = document.getElementById('dropbtn'); | |
| const checkedBoxes = Array.from(checkboxes).filter(cb => cb.checked && cb !== allCheckbox); | |
| if (checkedBoxes.length === 0) { | |
| allCheckbox.checked = true; | |
| dropbtn.textContent = "Index all meetings"; | |
| } else if (checkedBoxes.length === 1) { | |
| allCheckbox.checked = false; | |
| dropbtn.textContent = checkedBoxes[0].value; | |
| } else { | |
| allCheckbox.checked = false; | |
| dropbtn.textContent = `${checkedBoxes.length} meetings sélectionnés`; | |
| } | |
| } | |
| document.getElementById('tdocs-btn').addEventListener('click', () => { | |
| disableButtons() | |
| logMessage(`Started re-indexing TDocs`); | |
| if(currentURL){ | |
| if(!selectedMeetings.includes("ALL")){ | |
| fetch("/index_tdocs/meeting", {method: "POST", headers: {"Content-Type": "application/json"}, body: JSON.stringify({wg: document.getElementById("tdocs-wg-option").value, meetings: selectedMeetings})}) | |
| .then(resp => resp.text()) | |
| .then(data => { | |
| logMessage(`${data}`) | |
| enableButtons() | |
| }) | |
| } else { | |
| fetch("/index_tdocs/working_group", {method: "POST", headers: {"Content-Type": "application/json"}, body: JSON.stringify({wg: document.getElementById("tdocs-wg-option").value})}) | |
| .then(resp => resp.text()) | |
| .then(data => { | |
| logMessage(`${data}`) | |
| enableButtons() | |
| }) | |
| } | |
| } else { | |
| fetch("/index_tdocs/all", {method: "POST", headers: {"Content-Type": "application/json"}}) | |
| .then(resp => resp.text()) | |
| .then(data => { | |
| logMessage(`${data}`) | |
| enableButtons() | |
| }) | |
| } | |
| }); | |
| document.getElementById('spec-3gpp-btn').addEventListener('click', () => { | |
| disableButtons() | |
| logMessage(`Started re-indexing 3GPP Specifications`); | |
| fetch("/index_specs/3gpp", {method: "POST", headers: {"Content-Type": "application/json"}}) | |
| .then(resp => resp.text()) | |
| .then(data => { | |
| logMessage(`${data}`) | |
| enableButtons() | |
| }) | |
| }); | |
| document.getElementById('spec-etsi-btn').addEventListener('click', () => { | |
| logMessage('Started re-indexing ETSI Specifications'); | |
| disableButtons() | |
| fetch("/index_specs/etsi", {method: "POST", headers: {"Content-Type": "application/json"}}) | |
| .then(resp => resp.text()) | |
| .then(data => { | |
| logMessage(`${data}`) | |
| enableButtons() | |
| }) | |
| }); | |
| </script> | |
| </body> | |
| </html> | |