View module refactor with atomic recoil component instance states (#6810)
This PR refactors the view module to implement utils that avoid having to create hooks to inject the scope id in the states, like `useViewStates`, each componentState will know its unique related InstanceContext (which holds the instanceId), and thus will be able to retrieve it itself. We keep the naming componentState as it reflects the fact that those states are tied to instances of a component (or its children). We introduce the instance word where it is needed, in place of scopeId for example, to precise the fact that we handle instances of component state, one for each instance of a component. For example, the currentViewId is a state that is tied to an instance of the ViewBar, but as we can switch between views, we want currentViewId to be a componentState tied to an instance of the ViewBar component. This PR also refactors view filter and sort states to fix this issue : https://github.com/twentyhq/twenty/issues/6837 and other problems involving resetting those states between page navigation. Fixes https://github.com/twentyhq/twenty/issues/6837 --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
@ -1,9 +1,8 @@
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
|
||||
import { ObjectFilterDropdownScope } from '@/object-record/object-filter-dropdown/scopes/ObjectFilterDropdownScope';
|
||||
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
|
||||
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { availableFilterDefinitionsComponentState } from '@/views/states/availableFilterDefinitionsComponentState';
|
||||
import { MultipleFiltersDropdownButton } from './MultipleFiltersDropdownButton';
|
||||
import { SingleEntityObjectFilterDropdownButton } from './SingleEntityObjectFilterDropdownButton';
|
||||
|
||||
@ -16,12 +15,9 @@ export const ObjectFilterDropdownButton = ({
|
||||
filterDropdownId,
|
||||
hotkeyScope,
|
||||
}: ObjectFilterDropdownButtonProps) => {
|
||||
const { availableFilterDefinitionsState } = useFilterDropdown({
|
||||
filterDropdownId: filterDropdownId,
|
||||
});
|
||||
|
||||
const availableFilterDefinitions = useRecoilValue(
|
||||
availableFilterDefinitionsState,
|
||||
const availableFilterDefinitions = useRecoilComponentValueV2(
|
||||
availableFilterDefinitionsComponentState,
|
||||
filterDropdownId,
|
||||
);
|
||||
|
||||
const hasOnlyOneEntityFilter =
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { useState } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
|
||||
import { ObjectFilterDropdownFilterSelectMenuItem } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItem';
|
||||
@ -12,6 +10,8 @@ import { FiltersHotkeyScope } from '@/object-record/object-filter-dropdown/types
|
||||
import { SelectableItem } from '@/ui/layout/selectable-list/components/SelectableItem';
|
||||
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
|
||||
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { availableFilterDefinitionsComponentState } from '@/views/states/availableFilterDefinitionsComponentState';
|
||||
import { isDefined } from 'twenty-ui';
|
||||
|
||||
export const StyledInput = styled.input`
|
||||
@ -43,10 +43,8 @@ export const StyledInput = styled.input`
|
||||
export const ObjectFilterDropdownFilterSelect = () => {
|
||||
const [searchText, setSearchText] = useState('');
|
||||
|
||||
const { availableFilterDefinitionsState } = useFilterDropdown();
|
||||
|
||||
const availableFilterDefinitions = useRecoilValue(
|
||||
availableFilterDefinitionsState,
|
||||
const availableFilterDefinitions = useRecoilComponentValueV2(
|
||||
availableFilterDefinitionsComponentState,
|
||||
);
|
||||
|
||||
const sortedAvailableFilterDefinitions = [...availableFilterDefinitions]
|
||||
|
||||
@ -7,7 +7,7 @@ import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types
|
||||
import { MultipleRecordSelectDropdown } from '@/object-record/select/components/MultipleRecordSelectDropdown';
|
||||
import { useRecordsForSelect } from '@/object-record/select/hooks/useRecordsForSelect';
|
||||
import { SelectableRecord } from '@/object-record/select/types/SelectableRecord';
|
||||
import { useCombinedViewFilters } from '@/views/hooks/useCombinedViewFilters';
|
||||
import { useDeleteCombinedViewFilters } from '@/views/hooks/useDeleteCombinedViewFilters';
|
||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
@ -17,6 +17,7 @@ export const MAX_RECORDS_TO_DISPLAY = 3;
|
||||
type ObjectFilterDropdownRecordSelectProps = {
|
||||
viewComponentId?: string;
|
||||
};
|
||||
|
||||
export const ObjectFilterDropdownRecordSelect = ({
|
||||
viewComponentId,
|
||||
}: ObjectFilterDropdownRecordSelectProps) => {
|
||||
@ -31,7 +32,9 @@ export const ObjectFilterDropdownRecordSelect = ({
|
||||
emptyFilterButKeepDefinition,
|
||||
} = useFilterDropdown();
|
||||
|
||||
const { removeCombinedViewFilter } = useCombinedViewFilters(viewComponentId);
|
||||
const { deleteCombinedViewFilter } =
|
||||
useDeleteCombinedViewFilters(viewComponentId);
|
||||
|
||||
const { currentViewWithCombinedFiltersAndSorts } =
|
||||
useGetCurrentView(viewComponentId);
|
||||
|
||||
@ -78,7 +81,7 @@ export const ObjectFilterDropdownRecordSelect = ({
|
||||
|
||||
if (newSelectedRecordIds.length === 0) {
|
||||
emptyFilterButKeepDefinition();
|
||||
removeCombinedViewFilter(fieldId);
|
||||
deleteCombinedViewFilter(fieldId);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import React from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { IconChevronDown } from 'twenty-ui';
|
||||
|
||||
@ -11,8 +11,9 @@ import { StyledHeaderDropdownButton } from '@/ui/layout/dropdown/components/Styl
|
||||
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
|
||||
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
||||
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { availableFilterDefinitionsComponentState } from '@/views/states/availableFilterDefinitionsComponentState';
|
||||
import { getOperandsForFilterType } from '../utils/getOperandsForFilterType';
|
||||
|
||||
import { GenericEntityFilterChip } from './GenericEntityFilterChip';
|
||||
import { ObjectFilterDropdownRecordSelect } from './ObjectFilterDropdownRecordSelect';
|
||||
import { ObjectFilterDropdownSearchInput } from './ObjectFilterDropdownSearchInput';
|
||||
@ -25,14 +26,13 @@ export const SingleEntityObjectFilterDropdownButton = ({
|
||||
hotkeyScope: HotkeyScope;
|
||||
}) => {
|
||||
const {
|
||||
availableFilterDefinitionsState,
|
||||
selectedFilterState,
|
||||
setFilterDefinitionUsedInDropdown,
|
||||
setSelectedOperandInDropdown,
|
||||
} = useFilterDropdown();
|
||||
|
||||
const availableFilterDefinitions = useRecoilValue(
|
||||
availableFilterDefinitionsState,
|
||||
const availableFilterDefinitions = useRecoilComponentValueV2(
|
||||
availableFilterDefinitionsComponentState,
|
||||
);
|
||||
const selectedFilter = useRecoilValue(selectedFilterState);
|
||||
|
||||
|
||||
@ -2,8 +2,10 @@ import { Meta, StoryObj } from '@storybook/react';
|
||||
|
||||
import { TaskGroups } from '@/activities/tasks/components/TaskGroups';
|
||||
import { MultipleFiltersDropdownButton } from '@/object-record/object-filter-dropdown/components/MultipleFiltersDropdownButton';
|
||||
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
|
||||
import { ObjectFilterDropdownScope } from '@/object-record/object-filter-dropdown/scopes/ObjectFilterDropdownScope';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { availableFilterDefinitionsComponentState } from '@/views/states/availableFilterDefinitionsComponentState';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
import { within } from '@storybook/test';
|
||||
import { ComponentDecorator } from 'twenty-ui';
|
||||
import { FieldMetadataType } from '~/generated/graphql';
|
||||
@ -17,9 +19,12 @@ const meta: Meta<typeof MultipleFiltersDropdownButton> = {
|
||||
component: MultipleFiltersDropdownButton,
|
||||
decorators: [
|
||||
(Story) => {
|
||||
const { setAvailableFilterDefinitions } = useFilterDropdown({
|
||||
filterDropdownId: 'entity-tasks-filter-scope',
|
||||
});
|
||||
const instanceId = 'entity-tasks-filter-scope';
|
||||
const setAvailableFilterDefinitions = useSetRecoilComponentStateV2(
|
||||
availableFilterDefinitionsComponentState,
|
||||
instanceId,
|
||||
);
|
||||
|
||||
setAvailableFilterDefinitions([
|
||||
{
|
||||
fieldMetadataId: '1',
|
||||
@ -47,9 +52,11 @@ const meta: Meta<typeof MultipleFiltersDropdownButton> = {
|
||||
},
|
||||
]);
|
||||
return (
|
||||
<ObjectFilterDropdownScope filterScopeId="entity-tasks-filter-scope">
|
||||
<Story />
|
||||
</ObjectFilterDropdownScope>
|
||||
<ViewComponentInstanceContext.Provider value={{ instanceId }}>
|
||||
<ObjectFilterDropdownScope filterScopeId={instanceId}>
|
||||
<Story />
|
||||
</ObjectFilterDropdownScope>
|
||||
</ViewComponentInstanceContext.Provider>
|
||||
);
|
||||
},
|
||||
ObjectMetadataItemsDecorator,
|
||||
|
||||
@ -6,6 +6,8 @@ import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/
|
||||
import { useFilterDropdownStates } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdownStates';
|
||||
import { Filter } from '@/object-record/object-filter-dropdown/types/Filter';
|
||||
import { FilterDefinition } from '@/object-record/object-filter-dropdown/types/FilterDefinition';
|
||||
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
|
||||
import { availableFilterDefinitionsComponentState } from '@/views/states/availableFilterDefinitionsComponentState';
|
||||
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
||||
|
||||
const filterDropdownId = 'filterDropdownId';
|
||||
@ -35,11 +37,13 @@ describe('useFilterDropdown', () => {
|
||||
it('should set availableFilterDefinitions', async () => {
|
||||
const { result } = renderHook(() => {
|
||||
useFilterDropdown({ filterDropdownId });
|
||||
const { availableFilterDefinitionsState } =
|
||||
useFilterDropdownStates(filterDropdownId);
|
||||
|
||||
const [availableFilterDefinitions, setAvailableFilterDefinitions] =
|
||||
useRecoilState(availableFilterDefinitionsState);
|
||||
useRecoilComponentStateV2(
|
||||
availableFilterDefinitionsComponentState,
|
||||
filterDropdownId,
|
||||
);
|
||||
|
||||
return { availableFilterDefinitions, setAvailableFilterDefinitions };
|
||||
}, renderHookConfig);
|
||||
|
||||
|
||||
@ -18,7 +18,6 @@ export const useFilterDropdown = (props?: UseFilterDropdownProps) => {
|
||||
);
|
||||
|
||||
const {
|
||||
availableFilterDefinitionsState,
|
||||
filterDefinitionUsedInDropdownState,
|
||||
objectFilterDropdownSearchInputState,
|
||||
objectFilterDropdownSelectedRecordIdsState,
|
||||
@ -73,9 +72,6 @@ export const useFilterDropdown = (props?: UseFilterDropdownProps) => {
|
||||
],
|
||||
);
|
||||
|
||||
const setAvailableFilterDefinitions = useSetRecoilState(
|
||||
availableFilterDefinitionsState,
|
||||
);
|
||||
const setSelectedFilter = useSetRecoilState(selectedFilterState);
|
||||
const setSelectedOperandInDropdown = useSetRecoilState(
|
||||
selectedOperandInDropdownState,
|
||||
@ -106,7 +102,6 @@ export const useFilterDropdown = (props?: UseFilterDropdownProps) => {
|
||||
resetFilter,
|
||||
setSelectedFilter,
|
||||
setSelectedOperandInDropdown,
|
||||
setAvailableFilterDefinitions,
|
||||
setFilterDefinitionUsedInDropdown,
|
||||
setObjectFilterDropdownSearchInput,
|
||||
// setObjectFilterDropdownSelectedEntityId,
|
||||
@ -116,7 +111,6 @@ export const useFilterDropdown = (props?: UseFilterDropdownProps) => {
|
||||
setIsObjectFilterDropdownUnfolded,
|
||||
setOnFilterSelect,
|
||||
emptyFilterButKeepDefinition,
|
||||
availableFilterDefinitionsState,
|
||||
filterDefinitionUsedInDropdownState,
|
||||
objectFilterDropdownSearchInputState,
|
||||
// objectFilterDropdownSelectedEntityIdState,
|
||||
|
||||
@ -8,14 +8,8 @@ import { onFilterSelectComponentState } from '@/object-record/object-filter-drop
|
||||
import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState';
|
||||
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
|
||||
import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState';
|
||||
import { availableFilterDefinitionsComponentState } from '@/views/states/availableFilterDefinitionsComponentState';
|
||||
|
||||
export const useFilterDropdownStates = (scopeId: string) => {
|
||||
const availableFilterDefinitionsState = extractComponentState(
|
||||
availableFilterDefinitionsComponentState,
|
||||
scopeId,
|
||||
);
|
||||
|
||||
const filterDefinitionUsedInDropdownState = extractComponentState(
|
||||
filterDefinitionUsedInDropdownComponentState,
|
||||
scopeId,
|
||||
@ -63,7 +57,6 @@ export const useFilterDropdownStates = (scopeId: string) => {
|
||||
);
|
||||
|
||||
return {
|
||||
availableFilterDefinitionsState,
|
||||
filterDefinitionUsedInDropdownState,
|
||||
objectFilterDropdownSearchInputState,
|
||||
objectFilterDropdownSelectedRecordIdsState,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext';
|
||||
import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey';
|
||||
import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey';
|
||||
|
||||
type ObjectFilterDropdownScopeInternalContextProps = ComponentStateKey;
|
||||
type ObjectFilterDropdownScopeInternalContextProps = RecoilComponentStateKey;
|
||||
|
||||
export const ObjectFilterDropdownScopeInternalContext =
|
||||
createScopeInternalContext<ObjectFilterDropdownScopeInternalContextProps>();
|
||||
|
||||
@ -6,6 +6,8 @@ import { useSortDropdown } from '@/object-record/object-sort-dropdown/hooks/useS
|
||||
import { useSortDropdownStates } from '@/object-record/object-sort-dropdown/hooks/useSortDropdownStates';
|
||||
import { Sort } from '@/object-record/object-sort-dropdown/types/Sort';
|
||||
import { SortDefinition } from '@/object-record/object-sort-dropdown/types/SortDefinition';
|
||||
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
|
||||
import { availableSortDefinitionsComponentState } from '@/views/states/availableSortDefinitionsComponentState';
|
||||
|
||||
const Wrapper = ({ children }: { children: React.ReactNode }) => (
|
||||
<RecoilRoot>{children}</RecoilRoot>
|
||||
@ -24,11 +26,13 @@ describe('useSortDropdown', () => {
|
||||
it('should set availableSortDefinitions', async () => {
|
||||
const { result } = renderHook(() => {
|
||||
useSortDropdown({ sortDropdownId });
|
||||
const { availableSortDefinitionsState } =
|
||||
useSortDropdownStates(sortDropdownId);
|
||||
|
||||
// TODO: verify this instance id works
|
||||
const [availableSortDefinitions, setAvailableSortDefinitions] =
|
||||
useRecoilState(availableSortDefinitionsState);
|
||||
useRecoilComponentStateV2(
|
||||
availableSortDefinitionsComponentState,
|
||||
sortDropdownId,
|
||||
);
|
||||
|
||||
return {
|
||||
availableSortDefinitions,
|
||||
|
||||
@ -7,6 +7,8 @@ import selectedSortDirectionState from '@/object-record/object-sort-dropdown/sta
|
||||
import { SortDefinition } from '@/object-record/object-sort-dropdown/types/SortDefinition';
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { availableSortDefinitionsComponentState } from '@/views/states/availableSortDefinitionsComponentState';
|
||||
import {
|
||||
OBJECT_SORT_DROPDOWN_ID,
|
||||
VIEW_SORT_DROPDOWN_ID,
|
||||
@ -41,7 +43,6 @@ export const useObjectSortDropdown = () => {
|
||||
};
|
||||
|
||||
const {
|
||||
availableSortDefinitionsState,
|
||||
onSortSelectState,
|
||||
isSortSelectedState,
|
||||
objectSortDropdownSearchInputState,
|
||||
@ -52,8 +53,10 @@ export const useObjectSortDropdown = () => {
|
||||
});
|
||||
|
||||
const isSortSelected = useRecoilValue(isSortSelectedState);
|
||||
const availableSortDefinitions = useRecoilValue(
|
||||
availableSortDefinitionsState,
|
||||
|
||||
const availableSortDefinitions = useRecoilComponentValueV2(
|
||||
availableSortDefinitionsComponentState,
|
||||
VIEW_SORT_DROPDOWN_ID,
|
||||
);
|
||||
const onSortSelect = useRecoilValue(onSortSelectState);
|
||||
|
||||
|
||||
@ -14,8 +14,8 @@ export const useSortDropdown = (props?: UseSortProps) => {
|
||||
ObjectSortDropdownScopeInternalContext,
|
||||
props?.sortDropdownId,
|
||||
);
|
||||
|
||||
const {
|
||||
availableSortDefinitionsState,
|
||||
isSortSelectedState,
|
||||
onSortSelectState,
|
||||
objectSortDropdownSearchInputState,
|
||||
@ -35,7 +35,6 @@ export const useSortDropdown = (props?: UseSortProps) => {
|
||||
|
||||
return {
|
||||
scopeId,
|
||||
availableSortDefinitionsState,
|
||||
isSortSelectedState,
|
||||
onSortSelectState,
|
||||
objectSortDropdownSearchInputState,
|
||||
|
||||
@ -2,14 +2,8 @@ import { isSortSelectedComponentState } from '@/object-record/object-sort-dropdo
|
||||
import { objectSortDropdownSearchInputComponentState } from '@/object-record/object-sort-dropdown/states/objectSortDropdownSearchInputComponentState';
|
||||
import { onSortSelectComponentState } from '@/object-record/object-sort-dropdown/states/onSortSelectScopedState';
|
||||
import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState';
|
||||
import { availableSortDefinitionsComponentState } from '@/views/states/availableSortDefinitionsComponentState';
|
||||
|
||||
export const useSortDropdownStates = (scopeId: string) => {
|
||||
const availableSortDefinitionsState = extractComponentState(
|
||||
availableSortDefinitionsComponentState,
|
||||
scopeId,
|
||||
);
|
||||
|
||||
const isSortSelectedState = extractComponentState(
|
||||
isSortSelectedComponentState,
|
||||
scopeId,
|
||||
@ -26,7 +20,6 @@ export const useSortDropdownStates = (scopeId: string) => {
|
||||
);
|
||||
|
||||
return {
|
||||
availableSortDefinitionsState,
|
||||
isSortSelectedState,
|
||||
onSortSelectState,
|
||||
objectSortDropdownSearchInputState,
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext';
|
||||
import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey';
|
||||
import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey';
|
||||
|
||||
import { Sort } from '../../types/Sort';
|
||||
|
||||
type ObjectSortDropdownScopeInternalContextProps = ComponentStateKey & {
|
||||
type ObjectSortDropdownScopeInternalContextProps = RecoilComponentStateKey & {
|
||||
onSortSelect?: (sort: Sort) => void;
|
||||
};
|
||||
|
||||
|
||||
@ -2,9 +2,9 @@ import { RecordBoardColumnDefinition } from '@/object-record/record-board/types/
|
||||
import { FieldDefinition } from '@/object-record/record-field/types/FieldDefinition';
|
||||
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
|
||||
import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext';
|
||||
import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey';
|
||||
import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey';
|
||||
|
||||
type RecordBoardScopeInternalContextProps = ComponentStateKey & {
|
||||
type RecordBoardScopeInternalContextProps = RecoilComponentStateKey & {
|
||||
onFieldsChange: (fields: FieldDefinition<FieldMetadata>[]) => void;
|
||||
onColumnsChange: (column: RecordBoardColumnDefinition[]) => void;
|
||||
};
|
||||
|
||||
@ -27,7 +27,7 @@ export const useInitDraftValueV2 = <FieldValue>() => {
|
||||
const recordFieldInputScopeId = `${getRecordFieldInputId(
|
||||
recordId,
|
||||
fieldDefinition?.metadata?.fieldName,
|
||||
)}-scope`;
|
||||
)}`;
|
||||
|
||||
const getDraftValueSelector = extractComponentSelector<
|
||||
FieldInputDraftValue<FieldValue> | undefined
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext';
|
||||
import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey';
|
||||
import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey';
|
||||
|
||||
type RecordFieldInputScopeInternalContextProps = ComponentStateKey;
|
||||
type RecordFieldInputScopeInternalContextProps = RecoilComponentStateKey;
|
||||
|
||||
export const RecordFieldInputScopeInternalContext =
|
||||
createScopeInternalContext<RecordFieldInputScopeInternalContextProps>();
|
||||
|
||||
@ -24,6 +24,7 @@ import { RecordFieldValueSelectorContextProvider } from '@/object-record/record-
|
||||
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
|
||||
import { SpreadsheetImportProvider } from '@/spreadsheet-import/provider/components/SpreadsheetImportProvider';
|
||||
import { ViewBar } from '@/views/components/ViewBar';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
import { ViewField } from '@/views/types/ViewField';
|
||||
import { ViewType } from '@/views/types/ViewType';
|
||||
import { mapViewFieldsToColumnDefinitions } from '@/views/utils/mapViewFieldsToColumnDefinitions';
|
||||
@ -107,81 +108,91 @@ export const RecordIndexContainer = () => {
|
||||
return (
|
||||
<StyledContainer>
|
||||
<InformationBannerWrapper />
|
||||
<RecordFieldValueSelectorContextProvider>
|
||||
<SpreadsheetImportProvider>
|
||||
<StyledContainerWithPadding>
|
||||
<ViewBar
|
||||
viewBarId={recordIndexId}
|
||||
optionsDropdownButton={
|
||||
<RecordIndexOptionsDropdown
|
||||
recordIndexId={recordIndexId}
|
||||
objectNameSingular={objectNameSingular}
|
||||
viewType={recordIndexViewType ?? ViewType.Table}
|
||||
/>
|
||||
}
|
||||
onCurrentViewChange={(view) => {
|
||||
if (!view) {
|
||||
return;
|
||||
<ViewComponentInstanceContext.Provider
|
||||
value={{ instanceId: recordIndexId }}
|
||||
>
|
||||
<RecordFieldValueSelectorContextProvider>
|
||||
<SpreadsheetImportProvider>
|
||||
<StyledContainerWithPadding>
|
||||
<ViewBar
|
||||
viewBarId={recordIndexId}
|
||||
optionsDropdownButton={
|
||||
<RecordIndexOptionsDropdown
|
||||
recordIndexId={recordIndexId}
|
||||
objectNameSingular={objectNameSingular}
|
||||
viewType={recordIndexViewType ?? ViewType.Table}
|
||||
/>
|
||||
}
|
||||
onCurrentViewChange={(view) => {
|
||||
if (!view) {
|
||||
return;
|
||||
}
|
||||
|
||||
onViewFieldsChange(view.viewFields);
|
||||
setTableFilters(
|
||||
mapViewFiltersToFilters(view.viewFilters, filterDefinitions),
|
||||
);
|
||||
setRecordIndexFilters(
|
||||
mapViewFiltersToFilters(view.viewFilters, filterDefinitions),
|
||||
);
|
||||
setTableSorts(
|
||||
mapViewSortsToSorts(view.viewSorts, sortDefinitions),
|
||||
);
|
||||
setRecordIndexSorts(
|
||||
mapViewSortsToSorts(view.viewSorts, sortDefinitions),
|
||||
);
|
||||
setRecordIndexViewType(view.type);
|
||||
setRecordIndexViewKanbanFieldMetadataIdState(
|
||||
view.kanbanFieldMetadataId,
|
||||
);
|
||||
setRecordIndexIsCompactModeActive(view.isCompact);
|
||||
}}
|
||||
/>
|
||||
<RecordIndexViewBarEffect
|
||||
objectNamePlural={objectNamePlural}
|
||||
viewBarId={recordIndexId}
|
||||
/>
|
||||
</StyledContainerWithPadding>
|
||||
</SpreadsheetImportProvider>
|
||||
onViewFieldsChange(view.viewFields);
|
||||
setTableFilters(
|
||||
mapViewFiltersToFilters(
|
||||
view.viewFilters,
|
||||
filterDefinitions,
|
||||
),
|
||||
);
|
||||
setRecordIndexFilters(
|
||||
mapViewFiltersToFilters(
|
||||
view.viewFilters,
|
||||
filterDefinitions,
|
||||
),
|
||||
);
|
||||
setTableSorts(
|
||||
mapViewSortsToSorts(view.viewSorts, sortDefinitions),
|
||||
);
|
||||
setRecordIndexSorts(
|
||||
mapViewSortsToSorts(view.viewSorts, sortDefinitions),
|
||||
);
|
||||
setRecordIndexViewType(view.type);
|
||||
setRecordIndexViewKanbanFieldMetadataIdState(
|
||||
view.kanbanFieldMetadataId,
|
||||
);
|
||||
setRecordIndexIsCompactModeActive(view.isCompact);
|
||||
}}
|
||||
/>
|
||||
<RecordIndexViewBarEffect
|
||||
objectNamePlural={objectNamePlural}
|
||||
viewBarId={recordIndexId}
|
||||
/>
|
||||
</StyledContainerWithPadding>
|
||||
</SpreadsheetImportProvider>
|
||||
|
||||
{recordIndexViewType === ViewType.Table && (
|
||||
<>
|
||||
<RecordIndexTableContainer
|
||||
recordTableId={recordIndexId}
|
||||
viewBarId={recordIndexId}
|
||||
/>
|
||||
<RecordIndexTableContainerEffect
|
||||
objectNameSingular={objectNameSingular}
|
||||
recordTableId={recordIndexId}
|
||||
viewBarId={recordIndexId}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{recordIndexViewType === ViewType.Kanban && (
|
||||
<StyledContainerWithPadding fullHeight>
|
||||
<RecordIndexBoardContainer
|
||||
recordBoardId={recordIndexId}
|
||||
viewBarId={recordIndexId}
|
||||
objectNameSingular={objectNameSingular}
|
||||
/>
|
||||
<RecordIndexBoardDataLoader
|
||||
objectNameSingular={objectNameSingular}
|
||||
recordBoardId={recordIndexId}
|
||||
/>
|
||||
<RecordIndexBoardDataLoaderEffect
|
||||
objectNameSingular={objectNameSingular}
|
||||
recordBoardId={recordIndexId}
|
||||
/>
|
||||
</StyledContainerWithPadding>
|
||||
)}
|
||||
</RecordFieldValueSelectorContextProvider>
|
||||
{recordIndexViewType === ViewType.Table && (
|
||||
<>
|
||||
<RecordIndexTableContainer
|
||||
recordTableId={recordIndexId}
|
||||
viewBarId={recordIndexId}
|
||||
/>
|
||||
<RecordIndexTableContainerEffect
|
||||
objectNameSingular={objectNameSingular}
|
||||
recordTableId={recordIndexId}
|
||||
viewBarId={recordIndexId}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{recordIndexViewType === ViewType.Kanban && (
|
||||
<StyledContainerWithPadding fullHeight>
|
||||
<RecordIndexBoardContainer
|
||||
recordBoardId={recordIndexId}
|
||||
viewBarId={recordIndexId}
|
||||
objectNameSingular={objectNameSingular}
|
||||
/>
|
||||
<RecordIndexBoardDataLoader
|
||||
objectNameSingular={objectNameSingular}
|
||||
recordBoardId={recordIndexId}
|
||||
/>
|
||||
<RecordIndexBoardDataLoaderEffect
|
||||
objectNameSingular={objectNameSingular}
|
||||
recordBoardId={recordIndexId}
|
||||
/>
|
||||
</StyledContainerWithPadding>
|
||||
)}
|
||||
</RecordFieldValueSelectorContextProvider>
|
||||
</ViewComponentInstanceContext.Provider>
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
|
||||
@ -2,7 +2,7 @@ import { useRecoilState } from 'recoil';
|
||||
|
||||
import { isRemoveSortingModalOpenState } from '@/object-record/record-table/states/isRemoveSortingModalOpenState';
|
||||
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
|
||||
import { useCombinedViewSorts } from '@/views/hooks/useCombinedViewSorts';
|
||||
import { useDeleteCombinedViewSorts } from '@/views/hooks/useDeleteCombinedViewSorts';
|
||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||
|
||||
export const RecordIndexRemoveSortingModal = ({
|
||||
@ -21,11 +21,11 @@ export const RecordIndexRemoveSortingModal = ({
|
||||
isRemoveSortingModalOpenState,
|
||||
);
|
||||
|
||||
const { removeCombinedViewSort } = useCombinedViewSorts(recordTableId);
|
||||
const { deleteCombinedViewSort } = useDeleteCombinedViewSorts(recordTableId);
|
||||
|
||||
const handleRemoveClick = () => {
|
||||
fieldMetadataIds.forEach((id) => {
|
||||
removeCombinedViewSort(id);
|
||||
deleteCombinedViewSort(id);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@ -8,8 +8,9 @@ import { useHandleToggleColumnFilter } from '@/object-record/record-index/hooks/
|
||||
import { useHandleToggleColumnSort } from '@/object-record/record-index/hooks/useHandleToggleColumnSort';
|
||||
import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates';
|
||||
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
|
||||
import { useViewStates } from '@/views/hooks/internal/useViewStates';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecordCountInCurrentView } from '@/views/hooks/useSetRecordCountInCurrentView';
|
||||
import { entityCountInCurrentViewComponentState } from '@/views/states/entityCountInCurrentViewComponentState';
|
||||
|
||||
type RecordIndexTableContainerEffectProps = {
|
||||
objectNameSingular: string;
|
||||
@ -50,9 +51,10 @@ export const RecordIndexTableContainerEffect = ({
|
||||
const { tableRowIdsState, hasUserSelectedAllRowsState } =
|
||||
useRecordTableStates(recordTableId);
|
||||
|
||||
const { entityCountInCurrentViewState } = useViewStates(recordTableId);
|
||||
const entityCountInCurrentView = useRecoilValue(
|
||||
entityCountInCurrentViewState,
|
||||
// TODO: verify this instance id works
|
||||
const entityCountInCurrentView = useRecoilComponentValueV2(
|
||||
entityCountInCurrentViewComponentState,
|
||||
recordTableId,
|
||||
);
|
||||
const hasUserSelectedAllRows = useRecoilValue(hasUserSelectedAllRowsState);
|
||||
const tableRowIds = useRecoilValue(tableRowIdsState);
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { buildShowPageURL } from '@/object-record/record-show/utils/buildShowPageURL';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
export const useHandleIndexIdentifierClick = ({
|
||||
objectMetadataItem,
|
||||
@ -13,10 +13,9 @@ export const useHandleIndexIdentifierClick = ({
|
||||
}) => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const currentViewId = useRecoilValue(
|
||||
currentViewIdComponentState({
|
||||
scopeId: recordIndexId,
|
||||
}),
|
||||
const currentViewId = useRecoilComponentValueV2(
|
||||
currentViewIdComponentState,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
const handleIndexIdentifierClick = (recordId: string) => {
|
||||
|
||||
@ -7,7 +7,7 @@ import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldM
|
||||
import { Filter } from '@/object-record/object-filter-dropdown/types/Filter';
|
||||
import { getOperandsForFilterType } from '@/object-record/object-filter-dropdown/utils/getOperandsForFilterType';
|
||||
import { useDropdownV2 } from '@/ui/layout/dropdown/hooks/useDropdownV2';
|
||||
import { useCombinedViewFilters } from '@/views/hooks/useCombinedViewFilters';
|
||||
import { useUpsertCombinedViewFilters } from '@/views/hooks/useUpsertCombinedViewFilters';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
type UseHandleToggleColumnFilterProps = {
|
||||
@ -26,7 +26,7 @@ export const useHandleToggleColumnFilter = ({
|
||||
const { columnDefinitions } =
|
||||
useColumnDefinitionsFromFieldMetadata(objectMetadataItem);
|
||||
|
||||
const { upsertCombinedViewFilter } = useCombinedViewFilters(viewBarId);
|
||||
const { upsertCombinedViewFilter } = useUpsertCombinedViewFilters(viewBarId);
|
||||
const { openDropdown } = useDropdownV2();
|
||||
|
||||
const handleToggleColumnFilter = useCallback(
|
||||
|
||||
@ -3,7 +3,7 @@ import { useCallback } from 'react';
|
||||
import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata';
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { Sort } from '@/object-record/object-sort-dropdown/types/Sort';
|
||||
import { useCombinedViewSorts } from '@/views/hooks/useCombinedViewSorts';
|
||||
import { useUpsertCombinedViewSorts } from '@/views/hooks/useUpsertCombinedViewSorts';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
type UseHandleToggleColumnSortProps = {
|
||||
@ -22,7 +22,7 @@ export const useHandleToggleColumnSort = ({
|
||||
const { columnDefinitions } =
|
||||
useColumnDefinitionsFromFieldMetadata(objectMetadataItem);
|
||||
|
||||
const { upsertCombinedViewSort } = useCombinedViewSorts(viewBarId);
|
||||
const { upsertCombinedViewSort } = useUpsertCombinedViewSorts(viewBarId);
|
||||
|
||||
const handleToggleColumnSort = useCallback(
|
||||
(fieldMetadataId: string) => {
|
||||
|
||||
@ -6,7 +6,7 @@ import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadata
|
||||
import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
|
||||
import { Filter } from '@/object-record/object-filter-dropdown/types/Filter';
|
||||
import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates';
|
||||
import { useCombinedViewFilters } from '@/views/hooks/useCombinedViewFilters';
|
||||
import { useUpsertCombinedViewFilters } from '@/views/hooks/useUpsertCombinedViewFilters';
|
||||
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
@ -27,7 +27,7 @@ export const useHandleToggleTrashColumnFilter = ({
|
||||
const { columnDefinitions } =
|
||||
useColumnDefinitionsFromFieldMetadata(objectMetadataItem);
|
||||
|
||||
const { upsertCombinedViewFilter } = useCombinedViewFilters(viewBarId);
|
||||
const { upsertCombinedViewFilter } = useUpsertCombinedViewFilters(viewBarId);
|
||||
const { isSoftDeleteActiveState } = useRecordTableStates(viewBarId);
|
||||
|
||||
const handleToggleTrashColumnFilter = useCallback(() => {
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { SnackBarProviderScope } from '@/ui/feedback/snack-bar-manager/scopes/SnackBarProviderScope';
|
||||
import { act, renderHook, waitFor } from '@testing-library/react';
|
||||
import { percentage, sleep, useTableData } from '../useTableData';
|
||||
|
||||
import { useRecordBoard } from '@/object-record/record-board/hooks/useRecordBoard';
|
||||
import { recordBoardKanbanFieldMetadataNameComponentState } from '@/object-record/record-board/states/recordBoardKanbanFieldMetadataNameComponentState';
|
||||
import { useRecordIndexOptionsForBoard } from '@/object-record/record-index/options/hooks/useRecordIndexOptionsForBoard';
|
||||
import { SnackBarManagerScopeInternalContext } from '@/ui/feedback/snack-bar-manager/scopes/scope-internal-context/SnackBarManagerScopeInternalContext';
|
||||
import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState';
|
||||
import { ViewType } from '@/views/types/ViewType';
|
||||
import { MockedProvider, MockedResponse } from '@apollo/client/testing';
|
||||
@ -148,15 +148,19 @@ const mocks: MockedResponse[] = [
|
||||
];
|
||||
|
||||
const Wrapper = ({ children }: { children: ReactNode }) => (
|
||||
<Router>
|
||||
<RecoilRoot>
|
||||
<SnackBarProviderScope snackBarManagerScopeId="snack-bar-manager">
|
||||
<SnackBarManagerScopeInternalContext.Provider
|
||||
value={{
|
||||
scopeId: 'snack-bar-manager',
|
||||
}}
|
||||
>
|
||||
<Router>
|
||||
<RecoilRoot>
|
||||
<MockedProvider addTypename={false} mocks={mocks}>
|
||||
{children}
|
||||
</MockedProvider>
|
||||
</SnackBarProviderScope>
|
||||
</RecoilRoot>
|
||||
</Router>
|
||||
</RecoilRoot>
|
||||
</Router>
|
||||
</SnackBarManagerScopeInternalContext.Provider>
|
||||
);
|
||||
|
||||
const graphqlEmptyResponse = [
|
||||
@ -174,15 +178,19 @@ const graphqlEmptyResponse = [
|
||||
];
|
||||
|
||||
const WrapperWithEmptyResponse = ({ children }: { children: ReactNode }) => (
|
||||
<Router>
|
||||
<RecoilRoot>
|
||||
<SnackBarProviderScope snackBarManagerScopeId="snack-bar-manager">
|
||||
<SnackBarManagerScopeInternalContext.Provider
|
||||
value={{
|
||||
scopeId: 'snack-bar-manager',
|
||||
}}
|
||||
>
|
||||
<Router>
|
||||
<RecoilRoot>
|
||||
<MockedProvider addTypename={false} mocks={graphqlEmptyResponse}>
|
||||
{children}
|
||||
</MockedProvider>
|
||||
</SnackBarProviderScope>
|
||||
</RecoilRoot>
|
||||
</Router>
|
||||
</RecoilRoot>
|
||||
</Router>
|
||||
</SnackBarManagerScopeInternalContext.Provider>
|
||||
);
|
||||
|
||||
describe('useTableData', () => {
|
||||
@ -191,13 +199,13 @@ describe('useTableData', () => {
|
||||
describe('data fetching', () => {
|
||||
it('should handle no records', async () => {
|
||||
const callback = jest.fn();
|
||||
|
||||
const { result } = renderHook(
|
||||
() =>
|
||||
useTableData({
|
||||
recordIndexId,
|
||||
objectNameSingular,
|
||||
callback,
|
||||
|
||||
delayMs: 0,
|
||||
viewType: ViewType.Kanban,
|
||||
}),
|
||||
@ -209,7 +217,7 @@ describe('useTableData', () => {
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(callback).toHaveBeenCalledWith([], []);
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { OnDragEndResponder } from '@hello-pangea/dnd';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { useRecoilState } from 'recoil';
|
||||
|
||||
import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata';
|
||||
@ -8,8 +8,8 @@ import { useRecordBoard } from '@/object-record/record-board/hooks/useRecordBoar
|
||||
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
|
||||
import { recordIndexFieldDefinitionsState } from '@/object-record/record-index/states/recordIndexFieldDefinitionsState';
|
||||
import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
|
||||
import { useHandleViews } from '@/views/hooks/useHandleViews';
|
||||
import { useSaveCurrentViewFields } from '@/views/hooks/useSaveCurrentViewFields';
|
||||
import { useUpdateCurrentView } from '@/views/hooks/useUpdateCurrentView';
|
||||
import { GraphQLView } from '@/views/types/GraphQLView';
|
||||
import { mapBoardFieldDefinitionsToViewFields } from '@/views/utils/mapBoardFieldDefinitionsToViewFields';
|
||||
import { mapArrayToObject } from '~/utils/array/mapArrayToObject';
|
||||
@ -31,7 +31,7 @@ export const useRecordIndexOptionsForBoard = ({
|
||||
useRecoilState(recordIndexFieldDefinitionsState);
|
||||
|
||||
const { saveViewFields } = useSaveCurrentViewFields(viewBarId);
|
||||
const { updateCurrentView } = useHandleViews(viewBarId);
|
||||
const { updateCurrentView } = useUpdateCurrentView(viewBarId);
|
||||
const { isCompactModeActiveState } = useRecordBoard(recordBoardId);
|
||||
|
||||
const [isCompactModeActive, setIsCompactModeActive] = useRecoilState(
|
||||
|
||||
@ -2,7 +2,8 @@ import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates';
|
||||
import { ActionBar } from '@/ui/navigation/action-bar/components/ActionBar';
|
||||
import { useViewStates } from '@/views/hooks/internal/useViewStates';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { entityCountInCurrentViewComponentState } from '@/views/states/entityCountInCurrentViewComponentState';
|
||||
|
||||
export const RecordTableActionBar = ({
|
||||
recordTableId,
|
||||
@ -15,10 +16,12 @@ export const RecordTableActionBar = ({
|
||||
hasUserSelectedAllRowsState,
|
||||
} = useRecordTableStates(recordTableId);
|
||||
|
||||
const { entityCountInCurrentViewState } = useViewStates(recordTableId);
|
||||
const entityCountInCurrentView = useRecoilValue(
|
||||
entityCountInCurrentViewState,
|
||||
// TODO: verify this instance id works
|
||||
const entityCountInCurrentView = useRecoilComponentValueV2(
|
||||
entityCountInCurrentViewComponentState,
|
||||
recordTableId,
|
||||
);
|
||||
|
||||
const hasUserSelectedAllRows = useRecoilValue(hasUserSelectedAllRowsState);
|
||||
const tableRowIds = useRecoilValue(tableRowIdsState);
|
||||
const selectedRowIds = useRecoilValue(selectedRowIdsSelector());
|
||||
|
||||
@ -5,7 +5,7 @@ import { useHandleToggleTrashColumnFilter } from '@/object-record/record-index/h
|
||||
import { RecordTableContext } from '@/object-record/record-table/contexts/RecordTableContext';
|
||||
import { RecordTableEmptyStateDisplay } from '@/object-record/record-table/empty-state/components/RecordTableEmptyStateDisplay';
|
||||
import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates';
|
||||
import { useCombinedViewFilters } from '@/views/hooks/useCombinedViewFilters';
|
||||
import { useDeleteCombinedViewFilters } from '@/views/hooks/useDeleteCombinedViewFilters';
|
||||
import { useContext } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
@ -13,7 +13,8 @@ export const RecordTableEmptyStateSoftDelete = () => {
|
||||
const { objectMetadataItem, objectNameSingular, recordTableId } =
|
||||
useContext(RecordTableContext);
|
||||
|
||||
const { removeCombinedViewFilter } = useCombinedViewFilters(recordTableId);
|
||||
const { deleteCombinedViewFilter } =
|
||||
useDeleteCombinedViewFilters(recordTableId);
|
||||
const { tableFiltersState } = useRecordTableStates(recordTableId);
|
||||
|
||||
const tableFilters = useRecoilValue(tableFiltersState);
|
||||
@ -24,7 +25,7 @@ export const RecordTableEmptyStateSoftDelete = () => {
|
||||
});
|
||||
|
||||
const handleButtonClick = async () => {
|
||||
removeCombinedViewFilter(
|
||||
deleteCombinedViewFilter(
|
||||
tableFilters.find(
|
||||
(filter) =>
|
||||
filter.definition.label === 'Deleted at' &&
|
||||
|
||||
@ -48,14 +48,14 @@ describe('useSelectedTableCellEditMode', () => {
|
||||
|
||||
expect(mockCallbackInterface.set).toHaveBeenCalledWith(
|
||||
{
|
||||
key: 'isTableCellInEditModeComponentFamilyState__{"familyKey":{"column":0,"row":0},"scopeId":"yourScopeId-scope"}',
|
||||
key: 'isTableCellInEditModeComponentFamilyState__{"familyKey":{"column":0,"row":0},"scopeId":"yourScopeId"}',
|
||||
},
|
||||
false,
|
||||
);
|
||||
|
||||
expect(mockCallbackInterface.set).toHaveBeenCalledWith(
|
||||
{
|
||||
key: 'isTableCellInEditModeComponentFamilyState__{"familyKey":{"column":5,"row":1},"scopeId":"yourScopeId-scope"}',
|
||||
key: 'isTableCellInEditModeComponentFamilyState__{"familyKey":{"column":5,"row":1},"scopeId":"yourScopeId"}',
|
||||
},
|
||||
true,
|
||||
);
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
|
||||
import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext';
|
||||
import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey';
|
||||
import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey';
|
||||
|
||||
import { ColumnDefinition } from '../../types/ColumnDefinition';
|
||||
|
||||
// TODO: separate scope contexts from event contexts
|
||||
type RecordTableScopeInternalContextProps = ComponentStateKey & {
|
||||
type RecordTableScopeInternalContextProps = RecoilComponentStateKey & {
|
||||
onColumnsChange: (columns: ColumnDefinition<FieldMetadata>[]) => void;
|
||||
};
|
||||
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { RecordTableScopeInternalContext } from '@/object-record/record-table/scopes/scope-internal-context/RecordTableScopeInternalContext';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { createComponentStateV2_alpha } from '@/ui/utilities/state/component-state/utils/createComponentStateV2_alpha';
|
||||
|
||||
export const hasRecordTableFetchedAllRecordsComponentStateV2 =
|
||||
createComponentStateV2<boolean>({
|
||||
createComponentStateV2_alpha<boolean>({
|
||||
key: 'hasRecordTableFetchedAllRecordsComponentStateV2',
|
||||
componentContext: RecordTableScopeInternalContext,
|
||||
defaultValue: false,
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { RecordTableScopeInternalContext } from '@/object-record/record-table/scopes/scope-internal-context/RecordTableScopeInternalContext';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { createComponentStateV2_alpha } from '@/ui/utilities/state/component-state/utils/createComponentStateV2_alpha';
|
||||
|
||||
export const isRecordTableScrolledLeftComponentState =
|
||||
createComponentStateV2<boolean>({
|
||||
createComponentStateV2_alpha<boolean>({
|
||||
key: 'isRecordTableScrolledLeftComponentState',
|
||||
componentContext: RecordTableScopeInternalContext,
|
||||
defaultValue: true,
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { RecordTableScopeInternalContext } from '@/object-record/record-table/scopes/scope-internal-context/RecordTableScopeInternalContext';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { createComponentStateV2_alpha } from '@/ui/utilities/state/component-state/utils/createComponentStateV2_alpha';
|
||||
|
||||
export const isRecordTableScrolledTopComponentState =
|
||||
createComponentStateV2<boolean>({
|
||||
createComponentStateV2_alpha<boolean>({
|
||||
key: 'isRecordTableScrolledTopComponentState',
|
||||
componentContext: RecordTableScopeInternalContext,
|
||||
defaultValue: true,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext';
|
||||
import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey';
|
||||
import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey';
|
||||
|
||||
type RelationPickerScopeInternalContextProps = ComponentStateKey;
|
||||
type RelationPickerScopeInternalContextProps = RecoilComponentStateKey;
|
||||
|
||||
export const RelationPickerScopeInternalContext =
|
||||
createScopeInternalContext<RelationPickerScopeInternalContextProps>();
|
||||
|
||||
Reference in New Issue
Block a user