Omar ID EL MOUMEN commited on
Commit
d2afbf4
·
1 Parent(s): 255cedd

Remove index display + change index method

Browse files
Files changed (3) hide show
  1. app.py +46 -20
  2. static/script.js +1 -47
  3. templates/index.html +4 -12
app.py CHANGED
@@ -4,6 +4,8 @@ import json
4
  import os
5
  import time
6
  import traceback
 
 
7
  import warnings
8
  from fastapi import FastAPI, HTTPException
9
  from fastapi.middleware.cors import CORSMiddleware
@@ -11,7 +13,8 @@ from fastapi.responses import FileResponse
11
  from fastapi.staticfiles import StaticFiles
12
  from pydantic import BaseModel
13
  from typing import Dict, List, Optional
14
- import uvicorn
 
15
 
16
  warnings.filterwarnings("ignore")
17
 
@@ -53,21 +56,47 @@ class BatchDocResponse(BaseModel):
53
  class TsgDocFinder:
54
  def __init__(self):
55
  self.main_ftp_url = "https://www.3gpp.org/ftp"
56
- self.indexer_file = "indexed_docs.json"
 
 
 
 
 
57
  self.indexer = self.load_indexer()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
 
59
  def load_indexer(self):
60
  """Load existing index if available"""
61
- if os.path.exists(self.indexer_file):
62
- with open(self.indexer_file, "r", encoding="utf-8") as f:
63
- return json.load(f)
64
- return {}
65
-
66
- def save_indexer(self):
67
- """Save the updated index"""
68
- with open(self.indexer_file, "w", encoding="utf-8") as f:
69
- json.dump(self.indexer, f, indent=4, ensure_ascii=False)
70
 
 
 
 
 
 
 
 
 
 
 
 
71
  def get_workgroup(self, doc):
72
  main_tsg = "tsg_ct" if doc[0] == "C" else "tsg_sa" if doc[0] == "S" else None
73
  if main_tsg is None:
@@ -97,7 +126,7 @@ class TsgDocFinder:
97
  print(f"Error accessing {url}: {e}")
98
  return []
99
 
100
- def search_document(self, doc_id, release = None):
101
  """Search for a specific document by its ID"""
102
  original_id = doc_id
103
 
@@ -105,6 +134,10 @@ class TsgDocFinder:
105
  if original_id in self.indexer:
106
  return self.indexer[original_id]
107
 
 
 
 
 
108
  # Parse the document ID
109
  main_tsg, workgroup, doc = self.get_workgroup(doc_id)
110
  if not main_tsg:
@@ -134,7 +167,6 @@ class TsgDocFinder:
134
  if doc in file.lower() or original_id in file:
135
  doc_url = f"{docs_url}/{file}"
136
  self.indexer[original_id] = doc_url
137
- self.save_indexer()
138
  return doc_url
139
 
140
  # Check in ZIP subfolder if it exists
@@ -147,7 +179,6 @@ class TsgDocFinder:
147
  if doc in file.lower() or original_id in file:
148
  doc_url = f"{zip_url}/{file}"
149
  self.indexer[original_id] = doc_url
150
- self.save_indexer()
151
  return doc_url
152
 
153
  return f"Document {doc_id} not found"
@@ -231,9 +262,4 @@ def find_documents_batch(request: BatchDocRequest):
231
  results=results,
232
  missing=missing,
233
  search_time=time.time() - start_time
234
- )
235
-
236
- @app.get("/indexed", response_model=List[str])
237
- def get_indexed_documents():
238
- finder = TsgDocFinder()
239
- return list(finder.indexer.keys())
 
4
  import os
5
  import time
6
  import traceback
7
+ import psycopg2
8
+ from dotenv import load_dotenv
9
  import warnings
10
  from fastapi import FastAPI, HTTPException
11
  from fastapi.middleware.cors import CORSMiddleware
 
13
  from fastapi.staticfiles import StaticFiles
14
  from pydantic import BaseModel
15
  from typing import Dict, List, Optional
16
+
17
+ load_dotenv()
18
 
19
  warnings.filterwarnings("ignore")
20
 
 
56
  class TsgDocFinder:
57
  def __init__(self):
58
  self.main_ftp_url = "https://www.3gpp.org/ftp"
59
+ self.host = os.environ.get("PGSQL_HOST")
60
+ self.port = os.environ.get("PGSQL_PORT")
61
+ self.user = os.environ.get("PGSQL_USER")
62
+ self.password = os.environ.get("PGSQL_PASSWORD")
63
+ self.database = os.environ.get("PGSQL_DATABASE")
64
+ self.conn = self.connect()
65
  self.indexer = self.load_indexer()
