@diagrammo/dgmo 0.7.1 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +165 -165
- package/dist/index.cjs +206 -66
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +206 -66
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/gantt/parser.ts +5 -0
- package/src/gantt/renderer.ts +353 -87
- package/src/gantt/types.ts +4 -0
package/dist/index.cjs
CHANGED
|
@@ -7986,7 +7986,9 @@ function parseGantt(content, palette) {
|
|
|
7986
7986
|
criticalPath: false,
|
|
7987
7987
|
dependencies: false,
|
|
7988
7988
|
sort: "default",
|
|
7989
|
-
defaultSwimlaneGroup: null
|
|
7989
|
+
defaultSwimlaneGroup: null,
|
|
7990
|
+
optionLineNumbers: {},
|
|
7991
|
+
holidaysLineNumber: null
|
|
7990
7992
|
},
|
|
7991
7993
|
diagnostics,
|
|
7992
7994
|
error: null
|
|
@@ -8171,6 +8173,7 @@ function parseGantt(content, palette) {
|
|
|
8171
8173
|
inHolidaysBlock = true;
|
|
8172
8174
|
holidaysBlockIndent = indent;
|
|
8173
8175
|
inHeaderBlock = false;
|
|
8176
|
+
result.options.holidaysLineNumber = lineNumber;
|
|
8174
8177
|
continue;
|
|
8175
8178
|
}
|
|
8176
8179
|
const tagMatch = matchTagBlockHeading(line10);
|
|
@@ -8197,7 +8200,8 @@ function parseGantt(content, palette) {
|
|
|
8197
8200
|
startDate: eraMatch[1],
|
|
8198
8201
|
endDate: eraMatch[2],
|
|
8199
8202
|
label: eraExtracted.label,
|
|
8200
|
-
color: eraExtracted.color || null
|
|
8203
|
+
color: eraExtracted.color || null,
|
|
8204
|
+
lineNumber
|
|
8201
8205
|
});
|
|
8202
8206
|
inHeaderBlock = false;
|
|
8203
8207
|
continue;
|
|
@@ -8219,6 +8223,7 @@ function parseGantt(content, palette) {
|
|
|
8219
8223
|
if (optMatch && isKnownOption(optMatch[1].toLowerCase())) {
|
|
8220
8224
|
const key = optMatch[1].toLowerCase();
|
|
8221
8225
|
const value = optMatch[2].trim();
|
|
8226
|
+
result.options.optionLineNumbers[key] = lineNumber;
|
|
8222
8227
|
switch (key) {
|
|
8223
8228
|
case "start":
|
|
8224
8229
|
result.options.start = value;
|
|
@@ -16129,7 +16134,7 @@ function renderFlowchart(container, graph, layout, palette, isDark, onClickItem,
|
|
|
16129
16134
|
}
|
|
16130
16135
|
const contentG = svg.append("g").attr("transform", `translate(${offsetX}, ${offsetY}) scale(${scale})`);
|
|
16131
16136
|
const LABEL_CHAR_W = 7;
|
|
16132
|
-
const
|
|
16137
|
+
const LABEL_PAD2 = 8;
|
|
16133
16138
|
const LABEL_H = 16;
|
|
16134
16139
|
const PERP_OFFSET = 10;
|
|
16135
16140
|
const labelPositions = [];
|
|
@@ -16138,7 +16143,7 @@ function renderFlowchart(container, graph, layout, palette, isDark, onClickItem,
|
|
|
16138
16143
|
if (!edge.label || edge.points.length < 2) continue;
|
|
16139
16144
|
const midIdx = Math.floor(edge.points.length / 2);
|
|
16140
16145
|
const midPt = edge.points[midIdx];
|
|
16141
|
-
const bgW = edge.label.length * LABEL_CHAR_W +
|
|
16146
|
+
const bgW = edge.label.length * LABEL_CHAR_W + LABEL_PAD2;
|
|
16142
16147
|
const prev = edge.points[Math.max(0, midIdx - 1)];
|
|
16143
16148
|
const next = edge.points[Math.min(edge.points.length - 1, midIdx + 1)];
|
|
16144
16149
|
const dx = next.x - prev.x;
|
|
@@ -19381,8 +19386,46 @@ __export(renderer_exports9, {
|
|
|
19381
19386
|
buildTagLaneRowList: () => buildTagLaneRowList,
|
|
19382
19387
|
renderGantt: () => renderGantt
|
|
19383
19388
|
});
|
|
19389
|
+
function computeBarLabel(label, x1, barWidth, innerWidth, textColor) {
|
|
19390
|
+
const textWidth = label.length * CHAR_W;
|
|
19391
|
+
const x2 = x1 + barWidth;
|
|
19392
|
+
if (textWidth < barWidth - LABEL_PAD) {
|
|
19393
|
+
return { x: x1 + 6, anchor: "start", fill: textColor, text: label };
|
|
19394
|
+
}
|
|
19395
|
+
if (x2 + LABEL_GAP + textWidth <= innerWidth) {
|
|
19396
|
+
return { x: x2 + LABEL_GAP, anchor: "start", fill: textColor, text: label };
|
|
19397
|
+
}
|
|
19398
|
+
if (x1 - LABEL_GAP - textWidth >= 0) {
|
|
19399
|
+
return { x: x1 - LABEL_GAP, anchor: "end", fill: textColor, text: label };
|
|
19400
|
+
}
|
|
19401
|
+
const availWidth = x1 - LABEL_GAP;
|
|
19402
|
+
if (availWidth > CHAR_W * 3) {
|
|
19403
|
+
const maxChars = Math.floor(availWidth / CHAR_W) - 1;
|
|
19404
|
+
return { x: x1 - LABEL_GAP, anchor: "end", fill: textColor, text: label.slice(0, maxChars) + "\u2026" };
|
|
19405
|
+
}
|
|
19406
|
+
return null;
|
|
19407
|
+
}
|
|
19408
|
+
function renderLabelBand(svg, y, leftMargin, color, palette, cssPrefix, dataAttr) {
|
|
19409
|
+
const bandX = 5;
|
|
19410
|
+
const bandW = leftMargin - 7;
|
|
19411
|
+
const bandY = y - BAR_H / 2;
|
|
19412
|
+
const clipId = `gantt-band-clip-${bandClipCounter++}`;
|
|
19413
|
+
svg.append("clipPath").attr("id", clipId).append("rect").attr("x", bandX).attr("y", bandY).attr("width", bandW).attr("height", BAR_H).attr("rx", BAND_RADIUS);
|
|
19414
|
+
const tint2 = svg.append("rect").attr("class", `gantt-${cssPrefix}-band-bg`).attr("x", bandX).attr("y", bandY).attr("width", bandW).attr("height", BAR_H).attr("rx", BAND_RADIUS).attr("fill", mix(color, palette.bg, 20)).style("pointer-events", "none");
|
|
19415
|
+
const accent = svg.append("rect").attr("class", `gantt-${cssPrefix}-band-accent`).attr("x", bandX).attr("y", bandY).attr("width", BAND_ACCENT_W).attr("height", BAR_H).attr("fill", color).attr("clip-path", `url(#${clipId})`).style("pointer-events", "none");
|
|
19416
|
+
if (dataAttr) {
|
|
19417
|
+
tint2.attr(dataAttr.key, dataAttr.value);
|
|
19418
|
+
accent.attr(dataAttr.key, dataAttr.value);
|
|
19419
|
+
}
|
|
19420
|
+
}
|
|
19421
|
+
function appendTaskIcon(textEl, label, isMilestone, iconColor, textColor) {
|
|
19422
|
+
const icon = isMilestone ? "\u25C6" : "\u25CF";
|
|
19423
|
+
textEl.append("tspan").attr("fill", iconColor).text(icon);
|
|
19424
|
+
textEl.append("tspan").attr("fill", textColor).text(" " + label);
|
|
19425
|
+
}
|
|
19384
19426
|
function renderGantt(container, resolved, palette, isDark, options, exportDims) {
|
|
19385
19427
|
container.innerHTML = "";
|
|
19428
|
+
bandClipCounter = 0;
|
|
19386
19429
|
if (resolved.tasks.length === 0) return;
|
|
19387
19430
|
const onClickItem = options?.onClickItem;
|
|
19388
19431
|
const collapsedGroups = options?.collapsedGroups;
|
|
@@ -19401,10 +19444,13 @@ function renderGantt(container, resolved, palette, isDark, options, exportDims)
|
|
|
19401
19444
|
const isTagMode = tagRows !== null;
|
|
19402
19445
|
const allLabels = isTagMode ? [
|
|
19403
19446
|
...rows.filter((r) => r.type === "lane-header").map((r) => r.laneName),
|
|
19404
|
-
...rows.filter((r) => r.type === "task").map((r) => r.task.task.label)
|
|
19447
|
+
...rows.filter((r) => r.type === "task").map((r) => "\u25CF " + r.task.task.label)
|
|
19405
19448
|
] : [
|
|
19406
|
-
...resolved.tasks.map((t) => t.task.label),
|
|
19407
|
-
...resolved.groups.map((g2) =>
|
|
19449
|
+
...resolved.tasks.map((t) => "\u25CF " + t.task.label),
|
|
19450
|
+
...resolved.groups.map((g2) => {
|
|
19451
|
+
const px = g2.depth <= 2 ? g2.depth * 14 : 2 * 14 + (g2.depth - 2) * 8;
|
|
19452
|
+
return " ".repeat(Math.ceil(px / 7)) + g2.name;
|
|
19453
|
+
})
|
|
19408
19454
|
];
|
|
19409
19455
|
const maxLabelLen = Math.max(...allLabels.map((l) => l.length), 10);
|
|
19410
19456
|
const leftMargin = Math.max(MIN_LEFT_MARGIN, maxLabelLen * 7 + 30);
|
|
@@ -19413,8 +19459,10 @@ function renderGantt(container, resolved, palette, isDark, options, exportDims)
|
|
|
19413
19459
|
const titleHeight = title ? 50 : 20;
|
|
19414
19460
|
const tagLegendReserve = resolved.tagGroups.length > 0 ? LEGEND_HEIGHT + 8 : 0;
|
|
19415
19461
|
const topDateLabelReserve = 22;
|
|
19462
|
+
const hasOverheadLabels = resolved.markers.length > 0 || resolved.eras.length > 0;
|
|
19463
|
+
const markerLabelReserve = hasOverheadLabels ? 18 : 0;
|
|
19416
19464
|
const CONTENT_TOP_PAD = 16;
|
|
19417
|
-
const marginTop = titleHeight + tagLegendReserve + topDateLabelReserve;
|
|
19465
|
+
const marginTop = titleHeight + tagLegendReserve + topDateLabelReserve + markerLabelReserve;
|
|
19418
19466
|
const contentH = isTagMode ? totalRows * (BAR_H + ROW_GAP) : totalRows * (BAR_H + ROW_GAP) + GROUP_GAP2 * resolved.groups.length;
|
|
19419
19467
|
const innerHeight = CONTENT_TOP_PAD + contentH;
|
|
19420
19468
|
const outerHeight = marginTop + innerHeight + BOTTOM_MARGIN;
|
|
@@ -19442,6 +19490,7 @@ function renderGantt(container, resolved, palette, isDark, options, exportDims)
|
|
|
19442
19490
|
isDark,
|
|
19443
19491
|
hasCriticalPath,
|
|
19444
19492
|
criticalPathActive,
|
|
19493
|
+
resolved.options.optionLineNumbers,
|
|
19445
19494
|
(groupName) => {
|
|
19446
19495
|
currentActiveGroup = currentActiveGroup?.toLowerCase() === groupName.toLowerCase() ? null : groupName;
|
|
19447
19496
|
if (onActiveGroupChange) onActiveGroupChange(currentActiveGroup);
|
|
@@ -19480,7 +19529,25 @@ function renderGantt(container, resolved, palette, isDark, options, exportDims)
|
|
|
19480
19529
|
renderTimeScaleHorizontal(g, xScale, innerWidth, innerHeight, palette.text);
|
|
19481
19530
|
renderWeekendBands(g, resolved, xScale, innerHeight, palette, isDark);
|
|
19482
19531
|
renderHolidayBands(g, svg, resolved, xScale, innerHeight, palette, isDark, marginTop - 4, leftMargin, onClickItem);
|
|
19483
|
-
renderErasAndMarkers(g, resolved, xScale, innerHeight, palette);
|
|
19532
|
+
renderErasAndMarkers(g, svg, resolved, xScale, innerHeight, palette);
|
|
19533
|
+
let todayDate = null;
|
|
19534
|
+
let todayX = -1;
|
|
19535
|
+
const todayColor = palette.accent || "#e74c3c";
|
|
19536
|
+
const todayMarkerLineNum = resolved.options.optionLineNumbers["today-marker"];
|
|
19537
|
+
if (resolved.options.todayMarker !== "off") {
|
|
19538
|
+
if (resolved.options.todayMarker === "on") {
|
|
19539
|
+
todayDate = /* @__PURE__ */ new Date();
|
|
19540
|
+
} else {
|
|
19541
|
+
todayDate = /* @__PURE__ */ new Date(resolved.options.todayMarker + "T00:00:00");
|
|
19542
|
+
}
|
|
19543
|
+
todayX = xScale(dateToFractionalYear(todayDate));
|
|
19544
|
+
if (todayX >= 0 && todayX <= innerWidth) {
|
|
19545
|
+
const todayLine = g.append("line").attr("class", "gantt-today").attr("x1", todayX).attr("y1", 0).attr("x2", todayX).attr("y2", innerHeight + 10).attr("stroke", todayColor).attr("stroke-width", 2).attr("stroke-dasharray", "6 4").attr("opacity", 0.7).attr("pointer-events", "none");
|
|
19546
|
+
if (todayMarkerLineNum) todayLine.attr("data-line-number", String(todayMarkerLineNum));
|
|
19547
|
+
const todayLabel = g.append("text").attr("class", "gantt-today").attr("x", todayX).attr("y", innerHeight + 24).attr("text-anchor", "middle").attr("font-size", "10px").attr("fill", todayColor).attr("opacity", 0.7).attr("pointer-events", "none").text("Today");
|
|
19548
|
+
if (todayMarkerLineNum) todayLabel.attr("data-line-number", String(todayMarkerLineNum));
|
|
19549
|
+
}
|
|
19550
|
+
}
|
|
19484
19551
|
const taskPositions = /* @__PURE__ */ new Map();
|
|
19485
19552
|
const groupPositions = /* @__PURE__ */ new Map();
|
|
19486
19553
|
const lanePositions = /* @__PURE__ */ new Map();
|
|
@@ -19516,6 +19583,7 @@ function renderGantt(container, resolved, palette, isDark, options, exportDims)
|
|
|
19516
19583
|
laneBarWidth = Math.max(lx2 - lx1, 2);
|
|
19517
19584
|
}
|
|
19518
19585
|
lanePositions.set(row.laneName, { x1: lx1, x2: lx1 + laneBarWidth, y: yOffset + BAR_H / 2 });
|
|
19586
|
+
renderLabelBand(svg, marginTop + yOffset + BAR_H / 2, leftMargin, laneColor, palette, "lane", { key: "data-lane", value: row.laneName });
|
|
19519
19587
|
const labelG = svg.append("g").attr("class", "gantt-lane-header").attr(`data-tag-${row.tagKey}`, row.laneName.toLowerCase()).attr("data-lane", row.laneName).style("cursor", onToggleLane ? "pointer" : "default").on("click", () => {
|
|
19520
19588
|
if (onToggleLane) onToggleLane(row.laneName);
|
|
19521
19589
|
}).on("mouseenter", () => {
|
|
@@ -19541,7 +19609,7 @@ function renderGantt(container, resolved, palette, isDark, options, exportDims)
|
|
|
19541
19609
|
});
|
|
19542
19610
|
laneBandG.append("rect").attr("class", "gantt-lane-band").attr("x", lx1).attr("y", yOffset).attr("width", laneBarWidth).attr("height", BAR_H).attr("rx", 4).attr("fill", barFill).attr("stroke", laneColor).attr("stroke-width", 2);
|
|
19543
19611
|
if (row.aggregateProgress !== null && row.aggregateProgress > 0) {
|
|
19544
|
-
laneBandG.append("rect").attr("class", "gantt-lane-progress").attr("x", lx1).attr("y", yOffset).attr("width", laneBarWidth * Math.min(row.aggregateProgress / 100, 1)).attr("height", BAR_H).attr("
|
|
19612
|
+
laneBandG.append("rect").attr("class", "gantt-lane-progress").attr("x", lx1).attr("y", yOffset).attr("width", laneBarWidth * Math.min(row.aggregateProgress / 100, 1)).attr("height", BAR_H).attr("fill", laneColor).attr("opacity", 0.5).attr("pointer-events", "none");
|
|
19545
19613
|
}
|
|
19546
19614
|
}
|
|
19547
19615
|
yOffset += BAR_H + ROW_GAP;
|
|
@@ -19552,6 +19620,7 @@ function renderGantt(container, resolved, palette, isDark, options, exportDims)
|
|
|
19552
19620
|
const toggleIcon = isCollapsed ? "\u25BA" : "\u25BC";
|
|
19553
19621
|
const tagColor = resolveTagColor(group.metadata, resolved.tagGroups, currentActiveGroup, true);
|
|
19554
19622
|
const groupColor = tagColor && tagColor !== "#999999" ? tagColor : group.color || palette.textMuted;
|
|
19623
|
+
renderLabelBand(svg, marginTop + yOffset + BAR_H / 2, leftMargin, groupColor, palette, "group", { key: "data-group", value: group.name });
|
|
19555
19624
|
const labelG = svg.append("g").attr("class", "gantt-group-label").attr("data-group", group.name).attr("data-line-number", String(group.lineNumber)).style("cursor", onToggleGroup ? "pointer" : "default").on("click", () => {
|
|
19556
19625
|
if (onToggleGroup) onToggleGroup(group.name);
|
|
19557
19626
|
}).on("mouseenter", () => {
|
|
@@ -19561,7 +19630,8 @@ function renderGantt(container, resolved, palette, isDark, options, exportDims)
|
|
|
19561
19630
|
resetHighlight(g, svg);
|
|
19562
19631
|
hideGanttDateIndicators(g);
|
|
19563
19632
|
});
|
|
19564
|
-
const
|
|
19633
|
+
const groupIndent = group.depth <= 2 ? group.depth * 14 : 2 * 14 + (group.depth - 2) * 8;
|
|
19634
|
+
const labelX = 10 + groupIndent;
|
|
19565
19635
|
labelG.append("text").attr("x", labelX).attr("y", marginTop + yOffset + BAR_H / 2).attr("dy", "0.35em").attr("text-anchor", "start").attr("font-size", "11px").attr("font-weight", "bold").attr("fill", palette.text).text(toggleIcon + " " + group.name + (group.progress !== null ? ` ${Math.round(group.progress)}%` : ""));
|
|
19566
19636
|
const gStart = dateToFractionalYear(group.startDate);
|
|
19567
19637
|
const gEnd = dateToFractionalYear(group.endDate);
|
|
@@ -19579,7 +19649,12 @@ function renderGantt(container, resolved, palette, isDark, options, exportDims)
|
|
|
19579
19649
|
});
|
|
19580
19650
|
summaryG.append("rect").attr("x", gx1).attr("y", yOffset).attr("width", barWidth).attr("height", BAR_H).attr("rx", 4).attr("fill", mix(groupColor, palette.bg, 30)).attr("stroke", groupColor).attr("stroke-width", 2);
|
|
19581
19651
|
if (group.progress !== null && group.progress > 0) {
|
|
19582
|
-
summaryG.append("rect").attr("x", gx1).attr("y", yOffset).attr("width", barWidth * Math.min(group.progress / 100, 1)).attr("height", BAR_H).attr("
|
|
19652
|
+
summaryG.append("rect").attr("x", gx1).attr("y", yOffset).attr("width", barWidth * Math.min(group.progress / 100, 1)).attr("height", BAR_H).attr("fill", groupColor).attr("opacity", 0.5);
|
|
19653
|
+
}
|
|
19654
|
+
const summaryLabel = group.name + (group.progress !== null ? ` ${Math.round(group.progress)}%` : "");
|
|
19655
|
+
const summaryPlacement = computeBarLabel(summaryLabel, gx1, barWidth, innerWidth, palette.text);
|
|
19656
|
+
if (summaryPlacement) {
|
|
19657
|
+
summaryG.append("text").attr("x", summaryPlacement.x).attr("y", yOffset + BAR_H / 2).attr("dy", "0.35em").attr("font-size", "10px").attr("font-weight", "bold").attr("text-anchor", summaryPlacement.anchor).attr("fill", summaryPlacement.fill).attr("pointer-events", "none").text(summaryPlacement.text);
|
|
19583
19658
|
}
|
|
19584
19659
|
groupPositions.set(group.name, { x1: gx1, x2: gx1 + barWidth, y: yOffset + BAR_H / 2 });
|
|
19585
19660
|
} else {
|
|
@@ -19594,7 +19669,12 @@ function renderGantt(container, resolved, palette, isDark, options, exportDims)
|
|
|
19594
19669
|
});
|
|
19595
19670
|
groupBarG.append("rect").attr("x", gx1).attr("y", yOffset).attr("width", groupBarWidth).attr("height", BAR_H).attr("rx", 4).attr("fill", bandFill).attr("stroke", groupColor).attr("stroke-width", 2);
|
|
19596
19671
|
if (group.progress !== null && group.progress > 0) {
|
|
19597
|
-
groupBarG.append("rect").attr("class", "gantt-group-progress").attr("x", gx1).attr("y", yOffset).attr("width", groupBarWidth * Math.min(group.progress / 100, 1)).attr("height", BAR_H).attr("
|
|
19672
|
+
groupBarG.append("rect").attr("class", "gantt-group-progress").attr("x", gx1).attr("y", yOffset).attr("width", groupBarWidth * Math.min(group.progress / 100, 1)).attr("height", BAR_H).attr("fill", groupColor).attr("opacity", 0.5);
|
|
19673
|
+
}
|
|
19674
|
+
const expandedLabel = group.name + (group.progress !== null ? ` ${Math.round(group.progress)}%` : "");
|
|
19675
|
+
const expandedPlacement = computeBarLabel(expandedLabel, gx1, groupBarWidth, innerWidth, palette.text);
|
|
19676
|
+
if (expandedPlacement) {
|
|
19677
|
+
groupBarG.append("text").attr("x", expandedPlacement.x).attr("y", yOffset + BAR_H / 2).attr("dy", "0.35em").attr("font-size", "10px").attr("font-weight", "bold").attr("text-anchor", expandedPlacement.anchor).attr("fill", expandedPlacement.fill).attr("pointer-events", "none").text(expandedPlacement.text);
|
|
19598
19678
|
}
|
|
19599
19679
|
}
|
|
19600
19680
|
}
|
|
@@ -19602,9 +19682,12 @@ function renderGantt(container, resolved, palette, isDark, options, exportDims)
|
|
|
19602
19682
|
} else if (row.type === "task") {
|
|
19603
19683
|
const rt = row.task;
|
|
19604
19684
|
const task = rt.task;
|
|
19605
|
-
const
|
|
19685
|
+
const barColor = resolveTaskColor(rt, currentActiveGroup, resolved, seriesColors2, palette);
|
|
19686
|
+
const depth = rt.groupPath.length;
|
|
19687
|
+
const indent = depth <= 2 ? depth * 14 : 2 * 14 + (depth - 2) * 8;
|
|
19688
|
+
const taskLabelX = isTagMode ? 20 : 6 + indent;
|
|
19606
19689
|
const topGroup = rt.groupPath.length > 0 ? rt.groupPath[0] : null;
|
|
19607
|
-
const taskLabel = svg.append("text").attr("class", "gantt-task-label").attr("x", taskLabelX).attr("y", marginTop + yOffset + BAR_H / 2).attr("dy", "0.35em").attr("text-anchor", "start").attr("font-size", "11px").attr("fill", palette.text).attr("data-line-number", String(task.lineNumber)).attr("data-task-id", task.id).attr("data-group", topGroup).style("cursor", onClickItem ? "pointer" : "default").
|
|
19690
|
+
const taskLabel = svg.append("text").attr("class", "gantt-task-label").attr("x", taskLabelX).attr("y", marginTop + yOffset + BAR_H / 2).attr("dy", "0.35em").attr("text-anchor", "start").attr("font-size", "11px").attr("fill", palette.text).attr("data-line-number", String(task.lineNumber)).attr("data-task-id", task.id).attr("data-group", topGroup).style("cursor", onClickItem ? "pointer" : "default").on("click", () => {
|
|
19608
19691
|
if (onClickItem) onClickItem(task.lineNumber);
|
|
19609
19692
|
}).on("mouseenter", () => {
|
|
19610
19693
|
if (rt.isMilestone) {
|
|
@@ -19615,13 +19698,13 @@ function renderGantt(container, resolved, palette, isDark, options, exportDims)
|
|
|
19615
19698
|
}).on("mouseleave", () => {
|
|
19616
19699
|
resetHighlight(g, svg);
|
|
19617
19700
|
});
|
|
19701
|
+
appendTaskIcon(taskLabel, task.label, rt.isMilestone, barColor, palette.text);
|
|
19618
19702
|
for (const [key, value] of Object.entries(rt.effectiveMetadata)) {
|
|
19619
19703
|
taskLabel.attr(`data-tag-${key}`, value.toLowerCase());
|
|
19620
19704
|
}
|
|
19621
19705
|
if (rt.isCriticalPath) {
|
|
19622
19706
|
taskLabel.attr("data-critical-path", "true");
|
|
19623
19707
|
}
|
|
19624
|
-
let barColor = resolveTaskColor(rt, currentActiveGroup, resolved, seriesColors2, palette);
|
|
19625
19708
|
if (rt.isMilestone) {
|
|
19626
19709
|
const mx = xScale(dateToFractionalYear(rt.startDate));
|
|
19627
19710
|
const my = yOffset + BAR_H / 2;
|
|
@@ -19699,32 +19782,40 @@ function renderGantt(container, resolved, palette, isDark, options, exportDims)
|
|
|
19699
19782
|
progGrad.append("stop").attr("offset", "100%").attr("stop-color", barColor).attr("stop-opacity", 0);
|
|
19700
19783
|
progressFill = `url(#${progGradId})`;
|
|
19701
19784
|
}
|
|
19702
|
-
taskG.append("rect").attr("class", "gantt-progress").attr("x", x1).attr("y", yOffset).attr("width", progressWidth).attr("height", BAR_H).attr("
|
|
19785
|
+
taskG.append("rect").attr("class", "gantt-progress").attr("x", x1).attr("y", yOffset).attr("width", progressWidth).attr("height", BAR_H).attr("fill", progressFill).attr("opacity", 0.5);
|
|
19703
19786
|
}
|
|
19704
19787
|
if (rt.isCriticalPath) {
|
|
19705
19788
|
taskG.attr("data-critical-path", "true");
|
|
19706
19789
|
}
|
|
19707
|
-
const
|
|
19708
|
-
if (
|
|
19709
|
-
taskG.append("text").attr("x",
|
|
19790
|
+
const labelPlacement = computeBarLabel(task.label, x1, barWidth, innerWidth, palette.text);
|
|
19791
|
+
if (labelPlacement) {
|
|
19792
|
+
taskG.append("text").attr("x", labelPlacement.x).attr("y", yOffset + BAR_H / 2).attr("dy", "0.35em").attr("font-size", "10px").attr("text-anchor", labelPlacement.anchor).attr("fill", labelPlacement.fill).attr("pointer-events", "none").text(labelPlacement.text);
|
|
19710
19793
|
}
|
|
19711
19794
|
taskPositions.set(task.id, { x1, x2: x1 + barWidth, y: yOffset + BAR_H / 2 });
|
|
19712
19795
|
}
|
|
19713
19796
|
yOffset += BAR_H + ROW_GAP;
|
|
19714
19797
|
}
|
|
19715
19798
|
}
|
|
19716
|
-
if (
|
|
19717
|
-
|
|
19718
|
-
|
|
19719
|
-
|
|
19720
|
-
|
|
19721
|
-
|
|
19722
|
-
|
|
19723
|
-
|
|
19724
|
-
|
|
19725
|
-
|
|
19726
|
-
|
|
19727
|
-
|
|
19799
|
+
if (todayDate && todayX >= 0 && todayX <= innerWidth) {
|
|
19800
|
+
const todayHoverG = g.append("g").attr("class", "gantt-today-hover").style("cursor", "pointer");
|
|
19801
|
+
todayHoverG.append("rect").attr("x", todayX - 10).attr("y", -6).attr("width", 20).attr("height", innerHeight + 16).attr("fill", "transparent").attr("pointer-events", "all");
|
|
19802
|
+
const todayDateObj = todayDate;
|
|
19803
|
+
todayHoverG.on("mouseenter", () => {
|
|
19804
|
+
g.selectAll(".gantt-task").attr("opacity", FADE_OPACITY);
|
|
19805
|
+
g.selectAll(".gantt-milestone").attr("opacity", FADE_OPACITY);
|
|
19806
|
+
g.selectAll(".gantt-group-bar, .gantt-group-summary").attr("opacity", FADE_OPACITY);
|
|
19807
|
+
svg.selectAll(".gantt-group-label").attr("opacity", FADE_OPACITY);
|
|
19808
|
+
svg.selectAll(".gantt-task-label").attr("opacity", FADE_OPACITY);
|
|
19809
|
+
svg.selectAll(".gantt-lane-header").attr("opacity", FADE_OPACITY);
|
|
19810
|
+
g.selectAll(".gantt-lane-band, .gantt-lane-accent, .gantt-lane-band-group").attr("opacity", FADE_OPACITY);
|
|
19811
|
+
g.selectAll(".gantt-dep-arrow, .gantt-dep-arrowhead").attr("opacity", FADE_OPACITY);
|
|
19812
|
+
g.selectAll(".gantt-era-group").attr("opacity", FADE_OPACITY);
|
|
19813
|
+
g.selectAll(".gantt-marker-group").attr("opacity", FADE_OPACITY);
|
|
19814
|
+
showGanttDateIndicators(g, xScale, todayDateObj, null, innerHeight, todayColor);
|
|
19815
|
+
}).on("mouseleave", () => {
|
|
19816
|
+
resetHighlight(g, svg);
|
|
19817
|
+
hideGanttDateIndicators(g);
|
|
19818
|
+
});
|
|
19728
19819
|
}
|
|
19729
19820
|
if (resolved.options.dependencies) {
|
|
19730
19821
|
renderDependencyArrows(g, resolved, taskPositions, groupPositions, collapsedGroups, palette, isDark, isTagMode, lanePositions, collapsedLanes, taskLaneMap);
|
|
@@ -19841,10 +19932,10 @@ function renderDependencyArrows(g, resolved, taskPositions, groupPositions, coll
|
|
|
19841
19932
|
const path = `M ${sx} ${sy} C ${sx + cpOffset} ${sy}, ${tx - cpOffset} ${ty}, ${tx} ${ty}`;
|
|
19842
19933
|
const arrowColor = mix(palette.text, palette.bg, 50);
|
|
19843
19934
|
const isCpArrow = rt.isCriticalPath && targetTask.isCriticalPath;
|
|
19844
|
-
g.append("path").attr("class", "gantt-dep-arrow").attr("data-dep-from", rt.task.id).attr("data-dep-to", targetTask.task.id).attr("data-critical-path", isCpArrow ? "true" : null).attr("d", path).attr("fill", "none").attr("stroke", arrowColor).attr("stroke-width", 1.5).attr("opacity", 0.5);
|
|
19935
|
+
g.append("path").attr("class", "gantt-dep-arrow").attr("data-dep-from", rt.task.id).attr("data-dep-to", targetTask.task.id).attr("data-line-number", String(dep.lineNumber)).attr("data-critical-path", isCpArrow ? "true" : null).attr("d", path).attr("fill", "none").attr("stroke", arrowColor).attr("stroke-width", 1.5).attr("opacity", 0.5);
|
|
19845
19936
|
const headSize = 5;
|
|
19846
19937
|
const angle = 0;
|
|
19847
|
-
g.append("polygon").attr("class", "gantt-dep-arrowhead").attr("data-dep-from", rt.task.id).attr("data-dep-to", targetTask.task.id).attr("data-critical-path", isCpArrow ? "true" : null).attr("points", arrowheadPoints(tx, ty, headSize, angle)).attr("fill", arrowColor).attr("opacity", 0.5);
|
|
19938
|
+
g.append("polygon").attr("class", "gantt-dep-arrowhead").attr("data-dep-from", rt.task.id).attr("data-dep-to", targetTask.task.id).attr("data-line-number", String(dep.lineNumber)).attr("data-critical-path", isCpArrow ? "true" : null).attr("points", arrowheadPoints(tx, ty, headSize, angle)).attr("fill", arrowColor).attr("opacity", 0.5);
|
|
19848
19939
|
}
|
|
19849
19940
|
}
|
|
19850
19941
|
}
|
|
@@ -19865,7 +19956,9 @@ function applyCriticalPathHighlight(svg, chartG) {
|
|
|
19865
19956
|
el.attr("opacity", el.attr("data-critical-path") === "true" ? 1 : FADE_OPACITY);
|
|
19866
19957
|
});
|
|
19867
19958
|
svg.selectAll(".gantt-group-label").attr("opacity", FADE_OPACITY);
|
|
19959
|
+
svg.selectAll(".gantt-group-band-bg, .gantt-group-band-accent").attr("opacity", FADE_OPACITY);
|
|
19868
19960
|
svg.selectAll(".gantt-lane-header").attr("opacity", FADE_OPACITY);
|
|
19961
|
+
svg.selectAll(".gantt-lane-band-bg, .gantt-lane-band-accent").attr("opacity", FADE_OPACITY);
|
|
19869
19962
|
chartG.selectAll(".gantt-lane-band, .gantt-lane-accent").attr("opacity", FADE_OPACITY);
|
|
19870
19963
|
chartG.selectAll(".gantt-dep-arrow, .gantt-dep-arrowhead").each(function() {
|
|
19871
19964
|
const el = d3Selection10.select(this);
|
|
@@ -19877,7 +19970,9 @@ function resetHighlightAll(svg, chartG) {
|
|
|
19877
19970
|
chartG.selectAll(".gantt-group-bar, .gantt-group-summary").attr("opacity", 1);
|
|
19878
19971
|
svg.selectAll(".gantt-task-label").attr("opacity", 1);
|
|
19879
19972
|
svg.selectAll(".gantt-group-label").attr("opacity", 1);
|
|
19973
|
+
svg.selectAll(".gantt-group-band-bg, .gantt-group-band-accent").attr("opacity", 1);
|
|
19880
19974
|
svg.selectAll(".gantt-lane-header").attr("opacity", 1);
|
|
19975
|
+
svg.selectAll(".gantt-lane-band-bg, .gantt-lane-band-accent").attr("opacity", 1);
|
|
19881
19976
|
chartG.selectAll(".gantt-lane-band, .gantt-lane-accent").attr("opacity", 1);
|
|
19882
19977
|
chartG.selectAll(".gantt-dep-arrow, .gantt-dep-arrowhead").attr("opacity", 0.5);
|
|
19883
19978
|
}
|
|
@@ -19893,7 +19988,7 @@ function drawSwimlaneIcon(parent, x, y, isActive, palette) {
|
|
|
19893
19988
|
}
|
|
19894
19989
|
return iconG;
|
|
19895
19990
|
}
|
|
19896
|
-
function renderTagLegend(svg, chartG, tagGroups, activeGroupName, chartLeftMargin, chartInnerWidth, legendY, palette, isDark, hasCriticalPath, criticalPathActive, onToggle, onToggleCriticalPath, currentSwimlaneGroup, onSwimlaneChange, legendViewMode, resolvedTasks) {
|
|
19991
|
+
function renderTagLegend(svg, chartG, tagGroups, activeGroupName, chartLeftMargin, chartInnerWidth, legendY, palette, isDark, hasCriticalPath, criticalPathActive, optionLineNumbers, onToggle, onToggleCriticalPath, currentSwimlaneGroup, onSwimlaneChange, legendViewMode, resolvedTasks) {
|
|
19897
19992
|
const groupBg = isDark ? mix(palette.surface, palette.bg, 50) : mix(palette.surface, palette.bg, 30);
|
|
19898
19993
|
let visibleGroups;
|
|
19899
19994
|
if (activeGroupName) {
|
|
@@ -19954,7 +20049,8 @@ function renderTagLegend(svg, chartG, tagGroups, activeGroupName, chartLeftMargi
|
|
|
19954
20049
|
if (visibleGroups.length > 0) totalW += LEGEND_GROUP_GAP;
|
|
19955
20050
|
totalW += cpPillW;
|
|
19956
20051
|
}
|
|
19957
|
-
const
|
|
20052
|
+
const containerWidth = chartLeftMargin + chartInnerWidth + RIGHT_MARGIN;
|
|
20053
|
+
const legendX = (containerWidth - totalW) / 2;
|
|
19958
20054
|
const legendRow = svg.append("g").attr("class", "gantt-tag-legend-container").attr("transform", `translate(${legendX}, ${legendY})`);
|
|
19959
20055
|
let cursorX = 0;
|
|
19960
20056
|
for (let i = 0; i < visibleGroups.length; i++) {
|
|
@@ -19966,7 +20062,7 @@ function renderTagLegend(svg, chartG, tagGroups, activeGroupName, chartLeftMargi
|
|
|
19966
20062
|
const pillW = group.name.length * LEGEND_PILL_FONT_W + LEGEND_PILL_PAD + iconReserve;
|
|
19967
20063
|
const pillH = isActive ? LEGEND_HEIGHT - LEGEND_CAPSULE_PAD * 2 : LEGEND_HEIGHT;
|
|
19968
20064
|
const groupW = groupWidths[i];
|
|
19969
|
-
const gEl = legendRow.append("g").attr("transform", `translate(${cursorX}, 0)`).attr("class", "gantt-tag-legend-group").attr("data-tag-group", group.name).style("cursor", "pointer").on("click", () => {
|
|
20065
|
+
const gEl = legendRow.append("g").attr("transform", `translate(${cursorX}, 0)`).attr("class", "gantt-tag-legend-group").attr("data-tag-group", group.name).attr("data-line-number", String(group.lineNumber)).style("cursor", "pointer").on("click", () => {
|
|
19970
20066
|
if (onToggle) onToggle(group.name);
|
|
19971
20067
|
});
|
|
19972
20068
|
if (isActive) {
|
|
@@ -20000,7 +20096,7 @@ function renderTagLegend(svg, chartG, tagGroups, activeGroupName, chartLeftMargi
|
|
|
20000
20096
|
let ex = pillXOff + pillW + LEGEND_CAPSULE_PAD + 4;
|
|
20001
20097
|
for (const entry of entries) {
|
|
20002
20098
|
const entryValue = entry.value.toLowerCase();
|
|
20003
|
-
const entryG = gEl.append("g").attr("class", "gantt-legend-entry").style("cursor", "pointer");
|
|
20099
|
+
const entryG = gEl.append("g").attr("class", "gantt-legend-entry").attr("data-line-number", String(entry.lineNumber)).style("cursor", "pointer");
|
|
20004
20100
|
entryG.append("circle").attr("cx", ex + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
20005
20101
|
entryG.append("text").attr("x", ex + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP).attr("y", LEGEND_HEIGHT / 2 + LEGEND_ENTRY_FONT_SIZE / 2 - 2).attr("text-anchor", "start").attr("font-size", `${LEGEND_ENTRY_FONT_SIZE}px`).attr("fill", palette.textMuted).text(entry.value);
|
|
20006
20102
|
entryG.on("mouseenter", () => {
|
|
@@ -20036,9 +20132,11 @@ function renderTagLegend(svg, chartG, tagGroups, activeGroupName, chartLeftMargi
|
|
|
20036
20132
|
cursorX += groupW + LEGEND_GROUP_GAP;
|
|
20037
20133
|
}
|
|
20038
20134
|
if (hasCriticalPath) {
|
|
20135
|
+
const cpLineNum = optionLineNumbers["critical-path"];
|
|
20039
20136
|
const cpG = legendRow.append("g").attr("transform", `translate(${cursorX}, 0)`).attr("class", "gantt-legend-critical-path").style("cursor", "pointer").on("click", () => {
|
|
20040
20137
|
if (onToggleCriticalPath) onToggleCriticalPath();
|
|
20041
20138
|
});
|
|
20139
|
+
if (cpLineNum) cpG.attr("data-line-number", String(cpLineNum));
|
|
20042
20140
|
cpG.append("rect").attr("width", cpPillW).attr("height", LEGEND_HEIGHT).attr("rx", LEGEND_HEIGHT / 2).attr("fill", criticalPathActive ? palette.bg : groupBg);
|
|
20043
20141
|
if (criticalPathActive) {
|
|
20044
20142
|
cpG.append("rect").attr("width", cpPillW).attr("height", LEGEND_HEIGHT).attr("rx", LEGEND_HEIGHT / 2).attr("fill", "none").attr("stroke", mix(palette.textMuted, palette.bg, 50)).attr("stroke-width", 0.75);
|
|
@@ -20056,7 +20154,7 @@ function renderTagLegend(svg, chartG, tagGroups, activeGroupName, chartLeftMargi
|
|
|
20056
20154
|
});
|
|
20057
20155
|
}
|
|
20058
20156
|
}
|
|
20059
|
-
function renderErasAndMarkers(g, resolved, xScale, innerHeight, palette) {
|
|
20157
|
+
function renderErasAndMarkers(g, svg, resolved, xScale, innerHeight, palette) {
|
|
20060
20158
|
for (let i = 0; i < resolved.eras.length; i++) {
|
|
20061
20159
|
const era = resolved.eras[i];
|
|
20062
20160
|
const color = era.color || ERA_COLORS[i % ERA_COLORS.length];
|
|
@@ -20067,13 +20165,23 @@ function renderErasAndMarkers(g, resolved, xScale, innerHeight, palette) {
|
|
|
20067
20165
|
const hoverEraOpacity = 0.16;
|
|
20068
20166
|
const eraStartDate = parseDateStringToDate(era.startDate);
|
|
20069
20167
|
const eraEndDate = parseDateStringToDate(era.endDate);
|
|
20070
|
-
const eraG = g.append("g").attr("class", "gantt-era-group");
|
|
20168
|
+
const eraG = g.append("g").attr("class", "gantt-era-group").attr("data-line-number", String(era.lineNumber));
|
|
20071
20169
|
const eraRect = eraG.append("rect").attr("class", "gantt-era").attr("x", sx).attr("y", 0).attr("width", ex - sx).attr("height", innerHeight).attr("fill", color).attr("opacity", baseEraOpacity);
|
|
20072
|
-
eraG.append("text").attr("class", "gantt-era-label").attr("x", (sx + ex) / 2).attr("y",
|
|
20170
|
+
eraG.append("text").attr("class", "gantt-era-label").attr("x", (sx + ex) / 2).attr("y", -24).attr("text-anchor", "middle").attr("font-size", "10px").attr("fill", color).attr("opacity", 0.7).style("cursor", "pointer").text(era.label);
|
|
20073
20171
|
eraG.on("mouseenter", () => {
|
|
20172
|
+
g.selectAll(".gantt-task").attr("opacity", FADE_OPACITY);
|
|
20173
|
+
g.selectAll(".gantt-milestone").attr("opacity", FADE_OPACITY);
|
|
20174
|
+
g.selectAll(".gantt-group-bar, .gantt-group-summary").attr("opacity", FADE_OPACITY);
|
|
20175
|
+
svg.selectAll(".gantt-group-label").attr("opacity", FADE_OPACITY);
|
|
20176
|
+
svg.selectAll(".gantt-task-label").attr("opacity", FADE_OPACITY);
|
|
20177
|
+
svg.selectAll(".gantt-lane-header").attr("opacity", FADE_OPACITY);
|
|
20178
|
+
g.selectAll(".gantt-lane-band, .gantt-lane-accent, .gantt-lane-band-group").attr("opacity", FADE_OPACITY);
|
|
20179
|
+
g.selectAll(".gantt-dep-arrow, .gantt-dep-arrowhead").attr("opacity", FADE_OPACITY);
|
|
20180
|
+
g.selectAll(".gantt-marker-group").attr("opacity", FADE_OPACITY);
|
|
20074
20181
|
eraRect.attr("opacity", hoverEraOpacity);
|
|
20075
20182
|
showGanttDateIndicators(g, xScale, eraStartDate, eraEndDate, innerHeight, color);
|
|
20076
20183
|
}).on("mouseleave", () => {
|
|
20184
|
+
resetHighlight(g, svg);
|
|
20077
20185
|
eraRect.attr("opacity", baseEraOpacity);
|
|
20078
20186
|
hideGanttDateIndicators(g);
|
|
20079
20187
|
});
|
|
@@ -20085,22 +20193,31 @@ function renderErasAndMarkers(g, resolved, xScale, innerHeight, palette) {
|
|
|
20085
20193
|
const diamondSize = 5;
|
|
20086
20194
|
const labelY = -24;
|
|
20087
20195
|
const diamondY = labelY + 14;
|
|
20088
|
-
const markerG = g.append("g").attr("class", "gantt-marker-group").style("cursor", "pointer");
|
|
20196
|
+
const markerG = g.append("g").attr("class", "gantt-marker-group").attr("data-line-number", String(marker.lineNumber)).style("cursor", "pointer");
|
|
20089
20197
|
markerG.append("rect").attr("x", mx - 40).attr("y", labelY - 12).attr("width", 80).attr("height", innerHeight - labelY + 12).attr("fill", "transparent").attr("pointer-events", "all");
|
|
20090
20198
|
markerG.append("text").attr("class", "gantt-marker-label").attr("x", mx).attr("y", labelY).attr("text-anchor", "middle").attr("font-size", "11px").attr("font-weight", "600").attr("fill", color).text(marker.label);
|
|
20091
20199
|
markerG.append("path").attr("d", `M${mx},${diamondY - diamondSize} l${diamondSize},${diamondSize} l-${diamondSize},${diamondSize} l-${diamondSize},-${diamondSize} Z`).attr("fill", color).attr("opacity", 0.9);
|
|
20092
20200
|
markerG.append("line").attr("class", "gantt-marker").attr("x1", mx).attr("y1", diamondY + diamondSize).attr("x2", mx).attr("y2", innerHeight).attr("stroke", color).attr("stroke-width", 1.5).attr("stroke-dasharray", "6 4").attr("opacity", 0.5);
|
|
20093
20201
|
const markerLine = markerG.select(".gantt-marker");
|
|
20094
|
-
const markerLabel = markerG.select(".gantt-marker-label");
|
|
20095
20202
|
const markerDiamond = markerG.select("path");
|
|
20096
20203
|
markerG.on("mouseenter", () => {
|
|
20097
|
-
|
|
20098
|
-
|
|
20204
|
+
g.selectAll(".gantt-task").attr("opacity", FADE_OPACITY);
|
|
20205
|
+
g.selectAll(".gantt-milestone").attr("opacity", FADE_OPACITY);
|
|
20206
|
+
g.selectAll(".gantt-group-bar, .gantt-group-summary").attr("opacity", FADE_OPACITY);
|
|
20207
|
+
svg.selectAll(".gantt-group-label").attr("opacity", FADE_OPACITY);
|
|
20208
|
+
svg.selectAll(".gantt-task-label").attr("opacity", FADE_OPACITY);
|
|
20209
|
+
svg.selectAll(".gantt-lane-header").attr("opacity", FADE_OPACITY);
|
|
20210
|
+
g.selectAll(".gantt-lane-band, .gantt-lane-accent, .gantt-lane-band-group").attr("opacity", FADE_OPACITY);
|
|
20211
|
+
g.selectAll(".gantt-dep-arrow, .gantt-dep-arrowhead").attr("opacity", FADE_OPACITY);
|
|
20212
|
+
g.selectAll(".gantt-era-group").attr("opacity", FADE_OPACITY);
|
|
20213
|
+
g.selectAll(".gantt-marker-group").attr("opacity", FADE_OPACITY);
|
|
20214
|
+
markerG.attr("opacity", 1);
|
|
20215
|
+
markerLine.attr("opacity", 0.8);
|
|
20099
20216
|
markerDiamond.attr("opacity", 0);
|
|
20100
|
-
showGanttDateIndicators(g, xScale, markerDate, null, innerHeight, color);
|
|
20217
|
+
showGanttDateIndicators(g, xScale, markerDate, null, innerHeight, color, { skipStartLine: true });
|
|
20101
20218
|
}).on("mouseleave", () => {
|
|
20219
|
+
resetHighlight(g, svg);
|
|
20102
20220
|
markerLine.attr("opacity", 0.5);
|
|
20103
|
-
markerLabel.attr("opacity", 1);
|
|
20104
20221
|
markerDiamond.attr("opacity", 0.9);
|
|
20105
20222
|
hideGanttDateIndicators(g);
|
|
20106
20223
|
});
|
|
@@ -20114,11 +20231,7 @@ function parseDateStringToDate(s) {
|
|
|
20114
20231
|
return new Date(year, month, day);
|
|
20115
20232
|
}
|
|
20116
20233
|
function parseDateToFractionalYear(s) {
|
|
20117
|
-
|
|
20118
|
-
const year = parts[0];
|
|
20119
|
-
const month = parts.length >= 2 ? parts[1] : 1;
|
|
20120
|
-
const day = parts.length >= 3 ? parts[2] : 1;
|
|
20121
|
-
return year + (month - 1) / 12 + (day - 1) / 365;
|
|
20234
|
+
return dateToFractionalYear(parseDateStringToDate(s));
|
|
20122
20235
|
}
|
|
20123
20236
|
function highlightDeps(g, svg, taskId, resolved) {
|
|
20124
20237
|
const related = /* @__PURE__ */ new Set([taskId]);
|
|
@@ -20152,6 +20265,7 @@ function highlightDeps(g, svg, taskId, resolved) {
|
|
|
20152
20265
|
const isRelated = from && related.has(from) || to && related.has(to);
|
|
20153
20266
|
el.attr("opacity", isRelated ? 0.5 : FADE_OPACITY);
|
|
20154
20267
|
});
|
|
20268
|
+
g.selectAll(".gantt-marker-group").attr("opacity", FADE_OPACITY);
|
|
20155
20269
|
}
|
|
20156
20270
|
function highlightGroup(g, svg, groupName) {
|
|
20157
20271
|
g.selectAll(".gantt-task").each(function() {
|
|
@@ -20174,7 +20288,12 @@ function highlightGroup(g, svg, groupName) {
|
|
|
20174
20288
|
const el = d3Selection10.select(this);
|
|
20175
20289
|
el.attr("opacity", el.attr("data-group") === groupName ? 1 : FADE_OPACITY);
|
|
20176
20290
|
});
|
|
20291
|
+
svg.selectAll(".gantt-group-band-bg, .gantt-group-band-accent").each(function() {
|
|
20292
|
+
const el = d3Selection10.select(this);
|
|
20293
|
+
el.attr("opacity", el.attr("data-group") === groupName ? 1 : FADE_OPACITY);
|
|
20294
|
+
});
|
|
20177
20295
|
svg.selectAll(".gantt-lane-header").attr("opacity", FADE_OPACITY);
|
|
20296
|
+
svg.selectAll(".gantt-lane-band-bg, .gantt-lane-band-accent").attr("opacity", FADE_OPACITY);
|
|
20178
20297
|
g.selectAll(".gantt-lane-band, .gantt-lane-accent").attr("opacity", FADE_OPACITY);
|
|
20179
20298
|
g.selectAll(".gantt-marker-group").attr("opacity", FADE_OPACITY);
|
|
20180
20299
|
}
|
|
@@ -20201,8 +20320,13 @@ function highlightLane(g, svg, tagKey, laneName) {
|
|
|
20201
20320
|
const el = d3Selection10.select(this);
|
|
20202
20321
|
el.attr("opacity", el.attr("data-lane") === laneName ? 1 : FADE_OPACITY);
|
|
20203
20322
|
});
|
|
20323
|
+
svg.selectAll(".gantt-lane-band-bg, .gantt-lane-band-accent").each(function() {
|
|
20324
|
+
const el = d3Selection10.select(this);
|
|
20325
|
+
el.attr("opacity", el.attr("data-lane") === laneName ? 1 : FADE_OPACITY);
|
|
20326
|
+
});
|
|
20204
20327
|
g.selectAll(".gantt-group-bar, .gantt-group-summary").attr("opacity", FADE_OPACITY);
|
|
20205
20328
|
svg.selectAll(".gantt-group-label").attr("opacity", FADE_OPACITY);
|
|
20329
|
+
svg.selectAll(".gantt-group-band-bg, .gantt-group-band-accent").attr("opacity", FADE_OPACITY);
|
|
20206
20330
|
g.selectAll(".gantt-marker-group").attr("opacity", FADE_OPACITY);
|
|
20207
20331
|
}
|
|
20208
20332
|
function highlightTask(g, svg, taskId) {
|
|
@@ -20217,7 +20341,9 @@ function highlightTask(g, svg, taskId) {
|
|
|
20217
20341
|
});
|
|
20218
20342
|
g.selectAll(".gantt-group-bar, .gantt-group-summary").attr("opacity", FADE_OPACITY);
|
|
20219
20343
|
svg.selectAll(".gantt-group-label").attr("opacity", FADE_OPACITY);
|
|
20344
|
+
svg.selectAll(".gantt-group-band-bg, .gantt-group-band-accent").attr("opacity", FADE_OPACITY);
|
|
20220
20345
|
svg.selectAll(".gantt-lane-header").attr("opacity", FADE_OPACITY);
|
|
20346
|
+
svg.selectAll(".gantt-lane-band-bg, .gantt-lane-band-accent").attr("opacity", FADE_OPACITY);
|
|
20221
20347
|
g.selectAll(".gantt-lane-band, .gantt-lane-accent, .gantt-lane-band-group").attr("opacity", FADE_OPACITY);
|
|
20222
20348
|
g.selectAll(".gantt-dep-arrow, .gantt-dep-arrowhead").attr("opacity", FADE_OPACITY);
|
|
20223
20349
|
g.selectAll(".gantt-marker-group").attr("opacity", FADE_OPACITY);
|
|
@@ -20234,7 +20360,9 @@ function highlightMilestone(g, svg, taskId) {
|
|
|
20234
20360
|
});
|
|
20235
20361
|
g.selectAll(".gantt-group-bar, .gantt-group-summary").attr("opacity", FADE_OPACITY);
|
|
20236
20362
|
svg.selectAll(".gantt-group-label").attr("opacity", FADE_OPACITY);
|
|
20363
|
+
svg.selectAll(".gantt-group-band-bg, .gantt-group-band-accent").attr("opacity", FADE_OPACITY);
|
|
20237
20364
|
svg.selectAll(".gantt-lane-header").attr("opacity", FADE_OPACITY);
|
|
20365
|
+
svg.selectAll(".gantt-lane-band-bg, .gantt-lane-band-accent").attr("opacity", FADE_OPACITY);
|
|
20238
20366
|
g.selectAll(".gantt-lane-band, .gantt-lane-accent, .gantt-lane-band-group").attr("opacity", FADE_OPACITY);
|
|
20239
20367
|
g.selectAll(".gantt-dep-arrow, .gantt-dep-arrowhead").attr("opacity", FADE_OPACITY);
|
|
20240
20368
|
g.selectAll(".gantt-marker-group").attr("opacity", FADE_OPACITY);
|
|
@@ -20253,11 +20381,14 @@ function resetHighlight(g, svg) {
|
|
|
20253
20381
|
g.selectAll(".gantt-task, .gantt-milestone").attr("opacity", 1);
|
|
20254
20382
|
g.selectAll(".gantt-group-bar, .gantt-group-summary").attr("opacity", 1);
|
|
20255
20383
|
svg.selectAll(".gantt-group-label").attr("opacity", 1);
|
|
20384
|
+
svg.selectAll(".gantt-group-band-bg, .gantt-group-band-accent").attr("opacity", 1);
|
|
20256
20385
|
svg.selectAll(".gantt-task-label").attr("opacity", 1);
|
|
20257
20386
|
svg.selectAll(".gantt-lane-header").attr("opacity", 1);
|
|
20387
|
+
svg.selectAll(".gantt-lane-band-bg, .gantt-lane-band-accent").attr("opacity", 1);
|
|
20258
20388
|
g.selectAll(".gantt-lane-band, .gantt-lane-accent, .gantt-lane-band-group").attr("opacity", 1);
|
|
20259
20389
|
g.selectAll(".gantt-dep-arrow, .gantt-dep-arrowhead").attr("opacity", 0.5);
|
|
20260
20390
|
g.selectAll(".gantt-marker-group").attr("opacity", 1);
|
|
20391
|
+
g.selectAll(".gantt-era-group").attr("opacity", 1);
|
|
20261
20392
|
}
|
|
20262
20393
|
function buildRowList(resolved, collapsedGroups) {
|
|
20263
20394
|
const rows = [];
|
|
@@ -20411,15 +20542,18 @@ function diamondPoints(cx, cy, size) {
|
|
|
20411
20542
|
function formatGanttDate(d) {
|
|
20412
20543
|
return `${MONTH_ABBR[d.getMonth()]} ${d.getDate()}, ${d.getFullYear()}`;
|
|
20413
20544
|
}
|
|
20414
|
-
function showGanttDateIndicators(g, xScale, startDate, endDate, innerHeight, color) {
|
|
20545
|
+
function showGanttDateIndicators(g, xScale, startDate, endDate, innerHeight, color, options) {
|
|
20415
20546
|
g.selectAll(".gantt-scale-tick").attr("opacity", 0.05);
|
|
20416
20547
|
g.selectAll(".gantt-today").attr("opacity", 0.05);
|
|
20548
|
+
const hg = g.append("g").attr("class", "gantt-hover-date").attr("pointer-events", "none");
|
|
20417
20549
|
const tickLen = 6;
|
|
20418
20550
|
const startPos = xScale(dateToFractionalYear(startDate));
|
|
20419
20551
|
const startLabel = formatGanttDate(startDate);
|
|
20420
|
-
|
|
20421
|
-
|
|
20422
|
-
|
|
20552
|
+
if (!options?.skipStartLine) {
|
|
20553
|
+
hg.append("line").attr("class", "gantt-hover-date").attr("x1", startPos).attr("y1", -tickLen).attr("x2", startPos).attr("y2", innerHeight).attr("stroke", color).attr("stroke-width", 1.5).attr("stroke-dasharray", "4 4").attr("opacity", 0.6);
|
|
20554
|
+
}
|
|
20555
|
+
hg.append("text").attr("class", "gantt-hover-date").attr("x", startPos).attr("y", -tickLen - 4).attr("text-anchor", "middle").attr("fill", color).attr("font-size", "10px").attr("font-weight", "600").text(startLabel);
|
|
20556
|
+
hg.append("text").attr("class", "gantt-hover-date").attr("x", startPos).attr("y", innerHeight + tickLen + 12).attr("text-anchor", "middle").attr("fill", color).attr("font-size", "10px").attr("font-weight", "600").text(startLabel);
|
|
20423
20557
|
if (endDate && endDate.getTime() !== startDate.getTime()) {
|
|
20424
20558
|
const endPos = xScale(dateToFractionalYear(endDate));
|
|
20425
20559
|
const endLabel = formatGanttDate(endDate);
|
|
@@ -20436,15 +20570,15 @@ function showGanttDateIndicators(g, xScale, startDate, endDate, innerHeight, col
|
|
|
20436
20570
|
startAnchor = "middle";
|
|
20437
20571
|
endAnchor = "middle";
|
|
20438
20572
|
}
|
|
20439
|
-
|
|
20440
|
-
|
|
20573
|
+
hg.append("line").attr("class", "gantt-hover-date").attr("x1", endPos).attr("y1", -tickLen).attr("x2", endPos).attr("y2", innerHeight).attr("stroke", color).attr("stroke-width", 1.5).attr("stroke-dasharray", "4 4").attr("opacity", 0.6);
|
|
20574
|
+
hg.selectAll("text.gantt-hover-date").each(function() {
|
|
20441
20575
|
const el = d3Selection10.select(this);
|
|
20442
20576
|
if (el.text() === startLabel) {
|
|
20443
20577
|
el.attr("x", startLabelX).attr("text-anchor", startAnchor);
|
|
20444
20578
|
}
|
|
20445
20579
|
});
|
|
20446
|
-
|
|
20447
|
-
|
|
20580
|
+
hg.append("text").attr("class", "gantt-hover-date").attr("x", endLabelX).attr("y", -tickLen - 4).attr("text-anchor", endAnchor).attr("fill", color).attr("font-size", "10px").attr("font-weight", "600").text(endLabel);
|
|
20581
|
+
hg.append("text").attr("class", "gantt-hover-date").attr("x", endLabelX).attr("y", innerHeight + tickLen + 12).attr("text-anchor", endAnchor).attr("fill", color).attr("font-size", "10px").attr("font-weight", "600").text(endLabel);
|
|
20448
20582
|
}
|
|
20449
20583
|
}
|
|
20450
20584
|
function hideGanttDateIndicators(g) {
|
|
@@ -20489,7 +20623,7 @@ function renderTimeScaleHorizontal(g, scale, innerWidth, innerHeight, textColor)
|
|
|
20489
20623
|
g.append("text").attr("class", "gantt-scale-tick").attr("x", tick.pos).attr("y", innerHeight + tickLen + 12).attr("text-anchor", "middle").attr("font-size", "10px").attr("fill", textColor).attr("opacity", opacity).text(tick.label);
|
|
20490
20624
|
}
|
|
20491
20625
|
}
|
|
20492
|
-
var d3Scale, d3Selection10, BAR_H, ROW_GAP, GROUP_GAP2, MILESTONE_SIZE, MIN_LEFT_MARGIN, BOTTOM_MARGIN, RIGHT_MARGIN, JS_DAY_TO_WEEKDAY2, ERA_COLORS, FADE_OPACITY, MONTH_ABBR;
|
|
20626
|
+
var d3Scale, d3Selection10, BAR_H, ROW_GAP, GROUP_GAP2, MILESTONE_SIZE, MIN_LEFT_MARGIN, BOTTOM_MARGIN, RIGHT_MARGIN, CHAR_W, LABEL_PAD, LABEL_GAP, BAND_ACCENT_W, BAND_RADIUS, bandClipCounter, JS_DAY_TO_WEEKDAY2, ERA_COLORS, FADE_OPACITY, MONTH_ABBR;
|
|
20493
20627
|
var init_renderer9 = __esm({
|
|
20494
20628
|
"src/gantt/renderer.ts"() {
|
|
20495
20629
|
"use strict";
|
|
@@ -20508,6 +20642,12 @@ var init_renderer9 = __esm({
|
|
|
20508
20642
|
MIN_LEFT_MARGIN = 120;
|
|
20509
20643
|
BOTTOM_MARGIN = 40;
|
|
20510
20644
|
RIGHT_MARGIN = 20;
|
|
20645
|
+
CHAR_W = 6.5;
|
|
20646
|
+
LABEL_PAD = 8;
|
|
20647
|
+
LABEL_GAP = 5;
|
|
20648
|
+
BAND_ACCENT_W = 4;
|
|
20649
|
+
BAND_RADIUS = 4;
|
|
20650
|
+
bandClipCounter = 0;
|
|
20511
20651
|
JS_DAY_TO_WEEKDAY2 = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"];
|
|
20512
20652
|
ERA_COLORS = ["#5e81ac", "#a3be8c", "#ebcb8b", "#d08770", "#b48ead"];
|
|
20513
20653
|
FADE_OPACITY = 0.1;
|
|
@@ -20608,14 +20748,14 @@ function renderState(container, graph, layout, palette, isDark, onClickItem, exp
|
|
|
20608
20748
|
nodePositionMap.set(node.id, node);
|
|
20609
20749
|
}
|
|
20610
20750
|
const LABEL_CHAR_W = 7;
|
|
20611
|
-
const
|
|
20751
|
+
const LABEL_PAD2 = 8;
|
|
20612
20752
|
const LABEL_H = 16;
|
|
20613
20753
|
const PERP_OFFSET = 10;
|
|
20614
20754
|
const labelPositions = [];
|
|
20615
20755
|
for (let ei = 0; ei < layout.edges.length; ei++) {
|
|
20616
20756
|
const edge = layout.edges[ei];
|
|
20617
20757
|
if (!edge.label) continue;
|
|
20618
|
-
const bgW = edge.label.length * LABEL_CHAR_W +
|
|
20758
|
+
const bgW = edge.label.length * LABEL_CHAR_W + LABEL_PAD2;
|
|
20619
20759
|
let lx, ly;
|
|
20620
20760
|
if (edge.source === edge.target) {
|
|
20621
20761
|
const node = nodePositionMap.get(edge.source);
|
|
@@ -25115,12 +25255,12 @@ function renderQuadrant(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
25115
25255
|
};
|
|
25116
25256
|
const LABEL_MAX_FONT = 48;
|
|
25117
25257
|
const LABEL_MIN_FONT = 14;
|
|
25118
|
-
const
|
|
25258
|
+
const LABEL_PAD2 = 40;
|
|
25119
25259
|
const CHAR_WIDTH_RATIO3 = 0.6;
|
|
25120
25260
|
const estTextWidth = (text, fontSize) => text.length * fontSize * CHAR_WIDTH_RATIO3;
|
|
25121
25261
|
const quadrantLabelLayout = (text, qw2, qh2) => {
|
|
25122
|
-
const availW = qw2 -
|
|
25123
|
-
const availH = qh2 -
|
|
25262
|
+
const availW = qw2 - LABEL_PAD2;
|
|
25263
|
+
const availH = qh2 - LABEL_PAD2;
|
|
25124
25264
|
const words = text.split(/\s+/);
|
|
25125
25265
|
if (estTextWidth(text, LABEL_MAX_FONT) <= availW) {
|
|
25126
25266
|
const fs = Math.min(LABEL_MAX_FONT, availH);
|