Merge pull request #4126 from mermaid-js/sidv/timelineSectionWidth

💄 section width now covers all tasks - Timeline
This commit is contained in:
Knut Sveidqvist
2023-02-28 11:59:14 +01:00
committed by GitHub
2 changed files with 73 additions and 42 deletions

View File

@@ -295,6 +295,7 @@ export interface TimelineDiagramConfig extends BaseDiagramConfig {
leftMargin?: number; leftMargin?: number;
width?: number; width?: number;
height?: number; height?: number;
padding?: number;
boxMargin?: number; boxMargin?: number;
boxTextMargin?: number; boxTextMargin?: number;
noteMargin?: number; noteMargin?: number;
@@ -311,6 +312,7 @@ export interface TimelineDiagramConfig extends BaseDiagramConfig {
sectionFills?: string[]; sectionFills?: string[];
sectionColours?: string[]; sectionColours?: string[];
disableMulticolor?: boolean; disableMulticolor?: boolean;
useMaxWidth?: boolean;
} }
export interface GanttDiagramConfig extends BaseDiagramConfig { export interface GanttDiagramConfig extends BaseDiagramConfig {

View File

@@ -1,25 +1,37 @@
// @ts-nocheck TODO: fix file // @ts-ignore - db not typed yet
import { select } from 'd3'; import { select, Selection } from 'd3';
import svgDraw from './svgDraw'; import svgDraw from './svgDraw';
import { log } from '../../logger'; import { log } from '../../logger';
import { getConfig } from '../../config'; import { getConfig } from '../../config';
import { setupGraphViewbox } from '../../setupGraphViewbox'; import { setupGraphViewbox } from '../../setupGraphViewbox';
import { Diagram } from '../../Diagram';
import { MermaidConfig } from '../../config.type';
export const setConf = function (cnf) { interface Block<TDesc, TSection> {
const keys = Object.keys(cnf); number: number;
descr: TDesc;
section: TSection;
width: number;
padding: number;
maxHeight: number;
}
keys.forEach(function (key) { interface TimelineTask {
conf[key] = cnf[key]; id: number;
}); section: string;
}; type: string;
task: string;
export const draw = function (text, id, version, diagObj) { score: number;
events: string[];
}
export const draw = function (text: string, id: string, version: string, diagObj: Diagram) {
//1. Fetch the configuration //1. Fetch the configuration
const conf = getConfig(); const conf = getConfig();
const LEFT_MARGIN = conf.leftMargin ? conf.leftMargin : 50; // @ts-expect-error - wrong config?
const LEFT_MARGIN = conf.leftMargin ?? 50;
//2. Clear the diagram db before parsing //2. Clear the diagram db before parsing
diagObj.db.clear(); diagObj.db.clear?.();
//3. Parse the diagram text //3. Parse the diagram text
diagObj.parser.parse(text + '\n'); diagObj.parser.parse(text + '\n');
@@ -34,15 +46,19 @@ export const draw = function (text, id, version, diagObj) {
} }
const root = const root =
securityLevel === 'sandbox' securityLevel === 'sandbox'
? select(sandboxElement.nodes()[0].contentDocument.body) ? // @ts-ignore d3 types are wrong
select(sandboxElement.nodes()[0].contentDocument.body)
: select('body'); : select('body');
// @ts-ignore d3 types are wrong
const svg = root.select('#' + id); const svg = root.select('#' + id);
svg.append('g'); svg.append('g');
//4. Fetch the diagram data //4. Fetch the diagram data
const tasks = diagObj.db.getTasks(); // @ts-expect-error - db not typed yet
const tasks: TimelineTask[] = diagObj.db.getTasks();
// @ts-expect-error - db not typed yet
const title = diagObj.db.getCommonDb().getDiagramTitle(); const title = diagObj.db.getCommonDb().getDiagramTitle();
log.debug('task', tasks); log.debug('task', tasks);
@@ -50,7 +66,8 @@ export const draw = function (text, id, version, diagObj) {
svgDraw.initGraphics(svg); svgDraw.initGraphics(svg);
// fetch Sections // fetch Sections
const sections = diagObj.db.getSections(); // @ts-expect-error - db not typed yet
const sections: string[] = diagObj.db.getSections();
log.debug('sections', sections); log.debug('sections', sections);
let maxSectionHeight = 0; let maxSectionHeight = 0;
@@ -67,8 +84,8 @@ export const draw = function (text, id, version, diagObj) {
let hasSections = true; let hasSections = true;
//Calculate the max height of the sections //Calculate the max height of the sections
sections.forEach(function (section) { sections.forEach(function (section: string) {
const sectionNode = { const sectionNode: Block<string, number> = {
number: sectionNumber, number: sectionNumber,
descr: section, descr: section,
section: sectionNumber, section: sectionNumber,
@@ -87,8 +104,9 @@ export const draw = function (text, id, version, diagObj) {
log.debug('tasks.length', tasks.length); log.debug('tasks.length', tasks.length);
//calculate max task height //calculate max task height
// for loop till tasks.length // for loop till tasks.length
for (const [i, task] of tasks.entries()) { for (const [i, task] of tasks.entries()) {
const taskNode = { const taskNode: Block<TimelineTask, string> = {
number: i, number: i,
descr: task, descr: task,
section: task.section, section: task.section,
@@ -124,11 +142,14 @@ export const draw = function (text, id, version, diagObj) {
if (sections && sections.length > 0) { if (sections && sections.length > 0) {
sections.forEach((section) => { sections.forEach((section) => {
const sectionNode = { //filter task where tasks.section == section
const tasksForSection = tasks.filter((task) => task.section === section);
const sectionNode: Block<string, number> = {
number: sectionNumber, number: sectionNumber,
descr: section, descr: section,
section: sectionNumber, section: sectionNumber,
width: 150, width: 200 * Math.max(tasksForSection.length, 1) - 50,
padding: 20, padding: 20,
maxHeight: maxSectionHeight, maxHeight: maxSectionHeight,
}; };
@@ -142,8 +163,6 @@ export const draw = function (text, id, version, diagObj) {
masterY += maxSectionHeight + 50; masterY += maxSectionHeight + 50;
//draw tasks for this section //draw tasks for this section
//filter task where tasks.section == section
const tasksForSection = tasks.filter((task) => task.section === section);
if (tasksForSection.length > 0) { if (tasksForSection.length > 0) {
drawTasks( drawTasks(
svg, svg,
@@ -215,25 +234,25 @@ export const draw = function (text, id, version, diagObj) {
setupGraphViewbox( setupGraphViewbox(
undefined, undefined,
svg, svg,
conf.timeline.padding ? conf.timeline.padding : 50, conf.timeline?.padding ?? 50,
conf.timeline.useMaxWidth ? conf.timeline.useMaxWidth : false conf.timeline?.useMaxWidth ?? false
); );
// addSVGAccessibilityFields(diagObj.db, diagram, id); // addSVGAccessibilityFields(diagObj.db, diagram, id);
}; };
export const drawTasks = function ( export const drawTasks = function (
diagram, diagram: Selection<SVGElement, unknown, null, undefined>,
tasks, tasks: TimelineTask[],
sectionColor, sectionColor: number,
masterX, masterX: number,
masterY, masterY: number,
maxTaskHeight, maxTaskHeight: number,
conf, conf: MermaidConfig,
maxEventCount, maxEventCount: number,
maxEventLineLength, maxEventLineLength: number,
maxSectionHeight, maxSectionHeight: number,
isWithoutSections isWithoutSections: boolean
) { ) {
// Draw the tasks // Draw the tasks
for (const task of tasks) { for (const task of tasks) {
@@ -249,6 +268,7 @@ export const drawTasks = function (
log.debug('taskNode', taskNode); log.debug('taskNode', taskNode);
// create task wrapper // create task wrapper
const taskWrapper = diagram.append('g').attr('class', 'taskWrapper'); const taskWrapper = diagram.append('g').attr('class', 'taskWrapper');
const node = svgDraw.drawNode(taskWrapper, taskNode, sectionColor, conf); const node = svgDraw.drawNode(taskWrapper, taskNode, sectionColor, conf);
const taskHeight = node.height; const taskHeight = node.height;
@@ -263,11 +283,11 @@ export const drawTasks = function (
if (task.events) { if (task.events) {
// draw a line between the task and the events // draw a line between the task and the events
const lineWrapper = diagram.append('g').attr('class', 'lineWrapper'); const lineWrapper = diagram.append('g').attr('class', 'lineWrapper');
let linelength = maxTaskHeight; let lineLength = maxTaskHeight;
//add margin to task //add margin to task
masterY += 100; masterY += 100;
linelength = lineLength =
linelength + drawEvents(diagram, task.events, sectionColor, masterX, masterY, conf); lineLength + drawEvents(diagram, task.events, sectionColor, masterX, masterY, conf);
masterY -= 100; masterY -= 100;
lineWrapper lineWrapper
@@ -290,7 +310,7 @@ export const drawTasks = function (
} }
masterX = masterX + 200; masterX = masterX + 200;
if (isWithoutSections && !getConfig().timeline.disableMulticolor) { if (isWithoutSections && !conf.timeline?.disableMulticolor) {
sectionColor++; sectionColor++;
} }
} }
@@ -299,14 +319,21 @@ export const drawTasks = function (
masterY = masterY - 10; masterY = masterY - 10;
}; };
export const drawEvents = function (diagram, events, sectionColor, masterX, masterY, conf) { export const drawEvents = function (
diagram: Selection<SVGElement, unknown, null, undefined>,
events: string[],
sectionColor: number,
masterX: number,
masterY: number,
conf: MermaidConfig
) {
let maxEventHeight = 0; let maxEventHeight = 0;
const eventBeginY = masterY; const eventBeginY = masterY;
masterY = masterY + 100; masterY = masterY + 100;
// Draw the events // Draw the events
for (const event of events) { for (const event of events) {
// create node from event // create node from event
const eventNode = { const eventNode: Block<string, number> = {
descr: event, descr: event,
section: sectionColor, section: sectionColor,
number: sectionColor, number: sectionColor,
@@ -331,6 +358,8 @@ export const drawEvents = function (diagram, events, sectionColor, masterX, mast
}; };
export default { export default {
setConf, setConf: () => {
// no-op
},
draw, draw,
}; };