Skip to content

Commit bac50b8

Browse files
fixed file managements
1 parent 3e5d6e6 commit bac50b8

File tree

5 files changed

+385
-15
lines changed

5 files changed

+385
-15
lines changed

manage-files.js

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
#!/usr/bin/env node
2+
3+
/**
4+
* File Management Script for AI Journal Club
5+
*
6+
* This script helps sync the actual file presence with the localStorage state.
7+
* Run this to check which files exist and update the localStorage accordingly.
8+
*
9+
* Usage:
10+
* node manage-files.js [command]
11+
*
12+
* Commands:
13+
* check - Check which PDF files exist
14+
* sync - Sync localStorage with actual files (for development)
15+
* list - List all expected files
16+
*/
17+
18+
import fs from 'fs';
19+
import path from 'path';
20+
import { fileURLToPath } from 'url';
21+
22+
const __filename = fileURLToPath(import.meta.url);
23+
const __dirname = path.dirname(__filename);
24+
25+
const WEEKS = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
26+
const PDF_DIR = path.join(__dirname, 'public', 'pdfs');
27+
28+
function checkPDFFiles() {
29+
console.log('📁 Checking PDF files...\n');
30+
31+
const results = WEEKS.map(week => {
32+
const filePath = path.join(PDF_DIR, `week${week}.pdf`);
33+
const exists = fs.existsSync(filePath);
34+
35+
return {
36+
week,
37+
file: `week${week}.pdf`,
38+
exists,
39+
path: filePath
40+
};
41+
});
42+
43+
results.forEach(({ week, file, exists }) => {
44+
const status = exists ? '✅' : '❌';
45+
console.log(`${status} Week ${week}: ${file}`);
46+
});
47+
48+
const existingCount = results.filter(r => r.exists).length;
49+
console.log(`\n📊 Summary: ${existingCount}/${WEEKS.length} PDF files exist`);
50+
51+
return results;
52+
}
53+
54+
function listExpectedFiles() {
55+
console.log('📋 Expected PDF files:\n');
56+
57+
WEEKS.forEach(week => {
58+
console.log(`📄 week${week}.pdf - Week ${week}${week === 0 ? ' (Orientation)' : ''}`);
59+
});
60+
61+
console.log(`\n📁 Files should be placed in: ${PDF_DIR}`);
62+
}
63+
64+
function generateSyncInstructions(results) {
65+
console.log('\n🔧 To sync your development environment:');
66+
console.log('1. Open the admin page in your browser');
67+
console.log('2. Use the following localStorage commands in browser console:\n');
68+
69+
results.forEach(({ week, exists }) => {
70+
if (exists) {
71+
console.log(`localStorage.setItem('pdf_week_${week}', 'uploaded');`);
72+
}
73+
});
74+
75+
console.log('\n3. Refresh the main page to see the changes');
76+
}
77+
78+
function main() {
79+
const command = process.argv[2] || 'check';
80+
81+
console.log('🎓 AI Journal Club - File Management\n');
82+
83+
switch (command) {
84+
case 'check':
85+
const results = checkPDFFiles();
86+
generateSyncInstructions(results);
87+
break;
88+
89+
case 'list':
90+
listExpectedFiles();
91+
break;
92+
93+
case 'sync':
94+
console.log('💡 For a static site, localStorage sync must be done manually in the browser.');
95+
console.log('Use the "check" command to see the localStorage commands needed.');
96+
break;
97+
98+
default:
99+
console.log('❓ Unknown command. Available commands: check, list, sync');
100+
break;
101+
}
102+
}
103+
104+
// Ensure PDF directory exists
105+
if (!fs.existsSync(PDF_DIR)) {
106+
fs.mkdirSync(PDF_DIR, { recursive: true });
107+
}
108+
109+
main();

public/pdfs/week0.pdf

601 Bytes
Binary file not shown.

public/pdfs/week1.pdf

639 Bytes
Binary file not shown.

src/pages/admin.astro

Lines changed: 219 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,80 @@ import Layout from '../layouts/Layout.astro';
8686
</div>
8787
</section>
8888

