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("Index successful") | |
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("Index successful") | |
enableButtons() | |
}) | |
} | |
} else { | |
fetch("/index_tdocs/all", {method: "POST", headers: {"Content-Type": "application/json"}}) | |
.then(resp => resp.text()) | |
.then(data => { | |
logMessage("Index successful") | |
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("Index successful") | |
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("Index successful") | |
enableButtons() | |
}) | |
}); | |
</script> | |
</body> | |
</html> | |