Board V2 - Part 1 (#2619)

* improve useComputeDefinitionsFromFieldMetadata to prevent infinit loops

* fix viewFields

* improve initial seeding

* fix height 100%

* fix filters and sorts

* allow filter on currency

* remove probability from filter

* fix opportunities count

* fix persist filters and sorts
This commit is contained in:
bosiraphael
2023-11-21 18:01:30 +01:00
committed by GitHub
parent 9912f7a336
commit ad8331aa89
12 changed files with 152 additions and 95 deletions

View File

@ -1,4 +1,5 @@
import styled from '@emotion/styled';
import { useSetRecoilState } from 'recoil';
import { BoardContext } from '@/companies/states/contexts/BoardContext';
import { BoardOptionsDropdown } from '@/ui/layout/board/components/BoardOptionsDropdown';
@ -10,6 +11,7 @@ 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';
@ -35,8 +37,32 @@ export const CompanyBoard = ({
onEditColumnTitle,
}: 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 (
<ViewScope viewScopeId={viewScopeId}>
<ViewScope
viewScopeId={viewScopeId}
onViewFieldsChange={(viewFields) => {
setCurrentViewFields(viewFields);
}}
onViewFiltersChange={(viewFilters) => {
setCurrentViewFilters(viewFilters);
}}
onViewSortsChange={(viewSorts) => {
setCurrentViewSorts(viewSorts);
}}
>
<StyledContainer>
<BoardContext.Provider
value={{

View File

@ -1,6 +1,5 @@
import { useCallback, useEffect, useMemo, useState } from 'react';
import { useSearchParams } from 'react-router-dom';
import { useRecoilCallback, useRecoilState, useRecoilValue } from 'recoil';
import { useCallback, useEffect, useState } from 'react';
import { useRecoilState, useRecoilValue } from 'recoil';
import { Company } from '@/companies/types/Company';
import { useComputeDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useComputeDefinitionsFromFieldMetadata';
@ -16,13 +15,16 @@ import { useBoardContextMenuEntries } from '@/ui/layout/board/hooks/useBoardCont
import { availableBoardCardFieldsScopedState } from '@/ui/layout/board/states/availableBoardCardFieldsScopedState';
import { boardCardFieldsScopedState } from '@/ui/layout/board/states/boardCardFieldsScopedState';
import { isBoardLoadedState } from '@/ui/layout/board/states/isBoardLoadedState';
import { turnFiltersIntoWhereClauseV2 } from '@/ui/object/object-filter-dropdown/utils/turnFiltersIntoWhereClauseV2';
import { turnSortsIntoOrderByV2 } from '@/ui/object/object-sort-dropdown/utils/turnSortsIntoOrderByV2';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useRecoilScopedStateV2 } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedStateV2';
import { useSetRecoilScopedStateV2 } from '@/ui/utilities/recoil-scope/hooks/useSetRecoilScopedStateV2';
import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates';
import { useView } from '@/views/hooks/useView';
import { ViewType } from '@/views/types/ViewType';
import { mapViewFieldsToBoardFieldDefinitions } from '@/views/utils/mapViewFieldsToBoardFieldDefinitions';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters';
import { mapViewSortsToSorts } from '@/views/utils/mapViewSortsToSorts';
import { useUpdateCompanyBoardCardIds } from '../hooks/useUpdateBoardCardIds';
import { useUpdateCompanyBoard } from '../hooks/useUpdateCompanyBoardColumns';
@ -37,13 +39,19 @@ export const HooksCompanyBoardEffect = () => {
setViewType,
} = useView();
const { currentViewFieldsState } = useViewScopedStates();
const {
currentViewFieldsState,
currentViewFiltersState,
currentViewSortsState,
} = useViewScopedStates();
const [pipelineSteps, setPipelineSteps] = useState<PipelineStep[]>([]);
const [opportunities, setOpportunities] = useState<Opportunity[]>([]);
const [companies, setCompanies] = useState<Company[]>([]);
const currentViewFields = useRecoilValue(currentViewFieldsState);
const currentViewFilters = useRecoilValue(currentViewFiltersState);
const currentViewSorts = useRecoilValue(currentViewSortsState);
const { objectMetadataItem } = useObjectMetadataItem({
objectNamePlural: 'opportunities',
@ -64,6 +72,11 @@ export const HooksCompanyBoardEffect = () => {
const updateCompanyBoardCardIds = useUpdateCompanyBoardCardIds();
const updateCompanyBoard = useUpdateCompanyBoard();
const setAvailableBoardCardFields = useSetRecoilScopedStateV2(
availableBoardCardFieldsScopedState,
'company-board-view',
);
useFindManyObjectRecords({
objectNamePlural: 'pipelineSteps',
filter: {},
@ -75,23 +88,21 @@ export const HooksCompanyBoardEffect = () => {
),
});
const whereFilters = useMemo(() => {
return {
and: [
{
pipelineStepId: {
in: pipelineSteps.map((pipelineStep) => pipelineStep.id),
},
},
...[],
],
};
}, [pipelineSteps]) as any;
const filter = turnFiltersIntoWhereClauseV2(
mapViewFiltersToFilters(currentViewFilters),
objectMetadataItem?.fields ?? [],
);
const orderBy = turnSortsIntoOrderByV2(
mapViewSortsToSorts(currentViewSorts),
objectMetadataItem?.fields ?? [],
);
useFindManyObjectRecords({
skip: !pipelineSteps.length,
objectNamePlural: 'opportunities',
filter: whereFilters,
filter: filter,
orderBy: orderBy,
onCompleted: useCallback(
(data: PaginatedObjectTypeResults<Opportunity>) => {
const pipelineProgresses: Array<Opportunity> = data.edges.map(
@ -137,39 +148,6 @@ export const HooksCompanyBoardEffect = () => {
sortDefinitions,
]);
const setAvailableBoardCardFields = useRecoilCallback(
({ snapshot, set }) =>
(availableBoardCardFields: any) => {
const availableBoardCardFieldsFromState = snapshot
.getLoadable(
availableBoardCardFieldsScopedState({
scopeId: 'company-board-view',
}),
)
.getValue();
if (
!isDeeplyEqual(
availableBoardCardFieldsFromState,
availableBoardCardFields,
)
) {
set(
availableBoardCardFieldsScopedState({
scopeId: 'company-board-view',
}),
availableBoardCardFields,
);
}
},
[],
);
useRecoilScopedStateV2(
availableBoardCardFieldsScopedState,
'company-board-view',
);
useEffect(() => {
const availableTableColumns = columnDefinitions.filter(
filterAvailableTableColumns,
@ -179,11 +157,12 @@ export const HooksCompanyBoardEffect = () => {
}, [columnDefinitions, setAvailableBoardCardFields]);
useEffect(() => {
setViewObjectMetadataId?.('company');
if (!objectMetadataItem) {
return;
}
setViewObjectMetadataId?.(objectMetadataItem.id);
setViewType?.(ViewType.Kanban);
}, [setViewObjectMetadataId, setViewType]);
const [searchParams] = useSearchParams();
}, [objectMetadataItem, setViewObjectMetadataId, setViewType]);
const loading = !companies;
@ -194,9 +173,8 @@ export const HooksCompanyBoardEffect = () => {
if (!loading && opportunities && companies) {
setActionBarEntries();
setContextMenuEntries();
updateCompanyBoard(pipelineSteps, opportunities, companies);
setEntityCountInCurrentView(companies.length);
setEntityCountInCurrentView(opportunities.length);
}
}, [
companies,
@ -212,10 +190,13 @@ export const HooksCompanyBoardEffect = () => {
useEffect(() => {
if (currentViewFields) {
setBoardCardFields(
mapViewFieldsToBoardFieldDefinitions(currentViewFields, []),
mapViewFieldsToBoardFieldDefinitions(
currentViewFields,
columnDefinitions,
),
);
}
}, [currentViewFields, setBoardCardFields]);
}, [columnDefinitions, currentViewFields, setBoardCardFields]);
return <></>;
};