89+
<section class="delete-section">
90+
<h2>Delete Resources</h2>
91+
92+
<div class="delete-grid">
93+
<div class="delete-card">
94+
<h3>Delete PDF Files</h3>
95+
<p class="instruction">Remove PDF files from the course schedule.</p>
96+
97+
<div class="delete-form">
98+
<div class="form-group">
99+
<label for="delete-pdf-select">Select Week:</label>
100+
<select id="delete-pdf-select" class="form-control">
101+
<option value="">Choose a week...</option>
102+
<option value="0">Week 0 - OT</option>
103+
<option value="1">Week 1 - Efficient Methods for NLP</option>
104+
<option value="2">Week 2 - Efficient Inference for LLMs</option>
105+
<option value="3">Week 3 - DRPruning</option>
106+
<option value="4">Week 4 - QPruner</option>
107+
<option value="5">Week 5 - L4Q</option>
108+
<option value="6">Week 6 - ResLoRA</option>
109+
<option value="7">Week 7 - MeMoTune</option>
110+
<option value="8">Week 8 - DiffSkip</option>
111+
<option value="9">Week 9 - Constrained Decoding</option>
112+
<option value="10">Week 10 - DB-LLM</option>
113+
<option value="11">Week 11 - PruneVid</option>
114+
<option value="12">Week 12 - Continual Pre-training</option>
115+
<option value="13">Week 13 - Efficient LLMs Survey</option>
116+
</select>
117+
</div>
118+
119+
<button id="delete-pdf-btn" class="btn-danger">Delete PDF</button>
120+
</div>
121+
</div>
122+
123+
<div class="delete-card">
124+
<h3>Delete Video Links</h3>
125+
<p class="instruction">Remove video links from the course schedule.</p>
126+
127+
<div class="delete-form">
128+
<div class="form-group">
129+
<label for="delete-video-select">Select Week:</label>
130+
<select id="delete-video-select" class="form-control">
131+
<option value="">Choose a week...</option>
132+
<option value="0">Week 0 - OT</option>
133+
<option value="1">Week 1 - Efficient Methods for NLP</option>
134+
<option value="2">Week 2 - Efficient Inference for LLMs</option>
135+
<option value="3">Week 3 - DRPruning</option>
136+
<option value="4">Week 4 - QPruner</option>
137+
<option value="5">Week 5 - L4Q</option>
138+
<option value="6">Week 6 - ResLoRA</option>
139+
<option value="7">Week 7 - MeMoTune</option>
140+
<option value="8">Week 8 - DiffSkip</option>
141+
<option value="9">Week 9 - Constrained Decoding</option>
142+
<option value="10">Week 10 - DB-LLM</option>
143+
<option value="11">Week 11 - PruneVid</option>
144+
<option value="12">Week 12 - Continual Pre-training</option>
145+
<option value="13">Week 13 - Efficient LLMs Survey</option>
146+
</select>
147+
</div>
148+
149+
<button id="delete-video-btn" class="btn-danger">Delete Video Link</button>
150+
</div>
151+
</div>
152+
</div>
153+
</section>
154+
89155
<div class="info-box">
90156
<h3>📌 Usage Guide</h3>
91157
<ul>
92158
<li>PDF files are saved in public/pdfs/ folder as weekN.pdf format.</li>
93159
<li>Video links are stored in browser local storage. Separate management needed for production.</li>
94160
<li>Download links will appear on the main page after file upload.</li>
161+
<li>Use the delete section to remove PDFs or video links from specific weeks.</li>
162+
<li>All delete operations require confirmation to prevent accidental removal.</li>
95163
</ul>
96164
</div>
97165
</main>
@@ -291,22 +359,101 @@ import Layout from '../layouts/Layout.astro';
291359
color: #60a5fa;
292360
}
293361

