feat: record board component state refactor (#8779)
Fix #8758 This PR is migrating the recoil component state from v1 to v2 for board. It also now share some states and logics between board and table, further can be done later. Lastly this PR fix an issue since the PR #8613 that was treating no-value as a normal record-group.
This commit is contained in:
@ -10,46 +10,50 @@ import { useObjectNamePluralFromSingular } from '@/object-metadata/hooks/useObje
|
||||
|
||||
import { useOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useOptionsDropdown';
|
||||
import { RecordGroupsVisibilityDropdownSection } from '@/object-record/record-group/components/RecordGroupsVisibilityDropdownSection';
|
||||
import { useRecordGroups } from '@/object-record/record-group/hooks/useRecordGroups';
|
||||
import { useRecordGroupVisibility } from '@/object-record/record-group/hooks/useRecordGroupVisibility';
|
||||
import { recordGroupFieldMetadataComponentState } from '@/object-record/record-group/states/recordGroupFieldMetadataComponentState';
|
||||
import { hiddenRecordGroupIdsComponentSelector } from '@/object-record/record-group/states/selectors/hiddenRecordGroupIdsComponentSelector';
|
||||
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
|
||||
import { SettingsPath } from '@/types/SettingsPath';
|
||||
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
||||
import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMemorizedUrlState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
|
||||
export const ObjectOptionsDropdownHiddenRecordGroupsContent = () => {
|
||||
const {
|
||||
currentContentId,
|
||||
viewType,
|
||||
recordIndexId,
|
||||
objectMetadataItem,
|
||||
onContentChange,
|
||||
closeDropdown,
|
||||
} = useOptionsDropdown();
|
||||
|
||||
const { objectNamePlural } = useObjectNamePluralFromSingular({
|
||||
objectNameSingular: objectMetadataItem.nameSingular,
|
||||
});
|
||||
const recordGroupFieldMetadata = useRecoilComponentValueV2(
|
||||
recordGroupFieldMetadataComponentState,
|
||||
);
|
||||
|
||||
const { hiddenRecordGroups, viewGroupFieldMetadataItem } = useRecordGroups({
|
||||
const hiddenRecordGroupIds = useRecoilComponentValueV2(
|
||||
hiddenRecordGroupIdsComponentSelector,
|
||||
);
|
||||
|
||||
const { objectNamePlural } = useObjectNamePluralFromSingular({
|
||||
objectNameSingular: objectMetadataItem.nameSingular,
|
||||
});
|
||||
|
||||
const { handleVisibilityChange: handleRecordGroupVisibilityChange } =
|
||||
useRecordGroupVisibility({
|
||||
viewBarId: recordIndexId,
|
||||
viewType,
|
||||
});
|
||||
|
||||
const viewGroupSettingsUrl = getSettingsPagePath(
|
||||
SettingsPath.ObjectFieldEdit,
|
||||
{
|
||||
objectSlug: objectNamePlural,
|
||||
fieldSlug: viewGroupFieldMetadataItem?.name ?? '',
|
||||
fieldSlug: recordGroupFieldMetadata?.name ?? '',
|
||||
},
|
||||
);
|
||||
|
||||
@ -61,11 +65,11 @@ export const ObjectOptionsDropdownHiddenRecordGroupsContent = () => {
|
||||
useEffect(() => {
|
||||
if (
|
||||
currentContentId === 'hiddenRecordGroups' &&
|
||||
hiddenRecordGroups.length === 0
|
||||
hiddenRecordGroupIds.length === 0
|
||||
) {
|
||||
onContentChange('recordGroups');
|
||||
}
|
||||
}, [hiddenRecordGroups, currentContentId, onContentChange]);
|
||||
}, [hiddenRecordGroupIds, currentContentId, onContentChange]);
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -74,13 +78,13 @@ export const ObjectOptionsDropdownHiddenRecordGroupsContent = () => {
|
||||
StartIcon={IconChevronLeft}
|
||||
onClick={() => onContentChange('recordGroups')}
|
||||
>
|
||||
Hidden {viewGroupFieldMetadataItem?.label}
|
||||
Hidden {recordGroupFieldMetadata?.label}
|
||||
</DropdownMenuHeader>
|
||||
</DropdownMenuItemsContainer>
|
||||
|
||||
<RecordGroupsVisibilityDropdownSection
|
||||
title={`Hidden ${viewGroupFieldMetadataItem?.label}`}
|
||||
recordGroups={hiddenRecordGroups}
|
||||
title={`Hidden ${recordGroupFieldMetadata?.label}`}
|
||||
recordGroupIds={hiddenRecordGroupIds}
|
||||
onVisibilityChange={handleRecordGroupVisibilityChange}
|
||||
isDraggable={false}
|
||||
showSubheader={false}
|
||||
|
||||
@ -15,7 +15,7 @@ import { useHandleToggleTrashColumnFilter } from '@/object-record/record-index/h
|
||||
|
||||
import { useObjectOptionsForBoard } from '@/object-record/object-options-dropdown/hooks/useObjectOptionsForBoard';
|
||||
import { useOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useOptionsDropdown';
|
||||
import { useRecordGroups } from '@/object-record/record-group/hooks/useRecordGroups';
|
||||
import { recordGroupFieldMetadataComponentState } from '@/object-record/record-group/states/recordGroupFieldMetadataComponentState';
|
||||
import {
|
||||
displayedExportProgress,
|
||||
useExportRecords,
|
||||
@ -26,6 +26,7 @@ import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenu
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { ViewType } from '@/views/types/ViewType';
|
||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
||||
|
||||
@ -44,6 +45,10 @@ export const ObjectOptionsDropdownMenuContent = () => {
|
||||
objectNameSingular: objectMetadataItem.nameSingular,
|
||||
});
|
||||
|
||||
const recordGroupFieldMetadata = useRecoilComponentValueV2(
|
||||
recordGroupFieldMetadataComponentState,
|
||||
);
|
||||
|
||||
useScopedHotkeys(
|
||||
[Key.Escape],
|
||||
() => {
|
||||
@ -64,10 +69,6 @@ export const ObjectOptionsDropdownMenuContent = () => {
|
||||
viewBarId: recordIndexId,
|
||||
});
|
||||
|
||||
const { viewGroupFieldMetadataItem } = useRecordGroups({
|
||||
objectNameSingular: objectMetadataItem.nameSingular,
|
||||
});
|
||||
|
||||
const { openObjectRecordsSpreasheetImportDialog } =
|
||||
useOpenObjectRecordsSpreadsheetImportDialog(
|
||||
objectMetadataItem.nameSingular,
|
||||
@ -113,7 +114,7 @@ export const ObjectOptionsDropdownMenuContent = () => {
|
||||
onClick={() => onContentChange('recordGroups')}
|
||||
LeftIcon={IconLayoutList}
|
||||
text="Group by"
|
||||
contextualText={viewGroupFieldMetadataItem?.label}
|
||||
contextualText={recordGroupFieldMetadata?.label}
|
||||
hasSubMenu
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -12,7 +12,7 @@ import { useObjectNamePluralFromSingular } from '@/object-metadata/hooks/useObje
|
||||
import { StyledInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect';
|
||||
import { useOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useOptionsDropdown';
|
||||
import { useSearchRecordGroupField } from '@/object-record/object-options-dropdown/hooks/useSearchRecordGroupField';
|
||||
import { useRecordGroups } from '@/object-record/record-group/hooks/useRecordGroups';
|
||||
import { hiddenRecordGroupIdsComponentSelector } from '@/object-record/record-group/states/selectors/hiddenRecordGroupIdsComponentSelector';
|
||||
import { useHandleRecordGroupField } from '@/object-record/record-index/hooks/useHandleRecordGroupField';
|
||||
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
|
||||
import { SettingsPath } from '@/types/SettingsPath';
|
||||
@ -20,6 +20,7 @@ import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenu
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
||||
import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMemorizedUrlState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
|
||||
@ -38,9 +39,9 @@ export const ObjectOptionsDropdownRecordGroupFieldsContent = () => {
|
||||
objectNameSingular: objectMetadataItem.nameSingular,
|
||||
});
|
||||
|
||||
const { hiddenRecordGroups } = useRecordGroups({
|
||||
objectNameSingular: objectMetadataItem.nameSingular,
|
||||
});
|
||||
const hiddenRecordGroupIds = useRecoilComponentValueV2(
|
||||
hiddenRecordGroupIdsComponentSelector,
|
||||
);
|
||||
|
||||
const {
|
||||
recordGroupFieldSearchInput,
|
||||
@ -68,11 +69,11 @@ export const ObjectOptionsDropdownRecordGroupFieldsContent = () => {
|
||||
useEffect(() => {
|
||||
if (
|
||||
currentContentId === 'hiddenRecordGroups' &&
|
||||
hiddenRecordGroups.length === 0
|
||||
hiddenRecordGroupIds.length === 0
|
||||
) {
|
||||
onContentChange('recordGroups');
|
||||
}
|
||||
}, [hiddenRecordGroups, currentContentId, onContentChange]);
|
||||
}, [hiddenRecordGroupIds, currentContentId, onContentChange]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@ -8,24 +8,21 @@ import {
|
||||
} from 'twenty-ui';
|
||||
|
||||
import { useOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useOptionsDropdown';
|
||||
import { useRecordGroups } from '@/object-record/record-group/hooks/useRecordGroups';
|
||||
import { hiddenRecordGroupIdsComponentSelector } from '@/object-record/record-group/states/selectors/hiddenRecordGroupIdsComponentSelector';
|
||||
import { RecordGroupSort } from '@/object-record/record-group/types/RecordGroupSort';
|
||||
import { recordIndexRecordGroupSortComponentState } from '@/object-record/record-index/states/recordIndexRecordGroupSortComponentState';
|
||||
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
|
||||
export const ObjectOptionsDropdownRecordGroupSortContent = () => {
|
||||
const {
|
||||
currentContentId,
|
||||
objectMetadataItem,
|
||||
onContentChange,
|
||||
closeDropdown,
|
||||
} = useOptionsDropdown();
|
||||
const { currentContentId, onContentChange, closeDropdown } =
|
||||
useOptionsDropdown();
|
||||
|
||||
const { hiddenRecordGroups } = useRecordGroups({
|
||||
objectNameSingular: objectMetadataItem.nameSingular,
|
||||
});
|
||||
const hiddenRecordGroupIds = useRecoilComponentValueV2(
|
||||
hiddenRecordGroupIdsComponentSelector,
|
||||
);
|
||||
|
||||
const setRecordGroupSort = useSetRecoilComponentStateV2(
|
||||
recordIndexRecordGroupSortComponentState,
|
||||
@ -39,11 +36,11 @@ export const ObjectOptionsDropdownRecordGroupSortContent = () => {
|
||||
useEffect(() => {
|
||||
if (
|
||||
currentContentId === 'hiddenRecordGroups' &&
|
||||
hiddenRecordGroups.length === 0
|
||||
hiddenRecordGroupIds.length === 0
|
||||
) {
|
||||
onContentChange('recordGroups');
|
||||
}
|
||||
}, [hiddenRecordGroups, currentContentId, onContentChange]);
|
||||
}, [hiddenRecordGroupIds, currentContentId, onContentChange]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@ -13,8 +13,10 @@ import {
|
||||
import { useOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useOptionsDropdown';
|
||||
import { RecordGroupsVisibilityDropdownSection } from '@/object-record/record-group/components/RecordGroupsVisibilityDropdownSection';
|
||||
import { useRecordGroupReorder } from '@/object-record/record-group/hooks/useRecordGroupReorder';
|
||||
import { useRecordGroups } from '@/object-record/record-group/hooks/useRecordGroups';
|
||||
import { useRecordGroupVisibility } from '@/object-record/record-group/hooks/useRecordGroupVisibility';
|
||||
import { recordGroupFieldMetadataComponentState } from '@/object-record/record-group/states/recordGroupFieldMetadataComponentState';
|
||||
import { hiddenRecordGroupIdsComponentSelector } from '@/object-record/record-group/states/selectors/hiddenRecordGroupIdsComponentSelector';
|
||||
import { visibleRecordGroupIdsComponentSelector } from '@/object-record/record-group/states/selectors/visibleRecordGroupIdsComponentSelector';
|
||||
import { recordIndexRecordGroupHideComponentState } from '@/object-record/record-index/states/recordIndexRecordGroupHideComponentState';
|
||||
import { recordIndexRecordGroupIsDraggableSortComponentSelector } from '@/object-record/record-index/states/selectors/recordIndexRecordGroupIsDraggableSortComponentSelector';
|
||||
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader';
|
||||
@ -26,22 +28,20 @@ import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
||||
export const ObjectOptionsDropdownRecordGroupsContent = () => {
|
||||
const isViewGroupEnabled = useIsFeatureEnabled('IS_VIEW_GROUPS_ENABLED');
|
||||
|
||||
const {
|
||||
currentContentId,
|
||||
viewType,
|
||||
recordIndexId,
|
||||
objectMetadataItem,
|
||||
onContentChange,
|
||||
resetContent,
|
||||
} = useOptionsDropdown();
|
||||
const { currentContentId, recordIndexId, onContentChange, resetContent } =
|
||||
useOptionsDropdown();
|
||||
|
||||
const {
|
||||
hiddenRecordGroups,
|
||||
visibleRecordGroups,
|
||||
viewGroupFieldMetadataItem,
|
||||
} = useRecordGroups({
|
||||
objectNameSingular: objectMetadataItem.nameSingular,
|
||||
});
|
||||
const recordGroupFieldMetadata = useRecoilComponentValueV2(
|
||||
recordGroupFieldMetadataComponentState,
|
||||
);
|
||||
|
||||
const visibleRecordGroupIds = useRecoilComponentValueV2(
|
||||
visibleRecordGroupIdsComponentSelector,
|
||||
);
|
||||
|
||||
const hiddenRecordGroupIds = useRecoilComponentValueV2(
|
||||
hiddenRecordGroupIdsComponentSelector,
|
||||
);
|
||||
|
||||
const isDragableSortRecordGroup = useRecoilComponentValueV2(
|
||||
recordIndexRecordGroupIsDraggableSortComponentSelector,
|
||||
@ -56,23 +56,21 @@ export const ObjectOptionsDropdownRecordGroupsContent = () => {
|
||||
handleHideEmptyRecordGroupChange,
|
||||
} = useRecordGroupVisibility({
|
||||
viewBarId: recordIndexId,
|
||||
viewType,
|
||||
});
|
||||
|
||||
const { handleOrderChange: handleRecordGroupOrderChange } =
|
||||
useRecordGroupReorder({
|
||||
objectNameSingular: objectMetadataItem.nameSingular,
|
||||
viewBarId: recordIndexId,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
currentContentId === 'hiddenRecordGroups' &&
|
||||
hiddenRecordGroups.length === 0
|
||||
hiddenRecordGroupIds.length === 0
|
||||
) {
|
||||
onContentChange('recordGroups');
|
||||
}
|
||||
}, [hiddenRecordGroups, currentContentId, onContentChange]);
|
||||
}, [hiddenRecordGroupIds, currentContentId, onContentChange]);
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -86,9 +84,9 @@ export const ObjectOptionsDropdownRecordGroupsContent = () => {
|
||||
onClick={() => onContentChange('recordGroupFields')}
|
||||
LeftIcon={IconLayoutList}
|
||||
text={
|
||||
!viewGroupFieldMetadataItem
|
||||
!recordGroupFieldMetadata
|
||||
? 'Group by'
|
||||
: `Group by "${viewGroupFieldMetadataItem.label}"`
|
||||
: `Group by "${recordGroupFieldMetadata.label}"`
|
||||
}
|
||||
hasSubMenu
|
||||
/>
|
||||
@ -108,12 +106,12 @@ export const ObjectOptionsDropdownRecordGroupsContent = () => {
|
||||
toggleSize="small"
|
||||
/>
|
||||
</DropdownMenuItemsContainer>
|
||||
{visibleRecordGroups.length > 0 && (
|
||||
{visibleRecordGroupIds.length > 0 && (
|
||||
<>
|
||||
<DropdownMenuSeparator />
|
||||
<RecordGroupsVisibilityDropdownSection
|
||||
title="Visible groups"
|
||||
recordGroups={visibleRecordGroups}
|
||||
recordGroupIds={visibleRecordGroupIds}
|
||||
onDragEnd={handleRecordGroupOrderChange}
|
||||
onVisibilityChange={handleRecordGroupVisibilityChange}
|
||||
isDraggable={isDragableSortRecordGroup}
|
||||
@ -121,14 +119,14 @@ export const ObjectOptionsDropdownRecordGroupsContent = () => {
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{hiddenRecordGroups.length > 0 && (
|
||||
{hiddenRecordGroupIds.length > 0 && (
|
||||
<>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItemsContainer>
|
||||
<MenuItemNavigate
|
||||
onClick={() => onContentChange('hiddenRecordGroups')}
|
||||
LeftIcon={IconEyeOff}
|
||||
text={`Hidden ${viewGroupFieldMetadataItem?.label ?? ''}`}
|
||||
text={`Hidden ${recordGroupFieldMetadata?.label ?? ''}`}
|
||||
/>
|
||||
</DropdownMenuItemsContainer>
|
||||
</>
|
||||
|
||||
@ -4,10 +4,11 @@ import { useRecoilState } from 'recoil';
|
||||
|
||||
import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata';
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { useRecordBoard } from '@/object-record/record-board/hooks/useRecordBoard';
|
||||
import { isRecordBoardCompactModeActiveComponentState } from '@/object-record/record-board/states/isRecordBoardCompactModeActiveComponentState';
|
||||
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 { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
|
||||
import { useSaveCurrentViewFields } from '@/views/hooks/useSaveCurrentViewFields';
|
||||
import { useUpdateCurrentView } from '@/views/hooks/useUpdateCurrentView';
|
||||
import { GraphQLView } from '@/views/types/GraphQLView';
|
||||
@ -32,11 +33,12 @@ export const useObjectOptionsForBoard = ({
|
||||
|
||||
const { saveViewFields } = useSaveCurrentViewFields(viewBarId);
|
||||
const { updateCurrentView } = useUpdateCurrentView(viewBarId);
|
||||
const { isCompactModeActiveState } = useRecordBoard(recordBoardId);
|
||||
|
||||
const [isCompactModeActive, setIsCompactModeActive] = useRecoilState(
|
||||
isCompactModeActiveState,
|
||||
);
|
||||
const [isCompactModeActive, setIsCompactModeActive] =
|
||||
useRecoilComponentStateV2(
|
||||
isRecordBoardCompactModeActiveComponentState,
|
||||
recordBoardId,
|
||||
);
|
||||
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
objectNameSingular,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
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 { useContext, useRef } from 'react';
|
||||
import { useRecoilCallback, useRecoilValue } from 'recoil';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { Key } from 'ts-key-enum';
|
||||
|
||||
import { ActionBarHotkeyScope } from '@/action-menu/types/ActionBarHotKeyScope';
|
||||
@ -9,11 +9,15 @@ import { RecordBoardHeader } from '@/object-record/record-board/components/Recor
|
||||
import { RecordBoardStickyHeaderEffect } from '@/object-record/record-board/components/RecordBoardStickyHeaderEffect';
|
||||
import { RECORD_BOARD_CLICK_OUTSIDE_LISTENER_ID } from '@/object-record/record-board/constants/RecordBoardClickOutsideListenerId';
|
||||
import { RecordBoardContext } from '@/object-record/record-board/contexts/RecordBoardContext';
|
||||
import { useRecordBoardStates } from '@/object-record/record-board/hooks/internal/useRecordBoardStates';
|
||||
import { useRecordBoardSelection } from '@/object-record/record-board/hooks/useRecordBoardSelection';
|
||||
import { RecordBoardColumn } from '@/object-record/record-board/record-board-column/components/RecordBoardColumn';
|
||||
import { RecordBoardScope } from '@/object-record/record-board/scopes/RecordBoardScope';
|
||||
import { RecordBoardComponentInstanceContext } from '@/object-record/record-board/states/contexts/RecordBoardComponentInstanceContext';
|
||||
import { getDraggedRecordPosition } from '@/object-record/record-board/utils/getDraggedRecordPosition';
|
||||
import { recordGroupDefinitionFamilyState } from '@/object-record/record-group/states/recordGroupDefinitionFamilyState';
|
||||
import { visibleRecordGroupIdsComponentSelector } from '@/object-record/record-group/states/selectors/visibleRecordGroupIdsComponentSelector';
|
||||
import { recordIndexAllRowIdsComponentState } from '@/object-record/record-index/states/recordIndexAllRowIdsComponentState';
|
||||
import { recordIndexRowIdsByGroupComponentFamilyState } from '@/object-record/record-index/states/recordIndexRowIdsByGroupComponentFamilyState';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { TableHotkeyScope } from '@/object-record/record-table/types/TableHotkeyScope';
|
||||
import { DragSelect } from '@/ui/utilities/drag-select/components/DragSelect';
|
||||
@ -21,6 +25,9 @@ import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||
import { useListenClickOutsideV2 } from '@/ui/utilities/pointer-event/hooks/useListenClickOutsideV2';
|
||||
import { getScopeIdFromComponentId } from '@/ui/utilities/recoil-scope/utils/getScopeIdFromComponentId';
|
||||
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue';
|
||||
import { useScrollRestoration } from '~/hooks/useScrollRestoration';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
@ -58,14 +65,17 @@ export const RecordBoard = () => {
|
||||
useContext(RecordBoardContext);
|
||||
const boardRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const {
|
||||
columnIdsState,
|
||||
columnsFamilySelector,
|
||||
recordIdsByColumnIdFamilyState,
|
||||
allRecordIdsSelector,
|
||||
} = useRecordBoardStates(recordBoardId);
|
||||
const visibleRecordGroupIds = useRecoilComponentValueV2(
|
||||
visibleRecordGroupIdsComponentSelector,
|
||||
);
|
||||
|
||||
const columnIds = useRecoilValue(columnIdsState);
|
||||
const recordIndexRowIdsByGroupFamilyState = useRecoilComponentCallbackStateV2(
|
||||
recordIndexRowIdsByGroupComponentFamilyState,
|
||||
);
|
||||
|
||||
const recordIndexAllRowIdsState = useRecoilComponentCallbackStateV2(
|
||||
recordIndexAllRowIdsComponentState,
|
||||
);
|
||||
|
||||
const { resetRecordSelection, setRecordAsSelected } =
|
||||
useRecordBoardSelection(recordBoardId);
|
||||
@ -85,15 +95,16 @@ export const RecordBoard = () => {
|
||||
const selectAll = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
() => {
|
||||
const allRecordIds = snapshot
|
||||
.getLoadable(allRecordIdsSelector())
|
||||
.getValue();
|
||||
const allRecordIds = getSnapshotValue(
|
||||
snapshot,
|
||||
recordIndexAllRowIdsState,
|
||||
);
|
||||
|
||||
for (const recordId of allRecordIds) {
|
||||
setRecordAsSelected(recordId, true);
|
||||
}
|
||||
},
|
||||
[allRecordIdsSelector, setRecordAsSelected],
|
||||
[recordIndexAllRowIdsState, setRecordAsSelected],
|
||||
);
|
||||
|
||||
useScopedHotkeys('ctrl+a,meta+a', selectAll, TableHotkeyScope.Table);
|
||||
@ -111,42 +122,40 @@ export const RecordBoard = () => {
|
||||
if (!result.destination) return;
|
||||
|
||||
const draggedRecordId = result.draggableId;
|
||||
const sourceColumnId = result.source.droppableId;
|
||||
const destinationColumnId = result.destination.droppableId;
|
||||
const sourceRecordGroupId = result.source.droppableId;
|
||||
const destinationRecordGroupId = result.destination.droppableId;
|
||||
const destinationIndexInColumn = result.destination.index;
|
||||
|
||||
if (!destinationColumnId || !selectFieldMetadataItem) return;
|
||||
if (!destinationRecordGroupId || !selectFieldMetadataItem) return;
|
||||
|
||||
const column = snapshot
|
||||
.getLoadable(columnsFamilySelector(destinationColumnId))
|
||||
.getValue();
|
||||
const recordGroup = getSnapshotValue(
|
||||
snapshot,
|
||||
recordGroupDefinitionFamilyState(destinationRecordGroupId),
|
||||
);
|
||||
|
||||
if (!column) return;
|
||||
if (!recordGroup) return;
|
||||
|
||||
const destinationColumnRecordIds = snapshot
|
||||
.getLoadable(recordIdsByColumnIdFamilyState(destinationColumnId))
|
||||
.getValue();
|
||||
const otherRecordsInDestinationColumn =
|
||||
sourceColumnId === destinationColumnId
|
||||
? destinationColumnRecordIds.filter(
|
||||
const destinationRecordByGroupIds = getSnapshotValue(
|
||||
snapshot,
|
||||
recordIndexRowIdsByGroupFamilyState(destinationRecordGroupId),
|
||||
);
|
||||
const otherRecordIdsInDestinationColumn =
|
||||
sourceRecordGroupId === destinationRecordGroupId
|
||||
? destinationRecordByGroupIds.filter(
|
||||
(recordId) => recordId !== draggedRecordId,
|
||||
)
|
||||
: destinationColumnRecordIds;
|
||||
: destinationRecordByGroupIds;
|
||||
|
||||
const recordBeforeId =
|
||||
otherRecordsInDestinationColumn[destinationIndexInColumn - 1];
|
||||
otherRecordIdsInDestinationColumn[destinationIndexInColumn - 1];
|
||||
const recordBefore = recordBeforeId
|
||||
? snapshot
|
||||
.getLoadable(recordStoreFamilyState(recordBeforeId))
|
||||
.getValue()
|
||||
? getSnapshotValue(snapshot, recordStoreFamilyState(recordBeforeId))
|
||||
: null;
|
||||
|
||||
const recordAfterId =
|
||||
otherRecordsInDestinationColumn[destinationIndexInColumn];
|
||||
otherRecordIdsInDestinationColumn[destinationIndexInColumn];
|
||||
const recordAfter = recordAfterId
|
||||
? snapshot
|
||||
.getLoadable(recordStoreFamilyState(recordAfterId))
|
||||
.getValue()
|
||||
? getSnapshotValue(snapshot, recordStoreFamilyState(recordAfterId))
|
||||
: null;
|
||||
|
||||
const draggedRecordPosition = getDraggedRecordPosition(
|
||||
@ -157,14 +166,13 @@ export const RecordBoard = () => {
|
||||
updateOneRecord({
|
||||
idToUpdate: draggedRecordId,
|
||||
updateOneRecordInput: {
|
||||
[selectFieldMetadataItem.name]: column.value,
|
||||
[selectFieldMetadataItem.name]: recordGroup.value,
|
||||
position: draggedRecordPosition,
|
||||
},
|
||||
});
|
||||
},
|
||||
[
|
||||
columnsFamilySelector,
|
||||
recordIdsByColumnIdFamilyState,
|
||||
recordIndexRowIdsByGroupFamilyState,
|
||||
selectFieldMetadataItem,
|
||||
updateOneRecord,
|
||||
],
|
||||
@ -182,32 +190,36 @@ export const RecordBoard = () => {
|
||||
onColumnsChange={() => {}}
|
||||
onFieldsChange={() => {}}
|
||||
>
|
||||
<ScrollWrapper contextProviderName="recordBoard">
|
||||
<RecordBoardStickyHeaderEffect />
|
||||
<StyledContainerContainer>
|
||||
<RecordBoardHeader />
|
||||
<StyledBoardContentContainer>
|
||||
<StyledContainer ref={boardRef}>
|
||||
<DragDropContext onDragEnd={handleDragEnd}>
|
||||
<StyledColumnContainer>
|
||||
{columnIds.map((columnId) => (
|
||||
<RecordBoardColumn
|
||||
key={columnId}
|
||||
recordBoardColumnId={columnId}
|
||||
/>
|
||||
))}
|
||||
</StyledColumnContainer>
|
||||
</DragDropContext>
|
||||
</StyledContainer>
|
||||
<RecordBoardScrollRestoreEffect />
|
||||
<DragSelect
|
||||
dragSelectable={boardRef}
|
||||
onDragSelectionStart={resetRecordSelection}
|
||||
onDragSelectionChange={setRecordAsSelected}
|
||||
/>
|
||||
</StyledBoardContentContainer>
|
||||
</StyledContainerContainer>
|
||||
</ScrollWrapper>
|
||||
<RecordBoardComponentInstanceContext.Provider
|
||||
value={{ instanceId: recordBoardId }}
|
||||
>
|
||||
<ScrollWrapper contextProviderName="recordBoard">
|
||||
<RecordBoardStickyHeaderEffect />
|
||||
<StyledContainerContainer>
|
||||
<RecordBoardHeader />
|
||||
<StyledBoardContentContainer>
|
||||
<StyledContainer ref={boardRef}>
|
||||
<DragDropContext onDragEnd={handleDragEnd}>
|
||||
<StyledColumnContainer>
|
||||
{visibleRecordGroupIds.map((recordGroupId) => (
|
||||
<RecordBoardColumn
|
||||
key={recordGroupId}
|
||||
recordBoardColumnId={recordGroupId}
|
||||
/>
|
||||
))}
|
||||
</StyledColumnContainer>
|
||||
</DragDropContext>
|
||||
</StyledContainer>
|
||||
<RecordBoardScrollRestoreEffect />
|
||||
<DragSelect
|
||||
dragSelectable={boardRef}
|
||||
onDragSelectionStart={resetRecordSelection}
|
||||
onDragSelectionChange={setRecordAsSelected}
|
||||
/>
|
||||
</StyledBoardContentContainer>
|
||||
</StyledContainerContainer>
|
||||
</ScrollWrapper>
|
||||
</RecordBoardComponentInstanceContext.Provider>
|
||||
</RecordBoardScope>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { useRecordBoardStates } from '@/object-record/record-board/hooks/internal/useRecordBoardStates';
|
||||
import { RecordBoardColumnHeaderWrapper } from '@/object-record/record-board/record-board-column/components/RecordBoardColumnHeaderWrapper';
|
||||
import { visibleRecordGroupIdsComponentSelector } from '@/object-record/record-group/states/selectors/visibleRecordGroupIdsComponentSelector';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
const StyledHeaderContainer = styled.div`
|
||||
@ -24,14 +23,17 @@ const StyledHeaderContainer = styled.div`
|
||||
`;
|
||||
|
||||
export const RecordBoardHeader = () => {
|
||||
const { columnIdsState } = useRecordBoardStates();
|
||||
|
||||
const columnIds = useRecoilValue(columnIdsState);
|
||||
const visibleRecordGroupIds = useRecoilComponentValueV2(
|
||||
visibleRecordGroupIdsComponentSelector,
|
||||
);
|
||||
|
||||
return (
|
||||
<StyledHeaderContainer id="record-board-header">
|
||||
{columnIds.map((columnId) => (
|
||||
<RecordBoardColumnHeaderWrapper columnId={columnId} key={columnId} />
|
||||
{visibleRecordGroupIds.map((recordGroupId) => (
|
||||
<RecordBoardColumnHeaderWrapper
|
||||
columnId={recordGroupId}
|
||||
key={recordGroupId}
|
||||
/>
|
||||
))}
|
||||
</StyledHeaderContainer>
|
||||
);
|
||||
|
||||
@ -1,103 +0,0 @@
|
||||
import { RecordBoardScopeInternalContext } from '@/object-record/record-board/scopes/scope-internal-context/RecordBoardScopeInternalContext';
|
||||
import { isRecordBoardCardSelectedComponentFamilyState } from '@/object-record/record-board/states/isRecordBoardCardSelectedComponentFamilyState';
|
||||
import { isRecordBoardCompactModeActiveComponentState } from '@/object-record/record-board/states/isRecordBoardCompactModeActiveComponentState';
|
||||
import { isRecordBoardFetchingRecordsByColumnFamilyState } from '@/object-record/record-board/states/isRecordBoardFetchingRecordsByColumnFamilyState';
|
||||
import { isRecordBoardFetchingRecordsComponentState } from '@/object-record/record-board/states/isRecordBoardFetchingRecordsComponentState';
|
||||
import { recordBoardColumnIdsComponentState } from '@/object-record/record-board/states/recordBoardColumnIdsComponentState';
|
||||
import { recordBoardFieldDefinitionsComponentState } from '@/object-record/record-board/states/recordBoardFieldDefinitionsComponentState';
|
||||
import { recordBoardFiltersComponentState } from '@/object-record/record-board/states/recordBoardFiltersComponentState';
|
||||
import { recordBoardKanbanFieldMetadataNameComponentState } from '@/object-record/record-board/states/recordBoardKanbanFieldMetadataNameComponentState';
|
||||
import { recordBoardObjectSingularNameComponentState } from '@/object-record/record-board/states/recordBoardObjectSingularNameComponentState';
|
||||
import { recordBoardRecordIdsByColumnIdComponentFamilyState } from '@/object-record/record-board/states/recordBoardRecordIdsByColumnIdComponentFamilyState';
|
||||
import { recordBoardShouldFetchMoreInColumnComponentFamilyState } from '@/object-record/record-board/states/recordBoardShouldFetchMoreInColumnComponentFamilyState';
|
||||
import { recordBoardSortsComponentState } from '@/object-record/record-board/states/recordBoardSortsComponentState';
|
||||
import { recordBoardAllRecordIdsComponentSelector } from '@/object-record/record-board/states/selectors/recordBoardAllRecordIdsComponentSelector';
|
||||
import { recordBoardColumnsComponentFamilySelector } from '@/object-record/record-board/states/selectors/recordBoardColumnsComponentFamilySelector';
|
||||
import { recordBoardSelectedRecordIdsComponentSelector } from '@/object-record/record-board/states/selectors/recordBoardSelectedRecordIdsComponentSelector';
|
||||
import { recordBoardShouldFetchMoreComponentSelector } from '@/object-record/record-board/states/selectors/recordBoardShouldFetchMoreComponentFamilySelector';
|
||||
import { recordBoardVisibleFieldDefinitionsComponentSelector } from '@/object-record/record-board/states/selectors/recordBoardVisibleFieldDefinitionsComponentSelector';
|
||||
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
|
||||
import { getScopeIdOrUndefinedFromComponentId } from '@/ui/utilities/recoil-scope/utils/getScopeIdOrUndefinedFromComponentId';
|
||||
import { extractComponentFamilyState } from '@/ui/utilities/state/component-state/utils/extractComponentFamilyState';
|
||||
import { extractComponentReadOnlySelector } from '@/ui/utilities/state/component-state/utils/extractComponentReadOnlySelector';
|
||||
import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState';
|
||||
|
||||
export const useRecordBoardStates = (recordBoardId?: string) => {
|
||||
const scopeId = useAvailableScopeIdOrThrow(
|
||||
RecordBoardScopeInternalContext,
|
||||
getScopeIdOrUndefinedFromComponentId(recordBoardId),
|
||||
);
|
||||
|
||||
return {
|
||||
scopeId,
|
||||
objectSingularNameState: extractComponentState(
|
||||
recordBoardObjectSingularNameComponentState,
|
||||
scopeId,
|
||||
),
|
||||
kanbanFieldMetadataNameState: extractComponentState(
|
||||
recordBoardKanbanFieldMetadataNameComponentState,
|
||||
scopeId,
|
||||
),
|
||||
isFetchingRecordState: extractComponentState(
|
||||
isRecordBoardFetchingRecordsComponentState,
|
||||
scopeId,
|
||||
),
|
||||
isFetchingRecordsByColumnState: extractComponentFamilyState(
|
||||
isRecordBoardFetchingRecordsByColumnFamilyState,
|
||||
scopeId,
|
||||
),
|
||||
columnIdsState: extractComponentState(
|
||||
recordBoardColumnIdsComponentState,
|
||||
scopeId,
|
||||
),
|
||||
columnsFamilySelector: extractComponentFamilyState(
|
||||
recordBoardColumnsComponentFamilySelector,
|
||||
scopeId,
|
||||
),
|
||||
|
||||
filtersState: extractComponentState(
|
||||
recordBoardFiltersComponentState,
|
||||
scopeId,
|
||||
),
|
||||
sortsState: extractComponentState(recordBoardSortsComponentState, scopeId),
|
||||
fieldDefinitionsState: extractComponentState(
|
||||
recordBoardFieldDefinitionsComponentState,
|
||||
scopeId,
|
||||
),
|
||||
visibleFieldDefinitionsState: extractComponentReadOnlySelector(
|
||||
recordBoardVisibleFieldDefinitionsComponentSelector,
|
||||
scopeId,
|
||||
),
|
||||
|
||||
recordIdsByColumnIdFamilyState: extractComponentFamilyState(
|
||||
recordBoardRecordIdsByColumnIdComponentFamilyState,
|
||||
scopeId,
|
||||
),
|
||||
isRecordBoardCardSelectedFamilyState: extractComponentFamilyState(
|
||||
isRecordBoardCardSelectedComponentFamilyState,
|
||||
scopeId,
|
||||
),
|
||||
allRecordIdsSelector: extractComponentReadOnlySelector(
|
||||
recordBoardAllRecordIdsComponentSelector,
|
||||
scopeId,
|
||||
),
|
||||
selectedRecordIdsSelector: extractComponentReadOnlySelector(
|
||||
recordBoardSelectedRecordIdsComponentSelector,
|
||||
scopeId,
|
||||
),
|
||||
|
||||
isCompactModeActiveState: extractComponentState(
|
||||
isRecordBoardCompactModeActiveComponentState,
|
||||
scopeId,
|
||||
),
|
||||
|
||||
shouldFetchMoreInColumnFamilyState: extractComponentFamilyState(
|
||||
recordBoardShouldFetchMoreInColumnComponentFamilyState,
|
||||
scopeId,
|
||||
),
|
||||
shouldFetchMoreSelector: extractComponentReadOnlySelector(
|
||||
recordBoardShouldFetchMoreComponentSelector,
|
||||
scopeId,
|
||||
),
|
||||
};
|
||||
};
|
||||
@ -1,58 +0,0 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { useRecordBoardStates } from '@/object-record/record-board/hooks/internal/useRecordBoardStates';
|
||||
import { RecordGroupDefinition } from '@/object-record/record-group/types/RecordGroupDefinition';
|
||||
import { sortRecordGroupDefinitions } from '@/object-record/record-group/utils/sortRecordGroupDefinitions';
|
||||
import { recordIndexRecordGroupSortComponentState } from '@/object-record/record-index/states/recordIndexRecordGroupSortComponentState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
|
||||
export const useSetRecordBoardColumns = (recordBoardId?: string) => {
|
||||
const { scopeId, columnIdsState, columnsFamilySelector } =
|
||||
useRecordBoardStates(recordBoardId);
|
||||
|
||||
const recordGroupSort = useRecoilComponentValueV2(
|
||||
recordIndexRecordGroupSortComponentState,
|
||||
recordBoardId,
|
||||
);
|
||||
|
||||
const setColumns = useRecoilCallback(
|
||||
({ set, snapshot }) =>
|
||||
(columns: RecordGroupDefinition[]) => {
|
||||
const currentColumnsIds = snapshot
|
||||
.getLoadable(columnIdsState)
|
||||
.getValue();
|
||||
|
||||
const sortedColumns = sortRecordGroupDefinitions(
|
||||
columns,
|
||||
recordGroupSort,
|
||||
);
|
||||
|
||||
const columnIds = sortedColumns
|
||||
.filter(({ isVisible }) => isVisible)
|
||||
.map(({ id }) => id);
|
||||
|
||||
if (!isDeeplyEqual(currentColumnsIds, columnIds)) {
|
||||
set(columnIdsState, columnIds);
|
||||
}
|
||||
|
||||
columns.forEach((column) => {
|
||||
const currentColumn = snapshot
|
||||
.getLoadable(columnsFamilySelector(column.id))
|
||||
.getValue();
|
||||
|
||||
if (isDeeplyEqual(currentColumn, column)) {
|
||||
return;
|
||||
}
|
||||
|
||||
set(columnsFamilySelector(column.id), column);
|
||||
});
|
||||
},
|
||||
[columnIdsState, recordGroupSort, columnsFamilySelector],
|
||||
);
|
||||
|
||||
return {
|
||||
scopeId,
|
||||
setColumns,
|
||||
};
|
||||
};
|
||||
@ -1,63 +0,0 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { useRecordBoardStates } from '@/object-record/record-board/hooks/internal/useRecordBoardStates';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { sortRecordsByPosition } from '@/object-record/utils/sortRecordsByPosition';
|
||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
|
||||
export const useSetRecordBoardRecordIds = (recordBoardId?: string) => {
|
||||
const {
|
||||
scopeId,
|
||||
recordIdsByColumnIdFamilyState,
|
||||
columnsFamilySelector,
|
||||
columnIdsState,
|
||||
kanbanFieldMetadataNameState,
|
||||
} = useRecordBoardStates(recordBoardId);
|
||||
|
||||
const setRecordIds = useRecoilCallback(
|
||||
({ set, snapshot }) =>
|
||||
(records: ObjectRecord[]) => {
|
||||
const columnIds = snapshot.getLoadable(columnIdsState).getValue();
|
||||
|
||||
columnIds.forEach((columnId) => {
|
||||
const column = snapshot
|
||||
.getLoadable(columnsFamilySelector(columnId))
|
||||
.getValue();
|
||||
|
||||
const existingColumnRecordIds = snapshot
|
||||
.getLoadable(recordIdsByColumnIdFamilyState(columnId))
|
||||
.getValue();
|
||||
|
||||
const kanbanFieldMetadataName = snapshot
|
||||
.getLoadable(kanbanFieldMetadataNameState)
|
||||
.getValue();
|
||||
|
||||
if (!kanbanFieldMetadataName) {
|
||||
return;
|
||||
}
|
||||
|
||||
const columnRecordIds = records
|
||||
.filter(
|
||||
(record) => record[kanbanFieldMetadataName] === column?.value,
|
||||
)
|
||||
.sort(sortRecordsByPosition)
|
||||
.map((record) => record.id);
|
||||
|
||||
if (!isDeeplyEqual(existingColumnRecordIds, columnRecordIds)) {
|
||||
set(recordIdsByColumnIdFamilyState(columnId), columnRecordIds);
|
||||
}
|
||||
});
|
||||
},
|
||||
[
|
||||
columnIdsState,
|
||||
columnsFamilySelector,
|
||||
recordIdsByColumnIdFamilyState,
|
||||
kanbanFieldMetadataNameState,
|
||||
],
|
||||
);
|
||||
|
||||
return {
|
||||
scopeId,
|
||||
setRecordIds,
|
||||
};
|
||||
};
|
||||
@ -1,55 +0,0 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { useRecordBoardStates } from '@/object-record/record-board/hooks/internal/useRecordBoardStates';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { sortRecordsByPosition } from '@/object-record/utils/sortRecordsByPosition';
|
||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
|
||||
export const useSetRecordIdsForColumn = (recordBoardId?: string) => {
|
||||
const {
|
||||
scopeId,
|
||||
recordIdsByColumnIdFamilyState,
|
||||
columnsFamilySelector,
|
||||
kanbanFieldMetadataNameState,
|
||||
} = useRecordBoardStates(recordBoardId);
|
||||
|
||||
const setRecordIdsForColumn = useRecoilCallback(
|
||||
({ set, snapshot }) =>
|
||||
(columnId: string, records: ObjectRecord[]) => {
|
||||
const column = snapshot
|
||||
.getLoadable(columnsFamilySelector(columnId))
|
||||
.getValue();
|
||||
|
||||
const existingColumnRecordIds = snapshot
|
||||
.getLoadable(recordIdsByColumnIdFamilyState(columnId))
|
||||
.getValue();
|
||||
|
||||
const kanbanFieldMetadataName = snapshot
|
||||
.getLoadable(kanbanFieldMetadataNameState)
|
||||
.getValue();
|
||||
|
||||
if (!kanbanFieldMetadataName) {
|
||||
return;
|
||||
}
|
||||
|
||||
const columnRecordIds = records
|
||||
.filter((record) => record[kanbanFieldMetadataName] === column?.value)
|
||||
.sort(sortRecordsByPosition)
|
||||
.map((record) => record.id);
|
||||
|
||||
if (!isDeeplyEqual(existingColumnRecordIds, columnRecordIds)) {
|
||||
set(recordIdsByColumnIdFamilyState(columnId), columnRecordIds);
|
||||
}
|
||||
},
|
||||
[
|
||||
columnsFamilySelector,
|
||||
recordIdsByColumnIdFamilyState,
|
||||
kanbanFieldMetadataNameState,
|
||||
],
|
||||
);
|
||||
|
||||
return {
|
||||
scopeId,
|
||||
setRecordIdsForColumn,
|
||||
};
|
||||
};
|
||||
@ -1,43 +0,0 @@
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
|
||||
import { useRecordBoardStates } from '@/object-record/record-board/hooks/internal/useRecordBoardStates';
|
||||
import { useSetRecordBoardColumns } from '@/object-record/record-board/hooks/internal/useSetRecordBoardColumns';
|
||||
import { useSetRecordBoardRecordIds } from '@/object-record/record-board/hooks/internal/useSetRecordBoardRecordIds';
|
||||
import { useSetRecordIdsForColumn } from '@/object-record/record-board/hooks/internal/useSetRecordIdsForColumn';
|
||||
|
||||
export const useRecordBoard = (recordBoardId?: string) => {
|
||||
const {
|
||||
scopeId,
|
||||
fieldDefinitionsState,
|
||||
objectSingularNameState,
|
||||
selectedRecordIdsSelector,
|
||||
isCompactModeActiveState,
|
||||
kanbanFieldMetadataNameState,
|
||||
shouldFetchMoreSelector,
|
||||
isFetchingRecordsByColumnState,
|
||||
} = useRecordBoardStates(recordBoardId);
|
||||
|
||||
const { setColumns } = useSetRecordBoardColumns(recordBoardId);
|
||||
const { setRecordIds } = useSetRecordBoardRecordIds(recordBoardId);
|
||||
const { setRecordIdsForColumn } = useSetRecordIdsForColumn(recordBoardId);
|
||||
|
||||
const setFieldDefinitions = useSetRecoilState(fieldDefinitionsState);
|
||||
const setObjectSingularName = useSetRecoilState(objectSingularNameState);
|
||||
const setKanbanFieldMetadataName = useSetRecoilState(
|
||||
kanbanFieldMetadataNameState,
|
||||
);
|
||||
|
||||
return {
|
||||
scopeId,
|
||||
setColumns,
|
||||
setRecordIds,
|
||||
setFieldDefinitions,
|
||||
setObjectSingularName,
|
||||
setKanbanFieldMetadataName,
|
||||
selectedRecordIdsSelector,
|
||||
isCompactModeActiveState,
|
||||
shouldFetchMoreSelector,
|
||||
setRecordIdsForColumn,
|
||||
isFetchingRecordsByColumnState,
|
||||
};
|
||||
};
|
||||
@ -2,13 +2,25 @@ import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { getActionMenuDropdownIdFromActionMenuId } from '@/action-menu/utils/getActionMenuDropdownIdFromActionMenuId';
|
||||
import { getActionMenuIdFromRecordIndexId } from '@/action-menu/utils/getActionMenuIdFromRecordIndexId';
|
||||
import { useRecordBoardStates } from '@/object-record/record-board/hooks/internal/useRecordBoardStates';
|
||||
import { isRecordBoardCardSelectedComponentFamilyState } from '@/object-record/record-board/states/isRecordBoardCardSelectedComponentFamilyState';
|
||||
import { recordBoardSelectedRecordIdsComponentSelector } from '@/object-record/record-board/states/selectors/recordBoardSelectedRecordIdsComponentSelector';
|
||||
import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState';
|
||||
import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue';
|
||||
|
||||
export const useRecordBoardSelection = (recordBoardId: string) => {
|
||||
const { selectedRecordIdsSelector, isRecordBoardCardSelectedFamilyState } =
|
||||
useRecordBoardStates(recordBoardId);
|
||||
const isRecordBoardCardSelectedFamilyState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
isRecordBoardCardSelectedComponentFamilyState,
|
||||
recordBoardId,
|
||||
);
|
||||
|
||||
const recordBoardSelectedRecordIdsSelector =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
recordBoardSelectedRecordIdsComponentSelector,
|
||||
recordBoardId,
|
||||
);
|
||||
|
||||
const isActionMenuDropdownOpenState = extractComponentState(
|
||||
isDropdownOpenComponentState,
|
||||
@ -22,9 +34,10 @@ export const useRecordBoardSelection = (recordBoardId: string) => {
|
||||
() => {
|
||||
set(isActionMenuDropdownOpenState, false);
|
||||
|
||||
const recordIds = snapshot
|
||||
.getLoadable(selectedRecordIdsSelector())
|
||||
.getValue();
|
||||
const recordIds = getSnapshotValue(
|
||||
snapshot,
|
||||
recordBoardSelectedRecordIdsSelector,
|
||||
);
|
||||
|
||||
for (const recordId of recordIds) {
|
||||
set(isRecordBoardCardSelectedFamilyState(recordId), false);
|
||||
@ -32,7 +45,7 @@ export const useRecordBoardSelection = (recordBoardId: string) => {
|
||||
},
|
||||
[
|
||||
isActionMenuDropdownOpenState,
|
||||
selectedRecordIdsSelector,
|
||||
recordBoardSelectedRecordIdsSelector,
|
||||
isRecordBoardCardSelectedFamilyState,
|
||||
],
|
||||
);
|
||||
|
||||
@ -0,0 +1,110 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { recordGroupDefinitionFamilyState } from '@/object-record/record-group/states/recordGroupDefinitionFamilyState';
|
||||
import { recordGroupFieldMetadataComponentState } from '@/object-record/record-group/states/recordGroupFieldMetadataComponentState';
|
||||
import { visibleRecordGroupIdsComponentSelector } from '@/object-record/record-group/states/selectors/visibleRecordGroupIdsComponentSelector';
|
||||
import { recordIndexAllRowIdsComponentState } from '@/object-record/record-index/states/recordIndexAllRowIdsComponentState';
|
||||
import { recordIndexRowIdsByGroupComponentFamilyState } from '@/object-record/record-index/states/recordIndexRowIdsByGroupComponentFamilyState';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { sortRecordsByPosition } from '@/object-record/utils/sortRecordsByPosition';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue';
|
||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export const useSetRecordBoardRecordIds = (recordBoardId?: string) => {
|
||||
const visibleRecordGroupIdsSelector = useRecoilComponentCallbackStateV2(
|
||||
visibleRecordGroupIdsComponentSelector,
|
||||
);
|
||||
|
||||
const recordGroupFieldMetadataState = useRecoilComponentCallbackStateV2(
|
||||
recordGroupFieldMetadataComponentState,
|
||||
recordBoardId,
|
||||
);
|
||||
|
||||
const recordIndexAllRowIdsState = useRecoilComponentCallbackStateV2(
|
||||
recordIndexAllRowIdsComponentState,
|
||||
recordBoardId,
|
||||
);
|
||||
|
||||
const recordIndexRowIdsByGroupFamilyState = useRecoilComponentCallbackStateV2(
|
||||
recordIndexRowIdsByGroupComponentFamilyState,
|
||||
recordBoardId,
|
||||
);
|
||||
|
||||
const setRecordIds = useRecoilCallback(
|
||||
({ set, snapshot }) =>
|
||||
(records: ObjectRecord[]) => {
|
||||
const existingAllRowIds = getSnapshotValue(
|
||||
snapshot,
|
||||
recordIndexAllRowIdsState,
|
||||
);
|
||||
|
||||
const recordGroupIds = getSnapshotValue(
|
||||
snapshot,
|
||||
visibleRecordGroupIdsSelector,
|
||||
);
|
||||
|
||||
for (const recordGroupId of recordGroupIds) {
|
||||
const recordGroup = getSnapshotValue(
|
||||
snapshot,
|
||||
recordGroupDefinitionFamilyState(recordGroupId),
|
||||
);
|
||||
|
||||
const existingRecordGroupRowIds = getSnapshotValue(
|
||||
snapshot,
|
||||
recordIndexRowIdsByGroupFamilyState(recordGroupId),
|
||||
);
|
||||
|
||||
const recordGroupFieldMetadata = getSnapshotValue(
|
||||
snapshot,
|
||||
recordGroupFieldMetadataState,
|
||||
);
|
||||
|
||||
if (!isDefined(recordGroupFieldMetadata)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const recordGroupRowIds = records
|
||||
.filter(
|
||||
(record) =>
|
||||
record[recordGroupFieldMetadata.name] === recordGroup?.value,
|
||||
)
|
||||
.sort(sortRecordsByPosition)
|
||||
.map((record) => record.id);
|
||||
|
||||
if (!isDeeplyEqual(existingRecordGroupRowIds, recordGroupRowIds)) {
|
||||
set(
|
||||
recordIndexRowIdsByGroupFamilyState(recordGroupId),
|
||||
recordGroupRowIds,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const allRowIds: string[] = [];
|
||||
|
||||
for (const recordGroupId of recordGroupIds) {
|
||||
const tableRowIdsByGroup = getSnapshotValue(
|
||||
snapshot,
|
||||
recordIndexRowIdsByGroupFamilyState(recordGroupId),
|
||||
);
|
||||
|
||||
allRowIds.push(...tableRowIdsByGroup);
|
||||
}
|
||||
|
||||
if (!isDeeplyEqual(existingAllRowIds, allRowIds)) {
|
||||
set(recordIndexAllRowIdsState, allRowIds);
|
||||
}
|
||||
},
|
||||
[
|
||||
visibleRecordGroupIdsSelector,
|
||||
recordIndexRowIdsByGroupFamilyState,
|
||||
recordGroupFieldMetadataState,
|
||||
recordIndexAllRowIdsState,
|
||||
],
|
||||
);
|
||||
|
||||
return {
|
||||
setRecordIds,
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,109 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { recordGroupDefinitionFamilyState } from '@/object-record/record-group/states/recordGroupDefinitionFamilyState';
|
||||
import { recordGroupFieldMetadataComponentState } from '@/object-record/record-group/states/recordGroupFieldMetadataComponentState';
|
||||
import { recordGroupIdsComponentState } from '@/object-record/record-group/states/recordGroupIdsComponentState';
|
||||
import { recordIndexAllRowIdsComponentState } from '@/object-record/record-index/states/recordIndexAllRowIdsComponentState';
|
||||
import { recordIndexRowIdsByGroupComponentFamilyState } from '@/object-record/record-index/states/recordIndexRowIdsByGroupComponentFamilyState';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { sortRecordsByPosition } from '@/object-record/utils/sortRecordsByPosition';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue';
|
||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export const useSetRecordIdsForColumn = (recordBoardId?: string) => {
|
||||
const recordGroupIdsState = useRecoilComponentCallbackStateV2(
|
||||
recordGroupIdsComponentState,
|
||||
recordBoardId,
|
||||
);
|
||||
|
||||
const recordGroupFieldMetadataState = useRecoilComponentCallbackStateV2(
|
||||
recordGroupFieldMetadataComponentState,
|
||||
recordBoardId,
|
||||
);
|
||||
|
||||
const recordIndexAllRowIdsState = useRecoilComponentCallbackStateV2(
|
||||
recordIndexAllRowIdsComponentState,
|
||||
recordBoardId,
|
||||
);
|
||||
|
||||
const recordIndexRowIdsByGroupFamilyState = useRecoilComponentCallbackStateV2(
|
||||
recordIndexRowIdsByGroupComponentFamilyState,
|
||||
recordBoardId,
|
||||
);
|
||||
|
||||
const setRecordIdsForColumn = useRecoilCallback(
|
||||
({ set, snapshot }) =>
|
||||
(currentRecordGroupId: string, records: ObjectRecord[]) => {
|
||||
const existingAllRowIds = getSnapshotValue(
|
||||
snapshot,
|
||||
recordIndexAllRowIdsState,
|
||||
);
|
||||
|
||||
const recordGroupIds = getSnapshotValue(snapshot, recordGroupIdsState);
|
||||
|
||||
const recordGroup = getSnapshotValue(
|
||||
snapshot,
|
||||
recordGroupDefinitionFamilyState(currentRecordGroupId),
|
||||
);
|
||||
|
||||
const existingRecordGroupRowIds = getSnapshotValue(
|
||||
snapshot,
|
||||
recordIndexRowIdsByGroupFamilyState(currentRecordGroupId),
|
||||
);
|
||||
|
||||
const recordGroupFieldMetadata = getSnapshotValue(
|
||||
snapshot,
|
||||
recordGroupFieldMetadataState,
|
||||
);
|
||||
|
||||
if (!isDefined(recordGroupFieldMetadata)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const recordGroupRowIds = records
|
||||
.filter(
|
||||
(record) =>
|
||||
record[recordGroupFieldMetadata.name] === recordGroup?.value,
|
||||
)
|
||||
.sort(sortRecordsByPosition)
|
||||
.map((record) => record.id);
|
||||
|
||||
if (!isDeeplyEqual(existingRecordGroupRowIds, recordGroupRowIds)) {
|
||||
set(
|
||||
recordIndexRowIdsByGroupFamilyState(currentRecordGroupId),
|
||||
recordGroupRowIds,
|
||||
);
|
||||
}
|
||||
|
||||
const allRowIds: string[] = [];
|
||||
|
||||
for (const recordGroupId of recordGroupIds) {
|
||||
const tableRowIdsByGroup =
|
||||
recordGroupId !== currentRecordGroupId
|
||||
? getSnapshotValue(
|
||||
snapshot,
|
||||
recordIndexRowIdsByGroupFamilyState(recordGroupId),
|
||||
)
|
||||
: recordGroupRowIds;
|
||||
|
||||
allRowIds.push(...tableRowIdsByGroup);
|
||||
}
|
||||
|
||||
if (!isDeeplyEqual(existingAllRowIds, allRowIds)) {
|
||||
set(recordIndexAllRowIdsState, allRowIds);
|
||||
}
|
||||
},
|
||||
[
|
||||
recordGroupIdsState,
|
||||
recordIndexRowIdsByGroupFamilyState,
|
||||
recordGroupFieldMetadataState,
|
||||
recordIndexAllRowIdsState,
|
||||
],
|
||||
);
|
||||
|
||||
return {
|
||||
setRecordIdsForColumn,
|
||||
};
|
||||
};
|
||||
@ -3,9 +3,11 @@ import { recordIndexActionMenuDropdownPositionComponentState } from '@/action-me
|
||||
import { getActionMenuDropdownIdFromActionMenuId } from '@/action-menu/utils/getActionMenuDropdownIdFromActionMenuId';
|
||||
import { getActionMenuIdFromRecordIndexId } from '@/action-menu/utils/getActionMenuIdFromRecordIndexId';
|
||||
import { RecordBoardContext } from '@/object-record/record-board/contexts/RecordBoardContext';
|
||||
import { useRecordBoardStates } from '@/object-record/record-board/hooks/internal/useRecordBoardStates';
|
||||
import { RecordBoardCardContext } from '@/object-record/record-board/record-board-card/contexts/RecordBoardCardContext';
|
||||
import { RecordBoardScopeInternalContext } from '@/object-record/record-board/scopes/scope-internal-context/RecordBoardScopeInternalContext';
|
||||
import { isRecordBoardCardSelectedComponentFamilyState } from '@/object-record/record-board/states/isRecordBoardCardSelectedComponentFamilyState';
|
||||
import { isRecordBoardCompactModeActiveComponentState } from '@/object-record/record-board/states/isRecordBoardCompactModeActiveComponentState';
|
||||
import { recordBoardVisibleFieldDefinitionsComponentSelector } from '@/object-record/record-board/states/selectors/recordBoardVisibleFieldDefinitionsComponentSelector';
|
||||
import {
|
||||
FieldContext,
|
||||
RecordUpdateHook,
|
||||
@ -22,11 +24,13 @@ import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { TextInput } from '@/ui/input/components/TextInput';
|
||||
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
|
||||
import { RecordBoardScrollWrapperContext } from '@/ui/utilities/scroll/contexts/ScrollWrapperContexts';
|
||||
import { useRecoilComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyStateV2';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState';
|
||||
import styled from '@emotion/styled';
|
||||
import { ReactNode, useContext, useState } from 'react';
|
||||
import { InView, useInView } from 'react-intersection-observer';
|
||||
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
import { useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
import {
|
||||
AnimatedEaseInOut,
|
||||
AvatarChipVariant,
|
||||
@ -157,27 +161,30 @@ export const RecordBoardCard = ({
|
||||
onCreateSuccess?: () => void;
|
||||
position?: 'first' | 'last';
|
||||
}) => {
|
||||
const [newLabelValue, setNewLabelValue] = useState('');
|
||||
const { handleBlur, handleInputEnter } = useAddNewCard();
|
||||
const { recordId } = useContext(RecordBoardCardContext);
|
||||
|
||||
const [newLabelValue, setNewLabelValue] = useState('');
|
||||
|
||||
const { handleBlur, handleInputEnter } = useAddNewCard();
|
||||
|
||||
const { updateOneRecord, objectMetadataItem } =
|
||||
useContext(RecordBoardContext);
|
||||
const {
|
||||
isCompactModeActiveState,
|
||||
isRecordBoardCardSelectedFamilyState,
|
||||
visibleFieldDefinitionsState,
|
||||
} = useRecordBoardStates();
|
||||
const isCompactModeActive = useRecoilValue(isCompactModeActiveState);
|
||||
|
||||
const visibleFieldDefinitions = useRecoilComponentValueV2(
|
||||
recordBoardVisibleFieldDefinitionsComponentSelector,
|
||||
);
|
||||
|
||||
const isCompactModeActive = useRecoilComponentValueV2(
|
||||
isRecordBoardCompactModeActiveComponentState,
|
||||
);
|
||||
|
||||
const [isCardExpanded, setIsCardExpanded] = useState(false);
|
||||
|
||||
const [isCurrentCardSelected, setIsCurrentCardSelected] = useRecoilState(
|
||||
isRecordBoardCardSelectedFamilyState(recordId),
|
||||
);
|
||||
|
||||
const visibleFieldDefinitions = useRecoilValue(
|
||||
visibleFieldDefinitionsState(),
|
||||
);
|
||||
const [isCurrentCardSelected, setIsCurrentCardSelected] =
|
||||
useRecoilComponentFamilyStateV2(
|
||||
isRecordBoardCardSelectedComponentFamilyState,
|
||||
recordId,
|
||||
);
|
||||
|
||||
const record = useRecoilValue(recordStoreFamilyState(recordId));
|
||||
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { Droppable } from '@hello-pangea/dnd';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { useRecordBoardStates } from '@/object-record/record-board/hooks/internal/useRecordBoardStates';
|
||||
import { RecordBoardColumnCardsContainer } from '@/object-record/record-board/record-board-column/components/RecordBoardColumnCardsContainer';
|
||||
import { RecordBoardColumnContext } from '@/object-record/record-board/record-board-column/contexts/RecordBoardColumnContext';
|
||||
import { recordGroupDefinitionFamilyState } from '@/object-record/record-group/states/recordGroupDefinitionFamilyState';
|
||||
import { recordIndexRowIdsByGroupComponentFamilyState } from '@/object-record/record-index/states/recordIndexRowIdsByGroupComponentFamilyState';
|
||||
import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
const StyledColumn = styled.div`
|
||||
background-color: ${({ theme }) => theme.background.primary};
|
||||
@ -25,27 +27,26 @@ type RecordBoardColumnProps = {
|
||||
export const RecordBoardColumn = ({
|
||||
recordBoardColumnId,
|
||||
}: RecordBoardColumnProps) => {
|
||||
const { columnsFamilySelector, recordIdsByColumnIdFamilyState } =
|
||||
useRecordBoardStates();
|
||||
const columnDefinition = useRecoilValue(
|
||||
columnsFamilySelector(recordBoardColumnId),
|
||||
const recordGroupDefinition = useRecoilValue(
|
||||
recordGroupDefinitionFamilyState(recordBoardColumnId),
|
||||
);
|
||||
|
||||
const recordIds = useRecoilValue(
|
||||
recordIdsByColumnIdFamilyState(recordBoardColumnId),
|
||||
const recordRowIdsByGroup = useRecoilComponentFamilyValueV2(
|
||||
recordIndexRowIdsByGroupComponentFamilyState,
|
||||
recordBoardColumnId,
|
||||
);
|
||||
|
||||
if (!columnDefinition) {
|
||||
if (!recordGroupDefinition) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<RecordBoardColumnContext.Provider
|
||||
value={{
|
||||
columnDefinition: columnDefinition,
|
||||
recordCount: recordIds.length,
|
||||
columnDefinition: recordGroupDefinition,
|
||||
recordCount: recordRowIdsByGroup.length,
|
||||
columnId: recordBoardColumnId,
|
||||
recordIds,
|
||||
recordIds: recordRowIdsByGroup,
|
||||
}}
|
||||
>
|
||||
<Droppable droppableId={recordBoardColumnId}>
|
||||
@ -53,7 +54,7 @@ export const RecordBoardColumn = ({
|
||||
<StyledColumn>
|
||||
<RecordBoardColumnCardsContainer
|
||||
droppableProvided={droppableProvided}
|
||||
recordIds={recordIds}
|
||||
recordIds={recordRowIdsByGroup}
|
||||
/>
|
||||
</StyledColumn>
|
||||
)}
|
||||
|
||||
@ -5,7 +5,6 @@ import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { RecordBoardContext } from '@/object-record/record-board/contexts/RecordBoardContext';
|
||||
import { useRecordBoardStates } from '@/object-record/record-board/hooks/internal/useRecordBoardStates';
|
||||
import { RecordBoardColumnCardContainerSkeletonLoader } from '@/object-record/record-board/record-board-column/components/RecordBoardColumnCardContainerSkeletonLoader';
|
||||
import { RecordBoardColumnCardsMemo } from '@/object-record/record-board/record-board-column/components/RecordBoardColumnCardsMemo';
|
||||
import { RecordBoardColumnFetchMoreLoader } from '@/object-record/record-board/record-board-column/components/RecordBoardColumnFetchMoreLoader';
|
||||
@ -15,7 +14,10 @@ import { RecordBoardColumnNewRecordButton } from '@/object-record/record-board/r
|
||||
import { RecordBoardColumnContext } from '@/object-record/record-board/record-board-column/contexts/RecordBoardColumnContext';
|
||||
import { useIsOpportunitiesCompanyFieldDisabled } from '@/object-record/record-board/record-board-column/hooks/useIsOpportunitiesCompanyFieldDisabled';
|
||||
import { getNumberOfCardsPerColumnForSkeletonLoading } from '@/object-record/record-board/record-board-column/utils/getNumberOfCardsPerColumnForSkeletonLoading';
|
||||
import { isRecordBoardCompactModeActiveComponentState } from '@/object-record/record-board/states/isRecordBoardCompactModeActiveComponentState';
|
||||
import { recordBoardVisibleFieldDefinitionsComponentSelector } from '@/object-record/record-board/states/selectors/recordBoardVisibleFieldDefinitionsComponentSelector';
|
||||
import { isRecordIndexBoardColumnLoadingFamilyState } from '@/object-record/states/isRecordBoardColumnLoadingFamilyState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
|
||||
const StyledColumnCardsContainer = styled.div`
|
||||
display: flex;
|
||||
@ -56,16 +58,16 @@ export const RecordBoardColumnCardsContainer = ({
|
||||
isRecordIndexBoardColumnLoadingFamilyState(columnId),
|
||||
);
|
||||
|
||||
const { isCompactModeActiveState, visibleFieldDefinitionsState } =
|
||||
useRecordBoardStates();
|
||||
|
||||
const visibleFieldDefinitions = useRecoilValue(
|
||||
visibleFieldDefinitionsState(),
|
||||
const visibleFieldDefinitions = useRecoilComponentValueV2(
|
||||
recordBoardVisibleFieldDefinitionsComponentSelector,
|
||||
);
|
||||
|
||||
const numberOfFields = visibleFieldDefinitions.length;
|
||||
|
||||
const isCompactModeActive = useRecoilValue(isCompactModeActiveState);
|
||||
const isCompactModeActive = useRecoilComponentValueV2(
|
||||
isRecordBoardCompactModeActiveComponentState,
|
||||
);
|
||||
|
||||
const { isOpportunitiesCompanyFieldDisabled } =
|
||||
useIsOpportunitiesCompanyFieldDisabled();
|
||||
|
||||
|
||||
@ -5,7 +5,6 @@ import { useRecordGroupActions } from '@/object-record/record-group/hooks/useRec
|
||||
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
||||
import { ViewType } from '@/views/types/ViewType';
|
||||
import { MenuItem } from 'twenty-ui';
|
||||
|
||||
const StyledMenuContainer = styled.div`
|
||||
@ -26,9 +25,7 @@ export const RecordBoardColumnDropdownMenu = ({
|
||||
}: RecordBoardColumnDropdownMenuProps) => {
|
||||
const boardColumnMenuRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const recordGroupActions = useRecordGroupActions({
|
||||
viewType: ViewType.Kanban,
|
||||
});
|
||||
const recordGroupActions = useRecordGroupActions();
|
||||
|
||||
const closeMenu = useCallback(() => {
|
||||
onClose();
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { useContext, useEffect } from 'react';
|
||||
import { useInView } from 'react-intersection-observer';
|
||||
import styled from '@emotion/styled';
|
||||
import { useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { GRAY_SCALE } from 'twenty-ui';
|
||||
|
||||
import { useRecordBoardStates } from '@/object-record/record-board/hooks/internal/useRecordBoardStates';
|
||||
import { RecordBoardColumnContext } from '@/object-record/record-board/record-board-column/contexts/RecordBoardColumnContext';
|
||||
import { isRecordBoardFetchingRecordsByColumnFamilyState } from '@/object-record/record-board/states/isRecordBoardFetchingRecordsByColumnFamilyState';
|
||||
import { recordBoardShouldFetchMoreInColumnComponentFamilyState } from '@/object-record/record-board/states/recordBoardShouldFetchMoreInColumnComponentFamilyState';
|
||||
import { useSetRecoilComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentFamilyStateV2';
|
||||
|
||||
const StyledText = styled.div`
|
||||
align-items: center;
|
||||
@ -19,15 +21,14 @@ const StyledText = styled.div`
|
||||
|
||||
export const RecordBoardColumnFetchMoreLoader = () => {
|
||||
const { columnDefinition } = useContext(RecordBoardColumnContext);
|
||||
const { shouldFetchMoreInColumnFamilyState, isFetchingRecordsByColumnState } =
|
||||
useRecordBoardStates();
|
||||
|
||||
const isFetchingRecord = useRecoilValue(
|
||||
isFetchingRecordsByColumnState({ columnId: columnDefinition.id }),
|
||||
isRecordBoardFetchingRecordsByColumnFamilyState(columnDefinition.id),
|
||||
);
|
||||
|
||||
const setShouldFetchMore = useSetRecoilState(
|
||||
shouldFetchMoreInColumnFamilyState(columnDefinition.id),
|
||||
const setShouldFetchMore = useSetRecoilComponentFamilyStateV2(
|
||||
recordBoardShouldFetchMoreInColumnComponentFamilyState,
|
||||
columnDefinition.id,
|
||||
);
|
||||
|
||||
const { ref, inView } = useInView();
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import { isDefined } from 'twenty-ui';
|
||||
|
||||
import { useRecordBoardStates } from '@/object-record/record-board/hooks/internal/useRecordBoardStates';
|
||||
import { RecordBoardColumnHeader } from '@/object-record/record-board/record-board-column/components/RecordBoardColumnHeader';
|
||||
import { RecordBoardColumnContext } from '@/object-record/record-board/record-board-column/contexts/RecordBoardColumnContext';
|
||||
import { recordGroupDefinitionFamilyState } from '@/object-record/record-group/states/recordGroupDefinitionFamilyState';
|
||||
import { recordIndexRowIdsByGroupComponentFamilyState } from '@/object-record/record-index/states/recordIndexRowIdsByGroupComponentFamilyState';
|
||||
import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
type RecordBoardColumnHeaderWrapperProps = {
|
||||
@ -12,14 +14,16 @@ type RecordBoardColumnHeaderWrapperProps = {
|
||||
export const RecordBoardColumnHeaderWrapper = ({
|
||||
columnId,
|
||||
}: RecordBoardColumnHeaderWrapperProps) => {
|
||||
const { columnsFamilySelector, recordIdsByColumnIdFamilyState } =
|
||||
useRecordBoardStates();
|
||||
const recordGroupDefinition = useRecoilValue(
|
||||
recordGroupDefinitionFamilyState(columnId),
|
||||
);
|
||||
|
||||
const columnDefinition = useRecoilValue(columnsFamilySelector(columnId));
|
||||
const recordRowIdsByGroup = useRecoilComponentFamilyValueV2(
|
||||
recordIndexRowIdsByGroupComponentFamilyState,
|
||||
columnId,
|
||||
);
|
||||
|
||||
const recordIds = useRecoilValue(recordIdsByColumnIdFamilyState(columnId));
|
||||
|
||||
if (!isDefined(columnDefinition)) {
|
||||
if (!isDefined(recordGroupDefinition)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -27,9 +31,9 @@ export const RecordBoardColumnHeaderWrapper = ({
|
||||
<RecordBoardColumnContext.Provider
|
||||
value={{
|
||||
columnId,
|
||||
columnDefinition: columnDefinition,
|
||||
recordCount: recordIds.length,
|
||||
recordIds,
|
||||
columnDefinition: recordGroupDefinition,
|
||||
recordCount: recordRowIdsByGroup.length,
|
||||
recordIds: recordRowIdsByGroup,
|
||||
}}
|
||||
>
|
||||
<RecordBoardColumnHeader />
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import { useRecordBoardStates } from '@/object-record/record-board/hooks/internal/useRecordBoardStates';
|
||||
import { useAddNewCard } from '@/object-record/record-board/record-board-column/hooks/useAddNewCard';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { recordBoardVisibleFieldDefinitionsComponentSelector } from '@/object-record/record-board/states/selectors/recordBoardVisibleFieldDefinitionsComponentSelector';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
|
||||
export const useColumnNewCardActions = (columnId: string) => {
|
||||
const { visibleFieldDefinitionsState } = useRecordBoardStates();
|
||||
const visibleFieldDefinitions = useRecoilValue(
|
||||
visibleFieldDefinitionsState(),
|
||||
const visibleFieldDefinitions = useRecoilComponentValueV2(
|
||||
recordBoardVisibleFieldDefinitionsComponentSelector,
|
||||
);
|
||||
|
||||
const labelIdentifierField = visibleFieldDefinitions.find(
|
||||
(field) => field.isLabelIdentifier,
|
||||
);
|
||||
|
||||
@ -0,0 +1,4 @@
|
||||
import { createComponentInstanceContext } from '@/ui/utilities/state/component-state/utils/createComponentInstanceContext';
|
||||
|
||||
export const RecordBoardComponentInstanceContext =
|
||||
createComponentInstanceContext();
|
||||
@ -1,7 +1,9 @@
|
||||
import { createComponentFamilyState } from '@/ui/utilities/state/component-state/utils/createComponentFamilyState';
|
||||
import { RecordBoardComponentInstanceContext } from '@/object-record/record-board/states/contexts/RecordBoardComponentInstanceContext';
|
||||
import { createComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentFamilyStateV2';
|
||||
|
||||
export const isRecordBoardCardSelectedComponentFamilyState =
|
||||
createComponentFamilyState<boolean, string>({
|
||||
createComponentFamilyStateV2<boolean, string>({
|
||||
key: 'isRecordBoardCardSelectedComponentFamilyState',
|
||||
defaultValue: false,
|
||||
componentInstanceContext: RecordBoardComponentInstanceContext,
|
||||
});
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
import { RecordBoardComponentInstanceContext } from '@/object-record/record-board/states/contexts/RecordBoardComponentInstanceContext';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
|
||||
export const isRecordBoardCompactModeActiveComponentState =
|
||||
createComponentState<boolean>({
|
||||
createComponentStateV2<boolean>({
|
||||
key: 'isRecordBoardCompactModeActiveComponentState',
|
||||
defaultValue: false,
|
||||
componentInstanceContext: RecordBoardComponentInstanceContext,
|
||||
});
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
import { createComponentFamilyState } from '@/ui/utilities/state/component-state/utils/createComponentFamilyState';
|
||||
import { RecordGroupDefinition } from '@/object-record/record-group/types/RecordGroupDefinition';
|
||||
import { atomFamily } from 'recoil';
|
||||
|
||||
export const isRecordBoardFetchingRecordsByColumnFamilyState =
|
||||
createComponentFamilyState<boolean, { columnId: string }>({
|
||||
key: 'isRecordBoardFetchingRecordsByColumnFamilyState',
|
||||
defaultValue: false,
|
||||
});
|
||||
export const isRecordBoardFetchingRecordsByColumnFamilyState = atomFamily<
|
||||
boolean,
|
||||
RecordGroupDefinition['id']
|
||||
>({
|
||||
key: 'isRecordBoardFetchingRecordsByColumnFamilyState',
|
||||
default: false,
|
||||
});
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
|
||||
export const isRecordBoardFetchingRecordsComponentState =
|
||||
createComponentState<boolean>({
|
||||
key: 'isRecordBoardFetchingRecordsComponentState',
|
||||
defaultValue: false,
|
||||
});
|
||||
@ -1,8 +0,0 @@
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
|
||||
export const recordBoardColumnIdsComponentState = createComponentState<
|
||||
string[]
|
||||
>({
|
||||
key: 'recordBoardColumnIdsComponentState',
|
||||
defaultValue: [],
|
||||
});
|
||||
@ -1,8 +0,0 @@
|
||||
import { RecordGroupDefinition } from '@/object-record/record-group/types/RecordGroupDefinition';
|
||||
import { createComponentFamilyState } from '@/ui/utilities/state/component-state/utils/createComponentFamilyState';
|
||||
|
||||
export const recordBoardColumnsComponentFamilyState =
|
||||
createComponentFamilyState<RecordGroupDefinition | undefined, string>({
|
||||
key: 'recordBoardColumnsComponentFamilyState',
|
||||
defaultValue: undefined,
|
||||
});
|
||||
@ -1,10 +1,12 @@
|
||||
import { RecordBoardComponentInstanceContext } from '@/object-record/record-board/states/contexts/RecordBoardComponentInstanceContext';
|
||||
import { RecordBoardFieldDefinition } from '@/object-record/record-board/types/RecordBoardFieldDefinition';
|
||||
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
|
||||
export const recordBoardFieldDefinitionsComponentState = createComponentState<
|
||||
export const recordBoardFieldDefinitionsComponentState = createComponentStateV2<
|
||||
RecordBoardFieldDefinition<FieldMetadata>[]
|
||||
>({
|
||||
key: 'recordBoardFieldDefinitionsComponentState',
|
||||
defaultValue: [],
|
||||
componentInstanceContext: RecordBoardComponentInstanceContext,
|
||||
});
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
import { Filter } from '@/object-record/object-filter-dropdown/types/Filter';
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
|
||||
export const recordBoardFiltersComponentState = createComponentState<Filter[]>({
|
||||
key: 'recordBoardFiltersComponentState',
|
||||
defaultValue: [],
|
||||
});
|
||||
@ -1,7 +0,0 @@
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
|
||||
export const recordBoardKanbanFieldMetadataNameComponentState =
|
||||
createComponentState<string | undefined>({
|
||||
key: 'recordBoardKanbanFieldMetadataNameComponentState',
|
||||
defaultValue: undefined,
|
||||
});
|
||||
@ -1,7 +0,0 @@
|
||||
import { createComponentFamilyState } from '@/ui/utilities/state/component-state/utils/createComponentFamilyState';
|
||||
|
||||
export const recordBoardRecordIdsByColumnIdComponentFamilyState =
|
||||
createComponentFamilyState<string[], string>({
|
||||
key: 'recordBoardRecordIdsByColumnIdComponentFamilyState',
|
||||
defaultValue: [],
|
||||
});
|
||||
@ -1,7 +1,9 @@
|
||||
import { createComponentFamilyState } from '@/ui/utilities/state/component-state/utils/createComponentFamilyState';
|
||||
import { RecordBoardComponentInstanceContext } from '@/object-record/record-board/states/contexts/RecordBoardComponentInstanceContext';
|
||||
import { createComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentFamilyStateV2';
|
||||
|
||||
export const recordBoardShouldFetchMoreInColumnComponentFamilyState =
|
||||
createComponentFamilyState<boolean, string>({
|
||||
key: 'onRecordBoardFetchMoreIrecordBoardShouldFetchMoreInColumnComponentFamilyStatesVisibleComponentFamilyState',
|
||||
createComponentFamilyStateV2<boolean, string>({
|
||||
key: 'recordBoardShouldFetchMoreInColumnComponentFamilyState',
|
||||
defaultValue: false,
|
||||
componentInstanceContext: RecordBoardComponentInstanceContext,
|
||||
});
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
import { Sort } from '@/object-record/object-sort-dropdown/types/Sort';
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
|
||||
export const recordBoardSortsComponentState = createComponentState<Sort[]>({
|
||||
key: 'recordBoardSortsComponentState',
|
||||
defaultValue: [],
|
||||
});
|
||||
@ -1,26 +0,0 @@
|
||||
import { recordBoardColumnIdsComponentState } from '@/object-record/record-board/states/recordBoardColumnIdsComponentState';
|
||||
import { recordBoardRecordIdsByColumnIdComponentFamilyState } from '@/object-record/record-board/states/recordBoardRecordIdsByColumnIdComponentFamilyState';
|
||||
import { createComponentReadOnlySelector } from '@/ui/utilities/state/component-state/utils/createComponentReadOnlySelector';
|
||||
|
||||
export const recordBoardAllRecordIdsComponentSelector =
|
||||
createComponentReadOnlySelector<string[]>({
|
||||
key: 'recordBoardAllRecordIdsComponentSelector',
|
||||
get:
|
||||
({ scopeId }) =>
|
||||
({ get }) => {
|
||||
const columnIds = get(recordBoardColumnIdsComponentState({ scopeId }));
|
||||
|
||||
const recordIdsByColumn = columnIds.map((columnId) =>
|
||||
get(
|
||||
recordBoardRecordIdsByColumnIdComponentFamilyState({
|
||||
scopeId,
|
||||
familyKey: columnId,
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
const recordIds = recordIdsByColumn.flat();
|
||||
|
||||
return recordIds;
|
||||
},
|
||||
});
|
||||
@ -1,41 +0,0 @@
|
||||
import { recordBoardColumnsComponentFamilyState } from '@/object-record/record-board/states/recordBoardColumnsComponentFamilyState';
|
||||
import { createComponentFamilySelector } from '@/ui/utilities/state/component-state/utils/createComponentFamilySelector';
|
||||
import { RecordGroupDefinition } from '@/object-record/record-group/types/RecordGroupDefinition';
|
||||
|
||||
export const recordBoardColumnsComponentFamilySelector =
|
||||
createComponentFamilySelector<RecordGroupDefinition | undefined, string>({
|
||||
key: 'recordBoardColumnsComponentFamilySelector',
|
||||
get:
|
||||
({
|
||||
scopeId,
|
||||
familyKey: columnId,
|
||||
}: {
|
||||
scopeId: string;
|
||||
familyKey: string;
|
||||
}) =>
|
||||
({ get }) => {
|
||||
return get(
|
||||
recordBoardColumnsComponentFamilyState({
|
||||
scopeId,
|
||||
familyKey: columnId,
|
||||
}),
|
||||
);
|
||||
},
|
||||
set:
|
||||
({
|
||||
scopeId,
|
||||
familyKey: columnId,
|
||||
}: {
|
||||
scopeId: string;
|
||||
familyKey: string;
|
||||
}) =>
|
||||
({ set }, newColumn) => {
|
||||
set(
|
||||
recordBoardColumnsComponentFamilyState({
|
||||
scopeId,
|
||||
familyKey: columnId,
|
||||
}),
|
||||
newColumn,
|
||||
);
|
||||
},
|
||||
});
|
||||
@ -1,32 +1,24 @@
|
||||
import { RecordBoardComponentInstanceContext } from '@/object-record/record-board/states/contexts/RecordBoardComponentInstanceContext';
|
||||
import { isRecordBoardCardSelectedComponentFamilyState } from '@/object-record/record-board/states/isRecordBoardCardSelectedComponentFamilyState';
|
||||
import { recordBoardColumnIdsComponentState } from '@/object-record/record-board/states/recordBoardColumnIdsComponentState';
|
||||
import { recordBoardRecordIdsByColumnIdComponentFamilyState } from '@/object-record/record-board/states/recordBoardRecordIdsByColumnIdComponentFamilyState';
|
||||
import { createComponentReadOnlySelector } from '@/ui/utilities/state/component-state/utils/createComponentReadOnlySelector';
|
||||
import { recordIndexAllRowIdsComponentState } from '@/object-record/record-index/states/recordIndexAllRowIdsComponentState';
|
||||
import { createComponentSelectorV2 } from '@/ui/utilities/state/component-state/utils/createComponentSelectorV2';
|
||||
|
||||
export const recordBoardSelectedRecordIdsComponentSelector =
|
||||
createComponentReadOnlySelector<string[]>({
|
||||
createComponentSelectorV2<string[]>({
|
||||
key: 'recordBoardSelectedRecordIdsSelector',
|
||||
componentInstanceContext: RecordBoardComponentInstanceContext,
|
||||
get:
|
||||
({ scopeId }) =>
|
||||
({ instanceId }) =>
|
||||
({ get }) => {
|
||||
const columnIds = get(recordBoardColumnIdsComponentState({ scopeId }));
|
||||
|
||||
const recordIdsByColumn = columnIds.map((columnId) =>
|
||||
get(
|
||||
recordBoardRecordIdsByColumnIdComponentFamilyState({
|
||||
scopeId,
|
||||
familyKey: columnId,
|
||||
}),
|
||||
),
|
||||
const allRowIds = get(
|
||||
recordIndexAllRowIdsComponentState.atomFamily({ instanceId }),
|
||||
);
|
||||
|
||||
const recordIds = recordIdsByColumn.flat();
|
||||
|
||||
return recordIds.filter(
|
||||
return allRowIds.filter(
|
||||
(recordId) =>
|
||||
get(
|
||||
isRecordBoardCardSelectedComponentFamilyState({
|
||||
scopeId,
|
||||
isRecordBoardCardSelectedComponentFamilyState.atomFamily({
|
||||
instanceId,
|
||||
familyKey: recordId,
|
||||
}),
|
||||
) === true,
|
||||
|
||||
@ -1,28 +0,0 @@
|
||||
import { recordBoardColumnIdsComponentState } from '@/object-record/record-board/states/recordBoardColumnIdsComponentState';
|
||||
import { recordBoardShouldFetchMoreInColumnComponentFamilyState } from '@/object-record/record-board/states/recordBoardShouldFetchMoreInColumnComponentFamilyState';
|
||||
import { createComponentReadOnlySelector } from '@/ui/utilities/state/component-state/utils/createComponentReadOnlySelector';
|
||||
|
||||
export const recordBoardShouldFetchMoreComponentSelector =
|
||||
createComponentReadOnlySelector<boolean>({
|
||||
key: 'recordBoardShouldFetchMoreComponentSelector',
|
||||
get:
|
||||
({ scopeId }: { scopeId: string }) =>
|
||||
({ get }) => {
|
||||
const columnIds = get(
|
||||
recordBoardColumnIdsComponentState({
|
||||
scopeId,
|
||||
}),
|
||||
);
|
||||
|
||||
const shouldFetchMoreInColumns = columnIds.map((columnId) => {
|
||||
return get(
|
||||
recordBoardShouldFetchMoreInColumnComponentFamilyState({
|
||||
scopeId,
|
||||
familyKey: columnId,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
return shouldFetchMoreInColumns.some(Boolean);
|
||||
},
|
||||
});
|
||||
@ -1,13 +1,17 @@
|
||||
import { RecordBoardComponentInstanceContext } from '@/object-record/record-board/states/contexts/RecordBoardComponentInstanceContext';
|
||||
import { recordBoardFieldDefinitionsComponentState } from '@/object-record/record-board/states/recordBoardFieldDefinitionsComponentState';
|
||||
import { createComponentReadOnlySelector } from '@/ui/utilities/state/component-state/utils/createComponentReadOnlySelector';
|
||||
import { createComponentSelectorV2 } from '@/ui/utilities/state/component-state/utils/createComponentSelectorV2';
|
||||
|
||||
export const recordBoardVisibleFieldDefinitionsComponentSelector =
|
||||
createComponentReadOnlySelector({
|
||||
createComponentSelectorV2({
|
||||
key: 'recordBoardVisibleFieldDefinitionsComponentSelector',
|
||||
get:
|
||||
({ scopeId }) =>
|
||||
({ instanceId }) =>
|
||||
({ get }) =>
|
||||
get(recordBoardFieldDefinitionsComponentState({ scopeId }))
|
||||
get(
|
||||
recordBoardFieldDefinitionsComponentState.atomFamily({ instanceId }),
|
||||
)
|
||||
.filter((field) => field.isVisible)
|
||||
.sort((a, b) => a.position - b.position),
|
||||
componentInstanceContext: RecordBoardComponentInstanceContext,
|
||||
});
|
||||
|
||||
@ -1,31 +1,45 @@
|
||||
import { IconEye, IconEyeOff, MenuItemDraggable, Tag } from 'twenty-ui';
|
||||
|
||||
import { recordGroupDefinitionFamilyState } from '@/object-record/record-group/states/recordGroupDefinitionFamilyState';
|
||||
import {
|
||||
RecordGroupDefinition,
|
||||
RecordGroupDefinitionType,
|
||||
} from '@/object-record/record-group/types/RecordGroupDefinition';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
type RecordGroupMenuItemDraggableProps = {
|
||||
recordGroup: RecordGroupDefinition;
|
||||
recordGroupId: string;
|
||||
showDragGrip?: boolean;
|
||||
isDraggable?: boolean;
|
||||
onVisibilityChange: (viewGroup: RecordGroupDefinition) => void;
|
||||
onVisibilityChange: (recordGroup: RecordGroupDefinition) => void;
|
||||
};
|
||||
|
||||
export const RecordGroupMenuItemDraggable = ({
|
||||
recordGroup,
|
||||
recordGroupId,
|
||||
showDragGrip,
|
||||
isDraggable,
|
||||
onVisibilityChange,
|
||||
}: RecordGroupMenuItemDraggableProps) => {
|
||||
const recordGroup = useRecoilValue(
|
||||
recordGroupDefinitionFamilyState(recordGroupId),
|
||||
);
|
||||
|
||||
if (!isDefined(recordGroup)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const isNoValue = recordGroup.type === RecordGroupDefinitionType.NoValue;
|
||||
|
||||
const getIconButtons = (recordGroup: RecordGroupDefinition) => {
|
||||
const iconButtons = [
|
||||
{
|
||||
Icon: recordGroup.isVisible ? IconEyeOff : IconEye,
|
||||
onClick: () => onVisibilityChange(recordGroup),
|
||||
onClick: () =>
|
||||
onVisibilityChange({
|
||||
...recordGroup,
|
||||
isVisible: !recordGroup.isVisible,
|
||||
}),
|
||||
},
|
||||
].filter(isDefined);
|
||||
|
||||
|
||||
@ -13,17 +13,17 @@ import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/Drop
|
||||
import { StyledDropdownMenuSubheader } from '@/ui/layout/dropdown/components/StyledDropdownMenuSubheader';
|
||||
|
||||
type RecordGroupsVisibilityDropdownSectionProps = {
|
||||
recordGroups: RecordGroupDefinition[];
|
||||
recordGroupIds: string[];
|
||||
isDraggable: boolean;
|
||||
onDragEnd?: OnDragEndResponder;
|
||||
onVisibilityChange: (viewGroup: RecordGroupDefinition) => void;
|
||||
onVisibilityChange: (recordGroup: RecordGroupDefinition) => void;
|
||||
title: string;
|
||||
showSubheader?: boolean;
|
||||
showDragGrip: boolean;
|
||||
};
|
||||
|
||||
export const RecordGroupsVisibilityDropdownSection = ({
|
||||
recordGroups,
|
||||
recordGroupIds,
|
||||
isDraggable,
|
||||
onDragEnd,
|
||||
onVisibilityChange,
|
||||
@ -43,12 +43,13 @@ export const RecordGroupsVisibilityDropdownSection = ({
|
||||
<StyledDropdownMenuSubheader>{title}</StyledDropdownMenuSubheader>
|
||||
)}
|
||||
<DropdownMenuItemsContainer>
|
||||
{!!recordGroups.length && (
|
||||
{recordGroupIds.length > 0 && (
|
||||
<>
|
||||
{!isDraggable ? (
|
||||
recordGroups.map((recordGroup) => (
|
||||
recordGroupIds.map((recordGroupId) => (
|
||||
<RecordGroupMenuItemDraggable
|
||||
recordGroup={recordGroup}
|
||||
key={recordGroupId}
|
||||
recordGroupId={recordGroupId}
|
||||
onVisibilityChange={onVisibilityChange}
|
||||
showDragGrip={showDragGrip}
|
||||
isDraggable={isDraggable}
|
||||
@ -59,14 +60,14 @@ export const RecordGroupsVisibilityDropdownSection = ({
|
||||
onDragEnd={handleOnDrag}
|
||||
draggableItems={
|
||||
<>
|
||||
{recordGroups.map((recordGroup, index) => (
|
||||
{recordGroupIds.map((recordGroupId, index) => (
|
||||
<DraggableItem
|
||||
key={recordGroup.id}
|
||||
draggableId={recordGroup.id}
|
||||
key={recordGroupId}
|
||||
draggableId={recordGroupId}
|
||||
index={index + 1}
|
||||
itemComponent={
|
||||
<RecordGroupMenuItemDraggable
|
||||
recordGroup={recordGroup}
|
||||
recordGroupId={recordGroupId}
|
||||
onVisibilityChange={onVisibilityChange}
|
||||
showDragGrip={showDragGrip}
|
||||
isDraggable={isDraggable}
|
||||
|
||||
@ -1,37 +1,14 @@
|
||||
import { RecordGroupContext } from '@/object-record/record-group/states/context/RecordGroupContext';
|
||||
import { hasRecordGroupDefinitionsComponentSelector } from '@/object-record/record-group/states/hasRecordGroupDefinitionsComponentSelector';
|
||||
import { recordGroupDefinitionsComponentState } from '@/object-record/record-group/states/recordGroupDefinitionsComponentState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useContext, useMemo } from 'react';
|
||||
import { recordGroupDefinitionFamilyState } from '@/object-record/record-group/states/recordGroupDefinitionFamilyState';
|
||||
import { useContext } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
export const useCurrentRecordGroupDefinition = (recordTableId?: string) => {
|
||||
export const useCurrentRecordGroupDefinition = () => {
|
||||
const context = useContext(RecordGroupContext);
|
||||
|
||||
const hasRecordGroups = useRecoilComponentValueV2(
|
||||
hasRecordGroupDefinitionsComponentSelector,
|
||||
recordTableId,
|
||||
const recordGroupDefinition = useRecoilValue(
|
||||
recordGroupDefinitionFamilyState(context?.recordGroupId),
|
||||
);
|
||||
|
||||
const recordGroupDefinitions = useRecoilComponentValueV2(
|
||||
recordGroupDefinitionsComponentState,
|
||||
recordTableId,
|
||||
);
|
||||
|
||||
const recordGroupDefinition = useMemo(() => {
|
||||
if (!hasRecordGroups) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (!context) {
|
||||
throw new Error(
|
||||
'useCurrentRecordGroupDefinition must be used within a RecordGroupContextProvider.',
|
||||
);
|
||||
}
|
||||
|
||||
return recordGroupDefinitions.find(
|
||||
({ id }) => id === context.recordGroupId,
|
||||
);
|
||||
}, [context, hasRecordGroups, recordGroupDefinitions]);
|
||||
|
||||
return recordGroupDefinition;
|
||||
};
|
||||
|
||||
@ -2,24 +2,18 @@ import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadata
|
||||
import { getFieldSlug } from '@/object-metadata/utils/getFieldSlug';
|
||||
import { getObjectSlug } from '@/object-metadata/utils/getObjectSlug';
|
||||
import { RecordBoardColumnContext } from '@/object-record/record-board/record-board-column/contexts/RecordBoardColumnContext';
|
||||
import { useRecordGroups } from '@/object-record/record-group/hooks/useRecordGroups';
|
||||
import { useRecordGroupVisibility } from '@/object-record/record-group/hooks/useRecordGroupVisibility';
|
||||
import { recordGroupFieldMetadataComponentState } from '@/object-record/record-group/states/recordGroupFieldMetadataComponentState';
|
||||
import { RecordGroupAction } from '@/object-record/record-group/types/RecordGroupActions';
|
||||
import { RecordIndexRootPropsContext } from '@/object-record/record-index/contexts/RecordIndexRootPropsContext';
|
||||
import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMemorizedUrlState';
|
||||
import { ViewType } from '@/views/types/ViewType';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useCallback, useContext, useMemo } from 'react';
|
||||
import { useLocation, useNavigate } from 'react-router-dom';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
import { IconEyeOff, IconSettings, isDefined } from 'twenty-ui';
|
||||
|
||||
type UseRecordGroupActionsParams = {
|
||||
viewType: ViewType;
|
||||
};
|
||||
|
||||
export const useRecordGroupActions = ({
|
||||
viewType,
|
||||
}: UseRecordGroupActionsParams) => {
|
||||
export const useRecordGroupActions = () => {
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
|
||||
@ -35,14 +29,13 @@ export const useRecordGroupActions = ({
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const { viewGroupFieldMetadataItem } = useRecordGroups({
|
||||
objectNameSingular,
|
||||
});
|
||||
const recordGroupFieldMetadata = useRecoilComponentValueV2(
|
||||
recordGroupFieldMetadataComponentState,
|
||||
);
|
||||
|
||||
const { handleVisibilityChange: handleRecordGroupVisibilityChange } =
|
||||
useRecordGroupVisibility({
|
||||
viewBarId: recordIndexId,
|
||||
viewType,
|
||||
});
|
||||
|
||||
const setNavigationMemorizedUrl = useSetRecoilState(
|
||||
@ -52,11 +45,11 @@ export const useRecordGroupActions = ({
|
||||
const navigateToSelectSettings = useCallback(() => {
|
||||
setNavigationMemorizedUrl(location.pathname + location.search);
|
||||
|
||||
if (!isDefined(viewGroupFieldMetadataItem)) {
|
||||
throw new Error('viewGroupFieldMetadataItem is not a non-empty string');
|
||||
if (!isDefined(recordGroupFieldMetadata)) {
|
||||
throw new Error('recordGroupFieldMetadata is not a non-empty string');
|
||||
}
|
||||
|
||||
const settingsPath = `/settings/objects/${getObjectSlug(objectMetadataItem)}/${getFieldSlug(viewGroupFieldMetadataItem)}`;
|
||||
const settingsPath = `/settings/objects/${getObjectSlug(objectMetadataItem)}/${getFieldSlug(recordGroupFieldMetadata)}`;
|
||||
|
||||
navigate(settingsPath);
|
||||
}, [
|
||||
@ -65,7 +58,7 @@ export const useRecordGroupActions = ({
|
||||
location.search,
|
||||
navigate,
|
||||
objectMetadataItem,
|
||||
viewGroupFieldMetadataItem,
|
||||
recordGroupFieldMetadata,
|
||||
]);
|
||||
|
||||
const recordGroupActions: RecordGroupAction[] = useMemo(
|
||||
|
||||
@ -1,59 +1,89 @@
|
||||
import { OnDragEndResponder } from '@hello-pangea/dnd';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { useRecordGroups } from '@/object-record/record-group/hooks/useRecordGroups';
|
||||
import { recordGroupDefinitionsComponentState } from '@/object-record/record-group/states/recordGroupDefinitionsComponentState';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { useSetRecordGroup } from '@/object-record/record-group/hooks/useSetRecordGroup';
|
||||
import { recordGroupDefinitionFamilyState } from '@/object-record/record-group/states/recordGroupDefinitionFamilyState';
|
||||
import { visibleRecordGroupIdsComponentSelector } from '@/object-record/record-group/states/selectors/visibleRecordGroupIdsComponentSelector';
|
||||
import { RecordGroupDefinition } from '@/object-record/record-group/types/RecordGroupDefinition';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue';
|
||||
import { useSaveCurrentViewGroups } from '@/views/hooks/useSaveCurrentViewGroups';
|
||||
import { mapRecordGroupDefinitionsToViewGroups } from '@/views/utils/mapRecordGroupDefinitionsToViewGroups';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { moveArrayItem } from '~/utils/array/moveArrayItem';
|
||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
type UseRecordGroupHandlersParams = {
|
||||
objectNameSingular: string;
|
||||
viewBarId: string;
|
||||
};
|
||||
|
||||
export const useRecordGroupReorder = ({
|
||||
objectNameSingular,
|
||||
viewBarId,
|
||||
}: UseRecordGroupHandlersParams) => {
|
||||
const setRecordGroupDefinitions = useSetRecoilComponentStateV2(
|
||||
recordGroupDefinitionsComponentState,
|
||||
);
|
||||
const setRecordGroup = useSetRecordGroup(viewBarId);
|
||||
|
||||
const { visibleRecordGroups } = useRecordGroups({
|
||||
objectNameSingular: objectNameSingular,
|
||||
});
|
||||
const visibleRecordGroupIdsSelector = useRecoilComponentCallbackStateV2(
|
||||
visibleRecordGroupIdsComponentSelector,
|
||||
);
|
||||
|
||||
const { saveViewGroups } = useSaveCurrentViewGroups(viewBarId);
|
||||
|
||||
const handleOrderChange: OnDragEndResponder = useCallback(
|
||||
(result) => {
|
||||
if (!result.destination) {
|
||||
return;
|
||||
}
|
||||
const handleOrderChange: OnDragEndResponder = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
(result) => {
|
||||
if (!result.destination) {
|
||||
return;
|
||||
}
|
||||
|
||||
const reorderedVisibleBoardGroups = moveArrayItem(visibleRecordGroups, {
|
||||
fromIndex: result.source.index - 1,
|
||||
toIndex: result.destination.index - 1,
|
||||
});
|
||||
const visibleRecordGroupIds = getSnapshotValue(
|
||||
snapshot,
|
||||
visibleRecordGroupIdsSelector,
|
||||
);
|
||||
|
||||
if (isDeeplyEqual(visibleRecordGroups, reorderedVisibleBoardGroups))
|
||||
return;
|
||||
const reorderedVisibleRecordGroupIds = moveArrayItem(
|
||||
visibleRecordGroupIds,
|
||||
{
|
||||
fromIndex: result.source.index - 1,
|
||||
toIndex: result.destination.index - 1,
|
||||
},
|
||||
);
|
||||
|
||||
const updatedGroups = [...reorderedVisibleBoardGroups].map(
|
||||
(group, index) => ({ ...group, position: index }),
|
||||
);
|
||||
if (
|
||||
isDeeplyEqual(visibleRecordGroupIds, reorderedVisibleRecordGroupIds)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
setRecordGroupDefinitions(updatedGroups);
|
||||
saveViewGroups(mapRecordGroupDefinitionsToViewGroups(updatedGroups));
|
||||
},
|
||||
[saveViewGroups, setRecordGroupDefinitions, visibleRecordGroups],
|
||||
const updatedRecordGroups = reorderedVisibleRecordGroupIds.reduce<
|
||||
RecordGroupDefinition[]
|
||||
>((acc, recordGroupId, index) => {
|
||||
const recordGroupDefinition = getSnapshotValue(
|
||||
snapshot,
|
||||
recordGroupDefinitionFamilyState(recordGroupId),
|
||||
);
|
||||
|
||||
if (!isDefined(recordGroupDefinition)) {
|
||||
return acc;
|
||||
}
|
||||
|
||||
return [
|
||||
...acc,
|
||||
{
|
||||
...recordGroupDefinition,
|
||||
position: index,
|
||||
},
|
||||
];
|
||||
}, []);
|
||||
|
||||
setRecordGroup(updatedRecordGroups);
|
||||
saveViewGroups(
|
||||
mapRecordGroupDefinitionsToViewGroups(updatedRecordGroups),
|
||||
);
|
||||
},
|
||||
[saveViewGroups, setRecordGroup, visibleRecordGroupIdsSelector],
|
||||
);
|
||||
|
||||
return {
|
||||
visibleRecordGroups,
|
||||
handleOrderChange,
|
||||
};
|
||||
};
|
||||
|
||||
@ -1,125 +1,113 @@
|
||||
import { useRecordBoardStates } from '@/object-record/record-board/hooks/internal/useRecordBoardStates';
|
||||
import { recordGroupDefinitionsComponentState } from '@/object-record/record-group/states/recordGroupDefinitionsComponentState';
|
||||
import { recordGroupDefinitionFamilyState } from '@/object-record/record-group/states/recordGroupDefinitionFamilyState';
|
||||
import { recordGroupIdsComponentState } from '@/object-record/record-group/states/recordGroupIdsComponentState';
|
||||
import { RecordGroupDefinition } from '@/object-record/record-group/types/RecordGroupDefinition';
|
||||
import { recordIndexRecordGroupHideComponentState } from '@/object-record/record-index/states/recordIndexRecordGroupHideComponentState';
|
||||
import { tableRowIdsByGroupComponentFamilyState } from '@/object-record/record-table/states/tableRowIdsByGroupComponentFamilyState';
|
||||
import { recordIndexRowIdsByGroupComponentFamilyState } from '@/object-record/record-index/states/recordIndexRowIdsByGroupComponentFamilyState';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue';
|
||||
import { useSaveCurrentViewGroups } from '@/views/hooks/useSaveCurrentViewGroups';
|
||||
import { ViewType } from '@/views/types/ViewType';
|
||||
import { mapRecordGroupDefinitionsToViewGroups } from '@/views/utils/mapRecordGroupDefinitionsToViewGroups';
|
||||
import { recordGroupDefinitionToViewGroup } from '@/views/utils/recordGroupDefinitionToViewGroup';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
type UseRecordGroupVisibilityParams = {
|
||||
viewBarId: string;
|
||||
viewType: ViewType;
|
||||
};
|
||||
|
||||
export const useRecordGroupVisibility = ({
|
||||
viewBarId,
|
||||
viewType,
|
||||
}: UseRecordGroupVisibilityParams) => {
|
||||
const recordGroupDefinitionsState = useRecoilComponentCallbackStateV2(
|
||||
recordGroupDefinitionsComponentState,
|
||||
const recordIndexRecordGroupIdsState = useRecoilComponentCallbackStateV2(
|
||||
recordGroupIdsComponentState,
|
||||
);
|
||||
|
||||
const tableRowIdsByGroupFamilyState = useRecoilComponentCallbackStateV2(
|
||||
tableRowIdsByGroupComponentFamilyState,
|
||||
const recordIndexRowIdsByGroupFamilyState = useRecoilComponentCallbackStateV2(
|
||||
recordIndexRowIdsByGroupComponentFamilyState,
|
||||
viewBarId,
|
||||
);
|
||||
|
||||
const { recordIdsByColumnIdFamilyState } = useRecordBoardStates(viewBarId);
|
||||
|
||||
const objectOptionsDropdownRecordGroupHideState =
|
||||
useRecoilComponentCallbackStateV2(recordIndexRecordGroupHideComponentState);
|
||||
|
||||
const { saveViewGroups } = useSaveCurrentViewGroups(viewBarId);
|
||||
const { saveViewGroup, saveViewGroups } = useSaveCurrentViewGroups(viewBarId);
|
||||
|
||||
const handleVisibilityChange = useRecoilCallback(
|
||||
({ snapshot, set }) =>
|
||||
async (updatedRecordGroupDefinition: RecordGroupDefinition) => {
|
||||
const recordGroupDefinitions = getSnapshotValue(
|
||||
snapshot,
|
||||
recordGroupDefinitionsState,
|
||||
({ set }) =>
|
||||
async (updatedRecordGroup: RecordGroupDefinition) => {
|
||||
set(
|
||||
recordGroupDefinitionFamilyState(updatedRecordGroup.id),
|
||||
updatedRecordGroup,
|
||||
);
|
||||
|
||||
const updatedRecordGroupDefinitions = recordGroupDefinitions.map(
|
||||
(groupDefinition) =>
|
||||
groupDefinition.id === updatedRecordGroupDefinition.id
|
||||
? {
|
||||
...groupDefinition,
|
||||
isVisible: !groupDefinition.isVisible,
|
||||
}
|
||||
: groupDefinition,
|
||||
);
|
||||
|
||||
set(recordGroupDefinitionsState, updatedRecordGroupDefinitions);
|
||||
|
||||
saveViewGroups(
|
||||
mapRecordGroupDefinitionsToViewGroups(updatedRecordGroupDefinitions),
|
||||
);
|
||||
saveViewGroup(recordGroupDefinitionToViewGroup(updatedRecordGroup));
|
||||
|
||||
// If visibility is manually toggled, we should reset the hideEmptyRecordGroup state
|
||||
set(objectOptionsDropdownRecordGroupHideState, false);
|
||||
},
|
||||
[
|
||||
objectOptionsDropdownRecordGroupHideState,
|
||||
recordGroupDefinitionsState,
|
||||
saveViewGroups,
|
||||
],
|
||||
[saveViewGroup, objectOptionsDropdownRecordGroupHideState],
|
||||
);
|
||||
|
||||
const handleHideEmptyRecordGroupChange = useRecoilCallback(
|
||||
({ snapshot, set }) =>
|
||||
async () => {
|
||||
const recordGroupDefinitions = getSnapshotValue(
|
||||
const updatedRecordGroupDefinitions: RecordGroupDefinition[] = [];
|
||||
const recordGroupIds = getSnapshotValue(
|
||||
snapshot,
|
||||
recordGroupDefinitionsState,
|
||||
recordIndexRecordGroupIdsState,
|
||||
);
|
||||
|
||||
const currentHideState = getSnapshotValue(
|
||||
snapshot,
|
||||
objectOptionsDropdownRecordGroupHideState,
|
||||
);
|
||||
const newHideState = !currentHideState;
|
||||
|
||||
set(objectOptionsDropdownRecordGroupHideState, !currentHideState);
|
||||
set(objectOptionsDropdownRecordGroupHideState, newHideState);
|
||||
|
||||
const updatedRecordGroupDefinitions = recordGroupDefinitions.map(
|
||||
(recordGroup) => {
|
||||
// TODO: Maybe we can improve that and only use one state for both table and board
|
||||
const recordGroupRowIds =
|
||||
viewType === ViewType.Table
|
||||
? getSnapshotValue(
|
||||
snapshot,
|
||||
tableRowIdsByGroupFamilyState(recordGroup.id),
|
||||
)
|
||||
: getSnapshotValue(
|
||||
snapshot,
|
||||
recordIdsByColumnIdFamilyState(recordGroup.id),
|
||||
);
|
||||
for (const recordGroupId of recordGroupIds) {
|
||||
const recordGroup = getSnapshotValue(
|
||||
snapshot,
|
||||
recordGroupDefinitionFamilyState(recordGroupId),
|
||||
);
|
||||
|
||||
if (recordGroupRowIds.length > 0) {
|
||||
return recordGroup;
|
||||
}
|
||||
if (!isDefined(recordGroup)) {
|
||||
throw new Error(
|
||||
`Record group with id ${recordGroupId} not found in snapshot`,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
...recordGroup,
|
||||
isVisible: currentHideState,
|
||||
};
|
||||
},
|
||||
);
|
||||
const recordGroupRowIds = getSnapshotValue(
|
||||
snapshot,
|
||||
recordIndexRowIdsByGroupFamilyState(recordGroupId),
|
||||
);
|
||||
|
||||
if (recordGroupRowIds.length > 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const updatedRecordGroup = {
|
||||
...recordGroup,
|
||||
isVisible: !newHideState,
|
||||
};
|
||||
|
||||
set(
|
||||
recordGroupDefinitionFamilyState(recordGroupId),
|
||||
updatedRecordGroup,
|
||||
);
|
||||
|
||||
updatedRecordGroupDefinitions.push(updatedRecordGroup);
|
||||
}
|
||||
|
||||
saveViewGroups(
|
||||
mapRecordGroupDefinitionsToViewGroups(updatedRecordGroupDefinitions),
|
||||
);
|
||||
},
|
||||
[
|
||||
recordGroupDefinitionsState,
|
||||
recordIndexRecordGroupIdsState,
|
||||
objectOptionsDropdownRecordGroupHideState,
|
||||
saveViewGroups,
|
||||
viewType,
|
||||
tableRowIdsByGroupFamilyState,
|
||||
recordIdsByColumnIdFamilyState,
|
||||
recordIndexRowIdsByGroupFamilyState,
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
@ -1,58 +0,0 @@
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { recordGroupDefinitionsComponentState } from '@/object-record/record-group/states/recordGroupDefinitionsComponentState';
|
||||
import { sortRecordGroupDefinitions } from '@/object-record/record-group/utils/sortRecordGroupDefinitions';
|
||||
import { recordIndexRecordGroupSortComponentState } from '@/object-record/record-index/states/recordIndexRecordGroupSortComponentState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
|
||||
type UseRecordGroupsParams = {
|
||||
objectNameSingular: string;
|
||||
};
|
||||
|
||||
export const useRecordGroups = ({
|
||||
objectNameSingular,
|
||||
}: UseRecordGroupsParams) => {
|
||||
const recordGroupDefinitions = useRecoilComponentValueV2(
|
||||
recordGroupDefinitionsComponentState,
|
||||
);
|
||||
|
||||
const recordGroupSort = useRecoilComponentValueV2(
|
||||
recordIndexRecordGroupSortComponentState,
|
||||
);
|
||||
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const viewGroupFieldMetadataItem = useMemo(() => {
|
||||
if (recordGroupDefinitions.length === 0) return null;
|
||||
// We're assuming that all groups have the same fieldMetadataId for now
|
||||
const fieldMetadataId =
|
||||
'fieldMetadataId' in recordGroupDefinitions[0]
|
||||
? recordGroupDefinitions[0].fieldMetadataId
|
||||
: null;
|
||||
|
||||
if (!fieldMetadataId) return null;
|
||||
|
||||
return objectMetadataItem.fields.find(
|
||||
(field) => field.id === fieldMetadataId,
|
||||
);
|
||||
}, [objectMetadataItem, recordGroupDefinitions]);
|
||||
|
||||
const visibleRecordGroups = useMemo(
|
||||
() => sortRecordGroupDefinitions(recordGroupDefinitions, recordGroupSort),
|
||||
[recordGroupDefinitions, recordGroupSort],
|
||||
);
|
||||
|
||||
const hiddenRecordGroups = useMemo(
|
||||
() => recordGroupDefinitions.filter((boardGroup) => !boardGroup.isVisible),
|
||||
[recordGroupDefinitions],
|
||||
);
|
||||
|
||||
return {
|
||||
hiddenRecordGroups,
|
||||
visibleRecordGroups,
|
||||
viewGroupFieldMetadataItem,
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,83 @@
|
||||
import { recordGroupDefinitionFamilyState } from '@/object-record/record-group/states/recordGroupDefinitionFamilyState';
|
||||
import { recordGroupFieldMetadataComponentState } from '@/object-record/record-group/states/recordGroupFieldMetadataComponentState';
|
||||
import { recordGroupIdsComponentState } from '@/object-record/record-group/states/recordGroupIdsComponentState';
|
||||
import { RecordGroupDefinition } from '@/object-record/record-group/types/RecordGroupDefinition';
|
||||
import { RecordIndexRootPropsContext } from '@/object-record/record-index/contexts/RecordIndexRootPropsContext';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue';
|
||||
import { useContext } from 'react';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export const useSetRecordGroup = (viewId?: string) => {
|
||||
const { objectMetadataItem } = useContext(RecordIndexRootPropsContext);
|
||||
|
||||
const recordIndexRecordGroupIdsState = useRecoilComponentCallbackStateV2(
|
||||
recordGroupIdsComponentState,
|
||||
viewId,
|
||||
);
|
||||
|
||||
const recordGroupFieldMetadataState = useRecoilComponentCallbackStateV2(
|
||||
recordGroupFieldMetadataComponentState,
|
||||
viewId,
|
||||
);
|
||||
|
||||
return useRecoilCallback(
|
||||
({ snapshot, set }) =>
|
||||
(recordGroups: RecordGroupDefinition[]) => {
|
||||
if (recordGroups.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentRecordGroupId = getSnapshotValue(
|
||||
snapshot,
|
||||
recordIndexRecordGroupIdsState,
|
||||
);
|
||||
const fieldMetadataId = recordGroups[0].fieldMetadataId;
|
||||
const fieldMetadata = objectMetadataItem.fields.find(
|
||||
(field) => field.id === fieldMetadataId,
|
||||
);
|
||||
const currentFieldMetadata = getSnapshotValue(
|
||||
snapshot,
|
||||
recordGroupFieldMetadataState,
|
||||
);
|
||||
|
||||
// Set the field metadata linked to the record groups
|
||||
if (
|
||||
isDefined(fieldMetadata) &&
|
||||
!isDeeplyEqual(fieldMetadata, currentFieldMetadata)
|
||||
) {
|
||||
set(recordGroupFieldMetadataState, fieldMetadata);
|
||||
}
|
||||
|
||||
// Set the record groups by id
|
||||
recordGroups.forEach((recordGroup) => {
|
||||
const existingRecordGroup = getSnapshotValue(
|
||||
snapshot,
|
||||
recordGroupDefinitionFamilyState(recordGroup.id),
|
||||
);
|
||||
|
||||
if (isDeeplyEqual(existingRecordGroup, recordGroup)) {
|
||||
return;
|
||||
}
|
||||
|
||||
set(recordGroupDefinitionFamilyState(recordGroup.id), recordGroup);
|
||||
});
|
||||
|
||||
const recordGroupIds = recordGroups.map(({ id }) => id);
|
||||
|
||||
if (isDeeplyEqual(currentRecordGroupId, recordGroupIds)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the record group ids
|
||||
set(recordIndexRecordGroupIdsState, recordGroupIds);
|
||||
},
|
||||
[
|
||||
objectMetadataItem.fields,
|
||||
recordGroupFieldMetadataState,
|
||||
recordIndexRecordGroupIdsState,
|
||||
],
|
||||
);
|
||||
};
|
||||
@ -0,0 +1,10 @@
|
||||
import { RecordGroupDefinition } from '@/object-record/record-group/types/RecordGroupDefinition';
|
||||
import { atomFamily } from 'recoil';
|
||||
|
||||
export const recordGroupDefinitionFamilyState = atomFamily<
|
||||
RecordGroupDefinition | undefined,
|
||||
RecordGroupDefinition['id']
|
||||
>({
|
||||
key: 'recordGroupDefinitionFamilyState',
|
||||
default: undefined,
|
||||
});
|
||||
@ -0,0 +1,11 @@
|
||||
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
|
||||
export const recordGroupFieldMetadataComponentState = createComponentStateV2<
|
||||
FieldMetadataItem | undefined
|
||||
>({
|
||||
key: 'recordGroupFieldMetadataComponentState',
|
||||
defaultValue: undefined,
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
});
|
||||
@ -2,10 +2,10 @@ import { RecordGroupDefinition } from '@/object-record/record-group/types/Record
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
|
||||
export const recordGroupDefinitionsComponentState = createComponentStateV2<
|
||||
RecordGroupDefinition[]
|
||||
export const recordGroupIdsComponentState = createComponentStateV2<
|
||||
RecordGroupDefinition['id'][]
|
||||
>({
|
||||
key: 'recordGroupDefinitionsComponentState',
|
||||
key: 'recordGroupIdsComponentState',
|
||||
defaultValue: [],
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
});
|
||||
@ -1,21 +1,21 @@
|
||||
import { recordGroupDefinitionsComponentState } from '@/object-record/record-group/states/recordGroupDefinitionsComponentState';
|
||||
import { recordGroupIdsComponentState } from '@/object-record/record-group/states/recordGroupIdsComponentState';
|
||||
|
||||
import { createComponentSelectorV2 } from '@/ui/utilities/state/component-state/utils/createComponentSelectorV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
|
||||
export const hasRecordGroupDefinitionsComponentSelector =
|
||||
export const hasRecordGroupsComponentSelector =
|
||||
createComponentSelectorV2<boolean>({
|
||||
key: 'hasRecordGroupDefinitionsComponentSelector',
|
||||
key: 'hasRecordGroupsComponentSelector',
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
get:
|
||||
({ instanceId }) =>
|
||||
({ get }) => {
|
||||
const recordGroupDefinitions = get(
|
||||
recordGroupDefinitionsComponentState.atomFamily({
|
||||
const recordGroupIds = get(
|
||||
recordGroupIdsComponentState.atomFamily({
|
||||
instanceId,
|
||||
}),
|
||||
);
|
||||
|
||||
return recordGroupDefinitions.length > 0;
|
||||
return recordGroupIds.length > 0;
|
||||
},
|
||||
});
|
||||
@ -0,0 +1,34 @@
|
||||
import { recordGroupDefinitionFamilyState } from '@/object-record/record-group/states/recordGroupDefinitionFamilyState';
|
||||
import { recordGroupIdsComponentState } from '@/object-record/record-group/states/recordGroupIdsComponentState';
|
||||
|
||||
import { createComponentSelectorV2 } from '@/ui/utilities/state/component-state/utils/createComponentSelectorV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export const hiddenRecordGroupIdsComponentSelector = createComponentSelectorV2<
|
||||
string[]
|
||||
>({
|
||||
key: 'hiddenRecordGroupIdsComponentSelector',
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
get:
|
||||
({ instanceId }) =>
|
||||
({ get }) => {
|
||||
const recordGroupIds = get(
|
||||
recordGroupIdsComponentState.atomFamily({
|
||||
instanceId,
|
||||
}),
|
||||
);
|
||||
|
||||
return recordGroupIds.filter((recordGroupId) => {
|
||||
const recordGroupDefinition = get(
|
||||
recordGroupDefinitionFamilyState(recordGroupId),
|
||||
);
|
||||
|
||||
if (!isDefined(recordGroupDefinition)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !recordGroupDefinition.isVisible;
|
||||
});
|
||||
},
|
||||
});
|
||||
@ -0,0 +1,37 @@
|
||||
import { recordGroupDefinitionFamilyState } from '@/object-record/record-group/states/recordGroupDefinitionFamilyState';
|
||||
import { recordGroupIdsComponentState } from '@/object-record/record-group/states/recordGroupIdsComponentState';
|
||||
import { RecordGroupDefinition } from '@/object-record/record-group/types/RecordGroupDefinition';
|
||||
|
||||
import { createComponentSelectorV2 } from '@/ui/utilities/state/component-state/utils/createComponentSelectorV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export const recordGroupDefinitionsComponentSelector =
|
||||
createComponentSelectorV2<RecordGroupDefinition[]>({
|
||||
key: 'recordGroupDefinitionsComponentSelector',
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
get:
|
||||
({ instanceId }) =>
|
||||
({ get }) => {
|
||||
const recordGroupIds = get(
|
||||
recordGroupIdsComponentState.atomFamily({
|
||||
instanceId,
|
||||
}),
|
||||
);
|
||||
|
||||
return recordGroupIds.reduce<RecordGroupDefinition[]>(
|
||||
(acc, recordGroupId) => {
|
||||
const recordGroupDefinition = get(
|
||||
recordGroupDefinitionFamilyState(recordGroupId),
|
||||
);
|
||||
|
||||
if (!isDefined(recordGroupDefinition)) {
|
||||
return acc;
|
||||
}
|
||||
|
||||
return [...acc, recordGroupDefinition];
|
||||
},
|
||||
[],
|
||||
);
|
||||
},
|
||||
});
|
||||
@ -0,0 +1,63 @@
|
||||
import { recordGroupDefinitionFamilyState } from '@/object-record/record-group/states/recordGroupDefinitionFamilyState';
|
||||
import { recordGroupIdsComponentState } from '@/object-record/record-group/states/recordGroupIdsComponentState';
|
||||
import { RecordGroupDefinition } from '@/object-record/record-group/types/RecordGroupDefinition';
|
||||
import { RecordGroupSort } from '@/object-record/record-group/types/RecordGroupSort';
|
||||
import { sortedInsert } from '@/object-record/record-group/utils/sortedInsert';
|
||||
import { recordIndexRecordGroupSortComponentState } from '@/object-record/record-index/states/recordIndexRecordGroupSortComponentState';
|
||||
|
||||
import { createComponentSelectorV2 } from '@/ui/utilities/state/component-state/utils/createComponentSelectorV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export const visibleRecordGroupIdsComponentSelector = createComponentSelectorV2<
|
||||
string[]
|
||||
>({
|
||||
key: 'visibleRecordGroupIdsComponentSelector',
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
get:
|
||||
({ instanceId }) =>
|
||||
({ get }) => {
|
||||
const recordGroupSort = get(
|
||||
recordIndexRecordGroupSortComponentState.atomFamily({
|
||||
instanceId,
|
||||
}),
|
||||
);
|
||||
const recordGroupIds = get(
|
||||
recordGroupIdsComponentState.atomFamily({
|
||||
instanceId,
|
||||
}),
|
||||
);
|
||||
|
||||
const result: RecordGroupDefinition[] = [];
|
||||
|
||||
const comparator = (
|
||||
a: RecordGroupDefinition,
|
||||
b: RecordGroupDefinition,
|
||||
) => {
|
||||
switch (recordGroupSort) {
|
||||
case RecordGroupSort.Alphabetical:
|
||||
return a.title.localeCompare(b.title);
|
||||
case RecordGroupSort.ReverseAlphabetical:
|
||||
return b.title.localeCompare(a.title);
|
||||
case RecordGroupSort.Manual:
|
||||
default:
|
||||
return a.position - b.position;
|
||||
}
|
||||
};
|
||||
|
||||
for (const recordGroupId of recordGroupIds) {
|
||||
const recordGroupDefinition = get(
|
||||
recordGroupDefinitionFamilyState(recordGroupId),
|
||||
);
|
||||
|
||||
if (
|
||||
isDefined(recordGroupDefinition) &&
|
||||
recordGroupDefinition.isVisible
|
||||
) {
|
||||
sortedInsert(result, recordGroupDefinition, comparator);
|
||||
}
|
||||
}
|
||||
|
||||
return result.map(({ id }) => id);
|
||||
},
|
||||
});
|
||||
@ -5,7 +5,7 @@ export const sortRecordGroupDefinitions = (
|
||||
recordGroupDefinitions: RecordGroupDefinition[],
|
||||
recordGroupSort: RecordGroupSort,
|
||||
) => {
|
||||
const visibleGroups = recordGroupDefinitions.filter(
|
||||
const visibleRecordGroups = recordGroupDefinitions.filter(
|
||||
(boardGroup) => boardGroup.isVisible,
|
||||
);
|
||||
|
||||
@ -17,15 +17,15 @@ export const sortRecordGroupDefinitions = (
|
||||
|
||||
switch (recordGroupSort) {
|
||||
case RecordGroupSort.Alphabetical:
|
||||
return visibleGroups.sort((a, b) =>
|
||||
return visibleRecordGroups.sort((a, b) =>
|
||||
compareAlphabetical(a.title.toLowerCase(), b.title.toLowerCase()),
|
||||
);
|
||||
case RecordGroupSort.ReverseAlphabetical:
|
||||
return visibleGroups.sort((a, b) =>
|
||||
return visibleRecordGroups.sort((a, b) =>
|
||||
compareAlphabetical(a.title.toLowerCase(), b.title.toLowerCase(), true),
|
||||
);
|
||||
case RecordGroupSort.Manual:
|
||||
default:
|
||||
return visibleGroups.sort((a, b) => a.position - b.position);
|
||||
return visibleRecordGroups.sort((a, b) => a.position - b.position);
|
||||
}
|
||||
};
|
||||
|
||||
@ -0,0 +1,20 @@
|
||||
export const sortedInsert = <T>(
|
||||
array: T[],
|
||||
item: T,
|
||||
comparator: (a: T, b: T) => number,
|
||||
) => {
|
||||
let low = 0;
|
||||
let high = array.length;
|
||||
|
||||
while (low < high) {
|
||||
const mid = Math.floor((low + high) / 2);
|
||||
|
||||
if (comparator(item, array[mid]) < 0) {
|
||||
high = mid;
|
||||
} else {
|
||||
low = mid + 1;
|
||||
}
|
||||
}
|
||||
|
||||
array.splice(low, 0, item);
|
||||
};
|
||||
@ -5,7 +5,7 @@ import { isRecordBoardFetchingRecordsByColumnFamilyState } from '@/object-record
|
||||
import { recordBoardShouldFetchMoreInColumnComponentFamilyState } from '@/object-record/record-board/states/recordBoardShouldFetchMoreInColumnComponentFamilyState';
|
||||
import { useLoadRecordIndexBoardColumn } from '@/object-record/record-index/hooks/useLoadRecordIndexBoardColumn';
|
||||
import { isRecordIndexBoardColumnLoadingFamilyState } from '@/object-record/states/isRecordBoardColumnLoadingFamilyState';
|
||||
import { getScopeIdFromComponentId } from '@/ui/utilities/recoil-scope/utils/getScopeIdFromComponentId';
|
||||
import { useRecoilComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyStateV2';
|
||||
|
||||
export const RecordIndexBoardColumnLoaderEffect = ({
|
||||
objectNameSingular,
|
||||
@ -18,20 +18,14 @@ export const RecordIndexBoardColumnLoaderEffect = ({
|
||||
boardFieldMetadataId: string | null;
|
||||
columnId: string;
|
||||
}) => {
|
||||
const [shouldFetchMore, setShouldFetchMore] = useRecoilState(
|
||||
recordBoardShouldFetchMoreInColumnComponentFamilyState({
|
||||
scopeId: getScopeIdFromComponentId(recordBoardId),
|
||||
familyKey: columnId,
|
||||
}),
|
||||
const [shouldFetchMore, setShouldFetchMore] = useRecoilComponentFamilyStateV2(
|
||||
recordBoardShouldFetchMoreInColumnComponentFamilyState,
|
||||
columnId,
|
||||
recordBoardId,
|
||||
);
|
||||
|
||||
const [loadingRecordsForThisColumn, setLoadingRecordsForThisColumn] =
|
||||
useRecoilState(
|
||||
isRecordBoardFetchingRecordsByColumnFamilyState({
|
||||
scopeId: getScopeIdFromComponentId(recordBoardId),
|
||||
familyKey: { columnId },
|
||||
}),
|
||||
);
|
||||
useRecoilState(isRecordBoardFetchingRecordsByColumnFamilyState(columnId));
|
||||
|
||||
const { fetchMoreRecords, loading, records, hasNextPage } =
|
||||
useLoadRecordIndexBoardColumn({
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { useRecordBoardStates } from '@/object-record/record-board/hooks/internal/useRecordBoardStates';
|
||||
import { visibleRecordGroupIdsComponentSelector } from '@/object-record/record-group/states/selectors/visibleRecordGroupIdsComponentSelector';
|
||||
import { RecordIndexBoardColumnLoaderEffect } from '@/object-record/record-index/components/RecordIndexBoardColumnLoaderEffect';
|
||||
import { recordIndexKanbanFieldMetadataIdState } from '@/object-record/record-index/states/recordIndexKanbanFieldMetadataIdState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
|
||||
type RecordIndexBoardDataLoaderProps = {
|
||||
objectNameSingular: string;
|
||||
@ -18,6 +19,10 @@ export const RecordIndexBoardDataLoader = ({
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const visibleRecordGroupIds = useRecoilComponentValueV2(
|
||||
visibleRecordGroupIdsComponentSelector,
|
||||
);
|
||||
|
||||
const recordIndexKanbanFieldMetadataId = useRecoilValue(
|
||||
recordIndexKanbanFieldMetadataIdState,
|
||||
);
|
||||
@ -26,18 +31,14 @@ export const RecordIndexBoardDataLoader = ({
|
||||
(field) => field.id === recordIndexKanbanFieldMetadataId,
|
||||
);
|
||||
|
||||
const { columnIdsState } = useRecordBoardStates(recordBoardId);
|
||||
|
||||
const columnIds = useRecoilValue(columnIdsState);
|
||||
|
||||
return (
|
||||
<>
|
||||
{columnIds.map((columnId, index) => (
|
||||
{visibleRecordGroupIds.map((recordGroupId, index) => (
|
||||
<RecordIndexBoardColumnLoaderEffect
|
||||
objectNameSingular={objectNameSingular}
|
||||
boardFieldMetadataId={recordIndexKanbanFieldMetadataId}
|
||||
recordBoardId={recordBoardId}
|
||||
columnId={columnId}
|
||||
columnId={recordGroupId}
|
||||
key={index}
|
||||
/>
|
||||
))}
|
||||
|
||||
@ -1,101 +1,52 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { useRecordBoard } from '@/object-record/record-board/hooks/useRecordBoard';
|
||||
import { recordGroupDefinitionsComponentState } from '@/object-record/record-group/states/recordGroupDefinitionsComponentState';
|
||||
import { isRecordBoardCompactModeActiveComponentState } from '@/object-record/record-board/states/isRecordBoardCompactModeActiveComponentState';
|
||||
import { recordBoardFieldDefinitionsComponentState } from '@/object-record/record-board/states/recordBoardFieldDefinitionsComponentState';
|
||||
import { recordBoardSelectedRecordIdsComponentSelector } from '@/object-record/record-board/states/selectors/recordBoardSelectedRecordIdsComponentSelector';
|
||||
import { recordIndexFieldDefinitionsState } from '@/object-record/record-index/states/recordIndexFieldDefinitionsState';
|
||||
import { recordIndexIsCompactModeActiveState } from '@/object-record/record-index/states/recordIndexIsCompactModeActiveState';
|
||||
import { recordIndexKanbanFieldMetadataIdState } from '@/object-record/record-index/states/recordIndexKanbanFieldMetadataIdState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
type RecordIndexBoardDataLoaderEffectProps = {
|
||||
objectNameSingular: string;
|
||||
recordBoardId: string;
|
||||
};
|
||||
|
||||
export const RecordIndexBoardDataLoaderEffect = ({
|
||||
objectNameSingular,
|
||||
recordBoardId,
|
||||
}: RecordIndexBoardDataLoaderEffectProps) => {
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const recordIndexFieldDefinitions = useRecoilValue(
|
||||
recordIndexFieldDefinitionsState,
|
||||
);
|
||||
|
||||
const recordGroupDefinitions = useRecoilComponentValueV2(
|
||||
recordGroupDefinitionsComponentState,
|
||||
);
|
||||
|
||||
const recordIndexKanbanFieldMetadataId = useRecoilValue(
|
||||
recordIndexKanbanFieldMetadataIdState,
|
||||
);
|
||||
|
||||
const recordIndexIsCompactModeActive = useRecoilValue(
|
||||
recordIndexIsCompactModeActiveState,
|
||||
);
|
||||
|
||||
const { isCompactModeActiveState } = useRecordBoard(recordBoardId);
|
||||
const setRecordBoardFieldDefinitions = useSetRecoilComponentStateV2(
|
||||
recordBoardFieldDefinitionsComponentState,
|
||||
recordBoardId,
|
||||
);
|
||||
|
||||
const setIsCompactModeActive = useSetRecoilState(isCompactModeActiveState);
|
||||
const selectedRecordIds = useRecoilComponentValueV2(
|
||||
recordBoardSelectedRecordIdsComponentSelector,
|
||||
recordBoardId,
|
||||
);
|
||||
|
||||
const setIsCompactModeActive = useSetRecoilComponentStateV2(
|
||||
isRecordBoardCompactModeActiveComponentState,
|
||||
recordBoardId,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setIsCompactModeActive(recordIndexIsCompactModeActive);
|
||||
}, [recordIndexIsCompactModeActive, setIsCompactModeActive]);
|
||||
|
||||
const {
|
||||
setColumns,
|
||||
setObjectSingularName,
|
||||
selectedRecordIdsSelector,
|
||||
setFieldDefinitions,
|
||||
setKanbanFieldMetadataName,
|
||||
} = useRecordBoard(recordBoardId);
|
||||
|
||||
useEffect(() => {
|
||||
setFieldDefinitions(recordIndexFieldDefinitions);
|
||||
}, [recordIndexFieldDefinitions, setFieldDefinitions]);
|
||||
|
||||
useEffect(() => {
|
||||
setObjectSingularName(objectNameSingular);
|
||||
}, [objectNameSingular, setObjectSingularName]);
|
||||
|
||||
useEffect(() => {
|
||||
setColumns(recordGroupDefinitions);
|
||||
}, [recordGroupDefinitions, setColumns]);
|
||||
|
||||
// TODO: Remove this duplicate useEffect by ensuring it's not here because
|
||||
// We want it to be triggered by a change of objectMetadataItem, which would be an anti-pattern
|
||||
// As it is an unnecessary dependency
|
||||
useEffect(() => {
|
||||
setFieldDefinitions(recordIndexFieldDefinitions);
|
||||
}, [objectMetadataItem, setFieldDefinitions, recordIndexFieldDefinitions]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isDefined(recordIndexKanbanFieldMetadataId)) {
|
||||
const kanbanFieldMetadataName = objectMetadataItem?.fields.find(
|
||||
(field) =>
|
||||
field.type === FieldMetadataType.Select &&
|
||||
field.id === recordIndexKanbanFieldMetadataId,
|
||||
)?.name;
|
||||
|
||||
if (isDefined(kanbanFieldMetadataName)) {
|
||||
setKanbanFieldMetadataName(kanbanFieldMetadataName);
|
||||
}
|
||||
}
|
||||
}, [
|
||||
objectMetadataItem,
|
||||
recordIndexKanbanFieldMetadataId,
|
||||
setKanbanFieldMetadataName,
|
||||
]);
|
||||
|
||||
const selectedRecordIds = useRecoilValue(selectedRecordIdsSelector());
|
||||
setRecordBoardFieldDefinitions(recordIndexFieldDefinitions);
|
||||
}, [recordIndexFieldDefinitions, setRecordBoardFieldDefinitions]);
|
||||
|
||||
const setContextStoreTargetedRecords = useSetRecoilComponentStateV2(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
|
||||
@ -24,11 +24,9 @@ import { SpreadsheetImportProvider } from '@/spreadsheet-import/provider/compone
|
||||
|
||||
import { RecordIndexActionMenu } from '@/action-menu/components/RecordIndexActionMenu';
|
||||
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
import { useRecordBoard } from '@/object-record/record-board/hooks/useRecordBoard';
|
||||
import { recordGroupDefinitionsComponentState } from '@/object-record/record-group/states/recordGroupDefinitionsComponentState';
|
||||
import { useSetRecordGroup } from '@/object-record/record-group/hooks/useSetRecordGroup';
|
||||
import { RecordIndexFiltersToContextStoreEffect } from '@/object-record/record-index/components/RecordIndexFiltersToContextStoreEffect';
|
||||
import { recordIndexViewFilterGroupsState } from '@/object-record/record-index/states/recordIndexViewFilterGroupsState';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { ViewBar } from '@/views/components/ViewBar';
|
||||
import { ViewField } from '@/views/types/ViewField';
|
||||
@ -38,7 +36,7 @@ import { mapViewFieldsToColumnDefinitions } from '@/views/utils/mapViewFieldsToC
|
||||
import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters';
|
||||
import { mapViewGroupsToRecordGroupDefinitions } from '@/views/utils/mapViewGroupsToRecordGroupDefinitions';
|
||||
import { mapViewSortsToSorts } from '@/views/utils/mapViewSortsToSorts';
|
||||
import { useContext } from 'react';
|
||||
import { useCallback, useContext } from 'react';
|
||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
@ -68,9 +66,7 @@ export const RecordIndexContainer = () => {
|
||||
objectNameSingular,
|
||||
} = useContext(RecordIndexRootPropsContext);
|
||||
|
||||
const recordGroupDefinitionsCallbackState = useRecoilComponentCallbackStateV2(
|
||||
recordGroupDefinitionsComponentState,
|
||||
);
|
||||
const setRecordGroup = useSetRecordGroup(recordIndexId);
|
||||
|
||||
const { columnDefinitions, filterDefinitions, sortDefinitions } =
|
||||
useColumnDefinitionsFromFieldMetadata(objectMetadataItem);
|
||||
@ -96,8 +92,6 @@ export const RecordIndexContainer = () => {
|
||||
recordTableId: recordIndexId,
|
||||
});
|
||||
|
||||
const { setColumns } = useRecordBoard(recordIndexId);
|
||||
|
||||
const onViewFieldsChange = useRecoilCallback(
|
||||
({ set, snapshot }) =>
|
||||
(viewFields: ViewField[]) => {
|
||||
@ -124,30 +118,16 @@ export const RecordIndexContainer = () => {
|
||||
[columnDefinitions, setTableColumns],
|
||||
);
|
||||
|
||||
const onViewGroupsChange = useRecoilCallback(
|
||||
({ set, snapshot }) =>
|
||||
(viewGroups: ViewGroup[]) => {
|
||||
const newGroupDefinitions = mapViewGroupsToRecordGroupDefinitions({
|
||||
objectMetadataItem,
|
||||
viewGroups,
|
||||
});
|
||||
const onViewGroupsChange = useCallback(
|
||||
(viewGroups: ViewGroup[]) => {
|
||||
const newGroupDefinitions = mapViewGroupsToRecordGroupDefinitions({
|
||||
objectMetadataItem,
|
||||
viewGroups,
|
||||
});
|
||||
|
||||
setColumns(newGroupDefinitions);
|
||||
|
||||
const existingRecordIndexGroupDefinitions = snapshot
|
||||
.getLoadable(recordGroupDefinitionsCallbackState)
|
||||
.getValue();
|
||||
|
||||
if (
|
||||
!isDeeplyEqual(
|
||||
existingRecordIndexGroupDefinitions,
|
||||
newGroupDefinitions,
|
||||
)
|
||||
) {
|
||||
set(recordGroupDefinitionsCallbackState, newGroupDefinitions);
|
||||
}
|
||||
},
|
||||
[objectMetadataItem, recordGroupDefinitionsCallbackState, setColumns],
|
||||
setRecordGroup(newGroupDefinitions);
|
||||
},
|
||||
[objectMetadataItem, setRecordGroup],
|
||||
);
|
||||
|
||||
const setContextStoreTargetedRecordsRule = useSetRecoilComponentStateV2(
|
||||
@ -229,10 +209,7 @@ export const RecordIndexContainer = () => {
|
||||
objectNameSingular={objectNameSingular}
|
||||
recordBoardId={recordIndexId}
|
||||
/>
|
||||
<RecordIndexBoardDataLoaderEffect
|
||||
objectNameSingular={objectNameSingular}
|
||||
recordBoardId={recordIndexId}
|
||||
/>
|
||||
<RecordIndexBoardDataLoaderEffect recordBoardId={recordIndexId} />
|
||||
</StyledContainerWithPadding>
|
||||
)}
|
||||
<RecordIndexActionMenu />
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useRecordBoardStates } from '@/object-record/record-board/hooks/internal/useRecordBoardStates';
|
||||
import { useAddNewCard } from '@/object-record/record-board/record-board-column/hooks/useAddNewCard';
|
||||
import { useIsOpportunitiesCompanyFieldDisabled } from '@/object-record/record-board/record-board-column/hooks/useIsOpportunitiesCompanyFieldDisabled';
|
||||
import { recordBoardVisibleFieldDefinitionsComponentSelector } from '@/object-record/record-board/states/selectors/recordBoardVisibleFieldDefinitionsComponentSelector';
|
||||
import { visibleRecordGroupIdsComponentSelector } from '@/object-record/record-group/states/selectors/visibleRecordGroupIdsComponentSelector';
|
||||
import { RecordGroupDefinition } from '@/object-record/record-group/types/RecordGroupDefinition';
|
||||
import { RecordIndexPageKanbanAddMenuItem } from '@/object-record/record-index/components/RecordIndexPageKanbanAddMenuItem';
|
||||
import { RecordIndexRootPropsContext } from '@/object-record/record-index/contexts/RecordIndexRootPropsContext';
|
||||
@ -11,6 +12,7 @@ import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import styled from '@emotion/styled';
|
||||
import { useCallback, useContext } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
@ -32,6 +34,10 @@ export const RecordIndexPageKanbanAddButton = () => {
|
||||
);
|
||||
const { objectMetadataItem } = useObjectMetadataItem({ objectNameSingular });
|
||||
|
||||
const visibleRecordGroupIds = useRecoilComponentValueV2(
|
||||
visibleRecordGroupIdsComponentSelector,
|
||||
);
|
||||
|
||||
const recordIndexKanbanFieldMetadataId = useRecoilValue(
|
||||
recordIndexKanbanFieldMetadataIdState,
|
||||
);
|
||||
@ -42,12 +48,11 @@ export const RecordIndexPageKanbanAddButton = () => {
|
||||
const isOpportunity =
|
||||
objectMetadataItem.nameSingular === CoreObjectNameSingular.Opportunity;
|
||||
|
||||
const { columnIdsState, visibleFieldDefinitionsState } =
|
||||
useRecordBoardStates(recordIndexId);
|
||||
const columnIds = useRecoilValue(columnIdsState);
|
||||
const visibleFieldDefinitions = useRecoilValue(
|
||||
visibleFieldDefinitionsState(),
|
||||
const visibleFieldDefinitions = useRecoilComponentValueV2(
|
||||
recordBoardVisibleFieldDefinitionsComponentSelector,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
const labelIdentifierField = visibleFieldDefinitions.find(
|
||||
(field) => field.isLabelIdentifier,
|
||||
);
|
||||
@ -101,11 +106,10 @@ export const RecordIndexPageKanbanAddButton = () => {
|
||||
dropdownComponents={
|
||||
<StyledDropDownMenu>
|
||||
<StyledDropdownMenuItemsContainer>
|
||||
{columnIds.map((columnId) => (
|
||||
{visibleRecordGroupIds.map((recordGroupId) => (
|
||||
<RecordIndexPageKanbanAddMenuItem
|
||||
key={columnId}
|
||||
columnId={columnId}
|
||||
recordIndexId={recordIndexId}
|
||||
key={recordGroupId}
|
||||
columnId={recordGroupId}
|
||||
onItemClick={handleItemClick}
|
||||
/>
|
||||
))}
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import { recordGroupDefinitionFamilyState } from '@/object-record/record-group/states/recordGroupDefinitionFamilyState';
|
||||
import { RecordGroupDefinitionType } from '@/object-record/record-group/types/RecordGroupDefinition';
|
||||
import { useRecordIndexPageKanbanAddMenuItem } from '@/object-record/record-index/hooks/useRecordIndexPageKanbanAddMenuItem';
|
||||
import styled from '@emotion/styled';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { MenuItem, Tag } from 'twenty-ui';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
const StyledMenuItem = styled(MenuItem)`
|
||||
width: calc(100% - 2 * var(--horizontal-padding));
|
||||
@ -9,20 +11,18 @@ const StyledMenuItem = styled(MenuItem)`
|
||||
|
||||
type RecordIndexPageKanbanAddMenuItemProps = {
|
||||
columnId: string;
|
||||
recordIndexId: string;
|
||||
onItemClick: (columnDefinition: any) => void;
|
||||
};
|
||||
|
||||
export const RecordIndexPageKanbanAddMenuItem = ({
|
||||
columnId,
|
||||
recordIndexId,
|
||||
onItemClick,
|
||||
}: RecordIndexPageKanbanAddMenuItemProps) => {
|
||||
const { columnDefinition } = useRecordIndexPageKanbanAddMenuItem(
|
||||
recordIndexId,
|
||||
columnId,
|
||||
const recordGroupDefinition = useRecoilValue(
|
||||
recordGroupDefinitionFamilyState(columnId),
|
||||
);
|
||||
if (!columnDefinition) {
|
||||
|
||||
if (!isDefined(recordGroupDefinition)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -31,24 +31,24 @@ export const RecordIndexPageKanbanAddMenuItem = ({
|
||||
text={
|
||||
<Tag
|
||||
variant={
|
||||
columnDefinition.type === RecordGroupDefinitionType.Value
|
||||
recordGroupDefinition.type === RecordGroupDefinitionType.Value
|
||||
? 'solid'
|
||||
: 'outline'
|
||||
}
|
||||
color={
|
||||
columnDefinition.type === RecordGroupDefinitionType.Value
|
||||
? columnDefinition.color
|
||||
recordGroupDefinition.type === RecordGroupDefinitionType.Value
|
||||
? recordGroupDefinition.color
|
||||
: 'transparent'
|
||||
}
|
||||
text={columnDefinition.title}
|
||||
text={recordGroupDefinition.title}
|
||||
weight={
|
||||
columnDefinition.type === RecordGroupDefinitionType.Value
|
||||
recordGroupDefinition.type === RecordGroupDefinitionType.Value
|
||||
? 'regular'
|
||||
: 'medium'
|
||||
}
|
||||
/>
|
||||
}
|
||||
onClick={() => onItemClick(columnDefinition)}
|
||||
onClick={() => onItemClick(recordGroupDefinition)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@ -8,14 +8,12 @@ import {
|
||||
|
||||
import { PERSON_FRAGMENT_WITH_DEPTH_ZERO_RELATIONS } from '@/object-record/hooks/__mocks__/personFragments';
|
||||
import { useObjectOptionsForBoard } from '@/object-record/object-options-dropdown/hooks/useObjectOptionsForBoard';
|
||||
import { useRecordBoard } from '@/object-record/record-board/hooks/useRecordBoard';
|
||||
import { recordBoardKanbanFieldMetadataNameComponentState } from '@/object-record/record-board/states/recordBoardKanbanFieldMetadataNameComponentState';
|
||||
import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState';
|
||||
import { recordGroupFieldMetadataComponentState } from '@/object-record/record-group/states/recordGroupFieldMetadataComponentState';
|
||||
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
|
||||
import { ViewType } from '@/views/types/ViewType';
|
||||
import { MockedResponse } from '@apollo/client/testing';
|
||||
import { expect } from '@storybook/test';
|
||||
import gql from 'graphql-tag';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { getJestMetadataAndApolloMocksAndContextStoreWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndContextStoreWrapper';
|
||||
import { generatedMockObjectMetadataItems } from '~/testing/mock-data/generatedMockObjectMetadataItems';
|
||||
|
||||
@ -232,10 +230,12 @@ describe('useRecordData', () => {
|
||||
const callback = jest.fn();
|
||||
const { result } = renderHook(
|
||||
() => {
|
||||
const kanbanFieldNameState = extractComponentState(
|
||||
recordBoardKanbanFieldMetadataNameComponentState,
|
||||
recordIndexId,
|
||||
);
|
||||
const [recordGroupFieldMetadata, setRecordGroupFieldMetadata] =
|
||||
useRecoilComponentStateV2(
|
||||
recordGroupFieldMetadataComponentState,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
return {
|
||||
tableData: useExportFetchRecords({
|
||||
recordIndexId,
|
||||
@ -246,8 +246,8 @@ describe('useRecordData', () => {
|
||||
delayMs: 0,
|
||||
viewType: ViewType.Kanban,
|
||||
}),
|
||||
useRecordBoardHook: useRecordBoard(recordIndexId),
|
||||
kanbanFieldName: useRecoilValue(kanbanFieldNameState),
|
||||
kanbanFieldName: recordGroupFieldMetadata?.name,
|
||||
setRecordGroupFieldMetadata,
|
||||
kanbanData: useObjectOptionsForBoard({
|
||||
objectNameSingular: objectMetadataItem.nameSingular,
|
||||
recordBoardId: recordIndexId,
|
||||
@ -269,9 +269,7 @@ describe('useRecordData', () => {
|
||||
);
|
||||
|
||||
await act(async () => {
|
||||
result.current.useRecordBoardHook.setKanbanFieldMetadataName(
|
||||
updatedAtFieldMetadataItem?.name,
|
||||
);
|
||||
result.current.setRecordGroupFieldMetadata(updatedAtFieldMetadataItem);
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
@ -322,10 +320,12 @@ describe('useRecordData', () => {
|
||||
const callback = jest.fn();
|
||||
const { result } = renderHook(
|
||||
() => {
|
||||
const kanbanFieldNameState = extractComponentState(
|
||||
recordBoardKanbanFieldMetadataNameComponentState,
|
||||
recordIndexId,
|
||||
);
|
||||
const [recordGroupFieldMetadata, setRecordGroupFieldMetadata] =
|
||||
useRecoilComponentStateV2(
|
||||
recordGroupFieldMetadataComponentState,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
return {
|
||||
tableData: useExportFetchRecords({
|
||||
recordIndexId,
|
||||
@ -336,8 +336,9 @@ describe('useRecordData', () => {
|
||||
delayMs: 0,
|
||||
viewType: ViewType.Table,
|
||||
}),
|
||||
setKanbanFieldName: useRecordBoard(recordIndexId),
|
||||
kanbanFieldName: useRecoilValue(kanbanFieldNameState),
|
||||
objectMetadataItem,
|
||||
kanbanFieldName: recordGroupFieldMetadata?.name,
|
||||
setRecordGroupFieldMetadata,
|
||||
kanbanData: useObjectOptionsForBoard({
|
||||
objectNameSingular: objectMetadataItem.nameSingular,
|
||||
recordBoardId: recordIndexId,
|
||||
@ -351,9 +352,14 @@ describe('useRecordData', () => {
|
||||
);
|
||||
|
||||
await act(async () => {
|
||||
result.current.setKanbanFieldName.setKanbanFieldMetadataName(
|
||||
result.current.kanbanData.hiddenBoardFields[0].metadata.fieldName,
|
||||
);
|
||||
const fieldMetadataItem =
|
||||
result.current.objectMetadataItem?.fields.find(
|
||||
(fieldMetadata) =>
|
||||
fieldMetadata.id ===
|
||||
result.current.kanbanData.hiddenBoardFields[0].fieldMetadataId,
|
||||
);
|
||||
|
||||
result.current.setRecordGroupFieldMetadata(fieldMetadataItem);
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
|
||||
import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
|
||||
@ -13,7 +12,7 @@ import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { useLazyFindManyRecords } from '@/object-record/hooks/useLazyFindManyRecords';
|
||||
import { EXPORT_TABLE_DATA_DEFAULT_PAGE_SIZE } from '@/object-record/object-options-dropdown/constants/ExportTableDataDefaultPageSize';
|
||||
import { useObjectOptionsForBoard } from '@/object-record/object-options-dropdown/hooks/useObjectOptionsForBoard';
|
||||
import { useRecordBoardStates } from '@/object-record/record-board/hooks/internal/useRecordBoardStates';
|
||||
import { recordGroupFieldMetadataComponentState } from '@/object-record/record-group/states/recordGroupFieldMetadataComponentState';
|
||||
import { useFindManyParams } from '@/object-record/record-index/hooks/useLoadRecordIndexTable';
|
||||
import { visibleTableColumnsComponentSelector } from '@/object-record/record-table/states/selectors/visibleTableColumnsComponentSelector';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
@ -68,10 +67,13 @@ export const useExportFetchRecords = ({
|
||||
viewBarId: recordIndexId,
|
||||
});
|
||||
|
||||
const { kanbanFieldMetadataNameState } = useRecordBoardStates(recordIndexId);
|
||||
const kanbanFieldMetadataName = useRecoilValue(kanbanFieldMetadataNameState);
|
||||
const recordGroupFieldMetadata = useRecoilComponentValueV2(
|
||||
recordGroupFieldMetadataComponentState,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
const hiddenKanbanFieldColumn = hiddenBoardFields.find(
|
||||
(column) => column.metadata.fieldName === kanbanFieldMetadataName,
|
||||
(column) => column.metadata.fieldName === recordGroupFieldMetadata?.name,
|
||||
);
|
||||
const columns = useRecoilComponentValueV2(
|
||||
visibleTableColumnsComponentSelector,
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
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 { useSetRecordBoardRecordIds } from '@/object-record/record-board/hooks/useSetRecordBoardRecordIds';
|
||||
import { isRecordBoardCompactModeActiveComponentState } from '@/object-record/record-board/states/isRecordBoardCompactModeActiveComponentState';
|
||||
import { recordBoardFieldDefinitionsComponentState } from '@/object-record/record-board/states/recordBoardFieldDefinitionsComponentState';
|
||||
import { computeViewRecordGqlOperationFilter } from '@/object-record/record-filter/utils/computeViewRecordGqlOperationFilter';
|
||||
import { recordGroupDefinitionsComponentState } from '@/object-record/record-group/states/recordGroupDefinitionsComponentState';
|
||||
import { useRecordBoardRecordGqlFields } from '@/object-record/record-index/hooks/useRecordBoardRecordGqlFields';
|
||||
import { recordIndexFieldDefinitionsState } from '@/object-record/record-index/states/recordIndexFieldDefinitionsState';
|
||||
import { recordIndexFiltersState } from '@/object-record/record-index/states/recordIndexFiltersState';
|
||||
@ -14,7 +15,7 @@ import { recordIndexIsCompactModeActiveState } from '@/object-record/record-inde
|
||||
import { recordIndexSortsState } from '@/object-record/record-index/states/recordIndexSortsState';
|
||||
import { recordIndexViewFilterGroupsState } from '@/object-record/record-index/states/recordIndexViewFilterGroupsState';
|
||||
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { useSetRecordCountInCurrentView } from '@/views/hooks/useSetRecordCountInCurrentView';
|
||||
|
||||
type UseLoadRecordIndexBoardProps = {
|
||||
@ -31,33 +32,28 @@ export const useLoadRecordIndexBoard = ({
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
objectNameSingular,
|
||||
});
|
||||
const {
|
||||
setRecordIds: setRecordIdsInBoard,
|
||||
setFieldDefinitions,
|
||||
setColumns,
|
||||
isCompactModeActiveState,
|
||||
} = useRecordBoard(recordBoardId);
|
||||
|
||||
const setRecordBoardFieldDefinitions = useSetRecoilComponentStateV2(
|
||||
recordBoardFieldDefinitionsComponentState,
|
||||
recordBoardId,
|
||||
);
|
||||
|
||||
const { setRecordIds: setRecordIdsInBoard } =
|
||||
useSetRecordBoardRecordIds(recordBoardId);
|
||||
|
||||
const { upsertRecords: upsertRecordsInStore } = useUpsertRecordsInStore();
|
||||
|
||||
const recordIndexFieldDefinitions = useRecoilValue(
|
||||
recordIndexFieldDefinitionsState,
|
||||
);
|
||||
useEffect(() => {
|
||||
setFieldDefinitions(recordIndexFieldDefinitions);
|
||||
}, [recordIndexFieldDefinitions, setFieldDefinitions]);
|
||||
setRecordBoardFieldDefinitions(recordIndexFieldDefinitions);
|
||||
}, [recordIndexFieldDefinitions, setRecordBoardFieldDefinitions]);
|
||||
|
||||
const recordIndexViewFilterGroups = useRecoilValue(
|
||||
recordIndexViewFilterGroupsState,
|
||||
);
|
||||
|
||||
const recordGroupDefinitions = useRecoilComponentValueV2(
|
||||
recordGroupDefinitionsComponentState,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setColumns(recordGroupDefinitions);
|
||||
}, [recordGroupDefinitions, setColumns]);
|
||||
|
||||
const recordIndexFilters = useRecoilValue(recordIndexFiltersState);
|
||||
const recordIndexSorts = useRecoilValue(recordIndexSortsState);
|
||||
const requestFilters = computeViewRecordGqlOperationFilter(
|
||||
@ -92,7 +88,10 @@ export const useLoadRecordIndexBoard = ({
|
||||
const { setRecordCountInCurrentView } =
|
||||
useSetRecordCountInCurrentView(viewBarId);
|
||||
|
||||
const setIsCompactModeActive = useSetRecoilState(isCompactModeActiveState);
|
||||
const setIsCompactModeActive = useSetRecoilComponentStateV2(
|
||||
isRecordBoardCompactModeActiveComponentState,
|
||||
recordBoardId,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setRecordIdsInBoard(records);
|
||||
|
||||
@ -4,9 +4,9 @@ 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 { useRecordBoardStates } from '@/object-record/record-board/hooks/internal/useRecordBoardStates';
|
||||
import { useRecordBoard } from '@/object-record/record-board/hooks/useRecordBoard';
|
||||
import { useSetRecordIdsForColumn } from '@/object-record/record-board/hooks/useSetRecordIdsForColumn';
|
||||
import { computeViewRecordGqlOperationFilter } from '@/object-record/record-filter/utils/computeViewRecordGqlOperationFilter';
|
||||
import { recordGroupDefinitionFamilyState } from '@/object-record/record-group/states/recordGroupDefinitionFamilyState';
|
||||
import { useRecordBoardRecordGqlFields } from '@/object-record/record-index/hooks/useRecordBoardRecordGqlFields';
|
||||
import { recordIndexFiltersState } from '@/object-record/record-index/states/recordIndexFiltersState';
|
||||
import { recordIndexSortsState } from '@/object-record/record-index/states/recordIndexSortsState';
|
||||
@ -30,16 +30,18 @@ export const useLoadRecordIndexBoardColumn = ({
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
objectNameSingular,
|
||||
});
|
||||
const { setRecordIdsForColumn } = useRecordBoard(recordBoardId);
|
||||
const { columnsFamilySelector } = useRecordBoardStates(recordBoardId);
|
||||
const { setRecordIdsForColumn } = useSetRecordIdsForColumn(recordBoardId);
|
||||
const { upsertRecords: upsertRecordsInStore } = useUpsertRecordsInStore();
|
||||
|
||||
const recordGroupDefinition = useRecoilValue(
|
||||
recordGroupDefinitionFamilyState(columnId),
|
||||
);
|
||||
|
||||
const recordIndexViewFilterGroups = useRecoilValue(
|
||||
recordIndexViewFilterGroupsState,
|
||||
);
|
||||
const recordIndexFilters = useRecoilValue(recordIndexFiltersState);
|
||||
const recordIndexSorts = useRecoilValue(recordIndexSortsState);
|
||||
const columnDefinition = useRecoilValue(columnsFamilySelector(columnId));
|
||||
|
||||
const requestFilters = computeViewRecordGqlOperationFilter(
|
||||
recordIndexFilters,
|
||||
@ -60,9 +62,9 @@ export const useLoadRecordIndexBoardColumn = ({
|
||||
const filter = {
|
||||
...requestFilters,
|
||||
[recordIndexKanbanFieldMetadataItem?.name ?? '']: isDefined(
|
||||
columnDefinition?.value,
|
||||
recordGroupDefinition?.value,
|
||||
)
|
||||
? { in: [columnDefinition?.value] }
|
||||
? { in: [recordGroupDefinition?.value] }
|
||||
: { is: 'NULL' },
|
||||
};
|
||||
|
||||
|
||||
@ -27,8 +27,7 @@ export const useFindManyParams = (
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const currentRecordGroupDefinition =
|
||||
useCurrentRecordGroupDefinition(recordTableId);
|
||||
const currentRecordGroupDefinition = useCurrentRecordGroupDefinition();
|
||||
|
||||
const tableViewFilterGroups = useRecoilComponentValueV2(
|
||||
tableViewFilterGroupsComponentState,
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { getObjectMetadataIdentifierFields } from '@/object-metadata/utils/getObjectMetadataIdentifierFields';
|
||||
import { hasPositionField } from '@/object-metadata/utils/hasPositionField';
|
||||
import { useRecordBoardStates } from '@/object-record/record-board/hooks/internal/useRecordBoardStates';
|
||||
import { recordBoardVisibleFieldDefinitionsComponentSelector } from '@/object-record/record-board/states/selectors/recordBoardVisibleFieldDefinitionsComponentSelector';
|
||||
import { recordGroupFieldMetadataComponentState } from '@/object-record/record-group/states/recordGroupFieldMetadataComponentState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export const useRecordBoardRecordGqlFields = ({
|
||||
@ -13,15 +13,17 @@ export const useRecordBoardRecordGqlFields = ({
|
||||
recordBoardId: string;
|
||||
objectMetadataItem: ObjectMetadataItem;
|
||||
}) => {
|
||||
const { kanbanFieldMetadataNameState, visibleFieldDefinitionsState } =
|
||||
useRecordBoardStates(recordBoardId);
|
||||
const visibleFieldDefinitions = useRecoilComponentValueV2(
|
||||
recordBoardVisibleFieldDefinitionsComponentSelector,
|
||||
recordBoardId,
|
||||
);
|
||||
|
||||
const { imageIdentifierFieldMetadataItem, labelIdentifierFieldMetadataItem } =
|
||||
getObjectMetadataIdentifierFields({ objectMetadataItem });
|
||||
|
||||
const kanbanFieldMetadataName = useRecoilValue(kanbanFieldMetadataNameState);
|
||||
const visibleFieldDefinitions = useRecoilValue(
|
||||
visibleFieldDefinitionsState(),
|
||||
const recordGroupFieldMetadata = useRecoilComponentValueV2(
|
||||
recordGroupFieldMetadataComponentState,
|
||||
recordBoardId,
|
||||
);
|
||||
|
||||
const identifierQueryFields: Record<string, boolean> = {};
|
||||
@ -59,8 +61,8 @@ export const useRecordBoardRecordGqlFields = ({
|
||||
},
|
||||
};
|
||||
|
||||
if (isDefined(kanbanFieldMetadataName)) {
|
||||
recordGqlFields[kanbanFieldMetadataName] = true;
|
||||
if (isDefined(recordGroupFieldMetadata?.name)) {
|
||||
recordGqlFields[recordGroupFieldMetadata.name] = true;
|
||||
}
|
||||
|
||||
return recordGqlFields;
|
||||
|
||||
@ -1,12 +0,0 @@
|
||||
import { useRecordBoardStates } from '@/object-record/record-board/hooks/internal/useRecordBoardStates';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
export const useRecordIndexPageKanbanAddMenuItem = (
|
||||
recordIndexId: string,
|
||||
columnId: string,
|
||||
) => {
|
||||
const { columnsFamilySelector } = useRecordBoardStates(recordIndexId);
|
||||
const columnDefinition = useRecoilValue(columnsFamilySelector(columnId));
|
||||
|
||||
return { columnDefinition };
|
||||
};
|
||||
@ -0,0 +1,10 @@
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
|
||||
export const recordIndexAllRowIdsComponentState = createComponentStateV2<
|
||||
string[]
|
||||
>({
|
||||
key: 'recordIndexAllRowIdsComponentState',
|
||||
defaultValue: [],
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
});
|
||||
@ -1,10 +1,10 @@
|
||||
import { RecordGroupDefinition } from '@/object-record/record-group/types/RecordGroupDefinition';
|
||||
import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext';
|
||||
import { createComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentFamilyStateV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
|
||||
export const tableRowIdsByGroupComponentFamilyState =
|
||||
export const recordIndexRowIdsByGroupComponentFamilyState =
|
||||
createComponentFamilyStateV2<string[], RecordGroupDefinition['id']>({
|
||||
key: 'tableRowIdsByGroupComponentFamilyState',
|
||||
key: 'recordIndexRowIdsByGroupComponentFamilyState',
|
||||
defaultValue: [],
|
||||
componentInstanceContext: RecordTableComponentInstanceContext,
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
});
|
||||
@ -1,7 +1,8 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { isNonEmptyString, isNull } from '@sniptt/guards';
|
||||
|
||||
import { hasRecordGroupDefinitionsComponentSelector } from '@/object-record/record-group/states/hasRecordGroupDefinitionsComponentSelector';
|
||||
import { hasRecordGroupsComponentSelector } from '@/object-record/record-group/states/selectors/hasRecordGroupsComponentSelector';
|
||||
import { recordIndexAllRowIdsComponentState } from '@/object-record/record-index/states/recordIndexAllRowIdsComponentState';
|
||||
import { RecordTableComponentInstance } from '@/object-record/record-table/components/RecordTableComponentInstance';
|
||||
import { RecordTableContextProvider } from '@/object-record/record-table/components/RecordTableContextProvider';
|
||||
import { RecordTableStickyEffect } from '@/object-record/record-table/components/RecordTableStickyEffect';
|
||||
@ -16,7 +17,6 @@ import { RecordTableRecordGroupsBody } from '@/object-record/record-table/record
|
||||
import { RecordTableHeader } from '@/object-record/record-table/record-table-header/components/RecordTableHeader';
|
||||
import { isRecordTableInitialLoadingComponentState } from '@/object-record/record-table/states/isRecordTableInitialLoadingComponentState';
|
||||
import { recordTablePendingRecordIdComponentState } from '@/object-record/record-table/states/recordTablePendingRecordIdComponentState';
|
||||
import { tableAllRowIdsComponentState } from '@/object-record/record-table/states/tableAllRowIdsComponentState';
|
||||
import { DragSelect } from '@/ui/utilities/drag-select/components/DragSelect';
|
||||
import { useClickOutsideListener } from '@/ui/utilities/pointer-event/hooks/useClickOutsideListener';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
@ -53,8 +53,8 @@ export const RecordTable = ({
|
||||
recordTableId,
|
||||
);
|
||||
|
||||
const tableRowIds = useRecoilComponentValueV2(
|
||||
tableAllRowIdsComponentState,
|
||||
const allRowIds = useRecoilComponentValueV2(
|
||||
recordIndexAllRowIdsComponentState,
|
||||
recordTableId,
|
||||
);
|
||||
|
||||
@ -64,13 +64,13 @@ export const RecordTable = ({
|
||||
);
|
||||
|
||||
const hasRecordGroups = useRecoilComponentValueV2(
|
||||
hasRecordGroupDefinitionsComponentSelector,
|
||||
hasRecordGroupsComponentSelector,
|
||||
recordTableId,
|
||||
);
|
||||
|
||||
const recordTableIsEmpty =
|
||||
!isRecordTableInitialLoading &&
|
||||
tableRowIds.length === 0 &&
|
||||
allRowIds.length === 0 &&
|
||||
isNull(pendingRecordId);
|
||||
|
||||
const { resetTableRowSelection, setRowSelected } = useRecordTable({
|
||||
@ -109,9 +109,7 @@ export const RecordTable = ({
|
||||
{!hasRecordGroups ? (
|
||||
<RecordTableNoRecordGroupBody />
|
||||
) : (
|
||||
<RecordTableRecordGroupsBody
|
||||
objectNameSingular={objectNameSingular}
|
||||
/>
|
||||
<RecordTableRecordGroupsBody />
|
||||
)}
|
||||
<RecordTableStickyEffect />
|
||||
</StyledTable>
|
||||
|
||||
@ -1,14 +1,16 @@
|
||||
import { recordIndexAllRowIdsComponentState } from '@/object-record/record-index/states/recordIndexAllRowIdsComponentState';
|
||||
import { RecordTableBodyFetchMoreLoader } from '@/object-record/record-table/record-table-body/components/RecordTableBodyFetchMoreLoader';
|
||||
import { RecordTableRow } from '@/object-record/record-table/record-table-row/components/RecordTableRow';
|
||||
import { tableAllRowIdsComponentState } from '@/object-record/record-table/states/tableAllRowIdsComponentState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
|
||||
export const RecordTableNoRecordGroupRows = () => {
|
||||
const rowIds = useRecoilComponentValueV2(tableAllRowIdsComponentState);
|
||||
const allRowIds = useRecoilComponentValueV2(
|
||||
recordIndexAllRowIdsComponentState,
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
{rowIds.map((recordId, rowIndex) => {
|
||||
{allRowIds.map((recordId, rowIndex) => {
|
||||
return (
|
||||
<RecordTableRow
|
||||
key={recordId}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { useCurrentRecordGroupId } from '@/object-record/record-group/hooks/useCurrentRecordGroupId';
|
||||
import { recordIndexAllRowIdsComponentState } from '@/object-record/record-index/states/recordIndexAllRowIdsComponentState';
|
||||
import { recordIndexRowIdsByGroupComponentFamilyState } from '@/object-record/record-index/states/recordIndexRowIdsByGroupComponentFamilyState';
|
||||
import { RecordTableRow } from '@/object-record/record-table/record-table-row/components/RecordTableRow';
|
||||
import { tableAllRowIdsComponentState } from '@/object-record/record-table/states/tableAllRowIdsComponentState';
|
||||
import { tableRowIdsByGroupComponentFamilyState } from '@/object-record/record-table/states/tableRowIdsByGroupComponentFamilyState';
|
||||
import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useMemo } from 'react';
|
||||
@ -9,10 +9,12 @@ import { useMemo } from 'react';
|
||||
export const RecordTableRecordGroupRows = () => {
|
||||
const recordGroupId = useCurrentRecordGroupId();
|
||||
|
||||
const allRowIds = useRecoilComponentValueV2(tableAllRowIdsComponentState);
|
||||
const allRowIds = useRecoilComponentValueV2(
|
||||
recordIndexAllRowIdsComponentState,
|
||||
);
|
||||
|
||||
const recordGroupRowIds = useRecoilComponentFamilyValueV2(
|
||||
tableRowIdsByGroupComponentFamilyState,
|
||||
recordIndexRowIdsByGroupComponentFamilyState,
|
||||
recordGroupId,
|
||||
);
|
||||
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { isNull } from '@sniptt/guards';
|
||||
|
||||
import { recordIndexAllRowIdsComponentState } from '@/object-record/record-index/states/recordIndexAllRowIdsComponentState';
|
||||
import { RecordTableEmptyState } from '@/object-record/record-table/empty-state/components/RecordTableEmptyState';
|
||||
import { isRecordTableInitialLoadingComponentState } from '@/object-record/record-table/states/isRecordTableInitialLoadingComponentState';
|
||||
import { recordTablePendingRecordIdComponentState } from '@/object-record/record-table/states/recordTablePendingRecordIdComponentState';
|
||||
import { tableAllRowIdsComponentState } from '@/object-record/record-table/states/tableAllRowIdsComponentState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
|
||||
type RecordTableEmptyHandlerProps = {
|
||||
@ -20,8 +20,8 @@ export const RecordTableEmptyHandler = ({
|
||||
recordTableId,
|
||||
);
|
||||
|
||||
const tableRowIds = useRecoilComponentValueV2(
|
||||
tableAllRowIdsComponentState,
|
||||
const allRowIds = useRecoilComponentValueV2(
|
||||
recordIndexAllRowIdsComponentState,
|
||||
recordTableId,
|
||||
);
|
||||
|
||||
@ -32,7 +32,7 @@ export const RecordTableEmptyHandler = ({
|
||||
|
||||
const recordTableIsEmpty =
|
||||
!isRecordTableInitialLoading &&
|
||||
tableRowIds.length === 0 &&
|
||||
allRowIds.length === 0 &&
|
||||
isNull(pendingRecordId);
|
||||
|
||||
if (recordTableIsEmpty) {
|
||||
|
||||
@ -2,10 +2,10 @@ import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { getActionMenuDropdownIdFromActionMenuId } from '@/action-menu/utils/getActionMenuDropdownIdFromActionMenuId';
|
||||
import { getActionMenuIdFromRecordIndexId } from '@/action-menu/utils/getActionMenuIdFromRecordIndexId';
|
||||
import { recordIndexAllRowIdsComponentState } from '@/object-record/record-index/states/recordIndexAllRowIdsComponentState';
|
||||
import { hasUserSelectedAllRowsComponentState } from '@/object-record/record-table/record-table-row/states/hasUserSelectedAllRowsFamilyState';
|
||||
import { isRowSelectedComponentFamilyState } from '@/object-record/record-table/record-table-row/states/isRowSelectedComponentFamilyState';
|
||||
import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext';
|
||||
import { tableAllRowIdsComponentState } from '@/object-record/record-table/states/tableAllRowIdsComponentState';
|
||||
import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState';
|
||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||
@ -18,8 +18,8 @@ export const useResetTableRowSelection = (recordTableId?: string) => {
|
||||
recordTableId,
|
||||
);
|
||||
|
||||
const tableAllRowIdsState = useRecoilComponentCallbackStateV2(
|
||||
tableAllRowIdsComponentState,
|
||||
const recordIndexAllRowIdsState = useRecoilComponentCallbackStateV2(
|
||||
recordIndexAllRowIdsComponentState,
|
||||
recordTableIdFromContext,
|
||||
);
|
||||
|
||||
@ -43,9 +43,9 @@ export const useResetTableRowSelection = (recordTableId?: string) => {
|
||||
return useRecoilCallback(
|
||||
({ set, snapshot }) =>
|
||||
() => {
|
||||
const tableRowIds = getSnapshotValue(snapshot, tableAllRowIdsState);
|
||||
const allRowIds = getSnapshotValue(snapshot, recordIndexAllRowIdsState);
|
||||
|
||||
for (const rowId of tableRowIds) {
|
||||
for (const rowId of allRowIds) {
|
||||
set(isRowSelectedFamilyState(rowId), false);
|
||||
}
|
||||
|
||||
@ -54,7 +54,7 @@ export const useResetTableRowSelection = (recordTableId?: string) => {
|
||||
set(isActionMenuDropdownOpenState, false);
|
||||
},
|
||||
[
|
||||
tableAllRowIdsState,
|
||||
recordIndexAllRowIdsState,
|
||||
hasUserSelectedAllRowsState,
|
||||
isActionMenuDropdownOpenState,
|
||||
isRowSelectedFamilyState,
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { recordIndexAllRowIdsComponentState } from '@/object-record/record-index/states/recordIndexAllRowIdsComponentState';
|
||||
import { isRowSelectedComponentFamilyState } from '@/object-record/record-table/record-table-row/states/isRowSelectedComponentFamilyState';
|
||||
import { allRowsSelectedStatusComponentSelector } from '@/object-record/record-table/states/selectors/allRowsSelectedStatusComponentSelector';
|
||||
import { tableAllRowIdsComponentState } from '@/object-record/record-table/states/tableAllRowIdsComponentState';
|
||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
|
||||
@ -15,8 +15,8 @@ export const useSelectAllRows = (recordTableId?: string) => {
|
||||
isRowSelectedComponentFamilyState,
|
||||
recordTableId,
|
||||
);
|
||||
const tableAllRowIdsState = useRecoilComponentCallbackStateV2(
|
||||
tableAllRowIdsComponentState,
|
||||
const recordIndexAllRowIdsState = useRecoilComponentCallbackStateV2(
|
||||
recordIndexAllRowIdsComponentState,
|
||||
recordTableId,
|
||||
);
|
||||
|
||||
@ -28,24 +28,24 @@ export const useSelectAllRows = (recordTableId?: string) => {
|
||||
allRowsSelectedStatusSelector,
|
||||
);
|
||||
|
||||
const tableRowIds = getSnapshotValue(snapshot, tableAllRowIdsState);
|
||||
const allRowIds = getSnapshotValue(snapshot, recordIndexAllRowIdsState);
|
||||
|
||||
if (
|
||||
allRowsSelectedStatus === 'none' ||
|
||||
allRowsSelectedStatus === 'some'
|
||||
) {
|
||||
for (const rowId of tableRowIds) {
|
||||
for (const rowId of allRowIds) {
|
||||
set(isRowSelectedFamilyState(rowId), true);
|
||||
}
|
||||
} else {
|
||||
for (const rowId of tableRowIds) {
|
||||
for (const rowId of allRowIds) {
|
||||
set(isRowSelectedFamilyState(rowId), false);
|
||||
}
|
||||
}
|
||||
},
|
||||
[
|
||||
allRowsSelectedStatusSelector,
|
||||
tableAllRowIdsState,
|
||||
recordIndexAllRowIdsState,
|
||||
isRowSelectedFamilyState,
|
||||
],
|
||||
);
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { recordGroupDefinitionsComponentState } from '@/object-record/record-group/states/recordGroupDefinitionsComponentState';
|
||||
import { recordGroupIdsComponentState } from '@/object-record/record-group/states/recordGroupIdsComponentState';
|
||||
import { recordIndexAllRowIdsComponentState } from '@/object-record/record-index/states/recordIndexAllRowIdsComponentState';
|
||||
import { recordIndexRowIdsByGroupComponentFamilyState } from '@/object-record/record-index/states/recordIndexRowIdsByGroupComponentFamilyState';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { hasUserSelectedAllRowsComponentState } from '@/object-record/record-table/record-table-row/states/hasUserSelectedAllRowsFamilyState';
|
||||
import { isRowSelectedComponentFamilyState } from '@/object-record/record-table/record-table-row/states/isRowSelectedComponentFamilyState';
|
||||
import { tableAllRowIdsComponentState } from '@/object-record/record-table/states/tableAllRowIdsComponentState';
|
||||
import { tableRowIdsByGroupComponentFamilyState } from '@/object-record/record-table/states/tableRowIdsByGroupComponentFamilyState';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
@ -21,12 +21,12 @@ export const useSetRecordTableData = ({
|
||||
recordTableId,
|
||||
onEntityCountChange,
|
||||
}: useSetRecordTableDataProps) => {
|
||||
const tableRowIdsByGroupFamilyState = useRecoilComponentCallbackStateV2(
|
||||
tableRowIdsByGroupComponentFamilyState,
|
||||
const recordIndexRowIdsByGroupFamilyState = useRecoilComponentCallbackStateV2(
|
||||
recordIndexRowIdsByGroupComponentFamilyState,
|
||||
recordTableId,
|
||||
);
|
||||
const tableAllRowIdsState = useRecoilComponentCallbackStateV2(
|
||||
tableAllRowIdsComponentState,
|
||||
const recordIndexAllRowIdsState = useRecoilComponentCallbackStateV2(
|
||||
recordIndexAllRowIdsComponentState,
|
||||
recordTableId,
|
||||
);
|
||||
const isRowSelectedFamilyState = useRecoilComponentCallbackStateV2(
|
||||
@ -37,8 +37,8 @@ export const useSetRecordTableData = ({
|
||||
hasUserSelectedAllRowsComponentState,
|
||||
recordTableId,
|
||||
);
|
||||
const recordGroupDefinitionsState = useRecoilComponentCallbackStateV2(
|
||||
recordGroupDefinitionsComponentState,
|
||||
const recordIndexRecordGroupIdsState = useRecoilComponentCallbackStateV2(
|
||||
recordGroupIdsComponentState,
|
||||
recordTableId,
|
||||
);
|
||||
|
||||
@ -46,11 +46,11 @@ export const useSetRecordTableData = ({
|
||||
({ set, snapshot }) =>
|
||||
<T extends ObjectRecord>({
|
||||
records,
|
||||
recordGroupId,
|
||||
currentRecordGroupId,
|
||||
totalCount,
|
||||
}: {
|
||||
records: T[];
|
||||
recordGroupId?: string;
|
||||
currentRecordGroupId?: string;
|
||||
totalCount?: number;
|
||||
}) => {
|
||||
for (const record of records) {
|
||||
@ -66,9 +66,9 @@ export const useSetRecordTableData = ({
|
||||
|
||||
const currentRowIds = getSnapshotValue(
|
||||
snapshot,
|
||||
recordGroupId
|
||||
? tableRowIdsByGroupFamilyState(recordGroupId)
|
||||
: tableAllRowIdsState,
|
||||
currentRecordGroupId
|
||||
? recordIndexRowIdsByGroupFamilyState(currentRecordGroupId)
|
||||
: recordIndexAllRowIdsState,
|
||||
);
|
||||
|
||||
const hasUserSelectedAllRows = getSnapshotValue(
|
||||
@ -76,9 +76,9 @@ export const useSetRecordTableData = ({
|
||||
hasUserSelectedAllRowsState,
|
||||
);
|
||||
|
||||
const recordGroupDefinitions = getSnapshotValue(
|
||||
const recordGroupIds = getSnapshotValue(
|
||||
snapshot,
|
||||
recordGroupDefinitionsState,
|
||||
recordIndexRecordGroupIdsState,
|
||||
);
|
||||
|
||||
const recordIds = records.map((record) => record.id);
|
||||
@ -90,39 +90,42 @@ export const useSetRecordTableData = ({
|
||||
}
|
||||
}
|
||||
|
||||
if (isDefined(recordGroupId)) {
|
||||
if (isDefined(currentRecordGroupId)) {
|
||||
// TODO: Hack to store all ids in the same order as the record group definitions
|
||||
// Should be replaced by something more efficient
|
||||
const allRowIds: string[] = [];
|
||||
|
||||
set(tableRowIdsByGroupFamilyState(recordGroupId), recordIds);
|
||||
set(
|
||||
recordIndexRowIdsByGroupFamilyState(currentRecordGroupId),
|
||||
recordIds,
|
||||
);
|
||||
|
||||
for (const recordGroupDefinition of recordGroupDefinitions) {
|
||||
for (const recordGroupId of recordGroupIds) {
|
||||
const tableRowIdsByGroup =
|
||||
recordGroupDefinition.id !== recordGroupId
|
||||
recordGroupId !== currentRecordGroupId
|
||||
? getSnapshotValue(
|
||||
snapshot,
|
||||
tableRowIdsByGroupFamilyState(recordGroupDefinition.id),
|
||||
recordIndexRowIdsByGroupFamilyState(recordGroupId),
|
||||
)
|
||||
: recordIds;
|
||||
|
||||
allRowIds.push(...tableRowIdsByGroup);
|
||||
}
|
||||
set(tableAllRowIdsState, allRowIds);
|
||||
set(recordIndexAllRowIdsState, allRowIds);
|
||||
} else {
|
||||
set(tableAllRowIdsState, recordIds);
|
||||
set(recordIndexAllRowIdsState, recordIds);
|
||||
}
|
||||
|
||||
onEntityCountChange(totalCount);
|
||||
}
|
||||
},
|
||||
[
|
||||
tableRowIdsByGroupFamilyState,
|
||||
tableAllRowIdsState,
|
||||
recordGroupDefinitionsState,
|
||||
recordIndexRowIdsByGroupFamilyState,
|
||||
recordIndexAllRowIdsState,
|
||||
hasUserSelectedAllRowsState,
|
||||
recordIndexRecordGroupIdsState,
|
||||
onEntityCountChange,
|
||||
isRowSelectedFamilyState,
|
||||
hasUserSelectedAllRowsState,
|
||||
],
|
||||
);
|
||||
};
|
||||
|
||||
@ -3,9 +3,9 @@ import { useRecoilCallback } from 'recoil';
|
||||
import { MoveFocusDirection } from '@/object-record/record-table/types/MoveFocusDirection';
|
||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||
|
||||
import { recordIndexAllRowIdsComponentState } from '@/object-record/record-index/states/recordIndexAllRowIdsComponentState';
|
||||
import { numberOfTableColumnsComponentSelector } from '@/object-record/record-table/states/selectors/numberOfTableColumnsComponentSelector';
|
||||
import { softFocusPositionComponentState } from '@/object-record/record-table/states/softFocusPositionComponentState';
|
||||
import { tableAllRowIdsComponentState } from '@/object-record/record-table/states/tableAllRowIdsComponentState';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { useSetSoftFocusPosition } from './internal/useSetSoftFocusPosition';
|
||||
|
||||
@ -17,8 +17,8 @@ export const useRecordTableMoveFocus = (recordTableId?: string) => {
|
||||
recordTableId,
|
||||
);
|
||||
|
||||
const tableAllRowIdsState = useRecoilComponentCallbackStateV2(
|
||||
tableAllRowIdsComponentState,
|
||||
const recordIndexAllRowIdsState = useRecoilComponentCallbackStateV2(
|
||||
recordIndexAllRowIdsComponentState,
|
||||
recordTableId,
|
||||
);
|
||||
|
||||
@ -47,7 +47,7 @@ export const useRecordTableMoveFocus = (recordTableId?: string) => {
|
||||
const moveDown = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
() => {
|
||||
const allRowIds = getSnapshotValue(snapshot, tableAllRowIdsState);
|
||||
const allRowIds = getSnapshotValue(snapshot, recordIndexAllRowIdsState);
|
||||
const softFocusPosition = getSnapshotValue(
|
||||
snapshot,
|
||||
softFocusPositionState,
|
||||
@ -64,7 +64,7 @@ export const useRecordTableMoveFocus = (recordTableId?: string) => {
|
||||
row: newRowIndex,
|
||||
});
|
||||
},
|
||||
[tableAllRowIdsState, setSoftFocusPosition, softFocusPositionState],
|
||||
[recordIndexAllRowIdsState, setSoftFocusPosition, softFocusPositionState],
|
||||
);
|
||||
|
||||
const numberOfTableColumnsSelector = useRecoilComponentCallbackStateV2(
|
||||
@ -75,7 +75,7 @@ export const useRecordTableMoveFocus = (recordTableId?: string) => {
|
||||
const moveRight = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
() => {
|
||||
const allRowIds = getSnapshotValue(snapshot, tableAllRowIdsState);
|
||||
const allRowIds = getSnapshotValue(snapshot, recordIndexAllRowIdsState);
|
||||
const softFocusPosition = getSnapshotValue(
|
||||
snapshot,
|
||||
softFocusPositionState,
|
||||
@ -116,7 +116,7 @@ export const useRecordTableMoveFocus = (recordTableId?: string) => {
|
||||
}
|
||||
},
|
||||
[
|
||||
tableAllRowIdsState,
|
||||
recordIndexAllRowIdsState,
|
||||
softFocusPositionState,
|
||||
numberOfTableColumnsSelector,
|
||||
setSoftFocusPosition,
|
||||
|
||||
@ -3,10 +3,10 @@ import { ReactNode, useContext } from 'react';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
|
||||
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
|
||||
import { recordIndexAllRowIdsComponentState } from '@/object-record/record-index/states/recordIndexAllRowIdsComponentState';
|
||||
import { RecordTableContext } from '@/object-record/record-table/contexts/RecordTableContext';
|
||||
import { useComputeNewRowPosition } from '@/object-record/record-table/hooks/useComputeNewRowPosition';
|
||||
import { isRemoveSortingModalOpenState } from '@/object-record/record-table/states/isRemoveSortingModalOpenState';
|
||||
import { tableAllRowIdsComponentState } from '@/object-record/record-table/states/tableAllRowIdsComponentState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
@ -22,8 +22,8 @@ export const RecordTableBodyDragDropContext = ({
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const tableAllRowIds = useRecoilComponentValueV2(
|
||||
tableAllRowIdsComponentState,
|
||||
const allRowIds = useRecoilComponentValueV2(
|
||||
recordIndexAllRowIdsComponentState,
|
||||
);
|
||||
|
||||
const { currentViewWithCombinedFiltersAndSorts } =
|
||||
@ -43,7 +43,7 @@ export const RecordTableBodyDragDropContext = ({
|
||||
return;
|
||||
}
|
||||
|
||||
const computeResult = computeNewRowPosition(result, tableAllRowIds);
|
||||
const computeResult = computeNewRowPosition(result, allRowIds);
|
||||
|
||||
if (!isDefined(computeResult)) {
|
||||
return;
|
||||
|
||||
@ -1,22 +1,22 @@
|
||||
import { recordIndexAllRowIdsComponentState } from '@/object-record/record-index/states/recordIndexAllRowIdsComponentState';
|
||||
import { RecordTableNoRecordGroupRows } from '@/object-record/record-table/components/RecordTableNoRecordGroupRows';
|
||||
import { RecordTableBodyDragDropContext } from '@/object-record/record-table/record-table-body/components/RecordTableBodyDragDropContext';
|
||||
import { RecordTableBodyDroppable } from '@/object-record/record-table/record-table-body/components/RecordTableBodyDroppable';
|
||||
import { RecordTableBodyLoading } from '@/object-record/record-table/record-table-body/components/RecordTableBodyLoading';
|
||||
import { RecordTablePendingRow } from '@/object-record/record-table/record-table-row/components/RecordTablePendingRow';
|
||||
import { isRecordTableInitialLoadingComponentState } from '@/object-record/record-table/states/isRecordTableInitialLoadingComponentState';
|
||||
import { tableAllRowIdsComponentState } from '@/object-record/record-table/states/tableAllRowIdsComponentState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
|
||||
export const RecordTableNoRecordGroupBody = () => {
|
||||
const tableAllRowIds = useRecoilComponentValueV2(
|
||||
tableAllRowIdsComponentState,
|
||||
const allRowIds = useRecoilComponentValueV2(
|
||||
recordIndexAllRowIdsComponentState,
|
||||
);
|
||||
|
||||
const isRecordTableInitialLoading = useRecoilComponentValueV2(
|
||||
isRecordTableInitialLoadingComponentState,
|
||||
);
|
||||
|
||||
if (isRecordTableInitialLoading && tableAllRowIds.length === 0) {
|
||||
if (isRecordTableInitialLoading && allRowIds.length === 0) {
|
||||
return <RecordTableBodyLoading />;
|
||||
}
|
||||
|
||||
|
||||
@ -56,7 +56,7 @@ export const RecordTableRecordGroupBodyEffect = () => {
|
||||
if (!loading) {
|
||||
setRecordTableData({
|
||||
records,
|
||||
recordGroupId,
|
||||
currentRecordGroupId: recordGroupId,
|
||||
totalCount,
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,18 +1,15 @@
|
||||
import { RecordGroupContext } from '@/object-record/record-group/states/context/RecordGroupContext';
|
||||
import { recordGroupDefinitionsComponentState } from '@/object-record/record-group/states/recordGroupDefinitionsComponentState';
|
||||
import { recordGroupIdsComponentState } from '@/object-record/record-group/states/recordGroupIdsComponentState';
|
||||
import { RecordTableRecordGroupBodyEffect } from '@/object-record/record-table/record-table-body/components/RecordTableRecordGroupBodyEffect';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
|
||||
export const RecordTableRecordGroupBodyEffects = () => {
|
||||
const recordGroupDefinitions = useRecoilComponentValueV2(
|
||||
recordGroupDefinitionsComponentState,
|
||||
const recordGroupIds = useRecoilComponentValueV2(
|
||||
recordGroupIdsComponentState,
|
||||
);
|
||||
|
||||
return recordGroupDefinitions.map((recordGroupDefinition) => (
|
||||
<RecordGroupContext.Provider
|
||||
key={recordGroupDefinition.id}
|
||||
value={{ recordGroupId: recordGroupDefinition.id }}
|
||||
>
|
||||
return recordGroupIds.map((recordGroupId) => (
|
||||
<RecordGroupContext.Provider key={recordGroupId} value={{ recordGroupId }}>
|
||||
<RecordTableRecordGroupBodyEffect />
|
||||
</RecordGroupContext.Provider>
|
||||
));
|
||||
|
||||
@ -1,32 +1,28 @@
|
||||
import { useRecordGroups } from '@/object-record/record-group/hooks/useRecordGroups';
|
||||
import { RecordGroupContext } from '@/object-record/record-group/states/context/RecordGroupContext';
|
||||
import { visibleRecordGroupIdsComponentSelector } from '@/object-record/record-group/states/selectors/visibleRecordGroupIdsComponentSelector';
|
||||
import { recordIndexAllRowIdsComponentState } from '@/object-record/record-index/states/recordIndexAllRowIdsComponentState';
|
||||
import { RecordTableRecordGroupRows } from '@/object-record/record-table/components/RecordTableRecordGroupRows';
|
||||
import { RecordTableBodyDragDropContext } from '@/object-record/record-table/record-table-body/components/RecordTableBodyDragDropContext';
|
||||
import { RecordTableBodyDroppable } from '@/object-record/record-table/record-table-body/components/RecordTableBodyDroppable';
|
||||
import { RecordTableBodyLoading } from '@/object-record/record-table/record-table-body/components/RecordTableBodyLoading';
|
||||
import { RecordTablePendingRow } from '@/object-record/record-table/record-table-row/components/RecordTablePendingRow';
|
||||
import { isRecordTableInitialLoadingComponentState } from '@/object-record/record-table/states/isRecordTableInitialLoadingComponentState';
|
||||
import { tableAllRowIdsComponentState } from '@/object-record/record-table/states/tableAllRowIdsComponentState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
|
||||
type RecordTableRecordGroupsBodyProps = {
|
||||
objectNameSingular: string;
|
||||
};
|
||||
|
||||
export const RecordTableRecordGroupsBody = ({
|
||||
objectNameSingular,
|
||||
}: RecordTableRecordGroupsBodyProps) => {
|
||||
const tableAllRowIds = useRecoilComponentValueV2(
|
||||
tableAllRowIdsComponentState,
|
||||
export const RecordTableRecordGroupsBody = () => {
|
||||
const allRowIds = useRecoilComponentValueV2(
|
||||
recordIndexAllRowIdsComponentState,
|
||||
);
|
||||
|
||||
const isRecordTableInitialLoading = useRecoilComponentValueV2(
|
||||
isRecordTableInitialLoadingComponentState,
|
||||
);
|
||||
|
||||
const { visibleRecordGroups } = useRecordGroups({ objectNameSingular });
|
||||
const visibleRecordGroupIds = useRecoilComponentValueV2(
|
||||
visibleRecordGroupIdsComponentSelector,
|
||||
);
|
||||
|
||||
if (isRecordTableInitialLoading && tableAllRowIds.length === 0) {
|
||||
if (isRecordTableInitialLoading && allRowIds.length === 0) {
|
||||
return <RecordTableBodyLoading />;
|
||||
}
|
||||
|
||||
@ -34,10 +30,10 @@ export const RecordTableRecordGroupsBody = ({
|
||||
<RecordTableBodyDragDropContext>
|
||||
<RecordTableBodyDroppable>
|
||||
<RecordTablePendingRow />
|
||||
{visibleRecordGroups.map((recordGroupDefinition) => (
|
||||
{visibleRecordGroupIds.map((recordGroupId) => (
|
||||
<RecordGroupContext.Provider
|
||||
key={recordGroupDefinition.id}
|
||||
value={{ recordGroupId: recordGroupDefinition.id }}
|
||||
key={recordGroupId}
|
||||
value={{ recordGroupId }}
|
||||
>
|
||||
<RecordTableRecordGroupRows />
|
||||
</RecordGroupContext.Provider>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { selectedRowIdsComponentSelector } from '@/object-record/record-table/states/selectors/selectedRowIdsComponentSelector';
|
||||
|
||||
import { recordIndexAllRowIdsComponentState } from '@/object-record/record-index/states/recordIndexAllRowIdsComponentState';
|
||||
import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext';
|
||||
import { tableAllRowIdsComponentState } from '@/object-record/record-table/states/tableAllRowIdsComponentState';
|
||||
import { createComponentSelectorV2 } from '@/ui/utilities/state/component-state/utils/createComponentSelectorV2';
|
||||
import { AllRowsSelectedStatus } from '../../types/AllRowSelectedStatus';
|
||||
|
||||
@ -12,8 +12,9 @@ export const allRowsSelectedStatusComponentSelector =
|
||||
get:
|
||||
({ instanceId }) =>
|
||||
({ get }) => {
|
||||
const tableRowIds = get(
|
||||
tableAllRowIdsComponentState.atomFamily({
|
||||
const allRowIds = get(
|
||||
// TODO: Working because instanceId is the same, but we're not in the same context, should be changed !
|
||||
recordIndexAllRowIdsComponentState.atomFamily({
|
||||
instanceId,
|
||||
}),
|
||||
);
|
||||
@ -29,7 +30,7 @@ export const allRowsSelectedStatusComponentSelector =
|
||||
const allRowsSelectedStatus =
|
||||
numberOfSelectedRows === 0
|
||||
? 'none'
|
||||
: selectedRowIds.length === tableRowIds.length
|
||||
: selectedRowIds.length === allRowIds.length
|
||||
? 'all'
|
||||
: 'some';
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { recordIndexAllRowIdsComponentState } from '@/object-record/record-index/states/recordIndexAllRowIdsComponentState';
|
||||
import { isRowSelectedComponentFamilyState } from '@/object-record/record-table/record-table-row/states/isRowSelectedComponentFamilyState';
|
||||
import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext';
|
||||
import { tableAllRowIdsComponentState } from '@/object-record/record-table/states/tableAllRowIdsComponentState';
|
||||
import { createComponentSelectorV2 } from '@/ui/utilities/state/component-state/utils/createComponentSelectorV2';
|
||||
|
||||
export const selectedRowIdsComponentSelector = createComponentSelectorV2<
|
||||
@ -11,13 +11,14 @@ export const selectedRowIdsComponentSelector = createComponentSelectorV2<
|
||||
get:
|
||||
({ instanceId }) =>
|
||||
({ get }) => {
|
||||
const rowIds = get(
|
||||
tableAllRowIdsComponentState.atomFamily({
|
||||
const allRowIds = get(
|
||||
// TODO: Working because instanceId is the same, but we're not in the same context, should be changed !
|
||||
recordIndexAllRowIdsComponentState.atomFamily({
|
||||
instanceId,
|
||||
}),
|
||||
);
|
||||
|
||||
return rowIds.filter(
|
||||
return allRowIds.filter(
|
||||
(rowId) =>
|
||||
get(
|
||||
isRowSelectedComponentFamilyState.atomFamily({
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { recordIndexAllRowIdsComponentState } from '@/object-record/record-index/states/recordIndexAllRowIdsComponentState';
|
||||
import { isRowSelectedComponentFamilyState } from '@/object-record/record-table/record-table-row/states/isRowSelectedComponentFamilyState';
|
||||
import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext';
|
||||
import { tableAllRowIdsComponentState } from '@/object-record/record-table/states/tableAllRowIdsComponentState';
|
||||
import { createComponentSelectorV2 } from '@/ui/utilities/state/component-state/utils/createComponentSelectorV2';
|
||||
|
||||
export const unselectedRowIdsComponentSelector = createComponentSelectorV2<
|
||||
@ -12,7 +12,8 @@ export const unselectedRowIdsComponentSelector = createComponentSelectorV2<
|
||||
({ instanceId }) =>
|
||||
({ get }) => {
|
||||
const rowIds = get(
|
||||
tableAllRowIdsComponentState.atomFamily({
|
||||
// TODO: Working because instanceId is the same, but we're not in the same context, should be changed !
|
||||
recordIndexAllRowIdsComponentState.atomFamily({
|
||||
instanceId,
|
||||
}),
|
||||
);
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
|
||||
export const tableAllRowIdsComponentState = createComponentStateV2<string[]>({
|
||||
key: 'tableAllRowIdsComponentState',
|
||||
defaultValue: [],
|
||||
componentInstanceContext: RecordTableComponentInstanceContext,
|
||||
});
|
||||
Reference in New Issue
Block a user