diff --git a/public/admin.html b/public/admin.html
index 1398459..f99c084 100644
--- a/public/admin.html
+++ b/public/admin.html
@@ -169,12 +169,13 @@
-
đź“‚ Import from Homeschool folder
+
đź“‚ Import from .docx
+
-
-
+
+
diff --git a/public/admin.js b/public/admin.js
index 69fc2ea..5c581dc 100644
--- a/public/admin.js
+++ b/public/admin.js
@@ -504,7 +504,8 @@ $('#rte-youtube-btn').addEventListener('click', () => {
let scanImageBase64 = null;
function resetImportSection() {
- $('#import-file-select').innerHTML = '
';
+ $('#import-local-input').value = '';
+ $('#import-local-name').textContent = '';
$('#import-go-btn').disabled = true;
$('#import-status').textContent = '';
}
@@ -590,41 +591,28 @@ $('#scan-go-btn').addEventListener('click', async () => {
}
});
-// ---------- import from Homeschool folder ----------
+// ---------- import from local .docx file ----------
-$('#import-load-btn').addEventListener('click', async () => {
- $('#import-status').textContent = 'Loading files…';
- $('#import-file-select').innerHTML = '
';
- try {
- const { files } = await api('/api/admin/homeschool-files');
- if (!files.length) {
- $('#import-file-select').innerHTML = '
';
- $('#import-status').textContent = '';
- return;
- }
- $('#import-file-select').innerHTML =
- '
' +
- files.map((f) => `
`).join('');
- $('#import-go-btn').disabled = false;
- $('#import-status').textContent = `${files.length} file(s) found.`;
- } catch (err) {
- $('#import-status').textContent = `❌ ${err.message}`;
- }
-});
+$('#import-browse-btn').addEventListener('click', () => $('#import-local-input').click());
-$('#import-file-select').addEventListener('change', () => {
- $('#import-go-btn').disabled = !$('#import-file-select').value;
+$('#import-local-input').addEventListener('change', () => {
+ const file = $('#import-local-input').files[0];
+ $('#import-local-name').textContent = file ? file.name : '';
+ $('#import-go-btn').disabled = !file;
+ $('#import-status').textContent = '';
});
$('#import-go-btn').addEventListener('click', async () => {
- const path = $('#import-file-select').value;
- if (!path) return;
+ const file = $('#import-local-input').files[0];
+ if (!file) return;
const type = $('#ie-type').value;
- const mode = type === 'quiz' ? 'quiz' : type === 'lesson' ? 'lesson' : 'lesson';
+ const mode = type === 'quiz' ? 'quiz' : 'lesson';
$('#import-go-btn').disabled = true;
$('#import-status').textContent = '🔍 Extracting content… this may take a minute.';
try {
- const result = await api('/api/admin/import-docx', { method: 'POST', body: { path, mode } });
+ const arrayBuffer = await file.arrayBuffer();
+ const base64 = btoa(String.fromCharCode(...new Uint8Array(arrayBuffer)));
+ const result = await api('/api/admin/import-docx', { method: 'POST', body: { base64, mode } });
if (!$('#ie-title').value && result.title) $('#ie-title').value = result.title;
if (mode === 'quiz' && result.questions) {
$('#ie-questions').innerHTML = '';
diff --git a/server.js b/server.js
index 930deb0..d455a57 100644
--- a/server.js
+++ b/server.js
@@ -1538,18 +1538,22 @@ Respond with ONLY a JSON object in exactly this shape, nothing else, no markdown
};
app.post('/api/admin/import-docx', requirePin, async (req, res) => {
- const { path: relPath, mode } = req.body;
- if (!relPath || !TEXT_SCAN_PROMPTS[mode]) {
- return res.status(400).json({ error: 'path and mode (lesson or quiz) required' });
- }
- const fullPath = join(HOMESCHOOL_DIR, relPath);
- if (!fullPath.startsWith(HOMESCHOOL_DIR)) {
- return res.status(403).json({ error: 'Access denied' });
+ const { path: relPath, base64: b64, mode } = req.body;
+ if (!TEXT_SCAN_PROMPTS[mode] || (!relPath && !b64)) {
+ return res.status(400).json({ error: 'mode and either path or base64 required' });
}
let buffer;
- try { buffer = await readFile(fullPath); }
- catch (err) { return res.status(404).json({ error: `Could not read file: ${err.message}` }); }
+ if (b64) {
+ buffer = Buffer.from(b64, 'base64');
+ } else {
+ const fullPath = join(HOMESCHOOL_DIR, relPath);
+ if (!fullPath.startsWith(HOMESCHOOL_DIR)) {
+ return res.status(403).json({ error: 'Access denied' });
+ }
+ try { buffer = await readFile(fullPath); }
+ catch (err) { return res.status(404).json({ error: `Could not read file: ${err.message}` }); }
+ }
let docText;
try {