@copilotz/admin 0.3.5 → 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 +1526 -295
- 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 +1543 -297
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1432 -111
- 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,319 +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
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
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
|
+
)
|
|
600
806
|
}
|
|
601
807
|
),
|
|
602
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",
|
|
1252
|
+
size: "sm",
|
|
1253
|
+
className: "h-7 text-xs",
|
|
1254
|
+
onClick: () => onRangeChange("24h"),
|
|
1255
|
+
children: config.labels.range24h
|
|
1256
|
+
}
|
|
1257
|
+
),
|
|
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 })
|
|
1404
|
+
] }),
|
|
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(
|
|
1408
|
+
"div",
|
|
1409
|
+
{
|
|
1410
|
+
className: "rounded-xl border bg-card p-5 shadow-sm",
|
|
1411
|
+
children: [
|
|
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 })
|
|
1415
|
+
]
|
|
1416
|
+
},
|
|
1417
|
+
card.label
|
|
1418
|
+
)) })
|
|
645
1419
|
] }),
|
|
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 gap-4 md:grid-cols-2 xl:grid-cols-5", children: cards.map((card) => /* @__PURE__ */ jsx6(Card, { className: "gap-0 py-0", children: /* @__PURE__ */ jsxs2(CardContent, { className: "p-5", children: [
|
|
653
|
-
/* @__PURE__ */ jsx6("p", { className: "text-sm font-medium text-muted-foreground", children: card.label }),
|
|
654
|
-
/* @__PURE__ */ jsx6("p", { className: "mt-3 text-3xl font-semibold tracking-tight", children: formatNumber(card.value) }),
|
|
655
|
-
/* @__PURE__ */ jsx6("p", { className: "mt-2 text-xs text-muted-foreground", children: card.detail })
|
|
656
|
-
] }) }, card.label)) })
|
|
657
|
-
] }) : null,
|
|
658
|
-
config.features.showActivity ? /* @__PURE__ */ jsxs2("section", { className: "space-y-4", children: [
|
|
659
|
-
/* @__PURE__ */ jsx6(SectionHeading, { title: config.labels.activityTitle }),
|
|
660
|
-
/* @__PURE__ */ jsx6(
|
|
1420
|
+
config.features.showActivity && /* @__PURE__ */ jsxs7("section", { className: "space-y-4", children: [
|
|
1421
|
+
/* @__PURE__ */ jsx11(SectionHeading, { title: config.labels.activityTitle }),
|
|
1422
|
+
/* @__PURE__ */ jsx11(
|
|
661
1423
|
ActivityChart,
|
|
662
1424
|
{
|
|
663
|
-
interval
|
|
1425
|
+
interval,
|
|
664
1426
|
labels: config.labels,
|
|
665
1427
|
maxBars: config.ui.maxActivityBars,
|
|
666
|
-
points:
|
|
1428
|
+
points: activity
|
|
667
1429
|
}
|
|
668
1430
|
)
|
|
669
|
-
] })
|
|
670
|
-
/* @__PURE__ */
|
|
671
|
-
config.features.showThreads
|
|
1431
|
+
] }),
|
|
1432
|
+
/* @__PURE__ */ jsxs7("div", { className: "grid gap-6 lg:grid-cols-3", children: [
|
|
1433
|
+
config.features.showThreads && /* @__PURE__ */ jsx11(
|
|
672
1434
|
DataTable,
|
|
673
1435
|
{
|
|
674
|
-
rows:
|
|
1436
|
+
rows: threads,
|
|
675
1437
|
searchPlaceholder: config.labels.threadSearchPlaceholder,
|
|
676
1438
|
searchValue: threadSearch,
|
|
677
|
-
setSearchValue:
|
|
1439
|
+
setSearchValue: onThreadSearchChange,
|
|
678
1440
|
title: config.labels.threadsTitle,
|
|
679
|
-
children: /* @__PURE__ */
|
|
1441
|
+
children: /* @__PURE__ */ jsx11(
|
|
1442
|
+
ThreadsTable,
|
|
1443
|
+
{
|
|
1444
|
+
rows: threads,
|
|
1445
|
+
labels: config.labels,
|
|
1446
|
+
onThreadClick
|
|
1447
|
+
}
|
|
1448
|
+
)
|
|
680
1449
|
}
|
|
681
|
-
)
|
|
682
|
-
config.features.showParticipants
|
|
1450
|
+
),
|
|
1451
|
+
config.features.showParticipants && /* @__PURE__ */ jsx11(
|
|
683
1452
|
DataTable,
|
|
684
1453
|
{
|
|
685
|
-
rows:
|
|
1454
|
+
rows: participants,
|
|
686
1455
|
searchPlaceholder: config.labels.participantSearchPlaceholder,
|
|
687
1456
|
searchValue: participantSearch,
|
|
688
|
-
setSearchValue:
|
|
1457
|
+
setSearchValue: onParticipantSearchChange,
|
|
689
1458
|
title: config.labels.participantsTitle,
|
|
690
|
-
children: /* @__PURE__ */
|
|
691
|
-
ParticipantsTable,
|
|
692
|
-
{
|
|
693
|
-
rows: admin.participants,
|
|
694
|
-
labels: config.labels
|
|
695
|
-
}
|
|
696
|
-
)
|
|
1459
|
+
children: /* @__PURE__ */ jsx11(ParticipantsTable, { rows: participants, labels: config.labels })
|
|
697
1460
|
}
|
|
698
|
-
)
|
|
699
|
-
config.features.showAgents
|
|
1461
|
+
),
|
|
1462
|
+
config.features.showAgents && /* @__PURE__ */ jsx11(
|
|
700
1463
|
DataTable,
|
|
701
1464
|
{
|
|
702
|
-
rows:
|
|
1465
|
+
rows: agents,
|
|
703
1466
|
searchPlaceholder: config.labels.agentSearchPlaceholder,
|
|
704
1467
|
searchValue: agentSearch,
|
|
705
|
-
setSearchValue:
|
|
1468
|
+
setSearchValue: onAgentSearchChange,
|
|
706
1469
|
title: config.labels.agentsTitle,
|
|
707
|
-
children: /* @__PURE__ */
|
|
1470
|
+
children: /* @__PURE__ */ jsx11(AgentsTable, { rows: agents, labels: config.labels })
|
|
708
1471
|
}
|
|
709
|
-
)
|
|
1472
|
+
)
|
|
710
1473
|
] })
|
|
711
1474
|
] });
|
|
712
1475
|
};
|
|
713
1476
|
function SectionHeading({ title }) {
|
|
714
|
-
return /* @__PURE__ */
|
|
1477
|
+
return /* @__PURE__ */ jsx11("h3", { className: "text-lg font-semibold tracking-tight", children: title });
|
|
715
1478
|
}
|
|
716
1479
|
function ActivityChart(props) {
|
|
717
1480
|
const trimmedPoints = props.points.slice(-props.maxBars);
|
|
@@ -719,23 +1482,23 @@ function ActivityChart(props) {
|
|
|
719
1482
|
...trimmedPoints.map((point) => point.messageCount),
|
|
720
1483
|
1
|
|
721
1484
|
);
|
|
722
|
-
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(
|
|
723
1486
|
"div",
|
|
724
1487
|
{
|
|
725
1488
|
className: "flex min-w-0 flex-1 flex-col items-center gap-2",
|
|
726
1489
|
children: [
|
|
727
|
-
/* @__PURE__ */
|
|
1490
|
+
/* @__PURE__ */ jsx11("div", { className: "flex h-36 w-full items-end rounded-lg bg-muted px-1 pb-1", children: /* @__PURE__ */ jsx11(
|
|
728
1491
|
"div",
|
|
729
1492
|
{
|
|
730
|
-
className: "w-full rounded-md bg-primary",
|
|
1493
|
+
className: "w-full rounded-md bg-primary transition-all",
|
|
731
1494
|
style: {
|
|
732
1495
|
height: `${Math.max(point.messageCount / maxMessages * 100, 8)}%`
|
|
733
1496
|
}
|
|
734
1497
|
}
|
|
735
1498
|
) }),
|
|
736
|
-
/* @__PURE__ */
|
|
737
|
-
/* @__PURE__ */
|
|
738
|
-
/* @__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: [
|
|
739
1502
|
formatNumber(point.messageCount),
|
|
740
1503
|
" msg"
|
|
741
1504
|
] })
|
|
@@ -743,40 +1506,45 @@ function ActivityChart(props) {
|
|
|
743
1506
|
]
|
|
744
1507
|
},
|
|
745
1508
|
point.bucket
|
|
746
|
-
)) }) })
|
|
1509
|
+
)) }) });
|
|
747
1510
|
}
|
|
748
1511
|
function DataTable(props) {
|
|
749
|
-
return /* @__PURE__ */
|
|
750
|
-
/* @__PURE__ */
|
|
751
|
-
/* @__PURE__ */
|
|
752
|
-
/* @__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(
|
|
753
1516
|
Input,
|
|
754
1517
|
{
|
|
755
|
-
className: "w-full max-w-44
|
|
1518
|
+
className: "h-8 w-full max-w-44",
|
|
756
1519
|
onChange: (event) => props.setSearchValue(event.target.value),
|
|
757
1520
|
placeholder: props.searchPlaceholder,
|
|
758
1521
|
value: props.searchValue
|
|
759
1522
|
}
|
|
760
1523
|
)
|
|
761
1524
|
] }),
|
|
762
|
-
props.rows.length === 0 ? /* @__PURE__ */
|
|
763
|
-
] })
|
|
1525
|
+
props.rows.length === 0 ? /* @__PURE__ */ jsx11("p", { className: "text-sm text-muted-foreground", children: "No results" }) : props.children
|
|
1526
|
+
] });
|
|
764
1527
|
}
|
|
765
1528
|
function ThreadsTable({
|
|
766
1529
|
rows,
|
|
767
|
-
labels
|
|
1530
|
+
labels,
|
|
1531
|
+
onThreadClick
|
|
768
1532
|
}) {
|
|
769
|
-
return /* @__PURE__ */
|
|
1533
|
+
return /* @__PURE__ */ jsx11("div", { className: "space-y-3", children: rows.map((thread) => /* @__PURE__ */ jsxs7(
|
|
770
1534
|
"div",
|
|
771
1535
|
{
|
|
772
|
-
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),
|
|
773
1541
|
children: [
|
|
774
|
-
/* @__PURE__ */
|
|
775
|
-
/* @__PURE__ */
|
|
776
|
-
/* @__PURE__ */
|
|
777
|
-
/* @__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" })
|
|
778
1546
|
] }),
|
|
779
|
-
/* @__PURE__ */
|
|
1547
|
+
/* @__PURE__ */ jsx11(
|
|
780
1548
|
Badge,
|
|
781
1549
|
{
|
|
782
1550
|
variant: thread.status === "archived" ? "secondary" : "default",
|
|
@@ -784,16 +1552,16 @@ function ThreadsTable({
|
|
|
784
1552
|
}
|
|
785
1553
|
)
|
|
786
1554
|
] }),
|
|
787
|
-
/* @__PURE__ */
|
|
788
|
-
/* @__PURE__ */
|
|
1555
|
+
/* @__PURE__ */ jsxs7("div", { className: "mt-3 flex flex-wrap gap-3 text-xs text-muted-foreground", children: [
|
|
1556
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
789
1557
|
formatNumber(thread.messageCount),
|
|
790
1558
|
" messages"
|
|
791
1559
|
] }),
|
|
792
|
-
/* @__PURE__ */
|
|
1560
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
793
1561
|
thread.participantIds.length,
|
|
794
1562
|
" participants"
|
|
795
1563
|
] }),
|
|
796
|
-
/* @__PURE__ */
|
|
1564
|
+
/* @__PURE__ */ jsx11("span", { children: formatDate(thread.lastActivityAt) })
|
|
797
1565
|
] })
|
|
798
1566
|
]
|
|
799
1567
|
},
|
|
@@ -804,28 +1572,28 @@ function ParticipantsTable({
|
|
|
804
1572
|
rows,
|
|
805
1573
|
labels
|
|
806
1574
|
}) {
|
|
807
|
-
return /* @__PURE__ */
|
|
1575
|
+
return /* @__PURE__ */ jsx11("div", { className: "space-y-3", children: rows.map((participant) => /* @__PURE__ */ jsxs7(
|
|
808
1576
|
"div",
|
|
809
1577
|
{
|
|
810
1578
|
className: "rounded-lg border bg-muted/50 p-4",
|
|
811
1579
|
children: [
|
|
812
|
-
/* @__PURE__ */
|
|
813
|
-
/* @__PURE__ */
|
|
814
|
-
/* @__PURE__ */
|
|
815
|
-
/* @__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 })
|
|
816
1584
|
] }),
|
|
817
|
-
/* @__PURE__ */
|
|
1585
|
+
/* @__PURE__ */ jsx11(Badge, { variant: "outline", children: participant.isGlobal ? labels.scopeGlobal : labels.scopeScoped })
|
|
818
1586
|
] }),
|
|
819
|
-
/* @__PURE__ */
|
|
820
|
-
/* @__PURE__ */
|
|
1587
|
+
/* @__PURE__ */ jsxs7("div", { className: "mt-3 flex flex-wrap gap-3 text-xs text-muted-foreground", children: [
|
|
1588
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
821
1589
|
formatNumber(participant.messageCount),
|
|
822
1590
|
" messages"
|
|
823
1591
|
] }),
|
|
824
|
-
/* @__PURE__ */
|
|
1592
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
825
1593
|
formatNumber(participant.threadCount),
|
|
826
1594
|
" threads"
|
|
827
1595
|
] }),
|
|
828
|
-
/* @__PURE__ */
|
|
1596
|
+
/* @__PURE__ */ jsx11("span", { children: formatDate(participant.lastActivityAt) })
|
|
829
1597
|
] })
|
|
830
1598
|
]
|
|
831
1599
|
},
|
|
@@ -836,32 +1604,32 @@ function AgentsTable({
|
|
|
836
1604
|
rows,
|
|
837
1605
|
labels
|
|
838
1606
|
}) {
|
|
839
|
-
return /* @__PURE__ */
|
|
1607
|
+
return /* @__PURE__ */ jsx11("div", { className: "space-y-3", children: rows.map((agent) => /* @__PURE__ */ jsxs7(
|
|
840
1608
|
"div",
|
|
841
1609
|
{
|
|
842
1610
|
className: "rounded-lg border bg-muted/50 p-4",
|
|
843
1611
|
children: [
|
|
844
|
-
/* @__PURE__ */
|
|
845
|
-
/* @__PURE__ */
|
|
846
|
-
/* @__PURE__ */
|
|
847
|
-
/* @__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 })
|
|
848
1616
|
] }),
|
|
849
|
-
/* @__PURE__ */
|
|
1617
|
+
/* @__PURE__ */ jsx11(Badge, { variant: "outline", children: agent.isConfigured ? labels.configured : labels.unconfigured })
|
|
850
1618
|
] }),
|
|
851
|
-
/* @__PURE__ */
|
|
852
|
-
/* @__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: [
|
|
853
1621
|
formatNumber(agent.messageCount),
|
|
854
1622
|
" messages"
|
|
855
1623
|
] }),
|
|
856
|
-
/* @__PURE__ */
|
|
1624
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
857
1625
|
formatNumber(agent.llmCallCount),
|
|
858
1626
|
" LLM calls"
|
|
859
1627
|
] }),
|
|
860
|
-
/* @__PURE__ */
|
|
1628
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
861
1629
|
formatNumber(agent.toolCallMessageCount),
|
|
862
1630
|
" tool calls"
|
|
863
1631
|
] }),
|
|
864
|
-
/* @__PURE__ */
|
|
1632
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
865
1633
|
formatNumber(agent.totalTokens),
|
|
866
1634
|
" tokens"
|
|
867
1635
|
] })
|
|
@@ -897,6 +1665,484 @@ function formatDate(value) {
|
|
|
897
1665
|
function formatNumber(value) {
|
|
898
1666
|
return new Intl.NumberFormat().format(value);
|
|
899
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
|
+
};
|
|
900
2146
|
export {
|
|
901
2147
|
CopilotzAdmin,
|
|
902
2148
|
defaultAdminConfig,
|