66
+
67
+ def connect(self):
68
+ """Établit une connexion à la base de données PostgreSQL"""
69
+ try:
70
+ self.conn = psycopg2.connect(
71
+ host=self.host,
72
+ port=self.port,
73
+ user=self.user,
74
+ password=self.password,
75
+ dbname=self.database
76
+ )
77
+ return self.conn
78
+ except Exception as e:
79
+ print(f"Erreur de connexion à la base de données: {e}")
80
+ return None
81
 
82
  def load_indexer(self):
83
  """Load existing index if available"""
84
+ if not self.conn:
85
+ self.conn = self.connect()
86
+ if self.conn is None:
87
+ raise HTTPException(status_code=500, detail="Connexion à la base de donnée impossible")
 
 
 
 
 
88
 
89
+ cursor = self.conn.cursor()
90
+ try:
91
+ cursor.execute("SELECT doc_id, url FROM document_position")
92
+ rows = cursor.fetchall()
93
+ doc = {doc_id: url for doc_id, url in rows}
94
+ except:
95
+ raise HTTPException(status_code=500, detail="Erreur lors de la récupération")
96
+ finally:
97
+ cursor.close()
98
+ return doc
99
+
100
  def get_workgroup(self, doc):
101
  main_tsg = "tsg_ct" if doc[0] == "C" else "tsg_sa" if doc[0] == "S" else None
102
  if main_tsg is None:
 
126
  print(f"Error accessing {url}: {e}")
127
  return []
128
 
129
+ def search_document(self, doc_id: str, release = None):
130
  """Search for a specific document by its ID"""
131
  original_id = doc_id
132
 
 
134
  if original_id in self.indexer:
135
  return self.indexer[original_id]
136
 
137
+ for doc in self.indexer:
138
+ if original_id.startswith(doc):
139
+ return self.indexer[doc]
140
+
141
  # Parse the document ID
142
  main_tsg, workgroup, doc = self.get_workgroup(doc_id)
143
  if not main_tsg:
 
167
  if doc in file.lower() or original_id in file:
168
  doc_url = f"{docs_url}/{file}"
169
  self.indexer[original_id] = doc_url
 
170
  return doc_url
171
 
172
  # Check in ZIP subfolder if it exists
 
179
  if doc in file.lower() or original_id in file:
180
  doc_url = f"{zip_url}/{file}"
181
  self.indexer[original_id] = doc_url
 
182
  return doc_url
183
 
184
  return f"Document {doc_id} not found"
 
262
  results=results,
263
  missing=missing,
264
  search_time=time.time() - start_time
265
+ )
 
 
 
 
 
static/script.js CHANGED
@@ -12,9 +12,6 @@ const resultsContainer = document.getElementById('results-container');
12
  const resultsList = document.getElementById('results-list');
13
  const resultsStats = document.getElementById('results-stats');
14
  const errorMessage = document.getElementById('error-message');
15
- const indexedDocs = document.getElementById('indexed-docs');
16
- const indexedCount = document.getElementById('indexed-count');
17
- const indexedList = document.getElementById('indexed-list');
18
 
19
  // Search mode toggle
