@agent-native/dispatch 0.19.1 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/actions/provider-api-register.d.ts +9 -9
- package/dist/components/admin-navigation.d.ts +2 -1
- package/dist/components/admin-navigation.d.ts.map +1 -1
- package/dist/components/admin-navigation.js +10 -7
- package/dist/components/admin-navigation.js.map +1 -1
- package/dist/components/app-icon.d.ts +9 -0
- package/dist/components/app-icon.d.ts.map +1 -0
- package/dist/components/app-icon.js +85 -0
- package/dist/components/app-icon.js.map +1 -0
- package/dist/components/app-list-row.d.ts +12 -0
- package/dist/components/app-list-row.d.ts.map +1 -0
- package/dist/components/app-list-row.js +11 -0
- package/dist/components/app-list-row.js.map +1 -0
- package/dist/components/app-open-actions.d.ts +17 -0
- package/dist/components/app-open-actions.d.ts.map +1 -0
- package/dist/components/app-open-actions.js +20 -0
- package/dist/components/app-open-actions.js.map +1 -0
- package/dist/components/connected-app-card.d.ts +2 -1
- package/dist/components/connected-app-card.d.ts.map +1 -1
- package/dist/components/connected-app-card.js +8 -8
- package/dist/components/connected-app-card.js.map +1 -1
- package/dist/components/dispatch-control-plane.d.ts.map +1 -1
- package/dist/components/dispatch-control-plane.js +21 -14
- package/dist/components/dispatch-control-plane.js.map +1 -1
- package/dist/components/layout/Layout.d.ts.map +1 -1
- package/dist/components/layout/Layout.js +40 -19
- package/dist/components/layout/Layout.js.map +1 -1
- package/dist/components/layout/workspace-apps-rail.d.ts.map +1 -1
- package/dist/components/layout/workspace-apps-rail.js +10 -10
- package/dist/components/layout/workspace-apps-rail.js.map +1 -1
- package/dist/components/other-apps-section.d.ts +31 -0
- package/dist/components/other-apps-section.d.ts.map +1 -0
- package/dist/components/other-apps-section.js +59 -0
- package/dist/components/other-apps-section.js.map +1 -0
- package/dist/components/workspace-app-card.d.ts.map +1 -1
- package/dist/components/workspace-app-card.js +38 -28
- package/dist/components/workspace-app-card.js.map +1 -1
- package/dist/components/workspace-template-card.d.ts +8 -2
- package/dist/components/workspace-template-card.d.ts.map +1 -1
- package/dist/components/workspace-template-card.js +17 -13
- package/dist/components/workspace-template-card.js.map +1 -1
- package/dist/lib/other-apps.d.ts.map +1 -1
- package/dist/lib/other-apps.js +5 -1
- package/dist/lib/other-apps.js.map +1 -1
- package/dist/lib/workspace-apps.d.ts +1 -0
- package/dist/lib/workspace-apps.d.ts.map +1 -1
- package/dist/lib/workspace-apps.js +3 -0
- package/dist/lib/workspace-apps.js.map +1 -1
- package/dist/routes/index.d.ts.map +1 -1
- package/dist/routes/index.js +0 -2
- package/dist/routes/index.js.map +1 -1
- package/dist/routes/pages/admin._index.d.ts.map +1 -1
- package/dist/routes/pages/admin._index.js +32 -7
- package/dist/routes/pages/admin._index.js.map +1 -1
- package/dist/routes/pages/apps.$appId.d.ts.map +1 -1
- package/dist/routes/pages/apps.$appId.js +62 -13
- package/dist/routes/pages/apps.$appId.js.map +1 -1
- package/dist/routes/pages/apps.d.ts +1 -1
- package/dist/routes/pages/apps.d.ts.map +1 -1
- package/dist/routes/pages/apps.js +21 -30
- package/dist/routes/pages/apps.js.map +1 -1
- package/package.json +3 -3
- package/src/components/admin-navigation.tsx +21 -16
- package/src/components/app-icon.tsx +149 -0
- package/src/components/app-list-row.tsx +40 -0
- package/src/components/app-open-actions.tsx +111 -0
- package/src/components/connected-app-card.tsx +30 -34
- package/src/components/dispatch-control-plane.spec.tsx +28 -1
- package/src/components/dispatch-control-plane.tsx +122 -48
- package/src/components/layout/Layout.spec.tsx +4 -4
- package/src/components/layout/Layout.tsx +86 -55
- package/src/components/layout/workspace-apps-rail.tsx +20 -21
- package/src/components/other-apps-section.tsx +195 -0
- package/src/components/workspace-app-card.spec.tsx +58 -32
- package/src/components/workspace-app-card.tsx +222 -158
- package/src/components/workspace-template-card.spec.tsx +45 -7
- package/src/components/workspace-template-card.tsx +74 -81
- package/src/lib/other-apps.spec.ts +31 -0
- package/src/lib/other-apps.ts +9 -1
- package/src/lib/workspace-apps.ts +4 -0
- package/src/routes/index.spec.ts +2 -1
- package/src/routes/index.ts +0 -2
- package/src/routes/pages/admin._index.tsx +85 -17
- package/src/routes/pages/apps.$appId.tsx +144 -57
- package/src/routes/pages/apps.tsx +76 -147
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useActionMutation } from "@agent-native/core/client/hooks";
|
|
3
|
-
import { IconArrowUpRight, IconCircleCheck,
|
|
3
|
+
import { IconArrowUpRight, IconCircleCheck, IconPlus, IconPlugConnected, } from "@tabler/icons-react";
|
|
4
4
|
import { useEffect, useMemo, useState } from "react";
|
|
5
5
|
import { toast } from "sonner";
|
|
6
6
|
import { cn } from "../lib/utils.js";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { AppIcon } from "./app-icon.js";
|
|
8
|
+
import { AppListRow } from "./app-list-row.js";
|
|
9
|
+
import { AppOpenActions } from "./app-open-actions.js";
|
|
9
10
|
import { Button } from "./ui/button.js";
|
|
10
|
-
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, } from "./ui/card.js";
|
|
11
11
|
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "./ui/dialog.js";
|
|
12
12
|
import { Input } from "./ui/input.js";
|
|
13
13
|
import { Label } from "./ui/label.js";
|
|
@@ -18,12 +18,13 @@ const DEFAULT_LABELS = {
|
|
|
18
18
|
cancel: "Cancel",
|
|
19
19
|
integrationSetup: "Integration setup",
|
|
20
20
|
installed: "Installed",
|
|
21
|
-
remix: "
|
|
21
|
+
remix: "Add app",
|
|
22
22
|
remixing: "Creating app…",
|
|
23
23
|
remixSuccess: "Template app creation started.",
|
|
24
|
-
remixError: "Could not
|
|
24
|
+
remixError: "Could not add this app",
|
|
25
25
|
appIdRequired: "App ID is required.",
|
|
26
26
|
source: "Source",
|
|
27
|
+
openApp: "Open app",
|
|
27
28
|
viewLiveApp: "View the live app",
|
|
28
29
|
};
|
|
29
30
|
function slugifyAppId(value) {
|
|
@@ -41,7 +42,7 @@ function defaultAppIdFor(template, defaultAppId) {
|
|
|
41
42
|
if (defaultAppId)
|
|
42
43
|
return slugifyAppId(defaultAppId);
|
|
43
44
|
const sourceId = slugifyAppId(template.appId || template.name);
|
|
44
|
-
return `${sourceId}-
|
|
45
|
+
return `${sourceId}-app`;
|
|
45
46
|
}
|
|
46
47
|
function stringifyError(error) {
|
|
47
48
|
if (error instanceof Error && error.message)
|
|
@@ -53,7 +54,7 @@ function stringifyError(error) {
|
|
|
53
54
|
function mergeLabels(labels) {
|
|
54
55
|
return { ...DEFAULT_LABELS, ...labels };
|
|
55
56
|
}
|
|
56
|
-
export function WorkspaceTemplateCard({ template, defaultAppId, labels: labelOverrides, className, onRemixSuccess, }) {
|
|
57
|
+
export function WorkspaceTemplateCard({ template, defaultAppId, labels: labelOverrides, className, catalog = false, onRemixSuccess, }) {
|
|
57
58
|
const labels = useMemo(() => mergeLabels(labelOverrides), [labelOverrides]);
|
|
58
59
|
const [open, setOpen] = useState(false);
|
|
59
60
|
const [appId, setAppId] = useState(() => defaultAppIdFor(template, defaultAppId));
|
|
@@ -97,21 +98,24 @@ export function WorkspaceTemplateCard({ template, defaultAppId, labels: labelOve
|
|
|
97
98
|
appId: trimmedAppId,
|
|
98
99
|
});
|
|
99
100
|
}
|
|
100
|
-
return (_jsxs(
|
|
101
|
+
return (_jsxs(AppListRow, { className: cn("items-center", className), children: [_jsx(AppIcon, { id: template.id || template.templateId || template.name, name: template.name, icon: template.icon || undefined, color: template.color || undefined, size: "sm" }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [_jsx("h3", { className: "truncate text-sm font-semibold text-foreground", children: template.name }), isInstalled ? (_jsxs("span", { className: "inline-flex shrink-0 items-center gap-1 text-xs text-primary", children: [_jsx(IconCircleCheck, { size: 13 }), labels.installed] })) : null] }), template.description ? (_jsx("p", { className: "mt-0.5 truncate text-xs text-muted-foreground", children: template.description })) : null] }), _jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [catalog ? (_jsx(AppOpenActions, { name: template.name, href: liveUrl ?? null, target: "_blank", rel: "noreferrer", labels: {
|
|
102
|
+
addApp: labels.remix,
|
|
103
|
+
openApp: labels.openApp,
|
|
104
|
+
}, onAddApp: () => setOpen(true) })) : liveUrl ? (_jsx(Button, { variant: "ghost", size: "sm", className: "shrink-0", asChild: true, children: _jsxs("a", { href: liveUrl, target: "_blank", rel: "noreferrer", children: [labels.viewLiveApp, _jsx(IconArrowUpRight, {})] }) })) : null, _jsxs(Dialog, { open: open, onOpenChange: (nextOpen) => {
|
|
101
105
|
if (!remix.isPending)
|
|
102
106
|
setOpen(nextOpen);
|
|
103
|
-
}, children: [_jsx(DialogTrigger, { asChild: true, children: _jsxs(Button, { type: "button", size: "sm", children: [_jsx(
|
|
107
|
+
}, children: [!catalog ? (_jsx(DialogTrigger, { asChild: true, children: _jsxs(Button, { type: "button", variant: "outline", size: "sm", children: [_jsx(IconPlus, {}), labels.remix] }) })) : null, _jsxs(DialogContent, { className: "max-w-md", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: template.name }), _jsx(DialogDescription, { children: labels.appIdDescription })] }), _jsxs("form", { className: "flex flex-col gap-4", onSubmit: (event) => {
|
|
104
108
|
event.preventDefault();
|
|
105
109
|
submitRemix();
|
|
106
|
-
}, children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { htmlFor: `workspace-template-app-id-${templateIdFor(template)}`, children: labels.appId }), _jsx(Input, { id: `workspace-template-app-id-${templateIdFor(template)}`, value: appId, autoComplete: "off", onChange: (event) => setAppId(event.target.value), disabled: remix.isPending })] }), _jsxs(DialogFooter, { children: [_jsx(Button, { type: "button", variant: "outline", onClick: () => setOpen(false), disabled: remix.isPending, children: labels.cancel }), _jsxs(Button, { type: "submit", disabled: remix.isPending, children: [remix.isPending ? _jsx(Spinner, {}) : _jsx(IconArrowUpRight, {}), remix.isPending ? labels.remixing : labels.remix] })] })] })] })] })] })] }));
|
|
110
|
+
}, children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { htmlFor: `workspace-template-app-id-${templateIdFor(template)}`, children: labels.appId }), _jsx(Input, { id: `workspace-template-app-id-${templateIdFor(template)}`, value: appId, autoComplete: "off", onChange: (event) => setAppId(event.target.value), disabled: remix.isPending })] }), setupNote ? (_jsxs("div", { className: "flex items-start gap-2 rounded-lg bg-muted px-3 py-2 text-xs leading-5 text-muted-foreground", children: [_jsx(IconPlugConnected, { className: "mt-0.5 shrink-0", size: 15 }), _jsxs("span", { children: [_jsxs("span", { className: "font-medium text-foreground", children: [labels.integrationSetup, ":"] }), " ", setupNote] })] })) : null, _jsxs(DialogFooter, { children: [_jsx(Button, { type: "button", variant: "outline", onClick: () => setOpen(false), disabled: remix.isPending, children: labels.cancel }), _jsxs(Button, { type: "submit", disabled: remix.isPending, children: [remix.isPending ? _jsx(Spinner, {}) : _jsx(IconArrowUpRight, {}), remix.isPending ? labels.remixing : labels.remix] })] })] })] })] })] })] }));
|
|
107
111
|
}
|
|
108
112
|
function getTemplateItems(result) {
|
|
109
113
|
return Array.isArray(result) ? result : result.templates;
|
|
110
114
|
}
|
|
111
|
-
export function WorkspaceTemplatesSection({ templates: result, title, defaultAppId, labels, className, cardClassName, onRemixSuccess, }) {
|
|
115
|
+
export function WorkspaceTemplatesSection({ templates: result, title, defaultAppId, labels, className, cardClassName, listClassName, catalog = false, onRemixSuccess, }) {
|
|
112
116
|
const templates = getTemplateItems(result);
|
|
113
117
|
if (templates.length === 0)
|
|
114
118
|
return null;
|
|
115
|
-
return (_jsxs("section", { className: cn("flex flex-col gap-3", className), children: [title ? _jsx("div", { className: "text-sm font-semibold", children: title }) : null, _jsx("div", { className: "
|
|
119
|
+
return (_jsxs("section", { className: cn("flex flex-col gap-3", className), children: [title ? _jsx("div", { className: "text-sm font-semibold", children: title }) : null, _jsx("div", { className: cn("overflow-hidden rounded-2xl bg-card", listClassName), children: templates.map((template) => (_jsx(WorkspaceTemplateCard, { template: template, defaultAppId: defaultAppId, labels: labels, catalog: catalog, className: cardClassName, onRemixSuccess: onRemixSuccess }, templateIdFor(template)))) })] }));
|
|
116
120
|
}
|
|
117
121
|
//# sourceMappingURL=workspace-template-card.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-template-card.js","sourceRoot":"","sources":["../../src/components/workspace-template-card.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useActionMutation } from \"@agent-native/core/client/hooks\";\nimport {\n IconArrowUpRight,\n IconCircleCheck,\n IconCopy,\n IconExternalLink,\n IconFileText,\n IconPlugConnected,\n} from \"@tabler/icons-react\";\nimport { useEffect, useMemo, useState, type ReactNode } from \"react\";\nimport { toast } from \"sonner\";\n\nimport { cn } from \"../lib/utils\";\nimport { Alert, AlertDescription } from \"./ui/alert\";\nimport { Badge } from \"./ui/badge\";\nimport { Button } from \"./ui/button\";\nimport {\n Card,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"./ui/card\";\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"./ui/dialog\";\nimport { Input } from \"./ui/input\";\nimport { Label } from \"./ui/label\";\nimport { Spinner } from \"./ui/spinner\";\n\nexport interface CuratedWorkspaceTemplate {\n id?: string | null;\n templateId?: string | null;\n appId?: string | null;\n name: string;\n description?: string | null;\n source?: string | null;\n sourceDescription?: string | null;\n integrationSetup?: string | null;\n setupNote?: string | null;\n installed?: boolean | null;\n installedAppId?: string | null;\n liveUrl?: string | null;\n productUrl?: string | null;\n}\n\nexport type CuratedWorkspaceTemplatesResult =\n | CuratedWorkspaceTemplate[]\n | {\n templates: CuratedWorkspaceTemplate[];\n };\n\nexport interface WorkspaceTemplateLabels {\n appId: string;\n appIdDescription: string;\n cancel: string;\n integrationSetup: string;\n installed: string;\n remix: string;\n remixing: string;\n remixSuccess: string;\n remixError: string;\n appIdRequired: string;\n source: string;\n viewLiveApp: string;\n}\n\nconst DEFAULT_LABELS: WorkspaceTemplateLabels = {\n appId: \"App ID\",\n appIdDescription: \"Choose the URL-safe id for the new workspace app.\",\n cancel: \"Cancel\",\n integrationSetup: \"Integration setup\",\n installed: \"Installed\",\n remix: \"Create from template\",\n remixing: \"Creating app…\",\n remixSuccess: \"Template app creation started.\",\n remixError: \"Could not create an app from this template\",\n appIdRequired: \"App ID is required.\",\n source: \"Source\",\n viewLiveApp: \"View the live app\",\n};\n\nexport interface WorkspaceTemplateCardProps {\n template: CuratedWorkspaceTemplate;\n defaultAppId?: string;\n labels?: Partial<WorkspaceTemplateLabels>;\n className?: string;\n onRemixSuccess?: (\n result: unknown,\n template: CuratedWorkspaceTemplate,\n ) => void;\n}\n\nfunction slugifyAppId(value: string): string {\n return (\n value\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .slice(0, 48) || \"new-app\"\n );\n}\n\nfunction templateIdFor(template: CuratedWorkspaceTemplate): string {\n return template.templateId || template.id || template.appId || template.name;\n}\n\nfunction defaultAppIdFor(\n template: CuratedWorkspaceTemplate,\n defaultAppId?: string,\n): string {\n if (defaultAppId) return slugifyAppId(defaultAppId);\n const sourceId = slugifyAppId(template.appId || template.name);\n return `${sourceId}-remix`;\n}\n\nfunction stringifyError(error: unknown): string {\n if (error instanceof Error && error.message) return error.message;\n if (typeof error === \"string\") return error;\n return \"Unknown error\";\n}\n\nfunction mergeLabels(\n labels?: Partial<WorkspaceTemplateLabels>,\n): WorkspaceTemplateLabels {\n return { ...DEFAULT_LABELS, ...labels };\n}\n\nexport function WorkspaceTemplateCard({\n template,\n defaultAppId,\n labels: labelOverrides,\n className,\n onRemixSuccess,\n}: WorkspaceTemplateCardProps) {\n const labels = useMemo(() => mergeLabels(labelOverrides), [labelOverrides]);\n const [open, setOpen] = useState(false);\n const [appId, setAppId] = useState(() =>\n defaultAppIdFor(template, defaultAppId),\n );\n const isInstalled = Boolean(template.installed || template.installedAppId);\n const liveUrl = template.liveUrl || template.productUrl;\n const setupNote = template.integrationSetup || template.setupNote;\n const remix = useActionMutation(\"remix-workspace-template\", {\n onSuccess: (result) => {\n const mode = (result as { mode?: string } | null)?.mode;\n const message = (result as { message?: string } | null)?.message;\n if (mode === \"builder\") {\n toast.success(labels.remixSuccess);\n } else if (mode === \"builder-unavailable\") {\n toast.error(message || labels.remixError);\n } else if (mode === \"coming-soon\") {\n toast.info(message || labels.remixSuccess);\n } else {\n toast.success(labels.remixSuccess);\n }\n setOpen(false);\n onRemixSuccess?.(result, template);\n },\n onError: (error) =>\n toast.error(`${labels.remixError}: ${stringifyError(error)}`),\n });\n\n useEffect(() => {\n if (open) {\n setAppId(defaultAppIdFor(template, defaultAppId));\n }\n }, [defaultAppId, open, template]);\n\n function submitRemix() {\n const trimmedAppId = appId.trim();\n if (!trimmedAppId) {\n toast.error(labels.appIdRequired);\n return;\n }\n\n remix.mutate({\n templateId: templateIdFor(template),\n appId: trimmedAppId,\n });\n }\n\n return (\n <Card\n className={cn(\n \"flex h-full flex-col bg-card/40 shadow-none transition-[background-color] hover:bg-accent/15\",\n className,\n )}\n >\n <CardHeader className=\"gap-2 p-4\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex min-w-0 items-start gap-2.5\">\n <span className=\"mt-0.5 flex size-8 shrink-0 items-center justify-center rounded-md bg-muted/40 text-muted-foreground\">\n <IconFileText size={16} />\n </span>\n <div className=\"min-w-0\">\n <CardTitle className=\"truncate text-sm font-semibold\">\n {template.name}\n </CardTitle>\n {template.source || template.sourceDescription ? (\n <CardDescription className=\"mt-1 truncate text-xs\">\n <span className=\"font-medium text-foreground/70\">\n {labels.source}:\n </span>{\" \"}\n {template.sourceDescription || template.source}\n </CardDescription>\n ) : null}\n </div>\n </div>\n {isInstalled ? (\n <Badge\n variant=\"outline\"\n className=\"shrink-0 gap-1 border-primary/30 bg-primary/5 text-primary\"\n >\n <IconCircleCheck size={13} />\n {labels.installed}\n </Badge>\n ) : null}\n </div>\n </CardHeader>\n\n <CardContent className=\"flex flex-1 flex-col gap-3 p-4 pt-0\">\n {template.description ? (\n <p className=\"line-clamp-3 text-[13px] leading-5 text-muted-foreground\">\n {template.description}\n </p>\n ) : null}\n\n {setupNote ? (\n <Alert className=\"border-border/60 bg-muted/25 px-3 py-2 [&>svg]:left-3 [&>svg]:top-2.5\">\n <IconPlugConnected size={15} />\n <AlertDescription className=\"text-xs leading-5\">\n <span className=\"font-medium text-foreground/80\">\n {labels.integrationSetup}:\n </span>{\" \"}\n {setupNote}\n </AlertDescription>\n </Alert>\n ) : null}\n </CardContent>\n\n <CardFooter className=\"flex flex-wrap justify-between gap-2 p-4 pt-0\">\n {liveUrl ? (\n <Button variant=\"link\" size=\"sm\" className=\"h-8 px-0\" asChild>\n <a href={liveUrl} target=\"_blank\" rel=\"noreferrer\">\n {labels.viewLiveApp}\n <IconExternalLink />\n </a>\n </Button>\n ) : (\n <span />\n )}\n\n <Dialog\n open={open}\n onOpenChange={(nextOpen) => {\n if (!remix.isPending) setOpen(nextOpen);\n }}\n >\n <DialogTrigger asChild>\n <Button type=\"button\" size=\"sm\">\n <IconCopy />\n {labels.remix}\n </Button>\n </DialogTrigger>\n <DialogContent className=\"max-w-md\">\n <DialogHeader>\n <DialogTitle>{template.name}</DialogTitle>\n <DialogDescription>{labels.appIdDescription}</DialogDescription>\n </DialogHeader>\n <form\n className=\"flex flex-col gap-4\"\n onSubmit={(event) => {\n event.preventDefault();\n submitRemix();\n }}\n >\n <div className=\"flex flex-col gap-2\">\n <Label\n htmlFor={`workspace-template-app-id-${templateIdFor(template)}`}\n >\n {labels.appId}\n </Label>\n <Input\n id={`workspace-template-app-id-${templateIdFor(template)}`}\n value={appId}\n autoComplete=\"off\"\n onChange={(event) => setAppId(event.target.value)}\n disabled={remix.isPending}\n />\n </div>\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => setOpen(false)}\n disabled={remix.isPending}\n >\n {labels.cancel}\n </Button>\n <Button type=\"submit\" disabled={remix.isPending}>\n {remix.isPending ? <Spinner /> : <IconArrowUpRight />}\n {remix.isPending ? labels.remixing : labels.remix}\n </Button>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n </CardFooter>\n </Card>\n );\n}\n\nexport interface WorkspaceTemplatesSectionProps {\n templates: CuratedWorkspaceTemplatesResult;\n title?: ReactNode;\n defaultAppId?: string;\n labels?: Partial<WorkspaceTemplateLabels>;\n className?: string;\n cardClassName?: string;\n onRemixSuccess?: (\n result: unknown,\n template: CuratedWorkspaceTemplate,\n ) => void;\n}\n\nfunction getTemplateItems(\n result: CuratedWorkspaceTemplatesResult,\n): CuratedWorkspaceTemplate[] {\n return Array.isArray(result) ? result : result.templates;\n}\n\nexport function WorkspaceTemplatesSection({\n templates: result,\n title,\n defaultAppId,\n labels,\n className,\n cardClassName,\n onRemixSuccess,\n}: WorkspaceTemplatesSectionProps) {\n const templates = getTemplateItems(result);\n\n if (templates.length === 0) return null;\n\n return (\n <section className={cn(\"flex flex-col gap-3\", className)}>\n {title ? <div className=\"text-sm font-semibold\">{title}</div> : null}\n <div className=\"grid gap-3 md:grid-cols-2\">\n {templates.map((template) => (\n <WorkspaceTemplateCard\n key={templateIdFor(template)}\n template={template}\n defaultAppId={defaultAppId}\n labels={labels}\n className={cardClassName}\n onRemixSuccess={onRemixSuccess}\n />\n ))}\n </div>\n </section>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"workspace-template-card.js","sourceRoot":"","sources":["../../src/components/workspace-template-card.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useActionMutation } from \"@agent-native/core/client/hooks\";\nimport {\n IconArrowUpRight,\n IconCircleCheck,\n IconPlus,\n IconPlugConnected,\n} from \"@tabler/icons-react\";\nimport { useEffect, useMemo, useState, type ReactNode } from \"react\";\nimport { toast } from \"sonner\";\n\nimport { cn } from \"../lib/utils\";\nimport { AppIcon } from \"./app-icon\";\nimport { AppListRow } from \"./app-list-row\";\nimport { AppOpenActions } from \"./app-open-actions\";\nimport { Button } from \"./ui/button\";\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"./ui/dialog\";\nimport { Input } from \"./ui/input\";\nimport { Label } from \"./ui/label\";\nimport { Spinner } from \"./ui/spinner\";\n\nexport interface CuratedWorkspaceTemplate {\n id?: string | null;\n templateId?: string | null;\n appId?: string | null;\n name: string;\n description?: string | null;\n source?: string | null;\n sourceDescription?: string | null;\n icon?: string | null;\n color?: string | null;\n integrationSetup?: string | null;\n setupNote?: string | null;\n installed?: boolean | null;\n installedAppId?: string | null;\n liveUrl?: string | null;\n productUrl?: string | null;\n}\n\nexport type CuratedWorkspaceTemplatesResult =\n | CuratedWorkspaceTemplate[]\n | {\n templates: CuratedWorkspaceTemplate[];\n };\n\nexport interface WorkspaceTemplateLabels {\n appId: string;\n appIdDescription: string;\n cancel: string;\n integrationSetup: string;\n installed: string;\n remix: string;\n remixing: string;\n remixSuccess: string;\n remixError: string;\n appIdRequired: string;\n source: string;\n openApp: string;\n viewLiveApp: string;\n}\n\nconst DEFAULT_LABELS: WorkspaceTemplateLabels = {\n appId: \"App ID\",\n appIdDescription: \"Choose the URL-safe id for the new workspace app.\",\n cancel: \"Cancel\",\n integrationSetup: \"Integration setup\",\n installed: \"Installed\",\n remix: \"Add app\",\n remixing: \"Creating app…\",\n remixSuccess: \"Template app creation started.\",\n remixError: \"Could not add this app\",\n appIdRequired: \"App ID is required.\",\n source: \"Source\",\n openApp: \"Open app\",\n viewLiveApp: \"View the live app\",\n};\n\nexport interface WorkspaceTemplateCardProps {\n template: CuratedWorkspaceTemplate;\n defaultAppId?: string;\n labels?: Partial<WorkspaceTemplateLabels>;\n className?: string;\n catalog?: boolean;\n onRemixSuccess?: (\n result: unknown,\n template: CuratedWorkspaceTemplate,\n ) => void;\n}\n\nfunction slugifyAppId(value: string): string {\n return (\n value\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .slice(0, 48) || \"new-app\"\n );\n}\n\nfunction templateIdFor(template: CuratedWorkspaceTemplate): string {\n return template.templateId || template.id || template.appId || template.name;\n}\n\nfunction defaultAppIdFor(\n template: CuratedWorkspaceTemplate,\n defaultAppId?: string,\n): string {\n if (defaultAppId) return slugifyAppId(defaultAppId);\n const sourceId = slugifyAppId(template.appId || template.name);\n return `${sourceId}-app`;\n}\n\nfunction stringifyError(error: unknown): string {\n if (error instanceof Error && error.message) return error.message;\n if (typeof error === \"string\") return error;\n return \"Unknown error\";\n}\n\nfunction mergeLabels(\n labels?: Partial<WorkspaceTemplateLabels>,\n): WorkspaceTemplateLabels {\n return { ...DEFAULT_LABELS, ...labels };\n}\n\nexport function WorkspaceTemplateCard({\n template,\n defaultAppId,\n labels: labelOverrides,\n className,\n catalog = false,\n onRemixSuccess,\n}: WorkspaceTemplateCardProps) {\n const labels = useMemo(() => mergeLabels(labelOverrides), [labelOverrides]);\n const [open, setOpen] = useState(false);\n const [appId, setAppId] = useState(() =>\n defaultAppIdFor(template, defaultAppId),\n );\n const isInstalled = Boolean(template.installed || template.installedAppId);\n const liveUrl = template.liveUrl || template.productUrl;\n const setupNote = template.integrationSetup || template.setupNote;\n const remix = useActionMutation(\"remix-workspace-template\", {\n onSuccess: (result) => {\n const mode = (result as { mode?: string } | null)?.mode;\n const message = (result as { message?: string } | null)?.message;\n if (mode === \"builder\") {\n toast.success(labels.remixSuccess);\n } else if (mode === \"builder-unavailable\") {\n toast.error(message || labels.remixError);\n } else if (mode === \"coming-soon\") {\n toast.info(message || labels.remixSuccess);\n } else {\n toast.success(labels.remixSuccess);\n }\n setOpen(false);\n onRemixSuccess?.(result, template);\n },\n onError: (error) =>\n toast.error(`${labels.remixError}: ${stringifyError(error)}`),\n });\n\n useEffect(() => {\n if (open) {\n setAppId(defaultAppIdFor(template, defaultAppId));\n }\n }, [defaultAppId, open, template]);\n\n function submitRemix() {\n const trimmedAppId = appId.trim();\n if (!trimmedAppId) {\n toast.error(labels.appIdRequired);\n return;\n }\n\n remix.mutate({\n templateId: templateIdFor(template),\n appId: trimmedAppId,\n });\n }\n\n return (\n <AppListRow className={cn(\"items-center\", className)}>\n <AppIcon\n id={template.id || template.templateId || template.name}\n name={template.name}\n icon={template.icon || undefined}\n color={template.color || undefined}\n size=\"sm\"\n />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <h3 className=\"truncate text-sm font-semibold text-foreground\">\n {template.name}\n </h3>\n {isInstalled ? (\n <span className=\"inline-flex shrink-0 items-center gap-1 text-xs text-primary\">\n <IconCircleCheck size={13} />\n {labels.installed}\n </span>\n ) : null}\n </div>\n {template.description ? (\n <p className=\"mt-0.5 truncate text-xs text-muted-foreground\">\n {template.description}\n </p>\n ) : null}\n </div>\n <div className=\"flex shrink-0 items-center gap-2\">\n {catalog ? (\n <AppOpenActions\n name={template.name}\n href={liveUrl ?? null}\n target=\"_blank\"\n rel=\"noreferrer\"\n labels={{\n addApp: labels.remix,\n openApp: labels.openApp,\n }}\n onAddApp={() => setOpen(true)}\n />\n ) : liveUrl ? (\n <Button variant=\"ghost\" size=\"sm\" className=\"shrink-0\" asChild>\n <a href={liveUrl} target=\"_blank\" rel=\"noreferrer\">\n {labels.viewLiveApp}\n <IconArrowUpRight />\n </a>\n </Button>\n ) : null}\n\n <Dialog\n open={open}\n onOpenChange={(nextOpen) => {\n if (!remix.isPending) setOpen(nextOpen);\n }}\n >\n {!catalog ? (\n <DialogTrigger asChild>\n <Button type=\"button\" variant=\"outline\" size=\"sm\">\n <IconPlus />\n {labels.remix}\n </Button>\n </DialogTrigger>\n ) : null}\n <DialogContent className=\"max-w-md\">\n <DialogHeader>\n <DialogTitle>{template.name}</DialogTitle>\n <DialogDescription>{labels.appIdDescription}</DialogDescription>\n </DialogHeader>\n <form\n className=\"flex flex-col gap-4\"\n onSubmit={(event) => {\n event.preventDefault();\n submitRemix();\n }}\n >\n <div className=\"flex flex-col gap-2\">\n <Label\n htmlFor={`workspace-template-app-id-${templateIdFor(template)}`}\n >\n {labels.appId}\n </Label>\n <Input\n id={`workspace-template-app-id-${templateIdFor(template)}`}\n value={appId}\n autoComplete=\"off\"\n onChange={(event) => setAppId(event.target.value)}\n disabled={remix.isPending}\n />\n </div>\n {setupNote ? (\n <div className=\"flex items-start gap-2 rounded-lg bg-muted px-3 py-2 text-xs leading-5 text-muted-foreground\">\n <IconPlugConnected className=\"mt-0.5 shrink-0\" size={15} />\n <span>\n <span className=\"font-medium text-foreground\">\n {labels.integrationSetup}:\n </span>{\" \"}\n {setupNote}\n </span>\n </div>\n ) : null}\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => setOpen(false)}\n disabled={remix.isPending}\n >\n {labels.cancel}\n </Button>\n <Button type=\"submit\" disabled={remix.isPending}>\n {remix.isPending ? <Spinner /> : <IconArrowUpRight />}\n {remix.isPending ? labels.remixing : labels.remix}\n </Button>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n </div>\n </AppListRow>\n );\n}\n\nexport interface WorkspaceTemplatesSectionProps {\n templates: CuratedWorkspaceTemplatesResult;\n title?: ReactNode;\n defaultAppId?: string;\n labels?: Partial<WorkspaceTemplateLabels>;\n className?: string;\n cardClassName?: string;\n listClassName?: string;\n catalog?: boolean;\n onRemixSuccess?: (\n result: unknown,\n template: CuratedWorkspaceTemplate,\n ) => void;\n}\n\nfunction getTemplateItems(\n result: CuratedWorkspaceTemplatesResult,\n): CuratedWorkspaceTemplate[] {\n return Array.isArray(result) ? result : result.templates;\n}\n\nexport function WorkspaceTemplatesSection({\n templates: result,\n title,\n defaultAppId,\n labels,\n className,\n cardClassName,\n listClassName,\n catalog = false,\n onRemixSuccess,\n}: WorkspaceTemplatesSectionProps) {\n const templates = getTemplateItems(result);\n\n if (templates.length === 0) return null;\n\n return (\n <section className={cn(\"flex flex-col gap-3\", className)}>\n {title ? <div className=\"text-sm font-semibold\">{title}</div> : null}\n <div className={cn(\"overflow-hidden rounded-2xl bg-card\", listClassName)}>\n {templates.map((template) => (\n <WorkspaceTemplateCard\n key={templateIdFor(template)}\n template={template}\n defaultAppId={defaultAppId}\n labels={labels}\n catalog={catalog}\n className={cardClassName}\n onRemixSuccess={onRemixSuccess}\n />\n ))}\n </div>\n </section>\n );\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"other-apps.d.ts","sourceRoot":"","sources":["../../src/lib/other-apps.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,WAAW,CAAC;CAC7C;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;
|
|
1
|
+
{"version":3,"file":"other-apps.d.ts","sourceRoot":"","sources":["../../src/lib/other-apps.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,WAAW,CAAC;CAC7C;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAaD,wBAAgB,eAAe,CAC7B,aAAa,EAAE,mBAAmB,EAAE,EACpC,aAAa,EAAE,cAAc,EAAE,GAC9B,mBAAmB,EAAE,CAuBvB"}
|
package/dist/lib/other-apps.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const HIDDEN_OTHER_APP_IDS = new Set(["crm", "research"]);
|
|
1
2
|
function isHttpUrl(value) {
|
|
2
3
|
try {
|
|
3
4
|
const url = new URL(value);
|
|
@@ -16,7 +17,10 @@ export function filterOtherApps(connectedApps, workspaceApps) {
|
|
|
16
17
|
return connectedApps
|
|
17
18
|
.filter((app) => {
|
|
18
19
|
const id = app.id.trim().toLowerCase();
|
|
19
|
-
if (!id ||
|
|
20
|
+
if (!id ||
|
|
21
|
+
HIDDEN_OTHER_APP_IDS.has(id) ||
|
|
22
|
+
workspaceAppIds.has(id) ||
|
|
23
|
+
seen.has(id))
|
|
20
24
|
return false;
|
|
21
25
|
if (app.source === "workspace")
|
|
22
26
|
return false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"other-apps.js","sourceRoot":"","sources":["../../src/lib/other-apps.ts"],"names":[],"mappings":"AAcA,SAAS,SAAS,CAAC,KAAa;IAC9B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;QAC3B,OAAO,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC;IAC/D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,aAAoC,EACpC,aAA+B;IAE/B,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC;QAC9B,UAAU;QACV,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;KAC3D,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,OAAO,aAAa;SACjB,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE;QACd,MAAM,EAAE,GAAG,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACvC,
|
|
1
|
+
{"version":3,"file":"other-apps.js","sourceRoot":"","sources":["../../src/lib/other-apps.ts"],"names":[],"mappings":"AAcA,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC;AAE1D,SAAS,SAAS,CAAC,KAAa;IAC9B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;QAC3B,OAAO,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC;IAC/D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,aAAoC,EACpC,aAA+B;IAE/B,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC;QAC9B,UAAU;QACV,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;KAC3D,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,OAAO,aAAa;SACjB,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE;QACd,MAAM,EAAE,GAAG,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACvC,IACE,CAAC,EAAE;YACH,oBAAoB,CAAC,GAAG,CAAC,EAAE,CAAC;YAC5B,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;YACvB,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAEZ,OAAO,KAAK,CAAC;QACf,IAAI,GAAG,CAAC,MAAM,KAAK,WAAW;YAAE,OAAO,KAAK,CAAC;QAC7C,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;QACtC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACb,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;SACD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAClD,CAAC","sourcesContent":["export interface ConnectedAppSummary {\n id: string;\n name: string;\n description?: string;\n url: string;\n color?: string;\n source?: \"builtin\" | \"custom\" | \"workspace\";\n}\n\nexport interface WorkspaceAppId {\n id: string;\n isDispatch?: boolean;\n}\n\nconst HIDDEN_OTHER_APP_IDS = new Set([\"crm\", \"research\"]);\n\nfunction isHttpUrl(value: string): boolean {\n try {\n const url = new URL(value);\n return url.protocol === \"http:\" || url.protocol === \"https:\";\n } catch {\n return false;\n }\n}\n\nexport function filterOtherApps(\n connectedApps: ConnectedAppSummary[],\n workspaceApps: WorkspaceAppId[],\n): ConnectedAppSummary[] {\n const workspaceAppIds = new Set([\n \"dispatch\",\n ...workspaceApps.map((app) => app.id.trim().toLowerCase()),\n ]);\n const seen = new Set<string>();\n\n return connectedApps\n .filter((app) => {\n const id = app.id.trim().toLowerCase();\n if (\n !id ||\n HIDDEN_OTHER_APP_IDS.has(id) ||\n workspaceAppIds.has(id) ||\n seen.has(id)\n )\n return false;\n if (app.source === \"workspace\") return false;\n if (!isHttpUrl(app.url)) return false;\n seen.add(id);\n return true;\n })\n .sort((a, b) => a.name.localeCompare(b.name));\n}\n"]}
|
|
@@ -23,6 +23,7 @@ export interface WorkspaceAppSummary {
|
|
|
23
23
|
agentSkillsCount?: number | null;
|
|
24
24
|
archived?: boolean;
|
|
25
25
|
}
|
|
26
|
+
export declare function workspaceAppRoute(appId: string): string;
|
|
26
27
|
export declare function workspaceAppHref(app: WorkspaceAppSummary): string | null;
|
|
27
28
|
export declare function isPendingBuilderHref(app: WorkspaceAppSummary): boolean;
|
|
28
29
|
//# sourceMappingURL=workspace-apps.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-apps.d.ts","sourceRoot":"","sources":["../../src/lib/workspace-apps.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,UAAU,GAAG,QAAQ,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,mBAAmB,GAAG,MAAM,GAAG,IAAI,CAUxE;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAEtE"}
|
|
1
|
+
{"version":3,"file":"workspace-apps.d.ts","sourceRoot":"","sources":["../../src/lib/workspace-apps.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,UAAU,GAAG,QAAQ,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,mBAAmB,GAAG,MAAM,GAAG,IAAI,CAUxE;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAEtE"}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { withBuilderUtmTrackingParams } from "@agent-native/core/shared/builder-link-tracking";
|
|
2
|
+
export function workspaceAppRoute(appId) {
|
|
3
|
+
return `/apps/${encodeURIComponent(appId)}`;
|
|
4
|
+
}
|
|
2
5
|
export function workspaceAppHref(app) {
|
|
3
6
|
if (app.status === "pending") {
|
|
4
7
|
return app.builderUrl
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-apps.js","sourceRoot":"","sources":["../../src/lib/workspace-apps.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,4BAA4B,EAAE,MAAM,iDAAiD,CAAC;AA4B/F,MAAM,UAAU,gBAAgB,CAAC,GAAwB;IACvD,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,GAAG,CAAC,UAAU;YACnB,CAAC,CAAC,4BAA4B,CAAC,GAAG,CAAC,UAAU,EAAE;gBAC3C,QAAQ,EAAE,SAAS;gBACnB,OAAO,EAAE,iBAAiB;aAC3B,CAAC;YACJ,CAAC,CAAC,IAAI,CAAC;IACX,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,GAAG,IAAI,IAAI,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,GAAwB;IAC3D,OAAO,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC;AACtD,CAAC","sourcesContent":["import { withBuilderUtmTrackingParams } from \"@agent-native/core/shared/builder-link-tracking\";\n\nexport interface WorkspaceAppSummary {\n id: string;\n name: string;\n description?: string;\n path: string;\n url?: string | null;\n isDispatch?: boolean;\n audience?: \"internal\" | \"public\";\n publicPaths?: string[];\n protectedPaths?: string[];\n status?: \"ready\" | \"pending\";\n statusLabel?: string;\n builderUrl?: string | null;\n branchName?: string | null;\n createdAt?: string | null;\n createdBy?: string | null;\n owner?: string | null;\n teams?: string[];\n agentCardUrl?: string | null;\n agentCardReachable?: boolean;\n a2aEndpointUrl?: string | null;\n agentName?: string | null;\n agentSkillsCount?: number | null;\n archived?: boolean;\n}\n\nexport function workspaceAppHref(app: WorkspaceAppSummary): string | null {\n if (app.status === \"pending\") {\n return app.builderUrl\n ? withBuilderUtmTrackingParams(app.builderUrl, {\n campaign: \"product\",\n content: \"dispatch_branch\",\n })\n : null;\n }\n return app.path || app.url || null;\n}\n\nexport function isPendingBuilderHref(app: WorkspaceAppSummary): boolean {\n return app.status === \"pending\" && !!app.builderUrl;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"workspace-apps.js","sourceRoot":"","sources":["../../src/lib/workspace-apps.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,4BAA4B,EAAE,MAAM,iDAAiD,CAAC;AA4B/F,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,OAAO,SAAS,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,GAAwB;IACvD,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,GAAG,CAAC,UAAU;YACnB,CAAC,CAAC,4BAA4B,CAAC,GAAG,CAAC,UAAU,EAAE;gBAC3C,QAAQ,EAAE,SAAS;gBACnB,OAAO,EAAE,iBAAiB;aAC3B,CAAC;YACJ,CAAC,CAAC,IAAI,CAAC;IACX,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,GAAG,IAAI,IAAI,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,GAAwB;IAC3D,OAAO,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC;AACtD,CAAC","sourcesContent":["import { withBuilderUtmTrackingParams } from \"@agent-native/core/shared/builder-link-tracking\";\n\nexport interface WorkspaceAppSummary {\n id: string;\n name: string;\n description?: string;\n path: string;\n url?: string | null;\n isDispatch?: boolean;\n audience?: \"internal\" | \"public\";\n publicPaths?: string[];\n protectedPaths?: string[];\n status?: \"ready\" | \"pending\";\n statusLabel?: string;\n builderUrl?: string | null;\n branchName?: string | null;\n createdAt?: string | null;\n createdBy?: string | null;\n owner?: string | null;\n teams?: string[];\n agentCardUrl?: string | null;\n agentCardReachable?: boolean;\n a2aEndpointUrl?: string | null;\n agentName?: string | null;\n agentSkillsCount?: number | null;\n archived?: boolean;\n}\n\nexport function workspaceAppRoute(appId: string): string {\n return `/apps/${encodeURIComponent(appId)}`;\n}\n\nexport function workspaceAppHref(app: WorkspaceAppSummary): string | null {\n if (app.status === \"pending\") {\n return app.builderUrl\n ? withBuilderUtmTrackingParams(app.builderUrl, {\n campaign: \"product\",\n content: \"dispatch_branch\",\n })\n : null;\n }\n return app.path || app.url || null;\n}\n\nexport function isPendingBuilderHref(app: WorkspaceAppSummary): boolean {\n return app.status === \"pending\" && !!app.builderUrl;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/routes/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAgB,MAAM,0BAA0B,CAAC;AAE1E;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,cAAc,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/routes/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAgB,MAAM,0BAA0B,CAAC;AAE1E;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,cAAc,EAAE,WA+D5B,CAAC"}
|
package/dist/routes/index.js
CHANGED
|
@@ -37,8 +37,6 @@ export const dispatchRoutes = [
|
|
|
37
37
|
route("overview", "./pages/overview.js"),
|
|
38
38
|
route("admin", "./pages/admin.js", [
|
|
39
39
|
index("./pages/admin._index.js"),
|
|
40
|
-
route("apps", "./pages/apps.js"),
|
|
41
|
-
route("apps/:appId", "./pages/apps.$appId.js"),
|
|
42
40
|
route("new-app", "./pages/new-app.js"),
|
|
43
41
|
route("operations", "./pages/operations.js"),
|
|
44
42
|
route("metrics", "./pages/metrics.js"),
|
package/dist/routes/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/routes/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AAE1E;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,MAAM,cAAc,GAAgB;IACzC,KAAK,CAAC,mBAAmB,CAAC;IAC1B,KAAK,CAAC,iBAAiB,EAAE,4BAA4B,CAAC;IACtD,KAAK,CAAC,cAAc,EAAE,yBAAyB,CAAC;IAChD,KAAK,CAAC,MAAM,EAAE,iBAAiB,CAAC;IAChC,KAAK,CAAC,gBAAgB,EAAE,iBAAiB,CAAC;IAC1C,KAAK,CAAC,UAAU,EAAE,qBAAqB,CAAC;IACxC,KAAK,CAAC,OAAO,EAAE,kBAAkB,EAAE;QACjC,KAAK,CAAC,yBAAyB,CAAC;QAChC,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/routes/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { type RouteConfig, route, index } from \"@react-router/dev/routes\";\n\n/**\n * Dispatch's routes as a programmatic `RouteConfig[]`. Splat into the\n * consumer's `app/routes.ts`:\n *\n * ```ts\n * import { type RouteConfig } from \"@react-router/dev/routes\";\n * import { dispatchRoutes } from \"@agent-native/dispatch/routes\";\n *\n * export default [\n * ...localRoutes, // consumer's own routes win on collision\n * ...dispatchRoutes, // dispatch fills in everything else\n * ] satisfies RouteConfig;\n * ```\n *\n * Route precedence: React Router 7 matches in declaration order, so\n * placing `dispatchRoutes` LAST means consumer-defined routes with the\n * same path take precedence. To override a single dispatch route, define\n * it in your local routes; to keep it, omit it.\n *\n * The `file` paths below resolve relative to this file at runtime — they\n * point into `packages/dispatch/dist/routes/pages/*.js` after build.\n *\n * Naming maps the original flatRoutes file conventions:\n * `_index.tsx` → `index(...)`\n * `<name>.tsx` → `route(\"<name>\", ...)`\n * `<a>.$<param>.tsx` → `route(\"<a>/:<param>\", ...)`\n * `<a>._index.tsx` → flattened as `route(\"<a>\", ...)` (workspace\n * versions are bare and don't wrap a parent layout)\n */\nexport const dispatchRoutes: RouteConfig = [\n index(\"./pages/_index.js\"),\n route(\"browser-connect\", \"./pages/browser-connect.js\"),\n route(\"browser-chat\", \"./pages/browser-chat.js\"),\n route(\"chat\", \"./pages/chat.js\"),\n route(\"chat/:threadId\", \"./pages/chat.js\"),\n route(\"overview\", \"./pages/overview.js\"),\n route(\"admin\", \"./pages/admin.js\", [\n index(\"./pages/admin._index.js\"),\n route(\"new-app\", \"./pages/new-app.js\"),\n route(\"operations\", \"./pages/operations.js\"),\n route(\"metrics\", \"./pages/metrics.js\"),\n route(\"automations\", \"./pages/automations.js\"),\n route(\"approvals\", \"./pages/approvals.js\"),\n route(\"destinations\", \"./pages/destinations.js\"),\n route(\"integrations\", \"./pages/integrations.js\"),\n route(\"transactional-email\", \"./pages/transactional-email.js\"),\n route(\n \"transactional-email/:appId/:id\",\n \"./pages/transactional-email.$appId.$id.js\",\n ),\n route(\"vault\", \"./pages/vault.js\"),\n route(\"agents\", \"./pages/agents.js\"),\n route(\"workspace\", \"./pages/workspace.js\"),\n route(\"messaging\", \"./pages/messaging.js\"),\n route(\"identities\", \"./pages/identities.js\"),\n route(\"audit\", \"./pages/audit.js\"),\n route(\"dreams\", \"./pages/dreams.js\"),\n route(\"thread-debug\", \"./pages/thread-debug.js\"),\n ]),\n route(\"metrics\", \"./pages/metrics.js\"),\n route(\"operations\", \"./pages/operations.js\"),\n route(\"apps\", \"./pages/apps.js\"),\n route(\"apps/:appId\", \"./pages/apps.$appId.js\"),\n route(\"new-app\", \"./pages/new-app.js\"),\n route(\"vault\", \"./pages/vault.js\"),\n route(\"integrations\", \"./pages/integrations.js\"),\n route(\"agents\", \"./pages/agents.js\"),\n route(\"workspace\", \"./pages/workspace.js\"),\n route(\"messaging\", \"./pages/messaging.js\"),\n route(\"destinations\", \"./pages/destinations.js\"),\n route(\"transactional-email\", \"./pages/transactional-email.js\"),\n route(\n \"transactional-email/:appId/:id\",\n \"./pages/transactional-email.$appId.$id.js\",\n ),\n route(\"identities\", \"./pages/identities.js\"),\n route(\"approval\", \"./pages/approval.js\"),\n route(\"approvals\", \"./pages/approvals.js\"),\n route(\"automations\", \"./pages/automations.js\"),\n route(\"audit\", \"./pages/audit.js\"),\n route(\"settings\", \"./pages/settings.js\"),\n route(\"dreams\", \"./pages/dreams.js\"),\n route(\"thread-debug\", \"./pages/thread-debug.js\"),\n route(\"team\", \"./pages/team.js\"),\n route(\"extensions\", \"./pages/extensions._index.js\"),\n route(\"extensions/:id\", \"./pages/extensions.$id.js\"),\n route(\"extensions/:id/:slug\", \"./pages/extensions.$id.js\"),\n // Catch-all for /:appId — bounces /dispatch/<appId> to /<appId> when the\n // segment names a workspace app sibling (e.g. Builder.io routing a \"go to\n // /todo\" call through Dispatch's mount). Declared last so React Router 7's\n // specificity ranking still matches explicit static routes above first.\n route(\":appId\", \"./pages/$appId.js\"),\n];\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin._index.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/admin._index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"admin._index.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/admin._index.tsx"],"names":[],"mappings":"AAUA,wBAAgB,IAAI;;IAEnB;AAED,MAAM,CAAC,OAAO,UAAU,kBAAkB,oDAkBzC"}
|
|
@@ -1,19 +1,44 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useT } from "@agent-native/core/client/i18n";
|
|
3
|
+
import { IconChevronRight } from "@tabler/icons-react";
|
|
4
|
+
import { Link } from "react-router";
|
|
5
|
+
import { useAdminNavGroups, } from "../../components/admin-navigation.js";
|
|
3
6
|
import { DispatchShell } from "../../components/dispatch-shell.js";
|
|
4
7
|
export function meta() {
|
|
5
8
|
return [{ title: "Admin — Dispatch" }];
|
|
6
9
|
}
|
|
7
10
|
export default function AdminOverviewRoute() {
|
|
8
11
|
const t = useT();
|
|
12
|
+
const groups = useAdminNavGroups();
|
|
9
13
|
return (_jsx(DispatchShell, { title: t("dispatch.nav.admin", { defaultValue: "Admin" }), description: t("dispatch.pages.adminDescription", {
|
|
10
14
|
defaultValue: "Workspace controls and operations",
|
|
11
|
-
}), children:
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
}), children: _jsx("section", { className: "grid gap-4 sm:grid-cols-2 xl:grid-cols-3", children: groups.map((group, index) => (_jsx(AdminAreaCard, { group: group, index: index }, group.id))) }) }));
|
|
16
|
+
}
|
|
17
|
+
const GROUP_DESCRIPTIONS = {
|
|
18
|
+
workspace: "Apps, resources, and workspace setup",
|
|
19
|
+
operations: "Monitor runs, metrics, and audit history",
|
|
20
|
+
automation: "Control scheduled work and delivery",
|
|
21
|
+
connections: "Manage integrations, secrets, and messaging",
|
|
22
|
+
"agent-platform": "Manage connected agents and dreams",
|
|
23
|
+
"workspace-extensions": "Tools added by this workspace",
|
|
24
|
+
};
|
|
25
|
+
const GROUP_TONES = [
|
|
26
|
+
"bg-primary/10 text-primary",
|
|
27
|
+
"bg-secondary text-secondary-foreground",
|
|
28
|
+
"bg-accent text-accent-foreground",
|
|
29
|
+
"bg-muted text-foreground",
|
|
30
|
+
];
|
|
31
|
+
function AdminAreaCard({ group, index, }) {
|
|
32
|
+
const t = useT();
|
|
33
|
+
const GroupIcon = group.items[0]?.icon;
|
|
34
|
+
const tone = GROUP_TONES[index % GROUP_TONES.length];
|
|
35
|
+
return (_jsxs("div", { className: "rounded-2xl border border-transparent bg-card p-4 transition-[border-color,background-color] hover:border-border hover:bg-card/80", children: [_jsxs("div", { className: "flex items-start gap-3", children: [_jsx("span", { className: `flex size-10 shrink-0 items-center justify-center rounded-xl ${tone}`, children: GroupIcon ? _jsx(GroupIcon, { size: 19 }) : null }), _jsxs("div", { className: "min-w-0", children: [_jsx("h2", { className: "text-sm font-semibold text-foreground", children: t(group.labelKey, { defaultValue: group.label }) }), _jsx("p", { className: "mt-1 text-xs leading-5 text-muted-foreground", children: GROUP_DESCRIPTIONS[group.id] || "Workspace tools and controls" })] })] }), _jsx("div", { className: "mt-4 space-y-1", children: group.items
|
|
36
|
+
.filter((item) => item.id !== "admin-overview")
|
|
37
|
+
.map((item) => {
|
|
38
|
+
const ItemIcon = item.icon;
|
|
39
|
+
return (_jsxs(Link, { to: item.adminTo ?? item.to, className: "group flex min-h-9 items-center gap-2 rounded-lg px-2 text-sm text-muted-foreground transition-colors hover:bg-accent hover:text-foreground", children: [ItemIcon ? _jsx(ItemIcon, { size: 15, className: "shrink-0" }) : null, _jsx("span", { className: "min-w-0 flex-1 truncate", children: t(`dispatch.nav.${item.id}`, {
|
|
40
|
+
defaultValue: item.label,
|
|
41
|
+
}) }), _jsx(IconChevronRight, { size: 15, className: "shrink-0 opacity-0 transition-opacity group-hover:opacity-100" })] }, item.id));
|
|
42
|
+
}) })] }));
|
|
18
43
|
}
|
|
19
44
|
//# sourceMappingURL=admin._index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin._index.js","sourceRoot":"","sources":["../../../src/routes/pages/admin._index.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"admin._index.js","sourceRoot":"","sources":["../../../src/routes/pages/admin._index.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useT } from \"@agent-native/core/client/i18n\";\nimport { IconChevronRight } from \"@tabler/icons-react\";\nimport { Link } from \"react-router\";\n\nimport {\n useAdminNavGroups,\n type AdminNavGroup,\n} from \"../../components/admin-navigation\";\nimport { DispatchShell } from \"../../components/dispatch-shell\";\n\nexport function meta() {\n return [{ title: \"Admin — Dispatch\" }];\n}\n\nexport default function AdminOverviewRoute() {\n const t = useT();\n const groups = useAdminNavGroups();\n\n return (\n <DispatchShell\n title={t(\"dispatch.nav.admin\", { defaultValue: \"Admin\" })}\n description={t(\"dispatch.pages.adminDescription\", {\n defaultValue: \"Workspace controls and operations\",\n })}\n >\n <section className=\"grid gap-4 sm:grid-cols-2 xl:grid-cols-3\">\n {groups.map((group, index) => (\n <AdminAreaCard key={group.id} group={group} index={index} />\n ))}\n </section>\n </DispatchShell>\n );\n}\n\nconst GROUP_DESCRIPTIONS: Record<string, string> = {\n workspace: \"Apps, resources, and workspace setup\",\n operations: \"Monitor runs, metrics, and audit history\",\n automation: \"Control scheduled work and delivery\",\n connections: \"Manage integrations, secrets, and messaging\",\n \"agent-platform\": \"Manage connected agents and dreams\",\n \"workspace-extensions\": \"Tools added by this workspace\",\n};\n\nconst GROUP_TONES = [\n \"bg-primary/10 text-primary\",\n \"bg-secondary text-secondary-foreground\",\n \"bg-accent text-accent-foreground\",\n \"bg-muted text-foreground\",\n] as const;\n\nfunction AdminAreaCard({\n group,\n index,\n}: {\n group: AdminNavGroup;\n index: number;\n}) {\n const t = useT();\n const GroupIcon = group.items[0]?.icon;\n const tone = GROUP_TONES[index % GROUP_TONES.length];\n\n return (\n <div className=\"rounded-2xl border border-transparent bg-card p-4 transition-[border-color,background-color] hover:border-border hover:bg-card/80\">\n <div className=\"flex items-start gap-3\">\n <span\n className={`flex size-10 shrink-0 items-center justify-center rounded-xl ${tone}`}\n >\n {GroupIcon ? <GroupIcon size={19} /> : null}\n </span>\n <div className=\"min-w-0\">\n <h2 className=\"text-sm font-semibold text-foreground\">\n {t(group.labelKey, { defaultValue: group.label })}\n </h2>\n <p className=\"mt-1 text-xs leading-5 text-muted-foreground\">\n {GROUP_DESCRIPTIONS[group.id] || \"Workspace tools and controls\"}\n </p>\n </div>\n </div>\n\n <div className=\"mt-4 space-y-1\">\n {group.items\n .filter((item) => item.id !== \"admin-overview\")\n .map((item) => {\n const ItemIcon = item.icon;\n return (\n <Link\n key={item.id}\n to={item.adminTo ?? item.to}\n className=\"group flex min-h-9 items-center gap-2 rounded-lg px-2 text-sm text-muted-foreground transition-colors hover:bg-accent hover:text-foreground\"\n >\n {ItemIcon ? <ItemIcon size={15} className=\"shrink-0\" /> : null}\n <span className=\"min-w-0 flex-1 truncate\">\n {t(`dispatch.nav.${item.id}`, {\n defaultValue: item.label,\n })}\n </span>\n <IconChevronRight\n size={15}\n className=\"shrink-0 opacity-0 transition-opacity group-hover:opacity-100\"\n />\n </Link>\n );\n })}\n </div>\n </div>\n );\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apps.$appId.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/apps.$appId.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"apps.$appId.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/apps.$appId.tsx"],"names":[],"mappings":"AAkCA,wBAAgB,IAAI;;IAEnB;AAED,MAAM,CAAC,OAAO,UAAU,iBAAiB,oDAiMxC"}
|
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useActionQuery } from "@agent-native/core/client/hooks";
|
|
2
|
+
import { useActionMutation, useActionQuery, } from "@agent-native/core/client/hooks";
|
|
3
3
|
import { useT } from "@agent-native/core/client/i18n";
|
|
4
4
|
import { withBuilderUtmTrackingParams } from "@agent-native/core/shared/builder-link-tracking";
|
|
5
|
-
import { IconArrowLeft,
|
|
6
|
-
import { useEffect, useMemo } from "react";
|
|
7
|
-
import { Link,
|
|
5
|
+
import { IconArrowLeft, IconClockHour4 } from "@tabler/icons-react";
|
|
6
|
+
import { useEffect, useMemo, useState } from "react";
|
|
7
|
+
import { Link, useParams } from "react-router";
|
|
8
8
|
import { ActionQueryError } from "../../components/action-query-error.js";
|
|
9
|
-
import { DispatchShell } from "../../components/dispatch-shell.js";
|
|
10
9
|
import { Badge } from "../../components/ui/badge.js";
|
|
11
10
|
import { Button } from "../../components/ui/button.js";
|
|
12
11
|
import { Skeleton } from "../../components/ui/skeleton.js";
|
|
12
|
+
import { Spinner } from "../../components/ui/spinner.js";
|
|
13
13
|
import { workspaceAppHref, } from "../../lib/workspace-apps.js";
|
|
14
14
|
export function meta() {
|
|
15
15
|
return [{ title: "Workspace app - Dispatch" }];
|
|
16
16
|
}
|
|
17
17
|
export default function WorkspaceAppRoute() {
|
|
18
18
|
const t = useT();
|
|
19
|
-
const location = useLocation();
|
|
20
19
|
const { appId } = useParams();
|
|
21
20
|
const appsQuery = useActionQuery("list-workspace-apps", {
|
|
22
21
|
includeAgentCards: false,
|
|
@@ -24,14 +23,64 @@ export default function WorkspaceAppRoute() {
|
|
|
24
23
|
const { data: apps = [], isLoading } = appsQuery;
|
|
25
24
|
const app = useMemo(() => apps.find((item) => item.id === appId) ?? null, [appId, apps]);
|
|
26
25
|
const href = app ? workspaceAppHref(app) : null;
|
|
26
|
+
const [embedUrl, setEmbedUrl] = useState(null);
|
|
27
|
+
const [embedError, setEmbedError] = useState(null);
|
|
28
|
+
const [embedAttempt, setEmbedAttempt] = useState(0);
|
|
29
|
+
const createEmbedSession = useActionMutation("create_embed_session", {
|
|
30
|
+
skipActionQueryInvalidation: true,
|
|
31
|
+
});
|
|
32
|
+
const embedInput = useMemo(() => {
|
|
33
|
+
if (!app || !href)
|
|
34
|
+
return null;
|
|
35
|
+
const path = app.path.trim();
|
|
36
|
+
if (path.startsWith("/")) {
|
|
37
|
+
return { app: app.id, path, chrome: "minimal" };
|
|
38
|
+
}
|
|
39
|
+
return { app: app.id, url: href, chrome: "minimal" };
|
|
40
|
+
}, [app?.id, app?.path, href]);
|
|
27
41
|
useEffect(() => {
|
|
28
|
-
if (!app || app.status === "pending" || !
|
|
42
|
+
if (!app || app.status === "pending" || !embedInput)
|
|
29
43
|
return;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
44
|
+
let cancelled = false;
|
|
45
|
+
setEmbedUrl(null);
|
|
46
|
+
setEmbedError(null);
|
|
47
|
+
void createEmbedSession
|
|
48
|
+
.mutateAsync(embedInput)
|
|
49
|
+
.then((result) => {
|
|
50
|
+
if (!cancelled)
|
|
51
|
+
setEmbedUrl(result.startUrl);
|
|
52
|
+
})
|
|
53
|
+
.catch((cause) => {
|
|
54
|
+
if (!cancelled) {
|
|
55
|
+
setEmbedError(cause instanceof Error ? cause : new Error(String(cause)));
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
return () => {
|
|
59
|
+
cancelled = true;
|
|
60
|
+
};
|
|
61
|
+
}, [
|
|
62
|
+
app?.id,
|
|
63
|
+
app?.path,
|
|
64
|
+
app?.status,
|
|
65
|
+
createEmbedSession.mutateAsync,
|
|
66
|
+
embedAttempt,
|
|
67
|
+
embedInput,
|
|
68
|
+
]);
|
|
69
|
+
if (appsQuery.isError) {
|
|
70
|
+
return (_jsx("div", { className: "flex h-full min-h-0 items-center justify-center p-6", children: _jsx("div", { className: "w-full max-w-2xl", children: _jsx(ActionQueryError, { error: appsQuery.error, onRetry: () => void appsQuery.refetch() }) }) }));
|
|
71
|
+
}
|
|
72
|
+
if (isLoading && !app) {
|
|
73
|
+
return (_jsx("div", { className: "flex h-full min-h-0 items-center justify-center p-6", children: _jsxs("div", { className: "w-full max-w-2xl space-y-3 rounded-xl border bg-card p-6", children: [_jsx(Skeleton, { className: "h-5 w-48" }), _jsx(Skeleton, { className: "h-4 w-full" }), _jsx(Skeleton, { className: "h-4 w-2/3" })] }) }));
|
|
74
|
+
}
|
|
75
|
+
if (!app) {
|
|
76
|
+
return (_jsx("div", { className: "flex h-full min-h-0 items-center justify-center p-6", children: _jsxs("div", { className: "w-full max-w-2xl rounded-xl border bg-card p-6", children: [_jsx(Button, { asChild: true, size: "sm", variant: "ghost", className: "-ml-2 mb-4", children: _jsxs(Link, { to: "/apps", children: [_jsx(IconArrowLeft, { size: 15, className: "mr-1.5" }), t("dispatch.nav.apps")] }) }), _jsxs("div", { className: "space-y-3", children: [_jsx("h2", { className: "text-base font-semibold text-foreground", children: t("dispatch.pages.appNotFound") }), _jsx("p", { className: "text-sm text-muted-foreground", children: t("dispatch.pages.pageNotFoundDescription") })] })] }) }));
|
|
77
|
+
}
|
|
78
|
+
if (app.status === "pending") {
|
|
79
|
+
return (_jsx("div", { className: "flex h-full min-h-0 items-center justify-center p-6", children: _jsxs("div", { className: "w-full max-w-2xl rounded-xl border bg-card p-6", children: [_jsx(Button, { asChild: true, size: "sm", variant: "ghost", className: "-ml-2 mb-4", children: _jsxs(Link, { to: "/apps", children: [_jsx(IconArrowLeft, { size: 15, className: "mr-1.5" }), t("dispatch.nav.apps")] }) }), _jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx("h2", { className: "text-base font-semibold text-foreground", children: app.name }), _jsxs(Badge, { variant: "outline", className: "gap-1 border-amber-500/30 bg-amber-500/10 text-amber-700 dark:text-amber-300", children: [_jsx(IconClockHour4, { size: 12 }), t("dispatch.pages.building")] })] }), _jsxs("p", { className: "text-sm text-muted-foreground", children: [t("dispatch.pages.appBuildingPrefix"), " ", _jsx("span", { className: "font-mono text-foreground", children: app.path }), " ", t("dispatch.pages.appBuildingSuffix")] }), app.branchName ? (_jsx("p", { className: "text-xs text-muted-foreground", children: t("dispatch.pages.branch", { branch: app.branchName }) })) : null, app.builderUrl ? (_jsx(Button, { asChild: true, children: _jsx("a", { href: withBuilderUtmTrackingParams(app.builderUrl, {
|
|
80
|
+
campaign: "product",
|
|
81
|
+
content: "dispatch_branch",
|
|
82
|
+
}), target: "_blank", rel: "noreferrer", children: t("dispatch.pages.openBuilderBranch") }) })) : null] })] }) }));
|
|
83
|
+
}
|
|
84
|
+
return (_jsx("div", { "data-dispatch-workspace-app-host": true, className: "flex h-full min-h-0 flex-col bg-background", children: _jsx("div", { className: "min-h-0 flex-1 bg-muted/20", children: embedUrl ? (_jsx("iframe", { "data-dispatch-workspace-app-frame": true, src: embedUrl, title: app.name, referrerPolicy: "no-referrer", className: "h-full w-full border-0 bg-background" })) : embedError ? (_jsx("div", { className: "flex h-full items-center justify-center p-6", children: _jsx("div", { className: "w-full max-w-2xl", children: _jsx(ActionQueryError, { error: embedError, onRetry: () => setEmbedAttempt((attempt) => attempt + 1) }) }) })) : (_jsxs("div", { className: "flex h-full items-center justify-center", children: [_jsx(Spinner, { className: "size-5 text-muted-foreground" }), _jsx("span", { className: "sr-only", children: t("dispatch.pages.loading") })] })) }) }));
|
|
36
85
|
}
|
|
37
86
|
//# sourceMappingURL=apps.$appId.js.map
|