@knpkv/jira-clockify 0.2.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/LICENSE +21 -0
- package/README.md +121 -0
- package/dist/package.json +47 -0
- package/dist/src/bin.js +28 -0
- package/dist/src/bin.js.map +1 -0
- package/dist/src/cli/auth.js +169 -0
- package/dist/src/cli/auth.js.map +1 -0
- package/dist/src/cli/config.js +107 -0
- package/dist/src/cli/config.js.map +1 -0
- package/dist/src/cli/fuzzySelect.js +149 -0
- package/dist/src/cli/fuzzySelect.js.map +1 -0
- package/dist/src/cli/layers.js +59 -0
- package/dist/src/cli/layers.js.map +1 -0
- package/dist/src/cli/list.js +27 -0
- package/dist/src/cli/list.js.map +1 -0
- package/dist/src/cli/setup.js +134 -0
- package/dist/src/cli/setup.js.map +1 -0
- package/dist/src/cli/timer/discard.js +33 -0
- package/dist/src/cli/timer/discard.js.map +1 -0
- package/dist/src/cli/timer/edit.js +139 -0
- package/dist/src/cli/timer/edit.js.map +1 -0
- package/dist/src/cli/timer/index.js +12 -0
- package/dist/src/cli/timer/index.js.map +1 -0
- package/dist/src/cli/timer/log.js +96 -0
- package/dist/src/cli/timer/log.js.map +1 -0
- package/dist/src/cli/timer/start.js +156 -0
- package/dist/src/cli/timer/start.js.map +1 -0
- package/dist/src/cli/timer/status.js +80 -0
- package/dist/src/cli/timer/status.js.map +1 -0
- package/dist/src/cli/timer/stop.js +96 -0
- package/dist/src/cli/timer/stop.js.map +1 -0
- package/dist/src/cli/timer.js +7 -0
- package/dist/src/cli/timer.js.map +1 -0
- package/dist/src/main.js +24 -0
- package/dist/src/main.js.map +1 -0
- package/dist/src/services/ClockifyAuth.js +77 -0
- package/dist/src/services/ClockifyAuth.js.map +1 -0
- package/dist/src/services/ConfigService.js +66 -0
- package/dist/src/services/ConfigService.js.map +1 -0
- package/dist/src/services/StateWriter.js +69 -0
- package/dist/src/services/StateWriter.js.map +1 -0
- package/dist/src/services/TicketService.js +106 -0
- package/dist/src/services/TicketService.js.map +1 -0
- package/dist/src/services/TimerService.js +271 -0
- package/dist/src/services/TimerService.js.map +1 -0
- package/dist/src/tui/App.js +204 -0
- package/dist/src/tui/App.js.map +1 -0
- package/dist/src/tui/atoms/runtime.js +9 -0
- package/dist/src/tui/atoms/runtime.js.map +1 -0
- package/dist/src/tui/atoms/tickets.js +17 -0
- package/dist/src/tui/atoms/tickets.js.map +1 -0
- package/dist/src/tui/atoms/timer.js +31 -0
- package/dist/src/tui/atoms/timer.js.map +1 -0
- package/dist/src/tui/atoms/ui.js +10 -0
- package/dist/src/tui/atoms/ui.js.map +1 -0
- package/dist/src/tui/components/BigTimer.js +60 -0
- package/dist/src/tui/components/BigTimer.js.map +1 -0
- package/dist/src/tui/components/Footer.js +16 -0
- package/dist/src/tui/components/Footer.js.map +1 -0
- package/dist/src/tui/components/Header.js +16 -0
- package/dist/src/tui/components/Header.js.map +1 -0
- package/dist/src/tui/components/PopupInput.js +30 -0
- package/dist/src/tui/components/PopupInput.js.map +1 -0
- package/dist/src/tui/components/PopupMessage.js +47 -0
- package/dist/src/tui/components/PopupMessage.js.map +1 -0
- package/dist/src/tui/components/TicketList.js +40 -0
- package/dist/src/tui/components/TicketList.js.map +1 -0
- package/dist/src/tui/components/TicketRow.js +48 -0
- package/dist/src/tui/components/TicketRow.js.map +1 -0
- package/dist/src/tui/components/TimerDisplay.js +30 -0
- package/dist/src/tui/components/TimerDisplay.js.map +1 -0
- package/dist/src/tui/components/index.js +12 -0
- package/dist/src/tui/components/index.js.map +1 -0
- package/dist/src/tui/context/theme.js +15 -0
- package/dist/src/tui/context/theme.js.map +1 -0
- package/dist/src/tui/hooks/useElapsedTimer.js +35 -0
- package/dist/src/tui/hooks/useElapsedTimer.js.map +1 -0
- package/dist/src/tui/hooks/useTerminalSize.js +32 -0
- package/dist/src/tui/hooks/useTerminalSize.js.map +1 -0
- package/dist/src/utils/time.js +23 -0
- package/dist/src/utils/time.js.map +1 -0
- package/dist/test/TimerService.test.js +355 -0
- package/dist/test/TimerService.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/nvim/lua/jcf/branch.lua +26 -0
- package/nvim/lua/jcf/float.lua +87 -0
- package/nvim/lua/jcf/init.lua +70 -0
- package/nvim/lua/jcf/state.lua +56 -0
- package/nvim/lua/jcf/statusline.lua +31 -0
- package/nvim/lua/jcf/telescope.lua +50 -0
- package/nvim/plugin/jcf.vim +2 -0
- package/package.json +47 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "@opentui/react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Root TUI component โ keyboard routing, polling lifecycle, and view switching.
|
|
4
|
+
*
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
7
|
+
import { Result, useAtomSet, useAtomValue } from "@effect-atom/atom-react";
|
|
8
|
+
import { useKeyboard } from "@opentui/react";
|
|
9
|
+
import { useCallback, useEffect, useState } from "react";
|
|
10
|
+
import { refreshAtom, ticketsAtom } from "./atoms/tickets.js";
|
|
11
|
+
import { detectRunningAtom, discardTimerAtom, startTimerAtom, stopTimerAtom, timerStateAtom } from "./atoms/timer.js";
|
|
12
|
+
import { filterTextAtom, isFilteringAtom, selectedIndexAtom } from "./atoms/ui.js";
|
|
13
|
+
import { BigTimer } from "./components/BigTimer.js";
|
|
14
|
+
import { Footer, Header, TicketList } from "./components/index.js";
|
|
15
|
+
import { PopupInput } from "./components/PopupInput.js";
|
|
16
|
+
import { PopupMessage } from "./components/PopupMessage.js";
|
|
17
|
+
import { ThemeProvider } from "./context/theme.js";
|
|
18
|
+
function AppContent({ onQuit }) {
|
|
19
|
+
const refresh = useAtomSet(refreshAtom);
|
|
20
|
+
const detectRunning = useAtomSet(detectRunningAtom);
|
|
21
|
+
const selectedIndex = useAtomValue(selectedIndexAtom);
|
|
22
|
+
const setSelectedIndex = useAtomSet(selectedIndexAtom);
|
|
23
|
+
const startTimer = useAtomSet(startTimerAtom);
|
|
24
|
+
const stopTimer = useAtomSet(stopTimerAtom);
|
|
25
|
+
const discardTimer = useAtomSet(discardTimerAtom);
|
|
26
|
+
const filterText = useAtomValue(filterTextAtom);
|
|
27
|
+
const setFilterText = useAtomSet(filterTextAtom);
|
|
28
|
+
const isFiltering = useAtomValue(isFilteringAtom);
|
|
29
|
+
const setIsFiltering = useAtomSet(isFilteringAtom);
|
|
30
|
+
const [showTickets, setShowTickets] = useState(false);
|
|
31
|
+
const [isStopping, setIsStopping] = useState(false);
|
|
32
|
+
const [isDiscarding, setIsDiscarding] = useState(false);
|
|
33
|
+
// Captures the view state when popup opens so it doesn't flicker on timer state change
|
|
34
|
+
const [frozenOnTimer, setFrozenOnTimer] = useState(false);
|
|
35
|
+
const [resultMsg, setResultMsg] = useState(null);
|
|
36
|
+
const ticketsResult = useAtomValue(ticketsAtom);
|
|
37
|
+
const ticketState = Result.isSuccess(ticketsResult) ? ticketsResult.value : null;
|
|
38
|
+
const tickets = ticketState?.tickets ?? [];
|
|
39
|
+
const timerResult = useAtomValue(timerStateAtom);
|
|
40
|
+
const timerState = Result.isSuccess(timerResult) ? timerResult.value : null;
|
|
41
|
+
const timerActive = timerState?.active ?? false;
|
|
42
|
+
// Auto-switch views โ frozen while popup is showing
|
|
43
|
+
const hasPopup = isStopping || isDiscarding || resultMsg !== null;
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
if (hasPopup)
|
|
46
|
+
return; // don't switch while popup is open
|
|
47
|
+
if (timerActive)
|
|
48
|
+
setShowTickets(false);
|
|
49
|
+
}, [timerActive, hasPopup]);
|
|
50
|
+
// Initial data fetch
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
refresh();
|
|
53
|
+
detectRunning();
|
|
54
|
+
}, [refresh, detectRunning]);
|
|
55
|
+
// Clamp selectedIndex
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
if (tickets.length > 0 && selectedIndex >= tickets.length) {
|
|
58
|
+
setSelectedIndex(tickets.length - 1);
|
|
59
|
+
}
|
|
60
|
+
}, [tickets.length, selectedIndex, setSelectedIndex]);
|
|
61
|
+
// Poll Clockify every 30s โ paused while popup is open
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
if (hasPopup)
|
|
64
|
+
return;
|
|
65
|
+
const interval = setInterval(() => detectRunning(), 30_000);
|
|
66
|
+
return () => clearInterval(interval);
|
|
67
|
+
}, [detectRunning, hasPopup]);
|
|
68
|
+
// Observe stop result to show accurate Jira worklog status
|
|
69
|
+
const stopResult = useAtomValue(stopTimerAtom);
|
|
70
|
+
useEffect(() => {
|
|
71
|
+
if (!frozenOnTimer || isStopping)
|
|
72
|
+
return;
|
|
73
|
+
if (Result.isSuccess(stopResult)) {
|
|
74
|
+
const jiraOk = stopResult.value.jiraWorklogLogged;
|
|
75
|
+
setResultMsg({
|
|
76
|
+
title: "Timer stopped",
|
|
77
|
+
lines: [
|
|
78
|
+
{ text: "Clockify: saved โ", color: "#00CC66" },
|
|
79
|
+
jiraOk
|
|
80
|
+
? { text: "Jira worklog: saved โ", color: "#00CC66" }
|
|
81
|
+
: { text: "Jira worklog: failed โ", color: "#FF6666" }
|
|
82
|
+
],
|
|
83
|
+
type: jiraOk ? "success" : "error"
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
else if (Result.isFailure(stopResult)) {
|
|
87
|
+
setResultMsg({
|
|
88
|
+
title: "Timer stop failed",
|
|
89
|
+
lines: [{ text: "Could not stop timer", color: "#FF6666" }],
|
|
90
|
+
type: "error"
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}, [stopResult, frozenOnTimer, isStopping]);
|
|
94
|
+
// Stop handler with comment โ freeze view so popup stays visible
|
|
95
|
+
const handleStop = useCallback((comment) => {
|
|
96
|
+
setFrozenOnTimer(true); // keep big timer visible while popup shows
|
|
97
|
+
setIsStopping(false);
|
|
98
|
+
stopTimer({ comment: comment.trim() || undefined });
|
|
99
|
+
}, [stopTimer]);
|
|
100
|
+
useKeyboard((key) => {
|
|
101
|
+
if (key.name === "c" && key.ctrl) {
|
|
102
|
+
onQuit();
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
// Popup open โ block all keys (input handles its own)
|
|
106
|
+
if (isStopping || resultMsg)
|
|
107
|
+
return;
|
|
108
|
+
// Filter mode
|
|
109
|
+
if (isFiltering) {
|
|
110
|
+
if (key.name === "escape") {
|
|
111
|
+
setIsFiltering(false);
|
|
112
|
+
setFilterText("");
|
|
113
|
+
}
|
|
114
|
+
else if (key.name === "return") {
|
|
115
|
+
setIsFiltering(false);
|
|
116
|
+
}
|
|
117
|
+
else if (key.name === "backspace") {
|
|
118
|
+
setFilterText(filterText.slice(0, -1));
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
const char = key.char || (key.name?.length === 1 ? key.name : null);
|
|
122
|
+
if (char && char.length === 1)
|
|
123
|
+
setFilterText(filterText + char);
|
|
124
|
+
}
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
// Toggle timer โ tickets
|
|
128
|
+
if (key.name === "l" || key.name === "tab") {
|
|
129
|
+
if (timerActive)
|
|
130
|
+
setShowTickets(!showTickets);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
// Navigation (ticket list only)
|
|
134
|
+
if (showTickets || !timerActive) {
|
|
135
|
+
if (key.name === "up" || key.name === "k") {
|
|
136
|
+
setSelectedIndex(Math.max(0, selectedIndex - 1));
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
if (key.name === "down" || key.name === "j") {
|
|
140
|
+
setSelectedIndex(Math.min(tickets.length - 1, selectedIndex + 1));
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
switch (key.name) {
|
|
145
|
+
case "q":
|
|
146
|
+
onQuit();
|
|
147
|
+
break;
|
|
148
|
+
case "r":
|
|
149
|
+
refresh();
|
|
150
|
+
break;
|
|
151
|
+
case "/":
|
|
152
|
+
case "f":
|
|
153
|
+
if (showTickets || !timerActive)
|
|
154
|
+
setIsFiltering(true);
|
|
155
|
+
break;
|
|
156
|
+
case "s":
|
|
157
|
+
case "return": {
|
|
158
|
+
if (showTickets || !timerActive) {
|
|
159
|
+
const ticket = tickets[selectedIndex];
|
|
160
|
+
if (ticket)
|
|
161
|
+
startTimer(ticket);
|
|
162
|
+
}
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
case "x":
|
|
166
|
+
if (timerActive)
|
|
167
|
+
setIsStopping(true);
|
|
168
|
+
break;
|
|
169
|
+
case "d":
|
|
170
|
+
if (timerActive)
|
|
171
|
+
setIsDiscarding(true);
|
|
172
|
+
break;
|
|
173
|
+
case "escape":
|
|
174
|
+
if (filterText)
|
|
175
|
+
setFilterText("");
|
|
176
|
+
else if (showTickets && timerActive)
|
|
177
|
+
setShowTickets(false);
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
// Single return โ popups overlay on top of any view
|
|
182
|
+
// frozenOnTimer keeps big timer visible while result popup is showing
|
|
183
|
+
const showBigTimer = (timerActive || frozenOnTimer) && !showTickets;
|
|
184
|
+
return (_jsxs("box", { style: { flexDirection: "column", height: "100%", width: "100%" }, children: [_jsx(Header, {}), showBigTimer ? (_jsx(BigTimer, {})) : (_jsxs(_Fragment, { children: [_jsx(TicketList, {}), _jsx(Footer, {})] })), isDiscarding ? (_jsx(PopupMessage, { title: "Discard timer?", lines: [
|
|
185
|
+
{ text: "This will delete the Clockify entry.", color: "#FFCC00" },
|
|
186
|
+
{ text: "No Jira worklog will be created.", color: "#FFCC00" }
|
|
187
|
+
], type: "error", onDismiss: () => {
|
|
188
|
+
discardTimer();
|
|
189
|
+
setIsDiscarding(false);
|
|
190
|
+
setFrozenOnTimer(true);
|
|
191
|
+
setResultMsg({
|
|
192
|
+
title: "Timer discarded",
|
|
193
|
+
lines: [{ text: "Clockify entry deleted.", color: "#888888" }],
|
|
194
|
+
type: "info"
|
|
195
|
+
});
|
|
196
|
+
} })) : null, isStopping ? (_jsx(PopupInput, { title: "Stop timer \u2014 add a comment", placeholder: "What did you work on? (empty to skip)", onSubmit: handleStop, onCancel: () => setIsStopping(false) })) : null, resultMsg ? (_jsx(PopupMessage, { title: resultMsg.title, lines: resultMsg.lines, type: resultMsg.type, onDismiss: () => {
|
|
197
|
+
setResultMsg(null);
|
|
198
|
+
setFrozenOnTimer(false);
|
|
199
|
+
} })) : null] }));
|
|
200
|
+
}
|
|
201
|
+
export function App({ onQuit }) {
|
|
202
|
+
return (_jsx(ThemeProvider, { children: _jsx(AppContent, { onQuit: onQuit }) }));
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=App.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"App.js","sourceRoot":"","sources":["../../../src/tui/App.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Effect runtime bootstrapping for TUI atoms โ builds layers and provides runtime to Jotai atoms.
|
|
3
|
+
*
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
import { Atom } from "@effect-atom/atom-react";
|
|
7
|
+
import { HeadlessLayer } from "../../cli/layers.js";
|
|
8
|
+
export const runtimeAtom = Atom.runtime(HeadlessLayer);
|
|
9
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../../../src/tui/atoms/runtime.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAA;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAEnD,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,CAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Jotai atom for Jira ticket state, bridged from {@link TicketService} SubscriptionRef.
|
|
3
|
+
*
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
import { Effect } from "effect";
|
|
7
|
+
import { TicketService } from "../../services/TicketService.js";
|
|
8
|
+
import { runtimeAtom } from "./runtime.js";
|
|
9
|
+
export const ticketsAtom = runtimeAtom.subscribable(Effect.gen(function* () {
|
|
10
|
+
const service = yield* TicketService;
|
|
11
|
+
return service.state;
|
|
12
|
+
}));
|
|
13
|
+
export const refreshAtom = runtimeAtom.fn(Effect.fnUntraced(function* () {
|
|
14
|
+
const service = yield* TicketService;
|
|
15
|
+
yield* service.refresh;
|
|
16
|
+
}));
|
|
17
|
+
//# sourceMappingURL=tickets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tickets.js","sourceRoot":"","sources":["../../../../src/tui/atoms/tickets.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/B,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAA;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE1C,MAAM,CAAC,MAAM,WAAW,GAAG,WAAW,CAAC,YAAY,CACjD,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,aAAa,CAAA;IACpC,OAAO,OAAO,CAAC,KAAK,CAAA;AACtB,CAAC,CAAC,CACH,CAAA;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,WAAW,CAAC,EAAE,CACvC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC;IACzB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,aAAa,CAAA;IACpC,KAAK,CAAC,CAAC,OAAO,CAAC,OAAO,CAAA;AACxB,CAAC,CAAC,CACH,CAAA"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Jotai atoms for timer state and actions (start/stop), bridged from {@link TimerService}.
|
|
3
|
+
*
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
import { Atom } from "@effect-atom/atom-react";
|
|
7
|
+
import { Effect } from "effect";
|
|
8
|
+
import { TimerService } from "../../services/TimerService.js";
|
|
9
|
+
import { runtimeAtom } from "./runtime.js";
|
|
10
|
+
export const timerStateAtom = runtimeAtom.subscribable(Effect.gen(function* () {
|
|
11
|
+
const service = yield* TimerService;
|
|
12
|
+
return service.state;
|
|
13
|
+
}));
|
|
14
|
+
export const elapsedAtom = Atom.make(0).pipe(Atom.keepAlive);
|
|
15
|
+
export const startTimerAtom = runtimeAtom.fn(Effect.fnUntraced(function* (ticket) {
|
|
16
|
+
const service = yield* TimerService;
|
|
17
|
+
yield* service.start(ticket);
|
|
18
|
+
}));
|
|
19
|
+
export const stopTimerAtom = runtimeAtom.fn(Effect.fnUntraced(function* (options) {
|
|
20
|
+
const service = yield* TimerService;
|
|
21
|
+
return yield* service.stop(options);
|
|
22
|
+
}));
|
|
23
|
+
export const discardTimerAtom = runtimeAtom.fn(Effect.fnUntraced(function* () {
|
|
24
|
+
const service = yield* TimerService;
|
|
25
|
+
yield* service.discard;
|
|
26
|
+
}));
|
|
27
|
+
export const detectRunningAtom = runtimeAtom.fn(Effect.fnUntraced(function* () {
|
|
28
|
+
const service = yield* TimerService;
|
|
29
|
+
yield* service.detectRunning;
|
|
30
|
+
}));
|
|
31
|
+
//# sourceMappingURL=timer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timer.js","sourceRoot":"","sources":["../../../../src/tui/atoms/timer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAA;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B,OAAO,EAAoB,YAAY,EAAE,MAAM,gCAAgC,CAAA;AAC/E,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE1C,MAAM,CAAC,MAAM,cAAc,GAAG,WAAW,CAAC,YAAY,CACpD,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,YAAY,CAAA;IACnC,OAAO,OAAO,CAAC,KAAK,CAAA;AACtB,CAAC,CAAC,CACH,CAAA;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;AAE5D,MAAM,CAAC,MAAM,cAAc,GAAG,WAAW,CAAC,EAAE,CAC1C,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAC,MAAkB;IAC5C,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,YAAY,CAAA;IACnC,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;AAC9B,CAAC,CAAC,CACH,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,WAAW,CAAC,EAAE,CACzC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAC,OAAqB;IAC/C,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,YAAY,CAAA;IACnC,OAAO,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;AACrC,CAAC,CAAC,CACH,CAAA;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,WAAW,CAAC,EAAE,CAC5C,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC;IACzB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,YAAY,CAAA;IACnC,KAAK,CAAC,CAAC,OAAO,CAAC,OAAO,CAAA;AACxB,CAAC,CAAC,CACH,CAAA;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAG,WAAW,CAAC,EAAE,CAC7C,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC;IACzB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,YAAY,CAAA;IACnC,KAAK,CAAC,CAAC,OAAO,CAAC,aAAa,CAAA;AAC9B,CAAC,CAAC,CACH,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Jotai atoms for UI state โ filter text, active view, theme.
|
|
3
|
+
*
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
import { Atom } from "@effect-atom/atom-react";
|
|
7
|
+
export const selectedIndexAtom = Atom.make(0).pipe(Atom.keepAlive);
|
|
8
|
+
export const filterTextAtom = Atom.make("").pipe(Atom.keepAlive);
|
|
9
|
+
export const isFilteringAtom = Atom.make(false).pipe(Atom.keepAlive);
|
|
10
|
+
//# sourceMappingURL=ui.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../../../../src/tui/atoms/ui.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAA;AAI9C,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;AAClE,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;AAChE,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "@opentui/react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* 5ร5 ASCII digit timer display for the TUI main view.
|
|
4
|
+
*
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
7
|
+
import nodeProcess from "node:process";
|
|
8
|
+
import { useElapsedTimer } from "../hooks/useElapsedTimer.js";
|
|
9
|
+
// 5-line tall digit font (each digit is 5 rows ร 5 cols)
|
|
10
|
+
const DIGITS = {
|
|
11
|
+
"0": ["โโโโโ", "โ โ", "โ โ", "โ โ", "โโโโโ"],
|
|
12
|
+
"1": [" โ", " โ", " โ", " โ", " โ"],
|
|
13
|
+
"2": ["โโโโโ", " โ", "โโโโโ", "โ ", "โโโโโ"],
|
|
14
|
+
"3": ["โโโโโ", " โ", " โโโโฃ", " โ", "โโโโโ"],
|
|
15
|
+
"4": ["โ โ", "โ โ", "โโโโโฃ", " โ", " โ"],
|
|
16
|
+
"5": ["โโโโโ", "โ ", "โโโโโ", " โ", "โโโโโ"],
|
|
17
|
+
"6": ["โโโโโ", "โ ", "โ โโโโ", "โ โ", "โโโโโ"],
|
|
18
|
+
"7": ["โโโโโ", " โ", " โ", " โ", " โ"],
|
|
19
|
+
"8": ["โโโโโ", "โ โ", "โ โโโโฃ", "โ โ", "โโโโโ"],
|
|
20
|
+
"9": ["โโโโโ", "โ โ", "โโโโโฃ", " โ", "โโโโโ"],
|
|
21
|
+
":": [" ", " โ ", " ", " โ ", " "]
|
|
22
|
+
};
|
|
23
|
+
function renderBigTime(h, m, s) {
|
|
24
|
+
const chars = [...String(h).padStart(2, "0"), ":", ...String(m).padStart(2, "0"), ":", ...String(s).padStart(2, "0")];
|
|
25
|
+
const rows = ["", "", "", "", ""];
|
|
26
|
+
for (const char of chars) {
|
|
27
|
+
const glyph = DIGITS[char] ?? DIGITS["0"];
|
|
28
|
+
for (let row = 0; row < 5; row++) {
|
|
29
|
+
rows[row] += glyph[row] + " ";
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return rows;
|
|
33
|
+
}
|
|
34
|
+
function centerPad(text, width) {
|
|
35
|
+
if (text.length >= width)
|
|
36
|
+
return text;
|
|
37
|
+
const left = Math.floor((width - text.length) / 2);
|
|
38
|
+
return " ".repeat(left) + text;
|
|
39
|
+
}
|
|
40
|
+
export function BigTimer() {
|
|
41
|
+
const { elapsed, timerState } = useElapsedTimer();
|
|
42
|
+
const h = Math.floor(elapsed / 3600);
|
|
43
|
+
const m = Math.floor((elapsed % 3600) / 60);
|
|
44
|
+
const s = elapsed % 60;
|
|
45
|
+
const rows = renderBigTime(h, m, s);
|
|
46
|
+
const cols = nodeProcess.stdout.columns ?? 80;
|
|
47
|
+
// Progress bar
|
|
48
|
+
const barWidth = 40;
|
|
49
|
+
const filled = Math.floor((s / 60) * barWidth);
|
|
50
|
+
const bar = "โ".repeat(filled) + "โ".repeat(barWidth - filled);
|
|
51
|
+
// Metadata line
|
|
52
|
+
const meta = [
|
|
53
|
+
timerState?.projectName ? `โ ${timerState.projectName}` : timerState?.projectId ? "โ project" : null,
|
|
54
|
+
timerState?.billable ? "โ billable" : timerState?.billable === false ? "โ non-billable" : null
|
|
55
|
+
]
|
|
56
|
+
.filter(Boolean)
|
|
57
|
+
.join(" ");
|
|
58
|
+
return (_jsxs("box", { style: { flexDirection: "column", flexGrow: 1, width: "100%" }, children: [_jsx("box", { style: { flexGrow: 1 } }), _jsx("box", { style: { height: 1 }, children: _jsx("text", { fg: "#00CCFF", style: { fontWeight: "bold" }, children: centerPad(timerState?.ticketKey ?? "", cols) }) }), _jsx("box", { style: { height: 1 }, children: _jsx("text", { fg: "#888888", children: centerPad(timerState?.summary?.slice(0, 60) ?? "", cols) }) }), _jsx("box", { style: { height: 1 } }), rows.map((row, i) => (_jsx("box", { style: { height: 1 }, children: _jsx("text", { fg: "#7aa87a", children: centerPad(row, cols) }) }, i))), _jsx("box", { style: { height: 1 } }), _jsx("box", { style: { height: 1 }, children: _jsx("text", { fg: "#3a5a3a", children: centerPad(bar, cols) }) }), _jsx("box", { style: { height: 1 } }), _jsx("box", { style: { height: 1 }, children: _jsx("text", { fg: "#888888", children: centerPad("x stop d discard l tickets q quit", cols) }) }), meta ? (_jsx("box", { style: { height: 1 }, children: _jsx("text", { fg: "#555555", children: centerPad(meta, cols) }) })) : null, _jsx("box", { style: { flexGrow: 1 } })] }));
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=BigTimer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BigTimer.js","sourceRoot":"","sources":["../../../../src/tui/components/BigTimer.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "@opentui/react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Help footer showing available keyboard shortcuts.
|
|
4
|
+
*
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
7
|
+
import { useAtomValue } from "@effect-atom/atom-react";
|
|
8
|
+
import { isFilteringAtom } from "../atoms/ui.js";
|
|
9
|
+
export function Footer() {
|
|
10
|
+
const isFiltering = useAtomValue(isFilteringAtom);
|
|
11
|
+
if (isFiltering) {
|
|
12
|
+
return (_jsxs("box", { style: { height: 1, width: "100%", backgroundColor: "#1a1a2e", flexDirection: "row", paddingLeft: 1 }, children: [_jsx("box", { style: { backgroundColor: "#00CCFF", paddingLeft: 1, paddingRight: 1 }, children: _jsx("text", { fg: "#000000", children: "/" }) }), _jsx("text", { fg: "#888888", children: "type to filter \u00B7" }), _jsx("text", { fg: "#555555", children: "esc clear \u00B7 enter apply" })] }));
|
|
13
|
+
}
|
|
14
|
+
return (_jsx("box", { style: { height: 1, width: "100%", backgroundColor: "#1a1a2e", paddingLeft: 2 }, children: _jsx("text", { fg: "#888888", children: "โโ navigate s/โ start x stop / filter r refresh q quit" }) }));
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=Footer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Footer.js","sourceRoot":"","sources":["../../../../src/tui/components/Footer.tsx"],"names":[],"mappings":";AAAA;;;;GAIG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAEhD,MAAM,UAAU,MAAM;IACpB,MAAM,WAAW,GAAG,YAAY,CAAC,eAAe,CAAC,CAAA;IAEjD,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,CACL,eACE,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,aAAa,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,EAAS,aAE5G,cAAK,KAAK,EAAE,EAAE,eAAe,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAS,YAChF,eAAM,EAAE,EAAC,SAAS,kBAAS,GACvB,EACN,eAAM,EAAE,EAAC,SAAS,sCAAwB,EAC1C,eAAM,EAAE,EAAC,SAAS,6CAA+B,IAC7C,CACP,CAAA;IACH,CAAC;IAED,OAAO,CACL,cAAK,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC,EAAS,YACzF,eAAM,EAAE,EAAC,SAAS,YAAE,6DAA6D,GAAQ,GACrF,CACP,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "@opentui/react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Status bar showing active ticket, timer state, and project.
|
|
4
|
+
*
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
7
|
+
import { Result, useAtomValue } from "@effect-atom/atom-react";
|
|
8
|
+
import { timerStateAtom } from "../atoms/timer.js";
|
|
9
|
+
export function Header() {
|
|
10
|
+
const timerResult = useAtomValue(timerStateAtom);
|
|
11
|
+
const timerState = Result.isSuccess(timerResult) ? timerResult.value : null;
|
|
12
|
+
const statusIcon = timerState?.active ? "โ" : "โ";
|
|
13
|
+
const statusColor = timerState?.active ? "#00CC66" : "#888888";
|
|
14
|
+
return (_jsxs("box", { style: { height: 1, width: "100%", backgroundColor: "#1a1a2e", flexDirection: "row" }, children: [_jsx("text", { fg: statusColor, style: { fontWeight: "bold" }, children: ` ${statusIcon} ` }), timerState?.active && timerState.ticketKey ? (_jsx("text", { fg: "#00CCFF", style: { fontWeight: "bold" }, children: timerState.ticketKey })) : (_jsx("text", { fg: "#888888", children: "jcf" })), timerState?.active && timerState.summary ? (_jsx("text", { fg: "#888888", children: ` ${timerState.summary.slice(0, 50)}` })) : null, timerState?.active && timerState.projectName ? (_jsx("text", { fg: "#555555", children: ` [${timerState.projectName}]` })) : null] }));
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=Header.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Header.js","sourceRoot":"","sources":["../../../../src/tui/components/Header.tsx"],"names":[],"mappings":";AAAA;;;;GAIG;AACH,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAE9D,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAElD,MAAM,UAAU,MAAM;IACpB,MAAM,WAAW,GAAG,YAAY,CAAC,cAAc,CAAC,CAAA;IAChD,MAAM,UAAU,GAAsB,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAA;IAE9F,MAAM,UAAU,GAAG,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAA;IACjD,MAAM,WAAW,GAAG,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAA;IAE9D,OAAO,CACL,eAAK,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,aAAa,EAAE,KAAK,EAAS,aAC/F,eAAM,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,EAAS,YACxD,KAAK,UAAU,GAAG,GACd,EACN,UAAU,EAAE,MAAM,IAAI,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAC5C,eAAM,EAAE,EAAC,SAAS,EAAC,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,EAAS,YACpD,UAAU,CAAC,SAAS,GAChB,CACR,CAAC,CAAC,CAAC,CACF,eAAM,EAAE,EAAC,SAAS,oBAAW,CAC9B,EACA,UAAU,EAAE,MAAM,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAC1C,eAAM,EAAE,EAAC,SAAS,YAAE,KAAK,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,GAAQ,CACnE,CAAC,CAAC,CAAC,IAAI,EACP,UAAU,EAAE,MAAM,IAAI,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,CAC9C,eAAM,EAAE,EAAC,SAAS,YAAE,MAAM,UAAU,CAAC,WAAW,GAAG,GAAQ,CAC5D,CAAC,CAAC,CAAC,IAAI,IACJ,CACP,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "@opentui/react/jsx-runtime";
|
|
2
|
+
export function PopupInput({ onCancel, onSubmit, placeholder, title }) {
|
|
3
|
+
return (_jsxs("box", { style: {
|
|
4
|
+
position: "absolute",
|
|
5
|
+
top: 0,
|
|
6
|
+
left: 0,
|
|
7
|
+
width: "100%",
|
|
8
|
+
height: "100%",
|
|
9
|
+
justifyContent: "center",
|
|
10
|
+
alignItems: "center"
|
|
11
|
+
}, children: [_jsx("box", { style: {
|
|
12
|
+
position: "absolute",
|
|
13
|
+
top: 0,
|
|
14
|
+
left: 0,
|
|
15
|
+
width: "100%",
|
|
16
|
+
height: "100%",
|
|
17
|
+
backgroundColor: "rgba(0,0,0,0.6)"
|
|
18
|
+
} }), _jsxs("box", { style: {
|
|
19
|
+
width: 60,
|
|
20
|
+
height: 7,
|
|
21
|
+
flexDirection: "column",
|
|
22
|
+
backgroundColor: "#1a1a2e",
|
|
23
|
+
border: 1,
|
|
24
|
+
borderColor: "#444466",
|
|
25
|
+
paddingLeft: 2,
|
|
26
|
+
paddingRight: 2,
|
|
27
|
+
paddingTop: 1
|
|
28
|
+
}, children: [_jsx("box", { style: { height: 1 }, children: _jsx("text", { fg: "#FFCC00", style: { fontWeight: "bold" }, children: title }) }), _jsx("box", { style: { height: 1, marginTop: 1 }, children: _jsx("input", { focused: true, placeholder: placeholder ?? "", onSubmit: ((value) => onSubmit(value)), style: { width: "100%", backgroundColor: "#0f0f1a", fg: "#FFFFFF" } }) }), _jsx("box", { style: { height: 1, marginTop: 1 }, children: _jsx("text", { fg: "#888888", children: "enter: confirm esc: cancel" }) })] })] }));
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=PopupInput.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PopupInput.js","sourceRoot":"","sources":["../../../../src/tui/components/PopupInput.tsx"],"names":[],"mappings":";AAYA,MAAM,UAAU,UAAU,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAmB;IACpF,OAAO,CACL,eACE,KAAK,EACH;YACE,QAAQ,EAAE,UAAU;YACpB,GAAG,EAAE,CAAC;YACN,IAAI,EAAE,CAAC;YACP,KAAK,EAAE,MAAM;YACb,MAAM,EAAE,MAAM;YACd,cAAc,EAAE,QAAQ;YACxB,UAAU,EAAE,QAAQ;SACd,aAIV,cACE,KAAK,EACH;oBACE,QAAQ,EAAE,UAAU;oBACpB,GAAG,EAAE,CAAC;oBACN,IAAI,EAAE,CAAC;oBACP,KAAK,EAAE,MAAM;oBACb,MAAM,EAAE,MAAM;oBACd,eAAe,EAAE,iBAAiB;iBAC5B,GAEV,EAGF,eACE,KAAK,EACH;oBACE,KAAK,EAAE,EAAE;oBACT,MAAM,EAAE,CAAC;oBACT,aAAa,EAAE,QAAQ;oBACvB,eAAe,EAAE,SAAS;oBAC1B,MAAM,EAAE,CAAC;oBACT,WAAW,EAAE,SAAS;oBACtB,WAAW,EAAE,CAAC;oBACd,YAAY,EAAE,CAAC;oBACf,UAAU,EAAE,CAAC;iBACP,aAIV,cAAK,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,YACvB,eAAM,EAAE,EAAC,SAAS,EAAC,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,EAAS,YACpD,KAAK,GACD,GACH,EAGN,cAAK,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAS,YAC5C,gBACE,OAAO,QACP,WAAW,EAAE,WAAW,IAAI,EAAE,EAC9B,QAAQ,EAAE,CAAC,CAAC,KAAa,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAQ,EACrD,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,EAAE,EAAE,SAAS,EAAS,GAC1E,GACE,EAGN,cAAK,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAS,YAC5C,eAAM,EAAE,EAAC,SAAS,2CAAkC,GAChD,IACF,IACF,CACP,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "@opentui/react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Centered popup dialog showing a result message with OK button.
|
|
4
|
+
*
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
7
|
+
import { useKeyboard } from "@opentui/react";
|
|
8
|
+
const typeColors = {
|
|
9
|
+
success: "#00CC66",
|
|
10
|
+
error: "#FF4444",
|
|
11
|
+
info: "#00CCFF"
|
|
12
|
+
};
|
|
13
|
+
const typeIcons = {
|
|
14
|
+
success: "โ",
|
|
15
|
+
error: "โ",
|
|
16
|
+
info: "โ"
|
|
17
|
+
};
|
|
18
|
+
export function PopupMessage({ lines, onDismiss, title, type = "info" }) {
|
|
19
|
+
const color = typeColors[type];
|
|
20
|
+
const icon = typeIcons[type];
|
|
21
|
+
useKeyboard((key) => {
|
|
22
|
+
if (key.name === "return" || key.name === "escape" || key.name === "q") {
|
|
23
|
+
onDismiss();
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
const height = 4 + lines.length + 2; // border + title + gap + lines + gap + button
|
|
27
|
+
return (_jsx("box", { style: {
|
|
28
|
+
position: "absolute",
|
|
29
|
+
top: 0,
|
|
30
|
+
left: 0,
|
|
31
|
+
width: "100%",
|
|
32
|
+
height: "100%",
|
|
33
|
+
justifyContent: "center",
|
|
34
|
+
alignItems: "center"
|
|
35
|
+
}, children: _jsxs("box", { style: {
|
|
36
|
+
width: 56,
|
|
37
|
+
height,
|
|
38
|
+
flexDirection: "column",
|
|
39
|
+
backgroundColor: "#1a1a2e",
|
|
40
|
+
border: 1,
|
|
41
|
+
borderColor: color,
|
|
42
|
+
paddingLeft: 2,
|
|
43
|
+
paddingRight: 2,
|
|
44
|
+
paddingTop: 1
|
|
45
|
+
}, children: [_jsx("box", { style: { height: 1 }, children: _jsx("text", { fg: color, style: { fontWeight: "bold" }, children: `${icon} ${title}` }) }), _jsx("box", { style: { height: 1 } }), lines.map((line, i) => (_jsx("box", { style: { height: 1 }, children: _jsx("text", { fg: line.color ?? "#CCCCCC", children: ` ${line.text}` }) }, i))), _jsx("box", { style: { height: 1 } }), _jsx("box", { style: { height: 1, justifyContent: "center" }, children: _jsx("box", { style: { backgroundColor: color, paddingLeft: 2, paddingRight: 2 }, children: _jsx("text", { fg: "#000000", style: { fontWeight: "bold" }, children: "OK (enter)" }) }) })] }) }));
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=PopupMessage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PopupMessage.js","sourceRoot":"","sources":["../../../../src/tui/components/PopupMessage.tsx"],"names":[],"mappings":";AAAA;;;;GAIG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAS5C,MAAM,UAAU,GAAG;IACjB,OAAO,EAAE,SAAS;IAClB,KAAK,EAAE,SAAS;IAChB,IAAI,EAAE,SAAS;CAChB,CAAA;AAED,MAAM,SAAS,GAAG;IAChB,OAAO,EAAE,GAAG;IACZ,KAAK,EAAE,GAAG;IACV,IAAI,EAAE,GAAG;CACV,CAAA;AAED,MAAM,UAAU,YAAY,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,GAAG,MAAM,EAAqB;IACxF,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAA;IAC9B,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,CAAA;IAE5B,WAAW,CAAC,CAAC,GAAqC,EAAE,EAAE;QACpD,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,KAAK,GAAG,EAAE,CAAC;YACvE,SAAS,EAAE,CAAA;QACb,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,MAAM,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAA,CAAC,8CAA8C;IAElF,OAAO,CACL,cACE,KAAK,EACH;YACE,QAAQ,EAAE,UAAU;YACpB,GAAG,EAAE,CAAC;YACN,IAAI,EAAE,CAAC;YACP,KAAK,EAAE,MAAM;YACb,MAAM,EAAE,MAAM;YACd,cAAc,EAAE,QAAQ;YACxB,UAAU,EAAE,QAAQ;SACd,YAGV,eACE,KAAK,EACH;gBACE,KAAK,EAAE,EAAE;gBACT,MAAM;gBACN,aAAa,EAAE,QAAQ;gBACvB,eAAe,EAAE,SAAS;gBAC1B,MAAM,EAAE,CAAC;gBACT,WAAW,EAAE,KAAK;gBAClB,WAAW,EAAE,CAAC;gBACd,YAAY,EAAE,CAAC;gBACf,UAAU,EAAE,CAAC;aACP,aAIV,cAAK,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,YACvB,eAAM,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,EAAS,YAClD,GAAG,IAAI,IAAI,KAAK,EAAE,GACd,GACH,EAEN,cAAK,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,EAAS,GAAI,EAGnC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CACtB,cAAa,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,YAC/B,eAAM,EAAE,EAAE,IAAI,CAAC,KAAK,IAAI,SAAS,YAAG,KAAK,IAAI,CAAC,IAAI,EAAE,GAAQ,IADpD,CAAC,CAEL,CACP,CAAC,EAEF,cAAK,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,EAAS,GAAI,EAGpC,cAAK,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,cAAc,EAAE,QAAQ,EAAS,YACxD,cAAK,KAAK,EAAE,EAAE,eAAe,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAS,YAC5E,eAAM,EAAE,EAAC,SAAS,EAAC,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,EAAS,2BAEhD,GACH,GACF,IACF,GACF,CACP,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "@opentui/react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Ticket table with cursor selection and inline filtering.
|
|
4
|
+
*
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
7
|
+
import { Result, useAtomValue } from "@effect-atom/atom-react";
|
|
8
|
+
import { ticketsAtom } from "../atoms/tickets.js";
|
|
9
|
+
import { filterTextAtom, isFilteringAtom, selectedIndexAtom } from "../atoms/ui.js";
|
|
10
|
+
import { TicketRow } from "./TicketRow.js";
|
|
11
|
+
export function TicketList() {
|
|
12
|
+
const ticketResult = useAtomValue(ticketsAtom);
|
|
13
|
+
const selectedIndex = useAtomValue(selectedIndexAtom);
|
|
14
|
+
const filterText = useAtomValue(filterTextAtom);
|
|
15
|
+
const isFiltering = useAtomValue(isFilteringAtom);
|
|
16
|
+
const ticketState = Result.isSuccess(ticketResult) ? ticketResult.value : null;
|
|
17
|
+
if (!ticketState || ticketState.loading) {
|
|
18
|
+
return (_jsx("box", { style: { flexGrow: 1, paddingLeft: 2 }, children: _jsx("text", { fg: "#FFCC00", children: "Loading tickets..." }) }));
|
|
19
|
+
}
|
|
20
|
+
if (ticketState.error) {
|
|
21
|
+
return (_jsx("box", { style: { flexGrow: 1, paddingLeft: 2 }, children: _jsxs("text", { fg: "#FF4444", children: ["Error: ", ticketState.error] }) }));
|
|
22
|
+
}
|
|
23
|
+
// Apply filter
|
|
24
|
+
let tickets = ticketState.tickets;
|
|
25
|
+
if (filterText.trim()) {
|
|
26
|
+
const lower = filterText.toLowerCase();
|
|
27
|
+
tickets = tickets.filter((t) => t.key.toLowerCase().includes(lower) ||
|
|
28
|
+
t.summary.toLowerCase().includes(lower) ||
|
|
29
|
+
t.status.toLowerCase().includes(lower));
|
|
30
|
+
}
|
|
31
|
+
if (tickets.length === 0) {
|
|
32
|
+
return (_jsx("box", { style: { flexGrow: 1, paddingLeft: 2 }, children: _jsx("text", { fg: "#888888", children: filterText ? `No tickets matching "${filterText}"` : "No tickets found" }) }));
|
|
33
|
+
}
|
|
34
|
+
return (_jsxs("box", { style: { flexDirection: "column", flexGrow: 1 }, children: [_jsxs("box", { style: {
|
|
35
|
+
height: 1,
|
|
36
|
+
paddingLeft: 2,
|
|
37
|
+
paddingTop: 1
|
|
38
|
+
}, children: [_jsx("text", { fg: "#FFCC00", style: { fontWeight: "bold" }, children: "TICKETS" }), _jsx("text", { fg: "#888888", children: ` (${tickets.length})` }), isFiltering ? _jsx("text", { fg: "#00CCFF", children: ` filter: ${filterText}โ` }) : null] }), tickets.map((ticket, i) => (_jsx(TicketRow, { ticket: ticket, selected: i === selectedIndex }, ticket.key)))] }));
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=TicketList.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TicketList.js","sourceRoot":"","sources":["../../../../src/tui/components/TicketList.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "@opentui/react/jsx-runtime";
|
|
2
|
+
const statusColor = (status) => {
|
|
3
|
+
const s = status.toLowerCase();
|
|
4
|
+
if (s.includes("progress") || s.includes("development"))
|
|
5
|
+
return "#5599FF";
|
|
6
|
+
if (s.includes("review"))
|
|
7
|
+
return "#CC88FF";
|
|
8
|
+
if (s.includes("to do") || s.includes("open"))
|
|
9
|
+
return "#FFCC00";
|
|
10
|
+
if (s.includes("done") || s.includes("closed"))
|
|
11
|
+
return "#00CC66";
|
|
12
|
+
if (s.includes("block") || s.includes("impediment"))
|
|
13
|
+
return "#FF4444";
|
|
14
|
+
if (s.includes("deploy") || s.includes("stage"))
|
|
15
|
+
return "#00CC66";
|
|
16
|
+
if (s.includes("duplicate"))
|
|
17
|
+
return "#888888";
|
|
18
|
+
return "#CCCCCC";
|
|
19
|
+
};
|
|
20
|
+
const typeIcon = (type) => {
|
|
21
|
+
switch (type.toLowerCase()) {
|
|
22
|
+
case "bug":
|
|
23
|
+
return "๐";
|
|
24
|
+
case "story":
|
|
25
|
+
return "๐";
|
|
26
|
+
case "task":
|
|
27
|
+
return "โ";
|
|
28
|
+
case "epic":
|
|
29
|
+
return "โก";
|
|
30
|
+
case "subtask":
|
|
31
|
+
case "sub-task":
|
|
32
|
+
return "โณ";
|
|
33
|
+
default:
|
|
34
|
+
return "ยท";
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
export function TicketRow({ selected, ticket }) {
|
|
38
|
+
const bg = selected ? "#1a2744" : undefined;
|
|
39
|
+
const keyFg = selected ? "#00CCFF" : "#FFFFFF";
|
|
40
|
+
const summaryFg = selected ? "#CCCCCC" : "#999999";
|
|
41
|
+
return (_jsxs("box", { style: {
|
|
42
|
+
height: 1,
|
|
43
|
+
flexDirection: "row",
|
|
44
|
+
paddingLeft: 1,
|
|
45
|
+
...(bg ? { backgroundColor: bg } : {})
|
|
46
|
+
}, children: [_jsx("text", { fg: keyFg, children: selected ? "โฏ" : " " }), _jsx("text", { fg: "#888888", children: typeIcon(ticket.type) }), _jsx("text", { fg: keyFg, style: { fontWeight: "bold" }, children: ticket.key.padEnd(12) }), _jsx("text", { fg: summaryFg, children: ticket.summary.slice(0, 50).padEnd(50) }), _jsx("text", { fg: statusColor(ticket.status), children: ` ${ticket.status}` })] }));
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=TicketRow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TicketRow.js","sourceRoot":"","sources":["../../../../src/tui/components/TicketRow.tsx"],"names":[],"mappings":";AAYA,MAAM,WAAW,GAAG,CAAC,MAAc,EAAU,EAAE;IAC7C,MAAM,CAAC,GAAG,MAAM,CAAC,WAAW,EAAE,CAAA;IAC9B,IAAI,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC;QAAE,OAAO,SAAS,CAAA;IACzE,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,OAAO,SAAS,CAAA;IAC1C,IAAI,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,SAAS,CAAA;IAC/D,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,OAAO,SAAS,CAAA;IAChE,IAAI,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC;QAAE,OAAO,SAAS,CAAA;IACrE,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;QAAE,OAAO,SAAS,CAAA;IACjE,IAAI,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC;QAAE,OAAO,SAAS,CAAA;IAC7C,OAAO,SAAS,CAAA;AAClB,CAAC,CAAA;AAED,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAU,EAAE;IACxC,QAAQ,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;QAC3B,KAAK,KAAK;YACR,OAAO,IAAI,CAAA;QACb,KAAK,OAAO;YACV,OAAO,IAAI,CAAA;QACb,KAAK,MAAM;YACT,OAAO,GAAG,CAAA;QACZ,KAAK,MAAM;YACT,OAAO,GAAG,CAAA;QACZ,KAAK,SAAS,CAAC;QACf,KAAK,UAAU;YACb,OAAO,GAAG,CAAA;QACZ;YACE,OAAO,GAAG,CAAA;IACd,CAAC;AACH,CAAC,CAAA;AAED,MAAM,UAAU,SAAS,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAkB;IAC5D,MAAM,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAA;IAC3C,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAA;IAC9C,MAAM,SAAS,GAAG,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAA;IAElD,OAAO,CACL,eACE,KAAK,EACH;YACE,MAAM,EAAE,CAAC;YACT,aAAa,EAAE,KAAK;YACpB,WAAW,EAAE,CAAC;YACd,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAChC,aAGV,eAAM,EAAE,EAAE,KAAK,YAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAQ,EAC9C,eAAM,EAAE,EAAC,SAAS,YAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,GAAQ,EACjD,eAAM,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,EAAS,YAClD,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GACjB,EACP,eAAM,EAAE,EAAE,SAAS,YAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,GAAQ,EACpE,eAAM,EAAE,EAAE,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,YAAG,IAAI,MAAM,CAAC,MAAM,EAAE,GAAQ,IAC9D,CACP,CAAA;AACH,CAAC"}
|