@nightkatana/kronosys-app 1.0.0-beta.21 → 1.0.0-beta.22
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/README.md +1 -1
- package/app/changelog/page.tsx +87 -19
- package/app/globals.css +10 -8
- package/app/guide/page.tsx +71 -34
- package/app/implementation/page.tsx +70 -60
- package/app/licenses/page.tsx +79 -47
- package/app/logs/page.tsx +103 -47
- package/app/page.tsx +104 -169
- package/app/reporting/page.tsx +1918 -1436
- package/app/settings/page.tsx +66 -44
- package/components/KronosysPayloadProvider.tsx +19 -5
- package/components/dashboard/AppShellHeaderKronoFocus.tsx +78 -0
- package/components/dashboard/AppShellHeaderToolbarLayout.tsx +36 -0
- package/components/dashboard/AppShellHeaderUtilityRibbon.tsx +19 -0
- package/components/dashboard/AppShellHeaderWallClock.tsx +23 -17
- package/components/dashboard/AppShellRouteNav.tsx +336 -209
- package/components/dashboard/AppShellToolbarCommandCenter.tsx +225 -0
- package/components/dashboard/AppShellToolbarRouteNav.tsx +204 -0
- package/components/dashboard/DashboardCommandCenter.tsx +119 -30
- package/components/dashboard/KronoFocusPanel.tsx +287 -260
- package/components/dashboard/LanguageMenu.tsx +23 -7
- package/components/dashboard/PageRefreshButton.tsx +42 -16
- package/components/dashboard/ReportingTour.tsx +20 -2
- package/components/dashboard/SessionListPanel.tsx +4 -4
- package/components/dashboard/ThemeToggle.tsx +4 -3
- package/components/dashboard/useAnchoredFloatingPortalStyle.ts +9 -2
- package/components/dashboard/useKronoFocusLiveSeconds.ts +4 -2
- package/lib/appShellHeaderClasses.ts +22 -3
- package/lib/appShellToolbarChrome.ts +112 -0
- package/lib/appShellToolbarDeferredIntents.ts +112 -0
- package/lib/appShellToolbarSessionSlices.ts +67 -0
- package/lib/dashboardCopy.ts +78 -29
- package/lib/dashboardQuickSearch.ts +37 -6
- package/lib/dashboardUrlSession.ts +36 -0
- package/lib/generatedUserChangelog.ts +14 -0
- package/lib/implementationNotes.ts +18 -14
- package/lib/reportingAggregate.ts +68 -9
- package/lib/reportingMetricHelp.ts +8 -8
- package/lib/reportingStrings.ts +118 -9
- package/lib/reportingTagWeekBreakdown.ts +55 -13
- package/lib/settingsCopy.ts +6 -7
- package/lib/userGuideCopy.ts +29 -26
- package/package.json +7 -5
- package/server/db.ts +6 -4
- package/server/dbSchema.ts +2 -2
- package/components/dashboard/AppShellCommandCenterPlaceholder.tsx +0 -17
|
@@ -17,6 +17,11 @@ import {
|
|
|
17
17
|
} from "@/lib/dashboardShortcuts";
|
|
18
18
|
import type { DashboardSearchItem } from "@/lib/dashboardQuickSearch";
|
|
19
19
|
import { dataSearchItemMatches } from "@/lib/dashboardQuickSearchQuery";
|
|
20
|
+
import {
|
|
21
|
+
appShellToolbarIconLinkClass,
|
|
22
|
+
appShellToolbarRaisedWideTriggerClass,
|
|
23
|
+
appShellToolbarRibbonGroupClass,
|
|
24
|
+
} from "@/lib/appShellToolbarChrome";
|
|
20
25
|
|
|
21
26
|
export type DashboardCommandHandlers = {
|
|
22
27
|
newSession: () => void;
|
|
@@ -49,7 +54,7 @@ const DATA_SEARCH_TIMER_BASE =
|
|
|
49
54
|
"block w-full min-w-0 truncate text-[0.7rem] leading-snug tabular-nums";
|
|
50
55
|
|
|
51
56
|
function classForDataSearchTimer(
|
|
52
|
-
state: DashboardSearchItem["searchTimerState"]
|
|
57
|
+
state: DashboardSearchItem["searchTimerState"],
|
|
53
58
|
): string {
|
|
54
59
|
if (state === "active") {
|
|
55
60
|
return `${DATA_SEARCH_TIMER_BASE} text-emerald-600 dark:text-emerald-400/95`;
|
|
@@ -88,23 +93,64 @@ export function DashboardCommandCenter({
|
|
|
88
93
|
const combos = useMemo(() => mergeCombos(overrides), [overrides]);
|
|
89
94
|
|
|
90
95
|
const isMac =
|
|
91
|
-
typeof navigator !== "undefined" &&
|
|
96
|
+
typeof navigator !== "undefined" &&
|
|
97
|
+
/mac|iphone|ipad|ipod/i.test(navigator.platform ?? "");
|
|
92
98
|
|
|
93
99
|
const actions = useMemo(() => {
|
|
94
|
-
const list: Array<{
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
100
|
+
const list: Array<{
|
|
101
|
+
id: string;
|
|
102
|
+
label: string;
|
|
103
|
+
kw: string;
|
|
104
|
+
run: () => void;
|
|
105
|
+
}> = [
|
|
106
|
+
{
|
|
107
|
+
id: "new-session",
|
|
108
|
+
label: dt.commandNewSession,
|
|
109
|
+
kw: "new session nouvelle",
|
|
110
|
+
run: handlers.newSession,
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
id: "refresh",
|
|
114
|
+
label: dt.commandRefresh,
|
|
115
|
+
kw: "reload actualiser rafraîchir",
|
|
116
|
+
run: handlers.refresh,
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
id: "reporting",
|
|
120
|
+
label: dt.commandOpenReporting,
|
|
121
|
+
kw: "reporting graph bilan stats",
|
|
122
|
+
run: handlers.openReporting,
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
id: "settings",
|
|
126
|
+
label: dt.commandOpenSettings,
|
|
127
|
+
kw: "settings paramètres",
|
|
128
|
+
run: handlers.openSettings,
|
|
129
|
+
},
|
|
99
130
|
{
|
|
100
131
|
id: "user-guide",
|
|
101
132
|
label: dt.commandOpenUserGuide,
|
|
102
133
|
kw: "help aide manuel guide book livre",
|
|
103
134
|
run: handlers.openUserGuide,
|
|
104
135
|
},
|
|
105
|
-
{
|
|
106
|
-
|
|
107
|
-
|
|
136
|
+
{
|
|
137
|
+
id: "focus-sessions",
|
|
138
|
+
label: dt.commandFocusSessions,
|
|
139
|
+
kw: "sessions colonne liste",
|
|
140
|
+
run: handlers.focusSessions,
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
id: "focus-tasks",
|
|
144
|
+
label: dt.commandFocusTasks,
|
|
145
|
+
kw: "tasks tâches",
|
|
146
|
+
run: handlers.focusTasks,
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
id: "focus-tags",
|
|
150
|
+
label: dt.commandFocusTags,
|
|
151
|
+
kw: "tags étiquettes projects projets",
|
|
152
|
+
run: handlers.focusTags,
|
|
153
|
+
},
|
|
108
154
|
{
|
|
109
155
|
id: "toggle-theme",
|
|
110
156
|
label: dt.commandToggleTheme,
|
|
@@ -171,7 +217,7 @@ export function DashboardCommandCenter({
|
|
|
171
217
|
row.onSelect();
|
|
172
218
|
closePalette();
|
|
173
219
|
},
|
|
174
|
-
[closePalette, filtered]
|
|
220
|
+
[closePalette, filtered],
|
|
175
221
|
);
|
|
176
222
|
|
|
177
223
|
useEffect(() => {
|
|
@@ -239,7 +285,15 @@ export function DashboardCommandCenter({
|
|
|
239
285
|
};
|
|
240
286
|
window.addEventListener("keydown", onKey, true);
|
|
241
287
|
return () => window.removeEventListener("keydown", onKey, true);
|
|
242
|
-
}, [
|
|
288
|
+
}, [
|
|
289
|
+
actions,
|
|
290
|
+
closePalette,
|
|
291
|
+
combos,
|
|
292
|
+
handlers,
|
|
293
|
+
paletteOpen,
|
|
294
|
+
recordingId,
|
|
295
|
+
shortcutsOpen,
|
|
296
|
+
]);
|
|
243
297
|
|
|
244
298
|
const onPaletteKeyDown = (e: React.KeyboardEvent) => {
|
|
245
299
|
if (e.key === "ArrowDown") {
|
|
@@ -278,7 +332,11 @@ export function DashboardCommandCenter({
|
|
|
278
332
|
onKeyDown={onPaletteKeyDown}
|
|
279
333
|
>
|
|
280
334
|
<div className="flex items-center gap-2 border-b border-zinc-200 px-3 py-2 dark:border-zinc-700">
|
|
281
|
-
<Search
|
|
335
|
+
<Search
|
|
336
|
+
className="shrink-0 text-zinc-400"
|
|
337
|
+
size={18}
|
|
338
|
+
aria-hidden
|
|
339
|
+
/>
|
|
282
340
|
<input
|
|
283
341
|
ref={inputRef}
|
|
284
342
|
type="search"
|
|
@@ -293,11 +351,18 @@ export function DashboardCommandCenter({
|
|
|
293
351
|
{isMac ? "⌘K" : "Ctrl+K"}
|
|
294
352
|
</kbd>
|
|
295
353
|
</div>
|
|
296
|
-
<ul
|
|
354
|
+
<ul
|
|
355
|
+
id="dash-palette-results"
|
|
356
|
+
className="max-h-[min(50vh,22rem)] list-none overflow-y-auto py-1"
|
|
357
|
+
>
|
|
297
358
|
{query.trim() === "" ? (
|
|
298
|
-
<li className="px-3 py-4 text-center text-sm text-zinc-500">
|
|
359
|
+
<li className="px-3 py-4 text-center text-sm text-zinc-500">
|
|
360
|
+
{dt.dataSearchTypePrompt}
|
|
361
|
+
</li>
|
|
299
362
|
) : filtered.length === 0 ? (
|
|
300
|
-
<li className="px-3 py-4 text-center text-sm text-zinc-500">
|
|
363
|
+
<li className="px-3 py-4 text-center text-sm text-zinc-500">
|
|
364
|
+
{dt.dataSearchEmpty}
|
|
365
|
+
</li>
|
|
301
366
|
) : (
|
|
302
367
|
filtered.map((row, idx) => (
|
|
303
368
|
<li key={row.id} className="list-none">
|
|
@@ -312,7 +377,9 @@ export function DashboardCommandCenter({
|
|
|
312
377
|
onClick={() => runSearchRow(idx)}
|
|
313
378
|
>
|
|
314
379
|
<span className="flex w-full min-w-0 items-center justify-between gap-2">
|
|
315
|
-
<span className="min-w-0 truncate font-medium">
|
|
380
|
+
<span className="min-w-0 truncate font-medium">
|
|
381
|
+
{row.title}
|
|
382
|
+
</span>
|
|
316
383
|
{row.subtitle ? (
|
|
317
384
|
<span className="shrink-0 text-[0.65rem] uppercase tracking-wide text-zinc-500 dark:text-zinc-400">
|
|
318
385
|
{row.subtitle}
|
|
@@ -320,7 +387,11 @@ export function DashboardCommandCenter({
|
|
|
320
387
|
) : null}
|
|
321
388
|
</span>
|
|
322
389
|
{row.searchTimerLine ? (
|
|
323
|
-
<span
|
|
390
|
+
<span
|
|
391
|
+
className={classForDataSearchTimer(
|
|
392
|
+
row.searchTimerState,
|
|
393
|
+
)}
|
|
394
|
+
>
|
|
324
395
|
{row.searchTimerLine}
|
|
325
396
|
</span>
|
|
326
397
|
) : null}
|
|
@@ -339,7 +410,7 @@ export function DashboardCommandCenter({
|
|
|
339
410
|
</p>
|
|
340
411
|
</div>
|
|
341
412
|
</div>,
|
|
342
|
-
document.body
|
|
413
|
+
document.body,
|
|
343
414
|
)
|
|
344
415
|
: null;
|
|
345
416
|
|
|
@@ -359,7 +430,10 @@ export function DashboardCommandCenter({
|
|
|
359
430
|
>
|
|
360
431
|
<div className="max-h-[min(90vh,36rem)] w-full max-w-lg overflow-hidden rounded-xl border border-zinc-300 bg-white shadow-2xl dark:border-zinc-600 dark:bg-zinc-900">
|
|
361
432
|
<div className="flex items-center justify-between border-b border-zinc-200 px-4 py-3 dark:border-zinc-700">
|
|
362
|
-
<h2
|
|
433
|
+
<h2
|
|
434
|
+
id="dash-shortcuts-title"
|
|
435
|
+
className="text-base font-semibold text-zinc-900 dark:text-zinc-100"
|
|
436
|
+
>
|
|
363
437
|
{dt.shortcutsModalTitle}
|
|
364
438
|
</h2>
|
|
365
439
|
<button
|
|
@@ -388,16 +462,26 @@ export function DashboardCommandCenter({
|
|
|
388
462
|
</thead>
|
|
389
463
|
<tbody>
|
|
390
464
|
{actions
|
|
391
|
-
.filter(
|
|
465
|
+
.filter(
|
|
466
|
+
(a) =>
|
|
467
|
+
a.id !== "end-live-session" || handlers.endLiveSession,
|
|
468
|
+
)
|
|
392
469
|
.map((a) => {
|
|
393
470
|
const combo = combos[a.id] ?? "";
|
|
394
471
|
const recording = recordingId === a.id;
|
|
395
472
|
return (
|
|
396
|
-
<tr
|
|
397
|
-
|
|
473
|
+
<tr
|
|
474
|
+
key={a.id}
|
|
475
|
+
className="border-t border-zinc-100 dark:border-zinc-800"
|
|
476
|
+
>
|
|
477
|
+
<td className="px-2 py-2 text-zinc-800 dark:text-zinc-200">
|
|
478
|
+
{a.label}
|
|
479
|
+
</td>
|
|
398
480
|
<td className="px-2 py-2 font-mono text-xs text-zinc-600 dark:text-zinc-400">
|
|
399
481
|
{recording ? (
|
|
400
|
-
<span className="text-violet-600 dark:text-violet-300">
|
|
482
|
+
<span className="text-violet-600 dark:text-violet-300">
|
|
483
|
+
{dt.shortcutsRecordPrompt}
|
|
484
|
+
</span>
|
|
401
485
|
) : (
|
|
402
486
|
formatComboForDisplay(combo, isMac)
|
|
403
487
|
)}
|
|
@@ -433,29 +517,34 @@ export function DashboardCommandCenter({
|
|
|
433
517
|
</div>
|
|
434
518
|
</div>
|
|
435
519
|
</div>,
|
|
436
|
-
document.body
|
|
520
|
+
document.body,
|
|
437
521
|
)
|
|
438
522
|
: null;
|
|
439
523
|
|
|
440
524
|
return (
|
|
441
525
|
<>
|
|
442
|
-
<div
|
|
526
|
+
<div
|
|
527
|
+
id={toolbarDomId}
|
|
528
|
+
className={`${appShellToolbarRibbonGroupClass} shrink-0`}
|
|
529
|
+
>
|
|
443
530
|
<button
|
|
444
531
|
type="button"
|
|
445
|
-
className=
|
|
532
|
+
className={`${appShellToolbarRaisedWideTriggerClass} w-[9.5rem] max-w-[min(42vw,11rem)] gap-1.5 px-2 text-left text-xs text-zinc-500 sm:w-44 sm:max-w-none sm:px-2.5 sm:text-sm dark:text-zinc-400`}
|
|
446
533
|
onClick={openPalette}
|
|
447
534
|
aria-haspopup="dialog"
|
|
448
535
|
aria-expanded={paletteOpen ? "true" : "false"}
|
|
449
536
|
>
|
|
450
537
|
<Search className="shrink-0" size={16} aria-hidden />
|
|
451
|
-
<span className="min-w-0 flex-1 truncate">
|
|
452
|
-
|
|
538
|
+
<span className="min-w-0 flex-1 truncate">
|
|
539
|
+
{dt.dataSearchTrigger}
|
|
540
|
+
</span>
|
|
541
|
+
<kbd className="hidden shrink-0 rounded border border-zinc-300/90 bg-gradient-to-b from-white to-zinc-100 px-1 py-0.5 font-mono text-[0.6rem] text-zinc-500 shadow-[0_1px_1px_rgba(15,23,42,0.08)] sm:inline dark:border-zinc-600 dark:from-zinc-700 dark:to-zinc-800 dark:text-zinc-400">
|
|
453
542
|
{isMac ? "⌘K" : "Ctrl+K"}
|
|
454
543
|
</kbd>
|
|
455
544
|
</button>
|
|
456
545
|
<button
|
|
457
546
|
type="button"
|
|
458
|
-
className=
|
|
547
|
+
className={appShellToolbarIconLinkClass}
|
|
459
548
|
onClick={() => setShortcutsOpen(true)}
|
|
460
549
|
title={dt.shortcutsModalTitle}
|
|
461
550
|
aria-label={dt.shortcutsModalTitle}
|