diff --git a/front/src/modules/companies/board/components/CompanyBoard.tsx b/front/src/modules/companies/board/components/CompanyBoard.tsx index 98faf5f51..f95640b6a 100644 --- a/front/src/modules/companies/board/components/CompanyBoard.tsx +++ b/front/src/modules/companies/board/components/CompanyBoard.tsx @@ -1,5 +1,4 @@ import styled from '@emotion/styled'; -import { useSetRecoilState } from 'recoil'; import { BoardContext } from '@/companies/states/contexts/BoardContext'; import { BoardOptionsDropdown } from '@/ui/layout/board/components/BoardOptionsDropdown'; @@ -11,7 +10,6 @@ import { import { EntityBoardActionBar } from '@/ui/layout/board/components/EntityBoardActionBar'; import { EntityBoardContextMenu } from '@/ui/layout/board/components/EntityBoardContextMenu'; import { ViewBar } from '@/views/components/ViewBar'; -import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates'; import { ViewScope } from '@/views/scopes/ViewScope'; import { opportunitiesBoardOptions } from '~/pages/opportunities/opportunitiesBoardOptions'; @@ -38,30 +36,12 @@ export const CompanyBoard = ({ }: CompanyBoardProps) => { const viewScopeId = 'company-board-view'; - const { - currentViewFieldsState, - currentViewFiltersState, - currentViewSortsState, - } = useViewScopedStates({ - customViewScopeId: viewScopeId, - }); - - const setCurrentViewFields = useSetRecoilState(currentViewFieldsState); - const setCurrentViewFilters = useSetRecoilState(currentViewFiltersState); - const setCurrentViewSorts = useSetRecoilState(currentViewSortsState); - return ( { - setCurrentViewFields(viewFields); - }} - onViewFiltersChange={(viewFilters) => { - setCurrentViewFilters(viewFilters); - }} - onViewSortsChange={(viewSorts) => { - setCurrentViewSorts(viewSorts); - }} + onViewFieldsChange={() => {}} + onViewFiltersChange={() => {}} + onViewSortsChange={() => {}} > { const { BoardRecoilScopeContext } = useBoardContext(); - const { currentCardSelected, setCurrentCardSelected } = + const { isCurrentCardSelected, setCurrentCardSelected } = useCurrentCardSelected(); const boardCardId = useContext(BoardCardIdContext); @@ -200,9 +200,9 @@ export const CompanyBoardCard = () => { return ( setCurrentCardSelected(!currentCardSelected)} + onClick={() => setCurrentCardSelected(!isCurrentCardSelected)} > { )} setCurrentCardSelected(!currentCardSelected)} + checked={isCurrentCardSelected} + onChange={() => setCurrentCardSelected(!isCurrentCardSelected)} variant={CheckboxVariant.Secondary} /> diff --git a/front/src/modules/companies/components/HooksCompanyBoardEffect.tsx b/front/src/modules/companies/components/HooksCompanyBoardEffect.tsx index eb0b3d479..b1117091d 100644 --- a/front/src/modules/companies/components/HooksCompanyBoardEffect.tsx +++ b/front/src/modules/companies/components/HooksCompanyBoardEffect.tsx @@ -164,21 +164,19 @@ export const HooksCompanyBoardEffect = () => { setViewType?.(ViewType.Kanban); }, [objectMetadataItem, setViewObjectMetadataId, setViewType]); - const loading = !companies; - const { setActionBarEntries } = useBoardActionBarEntries(); const { setContextMenuEntries } = useBoardContextMenuEntries(); useEffect(() => { - if (!loading && opportunities && companies) { + if (opportunities && companies) { setActionBarEntries(); setContextMenuEntries(); + updateCompanyBoard(pipelineSteps, opportunities, companies); setEntityCountInCurrentView(opportunities.length); } }, [ companies, - loading, opportunities, pipelineSteps, setActionBarEntries, diff --git a/front/src/modules/companies/hooks/useUpdateCompanyBoardColumns.ts b/front/src/modules/companies/hooks/useUpdateCompanyBoardColumns.ts index 7bb049049..ae3aca0a1 100644 --- a/front/src/modules/companies/hooks/useUpdateCompanyBoardColumns.ts +++ b/front/src/modules/companies/hooks/useUpdateCompanyBoardColumns.ts @@ -105,7 +105,10 @@ export const useUpdateCompanyBoard = () => position: pipelineStep.position ?? 0, }; }); - if (currentBoardColumns.length === 0) { + if ( + currentBoardColumns.length === 0 && + !isDeeplyEqual(newBoardColumns, currentBoardColumns) + ) { set(boardColumnsState, newBoardColumns); set(savedBoardColumnsState, newBoardColumns); } diff --git a/front/src/modules/pipeline/hooks/usePipelineSteps.ts b/front/src/modules/pipeline/hooks/usePipelineSteps.ts index 39f0e6468..6326adee4 100644 --- a/front/src/modules/pipeline/hooks/usePipelineSteps.ts +++ b/front/src/modules/pipeline/hooks/usePipelineSteps.ts @@ -1,15 +1,12 @@ -import { useRecoilValue } from 'recoil'; +import { useRecoilCallback } from 'recoil'; import { useCreateOneObjectRecord } from '@/object-record/hooks/useCreateOneObjectRecord'; import { useDeleteOneObjectRecord } from '@/object-record/hooks/useDeleteOneObjectRecord'; +import { currentPipelineState } from '@/pipeline/states/currentPipelineState'; import { PipelineStep } from '@/pipeline/types/PipelineStep'; import { BoardColumnDefinition } from '@/ui/layout/board/types/BoardColumnDefinition'; -import { currentPipelineState } from '../states/currentPipelineState'; - export const usePipelineSteps = () => { - const currentPipeline = useRecoilValue(currentPipelineState); - const { createOneObject: createOnePipelineStep } = useCreateOneObjectRecord({ objectNameSingular: 'pipelineStep', @@ -20,28 +17,38 @@ export const usePipelineSteps = () => { objectNameSingular: 'pipelineStep', }); - const handlePipelineStepAdd = async (boardColumn: BoardColumnDefinition) => { - if (!currentPipeline?.id) return; + const handlePipelineStepAdd = useRecoilCallback( + ({ snapshot }) => + async (boardColumn: BoardColumnDefinition) => { + const currentPipeline = await snapshot.getPromise(currentPipelineState); + if (!currentPipeline?.id) return; - return createOnePipelineStep?.({ - variables: { - data: { - color: boardColumn.colorCode ?? 'gray', - id: boardColumn.id, - position: boardColumn.position, - name: boardColumn.title, - pipeline: { connect: { id: currentPipeline.id } }, - type: 'ongoing', - }, + return createOnePipelineStep?.({ + variables: { + data: { + color: boardColumn.colorCode ?? 'gray', + id: boardColumn.id, + position: boardColumn.position, + name: boardColumn.title, + pipeline: { connect: { id: currentPipeline.id } }, + type: 'ongoing', + }, + }, + }); }, - }); - }; + [createOnePipelineStep], + ); - const handlePipelineStepDelete = async (boardColumnId: string) => { - if (!currentPipeline?.id) return; + const handlePipelineStepDelete = useRecoilCallback( + ({ snapshot }) => + async (boardColumnId: string) => { + const currentPipeline = await snapshot.getPromise(currentPipelineState); + if (!currentPipeline?.id) return; - return deleteOnePipelineStep?.(boardColumnId); - }; + return deleteOnePipelineStep?.(boardColumnId); + }, + [deleteOnePipelineStep], + ); return { handlePipelineStepAdd, handlePipelineStepDelete }; }; diff --git a/front/src/modules/ui/input/hooks/useLazyLoadIcons.ts b/front/src/modules/ui/input/hooks/useLazyLoadIcons.ts index 486bfe106..45175cc5d 100644 --- a/front/src/modules/ui/input/hooks/useLazyLoadIcons.ts +++ b/front/src/modules/ui/input/hooks/useLazyLoadIcons.ts @@ -1,9 +1,10 @@ import { useEffect, useState } from 'react'; +import { useRecoilState } from 'recoil'; -import { IconComponent } from '@/ui/display/icon/types/IconComponent'; +import { iconsState } from '@/ui/input/states/iconsState'; export const useLazyLoadIcons = () => { - const [icons, setIcons] = useState>({}); + const [icons, setIcons] = useRecoilState(iconsState); const [isLoadingIcons, setIsLoadingIcons] = useState(true); useEffect(() => { @@ -11,7 +12,7 @@ export const useLazyLoadIcons = () => { setIcons(lazyLoadedIcons); setIsLoadingIcons(false); }); - }, []); + }, [setIcons]); return { icons, isLoadingIcons }; }; diff --git a/front/src/modules/ui/input/states/iconsState.ts b/front/src/modules/ui/input/states/iconsState.ts new file mode 100644 index 000000000..4f489150a --- /dev/null +++ b/front/src/modules/ui/input/states/iconsState.ts @@ -0,0 +1,8 @@ +import { atom } from 'recoil'; + +import { IconComponent } from '@/ui/display/icon/types/IconComponent'; + +export const iconsState = atom>({ + key: 'iconsState', + default: {}, +}); diff --git a/front/src/modules/ui/layout/board/components/EntityBoard.tsx b/front/src/modules/ui/layout/board/components/EntityBoard.tsx index 2178fdc49..0dfdf074d 100644 --- a/front/src/modules/ui/layout/board/components/EntityBoard.tsx +++ b/front/src/modules/ui/layout/board/components/EntityBoard.tsx @@ -1,5 +1,4 @@ import { useCallback, useRef } from 'react'; -import { useApolloClient } from '@apollo/client'; import styled from '@emotion/styled'; import { DragDropContext, OnDragEndResponder } from '@hello-pangea/dnd'; // Atlassian dnd does not support StrictMode from RN 18, so we use a fork @hello-pangea/dnd https://github.com/atlassian/react-beautiful-dnd/issues/2350 import { useRecoilValue } from 'recoil'; @@ -9,6 +8,9 @@ import { Opportunity } from '@/pipeline/types/Opportunity'; import { PageHotkeyScope } from '@/types/PageHotkeyScope'; import { StyledBoard } from '@/ui/layout/board/components/StyledBoard'; import { BoardColumnContext } from '@/ui/layout/board/contexts/BoardColumnContext'; +import { useSetCardSelected } from '@/ui/layout/board/hooks/useSetCardSelected'; +import { useUpdateBoardCardIds } from '@/ui/layout/board/hooks/useUpdateBoardCardIds'; +import { boardColumnsState } from '@/ui/layout/board/states/boardColumnsState'; import { DragSelect } from '@/ui/utilities/drag-select/components/DragSelect'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { useListenClickOutsideByClassName } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside'; @@ -16,10 +18,6 @@ import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope' import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper'; import { logError } from '~/utils/logError'; -import { useCurrentCardSelected } from '../hooks/useCurrentCardSelected'; -import { useSetCardSelected } from '../hooks/useSetCardSelected'; -import { useUpdateBoardCardIds } from '../hooks/useUpdateBoardCardIds'; -import { boardColumnsState } from '../states/boardColumnsState'; import { BoardColumnRecoilScopeContext } from '../states/recoil-scope-contexts/BoardColumnRecoilScopeContext'; import { BoardColumnDefinition } from '../types/BoardColumnDefinition'; import { BoardOptions } from '../types/BoardOptions'; @@ -53,16 +51,13 @@ export const EntityBoard = ({ onEditColumnTitle, }: EntityBoardProps) => { const boardColumns = useRecoilValue(boardColumnsState); - const setCardSelected = useSetCardSelected(); const { updateOneObject: updateOneOpportunity } = useUpdateOneObjectRecord({ objectNameSingular: 'opportunity', }); - const apolloClient = useApolloClient(); - - const { unselectAllActiveCards } = useCurrentCardSelected(); + const { unselectAllActiveCards, setCardSelected } = useSetCardSelected(); const updatePipelineProgressStageInDB = useCallback( async (pipelineProgressId: string, pipelineStepId: string) => { @@ -72,19 +67,8 @@ export const EntityBoard = ({ pipelineStepId: pipelineStepId, }, }); - - const cache = apolloClient.cache; - cache.modify({ - id: cache.identify({ - id: pipelineProgressId, - __typename: 'PipelineProgress', - }), - fields: { - pipelineStepId: () => pipelineStepId, - }, - }); }, - [apolloClient.cache, updateOneOpportunity], + [updateOneOpportunity], ); useListenClickOutsideByClassName({ @@ -135,7 +119,7 @@ export const EntityBoard = ({ PageHotkeyScope.OpportunitiesPage, ); - return (boardColumns?.length ?? 0) > 0 ? ( + return ( @@ -172,7 +156,5 @@ export const EntityBoard = ({ onDragSelectionChange={setCardSelected} /> - ) : ( - <> ); }; diff --git a/front/src/modules/ui/layout/board/hooks/useCurrentCardSelected.ts b/front/src/modules/ui/layout/board/hooks/useCurrentCardSelected.ts index 234704a74..450077914 100644 --- a/front/src/modules/ui/layout/board/hooks/useCurrentCardSelected.ts +++ b/front/src/modules/ui/layout/board/hooks/useCurrentCardSelected.ts @@ -1,16 +1,16 @@ import { useContext } from 'react'; import { useRecoilCallback, useRecoilValue, useSetRecoilState } from 'recoil'; +import { activeCardIdsState } from '@/ui/layout/board/states/activeCardIdsState'; import { actionBarOpenState } from '@/ui/navigation/action-bar/states/actionBarIsOpenState'; import { BoardCardIdContext } from '../contexts/BoardCardIdContext'; -import { activeCardIdsState } from '../states/activeCardIdsState'; import { isCardSelectedFamilyState } from '../states/isCardSelectedFamilyState'; export const useCurrentCardSelected = () => { const currentCardId = useContext(BoardCardIdContext); - const isCardSelected = useRecoilValue( + const isCurrentCardSelected = useRecoilValue( isCardSelectedFamilyState(currentCardId ?? ''), ); @@ -38,24 +38,8 @@ export const useCurrentCardSelected = () => { [currentCardId, setActiveCardIds], ); - const unselectAllActiveCards = useRecoilCallback( - ({ set, snapshot }) => - () => { - const activeCardIds = snapshot.getLoadable(activeCardIdsState).contents; - - activeCardIds.forEach((cardId: string) => { - set(isCardSelectedFamilyState(cardId), false); - }); - - set(activeCardIdsState, []); - set(actionBarOpenState, false); - }, - [], - ); - return { - currentCardSelected: isCardSelected, + isCurrentCardSelected, setCurrentCardSelected, - unselectAllActiveCards, }; }; diff --git a/front/src/modules/ui/layout/board/hooks/useSetCardSelected.ts b/front/src/modules/ui/layout/board/hooks/useSetCardSelected.ts index 66d83275a..45344e708 100644 --- a/front/src/modules/ui/layout/board/hooks/useSetCardSelected.ts +++ b/front/src/modules/ui/layout/board/hooks/useSetCardSelected.ts @@ -1,4 +1,4 @@ -import { useRecoilCallback, useSetRecoilState } from 'recoil'; +import { useRecoilCallback } from 'recoil'; import { actionBarOpenState } from '@/ui/navigation/action-bar/states/actionBarIsOpenState'; @@ -6,15 +6,13 @@ import { activeCardIdsState } from '../states/activeCardIdsState'; import { isCardSelectedFamilyState } from '../states/isCardSelectedFamilyState'; export const useSetCardSelected = () => { - const setActionBarOpenState = useSetRecoilState(actionBarOpenState); - - return useRecoilCallback( + const setCardSelected = useRecoilCallback( ({ set, snapshot }) => (cardId: string, selected: boolean) => { const activeCardIds = snapshot.getLoadable(activeCardIdsState).contents; set(isCardSelectedFamilyState(cardId), selected); - setActionBarOpenState(selected || activeCardIds.length > 0); + set(actionBarOpenState, selected || activeCardIds.length > 0); if (selected) { set(activeCardIdsState, [...activeCardIds, cardId]); @@ -26,4 +24,24 @@ export const useSetCardSelected = () => { } }, ); + + const unselectAllActiveCards = useRecoilCallback( + ({ set, snapshot }) => + () => { + const activeCardIds = snapshot.getLoadable(activeCardIdsState).contents; + + activeCardIds.forEach((cardId: string) => { + set(isCardSelectedFamilyState(cardId), false); + }); + + set(activeCardIdsState, []); + set(actionBarOpenState, false); + }, + [], + ); + + return { + setCardSelected, + unselectAllActiveCards, + }; }; diff --git a/front/src/pages/opportunities/Opportunities.tsx b/front/src/pages/opportunities/Opportunities.tsx index 9b34d0ef6..337b73ce0 100644 --- a/front/src/pages/opportunities/Opportunities.tsx +++ b/front/src/pages/opportunities/Opportunities.tsx @@ -1,9 +1,7 @@ -import { useEffect } from 'react'; import styled from '@emotion/styled'; import { CompanyBoard } from '@/companies/board/components/CompanyBoard'; import { CompanyBoardRecoilScopeContext } from '@/companies/states/recoil-scope-contexts/CompanyBoardRecoilScopeContext'; -import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { useUpdateOneObjectRecord } from '@/object-record/hooks/useUpdateOneObjectRecord'; import { PipelineAddButton } from '@/pipeline/components/PipelineAddButton'; import { usePipelineSteps } from '@/pipeline/hooks/usePipelineSteps'; @@ -14,7 +12,6 @@ import { PageBody } from '@/ui/layout/page/PageBody'; import { PageContainer } from '@/ui/layout/page/PageContainer'; import { PageHeader } from '@/ui/layout/page/PageHeader'; import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; -import { useView } from '@/views/hooks/useView'; import { opportunitiesBoardOptions } from '~/pages/opportunities/opportunitiesBoardOptions'; const StyledBoardContainer = styled.div` @@ -46,18 +43,6 @@ export const Opportunities = () => { }); }; - const opportunitiesV2MetadataId = useObjectMetadataItem({ - objectNameSingular: 'opportunity', - }).objectMetadataItem?.id; - - const { setViewObjectMetadataId } = useView({ - viewScopeId: 'company-board-view', - }); - - useEffect(() => { - setViewObjectMetadataId?.(opportunitiesV2MetadataId); - }, [opportunitiesV2MetadataId, setViewObjectMetadataId]); - return (