@agent-native/dispatch 0.4.0 → 0.5.1
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/index.d.ts.map +1 -1
- package/dist/actions/index.js +8 -0
- package/dist/actions/index.js.map +1 -1
- package/dist/components/layout/Layout.js +1 -1
- package/dist/components/layout/Layout.js.map +1 -1
- package/dist/components/workspace-app-card.d.ts.map +1 -1
- package/dist/components/workspace-app-card.js +33 -2
- package/dist/components/workspace-app-card.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.map +1 -1
- package/dist/routes/pages/apps.d.ts.map +1 -1
- package/dist/routes/pages/apps.js +41 -8
- package/dist/routes/pages/apps.js.map +1 -1
- package/dist/server/lib/app-creation-store.js +3 -3
- package/dist/server/lib/app-creation-store.js.map +1 -1
- package/package.json +2 -2
- package/src/actions/index.ts +4 -0
- package/src/components/layout/Layout.tsx +1 -1
- package/src/components/workspace-app-card.tsx +95 -5
- package/src/lib/workspace-apps.ts +1 -0
- package/src/routes/pages/apps.tsx +159 -6
- package/src/server/lib/app-creation-store.ts +3 -3
|
@@ -1,5 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import { useActionMutation, useActionQuery } from "@agent-native/core/client";
|
|
3
|
+
import {
|
|
4
|
+
IconApps,
|
|
5
|
+
IconBrush,
|
|
6
|
+
IconCalendarMonth,
|
|
7
|
+
IconChartBar,
|
|
8
|
+
IconClipboardList,
|
|
9
|
+
IconEyeOff,
|
|
10
|
+
IconFileText,
|
|
11
|
+
IconLoader2,
|
|
12
|
+
IconMail,
|
|
13
|
+
IconPlus,
|
|
14
|
+
IconPresentation,
|
|
15
|
+
IconScreenShare,
|
|
16
|
+
IconSparkles,
|
|
17
|
+
IconStack3,
|
|
18
|
+
IconVideo,
|
|
19
|
+
} from "@tabler/icons-react";
|
|
20
|
+
import { toast } from "sonner";
|
|
3
21
|
import { CreateAppPopover } from "@/components/create-app-popover";
|
|
4
22
|
import { DispatchShell } from "@/components/dispatch-shell";
|
|
5
23
|
import { WorkspaceAppCard } from "@/components/workspace-app-card";
|
|
@@ -16,10 +34,33 @@ interface WorkspaceInfo {
|
|
|
16
34
|
appCount: number;
|
|
17
35
|
}
|
|
18
36
|
|
|
37
|
+
interface AvailableTemplate {
|
|
38
|
+
name: string;
|
|
39
|
+
label: string;
|
|
40
|
+
hint: string;
|
|
41
|
+
icon: string;
|
|
42
|
+
color: string;
|
|
43
|
+
colorRgb: string;
|
|
44
|
+
core: boolean;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const TEMPLATE_ICONS: Record<string, typeof IconMail> = {
|
|
48
|
+
Mail: IconMail,
|
|
49
|
+
CalendarMonth: IconCalendarMonth,
|
|
50
|
+
FileText: IconFileText,
|
|
51
|
+
Presentation: IconPresentation,
|
|
52
|
+
ScreenShare: IconScreenShare,
|
|
53
|
+
ChartBar: IconChartBar,
|
|
54
|
+
ClipboardList: IconClipboardList,
|
|
55
|
+
Brush: IconBrush,
|
|
56
|
+
Video: IconVideo,
|
|
57
|
+
};
|
|
58
|
+
|
|
19
59
|
export default function AppsRoute() {
|
|
60
|
+
const [showHidden, setShowHidden] = useState(false);
|
|
20
61
|
const { data: apps = [] } = useActionQuery(
|
|
21
62
|
"list-workspace-apps",
|
|
22
|
-
{ includeAgentCards: false },
|
|
63
|
+
{ includeAgentCards: false, includeArchived: true },
|
|
23
64
|
{
|
|
24
65
|
refetchInterval: 2_000,
|
|
25
66
|
},
|
|
@@ -29,11 +70,20 @@ export default function AppsRoute() {
|
|
|
29
70
|
{},
|
|
30
71
|
{ staleTime: 60_000 },
|
|
31
72
|
);
|
|
73
|
+
const { data: templates = [] } = useActionQuery(
|
|
74
|
+
"list-available-workspace-templates",
|
|
75
|
+
{},
|
|
76
|
+
{ refetchInterval: 5_000 },
|
|
77
|
+
);
|
|
78
|
+
|
|
32
79
|
const ws = workspace as WorkspaceInfo | undefined;
|
|
33
80
|
const workspaceLabel = ws?.displayName ?? ws?.name ?? null;
|
|
34
|
-
const
|
|
81
|
+
const allApps = (apps as WorkspaceAppSummary[]).filter(
|
|
35
82
|
(app) => !app.isDispatch,
|
|
36
83
|
);
|
|
84
|
+
const visibleApps = allApps.filter((app) => !app.archived);
|
|
85
|
+
const archivedApps = allApps.filter((app) => app.archived);
|
|
86
|
+
const typedTemplates = templates as AvailableTemplate[];
|
|
37
87
|
|
|
38
88
|
return (
|
|
39
89
|
<DispatchShell
|
|
@@ -44,7 +94,7 @@ export default function AppsRoute() {
|
|
|
44
94
|
: "Open workspace apps and start new app creation from Dispatch."
|
|
45
95
|
}
|
|
46
96
|
>
|
|
47
|
-
<div className="space-y-
|
|
97
|
+
<div className="space-y-6">
|
|
48
98
|
<section className="space-y-3">
|
|
49
99
|
<div className="flex items-center justify-between gap-3">
|
|
50
100
|
<div className="flex items-center gap-2">
|
|
@@ -67,14 +117,117 @@ export default function AppsRoute() {
|
|
|
67
117
|
</div>
|
|
68
118
|
|
|
69
119
|
<div className="grid gap-3 md:grid-cols-2 xl:grid-cols-3">
|
|
70
|
-
{
|
|
120
|
+
{visibleApps.map((app) => (
|
|
71
121
|
<WorkspaceAppCard key={app.id} app={app} />
|
|
72
122
|
))}
|
|
73
123
|
|
|
74
124
|
<CreateAppPopover />
|
|
75
125
|
</div>
|
|
76
126
|
</section>
|
|
127
|
+
|
|
128
|
+
{typedTemplates.length > 0 ? (
|
|
129
|
+
<section className="space-y-3">
|
|
130
|
+
<div className="flex items-center gap-2">
|
|
131
|
+
<IconStack3 size={16} className="text-muted-foreground" />
|
|
132
|
+
<h2 className="text-sm font-semibold text-foreground">
|
|
133
|
+
Add a template
|
|
134
|
+
</h2>
|
|
135
|
+
<span className="text-xs text-muted-foreground">
|
|
136
|
+
Scaffold a first-party app into{" "}
|
|
137
|
+
<code className="font-mono text-[11px]">apps/</code>.
|
|
138
|
+
</span>
|
|
139
|
+
</div>
|
|
140
|
+
<div className="grid gap-3 md:grid-cols-2 xl:grid-cols-3">
|
|
141
|
+
{typedTemplates.map((template) => (
|
|
142
|
+
<AddTemplateCard key={template.name} template={template} />
|
|
143
|
+
))}
|
|
144
|
+
</div>
|
|
145
|
+
</section>
|
|
146
|
+
) : null}
|
|
147
|
+
|
|
148
|
+
{archivedApps.length > 0 ? (
|
|
149
|
+
<section className="space-y-3">
|
|
150
|
+
<button
|
|
151
|
+
type="button"
|
|
152
|
+
onClick={() => setShowHidden((cur) => !cur)}
|
|
153
|
+
className="inline-flex cursor-pointer items-center gap-2 text-xs text-muted-foreground hover:text-foreground"
|
|
154
|
+
>
|
|
155
|
+
<IconEyeOff size={14} />
|
|
156
|
+
{showHidden ? "Hide" : "Show"} {archivedApps.length} hidden{" "}
|
|
157
|
+
{archivedApps.length === 1 ? "app" : "apps"}
|
|
158
|
+
</button>
|
|
159
|
+
{showHidden ? (
|
|
160
|
+
<div className="grid gap-3 md:grid-cols-2 xl:grid-cols-3">
|
|
161
|
+
{archivedApps.map((app) => (
|
|
162
|
+
<WorkspaceAppCard key={app.id} app={app} />
|
|
163
|
+
))}
|
|
164
|
+
</div>
|
|
165
|
+
) : null}
|
|
166
|
+
</section>
|
|
167
|
+
) : null}
|
|
77
168
|
</div>
|
|
78
169
|
</DispatchShell>
|
|
79
170
|
);
|
|
80
171
|
}
|
|
172
|
+
|
|
173
|
+
function AddTemplateCard({ template }: { template: AvailableTemplate }) {
|
|
174
|
+
const Icon = TEMPLATE_ICONS[template.icon] ?? IconSparkles;
|
|
175
|
+
const scaffold = useActionMutation("scaffold-workspace-app", {
|
|
176
|
+
onSuccess: (result: any) => {
|
|
177
|
+
toast.success(
|
|
178
|
+
`Scaffolded apps/${result?.appId || template.name}. The gateway will pick it up shortly.`,
|
|
179
|
+
);
|
|
180
|
+
},
|
|
181
|
+
onError: (err) => {
|
|
182
|
+
toast.error(
|
|
183
|
+
`Could not scaffold ${template.label}: ${
|
|
184
|
+
err instanceof Error ? err.message : String(err)
|
|
185
|
+
}`,
|
|
186
|
+
);
|
|
187
|
+
},
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
return (
|
|
191
|
+
<div className="group relative flex items-start gap-3 rounded-lg border bg-card p-4 transition hover:border-foreground/30">
|
|
192
|
+
<div
|
|
193
|
+
className="flex h-9 w-9 shrink-0 items-center justify-center rounded-md"
|
|
194
|
+
style={{
|
|
195
|
+
backgroundColor: `rgb(${template.colorRgb} / 0.12)`,
|
|
196
|
+
color: template.color,
|
|
197
|
+
}}
|
|
198
|
+
>
|
|
199
|
+
<Icon size={18} />
|
|
200
|
+
</div>
|
|
201
|
+
<div className="min-w-0 flex-1">
|
|
202
|
+
<div className="flex min-w-0 items-center gap-2">
|
|
203
|
+
<h3 className="truncate text-sm font-semibold text-foreground">
|
|
204
|
+
{template.label}
|
|
205
|
+
</h3>
|
|
206
|
+
</div>
|
|
207
|
+
<p className="mt-1 line-clamp-2 text-xs leading-relaxed text-muted-foreground">
|
|
208
|
+
{template.hint}
|
|
209
|
+
</p>
|
|
210
|
+
<div className="mt-3">
|
|
211
|
+
<Button
|
|
212
|
+
size="sm"
|
|
213
|
+
variant="outline"
|
|
214
|
+
disabled={scaffold.isPending}
|
|
215
|
+
onClick={() => scaffold.mutate({ template: template.name })}
|
|
216
|
+
>
|
|
217
|
+
{scaffold.isPending ? (
|
|
218
|
+
<>
|
|
219
|
+
<IconLoader2 size={14} className="mr-1.5 animate-spin" />
|
|
220
|
+
Adding…
|
|
221
|
+
</>
|
|
222
|
+
) : (
|
|
223
|
+
<>
|
|
224
|
+
<IconPlus size={14} className="mr-1.5" />
|
|
225
|
+
Add to workspace
|
|
226
|
+
</>
|
|
227
|
+
)}
|
|
228
|
+
</Button>
|
|
229
|
+
</div>
|
|
230
|
+
</div>
|
|
231
|
+
</div>
|
|
232
|
+
);
|
|
233
|
+
}
|
|
@@ -782,7 +782,7 @@ const ADDABLE_TEMPLATES: AvailableWorkspaceTemplate[] = [
|
|
|
782
782
|
name: "calendar",
|
|
783
783
|
label: "Calendar",
|
|
784
784
|
hint: "Manage events, sync, and public booking",
|
|
785
|
-
icon: "
|
|
785
|
+
icon: "CalendarMonth",
|
|
786
786
|
color: "#8B5CF6",
|
|
787
787
|
colorRgb: "139 92 246",
|
|
788
788
|
core: true,
|
|
@@ -800,7 +800,7 @@ const ADDABLE_TEMPLATES: AvailableWorkspaceTemplate[] = [
|
|
|
800
800
|
name: "slides",
|
|
801
801
|
label: "Slides",
|
|
802
802
|
hint: "Generate and edit React presentations",
|
|
803
|
-
icon: "
|
|
803
|
+
icon: "Presentation",
|
|
804
804
|
color: "#EC4899",
|
|
805
805
|
colorRgb: "236 72 153",
|
|
806
806
|
core: true,
|
|
@@ -818,7 +818,7 @@ const ADDABLE_TEMPLATES: AvailableWorkspaceTemplate[] = [
|
|
|
818
818
|
name: "analytics",
|
|
819
819
|
label: "Analytics",
|
|
820
820
|
hint: "Connect data sources, prompt for charts",
|
|
821
|
-
icon: "
|
|
821
|
+
icon: "ChartBar",
|
|
822
822
|
color: "#F59E0B",
|
|
823
823
|
colorRgb: "245 158 11",
|
|
824
824
|
core: true,
|