@ondrej-svec/hog 1.10.0 → 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +1023 -885
- package/dist/cli.js.map +1 -1
- package/dist/fetch-worker.js +35 -26
- package/dist/fetch-worker.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -740,10 +740,11 @@ function fetchProjectEnrichment(repo, projectNumber) {
|
|
|
740
740
|
const [owner] = repo.split("/");
|
|
741
741
|
if (!owner) return /* @__PURE__ */ new Map();
|
|
742
742
|
const query = `
|
|
743
|
-
query($owner: String!, $projectNumber: Int
|
|
743
|
+
query($owner: String!, $projectNumber: Int!, $cursor: String) {
|
|
744
744
|
organization(login: $owner) {
|
|
745
745
|
projectV2(number: $projectNumber) {
|
|
746
|
-
items(first: 100) {
|
|
746
|
+
items(first: 100, after: $cursor) {
|
|
747
|
+
pageInfo { hasNextPage endCursor }
|
|
747
748
|
nodes {
|
|
748
749
|
content {
|
|
749
750
|
... on Issue {
|
|
@@ -769,33 +770,41 @@ function fetchProjectEnrichment(repo, projectNumber) {
|
|
|
769
770
|
}
|
|
770
771
|
`;
|
|
771
772
|
try {
|
|
772
|
-
const result = runGhJson([
|
|
773
|
-
"api",
|
|
774
|
-
"graphql",
|
|
775
|
-
"-f",
|
|
776
|
-
`query=${query}`,
|
|
777
|
-
"-F",
|
|
778
|
-
`owner=${owner}`,
|
|
779
|
-
"-F",
|
|
780
|
-
`projectNumber=${String(projectNumber)}`
|
|
781
|
-
]);
|
|
782
|
-
const items = result?.data?.organization?.projectV2?.items?.nodes ?? [];
|
|
783
773
|
const enrichMap = /* @__PURE__ */ new Map();
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
const
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
|
|
774
|
+
let cursor = null;
|
|
775
|
+
do {
|
|
776
|
+
const args = [
|
|
777
|
+
"api",
|
|
778
|
+
"graphql",
|
|
779
|
+
"-f",
|
|
780
|
+
`query=${query}`,
|
|
781
|
+
"-F",
|
|
782
|
+
`owner=${owner}`,
|
|
783
|
+
"-F",
|
|
784
|
+
`projectNumber=${String(projectNumber)}`
|
|
785
|
+
];
|
|
786
|
+
if (cursor) args.push("-f", `cursor=${cursor}`);
|
|
787
|
+
const result = runGhJson(args);
|
|
788
|
+
const page = result?.data?.organization?.projectV2?.items;
|
|
789
|
+
const nodes = page?.nodes ?? [];
|
|
790
|
+
for (const item of nodes) {
|
|
791
|
+
if (!item?.content?.number) continue;
|
|
792
|
+
const enrichment = {};
|
|
793
|
+
const fieldValues = item.fieldValues?.nodes ?? [];
|
|
794
|
+
for (const fv of fieldValues) {
|
|
795
|
+
if (!fv) continue;
|
|
796
|
+
if ("date" in fv && fv.date && DATE_FIELD_NAME_RE2.test(fv.field?.name ?? "")) {
|
|
797
|
+
enrichment.targetDate = fv.date;
|
|
798
|
+
}
|
|
799
|
+
if ("name" in fv && fv.field?.name === "Status" && fv.name) {
|
|
800
|
+
enrichment.projectStatus = fv.name;
|
|
801
|
+
}
|
|
795
802
|
}
|
|
803
|
+
enrichMap.set(item.content.number, enrichment);
|
|
796
804
|
}
|
|
797
|
-
|
|
798
|
-
|
|
805
|
+
if (!page?.pageInfo?.hasNextPage) break;
|
|
806
|
+
cursor = page.pageInfo.endCursor ?? null;
|
|
807
|
+
} while (cursor);
|
|
799
808
|
return enrichMap;
|
|
800
809
|
} catch {
|
|
801
810
|
return /* @__PURE__ */ new Map();
|
|
@@ -1630,7 +1639,7 @@ ${dueLine}` : dueLine;
|
|
|
1630
1639
|
const output = await createIssueAsync(repo, title, effectiveBody, labels);
|
|
1631
1640
|
const match = output.match(/\/(\d+)$/);
|
|
1632
1641
|
const issueNumber = match?.[1] ? parseInt(match[1], 10) : 0;
|
|
1633
|
-
const
|
|
1642
|
+
const shortName2 = repoConfig?.shortName ?? repo;
|
|
1634
1643
|
if (issueNumber > 0 && dueDate && repoConfig?.dueDateFieldId) {
|
|
1635
1644
|
const dueDateConfig = {
|
|
1636
1645
|
projectNumber: repoConfig.projectNumber,
|
|
@@ -1639,7 +1648,7 @@ ${dueLine}` : dueLine;
|
|
|
1639
1648
|
updateProjectItemDateAsync(repo, issueNumber, dueDateConfig, dueDate).catch(() => {
|
|
1640
1649
|
});
|
|
1641
1650
|
}
|
|
1642
|
-
t.resolve(`Created ${
|
|
1651
|
+
t.resolve(`Created ${shortName2}#${issueNumber}`);
|
|
1643
1652
|
refresh();
|
|
1644
1653
|
onOverlayDone();
|
|
1645
1654
|
return issueNumber > 0 ? { repo, issueNumber } : null;
|
|
@@ -1999,8 +2008,13 @@ function useKeyboard({
|
|
|
1999
2008
|
selectedRepoStatusOptionsLength,
|
|
2000
2009
|
actions,
|
|
2001
2010
|
onSearchEscape,
|
|
2002
|
-
|
|
2003
|
-
|
|
2011
|
+
panelFocus,
|
|
2012
|
+
reposNav,
|
|
2013
|
+
statusesNav,
|
|
2014
|
+
activityNav,
|
|
2015
|
+
onRepoEnter,
|
|
2016
|
+
onStatusEnter,
|
|
2017
|
+
onActivityEnter
|
|
2004
2018
|
}) {
|
|
2005
2019
|
const {
|
|
2006
2020
|
exit,
|
|
@@ -2036,19 +2050,41 @@ function useKeyboard({
|
|
|
2036
2050
|
}
|
|
2037
2051
|
if (ui.canNavigate) {
|
|
2038
2052
|
if (input2 === "j" || key.downArrow) {
|
|
2039
|
-
|
|
2053
|
+
switch (panelFocus.activePanelId) {
|
|
2054
|
+
case 1:
|
|
2055
|
+
reposNav.moveDown();
|
|
2056
|
+
break;
|
|
2057
|
+
case 2:
|
|
2058
|
+
statusesNav.moveDown();
|
|
2059
|
+
break;
|
|
2060
|
+
case 3:
|
|
2061
|
+
nav.moveDown();
|
|
2062
|
+
break;
|
|
2063
|
+
case 4:
|
|
2064
|
+
activityNav.moveDown();
|
|
2065
|
+
break;
|
|
2066
|
+
default:
|
|
2067
|
+
break;
|
|
2068
|
+
}
|
|
2040
2069
|
return;
|
|
2041
2070
|
}
|
|
2042
2071
|
if (input2 === "k" || key.upArrow) {
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2072
|
+
switch (panelFocus.activePanelId) {
|
|
2073
|
+
case 1:
|
|
2074
|
+
reposNav.moveUp();
|
|
2075
|
+
break;
|
|
2076
|
+
case 2:
|
|
2077
|
+
statusesNav.moveUp();
|
|
2078
|
+
break;
|
|
2079
|
+
case 3:
|
|
2080
|
+
nav.moveUp();
|
|
2081
|
+
break;
|
|
2082
|
+
case 4:
|
|
2083
|
+
activityNav.moveUp();
|
|
2084
|
+
break;
|
|
2085
|
+
default:
|
|
2086
|
+
break;
|
|
2050
2087
|
}
|
|
2051
|
-
key.shift ? tabNav.prev() : tabNav.next();
|
|
2052
2088
|
return;
|
|
2053
2089
|
}
|
|
2054
2090
|
}
|
|
@@ -2078,8 +2114,8 @@ function useKeyboard({
|
|
|
2078
2114
|
if (input2 === "r" && handleErrorAction("retry")) return;
|
|
2079
2115
|
if (ui.canAct) {
|
|
2080
2116
|
const digit = parseInt(input2, 10);
|
|
2081
|
-
if (!Number.isNaN(digit) && digit >=
|
|
2082
|
-
|
|
2117
|
+
if (!Number.isNaN(digit) && digit >= 0 && digit <= 4) {
|
|
2118
|
+
panelFocus.focusPanel(digit);
|
|
2083
2119
|
return;
|
|
2084
2120
|
}
|
|
2085
2121
|
if (input2 === "/") {
|
|
@@ -2096,14 +2132,6 @@ function useKeyboard({
|
|
|
2096
2132
|
refresh();
|
|
2097
2133
|
return;
|
|
2098
2134
|
}
|
|
2099
|
-
if (input2 === "s") {
|
|
2100
|
-
statusNav?.next();
|
|
2101
|
-
return;
|
|
2102
|
-
}
|
|
2103
|
-
if (input2 === "S") {
|
|
2104
|
-
statusNav?.prev();
|
|
2105
|
-
return;
|
|
2106
|
-
}
|
|
2107
2135
|
if (input2 === "o") {
|
|
2108
2136
|
handleSlack();
|
|
2109
2137
|
return;
|
|
@@ -2187,7 +2215,22 @@ function useKeyboard({
|
|
|
2187
2215
|
return;
|
|
2188
2216
|
}
|
|
2189
2217
|
if (key.return) {
|
|
2190
|
-
|
|
2218
|
+
switch (panelFocus.activePanelId) {
|
|
2219
|
+
case 1:
|
|
2220
|
+
onRepoEnter();
|
|
2221
|
+
break;
|
|
2222
|
+
case 2:
|
|
2223
|
+
onStatusEnter();
|
|
2224
|
+
break;
|
|
2225
|
+
case 3:
|
|
2226
|
+
handleOpen();
|
|
2227
|
+
break;
|
|
2228
|
+
case 4:
|
|
2229
|
+
onActivityEnter();
|
|
2230
|
+
break;
|
|
2231
|
+
default:
|
|
2232
|
+
break;
|
|
2233
|
+
}
|
|
2191
2234
|
return;
|
|
2192
2235
|
}
|
|
2193
2236
|
}
|
|
@@ -2195,8 +2238,13 @@ function useKeyboard({
|
|
|
2195
2238
|
[
|
|
2196
2239
|
ui,
|
|
2197
2240
|
nav,
|
|
2198
|
-
|
|
2199
|
-
|
|
2241
|
+
panelFocus,
|
|
2242
|
+
reposNav,
|
|
2243
|
+
statusesNav,
|
|
2244
|
+
activityNav,
|
|
2245
|
+
onRepoEnter,
|
|
2246
|
+
onStatusEnter,
|
|
2247
|
+
onActivityEnter,
|
|
2200
2248
|
exit,
|
|
2201
2249
|
refresh,
|
|
2202
2250
|
handleSlack,
|
|
@@ -2502,26 +2550,42 @@ var init_use_navigation = __esm({
|
|
|
2502
2550
|
}
|
|
2503
2551
|
});
|
|
2504
2552
|
|
|
2553
|
+
// src/board/hooks/use-panel-focus.ts
|
|
2554
|
+
import { useCallback as useCallback7, useState as useState4 } from "react";
|
|
2555
|
+
function usePanelFocus(initialPanel = 3) {
|
|
2556
|
+
const [activePanelId, setActivePanelId] = useState4(initialPanel);
|
|
2557
|
+
const focusPanel = useCallback7((id) => {
|
|
2558
|
+
setActivePanelId(id);
|
|
2559
|
+
}, []);
|
|
2560
|
+
const isPanelActive = useCallback7((id) => activePanelId === id, [activePanelId]);
|
|
2561
|
+
return { activePanelId, focusPanel, isPanelActive };
|
|
2562
|
+
}
|
|
2563
|
+
var init_use_panel_focus = __esm({
|
|
2564
|
+
"src/board/hooks/use-panel-focus.ts"() {
|
|
2565
|
+
"use strict";
|
|
2566
|
+
}
|
|
2567
|
+
});
|
|
2568
|
+
|
|
2505
2569
|
// src/board/hooks/use-toast.ts
|
|
2506
|
-
import { useCallback as
|
|
2570
|
+
import { useCallback as useCallback8, useRef as useRef6, useState as useState5 } from "react";
|
|
2507
2571
|
function useToast() {
|
|
2508
|
-
const [toasts, setToasts] =
|
|
2572
|
+
const [toasts, setToasts] = useState5([]);
|
|
2509
2573
|
const timersRef = useRef6(/* @__PURE__ */ new Map());
|
|
2510
|
-
const clearTimer =
|
|
2574
|
+
const clearTimer = useCallback8((id) => {
|
|
2511
2575
|
const timer = timersRef.current.get(id);
|
|
2512
2576
|
if (timer) {
|
|
2513
2577
|
clearTimeout(timer);
|
|
2514
2578
|
timersRef.current.delete(id);
|
|
2515
2579
|
}
|
|
2516
2580
|
}, []);
|
|
2517
|
-
const removeToast =
|
|
2581
|
+
const removeToast = useCallback8(
|
|
2518
2582
|
(id) => {
|
|
2519
2583
|
clearTimer(id);
|
|
2520
2584
|
setToasts((prev) => prev.filter((t) => t.id !== id));
|
|
2521
2585
|
},
|
|
2522
2586
|
[clearTimer]
|
|
2523
2587
|
);
|
|
2524
|
-
const addToast =
|
|
2588
|
+
const addToast = useCallback8(
|
|
2525
2589
|
(t) => {
|
|
2526
2590
|
const id = `toast-${++nextId}`;
|
|
2527
2591
|
const newToast = { ...t, id, createdAt: Date.now() };
|
|
@@ -2550,25 +2614,25 @@ function useToast() {
|
|
|
2550
2614
|
[removeToast, clearTimer]
|
|
2551
2615
|
);
|
|
2552
2616
|
const toast = {
|
|
2553
|
-
info:
|
|
2617
|
+
info: useCallback8(
|
|
2554
2618
|
(message) => {
|
|
2555
2619
|
addToast({ type: "info", message });
|
|
2556
2620
|
},
|
|
2557
2621
|
[addToast]
|
|
2558
2622
|
),
|
|
2559
|
-
success:
|
|
2623
|
+
success: useCallback8(
|
|
2560
2624
|
(message) => {
|
|
2561
2625
|
addToast({ type: "success", message });
|
|
2562
2626
|
},
|
|
2563
2627
|
[addToast]
|
|
2564
2628
|
),
|
|
2565
|
-
error:
|
|
2629
|
+
error: useCallback8(
|
|
2566
2630
|
(message, retry) => {
|
|
2567
2631
|
addToast(retry ? { type: "error", message, retry } : { type: "error", message });
|
|
2568
2632
|
},
|
|
2569
2633
|
[addToast]
|
|
2570
2634
|
),
|
|
2571
|
-
loading:
|
|
2635
|
+
loading: useCallback8(
|
|
2572
2636
|
(message) => {
|
|
2573
2637
|
const id = addToast({ type: "loading", message });
|
|
2574
2638
|
return {
|
|
@@ -2585,7 +2649,7 @@ function useToast() {
|
|
|
2585
2649
|
[addToast, removeToast]
|
|
2586
2650
|
)
|
|
2587
2651
|
};
|
|
2588
|
-
const handleErrorAction =
|
|
2652
|
+
const handleErrorAction = useCallback8(
|
|
2589
2653
|
(action) => {
|
|
2590
2654
|
const errorToast = toasts.find((t) => t.type === "error");
|
|
2591
2655
|
if (!errorToast) return false;
|
|
@@ -2615,7 +2679,7 @@ var init_use_toast = __esm({
|
|
|
2615
2679
|
});
|
|
2616
2680
|
|
|
2617
2681
|
// src/board/hooks/use-ui-state.ts
|
|
2618
|
-
import { useCallback as
|
|
2682
|
+
import { useCallback as useCallback9, useReducer as useReducer2 } from "react";
|
|
2619
2683
|
function enterStatusMode(state) {
|
|
2620
2684
|
if (state.mode !== "normal" && state.mode !== "overlay:bulkAction") return state;
|
|
2621
2685
|
const previousMode = state.mode === "overlay:bulkAction" ? "multiSelect" : "normal";
|
|
@@ -2689,22 +2753,22 @@ function useUIState() {
|
|
|
2689
2753
|
const [state, dispatch] = useReducer2(uiReducer, INITIAL_STATE2);
|
|
2690
2754
|
return {
|
|
2691
2755
|
state,
|
|
2692
|
-
enterSearch:
|
|
2693
|
-
enterComment:
|
|
2694
|
-
enterStatus:
|
|
2695
|
-
enterCreate:
|
|
2696
|
-
enterCreateNl:
|
|
2697
|
-
enterLabel:
|
|
2698
|
-
enterMultiSelect:
|
|
2699
|
-
enterBulkAction:
|
|
2700
|
-
enterConfirmPick:
|
|
2701
|
-
enterFocus:
|
|
2702
|
-
enterFuzzyPicker:
|
|
2703
|
-
enterEditIssue:
|
|
2704
|
-
toggleHelp:
|
|
2705
|
-
exitOverlay:
|
|
2706
|
-
exitToNormal:
|
|
2707
|
-
clearMultiSelect:
|
|
2756
|
+
enterSearch: useCallback9(() => dispatch({ type: "ENTER_SEARCH" }), []),
|
|
2757
|
+
enterComment: useCallback9(() => dispatch({ type: "ENTER_COMMENT" }), []),
|
|
2758
|
+
enterStatus: useCallback9(() => dispatch({ type: "ENTER_STATUS" }), []),
|
|
2759
|
+
enterCreate: useCallback9(() => dispatch({ type: "ENTER_CREATE" }), []),
|
|
2760
|
+
enterCreateNl: useCallback9(() => dispatch({ type: "ENTER_CREATE_NL" }), []),
|
|
2761
|
+
enterLabel: useCallback9(() => dispatch({ type: "ENTER_LABEL" }), []),
|
|
2762
|
+
enterMultiSelect: useCallback9(() => dispatch({ type: "ENTER_MULTI_SELECT" }), []),
|
|
2763
|
+
enterBulkAction: useCallback9(() => dispatch({ type: "ENTER_BULK_ACTION" }), []),
|
|
2764
|
+
enterConfirmPick: useCallback9(() => dispatch({ type: "ENTER_CONFIRM_PICK" }), []),
|
|
2765
|
+
enterFocus: useCallback9(() => dispatch({ type: "ENTER_FOCUS" }), []),
|
|
2766
|
+
enterFuzzyPicker: useCallback9(() => dispatch({ type: "ENTER_FUZZY_PICKER" }), []),
|
|
2767
|
+
enterEditIssue: useCallback9(() => dispatch({ type: "ENTER_EDIT_ISSUE" }), []),
|
|
2768
|
+
toggleHelp: useCallback9(() => dispatch({ type: "TOGGLE_HELP" }), []),
|
|
2769
|
+
exitOverlay: useCallback9(() => dispatch({ type: "EXIT_OVERLAY" }), []),
|
|
2770
|
+
exitToNormal: useCallback9(() => dispatch({ type: "EXIT_TO_NORMAL" }), []),
|
|
2771
|
+
clearMultiSelect: useCallback9(() => dispatch({ type: "CLEAR_MULTI_SELECT" }), []),
|
|
2708
2772
|
canNavigate: canNavigate(state),
|
|
2709
2773
|
canAct: canAct(state),
|
|
2710
2774
|
isOverlay: isOverlay(state)
|
|
@@ -2724,7 +2788,7 @@ var init_use_ui_state = __esm({
|
|
|
2724
2788
|
|
|
2725
2789
|
// src/board/components/action-log.tsx
|
|
2726
2790
|
import { Box, Text } from "ink";
|
|
2727
|
-
import { useEffect as useEffect2, useState as
|
|
2791
|
+
import { useEffect as useEffect2, useState as useState6 } from "react";
|
|
2728
2792
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2729
2793
|
function relativeTime(ago) {
|
|
2730
2794
|
const seconds = Math.floor((Date.now() - ago) / 1e3);
|
|
@@ -2745,7 +2809,7 @@ function statusColor(status) {
|
|
|
2745
2809
|
return "yellow";
|
|
2746
2810
|
}
|
|
2747
2811
|
function ActionLog({ entries }) {
|
|
2748
|
-
const [, setTick] =
|
|
2812
|
+
const [, setTick] = useState6(0);
|
|
2749
2813
|
useEffect2(() => {
|
|
2750
2814
|
const id = setInterval(() => setTick((t) => t + 1), 5e3);
|
|
2751
2815
|
return () => clearInterval(id);
|
|
@@ -2784,14 +2848,88 @@ var init_action_log = __esm({
|
|
|
2784
2848
|
}
|
|
2785
2849
|
});
|
|
2786
2850
|
|
|
2787
|
-
// src/board/components/
|
|
2851
|
+
// src/board/components/panel.tsx
|
|
2788
2852
|
import { Box as Box2, Text as Text2 } from "ink";
|
|
2789
|
-
import {
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
const
|
|
2793
|
-
return
|
|
2853
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
2854
|
+
function buildTopLine(title, width) {
|
|
2855
|
+
const titlePart = `\u2500 ${title} `;
|
|
2856
|
+
const dashCount = Math.max(0, width - 2 - titlePart.length);
|
|
2857
|
+
return `\u256D${titlePart}${"\u2500".repeat(dashCount)}\u256E`;
|
|
2858
|
+
}
|
|
2859
|
+
function Panel({ title, isActive, width, height, flexGrow, children }) {
|
|
2860
|
+
const color = isActive ? "cyan" : "gray";
|
|
2861
|
+
const topLine = buildTopLine(title, width);
|
|
2862
|
+
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", width, height, flexGrow, overflow: "hidden", children: [
|
|
2863
|
+
/* @__PURE__ */ jsx2(Text2, { color, children: topLine }),
|
|
2864
|
+
/* @__PURE__ */ jsx2(
|
|
2865
|
+
Box2,
|
|
2866
|
+
{
|
|
2867
|
+
borderStyle: "round",
|
|
2868
|
+
borderTop: false,
|
|
2869
|
+
borderColor: color,
|
|
2870
|
+
flexDirection: "column",
|
|
2871
|
+
flexGrow: 1,
|
|
2872
|
+
overflow: "hidden",
|
|
2873
|
+
width,
|
|
2874
|
+
children
|
|
2875
|
+
}
|
|
2876
|
+
)
|
|
2877
|
+
] });
|
|
2794
2878
|
}
|
|
2879
|
+
var init_panel = __esm({
|
|
2880
|
+
"src/board/components/panel.tsx"() {
|
|
2881
|
+
"use strict";
|
|
2882
|
+
}
|
|
2883
|
+
});
|
|
2884
|
+
|
|
2885
|
+
// src/board/components/activity-panel.tsx
|
|
2886
|
+
import { Box as Box3, Text as Text3 } from "ink";
|
|
2887
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
2888
|
+
function ActivityPanel({
|
|
2889
|
+
events,
|
|
2890
|
+
selectedIdx,
|
|
2891
|
+
isActive,
|
|
2892
|
+
height,
|
|
2893
|
+
width
|
|
2894
|
+
}) {
|
|
2895
|
+
const maxRows = Math.max(1, height - 2);
|
|
2896
|
+
const visible = events.slice(0, maxRows);
|
|
2897
|
+
return /* @__PURE__ */ jsx3(Panel, { title: "[4] Activity", isActive, width, height, children: visible.length === 0 ? /* @__PURE__ */ jsx3(Text3, { color: "gray", children: " No recent activity" }) : visible.map((event, i) => {
|
|
2898
|
+
const isSel = isActive && i === selectedIdx;
|
|
2899
|
+
const ago = timeAgo(event.timestamp);
|
|
2900
|
+
return /* @__PURE__ */ jsxs3(Box3, { children: [
|
|
2901
|
+
/* @__PURE__ */ jsxs3(Text3, { color: isSel ? "cyan" : "gray", bold: isSel, children: [
|
|
2902
|
+
isSel ? "\u25BA " : " ",
|
|
2903
|
+
ago
|
|
2904
|
+
] }),
|
|
2905
|
+
/* @__PURE__ */ jsxs3(Text3, { color: isSel ? "white" : "gray", children: [
|
|
2906
|
+
" ",
|
|
2907
|
+
"@",
|
|
2908
|
+
event.actor,
|
|
2909
|
+
" ",
|
|
2910
|
+
event.summary,
|
|
2911
|
+
" "
|
|
2912
|
+
] }),
|
|
2913
|
+
/* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
|
|
2914
|
+
"(",
|
|
2915
|
+
event.repoShortName,
|
|
2916
|
+
")"
|
|
2917
|
+
] })
|
|
2918
|
+
] }, `${event.repoShortName}:${event.issueNumber}:${i}`);
|
|
2919
|
+
}) });
|
|
2920
|
+
}
|
|
2921
|
+
var init_activity_panel = __esm({
|
|
2922
|
+
"src/board/components/activity-panel.tsx"() {
|
|
2923
|
+
"use strict";
|
|
2924
|
+
init_constants();
|
|
2925
|
+
init_panel();
|
|
2926
|
+
}
|
|
2927
|
+
});
|
|
2928
|
+
|
|
2929
|
+
// src/board/components/detail-panel.tsx
|
|
2930
|
+
import { Box as Box4, Text as Text4 } from "ink";
|
|
2931
|
+
import { useEffect as useEffect3 } from "react";
|
|
2932
|
+
import { Fragment, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
2795
2933
|
function stripMarkdown(text) {
|
|
2796
2934
|
return text.replace(/^#{1,6}\s+/gm, "").replace(/\*\*(.+?)\*\*/g, "$1").replace(/\*(.+?)\*/g, "$1").replace(/__(.+?)__/g, "$1").replace(/_(.+?)_/g, "$1").replace(/~~(.+?)~~/g, "$1").replace(/`{1,3}[^`]*`{1,3}/g, (m) => m.replace(/`/g, "")).replace(/^\s*[-*+]\s+/gm, " - ").replace(/^\s*\d+\.\s+/gm, " ").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/!\[([^\]]*)\]\([^)]+\)/g, "[$1]").replace(/^>\s+/gm, " ").replace(/---+/g, "").replace(/\n{3,}/g, "\n\n").trim();
|
|
2797
2935
|
}
|
|
@@ -2810,11 +2948,11 @@ function BodySection({
|
|
|
2810
2948
|
issueNumber
|
|
2811
2949
|
}) {
|
|
2812
2950
|
const { text, remaining } = formatBody(body, 15);
|
|
2813
|
-
return /* @__PURE__ */
|
|
2814
|
-
/* @__PURE__ */
|
|
2815
|
-
/* @__PURE__ */
|
|
2816
|
-
/* @__PURE__ */
|
|
2817
|
-
remaining > 0 ? /* @__PURE__ */
|
|
2951
|
+
return /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
2952
|
+
/* @__PURE__ */ jsx4(Text4, { children: "" }),
|
|
2953
|
+
/* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "--- Description ---" }),
|
|
2954
|
+
/* @__PURE__ */ jsx4(Text4, { wrap: "wrap", children: text }),
|
|
2955
|
+
remaining > 0 ? /* @__PURE__ */ jsxs4(Text4, { dimColor: true, children: [
|
|
2818
2956
|
"... (",
|
|
2819
2957
|
remaining,
|
|
2820
2958
|
" more lines \u2014 gh issue view ",
|
|
@@ -2835,8 +2973,8 @@ function formatCommentAge(createdAt) {
|
|
|
2835
2973
|
}
|
|
2836
2974
|
function DetailPanel({
|
|
2837
2975
|
issue,
|
|
2838
|
-
task: task2,
|
|
2839
2976
|
width,
|
|
2977
|
+
isActive,
|
|
2840
2978
|
commentsState,
|
|
2841
2979
|
fetchComments,
|
|
2842
2980
|
issueRepo
|
|
@@ -2846,174 +2984,108 @@ function DetailPanel({
|
|
|
2846
2984
|
if (commentsState !== null && commentsState !== void 0) return;
|
|
2847
2985
|
fetchComments(issueRepo, issue.number);
|
|
2848
2986
|
}, [issue, issueRepo, fetchComments, commentsState]);
|
|
2849
|
-
if (!
|
|
2850
|
-
return /* @__PURE__ */
|
|
2851
|
-
Box2,
|
|
2852
|
-
{
|
|
2853
|
-
width,
|
|
2854
|
-
borderStyle: "single",
|
|
2855
|
-
borderColor: "gray",
|
|
2856
|
-
flexDirection: "column",
|
|
2857
|
-
paddingX: 1,
|
|
2858
|
-
children: /* @__PURE__ */ jsx2(Text2, { color: "gray", children: "No item selected" })
|
|
2859
|
-
}
|
|
2860
|
-
);
|
|
2861
|
-
}
|
|
2862
|
-
if (issue) {
|
|
2863
|
-
return /* @__PURE__ */ jsxs2(
|
|
2864
|
-
Box2,
|
|
2865
|
-
{
|
|
2866
|
-
width,
|
|
2867
|
-
borderStyle: "single",
|
|
2868
|
-
borderColor: "cyan",
|
|
2869
|
-
flexDirection: "column",
|
|
2870
|
-
paddingX: 1,
|
|
2871
|
-
children: [
|
|
2872
|
-
/* @__PURE__ */ jsxs2(Text2, { color: "cyan", bold: true, children: [
|
|
2873
|
-
"#",
|
|
2874
|
-
issue.number,
|
|
2875
|
-
" ",
|
|
2876
|
-
issue.title
|
|
2877
|
-
] }),
|
|
2878
|
-
/* @__PURE__ */ jsx2(Text2, { children: "" }),
|
|
2879
|
-
/* @__PURE__ */ jsxs2(Box2, { children: [
|
|
2880
|
-
/* @__PURE__ */ jsx2(Text2, { color: "gray", children: "State: " }),
|
|
2881
|
-
/* @__PURE__ */ jsx2(Text2, { color: issue.state === "open" ? "green" : "red", children: issue.state })
|
|
2882
|
-
] }),
|
|
2883
|
-
(issue.assignees ?? []).length > 0 ? /* @__PURE__ */ jsxs2(Box2, { children: [
|
|
2884
|
-
/* @__PURE__ */ jsx2(Text2, { color: "gray", children: "Assignees: " }),
|
|
2885
|
-
/* @__PURE__ */ jsx2(Text2, { children: (issue.assignees ?? []).map((a) => a.login).join(", ") })
|
|
2886
|
-
] }) : null,
|
|
2887
|
-
issue.labels.length > 0 ? /* @__PURE__ */ jsxs2(Box2, { children: [
|
|
2888
|
-
/* @__PURE__ */ jsx2(Text2, { color: "gray", children: "Labels: " }),
|
|
2889
|
-
/* @__PURE__ */ jsx2(Text2, { children: issue.labels.map((l) => l.name).join(", ") })
|
|
2890
|
-
] }) : null,
|
|
2891
|
-
issue.projectStatus ? /* @__PURE__ */ jsxs2(Box2, { children: [
|
|
2892
|
-
/* @__PURE__ */ jsx2(Text2, { color: "gray", children: "Status: " }),
|
|
2893
|
-
/* @__PURE__ */ jsx2(Text2, { color: "magenta", children: issue.projectStatus })
|
|
2894
|
-
] }) : null,
|
|
2895
|
-
issue.targetDate ? /* @__PURE__ */ jsxs2(Box2, { children: [
|
|
2896
|
-
/* @__PURE__ */ jsx2(Text2, { color: "gray", children: "Target: " }),
|
|
2897
|
-
/* @__PURE__ */ jsx2(Text2, { children: issue.targetDate })
|
|
2898
|
-
] }) : null,
|
|
2899
|
-
/* @__PURE__ */ jsxs2(Box2, { children: [
|
|
2900
|
-
/* @__PURE__ */ jsx2(Text2, { color: "gray", children: "Updated: " }),
|
|
2901
|
-
/* @__PURE__ */ jsx2(Text2, { children: new Date(issue.updatedAt).toLocaleString() })
|
|
2902
|
-
] }),
|
|
2903
|
-
issue.slackThreadUrl ? /* @__PURE__ */ jsxs2(Box2, { children: [
|
|
2904
|
-
/* @__PURE__ */ jsx2(Text2, { color: "gray", children: "Slack: " }),
|
|
2905
|
-
/* @__PURE__ */ jsx2(Text2, { color: "blue", children: countSlackLinks(issue.body) > 1 ? `${countSlackLinks(issue.body)} links (s opens first)` : "thread (s to open)" })
|
|
2906
|
-
] }) : null,
|
|
2907
|
-
issue.body ? /* @__PURE__ */ jsx2(BodySection, { body: issue.body, issueNumber: issue.number }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
2908
|
-
/* @__PURE__ */ jsx2(Text2, { children: "" }),
|
|
2909
|
-
/* @__PURE__ */ jsx2(Text2, { color: "gray", children: "(no description)" })
|
|
2910
|
-
] }),
|
|
2911
|
-
/* @__PURE__ */ jsx2(Text2, { children: "" }),
|
|
2912
|
-
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "--- Comments ---" }),
|
|
2913
|
-
commentsState === "loading" ? /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "fetching comments..." }) : commentsState === "error" ? /* @__PURE__ */ jsx2(Text2, { color: "red", children: "could not load comments" }) : commentsState && commentsState.length === 0 ? /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "No comments yet." }) : commentsState && commentsState.length > 0 ? commentsState.slice(-5).map((comment, i) => (
|
|
2914
|
-
// biome-ignore lint/suspicious/noArrayIndexKey: stable list
|
|
2915
|
-
/* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", marginBottom: 1, children: [
|
|
2916
|
-
/* @__PURE__ */ jsxs2(Text2, { color: "cyan", children: [
|
|
2917
|
-
"@",
|
|
2918
|
-
comment.author.login,
|
|
2919
|
-
" \xB7 ",
|
|
2920
|
-
formatCommentAge(comment.createdAt)
|
|
2921
|
-
] }),
|
|
2922
|
-
/* @__PURE__ */ jsxs2(Text2, { wrap: "wrap", children: [
|
|
2923
|
-
" ",
|
|
2924
|
-
comment.body.split("\n")[0]
|
|
2925
|
-
] })
|
|
2926
|
-
] }, i)
|
|
2927
|
-
)) : /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "fetching comments..." }),
|
|
2928
|
-
/* @__PURE__ */ jsx2(Text2, { children: "" }),
|
|
2929
|
-
/* @__PURE__ */ jsx2(Text2, { color: "gray", dimColor: true, children: issue.url })
|
|
2930
|
-
]
|
|
2931
|
-
}
|
|
2932
|
-
);
|
|
2987
|
+
if (!issue) {
|
|
2988
|
+
return /* @__PURE__ */ jsx4(Panel, { title: "[0] Detail", isActive, width, children: /* @__PURE__ */ jsx4(Text4, { color: "gray", children: "No item selected" }) });
|
|
2933
2989
|
}
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
children:
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2990
|
+
return /* @__PURE__ */ jsxs4(Panel, { title: "[0] Detail", isActive, width, children: [
|
|
2991
|
+
/* @__PURE__ */ jsxs4(Text4, { color: "cyan", bold: true, children: [
|
|
2992
|
+
"#",
|
|
2993
|
+
issue.number,
|
|
2994
|
+
" ",
|
|
2995
|
+
issue.title
|
|
2996
|
+
] }),
|
|
2997
|
+
/* @__PURE__ */ jsx4(Text4, { children: "" }),
|
|
2998
|
+
/* @__PURE__ */ jsxs4(Box4, { children: [
|
|
2999
|
+
/* @__PURE__ */ jsx4(Text4, { color: "gray", children: "State: " }),
|
|
3000
|
+
/* @__PURE__ */ jsx4(Text4, { color: issue.state === "open" ? "green" : "red", children: issue.state })
|
|
3001
|
+
] }),
|
|
3002
|
+
(issue.assignees ?? []).length > 0 ? /* @__PURE__ */ jsxs4(Box4, { children: [
|
|
3003
|
+
/* @__PURE__ */ jsx4(Text4, { color: "gray", children: "Assignees: " }),
|
|
3004
|
+
/* @__PURE__ */ jsx4(Text4, { children: (issue.assignees ?? []).map((a) => a.login).join(", ") })
|
|
3005
|
+
] }) : null,
|
|
3006
|
+
issue.labels.length > 0 ? /* @__PURE__ */ jsxs4(Box4, { children: [
|
|
3007
|
+
/* @__PURE__ */ jsx4(Text4, { color: "gray", children: "Labels: " }),
|
|
3008
|
+
/* @__PURE__ */ jsx4(Text4, { children: issue.labels.map((l) => l.name).join(", ") })
|
|
3009
|
+
] }) : null,
|
|
3010
|
+
issue.projectStatus ? /* @__PURE__ */ jsxs4(Box4, { children: [
|
|
3011
|
+
/* @__PURE__ */ jsx4(Text4, { color: "gray", children: "Status: " }),
|
|
3012
|
+
/* @__PURE__ */ jsx4(Text4, { color: "magenta", children: issue.projectStatus })
|
|
3013
|
+
] }) : null,
|
|
3014
|
+
issue.targetDate ? /* @__PURE__ */ jsxs4(Box4, { children: [
|
|
3015
|
+
/* @__PURE__ */ jsx4(Text4, { color: "gray", children: "Target: " }),
|
|
3016
|
+
/* @__PURE__ */ jsx4(Text4, { children: issue.targetDate })
|
|
3017
|
+
] }) : null,
|
|
3018
|
+
/* @__PURE__ */ jsxs4(Box4, { children: [
|
|
3019
|
+
/* @__PURE__ */ jsx4(Text4, { color: "gray", children: "Updated: " }),
|
|
3020
|
+
/* @__PURE__ */ jsx4(Text4, { children: new Date(issue.updatedAt).toLocaleString() })
|
|
3021
|
+
] }),
|
|
3022
|
+
issue.slackThreadUrl ? /* @__PURE__ */ jsxs4(Box4, { children: [
|
|
3023
|
+
/* @__PURE__ */ jsx4(Text4, { color: "gray", children: "Slack: " }),
|
|
3024
|
+
/* @__PURE__ */ jsx4(Text4, { color: "blue", children: countSlackLinks(issue.body) > 1 ? `${countSlackLinks(issue.body)} links (s opens first)` : "thread (s to open)" })
|
|
3025
|
+
] }) : null,
|
|
3026
|
+
issue.body ? /* @__PURE__ */ jsx4(BodySection, { body: issue.body, issueNumber: issue.number }) : /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
3027
|
+
/* @__PURE__ */ jsx4(Text4, { children: "" }),
|
|
3028
|
+
/* @__PURE__ */ jsx4(Text4, { color: "gray", children: "(no description)" })
|
|
3029
|
+
] }),
|
|
3030
|
+
/* @__PURE__ */ jsx4(Text4, { children: "" }),
|
|
3031
|
+
/* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "--- Comments ---" }),
|
|
3032
|
+
commentsState === "loading" ? /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "fetching comments..." }) : commentsState === "error" ? /* @__PURE__ */ jsx4(Text4, { color: "red", children: "could not load comments" }) : commentsState && commentsState.length === 0 ? /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "No comments yet." }) : commentsState && commentsState.length > 0 ? commentsState.slice(-5).map((comment, i) => (
|
|
3033
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: stable list
|
|
3034
|
+
/* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", marginBottom: 1, children: [
|
|
3035
|
+
/* @__PURE__ */ jsxs4(Text4, { color: "cyan", children: [
|
|
3036
|
+
"@",
|
|
3037
|
+
comment.author.login,
|
|
3038
|
+
" \xB7 ",
|
|
3039
|
+
formatCommentAge(comment.createdAt)
|
|
2949
3040
|
] }),
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
] })
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
/* @__PURE__ */ jsx2(Text2, { children: "" }),
|
|
2960
|
-
/* @__PURE__ */ jsx2(Text2, { children: truncateLines(t.content, 8) })
|
|
2961
|
-
] }) : null,
|
|
2962
|
-
(t.items ?? []).length > 0 ? /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
2963
|
-
/* @__PURE__ */ jsx2(Text2, { children: "" }),
|
|
2964
|
-
/* @__PURE__ */ jsx2(Text2, { color: "gray", children: "Checklist:" }),
|
|
2965
|
-
t.items.slice(0, 5).map((item) => /* @__PURE__ */ jsxs2(Text2, { children: [
|
|
2966
|
-
item.status === 2 ? "\u2611" : "\u2610",
|
|
2967
|
-
" ",
|
|
2968
|
-
item.title
|
|
2969
|
-
] }, item.id)),
|
|
2970
|
-
t.items.length > 5 ? /* @__PURE__ */ jsxs2(Text2, { color: "gray", children: [
|
|
2971
|
-
"...and ",
|
|
2972
|
-
t.items.length - 5,
|
|
2973
|
-
" more"
|
|
2974
|
-
] }) : null
|
|
2975
|
-
] }) : null
|
|
2976
|
-
]
|
|
2977
|
-
}
|
|
2978
|
-
);
|
|
3041
|
+
/* @__PURE__ */ jsxs4(Text4, { wrap: "wrap", children: [
|
|
3042
|
+
" ",
|
|
3043
|
+
comment.body.split("\n")[0]
|
|
3044
|
+
] })
|
|
3045
|
+
] }, i)
|
|
3046
|
+
)) : /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "fetching comments..." }),
|
|
3047
|
+
/* @__PURE__ */ jsx4(Text4, { children: "" }),
|
|
3048
|
+
/* @__PURE__ */ jsx4(Text4, { color: "gray", dimColor: true, children: issue.url })
|
|
3049
|
+
] });
|
|
2979
3050
|
}
|
|
2980
|
-
var SLACK_URL_RE
|
|
3051
|
+
var SLACK_URL_RE;
|
|
2981
3052
|
var init_detail_panel = __esm({
|
|
2982
3053
|
"src/board/components/detail-panel.tsx"() {
|
|
2983
3054
|
"use strict";
|
|
2984
|
-
|
|
3055
|
+
init_panel();
|
|
2985
3056
|
SLACK_URL_RE = /https:\/\/[^/]+\.slack\.com\/archives\/[A-Z0-9]+\/p[0-9]+/gi;
|
|
2986
|
-
PRIORITY_LABELS2 = {
|
|
2987
|
-
[5 /* High */]: "High",
|
|
2988
|
-
[3 /* Medium */]: "Medium",
|
|
2989
|
-
[1 /* Low */]: "Low",
|
|
2990
|
-
[0 /* None */]: "None"
|
|
2991
|
-
};
|
|
2992
3057
|
}
|
|
2993
3058
|
});
|
|
2994
3059
|
|
|
2995
3060
|
// src/board/components/hint-bar.tsx
|
|
2996
|
-
import { Box as
|
|
2997
|
-
import { jsx as
|
|
2998
|
-
function HintBar({
|
|
3061
|
+
import { Box as Box5, Text as Text5 } from "ink";
|
|
3062
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
3063
|
+
function HintBar({
|
|
3064
|
+
uiMode,
|
|
3065
|
+
activePanelId,
|
|
3066
|
+
multiSelectCount,
|
|
3067
|
+
searchQuery,
|
|
3068
|
+
mineOnly,
|
|
3069
|
+
hasUndoable
|
|
3070
|
+
}) {
|
|
2999
3071
|
if (uiMode === "multiSelect") {
|
|
3000
|
-
return /* @__PURE__ */
|
|
3001
|
-
/* @__PURE__ */
|
|
3072
|
+
return /* @__PURE__ */ jsxs5(Box5, { children: [
|
|
3073
|
+
/* @__PURE__ */ jsxs5(Text5, { color: "cyan", bold: true, children: [
|
|
3002
3074
|
"[MULTI-SELECT] ",
|
|
3003
3075
|
multiSelectCount,
|
|
3004
3076
|
" selected"
|
|
3005
3077
|
] }),
|
|
3006
|
-
/* @__PURE__ */
|
|
3078
|
+
/* @__PURE__ */ jsx5(Text5, { color: "gray", children: " Space:toggle Enter:actions Esc:cancel" })
|
|
3007
3079
|
] });
|
|
3008
3080
|
}
|
|
3009
3081
|
if (uiMode === "focus") {
|
|
3010
|
-
return /* @__PURE__ */
|
|
3082
|
+
return /* @__PURE__ */ jsx5(Box5, { children: /* @__PURE__ */ jsx5(Text5, { color: "magenta", bold: true, children: "[FOCUS] Focus mode \u2014 Esc to exit" }) });
|
|
3011
3083
|
}
|
|
3012
3084
|
if (uiMode === "search") {
|
|
3013
|
-
return /* @__PURE__ */
|
|
3014
|
-
/* @__PURE__ */
|
|
3015
|
-
/* @__PURE__ */
|
|
3016
|
-
searchQuery ? /* @__PURE__ */
|
|
3085
|
+
return /* @__PURE__ */ jsxs5(Box5, { children: [
|
|
3086
|
+
/* @__PURE__ */ jsx5(Text5, { color: "yellow", bold: true, children: "[SEARCH]" }),
|
|
3087
|
+
/* @__PURE__ */ jsx5(Text5, { color: "gray", children: " type to filter Enter:confirm Esc:clear" }),
|
|
3088
|
+
searchQuery ? /* @__PURE__ */ jsxs5(Text5, { color: "yellow", children: [
|
|
3017
3089
|
' "',
|
|
3018
3090
|
searchQuery,
|
|
3019
3091
|
'"'
|
|
@@ -3021,19 +3093,22 @@ function HintBar({ uiMode, multiSelectCount, searchQuery, mineOnly, hasUndoable
|
|
|
3021
3093
|
] });
|
|
3022
3094
|
}
|
|
3023
3095
|
if (uiMode === "overlay:fuzzyPicker") {
|
|
3024
|
-
return /* @__PURE__ */
|
|
3096
|
+
return /* @__PURE__ */ jsx5(Box5, { children: /* @__PURE__ */ jsx5(Text5, { color: "gray", children: "\u2191\u2193/Ctrl-J/K:nav Enter:jump Esc:close" }) });
|
|
3025
3097
|
}
|
|
3026
3098
|
if (uiMode.startsWith("overlay:")) {
|
|
3027
|
-
return /* @__PURE__ */
|
|
3028
|
-
}
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3099
|
+
return /* @__PURE__ */ jsx5(Box5, { children: /* @__PURE__ */ jsx5(Text5, { color: "gray", children: "j/k:nav Enter:select Esc:cancel" }) });
|
|
3100
|
+
}
|
|
3101
|
+
const panelHints = {
|
|
3102
|
+
0: "j/k:scroll Esc:close ? help",
|
|
3103
|
+
1: "j/k:move Enter:filter 0-4:panel ? help",
|
|
3104
|
+
2: "j/k:move Enter:filter Esc:clear 0-4:panel ? help",
|
|
3105
|
+
3: `j/k:move p:pick m:status c:comment /:search n:new 0-4:panel${hasUndoable ? " u:undo" : ""} ? help q:quit`,
|
|
3106
|
+
4: "j/k:scroll Enter:jump r:refresh 0-4:panel ? help"
|
|
3107
|
+
};
|
|
3108
|
+
return /* @__PURE__ */ jsxs5(Box5, { children: [
|
|
3109
|
+
/* @__PURE__ */ jsx5(Text5, { color: "gray", children: panelHints[activePanelId] }),
|
|
3110
|
+
mineOnly ? /* @__PURE__ */ jsx5(Text5, { color: "cyan", children: " filter:@me" }) : null,
|
|
3111
|
+
searchQuery ? /* @__PURE__ */ jsxs5(Text5, { color: "yellow", children: [
|
|
3037
3112
|
' filter:"',
|
|
3038
3113
|
searchQuery,
|
|
3039
3114
|
'"'
|
|
@@ -3047,9 +3122,9 @@ var init_hint_bar = __esm({
|
|
|
3047
3122
|
});
|
|
3048
3123
|
|
|
3049
3124
|
// src/board/components/bulk-action-menu.tsx
|
|
3050
|
-
import { Box as
|
|
3051
|
-
import { useState as
|
|
3052
|
-
import { jsx as
|
|
3125
|
+
import { Box as Box6, Text as Text6, useInput as useInput2 } from "ink";
|
|
3126
|
+
import { useState as useState7 } from "react";
|
|
3127
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
3053
3128
|
function getMenuItems(selectionType) {
|
|
3054
3129
|
if (selectionType === "github") {
|
|
3055
3130
|
return [
|
|
@@ -3068,7 +3143,7 @@ function getMenuItems(selectionType) {
|
|
|
3068
3143
|
}
|
|
3069
3144
|
function BulkActionMenu({ count, selectionType, onSelect, onCancel }) {
|
|
3070
3145
|
const items = getMenuItems(selectionType);
|
|
3071
|
-
const [selectedIdx, setSelectedIdx] =
|
|
3146
|
+
const [selectedIdx, setSelectedIdx] = useState7(0);
|
|
3072
3147
|
useInput2((input2, key) => {
|
|
3073
3148
|
if (key.escape) return onCancel();
|
|
3074
3149
|
if (key.return) {
|
|
@@ -3084,13 +3159,13 @@ function BulkActionMenu({ count, selectionType, onSelect, onCancel }) {
|
|
|
3084
3159
|
}
|
|
3085
3160
|
});
|
|
3086
3161
|
if (items.length === 0) {
|
|
3087
|
-
return /* @__PURE__ */
|
|
3088
|
-
/* @__PURE__ */
|
|
3089
|
-
/* @__PURE__ */
|
|
3162
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
3163
|
+
/* @__PURE__ */ jsx6(Text6, { color: "yellow", children: "No bulk actions for mixed selection types." }),
|
|
3164
|
+
/* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Esc to cancel" })
|
|
3090
3165
|
] });
|
|
3091
3166
|
}
|
|
3092
|
-
return /* @__PURE__ */
|
|
3093
|
-
/* @__PURE__ */
|
|
3167
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
3168
|
+
/* @__PURE__ */ jsxs6(Text6, { color: "cyan", bold: true, children: [
|
|
3094
3169
|
"Bulk action (",
|
|
3095
3170
|
count,
|
|
3096
3171
|
" selected):"
|
|
@@ -3098,12 +3173,12 @@ function BulkActionMenu({ count, selectionType, onSelect, onCancel }) {
|
|
|
3098
3173
|
items.map((item, i) => {
|
|
3099
3174
|
const isSelected = i === selectedIdx;
|
|
3100
3175
|
const prefix = isSelected ? "> " : " ";
|
|
3101
|
-
return /* @__PURE__ */
|
|
3176
|
+
return /* @__PURE__ */ jsxs6(Text6, { ...isSelected ? { color: "cyan" } : {}, children: [
|
|
3102
3177
|
prefix,
|
|
3103
3178
|
item.label
|
|
3104
3179
|
] }, item.action.type);
|
|
3105
3180
|
}),
|
|
3106
|
-
/* @__PURE__ */
|
|
3181
|
+
/* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "j/k:navigate Enter:select Esc:cancel" })
|
|
3107
3182
|
] });
|
|
3108
3183
|
}
|
|
3109
3184
|
var init_bulk_action_menu = __esm({
|
|
@@ -3133,9 +3208,9 @@ import { mkdtempSync, readFileSync as readFileSync4, rmSync, writeFileSync as wr
|
|
|
3133
3208
|
import { tmpdir } from "os";
|
|
3134
3209
|
import { join as join4 } from "path";
|
|
3135
3210
|
import { TextInput } from "@inkjs/ui";
|
|
3136
|
-
import { Box as
|
|
3137
|
-
import { useEffect as useEffect4, useRef as useRef7, useState as
|
|
3138
|
-
import { jsx as
|
|
3211
|
+
import { Box as Box7, Text as Text7, useInput as useInput3, useStdin } from "ink";
|
|
3212
|
+
import { useEffect as useEffect4, useRef as useRef7, useState as useState8 } from "react";
|
|
3213
|
+
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
3139
3214
|
function CommentInput({
|
|
3140
3215
|
issueNumber,
|
|
3141
3216
|
onSubmit,
|
|
@@ -3143,8 +3218,8 @@ function CommentInput({
|
|
|
3143
3218
|
onPauseRefresh,
|
|
3144
3219
|
onResumeRefresh
|
|
3145
3220
|
}) {
|
|
3146
|
-
const [value, setValue] =
|
|
3147
|
-
const [editing, setEditing] =
|
|
3221
|
+
const [value, setValue] = useState8("");
|
|
3222
|
+
const [editing, setEditing] = useState8(false);
|
|
3148
3223
|
const { setRawMode } = useStdin();
|
|
3149
3224
|
const onSubmitRef = useRef7(onSubmit);
|
|
3150
3225
|
const onCancelRef = useRef7(onCancel);
|
|
@@ -3202,19 +3277,19 @@ function CommentInput({
|
|
|
3202
3277
|
}
|
|
3203
3278
|
}, [editing, value, setRawMode]);
|
|
3204
3279
|
if (editing) {
|
|
3205
|
-
return /* @__PURE__ */
|
|
3280
|
+
return /* @__PURE__ */ jsx7(Box7, { children: /* @__PURE__ */ jsxs7(Text7, { color: "cyan", children: [
|
|
3206
3281
|
"Opening editor for #",
|
|
3207
3282
|
issueNumber,
|
|
3208
3283
|
"\u2026"
|
|
3209
3284
|
] }) });
|
|
3210
3285
|
}
|
|
3211
|
-
return /* @__PURE__ */
|
|
3212
|
-
/* @__PURE__ */
|
|
3286
|
+
return /* @__PURE__ */ jsxs7(Box7, { children: [
|
|
3287
|
+
/* @__PURE__ */ jsxs7(Text7, { color: "cyan", children: [
|
|
3213
3288
|
"comment #",
|
|
3214
3289
|
issueNumber,
|
|
3215
3290
|
": "
|
|
3216
3291
|
] }),
|
|
3217
|
-
/* @__PURE__ */
|
|
3292
|
+
/* @__PURE__ */ jsx7(
|
|
3218
3293
|
TextInput,
|
|
3219
3294
|
{
|
|
3220
3295
|
defaultValue: value,
|
|
@@ -3236,16 +3311,16 @@ var init_comment_input = __esm({
|
|
|
3236
3311
|
});
|
|
3237
3312
|
|
|
3238
3313
|
// src/board/components/confirm-prompt.tsx
|
|
3239
|
-
import { Box as
|
|
3240
|
-
import { jsx as
|
|
3314
|
+
import { Box as Box8, Text as Text8, useInput as useInput4 } from "ink";
|
|
3315
|
+
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
3241
3316
|
function ConfirmPrompt({ message, onConfirm, onCancel }) {
|
|
3242
3317
|
useInput4((input2, key) => {
|
|
3243
3318
|
if (input2 === "y" || input2 === "Y") return onConfirm();
|
|
3244
3319
|
if (input2 === "n" || input2 === "N" || key.escape) return onCancel();
|
|
3245
3320
|
});
|
|
3246
|
-
return /* @__PURE__ */
|
|
3247
|
-
/* @__PURE__ */
|
|
3248
|
-
/* @__PURE__ */
|
|
3321
|
+
return /* @__PURE__ */ jsxs8(Box8, { children: [
|
|
3322
|
+
/* @__PURE__ */ jsx8(Text8, { color: "cyan", children: message }),
|
|
3323
|
+
/* @__PURE__ */ jsx8(Text8, { color: "gray", children: " (y/n)" })
|
|
3249
3324
|
] });
|
|
3250
3325
|
}
|
|
3251
3326
|
var init_confirm_prompt = __esm({
|
|
@@ -3256,9 +3331,9 @@ var init_confirm_prompt = __esm({
|
|
|
3256
3331
|
|
|
3257
3332
|
// src/board/components/label-picker.tsx
|
|
3258
3333
|
import { Spinner } from "@inkjs/ui";
|
|
3259
|
-
import { Box as
|
|
3260
|
-
import { useEffect as useEffect5, useRef as useRef8, useState as
|
|
3261
|
-
import { jsx as
|
|
3334
|
+
import { Box as Box9, Text as Text9, useInput as useInput5 } from "ink";
|
|
3335
|
+
import { useEffect as useEffect5, useRef as useRef8, useState as useState9 } from "react";
|
|
3336
|
+
import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
3262
3337
|
function LabelPicker({
|
|
3263
3338
|
repo,
|
|
3264
3339
|
currentLabels,
|
|
@@ -3267,11 +3342,11 @@ function LabelPicker({
|
|
|
3267
3342
|
onCancel,
|
|
3268
3343
|
onError
|
|
3269
3344
|
}) {
|
|
3270
|
-
const [labels, setLabels] =
|
|
3271
|
-
const [loading, setLoading] =
|
|
3272
|
-
const [fetchAttempted, setFetchAttempted] =
|
|
3273
|
-
const [selected, setSelected] =
|
|
3274
|
-
const [cursor, setCursor] =
|
|
3345
|
+
const [labels, setLabels] = useState9(labelCache[repo] ?? null);
|
|
3346
|
+
const [loading, setLoading] = useState9(labels === null);
|
|
3347
|
+
const [fetchAttempted, setFetchAttempted] = useState9(false);
|
|
3348
|
+
const [selected, setSelected] = useState9(new Set(currentLabels));
|
|
3349
|
+
const [cursor, setCursor] = useState9(0);
|
|
3275
3350
|
const submittedRef = useRef8(false);
|
|
3276
3351
|
useEffect5(() => {
|
|
3277
3352
|
if (labels !== null || fetchAttempted) return;
|
|
@@ -3333,21 +3408,21 @@ function LabelPicker({
|
|
|
3333
3408
|
}
|
|
3334
3409
|
});
|
|
3335
3410
|
if (loading) {
|
|
3336
|
-
return /* @__PURE__ */
|
|
3411
|
+
return /* @__PURE__ */ jsx9(Box9, { children: /* @__PURE__ */ jsx9(Spinner, { label: "Fetching labels..." }) });
|
|
3337
3412
|
}
|
|
3338
3413
|
const allLabels = labels ?? [];
|
|
3339
3414
|
if (allLabels.length === 0) {
|
|
3340
|
-
return /* @__PURE__ */
|
|
3341
|
-
/* @__PURE__ */
|
|
3342
|
-
/* @__PURE__ */
|
|
3343
|
-
/* @__PURE__ */
|
|
3415
|
+
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
|
|
3416
|
+
/* @__PURE__ */ jsx9(Text9, { color: "cyan", bold: true, children: "Labels:" }),
|
|
3417
|
+
/* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "No labels in this repo" }),
|
|
3418
|
+
/* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "Esc:cancel" })
|
|
3344
3419
|
] });
|
|
3345
3420
|
}
|
|
3346
3421
|
const repoLabelNames = new Set(allLabels.map((l) => l.name));
|
|
3347
3422
|
const orphanedLabels = currentLabels.filter((l) => !repoLabelNames.has(l));
|
|
3348
|
-
return /* @__PURE__ */
|
|
3349
|
-
/* @__PURE__ */
|
|
3350
|
-
orphanedLabels.map((name) => /* @__PURE__ */
|
|
3423
|
+
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
|
|
3424
|
+
/* @__PURE__ */ jsx9(Text9, { color: "cyan", bold: true, children: "Labels (Space:toggle Enter:confirm Esc:cancel):" }),
|
|
3425
|
+
orphanedLabels.map((name) => /* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
|
|
3351
3426
|
selected.has(name) ? "[x]" : "[ ]",
|
|
3352
3427
|
" ",
|
|
3353
3428
|
name,
|
|
@@ -3356,7 +3431,7 @@ function LabelPicker({
|
|
|
3356
3431
|
allLabels.map((label, i) => {
|
|
3357
3432
|
const isSel = i === cursor;
|
|
3358
3433
|
const isChecked = selected.has(label.name);
|
|
3359
|
-
return /* @__PURE__ */
|
|
3434
|
+
return /* @__PURE__ */ jsxs9(Text9, { ...isSel ? { color: "cyan" } : {}, children: [
|
|
3360
3435
|
isSel ? ">" : " ",
|
|
3361
3436
|
" ",
|
|
3362
3437
|
isChecked ? "[x]" : "[ ]",
|
|
@@ -3375,9 +3450,9 @@ var init_label_picker = __esm({
|
|
|
3375
3450
|
|
|
3376
3451
|
// src/board/components/create-issue-form.tsx
|
|
3377
3452
|
import { TextInput as TextInput2 } from "@inkjs/ui";
|
|
3378
|
-
import { Box as
|
|
3379
|
-
import { useState as
|
|
3380
|
-
import { jsx as
|
|
3453
|
+
import { Box as Box10, Text as Text10, useInput as useInput6 } from "ink";
|
|
3454
|
+
import { useState as useState10 } from "react";
|
|
3455
|
+
import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
3381
3456
|
function CreateIssueForm({
|
|
3382
3457
|
repos,
|
|
3383
3458
|
defaultRepo,
|
|
@@ -3389,9 +3464,9 @@ function CreateIssueForm({
|
|
|
3389
3464
|
0,
|
|
3390
3465
|
repos.findIndex((r) => r.name === defaultRepo)
|
|
3391
3466
|
) : 0;
|
|
3392
|
-
const [repoIdx, setRepoIdx] =
|
|
3393
|
-
const [title, setTitle] =
|
|
3394
|
-
const [field, setField] =
|
|
3467
|
+
const [repoIdx, setRepoIdx] = useState10(defaultRepoIdx);
|
|
3468
|
+
const [title, setTitle] = useState10("");
|
|
3469
|
+
const [field, setField] = useState10("title");
|
|
3395
3470
|
useInput6((input2, key) => {
|
|
3396
3471
|
if (field === "labels") return;
|
|
3397
3472
|
if (key.escape) return onCancel();
|
|
@@ -3408,15 +3483,15 @@ function CreateIssueForm({
|
|
|
3408
3483
|
});
|
|
3409
3484
|
const selectedRepo = repos[repoIdx];
|
|
3410
3485
|
if (field === "labels" && selectedRepo) {
|
|
3411
|
-
return /* @__PURE__ */
|
|
3412
|
-
/* @__PURE__ */
|
|
3413
|
-
/* @__PURE__ */
|
|
3486
|
+
return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
|
|
3487
|
+
/* @__PURE__ */ jsx10(Text10, { color: "cyan", bold: true, children: "Create Issue \u2014 Add Labels (optional)" }),
|
|
3488
|
+
/* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
|
|
3414
3489
|
"Repo: ",
|
|
3415
3490
|
selectedRepo.shortName,
|
|
3416
3491
|
" Title: ",
|
|
3417
3492
|
title
|
|
3418
3493
|
] }),
|
|
3419
|
-
/* @__PURE__ */
|
|
3494
|
+
/* @__PURE__ */ jsx10(
|
|
3420
3495
|
LabelPicker,
|
|
3421
3496
|
{
|
|
3422
3497
|
repo: selectedRepo.name,
|
|
@@ -3441,12 +3516,12 @@ function CreateIssueForm({
|
|
|
3441
3516
|
)
|
|
3442
3517
|
] });
|
|
3443
3518
|
}
|
|
3444
|
-
return /* @__PURE__ */
|
|
3445
|
-
/* @__PURE__ */
|
|
3446
|
-
/* @__PURE__ */
|
|
3447
|
-
/* @__PURE__ */
|
|
3448
|
-
repos.map((r, i) => /* @__PURE__ */
|
|
3449
|
-
|
|
3519
|
+
return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
|
|
3520
|
+
/* @__PURE__ */ jsx10(Text10, { color: "cyan", bold: true, children: "Create Issue" }),
|
|
3521
|
+
/* @__PURE__ */ jsxs10(Box10, { children: [
|
|
3522
|
+
/* @__PURE__ */ jsx10(Text10, { dimColor: field !== "repo", children: "Repo: " }),
|
|
3523
|
+
repos.map((r, i) => /* @__PURE__ */ jsx10(
|
|
3524
|
+
Text10,
|
|
3450
3525
|
{
|
|
3451
3526
|
...i === repoIdx ? { color: "cyan", bold: true } : {},
|
|
3452
3527
|
dimColor: field !== "repo",
|
|
@@ -3454,11 +3529,11 @@ function CreateIssueForm({
|
|
|
3454
3529
|
},
|
|
3455
3530
|
r.name
|
|
3456
3531
|
)),
|
|
3457
|
-
field === "repo" ? /* @__PURE__ */
|
|
3532
|
+
field === "repo" ? /* @__PURE__ */ jsx10(Text10, { dimColor: true, children: " j/k:select Tab:next" }) : null
|
|
3458
3533
|
] }),
|
|
3459
|
-
/* @__PURE__ */
|
|
3460
|
-
/* @__PURE__ */
|
|
3461
|
-
field === "title" ? /* @__PURE__ */
|
|
3534
|
+
/* @__PURE__ */ jsxs10(Box10, { children: [
|
|
3535
|
+
/* @__PURE__ */ jsx10(Text10, { dimColor: field !== "title", children: "Title: " }),
|
|
3536
|
+
field === "title" ? /* @__PURE__ */ jsx10(
|
|
3462
3537
|
TextInput2,
|
|
3463
3538
|
{
|
|
3464
3539
|
defaultValue: title,
|
|
@@ -3475,9 +3550,9 @@ function CreateIssueForm({
|
|
|
3475
3550
|
}
|
|
3476
3551
|
}
|
|
3477
3552
|
}
|
|
3478
|
-
) : /* @__PURE__ */
|
|
3553
|
+
) : /* @__PURE__ */ jsx10(Text10, { children: title || "(empty)" })
|
|
3479
3554
|
] }),
|
|
3480
|
-
/* @__PURE__ */
|
|
3555
|
+
/* @__PURE__ */ jsx10(Text10, { dimColor: true, children: "Tab:switch fields Enter:next Esc:cancel" })
|
|
3481
3556
|
] });
|
|
3482
3557
|
}
|
|
3483
3558
|
var init_create_issue_form = __esm({
|
|
@@ -3492,9 +3567,9 @@ import { spawnSync as spawnSync2 } from "child_process";
|
|
|
3492
3567
|
import { mkdtempSync as mkdtempSync2, readFileSync as readFileSync5, rmSync as rmSync2, writeFileSync as writeFileSync5 } from "fs";
|
|
3493
3568
|
import { tmpdir as tmpdir2 } from "os";
|
|
3494
3569
|
import { join as join5 } from "path";
|
|
3495
|
-
import { Box as
|
|
3496
|
-
import { useEffect as useEffect6, useRef as useRef9, useState as
|
|
3497
|
-
import { jsx as
|
|
3570
|
+
import { Box as Box11, Text as Text11, useStdin as useStdin2 } from "ink";
|
|
3571
|
+
import { useEffect as useEffect6, useRef as useRef9, useState as useState11 } from "react";
|
|
3572
|
+
import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
3498
3573
|
function buildEditorFile(issue, repoName, statusOptions, repoLabels) {
|
|
3499
3574
|
const statusNames = statusOptions.map((o) => o.name).join(", ");
|
|
3500
3575
|
const labelNames = repoLabels.map((l) => l.name).join(", ");
|
|
@@ -3577,7 +3652,7 @@ function EditIssueOverlay({
|
|
|
3577
3652
|
onToastError,
|
|
3578
3653
|
onPushEntry
|
|
3579
3654
|
}) {
|
|
3580
|
-
const [editing, setEditing] =
|
|
3655
|
+
const [editing, setEditing] = useState11(true);
|
|
3581
3656
|
const { setRawMode } = useStdin2();
|
|
3582
3657
|
const onDoneRef = useRef9(onDone);
|
|
3583
3658
|
const onPauseRef = useRef9(onPauseRefresh);
|
|
@@ -3736,7 +3811,7 @@ function EditIssueOverlay({
|
|
|
3736
3811
|
onPushEntry
|
|
3737
3812
|
]);
|
|
3738
3813
|
if (!editing) return null;
|
|
3739
|
-
return /* @__PURE__ */
|
|
3814
|
+
return /* @__PURE__ */ jsx11(Box11, { children: /* @__PURE__ */ jsxs11(Text11, { color: "cyan", children: [
|
|
3740
3815
|
"Opening editor for #",
|
|
3741
3816
|
issue.number,
|
|
3742
3817
|
"\u2026"
|
|
@@ -3752,17 +3827,17 @@ var init_edit_issue_overlay = __esm({
|
|
|
3752
3827
|
});
|
|
3753
3828
|
|
|
3754
3829
|
// src/board/components/focus-mode.tsx
|
|
3755
|
-
import { Box as
|
|
3756
|
-
import { useCallback as
|
|
3757
|
-
import { jsx as
|
|
3830
|
+
import { Box as Box12, Text as Text12, useInput as useInput7 } from "ink";
|
|
3831
|
+
import { useCallback as useCallback10, useEffect as useEffect7, useRef as useRef10, useState as useState12 } from "react";
|
|
3832
|
+
import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
3758
3833
|
function formatTime(secs) {
|
|
3759
3834
|
const m = Math.floor(secs / 60);
|
|
3760
3835
|
const s = secs % 60;
|
|
3761
3836
|
return `${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`;
|
|
3762
3837
|
}
|
|
3763
3838
|
function FocusMode({ label, durationSec, onExit, onEndAction }) {
|
|
3764
|
-
const [remaining, setRemaining] =
|
|
3765
|
-
const [timerDone, setTimerDone] =
|
|
3839
|
+
const [remaining, setRemaining] = useState12(durationSec);
|
|
3840
|
+
const [timerDone, setTimerDone] = useState12(false);
|
|
3766
3841
|
const bellSentRef = useRef10(false);
|
|
3767
3842
|
useEffect7(() => {
|
|
3768
3843
|
if (timerDone) return;
|
|
@@ -3784,7 +3859,7 @@ function FocusMode({ label, durationSec, onExit, onEndAction }) {
|
|
|
3784
3859
|
process.stdout.write("\x07");
|
|
3785
3860
|
}
|
|
3786
3861
|
}, [timerDone]);
|
|
3787
|
-
const handleInput =
|
|
3862
|
+
const handleInput = useCallback10(
|
|
3788
3863
|
(input2, key) => {
|
|
3789
3864
|
if (key.escape) {
|
|
3790
3865
|
if (timerDone) {
|
|
@@ -3811,23 +3886,23 @@ function FocusMode({ label, durationSec, onExit, onEndAction }) {
|
|
|
3811
3886
|
);
|
|
3812
3887
|
useInput7(handleInput);
|
|
3813
3888
|
if (timerDone) {
|
|
3814
|
-
return /* @__PURE__ */
|
|
3815
|
-
/* @__PURE__ */
|
|
3816
|
-
/* @__PURE__ */
|
|
3817
|
-
/* @__PURE__ */
|
|
3889
|
+
return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", children: [
|
|
3890
|
+
/* @__PURE__ */ jsxs12(Box12, { children: [
|
|
3891
|
+
/* @__PURE__ */ jsx12(Text12, { color: "green", bold: true, children: "Focus complete!" }),
|
|
3892
|
+
/* @__PURE__ */ jsxs12(Text12, { color: "gray", children: [
|
|
3818
3893
|
" ",
|
|
3819
3894
|
label
|
|
3820
3895
|
] })
|
|
3821
3896
|
] }),
|
|
3822
|
-
/* @__PURE__ */
|
|
3823
|
-
/* @__PURE__ */
|
|
3824
|
-
/* @__PURE__ */
|
|
3825
|
-
/* @__PURE__ */
|
|
3826
|
-
/* @__PURE__ */
|
|
3827
|
-
/* @__PURE__ */
|
|
3828
|
-
/* @__PURE__ */
|
|
3829
|
-
/* @__PURE__ */
|
|
3830
|
-
/* @__PURE__ */
|
|
3897
|
+
/* @__PURE__ */ jsxs12(Box12, { marginTop: 1, children: [
|
|
3898
|
+
/* @__PURE__ */ jsx12(Text12, { color: "cyan", children: "[c]" }),
|
|
3899
|
+
/* @__PURE__ */ jsx12(Text12, { children: " Continue " }),
|
|
3900
|
+
/* @__PURE__ */ jsx12(Text12, { color: "cyan", children: "[b]" }),
|
|
3901
|
+
/* @__PURE__ */ jsx12(Text12, { children: " Break " }),
|
|
3902
|
+
/* @__PURE__ */ jsx12(Text12, { color: "cyan", children: "[d]" }),
|
|
3903
|
+
/* @__PURE__ */ jsx12(Text12, { children: " Done " }),
|
|
3904
|
+
/* @__PURE__ */ jsx12(Text12, { color: "gray", children: "[Esc]" }),
|
|
3905
|
+
/* @__PURE__ */ jsx12(Text12, { children: " Exit" })
|
|
3831
3906
|
] })
|
|
3832
3907
|
] });
|
|
3833
3908
|
}
|
|
@@ -3835,21 +3910,21 @@ function FocusMode({ label, durationSec, onExit, onEndAction }) {
|
|
|
3835
3910
|
const barWidth = 20;
|
|
3836
3911
|
const filled = Math.round(progress * barWidth);
|
|
3837
3912
|
const bar = "\u2588".repeat(filled) + "\u2591".repeat(barWidth - filled);
|
|
3838
|
-
return /* @__PURE__ */
|
|
3839
|
-
/* @__PURE__ */
|
|
3840
|
-
/* @__PURE__ */
|
|
3913
|
+
return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", children: [
|
|
3914
|
+
/* @__PURE__ */ jsxs12(Box12, { children: [
|
|
3915
|
+
/* @__PURE__ */ jsxs12(Text12, { color: "magenta", bold: true, children: [
|
|
3841
3916
|
"Focus:",
|
|
3842
3917
|
" "
|
|
3843
3918
|
] }),
|
|
3844
|
-
/* @__PURE__ */
|
|
3919
|
+
/* @__PURE__ */ jsx12(Text12, { children: label })
|
|
3845
3920
|
] }),
|
|
3846
|
-
/* @__PURE__ */
|
|
3847
|
-
/* @__PURE__ */
|
|
3848
|
-
/* @__PURE__ */
|
|
3849
|
-
/* @__PURE__ */
|
|
3850
|
-
/* @__PURE__ */
|
|
3921
|
+
/* @__PURE__ */ jsxs12(Box12, { children: [
|
|
3922
|
+
/* @__PURE__ */ jsx12(Text12, { color: "magenta", children: bar }),
|
|
3923
|
+
/* @__PURE__ */ jsx12(Text12, { children: " " }),
|
|
3924
|
+
/* @__PURE__ */ jsx12(Text12, { bold: true, children: formatTime(remaining) }),
|
|
3925
|
+
/* @__PURE__ */ jsx12(Text12, { color: "gray", children: " remaining" })
|
|
3851
3926
|
] }),
|
|
3852
|
-
/* @__PURE__ */
|
|
3927
|
+
/* @__PURE__ */ jsx12(Text12, { color: "gray", dimColor: true, children: "Esc to exit focus" })
|
|
3853
3928
|
] });
|
|
3854
3929
|
}
|
|
3855
3930
|
var init_focus_mode = __esm({
|
|
@@ -3861,18 +3936,18 @@ var init_focus_mode = __esm({
|
|
|
3861
3936
|
// src/board/components/fuzzy-picker.tsx
|
|
3862
3937
|
import { TextInput as TextInput3 } from "@inkjs/ui";
|
|
3863
3938
|
import { Fzf } from "fzf";
|
|
3864
|
-
import { Box as
|
|
3865
|
-
import { useMemo as useMemo2, useState as
|
|
3866
|
-
import { jsx as
|
|
3939
|
+
import { Box as Box13, Text as Text13, useInput as useInput8 } from "ink";
|
|
3940
|
+
import { useMemo as useMemo2, useState as useState13 } from "react";
|
|
3941
|
+
import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
3867
3942
|
function keepCursorVisible(cursor, offset, visible) {
|
|
3868
3943
|
if (cursor < offset) return cursor;
|
|
3869
3944
|
if (cursor >= offset + visible) return cursor - visible + 1;
|
|
3870
3945
|
return offset;
|
|
3871
3946
|
}
|
|
3872
3947
|
function FuzzyPicker({ repos, onSelect, onClose }) {
|
|
3873
|
-
const [query, setQuery] =
|
|
3874
|
-
const [cursor, setCursor] =
|
|
3875
|
-
const [scrollOffset, setScrollOffset] =
|
|
3948
|
+
const [query, setQuery] = useState13("");
|
|
3949
|
+
const [cursor, setCursor] = useState13(0);
|
|
3950
|
+
const [scrollOffset, setScrollOffset] = useState13(0);
|
|
3876
3951
|
const allIssues = useMemo2(() => {
|
|
3877
3952
|
const items = [];
|
|
3878
3953
|
for (const rd of repos) {
|
|
@@ -3955,13 +4030,13 @@ function FuzzyPicker({ repos, onSelect, onClose }) {
|
|
|
3955
4030
|
});
|
|
3956
4031
|
const visibleResults = results.slice(scrollOffset, scrollOffset + VISIBLE);
|
|
3957
4032
|
const totalCount = results.length;
|
|
3958
|
-
return /* @__PURE__ */
|
|
3959
|
-
/* @__PURE__ */
|
|
3960
|
-
/* @__PURE__ */
|
|
4033
|
+
return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
|
|
4034
|
+
/* @__PURE__ */ jsxs13(Box13, { children: [
|
|
4035
|
+
/* @__PURE__ */ jsxs13(Text13, { color: "cyan", bold: true, children: [
|
|
3961
4036
|
"Find issue",
|
|
3962
4037
|
" "
|
|
3963
4038
|
] }),
|
|
3964
|
-
/* @__PURE__ */
|
|
4039
|
+
/* @__PURE__ */ jsxs13(Text13, { color: "gray", children: [
|
|
3965
4040
|
"(",
|
|
3966
4041
|
totalCount,
|
|
3967
4042
|
" match",
|
|
@@ -3969,14 +4044,14 @@ function FuzzyPicker({ repos, onSelect, onClose }) {
|
|
|
3969
4044
|
")",
|
|
3970
4045
|
" "
|
|
3971
4046
|
] }),
|
|
3972
|
-
/* @__PURE__ */
|
|
4047
|
+
/* @__PURE__ */ jsx13(Text13, { color: "gray", dimColor: true, children: "\u2191\u2193/Ctrl-J/K nav Enter:jump Esc:close" })
|
|
3973
4048
|
] }),
|
|
3974
|
-
/* @__PURE__ */
|
|
3975
|
-
/* @__PURE__ */
|
|
4049
|
+
/* @__PURE__ */ jsxs13(Box13, { children: [
|
|
4050
|
+
/* @__PURE__ */ jsxs13(Text13, { color: "yellow", children: [
|
|
3976
4051
|
">",
|
|
3977
4052
|
" "
|
|
3978
4053
|
] }),
|
|
3979
|
-
/* @__PURE__ */
|
|
4054
|
+
/* @__PURE__ */ jsx13(
|
|
3980
4055
|
TextInput3,
|
|
3981
4056
|
{
|
|
3982
4057
|
defaultValue: query,
|
|
@@ -3993,7 +4068,7 @@ function FuzzyPicker({ repos, onSelect, onClose }) {
|
|
|
3993
4068
|
}
|
|
3994
4069
|
)
|
|
3995
4070
|
] }),
|
|
3996
|
-
scrollOffset > 0 ? /* @__PURE__ */
|
|
4071
|
+
scrollOffset > 0 ? /* @__PURE__ */ jsxs13(Text13, { color: "gray", dimColor: true, children: [
|
|
3997
4072
|
"\u25B2 ",
|
|
3998
4073
|
scrollOffset,
|
|
3999
4074
|
" more above"
|
|
@@ -4002,7 +4077,7 @@ function FuzzyPicker({ repos, onSelect, onClose }) {
|
|
|
4002
4077
|
const isSelected = scrollOffset + idx === cursor;
|
|
4003
4078
|
const labelStr = issue.labels ? ` [${issue.labels.split(" ").slice(0, 2).join("] [")}]` : "";
|
|
4004
4079
|
const assigneeStr = issue.assignee ? ` @${issue.assignee.split(" ")[0]}` : "";
|
|
4005
|
-
return /* @__PURE__ */
|
|
4080
|
+
return /* @__PURE__ */ jsx13(Box13, { children: isSelected ? /* @__PURE__ */ jsxs13(Text13, { color: "cyan", bold: true, children: [
|
|
4006
4081
|
">",
|
|
4007
4082
|
" ",
|
|
4008
4083
|
issue.repoShortName,
|
|
@@ -4012,7 +4087,7 @@ function FuzzyPicker({ repos, onSelect, onClose }) {
|
|
|
4012
4087
|
issue.title,
|
|
4013
4088
|
labelStr,
|
|
4014
4089
|
assigneeStr
|
|
4015
|
-
] }) : /* @__PURE__ */
|
|
4090
|
+
] }) : /* @__PURE__ */ jsxs13(Text13, { children: [
|
|
4016
4091
|
" ",
|
|
4017
4092
|
issue.repoShortName,
|
|
4018
4093
|
"#",
|
|
@@ -4023,12 +4098,12 @@ function FuzzyPicker({ repos, onSelect, onClose }) {
|
|
|
4023
4098
|
assigneeStr
|
|
4024
4099
|
] }) }, issue.navId);
|
|
4025
4100
|
}),
|
|
4026
|
-
totalCount === 0 ? /* @__PURE__ */
|
|
4101
|
+
totalCount === 0 ? /* @__PURE__ */ jsxs13(Text13, { dimColor: true, children: [
|
|
4027
4102
|
'No issues match "',
|
|
4028
4103
|
query,
|
|
4029
4104
|
'"'
|
|
4030
4105
|
] }) : null,
|
|
4031
|
-
results.length > scrollOffset + VISIBLE ? /* @__PURE__ */
|
|
4106
|
+
results.length > scrollOffset + VISIBLE ? /* @__PURE__ */ jsxs13(Text13, { color: "gray", dimColor: true, children: [
|
|
4032
4107
|
"\u25BC ",
|
|
4033
4108
|
results.length - scrollOffset - VISIBLE,
|
|
4034
4109
|
" more below"
|
|
@@ -4042,29 +4117,29 @@ var init_fuzzy_picker = __esm({
|
|
|
4042
4117
|
});
|
|
4043
4118
|
|
|
4044
4119
|
// src/board/components/help-overlay.tsx
|
|
4045
|
-
import { Box as
|
|
4046
|
-
import { jsx as
|
|
4120
|
+
import { Box as Box14, Text as Text14, useInput as useInput9 } from "ink";
|
|
4121
|
+
import { jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
4047
4122
|
function HelpOverlay({ currentMode, onClose }) {
|
|
4048
4123
|
useInput9((_input, key) => {
|
|
4049
4124
|
if (key.escape) onClose();
|
|
4050
4125
|
});
|
|
4051
|
-
return /* @__PURE__ */
|
|
4052
|
-
/* @__PURE__ */
|
|
4053
|
-
/* @__PURE__ */
|
|
4054
|
-
/* @__PURE__ */
|
|
4126
|
+
return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
|
|
4127
|
+
/* @__PURE__ */ jsxs14(Box14, { justifyContent: "space-between", children: [
|
|
4128
|
+
/* @__PURE__ */ jsx14(Text14, { color: "cyan", bold: true, children: "Keyboard Shortcuts" }),
|
|
4129
|
+
/* @__PURE__ */ jsxs14(Text14, { dimColor: true, children: [
|
|
4055
4130
|
"mode: ",
|
|
4056
4131
|
currentMode
|
|
4057
4132
|
] })
|
|
4058
4133
|
] }),
|
|
4059
|
-
/* @__PURE__ */
|
|
4060
|
-
SHORTCUTS.map((group) => /* @__PURE__ */
|
|
4061
|
-
/* @__PURE__ */
|
|
4062
|
-
group.items.map((item) => /* @__PURE__ */
|
|
4063
|
-
/* @__PURE__ */
|
|
4064
|
-
/* @__PURE__ */
|
|
4134
|
+
/* @__PURE__ */ jsx14(Text14, { children: " " }),
|
|
4135
|
+
SHORTCUTS.map((group) => /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", marginBottom: 1, children: [
|
|
4136
|
+
/* @__PURE__ */ jsx14(Text14, { color: "yellow", bold: true, children: group.category }),
|
|
4137
|
+
group.items.map((item) => /* @__PURE__ */ jsxs14(Box14, { children: [
|
|
4138
|
+
/* @__PURE__ */ jsx14(Box14, { width: 16, children: /* @__PURE__ */ jsx14(Text14, { color: "green", children: item.key }) }),
|
|
4139
|
+
/* @__PURE__ */ jsx14(Text14, { children: item.desc })
|
|
4065
4140
|
] }, item.key))
|
|
4066
4141
|
] }, group.category)),
|
|
4067
|
-
/* @__PURE__ */
|
|
4142
|
+
/* @__PURE__ */ jsx14(Text14, { dimColor: true, children: "Press ? or Esc to close" })
|
|
4068
4143
|
] });
|
|
4069
4144
|
}
|
|
4070
4145
|
var SHORTCUTS;
|
|
@@ -4130,9 +4205,9 @@ import { mkdtempSync as mkdtempSync3, readFileSync as readFileSync6, rmSync as r
|
|
|
4130
4205
|
import { tmpdir as tmpdir3 } from "os";
|
|
4131
4206
|
import { join as join6 } from "path";
|
|
4132
4207
|
import { Spinner as Spinner2, TextInput as TextInput4 } from "@inkjs/ui";
|
|
4133
|
-
import { Box as
|
|
4134
|
-
import { useCallback as
|
|
4135
|
-
import { jsx as
|
|
4208
|
+
import { Box as Box15, Text as Text15, useInput as useInput10, useStdin as useStdin3 } from "ink";
|
|
4209
|
+
import { useCallback as useCallback11, useEffect as useEffect8, useRef as useRef11, useState as useState14 } from "react";
|
|
4210
|
+
import { jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
4136
4211
|
function NlCreateOverlay({
|
|
4137
4212
|
repos,
|
|
4138
4213
|
defaultRepoName,
|
|
@@ -4143,13 +4218,13 @@ function NlCreateOverlay({
|
|
|
4143
4218
|
onResumeRefresh,
|
|
4144
4219
|
onLlmFallback
|
|
4145
4220
|
}) {
|
|
4146
|
-
const [, setInput] =
|
|
4147
|
-
const [isParsing, setIsParsing] =
|
|
4148
|
-
const [parsed, setParsed] =
|
|
4149
|
-
const [parseError, setParseError] =
|
|
4150
|
-
const [step, setStep] =
|
|
4151
|
-
const [body, setBody] =
|
|
4152
|
-
const [editingBody, setEditingBody] =
|
|
4221
|
+
const [, setInput] = useState14("");
|
|
4222
|
+
const [isParsing, setIsParsing] = useState14(false);
|
|
4223
|
+
const [parsed, setParsed] = useState14(null);
|
|
4224
|
+
const [parseError, setParseError] = useState14(null);
|
|
4225
|
+
const [step, setStep] = useState14("input");
|
|
4226
|
+
const [body, setBody] = useState14("");
|
|
4227
|
+
const [editingBody, setEditingBody] = useState14(false);
|
|
4153
4228
|
const submittedRef = useRef11(false);
|
|
4154
4229
|
const parseParamsRef = useRef11(null);
|
|
4155
4230
|
const onSubmitRef = useRef11(onSubmit);
|
|
@@ -4165,7 +4240,7 @@ function NlCreateOverlay({
|
|
|
4165
4240
|
0,
|
|
4166
4241
|
repos.findIndex((r) => r.name === defaultRepoName)
|
|
4167
4242
|
) : 0;
|
|
4168
|
-
const [repoIdx, setRepoIdx] =
|
|
4243
|
+
const [repoIdx, setRepoIdx] = useState14(defaultRepoIdx);
|
|
4169
4244
|
const selectedRepo = repos[repoIdx];
|
|
4170
4245
|
useInput10((inputChar, key) => {
|
|
4171
4246
|
if (isParsing || editingBody) return;
|
|
@@ -4225,7 +4300,7 @@ function NlCreateOverlay({
|
|
|
4225
4300
|
setEditingBody(false);
|
|
4226
4301
|
}
|
|
4227
4302
|
}, [editingBody, body, setRawMode]);
|
|
4228
|
-
const handleInputSubmit =
|
|
4303
|
+
const handleInputSubmit = useCallback11(
|
|
4229
4304
|
(text) => {
|
|
4230
4305
|
const trimmed = text.trim();
|
|
4231
4306
|
if (!trimmed) return;
|
|
@@ -4258,27 +4333,27 @@ function NlCreateOverlay({
|
|
|
4258
4333
|
});
|
|
4259
4334
|
}, [isParsing, onLlmFallback]);
|
|
4260
4335
|
if (isParsing) {
|
|
4261
|
-
return /* @__PURE__ */
|
|
4262
|
-
/* @__PURE__ */
|
|
4263
|
-
/* @__PURE__ */
|
|
4336
|
+
return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", children: [
|
|
4337
|
+
/* @__PURE__ */ jsx15(Text15, { color: "cyan", bold: true, children: "\u2728 Creating Issue" }),
|
|
4338
|
+
/* @__PURE__ */ jsx15(Spinner2, { label: "Parsing..." })
|
|
4264
4339
|
] });
|
|
4265
4340
|
}
|
|
4266
4341
|
if (parsed && step === "body") {
|
|
4267
4342
|
if (editingBody) {
|
|
4268
|
-
return /* @__PURE__ */
|
|
4269
|
-
/* @__PURE__ */
|
|
4270
|
-
/* @__PURE__ */
|
|
4343
|
+
return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", children: [
|
|
4344
|
+
/* @__PURE__ */ jsx15(Text15, { color: "cyan", bold: true, children: "\u2728 Creating Issue" }),
|
|
4345
|
+
/* @__PURE__ */ jsx15(Text15, { color: "cyan", children: "Opening editor for body\u2026" })
|
|
4271
4346
|
] });
|
|
4272
4347
|
}
|
|
4273
|
-
return /* @__PURE__ */
|
|
4274
|
-
/* @__PURE__ */
|
|
4275
|
-
/* @__PURE__ */
|
|
4276
|
-
/* @__PURE__ */
|
|
4277
|
-
/* @__PURE__ */
|
|
4348
|
+
return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", children: [
|
|
4349
|
+
/* @__PURE__ */ jsx15(Text15, { color: "cyan", bold: true, children: "\u2728 Creating Issue" }),
|
|
4350
|
+
/* @__PURE__ */ jsxs15(Box15, { children: [
|
|
4351
|
+
/* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "Title: " }),
|
|
4352
|
+
/* @__PURE__ */ jsx15(Text15, { children: parsed.title })
|
|
4278
4353
|
] }),
|
|
4279
|
-
/* @__PURE__ */
|
|
4280
|
-
/* @__PURE__ */
|
|
4281
|
-
/* @__PURE__ */
|
|
4354
|
+
/* @__PURE__ */ jsxs15(Box15, { children: [
|
|
4355
|
+
/* @__PURE__ */ jsx15(Text15, { color: "cyan", children: "body: " }),
|
|
4356
|
+
/* @__PURE__ */ jsx15(
|
|
4282
4357
|
TextInput4,
|
|
4283
4358
|
{
|
|
4284
4359
|
defaultValue: body,
|
|
@@ -4300,45 +4375,45 @@ function NlCreateOverlay({
|
|
|
4300
4375
|
}
|
|
4301
4376
|
)
|
|
4302
4377
|
] }),
|
|
4303
|
-
/* @__PURE__ */
|
|
4378
|
+
/* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "Enter:create ctrl+e:editor Esc:back" })
|
|
4304
4379
|
] });
|
|
4305
4380
|
}
|
|
4306
4381
|
if (parsed) {
|
|
4307
4382
|
const labels = [...parsed.labels];
|
|
4308
|
-
return /* @__PURE__ */
|
|
4309
|
-
/* @__PURE__ */
|
|
4310
|
-
/* @__PURE__ */
|
|
4311
|
-
/* @__PURE__ */
|
|
4312
|
-
/* @__PURE__ */
|
|
4313
|
-
repos.length > 1 ? /* @__PURE__ */
|
|
4383
|
+
return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", children: [
|
|
4384
|
+
/* @__PURE__ */ jsx15(Text15, { color: "cyan", bold: true, children: "\u2728 Creating Issue" }),
|
|
4385
|
+
/* @__PURE__ */ jsxs15(Box15, { children: [
|
|
4386
|
+
/* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "Repo: " }),
|
|
4387
|
+
/* @__PURE__ */ jsx15(Text15, { color: "cyan", children: selectedRepo?.shortName ?? "(none)" }),
|
|
4388
|
+
repos.length > 1 ? /* @__PURE__ */ jsx15(Text15, { dimColor: true, children: " r:cycle" }) : null
|
|
4314
4389
|
] }),
|
|
4315
|
-
/* @__PURE__ */
|
|
4316
|
-
/* @__PURE__ */
|
|
4317
|
-
/* @__PURE__ */
|
|
4390
|
+
/* @__PURE__ */ jsxs15(Box15, { children: [
|
|
4391
|
+
/* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "Title: " }),
|
|
4392
|
+
/* @__PURE__ */ jsx15(Text15, { children: parsed.title })
|
|
4318
4393
|
] }),
|
|
4319
|
-
labels.length > 0 ? /* @__PURE__ */
|
|
4320
|
-
/* @__PURE__ */
|
|
4321
|
-
/* @__PURE__ */
|
|
4394
|
+
labels.length > 0 ? /* @__PURE__ */ jsxs15(Box15, { children: [
|
|
4395
|
+
/* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "Labels: " }),
|
|
4396
|
+
/* @__PURE__ */ jsx15(Text15, { children: labels.join(", ") })
|
|
4322
4397
|
] }) : null,
|
|
4323
|
-
parsed.assignee ? /* @__PURE__ */
|
|
4324
|
-
/* @__PURE__ */
|
|
4325
|
-
/* @__PURE__ */
|
|
4398
|
+
parsed.assignee ? /* @__PURE__ */ jsxs15(Box15, { children: [
|
|
4399
|
+
/* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "Assignee: " }),
|
|
4400
|
+
/* @__PURE__ */ jsxs15(Text15, { children: [
|
|
4326
4401
|
"@",
|
|
4327
4402
|
parsed.assignee
|
|
4328
4403
|
] })
|
|
4329
4404
|
] }) : null,
|
|
4330
|
-
parsed.dueDate ? /* @__PURE__ */
|
|
4331
|
-
/* @__PURE__ */
|
|
4332
|
-
/* @__PURE__ */
|
|
4405
|
+
parsed.dueDate ? /* @__PURE__ */ jsxs15(Box15, { children: [
|
|
4406
|
+
/* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "Due: " }),
|
|
4407
|
+
/* @__PURE__ */ jsx15(Text15, { children: formatDue(parsed.dueDate) })
|
|
4333
4408
|
] }) : null,
|
|
4334
|
-
/* @__PURE__ */
|
|
4409
|
+
/* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "Enter:add body Esc:cancel" })
|
|
4335
4410
|
] });
|
|
4336
4411
|
}
|
|
4337
|
-
return /* @__PURE__ */
|
|
4338
|
-
/* @__PURE__ */
|
|
4339
|
-
/* @__PURE__ */
|
|
4340
|
-
/* @__PURE__ */
|
|
4341
|
-
/* @__PURE__ */
|
|
4412
|
+
return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", children: [
|
|
4413
|
+
/* @__PURE__ */ jsx15(Text15, { color: "cyan", bold: true, children: "\u2728 What do you need to do?" }),
|
|
4414
|
+
/* @__PURE__ */ jsxs15(Box15, { children: [
|
|
4415
|
+
/* @__PURE__ */ jsx15(Text15, { color: "cyan", children: "> " }),
|
|
4416
|
+
/* @__PURE__ */ jsx15(
|
|
4342
4417
|
TextInput4,
|
|
4343
4418
|
{
|
|
4344
4419
|
placeholder: "fix login bug #bug #priority:high @me due friday",
|
|
@@ -4347,8 +4422,8 @@ function NlCreateOverlay({
|
|
|
4347
4422
|
}
|
|
4348
4423
|
)
|
|
4349
4424
|
] }),
|
|
4350
|
-
parseError ? /* @__PURE__ */
|
|
4351
|
-
/* @__PURE__ */
|
|
4425
|
+
parseError ? /* @__PURE__ */ jsx15(Text15, { color: "red", children: parseError }) : null,
|
|
4426
|
+
/* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "Tip: #label @user due <date> Enter:parse Esc:cancel" })
|
|
4352
4427
|
] });
|
|
4353
4428
|
}
|
|
4354
4429
|
function buildLabelList(parsed) {
|
|
@@ -4368,12 +4443,12 @@ var init_nl_create_overlay = __esm({
|
|
|
4368
4443
|
|
|
4369
4444
|
// src/board/components/search-bar.tsx
|
|
4370
4445
|
import { TextInput as TextInput5 } from "@inkjs/ui";
|
|
4371
|
-
import { Box as
|
|
4372
|
-
import { jsx as
|
|
4446
|
+
import { Box as Box16, Text as Text16 } from "ink";
|
|
4447
|
+
import { jsx as jsx16, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
4373
4448
|
function SearchBar({ defaultValue, onChange, onSubmit }) {
|
|
4374
|
-
return /* @__PURE__ */
|
|
4375
|
-
/* @__PURE__ */
|
|
4376
|
-
/* @__PURE__ */
|
|
4449
|
+
return /* @__PURE__ */ jsxs16(Box16, { children: [
|
|
4450
|
+
/* @__PURE__ */ jsx16(Text16, { color: "yellow", children: "/" }),
|
|
4451
|
+
/* @__PURE__ */ jsx16(
|
|
4377
4452
|
TextInput5,
|
|
4378
4453
|
{
|
|
4379
4454
|
defaultValue,
|
|
@@ -4391,9 +4466,9 @@ var init_search_bar = __esm({
|
|
|
4391
4466
|
});
|
|
4392
4467
|
|
|
4393
4468
|
// src/board/components/status-picker.tsx
|
|
4394
|
-
import { Box as
|
|
4395
|
-
import { useRef as useRef12, useState as
|
|
4396
|
-
import { jsx as
|
|
4469
|
+
import { Box as Box17, Text as Text17, useInput as useInput11 } from "ink";
|
|
4470
|
+
import { useRef as useRef12, useState as useState15 } from "react";
|
|
4471
|
+
import { jsx as jsx17, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
4397
4472
|
function isTerminal(name) {
|
|
4398
4473
|
return TERMINAL_STATUS_RE.test(name);
|
|
4399
4474
|
}
|
|
@@ -4440,11 +4515,11 @@ function StatusPicker({
|
|
|
4440
4515
|
onCancel,
|
|
4441
4516
|
showTerminalStatuses = true
|
|
4442
4517
|
}) {
|
|
4443
|
-
const [selectedIdx, setSelectedIdx] =
|
|
4518
|
+
const [selectedIdx, setSelectedIdx] = useState15(() => {
|
|
4444
4519
|
const idx = options.findIndex((o) => o.name === currentStatus);
|
|
4445
4520
|
return idx >= 0 ? idx : 0;
|
|
4446
4521
|
});
|
|
4447
|
-
const [confirmingTerminal, setConfirmingTerminal] =
|
|
4522
|
+
const [confirmingTerminal, setConfirmingTerminal] = useState15(false);
|
|
4448
4523
|
const submittedRef = useRef12(false);
|
|
4449
4524
|
useInput11((input2, key) => {
|
|
4450
4525
|
if (confirmingTerminal) {
|
|
@@ -4469,26 +4544,26 @@ function StatusPicker({
|
|
|
4469
4544
|
});
|
|
4470
4545
|
if (confirmingTerminal) {
|
|
4471
4546
|
const opt = options[selectedIdx];
|
|
4472
|
-
return /* @__PURE__ */
|
|
4473
|
-
/* @__PURE__ */
|
|
4547
|
+
return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", children: [
|
|
4548
|
+
/* @__PURE__ */ jsxs17(Text17, { color: "yellow", bold: true, children: [
|
|
4474
4549
|
"Mark as ",
|
|
4475
4550
|
opt?.name,
|
|
4476
4551
|
"?"
|
|
4477
4552
|
] }),
|
|
4478
|
-
/* @__PURE__ */
|
|
4479
|
-
/* @__PURE__ */
|
|
4553
|
+
/* @__PURE__ */ jsx17(Text17, { dimColor: true, children: "This will close the issue on GitHub." }),
|
|
4554
|
+
/* @__PURE__ */ jsx17(Text17, { children: "Continue? [y/n]" })
|
|
4480
4555
|
] });
|
|
4481
4556
|
}
|
|
4482
|
-
return /* @__PURE__ */
|
|
4483
|
-
/* @__PURE__ */
|
|
4557
|
+
return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", children: [
|
|
4558
|
+
/* @__PURE__ */ jsx17(Text17, { color: "cyan", bold: true, children: "Move to status:" }),
|
|
4484
4559
|
options.map((opt, i) => {
|
|
4485
4560
|
const isCurrent = opt.name === currentStatus;
|
|
4486
4561
|
const isSelected = i === selectedIdx;
|
|
4487
4562
|
const terminal = isTerminal(opt.name) && showTerminalStatuses;
|
|
4488
4563
|
const prefix = isSelected ? "> " : " ";
|
|
4489
4564
|
const suffix = isCurrent ? " (current)" : terminal ? " (Done)" : "";
|
|
4490
|
-
return /* @__PURE__ */
|
|
4491
|
-
|
|
4565
|
+
return /* @__PURE__ */ jsxs17(
|
|
4566
|
+
Text17,
|
|
4492
4567
|
{
|
|
4493
4568
|
...isSelected ? { color: "cyan" } : terminal ? { color: "yellow" } : {},
|
|
4494
4569
|
dimColor: isCurrent,
|
|
@@ -4501,7 +4576,7 @@ function StatusPicker({
|
|
|
4501
4576
|
opt.id
|
|
4502
4577
|
);
|
|
4503
4578
|
}),
|
|
4504
|
-
/* @__PURE__ */
|
|
4579
|
+
/* @__PURE__ */ jsx17(Text17, { dimColor: true, children: "j/k:navigate Enter:select Esc:cancel" })
|
|
4505
4580
|
] });
|
|
4506
4581
|
}
|
|
4507
4582
|
var init_status_picker = __esm({
|
|
@@ -4512,7 +4587,7 @@ var init_status_picker = __esm({
|
|
|
4512
4587
|
});
|
|
4513
4588
|
|
|
4514
4589
|
// src/board/components/overlay-renderer.tsx
|
|
4515
|
-
import { Fragment as Fragment2, jsx as
|
|
4590
|
+
import { Fragment as Fragment2, jsx as jsx18, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
4516
4591
|
function OverlayRenderer({
|
|
4517
4592
|
uiState,
|
|
4518
4593
|
config: config2,
|
|
@@ -4553,9 +4628,9 @@ function OverlayRenderer({
|
|
|
4553
4628
|
onPushEntry
|
|
4554
4629
|
}) {
|
|
4555
4630
|
const { mode, helpVisible } = uiState;
|
|
4556
|
-
return /* @__PURE__ */
|
|
4557
|
-
helpVisible ? /* @__PURE__ */
|
|
4558
|
-
mode === "overlay:status" && selectedRepoStatusOptions.length > 0 ? /* @__PURE__ */
|
|
4631
|
+
return /* @__PURE__ */ jsxs18(Fragment2, { children: [
|
|
4632
|
+
helpVisible ? /* @__PURE__ */ jsx18(HelpOverlay, { currentMode: mode, onClose: onToggleHelp }) : null,
|
|
4633
|
+
mode === "overlay:status" && selectedRepoStatusOptions.length > 0 ? /* @__PURE__ */ jsx18(
|
|
4559
4634
|
StatusPicker,
|
|
4560
4635
|
{
|
|
4561
4636
|
options: selectedRepoStatusOptions,
|
|
@@ -4564,7 +4639,7 @@ function OverlayRenderer({
|
|
|
4564
4639
|
onCancel: onExitOverlay
|
|
4565
4640
|
}
|
|
4566
4641
|
) : null,
|
|
4567
|
-
mode === "overlay:create" ? /* @__PURE__ */
|
|
4642
|
+
mode === "overlay:create" ? /* @__PURE__ */ jsx18(
|
|
4568
4643
|
CreateIssueForm,
|
|
4569
4644
|
{
|
|
4570
4645
|
repos: config2.repos,
|
|
@@ -4574,7 +4649,7 @@ function OverlayRenderer({
|
|
|
4574
4649
|
labelCache
|
|
4575
4650
|
}
|
|
4576
4651
|
) : null,
|
|
4577
|
-
mode === "overlay:confirmPick" ? /* @__PURE__ */
|
|
4652
|
+
mode === "overlay:confirmPick" ? /* @__PURE__ */ jsx18(
|
|
4578
4653
|
ConfirmPrompt,
|
|
4579
4654
|
{
|
|
4580
4655
|
message: "Pick this issue?",
|
|
@@ -4582,7 +4657,7 @@ function OverlayRenderer({
|
|
|
4582
4657
|
onCancel: onCancelPick
|
|
4583
4658
|
}
|
|
4584
4659
|
) : null,
|
|
4585
|
-
mode === "overlay:bulkAction" ? /* @__PURE__ */
|
|
4660
|
+
mode === "overlay:bulkAction" ? /* @__PURE__ */ jsx18(
|
|
4586
4661
|
BulkActionMenu,
|
|
4587
4662
|
{
|
|
4588
4663
|
count: multiSelectCount,
|
|
@@ -4591,7 +4666,7 @@ function OverlayRenderer({
|
|
|
4591
4666
|
onCancel: onExitOverlay
|
|
4592
4667
|
}
|
|
4593
4668
|
) : null,
|
|
4594
|
-
mode === "focus" && focusLabel ? /* @__PURE__ */
|
|
4669
|
+
mode === "focus" && focusLabel ? /* @__PURE__ */ jsx18(
|
|
4595
4670
|
FocusMode,
|
|
4596
4671
|
{
|
|
4597
4672
|
label: focusLabel,
|
|
@@ -4601,7 +4676,7 @@ function OverlayRenderer({
|
|
|
4601
4676
|
},
|
|
4602
4677
|
focusKey
|
|
4603
4678
|
) : null,
|
|
4604
|
-
mode === "overlay:label" && selectedIssue && defaultRepo ? /* @__PURE__ */
|
|
4679
|
+
mode === "overlay:label" && selectedIssue && defaultRepo ? /* @__PURE__ */ jsx18(
|
|
4605
4680
|
LabelPicker,
|
|
4606
4681
|
{
|
|
4607
4682
|
repo: defaultRepo,
|
|
@@ -4612,8 +4687,8 @@ function OverlayRenderer({
|
|
|
4612
4687
|
onError: onLabelError
|
|
4613
4688
|
}
|
|
4614
4689
|
) : null,
|
|
4615
|
-
mode === "search" ? /* @__PURE__ */
|
|
4616
|
-
mode === "overlay:comment" && selectedIssue ? /* @__PURE__ */
|
|
4690
|
+
mode === "search" ? /* @__PURE__ */ jsx18(SearchBar, { defaultValue: searchQuery, onChange: onSearchChange, onSubmit: onSearchSubmit }) : null,
|
|
4691
|
+
mode === "overlay:comment" && selectedIssue ? /* @__PURE__ */ jsx18(
|
|
4617
4692
|
CommentInput,
|
|
4618
4693
|
{
|
|
4619
4694
|
issueNumber: selectedIssue.number,
|
|
@@ -4623,8 +4698,8 @@ function OverlayRenderer({
|
|
|
4623
4698
|
onResumeRefresh
|
|
4624
4699
|
}
|
|
4625
4700
|
) : null,
|
|
4626
|
-
mode === "overlay:fuzzyPicker" ? /* @__PURE__ */
|
|
4627
|
-
mode === "overlay:createNl" ? /* @__PURE__ */
|
|
4701
|
+
mode === "overlay:fuzzyPicker" ? /* @__PURE__ */ jsx18(FuzzyPicker, { repos, onSelect: onFuzzySelect, onClose: onFuzzyClose }) : null,
|
|
4702
|
+
mode === "overlay:createNl" ? /* @__PURE__ */ jsx18(
|
|
4628
4703
|
NlCreateOverlay,
|
|
4629
4704
|
{
|
|
4630
4705
|
repos: config2.repos,
|
|
@@ -4637,7 +4712,7 @@ function OverlayRenderer({
|
|
|
4637
4712
|
onLlmFallback
|
|
4638
4713
|
}
|
|
4639
4714
|
) : null,
|
|
4640
|
-
mode === "overlay:editIssue" && selectedIssue && selectedRepoName ? /* @__PURE__ */
|
|
4715
|
+
mode === "overlay:editIssue" && selectedIssue && selectedRepoName ? /* @__PURE__ */ jsx18(
|
|
4641
4716
|
EditIssueOverlay,
|
|
4642
4717
|
{
|
|
4643
4718
|
issue: selectedIssue,
|
|
@@ -4673,9 +4748,104 @@ var init_overlay_renderer = __esm({
|
|
|
4673
4748
|
}
|
|
4674
4749
|
});
|
|
4675
4750
|
|
|
4751
|
+
// src/board/components/panel-layout.tsx
|
|
4752
|
+
import { Box as Box18 } from "ink";
|
|
4753
|
+
import { jsx as jsx19, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
4754
|
+
function getLayoutMode(cols) {
|
|
4755
|
+
if (cols >= WIDE_THRESHOLD) return "wide";
|
|
4756
|
+
if (cols >= MEDIUM_THRESHOLD) return "medium";
|
|
4757
|
+
return "stacked";
|
|
4758
|
+
}
|
|
4759
|
+
function getDetailWidth(cols) {
|
|
4760
|
+
return Math.floor(cols * 0.4);
|
|
4761
|
+
}
|
|
4762
|
+
function PanelLayout({
|
|
4763
|
+
cols,
|
|
4764
|
+
issuesPanelHeight,
|
|
4765
|
+
reposPanel,
|
|
4766
|
+
statusesPanel,
|
|
4767
|
+
issuesPanel,
|
|
4768
|
+
detailPanel,
|
|
4769
|
+
activityPanel
|
|
4770
|
+
}) {
|
|
4771
|
+
const mode = getLayoutMode(cols);
|
|
4772
|
+
if (mode === "wide") {
|
|
4773
|
+
const detailWidth = getDetailWidth(cols);
|
|
4774
|
+
return /* @__PURE__ */ jsxs19(Box18, { flexDirection: "column", children: [
|
|
4775
|
+
/* @__PURE__ */ jsxs19(Box18, { height: issuesPanelHeight, children: [
|
|
4776
|
+
/* @__PURE__ */ jsxs19(Box18, { flexDirection: "column", width: LEFT_COL_WIDTH, children: [
|
|
4777
|
+
reposPanel,
|
|
4778
|
+
statusesPanel
|
|
4779
|
+
] }),
|
|
4780
|
+
/* @__PURE__ */ jsx19(Box18, { flexGrow: 1, flexDirection: "column", children: issuesPanel }),
|
|
4781
|
+
/* @__PURE__ */ jsx19(Box18, { width: detailWidth, flexDirection: "column", children: detailPanel })
|
|
4782
|
+
] }),
|
|
4783
|
+
/* @__PURE__ */ jsx19(Box18, { height: ACTIVITY_HEIGHT, children: activityPanel })
|
|
4784
|
+
] });
|
|
4785
|
+
}
|
|
4786
|
+
if (mode === "medium") {
|
|
4787
|
+
return /* @__PURE__ */ jsxs19(Box18, { flexDirection: "column", children: [
|
|
4788
|
+
/* @__PURE__ */ jsxs19(Box18, { height: issuesPanelHeight, children: [
|
|
4789
|
+
/* @__PURE__ */ jsxs19(Box18, { flexDirection: "column", width: LEFT_COL_WIDTH, children: [
|
|
4790
|
+
reposPanel,
|
|
4791
|
+
statusesPanel
|
|
4792
|
+
] }),
|
|
4793
|
+
/* @__PURE__ */ jsx19(Box18, { flexGrow: 1, flexDirection: "column", children: issuesPanel })
|
|
4794
|
+
] }),
|
|
4795
|
+
/* @__PURE__ */ jsx19(Box18, { height: ACTIVITY_HEIGHT, children: activityPanel })
|
|
4796
|
+
] });
|
|
4797
|
+
}
|
|
4798
|
+
return /* @__PURE__ */ jsxs19(Box18, { flexDirection: "column", children: [
|
|
4799
|
+
reposPanel,
|
|
4800
|
+
statusesPanel,
|
|
4801
|
+
/* @__PURE__ */ jsx19(Box18, { flexGrow: 1, flexDirection: "column", children: issuesPanel }),
|
|
4802
|
+
/* @__PURE__ */ jsx19(Box18, { height: ACTIVITY_HEIGHT, children: activityPanel })
|
|
4803
|
+
] });
|
|
4804
|
+
}
|
|
4805
|
+
var WIDE_THRESHOLD, MEDIUM_THRESHOLD, LEFT_COL_WIDTH, ACTIVITY_HEIGHT;
|
|
4806
|
+
var init_panel_layout = __esm({
|
|
4807
|
+
"src/board/components/panel-layout.tsx"() {
|
|
4808
|
+
"use strict";
|
|
4809
|
+
WIDE_THRESHOLD = 160;
|
|
4810
|
+
MEDIUM_THRESHOLD = 100;
|
|
4811
|
+
LEFT_COL_WIDTH = 24;
|
|
4812
|
+
ACTIVITY_HEIGHT = 5;
|
|
4813
|
+
}
|
|
4814
|
+
});
|
|
4815
|
+
|
|
4816
|
+
// src/board/components/repos-panel.tsx
|
|
4817
|
+
import { Box as Box19, Text as Text18 } from "ink";
|
|
4818
|
+
import { jsx as jsx20, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
4819
|
+
function shortName(fullName) {
|
|
4820
|
+
return fullName.includes("/") ? fullName.split("/")[1] ?? fullName : fullName;
|
|
4821
|
+
}
|
|
4822
|
+
function ReposPanel({ repos, selectedIdx, isActive, width, flexGrow }) {
|
|
4823
|
+
const maxLabel = Math.max(4, width - 8);
|
|
4824
|
+
return /* @__PURE__ */ jsx20(Panel, { title: "[1] Repos", isActive, width, flexGrow, children: repos.length === 0 ? /* @__PURE__ */ jsx20(Text18, { color: "gray", children: "\u2014" }) : repos.map((repo, i) => {
|
|
4825
|
+
const isSel = i === selectedIdx;
|
|
4826
|
+
const label = shortName(repo.name).slice(0, maxLabel);
|
|
4827
|
+
return /* @__PURE__ */ jsxs20(Box19, { children: [
|
|
4828
|
+
/* @__PURE__ */ jsxs20(Text18, { color: isSel ? "cyan" : isActive ? "white" : "gray", bold: isSel, children: [
|
|
4829
|
+
isSel ? "\u25BA " : " ",
|
|
4830
|
+
label
|
|
4831
|
+
] }),
|
|
4832
|
+
/* @__PURE__ */ jsxs20(Text18, { color: "gray", children: [
|
|
4833
|
+
" ",
|
|
4834
|
+
repo.openCount
|
|
4835
|
+
] })
|
|
4836
|
+
] }, repo.name);
|
|
4837
|
+
}) });
|
|
4838
|
+
}
|
|
4839
|
+
var init_repos_panel = __esm({
|
|
4840
|
+
"src/board/components/repos-panel.tsx"() {
|
|
4841
|
+
"use strict";
|
|
4842
|
+
init_panel();
|
|
4843
|
+
}
|
|
4844
|
+
});
|
|
4845
|
+
|
|
4676
4846
|
// src/board/components/issue-row.tsx
|
|
4677
|
-
import { Box as
|
|
4678
|
-
import { Fragment as Fragment3, jsx as
|
|
4847
|
+
import { Box as Box20, Text as Text19 } from "ink";
|
|
4848
|
+
import { Fragment as Fragment3, jsx as jsx21, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
4679
4849
|
function truncate(s, max) {
|
|
4680
4850
|
return s.length > max ? `${s.slice(0, max - 1)}\u2026` : s;
|
|
4681
4851
|
}
|
|
@@ -4716,30 +4886,30 @@ function IssueRow({ issue, selfLogin, isSelected }) {
|
|
|
4716
4886
|
const labels = (issue.labels ?? []).slice(0, 2);
|
|
4717
4887
|
const target = formatTargetDate(issue.targetDate);
|
|
4718
4888
|
const titleStr = truncate(issue.title, 42).padEnd(42);
|
|
4719
|
-
return /* @__PURE__ */
|
|
4720
|
-
isSelected ? /* @__PURE__ */
|
|
4721
|
-
/* @__PURE__ */
|
|
4889
|
+
return /* @__PURE__ */ jsxs21(Box20, { children: [
|
|
4890
|
+
isSelected ? /* @__PURE__ */ jsx21(Text19, { color: "cyan", bold: true, children: "\u25B6 " }) : /* @__PURE__ */ jsx21(Text19, { children: " " }),
|
|
4891
|
+
/* @__PURE__ */ jsxs21(Text19, { color: "cyan", children: [
|
|
4722
4892
|
"#",
|
|
4723
4893
|
String(issue.number).padEnd(5)
|
|
4724
4894
|
] }),
|
|
4725
|
-
/* @__PURE__ */
|
|
4726
|
-
isSelected ? /* @__PURE__ */
|
|
4727
|
-
/* @__PURE__ */
|
|
4728
|
-
/* @__PURE__ */
|
|
4895
|
+
/* @__PURE__ */ jsx21(Text19, { children: " " }),
|
|
4896
|
+
isSelected ? /* @__PURE__ */ jsx21(Text19, { color: "white", bold: true, children: titleStr }) : /* @__PURE__ */ jsx21(Text19, { children: titleStr }),
|
|
4897
|
+
/* @__PURE__ */ jsx21(Text19, { children: " " }),
|
|
4898
|
+
/* @__PURE__ */ jsx21(Box20, { width: LABEL_COL_WIDTH, children: labels.map((l, i) => /* @__PURE__ */ jsxs21(Text19, { children: [
|
|
4729
4899
|
i > 0 ? " " : "",
|
|
4730
|
-
/* @__PURE__ */
|
|
4900
|
+
/* @__PURE__ */ jsxs21(Text19, { color: labelColor(l.name), children: [
|
|
4731
4901
|
"[",
|
|
4732
4902
|
truncate(l.name, 12),
|
|
4733
4903
|
"]"
|
|
4734
4904
|
] })
|
|
4735
4905
|
] }, l.name)) }),
|
|
4736
|
-
/* @__PURE__ */
|
|
4737
|
-
/* @__PURE__ */
|
|
4738
|
-
/* @__PURE__ */
|
|
4739
|
-
/* @__PURE__ */
|
|
4740
|
-
target.text ? /* @__PURE__ */
|
|
4741
|
-
/* @__PURE__ */
|
|
4742
|
-
/* @__PURE__ */
|
|
4906
|
+
/* @__PURE__ */ jsx21(Text19, { children: " " }),
|
|
4907
|
+
/* @__PURE__ */ jsx21(Text19, { color: assigneeColor, children: assigneeText.padEnd(14) }),
|
|
4908
|
+
/* @__PURE__ */ jsx21(Text19, { children: " " }),
|
|
4909
|
+
/* @__PURE__ */ jsx21(Text19, { color: "gray", children: timeAgo2(issue.updatedAt).padStart(4) }),
|
|
4910
|
+
target.text ? /* @__PURE__ */ jsxs21(Fragment3, { children: [
|
|
4911
|
+
/* @__PURE__ */ jsx21(Text19, { children: " " }),
|
|
4912
|
+
/* @__PURE__ */ jsx21(Text19, { color: target.color, children: target.text })
|
|
4743
4913
|
] }) : null
|
|
4744
4914
|
] });
|
|
4745
4915
|
}
|
|
@@ -4762,68 +4932,21 @@ var init_issue_row = __esm({
|
|
|
4762
4932
|
}
|
|
4763
4933
|
});
|
|
4764
4934
|
|
|
4765
|
-
// src/board/components/task-row.tsx
|
|
4766
|
-
import { Box as Box17, Text as Text17 } from "ink";
|
|
4767
|
-
import { jsx as jsx18, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
4768
|
-
function truncate2(s, max) {
|
|
4769
|
-
return s.length > max ? `${s.slice(0, max - 1)}\u2026` : s;
|
|
4770
|
-
}
|
|
4771
|
-
function formatDue2(dateStr) {
|
|
4772
|
-
if (!dateStr) return { text: "", color: "gray" };
|
|
4773
|
-
const d = new Date(dateStr);
|
|
4774
|
-
const days = Math.ceil((d.getTime() - Date.now()) / 864e5);
|
|
4775
|
-
if (days < 0) return { text: `${Math.abs(days)}d overdue`, color: "red" };
|
|
4776
|
-
if (days === 0) return { text: "today", color: "yellow" };
|
|
4777
|
-
if (days === 1) return { text: "tomorrow", color: "white" };
|
|
4778
|
-
if (days <= 7) return { text: `in ${days}d`, color: "white" };
|
|
4779
|
-
return {
|
|
4780
|
-
text: d.toLocaleDateString("en-US", { month: "short", day: "numeric" }),
|
|
4781
|
-
color: "gray"
|
|
4782
|
-
};
|
|
4783
|
-
}
|
|
4784
|
-
function TaskRow({ task: task2, isSelected }) {
|
|
4785
|
-
const pri = PRIORITY_INDICATORS[task2.priority] ?? DEFAULT_PRIORITY;
|
|
4786
|
-
const due = formatDue2(task2.dueDate);
|
|
4787
|
-
const titleStr = truncate2(task2.title, 45).padEnd(45);
|
|
4788
|
-
return /* @__PURE__ */ jsxs18(Box17, { children: [
|
|
4789
|
-
isSelected ? /* @__PURE__ */ jsx18(Text17, { color: "cyan", bold: true, children: "\u25B6 " }) : /* @__PURE__ */ jsx18(Text17, { children: " " }),
|
|
4790
|
-
/* @__PURE__ */ jsx18(Text17, { color: pri.color, children: pri.text }),
|
|
4791
|
-
/* @__PURE__ */ jsx18(Text17, { children: " " }),
|
|
4792
|
-
isSelected ? /* @__PURE__ */ jsx18(Text17, { color: "white", bold: true, children: titleStr }) : /* @__PURE__ */ jsx18(Text17, { children: titleStr }),
|
|
4793
|
-
/* @__PURE__ */ jsx18(Text17, { children: " " }),
|
|
4794
|
-
/* @__PURE__ */ jsx18(Text17, { color: due.color, children: due.text })
|
|
4795
|
-
] });
|
|
4796
|
-
}
|
|
4797
|
-
var PRIORITY_INDICATORS, DEFAULT_PRIORITY;
|
|
4798
|
-
var init_task_row = __esm({
|
|
4799
|
-
"src/board/components/task-row.tsx"() {
|
|
4800
|
-
"use strict";
|
|
4801
|
-
init_types();
|
|
4802
|
-
PRIORITY_INDICATORS = {
|
|
4803
|
-
[5 /* High */]: { text: "[!]", color: "red" },
|
|
4804
|
-
[3 /* Medium */]: { text: "[~]", color: "yellow" },
|
|
4805
|
-
[1 /* Low */]: { text: "[\u2193]", color: "blue" },
|
|
4806
|
-
[0 /* None */]: { text: " ", color: "gray" }
|
|
4807
|
-
};
|
|
4808
|
-
DEFAULT_PRIORITY = { text: " ", color: "gray" };
|
|
4809
|
-
}
|
|
4810
|
-
});
|
|
4811
|
-
|
|
4812
4935
|
// src/board/components/row-renderer.tsx
|
|
4813
|
-
import { Box as
|
|
4814
|
-
import { jsx as
|
|
4936
|
+
import { Box as Box21, Text as Text20 } from "ink";
|
|
4937
|
+
import { jsx as jsx22, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
4815
4938
|
function RowRenderer({ row, selectedId, selfLogin, isMultiSelected }) {
|
|
4816
4939
|
switch (row.type) {
|
|
4817
4940
|
case "sectionHeader": {
|
|
4818
4941
|
const arrow = row.isCollapsed ? "\u25B6" : "\u25BC";
|
|
4819
4942
|
const isSel = selectedId === row.navId;
|
|
4820
|
-
return /* @__PURE__ */
|
|
4821
|
-
/* @__PURE__ */
|
|
4943
|
+
return /* @__PURE__ */ jsxs22(Box21, { children: [
|
|
4944
|
+
/* @__PURE__ */ jsxs22(Text20, { color: isSel ? "cyan" : "white", bold: true, children: [
|
|
4822
4945
|
arrow,
|
|
4823
4946
|
" ",
|
|
4824
4947
|
row.label
|
|
4825
4948
|
] }),
|
|
4826
|
-
/* @__PURE__ */
|
|
4949
|
+
/* @__PURE__ */ jsxs22(Text20, { color: "gray", children: [
|
|
4827
4950
|
" ",
|
|
4828
4951
|
"(",
|
|
4829
4952
|
row.count,
|
|
@@ -4837,26 +4960,26 @@ function RowRenderer({ row, selectedId, selfLogin, isMultiSelected }) {
|
|
|
4837
4960
|
if (row.navId) {
|
|
4838
4961
|
const arrow = row.isCollapsed ? "\u25B6" : "\u25BC";
|
|
4839
4962
|
const isSel = selectedId === row.navId;
|
|
4840
|
-
return /* @__PURE__ */
|
|
4841
|
-
/* @__PURE__ */
|
|
4963
|
+
return /* @__PURE__ */ jsxs22(Box21, { children: [
|
|
4964
|
+
/* @__PURE__ */ jsxs22(Text20, { color: isSel ? "cyan" : "gray", children: [
|
|
4842
4965
|
" ",
|
|
4843
4966
|
arrow,
|
|
4844
4967
|
" ",
|
|
4845
4968
|
row.text
|
|
4846
4969
|
] }),
|
|
4847
|
-
/* @__PURE__ */
|
|
4970
|
+
/* @__PURE__ */ jsxs22(Text20, { color: "gray", children: [
|
|
4848
4971
|
" (",
|
|
4849
4972
|
row.count,
|
|
4850
4973
|
")"
|
|
4851
4974
|
] })
|
|
4852
4975
|
] });
|
|
4853
4976
|
}
|
|
4854
|
-
return /* @__PURE__ */
|
|
4855
|
-
/* @__PURE__ */
|
|
4977
|
+
return /* @__PURE__ */ jsxs22(Box21, { children: [
|
|
4978
|
+
/* @__PURE__ */ jsxs22(Text20, { bold: true, color: "white", children: [
|
|
4856
4979
|
" ",
|
|
4857
4980
|
row.text
|
|
4858
4981
|
] }),
|
|
4859
|
-
row.count != null ? /* @__PURE__ */
|
|
4982
|
+
row.count != null ? /* @__PURE__ */ jsxs22(Text20, { color: "gray", children: [
|
|
4860
4983
|
" (",
|
|
4861
4984
|
row.count,
|
|
4862
4985
|
")"
|
|
@@ -4865,32 +4988,25 @@ function RowRenderer({ row, selectedId, selfLogin, isMultiSelected }) {
|
|
|
4865
4988
|
}
|
|
4866
4989
|
case "issue": {
|
|
4867
4990
|
const checkbox2 = isMultiSelected != null ? isMultiSelected ? "\u2611 " : "\u2610 " : "";
|
|
4868
|
-
return /* @__PURE__ */
|
|
4869
|
-
checkbox2 ? /* @__PURE__ */
|
|
4870
|
-
/* @__PURE__ */
|
|
4871
|
-
] });
|
|
4872
|
-
}
|
|
4873
|
-
case "task": {
|
|
4874
|
-
const checkbox2 = isMultiSelected != null ? isMultiSelected ? "\u2611 " : "\u2610 " : "";
|
|
4875
|
-
return /* @__PURE__ */ jsxs19(Box18, { children: [
|
|
4876
|
-
checkbox2 ? /* @__PURE__ */ jsx19(Text18, { color: isMultiSelected ? "cyan" : "gray", children: checkbox2 }) : null,
|
|
4877
|
-
/* @__PURE__ */ jsx19(TaskRow, { task: row.task, isSelected: selectedId === row.navId })
|
|
4991
|
+
return /* @__PURE__ */ jsxs22(Box21, { children: [
|
|
4992
|
+
checkbox2 ? /* @__PURE__ */ jsx22(Text20, { color: isMultiSelected ? "cyan" : "gray", children: checkbox2 }) : null,
|
|
4993
|
+
/* @__PURE__ */ jsx22(IssueRow, { issue: row.issue, selfLogin, isSelected: selectedId === row.navId })
|
|
4878
4994
|
] });
|
|
4879
4995
|
}
|
|
4880
4996
|
case "activity": {
|
|
4881
|
-
const ago =
|
|
4882
|
-
return /* @__PURE__ */
|
|
4997
|
+
const ago = new Date(row.event.timestamp).toLocaleTimeString();
|
|
4998
|
+
return /* @__PURE__ */ jsxs22(Text20, { dimColor: true, children: [
|
|
4883
4999
|
" ",
|
|
4884
5000
|
ago,
|
|
4885
5001
|
": ",
|
|
4886
|
-
/* @__PURE__ */
|
|
5002
|
+
/* @__PURE__ */ jsxs22(Text20, { color: "gray", children: [
|
|
4887
5003
|
"@",
|
|
4888
5004
|
row.event.actor
|
|
4889
5005
|
] }),
|
|
4890
5006
|
" ",
|
|
4891
5007
|
row.event.summary,
|
|
4892
5008
|
" ",
|
|
4893
|
-
/* @__PURE__ */
|
|
5009
|
+
/* @__PURE__ */ jsxs22(Text20, { dimColor: true, children: [
|
|
4894
5010
|
"(",
|
|
4895
5011
|
row.event.repoShortName,
|
|
4896
5012
|
")"
|
|
@@ -4898,85 +5014,71 @@ function RowRenderer({ row, selectedId, selfLogin, isMultiSelected }) {
|
|
|
4898
5014
|
] });
|
|
4899
5015
|
}
|
|
4900
5016
|
case "error":
|
|
4901
|
-
return /* @__PURE__ */
|
|
5017
|
+
return /* @__PURE__ */ jsxs22(Text20, { color: "red", children: [
|
|
4902
5018
|
" Error: ",
|
|
4903
5019
|
row.text
|
|
4904
5020
|
] });
|
|
4905
5021
|
case "gap":
|
|
4906
|
-
return /* @__PURE__ */
|
|
5022
|
+
return /* @__PURE__ */ jsx22(Text20, { children: "" });
|
|
4907
5023
|
}
|
|
4908
5024
|
}
|
|
4909
5025
|
var init_row_renderer = __esm({
|
|
4910
5026
|
"src/board/components/row-renderer.tsx"() {
|
|
4911
5027
|
"use strict";
|
|
4912
|
-
init_constants();
|
|
4913
5028
|
init_issue_row();
|
|
4914
|
-
init_task_row();
|
|
4915
5029
|
}
|
|
4916
5030
|
});
|
|
4917
5031
|
|
|
4918
|
-
// src/board/components/
|
|
4919
|
-
import { Box as
|
|
4920
|
-
import { jsx as
|
|
4921
|
-
function
|
|
4922
|
-
|
|
4923
|
-
|
|
4924
|
-
|
|
4925
|
-
|
|
4926
|
-
|
|
4927
|
-
|
|
4928
|
-
|
|
4929
|
-
|
|
4930
|
-
|
|
4931
|
-
|
|
4932
|
-
|
|
4933
|
-
|
|
4934
|
-
|
|
4935
|
-
|
|
4936
|
-
|
|
4937
|
-
|
|
4938
|
-
|
|
4939
|
-
|
|
4940
|
-
|
|
4941
|
-
|
|
4942
|
-
import { Box as Box20, Text as Text20 } from "ink";
|
|
4943
|
-
import { jsx as jsx21, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
4944
|
-
function TabBar({ tabs, activeTabId, totalWidth }) {
|
|
4945
|
-
return /* @__PURE__ */ jsx21(Box20, { width: totalWidth, children: tabs.map((tab, i) => {
|
|
4946
|
-
const isActive = tab.id === activeTabId;
|
|
4947
|
-
return /* @__PURE__ */ jsx21(Box20, { marginRight: 2, children: /* @__PURE__ */ jsxs21(Text20, { bold: isActive, color: isActive ? "cyan" : "gray", children: [
|
|
4948
|
-
i + 1,
|
|
4949
|
-
":",
|
|
4950
|
-
tab.label,
|
|
4951
|
-
" (",
|
|
4952
|
-
tab.count,
|
|
4953
|
-
")"
|
|
4954
|
-
] }) }, tab.id);
|
|
5032
|
+
// src/board/components/statuses-panel.tsx
|
|
5033
|
+
import { Box as Box22, Text as Text21 } from "ink";
|
|
5034
|
+
import { jsx as jsx23, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
5035
|
+
function StatusesPanel({
|
|
5036
|
+
groups,
|
|
5037
|
+
selectedIdx,
|
|
5038
|
+
isActive,
|
|
5039
|
+
width,
|
|
5040
|
+
flexGrow
|
|
5041
|
+
}) {
|
|
5042
|
+
const maxLabel = Math.max(4, width - 8);
|
|
5043
|
+
return /* @__PURE__ */ jsx23(Panel, { title: "[2] Statuses", isActive, width, flexGrow, children: groups.length === 0 ? /* @__PURE__ */ jsx23(Text21, { color: "gray", children: "\u2014" }) : groups.map((group, i) => {
|
|
5044
|
+
const isSel = i === selectedIdx;
|
|
5045
|
+
const label = group.label.slice(0, maxLabel);
|
|
5046
|
+
return /* @__PURE__ */ jsxs23(Box22, { children: [
|
|
5047
|
+
/* @__PURE__ */ jsxs23(Text21, { color: isSel ? "cyan" : isActive ? "white" : "gray", bold: isSel, children: [
|
|
5048
|
+
isSel ? "\u25BA " : " ",
|
|
5049
|
+
label
|
|
5050
|
+
] }),
|
|
5051
|
+
/* @__PURE__ */ jsxs23(Text21, { color: "gray", children: [
|
|
5052
|
+
" ",
|
|
5053
|
+
group.count
|
|
5054
|
+
] })
|
|
5055
|
+
] }, group.id);
|
|
4955
5056
|
}) });
|
|
4956
5057
|
}
|
|
4957
|
-
var
|
|
4958
|
-
"src/board/components/
|
|
5058
|
+
var init_statuses_panel = __esm({
|
|
5059
|
+
"src/board/components/statuses-panel.tsx"() {
|
|
4959
5060
|
"use strict";
|
|
5061
|
+
init_panel();
|
|
4960
5062
|
}
|
|
4961
5063
|
});
|
|
4962
5064
|
|
|
4963
5065
|
// src/board/components/toast-container.tsx
|
|
4964
5066
|
import { Spinner as Spinner3 } from "@inkjs/ui";
|
|
4965
|
-
import { Box as
|
|
4966
|
-
import { Fragment as Fragment4, jsx as
|
|
5067
|
+
import { Box as Box23, Text as Text22 } from "ink";
|
|
5068
|
+
import { Fragment as Fragment4, jsx as jsx24, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
4967
5069
|
function ToastContainer({ toasts }) {
|
|
4968
5070
|
if (toasts.length === 0) return null;
|
|
4969
|
-
return /* @__PURE__ */
|
|
4970
|
-
/* @__PURE__ */
|
|
4971
|
-
/* @__PURE__ */
|
|
5071
|
+
return /* @__PURE__ */ jsx24(Box23, { flexDirection: "column", children: toasts.map((t) => /* @__PURE__ */ jsx24(Box23, { children: t.type === "loading" ? /* @__PURE__ */ jsxs24(Fragment4, { children: [
|
|
5072
|
+
/* @__PURE__ */ jsx24(Spinner3, { label: "" }),
|
|
5073
|
+
/* @__PURE__ */ jsxs24(Text22, { color: "cyan", children: [
|
|
4972
5074
|
" ",
|
|
4973
5075
|
t.message
|
|
4974
5076
|
] })
|
|
4975
|
-
] }) : /* @__PURE__ */
|
|
5077
|
+
] }) : /* @__PURE__ */ jsxs24(Text22, { color: TYPE_COLORS[t.type], children: [
|
|
4976
5078
|
TYPE_PREFIXES[t.type],
|
|
4977
5079
|
" ",
|
|
4978
5080
|
t.message,
|
|
4979
|
-
t.type === "error" ? /* @__PURE__ */
|
|
5081
|
+
t.type === "error" ? /* @__PURE__ */ jsx24(Text22, { color: "gray", children: t.retry ? " [r]etry [d]ismiss" : " [d]ismiss" }) : null
|
|
4980
5082
|
] }) }, t.id)) });
|
|
4981
5083
|
}
|
|
4982
5084
|
var TYPE_COLORS, TYPE_PREFIXES;
|
|
@@ -5000,9 +5102,9 @@ var init_toast_container = __esm({
|
|
|
5000
5102
|
// src/board/components/dashboard.tsx
|
|
5001
5103
|
import { execFileSync as execFileSync3, spawnSync as spawnSync4 } from "child_process";
|
|
5002
5104
|
import { Spinner as Spinner4 } from "@inkjs/ui";
|
|
5003
|
-
import { Box as
|
|
5004
|
-
import { useCallback as
|
|
5005
|
-
import { Fragment as Fragment5, jsx as
|
|
5105
|
+
import { Box as Box24, Text as Text23, useApp, useStdout } from "ink";
|
|
5106
|
+
import { useCallback as useCallback12, useEffect as useEffect9, useMemo as useMemo3, useRef as useRef13, useState as useState16 } from "react";
|
|
5107
|
+
import { Fragment as Fragment5, jsx as jsx25, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
5006
5108
|
function resolveStatusGroups(statusOptions, configuredGroups) {
|
|
5007
5109
|
if (configuredGroups && configuredGroups.length > 0) {
|
|
5008
5110
|
return configuredGroups.map((entry) => {
|
|
@@ -5040,7 +5142,7 @@ function groupByStatus(issues) {
|
|
|
5040
5142
|
}
|
|
5041
5143
|
return groups;
|
|
5042
5144
|
}
|
|
5043
|
-
function buildBoardTree(repos,
|
|
5145
|
+
function buildBoardTree(repos, activity) {
|
|
5044
5146
|
const sections = repos.map((rd) => {
|
|
5045
5147
|
const sectionId = rd.repo.name;
|
|
5046
5148
|
if (rd.error) {
|
|
@@ -5069,72 +5171,58 @@ function buildBoardTree(repos, tasks, activity) {
|
|
|
5069
5171
|
}
|
|
5070
5172
|
return { repo: rd.repo, sectionId, groups, error: null };
|
|
5071
5173
|
});
|
|
5072
|
-
return { activity, sections
|
|
5174
|
+
return { activity, sections };
|
|
5073
5175
|
}
|
|
5074
|
-
function
|
|
5075
|
-
|
|
5076
|
-
|
|
5077
|
-
label: repo.shortName,
|
|
5078
|
-
count: groups.reduce((s, g) => s + g.issues.length, 0)
|
|
5079
|
-
}));
|
|
5080
|
-
if (tree.activity.length > 0)
|
|
5081
|
-
tabs.push({ id: "activity", label: "Activity", count: tree.activity.length });
|
|
5082
|
-
if (tree.tasks.length > 0)
|
|
5083
|
-
tabs.push({ id: "ticktick", label: "Tasks", count: tree.tasks.length });
|
|
5084
|
-
return tabs;
|
|
5085
|
-
}
|
|
5086
|
-
function isRepoTab(tabId) {
|
|
5087
|
-
return tabId !== null && tabId !== "activity" && tabId !== "ticktick";
|
|
5088
|
-
}
|
|
5089
|
-
function buildStatusTabs(tabId, tree) {
|
|
5090
|
-
if (!isRepoTab(tabId)) return [];
|
|
5091
|
-
const section = tree.sections.find((s) => s.sectionId === tabId);
|
|
5176
|
+
function buildNavItemsForRepo(sections, repoName, statusGroupId) {
|
|
5177
|
+
if (!repoName) return [];
|
|
5178
|
+
const section = sections.find((s) => s.sectionId === repoName);
|
|
5092
5179
|
if (!section) return [];
|
|
5093
|
-
|
|
5094
|
-
}
|
|
5095
|
-
function buildNavItemsForTab(tabId, tree, activeStatusId) {
|
|
5096
|
-
if (tabId === "activity") return [];
|
|
5097
|
-
if (tabId === "ticktick")
|
|
5098
|
-
return tree.tasks.map((task2) => ({
|
|
5099
|
-
id: `tt:${task2.id}`,
|
|
5100
|
-
section: tabId,
|
|
5101
|
-
type: "item"
|
|
5102
|
-
}));
|
|
5103
|
-
const section = tree.sections.find((s) => s.sectionId === tabId);
|
|
5104
|
-
if (!section) return [];
|
|
5105
|
-
const activeGroup = section.groups.find((g) => g.subId === activeStatusId) ?? section.groups[0];
|
|
5180
|
+
const activeGroup = section.groups.find((g) => g.subId === statusGroupId) ?? section.groups[0];
|
|
5106
5181
|
if (!activeGroup) return [];
|
|
5107
5182
|
return activeGroup.issues.map((issue) => ({
|
|
5108
5183
|
id: `gh:${section.repo.name}:${issue.number}`,
|
|
5109
|
-
section:
|
|
5184
|
+
section: repoName,
|
|
5110
5185
|
type: "item"
|
|
5111
5186
|
}));
|
|
5112
5187
|
}
|
|
5113
|
-
function
|
|
5114
|
-
if (
|
|
5115
|
-
return
|
|
5116
|
-
|
|
5117
|
-
|
|
5118
|
-
|
|
5119
|
-
|
|
5120
|
-
|
|
5121
|
-
|
|
5122
|
-
|
|
5123
|
-
|
|
5124
|
-
|
|
5125
|
-
navId: `tt:${task2.id}`,
|
|
5126
|
-
task: task2
|
|
5127
|
-
}));
|
|
5128
|
-
const section = tree.sections.find((s) => s.sectionId === tabId);
|
|
5188
|
+
function buildFlatRowsForRepo(sections, repoName, statusGroupId) {
|
|
5189
|
+
if (!repoName) {
|
|
5190
|
+
return [
|
|
5191
|
+
{
|
|
5192
|
+
type: "subHeader",
|
|
5193
|
+
key: "select-repo",
|
|
5194
|
+
navId: null,
|
|
5195
|
+
text: "Select a repo in panel [1]"
|
|
5196
|
+
}
|
|
5197
|
+
];
|
|
5198
|
+
}
|
|
5199
|
+
const section = sections.find((s) => s.sectionId === repoName);
|
|
5129
5200
|
if (!section) return [];
|
|
5130
|
-
if (section.error)
|
|
5131
|
-
return [{ type: "error", key: `error:${
|
|
5132
|
-
|
|
5201
|
+
if (section.error) {
|
|
5202
|
+
return [{ type: "error", key: `error:${repoName}`, navId: null, text: section.error }];
|
|
5203
|
+
}
|
|
5204
|
+
if (section.groups.length === 0) {
|
|
5133
5205
|
return [
|
|
5134
|
-
{
|
|
5206
|
+
{
|
|
5207
|
+
type: "subHeader",
|
|
5208
|
+
key: `empty:${repoName}`,
|
|
5209
|
+
navId: null,
|
|
5210
|
+
text: "No open issues"
|
|
5211
|
+
}
|
|
5135
5212
|
];
|
|
5136
|
-
|
|
5213
|
+
}
|
|
5214
|
+
const activeGroup = section.groups.find((g) => g.subId === statusGroupId) ?? section.groups[0];
|
|
5137
5215
|
if (!activeGroup) return [];
|
|
5216
|
+
if (activeGroup.issues.length === 0) {
|
|
5217
|
+
return [
|
|
5218
|
+
{
|
|
5219
|
+
type: "subHeader",
|
|
5220
|
+
key: `empty-group:${statusGroupId}`,
|
|
5221
|
+
navId: null,
|
|
5222
|
+
text: "No issues in this status group"
|
|
5223
|
+
}
|
|
5224
|
+
];
|
|
5225
|
+
}
|
|
5138
5226
|
return activeGroup.issues.map((issue) => ({
|
|
5139
5227
|
type: "issue",
|
|
5140
5228
|
key: `gh:${section.repo.name}:${issue.number}`,
|
|
@@ -5161,13 +5249,13 @@ function findSelectedIssueWithRepo(repos, selectedId) {
|
|
|
5161
5249
|
return null;
|
|
5162
5250
|
}
|
|
5163
5251
|
function RefreshAge({ lastRefresh }) {
|
|
5164
|
-
const [, setTick] =
|
|
5252
|
+
const [, setTick] = useState16(0);
|
|
5165
5253
|
useEffect9(() => {
|
|
5166
5254
|
const id = setInterval(() => setTick((t) => t + 1), 1e4);
|
|
5167
5255
|
return () => clearInterval(id);
|
|
5168
5256
|
}, []);
|
|
5169
5257
|
if (!lastRefresh) return null;
|
|
5170
|
-
return /* @__PURE__ */
|
|
5258
|
+
return /* @__PURE__ */ jsxs25(Text23, { color: refreshAgeColor(lastRefresh), children: [
|
|
5171
5259
|
"Updated ",
|
|
5172
5260
|
timeAgo(lastRefresh)
|
|
5173
5261
|
] });
|
|
@@ -5191,19 +5279,16 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5191
5279
|
clearPendingMutation
|
|
5192
5280
|
} = useData(config2, options, refreshMs);
|
|
5193
5281
|
const allRepos = useMemo3(() => data?.repos ?? [], [data?.repos]);
|
|
5194
|
-
const allTasks = useMemo3(
|
|
5195
|
-
() => config2.ticktick.enabled ? data?.ticktick ?? [] : [],
|
|
5196
|
-
[data?.ticktick, config2.ticktick.enabled]
|
|
5197
|
-
);
|
|
5198
5282
|
const allActivity = useMemo3(() => data?.activity ?? [], [data?.activity]);
|
|
5199
5283
|
const ui = useUIState();
|
|
5200
|
-
const
|
|
5201
|
-
const [
|
|
5202
|
-
const
|
|
5284
|
+
const panelFocus = usePanelFocus(3);
|
|
5285
|
+
const [searchQuery, setSearchQuery] = useState16("");
|
|
5286
|
+
const [mineOnly, setMineOnly] = useState16(false);
|
|
5287
|
+
const handleToggleMine = useCallback12(() => {
|
|
5203
5288
|
setMineOnly((prev) => !prev);
|
|
5204
5289
|
}, []);
|
|
5205
5290
|
const { toasts, toast, handleErrorAction } = useToast();
|
|
5206
|
-
const [logVisible, setLogVisible] =
|
|
5291
|
+
const [logVisible, setLogVisible] = useState16(false);
|
|
5207
5292
|
const { entries: logEntries, pushEntry, undoLast, hasUndoable } = useActionLog(toast, refresh);
|
|
5208
5293
|
useEffect9(() => {
|
|
5209
5294
|
const last = logEntries[logEntries.length - 1];
|
|
@@ -5227,69 +5312,75 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5227
5312
|
const q = searchQuery.toLowerCase();
|
|
5228
5313
|
return filtered.map((rd) => ({ ...rd, issues: rd.issues.filter((i) => i.title.toLowerCase().includes(q)) })).filter((rd) => rd.issues.length > 0);
|
|
5229
5314
|
}, [allRepos, searchQuery, mineOnly, config2.board.assignee]);
|
|
5230
|
-
const
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
|
|
5239
|
-
|
|
5240
|
-
const [
|
|
5241
|
-
const
|
|
5242
|
-
const
|
|
5243
|
-
|
|
5244
|
-
|
|
5245
|
-
setActiveTabId(tabs[(Math.max(activeTabIdx, 0) + 1) % tabs.length]?.id ?? null);
|
|
5246
|
-
setActiveStatusId(null);
|
|
5247
|
-
}, [activeTabIdx, tabs]);
|
|
5248
|
-
const prevTab = useCallback11(() => {
|
|
5249
|
-
if (tabs.length === 0) return;
|
|
5250
|
-
setActiveTabId(tabs[(Math.max(activeTabIdx, 0) - 1 + tabs.length) % tabs.length]?.id ?? null);
|
|
5251
|
-
setActiveStatusId(null);
|
|
5252
|
-
}, [activeTabIdx, tabs]);
|
|
5253
|
-
const jumpToTab = useCallback11(
|
|
5254
|
-
(idx) => {
|
|
5255
|
-
const tab = tabs[idx];
|
|
5256
|
-
if (tab) {
|
|
5257
|
-
setActiveTabId(tab.id);
|
|
5258
|
-
setActiveStatusId(null);
|
|
5259
|
-
}
|
|
5260
|
-
},
|
|
5261
|
-
[tabs]
|
|
5315
|
+
const boardTree = useMemo3(() => buildBoardTree(repos, allActivity), [repos, allActivity]);
|
|
5316
|
+
const [selectedRepoIdx, setSelectedRepoIdx] = useState16(0);
|
|
5317
|
+
const clampedRepoIdx = Math.min(selectedRepoIdx, Math.max(0, boardTree.sections.length - 1));
|
|
5318
|
+
const reposNav = {
|
|
5319
|
+
moveUp: useCallback12(() => setSelectedRepoIdx((i) => Math.max(0, i - 1)), []),
|
|
5320
|
+
moveDown: useCallback12(
|
|
5321
|
+
() => setSelectedRepoIdx((i) => Math.min(Math.max(0, boardTree.sections.length - 1), i + 1)),
|
|
5322
|
+
[boardTree.sections.length]
|
|
5323
|
+
)
|
|
5324
|
+
};
|
|
5325
|
+
const [selectedStatusIdx, setSelectedStatusIdx] = useState16(0);
|
|
5326
|
+
const selectedSection = boardTree.sections[clampedRepoIdx] ?? null;
|
|
5327
|
+
const clampedStatusIdx = Math.min(
|
|
5328
|
+
selectedStatusIdx,
|
|
5329
|
+
Math.max(0, (selectedSection?.groups.length ?? 1) - 1)
|
|
5262
5330
|
);
|
|
5263
|
-
const
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
|
|
5331
|
+
const statusesNav = {
|
|
5332
|
+
moveUp: useCallback12(() => setSelectedStatusIdx((i) => Math.max(0, i - 1)), []),
|
|
5333
|
+
moveDown: useCallback12(
|
|
5334
|
+
() => setSelectedStatusIdx(
|
|
5335
|
+
(i) => Math.min(Math.max(0, (selectedSection?.groups.length ?? 1) - 1), i + 1)
|
|
5336
|
+
),
|
|
5337
|
+
[selectedSection?.groups.length]
|
|
5338
|
+
)
|
|
5339
|
+
};
|
|
5340
|
+
const [activitySelectedIdx, setActivitySelectedIdx] = useState16(0);
|
|
5341
|
+
const clampedActivityIdx = Math.min(
|
|
5342
|
+
activitySelectedIdx,
|
|
5343
|
+
Math.max(0, boardTree.activity.length - 1)
|
|
5267
5344
|
);
|
|
5268
|
-
const
|
|
5269
|
-
|
|
5270
|
-
|
|
5271
|
-
|
|
5272
|
-
|
|
5273
|
-
|
|
5274
|
-
|
|
5275
|
-
|
|
5276
|
-
const
|
|
5277
|
-
|
|
5278
|
-
|
|
5279
|
-
|
|
5345
|
+
const activityNav = {
|
|
5346
|
+
moveUp: useCallback12(() => setActivitySelectedIdx((i) => Math.max(0, i - 1)), []),
|
|
5347
|
+
moveDown: useCallback12(
|
|
5348
|
+
() => setActivitySelectedIdx((i) => Math.min(Math.max(0, boardTree.activity.length - 1), i + 1)),
|
|
5349
|
+
[boardTree.activity.length]
|
|
5350
|
+
)
|
|
5351
|
+
};
|
|
5352
|
+
const selectedRepoName = selectedSection?.sectionId ?? null;
|
|
5353
|
+
const selectedStatusGroup = selectedSection?.groups[clampedStatusIdx] ?? null;
|
|
5354
|
+
const selectedStatusGroupId = selectedStatusGroup?.subId ?? null;
|
|
5355
|
+
const onRepoEnter = useCallback12(() => {
|
|
5356
|
+
setSelectedStatusIdx(0);
|
|
5357
|
+
panelFocus.focusPanel(3);
|
|
5358
|
+
}, [panelFocus]);
|
|
5359
|
+
const onStatusEnter = useCallback12(() => {
|
|
5360
|
+
panelFocus.focusPanel(3);
|
|
5361
|
+
}, [panelFocus]);
|
|
5362
|
+
const onActivityEnter = useCallback12(() => {
|
|
5363
|
+
const event = boardTree.activity[clampedActivityIdx];
|
|
5364
|
+
if (!event) return;
|
|
5365
|
+
const repoIdx = boardTree.sections.findIndex(
|
|
5366
|
+
(s) => s.repo.shortName === event.repoShortName || s.sectionId.endsWith(`/${event.repoShortName}`)
|
|
5280
5367
|
);
|
|
5281
|
-
|
|
5368
|
+
if (repoIdx >= 0) {
|
|
5369
|
+
setSelectedRepoIdx(repoIdx);
|
|
5370
|
+
setSelectedStatusIdx(0);
|
|
5371
|
+
panelFocus.focusPanel(3);
|
|
5372
|
+
}
|
|
5373
|
+
}, [boardTree, clampedActivityIdx, panelFocus]);
|
|
5282
5374
|
const navItems = useMemo3(
|
|
5283
|
-
() =>
|
|
5284
|
-
[
|
|
5375
|
+
() => buildNavItemsForRepo(boardTree.sections, selectedRepoName, selectedStatusGroupId),
|
|
5376
|
+
[boardTree.sections, selectedRepoName, selectedStatusGroupId]
|
|
5285
5377
|
);
|
|
5286
5378
|
const nav = useNavigation(navItems);
|
|
5287
|
-
const getRepoForId =
|
|
5379
|
+
const getRepoForId = useCallback12((id) => {
|
|
5288
5380
|
if (id.startsWith("gh:")) {
|
|
5289
5381
|
const parts = id.split(":");
|
|
5290
5382
|
return parts.length >= 3 ? `${parts[1]}` : null;
|
|
5291
5383
|
}
|
|
5292
|
-
if (id.startsWith("tt:")) return "ticktick";
|
|
5293
5384
|
return null;
|
|
5294
5385
|
}, []);
|
|
5295
5386
|
const multiSelect = useMultiSelect(getRepoForId);
|
|
@@ -5313,8 +5404,8 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5313
5404
|
const pendingPickRef = useRef13(null);
|
|
5314
5405
|
const labelCacheRef = useRef13({});
|
|
5315
5406
|
const commentCacheRef = useRef13({});
|
|
5316
|
-
const [commentTick, setCommentTick] =
|
|
5317
|
-
const handleFetchComments =
|
|
5407
|
+
const [commentTick, setCommentTick] = useState16(0);
|
|
5408
|
+
const handleFetchComments = useCallback12((repo, issueNumber) => {
|
|
5318
5409
|
const key = `${repo}:${issueNumber}`;
|
|
5319
5410
|
if (commentCacheRef.current[key] !== void 0) return;
|
|
5320
5411
|
commentCacheRef.current[key] = "loading";
|
|
@@ -5327,7 +5418,7 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5327
5418
|
setCommentTick((t) => t + 1);
|
|
5328
5419
|
});
|
|
5329
5420
|
}, []);
|
|
5330
|
-
const handleCreateIssueWithPrompt =
|
|
5421
|
+
const handleCreateIssueWithPrompt = useCallback12(
|
|
5331
5422
|
(repo, title, body, dueDate, labels) => {
|
|
5332
5423
|
actions.handleCreateIssue(repo, title, body, dueDate, labels).then((result) => {
|
|
5333
5424
|
if (result) {
|
|
@@ -5338,7 +5429,7 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5338
5429
|
},
|
|
5339
5430
|
[actions, ui]
|
|
5340
5431
|
);
|
|
5341
|
-
const handleConfirmPick =
|
|
5432
|
+
const handleConfirmPick = useCallback12(() => {
|
|
5342
5433
|
const pending = pendingPickRef.current;
|
|
5343
5434
|
pendingPickRef.current = null;
|
|
5344
5435
|
ui.exitOverlay();
|
|
@@ -5356,12 +5447,12 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5356
5447
|
})
|
|
5357
5448
|
);
|
|
5358
5449
|
}, [config2, toast, refresh, ui]);
|
|
5359
|
-
const handleCancelPick =
|
|
5450
|
+
const handleCancelPick = useCallback12(() => {
|
|
5360
5451
|
pendingPickRef.current = null;
|
|
5361
5452
|
ui.exitOverlay();
|
|
5362
5453
|
}, [ui]);
|
|
5363
|
-
const [focusLabel, setFocusLabel] =
|
|
5364
|
-
const handleEnterFocus =
|
|
5454
|
+
const [focusLabel, setFocusLabel] = useState16(null);
|
|
5455
|
+
const handleEnterFocus = useCallback12(() => {
|
|
5365
5456
|
const id = nav.selectedId;
|
|
5366
5457
|
if (!id || isHeaderId(id)) return;
|
|
5367
5458
|
let label = "";
|
|
@@ -5371,20 +5462,16 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5371
5462
|
const rc = config2.repos.find((r) => r.name === found.repoName);
|
|
5372
5463
|
label = `${rc?.shortName ?? found.repoName}#${found.issue.number} \u2014 ${found.issue.title}`;
|
|
5373
5464
|
}
|
|
5374
|
-
} else if (id.startsWith("tt:")) {
|
|
5375
|
-
const taskId = id.slice(3);
|
|
5376
|
-
const task2 = tasks.find((t) => t.id === taskId);
|
|
5377
|
-
if (task2) label = task2.title;
|
|
5378
5465
|
}
|
|
5379
5466
|
if (!label) return;
|
|
5380
5467
|
setFocusLabel(label);
|
|
5381
5468
|
ui.enterFocus();
|
|
5382
|
-
}, [nav.selectedId, repos,
|
|
5383
|
-
const handleFocusExit =
|
|
5469
|
+
}, [nav.selectedId, repos, config2.repos, ui]);
|
|
5470
|
+
const handleFocusExit = useCallback12(() => {
|
|
5384
5471
|
setFocusLabel(null);
|
|
5385
5472
|
ui.exitToNormal();
|
|
5386
5473
|
}, [ui]);
|
|
5387
|
-
const handleFocusEndAction =
|
|
5474
|
+
const handleFocusEndAction = useCallback12(
|
|
5388
5475
|
(action) => {
|
|
5389
5476
|
switch (action) {
|
|
5390
5477
|
case "restart":
|
|
@@ -5410,9 +5497,9 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5410
5497
|
},
|
|
5411
5498
|
[toast, ui]
|
|
5412
5499
|
);
|
|
5413
|
-
const [focusKey, setFocusKey] =
|
|
5500
|
+
const [focusKey, setFocusKey] = useState16(0);
|
|
5414
5501
|
const { stdout } = useStdout();
|
|
5415
|
-
const [termSize, setTermSize] =
|
|
5502
|
+
const [termSize, setTermSize] = useState16({
|
|
5416
5503
|
cols: stdout?.columns ?? 80,
|
|
5417
5504
|
rows: stdout?.rows ?? 24
|
|
5418
5505
|
});
|
|
@@ -5424,24 +5511,33 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5424
5511
|
stdout.off("resize", onResize);
|
|
5425
5512
|
};
|
|
5426
5513
|
}, [stdout]);
|
|
5427
|
-
const
|
|
5428
|
-
const detailPanelWidth =
|
|
5514
|
+
const layoutMode = getLayoutMode(termSize.cols);
|
|
5515
|
+
const detailPanelWidth = layoutMode === "wide" ? getDetailWidth(termSize.cols) : Math.floor(termSize.cols * 0.35);
|
|
5516
|
+
const showDetailPanel = layoutMode === "wide";
|
|
5517
|
+
const usableWidth = termSize.cols - 2;
|
|
5518
|
+
const issuesPanelWidth = Math.max(
|
|
5519
|
+
20,
|
|
5520
|
+
layoutMode === "wide" ? usableWidth - LEFT_COL_WIDTH - getDetailWidth(termSize.cols) : layoutMode === "medium" ? usableWidth - LEFT_COL_WIDTH : usableWidth
|
|
5521
|
+
);
|
|
5522
|
+
const activityPanelWidth = usableWidth;
|
|
5429
5523
|
const overlayBarRows = ui.state.mode === "search" || ui.state.mode === "overlay:comment" ? 1 : 0;
|
|
5430
5524
|
const toastRows = toasts.length;
|
|
5431
5525
|
const logPaneRows = logVisible ? 4 : 0;
|
|
5432
|
-
const
|
|
5433
|
-
|
|
5434
|
-
|
|
5435
|
-
termSize.rows - chromeRows - overlayBarRows - toastRows - logPaneRows
|
|
5526
|
+
const totalPanelHeight = Math.max(
|
|
5527
|
+
8,
|
|
5528
|
+
termSize.rows - CHROME_ROWS - overlayBarRows - toastRows - logPaneRows
|
|
5436
5529
|
);
|
|
5530
|
+
const issuesPanelHeight = Math.max(5, totalPanelHeight - ACTIVITY_HEIGHT);
|
|
5437
5531
|
const flatRows = useMemo3(
|
|
5438
|
-
() =>
|
|
5439
|
-
[
|
|
5532
|
+
() => buildFlatRowsForRepo(boardTree.sections, selectedRepoName, selectedStatusGroupId),
|
|
5533
|
+
[boardTree.sections, selectedRepoName, selectedStatusGroupId]
|
|
5440
5534
|
);
|
|
5441
5535
|
const scrollRef = useRef13(0);
|
|
5442
|
-
const
|
|
5443
|
-
|
|
5444
|
-
|
|
5536
|
+
const prevRepoRef = useRef13(null);
|
|
5537
|
+
const prevStatusRef = useRef13(null);
|
|
5538
|
+
if (selectedRepoName !== prevRepoRef.current || selectedStatusGroupId !== prevStatusRef.current) {
|
|
5539
|
+
prevRepoRef.current = selectedRepoName;
|
|
5540
|
+
prevStatusRef.current = selectedStatusGroupId;
|
|
5445
5541
|
scrollRef.current = 0;
|
|
5446
5542
|
}
|
|
5447
5543
|
const selectedRowIdx = useMemo3(
|
|
@@ -5451,35 +5547,29 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5451
5547
|
if (selectedRowIdx >= 0) {
|
|
5452
5548
|
if (selectedRowIdx < scrollRef.current) {
|
|
5453
5549
|
scrollRef.current = selectedRowIdx;
|
|
5454
|
-
} else if (selectedRowIdx >= scrollRef.current +
|
|
5455
|
-
scrollRef.current = selectedRowIdx -
|
|
5550
|
+
} else if (selectedRowIdx >= scrollRef.current + issuesPanelHeight) {
|
|
5551
|
+
scrollRef.current = selectedRowIdx - issuesPanelHeight + 1;
|
|
5456
5552
|
}
|
|
5457
5553
|
}
|
|
5458
|
-
const maxOffset = Math.max(0, flatRows.length -
|
|
5554
|
+
const maxOffset = Math.max(0, flatRows.length - issuesPanelHeight);
|
|
5459
5555
|
scrollRef.current = Math.max(0, Math.min(scrollRef.current, maxOffset));
|
|
5460
|
-
const visibleRows = flatRows.slice(scrollRef.current, scrollRef.current +
|
|
5556
|
+
const visibleRows = flatRows.slice(scrollRef.current, scrollRef.current + issuesPanelHeight);
|
|
5461
5557
|
const hasMoreAbove = scrollRef.current > 0;
|
|
5462
|
-
const hasMoreBelow = scrollRef.current +
|
|
5558
|
+
const hasMoreBelow = scrollRef.current + issuesPanelHeight < flatRows.length;
|
|
5463
5559
|
const aboveCount = scrollRef.current;
|
|
5464
|
-
const belowCount = flatRows.length - scrollRef.current -
|
|
5560
|
+
const belowCount = flatRows.length - scrollRef.current - issuesPanelHeight;
|
|
5465
5561
|
const selectedItem = useMemo3(() => {
|
|
5466
5562
|
const id = nav.selectedId;
|
|
5467
|
-
if (!id || isHeaderId(id)) return { issue: null,
|
|
5563
|
+
if (!id || isHeaderId(id)) return { issue: null, repoName: null };
|
|
5468
5564
|
if (id.startsWith("gh:")) {
|
|
5469
5565
|
for (const rd of repos) {
|
|
5470
5566
|
for (const issue of rd.issues) {
|
|
5471
|
-
if (`gh:${rd.repo.name}:${issue.number}` === id)
|
|
5472
|
-
return { issue, task: null, repoName: rd.repo.name };
|
|
5567
|
+
if (`gh:${rd.repo.name}:${issue.number}` === id) return { issue, repoName: rd.repo.name };
|
|
5473
5568
|
}
|
|
5474
5569
|
}
|
|
5475
5570
|
}
|
|
5476
|
-
|
|
5477
|
-
|
|
5478
|
-
const task2 = tasks.find((t) => t.id === taskId);
|
|
5479
|
-
if (task2) return { issue: null, task: task2, repoName: null };
|
|
5480
|
-
}
|
|
5481
|
-
return { issue: null, task: null, repoName: null };
|
|
5482
|
-
}, [nav.selectedId, repos, tasks]);
|
|
5571
|
+
return { issue: null, repoName: null };
|
|
5572
|
+
}, [nav.selectedId, repos]);
|
|
5483
5573
|
const currentCommentsState = useMemo3(() => {
|
|
5484
5574
|
if (!(selectedItem.issue && selectedItem.repoName)) return null;
|
|
5485
5575
|
return commentCacheRef.current[`${selectedItem.repoName}:${selectedItem.issue.number}`] ?? null;
|
|
@@ -5490,20 +5580,20 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5490
5580
|
}, [selectedItem.repoName, config2.repos]);
|
|
5491
5581
|
const selectedRepoStatusOptions = useMemo3(() => {
|
|
5492
5582
|
const repoName = multiSelect.count > 0 ? multiSelect.constrainedRepo : selectedItem.repoName;
|
|
5493
|
-
if (!repoName
|
|
5583
|
+
if (!repoName) return [];
|
|
5494
5584
|
const rd = repos.find((r) => r.repo.name === repoName);
|
|
5495
5585
|
return rd?.statusOptions ?? [];
|
|
5496
5586
|
}, [selectedItem.repoName, repos, multiSelect.count, multiSelect.constrainedRepo]);
|
|
5497
|
-
const handleOpen =
|
|
5587
|
+
const handleOpen = useCallback12(() => {
|
|
5498
5588
|
const found = findSelectedIssueWithRepo(repos, nav.selectedId);
|
|
5499
5589
|
if (found) openInBrowser(found.issue.url);
|
|
5500
5590
|
}, [repos, nav.selectedId]);
|
|
5501
|
-
const handleSlack =
|
|
5591
|
+
const handleSlack = useCallback12(() => {
|
|
5502
5592
|
const found = findSelectedIssueWithRepo(repos, nav.selectedId);
|
|
5503
5593
|
if (!found?.issue.slackThreadUrl) return;
|
|
5504
5594
|
openInBrowser(found.issue.slackThreadUrl);
|
|
5505
5595
|
}, [repos, nav.selectedId]);
|
|
5506
|
-
const handleCopyLink =
|
|
5596
|
+
const handleCopyLink = useCallback12(() => {
|
|
5507
5597
|
const found = findSelectedIssueWithRepo(repos, nav.selectedId);
|
|
5508
5598
|
if (!found) return;
|
|
5509
5599
|
const rc = config2.repos.find((r) => r.name === found.repoName);
|
|
@@ -5529,17 +5619,12 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5529
5619
|
}
|
|
5530
5620
|
}, [repos, nav.selectedId, config2.repos, toast]);
|
|
5531
5621
|
const multiSelectType = useMemo3(() => {
|
|
5532
|
-
let hasGh = false;
|
|
5533
|
-
let hasTt = false;
|
|
5534
5622
|
for (const id of multiSelect.selected) {
|
|
5535
|
-
if (id.startsWith("
|
|
5536
|
-
if (id.startsWith("tt:")) hasTt = true;
|
|
5623
|
+
if (id.startsWith("tt:")) return "ticktick";
|
|
5537
5624
|
}
|
|
5538
|
-
if (hasGh && hasTt) return "mixed";
|
|
5539
|
-
if (hasTt) return "ticktick";
|
|
5540
5625
|
return "github";
|
|
5541
5626
|
}, [multiSelect.selected]);
|
|
5542
|
-
const handleBulkAction =
|
|
5627
|
+
const handleBulkAction = useCallback12(
|
|
5543
5628
|
(action) => {
|
|
5544
5629
|
const ids = multiSelect.selected;
|
|
5545
5630
|
switch (action.type) {
|
|
@@ -5572,10 +5657,9 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5572
5657
|
case "statusChange":
|
|
5573
5658
|
ui.enterStatus();
|
|
5574
5659
|
return;
|
|
5575
|
-
// status picker will call handleBulkStatusSelect on select
|
|
5576
5660
|
case "complete":
|
|
5577
5661
|
case "delete":
|
|
5578
|
-
toast.info(`Bulk ${action.type} not yet implemented
|
|
5662
|
+
toast.info(`Bulk ${action.type} not yet implemented`);
|
|
5579
5663
|
ui.exitOverlay();
|
|
5580
5664
|
multiSelect.clear();
|
|
5581
5665
|
return;
|
|
@@ -5583,7 +5667,7 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5583
5667
|
},
|
|
5584
5668
|
[multiSelect, actions, ui, toast]
|
|
5585
5669
|
);
|
|
5586
|
-
const handleBulkStatusSelect =
|
|
5670
|
+
const handleBulkStatusSelect = useCallback12(
|
|
5587
5671
|
(optionId) => {
|
|
5588
5672
|
const ids = multiSelect.selected;
|
|
5589
5673
|
ui.exitOverlay();
|
|
@@ -5599,30 +5683,28 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5599
5683
|
},
|
|
5600
5684
|
[multiSelect, actions, ui]
|
|
5601
5685
|
);
|
|
5602
|
-
const handleFuzzySelect =
|
|
5686
|
+
const handleFuzzySelect = useCallback12(
|
|
5603
5687
|
(navId) => {
|
|
5604
5688
|
nav.select(navId);
|
|
5605
5689
|
if (navId.startsWith("gh:")) {
|
|
5606
5690
|
const parts = navId.split(":");
|
|
5607
5691
|
const repoName = parts[1];
|
|
5608
5692
|
if (parts.length >= 3 && repoName) {
|
|
5609
|
-
|
|
5610
|
-
|
|
5611
|
-
|
|
5612
|
-
|
|
5613
|
-
|
|
5614
|
-
|
|
5615
|
-
|
|
5693
|
+
const repoIdx = boardTree.sections.findIndex((s) => s.sectionId === repoName);
|
|
5694
|
+
if (repoIdx >= 0) {
|
|
5695
|
+
setSelectedRepoIdx(repoIdx);
|
|
5696
|
+
const section = boardTree.sections[repoIdx];
|
|
5697
|
+
const issueNum = parts[2] ? Number(parts[2]) : null;
|
|
5698
|
+
const groupIdx = section?.groups.findIndex((g) => g.issues.some((iss) => iss.number === issueNum)) ?? -1;
|
|
5699
|
+
setSelectedStatusIdx(Math.max(0, groupIdx));
|
|
5700
|
+
}
|
|
5616
5701
|
}
|
|
5617
|
-
} else if (navId.startsWith("tt:")) {
|
|
5618
|
-
setActiveTabId("ticktick");
|
|
5619
|
-
setActiveStatusId(null);
|
|
5620
5702
|
}
|
|
5621
5703
|
ui.exitToNormal();
|
|
5622
5704
|
},
|
|
5623
5705
|
[nav, ui, boardTree]
|
|
5624
5706
|
);
|
|
5625
|
-
const onSearchEscape =
|
|
5707
|
+
const onSearchEscape = useCallback12(() => {
|
|
5626
5708
|
ui.exitOverlay();
|
|
5627
5709
|
setSearchQuery("");
|
|
5628
5710
|
}, [ui]);
|
|
@@ -5652,11 +5734,16 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5652
5734
|
handleToggleLog: () => setLogVisible((v) => !v)
|
|
5653
5735
|
},
|
|
5654
5736
|
onSearchEscape,
|
|
5655
|
-
|
|
5656
|
-
|
|
5737
|
+
panelFocus,
|
|
5738
|
+
reposNav,
|
|
5739
|
+
statusesNav,
|
|
5740
|
+
activityNav,
|
|
5741
|
+
onRepoEnter,
|
|
5742
|
+
onStatusEnter,
|
|
5743
|
+
onActivityEnter
|
|
5657
5744
|
});
|
|
5658
5745
|
if (status === "loading" && !data) {
|
|
5659
|
-
return /* @__PURE__ */
|
|
5746
|
+
return /* @__PURE__ */ jsx25(Box24, { flexDirection: "column", padding: 1, children: /* @__PURE__ */ jsx25(Spinner4, { label: "Loading dashboard..." }) });
|
|
5660
5747
|
}
|
|
5661
5748
|
const now = data?.fetchedAt ?? /* @__PURE__ */ new Date();
|
|
5662
5749
|
const dateStr = now.toLocaleDateString("en-US", {
|
|
@@ -5664,36 +5751,120 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5664
5751
|
day: "numeric",
|
|
5665
5752
|
year: "numeric"
|
|
5666
5753
|
});
|
|
5667
|
-
|
|
5668
|
-
|
|
5669
|
-
|
|
5670
|
-
|
|
5754
|
+
const reposData = boardTree.sections.map(({ repo, groups }) => ({
|
|
5755
|
+
name: repo.name,
|
|
5756
|
+
openCount: groups.reduce((s, g) => s + g.issues.length, 0)
|
|
5757
|
+
}));
|
|
5758
|
+
const statusesData = (selectedSection?.groups ?? []).map(({ label, subId, issues }) => ({
|
|
5759
|
+
id: subId,
|
|
5760
|
+
label,
|
|
5761
|
+
count: issues.length
|
|
5762
|
+
}));
|
|
5763
|
+
const reposPanel = /* @__PURE__ */ jsx25(
|
|
5764
|
+
ReposPanel,
|
|
5765
|
+
{
|
|
5766
|
+
repos: reposData,
|
|
5767
|
+
selectedIdx: clampedRepoIdx,
|
|
5768
|
+
isActive: panelFocus.activePanelId === 1,
|
|
5769
|
+
width: LEFT_COL_WIDTH
|
|
5770
|
+
}
|
|
5771
|
+
);
|
|
5772
|
+
const statusesPanel = /* @__PURE__ */ jsx25(
|
|
5773
|
+
StatusesPanel,
|
|
5774
|
+
{
|
|
5775
|
+
groups: statusesData,
|
|
5776
|
+
selectedIdx: clampedStatusIdx,
|
|
5777
|
+
isActive: panelFocus.activePanelId === 2,
|
|
5778
|
+
width: LEFT_COL_WIDTH,
|
|
5779
|
+
flexGrow: 1
|
|
5780
|
+
}
|
|
5781
|
+
);
|
|
5782
|
+
const issuesPanelTitle = `[3] Issues${selectedSection ? ` \u2014 ${selectedSection.repo.shortName}` : ""}${selectedStatusGroup ? ` / ${selectedStatusGroup.label}` : ""}`;
|
|
5783
|
+
const issuesPanel = /* @__PURE__ */ jsxs25(
|
|
5784
|
+
Panel,
|
|
5785
|
+
{
|
|
5786
|
+
title: issuesPanelTitle,
|
|
5787
|
+
isActive: panelFocus.activePanelId === 3,
|
|
5788
|
+
width: issuesPanelWidth,
|
|
5789
|
+
flexGrow: 1,
|
|
5790
|
+
children: [
|
|
5791
|
+
hasMoreAbove ? /* @__PURE__ */ jsxs25(Text23, { color: "gray", dimColor: true, children: [
|
|
5792
|
+
" ",
|
|
5793
|
+
"\u25B2",
|
|
5794
|
+
" ",
|
|
5795
|
+
aboveCount,
|
|
5796
|
+
" more above"
|
|
5797
|
+
] }) : null,
|
|
5798
|
+
visibleRows.map((row) => /* @__PURE__ */ jsx25(
|
|
5799
|
+
RowRenderer,
|
|
5800
|
+
{
|
|
5801
|
+
row,
|
|
5802
|
+
selectedId: nav.selectedId,
|
|
5803
|
+
selfLogin: config2.board.assignee,
|
|
5804
|
+
isMultiSelected: ui.state.mode === "multiSelect" && row.navId ? multiSelect.isSelected(row.navId) : void 0
|
|
5805
|
+
},
|
|
5806
|
+
row.key
|
|
5807
|
+
)),
|
|
5808
|
+
hasMoreBelow ? /* @__PURE__ */ jsxs25(Text23, { color: "gray", dimColor: true, children: [
|
|
5809
|
+
" ",
|
|
5810
|
+
"\u25BC",
|
|
5811
|
+
" ",
|
|
5812
|
+
belowCount,
|
|
5813
|
+
" more below"
|
|
5814
|
+
] }) : null
|
|
5815
|
+
]
|
|
5816
|
+
}
|
|
5817
|
+
);
|
|
5818
|
+
const detailPanel = showDetailPanel ? /* @__PURE__ */ jsx25(
|
|
5819
|
+
DetailPanel,
|
|
5820
|
+
{
|
|
5821
|
+
issue: selectedItem.issue,
|
|
5822
|
+
width: detailPanelWidth,
|
|
5823
|
+
isActive: panelFocus.activePanelId === 0,
|
|
5824
|
+
issueRepo: selectedItem.repoName,
|
|
5825
|
+
fetchComments: handleFetchComments,
|
|
5826
|
+
commentsState: currentCommentsState
|
|
5827
|
+
}
|
|
5828
|
+
) : null;
|
|
5829
|
+
const activityPanel = /* @__PURE__ */ jsx25(
|
|
5830
|
+
ActivityPanel,
|
|
5831
|
+
{
|
|
5832
|
+
events: boardTree.activity,
|
|
5833
|
+
selectedIdx: clampedActivityIdx,
|
|
5834
|
+
isActive: panelFocus.activePanelId === 4,
|
|
5835
|
+
height: ACTIVITY_HEIGHT,
|
|
5836
|
+
width: activityPanelWidth
|
|
5837
|
+
}
|
|
5838
|
+
);
|
|
5839
|
+
return /* @__PURE__ */ jsxs25(Box24, { flexDirection: "column", paddingX: 1, children: [
|
|
5840
|
+
/* @__PURE__ */ jsxs25(Box24, { children: [
|
|
5841
|
+
/* @__PURE__ */ jsx25(Text23, { color: "cyan", bold: true, children: "HOG BOARD" }),
|
|
5842
|
+
activeProfile ? /* @__PURE__ */ jsxs25(Text23, { color: "yellow", children: [
|
|
5671
5843
|
" [",
|
|
5672
5844
|
activeProfile,
|
|
5673
5845
|
"]"
|
|
5674
5846
|
] }) : null,
|
|
5675
|
-
/* @__PURE__ */
|
|
5847
|
+
/* @__PURE__ */ jsxs25(Text23, { color: "gray", children: [
|
|
5676
5848
|
" ",
|
|
5677
5849
|
"\u2014",
|
|
5678
5850
|
" ",
|
|
5679
5851
|
dateStr
|
|
5680
5852
|
] }),
|
|
5681
|
-
/* @__PURE__ */
|
|
5682
|
-
isRefreshing ? /* @__PURE__ */
|
|
5683
|
-
/* @__PURE__ */
|
|
5684
|
-
/* @__PURE__ */
|
|
5685
|
-
] }) : /* @__PURE__ */
|
|
5686
|
-
/* @__PURE__ */
|
|
5687
|
-
consecutiveFailures > 0 ? /* @__PURE__ */
|
|
5853
|
+
/* @__PURE__ */ jsx25(Text23, { children: " " }),
|
|
5854
|
+
isRefreshing ? /* @__PURE__ */ jsxs25(Fragment5, { children: [
|
|
5855
|
+
/* @__PURE__ */ jsx25(Spinner4, { label: "" }),
|
|
5856
|
+
/* @__PURE__ */ jsx25(Text23, { color: "cyan", children: " Refreshing..." })
|
|
5857
|
+
] }) : /* @__PURE__ */ jsxs25(Fragment5, { children: [
|
|
5858
|
+
/* @__PURE__ */ jsx25(RefreshAge, { lastRefresh }),
|
|
5859
|
+
consecutiveFailures > 0 ? /* @__PURE__ */ jsx25(Text23, { color: "red", children: " (!)" }) : null
|
|
5688
5860
|
] }),
|
|
5689
|
-
autoRefreshPaused ? /* @__PURE__ */
|
|
5861
|
+
autoRefreshPaused ? /* @__PURE__ */ jsx25(Text23, { color: "yellow", children: " Auto-refresh paused \u2014 press r to retry" }) : null
|
|
5690
5862
|
] }),
|
|
5691
|
-
error ? /* @__PURE__ */
|
|
5863
|
+
error ? /* @__PURE__ */ jsxs25(Text23, { color: "red", children: [
|
|
5692
5864
|
"Error: ",
|
|
5693
5865
|
error
|
|
5694
5866
|
] }) : null,
|
|
5695
|
-
/* @__PURE__ */
|
|
5696
|
-
/* @__PURE__ */ jsx23(
|
|
5867
|
+
/* @__PURE__ */ jsx25(
|
|
5697
5868
|
OverlayRenderer,
|
|
5698
5869
|
{
|
|
5699
5870
|
uiState: ui.state,
|
|
@@ -5735,61 +5906,25 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5735
5906
|
onPushEntry: pushEntry
|
|
5736
5907
|
}
|
|
5737
5908
|
),
|
|
5738
|
-
!ui.state.helpVisible && ui.state.mode !== "overlay:status" && ui.state.mode !== "overlay:create" && ui.state.mode !== "overlay:createNl" && ui.state.mode !== "overlay:bulkAction" && ui.state.mode !== "overlay:confirmPick" && ui.state.mode !== "focus" ? /* @__PURE__ */
|
|
5739
|
-
|
|
5740
|
-
|
|
5741
|
-
|
|
5742
|
-
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
5746
|
-
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
aboveCount,
|
|
5754
|
-
" more above"
|
|
5755
|
-
] }) : null,
|
|
5756
|
-
visibleRows.map((row) => /* @__PURE__ */ jsx23(
|
|
5757
|
-
RowRenderer,
|
|
5758
|
-
{
|
|
5759
|
-
row,
|
|
5760
|
-
selectedId: nav.selectedId,
|
|
5761
|
-
selfLogin: config2.board.assignee,
|
|
5762
|
-
isMultiSelected: ui.state.mode === "multiSelect" && row.navId ? multiSelect.isSelected(row.navId) : void 0
|
|
5763
|
-
},
|
|
5764
|
-
row.key
|
|
5765
|
-
)),
|
|
5766
|
-
hasMoreBelow ? /* @__PURE__ */ jsxs23(Text22, { color: "gray", dimColor: true, children: [
|
|
5767
|
-
" ",
|
|
5768
|
-
"\u25BC",
|
|
5769
|
-
" ",
|
|
5770
|
-
belowCount,
|
|
5771
|
-
" more below"
|
|
5772
|
-
] }) : null
|
|
5773
|
-
] }),
|
|
5774
|
-
showDetailPanel ? /* @__PURE__ */ jsx23(Box22, { marginLeft: 1, width: detailPanelWidth, children: /* @__PURE__ */ jsx23(
|
|
5775
|
-
DetailPanel,
|
|
5776
|
-
{
|
|
5777
|
-
issue: selectedItem.issue,
|
|
5778
|
-
task: selectedItem.task,
|
|
5779
|
-
width: detailPanelWidth,
|
|
5780
|
-
issueRepo: selectedItem.repoName,
|
|
5781
|
-
fetchComments: handleFetchComments,
|
|
5782
|
-
commentsState: currentCommentsState
|
|
5783
|
-
}
|
|
5784
|
-
) }) : null
|
|
5785
|
-
] })
|
|
5786
|
-
] }) : null,
|
|
5787
|
-
/* @__PURE__ */ jsx23(ToastContainer, { toasts }),
|
|
5788
|
-
logVisible ? /* @__PURE__ */ jsx23(ActionLog, { entries: logEntries }) : null,
|
|
5789
|
-
/* @__PURE__ */ jsx23(
|
|
5909
|
+
!ui.state.helpVisible && ui.state.mode !== "overlay:status" && ui.state.mode !== "overlay:create" && ui.state.mode !== "overlay:createNl" && ui.state.mode !== "overlay:bulkAction" && ui.state.mode !== "overlay:confirmPick" && ui.state.mode !== "focus" ? /* @__PURE__ */ jsx25(
|
|
5910
|
+
PanelLayout,
|
|
5911
|
+
{
|
|
5912
|
+
cols: termSize.cols,
|
|
5913
|
+
issuesPanelHeight,
|
|
5914
|
+
reposPanel,
|
|
5915
|
+
statusesPanel,
|
|
5916
|
+
issuesPanel,
|
|
5917
|
+
detailPanel,
|
|
5918
|
+
activityPanel
|
|
5919
|
+
}
|
|
5920
|
+
) : null,
|
|
5921
|
+
/* @__PURE__ */ jsx25(ToastContainer, { toasts }),
|
|
5922
|
+
logVisible ? /* @__PURE__ */ jsx25(ActionLog, { entries: logEntries }) : null,
|
|
5923
|
+
/* @__PURE__ */ jsx25(
|
|
5790
5924
|
HintBar,
|
|
5791
5925
|
{
|
|
5792
5926
|
uiMode: ui.state.mode,
|
|
5927
|
+
activePanelId: panelFocus.activePanelId,
|
|
5793
5928
|
multiSelectCount: multiSelect.count,
|
|
5794
5929
|
searchQuery,
|
|
5795
5930
|
mineOnly,
|
|
@@ -5798,7 +5933,7 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5798
5933
|
)
|
|
5799
5934
|
] });
|
|
5800
5935
|
}
|
|
5801
|
-
var PRIORITY_RANK,
|
|
5936
|
+
var PRIORITY_RANK, CHROME_ROWS;
|
|
5802
5937
|
var init_dashboard = __esm({
|
|
5803
5938
|
"src/board/components/dashboard.tsx"() {
|
|
5804
5939
|
"use strict";
|
|
@@ -5811,15 +5946,19 @@ var init_dashboard = __esm({
|
|
|
5811
5946
|
init_use_keyboard();
|
|
5812
5947
|
init_use_multi_select();
|
|
5813
5948
|
init_use_navigation();
|
|
5949
|
+
init_use_panel_focus();
|
|
5814
5950
|
init_use_toast();
|
|
5815
5951
|
init_use_ui_state();
|
|
5816
5952
|
init_action_log();
|
|
5953
|
+
init_activity_panel();
|
|
5817
5954
|
init_detail_panel();
|
|
5818
5955
|
init_hint_bar();
|
|
5819
5956
|
init_overlay_renderer();
|
|
5957
|
+
init_panel();
|
|
5958
|
+
init_panel_layout();
|
|
5959
|
+
init_repos_panel();
|
|
5820
5960
|
init_row_renderer();
|
|
5821
|
-
|
|
5822
|
-
init_tab_bar();
|
|
5961
|
+
init_statuses_panel();
|
|
5823
5962
|
init_toast_container();
|
|
5824
5963
|
PRIORITY_RANK = {
|
|
5825
5964
|
"priority:critical": 0,
|
|
@@ -5827,8 +5966,7 @@ var init_dashboard = __esm({
|
|
|
5827
5966
|
"priority:medium": 2,
|
|
5828
5967
|
"priority:low": 3
|
|
5829
5968
|
};
|
|
5830
|
-
|
|
5831
|
-
CHROME_ROWS_OTHER = 5;
|
|
5969
|
+
CHROME_ROWS = 3;
|
|
5832
5970
|
}
|
|
5833
5971
|
});
|
|
5834
5972
|
|
|
@@ -5838,10 +5976,10 @@ __export(live_exports, {
|
|
|
5838
5976
|
runLiveDashboard: () => runLiveDashboard
|
|
5839
5977
|
});
|
|
5840
5978
|
import { render } from "ink";
|
|
5841
|
-
import { jsx as
|
|
5979
|
+
import { jsx as jsx26 } from "react/jsx-runtime";
|
|
5842
5980
|
async function runLiveDashboard(config2, options, activeProfile) {
|
|
5843
5981
|
const instance = render(
|
|
5844
|
-
/* @__PURE__ */
|
|
5982
|
+
/* @__PURE__ */ jsx26(Dashboard, { config: config2, options, activeProfile: activeProfile ?? null })
|
|
5845
5983
|
);
|
|
5846
5984
|
setInkInstance(instance);
|
|
5847
5985
|
await instance.waitUntilExit();
|
|
@@ -5868,7 +6006,7 @@ function extractSlackUrl(body) {
|
|
|
5868
6006
|
const match = body.match(SLACK_URL_RE2);
|
|
5869
6007
|
return match?.[0];
|
|
5870
6008
|
}
|
|
5871
|
-
function fetchRecentActivity(repoName,
|
|
6009
|
+
function fetchRecentActivity(repoName, shortName2) {
|
|
5872
6010
|
try {
|
|
5873
6011
|
const output = execFileSync4(
|
|
5874
6012
|
"gh",
|
|
@@ -5922,7 +6060,7 @@ function fetchRecentActivity(repoName, shortName) {
|
|
|
5922
6060
|
}
|
|
5923
6061
|
events.push({
|
|
5924
6062
|
type: eventType,
|
|
5925
|
-
repoShortName:
|
|
6063
|
+
repoShortName: shortName2,
|
|
5926
6064
|
issueNumber: ev.number,
|
|
5927
6065
|
actor: ev.actor,
|
|
5928
6066
|
summary,
|
|
@@ -6064,7 +6202,7 @@ __export(format_static_exports, {
|
|
|
6064
6202
|
renderBoardJson: () => renderBoardJson,
|
|
6065
6203
|
renderStaticBoard: () => renderStaticBoard
|
|
6066
6204
|
});
|
|
6067
|
-
function
|
|
6205
|
+
function truncate2(s, max) {
|
|
6068
6206
|
return s.length > max ? `${s.slice(0, max - 1)}\u2026` : s;
|
|
6069
6207
|
}
|
|
6070
6208
|
function issueAssignee(issue, selfLogin) {
|
|
@@ -6077,13 +6215,13 @@ function issueAssignee(issue, selfLogin) {
|
|
|
6077
6215
|
}
|
|
6078
6216
|
function formatIssueLine(issue, selfLogin, maxTitle) {
|
|
6079
6217
|
const num = theme.text.accent(`#${String(issue.number).padEnd(5)}`);
|
|
6080
|
-
const title =
|
|
6218
|
+
const title = truncate2(issue.title, maxTitle);
|
|
6081
6219
|
const assignee = issueAssignee(issue, selfLogin);
|
|
6082
6220
|
return ` ${num} ${title.padEnd(maxTitle)} ${assignee}`;
|
|
6083
6221
|
}
|
|
6084
6222
|
function formatTaskLine(task2, maxTitle) {
|
|
6085
6223
|
const pri = task2.priority === 5 /* High */ ? theme.priority.high("[!]") : task2.priority === 3 /* Medium */ ? theme.priority.medium("[~]") : " ";
|
|
6086
|
-
const title =
|
|
6224
|
+
const title = truncate2(task2.title, maxTitle);
|
|
6087
6225
|
const due = task2.dueDate ? formatDueDate(task2.dueDate) : "";
|
|
6088
6226
|
return ` ${pri} ${title.padEnd(maxTitle)} ${theme.text.secondary(due)}`;
|
|
6089
6227
|
}
|
|
@@ -6504,13 +6642,13 @@ Configuring ${repoName}...`);
|
|
|
6504
6642
|
} else {
|
|
6505
6643
|
completionAction = { type: "closeIssue" };
|
|
6506
6644
|
}
|
|
6507
|
-
const
|
|
6645
|
+
const shortName2 = await input({
|
|
6508
6646
|
message: ` Short name for ${repoName}:`,
|
|
6509
6647
|
default: name
|
|
6510
6648
|
});
|
|
6511
6649
|
repos.push({
|
|
6512
6650
|
name: repoName,
|
|
6513
|
-
shortName,
|
|
6651
|
+
shortName: shortName2,
|
|
6514
6652
|
projectNumber,
|
|
6515
6653
|
statusFieldId,
|
|
6516
6654
|
...dueDateFieldId ? { dueDateFieldId } : {},
|
|
@@ -7004,7 +7142,7 @@ function resolveProjectId(projectId) {
|
|
|
7004
7142
|
process.exit(1);
|
|
7005
7143
|
}
|
|
7006
7144
|
var program = new Command();
|
|
7007
|
-
program.name("hog").description("Personal command deck \u2014 unified task dashboard for GitHub Projects + TickTick").version("1.
|
|
7145
|
+
program.name("hog").description("Personal command deck \u2014 unified task dashboard for GitHub Projects + TickTick").version("1.12.0").option("--json", "Force JSON output").option("--human", "Force human-readable output").hook("preAction", (thisCommand) => {
|
|
7008
7146
|
const opts = thisCommand.opts();
|
|
7009
7147
|
if (opts.json) setFormat("json");
|
|
7010
7148
|
if (opts.human) setFormat("human");
|
|
@@ -7199,7 +7337,7 @@ config.command("repos:add <name>").description("Add a repository to track (owner
|
|
|
7199
7337
|
console.error(`Repo "${name}" is already configured.`);
|
|
7200
7338
|
process.exit(1);
|
|
7201
7339
|
}
|
|
7202
|
-
const
|
|
7340
|
+
const shortName2 = name.split("/")[1] ?? name;
|
|
7203
7341
|
let completionAction;
|
|
7204
7342
|
switch (opts.completionType) {
|
|
7205
7343
|
case "addLabel":
|
|
@@ -7227,7 +7365,7 @@ config.command("repos:add <name>").description("Add a repository to track (owner
|
|
|
7227
7365
|
}
|
|
7228
7366
|
const newRepo = {
|
|
7229
7367
|
name,
|
|
7230
|
-
shortName,
|
|
7368
|
+
shortName: shortName2,
|
|
7231
7369
|
projectNumber: Number.parseInt(opts.projectNumber, 10),
|
|
7232
7370
|
statusFieldId: opts.statusFieldId,
|
|
7233
7371
|
completionAction
|
|
@@ -7237,7 +7375,7 @@ config.command("repos:add <name>").description("Add a repository to track (owner
|
|
|
7237
7375
|
if (useJson()) {
|
|
7238
7376
|
jsonOut({ ok: true, message: `Added ${name}`, data: newRepo });
|
|
7239
7377
|
} else {
|
|
7240
|
-
console.log(`Added ${
|
|
7378
|
+
console.log(`Added ${shortName2} \u2192 ${name}`);
|
|
7241
7379
|
}
|
|
7242
7380
|
});
|
|
7243
7381
|
config.command("repos:rm <name>").description("Remove a repository from tracking").action((name) => {
|