epiq 1.4.2 → 1.4.4
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 +1278 -440
- package/dist/index.js +49 -49
- package/dist/mcp.js +37 -37
- package/package.json +1 -1
package/dist/gui/main.js
CHANGED
|
@@ -24858,7 +24858,14 @@ var GUI_THEME = {
|
|
|
24858
24858
|
dim2: "rgb(100 107 133)",
|
|
24859
24859
|
accent: "#76d4ff",
|
|
24860
24860
|
green: "#8ce99a",
|
|
24861
|
-
red: "#ff8787"
|
|
24861
|
+
red: "#ff8787",
|
|
24862
|
+
transparent: "rgba(0, 0, 0, 0)"
|
|
24863
|
+
};
|
|
24864
|
+
var EVENT_CATEGORY_COLORS = {
|
|
24865
|
+
tickets: GUI_THEME.accent,
|
|
24866
|
+
comments: "#ffd479",
|
|
24867
|
+
tagging: "#c9a5ff",
|
|
24868
|
+
assigning: "#ff9ecd"
|
|
24862
24869
|
};
|
|
24863
24870
|
|
|
24864
24871
|
// source/gui/client/components/Aside.tsx
|
|
@@ -25318,11 +25325,16 @@ var User = ({
|
|
|
25318
25325
|
);
|
|
25319
25326
|
|
|
25320
25327
|
// source/version.ts
|
|
25321
|
-
var EPIQ_VERSION = "1.4.
|
|
25328
|
+
var EPIQ_VERSION = "1.4.4";
|
|
25322
25329
|
|
|
25323
25330
|
// source/gui/client/components/Header.tsx
|
|
25324
25331
|
var import_jsx_runtime7 = __toESM(require_jsx_runtime(), 1);
|
|
25325
|
-
var Header = ({
|
|
25332
|
+
var Header = ({
|
|
25333
|
+
state,
|
|
25334
|
+
connected,
|
|
25335
|
+
scrubbing,
|
|
25336
|
+
syncStatus
|
|
25337
|
+
}) => {
|
|
25326
25338
|
const syncColor = syncStatus.status === "synced" ? GUI_THEME.green : syncStatus.status === "failed" ? GUI_THEME.red : GUI_THEME.accent;
|
|
25327
25339
|
const syncLabel = syncStatus.status === "failed" ? "-" : syncStatus.msg.toLowerCase();
|
|
25328
25340
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
@@ -25381,6 +25393,10 @@ var Header = ({ state, connected, syncStatus }) => {
|
|
|
25381
25393
|
whiteSpace: "nowrap"
|
|
25382
25394
|
},
|
|
25383
25395
|
children: [
|
|
25396
|
+
scrubbing && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
25397
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { color: GUI_THEME.accent, fontWeight: 700 }, children: "Read-only" }),
|
|
25398
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { color: GUI_THEME.dim }, children: "|" })
|
|
25399
|
+
] }),
|
|
25384
25400
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
25385
25401
|
"span",
|
|
25386
25402
|
{
|
|
@@ -25397,7 +25413,6 @@ var Header = ({ state, connected, syncStatus }) => {
|
|
|
25397
25413
|
title: syncStatus.status === "failed" ? syncStatus.msg : void 0,
|
|
25398
25414
|
style: {
|
|
25399
25415
|
color: GUI_THEME.dim,
|
|
25400
|
-
minWidth: 72,
|
|
25401
25416
|
maxWidth: 220,
|
|
25402
25417
|
overflow: "hidden",
|
|
25403
25418
|
textOverflow: "ellipsis",
|
|
@@ -27715,11 +27730,11 @@ function addChildren(props, children) {
|
|
|
27715
27730
|
}
|
|
27716
27731
|
}
|
|
27717
27732
|
}
|
|
27718
|
-
function productionCreate(_,
|
|
27733
|
+
function productionCreate(_, jsx37, jsxs25) {
|
|
27719
27734
|
return create2;
|
|
27720
27735
|
function create2(_2, type, props, key) {
|
|
27721
27736
|
const isStaticChildren = Array.isArray(props.children);
|
|
27722
|
-
const fn = isStaticChildren ?
|
|
27737
|
+
const fn = isStaticChildren ? jsxs25 : jsx37;
|
|
27723
27738
|
return key ? fn(type, props, key) : fn(type, props);
|
|
27724
27739
|
}
|
|
27725
27740
|
}
|
|
@@ -39647,23 +39662,23 @@ var import_react11 = __toESM(require_react(), 1);
|
|
|
39647
39662
|
|
|
39648
39663
|
// source/gui/client/components/IconComment.tsx
|
|
39649
39664
|
var import_jsx_runtime22 = __toESM(require_jsx_runtime(), 1);
|
|
39650
|
-
var IconComment = ({ size =
|
|
39665
|
+
var IconComment = ({ size = 14 }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
39651
39666
|
"svg",
|
|
39652
39667
|
{
|
|
39653
39668
|
width: size,
|
|
39654
39669
|
height: size,
|
|
39655
|
-
viewBox: "0 0
|
|
39670
|
+
viewBox: "0 0 24 24",
|
|
39656
39671
|
fill: "none",
|
|
39672
|
+
stroke: "currentColor",
|
|
39673
|
+
strokeWidth: "2",
|
|
39674
|
+
strokeLinecap: "round",
|
|
39675
|
+
strokeLinejoin: "round",
|
|
39657
39676
|
"aria-hidden": "true",
|
|
39658
39677
|
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
39659
39678
|
"path",
|
|
39660
39679
|
{
|
|
39661
|
-
d: "M3.9 2.6h5.2a2.4 2.4 0 0 1 2.4 2.4v2.5a2.4 2.4 0 0 1-2.4 2.4H6.6l-1.8 2.1.2-2.1H3.9a2.4 2.4 0 0 1-2.4-2.4V5a2.4 2.4 0 0 1 2.4-2.4Z",
|
|
39662
39680
|
fill: "currentColor",
|
|
39663
|
-
|
|
39664
|
-
strokeWidth: "1.55",
|
|
39665
|
-
strokeLinecap: "round",
|
|
39666
|
-
strokeLinejoin: "round"
|
|
39681
|
+
d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"
|
|
39667
39682
|
}
|
|
39668
39683
|
)
|
|
39669
39684
|
}
|
|
@@ -39858,7 +39873,7 @@ var TicketCard = ({
|
|
|
39858
39873
|
color: isSelected ? GUI_THEME.accent : GUI_THEME.secondary,
|
|
39859
39874
|
background: isSelected ? "rgba(118,228,255,0.10)" : "rgba(255,255,255,0.035)",
|
|
39860
39875
|
border: `1px solid ${isSelected ? "rgba(118,228,255,0.28)" : GUI_THEME.line}`,
|
|
39861
|
-
borderRadius:
|
|
39876
|
+
borderRadius: 6,
|
|
39862
39877
|
padding: "3px 7px",
|
|
39863
39878
|
fontSize: 11,
|
|
39864
39879
|
fontWeight: 600,
|
|
@@ -39897,7 +39912,15 @@ var TicketCard = ({
|
|
|
39897
39912
|
paddingTop: 2,
|
|
39898
39913
|
marginTop: "-4px"
|
|
39899
39914
|
},
|
|
39900
|
-
children: ticket.assignees.map((assignee, idx) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
39915
|
+
children: ticket.assignees.map((assignee, idx) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
39916
|
+
User,
|
|
39917
|
+
{
|
|
39918
|
+
user: assignee,
|
|
39919
|
+
index: idx,
|
|
39920
|
+
isFocus: isSelected
|
|
39921
|
+
},
|
|
39922
|
+
assignee.id
|
|
39923
|
+
))
|
|
39901
39924
|
}
|
|
39902
39925
|
)
|
|
39903
39926
|
]
|
|
@@ -40203,7 +40226,7 @@ var EVENTS_MODE_TOTAL_HEIGHT = 8 + TRACK_HEIGHT * 2;
|
|
|
40203
40226
|
var EVENTS_SCATTER_HEIGHT = TRACK_HEIGHT + 16;
|
|
40204
40227
|
var EVENTS_MODE_VERTICAL_PADDING = (EVENTS_MODE_TOTAL_HEIGHT - EVENTS_SCATTER_HEIGHT) / 2;
|
|
40205
40228
|
var HOVER_HINT_WIDTH = 220;
|
|
40206
|
-
var SEGMENT_HIGHLIGHT_COLOR = "rgba(122,
|
|
40229
|
+
var SEGMENT_HIGHLIGHT_COLOR = "rgba(122, 157, 214, 0.14)";
|
|
40207
40230
|
var BUCKET_HIGHLIGHT_COLOR = "rgba(255, 255, 255, 0.06)";
|
|
40208
40231
|
var NEEDLE_COLOR = "rgba(255, 255, 255, 0.62)";
|
|
40209
40232
|
var MIN_BUCKET_COUNT_FOR_GAP = 300;
|
|
@@ -40239,8 +40262,15 @@ var buildAxis = (timeline, commits, now = Date.now()) => {
|
|
|
40239
40262
|
fractionToTime: (fraction) => Math.round(earliest + clamp(fraction, 0, 1) * span)
|
|
40240
40263
|
};
|
|
40241
40264
|
};
|
|
40242
|
-
var bucketIssueCounts = (axis, timeline) => {
|
|
40265
|
+
var bucketIssueCounts = (axis, timeline, view = "all", hiddenIds = /* @__PURE__ */ new Set()) => {
|
|
40243
40266
|
const counts = new Array(axis.bucketCount).fill(0);
|
|
40267
|
+
if (timeline && timeline.events.length > 0) {
|
|
40268
|
+
for (const entry of timeline.events) {
|
|
40269
|
+
if (!isShown(entry, view, hiddenIds)) continue;
|
|
40270
|
+
counts[axis.bucketIndexForTime(entry.t)] += 1;
|
|
40271
|
+
}
|
|
40272
|
+
return counts;
|
|
40273
|
+
}
|
|
40244
40274
|
for (const sparseBucket of timeline?.buckets ?? []) {
|
|
40245
40275
|
counts[axis.bucketIndexForTime(sparseBucket.t)] += sparseBucket.count;
|
|
40246
40276
|
}
|
|
@@ -40258,6 +40288,102 @@ var bucketCommitStats = (axis, commits) => {
|
|
|
40258
40288
|
}
|
|
40259
40289
|
return byIndex;
|
|
40260
40290
|
};
|
|
40291
|
+
var EVENT_CATEGORIES = [
|
|
40292
|
+
"tickets",
|
|
40293
|
+
"comments",
|
|
40294
|
+
"tagging",
|
|
40295
|
+
"assigning"
|
|
40296
|
+
];
|
|
40297
|
+
var BOARD_VIEWS = ["all", ...EVENT_CATEGORIES];
|
|
40298
|
+
var isBoardView = (value) => BOARD_VIEWS.includes(value);
|
|
40299
|
+
var boardViewColor = (view) => view === "all" ? GUI_THEME.accent : EVENT_CATEGORY_COLORS[view];
|
|
40300
|
+
var identityAxisFor = (view) => view === "comments" ? "actor" : view === "tagging" ? "tag" : view === "assigning" ? "assignee" : null;
|
|
40301
|
+
var CATEGORY_BY_ACTION = {
|
|
40302
|
+
"add.issue.comment": "comments",
|
|
40303
|
+
"edit.issue.comment": "comments",
|
|
40304
|
+
"delete.issue.comment": "comments",
|
|
40305
|
+
"add.issue.tag": "tagging",
|
|
40306
|
+
"remove.issue.tag": "tagging",
|
|
40307
|
+
"create.tag": "tagging",
|
|
40308
|
+
"add.issue.assignee": "assigning",
|
|
40309
|
+
"remove.issue.assignee": "assigning",
|
|
40310
|
+
"create.contributor": "assigning",
|
|
40311
|
+
"tombstone.contributor": "assigning",
|
|
40312
|
+
"restore.contributor": "assigning",
|
|
40313
|
+
"link.contributor.user": "assigning"
|
|
40314
|
+
};
|
|
40315
|
+
var categoryOf = (action) => CATEGORY_BY_ACTION[action] ?? "tickets";
|
|
40316
|
+
var identityOf = (entry, view) => {
|
|
40317
|
+
const axis = identityAxisFor(view);
|
|
40318
|
+
return axis === null ? null : entry[axis];
|
|
40319
|
+
};
|
|
40320
|
+
var listIdentities = (timeline, view) => {
|
|
40321
|
+
if (!timeline || identityAxisFor(view) === null) return [];
|
|
40322
|
+
const byId = /* @__PURE__ */ new Map();
|
|
40323
|
+
for (const entry of timeline.events) {
|
|
40324
|
+
if (categoryOf(entry.action) !== view) continue;
|
|
40325
|
+
const identity = identityOf(entry, view);
|
|
40326
|
+
if (identity && !byId.has(identity.id)) byId.set(identity.id, identity);
|
|
40327
|
+
}
|
|
40328
|
+
return [...byId.values()];
|
|
40329
|
+
};
|
|
40330
|
+
var soleVisibleIdentity = (identities, hiddenIds) => {
|
|
40331
|
+
const visible = identities.filter((identity) => !hiddenIds.has(identity.id));
|
|
40332
|
+
return visible.length === 1 ? visible[0] : null;
|
|
40333
|
+
};
|
|
40334
|
+
var dotDetail = (dot) => {
|
|
40335
|
+
const base = dot.label ?? `${dot.count ?? 0} board event${dot.count === 1 ? "" : "s"}`;
|
|
40336
|
+
return dot.identity && !base.includes(dot.identity.name) ? `${base} \u2014 ${dot.identity.name}` : base;
|
|
40337
|
+
};
|
|
40338
|
+
var EVENT_DOT_SIZE = 4;
|
|
40339
|
+
var EVENT_DOT_OPACITY = 0.55;
|
|
40340
|
+
var isShown = (entry, view, hiddenIds) => {
|
|
40341
|
+
if (view !== "all" && categoryOf(entry.action) !== view) return false;
|
|
40342
|
+
const identity = identityOf(entry, view);
|
|
40343
|
+
return identity === null || !hiddenIds.has(identity.id);
|
|
40344
|
+
};
|
|
40345
|
+
var buildEventDots = (timeline, view = "all", hiddenIds = /* @__PURE__ */ new Set()) => {
|
|
40346
|
+
if (!timeline) return [];
|
|
40347
|
+
if (timeline.events.length > 0) {
|
|
40348
|
+
return timeline.events.flatMap((entry, index2) => {
|
|
40349
|
+
if (!isShown(entry, view, hiddenIds)) return [];
|
|
40350
|
+
const category = categoryOf(entry.action);
|
|
40351
|
+
const identity = identityOf(entry, view);
|
|
40352
|
+
return [
|
|
40353
|
+
{
|
|
40354
|
+
// Two events can share a millisecond, so time alone is not a key.
|
|
40355
|
+
key: `${entry.t}-${index2}`,
|
|
40356
|
+
t: entry.t,
|
|
40357
|
+
count: null,
|
|
40358
|
+
label: entry.label,
|
|
40359
|
+
category,
|
|
40360
|
+
color: view === "all" ? EVENT_CATEGORY_COLORS[category] : identity?.color ?? GUI_THEME.accent,
|
|
40361
|
+
identity,
|
|
40362
|
+
size: EVENT_DOT_SIZE,
|
|
40363
|
+
opacity: EVENT_DOT_OPACITY
|
|
40364
|
+
}
|
|
40365
|
+
];
|
|
40366
|
+
});
|
|
40367
|
+
}
|
|
40368
|
+
const maxCount = maxOf(
|
|
40369
|
+
timeline.buckets.map((bucket) => bucket.count),
|
|
40370
|
+
1
|
|
40371
|
+
);
|
|
40372
|
+
return timeline.buckets.map((bucket) => {
|
|
40373
|
+
const intensity = bucket.count / maxCount;
|
|
40374
|
+
return {
|
|
40375
|
+
key: String(bucket.t),
|
|
40376
|
+
t: bucket.t,
|
|
40377
|
+
count: bucket.count,
|
|
40378
|
+
label: null,
|
|
40379
|
+
category: null,
|
|
40380
|
+
color: GUI_THEME.accent,
|
|
40381
|
+
identity: null,
|
|
40382
|
+
size: 3 + intensity * 6,
|
|
40383
|
+
opacity: 0.3 + intensity * 0.5
|
|
40384
|
+
};
|
|
40385
|
+
});
|
|
40386
|
+
};
|
|
40261
40387
|
var populatedRange = (bars) => bars.length > 0 ? [
|
|
40262
40388
|
bars.reduce((min, bar) => Math.min(min, bar.index), Infinity),
|
|
40263
40389
|
bars.reduce((max, bar) => Math.max(max, bar.index), -Infinity)
|
|
@@ -40266,8 +40392,9 @@ var hourFractionForTime = (time) => {
|
|
|
40266
40392
|
const date = new Date(time);
|
|
40267
40393
|
return (date.getHours() * 60 + date.getMinutes()) / (24 * 60);
|
|
40268
40394
|
};
|
|
40269
|
-
var SEGMENT_UNIT_ORDER = ["day", "week", "month", "year"];
|
|
40395
|
+
var SEGMENT_UNIT_ORDER = ["hour", "day", "week", "month", "year"];
|
|
40270
40396
|
var APPROX_UNIT_MS = {
|
|
40397
|
+
hour: 60 * 60 * 1e3,
|
|
40271
40398
|
day: 24 * 60 * 60 * 1e3,
|
|
40272
40399
|
week: 7 * 24 * 60 * 60 * 1e3,
|
|
40273
40400
|
month: 30.44 * 24 * 60 * 60 * 1e3,
|
|
@@ -40293,14 +40420,16 @@ var MONTH_LABELS = [
|
|
|
40293
40420
|
"Dec"
|
|
40294
40421
|
];
|
|
40295
40422
|
var advanceByUnit = (date, unit) => {
|
|
40296
|
-
if (unit === "
|
|
40423
|
+
if (unit === "hour") date.setHours(date.getHours() + 1);
|
|
40424
|
+
else if (unit === "day") date.setDate(date.getDate() + 1);
|
|
40297
40425
|
else if (unit === "week") date.setDate(date.getDate() + 7);
|
|
40298
40426
|
else if (unit === "month") date.setMonth(date.getMonth() + 1);
|
|
40299
40427
|
else date.setFullYear(date.getFullYear() + 1);
|
|
40300
40428
|
};
|
|
40301
40429
|
var segmentAt = (time, unit) => {
|
|
40302
40430
|
const start2 = new Date(time);
|
|
40303
|
-
start2.
|
|
40431
|
+
if (unit === "hour") start2.setMinutes(0, 0, 0);
|
|
40432
|
+
else start2.setHours(0, 0, 0, 0);
|
|
40304
40433
|
if (unit === "week") {
|
|
40305
40434
|
start2.setDate(start2.getDate() - (start2.getDay() + 6) % 7);
|
|
40306
40435
|
} else if (unit === "month") {
|
|
@@ -40311,7 +40440,10 @@ var segmentAt = (time, unit) => {
|
|
|
40311
40440
|
const end = new Date(start2);
|
|
40312
40441
|
advanceByUnit(end, unit);
|
|
40313
40442
|
const lastDay = new Date(end.getTime() - 1);
|
|
40314
|
-
const label = unit === "
|
|
40443
|
+
const label = unit === "hour" ? `${WEEKDAY_LABELS[start2.getDay()]} ${String(start2.getHours()).padStart(
|
|
40444
|
+
2,
|
|
40445
|
+
"0"
|
|
40446
|
+
)}: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()}`;
|
|
40315
40447
|
return { start: start2.getTime(), end: end.getTime(), label };
|
|
40316
40448
|
};
|
|
40317
40449
|
var formatInterval = (start2, end) => {
|
|
@@ -40320,12 +40452,19 @@ var formatInterval = (start2, end) => {
|
|
|
40320
40452
|
const endLabel = isSameDay(startDate, endDate) ? formatTimeOfDay(endDate) : formatDateTime(endDate);
|
|
40321
40453
|
return `${formatDateTime(startDate)} \u2013 ${endLabel}`;
|
|
40322
40454
|
};
|
|
40323
|
-
var SCOPES = ["week", "month", "year", "all"];
|
|
40455
|
+
var SCOPES = ["day", "week", "month", "year", "all"];
|
|
40324
40456
|
var SCOPE_DURATION_MS = {
|
|
40457
|
+
day: 24 * 60 * 60 * 1e3,
|
|
40325
40458
|
week: 7 * 24 * 60 * 60 * 1e3,
|
|
40326
40459
|
month: 30 * 24 * 60 * 60 * 1e3,
|
|
40327
40460
|
year: 365 * 24 * 60 * 60 * 1e3
|
|
40328
40461
|
};
|
|
40462
|
+
var SCOPE_RECENT_LABELS = {
|
|
40463
|
+
day: "Last 24 hours",
|
|
40464
|
+
week: "Last 7 days",
|
|
40465
|
+
month: "Last 30 days",
|
|
40466
|
+
year: "Last 365 days"
|
|
40467
|
+
};
|
|
40329
40468
|
var isScope = (value) => SCOPES.includes(value ?? "");
|
|
40330
40469
|
var getPeriodRange = (scope, offset) => {
|
|
40331
40470
|
if (scope === "all") return null;
|
|
@@ -40335,9 +40474,7 @@ var getPeriodRange = (scope, offset) => {
|
|
|
40335
40474
|
};
|
|
40336
40475
|
var formatPeriodLabel = (scope, offset, range) => {
|
|
40337
40476
|
if (scope === "all" || !range) return "All time";
|
|
40338
|
-
if (offset === 0)
|
|
40339
|
-
return scope === "week" ? "Last 7 days" : scope === "month" ? "Last 30 days" : "Last 365 days";
|
|
40340
|
-
}
|
|
40477
|
+
if (offset === 0) return SCOPE_RECENT_LABELS[scope];
|
|
40341
40478
|
const start2 = new Date(range.start);
|
|
40342
40479
|
const end = new Date(range.end);
|
|
40343
40480
|
return `${start2.getMonth() + 1}/${start2.getDate()} \u2013 ${end.getMonth() + 1}/${end.getDate()}`;
|
|
@@ -40354,10 +40491,16 @@ var hashUnitInterval = (key) => {
|
|
|
40354
40491
|
var DOT_APPEAR_MS = 260;
|
|
40355
40492
|
var DOT_APPEAR_SCATTER_MS = 620;
|
|
40356
40493
|
var dotDelayMs = (key) => Math.round(hashUnitInterval(key) * DOT_APPEAR_SCATTER_MS);
|
|
40357
|
-
var
|
|
40358
|
-
|
|
40359
|
-
)
|
|
40360
|
-
var
|
|
40494
|
+
var easeOutCubic = (t) => 1 - Math.pow(1 - t, 3);
|
|
40495
|
+
var easeInCubic = (t) => t * t * t;
|
|
40496
|
+
var dotEntranceScale = (key, elapsedMs) => easeOutCubic(clamp((elapsedMs - dotDelayMs(key)) / DOT_APPEAR_MS, 0, 1));
|
|
40497
|
+
var dotExitScale = (key, elapsedMs) => 1 - easeInCubic(
|
|
40498
|
+
clamp(
|
|
40499
|
+
(elapsedMs - (DOT_APPEAR_SCATTER_MS - dotDelayMs(key))) / DOT_APPEAR_MS,
|
|
40500
|
+
0,
|
|
40501
|
+
1
|
|
40502
|
+
)
|
|
40503
|
+
);
|
|
40361
40504
|
var DOT_EXIT_TOTAL_MS = DOT_APPEAR_SCATTER_MS + DOT_APPEAR_MS;
|
|
40362
40505
|
var BAR_GROW_MS = 200;
|
|
40363
40506
|
var BAR_GROW_SWEEP_MS = 560;
|
|
@@ -40450,6 +40593,19 @@ var usePersistedFlag = (key, fallback) => {
|
|
|
40450
40593
|
}
|
|
40451
40594
|
];
|
|
40452
40595
|
};
|
|
40596
|
+
var buildBoardFilter = (view, identities, hiddenIds) => {
|
|
40597
|
+
const axis = identityAxisFor(view);
|
|
40598
|
+
if (axis === null || hiddenIds.size === 0) return null;
|
|
40599
|
+
const visibleIds = new Set(
|
|
40600
|
+
identities.map((identity) => identity.id).filter((id) => !hiddenIds.has(id))
|
|
40601
|
+
);
|
|
40602
|
+
return { axis, visibleIds };
|
|
40603
|
+
};
|
|
40604
|
+
var issuePassesBoardFilter = (issue, commentAuthorIds, filter) => {
|
|
40605
|
+
if (!filter) return true;
|
|
40606
|
+
const ids = filter.axis === "tag" ? issue.tags.map((tag) => tag.id) : filter.axis === "assignee" ? issue.assignees.map((assignee) => assignee.id) : commentAuthorIds;
|
|
40607
|
+
return ids.some((id) => filter.visibleIds.has(id));
|
|
40608
|
+
};
|
|
40453
40609
|
|
|
40454
40610
|
// source/gui/client/components/ScrubberParts.tsx
|
|
40455
40611
|
var import_react14 = __toESM(require_react(), 1);
|
|
@@ -40534,9 +40690,32 @@ var Checkbox = ({
|
|
|
40534
40690
|
);
|
|
40535
40691
|
};
|
|
40536
40692
|
|
|
40537
|
-
// source/gui/client/components/
|
|
40693
|
+
// source/gui/client/components/IconBars.tsx
|
|
40538
40694
|
var import_jsx_runtime28 = __toESM(require_jsx_runtime(), 1);
|
|
40539
|
-
var
|
|
40695
|
+
var IconBars = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
40696
|
+
"svg",
|
|
40697
|
+
{
|
|
40698
|
+
width: size,
|
|
40699
|
+
height: size,
|
|
40700
|
+
viewBox: "0 0 24 24",
|
|
40701
|
+
fill: "none",
|
|
40702
|
+
stroke: "currentColor",
|
|
40703
|
+
strokeWidth: "2.2",
|
|
40704
|
+
strokeLinecap: "round",
|
|
40705
|
+
"aria-hidden": "true",
|
|
40706
|
+
children: [
|
|
40707
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("line", { x1: "3", y1: "8.5", x2: "3", y2: "15.5" }),
|
|
40708
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("line", { x1: "7.5", y1: "4.5", x2: "7.5", y2: "19.5" }),
|
|
40709
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("line", { x1: "12", y1: "7", x2: "12", y2: "17" }),
|
|
40710
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("line", { x1: "16.5", y1: "3", x2: "16.5", y2: "21" }),
|
|
40711
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("line", { x1: "21", y1: "9.5", x2: "21", y2: "14.5" })
|
|
40712
|
+
]
|
|
40713
|
+
}
|
|
40714
|
+
);
|
|
40715
|
+
|
|
40716
|
+
// source/gui/client/components/IconChevronDown.tsx
|
|
40717
|
+
var import_jsx_runtime29 = __toESM(require_jsx_runtime(), 1);
|
|
40718
|
+
var IconChevronDown = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
40540
40719
|
"svg",
|
|
40541
40720
|
{
|
|
40542
40721
|
width: size,
|
|
@@ -40548,13 +40727,13 @@ var IconChevronDown = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime2
|
|
|
40548
40727
|
strokeLinecap: "round",
|
|
40549
40728
|
strokeLinejoin: "round",
|
|
40550
40729
|
"aria-hidden": "true",
|
|
40551
|
-
children: /* @__PURE__ */ (0,
|
|
40730
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("polyline", { points: "6 9 12 15 18 9" })
|
|
40552
40731
|
}
|
|
40553
40732
|
);
|
|
40554
40733
|
|
|
40555
40734
|
// source/gui/client/components/IconChevronRight.tsx
|
|
40556
|
-
var
|
|
40557
|
-
var IconChevronRight = ({ size = 16 }) => /* @__PURE__ */ (0,
|
|
40735
|
+
var import_jsx_runtime30 = __toESM(require_jsx_runtime(), 1);
|
|
40736
|
+
var IconChevronRight = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
40558
40737
|
"svg",
|
|
40559
40738
|
{
|
|
40560
40739
|
width: size,
|
|
@@ -40566,12 +40745,33 @@ var IconChevronRight = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime
|
|
|
40566
40745
|
strokeLinecap: "round",
|
|
40567
40746
|
strokeLinejoin: "round",
|
|
40568
40747
|
"aria-hidden": "true",
|
|
40569
|
-
children: /* @__PURE__ */ (0,
|
|
40748
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("polyline", { points: "9 18 15 12 9 6" })
|
|
40749
|
+
}
|
|
40750
|
+
);
|
|
40751
|
+
|
|
40752
|
+
// source/gui/client/components/IconScatter.tsx
|
|
40753
|
+
var import_jsx_runtime31 = __toESM(require_jsx_runtime(), 1);
|
|
40754
|
+
var IconScatter = ({ size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
40755
|
+
"svg",
|
|
40756
|
+
{
|
|
40757
|
+
width: size,
|
|
40758
|
+
height: size,
|
|
40759
|
+
viewBox: "0 0 24 24",
|
|
40760
|
+
fill: "currentColor",
|
|
40761
|
+
stroke: "none",
|
|
40762
|
+
"aria-hidden": "true",
|
|
40763
|
+
children: [
|
|
40764
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("circle", { cx: "4.5", cy: "8", r: "2.2" }),
|
|
40765
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("circle", { cx: "9.5", cy: "17", r: "2.2" }),
|
|
40766
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("circle", { cx: "13", cy: "6.5", r: "2.2" }),
|
|
40767
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("circle", { cx: "17", cy: "14.5", r: "2.2" }),
|
|
40768
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("circle", { cx: "20.5", cy: "8.5", r: "2.2" })
|
|
40769
|
+
]
|
|
40570
40770
|
}
|
|
40571
40771
|
);
|
|
40572
40772
|
|
|
40573
40773
|
// source/gui/client/components/ScrubberParts.tsx
|
|
40574
|
-
var
|
|
40774
|
+
var import_jsx_runtime32 = __toESM(require_jsx_runtime(), 1);
|
|
40575
40775
|
var toggleButtonStyle = (active) => ({
|
|
40576
40776
|
background: "transparent",
|
|
40577
40777
|
border: `1px solid ${active ? GUI_THEME.accent : GUI_THEME.dim}`,
|
|
@@ -40581,6 +40781,330 @@ var toggleButtonStyle = (active) => ({
|
|
|
40581
40781
|
padding: "2px 8px",
|
|
40582
40782
|
cursor: "pointer"
|
|
40583
40783
|
});
|
|
40784
|
+
var iconToggleButtonStyle = (active) => ({
|
|
40785
|
+
...toggleButtonStyle(active),
|
|
40786
|
+
display: "inline-flex",
|
|
40787
|
+
alignItems: "center",
|
|
40788
|
+
justifyContent: "center",
|
|
40789
|
+
padding: "3px 7px"
|
|
40790
|
+
});
|
|
40791
|
+
var CATEGORY_LABELS = {
|
|
40792
|
+
tickets: "Tickets",
|
|
40793
|
+
comments: "Comments",
|
|
40794
|
+
tagging: "Tags",
|
|
40795
|
+
assigning: "Assignees"
|
|
40796
|
+
};
|
|
40797
|
+
var disclosureStyle = {
|
|
40798
|
+
background: "transparent",
|
|
40799
|
+
border: "none",
|
|
40800
|
+
padding: 0,
|
|
40801
|
+
display: "inline-flex",
|
|
40802
|
+
alignItems: "center",
|
|
40803
|
+
color: GUI_THEME.secondary,
|
|
40804
|
+
cursor: "pointer"
|
|
40805
|
+
};
|
|
40806
|
+
var VIEW_LABELS = {
|
|
40807
|
+
all: "All board events",
|
|
40808
|
+
...CATEGORY_LABELS
|
|
40809
|
+
};
|
|
40810
|
+
var SELECT_TRIGGER_WIDTH = 180;
|
|
40811
|
+
var selectTriggerStyle = (color2, disabled) => ({
|
|
40812
|
+
display: "inline-flex",
|
|
40813
|
+
alignItems: "center",
|
|
40814
|
+
justifyContent: "space-between",
|
|
40815
|
+
gap: 6,
|
|
40816
|
+
width: SELECT_TRIGGER_WIDTH,
|
|
40817
|
+
boxSizing: "border-box",
|
|
40818
|
+
background: "rgba(208, 223, 255, 0.08)",
|
|
40819
|
+
// None, but padded as though there were, so it sits at the same height as
|
|
40820
|
+
// the bordered toggles on either side.
|
|
40821
|
+
border: "none",
|
|
40822
|
+
color: disabled ? GUI_THEME.dim : color2,
|
|
40823
|
+
borderRadius: 6,
|
|
40824
|
+
fontFamily: "inherit",
|
|
40825
|
+
fontSize: 10,
|
|
40826
|
+
padding: "3px 7px 3px 9px",
|
|
40827
|
+
cursor: disabled ? "not-allowed" : "pointer",
|
|
40828
|
+
opacity: disabled ? 0.4 : 1
|
|
40829
|
+
});
|
|
40830
|
+
var nestedListStyle = {
|
|
40831
|
+
display: "flex",
|
|
40832
|
+
flexDirection: "column",
|
|
40833
|
+
gap: 7,
|
|
40834
|
+
marginLeft: 5,
|
|
40835
|
+
paddingLeft: 8,
|
|
40836
|
+
borderLeft: `1px solid ${GUI_THEME.line}`
|
|
40837
|
+
};
|
|
40838
|
+
var popoverStyle = {
|
|
40839
|
+
position: "absolute",
|
|
40840
|
+
top: "100%",
|
|
40841
|
+
left: 0,
|
|
40842
|
+
marginTop: 6,
|
|
40843
|
+
// Carries the column and its gap itself. Without them the options stack as
|
|
40844
|
+
// plain blocks and their radios sit edge to edge.
|
|
40845
|
+
display: "flex",
|
|
40846
|
+
flexDirection: "column",
|
|
40847
|
+
gap: 7,
|
|
40848
|
+
padding: "10px 14px 10px 10px",
|
|
40849
|
+
// Sized for the common case up front, so opening a kind with a list does
|
|
40850
|
+
// not visibly widen the panel under the pointer.
|
|
40851
|
+
minWidth: 200,
|
|
40852
|
+
// Slightly sheer over a blur, so the chart it filters stays legible beneath
|
|
40853
|
+
// it rather than being covered outright.
|
|
40854
|
+
background: "rgba(21, 26, 36, 0.88)",
|
|
40855
|
+
backdropFilter: "blur(12px)",
|
|
40856
|
+
WebkitBackdropFilter: "blur(12px)",
|
|
40857
|
+
border: `1px solid ${GUI_THEME.line}`,
|
|
40858
|
+
borderRadius: 8,
|
|
40859
|
+
boxShadow: "0 8px 24px rgba(0, 0, 0, 0.45)",
|
|
40860
|
+
// Above the dots and the needle, which sit at 1 and 2.
|
|
40861
|
+
zIndex: 30,
|
|
40862
|
+
whiteSpace: "nowrap"
|
|
40863
|
+
};
|
|
40864
|
+
var onlyButtonStyle = {
|
|
40865
|
+
background: "transparent",
|
|
40866
|
+
border: `1px solid ${GUI_THEME.line}`,
|
|
40867
|
+
borderRadius: 4,
|
|
40868
|
+
color: GUI_THEME.dim,
|
|
40869
|
+
fontFamily: "inherit",
|
|
40870
|
+
fontSize: 9,
|
|
40871
|
+
lineHeight: 1,
|
|
40872
|
+
padding: "2px 4px",
|
|
40873
|
+
cursor: "pointer"
|
|
40874
|
+
};
|
|
40875
|
+
var useDismissOnOutsideClick = (open, onDismiss) => {
|
|
40876
|
+
const ref = (0, import_react14.useRef)(null);
|
|
40877
|
+
(0, import_react14.useEffect)(() => {
|
|
40878
|
+
if (!open) return;
|
|
40879
|
+
const onPointerDown = (event) => {
|
|
40880
|
+
if (!ref.current?.contains(event.target)) onDismiss();
|
|
40881
|
+
};
|
|
40882
|
+
const onKeyDown = (event) => {
|
|
40883
|
+
if (event.key === "Escape") onDismiss();
|
|
40884
|
+
};
|
|
40885
|
+
document.addEventListener("mousedown", onPointerDown);
|
|
40886
|
+
document.addEventListener("keydown", onKeyDown);
|
|
40887
|
+
return () => {
|
|
40888
|
+
document.removeEventListener("mousedown", onPointerDown);
|
|
40889
|
+
document.removeEventListener("keydown", onKeyDown);
|
|
40890
|
+
};
|
|
40891
|
+
}, [open, onDismiss]);
|
|
40892
|
+
return ref;
|
|
40893
|
+
};
|
|
40894
|
+
var Radio = ({
|
|
40895
|
+
label,
|
|
40896
|
+
selected,
|
|
40897
|
+
color: color2,
|
|
40898
|
+
disabled,
|
|
40899
|
+
onSelect
|
|
40900
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
40901
|
+
"button",
|
|
40902
|
+
{
|
|
40903
|
+
type: "button",
|
|
40904
|
+
role: "radio",
|
|
40905
|
+
"aria-checked": selected,
|
|
40906
|
+
disabled,
|
|
40907
|
+
onClick: onSelect,
|
|
40908
|
+
style: {
|
|
40909
|
+
display: "flex",
|
|
40910
|
+
alignItems: "center",
|
|
40911
|
+
gap: 5,
|
|
40912
|
+
background: "transparent",
|
|
40913
|
+
border: "none",
|
|
40914
|
+
padding: 0,
|
|
40915
|
+
fontSize: 10,
|
|
40916
|
+
fontFamily: "inherit",
|
|
40917
|
+
color: selected ? color2 : GUI_THEME.dim,
|
|
40918
|
+
cursor: disabled ? "not-allowed" : "pointer",
|
|
40919
|
+
opacity: disabled ? 0.4 : 1
|
|
40920
|
+
},
|
|
40921
|
+
children: [
|
|
40922
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
40923
|
+
"span",
|
|
40924
|
+
{
|
|
40925
|
+
style: {
|
|
40926
|
+
width: 12,
|
|
40927
|
+
height: 12,
|
|
40928
|
+
borderRadius: "50%",
|
|
40929
|
+
border: `1px solid ${selected ? color2 : GUI_THEME.dim}`,
|
|
40930
|
+
display: "inline-flex",
|
|
40931
|
+
alignItems: "center",
|
|
40932
|
+
justifyContent: "center",
|
|
40933
|
+
flexShrink: 0
|
|
40934
|
+
},
|
|
40935
|
+
children: selected && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
40936
|
+
"span",
|
|
40937
|
+
{
|
|
40938
|
+
style: {
|
|
40939
|
+
width: 6,
|
|
40940
|
+
height: 6,
|
|
40941
|
+
borderRadius: "50%",
|
|
40942
|
+
background: color2
|
|
40943
|
+
}
|
|
40944
|
+
}
|
|
40945
|
+
)
|
|
40946
|
+
}
|
|
40947
|
+
),
|
|
40948
|
+
label
|
|
40949
|
+
]
|
|
40950
|
+
}
|
|
40951
|
+
);
|
|
40952
|
+
var BoardSeriesGroup = ({
|
|
40953
|
+
showIssues,
|
|
40954
|
+
view,
|
|
40955
|
+
identities,
|
|
40956
|
+
hiddenIds,
|
|
40957
|
+
expanded,
|
|
40958
|
+
identitiesExpanded,
|
|
40959
|
+
filtered,
|
|
40960
|
+
onChangeShowIssues,
|
|
40961
|
+
onChangeView,
|
|
40962
|
+
onToggleIdentity,
|
|
40963
|
+
onOnlyIdentity,
|
|
40964
|
+
onToggleExpanded,
|
|
40965
|
+
onSetIdentitiesExpanded
|
|
40966
|
+
}) => {
|
|
40967
|
+
const sole = soleVisibleIdentity(identities, hiddenIds);
|
|
40968
|
+
const partial = filtered && hiddenIds.size > 0 && identityAxisFor(view) !== null;
|
|
40969
|
+
const label = sole ? `${VIEW_LABELS[view]}: ${sole.name}` : partial ? `${VIEW_LABELS[view]} (multi)` : VIEW_LABELS[view];
|
|
40970
|
+
const color2 = sole?.color ?? (partial ? GUI_THEME.dim2 : boardViewColor(view));
|
|
40971
|
+
const ref = useDismissOnOutsideClick(expanded, onToggleExpanded);
|
|
40972
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
40973
|
+
"div",
|
|
40974
|
+
{
|
|
40975
|
+
ref,
|
|
40976
|
+
style: { position: "relative", display: "flex", flexDirection: "column" },
|
|
40977
|
+
children: [
|
|
40978
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
|
|
40979
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
40980
|
+
Checkbox,
|
|
40981
|
+
{
|
|
40982
|
+
label: null,
|
|
40983
|
+
title: "Show board events",
|
|
40984
|
+
checked: showIssues,
|
|
40985
|
+
activeColor: color2,
|
|
40986
|
+
onChange: onChangeShowIssues
|
|
40987
|
+
}
|
|
40988
|
+
),
|
|
40989
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
40990
|
+
"button",
|
|
40991
|
+
{
|
|
40992
|
+
type: "button",
|
|
40993
|
+
onClick: onToggleExpanded,
|
|
40994
|
+
disabled: !showIssues,
|
|
40995
|
+
title: filtered ? "Choose what the board series plots" : "This window holds too many events to split by kind",
|
|
40996
|
+
"aria-haspopup": "listbox",
|
|
40997
|
+
"aria-expanded": expanded,
|
|
40998
|
+
style: selectTriggerStyle(color2, !showIssues),
|
|
40999
|
+
children: [
|
|
41000
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
41001
|
+
"span",
|
|
41002
|
+
{
|
|
41003
|
+
style: {
|
|
41004
|
+
overflow: "hidden",
|
|
41005
|
+
textOverflow: "ellipsis",
|
|
41006
|
+
whiteSpace: "nowrap"
|
|
41007
|
+
},
|
|
41008
|
+
children: label
|
|
41009
|
+
}
|
|
41010
|
+
),
|
|
41011
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { style: { display: "inline-flex", flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(IconChevronDown, { size: 12 }) })
|
|
41012
|
+
]
|
|
41013
|
+
}
|
|
41014
|
+
)
|
|
41015
|
+
] }),
|
|
41016
|
+
expanded && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { role: "radiogroup", style: popoverStyle, children: BOARD_VIEWS.map((option) => {
|
|
41017
|
+
const selected = view === option;
|
|
41018
|
+
const hasList = identityAxisFor(option) !== null;
|
|
41019
|
+
const open = selected && identitiesExpanded;
|
|
41020
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
41021
|
+
"div",
|
|
41022
|
+
{
|
|
41023
|
+
style: { display: "flex", flexDirection: "column", gap: 7 },
|
|
41024
|
+
children: [
|
|
41025
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 3 }, children: [
|
|
41026
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
41027
|
+
Radio,
|
|
41028
|
+
{
|
|
41029
|
+
label: VIEW_LABELS[option],
|
|
41030
|
+
selected,
|
|
41031
|
+
color: boardViewColor(option),
|
|
41032
|
+
disabled: !showIssues || !filtered,
|
|
41033
|
+
onSelect: () => onChangeView(option)
|
|
41034
|
+
}
|
|
41035
|
+
),
|
|
41036
|
+
hasList && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
41037
|
+
"button",
|
|
41038
|
+
{
|
|
41039
|
+
type: "button",
|
|
41040
|
+
disabled: !showIssues || !filtered,
|
|
41041
|
+
onClick: () => {
|
|
41042
|
+
if (!selected) onChangeView(option);
|
|
41043
|
+
onSetIdentitiesExpanded(!open);
|
|
41044
|
+
},
|
|
41045
|
+
title: open ? "Hide the list" : "Pick which to show",
|
|
41046
|
+
"aria-expanded": open,
|
|
41047
|
+
style: disclosureStyle,
|
|
41048
|
+
children: open ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(IconChevronDown, { size: 12 }) : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(IconChevronRight, { size: 12 })
|
|
41049
|
+
}
|
|
41050
|
+
)
|
|
41051
|
+
] }),
|
|
41052
|
+
open && identities.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
41053
|
+
"div",
|
|
41054
|
+
{
|
|
41055
|
+
style: {
|
|
41056
|
+
...nestedListStyle,
|
|
41057
|
+
// A repo with dozens of tags would otherwise push the
|
|
41058
|
+
// board itself off the screen.
|
|
41059
|
+
maxHeight: 132,
|
|
41060
|
+
overflowY: "auto"
|
|
41061
|
+
},
|
|
41062
|
+
children: identities.map((identity) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
41063
|
+
"div",
|
|
41064
|
+
{
|
|
41065
|
+
style: {
|
|
41066
|
+
display: "flex",
|
|
41067
|
+
alignItems: "center",
|
|
41068
|
+
justifyContent: "space-between",
|
|
41069
|
+
gap: 10
|
|
41070
|
+
},
|
|
41071
|
+
children: [
|
|
41072
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
41073
|
+
Checkbox,
|
|
41074
|
+
{
|
|
41075
|
+
label: identity.name,
|
|
41076
|
+
checked: !hiddenIds.has(identity.id),
|
|
41077
|
+
activeColor: identity.color,
|
|
41078
|
+
disabled: !showIssues,
|
|
41079
|
+
onChange: (next) => onToggleIdentity(identity.id, next)
|
|
41080
|
+
}
|
|
41081
|
+
),
|
|
41082
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
41083
|
+
"button",
|
|
41084
|
+
{
|
|
41085
|
+
type: "button",
|
|
41086
|
+
title: `Show only ${identity.name}`,
|
|
41087
|
+
disabled: !showIssues,
|
|
41088
|
+
onClick: () => onOnlyIdentity(identity.id),
|
|
41089
|
+
style: onlyButtonStyle,
|
|
41090
|
+
children: "only"
|
|
41091
|
+
}
|
|
41092
|
+
)
|
|
41093
|
+
]
|
|
41094
|
+
},
|
|
41095
|
+
identity.id
|
|
41096
|
+
))
|
|
41097
|
+
}
|
|
41098
|
+
)
|
|
41099
|
+
]
|
|
41100
|
+
},
|
|
41101
|
+
option
|
|
41102
|
+
);
|
|
41103
|
+
}) })
|
|
41104
|
+
]
|
|
41105
|
+
}
|
|
41106
|
+
);
|
|
41107
|
+
};
|
|
40584
41108
|
var navButtonStyle = {
|
|
40585
41109
|
background: "transparent",
|
|
40586
41110
|
border: `1px solid ${GUI_THEME.dim}`,
|
|
@@ -40599,167 +41123,173 @@ var ScrubberControls = ({
|
|
|
40599
41123
|
showIssues,
|
|
40600
41124
|
showCommits,
|
|
40601
41125
|
allBoards,
|
|
41126
|
+
boardView,
|
|
41127
|
+
identities,
|
|
41128
|
+
hiddenIdentityIds,
|
|
41129
|
+
categoriesExpanded,
|
|
41130
|
+
identitiesExpanded,
|
|
41131
|
+
categoriesFiltered,
|
|
40602
41132
|
isScrubbing,
|
|
40603
|
-
|
|
41133
|
+
onReturnToLive,
|
|
40604
41134
|
onChangeScope,
|
|
40605
41135
|
onChangeOffset,
|
|
40606
41136
|
onChangeLayoutMode,
|
|
40607
41137
|
onChangeShowIssues,
|
|
40608
41138
|
onChangeShowCommits,
|
|
40609
41139
|
onChangeAllBoards,
|
|
40610
|
-
|
|
40611
|
-
|
|
40612
|
-
|
|
40613
|
-
|
|
40614
|
-
|
|
40615
|
-
|
|
40616
|
-
|
|
40617
|
-
|
|
40618
|
-
|
|
40619
|
-
|
|
40620
|
-
|
|
40621
|
-
|
|
40622
|
-
|
|
40623
|
-
|
|
40624
|
-
|
|
40625
|
-
|
|
40626
|
-
|
|
40627
|
-
|
|
40628
|
-
|
|
40629
|
-
|
|
40630
|
-
|
|
40631
|
-
|
|
40632
|
-
|
|
40633
|
-
|
|
40634
|
-
|
|
40635
|
-
|
|
40636
|
-
|
|
40637
|
-
|
|
40638
|
-
|
|
40639
|
-
|
|
40640
|
-
|
|
40641
|
-
|
|
40642
|
-
|
|
40643
|
-
|
|
40644
|
-
|
|
40645
|
-
|
|
40646
|
-
|
|
40647
|
-
|
|
40648
|
-
|
|
40649
|
-
|
|
41140
|
+
onChangeBoardView,
|
|
41141
|
+
onToggleIdentity,
|
|
41142
|
+
onOnlyIdentity,
|
|
41143
|
+
onToggleCategoriesExpanded,
|
|
41144
|
+
onSetIdentitiesExpanded
|
|
41145
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
41146
|
+
"div",
|
|
41147
|
+
{
|
|
41148
|
+
style: {
|
|
41149
|
+
display: "flex",
|
|
41150
|
+
alignItems: "center",
|
|
41151
|
+
justifyContent: "flex-end",
|
|
41152
|
+
gap: 12
|
|
41153
|
+
},
|
|
41154
|
+
children: [
|
|
41155
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
|
|
41156
|
+
scope !== "all" && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 2 }, children: [
|
|
41157
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
41158
|
+
"button",
|
|
41159
|
+
{
|
|
41160
|
+
title: "Earlier",
|
|
41161
|
+
onClick: () => onChangeOffset(offset + 1),
|
|
41162
|
+
style: navButtonStyle,
|
|
41163
|
+
children: "\u25C0"
|
|
41164
|
+
}
|
|
41165
|
+
),
|
|
41166
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
41167
|
+
"span",
|
|
41168
|
+
{
|
|
41169
|
+
style: {
|
|
41170
|
+
fontSize: 10,
|
|
41171
|
+
color: GUI_THEME.dim,
|
|
41172
|
+
whiteSpace: "nowrap",
|
|
41173
|
+
overflow: "hidden",
|
|
41174
|
+
// Fixed, not min, so the changing label never shifts the
|
|
41175
|
+
// buttons around it.
|
|
41176
|
+
width: 88,
|
|
41177
|
+
flexShrink: 0,
|
|
41178
|
+
textAlign: "center"
|
|
41179
|
+
},
|
|
41180
|
+
children: formatPeriodLabel(scope, offset, periodRange)
|
|
41181
|
+
}
|
|
41182
|
+
),
|
|
41183
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
41184
|
+
"button",
|
|
41185
|
+
{
|
|
41186
|
+
title: "Later",
|
|
41187
|
+
disabled: offset === 0,
|
|
41188
|
+
onClick: () => onChangeOffset(Math.max(0, offset - 1)),
|
|
41189
|
+
style: {
|
|
41190
|
+
...navButtonStyle,
|
|
41191
|
+
opacity: offset === 0 ? 0.35 : 1,
|
|
41192
|
+
cursor: offset === 0 ? "default" : "pointer"
|
|
41193
|
+
},
|
|
41194
|
+
children: "\u25B6"
|
|
41195
|
+
}
|
|
41196
|
+
)
|
|
41197
|
+
] }),
|
|
41198
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { style: { display: "flex", gap: 2 }, children: SCOPES.map((option) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
41199
|
+
"button",
|
|
41200
|
+
{
|
|
41201
|
+
onClick: () => onChangeScope(option),
|
|
41202
|
+
style: toggleButtonStyle(scope === option),
|
|
41203
|
+
children: scopeButtonLabel(option)
|
|
40650
41204
|
},
|
|
40651
|
-
|
|
40652
|
-
}
|
|
40653
|
-
)
|
|
40654
|
-
|
|
40655
|
-
|
|
40656
|
-
|
|
40657
|
-
|
|
40658
|
-
|
|
40659
|
-
|
|
40660
|
-
|
|
40661
|
-
|
|
40662
|
-
|
|
40663
|
-
|
|
40664
|
-
|
|
40665
|
-
|
|
40666
|
-
|
|
40667
|
-
|
|
40668
|
-
|
|
40669
|
-
|
|
40670
|
-
|
|
40671
|
-
|
|
40672
|
-
|
|
40673
|
-
|
|
40674
|
-
|
|
40675
|
-
|
|
40676
|
-
|
|
40677
|
-
|
|
40678
|
-
|
|
40679
|
-
|
|
40680
|
-
|
|
40681
|
-
|
|
40682
|
-
|
|
40683
|
-
|
|
40684
|
-
|
|
40685
|
-
|
|
40686
|
-
|
|
40687
|
-
|
|
40688
|
-
|
|
40689
|
-
|
|
40690
|
-
|
|
40691
|
-
|
|
40692
|
-
|
|
40693
|
-
|
|
40694
|
-
|
|
40695
|
-
|
|
40696
|
-
|
|
40697
|
-
|
|
40698
|
-
|
|
40699
|
-
|
|
40700
|
-
|
|
40701
|
-
|
|
40702
|
-
|
|
40703
|
-
|
|
40704
|
-
|
|
40705
|
-
|
|
40706
|
-
|
|
40707
|
-
|
|
40708
|
-
checked: allBoards,
|
|
40709
|
-
activeColor: GUI_THEME.accent,
|
|
40710
|
-
onChange: onChangeAllBoards
|
|
40711
|
-
}
|
|
40712
|
-
)
|
|
40713
|
-
] }),
|
|
40714
|
-
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
40715
|
-
"div",
|
|
40716
|
-
{
|
|
40717
|
-
style: {
|
|
40718
|
-
display: "flex",
|
|
40719
|
-
justifyContent: "flex-end",
|
|
40720
|
-
alignItems: "center",
|
|
40721
|
-
// Fixed, not min, so swapping between "Now" and "Return to live"
|
|
40722
|
-
// never resizes the controls row.
|
|
40723
|
-
width: 100,
|
|
40724
|
-
flexShrink: 0
|
|
40725
|
-
},
|
|
40726
|
-
children: isScrubbing ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
41205
|
+
option
|
|
41206
|
+
)) })
|
|
41207
|
+
] }),
|
|
41208
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { style: { display: "flex", gap: 2 }, children: [
|
|
41209
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
41210
|
+
"button",
|
|
41211
|
+
{
|
|
41212
|
+
title: "Volume \u2014 how much happened, per equal-width period, with no empty gaps for quiet stretches",
|
|
41213
|
+
"aria-label": "Volume",
|
|
41214
|
+
"aria-pressed": layoutMode === "even",
|
|
41215
|
+
onClick: () => onChangeLayoutMode("even"),
|
|
41216
|
+
style: iconToggleButtonStyle(layoutMode === "even"),
|
|
41217
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(IconBars, { size: 13 })
|
|
41218
|
+
}
|
|
41219
|
+
),
|
|
41220
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
41221
|
+
"button",
|
|
41222
|
+
{
|
|
41223
|
+
title: "Events \u2014 individual events by exact moment, x is elapsed time and y is time of day",
|
|
41224
|
+
"aria-label": "Events",
|
|
41225
|
+
"aria-pressed": layoutMode === "real",
|
|
41226
|
+
onClick: () => onChangeLayoutMode("real"),
|
|
41227
|
+
style: iconToggleButtonStyle(layoutMode === "real"),
|
|
41228
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(IconScatter, { size: 13 })
|
|
41229
|
+
}
|
|
41230
|
+
)
|
|
41231
|
+
] }),
|
|
41232
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { style: { display: "flex", gap: 12, alignItems: "center" }, children: [
|
|
41233
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
41234
|
+
Checkbox,
|
|
41235
|
+
{
|
|
41236
|
+
label: "Code",
|
|
41237
|
+
checked: showCommits,
|
|
41238
|
+
activeColor: GUI_THEME.green,
|
|
41239
|
+
onChange: onChangeShowCommits
|
|
41240
|
+
}
|
|
41241
|
+
),
|
|
41242
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
41243
|
+
BoardSeriesGroup,
|
|
41244
|
+
{
|
|
41245
|
+
showIssues,
|
|
41246
|
+
view: boardView,
|
|
41247
|
+
identities,
|
|
41248
|
+
hiddenIds: hiddenIdentityIds,
|
|
41249
|
+
expanded: categoriesExpanded,
|
|
41250
|
+
identitiesExpanded,
|
|
41251
|
+
filtered: categoriesFiltered,
|
|
41252
|
+
onChangeShowIssues,
|
|
41253
|
+
onChangeView: onChangeBoardView,
|
|
41254
|
+
onToggleIdentity,
|
|
41255
|
+
onOnlyIdentity,
|
|
41256
|
+
onToggleExpanded: onToggleCategoriesExpanded,
|
|
41257
|
+
onSetIdentitiesExpanded
|
|
41258
|
+
}
|
|
41259
|
+
)
|
|
41260
|
+
] }),
|
|
41261
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
40727
41262
|
"button",
|
|
40728
41263
|
{
|
|
40729
41264
|
onClick: onReturnToLive,
|
|
41265
|
+
disabled: !isScrubbing,
|
|
41266
|
+
title: isScrubbing ? "Leave history and follow the board again" : void 0,
|
|
40730
41267
|
style: {
|
|
40731
41268
|
background: "transparent",
|
|
40732
|
-
border: `1px solid ${GUI_THEME.accent}`,
|
|
40733
|
-
color: GUI_THEME.accent,
|
|
41269
|
+
border: `1px solid ${isScrubbing ? GUI_THEME.accent : GUI_THEME.transparent}`,
|
|
41270
|
+
color: isScrubbing ? GUI_THEME.accent : GUI_THEME.dim,
|
|
40734
41271
|
borderRadius: 6,
|
|
40735
|
-
|
|
41272
|
+
fontFamily: "inherit",
|
|
41273
|
+
width: 60,
|
|
41274
|
+
display: "inline-flex",
|
|
41275
|
+
alignItems: "center",
|
|
41276
|
+
justifyContent: isScrubbing ? "center" : "flex-end",
|
|
41277
|
+
fontSize: 10,
|
|
40736
41278
|
padding: "2px 8px",
|
|
40737
|
-
cursor: "pointer",
|
|
40738
|
-
whiteSpace: "nowrap"
|
|
40739
|
-
|
|
40740
|
-
children: "Return to live"
|
|
40741
|
-
}
|
|
40742
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
40743
|
-
"span",
|
|
40744
|
-
{
|
|
40745
|
-
style: {
|
|
40746
|
-
fontSize: 11,
|
|
40747
|
-
color: GUI_THEME.dim,
|
|
40748
|
-
overflow: "hidden",
|
|
40749
|
-
textAlign: "right",
|
|
40750
|
-
whiteSpace: "nowrap"
|
|
41279
|
+
cursor: isScrubbing ? "pointer" : "default",
|
|
41280
|
+
whiteSpace: "nowrap",
|
|
41281
|
+
flexShrink: 0
|
|
40751
41282
|
},
|
|
40752
|
-
children:
|
|
41283
|
+
children: isScrubbing ? "Resume" : "Now"
|
|
40753
41284
|
}
|
|
40754
41285
|
)
|
|
40755
|
-
|
|
40756
|
-
|
|
40757
|
-
|
|
41286
|
+
]
|
|
41287
|
+
}
|
|
41288
|
+
);
|
|
40758
41289
|
var ScrubberHeader = ({
|
|
40759
41290
|
collapsed,
|
|
40760
|
-
onToggleCollapsed
|
|
40761
|
-
|
|
40762
|
-
}) => /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
|
|
41291
|
+
onToggleCollapsed
|
|
41292
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
40763
41293
|
"div",
|
|
40764
41294
|
{
|
|
40765
41295
|
style: {
|
|
@@ -40769,34 +41299,26 @@ var ScrubberHeader = ({
|
|
|
40769
41299
|
fontSize: 11,
|
|
40770
41300
|
whiteSpace: "nowrap"
|
|
40771
41301
|
},
|
|
40772
|
-
children:
|
|
40773
|
-
|
|
40774
|
-
|
|
40775
|
-
|
|
40776
|
-
|
|
40777
|
-
|
|
40778
|
-
|
|
40779
|
-
|
|
40780
|
-
|
|
40781
|
-
|
|
40782
|
-
|
|
40783
|
-
|
|
40784
|
-
|
|
40785
|
-
|
|
40786
|
-
|
|
40787
|
-
|
|
40788
|
-
|
|
40789
|
-
|
|
40790
|
-
|
|
40791
|
-
|
|
40792
|
-
]
|
|
40793
|
-
}
|
|
40794
|
-
),
|
|
40795
|
-
scrubbingAsOf !== null && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
|
|
40796
|
-
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { style: { color: GUI_THEME.accent, fontWeight: 700 }, children: "Read-only" }),
|
|
40797
|
-
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { style: { color: GUI_THEME.primary }, children: scrubbingAsOf })
|
|
40798
|
-
] })
|
|
40799
|
-
]
|
|
41302
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
41303
|
+
"button",
|
|
41304
|
+
{
|
|
41305
|
+
onClick: onToggleCollapsed,
|
|
41306
|
+
title: collapsed ? "Show time travel" : "Hide time travel",
|
|
41307
|
+
"aria-label": collapsed ? "Show time travel" : "Hide time travel",
|
|
41308
|
+
"aria-expanded": !collapsed,
|
|
41309
|
+
style: {
|
|
41310
|
+
background: GUI_THEME.panel2,
|
|
41311
|
+
border: `1px solid ${GUI_THEME.line}`,
|
|
41312
|
+
borderRadius: 6,
|
|
41313
|
+
color: GUI_THEME.secondary,
|
|
41314
|
+
padding: "3px 7px",
|
|
41315
|
+
cursor: "pointer",
|
|
41316
|
+
display: "inline-flex",
|
|
41317
|
+
alignItems: "center"
|
|
41318
|
+
},
|
|
41319
|
+
children: collapsed ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(IconChevronRight, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(IconChevronDown, { size: 14 })
|
|
41320
|
+
}
|
|
41321
|
+
)
|
|
40800
41322
|
}
|
|
40801
41323
|
);
|
|
40802
41324
|
var SegmentHighlight = ({
|
|
@@ -40804,7 +41326,7 @@ var SegmentHighlight = ({
|
|
|
40804
41326
|
fractionForTime
|
|
40805
41327
|
}) => {
|
|
40806
41328
|
const left = fractionForTime(segment.start);
|
|
40807
|
-
return /* @__PURE__ */ (0,
|
|
41329
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
40808
41330
|
"div",
|
|
40809
41331
|
{
|
|
40810
41332
|
style: {
|
|
@@ -40836,7 +41358,7 @@ var SegmentHighlight = ({
|
|
|
40836
41358
|
var TrackBaseline = ({
|
|
40837
41359
|
color: color2,
|
|
40838
41360
|
anchor
|
|
40839
|
-
}) => /* @__PURE__ */ (0,
|
|
41361
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
40840
41362
|
"div",
|
|
40841
41363
|
{
|
|
40842
41364
|
style: {
|
|
@@ -40852,11 +41374,11 @@ var TrackBaseline = ({
|
|
|
40852
41374
|
}
|
|
40853
41375
|
}
|
|
40854
41376
|
);
|
|
40855
|
-
var HourAxisLabels = () => /* @__PURE__ */ (0,
|
|
41377
|
+
var HourAxisLabels = () => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_jsx_runtime32.Fragment, { children: [
|
|
40856
41378
|
["00:00", { top: EVENTS_MODE_VERTICAL_PADDING }],
|
|
40857
41379
|
["12:00", { top: "50%", transform: "translateY(-50%)" }],
|
|
40858
41380
|
["24:00", { bottom: EVENTS_MODE_VERTICAL_PADDING }]
|
|
40859
|
-
].map(([label, position3]) => /* @__PURE__ */ (0,
|
|
41381
|
+
].map(([label, position3]) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
40860
41382
|
"span",
|
|
40861
41383
|
{
|
|
40862
41384
|
style: {
|
|
@@ -40874,14 +41396,18 @@ var HourAxisLabels = () => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_
|
|
|
40874
41396
|
var SeriesLayer = ({
|
|
40875
41397
|
animate,
|
|
40876
41398
|
children
|
|
40877
|
-
}) => /* @__PURE__ */ (0,
|
|
41399
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
40878
41400
|
"div",
|
|
40879
41401
|
{
|
|
40880
41402
|
style: {
|
|
40881
41403
|
position: "absolute",
|
|
40882
41404
|
inset: 0,
|
|
40883
41405
|
pointerEvents: "none",
|
|
40884
|
-
animation: animate ? FADE_IN_ANIMATION : void 0
|
|
41406
|
+
animation: animate ? FADE_IN_ANIMATION : void 0,
|
|
41407
|
+
// Walls this subtree off from the needle and highlight moving above
|
|
41408
|
+
// it: without containment every frame of a drag re-lays-out the
|
|
41409
|
+
// thousands of dots inside, and the drag stutters.
|
|
41410
|
+
contain: "layout paint"
|
|
40885
41411
|
},
|
|
40886
41412
|
children
|
|
40887
41413
|
}
|
|
@@ -40904,8 +41430,8 @@ var VolumeBars = ({
|
|
|
40904
41430
|
const timeout = setTimeout(() => setFresh(false), BAR_ENTRANCE_TOTAL_MS);
|
|
40905
41431
|
return () => clearTimeout(timeout);
|
|
40906
41432
|
}, []);
|
|
40907
|
-
return /* @__PURE__ */ (0,
|
|
40908
|
-
highlightedIndex !== null && /* @__PURE__ */ (0,
|
|
41433
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
|
|
41434
|
+
highlightedIndex !== null && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
40909
41435
|
"div",
|
|
40910
41436
|
{
|
|
40911
41437
|
style: {
|
|
@@ -40921,7 +41447,7 @@ var VolumeBars = ({
|
|
|
40921
41447
|
}
|
|
40922
41448
|
}
|
|
40923
41449
|
),
|
|
40924
|
-
bars.map(({ index: index2, intensity }) => /* @__PURE__ */ (0,
|
|
41450
|
+
bars.map(({ index: index2, intensity }) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
40925
41451
|
"div",
|
|
40926
41452
|
{
|
|
40927
41453
|
style: {
|
|
@@ -40942,55 +41468,14 @@ var VolumeBars = ({
|
|
|
40942
41468
|
))
|
|
40943
41469
|
] });
|
|
40944
41470
|
};
|
|
40945
|
-
var ScatterDot = ({
|
|
40946
|
-
fraction,
|
|
40947
|
-
hourFraction,
|
|
40948
|
-
size,
|
|
40949
|
-
color: color2,
|
|
40950
|
-
opacity,
|
|
40951
|
-
zIndex,
|
|
40952
|
-
title,
|
|
40953
|
-
animation,
|
|
40954
|
-
interactive = true,
|
|
40955
|
-
onMouseEnter,
|
|
40956
|
-
onMouseLeave,
|
|
40957
|
-
onClick
|
|
40958
|
-
}) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
40959
|
-
"div",
|
|
40960
|
-
{
|
|
40961
|
-
title,
|
|
40962
|
-
onPointerDown: onClick && ((event) => event.stopPropagation()),
|
|
40963
|
-
onClick: onClick && ((event) => {
|
|
40964
|
-
event.stopPropagation();
|
|
40965
|
-
onClick();
|
|
40966
|
-
}),
|
|
40967
|
-
onMouseEnter,
|
|
40968
|
-
onMouseLeave,
|
|
40969
|
-
style: {
|
|
40970
|
-
position: "absolute",
|
|
40971
|
-
left: `${fraction * 100}%`,
|
|
40972
|
-
top: EVENTS_MODE_VERTICAL_PADDING + hourFraction * EVENTS_SCATTER_HEIGHT,
|
|
40973
|
-
width: size,
|
|
40974
|
-
height: size,
|
|
40975
|
-
borderRadius: "50%",
|
|
40976
|
-
background: color2,
|
|
40977
|
-
opacity,
|
|
40978
|
-
zIndex,
|
|
40979
|
-
transform: `translate(${-size / 2}px, -50%)`,
|
|
40980
|
-
animation,
|
|
40981
|
-
pointerEvents: interactive ? "auto" : "none",
|
|
40982
|
-
cursor: onClick ? "pointer" : void 0
|
|
40983
|
-
}
|
|
40984
|
-
}
|
|
40985
|
-
);
|
|
40986
41471
|
var ScrubberNeedle = ({ fraction }) => {
|
|
40987
41472
|
const [hovered, setHovered] = (0, import_react14.useState)(false);
|
|
40988
41473
|
const hover = {
|
|
40989
41474
|
onMouseEnter: () => setHovered(true),
|
|
40990
41475
|
onMouseLeave: () => setHovered(false)
|
|
40991
41476
|
};
|
|
40992
|
-
return /* @__PURE__ */ (0,
|
|
40993
|
-
/* @__PURE__ */ (0,
|
|
41477
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
|
|
41478
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
40994
41479
|
"div",
|
|
40995
41480
|
{
|
|
40996
41481
|
...hover,
|
|
@@ -41010,7 +41495,7 @@ var ScrubberNeedle = ({ fraction }) => {
|
|
|
41010
41495
|
}
|
|
41011
41496
|
}
|
|
41012
41497
|
),
|
|
41013
|
-
/* @__PURE__ */ (0,
|
|
41498
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
41014
41499
|
"div",
|
|
41015
41500
|
{
|
|
41016
41501
|
...hover,
|
|
@@ -41040,7 +41525,7 @@ var ScrubberHoverHint = ({
|
|
|
41040
41525
|
fraction,
|
|
41041
41526
|
trackWidthPx,
|
|
41042
41527
|
empty: empty3 = false
|
|
41043
|
-
}) => /* @__PURE__ */ (0,
|
|
41528
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
41044
41529
|
"div",
|
|
41045
41530
|
{
|
|
41046
41531
|
style: {
|
|
@@ -41072,8 +41557,8 @@ var ScrubberHoverHint = ({
|
|
|
41072
41557
|
zIndex: 5
|
|
41073
41558
|
},
|
|
41074
41559
|
children: [
|
|
41075
|
-
segmentLabel && /* @__PURE__ */ (0,
|
|
41076
|
-
/* @__PURE__ */ (0,
|
|
41560
|
+
segmentLabel && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { style: { fontSize: 10, color: GUI_THEME.dim }, children: segmentLabel }),
|
|
41561
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
41077
41562
|
"div",
|
|
41078
41563
|
{
|
|
41079
41564
|
style: {
|
|
@@ -41086,7 +41571,7 @@ var ScrubberHoverHint = ({
|
|
|
41086
41571
|
children: label
|
|
41087
41572
|
}
|
|
41088
41573
|
),
|
|
41089
|
-
rows.map((row, index2) => /* @__PURE__ */ (0,
|
|
41574
|
+
rows.map((row, index2) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
41090
41575
|
"div",
|
|
41091
41576
|
{
|
|
41092
41577
|
style: {
|
|
@@ -41102,19 +41587,183 @@ var ScrubberHoverHint = ({
|
|
|
41102
41587
|
]
|
|
41103
41588
|
}
|
|
41104
41589
|
);
|
|
41590
|
+
var HIT_RADIUS = 7;
|
|
41591
|
+
var pointAt = (layers, x, y, width) => {
|
|
41592
|
+
let best = null;
|
|
41593
|
+
let bestDistance = HIT_RADIUS * HIT_RADIUS;
|
|
41594
|
+
for (const layer of layers) {
|
|
41595
|
+
if (layer.leaving) continue;
|
|
41596
|
+
for (const point4 of layer.points) {
|
|
41597
|
+
const dx = point4.fraction * width - x;
|
|
41598
|
+
const dy = EVENTS_MODE_VERTICAL_PADDING + point4.hourFraction * EVENTS_SCATTER_HEIGHT - y;
|
|
41599
|
+
const distance = dx * dx + dy * dy;
|
|
41600
|
+
if (distance <= bestDistance) {
|
|
41601
|
+
bestDistance = distance;
|
|
41602
|
+
best = point4;
|
|
41603
|
+
}
|
|
41604
|
+
}
|
|
41605
|
+
}
|
|
41606
|
+
return best;
|
|
41607
|
+
};
|
|
41608
|
+
var ScatterCanvas = ({
|
|
41609
|
+
layers,
|
|
41610
|
+
animate,
|
|
41611
|
+
onPointEnter,
|
|
41612
|
+
onPointLeave,
|
|
41613
|
+
onInspectCommit
|
|
41614
|
+
}) => {
|
|
41615
|
+
const canvasRef = (0, import_react14.useRef)(null);
|
|
41616
|
+
const sizeRef = (0, import_react14.useRef)({ width: 0, height: 0 });
|
|
41617
|
+
const layersRef = (0, import_react14.useRef)(layers);
|
|
41618
|
+
layersRef.current = layers;
|
|
41619
|
+
const phasesRef = (0, import_react14.useRef)(/* @__PURE__ */ new Map());
|
|
41620
|
+
const frameRef = (0, import_react14.useRef)(null);
|
|
41621
|
+
const hoveredRef = (0, import_react14.useRef)(null);
|
|
41622
|
+
const [entrancePlaying, setEntrancePlaying] = (0, import_react14.useState)(false);
|
|
41623
|
+
const paint = (0, import_react14.useCallback)((now) => {
|
|
41624
|
+
const canvas = canvasRef.current;
|
|
41625
|
+
const context = canvas?.getContext("2d");
|
|
41626
|
+
if (!canvas || !context) return false;
|
|
41627
|
+
const { width, height } = sizeRef.current;
|
|
41628
|
+
context.clearRect(0, 0, width, height);
|
|
41629
|
+
let running = false;
|
|
41630
|
+
for (const layer of layersRef.current) {
|
|
41631
|
+
const phase = phasesRef.current.get(layer.id);
|
|
41632
|
+
const elapsed = phase ? now - phase.startedAt : null;
|
|
41633
|
+
const done = elapsed === null || elapsed >= DOT_EXIT_TOTAL_MS;
|
|
41634
|
+
if (phase && !done) running = true;
|
|
41635
|
+
if (phase?.mode === "out" && done) continue;
|
|
41636
|
+
for (const point4 of layer.points) {
|
|
41637
|
+
const scale = phase === null || phase === void 0 || done ? 1 : phase.mode === "in" ? dotEntranceScale(point4.key, elapsed) : dotExitScale(point4.key, elapsed);
|
|
41638
|
+
if (scale <= 0) continue;
|
|
41639
|
+
context.globalAlpha = point4.opacity;
|
|
41640
|
+
context.fillStyle = point4.color;
|
|
41641
|
+
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
|
+
);
|
|
41649
|
+
context.fill();
|
|
41650
|
+
}
|
|
41651
|
+
}
|
|
41652
|
+
context.globalAlpha = 1;
|
|
41653
|
+
return running;
|
|
41654
|
+
}, []);
|
|
41655
|
+
const run = (0, import_react14.useCallback)(() => {
|
|
41656
|
+
if (frameRef.current !== null) return;
|
|
41657
|
+
const step = () => {
|
|
41658
|
+
frameRef.current = null;
|
|
41659
|
+
const running = paint(performance.now());
|
|
41660
|
+
if (running) frameRef.current = requestAnimationFrame(step);
|
|
41661
|
+
else setEntrancePlaying(false);
|
|
41662
|
+
};
|
|
41663
|
+
frameRef.current = requestAnimationFrame(step);
|
|
41664
|
+
}, [paint]);
|
|
41665
|
+
(0, import_react14.useEffect)(() => {
|
|
41666
|
+
const canvas = canvasRef.current;
|
|
41667
|
+
const parent = canvas?.parentElement;
|
|
41668
|
+
if (!canvas || !parent) return;
|
|
41669
|
+
const resize = () => {
|
|
41670
|
+
const ratio = window.devicePixelRatio || 1;
|
|
41671
|
+
const { width, height } = parent.getBoundingClientRect();
|
|
41672
|
+
sizeRef.current = { width, height };
|
|
41673
|
+
canvas.width = Math.round(width * ratio);
|
|
41674
|
+
canvas.height = Math.round(height * ratio);
|
|
41675
|
+
canvas.style.width = `${width}px`;
|
|
41676
|
+
canvas.style.height = `${height}px`;
|
|
41677
|
+
canvas.getContext("2d")?.setTransform(ratio, 0, 0, ratio, 0, 0);
|
|
41678
|
+
paint(performance.now());
|
|
41679
|
+
};
|
|
41680
|
+
resize();
|
|
41681
|
+
const observer = new ResizeObserver(resize);
|
|
41682
|
+
observer.observe(parent);
|
|
41683
|
+
return () => observer.disconnect();
|
|
41684
|
+
}, [paint]);
|
|
41685
|
+
const signature = layers.map((layer) => `${layer.id}:${layer.generation}:${layer.leaving}`).join("|");
|
|
41686
|
+
(0, import_react14.useEffect)(() => {
|
|
41687
|
+
const seen = /* @__PURE__ */ new Set();
|
|
41688
|
+
for (const layer of layers) {
|
|
41689
|
+
seen.add(layer.id);
|
|
41690
|
+
const key = `${layer.generation}:${layer.leaving}`;
|
|
41691
|
+
const marker = `${layer.id}@${key}`;
|
|
41692
|
+
const current = phasesRef.current.get(layer.id);
|
|
41693
|
+
if (current?.marker === marker)
|
|
41694
|
+
continue;
|
|
41695
|
+
if (!animate) {
|
|
41696
|
+
phasesRef.current.delete(layer.id);
|
|
41697
|
+
continue;
|
|
41698
|
+
}
|
|
41699
|
+
phasesRef.current.set(layer.id, {
|
|
41700
|
+
mode: layer.leaving ? "out" : "in",
|
|
41701
|
+
startedAt: performance.now(),
|
|
41702
|
+
marker
|
|
41703
|
+
});
|
|
41704
|
+
if (!layer.leaving) setEntrancePlaying(true);
|
|
41705
|
+
}
|
|
41706
|
+
for (const id of [...phasesRef.current.keys()])
|
|
41707
|
+
if (!seen.has(id)) phasesRef.current.delete(id);
|
|
41708
|
+
if (animate) run();
|
|
41709
|
+
else paint(performance.now());
|
|
41710
|
+
}, [signature, animate, run, paint]);
|
|
41711
|
+
(0, import_react14.useEffect)(() => {
|
|
41712
|
+
if (frameRef.current === null) paint(performance.now());
|
|
41713
|
+
}, [layers, paint]);
|
|
41714
|
+
(0, import_react14.useEffect)(
|
|
41715
|
+
() => () => {
|
|
41716
|
+
if (frameRef.current !== null) cancelAnimationFrame(frameRef.current);
|
|
41717
|
+
},
|
|
41718
|
+
[]
|
|
41719
|
+
);
|
|
41720
|
+
const hitTest = (event) => {
|
|
41721
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
41722
|
+
return pointAt(
|
|
41723
|
+
layersRef.current,
|
|
41724
|
+
event.clientX - rect.left,
|
|
41725
|
+
event.clientY - rect.top,
|
|
41726
|
+
rect.width
|
|
41727
|
+
);
|
|
41728
|
+
};
|
|
41729
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
41730
|
+
"canvas",
|
|
41731
|
+
{
|
|
41732
|
+
ref: canvasRef,
|
|
41733
|
+
"data-entrance": entrancePlaying ? "playing" : "done",
|
|
41734
|
+
style: { position: "absolute", inset: 0 },
|
|
41735
|
+
onMouseMove: (event) => {
|
|
41736
|
+
const point4 = hitTest(event);
|
|
41737
|
+
if (point4?.key === hoveredRef.current) return;
|
|
41738
|
+
hoveredRef.current = point4?.key ?? null;
|
|
41739
|
+
if (point4) onPointEnter(point4);
|
|
41740
|
+
else onPointLeave();
|
|
41741
|
+
},
|
|
41742
|
+
onMouseLeave: () => {
|
|
41743
|
+
hoveredRef.current = null;
|
|
41744
|
+
onPointLeave();
|
|
41745
|
+
},
|
|
41746
|
+
onPointerDown: (event) => {
|
|
41747
|
+
if (hitTest(event)?.commitSha) event.stopPropagation();
|
|
41748
|
+
},
|
|
41749
|
+
onClick: (event) => {
|
|
41750
|
+
const sha = hitTest(event)?.commitSha;
|
|
41751
|
+
if (sha) onInspectCommit(sha);
|
|
41752
|
+
}
|
|
41753
|
+
}
|
|
41754
|
+
);
|
|
41755
|
+
};
|
|
41105
41756
|
|
|
41106
41757
|
// source/gui/client/components/ScrubberLayout.tsx
|
|
41107
|
-
var
|
|
41108
|
-
var dotAnimation = (key, animate, leaving) => !animate ? void 0 : leaving ? dotExitAnimation(key) : dotAppearAnimation(key);
|
|
41758
|
+
var import_jsx_runtime33 = __toESM(require_jsx_runtime(), 1);
|
|
41109
41759
|
var ScrubberLayout = ({
|
|
41110
41760
|
collapsed,
|
|
41111
41761
|
onToggleCollapsed,
|
|
41112
|
-
scrubbingAsOf,
|
|
41113
41762
|
controls,
|
|
41114
41763
|
chart
|
|
41115
41764
|
}) => {
|
|
41116
41765
|
const { axis, layoutMode, animate, windowKey, on } = chart;
|
|
41117
|
-
return /* @__PURE__ */ (0,
|
|
41766
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
41118
41767
|
Panel,
|
|
41119
41768
|
{
|
|
41120
41769
|
as: "div",
|
|
@@ -41131,8 +41780,8 @@ var ScrubberLayout = ({
|
|
|
41131
41780
|
overflow: "visible"
|
|
41132
41781
|
},
|
|
41133
41782
|
children: [
|
|
41134
|
-
/* @__PURE__ */ (0,
|
|
41135
|
-
/* @__PURE__ */ (0,
|
|
41783
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("style", { children: SCRUBBER_KEYFRAMES }),
|
|
41784
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
41136
41785
|
"div",
|
|
41137
41786
|
{
|
|
41138
41787
|
style: {
|
|
@@ -41141,27 +41790,26 @@ var ScrubberLayout = ({
|
|
|
41141
41790
|
gap: collapsed ? 0 : 8
|
|
41142
41791
|
},
|
|
41143
41792
|
children: [
|
|
41144
|
-
/* @__PURE__ */ (0,
|
|
41793
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
41145
41794
|
"div",
|
|
41146
41795
|
{
|
|
41147
41796
|
style: {
|
|
41148
41797
|
display: "flex",
|
|
41149
41798
|
alignItems: "center",
|
|
41150
41799
|
justifyContent: "space-between",
|
|
41151
|
-
//
|
|
41152
|
-
//
|
|
41800
|
+
// Holds the row's height when collapsing takes the controls out
|
|
41801
|
+
// of it.
|
|
41153
41802
|
minHeight: 22
|
|
41154
41803
|
},
|
|
41155
41804
|
children: [
|
|
41156
|
-
/* @__PURE__ */ (0,
|
|
41805
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
41157
41806
|
ScrubberHeader,
|
|
41158
41807
|
{
|
|
41159
41808
|
collapsed,
|
|
41160
|
-
onToggleCollapsed
|
|
41161
|
-
scrubbingAsOf
|
|
41809
|
+
onToggleCollapsed
|
|
41162
41810
|
}
|
|
41163
41811
|
),
|
|
41164
|
-
!collapsed && /* @__PURE__ */ (0,
|
|
41812
|
+
!collapsed && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ScrubberControls, { ...controls })
|
|
41165
41813
|
]
|
|
41166
41814
|
}
|
|
41167
41815
|
),
|
|
@@ -41169,7 +41817,7 @@ var ScrubberLayout = ({
|
|
|
41169
41817
|
// spanning them and the gap between. Pointer handlers belong here
|
|
41170
41818
|
// rather than on either chart, so a drag or hover anywhere across
|
|
41171
41819
|
// the pair — the gap included — counts as one timeline.
|
|
41172
|
-
/* @__PURE__ */ (0,
|
|
41820
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
41173
41821
|
"div",
|
|
41174
41822
|
{
|
|
41175
41823
|
onPointerDown: on.onPointerDown,
|
|
@@ -41186,14 +41834,14 @@ var ScrubberLayout = ({
|
|
|
41186
41834
|
cursor: "pointer"
|
|
41187
41835
|
},
|
|
41188
41836
|
children: [
|
|
41189
|
-
chart.hoveredSegment && /* @__PURE__ */ (0,
|
|
41837
|
+
chart.hoveredSegment && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
41190
41838
|
SegmentHighlight,
|
|
41191
41839
|
{
|
|
41192
41840
|
segment: chart.hoveredSegment,
|
|
41193
41841
|
fractionForTime: axis.fractionForTime
|
|
41194
41842
|
}
|
|
41195
41843
|
),
|
|
41196
|
-
/* @__PURE__ */ (0,
|
|
41844
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
41197
41845
|
"div",
|
|
41198
41846
|
{
|
|
41199
41847
|
ref: chart.trackRef,
|
|
@@ -41208,15 +41856,15 @@ var ScrubberLayout = ({
|
|
|
41208
41856
|
alignItems: "center"
|
|
41209
41857
|
},
|
|
41210
41858
|
children: [
|
|
41211
|
-
/* @__PURE__ */ (0,
|
|
41859
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
41212
41860
|
TrackBaseline,
|
|
41213
41861
|
{
|
|
41214
|
-
color:
|
|
41862
|
+
color: chart.issueSeriesColor,
|
|
41215
41863
|
anchor: layoutMode === "even" ? "bottom" : "centre"
|
|
41216
41864
|
}
|
|
41217
41865
|
),
|
|
41218
|
-
layoutMode === "real" && /* @__PURE__ */ (0,
|
|
41219
|
-
chart.showIssues && layoutMode === "even" && /* @__PURE__ */ (0,
|
|
41866
|
+
layoutMode === "real" && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(HourAxisLabels, {}),
|
|
41867
|
+
chart.showIssues && layoutMode === "even" && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(SeriesLayer, { animate, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
41220
41868
|
VolumeBars,
|
|
41221
41869
|
{
|
|
41222
41870
|
bars: chart.issueBars,
|
|
@@ -41224,75 +41872,25 @@ var ScrubberLayout = ({
|
|
|
41224
41872
|
firstBar: chart.issueBarRange[0],
|
|
41225
41873
|
lastBar: chart.issueBarRange[1],
|
|
41226
41874
|
highlightedIndex: chart.hoveredBucketIndex,
|
|
41227
|
-
color:
|
|
41875
|
+
color: chart.issueSeriesColor,
|
|
41228
41876
|
direction: "up",
|
|
41229
41877
|
animate
|
|
41230
41878
|
}
|
|
41231
41879
|
) }, `issues-${windowKey}`),
|
|
41232
|
-
|
|
41233
|
-
|
|
41234
|
-
{
|
|
41235
|
-
animate: animate && !chart.issueScatter.leaving,
|
|
41236
|
-
children: chart.eventBuckets.map((bucket) => {
|
|
41237
|
-
const intensity = bucket.count / chart.maxEventCount;
|
|
41238
|
-
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
41239
|
-
ScatterDot,
|
|
41240
|
-
{
|
|
41241
|
-
fraction: axis.fractionForTime(bucket.t),
|
|
41242
|
-
hourFraction: hourFractionForTime(bucket.t),
|
|
41243
|
-
size: 3 + intensity * 6,
|
|
41244
|
-
color: GUI_THEME.accent,
|
|
41245
|
-
opacity: 0.3 + intensity * 0.5,
|
|
41246
|
-
zIndex: 2,
|
|
41247
|
-
title: `${bucket.count} change${bucket.count === 1 ? "" : "s"}, ${formatDateTime(new Date(bucket.t))}`,
|
|
41248
|
-
animation: dotAnimation(
|
|
41249
|
-
String(bucket.t),
|
|
41250
|
-
animate,
|
|
41251
|
-
chart.issueScatter.leaving
|
|
41252
|
-
),
|
|
41253
|
-
interactive: !chart.issueScatter.leaving,
|
|
41254
|
-
onMouseEnter: () => on.onIssueDotEnter(bucket),
|
|
41255
|
-
onMouseLeave: on.onIssueDotLeave
|
|
41256
|
-
},
|
|
41257
|
-
bucket.t
|
|
41258
|
-
);
|
|
41259
|
-
})
|
|
41260
|
-
},
|
|
41261
|
-
`issues-${windowKey}`
|
|
41262
|
-
),
|
|
41263
|
-
chart.commitScatter.mounted && layoutMode === "real" && chart.commits.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
41264
|
-
SeriesLayer,
|
|
41880
|
+
layoutMode === "real" && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
41881
|
+
ScatterCanvas,
|
|
41265
41882
|
{
|
|
41266
|
-
|
|
41267
|
-
|
|
41268
|
-
|
|
41269
|
-
|
|
41270
|
-
|
|
41271
|
-
|
|
41272
|
-
size: 4,
|
|
41273
|
-
color: GUI_THEME.green,
|
|
41274
|
-
opacity: chart.hoveredCommitSha === commit.sha ? 1 : 0.55,
|
|
41275
|
-
zIndex: 1,
|
|
41276
|
-
title: `${formatDateTime(new Date(commit.time))} \u2014 ${commit.subject} \u2014 ${commit.author} (${commit.linesChanged.toLocaleString()} lines)`,
|
|
41277
|
-
animation: dotAnimation(
|
|
41278
|
-
commit.sha,
|
|
41279
|
-
animate,
|
|
41280
|
-
chart.commitScatter.leaving
|
|
41281
|
-
),
|
|
41282
|
-
interactive: !chart.commitScatter.leaving,
|
|
41283
|
-
onClick: () => on.onInspectCommit(commit.sha),
|
|
41284
|
-
onMouseEnter: () => on.onCommitDotEnter(commit),
|
|
41285
|
-
onMouseLeave: on.onCommitDotLeave
|
|
41286
|
-
},
|
|
41287
|
-
commit.sha
|
|
41288
|
-
))
|
|
41289
|
-
},
|
|
41290
|
-
`commits-${windowKey}`
|
|
41883
|
+
layers: chart.scatterLayers,
|
|
41884
|
+
animate,
|
|
41885
|
+
onPointEnter: on.onScatterPointEnter,
|
|
41886
|
+
onPointLeave: on.onScatterPointLeave,
|
|
41887
|
+
onInspectCommit: on.onInspectCommit
|
|
41888
|
+
}
|
|
41291
41889
|
)
|
|
41292
41890
|
]
|
|
41293
41891
|
}
|
|
41294
41892
|
),
|
|
41295
|
-
chart.showCommits && layoutMode === "even" && chart.commits.length > 0 && /* @__PURE__ */ (0,
|
|
41893
|
+
chart.showCommits && layoutMode === "even" && chart.commits.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
41296
41894
|
"div",
|
|
41297
41895
|
{
|
|
41298
41896
|
onMouseEnter: on.onCommitTrackMouseEnter,
|
|
@@ -41305,8 +41903,8 @@ var ScrubberLayout = ({
|
|
|
41305
41903
|
animation: animate ? FADE_IN_ANIMATION : void 0
|
|
41306
41904
|
},
|
|
41307
41905
|
children: [
|
|
41308
|
-
/* @__PURE__ */ (0,
|
|
41309
|
-
/* @__PURE__ */ (0,
|
|
41906
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(TrackBaseline, { color: GUI_THEME.green, anchor: "top" }),
|
|
41907
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
41310
41908
|
VolumeBars,
|
|
41311
41909
|
{
|
|
41312
41910
|
bars: chart.commitBars,
|
|
@@ -41323,17 +41921,17 @@ var ScrubberLayout = ({
|
|
|
41323
41921
|
},
|
|
41324
41922
|
`commits-${windowKey}`
|
|
41325
41923
|
),
|
|
41326
|
-
/* @__PURE__ */ (0,
|
|
41327
|
-
chart.boardHint && /* @__PURE__ */ (0,
|
|
41924
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ScrubberNeedle, { fraction: chart.thumbFraction }),
|
|
41925
|
+
chart.boardHint && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
41328
41926
|
ScrubberHoverHint,
|
|
41329
41927
|
{
|
|
41330
41928
|
...chart.boardHint,
|
|
41331
41929
|
segmentLabel: chart.hoveredSegment?.label,
|
|
41332
|
-
stripeColor:
|
|
41930
|
+
stripeColor: chart.issueSeriesColor,
|
|
41333
41931
|
trackWidthPx: chart.trackWidthPx
|
|
41334
41932
|
}
|
|
41335
41933
|
),
|
|
41336
|
-
chart.commitHint && /* @__PURE__ */ (0,
|
|
41934
|
+
chart.commitHint && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
41337
41935
|
ScrubberHoverHint,
|
|
41338
41936
|
{
|
|
41339
41937
|
...chart.commitHint,
|
|
@@ -41354,13 +41952,31 @@ var ScrubberLayout = ({
|
|
|
41354
41952
|
};
|
|
41355
41953
|
|
|
41356
41954
|
// source/gui/client/components/TimeScrubber.tsx
|
|
41357
|
-
var
|
|
41955
|
+
var import_jsx_runtime34 = __toESM(require_jsx_runtime(), 1);
|
|
41358
41956
|
var SCRUB_THROTTLE_MS = 120;
|
|
41957
|
+
var boardEventRow = (count) => `${count} board event${count === 1 ? "" : "s"}`;
|
|
41359
41958
|
var COLLAPSED_STORAGE_KEY = "epiq.timeScrubber.collapsed";
|
|
41360
41959
|
var SCOPE_STORAGE_KEY = "epiq.timeScrubber.scope";
|
|
41361
41960
|
var SHOW_ISSUES_STORAGE_KEY = "epiq.timeScrubber.showIssues";
|
|
41362
41961
|
var SHOW_COMMITS_STORAGE_KEY = "epiq.timeScrubber.showCommits";
|
|
41363
41962
|
var ALL_BOARDS_STORAGE_KEY = "epiq.timeScrubber.allBoards";
|
|
41963
|
+
var BOARD_VIEW_STORAGE_KEY = "epiq.timeScrubber.boardView";
|
|
41964
|
+
var HIDDEN_IDENTITIES_STORAGE_KEY = "epiq.timeScrubber.hiddenIdentities";
|
|
41965
|
+
var CATEGORIES_EXPANDED_STORAGE_KEY = "epiq.timeScrubber.categoriesExpanded";
|
|
41966
|
+
var IDENTITIES_EXPANDED_STORAGE_KEY = "epiq.timeScrubber.identitiesExpanded";
|
|
41967
|
+
var readStoredBoardView = () => {
|
|
41968
|
+
const stored = localStorage.getItem(BOARD_VIEW_STORAGE_KEY);
|
|
41969
|
+
return isBoardView(stored) ? stored : "all";
|
|
41970
|
+
};
|
|
41971
|
+
var readStoredHiddenIds = () => {
|
|
41972
|
+
try {
|
|
41973
|
+
const stored = localStorage.getItem(HIDDEN_IDENTITIES_STORAGE_KEY);
|
|
41974
|
+
const parsed = stored ? JSON.parse(stored) : [];
|
|
41975
|
+
return new Set(Array.isArray(parsed) ? parsed.map(String) : []);
|
|
41976
|
+
} catch {
|
|
41977
|
+
return /* @__PURE__ */ new Set();
|
|
41978
|
+
}
|
|
41979
|
+
};
|
|
41364
41980
|
var readStoredScope = () => {
|
|
41365
41981
|
const stored = localStorage.getItem(SCOPE_STORAGE_KEY);
|
|
41366
41982
|
return isScope(stored) ? stored : "all";
|
|
@@ -41375,7 +41991,8 @@ var TimeScrubber = ({
|
|
|
41375
41991
|
onRequestHistory,
|
|
41376
41992
|
boardId,
|
|
41377
41993
|
connected,
|
|
41378
|
-
onInspectCommit
|
|
41994
|
+
onInspectCommit,
|
|
41995
|
+
onBoardFilterChange
|
|
41379
41996
|
}) => {
|
|
41380
41997
|
const animate = !usePrefersReducedMotion();
|
|
41381
41998
|
const trackRef = (0, import_react15.useRef)(null);
|
|
@@ -41396,6 +42013,16 @@ var TimeScrubber = ({
|
|
|
41396
42013
|
SHOW_COMMITS_STORAGE_KEY,
|
|
41397
42014
|
true
|
|
41398
42015
|
);
|
|
42016
|
+
const [boardView, setBoardView] = (0, import_react15.useState)(readStoredBoardView);
|
|
42017
|
+
const [hiddenIdentityIds, setHiddenIdentityIds] = (0, import_react15.useState)(readStoredHiddenIds);
|
|
42018
|
+
const [categoriesExpanded, setCategoriesExpanded] = usePersistedFlag(
|
|
42019
|
+
CATEGORIES_EXPANDED_STORAGE_KEY,
|
|
42020
|
+
false
|
|
42021
|
+
);
|
|
42022
|
+
const [identitiesExpanded, setIdentitiesExpanded] = usePersistedFlag(
|
|
42023
|
+
IDENTITIES_EXPANDED_STORAGE_KEY,
|
|
42024
|
+
false
|
|
42025
|
+
);
|
|
41399
42026
|
const [allBoards, setAllBoards] = usePersistedFlag(
|
|
41400
42027
|
ALL_BOARDS_STORAGE_KEY,
|
|
41401
42028
|
false
|
|
@@ -41425,19 +42052,137 @@ var TimeScrubber = ({
|
|
|
41425
42052
|
armEntrance();
|
|
41426
42053
|
setOffset(nextOffset);
|
|
41427
42054
|
};
|
|
42055
|
+
const changeBoardView = (next) => {
|
|
42056
|
+
setBoardView(next);
|
|
42057
|
+
localStorage.setItem(BOARD_VIEW_STORAGE_KEY, next);
|
|
42058
|
+
};
|
|
42059
|
+
const isolateIdentity = (id) => {
|
|
42060
|
+
const others = identities.filter((identity) => identity.id !== id).map((identity) => identity.id);
|
|
42061
|
+
setHiddenIdentityIds((previous3) => {
|
|
42062
|
+
const isolated = !previous3.has(id) && others.length === previous3.size && others.every((other) => previous3.has(other));
|
|
42063
|
+
const hidden = isolated ? /* @__PURE__ */ new Set() : new Set(others);
|
|
42064
|
+
localStorage.setItem(
|
|
42065
|
+
HIDDEN_IDENTITIES_STORAGE_KEY,
|
|
42066
|
+
JSON.stringify([...hidden])
|
|
42067
|
+
);
|
|
42068
|
+
return hidden;
|
|
42069
|
+
});
|
|
42070
|
+
};
|
|
42071
|
+
const toggleIdentity = (id, next) => {
|
|
42072
|
+
setHiddenIdentityIds((previous3) => {
|
|
42073
|
+
const hidden = new Set(previous3);
|
|
42074
|
+
if (next) {
|
|
42075
|
+
hidden.delete(id);
|
|
42076
|
+
} else {
|
|
42077
|
+
hidden.add(id);
|
|
42078
|
+
}
|
|
42079
|
+
localStorage.setItem(
|
|
42080
|
+
HIDDEN_IDENTITIES_STORAGE_KEY,
|
|
42081
|
+
JSON.stringify([...hidden])
|
|
42082
|
+
);
|
|
42083
|
+
return hidden;
|
|
42084
|
+
});
|
|
42085
|
+
};
|
|
41428
42086
|
const changeAllBoards = (next) => {
|
|
41429
42087
|
armEntrance();
|
|
41430
42088
|
setAllBoards(next);
|
|
41431
42089
|
};
|
|
41432
|
-
const
|
|
41433
|
-
|
|
41434
|
-
const
|
|
41435
|
-
|
|
41436
|
-
|
|
41437
|
-
|
|
41438
|
-
|
|
41439
|
-
|
|
42090
|
+
const steadyBoardId = (0, import_react15.useRef)(boardId);
|
|
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)(
|
|
42097
|
+
() => JSON.stringify([boardView, [...hiddenIdentityIds].sort()]),
|
|
42098
|
+
[boardView, hiddenIdentityIds]
|
|
42099
|
+
);
|
|
42100
|
+
const entrance = (0, import_react15.useRef)(0);
|
|
42101
|
+
const armed = (0, import_react15.useRef)(true);
|
|
42102
|
+
const seenHistoryId = (0, import_react15.useRef)(historyId);
|
|
42103
|
+
const armEntrance = () => {
|
|
42104
|
+
armed.current = true;
|
|
42105
|
+
};
|
|
42106
|
+
const shownRef = (0, import_react15.useRef)({ timeline, commits });
|
|
42107
|
+
const heldKey = (0, import_react15.useRef)(null);
|
|
42108
|
+
const heldHistoryId = (0, import_react15.useRef)(null);
|
|
42109
|
+
const awaiting = (0, import_react15.useRef)(true);
|
|
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;
|
|
42116
|
+
shownRef.current = { timeline, commits };
|
|
42117
|
+
awaiting.current = false;
|
|
42118
|
+
}
|
|
42119
|
+
if (seenHistoryId.current !== historyId) {
|
|
42120
|
+
seenHistoryId.current = historyId;
|
|
42121
|
+
if (armed.current) {
|
|
42122
|
+
armed.current = false;
|
|
42123
|
+
entrance.current += 1;
|
|
42124
|
+
}
|
|
42125
|
+
}
|
|
42126
|
+
const shown = shownRef.current;
|
|
42127
|
+
const axis = (0, import_react15.useMemo)(() => buildAxis(shown.timeline, shown.commits), [shown]);
|
|
42128
|
+
const categoriesFiltered = (timeline?.events.length ?? 0) > 0;
|
|
42129
|
+
const identities = (0, import_react15.useMemo)(
|
|
42130
|
+
() => listIdentities(shown.timeline, boardView),
|
|
42131
|
+
[shown, boardView]
|
|
42132
|
+
);
|
|
42133
|
+
const soleIdentity = (0, import_react15.useMemo)(
|
|
42134
|
+
() => soleVisibleIdentity(identities, hiddenIdentityIds),
|
|
42135
|
+
[identities, hiddenIdentityIds]
|
|
41440
42136
|
);
|
|
42137
|
+
const issueCounts = bucketIssueCounts(
|
|
42138
|
+
axis,
|
|
42139
|
+
shown.timeline,
|
|
42140
|
+
boardView,
|
|
42141
|
+
hiddenIdentityIds
|
|
42142
|
+
);
|
|
42143
|
+
const commitStats = bucketCommitStats(axis, shown.commits);
|
|
42144
|
+
const liveEventDots = (0, import_react15.useMemo)(
|
|
42145
|
+
() => buildEventDots(shown.timeline, boardView, hiddenIdentityIds),
|
|
42146
|
+
[shown, boardView, hiddenIdentityIds]
|
|
42147
|
+
);
|
|
42148
|
+
const dragging = dragFraction !== null;
|
|
42149
|
+
const commitPoints = (0, import_react15.useMemo)(
|
|
42150
|
+
() => shown.commits.map((commit) => ({
|
|
42151
|
+
key: commit.sha,
|
|
42152
|
+
t: commit.time,
|
|
42153
|
+
fraction: axis.fractionForTime(commit.time),
|
|
42154
|
+
hourFraction: hourFractionForTime(commit.time),
|
|
42155
|
+
radius: 2,
|
|
42156
|
+
color: GUI_THEME.green,
|
|
42157
|
+
opacity: 0.55,
|
|
42158
|
+
// The hint labels the moment itself, so this is the rest of it.
|
|
42159
|
+
title: `${commit.subject} \u2014 ${commit.author} (${commit.linesChanged.toLocaleString()} lines)`,
|
|
42160
|
+
commitSha: commit.sha
|
|
42161
|
+
})),
|
|
42162
|
+
[shown.commits, axis]
|
|
42163
|
+
);
|
|
42164
|
+
const issuePoints = (0, import_react15.useMemo)(
|
|
42165
|
+
() => liveEventDots.map((dot) => ({
|
|
42166
|
+
key: dot.key,
|
|
42167
|
+
t: dot.t,
|
|
42168
|
+
fraction: axis.fractionForTime(dot.t),
|
|
42169
|
+
hourFraction: hourFractionForTime(dot.t),
|
|
42170
|
+
radius: dot.size / 2,
|
|
42171
|
+
color: dot.color,
|
|
42172
|
+
opacity: dot.opacity,
|
|
42173
|
+
title: dotDetail(dot),
|
|
42174
|
+
commitSha: null
|
|
42175
|
+
})),
|
|
42176
|
+
[liveEventDots, axis]
|
|
42177
|
+
);
|
|
42178
|
+
const boardFilter = (0, import_react15.useMemo)(
|
|
42179
|
+
() => buildBoardFilter(boardView, identities, hiddenIdentityIds),
|
|
42180
|
+
[boardView, identities, hiddenIdentityIds]
|
|
42181
|
+
);
|
|
42182
|
+
(0, import_react15.useEffect)(() => {
|
|
42183
|
+
onBoardFilterChange(boardFilter);
|
|
42184
|
+
}, [boardFilter]);
|
|
42185
|
+
const maxIssueBucketCount = maxOf(issueCounts, 1);
|
|
41441
42186
|
const maxCommitCount = maxOf(
|
|
41442
42187
|
Array.from(commitStats.values(), (stats) => stats.count),
|
|
41443
42188
|
1
|
|
@@ -41449,21 +42194,34 @@ var TimeScrubber = ({
|
|
|
41449
42194
|
index: index2,
|
|
41450
42195
|
intensity: stats.count / maxCommitCount
|
|
41451
42196
|
}));
|
|
41452
|
-
const
|
|
41453
|
-
const armed = (0, import_react15.useRef)(true);
|
|
41454
|
-
const seenHistoryId = (0, import_react15.useRef)(historyId);
|
|
41455
|
-
const armEntrance = () => {
|
|
41456
|
-
armed.current = true;
|
|
41457
|
-
};
|
|
41458
|
-
(0, import_react15.useEffect)(armEntrance, [boardId]);
|
|
42197
|
+
const armedBoardId = (0, import_react15.useRef)(boardId);
|
|
41459
42198
|
(0, import_react15.useEffect)(() => {
|
|
41460
|
-
if (
|
|
41461
|
-
|
|
41462
|
-
|
|
41463
|
-
|
|
41464
|
-
|
|
41465
|
-
|
|
41466
|
-
|
|
42199
|
+
if (boardId === null || boardId === armedBoardId.current) return;
|
|
42200
|
+
armedBoardId.current = boardId;
|
|
42201
|
+
armEntrance();
|
|
42202
|
+
}, [boardId]);
|
|
42203
|
+
const windowKey = `${layoutMode}-${entrance.current}-${filterKey}`;
|
|
42204
|
+
const scatterLayers = (0, import_react15.useMemo)(
|
|
42205
|
+
() => [
|
|
42206
|
+
...commitScatter.mounted ? [
|
|
42207
|
+
{
|
|
42208
|
+
id: "commits",
|
|
42209
|
+
points: commitPoints,
|
|
42210
|
+
generation: windowKey,
|
|
42211
|
+
leaving: commitScatter.leaving
|
|
42212
|
+
}
|
|
42213
|
+
] : [],
|
|
42214
|
+
...issueScatter.mounted ? [
|
|
42215
|
+
{
|
|
42216
|
+
id: "issues",
|
|
42217
|
+
points: issuePoints,
|
|
42218
|
+
generation: windowKey,
|
|
42219
|
+
leaving: issueScatter.leaving
|
|
42220
|
+
}
|
|
42221
|
+
] : []
|
|
42222
|
+
],
|
|
42223
|
+
[commitPoints, issuePoints, commitScatter, issueScatter, windowKey]
|
|
42224
|
+
);
|
|
41467
42225
|
const confirmedFraction = timeTravel.mode === "scrub" && timeTravel.asOfTime !== null ? axis.fractionForTime(timeTravel.asOfTime) : 1;
|
|
41468
42226
|
const fractionFromClientX = (clientX) => {
|
|
41469
42227
|
const track = trackRef.current;
|
|
@@ -41493,7 +42251,30 @@ var TimeScrubber = ({
|
|
|
41493
42251
|
);
|
|
41494
42252
|
const bucketTimeAt = (index2) => index2 !== null && index2 < axis.bucketCount ? axis.bucketTimeAt(index2) : void 0;
|
|
41495
42253
|
const centreFraction = (index2) => (index2 + 0.5) / axis.bucketCount;
|
|
41496
|
-
const
|
|
42254
|
+
const onScatterPointEnter = (0, import_react15.useCallback)(
|
|
42255
|
+
(point4) => {
|
|
42256
|
+
if (point4.commitSha) {
|
|
42257
|
+
const commit = shown.commits.find((c) => c.sha === point4.commitSha);
|
|
42258
|
+
if (commit) {
|
|
42259
|
+
setHoveredCommit({ commit, fraction: point4.fraction });
|
|
42260
|
+
setHoveredEvent(null);
|
|
42261
|
+
}
|
|
42262
|
+
return;
|
|
42263
|
+
}
|
|
42264
|
+
setHoveredCommit(null);
|
|
42265
|
+
setHoveredEvent({
|
|
42266
|
+
label: formatDateTime(new Date(point4.t)),
|
|
42267
|
+
detail: point4.title,
|
|
42268
|
+
t: point4.t,
|
|
42269
|
+
fraction: point4.fraction
|
|
42270
|
+
});
|
|
42271
|
+
},
|
|
42272
|
+
[shown.commits]
|
|
42273
|
+
);
|
|
42274
|
+
const onScatterPointLeave = (0, import_react15.useCallback)(() => {
|
|
42275
|
+
setHoveredEvent(null);
|
|
42276
|
+
setHoveredCommit(null);
|
|
42277
|
+
}, []);
|
|
41497
42278
|
const hoveredBucketTime = bucketTimeAt(hoveredBucketIndex);
|
|
41498
42279
|
const hoveredBucketCount = hoveredBucketIndex !== null ? issueCounts[hoveredBucketIndex] : void 0;
|
|
41499
42280
|
const boardHint = layoutMode === "even" ? hoveredBucketTime !== void 0 && hoveredBucketCount !== void 0 ? {
|
|
@@ -41506,7 +42287,7 @@ var TimeScrubber = ({
|
|
|
41506
42287
|
empty: hoveredBucketCount === 0
|
|
41507
42288
|
} : null : hoveredEvent ? {
|
|
41508
42289
|
label: hoveredEvent.label,
|
|
41509
|
-
rows: [
|
|
42290
|
+
rows: [hoveredEvent.detail],
|
|
41510
42291
|
fraction: hoveredEvent.fraction
|
|
41511
42292
|
} : null;
|
|
41512
42293
|
const hoveredCommitStats = hoveredCommitBucketIndex !== null ? commitStats.get(hoveredCommitBucketIndex) : void 0;
|
|
@@ -41535,12 +42316,11 @@ var TimeScrubber = ({
|
|
|
41535
42316
|
hoveredEvent?.t ?? hoveredCommit?.commit.time ?? (pointerFraction !== null ? axis.fractionToTime(pointerFraction) : void 0)
|
|
41536
42317
|
)) ?? null;
|
|
41537
42318
|
const segmentUnit = chooseSegmentUnit(axis.span);
|
|
41538
|
-
return /* @__PURE__ */ (0,
|
|
42319
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
41539
42320
|
ScrubberLayout,
|
|
41540
42321
|
{
|
|
41541
42322
|
collapsed,
|
|
41542
42323
|
onToggleCollapsed: () => setCollapsed(!collapsed),
|
|
41543
|
-
scrubbingAsOf: timeTravel.mode === "scrub" ? timeTravel.asOfTime ? formatDateTime(new Date(timeTravel.asOfTime)) : "" : null,
|
|
41544
42324
|
controls: {
|
|
41545
42325
|
scope,
|
|
41546
42326
|
offset,
|
|
@@ -41549,15 +42329,25 @@ var TimeScrubber = ({
|
|
|
41549
42329
|
showIssues,
|
|
41550
42330
|
showCommits,
|
|
41551
42331
|
allBoards,
|
|
41552
|
-
isScrubbing: timeTravel.mode === "scrub",
|
|
41553
|
-
nowLabel: scope === "all" || offset === 0 ? "Now" : formatDateTime(new Date(axis.latest)),
|
|
41554
42332
|
onChangeScope: changeScope,
|
|
41555
42333
|
onChangeOffset: changeOffset,
|
|
41556
42334
|
onChangeLayoutMode: setLayoutMode,
|
|
41557
42335
|
onChangeShowIssues: setShowIssues,
|
|
41558
42336
|
onChangeShowCommits: setShowCommits,
|
|
41559
42337
|
onChangeAllBoards: changeAllBoards,
|
|
41560
|
-
|
|
42338
|
+
boardView,
|
|
42339
|
+
identities,
|
|
42340
|
+
hiddenIdentityIds,
|
|
42341
|
+
categoriesExpanded,
|
|
42342
|
+
identitiesExpanded,
|
|
42343
|
+
categoriesFiltered,
|
|
42344
|
+
isScrubbing: timeTravel.mode === "scrub",
|
|
42345
|
+
onReturnToLive,
|
|
42346
|
+
onChangeBoardView: changeBoardView,
|
|
42347
|
+
onToggleIdentity: toggleIdentity,
|
|
42348
|
+
onOnlyIdentity: isolateIdentity,
|
|
42349
|
+
onToggleCategoriesExpanded: () => setCategoriesExpanded(!categoriesExpanded),
|
|
42350
|
+
onSetIdentitiesExpanded: setIdentitiesExpanded
|
|
41561
42351
|
},
|
|
41562
42352
|
chart: {
|
|
41563
42353
|
trackRef,
|
|
@@ -41573,9 +42363,12 @@ var TimeScrubber = ({
|
|
|
41573
42363
|
issueBarRange: populatedRange(issueBars),
|
|
41574
42364
|
commitBars,
|
|
41575
42365
|
commitBarRange: populatedRange(commitBars),
|
|
41576
|
-
|
|
41577
|
-
|
|
41578
|
-
|
|
42366
|
+
scatterLayers,
|
|
42367
|
+
issueSeriesColor: soleIdentity?.color ?? boardViewColor(boardView),
|
|
42368
|
+
dragging,
|
|
42369
|
+
// Exits still need their animation, so this only silences a series
|
|
42370
|
+
// that has finished arriving.
|
|
42371
|
+
commits: shown.commits,
|
|
41579
42372
|
hoveredCommitSha: hoveredCommit?.commit.sha ?? null,
|
|
41580
42373
|
hoveredBucketIndex,
|
|
41581
42374
|
hoveredCommitBucketIndex,
|
|
@@ -41615,18 +42408,8 @@ var TimeScrubber = ({
|
|
|
41615
42408
|
setHoveredCommitBucketIndex(bucketIndexFromEvent(event));
|
|
41616
42409
|
},
|
|
41617
42410
|
onCommitTrackMouseLeave: () => setHoveredCommitBucketIndex(null),
|
|
41618
|
-
|
|
41619
|
-
|
|
41620
|
-
count: bucket.count,
|
|
41621
|
-
t: bucket.t,
|
|
41622
|
-
fraction: axis.fractionForTime(bucket.t)
|
|
41623
|
-
}),
|
|
41624
|
-
onIssueDotLeave: () => setHoveredEvent(null),
|
|
41625
|
-
onCommitDotEnter: (commit) => setHoveredCommit({
|
|
41626
|
-
commit,
|
|
41627
|
-
fraction: axis.fractionForTime(commit.time)
|
|
41628
|
-
}),
|
|
41629
|
-
onCommitDotLeave: () => setHoveredCommit(null),
|
|
42411
|
+
onScatterPointEnter,
|
|
42412
|
+
onScatterPointLeave,
|
|
41630
42413
|
onInspectCommit
|
|
41631
42414
|
}
|
|
41632
42415
|
}
|
|
@@ -41717,8 +42500,8 @@ var nodeRef = (id) => id.slice(-NODE_REF_LENGTH).toUpperCase();
|
|
|
41717
42500
|
// source/gui/client/lib/gui-state-helper.tsx
|
|
41718
42501
|
var getResultValue = (payload) => {
|
|
41719
42502
|
if (!payload) return void 0;
|
|
41720
|
-
if (typeof payload === "object" && payload !== null && "value" in payload
|
|
41721
|
-
return payload.value;
|
|
42503
|
+
if (typeof payload === "object" && payload !== null && "value" in payload) {
|
|
42504
|
+
return payload.value ?? void 0;
|
|
41722
42505
|
}
|
|
41723
42506
|
if (typeof payload === "object" && payload !== null && "content" in payload && payload.content?.[0]?.text) {
|
|
41724
42507
|
return JSON.parse(payload.content[0].text).value;
|
|
@@ -41910,8 +42693,9 @@ var blobToBase64 = (blob) => new Promise((resolve, reject) => {
|
|
|
41910
42693
|
});
|
|
41911
42694
|
|
|
41912
42695
|
// source/gui/client/App.tsx
|
|
41913
|
-
var
|
|
41914
|
-
var
|
|
42696
|
+
var import_jsx_runtime35 = __toESM(require_jsx_runtime(), 1);
|
|
42697
|
+
var EMPTY_COMMENTS = {};
|
|
42698
|
+
var DropIndicator = () => /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
41915
42699
|
"div",
|
|
41916
42700
|
{
|
|
41917
42701
|
style: {
|
|
@@ -41955,7 +42739,7 @@ var App = () => {
|
|
|
41955
42739
|
const [mutationGate] = (0, import_react16.useState)(createMutationGate);
|
|
41956
42740
|
const selectedTab = searchParams.get("tab") === "comments" ? "comments" : "overview";
|
|
41957
42741
|
const navigate = useNavigate();
|
|
41958
|
-
const selectedBoard = (state && boardId ? findBoard(state, boardId) : null) ?? state?.boards[0] ?? null;
|
|
42742
|
+
const selectedBoard = (state && boardId ? findBoard(state, boardId) : null) ?? state?.boards?.[0] ?? null;
|
|
41959
42743
|
const selectedBoardId = selectedBoard?.id ?? null;
|
|
41960
42744
|
const selectedBoardIdRef = (0, import_react16.useRef)(selectedBoardId);
|
|
41961
42745
|
selectedBoardIdRef.current = selectedBoardId;
|
|
@@ -41980,9 +42764,38 @@ var App = () => {
|
|
|
41980
42764
|
if (!boardSlug) return;
|
|
41981
42765
|
void navigate(`/board/${boardSlug}`);
|
|
41982
42766
|
};
|
|
41983
|
-
const commentsByIssueId = state?.commentsByIssueId ??
|
|
42767
|
+
const commentsByIssueId = state?.commentsByIssueId ?? EMPTY_COMMENTS;
|
|
42768
|
+
const [issueDetail, setIssueDetail] = (0, import_react16.useState)(null);
|
|
42769
|
+
const [boardFilter, setBoardFilter] = (0, import_react16.useState)(null);
|
|
42770
|
+
const { visibleSwimlanes, hiddenIssueCount } = (0, import_react16.useMemo)(() => {
|
|
42771
|
+
const swimlanes = selectedBoard?.swimlanes ?? [];
|
|
42772
|
+
if (!boardFilter) return { visibleSwimlanes: swimlanes, hiddenIssueCount: 0 };
|
|
42773
|
+
let hidden = 0;
|
|
42774
|
+
const visible = swimlanes.map((swimlane) => {
|
|
42775
|
+
const issues = swimlane.issues.filter(
|
|
42776
|
+
(issue) => issuePassesBoardFilter(
|
|
42777
|
+
issue,
|
|
42778
|
+
(commentsByIssueId[issue.id] ?? []).map((comment) => comment.author.id),
|
|
42779
|
+
boardFilter
|
|
42780
|
+
)
|
|
42781
|
+
);
|
|
42782
|
+
hidden += swimlane.issues.length - issues.length;
|
|
42783
|
+
return { ...swimlane, issues };
|
|
42784
|
+
});
|
|
42785
|
+
return { visibleSwimlanes: visible, hiddenIssueCount: hidden };
|
|
42786
|
+
}, [selectedBoard, boardFilter, commentsByIssueId]);
|
|
41984
42787
|
const attachmentsByIssueId = state?.attachmentsByIssueId ?? {};
|
|
41985
42788
|
const [attachmentUploadStatus, setAttachmentUploadStatus] = (0, import_react16.useState)({ state: "idle" });
|
|
42789
|
+
(0, import_react16.useEffect)(() => {
|
|
42790
|
+
if (!selectedIssue) {
|
|
42791
|
+
setIssueDetail(null);
|
|
42792
|
+
return;
|
|
42793
|
+
}
|
|
42794
|
+
sendSocketJson(socketRef.current, {
|
|
42795
|
+
type: "issue:get",
|
|
42796
|
+
payload: { issueId: selectedIssue.id }
|
|
42797
|
+
});
|
|
42798
|
+
}, [selectedIssue?.id, state]);
|
|
41986
42799
|
const requestState = () => {
|
|
41987
42800
|
sendSocketJson(socketRef.current, { type: "state:get" });
|
|
41988
42801
|
};
|
|
@@ -42010,6 +42823,10 @@ var App = () => {
|
|
|
42010
42823
|
const nextState = getResultValue(message.payload);
|
|
42011
42824
|
if (nextState) setState(nextState);
|
|
42012
42825
|
}
|
|
42826
|
+
if (message.type === "issue") {
|
|
42827
|
+
const detail = getResultValue(message.payload);
|
|
42828
|
+
if (detail) setIssueDetail(detail);
|
|
42829
|
+
}
|
|
42013
42830
|
if (message.type === "issue:created") {
|
|
42014
42831
|
const created = getResultValue(message.payload);
|
|
42015
42832
|
if (created && boardId) {
|
|
@@ -42070,8 +42887,9 @@ var App = () => {
|
|
|
42070
42887
|
};
|
|
42071
42888
|
}, [boardId, navigate]);
|
|
42072
42889
|
(0, import_react16.useEffect)(() => {
|
|
42073
|
-
|
|
42074
|
-
|
|
42890
|
+
const first = state?.boards?.[0];
|
|
42891
|
+
if (!boardId && first) {
|
|
42892
|
+
void navigate(`/board/${first.ref}`, { replace: true });
|
|
42075
42893
|
}
|
|
42076
42894
|
}, [boardId, state, navigate]);
|
|
42077
42895
|
(0, import_react16.useEffect)(() => {
|
|
@@ -42421,7 +43239,7 @@ var App = () => {
|
|
|
42421
43239
|
});
|
|
42422
43240
|
send("issue:comment:delete", { commentId });
|
|
42423
43241
|
};
|
|
42424
|
-
return /* @__PURE__ */ (0,
|
|
43242
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
|
|
42425
43243
|
"div",
|
|
42426
43244
|
{
|
|
42427
43245
|
style: {
|
|
@@ -42433,30 +43251,38 @@ var App = () => {
|
|
|
42433
43251
|
flexDirection: "column"
|
|
42434
43252
|
},
|
|
42435
43253
|
children: [
|
|
42436
|
-
/* @__PURE__ */ (0,
|
|
42437
|
-
commitInspectError && /* @__PURE__ */ (0,
|
|
43254
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(GlobalScrollbarStyles, {}),
|
|
43255
|
+
commitInspectError && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
42438
43256
|
ErrorToast,
|
|
42439
43257
|
{
|
|
42440
43258
|
message: `Couldn't open commit diff: ${commitInspectError}`,
|
|
42441
43259
|
onDismiss: () => setCommitInspectError(null)
|
|
42442
43260
|
}
|
|
42443
43261
|
),
|
|
42444
|
-
removeError && /* @__PURE__ */ (0,
|
|
43262
|
+
removeError && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
42445
43263
|
ErrorToast,
|
|
42446
43264
|
{
|
|
42447
43265
|
message: removeError,
|
|
42448
43266
|
onDismiss: () => setRemoveError(null)
|
|
42449
43267
|
}
|
|
42450
43268
|
),
|
|
42451
|
-
actionError && /* @__PURE__ */ (0,
|
|
43269
|
+
actionError && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
42452
43270
|
ErrorToast,
|
|
42453
43271
|
{
|
|
42454
43272
|
message: actionError,
|
|
42455
43273
|
onDismiss: () => setActionError(null)
|
|
42456
43274
|
}
|
|
42457
43275
|
),
|
|
42458
|
-
/* @__PURE__ */ (0,
|
|
42459
|
-
|
|
43276
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
43277
|
+
Header,
|
|
43278
|
+
{
|
|
43279
|
+
state,
|
|
43280
|
+
connected,
|
|
43281
|
+
scrubbing: state?.timeTravel?.mode === "scrub",
|
|
43282
|
+
syncStatus
|
|
43283
|
+
}
|
|
43284
|
+
),
|
|
43285
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
42460
43286
|
TimeScrubber,
|
|
42461
43287
|
{
|
|
42462
43288
|
timeline: history.timeline,
|
|
@@ -42468,10 +43294,11 @@ var App = () => {
|
|
|
42468
43294
|
onInspectCommit: inspectCommit,
|
|
42469
43295
|
timeTravel: state?.timeTravel ?? { mode: "live", asOfTime: null },
|
|
42470
43296
|
onScrub: scrubToTime,
|
|
42471
|
-
onReturnToLive: returnToLive
|
|
43297
|
+
onReturnToLive: returnToLive,
|
|
43298
|
+
onBoardFilterChange: setBoardFilter
|
|
42472
43299
|
}
|
|
42473
43300
|
),
|
|
42474
|
-
/* @__PURE__ */ (0,
|
|
43301
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
|
|
42475
43302
|
"div",
|
|
42476
43303
|
{
|
|
42477
43304
|
style: {
|
|
@@ -42480,7 +43307,7 @@ var App = () => {
|
|
|
42480
43307
|
overflow: "hidden"
|
|
42481
43308
|
},
|
|
42482
43309
|
children: [
|
|
42483
|
-
/* @__PURE__ */ (0,
|
|
43310
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
|
|
42484
43311
|
"main",
|
|
42485
43312
|
{
|
|
42486
43313
|
onClick: clearPicked,
|
|
@@ -42495,24 +43322,35 @@ var App = () => {
|
|
|
42495
43322
|
overflow: "hidden"
|
|
42496
43323
|
},
|
|
42497
43324
|
children: [
|
|
42498
|
-
/* @__PURE__ */ (0,
|
|
42499
|
-
|
|
43325
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
43326
|
+
"div",
|
|
42500
43327
|
{
|
|
42501
|
-
|
|
42502
|
-
|
|
42503
|
-
|
|
42504
|
-
|
|
42505
|
-
|
|
42506
|
-
}
|
|
42507
|
-
|
|
42508
|
-
|
|
42509
|
-
|
|
42510
|
-
|
|
42511
|
-
|
|
42512
|
-
|
|
43328
|
+
style: {
|
|
43329
|
+
padding: "20px 10px",
|
|
43330
|
+
display: "flex",
|
|
43331
|
+
alignItems: "center",
|
|
43332
|
+
gap: 10
|
|
43333
|
+
},
|
|
43334
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
43335
|
+
Dropdown,
|
|
43336
|
+
{
|
|
43337
|
+
testId: "board-switcher",
|
|
43338
|
+
label: "Board:",
|
|
43339
|
+
value: selectedBoard ? {
|
|
43340
|
+
id: selectedBoard.id,
|
|
43341
|
+
label: selectedBoard.title
|
|
43342
|
+
} : null,
|
|
43343
|
+
items: state?.boards.map((board) => ({
|
|
43344
|
+
id: board.id,
|
|
43345
|
+
label: board.title
|
|
43346
|
+
})) ?? [],
|
|
43347
|
+
placeholder: "Loading...",
|
|
43348
|
+
onSelect: selectBoard
|
|
43349
|
+
}
|
|
43350
|
+
)
|
|
42513
43351
|
}
|
|
42514
|
-
)
|
|
42515
|
-
/* @__PURE__ */ (0,
|
|
43352
|
+
),
|
|
43353
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
|
|
42516
43354
|
"div",
|
|
42517
43355
|
{
|
|
42518
43356
|
style: {
|
|
@@ -42524,7 +43362,7 @@ var App = () => {
|
|
|
42524
43362
|
overflowY: "hidden"
|
|
42525
43363
|
},
|
|
42526
43364
|
children: [
|
|
42527
|
-
|
|
43365
|
+
visibleSwimlanes.map((swimlane) => /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
42528
43366
|
SwimlaneColumn,
|
|
42529
43367
|
{
|
|
42530
43368
|
swimlane,
|
|
@@ -42552,14 +43390,14 @@ var App = () => {
|
|
|
42552
43390
|
},
|
|
42553
43391
|
swimlane.id
|
|
42554
43392
|
)),
|
|
42555
|
-
!(selectedIssue && state?.user) && /* @__PURE__ */ (0,
|
|
43393
|
+
!(selectedIssue && state?.user) && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { style: { width: ASIDE_WIDTH, flexShrink: 0 } })
|
|
42556
43394
|
]
|
|
42557
43395
|
}
|
|
42558
43396
|
)
|
|
42559
43397
|
]
|
|
42560
43398
|
}
|
|
42561
43399
|
),
|
|
42562
|
-
pickedIssues.length > 1 && /* @__PURE__ */ (0,
|
|
43400
|
+
pickedIssues.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
42563
43401
|
BulkDetails,
|
|
42564
43402
|
{
|
|
42565
43403
|
issues: pickedIssues,
|
|
@@ -42587,13 +43425,13 @@ var App = () => {
|
|
|
42587
43425
|
onClear: clearPicked
|
|
42588
43426
|
}
|
|
42589
43427
|
),
|
|
42590
|
-
pickedIssues.length <= 1 && selectedIssue && state?.user && /* @__PURE__ */ (0,
|
|
43428
|
+
pickedIssues.length <= 1 && selectedIssue && state?.user && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
42591
43429
|
IssueDetails,
|
|
42592
43430
|
{
|
|
42593
43431
|
whoAmI: state.user,
|
|
42594
|
-
issue: selectedIssue,
|
|
43432
|
+
issue: issueDetail?.issueId === selectedIssue.id ? { ...selectedIssue, description: issueDetail.description } : selectedIssue,
|
|
42595
43433
|
activeTab: selectedTab,
|
|
42596
|
-
comments:
|
|
43434
|
+
comments: issueDetail?.issueId === selectedIssue.id ? issueDetail.comments : [],
|
|
42597
43435
|
onChangeTab: changeIssueDetailsTab,
|
|
42598
43436
|
onClose: closeIssueDetails,
|
|
42599
43437
|
onEditTitle: editIssueTitle,
|
|
@@ -42620,7 +43458,7 @@ var App = () => {
|
|
|
42620
43458
|
]
|
|
42621
43459
|
}
|
|
42622
43460
|
),
|
|
42623
|
-
createIssueModal && /* @__PURE__ */ (0,
|
|
43461
|
+
createIssueModal && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
42624
43462
|
CreateIssueModal,
|
|
42625
43463
|
{
|
|
42626
43464
|
title: createIssueModal.title,
|
|
@@ -42635,12 +43473,12 @@ var App = () => {
|
|
|
42635
43473
|
};
|
|
42636
43474
|
|
|
42637
43475
|
// source/gui/client/main.tsx
|
|
42638
|
-
var
|
|
43476
|
+
var import_jsx_runtime36 = __toESM(require_jsx_runtime(), 1);
|
|
42639
43477
|
(0, import_client.createRoot)(document.getElementById("root")).render(
|
|
42640
|
-
/* @__PURE__ */ (0,
|
|
42641
|
-
/* @__PURE__ */ (0,
|
|
42642
|
-
/* @__PURE__ */ (0,
|
|
42643
|
-
/* @__PURE__ */ (0,
|
|
43478
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(BrowserRouter, { children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(Routes, { children: [
|
|
43479
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(Route, { path: "/", element: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(App, {}) }),
|
|
43480
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(Route, { path: "/board/:boardId/*", element: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(App, {}) }),
|
|
43481
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(Route, { path: "*", element: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(Navigate, { to: "/", replace: true }) })
|
|
42644
43482
|
] }) })
|
|
42645
43483
|
);
|
|
42646
43484
|
/*! Bundled license information:
|