Skip to content

Commit bd41d12

Browse files
feat: Add KnowledgePackCard, CreateKnowledgePackForm components and API endpoints for managing knowledge packs
1 parent d42d5c9 commit bd41d12

1 file changed

Lines changed: 228 additions & 0 deletions

File tree

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
'use client'
2+
import {
3+
Tabs,
4+
TabsList,
5+
TabsTrigger,
6+
TabsContent,
7+
Button,
8+
DataTable,
9+
Checkbox,
10+
Badge,
11+
} from '@magickml/client-ui'
12+
13+
import { createEmbedderReactClient } from '@magickml/embedder-client-react'
14+
import { useAtomValue, useAtom } from 'jotai'
15+
import { WindowContainer, WindowHeader } from 'windows-shared'
16+
import { LoaderPicker } from './loader-picker'
17+
import KnowledgePackCard from '../_pkg/knowledge-pack-card'
18+
import CreateKnowledgePackForm from '../_pkg/create-pack'
19+
import { activePackIdAtom } from '../_pkg/state'
20+
import { embedderTokenAtom } from '../_pkg/state'
21+
import { Loader } from '@magickml/embedder/schema'
22+
import { ColumnDef } from '@tanstack/react-table'
23+
24+
type KnowledgeWindowProps = {
25+
token: string
26+
}
27+
export const KnowledgeWindow: React.FC<KnowledgeWindowProps> = () => {
28+
const token = useAtomValue(embedderTokenAtom)
29+
const client = createEmbedderReactClient({
30+
tsqPrefix: 'embedder',
31+
baseUrl:
32+
process.env.NEXT_PUBLIC_EMBEDDER_URL || 'http://localhost:3000/api',
33+
options: {
34+
axiosConfig: {
35+
withCredentials: true,
36+
headers: {
37+
Authorization: `Bearer ${token}`,
38+
},
39+
},
40+
},
41+
})
42+
43+
const { data: knowledgePacks } = client.useGetPacksByEntityAndOwner()
44+
45+
const [activePackId, setActivePackId] = useAtom(activePackIdAtom)
46+
47+
const { data: activePack } = client.useFindPack(
48+
{
49+
params: {
50+
id: activePackId || '',
51+
},
52+
},
53+
{
54+
enabled: !!activePackId,
55+
}
56+
)
57+
58+
const columns: ColumnDef<Loader, unknown>[] = [
59+
{
60+
id: 'select',
61+
header: ({ table }) => (
62+
<Checkbox
63+
checked={table.getIsAllPageRowsSelected()}
64+
onCheckedChange={value => table.toggleAllPageRowsSelected(!!value)}
65+
aria-label="Select all"
66+
/>
67+
),
68+
cell: ({ row }) => (
69+
<Checkbox
70+
checked={row.getIsSelected()}
71+
onCheckedChange={value => row.toggleSelected(!!value)}
72+
aria-label="Select row"
73+
/>
74+
),
75+
enableSorting: false,
76+
enableHiding: false,
77+
},
78+
{
79+
accessorKey: 'name',
80+
header: 'Name',
81+
cell: ({ row }) => <span className="text-xs">{row.original.name}</span>,
82+
},
83+
{
84+
accessorKey: 'type',
85+
header: 'Type',
86+
cell: ({ row }) => <span className="text-xs">{row.original.type}</span>,
87+
},
88+
89+
// {
90+
// accessorKey: 'sourceUrl',
91+
// header: 'Source URL',
92+
// size: 48,
93+
// maxSize: 48,
94+
// cell: ({ row }) => (
95+
// <span className="text-xs">
96+
// {row.original.sourceUrl ? row.original.sourceUrl : 'N/A'}
97+
// </span>
98+
// ),
99+
// },
100+
101+
{
102+
accessorKey: 'config',
103+
header: 'Source',
104+
cell: ({ row }) => (
105+
<span className="text-xs">{JSON.stringify(row.original.config)}</span>
106+
),
107+
},
108+
109+
{
110+
accessorKey: 'status',
111+
header: 'Status',
112+
// cell: ({ row }) => <span className="text-xs">{row.original.status}</span>,
113+
cell: ({ row }) => {
114+
switch (row.original.status) {
115+
case 'failed':
116+
return <Badge variant="destructive">{row.original.status}</Badge>
117+
case 'completed':
118+
return <Badge variant="secondary">{row.original.status}</Badge>
119+
case 'processing':
120+
return <Badge variant="outline">{row.original.status}</Badge>
121+
case 'pending':
122+
return <Badge variant="outline">{row.original.status}</Badge>
123+
default:
124+
return <Badge variant="outline">{row.original.status}</Badge>
125+
}
126+
},
127+
},
128+
]
129+
130+
return (
131+
<WindowContainer>
132+
<WindowHeader
133+
title={activePackId ? 'Knowledge Pack' : 'Knowledge'}
134+
description="Manage knowledge for your agent."
135+
/>
136+
<div className="px-8">
137+
<div className="flex items-center justify-between">
138+
{!activePackId ? (
139+
<Tabs key="kp" className="w-full" defaultValue="yours">
140+
<TabsList className="">
141+
<TabsTrigger value="yours">Yours</TabsTrigger>
142+
<TabsTrigger disabled value="official">
143+
Official
144+
</TabsTrigger>
145+
</TabsList>
146+
<TabsContent value="yours">
147+
<div className="flex items-center justify-between py-2">
148+
<h2 className="text-xl font-semibold">Knowledge Packs</h2>
149+
<CreateKnowledgePackForm client={client} />
150+
</div>
151+
<div className="grid grid-cols-4 gap-4">
152+
{knowledgePacks?.map((pack, index) => (
153+
<KnowledgePackCard
154+
id={pack.id}
155+
key={index}
156+
title={pack.name || ''}
157+
description={pack.description || ''}
158+
model={'Model 1'}
159+
created={pack.createdAt.toString()}
160+
updated={pack.createdAt.toString()}
161+
documents={10}
162+
/>
163+
))}
164+
</div>
165+
</TabsContent>
166+
</Tabs>
167+
) : (
168+
<Tabs key={activePackId} className="w-full" defaultValue="view">
169+
<TabsList className="">
170+
<TabsTrigger value="view">View</TabsTrigger>
171+
<TabsTrigger value="add">Add</TabsTrigger>
172+
</TabsList>
173+
174+
<TabsContent value="view">
175+
<DataTable<Loader, unknown>
176+
columns={columns}
177+
data={activePack?.loaders ?? []}
178+
filterInputPlaceholder="Search knowledge by id"
179+
columnVisibilityButtonProps={{
180+
children: 'Columns',
181+
}}
182+
renderRowActionMenu={() => null}
183+
paginationDivProps={{
184+
className: 'flex items-center justify-end space-x-2 py-4',
185+
}}
186+
pageCountDivProps={{
187+
className: 'flex-1 text-sm text-muted-foreground',
188+
}}
189+
previousButtonProps={{
190+
variant: 'outline',
191+
size: 'sm',
192+
// onClick: () =>
193+
// setPage(prevPage => Math.max(prevPage - 1, 1)),
194+
// disabled: page === 1,
195+
children: 'Previous',
196+
}}
197+
// nextButtonProps={{
198+
// variant: 'outline',
199+
// size: 'sm',
200+
// onClick: () => {
201+
// if (
202+
// knowledge &&2
203+
// page < Math.ceil(knowledge.total / limit)
204+
// ) {
205+
// setPage(prevPage => prevPage + 1)
206+
// }
207+
// },
208+
// disabled:
209+
// knowledge && page >= Math.ceil(knowledge.total / limit),
210+
// children: 'Next',
211+
// }}
212+
/>
213+
214+
<Button variant="outline" onClick={() => setActivePackId(null)}>
215+
Back
216+
</Button>
217+
</TabsContent>
218+
219+
<TabsContent value="add">
220+
<LoaderPicker client={client} />
221+
</TabsContent>
222+
</Tabs>
223+
)}
224+
</div>
225+
</div>
226+
</WindowContainer>
227+
)
228+
}

0 commit comments

Comments
 (0)