Add deep/quick search option
Browse files- app.py +21 -15
- static/script.js +29 -15
- templates/index.html +4 -1
app.py
CHANGED
@@ -223,6 +223,7 @@ class BatchDocResponse(BaseModel):
|
|
223 |
|
224 |
class KeywordRequest(BaseModel):
|
225 |
keywords: str
|
|
|
226 |
case_sensitive: Optional[bool] = False
|
227 |
release: Optional[str] = None
|
228 |
wg: Optional[str] = None
|
@@ -461,6 +462,7 @@ def search_spec(request: KeywordRequest):
|
|
461 |
release = request.release
|
462 |
working_group = request.wg
|
463 |
spec_type = request.spec_type
|
|
|
464 |
|
465 |
if spec.get('version', None) is None or (release is not None and spec["version"].split(".")[0] != str(release)):
|
466 |
continue
|
@@ -471,31 +473,35 @@ def search_spec(request: KeywordRequest):
|
|
471 |
|
472 |
contents = []
|
473 |
version = finder_spec.search_document(spec['id'], spec['release']).split("/")[-1].replace(".zip", "").split("-")[-1]
|
474 |
-
|
475 |
-
|
|
|
476 |
|
477 |
if request.mode == "and":
|
478 |
if all(kw in willLower(string, booleanLowered) for kw in kws):
|
479 |
put = True
|
480 |
-
if
|
481 |
-
|
482 |
-
|
483 |
-
if
|
484 |
-
|
485 |
-
|
|
|
486 |
elif request.mode == "or":
|
487 |
if any(kw in willLower(string, booleanLowered) for kw in kws):
|
488 |
put = True
|
489 |
-
if
|
490 |
-
|
491 |
-
|
492 |
-
if
|
493 |
-
|
494 |
-
|
|
|
495 |
|
496 |
if put:
|
497 |
spec_content = spec
|
498 |
-
|
|
|
499 |
results.append(spec_content)
|
500 |
else:
|
501 |
unique_specs.add(spec['id'])
|
|
|
223 |
|
224 |
class KeywordRequest(BaseModel):
|
225 |
keywords: str
|
226 |
+
search_mode: Literal["quick", "deep"]
|
227 |
case_sensitive: Optional[bool] = False
|
228 |
release: Optional[str] = None
|
229 |
wg: Optional[str] = None
|
|
|
462 |
release = request.release
|
463 |
working_group = request.wg
|
464 |
spec_type = request.spec_type
|
465 |
+
search_mode = request.search_mode
|
466 |
|
467 |
if spec.get('version', None) is None or (release is not None and spec["version"].split(".")[0] != str(release)):
|
468 |
continue
|
|
|
473 |
|
474 |
contents = []
|
475 |
version = finder_spec.search_document(spec['id'], spec['release']).split("/")[-1].replace(".zip", "").split("-")[-1]
|
476 |
+
if search_mode == "deep":
|
477 |
+
doc = finder_spec.get_document(spec['id'], version)
|
478 |
+
docValid = not isinstance(doc, str)
|
479 |
|
480 |
if request.mode == "and":
|
481 |
if all(kw in willLower(string, booleanLowered) for kw in kws):
|
482 |
put = True
|
483 |
+
if search_mode == "deep":
|
484 |
+
if docValid:
|
485 |
+
for chapter in list(doc.keys())[1:]:
|
486 |
+
if "references" not in chapter.lower() or "void" not in chapter.lower() or "annexe" not in doc[chapter].lower():
|
487 |
+
if all(kw in willLower(doc[chapter], booleanLowered) for kw in kws):
|
488 |
+
put = True
|
489 |
+
contents.append(chapter)
|
490 |
elif request.mode == "or":
|
491 |
if any(kw in willLower(string, booleanLowered) for kw in kws):
|
492 |
put = True
|
493 |
+
if search_mode == "deep":
|
494 |
+
if docValid:
|
495 |
+
for chapter in list(doc.keys())[1:]:
|
496 |
+
if "references" not in chapter.lower() or "void" not in chapter.lower() or "annexe" not in doc[chapter].lower():
|
497 |
+
if any(kw in willLower(doc[chapter], booleanLowered) for kw in kws):
|
498 |
+
put = True
|
499 |
+
contents.append(chapter)
|
500 |
|
501 |
if put:
|
502 |
spec_content = spec
|
503 |
+
if search_mode == "deep":
|
504 |
+
spec_content["contains"] = {chap: doc[chap] for chap in contents}
|
505 |
results.append(spec_content)
|
506 |
else:
|
507 |
unique_specs.add(spec['id'])
|
static/script.js
CHANGED
@@ -19,6 +19,7 @@ const modeFilter = document.querySelector("select[name=mode]")
|
|
19 |
const specTypeFilter = document.querySelector("select[name=spec_type]")
|
20 |
const workingGroupFilter = document.querySelector("select[name=working_group]")
|
21 |
const caseSensitiveFilter = document.querySelector("input[name=case_sensitive]")
|
|
|
22 |
|
23 |
const searchBtn = document.getElementById('search-btn');
|
24 |
const batchSearchBtn = document.getElementById('batch-search-btn');
|
@@ -82,7 +83,14 @@ document.getElementById('toggleFilters').onclick = function() {
|
|
82 |
};
|
83 |
|
84 |
keywordSearchBtn.addEventListener("click", async ()=>{
|
85 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
if (!keywords) {
|
87 |
showError("Please enter at least one keyword");
|
88 |
return;
|
@@ -94,12 +102,13 @@ keywordSearchBtn.addEventListener("click", async ()=>{
|
|
94 |
try{
|
95 |
let body = {
|
96 |
keywords,
|
97 |
-
"
|
98 |
-
"
|
|
|
99 |
};
|
100 |
-
if (
|
101 |
-
if (
|
102 |
-
if (
|
103 |
const response = await fetch("/search-spec", {
|
104 |
method: "POST",
|
105 |
headers: {
|
@@ -110,7 +119,7 @@ keywordSearchBtn.addEventListener("click", async ()=>{
|
|
110 |
|
111 |
const data = await response.json();
|
112 |
if (response.ok){
|
113 |
-
displayKeywordResults(data);
|
114 |
} else {
|
115 |
showError('Error processing batch request');
|
116 |
}
|
@@ -244,7 +253,7 @@ function displaySingleNotFound(docId, message) {
|
|
244 |
resultsContainer.style.display = 'block';
|
245 |
}
|
246 |
|
247 |
-
function displayKeywordResults(data) {
|
248 |
resultsList.innerHTML = '';
|
249 |
|
250 |
data.results.forEach(spec => {
|
@@ -265,19 +274,24 @@ function displayKeywordResults(data) {
|
|
265 |
<p>URL: <a target="_blank" href="${spec.url}">${spec.url}</a></p>
|
266 |
<p>Scope: ${spec.scope}</p>
|
267 |
</div>
|
268 |
-
<div class="result-actions">
|
269 |
-
<button class="get-section-btn btn" data-spec-id="${spec.id}">Get section</button>
|
270 |
-
</div>
|
271 |
`;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
272 |
|
273 |
// Ajouter le bouton au DOM
|
274 |
resultsList.appendChild(resultItem);
|
275 |
|
276 |
// Récupérer le bouton nouvellement créé
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
});
|
282 |
|
283 |
document.querySelectorAll('.get-section-btn').forEach(button => {
|
|
|
19 |
const specTypeFilter = document.querySelector("select[name=spec_type]")
|
20 |
const workingGroupFilter = document.querySelector("select[name=working_group]")
|
21 |
const caseSensitiveFilter = document.querySelector("input[name=case_sensitive]")
|
22 |
+
const searchMode = document.querySelector("select[name=search_mode]")
|
23 |
|
24 |
const searchBtn = document.getElementById('search-btn');
|
25 |
const batchSearchBtn = document.getElementById('batch-search-btn');
|
|
|
83 |
};
|
84 |
|
85 |
keywordSearchBtn.addEventListener("click", async ()=>{
|
86 |
+
let keywords = keywordInput.value.trim();
|
87 |
+
let release = releaseFilter.value;
|
88 |
+
let wg = workingGroupFilter.value;
|
89 |
+
let specType = specTypeFilter.value;
|
90 |
+
let search = searchMode.value;
|
91 |
+
let checked = caseSensitiveFilter.checked;
|
92 |
+
let mode = modeFilter.value;
|
93 |
+
|
94 |
if (!keywords) {
|
95 |
showError("Please enter at least one keyword");
|
96 |
return;
|
|
|
102 |
try{
|
103 |
let body = {
|
104 |
keywords,
|
105 |
+
"search_mode": search,
|
106 |
+
"case_sensitive": checked,
|
107 |
+
"mode": mode
|
108 |
};
|
109 |
+
if (release != ""){body.release = release}
|
110 |
+
if (wg != ""){body["working_group"] = wg}
|
111 |
+
if (specType != ""){body["spec_type"] = specType}
|
112 |
const response = await fetch("/search-spec", {
|
113 |
method: "POST",
|
114 |
headers: {
|
|
|
119 |
|
120 |
const data = await response.json();
|
121 |
if (response.ok){
|
122 |
+
displayKeywordResults(data, search);
|
123 |
} else {
|
124 |
showError('Error processing batch request');
|
125 |
}
|
|
|
253 |
resultsContainer.style.display = 'block';
|
254 |
}
|
255 |
|
256 |
+
function displayKeywordResults(data, mode) {
|
257 |
resultsList.innerHTML = '';
|
258 |
|
259 |
data.results.forEach(spec => {
|
|
|
274 |
<p>URL: <a target="_blank" href="${spec.url}">${spec.url}</a></p>
|
275 |
<p>Scope: ${spec.scope}</p>
|
276 |
</div>
|
|
|
|
|
|
|
277 |
`;
|
278 |
+
|
279 |
+
if(mode == "deep"){
|
280 |
+
resultItem.innerHTML += `
|
281 |
+
<div class="result-actions">
|
282 |
+
<button class="get-section-btn btn" data-spec-id="${spec.id}">Get section</button>
|
283 |
+
</div>
|
284 |
+
`
|
285 |
+
}
|
286 |
|
287 |
// Ajouter le bouton au DOM
|
288 |
resultsList.appendChild(resultItem);
|
289 |
|
290 |
// Récupérer le bouton nouvellement créé
|
291 |
+
if(mode == "deep"){
|
292 |
+
const button1 = resultItem.querySelector('.get-section-btn');
|
293 |
+
button1._sections = spec.contains;
|
294 |
+
}
|
295 |
});
|
296 |
|
297 |
document.querySelectorAll('.get-section-btn').forEach(button => {
|
templates/index.html
CHANGED
@@ -51,8 +51,11 @@
|
|
51 |
</div>
|
52 |
|
53 |
<div class="input-group keyword-input">
|
54 |
-
<label for="keywords">Keywords</label>
|
55 |
<div class="input-field">
|
|
|
|
|
|
|
|
|
56 |
<input type="text" id="keywords" placeholder="Enter your keywords separated by space">
|
57 |
<button id="keyword-search-btn" class="btn">Search</button>
|
58 |
</div>
|
|
|
51 |
</div>
|
52 |
|
53 |
<div class="input-group keyword-input">
|
|
|
54 |
<div class="input-field">
|
55 |
+
<select name="search_mode" class="filter-select" id="search-mode">
|
56 |
+
<option value="quick">Quick Search (only title & scope)</option>
|
57 |
+
<option value="deep">Deep Search</option>
|
58 |
+
</select>
|
59 |
<input type="text" id="keywords" placeholder="Enter your keywords separated by space">
|
60 |
<button id="keyword-search-btn" class="btn">Search</button>
|
61 |
</div>
|