diff --git a/client/src/pages/filaments/create.tsx b/client/src/pages/filaments/create.tsx index c6be378..44c45fc 100644 --- a/client/src/pages/filaments/create.tsx +++ b/client/src/pages/filaments/create.tsx @@ -4,6 +4,8 @@ import { Create, useForm, useSelect } from "@refinedev/antd"; import { Form, Input, Select, InputNumber, ColorPicker } from "antd"; import TextArea from "antd/es/input/TextArea"; import { numberFormatter, numberParser } from "../../utils/parsing"; +import { IVendor } from "../vendors/model"; +import { IFilament } from "./model"; interface CreateOrCloneProps { mode: "create" | "clone"; @@ -12,7 +14,7 @@ interface CreateOrCloneProps { export const FilamentCreate: React.FC< IResourceComponentsProps & CreateOrCloneProps > = (props) => { - const { formProps, saveButtonProps, formLoading } = useForm(); + const { formProps, saveButtonProps, formLoading } = useForm(); if (props.mode === "clone" && formProps.initialValues) { // Fix the vendor_id @@ -21,7 +23,7 @@ export const FilamentCreate: React.FC< } } - const { selectProps } = useSelect({ + const { selectProps } = useSelect({ resource: "vendor", optionLabel: "name", }); diff --git a/client/src/pages/filaments/edit.tsx b/client/src/pages/filaments/edit.tsx index 7d98b52..a7aa7cb 100644 --- a/client/src/pages/filaments/edit.tsx +++ b/client/src/pages/filaments/edit.tsx @@ -12,11 +12,13 @@ import { import dayjs from "dayjs"; import TextArea from "antd/es/input/TextArea"; import { numberFormatter, numberParser } from "../../utils/parsing"; +import { IVendor } from "../vendors/model"; +import { IFilament } from "./model"; export const FilamentEdit: React.FC = () => { - const { formProps, saveButtonProps } = useForm(); + const { formProps, saveButtonProps } = useForm(); - const { selectProps } = useSelect({ + const { selectProps } = useSelect({ resource: "vendor", optionLabel: "name", }); diff --git a/client/src/pages/filaments/list.tsx b/client/src/pages/filaments/list.tsx index fb28313..3bd9bf0 100644 --- a/client/src/pages/filaments/list.tsx +++ b/client/src/pages/filaments/list.tsx @@ -14,12 +14,16 @@ import dayjs from "dayjs"; import utc from "dayjs/plugin/utc"; import { IFilament } from "./model"; import { - filterPopulator, - genericFilterer, genericSorter, - getFiltersForField, getSortOrderForField, + typeSorters, } from "../../utils/sorting"; +import { + genericFilterer, + getFiltersForField, + typeFilters, + useListFiltersForField, +} from "../../utils/filtering"; import { FilterOutlined } from "@ant-design/icons"; import { useInitialTableState, @@ -28,6 +32,10 @@ import { dayjs.extend(utc); +interface IFilamentCollapsed extends IFilament { + vendor_name: string | null; +} + export const FilamentList: React.FC = () => { // Load initial state const initialState = useInitialTableState("filamentList"); @@ -49,26 +57,31 @@ export const FilamentList: React.FC = () => { }, }); + // Type the sorters and filters + const typedSorters = typeSorters(sorters); + const typedFilters = typeFilters(filters); + // Store state in local storage useStoreInitialState("filamentList", { sorters, filters }); - // Copy dataSource to avoid mutating the original - const dataSource = [...(tableProps.dataSource || [])]; - - // Add a vendor_name field to the dataSource - dataSource.forEach((element) => { - if (element.vendor) { - element.vendor_name = element.vendor.name; - } else { - element.vendor_name = null; + // Collapse the dataSource to a mutable list and add a filament_name field + const dataSource: IFilamentCollapsed[] = (tableProps.dataSource ?? []).map( + (element) => { + let vendor_name: string | null; + if (element.vendor) { + vendor_name = element.vendor.name; + } else { + vendor_name = null; + } + return { ...element, vendor_name }; } - }); + ); // Filter dataSource by the filters - const filteredDataSource = dataSource.filter(genericFilterer(filters)); + const filteredDataSource = dataSource.filter(genericFilterer(typedFilters)); // Sort dataSource by the sorters - filteredDataSource.sort(genericSorter(sorters)); + filteredDataSource.sort(genericSorter(typedSorters)); return ( = () => { dataIndex="id" title="Id" sorter={true} - sortOrder={getSortOrderForField(sorters, "id")} + sortOrder={getSortOrderForField(typedSorters, "id")} /> ( = () => { dataIndex="diameter" title="Diameter" sorter={true} - sortOrder={getSortOrderForField(sorters, "diameter")} + sortOrder={getSortOrderForField(typedSorters, "diameter")} render={(value) => ( = () => { dataIndex="weight" title="Weight" sorter={true} - sortOrder={getSortOrderForField(sorters, "weight")} + sortOrder={getSortOrderForField(typedSorters, "weight")} render={(value) => { if (value === null || value === undefined) { return <>; @@ -184,7 +197,7 @@ export const FilamentList: React.FC = () => { dataIndex="spool_weight" title="Spool Weight" sorter={true} - sortOrder={getSortOrderForField(sorters, "spool_weight")} + sortOrder={getSortOrderForField(typedSorters, "spool_weight")} render={(value) => { if (value === null || value === undefined) { return <>; @@ -204,15 +217,15 @@ export const FilamentList: React.FC = () => { dataIndex="article_number" title="Article Number" sorter={true} - sortOrder={getSortOrderForField(sorters, "article_number")} - filters={filterPopulator(dataSource, "article_number")} - filteredValue={getFiltersForField(filters, "article_number")} + sortOrder={getSortOrderForField(typedSorters, "article_number")} + filters={useListFiltersForField(dataSource, "article_number")} + filteredValue={getFiltersForField(typedFilters, "article_number")} /> ( = () => { dataIndex={["comment"]} title="Comment" sorter={true} - sortOrder={getSortOrderForField(sorters, "comment")} + sortOrder={getSortOrderForField(typedSorters, "comment")} /> = () => { - const { queryResult } = useShow(); + const { queryResult } = useShow(); const { data, isLoading } = queryResult; const record = data?.data; diff --git a/client/src/pages/spools/create.tsx b/client/src/pages/spools/create.tsx index fd61a45..0592962 100644 --- a/client/src/pages/spools/create.tsx +++ b/client/src/pages/spools/create.tsx @@ -5,6 +5,7 @@ import { Form, Input, DatePicker, Select, InputNumber } from "antd"; import dayjs from "dayjs"; import TextArea from "antd/es/input/TextArea"; import { IFilament } from "../filaments/model"; +import { ISpool } from "./model"; interface CreateOrCloneProps { mode: "create" | "clone"; @@ -13,7 +14,7 @@ interface CreateOrCloneProps { export const SpoolCreate: React.FC< IResourceComponentsProps & CreateOrCloneProps > = (props) => { - const { formProps, saveButtonProps, formLoading } = useForm(); + const { formProps, saveButtonProps, formLoading } = useForm(); if (props.mode === "clone" && formProps.initialValues) { // Clear out the values that we don't want to clone diff --git a/client/src/pages/spools/edit.tsx b/client/src/pages/spools/edit.tsx index eff438a..d7baa30 100644 --- a/client/src/pages/spools/edit.tsx +++ b/client/src/pages/spools/edit.tsx @@ -5,9 +5,10 @@ import { Form, Input, DatePicker, Select, InputNumber } from "antd"; import dayjs from "dayjs"; import TextArea from "antd/es/input/TextArea"; import { IFilament } from "../filaments/model"; +import { ISpool } from "./model"; export const SpoolEdit: React.FC = () => { - const { formProps, saveButtonProps } = useForm(); + const { formProps, saveButtonProps } = useForm(); const { queryResult } = useSelect({ resource: "filament", diff --git a/client/src/pages/spools/list.tsx b/client/src/pages/spools/list.tsx index 728946a..1e25d2d 100644 --- a/client/src/pages/spools/list.tsx +++ b/client/src/pages/spools/list.tsx @@ -14,12 +14,16 @@ import { NumberFieldUnit } from "../../components/numberField"; import dayjs from "dayjs"; import utc from "dayjs/plugin/utc"; import { - filterPopulator, - genericFilterer, genericSorter, - getFiltersForField, getSortOrderForField, + typeSorters, } from "../../utils/sorting"; +import { + genericFilterer, + getFiltersForField, + typeFilters, + useListFiltersForField, +} from "../../utils/filtering"; import { ISpool } from "./model"; import { useInitialTableState, @@ -29,6 +33,10 @@ import { FilterOutlined } from "@ant-design/icons"; dayjs.extend(utc); +interface ISpoolCollapsed extends ISpool { + filament_name: string; +} + export const SpoolList: React.FC = () => { // Load initial state const initialState = useInitialTableState("spoolList"); @@ -50,26 +58,31 @@ export const SpoolList: React.FC = () => { }, }); + // Type the sorters and filters + const typedSorters = typeSorters(sorters); + const typedFilters = typeFilters(filters); + // Store state in local storage useStoreInitialState("spoolList", { sorters, filters }); - // Copy dataSource to avoid mutating the original - const dataSource = [...(tableProps.dataSource || [])]; - - // Add a filament_name field to the dataSource - dataSource.forEach((element) => { - if (element.filament.vendor && "name" in element.filament.vendor) { - element.filament_name = `${element.filament.vendor.name} - ${element.filament.name}`; - } else { - element.filament_name = element.filament.name; + // Collapse the dataSource to a mutable list and add a filament_name field + const dataSource: ISpoolCollapsed[] = (tableProps.dataSource ?? []).map( + (element) => { + let filament_name: string; + if (element.filament.vendor && "name" in element.filament.vendor) { + filament_name = `${element.filament.vendor.name} - ${element.filament.name}`; + } else { + filament_name = element.filament.name ?? element.filament.id.toString(); + } + return { ...element, filament_name }; } - }); + ); // Filter dataSource by the filters - const filteredDataSource = dataSource.filter(genericFilterer(filters)); + const filteredDataSource = dataSource.filter(genericFilterer(typedFilters)); // Sort dataSource by the sorters - filteredDataSource.sort(genericSorter(sorters)); + filteredDataSource.sort(genericSorter(typedSorters)); return ( = () => { dataIndex="id" title="Id" sorter={true} - sortOrder={getSortOrderForField(sorters, "id")} + sortOrder={getSortOrderForField(typedSorters, "id")} /> { return ( = () => { dataIndex="remaining_weight" title="Estimated Remaining Weight" sorter={true} - sortOrder={getSortOrderForField(sorters, "remaining_weight")} + sortOrder={getSortOrderForField(typedSorters, "remaining_weight")} render={(value) => { if (value === null || value === undefined) { return ; @@ -150,23 +163,23 @@ export const SpoolList: React.FC = () => { dataIndex="location" title="Location" sorter={true} - sortOrder={getSortOrderForField(sorters, "location")} - filters={filterPopulator(dataSource, "location")} - filteredValue={getFiltersForField(filters, "location")} + sortOrder={getSortOrderForField(typedSorters, "location")} + filters={useListFiltersForField(dataSource, "location")} + filteredValue={getFiltersForField(typedFilters, "location")} /> (