@ondrej-svec/hog 1.10.0 → 1.11.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 +992 -865
- 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,61 @@ var init_action_log = __esm({
|
|
|
2784
2848
|
}
|
|
2785
2849
|
});
|
|
2786
2850
|
|
|
2787
|
-
// src/board/components/
|
|
2851
|
+
// src/board/components/activity-panel.tsx
|
|
2788
2852
|
import { Box as Box2, Text as Text2 } from "ink";
|
|
2789
|
-
import {
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
const
|
|
2793
|
-
|
|
2853
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
2854
|
+
function ActivityPanel({ events, selectedIdx, isActive, height }) {
|
|
2855
|
+
const borderColor = isActive ? "cyan" : "gray";
|
|
2856
|
+
const maxRows = Math.max(1, height - 2);
|
|
2857
|
+
const visible = events.slice(0, maxRows);
|
|
2858
|
+
return /* @__PURE__ */ jsxs2(
|
|
2859
|
+
Box2,
|
|
2860
|
+
{
|
|
2861
|
+
borderStyle: "single",
|
|
2862
|
+
borderColor,
|
|
2863
|
+
flexDirection: "column",
|
|
2864
|
+
height,
|
|
2865
|
+
overflow: "hidden",
|
|
2866
|
+
children: [
|
|
2867
|
+
/* @__PURE__ */ jsx2(Text2, { bold: true, color: isActive ? "cyan" : "white", children: "[4] Activity" }),
|
|
2868
|
+
visible.length === 0 ? /* @__PURE__ */ jsx2(Text2, { color: "gray", children: " No recent activity" }) : visible.map((event, i) => {
|
|
2869
|
+
const isSel = isActive && i === selectedIdx;
|
|
2870
|
+
const ago = timeAgo(event.timestamp);
|
|
2871
|
+
return /* @__PURE__ */ jsxs2(Box2, { children: [
|
|
2872
|
+
/* @__PURE__ */ jsxs2(Text2, { color: isSel ? "cyan" : "gray", bold: isSel, children: [
|
|
2873
|
+
isSel ? "\u25B6 " : " ",
|
|
2874
|
+
ago
|
|
2875
|
+
] }),
|
|
2876
|
+
/* @__PURE__ */ jsxs2(Text2, { color: isSel ? "white" : "gray", children: [
|
|
2877
|
+
" ",
|
|
2878
|
+
"@",
|
|
2879
|
+
event.actor,
|
|
2880
|
+
" ",
|
|
2881
|
+
event.summary,
|
|
2882
|
+
" "
|
|
2883
|
+
] }),
|
|
2884
|
+
/* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
|
|
2885
|
+
"(",
|
|
2886
|
+
event.repoShortName,
|
|
2887
|
+
")"
|
|
2888
|
+
] })
|
|
2889
|
+
] }, `${event.repoShortName}:${event.issueNumber}:${i}`);
|
|
2890
|
+
})
|
|
2891
|
+
]
|
|
2892
|
+
}
|
|
2893
|
+
);
|
|
2794
2894
|
}
|
|
2895
|
+
var init_activity_panel = __esm({
|
|
2896
|
+
"src/board/components/activity-panel.tsx"() {
|
|
2897
|
+
"use strict";
|
|
2898
|
+
init_constants();
|
|
2899
|
+
}
|
|
2900
|
+
});
|
|
2901
|
+
|
|
2902
|
+
// src/board/components/detail-panel.tsx
|
|
2903
|
+
import { Box as Box3, Text as Text3 } from "ink";
|
|
2904
|
+
import { useEffect as useEffect3 } from "react";
|
|
2905
|
+
import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
2795
2906
|
function stripMarkdown(text) {
|
|
2796
2907
|
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
2908
|
}
|
|
@@ -2810,11 +2921,11 @@ function BodySection({
|
|
|
2810
2921
|
issueNumber
|
|
2811
2922
|
}) {
|
|
2812
2923
|
const { text, remaining } = formatBody(body, 15);
|
|
2813
|
-
return /* @__PURE__ */
|
|
2814
|
-
/* @__PURE__ */
|
|
2815
|
-
/* @__PURE__ */
|
|
2816
|
-
/* @__PURE__ */
|
|
2817
|
-
remaining > 0 ? /* @__PURE__ */
|
|
2924
|
+
return /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
2925
|
+
/* @__PURE__ */ jsx3(Text3, { children: "" }),
|
|
2926
|
+
/* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "--- Description ---" }),
|
|
2927
|
+
/* @__PURE__ */ jsx3(Text3, { wrap: "wrap", children: text }),
|
|
2928
|
+
remaining > 0 ? /* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
|
|
2818
2929
|
"... (",
|
|
2819
2930
|
remaining,
|
|
2820
2931
|
" more lines \u2014 gh issue view ",
|
|
@@ -2835,185 +2946,143 @@ function formatCommentAge(createdAt) {
|
|
|
2835
2946
|
}
|
|
2836
2947
|
function DetailPanel({
|
|
2837
2948
|
issue,
|
|
2838
|
-
task: task2,
|
|
2839
2949
|
width,
|
|
2950
|
+
isActive,
|
|
2840
2951
|
commentsState,
|
|
2841
2952
|
fetchComments,
|
|
2842
2953
|
issueRepo
|
|
2843
2954
|
}) {
|
|
2955
|
+
const borderColor = isActive ? "cyan" : "gray";
|
|
2844
2956
|
useEffect3(() => {
|
|
2845
2957
|
if (!(issue && fetchComments && issueRepo)) return;
|
|
2846
2958
|
if (commentsState !== null && commentsState !== void 0) return;
|
|
2847
2959
|
fetchComments(issueRepo, issue.number);
|
|
2848
2960
|
}, [issue, issueRepo, fetchComments, commentsState]);
|
|
2849
|
-
if (!
|
|
2850
|
-
return /* @__PURE__ */
|
|
2851
|
-
|
|
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,
|
|
2961
|
+
if (!issue) {
|
|
2962
|
+
return /* @__PURE__ */ jsxs3(
|
|
2963
|
+
Box3,
|
|
2865
2964
|
{
|
|
2866
2965
|
width,
|
|
2867
2966
|
borderStyle: "single",
|
|
2868
|
-
borderColor
|
|
2967
|
+
borderColor,
|
|
2869
2968
|
flexDirection: "column",
|
|
2870
2969
|
paddingX: 1,
|
|
2871
2970
|
children: [
|
|
2872
|
-
/* @__PURE__ */
|
|
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 })
|
|
2971
|
+
/* @__PURE__ */ jsx3(Text3, { bold: true, color: isActive ? "cyan" : "white", children: "[0] Detail" }),
|
|
2972
|
+
/* @__PURE__ */ jsx3(Text3, { color: "gray", children: "No item selected" })
|
|
2930
2973
|
]
|
|
2931
2974
|
}
|
|
2932
2975
|
);
|
|
2933
2976
|
}
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
Box2,
|
|
2977
|
+
return /* @__PURE__ */ jsxs3(
|
|
2978
|
+
Box3,
|
|
2937
2979
|
{
|
|
2938
2980
|
width,
|
|
2939
2981
|
borderStyle: "single",
|
|
2940
|
-
borderColor
|
|
2982
|
+
borderColor,
|
|
2941
2983
|
flexDirection: "column",
|
|
2942
2984
|
paddingX: 1,
|
|
2943
2985
|
children: [
|
|
2944
|
-
/* @__PURE__ */
|
|
2945
|
-
/* @__PURE__ */
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2986
|
+
/* @__PURE__ */ jsx3(Text3, { bold: true, color: isActive ? "cyan" : "white", children: "[0] Detail" }),
|
|
2987
|
+
/* @__PURE__ */ jsxs3(Text3, { color: "cyan", bold: true, children: [
|
|
2988
|
+
"#",
|
|
2989
|
+
issue.number,
|
|
2990
|
+
" ",
|
|
2991
|
+
issue.title
|
|
2949
2992
|
] }),
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
/* @__PURE__ */
|
|
2993
|
+
/* @__PURE__ */ jsx3(Text3, { children: "" }),
|
|
2994
|
+
/* @__PURE__ */ jsxs3(Box3, { children: [
|
|
2995
|
+
/* @__PURE__ */ jsx3(Text3, { color: "gray", children: "State: " }),
|
|
2996
|
+
/* @__PURE__ */ jsx3(Text3, { color: issue.state === "open" ? "green" : "red", children: issue.state })
|
|
2997
|
+
] }),
|
|
2998
|
+
(issue.assignees ?? []).length > 0 ? /* @__PURE__ */ jsxs3(Box3, { children: [
|
|
2999
|
+
/* @__PURE__ */ jsx3(Text3, { color: "gray", children: "Assignees: " }),
|
|
3000
|
+
/* @__PURE__ */ jsx3(Text3, { children: (issue.assignees ?? []).map((a) => a.login).join(", ") })
|
|
2953
3001
|
] }) : null,
|
|
2954
|
-
|
|
2955
|
-
/* @__PURE__ */
|
|
2956
|
-
/* @__PURE__ */
|
|
3002
|
+
issue.labels.length > 0 ? /* @__PURE__ */ jsxs3(Box3, { children: [
|
|
3003
|
+
/* @__PURE__ */ jsx3(Text3, { color: "gray", children: "Labels: " }),
|
|
3004
|
+
/* @__PURE__ */ jsx3(Text3, { children: issue.labels.map((l) => l.name).join(", ") })
|
|
2957
3005
|
] }) : null,
|
|
2958
|
-
|
|
2959
|
-
/* @__PURE__ */
|
|
2960
|
-
/* @__PURE__ */
|
|
3006
|
+
issue.projectStatus ? /* @__PURE__ */ jsxs3(Box3, { children: [
|
|
3007
|
+
/* @__PURE__ */ jsx3(Text3, { color: "gray", children: "Status: " }),
|
|
3008
|
+
/* @__PURE__ */ jsx3(Text3, { color: "magenta", children: issue.projectStatus })
|
|
2961
3009
|
] }) : null,
|
|
2962
|
-
|
|
2963
|
-
/* @__PURE__ */
|
|
2964
|
-
/* @__PURE__ */
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
3010
|
+
issue.targetDate ? /* @__PURE__ */ jsxs3(Box3, { children: [
|
|
3011
|
+
/* @__PURE__ */ jsx3(Text3, { color: "gray", children: "Target: " }),
|
|
3012
|
+
/* @__PURE__ */ jsx3(Text3, { children: issue.targetDate })
|
|
3013
|
+
] }) : null,
|
|
3014
|
+
/* @__PURE__ */ jsxs3(Box3, { children: [
|
|
3015
|
+
/* @__PURE__ */ jsx3(Text3, { color: "gray", children: "Updated: " }),
|
|
3016
|
+
/* @__PURE__ */ jsx3(Text3, { children: new Date(issue.updatedAt).toLocaleString() })
|
|
3017
|
+
] }),
|
|
3018
|
+
issue.slackThreadUrl ? /* @__PURE__ */ jsxs3(Box3, { children: [
|
|
3019
|
+
/* @__PURE__ */ jsx3(Text3, { color: "gray", children: "Slack: " }),
|
|
3020
|
+
/* @__PURE__ */ jsx3(Text3, { color: "blue", children: countSlackLinks(issue.body) > 1 ? `${countSlackLinks(issue.body)} links (s opens first)` : "thread (s to open)" })
|
|
3021
|
+
] }) : null,
|
|
3022
|
+
issue.body ? /* @__PURE__ */ jsx3(BodySection, { body: issue.body, issueNumber: issue.number }) : /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
3023
|
+
/* @__PURE__ */ jsx3(Text3, { children: "" }),
|
|
3024
|
+
/* @__PURE__ */ jsx3(Text3, { color: "gray", children: "(no description)" })
|
|
3025
|
+
] }),
|
|
3026
|
+
/* @__PURE__ */ jsx3(Text3, { children: "" }),
|
|
3027
|
+
/* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "--- Comments ---" }),
|
|
3028
|
+
commentsState === "loading" ? /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "fetching comments..." }) : commentsState === "error" ? /* @__PURE__ */ jsx3(Text3, { color: "red", children: "could not load comments" }) : commentsState && commentsState.length === 0 ? /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "No comments yet." }) : commentsState && commentsState.length > 0 ? commentsState.slice(-5).map((comment, i) => (
|
|
3029
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: stable list
|
|
3030
|
+
/* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", marginBottom: 1, children: [
|
|
3031
|
+
/* @__PURE__ */ jsxs3(Text3, { color: "cyan", children: [
|
|
3032
|
+
"@",
|
|
3033
|
+
comment.author.login,
|
|
3034
|
+
" \xB7 ",
|
|
3035
|
+
formatCommentAge(comment.createdAt)
|
|
3036
|
+
] }),
|
|
3037
|
+
/* @__PURE__ */ jsxs3(Text3, { wrap: "wrap", children: [
|
|
3038
|
+
" ",
|
|
3039
|
+
comment.body.split("\n")[0]
|
|
3040
|
+
] })
|
|
3041
|
+
] }, i)
|
|
3042
|
+
)) : /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "fetching comments..." }),
|
|
3043
|
+
/* @__PURE__ */ jsx3(Text3, { children: "" }),
|
|
3044
|
+
/* @__PURE__ */ jsx3(Text3, { color: "gray", dimColor: true, children: issue.url })
|
|
2976
3045
|
]
|
|
2977
3046
|
}
|
|
2978
3047
|
);
|
|
2979
3048
|
}
|
|
2980
|
-
var SLACK_URL_RE
|
|
3049
|
+
var SLACK_URL_RE;
|
|
2981
3050
|
var init_detail_panel = __esm({
|
|
2982
3051
|
"src/board/components/detail-panel.tsx"() {
|
|
2983
3052
|
"use strict";
|
|
2984
|
-
init_types();
|
|
2985
3053
|
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
3054
|
}
|
|
2993
3055
|
});
|
|
2994
3056
|
|
|
2995
3057
|
// src/board/components/hint-bar.tsx
|
|
2996
|
-
import { Box as
|
|
2997
|
-
import { jsx as
|
|
2998
|
-
function HintBar({
|
|
3058
|
+
import { Box as Box4, Text as Text4 } from "ink";
|
|
3059
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
3060
|
+
function HintBar({
|
|
3061
|
+
uiMode,
|
|
3062
|
+
activePanelId,
|
|
3063
|
+
multiSelectCount,
|
|
3064
|
+
searchQuery,
|
|
3065
|
+
mineOnly,
|
|
3066
|
+
hasUndoable
|
|
3067
|
+
}) {
|
|
2999
3068
|
if (uiMode === "multiSelect") {
|
|
3000
|
-
return /* @__PURE__ */
|
|
3001
|
-
/* @__PURE__ */
|
|
3069
|
+
return /* @__PURE__ */ jsxs4(Box4, { children: [
|
|
3070
|
+
/* @__PURE__ */ jsxs4(Text4, { color: "cyan", bold: true, children: [
|
|
3002
3071
|
"[MULTI-SELECT] ",
|
|
3003
3072
|
multiSelectCount,
|
|
3004
3073
|
" selected"
|
|
3005
3074
|
] }),
|
|
3006
|
-
/* @__PURE__ */
|
|
3075
|
+
/* @__PURE__ */ jsx4(Text4, { color: "gray", children: " Space:toggle Enter:actions Esc:cancel" })
|
|
3007
3076
|
] });
|
|
3008
3077
|
}
|
|
3009
3078
|
if (uiMode === "focus") {
|
|
3010
|
-
return /* @__PURE__ */
|
|
3079
|
+
return /* @__PURE__ */ jsx4(Box4, { children: /* @__PURE__ */ jsx4(Text4, { color: "magenta", bold: true, children: "[FOCUS] Focus mode \u2014 Esc to exit" }) });
|
|
3011
3080
|
}
|
|
3012
3081
|
if (uiMode === "search") {
|
|
3013
|
-
return /* @__PURE__ */
|
|
3014
|
-
/* @__PURE__ */
|
|
3015
|
-
/* @__PURE__ */
|
|
3016
|
-
searchQuery ? /* @__PURE__ */
|
|
3082
|
+
return /* @__PURE__ */ jsxs4(Box4, { children: [
|
|
3083
|
+
/* @__PURE__ */ jsx4(Text4, { color: "yellow", bold: true, children: "[SEARCH]" }),
|
|
3084
|
+
/* @__PURE__ */ jsx4(Text4, { color: "gray", children: " type to filter Enter:confirm Esc:clear" }),
|
|
3085
|
+
searchQuery ? /* @__PURE__ */ jsxs4(Text4, { color: "yellow", children: [
|
|
3017
3086
|
' "',
|
|
3018
3087
|
searchQuery,
|
|
3019
3088
|
'"'
|
|
@@ -3021,19 +3090,22 @@ function HintBar({ uiMode, multiSelectCount, searchQuery, mineOnly, hasUndoable
|
|
|
3021
3090
|
] });
|
|
3022
3091
|
}
|
|
3023
3092
|
if (uiMode === "overlay:fuzzyPicker") {
|
|
3024
|
-
return /* @__PURE__ */
|
|
3093
|
+
return /* @__PURE__ */ jsx4(Box4, { children: /* @__PURE__ */ jsx4(Text4, { color: "gray", children: "\u2191\u2193/Ctrl-J/K:nav Enter:jump Esc:close" }) });
|
|
3025
3094
|
}
|
|
3026
3095
|
if (uiMode.startsWith("overlay:")) {
|
|
3027
|
-
return /* @__PURE__ */
|
|
3028
|
-
}
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3096
|
+
return /* @__PURE__ */ jsx4(Box4, { children: /* @__PURE__ */ jsx4(Text4, { color: "gray", children: "j/k:nav Enter:select Esc:cancel" }) });
|
|
3097
|
+
}
|
|
3098
|
+
const panelHints = {
|
|
3099
|
+
0: "j/k:scroll Esc:close ? help",
|
|
3100
|
+
1: "j/k:move Enter:filter 0-4:panel ? help",
|
|
3101
|
+
2: "j/k:move Enter:filter Esc:clear 0-4:panel ? help",
|
|
3102
|
+
3: `j/k:move p:pick m:status c:comment /:search n:new 0-4:panel${hasUndoable ? " u:undo" : ""} ? help q:quit`,
|
|
3103
|
+
4: "j/k:scroll Enter:jump r:refresh 0-4:panel ? help"
|
|
3104
|
+
};
|
|
3105
|
+
return /* @__PURE__ */ jsxs4(Box4, { children: [
|
|
3106
|
+
/* @__PURE__ */ jsx4(Text4, { color: "gray", children: panelHints[activePanelId] }),
|
|
3107
|
+
mineOnly ? /* @__PURE__ */ jsx4(Text4, { color: "cyan", children: " filter:@me" }) : null,
|
|
3108
|
+
searchQuery ? /* @__PURE__ */ jsxs4(Text4, { color: "yellow", children: [
|
|
3037
3109
|
' filter:"',
|
|
3038
3110
|
searchQuery,
|
|
3039
3111
|
'"'
|
|
@@ -3047,9 +3119,9 @@ var init_hint_bar = __esm({
|
|
|
3047
3119
|
});
|
|
3048
3120
|
|
|
3049
3121
|
// src/board/components/bulk-action-menu.tsx
|
|
3050
|
-
import { Box as
|
|
3051
|
-
import { useState as
|
|
3052
|
-
import { jsx as
|
|
3122
|
+
import { Box as Box5, Text as Text5, useInput as useInput2 } from "ink";
|
|
3123
|
+
import { useState as useState7 } from "react";
|
|
3124
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
3053
3125
|
function getMenuItems(selectionType) {
|
|
3054
3126
|
if (selectionType === "github") {
|
|
3055
3127
|
return [
|
|
@@ -3068,7 +3140,7 @@ function getMenuItems(selectionType) {
|
|
|
3068
3140
|
}
|
|
3069
3141
|
function BulkActionMenu({ count, selectionType, onSelect, onCancel }) {
|
|
3070
3142
|
const items = getMenuItems(selectionType);
|
|
3071
|
-
const [selectedIdx, setSelectedIdx] =
|
|
3143
|
+
const [selectedIdx, setSelectedIdx] = useState7(0);
|
|
3072
3144
|
useInput2((input2, key) => {
|
|
3073
3145
|
if (key.escape) return onCancel();
|
|
3074
3146
|
if (key.return) {
|
|
@@ -3084,13 +3156,13 @@ function BulkActionMenu({ count, selectionType, onSelect, onCancel }) {
|
|
|
3084
3156
|
}
|
|
3085
3157
|
});
|
|
3086
3158
|
if (items.length === 0) {
|
|
3087
|
-
return /* @__PURE__ */
|
|
3088
|
-
/* @__PURE__ */
|
|
3089
|
-
/* @__PURE__ */
|
|
3159
|
+
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
|
|
3160
|
+
/* @__PURE__ */ jsx5(Text5, { color: "yellow", children: "No bulk actions for mixed selection types." }),
|
|
3161
|
+
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "Esc to cancel" })
|
|
3090
3162
|
] });
|
|
3091
3163
|
}
|
|
3092
|
-
return /* @__PURE__ */
|
|
3093
|
-
/* @__PURE__ */
|
|
3164
|
+
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
|
|
3165
|
+
/* @__PURE__ */ jsxs5(Text5, { color: "cyan", bold: true, children: [
|
|
3094
3166
|
"Bulk action (",
|
|
3095
3167
|
count,
|
|
3096
3168
|
" selected):"
|
|
@@ -3098,12 +3170,12 @@ function BulkActionMenu({ count, selectionType, onSelect, onCancel }) {
|
|
|
3098
3170
|
items.map((item, i) => {
|
|
3099
3171
|
const isSelected = i === selectedIdx;
|
|
3100
3172
|
const prefix = isSelected ? "> " : " ";
|
|
3101
|
-
return /* @__PURE__ */
|
|
3173
|
+
return /* @__PURE__ */ jsxs5(Text5, { ...isSelected ? { color: "cyan" } : {}, children: [
|
|
3102
3174
|
prefix,
|
|
3103
3175
|
item.label
|
|
3104
3176
|
] }, item.action.type);
|
|
3105
3177
|
}),
|
|
3106
|
-
/* @__PURE__ */
|
|
3178
|
+
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "j/k:navigate Enter:select Esc:cancel" })
|
|
3107
3179
|
] });
|
|
3108
3180
|
}
|
|
3109
3181
|
var init_bulk_action_menu = __esm({
|
|
@@ -3133,9 +3205,9 @@ import { mkdtempSync, readFileSync as readFileSync4, rmSync, writeFileSync as wr
|
|
|
3133
3205
|
import { tmpdir } from "os";
|
|
3134
3206
|
import { join as join4 } from "path";
|
|
3135
3207
|
import { TextInput } from "@inkjs/ui";
|
|
3136
|
-
import { Box as
|
|
3137
|
-
import { useEffect as useEffect4, useRef as useRef7, useState as
|
|
3138
|
-
import { jsx as
|
|
3208
|
+
import { Box as Box6, Text as Text6, useInput as useInput3, useStdin } from "ink";
|
|
3209
|
+
import { useEffect as useEffect4, useRef as useRef7, useState as useState8 } from "react";
|
|
3210
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
3139
3211
|
function CommentInput({
|
|
3140
3212
|
issueNumber,
|
|
3141
3213
|
onSubmit,
|
|
@@ -3143,8 +3215,8 @@ function CommentInput({
|
|
|
3143
3215
|
onPauseRefresh,
|
|
3144
3216
|
onResumeRefresh
|
|
3145
3217
|
}) {
|
|
3146
|
-
const [value, setValue] =
|
|
3147
|
-
const [editing, setEditing] =
|
|
3218
|
+
const [value, setValue] = useState8("");
|
|
3219
|
+
const [editing, setEditing] = useState8(false);
|
|
3148
3220
|
const { setRawMode } = useStdin();
|
|
3149
3221
|
const onSubmitRef = useRef7(onSubmit);
|
|
3150
3222
|
const onCancelRef = useRef7(onCancel);
|
|
@@ -3202,19 +3274,19 @@ function CommentInput({
|
|
|
3202
3274
|
}
|
|
3203
3275
|
}, [editing, value, setRawMode]);
|
|
3204
3276
|
if (editing) {
|
|
3205
|
-
return /* @__PURE__ */
|
|
3277
|
+
return /* @__PURE__ */ jsx6(Box6, { children: /* @__PURE__ */ jsxs6(Text6, { color: "cyan", children: [
|
|
3206
3278
|
"Opening editor for #",
|
|
3207
3279
|
issueNumber,
|
|
3208
3280
|
"\u2026"
|
|
3209
3281
|
] }) });
|
|
3210
3282
|
}
|
|
3211
|
-
return /* @__PURE__ */
|
|
3212
|
-
/* @__PURE__ */
|
|
3283
|
+
return /* @__PURE__ */ jsxs6(Box6, { children: [
|
|
3284
|
+
/* @__PURE__ */ jsxs6(Text6, { color: "cyan", children: [
|
|
3213
3285
|
"comment #",
|
|
3214
3286
|
issueNumber,
|
|
3215
3287
|
": "
|
|
3216
3288
|
] }),
|
|
3217
|
-
/* @__PURE__ */
|
|
3289
|
+
/* @__PURE__ */ jsx6(
|
|
3218
3290
|
TextInput,
|
|
3219
3291
|
{
|
|
3220
3292
|
defaultValue: value,
|
|
@@ -3236,16 +3308,16 @@ var init_comment_input = __esm({
|
|
|
3236
3308
|
});
|
|
3237
3309
|
|
|
3238
3310
|
// src/board/components/confirm-prompt.tsx
|
|
3239
|
-
import { Box as
|
|
3240
|
-
import { jsx as
|
|
3311
|
+
import { Box as Box7, Text as Text7, useInput as useInput4 } from "ink";
|
|
3312
|
+
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
3241
3313
|
function ConfirmPrompt({ message, onConfirm, onCancel }) {
|
|
3242
3314
|
useInput4((input2, key) => {
|
|
3243
3315
|
if (input2 === "y" || input2 === "Y") return onConfirm();
|
|
3244
3316
|
if (input2 === "n" || input2 === "N" || key.escape) return onCancel();
|
|
3245
3317
|
});
|
|
3246
|
-
return /* @__PURE__ */
|
|
3247
|
-
/* @__PURE__ */
|
|
3248
|
-
/* @__PURE__ */
|
|
3318
|
+
return /* @__PURE__ */ jsxs7(Box7, { children: [
|
|
3319
|
+
/* @__PURE__ */ jsx7(Text7, { color: "cyan", children: message }),
|
|
3320
|
+
/* @__PURE__ */ jsx7(Text7, { color: "gray", children: " (y/n)" })
|
|
3249
3321
|
] });
|
|
3250
3322
|
}
|
|
3251
3323
|
var init_confirm_prompt = __esm({
|
|
@@ -3256,9 +3328,9 @@ var init_confirm_prompt = __esm({
|
|
|
3256
3328
|
|
|
3257
3329
|
// src/board/components/label-picker.tsx
|
|
3258
3330
|
import { Spinner } from "@inkjs/ui";
|
|
3259
|
-
import { Box as
|
|
3260
|
-
import { useEffect as useEffect5, useRef as useRef8, useState as
|
|
3261
|
-
import { jsx as
|
|
3331
|
+
import { Box as Box8, Text as Text8, useInput as useInput5 } from "ink";
|
|
3332
|
+
import { useEffect as useEffect5, useRef as useRef8, useState as useState9 } from "react";
|
|
3333
|
+
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
3262
3334
|
function LabelPicker({
|
|
3263
3335
|
repo,
|
|
3264
3336
|
currentLabels,
|
|
@@ -3267,11 +3339,11 @@ function LabelPicker({
|
|
|
3267
3339
|
onCancel,
|
|
3268
3340
|
onError
|
|
3269
3341
|
}) {
|
|
3270
|
-
const [labels, setLabels] =
|
|
3271
|
-
const [loading, setLoading] =
|
|
3272
|
-
const [fetchAttempted, setFetchAttempted] =
|
|
3273
|
-
const [selected, setSelected] =
|
|
3274
|
-
const [cursor, setCursor] =
|
|
3342
|
+
const [labels, setLabels] = useState9(labelCache[repo] ?? null);
|
|
3343
|
+
const [loading, setLoading] = useState9(labels === null);
|
|
3344
|
+
const [fetchAttempted, setFetchAttempted] = useState9(false);
|
|
3345
|
+
const [selected, setSelected] = useState9(new Set(currentLabels));
|
|
3346
|
+
const [cursor, setCursor] = useState9(0);
|
|
3275
3347
|
const submittedRef = useRef8(false);
|
|
3276
3348
|
useEffect5(() => {
|
|
3277
3349
|
if (labels !== null || fetchAttempted) return;
|
|
@@ -3333,21 +3405,21 @@ function LabelPicker({
|
|
|
3333
3405
|
}
|
|
3334
3406
|
});
|
|
3335
3407
|
if (loading) {
|
|
3336
|
-
return /* @__PURE__ */
|
|
3408
|
+
return /* @__PURE__ */ jsx8(Box8, { children: /* @__PURE__ */ jsx8(Spinner, { label: "Fetching labels..." }) });
|
|
3337
3409
|
}
|
|
3338
3410
|
const allLabels = labels ?? [];
|
|
3339
3411
|
if (allLabels.length === 0) {
|
|
3340
|
-
return /* @__PURE__ */
|
|
3341
|
-
/* @__PURE__ */
|
|
3342
|
-
/* @__PURE__ */
|
|
3343
|
-
/* @__PURE__ */
|
|
3412
|
+
return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
|
|
3413
|
+
/* @__PURE__ */ jsx8(Text8, { color: "cyan", bold: true, children: "Labels:" }),
|
|
3414
|
+
/* @__PURE__ */ jsx8(Text8, { dimColor: true, children: "No labels in this repo" }),
|
|
3415
|
+
/* @__PURE__ */ jsx8(Text8, { dimColor: true, children: "Esc:cancel" })
|
|
3344
3416
|
] });
|
|
3345
3417
|
}
|
|
3346
3418
|
const repoLabelNames = new Set(allLabels.map((l) => l.name));
|
|
3347
3419
|
const orphanedLabels = currentLabels.filter((l) => !repoLabelNames.has(l));
|
|
3348
|
-
return /* @__PURE__ */
|
|
3349
|
-
/* @__PURE__ */
|
|
3350
|
-
orphanedLabels.map((name) => /* @__PURE__ */
|
|
3420
|
+
return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
|
|
3421
|
+
/* @__PURE__ */ jsx8(Text8, { color: "cyan", bold: true, children: "Labels (Space:toggle Enter:confirm Esc:cancel):" }),
|
|
3422
|
+
orphanedLabels.map((name) => /* @__PURE__ */ jsxs8(Text8, { dimColor: true, children: [
|
|
3351
3423
|
selected.has(name) ? "[x]" : "[ ]",
|
|
3352
3424
|
" ",
|
|
3353
3425
|
name,
|
|
@@ -3356,7 +3428,7 @@ function LabelPicker({
|
|
|
3356
3428
|
allLabels.map((label, i) => {
|
|
3357
3429
|
const isSel = i === cursor;
|
|
3358
3430
|
const isChecked = selected.has(label.name);
|
|
3359
|
-
return /* @__PURE__ */
|
|
3431
|
+
return /* @__PURE__ */ jsxs8(Text8, { ...isSel ? { color: "cyan" } : {}, children: [
|
|
3360
3432
|
isSel ? ">" : " ",
|
|
3361
3433
|
" ",
|
|
3362
3434
|
isChecked ? "[x]" : "[ ]",
|
|
@@ -3375,9 +3447,9 @@ var init_label_picker = __esm({
|
|
|
3375
3447
|
|
|
3376
3448
|
// src/board/components/create-issue-form.tsx
|
|
3377
3449
|
import { TextInput as TextInput2 } from "@inkjs/ui";
|
|
3378
|
-
import { Box as
|
|
3379
|
-
import { useState as
|
|
3380
|
-
import { jsx as
|
|
3450
|
+
import { Box as Box9, Text as Text9, useInput as useInput6 } from "ink";
|
|
3451
|
+
import { useState as useState10 } from "react";
|
|
3452
|
+
import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
3381
3453
|
function CreateIssueForm({
|
|
3382
3454
|
repos,
|
|
3383
3455
|
defaultRepo,
|
|
@@ -3389,9 +3461,9 @@ function CreateIssueForm({
|
|
|
3389
3461
|
0,
|
|
3390
3462
|
repos.findIndex((r) => r.name === defaultRepo)
|
|
3391
3463
|
) : 0;
|
|
3392
|
-
const [repoIdx, setRepoIdx] =
|
|
3393
|
-
const [title, setTitle] =
|
|
3394
|
-
const [field, setField] =
|
|
3464
|
+
const [repoIdx, setRepoIdx] = useState10(defaultRepoIdx);
|
|
3465
|
+
const [title, setTitle] = useState10("");
|
|
3466
|
+
const [field, setField] = useState10("title");
|
|
3395
3467
|
useInput6((input2, key) => {
|
|
3396
3468
|
if (field === "labels") return;
|
|
3397
3469
|
if (key.escape) return onCancel();
|
|
@@ -3408,15 +3480,15 @@ function CreateIssueForm({
|
|
|
3408
3480
|
});
|
|
3409
3481
|
const selectedRepo = repos[repoIdx];
|
|
3410
3482
|
if (field === "labels" && selectedRepo) {
|
|
3411
|
-
return /* @__PURE__ */
|
|
3412
|
-
/* @__PURE__ */
|
|
3413
|
-
/* @__PURE__ */
|
|
3483
|
+
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
|
|
3484
|
+
/* @__PURE__ */ jsx9(Text9, { color: "cyan", bold: true, children: "Create Issue \u2014 Add Labels (optional)" }),
|
|
3485
|
+
/* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
|
|
3414
3486
|
"Repo: ",
|
|
3415
3487
|
selectedRepo.shortName,
|
|
3416
3488
|
" Title: ",
|
|
3417
3489
|
title
|
|
3418
3490
|
] }),
|
|
3419
|
-
/* @__PURE__ */
|
|
3491
|
+
/* @__PURE__ */ jsx9(
|
|
3420
3492
|
LabelPicker,
|
|
3421
3493
|
{
|
|
3422
3494
|
repo: selectedRepo.name,
|
|
@@ -3441,12 +3513,12 @@ function CreateIssueForm({
|
|
|
3441
3513
|
)
|
|
3442
3514
|
] });
|
|
3443
3515
|
}
|
|
3444
|
-
return /* @__PURE__ */
|
|
3445
|
-
/* @__PURE__ */
|
|
3446
|
-
/* @__PURE__ */
|
|
3447
|
-
/* @__PURE__ */
|
|
3448
|
-
repos.map((r, i) => /* @__PURE__ */
|
|
3449
|
-
|
|
3516
|
+
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
|
|
3517
|
+
/* @__PURE__ */ jsx9(Text9, { color: "cyan", bold: true, children: "Create Issue" }),
|
|
3518
|
+
/* @__PURE__ */ jsxs9(Box9, { children: [
|
|
3519
|
+
/* @__PURE__ */ jsx9(Text9, { dimColor: field !== "repo", children: "Repo: " }),
|
|
3520
|
+
repos.map((r, i) => /* @__PURE__ */ jsx9(
|
|
3521
|
+
Text9,
|
|
3450
3522
|
{
|
|
3451
3523
|
...i === repoIdx ? { color: "cyan", bold: true } : {},
|
|
3452
3524
|
dimColor: field !== "repo",
|
|
@@ -3454,11 +3526,11 @@ function CreateIssueForm({
|
|
|
3454
3526
|
},
|
|
3455
3527
|
r.name
|
|
3456
3528
|
)),
|
|
3457
|
-
field === "repo" ? /* @__PURE__ */
|
|
3529
|
+
field === "repo" ? /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: " j/k:select Tab:next" }) : null
|
|
3458
3530
|
] }),
|
|
3459
|
-
/* @__PURE__ */
|
|
3460
|
-
/* @__PURE__ */
|
|
3461
|
-
field === "title" ? /* @__PURE__ */
|
|
3531
|
+
/* @__PURE__ */ jsxs9(Box9, { children: [
|
|
3532
|
+
/* @__PURE__ */ jsx9(Text9, { dimColor: field !== "title", children: "Title: " }),
|
|
3533
|
+
field === "title" ? /* @__PURE__ */ jsx9(
|
|
3462
3534
|
TextInput2,
|
|
3463
3535
|
{
|
|
3464
3536
|
defaultValue: title,
|
|
@@ -3475,9 +3547,9 @@ function CreateIssueForm({
|
|
|
3475
3547
|
}
|
|
3476
3548
|
}
|
|
3477
3549
|
}
|
|
3478
|
-
) : /* @__PURE__ */
|
|
3550
|
+
) : /* @__PURE__ */ jsx9(Text9, { children: title || "(empty)" })
|
|
3479
3551
|
] }),
|
|
3480
|
-
/* @__PURE__ */
|
|
3552
|
+
/* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "Tab:switch fields Enter:next Esc:cancel" })
|
|
3481
3553
|
] });
|
|
3482
3554
|
}
|
|
3483
3555
|
var init_create_issue_form = __esm({
|
|
@@ -3492,9 +3564,9 @@ import { spawnSync as spawnSync2 } from "child_process";
|
|
|
3492
3564
|
import { mkdtempSync as mkdtempSync2, readFileSync as readFileSync5, rmSync as rmSync2, writeFileSync as writeFileSync5 } from "fs";
|
|
3493
3565
|
import { tmpdir as tmpdir2 } from "os";
|
|
3494
3566
|
import { join as join5 } from "path";
|
|
3495
|
-
import { Box as
|
|
3496
|
-
import { useEffect as useEffect6, useRef as useRef9, useState as
|
|
3497
|
-
import { jsx as
|
|
3567
|
+
import { Box as Box10, Text as Text10, useStdin as useStdin2 } from "ink";
|
|
3568
|
+
import { useEffect as useEffect6, useRef as useRef9, useState as useState11 } from "react";
|
|
3569
|
+
import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
3498
3570
|
function buildEditorFile(issue, repoName, statusOptions, repoLabels) {
|
|
3499
3571
|
const statusNames = statusOptions.map((o) => o.name).join(", ");
|
|
3500
3572
|
const labelNames = repoLabels.map((l) => l.name).join(", ");
|
|
@@ -3577,7 +3649,7 @@ function EditIssueOverlay({
|
|
|
3577
3649
|
onToastError,
|
|
3578
3650
|
onPushEntry
|
|
3579
3651
|
}) {
|
|
3580
|
-
const [editing, setEditing] =
|
|
3652
|
+
const [editing, setEditing] = useState11(true);
|
|
3581
3653
|
const { setRawMode } = useStdin2();
|
|
3582
3654
|
const onDoneRef = useRef9(onDone);
|
|
3583
3655
|
const onPauseRef = useRef9(onPauseRefresh);
|
|
@@ -3736,7 +3808,7 @@ function EditIssueOverlay({
|
|
|
3736
3808
|
onPushEntry
|
|
3737
3809
|
]);
|
|
3738
3810
|
if (!editing) return null;
|
|
3739
|
-
return /* @__PURE__ */
|
|
3811
|
+
return /* @__PURE__ */ jsx10(Box10, { children: /* @__PURE__ */ jsxs10(Text10, { color: "cyan", children: [
|
|
3740
3812
|
"Opening editor for #",
|
|
3741
3813
|
issue.number,
|
|
3742
3814
|
"\u2026"
|
|
@@ -3752,17 +3824,17 @@ var init_edit_issue_overlay = __esm({
|
|
|
3752
3824
|
});
|
|
3753
3825
|
|
|
3754
3826
|
// src/board/components/focus-mode.tsx
|
|
3755
|
-
import { Box as
|
|
3756
|
-
import { useCallback as
|
|
3757
|
-
import { jsx as
|
|
3827
|
+
import { Box as Box11, Text as Text11, useInput as useInput7 } from "ink";
|
|
3828
|
+
import { useCallback as useCallback10, useEffect as useEffect7, useRef as useRef10, useState as useState12 } from "react";
|
|
3829
|
+
import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
3758
3830
|
function formatTime(secs) {
|
|
3759
3831
|
const m = Math.floor(secs / 60);
|
|
3760
3832
|
const s = secs % 60;
|
|
3761
3833
|
return `${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`;
|
|
3762
3834
|
}
|
|
3763
3835
|
function FocusMode({ label, durationSec, onExit, onEndAction }) {
|
|
3764
|
-
const [remaining, setRemaining] =
|
|
3765
|
-
const [timerDone, setTimerDone] =
|
|
3836
|
+
const [remaining, setRemaining] = useState12(durationSec);
|
|
3837
|
+
const [timerDone, setTimerDone] = useState12(false);
|
|
3766
3838
|
const bellSentRef = useRef10(false);
|
|
3767
3839
|
useEffect7(() => {
|
|
3768
3840
|
if (timerDone) return;
|
|
@@ -3784,7 +3856,7 @@ function FocusMode({ label, durationSec, onExit, onEndAction }) {
|
|
|
3784
3856
|
process.stdout.write("\x07");
|
|
3785
3857
|
}
|
|
3786
3858
|
}, [timerDone]);
|
|
3787
|
-
const handleInput =
|
|
3859
|
+
const handleInput = useCallback10(
|
|
3788
3860
|
(input2, key) => {
|
|
3789
3861
|
if (key.escape) {
|
|
3790
3862
|
if (timerDone) {
|
|
@@ -3811,23 +3883,23 @@ function FocusMode({ label, durationSec, onExit, onEndAction }) {
|
|
|
3811
3883
|
);
|
|
3812
3884
|
useInput7(handleInput);
|
|
3813
3885
|
if (timerDone) {
|
|
3814
|
-
return /* @__PURE__ */
|
|
3815
|
-
/* @__PURE__ */
|
|
3816
|
-
/* @__PURE__ */
|
|
3817
|
-
/* @__PURE__ */
|
|
3886
|
+
return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", children: [
|
|
3887
|
+
/* @__PURE__ */ jsxs11(Box11, { children: [
|
|
3888
|
+
/* @__PURE__ */ jsx11(Text11, { color: "green", bold: true, children: "Focus complete!" }),
|
|
3889
|
+
/* @__PURE__ */ jsxs11(Text11, { color: "gray", children: [
|
|
3818
3890
|
" ",
|
|
3819
3891
|
label
|
|
3820
3892
|
] })
|
|
3821
3893
|
] }),
|
|
3822
|
-
/* @__PURE__ */
|
|
3823
|
-
/* @__PURE__ */
|
|
3824
|
-
/* @__PURE__ */
|
|
3825
|
-
/* @__PURE__ */
|
|
3826
|
-
/* @__PURE__ */
|
|
3827
|
-
/* @__PURE__ */
|
|
3828
|
-
/* @__PURE__ */
|
|
3829
|
-
/* @__PURE__ */
|
|
3830
|
-
/* @__PURE__ */
|
|
3894
|
+
/* @__PURE__ */ jsxs11(Box11, { marginTop: 1, children: [
|
|
3895
|
+
/* @__PURE__ */ jsx11(Text11, { color: "cyan", children: "[c]" }),
|
|
3896
|
+
/* @__PURE__ */ jsx11(Text11, { children: " Continue " }),
|
|
3897
|
+
/* @__PURE__ */ jsx11(Text11, { color: "cyan", children: "[b]" }),
|
|
3898
|
+
/* @__PURE__ */ jsx11(Text11, { children: " Break " }),
|
|
3899
|
+
/* @__PURE__ */ jsx11(Text11, { color: "cyan", children: "[d]" }),
|
|
3900
|
+
/* @__PURE__ */ jsx11(Text11, { children: " Done " }),
|
|
3901
|
+
/* @__PURE__ */ jsx11(Text11, { color: "gray", children: "[Esc]" }),
|
|
3902
|
+
/* @__PURE__ */ jsx11(Text11, { children: " Exit" })
|
|
3831
3903
|
] })
|
|
3832
3904
|
] });
|
|
3833
3905
|
}
|
|
@@ -3835,21 +3907,21 @@ function FocusMode({ label, durationSec, onExit, onEndAction }) {
|
|
|
3835
3907
|
const barWidth = 20;
|
|
3836
3908
|
const filled = Math.round(progress * barWidth);
|
|
3837
3909
|
const bar = "\u2588".repeat(filled) + "\u2591".repeat(barWidth - filled);
|
|
3838
|
-
return /* @__PURE__ */
|
|
3839
|
-
/* @__PURE__ */
|
|
3840
|
-
/* @__PURE__ */
|
|
3910
|
+
return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", children: [
|
|
3911
|
+
/* @__PURE__ */ jsxs11(Box11, { children: [
|
|
3912
|
+
/* @__PURE__ */ jsxs11(Text11, { color: "magenta", bold: true, children: [
|
|
3841
3913
|
"Focus:",
|
|
3842
3914
|
" "
|
|
3843
3915
|
] }),
|
|
3844
|
-
/* @__PURE__ */
|
|
3916
|
+
/* @__PURE__ */ jsx11(Text11, { children: label })
|
|
3845
3917
|
] }),
|
|
3846
|
-
/* @__PURE__ */
|
|
3847
|
-
/* @__PURE__ */
|
|
3848
|
-
/* @__PURE__ */
|
|
3849
|
-
/* @__PURE__ */
|
|
3850
|
-
/* @__PURE__ */
|
|
3918
|
+
/* @__PURE__ */ jsxs11(Box11, { children: [
|
|
3919
|
+
/* @__PURE__ */ jsx11(Text11, { color: "magenta", children: bar }),
|
|
3920
|
+
/* @__PURE__ */ jsx11(Text11, { children: " " }),
|
|
3921
|
+
/* @__PURE__ */ jsx11(Text11, { bold: true, children: formatTime(remaining) }),
|
|
3922
|
+
/* @__PURE__ */ jsx11(Text11, { color: "gray", children: " remaining" })
|
|
3851
3923
|
] }),
|
|
3852
|
-
/* @__PURE__ */
|
|
3924
|
+
/* @__PURE__ */ jsx11(Text11, { color: "gray", dimColor: true, children: "Esc to exit focus" })
|
|
3853
3925
|
] });
|
|
3854
3926
|
}
|
|
3855
3927
|
var init_focus_mode = __esm({
|
|
@@ -3861,18 +3933,18 @@ var init_focus_mode = __esm({
|
|
|
3861
3933
|
// src/board/components/fuzzy-picker.tsx
|
|
3862
3934
|
import { TextInput as TextInput3 } from "@inkjs/ui";
|
|
3863
3935
|
import { Fzf } from "fzf";
|
|
3864
|
-
import { Box as
|
|
3865
|
-
import { useMemo as useMemo2, useState as
|
|
3866
|
-
import { jsx as
|
|
3936
|
+
import { Box as Box12, Text as Text12, useInput as useInput8 } from "ink";
|
|
3937
|
+
import { useMemo as useMemo2, useState as useState13 } from "react";
|
|
3938
|
+
import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
3867
3939
|
function keepCursorVisible(cursor, offset, visible) {
|
|
3868
3940
|
if (cursor < offset) return cursor;
|
|
3869
3941
|
if (cursor >= offset + visible) return cursor - visible + 1;
|
|
3870
3942
|
return offset;
|
|
3871
3943
|
}
|
|
3872
3944
|
function FuzzyPicker({ repos, onSelect, onClose }) {
|
|
3873
|
-
const [query, setQuery] =
|
|
3874
|
-
const [cursor, setCursor] =
|
|
3875
|
-
const [scrollOffset, setScrollOffset] =
|
|
3945
|
+
const [query, setQuery] = useState13("");
|
|
3946
|
+
const [cursor, setCursor] = useState13(0);
|
|
3947
|
+
const [scrollOffset, setScrollOffset] = useState13(0);
|
|
3876
3948
|
const allIssues = useMemo2(() => {
|
|
3877
3949
|
const items = [];
|
|
3878
3950
|
for (const rd of repos) {
|
|
@@ -3955,13 +4027,13 @@ function FuzzyPicker({ repos, onSelect, onClose }) {
|
|
|
3955
4027
|
});
|
|
3956
4028
|
const visibleResults = results.slice(scrollOffset, scrollOffset + VISIBLE);
|
|
3957
4029
|
const totalCount = results.length;
|
|
3958
|
-
return /* @__PURE__ */
|
|
3959
|
-
/* @__PURE__ */
|
|
3960
|
-
/* @__PURE__ */
|
|
4030
|
+
return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
|
|
4031
|
+
/* @__PURE__ */ jsxs12(Box12, { children: [
|
|
4032
|
+
/* @__PURE__ */ jsxs12(Text12, { color: "cyan", bold: true, children: [
|
|
3961
4033
|
"Find issue",
|
|
3962
4034
|
" "
|
|
3963
4035
|
] }),
|
|
3964
|
-
/* @__PURE__ */
|
|
4036
|
+
/* @__PURE__ */ jsxs12(Text12, { color: "gray", children: [
|
|
3965
4037
|
"(",
|
|
3966
4038
|
totalCount,
|
|
3967
4039
|
" match",
|
|
@@ -3969,14 +4041,14 @@ function FuzzyPicker({ repos, onSelect, onClose }) {
|
|
|
3969
4041
|
")",
|
|
3970
4042
|
" "
|
|
3971
4043
|
] }),
|
|
3972
|
-
/* @__PURE__ */
|
|
4044
|
+
/* @__PURE__ */ jsx12(Text12, { color: "gray", dimColor: true, children: "\u2191\u2193/Ctrl-J/K nav Enter:jump Esc:close" })
|
|
3973
4045
|
] }),
|
|
3974
|
-
/* @__PURE__ */
|
|
3975
|
-
/* @__PURE__ */
|
|
4046
|
+
/* @__PURE__ */ jsxs12(Box12, { children: [
|
|
4047
|
+
/* @__PURE__ */ jsxs12(Text12, { color: "yellow", children: [
|
|
3976
4048
|
">",
|
|
3977
4049
|
" "
|
|
3978
4050
|
] }),
|
|
3979
|
-
/* @__PURE__ */
|
|
4051
|
+
/* @__PURE__ */ jsx12(
|
|
3980
4052
|
TextInput3,
|
|
3981
4053
|
{
|
|
3982
4054
|
defaultValue: query,
|
|
@@ -3993,7 +4065,7 @@ function FuzzyPicker({ repos, onSelect, onClose }) {
|
|
|
3993
4065
|
}
|
|
3994
4066
|
)
|
|
3995
4067
|
] }),
|
|
3996
|
-
scrollOffset > 0 ? /* @__PURE__ */
|
|
4068
|
+
scrollOffset > 0 ? /* @__PURE__ */ jsxs12(Text12, { color: "gray", dimColor: true, children: [
|
|
3997
4069
|
"\u25B2 ",
|
|
3998
4070
|
scrollOffset,
|
|
3999
4071
|
" more above"
|
|
@@ -4002,7 +4074,7 @@ function FuzzyPicker({ repos, onSelect, onClose }) {
|
|
|
4002
4074
|
const isSelected = scrollOffset + idx === cursor;
|
|
4003
4075
|
const labelStr = issue.labels ? ` [${issue.labels.split(" ").slice(0, 2).join("] [")}]` : "";
|
|
4004
4076
|
const assigneeStr = issue.assignee ? ` @${issue.assignee.split(" ")[0]}` : "";
|
|
4005
|
-
return /* @__PURE__ */
|
|
4077
|
+
return /* @__PURE__ */ jsx12(Box12, { children: isSelected ? /* @__PURE__ */ jsxs12(Text12, { color: "cyan", bold: true, children: [
|
|
4006
4078
|
">",
|
|
4007
4079
|
" ",
|
|
4008
4080
|
issue.repoShortName,
|
|
@@ -4012,7 +4084,7 @@ function FuzzyPicker({ repos, onSelect, onClose }) {
|
|
|
4012
4084
|
issue.title,
|
|
4013
4085
|
labelStr,
|
|
4014
4086
|
assigneeStr
|
|
4015
|
-
] }) : /* @__PURE__ */
|
|
4087
|
+
] }) : /* @__PURE__ */ jsxs12(Text12, { children: [
|
|
4016
4088
|
" ",
|
|
4017
4089
|
issue.repoShortName,
|
|
4018
4090
|
"#",
|
|
@@ -4023,12 +4095,12 @@ function FuzzyPicker({ repos, onSelect, onClose }) {
|
|
|
4023
4095
|
assigneeStr
|
|
4024
4096
|
] }) }, issue.navId);
|
|
4025
4097
|
}),
|
|
4026
|
-
totalCount === 0 ? /* @__PURE__ */
|
|
4098
|
+
totalCount === 0 ? /* @__PURE__ */ jsxs12(Text12, { dimColor: true, children: [
|
|
4027
4099
|
'No issues match "',
|
|
4028
4100
|
query,
|
|
4029
4101
|
'"'
|
|
4030
4102
|
] }) : null,
|
|
4031
|
-
results.length > scrollOffset + VISIBLE ? /* @__PURE__ */
|
|
4103
|
+
results.length > scrollOffset + VISIBLE ? /* @__PURE__ */ jsxs12(Text12, { color: "gray", dimColor: true, children: [
|
|
4032
4104
|
"\u25BC ",
|
|
4033
4105
|
results.length - scrollOffset - VISIBLE,
|
|
4034
4106
|
" more below"
|
|
@@ -4042,29 +4114,29 @@ var init_fuzzy_picker = __esm({
|
|
|
4042
4114
|
});
|
|
4043
4115
|
|
|
4044
4116
|
// src/board/components/help-overlay.tsx
|
|
4045
|
-
import { Box as
|
|
4046
|
-
import { jsx as
|
|
4117
|
+
import { Box as Box13, Text as Text13, useInput as useInput9 } from "ink";
|
|
4118
|
+
import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
4047
4119
|
function HelpOverlay({ currentMode, onClose }) {
|
|
4048
4120
|
useInput9((_input, key) => {
|
|
4049
4121
|
if (key.escape) onClose();
|
|
4050
4122
|
});
|
|
4051
|
-
return /* @__PURE__ */
|
|
4052
|
-
/* @__PURE__ */
|
|
4053
|
-
/* @__PURE__ */
|
|
4054
|
-
/* @__PURE__ */
|
|
4123
|
+
return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
|
|
4124
|
+
/* @__PURE__ */ jsxs13(Box13, { justifyContent: "space-between", children: [
|
|
4125
|
+
/* @__PURE__ */ jsx13(Text13, { color: "cyan", bold: true, children: "Keyboard Shortcuts" }),
|
|
4126
|
+
/* @__PURE__ */ jsxs13(Text13, { dimColor: true, children: [
|
|
4055
4127
|
"mode: ",
|
|
4056
4128
|
currentMode
|
|
4057
4129
|
] })
|
|
4058
4130
|
] }),
|
|
4059
|
-
/* @__PURE__ */
|
|
4060
|
-
SHORTCUTS.map((group) => /* @__PURE__ */
|
|
4061
|
-
/* @__PURE__ */
|
|
4062
|
-
group.items.map((item) => /* @__PURE__ */
|
|
4063
|
-
/* @__PURE__ */
|
|
4064
|
-
/* @__PURE__ */
|
|
4131
|
+
/* @__PURE__ */ jsx13(Text13, { children: " " }),
|
|
4132
|
+
SHORTCUTS.map((group) => /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", marginBottom: 1, children: [
|
|
4133
|
+
/* @__PURE__ */ jsx13(Text13, { color: "yellow", bold: true, children: group.category }),
|
|
4134
|
+
group.items.map((item) => /* @__PURE__ */ jsxs13(Box13, { children: [
|
|
4135
|
+
/* @__PURE__ */ jsx13(Box13, { width: 16, children: /* @__PURE__ */ jsx13(Text13, { color: "green", children: item.key }) }),
|
|
4136
|
+
/* @__PURE__ */ jsx13(Text13, { children: item.desc })
|
|
4065
4137
|
] }, item.key))
|
|
4066
4138
|
] }, group.category)),
|
|
4067
|
-
/* @__PURE__ */
|
|
4139
|
+
/* @__PURE__ */ jsx13(Text13, { dimColor: true, children: "Press ? or Esc to close" })
|
|
4068
4140
|
] });
|
|
4069
4141
|
}
|
|
4070
4142
|
var SHORTCUTS;
|
|
@@ -4130,9 +4202,9 @@ import { mkdtempSync as mkdtempSync3, readFileSync as readFileSync6, rmSync as r
|
|
|
4130
4202
|
import { tmpdir as tmpdir3 } from "os";
|
|
4131
4203
|
import { join as join6 } from "path";
|
|
4132
4204
|
import { Spinner as Spinner2, TextInput as TextInput4 } from "@inkjs/ui";
|
|
4133
|
-
import { Box as
|
|
4134
|
-
import { useCallback as
|
|
4135
|
-
import { jsx as
|
|
4205
|
+
import { Box as Box14, Text as Text14, useInput as useInput10, useStdin as useStdin3 } from "ink";
|
|
4206
|
+
import { useCallback as useCallback11, useEffect as useEffect8, useRef as useRef11, useState as useState14 } from "react";
|
|
4207
|
+
import { jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
4136
4208
|
function NlCreateOverlay({
|
|
4137
4209
|
repos,
|
|
4138
4210
|
defaultRepoName,
|
|
@@ -4143,13 +4215,13 @@ function NlCreateOverlay({
|
|
|
4143
4215
|
onResumeRefresh,
|
|
4144
4216
|
onLlmFallback
|
|
4145
4217
|
}) {
|
|
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] =
|
|
4218
|
+
const [, setInput] = useState14("");
|
|
4219
|
+
const [isParsing, setIsParsing] = useState14(false);
|
|
4220
|
+
const [parsed, setParsed] = useState14(null);
|
|
4221
|
+
const [parseError, setParseError] = useState14(null);
|
|
4222
|
+
const [step, setStep] = useState14("input");
|
|
4223
|
+
const [body, setBody] = useState14("");
|
|
4224
|
+
const [editingBody, setEditingBody] = useState14(false);
|
|
4153
4225
|
const submittedRef = useRef11(false);
|
|
4154
4226
|
const parseParamsRef = useRef11(null);
|
|
4155
4227
|
const onSubmitRef = useRef11(onSubmit);
|
|
@@ -4165,7 +4237,7 @@ function NlCreateOverlay({
|
|
|
4165
4237
|
0,
|
|
4166
4238
|
repos.findIndex((r) => r.name === defaultRepoName)
|
|
4167
4239
|
) : 0;
|
|
4168
|
-
const [repoIdx, setRepoIdx] =
|
|
4240
|
+
const [repoIdx, setRepoIdx] = useState14(defaultRepoIdx);
|
|
4169
4241
|
const selectedRepo = repos[repoIdx];
|
|
4170
4242
|
useInput10((inputChar, key) => {
|
|
4171
4243
|
if (isParsing || editingBody) return;
|
|
@@ -4225,7 +4297,7 @@ function NlCreateOverlay({
|
|
|
4225
4297
|
setEditingBody(false);
|
|
4226
4298
|
}
|
|
4227
4299
|
}, [editingBody, body, setRawMode]);
|
|
4228
|
-
const handleInputSubmit =
|
|
4300
|
+
const handleInputSubmit = useCallback11(
|
|
4229
4301
|
(text) => {
|
|
4230
4302
|
const trimmed = text.trim();
|
|
4231
4303
|
if (!trimmed) return;
|
|
@@ -4258,27 +4330,27 @@ function NlCreateOverlay({
|
|
|
4258
4330
|
});
|
|
4259
4331
|
}, [isParsing, onLlmFallback]);
|
|
4260
4332
|
if (isParsing) {
|
|
4261
|
-
return /* @__PURE__ */
|
|
4262
|
-
/* @__PURE__ */
|
|
4263
|
-
/* @__PURE__ */
|
|
4333
|
+
return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", children: [
|
|
4334
|
+
/* @__PURE__ */ jsx14(Text14, { color: "cyan", bold: true, children: "\u2728 Creating Issue" }),
|
|
4335
|
+
/* @__PURE__ */ jsx14(Spinner2, { label: "Parsing..." })
|
|
4264
4336
|
] });
|
|
4265
4337
|
}
|
|
4266
4338
|
if (parsed && step === "body") {
|
|
4267
4339
|
if (editingBody) {
|
|
4268
|
-
return /* @__PURE__ */
|
|
4269
|
-
/* @__PURE__ */
|
|
4270
|
-
/* @__PURE__ */
|
|
4340
|
+
return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", children: [
|
|
4341
|
+
/* @__PURE__ */ jsx14(Text14, { color: "cyan", bold: true, children: "\u2728 Creating Issue" }),
|
|
4342
|
+
/* @__PURE__ */ jsx14(Text14, { color: "cyan", children: "Opening editor for body\u2026" })
|
|
4271
4343
|
] });
|
|
4272
4344
|
}
|
|
4273
|
-
return /* @__PURE__ */
|
|
4274
|
-
/* @__PURE__ */
|
|
4275
|
-
/* @__PURE__ */
|
|
4276
|
-
/* @__PURE__ */
|
|
4277
|
-
/* @__PURE__ */
|
|
4345
|
+
return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", children: [
|
|
4346
|
+
/* @__PURE__ */ jsx14(Text14, { color: "cyan", bold: true, children: "\u2728 Creating Issue" }),
|
|
4347
|
+
/* @__PURE__ */ jsxs14(Box14, { children: [
|
|
4348
|
+
/* @__PURE__ */ jsx14(Text14, { dimColor: true, children: "Title: " }),
|
|
4349
|
+
/* @__PURE__ */ jsx14(Text14, { children: parsed.title })
|
|
4278
4350
|
] }),
|
|
4279
|
-
/* @__PURE__ */
|
|
4280
|
-
/* @__PURE__ */
|
|
4281
|
-
/* @__PURE__ */
|
|
4351
|
+
/* @__PURE__ */ jsxs14(Box14, { children: [
|
|
4352
|
+
/* @__PURE__ */ jsx14(Text14, { color: "cyan", children: "body: " }),
|
|
4353
|
+
/* @__PURE__ */ jsx14(
|
|
4282
4354
|
TextInput4,
|
|
4283
4355
|
{
|
|
4284
4356
|
defaultValue: body,
|
|
@@ -4300,45 +4372,45 @@ function NlCreateOverlay({
|
|
|
4300
4372
|
}
|
|
4301
4373
|
)
|
|
4302
4374
|
] }),
|
|
4303
|
-
/* @__PURE__ */
|
|
4375
|
+
/* @__PURE__ */ jsx14(Text14, { dimColor: true, children: "Enter:create ctrl+e:editor Esc:back" })
|
|
4304
4376
|
] });
|
|
4305
4377
|
}
|
|
4306
4378
|
if (parsed) {
|
|
4307
4379
|
const labels = [...parsed.labels];
|
|
4308
|
-
return /* @__PURE__ */
|
|
4309
|
-
/* @__PURE__ */
|
|
4310
|
-
/* @__PURE__ */
|
|
4311
|
-
/* @__PURE__ */
|
|
4312
|
-
/* @__PURE__ */
|
|
4313
|
-
repos.length > 1 ? /* @__PURE__ */
|
|
4380
|
+
return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", children: [
|
|
4381
|
+
/* @__PURE__ */ jsx14(Text14, { color: "cyan", bold: true, children: "\u2728 Creating Issue" }),
|
|
4382
|
+
/* @__PURE__ */ jsxs14(Box14, { children: [
|
|
4383
|
+
/* @__PURE__ */ jsx14(Text14, { dimColor: true, children: "Repo: " }),
|
|
4384
|
+
/* @__PURE__ */ jsx14(Text14, { color: "cyan", children: selectedRepo?.shortName ?? "(none)" }),
|
|
4385
|
+
repos.length > 1 ? /* @__PURE__ */ jsx14(Text14, { dimColor: true, children: " r:cycle" }) : null
|
|
4314
4386
|
] }),
|
|
4315
|
-
/* @__PURE__ */
|
|
4316
|
-
/* @__PURE__ */
|
|
4317
|
-
/* @__PURE__ */
|
|
4387
|
+
/* @__PURE__ */ jsxs14(Box14, { children: [
|
|
4388
|
+
/* @__PURE__ */ jsx14(Text14, { dimColor: true, children: "Title: " }),
|
|
4389
|
+
/* @__PURE__ */ jsx14(Text14, { children: parsed.title })
|
|
4318
4390
|
] }),
|
|
4319
|
-
labels.length > 0 ? /* @__PURE__ */
|
|
4320
|
-
/* @__PURE__ */
|
|
4321
|
-
/* @__PURE__ */
|
|
4391
|
+
labels.length > 0 ? /* @__PURE__ */ jsxs14(Box14, { children: [
|
|
4392
|
+
/* @__PURE__ */ jsx14(Text14, { dimColor: true, children: "Labels: " }),
|
|
4393
|
+
/* @__PURE__ */ jsx14(Text14, { children: labels.join(", ") })
|
|
4322
4394
|
] }) : null,
|
|
4323
|
-
parsed.assignee ? /* @__PURE__ */
|
|
4324
|
-
/* @__PURE__ */
|
|
4325
|
-
/* @__PURE__ */
|
|
4395
|
+
parsed.assignee ? /* @__PURE__ */ jsxs14(Box14, { children: [
|
|
4396
|
+
/* @__PURE__ */ jsx14(Text14, { dimColor: true, children: "Assignee: " }),
|
|
4397
|
+
/* @__PURE__ */ jsxs14(Text14, { children: [
|
|
4326
4398
|
"@",
|
|
4327
4399
|
parsed.assignee
|
|
4328
4400
|
] })
|
|
4329
4401
|
] }) : null,
|
|
4330
|
-
parsed.dueDate ? /* @__PURE__ */
|
|
4331
|
-
/* @__PURE__ */
|
|
4332
|
-
/* @__PURE__ */
|
|
4402
|
+
parsed.dueDate ? /* @__PURE__ */ jsxs14(Box14, { children: [
|
|
4403
|
+
/* @__PURE__ */ jsx14(Text14, { dimColor: true, children: "Due: " }),
|
|
4404
|
+
/* @__PURE__ */ jsx14(Text14, { children: formatDue(parsed.dueDate) })
|
|
4333
4405
|
] }) : null,
|
|
4334
|
-
/* @__PURE__ */
|
|
4406
|
+
/* @__PURE__ */ jsx14(Text14, { dimColor: true, children: "Enter:add body Esc:cancel" })
|
|
4335
4407
|
] });
|
|
4336
4408
|
}
|
|
4337
|
-
return /* @__PURE__ */
|
|
4338
|
-
/* @__PURE__ */
|
|
4339
|
-
/* @__PURE__ */
|
|
4340
|
-
/* @__PURE__ */
|
|
4341
|
-
/* @__PURE__ */
|
|
4409
|
+
return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", children: [
|
|
4410
|
+
/* @__PURE__ */ jsx14(Text14, { color: "cyan", bold: true, children: "\u2728 What do you need to do?" }),
|
|
4411
|
+
/* @__PURE__ */ jsxs14(Box14, { children: [
|
|
4412
|
+
/* @__PURE__ */ jsx14(Text14, { color: "cyan", children: "> " }),
|
|
4413
|
+
/* @__PURE__ */ jsx14(
|
|
4342
4414
|
TextInput4,
|
|
4343
4415
|
{
|
|
4344
4416
|
placeholder: "fix login bug #bug #priority:high @me due friday",
|
|
@@ -4347,8 +4419,8 @@ function NlCreateOverlay({
|
|
|
4347
4419
|
}
|
|
4348
4420
|
)
|
|
4349
4421
|
] }),
|
|
4350
|
-
parseError ? /* @__PURE__ */
|
|
4351
|
-
/* @__PURE__ */
|
|
4422
|
+
parseError ? /* @__PURE__ */ jsx14(Text14, { color: "red", children: parseError }) : null,
|
|
4423
|
+
/* @__PURE__ */ jsx14(Text14, { dimColor: true, children: "Tip: #label @user due <date> Enter:parse Esc:cancel" })
|
|
4352
4424
|
] });
|
|
4353
4425
|
}
|
|
4354
4426
|
function buildLabelList(parsed) {
|
|
@@ -4368,12 +4440,12 @@ var init_nl_create_overlay = __esm({
|
|
|
4368
4440
|
|
|
4369
4441
|
// src/board/components/search-bar.tsx
|
|
4370
4442
|
import { TextInput as TextInput5 } from "@inkjs/ui";
|
|
4371
|
-
import { Box as
|
|
4372
|
-
import { jsx as
|
|
4443
|
+
import { Box as Box15, Text as Text15 } from "ink";
|
|
4444
|
+
import { jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
4373
4445
|
function SearchBar({ defaultValue, onChange, onSubmit }) {
|
|
4374
|
-
return /* @__PURE__ */
|
|
4375
|
-
/* @__PURE__ */
|
|
4376
|
-
/* @__PURE__ */
|
|
4446
|
+
return /* @__PURE__ */ jsxs15(Box15, { children: [
|
|
4447
|
+
/* @__PURE__ */ jsx15(Text15, { color: "yellow", children: "/" }),
|
|
4448
|
+
/* @__PURE__ */ jsx15(
|
|
4377
4449
|
TextInput5,
|
|
4378
4450
|
{
|
|
4379
4451
|
defaultValue,
|
|
@@ -4391,9 +4463,9 @@ var init_search_bar = __esm({
|
|
|
4391
4463
|
});
|
|
4392
4464
|
|
|
4393
4465
|
// src/board/components/status-picker.tsx
|
|
4394
|
-
import { Box as
|
|
4395
|
-
import { useRef as useRef12, useState as
|
|
4396
|
-
import { jsx as
|
|
4466
|
+
import { Box as Box16, Text as Text16, useInput as useInput11 } from "ink";
|
|
4467
|
+
import { useRef as useRef12, useState as useState15 } from "react";
|
|
4468
|
+
import { jsx as jsx16, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
4397
4469
|
function isTerminal(name) {
|
|
4398
4470
|
return TERMINAL_STATUS_RE.test(name);
|
|
4399
4471
|
}
|
|
@@ -4440,11 +4512,11 @@ function StatusPicker({
|
|
|
4440
4512
|
onCancel,
|
|
4441
4513
|
showTerminalStatuses = true
|
|
4442
4514
|
}) {
|
|
4443
|
-
const [selectedIdx, setSelectedIdx] =
|
|
4515
|
+
const [selectedIdx, setSelectedIdx] = useState15(() => {
|
|
4444
4516
|
const idx = options.findIndex((o) => o.name === currentStatus);
|
|
4445
4517
|
return idx >= 0 ? idx : 0;
|
|
4446
4518
|
});
|
|
4447
|
-
const [confirmingTerminal, setConfirmingTerminal] =
|
|
4519
|
+
const [confirmingTerminal, setConfirmingTerminal] = useState15(false);
|
|
4448
4520
|
const submittedRef = useRef12(false);
|
|
4449
4521
|
useInput11((input2, key) => {
|
|
4450
4522
|
if (confirmingTerminal) {
|
|
@@ -4469,26 +4541,26 @@ function StatusPicker({
|
|
|
4469
4541
|
});
|
|
4470
4542
|
if (confirmingTerminal) {
|
|
4471
4543
|
const opt = options[selectedIdx];
|
|
4472
|
-
return /* @__PURE__ */
|
|
4473
|
-
/* @__PURE__ */
|
|
4544
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", children: [
|
|
4545
|
+
/* @__PURE__ */ jsxs16(Text16, { color: "yellow", bold: true, children: [
|
|
4474
4546
|
"Mark as ",
|
|
4475
4547
|
opt?.name,
|
|
4476
4548
|
"?"
|
|
4477
4549
|
] }),
|
|
4478
|
-
/* @__PURE__ */
|
|
4479
|
-
/* @__PURE__ */
|
|
4550
|
+
/* @__PURE__ */ jsx16(Text16, { dimColor: true, children: "This will close the issue on GitHub." }),
|
|
4551
|
+
/* @__PURE__ */ jsx16(Text16, { children: "Continue? [y/n]" })
|
|
4480
4552
|
] });
|
|
4481
4553
|
}
|
|
4482
|
-
return /* @__PURE__ */
|
|
4483
|
-
/* @__PURE__ */
|
|
4554
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", children: [
|
|
4555
|
+
/* @__PURE__ */ jsx16(Text16, { color: "cyan", bold: true, children: "Move to status:" }),
|
|
4484
4556
|
options.map((opt, i) => {
|
|
4485
4557
|
const isCurrent = opt.name === currentStatus;
|
|
4486
4558
|
const isSelected = i === selectedIdx;
|
|
4487
4559
|
const terminal = isTerminal(opt.name) && showTerminalStatuses;
|
|
4488
4560
|
const prefix = isSelected ? "> " : " ";
|
|
4489
4561
|
const suffix = isCurrent ? " (current)" : terminal ? " (Done)" : "";
|
|
4490
|
-
return /* @__PURE__ */
|
|
4491
|
-
|
|
4562
|
+
return /* @__PURE__ */ jsxs16(
|
|
4563
|
+
Text16,
|
|
4492
4564
|
{
|
|
4493
4565
|
...isSelected ? { color: "cyan" } : terminal ? { color: "yellow" } : {},
|
|
4494
4566
|
dimColor: isCurrent,
|
|
@@ -4501,7 +4573,7 @@ function StatusPicker({
|
|
|
4501
4573
|
opt.id
|
|
4502
4574
|
);
|
|
4503
4575
|
}),
|
|
4504
|
-
/* @__PURE__ */
|
|
4576
|
+
/* @__PURE__ */ jsx16(Text16, { dimColor: true, children: "j/k:navigate Enter:select Esc:cancel" })
|
|
4505
4577
|
] });
|
|
4506
4578
|
}
|
|
4507
4579
|
var init_status_picker = __esm({
|
|
@@ -4512,7 +4584,7 @@ var init_status_picker = __esm({
|
|
|
4512
4584
|
});
|
|
4513
4585
|
|
|
4514
4586
|
// src/board/components/overlay-renderer.tsx
|
|
4515
|
-
import { Fragment as Fragment2, jsx as
|
|
4587
|
+
import { Fragment as Fragment2, jsx as jsx17, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
4516
4588
|
function OverlayRenderer({
|
|
4517
4589
|
uiState,
|
|
4518
4590
|
config: config2,
|
|
@@ -4553,9 +4625,9 @@ function OverlayRenderer({
|
|
|
4553
4625
|
onPushEntry
|
|
4554
4626
|
}) {
|
|
4555
4627
|
const { mode, helpVisible } = uiState;
|
|
4556
|
-
return /* @__PURE__ */
|
|
4557
|
-
helpVisible ? /* @__PURE__ */
|
|
4558
|
-
mode === "overlay:status" && selectedRepoStatusOptions.length > 0 ? /* @__PURE__ */
|
|
4628
|
+
return /* @__PURE__ */ jsxs17(Fragment2, { children: [
|
|
4629
|
+
helpVisible ? /* @__PURE__ */ jsx17(HelpOverlay, { currentMode: mode, onClose: onToggleHelp }) : null,
|
|
4630
|
+
mode === "overlay:status" && selectedRepoStatusOptions.length > 0 ? /* @__PURE__ */ jsx17(
|
|
4559
4631
|
StatusPicker,
|
|
4560
4632
|
{
|
|
4561
4633
|
options: selectedRepoStatusOptions,
|
|
@@ -4564,7 +4636,7 @@ function OverlayRenderer({
|
|
|
4564
4636
|
onCancel: onExitOverlay
|
|
4565
4637
|
}
|
|
4566
4638
|
) : null,
|
|
4567
|
-
mode === "overlay:create" ? /* @__PURE__ */
|
|
4639
|
+
mode === "overlay:create" ? /* @__PURE__ */ jsx17(
|
|
4568
4640
|
CreateIssueForm,
|
|
4569
4641
|
{
|
|
4570
4642
|
repos: config2.repos,
|
|
@@ -4574,7 +4646,7 @@ function OverlayRenderer({
|
|
|
4574
4646
|
labelCache
|
|
4575
4647
|
}
|
|
4576
4648
|
) : null,
|
|
4577
|
-
mode === "overlay:confirmPick" ? /* @__PURE__ */
|
|
4649
|
+
mode === "overlay:confirmPick" ? /* @__PURE__ */ jsx17(
|
|
4578
4650
|
ConfirmPrompt,
|
|
4579
4651
|
{
|
|
4580
4652
|
message: "Pick this issue?",
|
|
@@ -4582,7 +4654,7 @@ function OverlayRenderer({
|
|
|
4582
4654
|
onCancel: onCancelPick
|
|
4583
4655
|
}
|
|
4584
4656
|
) : null,
|
|
4585
|
-
mode === "overlay:bulkAction" ? /* @__PURE__ */
|
|
4657
|
+
mode === "overlay:bulkAction" ? /* @__PURE__ */ jsx17(
|
|
4586
4658
|
BulkActionMenu,
|
|
4587
4659
|
{
|
|
4588
4660
|
count: multiSelectCount,
|
|
@@ -4591,7 +4663,7 @@ function OverlayRenderer({
|
|
|
4591
4663
|
onCancel: onExitOverlay
|
|
4592
4664
|
}
|
|
4593
4665
|
) : null,
|
|
4594
|
-
mode === "focus" && focusLabel ? /* @__PURE__ */
|
|
4666
|
+
mode === "focus" && focusLabel ? /* @__PURE__ */ jsx17(
|
|
4595
4667
|
FocusMode,
|
|
4596
4668
|
{
|
|
4597
4669
|
label: focusLabel,
|
|
@@ -4601,7 +4673,7 @@ function OverlayRenderer({
|
|
|
4601
4673
|
},
|
|
4602
4674
|
focusKey
|
|
4603
4675
|
) : null,
|
|
4604
|
-
mode === "overlay:label" && selectedIssue && defaultRepo ? /* @__PURE__ */
|
|
4676
|
+
mode === "overlay:label" && selectedIssue && defaultRepo ? /* @__PURE__ */ jsx17(
|
|
4605
4677
|
LabelPicker,
|
|
4606
4678
|
{
|
|
4607
4679
|
repo: defaultRepo,
|
|
@@ -4612,8 +4684,8 @@ function OverlayRenderer({
|
|
|
4612
4684
|
onError: onLabelError
|
|
4613
4685
|
}
|
|
4614
4686
|
) : null,
|
|
4615
|
-
mode === "search" ? /* @__PURE__ */
|
|
4616
|
-
mode === "overlay:comment" && selectedIssue ? /* @__PURE__ */
|
|
4687
|
+
mode === "search" ? /* @__PURE__ */ jsx17(SearchBar, { defaultValue: searchQuery, onChange: onSearchChange, onSubmit: onSearchSubmit }) : null,
|
|
4688
|
+
mode === "overlay:comment" && selectedIssue ? /* @__PURE__ */ jsx17(
|
|
4617
4689
|
CommentInput,
|
|
4618
4690
|
{
|
|
4619
4691
|
issueNumber: selectedIssue.number,
|
|
@@ -4623,8 +4695,8 @@ function OverlayRenderer({
|
|
|
4623
4695
|
onResumeRefresh
|
|
4624
4696
|
}
|
|
4625
4697
|
) : null,
|
|
4626
|
-
mode === "overlay:fuzzyPicker" ? /* @__PURE__ */
|
|
4627
|
-
mode === "overlay:createNl" ? /* @__PURE__ */
|
|
4698
|
+
mode === "overlay:fuzzyPicker" ? /* @__PURE__ */ jsx17(FuzzyPicker, { repos, onSelect: onFuzzySelect, onClose: onFuzzyClose }) : null,
|
|
4699
|
+
mode === "overlay:createNl" ? /* @__PURE__ */ jsx17(
|
|
4628
4700
|
NlCreateOverlay,
|
|
4629
4701
|
{
|
|
4630
4702
|
repos: config2.repos,
|
|
@@ -4637,7 +4709,7 @@ function OverlayRenderer({
|
|
|
4637
4709
|
onLlmFallback
|
|
4638
4710
|
}
|
|
4639
4711
|
) : null,
|
|
4640
|
-
mode === "overlay:editIssue" && selectedIssue && selectedRepoName ? /* @__PURE__ */
|
|
4712
|
+
mode === "overlay:editIssue" && selectedIssue && selectedRepoName ? /* @__PURE__ */ jsx17(
|
|
4641
4713
|
EditIssueOverlay,
|
|
4642
4714
|
{
|
|
4643
4715
|
issue: selectedIssue,
|
|
@@ -4673,9 +4745,106 @@ var init_overlay_renderer = __esm({
|
|
|
4673
4745
|
}
|
|
4674
4746
|
});
|
|
4675
4747
|
|
|
4748
|
+
// src/board/components/panel-layout.tsx
|
|
4749
|
+
import { Box as Box17 } from "ink";
|
|
4750
|
+
import { jsx as jsx18, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
4751
|
+
function getLayoutMode(cols) {
|
|
4752
|
+
if (cols >= WIDE_THRESHOLD) return "wide";
|
|
4753
|
+
if (cols >= MEDIUM_THRESHOLD) return "medium";
|
|
4754
|
+
return "stacked";
|
|
4755
|
+
}
|
|
4756
|
+
function getDetailWidth(cols) {
|
|
4757
|
+
return Math.floor(cols * 0.4);
|
|
4758
|
+
}
|
|
4759
|
+
function PanelLayout({
|
|
4760
|
+
cols,
|
|
4761
|
+
issuesPanelHeight,
|
|
4762
|
+
reposPanel,
|
|
4763
|
+
statusesPanel,
|
|
4764
|
+
issuesPanel,
|
|
4765
|
+
detailPanel,
|
|
4766
|
+
activityPanel
|
|
4767
|
+
}) {
|
|
4768
|
+
const mode = getLayoutMode(cols);
|
|
4769
|
+
if (mode === "wide") {
|
|
4770
|
+
const detailWidth = getDetailWidth(cols);
|
|
4771
|
+
return /* @__PURE__ */ jsxs18(Box17, { flexDirection: "column", children: [
|
|
4772
|
+
/* @__PURE__ */ jsxs18(Box17, { height: issuesPanelHeight, children: [
|
|
4773
|
+
/* @__PURE__ */ jsxs18(Box17, { flexDirection: "column", width: LEFT_COL_WIDTH, children: [
|
|
4774
|
+
reposPanel,
|
|
4775
|
+
statusesPanel
|
|
4776
|
+
] }),
|
|
4777
|
+
/* @__PURE__ */ jsx18(Box17, { flexGrow: 1, flexDirection: "column", children: issuesPanel }),
|
|
4778
|
+
/* @__PURE__ */ jsx18(Box17, { width: detailWidth, flexDirection: "column", children: detailPanel })
|
|
4779
|
+
] }),
|
|
4780
|
+
/* @__PURE__ */ jsx18(Box17, { height: ACTIVITY_HEIGHT, children: activityPanel })
|
|
4781
|
+
] });
|
|
4782
|
+
}
|
|
4783
|
+
if (mode === "medium") {
|
|
4784
|
+
return /* @__PURE__ */ jsxs18(Box17, { flexDirection: "column", children: [
|
|
4785
|
+
/* @__PURE__ */ jsxs18(Box17, { height: issuesPanelHeight, children: [
|
|
4786
|
+
/* @__PURE__ */ jsxs18(Box17, { flexDirection: "column", width: LEFT_COL_WIDTH, children: [
|
|
4787
|
+
reposPanel,
|
|
4788
|
+
statusesPanel
|
|
4789
|
+
] }),
|
|
4790
|
+
/* @__PURE__ */ jsx18(Box17, { flexGrow: 1, flexDirection: "column", children: issuesPanel })
|
|
4791
|
+
] }),
|
|
4792
|
+
/* @__PURE__ */ jsx18(Box17, { height: ACTIVITY_HEIGHT, children: activityPanel })
|
|
4793
|
+
] });
|
|
4794
|
+
}
|
|
4795
|
+
return /* @__PURE__ */ jsxs18(Box17, { flexDirection: "column", children: [
|
|
4796
|
+
reposPanel,
|
|
4797
|
+
statusesPanel,
|
|
4798
|
+
/* @__PURE__ */ jsx18(Box17, { flexGrow: 1, flexDirection: "column", children: issuesPanel }),
|
|
4799
|
+
/* @__PURE__ */ jsx18(Box17, { height: ACTIVITY_HEIGHT, children: activityPanel })
|
|
4800
|
+
] });
|
|
4801
|
+
}
|
|
4802
|
+
var WIDE_THRESHOLD, MEDIUM_THRESHOLD, LEFT_COL_WIDTH, ACTIVITY_HEIGHT;
|
|
4803
|
+
var init_panel_layout = __esm({
|
|
4804
|
+
"src/board/components/panel-layout.tsx"() {
|
|
4805
|
+
"use strict";
|
|
4806
|
+
WIDE_THRESHOLD = 160;
|
|
4807
|
+
MEDIUM_THRESHOLD = 100;
|
|
4808
|
+
LEFT_COL_WIDTH = 24;
|
|
4809
|
+
ACTIVITY_HEIGHT = 3;
|
|
4810
|
+
}
|
|
4811
|
+
});
|
|
4812
|
+
|
|
4813
|
+
// src/board/components/repos-panel.tsx
|
|
4814
|
+
import { Box as Box18, Text as Text17 } from "ink";
|
|
4815
|
+
import { jsx as jsx19, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
4816
|
+
function shortName(fullName) {
|
|
4817
|
+
return fullName.includes("/") ? fullName.split("/")[1] ?? fullName : fullName;
|
|
4818
|
+
}
|
|
4819
|
+
function ReposPanel({ repos, selectedIdx, isActive }) {
|
|
4820
|
+
const borderColor = isActive ? "cyan" : "gray";
|
|
4821
|
+
return /* @__PURE__ */ jsxs19(Box18, { borderStyle: "single", borderColor, flexDirection: "column", flexGrow: 1, children: [
|
|
4822
|
+
/* @__PURE__ */ jsx19(Text17, { bold: true, color: isActive ? "cyan" : "white", children: "[1] Repos" }),
|
|
4823
|
+
repos.length === 0 ? /* @__PURE__ */ jsx19(Text17, { color: "gray", children: " \u2014" }) : repos.map((repo, i) => {
|
|
4824
|
+
const isSel = i === selectedIdx;
|
|
4825
|
+
const label = shortName(repo.name);
|
|
4826
|
+
return /* @__PURE__ */ jsxs19(Box18, { children: [
|
|
4827
|
+
/* @__PURE__ */ jsxs19(Text17, { color: isSel ? "cyan" : isActive ? "white" : "gray", bold: isSel, children: [
|
|
4828
|
+
isSel ? "\u25B6 " : " ",
|
|
4829
|
+
label
|
|
4830
|
+
] }),
|
|
4831
|
+
/* @__PURE__ */ jsxs19(Text17, { color: "gray", children: [
|
|
4832
|
+
" ",
|
|
4833
|
+
repo.openCount
|
|
4834
|
+
] })
|
|
4835
|
+
] }, repo.name);
|
|
4836
|
+
})
|
|
4837
|
+
] });
|
|
4838
|
+
}
|
|
4839
|
+
var init_repos_panel = __esm({
|
|
4840
|
+
"src/board/components/repos-panel.tsx"() {
|
|
4841
|
+
"use strict";
|
|
4842
|
+
}
|
|
4843
|
+
});
|
|
4844
|
+
|
|
4676
4845
|
// src/board/components/issue-row.tsx
|
|
4677
|
-
import { Box as
|
|
4678
|
-
import { Fragment as Fragment3, jsx as
|
|
4846
|
+
import { Box as Box19, Text as Text18 } from "ink";
|
|
4847
|
+
import { Fragment as Fragment3, jsx as jsx20, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
4679
4848
|
function truncate(s, max) {
|
|
4680
4849
|
return s.length > max ? `${s.slice(0, max - 1)}\u2026` : s;
|
|
4681
4850
|
}
|
|
@@ -4716,30 +4885,30 @@ function IssueRow({ issue, selfLogin, isSelected }) {
|
|
|
4716
4885
|
const labels = (issue.labels ?? []).slice(0, 2);
|
|
4717
4886
|
const target = formatTargetDate(issue.targetDate);
|
|
4718
4887
|
const titleStr = truncate(issue.title, 42).padEnd(42);
|
|
4719
|
-
return /* @__PURE__ */
|
|
4720
|
-
isSelected ? /* @__PURE__ */
|
|
4721
|
-
/* @__PURE__ */
|
|
4888
|
+
return /* @__PURE__ */ jsxs20(Box19, { children: [
|
|
4889
|
+
isSelected ? /* @__PURE__ */ jsx20(Text18, { color: "cyan", bold: true, children: "\u25B6 " }) : /* @__PURE__ */ jsx20(Text18, { children: " " }),
|
|
4890
|
+
/* @__PURE__ */ jsxs20(Text18, { color: "cyan", children: [
|
|
4722
4891
|
"#",
|
|
4723
4892
|
String(issue.number).padEnd(5)
|
|
4724
4893
|
] }),
|
|
4725
|
-
/* @__PURE__ */
|
|
4726
|
-
isSelected ? /* @__PURE__ */
|
|
4727
|
-
/* @__PURE__ */
|
|
4728
|
-
/* @__PURE__ */
|
|
4894
|
+
/* @__PURE__ */ jsx20(Text18, { children: " " }),
|
|
4895
|
+
isSelected ? /* @__PURE__ */ jsx20(Text18, { color: "white", bold: true, children: titleStr }) : /* @__PURE__ */ jsx20(Text18, { children: titleStr }),
|
|
4896
|
+
/* @__PURE__ */ jsx20(Text18, { children: " " }),
|
|
4897
|
+
/* @__PURE__ */ jsx20(Box19, { width: LABEL_COL_WIDTH, children: labels.map((l, i) => /* @__PURE__ */ jsxs20(Text18, { children: [
|
|
4729
4898
|
i > 0 ? " " : "",
|
|
4730
|
-
/* @__PURE__ */
|
|
4899
|
+
/* @__PURE__ */ jsxs20(Text18, { color: labelColor(l.name), children: [
|
|
4731
4900
|
"[",
|
|
4732
4901
|
truncate(l.name, 12),
|
|
4733
4902
|
"]"
|
|
4734
4903
|
] })
|
|
4735
4904
|
] }, l.name)) }),
|
|
4736
|
-
/* @__PURE__ */
|
|
4737
|
-
/* @__PURE__ */
|
|
4738
|
-
/* @__PURE__ */
|
|
4739
|
-
/* @__PURE__ */
|
|
4740
|
-
target.text ? /* @__PURE__ */
|
|
4741
|
-
/* @__PURE__ */
|
|
4742
|
-
/* @__PURE__ */
|
|
4905
|
+
/* @__PURE__ */ jsx20(Text18, { children: " " }),
|
|
4906
|
+
/* @__PURE__ */ jsx20(Text18, { color: assigneeColor, children: assigneeText.padEnd(14) }),
|
|
4907
|
+
/* @__PURE__ */ jsx20(Text18, { children: " " }),
|
|
4908
|
+
/* @__PURE__ */ jsx20(Text18, { color: "gray", children: timeAgo2(issue.updatedAt).padStart(4) }),
|
|
4909
|
+
target.text ? /* @__PURE__ */ jsxs20(Fragment3, { children: [
|
|
4910
|
+
/* @__PURE__ */ jsx20(Text18, { children: " " }),
|
|
4911
|
+
/* @__PURE__ */ jsx20(Text18, { color: target.color, children: target.text })
|
|
4743
4912
|
] }) : null
|
|
4744
4913
|
] });
|
|
4745
4914
|
}
|
|
@@ -4762,68 +4931,21 @@ var init_issue_row = __esm({
|
|
|
4762
4931
|
}
|
|
4763
4932
|
});
|
|
4764
4933
|
|
|
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
4934
|
// src/board/components/row-renderer.tsx
|
|
4813
|
-
import { Box as
|
|
4814
|
-
import { jsx as
|
|
4935
|
+
import { Box as Box20, Text as Text19 } from "ink";
|
|
4936
|
+
import { jsx as jsx21, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
4815
4937
|
function RowRenderer({ row, selectedId, selfLogin, isMultiSelected }) {
|
|
4816
4938
|
switch (row.type) {
|
|
4817
4939
|
case "sectionHeader": {
|
|
4818
4940
|
const arrow = row.isCollapsed ? "\u25B6" : "\u25BC";
|
|
4819
4941
|
const isSel = selectedId === row.navId;
|
|
4820
|
-
return /* @__PURE__ */
|
|
4821
|
-
/* @__PURE__ */
|
|
4942
|
+
return /* @__PURE__ */ jsxs21(Box20, { children: [
|
|
4943
|
+
/* @__PURE__ */ jsxs21(Text19, { color: isSel ? "cyan" : "white", bold: true, children: [
|
|
4822
4944
|
arrow,
|
|
4823
4945
|
" ",
|
|
4824
4946
|
row.label
|
|
4825
4947
|
] }),
|
|
4826
|
-
/* @__PURE__ */
|
|
4948
|
+
/* @__PURE__ */ jsxs21(Text19, { color: "gray", children: [
|
|
4827
4949
|
" ",
|
|
4828
4950
|
"(",
|
|
4829
4951
|
row.count,
|
|
@@ -4837,26 +4959,26 @@ function RowRenderer({ row, selectedId, selfLogin, isMultiSelected }) {
|
|
|
4837
4959
|
if (row.navId) {
|
|
4838
4960
|
const arrow = row.isCollapsed ? "\u25B6" : "\u25BC";
|
|
4839
4961
|
const isSel = selectedId === row.navId;
|
|
4840
|
-
return /* @__PURE__ */
|
|
4841
|
-
/* @__PURE__ */
|
|
4962
|
+
return /* @__PURE__ */ jsxs21(Box20, { children: [
|
|
4963
|
+
/* @__PURE__ */ jsxs21(Text19, { color: isSel ? "cyan" : "gray", children: [
|
|
4842
4964
|
" ",
|
|
4843
4965
|
arrow,
|
|
4844
4966
|
" ",
|
|
4845
4967
|
row.text
|
|
4846
4968
|
] }),
|
|
4847
|
-
/* @__PURE__ */
|
|
4969
|
+
/* @__PURE__ */ jsxs21(Text19, { color: "gray", children: [
|
|
4848
4970
|
" (",
|
|
4849
4971
|
row.count,
|
|
4850
4972
|
")"
|
|
4851
4973
|
] })
|
|
4852
4974
|
] });
|
|
4853
4975
|
}
|
|
4854
|
-
return /* @__PURE__ */
|
|
4855
|
-
/* @__PURE__ */
|
|
4976
|
+
return /* @__PURE__ */ jsxs21(Box20, { children: [
|
|
4977
|
+
/* @__PURE__ */ jsxs21(Text19, { bold: true, color: "white", children: [
|
|
4856
4978
|
" ",
|
|
4857
4979
|
row.text
|
|
4858
4980
|
] }),
|
|
4859
|
-
row.count != null ? /* @__PURE__ */
|
|
4981
|
+
row.count != null ? /* @__PURE__ */ jsxs21(Text19, { color: "gray", children: [
|
|
4860
4982
|
" (",
|
|
4861
4983
|
row.count,
|
|
4862
4984
|
")"
|
|
@@ -4865,32 +4987,25 @@ function RowRenderer({ row, selectedId, selfLogin, isMultiSelected }) {
|
|
|
4865
4987
|
}
|
|
4866
4988
|
case "issue": {
|
|
4867
4989
|
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 })
|
|
4990
|
+
return /* @__PURE__ */ jsxs21(Box20, { children: [
|
|
4991
|
+
checkbox2 ? /* @__PURE__ */ jsx21(Text19, { color: isMultiSelected ? "cyan" : "gray", children: checkbox2 }) : null,
|
|
4992
|
+
/* @__PURE__ */ jsx21(IssueRow, { issue: row.issue, selfLogin, isSelected: selectedId === row.navId })
|
|
4878
4993
|
] });
|
|
4879
4994
|
}
|
|
4880
4995
|
case "activity": {
|
|
4881
|
-
const ago =
|
|
4882
|
-
return /* @__PURE__ */
|
|
4996
|
+
const ago = new Date(row.event.timestamp).toLocaleTimeString();
|
|
4997
|
+
return /* @__PURE__ */ jsxs21(Text19, { dimColor: true, children: [
|
|
4883
4998
|
" ",
|
|
4884
4999
|
ago,
|
|
4885
5000
|
": ",
|
|
4886
|
-
/* @__PURE__ */
|
|
5001
|
+
/* @__PURE__ */ jsxs21(Text19, { color: "gray", children: [
|
|
4887
5002
|
"@",
|
|
4888
5003
|
row.event.actor
|
|
4889
5004
|
] }),
|
|
4890
5005
|
" ",
|
|
4891
5006
|
row.event.summary,
|
|
4892
5007
|
" ",
|
|
4893
|
-
/* @__PURE__ */
|
|
5008
|
+
/* @__PURE__ */ jsxs21(Text19, { dimColor: true, children: [
|
|
4894
5009
|
"(",
|
|
4895
5010
|
row.event.repoShortName,
|
|
4896
5011
|
")"
|
|
@@ -4898,85 +5013,66 @@ function RowRenderer({ row, selectedId, selfLogin, isMultiSelected }) {
|
|
|
4898
5013
|
] });
|
|
4899
5014
|
}
|
|
4900
5015
|
case "error":
|
|
4901
|
-
return /* @__PURE__ */
|
|
5016
|
+
return /* @__PURE__ */ jsxs21(Text19, { color: "red", children: [
|
|
4902
5017
|
" Error: ",
|
|
4903
5018
|
row.text
|
|
4904
5019
|
] });
|
|
4905
5020
|
case "gap":
|
|
4906
|
-
return /* @__PURE__ */
|
|
5021
|
+
return /* @__PURE__ */ jsx21(Text19, { children: "" });
|
|
4907
5022
|
}
|
|
4908
5023
|
}
|
|
4909
5024
|
var init_row_renderer = __esm({
|
|
4910
5025
|
"src/board/components/row-renderer.tsx"() {
|
|
4911
5026
|
"use strict";
|
|
4912
|
-
init_constants();
|
|
4913
5027
|
init_issue_row();
|
|
4914
|
-
init_task_row();
|
|
4915
5028
|
}
|
|
4916
5029
|
});
|
|
4917
5030
|
|
|
4918
|
-
// src/board/components/
|
|
4919
|
-
import { Box as
|
|
4920
|
-
import { jsx as
|
|
4921
|
-
function
|
|
4922
|
-
|
|
4923
|
-
return /* @__PURE__ */
|
|
4924
|
-
|
|
4925
|
-
|
|
4926
|
-
|
|
4927
|
-
|
|
4928
|
-
|
|
4929
|
-
|
|
4930
|
-
|
|
4931
|
-
|
|
4932
|
-
|
|
4933
|
-
|
|
5031
|
+
// src/board/components/statuses-panel.tsx
|
|
5032
|
+
import { Box as Box21, Text as Text20 } from "ink";
|
|
5033
|
+
import { jsx as jsx22, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
5034
|
+
function StatusesPanel({ groups, selectedIdx, isActive }) {
|
|
5035
|
+
const borderColor = isActive ? "cyan" : "gray";
|
|
5036
|
+
return /* @__PURE__ */ jsxs22(Box21, { borderStyle: "single", borderColor, flexDirection: "column", flexGrow: 1, children: [
|
|
5037
|
+
/* @__PURE__ */ jsx22(Text20, { bold: true, color: isActive ? "cyan" : "white", children: "[2] Statuses" }),
|
|
5038
|
+
groups.length === 0 ? /* @__PURE__ */ jsx22(Text20, { color: "gray", children: " \u2014" }) : groups.map((group, i) => {
|
|
5039
|
+
const isSel = i === selectedIdx;
|
|
5040
|
+
return /* @__PURE__ */ jsxs22(Box21, { children: [
|
|
5041
|
+
/* @__PURE__ */ jsxs22(Text20, { color: isSel ? "cyan" : isActive ? "white" : "gray", bold: isSel, children: [
|
|
5042
|
+
isSel ? "\u25B6 " : " ",
|
|
5043
|
+
group.label
|
|
5044
|
+
] }),
|
|
5045
|
+
/* @__PURE__ */ jsxs22(Text20, { color: "gray", children: [
|
|
5046
|
+
" ",
|
|
5047
|
+
group.count
|
|
5048
|
+
] })
|
|
5049
|
+
] }, group.id);
|
|
5050
|
+
})
|
|
5051
|
+
] });
|
|
4934
5052
|
}
|
|
4935
|
-
var
|
|
4936
|
-
"src/board/components/
|
|
4937
|
-
"use strict";
|
|
4938
|
-
}
|
|
4939
|
-
});
|
|
4940
|
-
|
|
4941
|
-
// src/board/components/tab-bar.tsx
|
|
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);
|
|
4955
|
-
}) });
|
|
4956
|
-
}
|
|
4957
|
-
var init_tab_bar = __esm({
|
|
4958
|
-
"src/board/components/tab-bar.tsx"() {
|
|
5053
|
+
var init_statuses_panel = __esm({
|
|
5054
|
+
"src/board/components/statuses-panel.tsx"() {
|
|
4959
5055
|
"use strict";
|
|
4960
5056
|
}
|
|
4961
5057
|
});
|
|
4962
5058
|
|
|
4963
5059
|
// src/board/components/toast-container.tsx
|
|
4964
5060
|
import { Spinner as Spinner3 } from "@inkjs/ui";
|
|
4965
|
-
import { Box as
|
|
4966
|
-
import { Fragment as Fragment4, jsx as
|
|
5061
|
+
import { Box as Box22, Text as Text21 } from "ink";
|
|
5062
|
+
import { Fragment as Fragment4, jsx as jsx23, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
4967
5063
|
function ToastContainer({ toasts }) {
|
|
4968
5064
|
if (toasts.length === 0) return null;
|
|
4969
|
-
return /* @__PURE__ */
|
|
4970
|
-
/* @__PURE__ */
|
|
4971
|
-
/* @__PURE__ */
|
|
5065
|
+
return /* @__PURE__ */ jsx23(Box22, { flexDirection: "column", children: toasts.map((t) => /* @__PURE__ */ jsx23(Box22, { children: t.type === "loading" ? /* @__PURE__ */ jsxs23(Fragment4, { children: [
|
|
5066
|
+
/* @__PURE__ */ jsx23(Spinner3, { label: "" }),
|
|
5067
|
+
/* @__PURE__ */ jsxs23(Text21, { color: "cyan", children: [
|
|
4972
5068
|
" ",
|
|
4973
5069
|
t.message
|
|
4974
5070
|
] })
|
|
4975
|
-
] }) : /* @__PURE__ */
|
|
5071
|
+
] }) : /* @__PURE__ */ jsxs23(Text21, { color: TYPE_COLORS[t.type], children: [
|
|
4976
5072
|
TYPE_PREFIXES[t.type],
|
|
4977
5073
|
" ",
|
|
4978
5074
|
t.message,
|
|
4979
|
-
t.type === "error" ? /* @__PURE__ */
|
|
5075
|
+
t.type === "error" ? /* @__PURE__ */ jsx23(Text21, { color: "gray", children: t.retry ? " [r]etry [d]ismiss" : " [d]ismiss" }) : null
|
|
4980
5076
|
] }) }, t.id)) });
|
|
4981
5077
|
}
|
|
4982
5078
|
var TYPE_COLORS, TYPE_PREFIXES;
|
|
@@ -5000,9 +5096,9 @@ var init_toast_container = __esm({
|
|
|
5000
5096
|
// src/board/components/dashboard.tsx
|
|
5001
5097
|
import { execFileSync as execFileSync3, spawnSync as spawnSync4 } from "child_process";
|
|
5002
5098
|
import { Spinner as Spinner4 } from "@inkjs/ui";
|
|
5003
|
-
import { Box as
|
|
5004
|
-
import { useCallback as
|
|
5005
|
-
import { Fragment as Fragment5, jsx as
|
|
5099
|
+
import { Box as Box23, Text as Text22, useApp, useStdout } from "ink";
|
|
5100
|
+
import { useCallback as useCallback12, useEffect as useEffect9, useMemo as useMemo3, useRef as useRef13, useState as useState16 } from "react";
|
|
5101
|
+
import { Fragment as Fragment5, jsx as jsx24, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
5006
5102
|
function resolveStatusGroups(statusOptions, configuredGroups) {
|
|
5007
5103
|
if (configuredGroups && configuredGroups.length > 0) {
|
|
5008
5104
|
return configuredGroups.map((entry) => {
|
|
@@ -5040,7 +5136,7 @@ function groupByStatus(issues) {
|
|
|
5040
5136
|
}
|
|
5041
5137
|
return groups;
|
|
5042
5138
|
}
|
|
5043
|
-
function buildBoardTree(repos,
|
|
5139
|
+
function buildBoardTree(repos, activity) {
|
|
5044
5140
|
const sections = repos.map((rd) => {
|
|
5045
5141
|
const sectionId = rd.repo.name;
|
|
5046
5142
|
if (rd.error) {
|
|
@@ -5069,72 +5165,58 @@ function buildBoardTree(repos, tasks, activity) {
|
|
|
5069
5165
|
}
|
|
5070
5166
|
return { repo: rd.repo, sectionId, groups, error: null };
|
|
5071
5167
|
});
|
|
5072
|
-
return { activity, sections
|
|
5168
|
+
return { activity, sections };
|
|
5073
5169
|
}
|
|
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);
|
|
5092
|
-
if (!section) return [];
|
|
5093
|
-
return section.groups.map((g) => ({ id: g.subId, label: g.label, count: g.issues.length }));
|
|
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);
|
|
5170
|
+
function buildNavItemsForRepo(sections, repoName, statusGroupId) {
|
|
5171
|
+
if (!repoName) return [];
|
|
5172
|
+
const section = sections.find((s) => s.sectionId === repoName);
|
|
5104
5173
|
if (!section) return [];
|
|
5105
|
-
const activeGroup = section.groups.find((g) => g.subId ===
|
|
5174
|
+
const activeGroup = section.groups.find((g) => g.subId === statusGroupId) ?? section.groups[0];
|
|
5106
5175
|
if (!activeGroup) return [];
|
|
5107
5176
|
return activeGroup.issues.map((issue) => ({
|
|
5108
5177
|
id: `gh:${section.repo.name}:${issue.number}`,
|
|
5109
|
-
section:
|
|
5178
|
+
section: repoName,
|
|
5110
5179
|
type: "item"
|
|
5111
5180
|
}));
|
|
5112
5181
|
}
|
|
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);
|
|
5182
|
+
function buildFlatRowsForRepo(sections, repoName, statusGroupId) {
|
|
5183
|
+
if (!repoName) {
|
|
5184
|
+
return [
|
|
5185
|
+
{
|
|
5186
|
+
type: "subHeader",
|
|
5187
|
+
key: "select-repo",
|
|
5188
|
+
navId: null,
|
|
5189
|
+
text: "Select a repo in panel [1]"
|
|
5190
|
+
}
|
|
5191
|
+
];
|
|
5192
|
+
}
|
|
5193
|
+
const section = sections.find((s) => s.sectionId === repoName);
|
|
5129
5194
|
if (!section) return [];
|
|
5130
|
-
if (section.error)
|
|
5131
|
-
return [{ type: "error", key: `error:${
|
|
5132
|
-
|
|
5195
|
+
if (section.error) {
|
|
5196
|
+
return [{ type: "error", key: `error:${repoName}`, navId: null, text: section.error }];
|
|
5197
|
+
}
|
|
5198
|
+
if (section.groups.length === 0) {
|
|
5133
5199
|
return [
|
|
5134
|
-
{
|
|
5200
|
+
{
|
|
5201
|
+
type: "subHeader",
|
|
5202
|
+
key: `empty:${repoName}`,
|
|
5203
|
+
navId: null,
|
|
5204
|
+
text: "No open issues"
|
|
5205
|
+
}
|
|
5135
5206
|
];
|
|
5136
|
-
|
|
5207
|
+
}
|
|
5208
|
+
const activeGroup = section.groups.find((g) => g.subId === statusGroupId) ?? section.groups[0];
|
|
5137
5209
|
if (!activeGroup) return [];
|
|
5210
|
+
if (activeGroup.issues.length === 0) {
|
|
5211
|
+
return [
|
|
5212
|
+
{
|
|
5213
|
+
type: "subHeader",
|
|
5214
|
+
key: `empty-group:${statusGroupId}`,
|
|
5215
|
+
navId: null,
|
|
5216
|
+
text: "No issues in this status group"
|
|
5217
|
+
}
|
|
5218
|
+
];
|
|
5219
|
+
}
|
|
5138
5220
|
return activeGroup.issues.map((issue) => ({
|
|
5139
5221
|
type: "issue",
|
|
5140
5222
|
key: `gh:${section.repo.name}:${issue.number}`,
|
|
@@ -5161,13 +5243,13 @@ function findSelectedIssueWithRepo(repos, selectedId) {
|
|
|
5161
5243
|
return null;
|
|
5162
5244
|
}
|
|
5163
5245
|
function RefreshAge({ lastRefresh }) {
|
|
5164
|
-
const [, setTick] =
|
|
5246
|
+
const [, setTick] = useState16(0);
|
|
5165
5247
|
useEffect9(() => {
|
|
5166
5248
|
const id = setInterval(() => setTick((t) => t + 1), 1e4);
|
|
5167
5249
|
return () => clearInterval(id);
|
|
5168
5250
|
}, []);
|
|
5169
5251
|
if (!lastRefresh) return null;
|
|
5170
|
-
return /* @__PURE__ */
|
|
5252
|
+
return /* @__PURE__ */ jsxs24(Text22, { color: refreshAgeColor(lastRefresh), children: [
|
|
5171
5253
|
"Updated ",
|
|
5172
5254
|
timeAgo(lastRefresh)
|
|
5173
5255
|
] });
|
|
@@ -5191,19 +5273,16 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5191
5273
|
clearPendingMutation
|
|
5192
5274
|
} = useData(config2, options, refreshMs);
|
|
5193
5275
|
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
5276
|
const allActivity = useMemo3(() => data?.activity ?? [], [data?.activity]);
|
|
5199
5277
|
const ui = useUIState();
|
|
5200
|
-
const
|
|
5201
|
-
const [
|
|
5202
|
-
const
|
|
5278
|
+
const panelFocus = usePanelFocus(3);
|
|
5279
|
+
const [searchQuery, setSearchQuery] = useState16("");
|
|
5280
|
+
const [mineOnly, setMineOnly] = useState16(false);
|
|
5281
|
+
const handleToggleMine = useCallback12(() => {
|
|
5203
5282
|
setMineOnly((prev) => !prev);
|
|
5204
5283
|
}, []);
|
|
5205
5284
|
const { toasts, toast, handleErrorAction } = useToast();
|
|
5206
|
-
const [logVisible, setLogVisible] =
|
|
5285
|
+
const [logVisible, setLogVisible] = useState16(false);
|
|
5207
5286
|
const { entries: logEntries, pushEntry, undoLast, hasUndoable } = useActionLog(toast, refresh);
|
|
5208
5287
|
useEffect9(() => {
|
|
5209
5288
|
const last = logEntries[logEntries.length - 1];
|
|
@@ -5227,69 +5306,75 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5227
5306
|
const q = searchQuery.toLowerCase();
|
|
5228
5307
|
return filtered.map((rd) => ({ ...rd, issues: rd.issues.filter((i) => i.title.toLowerCase().includes(q)) })).filter((rd) => rd.issues.length > 0);
|
|
5229
5308
|
}, [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]
|
|
5309
|
+
const boardTree = useMemo3(() => buildBoardTree(repos, allActivity), [repos, allActivity]);
|
|
5310
|
+
const [selectedRepoIdx, setSelectedRepoIdx] = useState16(0);
|
|
5311
|
+
const clampedRepoIdx = Math.min(selectedRepoIdx, Math.max(0, boardTree.sections.length - 1));
|
|
5312
|
+
const reposNav = {
|
|
5313
|
+
moveUp: useCallback12(() => setSelectedRepoIdx((i) => Math.max(0, i - 1)), []),
|
|
5314
|
+
moveDown: useCallback12(
|
|
5315
|
+
() => setSelectedRepoIdx((i) => Math.min(Math.max(0, boardTree.sections.length - 1), i + 1)),
|
|
5316
|
+
[boardTree.sections.length]
|
|
5317
|
+
)
|
|
5318
|
+
};
|
|
5319
|
+
const [selectedStatusIdx, setSelectedStatusIdx] = useState16(0);
|
|
5320
|
+
const selectedSection = boardTree.sections[clampedRepoIdx] ?? null;
|
|
5321
|
+
const clampedStatusIdx = Math.min(
|
|
5322
|
+
selectedStatusIdx,
|
|
5323
|
+
Math.max(0, (selectedSection?.groups.length ?? 1) - 1)
|
|
5262
5324
|
);
|
|
5263
|
-
const
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
|
|
5325
|
+
const statusesNav = {
|
|
5326
|
+
moveUp: useCallback12(() => setSelectedStatusIdx((i) => Math.max(0, i - 1)), []),
|
|
5327
|
+
moveDown: useCallback12(
|
|
5328
|
+
() => setSelectedStatusIdx(
|
|
5329
|
+
(i) => Math.min(Math.max(0, (selectedSection?.groups.length ?? 1) - 1), i + 1)
|
|
5330
|
+
),
|
|
5331
|
+
[selectedSection?.groups.length]
|
|
5332
|
+
)
|
|
5333
|
+
};
|
|
5334
|
+
const [activitySelectedIdx, setActivitySelectedIdx] = useState16(0);
|
|
5335
|
+
const clampedActivityIdx = Math.min(
|
|
5336
|
+
activitySelectedIdx,
|
|
5337
|
+
Math.max(0, boardTree.activity.length - 1)
|
|
5267
5338
|
);
|
|
5268
|
-
const
|
|
5269
|
-
|
|
5270
|
-
|
|
5271
|
-
|
|
5272
|
-
|
|
5273
|
-
|
|
5274
|
-
|
|
5275
|
-
|
|
5276
|
-
const
|
|
5277
|
-
|
|
5278
|
-
|
|
5279
|
-
|
|
5339
|
+
const activityNav = {
|
|
5340
|
+
moveUp: useCallback12(() => setActivitySelectedIdx((i) => Math.max(0, i - 1)), []),
|
|
5341
|
+
moveDown: useCallback12(
|
|
5342
|
+
() => setActivitySelectedIdx((i) => Math.min(Math.max(0, boardTree.activity.length - 1), i + 1)),
|
|
5343
|
+
[boardTree.activity.length]
|
|
5344
|
+
)
|
|
5345
|
+
};
|
|
5346
|
+
const selectedRepoName = selectedSection?.sectionId ?? null;
|
|
5347
|
+
const selectedStatusGroup = selectedSection?.groups[clampedStatusIdx] ?? null;
|
|
5348
|
+
const selectedStatusGroupId = selectedStatusGroup?.subId ?? null;
|
|
5349
|
+
const onRepoEnter = useCallback12(() => {
|
|
5350
|
+
setSelectedStatusIdx(0);
|
|
5351
|
+
panelFocus.focusPanel(3);
|
|
5352
|
+
}, [panelFocus]);
|
|
5353
|
+
const onStatusEnter = useCallback12(() => {
|
|
5354
|
+
panelFocus.focusPanel(3);
|
|
5355
|
+
}, [panelFocus]);
|
|
5356
|
+
const onActivityEnter = useCallback12(() => {
|
|
5357
|
+
const event = boardTree.activity[clampedActivityIdx];
|
|
5358
|
+
if (!event) return;
|
|
5359
|
+
const repoIdx = boardTree.sections.findIndex(
|
|
5360
|
+
(s) => s.repo.shortName === event.repoShortName || s.sectionId.endsWith(`/${event.repoShortName}`)
|
|
5280
5361
|
);
|
|
5281
|
-
|
|
5362
|
+
if (repoIdx >= 0) {
|
|
5363
|
+
setSelectedRepoIdx(repoIdx);
|
|
5364
|
+
setSelectedStatusIdx(0);
|
|
5365
|
+
panelFocus.focusPanel(3);
|
|
5366
|
+
}
|
|
5367
|
+
}, [boardTree, clampedActivityIdx, panelFocus]);
|
|
5282
5368
|
const navItems = useMemo3(
|
|
5283
|
-
() =>
|
|
5284
|
-
[
|
|
5369
|
+
() => buildNavItemsForRepo(boardTree.sections, selectedRepoName, selectedStatusGroupId),
|
|
5370
|
+
[boardTree.sections, selectedRepoName, selectedStatusGroupId]
|
|
5285
5371
|
);
|
|
5286
5372
|
const nav = useNavigation(navItems);
|
|
5287
|
-
const getRepoForId =
|
|
5373
|
+
const getRepoForId = useCallback12((id) => {
|
|
5288
5374
|
if (id.startsWith("gh:")) {
|
|
5289
5375
|
const parts = id.split(":");
|
|
5290
5376
|
return parts.length >= 3 ? `${parts[1]}` : null;
|
|
5291
5377
|
}
|
|
5292
|
-
if (id.startsWith("tt:")) return "ticktick";
|
|
5293
5378
|
return null;
|
|
5294
5379
|
}, []);
|
|
5295
5380
|
const multiSelect = useMultiSelect(getRepoForId);
|
|
@@ -5313,8 +5398,8 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5313
5398
|
const pendingPickRef = useRef13(null);
|
|
5314
5399
|
const labelCacheRef = useRef13({});
|
|
5315
5400
|
const commentCacheRef = useRef13({});
|
|
5316
|
-
const [commentTick, setCommentTick] =
|
|
5317
|
-
const handleFetchComments =
|
|
5401
|
+
const [commentTick, setCommentTick] = useState16(0);
|
|
5402
|
+
const handleFetchComments = useCallback12((repo, issueNumber) => {
|
|
5318
5403
|
const key = `${repo}:${issueNumber}`;
|
|
5319
5404
|
if (commentCacheRef.current[key] !== void 0) return;
|
|
5320
5405
|
commentCacheRef.current[key] = "loading";
|
|
@@ -5327,7 +5412,7 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5327
5412
|
setCommentTick((t) => t + 1);
|
|
5328
5413
|
});
|
|
5329
5414
|
}, []);
|
|
5330
|
-
const handleCreateIssueWithPrompt =
|
|
5415
|
+
const handleCreateIssueWithPrompt = useCallback12(
|
|
5331
5416
|
(repo, title, body, dueDate, labels) => {
|
|
5332
5417
|
actions.handleCreateIssue(repo, title, body, dueDate, labels).then((result) => {
|
|
5333
5418
|
if (result) {
|
|
@@ -5338,7 +5423,7 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5338
5423
|
},
|
|
5339
5424
|
[actions, ui]
|
|
5340
5425
|
);
|
|
5341
|
-
const handleConfirmPick =
|
|
5426
|
+
const handleConfirmPick = useCallback12(() => {
|
|
5342
5427
|
const pending = pendingPickRef.current;
|
|
5343
5428
|
pendingPickRef.current = null;
|
|
5344
5429
|
ui.exitOverlay();
|
|
@@ -5356,12 +5441,12 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5356
5441
|
})
|
|
5357
5442
|
);
|
|
5358
5443
|
}, [config2, toast, refresh, ui]);
|
|
5359
|
-
const handleCancelPick =
|
|
5444
|
+
const handleCancelPick = useCallback12(() => {
|
|
5360
5445
|
pendingPickRef.current = null;
|
|
5361
5446
|
ui.exitOverlay();
|
|
5362
5447
|
}, [ui]);
|
|
5363
|
-
const [focusLabel, setFocusLabel] =
|
|
5364
|
-
const handleEnterFocus =
|
|
5448
|
+
const [focusLabel, setFocusLabel] = useState16(null);
|
|
5449
|
+
const handleEnterFocus = useCallback12(() => {
|
|
5365
5450
|
const id = nav.selectedId;
|
|
5366
5451
|
if (!id || isHeaderId(id)) return;
|
|
5367
5452
|
let label = "";
|
|
@@ -5371,20 +5456,16 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5371
5456
|
const rc = config2.repos.find((r) => r.name === found.repoName);
|
|
5372
5457
|
label = `${rc?.shortName ?? found.repoName}#${found.issue.number} \u2014 ${found.issue.title}`;
|
|
5373
5458
|
}
|
|
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
5459
|
}
|
|
5379
5460
|
if (!label) return;
|
|
5380
5461
|
setFocusLabel(label);
|
|
5381
5462
|
ui.enterFocus();
|
|
5382
|
-
}, [nav.selectedId, repos,
|
|
5383
|
-
const handleFocusExit =
|
|
5463
|
+
}, [nav.selectedId, repos, config2.repos, ui]);
|
|
5464
|
+
const handleFocusExit = useCallback12(() => {
|
|
5384
5465
|
setFocusLabel(null);
|
|
5385
5466
|
ui.exitToNormal();
|
|
5386
5467
|
}, [ui]);
|
|
5387
|
-
const handleFocusEndAction =
|
|
5468
|
+
const handleFocusEndAction = useCallback12(
|
|
5388
5469
|
(action) => {
|
|
5389
5470
|
switch (action) {
|
|
5390
5471
|
case "restart":
|
|
@@ -5410,9 +5491,9 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5410
5491
|
},
|
|
5411
5492
|
[toast, ui]
|
|
5412
5493
|
);
|
|
5413
|
-
const [focusKey, setFocusKey] =
|
|
5494
|
+
const [focusKey, setFocusKey] = useState16(0);
|
|
5414
5495
|
const { stdout } = useStdout();
|
|
5415
|
-
const [termSize, setTermSize] =
|
|
5496
|
+
const [termSize, setTermSize] = useState16({
|
|
5416
5497
|
cols: stdout?.columns ?? 80,
|
|
5417
5498
|
rows: stdout?.rows ?? 24
|
|
5418
5499
|
});
|
|
@@ -5424,24 +5505,27 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5424
5505
|
stdout.off("resize", onResize);
|
|
5425
5506
|
};
|
|
5426
5507
|
}, [stdout]);
|
|
5427
|
-
const
|
|
5428
|
-
const detailPanelWidth =
|
|
5508
|
+
const layoutMode = getLayoutMode(termSize.cols);
|
|
5509
|
+
const detailPanelWidth = layoutMode === "wide" ? getDetailWidth(termSize.cols) : Math.floor(termSize.cols * 0.35);
|
|
5510
|
+
const showDetailPanel = layoutMode === "wide";
|
|
5429
5511
|
const overlayBarRows = ui.state.mode === "search" || ui.state.mode === "overlay:comment" ? 1 : 0;
|
|
5430
5512
|
const toastRows = toasts.length;
|
|
5431
5513
|
const logPaneRows = logVisible ? 4 : 0;
|
|
5432
|
-
const
|
|
5433
|
-
|
|
5434
|
-
|
|
5435
|
-
termSize.rows - chromeRows - overlayBarRows - toastRows - logPaneRows
|
|
5514
|
+
const totalPanelHeight = Math.max(
|
|
5515
|
+
8,
|
|
5516
|
+
termSize.rows - CHROME_ROWS - overlayBarRows - toastRows - logPaneRows
|
|
5436
5517
|
);
|
|
5518
|
+
const issuesPanelHeight = Math.max(5, totalPanelHeight - ACTIVITY_HEIGHT);
|
|
5437
5519
|
const flatRows = useMemo3(
|
|
5438
|
-
() =>
|
|
5439
|
-
[
|
|
5520
|
+
() => buildFlatRowsForRepo(boardTree.sections, selectedRepoName, selectedStatusGroupId),
|
|
5521
|
+
[boardTree.sections, selectedRepoName, selectedStatusGroupId]
|
|
5440
5522
|
);
|
|
5441
5523
|
const scrollRef = useRef13(0);
|
|
5442
|
-
const
|
|
5443
|
-
|
|
5444
|
-
|
|
5524
|
+
const prevRepoRef = useRef13(null);
|
|
5525
|
+
const prevStatusRef = useRef13(null);
|
|
5526
|
+
if (selectedRepoName !== prevRepoRef.current || selectedStatusGroupId !== prevStatusRef.current) {
|
|
5527
|
+
prevRepoRef.current = selectedRepoName;
|
|
5528
|
+
prevStatusRef.current = selectedStatusGroupId;
|
|
5445
5529
|
scrollRef.current = 0;
|
|
5446
5530
|
}
|
|
5447
5531
|
const selectedRowIdx = useMemo3(
|
|
@@ -5451,35 +5535,29 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5451
5535
|
if (selectedRowIdx >= 0) {
|
|
5452
5536
|
if (selectedRowIdx < scrollRef.current) {
|
|
5453
5537
|
scrollRef.current = selectedRowIdx;
|
|
5454
|
-
} else if (selectedRowIdx >= scrollRef.current +
|
|
5455
|
-
scrollRef.current = selectedRowIdx -
|
|
5538
|
+
} else if (selectedRowIdx >= scrollRef.current + issuesPanelHeight) {
|
|
5539
|
+
scrollRef.current = selectedRowIdx - issuesPanelHeight + 1;
|
|
5456
5540
|
}
|
|
5457
5541
|
}
|
|
5458
|
-
const maxOffset = Math.max(0, flatRows.length -
|
|
5542
|
+
const maxOffset = Math.max(0, flatRows.length - issuesPanelHeight);
|
|
5459
5543
|
scrollRef.current = Math.max(0, Math.min(scrollRef.current, maxOffset));
|
|
5460
|
-
const visibleRows = flatRows.slice(scrollRef.current, scrollRef.current +
|
|
5544
|
+
const visibleRows = flatRows.slice(scrollRef.current, scrollRef.current + issuesPanelHeight);
|
|
5461
5545
|
const hasMoreAbove = scrollRef.current > 0;
|
|
5462
|
-
const hasMoreBelow = scrollRef.current +
|
|
5546
|
+
const hasMoreBelow = scrollRef.current + issuesPanelHeight < flatRows.length;
|
|
5463
5547
|
const aboveCount = scrollRef.current;
|
|
5464
|
-
const belowCount = flatRows.length - scrollRef.current -
|
|
5548
|
+
const belowCount = flatRows.length - scrollRef.current - issuesPanelHeight;
|
|
5465
5549
|
const selectedItem = useMemo3(() => {
|
|
5466
5550
|
const id = nav.selectedId;
|
|
5467
|
-
if (!id || isHeaderId(id)) return { issue: null,
|
|
5551
|
+
if (!id || isHeaderId(id)) return { issue: null, repoName: null };
|
|
5468
5552
|
if (id.startsWith("gh:")) {
|
|
5469
5553
|
for (const rd of repos) {
|
|
5470
5554
|
for (const issue of rd.issues) {
|
|
5471
|
-
if (`gh:${rd.repo.name}:${issue.number}` === id)
|
|
5472
|
-
return { issue, task: null, repoName: rd.repo.name };
|
|
5555
|
+
if (`gh:${rd.repo.name}:${issue.number}` === id) return { issue, repoName: rd.repo.name };
|
|
5473
5556
|
}
|
|
5474
5557
|
}
|
|
5475
5558
|
}
|
|
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]);
|
|
5559
|
+
return { issue: null, repoName: null };
|
|
5560
|
+
}, [nav.selectedId, repos]);
|
|
5483
5561
|
const currentCommentsState = useMemo3(() => {
|
|
5484
5562
|
if (!(selectedItem.issue && selectedItem.repoName)) return null;
|
|
5485
5563
|
return commentCacheRef.current[`${selectedItem.repoName}:${selectedItem.issue.number}`] ?? null;
|
|
@@ -5490,20 +5568,20 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5490
5568
|
}, [selectedItem.repoName, config2.repos]);
|
|
5491
5569
|
const selectedRepoStatusOptions = useMemo3(() => {
|
|
5492
5570
|
const repoName = multiSelect.count > 0 ? multiSelect.constrainedRepo : selectedItem.repoName;
|
|
5493
|
-
if (!repoName
|
|
5571
|
+
if (!repoName) return [];
|
|
5494
5572
|
const rd = repos.find((r) => r.repo.name === repoName);
|
|
5495
5573
|
return rd?.statusOptions ?? [];
|
|
5496
5574
|
}, [selectedItem.repoName, repos, multiSelect.count, multiSelect.constrainedRepo]);
|
|
5497
|
-
const handleOpen =
|
|
5575
|
+
const handleOpen = useCallback12(() => {
|
|
5498
5576
|
const found = findSelectedIssueWithRepo(repos, nav.selectedId);
|
|
5499
5577
|
if (found) openInBrowser(found.issue.url);
|
|
5500
5578
|
}, [repos, nav.selectedId]);
|
|
5501
|
-
const handleSlack =
|
|
5579
|
+
const handleSlack = useCallback12(() => {
|
|
5502
5580
|
const found = findSelectedIssueWithRepo(repos, nav.selectedId);
|
|
5503
5581
|
if (!found?.issue.slackThreadUrl) return;
|
|
5504
5582
|
openInBrowser(found.issue.slackThreadUrl);
|
|
5505
5583
|
}, [repos, nav.selectedId]);
|
|
5506
|
-
const handleCopyLink =
|
|
5584
|
+
const handleCopyLink = useCallback12(() => {
|
|
5507
5585
|
const found = findSelectedIssueWithRepo(repos, nav.selectedId);
|
|
5508
5586
|
if (!found) return;
|
|
5509
5587
|
const rc = config2.repos.find((r) => r.name === found.repoName);
|
|
@@ -5529,17 +5607,12 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5529
5607
|
}
|
|
5530
5608
|
}, [repos, nav.selectedId, config2.repos, toast]);
|
|
5531
5609
|
const multiSelectType = useMemo3(() => {
|
|
5532
|
-
let hasGh = false;
|
|
5533
|
-
let hasTt = false;
|
|
5534
5610
|
for (const id of multiSelect.selected) {
|
|
5535
|
-
if (id.startsWith("
|
|
5536
|
-
if (id.startsWith("tt:")) hasTt = true;
|
|
5611
|
+
if (id.startsWith("tt:")) return "ticktick";
|
|
5537
5612
|
}
|
|
5538
|
-
if (hasGh && hasTt) return "mixed";
|
|
5539
|
-
if (hasTt) return "ticktick";
|
|
5540
5613
|
return "github";
|
|
5541
5614
|
}, [multiSelect.selected]);
|
|
5542
|
-
const handleBulkAction =
|
|
5615
|
+
const handleBulkAction = useCallback12(
|
|
5543
5616
|
(action) => {
|
|
5544
5617
|
const ids = multiSelect.selected;
|
|
5545
5618
|
switch (action.type) {
|
|
@@ -5572,10 +5645,9 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5572
5645
|
case "statusChange":
|
|
5573
5646
|
ui.enterStatus();
|
|
5574
5647
|
return;
|
|
5575
|
-
// status picker will call handleBulkStatusSelect on select
|
|
5576
5648
|
case "complete":
|
|
5577
5649
|
case "delete":
|
|
5578
|
-
toast.info(`Bulk ${action.type} not yet implemented
|
|
5650
|
+
toast.info(`Bulk ${action.type} not yet implemented`);
|
|
5579
5651
|
ui.exitOverlay();
|
|
5580
5652
|
multiSelect.clear();
|
|
5581
5653
|
return;
|
|
@@ -5583,7 +5655,7 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5583
5655
|
},
|
|
5584
5656
|
[multiSelect, actions, ui, toast]
|
|
5585
5657
|
);
|
|
5586
|
-
const handleBulkStatusSelect =
|
|
5658
|
+
const handleBulkStatusSelect = useCallback12(
|
|
5587
5659
|
(optionId) => {
|
|
5588
5660
|
const ids = multiSelect.selected;
|
|
5589
5661
|
ui.exitOverlay();
|
|
@@ -5599,30 +5671,28 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5599
5671
|
},
|
|
5600
5672
|
[multiSelect, actions, ui]
|
|
5601
5673
|
);
|
|
5602
|
-
const handleFuzzySelect =
|
|
5674
|
+
const handleFuzzySelect = useCallback12(
|
|
5603
5675
|
(navId) => {
|
|
5604
5676
|
nav.select(navId);
|
|
5605
5677
|
if (navId.startsWith("gh:")) {
|
|
5606
5678
|
const parts = navId.split(":");
|
|
5607
5679
|
const repoName = parts[1];
|
|
5608
5680
|
if (parts.length >= 3 && repoName) {
|
|
5609
|
-
|
|
5610
|
-
|
|
5611
|
-
|
|
5612
|
-
|
|
5613
|
-
|
|
5614
|
-
|
|
5615
|
-
|
|
5681
|
+
const repoIdx = boardTree.sections.findIndex((s) => s.sectionId === repoName);
|
|
5682
|
+
if (repoIdx >= 0) {
|
|
5683
|
+
setSelectedRepoIdx(repoIdx);
|
|
5684
|
+
const section = boardTree.sections[repoIdx];
|
|
5685
|
+
const issueNum = parts[2] ? Number(parts[2]) : null;
|
|
5686
|
+
const groupIdx = section?.groups.findIndex((g) => g.issues.some((iss) => iss.number === issueNum)) ?? -1;
|
|
5687
|
+
setSelectedStatusIdx(Math.max(0, groupIdx));
|
|
5688
|
+
}
|
|
5616
5689
|
}
|
|
5617
|
-
} else if (navId.startsWith("tt:")) {
|
|
5618
|
-
setActiveTabId("ticktick");
|
|
5619
|
-
setActiveStatusId(null);
|
|
5620
5690
|
}
|
|
5621
5691
|
ui.exitToNormal();
|
|
5622
5692
|
},
|
|
5623
5693
|
[nav, ui, boardTree]
|
|
5624
5694
|
);
|
|
5625
|
-
const onSearchEscape =
|
|
5695
|
+
const onSearchEscape = useCallback12(() => {
|
|
5626
5696
|
ui.exitOverlay();
|
|
5627
5697
|
setSearchQuery("");
|
|
5628
5698
|
}, [ui]);
|
|
@@ -5652,11 +5722,16 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5652
5722
|
handleToggleLog: () => setLogVisible((v) => !v)
|
|
5653
5723
|
},
|
|
5654
5724
|
onSearchEscape,
|
|
5655
|
-
|
|
5656
|
-
|
|
5725
|
+
panelFocus,
|
|
5726
|
+
reposNav,
|
|
5727
|
+
statusesNav,
|
|
5728
|
+
activityNav,
|
|
5729
|
+
onRepoEnter,
|
|
5730
|
+
onStatusEnter,
|
|
5731
|
+
onActivityEnter
|
|
5657
5732
|
});
|
|
5658
5733
|
if (status === "loading" && !data) {
|
|
5659
|
-
return /* @__PURE__ */
|
|
5734
|
+
return /* @__PURE__ */ jsx24(Box23, { flexDirection: "column", padding: 1, children: /* @__PURE__ */ jsx24(Spinner4, { label: "Loading dashboard..." }) });
|
|
5660
5735
|
}
|
|
5661
5736
|
const now = data?.fetchedAt ?? /* @__PURE__ */ new Date();
|
|
5662
5737
|
const dateStr = now.toLocaleDateString("en-US", {
|
|
@@ -5664,36 +5739,122 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5664
5739
|
day: "numeric",
|
|
5665
5740
|
year: "numeric"
|
|
5666
5741
|
});
|
|
5667
|
-
|
|
5668
|
-
|
|
5669
|
-
|
|
5670
|
-
|
|
5742
|
+
const reposData = boardTree.sections.map(({ repo, groups }) => ({
|
|
5743
|
+
name: repo.name,
|
|
5744
|
+
openCount: groups.reduce((s, g) => s + g.issues.length, 0)
|
|
5745
|
+
}));
|
|
5746
|
+
const statusesData = (selectedSection?.groups ?? []).map(({ label, subId, issues }) => ({
|
|
5747
|
+
id: subId,
|
|
5748
|
+
label,
|
|
5749
|
+
count: issues.length
|
|
5750
|
+
}));
|
|
5751
|
+
const reposPanel = /* @__PURE__ */ jsx24(
|
|
5752
|
+
ReposPanel,
|
|
5753
|
+
{
|
|
5754
|
+
repos: reposData,
|
|
5755
|
+
selectedIdx: clampedRepoIdx,
|
|
5756
|
+
isActive: panelFocus.activePanelId === 1
|
|
5757
|
+
}
|
|
5758
|
+
);
|
|
5759
|
+
const statusesPanel = /* @__PURE__ */ jsx24(
|
|
5760
|
+
StatusesPanel,
|
|
5761
|
+
{
|
|
5762
|
+
groups: statusesData,
|
|
5763
|
+
selectedIdx: clampedStatusIdx,
|
|
5764
|
+
isActive: panelFocus.activePanelId === 2
|
|
5765
|
+
}
|
|
5766
|
+
);
|
|
5767
|
+
const issuesBorderColor = panelFocus.activePanelId === 3 ? "cyan" : "gray";
|
|
5768
|
+
const issuesPanel = /* @__PURE__ */ jsxs24(
|
|
5769
|
+
Box23,
|
|
5770
|
+
{
|
|
5771
|
+
borderStyle: "single",
|
|
5772
|
+
borderColor: issuesBorderColor,
|
|
5773
|
+
flexDirection: "column",
|
|
5774
|
+
flexGrow: 1,
|
|
5775
|
+
overflow: "hidden",
|
|
5776
|
+
children: [
|
|
5777
|
+
/* @__PURE__ */ jsxs24(Text22, { bold: true, color: panelFocus.activePanelId === 3 ? "cyan" : "white", children: [
|
|
5778
|
+
"[3] Issues",
|
|
5779
|
+
selectedSection ? ` \u2014 ${selectedSection.repo.shortName}` : "",
|
|
5780
|
+
selectedStatusGroup ? ` / ${selectedStatusGroup.label}` : ""
|
|
5781
|
+
] }),
|
|
5782
|
+
hasMoreAbove ? /* @__PURE__ */ jsxs24(Text22, { color: "gray", dimColor: true, children: [
|
|
5783
|
+
" ",
|
|
5784
|
+
"\u25B2",
|
|
5785
|
+
" ",
|
|
5786
|
+
aboveCount,
|
|
5787
|
+
" more above"
|
|
5788
|
+
] }) : null,
|
|
5789
|
+
visibleRows.map((row) => /* @__PURE__ */ jsx24(
|
|
5790
|
+
RowRenderer,
|
|
5791
|
+
{
|
|
5792
|
+
row,
|
|
5793
|
+
selectedId: nav.selectedId,
|
|
5794
|
+
selfLogin: config2.board.assignee,
|
|
5795
|
+
isMultiSelected: ui.state.mode === "multiSelect" && row.navId ? multiSelect.isSelected(row.navId) : void 0
|
|
5796
|
+
},
|
|
5797
|
+
row.key
|
|
5798
|
+
)),
|
|
5799
|
+
hasMoreBelow ? /* @__PURE__ */ jsxs24(Text22, { color: "gray", dimColor: true, children: [
|
|
5800
|
+
" ",
|
|
5801
|
+
"\u25BC",
|
|
5802
|
+
" ",
|
|
5803
|
+
belowCount,
|
|
5804
|
+
" more below"
|
|
5805
|
+
] }) : null
|
|
5806
|
+
]
|
|
5807
|
+
}
|
|
5808
|
+
);
|
|
5809
|
+
const detailPanel = showDetailPanel ? /* @__PURE__ */ jsx24(
|
|
5810
|
+
DetailPanel,
|
|
5811
|
+
{
|
|
5812
|
+
issue: selectedItem.issue,
|
|
5813
|
+
width: detailPanelWidth,
|
|
5814
|
+
isActive: panelFocus.activePanelId === 0,
|
|
5815
|
+
issueRepo: selectedItem.repoName,
|
|
5816
|
+
fetchComments: handleFetchComments,
|
|
5817
|
+
commentsState: currentCommentsState
|
|
5818
|
+
}
|
|
5819
|
+
) : null;
|
|
5820
|
+
const activityPanel = /* @__PURE__ */ jsx24(
|
|
5821
|
+
ActivityPanel,
|
|
5822
|
+
{
|
|
5823
|
+
events: boardTree.activity,
|
|
5824
|
+
selectedIdx: clampedActivityIdx,
|
|
5825
|
+
isActive: panelFocus.activePanelId === 4,
|
|
5826
|
+
height: ACTIVITY_HEIGHT
|
|
5827
|
+
}
|
|
5828
|
+
);
|
|
5829
|
+
return /* @__PURE__ */ jsxs24(Box23, { flexDirection: "column", paddingX: 1, children: [
|
|
5830
|
+
/* @__PURE__ */ jsxs24(Box23, { children: [
|
|
5831
|
+
/* @__PURE__ */ jsx24(Text22, { color: "cyan", bold: true, children: "HOG BOARD" }),
|
|
5832
|
+
activeProfile ? /* @__PURE__ */ jsxs24(Text22, { color: "yellow", children: [
|
|
5671
5833
|
" [",
|
|
5672
5834
|
activeProfile,
|
|
5673
5835
|
"]"
|
|
5674
5836
|
] }) : null,
|
|
5675
|
-
/* @__PURE__ */
|
|
5837
|
+
/* @__PURE__ */ jsxs24(Text22, { color: "gray", children: [
|
|
5676
5838
|
" ",
|
|
5677
5839
|
"\u2014",
|
|
5678
5840
|
" ",
|
|
5679
5841
|
dateStr
|
|
5680
5842
|
] }),
|
|
5681
|
-
/* @__PURE__ */
|
|
5682
|
-
isRefreshing ? /* @__PURE__ */
|
|
5683
|
-
/* @__PURE__ */
|
|
5684
|
-
/* @__PURE__ */
|
|
5685
|
-
] }) : /* @__PURE__ */
|
|
5686
|
-
/* @__PURE__ */
|
|
5687
|
-
consecutiveFailures > 0 ? /* @__PURE__ */
|
|
5843
|
+
/* @__PURE__ */ jsx24(Text22, { children: " " }),
|
|
5844
|
+
isRefreshing ? /* @__PURE__ */ jsxs24(Fragment5, { children: [
|
|
5845
|
+
/* @__PURE__ */ jsx24(Spinner4, { label: "" }),
|
|
5846
|
+
/* @__PURE__ */ jsx24(Text22, { color: "cyan", children: " Refreshing..." })
|
|
5847
|
+
] }) : /* @__PURE__ */ jsxs24(Fragment5, { children: [
|
|
5848
|
+
/* @__PURE__ */ jsx24(RefreshAge, { lastRefresh }),
|
|
5849
|
+
consecutiveFailures > 0 ? /* @__PURE__ */ jsx24(Text22, { color: "red", children: " (!)" }) : null
|
|
5688
5850
|
] }),
|
|
5689
|
-
autoRefreshPaused ? /* @__PURE__ */
|
|
5851
|
+
autoRefreshPaused ? /* @__PURE__ */ jsx24(Text22, { color: "yellow", children: " Auto-refresh paused \u2014 press r to retry" }) : null
|
|
5690
5852
|
] }),
|
|
5691
|
-
error ? /* @__PURE__ */
|
|
5853
|
+
error ? /* @__PURE__ */ jsxs24(Text22, { color: "red", children: [
|
|
5692
5854
|
"Error: ",
|
|
5693
5855
|
error
|
|
5694
5856
|
] }) : null,
|
|
5695
|
-
/* @__PURE__ */
|
|
5696
|
-
/* @__PURE__ */ jsx23(
|
|
5857
|
+
/* @__PURE__ */ jsx24(
|
|
5697
5858
|
OverlayRenderer,
|
|
5698
5859
|
{
|
|
5699
5860
|
uiState: ui.state,
|
|
@@ -5735,61 +5896,25 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5735
5896
|
onPushEntry: pushEntry
|
|
5736
5897
|
}
|
|
5737
5898
|
),
|
|
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(
|
|
5899
|
+
!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__ */ jsx24(
|
|
5900
|
+
PanelLayout,
|
|
5901
|
+
{
|
|
5902
|
+
cols: termSize.cols,
|
|
5903
|
+
issuesPanelHeight,
|
|
5904
|
+
reposPanel,
|
|
5905
|
+
statusesPanel,
|
|
5906
|
+
issuesPanel,
|
|
5907
|
+
detailPanel,
|
|
5908
|
+
activityPanel
|
|
5909
|
+
}
|
|
5910
|
+
) : null,
|
|
5911
|
+
/* @__PURE__ */ jsx24(ToastContainer, { toasts }),
|
|
5912
|
+
logVisible ? /* @__PURE__ */ jsx24(ActionLog, { entries: logEntries }) : null,
|
|
5913
|
+
/* @__PURE__ */ jsx24(
|
|
5790
5914
|
HintBar,
|
|
5791
5915
|
{
|
|
5792
5916
|
uiMode: ui.state.mode,
|
|
5917
|
+
activePanelId: panelFocus.activePanelId,
|
|
5793
5918
|
multiSelectCount: multiSelect.count,
|
|
5794
5919
|
searchQuery,
|
|
5795
5920
|
mineOnly,
|
|
@@ -5798,7 +5923,7 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5798
5923
|
)
|
|
5799
5924
|
] });
|
|
5800
5925
|
}
|
|
5801
|
-
var PRIORITY_RANK,
|
|
5926
|
+
var PRIORITY_RANK, CHROME_ROWS;
|
|
5802
5927
|
var init_dashboard = __esm({
|
|
5803
5928
|
"src/board/components/dashboard.tsx"() {
|
|
5804
5929
|
"use strict";
|
|
@@ -5811,15 +5936,18 @@ var init_dashboard = __esm({
|
|
|
5811
5936
|
init_use_keyboard();
|
|
5812
5937
|
init_use_multi_select();
|
|
5813
5938
|
init_use_navigation();
|
|
5939
|
+
init_use_panel_focus();
|
|
5814
5940
|
init_use_toast();
|
|
5815
5941
|
init_use_ui_state();
|
|
5816
5942
|
init_action_log();
|
|
5943
|
+
init_activity_panel();
|
|
5817
5944
|
init_detail_panel();
|
|
5818
5945
|
init_hint_bar();
|
|
5819
5946
|
init_overlay_renderer();
|
|
5947
|
+
init_panel_layout();
|
|
5948
|
+
init_repos_panel();
|
|
5820
5949
|
init_row_renderer();
|
|
5821
|
-
|
|
5822
|
-
init_tab_bar();
|
|
5950
|
+
init_statuses_panel();
|
|
5823
5951
|
init_toast_container();
|
|
5824
5952
|
PRIORITY_RANK = {
|
|
5825
5953
|
"priority:critical": 0,
|
|
@@ -5827,8 +5955,7 @@ var init_dashboard = __esm({
|
|
|
5827
5955
|
"priority:medium": 2,
|
|
5828
5956
|
"priority:low": 3
|
|
5829
5957
|
};
|
|
5830
|
-
|
|
5831
|
-
CHROME_ROWS_OTHER = 5;
|
|
5958
|
+
CHROME_ROWS = 3;
|
|
5832
5959
|
}
|
|
5833
5960
|
});
|
|
5834
5961
|
|
|
@@ -5838,10 +5965,10 @@ __export(live_exports, {
|
|
|
5838
5965
|
runLiveDashboard: () => runLiveDashboard
|
|
5839
5966
|
});
|
|
5840
5967
|
import { render } from "ink";
|
|
5841
|
-
import { jsx as
|
|
5968
|
+
import { jsx as jsx25 } from "react/jsx-runtime";
|
|
5842
5969
|
async function runLiveDashboard(config2, options, activeProfile) {
|
|
5843
5970
|
const instance = render(
|
|
5844
|
-
/* @__PURE__ */
|
|
5971
|
+
/* @__PURE__ */ jsx25(Dashboard, { config: config2, options, activeProfile: activeProfile ?? null })
|
|
5845
5972
|
);
|
|
5846
5973
|
setInkInstance(instance);
|
|
5847
5974
|
await instance.waitUntilExit();
|
|
@@ -5868,7 +5995,7 @@ function extractSlackUrl(body) {
|
|
|
5868
5995
|
const match = body.match(SLACK_URL_RE2);
|
|
5869
5996
|
return match?.[0];
|
|
5870
5997
|
}
|
|
5871
|
-
function fetchRecentActivity(repoName,
|
|
5998
|
+
function fetchRecentActivity(repoName, shortName2) {
|
|
5872
5999
|
try {
|
|
5873
6000
|
const output = execFileSync4(
|
|
5874
6001
|
"gh",
|
|
@@ -5922,7 +6049,7 @@ function fetchRecentActivity(repoName, shortName) {
|
|
|
5922
6049
|
}
|
|
5923
6050
|
events.push({
|
|
5924
6051
|
type: eventType,
|
|
5925
|
-
repoShortName:
|
|
6052
|
+
repoShortName: shortName2,
|
|
5926
6053
|
issueNumber: ev.number,
|
|
5927
6054
|
actor: ev.actor,
|
|
5928
6055
|
summary,
|
|
@@ -6064,7 +6191,7 @@ __export(format_static_exports, {
|
|
|
6064
6191
|
renderBoardJson: () => renderBoardJson,
|
|
6065
6192
|
renderStaticBoard: () => renderStaticBoard
|
|
6066
6193
|
});
|
|
6067
|
-
function
|
|
6194
|
+
function truncate2(s, max) {
|
|
6068
6195
|
return s.length > max ? `${s.slice(0, max - 1)}\u2026` : s;
|
|
6069
6196
|
}
|
|
6070
6197
|
function issueAssignee(issue, selfLogin) {
|
|
@@ -6077,13 +6204,13 @@ function issueAssignee(issue, selfLogin) {
|
|
|
6077
6204
|
}
|
|
6078
6205
|
function formatIssueLine(issue, selfLogin, maxTitle) {
|
|
6079
6206
|
const num = theme.text.accent(`#${String(issue.number).padEnd(5)}`);
|
|
6080
|
-
const title =
|
|
6207
|
+
const title = truncate2(issue.title, maxTitle);
|
|
6081
6208
|
const assignee = issueAssignee(issue, selfLogin);
|
|
6082
6209
|
return ` ${num} ${title.padEnd(maxTitle)} ${assignee}`;
|
|
6083
6210
|
}
|
|
6084
6211
|
function formatTaskLine(task2, maxTitle) {
|
|
6085
6212
|
const pri = task2.priority === 5 /* High */ ? theme.priority.high("[!]") : task2.priority === 3 /* Medium */ ? theme.priority.medium("[~]") : " ";
|
|
6086
|
-
const title =
|
|
6213
|
+
const title = truncate2(task2.title, maxTitle);
|
|
6087
6214
|
const due = task2.dueDate ? formatDueDate(task2.dueDate) : "";
|
|
6088
6215
|
return ` ${pri} ${title.padEnd(maxTitle)} ${theme.text.secondary(due)}`;
|
|
6089
6216
|
}
|
|
@@ -6504,13 +6631,13 @@ Configuring ${repoName}...`);
|
|
|
6504
6631
|
} else {
|
|
6505
6632
|
completionAction = { type: "closeIssue" };
|
|
6506
6633
|
}
|
|
6507
|
-
const
|
|
6634
|
+
const shortName2 = await input({
|
|
6508
6635
|
message: ` Short name for ${repoName}:`,
|
|
6509
6636
|
default: name
|
|
6510
6637
|
});
|
|
6511
6638
|
repos.push({
|
|
6512
6639
|
name: repoName,
|
|
6513
|
-
shortName,
|
|
6640
|
+
shortName: shortName2,
|
|
6514
6641
|
projectNumber,
|
|
6515
6642
|
statusFieldId,
|
|
6516
6643
|
...dueDateFieldId ? { dueDateFieldId } : {},
|
|
@@ -7004,7 +7131,7 @@ function resolveProjectId(projectId) {
|
|
|
7004
7131
|
process.exit(1);
|
|
7005
7132
|
}
|
|
7006
7133
|
var program = new Command();
|
|
7007
|
-
program.name("hog").description("Personal command deck \u2014 unified task dashboard for GitHub Projects + TickTick").version("1.
|
|
7134
|
+
program.name("hog").description("Personal command deck \u2014 unified task dashboard for GitHub Projects + TickTick").version("1.11.0").option("--json", "Force JSON output").option("--human", "Force human-readable output").hook("preAction", (thisCommand) => {
|
|
7008
7135
|
const opts = thisCommand.opts();
|
|
7009
7136
|
if (opts.json) setFormat("json");
|
|
7010
7137
|
if (opts.human) setFormat("human");
|
|
@@ -7199,7 +7326,7 @@ config.command("repos:add <name>").description("Add a repository to track (owner
|
|
|
7199
7326
|
console.error(`Repo "${name}" is already configured.`);
|
|
7200
7327
|
process.exit(1);
|
|
7201
7328
|
}
|
|
7202
|
-
const
|
|
7329
|
+
const shortName2 = name.split("/")[1] ?? name;
|
|
7203
7330
|
let completionAction;
|
|
7204
7331
|
switch (opts.completionType) {
|
|
7205
7332
|
case "addLabel":
|
|
@@ -7227,7 +7354,7 @@ config.command("repos:add <name>").description("Add a repository to track (owner
|
|
|
7227
7354
|
}
|
|
7228
7355
|
const newRepo = {
|
|
7229
7356
|
name,
|
|
7230
|
-
shortName,
|
|
7357
|
+
shortName: shortName2,
|
|
7231
7358
|
projectNumber: Number.parseInt(opts.projectNumber, 10),
|
|
7232
7359
|
statusFieldId: opts.statusFieldId,
|
|
7233
7360
|
completionAction
|
|
@@ -7237,7 +7364,7 @@ config.command("repos:add <name>").description("Add a repository to track (owner
|
|
|
7237
7364
|
if (useJson()) {
|
|
7238
7365
|
jsonOut({ ok: true, message: `Added ${name}`, data: newRepo });
|
|
7239
7366
|
} else {
|
|
7240
|
-
console.log(`Added ${
|
|
7367
|
+
console.log(`Added ${shortName2} \u2192 ${name}`);
|
|
7241
7368
|
}
|
|
7242
7369
|
});
|
|
7243
7370
|
config.command("repos:rm <name>").description("Remove a repository from tracking").action((name) => {
|