Reqxtract-v2 / index.html
om4r932's picture
Add query requirements capacity + TODO : Categorization
040cfa1
raw
history blame
15.1 kB
<!DOCTYPE html>
<html lang="fr" data-theme="light">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Requirements Extractor</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/full.css" rel="stylesheet">
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="p-8 bg-base-100">
<div class="container mx-auto">
<h1 class="text-4xl font-bold text-center mb-8">Requirements Extractor</h1>
<div id="dataFrameForm">
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6">
<select class="select select-bordered" id="workingGroupSelect">
<option disabled selected value="">Working Group</option>
<option>SA1</option>
<option>SA2</option>
<option>SA3</option>
<option>SA4</option>
<option>SA5</option>
<option>SA6</option>
<option>CT1</option>
<option>CT2</option>
<option>CT3</option>
<option>CT4</option>
<option>CT5</option>
<option>CT6</option>
</select>
<select class="select select-bordered" id="meetingSelect" disabled>
<option disabled selected value="">Select a working group</option>
</select>
<button class="btn" id="getTDocs">Get TDocs</button>
</div>
</div>
<div class="hidden" id="filters">
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6">
<select class="select select-bordered" id="docType">
<option disabled selected value="">Type</option>
<option>Tous</option>
</select>
<select class="select select-bordered" id="docStatus">
<option disabled selected value="">Status</option>
<option>Tous</option>
</select>
<select class="select select-bordered" id="agendaItem">
<option disabled selected value="">Agenda Item</option>
<option>Tous</option>
</select>
</div>
</div>
<div class="flex justify-center mt-12 min-h-screen hidden" id="queryReqForm">
<div class="w-full max-w-md">
<div class="grid grid-cols-1 gap-4">
<textarea placeholder="Enter your problem description here ..."
class="w-full mx-auto px-4 py-2 border rounded" id="problemDescription" />
<button class="w-1/2 mx-auto px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700" id="queryReq">
Find requirements
</button>
</div>
</div>
</div>
<center>
<span class="loading loading-bars loading-xl hidden" id="loadingBar"></span>
<p class="hidden" id="progressText"></p>
</center>
<!-- Tableau des données -->
<div class="max-h-[65vh] overflow-y-auto" id="dataFrameDiv">
<table class="table table-zebra w-full" id="dataFrame">
<thead class="sticky top-0 bg-base-200 z-10">
<tr class="bg-base-200">
<th>TDoc</th>
<th>Title</th>
<th>Type</th>
<th>Status</th>
<th>Agenda Item N°</th>
<th>URL</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
<center>
<div id="buttons">
<p id="reqStatus" class="mt-6 hidden">Requirements extracted</p>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6">
<button class="btn mt-6" id="getReqs">Get Requirements</button>
<button class="btn mt-6 hidden" id="searchReq">Query requirements</button>
<button class="btn mt-6 hidden" id="categorizeReq">Categorize requirements</button>
</div>
</div>
</center>
</div>
<script>
let requirements;
function getDataFrame(){
document.getElementById("loadingBar").classList.remove("hidden");
const wg = document.getElementById('workingGroupSelect').value;
const meeting = document.getElementById('meetingSelect').value;
document.getElementById('docType').innerHTML = `
<option disabled selected value="">Type</option>
<option>Tous</option>
`
document.getElementById('docStatus').innerHTML = `
<option disabled selected value="">Status</option>
<option>Tous</option>
`
document.getElementById('agendaItem').innerHTML = `
<option disabled selected value="">Agenda Item</option>
<option>Tous</option>
`
const dataFrame = document.getElementById("dataFrame");
document.getElementById("progressText").classList.remove('hidden')
document.getElementById("progressText").innerHTML = "Loading ...";
document.getElementById("loadingBar").classList.remove("hidden")
fetch("/get_dataframe", {method: "POST", headers: {"Content-Type": "application/json"}, body: JSON.stringify({"working_group": wg, "meeting": meeting})})
.then(resp => resp.json())
.then(data => {
document.getElementById("filters").classList.remove("hidden")
document.getElementById("loadingBar").classList.add("hidden");
const dataframeBody = dataFrame.querySelector("tbody");
dataframeBody.innerHTML = "";
const setType = new Set();
const setAgenda = new Set();
const setStatus = new Set();
data.data.forEach(row => {
const tr = document.createElement("tr");
tr.setAttribute("data-type", row['Type']);
tr.setAttribute("data-status", row["TDoc Status"]);
tr.setAttribute("data-agenda", row["Agenda item description"]);
tr.innerHTML = `
<td>${row["TDoc"]}</td>
<td>${row["Title"]}</td>
<td>${row["Type"]}</td>
<td>${row["TDoc Status"]}</td>
<td>${row["Agenda item description"]}</td>
<td>
<a href="${row["URL"]}" class="link">${row["URL"]}</a>
</td>
`;
dataframeBody.appendChild(tr);
setType.add(row["Type"]);
setAgenda.add(row["Agenda item description"]);
setStatus.add(row["TDoc Status"]);
})
setType.forEach(tdoctype => {
const option = document.createElement("option");
option.textContent = tdoctype;
option.value = tdoctype;
document.getElementById('docType').appendChild(option);
})
setAgenda.forEach(agenda => {
const option = document.createElement("option");
option.textContent = agenda;
option.value = agenda;
document.getElementById('agendaItem').appendChild(option);
})
setStatus.forEach(status => {
const option = document.createElement("option");
option.textContent = status;
option.value = status;
document.getElementById('docStatus').appendChild(option);
})
})
document.getElementById("progressText").classList.add('hidden')
document.getElementById("loadingBar").classList.add("hidden")
}
function filterTable() {
const type = document.getElementById('docType').value
const status = document.getElementById('docStatus').value
const agenda = document.getElementById('agendaItem').value
document.querySelectorAll('#dataFrame tbody tr').forEach(row => {
const showRow =
(type === 'Tous' || row.dataset.type === type || type === "") &&
(status === 'Tous' || row.dataset.status === status || status === "") &&
(agenda === 'Tous' || row.dataset.agenda === agenda || agenda === "")
row.style.display = showRow ? '' : 'none'
})
}
function getMeetings(){
const workingGroup = document.getElementById("workingGroupSelect").value;
document.getElementById("meetingSelect").setAttribute('disabled', 'true')
document.getElementById("meetingSelect").innerHTML = "<option>Loading...</option>"
document.getElementById("getTDocs").setAttribute('disabled', 'true')
fetch("/get_meetings", {method: "POST", headers: {"Content-Type": "application/json"}, body: JSON.stringify({"working_group": workingGroup})})
.then(resp => resp.json())
.then(data => {
document.getElementById("meetingSelect").innerHTML = "";
document.getElementById("meetingSelect").removeAttribute("disabled");
document.getElementById("getTDocs").removeAttribute("disabled")
for(const [key, value] of Object.entries(data.meetings)){
const option = document.createElement("option");
option.textContent = key;
option.value = value;
document.getElementById('meetingSelect').appendChild(option);
}
})
}
function generateRequirements(){
const bodyreq = tableToGenBody();
document.getElementById("progressText").classList.remove('hidden');
document.getElementById("progressText").innerHTML = "Generating requirements, please wait, it may take a while ...";
document.getElementById("loadingBar").classList.remove("hidden");
fetch("/generate_requirements", {method: "POST", headers: {"Content-Type": "application/json"}, body: JSON.stringify({"documents": bodyreq})})
.then(resp => resp.json())
.then(data => {
requirements = [];
data.requirements.forEach(obj => {
obj.requirements.forEach(req => {
requirements.push({"document": obj.document, "context": obj.context, "requirement": req})
})
})
document.getElementById("loadingBar").classList.add("hidden");
document.getElementById("progressText").classList.add("hidden");
document.getElementById("reqStatus").classList.remove("hidden");
document.getElementById("getReqs").classList.add("hidden");
document.getElementById("searchReq").classList.remove("hidden");
document.getElementById("categorizeReq").classList.remove("hidden");
})
}
function queryRequirements(){
fetch("/get_reqs_from_query", {method: "POST", headers: {"Content-Type": "application/json"}, body: JSON.stringify({query: document.getElementById("problemDescription").value, requirements})})
.then(resp => resp.json())
.then(data => {
const dataFrame = document.getElementById("dataFrameDiv");
const dataFrameHead = dataFrame.querySelector("thead");
const dataFrameBody = dataFrame.querySelector("tbody");
dataFrame.classList.remove("hidden");
dataFrameHead.innerHTML = `
<th>TDoc</th>
<th>Context</th>
<th>Requirement</th>
`;
dataFrameBody.innerHTML = "";
data.requirements.forEach(req => {
const tr = document.createElement("tr");
tr.innerHTML = `
<td>${req["document"]}</td>
<td>${req["context"]}</td>
<td>${req["requirement"]}</td>
`;
dataFrameBody.appendChild(tr);
})
})
}
function tableToGenBody() {
// columnsMap : { "NomHeaderDansTable": "nom_voulu", ... }
let columnsMap = {"TDoc": "document", "URL": "url"};
const headers = Array.from(dataFrame.querySelectorAll('thead th')).map(th => th.innerText.trim());
// Indices des colonnes à extraire
const selectedIndices = headers
.map((header, idx) => columnsMap[header] ? idx : -1)
.filter(idx => idx !== -1);
return Array.from(dataFrame.querySelectorAll('tbody tr'))
.filter(row => getComputedStyle(row).display !== 'none')
.map(row => {
const cells = Array.from(row.querySelectorAll('td'));
const obj = {};
selectedIndices.forEach(idx => {
const originalHeader = headers[idx];
const newKey = columnsMap[originalHeader];
obj[newKey] = cells[idx].innerText.trim();
});
return obj;
});
}
// Écouteurs d'événements pour les filtres
document.getElementById('docType').addEventListener('change', filterTable)
document.getElementById('docStatus').addEventListener('change', filterTable)
document.getElementById('agendaItem').addEventListener('change', filterTable)
document.getElementById("workingGroupSelect").addEventListener('change', getMeetings)
document.getElementById('getTDocs').addEventListener('click', getDataFrame)
document.getElementById("getReqs").addEventListener("click", generateRequirements);
document.getElementById("queryReq").addEventListener("click", queryRequirements)
document.getElementById('searchReq').addEventListener('click', ()=>{
document.getElementById('dataFrameForm').classList.add('hidden');
document.getElementById('filters').classList.add('hidden');
document.getElementById('queryReqForm').classList.remove('hidden');
document.getElementById('dataFrameDiv').classList.add('hidden');
document.getElementById('buttons').classList.add('hidden');
})
</script>
</body>
</html>