diff --git a/gui/rpk-gui/src/lib/crud/components/crud-filters.tsx b/gui/rpk-gui/src/lib/crud/components/crud-filters.tsx index a2312ca..3b8fcbd 100644 --- a/gui/rpk-gui/src/lib/crud/components/crud-filters.tsx +++ b/gui/rpk-gui/src/lib/crud/components/crud-filters.tsx @@ -1,10 +1,8 @@ -import { useEffect, useState } from "react"; -import { jsonschemaProvider } from "../providers/jsonschema-provider"; import { Accordion, AccordionDetails, AccordionSummary, CircularProgress } from "@mui/material"; import FilterForm from "../../filter-form/components/filter-form"; import TextField from "@mui/material/TextField"; -import { useSearchParams } from "react-router"; import { GridExpandMoreIcon } from "@mui/x-data-grid"; +import { useResourceFilter } from "../hook"; export type OnChangeValue = { search: string | null @@ -19,24 +17,7 @@ type CrudFiltersProps = { const CrudFilters = (props: CrudFiltersProps) => { const { resourceName, resourcePath, onChange } = props - - const [hasSearch, setHasSearch] = useState(false) - const [filtersSchema, setFiltersSchema] = useState([]) - const [filtersLoading, setFiltersLoading] = useState(true); - useEffect(() => { - const fetchSchema = async () => { - try { - setHasSearch(await jsonschemaProvider.hasSearch(resourcePath)) - const resourceFilters = await jsonschemaProvider.getListFilters(resourceName, resourcePath) - setFiltersSchema(resourceFilters); - setFiltersLoading(false); - } catch (error) { - console.error('Error fetching data:', error); - setFiltersLoading(false); - } - }; - fetchSchema(); - }, []); + const { hasSearch, filtersSchema, filtersLoading } = useResourceFilter(resourceName, resourcePath) if (filtersLoading) { return @@ -81,8 +62,6 @@ type SearchFilter = { const SearchFilter = (props: SearchFilter) => { const {value, onChange} = props; - const [searchParams, setSearchParams] = useSearchParams(); - return ( = (props) => { const { schemaName, uiSchema, record, resourceBasePath, defaultValue, children, onSubmit=(data: any) => {}, card=false } = props; - - const [schema, setSchema] = useState({}); - const [schemaLoading, setSchemaLoading] = useState(true); - useEffect(() => { - const fetchSchema = async () => { - try { - let resourceSchema - if (record === undefined) { - resourceSchema = await jsonschemaProvider.getCreateResourceSchema(schemaName); - } else { - if (card) { - resourceSchema = await jsonschemaProvider.getCardResourceSchema(schemaName); - } else { - resourceSchema = await jsonschemaProvider.getUpdateResourceSchema(schemaName); - } - } - setSchema(resourceSchema); - setSchemaLoading(false); - } catch (error) { - console.error('Error fetching data:', error); - setSchemaLoading(false); - } - }; - fetchSchema(); - }, []); + const type = record === undefined ? "create" : card ? "card" : "update" + const { schema, schemaLoading } = useResourceSchema(schemaName, type); if(schemaLoading) { return diff --git a/gui/rpk-gui/src/lib/crud/components/crud-list.tsx b/gui/rpk-gui/src/lib/crud/components/crud-list.tsx index 9943abe..fef2b95 100644 --- a/gui/rpk-gui/src/lib/crud/components/crud-list.tsx +++ b/gui/rpk-gui/src/lib/crud/components/crud-list.tsx @@ -1,8 +1,7 @@ +import { CircularProgress } from "@mui/material"; import { DataGrid, GridColDef, GridColumnVisibilityModel, GridValidRowModel } from "@mui/x-data-grid"; import { UiSchema } from "@rjsf/utils"; -import React, { useEffect, useState } from "react"; -import { jsonschemaProvider } from "../providers/jsonschema-provider"; -import { CircularProgress } from "@mui/material"; +import { useResourceColumns } from "../hook"; type CrudListProps = { schemaName: string, @@ -32,24 +31,9 @@ const CrudList = (props: CrudListProps) => { columnDefinitions } = props; - const [columnSchema, setColumnSchema] = useState>() - const [schemaLoading, setSchemaLoading] = useState(true); - useEffect(() => { - const fetchSchema = async () => { - try { - const resourceColumns = await jsonschemaProvider.getReadResourceColumns(schemaName) - const definedColumns = computeColumnSchema(columnDefinitions, resourceColumns) - setColumnSchema(definedColumns); - setSchemaLoading(false); - } catch (error) { - console.error('Error fetching data:', error); - setSchemaLoading(false); - } - }; - fetchSchema(); - }, []); + const { columnSchema, columnLoading } = useResourceColumns(schemaName, columnDefinitions); - if (schemaLoading || columnSchema === undefined) { + if (columnLoading || columnSchema === undefined) { return } @@ -69,26 +53,4 @@ const CrudList = (props: CrudListProps) => { ) } -function computeColumnSchema(definitionColumns: ColumnDefinition[], resourceColumns: GridColDef[]): ColumnSchema { - //reorder resourceColumns as in definition - definitionColumns.slice().reverse().forEach(first => { - resourceColumns.sort(function(x,y){ return x.field == first.field ? -1 : y.field == first.field ? 1 : 0; }); - }) - - let visibilityModel: GridColumnVisibilityModel = {} - resourceColumns.forEach((resource, index) =>{ - visibilityModel[resource.field] = definitionColumns.some(col => col.field == resource.field && !col.hide) - definitionColumns.forEach((def) => { - if (def.field == resource.field) { - resourceColumns[index] = {...resource, ...def.column}; - } - }) - }) - - return { - columns: resourceColumns, - columnVisibilityModel: visibilityModel - } -} - export default CrudList; diff --git a/gui/rpk-gui/src/lib/crud/hook/index.tsx b/gui/rpk-gui/src/lib/crud/hook/index.tsx new file mode 100644 index 0000000..aca9ab9 --- /dev/null +++ b/gui/rpk-gui/src/lib/crud/hook/index.tsx @@ -0,0 +1,109 @@ +import { useEffect, useState } from "react"; +import { jsonschemaProvider } from "../providers/jsonschema-provider"; +import { GridColDef, GridColumnVisibilityModel, GridValidRowModel } from "@mui/x-data-grid"; + +type ResourceSchemaType = "create" | "update" | "card"; + +export function useResourceSchema(schemaName: string, type: ResourceSchemaType) { + const [schema, setSchema] = useState({}); + const [schemaLoading, setSchemaLoading] = useState(true); + + useEffect(() => { + const fetchSchema = async () => { + try { + let resourceSchema + if (type == "create") { + resourceSchema = await jsonschemaProvider.getCreateResourceSchema(schemaName); + } else if (type == "update") { + resourceSchema = await jsonschemaProvider.getCardResourceSchema(schemaName); + } else { + resourceSchema = await jsonschemaProvider.getUpdateResourceSchema(schemaName); + } + setSchema(resourceSchema); + setSchemaLoading(false); + } catch (error) { + console.error(`Error while retrieving schema: ${schemaName} `, error); + setSchemaLoading(false); + } + }; + fetchSchema(); + }, []); + + return { schema, schemaLoading } +} + +type ColumnSchema = { + columns: GridColDef[], + columnVisibilityModel: GridColumnVisibilityModel +} + +type ColumnDefinition = { + field: string, + column: Partial, + hide?: boolean +} + +export function useResourceColumns(schemaName: string, columnDefinitions: ColumnDefinition[]) { + const [columnSchema, setColumnSchema] = useState>() + const [columnLoading, setColumnLoading] = useState(true); + useEffect(() => { + const fetchSchema = async () => { + try { + const resourceColumns = await jsonschemaProvider.getReadResourceColumns(schemaName) + const definedColumns = computeColumnSchema(columnDefinitions, resourceColumns) + setColumnSchema(definedColumns); + setColumnLoading(false); + } catch (error) { + console.error('Error while retrieving columns schema:', error); + setColumnLoading(false); + } + }; + fetchSchema(); + }, []); + + return { columnSchema, columnLoading } +} + +function computeColumnSchema(definitionColumns: ColumnDefinition[], resourceColumns: GridColDef[]): ColumnSchema { + //reorder resourceColumns as in definition + definitionColumns.slice().reverse().forEach(first => { + resourceColumns.sort(function(x,y){ return x.field == first.field ? -1 : y.field == first.field ? 1 : 0; }); + }) + + let visibilityModel: GridColumnVisibilityModel = {} + resourceColumns.forEach((resource, index) =>{ + visibilityModel[resource.field] = definitionColumns.some(col => col.field == resource.field && !col.hide) + definitionColumns.forEach((def) => { + if (def.field == resource.field) { + resourceColumns[index] = {...resource, ...def.column}; + } + }) + }) + + return { + columns: resourceColumns, + columnVisibilityModel: visibilityModel + } +} + +export function useResourceFilter(resourceName: string, resourcePath: string) { + const [hasSearch, setHasSearch] = useState(false) + const [filtersSchema, setFiltersSchema] = useState([]) + const [filtersLoading, setFiltersLoading] = useState(true); + useEffect(() => { + const fetchSchema = async () => { + try { + setHasSearch(await jsonschemaProvider.hasSearch(resourcePath)) + const resourceFilters = await jsonschemaProvider.getListFilters(resourceName, resourcePath) + setFiltersSchema(resourceFilters); + setFiltersLoading(false); + } catch (error) { + console.error('Error while retrieving filter schema:', error); + setFiltersLoading(false); + } + }; + fetchSchema(); + }, []); + + return { hasSearch, filtersSchema, filtersLoading } +}