@copilotz/admin 0.3.6 → 0.3.7
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/index.cjs +1515 -291
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +63 -20
- package/dist/index.d.ts +63 -20
- package/dist/index.js +1532 -293
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1405 -84
- package/package.json +5 -1
package/dist/index.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
// src/CopilotzAdmin.tsx
|
|
2
2
|
import {
|
|
3
|
+
useCallback as useCallback4,
|
|
3
4
|
useDeferredValue,
|
|
4
|
-
useMemo as
|
|
5
|
-
useState as
|
|
5
|
+
useMemo as useMemo3,
|
|
6
|
+
useState as useState5
|
|
6
7
|
} from "react";
|
|
7
8
|
|
|
8
9
|
// src/config.ts
|
|
9
10
|
var defaultAdminConfig = {
|
|
10
11
|
branding: {
|
|
11
12
|
title: "Copilotz Admin",
|
|
12
|
-
subtitle: "
|
|
13
|
+
subtitle: "Operational visibility for Copilotz clients",
|
|
13
14
|
logo: null,
|
|
14
15
|
actions: null
|
|
15
16
|
},
|
|
@@ -43,24 +44,33 @@ var defaultAdminConfig = {
|
|
|
43
44
|
scopeScoped: "Scoped",
|
|
44
45
|
configured: "Configured",
|
|
45
46
|
unconfigured: "Observed only",
|
|
46
|
-
noResults: "No results"
|
|
47
|
+
noResults: "No results",
|
|
48
|
+
eventsTitle: "Events",
|
|
49
|
+
dashboardTitle: "Dashboard"
|
|
47
50
|
},
|
|
48
51
|
features: {
|
|
49
52
|
showOverview: true,
|
|
50
53
|
showActivity: true,
|
|
51
54
|
showThreads: true,
|
|
52
55
|
showParticipants: true,
|
|
53
|
-
showAgents: true
|
|
56
|
+
showAgents: true,
|
|
57
|
+
showEvents: false
|
|
54
58
|
},
|
|
55
59
|
ui: {
|
|
56
60
|
compact: false,
|
|
57
61
|
maxActivityBars: 18
|
|
58
62
|
},
|
|
63
|
+
sidebar: {
|
|
64
|
+
defaultOpen: true,
|
|
65
|
+
collapsible: "icon"
|
|
66
|
+
},
|
|
59
67
|
baseUrl: "",
|
|
60
68
|
getRequestHeaders: async () => ({}),
|
|
61
69
|
namespace: "",
|
|
62
70
|
initialRange: "7d",
|
|
63
|
-
initialInterval: "day"
|
|
71
|
+
initialInterval: "day",
|
|
72
|
+
defaultPage: "dashboard",
|
|
73
|
+
onNavigate: null
|
|
64
74
|
};
|
|
65
75
|
function mergeAdminConfig(_baseConfig, userConfig) {
|
|
66
76
|
if (!userConfig) return defaultAdminConfig;
|
|
@@ -81,11 +91,17 @@ function mergeAdminConfig(_baseConfig, userConfig) {
|
|
|
81
91
|
...defaultAdminConfig.ui,
|
|
82
92
|
...userConfig.ui
|
|
83
93
|
},
|
|
94
|
+
sidebar: {
|
|
95
|
+
...defaultAdminConfig.sidebar,
|
|
96
|
+
...userConfig.sidebar
|
|
97
|
+
},
|
|
84
98
|
baseUrl: userConfig.baseUrl ?? defaultAdminConfig.baseUrl,
|
|
85
99
|
getRequestHeaders: userConfig.getRequestHeaders ?? defaultAdminConfig.getRequestHeaders,
|
|
86
100
|
namespace: userConfig.namespace ?? defaultAdminConfig.namespace,
|
|
87
101
|
initialRange: userConfig.initialRange ?? defaultAdminConfig.initialRange,
|
|
88
|
-
initialInterval: userConfig.initialInterval ?? defaultAdminConfig.initialInterval
|
|
102
|
+
initialInterval: userConfig.initialInterval ?? defaultAdminConfig.initialInterval,
|
|
103
|
+
defaultPage: userConfig.defaultPage ?? defaultAdminConfig.defaultPage,
|
|
104
|
+
onNavigate: userConfig.onNavigate ?? defaultAdminConfig.onNavigate
|
|
89
105
|
};
|
|
90
106
|
}
|
|
91
107
|
|
|
@@ -159,6 +175,21 @@ async function fetchAdminJson(path, params, options) {
|
|
|
159
175
|
const payload = await response.json();
|
|
160
176
|
return payload.data;
|
|
161
177
|
}
|
|
178
|
+
async function fetchRawJson(path, params, options) {
|
|
179
|
+
const url = new URL(`${resolveBaseUrl(options?.baseUrl)}${path}`, window.location.origin);
|
|
180
|
+
for (const [key, value] of Object.entries(params)) {
|
|
181
|
+
if (typeof value === "string" && value.length > 0) {
|
|
182
|
+
url.searchParams.set(key, value);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
const response = await fetch(url.toString(), {
|
|
186
|
+
headers: await withAuthHeaders({}, options?.getRequestHeaders)
|
|
187
|
+
});
|
|
188
|
+
if (!response.ok) {
|
|
189
|
+
throw new Error(`Admin request failed (${response.status})`);
|
|
190
|
+
}
|
|
191
|
+
return await response.json();
|
|
192
|
+
}
|
|
162
193
|
async function fetchAdminOverview(range, namespace, options) {
|
|
163
194
|
const windowRange = getRangeWindow(range);
|
|
164
195
|
return await fetchAdminJson("/v1/admin/overview", {
|
|
@@ -197,6 +228,23 @@ async function fetchAdminAgents(search, namespace, options) {
|
|
|
197
228
|
limit: "8"
|
|
198
229
|
}, options);
|
|
199
230
|
}
|
|
231
|
+
async function fetchThreadDetail(threadId, options) {
|
|
232
|
+
return await fetchAdminJson(
|
|
233
|
+
`/v1/threads/${encodeURIComponent(threadId)}`,
|
|
234
|
+
{},
|
|
235
|
+
options
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
async function fetchThreadMessages(threadId, messageOptions, options) {
|
|
239
|
+
return await fetchRawJson(
|
|
240
|
+
`/v1/threads/${encodeURIComponent(threadId)}/messages`,
|
|
241
|
+
{
|
|
242
|
+
limit: messageOptions?.limit?.toString(),
|
|
243
|
+
before: messageOptions?.before
|
|
244
|
+
},
|
|
245
|
+
options
|
|
246
|
+
);
|
|
247
|
+
}
|
|
200
248
|
|
|
201
249
|
// src/useCopilotzAdmin.ts
|
|
202
250
|
function useCopilotzAdmin(options = {}) {
|
|
@@ -322,6 +370,19 @@ function Card({ className, ...props }) {
|
|
|
322
370
|
}
|
|
323
371
|
);
|
|
324
372
|
}
|
|
373
|
+
function CardHeader({ className, ...props }) {
|
|
374
|
+
return /* @__PURE__ */ jsx(
|
|
375
|
+
"div",
|
|
376
|
+
{
|
|
377
|
+
"data-slot": "card-header",
|
|
378
|
+
className: cn(
|
|
379
|
+
"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
|
|
380
|
+
className
|
|
381
|
+
),
|
|
382
|
+
...props
|
|
383
|
+
}
|
|
384
|
+
);
|
|
385
|
+
}
|
|
325
386
|
function CardContent({ className, ...props }) {
|
|
326
387
|
return /* @__PURE__ */ jsx(
|
|
327
388
|
"div",
|
|
@@ -380,10 +441,83 @@ function Button({
|
|
|
380
441
|
);
|
|
381
442
|
}
|
|
382
443
|
|
|
444
|
+
// src/components/ui/tooltip.tsx
|
|
445
|
+
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
|
446
|
+
import { jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
447
|
+
function TooltipProvider({
|
|
448
|
+
delayDuration = 0,
|
|
449
|
+
...props
|
|
450
|
+
}) {
|
|
451
|
+
return /* @__PURE__ */ jsx3(
|
|
452
|
+
TooltipPrimitive.Provider,
|
|
453
|
+
{
|
|
454
|
+
"data-slot": "tooltip-provider",
|
|
455
|
+
delayDuration,
|
|
456
|
+
...props
|
|
457
|
+
}
|
|
458
|
+
);
|
|
459
|
+
}
|
|
460
|
+
function Tooltip({
|
|
461
|
+
...props
|
|
462
|
+
}) {
|
|
463
|
+
return /* @__PURE__ */ jsx3(TooltipProvider, { children: /* @__PURE__ */ jsx3(TooltipPrimitive.Root, { "data-slot": "tooltip", ...props }) });
|
|
464
|
+
}
|
|
465
|
+
function TooltipTrigger({
|
|
466
|
+
...props
|
|
467
|
+
}) {
|
|
468
|
+
return /* @__PURE__ */ jsx3(TooltipPrimitive.Trigger, { "data-slot": "tooltip-trigger", ...props });
|
|
469
|
+
}
|
|
470
|
+
function TooltipContent({
|
|
471
|
+
className,
|
|
472
|
+
sideOffset = 0,
|
|
473
|
+
children,
|
|
474
|
+
...props
|
|
475
|
+
}) {
|
|
476
|
+
return /* @__PURE__ */ jsx3(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
|
|
477
|
+
TooltipPrimitive.Content,
|
|
478
|
+
{
|
|
479
|
+
"data-slot": "tooltip-content",
|
|
480
|
+
sideOffset,
|
|
481
|
+
className: cn(
|
|
482
|
+
"bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance",
|
|
483
|
+
className
|
|
484
|
+
),
|
|
485
|
+
...props,
|
|
486
|
+
children: [
|
|
487
|
+
children,
|
|
488
|
+
/* @__PURE__ */ jsx3(TooltipPrimitive.Arrow, { className: "bg-primary fill-primary z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" })
|
|
489
|
+
]
|
|
490
|
+
}
|
|
491
|
+
) });
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// src/components/ui/sidebar.tsx
|
|
495
|
+
import * as React3 from "react";
|
|
496
|
+
import { Slot as Slot2 } from "@radix-ui/react-slot";
|
|
497
|
+
import { cva as cva2 } from "class-variance-authority";
|
|
498
|
+
import { PanelLeftIcon } from "lucide-react";
|
|
499
|
+
|
|
500
|
+
// src/hooks/use-mobile.ts
|
|
501
|
+
import * as React from "react";
|
|
502
|
+
var MOBILE_BREAKPOINT = 768;
|
|
503
|
+
function useIsMobile() {
|
|
504
|
+
const [isMobile, setIsMobile] = React.useState(void 0);
|
|
505
|
+
React.useEffect(() => {
|
|
506
|
+
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
|
|
507
|
+
const onChange = () => {
|
|
508
|
+
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
509
|
+
};
|
|
510
|
+
mql.addEventListener("change", onChange);
|
|
511
|
+
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
512
|
+
return () => mql.removeEventListener("change", onChange);
|
|
513
|
+
}, []);
|
|
514
|
+
return !!isMobile;
|
|
515
|
+
}
|
|
516
|
+
|
|
383
517
|
// src/components/ui/input.tsx
|
|
384
|
-
import { jsx as
|
|
518
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
385
519
|
function Input({ className, type, ...props }) {
|
|
386
|
-
return /* @__PURE__ */
|
|
520
|
+
return /* @__PURE__ */ jsx4(
|
|
387
521
|
"input",
|
|
388
522
|
{
|
|
389
523
|
type,
|
|
@@ -399,326 +533,948 @@ function Input({ className, type, ...props }) {
|
|
|
399
533
|
);
|
|
400
534
|
}
|
|
401
535
|
|
|
402
|
-
// src/components/ui/
|
|
403
|
-
import
|
|
404
|
-
import
|
|
405
|
-
import {
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
{
|
|
409
|
-
|
|
410
|
-
variant: {
|
|
411
|
-
default: "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
|
|
412
|
-
secondary: "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
|
|
413
|
-
destructive: "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
|
|
414
|
-
outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground"
|
|
415
|
-
}
|
|
416
|
-
},
|
|
417
|
-
defaultVariants: {
|
|
418
|
-
variant: "default"
|
|
419
|
-
}
|
|
536
|
+
// src/components/ui/sheet.tsx
|
|
537
|
+
import * as React2 from "react";
|
|
538
|
+
import * as SheetPrimitive from "@radix-ui/react-dialog";
|
|
539
|
+
import { XIcon } from "lucide-react";
|
|
540
|
+
import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
541
|
+
function cleanupBodyStyles() {
|
|
542
|
+
if (typeof document !== "undefined" && document.body.style.pointerEvents === "none") {
|
|
543
|
+
document.body.style.pointerEvents = "";
|
|
420
544
|
}
|
|
421
|
-
|
|
422
|
-
function
|
|
545
|
+
}
|
|
546
|
+
function Sheet({ open, onOpenChange, ...props }) {
|
|
547
|
+
const prevOpenRef = React2.useRef(open);
|
|
548
|
+
React2.useEffect(() => {
|
|
549
|
+
if (prevOpenRef.current === true && open === false) {
|
|
550
|
+
const timeout = setTimeout(cleanupBodyStyles, 350);
|
|
551
|
+
return () => clearTimeout(timeout);
|
|
552
|
+
}
|
|
553
|
+
prevOpenRef.current = open;
|
|
554
|
+
}, [open]);
|
|
555
|
+
React2.useEffect(() => {
|
|
556
|
+
return () => {
|
|
557
|
+
cleanupBodyStyles();
|
|
558
|
+
};
|
|
559
|
+
}, []);
|
|
560
|
+
return /* @__PURE__ */ jsx5(SheetPrimitive.Root, { "data-slot": "sheet", open, onOpenChange, ...props });
|
|
561
|
+
}
|
|
562
|
+
function SheetPortal({
|
|
563
|
+
...props
|
|
564
|
+
}) {
|
|
565
|
+
return /* @__PURE__ */ jsx5(SheetPrimitive.Portal, { "data-slot": "sheet-portal", ...props });
|
|
566
|
+
}
|
|
567
|
+
function SheetOverlay({
|
|
423
568
|
className,
|
|
424
|
-
variant,
|
|
425
|
-
asChild = false,
|
|
426
569
|
...props
|
|
427
570
|
}) {
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
Comp,
|
|
571
|
+
return /* @__PURE__ */ jsx5(
|
|
572
|
+
SheetPrimitive.Overlay,
|
|
431
573
|
{
|
|
432
|
-
"data-slot": "
|
|
433
|
-
className: cn(
|
|
574
|
+
"data-slot": "sheet-overlay",
|
|
575
|
+
className: cn(
|
|
576
|
+
"fixed inset-0 z-50 bg-black/50",
|
|
577
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
578
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
579
|
+
"data-[state=closed]:pointer-events-none",
|
|
580
|
+
className
|
|
581
|
+
),
|
|
434
582
|
...props
|
|
435
583
|
}
|
|
436
584
|
);
|
|
437
585
|
}
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
/* @__PURE__ */ jsx5(SelectPrimitive.ScrollUpButton, { className: "flex cursor-default items-center justify-center py-1", children: /* @__PURE__ */ jsx5(ChevronUp, { className: "h-4 w-4" }) }),
|
|
475
|
-
/* @__PURE__ */ jsx5(
|
|
476
|
-
SelectPrimitive.Viewport,
|
|
477
|
-
{
|
|
478
|
-
className: cn(
|
|
479
|
-
"p-1",
|
|
480
|
-
position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
|
|
481
|
-
),
|
|
482
|
-
children
|
|
483
|
-
}
|
|
484
|
-
),
|
|
485
|
-
/* @__PURE__ */ jsx5(SelectPrimitive.ScrollDownButton, { className: "flex cursor-default items-center justify-center py-1", children: /* @__PURE__ */ jsx5(ChevronDown, { className: "h-4 w-4" }) })
|
|
486
|
-
]
|
|
487
|
-
}
|
|
488
|
-
) }));
|
|
489
|
-
SelectContent.displayName = SelectPrimitive.Content.displayName;
|
|
490
|
-
var SelectItem = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
491
|
-
SelectPrimitive.Item,
|
|
492
|
-
{
|
|
493
|
-
ref,
|
|
494
|
-
className: cn(
|
|
495
|
-
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
496
|
-
className
|
|
497
|
-
),
|
|
498
|
-
...props,
|
|
499
|
-
children: [
|
|
500
|
-
/* @__PURE__ */ jsx5(SelectPrimitive.ItemText, { children }),
|
|
501
|
-
/* @__PURE__ */ jsx5(SelectPrimitive.ItemIndicator, { className: "absolute right-2 inline-flex items-center justify-center", children: /* @__PURE__ */ jsx5(Check, { className: "h-4 w-4" }) })
|
|
502
|
-
]
|
|
503
|
-
}
|
|
504
|
-
));
|
|
505
|
-
SelectItem.displayName = SelectPrimitive.Item.displayName;
|
|
506
|
-
|
|
507
|
-
// src/CopilotzAdmin.tsx
|
|
508
|
-
import { jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
509
|
-
var CopilotzAdmin = ({
|
|
510
|
-
config: userConfig,
|
|
511
|
-
className
|
|
512
|
-
}) => {
|
|
513
|
-
const config = useMemo2(
|
|
514
|
-
() => mergeAdminConfig(defaultAdminConfig, userConfig),
|
|
515
|
-
[userConfig]
|
|
516
|
-
);
|
|
517
|
-
const [threadSearch, setThreadSearch] = useState2("");
|
|
518
|
-
const [participantSearch, setParticipantSearch] = useState2("");
|
|
519
|
-
const [agentSearch, setAgentSearch] = useState2("");
|
|
520
|
-
const deferredThreadSearch = useDeferredValue(threadSearch);
|
|
521
|
-
const deferredParticipantSearch = useDeferredValue(participantSearch);
|
|
522
|
-
const deferredAgentSearch = useDeferredValue(agentSearch);
|
|
523
|
-
const admin = useCopilotzAdmin({
|
|
524
|
-
baseUrl: config.baseUrl,
|
|
525
|
-
getRequestHeaders: config.getRequestHeaders,
|
|
526
|
-
namespace: config.namespace,
|
|
527
|
-
range: config.initialRange,
|
|
528
|
-
interval: config.initialInterval,
|
|
529
|
-
threadSearch: deferredThreadSearch,
|
|
530
|
-
participantSearch: deferredParticipantSearch,
|
|
531
|
-
agentSearch: deferredAgentSearch
|
|
532
|
-
});
|
|
533
|
-
const cards = [
|
|
534
|
-
{
|
|
535
|
-
label: config.labels.messagesCard,
|
|
536
|
-
value: admin.overview?.messageTotals.total ?? 0,
|
|
537
|
-
detail: `${admin.overview?.messageTotals.toolCallMessages ?? 0} tool-call messages`
|
|
538
|
-
},
|
|
586
|
+
function SheetContent({
|
|
587
|
+
className,
|
|
588
|
+
children,
|
|
589
|
+
side = "right",
|
|
590
|
+
...props
|
|
591
|
+
}) {
|
|
592
|
+
return /* @__PURE__ */ jsxs2(SheetPortal, { children: [
|
|
593
|
+
/* @__PURE__ */ jsx5(SheetOverlay, {}),
|
|
594
|
+
/* @__PURE__ */ jsxs2(
|
|
595
|
+
SheetPrimitive.Content,
|
|
596
|
+
{
|
|
597
|
+
"data-slot": "sheet-content",
|
|
598
|
+
"aria-describedby": void 0,
|
|
599
|
+
className: cn(
|
|
600
|
+
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
|
|
601
|
+
side === "right" && "data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm",
|
|
602
|
+
side === "left" && "data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm",
|
|
603
|
+
side === "top" && "data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 h-auto border-b",
|
|
604
|
+
side === "bottom" && "data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 h-auto border-t",
|
|
605
|
+
className
|
|
606
|
+
),
|
|
607
|
+
...props,
|
|
608
|
+
children: [
|
|
609
|
+
children,
|
|
610
|
+
/* @__PURE__ */ jsxs2(SheetPrimitive.Close, { className: "ring-offset-background focus:ring-ring data-[state=open]:bg-secondary absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none", children: [
|
|
611
|
+
/* @__PURE__ */ jsx5(XIcon, { className: "size-4" }),
|
|
612
|
+
/* @__PURE__ */ jsx5("span", { className: "sr-only", children: "Close" })
|
|
613
|
+
] })
|
|
614
|
+
]
|
|
615
|
+
}
|
|
616
|
+
)
|
|
617
|
+
] });
|
|
618
|
+
}
|
|
619
|
+
function SheetHeader({ className, ...props }) {
|
|
620
|
+
return /* @__PURE__ */ jsx5(
|
|
621
|
+
"div",
|
|
539
622
|
{
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
}
|
|
623
|
+
"data-slot": "sheet-header",
|
|
624
|
+
className: cn("flex flex-col gap-1.5 p-4", className),
|
|
625
|
+
...props
|
|
626
|
+
}
|
|
627
|
+
);
|
|
628
|
+
}
|
|
629
|
+
function SheetTitle({
|
|
630
|
+
className,
|
|
631
|
+
...props
|
|
632
|
+
}) {
|
|
633
|
+
return /* @__PURE__ */ jsx5(
|
|
634
|
+
SheetPrimitive.Title,
|
|
544
635
|
{
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
}
|
|
636
|
+
"data-slot": "sheet-title",
|
|
637
|
+
className: cn("text-foreground font-semibold", className),
|
|
638
|
+
...props
|
|
639
|
+
}
|
|
640
|
+
);
|
|
641
|
+
}
|
|
642
|
+
function SheetDescription({
|
|
643
|
+
className,
|
|
644
|
+
...props
|
|
645
|
+
}) {
|
|
646
|
+
return /* @__PURE__ */ jsx5(
|
|
647
|
+
SheetPrimitive.Description,
|
|
549
648
|
{
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
649
|
+
"data-slot": "sheet-description",
|
|
650
|
+
className: cn("text-muted-foreground text-sm", className),
|
|
651
|
+
...props
|
|
652
|
+
}
|
|
653
|
+
);
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
// src/components/ui/sidebar.tsx
|
|
657
|
+
import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
658
|
+
var SIDEBAR_COOKIE_NAME = "sidebar_state";
|
|
659
|
+
var SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
|
|
660
|
+
var SIDEBAR_WIDTH = "16rem";
|
|
661
|
+
var SIDEBAR_WIDTH_MOBILE = "18rem";
|
|
662
|
+
var SIDEBAR_WIDTH_ICON = "3rem";
|
|
663
|
+
var SIDEBAR_KEYBOARD_SHORTCUT = "b";
|
|
664
|
+
var SidebarContext = React3.createContext(null);
|
|
665
|
+
function useSidebar() {
|
|
666
|
+
const context = React3.useContext(SidebarContext);
|
|
667
|
+
if (!context) {
|
|
668
|
+
throw new Error("useSidebar must be used within a SidebarProvider.");
|
|
669
|
+
}
|
|
670
|
+
return context;
|
|
671
|
+
}
|
|
672
|
+
function SidebarProvider({
|
|
673
|
+
defaultOpen = true,
|
|
674
|
+
open: openProp,
|
|
675
|
+
onOpenChange: setOpenProp,
|
|
676
|
+
className,
|
|
677
|
+
style,
|
|
678
|
+
children,
|
|
679
|
+
...props
|
|
680
|
+
}) {
|
|
681
|
+
const isMobile = useIsMobile();
|
|
682
|
+
const [openMobile, setOpenMobile] = React3.useState(false);
|
|
683
|
+
const [_open, _setOpen] = React3.useState(defaultOpen);
|
|
684
|
+
const open = openProp ?? _open;
|
|
685
|
+
const setOpen = React3.useCallback(
|
|
686
|
+
(value) => {
|
|
687
|
+
const openState = typeof value === "function" ? value(open) : value;
|
|
688
|
+
if (setOpenProp) {
|
|
689
|
+
setOpenProp(openState);
|
|
690
|
+
} else {
|
|
691
|
+
_setOpen(openState);
|
|
692
|
+
}
|
|
693
|
+
document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;
|
|
553
694
|
},
|
|
695
|
+
[setOpenProp, open]
|
|
696
|
+
);
|
|
697
|
+
const toggleSidebar = React3.useCallback(() => {
|
|
698
|
+
return isMobile ? setOpenMobile((open2) => !open2) : setOpen((open2) => !open2);
|
|
699
|
+
}, [isMobile, setOpen, setOpenMobile]);
|
|
700
|
+
React3.useEffect(() => {
|
|
701
|
+
const handleKeyDown = (event) => {
|
|
702
|
+
if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) {
|
|
703
|
+
event.preventDefault();
|
|
704
|
+
toggleSidebar();
|
|
705
|
+
}
|
|
706
|
+
};
|
|
707
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
708
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
709
|
+
}, [toggleSidebar]);
|
|
710
|
+
const state = open ? "expanded" : "collapsed";
|
|
711
|
+
const contextValue = React3.useMemo(
|
|
712
|
+
() => ({
|
|
713
|
+
state,
|
|
714
|
+
open,
|
|
715
|
+
setOpen,
|
|
716
|
+
isMobile,
|
|
717
|
+
openMobile,
|
|
718
|
+
setOpenMobile,
|
|
719
|
+
toggleSidebar
|
|
720
|
+
}),
|
|
721
|
+
[state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar]
|
|
722
|
+
);
|
|
723
|
+
return /* @__PURE__ */ jsx6(SidebarContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx6(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsx6(
|
|
724
|
+
"div",
|
|
554
725
|
{
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
726
|
+
"data-slot": "sidebar-wrapper",
|
|
727
|
+
style: {
|
|
728
|
+
"--sidebar-width": SIDEBAR_WIDTH,
|
|
729
|
+
"--sidebar-width-icon": SIDEBAR_WIDTH_ICON,
|
|
730
|
+
...style
|
|
731
|
+
},
|
|
732
|
+
className: cn(
|
|
733
|
+
"group/sidebar-wrapper has-data-[variant=inset]:bg-sidebar flex min-h-svh w-full",
|
|
734
|
+
className
|
|
735
|
+
),
|
|
736
|
+
...props,
|
|
737
|
+
children
|
|
558
738
|
}
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
739
|
+
) }) });
|
|
740
|
+
}
|
|
741
|
+
function Sidebar({
|
|
742
|
+
side = "left",
|
|
743
|
+
variant = "sidebar",
|
|
744
|
+
collapsible = "offcanvas",
|
|
745
|
+
className,
|
|
746
|
+
children,
|
|
747
|
+
...props
|
|
748
|
+
}) {
|
|
749
|
+
const { isMobile, state, openMobile, setOpenMobile } = useSidebar();
|
|
750
|
+
if (collapsible === "none") {
|
|
751
|
+
return /* @__PURE__ */ jsx6(
|
|
752
|
+
"div",
|
|
753
|
+
{
|
|
754
|
+
"data-slot": "sidebar",
|
|
755
|
+
className: cn(
|
|
756
|
+
"bg-sidebar text-sidebar-foreground flex h-full w-(--sidebar-width) flex-col",
|
|
757
|
+
className
|
|
758
|
+
),
|
|
759
|
+
...props,
|
|
760
|
+
children
|
|
761
|
+
}
|
|
762
|
+
);
|
|
562
763
|
}
|
|
563
|
-
if (
|
|
564
|
-
return /* @__PURE__ */ jsx6(
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
764
|
+
if (isMobile) {
|
|
765
|
+
return /* @__PURE__ */ jsx6(Sheet, { open: openMobile, onOpenChange: setOpenMobile, ...props, children: /* @__PURE__ */ jsxs3(
|
|
766
|
+
SheetContent,
|
|
767
|
+
{
|
|
768
|
+
"data-sidebar": "sidebar",
|
|
769
|
+
"data-slot": "sidebar",
|
|
770
|
+
"data-mobile": "true",
|
|
771
|
+
className: "bg-sidebar text-sidebar-foreground w-(--sidebar-width) p-0 [&>button]:hidden",
|
|
772
|
+
style: {
|
|
773
|
+
"--sidebar-width": SIDEBAR_WIDTH_MOBILE
|
|
774
|
+
},
|
|
775
|
+
side,
|
|
776
|
+
children: [
|
|
777
|
+
/* @__PURE__ */ jsxs3(SheetHeader, { className: "sr-only", children: [
|
|
778
|
+
/* @__PURE__ */ jsx6(SheetTitle, { children: "Sidebar" }),
|
|
779
|
+
/* @__PURE__ */ jsx6(SheetDescription, { children: "Displays the mobile sidebar." })
|
|
780
|
+
] }),
|
|
781
|
+
/* @__PURE__ */ jsx6("div", { className: "flex h-full w-full flex-col", children })
|
|
782
|
+
]
|
|
783
|
+
}
|
|
784
|
+
) });
|
|
575
785
|
}
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
] }),
|
|
587
|
-
config.namespace ? /* @__PURE__ */ jsxs2("p", { className: "text-xs font-medium uppercase tracking-[0.18em] text-muted-foreground", children: [
|
|
588
|
-
"Namespace: ",
|
|
589
|
-
config.namespace
|
|
590
|
-
] }) : null
|
|
591
|
-
] }),
|
|
592
|
-
/* @__PURE__ */ jsxs2("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
786
|
+
return /* @__PURE__ */ jsxs3(
|
|
787
|
+
"div",
|
|
788
|
+
{
|
|
789
|
+
className: "group peer text-sidebar-foreground hidden md:block",
|
|
790
|
+
"data-state": state,
|
|
791
|
+
"data-collapsible": state === "collapsed" ? collapsible : "",
|
|
792
|
+
"data-variant": variant,
|
|
793
|
+
"data-side": side,
|
|
794
|
+
"data-slot": "sidebar",
|
|
795
|
+
children: [
|
|
593
796
|
/* @__PURE__ */ jsx6(
|
|
594
|
-
|
|
797
|
+
"div",
|
|
595
798
|
{
|
|
596
|
-
|
|
799
|
+
"data-slot": "sidebar-gap",
|
|
800
|
+
className: cn(
|
|
801
|
+
"relative w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear",
|
|
802
|
+
"group-data-[collapsible=offcanvas]:w-0",
|
|
803
|
+
"group-data-[side=right]:rotate-180",
|
|
804
|
+
variant === "floating" || variant === "inset" ? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]" : "group-data-[collapsible=icon]:w-(--sidebar-width-icon)"
|
|
805
|
+
)
|
|
806
|
+
}
|
|
807
|
+
),
|
|
808
|
+
/* @__PURE__ */ jsx6(
|
|
809
|
+
"div",
|
|
810
|
+
{
|
|
811
|
+
"data-slot": "sidebar-container",
|
|
812
|
+
className: cn(
|
|
813
|
+
"fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:flex",
|
|
814
|
+
side === "left" ? "left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]" : "right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]",
|
|
815
|
+
variant === "floating" || variant === "inset" ? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]" : "group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l",
|
|
816
|
+
className
|
|
817
|
+
),
|
|
818
|
+
...props,
|
|
819
|
+
children: /* @__PURE__ */ jsx6(
|
|
820
|
+
"div",
|
|
821
|
+
{
|
|
822
|
+
"data-sidebar": "sidebar",
|
|
823
|
+
"data-slot": "sidebar-inner",
|
|
824
|
+
className: "bg-sidebar group-data-[variant=floating]:border-sidebar-border flex h-full w-full flex-col group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:shadow-sm",
|
|
825
|
+
children
|
|
826
|
+
}
|
|
827
|
+
)
|
|
828
|
+
}
|
|
829
|
+
)
|
|
830
|
+
]
|
|
831
|
+
}
|
|
832
|
+
);
|
|
833
|
+
}
|
|
834
|
+
function SidebarTrigger({
|
|
835
|
+
className,
|
|
836
|
+
onClick,
|
|
837
|
+
...props
|
|
838
|
+
}) {
|
|
839
|
+
const { toggleSidebar } = useSidebar();
|
|
840
|
+
return /* @__PURE__ */ jsxs3(
|
|
841
|
+
Button,
|
|
842
|
+
{
|
|
843
|
+
"data-sidebar": "trigger",
|
|
844
|
+
"data-slot": "sidebar-trigger",
|
|
845
|
+
variant: "ghost",
|
|
846
|
+
size: "icon",
|
|
847
|
+
className: cn("size-7", className),
|
|
848
|
+
onClick: (event) => {
|
|
849
|
+
onClick?.(event);
|
|
850
|
+
toggleSidebar();
|
|
851
|
+
},
|
|
852
|
+
...props,
|
|
853
|
+
children: [
|
|
854
|
+
/* @__PURE__ */ jsx6(PanelLeftIcon, {}),
|
|
855
|
+
/* @__PURE__ */ jsx6("span", { className: "sr-only", children: "Toggle Sidebar" })
|
|
856
|
+
]
|
|
857
|
+
}
|
|
858
|
+
);
|
|
859
|
+
}
|
|
860
|
+
function SidebarRail({ className, ...props }) {
|
|
861
|
+
const { toggleSidebar } = useSidebar();
|
|
862
|
+
return /* @__PURE__ */ jsx6(
|
|
863
|
+
"button",
|
|
864
|
+
{
|
|
865
|
+
"data-sidebar": "rail",
|
|
866
|
+
"data-slot": "sidebar-rail",
|
|
867
|
+
"aria-label": "Toggle Sidebar",
|
|
868
|
+
tabIndex: -1,
|
|
869
|
+
onClick: toggleSidebar,
|
|
870
|
+
title: "Toggle Sidebar",
|
|
871
|
+
className: cn(
|
|
872
|
+
"hover:after:bg-sidebar-border absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] sm:flex",
|
|
873
|
+
"in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize",
|
|
874
|
+
"[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize",
|
|
875
|
+
"hover:group-data-[collapsible=offcanvas]:bg-sidebar group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full",
|
|
876
|
+
"[[data-side=left][data-collapsible=offcanvas]_&]:-right-2",
|
|
877
|
+
"[[data-side=right][data-collapsible=offcanvas]_&]:-left-2",
|
|
878
|
+
className
|
|
879
|
+
),
|
|
880
|
+
...props
|
|
881
|
+
}
|
|
882
|
+
);
|
|
883
|
+
}
|
|
884
|
+
function SidebarInset({ className, ...props }) {
|
|
885
|
+
return /* @__PURE__ */ jsx6(
|
|
886
|
+
"main",
|
|
887
|
+
{
|
|
888
|
+
"data-slot": "sidebar-inset",
|
|
889
|
+
className: cn(
|
|
890
|
+
"bg-background relative flex w-full flex-1 flex-col",
|
|
891
|
+
"md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2",
|
|
892
|
+
className
|
|
893
|
+
),
|
|
894
|
+
...props
|
|
895
|
+
}
|
|
896
|
+
);
|
|
897
|
+
}
|
|
898
|
+
function SidebarHeader({ className, ...props }) {
|
|
899
|
+
return /* @__PURE__ */ jsx6(
|
|
900
|
+
"div",
|
|
901
|
+
{
|
|
902
|
+
"data-slot": "sidebar-header",
|
|
903
|
+
"data-sidebar": "header",
|
|
904
|
+
className: cn("flex flex-col gap-2 p-2", className),
|
|
905
|
+
...props
|
|
906
|
+
}
|
|
907
|
+
);
|
|
908
|
+
}
|
|
909
|
+
function SidebarFooter({ className, ...props }) {
|
|
910
|
+
return /* @__PURE__ */ jsx6(
|
|
911
|
+
"div",
|
|
912
|
+
{
|
|
913
|
+
"data-slot": "sidebar-footer",
|
|
914
|
+
"data-sidebar": "footer",
|
|
915
|
+
className: cn("flex flex-col gap-2 p-2", className),
|
|
916
|
+
...props
|
|
917
|
+
}
|
|
918
|
+
);
|
|
919
|
+
}
|
|
920
|
+
function SidebarContent({ className, ...props }) {
|
|
921
|
+
return /* @__PURE__ */ jsx6(
|
|
922
|
+
"div",
|
|
923
|
+
{
|
|
924
|
+
"data-slot": "sidebar-content",
|
|
925
|
+
"data-sidebar": "content",
|
|
926
|
+
className: cn(
|
|
927
|
+
"flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden",
|
|
928
|
+
className
|
|
929
|
+
),
|
|
930
|
+
...props
|
|
931
|
+
}
|
|
932
|
+
);
|
|
933
|
+
}
|
|
934
|
+
function SidebarGroup({ className, ...props }) {
|
|
935
|
+
return /* @__PURE__ */ jsx6(
|
|
936
|
+
"div",
|
|
937
|
+
{
|
|
938
|
+
"data-slot": "sidebar-group",
|
|
939
|
+
"data-sidebar": "group",
|
|
940
|
+
className: cn("relative flex w-full min-w-0 flex-col p-2", className),
|
|
941
|
+
...props
|
|
942
|
+
}
|
|
943
|
+
);
|
|
944
|
+
}
|
|
945
|
+
function SidebarGroupLabel({
|
|
946
|
+
className,
|
|
947
|
+
asChild = false,
|
|
948
|
+
...props
|
|
949
|
+
}) {
|
|
950
|
+
const Comp = asChild ? Slot2 : "div";
|
|
951
|
+
return /* @__PURE__ */ jsx6(
|
|
952
|
+
Comp,
|
|
953
|
+
{
|
|
954
|
+
"data-slot": "sidebar-group-label",
|
|
955
|
+
"data-sidebar": "group-label",
|
|
956
|
+
className: cn(
|
|
957
|
+
"text-sidebar-foreground/70 ring-sidebar-ring flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium outline-hidden transition-[margin,opacity] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
|
|
958
|
+
"group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0",
|
|
959
|
+
className
|
|
960
|
+
),
|
|
961
|
+
...props
|
|
962
|
+
}
|
|
963
|
+
);
|
|
964
|
+
}
|
|
965
|
+
function SidebarGroupContent({
|
|
966
|
+
className,
|
|
967
|
+
...props
|
|
968
|
+
}) {
|
|
969
|
+
return /* @__PURE__ */ jsx6(
|
|
970
|
+
"div",
|
|
971
|
+
{
|
|
972
|
+
"data-slot": "sidebar-group-content",
|
|
973
|
+
"data-sidebar": "group-content",
|
|
974
|
+
className: cn("w-full text-sm", className),
|
|
975
|
+
...props
|
|
976
|
+
}
|
|
977
|
+
);
|
|
978
|
+
}
|
|
979
|
+
function SidebarMenu({ className, ...props }) {
|
|
980
|
+
return /* @__PURE__ */ jsx6(
|
|
981
|
+
"ul",
|
|
982
|
+
{
|
|
983
|
+
"data-slot": "sidebar-menu",
|
|
984
|
+
"data-sidebar": "menu",
|
|
985
|
+
className: cn("flex w-full min-w-0 flex-col gap-1", className),
|
|
986
|
+
...props
|
|
987
|
+
}
|
|
988
|
+
);
|
|
989
|
+
}
|
|
990
|
+
function SidebarMenuItem({ className, ...props }) {
|
|
991
|
+
return /* @__PURE__ */ jsx6(
|
|
992
|
+
"li",
|
|
993
|
+
{
|
|
994
|
+
"data-slot": "sidebar-menu-item",
|
|
995
|
+
"data-sidebar": "menu-item",
|
|
996
|
+
className: cn("group/menu-item relative", className),
|
|
997
|
+
...props
|
|
998
|
+
}
|
|
999
|
+
);
|
|
1000
|
+
}
|
|
1001
|
+
var sidebarMenuButtonVariants = cva2(
|
|
1002
|
+
"peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-hidden ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-data-[sidebar=menu-action]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0",
|
|
1003
|
+
{
|
|
1004
|
+
variants: {
|
|
1005
|
+
variant: {
|
|
1006
|
+
default: "hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
|
|
1007
|
+
outline: "bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]"
|
|
1008
|
+
},
|
|
1009
|
+
size: {
|
|
1010
|
+
default: "h-8 text-sm",
|
|
1011
|
+
sm: "h-7 text-xs",
|
|
1012
|
+
lg: "h-12 text-sm group-data-[collapsible=icon]:p-0!"
|
|
1013
|
+
}
|
|
1014
|
+
},
|
|
1015
|
+
defaultVariants: {
|
|
1016
|
+
variant: "default",
|
|
1017
|
+
size: "default"
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
);
|
|
1021
|
+
function SidebarMenuButton({
|
|
1022
|
+
asChild = false,
|
|
1023
|
+
isActive = false,
|
|
1024
|
+
variant = "default",
|
|
1025
|
+
size = "default",
|
|
1026
|
+
tooltip,
|
|
1027
|
+
className,
|
|
1028
|
+
...props
|
|
1029
|
+
}) {
|
|
1030
|
+
const Comp = asChild ? Slot2 : "button";
|
|
1031
|
+
const { isMobile, state } = useSidebar();
|
|
1032
|
+
const button = /* @__PURE__ */ jsx6(
|
|
1033
|
+
Comp,
|
|
1034
|
+
{
|
|
1035
|
+
"data-slot": "sidebar-menu-button",
|
|
1036
|
+
"data-sidebar": "menu-button",
|
|
1037
|
+
"data-size": size,
|
|
1038
|
+
"data-active": isActive,
|
|
1039
|
+
className: cn(sidebarMenuButtonVariants({ variant, size }), className),
|
|
1040
|
+
...props
|
|
1041
|
+
}
|
|
1042
|
+
);
|
|
1043
|
+
if (!tooltip) {
|
|
1044
|
+
return button;
|
|
1045
|
+
}
|
|
1046
|
+
if (typeof tooltip === "string") {
|
|
1047
|
+
tooltip = {
|
|
1048
|
+
children: tooltip
|
|
1049
|
+
};
|
|
1050
|
+
}
|
|
1051
|
+
return /* @__PURE__ */ jsxs3(Tooltip, { children: [
|
|
1052
|
+
/* @__PURE__ */ jsx6(TooltipTrigger, { asChild: true, children: button }),
|
|
1053
|
+
/* @__PURE__ */ jsx6(
|
|
1054
|
+
TooltipContent,
|
|
1055
|
+
{
|
|
1056
|
+
side: "right",
|
|
1057
|
+
align: "center",
|
|
1058
|
+
hidden: state !== "collapsed" || isMobile,
|
|
1059
|
+
...tooltip
|
|
1060
|
+
}
|
|
1061
|
+
)
|
|
1062
|
+
] });
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
// src/components/layout/AdminSidebar.tsx
|
|
1066
|
+
import {
|
|
1067
|
+
LayoutDashboard,
|
|
1068
|
+
MessageSquare,
|
|
1069
|
+
Users,
|
|
1070
|
+
Bot,
|
|
1071
|
+
Activity
|
|
1072
|
+
} from "lucide-react";
|
|
1073
|
+
import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1074
|
+
var NAV_ITEMS = [
|
|
1075
|
+
{
|
|
1076
|
+
page: "dashboard",
|
|
1077
|
+
label: "Dashboard",
|
|
1078
|
+
icon: LayoutDashboard
|
|
1079
|
+
},
|
|
1080
|
+
{
|
|
1081
|
+
page: "threads",
|
|
1082
|
+
label: "Threads",
|
|
1083
|
+
icon: MessageSquare,
|
|
1084
|
+
featureKey: "showThreads"
|
|
1085
|
+
},
|
|
1086
|
+
{
|
|
1087
|
+
page: "participants",
|
|
1088
|
+
label: "Participants",
|
|
1089
|
+
icon: Users,
|
|
1090
|
+
featureKey: "showParticipants"
|
|
1091
|
+
},
|
|
1092
|
+
{
|
|
1093
|
+
page: "agents",
|
|
1094
|
+
label: "Agents",
|
|
1095
|
+
icon: Bot,
|
|
1096
|
+
featureKey: "showAgents"
|
|
1097
|
+
},
|
|
1098
|
+
{
|
|
1099
|
+
page: "events",
|
|
1100
|
+
label: "Events",
|
|
1101
|
+
icon: Activity,
|
|
1102
|
+
featureKey: "showEvents"
|
|
1103
|
+
}
|
|
1104
|
+
];
|
|
1105
|
+
var AdminSidebar = ({
|
|
1106
|
+
config,
|
|
1107
|
+
currentPage,
|
|
1108
|
+
onNavigate
|
|
1109
|
+
}) => {
|
|
1110
|
+
const visibleItems = NAV_ITEMS.filter(
|
|
1111
|
+
(item) => !item.featureKey || config.features[item.featureKey]
|
|
1112
|
+
);
|
|
1113
|
+
return /* @__PURE__ */ jsxs4(Sidebar, { collapsible: config.sidebar.collapsible, children: [
|
|
1114
|
+
/* @__PURE__ */ jsx7(SidebarHeader, { children: /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-3 px-2 py-3", children: [
|
|
1115
|
+
/* @__PURE__ */ jsx7("div", { className: "flex items-center justify-center shrink-0", children: config.branding.logo || /* @__PURE__ */ jsx7("div", { className: "flex h-8 w-8 items-center justify-center rounded-lg bg-primary text-primary-foreground", children: /* @__PURE__ */ jsx7(LayoutDashboard, { className: "h-4 w-4" }) }) }),
|
|
1116
|
+
/* @__PURE__ */ jsxs4("div", { className: "flex flex-col min-w-0 group-data-[collapsible=icon]:hidden", children: [
|
|
1117
|
+
/* @__PURE__ */ jsx7("span", { className: "text-sm font-semibold truncate", children: config.branding.title }),
|
|
1118
|
+
config.branding.subtitle && /* @__PURE__ */ jsx7("span", { className: "text-xs text-muted-foreground truncate", children: config.branding.subtitle })
|
|
1119
|
+
] })
|
|
1120
|
+
] }) }),
|
|
1121
|
+
/* @__PURE__ */ jsx7(SidebarContent, { children: /* @__PURE__ */ jsxs4(SidebarGroup, { children: [
|
|
1122
|
+
/* @__PURE__ */ jsx7(SidebarGroupLabel, { className: "group-data-[collapsible=icon]:hidden", children: "Navigation" }),
|
|
1123
|
+
/* @__PURE__ */ jsx7(SidebarGroupContent, { children: /* @__PURE__ */ jsx7(SidebarMenu, { children: visibleItems.map((item) => {
|
|
1124
|
+
const Icon2 = item.icon;
|
|
1125
|
+
const label = config.labels[`${item.page}Title`] || item.label;
|
|
1126
|
+
return /* @__PURE__ */ jsx7(SidebarMenuItem, { children: /* @__PURE__ */ jsxs4(
|
|
1127
|
+
SidebarMenuButton,
|
|
1128
|
+
{
|
|
1129
|
+
isActive: currentPage === item.page,
|
|
1130
|
+
onClick: () => onNavigate(item.page),
|
|
1131
|
+
tooltip: label,
|
|
1132
|
+
children: [
|
|
1133
|
+
/* @__PURE__ */ jsx7(Icon2, {}),
|
|
1134
|
+
/* @__PURE__ */ jsx7("span", { children: label })
|
|
1135
|
+
]
|
|
1136
|
+
}
|
|
1137
|
+
) }, item.page);
|
|
1138
|
+
}) }) })
|
|
1139
|
+
] }) }),
|
|
1140
|
+
config.namespace && /* @__PURE__ */ jsx7(SidebarFooter, { children: /* @__PURE__ */ jsx7("div", { className: "px-2 py-2 text-xs text-muted-foreground group-data-[collapsible=icon]:hidden", children: /* @__PURE__ */ jsx7("span", { className: "font-medium uppercase tracking-[0.18em]", children: config.namespace }) }) }),
|
|
1141
|
+
/* @__PURE__ */ jsx7(SidebarRail, {})
|
|
1142
|
+
] });
|
|
1143
|
+
};
|
|
1144
|
+
|
|
1145
|
+
// src/components/layout/AdminHeader.tsx
|
|
1146
|
+
import { RefreshCw } from "lucide-react";
|
|
1147
|
+
|
|
1148
|
+
// src/components/ui/select.tsx
|
|
1149
|
+
import * as React4 from "react";
|
|
1150
|
+
import * as SelectPrimitive from "@radix-ui/react-select";
|
|
1151
|
+
import { Check, ChevronDown, ChevronUp } from "lucide-react";
|
|
1152
|
+
import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1153
|
+
var Select = SelectPrimitive.Root;
|
|
1154
|
+
var SelectValue = SelectPrimitive.Value;
|
|
1155
|
+
var SelectTrigger = React4.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs5(
|
|
1156
|
+
SelectPrimitive.Trigger,
|
|
1157
|
+
{
|
|
1158
|
+
ref,
|
|
1159
|
+
className: cn(
|
|
1160
|
+
"flex h-9 w-full items-center justify-between gap-2 rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-xs outline-none transition-colors placeholder:text-muted-foreground focus:ring-2 focus:ring-ring/40 disabled:cursor-not-allowed disabled:opacity-50",
|
|
1161
|
+
className
|
|
1162
|
+
),
|
|
1163
|
+
...props,
|
|
1164
|
+
children: [
|
|
1165
|
+
children,
|
|
1166
|
+
/* @__PURE__ */ jsx8(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ jsx8(ChevronDown, { className: "h-4 w-4 opacity-50" }) })
|
|
1167
|
+
]
|
|
1168
|
+
}
|
|
1169
|
+
));
|
|
1170
|
+
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
|
|
1171
|
+
var SelectContent = React4.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx8(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs5(
|
|
1172
|
+
SelectPrimitive.Content,
|
|
1173
|
+
{
|
|
1174
|
+
ref,
|
|
1175
|
+
className: cn(
|
|
1176
|
+
"relative z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md",
|
|
1177
|
+
position === "popper" && "translate-y-1",
|
|
1178
|
+
className
|
|
1179
|
+
),
|
|
1180
|
+
position,
|
|
1181
|
+
...props,
|
|
1182
|
+
children: [
|
|
1183
|
+
/* @__PURE__ */ jsx8(SelectPrimitive.ScrollUpButton, { className: "flex cursor-default items-center justify-center py-1", children: /* @__PURE__ */ jsx8(ChevronUp, { className: "h-4 w-4" }) }),
|
|
1184
|
+
/* @__PURE__ */ jsx8(
|
|
1185
|
+
SelectPrimitive.Viewport,
|
|
1186
|
+
{
|
|
1187
|
+
className: cn(
|
|
1188
|
+
"p-1",
|
|
1189
|
+
position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
|
|
1190
|
+
),
|
|
1191
|
+
children
|
|
1192
|
+
}
|
|
1193
|
+
),
|
|
1194
|
+
/* @__PURE__ */ jsx8(SelectPrimitive.ScrollDownButton, { className: "flex cursor-default items-center justify-center py-1", children: /* @__PURE__ */ jsx8(ChevronDown, { className: "h-4 w-4" }) })
|
|
1195
|
+
]
|
|
1196
|
+
}
|
|
1197
|
+
) }));
|
|
1198
|
+
SelectContent.displayName = SelectPrimitive.Content.displayName;
|
|
1199
|
+
var SelectItem = React4.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs5(
|
|
1200
|
+
SelectPrimitive.Item,
|
|
1201
|
+
{
|
|
1202
|
+
ref,
|
|
1203
|
+
className: cn(
|
|
1204
|
+
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
1205
|
+
className
|
|
1206
|
+
),
|
|
1207
|
+
...props,
|
|
1208
|
+
children: [
|
|
1209
|
+
/* @__PURE__ */ jsx8(SelectPrimitive.ItemText, { children }),
|
|
1210
|
+
/* @__PURE__ */ jsx8(SelectPrimitive.ItemIndicator, { className: "absolute right-2 inline-flex items-center justify-center", children: /* @__PURE__ */ jsx8(Check, { className: "h-4 w-4" }) })
|
|
1211
|
+
]
|
|
1212
|
+
}
|
|
1213
|
+
));
|
|
1214
|
+
SelectItem.displayName = SelectPrimitive.Item.displayName;
|
|
1215
|
+
|
|
1216
|
+
// src/components/layout/AdminHeader.tsx
|
|
1217
|
+
import { Fragment, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1218
|
+
var PAGE_TITLES = {
|
|
1219
|
+
dashboard: "Dashboard",
|
|
1220
|
+
threads: "Threads",
|
|
1221
|
+
"thread-detail": "Thread Detail",
|
|
1222
|
+
participants: "Participants",
|
|
1223
|
+
agents: "Agents",
|
|
1224
|
+
events: "Events"
|
|
1225
|
+
};
|
|
1226
|
+
var AdminHeader = ({
|
|
1227
|
+
config,
|
|
1228
|
+
currentPage,
|
|
1229
|
+
range,
|
|
1230
|
+
interval,
|
|
1231
|
+
onRangeChange,
|
|
1232
|
+
onIntervalChange,
|
|
1233
|
+
onRefresh,
|
|
1234
|
+
isLoading
|
|
1235
|
+
}) => {
|
|
1236
|
+
const pageTitle = config.labels[`${currentPage}Title`] || PAGE_TITLES[currentPage];
|
|
1237
|
+
return /* @__PURE__ */ jsx9(Card, { className: "py-0 border-b rounded-none relative z-10 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/80", children: /* @__PURE__ */ jsx9(CardHeader, { className: "p-2", children: /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between gap-2", children: [
|
|
1238
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-1", children: [
|
|
1239
|
+
/* @__PURE__ */ jsxs6(Tooltip, { children: [
|
|
1240
|
+
/* @__PURE__ */ jsx9(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx9(SidebarTrigger, { className: "-ml-1" }) }),
|
|
1241
|
+
/* @__PURE__ */ jsx9(TooltipContent, { children: "Toggle Sidebar" })
|
|
1242
|
+
] }),
|
|
1243
|
+
/* @__PURE__ */ jsx9("h1", { className: "text-sm font-medium ml-2", children: pageTitle })
|
|
1244
|
+
] }),
|
|
1245
|
+
/* @__PURE__ */ jsx9("div", { className: "flex-1" }),
|
|
1246
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-1", children: [
|
|
1247
|
+
currentPage === "dashboard" && /* @__PURE__ */ jsxs6(Fragment, { children: [
|
|
1248
|
+
/* @__PURE__ */ jsx9(
|
|
1249
|
+
Button,
|
|
1250
|
+
{
|
|
1251
|
+
variant: range === "24h" ? "default" : "ghost",
|
|
597
1252
|
size: "sm",
|
|
598
|
-
|
|
1253
|
+
className: "h-7 text-xs",
|
|
1254
|
+
onClick: () => onRangeChange("24h"),
|
|
599
1255
|
children: config.labels.range24h
|
|
600
1256
|
}
|
|
601
1257
|
),
|
|
602
|
-
/* @__PURE__ */
|
|
1258
|
+
/* @__PURE__ */ jsx9(
|
|
603
1259
|
Button,
|
|
604
1260
|
{
|
|
605
|
-
variant:
|
|
1261
|
+
variant: range === "7d" ? "default" : "ghost",
|
|
606
1262
|
size: "sm",
|
|
607
|
-
|
|
1263
|
+
className: "h-7 text-xs",
|
|
1264
|
+
onClick: () => onRangeChange("7d"),
|
|
608
1265
|
children: config.labels.range7d
|
|
609
1266
|
}
|
|
610
1267
|
),
|
|
611
|
-
/* @__PURE__ */
|
|
1268
|
+
/* @__PURE__ */ jsx9(
|
|
612
1269
|
Button,
|
|
613
1270
|
{
|
|
614
|
-
variant:
|
|
1271
|
+
variant: range === "30d" ? "default" : "ghost",
|
|
615
1272
|
size: "sm",
|
|
616
|
-
|
|
1273
|
+
className: "h-7 text-xs",
|
|
1274
|
+
onClick: () => onRangeChange("30d"),
|
|
617
1275
|
children: config.labels.range30d
|
|
618
1276
|
}
|
|
619
1277
|
),
|
|
620
|
-
/* @__PURE__ */
|
|
1278
|
+
/* @__PURE__ */ jsxs6(
|
|
621
1279
|
Select,
|
|
622
1280
|
{
|
|
623
|
-
value:
|
|
624
|
-
onValueChange: (v) =>
|
|
1281
|
+
value: interval,
|
|
1282
|
+
onValueChange: (v) => onIntervalChange(v),
|
|
625
1283
|
children: [
|
|
626
|
-
/* @__PURE__ */
|
|
627
|
-
/* @__PURE__ */
|
|
628
|
-
/* @__PURE__ */
|
|
629
|
-
/* @__PURE__ */
|
|
1284
|
+
/* @__PURE__ */ jsx9(SelectTrigger, { className: "h-7 w-[90px] text-xs", children: /* @__PURE__ */ jsx9(SelectValue, {}) }),
|
|
1285
|
+
/* @__PURE__ */ jsxs6(SelectContent, { children: [
|
|
1286
|
+
/* @__PURE__ */ jsx9(SelectItem, { value: "hour", children: config.labels.intervalHour }),
|
|
1287
|
+
/* @__PURE__ */ jsx9(SelectItem, { value: "day", children: config.labels.intervalDay })
|
|
630
1288
|
] })
|
|
631
1289
|
]
|
|
632
1290
|
}
|
|
633
|
-
)
|
|
634
|
-
|
|
1291
|
+
)
|
|
1292
|
+
] }),
|
|
1293
|
+
/* @__PURE__ */ jsxs6(Tooltip, { children: [
|
|
1294
|
+
/* @__PURE__ */ jsx9(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx9(
|
|
635
1295
|
Button,
|
|
636
1296
|
{
|
|
637
|
-
variant: "
|
|
638
|
-
size: "
|
|
639
|
-
|
|
640
|
-
|
|
1297
|
+
variant: "ghost",
|
|
1298
|
+
size: "icon",
|
|
1299
|
+
className: "h-7 w-7",
|
|
1300
|
+
onClick: onRefresh,
|
|
1301
|
+
disabled: isLoading,
|
|
1302
|
+
children: /* @__PURE__ */ jsx9(
|
|
1303
|
+
RefreshCw,
|
|
1304
|
+
{
|
|
1305
|
+
className: `h-4 w-4 ${isLoading ? "animate-spin" : ""}`
|
|
1306
|
+
}
|
|
1307
|
+
)
|
|
641
1308
|
}
|
|
642
|
-
),
|
|
643
|
-
config.
|
|
644
|
-
] })
|
|
1309
|
+
) }),
|
|
1310
|
+
/* @__PURE__ */ jsx9(TooltipContent, { children: config.labels.refresh })
|
|
1311
|
+
] }),
|
|
1312
|
+
config.branding.actions
|
|
1313
|
+
] })
|
|
1314
|
+
] }) }) });
|
|
1315
|
+
};
|
|
1316
|
+
|
|
1317
|
+
// src/components/ui/badge.tsx
|
|
1318
|
+
import { Slot as Slot3 } from "@radix-ui/react-slot";
|
|
1319
|
+
import { cva as cva3 } from "class-variance-authority";
|
|
1320
|
+
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
1321
|
+
var badgeVariants = cva3(
|
|
1322
|
+
"inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
|
|
1323
|
+
{
|
|
1324
|
+
variants: {
|
|
1325
|
+
variant: {
|
|
1326
|
+
default: "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
|
|
1327
|
+
secondary: "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
|
|
1328
|
+
destructive: "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
|
|
1329
|
+
outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground"
|
|
1330
|
+
}
|
|
1331
|
+
},
|
|
1332
|
+
defaultVariants: {
|
|
1333
|
+
variant: "default"
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1336
|
+
);
|
|
1337
|
+
function Badge({
|
|
1338
|
+
className,
|
|
1339
|
+
variant,
|
|
1340
|
+
asChild = false,
|
|
1341
|
+
...props
|
|
1342
|
+
}) {
|
|
1343
|
+
const Comp = asChild ? Slot3 : "span";
|
|
1344
|
+
return /* @__PURE__ */ jsx10(
|
|
1345
|
+
Comp,
|
|
1346
|
+
{
|
|
1347
|
+
"data-slot": "badge",
|
|
1348
|
+
className: cn(badgeVariants({ variant }), className),
|
|
1349
|
+
...props
|
|
1350
|
+
}
|
|
1351
|
+
);
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
// src/components/views/DashboardView.tsx
|
|
1355
|
+
import { jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1356
|
+
var DashboardView = ({
|
|
1357
|
+
config,
|
|
1358
|
+
overview,
|
|
1359
|
+
activity,
|
|
1360
|
+
threads,
|
|
1361
|
+
participants,
|
|
1362
|
+
agents,
|
|
1363
|
+
interval,
|
|
1364
|
+
threadSearch,
|
|
1365
|
+
participantSearch,
|
|
1366
|
+
agentSearch,
|
|
1367
|
+
onThreadSearchChange,
|
|
1368
|
+
onParticipantSearchChange,
|
|
1369
|
+
onAgentSearchChange,
|
|
1370
|
+
onThreadClick
|
|
1371
|
+
}) => {
|
|
1372
|
+
const cards = [
|
|
1373
|
+
{
|
|
1374
|
+
label: config.labels.messagesCard,
|
|
1375
|
+
value: overview?.messageTotals.total ?? 0,
|
|
1376
|
+
detail: `${overview?.messageTotals.toolCallMessages ?? 0} tool-call messages`
|
|
1377
|
+
},
|
|
1378
|
+
{
|
|
1379
|
+
label: config.labels.activeThreadsCard,
|
|
1380
|
+
value: overview?.threadTotals.active ?? 0,
|
|
1381
|
+
detail: `${overview?.threadTotals.total ?? 0} total threads`
|
|
1382
|
+
},
|
|
1383
|
+
{
|
|
1384
|
+
label: config.labels.participantsCard,
|
|
1385
|
+
value: overview?.participantTotals.total ?? 0,
|
|
1386
|
+
detail: `${overview?.participantTotals.agents ?? 0} agents`
|
|
1387
|
+
},
|
|
1388
|
+
{
|
|
1389
|
+
label: config.labels.tokensCard,
|
|
1390
|
+
value: overview?.llmTotals.totalTokens ?? 0,
|
|
1391
|
+
detail: `${overview?.llmTotals.totalCalls ?? 0} calls`
|
|
1392
|
+
},
|
|
1393
|
+
{
|
|
1394
|
+
label: config.labels.queueCard,
|
|
1395
|
+
value: overview?.queueTotals.pending ?? 0,
|
|
1396
|
+
detail: `${overview?.queueTotals.failed ?? 0} failed`
|
|
1397
|
+
}
|
|
1398
|
+
];
|
|
1399
|
+
const isEmpty = cards.every((card) => card.value === 0) && activity.length === 0 && threads.length === 0 && participants.length === 0 && agents.length === 0;
|
|
1400
|
+
return /* @__PURE__ */ jsxs7("div", { className: "space-y-6", children: [
|
|
1401
|
+
isEmpty && /* @__PURE__ */ jsxs7("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
|
|
1402
|
+
/* @__PURE__ */ jsx11("h3", { className: "text-lg font-semibold", children: config.labels.emptyTitle }),
|
|
1403
|
+
/* @__PURE__ */ jsx11("p", { className: "mt-2 text-sm text-muted-foreground", children: config.labels.emptyDescription })
|
|
645
1404
|
] }),
|
|
646
|
-
|
|
647
|
-
/* @__PURE__ */
|
|
648
|
-
/* @__PURE__ */
|
|
649
|
-
] }) : null,
|
|
650
|
-
config.features.showOverview ? /* @__PURE__ */ jsxs2("section", { className: "space-y-4", children: [
|
|
651
|
-
/* @__PURE__ */ jsx6(SectionHeading, { title: config.labels.overviewTitle }),
|
|
652
|
-
/* @__PURE__ */ jsx6("div", { className: "grid grid-cols-2 gap-4 md:grid-cols-3 lg:grid-cols-5", children: cards.map((card) => /* @__PURE__ */ jsxs2(
|
|
1405
|
+
config.features.showOverview && /* @__PURE__ */ jsxs7("section", { className: "space-y-4", children: [
|
|
1406
|
+
/* @__PURE__ */ jsx11(SectionHeading, { title: config.labels.overviewTitle }),
|
|
1407
|
+
/* @__PURE__ */ jsx11("div", { className: "grid grid-cols-2 gap-4 md:grid-cols-3 lg:grid-cols-5", children: cards.map((card) => /* @__PURE__ */ jsxs7(
|
|
653
1408
|
"div",
|
|
654
1409
|
{
|
|
655
|
-
className: "rounded-xl border bg-
|
|
1410
|
+
className: "rounded-xl border bg-card p-5 shadow-sm",
|
|
656
1411
|
children: [
|
|
657
|
-
/* @__PURE__ */
|
|
658
|
-
/* @__PURE__ */
|
|
659
|
-
/* @__PURE__ */
|
|
1412
|
+
/* @__PURE__ */ jsx11("p", { className: "text-sm font-medium text-muted-foreground", children: card.label }),
|
|
1413
|
+
/* @__PURE__ */ jsx11("p", { className: "mt-3 text-3xl font-semibold tracking-tight", children: formatNumber(card.value) }),
|
|
1414
|
+
/* @__PURE__ */ jsx11("p", { className: "mt-2 text-xs text-muted-foreground", children: card.detail })
|
|
660
1415
|
]
|
|
661
1416
|
},
|
|
662
1417
|
card.label
|
|
663
1418
|
)) })
|
|
664
|
-
] })
|
|
665
|
-
config.features.showActivity
|
|
666
|
-
/* @__PURE__ */
|
|
667
|
-
/* @__PURE__ */
|
|
1419
|
+
] }),
|
|
1420
|
+
config.features.showActivity && /* @__PURE__ */ jsxs7("section", { className: "space-y-4", children: [
|
|
1421
|
+
/* @__PURE__ */ jsx11(SectionHeading, { title: config.labels.activityTitle }),
|
|
1422
|
+
/* @__PURE__ */ jsx11(
|
|
668
1423
|
ActivityChart,
|
|
669
1424
|
{
|
|
670
|
-
interval
|
|
1425
|
+
interval,
|
|
671
1426
|
labels: config.labels,
|
|
672
1427
|
maxBars: config.ui.maxActivityBars,
|
|
673
|
-
points:
|
|
1428
|
+
points: activity
|
|
674
1429
|
}
|
|
675
1430
|
)
|
|
676
|
-
] })
|
|
677
|
-
/* @__PURE__ */
|
|
678
|
-
config.features.showThreads
|
|
1431
|
+
] }),
|
|
1432
|
+
/* @__PURE__ */ jsxs7("div", { className: "grid gap-6 lg:grid-cols-3", children: [
|
|
1433
|
+
config.features.showThreads && /* @__PURE__ */ jsx11(
|
|
679
1434
|
DataTable,
|
|
680
1435
|
{
|
|
681
|
-
rows:
|
|
1436
|
+
rows: threads,
|
|
682
1437
|
searchPlaceholder: config.labels.threadSearchPlaceholder,
|
|
683
1438
|
searchValue: threadSearch,
|
|
684
|
-
setSearchValue:
|
|
1439
|
+
setSearchValue: onThreadSearchChange,
|
|
685
1440
|
title: config.labels.threadsTitle,
|
|
686
|
-
children: /* @__PURE__ */
|
|
1441
|
+
children: /* @__PURE__ */ jsx11(
|
|
1442
|
+
ThreadsTable,
|
|
1443
|
+
{
|
|
1444
|
+
rows: threads,
|
|
1445
|
+
labels: config.labels,
|
|
1446
|
+
onThreadClick
|
|
1447
|
+
}
|
|
1448
|
+
)
|
|
687
1449
|
}
|
|
688
|
-
)
|
|
689
|
-
config.features.showParticipants
|
|
1450
|
+
),
|
|
1451
|
+
config.features.showParticipants && /* @__PURE__ */ jsx11(
|
|
690
1452
|
DataTable,
|
|
691
1453
|
{
|
|
692
|
-
rows:
|
|
1454
|
+
rows: participants,
|
|
693
1455
|
searchPlaceholder: config.labels.participantSearchPlaceholder,
|
|
694
1456
|
searchValue: participantSearch,
|
|
695
|
-
setSearchValue:
|
|
1457
|
+
setSearchValue: onParticipantSearchChange,
|
|
696
1458
|
title: config.labels.participantsTitle,
|
|
697
|
-
children: /* @__PURE__ */
|
|
698
|
-
ParticipantsTable,
|
|
699
|
-
{
|
|
700
|
-
rows: admin.participants,
|
|
701
|
-
labels: config.labels
|
|
702
|
-
}
|
|
703
|
-
)
|
|
1459
|
+
children: /* @__PURE__ */ jsx11(ParticipantsTable, { rows: participants, labels: config.labels })
|
|
704
1460
|
}
|
|
705
|
-
)
|
|
706
|
-
config.features.showAgents
|
|
1461
|
+
),
|
|
1462
|
+
config.features.showAgents && /* @__PURE__ */ jsx11(
|
|
707
1463
|
DataTable,
|
|
708
1464
|
{
|
|
709
|
-
rows:
|
|
1465
|
+
rows: agents,
|
|
710
1466
|
searchPlaceholder: config.labels.agentSearchPlaceholder,
|
|
711
1467
|
searchValue: agentSearch,
|
|
712
|
-
setSearchValue:
|
|
1468
|
+
setSearchValue: onAgentSearchChange,
|
|
713
1469
|
title: config.labels.agentsTitle,
|
|
714
|
-
children: /* @__PURE__ */
|
|
1470
|
+
children: /* @__PURE__ */ jsx11(AgentsTable, { rows: agents, labels: config.labels })
|
|
715
1471
|
}
|
|
716
|
-
)
|
|
1472
|
+
)
|
|
717
1473
|
] })
|
|
718
|
-
] })
|
|
1474
|
+
] });
|
|
719
1475
|
};
|
|
720
1476
|
function SectionHeading({ title }) {
|
|
721
|
-
return /* @__PURE__ */
|
|
1477
|
+
return /* @__PURE__ */ jsx11("h3", { className: "text-lg font-semibold tracking-tight", children: title });
|
|
722
1478
|
}
|
|
723
1479
|
function ActivityChart(props) {
|
|
724
1480
|
const trimmedPoints = props.points.slice(-props.maxBars);
|
|
@@ -726,12 +1482,12 @@ function ActivityChart(props) {
|
|
|
726
1482
|
...trimmedPoints.map((point) => point.messageCount),
|
|
727
1483
|
1
|
|
728
1484
|
);
|
|
729
|
-
return /* @__PURE__ */
|
|
1485
|
+
return /* @__PURE__ */ jsx11("div", { className: "rounded-xl border bg-card p-5 shadow-sm", children: trimmedPoints.length === 0 ? /* @__PURE__ */ jsx11("p", { className: "text-sm text-muted-foreground", children: props.labels.noResults }) : /* @__PURE__ */ jsx11("div", { className: "flex min-h-48 items-end gap-2", children: trimmedPoints.map((point) => /* @__PURE__ */ jsxs7(
|
|
730
1486
|
"div",
|
|
731
1487
|
{
|
|
732
1488
|
className: "flex min-w-0 flex-1 flex-col items-center gap-2",
|
|
733
1489
|
children: [
|
|
734
|
-
/* @__PURE__ */
|
|
1490
|
+
/* @__PURE__ */ jsx11("div", { className: "flex h-36 w-full items-end rounded-lg bg-muted px-1 pb-1", children: /* @__PURE__ */ jsx11(
|
|
735
1491
|
"div",
|
|
736
1492
|
{
|
|
737
1493
|
className: "w-full rounded-md bg-primary transition-all",
|
|
@@ -740,9 +1496,9 @@ function ActivityChart(props) {
|
|
|
740
1496
|
}
|
|
741
1497
|
}
|
|
742
1498
|
) }),
|
|
743
|
-
/* @__PURE__ */
|
|
744
|
-
/* @__PURE__ */
|
|
745
|
-
/* @__PURE__ */
|
|
1499
|
+
/* @__PURE__ */ jsxs7("div", { className: "text-center", children: [
|
|
1500
|
+
/* @__PURE__ */ jsx11("p", { className: "text-xs font-medium", children: formatBucket(point.bucket, props.interval) }),
|
|
1501
|
+
/* @__PURE__ */ jsxs7("p", { className: "text-[11px] text-muted-foreground", children: [
|
|
746
1502
|
formatNumber(point.messageCount),
|
|
747
1503
|
" msg"
|
|
748
1504
|
] })
|
|
@@ -753,10 +1509,10 @@ function ActivityChart(props) {
|
|
|
753
1509
|
)) }) });
|
|
754
1510
|
}
|
|
755
1511
|
function DataTable(props) {
|
|
756
|
-
return /* @__PURE__ */
|
|
757
|
-
/* @__PURE__ */
|
|
758
|
-
/* @__PURE__ */
|
|
759
|
-
/* @__PURE__ */
|
|
1512
|
+
return /* @__PURE__ */ jsxs7("div", { className: "rounded-xl border bg-card p-5 shadow-sm", children: [
|
|
1513
|
+
/* @__PURE__ */ jsxs7("div", { className: "mb-4 flex items-center justify-between gap-3", children: [
|
|
1514
|
+
/* @__PURE__ */ jsx11(SectionHeading, { title: props.title }),
|
|
1515
|
+
/* @__PURE__ */ jsx11(
|
|
760
1516
|
Input,
|
|
761
1517
|
{
|
|
762
1518
|
className: "h-8 w-full max-w-44",
|
|
@@ -766,24 +1522,29 @@ function DataTable(props) {
|
|
|
766
1522
|
}
|
|
767
1523
|
)
|
|
768
1524
|
] }),
|
|
769
|
-
props.rows.length === 0 ? /* @__PURE__ */
|
|
1525
|
+
props.rows.length === 0 ? /* @__PURE__ */ jsx11("p", { className: "text-sm text-muted-foreground", children: "No results" }) : props.children
|
|
770
1526
|
] });
|
|
771
1527
|
}
|
|
772
1528
|
function ThreadsTable({
|
|
773
1529
|
rows,
|
|
774
|
-
labels
|
|
1530
|
+
labels,
|
|
1531
|
+
onThreadClick
|
|
775
1532
|
}) {
|
|
776
|
-
return /* @__PURE__ */
|
|
1533
|
+
return /* @__PURE__ */ jsx11("div", { className: "space-y-3", children: rows.map((thread) => /* @__PURE__ */ jsxs7(
|
|
777
1534
|
"div",
|
|
778
1535
|
{
|
|
779
|
-
className:
|
|
1536
|
+
className: cn(
|
|
1537
|
+
"rounded-lg border bg-muted/50 p-4",
|
|
1538
|
+
onThreadClick && "cursor-pointer hover:bg-muted transition-colors"
|
|
1539
|
+
),
|
|
1540
|
+
onClick: () => onThreadClick?.(thread.threadId),
|
|
780
1541
|
children: [
|
|
781
|
-
/* @__PURE__ */
|
|
782
|
-
/* @__PURE__ */
|
|
783
|
-
/* @__PURE__ */
|
|
784
|
-
/* @__PURE__ */
|
|
1542
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex items-start justify-between gap-3", children: [
|
|
1543
|
+
/* @__PURE__ */ jsxs7("div", { className: "min-w-0", children: [
|
|
1544
|
+
/* @__PURE__ */ jsx11("p", { className: "font-medium", children: thread.name }),
|
|
1545
|
+
/* @__PURE__ */ jsx11("p", { className: "mt-1 truncate text-xs text-muted-foreground", children: thread.summary ?? thread.lastMessagePreview ?? "No summary yet" })
|
|
785
1546
|
] }),
|
|
786
|
-
/* @__PURE__ */
|
|
1547
|
+
/* @__PURE__ */ jsx11(
|
|
787
1548
|
Badge,
|
|
788
1549
|
{
|
|
789
1550
|
variant: thread.status === "archived" ? "secondary" : "default",
|
|
@@ -791,16 +1552,16 @@ function ThreadsTable({
|
|
|
791
1552
|
}
|
|
792
1553
|
)
|
|
793
1554
|
] }),
|
|
794
|
-
/* @__PURE__ */
|
|
795
|
-
/* @__PURE__ */
|
|
1555
|
+
/* @__PURE__ */ jsxs7("div", { className: "mt-3 flex flex-wrap gap-3 text-xs text-muted-foreground", children: [
|
|
1556
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
796
1557
|
formatNumber(thread.messageCount),
|
|
797
1558
|
" messages"
|
|
798
1559
|
] }),
|
|
799
|
-
/* @__PURE__ */
|
|
1560
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
800
1561
|
thread.participantIds.length,
|
|
801
1562
|
" participants"
|
|
802
1563
|
] }),
|
|
803
|
-
/* @__PURE__ */
|
|
1564
|
+
/* @__PURE__ */ jsx11("span", { children: formatDate(thread.lastActivityAt) })
|
|
804
1565
|
] })
|
|
805
1566
|
]
|
|
806
1567
|
},
|
|
@@ -811,28 +1572,28 @@ function ParticipantsTable({
|
|
|
811
1572
|
rows,
|
|
812
1573
|
labels
|
|
813
1574
|
}) {
|
|
814
|
-
return /* @__PURE__ */
|
|
1575
|
+
return /* @__PURE__ */ jsx11("div", { className: "space-y-3", children: rows.map((participant) => /* @__PURE__ */ jsxs7(
|
|
815
1576
|
"div",
|
|
816
1577
|
{
|
|
817
1578
|
className: "rounded-lg border bg-muted/50 p-4",
|
|
818
1579
|
children: [
|
|
819
|
-
/* @__PURE__ */
|
|
820
|
-
/* @__PURE__ */
|
|
821
|
-
/* @__PURE__ */
|
|
822
|
-
/* @__PURE__ */
|
|
1580
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex items-start justify-between gap-3", children: [
|
|
1581
|
+
/* @__PURE__ */ jsxs7("div", { className: "min-w-0", children: [
|
|
1582
|
+
/* @__PURE__ */ jsx11("p", { className: "font-medium", children: participant.displayName }),
|
|
1583
|
+
/* @__PURE__ */ jsx11("p", { className: "mt-1 text-xs uppercase tracking-[0.18em] text-muted-foreground", children: participant.participantType })
|
|
823
1584
|
] }),
|
|
824
|
-
/* @__PURE__ */
|
|
1585
|
+
/* @__PURE__ */ jsx11(Badge, { variant: "outline", children: participant.isGlobal ? labels.scopeGlobal : labels.scopeScoped })
|
|
825
1586
|
] }),
|
|
826
|
-
/* @__PURE__ */
|
|
827
|
-
/* @__PURE__ */
|
|
1587
|
+
/* @__PURE__ */ jsxs7("div", { className: "mt-3 flex flex-wrap gap-3 text-xs text-muted-foreground", children: [
|
|
1588
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
828
1589
|
formatNumber(participant.messageCount),
|
|
829
1590
|
" messages"
|
|
830
1591
|
] }),
|
|
831
|
-
/* @__PURE__ */
|
|
1592
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
832
1593
|
formatNumber(participant.threadCount),
|
|
833
1594
|
" threads"
|
|
834
1595
|
] }),
|
|
835
|
-
/* @__PURE__ */
|
|
1596
|
+
/* @__PURE__ */ jsx11("span", { children: formatDate(participant.lastActivityAt) })
|
|
836
1597
|
] })
|
|
837
1598
|
]
|
|
838
1599
|
},
|
|
@@ -843,32 +1604,32 @@ function AgentsTable({
|
|
|
843
1604
|
rows,
|
|
844
1605
|
labels
|
|
845
1606
|
}) {
|
|
846
|
-
return /* @__PURE__ */
|
|
1607
|
+
return /* @__PURE__ */ jsx11("div", { className: "space-y-3", children: rows.map((agent) => /* @__PURE__ */ jsxs7(
|
|
847
1608
|
"div",
|
|
848
1609
|
{
|
|
849
1610
|
className: "rounded-lg border bg-muted/50 p-4",
|
|
850
1611
|
children: [
|
|
851
|
-
/* @__PURE__ */
|
|
852
|
-
/* @__PURE__ */
|
|
853
|
-
/* @__PURE__ */
|
|
854
|
-
/* @__PURE__ */
|
|
1612
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex items-start justify-between gap-3", children: [
|
|
1613
|
+
/* @__PURE__ */ jsxs7("div", { className: "min-w-0", children: [
|
|
1614
|
+
/* @__PURE__ */ jsx11("p", { className: "font-medium", children: agent.displayName }),
|
|
1615
|
+
/* @__PURE__ */ jsx11("p", { className: "mt-1 truncate text-xs text-muted-foreground", children: agent.description ?? agent.agentId })
|
|
855
1616
|
] }),
|
|
856
|
-
/* @__PURE__ */
|
|
1617
|
+
/* @__PURE__ */ jsx11(Badge, { variant: "outline", children: agent.isConfigured ? labels.configured : labels.unconfigured })
|
|
857
1618
|
] }),
|
|
858
|
-
/* @__PURE__ */
|
|
859
|
-
/* @__PURE__ */
|
|
1619
|
+
/* @__PURE__ */ jsxs7("div", { className: "mt-3 grid grid-cols-2 gap-2 text-xs text-muted-foreground", children: [
|
|
1620
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
860
1621
|
formatNumber(agent.messageCount),
|
|
861
1622
|
" messages"
|
|
862
1623
|
] }),
|
|
863
|
-
/* @__PURE__ */
|
|
1624
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
864
1625
|
formatNumber(agent.llmCallCount),
|
|
865
1626
|
" LLM calls"
|
|
866
1627
|
] }),
|
|
867
|
-
/* @__PURE__ */
|
|
1628
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
868
1629
|
formatNumber(agent.toolCallMessageCount),
|
|
869
1630
|
" tool calls"
|
|
870
1631
|
] }),
|
|
871
|
-
/* @__PURE__ */
|
|
1632
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
872
1633
|
formatNumber(agent.totalTokens),
|
|
873
1634
|
" tokens"
|
|
874
1635
|
] })
|
|
@@ -904,6 +1665,484 @@ function formatDate(value) {
|
|
|
904
1665
|
function formatNumber(value) {
|
|
905
1666
|
return new Intl.NumberFormat().format(value);
|
|
906
1667
|
}
|
|
1668
|
+
|
|
1669
|
+
// src/components/views/ThreadsView.tsx
|
|
1670
|
+
import { Search, MessageSquare as MessageSquare2 } from "lucide-react";
|
|
1671
|
+
import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1672
|
+
var ThreadsView = ({
|
|
1673
|
+
config,
|
|
1674
|
+
threads,
|
|
1675
|
+
searchValue,
|
|
1676
|
+
onSearchChange,
|
|
1677
|
+
onThreadClick
|
|
1678
|
+
}) => {
|
|
1679
|
+
return /* @__PURE__ */ jsxs8("div", { className: "space-y-4", children: [
|
|
1680
|
+
/* @__PURE__ */ jsxs8("div", { className: "relative max-w-sm", children: [
|
|
1681
|
+
/* @__PURE__ */ jsx12(Search, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
|
|
1682
|
+
/* @__PURE__ */ jsx12(
|
|
1683
|
+
Input,
|
|
1684
|
+
{
|
|
1685
|
+
className: "pl-9",
|
|
1686
|
+
placeholder: config.labels.threadSearchPlaceholder,
|
|
1687
|
+
value: searchValue,
|
|
1688
|
+
onChange: (e) => onSearchChange(e.target.value)
|
|
1689
|
+
}
|
|
1690
|
+
)
|
|
1691
|
+
] }),
|
|
1692
|
+
threads.length === 0 ? /* @__PURE__ */ jsxs8("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
|
|
1693
|
+
/* @__PURE__ */ jsx12(MessageSquare2, { className: "mx-auto h-8 w-8 text-muted-foreground/50" }),
|
|
1694
|
+
/* @__PURE__ */ jsx12("p", { className: "mt-3 text-sm text-muted-foreground", children: searchValue ? config.labels.noResults : config.labels.emptyDescription })
|
|
1695
|
+
] }) : /* @__PURE__ */ jsx12("div", { className: "space-y-2", children: threads.map((thread) => /* @__PURE__ */ jsxs8(
|
|
1696
|
+
"div",
|
|
1697
|
+
{
|
|
1698
|
+
className: "flex items-center gap-4 rounded-lg border bg-card p-4 transition-colors hover:bg-muted/50 cursor-pointer",
|
|
1699
|
+
onClick: () => onThreadClick?.(thread.threadId),
|
|
1700
|
+
children: [
|
|
1701
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex-1 min-w-0", children: [
|
|
1702
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
|
|
1703
|
+
/* @__PURE__ */ jsx12("p", { className: "font-medium truncate", children: thread.name }),
|
|
1704
|
+
/* @__PURE__ */ jsx12(
|
|
1705
|
+
Badge,
|
|
1706
|
+
{
|
|
1707
|
+
variant: thread.status === "archived" ? "secondary" : "default",
|
|
1708
|
+
className: "shrink-0",
|
|
1709
|
+
children: thread.status === "archived" ? config.labels.statusArchived : config.labels.statusActive
|
|
1710
|
+
}
|
|
1711
|
+
)
|
|
1712
|
+
] }),
|
|
1713
|
+
/* @__PURE__ */ jsx12("p", { className: "mt-1 text-sm text-muted-foreground truncate", children: thread.summary ?? thread.lastMessagePreview ?? "No summary yet" })
|
|
1714
|
+
] }),
|
|
1715
|
+
/* @__PURE__ */ jsxs8("div", { className: "text-right text-xs text-muted-foreground shrink-0 space-y-1", children: [
|
|
1716
|
+
/* @__PURE__ */ jsxs8("p", { children: [
|
|
1717
|
+
formatNumber2(thread.messageCount),
|
|
1718
|
+
" messages"
|
|
1719
|
+
] }),
|
|
1720
|
+
/* @__PURE__ */ jsxs8("p", { children: [
|
|
1721
|
+
thread.participantIds.length,
|
|
1722
|
+
" participants"
|
|
1723
|
+
] }),
|
|
1724
|
+
/* @__PURE__ */ jsx12("p", { children: formatDate2(thread.lastActivityAt) })
|
|
1725
|
+
] })
|
|
1726
|
+
]
|
|
1727
|
+
},
|
|
1728
|
+
thread.threadId
|
|
1729
|
+
)) })
|
|
1730
|
+
] });
|
|
1731
|
+
};
|
|
1732
|
+
function formatDate2(value) {
|
|
1733
|
+
if (!value) return "No activity";
|
|
1734
|
+
const date = new Date(value);
|
|
1735
|
+
if (Number.isNaN(date.getTime())) return value;
|
|
1736
|
+
return date.toLocaleString(void 0, {
|
|
1737
|
+
month: "short",
|
|
1738
|
+
day: "numeric",
|
|
1739
|
+
hour: "numeric",
|
|
1740
|
+
minute: "2-digit"
|
|
1741
|
+
});
|
|
1742
|
+
}
|
|
1743
|
+
function formatNumber2(value) {
|
|
1744
|
+
return new Intl.NumberFormat().format(value);
|
|
1745
|
+
}
|
|
1746
|
+
|
|
1747
|
+
// src/components/views/ThreadDetailView.tsx
|
|
1748
|
+
import { useCallback as useCallback3, useEffect as useEffect5, useState as useState4 } from "react";
|
|
1749
|
+
import {
|
|
1750
|
+
ArrowLeft,
|
|
1751
|
+
Bot as Bot2,
|
|
1752
|
+
ChevronUp as ChevronUp2,
|
|
1753
|
+
Loader2,
|
|
1754
|
+
User,
|
|
1755
|
+
Wrench,
|
|
1756
|
+
Cpu
|
|
1757
|
+
} from "lucide-react";
|
|
1758
|
+
import { jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1759
|
+
var MESSAGES_PAGE_SIZE = 50;
|
|
1760
|
+
var ThreadDetailView = ({
|
|
1761
|
+
threadId,
|
|
1762
|
+
config,
|
|
1763
|
+
onBack
|
|
1764
|
+
}) => {
|
|
1765
|
+
const [thread, setThread] = useState4(null);
|
|
1766
|
+
const [messages, setMessages] = useState4([]);
|
|
1767
|
+
const [pageInfo, setPageInfo] = useState4(null);
|
|
1768
|
+
const [isLoading, setIsLoading] = useState4(true);
|
|
1769
|
+
const [isLoadingMore, setIsLoadingMore] = useState4(false);
|
|
1770
|
+
const [error, setError] = useState4(null);
|
|
1771
|
+
const fetchOptions = {
|
|
1772
|
+
baseUrl: config.baseUrl,
|
|
1773
|
+
getRequestHeaders: config.getRequestHeaders
|
|
1774
|
+
};
|
|
1775
|
+
const loadInitial = useCallback3(async () => {
|
|
1776
|
+
setIsLoading(true);
|
|
1777
|
+
setError(null);
|
|
1778
|
+
try {
|
|
1779
|
+
const [threadData, messagesData] = await Promise.all([
|
|
1780
|
+
fetchThreadDetail(threadId, fetchOptions),
|
|
1781
|
+
fetchThreadMessages(threadId, { limit: MESSAGES_PAGE_SIZE }, fetchOptions)
|
|
1782
|
+
]);
|
|
1783
|
+
setThread(threadData);
|
|
1784
|
+
setMessages(messagesData.data);
|
|
1785
|
+
setPageInfo(messagesData.pageInfo);
|
|
1786
|
+
} catch (err) {
|
|
1787
|
+
setError(
|
|
1788
|
+
err instanceof Error ? err : new Error("Failed to load thread")
|
|
1789
|
+
);
|
|
1790
|
+
} finally {
|
|
1791
|
+
setIsLoading(false);
|
|
1792
|
+
}
|
|
1793
|
+
}, [threadId, config.baseUrl, config.getRequestHeaders]);
|
|
1794
|
+
useEffect5(() => {
|
|
1795
|
+
void loadInitial();
|
|
1796
|
+
}, [loadInitial]);
|
|
1797
|
+
const loadMore = useCallback3(async () => {
|
|
1798
|
+
if (!pageInfo?.hasMoreBefore || !pageInfo.oldestMessageId || isLoadingMore) {
|
|
1799
|
+
return;
|
|
1800
|
+
}
|
|
1801
|
+
setIsLoadingMore(true);
|
|
1802
|
+
try {
|
|
1803
|
+
const older = await fetchThreadMessages(
|
|
1804
|
+
threadId,
|
|
1805
|
+
{ limit: MESSAGES_PAGE_SIZE, before: pageInfo.oldestMessageId },
|
|
1806
|
+
fetchOptions
|
|
1807
|
+
);
|
|
1808
|
+
setMessages((prev) => [...older.data, ...prev]);
|
|
1809
|
+
setPageInfo(older.pageInfo);
|
|
1810
|
+
} catch {
|
|
1811
|
+
} finally {
|
|
1812
|
+
setIsLoadingMore(false);
|
|
1813
|
+
}
|
|
1814
|
+
}, [threadId, pageInfo, isLoadingMore, config.baseUrl, config.getRequestHeaders]);
|
|
1815
|
+
if (isLoading) {
|
|
1816
|
+
return /* @__PURE__ */ jsx13("div", { className: "flex items-center justify-center py-20", children: /* @__PURE__ */ jsx13(Loader2, { className: "h-6 w-6 animate-spin text-muted-foreground" }) });
|
|
1817
|
+
}
|
|
1818
|
+
if (error) {
|
|
1819
|
+
return /* @__PURE__ */ jsxs9("div", { className: "space-y-4 py-10 text-center", children: [
|
|
1820
|
+
/* @__PURE__ */ jsx13("p", { className: "text-destructive font-medium", children: error.message }),
|
|
1821
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex justify-center gap-2", children: [
|
|
1822
|
+
/* @__PURE__ */ jsxs9(Button, { variant: "outline", onClick: onBack, children: [
|
|
1823
|
+
/* @__PURE__ */ jsx13(ArrowLeft, { className: "mr-2 h-4 w-4" }),
|
|
1824
|
+
"Back"
|
|
1825
|
+
] }),
|
|
1826
|
+
/* @__PURE__ */ jsx13(Button, { variant: "destructive", onClick: () => void loadInitial(), children: config.labels.retry })
|
|
1827
|
+
] })
|
|
1828
|
+
] });
|
|
1829
|
+
}
|
|
1830
|
+
return /* @__PURE__ */ jsxs9("div", { className: "space-y-6", children: [
|
|
1831
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex items-start gap-4", children: [
|
|
1832
|
+
/* @__PURE__ */ jsx13(
|
|
1833
|
+
Button,
|
|
1834
|
+
{
|
|
1835
|
+
variant: "ghost",
|
|
1836
|
+
size: "icon",
|
|
1837
|
+
className: "mt-1 shrink-0",
|
|
1838
|
+
onClick: onBack,
|
|
1839
|
+
children: /* @__PURE__ */ jsx13(ArrowLeft, { className: "h-4 w-4" })
|
|
1840
|
+
}
|
|
1841
|
+
),
|
|
1842
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex-1 min-w-0", children: [
|
|
1843
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2", children: [
|
|
1844
|
+
/* @__PURE__ */ jsx13("h2", { className: "text-xl font-semibold truncate", children: thread?.name ?? threadId }),
|
|
1845
|
+
/* @__PURE__ */ jsx13(
|
|
1846
|
+
Badge,
|
|
1847
|
+
{
|
|
1848
|
+
variant: thread?.status === "archived" ? "secondary" : "default",
|
|
1849
|
+
children: thread?.status === "archived" ? config.labels.statusArchived : config.labels.statusActive
|
|
1850
|
+
}
|
|
1851
|
+
)
|
|
1852
|
+
] }),
|
|
1853
|
+
thread?.summary && /* @__PURE__ */ jsx13("p", { className: "mt-1 text-sm text-muted-foreground", children: thread.summary }),
|
|
1854
|
+
/* @__PURE__ */ jsxs9("div", { className: "mt-2 flex flex-wrap gap-4 text-xs text-muted-foreground", children: [
|
|
1855
|
+
thread?.createdAt && /* @__PURE__ */ jsxs9("span", { children: [
|
|
1856
|
+
"Created ",
|
|
1857
|
+
formatDate3(thread.createdAt)
|
|
1858
|
+
] }),
|
|
1859
|
+
thread?.updatedAt && /* @__PURE__ */ jsxs9("span", { children: [
|
|
1860
|
+
"Updated ",
|
|
1861
|
+
formatDate3(thread.updatedAt)
|
|
1862
|
+
] }),
|
|
1863
|
+
thread?.participants && /* @__PURE__ */ jsxs9("span", { children: [
|
|
1864
|
+
thread.participants.length,
|
|
1865
|
+
" participants"
|
|
1866
|
+
] })
|
|
1867
|
+
] })
|
|
1868
|
+
] })
|
|
1869
|
+
] }),
|
|
1870
|
+
/* @__PURE__ */ jsxs9("div", { className: "space-y-1", children: [
|
|
1871
|
+
/* @__PURE__ */ jsx13("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsxs9("h3", { className: "text-sm font-medium text-muted-foreground", children: [
|
|
1872
|
+
"Messages (",
|
|
1873
|
+
messages.length,
|
|
1874
|
+
pageInfo?.hasMoreBefore ? "+" : "",
|
|
1875
|
+
")"
|
|
1876
|
+
] }) }),
|
|
1877
|
+
pageInfo?.hasMoreBefore && /* @__PURE__ */ jsx13("div", { className: "flex justify-center py-2", children: /* @__PURE__ */ jsxs9(
|
|
1878
|
+
Button,
|
|
1879
|
+
{
|
|
1880
|
+
variant: "ghost",
|
|
1881
|
+
size: "sm",
|
|
1882
|
+
onClick: () => void loadMore(),
|
|
1883
|
+
disabled: isLoadingMore,
|
|
1884
|
+
children: [
|
|
1885
|
+
isLoadingMore ? /* @__PURE__ */ jsx13(Loader2, { className: "mr-2 h-3 w-3 animate-spin" }) : /* @__PURE__ */ jsx13(ChevronUp2, { className: "mr-2 h-3 w-3" }),
|
|
1886
|
+
"Load older messages"
|
|
1887
|
+
]
|
|
1888
|
+
}
|
|
1889
|
+
) }),
|
|
1890
|
+
/* @__PURE__ */ jsx13("div", { className: "rounded-lg border bg-card", children: messages.length === 0 ? /* @__PURE__ */ jsx13("p", { className: "p-6 text-center text-sm text-muted-foreground", children: "No messages in this thread yet." }) : /* @__PURE__ */ jsx13("div", { className: "divide-y", children: messages.map((message) => /* @__PURE__ */ jsx13(MessageRow, { message }, message.id)) }) })
|
|
1891
|
+
] })
|
|
1892
|
+
] });
|
|
1893
|
+
};
|
|
1894
|
+
function MessageRow({ message }) {
|
|
1895
|
+
const [expanded, setExpanded] = useState4(false);
|
|
1896
|
+
const hasToolCalls = Array.isArray(message.toolCalls) && message.toolCalls.length > 0;
|
|
1897
|
+
const hasReasoning = !!message.reasoning;
|
|
1898
|
+
return /* @__PURE__ */ jsx13("div", { className: "px-4 py-3", children: /* @__PURE__ */ jsxs9("div", { className: "flex items-start gap-3", children: [
|
|
1899
|
+
/* @__PURE__ */ jsx13(SenderIcon, { senderType: message.senderType }),
|
|
1900
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex-1 min-w-0", children: [
|
|
1901
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2 text-xs", children: [
|
|
1902
|
+
/* @__PURE__ */ jsx13("span", { className: "font-medium", children: message.senderId ?? message.senderUserId ?? message.senderType }),
|
|
1903
|
+
/* @__PURE__ */ jsx13(Badge, { variant: "outline", className: "text-[10px] px-1.5 py-0", children: message.senderType }),
|
|
1904
|
+
message.createdAt && /* @__PURE__ */ jsx13("span", { className: "text-muted-foreground", children: formatTimestamp(message.createdAt) })
|
|
1905
|
+
] }),
|
|
1906
|
+
message.content && /* @__PURE__ */ jsx13("p", { className: "mt-1 text-sm whitespace-pre-wrap break-words", children: message.content }),
|
|
1907
|
+
(hasToolCalls || hasReasoning) && /* @__PURE__ */ jsxs9("div", { className: "mt-2 space-y-2", children: [
|
|
1908
|
+
hasToolCalls && /* @__PURE__ */ jsxs9(
|
|
1909
|
+
"button",
|
|
1910
|
+
{
|
|
1911
|
+
type: "button",
|
|
1912
|
+
onClick: () => setExpanded(!expanded),
|
|
1913
|
+
className: "inline-flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground transition-colors",
|
|
1914
|
+
children: [
|
|
1915
|
+
/* @__PURE__ */ jsx13(Wrench, { className: "h-3 w-3" }),
|
|
1916
|
+
message.toolCalls.length,
|
|
1917
|
+
" tool call",
|
|
1918
|
+
message.toolCalls.length > 1 ? "s" : ""
|
|
1919
|
+
]
|
|
1920
|
+
}
|
|
1921
|
+
),
|
|
1922
|
+
hasReasoning && /* @__PURE__ */ jsxs9(
|
|
1923
|
+
"button",
|
|
1924
|
+
{
|
|
1925
|
+
type: "button",
|
|
1926
|
+
onClick: () => setExpanded(!expanded),
|
|
1927
|
+
className: "inline-flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground transition-colors",
|
|
1928
|
+
children: [
|
|
1929
|
+
/* @__PURE__ */ jsx13(Cpu, { className: "h-3 w-3" }),
|
|
1930
|
+
"Reasoning"
|
|
1931
|
+
]
|
|
1932
|
+
}
|
|
1933
|
+
),
|
|
1934
|
+
expanded && /* @__PURE__ */ jsx13("pre", { className: "mt-2 rounded-md bg-muted p-3 text-xs overflow-auto max-h-60", children: JSON.stringify(
|
|
1935
|
+
{
|
|
1936
|
+
...hasToolCalls ? { toolCalls: message.toolCalls } : {},
|
|
1937
|
+
...hasReasoning ? { reasoning: message.reasoning } : {}
|
|
1938
|
+
},
|
|
1939
|
+
null,
|
|
1940
|
+
2
|
|
1941
|
+
) })
|
|
1942
|
+
] })
|
|
1943
|
+
] })
|
|
1944
|
+
] }) });
|
|
1945
|
+
}
|
|
1946
|
+
function SenderIcon({ senderType }) {
|
|
1947
|
+
const base = "flex h-7 w-7 shrink-0 items-center justify-center rounded-full";
|
|
1948
|
+
switch (senderType) {
|
|
1949
|
+
case "agent":
|
|
1950
|
+
return /* @__PURE__ */ jsx13("div", { className: cn(base, "bg-primary/10 text-primary"), children: /* @__PURE__ */ jsx13(Bot2, { className: "h-3.5 w-3.5" }) });
|
|
1951
|
+
case "user":
|
|
1952
|
+
return /* @__PURE__ */ jsx13("div", { className: cn(base, "bg-secondary text-secondary-foreground"), children: /* @__PURE__ */ jsx13(User, { className: "h-3.5 w-3.5" }) });
|
|
1953
|
+
case "tool":
|
|
1954
|
+
return /* @__PURE__ */ jsx13("div", { className: cn(base, "bg-muted text-muted-foreground"), children: /* @__PURE__ */ jsx13(Wrench, { className: "h-3.5 w-3.5" }) });
|
|
1955
|
+
default:
|
|
1956
|
+
return /* @__PURE__ */ jsx13("div", { className: cn(base, "bg-muted text-muted-foreground"), children: /* @__PURE__ */ jsx13(Cpu, { className: "h-3.5 w-3.5" }) });
|
|
1957
|
+
}
|
|
1958
|
+
}
|
|
1959
|
+
function formatDate3(value) {
|
|
1960
|
+
const date = new Date(value);
|
|
1961
|
+
if (Number.isNaN(date.getTime())) return value;
|
|
1962
|
+
return date.toLocaleDateString(void 0, {
|
|
1963
|
+
month: "short",
|
|
1964
|
+
day: "numeric",
|
|
1965
|
+
year: "numeric"
|
|
1966
|
+
});
|
|
1967
|
+
}
|
|
1968
|
+
function formatTimestamp(value) {
|
|
1969
|
+
const date = new Date(value);
|
|
1970
|
+
if (Number.isNaN(date.getTime())) return value;
|
|
1971
|
+
return date.toLocaleString(void 0, {
|
|
1972
|
+
month: "short",
|
|
1973
|
+
day: "numeric",
|
|
1974
|
+
hour: "numeric",
|
|
1975
|
+
minute: "2-digit",
|
|
1976
|
+
second: "2-digit"
|
|
1977
|
+
});
|
|
1978
|
+
}
|
|
1979
|
+
|
|
1980
|
+
// src/CopilotzAdmin.tsx
|
|
1981
|
+
import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1982
|
+
var CopilotzAdmin = ({
|
|
1983
|
+
config: userConfig,
|
|
1984
|
+
className
|
|
1985
|
+
}) => {
|
|
1986
|
+
const config = useMemo3(
|
|
1987
|
+
() => mergeAdminConfig(defaultAdminConfig, userConfig),
|
|
1988
|
+
[userConfig]
|
|
1989
|
+
);
|
|
1990
|
+
const [route, setRoute] = useState5({ page: config.defaultPage });
|
|
1991
|
+
const [threadSearch, setThreadSearch] = useState5("");
|
|
1992
|
+
const [participantSearch, setParticipantSearch] = useState5("");
|
|
1993
|
+
const [agentSearch, setAgentSearch] = useState5("");
|
|
1994
|
+
const deferredThreadSearch = useDeferredValue(threadSearch);
|
|
1995
|
+
const deferredParticipantSearch = useDeferredValue(participantSearch);
|
|
1996
|
+
const deferredAgentSearch = useDeferredValue(agentSearch);
|
|
1997
|
+
const admin = useCopilotzAdmin({
|
|
1998
|
+
baseUrl: config.baseUrl,
|
|
1999
|
+
getRequestHeaders: config.getRequestHeaders,
|
|
2000
|
+
namespace: config.namespace,
|
|
2001
|
+
range: config.initialRange,
|
|
2002
|
+
interval: config.initialInterval,
|
|
2003
|
+
threadSearch: deferredThreadSearch,
|
|
2004
|
+
participantSearch: deferredParticipantSearch,
|
|
2005
|
+
agentSearch: deferredAgentSearch
|
|
2006
|
+
});
|
|
2007
|
+
const navigate = useCallback4(
|
|
2008
|
+
(next) => {
|
|
2009
|
+
setRoute(next);
|
|
2010
|
+
config.onNavigate?.(next);
|
|
2011
|
+
},
|
|
2012
|
+
[config]
|
|
2013
|
+
);
|
|
2014
|
+
const handleSidebarNavigate = useCallback4(
|
|
2015
|
+
(page) => navigate({ page }),
|
|
2016
|
+
[navigate]
|
|
2017
|
+
);
|
|
2018
|
+
const handleThreadClick = useCallback4(
|
|
2019
|
+
(threadId) => navigate({ page: "thread-detail", resourceId: threadId }),
|
|
2020
|
+
[navigate]
|
|
2021
|
+
);
|
|
2022
|
+
const handleBackToThreads = useCallback4(
|
|
2023
|
+
() => navigate({ page: "threads" }),
|
|
2024
|
+
[navigate]
|
|
2025
|
+
);
|
|
2026
|
+
const sidebarPage = route.page === "thread-detail" ? "threads" : route.page;
|
|
2027
|
+
if (admin.isLoading && !admin.overview) {
|
|
2028
|
+
return /* @__PURE__ */ jsx14(Card, { className: cn("border-border", className), children: /* @__PURE__ */ jsx14(CardContent, { className: "text-muted-foreground flex items-center justify-center min-h-[200px]", children: config.labels.loading }) });
|
|
2029
|
+
}
|
|
2030
|
+
if (admin.error && !admin.overview) {
|
|
2031
|
+
return /* @__PURE__ */ jsx14(
|
|
2032
|
+
Card,
|
|
2033
|
+
{
|
|
2034
|
+
className: cn("border-destructive/50 bg-destructive/10", className),
|
|
2035
|
+
children: /* @__PURE__ */ jsxs10(CardContent, { className: "space-y-4", children: [
|
|
2036
|
+
/* @__PURE__ */ jsx14("p", { className: "text-base font-semibold text-destructive", children: admin.error.message }),
|
|
2037
|
+
/* @__PURE__ */ jsx14(
|
|
2038
|
+
Button,
|
|
2039
|
+
{
|
|
2040
|
+
variant: "destructive",
|
|
2041
|
+
onClick: () => void admin.refresh(),
|
|
2042
|
+
children: config.labels.retry
|
|
2043
|
+
}
|
|
2044
|
+
)
|
|
2045
|
+
] })
|
|
2046
|
+
}
|
|
2047
|
+
);
|
|
2048
|
+
}
|
|
2049
|
+
const renderCurrentView = () => {
|
|
2050
|
+
switch (route.page) {
|
|
2051
|
+
case "dashboard":
|
|
2052
|
+
return /* @__PURE__ */ jsx14(
|
|
2053
|
+
DashboardView,
|
|
2054
|
+
{
|
|
2055
|
+
config,
|
|
2056
|
+
overview: admin.overview,
|
|
2057
|
+
activity: admin.activity,
|
|
2058
|
+
threads: admin.threads,
|
|
2059
|
+
participants: admin.participants,
|
|
2060
|
+
agents: admin.agents,
|
|
2061
|
+
interval: admin.filters.interval,
|
|
2062
|
+
threadSearch,
|
|
2063
|
+
participantSearch,
|
|
2064
|
+
agentSearch,
|
|
2065
|
+
onThreadSearchChange: setThreadSearch,
|
|
2066
|
+
onParticipantSearchChange: setParticipantSearch,
|
|
2067
|
+
onAgentSearchChange: setAgentSearch,
|
|
2068
|
+
onThreadClick: handleThreadClick
|
|
2069
|
+
}
|
|
2070
|
+
);
|
|
2071
|
+
case "threads":
|
|
2072
|
+
return /* @__PURE__ */ jsx14(
|
|
2073
|
+
ThreadsView,
|
|
2074
|
+
{
|
|
2075
|
+
config,
|
|
2076
|
+
threads: admin.threads,
|
|
2077
|
+
searchValue: threadSearch,
|
|
2078
|
+
onSearchChange: setThreadSearch,
|
|
2079
|
+
onThreadClick: handleThreadClick
|
|
2080
|
+
}
|
|
2081
|
+
);
|
|
2082
|
+
case "thread-detail":
|
|
2083
|
+
return route.resourceId ? /* @__PURE__ */ jsx14(
|
|
2084
|
+
ThreadDetailView,
|
|
2085
|
+
{
|
|
2086
|
+
threadId: route.resourceId,
|
|
2087
|
+
config,
|
|
2088
|
+
onBack: handleBackToThreads
|
|
2089
|
+
}
|
|
2090
|
+
) : null;
|
|
2091
|
+
case "participants":
|
|
2092
|
+
return /* @__PURE__ */ jsxs10("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
|
|
2093
|
+
/* @__PURE__ */ jsx14("h3", { className: "text-lg font-semibold", children: config.labels.participantsTitle }),
|
|
2094
|
+
/* @__PURE__ */ jsx14("p", { className: "mt-2 text-sm text-muted-foreground", children: "Detailed participant management coming soon." })
|
|
2095
|
+
] });
|
|
2096
|
+
case "agents":
|
|
2097
|
+
return /* @__PURE__ */ jsxs10("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
|
|
2098
|
+
/* @__PURE__ */ jsx14("h3", { className: "text-lg font-semibold", children: config.labels.agentsTitle }),
|
|
2099
|
+
/* @__PURE__ */ jsx14("p", { className: "mt-2 text-sm text-muted-foreground", children: "Agent configuration management coming soon." })
|
|
2100
|
+
] });
|
|
2101
|
+
case "events":
|
|
2102
|
+
return /* @__PURE__ */ jsxs10("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
|
|
2103
|
+
/* @__PURE__ */ jsx14("h3", { className: "text-lg font-semibold", children: config.labels.eventsTitle }),
|
|
2104
|
+
/* @__PURE__ */ jsx14("p", { className: "mt-2 text-sm text-muted-foreground", children: "Event inspector coming soon." })
|
|
2105
|
+
] });
|
|
2106
|
+
default:
|
|
2107
|
+
return null;
|
|
2108
|
+
}
|
|
2109
|
+
};
|
|
2110
|
+
return /* @__PURE__ */ jsx14(TooltipProvider, { children: /* @__PURE__ */ jsx14(SidebarProvider, { defaultOpen: config.sidebar.defaultOpen, children: /* @__PURE__ */ jsxs10(
|
|
2111
|
+
"div",
|
|
2112
|
+
{
|
|
2113
|
+
className: cn(
|
|
2114
|
+
"flex h-[100svh] md:h-screen bg-background w-full overflow-hidden",
|
|
2115
|
+
className
|
|
2116
|
+
),
|
|
2117
|
+
children: [
|
|
2118
|
+
/* @__PURE__ */ jsx14(
|
|
2119
|
+
AdminSidebar,
|
|
2120
|
+
{
|
|
2121
|
+
config,
|
|
2122
|
+
currentPage: sidebarPage,
|
|
2123
|
+
onNavigate: handleSidebarNavigate
|
|
2124
|
+
}
|
|
2125
|
+
),
|
|
2126
|
+
/* @__PURE__ */ jsx14(SidebarInset, { children: /* @__PURE__ */ jsxs10("div", { className: "flex flex-col h-full min-h-0", children: [
|
|
2127
|
+
/* @__PURE__ */ jsx14(
|
|
2128
|
+
AdminHeader,
|
|
2129
|
+
{
|
|
2130
|
+
config,
|
|
2131
|
+
currentPage: route.page,
|
|
2132
|
+
range: admin.filters.range,
|
|
2133
|
+
interval: admin.filters.interval,
|
|
2134
|
+
onRangeChange: admin.setRange,
|
|
2135
|
+
onIntervalChange: admin.setInterval,
|
|
2136
|
+
onRefresh: () => void admin.refresh(),
|
|
2137
|
+
isLoading: admin.isLoading
|
|
2138
|
+
}
|
|
2139
|
+
),
|
|
2140
|
+
/* @__PURE__ */ jsx14("div", { className: "flex-1 overflow-auto p-6", children: renderCurrentView() })
|
|
2141
|
+
] }) })
|
|
2142
|
+
]
|
|
2143
|
+
}
|
|
2144
|
+
) }) });
|
|
2145
|
+
};
|
|
907
2146
|
export {
|
|
908
2147
|
CopilotzAdmin,
|
|
909
2148
|
defaultAdminConfig,
|