LiamKhoaLe commited on
Commit
ba690ef
·
1 Parent(s): 60bebee

Upd files page

Browse files
Files changed (4) hide show
  1. app.py +12 -0
  2. static/index.html +9 -0
  3. static/script.js +43 -3
  4. static/sidebar.js +16 -6
app.py CHANGED
@@ -525,6 +525,18 @@ async def list_project_files(user_id: str, project_id: str):
525
  return {"files": files, "filenames": filenames}
526
 
527
 
 
 
 
 
 
 
 
 
 
 
 
 
528
  @app.get("/cards")
529
  def list_cards(user_id: str, project_id: str, filename: Optional[str] = None, limit: int = 50, skip: int = 0):
530
  """List cards for a project"""
 
525
  return {"files": files, "filenames": filenames}
526
 
527
 
528
+ @app.delete("/files", response_model=MessageResponse)
529
+ async def delete_file(user_id: str, project_id: str, filename: str):
530
+ """Delete a file summary and associated chunks for a project."""
531
+ try:
532
+ rag.db["files"].delete_many({"user_id": user_id, "project_id": project_id, "filename": filename})
533
+ rag.db["chunks"].delete_many({"user_id": user_id, "project_id": project_id, "filename": filename})
534
+ logger.info(f"[FILES] Deleted file {filename} for user {user_id} project {project_id}")
535
+ return MessageResponse(message="File deleted")
536
+ except Exception as e:
537
+ raise HTTPException(500, detail=f"Failed to delete file: {str(e)}")
538
+
539
+
540
  @app.get("/cards")
541
  def list_cards(user_id: str, project_id: str, filename: Optional[str] = None, limit: int = 50, skip: int = 0):
542
  """List cards for a project"""
static/index.html CHANGED
@@ -136,6 +136,15 @@
136
 
137
  <!-- Project Content (hidden until project selected) -->
138
  <div class="project-content" id="project-content" style="display:none;">
 
 
 
 
 
 
 
 
 
139
  <!-- Upload Section -->
140
  <section class="card reveal" id="upload-section">
141
  <div class="card-header">
 
136
 
137
  <!-- Project Content (hidden until project selected) -->
138
  <div class="project-content" id="project-content" style="display:none;">
139
+ <!-- Files Section -->
140
+ <section class="card reveal" id="files-section" style="display:none;">
141
+ <div class="card-header">
142
+ <h2>📄 Project Files</h2>
143
+ <p>Browse your files, view summaries, and manage them</p>
144
+ </div>
145
+ <div id="files-list"></div>
146
+ </section>
147
+
148
  <!-- Upload Section -->
149
  <section class="card reveal" id="upload-section">
150
  <div class="card-header">
static/script.js CHANGED
@@ -153,14 +153,54 @@
153
 
154
  function renderStoredFiles(files) {
155
  const container = document.getElementById('stored-file-items');
156
- if (!container) return;
 
 
 
 
 
 
 
 
 
157
  if (!files || files.length === 0) {
158
- container.innerHTML = '<div class="muted">No files stored yet.</div>';
159
  return;
160
  }
161
- container.innerHTML = files.map(f => `<div class="pill">${f.filename}</div>`).join(' ');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
  }
163
 
 
 
 
 
 
164
  // Duplicate detection: returns {toUpload, replace, renameMap}
