From 09f286509998eb84dfc28cceed4e61b7358b215f Mon Sep 17 00:00:00 2001 From: hatim dinia Date: Wed, 27 Mar 2024 13:24:31 +0100 Subject: [PATCH] refactor(bc): minor adjustements --- webapp/src/common/types.ts | 4 -- .../BindingConstraints/AddDialog.tsx | 34 +++++++------ .../BindingConstPropsView.tsx | 50 +++++++++---------- .../BindingConstView/ConstraintFields.tsx | 27 ++++++---- .../BindingConstView/ConstraintTerm/index.tsx | 6 +-- .../BindingConstView/Matrix.tsx | 7 ++- .../BindingConstView/index.tsx | 3 ++ .../Modelization/BindingConstraints/index.tsx | 18 +++---- 8 files changed, 83 insertions(+), 66 deletions(-) diff --git a/webapp/src/common/types.ts b/webapp/src/common/types.ts index 0c35290380..509ac4c4ff 100644 --- a/webapp/src/common/types.ts +++ b/webapp/src/common/types.ts @@ -465,10 +465,6 @@ export interface LinkClusterElement { name: string; } -// TODO wrong types -// LinkWithClusters -// ClusterWithLinks -// Combine both export interface LinkClusterItem { element: LinkClusterElement; item_list: LinkClusterElement[]; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/AddDialog.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/AddDialog.tsx index 1492c9bdc1..88119adf27 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/AddDialog.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/AddDialog.tsx @@ -32,15 +32,14 @@ interface Props { const defaultValues = { name: "", - group: "", + group: "default", enabled: true, timeStep: TimeStep.HOURLY, operator: BindingConstraintOperator.LESS, comments: "", -} as const; +}; // TODO rename AddConstraintDialog -// TODO refactor and add group field function AddDialog({ open, onClose, @@ -74,7 +73,7 @@ function AddDialog({ // Event Handlers //////////////////////////////////////////////////////////////// - const handleSubmit = async ({ + const handleSubmit = ({ values, }: SubmitHandlerPlus) => { return createBindingConstraint(study.id, values); @@ -88,17 +87,17 @@ function AddDialog({ * !WARNING: Current Implementation Issues & Future Directions * * Issues Identified: - * 1. **State vs. Router**: Utilizes global state for navigation-related concerns better suited for URL routing, reducing shareability and persistence. - * 2. **Full List Reload**: Inefficiently reloads the entire list after adding an item, leading to unnecessary network use and performance hits. - * 3. **Global State Overuse**: Over-relies on global state for operations that could be localized, complicating the application unnecessarily. + * 1. State vs. Router: Utilizes global state for navigation-related concerns better suited for URL routing, reducing shareability and persistence. + * 2. Full List Reload: Inefficiently reloads the entire list after adding an item, leading to unnecessary network use and performance hits. + * 3. Global State Overuse: Over-relies on global state for operations that could be localized, complicating the application unnecessarily. * * Future Solutions: - * - **React Router Integration**: Leverage URL parameters for selecting and displaying binding constraints, improving UX and state persistence. - * - **React Query for State Management**: Utilize React Query for data fetching and state management. This introduces benefits like: - * - **Automatic Revalidation**: Only fetches data when needed, reducing unnecessary network requests. - * - **Optimistic Updates**: Immediately reflect changes in the UI while the backend processes the request, enhancing perceived performance. - * - **Cache Management**: Efficiently manage and invalidate cache, ensuring data consistency without manual reloads. - * - **Efficient State Updates**: Post-creation, append the new item to the existing list or use React Query's mutation to update the list optimally. + * - React Router Integration: Leverage URL parameters for selecting and displaying binding constraints, improving UX and state persistence. + * - React Query for State Management: Utilize React Query for data fetching and state management. This introduces benefits like: + * - Automatic Revalidation: Only fetches data when needed, reducing unnecessary network requests. + * - Optimistic Updates: Immediately reflect changes in the UI while the backend processes the request, enhancing perceived performance. + * - Cache Management: Efficiently manage and invalidate cache, ensuring data consistency without manual reloads. + * - Efficient State Updates: Post-creation, append the new item to the existing list or use React Query's mutation to update the list optimally. * * Adopting these strategies will significantly enhance efficiency, maintainability, and UX, addressing current architectural weaknesses. */ @@ -147,11 +146,18 @@ function AddDialog({ validateString(v, { existingValues: existingConstraints }), }} /> - {study.version >= "870" && ( + {Number(study.version) >= 870 && ( + validateString(v, { + max: 20, + specialChars: "-", + }), + }} /> )} void; - currentBindingConst?: string; + currentConstraint?: string; reloadConstraintsList: VoidFunction; } @@ -15,32 +15,32 @@ interface Props { function BindingConstPropsView({ list, onClick, - currentBindingConst, + currentConstraint, reloadConstraintsList, }: Props) { - const [bindingConstNameFilter, setBindingConstNameFilter] = - useState(); + const [searchedConstraint, setSearchedConstraint] = useState(""); const [addBindingConst, setAddBindingConst] = useState(false); - const [filteredBindingConst, setFilteredBindingConst] = useState< - BindingConstraint[] - >(list || []); + const [filteredConstraints, setFilteredConstraints] = useState(list); useEffect(() => { - const filter = (): BindingConstraint[] => { - if (list) { - return list.filter( - (s) => - !bindingConstNameFilter || - s.name.search(new RegExp(bindingConstNameFilter, "i")) !== -1, - ); - } - return []; - }; - setFilteredBindingConst(filter()); - }, [list, bindingConstNameFilter]); + if (!list) { + setFilteredConstraints([]); + return; + } + + if (!searchedConstraint) { + setFilteredConstraints(list); + return; + } + + const pattern = new RegExp(searchedConstraint, "i"); + const filtered = list.filter((s) => pattern.test(s.name)); + + setFilteredConstraints(filtered); + }, [list, searchedConstraint]); const existingConstraints = useMemo( - () => list.map(({ name }) => name.toLowerCase()), + () => list.map(({ name }) => name), [list], ); @@ -53,17 +53,17 @@ function BindingConstPropsView({ ({ - label: item.name, - name: item.id, + list={filteredConstraints.map((constraint) => ({ + label: constraint.name, + name: constraint.id, }))} - currentElement={currentBindingConst} + currentElement={currentConstraint} setSelectedItem={(elm) => onClick(elm.name)} /> } secondaryContent={
} onAdd={() => setAddBindingConst(true)} - onSearchFilterChange={(e) => setBindingConstNameFilter(e as string)} + onSearchFilterChange={(e) => setSearchedConstraint(e)} /> {addBindingConst && ( validateString(v) }} sx={{ m: 0 }} // TODO: Remove when updating MUI Theme /> - + {Number(study.version) >= 870 && ( + + validateString(v, { + max: 20, + specialChars: "-", + }), + }} + sx={{ m: 0 }} // TODO: Remove when updating MUI Theme + /> + )} - - {study.version >= "840" && ( + {Number(study.version) >= 840 && ( , ) => { const value = event.target.value; - const newOffset = value === "" ? undefined : parseFloat(value); + const newOffset = value === "" ? undefined : parseInt(value, 10); setOffset(newOffset); saveValue({ ...term, offset: newOffset }); }; @@ -148,7 +148,7 @@ function ConstraintTermItem({ size="small" type="number" value={weight} - onChange={(e) => handleWeightChange(e)} + onChange={handleWeightChange} sx={{ maxWidth: 150, mr: 0 }} /> } @@ -184,7 +184,7 @@ function ConstraintTermItem({ size="small" type="number" value={offset} - onChange={(e) => handleOffsetChange(e)} + onChange={handleOffsetChange} sx={{ maxWidth: 100 }} /> diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/Matrix.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/Matrix.tsx index 4ad62a5d5b..fbd3fb96f8 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/Matrix.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/Matrix.tsx @@ -29,6 +29,10 @@ function Matrix({ study, operator, constraintId, open, onClose }: Props) { ), }; + //////////////////////////////////////////////////////////////// + // JSX + //////////////////////////////////////////////////////////////// + return ( - {study.version >= "870" ? ( + {Number(study.version) >= 870 ? ( <> {operator === "less" && ( - ( <> + {/* Header controls */} + {/* Constraint properties form */}
+ {/* Constraint terms form */}
getBindingConstraintList(study.id), [study.id, bindingConstraints], ); useEffect(() => { - if (constraintsRes.data && !currentConstraintId) { - const firstConstraintId = constraintsRes.data[0].id; + if (constraints.data && !currentConstraintId) { + const firstConstraintId = constraints.data[0].id; dispatch(setCurrentBindingConst(firstConstraintId)); } - }, [constraintsRes, currentConstraintId, dispatch]); + }, [constraints, currentConstraintId, dispatch]); //////////////////////////////////////////////////////////////// // Event Handlers //////////////////////////////////////////////////////////////// - const handleConstraintChange = (bindingConstId: string): void => { - dispatch(setCurrentBindingConst(bindingConstId)); + const handleConstraintChange = (constraintId: string): void => { + dispatch(setCurrentBindingConst(constraintId)); }; //////////////////////////////////////////////////////////////// @@ -55,7 +55,7 @@ function BindingConstraints() { return ( } ifResolved={(data) => ( @@ -63,8 +63,8 @@ function BindingConstraints() {