|
<!DOCTYPE html> |
|
<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; |
|
z-index: 9999; |
|
background-color: white; |
|
border: 1px solid #ccc; |
|
|
|
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; |
|
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; |
|
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'); |
|
|
|
|
|
initCheckboxListeners(); |
|
|
|
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; |
|
} |
|
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(); |
|
} |
|
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> |
|
|