feat: display record identifier field as first column in table (#3788)

* feat: display record identifier field as first column in table

& forbid hiding and moving record identifier column

Closes #3303

* refactor: add availableTableColumnKeysSelectorScopeMap

* feat: show plus icon button for label identifier column and dropdown menu for other columns

* fix: use label identifier field value in RecordShowPage title

* refactor: remove availableColumnKeys selector

* refactor: review - compute label identifier logic in mapViewFieldsToColumnDefinitions + remove selectors

* fix: several fixes

* fix: fix board fields isVisible

* fix: fix board fields reordering

* fix: more board fields fixes

* fix: fix hiddenTableColumnsSelectorScopeMap
This commit is contained in:
Thaïs
2024-02-09 08:36:08 -03:00
committed by GitHub
parent 9299ad1432
commit 201a2c8acc
30 changed files with 636 additions and 580 deletions

View File

@ -26,6 +26,7 @@ import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { ViewFieldsVisibilityDropdownSection } from '@/views/components/ViewFieldsVisibilityDropdownSection';
import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates';
import { useViewBar } from '@/views/hooks/useViewBar';
import { moveArrayItem } from '~/utils/array/moveArrayItem';
import { useRecordBoardDeprecatedCardFieldsInternal } from '../../hooks/internal/useRecordBoardDeprecatedCardFieldsInternal';
import { BoardColumnDefinition } from '../../types/BoardColumnDefinition';
@ -113,11 +114,12 @@ export const RecordBoardDeprecatedOptionsDropdownContent = ({
return;
}
const reorderFields = [...visibleBoardCardFields];
const [removed] = reorderFields.splice(result.source.index - 1, 1);
reorderFields.splice(result.destination.index - 1, 0, removed);
const reorderedFields = moveArrayItem(visibleBoardCardFields, {
fromIndex: result.source.index - 1,
toIndex: result.destination.index - 1,
});
handleFieldsReorder(reorderFields);
handleFieldsReorder(reorderedFields);
},
[handleFieldsReorder, visibleBoardCardFields],
);
@ -217,10 +219,9 @@ export const RecordBoardDeprecatedOptionsDropdownContent = ({
<ViewFieldsVisibilityDropdownSection
title="Visible"
fields={visibleBoardCardFields}
isVisible={true}
onVisibilityChange={handleFieldVisibilityChange}
isDraggable={true}
isDraggable
onDragEnd={handleReorderField}
onVisibilityChange={handleFieldVisibilityChange}
/>
)}
{hasVisibleFields && hasHiddenFields && <DropdownMenuSeparator />}
@ -228,9 +229,8 @@ export const RecordBoardDeprecatedOptionsDropdownContent = ({
<ViewFieldsVisibilityDropdownSection
title="Hidden"
fields={hiddenBoardCardFields}
isVisible={false}
onVisibilityChange={handleFieldVisibilityChange}
isDraggable={false}
onVisibilityChange={handleFieldVisibilityChange}
/>
)}
</>

View File

