165 lines
6.6 KiB
JavaScript
165 lines
6.6 KiB
JavaScript
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;
|