diff --git a/frontend/src/components/types/index.ts b/frontend/src/components/types/index.ts index 7af1c545..a7ff5405 100644 --- a/frontend/src/components/types/index.ts +++ b/frontend/src/components/types/index.ts @@ -8,6 +8,7 @@ export type InputProps = { maxLength?: number; name?: string; placeholder?: string; + label?: string; className?: string; children?: React.ReactElement; onChange: ( diff --git a/frontend/src/upload/Upload.tsx b/frontend/src/upload/Upload.tsx index d2188966..0dfcc89a 100644 --- a/frontend/src/upload/Upload.tsx +++ b/frontend/src/upload/Upload.tsx @@ -8,6 +8,7 @@ import FileUpload from '../assets/file_upload.svg'; import WebsiteCollect from '../assets/website_collect.svg'; import Dropdown from '../components/Dropdown'; import Input from '../components/Input'; +import ToggleSwitch from '../components/ToggleSwitch'; import { ActiveState, Doc } from '../models/misc'; import { getDocs } from '../preferences/preferenceApi'; import { @@ -23,7 +24,9 @@ import { GithubIngestorConfig, CrawlerIngestorConfig, UrlIngestorConfig, + IngestorFormSchemas, } from './types/ingestor'; +import { IngestorDefaultConfigs } from '../upload/types/ingestor'; type IngestorState = { type: IngestorType; @@ -53,14 +56,111 @@ function Upload({ const [files, setfiles] = useState(receivedFile); const [activeTab, setActiveTab] = useState(renderTab); + const renderFormFields = () => { + const schema = IngestorFormSchemas[ingestor.type]; + + return schema.map((field) => { + switch (field.type) { + case 'string': + return ( +
+ +
+ ); + case 'number': + return ( +
+ +
+ ); + case 'enum': + return ( +
+ { + const syntheticEvent = { + target: { + name: field.name, + value: + typeof value === 'string' + ? value + : JSON.stringify(value), + }, + } as React.ChangeEvent; + handleIngestorChange(syntheticEvent); + }} + size="w-full" + rounded="3xl" + placeholder={field.label} + border="border" + borderColor="gray-5000" + /> +
+ ); + case 'boolean': + return ( +
+ { + const syntheticEvent = { + target: { + name: field.name, + value: checked, + }, + } as unknown as React.ChangeEvent; + handleIngestorChange(syntheticEvent); + }} + className="mt-2" + /> +
+ ); + default: + return null; + } + }); + }; + // New unified ingestor state - const [ingestor, setIngestor] = useState({ - type: 'crawler', - name: '', - config: { - name: '', - url: '', - } as CrawlerIngestorConfig, + const [ingestor, setIngestor] = useState(() => { + const defaultType: IngestorType = 'crawler'; + const defaultConfig = IngestorDefaultConfigs[defaultType]; + return { + type: defaultType, + name: defaultConfig.name, + config: defaultConfig.config, + }; }); const [progress, setProgress] = useState<{ @@ -474,47 +574,12 @@ function Upload({ }; const handleIngestorTypeChange = (type: IngestorType) => { - let newConfig: - | RedditIngestorConfig - | GithubIngestorConfig - | CrawlerIngestorConfig - | UrlIngestorConfig; - - switch (type) { - case 'reddit': - newConfig = { - name: ingestor.name, - client_id: '', - client_secret: '', - user_agent: '', - search_queries: [], - number_posts: 10, - }; - break; - case 'github': - newConfig = { - name: ingestor.name, - repo_url: '', - }; - break; - case 'crawler': - case 'url': - newConfig = { - name: ingestor.name, - url: '', - }; - break; - default: - newConfig = { - name: ingestor.name, - url: '', - } as CrawlerIngestorConfig; - } + const defaultConfig = IngestorDefaultConfigs[type]; setIngestor({ type, - name: ingestor.name, - config: newConfig, + name: defaultConfig.name, + config: defaultConfig.config, }); }; @@ -611,97 +676,17 @@ function Upload({ opt.value === ingestor.type) || null + } onSelect={(selected: { label: string; value: string }) => handleIngestorTypeChange(selected.value as IngestorType) } size="w-full" rounded="3xl" /> - {ingestor.type === 'reddit' ? ( - <> - - - - - - - ) : ingestor.type === 'github' ? ( - - ) : ( - <> - - setIngestor({ ...ingestor, name: e.target.value }) - } - borderVariant="thin" - /> - - - )} + {/* Dynamically render form fields based on schema */} + {renderFormFields()} )}
diff --git a/frontend/src/upload/types/ingestor.ts b/frontend/src/upload/types/ingestor.ts index 6a4db869..f9a4f879 100644 --- a/frontend/src/upload/types/ingestor.ts +++ b/frontend/src/upload/types/ingestor.ts @@ -41,3 +41,121 @@ export type IngestorFormData = { source: IngestorType; data: string; }; + +export type FieldType = 'string' | 'number' | 'enum' | 'boolean'; + +export interface FormField { + name: keyof BaseIngestorConfig | string; + label: string; + type: FieldType; + options?: { label: string; value: string }[]; +} + +export const IngestorFormSchemas: Record = { + crawler: [ + { + name: 'name', + label: 'Name', + type: 'string', + }, + { + name: 'url', + label: 'URL', + type: 'string', + }, + ], + url: [ + { + name: 'name', + label: 'Name', + type: 'string', + }, + { + name: 'url', + label: 'URL', + type: 'string', + }, + ], + reddit: [ + { + name: 'name', + label: 'Name', + type: 'string', + }, + { + name: 'client_id', + label: 'Client ID', + type: 'string', + }, + { + name: 'client_secret', + label: 'Client Secret', + type: 'string', + }, + { + name: 'user_agent', + label: 'User Agent', + type: 'string', + }, + { + name: 'search_queries', + label: 'Search Queries', + type: 'string', + }, + { + name: 'number_posts', + label: 'Number of Posts', + type: 'number', + }, + ], + github: [ + { + name: 'name', + label: 'Name', + type: 'string', + }, + { + name: 'repo_url', + label: 'Repository URL', + type: 'string', + }, + ], +}; + +export const IngestorDefaultConfigs: Record< + IngestorType, + Omit +> = { + crawler: { + name: '', + config: { + name: '', + url: '', + } as CrawlerIngestorConfig, + }, + url: { + name: '', + config: { + name: '', + url: '', + } as UrlIngestorConfig, + }, + reddit: { + name: '', + config: { + name: '', + client_id: '', + client_secret: '', + user_agent: '', + search_queries: [], + number_posts: 10, + } as RedditIngestorConfig, + }, + github: { + name: '', + config: { + name: '', + repo_url: '', + } as GithubIngestorConfig, + }, +};