From 0b5970b21e1b649cd8fc9c22f50c66f582f6f89d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 16 Jan 2026 02:34:22 +0000 Subject: [PATCH 1/5] Initial plan From b466a854350298fb26217b31db59ccf7f90274f3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 16 Jan 2026 02:44:37 +0000 Subject: [PATCH 2/5] Fix ESLint errors from CI build failure Co-authored-by: fitzergerald <182300328+fitzergerald@users.noreply.github.com> --- src/__testing__/routing.test.ts | 2 +- src/actors/worker/workerfy.ts | 4 +-- src/base/Hidden/Hidden.tsx | 2 +- .../CatalogDesignTable/CatalogDesignTable.tsx | 2 +- .../CatalogDetail/ChallengesSection.tsx | 27 +++++++++++-------- src/custom/CatalogDetail/ContentClassInfo.tsx | 19 ++++++++----- src/custom/CatalogDetail/LearningSection.tsx | 27 +++++++++++-------- .../CustomCatalog/CatalogCardDesignLogo.tsx | 27 ++++++++++++------- src/custom/FlipCard/FlipCard.tsx | 4 +-- src/custom/Modal/index.tsx | 8 +++--- .../ResourceDetailFormatters/Formatter.tsx | 23 +++++++--------- src/custom/ResponsiveDataTable.tsx | 6 ++--- src/custom/ShareModal/ShareModal.tsx | 2 +- .../TeamTable/TeamTableConfiguration.tsx | 8 +++--- src/custom/TypingFilter/index.tsx | 2 +- src/custom/Workspaces/EnvironmentTable.tsx | 3 ++- .../Workspaces/WorkspaceContentMoveModal.tsx | 2 +- src/custom/Workspaces/WorkspaceViewsTable.tsx | 3 ++- .../hooks/useEnvironmentAssignment.tsx | 6 ++--- .../Workspaces/hooks/useTeamAssignment.tsx | 4 +-- src/redux-persist/PersistedStateProvider.tsx | 18 ++++++++----- src/redux-persist/initReduxPersist.ts | 2 +- 22 files changed, 113 insertions(+), 88 deletions(-) diff --git a/src/__testing__/routing.test.ts b/src/__testing__/routing.test.ts index c64d26990..0d556ac7f 100644 --- a/src/__testing__/routing.test.ts +++ b/src/__testing__/routing.test.ts @@ -43,7 +43,7 @@ describe('routing utilities', () => { expect(getShareableResourceRoute(RESOURCE_TYPE.DESIGN, 'd2', 'design')).toBe( 'http://localhost/workspace?mode=design&design=d2' ); - expect(() => getShareableResourceRoute('filter' as any, 'f1', 'filter')).toThrow( + expect(() => getShareableResourceRoute('filter' as unknown as RESOURCE_TYPE, 'f1', 'filter')).toThrow( 'Unknown resource type filter' ); }); diff --git a/src/actors/worker/workerfy.ts b/src/actors/worker/workerfy.ts index 3e58b0f4a..41075e7e6 100644 --- a/src/actors/worker/workerfy.ts +++ b/src/actors/worker/workerfy.ts @@ -71,8 +71,8 @@ export const workerfyActor = (actor: AnyActorLogic) => { } if (event.data.type === WORKER_COMMANDS.STOP_ACTOR) { - snapshotSubscription?.unsubscribe && snapshotSubscription.unsubscribe(); - actorRef?.stop && actorRef.stop(); + snapshotSubscription?.unsubscribe?.(); + actorRef?.stop?.(); } if (event.data.type === WORKER_COMMANDS.SEND_EVENT) { diff --git a/src/base/Hidden/Hidden.tsx b/src/base/Hidden/Hidden.tsx index 22f258115..468c54cac 100644 --- a/src/base/Hidden/Hidden.tsx +++ b/src/base/Hidden/Hidden.tsx @@ -2,7 +2,7 @@ import { Hidden as MuiHidden, HiddenProps as MuiHiddenProps } from '@mui/materia import React from 'react'; export const Hidden = React.forwardRef((props, ref) => { - return React.cloneElement(, { ref }); + return ; }); export default Hidden; diff --git a/src/custom/CatalogDesignTable/CatalogDesignTable.tsx b/src/custom/CatalogDesignTable/CatalogDesignTable.tsx index 9f9673c42..90e5e55c3 100644 --- a/src/custom/CatalogDesignTable/CatalogDesignTable.tsx +++ b/src/custom/CatalogDesignTable/CatalogDesignTable.tsx @@ -72,7 +72,7 @@ export const CatalogDesignsTable: React.FC = ({ setPageSize(tableState.rowsPerPage); break; case 'search': - setSearch && setSearch(tableState.searchText !== null ? tableState.searchText : ''); + setSearch?.(tableState.searchText !== null ? tableState.searchText : ''); break; case 'sort': if ( diff --git a/src/custom/CatalogDetail/ChallengesSection.tsx b/src/custom/CatalogDetail/ChallengesSection.tsx index 1c0a026f9..cbed2c4c5 100644 --- a/src/custom/CatalogDetail/ChallengesSection.tsx +++ b/src/custom/CatalogDetail/ChallengesSection.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from 'react'; +import React, { useMemo, useState } from 'react'; import { Link, ListItemIcon } from '../../base'; import { MESHERY_CLOUD_PROD } from '../../constants/constants'; import { ChallengesIcon } from '../../icons'; @@ -14,18 +14,23 @@ interface ChallengesSectionProps { const ChallengesSection: React.FC = ({ filteredAcademyData }) => { const theme = useTheme(); - const [openChallenges, setOpenChallenges] = useState(false); - const [autoUpdate, setAutoUpdate] = useState(true); - - useEffect(() => { - if (autoUpdate) { - setOpenChallenges((filteredAcademyData?.['challenges'] ?? []).length > 0); - } - }, [filteredAcademyData, autoUpdate]); + const userToggledRef = React.useRef(false); + const [userToggleValue, setUserToggleValue] = useState(null); + + const hasChallenges = useMemo( + () => (filteredAcademyData?.['challenges'] ?? []).length > 0, + [filteredAcademyData] + ); + + // Derive the open state: use user's manual toggle if set, otherwise use hasChallenges + const openChallenges = userToggleValue !== null ? userToggleValue : hasChallenges; const toggleOpenChallenges = () => { - setOpenChallenges((prev) => !prev); - setAutoUpdate(false); + setUserToggleValue((prev) => { + const currentValue = prev !== null ? prev : hasChallenges; + return !currentValue; + }); + userToggledRef.current = true; }; const renderChallengeItem = (item: string, index: number) => ( diff --git a/src/custom/CatalogDetail/ContentClassInfo.tsx b/src/custom/CatalogDetail/ContentClassInfo.tsx index effd24378..29eedb0ea 100644 --- a/src/custom/CatalogDetail/ContentClassInfo.tsx +++ b/src/custom/CatalogDetail/ContentClassInfo.tsx @@ -12,6 +12,17 @@ interface ContentClassInfoProps { classes: Class[]; } +interface ClassIconProps { + className: string; + contentClass: ContentClassType; +} + +const ClassIcon: React.FC = ({ className, contentClass }) => { + const Icon = contentClass[className]?.icon; + const fill = contentClass[className]?.color; + return Icon ? : null; +}; + const ContentClassInfo: React.FC = ({ contentClass, classes }) => { const _classDescription = (className: string): string | undefined => { const classObj = classes && classes.find((classObj) => classObj.class === className); @@ -35,12 +46,6 @@ const ContentClassInfo: React.FC = ({ contentClass, class } } as const; - const ClassIcon: React.FC<{ className: string }> = ({ className }) => { - const Icon = CONTENT_CLASS[className]?.icon; - const fill = CONTENT_CLASS[className]?.color; - return Icon ? : null; - }; - return (
@@ -61,7 +66,7 @@ const ContentClassInfo: React.FC = ({ contentClass, class fontFamily: 'inherit' }} > - + {formatToTitleCase(contentClass)}
diff --git a/src/custom/CatalogDetail/LearningSection.tsx b/src/custom/CatalogDetail/LearningSection.tsx index 674b5757e..75a2bb321 100644 --- a/src/custom/CatalogDetail/LearningSection.tsx +++ b/src/custom/CatalogDetail/LearningSection.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React, { useMemo, useState } from 'react'; import { Link, ListItemIcon } from '../../base'; import { MESHERY_CLOUD_PROD } from '../../constants/constants'; import { LearningIcon } from '../../icons'; @@ -14,18 +14,23 @@ interface LearningSectionProps { const LearningSection: React.FC = ({ filteredAcademyData }) => { const theme = useTheme(); - const [openLearning, setOpenLearning] = useState(false); - const [autoUpdate, setAutoUpdate] = useState(true); - - useEffect(() => { - if (autoUpdate) { - setOpenLearning(Boolean((filteredAcademyData?.['learning-path'] ?? []).length > 0)); - } - }, [filteredAcademyData, autoUpdate]); + const userToggledRef = React.useRef(false); + const [userToggleValue, setUserToggleValue] = useState(null); + + const hasLearningPaths = useMemo( + () => Boolean((filteredAcademyData?.['learning-path'] ?? []).length > 0), + [filteredAcademyData] + ); + + // Derive the open state: use user's manual toggle if set, otherwise use hasLearningPaths + const openLearning = userToggleValue !== null ? userToggleValue : hasLearningPaths; const toggleOpenLearning = (): void => { - setOpenLearning((prev) => !prev); - setAutoUpdate(false); + setUserToggleValue((prev) => { + const currentValue = prev !== null ? prev : hasLearningPaths; + return !currentValue; + }); + userToggledRef.current = true; }; const renderLearningItem = (item: string, index: number) => ( diff --git a/src/custom/CustomCatalog/CatalogCardDesignLogo.tsx b/src/custom/CustomCatalog/CatalogCardDesignLogo.tsx index 30e3473f4..537855c72 100644 --- a/src/custom/CustomCatalog/CatalogCardDesignLogo.tsx +++ b/src/custom/CustomCatalog/CatalogCardDesignLogo.tsx @@ -11,6 +11,21 @@ interface CatalogCardDesignLogoProps { style?: React.CSSProperties; } +interface SvgComponentProps { + type: { type: string }; + width: string; + height: string; + style: React.CSSProperties; +} + +const SvgComponent: React.FC = ({ type, width, height, style }) => { + return type.type === 'filter' ? ( + + ) : ( + + ); +}; + const CatalogCardDesignLogo: React.FC = ({ zoomEffect = false, imgURL, @@ -32,14 +47,6 @@ const CatalogCardDesignLogo: React.FC = ({ setIsZoomed(false); }; - const SvgComponent: React.FC<{ type: { type: string } }> = ({ type }) => { - return type.type === 'filter' ? ( - - ) : ( - - ); - }; - return ( <> {imgURL && imgURL.length > 0 ? ( @@ -82,11 +89,11 @@ const CatalogCardDesignLogo: React.FC = ({ ) : ( - + )} ) : ( - + )} ); diff --git a/src/custom/FlipCard/FlipCard.tsx b/src/custom/FlipCard/FlipCard.tsx index 895964773..a6b320d27 100644 --- a/src/custom/FlipCard/FlipCard.tsx +++ b/src/custom/FlipCard/FlipCard.tsx @@ -108,8 +108,8 @@ export function FlipCard({ onClick={() => { if (disableFlip) return; setFlipped((flipped) => !flipped); - onClick && onClick(); - onShow && onShow(); + onClick?.(); + onShow?.(); }} > (null); const openModal: openModalCallback = ({ title, reactNode = null, onClose }) => { - title && setTitle(title); - onClose && (onCloseRef.current = onClose); + if (title) setTitle(title); + if (onClose) onCloseRef.current = onClose; setOpen(true); - reactNode && setReactNode(reactNode); + if (reactNode) setReactNode(reactNode); }; const closeModal = () => { setOpen(false); - onCloseRef.current && onCloseRef.current(); + onCloseRef.current?.(); setReactNode(null); setTitle(''); onCloseRef.current = null; diff --git a/src/custom/ResourceDetailFormatters/Formatter.tsx b/src/custom/ResourceDetailFormatters/Formatter.tsx index fa3894574..2311f51bc 100644 --- a/src/custom/ResourceDetailFormatters/Formatter.tsx +++ b/src/custom/ResourceDetailFormatters/Formatter.tsx @@ -358,6 +358,13 @@ export const StatusChip = ({ status }: { status: string }) => { ); }; +const ResourceProgress: React.FC ChartOptions }> = ({ title, percentage, type, chartOptions }) => ( + + {title} + + +); + export const MemoryUsage: React.FC = ({ allocatable, capacity, @@ -427,25 +434,15 @@ export const MemoryUsage: React.FC = ({ [height, width] ); - const ResourceProgress = useCallback>( - ({ title, percentage, type }) => ( - - {title} - - - ), - [chartOptions] - ); - if (!allocatable || !capacity) { return null; } return ( - - - + + + ); }; diff --git a/src/custom/ResponsiveDataTable.tsx b/src/custom/ResponsiveDataTable.tsx index 6d357aab3..8088f254c 100644 --- a/src/custom/ResponsiveDataTable.tsx +++ b/src/custom/ResponsiveDataTable.tsx @@ -179,7 +179,7 @@ const ResponsiveDataTable = ({ if (colToAdd) { if (colToAdd.options) { colToAdd.options.display = true; - updateCols && updateCols([...columns]); + updateCols?.([...columns]); } } break; @@ -189,7 +189,7 @@ const ResponsiveDataTable = ({ if (colToRemove) { if (colToRemove.options) { colToRemove.options.display = false; - updateCols && updateCols([...columns]); + updateCols?.([...columns]); } } break; @@ -236,7 +236,7 @@ const ResponsiveDataTable = ({ } } }); - updateCols && updateCols([...columns]); + updateCols?.([...columns]); // eslint-disable-next-line react-hooks/exhaustive-deps }, [columnVisibility, updateCols]); diff --git a/src/custom/ShareModal/ShareModal.tsx b/src/custom/ShareModal/ShareModal.tsx index c26fdbb51..252150508 100644 --- a/src/custom/ShareModal/ShareModal.tsx +++ b/src/custom/ShareModal/ShareModal.tsx @@ -82,7 +82,7 @@ const AccessListActor: React.FC = ({ src={actorData.avatar_url} imgProps={{ referrerPolicy: 'no-referrer' }} onClick={() => { - hostURL && openInNewTab(`${hostURL}/user/${actorData.id}`); + if (hostURL) openInNewTab(`${hostURL}/user/${actorData.id}`); }} /> diff --git a/src/custom/TeamTable/TeamTableConfiguration.tsx b/src/custom/TeamTable/TeamTableConfiguration.tsx index 46ce3404a..52bb23ad6 100644 --- a/src/custom/TeamTable/TeamTableConfiguration.tsx +++ b/src/custom/TeamTable/TeamTableConfiguration.tsx @@ -227,7 +227,7 @@ export default function TeamTableConfiguration({ id={`edit_team-${tableMeta.rowIndex}`} title="Edit Team" onClick={(ev) => { - isEditTeamAllowed && handleTeamView(ev, tableMeta.rowData); + if (isEditTeamAllowed) handleTeamView(ev, tableMeta.rowData); }} iconType="edit" > @@ -252,9 +252,9 @@ export default function TeamTableConfiguration({ id={`remove_team-${tableMeta.rowIndex}`} title={'Move Team'} onClick={() => { - isRemoveTeamFromWorkspaceAllowed && - handleRemoveTeamFromWorkspace && + if (isRemoveTeamFromWorkspaceAllowed && handleRemoveTeamFromWorkspace) { handleRemoveTeamFromWorkspace(tableMeta.rowData[0]); + } }} iconType="delete" > @@ -267,7 +267,7 @@ export default function TeamTableConfiguration({ id={`delete_team-${tableMeta.rowIndex}`} title={'Delete Team'} onClick={(ev: React.MouseEvent) => { - isDeleteTeamAllowed && handleDeleteTeam(ev, tableMeta.rowData); + if (isDeleteTeamAllowed) handleDeleteTeam(ev, tableMeta.rowData); }} iconType="delete" > diff --git a/src/custom/TypingFilter/index.tsx b/src/custom/TypingFilter/index.tsx index b87e59f0c..de3f4d2a9 100644 --- a/src/custom/TypingFilter/index.tsx +++ b/src/custom/TypingFilter/index.tsx @@ -147,7 +147,7 @@ export function TypingFilter({ filterSchema, handleFilter, autoFilter = false }: /> = ({ id={`delete_team-${tableMeta.rowIndex}`} title="Remove Environment" onClick={() => { - isRemoveAllowed && + if (isRemoveAllowed) { unassignEnvironmentFromWorkspace({ workspaceId, environmentId: tableMeta.rowData[0] }); + } }} iconType="delete" > diff --git a/src/custom/Workspaces/WorkspaceContentMoveModal.tsx b/src/custom/Workspaces/WorkspaceContentMoveModal.tsx index 6eee55ab0..be5a1b5c0 100644 --- a/src/custom/Workspaces/WorkspaceContentMoveModal.tsx +++ b/src/custom/Workspaces/WorkspaceContentMoveModal.tsx @@ -150,7 +150,7 @@ const WorkspaceContentMoveModal: React.FC = ({ message: `Successfully moved ${type === RESOURCE_TYPE.DESIGN ? 'design' : 'view'}${multiSelectedContent.length > 1 ? 's' : ''} to ${selectedWorkspaceForMove!.name}`, event_type: EVENT_TYPES.SUCCESS }); - } catch (error) { + } catch { notify({ message: `Failed to move ${type === RESOURCE_TYPE.DESIGN ? 'design' : 'view'}. Please try again.`, event_type: EVENT_TYPES.ERROR diff --git a/src/custom/Workspaces/WorkspaceViewsTable.tsx b/src/custom/Workspaces/WorkspaceViewsTable.tsx index ff4a29709..525a253a2 100644 --- a/src/custom/Workspaces/WorkspaceViewsTable.tsx +++ b/src/custom/Workspaces/WorkspaceViewsTable.tsx @@ -254,11 +254,12 @@ const WorkspaceViewsTable: React.FC = ({ id={`delete_view-${tableMeta.rowIndex}`} title="Move View" onClick={() => { - isRemoveAllowed && + if (isRemoveAllowed) { unassignviewFromWorkspace({ workspaceId, viewId: tableMeta.rowData[0] }); + } }} iconType="delete" > diff --git a/src/custom/Workspaces/hooks/useEnvironmentAssignment.tsx b/src/custom/Workspaces/hooks/useEnvironmentAssignment.tsx index 1e34ea422..48e348efe 100644 --- a/src/custom/Workspaces/hooks/useEnvironmentAssignment.tsx +++ b/src/custom/Workspaces/hooks/useEnvironmentAssignment.tsx @@ -136,9 +136,9 @@ const useEnvironmentAssignment = ({ const handleAssignEnvironmentsData = (updatedAssignedData: Environment[]) => { const { addedEnvironmentsIds, removedEnvironmentsIds } = getAddedAndRemovedEnvironments(updatedAssignedData); - addedEnvironmentsIds.length > 0 || removedEnvironmentsIds.length > 0 - ? setDisableTransferButton(false) - : setDisableTransferButton(true); + setDisableTransferButton( + addedEnvironmentsIds.length === 0 && removedEnvironmentsIds.length === 0 + ); setAssignedEnvironments(updatedAssignedData); }; diff --git a/src/custom/Workspaces/hooks/useTeamAssignment.tsx b/src/custom/Workspaces/hooks/useTeamAssignment.tsx index e3f177595..f0b240aba 100644 --- a/src/custom/Workspaces/hooks/useTeamAssignment.tsx +++ b/src/custom/Workspaces/hooks/useTeamAssignment.tsx @@ -124,9 +124,7 @@ const useTeamAssignment = ({ const handleAssignTeamsData = (updatedAssignedData: Team[]) => { const { addedTeamsIds, removedTeamsIds } = getAddedAndRemovedTeams(updatedAssignedData); - addedTeamsIds.length > 0 || removedTeamsIds.length > 0 - ? setDisableTransferButton(false) - : setDisableTransferButton(true); + setDisableTransferButton(addedTeamsIds.length === 0 && removedTeamsIds.length === 0); setAssignedTeams(updatedAssignedData); }; diff --git a/src/redux-persist/PersistedStateProvider.tsx b/src/redux-persist/PersistedStateProvider.tsx index 80dd097cd..658388b5a 100644 --- a/src/redux-persist/PersistedStateProvider.tsx +++ b/src/redux-persist/PersistedStateProvider.tsx @@ -23,12 +23,18 @@ export const PersistedStateProvider: FC = ({ if (!loading) { return; } - try { - dispatch(loadPersistedState()); - } catch (e) { - setError(e as Error); - } - setLoading(false); + + const loadState = async () => { + try { + dispatch(loadPersistedState()); + setLoading(false); + } catch (e) { + setError(e as Error); + setLoading(false); + } + }; + + loadState(); }, [loading, dispatch, loadPersistedState]); if (error) { diff --git a/src/redux-persist/initReduxPersist.ts b/src/redux-persist/initReduxPersist.ts index 5c3e9cbee..d84bfa8f0 100644 --- a/src/redux-persist/initReduxPersist.ts +++ b/src/redux-persist/initReduxPersist.ts @@ -80,7 +80,7 @@ export const initReduxPersist = (actionsToPersist: ActionsToPersist) => { inflatedState = JSON.parse(inflatedState); dispatch(rehydrateState(path, inflatedState)); } - } catch (e) { + } catch { console.error(`Error rehydrating state for reducer ${path}`, inflatedState); } }); From 60b225b3808ee3e3d19c34042fdd76975809f1ec Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 16 Jan 2026 02:47:17 +0000 Subject: [PATCH 3/5] Fix Hidden component to not forward ref (MuiHidden doesn't support it) Co-authored-by: fitzergerald <182300328+fitzergerald@users.noreply.github.com> --- src/base/Hidden/Hidden.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/base/Hidden/Hidden.tsx b/src/base/Hidden/Hidden.tsx index 468c54cac..44bcd5c8e 100644 --- a/src/base/Hidden/Hidden.tsx +++ b/src/base/Hidden/Hidden.tsx @@ -1,8 +1,9 @@ import { Hidden as MuiHidden, HiddenProps as MuiHiddenProps } from '@mui/material'; import React from 'react'; -export const Hidden = React.forwardRef((props, ref) => { - return ; +export const Hidden = React.forwardRef((props) => { + // MuiHidden doesn't support ref forwarding + return ; }); export default Hidden; From 5d7e9048f1f5a2256c5ff1f9c4549f11de8c4339 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 16 Jan 2026 02:49:02 +0000 Subject: [PATCH 4/5] Remove unused userToggledRef from ChallengesSection and LearningSection Co-authored-by: fitzergerald <182300328+fitzergerald@users.noreply.github.com> --- src/custom/CatalogDetail/ChallengesSection.tsx | 2 -- src/custom/CatalogDetail/LearningSection.tsx | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/custom/CatalogDetail/ChallengesSection.tsx b/src/custom/CatalogDetail/ChallengesSection.tsx index cbed2c4c5..dfaaa8b22 100644 --- a/src/custom/CatalogDetail/ChallengesSection.tsx +++ b/src/custom/CatalogDetail/ChallengesSection.tsx @@ -14,7 +14,6 @@ interface ChallengesSectionProps { const ChallengesSection: React.FC = ({ filteredAcademyData }) => { const theme = useTheme(); - const userToggledRef = React.useRef(false); const [userToggleValue, setUserToggleValue] = useState(null); const hasChallenges = useMemo( @@ -30,7 +29,6 @@ const ChallengesSection: React.FC = ({ filteredAcademyDa const currentValue = prev !== null ? prev : hasChallenges; return !currentValue; }); - userToggledRef.current = true; }; const renderChallengeItem = (item: string, index: number) => ( diff --git a/src/custom/CatalogDetail/LearningSection.tsx b/src/custom/CatalogDetail/LearningSection.tsx index 75a2bb321..dc19c608e 100644 --- a/src/custom/CatalogDetail/LearningSection.tsx +++ b/src/custom/CatalogDetail/LearningSection.tsx @@ -14,7 +14,6 @@ interface LearningSectionProps { const LearningSection: React.FC = ({ filteredAcademyData }) => { const theme = useTheme(); - const userToggledRef = React.useRef(false); const [userToggleValue, setUserToggleValue] = useState(null); const hasLearningPaths = useMemo( @@ -30,7 +29,6 @@ const LearningSection: React.FC = ({ filteredAcademyData } const currentValue = prev !== null ? prev : hasLearningPaths; return !currentValue; }); - userToggledRef.current = true; }; const renderLearningItem = (item: string, index: number) => ( From 72f1dd6276352d31c95f1acd7e088a27e1bca8b7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 16 Jan 2026 02:51:26 +0000 Subject: [PATCH 5/5] Address code review feedback: use finally block, separate interface, and nullish coalescing Co-authored-by: fitzergerald <182300328+fitzergerald@users.noreply.github.com> --- src/custom/CatalogDetail/ChallengesSection.tsx | 2 +- src/custom/CatalogDetail/LearningSection.tsx | 2 +- src/custom/ResourceDetailFormatters/Formatter.tsx | 6 +++++- src/redux-persist/PersistedStateProvider.tsx | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/custom/CatalogDetail/ChallengesSection.tsx b/src/custom/CatalogDetail/ChallengesSection.tsx index dfaaa8b22..03d29bd4c 100644 --- a/src/custom/CatalogDetail/ChallengesSection.tsx +++ b/src/custom/CatalogDetail/ChallengesSection.tsx @@ -22,7 +22,7 @@ const ChallengesSection: React.FC = ({ filteredAcademyDa ); // Derive the open state: use user's manual toggle if set, otherwise use hasChallenges - const openChallenges = userToggleValue !== null ? userToggleValue : hasChallenges; + const openChallenges = userToggleValue ?? hasChallenges; const toggleOpenChallenges = () => { setUserToggleValue((prev) => { diff --git a/src/custom/CatalogDetail/LearningSection.tsx b/src/custom/CatalogDetail/LearningSection.tsx index dc19c608e..74b22940f 100644 --- a/src/custom/CatalogDetail/LearningSection.tsx +++ b/src/custom/CatalogDetail/LearningSection.tsx @@ -22,7 +22,7 @@ const LearningSection: React.FC = ({ filteredAcademyData } ); // Derive the open state: use user's manual toggle if set, otherwise use hasLearningPaths - const openLearning = userToggleValue !== null ? userToggleValue : hasLearningPaths; + const openLearning = userToggleValue ?? hasLearningPaths; const toggleOpenLearning = (): void => { setUserToggleValue((prev) => { diff --git a/src/custom/ResourceDetailFormatters/Formatter.tsx b/src/custom/ResourceDetailFormatters/Formatter.tsx index 2311f51bc..b13c0e429 100644 --- a/src/custom/ResourceDetailFormatters/Formatter.tsx +++ b/src/custom/ResourceDetailFormatters/Formatter.tsx @@ -65,6 +65,10 @@ interface ResourceProgressProps { type: string; } +interface ResourceProgressWithChartProps extends ResourceProgressProps { + chartOptions: (percentage: number, type: string) => ChartOptions; +} + interface StatusColorType { background: string; text: string; @@ -358,7 +362,7 @@ export const StatusChip = ({ status }: { status: string }) => { ); }; -const ResourceProgress: React.FC ChartOptions }> = ({ title, percentage, type, chartOptions }) => ( +const ResourceProgress: React.FC = ({ title, percentage, type, chartOptions }) => ( {title} diff --git a/src/redux-persist/PersistedStateProvider.tsx b/src/redux-persist/PersistedStateProvider.tsx index 658388b5a..2de91cbe3 100644 --- a/src/redux-persist/PersistedStateProvider.tsx +++ b/src/redux-persist/PersistedStateProvider.tsx @@ -27,9 +27,9 @@ export const PersistedStateProvider: FC = ({ const loadState = async () => { try { dispatch(loadPersistedState()); - setLoading(false); } catch (e) { setError(e as Error); + } finally { setLoading(false); } };