Refactor ObjectDataTable to work with new views system (#2274)

Complete work
This commit is contained in:
Charles Bochet
2023-10-29 23:50:59 +01:00
committed by GitHub
parent 9bab28912d
commit d38497c46a
39 changed files with 578 additions and 373 deletions

View File

@ -79,6 +79,7 @@ const StyledTableContainer = styled.div`
flex-direction: column;
height: 100%;
overflow: auto;
position: relative;
`;
type DataTableProps = {
@ -121,20 +122,20 @@ export const DataTable = ({ updateEntityMutation }: DataTableProps) => {
return (
<EntityUpdateMutationContext.Provider value={updateEntityMutation}>
<StyledTableWithHeader>
<StyledTableContainer ref={tableBodyRef}>
<StyledTableContainer>
<ScrollWrapper>
<div>
<div ref={tableBodyRef}>
<StyledTable className="entity-table-cell">
<DataTableHeader />
<DataTableBody />
</StyledTable>
<DragSelect
dragSelectable={tableBodyRef}
onDragSelectionStart={resetTableRowSelection}
onDragSelectionChange={setRowSelectedState}
/>
</div>
</ScrollWrapper>
<DragSelect
dragSelectable={tableBodyRef}
onDragSelectionStart={resetTableRowSelection}
onDragSelectionChange={setRowSelectedState}
/>
</StyledTableContainer>
</StyledTableWithHeader>
</EntityUpdateMutationContext.Provider>

View File

@ -23,10 +23,8 @@ export const DataTableEffect = ({
getRequestResultKey,
getRequestOptimisticEffectDefinition,
filterDefinitionArray,
setActionBarEntries,
setContextMenuEntries,
sortDefinitionArray,
}: {
useGetRequest: typeof useGetCompaniesQuery | typeof useGetPeopleQuery;
getRequestResultKey: string;
@ -59,7 +57,7 @@ export const DataTableEffect = ({
onCompleted: (data: any) => {
const entities = data[getRequestResultKey] ?? [];
setDataTableData(entities, filterDefinitionArray, sortDefinitionArray);
setDataTableData(entities);
registerOptimisticEffect({
variables: { orderBy: sortsOrderBy, where: tablefiltersWhere },

View File

@ -1,15 +1,10 @@
import { useRecoilCallback } from 'recoil';
import { entityFieldsFamilyState } from '@/ui/data/field/states/entityFieldsFamilyState';
import { FilterDefinition } from '@/ui/data/filter/types/FilterDefinition';
import { useRecoilScopeId } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopeId';
import { useView } from '@/views/hooks/useView';
import { availableSortDefinitionsScopedState } from '@/views/states/availableSortDefinitionsScopedState';
import { SortDefinition } from '../../sort/types/SortDefinition';
import { isFetchingDataTableDataState } from '../states/isFetchingDataTableDataState';
import { numberOfTableRowsState } from '../states/numberOfTableRowsState';
import { TableRecoilScopeContext } from '../states/recoil-scope-contexts/TableRecoilScopeContext';
import { tableRowIdsState } from '../states/tableRowIdsState';
import { useResetTableRowSelection } from './useResetTableRowSelection';
@ -18,15 +13,9 @@ export const useSetDataTableData = () => {
const resetTableRowSelection = useResetTableRowSelection();
const { setEntityCountInCurrentView } = useView();
const tableContextScopeId = useRecoilScopeId(TableRecoilScopeContext);
return useRecoilCallback(
({ set, snapshot }) =>
<T extends { id: string }>(
newEntityArray: T[],
filterDefinitionArray: FilterDefinition[],
sortDefinitionArray: SortDefinition[],
) => {
<T extends { id: string }>(newEntityArray: T[]) => {
for (const entity of newEntityArray) {
const currentEntity = snapshot
.getLoadable(entityFieldsFamilyState(entity.id))
@ -50,16 +39,9 @@ export const useSetDataTableData = () => {
resetTableRowSelection();
set(numberOfTableRowsState, entityIds.length);
setEntityCountInCurrentView(entityIds.length);
set(
availableSortDefinitionsScopedState({ scopeId: tableContextScopeId }),
sortDefinitionArray,
);
set(isFetchingDataTableDataState, false);
},
[resetTableRowSelection, setEntityCountInCurrentView, tableContextScopeId],
[resetTableRowSelection, setEntityCountInCurrentView],
);
};

View File

@ -0,0 +1,53 @@
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
import { Field } from '~/generated/graphql';
import { Filter } from '../types/Filter';
type FilterToTurnIntoWhereClause = Omit<Filter, 'definition'> & {
definition: {
type: Filter['definition']['type'];
};
};
export const turnFiltersIntoWhereClauseV2 = (
filters: FilterToTurnIntoWhereClause[],
fields: Pick<Field, 'id' | 'name'>[],
) => {
const whereClause: Record<string, any> = {};
filters.forEach((filter) => {
const correspondingField = fields.find(
(field) => field.id === filter.fieldId,
);
if (!correspondingField) {
throw new Error(
`Could not find field ${filter.fieldId} in metadata object`,
);
}
switch (filter.definition.type) {
case 'text':
switch (filter.operand) {
case ViewFilterOperand.Contains:
whereClause[correspondingField.name] = {
eq: filter.value,
};
return;
case ViewFilterOperand.DoesNotContain:
whereClause[correspondingField.name] = {
not: {
eq: filter.value,
},
};
return;
default:
throw new Error(
`Unknown operand ${filter.operand} for ${filter.definition.type} filter`,
);
}
default:
throw new Error('Unknown filter type');
}
});
return whereClause;
};

View File

@ -1,6 +1,6 @@
import { useRecoilScopedStateV2 } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedStateV2';
import { availableSortDefinitionsScopedState } from '@/views/states/availableSortDefinitionsScopedState';
import { availableSortDefinitionsScopedState } from '../states/availableSortDefinitionsScopedState';
import { isSortSelectedScopedState } from '../states/isSortSelectedScopedState';
export const useSortStates = (scopeId: string) => {

View File

@ -2,7 +2,9 @@ import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScope
import { SortDefinition } from '../types/SortDefinition';
export const availableSortsScopedState = createScopedState<SortDefinition[]>({
key: 'availableSortsScopedState',
export const availableSortDefinitionsScopedState = createScopedState<
SortDefinition[]
>({
key: 'availableSortDefinitionsScopedState',
defaultValue: [],
});

View File

@ -0,0 +1,26 @@
import { Field } from '~/generated/graphql';
import { Sort } from '../types/Sort';
export const turnSortsIntoOrderByV2 = (
sorts: Sort[],
fields: Pick<Field, 'id' | 'name'>[],
) => {
const sortsObject: Record<string, 'AscNullsFirst' | 'DescNullsLast'> = {};
sorts.forEach((sort) => {
const correspondingField = fields.find(
(field) => field.id === sort.fieldId,
);
if (!correspondingField) {
throw new Error(
`Could not find field ${sort.fieldId} in metadata object`,
);
}
const direction =
sort.direction === 'asc' ? 'AscNullsFirst' : 'DescNullsLast';
sortsObject[correspondingField.name] = direction;
});
return sortsObject;
};

View File

@ -42,6 +42,7 @@ const StyledWrapper = styled.div`
flex-direction: column;
height: 100%;
overflow: hidden;
position: relative;
width: 100%;
`;

View File

@ -2,7 +2,7 @@ import { MemoryRouter } from 'react-router-dom';
import { Meta, StoryObj } from '@storybook/react';
import { useSetRecoilState } from 'recoil';
import { useCompanyTableActionBarEntries } from '@/companies/hooks/useCompanyTableActionBarEntries';
import { useCompanyTableContextMenuEntries } from '@/companies/hooks/useCompanyTableContextMenuEntries';
import { CompanyTableMockMode } from '@/companies/table/components/CompanyTableMockMode';
import { TableRecoilScopeContext } from '@/ui/data/data-table/states/recoil-scope-contexts/TableRecoilScopeContext';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
@ -12,7 +12,7 @@ import { actionBarOpenState } from '../../states/actionBarIsOpenState';
import { ActionBar } from '../ActionBar';
const FilledActionBar = (props: { selectedIds: string[] }) => {
const { setActionBarEntries } = useCompanyTableActionBarEntries();
const { setActionBarEntries } = useCompanyTableContextMenuEntries();
setActionBarEntries();
const setActionBarOpenState = useSetRecoilState(actionBarOpenState);
setActionBarOpenState(true);