362+
.delete-section {
363+
margin: 3rem 0;
364+
}
365+
366+
.delete-section h2 {
367+
font-size: 1.8rem;
368+
font-weight: 600;
369+
color: #f9fafb;
370+
margin-bottom: 1.5rem;
371+
}
372+
373+
.delete-grid {
374+
display: grid;
375+
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
376+
gap: 2rem;
377+
}
378+
379+
.delete-card {
380+
background: rgba(220, 38, 38, 0.1);
381+
border: 1px solid #dc2626;
382+
border-radius: 12px;
383+
padding: 2rem;
384+
backdrop-filter: blur(10px);
385+
}
386+
387+
.delete-card h3 {
388+
font-size: 1.3rem;
389+
font-weight: 600;
390+
color: #fca5a5;
391+
margin-bottom: 0.5rem;
392+
}
393+
394+
.delete-form {
395+
display: flex;
396+
flex-direction: column;
397+
gap: 1.5rem;
398+
}
399+
400+
.btn-danger {
401+
padding: 0.75rem 1.5rem;
402+
background: linear-gradient(135deg, #dc2626 0%, #b91c1c 100%);
403+
color: white;
404+
border: none;
405+
border-radius: 6px;
406+
font-weight: 500;
407+
cursor: pointer;
408+
transition: all 0.2s ease;
409+
font-size: 0.95rem;
410+
}
411+
412+
.btn-danger:hover {
413+
transform: translateY(-1px);
414+
box-shadow: 0 4px 12px rgba(220, 38, 38, 0.3);
415+
background: linear-gradient(135deg, #b91c1c 0%, #991b1b 100%);
416+
}
417+
418+
.btn-danger:active {
419+
transform: translateY(0);
420+
}
421+
422+
.btn-danger:disabled {
423+
opacity: 0.5;
424+
cursor: not-allowed;
425+
transform: none;
426+
box-shadow: none;
427+
}
428+
294429
@media (max-width: 768px) {
295430
.upload-section {
296431
grid-template-columns: 1fr;
297432
}
298433

434+
.delete-grid {
435+
grid-template-columns: 1fr;
436+
}
437+
299438
.admin-header h1 {
300439
font-size: 2rem;
301440
}
302441

303-
.upload-card {
442+
.upload-card, .delete-card {
304443
padding: 1.5rem;
305444
}
306445
}
307446
</style>
308447

309448
<script>
449+
// Trigger update across all tabs
450+
function triggerGlobalUpdate() {
451+
// Dispatch custom event for same-tab updates
452+
window.dispatchEvent(new CustomEvent('resourcesUpdated'));
453+
454+
// For cross-tab updates, we rely on the storage event and periodic checks
455+
}
456+
310457
// Status update function
311458
function updateStatus() {
312459
const statusGrid = document.getElementById('status-grid');
@@ -330,13 +477,14 @@ import Layout from '../layouts/Layout.astro';
330477
];
331478

332479
statusGrid.innerHTML = weeks.map(item => {
480+
const hasPdf = localStorage.getItem(`pdf_week_${item.week}`) !== null;
333481
const hasVideo = localStorage.getItem(`video_week_${item.week}`) !== null;
334482

335483
return `
336-
<div class="status-item ${hasVideo ? 'has-video' : ''}">
484+
<div class="status-item ${hasPdf ? 'has-pdf' : ''} ${hasVideo ? 'has-video' : ''}">
337485
<div class="week-label">Week ${item.week}</div>
338486
<div class="status-indicators">
339-
<div class="indicator" title="PDF"></div>
487+
<div class="indicator ${hasPdf ? 'active' : ''}" title="PDF"></div>
340488
<div class="indicator ${hasVideo ? 'active' : ''}" title="Video"></div>
341489
</div>
342490
</div>
@@ -364,11 +512,15 @@ import Layout from '../layouts/Layout.astro';
364512
return;
365513
}
366514

515+
// Mark PDF as uploaded in localStorage
516+
localStorage.setItem(`pdf_week_${week}`, 'uploaded');
517+
367518
// In actual implementation, upload file to server
368519
alert(`Week ${week} PDF file has been uploaded.\nIn production, it will be saved as public/pdfs/week${week}.pdf`);
369520

370521
fileInput.value = '';
371522
updateStatus();
523+
triggerGlobalUpdate();
372524
});
373525

374526
// Save video link
@@ -398,6 +550,70 @@ import Layout from '../layouts/Layout.astro';
398550

399551
urlInput.value = '';
400552
updateStatus();
553+
triggerGlobalUpdate();
554+
});
555+
556+
// Delete PDF functionality
557+
document.getElementById('delete-pdf-btn')?.addEventListener('click', function() {
558+
const weekSelect = document.getElementById('delete-pdf-select') as HTMLSelectElement;
559+
560+
if (!weekSelect) return;
561+
562+
const week = weekSelect.value;
563+
564+
if (!week) {
565+
alert('Please select a week to delete PDF from.');
566+
return;
567+
}
568+
569+
const hasPdf = localStorage.getItem(`pdf_week_${week}`) !== null;
570+
571+
if (!hasPdf) {
572+
alert(`No PDF found for Week ${week}.`);
573+
return;
574+
}
575+
576+
if (confirm(`Are you sure you want to delete the PDF for Week ${week}?\nThis action cannot be undone.`)) {
577+
// Remove PDF status from localStorage
578+
localStorage.removeItem(`pdf_week_${week}`);
579+
580+
// In actual implementation, this would delete the file from server
581+
alert(`Week ${week} PDF has been deleted.\nIn production, this would remove public/pdfs/week${week}.pdf`);
582+
583+
weekSelect.value = '';
584+
updateStatus();
585+
triggerGlobalUpdate();
586+
}
587+
});
588+
589+
// Delete video link functionality
590+
document.getElementById('delete-video-btn')?.addEventListener('click', function() {
591+
const weekSelect = document.getElementById('delete-video-select') as HTMLSelectElement;
592+
593+
if (!weekSelect) return;
594+
595+
const week = weekSelect.value;
596+
597+
if (!week) {
598+
alert('Please select a week to delete video link from.');
599+
return;
600+
}
601+
602+
const hasVideo = localStorage.getItem(`video_week_${week}`) !== null;
603+
604+
if (!hasVideo) {
605+
alert(`No video link found for Week ${week}.`);
606+
return;
607+
}
608+
609+
if (confirm(`Are you sure you want to delete the video link for Week ${week}?\nThis action cannot be undone.`)) {
610+
localStorage.removeItem(`video_week_${week}`);
611+
alert(`Week ${week} video link has been deleted.`);
612+
613+
weekSelect.value = '';
614+
updateStatus();
615+
triggerGlobalUpdate();
616+
}
401617
});
402618

403619
// Update status on page load

0 commit comments

Comments
 (0)