20
  singleModeBtn.addEventListener('click', () => {
@@ -55,7 +52,6 @@ searchBtn.addEventListener('click', async () => {
55
 
56
  if (response.ok) {
57
  displaySingleResult(data);
58
- loadIndexedDocuments(); // Refresh indexed docs
59
  } else {
60
  displaySingleNotFound(docId, data.detail);
61
  }
@@ -100,7 +96,6 @@ batchSearchBtn.addEventListener('click', async () => {
100
 
101
  if (response.ok) {
102
  displayBatchResults(data);
103
- loadIndexedDocuments(); // Refresh indexed docs
104
  } else {
105
  showError('Error processing batch request');
106
  }
@@ -192,44 +187,6 @@ function displayBatchResults(data) {
192
  resultsContainer.style.display = 'block';
193
  }
194
 
195
- // Load indexed documents
196
- async function loadIndexedDocuments() {
197
- try {
198
- const response = await fetch(`/indexed`);
199
- if (response.ok) {
200
- const data = await response.json();
201
- displayIndexedDocuments(data);
202
- }
203
- } catch (error) {
204
- console.error('Error loading indexed documents:', error);
205
- }
206
- }
207
-
208
- // Display indexed documents
209
- function displayIndexedDocuments(docIds) {
210
- indexedList.innerHTML = '';
211
- indexedCount.textContent = `${docIds.length} documents`;
212
-
213
- if (docIds.length === 0) {
214
- const emptyMessage = document.createElement('p');
215
- emptyMessage.textContent = 'No documents have been indexed yet.';
216
- indexedList.appendChild(emptyMessage);
217
- return;
218
- }
219
-
220
- docIds.forEach(docId => {
221
- const docItem = document.createElement('div');
222
- docItem.className = 'indexed-item';
223
- docItem.textContent = docId;
224
- docItem.addEventListener('click', () => {
225
- docIdInput.value = docId;
226
- singleModeBtn.click();
227
- searchBtn.click();
228
- });
229
- indexedList.appendChild(docItem);
230
- });
231
- }
232
-
233
  // Show loader
234
  function showLoader() {
235
  loader.style.display = 'block';
@@ -256,7 +213,4 @@ docIdInput.addEventListener('keypress', (e) => {
256
  if (e.key === 'Enter') {
257
  searchBtn.click();
258
  }
259
- });
260
-
261
- // Load indexed documents on page load
262
- document.addEventListener('DOMContentLoaded', loadIndexedDocuments);
 
12
  const resultsList = document.getElementById('results-list');
13
  const resultsStats = document.getElementById('results-stats');
14
  const errorMessage = document.getElementById('error-message');
 
 
 
15
 
16
  // Search mode toggle
17
  singleModeBtn.addEventListener('click', () => {
 
52
 
53
  if (response.ok) {
54
  displaySingleResult(data);
 
55
  } else {
56
  displaySingleNotFound(docId, data.detail);
57
  }
 
96
 
97
  if (response.ok) {
98
  displayBatchResults(data);
 
99
  } else {
100
  showError('Error processing batch request');
101
  }
 
187
  resultsContainer.style.display = 'block';
188
  }
189
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
  // Show loader
191
  function showLoader() {
192
  loader.style.display = 'block';
 
213
  if (e.key === 'Enter') {
214
  searchBtn.click();
215
  }
216
+ });
 
 
 
templates/index.html CHANGED
@@ -21,7 +21,7 @@
21
  <div class="search-container">
22
  <div class="search-header">
23
  <h2>Find 3GPP Documents</h2>
24
- <p>Enter a TSG document ID (e.g., S1-123456, C2-987654) to locate the document in the 3GPP FTP server.</p>
25
  </div>
26
 
27
  <div class="search-mode">
@@ -33,14 +33,14 @@
33
  <div class="input-group single-input">
34
  <label for="doc-id">Document ID</label>
35
  <div class="input-field">
36
- <input type="text" id="doc-id" placeholder="Enter document ID (e.g., S1-123456)">
37
  <button id="search-btn" class="btn">Search</button>
38
  </div>
39
  </div>
40
 
41
  <div class="input-group batch-input">
42
- <label for="batch-ids">Document IDs (one per line)</label>
43
- <textarea id="batch-ids" placeholder="Enter document IDs, one per line (e.g., S1-123456, C2-987654)"></textarea>
44
  <div class="hint">Enter one document ID per line</div>
45
  <button id="batch-search-btn" class="btn" style="margin-top: 10px;">Search All</button>
46
  </div>
@@ -61,14 +61,6 @@
61
  </div>
62
  <div class="results-list" id="results-list"></div>
63
  </div>
64
-
65
- <div class="indexed-docs" id="indexed-docs">
66
- <div class="indexed-header">
67
- <h2>Indexed Documents</h2>
68
- <div class="indexed-count" id="indexed-count">0 documents</div>
69
- </div>
70
- <div class="indexed-list" id="indexed-list"></div>
71
- </div>
72
  </div>
73
 
74
  <footer>
 
21
  <div class="search-container">
22
  <div class="search-header">
23
  <h2>Find 3GPP Documents</h2>
24
+ <p>Enter a TSG document ID / specification ID (e.g., S1-123456, C2-987654 or 31.102) to locate the document in the 3GPP FTP server.</p>
25
  </div>
26
 
27
  <div class="search-mode">
 
33
  <div class="input-group single-input">
34
  <label for="doc-id">Document ID</label>
35
  <div class="input-field">
36
+ <input type="text" id="doc-id" placeholder="Enter document ID or specification ID (e.g., S1-123456, 12.345)">
37
  <button id="search-btn" class="btn">Search</button>
38
  </div>
39
  </div>
40
 
41
  <div class="input-group batch-input">
42
+ <label for="batch-ids">Document IDs or Specification IDs (one per line)</label>
43
+ <textarea id="batch-ids" placeholder="Enter document IDs or specification IDs, one per line (e.g., S1-123456, C2-987654, 31.102)"></textarea>
44
  <div class="hint">Enter one document ID per line</div>
45
  <button id="batch-search-btn" class="btn" style="margin-top: 10px;">Search All</button>
46
  </div>
 
61
  </div>
62
  <div class="results-list" id="results-list"></div>
63
  </div>
 
 
 
 
 
 
 
 
64
  </div>
65
 
66
  <footer>