epiq 1.4.4 → 1.5.0
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 +1719 -813
- package/dist/index.js +56 -56
- package/dist/mcp.js +46 -46
- package/package.json +1 -1
package/dist/gui/main.js
CHANGED
|
@@ -22497,18 +22497,18 @@ function matchPath(pattern, pathname) {
|
|
|
22497
22497
|
let pathnameBase = matchedPathname.replace(/(.)\/+$/, "$1");
|
|
22498
22498
|
let captureGroups = match.slice(1);
|
|
22499
22499
|
let params = compiledParams.reduce(
|
|
22500
|
-
(
|
|
22500
|
+
(memo22, { paramName, isOptional }, index2) => {
|
|
22501
22501
|
if (paramName === "*") {
|
|
22502
22502
|
let splatValue = captureGroups[index2] || "";
|
|
22503
22503
|
pathnameBase = matchedPathname.slice(0, matchedPathname.length - splatValue.length).replace(/(.)\/+$/, "$1");
|
|
22504
22504
|
}
|
|
22505
22505
|
const value = captureGroups[index2];
|
|
22506
22506
|
if (isOptional && !value) {
|
|
22507
|
-
|
|
22507
|
+
memo22[paramName] = void 0;
|
|
22508
22508
|
} else {
|
|
22509
|
-
|
|
22509
|
+
memo22[paramName] = (value || "").replace(/%2F/g, "/");
|
|
22510
22510
|
}
|
|
22511
|
-
return
|
|
22511
|
+
return memo22;
|
|
22512
22512
|
},
|
|
22513
22513
|
{}
|
|
22514
22514
|
);
|
|
@@ -23610,9 +23610,9 @@ function shouldProcessLinkClick(event, target) {
|
|
|
23610
23610
|
}
|
|
23611
23611
|
function createSearchParams(init = "") {
|
|
23612
23612
|
return new URLSearchParams(
|
|
23613
|
-
typeof init === "string" || Array.isArray(init) || init instanceof URLSearchParams ? init : Object.keys(init).reduce((
|
|
23613
|
+
typeof init === "string" || Array.isArray(init) || init instanceof URLSearchParams ? init : Object.keys(init).reduce((memo22, key) => {
|
|
23614
23614
|
let value = init[key];
|
|
23615
|
-
return
|
|
23615
|
+
return memo22.concat(
|
|
23616
23616
|
Array.isArray(value) ? value.map((v) => [key, v]) : [[key, value]]
|
|
23617
23617
|
);
|
|
23618
23618
|
}, [])
|
|
@@ -24838,7 +24838,7 @@ function useViewTransitionState(to, { relative } = {}) {
|
|
|
24838
24838
|
}
|
|
24839
24839
|
|
|
24840
24840
|
// source/gui/client/App.tsx
|
|
24841
|
-
var
|
|
24841
|
+
var import_react18 = __toESM(require_react(), 1);
|
|
24842
24842
|
|
|
24843
24843
|
// source/gui/client/components/Aside.tsx
|
|
24844
24844
|
var import_react = __toESM(require_react(), 1);
|
|
@@ -24940,9 +24940,13 @@ var Button = ({
|
|
|
24940
24940
|
);
|
|
24941
24941
|
};
|
|
24942
24942
|
|
|
24943
|
-
// source/gui/client/components/
|
|
24943
|
+
// source/gui/client/components/CreateNodeModal.tsx
|
|
24944
24944
|
var import_jsx_runtime3 = __toESM(require_jsx_runtime(), 1);
|
|
24945
|
-
var
|
|
24945
|
+
var CreateNodeModal = ({
|
|
24946
|
+
eyebrow,
|
|
24947
|
+
fieldLabel,
|
|
24948
|
+
placeholder,
|
|
24949
|
+
confirmLabel = "create",
|
|
24946
24950
|
title,
|
|
24947
24951
|
onChangeTitle,
|
|
24948
24952
|
onCreate,
|
|
@@ -24988,7 +24992,7 @@ var CreateIssueModal = ({
|
|
|
24988
24992
|
letterSpacing: 1,
|
|
24989
24993
|
textTransform: "uppercase"
|
|
24990
24994
|
},
|
|
24991
|
-
children:
|
|
24995
|
+
children: eyebrow
|
|
24992
24996
|
}
|
|
24993
24997
|
),
|
|
24994
24998
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
@@ -24999,7 +25003,7 @@ var CreateIssueModal = ({
|
|
|
24999
25003
|
fontSize: 10,
|
|
25000
25004
|
color: GUI_THEME.primary
|
|
25001
25005
|
},
|
|
25002
|
-
children:
|
|
25006
|
+
children: fieldLabel
|
|
25003
25007
|
}
|
|
25004
25008
|
),
|
|
25005
25009
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
@@ -25007,7 +25011,7 @@ var CreateIssueModal = ({
|
|
|
25007
25011
|
{
|
|
25008
25012
|
autoFocus: true,
|
|
25009
25013
|
value: title,
|
|
25010
|
-
placeholder
|
|
25014
|
+
placeholder,
|
|
25011
25015
|
onChange: (event) => onChangeTitle(event.target.value),
|
|
25012
25016
|
onKeyDown: (event) => {
|
|
25013
25017
|
if (event.key === "Escape") {
|
|
@@ -25039,8 +25043,8 @@ var CreateIssueModal = ({
|
|
|
25039
25043
|
marginTop: 20
|
|
25040
25044
|
},
|
|
25041
25045
|
children: [
|
|
25042
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Button, { variant: "ghost", onClick: onClose, children: "cancel" }),
|
|
25043
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Button, { variant: "primary", children:
|
|
25046
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Button, { type: "button", variant: "ghost", onClick: onClose, children: "cancel" }),
|
|
25047
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Button, { type: "submit", variant: "primary", children: confirmLabel })
|
|
25044
25048
|
]
|
|
25045
25049
|
}
|
|
25046
25050
|
)
|
|
@@ -25050,130 +25054,144 @@ var CreateIssueModal = ({
|
|
|
25050
25054
|
}
|
|
25051
25055
|
);
|
|
25052
25056
|
|
|
25053
|
-
// source/gui/client/components/
|
|
25057
|
+
// source/gui/client/components/AddSwimlaneColumn.tsx
|
|
25054
25058
|
var import_react3 = __toESM(require_react(), 1);
|
|
25055
25059
|
var import_jsx_runtime4 = __toESM(require_jsx_runtime(), 1);
|
|
25056
|
-
var
|
|
25057
|
-
|
|
25058
|
-
|
|
25059
|
-
items,
|
|
25060
|
-
placeholder = "Select...",
|
|
25061
|
-
onSelect,
|
|
25062
|
-
testId
|
|
25063
|
-
}) => {
|
|
25064
|
-
const [open, setOpen] = (0, import_react3.useState)(false);
|
|
25065
|
-
const ref = (0, import_react3.useRef)(null);
|
|
25066
|
-
(0, import_react3.useEffect)(() => {
|
|
25067
|
-
const close = (event) => {
|
|
25068
|
-
if (ref.current && !ref.current.contains(event.target)) {
|
|
25069
|
-
setOpen(false);
|
|
25070
|
-
}
|
|
25071
|
-
};
|
|
25072
|
-
document.addEventListener("mousedown", close);
|
|
25073
|
-
return () => document.removeEventListener("mousedown", close);
|
|
25074
|
-
}, []);
|
|
25060
|
+
var COLUMN_WIDTH = 360;
|
|
25061
|
+
var AddSwimlaneColumn = ({ onClick }) => {
|
|
25062
|
+
const [hovered, setHovered] = (0, import_react3.useState)(false);
|
|
25075
25063
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
25076
|
-
"
|
|
25064
|
+
"button",
|
|
25077
25065
|
{
|
|
25078
|
-
|
|
25066
|
+
type: "button",
|
|
25067
|
+
"data-testid": "add-swimlane",
|
|
25068
|
+
title: "Add swimlane",
|
|
25069
|
+
onClick,
|
|
25070
|
+
onMouseEnter: () => setHovered(true),
|
|
25071
|
+
onMouseLeave: () => setHovered(false),
|
|
25079
25072
|
style: {
|
|
25080
|
-
|
|
25081
|
-
|
|
25073
|
+
appearance: "none",
|
|
25074
|
+
WebkitAppearance: "none",
|
|
25075
|
+
width: COLUMN_WIDTH,
|
|
25076
|
+
minWidth: COLUMN_WIDTH,
|
|
25077
|
+
height: "100%",
|
|
25078
|
+
boxSizing: "border-box",
|
|
25079
|
+
border: `1px dashed ${hovered ? GUI_THEME.secondary : GUI_THEME.line}`,
|
|
25080
|
+
borderRadius: 12,
|
|
25081
|
+
background: hovered ? GUI_THEME.bgHighlight : "transparent",
|
|
25082
|
+
color: hovered ? GUI_THEME.secondary : GUI_THEME.dim,
|
|
25082
25083
|
display: "flex",
|
|
25084
|
+
flexDirection: "column",
|
|
25083
25085
|
alignItems: "center",
|
|
25084
|
-
|
|
25086
|
+
justifyContent: "center",
|
|
25087
|
+
gap: 6,
|
|
25088
|
+
cursor: "pointer",
|
|
25089
|
+
fontFamily: "inherit",
|
|
25090
|
+
outline: "none",
|
|
25091
|
+
transition: "color 120ms ease, border-color 120ms ease, background 120ms ease"
|
|
25085
25092
|
},
|
|
25086
25093
|
children: [
|
|
25087
|
-
|
|
25088
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.
|
|
25089
|
-
Button,
|
|
25090
|
-
{
|
|
25091
|
-
variant: "ghost",
|
|
25092
|
-
"data-testid": testId,
|
|
25093
|
-
onClick: () => setOpen((value2) => !value2),
|
|
25094
|
-
style: {
|
|
25095
|
-
display: "flex",
|
|
25096
|
-
alignItems: "center",
|
|
25097
|
-
width: 100
|
|
25098
|
-
},
|
|
25099
|
-
children: [
|
|
25100
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: value?.label ?? placeholder }),
|
|
25101
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
25102
|
-
"span",
|
|
25103
|
-
{
|
|
25104
|
-
style: {
|
|
25105
|
-
marginLeft: "auto",
|
|
25106
|
-
color: GUI_THEME.dim,
|
|
25107
|
-
fontSize: "12px",
|
|
25108
|
-
display: "inline-block",
|
|
25109
|
-
transform: open ? "rotate(90deg)" : "rotate(0deg)",
|
|
25110
|
-
transition: "transform 120ms ease"
|
|
25111
|
-
},
|
|
25112
|
-
children: "\u276F"
|
|
25113
|
-
}
|
|
25114
|
-
)
|
|
25115
|
-
]
|
|
25116
|
-
}
|
|
25117
|
-
),
|
|
25118
|
-
open && items.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
25119
|
-
"div",
|
|
25120
|
-
{
|
|
25121
|
-
style: {
|
|
25122
|
-
position: "absolute",
|
|
25123
|
-
top: 28,
|
|
25124
|
-
left: label ? 62 : 0,
|
|
25125
|
-
minWidth: 220,
|
|
25126
|
-
background: GUI_THEME.bg,
|
|
25127
|
-
border: `1px solid ${GUI_THEME.line}`,
|
|
25128
|
-
borderRadius: 8,
|
|
25129
|
-
boxShadow: "0 12px 32px rgba(0, 0, 0, 0.35)",
|
|
25130
|
-
padding: 6,
|
|
25131
|
-
zIndex: 10
|
|
25132
|
-
},
|
|
25133
|
-
children: items.map((item) => {
|
|
25134
|
-
const selected = item.id === value?.id;
|
|
25135
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
25136
|
-
"button",
|
|
25137
|
-
{
|
|
25138
|
-
type: "button",
|
|
25139
|
-
"data-testid": testId ? `${testId}-option` : void 0,
|
|
25140
|
-
onClick: () => {
|
|
25141
|
-
setOpen(false);
|
|
25142
|
-
onSelect(item.id);
|
|
25143
|
-
},
|
|
25144
|
-
style: {
|
|
25145
|
-
width: "100%",
|
|
25146
|
-
display: "flex",
|
|
25147
|
-
justifyContent: "space-between",
|
|
25148
|
-
alignItems: "center",
|
|
25149
|
-
border: "none",
|
|
25150
|
-
background: selected ? GUI_THEME.line : "transparent",
|
|
25151
|
-
color: selected ? GUI_THEME.accent : GUI_THEME.primary,
|
|
25152
|
-
fontFamily: "inherit",
|
|
25153
|
-
fontSize: 11,
|
|
25154
|
-
textAlign: "left",
|
|
25155
|
-
padding: "8px 10px",
|
|
25156
|
-
borderRadius: 6,
|
|
25157
|
-
cursor: "pointer"
|
|
25158
|
-
},
|
|
25159
|
-
children: [
|
|
25160
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: item.label }),
|
|
25161
|
-
selected ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "\u2713" }) : null
|
|
25162
|
-
]
|
|
25163
|
-
},
|
|
25164
|
-
item.id
|
|
25165
|
-
);
|
|
25166
|
-
})
|
|
25167
|
-
}
|
|
25168
|
-
) : null
|
|
25094
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: { fontSize: 20, lineHeight: 1 }, children: "+" }),
|
|
25095
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: { fontSize: 12 }, children: "new swimlane" })
|
|
25169
25096
|
]
|
|
25170
25097
|
}
|
|
25171
25098
|
);
|
|
25172
25099
|
};
|
|
25173
25100
|
|
|
25101
|
+
// source/gui/client/components/ConfirmModal.tsx
|
|
25102
|
+
var import_jsx_runtime5 = __toESM(require_jsx_runtime(), 1);
|
|
25103
|
+
var ConfirmModal = ({
|
|
25104
|
+
eyebrow,
|
|
25105
|
+
heading: heading3,
|
|
25106
|
+
body,
|
|
25107
|
+
confirmLabel,
|
|
25108
|
+
onConfirm,
|
|
25109
|
+
onClose
|
|
25110
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
25111
|
+
"div",
|
|
25112
|
+
{
|
|
25113
|
+
style: {
|
|
25114
|
+
position: "fixed",
|
|
25115
|
+
inset: 0,
|
|
25116
|
+
background: "rgba(0, 0, 0, 0.25)",
|
|
25117
|
+
backdropFilter: "blur(.5px)",
|
|
25118
|
+
display: "flex",
|
|
25119
|
+
alignItems: "center",
|
|
25120
|
+
justifyContent: "center",
|
|
25121
|
+
zIndex: 1e3
|
|
25122
|
+
},
|
|
25123
|
+
onMouseDown: onClose,
|
|
25124
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
25125
|
+
"form",
|
|
25126
|
+
{
|
|
25127
|
+
"data-testid": "confirm-modal",
|
|
25128
|
+
onSubmit: (event) => {
|
|
25129
|
+
event.preventDefault();
|
|
25130
|
+
onConfirm();
|
|
25131
|
+
},
|
|
25132
|
+
onMouseDown: (event) => event.stopPropagation(),
|
|
25133
|
+
onKeyDown: (event) => {
|
|
25134
|
+
if (event.key === "Escape") onClose();
|
|
25135
|
+
},
|
|
25136
|
+
style: {
|
|
25137
|
+
marginTop: "-200px",
|
|
25138
|
+
width: 360,
|
|
25139
|
+
background: GUI_THEME.panel,
|
|
25140
|
+
border: `1px solid ${GUI_THEME.line}`,
|
|
25141
|
+
borderRadius: 12,
|
|
25142
|
+
padding: 20
|
|
25143
|
+
},
|
|
25144
|
+
children: [
|
|
25145
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
25146
|
+
"div",
|
|
25147
|
+
{
|
|
25148
|
+
style: {
|
|
25149
|
+
color: GUI_THEME.red,
|
|
25150
|
+
fontSize: 10,
|
|
25151
|
+
marginBottom: 8,
|
|
25152
|
+
letterSpacing: 1,
|
|
25153
|
+
textTransform: "uppercase"
|
|
25154
|
+
},
|
|
25155
|
+
children: eyebrow
|
|
25156
|
+
}
|
|
25157
|
+
),
|
|
25158
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h2", { style: { margin: "0 0 10px", fontSize: 13, color: GUI_THEME.primary }, children: heading3 }),
|
|
25159
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
25160
|
+
"p",
|
|
25161
|
+
{
|
|
25162
|
+
style: {
|
|
25163
|
+
margin: 0,
|
|
25164
|
+
fontSize: 12,
|
|
25165
|
+
lineHeight: 1.7,
|
|
25166
|
+
color: GUI_THEME.secondary
|
|
25167
|
+
},
|
|
25168
|
+
children: body
|
|
25169
|
+
}
|
|
25170
|
+
),
|
|
25171
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
25172
|
+
"div",
|
|
25173
|
+
{
|
|
25174
|
+
style: {
|
|
25175
|
+
display: "flex",
|
|
25176
|
+
justifyContent: "flex-end",
|
|
25177
|
+
gap: 10,
|
|
25178
|
+
marginTop: 20
|
|
25179
|
+
},
|
|
25180
|
+
children: [
|
|
25181
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Button, { autoFocus: true, type: "button", variant: "ghost", onClick: onClose, children: "cancel" }),
|
|
25182
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Button, { type: "submit", variant: "primary", style: { color: GUI_THEME.red }, children: confirmLabel })
|
|
25183
|
+
]
|
|
25184
|
+
}
|
|
25185
|
+
)
|
|
25186
|
+
]
|
|
25187
|
+
}
|
|
25188
|
+
)
|
|
25189
|
+
}
|
|
25190
|
+
);
|
|
25191
|
+
|
|
25174
25192
|
// source/gui/client/components/Panel.tsx
|
|
25175
25193
|
var import_react4 = __toESM(require_react(), 1);
|
|
25176
|
-
var
|
|
25194
|
+
var import_jsx_runtime6 = __toESM(require_jsx_runtime(), 1);
|
|
25177
25195
|
var POINTER_SAMPLE_MS = 16;
|
|
25178
25196
|
var Panel = ({
|
|
25179
25197
|
as,
|
|
@@ -25223,7 +25241,7 @@ var Panel = ({
|
|
|
25223
25241
|
return () => window.removeEventListener("mousemove", onMove);
|
|
25224
25242
|
}, [proximityReach]);
|
|
25225
25243
|
const glowStrength = active ? 1 : proximityReach !== void 0 ? proximity : hovered ? 1 : 0;
|
|
25226
|
-
return /* @__PURE__ */ (0,
|
|
25244
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
25227
25245
|
Component4,
|
|
25228
25246
|
{
|
|
25229
25247
|
...props,
|
|
@@ -25251,56 +25269,292 @@ var Panel = ({
|
|
|
25251
25269
|
...style
|
|
25252
25270
|
},
|
|
25253
25271
|
children: [
|
|
25254
|
-
/* @__PURE__ */ (0,
|
|
25272
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
25273
|
+
"div",
|
|
25274
|
+
{
|
|
25275
|
+
ref: glowRef,
|
|
25276
|
+
style: {
|
|
25277
|
+
position: "absolute",
|
|
25278
|
+
inset: 0,
|
|
25279
|
+
borderRadius,
|
|
25280
|
+
padding: 1,
|
|
25281
|
+
pointerEvents: "none",
|
|
25282
|
+
opacity: glowStrength * glowOpacity,
|
|
25283
|
+
background: `radial-gradient(
|
|
25284
|
+
${glowRadius}px circle at ${mouse.x}px ${mouse.y}px,
|
|
25285
|
+
${glowColor},
|
|
25286
|
+
transparent 100%
|
|
25287
|
+
)`,
|
|
25288
|
+
mask: "linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0)",
|
|
25289
|
+
WebkitMask: "linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0)",
|
|
25290
|
+
maskComposite: "exclude",
|
|
25291
|
+
WebkitMaskComposite: "xor",
|
|
25292
|
+
transition: "opacity 140ms ease"
|
|
25293
|
+
}
|
|
25294
|
+
}
|
|
25295
|
+
),
|
|
25296
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
25255
25297
|
"div",
|
|
25256
25298
|
{
|
|
25257
|
-
ref: glowRef,
|
|
25258
25299
|
style: {
|
|
25259
|
-
position: "
|
|
25260
|
-
|
|
25261
|
-
|
|
25262
|
-
|
|
25263
|
-
|
|
25264
|
-
|
|
25265
|
-
|
|
25266
|
-
|
|
25267
|
-
|
|
25268
|
-
|
|
25269
|
-
|
|
25270
|
-
|
|
25271
|
-
|
|
25272
|
-
|
|
25273
|
-
|
|
25274
|
-
|
|
25275
|
-
|
|
25300
|
+
position: "relative",
|
|
25301
|
+
zIndex: 1,
|
|
25302
|
+
height: "100%",
|
|
25303
|
+
display: "flex",
|
|
25304
|
+
flexDirection: "column",
|
|
25305
|
+
minHeight: 0
|
|
25306
|
+
},
|
|
25307
|
+
children
|
|
25308
|
+
}
|
|
25309
|
+
)
|
|
25310
|
+
]
|
|
25311
|
+
}
|
|
25312
|
+
);
|
|
25313
|
+
};
|
|
25314
|
+
|
|
25315
|
+
// source/gui/client/components/InitProjectScreen.tsx
|
|
25316
|
+
var import_jsx_runtime7 = __toESM(require_jsx_runtime(), 1);
|
|
25317
|
+
var codeStyle = {
|
|
25318
|
+
background: GUI_THEME.panel2,
|
|
25319
|
+
border: `1px solid ${GUI_THEME.line}`,
|
|
25320
|
+
borderRadius: 6,
|
|
25321
|
+
padding: "2px 6px",
|
|
25322
|
+
color: GUI_THEME.primary
|
|
25323
|
+
};
|
|
25324
|
+
var InitProjectScreen = ({ repoRoot, message, onRetry }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
25325
|
+
"div",
|
|
25326
|
+
{
|
|
25327
|
+
"data-testid": "init-project-screen",
|
|
25328
|
+
style: {
|
|
25329
|
+
height: "100vh",
|
|
25330
|
+
background: GUI_THEME.bg,
|
|
25331
|
+
color: GUI_THEME.primary,
|
|
25332
|
+
fontFamily: "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace",
|
|
25333
|
+
display: "flex",
|
|
25334
|
+
alignItems: "center",
|
|
25335
|
+
justifyContent: "center",
|
|
25336
|
+
padding: 30
|
|
25337
|
+
},
|
|
25338
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
25339
|
+
Panel,
|
|
25340
|
+
{
|
|
25341
|
+
proximityReach: 300,
|
|
25342
|
+
style: { width: 520, background: GUI_THEME.panel },
|
|
25343
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
25344
|
+
"div",
|
|
25345
|
+
{
|
|
25346
|
+
style: {
|
|
25347
|
+
padding: 28,
|
|
25348
|
+
display: "flex",
|
|
25349
|
+
flexDirection: "column",
|
|
25350
|
+
gap: 16
|
|
25351
|
+
},
|
|
25352
|
+
children: [
|
|
25353
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
25354
|
+
"div",
|
|
25355
|
+
{
|
|
25356
|
+
style: {
|
|
25357
|
+
color: GUI_THEME.accent,
|
|
25358
|
+
fontSize: 10,
|
|
25359
|
+
letterSpacing: 1,
|
|
25360
|
+
textTransform: "uppercase"
|
|
25361
|
+
},
|
|
25362
|
+
children: "Initialize project"
|
|
25363
|
+
}
|
|
25364
|
+
),
|
|
25365
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h1", { style: { margin: 0, fontSize: 16, fontWeight: 700 }, children: "This folder is not an epiq project yet" }),
|
|
25366
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
25367
|
+
"div",
|
|
25368
|
+
{
|
|
25369
|
+
style: { fontSize: 12, color: GUI_THEME.secondary, lineHeight: 1.7 },
|
|
25370
|
+
children: [
|
|
25371
|
+
"No ",
|
|
25372
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: codeStyle, children: ".epiq/project.json" }),
|
|
25373
|
+
" was found in this directory or any of its parents:"
|
|
25374
|
+
]
|
|
25375
|
+
}
|
|
25376
|
+
),
|
|
25377
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
25378
|
+
"div",
|
|
25379
|
+
{
|
|
25380
|
+
style: {
|
|
25381
|
+
...codeStyle,
|
|
25382
|
+
fontSize: 12,
|
|
25383
|
+
padding: "10px 12px",
|
|
25384
|
+
wordBreak: "break-all"
|
|
25385
|
+
},
|
|
25386
|
+
children: repoRoot
|
|
25387
|
+
}
|
|
25388
|
+
),
|
|
25389
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
25390
|
+
"div",
|
|
25391
|
+
{
|
|
25392
|
+
style: { fontSize: 12, color: GUI_THEME.secondary, lineHeight: 1.7 },
|
|
25393
|
+
children: [
|
|
25394
|
+
"To start tracking issues here, run ",
|
|
25395
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: codeStyle, children: "epiq" }),
|
|
25396
|
+
" ",
|
|
25397
|
+
"in that folder and type ",
|
|
25398
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: codeStyle, children: ":init" }),
|
|
25399
|
+
". That creates, commits and pushes",
|
|
25400
|
+
" ",
|
|
25401
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: codeStyle, children: ".epiq/project.json" }),
|
|
25402
|
+
". Then come back and reload."
|
|
25403
|
+
]
|
|
25404
|
+
}
|
|
25405
|
+
),
|
|
25406
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
25407
|
+
"div",
|
|
25408
|
+
{
|
|
25409
|
+
style: {
|
|
25410
|
+
display: "flex",
|
|
25411
|
+
alignItems: "center",
|
|
25412
|
+
justifyContent: "space-between",
|
|
25413
|
+
gap: 12,
|
|
25414
|
+
marginTop: 4
|
|
25415
|
+
},
|
|
25416
|
+
children: [
|
|
25417
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { fontSize: 10, color: GUI_THEME.dim }, children: message }),
|
|
25418
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Button, { variant: "primary", onClick: onRetry, children: "check again" })
|
|
25419
|
+
]
|
|
25420
|
+
}
|
|
25421
|
+
)
|
|
25422
|
+
]
|
|
25423
|
+
}
|
|
25424
|
+
)
|
|
25425
|
+
}
|
|
25426
|
+
)
|
|
25427
|
+
}
|
|
25428
|
+
);
|
|
25429
|
+
|
|
25430
|
+
// source/gui/client/components/Dropdown.tsx
|
|
25431
|
+
var import_react5 = __toESM(require_react(), 1);
|
|
25432
|
+
var import_jsx_runtime8 = __toESM(require_jsx_runtime(), 1);
|
|
25433
|
+
var Dropdown = ({
|
|
25434
|
+
label,
|
|
25435
|
+
value,
|
|
25436
|
+
items,
|
|
25437
|
+
placeholder = "Select...",
|
|
25438
|
+
onSelect,
|
|
25439
|
+
testId
|
|
25440
|
+
}) => {
|
|
25441
|
+
const [open, setOpen] = (0, import_react5.useState)(false);
|
|
25442
|
+
const ref = (0, import_react5.useRef)(null);
|
|
25443
|
+
(0, import_react5.useEffect)(() => {
|
|
25444
|
+
const close = (event) => {
|
|
25445
|
+
if (ref.current && !ref.current.contains(event.target)) {
|
|
25446
|
+
setOpen(false);
|
|
25447
|
+
}
|
|
25448
|
+
};
|
|
25449
|
+
document.addEventListener("mousedown", close);
|
|
25450
|
+
return () => document.removeEventListener("mousedown", close);
|
|
25451
|
+
}, []);
|
|
25452
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
25453
|
+
"div",
|
|
25454
|
+
{
|
|
25455
|
+
ref,
|
|
25456
|
+
style: {
|
|
25457
|
+
position: "relative",
|
|
25458
|
+
width: "fit-content",
|
|
25459
|
+
display: "flex",
|
|
25460
|
+
alignItems: "center",
|
|
25461
|
+
gap: 12
|
|
25462
|
+
},
|
|
25463
|
+
children: [
|
|
25464
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: { color: GUI_THEME.secondary, fontSize: "12px" }, children: label }) : null,
|
|
25465
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
25466
|
+
Button,
|
|
25467
|
+
{
|
|
25468
|
+
variant: "ghost",
|
|
25469
|
+
"data-testid": testId,
|
|
25470
|
+
onClick: () => setOpen((value2) => !value2),
|
|
25471
|
+
style: {
|
|
25472
|
+
display: "flex",
|
|
25473
|
+
alignItems: "center",
|
|
25474
|
+
width: 100
|
|
25475
|
+
},
|
|
25476
|
+
children: [
|
|
25477
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: value?.label ?? placeholder }),
|
|
25478
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
25479
|
+
"span",
|
|
25480
|
+
{
|
|
25481
|
+
style: {
|
|
25482
|
+
marginLeft: "auto",
|
|
25483
|
+
color: GUI_THEME.dim,
|
|
25484
|
+
fontSize: "12px",
|
|
25485
|
+
display: "inline-block",
|
|
25486
|
+
transform: open ? "rotate(90deg)" : "rotate(0deg)",
|
|
25487
|
+
transition: "transform 120ms ease"
|
|
25488
|
+
},
|
|
25489
|
+
children: "\u276F"
|
|
25490
|
+
}
|
|
25491
|
+
)
|
|
25492
|
+
]
|
|
25276
25493
|
}
|
|
25277
25494
|
),
|
|
25278
|
-
/* @__PURE__ */ (0,
|
|
25495
|
+
open && items.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
25279
25496
|
"div",
|
|
25280
25497
|
{
|
|
25281
25498
|
style: {
|
|
25282
|
-
position: "
|
|
25283
|
-
|
|
25284
|
-
|
|
25285
|
-
|
|
25286
|
-
|
|
25287
|
-
|
|
25499
|
+
position: "absolute",
|
|
25500
|
+
top: 28,
|
|
25501
|
+
left: label ? 62 : 0,
|
|
25502
|
+
minWidth: 220,
|
|
25503
|
+
background: GUI_THEME.bg,
|
|
25504
|
+
border: `1px solid ${GUI_THEME.line}`,
|
|
25505
|
+
borderRadius: 8,
|
|
25506
|
+
boxShadow: "0 12px 32px rgba(0, 0, 0, 0.35)",
|
|
25507
|
+
padding: 6,
|
|
25508
|
+
zIndex: 10
|
|
25288
25509
|
},
|
|
25289
|
-
children
|
|
25510
|
+
children: items.map((item) => {
|
|
25511
|
+
const selected = item.id === value?.id;
|
|
25512
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
25513
|
+
"button",
|
|
25514
|
+
{
|
|
25515
|
+
type: "button",
|
|
25516
|
+
"data-testid": testId ? `${testId}-option` : void 0,
|
|
25517
|
+
onClick: () => {
|
|
25518
|
+
setOpen(false);
|
|
25519
|
+
onSelect(item.id);
|
|
25520
|
+
},
|
|
25521
|
+
style: {
|
|
25522
|
+
width: "100%",
|
|
25523
|
+
display: "flex",
|
|
25524
|
+
justifyContent: "space-between",
|
|
25525
|
+
alignItems: "center",
|
|
25526
|
+
border: "none",
|
|
25527
|
+
background: selected ? GUI_THEME.line : "transparent",
|
|
25528
|
+
color: selected ? GUI_THEME.accent : GUI_THEME.primary,
|
|
25529
|
+
fontFamily: "inherit",
|
|
25530
|
+
fontSize: 11,
|
|
25531
|
+
textAlign: "left",
|
|
25532
|
+
padding: "8px 10px",
|
|
25533
|
+
borderRadius: 6,
|
|
25534
|
+
cursor: "pointer"
|
|
25535
|
+
},
|
|
25536
|
+
children: [
|
|
25537
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: item.label }),
|
|
25538
|
+
selected ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: "\u2713" }) : null
|
|
25539
|
+
]
|
|
25540
|
+
},
|
|
25541
|
+
item.id
|
|
25542
|
+
);
|
|
25543
|
+
})
|
|
25290
25544
|
}
|
|
25291
|
-
)
|
|
25545
|
+
) : null
|
|
25292
25546
|
]
|
|
25293
25547
|
}
|
|
25294
25548
|
);
|
|
25295
25549
|
};
|
|
25296
25550
|
|
|
25297
25551
|
// source/gui/client/components/User.tsx
|
|
25298
|
-
var
|
|
25552
|
+
var import_jsx_runtime9 = __toESM(require_jsx_runtime(), 1);
|
|
25299
25553
|
var User = ({
|
|
25300
25554
|
user,
|
|
25301
25555
|
index: index2,
|
|
25302
25556
|
isFocus
|
|
25303
|
-
}) => /* @__PURE__ */ (0,
|
|
25557
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
25304
25558
|
"span",
|
|
25305
25559
|
{
|
|
25306
25560
|
title: user.name,
|
|
@@ -25325,19 +25579,20 @@ var User = ({
|
|
|
25325
25579
|
);
|
|
25326
25580
|
|
|
25327
25581
|
// source/version.ts
|
|
25328
|
-
var EPIQ_VERSION = "1.
|
|
25582
|
+
var EPIQ_VERSION = "1.5.0";
|
|
25329
25583
|
|
|
25330
25584
|
// source/gui/client/components/Header.tsx
|
|
25331
|
-
var
|
|
25585
|
+
var import_jsx_runtime10 = __toESM(require_jsx_runtime(), 1);
|
|
25332
25586
|
var Header = ({
|
|
25333
25587
|
state,
|
|
25334
|
-
|
|
25588
|
+
connection,
|
|
25589
|
+
onReconnect,
|
|
25335
25590
|
scrubbing,
|
|
25336
25591
|
syncStatus
|
|
25337
25592
|
}) => {
|
|
25338
|
-
const syncColor = syncStatus.status === "synced" ? GUI_THEME.green : syncStatus.status === "failed" ? GUI_THEME.red : GUI_THEME.accent;
|
|
25593
|
+
const syncColor = syncStatus.status === "synced" ? GUI_THEME.green : syncStatus.status === "failed" ? GUI_THEME.red : syncStatus.status === "offline" ? GUI_THEME.dim : GUI_THEME.accent;
|
|
25339
25594
|
const syncLabel = syncStatus.status === "failed" ? "-" : syncStatus.msg.toLowerCase();
|
|
25340
|
-
return /* @__PURE__ */ (0,
|
|
25595
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
25341
25596
|
Panel,
|
|
25342
25597
|
{
|
|
25343
25598
|
as: "header",
|
|
@@ -25351,7 +25606,7 @@ var Header = ({
|
|
|
25351
25606
|
borderRight: "none",
|
|
25352
25607
|
borderTop: "none"
|
|
25353
25608
|
},
|
|
25354
|
-
children: /* @__PURE__ */ (0,
|
|
25609
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
25355
25610
|
"div",
|
|
25356
25611
|
{
|
|
25357
25612
|
style: {
|
|
@@ -25362,7 +25617,7 @@ var Header = ({
|
|
|
25362
25617
|
justifyContent: "space-between"
|
|
25363
25618
|
},
|
|
25364
25619
|
children: [
|
|
25365
|
-
/* @__PURE__ */ (0,
|
|
25620
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
25366
25621
|
"div",
|
|
25367
25622
|
{
|
|
25368
25623
|
style: {
|
|
@@ -25373,7 +25628,7 @@ var Header = ({
|
|
|
25373
25628
|
children: ":epiq"
|
|
25374
25629
|
}
|
|
25375
25630
|
),
|
|
25376
|
-
/* @__PURE__ */ (0,
|
|
25631
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
25377
25632
|
"div",
|
|
25378
25633
|
{
|
|
25379
25634
|
style: {
|
|
@@ -25382,7 +25637,7 @@ var Header = ({
|
|
|
25382
25637
|
gap: 24
|
|
25383
25638
|
},
|
|
25384
25639
|
children: [
|
|
25385
|
-
/* @__PURE__ */ (0,
|
|
25640
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
25386
25641
|
"div",
|
|
25387
25642
|
{
|
|
25388
25643
|
style: {
|
|
@@ -25393,11 +25648,11 @@ var Header = ({
|
|
|
25393
25648
|
whiteSpace: "nowrap"
|
|
25394
25649
|
},
|
|
25395
25650
|
children: [
|
|
25396
|
-
scrubbing && /* @__PURE__ */ (0,
|
|
25397
|
-
/* @__PURE__ */ (0,
|
|
25398
|
-
/* @__PURE__ */ (0,
|
|
25651
|
+
scrubbing && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
|
|
25652
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { style: { color: GUI_THEME.accent, fontWeight: 700 }, children: "Read-only" }),
|
|
25653
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { style: { color: GUI_THEME.dim }, children: "|" })
|
|
25399
25654
|
] }),
|
|
25400
|
-
/* @__PURE__ */ (0,
|
|
25655
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
25401
25656
|
"span",
|
|
25402
25657
|
{
|
|
25403
25658
|
style: {
|
|
@@ -25407,7 +25662,7 @@ var Header = ({
|
|
|
25407
25662
|
justifyContent: "flex-end"
|
|
25408
25663
|
},
|
|
25409
25664
|
children: [
|
|
25410
|
-
/* @__PURE__ */ (0,
|
|
25665
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
25411
25666
|
"span",
|
|
25412
25667
|
{
|
|
25413
25668
|
title: syncStatus.status === "failed" ? syncStatus.msg : void 0,
|
|
@@ -25419,14 +25674,14 @@ var Header = ({
|
|
|
25419
25674
|
whiteSpace: "nowrap",
|
|
25420
25675
|
textAlign: "right"
|
|
25421
25676
|
},
|
|
25422
|
-
children: connected ? syncLabel : "-"
|
|
25677
|
+
children: connection === "connected" ? syncLabel : "-"
|
|
25423
25678
|
}
|
|
25424
25679
|
),
|
|
25425
|
-
/* @__PURE__ */ (0,
|
|
25680
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
25426
25681
|
"span",
|
|
25427
25682
|
{
|
|
25428
25683
|
style: {
|
|
25429
|
-
color: connected ? syncColor : GUI_THEME.dim,
|
|
25684
|
+
color: connection === "connected" ? syncColor : GUI_THEME.dim,
|
|
25430
25685
|
fontSize: 4
|
|
25431
25686
|
},
|
|
25432
25687
|
children: "\u25CF"
|
|
@@ -25435,18 +25690,31 @@ var Header = ({
|
|
|
25435
25690
|
]
|
|
25436
25691
|
}
|
|
25437
25692
|
),
|
|
25438
|
-
/* @__PURE__ */ (0,
|
|
25439
|
-
/* @__PURE__ */ (0,
|
|
25693
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { style: { color: GUI_THEME.dim }, children: "|" }),
|
|
25694
|
+
connection === "connected" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { style: { color: GUI_THEME.dim }, children: "connected" }) : connection === "connecting" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { style: { color: GUI_THEME.dim }, children: "connecting\u2026" }) : connection === "reconnecting" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
25440
25695
|
"span",
|
|
25441
25696
|
{
|
|
25442
|
-
|
|
25443
|
-
|
|
25444
|
-
|
|
25445
|
-
children: connected ? "connected" : "disconnected"
|
|
25697
|
+
"data-testid": "reconnecting",
|
|
25698
|
+
style: { color: GUI_THEME.accent },
|
|
25699
|
+
children: "reconnecting\u2026"
|
|
25446
25700
|
}
|
|
25701
|
+
) : (
|
|
25702
|
+
// The button alone says it: an offer to reconnect only makes
|
|
25703
|
+
// sense if the connection is gone.
|
|
25704
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
25705
|
+
Button,
|
|
25706
|
+
{
|
|
25707
|
+
"data-testid": "connection-lost",
|
|
25708
|
+
variant: "ghost",
|
|
25709
|
+
onClick: onReconnect,
|
|
25710
|
+
title: "Not connected \u2014 reconnect now",
|
|
25711
|
+
style: { color: GUI_THEME.red, fontSize: 10 },
|
|
25712
|
+
children: "reconnect"
|
|
25713
|
+
}
|
|
25714
|
+
)
|
|
25447
25715
|
),
|
|
25448
|
-
/* @__PURE__ */ (0,
|
|
25449
|
-
/* @__PURE__ */ (0,
|
|
25716
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { style: { color: GUI_THEME.dim }, children: "|" }),
|
|
25717
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
25450
25718
|
"span",
|
|
25451
25719
|
{
|
|
25452
25720
|
style: {
|
|
@@ -25458,7 +25726,7 @@ var Header = ({
|
|
|
25458
25726
|
]
|
|
25459
25727
|
}
|
|
25460
25728
|
),
|
|
25461
|
-
state?.user && /* @__PURE__ */ (0,
|
|
25729
|
+
state?.user && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(User, { user: state.user })
|
|
25462
25730
|
]
|
|
25463
25731
|
}
|
|
25464
25732
|
)
|
|
@@ -25470,14 +25738,14 @@ var Header = ({
|
|
|
25470
25738
|
};
|
|
25471
25739
|
|
|
25472
25740
|
// source/gui/client/components/IssueDetails.tsx
|
|
25473
|
-
var
|
|
25741
|
+
var import_react11 = __toESM(require_react(), 1);
|
|
25474
25742
|
|
|
25475
25743
|
// source/gui/client/components/ManageContributorsModal.tsx
|
|
25476
|
-
var
|
|
25744
|
+
var import_react6 = __toESM(require_react(), 1);
|
|
25477
25745
|
|
|
25478
25746
|
// source/gui/client/components/IconLock.tsx
|
|
25479
|
-
var
|
|
25480
|
-
var IconLock = ({ size = 13 }) => /* @__PURE__ */ (0,
|
|
25747
|
+
var import_jsx_runtime11 = __toESM(require_jsx_runtime(), 1);
|
|
25748
|
+
var IconLock = ({ size = 13 }) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
25481
25749
|
"svg",
|
|
25482
25750
|
{
|
|
25483
25751
|
width: size,
|
|
@@ -25490,16 +25758,16 @@ var IconLock = ({ size = 13 }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
|
25490
25758
|
strokeLinejoin: "round",
|
|
25491
25759
|
"aria-hidden": "true",
|
|
25492
25760
|
children: [
|
|
25493
|
-
/* @__PURE__ */ (0,
|
|
25494
|
-
/* @__PURE__ */ (0,
|
|
25495
|
-
/* @__PURE__ */ (0,
|
|
25761
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("rect", { x: "3", y: "11", width: "18", height: "11", rx: "2", ry: "2" }),
|
|
25762
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { d: "M7 11V7a5 5 0 0 1 10 0v4" }),
|
|
25763
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("circle", { cx: "12", cy: "16.5", r: "2.1", fill: "currentColor", stroke: "none" })
|
|
25496
25764
|
]
|
|
25497
25765
|
}
|
|
25498
25766
|
);
|
|
25499
25767
|
|
|
25500
25768
|
// source/gui/client/components/IconTrash.tsx
|
|
25501
|
-
var
|
|
25502
|
-
var IconTrash = ({ size = 14 }) => /* @__PURE__ */ (0,
|
|
25769
|
+
var import_jsx_runtime12 = __toESM(require_jsx_runtime(), 1);
|
|
25770
|
+
var IconTrash = ({ size = 14 }) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
25503
25771
|
"svg",
|
|
25504
25772
|
{
|
|
25505
25773
|
width: size,
|
|
@@ -25512,24 +25780,24 @@ var IconTrash = ({ size = 14 }) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)
|
|
|
25512
25780
|
strokeLinejoin: "round",
|
|
25513
25781
|
"aria-hidden": "true",
|
|
25514
25782
|
children: [
|
|
25515
|
-
/* @__PURE__ */ (0,
|
|
25516
|
-
/* @__PURE__ */ (0,
|
|
25517
|
-
/* @__PURE__ */ (0,
|
|
25518
|
-
/* @__PURE__ */ (0,
|
|
25783
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("polyline", { points: "3 6 5 6 21 6" }),
|
|
25784
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" }),
|
|
25785
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("line", { x1: "10", y1: "11", x2: "10", y2: "17" }),
|
|
25786
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("line", { x1: "14", y1: "11", x2: "14", y2: "17" })
|
|
25519
25787
|
]
|
|
25520
25788
|
}
|
|
25521
25789
|
);
|
|
25522
25790
|
|
|
25523
25791
|
// source/gui/client/components/ManageContributorsModal.tsx
|
|
25524
|
-
var
|
|
25792
|
+
var import_jsx_runtime13 = __toESM(require_jsx_runtime(), 1);
|
|
25525
25793
|
var ManageContributorsModal = ({
|
|
25526
25794
|
contributors,
|
|
25527
25795
|
onRemove,
|
|
25528
25796
|
onClose
|
|
25529
25797
|
}) => {
|
|
25530
|
-
const [armedId, setArmedId] = (0,
|
|
25798
|
+
const [armedId, setArmedId] = (0, import_react6.useState)(null);
|
|
25531
25799
|
const sorted = [...contributors].sort((a, b) => a.name.localeCompare(b.name));
|
|
25532
|
-
return /* @__PURE__ */ (0,
|
|
25800
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
25533
25801
|
"div",
|
|
25534
25802
|
{
|
|
25535
25803
|
style: {
|
|
@@ -25543,7 +25811,7 @@ var ManageContributorsModal = ({
|
|
|
25543
25811
|
zIndex: 1e3
|
|
25544
25812
|
},
|
|
25545
25813
|
onMouseDown: onClose,
|
|
25546
|
-
children: /* @__PURE__ */ (0,
|
|
25814
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
25547
25815
|
"div",
|
|
25548
25816
|
{
|
|
25549
25817
|
onMouseDown: (event) => event.stopPropagation(),
|
|
@@ -25559,7 +25827,7 @@ var ManageContributorsModal = ({
|
|
|
25559
25827
|
gap: 14
|
|
25560
25828
|
},
|
|
25561
25829
|
children: [
|
|
25562
|
-
/* @__PURE__ */ (0,
|
|
25830
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
25563
25831
|
"div",
|
|
25564
25832
|
{
|
|
25565
25833
|
style: {
|
|
@@ -25571,8 +25839,8 @@ var ManageContributorsModal = ({
|
|
|
25571
25839
|
children: "Manage external contributors"
|
|
25572
25840
|
}
|
|
25573
25841
|
),
|
|
25574
|
-
/* @__PURE__ */ (0,
|
|
25575
|
-
/* @__PURE__ */ (0,
|
|
25842
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { fontSize: 12, color: GUI_THEME.secondary }, children: "Remove contributors from the suggestion lists. Locked ones have contributed, so their name is in the immutable log either way." }),
|
|
25843
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
25576
25844
|
"div",
|
|
25577
25845
|
{
|
|
25578
25846
|
style: {
|
|
@@ -25585,7 +25853,7 @@ var ManageContributorsModal = ({
|
|
|
25585
25853
|
children: sorted.map((contributor) => {
|
|
25586
25854
|
const locked = contributor.hasAuthoredAnywhere;
|
|
25587
25855
|
const armed = armedId === contributor.id;
|
|
25588
|
-
return /* @__PURE__ */ (0,
|
|
25856
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
25589
25857
|
"div",
|
|
25590
25858
|
{
|
|
25591
25859
|
style: {
|
|
@@ -25597,7 +25865,7 @@ var ManageContributorsModal = ({
|
|
|
25597
25865
|
borderRadius: 6
|
|
25598
25866
|
},
|
|
25599
25867
|
children: [
|
|
25600
|
-
/* @__PURE__ */ (0,
|
|
25868
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
25601
25869
|
"span",
|
|
25602
25870
|
{
|
|
25603
25871
|
style: {
|
|
@@ -25611,7 +25879,7 @@ var ManageContributorsModal = ({
|
|
|
25611
25879
|
]
|
|
25612
25880
|
}
|
|
25613
25881
|
),
|
|
25614
|
-
locked ? /* @__PURE__ */ (0,
|
|
25882
|
+
locked ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
25615
25883
|
"span",
|
|
25616
25884
|
{
|
|
25617
25885
|
title: "Has contributed \u2014 their name is in the immutable log either way",
|
|
@@ -25623,9 +25891,9 @@ var ManageContributorsModal = ({
|
|
|
25623
25891
|
// removable rows keep the same height.
|
|
25624
25892
|
padding: "3px 6px"
|
|
25625
25893
|
},
|
|
25626
|
-
children: /* @__PURE__ */ (0,
|
|
25894
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(IconLock, {})
|
|
25627
25895
|
}
|
|
25628
|
-
) : contributor.isRemoved ? /* @__PURE__ */ (0,
|
|
25896
|
+
) : contributor.isRemoved ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: { color: GUI_THEME.dim, fontSize: 10 }, children: "removed" }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
25629
25897
|
Button,
|
|
25630
25898
|
{
|
|
25631
25899
|
variant: "ghost",
|
|
@@ -25643,8 +25911,8 @@ var ManageContributorsModal = ({
|
|
|
25643
25911
|
borderColor: armed ? GUI_THEME.red : void 0
|
|
25644
25912
|
},
|
|
25645
25913
|
children: [
|
|
25646
|
-
armed && /* @__PURE__ */ (0,
|
|
25647
|
-
/* @__PURE__ */ (0,
|
|
25914
|
+
armed && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: { fontSize: 10 }, children: "confirm" }),
|
|
25915
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(IconTrash, {})
|
|
25648
25916
|
]
|
|
25649
25917
|
}
|
|
25650
25918
|
)
|
|
@@ -25655,7 +25923,7 @@ var ManageContributorsModal = ({
|
|
|
25655
25923
|
})
|
|
25656
25924
|
}
|
|
25657
25925
|
),
|
|
25658
|
-
/* @__PURE__ */ (0,
|
|
25926
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { display: "flex", justifyContent: "flex-end" }, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Button, { variant: "ghost", onClick: onClose, children: "close" }) })
|
|
25659
25927
|
]
|
|
25660
25928
|
}
|
|
25661
25929
|
)
|
|
@@ -25664,8 +25932,8 @@ var ManageContributorsModal = ({
|
|
|
25664
25932
|
};
|
|
25665
25933
|
|
|
25666
25934
|
// source/gui/client/components/CopyRef.tsx
|
|
25667
|
-
var
|
|
25668
|
-
var
|
|
25935
|
+
var import_react7 = __toESM(require_react(), 1);
|
|
25936
|
+
var import_jsx_runtime14 = __toESM(require_jsx_runtime(), 1);
|
|
25669
25937
|
var copyToClipboard = async (value) => {
|
|
25670
25938
|
try {
|
|
25671
25939
|
await navigator.clipboard.writeText(value);
|
|
@@ -25675,12 +25943,12 @@ var copyToClipboard = async (value) => {
|
|
|
25675
25943
|
}
|
|
25676
25944
|
};
|
|
25677
25945
|
var CopyRef = ({ refValue }) => {
|
|
25678
|
-
const [copied, setCopied] = (0,
|
|
25679
|
-
const resetTimer = (0,
|
|
25946
|
+
const [copied, setCopied] = (0, import_react7.useState)(false);
|
|
25947
|
+
const resetTimer = (0, import_react7.useRef)(
|
|
25680
25948
|
void 0
|
|
25681
25949
|
);
|
|
25682
|
-
(0,
|
|
25683
|
-
return /* @__PURE__ */ (0,
|
|
25950
|
+
(0, import_react7.useEffect)(() => () => clearTimeout(resetTimer.current), []);
|
|
25951
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
25684
25952
|
"button",
|
|
25685
25953
|
{
|
|
25686
25954
|
type: "button",
|
|
@@ -25715,8 +25983,8 @@ var CopyRef = ({ refValue }) => {
|
|
|
25715
25983
|
};
|
|
25716
25984
|
|
|
25717
25985
|
// source/gui/client/components/FormHeader.tsx
|
|
25718
|
-
var
|
|
25719
|
-
var FormHeader = ({ children }) => /* @__PURE__ */ (0,
|
|
25986
|
+
var import_jsx_runtime15 = __toESM(require_jsx_runtime(), 1);
|
|
25987
|
+
var FormHeader = ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
25720
25988
|
"div",
|
|
25721
25989
|
{
|
|
25722
25990
|
style: {
|
|
@@ -25731,8 +25999,8 @@ var FormHeader = ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)
|
|
|
25731
25999
|
);
|
|
25732
26000
|
|
|
25733
26001
|
// source/gui/client/components/FormPrimitives.tsx
|
|
25734
|
-
var
|
|
25735
|
-
var Input = (props) => /* @__PURE__ */ (0,
|
|
26002
|
+
var import_jsx_runtime16 = __toESM(require_jsx_runtime(), 1);
|
|
26003
|
+
var Input = (props) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
25736
26004
|
"input",
|
|
25737
26005
|
{
|
|
25738
26006
|
...props,
|
|
@@ -25750,7 +26018,7 @@ var Input = (props) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
|
25750
26018
|
}
|
|
25751
26019
|
}
|
|
25752
26020
|
);
|
|
25753
|
-
var Textarea = (props) => /* @__PURE__ */ (0,
|
|
26021
|
+
var Textarea = (props) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
25754
26022
|
"textarea",
|
|
25755
26023
|
{
|
|
25756
26024
|
maxLength: props.maxLength ?? 1500,
|
|
@@ -25772,28 +26040,28 @@ var Textarea = (props) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
|
25772
26040
|
}
|
|
25773
26041
|
}
|
|
25774
26042
|
);
|
|
25775
|
-
var ActionRow = ({ children }) => /* @__PURE__ */ (0,
|
|
26043
|
+
var ActionRow = ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
25776
26044
|
"div",
|
|
25777
26045
|
{
|
|
25778
26046
|
style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 8 },
|
|
25779
26047
|
children
|
|
25780
26048
|
}
|
|
25781
26049
|
);
|
|
25782
|
-
var AddRow = ({ children }) => /* @__PURE__ */ (0,
|
|
25783
|
-
var ChipRow = ({ children }) => /* @__PURE__ */ (0,
|
|
25784
|
-
var Empty = ({ children }) => /* @__PURE__ */ (0,
|
|
26050
|
+
var AddRow = ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { style: { display: "flex", gap: 8, marginTop: 10 }, children });
|
|
26051
|
+
var ChipRow = ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { style: { display: "flex", gap: 8, flexWrap: "wrap", marginTop: 10 }, children });
|
|
26052
|
+
var Empty = ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { style: { display: "inline-block", marginTop: 8, color: GUI_THEME.dim }, children });
|
|
25785
26053
|
|
|
25786
26054
|
// source/gui/client/components/IssueAttachments.tsx
|
|
25787
|
-
var
|
|
26055
|
+
var import_react8 = __toESM(require_react(), 1);
|
|
25788
26056
|
|
|
25789
26057
|
// source/gui/client/components/Section.tsx
|
|
25790
|
-
var
|
|
26058
|
+
var import_jsx_runtime17 = __toESM(require_jsx_runtime(), 1);
|
|
25791
26059
|
var Section = ({
|
|
25792
26060
|
title,
|
|
25793
26061
|
action,
|
|
25794
26062
|
children,
|
|
25795
26063
|
first = false
|
|
25796
|
-
}) => /* @__PURE__ */ (0,
|
|
26064
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
25797
26065
|
"section",
|
|
25798
26066
|
{
|
|
25799
26067
|
style: {
|
|
@@ -25801,7 +26069,7 @@ var Section = ({
|
|
|
25801
26069
|
borderTop: first ? "none" : `1px solid ${GUI_THEME.line}`
|
|
25802
26070
|
},
|
|
25803
26071
|
children: [
|
|
25804
|
-
/* @__PURE__ */ (0,
|
|
26072
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
25805
26073
|
"div",
|
|
25806
26074
|
{
|
|
25807
26075
|
style: {
|
|
@@ -25811,7 +26079,7 @@ var Section = ({
|
|
|
25811
26079
|
gap: 12
|
|
25812
26080
|
},
|
|
25813
26081
|
children: [
|
|
25814
|
-
/* @__PURE__ */ (0,
|
|
26082
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
25815
26083
|
"span",
|
|
25816
26084
|
{
|
|
25817
26085
|
style: {
|
|
@@ -25833,7 +26101,7 @@ var Section = ({
|
|
|
25833
26101
|
);
|
|
25834
26102
|
|
|
25835
26103
|
// source/gui/client/components/IssueAttachments.tsx
|
|
25836
|
-
var
|
|
26104
|
+
var import_jsx_runtime18 = __toESM(require_jsx_runtime(), 1);
|
|
25837
26105
|
var IssueAttachments = ({
|
|
25838
26106
|
issueId,
|
|
25839
26107
|
readonly,
|
|
@@ -25842,15 +26110,15 @@ var IssueAttachments = ({
|
|
|
25842
26110
|
onUploadFiles,
|
|
25843
26111
|
onDeleteAttachment
|
|
25844
26112
|
}) => {
|
|
25845
|
-
const [dragging, setDragging] = (0,
|
|
25846
|
-
const [lightbox, setLightbox] = (0,
|
|
25847
|
-
const [broken, setBroken] = (0,
|
|
25848
|
-
(0,
|
|
26113
|
+
const [dragging, setDragging] = (0, import_react8.useState)(false);
|
|
26114
|
+
const [lightbox, setLightbox] = (0, import_react8.useState)(null);
|
|
26115
|
+
const [broken, setBroken] = (0, import_react8.useState)({});
|
|
26116
|
+
(0, import_react8.useEffect)(() => {
|
|
25849
26117
|
setLightbox(null);
|
|
25850
26118
|
setDragging(false);
|
|
25851
26119
|
setBroken({});
|
|
25852
26120
|
}, [issueId]);
|
|
25853
|
-
(0,
|
|
26121
|
+
(0, import_react8.useEffect)(() => {
|
|
25854
26122
|
if (!lightbox) return;
|
|
25855
26123
|
const onKeyDown = (event) => {
|
|
25856
26124
|
if (event.key === "Escape") setLightbox(null);
|
|
@@ -25868,12 +26136,12 @@ var IssueAttachments = ({
|
|
|
25868
26136
|
);
|
|
25869
26137
|
if (files.length > 0) onUploadFiles?.(issueId, files);
|
|
25870
26138
|
};
|
|
25871
|
-
return /* @__PURE__ */ (0,
|
|
26139
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
25872
26140
|
Section,
|
|
25873
26141
|
{
|
|
25874
26142
|
title: `Attachments${attachments.length ? ` (${attachments.length})` : ""}`,
|
|
25875
26143
|
children: [
|
|
25876
|
-
/* @__PURE__ */ (0,
|
|
26144
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
25877
26145
|
"div",
|
|
25878
26146
|
{
|
|
25879
26147
|
onDragOver: (event) => {
|
|
@@ -25891,7 +26159,7 @@ var IssueAttachments = ({
|
|
|
25891
26159
|
transition: "padding 0.12s ease, border-color 0.12s ease"
|
|
25892
26160
|
},
|
|
25893
26161
|
children: [
|
|
25894
|
-
attachments.length === 0 ? /* @__PURE__ */ (0,
|
|
26162
|
+
attachments.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Empty, { children: canUpload ? "No attachments \u2014 drop an image here" : "No attachments" }) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
25895
26163
|
"div",
|
|
25896
26164
|
{
|
|
25897
26165
|
style: {
|
|
@@ -25899,12 +26167,12 @@ var IssueAttachments = ({
|
|
|
25899
26167
|
flexWrap: "wrap",
|
|
25900
26168
|
gap: 8
|
|
25901
26169
|
},
|
|
25902
|
-
children: attachments.map((attachment) => /* @__PURE__ */ (0,
|
|
26170
|
+
children: attachments.map((attachment) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
25903
26171
|
"div",
|
|
25904
26172
|
{
|
|
25905
26173
|
style: { position: "relative", width: 72, height: 72 },
|
|
25906
26174
|
children: [
|
|
25907
|
-
/* @__PURE__ */ (0,
|
|
26175
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
25908
26176
|
"button",
|
|
25909
26177
|
{
|
|
25910
26178
|
type: "button",
|
|
@@ -25924,7 +26192,7 @@ var IssueAttachments = ({
|
|
|
25924
26192
|
width: "100%",
|
|
25925
26193
|
height: "100%"
|
|
25926
26194
|
},
|
|
25927
|
-
children: broken[attachment.id] ? /* @__PURE__ */ (0,
|
|
26195
|
+
children: broken[attachment.id] ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
25928
26196
|
"span",
|
|
25929
26197
|
{
|
|
25930
26198
|
title: "Attachment unavailable (missing, corrupt, or over the size cap)",
|
|
@@ -25941,7 +26209,7 @@ var IssueAttachments = ({
|
|
|
25941
26209
|
},
|
|
25942
26210
|
children: "unavailable"
|
|
25943
26211
|
}
|
|
25944
|
-
) : /* @__PURE__ */ (0,
|
|
26212
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
25945
26213
|
"img",
|
|
25946
26214
|
{
|
|
25947
26215
|
src: `/media/${attachment.fileName}`,
|
|
@@ -25958,7 +26226,7 @@ var IssueAttachments = ({
|
|
|
25958
26226
|
)
|
|
25959
26227
|
}
|
|
25960
26228
|
),
|
|
25961
|
-
attachment.canDelete && !readonly && onDeleteAttachment && /* @__PURE__ */ (0,
|
|
26229
|
+
attachment.canDelete && !readonly && onDeleteAttachment && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
25962
26230
|
"button",
|
|
25963
26231
|
{
|
|
25964
26232
|
type: "button",
|
|
@@ -25988,7 +26256,7 @@ var IssueAttachments = ({
|
|
|
25988
26256
|
))
|
|
25989
26257
|
}
|
|
25990
26258
|
),
|
|
25991
|
-
canUpload && attachments.length > 0 && /* @__PURE__ */ (0,
|
|
26259
|
+
canUpload && attachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
25992
26260
|
"div",
|
|
25993
26261
|
{
|
|
25994
26262
|
style: {
|
|
@@ -25999,7 +26267,7 @@ var IssueAttachments = ({
|
|
|
25999
26267
|
children: "drop an image to attach"
|
|
26000
26268
|
}
|
|
26001
26269
|
),
|
|
26002
|
-
uploadStatus.state === "uploading" && /* @__PURE__ */ (0,
|
|
26270
|
+
uploadStatus.state === "uploading" && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
26003
26271
|
"div",
|
|
26004
26272
|
{
|
|
26005
26273
|
style: {
|
|
@@ -26014,7 +26282,7 @@ var IssueAttachments = ({
|
|
|
26014
26282
|
]
|
|
26015
26283
|
}
|
|
26016
26284
|
),
|
|
26017
|
-
uploadStatus.state === "error" && /* @__PURE__ */ (0,
|
|
26285
|
+
uploadStatus.state === "error" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
26018
26286
|
"div",
|
|
26019
26287
|
{
|
|
26020
26288
|
style: {
|
|
@@ -26028,7 +26296,7 @@ var IssueAttachments = ({
|
|
|
26028
26296
|
]
|
|
26029
26297
|
}
|
|
26030
26298
|
),
|
|
26031
|
-
lightbox && /* @__PURE__ */ (0,
|
|
26299
|
+
lightbox && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
26032
26300
|
"div",
|
|
26033
26301
|
{
|
|
26034
26302
|
onClick: () => setLightbox(null),
|
|
@@ -26045,7 +26313,7 @@ var IssueAttachments = ({
|
|
|
26045
26313
|
cursor: "zoom-out"
|
|
26046
26314
|
},
|
|
26047
26315
|
children: [
|
|
26048
|
-
/* @__PURE__ */ (0,
|
|
26316
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
26049
26317
|
"img",
|
|
26050
26318
|
{
|
|
26051
26319
|
src: `/media/${lightbox.fileName}`,
|
|
@@ -26058,7 +26326,7 @@ var IssueAttachments = ({
|
|
|
26058
26326
|
}
|
|
26059
26327
|
}
|
|
26060
26328
|
),
|
|
26061
|
-
/* @__PURE__ */ (0,
|
|
26329
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { color: GUI_THEME.secondary, fontSize: 11 }, children: [
|
|
26062
26330
|
lightbox.name,
|
|
26063
26331
|
" \xB7 ",
|
|
26064
26332
|
Math.max(1, Math.round(lightbox.bytes / 1024)),
|
|
@@ -26074,7 +26342,7 @@ var IssueAttachments = ({
|
|
|
26074
26342
|
};
|
|
26075
26343
|
|
|
26076
26344
|
// source/gui/client/components/IssueComments.tsx
|
|
26077
|
-
var
|
|
26345
|
+
var import_react10 = __toESM(require_react(), 1);
|
|
26078
26346
|
|
|
26079
26347
|
// source/gui/client/lib/gui-format.helper.ts
|
|
26080
26348
|
var timeAgo = (timestampMs) => {
|
|
@@ -26094,6 +26362,10 @@ var timeAgo = (timestampMs) => {
|
|
|
26094
26362
|
}
|
|
26095
26363
|
return "just now";
|
|
26096
26364
|
};
|
|
26365
|
+
var formatAbsolute = (timestampMs) => new Date(timestampMs).toLocaleString(void 0, {
|
|
26366
|
+
dateStyle: "medium",
|
|
26367
|
+
timeStyle: "short"
|
|
26368
|
+
});
|
|
26097
26369
|
|
|
26098
26370
|
// node_modules/devlop/lib/default.js
|
|
26099
26371
|
function ok() {
|
|
@@ -27730,11 +28002,11 @@ function addChildren(props, children) {
|
|
|
27730
28002
|
}
|
|
27731
28003
|
}
|
|
27732
28004
|
}
|
|
27733
|
-
function productionCreate(_,
|
|
28005
|
+
function productionCreate(_, jsx42, jsxs30) {
|
|
27734
28006
|
return create2;
|
|
27735
28007
|
function create2(_2, type, props, key) {
|
|
27736
28008
|
const isStaticChildren = Array.isArray(props.children);
|
|
27737
|
-
const fn = isStaticChildren ?
|
|
28009
|
+
const fn = isStaticChildren ? jsxs30 : jsx42;
|
|
27738
28010
|
return key ? fn(type, props, key) : fn(type, props);
|
|
27739
28011
|
}
|
|
27740
28012
|
}
|
|
@@ -27979,8 +28251,8 @@ var urlAttributes = {
|
|
|
27979
28251
|
};
|
|
27980
28252
|
|
|
27981
28253
|
// node_modules/react-markdown/lib/index.js
|
|
27982
|
-
var
|
|
27983
|
-
var
|
|
28254
|
+
var import_jsx_runtime19 = __toESM(require_jsx_runtime(), 1);
|
|
28255
|
+
var import_react9 = __toESM(require_react(), 1);
|
|
27984
28256
|
|
|
27985
28257
|
// node_modules/mdast-util-to-string/lib/index.js
|
|
27986
28258
|
var emptyOptions2 = {};
|
|
@@ -35654,11 +35926,11 @@ function post(tree, options) {
|
|
|
35654
35926
|
}
|
|
35655
35927
|
visit(tree, transform);
|
|
35656
35928
|
return toJsxRuntime(tree, {
|
|
35657
|
-
Fragment:
|
|
35929
|
+
Fragment: import_jsx_runtime19.Fragment,
|
|
35658
35930
|
components: components2,
|
|
35659
35931
|
ignoreInvalidStyle: true,
|
|
35660
|
-
jsx:
|
|
35661
|
-
jsxs:
|
|
35932
|
+
jsx: import_jsx_runtime19.jsx,
|
|
35933
|
+
jsxs: import_jsx_runtime19.jsxs,
|
|
35662
35934
|
passKeys: true,
|
|
35663
35935
|
passNode: true
|
|
35664
35936
|
});
|
|
@@ -38781,16 +39053,16 @@ function remarkGfm(options) {
|
|
|
38781
39053
|
}
|
|
38782
39054
|
|
|
38783
39055
|
// source/gui/client/components/MarkdownContent.tsx
|
|
38784
|
-
var
|
|
39056
|
+
var import_jsx_runtime20 = __toESM(require_jsx_runtime(), 1);
|
|
38785
39057
|
var components = {
|
|
38786
|
-
p: ({ children }) => /* @__PURE__ */ (0,
|
|
38787
|
-
ul: ({ children }) => /* @__PURE__ */ (0,
|
|
38788
|
-
ol: ({ children }) => /* @__PURE__ */ (0,
|
|
38789
|
-
li: ({ children }) => /* @__PURE__ */ (0,
|
|
38790
|
-
h1: ({ children }) => /* @__PURE__ */ (0,
|
|
38791
|
-
h2: ({ children }) => /* @__PURE__ */ (0,
|
|
38792
|
-
h3: ({ children }) => /* @__PURE__ */ (0,
|
|
38793
|
-
a: ({ children, href }) => /* @__PURE__ */ (0,
|
|
39058
|
+
p: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { style: { margin: "0 0 14px" }, children }),
|
|
39059
|
+
ul: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("ul", { style: { margin: "0 0 14px", paddingLeft: 20 }, children }),
|
|
39060
|
+
ol: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("ol", { style: { margin: "0 0 14px", paddingLeft: 20 }, children }),
|
|
39061
|
+
li: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("li", { style: { margin: "2px 0" }, children }),
|
|
39062
|
+
h1: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h1", { style: { fontSize: 16, margin: "0 0 14px" }, children }),
|
|
39063
|
+
h2: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h2", { style: { fontSize: 14, margin: "0 0 14px" }, children }),
|
|
39064
|
+
h3: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h3", { style: { fontSize: 13, margin: "0 0 14px" }, children }),
|
|
39065
|
+
a: ({ children, href }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
38794
39066
|
"a",
|
|
38795
39067
|
{
|
|
38796
39068
|
href,
|
|
@@ -38800,7 +39072,7 @@ var components = {
|
|
|
38800
39072
|
children
|
|
38801
39073
|
}
|
|
38802
39074
|
),
|
|
38803
|
-
blockquote: ({ children }) => /* @__PURE__ */ (0,
|
|
39075
|
+
blockquote: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
38804
39076
|
"blockquote",
|
|
38805
39077
|
{
|
|
38806
39078
|
style: {
|
|
@@ -38814,7 +39086,7 @@ var components = {
|
|
|
38814
39086
|
),
|
|
38815
39087
|
code: ({ children, className }) => {
|
|
38816
39088
|
const isBlock = Boolean(className);
|
|
38817
|
-
return /* @__PURE__ */ (0,
|
|
39089
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
38818
39090
|
"code",
|
|
38819
39091
|
{
|
|
38820
39092
|
style: {
|
|
@@ -38831,8 +39103,8 @@ var components = {
|
|
|
38831
39103
|
}
|
|
38832
39104
|
);
|
|
38833
39105
|
},
|
|
38834
|
-
pre: ({ children }) => /* @__PURE__ */ (0,
|
|
38835
|
-
hr: () => /* @__PURE__ */ (0,
|
|
39106
|
+
pre: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("pre", { style: { margin: "0 0 14px" }, children }),
|
|
39107
|
+
hr: () => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
38836
39108
|
"hr",
|
|
38837
39109
|
{
|
|
38838
39110
|
style: {
|
|
@@ -38846,7 +39118,7 @@ var components = {
|
|
|
38846
39118
|
var MarkdownContent = ({
|
|
38847
39119
|
content: content3,
|
|
38848
39120
|
softBreaks = false
|
|
38849
|
-
}) => /* @__PURE__ */ (0,
|
|
39121
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
38850
39122
|
"div",
|
|
38851
39123
|
{
|
|
38852
39124
|
style: {
|
|
@@ -38859,7 +39131,7 @@ var MarkdownContent = ({
|
|
|
38859
39131
|
// collapsing, so the container doesn't end in dead whitespace.
|
|
38860
39132
|
marginBottom: -14
|
|
38861
39133
|
},
|
|
38862
|
-
children: /* @__PURE__ */ (0,
|
|
39134
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
38863
39135
|
Markdown,
|
|
38864
39136
|
{
|
|
38865
39137
|
remarkPlugins: softBreaks ? [remarkGfm, remarkBreaks] : [remarkGfm],
|
|
@@ -38874,7 +39146,7 @@ var MarkdownContent = ({
|
|
|
38874
39146
|
var MAX_COMMENT_LENGTH = 4e3;
|
|
38875
39147
|
|
|
38876
39148
|
// source/gui/client/components/IssueComments.tsx
|
|
38877
|
-
var
|
|
39149
|
+
var import_jsx_runtime21 = __toESM(require_jsx_runtime(), 1);
|
|
38878
39150
|
var IssueComments = ({
|
|
38879
39151
|
whoAmI,
|
|
38880
39152
|
issueId,
|
|
@@ -38883,7 +39155,7 @@ var IssueComments = ({
|
|
|
38883
39155
|
onAddComment,
|
|
38884
39156
|
onDeleteComment
|
|
38885
39157
|
}) => {
|
|
38886
|
-
const [body, setBody] = (0,
|
|
39158
|
+
const [body, setBody] = (0, import_react10.useState)("");
|
|
38887
39159
|
const length = body.trim().length;
|
|
38888
39160
|
const tooLong = length > MAX_COMMENT_LENGTH;
|
|
38889
39161
|
const addComment = () => {
|
|
@@ -38892,8 +39164,8 @@ var IssueComments = ({
|
|
|
38892
39164
|
onAddComment?.(issueId, nextBody);
|
|
38893
39165
|
setBody("");
|
|
38894
39166
|
};
|
|
38895
|
-
return /* @__PURE__ */ (0,
|
|
38896
|
-
comments.length === 0 ? /* @__PURE__ */ (0,
|
|
39167
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
|
|
39168
|
+
comments.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Empty, { children: "No comments" }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: 12 }, children: comments.map((comment) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
38897
39169
|
"div",
|
|
38898
39170
|
{
|
|
38899
39171
|
style: {
|
|
@@ -38903,7 +39175,7 @@ var IssueComments = ({
|
|
|
38903
39175
|
background: GUI_THEME.tertiary
|
|
38904
39176
|
},
|
|
38905
39177
|
children: [
|
|
38906
|
-
/* @__PURE__ */ (0,
|
|
39178
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
38907
39179
|
"div",
|
|
38908
39180
|
{
|
|
38909
39181
|
style: {
|
|
@@ -38913,15 +39185,15 @@ var IssueComments = ({
|
|
|
38913
39185
|
marginBottom: 8
|
|
38914
39186
|
},
|
|
38915
39187
|
children: [
|
|
38916
|
-
/* @__PURE__ */ (0,
|
|
39188
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { color: GUI_THEME.secondary, fontSize: 11 }, children: [
|
|
38917
39189
|
comment.author.name ?? "unknown",
|
|
38918
|
-
comment.createdAt && /* @__PURE__ */ (0,
|
|
39190
|
+
comment.createdAt && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { style: { color: GUI_THEME.dim2 }, children: [
|
|
38919
39191
|
" ",
|
|
38920
39192
|
"\xB7 ",
|
|
38921
39193
|
timeAgo(comment.createdAt)
|
|
38922
39194
|
] })
|
|
38923
39195
|
] }),
|
|
38924
|
-
!readonly && comment.author.id === whoAmI.id && onDeleteComment && /* @__PURE__ */ (0,
|
|
39196
|
+
!readonly && comment.author.id === whoAmI.id && onDeleteComment && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
38925
39197
|
Button,
|
|
38926
39198
|
{
|
|
38927
39199
|
variant: "ghost",
|
|
@@ -38936,13 +39208,13 @@ var IssueComments = ({
|
|
|
38936
39208
|
]
|
|
38937
39209
|
}
|
|
38938
39210
|
),
|
|
38939
|
-
/* @__PURE__ */ (0,
|
|
39211
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(MarkdownContent, { content: comment.body, softBreaks: true })
|
|
38940
39212
|
]
|
|
38941
39213
|
},
|
|
38942
39214
|
comment.id
|
|
38943
39215
|
)) }),
|
|
38944
|
-
!readonly && /* @__PURE__ */ (0,
|
|
38945
|
-
/* @__PURE__ */ (0,
|
|
39216
|
+
!readonly && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginTop: 20 }, children: [
|
|
39217
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
38946
39218
|
Textarea,
|
|
38947
39219
|
{
|
|
38948
39220
|
maxLength: Number.MAX_SAFE_INTEGER,
|
|
@@ -38962,8 +39234,8 @@ var IssueComments = ({
|
|
|
38962
39234
|
}
|
|
38963
39235
|
}
|
|
38964
39236
|
),
|
|
38965
|
-
/* @__PURE__ */ (0,
|
|
38966
|
-
length > MAX_COMMENT_LENGTH / 2 && /* @__PURE__ */ (0,
|
|
39237
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(ActionRow, { children: [
|
|
39238
|
+
length > MAX_COMMENT_LENGTH / 2 && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
38967
39239
|
"span",
|
|
38968
39240
|
{
|
|
38969
39241
|
style: {
|
|
@@ -38974,19 +39246,19 @@ var IssueComments = ({
|
|
|
38974
39246
|
children: tooLong ? `${length - MAX_COMMENT_LENGTH} over the limit` : `${MAX_COMMENT_LENGTH - length} left`
|
|
38975
39247
|
}
|
|
38976
39248
|
),
|
|
38977
|
-
/* @__PURE__ */ (0,
|
|
39249
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Button, { disabled: tooLong, onClick: addComment, children: "comment" })
|
|
38978
39250
|
] })
|
|
38979
39251
|
] })
|
|
38980
39252
|
] });
|
|
38981
39253
|
};
|
|
38982
39254
|
|
|
38983
39255
|
// source/gui/client/components/Tabs.tsx
|
|
38984
|
-
var
|
|
39256
|
+
var import_jsx_runtime22 = __toESM(require_jsx_runtime(), 1);
|
|
38985
39257
|
var Tabs = ({
|
|
38986
39258
|
activeTab,
|
|
38987
39259
|
tabs,
|
|
38988
39260
|
onChange
|
|
38989
|
-
}) => /* @__PURE__ */ (0,
|
|
39261
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
38990
39262
|
"div",
|
|
38991
39263
|
{
|
|
38992
39264
|
style: {
|
|
@@ -38997,7 +39269,7 @@ var Tabs = ({
|
|
|
38997
39269
|
},
|
|
38998
39270
|
children: tabs.map((tab2) => {
|
|
38999
39271
|
const active = tab2.id === activeTab;
|
|
39000
|
-
return /* @__PURE__ */ (0,
|
|
39272
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
39001
39273
|
"button",
|
|
39002
39274
|
{
|
|
39003
39275
|
type: "button",
|
|
@@ -39015,7 +39287,7 @@ var Tabs = ({
|
|
|
39015
39287
|
},
|
|
39016
39288
|
children: [
|
|
39017
39289
|
tab2.label,
|
|
39018
|
-
typeof tab2.count === "number" && /* @__PURE__ */ (0,
|
|
39290
|
+
typeof tab2.count === "number" && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
39019
39291
|
"span",
|
|
39020
39292
|
{
|
|
39021
39293
|
style: { color: tab2.count ? GUI_THEME.secondary : GUI_THEME.dim },
|
|
@@ -39035,11 +39307,71 @@ var Tabs = ({
|
|
|
39035
39307
|
}
|
|
39036
39308
|
);
|
|
39037
39309
|
|
|
39310
|
+
// source/gui/client/components/IssueHistory.tsx
|
|
39311
|
+
var import_jsx_runtime23 = __toESM(require_jsx_runtime(), 1);
|
|
39312
|
+
var IssueHistory = ({
|
|
39313
|
+
entries,
|
|
39314
|
+
onHoverEvent
|
|
39315
|
+
}) => {
|
|
39316
|
+
if (entries.length === 0) {
|
|
39317
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { color: GUI_THEME.dim, fontSize: 12 }, children: "No history yet" });
|
|
39318
|
+
}
|
|
39319
|
+
const ordered = [...entries].reverse();
|
|
39320
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
39321
|
+
"div",
|
|
39322
|
+
{
|
|
39323
|
+
"data-testid": "issue-history",
|
|
39324
|
+
onMouseLeave: () => onHoverEvent(null),
|
|
39325
|
+
style: { display: "flex", flexDirection: "column" },
|
|
39326
|
+
children: ordered.map((entry, index2) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
39327
|
+
"div",
|
|
39328
|
+
{
|
|
39329
|
+
"data-testid": "issue-history-row",
|
|
39330
|
+
onMouseEnter: () => onHoverEvent(entry.id),
|
|
39331
|
+
style: {
|
|
39332
|
+
display: "flex",
|
|
39333
|
+
alignItems: "baseline",
|
|
39334
|
+
gap: 14,
|
|
39335
|
+
padding: "8px 0",
|
|
39336
|
+
borderTop: index2 === 0 ? "none" : `1px solid ${GUI_THEME.line}`,
|
|
39337
|
+
fontSize: 12
|
|
39338
|
+
},
|
|
39339
|
+
children: [
|
|
39340
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(User, { user: entry.actor }),
|
|
39341
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
39342
|
+
"span",
|
|
39343
|
+
{
|
|
39344
|
+
style: {
|
|
39345
|
+
flex: 1,
|
|
39346
|
+
color: GUI_THEME.primary,
|
|
39347
|
+
fontFamily: CONTENT_FONT
|
|
39348
|
+
},
|
|
39349
|
+
children: entry.label
|
|
39350
|
+
}
|
|
39351
|
+
),
|
|
39352
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
39353
|
+
"span",
|
|
39354
|
+
{
|
|
39355
|
+
title: formatAbsolute(entry.t),
|
|
39356
|
+
style: { color: GUI_THEME.dim, whiteSpace: "nowrap" },
|
|
39357
|
+
children: timeAgo(entry.t)
|
|
39358
|
+
}
|
|
39359
|
+
)
|
|
39360
|
+
]
|
|
39361
|
+
},
|
|
39362
|
+
entry.id
|
|
39363
|
+
))
|
|
39364
|
+
}
|
|
39365
|
+
);
|
|
39366
|
+
};
|
|
39367
|
+
|
|
39038
39368
|
// source/gui/client/components/IssueDetails.tsx
|
|
39039
|
-
var
|
|
39369
|
+
var import_jsx_runtime24 = __toESM(require_jsx_runtime(), 1);
|
|
39040
39370
|
var IssueDetails = ({
|
|
39041
39371
|
whoAmI,
|
|
39042
39372
|
comments,
|
|
39373
|
+
history,
|
|
39374
|
+
onHoverHistoryEvent,
|
|
39043
39375
|
activeTab,
|
|
39044
39376
|
onChangeTab,
|
|
39045
39377
|
issue,
|
|
@@ -39064,37 +39396,27 @@ var IssueDetails = ({
|
|
|
39064
39396
|
knownAssignees: assignees,
|
|
39065
39397
|
onOpenAssigneePicker
|
|
39066
39398
|
}) => {
|
|
39067
|
-
const [title, setTitle] = (0,
|
|
39068
|
-
const [description, setDescription] = (0,
|
|
39069
|
-
const [tagName, setTagName] = (0,
|
|
39070
|
-
const [assigneeName, setAssigneeName] = (0,
|
|
39071
|
-
const [managingContributors, setManagingContributors] = (0,
|
|
39072
|
-
const [editingTitle, setEditingTitle] = (0,
|
|
39073
|
-
const [editingDescription, setEditingDescription] = (0,
|
|
39074
|
-
const [addingTag, setAddingTag] = (0,
|
|
39075
|
-
const [addingAssignee, setAddingAssignee] = (0,
|
|
39076
|
-
const panelRef = (0,
|
|
39077
|
-
const titleTextareaRef = (0,
|
|
39399
|
+
const [title, setTitle] = (0, import_react11.useState)("");
|
|
39400
|
+
const [description, setDescription] = (0, import_react11.useState)("");
|
|
39401
|
+
const [tagName, setTagName] = (0, import_react11.useState)("");
|
|
39402
|
+
const [assigneeName, setAssigneeName] = (0, import_react11.useState)("");
|
|
39403
|
+
const [managingContributors, setManagingContributors] = (0, import_react11.useState)(false);
|
|
39404
|
+
const [editingTitle, setEditingTitle] = (0, import_react11.useState)(false);
|
|
39405
|
+
const [editingDescription, setEditingDescription] = (0, import_react11.useState)(false);
|
|
39406
|
+
const [addingTag, setAddingTag] = (0, import_react11.useState)(false);
|
|
39407
|
+
const [addingAssignee, setAddingAssignee] = (0, import_react11.useState)(false);
|
|
39408
|
+
const panelRef = (0, import_react11.useRef)(null);
|
|
39409
|
+
const titleTextareaRef = (0, import_react11.useRef)(null);
|
|
39078
39410
|
const resizeTitleTextarea = () => {
|
|
39079
39411
|
const el = titleTextareaRef.current;
|
|
39080
39412
|
if (!el) return;
|
|
39081
39413
|
el.style.height = "auto";
|
|
39082
39414
|
el.style.height = `${el.scrollHeight}px`;
|
|
39083
39415
|
};
|
|
39084
|
-
(0,
|
|
39416
|
+
(0, import_react11.useEffect)(() => {
|
|
39085
39417
|
if (editingTitle) resizeTitleTextarea();
|
|
39086
39418
|
}, [editingTitle]);
|
|
39087
|
-
(0,
|
|
39088
|
-
if (!issue) return;
|
|
39089
|
-
const handleClickOutside = (event) => {
|
|
39090
|
-
if (panelRef.current && !panelRef.current.contains(event.target)) {
|
|
39091
|
-
onClose();
|
|
39092
|
-
}
|
|
39093
|
-
};
|
|
39094
|
-
document.addEventListener("mousedown", handleClickOutside);
|
|
39095
|
-
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
39096
|
-
}, [issue, onClose]);
|
|
39097
|
-
(0, import_react10.useEffect)(() => {
|
|
39419
|
+
(0, import_react11.useEffect)(() => {
|
|
39098
39420
|
setTitle(issue?.title ?? "");
|
|
39099
39421
|
setDescription(issue?.description ?? "");
|
|
39100
39422
|
setTagName("");
|
|
@@ -39107,7 +39429,8 @@ var IssueDetails = ({
|
|
|
39107
39429
|
const disabled = !issue || issue.readonly;
|
|
39108
39430
|
const tabs = [
|
|
39109
39431
|
{ id: "overview", label: "Overview" },
|
|
39110
|
-
{ id: "comments", label: "Comments", count: comments.length }
|
|
39432
|
+
{ id: "comments", label: "Comments", count: comments.length },
|
|
39433
|
+
{ id: "history", label: "Log", count: history.length }
|
|
39111
39434
|
];
|
|
39112
39435
|
const saveTitle = () => {
|
|
39113
39436
|
if (disabled || !issue) return setEditingTitle(false);
|
|
@@ -39159,10 +39482,10 @@ var IssueDetails = ({
|
|
|
39159
39482
|
).filter((assignee) => !assignee.isRemoved).sort(
|
|
39160
39483
|
(a, b) => assigneeRank(a) - assigneeRank(b) || a.name.localeCompare(b.name)
|
|
39161
39484
|
);
|
|
39162
|
-
return /* @__PURE__ */ (0,
|
|
39163
|
-
issue ? /* @__PURE__ */ (0,
|
|
39164
|
-
/* @__PURE__ */ (0,
|
|
39165
|
-
/* @__PURE__ */ (0,
|
|
39485
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(Aside, { ref: panelRef, children: [
|
|
39486
|
+
issue ? /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
|
|
39487
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(FormHeader, { children: [
|
|
39488
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
39166
39489
|
"span",
|
|
39167
39490
|
{
|
|
39168
39491
|
style: {
|
|
@@ -39171,12 +39494,12 @@ var IssueDetails = ({
|
|
|
39171
39494
|
textTransform: "uppercase",
|
|
39172
39495
|
letterSpacing: "0.08em"
|
|
39173
39496
|
},
|
|
39174
|
-
children: issue.ref && /* @__PURE__ */ (0,
|
|
39497
|
+
children: issue.ref && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(CopyRef, { refValue: issue.ref })
|
|
39175
39498
|
}
|
|
39176
39499
|
),
|
|
39177
|
-
/* @__PURE__ */ (0,
|
|
39500
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Button, { variant: "ghost", onClick: onClose, children: "\xD7" })
|
|
39178
39501
|
] }),
|
|
39179
|
-
editingTitle ? /* @__PURE__ */ (0,
|
|
39502
|
+
editingTitle ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
39180
39503
|
"textarea",
|
|
39181
39504
|
{
|
|
39182
39505
|
ref: titleTextareaRef,
|
|
@@ -39214,7 +39537,7 @@ var IssueDetails = ({
|
|
|
39214
39537
|
marginBottom: 20
|
|
39215
39538
|
}
|
|
39216
39539
|
}
|
|
39217
|
-
) : /* @__PURE__ */ (0,
|
|
39540
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
39218
39541
|
"div",
|
|
39219
39542
|
{
|
|
39220
39543
|
onClick: () => !issue.readonly && setEditingTitle(true),
|
|
@@ -39230,14 +39553,30 @@ var IssueDetails = ({
|
|
|
39230
39553
|
children: issue.title
|
|
39231
39554
|
}
|
|
39232
39555
|
),
|
|
39233
|
-
/* @__PURE__ */ (0,
|
|
39234
|
-
activeTab === "overview" && /* @__PURE__ */ (0,
|
|
39235
|
-
/* @__PURE__ */ (0,
|
|
39556
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Tabs, { tabs, activeTab, onChange: onChangeTab }),
|
|
39557
|
+
activeTab === "overview" && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
|
|
39558
|
+
issue.createdAt > 0 && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
39559
|
+
"div",
|
|
39560
|
+
{
|
|
39561
|
+
"data-testid": "issue-created-at",
|
|
39562
|
+
title: formatAbsolute(issue.createdAt),
|
|
39563
|
+
style: {
|
|
39564
|
+
fontSize: 11,
|
|
39565
|
+
color: GUI_THEME.dim,
|
|
39566
|
+
marginBottom: 14
|
|
39567
|
+
},
|
|
39568
|
+
children: [
|
|
39569
|
+
"Created ",
|
|
39570
|
+
timeAgo(issue.createdAt)
|
|
39571
|
+
]
|
|
39572
|
+
}
|
|
39573
|
+
),
|
|
39574
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
39236
39575
|
Section,
|
|
39237
39576
|
{
|
|
39238
39577
|
first: true,
|
|
39239
39578
|
title: "Description",
|
|
39240
|
-
action: !issue.readonly && !editingDescription && /* @__PURE__ */ (0,
|
|
39579
|
+
action: !issue.readonly && !editingDescription && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
39241
39580
|
Button,
|
|
39242
39581
|
{
|
|
39243
39582
|
variant: "ghost",
|
|
@@ -39245,8 +39584,8 @@ var IssueDetails = ({
|
|
|
39245
39584
|
children: "edit"
|
|
39246
39585
|
}
|
|
39247
39586
|
),
|
|
39248
|
-
children: editingDescription ? /* @__PURE__ */ (0,
|
|
39249
|
-
/* @__PURE__ */ (0,
|
|
39587
|
+
children: editingDescription ? /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
|
|
39588
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
39250
39589
|
Textarea,
|
|
39251
39590
|
{
|
|
39252
39591
|
value: description,
|
|
@@ -39268,11 +39607,11 @@ var IssueDetails = ({
|
|
|
39268
39607
|
}
|
|
39269
39608
|
}
|
|
39270
39609
|
),
|
|
39271
|
-
/* @__PURE__ */ (0,
|
|
39272
|
-
/* @__PURE__ */ (0,
|
|
39273
|
-
/* @__PURE__ */ (0,
|
|
39610
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(ActionRow, { children: [
|
|
39611
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Button, { onClick: saveDescription, children: "save" }),
|
|
39612
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Button, { variant: "ghost", onClick: cancelDescription, children: "cancel" })
|
|
39274
39613
|
] })
|
|
39275
|
-
] }) : issue.description ? /* @__PURE__ */ (0,
|
|
39614
|
+
] }) : issue.description ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
39276
39615
|
"div",
|
|
39277
39616
|
{
|
|
39278
39617
|
style: {
|
|
@@ -39283,18 +39622,18 @@ var IssueDetails = ({
|
|
|
39283
39622
|
background: GUI_THEME.tertiary,
|
|
39284
39623
|
borderRadius: 8
|
|
39285
39624
|
},
|
|
39286
|
-
children: /* @__PURE__ */ (0,
|
|
39625
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(MarkdownContent, { content: issue.description })
|
|
39287
39626
|
}
|
|
39288
|
-
) : /* @__PURE__ */ (0,
|
|
39627
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Empty, { children: "No description" })
|
|
39289
39628
|
}
|
|
39290
39629
|
),
|
|
39291
|
-
/* @__PURE__ */ (0,
|
|
39630
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
39292
39631
|
Section,
|
|
39293
39632
|
{
|
|
39294
39633
|
title: "Tags",
|
|
39295
|
-
action: !issue.readonly && !addingTag && /* @__PURE__ */ (0,
|
|
39634
|
+
action: !issue.readonly && !addingTag && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Button, { variant: "ghost", onClick: () => setAddingTag(true), children: "+" }) || addingTag && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Button, { variant: "ghost", onClick: () => setAddingTag(false), children: "-" }),
|
|
39296
39635
|
children: [
|
|
39297
|
-
/* @__PURE__ */ (0,
|
|
39636
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ChipRow, { children: issue.tags.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Empty, { children: "No tags" }) : issue.tags.map((tag) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
39298
39637
|
Button,
|
|
39299
39638
|
{
|
|
39300
39639
|
variant: "chip",
|
|
@@ -39310,7 +39649,7 @@ var IssueDetails = ({
|
|
|
39310
39649
|
},
|
|
39311
39650
|
tag.id
|
|
39312
39651
|
)) }),
|
|
39313
|
-
addingTag && /* @__PURE__ */ (0,
|
|
39652
|
+
addingTag && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ChipRow, { children: availableTags.map((tag) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
39314
39653
|
Button,
|
|
39315
39654
|
{
|
|
39316
39655
|
variant: "chip",
|
|
@@ -39325,8 +39664,8 @@ var IssueDetails = ({
|
|
|
39325
39664
|
},
|
|
39326
39665
|
tag.id
|
|
39327
39666
|
)) }),
|
|
39328
|
-
addingTag && /* @__PURE__ */ (0,
|
|
39329
|
-
/* @__PURE__ */ (0,
|
|
39667
|
+
addingTag && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(AddRow, { children: [
|
|
39668
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
39330
39669
|
Input,
|
|
39331
39670
|
{
|
|
39332
39671
|
value: tagName,
|
|
@@ -39342,16 +39681,16 @@ var IssueDetails = ({
|
|
|
39342
39681
|
}
|
|
39343
39682
|
}
|
|
39344
39683
|
),
|
|
39345
|
-
/* @__PURE__ */ (0,
|
|
39684
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Button, { onClick: addTag, children: "add" })
|
|
39346
39685
|
] })
|
|
39347
39686
|
]
|
|
39348
39687
|
}
|
|
39349
39688
|
),
|
|
39350
|
-
/* @__PURE__ */ (0,
|
|
39689
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
39351
39690
|
Section,
|
|
39352
39691
|
{
|
|
39353
39692
|
title: "Assignees",
|
|
39354
|
-
action: !issue.readonly && !addingAssignee && /* @__PURE__ */ (0,
|
|
39693
|
+
action: !issue.readonly && !addingAssignee && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
39355
39694
|
Button,
|
|
39356
39695
|
{
|
|
39357
39696
|
variant: "ghost",
|
|
@@ -39361,7 +39700,7 @@ var IssueDetails = ({
|
|
|
39361
39700
|
},
|
|
39362
39701
|
children: "+"
|
|
39363
39702
|
}
|
|
39364
|
-
) || addingAssignee && /* @__PURE__ */ (0,
|
|
39703
|
+
) || addingAssignee && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
39365
39704
|
Button,
|
|
39366
39705
|
{
|
|
39367
39706
|
variant: "ghost",
|
|
@@ -39370,7 +39709,7 @@ var IssueDetails = ({
|
|
|
39370
39709
|
}
|
|
39371
39710
|
),
|
|
39372
39711
|
children: [
|
|
39373
|
-
/* @__PURE__ */ (0,
|
|
39712
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ChipRow, { children: issue.assignees.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Empty, { children: "No assignees" }) : issue.assignees.map((assignee) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
39374
39713
|
Button,
|
|
39375
39714
|
{
|
|
39376
39715
|
variant: "chip",
|
|
@@ -39387,7 +39726,7 @@ var IssueDetails = ({
|
|
|
39387
39726
|
},
|
|
39388
39727
|
assignee.id
|
|
39389
39728
|
)) }),
|
|
39390
|
-
addingAssignee && /* @__PURE__ */ (0,
|
|
39729
|
+
addingAssignee && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ChipRow, { children: availableAssignees.map((assignee) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
39391
39730
|
Button,
|
|
39392
39731
|
{
|
|
39393
39732
|
variant: "chip",
|
|
@@ -39410,7 +39749,7 @@ var IssueDetails = ({
|
|
|
39410
39749
|
)) }),
|
|
39411
39750
|
addingAssignee && assignees.some(
|
|
39412
39751
|
(a) => !a.hasAuthoredAnywhere && !a.isRemoved
|
|
39413
|
-
) && /* @__PURE__ */ (0,
|
|
39752
|
+
) && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ChipRow, { children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
39414
39753
|
Button,
|
|
39415
39754
|
{
|
|
39416
39755
|
variant: "ghost",
|
|
@@ -39420,8 +39759,8 @@ var IssueDetails = ({
|
|
|
39420
39759
|
children: "manage contributors\u2026"
|
|
39421
39760
|
}
|
|
39422
39761
|
) }),
|
|
39423
|
-
addingAssignee && /* @__PURE__ */ (0,
|
|
39424
|
-
/* @__PURE__ */ (0,
|
|
39762
|
+
addingAssignee && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(AddRow, { children: [
|
|
39763
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
39425
39764
|
Input,
|
|
39426
39765
|
{
|
|
39427
39766
|
value: assigneeName,
|
|
@@ -39437,7 +39776,7 @@ var IssueDetails = ({
|
|
|
39437
39776
|
}
|
|
39438
39777
|
}
|
|
39439
39778
|
),
|
|
39440
|
-
/* @__PURE__ */ (0,
|
|
39779
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
39441
39780
|
Button,
|
|
39442
39781
|
{
|
|
39443
39782
|
onClick: addAssignee,
|
|
@@ -39449,7 +39788,7 @@ var IssueDetails = ({
|
|
|
39449
39788
|
]
|
|
39450
39789
|
}
|
|
39451
39790
|
),
|
|
39452
|
-
/* @__PURE__ */ (0,
|
|
39791
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
39453
39792
|
IssueAttachments,
|
|
39454
39793
|
{
|
|
39455
39794
|
issueId: issue.id,
|
|
@@ -39460,16 +39799,16 @@ var IssueDetails = ({
|
|
|
39460
39799
|
onDeleteAttachment
|
|
39461
39800
|
}
|
|
39462
39801
|
),
|
|
39463
|
-
/* @__PURE__ */ (0,
|
|
39802
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
39464
39803
|
Section,
|
|
39465
39804
|
{
|
|
39466
39805
|
title: "Actions",
|
|
39467
|
-
action: !issue.readonly && (issue.isClosed ? /* @__PURE__ */ (0,
|
|
39806
|
+
action: !issue.readonly && (issue.isClosed ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Button, { onClick: () => onReopenIssue(issue.id), children: "reopen issue" }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Button, { onClick: () => onCloseIssue(issue.id), children: "close issue" })),
|
|
39468
39807
|
children: ""
|
|
39469
39808
|
}
|
|
39470
39809
|
)
|
|
39471
39810
|
] }),
|
|
39472
|
-
activeTab === "comments" && /* @__PURE__ */ (0,
|
|
39811
|
+
activeTab === "comments" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
39473
39812
|
IssueComments,
|
|
39474
39813
|
{
|
|
39475
39814
|
whoAmI,
|
|
@@ -39479,9 +39818,16 @@ var IssueDetails = ({
|
|
|
39479
39818
|
onAddComment,
|
|
39480
39819
|
onDeleteComment
|
|
39481
39820
|
}
|
|
39821
|
+
),
|
|
39822
|
+
activeTab === "history" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
39823
|
+
IssueHistory,
|
|
39824
|
+
{
|
|
39825
|
+
entries: history,
|
|
39826
|
+
onHoverEvent: onHoverHistoryEvent
|
|
39827
|
+
}
|
|
39482
39828
|
)
|
|
39483
|
-
] }) : /* @__PURE__ */ (0,
|
|
39484
|
-
managingContributors && /* @__PURE__ */ (0,
|
|
39829
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Empty, { children: "Select an issue" }),
|
|
39830
|
+
managingContributors && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
39485
39831
|
ManageContributorsModal,
|
|
39486
39832
|
{
|
|
39487
39833
|
contributors: assignees,
|
|
@@ -39493,7 +39839,7 @@ var IssueDetails = ({
|
|
|
39493
39839
|
};
|
|
39494
39840
|
|
|
39495
39841
|
// source/gui/client/components/BulkDetails.tsx
|
|
39496
|
-
var
|
|
39842
|
+
var import_jsx_runtime25 = __toESM(require_jsx_runtime(), 1);
|
|
39497
39843
|
var countBy = (issues, pick) => {
|
|
39498
39844
|
const byId = /* @__PURE__ */ new Map();
|
|
39499
39845
|
for (const issue of issues) {
|
|
@@ -39504,6 +39850,7 @@ var countBy = (issues, pick) => {
|
|
|
39504
39850
|
}
|
|
39505
39851
|
return [...byId.values()];
|
|
39506
39852
|
};
|
|
39853
|
+
var ticketWord = (count) => count === 1 ? "ticket" : "tickets";
|
|
39507
39854
|
var BulkDetails = ({
|
|
39508
39855
|
issues,
|
|
39509
39856
|
knownTags,
|
|
@@ -39521,6 +39868,8 @@ var BulkDetails = ({
|
|
|
39521
39868
|
onClear
|
|
39522
39869
|
}) => {
|
|
39523
39870
|
const total = issues.length;
|
|
39871
|
+
const openCount = issues.filter((issue) => !issue.isClosed).length;
|
|
39872
|
+
const closedCount = total - openCount;
|
|
39524
39873
|
const tags = countBy(issues, (issue) => issue.tags);
|
|
39525
39874
|
const assignees = countBy(issues, (issue) => issue.assignees);
|
|
39526
39875
|
const availableTags = knownTags.filter(
|
|
@@ -39532,8 +39881,8 @@ var BulkDetails = ({
|
|
|
39532
39881
|
)
|
|
39533
39882
|
);
|
|
39534
39883
|
const partial = (count) => count === total ? "" : ` ${count}/${total}`;
|
|
39535
|
-
return /* @__PURE__ */ (0,
|
|
39536
|
-
/* @__PURE__ */ (0,
|
|
39884
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(Aside, { children: [
|
|
39885
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
39537
39886
|
"div",
|
|
39538
39887
|
{
|
|
39539
39888
|
style: {
|
|
@@ -39544,16 +39893,16 @@ var BulkDetails = ({
|
|
|
39544
39893
|
marginBottom: 12
|
|
39545
39894
|
},
|
|
39546
39895
|
children: [
|
|
39547
|
-
/* @__PURE__ */ (0,
|
|
39896
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { style: { fontSize: 13, fontWeight: 600, color: GUI_THEME.primary }, children: [
|
|
39548
39897
|
total,
|
|
39549
39898
|
" tickets selected"
|
|
39550
39899
|
] }),
|
|
39551
|
-
/* @__PURE__ */ (0,
|
|
39900
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Button, { variant: "ghost", onClick: onClear, children: "clear" })
|
|
39552
39901
|
]
|
|
39553
39902
|
}
|
|
39554
39903
|
),
|
|
39555
|
-
/* @__PURE__ */ (0,
|
|
39556
|
-
/* @__PURE__ */ (0,
|
|
39904
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(Section, { title: "Tags", children: [
|
|
39905
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ChipRow, { children: tags.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Empty, { children: "No tags" }) : tags.map(({ item, count }) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
39557
39906
|
Button,
|
|
39558
39907
|
{
|
|
39559
39908
|
variant: "chip",
|
|
@@ -39568,7 +39917,7 @@ var BulkDetails = ({
|
|
|
39568
39917
|
},
|
|
39569
39918
|
item.id
|
|
39570
39919
|
)) }),
|
|
39571
|
-
/* @__PURE__ */ (0,
|
|
39920
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ChipRow, { children: availableTags.map((tag) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
39572
39921
|
Button,
|
|
39573
39922
|
{
|
|
39574
39923
|
variant: "chip",
|
|
@@ -39582,8 +39931,8 @@ var BulkDetails = ({
|
|
|
39582
39931
|
},
|
|
39583
39932
|
tag.id
|
|
39584
39933
|
)) }),
|
|
39585
|
-
/* @__PURE__ */ (0,
|
|
39586
|
-
/* @__PURE__ */ (0,
|
|
39934
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(AddRow, { children: [
|
|
39935
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
39587
39936
|
Input,
|
|
39588
39937
|
{
|
|
39589
39938
|
value: tagName,
|
|
@@ -39596,11 +39945,11 @@ var BulkDetails = ({
|
|
|
39596
39945
|
}
|
|
39597
39946
|
}
|
|
39598
39947
|
),
|
|
39599
|
-
/* @__PURE__ */ (0,
|
|
39948
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Button, { onClick: () => tagName.trim() && onAddTag(tagName.trim()), children: "add" })
|
|
39600
39949
|
] })
|
|
39601
39950
|
] }),
|
|
39602
|
-
/* @__PURE__ */ (0,
|
|
39603
|
-
/* @__PURE__ */ (0,
|
|
39951
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(Section, { title: "Assignees", children: [
|
|
39952
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ChipRow, { children: assignees.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Empty, { children: "No assignees" }) : assignees.map(({ item, count }) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
39604
39953
|
Button,
|
|
39605
39954
|
{
|
|
39606
39955
|
variant: "chip",
|
|
@@ -39616,7 +39965,7 @@ var BulkDetails = ({
|
|
|
39616
39965
|
},
|
|
39617
39966
|
item.id
|
|
39618
39967
|
)) }),
|
|
39619
|
-
/* @__PURE__ */ (0,
|
|
39968
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ChipRow, { children: availableAssignees.map((person) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
39620
39969
|
Button,
|
|
39621
39970
|
{
|
|
39622
39971
|
variant: "chip",
|
|
@@ -39630,7 +39979,7 @@ var BulkDetails = ({
|
|
|
39630
39979
|
},
|
|
39631
39980
|
person.id
|
|
39632
39981
|
)) }),
|
|
39633
|
-
/* @__PURE__ */ (0,
|
|
39982
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(AddRow, { children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
39634
39983
|
Input,
|
|
39635
39984
|
{
|
|
39636
39985
|
value: assigneeName,
|
|
@@ -39639,30 +39988,80 @@ var BulkDetails = ({
|
|
|
39639
39988
|
}
|
|
39640
39989
|
) })
|
|
39641
39990
|
] }),
|
|
39642
|
-
/* @__PURE__ */ (0,
|
|
39643
|
-
/* @__PURE__ */ (0,
|
|
39991
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Section, { title: "Actions", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(ChipRow, { children: [
|
|
39992
|
+
openCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(Button, { onClick: onCloseIssues, children: [
|
|
39644
39993
|
"close ",
|
|
39645
|
-
|
|
39646
|
-
"
|
|
39994
|
+
openCount,
|
|
39995
|
+
" ",
|
|
39996
|
+
ticketWord(openCount)
|
|
39647
39997
|
] }),
|
|
39648
|
-
/* @__PURE__ */ (0,
|
|
39998
|
+
closedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(Button, { onClick: onReopenIssues, children: [
|
|
39649
39999
|
"reopen ",
|
|
39650
|
-
|
|
39651
|
-
"
|
|
40000
|
+
closedCount,
|
|
40001
|
+
" ",
|
|
40002
|
+
ticketWord(closedCount)
|
|
39652
40003
|
] })
|
|
39653
40004
|
] }) })
|
|
39654
40005
|
] });
|
|
39655
40006
|
};
|
|
39656
40007
|
|
|
39657
40008
|
// source/gui/client/components/SwimlaneColumn.tsx
|
|
39658
|
-
var
|
|
40009
|
+
var import_react14 = __toESM(require_react(), 1);
|
|
39659
40010
|
|
|
39660
40011
|
// source/gui/client/components/TicketCard.tsx
|
|
39661
|
-
var
|
|
40012
|
+
var import_react12 = __toESM(require_react(), 1);
|
|
40013
|
+
|
|
40014
|
+
// source/gui/client/lib/gui-move-swimlane.ts
|
|
40015
|
+
var SWIMLANE_DRAG_TYPE = "application/x-epiq-swimlane";
|
|
40016
|
+
var isSwimlaneDrag = (dataTransfer) => Boolean(dataTransfer?.types.includes(SWIMLANE_DRAG_TYPE));
|
|
40017
|
+
var toMovePosition = (siblings, targetIndex) => {
|
|
40018
|
+
if (siblings.length === 0) return { at: "start" };
|
|
40019
|
+
if (targetIndex >= siblings.length) return { at: "end" };
|
|
40020
|
+
return { at: "before", sibling: siblings[Math.max(0, targetIndex)].id };
|
|
40021
|
+
};
|
|
40022
|
+
var reorder = (swimlanes, swimlaneId, targetIndex) => {
|
|
40023
|
+
const moved = swimlanes.find((swimlane) => swimlane.id === swimlaneId);
|
|
40024
|
+
if (!moved) return swimlanes;
|
|
40025
|
+
const without = swimlanes.filter((swimlane) => swimlane.id !== swimlaneId);
|
|
40026
|
+
const index2 = Math.max(0, Math.min(targetIndex, without.length));
|
|
40027
|
+
return [...without.slice(0, index2), moved, ...without.slice(index2)];
|
|
40028
|
+
};
|
|
40029
|
+
var moveSwimlane = (state, setState, send) => (swimlaneId, boardId, targetIndex) => {
|
|
40030
|
+
if (!state) return;
|
|
40031
|
+
const board = state.boards.find((candidate) => candidate.id === boardId);
|
|
40032
|
+
if (!board) return;
|
|
40033
|
+
const currentIndex = board.swimlanes.findIndex(
|
|
40034
|
+
(swimlane) => swimlane.id === swimlaneId
|
|
40035
|
+
);
|
|
40036
|
+
if (currentIndex === -1) return;
|
|
40037
|
+
if (targetIndex === currentIndex || targetIndex === currentIndex + 1)
|
|
40038
|
+
return;
|
|
40039
|
+
const withoutMoved = board.swimlanes.filter(
|
|
40040
|
+
(swimlane) => swimlane.id !== swimlaneId
|
|
40041
|
+
);
|
|
40042
|
+
const indexWithoutMoved = targetIndex > currentIndex ? targetIndex - 1 : targetIndex;
|
|
40043
|
+
const position3 = toMovePosition(withoutMoved, indexWithoutMoved);
|
|
40044
|
+
setState(
|
|
40045
|
+
(current) => current ? {
|
|
40046
|
+
...current,
|
|
40047
|
+
boards: current.boards.map(
|
|
40048
|
+
(candidate) => candidate.id === boardId ? {
|
|
40049
|
+
...candidate,
|
|
40050
|
+
swimlanes: reorder(
|
|
40051
|
+
candidate.swimlanes,
|
|
40052
|
+
swimlaneId,
|
|
40053
|
+
indexWithoutMoved
|
|
40054
|
+
)
|
|
40055
|
+
} : candidate
|
|
40056
|
+
)
|
|
40057
|
+
} : current
|
|
40058
|
+
);
|
|
40059
|
+
send("swimlane:move", { swimlaneId, boardId, position: position3 });
|
|
40060
|
+
};
|
|
39662
40061
|
|
|
39663
40062
|
// source/gui/client/components/IconComment.tsx
|
|
39664
|
-
var
|
|
39665
|
-
var IconComment = ({ size = 14 }) => /* @__PURE__ */ (0,
|
|
40063
|
+
var import_jsx_runtime26 = __toESM(require_jsx_runtime(), 1);
|
|
40064
|
+
var IconComment = ({ size = 14 }) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
39666
40065
|
"svg",
|
|
39667
40066
|
{
|
|
39668
40067
|
width: size,
|
|
@@ -39674,7 +40073,7 @@ var IconComment = ({ size = 14 }) => /* @__PURE__ */ (0, import_jsx_runtime22.js
|
|
|
39674
40073
|
strokeLinecap: "round",
|
|
39675
40074
|
strokeLinejoin: "round",
|
|
39676
40075
|
"aria-hidden": "true",
|
|
39677
|
-
children: /* @__PURE__ */ (0,
|
|
40076
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
39678
40077
|
"path",
|
|
39679
40078
|
{
|
|
39680
40079
|
fill: "currentColor",
|
|
@@ -39685,7 +40084,7 @@ var IconComment = ({ size = 14 }) => /* @__PURE__ */ (0, import_jsx_runtime22.js
|
|
|
39685
40084
|
);
|
|
39686
40085
|
|
|
39687
40086
|
// source/gui/client/components/TicketCard.tsx
|
|
39688
|
-
var
|
|
40087
|
+
var import_jsx_runtime27 = __toESM(require_jsx_runtime(), 1);
|
|
39689
40088
|
var TicketCard = ({
|
|
39690
40089
|
ticket,
|
|
39691
40090
|
index: index2,
|
|
@@ -39697,8 +40096,8 @@ var TicketCard = ({
|
|
|
39697
40096
|
onDragOverIssue,
|
|
39698
40097
|
onDropIssueAt
|
|
39699
40098
|
}) => {
|
|
39700
|
-
const cardRef = (0,
|
|
39701
|
-
(0,
|
|
40099
|
+
const cardRef = (0, import_react12.useRef)(null);
|
|
40100
|
+
(0, import_react12.useEffect)(() => {
|
|
39702
40101
|
if (!isSelected) return;
|
|
39703
40102
|
cardRef.current?.scrollIntoView({
|
|
39704
40103
|
behavior: "smooth",
|
|
@@ -39707,7 +40106,7 @@ var TicketCard = ({
|
|
|
39707
40106
|
});
|
|
39708
40107
|
}, [isSelected]);
|
|
39709
40108
|
const getVisualTargetIndex = (isAfterMiddle) => index2 + (isAfterMiddle ? 1 : 0);
|
|
39710
|
-
return /* @__PURE__ */ (0,
|
|
40109
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
39711
40110
|
"div",
|
|
39712
40111
|
{
|
|
39713
40112
|
ref: cardRef,
|
|
@@ -39721,6 +40120,7 @@ var TicketCard = ({
|
|
|
39721
40120
|
event.dataTransfer.setData("text/plain", ticket.id);
|
|
39722
40121
|
},
|
|
39723
40122
|
onDragOver: (event) => {
|
|
40123
|
+
if (isSwimlaneDrag(event.dataTransfer)) return;
|
|
39724
40124
|
event.preventDefault();
|
|
39725
40125
|
event.dataTransfer.dropEffect = "move";
|
|
39726
40126
|
const rect = event.currentTarget.getBoundingClientRect();
|
|
@@ -39728,6 +40128,7 @@ var TicketCard = ({
|
|
|
39728
40128
|
onDragOverIssue(getVisualTargetIndex(isAfterMiddle));
|
|
39729
40129
|
},
|
|
39730
40130
|
onDrop: (event) => {
|
|
40131
|
+
if (isSwimlaneDrag(event.dataTransfer)) return;
|
|
39731
40132
|
event.preventDefault();
|
|
39732
40133
|
event.stopPropagation();
|
|
39733
40134
|
const issueId = event.dataTransfer.getData("text/plain");
|
|
@@ -39748,14 +40149,10 @@ var TicketCard = ({
|
|
|
39748
40149
|
minHeight: "58px",
|
|
39749
40150
|
borderRadius: "8px",
|
|
39750
40151
|
marginBottom: 4,
|
|
39751
|
-
border: `1px solid ${isSelected || isPicked ? GUI_THEME.accent : "transparent"}
|
|
39752
|
-
// Only the multi-selection is outlined, so it stays legible when the
|
|
39753
|
-
// details panel is closed.
|
|
39754
|
-
outline: isPicked ? `1px solid ${GUI_THEME.accent}` : void 0,
|
|
39755
|
-
outlineOffset: 1
|
|
40152
|
+
border: `1px solid ${isSelected || isPicked ? GUI_THEME.accent : "transparent"}`
|
|
39756
40153
|
},
|
|
39757
40154
|
children: [
|
|
39758
|
-
/* @__PURE__ */ (0,
|
|
40155
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
39759
40156
|
"div",
|
|
39760
40157
|
{
|
|
39761
40158
|
style: {
|
|
@@ -39769,7 +40166,7 @@ var TicketCard = ({
|
|
|
39769
40166
|
children: isSelected ? "\u276F" : index2 + 1
|
|
39770
40167
|
}
|
|
39771
40168
|
),
|
|
39772
|
-
/* @__PURE__ */ (0,
|
|
40169
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
39773
40170
|
"div",
|
|
39774
40171
|
{
|
|
39775
40172
|
style: {
|
|
@@ -39781,7 +40178,7 @@ var TicketCard = ({
|
|
|
39781
40178
|
paddingLeft: 8
|
|
39782
40179
|
},
|
|
39783
40180
|
children: [
|
|
39784
|
-
/* @__PURE__ */ (0,
|
|
40181
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
39785
40182
|
"div",
|
|
39786
40183
|
{
|
|
39787
40184
|
style: {
|
|
@@ -39792,7 +40189,7 @@ var TicketCard = ({
|
|
|
39792
40189
|
flex: 1
|
|
39793
40190
|
},
|
|
39794
40191
|
children: [
|
|
39795
|
-
/* @__PURE__ */ (0,
|
|
40192
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
39796
40193
|
"div",
|
|
39797
40194
|
{
|
|
39798
40195
|
style: {
|
|
@@ -39808,17 +40205,17 @@ var TicketCard = ({
|
|
|
39808
40205
|
children: ticket.title
|
|
39809
40206
|
}
|
|
39810
40207
|
),
|
|
39811
|
-
ticket.ref && /* @__PURE__ */ (0,
|
|
40208
|
+
ticket.ref && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
39812
40209
|
"div",
|
|
39813
40210
|
{
|
|
39814
40211
|
style: {
|
|
39815
40212
|
color: GUI_THEME.dim2,
|
|
39816
40213
|
fontSize: 10
|
|
39817
40214
|
},
|
|
39818
|
-
children: /* @__PURE__ */ (0,
|
|
40215
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(CopyRef, { refValue: ticket.ref })
|
|
39819
40216
|
}
|
|
39820
40217
|
),
|
|
39821
|
-
/* @__PURE__ */ (0,
|
|
40218
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
39822
40219
|
"div",
|
|
39823
40220
|
{
|
|
39824
40221
|
style: {
|
|
@@ -39827,7 +40224,7 @@ var TicketCard = ({
|
|
|
39827
40224
|
gap: 6,
|
|
39828
40225
|
alignItems: "center"
|
|
39829
40226
|
},
|
|
39830
|
-
children: ticket.tags.map((tag) => /* @__PURE__ */ (0,
|
|
40227
|
+
children: ticket.tags.map((tag) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
39831
40228
|
"span",
|
|
39832
40229
|
{
|
|
39833
40230
|
style: {
|
|
@@ -39847,7 +40244,7 @@ var TicketCard = ({
|
|
|
39847
40244
|
]
|
|
39848
40245
|
}
|
|
39849
40246
|
),
|
|
39850
|
-
/* @__PURE__ */ (0,
|
|
40247
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
39851
40248
|
"div",
|
|
39852
40249
|
{
|
|
39853
40250
|
style: {
|
|
@@ -39857,7 +40254,7 @@ var TicketCard = ({
|
|
|
39857
40254
|
flexShrink: 0,
|
|
39858
40255
|
paddingTop: 2
|
|
39859
40256
|
},
|
|
39860
|
-
children: commentCount > 0 && /* @__PURE__ */ (0,
|
|
40257
|
+
children: commentCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
39861
40258
|
"button",
|
|
39862
40259
|
{
|
|
39863
40260
|
type: "button",
|
|
@@ -39895,14 +40292,14 @@ var TicketCard = ({
|
|
|
39895
40292
|
event.currentTarget.style.transform = "translateY(0)";
|
|
39896
40293
|
},
|
|
39897
40294
|
children: [
|
|
39898
|
-
/* @__PURE__ */ (0,
|
|
39899
|
-
/* @__PURE__ */ (0,
|
|
40295
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(IconComment, {}),
|
|
40296
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { children: commentCount })
|
|
39900
40297
|
]
|
|
39901
40298
|
}
|
|
39902
40299
|
)
|
|
39903
40300
|
}
|
|
39904
40301
|
),
|
|
39905
|
-
ticket.assignees.length > 0 && /* @__PURE__ */ (0,
|
|
40302
|
+
ticket.assignees.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
39906
40303
|
"div",
|
|
39907
40304
|
{
|
|
39908
40305
|
style: {
|
|
@@ -39912,7 +40309,7 @@ var TicketCard = ({
|
|
|
39912
40309
|
paddingTop: 2,
|
|
39913
40310
|
marginTop: "-4px"
|
|
39914
40311
|
},
|
|
39915
|
-
children: ticket.assignees.map((assignee, idx) => /* @__PURE__ */ (0,
|
|
40312
|
+
children: ticket.assignees.map((assignee, idx) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
39916
40313
|
User,
|
|
39917
40314
|
{
|
|
39918
40315
|
user: assignee,
|
|
@@ -39931,8 +40328,130 @@ var TicketCard = ({
|
|
|
39931
40328
|
);
|
|
39932
40329
|
};
|
|
39933
40330
|
|
|
40331
|
+
// source/gui/client/components/KebabMenu.tsx
|
|
40332
|
+
var import_react13 = __toESM(require_react(), 1);
|
|
40333
|
+
var import_jsx_runtime28 = __toESM(require_jsx_runtime(), 1);
|
|
40334
|
+
var KebabMenu = ({
|
|
40335
|
+
items,
|
|
40336
|
+
testId
|
|
40337
|
+
}) => {
|
|
40338
|
+
const [open, setOpen] = (0, import_react13.useState)(false);
|
|
40339
|
+
const [hovered, setHovered] = (0, import_react13.useState)(false);
|
|
40340
|
+
const ref = (0, import_react13.useRef)(null);
|
|
40341
|
+
(0, import_react13.useEffect)(() => {
|
|
40342
|
+
if (!open) return;
|
|
40343
|
+
const close = (event) => {
|
|
40344
|
+
if (ref.current && !ref.current.contains(event.target)) {
|
|
40345
|
+
setOpen(false);
|
|
40346
|
+
}
|
|
40347
|
+
};
|
|
40348
|
+
const onEscape = (event) => {
|
|
40349
|
+
if (event.key === "Escape") setOpen(false);
|
|
40350
|
+
};
|
|
40351
|
+
document.addEventListener("mousedown", close);
|
|
40352
|
+
document.addEventListener("keydown", onEscape);
|
|
40353
|
+
return () => {
|
|
40354
|
+
document.removeEventListener("mousedown", close);
|
|
40355
|
+
document.removeEventListener("keydown", onEscape);
|
|
40356
|
+
};
|
|
40357
|
+
}, [open]);
|
|
40358
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { ref, style: { position: "relative", display: "flex" }, children: [
|
|
40359
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
40360
|
+
"button",
|
|
40361
|
+
{
|
|
40362
|
+
type: "button",
|
|
40363
|
+
"data-testid": testId,
|
|
40364
|
+
title: "Swimlane actions",
|
|
40365
|
+
"aria-haspopup": "menu",
|
|
40366
|
+
"aria-expanded": open,
|
|
40367
|
+
onClick: () => setOpen((value) => !value),
|
|
40368
|
+
onMouseEnter: () => setHovered(true),
|
|
40369
|
+
onMouseLeave: () => setHovered(false),
|
|
40370
|
+
style: {
|
|
40371
|
+
appearance: "none",
|
|
40372
|
+
WebkitAppearance: "none",
|
|
40373
|
+
background: hovered ? "rgba(255,255,255,0.04)" : "transparent",
|
|
40374
|
+
border: `1px solid ${open || hovered ? GUI_THEME.line : "transparent"}`,
|
|
40375
|
+
borderRadius: 6,
|
|
40376
|
+
color: open || hovered ? GUI_THEME.secondary : GUI_THEME.dim,
|
|
40377
|
+
cursor: "pointer",
|
|
40378
|
+
fontFamily: "inherit",
|
|
40379
|
+
fontSize: 12,
|
|
40380
|
+
lineHeight: 1,
|
|
40381
|
+
padding: "3px 6px",
|
|
40382
|
+
outline: "none",
|
|
40383
|
+
transition: "color 120ms ease, background 120ms ease"
|
|
40384
|
+
},
|
|
40385
|
+
children: "\u22EE"
|
|
40386
|
+
}
|
|
40387
|
+
),
|
|
40388
|
+
open && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
40389
|
+
"div",
|
|
40390
|
+
{
|
|
40391
|
+
role: "menu",
|
|
40392
|
+
style: {
|
|
40393
|
+
position: "absolute",
|
|
40394
|
+
top: 26,
|
|
40395
|
+
right: 0,
|
|
40396
|
+
minWidth: 140,
|
|
40397
|
+
background: GUI_THEME.bg,
|
|
40398
|
+
border: `1px solid ${GUI_THEME.line}`,
|
|
40399
|
+
borderRadius: 8,
|
|
40400
|
+
boxShadow: "0 12px 32px rgba(0, 0, 0, 0.35)",
|
|
40401
|
+
padding: 6,
|
|
40402
|
+
zIndex: 20
|
|
40403
|
+
},
|
|
40404
|
+
children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
40405
|
+
MenuItem,
|
|
40406
|
+
{
|
|
40407
|
+
item,
|
|
40408
|
+
testId: testId ? `${testId}-${item.id}` : void 0,
|
|
40409
|
+
onDone: () => setOpen(false)
|
|
40410
|
+
},
|
|
40411
|
+
item.id
|
|
40412
|
+
))
|
|
40413
|
+
}
|
|
40414
|
+
)
|
|
40415
|
+
] });
|
|
40416
|
+
};
|
|
40417
|
+
var MenuItem = ({
|
|
40418
|
+
item,
|
|
40419
|
+
testId,
|
|
40420
|
+
onDone
|
|
40421
|
+
}) => {
|
|
40422
|
+
const [hovered, setHovered] = (0, import_react13.useState)(false);
|
|
40423
|
+
const color2 = item.danger ? GUI_THEME.red : GUI_THEME.primary;
|
|
40424
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
40425
|
+
"button",
|
|
40426
|
+
{
|
|
40427
|
+
type: "button",
|
|
40428
|
+
role: "menuitem",
|
|
40429
|
+
"data-testid": testId,
|
|
40430
|
+
onClick: () => {
|
|
40431
|
+
onDone();
|
|
40432
|
+
item.onSelect();
|
|
40433
|
+
},
|
|
40434
|
+
onMouseEnter: () => setHovered(true),
|
|
40435
|
+
onMouseLeave: () => setHovered(false),
|
|
40436
|
+
style: {
|
|
40437
|
+
width: "100%",
|
|
40438
|
+
border: "none",
|
|
40439
|
+
background: hovered ? GUI_THEME.line : "transparent",
|
|
40440
|
+
color: color2,
|
|
40441
|
+
fontFamily: "inherit",
|
|
40442
|
+
fontSize: 11,
|
|
40443
|
+
textAlign: "left",
|
|
40444
|
+
padding: "8px 10px",
|
|
40445
|
+
borderRadius: 6,
|
|
40446
|
+
cursor: "pointer"
|
|
40447
|
+
},
|
|
40448
|
+
children: item.label
|
|
40449
|
+
}
|
|
40450
|
+
);
|
|
40451
|
+
};
|
|
40452
|
+
|
|
39934
40453
|
// source/gui/client/components/SwimlaneColumn.tsx
|
|
39935
|
-
var
|
|
40454
|
+
var import_jsx_runtime29 = __toESM(require_jsx_runtime(), 1);
|
|
39936
40455
|
var COLUMN_GLOW_COLOR = "rgb(140, 176, 232)";
|
|
39937
40456
|
var COLUMN_PADDING = 14;
|
|
39938
40457
|
var SCROLLBAR_GUTTER_INSET = COLUMN_PADDING / 2;
|
|
@@ -39947,12 +40466,18 @@ var SwimlaneColumn = ({
|
|
|
39947
40466
|
onSelectIssue,
|
|
39948
40467
|
pickedIssueIds,
|
|
39949
40468
|
onCreateIssue,
|
|
40469
|
+
onRenameSwimlane,
|
|
40470
|
+
onDeleteSwimlane,
|
|
40471
|
+
dropSide,
|
|
40472
|
+
onSwimlaneDragOver,
|
|
40473
|
+
onSwimlaneDragEnd,
|
|
40474
|
+
onDropSwimlane,
|
|
39950
40475
|
onDropIssue,
|
|
39951
40476
|
onDragOver,
|
|
39952
40477
|
onDragOverIssue,
|
|
39953
40478
|
onDragLeave
|
|
39954
40479
|
}) => {
|
|
39955
|
-
return /* @__PURE__ */ (0,
|
|
40480
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
39956
40481
|
Panel,
|
|
39957
40482
|
{
|
|
39958
40483
|
as: "section",
|
|
@@ -39979,6 +40504,11 @@ var SwimlaneColumn = ({
|
|
|
39979
40504
|
onDragOver: (event) => {
|
|
39980
40505
|
event.preventDefault();
|
|
39981
40506
|
event.dataTransfer.dropEffect = "move";
|
|
40507
|
+
if (isSwimlaneDrag(event.dataTransfer)) {
|
|
40508
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
40509
|
+
const side = event.clientX < rect.left + rect.width / 2 ? "left" : "right";
|
|
40510
|
+
return onSwimlaneDragOver(swimlane.id, side);
|
|
40511
|
+
}
|
|
39982
40512
|
onDragOver(swimlane.id);
|
|
39983
40513
|
if (dropIndex === null) {
|
|
39984
40514
|
onDragOverIssue(swimlane.id, swimlane.issues.length);
|
|
@@ -39989,9 +40519,13 @@ var SwimlaneColumn = ({
|
|
|
39989
40519
|
onDragLeave();
|
|
39990
40520
|
}
|
|
39991
40521
|
},
|
|
40522
|
+
"data-drop-side": dropSide ?? void 0,
|
|
39992
40523
|
onDrop: (event) => {
|
|
39993
40524
|
event.preventDefault();
|
|
39994
40525
|
event.stopPropagation();
|
|
40526
|
+
if (isSwimlaneDrag(event.dataTransfer)) {
|
|
40527
|
+
return onDropSwimlane(event.dataTransfer.getData(SWIMLANE_DRAG_TYPE));
|
|
40528
|
+
}
|
|
39995
40529
|
const issueId = event.dataTransfer.getData("text/plain");
|
|
39996
40530
|
if (!issueId) return;
|
|
39997
40531
|
const targetIndex = dropIndex ?? swimlane.issues.length;
|
|
@@ -39999,19 +40533,46 @@ var SwimlaneColumn = ({
|
|
|
39999
40533
|
onDragLeave();
|
|
40000
40534
|
},
|
|
40001
40535
|
children: [
|
|
40002
|
-
/* @__PURE__ */ (0,
|
|
40536
|
+
dropSide && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
40537
|
+
"div",
|
|
40538
|
+
{
|
|
40539
|
+
"data-testid": "swimlane-drop-indicator",
|
|
40540
|
+
style: {
|
|
40541
|
+
position: "absolute",
|
|
40542
|
+
top: 8,
|
|
40543
|
+
bottom: 8,
|
|
40544
|
+
[dropSide]: -1,
|
|
40545
|
+
width: 2,
|
|
40546
|
+
borderRadius: 999,
|
|
40547
|
+
background: GUI_THEME.accent,
|
|
40548
|
+
boxShadow: `0 0 12px ${GUI_THEME.accent}`,
|
|
40549
|
+
zIndex: 2
|
|
40550
|
+
}
|
|
40551
|
+
}
|
|
40552
|
+
),
|
|
40553
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
40003
40554
|
"header",
|
|
40004
40555
|
{
|
|
40556
|
+
draggable: !swimlane.readonly,
|
|
40557
|
+
"data-testid": "swimlane-handle",
|
|
40558
|
+
onDragStart: (event) => {
|
|
40559
|
+
event.stopPropagation();
|
|
40560
|
+
event.dataTransfer.effectAllowed = "move";
|
|
40561
|
+
event.dataTransfer.setData(SWIMLANE_DRAG_TYPE, swimlane.id);
|
|
40562
|
+
event.dataTransfer.setData("text/plain", "");
|
|
40563
|
+
},
|
|
40564
|
+
onDragEnd: onSwimlaneDragEnd,
|
|
40005
40565
|
style: {
|
|
40006
40566
|
height: 48,
|
|
40007
40567
|
flexShrink: 0,
|
|
40008
40568
|
display: "flex",
|
|
40009
40569
|
fontSize: 12,
|
|
40010
40570
|
justifyContent: "space-between",
|
|
40011
|
-
alignItems: "center"
|
|
40571
|
+
alignItems: "center",
|
|
40572
|
+
cursor: swimlane.readonly ? "default" : "grab"
|
|
40012
40573
|
},
|
|
40013
40574
|
children: [
|
|
40014
|
-
/* @__PURE__ */ (0,
|
|
40575
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
40015
40576
|
"div",
|
|
40016
40577
|
{
|
|
40017
40578
|
style: {
|
|
@@ -40020,50 +40581,71 @@ var SwimlaneColumn = ({
|
|
|
40020
40581
|
gap: 8
|
|
40021
40582
|
},
|
|
40022
40583
|
children: [
|
|
40023
|
-
/* @__PURE__ */ (0,
|
|
40584
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
40024
40585
|
"span",
|
|
40025
40586
|
{
|
|
40026
40587
|
style: { color: selected ? GUI_THEME.accent : GUI_THEME.secondary },
|
|
40027
40588
|
children: selected ? "\u276F" : " "
|
|
40028
40589
|
}
|
|
40029
40590
|
),
|
|
40030
|
-
/* @__PURE__ */ (0,
|
|
40591
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
40031
40592
|
"strong",
|
|
40032
40593
|
{
|
|
40033
40594
|
style: { color: selected ? GUI_THEME.accent : GUI_THEME.primary },
|
|
40034
40595
|
children: swimlane.title
|
|
40035
40596
|
}
|
|
40036
40597
|
),
|
|
40037
|
-
/* @__PURE__ */ (0,
|
|
40598
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("span", { style: { color: GUI_THEME.dim }, children: [
|
|
40038
40599
|
"(",
|
|
40039
40600
|
swimlane.issues.length,
|
|
40040
40601
|
")"
|
|
40041
40602
|
] }),
|
|
40042
|
-
swimlane.readonly && /* @__PURE__ */ (0,
|
|
40603
|
+
swimlane.readonly && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
40043
40604
|
"span",
|
|
40044
40605
|
{
|
|
40045
40606
|
title: "Read-only",
|
|
40046
40607
|
style: { display: "flex", color: GUI_THEME.dim },
|
|
40047
|
-
children: /* @__PURE__ */ (0,
|
|
40608
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(IconLock, {})
|
|
40048
40609
|
}
|
|
40049
40610
|
)
|
|
40050
40611
|
]
|
|
40051
40612
|
}
|
|
40052
40613
|
),
|
|
40053
|
-
/* @__PURE__ */ (0,
|
|
40054
|
-
|
|
40055
|
-
|
|
40056
|
-
|
|
40057
|
-
|
|
40058
|
-
|
|
40059
|
-
|
|
40060
|
-
|
|
40061
|
-
|
|
40062
|
-
|
|
40614
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 2 }, children: [
|
|
40615
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
40616
|
+
Button,
|
|
40617
|
+
{
|
|
40618
|
+
variant: "ghost",
|
|
40619
|
+
onClick: () => onCreateIssue(swimlane.id),
|
|
40620
|
+
disabled: swimlane.readonly,
|
|
40621
|
+
title: "Add issue",
|
|
40622
|
+
children: "+"
|
|
40623
|
+
}
|
|
40624
|
+
),
|
|
40625
|
+
!swimlane.readonly && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
40626
|
+
KebabMenu,
|
|
40627
|
+
{
|
|
40628
|
+
testId: "swimlane-menu",
|
|
40629
|
+
items: [
|
|
40630
|
+
{
|
|
40631
|
+
id: "rename",
|
|
40632
|
+
label: "rename",
|
|
40633
|
+
onSelect: () => onRenameSwimlane(swimlane.id)
|
|
40634
|
+
},
|
|
40635
|
+
{
|
|
40636
|
+
id: "delete",
|
|
40637
|
+
label: "delete",
|
|
40638
|
+
danger: true,
|
|
40639
|
+
onSelect: () => onDeleteSwimlane(swimlane.id)
|
|
40640
|
+
}
|
|
40641
|
+
]
|
|
40642
|
+
}
|
|
40643
|
+
)
|
|
40644
|
+
] })
|
|
40063
40645
|
]
|
|
40064
40646
|
}
|
|
40065
40647
|
),
|
|
40066
|
-
/* @__PURE__ */ (0,
|
|
40648
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
40067
40649
|
"div",
|
|
40068
40650
|
{
|
|
40069
40651
|
style: {
|
|
@@ -40074,24 +40656,10 @@ var SwimlaneColumn = ({
|
|
|
40074
40656
|
flex: 1,
|
|
40075
40657
|
minHeight: 0
|
|
40076
40658
|
},
|
|
40077
|
-
children: swimlane.issues.length === 0 ? /* @__PURE__ */ (0,
|
|
40078
|
-
|
|
40079
|
-
|
|
40080
|
-
|
|
40081
|
-
{
|
|
40082
|
-
style: {
|
|
40083
|
-
padding: 24,
|
|
40084
|
-
textAlign: "center",
|
|
40085
|
-
color: GUI_THEME.dim,
|
|
40086
|
-
fontSize: 12
|
|
40087
|
-
},
|
|
40088
|
-
children: "Drop issue here"
|
|
40089
|
-
}
|
|
40090
|
-
)
|
|
40091
|
-
] }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
|
|
40092
|
-
swimlane.issues.map((ticket, index2) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react12.default.Fragment, { children: [
|
|
40093
|
-
dropIndex === index2 && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(DropIndicator, {}),
|
|
40094
|
-
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
40659
|
+
children: swimlane.issues.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_jsx_runtime29.Fragment, {}) : /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_jsx_runtime29.Fragment, { children: [
|
|
40660
|
+
swimlane.issues.map((ticket, index2) => /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_react14.default.Fragment, { children: [
|
|
40661
|
+
dropIndex === index2 && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(DropIndicator, {}),
|
|
40662
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
40095
40663
|
TicketCard,
|
|
40096
40664
|
{
|
|
40097
40665
|
ticket,
|
|
@@ -40109,7 +40677,7 @@ var SwimlaneColumn = ({
|
|
|
40109
40677
|
}
|
|
40110
40678
|
)
|
|
40111
40679
|
] }, ticket.id)),
|
|
40112
|
-
dropIndex === swimlane.issues.length && /* @__PURE__ */ (0,
|
|
40680
|
+
dropIndex === swimlane.issues.length && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(DropIndicator, {})
|
|
40113
40681
|
] })
|
|
40114
40682
|
}
|
|
40115
40683
|
)
|
|
@@ -40119,9 +40687,9 @@ var SwimlaneColumn = ({
|
|
|
40119
40687
|
};
|
|
40120
40688
|
|
|
40121
40689
|
// source/gui/client/components/GlobalScrollbarStyles.tsx
|
|
40122
|
-
var
|
|
40690
|
+
var import_jsx_runtime30 = __toESM(require_jsx_runtime(), 1);
|
|
40123
40691
|
var SCROLLBAR_SIZE = 3;
|
|
40124
|
-
var GlobalScrollbarStyles = () => /* @__PURE__ */ (0,
|
|
40692
|
+
var GlobalScrollbarStyles = () => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("style", { children: `
|
|
40125
40693
|
/* Gated deliberately: Chrome implements scrollbar-width/-color too, and
|
|
40126
40694
|
setting either makes it ignore the ::-webkit-scrollbar rules below. */
|
|
40127
40695
|
@supports not selector(::-webkit-scrollbar) {
|
|
@@ -40162,8 +40730,8 @@ var GlobalScrollbarStyles = () => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
|
40162
40730
|
` });
|
|
40163
40731
|
|
|
40164
40732
|
// source/gui/client/components/ErrorToast.tsx
|
|
40165
|
-
var
|
|
40166
|
-
var ErrorToast = ({ message, onDismiss }) => /* @__PURE__ */ (0,
|
|
40733
|
+
var import_jsx_runtime31 = __toESM(require_jsx_runtime(), 1);
|
|
40734
|
+
var ErrorToast = ({ message, onDismiss }) => /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
40167
40735
|
"div",
|
|
40168
40736
|
{
|
|
40169
40737
|
style: {
|
|
@@ -40184,8 +40752,8 @@ var ErrorToast = ({ message, onDismiss }) => /* @__PURE__ */ (0, import_jsx_runt
|
|
|
40184
40752
|
boxShadow: "0 4px 16px rgba(0, 0, 0, 0.4)"
|
|
40185
40753
|
},
|
|
40186
40754
|
children: [
|
|
40187
|
-
/* @__PURE__ */ (0,
|
|
40188
|
-
/* @__PURE__ */ (0,
|
|
40755
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { style: { flex: 1, minWidth: 0, overflowWrap: "anywhere" }, children: message }),
|
|
40756
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
40189
40757
|
"button",
|
|
40190
40758
|
{
|
|
40191
40759
|
onClick: onDismiss,
|
|
@@ -40206,7 +40774,7 @@ var ErrorToast = ({ message, onDismiss }) => /* @__PURE__ */ (0, import_jsx_runt
|
|
|
40206
40774
|
);
|
|
40207
40775
|
|
|
40208
40776
|
// source/gui/client/components/TimeScrubber.tsx
|
|
40209
|
-
var
|
|
40777
|
+
var import_react17 = __toESM(require_react(), 1);
|
|
40210
40778
|
|
|
40211
40779
|
// source/lib/utils/date.utils.ts
|
|
40212
40780
|
var pad = (n) => String(n).padStart(2, "0");
|
|
@@ -40219,8 +40787,9 @@ var minOf = (values, seed) => values.reduce((min, value) => value < min ? value
|
|
|
40219
40787
|
var maxOf = (values, seed) => values.reduce((max, value) => value > max ? value : max, seed);
|
|
40220
40788
|
|
|
40221
40789
|
// source/gui/client/lib/scrubber.ts
|
|
40222
|
-
var
|
|
40790
|
+
var import_react15 = __toESM(require_react(), 1);
|
|
40223
40791
|
var clamp = (value, min, max) => Math.min(max, Math.max(min, value));
|
|
40792
|
+
var isLayoutMode = (value) => value === "even" || value === "real";
|
|
40224
40793
|
var TRACK_HEIGHT = 24;
|
|
40225
40794
|
var EVENTS_MODE_TOTAL_HEIGHT = 8 + TRACK_HEIGHT * 2;
|
|
40226
40795
|
var EVENTS_SCATTER_HEIGHT = TRACK_HEIGHT + 16;
|
|
@@ -40241,12 +40810,11 @@ var bucketCountForSpan = (spanMs) => {
|
|
|
40241
40810
|
);
|
|
40242
40811
|
};
|
|
40243
40812
|
var buildAxis = (timeline, commits, now = Date.now()) => {
|
|
40244
|
-
const
|
|
40245
|
-
const
|
|
40246
|
-
|
|
40247
|
-
|
|
40248
|
-
);
|
|
40249
|
-
const latest = maxOf(commitBounds, timeline?.latest ?? now);
|
|
40813
|
+
const commitTimes = commits.map((c) => c.time);
|
|
40814
|
+
const windowStart = timeline?.earliest ?? minOf(commitTimes, now);
|
|
40815
|
+
const windowEnd = timeline?.latest ?? maxOf(commitTimes, now);
|
|
40816
|
+
const earliest = minOf(commitTimes, windowStart);
|
|
40817
|
+
const latest = maxOf(commitTimes, windowEnd);
|
|
40250
40818
|
const span = Math.max(1, latest - earliest);
|
|
40251
40819
|
const bucketCount = bucketCountForSpan(span);
|
|
40252
40820
|
const bucketMs = span / bucketCount;
|
|
@@ -40308,6 +40876,7 @@ var CATEGORY_BY_ACTION = {
|
|
|
40308
40876
|
"add.issue.assignee": "assigning",
|
|
40309
40877
|
"remove.issue.assignee": "assigning",
|
|
40310
40878
|
"create.contributor": "assigning",
|
|
40879
|
+
"rename.contributor": "assigning",
|
|
40311
40880
|
"tombstone.contributor": "assigning",
|
|
40312
40881
|
"restore.contributor": "assigning",
|
|
40313
40882
|
"link.contributor.user": "assigning"
|
|
@@ -40353,6 +40922,7 @@ var buildEventDots = (timeline, view = "all", hiddenIds = /* @__PURE__ */ new Se
|
|
|
40353
40922
|
{
|
|
40354
40923
|
// Two events can share a millisecond, so time alone is not a key.
|
|
40355
40924
|
key: `${entry.t}-${index2}`,
|
|
40925
|
+
id: entry.id,
|
|
40356
40926
|
t: entry.t,
|
|
40357
40927
|
count: null,
|
|
40358
40928
|
label: entry.label,
|
|
@@ -40373,6 +40943,7 @@ var buildEventDots = (timeline, view = "all", hiddenIds = /* @__PURE__ */ new Se
|
|
|
40373
40943
|
const intensity = bucket.count / maxCount;
|
|
40374
40944
|
return {
|
|
40375
40945
|
key: String(bucket.t),
|
|
40946
|
+
id: null,
|
|
40376
40947
|
t: bucket.t,
|
|
40377
40948
|
count: bucket.count,
|
|
40378
40949
|
label: null,
|
|
@@ -40392,8 +40963,16 @@ var hourFractionForTime = (time) => {
|
|
|
40392
40963
|
const date = new Date(time);
|
|
40393
40964
|
return (date.getHours() * 60 + date.getMinutes()) / (24 * 60);
|
|
40394
40965
|
};
|
|
40395
|
-
var SEGMENT_UNIT_ORDER = [
|
|
40966
|
+
var SEGMENT_UNIT_ORDER = [
|
|
40967
|
+
"minute",
|
|
40968
|
+
"hour",
|
|
40969
|
+
"day",
|
|
40970
|
+
"week",
|
|
40971
|
+
"month",
|
|
40972
|
+
"year"
|
|
40973
|
+
];
|
|
40396
40974
|
var APPROX_UNIT_MS = {
|
|
40975
|
+
minute: 60 * 1e3,
|
|
40397
40976
|
hour: 60 * 60 * 1e3,
|
|
40398
40977
|
day: 24 * 60 * 60 * 1e3,
|
|
40399
40978
|
week: 7 * 24 * 60 * 60 * 1e3,
|
|
@@ -40401,9 +40980,16 @@ var APPROX_UNIT_MS = {
|
|
|
40401
40980
|
year: 365.25 * 24 * 60 * 60 * 1e3
|
|
40402
40981
|
};
|
|
40403
40982
|
var MAX_SEGMENTS = 35;
|
|
40404
|
-
var
|
|
40405
|
-
|
|
40406
|
-
|
|
40983
|
+
var MIN_SEGMENTS = 2;
|
|
40984
|
+
var chooseSegmentUnit = (spanMs) => {
|
|
40985
|
+
const index2 = SEGMENT_UNIT_ORDER.findIndex(
|
|
40986
|
+
(unit) => spanMs / APPROX_UNIT_MS[unit] <= MAX_SEGMENTS
|
|
40987
|
+
);
|
|
40988
|
+
if (index2 === -1) return "year";
|
|
40989
|
+
const chosen = SEGMENT_UNIT_ORDER[index2];
|
|
40990
|
+
if (spanMs / APPROX_UNIT_MS[chosen] >= MIN_SEGMENTS) return chosen;
|
|
40991
|
+
return SEGMENT_UNIT_ORDER[Math.max(0, index2 - 1)];
|
|
40992
|
+
};
|
|
40407
40993
|
var WEEKDAY_LABELS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
40408
40994
|
var MONTH_LABELS = [
|
|
40409
40995
|
"Jan",
|
|
@@ -40420,7 +41006,8 @@ var MONTH_LABELS = [
|
|
|
40420
41006
|
"Dec"
|
|
40421
41007
|
];
|
|
40422
41008
|
var advanceByUnit = (date, unit) => {
|
|
40423
|
-
if (unit === "
|
|
41009
|
+
if (unit === "minute") date.setMinutes(date.getMinutes() + 1);
|
|
41010
|
+
else if (unit === "hour") date.setHours(date.getHours() + 1);
|
|
40424
41011
|
else if (unit === "day") date.setDate(date.getDate() + 1);
|
|
40425
41012
|
else if (unit === "week") date.setDate(date.getDate() + 7);
|
|
40426
41013
|
else if (unit === "month") date.setMonth(date.getMonth() + 1);
|
|
@@ -40428,7 +41015,8 @@ var advanceByUnit = (date, unit) => {
|
|
|
40428
41015
|
};
|
|
40429
41016
|
var segmentAt = (time, unit) => {
|
|
40430
41017
|
const start2 = new Date(time);
|
|
40431
|
-
if (unit === "
|
|
41018
|
+
if (unit === "minute") start2.setSeconds(0, 0);
|
|
41019
|
+
else if (unit === "hour") start2.setMinutes(0, 0, 0);
|
|
40432
41020
|
else start2.setHours(0, 0, 0, 0);
|
|
40433
41021
|
if (unit === "week") {
|
|
40434
41022
|
start2.setDate(start2.getDate() - (start2.getDay() + 6) % 7);
|
|
@@ -40440,7 +41028,10 @@ var segmentAt = (time, unit) => {
|
|
|
40440
41028
|
const end = new Date(start2);
|
|
40441
41029
|
advanceByUnit(end, unit);
|
|
40442
41030
|
const lastDay = new Date(end.getTime() - 1);
|
|
40443
|
-
const
|
|
41031
|
+
const clock = (date) => `${String(date.getHours()).padStart(2, "0")}:${String(
|
|
41032
|
+
date.getMinutes()
|
|
41033
|
+
).padStart(2, "0")}`;
|
|
41034
|
+
const label = unit === "minute" ? clock(start2) : unit === "hour" ? `${WEEKDAY_LABELS[start2.getDay()]} ${String(start2.getHours()).padStart(
|
|
40444
41035
|
2,
|
|
40445
41036
|
"0"
|
|
40446
41037
|
)}: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()}`;
|
|
@@ -40452,14 +41043,23 @@ var formatInterval = (start2, end) => {
|
|
|
40452
41043
|
const endLabel = isSameDay(startDate, endDate) ? formatTimeOfDay(endDate) : formatDateTime(endDate);
|
|
40453
41044
|
return `${formatDateTime(startDate)} \u2013 ${endLabel}`;
|
|
40454
41045
|
};
|
|
40455
|
-
var SCOPES = [
|
|
41046
|
+
var SCOPES = [
|
|
41047
|
+
"hour",
|
|
41048
|
+
"day",
|
|
41049
|
+
"week",
|
|
41050
|
+
"month",
|
|
41051
|
+
"year",
|
|
41052
|
+
"all"
|
|
41053
|
+
];
|
|
40456
41054
|
var SCOPE_DURATION_MS = {
|
|
41055
|
+
hour: 60 * 60 * 1e3,
|
|
40457
41056
|
day: 24 * 60 * 60 * 1e3,
|
|
40458
41057
|
week: 7 * 24 * 60 * 60 * 1e3,
|
|
40459
41058
|
month: 30 * 24 * 60 * 60 * 1e3,
|
|
40460
41059
|
year: 365 * 24 * 60 * 60 * 1e3
|
|
40461
41060
|
};
|
|
40462
41061
|
var SCOPE_RECENT_LABELS = {
|
|
41062
|
+
hour: "Last hour",
|
|
40463
41063
|
day: "Last 24 hours",
|
|
40464
41064
|
week: "Last 7 days",
|
|
40465
41065
|
month: "Last 30 days",
|
|
@@ -40542,10 +41142,10 @@ var SCRUBBER_KEYFRAMES = `
|
|
|
40542
41142
|
`;
|
|
40543
41143
|
var REDUCED_MOTION_QUERY = "(prefers-reduced-motion: reduce)";
|
|
40544
41144
|
var usePrefersReducedMotion = () => {
|
|
40545
|
-
const [reduced, setReduced] = (0,
|
|
41145
|
+
const [reduced, setReduced] = (0, import_react15.useState)(
|
|
40546
41146
|
() => window.matchMedia(REDUCED_MOTION_QUERY).matches
|
|
40547
41147
|
);
|
|
40548
|
-
(0,
|
|
41148
|
+
(0, import_react15.useEffect)(() => {
|
|
40549
41149
|
const query = window.matchMedia(REDUCED_MOTION_QUERY);
|
|
40550
41150
|
const onChange = () => setReduced(query.matches);
|
|
40551
41151
|
query.addEventListener("change", onChange);
|
|
@@ -40554,12 +41154,12 @@ var usePrefersReducedMotion = () => {
|
|
|
40554
41154
|
return reduced;
|
|
40555
41155
|
};
|
|
40556
41156
|
var useExitTransition = (visible, durationMs) => {
|
|
40557
|
-
const [mounted, setMounted] = (0,
|
|
40558
|
-
const [leaving, setLeaving] = (0,
|
|
40559
|
-
const wasVisible = (0,
|
|
40560
|
-
const duration = (0,
|
|
41157
|
+
const [mounted, setMounted] = (0, import_react15.useState)(visible);
|
|
41158
|
+
const [leaving, setLeaving] = (0, import_react15.useState)(false);
|
|
41159
|
+
const wasVisible = (0, import_react15.useRef)(visible);
|
|
41160
|
+
const duration = (0, import_react15.useRef)(durationMs);
|
|
40561
41161
|
duration.current = durationMs;
|
|
40562
|
-
(0,
|
|
41162
|
+
(0, import_react15.useEffect)(() => {
|
|
40563
41163
|
if (visible === wasVisible.current) return;
|
|
40564
41164
|
wasVisible.current = visible;
|
|
40565
41165
|
if (visible) {
|
|
@@ -40578,10 +41178,10 @@ var useExitTransition = (visible, durationMs) => {
|
|
|
40578
41178
|
}, duration.current);
|
|
40579
41179
|
return () => clearTimeout(timeout);
|
|
40580
41180
|
}, [visible]);
|
|
40581
|
-
return { mounted, leaving };
|
|
41181
|
+
return (0, import_react15.useMemo)(() => ({ mounted, leaving }), [mounted, leaving]);
|
|
40582
41182
|
};
|
|
40583
41183
|
var usePersistedFlag = (key, fallback) => {
|
|
40584
|
-
const [value, setValue] = (0,
|
|
41184
|
+
const [value, setValue] = (0, import_react15.useState)(() => {
|
|
40585
41185
|
const stored = localStorage.getItem(key);
|
|
40586
41186
|
return stored === null ? fallback : stored === "true";
|
|
40587
41187
|
});
|
|
@@ -40608,10 +41208,10 @@ var issuePassesBoardFilter = (issue, commentAuthorIds, filter) => {
|
|
|
40608
41208
|
};
|
|
40609
41209
|
|
|
40610
41210
|
// source/gui/client/components/ScrubberParts.tsx
|
|
40611
|
-
var
|
|
41211
|
+
var import_react16 = __toESM(require_react(), 1);
|
|
40612
41212
|
|
|
40613
41213
|
// source/gui/client/components/Checkbox.tsx
|
|
40614
|
-
var
|
|
41214
|
+
var import_jsx_runtime32 = __toESM(require_jsx_runtime(), 1);
|
|
40615
41215
|
var Checkbox = ({
|
|
40616
41216
|
label,
|
|
40617
41217
|
checked,
|
|
@@ -40621,7 +41221,7 @@ var Checkbox = ({
|
|
|
40621
41221
|
title
|
|
40622
41222
|
}) => {
|
|
40623
41223
|
const color2 = checked ? activeColor : GUI_THEME.dim;
|
|
40624
|
-
return /* @__PURE__ */ (0,
|
|
41224
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
40625
41225
|
"label",
|
|
40626
41226
|
{
|
|
40627
41227
|
title,
|
|
@@ -40635,7 +41235,7 @@ var Checkbox = ({
|
|
|
40635
41235
|
opacity: disabled ? 0.4 : 1
|
|
40636
41236
|
},
|
|
40637
41237
|
children: [
|
|
40638
|
-
/* @__PURE__ */ (0,
|
|
41238
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
40639
41239
|
"span",
|
|
40640
41240
|
{
|
|
40641
41241
|
style: {
|
|
@@ -40652,7 +41252,7 @@ var Checkbox = ({
|
|
|
40652
41252
|
flexShrink: 0
|
|
40653
41253
|
},
|
|
40654
41254
|
children: [
|
|
40655
|
-
/* @__PURE__ */ (0,
|
|
41255
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
40656
41256
|
"input",
|
|
40657
41257
|
{
|
|
40658
41258
|
type: "checkbox",
|
|
@@ -40670,7 +41270,7 @@ var Checkbox = ({
|
|
|
40670
41270
|
}
|
|
40671
41271
|
}
|
|
40672
41272
|
),
|
|
40673
|
-
checked && /* @__PURE__ */ (0,
|
|
41273
|
+
checked && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
40674
41274
|
"span",
|
|
40675
41275
|
{
|
|
40676
41276
|
style: {
|
|
@@ -40691,8 +41291,8 @@ var Checkbox = ({
|
|
|
40691
41291
|
};
|
|
40692
41292
|
|
|
40693
41293
|
// source/gui/client/components/IconBars.tsx
|
|
40694
|
-
var
|
|
40695
|
-
var IconBars = ({ size = 16 }) => /* @__PURE__ */ (0,
|
|
41294
|
+
var import_jsx_runtime33 = __toESM(require_jsx_runtime(), 1);
|
|
41295
|
+
var IconBars = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
40696
41296
|
"svg",
|
|
40697
41297
|
{
|
|
40698
41298
|
width: size,
|
|
@@ -40704,18 +41304,18 @@ var IconBars = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)
|
|
|
40704
41304
|
strokeLinecap: "round",
|
|
40705
41305
|
"aria-hidden": "true",
|
|
40706
41306
|
children: [
|
|
40707
|
-
/* @__PURE__ */ (0,
|
|
40708
|
-
/* @__PURE__ */ (0,
|
|
40709
|
-
/* @__PURE__ */ (0,
|
|
40710
|
-
/* @__PURE__ */ (0,
|
|
40711
|
-
/* @__PURE__ */ (0,
|
|
41307
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("line", { x1: "3", y1: "8.5", x2: "3", y2: "15.5" }),
|
|
41308
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("line", { x1: "7.5", y1: "4.5", x2: "7.5", y2: "19.5" }),
|
|
41309
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("line", { x1: "12", y1: "7", x2: "12", y2: "17" }),
|
|
41310
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("line", { x1: "16.5", y1: "3", x2: "16.5", y2: "21" }),
|
|
41311
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("line", { x1: "21", y1: "9.5", x2: "21", y2: "14.5" })
|
|
40712
41312
|
]
|
|
40713
41313
|
}
|
|
40714
41314
|
);
|
|
40715
41315
|
|
|
40716
41316
|
// source/gui/client/components/IconChevronDown.tsx
|
|
40717
|
-
var
|
|
40718
|
-
var IconChevronDown = ({ size = 16 }) => /* @__PURE__ */ (0,
|
|
41317
|
+
var import_jsx_runtime34 = __toESM(require_jsx_runtime(), 1);
|
|
41318
|
+
var IconChevronDown = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
40719
41319
|
"svg",
|
|
40720
41320
|
{
|
|
40721
41321
|
width: size,
|
|
@@ -40727,13 +41327,13 @@ var IconChevronDown = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime2
|
|
|
40727
41327
|
strokeLinecap: "round",
|
|
40728
41328
|
strokeLinejoin: "round",
|
|
40729
41329
|
"aria-hidden": "true",
|
|
40730
|
-
children: /* @__PURE__ */ (0,
|
|
41330
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("polyline", { points: "6 9 12 15 18 9" })
|
|
40731
41331
|
}
|
|
40732
41332
|
);
|
|
40733
41333
|
|
|
40734
41334
|
// source/gui/client/components/IconChevronRight.tsx
|
|
40735
|
-
var
|
|
40736
|
-
var IconChevronRight = ({ size = 16 }) => /* @__PURE__ */ (0,
|
|
41335
|
+
var import_jsx_runtime35 = __toESM(require_jsx_runtime(), 1);
|
|
41336
|
+
var IconChevronRight = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
40737
41337
|
"svg",
|
|
40738
41338
|
{
|
|
40739
41339
|
width: size,
|
|
@@ -40745,13 +41345,13 @@ var IconChevronRight = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime
|
|
|
40745
41345
|
strokeLinecap: "round",
|
|
40746
41346
|
strokeLinejoin: "round",
|
|
40747
41347
|
"aria-hidden": "true",
|
|
40748
|
-
children: /* @__PURE__ */ (0,
|
|
41348
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("polyline", { points: "9 18 15 12 9 6" })
|
|
40749
41349
|
}
|
|
40750
41350
|
);
|
|
40751
41351
|
|
|
40752
41352
|
// source/gui/client/components/IconScatter.tsx
|
|
40753
|
-
var
|
|
40754
|
-
var IconScatter = ({ size = 16 }) => /* @__PURE__ */ (0,
|
|
41353
|
+
var import_jsx_runtime36 = __toESM(require_jsx_runtime(), 1);
|
|
41354
|
+
var IconScatter = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
40755
41355
|
"svg",
|
|
40756
41356
|
{
|
|
40757
41357
|
width: size,
|
|
@@ -40761,17 +41361,17 @@ var IconScatter = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime31.js
|
|
|
40761
41361
|
stroke: "none",
|
|
40762
41362
|
"aria-hidden": "true",
|
|
40763
41363
|
children: [
|
|
40764
|
-
/* @__PURE__ */ (0,
|
|
40765
|
-
/* @__PURE__ */ (0,
|
|
40766
|
-
/* @__PURE__ */ (0,
|
|
40767
|
-
/* @__PURE__ */ (0,
|
|
40768
|
-
/* @__PURE__ */ (0,
|
|
41364
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("circle", { cx: "4.5", cy: "8", r: "2.2" }),
|
|
41365
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("circle", { cx: "9.5", cy: "17", r: "2.2" }),
|
|
41366
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("circle", { cx: "13", cy: "6.5", r: "2.2" }),
|
|
41367
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("circle", { cx: "17", cy: "14.5", r: "2.2" }),
|
|
41368
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("circle", { cx: "20.5", cy: "8.5", r: "2.2" })
|
|
40769
41369
|
]
|
|
40770
41370
|
}
|
|
40771
41371
|
);
|
|
40772
41372
|
|
|
40773
41373
|
// source/gui/client/components/ScrubberParts.tsx
|
|
40774
|
-
var
|
|
41374
|
+
var import_jsx_runtime37 = __toESM(require_jsx_runtime(), 1);
|
|
40775
41375
|
var toggleButtonStyle = (active) => ({
|
|
40776
41376
|
background: "transparent",
|
|
40777
41377
|
border: `1px solid ${active ? GUI_THEME.accent : GUI_THEME.dim}`,
|
|
@@ -40781,6 +41381,20 @@ var toggleButtonStyle = (active) => ({
|
|
|
40781
41381
|
padding: "2px 8px",
|
|
40782
41382
|
cursor: "pointer"
|
|
40783
41383
|
});
|
|
41384
|
+
var scopeButtonStyle = (active) => ({
|
|
41385
|
+
background: "transparent",
|
|
41386
|
+
border: "none",
|
|
41387
|
+
borderBottom: `1px solid ${active ? GUI_THEME.accent : "transparent"}`,
|
|
41388
|
+
color: active ? GUI_THEME.primary : GUI_THEME.dim,
|
|
41389
|
+
borderRadius: 0,
|
|
41390
|
+
fontSize: 10,
|
|
41391
|
+
padding: "2px 6px 3px",
|
|
41392
|
+
cursor: "pointer"
|
|
41393
|
+
});
|
|
41394
|
+
var mutedStyle = {
|
|
41395
|
+
opacity: 0.4,
|
|
41396
|
+
cursor: "not-allowed"
|
|
41397
|
+
};
|
|
40784
41398
|
var iconToggleButtonStyle = (active) => ({
|
|
40785
41399
|
...toggleButtonStyle(active),
|
|
40786
41400
|
display: "inline-flex",
|
|
@@ -40873,8 +41487,8 @@ var onlyButtonStyle = {
|
|
|
40873
41487
|
cursor: "pointer"
|
|
40874
41488
|
};
|
|
40875
41489
|
var useDismissOnOutsideClick = (open, onDismiss) => {
|
|
40876
|
-
const ref = (0,
|
|
40877
|
-
(0,
|
|
41490
|
+
const ref = (0, import_react16.useRef)(null);
|
|
41491
|
+
(0, import_react16.useEffect)(() => {
|
|
40878
41492
|
if (!open) return;
|
|
40879
41493
|
const onPointerDown = (event) => {
|
|
40880
41494
|
if (!ref.current?.contains(event.target)) onDismiss();
|
|
@@ -40897,7 +41511,7 @@ var Radio = ({
|
|
|
40897
41511
|
color: color2,
|
|
40898
41512
|
disabled,
|
|
40899
41513
|
onSelect
|
|
40900
|
-
}) => /* @__PURE__ */ (0,
|
|
41514
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
|
|
40901
41515
|
"button",
|
|
40902
41516
|
{
|
|
40903
41517
|
type: "button",
|
|
@@ -40919,7 +41533,7 @@ var Radio = ({
|
|
|
40919
41533
|
opacity: disabled ? 0.4 : 1
|
|
40920
41534
|
},
|
|
40921
41535
|
children: [
|
|
40922
|
-
/* @__PURE__ */ (0,
|
|
41536
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
40923
41537
|
"span",
|
|
40924
41538
|
{
|
|
40925
41539
|
style: {
|
|
@@ -40932,7 +41546,7 @@ var Radio = ({
|
|
|
40932
41546
|
justifyContent: "center",
|
|
40933
41547
|
flexShrink: 0
|
|
40934
41548
|
},
|
|
40935
|
-
children: selected && /* @__PURE__ */ (0,
|
|
41549
|
+
children: selected && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
40936
41550
|
"span",
|
|
40937
41551
|
{
|
|
40938
41552
|
style: {
|
|
@@ -40950,6 +41564,7 @@ var Radio = ({
|
|
|
40950
41564
|
}
|
|
40951
41565
|
);
|
|
40952
41566
|
var BoardSeriesGroup = ({
|
|
41567
|
+
connected,
|
|
40953
41568
|
showIssues,
|
|
40954
41569
|
view,
|
|
40955
41570
|
identities,
|
|
@@ -40969,35 +41584,39 @@ var BoardSeriesGroup = ({
|
|
|
40969
41584
|
const label = sole ? `${VIEW_LABELS[view]}: ${sole.name}` : partial ? `${VIEW_LABELS[view]} (multi)` : VIEW_LABELS[view];
|
|
40970
41585
|
const color2 = sole?.color ?? (partial ? GUI_THEME.dim2 : boardViewColor(view));
|
|
40971
41586
|
const ref = useDismissOnOutsideClick(expanded, onToggleExpanded);
|
|
40972
|
-
return /* @__PURE__ */ (0,
|
|
41587
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
|
|
40973
41588
|
"div",
|
|
40974
41589
|
{
|
|
40975
41590
|
ref,
|
|
40976
41591
|
style: { position: "relative", display: "flex", flexDirection: "column" },
|
|
40977
41592
|
children: [
|
|
40978
|
-
/* @__PURE__ */ (0,
|
|
40979
|
-
/* @__PURE__ */ (0,
|
|
41593
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
|
|
41594
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
40980
41595
|
Checkbox,
|
|
40981
41596
|
{
|
|
40982
41597
|
label: null,
|
|
40983
41598
|
title: "Show board events",
|
|
40984
41599
|
checked: showIssues,
|
|
40985
41600
|
activeColor: color2,
|
|
41601
|
+
disabled: !connected,
|
|
40986
41602
|
onChange: onChangeShowIssues
|
|
40987
41603
|
}
|
|
40988
41604
|
),
|
|
40989
|
-
/* @__PURE__ */ (0,
|
|
41605
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
|
|
40990
41606
|
"button",
|
|
40991
41607
|
{
|
|
40992
41608
|
type: "button",
|
|
40993
41609
|
onClick: onToggleExpanded,
|
|
40994
|
-
disabled: !showIssues,
|
|
41610
|
+
disabled: !showIssues || !connected,
|
|
40995
41611
|
title: filtered ? "Choose what the board series plots" : "This window holds too many events to split by kind",
|
|
40996
41612
|
"aria-haspopup": "listbox",
|
|
40997
41613
|
"aria-expanded": expanded,
|
|
40998
|
-
style:
|
|
41614
|
+
style: {
|
|
41615
|
+
...selectTriggerStyle(color2, !showIssues),
|
|
41616
|
+
...connected ? {} : mutedStyle
|
|
41617
|
+
},
|
|
40999
41618
|
children: [
|
|
41000
|
-
/* @__PURE__ */ (0,
|
|
41619
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
41001
41620
|
"span",
|
|
41002
41621
|
{
|
|
41003
41622
|
style: {
|
|
@@ -41008,22 +41627,22 @@ var BoardSeriesGroup = ({
|
|
|
41008
41627
|
children: label
|
|
41009
41628
|
}
|
|
41010
41629
|
),
|
|
41011
|
-
/* @__PURE__ */ (0,
|
|
41630
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { style: { display: "inline-flex", flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(IconChevronDown, { size: 12 }) })
|
|
41012
41631
|
]
|
|
41013
41632
|
}
|
|
41014
41633
|
)
|
|
41015
41634
|
] }),
|
|
41016
|
-
expanded && /* @__PURE__ */ (0,
|
|
41635
|
+
expanded && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { role: "radiogroup", style: popoverStyle, children: BOARD_VIEWS.map((option) => {
|
|
41017
41636
|
const selected = view === option;
|
|
41018
41637
|
const hasList = identityAxisFor(option) !== null;
|
|
41019
41638
|
const open = selected && identitiesExpanded;
|
|
41020
|
-
return /* @__PURE__ */ (0,
|
|
41639
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
|
|
41021
41640
|
"div",
|
|
41022
41641
|
{
|
|
41023
41642
|
style: { display: "flex", flexDirection: "column", gap: 7 },
|
|
41024
41643
|
children: [
|
|
41025
|
-
/* @__PURE__ */ (0,
|
|
41026
|
-
/* @__PURE__ */ (0,
|
|
41644
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 3 }, children: [
|
|
41645
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
41027
41646
|
Radio,
|
|
41028
41647
|
{
|
|
41029
41648
|
label: VIEW_LABELS[option],
|
|
@@ -41033,7 +41652,7 @@ var BoardSeriesGroup = ({
|
|
|
41033
41652
|
onSelect: () => onChangeView(option)
|
|
41034
41653
|
}
|
|
41035
41654
|
),
|
|
41036
|
-
hasList && /* @__PURE__ */ (0,
|
|
41655
|
+
hasList && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
41037
41656
|
"button",
|
|
41038
41657
|
{
|
|
41039
41658
|
type: "button",
|
|
@@ -41045,11 +41664,11 @@ var BoardSeriesGroup = ({
|
|
|
41045
41664
|
title: open ? "Hide the list" : "Pick which to show",
|
|
41046
41665
|
"aria-expanded": open,
|
|
41047
41666
|
style: disclosureStyle,
|
|
41048
|
-
children: open ? /* @__PURE__ */ (0,
|
|
41667
|
+
children: open ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(IconChevronDown, { size: 12 }) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(IconChevronRight, { size: 12 })
|
|
41049
41668
|
}
|
|
41050
41669
|
)
|
|
41051
41670
|
] }),
|
|
41052
|
-
open && identities.length > 0 && /* @__PURE__ */ (0,
|
|
41671
|
+
open && identities.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
41053
41672
|
"div",
|
|
41054
41673
|
{
|
|
41055
41674
|
style: {
|
|
@@ -41059,7 +41678,7 @@ var BoardSeriesGroup = ({
|
|
|
41059
41678
|
maxHeight: 132,
|
|
41060
41679
|
overflowY: "auto"
|
|
41061
41680
|
},
|
|
41062
|
-
children: identities.map((identity) => /* @__PURE__ */ (0,
|
|
41681
|
+
children: identities.map((identity) => /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
|
|
41063
41682
|
"div",
|
|
41064
41683
|
{
|
|
41065
41684
|
style: {
|
|
@@ -41069,7 +41688,7 @@ var BoardSeriesGroup = ({
|
|
|
41069
41688
|
gap: 10
|
|
41070
41689
|
},
|
|
41071
41690
|
children: [
|
|
41072
|
-
/* @__PURE__ */ (0,
|
|
41691
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
41073
41692
|
Checkbox,
|
|
41074
41693
|
{
|
|
41075
41694
|
label: identity.name,
|
|
@@ -41079,7 +41698,7 @@ var BoardSeriesGroup = ({
|
|
|
41079
41698
|
onChange: (next) => onToggleIdentity(identity.id, next)
|
|
41080
41699
|
}
|
|
41081
41700
|
),
|
|
41082
|
-
/* @__PURE__ */ (0,
|
|
41701
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
41083
41702
|
"button",
|
|
41084
41703
|
{
|
|
41085
41704
|
type: "button",
|
|
@@ -41116,6 +41735,7 @@ var navButtonStyle = {
|
|
|
41116
41735
|
lineHeight: 1
|
|
41117
41736
|
};
|
|
41118
41737
|
var ScrubberControls = ({
|
|
41738
|
+
connected,
|
|
41119
41739
|
scope,
|
|
41120
41740
|
offset,
|
|
41121
41741
|
periodRange,
|
|
@@ -41142,7 +41762,7 @@ var ScrubberControls = ({
|
|
|
41142
41762
|
onOnlyIdentity,
|
|
41143
41763
|
onToggleCategoriesExpanded,
|
|
41144
41764
|
onSetIdentitiesExpanded
|
|
41145
|
-
}) => /* @__PURE__ */ (0,
|
|
41765
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
|
|
41146
41766
|
"div",
|
|
41147
41767
|
{
|
|
41148
41768
|
style: {
|
|
@@ -41152,18 +41772,19 @@ var ScrubberControls = ({
|
|
|
41152
41772
|
gap: 12
|
|
41153
41773
|
},
|
|
41154
41774
|
children: [
|
|
41155
|
-
/* @__PURE__ */ (0,
|
|
41156
|
-
scope !== "all" && /* @__PURE__ */ (0,
|
|
41157
|
-
/* @__PURE__ */ (0,
|
|
41775
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
|
|
41776
|
+
scope !== "all" && /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 2 }, children: [
|
|
41777
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
41158
41778
|
"button",
|
|
41159
41779
|
{
|
|
41160
41780
|
title: "Earlier",
|
|
41781
|
+
disabled: !connected,
|
|
41161
41782
|
onClick: () => onChangeOffset(offset + 1),
|
|
41162
|
-
style: navButtonStyle,
|
|
41783
|
+
style: { ...navButtonStyle, ...connected ? {} : mutedStyle },
|
|
41163
41784
|
children: "\u25C0"
|
|
41164
41785
|
}
|
|
41165
41786
|
),
|
|
41166
|
-
/* @__PURE__ */ (0,
|
|
41787
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
41167
41788
|
"span",
|
|
41168
41789
|
{
|
|
41169
41790
|
style: {
|
|
@@ -41180,11 +41801,11 @@ var ScrubberControls = ({
|
|
|
41180
41801
|
children: formatPeriodLabel(scope, offset, periodRange)
|
|
41181
41802
|
}
|
|
41182
41803
|
),
|
|
41183
|
-
/* @__PURE__ */ (0,
|
|
41804
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
41184
41805
|
"button",
|
|
41185
41806
|
{
|
|
41186
41807
|
title: "Later",
|
|
41187
|
-
disabled: offset === 0,
|
|
41808
|
+
disabled: offset === 0 || !connected,
|
|
41188
41809
|
onClick: () => onChangeOffset(Math.max(0, offset - 1)),
|
|
41189
41810
|
style: {
|
|
41190
41811
|
...navButtonStyle,
|
|
@@ -41195,53 +41816,68 @@ var ScrubberControls = ({
|
|
|
41195
41816
|
}
|
|
41196
41817
|
)
|
|
41197
41818
|
] }),
|
|
41198
|
-
/* @__PURE__ */ (0,
|
|
41819
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { style: { display: "flex", gap: 2 }, children: SCOPES.map((option) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
41199
41820
|
"button",
|
|
41200
41821
|
{
|
|
41822
|
+
"aria-pressed": scope === option,
|
|
41823
|
+
disabled: !connected,
|
|
41201
41824
|
onClick: () => onChangeScope(option),
|
|
41202
|
-
style:
|
|
41825
|
+
style: {
|
|
41826
|
+
...scopeButtonStyle(scope === option),
|
|
41827
|
+
...connected ? {} : mutedStyle
|
|
41828
|
+
},
|
|
41203
41829
|
children: scopeButtonLabel(option)
|
|
41204
41830
|
},
|
|
41205
41831
|
option
|
|
41206
41832
|
)) })
|
|
41207
41833
|
] }),
|
|
41208
|
-
/* @__PURE__ */ (0,
|
|
41209
|
-
/* @__PURE__ */ (0,
|
|
41834
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { style: { display: "flex", gap: 2 }, children: [
|
|
41835
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
41210
41836
|
"button",
|
|
41211
41837
|
{
|
|
41212
41838
|
title: "Volume \u2014 how much happened, per equal-width period, with no empty gaps for quiet stretches",
|
|
41213
41839
|
"aria-label": "Volume",
|
|
41214
41840
|
"aria-pressed": layoutMode === "even",
|
|
41841
|
+
disabled: !connected,
|
|
41215
41842
|
onClick: () => onChangeLayoutMode("even"),
|
|
41216
|
-
style:
|
|
41217
|
-
|
|
41843
|
+
style: {
|
|
41844
|
+
...iconToggleButtonStyle(layoutMode === "even"),
|
|
41845
|
+
...connected ? {} : mutedStyle
|
|
41846
|
+
},
|
|
41847
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(IconBars, { size: 13 })
|
|
41218
41848
|
}
|
|
41219
41849
|
),
|
|
41220
|
-
/* @__PURE__ */ (0,
|
|
41850
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
41221
41851
|
"button",
|
|
41222
41852
|
{
|
|
41223
41853
|
title: "Events \u2014 individual events by exact moment, x is elapsed time and y is time of day",
|
|
41224
41854
|
"aria-label": "Events",
|
|
41225
41855
|
"aria-pressed": layoutMode === "real",
|
|
41856
|
+
disabled: !connected,
|
|
41226
41857
|
onClick: () => onChangeLayoutMode("real"),
|
|
41227
|
-
style:
|
|
41228
|
-
|
|
41858
|
+
style: {
|
|
41859
|
+
...iconToggleButtonStyle(layoutMode === "real"),
|
|
41860
|
+
...connected ? {} : mutedStyle
|
|
41861
|
+
},
|
|
41862
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(IconScatter, { size: 13 })
|
|
41229
41863
|
}
|
|
41230
41864
|
)
|
|
41231
41865
|
] }),
|
|
41232
|
-
/* @__PURE__ */ (0,
|
|
41233
|
-
/* @__PURE__ */ (0,
|
|
41866
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { style: { display: "flex", gap: 12, alignItems: "center" }, children: [
|
|
41867
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
41234
41868
|
Checkbox,
|
|
41235
41869
|
{
|
|
41236
41870
|
label: "Code",
|
|
41237
41871
|
checked: showCommits,
|
|
41238
41872
|
activeColor: GUI_THEME.green,
|
|
41873
|
+
disabled: !connected,
|
|
41239
41874
|
onChange: onChangeShowCommits
|
|
41240
41875
|
}
|
|
41241
41876
|
),
|
|
41242
|
-
/* @__PURE__ */ (0,
|
|
41877
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
41243
41878
|
BoardSeriesGroup,
|
|
41244
41879
|
{
|
|
41880
|
+
connected,
|
|
41245
41881
|
showIssues,
|
|
41246
41882
|
view: boardView,
|
|
41247
41883
|
identities,
|
|
@@ -41258,7 +41894,7 @@ var ScrubberControls = ({
|
|
|
41258
41894
|
}
|
|
41259
41895
|
)
|
|
41260
41896
|
] }),
|
|
41261
|
-
/* @__PURE__ */ (0,
|
|
41897
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
41262
41898
|
"button",
|
|
41263
41899
|
{
|
|
41264
41900
|
onClick: onReturnToLive,
|
|
@@ -41289,7 +41925,7 @@ var ScrubberControls = ({
|
|
|
41289
41925
|
var ScrubberHeader = ({
|
|
41290
41926
|
collapsed,
|
|
41291
41927
|
onToggleCollapsed
|
|
41292
|
-
}) => /* @__PURE__ */ (0,
|
|
41928
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
41293
41929
|
"div",
|
|
41294
41930
|
{
|
|
41295
41931
|
style: {
|
|
@@ -41299,7 +41935,7 @@ var ScrubberHeader = ({
|
|
|
41299
41935
|
fontSize: 11,
|
|
41300
41936
|
whiteSpace: "nowrap"
|
|
41301
41937
|
},
|
|
41302
|
-
children: /* @__PURE__ */ (0,
|
|
41938
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
41303
41939
|
"button",
|
|
41304
41940
|
{
|
|
41305
41941
|
onClick: onToggleCollapsed,
|
|
@@ -41316,7 +41952,7 @@ var ScrubberHeader = ({
|
|
|
41316
41952
|
display: "inline-flex",
|
|
41317
41953
|
alignItems: "center"
|
|
41318
41954
|
},
|
|
41319
|
-
children: collapsed ? /* @__PURE__ */ (0,
|
|
41955
|
+
children: collapsed ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(IconChevronRight, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(IconChevronDown, { size: 14 })
|
|
41320
41956
|
}
|
|
41321
41957
|
)
|
|
41322
41958
|
}
|
|
@@ -41326,7 +41962,7 @@ var SegmentHighlight = ({
|
|
|
41326
41962
|
fractionForTime
|
|
41327
41963
|
}) => {
|
|
41328
41964
|
const left = fractionForTime(segment.start);
|
|
41329
|
-
return /* @__PURE__ */ (0,
|
|
41965
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
41330
41966
|
"div",
|
|
41331
41967
|
{
|
|
41332
41968
|
style: {
|
|
@@ -41358,7 +41994,7 @@ var SegmentHighlight = ({
|
|
|
41358
41994
|
var TrackBaseline = ({
|
|
41359
41995
|
color: color2,
|
|
41360
41996
|
anchor
|
|
41361
|
-
}) => /* @__PURE__ */ (0,
|
|
41997
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
41362
41998
|
"div",
|
|
41363
41999
|
{
|
|
41364
42000
|
style: {
|
|
@@ -41374,11 +42010,11 @@ var TrackBaseline = ({
|
|
|
41374
42010
|
}
|
|
41375
42011
|
}
|
|
41376
42012
|
);
|
|
41377
|
-
var HourAxisLabels = () => /* @__PURE__ */ (0,
|
|
42013
|
+
var HourAxisLabels = () => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_jsx_runtime37.Fragment, { children: [
|
|
41378
42014
|
["00:00", { top: EVENTS_MODE_VERTICAL_PADDING }],
|
|
41379
42015
|
["12:00", { top: "50%", transform: "translateY(-50%)" }],
|
|
41380
42016
|
["24:00", { bottom: EVENTS_MODE_VERTICAL_PADDING }]
|
|
41381
|
-
].map(([label, position3]) => /* @__PURE__ */ (0,
|
|
42017
|
+
].map(([label, position3]) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
41382
42018
|
"span",
|
|
41383
42019
|
{
|
|
41384
42020
|
style: {
|
|
@@ -41396,7 +42032,7 @@ var HourAxisLabels = () => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_
|
|
|
41396
42032
|
var SeriesLayer = ({
|
|
41397
42033
|
animate,
|
|
41398
42034
|
children
|
|
41399
|
-
}) => /* @__PURE__ */ (0,
|
|
42035
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
41400
42036
|
"div",
|
|
41401
42037
|
{
|
|
41402
42038
|
style: {
|
|
@@ -41412,12 +42048,30 @@ var SeriesLayer = ({
|
|
|
41412
42048
|
children
|
|
41413
42049
|
}
|
|
41414
42050
|
);
|
|
41415
|
-
var
|
|
42051
|
+
var BucketHighlight = ({
|
|
42052
|
+
index: index2,
|
|
42053
|
+
bucketCount
|
|
42054
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
42055
|
+
"div",
|
|
42056
|
+
{
|
|
42057
|
+
style: {
|
|
42058
|
+
position: "absolute",
|
|
42059
|
+
left: `${index2 * (100 / bucketCount)}%`,
|
|
42060
|
+
top: 0,
|
|
42061
|
+
bottom: 0,
|
|
42062
|
+
width: `${100 / bucketCount}%`,
|
|
42063
|
+
// A bucket can be thinner than a pixel at wide spans.
|
|
42064
|
+
minWidth: 2,
|
|
42065
|
+
background: BUCKET_HIGHLIGHT_COLOR,
|
|
42066
|
+
pointerEvents: "none"
|
|
42067
|
+
}
|
|
42068
|
+
}
|
|
42069
|
+
);
|
|
42070
|
+
var VolumeBarsImpl = ({
|
|
41416
42071
|
bars,
|
|
41417
42072
|
bucketCount,
|
|
41418
42073
|
firstBar,
|
|
41419
42074
|
lastBar,
|
|
41420
|
-
highlightedIndex,
|
|
41421
42075
|
color: color2,
|
|
41422
42076
|
direction,
|
|
41423
42077
|
animate
|
|
@@ -41425,57 +42079,40 @@ var VolumeBars = ({
|
|
|
41425
42079
|
const widthPercent = 100 / bucketCount;
|
|
41426
42080
|
const barWidth = barWidthCss(bucketCount);
|
|
41427
42081
|
const growsUp = direction === "up";
|
|
41428
|
-
const [fresh, setFresh] = (0,
|
|
41429
|
-
(0,
|
|
42082
|
+
const [fresh, setFresh] = (0, import_react16.useState)(true);
|
|
42083
|
+
(0, import_react16.useEffect)(() => {
|
|
41430
42084
|
const timeout = setTimeout(() => setFresh(false), BAR_ENTRANCE_TOTAL_MS);
|
|
41431
42085
|
return () => clearTimeout(timeout);
|
|
41432
42086
|
}, []);
|
|
41433
|
-
return /* @__PURE__ */ (0,
|
|
41434
|
-
|
|
41435
|
-
|
|
41436
|
-
{
|
|
41437
|
-
|
|
41438
|
-
|
|
41439
|
-
|
|
41440
|
-
|
|
41441
|
-
|
|
41442
|
-
|
|
41443
|
-
|
|
41444
|
-
|
|
41445
|
-
|
|
41446
|
-
|
|
41447
|
-
|
|
42087
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_jsx_runtime37.Fragment, { children: bars.map(({ index: index2, intensity }) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
42088
|
+
"div",
|
|
42089
|
+
{
|
|
42090
|
+
style: {
|
|
42091
|
+
position: "absolute",
|
|
42092
|
+
left: `${index2 * widthPercent}%`,
|
|
42093
|
+
...growsUp ? { bottom: 0 } : { top: 0 },
|
|
42094
|
+
width: barWidth,
|
|
42095
|
+
height: 3 + intensity * (TRACK_HEIGHT - 3),
|
|
42096
|
+
borderRadius: growsUp ? "1px 1px 0 0" : "0 0 1px 1px",
|
|
42097
|
+
background: color2,
|
|
42098
|
+
opacity: 0.35 + intensity * 0.65,
|
|
42099
|
+
transformOrigin: growsUp ? "bottom" : "top",
|
|
42100
|
+
animation: animate && fresh ? barGrowAnimation(index2, firstBar, lastBar) : void 0,
|
|
42101
|
+
pointerEvents: "none"
|
|
41448
42102
|
}
|
|
41449
|
-
|
|
41450
|
-
|
|
41451
|
-
|
|
41452
|
-
{
|
|
41453
|
-
style: {
|
|
41454
|
-
position: "absolute",
|
|
41455
|
-
left: `${index2 * widthPercent}%`,
|
|
41456
|
-
...growsUp ? { bottom: 0 } : { top: 0 },
|
|
41457
|
-
width: barWidth,
|
|
41458
|
-
height: 3 + intensity * (TRACK_HEIGHT - 3),
|
|
41459
|
-
borderRadius: growsUp ? "1px 1px 0 0" : "0 0 1px 1px",
|
|
41460
|
-
background: color2,
|
|
41461
|
-
opacity: 0.35 + intensity * 0.65,
|
|
41462
|
-
transformOrigin: growsUp ? "bottom" : "top",
|
|
41463
|
-
animation: animate && fresh ? barGrowAnimation(index2, firstBar, lastBar) : void 0,
|
|
41464
|
-
pointerEvents: "none"
|
|
41465
|
-
}
|
|
41466
|
-
},
|
|
41467
|
-
index2
|
|
41468
|
-
))
|
|
41469
|
-
] });
|
|
42103
|
+
},
|
|
42104
|
+
index2
|
|
42105
|
+
)) });
|
|
41470
42106
|
};
|
|
42107
|
+
var VolumeBars = (0, import_react16.memo)(VolumeBarsImpl);
|
|
41471
42108
|
var ScrubberNeedle = ({ fraction }) => {
|
|
41472
|
-
const [hovered, setHovered] = (0,
|
|
42109
|
+
const [hovered, setHovered] = (0, import_react16.useState)(false);
|
|
41473
42110
|
const hover = {
|
|
41474
42111
|
onMouseEnter: () => setHovered(true),
|
|
41475
42112
|
onMouseLeave: () => setHovered(false)
|
|
41476
42113
|
};
|
|
41477
|
-
return /* @__PURE__ */ (0,
|
|
41478
|
-
/* @__PURE__ */ (0,
|
|
42114
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_jsx_runtime37.Fragment, { children: [
|
|
42115
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
41479
42116
|
"div",
|
|
41480
42117
|
{
|
|
41481
42118
|
...hover,
|
|
@@ -41495,7 +42132,7 @@ var ScrubberNeedle = ({ fraction }) => {
|
|
|
41495
42132
|
}
|
|
41496
42133
|
}
|
|
41497
42134
|
),
|
|
41498
|
-
/* @__PURE__ */ (0,
|
|
42135
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
41499
42136
|
"div",
|
|
41500
42137
|
{
|
|
41501
42138
|
...hover,
|
|
@@ -41525,7 +42162,7 @@ var ScrubberHoverHint = ({
|
|
|
41525
42162
|
fraction,
|
|
41526
42163
|
trackWidthPx,
|
|
41527
42164
|
empty: empty3 = false
|
|
41528
|
-
}) => /* @__PURE__ */ (0,
|
|
42165
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
|
|
41529
42166
|
"div",
|
|
41530
42167
|
{
|
|
41531
42168
|
style: {
|
|
@@ -41557,8 +42194,8 @@ var ScrubberHoverHint = ({
|
|
|
41557
42194
|
zIndex: 5
|
|
41558
42195
|
},
|
|
41559
42196
|
children: [
|
|
41560
|
-
segmentLabel && /* @__PURE__ */ (0,
|
|
41561
|
-
/* @__PURE__ */ (0,
|
|
42197
|
+
segmentLabel && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { style: { fontSize: 10, color: GUI_THEME.dim }, children: segmentLabel }),
|
|
42198
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
41562
42199
|
"div",
|
|
41563
42200
|
{
|
|
41564
42201
|
style: {
|
|
@@ -41571,7 +42208,7 @@ var ScrubberHoverHint = ({
|
|
|
41571
42208
|
children: label
|
|
41572
42209
|
}
|
|
41573
42210
|
),
|
|
41574
|
-
rows.map((row, index2) => /* @__PURE__ */ (0,
|
|
42211
|
+
rows.map((row, index2) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
41575
42212
|
"div",
|
|
41576
42213
|
{
|
|
41577
42214
|
style: {
|
|
@@ -41605,22 +42242,31 @@ var pointAt = (layers, x, y, width) => {
|
|
|
41605
42242
|
}
|
|
41606
42243
|
return best;
|
|
41607
42244
|
};
|
|
42245
|
+
var DIMMED_ALPHA = 0.08;
|
|
42246
|
+
var HIGHLIGHT_RADIUS_SCALE = 2.2;
|
|
41608
42247
|
var ScatterCanvas = ({
|
|
41609
42248
|
layers,
|
|
41610
42249
|
animate,
|
|
42250
|
+
highlightId,
|
|
41611
42251
|
onPointEnter,
|
|
41612
42252
|
onPointLeave,
|
|
41613
42253
|
onInspectCommit
|
|
41614
42254
|
}) => {
|
|
41615
|
-
const canvasRef = (0,
|
|
41616
|
-
const sizeRef = (0,
|
|
41617
|
-
const layersRef = (0,
|
|
42255
|
+
const canvasRef = (0, import_react16.useRef)(null);
|
|
42256
|
+
const sizeRef = (0, import_react16.useRef)({ width: 0, height: 0 });
|
|
42257
|
+
const layersRef = (0, import_react16.useRef)(layers);
|
|
41618
42258
|
layersRef.current = layers;
|
|
41619
|
-
const
|
|
41620
|
-
|
|
41621
|
-
|
|
41622
|
-
|
|
41623
|
-
const
|
|
42259
|
+
const activeHighlight = (0, import_react16.useMemo)(
|
|
42260
|
+
() => highlightId !== null && layers.some((layer) => layer.points.some((point4) => point4.id === highlightId)) ? highlightId : null,
|
|
42261
|
+
[layers, highlightId]
|
|
42262
|
+
);
|
|
42263
|
+
const highlightRef = (0, import_react16.useRef)(activeHighlight);
|
|
42264
|
+
highlightRef.current = activeHighlight;
|
|
42265
|
+
const phasesRef = (0, import_react16.useRef)(/* @__PURE__ */ new Map());
|
|
42266
|
+
const frameRef = (0, import_react16.useRef)(null);
|
|
42267
|
+
const hoveredRef = (0, import_react16.useRef)(null);
|
|
42268
|
+
const [entrancePlaying, setEntrancePlaying] = (0, import_react16.useState)(false);
|
|
42269
|
+
const paint = (0, import_react16.useCallback)((now) => {
|
|
41624
42270
|
const canvas = canvasRef.current;
|
|
41625
42271
|
const context = canvas?.getContext("2d");
|
|
41626
42272
|
if (!canvas || !context) return false;
|
|
@@ -41636,23 +42282,28 @@ var ScatterCanvas = ({
|
|
|
41636
42282
|
for (const point4 of layer.points) {
|
|
41637
42283
|
const scale = phase === null || phase === void 0 || done ? 1 : phase.mode === "in" ? dotEntranceScale(point4.key, elapsed) : dotExitScale(point4.key, elapsed);
|
|
41638
42284
|
if (scale <= 0) continue;
|
|
41639
|
-
|
|
42285
|
+
const highlight = highlightRef.current;
|
|
42286
|
+
const isHighlighted = highlight !== null && point4.id === highlight;
|
|
42287
|
+
const radiusScale = scale * (isHighlighted ? HIGHLIGHT_RADIUS_SCALE : 1);
|
|
42288
|
+
const cx = point4.fraction * width;
|
|
42289
|
+
const cy = EVENTS_MODE_VERTICAL_PADDING + point4.hourFraction * EVENTS_SCATTER_HEIGHT;
|
|
42290
|
+
context.globalAlpha = highlight === null ? point4.opacity : isHighlighted ? 1 : DIMMED_ALPHA;
|
|
41640
42291
|
context.fillStyle = point4.color;
|
|
41641
42292
|
context.beginPath();
|
|
41642
|
-
context.arc(
|
|
41643
|
-
point4.fraction * width,
|
|
41644
|
-
EVENTS_MODE_VERTICAL_PADDING + point4.hourFraction * EVENTS_SCATTER_HEIGHT,
|
|
41645
|
-
point4.radius * scale,
|
|
41646
|
-
0,
|
|
41647
|
-
Math.PI * 2
|
|
41648
|
-
);
|
|
42293
|
+
context.arc(cx, cy, point4.radius * radiusScale, 0, Math.PI * 2);
|
|
41649
42294
|
context.fill();
|
|
42295
|
+
if (isHighlighted) {
|
|
42296
|
+
context.globalAlpha = 0.25;
|
|
42297
|
+
context.beginPath();
|
|
42298
|
+
context.arc(cx, cy, point4.radius * radiusScale * 2.4, 0, Math.PI * 2);
|
|
42299
|
+
context.fill();
|
|
42300
|
+
}
|
|
41650
42301
|
}
|
|
41651
42302
|
}
|
|
41652
42303
|
context.globalAlpha = 1;
|
|
41653
42304
|
return running;
|
|
41654
42305
|
}, []);
|
|
41655
|
-
const run = (0,
|
|
42306
|
+
const run = (0, import_react16.useCallback)(() => {
|
|
41656
42307
|
if (frameRef.current !== null) return;
|
|
41657
42308
|
const step = () => {
|
|
41658
42309
|
frameRef.current = null;
|
|
@@ -41662,7 +42313,7 @@ var ScatterCanvas = ({
|
|
|
41662
42313
|
};
|
|
41663
42314
|
frameRef.current = requestAnimationFrame(step);
|
|
41664
42315
|
}, [paint]);
|
|
41665
|
-
(0,
|
|
42316
|
+
(0, import_react16.useEffect)(() => {
|
|
41666
42317
|
const canvas = canvasRef.current;
|
|
41667
42318
|
const parent = canvas?.parentElement;
|
|
41668
42319
|
if (!canvas || !parent) return;
|
|
@@ -41683,7 +42334,7 @@ var ScatterCanvas = ({
|
|
|
41683
42334
|
return () => observer.disconnect();
|
|
41684
42335
|
}, [paint]);
|
|
41685
42336
|
const signature = layers.map((layer) => `${layer.id}:${layer.generation}:${layer.leaving}`).join("|");
|
|
41686
|
-
(0,
|
|
42337
|
+
(0, import_react16.useEffect)(() => {
|
|
41687
42338
|
const seen = /* @__PURE__ */ new Set();
|
|
41688
42339
|
for (const layer of layers) {
|
|
41689
42340
|
seen.add(layer.id);
|
|
@@ -41708,10 +42359,10 @@ var ScatterCanvas = ({
|
|
|
41708
42359
|
if (animate) run();
|
|
41709
42360
|
else paint(performance.now());
|
|
41710
42361
|
}, [signature, animate, run, paint]);
|
|
41711
|
-
(0,
|
|
42362
|
+
(0, import_react16.useEffect)(() => {
|
|
41712
42363
|
if (frameRef.current === null) paint(performance.now());
|
|
41713
|
-
}, [layers, paint]);
|
|
41714
|
-
(0,
|
|
42364
|
+
}, [layers, activeHighlight, paint]);
|
|
42365
|
+
(0, import_react16.useEffect)(
|
|
41715
42366
|
() => () => {
|
|
41716
42367
|
if (frameRef.current !== null) cancelAnimationFrame(frameRef.current);
|
|
41717
42368
|
},
|
|
@@ -41726,11 +42377,13 @@ var ScatterCanvas = ({
|
|
|
41726
42377
|
rect.width
|
|
41727
42378
|
);
|
|
41728
42379
|
};
|
|
41729
|
-
return /* @__PURE__ */ (0,
|
|
42380
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
41730
42381
|
"canvas",
|
|
41731
42382
|
{
|
|
41732
42383
|
ref: canvasRef,
|
|
42384
|
+
"data-testid": "scatter-canvas",
|
|
41733
42385
|
"data-entrance": entrancePlaying ? "playing" : "done",
|
|
42386
|
+
"data-highlight": activeHighlight ?? "",
|
|
41734
42387
|
style: { position: "absolute", inset: 0 },
|
|
41735
42388
|
onMouseMove: (event) => {
|
|
41736
42389
|
const point4 = hitTest(event);
|
|
@@ -41755,7 +42408,8 @@ var ScatterCanvas = ({
|
|
|
41755
42408
|
};
|
|
41756
42409
|
|
|
41757
42410
|
// source/gui/client/components/ScrubberLayout.tsx
|
|
41758
|
-
var
|
|
42411
|
+
var import_jsx_runtime38 = __toESM(require_jsx_runtime(), 1);
|
|
42412
|
+
var DAY_MS2 = 24 * 60 * 60 * 1e3;
|
|
41759
42413
|
var ScrubberLayout = ({
|
|
41760
42414
|
collapsed,
|
|
41761
42415
|
onToggleCollapsed,
|
|
@@ -41763,7 +42417,7 @@ var ScrubberLayout = ({
|
|
|
41763
42417
|
chart
|
|
41764
42418
|
}) => {
|
|
41765
42419
|
const { axis, layoutMode, animate, windowKey, on } = chart;
|
|
41766
|
-
return /* @__PURE__ */ (0,
|
|
42420
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
41767
42421
|
Panel,
|
|
41768
42422
|
{
|
|
41769
42423
|
as: "div",
|
|
@@ -41780,8 +42434,8 @@ var ScrubberLayout = ({
|
|
|
41780
42434
|
overflow: "visible"
|
|
41781
42435
|
},
|
|
41782
42436
|
children: [
|
|
41783
|
-
/* @__PURE__ */ (0,
|
|
41784
|
-
/* @__PURE__ */ (0,
|
|
42437
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("style", { children: SCRUBBER_KEYFRAMES }),
|
|
42438
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
41785
42439
|
"div",
|
|
41786
42440
|
{
|
|
41787
42441
|
style: {
|
|
@@ -41790,7 +42444,7 @@ var ScrubberLayout = ({
|
|
|
41790
42444
|
gap: collapsed ? 0 : 8
|
|
41791
42445
|
},
|
|
41792
42446
|
children: [
|
|
41793
|
-
/* @__PURE__ */ (0,
|
|
42447
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
41794
42448
|
"div",
|
|
41795
42449
|
{
|
|
41796
42450
|
style: {
|
|
@@ -41802,14 +42456,14 @@ var ScrubberLayout = ({
|
|
|
41802
42456
|
minHeight: 22
|
|
41803
42457
|
},
|
|
41804
42458
|
children: [
|
|
41805
|
-
/* @__PURE__ */ (0,
|
|
42459
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
41806
42460
|
ScrubberHeader,
|
|
41807
42461
|
{
|
|
41808
42462
|
collapsed,
|
|
41809
42463
|
onToggleCollapsed
|
|
41810
42464
|
}
|
|
41811
42465
|
),
|
|
41812
|
-
!collapsed && /* @__PURE__ */ (0,
|
|
42466
|
+
!collapsed && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ScrubberControls, { ...controls })
|
|
41813
42467
|
]
|
|
41814
42468
|
}
|
|
41815
42469
|
),
|
|
@@ -41817,9 +42471,10 @@ var ScrubberLayout = ({
|
|
|
41817
42471
|
// spanning them and the gap between. Pointer handlers belong here
|
|
41818
42472
|
// rather than on either chart, so a drag or hover anywhere across
|
|
41819
42473
|
// the pair — the gap included — counts as one timeline.
|
|
41820
|
-
/* @__PURE__ */ (0,
|
|
42474
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
41821
42475
|
"div",
|
|
41822
42476
|
{
|
|
42477
|
+
"data-testid": "scrubber-track",
|
|
41823
42478
|
onPointerDown: on.onPointerDown,
|
|
41824
42479
|
onPointerMove: on.onPointerMove,
|
|
41825
42480
|
onPointerUp: on.onPointerEnd,
|
|
@@ -41831,17 +42486,17 @@ var ScrubberLayout = ({
|
|
|
41831
42486
|
display: "flex",
|
|
41832
42487
|
flexDirection: "column",
|
|
41833
42488
|
gap: 8,
|
|
41834
|
-
cursor: "pointer"
|
|
42489
|
+
cursor: chart.connected ? "pointer" : "default"
|
|
41835
42490
|
},
|
|
41836
42491
|
children: [
|
|
41837
|
-
chart.hoveredSegment && /* @__PURE__ */ (0,
|
|
42492
|
+
chart.hoveredSegment && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
41838
42493
|
SegmentHighlight,
|
|
41839
42494
|
{
|
|
41840
42495
|
segment: chart.hoveredSegment,
|
|
41841
42496
|
fractionForTime: axis.fractionForTime
|
|
41842
42497
|
}
|
|
41843
42498
|
),
|
|
41844
|
-
/* @__PURE__ */ (0,
|
|
42499
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
41845
42500
|
"div",
|
|
41846
42501
|
{
|
|
41847
42502
|
ref: chart.trackRef,
|
|
@@ -41856,32 +42511,41 @@ var ScrubberLayout = ({
|
|
|
41856
42511
|
alignItems: "center"
|
|
41857
42512
|
},
|
|
41858
42513
|
children: [
|
|
41859
|
-
/* @__PURE__ */ (0,
|
|
42514
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
41860
42515
|
TrackBaseline,
|
|
41861
42516
|
{
|
|
41862
42517
|
color: chart.issueSeriesColor,
|
|
41863
42518
|
anchor: layoutMode === "even" ? "bottom" : "centre"
|
|
41864
42519
|
}
|
|
41865
42520
|
),
|
|
41866
|
-
layoutMode === "real" && /* @__PURE__ */ (0,
|
|
41867
|
-
chart.showIssues && layoutMode === "even" && /* @__PURE__ */ (0,
|
|
41868
|
-
|
|
41869
|
-
|
|
41870
|
-
|
|
41871
|
-
|
|
41872
|
-
|
|
41873
|
-
|
|
41874
|
-
|
|
41875
|
-
|
|
41876
|
-
|
|
41877
|
-
|
|
41878
|
-
|
|
41879
|
-
|
|
41880
|
-
|
|
42521
|
+
layoutMode === "real" && axis.span >= DAY_MS2 && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(HourAxisLabels, {}),
|
|
42522
|
+
chart.showIssues && layoutMode === "even" && /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_jsx_runtime38.Fragment, { children: [
|
|
42523
|
+
chart.hoveredBucketIndex !== null && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
42524
|
+
BucketHighlight,
|
|
42525
|
+
{
|
|
42526
|
+
index: chart.hoveredBucketIndex,
|
|
42527
|
+
bucketCount: axis.bucketCount
|
|
42528
|
+
}
|
|
42529
|
+
),
|
|
42530
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(SeriesLayer, { animate, children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
42531
|
+
VolumeBars,
|
|
42532
|
+
{
|
|
42533
|
+
bars: chart.issueBars,
|
|
42534
|
+
bucketCount: axis.bucketCount,
|
|
42535
|
+
firstBar: chart.issueBarRange[0],
|
|
42536
|
+
lastBar: chart.issueBarRange[1],
|
|
42537
|
+
color: chart.issueSeriesColor,
|
|
42538
|
+
direction: "up",
|
|
42539
|
+
animate
|
|
42540
|
+
}
|
|
42541
|
+
) }, `issues-${windowKey}`)
|
|
42542
|
+
] }),
|
|
42543
|
+
layoutMode === "real" && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
41881
42544
|
ScatterCanvas,
|
|
41882
42545
|
{
|
|
41883
42546
|
layers: chart.scatterLayers,
|
|
41884
42547
|
animate,
|
|
42548
|
+
highlightId: chart.highlightEventId,
|
|
41885
42549
|
onPointEnter: on.onScatterPointEnter,
|
|
41886
42550
|
onPointLeave: on.onScatterPointLeave,
|
|
41887
42551
|
onInspectCommit: on.onInspectCommit
|
|
@@ -41890,7 +42554,7 @@ var ScrubberLayout = ({
|
|
|
41890
42554
|
]
|
|
41891
42555
|
}
|
|
41892
42556
|
),
|
|
41893
|
-
chart.showCommits && layoutMode === "even" && chart.commits.length > 0 && /* @__PURE__ */ (0,
|
|
42557
|
+
chart.showCommits && layoutMode === "even" && chart.commits.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
41894
42558
|
"div",
|
|
41895
42559
|
{
|
|
41896
42560
|
onMouseEnter: on.onCommitTrackMouseEnter,
|
|
@@ -41903,15 +42567,21 @@ var ScrubberLayout = ({
|
|
|
41903
42567
|
animation: animate ? FADE_IN_ANIMATION : void 0
|
|
41904
42568
|
},
|
|
41905
42569
|
children: [
|
|
41906
|
-
/* @__PURE__ */ (0,
|
|
41907
|
-
/* @__PURE__ */ (0,
|
|
42570
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(TrackBaseline, { color: GUI_THEME.green, anchor: "top" }),
|
|
42571
|
+
chart.hoveredCommitBucketIndex !== null && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
42572
|
+
BucketHighlight,
|
|
42573
|
+
{
|
|
42574
|
+
index: chart.hoveredCommitBucketIndex,
|
|
42575
|
+
bucketCount: axis.bucketCount
|
|
42576
|
+
}
|
|
42577
|
+
),
|
|
42578
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
41908
42579
|
VolumeBars,
|
|
41909
42580
|
{
|
|
41910
42581
|
bars: chart.commitBars,
|
|
41911
42582
|
bucketCount: axis.bucketCount,
|
|
41912
42583
|
firstBar: chart.commitBarRange[0],
|
|
41913
42584
|
lastBar: chart.commitBarRange[1],
|
|
41914
|
-
highlightedIndex: chart.hoveredCommitBucketIndex,
|
|
41915
42585
|
color: GUI_THEME.green,
|
|
41916
42586
|
direction: "down",
|
|
41917
42587
|
animate
|
|
@@ -41921,8 +42591,8 @@ var ScrubberLayout = ({
|
|
|
41921
42591
|
},
|
|
41922
42592
|
`commits-${windowKey}`
|
|
41923
42593
|
),
|
|
41924
|
-
/* @__PURE__ */ (0,
|
|
41925
|
-
chart.boardHint && /* @__PURE__ */ (0,
|
|
42594
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ScrubberNeedle, { fraction: chart.thumbFraction }),
|
|
42595
|
+
chart.boardHint && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
41926
42596
|
ScrubberHoverHint,
|
|
41927
42597
|
{
|
|
41928
42598
|
...chart.boardHint,
|
|
@@ -41931,7 +42601,7 @@ var ScrubberLayout = ({
|
|
|
41931
42601
|
trackWidthPx: chart.trackWidthPx
|
|
41932
42602
|
}
|
|
41933
42603
|
),
|
|
41934
|
-
chart.commitHint && /* @__PURE__ */ (0,
|
|
42604
|
+
chart.commitHint && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
41935
42605
|
ScrubberHoverHint,
|
|
41936
42606
|
{
|
|
41937
42607
|
...chart.commitHint,
|
|
@@ -41952,10 +42622,11 @@ var ScrubberLayout = ({
|
|
|
41952
42622
|
};
|
|
41953
42623
|
|
|
41954
42624
|
// source/gui/client/components/TimeScrubber.tsx
|
|
41955
|
-
var
|
|
42625
|
+
var import_jsx_runtime39 = __toESM(require_jsx_runtime(), 1);
|
|
41956
42626
|
var SCRUB_THROTTLE_MS = 120;
|
|
41957
42627
|
var boardEventRow = (count) => `${count} board event${count === 1 ? "" : "s"}`;
|
|
41958
42628
|
var COLLAPSED_STORAGE_KEY = "epiq.timeScrubber.collapsed";
|
|
42629
|
+
var LAYOUT_MODE_STORAGE_KEY = "epiq.timeScrubber.layoutMode";
|
|
41959
42630
|
var SCOPE_STORAGE_KEY = "epiq.timeScrubber.scope";
|
|
41960
42631
|
var SHOW_ISSUES_STORAGE_KEY = "epiq.timeScrubber.showIssues";
|
|
41961
42632
|
var SHOW_COMMITS_STORAGE_KEY = "epiq.timeScrubber.showCommits";
|
|
@@ -41977,6 +42648,10 @@ var readStoredHiddenIds = () => {
|
|
|
41977
42648
|
return /* @__PURE__ */ new Set();
|
|
41978
42649
|
}
|
|
41979
42650
|
};
|
|
42651
|
+
var readStoredLayoutMode = () => {
|
|
42652
|
+
const stored = localStorage.getItem(LAYOUT_MODE_STORAGE_KEY);
|
|
42653
|
+
return isLayoutMode(stored) ? stored : "even";
|
|
42654
|
+
};
|
|
41980
42655
|
var readStoredScope = () => {
|
|
41981
42656
|
const stored = localStorage.getItem(SCOPE_STORAGE_KEY);
|
|
41982
42657
|
return isScope(stored) ? stored : "all";
|
|
@@ -41991,16 +42666,19 @@ var TimeScrubber = ({
|
|
|
41991
42666
|
onRequestHistory,
|
|
41992
42667
|
boardId,
|
|
41993
42668
|
connected,
|
|
42669
|
+
socketEpoch,
|
|
42670
|
+
highlightEventId,
|
|
41994
42671
|
onInspectCommit,
|
|
41995
42672
|
onBoardFilterChange
|
|
41996
42673
|
}) => {
|
|
41997
42674
|
const animate = !usePrefersReducedMotion();
|
|
41998
|
-
const trackRef = (0,
|
|
41999
|
-
const lastDispatchRef = (0,
|
|
42000
|
-
const
|
|
42001
|
-
const [
|
|
42002
|
-
const [
|
|
42003
|
-
const [
|
|
42675
|
+
const trackRef = (0, import_react17.useRef)(null);
|
|
42676
|
+
const lastDispatchRef = (0, import_react17.useRef)(0);
|
|
42677
|
+
const lastTargetRef = (0, import_react17.useRef)(null);
|
|
42678
|
+
const [layoutMode, setLayoutMode] = (0, import_react17.useState)(readStoredLayoutMode);
|
|
42679
|
+
const [scope, setScope] = (0, import_react17.useState)(readStoredScope);
|
|
42680
|
+
const [offset, setOffset] = (0, import_react17.useState)(0);
|
|
42681
|
+
const [dragFraction, setDragFraction] = (0, import_react17.useState)(null);
|
|
42004
42682
|
const [collapsed, setCollapsed] = usePersistedFlag(
|
|
42005
42683
|
COLLAPSED_STORAGE_KEY,
|
|
42006
42684
|
false
|
|
@@ -42013,8 +42691,8 @@ var TimeScrubber = ({
|
|
|
42013
42691
|
SHOW_COMMITS_STORAGE_KEY,
|
|
42014
42692
|
true
|
|
42015
42693
|
);
|
|
42016
|
-
const [boardView, setBoardView] = (0,
|
|
42017
|
-
const [hiddenIdentityIds, setHiddenIdentityIds] = (0,
|
|
42694
|
+
const [boardView, setBoardView] = (0, import_react17.useState)(readStoredBoardView);
|
|
42695
|
+
const [hiddenIdentityIds, setHiddenIdentityIds] = (0, import_react17.useState)(readStoredHiddenIds);
|
|
42018
42696
|
const [categoriesExpanded, setCategoriesExpanded] = usePersistedFlag(
|
|
42019
42697
|
CATEGORIES_EXPANDED_STORAGE_KEY,
|
|
42020
42698
|
false
|
|
@@ -42030,18 +42708,26 @@ var TimeScrubber = ({
|
|
|
42030
42708
|
const exitMs = layoutMode === "real" && animate ? DOT_EXIT_TOTAL_MS : 0;
|
|
42031
42709
|
const issueScatter = useExitTransition(showIssues, exitMs);
|
|
42032
42710
|
const commitScatter = useExitTransition(showCommits, exitMs);
|
|
42033
|
-
const [hoveredEvent, setHoveredEvent] = (0,
|
|
42034
|
-
const [pointerFraction, setPointerFraction] = (0,
|
|
42035
|
-
const [hoveredCommit, setHoveredCommit] = (0,
|
|
42036
|
-
const [hoveredBucketIndex, setHoveredBucketIndex] = (0,
|
|
42711
|
+
const [hoveredEvent, setHoveredEvent] = (0, import_react17.useState)(null);
|
|
42712
|
+
const [pointerFraction, setPointerFraction] = (0, import_react17.useState)(null);
|
|
42713
|
+
const [hoveredCommit, setHoveredCommit] = (0, import_react17.useState)(null);
|
|
42714
|
+
const [hoveredBucketIndex, setHoveredBucketIndex] = (0, import_react17.useState)(
|
|
42037
42715
|
null
|
|
42038
42716
|
);
|
|
42039
|
-
const [hoveredCommitBucketIndex, setHoveredCommitBucketIndex] = (0,
|
|
42717
|
+
const [hoveredCommitBucketIndex, setHoveredCommitBucketIndex] = (0, import_react17.useState)(null);
|
|
42040
42718
|
const periodRange = getPeriodRange(scope, offset);
|
|
42041
|
-
(0,
|
|
42719
|
+
(0, import_react17.useEffect)(() => {
|
|
42042
42720
|
if (!connected) return;
|
|
42043
|
-
onRequestHistory(
|
|
42044
|
-
|
|
42721
|
+
pendingRequestId.current = onRequestHistory(
|
|
42722
|
+
periodRange?.start,
|
|
42723
|
+
periodRange?.end,
|
|
42724
|
+
allBoards
|
|
42725
|
+
);
|
|
42726
|
+
}, [scope, offset, boardId, allBoards, connected, socketEpoch]);
|
|
42727
|
+
const changeLayoutMode = (next) => {
|
|
42728
|
+
setLayoutMode(next);
|
|
42729
|
+
localStorage.setItem(LAYOUT_MODE_STORAGE_KEY, next);
|
|
42730
|
+
};
|
|
42045
42731
|
const changeScope = (nextScope) => {
|
|
42046
42732
|
armEntrance();
|
|
42047
42733
|
setScope(nextScope);
|
|
@@ -42087,68 +42773,53 @@ var TimeScrubber = ({
|
|
|
42087
42773
|
armEntrance();
|
|
42088
42774
|
setAllBoards(next);
|
|
42089
42775
|
};
|
|
42090
|
-
const
|
|
42091
|
-
if (boardId !== null) steadyBoardId.current = boardId;
|
|
42092
|
-
const requestKey = (0, import_react15.useMemo)(
|
|
42093
|
-
() => JSON.stringify([scope, offset, steadyBoardId.current, allBoards]),
|
|
42094
|
-
[scope, offset, steadyBoardId.current, allBoards]
|
|
42095
|
-
);
|
|
42096
|
-
const filterKey = (0, import_react15.useMemo)(
|
|
42776
|
+
const filterKey = (0, import_react17.useMemo)(
|
|
42097
42777
|
() => JSON.stringify([boardView, [...hiddenIdentityIds].sort()]),
|
|
42098
42778
|
[boardView, hiddenIdentityIds]
|
|
42099
42779
|
);
|
|
42100
|
-
const entrance = (0,
|
|
42101
|
-
const armed = (0,
|
|
42102
|
-
const seenHistoryId = (0, import_react15.useRef)(historyId);
|
|
42780
|
+
const entrance = (0, import_react17.useRef)(0);
|
|
42781
|
+
const armed = (0, import_react17.useRef)(true);
|
|
42103
42782
|
const armEntrance = () => {
|
|
42104
42783
|
armed.current = true;
|
|
42105
42784
|
};
|
|
42106
|
-
const shownRef = (0,
|
|
42107
|
-
const
|
|
42108
|
-
|
|
42109
|
-
|
|
42110
|
-
if (heldKey.current !== requestKey) {
|
|
42111
|
-
heldKey.current = requestKey;
|
|
42112
|
-
awaiting.current = true;
|
|
42113
|
-
}
|
|
42114
|
-
if (awaiting.current && heldHistoryId.current !== historyId) {
|
|
42115
|
-
heldHistoryId.current = historyId;
|
|
42785
|
+
const shownRef = (0, import_react17.useRef)({ timeline, commits });
|
|
42786
|
+
const pendingRequestId = (0, import_react17.useRef)(null);
|
|
42787
|
+
if (pendingRequestId.current !== null && historyId === pendingRequestId.current) {
|
|
42788
|
+
pendingRequestId.current = null;
|
|
42116
42789
|
shownRef.current = { timeline, commits };
|
|
42117
|
-
awaiting.current = false;
|
|
42118
|
-
}
|
|
42119
|
-
if (seenHistoryId.current !== historyId) {
|
|
42120
|
-
seenHistoryId.current = historyId;
|
|
42121
42790
|
if (armed.current) {
|
|
42122
42791
|
armed.current = false;
|
|
42123
42792
|
entrance.current += 1;
|
|
42124
42793
|
}
|
|
42125
42794
|
}
|
|
42126
42795
|
const shown = shownRef.current;
|
|
42127
|
-
const axis = (0,
|
|
42796
|
+
const axis = (0, import_react17.useMemo)(() => buildAxis(shown.timeline, shown.commits), [shown]);
|
|
42128
42797
|
const categoriesFiltered = (timeline?.events.length ?? 0) > 0;
|
|
42129
|
-
const identities = (0,
|
|
42798
|
+
const identities = (0, import_react17.useMemo)(
|
|
42130
42799
|
() => listIdentities(shown.timeline, boardView),
|
|
42131
42800
|
[shown, boardView]
|
|
42132
42801
|
);
|
|
42133
|
-
const soleIdentity = (0,
|
|
42802
|
+
const soleIdentity = (0, import_react17.useMemo)(
|
|
42134
42803
|
() => soleVisibleIdentity(identities, hiddenIdentityIds),
|
|
42135
42804
|
[identities, hiddenIdentityIds]
|
|
42136
42805
|
);
|
|
42137
|
-
const issueCounts =
|
|
42138
|
-
axis,
|
|
42139
|
-
shown
|
|
42140
|
-
|
|
42141
|
-
|
|
42806
|
+
const issueCounts = (0, import_react17.useMemo)(
|
|
42807
|
+
() => bucketIssueCounts(axis, shown.timeline, boardView, hiddenIdentityIds),
|
|
42808
|
+
[axis, shown, boardView, hiddenIdentityIds]
|
|
42809
|
+
);
|
|
42810
|
+
const commitStats = (0, import_react17.useMemo)(
|
|
42811
|
+
() => bucketCommitStats(axis, shown.commits),
|
|
42812
|
+
[axis, shown.commits]
|
|
42142
42813
|
);
|
|
42143
|
-
const
|
|
42144
|
-
const liveEventDots = (0, import_react15.useMemo)(
|
|
42814
|
+
const liveEventDots = (0, import_react17.useMemo)(
|
|
42145
42815
|
() => buildEventDots(shown.timeline, boardView, hiddenIdentityIds),
|
|
42146
42816
|
[shown, boardView, hiddenIdentityIds]
|
|
42147
42817
|
);
|
|
42148
42818
|
const dragging = dragFraction !== null;
|
|
42149
|
-
const commitPoints = (0,
|
|
42819
|
+
const commitPoints = (0, import_react17.useMemo)(
|
|
42150
42820
|
() => shown.commits.map((commit) => ({
|
|
42151
42821
|
key: commit.sha,
|
|
42822
|
+
id: null,
|
|
42152
42823
|
t: commit.time,
|
|
42153
42824
|
fraction: axis.fractionForTime(commit.time),
|
|
42154
42825
|
hourFraction: hourFractionForTime(commit.time),
|
|
@@ -42161,9 +42832,10 @@ var TimeScrubber = ({
|
|
|
42161
42832
|
})),
|
|
42162
42833
|
[shown.commits, axis]
|
|
42163
42834
|
);
|
|
42164
|
-
const issuePoints = (0,
|
|
42835
|
+
const issuePoints = (0, import_react17.useMemo)(
|
|
42165
42836
|
() => liveEventDots.map((dot) => ({
|
|
42166
42837
|
key: dot.key,
|
|
42838
|
+
id: dot.id,
|
|
42167
42839
|
t: dot.t,
|
|
42168
42840
|
fraction: axis.fractionForTime(dot.t),
|
|
42169
42841
|
hourFraction: hourFractionForTime(dot.t),
|
|
@@ -42175,33 +42847,42 @@ var TimeScrubber = ({
|
|
|
42175
42847
|
})),
|
|
42176
42848
|
[liveEventDots, axis]
|
|
42177
42849
|
);
|
|
42178
|
-
const boardFilter = (0,
|
|
42850
|
+
const boardFilter = (0, import_react17.useMemo)(
|
|
42179
42851
|
() => buildBoardFilter(boardView, identities, hiddenIdentityIds),
|
|
42180
42852
|
[boardView, identities, hiddenIdentityIds]
|
|
42181
42853
|
);
|
|
42182
|
-
(0,
|
|
42854
|
+
(0, import_react17.useEffect)(() => {
|
|
42183
42855
|
onBoardFilterChange(boardFilter);
|
|
42184
42856
|
}, [boardFilter]);
|
|
42185
|
-
const
|
|
42186
|
-
|
|
42187
|
-
|
|
42188
|
-
|
|
42189
|
-
|
|
42190
|
-
|
|
42191
|
-
|
|
42857
|
+
const issueBars = (0, import_react17.useMemo)(() => {
|
|
42858
|
+
const max = maxOf(issueCounts, 1);
|
|
42859
|
+
return issueCounts.flatMap(
|
|
42860
|
+
(count, index2) => count > 0 ? [{ index: index2, intensity: count / max }] : []
|
|
42861
|
+
);
|
|
42862
|
+
}, [issueCounts]);
|
|
42863
|
+
const commitBars = (0, import_react17.useMemo)(() => {
|
|
42864
|
+
const max = maxOf(
|
|
42865
|
+
Array.from(commitStats.values(), (stats) => stats.count),
|
|
42866
|
+
1
|
|
42867
|
+
);
|
|
42868
|
+
return Array.from(commitStats, ([index2, stats]) => ({
|
|
42869
|
+
index: index2,
|
|
42870
|
+
intensity: stats.count / max
|
|
42871
|
+
}));
|
|
42872
|
+
}, [commitStats]);
|
|
42873
|
+
const issueBarRange = (0, import_react17.useMemo)(() => populatedRange(issueBars), [issueBars]);
|
|
42874
|
+
const commitBarRange = (0, import_react17.useMemo)(
|
|
42875
|
+
() => populatedRange(commitBars),
|
|
42876
|
+
[commitBars]
|
|
42192
42877
|
);
|
|
42193
|
-
const
|
|
42194
|
-
|
|
42195
|
-
intensity: stats.count / maxCommitCount
|
|
42196
|
-
}));
|
|
42197
|
-
const armedBoardId = (0, import_react15.useRef)(boardId);
|
|
42198
|
-
(0, import_react15.useEffect)(() => {
|
|
42878
|
+
const armedBoardId = (0, import_react17.useRef)(boardId);
|
|
42879
|
+
(0, import_react17.useEffect)(() => {
|
|
42199
42880
|
if (boardId === null || boardId === armedBoardId.current) return;
|
|
42200
42881
|
armedBoardId.current = boardId;
|
|
42201
42882
|
armEntrance();
|
|
42202
42883
|
}, [boardId]);
|
|
42203
42884
|
const windowKey = `${layoutMode}-${entrance.current}-${filterKey}`;
|
|
42204
|
-
const scatterLayers = (0,
|
|
42885
|
+
const scatterLayers = (0, import_react17.useMemo)(
|
|
42205
42886
|
() => [
|
|
42206
42887
|
...commitScatter.mounted ? [
|
|
42207
42888
|
{
|
|
@@ -42230,11 +42911,18 @@ var TimeScrubber = ({
|
|
|
42230
42911
|
return clamp((clientX - rect.left) / Math.max(1, rect.width), 0, 1);
|
|
42231
42912
|
};
|
|
42232
42913
|
const dispatchScrub = (fraction, force) => {
|
|
42914
|
+
if (!connected) return;
|
|
42915
|
+
const target = axis.fractionToTime(fraction);
|
|
42916
|
+
if (target === lastTargetRef.current) return;
|
|
42233
42917
|
const now = Date.now();
|
|
42234
42918
|
if (!force && now - lastDispatchRef.current < SCRUB_THROTTLE_MS) return;
|
|
42235
42919
|
lastDispatchRef.current = now;
|
|
42236
|
-
|
|
42920
|
+
lastTargetRef.current = target;
|
|
42921
|
+
onScrub(target);
|
|
42237
42922
|
};
|
|
42923
|
+
(0, import_react17.useEffect)(() => {
|
|
42924
|
+
if (timeTravel.mode !== "scrub") lastTargetRef.current = null;
|
|
42925
|
+
}, [timeTravel.mode]);
|
|
42238
42926
|
const endDrag = () => {
|
|
42239
42927
|
if (dragFraction === null) return;
|
|
42240
42928
|
dispatchScrub(dragFraction, true);
|
|
@@ -42251,7 +42939,7 @@ var TimeScrubber = ({
|
|
|
42251
42939
|
);
|
|
42252
42940
|
const bucketTimeAt = (index2) => index2 !== null && index2 < axis.bucketCount ? axis.bucketTimeAt(index2) : void 0;
|
|
42253
42941
|
const centreFraction = (index2) => (index2 + 0.5) / axis.bucketCount;
|
|
42254
|
-
const onScatterPointEnter = (0,
|
|
42942
|
+
const onScatterPointEnter = (0, import_react17.useCallback)(
|
|
42255
42943
|
(point4) => {
|
|
42256
42944
|
if (point4.commitSha) {
|
|
42257
42945
|
const commit = shown.commits.find((c) => c.sha === point4.commitSha);
|
|
@@ -42271,7 +42959,7 @@ var TimeScrubber = ({
|
|
|
42271
42959
|
},
|
|
42272
42960
|
[shown.commits]
|
|
42273
42961
|
);
|
|
42274
|
-
const onScatterPointLeave = (0,
|
|
42962
|
+
const onScatterPointLeave = (0, import_react17.useCallback)(() => {
|
|
42275
42963
|
setHoveredEvent(null);
|
|
42276
42964
|
setHoveredCommit(null);
|
|
42277
42965
|
}, []);
|
|
@@ -42316,12 +43004,13 @@ var TimeScrubber = ({
|
|
|
42316
43004
|
hoveredEvent?.t ?? hoveredCommit?.commit.time ?? (pointerFraction !== null ? axis.fractionToTime(pointerFraction) : void 0)
|
|
42317
43005
|
)) ?? null;
|
|
42318
43006
|
const segmentUnit = chooseSegmentUnit(axis.span);
|
|
42319
|
-
return /* @__PURE__ */ (0,
|
|
43007
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
42320
43008
|
ScrubberLayout,
|
|
42321
43009
|
{
|
|
42322
43010
|
collapsed,
|
|
42323
43011
|
onToggleCollapsed: () => setCollapsed(!collapsed),
|
|
42324
43012
|
controls: {
|
|
43013
|
+
connected,
|
|
42325
43014
|
scope,
|
|
42326
43015
|
offset,
|
|
42327
43016
|
periodRange,
|
|
@@ -42331,7 +43020,7 @@ var TimeScrubber = ({
|
|
|
42331
43020
|
allBoards,
|
|
42332
43021
|
onChangeScope: changeScope,
|
|
42333
43022
|
onChangeOffset: changeOffset,
|
|
42334
|
-
onChangeLayoutMode:
|
|
43023
|
+
onChangeLayoutMode: changeLayoutMode,
|
|
42335
43024
|
onChangeShowIssues: setShowIssues,
|
|
42336
43025
|
onChangeShowCommits: setShowCommits,
|
|
42337
43026
|
onChangeAllBoards: changeAllBoards,
|
|
@@ -42360,9 +43049,9 @@ var TimeScrubber = ({
|
|
|
42360
43049
|
issueScatter,
|
|
42361
43050
|
commitScatter,
|
|
42362
43051
|
issueBars,
|
|
42363
|
-
issueBarRange
|
|
43052
|
+
issueBarRange,
|
|
42364
43053
|
commitBars,
|
|
42365
|
-
commitBarRange
|
|
43054
|
+
commitBarRange,
|
|
42366
43055
|
scatterLayers,
|
|
42367
43056
|
issueSeriesColor: soleIdentity?.color ?? boardViewColor(boardView),
|
|
42368
43057
|
dragging,
|
|
@@ -42373,7 +43062,9 @@ var TimeScrubber = ({
|
|
|
42373
43062
|
hoveredBucketIndex,
|
|
42374
43063
|
hoveredCommitBucketIndex,
|
|
42375
43064
|
hoveredSegment: hoveredSegmentTime !== null ? segmentAt(hoveredSegmentTime, segmentUnit) : null,
|
|
43065
|
+
connected,
|
|
42376
43066
|
thumbFraction: dragFraction ?? confirmedFraction,
|
|
43067
|
+
highlightEventId,
|
|
42377
43068
|
trackWidthPx: trackRef.current?.clientWidth ?? 0,
|
|
42378
43069
|
boardHint,
|
|
42379
43070
|
commitHint,
|
|
@@ -42418,7 +43109,7 @@ var TimeScrubber = ({
|
|
|
42418
43109
|
};
|
|
42419
43110
|
|
|
42420
43111
|
// source/gui/client/lib/gui-move-issue.tsx
|
|
42421
|
-
var
|
|
43112
|
+
var toMovePosition2 = (targetIssues, targetIndex) => {
|
|
42422
43113
|
if (targetIssues.length === 0) return { at: "start" };
|
|
42423
43114
|
if (targetIndex === "end") return { at: "end" };
|
|
42424
43115
|
const index2 = Math.max(0, Math.min(targetIndex, targetIssues.length));
|
|
@@ -42453,7 +43144,7 @@ var findMove = (state, issueId, parentId, targetIndex) => {
|
|
|
42453
43144
|
}
|
|
42454
43145
|
if (!movedIssue || !sourceSwimlaneId || !targetSwimlane) return null;
|
|
42455
43146
|
const targetIssues = sourceSwimlaneId === targetSwimlane.id ? targetSwimlane.issues.filter((issue) => issue.id !== issueId) : targetSwimlane.issues;
|
|
42456
|
-
const position3 =
|
|
43147
|
+
const position3 = toMovePosition2(targetIssues, targetIndex);
|
|
42457
43148
|
return {
|
|
42458
43149
|
movedIssue,
|
|
42459
43150
|
position: position3,
|
|
@@ -42493,6 +43184,12 @@ var moveIssue = (state, setState, send) => (issueIds, parentId, targetIndex) =>
|
|
|
42493
43184
|
setState((current) => current ? next : current);
|
|
42494
43185
|
};
|
|
42495
43186
|
|
|
43187
|
+
// source/gui/client/lib/reconnect.ts
|
|
43188
|
+
var BASE_DELAY_MS = 500;
|
|
43189
|
+
var MAX_DELAY_MS = 8e3;
|
|
43190
|
+
var MAX_RECONNECT_ATTEMPTS = 5;
|
|
43191
|
+
var reconnectDelayMs = (attempt) => attempt >= MAX_RECONNECT_ATTEMPTS ? null : Math.min(MAX_DELAY_MS, BASE_DELAY_MS * 2 ** attempt);
|
|
43192
|
+
|
|
42496
43193
|
// source/lib/utils/node-ref.ts
|
|
42497
43194
|
var NODE_REF_LENGTH = 7;
|
|
42498
43195
|
var nodeRef = (id) => id.slice(-NODE_REF_LENGTH).toUpperCase();
|
|
@@ -42522,6 +43219,17 @@ var findIssue = (state, issueRefOrId) => findByRefOrId(
|
|
|
42522
43219
|
issueRefOrId
|
|
42523
43220
|
);
|
|
42524
43221
|
var findBoard = (state, boardRefOrId) => findByRefOrId(state.boards, boardRefOrId);
|
|
43222
|
+
var updateSwimlaneInGuiState = (state, swimlaneId, updateSwimlane) => ({
|
|
43223
|
+
...state,
|
|
43224
|
+
boards: state.boards.map((board) => ({
|
|
43225
|
+
...board,
|
|
43226
|
+
swimlanes: board.swimlanes.flatMap((swimlane) => {
|
|
43227
|
+
if (swimlane.id !== swimlaneId) return [swimlane];
|
|
43228
|
+
const next = updateSwimlane(swimlane);
|
|
43229
|
+
return next ? [next] : [];
|
|
43230
|
+
})
|
|
43231
|
+
}))
|
|
43232
|
+
});
|
|
42525
43233
|
var updateIssueInGuiState = (state, issueId, updateIssue) => ({
|
|
42526
43234
|
...state,
|
|
42527
43235
|
boards: state.boards.map((board) => ({
|
|
@@ -42591,6 +43299,10 @@ var createHistoryBuffer = (publish) => {
|
|
|
42591
43299
|
var MUTATING_MESSAGE_TYPES = /* @__PURE__ */ new Set([
|
|
42592
43300
|
"sync",
|
|
42593
43301
|
"issues:create",
|
|
43302
|
+
"swimlane:create",
|
|
43303
|
+
"swimlane:edit:title",
|
|
43304
|
+
"swimlane:delete",
|
|
43305
|
+
"swimlane:move",
|
|
42594
43306
|
"issues:move",
|
|
42595
43307
|
"issue:close",
|
|
42596
43308
|
"issue:reopen",
|
|
@@ -42693,11 +43405,13 @@ var blobToBase64 = (blob) => new Promise((resolve, reject) => {
|
|
|
42693
43405
|
});
|
|
42694
43406
|
|
|
42695
43407
|
// source/gui/client/App.tsx
|
|
42696
|
-
var
|
|
43408
|
+
var import_jsx_runtime40 = __toESM(require_jsx_runtime(), 1);
|
|
42697
43409
|
var EMPTY_COMMENTS = {};
|
|
42698
|
-
var
|
|
43410
|
+
var BOARD_GUTTER = 30;
|
|
43411
|
+
var DropIndicator = () => /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
42699
43412
|
"div",
|
|
42700
43413
|
{
|
|
43414
|
+
"data-testid": "ticket-drop-indicator",
|
|
42701
43415
|
style: {
|
|
42702
43416
|
height: 2,
|
|
42703
43417
|
background: GUI_THEME.accent,
|
|
@@ -42713,39 +43427,60 @@ var App = () => {
|
|
|
42713
43427
|
const legacyIssueMatch = useMatch("/board/:boardId/:issueId");
|
|
42714
43428
|
const issueId = issueMatch?.params.issueId ?? legacyIssueMatch?.params.issueId;
|
|
42715
43429
|
const [searchParams, setSearchParams] = useSearchParams();
|
|
42716
|
-
const [connected, setConnected] = (0,
|
|
42717
|
-
const [
|
|
43430
|
+
const [connected, setConnected] = (0, import_react18.useState)(false);
|
|
43431
|
+
const [socketEpoch, setSocketEpoch] = (0, import_react18.useState)(0);
|
|
43432
|
+
const [syncStatus, setSyncStatus] = (0, import_react18.useState)({
|
|
42718
43433
|
status: "synced",
|
|
42719
43434
|
msg: "idle"
|
|
42720
43435
|
});
|
|
42721
|
-
const [state, setState] = (0,
|
|
42722
|
-
const [
|
|
42723
|
-
const [
|
|
42724
|
-
const [
|
|
42725
|
-
const [
|
|
43436
|
+
const [state, setState] = (0, import_react18.useState)(null);
|
|
43437
|
+
const [noProject, setNoProject] = (0, import_react18.useState)(null);
|
|
43438
|
+
const [contributors, setContributors] = (0, import_react18.useState)([]);
|
|
43439
|
+
const [history, setHistory] = (0, import_react18.useState)({ requestId: 0, timeline: null, commits: [] });
|
|
43440
|
+
const [historyBuffer] = (0, import_react18.useState)(() => createHistoryBuffer(setHistory));
|
|
43441
|
+
const [commitInspectError, setCommitInspectError] = (0, import_react18.useState)(
|
|
43442
|
+
null
|
|
43443
|
+
);
|
|
43444
|
+
const [removeError, setRemoveError] = (0, import_react18.useState)(null);
|
|
43445
|
+
const [actionError, setActionError] = (0, import_react18.useState)(null);
|
|
43446
|
+
const [dragOverSwimlaneId, setDragOverSwimlaneId] = (0, import_react18.useState)(
|
|
43447
|
+
null
|
|
43448
|
+
);
|
|
43449
|
+
const [dropTarget, setDropTarget] = (0, import_react18.useState)(null);
|
|
43450
|
+
const [pickedIssueIds, setPickedIssueIds] = (0, import_react18.useState)([]);
|
|
43451
|
+
const [boardMenuOpen, setBoardMenuOpen] = (0, import_react18.useState)(false);
|
|
43452
|
+
const [createIssueModal, setCreateIssueModal] = (0, import_react18.useState)(null);
|
|
43453
|
+
const [createSwimlaneTitle, setCreateSwimlaneTitle] = (0, import_react18.useState)(
|
|
42726
43454
|
null
|
|
42727
43455
|
);
|
|
42728
|
-
const [
|
|
42729
|
-
const [
|
|
42730
|
-
const [
|
|
43456
|
+
const [renameSwimlane, setRenameSwimlane] = (0, import_react18.useState)(null);
|
|
43457
|
+
const [deleteSwimlaneId, setDeleteSwimlaneId] = (0, import_react18.useState)(null);
|
|
43458
|
+
const [hoveredLogEventId, setHoveredLogEventId] = (0, import_react18.useState)(
|
|
42731
43459
|
null
|
|
42732
43460
|
);
|
|
42733
|
-
const [
|
|
42734
|
-
const
|
|
42735
|
-
const
|
|
42736
|
-
const [
|
|
42737
|
-
const
|
|
42738
|
-
const
|
|
42739
|
-
const
|
|
42740
|
-
const
|
|
43461
|
+
const [swimlaneDropEdge, setSwimlaneDropEdge] = (0, import_react18.useState)(null);
|
|
43462
|
+
const boardMenuRef = (0, import_react18.useRef)(null);
|
|
43463
|
+
const socketRef = (0, import_react18.useRef)(null);
|
|
43464
|
+
const [reconnectTick, setReconnectTick] = (0, import_react18.useState)(0);
|
|
43465
|
+
const [reconnectExhausted, setReconnectExhausted] = (0, import_react18.useState)(false);
|
|
43466
|
+
const reconnectAttempts = (0, import_react18.useRef)(0);
|
|
43467
|
+
const reconnectTimer = (0, import_react18.useRef)(null);
|
|
43468
|
+
const reconnectNow = () => {
|
|
43469
|
+
reconnectAttempts.current = 0;
|
|
43470
|
+
setReconnectExhausted(false);
|
|
43471
|
+
setReconnectTick((tick) => tick + 1);
|
|
43472
|
+
};
|
|
43473
|
+
const [mutationGate] = (0, import_react18.useState)(createMutationGate);
|
|
43474
|
+
const tabParam = searchParams.get("tab");
|
|
43475
|
+
const selectedTab = tabParam === "comments" || tabParam === "history" ? tabParam : "overview";
|
|
42741
43476
|
const navigate = useNavigate();
|
|
42742
43477
|
const selectedBoard = (state && boardId ? findBoard(state, boardId) : null) ?? state?.boards?.[0] ?? null;
|
|
42743
43478
|
const selectedBoardId = selectedBoard?.id ?? null;
|
|
42744
|
-
const selectedBoardIdRef = (0,
|
|
43479
|
+
const selectedBoardIdRef = (0, import_react18.useRef)(selectedBoardId);
|
|
42745
43480
|
selectedBoardIdRef.current = selectedBoardId;
|
|
42746
43481
|
const boardSlug = selectedBoard?.ref ?? boardId;
|
|
42747
43482
|
const selectedIssue = state && issueId ? findIssue(state, issueId) : null;
|
|
42748
|
-
(0,
|
|
43483
|
+
(0, import_react18.useEffect)(() => {
|
|
42749
43484
|
const onPaste = (event) => {
|
|
42750
43485
|
if (!selectedIssue || selectedIssue.readonly) return;
|
|
42751
43486
|
const target = event.target;
|
|
@@ -42765,9 +43500,9 @@ var App = () => {
|
|
|
42765
43500
|
void navigate(`/board/${boardSlug}`);
|
|
42766
43501
|
};
|
|
42767
43502
|
const commentsByIssueId = state?.commentsByIssueId ?? EMPTY_COMMENTS;
|
|
42768
|
-
const [issueDetail, setIssueDetail] = (0,
|
|
42769
|
-
const [boardFilter, setBoardFilter] = (0,
|
|
42770
|
-
const { visibleSwimlanes, hiddenIssueCount } = (0,
|
|
43503
|
+
const [issueDetail, setIssueDetail] = (0, import_react18.useState)(null);
|
|
43504
|
+
const [boardFilter, setBoardFilter] = (0, import_react18.useState)(null);
|
|
43505
|
+
const { visibleSwimlanes, hiddenIssueCount } = (0, import_react18.useMemo)(() => {
|
|
42771
43506
|
const swimlanes = selectedBoard?.swimlanes ?? [];
|
|
42772
43507
|
if (!boardFilter) return { visibleSwimlanes: swimlanes, hiddenIssueCount: 0 };
|
|
42773
43508
|
let hidden = 0;
|
|
@@ -42785,8 +43520,8 @@ var App = () => {
|
|
|
42785
43520
|
return { visibleSwimlanes: visible, hiddenIssueCount: hidden };
|
|
42786
43521
|
}, [selectedBoard, boardFilter, commentsByIssueId]);
|
|
42787
43522
|
const attachmentsByIssueId = state?.attachmentsByIssueId ?? {};
|
|
42788
|
-
const [attachmentUploadStatus, setAttachmentUploadStatus] = (0,
|
|
42789
|
-
(0,
|
|
43523
|
+
const [attachmentUploadStatus, setAttachmentUploadStatus] = (0, import_react18.useState)({ state: "idle" });
|
|
43524
|
+
(0, import_react18.useEffect)(() => {
|
|
42790
43525
|
if (!selectedIssue) {
|
|
42791
43526
|
setIssueDetail(null);
|
|
42792
43527
|
return;
|
|
@@ -42799,29 +43534,50 @@ var App = () => {
|
|
|
42799
43534
|
const requestState = () => {
|
|
42800
43535
|
sendSocketJson(socketRef.current, { type: "state:get" });
|
|
42801
43536
|
};
|
|
42802
|
-
(0,
|
|
43537
|
+
(0, import_react18.useEffect)(() => {
|
|
42803
43538
|
const socket = new WebSocket(
|
|
42804
43539
|
`ws://${window.location.host}/ws${boardId ? `?boardId=${boardId}` : ""}`
|
|
42805
43540
|
);
|
|
42806
43541
|
socketRef.current = socket;
|
|
43542
|
+
let replaced = false;
|
|
42807
43543
|
socket.addEventListener("open", () => {
|
|
42808
43544
|
setConnected(true);
|
|
43545
|
+
setSocketEpoch((epoch) => epoch + 1);
|
|
43546
|
+
reconnectAttempts.current = 0;
|
|
43547
|
+
setReconnectExhausted(false);
|
|
42809
43548
|
mutationGate.reset();
|
|
42810
43549
|
sendSocketJson(socket, { type: "state:get" });
|
|
42811
43550
|
});
|
|
42812
43551
|
socket.addEventListener("close", () => {
|
|
42813
|
-
setConnected(false);
|
|
42814
|
-
mutationGate.reset();
|
|
42815
43552
|
if (socketRef.current === socket) {
|
|
42816
43553
|
socketRef.current = null;
|
|
42817
43554
|
}
|
|
43555
|
+
if (replaced) return;
|
|
43556
|
+
setConnected(false);
|
|
43557
|
+
mutationGate.reset();
|
|
43558
|
+
const delay = reconnectDelayMs(reconnectAttempts.current);
|
|
43559
|
+
if (delay === null) {
|
|
43560
|
+
setReconnectExhausted(true);
|
|
43561
|
+
return;
|
|
43562
|
+
}
|
|
43563
|
+
reconnectAttempts.current += 1;
|
|
43564
|
+
reconnectTimer.current = window.setTimeout(
|
|
43565
|
+
() => setReconnectTick((tick) => tick + 1),
|
|
43566
|
+
delay
|
|
43567
|
+
);
|
|
42818
43568
|
});
|
|
42819
43569
|
socket.addEventListener("message", (event) => {
|
|
42820
43570
|
const message = JSON.parse(event.data);
|
|
42821
43571
|
mutationGate.received(message.type);
|
|
42822
43572
|
if (message.type === "state" && !mutationGate.holdsState()) {
|
|
42823
43573
|
const nextState = getResultValue(message.payload);
|
|
42824
|
-
if (nextState)
|
|
43574
|
+
if (nextState) {
|
|
43575
|
+
setState(nextState);
|
|
43576
|
+
setNoProject(null);
|
|
43577
|
+
}
|
|
43578
|
+
}
|
|
43579
|
+
if (message.type === "state:unavailable") {
|
|
43580
|
+
setNoProject(message.payload);
|
|
42825
43581
|
}
|
|
42826
43582
|
if (message.type === "issue") {
|
|
42827
43583
|
const detail = getResultValue(message.payload);
|
|
@@ -42880,19 +43636,24 @@ var App = () => {
|
|
|
42880
43636
|
}
|
|
42881
43637
|
});
|
|
42882
43638
|
return () => {
|
|
43639
|
+
replaced = true;
|
|
43640
|
+
if (reconnectTimer.current !== null) {
|
|
43641
|
+
clearTimeout(reconnectTimer.current);
|
|
43642
|
+
reconnectTimer.current = null;
|
|
43643
|
+
}
|
|
42883
43644
|
if (socketRef.current === socket) {
|
|
42884
43645
|
socketRef.current = null;
|
|
42885
43646
|
}
|
|
42886
43647
|
socket.close();
|
|
42887
43648
|
};
|
|
42888
|
-
}, [boardId, navigate]);
|
|
42889
|
-
(0,
|
|
43649
|
+
}, [boardId, navigate, reconnectTick]);
|
|
43650
|
+
(0, import_react18.useEffect)(() => {
|
|
42890
43651
|
const first = state?.boards?.[0];
|
|
42891
43652
|
if (!boardId && first) {
|
|
42892
43653
|
void navigate(`/board/${first.ref}`, { replace: true });
|
|
42893
43654
|
}
|
|
42894
43655
|
}, [boardId, state, navigate]);
|
|
42895
|
-
(0,
|
|
43656
|
+
(0, import_react18.useEffect)(() => {
|
|
42896
43657
|
const close = (event) => {
|
|
42897
43658
|
if (boardMenuRef.current && !boardMenuRef.current.contains(event.target)) {
|
|
42898
43659
|
setBoardMenuOpen(false);
|
|
@@ -42915,8 +43676,8 @@ var App = () => {
|
|
|
42915
43676
|
);
|
|
42916
43677
|
};
|
|
42917
43678
|
const clearPicked = () => setPickedIssueIds([]);
|
|
42918
|
-
const [bulkTagName, setBulkTagName] = (0,
|
|
42919
|
-
const [bulkAssigneeName, setBulkAssigneeName] = (0,
|
|
43679
|
+
const [bulkTagName, setBulkTagName] = (0, import_react18.useState)("");
|
|
43680
|
+
const [bulkAssigneeName, setBulkAssigneeName] = (0, import_react18.useState)("");
|
|
42920
43681
|
const pickedIssues = (state?.boards ?? []).flatMap((board) => board.swimlanes).flatMap((swimlane) => swimlane.issues).filter((issue) => pickedIssueIds.includes(issue.id));
|
|
42921
43682
|
const forPicked = (act) => {
|
|
42922
43683
|
for (const issue of pickedIssues) act(issue.id);
|
|
@@ -42926,7 +43687,7 @@ var App = () => {
|
|
|
42926
43687
|
setPickedIssueIds([nextIssueId]);
|
|
42927
43688
|
if (!boardSlug) return;
|
|
42928
43689
|
void navigate(
|
|
42929
|
-
`/board/${boardSlug}/issue/${nodeRef(nextIssueId)}?tab
|
|
43690
|
+
`/board/${boardSlug}/issue/${nodeRef(nextIssueId)}?tab=${selectedTab}`
|
|
42930
43691
|
);
|
|
42931
43692
|
};
|
|
42932
43693
|
const selectIssueComments = (nextIssueId) => {
|
|
@@ -43070,7 +43831,7 @@ var App = () => {
|
|
|
43070
43831
|
const returnToLive = () => {
|
|
43071
43832
|
send("time-travel:live", {});
|
|
43072
43833
|
};
|
|
43073
|
-
const requestBoardHistory = (0,
|
|
43834
|
+
const requestBoardHistory = (0, import_react18.useCallback)(
|
|
43074
43835
|
(start2, end, allBoards) => {
|
|
43075
43836
|
const window2 = start2 !== void 0 ? { start: start2, end } : void 0;
|
|
43076
43837
|
const requestId = historyBuffer.open();
|
|
@@ -43086,33 +43847,34 @@ var App = () => {
|
|
|
43086
43847
|
type: "commits:get",
|
|
43087
43848
|
payload: { ...window2, requestId }
|
|
43088
43849
|
});
|
|
43850
|
+
return requestId;
|
|
43089
43851
|
},
|
|
43090
43852
|
[selectedBoardId]
|
|
43091
43853
|
);
|
|
43092
|
-
const requestContributors = (0,
|
|
43854
|
+
const requestContributors = (0, import_react18.useCallback)(() => {
|
|
43093
43855
|
sendSocketJson(socketRef.current, {
|
|
43094
43856
|
type: "contributors:get",
|
|
43095
43857
|
payload: { boardId: selectedBoardIdRef.current }
|
|
43096
43858
|
});
|
|
43097
43859
|
}, []);
|
|
43098
|
-
(0,
|
|
43860
|
+
(0, import_react18.useEffect)(() => {
|
|
43099
43861
|
setContributors([]);
|
|
43100
43862
|
setPickedIssueIds([]);
|
|
43101
43863
|
}, [selectedBoardId]);
|
|
43102
|
-
const inspectCommit = (0,
|
|
43864
|
+
const inspectCommit = (0, import_react18.useCallback)((sha) => {
|
|
43103
43865
|
sendSocketJson(socketRef.current, { type: "commit:inspect", payload: { sha } });
|
|
43104
43866
|
}, []);
|
|
43105
|
-
(0,
|
|
43867
|
+
(0, import_react18.useEffect)(() => {
|
|
43106
43868
|
if (!commitInspectError) return;
|
|
43107
43869
|
const timeout = setTimeout(() => setCommitInspectError(null), 8e3);
|
|
43108
43870
|
return () => clearTimeout(timeout);
|
|
43109
43871
|
}, [commitInspectError]);
|
|
43110
|
-
(0,
|
|
43872
|
+
(0, import_react18.useEffect)(() => {
|
|
43111
43873
|
if (!removeError) return;
|
|
43112
43874
|
const timeout = setTimeout(() => setRemoveError(null), 8e3);
|
|
43113
43875
|
return () => clearTimeout(timeout);
|
|
43114
43876
|
}, [removeError]);
|
|
43115
|
-
(0,
|
|
43877
|
+
(0, import_react18.useEffect)(() => {
|
|
43116
43878
|
if (!actionError) return;
|
|
43117
43879
|
const timeout = setTimeout(() => setActionError(null), 8e3);
|
|
43118
43880
|
return () => clearTimeout(timeout);
|
|
@@ -43138,6 +43900,81 @@ var App = () => {
|
|
|
43138
43900
|
parentId
|
|
43139
43901
|
});
|
|
43140
43902
|
};
|
|
43903
|
+
const createSwimlane = () => {
|
|
43904
|
+
if (createSwimlaneTitle === null || !selectedBoard) return;
|
|
43905
|
+
const title = createSwimlaneTitle.trim() || "New swimlane";
|
|
43906
|
+
const boardId2 = selectedBoard.id;
|
|
43907
|
+
setCreateSwimlaneTitle(null);
|
|
43908
|
+
setState(
|
|
43909
|
+
(prev) => prev ? {
|
|
43910
|
+
...prev,
|
|
43911
|
+
boards: prev.boards.map(
|
|
43912
|
+
(board) => board.id === boardId2 ? {
|
|
43913
|
+
...board,
|
|
43914
|
+
swimlanes: [
|
|
43915
|
+
...board.swimlanes,
|
|
43916
|
+
{
|
|
43917
|
+
id: `pending-swimlane-${title}`,
|
|
43918
|
+
title,
|
|
43919
|
+
readonly: true,
|
|
43920
|
+
issues: []
|
|
43921
|
+
}
|
|
43922
|
+
]
|
|
43923
|
+
} : board
|
|
43924
|
+
)
|
|
43925
|
+
} : prev
|
|
43926
|
+
);
|
|
43927
|
+
send("swimlane:create", { title, boardId: boardId2 });
|
|
43928
|
+
};
|
|
43929
|
+
const openRenameSwimlane = (swimlaneId) => {
|
|
43930
|
+
const swimlane = visibleSwimlanes.find((x) => x.id === swimlaneId);
|
|
43931
|
+
if (!swimlane) return;
|
|
43932
|
+
setRenameSwimlane({ swimlaneId, title: swimlane.title });
|
|
43933
|
+
};
|
|
43934
|
+
const submitRenameSwimlane = () => {
|
|
43935
|
+
if (!renameSwimlane) return;
|
|
43936
|
+
const { swimlaneId } = renameSwimlane;
|
|
43937
|
+
const title = renameSwimlane.title.trim();
|
|
43938
|
+
setRenameSwimlane(null);
|
|
43939
|
+
if (!title) return;
|
|
43940
|
+
setState(
|
|
43941
|
+
(prev) => prev ? updateSwimlaneInGuiState(prev, swimlaneId, (swimlane) => ({
|
|
43942
|
+
...swimlane,
|
|
43943
|
+
title
|
|
43944
|
+
})) : prev
|
|
43945
|
+
);
|
|
43946
|
+
send("swimlane:edit:title", { swimlaneId, title });
|
|
43947
|
+
};
|
|
43948
|
+
const deletingSwimlane = selectedBoard?.swimlanes.find((x) => x.id === deleteSwimlaneId) ?? null;
|
|
43949
|
+
const offline = !connected && state !== null;
|
|
43950
|
+
const shownSwimlanes = (0, import_react18.useMemo)(
|
|
43951
|
+
() => offline ? visibleSwimlanes.map((swimlane) => ({
|
|
43952
|
+
...swimlane,
|
|
43953
|
+
readonly: true,
|
|
43954
|
+
issues: swimlane.issues.map((issue) => ({ ...issue, readonly: true }))
|
|
43955
|
+
})) : visibleSwimlanes,
|
|
43956
|
+
[offline, visibleSwimlanes]
|
|
43957
|
+
);
|
|
43958
|
+
const dropSwimlane = (swimlaneId) => {
|
|
43959
|
+
const edge = swimlaneDropEdge;
|
|
43960
|
+
setSwimlaneDropEdge(null);
|
|
43961
|
+
if (!edge || !swimlaneId || !selectedBoard) return;
|
|
43962
|
+
const overIndex = visibleSwimlanes.findIndex((x) => x.id === edge.swimlaneId);
|
|
43963
|
+
if (overIndex === -1) return;
|
|
43964
|
+
moveSwimlane(state, setState, send)(
|
|
43965
|
+
swimlaneId,
|
|
43966
|
+
selectedBoard.id,
|
|
43967
|
+
edge.side === "left" ? overIndex : overIndex + 1
|
|
43968
|
+
);
|
|
43969
|
+
};
|
|
43970
|
+
const confirmDeleteSwimlane = () => {
|
|
43971
|
+
if (!deleteSwimlaneId) return;
|
|
43972
|
+
setState(
|
|
43973
|
+
(prev) => prev ? updateSwimlaneInGuiState(prev, deleteSwimlaneId, () => null) : prev
|
|
43974
|
+
);
|
|
43975
|
+
send("swimlane:delete", { swimlaneId: deleteSwimlaneId });
|
|
43976
|
+
setDeleteSwimlaneId(null);
|
|
43977
|
+
};
|
|
43141
43978
|
const addIssueComment = (issueId2, body) => {
|
|
43142
43979
|
setState((prev) => {
|
|
43143
43980
|
if (!prev) return prev;
|
|
@@ -43239,7 +44076,17 @@ var App = () => {
|
|
|
43239
44076
|
});
|
|
43240
44077
|
send("issue:comment:delete", { commentId });
|
|
43241
44078
|
};
|
|
43242
|
-
|
|
44079
|
+
if (noProject) {
|
|
44080
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
44081
|
+
InitProjectScreen,
|
|
44082
|
+
{
|
|
44083
|
+
repoRoot: noProject.repoRoot,
|
|
44084
|
+
message: noProject.message,
|
|
44085
|
+
onRetry: requestState
|
|
44086
|
+
}
|
|
44087
|
+
);
|
|
44088
|
+
}
|
|
44089
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
|
|
43243
44090
|
"div",
|
|
43244
44091
|
{
|
|
43245
44092
|
style: {
|
|
@@ -43251,38 +44098,39 @@ var App = () => {
|
|
|
43251
44098
|
flexDirection: "column"
|
|
43252
44099
|
},
|
|
43253
44100
|
children: [
|
|
43254
|
-
/* @__PURE__ */ (0,
|
|
43255
|
-
commitInspectError && /* @__PURE__ */ (0,
|
|
44101
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(GlobalScrollbarStyles, {}),
|
|
44102
|
+
commitInspectError && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
43256
44103
|
ErrorToast,
|
|
43257
44104
|
{
|
|
43258
44105
|
message: `Couldn't open commit diff: ${commitInspectError}`,
|
|
43259
44106
|
onDismiss: () => setCommitInspectError(null)
|
|
43260
44107
|
}
|
|
43261
44108
|
),
|
|
43262
|
-
removeError && /* @__PURE__ */ (0,
|
|
44109
|
+
removeError && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
43263
44110
|
ErrorToast,
|
|
43264
44111
|
{
|
|
43265
44112
|
message: removeError,
|
|
43266
44113
|
onDismiss: () => setRemoveError(null)
|
|
43267
44114
|
}
|
|
43268
44115
|
),
|
|
43269
|
-
actionError && /* @__PURE__ */ (0,
|
|
44116
|
+
actionError && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
43270
44117
|
ErrorToast,
|
|
43271
44118
|
{
|
|
43272
44119
|
message: actionError,
|
|
43273
44120
|
onDismiss: () => setActionError(null)
|
|
43274
44121
|
}
|
|
43275
44122
|
),
|
|
43276
|
-
/* @__PURE__ */ (0,
|
|
44123
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
43277
44124
|
Header,
|
|
43278
44125
|
{
|
|
43279
44126
|
state,
|
|
43280
|
-
connected,
|
|
44127
|
+
connection: connected ? "connected" : !offline ? "connecting" : reconnectExhausted ? "lost" : "reconnecting",
|
|
44128
|
+
onReconnect: reconnectNow,
|
|
43281
44129
|
scrubbing: state?.timeTravel?.mode === "scrub",
|
|
43282
44130
|
syncStatus
|
|
43283
44131
|
}
|
|
43284
44132
|
),
|
|
43285
|
-
/* @__PURE__ */ (0,
|
|
44133
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
43286
44134
|
TimeScrubber,
|
|
43287
44135
|
{
|
|
43288
44136
|
timeline: history.timeline,
|
|
@@ -43290,31 +44138,33 @@ var App = () => {
|
|
|
43290
44138
|
historyId: history.requestId,
|
|
43291
44139
|
boardId: selectedBoardId,
|
|
43292
44140
|
connected,
|
|
44141
|
+
socketEpoch,
|
|
43293
44142
|
onRequestHistory: requestBoardHistory,
|
|
43294
44143
|
onInspectCommit: inspectCommit,
|
|
44144
|
+
highlightEventId: hoveredLogEventId,
|
|
43295
44145
|
timeTravel: state?.timeTravel ?? { mode: "live", asOfTime: null },
|
|
43296
44146
|
onScrub: scrubToTime,
|
|
43297
44147
|
onReturnToLive: returnToLive,
|
|
43298
44148
|
onBoardFilterChange: setBoardFilter
|
|
43299
44149
|
}
|
|
43300
44150
|
),
|
|
43301
|
-
/* @__PURE__ */ (0,
|
|
44151
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
|
|
43302
44152
|
"div",
|
|
43303
44153
|
{
|
|
43304
44154
|
style: {
|
|
43305
44155
|
display: "flex",
|
|
43306
44156
|
flex: 1,
|
|
43307
|
-
overflow: "hidden"
|
|
44157
|
+
overflow: "hidden",
|
|
44158
|
+
opacity: offline ? 0.55 : 1,
|
|
44159
|
+
transition: "opacity 160ms ease"
|
|
43308
44160
|
},
|
|
43309
44161
|
children: [
|
|
43310
|
-
/* @__PURE__ */ (0,
|
|
44162
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
|
|
43311
44163
|
"main",
|
|
43312
44164
|
{
|
|
43313
44165
|
onClick: clearPicked,
|
|
43314
44166
|
style: {
|
|
43315
|
-
|
|
43316
|
-
// container, and a gap below it would strand its scrollbar.
|
|
43317
|
-
padding: "0 30px 0 30px",
|
|
44167
|
+
padding: "0 0 0 30px",
|
|
43318
44168
|
flex: 1,
|
|
43319
44169
|
minHeight: 0,
|
|
43320
44170
|
display: "flex",
|
|
@@ -43322,7 +44172,7 @@ var App = () => {
|
|
|
43322
44172
|
overflow: "hidden"
|
|
43323
44173
|
},
|
|
43324
44174
|
children: [
|
|
43325
|
-
/* @__PURE__ */ (0,
|
|
44175
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
43326
44176
|
"div",
|
|
43327
44177
|
{
|
|
43328
44178
|
style: {
|
|
@@ -43331,7 +44181,7 @@ var App = () => {
|
|
|
43331
44181
|
alignItems: "center",
|
|
43332
44182
|
gap: 10
|
|
43333
44183
|
},
|
|
43334
|
-
children: /* @__PURE__ */ (0,
|
|
44184
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
43335
44185
|
Dropdown,
|
|
43336
44186
|
{
|
|
43337
44187
|
testId: "board-switcher",
|
|
@@ -43350,7 +44200,7 @@ var App = () => {
|
|
|
43350
44200
|
)
|
|
43351
44201
|
}
|
|
43352
44202
|
),
|
|
43353
|
-
/* @__PURE__ */ (0,
|
|
44203
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
|
|
43354
44204
|
"div",
|
|
43355
44205
|
{
|
|
43356
44206
|
style: {
|
|
@@ -43362,7 +44212,7 @@ var App = () => {
|
|
|
43362
44212
|
overflowY: "hidden"
|
|
43363
44213
|
},
|
|
43364
44214
|
children: [
|
|
43365
|
-
|
|
44215
|
+
shownSwimlanes.map((swimlane) => /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
43366
44216
|
SwimlaneColumn,
|
|
43367
44217
|
{
|
|
43368
44218
|
swimlane,
|
|
@@ -43374,6 +44224,12 @@ var App = () => {
|
|
|
43374
44224
|
onSelectIssue: selectIssue,
|
|
43375
44225
|
onSelectIssueComments: selectIssueComments,
|
|
43376
44226
|
onCreateIssue: openCreateIssueModal,
|
|
44227
|
+
onRenameSwimlane: openRenameSwimlane,
|
|
44228
|
+
onDeleteSwimlane: setDeleteSwimlaneId,
|
|
44229
|
+
dropSide: swimlaneDropEdge?.swimlaneId === swimlane.id ? swimlaneDropEdge.side : null,
|
|
44230
|
+
onSwimlaneDragOver: (swimlaneId, side) => setSwimlaneDropEdge({ swimlaneId, side }),
|
|
44231
|
+
onSwimlaneDragEnd: () => setSwimlaneDropEdge(null),
|
|
44232
|
+
onDropSwimlane: dropSwimlane,
|
|
43377
44233
|
onDropIssue: (issueId2, swimlaneId, targetIndex) => {
|
|
43378
44234
|
const moving = pickedIssueIds.includes(issueId2) ? pickedIssueIds : [issueId2];
|
|
43379
44235
|
moveIssue(state, setState, send)(
|
|
@@ -43390,14 +44246,16 @@ var App = () => {
|
|
|
43390
44246
|
},
|
|
43391
44247
|
swimlane.id
|
|
43392
44248
|
)),
|
|
43393
|
-
!
|
|
44249
|
+
selectedBoard && !selectedBoard.readonly && !offline && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(AddSwimlaneColumn, { onClick: () => setCreateSwimlaneTitle("") }),
|
|
44250
|
+
!(selectedIssue && state?.user) && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { style: { width: ASIDE_WIDTH, flexShrink: 0 } }),
|
|
44251
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { style: { width: BOARD_GUTTER, flexShrink: 0 } })
|
|
43394
44252
|
]
|
|
43395
44253
|
}
|
|
43396
44254
|
)
|
|
43397
44255
|
]
|
|
43398
44256
|
}
|
|
43399
44257
|
),
|
|
43400
|
-
pickedIssues.length > 1 && /* @__PURE__ */ (0,
|
|
44258
|
+
pickedIssues.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
43401
44259
|
BulkDetails,
|
|
43402
44260
|
{
|
|
43403
44261
|
issues: pickedIssues,
|
|
@@ -43415,23 +44273,32 @@ var App = () => {
|
|
|
43415
44273
|
onAddAssignee: (assigneeId) => forPicked((id) => addIssueAssignee(id, assigneeId)),
|
|
43416
44274
|
onRemoveAssignee: (assigneeId) => forPicked((id) => removeIssueAssignee(id, assigneeId)),
|
|
43417
44275
|
onCloseIssues: () => {
|
|
43418
|
-
|
|
44276
|
+
for (const issue of pickedIssues) {
|
|
44277
|
+
if (!issue.isClosed) closeIssue(issue.id);
|
|
44278
|
+
}
|
|
43419
44279
|
clearPicked();
|
|
43420
44280
|
},
|
|
43421
44281
|
onReopenIssues: () => {
|
|
43422
|
-
|
|
44282
|
+
for (const issue of pickedIssues) {
|
|
44283
|
+
if (issue.isClosed) reopenIssue(issue.id);
|
|
44284
|
+
}
|
|
43423
44285
|
clearPicked();
|
|
43424
44286
|
},
|
|
43425
44287
|
onClear: clearPicked
|
|
43426
44288
|
}
|
|
43427
44289
|
),
|
|
43428
|
-
pickedIssues.length <= 1 && selectedIssue && state?.user && /* @__PURE__ */ (0,
|
|
44290
|
+
pickedIssues.length <= 1 && selectedIssue && state?.user && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
43429
44291
|
IssueDetails,
|
|
43430
44292
|
{
|
|
43431
44293
|
whoAmI: state.user,
|
|
43432
|
-
issue:
|
|
44294
|
+
issue: (() => {
|
|
44295
|
+
const base = issueDetail?.issueId === selectedIssue.id ? { ...selectedIssue, description: issueDetail.description } : selectedIssue;
|
|
44296
|
+
return offline ? { ...base, readonly: true } : base;
|
|
44297
|
+
})(),
|
|
43433
44298
|
activeTab: selectedTab,
|
|
43434
44299
|
comments: issueDetail?.issueId === selectedIssue.id ? issueDetail.comments : [],
|
|
44300
|
+
history: issueDetail?.issueId === selectedIssue.id ? issueDetail.history : [],
|
|
44301
|
+
onHoverHistoryEvent: setHoveredLogEventId,
|
|
43435
44302
|
onChangeTab: changeIssueDetailsTab,
|
|
43436
44303
|
onClose: closeIssueDetails,
|
|
43437
44304
|
onEditTitle: editIssueTitle,
|
|
@@ -43458,14 +44325,53 @@ var App = () => {
|
|
|
43458
44325
|
]
|
|
43459
44326
|
}
|
|
43460
44327
|
),
|
|
43461
|
-
createIssueModal && /* @__PURE__ */ (0,
|
|
43462
|
-
|
|
44328
|
+
createIssueModal && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
44329
|
+
CreateNodeModal,
|
|
43463
44330
|
{
|
|
44331
|
+
eyebrow: "New issue",
|
|
44332
|
+
fieldLabel: "title",
|
|
44333
|
+
placeholder: "issue name",
|
|
43464
44334
|
title: createIssueModal.title,
|
|
43465
44335
|
onChangeTitle: (title) => setCreateIssueModal((prev) => prev ? { ...prev, title } : prev),
|
|
43466
44336
|
onCreate: createIssue,
|
|
43467
44337
|
onClose: () => setCreateIssueModal(null)
|
|
43468
44338
|
}
|
|
44339
|
+
),
|
|
44340
|
+
renameSwimlane && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
44341
|
+
CreateNodeModal,
|
|
44342
|
+
{
|
|
44343
|
+
eyebrow: "Rename swimlane",
|
|
44344
|
+
fieldLabel: "title",
|
|
44345
|
+
placeholder: "swimlane name",
|
|
44346
|
+
confirmLabel: "rename",
|
|
44347
|
+
title: renameSwimlane.title,
|
|
44348
|
+
onChangeTitle: (title) => setRenameSwimlane((prev) => prev ? { ...prev, title } : prev),
|
|
44349
|
+
onCreate: submitRenameSwimlane,
|
|
44350
|
+
onClose: () => setRenameSwimlane(null)
|
|
44351
|
+
}
|
|
44352
|
+
),
|
|
44353
|
+
deletingSwimlane && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
44354
|
+
ConfirmModal,
|
|
44355
|
+
{
|
|
44356
|
+
eyebrow: "Delete swimlane",
|
|
44357
|
+
heading: `Delete "${deletingSwimlane.title}"?`,
|
|
44358
|
+
body: deletingSwimlane.issues.length > 0 ? `This also deletes the ${deletingSwimlane.issues.length} ticket${deletingSwimlane.issues.length === 1 ? "" : "s"} in it. Their history stays in the event log, but they leave the board.` : "The swimlane is empty, so nothing else goes with it.",
|
|
44359
|
+
confirmLabel: "delete",
|
|
44360
|
+
onConfirm: confirmDeleteSwimlane,
|
|
44361
|
+
onClose: () => setDeleteSwimlaneId(null)
|
|
44362
|
+
}
|
|
44363
|
+
),
|
|
44364
|
+
createSwimlaneTitle !== null && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
44365
|
+
CreateNodeModal,
|
|
44366
|
+
{
|
|
44367
|
+
eyebrow: "New swimlane",
|
|
44368
|
+
fieldLabel: "title",
|
|
44369
|
+
placeholder: "swimlane name",
|
|
44370
|
+
title: createSwimlaneTitle,
|
|
44371
|
+
onChangeTitle: setCreateSwimlaneTitle,
|
|
44372
|
+
onCreate: createSwimlane,
|
|
44373
|
+
onClose: () => setCreateSwimlaneTitle(null)
|
|
44374
|
+
}
|
|
43469
44375
|
)
|
|
43470
44376
|
]
|
|
43471
44377
|
}
|
|
@@ -43473,12 +44379,12 @@ var App = () => {
|
|
|
43473
44379
|
};
|
|
43474
44380
|
|
|
43475
44381
|
// source/gui/client/main.tsx
|
|
43476
|
-
var
|
|
44382
|
+
var import_jsx_runtime41 = __toESM(require_jsx_runtime(), 1);
|
|
43477
44383
|
(0, import_client.createRoot)(document.getElementById("root")).render(
|
|
43478
|
-
/* @__PURE__ */ (0,
|
|
43479
|
-
/* @__PURE__ */ (0,
|
|
43480
|
-
/* @__PURE__ */ (0,
|
|
43481
|
-
/* @__PURE__ */ (0,
|
|
44384
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(BrowserRouter, { children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(Routes, { children: [
|
|
44385
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(Route, { path: "/", element: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(App, {}) }),
|
|
44386
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(Route, { path: "/board/:boardId/*", element: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(App, {}) }),
|
|
44387
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(Route, { path: "*", element: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(Navigate, { to: "/", replace: true }) })
|
|
43482
44388
|
] }) })
|
|
43483
44389
|
);
|
|
43484
44390
|
/*! Bundled license information:
|