diff --git a/gui/rpk-gui/src/lib/crud/components/widgets/foreign-key.tsx b/gui/rpk-gui/src/lib/crud/components/widgets/foreign-key.tsx index b9580f4..f0b1b48 100644 --- a/gui/rpk-gui/src/lib/crud/components/widgets/foreign-key.tsx +++ b/gui/rpk-gui/src/lib/crud/components/widgets/foreign-key.tsx @@ -1,11 +1,11 @@ -import {FormContextType, RJSFSchema, StrictRJSFSchema, WidgetProps} from '@rjsf/utils'; -import { Autocomplete } from "@mui/material"; -import { useState, useEffect } from "react"; -import TextField from "@mui/material/TextField"; -import {BaseRecord, useList, useOne} from "@refinedev/core"; +import {FormContextType, RJSFSchema, WidgetProps} from '@rjsf/utils'; +import { Autocomplete, CircularProgress, TextField } from "@mui/material"; +import React, { useState, useEffect, useContext } from "react"; +import { useList, useOne } from "@refinedev/core"; +import { ResourceContext } from "../../contexts/ResourceContext"; type ForeignKeySchema = RJSFSchema & { - foreign_key?: { + foreignKey?: { reference: { resource: string, label: string @@ -16,59 +16,90 @@ type ForeignKeySchema = RJSFSchema & { export default function ForeignKeyWidget( props: WidgetProps ) { - if (props.schema.foreign_key === undefined) { + if (props.schema.foreignKey === undefined) { return; } - const resource = props.schema.foreign_key.reference.resource - const labelField = props.schema.foreign_key.reference.label + const { onChange, value: originalValue } = props; + const [initialState, setInitialState] = useState(true); + if (originalValue != null && initialState) { + return {setInitialState(false); onChange(null)}}/> + } - const valueResult = useOne({ - resource: resource, - id: props.value != null ? props.value : undefined + return ( + + ) +}; + +const InitialValue = ( + props: WidgetProps & { onClear: () => void } +) => { + const { onClear, value } = props; + + if (props.schema.foreignKey === undefined) { + return; + } + const { resource, label: labelField = "label" } = props.schema.foreignKey.reference + const { basePath } = useContext(ResourceContext) + + const { data, isLoading } = useOne({ + resource: `${basePath}/${resource}`, + id: value }); - const empty_option: BaseRecord = { - id: undefined - } - empty_option[labelField] = "(None)" - - const [inputValue, setInputValue] = useState(""); - const [selectedValue, setSelectedValue] = useState(valueResult.data?.data || null); - const [debouncedInputValue, setDebouncedInputValue] = useState(inputValue); - - useEffect(() => { - const handler = setTimeout(() => setDebouncedInputValue(inputValue), 300); // Adjust debounce delay as needed - return () => clearTimeout(handler); - }, [inputValue]); - - const listResult = useList({ - resource: resource, - pagination: { current: 1, pageSize: 10 }, - filters: [{ field: "name", operator: "contains", value: debouncedInputValue }], - sorters: [{ field: "name", order: "asc" }], - }); - - const options = listResult.data?.data || []; - if (! props.required) { - options.unshift(empty_option); - } - const isLoading = listResult.isLoading || valueResult.isLoading; - - if(! selectedValue && valueResult.data) { - setSelectedValue(valueResult.data?.data) + if (isLoading || data === undefined) { + return } return ( { - setSelectedValue(newValue ? newValue : empty_option); - props.onChange(newValue ? newValue.id : null); + value={data.data} + onChange={() => onClear()} + onInputChange={() => onClear()} + options={[data.data]} + getOptionLabel={(option) => option ? option[labelField] : ""} + loading={isLoading} + renderInput={(params) => ( + + )} + /> + ) +} + +const RealAutocomplete = ( + props: WidgetProps +) => { + if (props.schema.foreignKey === undefined) { + return; + } + const { onChange } = props + + const [searchString, setSearchString] = useState(""); + const [debouncedInputValue, setDebouncedInputValue] = useState(); + useEffect(() => { + const handler = setTimeout(() => setDebouncedInputValue(searchString), 300); // Adjust debounce delay as needed + return () => clearTimeout(handler); + }, [searchString]); + + const { resource, label: labelField = "label" } = props.schema.foreignKey.reference + const { basePath } = useContext(ResourceContext) + const { data, isLoading } = useList({ + resource: `${basePath}/${resource}`, + pagination: { current: 1, pageSize: 10, mode: "server" }, + filters: [{ field: "label", operator: "contains", value: debouncedInputValue }], + sorters: [{ field: "label", order: "asc" }], + }); + + return ( + { + onChange(value ? value.id : null); return true; }} - //inputValue={inputValue} - onInputChange={(event, newInputValue) => setInputValue(newInputValue)} - options={options} + onInputChange={(event, newInputValue) => { + setSearchString(newInputValue) + console.log(newInputValue) + }} + options={data ? data.data : []} getOptionLabel={(option) => option ? option[labelField] : ""} loading={isLoading} renderInput={(params) => ( @@ -76,4 +107,4 @@ export default function ForeignKeyWidget ); -}; +}