epiq 1.4.1 → 1.4.3
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/gui/main.js +1595 -467
- package/dist/index.js +49 -49
- package/dist/mcp.js +37 -37
- package/package.json +1 -1
package/dist/gui/main.js
CHANGED
|
@@ -22849,6 +22849,19 @@ function useLocation() {
|
|
|
22849
22849
|
);
|
|
22850
22850
|
return React2.useContext(LocationContext).location;
|
|
22851
22851
|
}
|
|
22852
|
+
function useMatch(pattern) {
|
|
22853
|
+
invariant(
|
|
22854
|
+
useInRouterContext(),
|
|
22855
|
+
// TODO: This error is probably because they somehow have 2 versions of the
|
|
22856
|
+
// router loaded. We can help them understand how to avoid that.
|
|
22857
|
+
`useMatch() may be used only in the context of a <Router> component.`
|
|
22858
|
+
);
|
|
22859
|
+
let { pathname } = useLocation();
|
|
22860
|
+
return React2.useMemo(
|
|
22861
|
+
() => matchPath(pattern, decodePath(pathname)),
|
|
22862
|
+
[pathname, pattern]
|
|
22863
|
+
);
|
|
22864
|
+
}
|
|
22852
22865
|
var navigateEffectWarning = `You should call navigate() in a React.useEffect(), not when your component is first rendered.`;
|
|
22853
22866
|
function useIsomorphicLayoutEffect(cb) {
|
|
22854
22867
|
let isStatic = React2.useContext(NavigationContext).static;
|
|
@@ -24825,7 +24838,7 @@ function useViewTransitionState(to, { relative } = {}) {
|
|
|
24825
24838
|
}
|
|
24826
24839
|
|
|
24827
24840
|
// source/gui/client/App.tsx
|
|
24828
|
-
var
|
|
24841
|
+
var import_react16 = __toESM(require_react(), 1);
|
|
24829
24842
|
|
|
24830
24843
|
// source/gui/client/components/Aside.tsx
|
|
24831
24844
|
var import_react = __toESM(require_react(), 1);
|
|
@@ -24847,6 +24860,12 @@ var GUI_THEME = {
|
|
|
24847
24860
|
green: "#8ce99a",
|
|
24848
24861
|
red: "#ff8787"
|
|
24849
24862
|
};
|
|
24863
|
+
var EVENT_CATEGORY_COLORS = {
|
|
24864
|
+
tickets: GUI_THEME.accent,
|
|
24865
|
+
comments: "#ffd479",
|
|
24866
|
+
tagging: "#c9a5ff",
|
|
24867
|
+
assigning: "#ff9ecd"
|
|
24868
|
+
};
|
|
24850
24869
|
|
|
24851
24870
|
// source/gui/client/components/Aside.tsx
|
|
24852
24871
|
var import_jsx_runtime = __toESM(require_jsx_runtime(), 1);
|
|
@@ -25305,7 +25324,7 @@ var User = ({
|
|
|
25305
25324
|
);
|
|
25306
25325
|
|
|
25307
25326
|
// source/version.ts
|
|
25308
|
-
var EPIQ_VERSION = "1.4.
|
|
25327
|
+
var EPIQ_VERSION = "1.4.3";
|
|
25309
25328
|
|
|
25310
25329
|
// source/gui/client/components/Header.tsx
|
|
25311
25330
|
var import_jsx_runtime7 = __toESM(require_jsx_runtime(), 1);
|
|
@@ -27702,11 +27721,11 @@ function addChildren(props, children) {
|
|
|
27702
27721
|
}
|
|
27703
27722
|
}
|
|
27704
27723
|
}
|
|
27705
|
-
function productionCreate(_,
|
|
27724
|
+
function productionCreate(_, jsx35, jsxs23) {
|
|
27706
27725
|
return create2;
|
|
27707
27726
|
function create2(_2, type, props, key) {
|
|
27708
27727
|
const isStaticChildren = Array.isArray(props.children);
|
|
27709
|
-
const fn = isStaticChildren ?
|
|
27728
|
+
const fn = isStaticChildren ? jsxs23 : jsx35;
|
|
27710
27729
|
return key ? fn(type, props, key) : fn(type, props);
|
|
27711
27730
|
}
|
|
27712
27731
|
}
|
|
@@ -38842,6 +38861,9 @@ var MarkdownContent = ({
|
|
|
38842
38861
|
}
|
|
38843
38862
|
);
|
|
38844
38863
|
|
|
38864
|
+
// source/lib/utils/comment.limits.ts
|
|
38865
|
+
var MAX_COMMENT_LENGTH = 4e3;
|
|
38866
|
+
|
|
38845
38867
|
// source/gui/client/components/IssueComments.tsx
|
|
38846
38868
|
var import_jsx_runtime18 = __toESM(require_jsx_runtime(), 1);
|
|
38847
38869
|
var IssueComments = ({
|
|
@@ -38853,9 +38875,11 @@ var IssueComments = ({
|
|
|
38853
38875
|
onDeleteComment
|
|
38854
38876
|
}) => {
|
|
38855
38877
|
const [body, setBody] = (0, import_react9.useState)("");
|
|
38878
|
+
const length = body.trim().length;
|
|
38879
|
+
const tooLong = length > MAX_COMMENT_LENGTH;
|
|
38856
38880
|
const addComment = () => {
|
|
38857
38881
|
const nextBody = body.trim();
|
|
38858
|
-
if (!nextBody) return;
|
|
38882
|
+
if (!nextBody || tooLong) return;
|
|
38859
38883
|
onAddComment?.(issueId, nextBody);
|
|
38860
38884
|
setBody("");
|
|
38861
38885
|
};
|
|
@@ -38912,7 +38936,7 @@ var IssueComments = ({
|
|
|
38912
38936
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
38913
38937
|
Textarea,
|
|
38914
38938
|
{
|
|
38915
|
-
maxLength:
|
|
38939
|
+
maxLength: Number.MAX_SAFE_INTEGER,
|
|
38916
38940
|
value: body,
|
|
38917
38941
|
placeholder: "write a comment",
|
|
38918
38942
|
onChange: (event) => setBody(event.target.value),
|
|
@@ -38929,7 +38953,20 @@ var IssueComments = ({
|
|
|
38929
38953
|
}
|
|
38930
38954
|
}
|
|
38931
38955
|
),
|
|
38932
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.
|
|
38956
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(ActionRow, { children: [
|
|
38957
|
+
length > MAX_COMMENT_LENGTH / 2 && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
38958
|
+
"span",
|
|
38959
|
+
{
|
|
38960
|
+
style: {
|
|
38961
|
+
alignSelf: "center",
|
|
38962
|
+
fontSize: 11,
|
|
38963
|
+
color: tooLong ? GUI_THEME.red : GUI_THEME.dim
|
|
38964
|
+
},
|
|
38965
|
+
children: tooLong ? `${length - MAX_COMMENT_LENGTH} over the limit` : `${MAX_COMMENT_LENGTH - length} left`
|
|
38966
|
+
}
|
|
38967
|
+
),
|
|
38968
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Button, { disabled: tooLong, onClick: addComment, children: "comment" })
|
|
38969
|
+
] })
|
|
38933
38970
|
] })
|
|
38934
38971
|
] });
|
|
38935
38972
|
};
|
|
@@ -39446,12 +39483,177 @@ var IssueDetails = ({
|
|
|
39446
39483
|
] });
|
|
39447
39484
|
};
|
|
39448
39485
|
|
|
39486
|
+
// source/gui/client/components/BulkDetails.tsx
|
|
39487
|
+
var import_jsx_runtime21 = __toESM(require_jsx_runtime(), 1);
|
|
39488
|
+
var countBy = (issues, pick) => {
|
|
39489
|
+
const byId = /* @__PURE__ */ new Map();
|
|
39490
|
+
for (const issue of issues) {
|
|
39491
|
+
for (const item of pick(issue)) {
|
|
39492
|
+
const seen = byId.get(item.id);
|
|
39493
|
+
byId.set(item.id, { item, count: (seen?.count ?? 0) + 1 });
|
|
39494
|
+
}
|
|
39495
|
+
}
|
|
39496
|
+
return [...byId.values()];
|
|
39497
|
+
};
|
|
39498
|
+
var BulkDetails = ({
|
|
39499
|
+
issues,
|
|
39500
|
+
knownTags,
|
|
39501
|
+
knownAssignees,
|
|
39502
|
+
tagName,
|
|
39503
|
+
assigneeName,
|
|
39504
|
+
onChangeTagName,
|
|
39505
|
+
onChangeAssigneeName,
|
|
39506
|
+
onAddTag,
|
|
39507
|
+
onRemoveTag,
|
|
39508
|
+
onAddAssignee,
|
|
39509
|
+
onRemoveAssignee,
|
|
39510
|
+
onCloseIssues,
|
|
39511
|
+
onReopenIssues,
|
|
39512
|
+
onClear
|
|
39513
|
+
}) => {
|
|
39514
|
+
const total = issues.length;
|
|
39515
|
+
const tags = countBy(issues, (issue) => issue.tags);
|
|
39516
|
+
const assignees = countBy(issues, (issue) => issue.assignees);
|
|
39517
|
+
const availableTags = knownTags.filter(
|
|
39518
|
+
(tag) => !tags.some((entry) => entry.item.id === tag.id && entry.count === total)
|
|
39519
|
+
);
|
|
39520
|
+
const availableAssignees = knownAssignees.filter(
|
|
39521
|
+
(person) => !assignees.some(
|
|
39522
|
+
(entry) => entry.item.id === person.id && entry.count === total
|
|
39523
|
+
)
|
|
39524
|
+
);
|
|
39525
|
+
const partial = (count) => count === total ? "" : ` ${count}/${total}`;
|
|
39526
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Aside, { children: [
|
|
39527
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
39528
|
+
"div",
|
|
39529
|
+
{
|
|
39530
|
+
style: {
|
|
39531
|
+
display: "flex",
|
|
39532
|
+
alignItems: "center",
|
|
39533
|
+
justifyContent: "space-between",
|
|
39534
|
+
gap: 8,
|
|
39535
|
+
marginBottom: 12
|
|
39536
|
+
},
|
|
39537
|
+
children: [
|
|
39538
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { fontSize: 13, fontWeight: 600, color: GUI_THEME.primary }, children: [
|
|
39539
|
+
total,
|
|
39540
|
+
" tickets selected"
|
|
39541
|
+
] }),
|
|
39542
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Button, { variant: "ghost", onClick: onClear, children: "clear" })
|
|
39543
|
+
]
|
|
39544
|
+
}
|
|
39545
|
+
),
|
|
39546
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Section, { title: "Tags", children: [
|
|
39547
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ChipRow, { children: tags.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Empty, { children: "No tags" }) : tags.map(({ item, count }) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
39548
|
+
Button,
|
|
39549
|
+
{
|
|
39550
|
+
variant: "chip",
|
|
39551
|
+
title: "Remove from every selected ticket",
|
|
39552
|
+
onClick: () => onRemoveTag(item.id),
|
|
39553
|
+
style: { color: item.color },
|
|
39554
|
+
children: [
|
|
39555
|
+
item.name,
|
|
39556
|
+
partial(count),
|
|
39557
|
+
" \xD7"
|
|
39558
|
+
]
|
|
39559
|
+
},
|
|
39560
|
+
item.id
|
|
39561
|
+
)) }),
|
|
39562
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ChipRow, { children: availableTags.map((tag) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
39563
|
+
Button,
|
|
39564
|
+
{
|
|
39565
|
+
variant: "chip",
|
|
39566
|
+
title: "Add to every selected ticket",
|
|
39567
|
+
onClick: () => onAddTag(tag.name),
|
|
39568
|
+
style: { color: tag.color, opacity: 0.6 },
|
|
39569
|
+
children: [
|
|
39570
|
+
"+ ",
|
|
39571
|
+
tag.name
|
|
39572
|
+
]
|
|
39573
|
+
},
|
|
39574
|
+
tag.id
|
|
39575
|
+
)) }),
|
|
39576
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(AddRow, { children: [
|
|
39577
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
39578
|
+
Input,
|
|
39579
|
+
{
|
|
39580
|
+
value: tagName,
|
|
39581
|
+
placeholder: "new tag",
|
|
39582
|
+
onChange: (event) => onChangeTagName(event.target.value),
|
|
39583
|
+
onKeyDown: (event) => {
|
|
39584
|
+
if (event.key === "Enter" && tagName.trim()) {
|
|
39585
|
+
onAddTag(tagName.trim());
|
|
39586
|
+
}
|
|
39587
|
+
}
|
|
39588
|
+
}
|
|
39589
|
+
),
|
|
39590
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Button, { onClick: () => tagName.trim() && onAddTag(tagName.trim()), children: "add" })
|
|
39591
|
+
] })
|
|
39592
|
+
] }),
|
|
39593
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Section, { title: "Assignees", children: [
|
|
39594
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ChipRow, { children: assignees.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Empty, { children: "No assignees" }) : assignees.map(({ item, count }) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
39595
|
+
Button,
|
|
39596
|
+
{
|
|
39597
|
+
variant: "chip",
|
|
39598
|
+
title: "Remove from every selected ticket",
|
|
39599
|
+
onClick: () => onRemoveAssignee(item.id),
|
|
39600
|
+
style: { color: item.color },
|
|
39601
|
+
children: [
|
|
39602
|
+
"@",
|
|
39603
|
+
item.name,
|
|
39604
|
+
partial(count),
|
|
39605
|
+
" \xD7"
|
|
39606
|
+
]
|
|
39607
|
+
},
|
|
39608
|
+
item.id
|
|
39609
|
+
)) }),
|
|
39610
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ChipRow, { children: availableAssignees.map((person) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
39611
|
+
Button,
|
|
39612
|
+
{
|
|
39613
|
+
variant: "chip",
|
|
39614
|
+
title: "Add to every selected ticket",
|
|
39615
|
+
onClick: () => onAddAssignee(person.id),
|
|
39616
|
+
style: { color: person.color, opacity: 0.6 },
|
|
39617
|
+
children: [
|
|
39618
|
+
"+ @",
|
|
39619
|
+
person.isSelf ? "me" : person.name
|
|
39620
|
+
]
|
|
39621
|
+
},
|
|
39622
|
+
person.id
|
|
39623
|
+
)) }),
|
|
39624
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(AddRow, { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
39625
|
+
Input,
|
|
39626
|
+
{
|
|
39627
|
+
value: assigneeName,
|
|
39628
|
+
placeholder: "name of unknown contributor",
|
|
39629
|
+
onChange: (event) => onChangeAssigneeName(event.target.value)
|
|
39630
|
+
}
|
|
39631
|
+
) })
|
|
39632
|
+
] }),
|
|
39633
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Section, { title: "Actions", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(ChipRow, { children: [
|
|
39634
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Button, { onClick: onCloseIssues, children: [
|
|
39635
|
+
"close ",
|
|
39636
|
+
total,
|
|
39637
|
+
" tickets"
|
|
39638
|
+
] }),
|
|
39639
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Button, { onClick: onReopenIssues, children: [
|
|
39640
|
+
"reopen ",
|
|
39641
|
+
total,
|
|
39642
|
+
" tickets"
|
|
39643
|
+
] })
|
|
39644
|
+
] }) })
|
|
39645
|
+
] });
|
|
39646
|
+
};
|
|
39647
|
+
|
|
39449
39648
|
// source/gui/client/components/SwimlaneColumn.tsx
|
|
39649
|
+
var import_react12 = __toESM(require_react(), 1);
|
|
39650
|
+
|
|
39651
|
+
// source/gui/client/components/TicketCard.tsx
|
|
39450
39652
|
var import_react11 = __toESM(require_react(), 1);
|
|
39451
39653
|
|
|
39452
39654
|
// source/gui/client/components/IconComment.tsx
|
|
39453
|
-
var
|
|
39454
|
-
var IconComment = ({ size = 16 }) => /* @__PURE__ */ (0,
|
|
39655
|
+
var import_jsx_runtime22 = __toESM(require_jsx_runtime(), 1);
|
|
39656
|
+
var IconComment = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
39455
39657
|
"svg",
|
|
39456
39658
|
{
|
|
39457
39659
|
width: size,
|
|
@@ -39459,7 +39661,7 @@ var IconComment = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime21.js
|
|
|
39459
39661
|
viewBox: "0 0 16 16",
|
|
39460
39662
|
fill: "none",
|
|
39461
39663
|
"aria-hidden": "true",
|
|
39462
|
-
children: /* @__PURE__ */ (0,
|
|
39664
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
39463
39665
|
"path",
|
|
39464
39666
|
{
|
|
39465
39667
|
d: "M3.9 2.6h5.2a2.4 2.4 0 0 1 2.4 2.4v2.5a2.4 2.4 0 0 1-2.4 2.4H6.6l-1.8 2.1.2-2.1H3.9a2.4 2.4 0 0 1-2.4-2.4V5a2.4 2.4 0 0 1 2.4-2.4Z",
|
|
@@ -39474,28 +39676,40 @@ var IconComment = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime21.js
|
|
|
39474
39676
|
);
|
|
39475
39677
|
|
|
39476
39678
|
// source/gui/client/components/TicketCard.tsx
|
|
39477
|
-
var
|
|
39679
|
+
var import_jsx_runtime23 = __toESM(require_jsx_runtime(), 1);
|
|
39478
39680
|
var TicketCard = ({
|
|
39479
39681
|
ticket,
|
|
39480
39682
|
index: index2,
|
|
39481
39683
|
isSelected,
|
|
39684
|
+
isPicked,
|
|
39482
39685
|
commentCount,
|
|
39483
39686
|
onOpenComments,
|
|
39484
39687
|
onSelect,
|
|
39485
|
-
onDragStart,
|
|
39486
39688
|
onDragOverIssue,
|
|
39487
39689
|
onDropIssueAt
|
|
39488
39690
|
}) => {
|
|
39691
|
+
const cardRef = (0, import_react11.useRef)(null);
|
|
39692
|
+
(0, import_react11.useEffect)(() => {
|
|
39693
|
+
if (!isSelected) return;
|
|
39694
|
+
cardRef.current?.scrollIntoView({
|
|
39695
|
+
behavior: "smooth",
|
|
39696
|
+
block: "nearest",
|
|
39697
|
+
inline: "nearest"
|
|
39698
|
+
});
|
|
39699
|
+
}, [isSelected]);
|
|
39489
39700
|
const getVisualTargetIndex = (isAfterMiddle) => index2 + (isAfterMiddle ? 1 : 0);
|
|
39490
|
-
return /* @__PURE__ */ (0,
|
|
39701
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
39491
39702
|
"div",
|
|
39492
39703
|
{
|
|
39704
|
+
ref: cardRef,
|
|
39493
39705
|
draggable: !ticket.readonly,
|
|
39494
|
-
onClick:
|
|
39706
|
+
onClick: (event) => {
|
|
39707
|
+
event.stopPropagation();
|
|
39708
|
+
onSelect({ toggle: event.metaKey || event.ctrlKey || event.shiftKey });
|
|
39709
|
+
},
|
|
39495
39710
|
onDragStart: (event) => {
|
|
39496
39711
|
event.dataTransfer.effectAllowed = "move";
|
|
39497
39712
|
event.dataTransfer.setData("text/plain", ticket.id);
|
|
39498
|
-
onDragStart(ticket.id);
|
|
39499
39713
|
},
|
|
39500
39714
|
onDragOver: (event) => {
|
|
39501
39715
|
event.preventDefault();
|
|
@@ -39517,18 +39731,22 @@ var TicketCard = ({
|
|
|
39517
39731
|
display: "flex",
|
|
39518
39732
|
alignItems: "flex-start",
|
|
39519
39733
|
gap: 10,
|
|
39520
|
-
color: isSelected ? GUI_THEME.accent : GUI_THEME.primary,
|
|
39734
|
+
color: isSelected || isPicked ? GUI_THEME.accent : GUI_THEME.primary,
|
|
39521
39735
|
fontSize: 11,
|
|
39522
39736
|
cursor: ticket.readonly ? "default" : "grab",
|
|
39523
|
-
background: isSelected ? "rgba(118,228,255,0.08)" : "rgba(185, 192, 255, 0.06)",
|
|
39737
|
+
background: isSelected || isPicked ? "rgba(118,228,255,0.08)" : "rgba(185, 192, 255, 0.06)",
|
|
39524
39738
|
padding: "10px 8px",
|
|
39525
39739
|
minHeight: "58px",
|
|
39526
39740
|
borderRadius: "8px",
|
|
39527
39741
|
marginBottom: 4,
|
|
39528
|
-
border: `1px solid ${isSelected ? GUI_THEME.accent : "transparent"}
|
|
39742
|
+
border: `1px solid ${isSelected || isPicked ? GUI_THEME.accent : "transparent"}`,
|
|
39743
|
+
// Only the multi-selection is outlined, so it stays legible when the
|
|
39744
|
+
// details panel is closed.
|
|
39745
|
+
outline: isPicked ? `1px solid ${GUI_THEME.accent}` : void 0,
|
|
39746
|
+
outlineOffset: 1
|
|
39529
39747
|
},
|
|
39530
39748
|
children: [
|
|
39531
|
-
/* @__PURE__ */ (0,
|
|
39749
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
39532
39750
|
"div",
|
|
39533
39751
|
{
|
|
39534
39752
|
style: {
|
|
@@ -39542,7 +39760,7 @@ var TicketCard = ({
|
|
|
39542
39760
|
children: isSelected ? "\u276F" : index2 + 1
|
|
39543
39761
|
}
|
|
39544
39762
|
),
|
|
39545
|
-
/* @__PURE__ */ (0,
|
|
39763
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
39546
39764
|
"div",
|
|
39547
39765
|
{
|
|
39548
39766
|
style: {
|
|
@@ -39554,7 +39772,7 @@ var TicketCard = ({
|
|
|
39554
39772
|
paddingLeft: 8
|
|
39555
39773
|
},
|
|
39556
39774
|
children: [
|
|
39557
|
-
/* @__PURE__ */ (0,
|
|
39775
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
39558
39776
|
"div",
|
|
39559
39777
|
{
|
|
39560
39778
|
style: {
|
|
@@ -39565,7 +39783,7 @@ var TicketCard = ({
|
|
|
39565
39783
|
flex: 1
|
|
39566
39784
|
},
|
|
39567
39785
|
children: [
|
|
39568
|
-
/* @__PURE__ */ (0,
|
|
39786
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
39569
39787
|
"div",
|
|
39570
39788
|
{
|
|
39571
39789
|
style: {
|
|
@@ -39581,17 +39799,17 @@ var TicketCard = ({
|
|
|
39581
39799
|
children: ticket.title
|
|
39582
39800
|
}
|
|
39583
39801
|
),
|
|
39584
|
-
ticket.ref && /* @__PURE__ */ (0,
|
|
39802
|
+
ticket.ref && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
39585
39803
|
"div",
|
|
39586
39804
|
{
|
|
39587
39805
|
style: {
|
|
39588
39806
|
color: GUI_THEME.dim2,
|
|
39589
39807
|
fontSize: 10
|
|
39590
39808
|
},
|
|
39591
|
-
children: /* @__PURE__ */ (0,
|
|
39809
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(CopyRef, { refValue: ticket.ref })
|
|
39592
39810
|
}
|
|
39593
39811
|
),
|
|
39594
|
-
/* @__PURE__ */ (0,
|
|
39812
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
39595
39813
|
"div",
|
|
39596
39814
|
{
|
|
39597
39815
|
style: {
|
|
@@ -39600,7 +39818,7 @@ var TicketCard = ({
|
|
|
39600
39818
|
gap: 6,
|
|
39601
39819
|
alignItems: "center"
|
|
39602
39820
|
},
|
|
39603
|
-
children: ticket.tags.map((tag) => /* @__PURE__ */ (0,
|
|
39821
|
+
children: ticket.tags.map((tag) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
39604
39822
|
"span",
|
|
39605
39823
|
{
|
|
39606
39824
|
style: {
|
|
@@ -39620,7 +39838,7 @@ var TicketCard = ({
|
|
|
39620
39838
|
]
|
|
39621
39839
|
}
|
|
39622
39840
|
),
|
|
39623
|
-
/* @__PURE__ */ (0,
|
|
39841
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
39624
39842
|
"div",
|
|
39625
39843
|
{
|
|
39626
39844
|
style: {
|
|
@@ -39630,7 +39848,7 @@ var TicketCard = ({
|
|
|
39630
39848
|
flexShrink: 0,
|
|
39631
39849
|
paddingTop: 2
|
|
39632
39850
|
},
|
|
39633
|
-
children: commentCount > 0 && /* @__PURE__ */ (0,
|
|
39851
|
+
children: commentCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
39634
39852
|
"button",
|
|
39635
39853
|
{
|
|
39636
39854
|
type: "button",
|
|
@@ -39668,14 +39886,14 @@ var TicketCard = ({
|
|
|
39668
39886
|
event.currentTarget.style.transform = "translateY(0)";
|
|
39669
39887
|
},
|
|
39670
39888
|
children: [
|
|
39671
|
-
/* @__PURE__ */ (0,
|
|
39672
|
-
/* @__PURE__ */ (0,
|
|
39889
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(IconComment, {}),
|
|
39890
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { children: commentCount })
|
|
39673
39891
|
]
|
|
39674
39892
|
}
|
|
39675
39893
|
)
|
|
39676
39894
|
}
|
|
39677
39895
|
),
|
|
39678
|
-
ticket.assignees.length > 0 && /* @__PURE__ */ (0,
|
|
39896
|
+
ticket.assignees.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
39679
39897
|
"div",
|
|
39680
39898
|
{
|
|
39681
39899
|
style: {
|
|
@@ -39685,7 +39903,15 @@ var TicketCard = ({
|
|
|
39685
39903
|
paddingTop: 2,
|
|
39686
39904
|
marginTop: "-4px"
|
|
39687
39905
|
},
|
|
39688
|
-
children: ticket.assignees.map((assignee, idx) => /* @__PURE__ */ (0,
|
|
39906
|
+
children: ticket.assignees.map((assignee, idx) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
39907
|
+
User,
|
|
39908
|
+
{
|
|
39909
|
+
user: assignee,
|
|
39910
|
+
index: idx,
|
|
39911
|
+
isFocus: isSelected
|
|
39912
|
+
},
|
|
39913
|
+
assignee.id
|
|
39914
|
+
))
|
|
39689
39915
|
}
|
|
39690
39916
|
)
|
|
39691
39917
|
]
|
|
@@ -39697,7 +39923,7 @@ var TicketCard = ({
|
|
|
39697
39923
|
};
|
|
39698
39924
|
|
|
39699
39925
|
// source/gui/client/components/SwimlaneColumn.tsx
|
|
39700
|
-
var
|
|
39926
|
+
var import_jsx_runtime24 = __toESM(require_jsx_runtime(), 1);
|
|
39701
39927
|
var COLUMN_GLOW_COLOR = "rgb(140, 176, 232)";
|
|
39702
39928
|
var COLUMN_PADDING = 14;
|
|
39703
39929
|
var SCROLLBAR_GUTTER_INSET = COLUMN_PADDING / 2;
|
|
@@ -39710,13 +39936,14 @@ var SwimlaneColumn = ({
|
|
|
39710
39936
|
dragOver,
|
|
39711
39937
|
dropIndex,
|
|
39712
39938
|
onSelectIssue,
|
|
39939
|
+
pickedIssueIds,
|
|
39713
39940
|
onCreateIssue,
|
|
39714
39941
|
onDropIssue,
|
|
39715
39942
|
onDragOver,
|
|
39716
39943
|
onDragOverIssue,
|
|
39717
39944
|
onDragLeave
|
|
39718
39945
|
}) => {
|
|
39719
|
-
return /* @__PURE__ */ (0,
|
|
39946
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
39720
39947
|
Panel,
|
|
39721
39948
|
{
|
|
39722
39949
|
as: "section",
|
|
@@ -39763,7 +39990,7 @@ var SwimlaneColumn = ({
|
|
|
39763
39990
|
onDragLeave();
|
|
39764
39991
|
},
|
|
39765
39992
|
children: [
|
|
39766
|
-
/* @__PURE__ */ (0,
|
|
39993
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
39767
39994
|
"header",
|
|
39768
39995
|
{
|
|
39769
39996
|
style: {
|
|
@@ -39775,7 +40002,7 @@ var SwimlaneColumn = ({
|
|
|
39775
40002
|
alignItems: "center"
|
|
39776
40003
|
},
|
|
39777
40004
|
children: [
|
|
39778
|
-
/* @__PURE__ */ (0,
|
|
40005
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
39779
40006
|
"div",
|
|
39780
40007
|
{
|
|
39781
40008
|
style: {
|
|
@@ -39784,37 +40011,37 @@ var SwimlaneColumn = ({
|
|
|
39784
40011
|
gap: 8
|
|
39785
40012
|
},
|
|
39786
40013
|
children: [
|
|
39787
|
-
/* @__PURE__ */ (0,
|
|
40014
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
39788
40015
|
"span",
|
|
39789
40016
|
{
|
|
39790
40017
|
style: { color: selected ? GUI_THEME.accent : GUI_THEME.secondary },
|
|
39791
40018
|
children: selected ? "\u276F" : " "
|
|
39792
40019
|
}
|
|
39793
40020
|
),
|
|
39794
|
-
/* @__PURE__ */ (0,
|
|
40021
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
39795
40022
|
"strong",
|
|
39796
40023
|
{
|
|
39797
40024
|
style: { color: selected ? GUI_THEME.accent : GUI_THEME.primary },
|
|
39798
40025
|
children: swimlane.title
|
|
39799
40026
|
}
|
|
39800
40027
|
),
|
|
39801
|
-
/* @__PURE__ */ (0,
|
|
40028
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { style: { color: GUI_THEME.dim }, children: [
|
|
39802
40029
|
"(",
|
|
39803
40030
|
swimlane.issues.length,
|
|
39804
40031
|
")"
|
|
39805
40032
|
] }),
|
|
39806
|
-
swimlane.readonly && /* @__PURE__ */ (0,
|
|
40033
|
+
swimlane.readonly && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
39807
40034
|
"span",
|
|
39808
40035
|
{
|
|
39809
40036
|
title: "Read-only",
|
|
39810
40037
|
style: { display: "flex", color: GUI_THEME.dim },
|
|
39811
|
-
children: /* @__PURE__ */ (0,
|
|
40038
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(IconLock, {})
|
|
39812
40039
|
}
|
|
39813
40040
|
)
|
|
39814
40041
|
]
|
|
39815
40042
|
}
|
|
39816
40043
|
),
|
|
39817
|
-
/* @__PURE__ */ (0,
|
|
40044
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
39818
40045
|
Button,
|
|
39819
40046
|
{
|
|
39820
40047
|
variant: "ghost",
|
|
@@ -39827,7 +40054,7 @@ var SwimlaneColumn = ({
|
|
|
39827
40054
|
]
|
|
39828
40055
|
}
|
|
39829
40056
|
),
|
|
39830
|
-
/* @__PURE__ */ (0,
|
|
40057
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
39831
40058
|
"div",
|
|
39832
40059
|
{
|
|
39833
40060
|
style: {
|
|
@@ -39838,9 +40065,9 @@ var SwimlaneColumn = ({
|
|
|
39838
40065
|
flex: 1,
|
|
39839
40066
|
minHeight: 0
|
|
39840
40067
|
},
|
|
39841
|
-
children: swimlane.issues.length === 0 ? /* @__PURE__ */ (0,
|
|
39842
|
-
dropIndex === 0 && /* @__PURE__ */ (0,
|
|
39843
|
-
/* @__PURE__ */ (0,
|
|
40068
|
+
children: swimlane.issues.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
|
|
40069
|
+
dropIndex === 0 && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(DropIndicator, {}),
|
|
40070
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
39844
40071
|
"div",
|
|
39845
40072
|
{
|
|
39846
40073
|
style: {
|
|
@@ -39852,17 +40079,17 @@ var SwimlaneColumn = ({
|
|
|
39852
40079
|
children: "Drop issue here"
|
|
39853
40080
|
}
|
|
39854
40081
|
)
|
|
39855
|
-
] }) : /* @__PURE__ */ (0,
|
|
39856
|
-
swimlane.issues.map((ticket, index2) => /* @__PURE__ */ (0,
|
|
39857
|
-
dropIndex === index2 && /* @__PURE__ */ (0,
|
|
39858
|
-
/* @__PURE__ */ (0,
|
|
40082
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
|
|
40083
|
+
swimlane.issues.map((ticket, index2) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react12.default.Fragment, { children: [
|
|
40084
|
+
dropIndex === index2 && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(DropIndicator, {}),
|
|
40085
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
39859
40086
|
TicketCard,
|
|
39860
40087
|
{
|
|
39861
40088
|
ticket,
|
|
39862
40089
|
index: index2,
|
|
39863
40090
|
isSelected: ticket.id === selectedIssueId,
|
|
39864
|
-
|
|
39865
|
-
|
|
40091
|
+
isPicked: pickedIssueIds.includes(ticket.id),
|
|
40092
|
+
onSelect: (options) => onSelectIssue(ticket.id, options),
|
|
39866
40093
|
onOpenComments: onSelectIssueComments,
|
|
39867
40094
|
commentCount: commentsByIssueId[ticket.id]?.length ?? 0,
|
|
39868
40095
|
onDragOverIssue: (targetIndex) => onDragOverIssue(swimlane.id, targetIndex),
|
|
@@ -39873,7 +40100,7 @@ var SwimlaneColumn = ({
|
|
|
39873
40100
|
}
|
|
39874
40101
|
)
|
|
39875
40102
|
] }, ticket.id)),
|
|
39876
|
-
dropIndex === swimlane.issues.length && /* @__PURE__ */ (0,
|
|
40103
|
+
dropIndex === swimlane.issues.length && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(DropIndicator, {})
|
|
39877
40104
|
] })
|
|
39878
40105
|
}
|
|
39879
40106
|
)
|
|
@@ -39883,9 +40110,9 @@ var SwimlaneColumn = ({
|
|
|
39883
40110
|
};
|
|
39884
40111
|
|
|
39885
40112
|
// source/gui/client/components/GlobalScrollbarStyles.tsx
|
|
39886
|
-
var
|
|
40113
|
+
var import_jsx_runtime25 = __toESM(require_jsx_runtime(), 1);
|
|
39887
40114
|
var SCROLLBAR_SIZE = 3;
|
|
39888
|
-
var GlobalScrollbarStyles = () => /* @__PURE__ */ (0,
|
|
40115
|
+
var GlobalScrollbarStyles = () => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("style", { children: `
|
|
39889
40116
|
/* Gated deliberately: Chrome implements scrollbar-width/-color too, and
|
|
39890
40117
|
setting either makes it ignore the ::-webkit-scrollbar rules below. */
|
|
39891
40118
|
@supports not selector(::-webkit-scrollbar) {
|
|
@@ -39926,8 +40153,8 @@ var GlobalScrollbarStyles = () => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
|
39926
40153
|
` });
|
|
39927
40154
|
|
|
39928
40155
|
// source/gui/client/components/ErrorToast.tsx
|
|
39929
|
-
var
|
|
39930
|
-
var ErrorToast = ({ message, onDismiss }) => /* @__PURE__ */ (0,
|
|
40156
|
+
var import_jsx_runtime26 = __toESM(require_jsx_runtime(), 1);
|
|
40157
|
+
var ErrorToast = ({ message, onDismiss }) => /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
39931
40158
|
"div",
|
|
39932
40159
|
{
|
|
39933
40160
|
style: {
|
|
@@ -39948,8 +40175,8 @@ var ErrorToast = ({ message, onDismiss }) => /* @__PURE__ */ (0, import_jsx_runt
|
|
|
39948
40175
|
boxShadow: "0 4px 16px rgba(0, 0, 0, 0.4)"
|
|
39949
40176
|
},
|
|
39950
40177
|
children: [
|
|
39951
|
-
/* @__PURE__ */ (0,
|
|
39952
|
-
/* @__PURE__ */ (0,
|
|
40178
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { style: { flex: 1, minWidth: 0, overflowWrap: "anywhere" }, children: message }),
|
|
40179
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
39953
40180
|
"button",
|
|
39954
40181
|
{
|
|
39955
40182
|
onClick: onDismiss,
|
|
@@ -39970,7 +40197,7 @@ var ErrorToast = ({ message, onDismiss }) => /* @__PURE__ */ (0, import_jsx_runt
|
|
|
39970
40197
|
);
|
|
39971
40198
|
|
|
39972
40199
|
// source/gui/client/components/TimeScrubber.tsx
|
|
39973
|
-
var
|
|
40200
|
+
var import_react15 = __toESM(require_react(), 1);
|
|
39974
40201
|
|
|
39975
40202
|
// source/lib/utils/date.utils.ts
|
|
39976
40203
|
var pad = (n) => String(n).padStart(2, "0");
|
|
@@ -39983,14 +40210,14 @@ var minOf = (values, seed) => values.reduce((min, value) => value < min ? value
|
|
|
39983
40210
|
var maxOf = (values, seed) => values.reduce((max, value) => value > max ? value : max, seed);
|
|
39984
40211
|
|
|
39985
40212
|
// source/gui/client/lib/scrubber.ts
|
|
39986
|
-
var
|
|
40213
|
+
var import_react13 = __toESM(require_react(), 1);
|
|
39987
40214
|
var clamp = (value, min, max) => Math.min(max, Math.max(min, value));
|
|
39988
40215
|
var TRACK_HEIGHT = 24;
|
|
39989
40216
|
var EVENTS_MODE_TOTAL_HEIGHT = 8 + TRACK_HEIGHT * 2;
|
|
39990
40217
|
var EVENTS_SCATTER_HEIGHT = TRACK_HEIGHT + 16;
|
|
39991
40218
|
var EVENTS_MODE_VERTICAL_PADDING = (EVENTS_MODE_TOTAL_HEIGHT - EVENTS_SCATTER_HEIGHT) / 2;
|
|
39992
40219
|
var HOVER_HINT_WIDTH = 220;
|
|
39993
|
-
var SEGMENT_HIGHLIGHT_COLOR = "rgba(122,
|
|
40220
|
+
var SEGMENT_HIGHLIGHT_COLOR = "rgba(122, 157, 214, 0.14)";
|
|
39994
40221
|
var BUCKET_HIGHLIGHT_COLOR = "rgba(255, 255, 255, 0.06)";
|
|
39995
40222
|
var NEEDLE_COLOR = "rgba(255, 255, 255, 0.62)";
|
|
39996
40223
|
var MIN_BUCKET_COUNT_FOR_GAP = 300;
|
|
@@ -40026,8 +40253,15 @@ var buildAxis = (timeline, commits, now = Date.now()) => {
|
|
|
40026
40253
|
fractionToTime: (fraction) => Math.round(earliest + clamp(fraction, 0, 1) * span)
|
|
40027
40254
|
};
|
|
40028
40255
|
};
|
|
40029
|
-
var bucketIssueCounts = (axis, timeline) => {
|
|
40256
|
+
var bucketIssueCounts = (axis, timeline, view = "all", hiddenIds = /* @__PURE__ */ new Set()) => {
|
|
40030
40257
|
const counts = new Array(axis.bucketCount).fill(0);
|
|
40258
|
+
if (timeline && timeline.events.length > 0) {
|
|
40259
|
+
for (const entry of timeline.events) {
|
|
40260
|
+
if (!isShown(entry, view, hiddenIds)) continue;
|
|
40261
|
+
counts[axis.bucketIndexForTime(entry.t)] += 1;
|
|
40262
|
+
}
|
|
40263
|
+
return counts;
|
|
40264
|
+
}
|
|
40031
40265
|
for (const sparseBucket of timeline?.buckets ?? []) {
|
|
40032
40266
|
counts[axis.bucketIndexForTime(sparseBucket.t)] += sparseBucket.count;
|
|
40033
40267
|
}
|
|
@@ -40045,6 +40279,102 @@ var bucketCommitStats = (axis, commits) => {
|
|
|
40045
40279
|
}
|
|
40046
40280
|
return byIndex;
|
|
40047
40281
|
};
|
|
40282
|
+
var EVENT_CATEGORIES = [
|
|
40283
|
+
"tickets",
|
|
40284
|
+
"comments",
|
|
40285
|
+
"tagging",
|
|
40286
|
+
"assigning"
|
|
40287
|
+
];
|
|
40288
|
+
var BOARD_VIEWS = ["all", ...EVENT_CATEGORIES];
|
|
40289
|
+
var isBoardView = (value) => BOARD_VIEWS.includes(value);
|
|
40290
|
+
var boardViewColor = (view) => view === "all" ? GUI_THEME.accent : EVENT_CATEGORY_COLORS[view];
|
|
40291
|
+
var identityAxisFor = (view) => view === "comments" ? "actor" : view === "tagging" ? "tag" : view === "assigning" ? "assignee" : null;
|
|
40292
|
+
var CATEGORY_BY_ACTION = {
|
|
40293
|
+
"add.issue.comment": "comments",
|
|
40294
|
+
"edit.issue.comment": "comments",
|
|
40295
|
+
"delete.issue.comment": "comments",
|
|
40296
|
+
"add.issue.tag": "tagging",
|
|
40297
|
+
"remove.issue.tag": "tagging",
|
|
40298
|
+
"create.tag": "tagging",
|
|
40299
|
+
"add.issue.assignee": "assigning",
|
|
40300
|
+
"remove.issue.assignee": "assigning",
|
|
40301
|
+
"create.contributor": "assigning",
|
|
40302
|
+
"tombstone.contributor": "assigning",
|
|
40303
|
+
"restore.contributor": "assigning",
|
|
40304
|
+
"link.contributor.user": "assigning"
|
|
40305
|
+
};
|
|
40306
|
+
var categoryOf = (action) => CATEGORY_BY_ACTION[action] ?? "tickets";
|
|
40307
|
+
var identityOf = (entry, view) => {
|
|
40308
|
+
const axis = identityAxisFor(view);
|
|
40309
|
+
return axis === null ? null : entry[axis];
|
|
40310
|
+
};
|
|
40311
|
+
var listIdentities = (timeline, view) => {
|
|
40312
|
+
if (!timeline || identityAxisFor(view) === null) return [];
|
|
40313
|
+
const byId = /* @__PURE__ */ new Map();
|
|
40314
|
+
for (const entry of timeline.events) {
|
|
40315
|
+
if (categoryOf(entry.action) !== view) continue;
|
|
40316
|
+
const identity = identityOf(entry, view);
|
|
40317
|
+
if (identity && !byId.has(identity.id)) byId.set(identity.id, identity);
|
|
40318
|
+
}
|
|
40319
|
+
return [...byId.values()];
|
|
40320
|
+
};
|
|
40321
|
+
var soleVisibleIdentity = (identities, hiddenIds) => {
|
|
40322
|
+
const visible = identities.filter((identity) => !hiddenIds.has(identity.id));
|
|
40323
|
+
return visible.length === 1 ? visible[0] : null;
|
|
40324
|
+
};
|
|
40325
|
+
var dotDetail = (dot) => {
|
|
40326
|
+
const base = dot.label ?? `${dot.count ?? 0} board event${dot.count === 1 ? "" : "s"}`;
|
|
40327
|
+
return dot.identity && !base.includes(dot.identity.name) ? `${base} \u2014 ${dot.identity.name}` : base;
|
|
40328
|
+
};
|
|
40329
|
+
var EVENT_DOT_SIZE = 4;
|
|
40330
|
+
var EVENT_DOT_OPACITY = 0.55;
|
|
40331
|
+
var isShown = (entry, view, hiddenIds) => {
|
|
40332
|
+
if (view !== "all" && categoryOf(entry.action) !== view) return false;
|
|
40333
|
+
const identity = identityOf(entry, view);
|
|
40334
|
+
return identity === null || !hiddenIds.has(identity.id);
|
|
40335
|
+
};
|
|
40336
|
+
var buildEventDots = (timeline, view = "all", hiddenIds = /* @__PURE__ */ new Set()) => {
|
|
40337
|
+
if (!timeline) return [];
|
|
40338
|
+
if (timeline.events.length > 0) {
|
|
40339
|
+
return timeline.events.flatMap((entry, index2) => {
|
|
40340
|
+
if (!isShown(entry, view, hiddenIds)) return [];
|
|
40341
|
+
const category = categoryOf(entry.action);
|
|
40342
|
+
const identity = identityOf(entry, view);
|
|
40343
|
+
return [
|
|
40344
|
+
{
|
|
40345
|
+
// Two events can share a millisecond, so time alone is not a key.
|
|
40346
|
+
key: `${entry.t}-${index2}`,
|
|
40347
|
+
t: entry.t,
|
|
40348
|
+
count: null,
|
|
40349
|
+
label: entry.label,
|
|
40350
|
+
category,
|
|
40351
|
+
color: view === "all" ? EVENT_CATEGORY_COLORS[category] : identity?.color ?? GUI_THEME.accent,
|
|
40352
|
+
identity,
|
|
40353
|
+
size: EVENT_DOT_SIZE,
|
|
40354
|
+
opacity: EVENT_DOT_OPACITY
|
|
40355
|
+
}
|
|
40356
|
+
];
|
|
40357
|
+
});
|
|
40358
|
+
}
|
|
40359
|
+
const maxCount = maxOf(
|
|
40360
|
+
timeline.buckets.map((bucket) => bucket.count),
|
|
40361
|
+
1
|
|
40362
|
+
);
|
|
40363
|
+
return timeline.buckets.map((bucket) => {
|
|
40364
|
+
const intensity = bucket.count / maxCount;
|
|
40365
|
+
return {
|
|
40366
|
+
key: String(bucket.t),
|
|
40367
|
+
t: bucket.t,
|
|
40368
|
+
count: bucket.count,
|
|
40369
|
+
label: null,
|
|
40370
|
+
category: null,
|
|
40371
|
+
color: GUI_THEME.accent,
|
|
40372
|
+
identity: null,
|
|
40373
|
+
size: 3 + intensity * 6,
|
|
40374
|
+
opacity: 0.3 + intensity * 0.5
|
|
40375
|
+
};
|
|
40376
|
+
});
|
|
40377
|
+
};
|
|
40048
40378
|
var populatedRange = (bars) => bars.length > 0 ? [
|
|
40049
40379
|
bars.reduce((min, bar) => Math.min(min, bar.index), Infinity),
|
|
40050
40380
|
bars.reduce((max, bar) => Math.max(max, bar.index), -Infinity)
|
|
@@ -40053,8 +40383,9 @@ var hourFractionForTime = (time) => {
|
|
|
40053
40383
|
const date = new Date(time);
|
|
40054
40384
|
return (date.getHours() * 60 + date.getMinutes()) / (24 * 60);
|
|
40055
40385
|
};
|
|
40056
|
-
var SEGMENT_UNIT_ORDER = ["day", "week", "month", "year"];
|
|
40386
|
+
var SEGMENT_UNIT_ORDER = ["hour", "day", "week", "month", "year"];
|
|
40057
40387
|
var APPROX_UNIT_MS = {
|
|
40388
|
+
hour: 60 * 60 * 1e3,
|
|
40058
40389
|
day: 24 * 60 * 60 * 1e3,
|
|
40059
40390
|
week: 7 * 24 * 60 * 60 * 1e3,
|
|
40060
40391
|
month: 30.44 * 24 * 60 * 60 * 1e3,
|
|
@@ -40080,14 +40411,16 @@ var MONTH_LABELS = [
|
|
|
40080
40411
|
"Dec"
|
|
40081
40412
|
];
|
|
40082
40413
|
var advanceByUnit = (date, unit) => {
|
|
40083
|
-
if (unit === "
|
|
40414
|
+
if (unit === "hour") date.setHours(date.getHours() + 1);
|
|
40415
|
+
else if (unit === "day") date.setDate(date.getDate() + 1);
|
|
40084
40416
|
else if (unit === "week") date.setDate(date.getDate() + 7);
|
|
40085
40417
|
else if (unit === "month") date.setMonth(date.getMonth() + 1);
|
|
40086
40418
|
else date.setFullYear(date.getFullYear() + 1);
|
|
40087
40419
|
};
|
|
40088
40420
|
var segmentAt = (time, unit) => {
|
|
40089
40421
|
const start2 = new Date(time);
|
|
40090
|
-
start2.
|
|
40422
|
+
if (unit === "hour") start2.setMinutes(0, 0, 0);
|
|
40423
|
+
else start2.setHours(0, 0, 0, 0);
|
|
40091
40424
|
if (unit === "week") {
|
|
40092
40425
|
start2.setDate(start2.getDate() - (start2.getDay() + 6) % 7);
|
|
40093
40426
|
} else if (unit === "month") {
|
|
@@ -40098,7 +40431,10 @@ var segmentAt = (time, unit) => {
|
|
|
40098
40431
|
const end = new Date(start2);
|
|
40099
40432
|
advanceByUnit(end, unit);
|
|
40100
40433
|
const lastDay = new Date(end.getTime() - 1);
|
|
40101
|
-
const label = unit === "
|
|
40434
|
+
const label = unit === "hour" ? `${WEEKDAY_LABELS[start2.getDay()]} ${String(start2.getHours()).padStart(
|
|
40435
|
+
2,
|
|
40436
|
+
"0"
|
|
40437
|
+
)}:00` : unit === "day" ? `${WEEKDAY_LABELS[start2.getDay()]} ${start2.getDate()} ${MONTH_LABELS[start2.getMonth()]}` : unit === "week" ? start2.getMonth() === lastDay.getMonth() ? `${start2.getDate()}\u2013${lastDay.getDate()} ${MONTH_LABELS[start2.getMonth()]}` : `${start2.getDate()} ${MONTH_LABELS[start2.getMonth()]} \u2013 ${lastDay.getDate()} ${MONTH_LABELS[lastDay.getMonth()]}` : unit === "month" ? `${MONTH_LABELS[start2.getMonth()]} ${start2.getFullYear()}` : `${start2.getFullYear()}`;
|
|
40102
40438
|
return { start: start2.getTime(), end: end.getTime(), label };
|
|
40103
40439
|
};
|
|
40104
40440
|
var formatInterval = (start2, end) => {
|
|
@@ -40107,12 +40443,19 @@ var formatInterval = (start2, end) => {
|
|
|
40107
40443
|
const endLabel = isSameDay(startDate, endDate) ? formatTimeOfDay(endDate) : formatDateTime(endDate);
|
|
40108
40444
|
return `${formatDateTime(startDate)} \u2013 ${endLabel}`;
|
|
40109
40445
|
};
|
|
40110
|
-
var SCOPES = ["week", "month", "year", "all"];
|
|
40446
|
+
var SCOPES = ["day", "week", "month", "year", "all"];
|
|
40111
40447
|
var SCOPE_DURATION_MS = {
|
|
40448
|
+
day: 24 * 60 * 60 * 1e3,
|
|
40112
40449
|
week: 7 * 24 * 60 * 60 * 1e3,
|
|
40113
40450
|
month: 30 * 24 * 60 * 60 * 1e3,
|
|
40114
40451
|
year: 365 * 24 * 60 * 60 * 1e3
|
|
40115
40452
|
};
|
|
40453
|
+
var SCOPE_RECENT_LABELS = {
|
|
40454
|
+
day: "Last 24 hours",
|
|
40455
|
+
week: "Last 7 days",
|
|
40456
|
+
month: "Last 30 days",
|
|
40457
|
+
year: "Last 365 days"
|
|
40458
|
+
};
|
|
40116
40459
|
var isScope = (value) => SCOPES.includes(value ?? "");
|
|
40117
40460
|
var getPeriodRange = (scope, offset) => {
|
|
40118
40461
|
if (scope === "all") return null;
|
|
@@ -40122,9 +40465,7 @@ var getPeriodRange = (scope, offset) => {
|
|
|
40122
40465
|
};
|
|
40123
40466
|
var formatPeriodLabel = (scope, offset, range) => {
|
|
40124
40467
|
if (scope === "all" || !range) return "All time";
|
|
40125
|
-
if (offset === 0)
|
|
40126
|
-
return scope === "week" ? "Last 7 days" : scope === "month" ? "Last 30 days" : "Last 365 days";
|
|
40127
|
-
}
|
|
40468
|
+
if (offset === 0) return SCOPE_RECENT_LABELS[scope];
|
|
40128
40469
|
const start2 = new Date(range.start);
|
|
40129
40470
|
const end = new Date(range.end);
|
|
40130
40471
|
return `${start2.getMonth() + 1}/${start2.getDate()} \u2013 ${end.getMonth() + 1}/${end.getDate()}`;
|
|
@@ -40141,10 +40482,16 @@ var hashUnitInterval = (key) => {
|
|
|
40141
40482
|
var DOT_APPEAR_MS = 260;
|
|
40142
40483
|
var DOT_APPEAR_SCATTER_MS = 620;
|
|
40143
40484
|
var dotDelayMs = (key) => Math.round(hashUnitInterval(key) * DOT_APPEAR_SCATTER_MS);
|
|
40144
|
-
var
|
|
40145
|
-
|
|
40146
|
-
)
|
|
40147
|
-
var
|
|
40485
|
+
var easeOutCubic = (t) => 1 - Math.pow(1 - t, 3);
|
|
40486
|
+
var easeInCubic = (t) => t * t * t;
|
|
40487
|
+
var dotEntranceScale = (key, elapsedMs) => easeOutCubic(clamp((elapsedMs - dotDelayMs(key)) / DOT_APPEAR_MS, 0, 1));
|
|
40488
|
+
var dotExitScale = (key, elapsedMs) => 1 - easeInCubic(
|
|
40489
|
+
clamp(
|
|
40490
|
+
(elapsedMs - (DOT_APPEAR_SCATTER_MS - dotDelayMs(key))) / DOT_APPEAR_MS,
|
|
40491
|
+
0,
|
|
40492
|
+
1
|
|
40493
|
+
)
|
|
40494
|
+
);
|
|
40148
40495
|
var DOT_EXIT_TOTAL_MS = DOT_APPEAR_SCATTER_MS + DOT_APPEAR_MS;
|
|
40149
40496
|
var BAR_GROW_MS = 200;
|
|
40150
40497
|
var BAR_GROW_SWEEP_MS = 560;
|
|
@@ -40155,6 +40502,7 @@ var barGrowAnimation = (index2, firstIndex, lastIndex) => {
|
|
|
40155
40502
|
0
|
|
40156
40503
|
)}ms backwards`;
|
|
40157
40504
|
};
|
|
40505
|
+
var BAR_ENTRANCE_TOTAL_MS = BAR_GROW_MS + BAR_GROW_SWEEP_MS;
|
|
40158
40506
|
var FADE_IN_ANIMATION = "epiqScrubberFadeIn 320ms ease-out";
|
|
40159
40507
|
var SCRUBBER_KEYFRAMES = `
|
|
40160
40508
|
/* Must animate the standalone 'scale' property, not 'transform': the dots
|
|
@@ -40185,10 +40533,10 @@ var SCRUBBER_KEYFRAMES = `
|
|
|
40185
40533
|
`;
|
|
40186
40534
|
var REDUCED_MOTION_QUERY = "(prefers-reduced-motion: reduce)";
|
|
40187
40535
|
var usePrefersReducedMotion = () => {
|
|
40188
|
-
const [reduced, setReduced] = (0,
|
|
40536
|
+
const [reduced, setReduced] = (0, import_react13.useState)(
|
|
40189
40537
|
() => window.matchMedia(REDUCED_MOTION_QUERY).matches
|
|
40190
40538
|
);
|
|
40191
|
-
(0,
|
|
40539
|
+
(0, import_react13.useEffect)(() => {
|
|
40192
40540
|
const query = window.matchMedia(REDUCED_MOTION_QUERY);
|
|
40193
40541
|
const onChange = () => setReduced(query.matches);
|
|
40194
40542
|
query.addEventListener("change", onChange);
|
|
@@ -40197,12 +40545,12 @@ var usePrefersReducedMotion = () => {
|
|
|
40197
40545
|
return reduced;
|
|
40198
40546
|
};
|
|
40199
40547
|
var useExitTransition = (visible, durationMs) => {
|
|
40200
|
-
const [mounted, setMounted] = (0,
|
|
40201
|
-
const [leaving, setLeaving] = (0,
|
|
40202
|
-
const wasVisible = (0,
|
|
40203
|
-
const duration = (0,
|
|
40548
|
+
const [mounted, setMounted] = (0, import_react13.useState)(visible);
|
|
40549
|
+
const [leaving, setLeaving] = (0, import_react13.useState)(false);
|
|
40550
|
+
const wasVisible = (0, import_react13.useRef)(visible);
|
|
40551
|
+
const duration = (0, import_react13.useRef)(durationMs);
|
|
40204
40552
|
duration.current = durationMs;
|
|
40205
|
-
(0,
|
|
40553
|
+
(0, import_react13.useEffect)(() => {
|
|
40206
40554
|
if (visible === wasVisible.current) return;
|
|
40207
40555
|
wasVisible.current = visible;
|
|
40208
40556
|
if (visible) {
|
|
@@ -40224,7 +40572,7 @@ var useExitTransition = (visible, durationMs) => {
|
|
|
40224
40572
|
return { mounted, leaving };
|
|
40225
40573
|
};
|
|
40226
40574
|
var usePersistedFlag = (key, fallback) => {
|
|
40227
|
-
const [value, setValue] = (0,
|
|
40575
|
+
const [value, setValue] = (0, import_react13.useState)(() => {
|
|
40228
40576
|
const stored = localStorage.getItem(key);
|
|
40229
40577
|
return stored === null ? fallback : stored === "true";
|
|
40230
40578
|
});
|
|
@@ -40236,12 +40584,25 @@ var usePersistedFlag = (key, fallback) => {
|
|
|
40236
40584
|
}
|
|
40237
40585
|
];
|
|
40238
40586
|
};
|
|
40587
|
+
var buildBoardFilter = (view, identities, hiddenIds) => {
|
|
40588
|
+
const axis = identityAxisFor(view);
|
|
40589
|
+
if (axis === null || hiddenIds.size === 0) return null;
|
|
40590
|
+
const visibleIds = new Set(
|
|
40591
|
+
identities.map((identity) => identity.id).filter((id) => !hiddenIds.has(id))
|
|
40592
|
+
);
|
|
40593
|
+
return { axis, visibleIds };
|
|
40594
|
+
};
|
|
40595
|
+
var issuePassesBoardFilter = (issue, commentAuthorIds, filter) => {
|
|
40596
|
+
if (!filter) return true;
|
|
40597
|
+
const ids = filter.axis === "tag" ? issue.tags.map((tag) => tag.id) : filter.axis === "assignee" ? issue.assignees.map((assignee) => assignee.id) : commentAuthorIds;
|
|
40598
|
+
return ids.some((id) => filter.visibleIds.has(id));
|
|
40599
|
+
};
|
|
40239
40600
|
|
|
40240
40601
|
// source/gui/client/components/ScrubberParts.tsx
|
|
40241
|
-
var
|
|
40602
|
+
var import_react14 = __toESM(require_react(), 1);
|
|
40242
40603
|
|
|
40243
40604
|
// source/gui/client/components/Checkbox.tsx
|
|
40244
|
-
var
|
|
40605
|
+
var import_jsx_runtime27 = __toESM(require_jsx_runtime(), 1);
|
|
40245
40606
|
var Checkbox = ({
|
|
40246
40607
|
label,
|
|
40247
40608
|
checked,
|
|
@@ -40251,7 +40612,7 @@ var Checkbox = ({
|
|
|
40251
40612
|
title
|
|
40252
40613
|
}) => {
|
|
40253
40614
|
const color2 = checked ? activeColor : GUI_THEME.dim;
|
|
40254
|
-
return /* @__PURE__ */ (0,
|
|
40615
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
40255
40616
|
"label",
|
|
40256
40617
|
{
|
|
40257
40618
|
title,
|
|
@@ -40265,7 +40626,7 @@ var Checkbox = ({
|
|
|
40265
40626
|
opacity: disabled ? 0.4 : 1
|
|
40266
40627
|
},
|
|
40267
40628
|
children: [
|
|
40268
|
-
/* @__PURE__ */ (0,
|
|
40629
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
40269
40630
|
"span",
|
|
40270
40631
|
{
|
|
40271
40632
|
style: {
|
|
@@ -40282,7 +40643,7 @@ var Checkbox = ({
|
|
|
40282
40643
|
flexShrink: 0
|
|
40283
40644
|
},
|
|
40284
40645
|
children: [
|
|
40285
|
-
/* @__PURE__ */ (0,
|
|
40646
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
40286
40647
|
"input",
|
|
40287
40648
|
{
|
|
40288
40649
|
type: "checkbox",
|
|
@@ -40300,7 +40661,7 @@ var Checkbox = ({
|
|
|
40300
40661
|
}
|
|
40301
40662
|
}
|
|
40302
40663
|
),
|
|
40303
|
-
checked && /* @__PURE__ */ (0,
|
|
40664
|
+
checked && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
40304
40665
|
"span",
|
|
40305
40666
|
{
|
|
40306
40667
|
style: {
|
|
@@ -40321,8 +40682,8 @@ var Checkbox = ({
|
|
|
40321
40682
|
};
|
|
40322
40683
|
|
|
40323
40684
|
// source/gui/client/components/IconChevronDown.tsx
|
|
40324
|
-
var
|
|
40325
|
-
var IconChevronDown = ({ size = 16 }) => /* @__PURE__ */ (0,
|
|
40685
|
+
var import_jsx_runtime28 = __toESM(require_jsx_runtime(), 1);
|
|
40686
|
+
var IconChevronDown = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
40326
40687
|
"svg",
|
|
40327
40688
|
{
|
|
40328
40689
|
width: size,
|
|
@@ -40334,13 +40695,13 @@ var IconChevronDown = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime2
|
|
|
40334
40695
|
strokeLinecap: "round",
|
|
40335
40696
|
strokeLinejoin: "round",
|
|
40336
40697
|
"aria-hidden": "true",
|
|
40337
|
-
children: /* @__PURE__ */ (0,
|
|
40698
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("polyline", { points: "6 9 12 15 18 9" })
|
|
40338
40699
|
}
|
|
40339
40700
|
);
|
|
40340
40701
|
|
|
40341
40702
|
// source/gui/client/components/IconChevronRight.tsx
|
|
40342
|
-
var
|
|
40343
|
-
var IconChevronRight = ({ size = 16 }) => /* @__PURE__ */ (0,
|
|
40703
|
+
var import_jsx_runtime29 = __toESM(require_jsx_runtime(), 1);
|
|
40704
|
+
var IconChevronRight = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
40344
40705
|
"svg",
|
|
40345
40706
|
{
|
|
40346
40707
|
width: size,
|
|
@@ -40352,12 +40713,12 @@ var IconChevronRight = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime
|
|
|
40352
40713
|
strokeLinecap: "round",
|
|
40353
40714
|
strokeLinejoin: "round",
|
|
40354
40715
|
"aria-hidden": "true",
|
|
40355
|
-
children: /* @__PURE__ */ (0,
|
|
40716
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("polyline", { points: "9 18 15 12 9 6" })
|
|
40356
40717
|
}
|
|
40357
40718
|
);
|
|
40358
40719
|
|
|
40359
40720
|
// source/gui/client/components/ScrubberParts.tsx
|
|
40360
|
-
var
|
|
40721
|
+
var import_jsx_runtime30 = __toESM(require_jsx_runtime(), 1);
|
|
40361
40722
|
var toggleButtonStyle = (active) => ({
|
|
40362
40723
|
background: "transparent",
|
|
40363
40724
|
border: `1px solid ${active ? GUI_THEME.accent : GUI_THEME.dim}`,
|
|
@@ -40367,6 +40728,319 @@ var toggleButtonStyle = (active) => ({
|
|
|
40367
40728
|
padding: "2px 8px",
|
|
40368
40729
|
cursor: "pointer"
|
|
40369
40730
|
});
|
|
40731
|
+
var CATEGORY_LABELS = {
|
|
40732
|
+
tickets: "Tickets",
|
|
40733
|
+
comments: "Comments",
|
|
40734
|
+
tagging: "Tags",
|
|
40735
|
+
assigning: "Assignees"
|
|
40736
|
+
};
|
|
40737
|
+
var disclosureStyle = {
|
|
40738
|
+
background: "transparent",
|
|
40739
|
+
border: "none",
|
|
40740
|
+
padding: 0,
|
|
40741
|
+
display: "inline-flex",
|
|
40742
|
+
alignItems: "center",
|
|
40743
|
+
color: GUI_THEME.secondary,
|
|
40744
|
+
cursor: "pointer"
|
|
40745
|
+
};
|
|
40746
|
+
var VIEW_LABELS = {
|
|
40747
|
+
all: "All board events",
|
|
40748
|
+
...CATEGORY_LABELS
|
|
40749
|
+
};
|
|
40750
|
+
var SELECT_TRIGGER_WIDTH = 180;
|
|
40751
|
+
var selectTriggerStyle = (color2, disabled) => ({
|
|
40752
|
+
display: "inline-flex",
|
|
40753
|
+
alignItems: "center",
|
|
40754
|
+
justifyContent: "space-between",
|
|
40755
|
+
gap: 6,
|
|
40756
|
+
width: SELECT_TRIGGER_WIDTH,
|
|
40757
|
+
boxSizing: "border-box",
|
|
40758
|
+
background: "rgba(208, 223, 255, 0.08)",
|
|
40759
|
+
// None, but padded as though there were, so it sits at the same height as
|
|
40760
|
+
// the bordered toggles on either side.
|
|
40761
|
+
border: "none",
|
|
40762
|
+
color: disabled ? GUI_THEME.dim : color2,
|
|
40763
|
+
borderRadius: 6,
|
|
40764
|
+
fontFamily: "inherit",
|
|
40765
|
+
fontSize: 10,
|
|
40766
|
+
padding: "3px 7px 3px 9px",
|
|
40767
|
+
cursor: disabled ? "not-allowed" : "pointer",
|
|
40768
|
+
opacity: disabled ? 0.4 : 1
|
|
40769
|
+
});
|
|
40770
|
+
var nestedListStyle = {
|
|
40771
|
+
display: "flex",
|
|
40772
|
+
flexDirection: "column",
|
|
40773
|
+
gap: 7,
|
|
40774
|
+
marginLeft: 5,
|
|
40775
|
+
paddingLeft: 8,
|
|
40776
|
+
borderLeft: `1px solid ${GUI_THEME.line}`
|
|
40777
|
+
};
|
|
40778
|
+
var popoverStyle = {
|
|
40779
|
+
position: "absolute",
|
|
40780
|
+
top: "100%",
|
|
40781
|
+
left: 0,
|
|
40782
|
+
marginTop: 6,
|
|
40783
|
+
// Carries the column and its gap itself. Without them the options stack as
|
|
40784
|
+
// plain blocks and their radios sit edge to edge.
|
|
40785
|
+
display: "flex",
|
|
40786
|
+
flexDirection: "column",
|
|
40787
|
+
gap: 7,
|
|
40788
|
+
padding: "10px 14px 10px 10px",
|
|
40789
|
+
// Sized for the common case up front, so opening a kind with a list does
|
|
40790
|
+
// not visibly widen the panel under the pointer.
|
|
40791
|
+
minWidth: 200,
|
|
40792
|
+
background: GUI_THEME.panel2,
|
|
40793
|
+
border: `1px solid ${GUI_THEME.line}`,
|
|
40794
|
+
borderRadius: 8,
|
|
40795
|
+
boxShadow: "0 8px 24px rgba(0, 0, 0, 0.45)",
|
|
40796
|
+
// Above the dots and the needle, which sit at 1 and 2.
|
|
40797
|
+
zIndex: 30,
|
|
40798
|
+
whiteSpace: "nowrap"
|
|
40799
|
+
};
|
|
40800
|
+
var onlyButtonStyle = {
|
|
40801
|
+
background: "transparent",
|
|
40802
|
+
border: `1px solid ${GUI_THEME.line}`,
|
|
40803
|
+
borderRadius: 4,
|
|
40804
|
+
color: GUI_THEME.dim,
|
|
40805
|
+
fontFamily: "inherit",
|
|
40806
|
+
fontSize: 9,
|
|
40807
|
+
lineHeight: 1,
|
|
40808
|
+
padding: "2px 4px",
|
|
40809
|
+
cursor: "pointer"
|
|
40810
|
+
};
|
|
40811
|
+
var useDismissOnOutsideClick = (open, onDismiss) => {
|
|
40812
|
+
const ref = (0, import_react14.useRef)(null);
|
|
40813
|
+
(0, import_react14.useEffect)(() => {
|
|
40814
|
+
if (!open) return;
|
|
40815
|
+
const onPointerDown = (event) => {
|
|
40816
|
+
if (!ref.current?.contains(event.target)) onDismiss();
|
|
40817
|
+
};
|
|
40818
|
+
const onKeyDown = (event) => {
|
|
40819
|
+
if (event.key === "Escape") onDismiss();
|
|
40820
|
+
};
|
|
40821
|
+
document.addEventListener("mousedown", onPointerDown);
|
|
40822
|
+
document.addEventListener("keydown", onKeyDown);
|
|
40823
|
+
return () => {
|
|
40824
|
+
document.removeEventListener("mousedown", onPointerDown);
|
|
40825
|
+
document.removeEventListener("keydown", onKeyDown);
|
|
40826
|
+
};
|
|
40827
|
+
}, [open, onDismiss]);
|
|
40828
|
+
return ref;
|
|
40829
|
+
};
|
|
40830
|
+
var Radio = ({
|
|
40831
|
+
label,
|
|
40832
|
+
selected,
|
|
40833
|
+
color: color2,
|
|
40834
|
+
disabled,
|
|
40835
|
+
onSelect
|
|
40836
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
|
|
40837
|
+
"button",
|
|
40838
|
+
{
|
|
40839
|
+
type: "button",
|
|
40840
|
+
role: "radio",
|
|
40841
|
+
"aria-checked": selected,
|
|
40842
|
+
disabled,
|
|
40843
|
+
onClick: onSelect,
|
|
40844
|
+
style: {
|
|
40845
|
+
display: "flex",
|
|
40846
|
+
alignItems: "center",
|
|
40847
|
+
gap: 5,
|
|
40848
|
+
background: "transparent",
|
|
40849
|
+
border: "none",
|
|
40850
|
+
padding: 0,
|
|
40851
|
+
fontSize: 10,
|
|
40852
|
+
fontFamily: "inherit",
|
|
40853
|
+
color: selected ? color2 : GUI_THEME.dim,
|
|
40854
|
+
cursor: disabled ? "not-allowed" : "pointer",
|
|
40855
|
+
opacity: disabled ? 0.4 : 1
|
|
40856
|
+
},
|
|
40857
|
+
children: [
|
|
40858
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
40859
|
+
"span",
|
|
40860
|
+
{
|
|
40861
|
+
style: {
|
|
40862
|
+
width: 12,
|
|
40863
|
+
height: 12,
|
|
40864
|
+
borderRadius: "50%",
|
|
40865
|
+
border: `1px solid ${selected ? color2 : GUI_THEME.dim}`,
|
|
40866
|
+
display: "inline-flex",
|
|
40867
|
+
alignItems: "center",
|
|
40868
|
+
justifyContent: "center",
|
|
40869
|
+
flexShrink: 0
|
|
40870
|
+
},
|
|
40871
|
+
children: selected && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
40872
|
+
"span",
|
|
40873
|
+
{
|
|
40874
|
+
style: {
|
|
40875
|
+
width: 6,
|
|
40876
|
+
height: 6,
|
|
40877
|
+
borderRadius: "50%",
|
|
40878
|
+
background: color2
|
|
40879
|
+
}
|
|
40880
|
+
}
|
|
40881
|
+
)
|
|
40882
|
+
}
|
|
40883
|
+
),
|
|
40884
|
+
label
|
|
40885
|
+
]
|
|
40886
|
+
}
|
|
40887
|
+
);
|
|
40888
|
+
var BoardSeriesGroup = ({
|
|
40889
|
+
showIssues,
|
|
40890
|
+
view,
|
|
40891
|
+
identities,
|
|
40892
|
+
hiddenIds,
|
|
40893
|
+
expanded,
|
|
40894
|
+
identitiesExpanded,
|
|
40895
|
+
filtered,
|
|
40896
|
+
onChangeShowIssues,
|
|
40897
|
+
onChangeView,
|
|
40898
|
+
onToggleIdentity,
|
|
40899
|
+
onOnlyIdentity,
|
|
40900
|
+
onToggleExpanded,
|
|
40901
|
+
onSetIdentitiesExpanded
|
|
40902
|
+
}) => {
|
|
40903
|
+
const sole = soleVisibleIdentity(identities, hiddenIds);
|
|
40904
|
+
const partial = filtered && hiddenIds.size > 0 && identityAxisFor(view) !== null;
|
|
40905
|
+
const label = sole ? `${VIEW_LABELS[view]}: ${sole.name}` : partial ? `${VIEW_LABELS[view]} (multi)` : VIEW_LABELS[view];
|
|
40906
|
+
const color2 = sole?.color ?? (partial ? GUI_THEME.dim2 : boardViewColor(view));
|
|
40907
|
+
const ref = useDismissOnOutsideClick(expanded, onToggleExpanded);
|
|
40908
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
|
|
40909
|
+
"div",
|
|
40910
|
+
{
|
|
40911
|
+
ref,
|
|
40912
|
+
style: { position: "relative", display: "flex", flexDirection: "column" },
|
|
40913
|
+
children: [
|
|
40914
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
|
|
40915
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
40916
|
+
Checkbox,
|
|
40917
|
+
{
|
|
40918
|
+
label: null,
|
|
40919
|
+
title: "Show board events",
|
|
40920
|
+
checked: showIssues,
|
|
40921
|
+
activeColor: color2,
|
|
40922
|
+
onChange: onChangeShowIssues
|
|
40923
|
+
}
|
|
40924
|
+
),
|
|
40925
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
|
|
40926
|
+
"button",
|
|
40927
|
+
{
|
|
40928
|
+
type: "button",
|
|
40929
|
+
onClick: onToggleExpanded,
|
|
40930
|
+
disabled: !showIssues,
|
|
40931
|
+
title: filtered ? "Choose what the board series plots" : "This window holds too many events to split by kind",
|
|
40932
|
+
"aria-haspopup": "listbox",
|
|
40933
|
+
"aria-expanded": expanded,
|
|
40934
|
+
style: selectTriggerStyle(color2, !showIssues),
|
|
40935
|
+
children: [
|
|
40936
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
40937
|
+
"span",
|
|
40938
|
+
{
|
|
40939
|
+
style: {
|
|
40940
|
+
overflow: "hidden",
|
|
40941
|
+
textOverflow: "ellipsis",
|
|
40942
|
+
whiteSpace: "nowrap"
|
|
40943
|
+
},
|
|
40944
|
+
children: label
|
|
40945
|
+
}
|
|
40946
|
+
),
|
|
40947
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { style: { display: "inline-flex", flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(IconChevronDown, { size: 12 }) })
|
|
40948
|
+
]
|
|
40949
|
+
}
|
|
40950
|
+
)
|
|
40951
|
+
] }),
|
|
40952
|
+
expanded && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { role: "radiogroup", style: popoverStyle, children: BOARD_VIEWS.map((option) => {
|
|
40953
|
+
const selected = view === option;
|
|
40954
|
+
const hasList = identityAxisFor(option) !== null;
|
|
40955
|
+
const open = selected && identitiesExpanded;
|
|
40956
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
|
|
40957
|
+
"div",
|
|
40958
|
+
{
|
|
40959
|
+
style: { display: "flex", flexDirection: "column", gap: 7 },
|
|
40960
|
+
children: [
|
|
40961
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 3 }, children: [
|
|
40962
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
40963
|
+
Radio,
|
|
40964
|
+
{
|
|
40965
|
+
label: VIEW_LABELS[option],
|
|
40966
|
+
selected,
|
|
40967
|
+
color: boardViewColor(option),
|
|
40968
|
+
disabled: !showIssues || !filtered,
|
|
40969
|
+
onSelect: () => onChangeView(option)
|
|
40970
|
+
}
|
|
40971
|
+
),
|
|
40972
|
+
hasList && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
40973
|
+
"button",
|
|
40974
|
+
{
|
|
40975
|
+
type: "button",
|
|
40976
|
+
disabled: !showIssues || !filtered,
|
|
40977
|
+
onClick: () => {
|
|
40978
|
+
if (!selected) onChangeView(option);
|
|
40979
|
+
onSetIdentitiesExpanded(!open);
|
|
40980
|
+
},
|
|
40981
|
+
title: open ? "Hide the list" : "Pick which to show",
|
|
40982
|
+
"aria-expanded": open,
|
|
40983
|
+
style: disclosureStyle,
|
|
40984
|
+
children: open ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(IconChevronDown, { size: 12 }) : /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(IconChevronRight, { size: 12 })
|
|
40985
|
+
}
|
|
40986
|
+
)
|
|
40987
|
+
] }),
|
|
40988
|
+
open && identities.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
40989
|
+
"div",
|
|
40990
|
+
{
|
|
40991
|
+
style: {
|
|
40992
|
+
...nestedListStyle,
|
|
40993
|
+
// A repo with dozens of tags would otherwise push the
|
|
40994
|
+
// board itself off the screen.
|
|
40995
|
+
maxHeight: 132,
|
|
40996
|
+
overflowY: "auto"
|
|
40997
|
+
},
|
|
40998
|
+
children: identities.map((identity) => /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
|
|
40999
|
+
"div",
|
|
41000
|
+
{
|
|
41001
|
+
style: {
|
|
41002
|
+
display: "flex",
|
|
41003
|
+
alignItems: "center",
|
|
41004
|
+
justifyContent: "space-between",
|
|
41005
|
+
gap: 10
|
|
41006
|
+
},
|
|
41007
|
+
children: [
|
|
41008
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
41009
|
+
Checkbox,
|
|
41010
|
+
{
|
|
41011
|
+
label: identity.name,
|
|
41012
|
+
checked: !hiddenIds.has(identity.id),
|
|
41013
|
+
activeColor: identity.color,
|
|
41014
|
+
disabled: !showIssues,
|
|
41015
|
+
onChange: (next) => onToggleIdentity(identity.id, next)
|
|
41016
|
+
}
|
|
41017
|
+
),
|
|
41018
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
41019
|
+
"button",
|
|
41020
|
+
{
|
|
41021
|
+
type: "button",
|
|
41022
|
+
title: `Show only ${identity.name}`,
|
|
41023
|
+
disabled: !showIssues,
|
|
41024
|
+
onClick: () => onOnlyIdentity(identity.id),
|
|
41025
|
+
style: onlyButtonStyle,
|
|
41026
|
+
children: "only"
|
|
41027
|
+
}
|
|
41028
|
+
)
|
|
41029
|
+
]
|
|
41030
|
+
},
|
|
41031
|
+
identity.id
|
|
41032
|
+
))
|
|
41033
|
+
}
|
|
41034
|
+
)
|
|
41035
|
+
]
|
|
41036
|
+
},
|
|
41037
|
+
option
|
|
41038
|
+
);
|
|
41039
|
+
}) })
|
|
41040
|
+
]
|
|
41041
|
+
}
|
|
41042
|
+
);
|
|
41043
|
+
};
|
|
40370
41044
|
var navButtonStyle = {
|
|
40371
41045
|
background: "transparent",
|
|
40372
41046
|
border: `1px solid ${GUI_THEME.dim}`,
|
|
@@ -40385,6 +41059,12 @@ var ScrubberControls = ({
|
|
|
40385
41059
|
showIssues,
|
|
40386
41060
|
showCommits,
|
|
40387
41061
|
allBoards,
|
|
41062
|
+
boardView,
|
|
41063
|
+
identities,
|
|
41064
|
+
hiddenIdentityIds,
|
|
41065
|
+
categoriesExpanded,
|
|
41066
|
+
identitiesExpanded,
|
|
41067
|
+
categoriesFiltered,
|
|
40388
41068
|
isScrubbing,
|
|
40389
41069
|
nowLabel,
|
|
40390
41070
|
onChangeScope,
|
|
@@ -40393,11 +41073,16 @@ var ScrubberControls = ({
|
|
|
40393
41073
|
onChangeShowIssues,
|
|
40394
41074
|
onChangeShowCommits,
|
|
40395
41075
|
onChangeAllBoards,
|
|
41076
|
+
onChangeBoardView,
|
|
41077
|
+
onToggleIdentity,
|
|
41078
|
+
onOnlyIdentity,
|
|
41079
|
+
onToggleCategoriesExpanded,
|
|
41080
|
+
onSetIdentitiesExpanded,
|
|
40396
41081
|
onReturnToLive
|
|
40397
|
-
}) => /* @__PURE__ */ (0,
|
|
40398
|
-
/* @__PURE__ */ (0,
|
|
40399
|
-
scope !== "all" && /* @__PURE__ */ (0,
|
|
40400
|
-
/* @__PURE__ */ (0,
|
|
41082
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 12 }, children: [
|
|
41083
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
|
|
41084
|
+
scope !== "all" && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 2 }, children: [
|
|
41085
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
40401
41086
|
"button",
|
|
40402
41087
|
{
|
|
40403
41088
|
title: "Earlier",
|
|
@@ -40406,7 +41091,7 @@ var ScrubberControls = ({
|
|
|
40406
41091
|
children: "\u25C0"
|
|
40407
41092
|
}
|
|
40408
41093
|
),
|
|
40409
|
-
/* @__PURE__ */ (0,
|
|
41094
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
40410
41095
|
"span",
|
|
40411
41096
|
{
|
|
40412
41097
|
style: {
|
|
@@ -40423,7 +41108,7 @@ var ScrubberControls = ({
|
|
|
40423
41108
|
children: formatPeriodLabel(scope, offset, periodRange)
|
|
40424
41109
|
}
|
|
40425
41110
|
),
|
|
40426
|
-
/* @__PURE__ */ (0,
|
|
41111
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
40427
41112
|
"button",
|
|
40428
41113
|
{
|
|
40429
41114
|
title: "Later",
|
|
@@ -40438,7 +41123,7 @@ var ScrubberControls = ({
|
|
|
40438
41123
|
}
|
|
40439
41124
|
)
|
|
40440
41125
|
] }),
|
|
40441
|
-
/* @__PURE__ */ (0,
|
|
41126
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { style: { display: "flex", gap: 2 }, children: SCOPES.map((option) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
40442
41127
|
"button",
|
|
40443
41128
|
{
|
|
40444
41129
|
onClick: () => onChangeScope(option),
|
|
@@ -40448,8 +41133,8 @@ var ScrubberControls = ({
|
|
|
40448
41133
|
option
|
|
40449
41134
|
)) })
|
|
40450
41135
|
] }),
|
|
40451
|
-
/* @__PURE__ */ (0,
|
|
40452
|
-
/* @__PURE__ */ (0,
|
|
41136
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { style: { display: "flex", gap: 2 }, children: [
|
|
41137
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
40453
41138
|
"button",
|
|
40454
41139
|
{
|
|
40455
41140
|
title: "How much happened, per equal-width period \u2014 no empty gaps for quiet stretches",
|
|
@@ -40458,7 +41143,7 @@ var ScrubberControls = ({
|
|
|
40458
41143
|
children: "Volume"
|
|
40459
41144
|
}
|
|
40460
41145
|
),
|
|
40461
|
-
/* @__PURE__ */ (0,
|
|
41146
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
40462
41147
|
"button",
|
|
40463
41148
|
{
|
|
40464
41149
|
title: "Individual events by exact moment \u2014 x is elapsed time, y is time of day",
|
|
@@ -40468,17 +41153,8 @@ var ScrubberControls = ({
|
|
|
40468
41153
|
}
|
|
40469
41154
|
)
|
|
40470
41155
|
] }),
|
|
40471
|
-
/* @__PURE__ */ (0,
|
|
40472
|
-
/* @__PURE__ */ (0,
|
|
40473
|
-
Checkbox,
|
|
40474
|
-
{
|
|
40475
|
-
label: "Board",
|
|
40476
|
-
checked: showIssues,
|
|
40477
|
-
activeColor: GUI_THEME.accent,
|
|
40478
|
-
onChange: onChangeShowIssues
|
|
40479
|
-
}
|
|
40480
|
-
),
|
|
40481
|
-
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
41156
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { style: { display: "flex", gap: 12, alignItems: "center" }, children: [
|
|
41157
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
40482
41158
|
Checkbox,
|
|
40483
41159
|
{
|
|
40484
41160
|
label: "Code",
|
|
@@ -40487,17 +41163,26 @@ var ScrubberControls = ({
|
|
|
40487
41163
|
onChange: onChangeShowCommits
|
|
40488
41164
|
}
|
|
40489
41165
|
),
|
|
40490
|
-
/* @__PURE__ */ (0,
|
|
40491
|
-
|
|
41166
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
41167
|
+
BoardSeriesGroup,
|
|
40492
41168
|
{
|
|
40493
|
-
|
|
40494
|
-
|
|
40495
|
-
|
|
40496
|
-
|
|
41169
|
+
showIssues,
|
|
41170
|
+
view: boardView,
|
|
41171
|
+
identities,
|
|
41172
|
+
hiddenIds: hiddenIdentityIds,
|
|
41173
|
+
expanded: categoriesExpanded,
|
|
41174
|
+
identitiesExpanded,
|
|
41175
|
+
filtered: categoriesFiltered,
|
|
41176
|
+
onChangeShowIssues,
|
|
41177
|
+
onChangeView: onChangeBoardView,
|
|
41178
|
+
onToggleIdentity,
|
|
41179
|
+
onOnlyIdentity,
|
|
41180
|
+
onToggleExpanded: onToggleCategoriesExpanded,
|
|
41181
|
+
onSetIdentitiesExpanded
|
|
40497
41182
|
}
|
|
40498
41183
|
)
|
|
40499
41184
|
] }),
|
|
40500
|
-
/* @__PURE__ */ (0,
|
|
41185
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
40501
41186
|
"div",
|
|
40502
41187
|
{
|
|
40503
41188
|
style: {
|
|
@@ -40509,7 +41194,7 @@ var ScrubberControls = ({
|
|
|
40509
41194
|
width: 100,
|
|
40510
41195
|
flexShrink: 0
|
|
40511
41196
|
},
|
|
40512
|
-
children: isScrubbing ? /* @__PURE__ */ (0,
|
|
41197
|
+
children: isScrubbing ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
40513
41198
|
"button",
|
|
40514
41199
|
{
|
|
40515
41200
|
onClick: onReturnToLive,
|
|
@@ -40525,7 +41210,7 @@ var ScrubberControls = ({
|
|
|
40525
41210
|
},
|
|
40526
41211
|
children: "Return to live"
|
|
40527
41212
|
}
|
|
40528
|
-
) : /* @__PURE__ */ (0,
|
|
41213
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
40529
41214
|
"span",
|
|
40530
41215
|
{
|
|
40531
41216
|
style: {
|
|
@@ -40545,7 +41230,7 @@ var ScrubberHeader = ({
|
|
|
40545
41230
|
collapsed,
|
|
40546
41231
|
onToggleCollapsed,
|
|
40547
41232
|
scrubbingAsOf
|
|
40548
|
-
}) => /* @__PURE__ */ (0,
|
|
41233
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
|
|
40549
41234
|
"div",
|
|
40550
41235
|
{
|
|
40551
41236
|
style: {
|
|
@@ -40556,7 +41241,7 @@ var ScrubberHeader = ({
|
|
|
40556
41241
|
whiteSpace: "nowrap"
|
|
40557
41242
|
},
|
|
40558
41243
|
children: [
|
|
40559
|
-
/* @__PURE__ */ (0,
|
|
41244
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
|
|
40560
41245
|
"button",
|
|
40561
41246
|
{
|
|
40562
41247
|
onClick: onToggleCollapsed,
|
|
@@ -40574,13 +41259,13 @@ var ScrubberHeader = ({
|
|
|
40574
41259
|
},
|
|
40575
41260
|
children: [
|
|
40576
41261
|
"Time travel",
|
|
40577
|
-
collapsed ? /* @__PURE__ */ (0,
|
|
41262
|
+
collapsed ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(IconChevronRight, { size: 12 }) : /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(IconChevronDown, { size: 12 })
|
|
40578
41263
|
]
|
|
40579
41264
|
}
|
|
40580
41265
|
),
|
|
40581
|
-
scrubbingAsOf !== null && /* @__PURE__ */ (0,
|
|
40582
|
-
/* @__PURE__ */ (0,
|
|
40583
|
-
/* @__PURE__ */ (0,
|
|
41266
|
+
scrubbingAsOf !== null && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
|
|
41267
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { style: { color: GUI_THEME.accent, fontWeight: 700 }, children: "Read-only" }),
|
|
41268
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { style: { color: GUI_THEME.primary }, children: scrubbingAsOf })
|
|
40584
41269
|
] })
|
|
40585
41270
|
]
|
|
40586
41271
|
}
|
|
@@ -40590,7 +41275,7 @@ var SegmentHighlight = ({
|
|
|
40590
41275
|
fractionForTime
|
|
40591
41276
|
}) => {
|
|
40592
41277
|
const left = fractionForTime(segment.start);
|
|
40593
|
-
return /* @__PURE__ */ (0,
|
|
41278
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
40594
41279
|
"div",
|
|
40595
41280
|
{
|
|
40596
41281
|
style: {
|
|
@@ -40622,7 +41307,7 @@ var SegmentHighlight = ({
|
|
|
40622
41307
|
var TrackBaseline = ({
|
|
40623
41308
|
color: color2,
|
|
40624
41309
|
anchor
|
|
40625
|
-
}) => /* @__PURE__ */ (0,
|
|
41310
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
40626
41311
|
"div",
|
|
40627
41312
|
{
|
|
40628
41313
|
style: {
|
|
@@ -40638,11 +41323,11 @@ var TrackBaseline = ({
|
|
|
40638
41323
|
}
|
|
40639
41324
|
}
|
|
40640
41325
|
);
|
|
40641
|
-
var HourAxisLabels = () => /* @__PURE__ */ (0,
|
|
41326
|
+
var HourAxisLabels = () => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_jsx_runtime30.Fragment, { children: [
|
|
40642
41327
|
["00:00", { top: EVENTS_MODE_VERTICAL_PADDING }],
|
|
40643
41328
|
["12:00", { top: "50%", transform: "translateY(-50%)" }],
|
|
40644
41329
|
["24:00", { bottom: EVENTS_MODE_VERTICAL_PADDING }]
|
|
40645
|
-
].map(([label, position3]) => /* @__PURE__ */ (0,
|
|
41330
|
+
].map(([label, position3]) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
40646
41331
|
"span",
|
|
40647
41332
|
{
|
|
40648
41333
|
style: {
|
|
@@ -40660,14 +41345,18 @@ var HourAxisLabels = () => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_
|
|
|
40660
41345
|
var SeriesLayer = ({
|
|
40661
41346
|
animate,
|
|
40662
41347
|
children
|
|
40663
|
-
}) => /* @__PURE__ */ (0,
|
|
41348
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
40664
41349
|
"div",
|
|
40665
41350
|
{
|
|
40666
41351
|
style: {
|
|
40667
41352
|
position: "absolute",
|
|
40668
41353
|
inset: 0,
|
|
40669
41354
|
pointerEvents: "none",
|
|
40670
|
-
animation: animate ? FADE_IN_ANIMATION : void 0
|
|
41355
|
+
animation: animate ? FADE_IN_ANIMATION : void 0,
|
|
41356
|
+
// Walls this subtree off from the needle and highlight moving above
|
|
41357
|
+
// it: without containment every frame of a drag re-lays-out the
|
|
41358
|
+
// thousands of dots inside, and the drag stutters.
|
|
41359
|
+
contain: "layout paint"
|
|
40671
41360
|
},
|
|
40672
41361
|
children
|
|
40673
41362
|
}
|
|
@@ -40685,8 +41374,13 @@ var VolumeBars = ({
|
|
|
40685
41374
|
const widthPercent = 100 / bucketCount;
|
|
40686
41375
|
const barWidth = barWidthCss(bucketCount);
|
|
40687
41376
|
const growsUp = direction === "up";
|
|
40688
|
-
|
|
40689
|
-
|
|
41377
|
+
const [fresh, setFresh] = (0, import_react14.useState)(true);
|
|
41378
|
+
(0, import_react14.useEffect)(() => {
|
|
41379
|
+
const timeout = setTimeout(() => setFresh(false), BAR_ENTRANCE_TOTAL_MS);
|
|
41380
|
+
return () => clearTimeout(timeout);
|
|
41381
|
+
}, []);
|
|
41382
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
|
|
41383
|
+
highlightedIndex !== null && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
40690
41384
|
"div",
|
|
40691
41385
|
{
|
|
40692
41386
|
style: {
|
|
@@ -40702,7 +41396,7 @@ var VolumeBars = ({
|
|
|
40702
41396
|
}
|
|
40703
41397
|
}
|
|
40704
41398
|
),
|
|
40705
|
-
bars.map(({ index: index2, intensity }) => /* @__PURE__ */ (0,
|
|
41399
|
+
bars.map(({ index: index2, intensity }) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
40706
41400
|
"div",
|
|
40707
41401
|
{
|
|
40708
41402
|
style: {
|
|
@@ -40715,7 +41409,7 @@ var VolumeBars = ({
|
|
|
40715
41409
|
background: color2,
|
|
40716
41410
|
opacity: 0.35 + intensity * 0.65,
|
|
40717
41411
|
transformOrigin: growsUp ? "bottom" : "top",
|
|
40718
|
-
animation: animate ? barGrowAnimation(index2, firstBar, lastBar) : void 0,
|
|
41412
|
+
animation: animate && fresh ? barGrowAnimation(index2, firstBar, lastBar) : void 0,
|
|
40719
41413
|
pointerEvents: "none"
|
|
40720
41414
|
}
|
|
40721
41415
|
},
|
|
@@ -40723,55 +41417,14 @@ var VolumeBars = ({
|
|
|
40723
41417
|
))
|
|
40724
41418
|
] });
|
|
40725
41419
|
};
|
|
40726
|
-
var ScatterDot = ({
|
|
40727
|
-
fraction,
|
|
40728
|
-
hourFraction,
|
|
40729
|
-
size,
|
|
40730
|
-
color: color2,
|
|
40731
|
-
opacity,
|
|
40732
|
-
zIndex,
|
|
40733
|
-
title,
|
|
40734
|
-
animation,
|
|
40735
|
-
interactive = true,
|
|
40736
|
-
onMouseEnter,
|
|
40737
|
-
onMouseLeave,
|
|
40738
|
-
onClick
|
|
40739
|
-
}) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
40740
|
-
"div",
|
|
40741
|
-
{
|
|
40742
|
-
title,
|
|
40743
|
-
onPointerDown: onClick && ((event) => event.stopPropagation()),
|
|
40744
|
-
onClick: onClick && ((event) => {
|
|
40745
|
-
event.stopPropagation();
|
|
40746
|
-
onClick();
|
|
40747
|
-
}),
|
|
40748
|
-
onMouseEnter,
|
|
40749
|
-
onMouseLeave,
|
|
40750
|
-
style: {
|
|
40751
|
-
position: "absolute",
|
|
40752
|
-
left: `${fraction * 100}%`,
|
|
40753
|
-
top: EVENTS_MODE_VERTICAL_PADDING + hourFraction * EVENTS_SCATTER_HEIGHT,
|
|
40754
|
-
width: size,
|
|
40755
|
-
height: size,
|
|
40756
|
-
borderRadius: "50%",
|
|
40757
|
-
background: color2,
|
|
40758
|
-
opacity,
|
|
40759
|
-
zIndex,
|
|
40760
|
-
transform: `translate(${-size / 2}px, -50%)`,
|
|
40761
|
-
animation,
|
|
40762
|
-
pointerEvents: interactive ? "auto" : "none",
|
|
40763
|
-
cursor: onClick ? "pointer" : void 0
|
|
40764
|
-
}
|
|
40765
|
-
}
|
|
40766
|
-
);
|
|
40767
41420
|
var ScrubberNeedle = ({ fraction }) => {
|
|
40768
|
-
const [hovered, setHovered] = (0,
|
|
41421
|
+
const [hovered, setHovered] = (0, import_react14.useState)(false);
|
|
40769
41422
|
const hover = {
|
|
40770
41423
|
onMouseEnter: () => setHovered(true),
|
|
40771
41424
|
onMouseLeave: () => setHovered(false)
|
|
40772
41425
|
};
|
|
40773
|
-
return /* @__PURE__ */ (0,
|
|
40774
|
-
/* @__PURE__ */ (0,
|
|
41426
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
|
|
41427
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
40775
41428
|
"div",
|
|
40776
41429
|
{
|
|
40777
41430
|
...hover,
|
|
@@ -40791,7 +41444,7 @@ var ScrubberNeedle = ({ fraction }) => {
|
|
|
40791
41444
|
}
|
|
40792
41445
|
}
|
|
40793
41446
|
),
|
|
40794
|
-
/* @__PURE__ */ (0,
|
|
41447
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
40795
41448
|
"div",
|
|
40796
41449
|
{
|
|
40797
41450
|
...hover,
|
|
@@ -40821,7 +41474,7 @@ var ScrubberHoverHint = ({
|
|
|
40821
41474
|
fraction,
|
|
40822
41475
|
trackWidthPx,
|
|
40823
41476
|
empty: empty3 = false
|
|
40824
|
-
}) => /* @__PURE__ */ (0,
|
|
41477
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
|
|
40825
41478
|
"div",
|
|
40826
41479
|
{
|
|
40827
41480
|
style: {
|
|
@@ -40853,8 +41506,8 @@ var ScrubberHoverHint = ({
|
|
|
40853
41506
|
zIndex: 5
|
|
40854
41507
|
},
|
|
40855
41508
|
children: [
|
|
40856
|
-
segmentLabel && /* @__PURE__ */ (0,
|
|
40857
|
-
/* @__PURE__ */ (0,
|
|
41509
|
+
segmentLabel && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { style: { fontSize: 10, color: GUI_THEME.dim }, children: segmentLabel }),
|
|
41510
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
40858
41511
|
"div",
|
|
40859
41512
|
{
|
|
40860
41513
|
style: {
|
|
@@ -40867,7 +41520,7 @@ var ScrubberHoverHint = ({
|
|
|
40867
41520
|
children: label
|
|
40868
41521
|
}
|
|
40869
41522
|
),
|
|
40870
|
-
rows.map((row, index2) => /* @__PURE__ */ (0,
|
|
41523
|
+
rows.map((row, index2) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
40871
41524
|
"div",
|
|
40872
41525
|
{
|
|
40873
41526
|
style: {
|
|
@@ -40883,10 +41536,175 @@ var ScrubberHoverHint = ({
|
|
|
40883
41536
|
]
|
|
40884
41537
|
}
|
|
40885
41538
|
);
|
|
41539
|
+
var HIT_RADIUS = 7;
|
|
41540
|
+
var pointAt = (layers, x, y, width) => {
|
|
41541
|
+
let best = null;
|
|
41542
|
+
let bestDistance = HIT_RADIUS * HIT_RADIUS;
|
|
41543
|
+
for (const layer of layers) {
|
|
41544
|
+
if (layer.leaving) continue;
|
|
41545
|
+
for (const point4 of layer.points) {
|
|
41546
|
+
const dx = point4.fraction * width - x;
|
|
41547
|
+
const dy = EVENTS_MODE_VERTICAL_PADDING + point4.hourFraction * EVENTS_SCATTER_HEIGHT - y;
|
|
41548
|
+
const distance = dx * dx + dy * dy;
|
|
41549
|
+
if (distance <= bestDistance) {
|
|
41550
|
+
bestDistance = distance;
|
|
41551
|
+
best = point4;
|
|
41552
|
+
}
|
|
41553
|
+
}
|
|
41554
|
+
}
|
|
41555
|
+
return best;
|
|
41556
|
+
};
|
|
41557
|
+
var ScatterCanvas = ({
|
|
41558
|
+
layers,
|
|
41559
|
+
animate,
|
|
41560
|
+
onPointEnter,
|
|
41561
|
+
onPointLeave,
|
|
41562
|
+
onInspectCommit
|
|
41563
|
+
}) => {
|
|
41564
|
+
const canvasRef = (0, import_react14.useRef)(null);
|
|
41565
|
+
const sizeRef = (0, import_react14.useRef)({ width: 0, height: 0 });
|
|
41566
|
+
const layersRef = (0, import_react14.useRef)(layers);
|
|
41567
|
+
layersRef.current = layers;
|
|
41568
|
+
const phasesRef = (0, import_react14.useRef)(/* @__PURE__ */ new Map());
|
|
41569
|
+
const frameRef = (0, import_react14.useRef)(null);
|
|
41570
|
+
const hoveredRef = (0, import_react14.useRef)(null);
|
|
41571
|
+
const [entrancePlaying, setEntrancePlaying] = (0, import_react14.useState)(false);
|
|
41572
|
+
const paint = (0, import_react14.useCallback)((now) => {
|
|
41573
|
+
const canvas = canvasRef.current;
|
|
41574
|
+
const context = canvas?.getContext("2d");
|
|
41575
|
+
if (!canvas || !context) return false;
|
|
41576
|
+
const { width, height } = sizeRef.current;
|
|
41577
|
+
context.clearRect(0, 0, width, height);
|
|
41578
|
+
let running = false;
|
|
41579
|
+
for (const layer of layersRef.current) {
|
|
41580
|
+
const phase = phasesRef.current.get(layer.id);
|
|
41581
|
+
const elapsed = phase ? now - phase.startedAt : null;
|
|
41582
|
+
const done = elapsed === null || elapsed >= DOT_EXIT_TOTAL_MS;
|
|
41583
|
+
if (phase && !done) running = true;
|
|
41584
|
+
if (phase?.mode === "out" && done) continue;
|
|
41585
|
+
for (const point4 of layer.points) {
|
|
41586
|
+
const scale = phase === null || phase === void 0 || done ? 1 : phase.mode === "in" ? dotEntranceScale(point4.key, elapsed) : dotExitScale(point4.key, elapsed);
|
|
41587
|
+
if (scale <= 0) continue;
|
|
41588
|
+
context.globalAlpha = point4.opacity;
|
|
41589
|
+
context.fillStyle = point4.color;
|
|
41590
|
+
context.beginPath();
|
|
41591
|
+
context.arc(
|
|
41592
|
+
point4.fraction * width,
|
|
41593
|
+
EVENTS_MODE_VERTICAL_PADDING + point4.hourFraction * EVENTS_SCATTER_HEIGHT,
|
|
41594
|
+
point4.radius * scale,
|
|
41595
|
+
0,
|
|
41596
|
+
Math.PI * 2
|
|
41597
|
+
);
|
|
41598
|
+
context.fill();
|
|
41599
|
+
}
|
|
41600
|
+
}
|
|
41601
|
+
context.globalAlpha = 1;
|
|
41602
|
+
return running;
|
|
41603
|
+
}, []);
|
|
41604
|
+
const run = (0, import_react14.useCallback)(() => {
|
|
41605
|
+
if (frameRef.current !== null) return;
|
|
41606
|
+
const step = () => {
|
|
41607
|
+
frameRef.current = null;
|
|
41608
|
+
const running = paint(performance.now());
|
|
41609
|
+
if (running) frameRef.current = requestAnimationFrame(step);
|
|
41610
|
+
else setEntrancePlaying(false);
|
|
41611
|
+
};
|
|
41612
|
+
frameRef.current = requestAnimationFrame(step);
|
|
41613
|
+
}, [paint]);
|
|
41614
|
+
(0, import_react14.useEffect)(() => {
|
|
41615
|
+
const canvas = canvasRef.current;
|
|
41616
|
+
const parent = canvas?.parentElement;
|
|
41617
|
+
if (!canvas || !parent) return;
|
|
41618
|
+
const resize = () => {
|
|
41619
|
+
const ratio = window.devicePixelRatio || 1;
|
|
41620
|
+
const { width, height } = parent.getBoundingClientRect();
|
|
41621
|
+
sizeRef.current = { width, height };
|
|
41622
|
+
canvas.width = Math.round(width * ratio);
|
|
41623
|
+
canvas.height = Math.round(height * ratio);
|
|
41624
|
+
canvas.style.width = `${width}px`;
|
|
41625
|
+
canvas.style.height = `${height}px`;
|
|
41626
|
+
canvas.getContext("2d")?.setTransform(ratio, 0, 0, ratio, 0, 0);
|
|
41627
|
+
paint(performance.now());
|
|
41628
|
+
};
|
|
41629
|
+
resize();
|
|
41630
|
+
const observer = new ResizeObserver(resize);
|
|
41631
|
+
observer.observe(parent);
|
|
41632
|
+
return () => observer.disconnect();
|
|
41633
|
+
}, [paint]);
|
|
41634
|
+
const signature = layers.map((layer) => `${layer.id}:${layer.generation}:${layer.leaving}`).join("|");
|
|
41635
|
+
(0, import_react14.useEffect)(() => {
|
|
41636
|
+
const seen = /* @__PURE__ */ new Set();
|
|
41637
|
+
for (const layer of layers) {
|
|
41638
|
+
seen.add(layer.id);
|
|
41639
|
+
const key = `${layer.generation}:${layer.leaving}`;
|
|
41640
|
+
const marker = `${layer.id}@${key}`;
|
|
41641
|
+
const current = phasesRef.current.get(layer.id);
|
|
41642
|
+
if (current?.marker === marker)
|
|
41643
|
+
continue;
|
|
41644
|
+
if (!animate) {
|
|
41645
|
+
phasesRef.current.delete(layer.id);
|
|
41646
|
+
continue;
|
|
41647
|
+
}
|
|
41648
|
+
phasesRef.current.set(layer.id, {
|
|
41649
|
+
mode: layer.leaving ? "out" : "in",
|
|
41650
|
+
startedAt: performance.now(),
|
|
41651
|
+
marker
|
|
41652
|
+
});
|
|
41653
|
+
if (!layer.leaving) setEntrancePlaying(true);
|
|
41654
|
+
}
|
|
41655
|
+
for (const id of [...phasesRef.current.keys()])
|
|
41656
|
+
if (!seen.has(id)) phasesRef.current.delete(id);
|
|
41657
|
+
if (animate) run();
|
|
41658
|
+
else paint(performance.now());
|
|
41659
|
+
}, [signature, animate, run, paint]);
|
|
41660
|
+
(0, import_react14.useEffect)(() => {
|
|
41661
|
+
if (frameRef.current === null) paint(performance.now());
|
|
41662
|
+
}, [layers, paint]);
|
|
41663
|
+
(0, import_react14.useEffect)(
|
|
41664
|
+
() => () => {
|
|
41665
|
+
if (frameRef.current !== null) cancelAnimationFrame(frameRef.current);
|
|
41666
|
+
},
|
|
41667
|
+
[]
|
|
41668
|
+
);
|
|
41669
|
+
const hitTest = (event) => {
|
|
41670
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
41671
|
+
return pointAt(
|
|
41672
|
+
layersRef.current,
|
|
41673
|
+
event.clientX - rect.left,
|
|
41674
|
+
event.clientY - rect.top,
|
|
41675
|
+
rect.width
|
|
41676
|
+
);
|
|
41677
|
+
};
|
|
41678
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
41679
|
+
"canvas",
|
|
41680
|
+
{
|
|
41681
|
+
ref: canvasRef,
|
|
41682
|
+
"data-entrance": entrancePlaying ? "playing" : "done",
|
|
41683
|
+
style: { position: "absolute", inset: 0 },
|
|
41684
|
+
onMouseMove: (event) => {
|
|
41685
|
+
const point4 = hitTest(event);
|
|
41686
|
+
if (point4?.key === hoveredRef.current) return;
|
|
41687
|
+
hoveredRef.current = point4?.key ?? null;
|
|
41688
|
+
if (point4) onPointEnter(point4);
|
|
41689
|
+
else onPointLeave();
|
|
41690
|
+
},
|
|
41691
|
+
onMouseLeave: () => {
|
|
41692
|
+
hoveredRef.current = null;
|
|
41693
|
+
onPointLeave();
|
|
41694
|
+
},
|
|
41695
|
+
onPointerDown: (event) => {
|
|
41696
|
+
if (hitTest(event)?.commitSha) event.stopPropagation();
|
|
41697
|
+
},
|
|
41698
|
+
onClick: (event) => {
|
|
41699
|
+
const sha = hitTest(event)?.commitSha;
|
|
41700
|
+
if (sha) onInspectCommit(sha);
|
|
41701
|
+
}
|
|
41702
|
+
}
|
|
41703
|
+
);
|
|
41704
|
+
};
|
|
40886
41705
|
|
|
40887
41706
|
// source/gui/client/components/ScrubberLayout.tsx
|
|
40888
|
-
var
|
|
40889
|
-
var dotAnimation = (key, animate, leaving) => !animate ? void 0 : leaving ? dotExitAnimation(key) : dotAppearAnimation(key);
|
|
41707
|
+
var import_jsx_runtime31 = __toESM(require_jsx_runtime(), 1);
|
|
40890
41708
|
var ScrubberLayout = ({
|
|
40891
41709
|
collapsed,
|
|
40892
41710
|
onToggleCollapsed,
|
|
@@ -40895,7 +41713,7 @@ var ScrubberLayout = ({
|
|
|
40895
41713
|
chart
|
|
40896
41714
|
}) => {
|
|
40897
41715
|
const { axis, layoutMode, animate, windowKey, on } = chart;
|
|
40898
|
-
return /* @__PURE__ */ (0,
|
|
41716
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
40899
41717
|
Panel,
|
|
40900
41718
|
{
|
|
40901
41719
|
as: "div",
|
|
@@ -40912,8 +41730,8 @@ var ScrubberLayout = ({
|
|
|
40912
41730
|
overflow: "visible"
|
|
40913
41731
|
},
|
|
40914
41732
|
children: [
|
|
40915
|
-
/* @__PURE__ */ (0,
|
|
40916
|
-
/* @__PURE__ */ (0,
|
|
41733
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("style", { children: SCRUBBER_KEYFRAMES }),
|
|
41734
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
40917
41735
|
"div",
|
|
40918
41736
|
{
|
|
40919
41737
|
style: {
|
|
@@ -40922,7 +41740,7 @@ var ScrubberLayout = ({
|
|
|
40922
41740
|
gap: collapsed ? 0 : 8
|
|
40923
41741
|
},
|
|
40924
41742
|
children: [
|
|
40925
|
-
/* @__PURE__ */ (0,
|
|
41743
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
40926
41744
|
"div",
|
|
40927
41745
|
{
|
|
40928
41746
|
style: {
|
|
@@ -40934,7 +41752,7 @@ var ScrubberLayout = ({
|
|
|
40934
41752
|
minHeight: 22
|
|
40935
41753
|
},
|
|
40936
41754
|
children: [
|
|
40937
|
-
/* @__PURE__ */ (0,
|
|
41755
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
40938
41756
|
ScrubberHeader,
|
|
40939
41757
|
{
|
|
40940
41758
|
collapsed,
|
|
@@ -40942,7 +41760,7 @@ var ScrubberLayout = ({
|
|
|
40942
41760
|
scrubbingAsOf
|
|
40943
41761
|
}
|
|
40944
41762
|
),
|
|
40945
|
-
!collapsed && /* @__PURE__ */ (0,
|
|
41763
|
+
!collapsed && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(ScrubberControls, { ...controls })
|
|
40946
41764
|
]
|
|
40947
41765
|
}
|
|
40948
41766
|
),
|
|
@@ -40950,7 +41768,7 @@ var ScrubberLayout = ({
|
|
|
40950
41768
|
// spanning them and the gap between. Pointer handlers belong here
|
|
40951
41769
|
// rather than on either chart, so a drag or hover anywhere across
|
|
40952
41770
|
// the pair — the gap included — counts as one timeline.
|
|
40953
|
-
/* @__PURE__ */ (0,
|
|
41771
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
40954
41772
|
"div",
|
|
40955
41773
|
{
|
|
40956
41774
|
onPointerDown: on.onPointerDown,
|
|
@@ -40967,14 +41785,14 @@ var ScrubberLayout = ({
|
|
|
40967
41785
|
cursor: "pointer"
|
|
40968
41786
|
},
|
|
40969
41787
|
children: [
|
|
40970
|
-
chart.hoveredSegment && /* @__PURE__ */ (0,
|
|
41788
|
+
chart.hoveredSegment && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
40971
41789
|
SegmentHighlight,
|
|
40972
41790
|
{
|
|
40973
41791
|
segment: chart.hoveredSegment,
|
|
40974
41792
|
fractionForTime: axis.fractionForTime
|
|
40975
41793
|
}
|
|
40976
41794
|
),
|
|
40977
|
-
/* @__PURE__ */ (0,
|
|
41795
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
40978
41796
|
"div",
|
|
40979
41797
|
{
|
|
40980
41798
|
ref: chart.trackRef,
|
|
@@ -40989,15 +41807,15 @@ var ScrubberLayout = ({
|
|
|
40989
41807
|
alignItems: "center"
|
|
40990
41808
|
},
|
|
40991
41809
|
children: [
|
|
40992
|
-
/* @__PURE__ */ (0,
|
|
41810
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
40993
41811
|
TrackBaseline,
|
|
40994
41812
|
{
|
|
40995
|
-
color:
|
|
41813
|
+
color: chart.issueSeriesColor,
|
|
40996
41814
|
anchor: layoutMode === "even" ? "bottom" : "centre"
|
|
40997
41815
|
}
|
|
40998
41816
|
),
|
|
40999
|
-
layoutMode === "real" && /* @__PURE__ */ (0,
|
|
41000
|
-
chart.showIssues && layoutMode === "even" && /* @__PURE__ */ (0,
|
|
41817
|
+
layoutMode === "real" && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(HourAxisLabels, {}),
|
|
41818
|
+
chart.showIssues && layoutMode === "even" && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(SeriesLayer, { animate, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
41001
41819
|
VolumeBars,
|
|
41002
41820
|
{
|
|
41003
41821
|
bars: chart.issueBars,
|
|
@@ -41005,75 +41823,25 @@ var ScrubberLayout = ({
|
|
|
41005
41823
|
firstBar: chart.issueBarRange[0],
|
|
41006
41824
|
lastBar: chart.issueBarRange[1],
|
|
41007
41825
|
highlightedIndex: chart.hoveredBucketIndex,
|
|
41008
|
-
color:
|
|
41826
|
+
color: chart.issueSeriesColor,
|
|
41009
41827
|
direction: "up",
|
|
41010
41828
|
animate
|
|
41011
41829
|
}
|
|
41012
41830
|
) }, `issues-${windowKey}`),
|
|
41013
|
-
|
|
41014
|
-
|
|
41015
|
-
{
|
|
41016
|
-
animate: animate && !chart.issueScatter.leaving,
|
|
41017
|
-
children: chart.eventBuckets.map((bucket) => {
|
|
41018
|
-
const intensity = bucket.count / chart.maxEventCount;
|
|
41019
|
-
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
41020
|
-
ScatterDot,
|
|
41021
|
-
{
|
|
41022
|
-
fraction: axis.fractionForTime(bucket.t),
|
|
41023
|
-
hourFraction: hourFractionForTime(bucket.t),
|
|
41024
|
-
size: 3 + intensity * 6,
|
|
41025
|
-
color: GUI_THEME.accent,
|
|
41026
|
-
opacity: 0.3 + intensity * 0.5,
|
|
41027
|
-
zIndex: 2,
|
|
41028
|
-
title: `${bucket.count} change${bucket.count === 1 ? "" : "s"}, ${formatDateTime(new Date(bucket.t))}`,
|
|
41029
|
-
animation: dotAnimation(
|
|
41030
|
-
String(bucket.t),
|
|
41031
|
-
animate,
|
|
41032
|
-
chart.issueScatter.leaving
|
|
41033
|
-
),
|
|
41034
|
-
interactive: !chart.issueScatter.leaving,
|
|
41035
|
-
onMouseEnter: () => on.onIssueDotEnter(bucket),
|
|
41036
|
-
onMouseLeave: on.onIssueDotLeave
|
|
41037
|
-
},
|
|
41038
|
-
bucket.t
|
|
41039
|
-
);
|
|
41040
|
-
})
|
|
41041
|
-
},
|
|
41042
|
-
`issues-${windowKey}`
|
|
41043
|
-
),
|
|
41044
|
-
chart.commitScatter.mounted && layoutMode === "real" && chart.commits.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
41045
|
-
SeriesLayer,
|
|
41831
|
+
layoutMode === "real" && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
41832
|
+
ScatterCanvas,
|
|
41046
41833
|
{
|
|
41047
|
-
|
|
41048
|
-
|
|
41049
|
-
|
|
41050
|
-
|
|
41051
|
-
|
|
41052
|
-
|
|
41053
|
-
size: 4,
|
|
41054
|
-
color: GUI_THEME.green,
|
|
41055
|
-
opacity: chart.hoveredCommitSha === commit.sha ? 1 : 0.55,
|
|
41056
|
-
zIndex: 1,
|
|
41057
|
-
title: `${formatDateTime(new Date(commit.time))} \u2014 ${commit.subject} \u2014 ${commit.author} (${commit.linesChanged.toLocaleString()} lines)`,
|
|
41058
|
-
animation: dotAnimation(
|
|
41059
|
-
commit.sha,
|
|
41060
|
-
animate,
|
|
41061
|
-
chart.commitScatter.leaving
|
|
41062
|
-
),
|
|
41063
|
-
interactive: !chart.commitScatter.leaving,
|
|
41064
|
-
onClick: () => on.onInspectCommit(commit.sha),
|
|
41065
|
-
onMouseEnter: () => on.onCommitDotEnter(commit),
|
|
41066
|
-
onMouseLeave: on.onCommitDotLeave
|
|
41067
|
-
},
|
|
41068
|
-
commit.sha
|
|
41069
|
-
))
|
|
41070
|
-
},
|
|
41071
|
-
`commits-${windowKey}`
|
|
41834
|
+
layers: chart.scatterLayers,
|
|
41835
|
+
animate,
|
|
41836
|
+
onPointEnter: on.onScatterPointEnter,
|
|
41837
|
+
onPointLeave: on.onScatterPointLeave,
|
|
41838
|
+
onInspectCommit: on.onInspectCommit
|
|
41839
|
+
}
|
|
41072
41840
|
)
|
|
41073
41841
|
]
|
|
41074
41842
|
}
|
|
41075
41843
|
),
|
|
41076
|
-
chart.showCommits && layoutMode === "even" && chart.commits.length > 0 && /* @__PURE__ */ (0,
|
|
41844
|
+
chart.showCommits && layoutMode === "even" && chart.commits.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
41077
41845
|
"div",
|
|
41078
41846
|
{
|
|
41079
41847
|
onMouseEnter: on.onCommitTrackMouseEnter,
|
|
@@ -41086,8 +41854,8 @@ var ScrubberLayout = ({
|
|
|
41086
41854
|
animation: animate ? FADE_IN_ANIMATION : void 0
|
|
41087
41855
|
},
|
|
41088
41856
|
children: [
|
|
41089
|
-
/* @__PURE__ */ (0,
|
|
41090
|
-
/* @__PURE__ */ (0,
|
|
41857
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(TrackBaseline, { color: GUI_THEME.green, anchor: "top" }),
|
|
41858
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
41091
41859
|
VolumeBars,
|
|
41092
41860
|
{
|
|
41093
41861
|
bars: chart.commitBars,
|
|
@@ -41104,17 +41872,17 @@ var ScrubberLayout = ({
|
|
|
41104
41872
|
},
|
|
41105
41873
|
`commits-${windowKey}`
|
|
41106
41874
|
),
|
|
41107
|
-
/* @__PURE__ */ (0,
|
|
41108
|
-
chart.boardHint && /* @__PURE__ */ (0,
|
|
41875
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(ScrubberNeedle, { fraction: chart.thumbFraction }),
|
|
41876
|
+
chart.boardHint && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
41109
41877
|
ScrubberHoverHint,
|
|
41110
41878
|
{
|
|
41111
41879
|
...chart.boardHint,
|
|
41112
41880
|
segmentLabel: chart.hoveredSegment?.label,
|
|
41113
|
-
stripeColor:
|
|
41881
|
+
stripeColor: chart.issueSeriesColor,
|
|
41114
41882
|
trackWidthPx: chart.trackWidthPx
|
|
41115
41883
|
}
|
|
41116
41884
|
),
|
|
41117
|
-
chart.commitHint && /* @__PURE__ */ (0,
|
|
41885
|
+
chart.commitHint && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
41118
41886
|
ScrubberHoverHint,
|
|
41119
41887
|
{
|
|
41120
41888
|
...chart.commitHint,
|
|
@@ -41135,13 +41903,31 @@ var ScrubberLayout = ({
|
|
|
41135
41903
|
};
|
|
41136
41904
|
|
|
41137
41905
|
// source/gui/client/components/TimeScrubber.tsx
|
|
41138
|
-
var
|
|
41906
|
+
var import_jsx_runtime32 = __toESM(require_jsx_runtime(), 1);
|
|
41139
41907
|
var SCRUB_THROTTLE_MS = 120;
|
|
41908
|
+
var boardEventRow = (count) => `${count} board event${count === 1 ? "" : "s"}`;
|
|
41140
41909
|
var COLLAPSED_STORAGE_KEY = "epiq.timeScrubber.collapsed";
|
|
41141
41910
|
var SCOPE_STORAGE_KEY = "epiq.timeScrubber.scope";
|
|
41142
41911
|
var SHOW_ISSUES_STORAGE_KEY = "epiq.timeScrubber.showIssues";
|
|
41143
41912
|
var SHOW_COMMITS_STORAGE_KEY = "epiq.timeScrubber.showCommits";
|
|
41144
41913
|
var ALL_BOARDS_STORAGE_KEY = "epiq.timeScrubber.allBoards";
|
|
41914
|
+
var BOARD_VIEW_STORAGE_KEY = "epiq.timeScrubber.boardView";
|
|
41915
|
+
var HIDDEN_IDENTITIES_STORAGE_KEY = "epiq.timeScrubber.hiddenIdentities";
|
|
41916
|
+
var CATEGORIES_EXPANDED_STORAGE_KEY = "epiq.timeScrubber.categoriesExpanded";
|
|
41917
|
+
var IDENTITIES_EXPANDED_STORAGE_KEY = "epiq.timeScrubber.identitiesExpanded";
|
|
41918
|
+
var readStoredBoardView = () => {
|
|
41919
|
+
const stored = localStorage.getItem(BOARD_VIEW_STORAGE_KEY);
|
|
41920
|
+
return isBoardView(stored) ? stored : "all";
|
|
41921
|
+
};
|
|
41922
|
+
var readStoredHiddenIds = () => {
|
|
41923
|
+
try {
|
|
41924
|
+
const stored = localStorage.getItem(HIDDEN_IDENTITIES_STORAGE_KEY);
|
|
41925
|
+
const parsed = stored ? JSON.parse(stored) : [];
|
|
41926
|
+
return new Set(Array.isArray(parsed) ? parsed.map(String) : []);
|
|
41927
|
+
} catch {
|
|
41928
|
+
return /* @__PURE__ */ new Set();
|
|
41929
|
+
}
|
|
41930
|
+
};
|
|
41145
41931
|
var readStoredScope = () => {
|
|
41146
41932
|
const stored = localStorage.getItem(SCOPE_STORAGE_KEY);
|
|
41147
41933
|
return isScope(stored) ? stored : "all";
|
|
@@ -41149,21 +41935,23 @@ var readStoredScope = () => {
|
|
|
41149
41935
|
var TimeScrubber = ({
|
|
41150
41936
|
timeline,
|
|
41151
41937
|
commits,
|
|
41938
|
+
historyId,
|
|
41152
41939
|
timeTravel,
|
|
41153
41940
|
onScrub,
|
|
41154
41941
|
onReturnToLive,
|
|
41155
41942
|
onRequestHistory,
|
|
41156
41943
|
boardId,
|
|
41157
41944
|
connected,
|
|
41158
|
-
onInspectCommit
|
|
41945
|
+
onInspectCommit,
|
|
41946
|
+
onBoardFilterChange
|
|
41159
41947
|
}) => {
|
|
41160
41948
|
const animate = !usePrefersReducedMotion();
|
|
41161
|
-
const trackRef = (0,
|
|
41162
|
-
const lastDispatchRef = (0,
|
|
41163
|
-
const [layoutMode, setLayoutMode] = (0,
|
|
41164
|
-
const [scope, setScope] = (0,
|
|
41165
|
-
const [offset, setOffset] = (0,
|
|
41166
|
-
const [dragFraction, setDragFraction] = (0,
|
|
41949
|
+
const trackRef = (0, import_react15.useRef)(null);
|
|
41950
|
+
const lastDispatchRef = (0, import_react15.useRef)(0);
|
|
41951
|
+
const [layoutMode, setLayoutMode] = (0, import_react15.useState)("even");
|
|
41952
|
+
const [scope, setScope] = (0, import_react15.useState)(readStoredScope);
|
|
41953
|
+
const [offset, setOffset] = (0, import_react15.useState)(0);
|
|
41954
|
+
const [dragFraction, setDragFraction] = (0, import_react15.useState)(null);
|
|
41167
41955
|
const [collapsed, setCollapsed] = usePersistedFlag(
|
|
41168
41956
|
COLLAPSED_STORAGE_KEY,
|
|
41169
41957
|
false
|
|
@@ -41176,6 +41964,16 @@ var TimeScrubber = ({
|
|
|
41176
41964
|
SHOW_COMMITS_STORAGE_KEY,
|
|
41177
41965
|
true
|
|
41178
41966
|
);
|
|
41967
|
+
const [boardView, setBoardView] = (0, import_react15.useState)(readStoredBoardView);
|
|
41968
|
+
const [hiddenIdentityIds, setHiddenIdentityIds] = (0, import_react15.useState)(readStoredHiddenIds);
|
|
41969
|
+
const [categoriesExpanded, setCategoriesExpanded] = usePersistedFlag(
|
|
41970
|
+
CATEGORIES_EXPANDED_STORAGE_KEY,
|
|
41971
|
+
false
|
|
41972
|
+
);
|
|
41973
|
+
const [identitiesExpanded, setIdentitiesExpanded] = usePersistedFlag(
|
|
41974
|
+
IDENTITIES_EXPANDED_STORAGE_KEY,
|
|
41975
|
+
false
|
|
41976
|
+
);
|
|
41179
41977
|
const [allBoards, setAllBoards] = usePersistedFlag(
|
|
41180
41978
|
ALL_BOARDS_STORAGE_KEY,
|
|
41181
41979
|
false
|
|
@@ -41183,32 +41981,146 @@ var TimeScrubber = ({
|
|
|
41183
41981
|
const exitMs = layoutMode === "real" && animate ? DOT_EXIT_TOTAL_MS : 0;
|
|
41184
41982
|
const issueScatter = useExitTransition(showIssues, exitMs);
|
|
41185
41983
|
const commitScatter = useExitTransition(showCommits, exitMs);
|
|
41186
|
-
const [hoveredEvent, setHoveredEvent] = (0,
|
|
41187
|
-
const [pointerFraction, setPointerFraction] = (0,
|
|
41188
|
-
const [hoveredCommit, setHoveredCommit] = (0,
|
|
41189
|
-
const [hoveredBucketIndex, setHoveredBucketIndex] = (0,
|
|
41984
|
+
const [hoveredEvent, setHoveredEvent] = (0, import_react15.useState)(null);
|
|
41985
|
+
const [pointerFraction, setPointerFraction] = (0, import_react15.useState)(null);
|
|
41986
|
+
const [hoveredCommit, setHoveredCommit] = (0, import_react15.useState)(null);
|
|
41987
|
+
const [hoveredBucketIndex, setHoveredBucketIndex] = (0, import_react15.useState)(
|
|
41190
41988
|
null
|
|
41191
41989
|
);
|
|
41192
|
-
const [hoveredCommitBucketIndex, setHoveredCommitBucketIndex] = (0,
|
|
41990
|
+
const [hoveredCommitBucketIndex, setHoveredCommitBucketIndex] = (0, import_react15.useState)(null);
|
|
41193
41991
|
const periodRange = getPeriodRange(scope, offset);
|
|
41194
|
-
(0,
|
|
41992
|
+
(0, import_react15.useEffect)(() => {
|
|
41195
41993
|
if (!connected) return;
|
|
41196
41994
|
onRequestHistory(periodRange?.start, periodRange?.end, allBoards);
|
|
41197
41995
|
}, [scope, offset, boardId, allBoards, connected]);
|
|
41198
41996
|
const changeScope = (nextScope) => {
|
|
41997
|
+
armEntrance();
|
|
41199
41998
|
setScope(nextScope);
|
|
41200
41999
|
setOffset(0);
|
|
41201
42000
|
localStorage.setItem(SCOPE_STORAGE_KEY, nextScope);
|
|
41202
42001
|
};
|
|
41203
|
-
const
|
|
41204
|
-
|
|
41205
|
-
|
|
41206
|
-
|
|
41207
|
-
const
|
|
41208
|
-
|
|
41209
|
-
|
|
41210
|
-
|
|
42002
|
+
const changeOffset = (nextOffset) => {
|
|
42003
|
+
armEntrance();
|
|
42004
|
+
setOffset(nextOffset);
|
|
42005
|
+
};
|
|
42006
|
+
const changeBoardView = (next) => {
|
|
42007
|
+
setBoardView(next);
|
|
42008
|
+
localStorage.setItem(BOARD_VIEW_STORAGE_KEY, next);
|
|
42009
|
+
};
|
|
42010
|
+
const isolateIdentity = (id) => {
|
|
42011
|
+
const others = identities.filter((identity) => identity.id !== id).map((identity) => identity.id);
|
|
42012
|
+
setHiddenIdentityIds((previous3) => {
|
|
42013
|
+
const isolated = !previous3.has(id) && others.length === previous3.size && others.every((other) => previous3.has(other));
|
|
42014
|
+
const hidden = isolated ? /* @__PURE__ */ new Set() : new Set(others);
|
|
42015
|
+
localStorage.setItem(
|
|
42016
|
+
HIDDEN_IDENTITIES_STORAGE_KEY,
|
|
42017
|
+
JSON.stringify([...hidden])
|
|
42018
|
+
);
|
|
42019
|
+
return hidden;
|
|
42020
|
+
});
|
|
42021
|
+
};
|
|
42022
|
+
const toggleIdentity = (id, next) => {
|
|
42023
|
+
setHiddenIdentityIds((previous3) => {
|
|
42024
|
+
const hidden = new Set(previous3);
|
|
42025
|
+
if (next) {
|
|
42026
|
+
hidden.delete(id);
|
|
42027
|
+
} else {
|
|
42028
|
+
hidden.add(id);
|
|
42029
|
+
}
|
|
42030
|
+
localStorage.setItem(
|
|
42031
|
+
HIDDEN_IDENTITIES_STORAGE_KEY,
|
|
42032
|
+
JSON.stringify([...hidden])
|
|
42033
|
+
);
|
|
42034
|
+
return hidden;
|
|
42035
|
+
});
|
|
42036
|
+
};
|
|
42037
|
+
const changeAllBoards = (next) => {
|
|
42038
|
+
armEntrance();
|
|
42039
|
+
setAllBoards(next);
|
|
42040
|
+
};
|
|
42041
|
+
const steadyBoardId = (0, import_react15.useRef)(boardId);
|
|
42042
|
+
if (boardId !== null) steadyBoardId.current = boardId;
|
|
42043
|
+
const requestKey = (0, import_react15.useMemo)(
|
|
42044
|
+
() => JSON.stringify([scope, offset, steadyBoardId.current, allBoards]),
|
|
42045
|
+
[scope, offset, steadyBoardId.current, allBoards]
|
|
42046
|
+
);
|
|
42047
|
+
const filterKey = (0, import_react15.useMemo)(
|
|
42048
|
+
() => JSON.stringify([boardView, [...hiddenIdentityIds].sort()]),
|
|
42049
|
+
[boardView, hiddenIdentityIds]
|
|
42050
|
+
);
|
|
42051
|
+
const shownRef = (0, import_react15.useRef)({ timeline, commits });
|
|
42052
|
+
const heldKey = (0, import_react15.useRef)(null);
|
|
42053
|
+
const heldHistoryId = (0, import_react15.useRef)(null);
|
|
42054
|
+
const awaiting = (0, import_react15.useRef)(true);
|
|
42055
|
+
if (heldKey.current !== requestKey) {
|
|
42056
|
+
heldKey.current = requestKey;
|
|
42057
|
+
awaiting.current = true;
|
|
42058
|
+
}
|
|
42059
|
+
if (awaiting.current && heldHistoryId.current !== historyId) {
|
|
42060
|
+
heldHistoryId.current = historyId;
|
|
42061
|
+
shownRef.current = { timeline, commits };
|
|
42062
|
+
awaiting.current = false;
|
|
42063
|
+
}
|
|
42064
|
+
const shown = shownRef.current;
|
|
42065
|
+
const axis = (0, import_react15.useMemo)(() => buildAxis(shown.timeline, shown.commits), [shown]);
|
|
42066
|
+
const categoriesFiltered = (timeline?.events.length ?? 0) > 0;
|
|
42067
|
+
const identities = (0, import_react15.useMemo)(
|
|
42068
|
+
() => listIdentities(shown.timeline, boardView),
|
|
42069
|
+
[shown, boardView]
|
|
42070
|
+
);
|
|
42071
|
+
const soleIdentity = (0, import_react15.useMemo)(
|
|
42072
|
+
() => soleVisibleIdentity(identities, hiddenIdentityIds),
|
|
42073
|
+
[identities, hiddenIdentityIds]
|
|
42074
|
+
);
|
|
42075
|
+
const issueCounts = bucketIssueCounts(
|
|
42076
|
+
axis,
|
|
42077
|
+
shown.timeline,
|
|
42078
|
+
boardView,
|
|
42079
|
+
hiddenIdentityIds
|
|
42080
|
+
);
|
|
42081
|
+
const commitStats = bucketCommitStats(axis, shown.commits);
|
|
42082
|
+
const liveEventDots = (0, import_react15.useMemo)(
|
|
42083
|
+
() => buildEventDots(shown.timeline, boardView, hiddenIdentityIds),
|
|
42084
|
+
[shown, boardView, hiddenIdentityIds]
|
|
42085
|
+
);
|
|
42086
|
+
const dragging = dragFraction !== null;
|
|
42087
|
+
const commitPoints = (0, import_react15.useMemo)(
|
|
42088
|
+
() => shown.commits.map((commit) => ({
|
|
42089
|
+
key: commit.sha,
|
|
42090
|
+
t: commit.time,
|
|
42091
|
+
fraction: axis.fractionForTime(commit.time),
|
|
42092
|
+
hourFraction: hourFractionForTime(commit.time),
|
|
42093
|
+
radius: 2,
|
|
42094
|
+
color: GUI_THEME.green,
|
|
42095
|
+
opacity: 0.55,
|
|
42096
|
+
// The hint labels the moment itself, so this is the rest of it.
|
|
42097
|
+
title: `${commit.subject} \u2014 ${commit.author} (${commit.linesChanged.toLocaleString()} lines)`,
|
|
42098
|
+
commitSha: commit.sha
|
|
42099
|
+
})),
|
|
42100
|
+
[shown.commits, axis]
|
|
41211
42101
|
);
|
|
42102
|
+
const issuePoints = (0, import_react15.useMemo)(
|
|
42103
|
+
() => liveEventDots.map((dot) => ({
|
|
42104
|
+
key: dot.key,
|
|
42105
|
+
t: dot.t,
|
|
42106
|
+
fraction: axis.fractionForTime(dot.t),
|
|
42107
|
+
hourFraction: hourFractionForTime(dot.t),
|
|
42108
|
+
radius: dot.size / 2,
|
|
42109
|
+
color: dot.color,
|
|
42110
|
+
opacity: dot.opacity,
|
|
42111
|
+
title: dotDetail(dot),
|
|
42112
|
+
commitSha: null
|
|
42113
|
+
})),
|
|
42114
|
+
[liveEventDots, axis]
|
|
42115
|
+
);
|
|
42116
|
+
const boardFilter = (0, import_react15.useMemo)(
|
|
42117
|
+
() => buildBoardFilter(boardView, identities, hiddenIdentityIds),
|
|
42118
|
+
[boardView, identities, hiddenIdentityIds]
|
|
42119
|
+
);
|
|
42120
|
+
(0, import_react15.useEffect)(() => {
|
|
42121
|
+
onBoardFilterChange(boardFilter);
|
|
42122
|
+
}, [boardFilter]);
|
|
42123
|
+
const maxIssueBucketCount = maxOf(issueCounts, 1);
|
|
41212
42124
|
const maxCommitCount = maxOf(
|
|
41213
42125
|
Array.from(commitStats.values(), (stats) => stats.count),
|
|
41214
42126
|
1
|
|
@@ -41220,11 +42132,47 @@ var TimeScrubber = ({
|
|
|
41220
42132
|
index: index2,
|
|
41221
42133
|
intensity: stats.count / maxCommitCount
|
|
41222
42134
|
}));
|
|
41223
|
-
const [
|
|
41224
|
-
const
|
|
41225
|
-
(0,
|
|
41226
|
-
|
|
41227
|
-
|
|
42135
|
+
const [entrance, setEntrance] = (0, import_react15.useState)(0);
|
|
42136
|
+
const armed = (0, import_react15.useRef)(true);
|
|
42137
|
+
const seenHistoryId = (0, import_react15.useRef)(historyId);
|
|
42138
|
+
const armEntrance = () => {
|
|
42139
|
+
armed.current = true;
|
|
42140
|
+
};
|
|
42141
|
+
const armedBoardId = (0, import_react15.useRef)(boardId);
|
|
42142
|
+
(0, import_react15.useEffect)(() => {
|
|
42143
|
+
if (boardId === null || boardId === armedBoardId.current) return;
|
|
42144
|
+
armedBoardId.current = boardId;
|
|
42145
|
+
armEntrance();
|
|
42146
|
+
}, [boardId]);
|
|
42147
|
+
(0, import_react15.useEffect)(() => {
|
|
42148
|
+
if (seenHistoryId.current === historyId) return;
|
|
42149
|
+
seenHistoryId.current = historyId;
|
|
42150
|
+
if (!armed.current) return;
|
|
42151
|
+
armed.current = false;
|
|
42152
|
+
setEntrance((generation) => generation + 1);
|
|
42153
|
+
}, [historyId]);
|
|
42154
|
+
const windowKey = `${layoutMode}-${entrance}-${filterKey}`;
|
|
42155
|
+
const scatterLayers = (0, import_react15.useMemo)(
|
|
42156
|
+
() => [
|
|
42157
|
+
...commitScatter.mounted ? [
|
|
42158
|
+
{
|
|
42159
|
+
id: "commits",
|
|
42160
|
+
points: commitPoints,
|
|
42161
|
+
generation: windowKey,
|
|
42162
|
+
leaving: commitScatter.leaving
|
|
42163
|
+
}
|
|
42164
|
+
] : [],
|
|
42165
|
+
...issueScatter.mounted ? [
|
|
42166
|
+
{
|
|
42167
|
+
id: "issues",
|
|
42168
|
+
points: issuePoints,
|
|
42169
|
+
generation: windowKey,
|
|
42170
|
+
leaving: issueScatter.leaving
|
|
42171
|
+
}
|
|
42172
|
+
] : []
|
|
42173
|
+
],
|
|
42174
|
+
[commitPoints, issuePoints, commitScatter, issueScatter, windowKey]
|
|
42175
|
+
);
|
|
41228
42176
|
const confirmedFraction = timeTravel.mode === "scrub" && timeTravel.asOfTime !== null ? axis.fractionForTime(timeTravel.asOfTime) : 1;
|
|
41229
42177
|
const fractionFromClientX = (clientX) => {
|
|
41230
42178
|
const track = trackRef.current;
|
|
@@ -41254,7 +42202,30 @@ var TimeScrubber = ({
|
|
|
41254
42202
|
);
|
|
41255
42203
|
const bucketTimeAt = (index2) => index2 !== null && index2 < axis.bucketCount ? axis.bucketTimeAt(index2) : void 0;
|
|
41256
42204
|
const centreFraction = (index2) => (index2 + 0.5) / axis.bucketCount;
|
|
41257
|
-
const
|
|
42205
|
+
const onScatterPointEnter = (0, import_react15.useCallback)(
|
|
42206
|
+
(point4) => {
|
|
42207
|
+
if (point4.commitSha) {
|
|
42208
|
+
const commit = shown.commits.find((c) => c.sha === point4.commitSha);
|
|
42209
|
+
if (commit) {
|
|
42210
|
+
setHoveredCommit({ commit, fraction: point4.fraction });
|
|
42211
|
+
setHoveredEvent(null);
|
|
42212
|
+
}
|
|
42213
|
+
return;
|
|
42214
|
+
}
|
|
42215
|
+
setHoveredCommit(null);
|
|
42216
|
+
setHoveredEvent({
|
|
42217
|
+
label: formatDateTime(new Date(point4.t)),
|
|
42218
|
+
detail: point4.title,
|
|
42219
|
+
t: point4.t,
|
|
42220
|
+
fraction: point4.fraction
|
|
42221
|
+
});
|
|
42222
|
+
},
|
|
42223
|
+
[shown.commits]
|
|
42224
|
+
);
|
|
42225
|
+
const onScatterPointLeave = (0, import_react15.useCallback)(() => {
|
|
42226
|
+
setHoveredEvent(null);
|
|
42227
|
+
setHoveredCommit(null);
|
|
42228
|
+
}, []);
|
|
41258
42229
|
const hoveredBucketTime = bucketTimeAt(hoveredBucketIndex);
|
|
41259
42230
|
const hoveredBucketCount = hoveredBucketIndex !== null ? issueCounts[hoveredBucketIndex] : void 0;
|
|
41260
42231
|
const boardHint = layoutMode === "even" ? hoveredBucketTime !== void 0 && hoveredBucketCount !== void 0 ? {
|
|
@@ -41267,7 +42238,7 @@ var TimeScrubber = ({
|
|
|
41267
42238
|
empty: hoveredBucketCount === 0
|
|
41268
42239
|
} : null : hoveredEvent ? {
|
|
41269
42240
|
label: hoveredEvent.label,
|
|
41270
|
-
rows: [
|
|
42241
|
+
rows: [hoveredEvent.detail],
|
|
41271
42242
|
fraction: hoveredEvent.fraction
|
|
41272
42243
|
} : null;
|
|
41273
42244
|
const hoveredCommitStats = hoveredCommitBucketIndex !== null ? commitStats.get(hoveredCommitBucketIndex) : void 0;
|
|
@@ -41296,7 +42267,7 @@ var TimeScrubber = ({
|
|
|
41296
42267
|
hoveredEvent?.t ?? hoveredCommit?.commit.time ?? (pointerFraction !== null ? axis.fractionToTime(pointerFraction) : void 0)
|
|
41297
42268
|
)) ?? null;
|
|
41298
42269
|
const segmentUnit = chooseSegmentUnit(axis.span);
|
|
41299
|
-
return /* @__PURE__ */ (0,
|
|
42270
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
41300
42271
|
ScrubberLayout,
|
|
41301
42272
|
{
|
|
41302
42273
|
collapsed,
|
|
@@ -41313,11 +42284,22 @@ var TimeScrubber = ({
|
|
|
41313
42284
|
isScrubbing: timeTravel.mode === "scrub",
|
|
41314
42285
|
nowLabel: scope === "all" || offset === 0 ? "Now" : formatDateTime(new Date(axis.latest)),
|
|
41315
42286
|
onChangeScope: changeScope,
|
|
41316
|
-
onChangeOffset:
|
|
42287
|
+
onChangeOffset: changeOffset,
|
|
41317
42288
|
onChangeLayoutMode: setLayoutMode,
|
|
41318
42289
|
onChangeShowIssues: setShowIssues,
|
|
41319
42290
|
onChangeShowCommits: setShowCommits,
|
|
41320
|
-
onChangeAllBoards:
|
|
42291
|
+
onChangeAllBoards: changeAllBoards,
|
|
42292
|
+
boardView,
|
|
42293
|
+
identities,
|
|
42294
|
+
hiddenIdentityIds,
|
|
42295
|
+
categoriesExpanded,
|
|
42296
|
+
identitiesExpanded,
|
|
42297
|
+
categoriesFiltered,
|
|
42298
|
+
onChangeBoardView: changeBoardView,
|
|
42299
|
+
onToggleIdentity: toggleIdentity,
|
|
42300
|
+
onOnlyIdentity: isolateIdentity,
|
|
42301
|
+
onToggleCategoriesExpanded: () => setCategoriesExpanded(!categoriesExpanded),
|
|
42302
|
+
onSetIdentitiesExpanded: setIdentitiesExpanded,
|
|
41321
42303
|
onReturnToLive
|
|
41322
42304
|
},
|
|
41323
42305
|
chart: {
|
|
@@ -41325,7 +42307,7 @@ var TimeScrubber = ({
|
|
|
41325
42307
|
axis,
|
|
41326
42308
|
layoutMode,
|
|
41327
42309
|
animate,
|
|
41328
|
-
windowKey
|
|
42310
|
+
windowKey,
|
|
41329
42311
|
showIssues,
|
|
41330
42312
|
showCommits,
|
|
41331
42313
|
issueScatter,
|
|
@@ -41334,9 +42316,12 @@ var TimeScrubber = ({
|
|
|
41334
42316
|
issueBarRange: populatedRange(issueBars),
|
|
41335
42317
|
commitBars,
|
|
41336
42318
|
commitBarRange: populatedRange(commitBars),
|
|
41337
|
-
|
|
41338
|
-
|
|
41339
|
-
|
|
42319
|
+
scatterLayers,
|
|
42320
|
+
issueSeriesColor: soleIdentity?.color ?? boardViewColor(boardView),
|
|
42321
|
+
dragging,
|
|
42322
|
+
// Exits still need their animation, so this only silences a series
|
|
42323
|
+
// that has finished arriving.
|
|
42324
|
+
commits: shown.commits,
|
|
41340
42325
|
hoveredCommitSha: hoveredCommit?.commit.sha ?? null,
|
|
41341
42326
|
hoveredBucketIndex,
|
|
41342
42327
|
hoveredCommitBucketIndex,
|
|
@@ -41376,18 +42361,8 @@ var TimeScrubber = ({
|
|
|
41376
42361
|
setHoveredCommitBucketIndex(bucketIndexFromEvent(event));
|
|
41377
42362
|
},
|
|
41378
42363
|
onCommitTrackMouseLeave: () => setHoveredCommitBucketIndex(null),
|
|
41379
|
-
|
|
41380
|
-
|
|
41381
|
-
count: bucket.count,
|
|
41382
|
-
t: bucket.t,
|
|
41383
|
-
fraction: axis.fractionForTime(bucket.t)
|
|
41384
|
-
}),
|
|
41385
|
-
onIssueDotLeave: () => setHoveredEvent(null),
|
|
41386
|
-
onCommitDotEnter: (commit) => setHoveredCommit({
|
|
41387
|
-
commit,
|
|
41388
|
-
fraction: axis.fractionForTime(commit.time)
|
|
41389
|
-
}),
|
|
41390
|
-
onCommitDotLeave: () => setHoveredCommit(null),
|
|
42364
|
+
onScatterPointEnter,
|
|
42365
|
+
onScatterPointLeave,
|
|
41391
42366
|
onInspectCommit
|
|
41392
42367
|
}
|
|
41393
42368
|
}
|
|
@@ -41395,34 +42370,6 @@ var TimeScrubber = ({
|
|
|
41395
42370
|
);
|
|
41396
42371
|
};
|
|
41397
42372
|
|
|
41398
|
-
// source/gui/client/lib/socket-send.ts
|
|
41399
|
-
var pending = /* @__PURE__ */ new WeakMap();
|
|
41400
|
-
var sendSocketJson = (socket, data2) => {
|
|
41401
|
-
if (!socket) return;
|
|
41402
|
-
const message = JSON.stringify(data2);
|
|
41403
|
-
if (socket.readyState === WebSocket.OPEN) {
|
|
41404
|
-
socket.send(message);
|
|
41405
|
-
return;
|
|
41406
|
-
}
|
|
41407
|
-
if (socket.readyState !== WebSocket.CONNECTING) return;
|
|
41408
|
-
const queued = pending.get(socket);
|
|
41409
|
-
if (queued) {
|
|
41410
|
-
queued.push(message);
|
|
41411
|
-
return;
|
|
41412
|
-
}
|
|
41413
|
-
pending.set(socket, [message]);
|
|
41414
|
-
socket.addEventListener(
|
|
41415
|
-
"open",
|
|
41416
|
-
() => {
|
|
41417
|
-
for (const queuedMessage of pending.get(socket) ?? []) {
|
|
41418
|
-
socket.send(queuedMessage);
|
|
41419
|
-
}
|
|
41420
|
-
pending.delete(socket);
|
|
41421
|
-
},
|
|
41422
|
-
{ once: true }
|
|
41423
|
-
);
|
|
41424
|
-
};
|
|
41425
|
-
|
|
41426
42373
|
// source/gui/client/lib/gui-move-issue.tsx
|
|
41427
42374
|
var toMovePosition = (targetIssues, targetIndex) => {
|
|
41428
42375
|
if (targetIssues.length === 0) return { at: "start" };
|
|
@@ -41467,47 +42414,36 @@ var findMove = (state, issueId, parentId, targetIndex) => {
|
|
|
41467
42414
|
targetParentId: targetSwimlane.id
|
|
41468
42415
|
};
|
|
41469
42416
|
};
|
|
41470
|
-
var
|
|
41471
|
-
|
|
41472
|
-
|
|
41473
|
-
|
|
41474
|
-
|
|
41475
|
-
|
|
41476
|
-
|
|
41477
|
-
|
|
41478
|
-
|
|
41479
|
-
|
|
41480
|
-
|
|
41481
|
-
|
|
41482
|
-
|
|
41483
|
-
|
|
41484
|
-
|
|
41485
|
-
|
|
41486
|
-
|
|
41487
|
-
|
|
41488
|
-
|
|
41489
|
-
|
|
41490
|
-
|
|
41491
|
-
|
|
41492
|
-
|
|
41493
|
-
|
|
41494
|
-
|
|
41495
|
-
|
|
41496
|
-
|
|
41497
|
-
|
|
41498
|
-
|
|
41499
|
-
|
|
41500
|
-
};
|
|
41501
|
-
});
|
|
41502
|
-
if (!position3) return;
|
|
41503
|
-
sendSocketJson(socketRef.current, {
|
|
41504
|
-
type: "issues:move",
|
|
41505
|
-
payload: {
|
|
41506
|
-
issueId,
|
|
41507
|
-
parentId,
|
|
41508
|
-
position: position3
|
|
41509
|
-
}
|
|
41510
|
-
});
|
|
42417
|
+
var applyMove = (state, issueId, parentId, targetIndex, movedIssue) => ({
|
|
42418
|
+
...state,
|
|
42419
|
+
boards: state.boards.map((board) => ({
|
|
42420
|
+
...board,
|
|
42421
|
+
swimlanes: board.swimlanes.map((swimlane) => {
|
|
42422
|
+
const issuesWithoutMoved = swimlane.issues.filter(
|
|
42423
|
+
(issue) => issue.id !== issueId
|
|
42424
|
+
);
|
|
42425
|
+
if (swimlane.id !== parentId) {
|
|
42426
|
+
return { ...swimlane, issues: issuesWithoutMoved };
|
|
42427
|
+
}
|
|
42428
|
+
const nextIssues = [...issuesWithoutMoved];
|
|
42429
|
+
const index2 = targetIndex === "end" ? nextIssues.length : Math.max(0, Math.min(targetIndex, nextIssues.length));
|
|
42430
|
+
nextIssues.splice(index2, 0, movedIssue);
|
|
42431
|
+
return { ...swimlane, issues: nextIssues };
|
|
42432
|
+
})
|
|
42433
|
+
}))
|
|
42434
|
+
});
|
|
42435
|
+
var moveIssue = (state, setState, send) => (issueIds, parentId, targetIndex) => {
|
|
42436
|
+
if (!state) return;
|
|
42437
|
+
let running = state;
|
|
42438
|
+
for (const [offset, issueId] of issueIds.entries()) {
|
|
42439
|
+
const index2 = targetIndex === "end" ? "end" : targetIndex + offset;
|
|
42440
|
+
const move = findMove(running, issueId, parentId, index2);
|
|
42441
|
+
if (!move) continue;
|
|
42442
|
+
running = applyMove(running, issueId, parentId, index2, move.movedIssue);
|
|
42443
|
+
send("issues:move", { issueId, parentId, position: move.position });
|
|
42444
|
+
}
|
|
42445
|
+
const next = running;
|
|
42446
|
+
setState((current) => current ? next : current);
|
|
41511
42447
|
};
|
|
41512
42448
|
|
|
41513
42449
|
// source/lib/utils/node-ref.ts
|
|
@@ -41517,8 +42453,8 @@ var nodeRef = (id) => id.slice(-NODE_REF_LENGTH).toUpperCase();
|
|
|
41517
42453
|
// source/gui/client/lib/gui-state-helper.tsx
|
|
41518
42454
|
var getResultValue = (payload) => {
|
|
41519
42455
|
if (!payload) return void 0;
|
|
41520
|
-
if (typeof payload === "object" && payload !== null && "value" in payload
|
|
41521
|
-
return payload.value;
|
|
42456
|
+
if (typeof payload === "object" && payload !== null && "value" in payload) {
|
|
42457
|
+
return payload.value ?? void 0;
|
|
41522
42458
|
}
|
|
41523
42459
|
if (typeof payload === "object" && payload !== null && "content" in payload && payload.content?.[0]?.text) {
|
|
41524
42460
|
return JSON.parse(payload.content[0].text).value;
|
|
@@ -41552,6 +42488,34 @@ var updateIssueInGuiState = (state, issueId, updateIssue) => ({
|
|
|
41552
42488
|
}))
|
|
41553
42489
|
});
|
|
41554
42490
|
|
|
42491
|
+
// source/gui/client/lib/socket-send.ts
|
|
42492
|
+
var pending = /* @__PURE__ */ new WeakMap();
|
|
42493
|
+
var sendSocketJson = (socket, data2) => {
|
|
42494
|
+
if (!socket) return;
|
|
42495
|
+
const message = JSON.stringify(data2);
|
|
42496
|
+
if (socket.readyState === WebSocket.OPEN) {
|
|
42497
|
+
socket.send(message);
|
|
42498
|
+
return;
|
|
42499
|
+
}
|
|
42500
|
+
if (socket.readyState !== WebSocket.CONNECTING) return;
|
|
42501
|
+
const queued = pending.get(socket);
|
|
42502
|
+
if (queued) {
|
|
42503
|
+
queued.push(message);
|
|
42504
|
+
return;
|
|
42505
|
+
}
|
|
42506
|
+
pending.set(socket, [message]);
|
|
42507
|
+
socket.addEventListener(
|
|
42508
|
+
"open",
|
|
42509
|
+
() => {
|
|
42510
|
+
for (const queuedMessage of pending.get(socket) ?? []) {
|
|
42511
|
+
socket.send(queuedMessage);
|
|
42512
|
+
}
|
|
42513
|
+
pending.delete(socket);
|
|
42514
|
+
},
|
|
42515
|
+
{ once: true }
|
|
42516
|
+
);
|
|
42517
|
+
};
|
|
42518
|
+
|
|
41555
42519
|
// source/gui/client/lib/history-buffer.ts
|
|
41556
42520
|
var createHistoryBuffer = (publish) => {
|
|
41557
42521
|
let lastRequestId = 0;
|
|
@@ -41571,7 +42535,48 @@ var createHistoryBuffer = (publish) => {
|
|
|
41571
42535
|
const { timeline, commits } = pending2;
|
|
41572
42536
|
if (!timeline || !commits) return;
|
|
41573
42537
|
pending2 = {};
|
|
41574
|
-
publish({ timeline, commits });
|
|
42538
|
+
publish({ requestId, timeline, commits });
|
|
42539
|
+
}
|
|
42540
|
+
};
|
|
42541
|
+
};
|
|
42542
|
+
|
|
42543
|
+
// source/gui/client/lib/gui-mutations.ts
|
|
42544
|
+
var MUTATING_MESSAGE_TYPES = /* @__PURE__ */ new Set([
|
|
42545
|
+
"sync",
|
|
42546
|
+
"issues:create",
|
|
42547
|
+
"issues:move",
|
|
42548
|
+
"issue:close",
|
|
42549
|
+
"issue:reopen",
|
|
42550
|
+
"issue:edit:title",
|
|
42551
|
+
"issue:edit:description",
|
|
42552
|
+
"issue:tag:add",
|
|
42553
|
+
"issue:tag:remove",
|
|
42554
|
+
"contributor:remove",
|
|
42555
|
+
"issue:assignee:add",
|
|
42556
|
+
"issue:assignee:remove",
|
|
42557
|
+
"issue:comment:add",
|
|
42558
|
+
"issue:comment:delete"
|
|
42559
|
+
]);
|
|
42560
|
+
|
|
42561
|
+
// source/gui/client/lib/mutation-gate.ts
|
|
42562
|
+
var createMutationGate = () => {
|
|
42563
|
+
let pending2 = 0;
|
|
42564
|
+
return {
|
|
42565
|
+
sent(type) {
|
|
42566
|
+
if (MUTATING_MESSAGE_TYPES.has(type)) pending2 += 1;
|
|
42567
|
+
},
|
|
42568
|
+
/** `error` counts too: the handler paths that fail early send no result. */
|
|
42569
|
+
received(type) {
|
|
42570
|
+
if (type === "error" || type?.endsWith(":result")) {
|
|
42571
|
+
pending2 = Math.max(0, pending2 - 1);
|
|
42572
|
+
}
|
|
42573
|
+
},
|
|
42574
|
+
/** A reply owed on a closed socket never arrives. */
|
|
42575
|
+
reset() {
|
|
42576
|
+
pending2 = 0;
|
|
42577
|
+
},
|
|
42578
|
+
holdsState() {
|
|
42579
|
+
return pending2 > 0;
|
|
41575
42580
|
}
|
|
41576
42581
|
};
|
|
41577
42582
|
};
|
|
@@ -41641,8 +42646,9 @@ var blobToBase64 = (blob) => new Promise((resolve, reject) => {
|
|
|
41641
42646
|
});
|
|
41642
42647
|
|
|
41643
42648
|
// source/gui/client/App.tsx
|
|
41644
|
-
var
|
|
41645
|
-
var
|
|
42649
|
+
var import_jsx_runtime33 = __toESM(require_jsx_runtime(), 1);
|
|
42650
|
+
var EMPTY_COMMENTS = {};
|
|
42651
|
+
var DropIndicator = () => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
41646
42652
|
"div",
|
|
41647
42653
|
{
|
|
41648
42654
|
style: {
|
|
@@ -41655,38 +42661,44 @@ var DropIndicator = () => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
|
41655
42661
|
}
|
|
41656
42662
|
);
|
|
41657
42663
|
var App = () => {
|
|
41658
|
-
const { boardId
|
|
42664
|
+
const { boardId } = useParams();
|
|
42665
|
+
const issueMatch = useMatch("/board/:boardId/issue/:issueId");
|
|
42666
|
+
const legacyIssueMatch = useMatch("/board/:boardId/:issueId");
|
|
42667
|
+
const issueId = issueMatch?.params.issueId ?? legacyIssueMatch?.params.issueId;
|
|
41659
42668
|
const [searchParams, setSearchParams] = useSearchParams();
|
|
41660
|
-
const [connected, setConnected] = (0,
|
|
41661
|
-
const [syncStatus, setSyncStatus] = (0,
|
|
42669
|
+
const [connected, setConnected] = (0, import_react16.useState)(false);
|
|
42670
|
+
const [syncStatus, setSyncStatus] = (0, import_react16.useState)({
|
|
41662
42671
|
status: "synced",
|
|
41663
42672
|
msg: "idle"
|
|
41664
42673
|
});
|
|
41665
|
-
const [state, setState] = (0,
|
|
41666
|
-
const [contributors, setContributors] = (0,
|
|
41667
|
-
const [history, setHistory] = (0,
|
|
41668
|
-
const [historyBuffer] = (0,
|
|
41669
|
-
const [commitInspectError, setCommitInspectError] = (0,
|
|
42674
|
+
const [state, setState] = (0, import_react16.useState)(null);
|
|
42675
|
+
const [contributors, setContributors] = (0, import_react16.useState)([]);
|
|
42676
|
+
const [history, setHistory] = (0, import_react16.useState)({ requestId: 0, timeline: null, commits: [] });
|
|
42677
|
+
const [historyBuffer] = (0, import_react16.useState)(() => createHistoryBuffer(setHistory));
|
|
42678
|
+
const [commitInspectError, setCommitInspectError] = (0, import_react16.useState)(
|
|
41670
42679
|
null
|
|
41671
42680
|
);
|
|
41672
|
-
const [removeError, setRemoveError] = (0,
|
|
41673
|
-
const [
|
|
42681
|
+
const [removeError, setRemoveError] = (0, import_react16.useState)(null);
|
|
42682
|
+
const [actionError, setActionError] = (0, import_react16.useState)(null);
|
|
42683
|
+
const [dragOverSwimlaneId, setDragOverSwimlaneId] = (0, import_react16.useState)(
|
|
41674
42684
|
null
|
|
41675
42685
|
);
|
|
41676
|
-
const [dropTarget, setDropTarget] = (0,
|
|
41677
|
-
const [
|
|
41678
|
-
const [
|
|
41679
|
-
const
|
|
41680
|
-
const
|
|
42686
|
+
const [dropTarget, setDropTarget] = (0, import_react16.useState)(null);
|
|
42687
|
+
const [pickedIssueIds, setPickedIssueIds] = (0, import_react16.useState)([]);
|
|
42688
|
+
const [boardMenuOpen, setBoardMenuOpen] = (0, import_react16.useState)(false);
|
|
42689
|
+
const [createIssueModal, setCreateIssueModal] = (0, import_react16.useState)(null);
|
|
42690
|
+
const boardMenuRef = (0, import_react16.useRef)(null);
|
|
42691
|
+
const socketRef = (0, import_react16.useRef)(null);
|
|
42692
|
+
const [mutationGate] = (0, import_react16.useState)(createMutationGate);
|
|
41681
42693
|
const selectedTab = searchParams.get("tab") === "comments" ? "comments" : "overview";
|
|
41682
42694
|
const navigate = useNavigate();
|
|
41683
|
-
const selectedBoard = (state && boardId ? findBoard(state, boardId) : null) ?? state?.boards[0] ?? null;
|
|
42695
|
+
const selectedBoard = (state && boardId ? findBoard(state, boardId) : null) ?? state?.boards?.[0] ?? null;
|
|
41684
42696
|
const selectedBoardId = selectedBoard?.id ?? null;
|
|
41685
|
-
const selectedBoardIdRef = (0,
|
|
42697
|
+
const selectedBoardIdRef = (0, import_react16.useRef)(selectedBoardId);
|
|
41686
42698
|
selectedBoardIdRef.current = selectedBoardId;
|
|
41687
42699
|
const boardSlug = selectedBoard?.ref ?? boardId;
|
|
41688
42700
|
const selectedIssue = state && issueId ? findIssue(state, issueId) : null;
|
|
41689
|
-
(0,
|
|
42701
|
+
(0, import_react16.useEffect)(() => {
|
|
41690
42702
|
const onPaste = (event) => {
|
|
41691
42703
|
if (!selectedIssue || selectedIssue.readonly) return;
|
|
41692
42704
|
const target = event.target;
|
|
@@ -41705,33 +42717,69 @@ var App = () => {
|
|
|
41705
42717
|
if (!boardSlug) return;
|
|
41706
42718
|
void navigate(`/board/${boardSlug}`);
|
|
41707
42719
|
};
|
|
41708
|
-
const commentsByIssueId = state?.commentsByIssueId ??
|
|
42720
|
+
const commentsByIssueId = state?.commentsByIssueId ?? EMPTY_COMMENTS;
|
|
42721
|
+
const [issueDetail, setIssueDetail] = (0, import_react16.useState)(null);
|
|
42722
|
+
const [boardFilter, setBoardFilter] = (0, import_react16.useState)(null);
|
|
42723
|
+
const { visibleSwimlanes, hiddenIssueCount } = (0, import_react16.useMemo)(() => {
|
|
42724
|
+
const swimlanes = selectedBoard?.swimlanes ?? [];
|
|
42725
|
+
if (!boardFilter) return { visibleSwimlanes: swimlanes, hiddenIssueCount: 0 };
|
|
42726
|
+
let hidden = 0;
|
|
42727
|
+
const visible = swimlanes.map((swimlane) => {
|
|
42728
|
+
const issues = swimlane.issues.filter(
|
|
42729
|
+
(issue) => issuePassesBoardFilter(
|
|
42730
|
+
issue,
|
|
42731
|
+
(commentsByIssueId[issue.id] ?? []).map((comment) => comment.author.id),
|
|
42732
|
+
boardFilter
|
|
42733
|
+
)
|
|
42734
|
+
);
|
|
42735
|
+
hidden += swimlane.issues.length - issues.length;
|
|
42736
|
+
return { ...swimlane, issues };
|
|
42737
|
+
});
|
|
42738
|
+
return { visibleSwimlanes: visible, hiddenIssueCount: hidden };
|
|
42739
|
+
}, [selectedBoard, boardFilter, commentsByIssueId]);
|
|
41709
42740
|
const attachmentsByIssueId = state?.attachmentsByIssueId ?? {};
|
|
41710
|
-
const [attachmentUploadStatus, setAttachmentUploadStatus] = (0,
|
|
42741
|
+
const [attachmentUploadStatus, setAttachmentUploadStatus] = (0, import_react16.useState)({ state: "idle" });
|
|
42742
|
+
(0, import_react16.useEffect)(() => {
|
|
42743
|
+
if (!selectedIssue) {
|
|
42744
|
+
setIssueDetail(null);
|
|
42745
|
+
return;
|
|
42746
|
+
}
|
|
42747
|
+
sendSocketJson(socketRef.current, {
|
|
42748
|
+
type: "issue:get",
|
|
42749
|
+
payload: { issueId: selectedIssue.id }
|
|
42750
|
+
});
|
|
42751
|
+
}, [selectedIssue?.id, state]);
|
|
41711
42752
|
const requestState = () => {
|
|
41712
42753
|
sendSocketJson(socketRef.current, { type: "state:get" });
|
|
41713
42754
|
};
|
|
41714
|
-
(0,
|
|
42755
|
+
(0, import_react16.useEffect)(() => {
|
|
41715
42756
|
const socket = new WebSocket(
|
|
41716
42757
|
`ws://${window.location.host}/ws${boardId ? `?boardId=${boardId}` : ""}`
|
|
41717
42758
|
);
|
|
41718
42759
|
socketRef.current = socket;
|
|
41719
42760
|
socket.addEventListener("open", () => {
|
|
41720
42761
|
setConnected(true);
|
|
42762
|
+
mutationGate.reset();
|
|
41721
42763
|
sendSocketJson(socket, { type: "state:get" });
|
|
41722
42764
|
});
|
|
41723
42765
|
socket.addEventListener("close", () => {
|
|
41724
42766
|
setConnected(false);
|
|
42767
|
+
mutationGate.reset();
|
|
41725
42768
|
if (socketRef.current === socket) {
|
|
41726
42769
|
socketRef.current = null;
|
|
41727
42770
|
}
|
|
41728
42771
|
});
|
|
41729
42772
|
socket.addEventListener("message", (event) => {
|
|
41730
42773
|
const message = JSON.parse(event.data);
|
|
41731
|
-
|
|
42774
|
+
mutationGate.received(message.type);
|
|
42775
|
+
if (message.type === "state" && !mutationGate.holdsState()) {
|
|
41732
42776
|
const nextState = getResultValue(message.payload);
|
|
41733
42777
|
if (nextState) setState(nextState);
|
|
41734
42778
|
}
|
|
42779
|
+
if (message.type === "issue") {
|
|
42780
|
+
const detail = getResultValue(message.payload);
|
|
42781
|
+
if (detail) setIssueDetail(detail);
|
|
42782
|
+
}
|
|
41735
42783
|
if (message.type === "issue:created") {
|
|
41736
42784
|
const created = getResultValue(message.payload);
|
|
41737
42785
|
if (created && boardId) {
|
|
@@ -41741,7 +42789,9 @@ var App = () => {
|
|
|
41741
42789
|
}
|
|
41742
42790
|
}
|
|
41743
42791
|
if (message.type === "failed") {
|
|
41744
|
-
|
|
42792
|
+
setActionError(
|
|
42793
|
+
typeof message.payload === "string" ? message.payload : "The board refused that change"
|
|
42794
|
+
);
|
|
41745
42795
|
requestState();
|
|
41746
42796
|
}
|
|
41747
42797
|
if (message.type === "timeline") {
|
|
@@ -41789,12 +42839,13 @@ var App = () => {
|
|
|
41789
42839
|
socket.close();
|
|
41790
42840
|
};
|
|
41791
42841
|
}, [boardId, navigate]);
|
|
41792
|
-
(0,
|
|
41793
|
-
|
|
41794
|
-
|
|
42842
|
+
(0, import_react16.useEffect)(() => {
|
|
42843
|
+
const first = state?.boards?.[0];
|
|
42844
|
+
if (!boardId && first) {
|
|
42845
|
+
void navigate(`/board/${first.ref}`, { replace: true });
|
|
41795
42846
|
}
|
|
41796
42847
|
}, [boardId, state, navigate]);
|
|
41797
|
-
(0,
|
|
42848
|
+
(0, import_react16.useEffect)(() => {
|
|
41798
42849
|
const close = (event) => {
|
|
41799
42850
|
if (boardMenuRef.current && !boardMenuRef.current.contains(event.target)) {
|
|
41800
42851
|
setBoardMenuOpen(false);
|
|
@@ -41808,9 +42859,24 @@ var App = () => {
|
|
|
41808
42859
|
setDropTarget(null);
|
|
41809
42860
|
};
|
|
41810
42861
|
const send = (type, payload) => {
|
|
42862
|
+
mutationGate.sent(type);
|
|
41811
42863
|
sendSocketJson(socketRef.current, { type, payload });
|
|
41812
42864
|
};
|
|
41813
|
-
const
|
|
42865
|
+
const togglePicked = (nextIssueId) => {
|
|
42866
|
+
setPickedIssueIds(
|
|
42867
|
+
(current) => current.includes(nextIssueId) ? current.filter((id) => id !== nextIssueId) : [...current, nextIssueId]
|
|
42868
|
+
);
|
|
42869
|
+
};
|
|
42870
|
+
const clearPicked = () => setPickedIssueIds([]);
|
|
42871
|
+
const [bulkTagName, setBulkTagName] = (0, import_react16.useState)("");
|
|
42872
|
+
const [bulkAssigneeName, setBulkAssigneeName] = (0, import_react16.useState)("");
|
|
42873
|
+
const pickedIssues = (state?.boards ?? []).flatMap((board) => board.swimlanes).flatMap((swimlane) => swimlane.issues).filter((issue) => pickedIssueIds.includes(issue.id));
|
|
42874
|
+
const forPicked = (act) => {
|
|
42875
|
+
for (const issue of pickedIssues) act(issue.id);
|
|
42876
|
+
};
|
|
42877
|
+
const selectIssue = (nextIssueId, { toggle } = { toggle: false }) => {
|
|
42878
|
+
if (toggle) return togglePicked(nextIssueId);
|
|
42879
|
+
setPickedIssueIds([nextIssueId]);
|
|
41814
42880
|
if (!boardSlug) return;
|
|
41815
42881
|
void navigate(
|
|
41816
42882
|
`/board/${boardSlug}/issue/${nodeRef(nextIssueId)}?tab=overview`
|
|
@@ -41957,7 +43023,7 @@ var App = () => {
|
|
|
41957
43023
|
const returnToLive = () => {
|
|
41958
43024
|
send("time-travel:live", {});
|
|
41959
43025
|
};
|
|
41960
|
-
const requestBoardHistory = (0,
|
|
43026
|
+
const requestBoardHistory = (0, import_react16.useCallback)(
|
|
41961
43027
|
(start2, end, allBoards) => {
|
|
41962
43028
|
const window2 = start2 !== void 0 ? { start: start2, end } : void 0;
|
|
41963
43029
|
const requestId = historyBuffer.open();
|
|
@@ -41976,28 +43042,34 @@ var App = () => {
|
|
|
41976
43042
|
},
|
|
41977
43043
|
[selectedBoardId]
|
|
41978
43044
|
);
|
|
41979
|
-
const requestContributors = (0,
|
|
43045
|
+
const requestContributors = (0, import_react16.useCallback)(() => {
|
|
41980
43046
|
sendSocketJson(socketRef.current, {
|
|
41981
43047
|
type: "contributors:get",
|
|
41982
43048
|
payload: { boardId: selectedBoardIdRef.current }
|
|
41983
43049
|
});
|
|
41984
43050
|
}, []);
|
|
41985
|
-
(0,
|
|
43051
|
+
(0, import_react16.useEffect)(() => {
|
|
41986
43052
|
setContributors([]);
|
|
43053
|
+
setPickedIssueIds([]);
|
|
41987
43054
|
}, [selectedBoardId]);
|
|
41988
|
-
const inspectCommit = (0,
|
|
43055
|
+
const inspectCommit = (0, import_react16.useCallback)((sha) => {
|
|
41989
43056
|
sendSocketJson(socketRef.current, { type: "commit:inspect", payload: { sha } });
|
|
41990
43057
|
}, []);
|
|
41991
|
-
(0,
|
|
43058
|
+
(0, import_react16.useEffect)(() => {
|
|
41992
43059
|
if (!commitInspectError) return;
|
|
41993
43060
|
const timeout = setTimeout(() => setCommitInspectError(null), 8e3);
|
|
41994
43061
|
return () => clearTimeout(timeout);
|
|
41995
43062
|
}, [commitInspectError]);
|
|
41996
|
-
(0,
|
|
43063
|
+
(0, import_react16.useEffect)(() => {
|
|
41997
43064
|
if (!removeError) return;
|
|
41998
43065
|
const timeout = setTimeout(() => setRemoveError(null), 8e3);
|
|
41999
43066
|
return () => clearTimeout(timeout);
|
|
42000
43067
|
}, [removeError]);
|
|
43068
|
+
(0, import_react16.useEffect)(() => {
|
|
43069
|
+
if (!actionError) return;
|
|
43070
|
+
const timeout = setTimeout(() => setActionError(null), 8e3);
|
|
43071
|
+
return () => clearTimeout(timeout);
|
|
43072
|
+
}, [actionError]);
|
|
42001
43073
|
const selectBoard = (nextBoardId) => {
|
|
42002
43074
|
setBoardMenuOpen(false);
|
|
42003
43075
|
clearDragState();
|
|
@@ -42120,7 +43192,7 @@ var App = () => {
|
|
|
42120
43192
|
});
|
|
42121
43193
|
send("issue:comment:delete", { commentId });
|
|
42122
43194
|
};
|
|
42123
|
-
return /* @__PURE__ */ (0,
|
|
43195
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
42124
43196
|
"div",
|
|
42125
43197
|
{
|
|
42126
43198
|
style: {
|
|
@@ -42132,37 +43204,46 @@ var App = () => {
|
|
|
42132
43204
|
flexDirection: "column"
|
|
42133
43205
|
},
|
|
42134
43206
|
children: [
|
|
42135
|
-
/* @__PURE__ */ (0,
|
|
42136
|
-
commitInspectError && /* @__PURE__ */ (0,
|
|
43207
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(GlobalScrollbarStyles, {}),
|
|
43208
|
+
commitInspectError && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
42137
43209
|
ErrorToast,
|
|
42138
43210
|
{
|
|
42139
43211
|
message: `Couldn't open commit diff: ${commitInspectError}`,
|
|
42140
43212
|
onDismiss: () => setCommitInspectError(null)
|
|
42141
43213
|
}
|
|
42142
43214
|
),
|
|
42143
|
-
removeError && /* @__PURE__ */ (0,
|
|
43215
|
+
removeError && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
42144
43216
|
ErrorToast,
|
|
42145
43217
|
{
|
|
42146
43218
|
message: removeError,
|
|
42147
43219
|
onDismiss: () => setRemoveError(null)
|
|
42148
43220
|
}
|
|
42149
43221
|
),
|
|
42150
|
-
/* @__PURE__ */ (0,
|
|
42151
|
-
|
|
43222
|
+
actionError && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
43223
|
+
ErrorToast,
|
|
43224
|
+
{
|
|
43225
|
+
message: actionError,
|
|
43226
|
+
onDismiss: () => setActionError(null)
|
|
43227
|
+
}
|
|
43228
|
+
),
|
|
43229
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Header, { state, connected, syncStatus }),
|
|
43230
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
42152
43231
|
TimeScrubber,
|
|
42153
43232
|
{
|
|
42154
43233
|
timeline: history.timeline,
|
|
42155
43234
|
commits: history.commits,
|
|
43235
|
+
historyId: history.requestId,
|
|
42156
43236
|
boardId: selectedBoardId,
|
|
42157
43237
|
connected,
|
|
42158
43238
|
onRequestHistory: requestBoardHistory,
|
|
42159
43239
|
onInspectCommit: inspectCommit,
|
|
42160
43240
|
timeTravel: state?.timeTravel ?? { mode: "live", asOfTime: null },
|
|
42161
43241
|
onScrub: scrubToTime,
|
|
42162
|
-
onReturnToLive: returnToLive
|
|
43242
|
+
onReturnToLive: returnToLive,
|
|
43243
|
+
onBoardFilterChange: setBoardFilter
|
|
42163
43244
|
}
|
|
42164
43245
|
),
|
|
42165
|
-
/* @__PURE__ */ (0,
|
|
43246
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
42166
43247
|
"div",
|
|
42167
43248
|
{
|
|
42168
43249
|
style: {
|
|
@@ -42171,9 +43252,10 @@ var App = () => {
|
|
|
42171
43252
|
overflow: "hidden"
|
|
42172
43253
|
},
|
|
42173
43254
|
children: [
|
|
42174
|
-
/* @__PURE__ */ (0,
|
|
43255
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
42175
43256
|
"main",
|
|
42176
43257
|
{
|
|
43258
|
+
onClick: clearPicked,
|
|
42177
43259
|
style: {
|
|
42178
43260
|
// No bottom padding: the board row is the horizontal scroll
|
|
42179
43261
|
// container, and a gap below it would strand its scrollbar.
|
|
@@ -42185,24 +43267,35 @@ var App = () => {
|
|
|
42185
43267
|
overflow: "hidden"
|
|
42186
43268
|
},
|
|
42187
43269
|
children: [
|
|
42188
|
-
/* @__PURE__ */ (0,
|
|
42189
|
-
|
|
43270
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
43271
|
+
"div",
|
|
42190
43272
|
{
|
|
42191
|
-
|
|
42192
|
-
|
|
42193
|
-
|
|
42194
|
-
|
|
42195
|
-
|
|
42196
|
-
}
|
|
42197
|
-
|
|
42198
|
-
|
|
42199
|
-
|
|
42200
|
-
|
|
42201
|
-
|
|
42202
|
-
|
|
43273
|
+
style: {
|
|
43274
|
+
padding: "20px 10px",
|
|
43275
|
+
display: "flex",
|
|
43276
|
+
alignItems: "center",
|
|
43277
|
+
gap: 10
|
|
43278
|
+
},
|
|
43279
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
43280
|
+
Dropdown,
|
|
43281
|
+
{
|
|
43282
|
+
testId: "board-switcher",
|
|
43283
|
+
label: "Board:",
|
|
43284
|
+
value: selectedBoard ? {
|
|
43285
|
+
id: selectedBoard.id,
|
|
43286
|
+
label: selectedBoard.title
|
|
43287
|
+
} : null,
|
|
43288
|
+
items: state?.boards.map((board) => ({
|
|
43289
|
+
id: board.id,
|
|
43290
|
+
label: board.title
|
|
43291
|
+
})) ?? [],
|
|
43292
|
+
placeholder: "Loading...",
|
|
43293
|
+
onSelect: selectBoard
|
|
43294
|
+
}
|
|
43295
|
+
)
|
|
42203
43296
|
}
|
|
42204
|
-
)
|
|
42205
|
-
/* @__PURE__ */ (0,
|
|
43297
|
+
),
|
|
43298
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
42206
43299
|
"div",
|
|
42207
43300
|
{
|
|
42208
43301
|
style: {
|
|
@@ -42214,7 +43307,7 @@ var App = () => {
|
|
|
42214
43307
|
overflowY: "hidden"
|
|
42215
43308
|
},
|
|
42216
43309
|
children: [
|
|
42217
|
-
|
|
43310
|
+
visibleSwimlanes.map((swimlane) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
42218
43311
|
SwimlaneColumn,
|
|
42219
43312
|
{
|
|
42220
43313
|
swimlane,
|
|
@@ -42226,27 +43319,64 @@ var App = () => {
|
|
|
42226
43319
|
onSelectIssue: selectIssue,
|
|
42227
43320
|
onSelectIssueComments: selectIssueComments,
|
|
42228
43321
|
onCreateIssue: openCreateIssueModal,
|
|
42229
|
-
onDropIssue:
|
|
43322
|
+
onDropIssue: (issueId2, swimlaneId, targetIndex) => {
|
|
43323
|
+
const moving = pickedIssueIds.includes(issueId2) ? pickedIssueIds : [issueId2];
|
|
43324
|
+
moveIssue(state, setState, send)(
|
|
43325
|
+
moving,
|
|
43326
|
+
swimlaneId,
|
|
43327
|
+
targetIndex
|
|
43328
|
+
);
|
|
43329
|
+
clearPicked();
|
|
43330
|
+
},
|
|
43331
|
+
pickedIssueIds,
|
|
42230
43332
|
onDragOver: setDragOverSwimlaneId,
|
|
42231
43333
|
onDragOverIssue: (swimlaneId, index2) => setDropTarget({ swimlaneId, index: index2 }),
|
|
42232
43334
|
onDragLeave: clearDragState
|
|
42233
43335
|
},
|
|
42234
43336
|
swimlane.id
|
|
42235
43337
|
)),
|
|
42236
|
-
!(selectedIssue && state?.user) && /* @__PURE__ */ (0,
|
|
43338
|
+
!(selectedIssue && state?.user) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { style: { width: ASIDE_WIDTH, flexShrink: 0 } })
|
|
42237
43339
|
]
|
|
42238
43340
|
}
|
|
42239
43341
|
)
|
|
42240
43342
|
]
|
|
42241
43343
|
}
|
|
42242
43344
|
),
|
|
42243
|
-
|
|
43345
|
+
pickedIssues.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
43346
|
+
BulkDetails,
|
|
43347
|
+
{
|
|
43348
|
+
issues: pickedIssues,
|
|
43349
|
+
knownTags: state?.tags ?? [],
|
|
43350
|
+
knownAssignees: contributors,
|
|
43351
|
+
tagName: bulkTagName,
|
|
43352
|
+
assigneeName: bulkAssigneeName,
|
|
43353
|
+
onChangeTagName: setBulkTagName,
|
|
43354
|
+
onChangeAssigneeName: setBulkAssigneeName,
|
|
43355
|
+
onAddTag: (name2) => {
|
|
43356
|
+
forPicked((id) => addIssueTag(id, name2));
|
|
43357
|
+
setBulkTagName("");
|
|
43358
|
+
},
|
|
43359
|
+
onRemoveTag: (tagId) => forPicked((id) => removeIssueTag(id, tagId)),
|
|
43360
|
+
onAddAssignee: (assigneeId) => forPicked((id) => addIssueAssignee(id, assigneeId)),
|
|
43361
|
+
onRemoveAssignee: (assigneeId) => forPicked((id) => removeIssueAssignee(id, assigneeId)),
|
|
43362
|
+
onCloseIssues: () => {
|
|
43363
|
+
forPicked(closeIssue);
|
|
43364
|
+
clearPicked();
|
|
43365
|
+
},
|
|
43366
|
+
onReopenIssues: () => {
|
|
43367
|
+
forPicked(reopenIssue);
|
|
43368
|
+
clearPicked();
|
|
43369
|
+
},
|
|
43370
|
+
onClear: clearPicked
|
|
43371
|
+
}
|
|
43372
|
+
),
|
|
43373
|
+
pickedIssues.length <= 1 && selectedIssue && state?.user && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
42244
43374
|
IssueDetails,
|
|
42245
43375
|
{
|
|
42246
43376
|
whoAmI: state.user,
|
|
42247
|
-
issue: selectedIssue,
|
|
43377
|
+
issue: issueDetail?.issueId === selectedIssue.id ? { ...selectedIssue, description: issueDetail.description } : selectedIssue,
|
|
42248
43378
|
activeTab: selectedTab,
|
|
42249
|
-
comments:
|
|
43379
|
+
comments: issueDetail?.issueId === selectedIssue.id ? issueDetail.comments : [],
|
|
42250
43380
|
onChangeTab: changeIssueDetailsTab,
|
|
42251
43381
|
onClose: closeIssueDetails,
|
|
42252
43382
|
onEditTitle: editIssueTitle,
|
|
@@ -42273,7 +43403,7 @@ var App = () => {
|
|
|
42273
43403
|
]
|
|
42274
43404
|
}
|
|
42275
43405
|
),
|
|
42276
|
-
createIssueModal && /* @__PURE__ */ (0,
|
|
43406
|
+
createIssueModal && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
42277
43407
|
CreateIssueModal,
|
|
42278
43408
|
{
|
|
42279
43409
|
title: createIssueModal.title,
|
|
@@ -42288,14 +43418,12 @@ var App = () => {
|
|
|
42288
43418
|
};
|
|
42289
43419
|
|
|
42290
43420
|
// source/gui/client/main.tsx
|
|
42291
|
-
var
|
|
43421
|
+
var import_jsx_runtime34 = __toESM(require_jsx_runtime(), 1);
|
|
42292
43422
|
(0, import_client.createRoot)(document.getElementById("root")).render(
|
|
42293
|
-
/* @__PURE__ */ (0,
|
|
42294
|
-
/* @__PURE__ */ (0,
|
|
42295
|
-
/* @__PURE__ */ (0,
|
|
42296
|
-
/* @__PURE__ */ (0,
|
|
42297
|
-
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Route, { path: "/board/:boardId/:issueId", element: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(App, {}) }),
|
|
42298
|
-
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Route, { path: "*", element: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Navigate, { to: "/", replace: true }) })
|
|
43423
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(BrowserRouter, { children: /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(Routes, { children: [
|
|
43424
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(Route, { path: "/", element: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(App, {}) }),
|
|
43425
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(Route, { path: "/board/:boardId/*", element: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(App, {}) }),
|
|
43426
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(Route, { path: "*", element: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(Navigate, { to: "/", replace: true }) })
|
|
42299
43427
|
] }) })
|
|
42300
43428
|
);
|
|
42301
43429
|
/*! Bundled license information:
|