@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.js
CHANGED
|
@@ -7964,7 +7964,9 @@ function parseGantt(content, palette) {
|
|
|
7964
7964
|
criticalPath: false,
|
|
7965
7965
|
dependencies: false,
|
|
7966
7966
|
sort: "default",
|
|
7967
|
-
defaultSwimlaneGroup: null
|
|
7967
|
+
defaultSwimlaneGroup: null,
|
|
7968
|
+
optionLineNumbers: {},
|
|
7969
|
+
holidaysLineNumber: null
|
|
7968
7970
|
},
|
|
7969
7971
|
diagnostics,
|
|
7970
7972
|
error: null
|
|
@@ -8149,6 +8151,7 @@ function parseGantt(content, palette) {
|
|
|
8149
8151
|
inHolidaysBlock = true;
|
|
8150
8152
|
holidaysBlockIndent = indent;
|
|
8151
8153
|
inHeaderBlock = false;
|
|
8154
|
+
result.options.holidaysLineNumber = lineNumber;
|
|
8152
8155
|
continue;
|
|
8153
8156
|
}
|
|
8154
8157
|
const tagMatch = matchTagBlockHeading(line10);
|
|
@@ -8175,7 +8178,8 @@ function parseGantt(content, palette) {
|
|
|
8175
8178
|
startDate: eraMatch[1],
|
|
8176
8179
|
endDate: eraMatch[2],
|
|
8177
8180
|
label: eraExtracted.label,
|
|
8178
|
-
color: eraExtracted.color || null
|
|
8181
|
+
color: eraExtracted.color || null,
|
|
8182
|
+
lineNumber
|
|
8179
8183
|
});
|
|
8180
8184
|
inHeaderBlock = false;
|
|
8181
8185
|
continue;
|
|
@@ -8197,6 +8201,7 @@ function parseGantt(content, palette) {
|
|
|
8197
8201
|
if (optMatch && isKnownOption(optMatch[1].toLowerCase())) {
|
|
8198
8202
|
const key = optMatch[1].toLowerCase();
|
|
8199
8203
|
const value = optMatch[2].trim();
|
|
8204
|
+
result.options.optionLineNumbers[key] = lineNumber;
|
|
8200
8205
|
switch (key) {
|
|
8201
8206
|
case "start":
|
|
8202
8207
|
result.options.start = value;
|
|
@@ -16109,7 +16114,7 @@ function renderFlowchart(container, graph, layout, palette, isDark, onClickItem,
|
|
|
16109
16114
|
}
|
|
16110
16115
|
const contentG = svg.append("g").attr("transform", `translate(${offsetX}, ${offsetY}) scale(${scale})`);
|
|
16111
16116
|
const LABEL_CHAR_W = 7;
|
|
16112
|
-
const
|
|
16117
|
+
const LABEL_PAD2 = 8;
|
|
16113
16118
|
const LABEL_H = 16;
|
|
16114
16119
|
const PERP_OFFSET = 10;
|
|
16115
16120
|
const labelPositions = [];
|
|
@@ -16118,7 +16123,7 @@ function renderFlowchart(container, graph, layout, palette, isDark, onClickItem,
|
|
|
16118
16123
|
if (!edge.label || edge.points.length < 2) continue;
|
|
16119
16124
|
const midIdx = Math.floor(edge.points.length / 2);
|
|
16120
16125
|
const midPt = edge.points[midIdx];
|
|
16121
|
-
const bgW = edge.label.length * LABEL_CHAR_W +
|
|
16126
|
+
const bgW = edge.label.length * LABEL_CHAR_W + LABEL_PAD2;
|
|
16122
16127
|
const prev = edge.points[Math.max(0, midIdx - 1)];
|
|
16123
16128
|
const next = edge.points[Math.min(edge.points.length - 1, midIdx + 1)];
|
|
16124
16129
|
const dx = next.x - prev.x;
|
|
@@ -19361,8 +19366,46 @@ __export(renderer_exports9, {
|
|
|
19361
19366
|
});
|
|
19362
19367
|
import * as d3Scale from "d3-scale";
|
|
19363
19368
|
import * as d3Selection10 from "d3-selection";
|
|
19369
|
+
function computeBarLabel(label, x1, barWidth, innerWidth, textColor) {
|
|
19370
|
+
const textWidth = label.length * CHAR_W;
|
|
19371
|
+
const x2 = x1 + barWidth;
|
|
19372
|
+
if (textWidth < barWidth - LABEL_PAD) {
|
|
19373
|
+
return { x: x1 + 6, anchor: "start", fill: textColor, text: label };
|
|
19374
|
+
}
|
|
19375
|
+
if (x2 + LABEL_GAP + textWidth <= innerWidth) {
|
|
19376
|
+
return { x: x2 + LABEL_GAP, anchor: "start", fill: textColor, text: label };
|
|
19377
|
+
}
|
|
19378
|
+
if (x1 - LABEL_GAP - textWidth >= 0) {
|
|
19379
|
+
return { x: x1 - LABEL_GAP, anchor: "end", fill: textColor, text: label };
|
|
19380
|
+
}
|
|
19381
|
+
const availWidth = x1 - LABEL_GAP;
|
|
19382
|
+
if (availWidth > CHAR_W * 3) {
|
|
19383
|
+
const maxChars = Math.floor(availWidth / CHAR_W) - 1;
|
|
19384
|
+
return { x: x1 - LABEL_GAP, anchor: "end", fill: textColor, text: label.slice(0, maxChars) + "\u2026" };
|
|
19385
|
+
}
|
|
19386
|
+
return null;
|
|
19387
|
+
}
|
|
19388
|
+
function renderLabelBand(svg, y, leftMargin, color, palette, cssPrefix, dataAttr) {
|
|
19389
|
+
const bandX = 5;
|
|
19390
|
+
const bandW = leftMargin - 7;
|
|
19391
|
+
const bandY = y - BAR_H / 2;
|
|
19392
|
+
const clipId = `gantt-band-clip-${bandClipCounter++}`;
|
|
19393
|
+
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);
|
|
19394
|
+
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");
|
|
19395
|
+
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");
|
|
19396
|
+
if (dataAttr) {
|
|
19397
|
+
tint2.attr(dataAttr.key, dataAttr.value);
|
|
19398
|
+
accent.attr(dataAttr.key, dataAttr.value);
|
|
19399
|
+
}
|
|
19400
|
+
}
|
|
19401
|
+
function appendTaskIcon(textEl, label, isMilestone, iconColor, textColor) {
|
|
19402
|
+
const icon = isMilestone ? "\u25C6" : "\u25CF";
|
|
19403
|
+
textEl.append("tspan").attr("fill", iconColor).text(icon);
|
|
19404
|
+
textEl.append("tspan").attr("fill", textColor).text(" " + label);
|
|
19405
|
+
}
|
|
19364
19406
|
function renderGantt(container, resolved, palette, isDark, options, exportDims) {
|
|
19365
19407
|
container.innerHTML = "";
|
|
19408
|
+
bandClipCounter = 0;
|
|
19366
19409
|
if (resolved.tasks.length === 0) return;
|
|
19367
19410
|
const onClickItem = options?.onClickItem;
|
|
19368
19411
|
const collapsedGroups = options?.collapsedGroups;
|
|
@@ -19381,10 +19424,13 @@ function renderGantt(container, resolved, palette, isDark, options, exportDims)
|
|
|
19381
19424
|
const isTagMode = tagRows !== null;
|
|
19382
19425
|
const allLabels = isTagMode ? [
|
|
19383
19426
|
...rows.filter((r) => r.type === "lane-header").map((r) => r.laneName),
|
|
19384
|
-
...rows.filter((r) => r.type === "task").map((r) => r.task.task.label)
|
|
19427
|
+
...rows.filter((r) => r.type === "task").map((r) => "\u25CF " + r.task.task.label)
|
|
19385
19428
|
] : [
|
|
19386
|
-
...resolved.tasks.map((t) => t.task.label),
|
|
19387
|
-
...resolved.groups.map((g2) =>
|
|
19429
|
+
...resolved.tasks.map((t) => "\u25CF " + t.task.label),
|
|
19430
|
+
...resolved.groups.map((g2) => {
|
|
19431
|
+
const px = g2.depth <= 2 ? g2.depth * 14 : 2 * 14 + (g2.depth - 2) * 8;
|
|
19432
|
+
return " ".repeat(Math.ceil(px / 7)) + g2.name;
|
|
19433
|
+
})
|
|
19388
19434
|
];
|
|
19389
19435
|
const maxLabelLen = Math.max(...allLabels.map((l) => l.length), 10);
|
|
19390
19436
|
const leftMargin = Math.max(MIN_LEFT_MARGIN, maxLabelLen * 7 + 30);
|
|
@@ -19393,8 +19439,10 @@ function renderGantt(container, resolved, palette, isDark, options, exportDims)
|
|
|
19393
19439
|
const titleHeight = title ? 50 : 20;
|
|
19394
19440
|
const tagLegendReserve = resolved.tagGroups.length > 0 ? LEGEND_HEIGHT + 8 : 0;
|
|
19395
19441
|
const topDateLabelReserve = 22;
|
|
19442
|
+
const hasOverheadLabels = resolved.markers.length > 0 || resolved.eras.length > 0;
|
|
19443
|
+
const markerLabelReserve = hasOverheadLabels ? 18 : 0;
|
|
19396
19444
|
const CONTENT_TOP_PAD = 16;
|
|
19397
|
-
const marginTop = titleHeight + tagLegendReserve + topDateLabelReserve;
|
|
19445
|
+
const marginTop = titleHeight + tagLegendReserve + topDateLabelReserve + markerLabelReserve;
|
|
19398
19446
|
const contentH = isTagMode ? totalRows * (BAR_H + ROW_GAP) : totalRows * (BAR_H + ROW_GAP) + GROUP_GAP2 * resolved.groups.length;
|
|
19399
19447
|
const innerHeight = CONTENT_TOP_PAD + contentH;
|
|
19400
19448
|
const outerHeight = marginTop + innerHeight + BOTTOM_MARGIN;
|
|
@@ -19422,6 +19470,7 @@ function renderGantt(container, resolved, palette, isDark, options, exportDims)
|
|
|
19422
19470
|
isDark,
|
|
19423
19471
|
hasCriticalPath,
|
|
19424
19472
|
criticalPathActive,
|
|
19473
|
+
resolved.options.optionLineNumbers,
|
|
19425
19474
|
(groupName) => {
|
|
19426
19475
|
currentActiveGroup = currentActiveGroup?.toLowerCase() === groupName.toLowerCase() ? null : groupName;
|
|
19427
19476
|
if (onActiveGroupChange) onActiveGroupChange(currentActiveGroup);
|
|
@@ -19460,7 +19509,25 @@ function renderGantt(container, resolved, palette, isDark, options, exportDims)
|
|
|
19460
19509
|
renderTimeScaleHorizontal(g, xScale, innerWidth, innerHeight, palette.text);
|
|
19461
19510
|
renderWeekendBands(g, resolved, xScale, innerHeight, palette, isDark);
|
|
19462
19511
|
renderHolidayBands(g, svg, resolved, xScale, innerHeight, palette, isDark, marginTop - 4, leftMargin, onClickItem);
|
|
19463
|
-
renderErasAndMarkers(g, resolved, xScale, innerHeight, palette);
|
|
19512
|
+
renderErasAndMarkers(g, svg, resolved, xScale, innerHeight, palette);
|
|
19513
|
+
let todayDate = null;
|
|
19514
|
+
let todayX = -1;
|
|
19515
|
+
const todayColor = palette.accent || "#e74c3c";
|
|
19516
|
+
const todayMarkerLineNum = resolved.options.optionLineNumbers["today-marker"];
|
|
19517
|
+
if (resolved.options.todayMarker !== "off") {
|
|
19518
|
+
if (resolved.options.todayMarker === "on") {
|
|
19519
|
+
todayDate = /* @__PURE__ */ new Date();
|
|
19520
|
+
} else {
|
|
19521
|
+
todayDate = /* @__PURE__ */ new Date(resolved.options.todayMarker + "T00:00:00");
|
|
19522
|
+
}
|
|
19523
|
+
todayX = xScale(dateToFractionalYear(todayDate));
|
|
19524
|
+
if (todayX >= 0 && todayX <= innerWidth) {
|
|
19525
|
+
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");
|
|
19526
|
+
if (todayMarkerLineNum) todayLine.attr("data-line-number", String(todayMarkerLineNum));
|
|
19527
|
+
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");
|
|
19528
|
+
if (todayMarkerLineNum) todayLabel.attr("data-line-number", String(todayMarkerLineNum));
|
|
19529
|
+
}
|
|
19530
|
+
}
|
|
19464
19531
|
const taskPositions = /* @__PURE__ */ new Map();
|
|
19465
19532
|
const groupPositions = /* @__PURE__ */ new Map();
|
|
19466
19533
|
const lanePositions = /* @__PURE__ */ new Map();
|
|
@@ -19496,6 +19563,7 @@ function renderGantt(container, resolved, palette, isDark, options, exportDims)
|
|
|
19496
19563
|
laneBarWidth = Math.max(lx2 - lx1, 2);
|
|
19497
19564
|
}
|
|
19498
19565
|
lanePositions.set(row.laneName, { x1: lx1, x2: lx1 + laneBarWidth, y: yOffset + BAR_H / 2 });
|
|
19566
|
+
renderLabelBand(svg, marginTop + yOffset + BAR_H / 2, leftMargin, laneColor, palette, "lane", { key: "data-lane", value: row.laneName });
|
|
19499
19567
|
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", () => {
|
|
19500
19568
|
if (onToggleLane) onToggleLane(row.laneName);
|
|
19501
19569
|
}).on("mouseenter", () => {
|
|
@@ -19521,7 +19589,7 @@ function renderGantt(container, resolved, palette, isDark, options, exportDims)
|
|
|
19521
19589
|
});
|
|
19522
19590
|
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);
|
|
19523
19591
|
if (row.aggregateProgress !== null && row.aggregateProgress > 0) {
|
|
19524
|
-
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("
|
|
19592
|
+
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");
|
|
19525
19593
|
}
|
|
19526
19594
|
}
|
|
19527
19595
|
yOffset += BAR_H + ROW_GAP;
|
|
@@ -19532,6 +19600,7 @@ function renderGantt(container, resolved, palette, isDark, options, exportDims)
|
|
|
19532
19600
|
const toggleIcon = isCollapsed ? "\u25BA" : "\u25BC";
|
|
19533
19601
|
const tagColor = resolveTagColor(group.metadata, resolved.tagGroups, currentActiveGroup, true);
|
|
19534
19602
|
const groupColor = tagColor && tagColor !== "#999999" ? tagColor : group.color || palette.textMuted;
|
|
19603
|
+
renderLabelBand(svg, marginTop + yOffset + BAR_H / 2, leftMargin, groupColor, palette, "group", { key: "data-group", value: group.name });
|
|
19535
19604
|
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", () => {
|
|
19536
19605
|
if (onToggleGroup) onToggleGroup(group.name);
|
|
19537
19606
|
}).on("mouseenter", () => {
|
|
@@ -19541,7 +19610,8 @@ function renderGantt(container, resolved, palette, isDark, options, exportDims)
|
|
|
19541
19610
|
resetHighlight(g, svg);
|
|
19542
19611
|
hideGanttDateIndicators(g);
|
|
19543
19612
|
});
|
|
19544
|
-
const
|
|
19613
|
+
const groupIndent = group.depth <= 2 ? group.depth * 14 : 2 * 14 + (group.depth - 2) * 8;
|
|
19614
|
+
const labelX = 10 + groupIndent;
|
|
19545
19615
|
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)}%` : ""));
|
|
19546
19616
|
const gStart = dateToFractionalYear(group.startDate);
|
|
19547
19617
|
const gEnd = dateToFractionalYear(group.endDate);
|
|
@@ -19559,7 +19629,12 @@ function renderGantt(container, resolved, palette, isDark, options, exportDims)
|
|
|
19559
19629
|
});
|
|
19560
19630
|
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);
|
|
19561
19631
|
if (group.progress !== null && group.progress > 0) {
|
|
19562
|
-
summaryG.append("rect").attr("x", gx1).attr("y", yOffset).attr("width", barWidth * Math.min(group.progress / 100, 1)).attr("height", BAR_H).attr("
|
|
19632
|
+
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);
|
|
19633
|
+
}
|
|
19634
|
+
const summaryLabel = group.name + (group.progress !== null ? ` ${Math.round(group.progress)}%` : "");
|
|
19635
|
+
const summaryPlacement = computeBarLabel(summaryLabel, gx1, barWidth, innerWidth, palette.text);
|
|
19636
|
+
if (summaryPlacement) {
|
|
19637
|
+
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);
|
|
19563
19638
|
}
|
|
19564
19639
|
groupPositions.set(group.name, { x1: gx1, x2: gx1 + barWidth, y: yOffset + BAR_H / 2 });
|
|
19565
19640
|
} else {
|
|
@@ -19574,7 +19649,12 @@ function renderGantt(container, resolved, palette, isDark, options, exportDims)
|
|
|
19574
19649
|
});
|
|
19575
19650
|
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);
|
|
19576
19651
|
if (group.progress !== null && group.progress > 0) {
|
|
19577
|
-
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("
|
|
19652
|
+
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);
|
|
19653
|
+
}
|
|
19654
|
+
const expandedLabel = group.name + (group.progress !== null ? ` ${Math.round(group.progress)}%` : "");
|
|
19655
|
+
const expandedPlacement = computeBarLabel(expandedLabel, gx1, groupBarWidth, innerWidth, palette.text);
|
|
19656
|
+
if (expandedPlacement) {
|
|
19657
|
+
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);
|
|
19578
19658
|
}
|
|
19579
19659
|
}
|
|
19580
19660
|
}
|
|
@@ -19582,9 +19662,12 @@ function renderGantt(container, resolved, palette, isDark, options, exportDims)
|
|
|
19582
19662
|
} else if (row.type === "task") {
|
|
19583
19663
|
const rt = row.task;
|
|
19584
19664
|
const task = rt.task;
|
|
19585
|
-
const
|
|
19665
|
+
const barColor = resolveTaskColor(rt, currentActiveGroup, resolved, seriesColors2, palette);
|
|
19666
|
+
const depth = rt.groupPath.length;
|
|
19667
|
+
const indent = depth <= 2 ? depth * 14 : 2 * 14 + (depth - 2) * 8;
|
|
19668
|
+
const taskLabelX = isTagMode ? 20 : 6 + indent;
|
|
19586
19669
|
const topGroup = rt.groupPath.length > 0 ? rt.groupPath[0] : null;
|
|
19587
|
-
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").
|
|
19670
|
+
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", () => {
|
|
19588
19671
|
if (onClickItem) onClickItem(task.lineNumber);
|
|
19589
19672
|
}).on("mouseenter", () => {
|
|
19590
19673
|
if (rt.isMilestone) {
|
|
@@ -19595,13 +19678,13 @@ function renderGantt(container, resolved, palette, isDark, options, exportDims)
|
|
|
19595
19678
|
}).on("mouseleave", () => {
|
|
19596
19679
|
resetHighlight(g, svg);
|
|
19597
19680
|
});
|
|
19681
|
+
appendTaskIcon(taskLabel, task.label, rt.isMilestone, barColor, palette.text);
|
|
19598
19682
|
for (const [key, value] of Object.entries(rt.effectiveMetadata)) {
|
|
19599
19683
|
taskLabel.attr(`data-tag-${key}`, value.toLowerCase());
|
|
19600
19684
|
}
|
|
19601
19685
|
if (rt.isCriticalPath) {
|
|
19602
19686
|
taskLabel.attr("data-critical-path", "true");
|
|
19603
19687
|
}
|
|
19604
|
-
let barColor = resolveTaskColor(rt, currentActiveGroup, resolved, seriesColors2, palette);
|
|
19605
19688
|
if (rt.isMilestone) {
|
|
19606
19689
|
const mx = xScale(dateToFractionalYear(rt.startDate));
|
|
19607
19690
|
const my = yOffset + BAR_H / 2;
|
|
@@ -19679,32 +19762,40 @@ function renderGantt(container, resolved, palette, isDark, options, exportDims)
|
|
|
19679
19762
|
progGrad.append("stop").attr("offset", "100%").attr("stop-color", barColor).attr("stop-opacity", 0);
|
|
19680
19763
|
progressFill = `url(#${progGradId})`;
|
|
19681
19764
|
}
|
|
19682
|
-
taskG.append("rect").attr("class", "gantt-progress").attr("x", x1).attr("y", yOffset).attr("width", progressWidth).attr("height", BAR_H).attr("
|
|
19765
|
+
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);
|
|
19683
19766
|
}
|
|
19684
19767
|
if (rt.isCriticalPath) {
|
|
19685
19768
|
taskG.attr("data-critical-path", "true");
|
|
19686
19769
|
}
|
|
19687
|
-
const
|
|
19688
|
-
if (
|
|
19689
|
-
taskG.append("text").attr("x",
|
|
19770
|
+
const labelPlacement = computeBarLabel(task.label, x1, barWidth, innerWidth, palette.text);
|
|
19771
|
+
if (labelPlacement) {
|
|
19772
|
+
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);
|
|
19690
19773
|
}
|
|
19691
19774
|
taskPositions.set(task.id, { x1, x2: x1 + barWidth, y: yOffset + BAR_H / 2 });
|
|
19692
19775
|
}
|
|
19693
19776
|
yOffset += BAR_H + ROW_GAP;
|
|
19694
19777
|
}
|
|
19695
19778
|
}
|
|
19696
|
-
if (
|
|
19697
|
-
|
|
19698
|
-
|
|
19699
|
-
|
|
19700
|
-
|
|
19701
|
-
|
|
19702
|
-
|
|
19703
|
-
|
|
19704
|
-
|
|
19705
|
-
|
|
19706
|
-
|
|
19707
|
-
|
|
19779
|
+
if (todayDate && todayX >= 0 && todayX <= innerWidth) {
|
|
19780
|
+
const todayHoverG = g.append("g").attr("class", "gantt-today-hover").style("cursor", "pointer");
|
|
19781
|
+
todayHoverG.append("rect").attr("x", todayX - 10).attr("y", -6).attr("width", 20).attr("height", innerHeight + 16).attr("fill", "transparent").attr("pointer-events", "all");
|
|
19782
|
+
const todayDateObj = todayDate;
|
|
19783
|
+
todayHoverG.on("mouseenter", () => {
|
|
19784
|
+
g.selectAll(".gantt-task").attr("opacity", FADE_OPACITY);
|
|
19785
|
+
g.selectAll(".gantt-milestone").attr("opacity", FADE_OPACITY);
|
|
19786
|
+
g.selectAll(".gantt-group-bar, .gantt-group-summary").attr("opacity", FADE_OPACITY);
|
|
19787
|
+
svg.selectAll(".gantt-group-label").attr("opacity", FADE_OPACITY);
|
|
19788
|
+
svg.selectAll(".gantt-task-label").attr("opacity", FADE_OPACITY);
|
|
19789
|
+
svg.selectAll(".gantt-lane-header").attr("opacity", FADE_OPACITY);
|
|
19790
|
+
g.selectAll(".gantt-lane-band, .gantt-lane-accent, .gantt-lane-band-group").attr("opacity", FADE_OPACITY);
|
|
19791
|
+
g.selectAll(".gantt-dep-arrow, .gantt-dep-arrowhead").attr("opacity", FADE_OPACITY);
|
|
19792
|
+
g.selectAll(".gantt-era-group").attr("opacity", FADE_OPACITY);
|
|
19793
|
+
g.selectAll(".gantt-marker-group").attr("opacity", FADE_OPACITY);
|
|
19794
|
+
showGanttDateIndicators(g, xScale, todayDateObj, null, innerHeight, todayColor);
|
|
19795
|
+
}).on("mouseleave", () => {
|
|
19796
|
+
resetHighlight(g, svg);
|
|
19797
|
+
hideGanttDateIndicators(g);
|
|
19798
|
+
});
|
|
19708
19799
|
}
|
|
19709
19800
|
if (resolved.options.dependencies) {
|
|
19710
19801
|
renderDependencyArrows(g, resolved, taskPositions, groupPositions, collapsedGroups, palette, isDark, isTagMode, lanePositions, collapsedLanes, taskLaneMap);
|
|
@@ -19821,10 +19912,10 @@ function renderDependencyArrows(g, resolved, taskPositions, groupPositions, coll
|
|
|
19821
19912
|
const path = `M ${sx} ${sy} C ${sx + cpOffset} ${sy}, ${tx - cpOffset} ${ty}, ${tx} ${ty}`;
|
|
19822
19913
|
const arrowColor = mix(palette.text, palette.bg, 50);
|
|
19823
19914
|
const isCpArrow = rt.isCriticalPath && targetTask.isCriticalPath;
|
|
19824
|
-
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);
|
|
19915
|
+
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);
|
|
19825
19916
|
const headSize = 5;
|
|
19826
19917
|
const angle = 0;
|
|
19827
|
-
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);
|
|
19918
|
+
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);
|
|
19828
19919
|
}
|
|
19829
19920
|
}
|
|
19830
19921
|
}
|
|
@@ -19845,7 +19936,9 @@ function applyCriticalPathHighlight(svg, chartG) {
|
|
|
19845
19936
|
el.attr("opacity", el.attr("data-critical-path") === "true" ? 1 : FADE_OPACITY);
|
|
19846
19937
|
});
|
|
19847
19938
|
svg.selectAll(".gantt-group-label").attr("opacity", FADE_OPACITY);
|
|
19939
|
+
svg.selectAll(".gantt-group-band-bg, .gantt-group-band-accent").attr("opacity", FADE_OPACITY);
|
|
19848
19940
|
svg.selectAll(".gantt-lane-header").attr("opacity", FADE_OPACITY);
|
|
19941
|
+
svg.selectAll(".gantt-lane-band-bg, .gantt-lane-band-accent").attr("opacity", FADE_OPACITY);
|
|
19849
19942
|
chartG.selectAll(".gantt-lane-band, .gantt-lane-accent").attr("opacity", FADE_OPACITY);
|
|
19850
19943
|
chartG.selectAll(".gantt-dep-arrow, .gantt-dep-arrowhead").each(function() {
|
|
19851
19944
|
const el = d3Selection10.select(this);
|
|
@@ -19857,7 +19950,9 @@ function resetHighlightAll(svg, chartG) {
|
|
|
19857
19950
|
chartG.selectAll(".gantt-group-bar, .gantt-group-summary").attr("opacity", 1);
|
|
19858
19951
|
svg.selectAll(".gantt-task-label").attr("opacity", 1);
|
|
19859
19952
|
svg.selectAll(".gantt-group-label").attr("opacity", 1);
|
|
19953
|
+
svg.selectAll(".gantt-group-band-bg, .gantt-group-band-accent").attr("opacity", 1);
|
|
19860
19954
|
svg.selectAll(".gantt-lane-header").attr("opacity", 1);
|
|
19955
|
+
svg.selectAll(".gantt-lane-band-bg, .gantt-lane-band-accent").attr("opacity", 1);
|
|
19861
19956
|
chartG.selectAll(".gantt-lane-band, .gantt-lane-accent").attr("opacity", 1);
|
|
19862
19957
|
chartG.selectAll(".gantt-dep-arrow, .gantt-dep-arrowhead").attr("opacity", 0.5);
|
|
19863
19958
|
}
|
|
@@ -19873,7 +19968,7 @@ function drawSwimlaneIcon(parent, x, y, isActive, palette) {
|
|
|
19873
19968
|
}
|
|
19874
19969
|
return iconG;
|
|
19875
19970
|
}
|
|
19876
|
-
function renderTagLegend(svg, chartG, tagGroups, activeGroupName, chartLeftMargin, chartInnerWidth, legendY, palette, isDark, hasCriticalPath, criticalPathActive, onToggle, onToggleCriticalPath, currentSwimlaneGroup, onSwimlaneChange, legendViewMode, resolvedTasks) {
|
|
19971
|
+
function renderTagLegend(svg, chartG, tagGroups, activeGroupName, chartLeftMargin, chartInnerWidth, legendY, palette, isDark, hasCriticalPath, criticalPathActive, optionLineNumbers, onToggle, onToggleCriticalPath, currentSwimlaneGroup, onSwimlaneChange, legendViewMode, resolvedTasks) {
|
|
19877
19972
|
const groupBg = isDark ? mix(palette.surface, palette.bg, 50) : mix(palette.surface, palette.bg, 30);
|
|
19878
19973
|
let visibleGroups;
|
|
19879
19974
|
if (activeGroupName) {
|
|
@@ -19934,7 +20029,8 @@ function renderTagLegend(svg, chartG, tagGroups, activeGroupName, chartLeftMargi
|
|
|
19934
20029
|
if (visibleGroups.length > 0) totalW += LEGEND_GROUP_GAP;
|
|
19935
20030
|
totalW += cpPillW;
|
|
19936
20031
|
}
|
|
19937
|
-
const
|
|
20032
|
+
const containerWidth = chartLeftMargin + chartInnerWidth + RIGHT_MARGIN;
|
|
20033
|
+
const legendX = (containerWidth - totalW) / 2;
|
|
19938
20034
|
const legendRow = svg.append("g").attr("class", "gantt-tag-legend-container").attr("transform", `translate(${legendX}, ${legendY})`);
|
|
19939
20035
|
let cursorX = 0;
|
|
19940
20036
|
for (let i = 0; i < visibleGroups.length; i++) {
|
|
@@ -19946,7 +20042,7 @@ function renderTagLegend(svg, chartG, tagGroups, activeGroupName, chartLeftMargi
|
|
|
19946
20042
|
const pillW = group.name.length * LEGEND_PILL_FONT_W + LEGEND_PILL_PAD + iconReserve;
|
|
19947
20043
|
const pillH = isActive ? LEGEND_HEIGHT - LEGEND_CAPSULE_PAD * 2 : LEGEND_HEIGHT;
|
|
19948
20044
|
const groupW = groupWidths[i];
|
|
19949
|
-
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", () => {
|
|
20045
|
+
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", () => {
|
|
19950
20046
|
if (onToggle) onToggle(group.name);
|
|
19951
20047
|
});
|
|
19952
20048
|
if (isActive) {
|
|
@@ -19980,7 +20076,7 @@ function renderTagLegend(svg, chartG, tagGroups, activeGroupName, chartLeftMargi
|
|
|
19980
20076
|
let ex = pillXOff + pillW + LEGEND_CAPSULE_PAD + 4;
|
|
19981
20077
|
for (const entry of entries) {
|
|
19982
20078
|
const entryValue = entry.value.toLowerCase();
|
|
19983
|
-
const entryG = gEl.append("g").attr("class", "gantt-legend-entry").style("cursor", "pointer");
|
|
20079
|
+
const entryG = gEl.append("g").attr("class", "gantt-legend-entry").attr("data-line-number", String(entry.lineNumber)).style("cursor", "pointer");
|
|
19984
20080
|
entryG.append("circle").attr("cx", ex + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
19985
20081
|
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);
|
|
19986
20082
|
entryG.on("mouseenter", () => {
|
|
@@ -20016,9 +20112,11 @@ function renderTagLegend(svg, chartG, tagGroups, activeGroupName, chartLeftMargi
|
|
|
20016
20112
|
cursorX += groupW + LEGEND_GROUP_GAP;
|
|
20017
20113
|
}
|
|
20018
20114
|
if (hasCriticalPath) {
|
|
20115
|
+
const cpLineNum = optionLineNumbers["critical-path"];
|
|
20019
20116
|
const cpG = legendRow.append("g").attr("transform", `translate(${cursorX}, 0)`).attr("class", "gantt-legend-critical-path").style("cursor", "pointer").on("click", () => {
|
|
20020
20117
|
if (onToggleCriticalPath) onToggleCriticalPath();
|
|
20021
20118
|
});
|
|
20119
|
+
if (cpLineNum) cpG.attr("data-line-number", String(cpLineNum));
|
|
20022
20120
|
cpG.append("rect").attr("width", cpPillW).attr("height", LEGEND_HEIGHT).attr("rx", LEGEND_HEIGHT / 2).attr("fill", criticalPathActive ? palette.bg : groupBg);
|
|
20023
20121
|
if (criticalPathActive) {
|
|
20024
20122
|
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);
|
|
@@ -20036,7 +20134,7 @@ function renderTagLegend(svg, chartG, tagGroups, activeGroupName, chartLeftMargi
|
|
|
20036
20134
|
});
|
|
20037
20135
|
}
|
|
20038
20136
|
}
|
|
20039
|
-
function renderErasAndMarkers(g, resolved, xScale, innerHeight, palette) {
|
|
20137
|
+
function renderErasAndMarkers(g, svg, resolved, xScale, innerHeight, palette) {
|
|
20040
20138
|
for (let i = 0; i < resolved.eras.length; i++) {
|
|
20041
20139
|
const era = resolved.eras[i];
|
|
20042
20140
|
const color = era.color || ERA_COLORS[i % ERA_COLORS.length];
|
|
@@ -20047,13 +20145,23 @@ function renderErasAndMarkers(g, resolved, xScale, innerHeight, palette) {
|
|
|
20047
20145
|
const hoverEraOpacity = 0.16;
|
|
20048
20146
|
const eraStartDate = parseDateStringToDate(era.startDate);
|
|
20049
20147
|
const eraEndDate = parseDateStringToDate(era.endDate);
|
|
20050
|
-
const eraG = g.append("g").attr("class", "gantt-era-group");
|
|
20148
|
+
const eraG = g.append("g").attr("class", "gantt-era-group").attr("data-line-number", String(era.lineNumber));
|
|
20051
20149
|
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);
|
|
20052
|
-
eraG.append("text").attr("class", "gantt-era-label").attr("x", (sx + ex) / 2).attr("y",
|
|
20150
|
+
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);
|
|
20053
20151
|
eraG.on("mouseenter", () => {
|
|
20152
|
+
g.selectAll(".gantt-task").attr("opacity", FADE_OPACITY);
|
|
20153
|
+
g.selectAll(".gantt-milestone").attr("opacity", FADE_OPACITY);
|
|
20154
|
+
g.selectAll(".gantt-group-bar, .gantt-group-summary").attr("opacity", FADE_OPACITY);
|
|
20155
|
+
svg.selectAll(".gantt-group-label").attr("opacity", FADE_OPACITY);
|
|
20156
|
+
svg.selectAll(".gantt-task-label").attr("opacity", FADE_OPACITY);
|
|
20157
|
+
svg.selectAll(".gantt-lane-header").attr("opacity", FADE_OPACITY);
|
|
20158
|
+
g.selectAll(".gantt-lane-band, .gantt-lane-accent, .gantt-lane-band-group").attr("opacity", FADE_OPACITY);
|
|
20159
|
+
g.selectAll(".gantt-dep-arrow, .gantt-dep-arrowhead").attr("opacity", FADE_OPACITY);
|
|
20160
|
+
g.selectAll(".gantt-marker-group").attr("opacity", FADE_OPACITY);
|
|
20054
20161
|
eraRect.attr("opacity", hoverEraOpacity);
|
|
20055
20162
|
showGanttDateIndicators(g, xScale, eraStartDate, eraEndDate, innerHeight, color);
|
|
20056
20163
|
}).on("mouseleave", () => {
|
|
20164
|
+
resetHighlight(g, svg);
|
|
20057
20165
|
eraRect.attr("opacity", baseEraOpacity);
|
|
20058
20166
|
hideGanttDateIndicators(g);
|
|
20059
20167
|
});
|
|
@@ -20065,22 +20173,31 @@ function renderErasAndMarkers(g, resolved, xScale, innerHeight, palette) {
|
|
|
20065
20173
|
const diamondSize = 5;
|
|
20066
20174
|
const labelY = -24;
|
|
20067
20175
|
const diamondY = labelY + 14;
|
|
20068
|
-
const markerG = g.append("g").attr("class", "gantt-marker-group").style("cursor", "pointer");
|
|
20176
|
+
const markerG = g.append("g").attr("class", "gantt-marker-group").attr("data-line-number", String(marker.lineNumber)).style("cursor", "pointer");
|
|
20069
20177
|
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");
|
|
20070
20178
|
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);
|
|
20071
20179
|
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);
|
|
20072
20180
|
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);
|
|
20073
20181
|
const markerLine = markerG.select(".gantt-marker");
|
|
20074
|
-
const markerLabel = markerG.select(".gantt-marker-label");
|
|
20075
20182
|
const markerDiamond = markerG.select("path");
|
|
20076
20183
|
markerG.on("mouseenter", () => {
|
|
20077
|
-
|
|
20078
|
-
|
|
20184
|
+
g.selectAll(".gantt-task").attr("opacity", FADE_OPACITY);
|
|
20185
|
+
g.selectAll(".gantt-milestone").attr("opacity", FADE_OPACITY);
|
|
20186
|
+
g.selectAll(".gantt-group-bar, .gantt-group-summary").attr("opacity", FADE_OPACITY);
|
|
20187
|
+
svg.selectAll(".gantt-group-label").attr("opacity", FADE_OPACITY);
|
|
20188
|
+
svg.selectAll(".gantt-task-label").attr("opacity", FADE_OPACITY);
|
|
20189
|
+
svg.selectAll(".gantt-lane-header").attr("opacity", FADE_OPACITY);
|
|
20190
|
+
g.selectAll(".gantt-lane-band, .gantt-lane-accent, .gantt-lane-band-group").attr("opacity", FADE_OPACITY);
|
|
20191
|
+
g.selectAll(".gantt-dep-arrow, .gantt-dep-arrowhead").attr("opacity", FADE_OPACITY);
|
|
20192
|
+
g.selectAll(".gantt-era-group").attr("opacity", FADE_OPACITY);
|
|
20193
|
+
g.selectAll(".gantt-marker-group").attr("opacity", FADE_OPACITY);
|
|
20194
|
+
markerG.attr("opacity", 1);
|
|
20195
|
+
markerLine.attr("opacity", 0.8);
|
|
20079
20196
|
markerDiamond.attr("opacity", 0);
|
|
20080
|
-
showGanttDateIndicators(g, xScale, markerDate, null, innerHeight, color);
|
|
20197
|
+
showGanttDateIndicators(g, xScale, markerDate, null, innerHeight, color, { skipStartLine: true });
|
|
20081
20198
|
}).on("mouseleave", () => {
|
|
20199
|
+
resetHighlight(g, svg);
|
|
20082
20200
|
markerLine.attr("opacity", 0.5);
|
|
20083
|
-
markerLabel.attr("opacity", 1);
|
|
20084
20201
|
markerDiamond.attr("opacity", 0.9);
|
|
20085
20202
|
hideGanttDateIndicators(g);
|
|
20086
20203
|
});
|
|
@@ -20094,11 +20211,7 @@ function parseDateStringToDate(s) {
|
|
|
20094
20211
|
return new Date(year, month, day);
|
|
20095
20212
|
}
|
|
20096
20213
|
function parseDateToFractionalYear(s) {
|
|
20097
|
-
|
|
20098
|
-
const year = parts[0];
|
|
20099
|
-
const month = parts.length >= 2 ? parts[1] : 1;
|
|
20100
|
-
const day = parts.length >= 3 ? parts[2] : 1;
|
|
20101
|
-
return year + (month - 1) / 12 + (day - 1) / 365;
|
|
20214
|
+
return dateToFractionalYear(parseDateStringToDate(s));
|
|
20102
20215
|
}
|
|
20103
20216
|
function highlightDeps(g, svg, taskId, resolved) {
|
|
20104
20217
|
const related = /* @__PURE__ */ new Set([taskId]);
|
|
@@ -20132,6 +20245,7 @@ function highlightDeps(g, svg, taskId, resolved) {
|
|
|
20132
20245
|
const isRelated = from && related.has(from) || to && related.has(to);
|
|
20133
20246
|
el.attr("opacity", isRelated ? 0.5 : FADE_OPACITY);
|
|
20134
20247
|
});
|
|
20248
|
+
g.selectAll(".gantt-marker-group").attr("opacity", FADE_OPACITY);
|
|
20135
20249
|
}
|
|
20136
20250
|
function highlightGroup(g, svg, groupName) {
|
|
20137
20251
|
g.selectAll(".gantt-task").each(function() {
|
|
@@ -20154,7 +20268,12 @@ function highlightGroup(g, svg, groupName) {
|
|
|
20154
20268
|
const el = d3Selection10.select(this);
|
|
20155
20269
|
el.attr("opacity", el.attr("data-group") === groupName ? 1 : FADE_OPACITY);
|
|
20156
20270
|
});
|
|
20271
|
+
svg.selectAll(".gantt-group-band-bg, .gantt-group-band-accent").each(function() {
|
|
20272
|
+
const el = d3Selection10.select(this);
|
|
20273
|
+
el.attr("opacity", el.attr("data-group") === groupName ? 1 : FADE_OPACITY);
|
|
20274
|
+
});
|
|
20157
20275
|
svg.selectAll(".gantt-lane-header").attr("opacity", FADE_OPACITY);
|
|
20276
|
+
svg.selectAll(".gantt-lane-band-bg, .gantt-lane-band-accent").attr("opacity", FADE_OPACITY);
|
|
20158
20277
|
g.selectAll(".gantt-lane-band, .gantt-lane-accent").attr("opacity", FADE_OPACITY);
|
|
20159
20278
|
g.selectAll(".gantt-marker-group").attr("opacity", FADE_OPACITY);
|
|
20160
20279
|
}
|
|
@@ -20181,8 +20300,13 @@ function highlightLane(g, svg, tagKey, laneName) {
|
|
|
20181
20300
|
const el = d3Selection10.select(this);
|
|
20182
20301
|
el.attr("opacity", el.attr("data-lane") === laneName ? 1 : FADE_OPACITY);
|
|
20183
20302
|
});
|
|
20303
|
+
svg.selectAll(".gantt-lane-band-bg, .gantt-lane-band-accent").each(function() {
|
|
20304
|
+
const el = d3Selection10.select(this);
|
|
20305
|
+
el.attr("opacity", el.attr("data-lane") === laneName ? 1 : FADE_OPACITY);
|
|
20306
|
+
});
|
|
20184
20307
|
g.selectAll(".gantt-group-bar, .gantt-group-summary").attr("opacity", FADE_OPACITY);
|
|
20185
20308
|
svg.selectAll(".gantt-group-label").attr("opacity", FADE_OPACITY);
|
|
20309
|
+
svg.selectAll(".gantt-group-band-bg, .gantt-group-band-accent").attr("opacity", FADE_OPACITY);
|
|
20186
20310
|
g.selectAll(".gantt-marker-group").attr("opacity", FADE_OPACITY);
|
|
20187
20311
|
}
|
|
20188
20312
|
function highlightTask(g, svg, taskId) {
|
|
@@ -20197,7 +20321,9 @@ function highlightTask(g, svg, taskId) {
|
|
|
20197
20321
|
});
|
|
20198
20322
|
g.selectAll(".gantt-group-bar, .gantt-group-summary").attr("opacity", FADE_OPACITY);
|
|
20199
20323
|
svg.selectAll(".gantt-group-label").attr("opacity", FADE_OPACITY);
|
|
20324
|
+
svg.selectAll(".gantt-group-band-bg, .gantt-group-band-accent").attr("opacity", FADE_OPACITY);
|
|
20200
20325
|
svg.selectAll(".gantt-lane-header").attr("opacity", FADE_OPACITY);
|
|
20326
|
+
svg.selectAll(".gantt-lane-band-bg, .gantt-lane-band-accent").attr("opacity", FADE_OPACITY);
|
|
20201
20327
|
g.selectAll(".gantt-lane-band, .gantt-lane-accent, .gantt-lane-band-group").attr("opacity", FADE_OPACITY);
|
|
20202
20328
|
g.selectAll(".gantt-dep-arrow, .gantt-dep-arrowhead").attr("opacity", FADE_OPACITY);
|
|
20203
20329
|
g.selectAll(".gantt-marker-group").attr("opacity", FADE_OPACITY);
|
|
@@ -20214,7 +20340,9 @@ function highlightMilestone(g, svg, taskId) {
|
|
|
20214
20340
|
});
|
|
20215
20341
|
g.selectAll(".gantt-group-bar, .gantt-group-summary").attr("opacity", FADE_OPACITY);
|
|
20216
20342
|
svg.selectAll(".gantt-group-label").attr("opacity", FADE_OPACITY);
|
|
20343
|
+
svg.selectAll(".gantt-group-band-bg, .gantt-group-band-accent").attr("opacity", FADE_OPACITY);
|
|
20217
20344
|
svg.selectAll(".gantt-lane-header").attr("opacity", FADE_OPACITY);
|
|
20345
|
+
svg.selectAll(".gantt-lane-band-bg, .gantt-lane-band-accent").attr("opacity", FADE_OPACITY);
|
|
20218
20346
|
g.selectAll(".gantt-lane-band, .gantt-lane-accent, .gantt-lane-band-group").attr("opacity", FADE_OPACITY);
|
|
20219
20347
|
g.selectAll(".gantt-dep-arrow, .gantt-dep-arrowhead").attr("opacity", FADE_OPACITY);
|
|
20220
20348
|
g.selectAll(".gantt-marker-group").attr("opacity", FADE_OPACITY);
|
|
@@ -20233,11 +20361,14 @@ function resetHighlight(g, svg) {
|
|
|
20233
20361
|
g.selectAll(".gantt-task, .gantt-milestone").attr("opacity", 1);
|
|
20234
20362
|
g.selectAll(".gantt-group-bar, .gantt-group-summary").attr("opacity", 1);
|
|
20235
20363
|
svg.selectAll(".gantt-group-label").attr("opacity", 1);
|
|
20364
|
+
svg.selectAll(".gantt-group-band-bg, .gantt-group-band-accent").attr("opacity", 1);
|
|
20236
20365
|
svg.selectAll(".gantt-task-label").attr("opacity", 1);
|
|
20237
20366
|
svg.selectAll(".gantt-lane-header").attr("opacity", 1);
|
|
20367
|
+
svg.selectAll(".gantt-lane-band-bg, .gantt-lane-band-accent").attr("opacity", 1);
|
|
20238
20368
|
g.selectAll(".gantt-lane-band, .gantt-lane-accent, .gantt-lane-band-group").attr("opacity", 1);
|
|
20239
20369
|
g.selectAll(".gantt-dep-arrow, .gantt-dep-arrowhead").attr("opacity", 0.5);
|
|
20240
20370
|
g.selectAll(".gantt-marker-group").attr("opacity", 1);
|
|
20371
|
+
g.selectAll(".gantt-era-group").attr("opacity", 1);
|
|
20241
20372
|
}
|
|
20242
20373
|
function buildRowList(resolved, collapsedGroups) {
|
|
20243
20374
|
const rows = [];
|
|
@@ -20391,15 +20522,18 @@ function diamondPoints(cx, cy, size) {
|
|
|
20391
20522
|
function formatGanttDate(d) {
|
|
20392
20523
|
return `${MONTH_ABBR[d.getMonth()]} ${d.getDate()}, ${d.getFullYear()}`;
|
|
20393
20524
|
}
|
|
20394
|
-
function showGanttDateIndicators(g, xScale, startDate, endDate, innerHeight, color) {
|
|
20525
|
+
function showGanttDateIndicators(g, xScale, startDate, endDate, innerHeight, color, options) {
|
|
20395
20526
|
g.selectAll(".gantt-scale-tick").attr("opacity", 0.05);
|
|
20396
20527
|
g.selectAll(".gantt-today").attr("opacity", 0.05);
|
|
20528
|
+
const hg = g.append("g").attr("class", "gantt-hover-date").attr("pointer-events", "none");
|
|
20397
20529
|
const tickLen = 6;
|
|
20398
20530
|
const startPos = xScale(dateToFractionalYear(startDate));
|
|
20399
20531
|
const startLabel = formatGanttDate(startDate);
|
|
20400
|
-
|
|
20401
|
-
|
|
20402
|
-
|
|
20532
|
+
if (!options?.skipStartLine) {
|
|
20533
|
+
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);
|
|
20534
|
+
}
|
|
20535
|
+
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);
|
|
20536
|
+
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);
|
|
20403
20537
|
if (endDate && endDate.getTime() !== startDate.getTime()) {
|
|
20404
20538
|
const endPos = xScale(dateToFractionalYear(endDate));
|
|
20405
20539
|
const endLabel = formatGanttDate(endDate);
|
|
@@ -20416,15 +20550,15 @@ function showGanttDateIndicators(g, xScale, startDate, endDate, innerHeight, col
|
|
|
20416
20550
|
startAnchor = "middle";
|
|
20417
20551
|
endAnchor = "middle";
|
|
20418
20552
|
}
|
|
20419
|
-
|
|
20420
|
-
|
|
20553
|
+
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);
|
|
20554
|
+
hg.selectAll("text.gantt-hover-date").each(function() {
|
|
20421
20555
|
const el = d3Selection10.select(this);
|
|
20422
20556
|
if (el.text() === startLabel) {
|
|
20423
20557
|
el.attr("x", startLabelX).attr("text-anchor", startAnchor);
|
|
20424
20558
|
}
|
|
20425
20559
|
});
|
|
20426
|
-
|
|
20427
|
-
|
|
20560
|
+
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);
|
|
20561
|
+
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);
|
|
20428
20562
|
}
|
|
20429
20563
|
}
|
|
20430
20564
|
function hideGanttDateIndicators(g) {
|
|
@@ -20469,7 +20603,7 @@ function renderTimeScaleHorizontal(g, scale, innerWidth, innerHeight, textColor)
|
|
|
20469
20603
|
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);
|
|
20470
20604
|
}
|
|
20471
20605
|
}
|
|
20472
|
-
var 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;
|
|
20606
|
+
var 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;
|
|
20473
20607
|
var init_renderer9 = __esm({
|
|
20474
20608
|
"src/gantt/renderer.ts"() {
|
|
20475
20609
|
"use strict";
|
|
@@ -20486,6 +20620,12 @@ var init_renderer9 = __esm({
|
|
|
20486
20620
|
MIN_LEFT_MARGIN = 120;
|
|
20487
20621
|
BOTTOM_MARGIN = 40;
|
|
20488
20622
|
RIGHT_MARGIN = 20;
|
|
20623
|
+
CHAR_W = 6.5;
|
|
20624
|
+
LABEL_PAD = 8;
|
|
20625
|
+
LABEL_GAP = 5;
|
|
20626
|
+
BAND_ACCENT_W = 4;
|
|
20627
|
+
BAND_RADIUS = 4;
|
|
20628
|
+
bandClipCounter = 0;
|
|
20489
20629
|
JS_DAY_TO_WEEKDAY2 = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"];
|
|
20490
20630
|
ERA_COLORS = ["#5e81ac", "#a3be8c", "#ebcb8b", "#d08770", "#b48ead"];
|
|
20491
20631
|
FADE_OPACITY = 0.1;
|
|
@@ -20588,14 +20728,14 @@ function renderState(container, graph, layout, palette, isDark, onClickItem, exp
|
|
|
20588
20728
|
nodePositionMap.set(node.id, node);
|
|
20589
20729
|
}
|
|
20590
20730
|
const LABEL_CHAR_W = 7;
|
|
20591
|
-
const
|
|
20731
|
+
const LABEL_PAD2 = 8;
|
|
20592
20732
|
const LABEL_H = 16;
|
|
20593
20733
|
const PERP_OFFSET = 10;
|
|
20594
20734
|
const labelPositions = [];
|
|
20595
20735
|
for (let ei = 0; ei < layout.edges.length; ei++) {
|
|
20596
20736
|
const edge = layout.edges[ei];
|
|
20597
20737
|
if (!edge.label) continue;
|
|
20598
|
-
const bgW = edge.label.length * LABEL_CHAR_W +
|
|
20738
|
+
const bgW = edge.label.length * LABEL_CHAR_W + LABEL_PAD2;
|
|
20599
20739
|
let lx, ly;
|
|
20600
20740
|
if (edge.source === edge.target) {
|
|
20601
20741
|
const node = nodePositionMap.get(edge.source);
|
|
@@ -25098,12 +25238,12 @@ function renderQuadrant(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
25098
25238
|
};
|
|
25099
25239
|
const LABEL_MAX_FONT = 48;
|
|
25100
25240
|
const LABEL_MIN_FONT = 14;
|
|
25101
|
-
const
|
|
25241
|
+
const LABEL_PAD2 = 40;
|
|
25102
25242
|
const CHAR_WIDTH_RATIO3 = 0.6;
|
|
25103
25243
|
const estTextWidth = (text, fontSize) => text.length * fontSize * CHAR_WIDTH_RATIO3;
|
|
25104
25244
|
const quadrantLabelLayout = (text, qw2, qh2) => {
|
|
25105
|
-
const availW = qw2 -
|
|
25106
|
-
const availH = qh2 -
|
|
25245
|
+
const availW = qw2 - LABEL_PAD2;
|
|
25246
|
+
const availH = qh2 - LABEL_PAD2;
|
|
25107
25247
|
const words = text.split(/\s+/);
|
|
25108
25248
|
if (estTextWidth(text, LABEL_MAX_FONT) <= availW) {
|
|
25109
25249
|
const fs = Math.min(LABEL_MAX_FONT, availH);
|