165
  async function resolveDuplicates(files) {
166
  const existing = window.__sb_current_filenames || new Set();
 
153
 
154
  function renderStoredFiles(files) {
155
  const container = document.getElementById('stored-file-items');
156
+ if (container) {
157
+ if (!files || files.length === 0) {
158
+ container.innerHTML = '<div class="muted">No files stored yet.</div>';
159
+ } else {
160
+ container.innerHTML = files.map(f => `<div class=\"pill\">${f.filename}</div>`).join(' ');
161
+ }
162
+ }
163
+ // Also render into Files page section
164
+ const list = document.getElementById('files-list');
165
+ if (!list) return;
166
  if (!files || files.length === 0) {
167
+ list.innerHTML = '<div class="muted">No files in this project.</div>';
168
  return;
169
  }
170
+ list.innerHTML = files.map(f => `
171
+ <div class="file-card">
172
+ <div class="file-card-head">
173
+ <div class="file-name">${f.filename}</div>
174
+ <button class="file-del" data-fn="${encodeURIComponent(f.filename)}" title="Delete">🗑️</button>
175
+ </div>
176
+ <div class="file-summary">${(f.summary || '').replace(/</g,'&lt;')}</div>
177
+ </div>
178
+ `).join('');
179
+ // bind deletes
180
+ list.querySelectorAll('.file-del').forEach(btn => {
181
+ btn.addEventListener('click', async () => {
182
+ const filename = decodeURIComponent(btn.getAttribute('data-fn'));
183
+ if (!confirm(`Delete ${filename}? This will remove all related chunks.`)) return;
184
+ const user = window.__sb_get_user();
185
+ const currentProject = window.__sb_get_current_project && window.__sb_get_current_project();
186
+ if (!user || !currentProject) return;
187
+ try {
188
+ const res = await fetch(`/files?user_id=${encodeURIComponent(user.user_id)}&project_id=${encodeURIComponent(currentProject.project_id)}&filename=${encodeURIComponent(filename)}`, { method: 'DELETE' });
189
+ if (res.ok) {
190
+ await loadStoredFiles();
191
+ } else {
192
+ alert('Failed to delete file');
193
+ }
194
+ } catch {}
195
+ });
196
+ });
197
  }
198
 
199
+ // Expose show files section
200
+ window.__sb_show_files_section = async () => {
201
+ await loadStoredFiles();
202
+ };
203
+
204
  // Duplicate detection: returns {toUpload, replace, renameMap}
205
  async function resolveDuplicates(files) {
206
  const existing = window.__sb_current_filenames || new Set();
static/sidebar.js CHANGED
@@ -110,22 +110,22 @@
110
  switch (section) {
111
  case 'projects':
112
  // Projects section is always visible, no action needed
 
113
  break;
114
  case 'files':
115
- // Could show file browser or file management interface
116
- console.log('Navigate to Files section');
 
 
117
  break;
118
  case 'chat':
119
- // Could show chat history or chat interface
120
- console.log('Navigate to Chat section');
121
  break;
122
  case 'analytics':
123
  // Could show usage analytics or insights
124
- console.log('Navigate to Analytics section');
125
  break;
126
  case 'settings':
127
  // Could show user settings or preferences
128
- console.log('Navigate to Settings section');
129
  break;
130
  }
131
 
@@ -135,6 +135,16 @@
135
  }
136
  }
137
 
 
 
 
 
 
 
 
 
 
 
138
  function updatePageTitle() {
139
  const titles = {
140
  'projects': 'Projects',
 
110
  switch (section) {
111
  case 'projects':
112
  // Projects section is always visible, no action needed
113
+ showSection('upload');
114
  break;
115
  case 'files':
116
+ showSection('files');
117
+ if (window.__sb_show_files_section) {
118
+ window.__sb_show_files_section();
119
+ }
120
  break;
121
  case 'chat':
122
+ showSection('chat');
 
123
  break;
124
  case 'analytics':
125
  // Could show usage analytics or insights
 
126
  break;
127
  case 'settings':
128
  // Could show user settings or preferences
 
129
  break;
130
  }
131
 
 
135
  }
136
  }
137
 
138
+ function showSection(name) {
139
+ const upload = document.getElementById('upload-section');
140
+ const chat = document.getElementById('chat-section');
141
+ const files = document.getElementById('files-section');
142
+ if (!upload || !chat || !files) return;
143
+ upload.style.display = name === 'upload' ? 'block' : 'none';
144
+ chat.style.display = name === 'chat' ? 'block' : 'none';
145
+ files.style.display = name === 'files' ? 'block' : 'none';
146
+ }
147
+
148
  function updatePageTitle() {
149
  const titles = {
150
  'projects': 'Projects',