Files
TaskMate/backend/routes/import.js
Claude Project Manager ab1e5be9a9 Initial commit
2025-12-28 21:36:45 +00:00

270 Zeilen
7.3 KiB
JavaScript

/**
* TASKMATE - Import Routes
* ========================
* Import von JSON-Backups
*/
const express = require('express');
const router = express.Router();
const { getDb } = require('../database');
const logger = require('../utils/logger');
/**
* POST /api/import/project
* Projekt aus JSON importieren
*/
router.post('/project', (req, res) => {
try {
const { data, overwrite = false } = req.body;
if (!data || !data.project) {
return res.status(400).json({ error: 'Ungültiges Import-Format' });
}
const db = getDb();
// Transaktion starten
const importProject = db.transaction(() => {
const importData = data;
// Projekt erstellen
const projectResult = db.prepare(`
INSERT INTO projects (name, description, created_by)
VALUES (?, ?, ?)
`).run(
importData.project.name + (overwrite ? '' : ' (Import)'),
importData.project.description,
req.user.id
);
const newProjectId = projectResult.lastInsertRowid;
// Mapping für alte -> neue IDs
const columnMap = new Map();
const labelMap = new Map();
const taskMap = new Map();
// Spalten importieren
if (importData.columns) {
const insertColumn = db.prepare(`
INSERT INTO columns (project_id, name, position, color)
VALUES (?, ?, ?, ?)
`);
importData.columns.forEach(col => {
const result = insertColumn.run(newProjectId, col.name, col.position, col.color);
columnMap.set(col.id, result.lastInsertRowid);
});
}
// Labels importieren
if (importData.labels) {
const insertLabel = db.prepare(`
INSERT INTO labels (project_id, name, color)
VALUES (?, ?, ?)
`);
importData.labels.forEach(label => {
const result = insertLabel.run(newProjectId, label.name, label.color);
labelMap.set(label.id, result.lastInsertRowid);
});
}
// Aufgaben importieren
if (importData.tasks) {
const insertTask = db.prepare(`
INSERT INTO tasks (
project_id, column_id, title, description, priority,
due_date, time_estimate_min, position, created_by
)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
`);
importData.tasks.forEach(task => {
const newColumnId = columnMap.get(task.column_id);
if (!newColumnId) return;
const result = insertTask.run(
newProjectId,
newColumnId,
task.title,
task.description,
task.priority || 'medium',
task.due_date,
task.time_estimate_min,
task.position,
req.user.id
);
taskMap.set(task.id, result.lastInsertRowid);
// Task-Labels
if (task.labels) {
const insertTaskLabel = db.prepare(
'INSERT INTO task_labels (task_id, label_id) VALUES (?, ?)'
);
task.labels.forEach(label => {
const newLabelId = labelMap.get(label.id);
if (newLabelId) {
try {
insertTaskLabel.run(result.lastInsertRowid, newLabelId);
} catch (e) { /* Ignorieren */ }
}
});
}
// Subtasks
if (task.subtasks) {
const insertSubtask = db.prepare(
'INSERT INTO subtasks (task_id, title, completed, position) VALUES (?, ?, ?, ?)'
);
task.subtasks.forEach(st => {
insertSubtask.run(
result.lastInsertRowid,
st.title,
st.completed ? 1 : 0,
st.position
);
});
}
// Links
if (task.links) {
const insertLink = db.prepare(
'INSERT INTO links (task_id, title, url, created_by) VALUES (?, ?, ?, ?)'
);
task.links.forEach(link => {
insertLink.run(result.lastInsertRowid, link.title, link.url, req.user.id);
});
}
});
}
// Vorlagen importieren
if (importData.templates) {
const insertTemplate = db.prepare(`
INSERT INTO task_templates (
project_id, name, title_template, description,
priority, labels, subtasks, time_estimate_min
)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
`);
importData.templates.forEach(tmpl => {
// Labels-IDs mappen
let newLabels = null;
if (tmpl.labels) {
const oldLabels = typeof tmpl.labels === 'string' ? JSON.parse(tmpl.labels) : tmpl.labels;
const mappedLabels = oldLabels.map(id => labelMap.get(id)).filter(id => id);
newLabels = JSON.stringify(mappedLabels);
}
insertTemplate.run(
newProjectId,
tmpl.name,
tmpl.title_template,
tmpl.description,
tmpl.priority,
newLabels,
tmpl.subtasks,
tmpl.time_estimate_min
);
});
}
return {
projectId: newProjectId,
columnsImported: columnMap.size,
labelsImported: labelMap.size,
tasksImported: taskMap.size
};
});
const result = importProject();
logger.info(`Projekt importiert: ID ${result.projectId} (${result.tasksImported} Aufgaben)`);
res.status(201).json({
message: 'Import erfolgreich',
...result
});
} catch (error) {
logger.error('Fehler beim Import:', { error: error.message });
res.status(500).json({ error: 'Import fehlgeschlagen: ' + error.message });
}
});
/**
* POST /api/import/validate
* Import-Datei validieren
*/
router.post('/validate', (req, res) => {
try {
const { data } = req.body;
const errors = [];
const warnings = [];
if (!data) {
errors.push('Keine Daten vorhanden');
return res.json({ valid: false, errors, warnings });
}
// Version prüfen
if (!data.version) {
warnings.push('Keine Versionsangabe gefunden');
}
// Projekt prüfen
if (!data.project) {
errors.push('Kein Projekt in den Daten gefunden');
} else {
if (!data.project.name) {
errors.push('Projektname fehlt');
}
}
// Spalten prüfen
if (!data.columns || data.columns.length === 0) {
errors.push('Keine Spalten in den Daten gefunden');
}
// Aufgaben prüfen
if (data.tasks) {
data.tasks.forEach((task, idx) => {
if (!task.title) {
warnings.push(`Aufgabe ${idx + 1} hat keinen Titel`);
}
if (!task.column_id) {
warnings.push(`Aufgabe "${task.title || idx + 1}" hat keine Spalten-ID`);
}
});
}
// Statistiken
const stats = {
projectName: data.project?.name || 'Unbekannt',
columns: data.columns?.length || 0,
labels: data.labels?.length || 0,
tasks: data.tasks?.length || 0,
templates: data.templates?.length || 0
};
res.json({
valid: errors.length === 0,
errors,
warnings,
stats
});
} catch (error) {
logger.error('Fehler bei Import-Validierung:', { error: error.message });
res.status(400).json({
valid: false,
errors: ['Ungültiges JSON-Format'],
warnings: []
});
}
});
module.exports = router;