Remap items in board (#3643)

* Remap items in board

* Fix according to review
This commit is contained in:
Charles Bochet
2024-01-26 17:09:30 +01:00
committed by GitHub
parent ebfa1bea99
commit 070900e4eb
26 changed files with 320 additions and 47 deletions

View File

@ -3,7 +3,7 @@ import styled from '@emotion/styled';
import { DragDropContext } 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 { DragDropContext } 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'; import { useRecoilValue } from 'recoil';
import { useRecordBoard } from '@/object-record/record-board/hooks/useRecordBoard'; import { useRecordBoardStates } from '@/object-record/record-board/hooks/internal/useRecordBoardStates';
import { RecordBoardColumn } from '@/object-record/record-board/record-board-column/components/RecordBoardColumn'; import { RecordBoardColumn } from '@/object-record/record-board/record-board-column/components/RecordBoardColumn';
import { RecordBoardScope } from '@/object-record/record-board/scopes/RecordBoardScope'; import { RecordBoardScope } from '@/object-record/record-board/scopes/RecordBoardScope';
import { DragSelect } from '@/ui/utilities/drag-select/components/DragSelect'; import { DragSelect } from '@/ui/utilities/drag-select/components/DragSelect';
@ -40,7 +40,7 @@ const StyledBoardHeader = styled.div`
export const RecordBoard = ({ recordBoardId }: RecordBoardProps) => { export const RecordBoard = ({ recordBoardId }: RecordBoardProps) => {
const boardRef = useRef<HTMLDivElement>(null); const boardRef = useRef<HTMLDivElement>(null);
const { getColumnIdsState } = useRecordBoard(recordBoardId); const { getColumnIdsState } = useRecordBoardStates(recordBoardId);
const columnIds = useRecoilValue(getColumnIdsState()); const columnIds = useRecoilValue(getColumnIdsState());

View File

@ -2,6 +2,11 @@ import { RecordBoardScopeInternalContext } from '@/object-record/record-board/sc
import { isFirstRecordBoardColumnFamilyStateScopeMap } from '@/object-record/record-board/states/isFirstRecordBoardColumnFamilyStateScopeMap'; import { isFirstRecordBoardColumnFamilyStateScopeMap } from '@/object-record/record-board/states/isFirstRecordBoardColumnFamilyStateScopeMap';
import { isLastRecordBoardColumnFamilyStateScopeMap } from '@/object-record/record-board/states/isLastRecordBoardColumnFamilyStateScopeMap'; import { isLastRecordBoardColumnFamilyStateScopeMap } from '@/object-record/record-board/states/isLastRecordBoardColumnFamilyStateScopeMap';
import { recordBoardColumnIdsStateScopeMap } from '@/object-record/record-board/states/recordBoardColumnIdsStateScopeMap'; import { recordBoardColumnIdsStateScopeMap } from '@/object-record/record-board/states/recordBoardColumnIdsStateScopeMap';
import { recordBoardFieldDefinitionsStateScopeMap } from '@/object-record/record-board/states/recordBoardFieldDefinitionsStateScopeMap';
import { recordBoardFiltersStateScopeMap } from '@/object-record/record-board/states/recordBoardFiltersStateScopeMap';
import { recordBoardObjectMetadataSingularNameStateScopeMap } from '@/object-record/record-board/states/recordBoardObjectMetadataSingularNameStateScopeMap';
import { recordBoardRecordIdsByColumnIdFamilyStateScopeMap } from '@/object-record/record-board/states/recordBoardRecordIdsByColumnIdFamilyStateScopeMap';
import { recordBoardSortsStateScopeMap } from '@/object-record/record-board/states/recordBoardSortsStateScopeMap';
import { recordBoardColumnsFamilySelectorScopeMap } from '@/object-record/record-board/states/selectors/recordBoardColumnsFamilySelectorScopeMap'; import { recordBoardColumnsFamilySelectorScopeMap } from '@/object-record/record-board/states/selectors/recordBoardColumnsFamilySelectorScopeMap';
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId'; import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
import { getFamilyState } from '@/ui/utilities/recoil-scope/utils/getFamilyState'; import { getFamilyState } from '@/ui/utilities/recoil-scope/utils/getFamilyState';
@ -16,6 +21,10 @@ export const useRecordBoardStates = (recordBoardId?: string) => {
return { return {
scopeId, scopeId,
getObjectMetadataSingularNameState: getState(
recordBoardObjectMetadataSingularNameStateScopeMap,
scopeId,
),
getColumnIdsState: getState(recordBoardColumnIdsStateScopeMap, scopeId), getColumnIdsState: getState(recordBoardColumnIdsStateScopeMap, scopeId),
isFirstColumnFamilyState: getFamilyState( isFirstColumnFamilyState: getFamilyState(
isFirstRecordBoardColumnFamilyStateScopeMap, isFirstRecordBoardColumnFamilyStateScopeMap,
@ -29,5 +38,17 @@ export const useRecordBoardStates = (recordBoardId?: string) => {
recordBoardColumnsFamilySelectorScopeMap, recordBoardColumnsFamilySelectorScopeMap,
scopeId, scopeId,
), ),
getFiltersState: getState(recordBoardFiltersStateScopeMap, scopeId),
getSortsState: getState(recordBoardSortsStateScopeMap, scopeId),
getFieldDefinitionsState: getState(
recordBoardFieldDefinitionsStateScopeMap,
scopeId,
),
recordBoardRecordIdsByColumnIdFamilyState: getFamilyState(
recordBoardRecordIdsByColumnIdFamilyStateScopeMap,
scopeId,
),
}; };
}; };

View File

@ -8,7 +8,7 @@ export const useSetRecordBoardColumns = (recordBoardId?: string) => {
const { scopeId, getColumnIdsState, columnsFamilySelector } = const { scopeId, getColumnIdsState, columnsFamilySelector } =
useRecordBoardStates(recordBoardId); useRecordBoardStates(recordBoardId);
const setRecordBoardColumns = useRecoilCallback( const setColumns = useRecoilCallback(
({ set, snapshot }) => ({ set, snapshot }) =>
(columns: RecordBoardColumnDefinition[]) => { (columns: RecordBoardColumnDefinition[]) => {
const currentColumnsIds = snapshot const currentColumnsIds = snapshot
@ -43,6 +43,6 @@ export const useSetRecordBoardColumns = (recordBoardId?: string) => {
return { return {
scopeId, scopeId,
setRecordBoardColumns, setColumns,
}; };
}; };

View File

@ -0,0 +1,44 @@
import { useRecoilCallback } from 'recoil';
import { useRecordBoardStates } from '@/object-record/record-board/hooks/internal/useRecordBoardStates';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
export const useSetRecordBoardRecordIds = (recordBoardId?: string) => {
const {
scopeId,
recordBoardRecordIdsByColumnIdFamilyState,
columnsFamilySelector,
getColumnIdsState,
} = useRecordBoardStates(recordBoardId);
const setRecordIds = useRecoilCallback(
({ set, snapshot }) =>
(records: ObjectRecord[]) => {
const columnIds = snapshot.getLoadable(getColumnIdsState()).getValue();
columnIds.forEach((columnId) => {
const column = snapshot
.getLoadable(columnsFamilySelector(columnId))
.getValue();
const columnRecordIds = records
.filter((record) => record.stage === column?.value)
.map((record) => record.id);
set(
recordBoardRecordIdsByColumnIdFamilyState(columnId),
columnRecordIds,
);
});
},
[
columnsFamilySelector,
getColumnIdsState,
recordBoardRecordIdsByColumnIdFamilyState,
],
);
return {
scopeId,
setRecordIds,
};
};

View File

@ -1,16 +1,21 @@
import { useSetRecoilState } from 'recoil';
import { useRecordBoardStates } from '@/object-record/record-board/hooks/internal/useRecordBoardStates'; import { useRecordBoardStates } from '@/object-record/record-board/hooks/internal/useRecordBoardStates';
import { useSetRecordBoardColumns } from '@/object-record/record-board/hooks/internal/useSetRecordBoardColumns'; import { useSetRecordBoardColumns } from '@/object-record/record-board/hooks/internal/useSetRecordBoardColumns';
import { useSetRecordBoardRecordIds } from '@/object-record/record-board/hooks/internal/useSetRecordBoardRecordIds';
export const useRecordBoard = (recordBoardId?: string) => { export const useRecordBoard = (recordBoardId?: string) => {
const { scopeId, getColumnIdsState, columnsFamilySelector } = const { scopeId, getFieldDefinitionsState } =
useRecordBoardStates(recordBoardId); useRecordBoardStates(recordBoardId);
const { setRecordBoardColumns } = useSetRecordBoardColumns(recordBoardId); const { setColumns } = useSetRecordBoardColumns(recordBoardId);
const { setRecordIds } = useSetRecordBoardRecordIds(recordBoardId);
const setFieldDefinitions = useSetRecoilState(getFieldDefinitionsState());
return { return {
scopeId, scopeId,
getColumnIdsState, setColumns,
columnsFamilySelector, setRecordIds,
setRecordBoardColumns, setFieldDefinitions,
}; };
}; };

View File

@ -33,6 +33,7 @@ export const RecordBoardColumn = ({
isFirstColumnFamilyState, isFirstColumnFamilyState,
isLastColumnFamilyState, isLastColumnFamilyState,
columnsFamilySelector, columnsFamilySelector,
recordBoardRecordIdsByColumnIdFamilyState,
} = useRecordBoardStates(); } = useRecordBoardStates();
const columnDefinition = useRecoilValue( const columnDefinition = useRecoilValue(
columnsFamilySelector(recordBoardColumnId), columnsFamilySelector(recordBoardColumnId),
@ -46,7 +47,11 @@ export const RecordBoardColumn = ({
isLastColumnFamilyState(recordBoardColumnId), isLastColumnFamilyState(recordBoardColumnId),
); );
if (!columnDefinition) { const recordIds = useRecoilValue(
recordBoardRecordIdsByColumnIdFamilyState(recordBoardColumnId),
);
if (!columnDefinition || !recordIds) {
return null; return null;
} }
@ -65,11 +70,10 @@ export const RecordBoardColumn = ({
<RecordBoardColumnCardsContainer <RecordBoardColumnCardsContainer
droppableProvided={droppableProvided} droppableProvided={droppableProvided}
> >
{[].map((cardId, _index) => ( {recordIds.map((recordId) => (
<BoardCardIdContext.Provider <BoardCardIdContext.Provider value={recordId} key={recordId}>
value={cardId} <div>Card</div>
key={cardId} </BoardCardIdContext.Provider>
></BoardCardIdContext.Provider>
))} ))}
</RecordBoardColumnCardsContainer> </RecordBoardColumnCardsContainer>
</StyledColumn> </StyledColumn>

View File

@ -0,0 +1,10 @@
import { FieldMetadata } from '@/object-record/field/types/FieldMetadata';
import { RecordBoardFieldDefinition } from '@/object-record/record-board/types/RecordBoardFieldDefinition';
import { createStateScopeMap } from '@/ui/utilities/recoil-scope/utils/createStateScopeMap';
export const recordBoardFieldDefinitionsStateScopeMap = createStateScopeMap<
RecordBoardFieldDefinition<FieldMetadata>[]
>({
key: 'recordBoardFieldDefinitionsStateScopeMap',
defaultValue: [],
});

View File

@ -0,0 +1,7 @@
import { Filter } from '@/object-record/object-filter-dropdown/types/Filter';
import { createStateScopeMap } from '@/ui/utilities/recoil-scope/utils/createStateScopeMap';
export const recordBoardFiltersStateScopeMap = createStateScopeMap<Filter[]>({
key: 'recordBoardFiltersStateScopeMap',
defaultValue: [],
});

View File

@ -0,0 +1,7 @@
import { createStateScopeMap } from '@/ui/utilities/recoil-scope/utils/createStateScopeMap';
export const recordBoardObjectMetadataSingularNameStateScopeMap =
createStateScopeMap<string | undefined>({
key: 'recordBoardObjectMetadataSingularNameStateScopeMap',
defaultValue: undefined,
});

View File

@ -0,0 +1,7 @@
import { createFamilyStateScopeMap } from '@/ui/utilities/recoil-scope/utils/createFamilyStateScopeMap';
export const recordBoardRecordIdsByColumnIdFamilyStateScopeMap =
createFamilyStateScopeMap<string[], string>({
key: 'recordBoardRecordIdsByColumnIdFamilyStateScopeMap',
defaultValue: [],
});

View File

@ -0,0 +1,7 @@
import { Sort } from '@/object-record/object-sort-dropdown/types/Sort';
import { createStateScopeMap } from '@/ui/utilities/recoil-scope/utils/createStateScopeMap';
export const recordBoardSortsStateScopeMap = createStateScopeMap<Sort[]>({
key: 'recordBoardSortsStateScopeMap',
defaultValue: [],
});

View File

@ -4,6 +4,7 @@ import { ThemeColor } from '@/ui/theme/constants/colors';
export type RecordBoardColumnDefinition = { export type RecordBoardColumnDefinition = {
id: string; id: string;
title: string; title: string;
value: string;
position: number; position: number;
color: ThemeColor; color: ThemeColor;
actions: RecordBoardColumnAction[]; actions: RecordBoardColumnAction[];

View File

@ -0,0 +1,9 @@
import { FieldDefinition } from '@/object-record/field/types/FieldDefinition';
import { FieldMetadata } from '@/object-record/field/types/FieldMetadata';
export type RecordBoardFieldDefinition<T extends FieldMetadata> =
FieldDefinition<T> & {
viewFieldId?: string;
position: number;
isVisible?: boolean;
};

View File

@ -3,12 +3,12 @@ import { RecordBoard } from '@/object-record/record-board/components/RecordBoard
type RecordIndexBoardContainerProps = { type RecordIndexBoardContainerProps = {
recordBoardId: string; recordBoardId: string;
viewBarId: string; viewBarId: string;
objectNamePlural: string; objectNameSingular: string;
createRecord: () => Promise<void>; createRecord: () => Promise<void>;
}; };
export const RecordIndexBoardContainer = ({ export const RecordIndexBoardContainer = ({
recordBoardId, recordBoardId,
}: RecordIndexBoardContainerProps) => { }: RecordIndexBoardContainerProps) => {
return <RecordBoard recordBoardId={recordBoardId}></RecordBoard>; return <RecordBoard recordBoardId={recordBoardId} />;
}; };

View File

@ -2,38 +2,36 @@ import { useCallback, useEffect } from 'react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural';
import { useRecordBoard } from '@/object-record/record-board/hooks/useRecordBoard'; import { useRecordBoard } from '@/object-record/record-board/hooks/useRecordBoard';
import { useLoadRecordIndexBoard } from '@/object-record/record-index/hooks/useLoadRecordIndexBoard';
import { computeRecordBoardColumnDefinitionsFromObjectMetadata } from '@/object-record/utils/computeRecordBoardColumnDefinitionsFromObjectMetadata'; import { computeRecordBoardColumnDefinitionsFromObjectMetadata } from '@/object-record/utils/computeRecordBoardColumnDefinitionsFromObjectMetadata';
type RecordIndexBoardContainerEffectProps = { type RecordIndexBoardContainerEffectProps = {
objectNamePlural: string; objectNameSingular: string;
recordBoardId: string; recordBoardId: string;
viewBarId: string; viewBarId: string;
}; };
export const RecordIndexBoardContainerEffect = ({ export const RecordIndexBoardContainerEffect = ({
objectNamePlural, objectNameSingular,
recordBoardId, recordBoardId,
}: RecordIndexBoardContainerEffectProps) => { }: RecordIndexBoardContainerEffectProps) => {
const { objectNameSingular } = useObjectNameSingularFromPlural({
objectNamePlural,
});
const { objectMetadataItem } = useObjectMetadataItem({ const { objectMetadataItem } = useObjectMetadataItem({
objectNameSingular, objectNameSingular,
}); });
useLoadRecordIndexBoard(objectNameSingular, recordBoardId);
const navigate = useNavigate(); const navigate = useNavigate();
const navigateToSelectSettings = useCallback(() => { const navigateToSelectSettings = useCallback(() => {
navigate(`/settings/objects/${objectNamePlural}`); navigate(`/settings/objects/${objectMetadataItem.namePlural}`);
}, [navigate, objectNamePlural]); }, [navigate, objectMetadataItem.namePlural]);
const { setRecordBoardColumns } = useRecordBoard(recordBoardId); const { setColumns } = useRecordBoard(recordBoardId);
useEffect(() => { useEffect(() => {
setRecordBoardColumns( setColumns(
computeRecordBoardColumnDefinitionsFromObjectMetadata( computeRecordBoardColumnDefinitionsFromObjectMetadata(
objectMetadataItem, objectMetadataItem,
navigateToSelectSettings, navigateToSelectSettings,
@ -43,7 +41,7 @@ export const RecordIndexBoardContainerEffect = ({
navigateToSelectSettings, navigateToSelectSettings,
objectMetadataItem, objectMetadataItem,
objectNameSingular, objectNameSingular,
setRecordBoardColumns, setColumns,
]); ]);
return <></>; return <></>;

View File

@ -1,5 +1,6 @@
import { useState } from 'react'; import { useState } from 'react';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { useSetRecoilState } from 'recoil';
import { useSpreadsheetCompanyImport } from '@/companies/hooks/useSpreadsheetCompanyImport'; import { useSpreadsheetCompanyImport } from '@/companies/hooks/useSpreadsheetCompanyImport';
import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata'; import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata';
@ -10,6 +11,9 @@ import { RecordIndexBoardContainerEffect } from '@/object-record/record-index/co
import { RecordIndexTableContainer } from '@/object-record/record-index/components/RecordIndexTableContainer'; import { RecordIndexTableContainer } from '@/object-record/record-index/components/RecordIndexTableContainer';
import { RecordIndexTableContainerEffect } from '@/object-record/record-index/components/RecordIndexTableContainerEffect'; import { RecordIndexTableContainerEffect } from '@/object-record/record-index/components/RecordIndexTableContainerEffect';
import { RecordIndexViewBarEffect } from '@/object-record/record-index/components/RecordIndexViewBarEffect'; import { RecordIndexViewBarEffect } from '@/object-record/record-index/components/RecordIndexViewBarEffect';
import { recordIndexFieldDefinitionsState } from '@/object-record/record-index/states/recordIndexFieldDefinitionsState';
import { recordIndexFiltersState } from '@/object-record/record-index/states/recordIndexFiltersState';
import { recordIndexSortsState } from '@/object-record/record-index/states/recordIndexSortsState';
import { TableOptionsDropdownId } from '@/object-record/record-table/constants/TableOptionsDropdownId'; import { TableOptionsDropdownId } from '@/object-record/record-table/constants/TableOptionsDropdownId';
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable'; import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
import { TableOptionsDropdown } from '@/object-record/record-table/options/components/TableOptionsDropdown'; import { TableOptionsDropdown } from '@/object-record/record-table/options/components/TableOptionsDropdown';
@ -56,6 +60,12 @@ export const RecordIndexContainer = ({
const { columnDefinitions } = const { columnDefinitions } =
useColumnDefinitionsFromFieldMetadata(objectMetadataItem); useColumnDefinitionsFromFieldMetadata(objectMetadataItem);
const setRecordIndexFieldDefinitions = useSetRecoilState(
recordIndexFieldDefinitionsState,
);
const setRecordIndexFilters = useSetRecoilState(recordIndexFiltersState);
const setRecordIndexSorts = useSetRecoilState(recordIndexSortsState);
const { openPersonSpreadsheetImport } = useSpreadsheetPersonImport(); const { openPersonSpreadsheetImport } = useSpreadsheetPersonImport();
const { openCompanySpreadsheetImport } = useSpreadsheetCompanyImport(); const { openCompanySpreadsheetImport } = useSpreadsheetCompanyImport();
@ -91,12 +101,17 @@ export const RecordIndexContainer = ({
setTableColumns( setTableColumns(
mapViewFieldsToColumnDefinitions(viewFields, columnDefinitions), mapViewFieldsToColumnDefinitions(viewFields, columnDefinitions),
); );
setRecordIndexFieldDefinitions(
mapViewFieldsToColumnDefinitions(viewFields, columnDefinitions),
);
}} }}
onViewFiltersChange={(viewFilters) => { onViewFiltersChange={(viewFilters) => {
setTableFilters(mapViewFiltersToFilters(viewFilters)); setTableFilters(mapViewFiltersToFilters(viewFilters));
setRecordIndexFilters(mapViewFiltersToFilters(viewFilters));
}} }}
onViewSortsChange={(viewSorts) => { onViewSortsChange={(viewSorts) => {
setTableSorts(mapViewSortsToSorts(viewSorts)); setTableSorts(mapViewSortsToSorts(viewSorts));
setRecordIndexSorts(mapViewSortsToSorts(viewSorts));
}} }}
onViewTypeChange={(viewType: ViewType) => { onViewTypeChange={(viewType: ViewType) => {
setRecordIndexViewType(viewType); setRecordIndexViewType(viewType);
@ -112,11 +127,11 @@ export const RecordIndexContainer = ({
<RecordIndexTableContainer <RecordIndexTableContainer
recordTableId={recordIndexId} recordTableId={recordIndexId}
viewBarId={recordIndexId} viewBarId={recordIndexId}
objectNamePlural={objectNamePlural} objectNameSingular={objectNameSingular}
createRecord={createRecord} createRecord={createRecord}
/> />
<RecordIndexTableContainerEffect <RecordIndexTableContainerEffect
objectNamePlural={objectNamePlural} objectNameSingular={objectNameSingular}
recordTableId={recordIndexId} recordTableId={recordIndexId}
viewBarId={recordIndexId} viewBarId={recordIndexId}
/> />
@ -127,11 +142,11 @@ export const RecordIndexContainer = ({
<RecordIndexBoardContainer <RecordIndexBoardContainer
recordBoardId={recordIndexId} recordBoardId={recordIndexId}
viewBarId={recordIndexId} viewBarId={recordIndexId}
objectNamePlural={objectNamePlural} objectNameSingular={objectNameSingular}
createRecord={createRecord} createRecord={createRecord}
/> />
<RecordIndexBoardContainerEffect <RecordIndexBoardContainerEffect
objectNamePlural={objectNamePlural} objectNameSingular={objectNameSingular}
recordBoardId={recordIndexId} recordBoardId={recordIndexId}
viewBarId={recordIndexId} viewBarId={recordIndexId}
/> />

View File

@ -1,4 +1,4 @@
import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { RecordUpdateHookParams } from '@/object-record/field/contexts/FieldContext'; import { RecordUpdateHookParams } from '@/object-record/field/contexts/FieldContext';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
import { RecordTableActionBar } from '@/object-record/record-table/action-bar/components/RecordTableActionBar'; import { RecordTableActionBar } from '@/object-record/record-table/action-bar/components/RecordTableActionBar';
@ -8,18 +8,18 @@ import { RecordTableContextMenu } from '@/object-record/record-table/context-men
type RecordIndexTableContainerProps = { type RecordIndexTableContainerProps = {
recordTableId: string; recordTableId: string;
viewBarId: string; viewBarId: string;
objectNamePlural: string; objectNameSingular: string;
createRecord: () => Promise<void>; createRecord: () => Promise<void>;
}; };
export const RecordIndexTableContainer = ({ export const RecordIndexTableContainer = ({
recordTableId, recordTableId,
viewBarId, viewBarId,
objectNamePlural, objectNameSingular,
createRecord, createRecord,
}: RecordIndexTableContainerProps) => { }: RecordIndexTableContainerProps) => {
const { objectNameSingular } = useObjectNameSingularFromPlural({ const { objectMetadataItem } = useObjectMetadataItem({
objectNamePlural, objectNameSingular,
}); });
const { updateOneRecord } = useUpdateOneRecord({ const { updateOneRecord } = useUpdateOneRecord({
@ -37,7 +37,7 @@ export const RecordIndexTableContainer = ({
<> <>
<RecordTableWithWrappers <RecordTableWithWrappers
recordTableId={recordTableId} recordTableId={recordTableId}
objectNamePlural={objectNamePlural} objectNamePlural={objectMetadataItem.namePlural}
viewBarId={viewBarId} viewBarId={viewBarId}
updateRecordMutation={updateEntity} updateRecordMutation={updateEntity}
createRecord={createRecord} createRecord={createRecord}

View File

@ -2,20 +2,19 @@ import { useEffect } from 'react';
import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata'; import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural';
import { useRecordTableContextMenuEntries } from '@/object-record/hooks/useRecordTableContextMenuEntries'; import { useRecordTableContextMenuEntries } from '@/object-record/hooks/useRecordTableContextMenuEntries';
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable'; import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
import { filterAvailableTableColumns } from '@/object-record/utils/filterAvailableTableColumns'; import { filterAvailableTableColumns } from '@/object-record/utils/filterAvailableTableColumns';
import { useViewBar } from '@/views/hooks/useViewBar'; import { useViewBar } from '@/views/hooks/useViewBar';
type RecordIndexTableContainerEffectProps = { type RecordIndexTableContainerEffectProps = {
objectNamePlural: string; objectNameSingular: string;
recordTableId: string; recordTableId: string;
viewBarId: string; viewBarId: string;
}; };
export const RecordIndexTableContainerEffect = ({ export const RecordIndexTableContainerEffect = ({
objectNamePlural, objectNameSingular,
recordTableId, recordTableId,
viewBarId, viewBarId,
}: RecordIndexTableContainerEffectProps) => { }: RecordIndexTableContainerEffectProps) => {
@ -25,10 +24,6 @@ export const RecordIndexTableContainerEffect = ({
setObjectMetadataConfig, setObjectMetadataConfig,
} = useRecordTable({ recordTableId }); } = useRecordTable({ recordTableId });
const { objectNameSingular } = useObjectNameSingularFromPlural({
objectNamePlural,
});
const { const {
objectMetadataItem, objectMetadataItem,
basePathToShowPage, basePathToShowPage,
@ -74,7 +69,7 @@ export const RecordIndexTableContainerEffect = ({
const { setActionBarEntries, setContextMenuEntries } = const { setActionBarEntries, setContextMenuEntries } =
useRecordTableContextMenuEntries({ useRecordTableContextMenuEntries({
objectNamePlural, objectNamePlural: objectMetadataItem.namePlural,
recordTableId, recordTableId,
}); });

View File

@ -0,0 +1,64 @@
import { useEffect } from 'react';
import { useRecoilValue } from 'recoil';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { turnSortsIntoOrderBy } from '@/object-record/object-sort-dropdown/utils/turnSortsIntoOrderBy';
import { useRecordBoard } from '@/object-record/record-board/hooks/useRecordBoard';
import { turnObjectDropdownFilterIntoQueryFilter } from '@/object-record/record-filter/utils/turnObjectDropdownFilterIntoQueryFilter';
import { recordIndexFieldDefinitionsState } from '@/object-record/record-index/states/recordIndexFieldDefinitionsState';
import { recordIndexFiltersState } from '@/object-record/record-index/states/recordIndexFiltersState';
import { recordIndexSortsState } from '@/object-record/record-index/states/recordIndexSortsState';
import { useSetRecordInStore } from '@/object-record/record-store/hooks/useSetRecordInStore';
export const useLoadRecordIndexBoard = (
objectNameSingular: string,
recordBoardId: string,
) => {
const { objectMetadataItem } = useObjectMetadataItem({
objectNameSingular,
});
const { setRecordIds: setRecordIdsInBoard, setFieldDefinitions } =
useRecordBoard(recordBoardId);
const { setRecords: setRecordsInStore } = useSetRecordInStore();
const recordIndexFieldDefinitions = useRecoilValue(
recordIndexFieldDefinitionsState,
);
useEffect(() => {
setFieldDefinitions(recordIndexFieldDefinitions);
}, [recordIndexFieldDefinitions, setFieldDefinitions]);
const recordIndexFilters = useRecoilValue(recordIndexFiltersState);
const recordIndexSorts = useRecoilValue(recordIndexSortsState);
const requestFilters = turnObjectDropdownFilterIntoQueryFilter(
recordIndexFilters,
objectMetadataItem?.fields ?? [],
);
const orderBy = turnSortsIntoOrderBy(
recordIndexSorts,
objectMetadataItem?.fields ?? [],
);
const { records, loading, fetchMoreRecords, queryStateIdentifier } =
useFindManyRecords({
objectNameSingular,
filter: requestFilters,
orderBy,
});
useEffect(() => {
setRecordIdsInBoard(records);
}, [records, setRecordIdsInBoard]);
useEffect(() => {
setRecordsInStore(records);
}, [records, setRecordsInStore]);
return {
records,
loading,
fetchMoreRecords,
queryStateIdentifier,
};
};

View File

@ -0,0 +1,11 @@
import { atom } from 'recoil';
import { FieldMetadata } from '@/object-record/field/types/FieldMetadata';
import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
export const recordIndexFieldDefinitionsState = atom<
ColumnDefinition<FieldMetadata>[]
>({
key: 'recordIndexFieldDefinitionsState',
default: [],
});

View File

@ -0,0 +1,8 @@
import { atom } from 'recoil';
import { Filter } from '@/object-record/object-filter-dropdown/types/Filter';
export const recordIndexFiltersState = atom<Filter[]>({
key: 'recordIndexFiltersState',
default: [],
});

View File

@ -0,0 +1,8 @@
import { atom } from 'recoil';
import { Sort } from '@/object-record/object-sort-dropdown/types/Sort';
export const recordIndexSortsState = atom<Sort[]>({
key: 'recordIndexSortsState',
default: [],
});

View File

@ -0,0 +1,26 @@
import { useRecoilCallback } from 'recoil';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
export const useSetRecordInStore = () => {
const setRecords = useRecoilCallback(
({ set, snapshot }) =>
(records: ObjectRecord[]) => {
records.forEach((record) => {
const currentRecord = snapshot
.getLoadable(recordStoreFamilyState(record.id))
.valueOrThrow();
if (JSON.stringify(currentRecord) !== JSON.stringify(record)) {
set(recordStoreFamilyState(record.id), record);
}
});
},
[],
);
return {
setRecords,
};
};

View File

@ -0,0 +1,8 @@
import { atomFamily } from 'recoil';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
export const recordStoreFamilyState = atomFamily<ObjectRecord | null, string>({
key: 'recordStoreFamilyState',
default: null,
});

View File

@ -0,0 +1,17 @@
import { selectorFamily } from 'recoil';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
export const recordStoreFamilySelector = selectorFamily({
key: 'recordStoreFamilySelector',
get:
<T>({ fieldName, recordId }: { fieldName: string; recordId: string }) =>
({ get }) =>
get(recordStoreFamilyState(recordId))?.[fieldName] as T,
set:
<T>({ fieldName, recordId }: { fieldName: string; recordId: string }) =>
({ set }, newValue: T) =>
set(recordStoreFamilyState(recordId), (prevState) =>
prevState ? { ...prevState, [fieldName]: newValue } : null,
),
});

View File

@ -24,6 +24,7 @@ export const computeRecordBoardColumnDefinitionsFromObjectMetadata = (
return selectFieldMetadataItem.options.map((selectOption) => ({ return selectFieldMetadataItem.options.map((selectOption) => ({
id: selectOption.id, id: selectOption.id,
title: selectOption.label, title: selectOption.label,
value: selectOption.value,
color: selectOption.color, color: selectOption.color,
position: selectOption.position, position: selectOption.position,
actions: [ actions: [