Files

165 lines
6.6 KiB
JavaScript
Raw Permalink Normal View History

const express = require('express');
const router = express.Router();
const { getDb } = require('../db');
const { parseDiagramJson, DIAGRAM_TYPE_LABELS } = require('../lib/rack-diagram');
router.get('/designer', (req, res) => {
const db = getDb();
const clients = db.prepare('SELECT id, name FROM clients ORDER BY name').all();
const clientId = req.query.client_id || req.session.activeClientId || null;
const host = process.env.BASE_URL || `http://${req.hostname}:3000`;
const designerBase = host.replace(':3000', ':3001') + '/python-editor/';
res.render('designer-embed', { clients, clientId, designerUrl: designerBase });
});
router.get('/', (req, res) => {
const db = getDb();
const { search, client_id, diagram_type } = req.query;
let sql = `SELECT d.*, c.name as client_name,
json_array_length(d.nodes) as node_count
FROM data_diagrams d JOIN clients c ON c.id = d.client_id WHERE 1=1`;
const params = [];
if (search) {
sql += ` AND (d.name LIKE ? OR d.description LIKE ?)`;
params.push(`%${search}%`, `%${search}%`);
}
if (client_id) {
sql += ` AND d.client_id = ?`;
params.push(client_id);
}
if (diagram_type) {
sql += ` AND d.diagram_type = ?`;
params.push(diagram_type);
}
sql += ` ORDER BY d.updated_at DESC`;
const diagrams = db.prepare(sql).all(...params);
const clients = db.prepare('SELECT id, name FROM clients ORDER BY name').all();
res.render('arch-list', { diagrams, clients, filters: req.query });
});
router.get('/new', (req, res) => {
const db = getDb();
const clients = db.prepare('SELECT id, name FROM clients ORDER BY name').all();
res.render('arch-editor', { diagram: null, clients, clientId: null, rack: null, rackDevices: [], linkedDiagrams: [], defaultDiagramType: null, error: null });
});
router.get('/new/:clientId', (req, res) => {
const db = getDb();
const clients = db.prepare('SELECT id, name FROM clients ORDER BY name').all();
res.render('arch-editor', { diagram: null, clients, clientId: parseInt(req.params.clientId), rack: null, rackDevices: [], linkedDiagrams: [], defaultDiagramType: null, error: null });
});
router.post('/save', (req, res) => {
const db = getDb();
const { id, client_id, name, description, diagram_type, nodes, edges, rack_id } = req.body;
if (!name || !client_id) return res.status(400).json({ error: 'Name and client required' });
if (id) {
db.prepare("UPDATE data_diagrams SET name=?, description=?, diagram_type=?, nodes=?, edges=?, rack_id=?, updated_at=datetime('now') WHERE id=?")
.run(name, description, diagram_type || 'data_architecture', nodes || '[]', edges || '[]', rack_id || null, id);
res.json({ id: parseInt(id, 10) });
} else {
const result = db.prepare('INSERT INTO data_diagrams (client_id, name, description, diagram_type, nodes, edges, rack_id) VALUES (?,?,?,?,?,?,?)')
.run(client_id, name, description, diagram_type || 'data_architecture', nodes || '[]', edges || '[]', rack_id || null);
res.json({ id: result.lastInsertRowid });
}
});
router.get('/:id', (req, res) => {
const db = getDb();
const diagram = db.prepare('SELECT d.*, c.name as client_name FROM data_diagrams d JOIN clients c ON c.id = d.client_id WHERE d.id = ?').get(req.params.id);
if (!diagram) return res.redirect('/architecture');
if (diagram.rack_id && !req.query.embed && req.query.stay !== '1') {
return res.redirect('/racks/' + diagram.rack_id + '/diagram/' + diagram.id);
}
const clients = db.prepare('SELECT id, name FROM clients ORDER BY name').all();
let rack = null;
let rackDevices = [];
let linkedDiagrams = [];
let flowDiagram = null;
let landscapeDiagram = null;
if (diagram.rack_id) {
rack = db.prepare('SELECT r.*, c.name as client_name FROM racks r JOIN clients c ON c.id = r.client_id WHERE r.id = ?').get(diagram.rack_id);
rackDevices = db.prepare('SELECT * FROM rack_devices WHERE rack_id = ? ORDER BY position_u ASC').all(diagram.rack_id);
linkedDiagrams = db.prepare('SELECT id, name, diagram_type FROM data_diagrams WHERE rack_id = ?').all(diagram.rack_id);
flowDiagram = linkedDiagrams.find(d => d.diagram_type === 'application_flow') || null;
landscapeDiagram = linkedDiagrams.find(d => d.diagram_type === 'application_landscape') || null;
}
const { getWorkspaceTab } = require('../lib/rack-diagram');
res.render('arch-editor', {
diagram,
clients,
clientId: diagram.client_id,
rack,
rackDevices,
linkedDiagrams,
flowDiagram,
landscapeDiagram,
defaultDiagramType: null,
workspaceTab: rack ? getWorkspaceTab(diagram.diagram_type) : null,
embed: req.query.embed === '1',
error: null
});
});
router.post('/:id/delete', (req, res) => {
const db = getDb();
db.prepare('DELETE FROM data_diagrams WHERE id = ?').run(req.params.id);
res.redirect('/architecture');
});
router.get('/report/:id', (req, res) => {
const db = getDb();
const diagram = db.prepare('SELECT d.*, c.name as client_name FROM data_diagrams d JOIN clients c ON c.id = d.client_id WHERE d.id = ?').get(req.params.id);
if (!diagram) return res.redirect('/architecture');
if (diagram.rack_id) return res.redirect('/racks/' + diagram.rack_id + '/report');
let nodes = JSON.parse(diagram.nodes);
let edges = JSON.parse(diagram.edges);
if (!Array.isArray(nodes) && nodes && nodes.nodes) { edges = nodes.edges || []; nodes = nodes.nodes || []; }
if (!Array.isArray(edges) && edges && edges.nodes) { nodes = edges.nodes || []; edges = edges.edges || []; }
const typeCount = {};
const vendorCount = {};
nodes.forEach(n => {
typeCount[n.type ? n.type.split('-')[0] : 'other'] = (typeCount[n.type ? n.type.split('-')[0] : 'other'] || 0) + 1;
if (n.vendor) vendorCount[n.vendor] = (vendorCount[n.vendor] || 0) + 1;
});
res.render('arch-report', { diagram, nodes, edges, typeCount, vendorCount });
});
router.get('/render/:id', (req, res) => {
const db = getDb();
const diagram = db.prepare('SELECT * FROM data_diagrams WHERE id = ?').get(req.params.id);
if (!diagram) return res.status(404).json({ error: 'not found' });
let nodes = JSON.parse(diagram.nodes);
let edges = JSON.parse(diagram.edges);
// Handle legacy Python-editor format: nodes/edges columns store {"nodes":[...],"edges":[...]}
if (!Array.isArray(nodes) && nodes && nodes.nodes) {
edges = nodes.edges || [];
nodes = nodes.nodes || [];
}
if (!Array.isArray(edges) && edges && edges.nodes) {
nodes = edges.nodes || [];
edges = edges.edges || [];
}
res.json({
name: diagram.name,
description: diagram.description,
diagram_type: diagram.diagram_type,
nodes,
edges
});
});
module.exports = router;