diff --git a/apps/web/core/components/work-item-filters/filters-hoc/base.tsx b/apps/web/core/components/work-item-filters/filters-hoc/base.tsx index a96b522d5..487d351c4 100644 --- a/apps/web/core/components/work-item-filters/filters-hoc/base.tsx +++ b/apps/web/core/components/work-item-filters/filters-hoc/base.tsx @@ -62,27 +62,28 @@ const WorkItemFilterRoot = observer((props: TWorkItemFilterProps) => { [isTemporary, entityId] ); // memoize initial values to prevent re-computations when reference changes - const initialUserFilters = useMemo( - () => initialWorkItemFilters.richFilters, - // eslint-disable-next-line react-hooks/exhaustive-deps - [] - ); // Empty dependency array to capture only the initial value + const initialUserFilters = useMemo(() => initialWorkItemFilters.richFilters, [initialWorkItemFilters]); const workItemFiltersConfig = useWorkItemFiltersConfig({ allowedFilters: filtersToShowByLayout ? filtersToShowByLayout : [], ...entityConfigProps, }); // get or create filter instance - const workItemLayoutFilter = getOrCreateFilter({ - entityType, - entityId: workItemEntityID, - initialExpression: initialUserFilters, - onExpressionChange: updateFilters, - expressionOptions: { - saveViewOptions, - updateViewOptions, - }, - showOnMount, - }); + const workItemLayoutFilter = useMemo( + () => + getOrCreateFilter({ + entityType, + entityId: workItemEntityID, + initialExpression: initialUserFilters, + onExpressionChange: updateFilters, + expressionOptions: { + saveViewOptions, + updateViewOptions, + }, + showOnMount, + }), + // eslint-disable-next-line react-hooks/exhaustive-deps + [entityType, workItemEntityID, saveViewOptions, updateViewOptions, updateFilters] + ); // delete filter instance when component unmounts useEffect( @@ -92,8 +93,14 @@ const WorkItemFilterRoot = observer((props: TWorkItemFilterProps) => { [deleteFilter, entityType, workItemEntityID] ); - workItemLayoutFilter.configManager.setAreConfigsReady(workItemFiltersConfig.areAllConfigsInitialized); - workItemLayoutFilter.configManager.registerAll(workItemFiltersConfig.configs); + useEffect(() => { + workItemLayoutFilter.configManager.setAreConfigsReady(workItemFiltersConfig.areAllConfigsInitialized); + workItemLayoutFilter.configManager.registerAll(workItemFiltersConfig.configs); + }, [ + workItemFiltersConfig.areAllConfigsInitialized, + workItemFiltersConfig.configs, + workItemLayoutFilter.configManager, + ]); return <>{typeof children === "function" ? children({ filter: workItemLayoutFilter }) : children}; }); diff --git a/apps/web/core/components/work-item-filters/filters-hoc/project-level.tsx b/apps/web/core/components/work-item-filters/filters-hoc/project-level.tsx index 9a7aa5c98..8b73dba41 100644 --- a/apps/web/core/components/work-item-filters/filters-hoc/project-level.tsx +++ b/apps/web/core/components/work-item-filters/filters-hoc/project-level.tsx @@ -88,6 +88,17 @@ export const ProjectLevelWorkItemFiltersHOC = observer((props: TProjectLevelWork isCurrentUserOwner, ] ); + const createViewLabel = useMemo(() => props.saveViewOptions?.label, [props.saveViewOptions?.label]); + const updateViewLabel = useMemo(() => props.updateViewOptions?.label, [props.updateViewOptions?.label]); + const hasAdditionalChanges = useMemo( + () => + !isEqual(initialWorkItemFilters?.displayFilters, viewDetails?.display_filters) || + !isEqual( + removeNillKeys(initialWorkItemFilters?.displayProperties), + removeNillKeys(viewDetails?.display_properties) + ), + [initialWorkItemFilters, viewDetails] + ); const getDefaultViewDetailPayload: () => Partial = useCallback( () => ({ @@ -108,6 +119,17 @@ export const ProjectLevelWorkItemFiltersHOC = observer((props: TProjectLevelWork [initialWorkItemFilters] ); + const handleViewSave = useCallback( + (expression: TWorkItemFilterExpression) => { + setCreateViewPayload({ + ...getDefaultViewDetailPayload(), + ...getViewFilterPayload(expression), + }); + setIsCreateViewModalOpen(true); + }, + [getDefaultViewDetailPayload, getViewFilterPayload] + ); + const handleViewUpdate = useCallback( (filterExpression: TWorkItemFilterExpression) => { if (!viewDetails) { @@ -153,6 +175,25 @@ export const ProjectLevelWorkItemFiltersHOC = observer((props: TProjectLevelWork [viewDetails, updateView, workspaceSlug, projectId, getViewFilterPayload] ); + const saveViewOptions = useMemo( + () => ({ + label: createViewLabel, + isDisabled: !canCreateView, + onViewSave: handleViewSave, + }), + [createViewLabel, canCreateView, handleViewSave] + ); + + const updateViewOptions = useMemo( + () => ({ + label: updateViewLabel, + isDisabled: !canUpdateView, + hasAdditionalChanges, + onViewUpdate: handleViewUpdate, + }), + [updateViewLabel, canUpdateView, hasAdditionalChanges, handleViewUpdate] + ); + return ( <> { - setCreateViewPayload({ - ...getDefaultViewDetailPayload(), - ...getViewFilterPayload(expression), - }); - setIsCreateViewModalOpen(true); - }, - }} - updateViewOptions={{ - label: props.updateViewOptions?.label, - isDisabled: !canUpdateView, - hasAdditionalChanges: - !isEqual(initialWorkItemFilters?.displayFilters, viewDetails?.display_filters) || - !isEqual( - removeNillKeys(initialWorkItemFilters?.displayProperties), - removeNillKeys(viewDetails?.display_properties) - ), - onViewUpdate: handleViewUpdate, - }} + saveViewOptions={saveViewOptions} + updateViewOptions={updateViewOptions} > {children} diff --git a/apps/web/core/components/work-item-filters/filters-hoc/workspace-level.tsx b/apps/web/core/components/work-item-filters/filters-hoc/workspace-level.tsx index 26520f85d..86051a37f 100644 --- a/apps/web/core/components/work-item-filters/filters-hoc/workspace-level.tsx +++ b/apps/web/core/components/work-item-filters/filters-hoc/workspace-level.tsx @@ -70,6 +70,17 @@ export const WorkspaceLevelWorkItemFiltersHOC = observer((props: TWorkspaceLevel isCurrentUserOwner, ] ); + const createViewLabel = useMemo(() => props.saveViewOptions?.label, [props.saveViewOptions?.label]); + const updateViewLabel = useMemo(() => props.updateViewOptions?.label, [props.updateViewOptions?.label]); + const hasAdditionalChanges = useMemo( + () => + !isEqual(initialWorkItemFilters?.displayFilters, viewDetails?.display_filters) || + !isEqual( + removeNillKeys(initialWorkItemFilters?.displayProperties), + removeNillKeys(viewDetails?.display_properties) + ), + [initialWorkItemFilters, viewDetails] + ); const getDefaultViewDetailPayload: () => Partial = useCallback( () => ({ @@ -89,6 +100,17 @@ export const WorkspaceLevelWorkItemFiltersHOC = observer((props: TWorkspaceLevel [initialWorkItemFilters] ); + const handleViewSave = useCallback( + (expression: TWorkItemFilterExpression) => { + setCreateViewPayload({ + ...getDefaultViewDetailPayload(), + ...getViewFilterPayload(expression), + }); + setIsCreateViewModalOpen(true); + }, + [getDefaultViewDetailPayload, getViewFilterPayload] + ); + const handleViewUpdate = useCallback( (filterExpression: TWorkItemFilterExpression) => { if (!viewDetails) { @@ -140,6 +162,25 @@ export const WorkspaceLevelWorkItemFiltersHOC = observer((props: TWorkspaceLevel [viewDetails, updateGlobalView, workspaceSlug, getViewFilterPayload] ); + const saveViewOptions = useMemo( + () => ({ + label: createViewLabel, + isDisabled: !canCreateView, + onViewSave: handleViewSave, + }), + [createViewLabel, canCreateView, handleViewSave] + ); + + const updateViewOptions = useMemo( + () => ({ + label: updateViewLabel, + isDisabled: !canUpdateView, + hasAdditionalChanges, + onViewUpdate: handleViewUpdate, + }), + [updateViewLabel, canUpdateView, hasAdditionalChanges, handleViewUpdate] + ); + return ( <> { - setCreateViewPayload({ - ...getDefaultViewDetailPayload(), - ...getViewFilterPayload(expression), - }); - setIsCreateViewModalOpen(true); - }, - }} - updateViewOptions={{ - label: props.updateViewOptions?.label, - isDisabled: !canUpdateView, - hasAdditionalChanges: - !isEqual(initialWorkItemFilters?.displayFilters, viewDetails?.display_filters) || - !isEqual( - removeNillKeys(initialWorkItemFilters?.displayProperties), - removeNillKeys(viewDetails?.display_properties) - ), - onViewUpdate: handleViewUpdate, - }} + saveViewOptions={saveViewOptions} + updateViewOptions={updateViewOptions} > {children} diff --git a/packages/shared-state/src/store/rich-filters/filter.ts b/packages/shared-state/src/store/rich-filters/filter.ts index 94236036b..5fe35cc36 100644 --- a/packages/shared-state/src/store/rich-filters/filter.ts +++ b/packages/shared-state/src/store/rich-filters/filter.ts @@ -160,7 +160,7 @@ export class FilterInstance