Fixes for erDiagram, pie charts and journey diagram

This commit is contained in:
Knut Sveidqvist 2022-07-04 18:11:58 +02:00
parent 5318ec6dbf
commit 682a1404ca
6 changed files with 81 additions and 67 deletions

View File

@ -30,15 +30,16 @@
<div class="mermaid2" style="width: 50%;">
journey
title Adding journey diagram functionality to mermaid
accTitle: Adding acc journey diagram functionality to mermaid
accDescr {
My multi-line description
of the diagram
}
section Order from website
<div class="mermaid" style="width: 50%;">
journey
title My working day
section Go to work
Make tea: 5: Me
Go upstairs: 3: Me
Do work: 1: Me, Cat
section Go home
Go downstairs: 5: Me
Sit down: 5: Mee
</div>
<div class="mermaid2" style="width: 50%;">
pie
@ -135,7 +136,7 @@ requirementDiagram
test_req - contains -> test_req3
test_req <- copies - test_entity2
</div>
<div class="mermaid" style="width: 100%;">
<div class="mermaid2" style="width: 100%;">
gantt
dateFormat YYYY-MM-DD
title Adding GANTT diagram functionality to mermaid
@ -242,6 +243,21 @@ class Class10 {
+run()
}
</div>
<div class="mermaid2" style="width: 100%;">
erDiagram
CAR ||--o{ NAMED-DRIVER : allows
CAR {
string registrationNumber
string make
string model
}
PERSON ||--o{ NAMED-DRIVER : is
PERSON {
string firstName
string lastName
int age
}
</div>
<script src="./mermaid.js"></script>
<script>

View File

@ -159,9 +159,11 @@ class Diagram {
break;
case 'journey':
log.debug('Journey');
journeyRenderer.setConf(cnf.journey);
this.parser = journeyParser;
this.parser.parser.yy = journeyDb;
this.db = journeyDb;
this.db.clear();
this.renderer = journeyRenderer;
break;
case 'requirement':

View File

@ -1,7 +1,7 @@
import graphlib from 'graphlib';
import { line, curveBasis, select } from 'd3';
import erDb from './erDb';
import erParser from './parser/erDiagram';
// import erDb from './erDb';
// import erParser from './parser/erDiagram';
import dagre from 'dagre';
import { getConfig } from '../../config';
import { log } from '../../logger';
@ -9,7 +9,7 @@ import erMarkers from './erMarkers';
import { configureSvgSize } from '../../utils';
import addSVGAccessibilityFields from '../../accessibility';
const conf = {};
let conf = {};
/**
* Allows the top-level API module to inject config specific to this renderer, storing it in the
@ -409,8 +409,9 @@ let relCnt = 0;
* @param g The graph containing the edge information
* @param insert The insertion point in the svg DOM (because relationships have markers that need to
* sit 'behind' opaque entity boxes)
* @param diagObj
*/
const drawRelationshipFromLayout = function (svg, rel, g, insert) {
const drawRelationshipFromLayout = function (svg, rel, g, insert, diagObj) {
relCnt++;
// Find the edge relating to this relationship
@ -435,7 +436,7 @@ const drawRelationshipFromLayout = function (svg, rel, g, insert) {
.attr('fill', 'none');
// ...and with dashes if necessary
if (rel.relSpec.relType === erDb.Identification.NON_IDENTIFYING) {
if (rel.relSpec.relType === diagObj.db.Identification.NON_IDENTIFYING) {
svgPath.attr('stroke-dasharray', '8,8');
}
@ -457,40 +458,40 @@ const drawRelationshipFromLayout = function (svg, rel, g, insert) {
// Note that the 'A' entity's marker is at the end of the relationship and the 'B' entity's marker is at the start
switch (rel.relSpec.cardA) {
case erDb.Cardinality.ZERO_OR_ONE:
case diagObj.db.Cardinality.ZERO_OR_ONE:
svgPath.attr('marker-end', 'url(' + url + '#' + erMarkers.ERMarkers.ZERO_OR_ONE_END + ')');
break;
case erDb.Cardinality.ZERO_OR_MORE:
case diagObj.db.Cardinality.ZERO_OR_MORE:
svgPath.attr('marker-end', 'url(' + url + '#' + erMarkers.ERMarkers.ZERO_OR_MORE_END + ')');
break;
case erDb.Cardinality.ONE_OR_MORE:
case diagObj.db.Cardinality.ONE_OR_MORE:
svgPath.attr('marker-end', 'url(' + url + '#' + erMarkers.ERMarkers.ONE_OR_MORE_END + ')');
break;
case erDb.Cardinality.ONLY_ONE:
case diagObj.db.Cardinality.ONLY_ONE:
svgPath.attr('marker-end', 'url(' + url + '#' + erMarkers.ERMarkers.ONLY_ONE_END + ')');
break;
}
switch (rel.relSpec.cardB) {
case erDb.Cardinality.ZERO_OR_ONE:
case diagObj.db.Cardinality.ZERO_OR_ONE:
svgPath.attr(
'marker-start',
'url(' + url + '#' + erMarkers.ERMarkers.ZERO_OR_ONE_START + ')'
);
break;
case erDb.Cardinality.ZERO_OR_MORE:
case diagObj.db.Cardinality.ZERO_OR_MORE:
svgPath.attr(
'marker-start',
'url(' + url + '#' + erMarkers.ERMarkers.ZERO_OR_MORE_START + ')'
);
break;
case erDb.Cardinality.ONE_OR_MORE:
case diagObj.db.Cardinality.ONE_OR_MORE:
svgPath.attr(
'marker-start',
'url(' + url + '#' + erMarkers.ERMarkers.ONE_OR_MORE_START + ')'
);
break;
case erDb.Cardinality.ONLY_ONE:
case diagObj.db.Cardinality.ONLY_ONE:
svgPath.attr('marker-start', 'url(' + url + '#' + erMarkers.ERMarkers.ONLY_ONE_START + ')');
break;
}
@ -540,12 +541,14 @@ const drawRelationshipFromLayout = function (svg, rel, g, insert) {
*
* @param text The text of the diagram
* @param id The unique id of the DOM node that contains the diagram
* @param _version
* @param diag
* @param diagObj
*/
export const draw = function (text, id) {
export const draw = function (text, id, _version, diagObj) {
conf = getConfig().er;
log.info('Drawing ER diagram');
erDb.clear();
const parser = erParser.parser;
parser.yy = erDb;
// diag.db.clear();
const securityLevel = getConfig().securityLevel;
// Handle root and Document for when rendering in sanbox mode
let sandboxElement;
@ -556,14 +559,14 @@ export const draw = function (text, id) {
securityLevel === 'sandbox'
? select(sandboxElement.nodes()[0].contentDocument.body)
: select('body');
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
// const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
// Parse the text to populate erDb
try {
parser.parse(text);
} catch (err) {
log.debug('Parsing failed');
}
// try {
// parser.parse(text);
// } catch (err) {
// log.debug('Parsing failed');
// }
// Get a reference to the svg node that contains the text
const svg = root.select(`[id='${id}']`);
@ -612,12 +615,12 @@ export const draw = function (text, id) {
// Draw the entities (at 0,0), returning the first svg node that got
// inserted - this represents the insertion point for relationship paths
const firstEntity = drawEntities(svg, erDb.getEntities(), g);
const firstEntity = drawEntities(svg, diagObj.db.getEntities(), g);
// TODO: externalise the addition of entities to the graph - it's a bit 'buried' in the above
// Add all the relationships to the graph
const relationships = addRelationships(erDb.getRelationships(), g);
const relationships = addRelationships(diagObj.db.getRelationships(), g);
dagre.layout(g); // Node and edge positions will be updated
@ -626,7 +629,7 @@ export const draw = function (text, id) {
// Draw the relationships
relationships.forEach(function (rel) {
drawRelationshipFromLayout(svg, rel, g, firstEntity);
drawRelationshipFromLayout(svg, rel, g, firstEntity, diagObj);
});
const padding = conf.diagramPadding;
@ -639,7 +642,7 @@ export const draw = function (text, id) {
svg.attr('viewBox', `${svgBounds.x - padding} ${svgBounds.y - padding} ${width} ${height}`);
addSVGAccessibilityFields(parser.yy, svg, id);
addSVGAccessibilityFields(diagObj.db, svg, id);
}; // draw
export default {

View File

@ -1,7 +1,5 @@
/** Created by AshishJ on 11-09-2019. */
import { select, scaleOrdinal, pie as d3pie, arc } from 'd3';
import pieData from './pieDb';
import pieParser from './parser/pie';
import { log } from '../../logger';
import { configureSvgSize } from '../../utils';
import * as configApi from '../../config';
@ -17,11 +15,9 @@ let conf = configApi.getConfig();
*/
let width;
const height = 450;
export const draw = (txt, id) => {
export const draw = (txt, id, _version, diagObj) => {
try {
conf = configApi.getConfig();
const parser = pieParser.parser;
parser.yy = pieData;
log.debug('Rendering info diagram\n' + txt);
const securityLevel = configApi.getConfig().securityLevel;
@ -37,8 +33,8 @@ export const draw = (txt, id) => {
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
// Parse the Pie Chart definition
parser.yy.clear();
parser.parse(txt);
diagObj.db.clear();
diagObj.parser.parse(txt);
log.debug('Parsed info diagram');
const elem = doc.getElementById(id);
width = elem.parentElement.offsetWidth;
@ -57,7 +53,7 @@ export const draw = (txt, id) => {
const diagram = root.select('#' + id);
configureSvgSize(diagram, height, width, conf.pie.useMaxWidth);
addSVGAccessibilityFields(parser.yy, diagram, id);
addSVGAccessibilityFields(diagObj.db, diagram, id);
// Set viewBox
elem.setAttribute('viewBox', '0 0 ' + width + ' ' + height);
@ -72,7 +68,7 @@ export const draw = (txt, id) => {
.append('g')
.attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')');
var data = pieData.getSections();
var data = diagObj.db.getSections();
var sum = 0;
Object.keys(data).forEach(function (key) {
sum += data[key];
@ -136,7 +132,7 @@ export const draw = (txt, id) => {
svg
.append('text')
.text(parser.yy.getDiagramTitle())
.text(diagObj.db.getDiagramTitle())
.attr('x', 0)
.attr('y', -(height - 50) / 2)
.attr('class', 'pieTitleText');
@ -169,7 +165,7 @@ export const draw = (txt, id) => {
.attr('x', legendRectSize + legendSpacing)
.attr('y', legendRectSize - legendSpacing)
.text(function (d) {
if (parser.yy.getShowData() || conf.showData || conf.pie.showData) {
if (diagObj.db.getShowData() || conf.showData || conf.pie.showData) {
return d.data[0] + ' [' + d.data[1] + ']';
} else {
return d.data[0];

View File

@ -1,13 +1,9 @@
import { select } from 'd3';
import { parser } from './parser/journey';
import journeyDb from './journeyDb';
import svgDraw from './svgDraw';
import { getConfig } from '../../config';
import { configureSvgSize } from '../../utils';
import addSVGAccessibilityFields from '../../accessibility';
parser.yy = journeyDb;
export const setConf = function (cnf) {
const keys = Object.keys(cnf);
@ -50,10 +46,10 @@ function drawActorLegend(diagram) {
}
const conf = getConfig().journey;
const LEFT_MARGIN = getConfig().journey.leftMargin;
export const draw = function (text, id) {
export const draw = function (text, id, version, diagObj) {
const conf = getConfig().journey;
parser.yy.clear();
parser.parse(text + '\n');
diagObj.db.clear();
diagObj.parser.parse(text + '\n');
const securityLevel = getConfig().securityLevel;
// Handle root and Document for when rendering in sanbox mode
@ -65,17 +61,18 @@ export const draw = function (text, id) {
securityLevel === 'sandbox'
? select(sandboxElement.nodes()[0].contentDocument.body)
: select('body');
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
// const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
bounds.init();
const diagram = root.select('#' + id);
svgDraw.initGraphics(diagram);
const tasks = parser.yy.getTasks();
const title = parser.yy.getDiagramTitle();
const tasks = diagObj.db.getTasks();
console.log('text and tasks', text, tasks);
const title = diagObj.db.getDiagramTitle();
const actorNames = parser.yy.getActors();
const actorNames = diagObj.db.getActors();
for (let member in actors) delete actors[member];
let actorPos = 0;
actorNames.forEach((actorName) => {
@ -122,7 +119,7 @@ export const draw = function (text, id) {
diagram.attr('preserveAspectRatio', 'xMinYMin meet');
diagram.attr('height', height + extraVertForTitle + 25);
addSVGAccessibilityFields(parser.yy, diagram, id);
addSVGAccessibilityFields(diagObj.db, diagram, id);
};
export const bounds = {

View File

@ -380,8 +380,8 @@ const render = function (id, _txt, cb, container) {
break;
case 'gantt':
cnf.gantt.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
ganttRenderer.setConf(cnf.gantt);
ganttRenderer.draw(txt, id, pkg.version, diag);
diag.renderer.setConf(cnf.gantt);
diag.renderer.draw(txt, id, pkg.version, diag);
break;
case 'class':
cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
@ -409,15 +409,15 @@ const render = function (id, _txt, cb, container) {
infoRenderer.draw(txt, id, pkg.version, diag);
break;
case 'pie':
pieRenderer.draw(txt, id, pkg.version, diag);
diag.renderer.draw(txt, id, pkg.version, diag);
break;
case 'er':
erRenderer.setConf(cnf.er);
erRenderer.draw(txt, id, pkg.version, diag);
// erRenderer.setConf(cnf.er);
diag.renderer.draw(txt, id, pkg.version, diag);
break;
case 'journey':
journeyRenderer.setConf(cnf.journey);
journeyRenderer.draw(txt, id, pkg.version, diag);
// journeyRenderer.setConf(cnf.journey);
diag.renderer.draw(txt, id, pkg.version, diag);
break;
case 'requirement':
requirementRenderer.setConf(cnf.requirement);