feat(arch): dynamic node sizing

This commit is contained in:
NicolasNewman
2024-03-25 14:17:05 -05:00
parent 5e214877a4
commit a493e2fbb3
5 changed files with 33 additions and 22 deletions

View File

@@ -638,7 +638,7 @@ export interface RequirementDiagramConfig extends BaseDiagramConfig {
*/
export interface ArchitectureDiagramConfig extends BaseDiagramConfig {
padding?: number;
maxNodeWidth?: number;
iconSize?: number;
}
/**
* The object containing configurations specific for mindmap diagrams

View File

@@ -6,6 +6,7 @@ import type {
ArchitectureDirection,
ArchitectureLine,
} from './architectureTypes.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
import { isArchitectureDirection } from './architectureTypes.js';
import {
setAccTitle,
@@ -36,10 +37,6 @@ let lines = DEFAULT_ARCHITECTURE_DB.lines;
let elements: Record<string, D3Element> = {};
let cnt = DEFAULT_ARCHITECTURE_DB.cnt;
const config: Required<ArchitectureDiagramConfig> = structuredClone(DEFAULT_ARCHITECTURE_CONFIG);
const getConfig = (): Required<ArchitectureDiagramConfig> => structuredClone(config);
const clear = (): void => {
services = structuredClone(DEFAULT_ARCHITECTURE_DB.services);
groups = structuredClone(DEFAULT_ARCHITECTURE_DB.groups);
@@ -109,7 +106,6 @@ const setElementForId = (id: string, element: D3Element) => {
const getElementById = (id: string) => elements[id];
export const db: ArchitectureDB = {
getConfig,
clear,
setDiagramTitle,
getDiagramTitle,
@@ -127,3 +123,14 @@ export const db: ArchitectureDB = {
setElementForId,
getElementById,
};
function getConfigField<T extends keyof ArchitectureDiagramConfig>(field: T): Required<ArchitectureDiagramConfig>[T] {
const arch = getConfig().architecture;
if (arch && arch[field] !== undefined) {
const a = arch[field];
return arch[field] as Required<ArchitectureDiagramConfig>[T]
}
return DEFAULT_ARCHITECTURE_CONFIG[field]
}
export { getConfigField }

View File

@@ -17,9 +17,9 @@ import {
} from './architectureTypes.js';
import { select } from 'd3';
import { setupGraphViewbox } from '../../setupGraphViewbox.js';
import defaultConfig from '../../defaultConfig.js';
import type { D3Element } from '../../mermaidAPI.js';
import { drawEdges, drawGroups, drawService } from './svgDraw.js';
import { getConfigField } from './architectureDb.js';
cytoscape.use(fcose);
@@ -33,9 +33,8 @@ function addServices(services: ArchitectureService[], cy: cytoscape.Core) {
icon: service.icon,
label: service.title,
parent: service.in,
// TODO: dynamic size
width: 80,
height: 80,
width: getConfigField('iconSize'),
height: getConfigField('iconSize'),
},
classes: 'node-service',
});
@@ -286,8 +285,8 @@ export const draw: DrawDefinition = async (text, id, _version, diagObj: Diagram)
setupGraphViewbox(
undefined,
svg,
conf.architecture?.padding ?? defaultConfig.architecture.padding,
conf.architecture?.useMaxWidth ?? defaultConfig.architecture.useMaxWidth
getConfigField('padding'),
getConfigField('useMaxWidth')
);
};

View File

@@ -8,6 +8,7 @@ import type { MermaidConfig } from '../../config.type.js';
import type cytoscape from 'cytoscape';
import { log } from '../../logger.js';
import { getIcon, isIconNameInUse } from '../../rendering-util/svgRegister.js';
import { getConfigField } from './architectureDb.js';
declare module 'cytoscape' {
interface EdgeSingular {
@@ -76,20 +77,23 @@ export const drawEdges = function (edgesEl: D3Element, cy: cytoscape.Core) {
};
export const drawGroups = function (groupsEl: D3Element, cy: cytoscape.Core) {
const iconSize = getConfigField('iconSize')
const halfIconSize = iconSize / 2
cy.nodes().map((node, id) => {
const data = node.data();
if (data.type === 'group') {
const { h, w, x1, x2, y1, y2 } = node.boundingBox();
let bkgElem = groupsEl
.append('rect')
.attr('x', x1 + 40)
.attr('y', y1 + 40)
.attr('x', x1 + halfIconSize)
.attr('y', y1 + halfIconSize)
.attr('width', w)
.attr('height', h)
.attr('class', 'node-bkg');
const textElem = groupsEl.append('g');
createText(textElem, data.title, {
createText(textElem, data.label, {
useHtmlLabels: false,
width: w,
classes: 'architecture-service-label',
@@ -100,7 +104,7 @@ export const drawGroups = function (groupsEl: D3Element, cy: cytoscape.Core) {
.attr('dominant-baseline', 'start')
.attr('text-anchor', 'start');
textElem.attr('transform', 'translate(' + (x1 + 44) + ', ' + (y1 + 42) + ')');
textElem.attr('transform', 'translate(' + (x1 + halfIconSize + 4) + ', ' + (y1 + halfIconSize + 2) + ')');
}
});
};
@@ -112,6 +116,7 @@ export const drawService = function (
conf: MermaidConfig
): number {
const serviceElem = elem.append('g');
const iconSize = getConfigField('iconSize')
if (service.title) {
const textElem = serviceElem.append('g');
@@ -129,7 +134,7 @@ export const drawService = function (
textElem.attr(
'transform',
// TODO: dynamic size
'translate(' + 80 / 2 + ', ' + 80 + ')'
'translate(' + (iconSize / 2) + ', ' + iconSize + ')'
);
}
@@ -138,13 +143,13 @@ export const drawService = function (
if (!isIconNameInUse(service.icon)) {
throw new Error(`Invalid SVG Icon name: "${service.icon}"`);
}
bkgElem = getIcon(service.icon)?.(bkgElem);
bkgElem = getIcon(service.icon)?.(bkgElem, iconSize);
} else {
bkgElem
.append('path')
.attr('class', 'node-bkg')
.attr('id', 'node-' + service.id)
.attr('d', `M0 ${80 - 0} v${-80 + 2 * 0} q0,-5 5,-5 h${80 - 2 * 0} q5,0 5,5 v${80 - 0} H0 Z`);
.attr('d', `M0 ${iconSize - 0} v${-iconSize + 2 * 0} q0,-5 5,-5 h${iconSize - 2 * 0} q5,0 5,5 v${iconSize - 0} H0 Z`);
}
serviceElem.attr('class', 'architecture-service');

View File

@@ -865,14 +865,14 @@ $defs: # JSON Schema definition (maybe we should move these to a separate file)
required:
- useMaxWidth
- padding
- maxNodeWidth
- iconSize
properties:
padding:
type: number
default: 10
maxNodeWidth:
iconSize:
type: number
default: 200
default: 80
MindmapDiagramConfig:
title: Mindmap Diagram Config