@ -74,25 +74,29 @@ export const RecordIndexContainer = ({
const onViewFieldsChange = useRecoilCallback(
({ set, snapshot }) =>
(viewFields: ViewField[]) => {
setTableColumns(
mapViewFieldsToColumnDefinitions(viewFields, columnDefinitions),
const newFieldDefinitions = mapViewFieldsToColumnDefinitions({
viewFields,
columnDefinitions,
});
setTableColumns(newFieldDefinitions);
const newRecordIndexFieldDefinitions = newFieldDefinitions.filter(
(boardField) => !boardField.isLabelIdentifier,
);
const existingRecordIndexFieldDefinitions = snapshot
.getLoadable(recordIndexFieldDefinitionsState)
.getValue();
const newFieldDefinitions = mapViewFieldsToColumnDefinitions(
viewFields,
columnDefinitions,
);
if (
!isDeeplyEqual(
existingRecordIndexFieldDefinitions,
newFieldDefinitions,
newRecordIndexFieldDefinitions,
)
)
set(recordIndexFieldDefinitionsState, newFieldDefinitions);
) {
set(recordIndexFieldDefinitionsState, newRecordIndexFieldDefinitions);
}
},
[columnDefinitions, setTableColumns],
);

View File

@ -5,7 +5,6 @@ import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/u
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useRecordActionBar } from '@/object-record/record-action-bar/hooks/useRecordActionBar';
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
import { filterAvailableTableColumns } from '@/object-record/utils/filterAvailableTableColumns';
import { useViewBar } from '@/views/hooks/useViewBar';
type RecordIndexTableContainerEffectProps = {
@ -32,7 +31,7 @@ export const RecordIndexTableContainerEffect = ({
objectNameSingular,
});
const { columnDefinitions, filterDefinitions, sortDefinitions } =
const { columnDefinitions } =
useColumnDefinitionsFromFieldMetadata(objectMetadataItem);
const { setEntityCountInCurrentView } = useViewBar({
@ -40,18 +39,8 @@ export const RecordIndexTableContainerEffect = ({
});
useEffect(() => {
const availableTableColumns = columnDefinitions.filter(
filterAvailableTableColumns,
);
setAvailableTableColumns(availableTableColumns);
}, [
columnDefinitions,
objectMetadataItem,
sortDefinitions,
filterDefinitions,
setAvailableTableColumns,
]);
setAvailableTableColumns(columnDefinitions);
}, [columnDefinitions, setAvailableTableColumns]);
const selectedRowIds = useRecoilValue(getSelectedRowIdsSelector());

View File

@ -159,10 +159,9 @@ export const RecordIndexOptionsDropdownContent = ({
<ViewFieldsVisibilityDropdownSection
title="Visible"
fields={visibleRecordFields}
isVisible={true}
onVisibilityChange={handleChangeFieldVisibility}
isDraggable={true}
isDraggable
onDragEnd={handleReorderFields}
onVisibilityChange={handleChangeFieldVisibility}
/>
{hiddenRecordFields.length > 0 && (
<>
@ -170,9 +169,8 @@ export const RecordIndexOptionsDropdownContent = ({
<ViewFieldsVisibilityDropdownSection
title="Hidden"
fields={hiddenRecordFields}
isVisible={false}
onVisibilityChange={handleChangeFieldVisibility}
isDraggable={false}
onVisibilityChange={handleChangeFieldVisibility}
/>
</>
)}

View File

@ -9,10 +9,12 @@ import { useRecordBoard } from '@/object-record/record-board/hooks/useRecordBoar
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
import { recordIndexFieldDefinitionsState } from '@/object-record/record-index/states/recordIndexFieldDefinitionsState';
import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
import { filterAvailableTableColumns } from '@/object-record/utils/filterAvailableTableColumns';
import { useViewFields } from '@/views/hooks/internal/useViewFields';
import { useViews } from '@/views/hooks/internal/useViews';
import { GraphQLView } from '@/views/types/GraphQLView';
import { mapArrayToObject } from '~/utils/array/mapArrayToObject';
import { moveArrayItem } from '~/utils/array/moveArrayItem';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
type useRecordIndexOptionsForBoardParams = {
objectNameSingular: string;
@ -40,74 +42,82 @@ export const useRecordIndexOptionsForBoard = ({
objectNameSingular,
});
const { columnDefinitions: availableColumnDefinitions } =
const { columnDefinitions } =
useColumnDefinitionsFromFieldMetadata(objectMetadataItem);
// Todo replace this with label identifier logic
const columnDefinitions = availableColumnDefinitions
.filter(
(columnDefinition) => columnDefinition.metadata.fieldName !== 'name',
)
.filter(filterAvailableTableColumns);
const availableColumnDefinitions = useMemo(
() =>
columnDefinitions.filter(({ isLabelIdentifier }) => !isLabelIdentifier),
[columnDefinitions],
);
const recordIndexFieldDefinitionsByKey = useMemo(
() =>
mapArrayToObject(
recordIndexFieldDefinitions,
({ fieldMetadataId }) => fieldMetadataId,
),
[recordIndexFieldDefinitions],
);
const visibleBoardFields = useMemo(
() =>
columnDefinitions.filter((columnDefinition) => {
return recordIndexFieldDefinitions.some(
(existingRecordFieldDefinition) => {
return (
columnDefinition.fieldMetadataId ===
existingRecordFieldDefinition.fieldMetadataId &&
existingRecordFieldDefinition.isVisible
);
},
);
}),
[columnDefinitions, recordIndexFieldDefinitions],
recordIndexFieldDefinitions
.filter((boardField) => boardField.isVisible)
.sort(
(boardFieldA, boardFieldB) =>
boardFieldA.position - boardFieldB.position,
),
[recordIndexFieldDefinitions],
);
const hiddenBoardFields = useMemo(
() =>
columnDefinitions.filter((columnDefinition) => {
return !recordIndexFieldDefinitions.some(
(existingRecordFieldDefinition) => {
return (
columnDefinition.fieldMetadataId ===
existingRecordFieldDefinition.fieldMetadataId &&
existingRecordFieldDefinition.isVisible
);
},
);
}),
[columnDefinitions, recordIndexFieldDefinitions],
availableColumnDefinitions
.filter(
({ fieldMetadataId }) =>
!recordIndexFieldDefinitionsByKey[fieldMetadataId]?.isVisible,
)
.map((availableColumnDefinition) => {
const { fieldMetadataId } = availableColumnDefinition;
const existingBoardField =
recordIndexFieldDefinitionsByKey[fieldMetadataId];
return {
...(existingBoardField || availableColumnDefinition),
isVisible: false,
};
}),
[availableColumnDefinitions, recordIndexFieldDefinitionsByKey],
);
const handleReorderBoardFields: OnDragEndResponder = useCallback(
(result) => {
if (
!result.destination ||
result.destination.index === 1 ||
result.source.index === 1
) {
if (!result.destination) {
return;
}
const reorderFields = [...recordIndexFieldDefinitions];
const [removed] = reorderFields.splice(result.source.index - 1, 1);
reorderFields.splice(result.destination.index - 1, 0, removed);
const reorderedVisibleBoardFields = moveArrayItem(visibleBoardFields, {
fromIndex: result.source.index - 1,
toIndex: result.destination.index - 1,
});
const updatedFields = reorderFields.map((field, index) => ({
...field,
position: index,
}));
if (isDeeplyEqual(visibleBoardFields, reorderedVisibleBoardFields))
return;
const updatedFields = [
...reorderedVisibleBoardFields,
...hiddenBoardFields,
].map((field, index) => ({ ...field, position: index }));
setRecordIndexFieldDefinitions(updatedFields);
persistViewFields(mapBoardFieldDefinitionsToViewFields(updatedFields));
},
[
hiddenBoardFields,
persistViewFields,
recordIndexFieldDefinitions,
setRecordIndexFieldDefinitions,
visibleBoardFields,
],
);
@ -120,36 +130,43 @@ export const useRecordIndexOptionsForBoard = ({
'size' | 'position'
>,
) => {
const isNewViewField = !recordIndexFieldDefinitions.some(
(fieldDefinition) =>
fieldDefinition.fieldMetadataId ===
updatedFieldDefinition.fieldMetadataId,
const isNewViewField = !(
updatedFieldDefinition.fieldMetadataId in
recordIndexFieldDefinitionsByKey
);
let updatedFieldsDefinitions: ColumnDefinition<FieldMetadata>[];
if (isNewViewField) {
const correspondingFieldDefinition = columnDefinitions.find(
(availableTableColumn) =>
availableTableColumn.fieldMetadataId ===
const correspondingFieldDefinition = availableColumnDefinitions.find(
(availableColumnDefinition) =>
availableColumnDefinition.fieldMetadataId ===
updatedFieldDefinition.fieldMetadataId,
);
if (!correspondingFieldDefinition) return;
const lastVisibleBoardField =
visibleBoardFields[visibleBoardFields.length - 1];
updatedFieldsDefinitions = [
...recordIndexFieldDefinitions,
{ ...correspondingFieldDefinition, isVisible: true },
{
...correspondingFieldDefinition,
position: lastVisibleBoardField.position + 1,
isVisible: true,
},
];
} else {
updatedFieldsDefinitions = recordIndexFieldDefinitions.map(
(exitingFieldDefinition) =>
exitingFieldDefinition.fieldMetadataId ===
(existingFieldDefinition) =>
existingFieldDefinition.fieldMetadataId ===
updatedFieldDefinition.fieldMetadataId
? {
...exitingFieldDefinition,
isVisible: !exitingFieldDefinition.isVisible,
...existingFieldDefinition,
isVisible: !existingFieldDefinition.isVisible,
}
: exitingFieldDefinition,
: existingFieldDefinition,
);
}
@ -160,10 +177,12 @@ export const useRecordIndexOptionsForBoard = ({
);
},
[
recordIndexFieldDefinitions,
recordIndexFieldDefinitionsByKey,
setRecordIndexFieldDefinitions,
persistViewFields,
columnDefinitions,
availableColumnDefinitions,
visibleBoardFields,
recordIndexFieldDefinitions,
],
);

View File

@ -4,6 +4,7 @@ import { useRecoilValue } from 'recoil';
import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates';
import { useTableColumns } from '@/object-record/record-table/hooks/useTableColumns';
import { moveArrayItem } from '~/utils/array/moveArrayItem';
export const useRecordIndexOptionsForTable = (recordTableId: string) => {
const { getHiddenTableColumnsSelector, getVisibleTableColumnsSelector } =
@ -26,11 +27,12 @@ export const useRecordIndexOptionsForTable = (recordTableId: string) => {
return;
}
const reorderFields = [...visibleTableColumns];
const [removed] = reorderFields.splice(result.source.index - 1, 1);
reorderFields.splice(result.destination.index - 1, 0, removed);
const reorderedFields = moveArrayItem(visibleTableColumns, {
fromIndex: result.source.index - 1,
toIndex: result.destination.index - 1,
});
handleColumnReorder(reorderFields);
handleColumnReorder(reorderedFields);
},
[visibleTableColumns, handleColumnReorder],
);

View File

@ -9,9 +9,6 @@ import { RecordTableColumnDropdownMenu } from './RecordTableColumnDropdownMenu';
type ColumnHeadWithDropdownProps = {
column: ColumnDefinition<FieldMetadata>;
isFirstColumn: boolean;
isLastColumn: boolean;
primaryColumnKey: string;
};
const StyledDropdown = styled(Dropdown)`
@ -21,22 +18,12 @@ const StyledDropdown = styled(Dropdown)`
export const ColumnHeadWithDropdown = ({
column,
isFirstColumn,
isLastColumn,
primaryColumnKey,
}: ColumnHeadWithDropdownProps) => {
return (
<StyledDropdown
dropdownId={column.fieldMetadataId + '-header'}
clickableComponent={<ColumnHead column={column} />}
dropdownComponents={
<RecordTableColumnDropdownMenu
column={column}
isFirstColumn={isFirstColumn}
isLastColumn={isLastColumn}
primaryColumnKey={primaryColumnKey}
/>
}
dropdownComponents={<RecordTableColumnDropdownMenu column={column} />}
dropdownOffset={{ x: -1 }}
dropdownPlacement="bottom-start"
dropdownHotkeyScope={{ scope: column.fieldMetadataId + '-header' }}

View File

@ -1,4 +1,7 @@
import { useRecoilValue } from 'recoil';
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates';
import { IconArrowLeft, IconArrowRight, IconEyeOff } from '@/ui/display/icon';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
@ -9,17 +12,23 @@ import { ColumnDefinition } from '../types/ColumnDefinition';
export type RecordTableColumnDropdownMenuProps = {
column: ColumnDefinition<FieldMetadata>;
isFirstColumn: boolean;
isLastColumn: boolean;
primaryColumnKey: string;
};
export const RecordTableColumnDropdownMenu = ({
column,
isFirstColumn,
isLastColumn,
primaryColumnKey,
}: RecordTableColumnDropdownMenuProps) => {
const { getVisibleTableColumnsSelector } = useRecordTableStates();
const visibleTableColumns = useRecoilValue(getVisibleTableColumnsSelector());
const secondVisibleColumn = visibleTableColumns[1];
const canMoveLeft =
column.fieldMetadataId !== secondVisibleColumn?.fieldMetadataId;
const lastVisibleColumn = visibleTableColumns[visibleTableColumns.length - 1];
const canMoveRight =
column.fieldMetadataId !== lastVisibleColumn?.fieldMetadataId;
const { handleColumnVisibilityChange, handleMoveTableColumn } =
useTableColumns();
@ -27,17 +36,17 @@ export const RecordTableColumnDropdownMenu = ({
const handleColumnMoveLeft = () => {
closeDropdown();
if (isFirstColumn) {
return;
}
if (!canMoveLeft) return;
handleMoveTableColumn('left', column);
};
const handleColumnMoveRight = () => {
closeDropdown();
if (isLastColumn) {
return;
}
if (!canMoveRight) return;
handleMoveTableColumn('right', column);
};
@ -46,18 +55,16 @@ export const RecordTableColumnDropdownMenu = ({
handleColumnVisibilityChange(column);
};
return column.fieldMetadataId === primaryColumnKey ? (
<></>
) : (
return (
<DropdownMenuItemsContainer>
{!isFirstColumn && (
{canMoveLeft && (
<MenuItem
LeftIcon={IconArrowLeft}
onClick={handleColumnMoveLeft}
text="Move left"
/>
)}
{!isLastColumn && (
{canMoveRight && (
<MenuItem
LeftIcon={IconArrowRight}
onClick={handleColumnMoveRight}

View File

@ -1,8 +1,9 @@
import { useCallback, useState } from 'react';
import { useCallback, useMemo, useState } from 'react';
import styled from '@emotion/styled';
import { useRecoilCallback, useRecoilState, useRecoilValue } from 'recoil';
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
import { ColumnHead } from '@/object-record/record-table/components/ColumnHead';
import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates';
import { useTableColumns } from '@/object-record/record-table/hooks/useTableColumns';
import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
@ -10,6 +11,7 @@ import { IconPlus } from '@/ui/display/icon';
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
import { useTrackPointer } from '@/ui/utilities/pointer-event/hooks/useTrackPointer';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { mapArrayToObject } from '~/utils/array/mapArrayToObject';
import { ColumnHeadWithDropdown } from './ColumnHeadWithDropdown';
@ -80,20 +82,19 @@ export const RecordTableHeaderCell = ({
column: ColumnDefinition<FieldMetadata>;
createRecord: () => void;
}) => {
const {
getResizeFieldOffsetState,
getTableColumnsState,
getTableColumnsByKeySelector,
getVisibleTableColumnsSelector,
} = useRecordTableStates();
const { getResizeFieldOffsetState, getTableColumnsState } =
useRecordTableStates();
const [resizeFieldOffset, setResizeFieldOffset] = useRecoilState(
getResizeFieldOffsetState(),
);
const tableColumns = useRecoilValue(getTableColumnsState());
const tableColumnsByKey = useRecoilValue(getTableColumnsByKeySelector());
const visibleTableColumns = useRecoilValue(getVisibleTableColumnsSelector());
const tableColumnsByKey = useMemo(
() =>
mapArrayToObject(tableColumns, ({ fieldMetadataId }) => fieldMetadataId),
[tableColumns],
);
const [initialPointerPositionX, setInitialPointerPositionX] = useState<
number | null
@ -108,10 +109,6 @@ export const RecordTableHeaderCell = ({
const [iconVisibility, setIconVisibility] = useState(false);
const primaryColumn = visibleTableColumns.find(
(column) => column.position === 0,
);
const handleResizeHandlerMove = useCallback(
(positionX: number) => {
if (!initialPointerPositionX) return;
@ -182,13 +179,12 @@ export const RecordTableHeaderCell = ({
onMouseEnter={() => setIconVisibility(true)}
onMouseLeave={() => setIconVisibility(false)}
>
<ColumnHeadWithDropdown
column={column}
isFirstColumn={column.position === 1}
isLastColumn={column.position === visibleTableColumns.length - 1}
primaryColumnKey={primaryColumn?.fieldMetadataId || ''}
/>
{iconVisibility && column.position === 0 && (
{column.isLabelIdentifier ? (
<ColumnHead column={column} />
) : (
<ColumnHeadWithDropdown column={column} />
)}
{iconVisibility && !!column.isLabelIdentifier && (
<StyledHeaderIcon>
<LightIconButton
Icon={IconPlus}

View File

@ -55,23 +55,21 @@ export const RecordTableRow = ({ recordId, rowIndex }: RecordTableRowProps) => {
<StyledTd>
<CheckboxCell />
</StyledTd>
{[...visibleTableColumns]
.sort((columnA, columnB) => columnA.position - columnB.position)
.map((column, columnIndex) => {
return inView ? (
<RecordTableCellContext.Provider
value={{
columnDefinition: column,
columnIndex,
}}
key={column.fieldMetadataId}
>
<RecordTableCellContainer />
</RecordTableCellContext.Provider>
) : (
<td key={column.fieldMetadataId}></td>
);
})}
{visibleTableColumns.map((column, columnIndex) =>
inView ? (
<RecordTableCellContext.Provider
value={{
columnDefinition: column,
columnIndex,
}}
key={column.fieldMetadataId}
>
<RecordTableCellContainer />
</RecordTableCellContext.Provider>
) : (
<td key={column.fieldMetadataId}></td>
),
)}
<td></td>
</tr>
</RecordTableRowContext.Provider>

View File

@ -14,7 +14,6 @@ import { allRowsSelectedStatusSelectorScopeMap } from '@/object-record/record-ta
import { hiddenTableColumnsSelectorScopeMap } from '@/object-record/record-table/states/selectors/hiddenTableColumnsSelectorScopeMap';
import { numberOfTableColumnsSelectorScopeMap } from '@/object-record/record-table/states/selectors/numberOfTableColumnsSelectorScopeMap';
import { selectedRowIdsSelectorScopeMap } from '@/object-record/record-table/states/selectors/selectedRowIdsSelectorScopeMap';
import { tableColumnsByKeySelectorScopeMap } from '@/object-record/record-table/states/selectors/tableColumnsByKeySelectorScopeMap';
import { visibleTableColumnsSelectorScopeMap } from '@/object-record/record-table/states/selectors/visibleTableColumnsSelectorScopeMap';
import { softFocusPositionStateScopeMap } from '@/object-record/record-table/states/softFocusPositionStateScopeMap';
import { tableColumnsStateScopeMap } from '@/object-record/record-table/states/tableColumnsStateScopeMap';
@ -106,10 +105,6 @@ export const useRecordTableStates = (recordTableId?: string) => {
selectedRowIdsSelectorScopeMap,
scopeId,
),
getTableColumnsByKeySelector: getSelectorReadOnly(
tableColumnsByKeySelectorScopeMap,
scopeId,
),
getVisibleTableColumnsSelector: getSelectorReadOnly(
visibleTableColumnsSelectorScopeMap,
scopeId,

View File

@ -1,7 +1,7 @@
import { availableTableColumnsStateScopeMap } from '@/object-record/record-table/states/availableTableColumnsStateScopeMap';
import { tableColumnsStateScopeMap } from '@/object-record/record-table/states/tableColumnsStateScopeMap';
import { createSelectorReadOnlyScopeMap } from '@/ui/utilities/recoil-scope/utils/createSelectorReadOnlyScopeMap';
import { availableTableColumnsStateScopeMap } from '../availableTableColumnsStateScopeMap';
import { tableColumnsStateScopeMap } from '../tableColumnsStateScopeMap';
import { mapArrayToObject } from '~/utils/array/mapArrayToObject';
export const hiddenTableColumnsSelectorScopeMap =
createSelectorReadOnlyScopeMap({
@ -9,19 +9,30 @@ export const hiddenTableColumnsSelectorScopeMap =
get:
({ scopeId }) =>
({ get }) => {
const columns = get(tableColumnsStateScopeMap({ scopeId }));
const columnKeys = columns.map(
const tableColumns = get(tableColumnsStateScopeMap({ scopeId }));
const availableColumns = get(
availableTableColumnsStateScopeMap({ scopeId }),
);
const tableColumnsByKey = mapArrayToObject(
tableColumns,
({ fieldMetadataId }) => fieldMetadataId,
);
const otherAvailableColumns = get(
availableTableColumnsStateScopeMap({ scopeId }),
).filter(
({ fieldMetadataId }) => !columnKeys.includes(fieldMetadataId),
);
return [
...columns.filter((column) => !column.isVisible),
...otherAvailableColumns,
];
const hiddenColumns = availableColumns
.filter(
({ fieldMetadataId }) =>
!tableColumnsByKey[fieldMetadataId]?.isVisible,
)
.map((availableColumn) => {
const { fieldMetadataId } = availableColumn;
const existingTableColumn = tableColumnsByKey[fieldMetadataId];
return {
...(existingTableColumn || availableColumn),
isVisible: false,
};
});
return hiddenColumns;
},
});

View File

@ -1,20 +0,0 @@
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
import { createSelectorReadOnlyScopeMap } from '@/ui/utilities/recoil-scope/utils/createSelectorReadOnlyScopeMap';
import { tableColumnsStateScopeMap } from '../tableColumnsStateScopeMap';
export const tableColumnsByKeySelectorScopeMap = createSelectorReadOnlyScopeMap(
{
key: 'tableColumnsByKeySelectorScopeMap',
get:
({ scopeId }) =>
({ get }) =>
get(tableColumnsStateScopeMap({ scopeId })).reduce<
Record<string, ColumnDefinition<FieldMetadata>>
>(
(result, column) => ({ ...result, [column.fieldMetadataId]: column }),
{},
),
},
);

View File

@ -1,8 +1,6 @@
import { availableTableColumnsStateScopeMap } from '@/object-record/record-table/states/availableTableColumnsStateScopeMap';
import { tableColumnsStateScopeMap } from '@/object-record/record-table/states/tableColumnsStateScopeMap';
import { createSelectorReadOnlyScopeMap } from '@/ui/utilities/recoil-scope/utils/createSelectorReadOnlyScopeMap';
import { tableColumnsStateScopeMap } from '../tableColumnsStateScopeMap';
export const visibleTableColumnsSelectorScopeMap =
createSelectorReadOnlyScopeMap({
key: 'visibleTableColumnsSelectorScopeMap',
@ -10,16 +8,8 @@ export const visibleTableColumnsSelectorScopeMap =
({ scopeId }) =>
({ get }) => {
const columns = get(tableColumnsStateScopeMap({ scopeId }));
const availableColumnKeys = get(
availableTableColumnsStateScopeMap({ scopeId }),
).map(({ fieldMetadataId }) => fieldMetadataId);
return [...columns]
.filter(
(column) =>
column.isVisible &&
availableColumnKeys.includes(column.fieldMetadataId),
)
.sort((a, b) => a.position - b.position);
return columns
.filter((column) => column.isVisible)
.sort((columnA, columnB) => columnA.position - columnB.position);
},
});

View File

@ -4,6 +4,7 @@ import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'
export type ColumnDefinition<T extends FieldMetadata> = FieldDefinition<T> & {
size: number;
position: number;
isLabelIdentifier?: boolean;
isVisible?: boolean;
viewFieldId?: string;
};