Skip to content

Commit 58cc2d3

Browse files
authored
Add widgets for editing examples (#107)
1 parent d5231a4 commit 58cc2d3

File tree

4 files changed

+434
-148
lines changed

4 files changed

+434
-148
lines changed
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
"use client";
2+
3+
import {
4+
AbsoluteCenter,
5+
Box,
6+
Button,
7+
Divider,
8+
IconButton,
9+
Table,
10+
TableCaption,
11+
Tbody,
12+
Td,
13+
Text,
14+
Th,
15+
Thead,
16+
Tr,
17+
} from "@chakra-ui/react";
18+
19+
import { TrashIcon } from "@heroicons/react/24/outline";
20+
import Form from "@rjsf/chakra-ui";
21+
import validator from "@rjsf/validator-ajv8";
22+
import { docco } from "react-syntax-highlighter/dist/esm/styles/hljs";
23+
24+
import SyntaxHighlighter from "react-syntax-highlighter";
25+
import {
26+
useCreateExample,
27+
useDeleteExample,
28+
useGetExtractor,
29+
useListExamples,
30+
} from "../utils/api";
31+
32+
type ExtractorProps = {
33+
extractorId: string;
34+
isShared: boolean;
35+
};
36+
37+
/**
38+
* Component to view and manage an extractor.
39+
*/
40+
const Examples = ({ extractorId }: { extractorId: string }) => {
41+
const listExamplesQuery = useListExamples({
42+
extractor_id: extractorId,
43+
limit: 10,
44+
offset: 0, // Hard code pagination for now
45+
});
46+
const useDeleteMutation = useDeleteExample();
47+
if (listExamplesQuery.isLoading) {
48+
return <div>Loading...</div>;
49+
}
50+
if (listExamplesQuery.isError) {
51+
return (
52+
<div>Unable to load examples for extractor with ID: {extractorId}</div>
53+
);
54+
}
55+
const data = listExamplesQuery.data;
56+
return (
57+
<div className="w-5/5">
58+
{data && data.length === 0 ? (
59+
<Text>Use the form below to add examples to the extractor</Text>
60+
) : (
61+
<Table variant="simple">
62+
<TableCaption placement={"top"}>
63+
View and Delete Examples
64+
</TableCaption>
65+
<Thead>
66+
<Tr>
67+
<Th>Content</Th>
68+
<Th>Output</Th>
69+
<Th>Action</Th>
70+
</Tr>
71+
</Thead>
72+
<Tbody>
73+
{data &&
74+
data.map((example) => (
75+
<Tr key={example.uuid}>
76+
<Td>{example.content}</Td>
77+
<Td>
78+
<SyntaxHighlighter language="json" style={docco}>
79+
{JSON.stringify(example.output, null, 2)}
80+
</SyntaxHighlighter>
81+
</Td>
82+
<Td>
83+
<IconButton
84+
onClick={() =>
85+
useDeleteMutation.mutate({ uuid: example.uuid })
86+
}
87+
variant={"outline"}
88+
isLoading={useDeleteMutation.isPending}
89+
colorScheme="red"
90+
aria-label="Delete example"
91+
icon={<TrashIcon />}
92+
/>
93+
</Td>
94+
</Tr>
95+
))}
96+
</Tbody>
97+
</Table>
98+
)}
99+
</div>
100+
);
101+
};
102+
103+
export const ExampleEditor = ({ extractorId, isShared }: ExtractorProps) => {
104+
const { data, isLoading, isError } = useGetExtractor(extractorId, isShared);
105+
const createExampleMutation = useCreateExample();
106+
if (isLoading) {
107+
return <div>Loading...</div>;
108+
}
109+
if (isError) {
110+
return <div>Unable to load extractor with ID: {extractorId}</div>;
111+
}
112+
113+
if (data === undefined) {
114+
throw new Error("Data is undefined");
115+
}
116+
117+
const newSchema = {
118+
type: "object",
119+
properties: {
120+
content: {
121+
type: "string",
122+
title: "Content",
123+
},
124+
output: {
125+
// Array of data.schema
126+
type: "array",
127+
items: {
128+
...data.schema,
129+
title: undefined,
130+
description: undefined,
131+
},
132+
},
133+
},
134+
required: ["content"],
135+
};
136+
137+
const UISchema = {
138+
content: {
139+
"ui:autoFocus": true,
140+
"ui:placeholder": "Enter contact to extract",
141+
"ui:widget": "textarea",
142+
"ui:description": "Enter the text to extract information from",
143+
},
144+
output: {
145+
"ui:autoFocus": false,
146+
"ui:title": "Outputs",
147+
},
148+
};
149+
150+
const handleAddExample = (
151+
/* eslint-disable @typescript-eslint/no-explicit-any */
152+
formData: any,
153+
) => {
154+
createExampleMutation.mutate({
155+
extractor_id: extractorId,
156+
content: formData.formData.content,
157+
output: formData.formData.output,
158+
});
159+
};
160+
161+
return (
162+
<div className="mr-auto">
163+
<Examples extractorId={extractorId} />
164+
<Box position="relative" padding="10">
165+
<Divider />
166+
<AbsoluteCenter bg="white" px="4">
167+
<Text>Add</Text>
168+
</AbsoluteCenter>
169+
</Box>
170+
<Form
171+
// @ts-expect-error - Need to investigate
172+
schema={newSchema}
173+
uiSchema={UISchema}
174+
validator={validator}
175+
onSubmit={(formData) => handleAddExample(formData)}
176+
>
177+
<div>
178+
<Button type="submit">Add Example</Button>
179+
</div>
180+
</Form>
181+
</div>
182+
);
183+
};

frontend/app/components/Extractor.tsx

Lines changed: 0 additions & 62 deletions
This file was deleted.

0 commit comments

Comments
 (0)