fix: initialize file editor and remove broken individual file uploads

Changes:
- Add fileEditor.init() call in DOMContentLoaded to activate edit buttons
- Remove individual file upload inputs (projectInput, svgInput, cssInput, csvInput)
  that had CORS issues when loading project configurations
- Keep only the folder picker which works reliably
- Update UI to emphasize folder picker as the primary loading method
- Remove corresponding event handlers from engine.js
- Remove tests for individual file upload functionality

The folder picker loads all project files in one operation without CORS
issues, while individual file uploads failed when trying to load
referenced files (CSV, SVG, CSS) from the project.json.

All 56 tests passing.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-23 23:14:57 +01:00
parent 710794de88
commit a5811040e7
3 changed files with 23 additions and 218 deletions

109
engine.js
View File

@@ -824,114 +824,7 @@ window.setupEventHandlers = function() {
});
}
const projectInput = document.getElementById("projectInput");
if (projectInput) {
projectInput.addEventListener("change", async (ev) => {
const file = ev.target.files[0];
if (!file) return;
try {
const text = await file.text();
const cfg = JSON.parse(text);
// For manually loaded projects, try to infer base path from filename
// If it's example/project.json or binect/project.json, set appropriate base path
const filename = file.name;
if (filename === 'project.json') {
// Try to detect if this is a known project by checking the config
if (cfg.name && cfg.name.includes('Example')) {
window.timelineEngine.projectBasePath = 'example/';
console.log("Detected example project, setting base path to example/");
} else if (cfg.name && (cfg.name.includes('My Project') || cfg.name.includes('Roadmap'))) {
window.timelineEngine.projectBasePath = 'my-project/';
console.log("Detected my-project, setting base path to my-project/");
} else {
window.timelineEngine.projectBasePath = '';
console.log("Unknown project, clearing base path");
}
} else {
window.timelineEngine.projectBasePath = '';
}
window.timelineEngine.updateFileStatus('project', file.name, 'loaded');
// Enable project edit button
if (window.fileEditor) {
window.fileEditor.enableEditButton('project');
}
await window.timelineEngine.loadProjectConfigObject(cfg);
// Show message about relative paths if project has data sources
if (cfg.dataSource || cfg.stylesheet || cfg.svgTemplate) {
const viewer = document.getElementById("viewer");
if (viewer && (viewer.innerHTML.includes("could not be loaded") || viewer.innerHTML.includes("Keine gültigen Items"))) {
viewer.innerHTML += "<br><br><em style='color:#6c757d; font-size:12px;'>💡 Hinweis: Stelle sicher, dass sich die referenzierten Dateien (CSV, CSS, SVG) im gleichen Verzeichnis wie die HTML-Datei befinden.</em>";
}
}
} catch (error) {
console.error("Error loading project:", error);
window.timelineEngine.updateFileStatus('project', file.name, 'error');
}
});
}
const csvInput = document.getElementById("csvInput");
if (csvInput) {
csvInput.addEventListener("change", async (ev) => {
const file = ev.target.files[0];
if (!file) return;
const text = await file.text();
window.timelineEngine.csvOverride = true;
window.timelineEngine.updateFileStatus('csv', file.name, 'loaded');
// Enable CSV edit button
if (window.fileEditor) {
window.fileEditor.enableEditButton('csv');
}
window.timelineEngine.processCsv(text);
});
}
const cssInput = document.getElementById("cssInput");
if (cssInput) {
cssInput.addEventListener("change", async (ev) => {
const file = ev.target.files[0];
if (!file) return;
const cssText = await file.text();
window.timelineEngine.cssData = cssText; // Store for editing
window.timelineEngine.cssOverride = true;
const blob = new Blob([cssText], { type: "text/css" });
document.getElementById("dynamicCss").href = URL.createObjectURL(blob);
window.timelineEngine.updateFileStatus('css', file.name, 'loaded');
// Enable CSS edit button
if (window.fileEditor) {
window.fileEditor.enableEditButton('css');
}
});
}
const svgInput = document.getElementById("svgInput");
if (svgInput) {
svgInput.addEventListener("change", async (ev) => {
const file = ev.target.files[0];
if (!file) return;
window.timelineEngine.template = await file.text();
window.timelineEngine.updateFileStatus('svg', file.name, 'loaded');
// Enable SVG edit button
if (window.fileEditor) {
window.fileEditor.enableEditButton('svg');
}
// Show template fields in debug panel
window.timelineEngine.showTemplateFields();
// Show template preview immediately when manually loaded
window.timelineEngine.showTemplatePreview();
});
}
// Individual file inputs removed - use folder picker instead
const downloadSvg = document.getElementById("downloadSvg");
if (downloadSvg) {