mirror of
https://github.com/sotam0316/drawNET.git
synced 2026-04-25 20:18:37 +09:00
139 lines
5.5 KiB
JavaScript
139 lines
5.5 KiB
JavaScript
import { state } from '../../../state.js';
|
|
import { shapeRegistry } from '../registry.js';
|
|
import { getLabelAttributes, generateRackUnitsPath } from '../utils.js';
|
|
import { DEFAULTS } from '../../../constants.js';
|
|
import { calculateCellZIndex } from '../../layers.js';
|
|
|
|
/**
|
|
* getX6NodeConfig - Maps data properties to X6 node attributes using ShapeRegistry
|
|
*/
|
|
export function getX6NodeConfig(data) {
|
|
const nodeType = (data.type || '').toLowerCase();
|
|
|
|
// 1. Find the plugin in the registry
|
|
let plugin = shapeRegistry.get(nodeType);
|
|
|
|
// Fallback for generic types if not found by direct name
|
|
if (!plugin) {
|
|
if (nodeType === 'rectangle') plugin = shapeRegistry.get('rect');
|
|
else if (nodeType === 'blank') plugin = shapeRegistry.get('dummy');
|
|
}
|
|
|
|
// Default to 'default' plugin if still not found
|
|
if (!plugin) plugin = shapeRegistry.get('default');
|
|
|
|
// 2. Resolve asset path (Skip for groups and primitives!)
|
|
const primitives = ['rect', 'circle', 'ellipse', 'rounded-rect', 'text-box', 'label', 'dot', 'dummy', 'rack', 'triangle', 'diamond', 'parallelogram', 'cylinder', 'document', 'manual-input', 'table', 'user', 'admin', 'hourglass', 'polyline'];
|
|
let assetPath = `/static/assets/${DEFAULTS.DEFAULT_ICON}`;
|
|
|
|
if (data.is_group || primitives.includes(nodeType)) {
|
|
assetPath = undefined;
|
|
} else if (plugin.shape === 'drawnet-node' || plugin.type === 'default' || !plugin.icon) {
|
|
const currentPath = data.assetPath || data.asset_path;
|
|
if (currentPath) {
|
|
assetPath = currentPath.startsWith('/static/assets/') ? currentPath : `/static/assets/${currentPath}`;
|
|
} else {
|
|
const matchedAsset = state.assetsData?.find(a => {
|
|
const searchType = (a.type || '').toLowerCase();
|
|
const searchId = (a.id || '').toLowerCase();
|
|
return nodeType === searchType || nodeType === searchId ||
|
|
nodeType.includes(searchType) || nodeType.includes(searchId);
|
|
});
|
|
|
|
if (matchedAsset) {
|
|
const iconFileName = matchedAsset.path || (matchedAsset.views && matchedAsset.views.icon) || DEFAULTS.DEFAULT_ICON;
|
|
assetPath = `/static/assets/${iconFileName}`;
|
|
data.assetPath = iconFileName;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 3. Build Base Configuration
|
|
let config = {
|
|
id: data.id,
|
|
shape: plugin.shape,
|
|
position: data.pos ? { x: data.pos.x, y: data.pos.y } : { x: 100, y: 100 },
|
|
zIndex: data.zIndex || calculateCellZIndex(data, 0, true),
|
|
movable: !data.locked,
|
|
deletable: !data.locked,
|
|
data: data,
|
|
attrs: {
|
|
label: {
|
|
text: data.label || '',
|
|
fill: data.color || data['text-color'] || '#64748b',
|
|
...getLabelAttributes(data.label_pos || data['label-pos'], nodeType, data.is_group)
|
|
}
|
|
}
|
|
};
|
|
|
|
// 4. Plugin Specific Overrides
|
|
if (data.is_group) {
|
|
config.attrs.body = {
|
|
fill: data.background || '#f1f5f9',
|
|
stroke: data['border-color'] || '#3b82f6'
|
|
};
|
|
} else if (plugin.shape === 'drawnet-icon' && plugin.icon) {
|
|
config.attrs.icon = {
|
|
text: plugin.icon,
|
|
fill: data.color || '#64748b'
|
|
};
|
|
} else if (plugin.shape === 'drawnet-node') {
|
|
config.attrs.image = { 'xlink:href': assetPath };
|
|
}
|
|
|
|
// 5. Primitive Styling Persistence
|
|
if (primitives.includes(nodeType)) {
|
|
if (!config.attrs.body) config.attrs.body = {};
|
|
if (data.fill) config.attrs.body.fill = data.fill;
|
|
if (data.border) config.attrs.body.stroke = data.border;
|
|
}
|
|
|
|
// Rack specific handling
|
|
if (nodeType === 'rack') {
|
|
const slots = data.slots || 42;
|
|
const height = data.height || 600;
|
|
config.data.is_group = true;
|
|
config.attrs = {
|
|
...config.attrs,
|
|
units: { d: generateRackUnitsPath(height, slots) },
|
|
label: { text: data.label || `Rack (${slots}U)` }
|
|
};
|
|
}
|
|
|
|
// Rich Card specific handling
|
|
if (nodeType === 'rich-card' || plugin.shape === 'drawnet-rich-card') {
|
|
config.data.headerText = data.headerText || data.label || 'RICH INFO CARD';
|
|
config.data.content = data.content || '1. Content goes here...\n2. Support multiple lines';
|
|
config.data.cardType = data.cardType || 'numbered';
|
|
config.data.headerColor = data.headerColor || '#3b82f6';
|
|
config.data.headerAlign = data.headerAlign || 'left';
|
|
config.data.contentAlign = data.contentAlign || 'left';
|
|
|
|
const hAnchor = config.data.headerAlign === 'center' ? 'middle' : (config.data.headerAlign === 'right' ? 'end' : 'start');
|
|
const hX = config.data.headerAlign === 'center' ? 0.5 : (config.data.headerAlign === 'right' ? '100%' : 10);
|
|
const hX2 = config.data.headerAlign === 'right' ? -10 : 0;
|
|
|
|
config.attrs = {
|
|
...config.attrs,
|
|
headerLabel: {
|
|
text: config.data.headerText,
|
|
textAnchor: hAnchor,
|
|
refX: hX,
|
|
refX2: hX2
|
|
},
|
|
header: { fill: config.data.headerColor },
|
|
body: { stroke: config.data.headerColor }
|
|
};
|
|
|
|
// Initial render trigger (Hack: X6 might not be ready, so we defer)
|
|
setTimeout(() => {
|
|
const cell = state.graph.getCellById(config.id);
|
|
if (cell) {
|
|
import('../utils.js').then(m => m.renderRichContent(cell));
|
|
}
|
|
}, 50);
|
|
}
|
|
|
|
return config;
|
|
}
|