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 { ObjectFilterDropdownScope } from '@/object-record/object-filter-dropdown/scopes/ObjectFilterDropdownScope';
|
||||||
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
|
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 { MultipleFiltersDropdownButton } from './MultipleFiltersDropdownButton';
|
||||||
import { SingleEntityObjectFilterDropdownButton } from './SingleEntityObjectFilterDropdownButton';
|
import { SingleEntityObjectFilterDropdownButton } from './SingleEntityObjectFilterDropdownButton';
|
||||||
|
|
||||||
@ -16,12 +15,9 @@ export const ObjectFilterDropdownButton = ({
|
|||||||
filterDropdownId,
|
filterDropdownId,
|
||||||
hotkeyScope,
|
hotkeyScope,
|
||||||
}: ObjectFilterDropdownButtonProps) => {
|
}: ObjectFilterDropdownButtonProps) => {
|
||||||
const { availableFilterDefinitionsState } = useFilterDropdown({
|
const availableFilterDefinitions = useRecoilComponentValueV2(
|
||||||
filterDropdownId: filterDropdownId,
|
availableFilterDefinitionsComponentState,
|
||||||
});
|
filterDropdownId,
|
||||||
|
|
||||||
const availableFilterDefinitions = useRecoilValue(
|
|
||||||
availableFilterDefinitionsState,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const hasOnlyOneEntityFilter =
|
const hasOnlyOneEntityFilter =
|
||||||
|
|||||||
@ -1,8 +1,6 @@
|
|||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { useState } from 'react';
|
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 { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||||
|
|
||||||
import { ObjectFilterDropdownFilterSelectMenuItem } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItem';
|
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 { SelectableItem } from '@/ui/layout/selectable-list/components/SelectableItem';
|
||||||
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
|
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
|
||||||
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
|
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';
|
import { isDefined } from 'twenty-ui';
|
||||||
|
|
||||||
export const StyledInput = styled.input`
|
export const StyledInput = styled.input`
|
||||||
@ -43,10 +43,8 @@ export const StyledInput = styled.input`
|
|||||||
export const ObjectFilterDropdownFilterSelect = () => {
|
export const ObjectFilterDropdownFilterSelect = () => {
|
||||||
const [searchText, setSearchText] = useState('');
|
const [searchText, setSearchText] = useState('');
|
||||||
|
|
||||||
const { availableFilterDefinitionsState } = useFilterDropdown();
|
const availableFilterDefinitions = useRecoilComponentValueV2(
|
||||||
|
availableFilterDefinitionsComponentState,
|
||||||
const availableFilterDefinitions = useRecoilValue(
|
|
||||||
availableFilterDefinitionsState,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const sortedAvailableFilterDefinitions = [...availableFilterDefinitions]
|
const sortedAvailableFilterDefinitions = [...availableFilterDefinitions]
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types
|
|||||||
import { MultipleRecordSelectDropdown } from '@/object-record/select/components/MultipleRecordSelectDropdown';
|
import { MultipleRecordSelectDropdown } from '@/object-record/select/components/MultipleRecordSelectDropdown';
|
||||||
import { useRecordsForSelect } from '@/object-record/select/hooks/useRecordsForSelect';
|
import { useRecordsForSelect } from '@/object-record/select/hooks/useRecordsForSelect';
|
||||||
import { SelectableRecord } from '@/object-record/select/types/SelectableRecord';
|
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 { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isDefined } from '~/utils/isDefined';
|
||||||
|
|
||||||
@ -17,6 +17,7 @@ export const MAX_RECORDS_TO_DISPLAY = 3;
|
|||||||
type ObjectFilterDropdownRecordSelectProps = {
|
type ObjectFilterDropdownRecordSelectProps = {
|
||||||
viewComponentId?: string;
|
viewComponentId?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ObjectFilterDropdownRecordSelect = ({
|
export const ObjectFilterDropdownRecordSelect = ({
|
||||||
viewComponentId,
|
viewComponentId,
|
||||||
}: ObjectFilterDropdownRecordSelectProps) => {
|
}: ObjectFilterDropdownRecordSelectProps) => {
|
||||||
@ -31,7 +32,9 @@ export const ObjectFilterDropdownRecordSelect = ({
|
|||||||
emptyFilterButKeepDefinition,
|
emptyFilterButKeepDefinition,
|
||||||
} = useFilterDropdown();
|
} = useFilterDropdown();
|
||||||
|
|
||||||
const { removeCombinedViewFilter } = useCombinedViewFilters(viewComponentId);
|
const { deleteCombinedViewFilter } =
|
||||||
|
useDeleteCombinedViewFilters(viewComponentId);
|
||||||
|
|
||||||
const { currentViewWithCombinedFiltersAndSorts } =
|
const { currentViewWithCombinedFiltersAndSorts } =
|
||||||
useGetCurrentView(viewComponentId);
|
useGetCurrentView(viewComponentId);
|
||||||
|
|
||||||
@ -78,7 +81,7 @@ export const ObjectFilterDropdownRecordSelect = ({
|
|||||||
|
|
||||||
if (newSelectedRecordIds.length === 0) {
|
if (newSelectedRecordIds.length === 0) {
|
||||||
emptyFilterButKeepDefinition();
|
emptyFilterButKeepDefinition();
|
||||||
removeCombinedViewFilter(fieldId);
|
deleteCombinedViewFilter(fieldId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
|
||||||
import { useTheme } from '@emotion/react';
|
import { useTheme } from '@emotion/react';
|
||||||
|
import React from 'react';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
import { IconChevronDown } from 'twenty-ui';
|
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 { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
|
||||||
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
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 { getOperandsForFilterType } from '../utils/getOperandsForFilterType';
|
||||||
|
|
||||||
import { GenericEntityFilterChip } from './GenericEntityFilterChip';
|
import { GenericEntityFilterChip } from './GenericEntityFilterChip';
|
||||||
import { ObjectFilterDropdownRecordSelect } from './ObjectFilterDropdownRecordSelect';
|
import { ObjectFilterDropdownRecordSelect } from './ObjectFilterDropdownRecordSelect';
|
||||||
import { ObjectFilterDropdownSearchInput } from './ObjectFilterDropdownSearchInput';
|
import { ObjectFilterDropdownSearchInput } from './ObjectFilterDropdownSearchInput';
|
||||||
@ -25,14 +26,13 @@ export const SingleEntityObjectFilterDropdownButton = ({
|
|||||||
hotkeyScope: HotkeyScope;
|
hotkeyScope: HotkeyScope;
|
||||||
}) => {
|
}) => {
|
||||||
const {
|
const {
|
||||||
availableFilterDefinitionsState,
|
|
||||||
selectedFilterState,
|
selectedFilterState,
|
||||||
setFilterDefinitionUsedInDropdown,
|
setFilterDefinitionUsedInDropdown,
|
||||||
setSelectedOperandInDropdown,
|
setSelectedOperandInDropdown,
|
||||||
} = useFilterDropdown();
|
} = useFilterDropdown();
|
||||||
|
|
||||||
const availableFilterDefinitions = useRecoilValue(
|
const availableFilterDefinitions = useRecoilComponentValueV2(
|
||||||
availableFilterDefinitionsState,
|
availableFilterDefinitionsComponentState,
|
||||||
);
|
);
|
||||||
const selectedFilter = useRecoilValue(selectedFilterState);
|
const selectedFilter = useRecoilValue(selectedFilterState);
|
||||||
|
|
||||||
|
|||||||
@ -2,8 +2,10 @@ import { Meta, StoryObj } from '@storybook/react';
|
|||||||
|
|
||||||
import { TaskGroups } from '@/activities/tasks/components/TaskGroups';
|
import { TaskGroups } from '@/activities/tasks/components/TaskGroups';
|
||||||
import { MultipleFiltersDropdownButton } from '@/object-record/object-filter-dropdown/components/MultipleFiltersDropdownButton';
|
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 { 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 { within } from '@storybook/test';
|
||||||
import { ComponentDecorator } from 'twenty-ui';
|
import { ComponentDecorator } from 'twenty-ui';
|
||||||
import { FieldMetadataType } from '~/generated/graphql';
|
import { FieldMetadataType } from '~/generated/graphql';
|
||||||
@ -17,9 +19,12 @@ const meta: Meta<typeof MultipleFiltersDropdownButton> = {
|
|||||||
component: MultipleFiltersDropdownButton,
|
component: MultipleFiltersDropdownButton,
|
||||||
decorators: [
|
decorators: [
|
||||||
(Story) => {
|
(Story) => {
|
||||||
const { setAvailableFilterDefinitions } = useFilterDropdown({
|
const instanceId = 'entity-tasks-filter-scope';
|
||||||
filterDropdownId: 'entity-tasks-filter-scope',
|
const setAvailableFilterDefinitions = useSetRecoilComponentStateV2(
|
||||||
});
|
availableFilterDefinitionsComponentState,
|
||||||
|
instanceId,
|
||||||
|
);
|
||||||
|
|
||||||
setAvailableFilterDefinitions([
|
setAvailableFilterDefinitions([
|
||||||
{
|
{
|
||||||
fieldMetadataId: '1',
|
fieldMetadataId: '1',
|
||||||
@ -47,9 +52,11 @@ const meta: Meta<typeof MultipleFiltersDropdownButton> = {
|
|||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
return (
|
return (
|
||||||
<ObjectFilterDropdownScope filterScopeId="entity-tasks-filter-scope">
|
<ViewComponentInstanceContext.Provider value={{ instanceId }}>
|
||||||
<Story />
|
<ObjectFilterDropdownScope filterScopeId={instanceId}>
|
||||||
</ObjectFilterDropdownScope>
|
<Story />
|
||||||
|
</ObjectFilterDropdownScope>
|
||||||
|
</ViewComponentInstanceContext.Provider>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
ObjectMetadataItemsDecorator,
|
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 { useFilterDropdownStates } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdownStates';
|
||||||
import { Filter } from '@/object-record/object-filter-dropdown/types/Filter';
|
import { Filter } from '@/object-record/object-filter-dropdown/types/Filter';
|
||||||
import { FilterDefinition } from '@/object-record/object-filter-dropdown/types/FilterDefinition';
|
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';
|
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
||||||
|
|
||||||
const filterDropdownId = 'filterDropdownId';
|
const filterDropdownId = 'filterDropdownId';
|
||||||
@ -35,11 +37,13 @@ describe('useFilterDropdown', () => {
|
|||||||
it('should set availableFilterDefinitions', async () => {
|
it('should set availableFilterDefinitions', async () => {
|
||||||
const { result } = renderHook(() => {
|
const { result } = renderHook(() => {
|
||||||
useFilterDropdown({ filterDropdownId });
|
useFilterDropdown({ filterDropdownId });
|
||||||
const { availableFilterDefinitionsState } =
|
|
||||||
useFilterDropdownStates(filterDropdownId);
|
|
||||||
|
|
||||||
const [availableFilterDefinitions, setAvailableFilterDefinitions] =
|
const [availableFilterDefinitions, setAvailableFilterDefinitions] =
|
||||||
useRecoilState(availableFilterDefinitionsState);
|
useRecoilComponentStateV2(
|
||||||
|
availableFilterDefinitionsComponentState,
|
||||||
|
filterDropdownId,
|
||||||
|
);
|
||||||
|
|
||||||
return { availableFilterDefinitions, setAvailableFilterDefinitions };
|
return { availableFilterDefinitions, setAvailableFilterDefinitions };
|
||||||
}, renderHookConfig);
|
}, renderHookConfig);
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,6 @@ export const useFilterDropdown = (props?: UseFilterDropdownProps) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
availableFilterDefinitionsState,
|
|
||||||
filterDefinitionUsedInDropdownState,
|
filterDefinitionUsedInDropdownState,
|
||||||
objectFilterDropdownSearchInputState,
|
objectFilterDropdownSearchInputState,
|
||||||
objectFilterDropdownSelectedRecordIdsState,
|
objectFilterDropdownSelectedRecordIdsState,
|
||||||
@ -73,9 +72,6 @@ export const useFilterDropdown = (props?: UseFilterDropdownProps) => {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
const setAvailableFilterDefinitions = useSetRecoilState(
|
|
||||||
availableFilterDefinitionsState,
|
|
||||||
);
|
|
||||||
const setSelectedFilter = useSetRecoilState(selectedFilterState);
|
const setSelectedFilter = useSetRecoilState(selectedFilterState);
|
||||||
const setSelectedOperandInDropdown = useSetRecoilState(
|
const setSelectedOperandInDropdown = useSetRecoilState(
|
||||||
selectedOperandInDropdownState,
|
selectedOperandInDropdownState,
|
||||||
@ -106,7 +102,6 @@ export const useFilterDropdown = (props?: UseFilterDropdownProps) => {
|
|||||||
resetFilter,
|
resetFilter,
|
||||||
setSelectedFilter,
|
setSelectedFilter,
|
||||||
setSelectedOperandInDropdown,
|
setSelectedOperandInDropdown,
|
||||||
setAvailableFilterDefinitions,
|
|
||||||
setFilterDefinitionUsedInDropdown,
|
setFilterDefinitionUsedInDropdown,
|
||||||
setObjectFilterDropdownSearchInput,
|
setObjectFilterDropdownSearchInput,
|
||||||
// setObjectFilterDropdownSelectedEntityId,
|
// setObjectFilterDropdownSelectedEntityId,
|
||||||
@ -116,7 +111,6 @@ export const useFilterDropdown = (props?: UseFilterDropdownProps) => {
|
|||||||
setIsObjectFilterDropdownUnfolded,
|
setIsObjectFilterDropdownUnfolded,
|
||||||
setOnFilterSelect,
|
setOnFilterSelect,
|
||||||
emptyFilterButKeepDefinition,
|
emptyFilterButKeepDefinition,
|
||||||
availableFilterDefinitionsState,
|
|
||||||
filterDefinitionUsedInDropdownState,
|
filterDefinitionUsedInDropdownState,
|
||||||
objectFilterDropdownSearchInputState,
|
objectFilterDropdownSearchInputState,
|
||||||
// objectFilterDropdownSelectedEntityIdState,
|
// objectFilterDropdownSelectedEntityIdState,
|
||||||
|
|||||||
@ -8,14 +8,8 @@ import { onFilterSelectComponentState } from '@/object-record/object-filter-drop
|
|||||||
import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState';
|
import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState';
|
||||||
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
|
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
|
||||||
import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState';
|
import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState';
|
||||||
import { availableFilterDefinitionsComponentState } from '@/views/states/availableFilterDefinitionsComponentState';
|
|
||||||
|
|
||||||
export const useFilterDropdownStates = (scopeId: string) => {
|
export const useFilterDropdownStates = (scopeId: string) => {
|
||||||
const availableFilterDefinitionsState = extractComponentState(
|
|
||||||
availableFilterDefinitionsComponentState,
|
|
||||||
scopeId,
|
|
||||||
);
|
|
||||||
|
|
||||||
const filterDefinitionUsedInDropdownState = extractComponentState(
|
const filterDefinitionUsedInDropdownState = extractComponentState(
|
||||||
filterDefinitionUsedInDropdownComponentState,
|
filterDefinitionUsedInDropdownComponentState,
|
||||||
scopeId,
|
scopeId,
|
||||||
@ -63,7 +57,6 @@ export const useFilterDropdownStates = (scopeId: string) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
availableFilterDefinitionsState,
|
|
||||||
filterDefinitionUsedInDropdownState,
|
filterDefinitionUsedInDropdownState,
|
||||||
objectFilterDropdownSearchInputState,
|
objectFilterDropdownSearchInputState,
|
||||||
objectFilterDropdownSelectedRecordIdsState,
|
objectFilterDropdownSelectedRecordIdsState,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext';
|
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 =
|
export const ObjectFilterDropdownScopeInternalContext =
|
||||||
createScopeInternalContext<ObjectFilterDropdownScopeInternalContextProps>();
|
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 { useSortDropdownStates } from '@/object-record/object-sort-dropdown/hooks/useSortDropdownStates';
|
||||||
import { Sort } from '@/object-record/object-sort-dropdown/types/Sort';
|
import { Sort } from '@/object-record/object-sort-dropdown/types/Sort';
|
||||||
import { SortDefinition } from '@/object-record/object-sort-dropdown/types/SortDefinition';
|
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 }) => (
|
const Wrapper = ({ children }: { children: React.ReactNode }) => (
|
||||||
<RecoilRoot>{children}</RecoilRoot>
|
<RecoilRoot>{children}</RecoilRoot>
|
||||||
@ -24,11 +26,13 @@ describe('useSortDropdown', () => {
|
|||||||
it('should set availableSortDefinitions', async () => {
|
it('should set availableSortDefinitions', async () => {
|
||||||
const { result } = renderHook(() => {
|
const { result } = renderHook(() => {
|
||||||
useSortDropdown({ sortDropdownId });
|
useSortDropdown({ sortDropdownId });
|
||||||
const { availableSortDefinitionsState } =
|
|
||||||
useSortDropdownStates(sortDropdownId);
|
|
||||||
|
|
||||||
|
// TODO: verify this instance id works
|
||||||
const [availableSortDefinitions, setAvailableSortDefinitions] =
|
const [availableSortDefinitions, setAvailableSortDefinitions] =
|
||||||
useRecoilState(availableSortDefinitionsState);
|
useRecoilComponentStateV2(
|
||||||
|
availableSortDefinitionsComponentState,
|
||||||
|
sortDropdownId,
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
availableSortDefinitions,
|
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 { SortDefinition } from '@/object-record/object-sort-dropdown/types/SortDefinition';
|
||||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
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 {
|
import {
|
||||||
OBJECT_SORT_DROPDOWN_ID,
|
OBJECT_SORT_DROPDOWN_ID,
|
||||||
VIEW_SORT_DROPDOWN_ID,
|
VIEW_SORT_DROPDOWN_ID,
|
||||||
@ -41,7 +43,6 @@ export const useObjectSortDropdown = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const {
|
const {
|
||||||
availableSortDefinitionsState,
|
|
||||||
onSortSelectState,
|
onSortSelectState,
|
||||||
isSortSelectedState,
|
isSortSelectedState,
|
||||||
objectSortDropdownSearchInputState,
|
objectSortDropdownSearchInputState,
|
||||||
@ -52,8 +53,10 @@ export const useObjectSortDropdown = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const isSortSelected = useRecoilValue(isSortSelectedState);
|
const isSortSelected = useRecoilValue(isSortSelectedState);
|
||||||
const availableSortDefinitions = useRecoilValue(
|
|
||||||
availableSortDefinitionsState,
|
const availableSortDefinitions = useRecoilComponentValueV2(
|
||||||
|
availableSortDefinitionsComponentState,
|
||||||
|
VIEW_SORT_DROPDOWN_ID,
|
||||||
);
|
);
|
||||||
const onSortSelect = useRecoilValue(onSortSelectState);
|
const onSortSelect = useRecoilValue(onSortSelectState);
|
||||||
|
|
||||||
|
|||||||
@ -14,8 +14,8 @@ export const useSortDropdown = (props?: UseSortProps) => {
|
|||||||
ObjectSortDropdownScopeInternalContext,
|
ObjectSortDropdownScopeInternalContext,
|
||||||
props?.sortDropdownId,
|
props?.sortDropdownId,
|
||||||
);
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
availableSortDefinitionsState,
|
|
||||||
isSortSelectedState,
|
isSortSelectedState,
|
||||||
onSortSelectState,
|
onSortSelectState,
|
||||||
objectSortDropdownSearchInputState,
|
objectSortDropdownSearchInputState,
|
||||||
@ -35,7 +35,6 @@ export const useSortDropdown = (props?: UseSortProps) => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
scopeId,
|
scopeId,
|
||||||
availableSortDefinitionsState,
|
|
||||||
isSortSelectedState,
|
isSortSelectedState,
|
||||||
onSortSelectState,
|
onSortSelectState,
|
||||||
objectSortDropdownSearchInputState,
|
objectSortDropdownSearchInputState,
|
||||||
|
|||||||
@ -2,14 +2,8 @@ import { isSortSelectedComponentState } from '@/object-record/object-sort-dropdo
|
|||||||
import { objectSortDropdownSearchInputComponentState } from '@/object-record/object-sort-dropdown/states/objectSortDropdownSearchInputComponentState';
|
import { objectSortDropdownSearchInputComponentState } from '@/object-record/object-sort-dropdown/states/objectSortDropdownSearchInputComponentState';
|
||||||
import { onSortSelectComponentState } from '@/object-record/object-sort-dropdown/states/onSortSelectScopedState';
|
import { onSortSelectComponentState } from '@/object-record/object-sort-dropdown/states/onSortSelectScopedState';
|
||||||
import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState';
|
import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState';
|
||||||
import { availableSortDefinitionsComponentState } from '@/views/states/availableSortDefinitionsComponentState';
|
|
||||||
|
|
||||||
export const useSortDropdownStates = (scopeId: string) => {
|
export const useSortDropdownStates = (scopeId: string) => {
|
||||||
const availableSortDefinitionsState = extractComponentState(
|
|
||||||
availableSortDefinitionsComponentState,
|
|
||||||
scopeId,
|
|
||||||
);
|
|
||||||
|
|
||||||
const isSortSelectedState = extractComponentState(
|
const isSortSelectedState = extractComponentState(
|
||||||
isSortSelectedComponentState,
|
isSortSelectedComponentState,
|
||||||
scopeId,
|
scopeId,
|
||||||
@ -26,7 +20,6 @@ export const useSortDropdownStates = (scopeId: string) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
availableSortDefinitionsState,
|
|
||||||
isSortSelectedState,
|
isSortSelectedState,
|
||||||
onSortSelectState,
|
onSortSelectState,
|
||||||
objectSortDropdownSearchInputState,
|
objectSortDropdownSearchInputState,
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext';
|
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';
|
import { Sort } from '../../types/Sort';
|
||||||
|
|
||||||
type ObjectSortDropdownScopeInternalContextProps = ComponentStateKey & {
|
type ObjectSortDropdownScopeInternalContextProps = RecoilComponentStateKey & {
|
||||||
onSortSelect?: (sort: Sort) => void;
|
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 { FieldDefinition } from '@/object-record/record-field/types/FieldDefinition';
|
||||||
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
|
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
|
||||||
import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext';
|
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;
|
onFieldsChange: (fields: FieldDefinition<FieldMetadata>[]) => void;
|
||||||
onColumnsChange: (column: RecordBoardColumnDefinition[]) => void;
|
onColumnsChange: (column: RecordBoardColumnDefinition[]) => void;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -27,7 +27,7 @@ export const useInitDraftValueV2 = <FieldValue>() => {
|
|||||||
const recordFieldInputScopeId = `${getRecordFieldInputId(
|
const recordFieldInputScopeId = `${getRecordFieldInputId(
|
||||||
recordId,
|
recordId,
|
||||||
fieldDefinition?.metadata?.fieldName,
|
fieldDefinition?.metadata?.fieldName,
|
||||||
)}-scope`;
|
)}`;
|
||||||
|
|
||||||
const getDraftValueSelector = extractComponentSelector<
|
const getDraftValueSelector = extractComponentSelector<
|
||||||
FieldInputDraftValue<FieldValue> | undefined
|
FieldInputDraftValue<FieldValue> | undefined
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext';
|
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 =
|
export const RecordFieldInputScopeInternalContext =
|
||||||
createScopeInternalContext<RecordFieldInputScopeInternalContextProps>();
|
createScopeInternalContext<RecordFieldInputScopeInternalContextProps>();
|
||||||
|
|||||||
@ -24,6 +24,7 @@ import { RecordFieldValueSelectorContextProvider } from '@/object-record/record-
|
|||||||
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
|
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
|
||||||
import { SpreadsheetImportProvider } from '@/spreadsheet-import/provider/components/SpreadsheetImportProvider';
|
import { SpreadsheetImportProvider } from '@/spreadsheet-import/provider/components/SpreadsheetImportProvider';
|
||||||
import { ViewBar } from '@/views/components/ViewBar';
|
import { ViewBar } from '@/views/components/ViewBar';
|
||||||
|
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||||
import { ViewField } from '@/views/types/ViewField';
|
import { ViewField } from '@/views/types/ViewField';
|
||||||
import { ViewType } from '@/views/types/ViewType';
|
import { ViewType } from '@/views/types/ViewType';
|
||||||
import { mapViewFieldsToColumnDefinitions } from '@/views/utils/mapViewFieldsToColumnDefinitions';
|
import { mapViewFieldsToColumnDefinitions } from '@/views/utils/mapViewFieldsToColumnDefinitions';
|
||||||
@ -107,81 +108,91 @@ export const RecordIndexContainer = () => {
|
|||||||
return (
|
return (
|
||||||
<StyledContainer>
|
<StyledContainer>
|
||||||
<InformationBannerWrapper />
|
<InformationBannerWrapper />
|
||||||
<RecordFieldValueSelectorContextProvider>
|
<ViewComponentInstanceContext.Provider
|
||||||
<SpreadsheetImportProvider>
|
value={{ instanceId: recordIndexId }}
|
||||||
<StyledContainerWithPadding>
|
>
|
||||||
<ViewBar
|
<RecordFieldValueSelectorContextProvider>
|
||||||
viewBarId={recordIndexId}
|
<SpreadsheetImportProvider>
|
||||||
optionsDropdownButton={
|
<StyledContainerWithPadding>
|
||||||
<RecordIndexOptionsDropdown
|
<ViewBar
|
||||||
recordIndexId={recordIndexId}
|
viewBarId={recordIndexId}
|
||||||
objectNameSingular={objectNameSingular}
|
optionsDropdownButton={
|
||||||
viewType={recordIndexViewType ?? ViewType.Table}
|
<RecordIndexOptionsDropdown
|
||||||
/>
|
recordIndexId={recordIndexId}
|
||||||
}
|
objectNameSingular={objectNameSingular}
|
||||||
onCurrentViewChange={(view) => {
|
viewType={recordIndexViewType ?? ViewType.Table}
|
||||||
if (!view) {
|
/>
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
onCurrentViewChange={(view) => {
|
||||||
|
if (!view) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
onViewFieldsChange(view.viewFields);
|
onViewFieldsChange(view.viewFields);
|
||||||
setTableFilters(
|
setTableFilters(
|
||||||
mapViewFiltersToFilters(view.viewFilters, filterDefinitions),
|
mapViewFiltersToFilters(
|
||||||
);
|
view.viewFilters,
|
||||||
setRecordIndexFilters(
|
filterDefinitions,
|
||||||
mapViewFiltersToFilters(view.viewFilters, filterDefinitions),
|
),
|
||||||
);
|
);
|
||||||
setTableSorts(
|
setRecordIndexFilters(
|
||||||
mapViewSortsToSorts(view.viewSorts, sortDefinitions),
|
mapViewFiltersToFilters(
|
||||||
);
|
view.viewFilters,
|
||||||
setRecordIndexSorts(
|
filterDefinitions,
|
||||||
mapViewSortsToSorts(view.viewSorts, sortDefinitions),
|
),
|
||||||
);
|
);
|
||||||
setRecordIndexViewType(view.type);
|
setTableSorts(
|
||||||
setRecordIndexViewKanbanFieldMetadataIdState(
|
mapViewSortsToSorts(view.viewSorts, sortDefinitions),
|
||||||
view.kanbanFieldMetadataId,
|
);
|
||||||
);
|
setRecordIndexSorts(
|
||||||
setRecordIndexIsCompactModeActive(view.isCompact);
|
mapViewSortsToSorts(view.viewSorts, sortDefinitions),
|
||||||
}}
|
);
|
||||||
/>
|
setRecordIndexViewType(view.type);
|
||||||
<RecordIndexViewBarEffect
|
setRecordIndexViewKanbanFieldMetadataIdState(
|
||||||
objectNamePlural={objectNamePlural}
|
view.kanbanFieldMetadataId,
|
||||||
viewBarId={recordIndexId}
|
);
|
||||||
/>
|
setRecordIndexIsCompactModeActive(view.isCompact);
|
||||||
</StyledContainerWithPadding>
|
}}
|
||||||
</SpreadsheetImportProvider>
|
/>
|
||||||
|
<RecordIndexViewBarEffect
|
||||||
|
objectNamePlural={objectNamePlural}
|
||||||
|
viewBarId={recordIndexId}
|
||||||
|
/>
|
||||||
|
</StyledContainerWithPadding>
|
||||||
|
</SpreadsheetImportProvider>
|
||||||
|
|
||||||
{recordIndexViewType === ViewType.Table && (
|
{recordIndexViewType === ViewType.Table && (
|
||||||
<>
|
<>
|
||||||
<RecordIndexTableContainer
|
<RecordIndexTableContainer
|
||||||
recordTableId={recordIndexId}
|
recordTableId={recordIndexId}
|
||||||
viewBarId={recordIndexId}
|
viewBarId={recordIndexId}
|
||||||
/>
|
/>
|
||||||
<RecordIndexTableContainerEffect
|
<RecordIndexTableContainerEffect
|
||||||
objectNameSingular={objectNameSingular}
|
objectNameSingular={objectNameSingular}
|
||||||
recordTableId={recordIndexId}
|
recordTableId={recordIndexId}
|
||||||
viewBarId={recordIndexId}
|
viewBarId={recordIndexId}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{recordIndexViewType === ViewType.Kanban && (
|
{recordIndexViewType === ViewType.Kanban && (
|
||||||
<StyledContainerWithPadding fullHeight>
|
<StyledContainerWithPadding fullHeight>
|
||||||
<RecordIndexBoardContainer
|
<RecordIndexBoardContainer
|
||||||
recordBoardId={recordIndexId}
|
recordBoardId={recordIndexId}
|
||||||
viewBarId={recordIndexId}
|
viewBarId={recordIndexId}
|
||||||
objectNameSingular={objectNameSingular}
|
objectNameSingular={objectNameSingular}
|
||||||
/>
|
/>
|
||||||
<RecordIndexBoardDataLoader
|
<RecordIndexBoardDataLoader
|
||||||
objectNameSingular={objectNameSingular}
|
objectNameSingular={objectNameSingular}
|
||||||
recordBoardId={recordIndexId}
|
recordBoardId={recordIndexId}
|
||||||
/>
|
/>
|
||||||
<RecordIndexBoardDataLoaderEffect
|
<RecordIndexBoardDataLoaderEffect
|
||||||
objectNameSingular={objectNameSingular}
|
objectNameSingular={objectNameSingular}
|
||||||
recordBoardId={recordIndexId}
|
recordBoardId={recordIndexId}
|
||||||
/>
|
/>
|
||||||
</StyledContainerWithPadding>
|
</StyledContainerWithPadding>
|
||||||
)}
|
)}
|
||||||
</RecordFieldValueSelectorContextProvider>
|
</RecordFieldValueSelectorContextProvider>
|
||||||
|
</ViewComponentInstanceContext.Provider>
|
||||||
</StyledContainer>
|
</StyledContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { useRecoilState } from 'recoil';
|
|||||||
|
|
||||||
import { isRemoveSortingModalOpenState } from '@/object-record/record-table/states/isRemoveSortingModalOpenState';
|
import { isRemoveSortingModalOpenState } from '@/object-record/record-table/states/isRemoveSortingModalOpenState';
|
||||||
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
|
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';
|
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||||
|
|
||||||
export const RecordIndexRemoveSortingModal = ({
|
export const RecordIndexRemoveSortingModal = ({
|
||||||
@ -21,11 +21,11 @@ export const RecordIndexRemoveSortingModal = ({
|
|||||||
isRemoveSortingModalOpenState,
|
isRemoveSortingModalOpenState,
|
||||||
);
|
);
|
||||||
|
|
||||||
const { removeCombinedViewSort } = useCombinedViewSorts(recordTableId);
|
const { deleteCombinedViewSort } = useDeleteCombinedViewSorts(recordTableId);
|
||||||
|
|
||||||
const handleRemoveClick = () => {
|
const handleRemoveClick = () => {
|
||||||
fieldMetadataIds.forEach((id) => {
|
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 { useHandleToggleColumnSort } from '@/object-record/record-index/hooks/useHandleToggleColumnSort';
|
||||||
import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates';
|
import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates';
|
||||||
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
|
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 { useSetRecordCountInCurrentView } from '@/views/hooks/useSetRecordCountInCurrentView';
|
||||||
|
import { entityCountInCurrentViewComponentState } from '@/views/states/entityCountInCurrentViewComponentState';
|
||||||
|
|
||||||
type RecordIndexTableContainerEffectProps = {
|
type RecordIndexTableContainerEffectProps = {
|
||||||
objectNameSingular: string;
|
objectNameSingular: string;
|
||||||
@ -50,9 +51,10 @@ export const RecordIndexTableContainerEffect = ({
|
|||||||
const { tableRowIdsState, hasUserSelectedAllRowsState } =
|
const { tableRowIdsState, hasUserSelectedAllRowsState } =
|
||||||
useRecordTableStates(recordTableId);
|
useRecordTableStates(recordTableId);
|
||||||
|
|
||||||
const { entityCountInCurrentViewState } = useViewStates(recordTableId);
|
// TODO: verify this instance id works
|
||||||
const entityCountInCurrentView = useRecoilValue(
|
const entityCountInCurrentView = useRecoilComponentValueV2(
|
||||||
entityCountInCurrentViewState,
|
entityCountInCurrentViewComponentState,
|
||||||
|
recordTableId,
|
||||||
);
|
);
|
||||||
const hasUserSelectedAllRows = useRecoilValue(hasUserSelectedAllRowsState);
|
const hasUserSelectedAllRows = useRecoilValue(hasUserSelectedAllRowsState);
|
||||||
const tableRowIds = useRecoilValue(tableRowIdsState);
|
const tableRowIds = useRecoilValue(tableRowIdsState);
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||||
import { buildShowPageURL } from '@/object-record/record-show/utils/buildShowPageURL';
|
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 { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { useRecoilValue } from 'recoil';
|
|
||||||
|
|
||||||
export const useHandleIndexIdentifierClick = ({
|
export const useHandleIndexIdentifierClick = ({
|
||||||
objectMetadataItem,
|
objectMetadataItem,
|
||||||
@ -13,10 +13,9 @@ export const useHandleIndexIdentifierClick = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const currentViewId = useRecoilValue(
|
const currentViewId = useRecoilComponentValueV2(
|
||||||
currentViewIdComponentState({
|
currentViewIdComponentState,
|
||||||
scopeId: recordIndexId,
|
recordIndexId,
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleIndexIdentifierClick = (recordId: string) => {
|
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 { Filter } from '@/object-record/object-filter-dropdown/types/Filter';
|
||||||
import { getOperandsForFilterType } from '@/object-record/object-filter-dropdown/utils/getOperandsForFilterType';
|
import { getOperandsForFilterType } from '@/object-record/object-filter-dropdown/utils/getOperandsForFilterType';
|
||||||
import { useDropdownV2 } from '@/ui/layout/dropdown/hooks/useDropdownV2';
|
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';
|
import { isDefined } from '~/utils/isDefined';
|
||||||
|
|
||||||
type UseHandleToggleColumnFilterProps = {
|
type UseHandleToggleColumnFilterProps = {
|
||||||
@ -26,7 +26,7 @@ export const useHandleToggleColumnFilter = ({
|
|||||||
const { columnDefinitions } =
|
const { columnDefinitions } =
|
||||||
useColumnDefinitionsFromFieldMetadata(objectMetadataItem);
|
useColumnDefinitionsFromFieldMetadata(objectMetadataItem);
|
||||||
|
|
||||||
const { upsertCombinedViewFilter } = useCombinedViewFilters(viewBarId);
|
const { upsertCombinedViewFilter } = useUpsertCombinedViewFilters(viewBarId);
|
||||||
const { openDropdown } = useDropdownV2();
|
const { openDropdown } = useDropdownV2();
|
||||||
|
|
||||||
const handleToggleColumnFilter = useCallback(
|
const handleToggleColumnFilter = useCallback(
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { useCallback } from 'react';
|
|||||||
import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata';
|
import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata';
|
||||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||||
import { Sort } from '@/object-record/object-sort-dropdown/types/Sort';
|
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';
|
import { isDefined } from '~/utils/isDefined';
|
||||||
|
|
||||||
type UseHandleToggleColumnSortProps = {
|
type UseHandleToggleColumnSortProps = {
|
||||||
@ -22,7 +22,7 @@ export const useHandleToggleColumnSort = ({
|
|||||||
const { columnDefinitions } =
|
const { columnDefinitions } =
|
||||||
useColumnDefinitionsFromFieldMetadata(objectMetadataItem);
|
useColumnDefinitionsFromFieldMetadata(objectMetadataItem);
|
||||||
|
|
||||||
const { upsertCombinedViewSort } = useCombinedViewSorts(viewBarId);
|
const { upsertCombinedViewSort } = useUpsertCombinedViewSorts(viewBarId);
|
||||||
|
|
||||||
const handleToggleColumnSort = useCallback(
|
const handleToggleColumnSort = useCallback(
|
||||||
(fieldMetadataId: string) => {
|
(fieldMetadataId: string) => {
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadata
|
|||||||
import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
|
import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
|
||||||
import { Filter } from '@/object-record/object-filter-dropdown/types/Filter';
|
import { Filter } from '@/object-record/object-filter-dropdown/types/Filter';
|
||||||
import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates';
|
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 { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
||||||
import { useRecoilCallback } from 'recoil';
|
import { useRecoilCallback } from 'recoil';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isDefined } from '~/utils/isDefined';
|
||||||
@ -27,7 +27,7 @@ export const useHandleToggleTrashColumnFilter = ({
|
|||||||
const { columnDefinitions } =
|
const { columnDefinitions } =
|
||||||
useColumnDefinitionsFromFieldMetadata(objectMetadataItem);
|
useColumnDefinitionsFromFieldMetadata(objectMetadataItem);
|
||||||
|
|
||||||
const { upsertCombinedViewFilter } = useCombinedViewFilters(viewBarId);
|
const { upsertCombinedViewFilter } = useUpsertCombinedViewFilters(viewBarId);
|
||||||
const { isSoftDeleteActiveState } = useRecordTableStates(viewBarId);
|
const { isSoftDeleteActiveState } = useRecordTableStates(viewBarId);
|
||||||
|
|
||||||
const handleToggleTrashColumnFilter = useCallback(() => {
|
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 { act, renderHook, waitFor } from '@testing-library/react';
|
||||||
import { percentage, sleep, useTableData } from '../useTableData';
|
import { percentage, sleep, useTableData } from '../useTableData';
|
||||||
|
|
||||||
import { useRecordBoard } from '@/object-record/record-board/hooks/useRecordBoard';
|
import { useRecordBoard } from '@/object-record/record-board/hooks/useRecordBoard';
|
||||||
import { recordBoardKanbanFieldMetadataNameComponentState } from '@/object-record/record-board/states/recordBoardKanbanFieldMetadataNameComponentState';
|
import { recordBoardKanbanFieldMetadataNameComponentState } from '@/object-record/record-board/states/recordBoardKanbanFieldMetadataNameComponentState';
|
||||||
import { useRecordIndexOptionsForBoard } from '@/object-record/record-index/options/hooks/useRecordIndexOptionsForBoard';
|
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 { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState';
|
||||||
import { ViewType } from '@/views/types/ViewType';
|
import { ViewType } from '@/views/types/ViewType';
|
||||||
import { MockedProvider, MockedResponse } from '@apollo/client/testing';
|
import { MockedProvider, MockedResponse } from '@apollo/client/testing';
|
||||||
@ -148,15 +148,19 @@ const mocks: MockedResponse[] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
const Wrapper = ({ children }: { children: ReactNode }) => (
|
const Wrapper = ({ children }: { children: ReactNode }) => (
|
||||||
<Router>
|
<SnackBarManagerScopeInternalContext.Provider
|
||||||
<RecoilRoot>
|
value={{
|
||||||
<SnackBarProviderScope snackBarManagerScopeId="snack-bar-manager">
|
scopeId: 'snack-bar-manager',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Router>
|
||||||
|
<RecoilRoot>
|
||||||
<MockedProvider addTypename={false} mocks={mocks}>
|
<MockedProvider addTypename={false} mocks={mocks}>
|
||||||
{children}
|
{children}
|
||||||
</MockedProvider>
|
</MockedProvider>
|
||||||
</SnackBarProviderScope>
|
</RecoilRoot>
|
||||||
</RecoilRoot>
|
</Router>
|
||||||
</Router>
|
</SnackBarManagerScopeInternalContext.Provider>
|
||||||
);
|
);
|
||||||
|
|
||||||
const graphqlEmptyResponse = [
|
const graphqlEmptyResponse = [
|
||||||
@ -174,15 +178,19 @@ const graphqlEmptyResponse = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
const WrapperWithEmptyResponse = ({ children }: { children: ReactNode }) => (
|
const WrapperWithEmptyResponse = ({ children }: { children: ReactNode }) => (
|
||||||
<Router>
|
<SnackBarManagerScopeInternalContext.Provider
|
||||||
<RecoilRoot>
|
value={{
|
||||||
<SnackBarProviderScope snackBarManagerScopeId="snack-bar-manager">
|
scopeId: 'snack-bar-manager',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Router>
|
||||||
|
<RecoilRoot>
|
||||||
<MockedProvider addTypename={false} mocks={graphqlEmptyResponse}>
|
<MockedProvider addTypename={false} mocks={graphqlEmptyResponse}>
|
||||||
{children}
|
{children}
|
||||||
</MockedProvider>
|
</MockedProvider>
|
||||||
</SnackBarProviderScope>
|
</RecoilRoot>
|
||||||
</RecoilRoot>
|
</Router>
|
||||||
</Router>
|
</SnackBarManagerScopeInternalContext.Provider>
|
||||||
);
|
);
|
||||||
|
|
||||||
describe('useTableData', () => {
|
describe('useTableData', () => {
|
||||||
@ -191,13 +199,13 @@ describe('useTableData', () => {
|
|||||||
describe('data fetching', () => {
|
describe('data fetching', () => {
|
||||||
it('should handle no records', async () => {
|
it('should handle no records', async () => {
|
||||||
const callback = jest.fn();
|
const callback = jest.fn();
|
||||||
|
|
||||||
const { result } = renderHook(
|
const { result } = renderHook(
|
||||||
() =>
|
() =>
|
||||||
useTableData({
|
useTableData({
|
||||||
recordIndexId,
|
recordIndexId,
|
||||||
objectNameSingular,
|
objectNameSingular,
|
||||||
callback,
|
callback,
|
||||||
|
|
||||||
delayMs: 0,
|
delayMs: 0,
|
||||||
viewType: ViewType.Kanban,
|
viewType: ViewType.Kanban,
|
||||||
}),
|
}),
|
||||||
@ -209,7 +217,7 @@ describe('useTableData', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
await waitFor(() => {
|
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 { OnDragEndResponder } from '@hello-pangea/dnd';
|
||||||
|
import { useCallback, useMemo } from 'react';
|
||||||
import { useRecoilState } from 'recoil';
|
import { useRecoilState } from 'recoil';
|
||||||
|
|
||||||
import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata';
|
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 { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
|
||||||
import { recordIndexFieldDefinitionsState } from '@/object-record/record-index/states/recordIndexFieldDefinitionsState';
|
import { recordIndexFieldDefinitionsState } from '@/object-record/record-index/states/recordIndexFieldDefinitionsState';
|
||||||
import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
|
import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
|
||||||
import { useHandleViews } from '@/views/hooks/useHandleViews';
|
|
||||||
import { useSaveCurrentViewFields } from '@/views/hooks/useSaveCurrentViewFields';
|
import { useSaveCurrentViewFields } from '@/views/hooks/useSaveCurrentViewFields';
|
||||||
|
import { useUpdateCurrentView } from '@/views/hooks/useUpdateCurrentView';
|
||||||
import { GraphQLView } from '@/views/types/GraphQLView';
|
import { GraphQLView } from '@/views/types/GraphQLView';
|
||||||
import { mapBoardFieldDefinitionsToViewFields } from '@/views/utils/mapBoardFieldDefinitionsToViewFields';
|
import { mapBoardFieldDefinitionsToViewFields } from '@/views/utils/mapBoardFieldDefinitionsToViewFields';
|
||||||
import { mapArrayToObject } from '~/utils/array/mapArrayToObject';
|
import { mapArrayToObject } from '~/utils/array/mapArrayToObject';
|
||||||
@ -31,7 +31,7 @@ export const useRecordIndexOptionsForBoard = ({
|
|||||||
useRecoilState(recordIndexFieldDefinitionsState);
|
useRecoilState(recordIndexFieldDefinitionsState);
|
||||||
|
|
||||||
const { saveViewFields } = useSaveCurrentViewFields(viewBarId);
|
const { saveViewFields } = useSaveCurrentViewFields(viewBarId);
|
||||||
const { updateCurrentView } = useHandleViews(viewBarId);
|
const { updateCurrentView } = useUpdateCurrentView(viewBarId);
|
||||||
const { isCompactModeActiveState } = useRecordBoard(recordBoardId);
|
const { isCompactModeActiveState } = useRecordBoard(recordBoardId);
|
||||||
|
|
||||||
const [isCompactModeActive, setIsCompactModeActive] = useRecoilState(
|
const [isCompactModeActive, setIsCompactModeActive] = useRecoilState(
|
||||||
|
|||||||
@ -2,7 +2,8 @@ import { useRecoilValue } from 'recoil';
|
|||||||
|
|
||||||
import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates';
|
import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates';
|
||||||
import { ActionBar } from '@/ui/navigation/action-bar/components/ActionBar';
|
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 = ({
|
export const RecordTableActionBar = ({
|
||||||
recordTableId,
|
recordTableId,
|
||||||
@ -15,10 +16,12 @@ export const RecordTableActionBar = ({
|
|||||||
hasUserSelectedAllRowsState,
|
hasUserSelectedAllRowsState,
|
||||||
} = useRecordTableStates(recordTableId);
|
} = useRecordTableStates(recordTableId);
|
||||||
|
|
||||||
const { entityCountInCurrentViewState } = useViewStates(recordTableId);
|
// TODO: verify this instance id works
|
||||||
const entityCountInCurrentView = useRecoilValue(
|
const entityCountInCurrentView = useRecoilComponentValueV2(
|
||||||
entityCountInCurrentViewState,
|
entityCountInCurrentViewComponentState,
|
||||||
|
recordTableId,
|
||||||
);
|
);
|
||||||
|
|
||||||
const hasUserSelectedAllRows = useRecoilValue(hasUserSelectedAllRowsState);
|
const hasUserSelectedAllRows = useRecoilValue(hasUserSelectedAllRowsState);
|
||||||
const tableRowIds = useRecoilValue(tableRowIdsState);
|
const tableRowIds = useRecoilValue(tableRowIdsState);
|
||||||
const selectedRowIds = useRecoilValue(selectedRowIdsSelector());
|
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 { RecordTableContext } from '@/object-record/record-table/contexts/RecordTableContext';
|
||||||
import { RecordTableEmptyStateDisplay } from '@/object-record/record-table/empty-state/components/RecordTableEmptyStateDisplay';
|
import { RecordTableEmptyStateDisplay } from '@/object-record/record-table/empty-state/components/RecordTableEmptyStateDisplay';
|
||||||
import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates';
|
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 { useContext } from 'react';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
@ -13,7 +13,8 @@ export const RecordTableEmptyStateSoftDelete = () => {
|
|||||||
const { objectMetadataItem, objectNameSingular, recordTableId } =
|
const { objectMetadataItem, objectNameSingular, recordTableId } =
|
||||||
useContext(RecordTableContext);
|
useContext(RecordTableContext);
|
||||||
|
|
||||||
const { removeCombinedViewFilter } = useCombinedViewFilters(recordTableId);
|
const { deleteCombinedViewFilter } =
|
||||||
|
useDeleteCombinedViewFilters(recordTableId);
|
||||||
const { tableFiltersState } = useRecordTableStates(recordTableId);
|
const { tableFiltersState } = useRecordTableStates(recordTableId);
|
||||||
|
|
||||||
const tableFilters = useRecoilValue(tableFiltersState);
|
const tableFilters = useRecoilValue(tableFiltersState);
|
||||||
@ -24,7 +25,7 @@ export const RecordTableEmptyStateSoftDelete = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const handleButtonClick = async () => {
|
const handleButtonClick = async () => {
|
||||||
removeCombinedViewFilter(
|
deleteCombinedViewFilter(
|
||||||
tableFilters.find(
|
tableFilters.find(
|
||||||
(filter) =>
|
(filter) =>
|
||||||
filter.definition.label === 'Deleted at' &&
|
filter.definition.label === 'Deleted at' &&
|
||||||
|
|||||||
@ -48,14 +48,14 @@ describe('useSelectedTableCellEditMode', () => {
|
|||||||
|
|
||||||
expect(mockCallbackInterface.set).toHaveBeenCalledWith(
|
expect(mockCallbackInterface.set).toHaveBeenCalledWith(
|
||||||
{
|
{
|
||||||
key: 'isTableCellInEditModeComponentFamilyState__{"familyKey":{"column":0,"row":0},"scopeId":"yourScopeId-scope"}',
|
key: 'isTableCellInEditModeComponentFamilyState__{"familyKey":{"column":0,"row":0},"scopeId":"yourScopeId"}',
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(mockCallbackInterface.set).toHaveBeenCalledWith(
|
expect(mockCallbackInterface.set).toHaveBeenCalledWith(
|
||||||
{
|
{
|
||||||
key: 'isTableCellInEditModeComponentFamilyState__{"familyKey":{"column":5,"row":1},"scopeId":"yourScopeId-scope"}',
|
key: 'isTableCellInEditModeComponentFamilyState__{"familyKey":{"column":5,"row":1},"scopeId":"yourScopeId"}',
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
|
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
|
||||||
import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext';
|
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';
|
import { ColumnDefinition } from '../../types/ColumnDefinition';
|
||||||
|
|
||||||
// TODO: separate scope contexts from event contexts
|
// TODO: separate scope contexts from event contexts
|
||||||
type RecordTableScopeInternalContextProps = ComponentStateKey & {
|
type RecordTableScopeInternalContextProps = RecoilComponentStateKey & {
|
||||||
onColumnsChange: (columns: ColumnDefinition<FieldMetadata>[]) => void;
|
onColumnsChange: (columns: ColumnDefinition<FieldMetadata>[]) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import { RecordTableScopeInternalContext } from '@/object-record/record-table/scopes/scope-internal-context/RecordTableScopeInternalContext';
|
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 =
|
export const hasRecordTableFetchedAllRecordsComponentStateV2 =
|
||||||
createComponentStateV2<boolean>({
|
createComponentStateV2_alpha<boolean>({
|
||||||
key: 'hasRecordTableFetchedAllRecordsComponentStateV2',
|
key: 'hasRecordTableFetchedAllRecordsComponentStateV2',
|
||||||
componentContext: RecordTableScopeInternalContext,
|
componentContext: RecordTableScopeInternalContext,
|
||||||
defaultValue: false,
|
defaultValue: false,
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import { RecordTableScopeInternalContext } from '@/object-record/record-table/scopes/scope-internal-context/RecordTableScopeInternalContext';
|
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 =
|
export const isRecordTableScrolledLeftComponentState =
|
||||||
createComponentStateV2<boolean>({
|
createComponentStateV2_alpha<boolean>({
|
||||||
key: 'isRecordTableScrolledLeftComponentState',
|
key: 'isRecordTableScrolledLeftComponentState',
|
||||||
componentContext: RecordTableScopeInternalContext,
|
componentContext: RecordTableScopeInternalContext,
|
||||||
defaultValue: true,
|
defaultValue: true,
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import { RecordTableScopeInternalContext } from '@/object-record/record-table/scopes/scope-internal-context/RecordTableScopeInternalContext';
|
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 =
|
export const isRecordTableScrolledTopComponentState =
|
||||||
createComponentStateV2<boolean>({
|
createComponentStateV2_alpha<boolean>({
|
||||||
key: 'isRecordTableScrolledTopComponentState',
|
key: 'isRecordTableScrolledTopComponentState',
|
||||||
componentContext: RecordTableScopeInternalContext,
|
componentContext: RecordTableScopeInternalContext,
|
||||||
defaultValue: true,
|
defaultValue: true,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext';
|
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 =
|
export const RelationPickerScopeInternalContext =
|
||||||
createScopeInternalContext<RelationPickerScopeInternalContextProps>();
|
createScopeInternalContext<RelationPickerScopeInternalContextProps>();
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import { RecordIndexOptionsDropdown } from '@/object-record/record-index/options
|
|||||||
import { RecordTableWithWrappers } from '@/object-record/record-table/components/RecordTableWithWrappers';
|
import { RecordTableWithWrappers } from '@/object-record/record-table/components/RecordTableWithWrappers';
|
||||||
import { SignInBackgroundMockContainerEffect } from '@/sign-in-background-mock/components/SignInBackgroundMockContainerEffect';
|
import { SignInBackgroundMockContainerEffect } from '@/sign-in-background-mock/components/SignInBackgroundMockContainerEffect';
|
||||||
import { ViewBar } from '@/views/components/ViewBar';
|
import { ViewBar } from '@/views/components/ViewBar';
|
||||||
|
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||||
import { ViewType } from '@/views/types/ViewType';
|
import { ViewType } from '@/views/types/ViewType';
|
||||||
|
|
||||||
const StyledContainer = styled.div`
|
const StyledContainer = styled.div`
|
||||||
@ -21,28 +22,30 @@ export const SignInBackgroundMockContainer = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledContainer>
|
<StyledContainer>
|
||||||
<ViewBar
|
<ViewComponentInstanceContext.Provider value={{ instanceId: viewBarId }}>
|
||||||
viewBarId={viewBarId}
|
<ViewBar
|
||||||
onCurrentViewChange={async () => {}}
|
viewBarId={viewBarId}
|
||||||
optionsDropdownButton={
|
onCurrentViewChange={async () => {}}
|
||||||
<RecordIndexOptionsDropdown
|
optionsDropdownButton={
|
||||||
recordIndexId={recordIndexId}
|
<RecordIndexOptionsDropdown
|
||||||
objectNameSingular={objectNameSingular}
|
recordIndexId={recordIndexId}
|
||||||
viewType={ViewType.Table}
|
objectNameSingular={objectNameSingular}
|
||||||
/>
|
viewType={ViewType.Table}
|
||||||
}
|
/>
|
||||||
/>
|
}
|
||||||
<SignInBackgroundMockContainerEffect
|
/>
|
||||||
objectNamePlural={objectNamePlural}
|
<SignInBackgroundMockContainerEffect
|
||||||
recordTableId={recordIndexId}
|
objectNamePlural={objectNamePlural}
|
||||||
viewId={viewBarId}
|
recordTableId={recordIndexId}
|
||||||
/>
|
viewId={viewBarId}
|
||||||
<RecordTableWithWrappers
|
/>
|
||||||
objectNameSingular={objectNameSingular}
|
<RecordTableWithWrappers
|
||||||
recordTableId={recordIndexId}
|
objectNameSingular={objectNameSingular}
|
||||||
viewBarId={viewBarId}
|
recordTableId={recordIndexId}
|
||||||
updateRecordMutation={() => {}}
|
viewBarId={viewBarId}
|
||||||
/>
|
updateRecordMutation={() => {}}
|
||||||
|
/>
|
||||||
|
</ViewComponentInstanceContext.Provider>
|
||||||
</StyledContainer>
|
</StyledContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext';
|
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 DialogManagerScopeInternalContextProps = ComponentStateKey;
|
type DialogManagerScopeInternalContextProps = RecoilComponentStateKey;
|
||||||
|
|
||||||
export const DialogManagerScopeInternalContext =
|
export const DialogManagerScopeInternalContext =
|
||||||
createScopeInternalContext<DialogManagerScopeInternalContextProps>();
|
createScopeInternalContext<DialogManagerScopeInternalContextProps>();
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext';
|
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 SnackBarManagerScopeInternalContextProps = ComponentStateKey;
|
type SnackBarManagerScopeInternalContextProps = RecoilComponentStateKey;
|
||||||
|
|
||||||
export const SnackBarManagerScopeInternalContext =
|
export const SnackBarManagerScopeInternalContext =
|
||||||
createScopeInternalContext<SnackBarManagerScopeInternalContextProps>();
|
createScopeInternalContext<SnackBarManagerScopeInternalContextProps>();
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext';
|
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 DropdownScopeInternalContextProps = ComponentStateKey;
|
type DropdownScopeInternalContextProps = RecoilComponentStateKey;
|
||||||
|
|
||||||
export const DropdownScopeInternalContext =
|
export const DropdownScopeInternalContext =
|
||||||
createScopeInternalContext<DropdownScopeInternalContextProps>();
|
createScopeInternalContext<DropdownScopeInternalContextProps>();
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext';
|
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 SelectableListScopeInternalContextProps = ComponentStateKey;
|
type SelectableListScopeInternalContextProps = RecoilComponentStateKey;
|
||||||
|
|
||||||
export const SelectableListScopeInternalContext =
|
export const SelectableListScopeInternalContext =
|
||||||
createScopeInternalContext<SelectableListScopeInternalContextProps>();
|
createScopeInternalContext<SelectableListScopeInternalContextProps>();
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { useTabListStates } from '@/ui/layout/tab/hooks/internal/useTabListState
|
|||||||
|
|
||||||
export const useTabList = (tabListId?: string) => {
|
export const useTabList = (tabListId?: string) => {
|
||||||
const { activeTabIdState } = useTabListStates({
|
const { activeTabIdState } = useTabListStates({
|
||||||
tabListScopeId: `${tabListId}-scope`,
|
tabListScopeId: tabListId,
|
||||||
});
|
});
|
||||||
|
|
||||||
const setActiveTabId = useSetRecoilState(activeTabIdState);
|
const setActiveTabId = useSetRecoilState(activeTabIdState);
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext';
|
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 TabListScopeInternalContextProps = ComponentStateKey;
|
type TabListScopeInternalContextProps = RecoilComponentStateKey;
|
||||||
|
|
||||||
export const TabListScopeInternalContext =
|
export const TabListScopeInternalContext =
|
||||||
createScopeInternalContext<TabListScopeInternalContextProps>();
|
createScopeInternalContext<TabListScopeInternalContextProps>();
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import { RecoilState, useRecoilState } from 'recoil';
|
import { RecoilState, useRecoilState } from 'recoil';
|
||||||
|
|
||||||
import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey';
|
import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey';
|
||||||
|
|
||||||
export const useRecoilScopedStateV2 = <StateType>(
|
export const useRecoilScopedStateV2 = <StateType>(
|
||||||
recoilState: (scopedKey: ComponentStateKey) => RecoilState<StateType>,
|
recoilState: (scopedKey: RecoilComponentStateKey) => RecoilState<StateType>,
|
||||||
scopeId: string,
|
scopeId: string,
|
||||||
) => {
|
) => {
|
||||||
return useRecoilState<StateType>(
|
return useRecoilState<StateType>(
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
import { Context, createContext } from 'react';
|
import { Context, createContext } from 'react';
|
||||||
|
|
||||||
import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey';
|
import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey';
|
||||||
|
|
||||||
type ScopeInternalContext<T extends ComponentStateKey> = Context<T | null>;
|
type ScopeInternalContext<T extends RecoilComponentStateKey> =
|
||||||
|
Context<T | null>;
|
||||||
|
|
||||||
export const createScopeInternalContext = <T extends ComponentStateKey>(
|
export const createScopeInternalContext = <T extends RecoilComponentStateKey>(
|
||||||
initialValue?: T,
|
initialValue?: T,
|
||||||
) => {
|
) => {
|
||||||
return createContext<T | null>(
|
return createContext<T | null>(
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { RecoilValueReadOnly } from 'recoil';
|
import { RecoilValueReadOnly } from 'recoil';
|
||||||
|
|
||||||
import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey';
|
import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey';
|
||||||
|
|
||||||
export type RecoilScopedSelector<StateType> = (
|
export type RecoilScopedSelector<StateType> = (
|
||||||
scopedKey: ComponentStateKey,
|
scopedKey: RecoilComponentStateKey,
|
||||||
) => RecoilValueReadOnly<StateType>;
|
) => RecoilValueReadOnly<StateType>;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { RecoilState } from 'recoil';
|
import { RecoilState } from 'recoil';
|
||||||
|
|
||||||
import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey';
|
import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey';
|
||||||
|
|
||||||
export type RecoilScopedState<StateType> = (
|
export type RecoilScopedState<StateType> = (
|
||||||
scopedKey: ComponentStateKey,
|
scopedKey: RecoilComponentStateKey,
|
||||||
) => RecoilState<StateType>;
|
) => RecoilState<StateType>;
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
export const getScopeIdFromComponentId = (componentId: string) =>
|
export const getScopeIdFromComponentId = (componentId: string) =>
|
||||||
`${componentId}-scope`;
|
`${componentId}`;
|
||||||
|
|||||||
@ -0,0 +1,24 @@
|
|||||||
|
import { useComponentInstanceStateContext } from '@/ui/utilities/state/component-state/hooks/useComponentInstanceStateContext';
|
||||||
|
import { ComponentInstanceStateContext } from '@/ui/utilities/state/component-state/types/ComponentInstanceStateContext';
|
||||||
|
import { isNonEmptyString } from '@sniptt/guards';
|
||||||
|
|
||||||
|
export const useAvailableComponentInstanceIdOrThrow = <
|
||||||
|
T extends { instanceId: string },
|
||||||
|
>(
|
||||||
|
Context: ComponentInstanceStateContext<T>,
|
||||||
|
instanceIdFromProps?: string,
|
||||||
|
): string => {
|
||||||
|
const instanceStateContext = useComponentInstanceStateContext(Context);
|
||||||
|
|
||||||
|
const instanceIdFromContext = instanceStateContext?.instanceId;
|
||||||
|
|
||||||
|
if (isNonEmptyString(instanceIdFromProps)) {
|
||||||
|
return instanceIdFromProps;
|
||||||
|
} else if (isNonEmptyString(instanceIdFromContext)) {
|
||||||
|
return instanceIdFromContext;
|
||||||
|
} else {
|
||||||
|
throw new Error(
|
||||||
|
'Instance id is not provided and cannot be found in context.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
import { ComponentInstanceStateContext } from '@/ui/utilities/state/component-state/types/ComponentInstanceStateContext';
|
||||||
|
import { useContext } from 'react';
|
||||||
|
|
||||||
|
export const useComponentInstanceStateContext = <
|
||||||
|
T extends { instanceId: string },
|
||||||
|
>(
|
||||||
|
Context: ComponentInstanceStateContext<T>,
|
||||||
|
) => {
|
||||||
|
const context = useContext(Context);
|
||||||
|
|
||||||
|
return context;
|
||||||
|
};
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
|
||||||
|
import { getScopeIdOrUndefinedFromComponentId } from '@/ui/utilities/recoil-scope/utils/getScopeIdOrUndefinedFromComponentId';
|
||||||
|
import { RecoilComponentState } from '@/ui/utilities/state/component-state/types/RecoilComponentState';
|
||||||
|
|
||||||
|
export const useRecoilCallbackState = <Value>(
|
||||||
|
componentState: RecoilComponentState<Value>,
|
||||||
|
componentId?: string,
|
||||||
|
) => {
|
||||||
|
const componentContext = (window as any).componentContextStateMap?.get(
|
||||||
|
componentState.key,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!componentContext) {
|
||||||
|
throw new Error(
|
||||||
|
`Component context for key "${componentState.key}" is not defined`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const internalScopeId = useAvailableScopeIdOrThrow(
|
||||||
|
componentContext,
|
||||||
|
getScopeIdOrUndefinedFromComponentId(componentId),
|
||||||
|
);
|
||||||
|
|
||||||
|
return componentState.atomFamily({
|
||||||
|
scopeId: internalScopeId,
|
||||||
|
});
|
||||||
|
};
|
||||||
@ -0,0 +1,128 @@
|
|||||||
|
/* eslint-disable no-redeclare */
|
||||||
|
/* eslint-disable prefer-arrow/prefer-arrow-functions */
|
||||||
|
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||||
|
import { ComponentFamilyReadOnlySelectorV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilyReadOnlySelectorV2';
|
||||||
|
import { ComponentFamilySelectorV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilySelectorV2';
|
||||||
|
import { ComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilyStateV2';
|
||||||
|
import { ComponentReadOnlySelectorV2 } from '@/ui/utilities/state/component-state/types/ComponentReadOnlySelectorV2';
|
||||||
|
import { ComponentSelectorV2 } from '@/ui/utilities/state/component-state/types/ComponentSelectorV2';
|
||||||
|
import { ComponentStateV2 } from '@/ui/utilities/state/component-state/types/ComponentStateV2';
|
||||||
|
import { globalComponentInstanceContextMap } from '@/ui/utilities/state/component-state/utils/globalComponentInstanceContextMap';
|
||||||
|
import { RecoilState, RecoilValueReadOnly, SerializableParam } from 'recoil';
|
||||||
|
|
||||||
|
export function useRecoilComponentCallbackStateV2<ValueType>(
|
||||||
|
componentState: ComponentStateV2<ValueType>,
|
||||||
|
instanceIdFromProps?: string,
|
||||||
|
): RecoilState<ValueType>;
|
||||||
|
export function useRecoilComponentCallbackStateV2<ValueType>(
|
||||||
|
componentSelector: ComponentSelectorV2<ValueType>,
|
||||||
|
instanceIdFromProps?: string,
|
||||||
|
): RecoilState<ValueType>;
|
||||||
|
export function useRecoilComponentCallbackStateV2<ValueType>(
|
||||||
|
componentReadOnlySelector: ComponentReadOnlySelectorV2<ValueType>,
|
||||||
|
instanceIdFromProps?: string,
|
||||||
|
): RecoilValueReadOnly<ValueType>;
|
||||||
|
export function useRecoilComponentCallbackStateV2<
|
||||||
|
ValueType,
|
||||||
|
FamilyKey extends SerializableParam,
|
||||||
|
>(
|
||||||
|
componentFamilyState: ComponentFamilyStateV2<ValueType, FamilyKey>,
|
||||||
|
instanceIdFromProps?: string,
|
||||||
|
): (familyKey: FamilyKey) => RecoilState<ValueType>;
|
||||||
|
export function useRecoilComponentCallbackStateV2<
|
||||||
|
ValueType,
|
||||||
|
FamilyKey extends SerializableParam,
|
||||||
|
>(
|
||||||
|
componentFamilySelector: ComponentFamilySelectorV2<ValueType, FamilyKey>,
|
||||||
|
instanceIdFromProps?: string,
|
||||||
|
): (familyKey: FamilyKey) => RecoilState<ValueType>;
|
||||||
|
export function useRecoilComponentCallbackStateV2<
|
||||||
|
ValueType,
|
||||||
|
FamilyKey extends SerializableParam,
|
||||||
|
>(
|
||||||
|
componentFamilyReadOnlySelector: ComponentFamilyReadOnlySelectorV2<
|
||||||
|
ValueType,
|
||||||
|
FamilyKey
|
||||||
|
>,
|
||||||
|
instanceIdFromProps?: string,
|
||||||
|
): (familyKey: FamilyKey) => RecoilValueReadOnly<ValueType>;
|
||||||
|
export function useRecoilComponentCallbackStateV2<
|
||||||
|
ValueType,
|
||||||
|
FamilyKey extends SerializableParam,
|
||||||
|
>(
|
||||||
|
componentFamilyState: ComponentFamilyStateV2<ValueType, FamilyKey>,
|
||||||
|
instanceIdFromProps?: string,
|
||||||
|
): (familyKey: FamilyKey) => RecoilState<ValueType>;
|
||||||
|
export function useRecoilComponentCallbackStateV2<
|
||||||
|
ComponentState extends
|
||||||
|
| ComponentStateV2<ValueType>
|
||||||
|
| ComponentSelectorV2<ValueType>
|
||||||
|
| ComponentReadOnlySelectorV2<ValueType>
|
||||||
|
| ComponentFamilyStateV2<ValueType, FamilyKey>
|
||||||
|
| ComponentFamilySelectorV2<ValueType, FamilyKey>
|
||||||
|
| ComponentFamilyReadOnlySelectorV2<ValueType, FamilyKey>,
|
||||||
|
ValueType,
|
||||||
|
FamilyKey extends SerializableParam = never,
|
||||||
|
>(
|
||||||
|
componentState: ComponentState,
|
||||||
|
instanceIdFromProps?: string,
|
||||||
|
):
|
||||||
|
| RecoilState<ValueType>
|
||||||
|
| RecoilValueReadOnly<ValueType>
|
||||||
|
| ((familyKey: FamilyKey) => RecoilState<ValueType>)
|
||||||
|
| ((familyKey: FamilyKey) => RecoilValueReadOnly<ValueType>) {
|
||||||
|
const componentStateKey = componentState.key;
|
||||||
|
|
||||||
|
const componentInstanceContext =
|
||||||
|
globalComponentInstanceContextMap.get(componentStateKey);
|
||||||
|
|
||||||
|
if (!componentInstanceContext) {
|
||||||
|
throw new Error(
|
||||||
|
`Instance context for key "${componentStateKey}" is not defined, check the component state declaration.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const instanceId = useAvailableComponentInstanceIdOrThrow(
|
||||||
|
componentInstanceContext,
|
||||||
|
instanceIdFromProps,
|
||||||
|
);
|
||||||
|
|
||||||
|
switch (componentState.type) {
|
||||||
|
case 'ComponentState': {
|
||||||
|
return componentState.atomFamily({
|
||||||
|
instanceId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
case 'ComponentSelector': {
|
||||||
|
return componentState.selectorFamily({
|
||||||
|
instanceId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
case 'ComponentReadOnlySelector': {
|
||||||
|
return componentState.selectorFamily({
|
||||||
|
instanceId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
case 'ComponentFamilyState': {
|
||||||
|
return (familyKey: FamilyKey) =>
|
||||||
|
componentState.atomFamily({
|
||||||
|
instanceId,
|
||||||
|
familyKey,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
case 'ComponentFamilySelector': {
|
||||||
|
return (familyKey: FamilyKey) =>
|
||||||
|
componentState.selectorFamily({
|
||||||
|
instanceId,
|
||||||
|
familyKey,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
case 'ComponentFamilyReadOnlySelector': {
|
||||||
|
return (familyKey: FamilyKey) =>
|
||||||
|
componentState.selectorFamily({
|
||||||
|
instanceId,
|
||||||
|
familyKey,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
/* eslint-disable react-hooks/rules-of-hooks */
|
||||||
|
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||||
|
import { ComponentFamilyReadOnlySelectorV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilyReadOnlySelectorV2';
|
||||||
|
import { ComponentFamilySelectorV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilySelectorV2';
|
||||||
|
import { ComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilyStateV2';
|
||||||
|
import { globalComponentInstanceContextMap } from '@/ui/utilities/state/component-state/utils/globalComponentInstanceContextMap';
|
||||||
|
import { SerializableParam, useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
|
export const useRecoilComponentFamilyValueV2 = <
|
||||||
|
StateType,
|
||||||
|
FamilyKey extends SerializableParam,
|
||||||
|
>(
|
||||||
|
componentStateV2:
|
||||||
|
| ComponentFamilyStateV2<StateType, FamilyKey>
|
||||||
|
| ComponentFamilySelectorV2<StateType, FamilyKey>
|
||||||
|
| ComponentFamilyReadOnlySelectorV2<StateType, FamilyKey>,
|
||||||
|
familyKey: FamilyKey,
|
||||||
|
instanceIdFromProps?: string,
|
||||||
|
): StateType => {
|
||||||
|
const instanceContext = globalComponentInstanceContextMap.get(
|
||||||
|
componentStateV2.key,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!instanceContext) {
|
||||||
|
throw new Error(
|
||||||
|
`Instance context for key "${componentStateV2.key}" is not defined`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const instanceId = useAvailableComponentInstanceIdOrThrow(
|
||||||
|
instanceContext,
|
||||||
|
instanceIdFromProps,
|
||||||
|
);
|
||||||
|
|
||||||
|
switch (componentStateV2.type) {
|
||||||
|
case 'ComponentFamilyState': {
|
||||||
|
return useRecoilValue(
|
||||||
|
componentStateV2.atomFamily({ familyKey, instanceId }),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
case 'ComponentFamilySelector': {
|
||||||
|
return useRecoilValue(
|
||||||
|
componentStateV2.selectorFamily({ familyKey, instanceId }),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
case 'ComponentFamilyReadOnlySelector': {
|
||||||
|
return useRecoilValue(
|
||||||
|
componentStateV2.selectorFamily({ familyKey, instanceId }),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
|
||||||
|
import { getScopeIdOrUndefinedFromComponentId } from '@/ui/utilities/recoil-scope/utils/getScopeIdOrUndefinedFromComponentId';
|
||||||
|
import { RecoilComponentState } from '@/ui/utilities/state/component-state/types/RecoilComponentState';
|
||||||
|
import { useRecoilState } from 'recoil';
|
||||||
|
|
||||||
|
export const useRecoilComponentState = <StateType>(
|
||||||
|
componentState: RecoilComponentState<StateType>,
|
||||||
|
componentId?: string,
|
||||||
|
) => {
|
||||||
|
const componentContext = (window as any).componentContextStateMap?.get(
|
||||||
|
componentState.key,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!componentContext) {
|
||||||
|
throw new Error(
|
||||||
|
`Component context for key "${componentState.key}" is not defined`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const internalComponentId = useAvailableScopeIdOrThrow(
|
||||||
|
componentContext,
|
||||||
|
getScopeIdOrUndefinedFromComponentId(componentId),
|
||||||
|
);
|
||||||
|
|
||||||
|
return useRecoilState(
|
||||||
|
componentState.atomFamily({ scopeId: internalComponentId }),
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||||
|
import { ComponentStateV2 } from '@/ui/utilities/state/component-state/types/ComponentStateV2';
|
||||||
|
import { globalComponentInstanceContextMap } from '@/ui/utilities/state/component-state/utils/globalComponentInstanceContextMap';
|
||||||
|
import { useRecoilState } from 'recoil';
|
||||||
|
|
||||||
|
export const useRecoilComponentStateV2 = <StateType>(
|
||||||
|
componentState: ComponentStateV2<StateType>,
|
||||||
|
instanceIdFromProps?: string,
|
||||||
|
) => {
|
||||||
|
const componentInstanceContext = globalComponentInstanceContextMap.get(
|
||||||
|
componentState.key,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!componentInstanceContext) {
|
||||||
|
throw new Error(
|
||||||
|
`Instance context for key "${componentState.key}" is not defined`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const instanceId = useAvailableComponentInstanceIdOrThrow(
|
||||||
|
componentInstanceContext,
|
||||||
|
instanceIdFromProps,
|
||||||
|
);
|
||||||
|
|
||||||
|
return useRecoilState(componentState.atomFamily({ instanceId }));
|
||||||
|
};
|
||||||
@ -2,10 +2,10 @@ import { useRecoilValue } from 'recoil';
|
|||||||
|
|
||||||
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
|
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
|
||||||
import { getScopeIdOrUndefinedFromComponentId } from '@/ui/utilities/recoil-scope/utils/getScopeIdOrUndefinedFromComponentId';
|
import { getScopeIdOrUndefinedFromComponentId } from '@/ui/utilities/recoil-scope/utils/getScopeIdOrUndefinedFromComponentId';
|
||||||
import { ComponentState } from '@/ui/utilities/state/component-state/types/ComponentState';
|
import { RecoilComponentState } from '@/ui/utilities/state/component-state/types/RecoilComponentState';
|
||||||
|
|
||||||
export const useRecoilComponentValue = <StateType>(
|
export const useRecoilComponentValue = <StateType>(
|
||||||
componentState: ComponentState<StateType>,
|
componentState: RecoilComponentState<StateType>,
|
||||||
componentId?: string,
|
componentId?: string,
|
||||||
) => {
|
) => {
|
||||||
const componentContext = (window as any).componentContextStateMap?.get(
|
const componentContext = (window as any).componentContextStateMap?.get(
|
||||||
|
|||||||
@ -0,0 +1,26 @@
|
|||||||
|
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||||
|
import { ComponentStateV2 } from '@/ui/utilities/state/component-state/types/ComponentStateV2';
|
||||||
|
import { globalComponentInstanceContextMap } from '@/ui/utilities/state/component-state/utils/globalComponentInstanceContextMap';
|
||||||
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
|
export const useRecoilComponentValueV2 = <StateType>(
|
||||||
|
componentStateV2: ComponentStateV2<StateType>,
|
||||||
|
instanceIdFromProps?: string,
|
||||||
|
) => {
|
||||||
|
const instanceContext = globalComponentInstanceContextMap.get(
|
||||||
|
componentStateV2.key,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!instanceContext) {
|
||||||
|
throw new Error(
|
||||||
|
`Instance context for key "${componentStateV2.key}" is not defined`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const instanceId = useAvailableComponentInstanceIdOrThrow(
|
||||||
|
instanceContext,
|
||||||
|
instanceIdFromProps,
|
||||||
|
);
|
||||||
|
|
||||||
|
return useRecoilValue(componentStateV2.atomFamily({ instanceId }));
|
||||||
|
};
|
||||||
@ -1,9 +1,9 @@
|
|||||||
import { useScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useScopeInternalContext';
|
import { useScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useScopeInternalContext';
|
||||||
import { ComponentFamilyState } from '@/ui/utilities/state/component-state/types/ComponentFamilyState';
|
import { ComponentFamilyState } from '@/ui/utilities/state/component-state/types/ComponentFamilyState';
|
||||||
import { ComponentState } from '@/ui/utilities/state/component-state/types/ComponentState';
|
import { RecoilComponentState } from '@/ui/utilities/state/component-state/types/RecoilComponentState';
|
||||||
|
|
||||||
export const useScopeIdFromStateContext = (
|
export const useScopeIdFromStateContext = (
|
||||||
componentState: ComponentState<any> | ComponentFamilyState<any, any>,
|
componentState: RecoilComponentState<any> | ComponentFamilyState<any, any>,
|
||||||
) => {
|
) => {
|
||||||
const componentContext = (window as any).componentContextStateMap?.get(
|
const componentContext = (window as any).componentContextStateMap?.get(
|
||||||
componentState.key,
|
componentState.key,
|
||||||
|
|||||||
@ -0,0 +1,52 @@
|
|||||||
|
/* eslint-disable react-hooks/rules-of-hooks */
|
||||||
|
|
||||||
|
// We're disabling rules-of-hooks because we're sure that the call order cannot be modified
|
||||||
|
// because a component state cannot change its type during its lifecycle
|
||||||
|
|
||||||
|
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||||
|
import { ComponentFamilySelectorV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilySelectorV2';
|
||||||
|
import { ComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilyStateV2';
|
||||||
|
import { globalComponentInstanceContextMap } from '@/ui/utilities/state/component-state/utils/globalComponentInstanceContextMap';
|
||||||
|
import { SerializableParam, SetterOrUpdater, useSetRecoilState } from 'recoil';
|
||||||
|
|
||||||
|
export const useSetRecoilComponentFamilyStateV2 = <
|
||||||
|
StateType,
|
||||||
|
FamilyKey extends SerializableParam,
|
||||||
|
>(
|
||||||
|
componentState:
|
||||||
|
| ComponentFamilyStateV2<StateType, FamilyKey>
|
||||||
|
| ComponentFamilySelectorV2<StateType, FamilyKey>,
|
||||||
|
familyKey: FamilyKey,
|
||||||
|
instanceIdFromProps?: string,
|
||||||
|
): SetterOrUpdater<StateType> => {
|
||||||
|
const componentInstanceContext = globalComponentInstanceContextMap.get(
|
||||||
|
componentState.key,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!componentInstanceContext) {
|
||||||
|
throw new Error(
|
||||||
|
`Instance context for key "${componentState.key}" is not defined`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const instanceId = useAvailableComponentInstanceIdOrThrow(
|
||||||
|
componentInstanceContext,
|
||||||
|
instanceIdFromProps,
|
||||||
|
);
|
||||||
|
|
||||||
|
switch (componentState.type) {
|
||||||
|
case 'ComponentFamilyState': {
|
||||||
|
return useSetRecoilState(
|
||||||
|
componentState.atomFamily({ familyKey, instanceId }),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
case 'ComponentFamilySelector': {
|
||||||
|
return useSetRecoilState(
|
||||||
|
componentState.selectorFamily({
|
||||||
|
familyKey,
|
||||||
|
instanceId,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -2,10 +2,10 @@ import { useSetRecoilState } from 'recoil';
|
|||||||
|
|
||||||
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
|
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
|
||||||
import { getScopeIdOrUndefinedFromComponentId } from '@/ui/utilities/recoil-scope/utils/getScopeIdOrUndefinedFromComponentId';
|
import { getScopeIdOrUndefinedFromComponentId } from '@/ui/utilities/recoil-scope/utils/getScopeIdOrUndefinedFromComponentId';
|
||||||
import { ComponentState } from '@/ui/utilities/state/component-state/types/ComponentState';
|
import { RecoilComponentState } from '@/ui/utilities/state/component-state/types/RecoilComponentState';
|
||||||
|
|
||||||
export const useSetRecoilComponentState = <StateType>(
|
export const useSetRecoilComponentState = <StateType>(
|
||||||
componentState: ComponentState<StateType>,
|
componentState: RecoilComponentState<StateType>,
|
||||||
componentId?: string,
|
componentId?: string,
|
||||||
) => {
|
) => {
|
||||||
const componentContext = (window as any).componentContextStateMap?.get(
|
const componentContext = (window as any).componentContextStateMap?.get(
|
||||||
|
|||||||
@ -0,0 +1,26 @@
|
|||||||
|
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||||
|
import { ComponentStateV2 } from '@/ui/utilities/state/component-state/types/ComponentStateV2';
|
||||||
|
import { globalComponentInstanceContextMap } from '@/ui/utilities/state/component-state/utils/globalComponentInstanceContextMap';
|
||||||
|
import { SetterOrUpdater, useSetRecoilState } from 'recoil';
|
||||||
|
|
||||||
|
export const useSetRecoilComponentStateV2 = <ValueType>(
|
||||||
|
componentState: ComponentStateV2<ValueType>,
|
||||||
|
instanceIdFromProps?: string,
|
||||||
|
): SetterOrUpdater<ValueType> => {
|
||||||
|
const componentInstanceContext = globalComponentInstanceContextMap.get(
|
||||||
|
componentState.key,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!componentInstanceContext) {
|
||||||
|
throw new Error(
|
||||||
|
`Instance context for key "${componentState.key}" is not defined`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const instanceId = useAvailableComponentInstanceIdOrThrow(
|
||||||
|
componentInstanceContext,
|
||||||
|
instanceIdFromProps,
|
||||||
|
);
|
||||||
|
|
||||||
|
return useSetRecoilState(componentState.atomFamily({ instanceId }));
|
||||||
|
};
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
import { ComponentFamilyStateKeyV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilyStateKeyV2';
|
||||||
|
import { ComponentStateTypeV2 } from '@/ui/utilities/state/component-state/types/ComponentStateTypeV2';
|
||||||
|
import { RecoilValueReadOnly, SerializableParam } from 'recoil';
|
||||||
|
|
||||||
|
export type ComponentFamilyReadOnlySelectorV2<
|
||||||
|
StateType,
|
||||||
|
FamilyKey extends SerializableParam,
|
||||||
|
> = {
|
||||||
|
type: Extract<ComponentStateTypeV2, 'ComponentFamilyReadOnlySelector'>;
|
||||||
|
key: string;
|
||||||
|
selectorFamily: (
|
||||||
|
componentFamilyStateKey: ComponentFamilyStateKeyV2<FamilyKey>,
|
||||||
|
) => RecoilValueReadOnly<StateType>;
|
||||||
|
};
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
import { ComponentFamilyStateKeyV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilyStateKeyV2';
|
||||||
|
import { ComponentStateTypeV2 } from '@/ui/utilities/state/component-state/types/ComponentStateTypeV2';
|
||||||
|
import { RecoilState, SerializableParam } from 'recoil';
|
||||||
|
|
||||||
|
export type ComponentFamilySelectorV2<
|
||||||
|
StateType,
|
||||||
|
FamilyKey extends SerializableParam,
|
||||||
|
> = {
|
||||||
|
type: Extract<ComponentStateTypeV2, 'ComponentFamilySelector'>;
|
||||||
|
key: string;
|
||||||
|
selectorFamily: (
|
||||||
|
componentFamilyStateKey: ComponentFamilyStateKeyV2<FamilyKey>,
|
||||||
|
) => RecoilState<StateType>;
|
||||||
|
};
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
import { ComponentStateKeyV2 } from '@/ui/utilities/state/component-state/types/ComponentStateKeyV2';
|
||||||
|
import { SerializableParam } from 'recoil';
|
||||||
|
|
||||||
|
export type ComponentFamilyStateKeyV2<FamilyKey extends SerializableParam> =
|
||||||
|
ComponentStateKeyV2 & {
|
||||||
|
familyKey: FamilyKey;
|
||||||
|
};
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
import { ComponentFamilyStateKeyV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilyStateKeyV2';
|
||||||
|
import { ComponentStateTypeV2 } from '@/ui/utilities/state/component-state/types/ComponentStateTypeV2';
|
||||||
|
import { RecoilState, SerializableParam } from 'recoil';
|
||||||
|
|
||||||
|
export type ComponentFamilyStateV2<
|
||||||
|
StateType,
|
||||||
|
FamilyKey extends SerializableParam,
|
||||||
|
> = {
|
||||||
|
type: Extract<ComponentStateTypeV2, 'ComponentFamilyState'>;
|
||||||
|
key: string;
|
||||||
|
atomFamily: (
|
||||||
|
componentFamilyStateKey: ComponentFamilyStateKeyV2<FamilyKey>,
|
||||||
|
) => RecoilState<StateType>;
|
||||||
|
};
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
import { Context } from 'react';
|
||||||
|
|
||||||
|
export type ComponentInstanceStateContext<T extends { instanceId: string }> =
|
||||||
|
Context<T | null>;
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
import { ComponentStateKeyV2 } from '@/ui/utilities/state/component-state/types/ComponentStateKeyV2';
|
||||||
|
import { ComponentStateTypeV2 } from '@/ui/utilities/state/component-state/types/ComponentStateTypeV2';
|
||||||
|
import { RecoilValueReadOnly } from 'recoil';
|
||||||
|
|
||||||
|
export type ComponentReadOnlySelectorV2<StateType> = {
|
||||||
|
type: Extract<ComponentStateTypeV2, 'ComponentReadOnlySelector'>;
|
||||||
|
key: string;
|
||||||
|
selectorFamily: (
|
||||||
|
componentStateKey: ComponentStateKeyV2,
|
||||||
|
) => RecoilValueReadOnly<StateType>;
|
||||||
|
};
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
import { ComponentStateKeyV2 } from '@/ui/utilities/state/component-state/types/ComponentStateKeyV2';
|
||||||
|
import { ComponentStateTypeV2 } from '@/ui/utilities/state/component-state/types/ComponentStateTypeV2';
|
||||||
|
import { RecoilState } from 'recoil';
|
||||||
|
|
||||||
|
export type ComponentSelectorV2<StateType> = {
|
||||||
|
type: Extract<ComponentStateTypeV2, 'ComponentSelector'>;
|
||||||
|
key: string;
|
||||||
|
selectorFamily: (
|
||||||
|
componentStateKey: ComponentStateKeyV2,
|
||||||
|
) => RecoilState<StateType>;
|
||||||
|
};
|
||||||
@ -1,8 +0,0 @@
|
|||||||
import { RecoilState } from 'recoil';
|
|
||||||
|
|
||||||
import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey';
|
|
||||||
|
|
||||||
export type ComponentState<StateType> = {
|
|
||||||
key: string;
|
|
||||||
atomFamily: (componentStateKey: ComponentStateKey) => RecoilState<StateType>;
|
|
||||||
};
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
export type ComponentStateKey = {
|
|
||||||
scopeId: string;
|
|
||||||
};
|
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
export type ComponentStateKeyV2 = {
|
||||||
|
instanceId: string;
|
||||||
|
};
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
export type ComponentStateTypeV2 =
|
||||||
|
| 'ComponentState'
|
||||||
|
| 'ComponentFamilyState'
|
||||||
|
| 'ComponentSelector'
|
||||||
|
| 'ComponentReadOnlySelector'
|
||||||
|
| 'ComponentFamilySelector'
|
||||||
|
| 'ComponentFamilyReadOnlySelector';
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
import { ComponentStateKeyV2 } from '@/ui/utilities/state/component-state/types/ComponentStateKeyV2';
|
||||||
|
import { ComponentStateTypeV2 } from '@/ui/utilities/state/component-state/types/ComponentStateTypeV2';
|
||||||
|
import { RecoilState } from 'recoil';
|
||||||
|
|
||||||
|
export type ComponentStateV2<StateType> = {
|
||||||
|
type: Extract<ComponentStateTypeV2, 'ComponentState'>;
|
||||||
|
key: string;
|
||||||
|
atomFamily: (
|
||||||
|
componentStateKey: ComponentStateKeyV2,
|
||||||
|
) => RecoilState<StateType>;
|
||||||
|
};
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
import { RecoilState } from 'recoil';
|
||||||
|
import { RecoilComponentStateKey } from './RecoilComponentStateKey';
|
||||||
|
|
||||||
|
export type RecoilComponentState<StateType> = {
|
||||||
|
key: string;
|
||||||
|
atomFamily: (
|
||||||
|
componentStateKey: RecoilComponentStateKey,
|
||||||
|
) => RecoilState<StateType>;
|
||||||
|
};
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
export type RecoilComponentStateKey = {
|
||||||
|
scopeId: string;
|
||||||
|
};
|
||||||
@ -0,0 +1,58 @@
|
|||||||
|
import { selectorFamily, SerializableParam } from 'recoil';
|
||||||
|
|
||||||
|
import { ComponentFamilyReadOnlySelectorV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilyReadOnlySelectorV2';
|
||||||
|
import { ComponentFamilySelectorV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilySelectorV2';
|
||||||
|
import { ComponentFamilyStateKeyV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilyStateKeyV2';
|
||||||
|
import { ComponentInstanceStateContext } from '@/ui/utilities/state/component-state/types/ComponentInstanceStateContext';
|
||||||
|
import { globalComponentInstanceContextMap } from '@/ui/utilities/state/component-state/utils/globalComponentInstanceContextMap';
|
||||||
|
import { SelectorGetter } from '@/ui/utilities/state/types/SelectorGetter';
|
||||||
|
import { SelectorSetter } from '@/ui/utilities/state/types/SelectorSetter';
|
||||||
|
import { isDefined } from 'twenty-ui';
|
||||||
|
|
||||||
|
export const createComponentFamilySelectorV2 = <
|
||||||
|
ValueType,
|
||||||
|
FamilyKey extends SerializableParam,
|
||||||
|
>({
|
||||||
|
key,
|
||||||
|
get,
|
||||||
|
set,
|
||||||
|
componentInstanceContext,
|
||||||
|
}: {
|
||||||
|
key: string;
|
||||||
|
get: SelectorGetter<ValueType, ComponentFamilyStateKeyV2<FamilyKey>>;
|
||||||
|
set?: SelectorSetter<ValueType, ComponentFamilyStateKeyV2<FamilyKey>>;
|
||||||
|
componentInstanceContext: ComponentInstanceStateContext<any> | null;
|
||||||
|
}):
|
||||||
|
| ComponentFamilySelectorV2<ValueType, FamilyKey>
|
||||||
|
| ComponentFamilyReadOnlySelectorV2<ValueType, FamilyKey> => {
|
||||||
|
if (isDefined(componentInstanceContext)) {
|
||||||
|
globalComponentInstanceContextMap.set(key, componentInstanceContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDefined(set)) {
|
||||||
|
return {
|
||||||
|
type: 'ComponentFamilySelector',
|
||||||
|
key,
|
||||||
|
selectorFamily: selectorFamily<
|
||||||
|
ValueType,
|
||||||
|
ComponentFamilyStateKeyV2<FamilyKey>
|
||||||
|
>({
|
||||||
|
key,
|
||||||
|
get,
|
||||||
|
set,
|
||||||
|
}),
|
||||||
|
} satisfies ComponentFamilySelectorV2<ValueType, FamilyKey>;
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
type: 'ComponentFamilyReadOnlySelector',
|
||||||
|
key,
|
||||||
|
selectorFamily: selectorFamily<
|
||||||
|
ValueType,
|
||||||
|
ComponentFamilyStateKeyV2<FamilyKey>
|
||||||
|
>({
|
||||||
|
key,
|
||||||
|
get,
|
||||||
|
}),
|
||||||
|
} satisfies ComponentFamilyReadOnlySelectorV2<ValueType, FamilyKey>;
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -1,13 +1,15 @@
|
|||||||
|
import { ComponentFamilyStateKeyV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilyStateKeyV2';
|
||||||
|
import { ComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilyStateV2';
|
||||||
|
import { ComponentInstanceStateContext } from '@/ui/utilities/state/component-state/types/ComponentInstanceStateContext';
|
||||||
|
import { globalComponentInstanceContextMap } from '@/ui/utilities/state/component-state/utils/globalComponentInstanceContextMap';
|
||||||
import { AtomEffect, atomFamily, SerializableParam } from 'recoil';
|
import { AtomEffect, atomFamily, SerializableParam } from 'recoil';
|
||||||
|
|
||||||
import { ScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/types/ScopeInternalContext';
|
|
||||||
import { ComponentFamilyStateKey } from '@/ui/utilities/state/component-state/types/ComponentFamilyStateKey';
|
|
||||||
import { isDefined } from 'twenty-ui';
|
import { isDefined } from 'twenty-ui';
|
||||||
|
|
||||||
type CreateComponentFamilyStateV2Type<ValueType> = {
|
type CreateComponentFamilyStateArgs<ValueType> = {
|
||||||
key: string;
|
key: string;
|
||||||
defaultValue: ValueType;
|
defaultValue: ValueType;
|
||||||
componentContext: ScopeInternalContext<any> | null;
|
componentInstanceContext: ComponentInstanceStateContext<any> | null;
|
||||||
effects?: AtomEffect<ValueType>[];
|
effects?: AtomEffect<ValueType>[];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -18,22 +20,22 @@ export const createComponentFamilyStateV2 = <
|
|||||||
key,
|
key,
|
||||||
effects,
|
effects,
|
||||||
defaultValue,
|
defaultValue,
|
||||||
componentContext,
|
componentInstanceContext,
|
||||||
}: CreateComponentFamilyStateV2Type<ValueType>) => {
|
}: CreateComponentFamilyStateArgs<ValueType>): ComponentFamilyStateV2<
|
||||||
if (isDefined(componentContext)) {
|
ValueType,
|
||||||
if (!isDefined((window as any).componentContextStateMap)) {
|
FamilyKey
|
||||||
(window as any).componentContextStateMap = new Map();
|
> => {
|
||||||
}
|
if (isDefined(componentInstanceContext)) {
|
||||||
|
globalComponentInstanceContextMap.set(key, componentInstanceContext);
|
||||||
(window as any).componentContextStateMap.set(key, componentContext);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
type: 'ComponentFamilyState',
|
||||||
key,
|
key,
|
||||||
atomFamily: atomFamily<ValueType, ComponentFamilyStateKey<FamilyKey>>({
|
atomFamily: atomFamily<ValueType, ComponentFamilyStateKeyV2<FamilyKey>>({
|
||||||
key,
|
key,
|
||||||
default: defaultValue,
|
default: defaultValue,
|
||||||
effects,
|
effects,
|
||||||
}),
|
}),
|
||||||
};
|
} satisfies ComponentFamilyStateV2<ValueType, FamilyKey>;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -0,0 +1,13 @@
|
|||||||
|
import { ComponentInstanceStateContext } from '@/ui/utilities/state/component-state/types/ComponentInstanceStateContext';
|
||||||
|
import { ComponentStateKeyV2 } from '@/ui/utilities/state/component-state/types/ComponentStateKeyV2';
|
||||||
|
import { createContext } from 'react';
|
||||||
|
|
||||||
|
export const createComponentInstanceContext = <
|
||||||
|
T extends ComponentStateKeyV2 = ComponentStateKeyV2,
|
||||||
|
>(
|
||||||
|
initialValue?: T,
|
||||||
|
) => {
|
||||||
|
return createContext<T | null>(
|
||||||
|
initialValue ?? null,
|
||||||
|
) as ComponentInstanceStateContext<T>;
|
||||||
|
};
|
||||||
@ -1,6 +1,6 @@
|
|||||||
import { selectorFamily } from 'recoil';
|
import { selectorFamily } from 'recoil';
|
||||||
|
|
||||||
import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey';
|
import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey';
|
||||||
import { SelectorGetter } from '@/ui/utilities/state/types/SelectorGetter';
|
import { SelectorGetter } from '@/ui/utilities/state/types/SelectorGetter';
|
||||||
|
|
||||||
export const createComponentReadOnlySelector = <ValueType>({
|
export const createComponentReadOnlySelector = <ValueType>({
|
||||||
@ -8,9 +8,9 @@ export const createComponentReadOnlySelector = <ValueType>({
|
|||||||
get,
|
get,
|
||||||
}: {
|
}: {
|
||||||
key: string;
|
key: string;
|
||||||
get: SelectorGetter<ValueType, ComponentStateKey>;
|
get: SelectorGetter<ValueType, RecoilComponentStateKey>;
|
||||||
}) => {
|
}) => {
|
||||||
return selectorFamily<ValueType, ComponentStateKey>({
|
return selectorFamily<ValueType, RecoilComponentStateKey>({
|
||||||
key,
|
key,
|
||||||
get,
|
get,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { selectorFamily } from 'recoil';
|
import { selectorFamily } from 'recoil';
|
||||||
|
|
||||||
import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey';
|
import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey';
|
||||||
import { SelectorGetter } from '@/ui/utilities/state/types/SelectorGetter';
|
import { SelectorGetter } from '@/ui/utilities/state/types/SelectorGetter';
|
||||||
import { SelectorSetter } from '@/ui/utilities/state/types/SelectorSetter';
|
import { SelectorSetter } from '@/ui/utilities/state/types/SelectorSetter';
|
||||||
|
|
||||||
@ -10,10 +10,10 @@ export const createComponentSelector = <ValueType>({
|
|||||||
set,
|
set,
|
||||||
}: {
|
}: {
|
||||||
key: string;
|
key: string;
|
||||||
get: SelectorGetter<ValueType, ComponentStateKey>;
|
get: SelectorGetter<ValueType, RecoilComponentStateKey>;
|
||||||
set: SelectorSetter<ValueType, ComponentStateKey>;
|
set: SelectorSetter<ValueType, RecoilComponentStateKey>;
|
||||||
}) => {
|
}) => {
|
||||||
return selectorFamily<ValueType, ComponentStateKey>({
|
return selectorFamily<ValueType, RecoilComponentStateKey>({
|
||||||
key,
|
key,
|
||||||
get,
|
get,
|
||||||
set,
|
set,
|
||||||
|
|||||||
@ -0,0 +1,47 @@
|
|||||||
|
import { selectorFamily } from 'recoil';
|
||||||
|
|
||||||
|
import { ComponentInstanceStateContext } from '@/ui/utilities/state/component-state/types/ComponentInstanceStateContext';
|
||||||
|
import { ComponentReadOnlySelectorV2 } from '@/ui/utilities/state/component-state/types/ComponentReadOnlySelectorV2';
|
||||||
|
import { ComponentSelectorV2 } from '@/ui/utilities/state/component-state/types/ComponentSelectorV2';
|
||||||
|
import { ComponentStateKeyV2 } from '@/ui/utilities/state/component-state/types/ComponentStateKeyV2';
|
||||||
|
import { globalComponentInstanceContextMap } from '@/ui/utilities/state/component-state/utils/globalComponentInstanceContextMap';
|
||||||
|
import { SelectorGetter } from '@/ui/utilities/state/types/SelectorGetter';
|
||||||
|
import { SelectorSetter } from '@/ui/utilities/state/types/SelectorSetter';
|
||||||
|
import { isDefined } from 'twenty-ui';
|
||||||
|
|
||||||
|
export const createComponentSelectorV2 = <ValueType>({
|
||||||
|
key,
|
||||||
|
get,
|
||||||
|
set,
|
||||||
|
instanceContext,
|
||||||
|
}: {
|
||||||
|
key: string;
|
||||||
|
get: SelectorGetter<ValueType, ComponentStateKeyV2>;
|
||||||
|
set?: SelectorSetter<ValueType, ComponentStateKeyV2>;
|
||||||
|
instanceContext: ComponentInstanceStateContext<any> | null;
|
||||||
|
}): ComponentSelectorV2<ValueType> | ComponentReadOnlySelectorV2<ValueType> => {
|
||||||
|
if (isDefined(instanceContext)) {
|
||||||
|
globalComponentInstanceContextMap.set(key, instanceContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDefined(set)) {
|
||||||
|
return {
|
||||||
|
type: 'ComponentSelector',
|
||||||
|
key,
|
||||||
|
selectorFamily: selectorFamily<ValueType, ComponentStateKeyV2>({
|
||||||
|
key,
|
||||||
|
get,
|
||||||
|
set,
|
||||||
|
}),
|
||||||
|
} satisfies ComponentSelectorV2<ValueType>;
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
type: 'ComponentReadOnlySelector',
|
||||||
|
key,
|
||||||
|
selectorFamily: selectorFamily<ValueType, ComponentStateKeyV2>({
|
||||||
|
key,
|
||||||
|
get,
|
||||||
|
}),
|
||||||
|
} satisfies ComponentReadOnlySelectorV2<ValueType>;
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -1,6 +1,6 @@
|
|||||||
import { AtomEffect, atomFamily } from 'recoil';
|
import { AtomEffect, atomFamily } from 'recoil';
|
||||||
|
|
||||||
import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey';
|
import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey';
|
||||||
|
|
||||||
type CreateComponentStateType<ValueType> = {
|
type CreateComponentStateType<ValueType> = {
|
||||||
key: string;
|
key: string;
|
||||||
@ -13,7 +13,7 @@ export const createComponentState = <ValueType>({
|
|||||||
defaultValue,
|
defaultValue,
|
||||||
effects,
|
effects,
|
||||||
}: CreateComponentStateType<ValueType>) => {
|
}: CreateComponentStateType<ValueType>) => {
|
||||||
return atomFamily<ValueType, ComponentStateKey>({
|
return atomFamily<ValueType, RecoilComponentStateKey>({
|
||||||
key,
|
key,
|
||||||
default: defaultValue,
|
default: defaultValue,
|
||||||
effects: effects,
|
effects: effects,
|
||||||
|
|||||||
@ -1,37 +1,35 @@
|
|||||||
|
import { ComponentInstanceStateContext } from '@/ui/utilities/state/component-state/types/ComponentInstanceStateContext';
|
||||||
|
import { ComponentStateKeyV2 } from '@/ui/utilities/state/component-state/types/ComponentStateKeyV2';
|
||||||
|
import { ComponentStateV2 } from '@/ui/utilities/state/component-state/types/ComponentStateV2';
|
||||||
|
import { globalComponentInstanceContextMap } from '@/ui/utilities/state/component-state/utils/globalComponentInstanceContextMap';
|
||||||
import { AtomEffect, atomFamily } from 'recoil';
|
import { AtomEffect, atomFamily } from 'recoil';
|
||||||
|
|
||||||
import { ScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/types/ScopeInternalContext';
|
|
||||||
import { ComponentState } from '@/ui/utilities/state/component-state/types/ComponentState';
|
|
||||||
import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey';
|
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isDefined } from '~/utils/isDefined';
|
||||||
|
|
||||||
type CreateComponentStateV2Type<ValueType> = {
|
type CreateComponentInstanceStateArgs<ValueType> = {
|
||||||
key: string;
|
key: string;
|
||||||
defaultValue: ValueType;
|
defaultValue: ValueType;
|
||||||
componentContext?: ScopeInternalContext<any> | null;
|
componentInstanceContext: ComponentInstanceStateContext<any> | null;
|
||||||
effects?: AtomEffect<ValueType>[];
|
effects?: AtomEffect<ValueType>[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const createComponentStateV2 = <ValueType>({
|
export const createComponentStateV2 = <ValueType>({
|
||||||
key,
|
key,
|
||||||
defaultValue,
|
defaultValue,
|
||||||
componentContext,
|
componentInstanceContext,
|
||||||
effects,
|
effects,
|
||||||
}: CreateComponentStateV2Type<ValueType>): ComponentState<ValueType> => {
|
}: CreateComponentInstanceStateArgs<ValueType>): ComponentStateV2<ValueType> => {
|
||||||
if (isDefined(componentContext)) {
|
if (isDefined(componentInstanceContext)) {
|
||||||
if (!isDefined((window as any).componentContextStateMap)) {
|
globalComponentInstanceContextMap.set(key, componentInstanceContext);
|
||||||
(window as any).componentContextStateMap = new Map();
|
|
||||||
}
|
|
||||||
|
|
||||||
(window as any).componentContextStateMap.set(key, componentContext);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
type: 'ComponentState',
|
||||||
key,
|
key,
|
||||||
atomFamily: atomFamily<ValueType, ComponentStateKey>({
|
atomFamily: atomFamily<ValueType, ComponentStateKeyV2>({
|
||||||
key,
|
key,
|
||||||
default: defaultValue,
|
default: defaultValue,
|
||||||
effects: effects,
|
effects: effects,
|
||||||
}),
|
}),
|
||||||
};
|
} satisfies ComponentStateV2<ValueType>;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -0,0 +1,38 @@
|
|||||||
|
import { AtomEffect, atomFamily } from 'recoil';
|
||||||
|
|
||||||
|
import { ScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/types/ScopeInternalContext';
|
||||||
|
|
||||||
|
import { RecoilComponentState } from '@/ui/utilities/state/component-state/types/RecoilComponentState';
|
||||||
|
import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey';
|
||||||
|
import { isDefined } from '~/utils/isDefined';
|
||||||
|
|
||||||
|
type CreateComponentStateV2Type<ValueType> = {
|
||||||
|
key: string;
|
||||||
|
defaultValue: ValueType;
|
||||||
|
componentContext?: ScopeInternalContext<any> | null;
|
||||||
|
effects?: AtomEffect<ValueType>[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createComponentStateV2_alpha = <ValueType>({
|
||||||
|
key,
|
||||||
|
defaultValue,
|
||||||
|
componentContext,
|
||||||
|
effects,
|
||||||
|
}: CreateComponentStateV2Type<ValueType>): RecoilComponentState<ValueType> => {
|
||||||
|
if (isDefined(componentContext)) {
|
||||||
|
if (!isDefined((window as any).componentContextStateMap)) {
|
||||||
|
(window as any).componentContextStateMap = new Map();
|
||||||
|
}
|
||||||
|
|
||||||
|
(window as any).componentContextStateMap.set(key, componentContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
key,
|
||||||
|
atomFamily: atomFamily<ValueType, RecoilComponentStateKey>({
|
||||||
|
key,
|
||||||
|
default: defaultValue,
|
||||||
|
effects: effects,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
import { createContext } from 'react';
|
||||||
|
|
||||||
|
export const createEventContext = <
|
||||||
|
Events extends Record<string, (...args: any) => void>,
|
||||||
|
>(
|
||||||
|
initialValue?: Events,
|
||||||
|
) => {
|
||||||
|
return createContext<Events>((initialValue ?? {}) as Events);
|
||||||
|
};
|
||||||
@ -1,10 +1,10 @@
|
|||||||
import { RecoilValueReadOnly } from 'recoil';
|
import { RecoilValueReadOnly } from 'recoil';
|
||||||
|
|
||||||
import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey';
|
import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey';
|
||||||
|
|
||||||
export const extractComponentReadOnlySelector = <StateType>(
|
export const extractComponentReadOnlySelector = <StateType>(
|
||||||
componentSelector: (
|
componentSelector: (
|
||||||
componentStateKey: ComponentStateKey,
|
componentStateKey: RecoilComponentStateKey,
|
||||||
) => RecoilValueReadOnly<StateType>,
|
) => RecoilValueReadOnly<StateType>,
|
||||||
scopeId: string,
|
scopeId: string,
|
||||||
) => {
|
) => {
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import { RecoilState } from 'recoil';
|
import { RecoilState } from 'recoil';
|
||||||
|
|
||||||
import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey';
|
import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey';
|
||||||
|
|
||||||
export const extractComponentSelector = <StateType>(
|
export const extractComponentSelector = <StateType>(
|
||||||
componentSelector: (
|
componentSelector: (
|
||||||
componentStateKey: ComponentStateKey,
|
componentStateKey: RecoilComponentStateKey,
|
||||||
) => RecoilState<StateType>,
|
) => RecoilState<StateType>,
|
||||||
scopeId: string,
|
scopeId: string,
|
||||||
) => {
|
) => {
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import { RecoilState } from 'recoil';
|
import { RecoilState } from 'recoil';
|
||||||
|
|
||||||
import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey';
|
import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey';
|
||||||
|
|
||||||
export const extractComponentState = <StateType>(
|
export const extractComponentState = <StateType>(
|
||||||
componentState: (
|
componentState: (
|
||||||
componentStateKey: ComponentStateKey,
|
componentStateKey: RecoilComponentStateKey,
|
||||||
) => RecoilState<StateType>,
|
) => RecoilState<StateType>,
|
||||||
scopeId: string,
|
scopeId: string,
|
||||||
) => {
|
) => {
|
||||||
|
|||||||
@ -0,0 +1,21 @@
|
|||||||
|
import { ComponentInstanceStateContext } from '@/ui/utilities/state/component-state/types/ComponentInstanceStateContext';
|
||||||
|
import { isDefined } from 'twenty-ui';
|
||||||
|
|
||||||
|
class ComponentInstanceContextMap {
|
||||||
|
constructor() {
|
||||||
|
if (!isDefined((window as any).componentComponentStateContextMap)) {
|
||||||
|
(window as any).componentComponentStateContextMap = new Map();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public get(key: string): ComponentInstanceStateContext<any> {
|
||||||
|
return (window as any).componentComponentStateContextMap.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public set(key: string, context: ComponentInstanceStateContext<any>) {
|
||||||
|
(window as any).componentComponentStateContextMap.set(key, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const globalComponentInstanceContextMap =
|
||||||
|
new ComponentInstanceContextMap();
|
||||||
@ -1,5 +1,4 @@
|
|||||||
import { useCallback, useEffect } from 'react';
|
import { useCallback, useEffect } from 'react';
|
||||||
import { useRecoilValue } from 'recoil';
|
|
||||||
|
|
||||||
import { MultipleFiltersDropdownContent } from '@/object-record/object-filter-dropdown/components/MultipleFiltersDropdownContent';
|
import { MultipleFiltersDropdownContent } from '@/object-record/object-filter-dropdown/components/MultipleFiltersDropdownContent';
|
||||||
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
|
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
|
||||||
@ -8,8 +7,11 @@ import { FilterOperand } from '@/object-record/object-filter-dropdown/types/Filt
|
|||||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||||
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
|
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
|
||||||
|
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||||
import { EditableFilterChip } from '@/views/components/EditableFilterChip';
|
import { EditableFilterChip } from '@/views/components/EditableFilterChip';
|
||||||
import { useCombinedViewFilters } from '@/views/hooks/useCombinedViewFilters';
|
|
||||||
|
import { useDeleteCombinedViewFilters } from '@/views/hooks/useDeleteCombinedViewFilters';
|
||||||
|
import { availableFilterDefinitionsComponentState } from '@/views/states/availableFilterDefinitionsComponentState';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isDefined } from '~/utils/isDefined';
|
||||||
|
|
||||||
type EditableFilterDropdownButtonProps = {
|
type EditableFilterDropdownButtonProps = {
|
||||||
@ -24,7 +26,6 @@ export const EditableFilterDropdownButton = ({
|
|||||||
hotkeyScope,
|
hotkeyScope,
|
||||||
}: EditableFilterDropdownButtonProps) => {
|
}: EditableFilterDropdownButtonProps) => {
|
||||||
const {
|
const {
|
||||||
availableFilterDefinitionsState,
|
|
||||||
setFilterDefinitionUsedInDropdown,
|
setFilterDefinitionUsedInDropdown,
|
||||||
setSelectedOperandInDropdown,
|
setSelectedOperandInDropdown,
|
||||||
setSelectedFilter,
|
setSelectedFilter,
|
||||||
@ -32,13 +33,15 @@ export const EditableFilterDropdownButton = ({
|
|||||||
filterDropdownId: viewFilterDropdownId,
|
filterDropdownId: viewFilterDropdownId,
|
||||||
});
|
});
|
||||||
|
|
||||||
const availableFilterDefinitions = useRecoilValue(
|
// TODO: verify this instance id works
|
||||||
availableFilterDefinitionsState,
|
const availableFilterDefinitions = useRecoilComponentValueV2(
|
||||||
|
availableFilterDefinitionsComponentState,
|
||||||
|
viewFilterDropdownId,
|
||||||
);
|
);
|
||||||
|
|
||||||
const { closeDropdown } = useDropdown(viewFilterDropdownId);
|
const { closeDropdown } = useDropdown(viewFilterDropdownId);
|
||||||
|
|
||||||
const { removeCombinedViewFilter } = useCombinedViewFilters();
|
const { deleteCombinedViewFilter } = useDeleteCombinedViewFilters();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const filterDefinition = availableFilterDefinitions.find(
|
const filterDefinition = availableFilterDefinitions.find(
|
||||||
@ -63,7 +66,7 @@ export const EditableFilterDropdownButton = ({
|
|||||||
const handleRemove = () => {
|
const handleRemove = () => {
|
||||||
closeDropdown();
|
closeDropdown();
|
||||||
|
|
||||||
removeCombinedViewFilter(viewFilter.id);
|
deleteCombinedViewFilter(viewFilter.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDropdownClickOutside = useCallback(() => {
|
const handleDropdownClickOutside = useCallback(() => {
|
||||||
@ -72,9 +75,9 @@ export const EditableFilterDropdownButton = ({
|
|||||||
!value &&
|
!value &&
|
||||||
![FilterOperand.IsEmpty, FilterOperand.IsNotEmpty].includes(operand)
|
![FilterOperand.IsEmpty, FilterOperand.IsNotEmpty].includes(operand)
|
||||||
) {
|
) {
|
||||||
removeCombinedViewFilter(fieldId);
|
deleteCombinedViewFilter(fieldId);
|
||||||
}
|
}
|
||||||
}, [viewFilter, removeCombinedViewFilter]);
|
}, [viewFilter, deleteCombinedViewFilter]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dropdown
|
<Dropdown
|
||||||
|
|||||||
@ -2,18 +2,20 @@ import { IconArrowDown, IconArrowUp } from 'twenty-ui';
|
|||||||
|
|
||||||
import { Sort } from '@/object-record/object-sort-dropdown/types/Sort';
|
import { Sort } from '@/object-record/object-sort-dropdown/types/Sort';
|
||||||
import { SortOrFilterChip } from '@/views/components/SortOrFilterChip';
|
import { SortOrFilterChip } from '@/views/components/SortOrFilterChip';
|
||||||
import { useCombinedViewSorts } from '@/views/hooks/useCombinedViewSorts';
|
import { useDeleteCombinedViewSorts } from '@/views/hooks/useDeleteCombinedViewSorts';
|
||||||
|
import { useUpsertCombinedViewSorts } from '@/views/hooks/useUpsertCombinedViewSorts';
|
||||||
|
|
||||||
type EditableSortChipProps = {
|
type EditableSortChipProps = {
|
||||||
viewSort: Sort;
|
viewSort: Sort;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const EditableSortChip = ({ viewSort }: EditableSortChipProps) => {
|
export const EditableSortChip = ({ viewSort }: EditableSortChipProps) => {
|
||||||
const { removeCombinedViewSort, upsertCombinedViewSort } =
|
const { deleteCombinedViewSort } = useDeleteCombinedViewSorts();
|
||||||
useCombinedViewSorts();
|
|
||||||
|
const { upsertCombinedViewSort } = useUpsertCombinedViewSorts();
|
||||||
|
|
||||||
const handleRemoveClick = () => {
|
const handleRemoveClick = () => {
|
||||||
removeCombinedViewSort(viewSort.fieldMetadataId);
|
deleteCombinedViewSort(viewSort.fieldMetadataId);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
|
|||||||
@ -1,18 +1,23 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useSetRecoilState } from 'recoil';
|
|
||||||
|
|
||||||
|
import { useSetRecoilComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentFamilyStateV2';
|
||||||
import { useViewFromQueryParams } from '@/views/hooks/internal/useViewFromQueryParams';
|
import { useViewFromQueryParams } from '@/views/hooks/internal/useViewFromQueryParams';
|
||||||
import { useViewStates } from '@/views/hooks/internal/useViewStates';
|
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||||
import { useResetCurrentView } from '@/views/hooks/useResetCurrentView';
|
import { useResetUnsavedViewStates } from '@/views/hooks/useResetUnsavedViewStates';
|
||||||
|
import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState';
|
||||||
|
import { isDefined } from 'twenty-ui';
|
||||||
|
|
||||||
export const QueryParamsFiltersEffect = () => {
|
export const QueryParamsFiltersEffect = () => {
|
||||||
const { hasFiltersQueryParams, getFiltersFromQueryParams } =
|
const { hasFiltersQueryParams, getFiltersFromQueryParams, viewIdQueryParam } =
|
||||||
useViewFromQueryParams();
|
useViewFromQueryParams();
|
||||||
const { unsavedToUpsertViewFiltersState } = useViewStates();
|
|
||||||
const setUnsavedViewFilter = useSetRecoilState(
|
const setUnsavedViewFilter = useSetRecoilComponentFamilyStateV2(
|
||||||
unsavedToUpsertViewFiltersState,
|
unsavedToUpsertViewFiltersComponentFamilyState,
|
||||||
|
{ viewId: viewIdQueryParam },
|
||||||
);
|
);
|
||||||
const { resetCurrentView } = useResetCurrentView();
|
|
||||||
|
const { resetUnsavedViewStates } = useResetUnsavedViewStates();
|
||||||
|
const { currentViewId } = useGetCurrentView();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!hasFiltersQueryParams) {
|
if (!hasFiltersQueryParams) {
|
||||||
@ -26,13 +31,16 @@ export const QueryParamsFiltersEffect = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
resetCurrentView();
|
if (isDefined(currentViewId)) {
|
||||||
|
resetUnsavedViewStates(currentViewId);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}, [
|
}, [
|
||||||
getFiltersFromQueryParams,
|
getFiltersFromQueryParams,
|
||||||
hasFiltersQueryParams,
|
hasFiltersQueryParams,
|
||||||
resetCurrentView,
|
resetUnsavedViewStates,
|
||||||
setUnsavedViewFilter,
|
setUnsavedViewFilter,
|
||||||
|
currentViewId,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return <></>;
|
return <></>;
|
||||||
|
|||||||
@ -1,22 +1,26 @@
|
|||||||
import { useLastVisitedObjectMetadataItem } from '@/navigation/hooks/useLastVisitedObjectMetadataItem';
|
import { useLastVisitedObjectMetadataItem } from '@/navigation/hooks/useLastVisitedObjectMetadataItem';
|
||||||
import { useLastVisitedView } from '@/navigation/hooks/useLastVisitedView';
|
import { useLastVisitedView } from '@/navigation/hooks/useLastVisitedView';
|
||||||
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
|
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
|
||||||
|
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
|
||||||
import { useViewFromQueryParams } from '@/views/hooks/internal/useViewFromQueryParams';
|
import { useViewFromQueryParams } from '@/views/hooks/internal/useViewFromQueryParams';
|
||||||
import { useViewStates } from '@/views/hooks/internal/useViewStates';
|
|
||||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||||
import { useResetCurrentView } from '@/views/hooks/useResetCurrentView';
|
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
|
||||||
import { isUndefined } from '@sniptt/guards';
|
import { isUndefined } from '@sniptt/guards';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useRecoilState } from 'recoil';
|
|
||||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isDefined } from '~/utils/isDefined';
|
||||||
|
|
||||||
export const QueryParamsViewIdEffect = () => {
|
export const QueryParamsViewIdEffect = () => {
|
||||||
const { getFiltersFromQueryParams, viewIdQueryParam } =
|
const { getFiltersFromQueryParams, viewIdQueryParam } =
|
||||||
useViewFromQueryParams();
|
useViewFromQueryParams();
|
||||||
const { currentViewIdState, componentId: objectNamePlural } = useViewStates();
|
|
||||||
|
|
||||||
const [currentViewId, setCurrentViewId] = useRecoilState(currentViewIdState);
|
// TODO: fix this implicit hack
|
||||||
|
const { instanceId: objectNamePlural } = useGetCurrentView();
|
||||||
|
|
||||||
|
const [currentViewId, setCurrentViewId] = useRecoilComponentStateV2(
|
||||||
|
currentViewIdComponentState,
|
||||||
|
);
|
||||||
|
|
||||||
const { viewsOnCurrentObject } = useGetCurrentView();
|
const { viewsOnCurrentObject } = useGetCurrentView();
|
||||||
const { findObjectMetadataItemByNamePlural } =
|
const { findObjectMetadataItemByNamePlural } =
|
||||||
useFilteredObjectMetadataItems();
|
useFilteredObjectMetadataItems();
|
||||||
@ -34,13 +38,14 @@ export const QueryParamsViewIdEffect = () => {
|
|||||||
lastVisitedObjectMetadataItemId,
|
lastVisitedObjectMetadataItemId,
|
||||||
);
|
);
|
||||||
|
|
||||||
const { resetCurrentView } = useResetCurrentView();
|
// // TODO: scope view bar per view id if possible
|
||||||
|
// const { resetCurrentView } = useResetCurrentView();
|
||||||
|
|
||||||
useEffect(() => {
|
// useEffect(() => {
|
||||||
if (isDefined(currentViewId)) {
|
// if (isDefined(currentViewId)) {
|
||||||
resetCurrentView();
|
// resetCurrentView();
|
||||||
}
|
// }
|
||||||
}, [resetCurrentView, currentViewId]);
|
// }, [resetCurrentView, currentViewId]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const indexView = viewsOnCurrentObject.find((view) => view.key === 'INDEX');
|
const indexView = viewsOnCurrentObject.find((view) => view.key === 'INDEX');
|
||||||
|
|||||||
@ -1,6 +1,4 @@
|
|||||||
import { useCallback } from 'react';
|
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { useRecoilValue, useSetRecoilState } from 'recoil';
|
|
||||||
import { IconChevronDown, IconPlus } from 'twenty-ui';
|
import { IconChevronDown, IconPlus } from 'twenty-ui';
|
||||||
|
|
||||||
import { Button } from '@/ui/input/button/components/Button';
|
import { Button } from '@/ui/input/button/components/Button';
|
||||||
@ -10,14 +8,18 @@ import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/Drop
|
|||||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||||
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
||||||
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
|
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
|
||||||
|
import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2';
|
||||||
|
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||||
|
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||||
import { UPDATE_VIEW_BUTTON_DROPDOWN_ID } from '@/views/constants/UpdateViewButtonDropdownId';
|
import { UPDATE_VIEW_BUTTON_DROPDOWN_ID } from '@/views/constants/UpdateViewButtonDropdownId';
|
||||||
import { useViewFromQueryParams } from '@/views/hooks/internal/useViewFromQueryParams';
|
import { useViewFromQueryParams } from '@/views/hooks/internal/useViewFromQueryParams';
|
||||||
import { useViewStates } from '@/views/hooks/internal/useViewStates';
|
|
||||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||||
import { useSaveCurrentViewFiltersAndSorts } from '@/views/hooks/useSaveCurrentViewFiltersAndSorts';
|
import { useSaveCurrentViewFiltersAndSorts } from '@/views/hooks/useSaveCurrentViewFiltersAndSorts';
|
||||||
|
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
|
||||||
|
import { canPersistViewComponentFamilySelector } from '@/views/states/selectors/canPersistViewComponentFamilySelector';
|
||||||
import { VIEW_PICKER_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerDropdownId';
|
import { VIEW_PICKER_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerDropdownId';
|
||||||
import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode';
|
import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode';
|
||||||
import { useViewPickerStates } from '@/views/view-picker/hooks/useViewPickerStates';
|
import { viewPickerReferenceViewIdComponentState } from '@/views/view-picker/states/viewPickerReferenceViewIdComponentState';
|
||||||
|
|
||||||
const StyledContainer = styled.div`
|
const StyledContainer = styled.div`
|
||||||
border-radius: ${({ theme }) => theme.border.radius.md};
|
border-radius: ${({ theme }) => theme.border.radius.md};
|
||||||
@ -33,12 +35,16 @@ export type UpdateViewButtonGroupProps = {
|
|||||||
export const UpdateViewButtonGroup = ({
|
export const UpdateViewButtonGroup = ({
|
||||||
hotkeyScope,
|
hotkeyScope,
|
||||||
}: UpdateViewButtonGroupProps) => {
|
}: UpdateViewButtonGroupProps) => {
|
||||||
const { canPersistViewSelector, currentViewIdState } = useViewStates();
|
|
||||||
const { saveCurrentViewFilterAndSorts } = useSaveCurrentViewFiltersAndSorts();
|
const { saveCurrentViewFilterAndSorts } = useSaveCurrentViewFiltersAndSorts();
|
||||||
|
|
||||||
const { setViewPickerMode } = useViewPickerMode();
|
const { setViewPickerMode } = useViewPickerMode();
|
||||||
const { viewPickerReferenceViewIdState } = useViewPickerStates();
|
|
||||||
const canPersistView = useRecoilValue(canPersistViewSelector());
|
const currentViewId = useRecoilComponentValueV2(currentViewIdComponentState);
|
||||||
|
|
||||||
|
const canPersistView = useRecoilComponentFamilyValueV2(
|
||||||
|
canPersistViewComponentFamilySelector,
|
||||||
|
{ viewId: currentViewId },
|
||||||
|
);
|
||||||
|
|
||||||
const { closeDropdown: closeUpdateViewButtonDropdown } = useDropdown(
|
const { closeDropdown: closeUpdateViewButtonDropdown } = useDropdown(
|
||||||
UPDATE_VIEW_BUTTON_DROPDOWN_ID,
|
UPDATE_VIEW_BUTTON_DROPDOWN_ID,
|
||||||
@ -48,30 +54,31 @@ export const UpdateViewButtonGroup = ({
|
|||||||
);
|
);
|
||||||
const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView();
|
const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView();
|
||||||
|
|
||||||
const currentViewId = useRecoilValue(currentViewIdState);
|
const setViewPickerReferenceViewId = useSetRecoilComponentStateV2(
|
||||||
|
viewPickerReferenceViewIdComponentState,
|
||||||
const setViewPickerReferenceViewId = useSetRecoilState(
|
|
||||||
viewPickerReferenceViewIdState,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleViewCreate = useCallback(() => {
|
const openViewPickerInCreateMode = () => {
|
||||||
if (!currentViewId) {
|
if (!currentViewId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
openViewPickerDropdown();
|
openViewPickerDropdown();
|
||||||
setViewPickerReferenceViewId(currentViewId);
|
setViewPickerReferenceViewId(currentViewId);
|
||||||
setViewPickerMode('create');
|
setViewPickerMode('create-from-current');
|
||||||
|
|
||||||
closeUpdateViewButtonDropdown();
|
closeUpdateViewButtonDropdown();
|
||||||
}, [
|
};
|
||||||
closeUpdateViewButtonDropdown,
|
|
||||||
currentViewId,
|
|
||||||
openViewPickerDropdown,
|
|
||||||
setViewPickerMode,
|
|
||||||
setViewPickerReferenceViewId,
|
|
||||||
]);
|
|
||||||
|
|
||||||
const handleViewUpdate = async () => {
|
const handleCreateViewClick = () => {
|
||||||
|
openViewPickerInCreateMode();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSaveAsNewViewClick = () => {
|
||||||
|
openViewPickerInCreateMode();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleUpdateViewClick = async () => {
|
||||||
await saveCurrentViewFilterAndSorts();
|
await saveCurrentViewFilterAndSorts();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -87,7 +94,7 @@ export const UpdateViewButtonGroup = ({
|
|||||||
<StyledContainer>
|
<StyledContainer>
|
||||||
{currentViewWithCombinedFiltersAndSorts?.key !== 'INDEX' ? (
|
{currentViewWithCombinedFiltersAndSorts?.key !== 'INDEX' ? (
|
||||||
<ButtonGroup size="small" accent="blue">
|
<ButtonGroup size="small" accent="blue">
|
||||||
<Button title="Update view" onClick={handleViewUpdate} />
|
<Button title="Update view" onClick={handleUpdateViewClick} />
|
||||||
<Dropdown
|
<Dropdown
|
||||||
dropdownId={UPDATE_VIEW_BUTTON_DROPDOWN_ID}
|
dropdownId={UPDATE_VIEW_BUTTON_DROPDOWN_ID}
|
||||||
dropdownHotkeyScope={hotkeyScope}
|
dropdownHotkeyScope={hotkeyScope}
|
||||||
@ -103,7 +110,7 @@ export const UpdateViewButtonGroup = ({
|
|||||||
<>
|
<>
|
||||||
<DropdownMenuItemsContainer>
|
<DropdownMenuItemsContainer>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
onClick={handleViewCreate}
|
onClick={handleCreateViewClick}
|
||||||
LeftIcon={IconPlus}
|
LeftIcon={IconPlus}
|
||||||
text="Create view"
|
text="Create view"
|
||||||
/>
|
/>
|
||||||
@ -115,7 +122,7 @@ export const UpdateViewButtonGroup = ({
|
|||||||
) : (
|
) : (
|
||||||
<Button
|
<Button
|
||||||
title="Save as new view"
|
title="Save as new view"
|
||||||
onClick={handleViewCreate}
|
onClick={handleSaveAsNewViewClick}
|
||||||
accent="blue"
|
accent="blue"
|
||||||
size="small"
|
size="small"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObje
|
|||||||
import { Filter } from '@/object-record/object-filter-dropdown/types/Filter';
|
import { Filter } from '@/object-record/object-filter-dropdown/types/Filter';
|
||||||
import { useHandleToggleTrashColumnFilter } from '@/object-record/record-index/hooks/useHandleToggleTrashColumnFilter';
|
import { useHandleToggleTrashColumnFilter } from '@/object-record/record-index/hooks/useHandleToggleTrashColumnFilter';
|
||||||
import { SortOrFilterChip } from '@/views/components/SortOrFilterChip';
|
import { SortOrFilterChip } from '@/views/components/SortOrFilterChip';
|
||||||
import { useCombinedViewFilters } from '@/views/hooks/useCombinedViewFilters';
|
import { useDeleteCombinedViewFilters } from '@/views/hooks/useDeleteCombinedViewFilters';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
|
|
||||||
type VariantFilterChipProps = {
|
type VariantFilterChipProps = {
|
||||||
@ -16,7 +16,7 @@ export const VariantFilterChip = ({
|
|||||||
viewFilter,
|
viewFilter,
|
||||||
viewBarId,
|
viewBarId,
|
||||||
}: VariantFilterChipProps) => {
|
}: VariantFilterChipProps) => {
|
||||||
const { removeCombinedViewFilter } = useCombinedViewFilters();
|
const { deleteCombinedViewFilter } = useDeleteCombinedViewFilters();
|
||||||
|
|
||||||
const { objectNamePlural } = useParams();
|
const { objectNamePlural } = useParams();
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ export const VariantFilterChip = ({
|
|||||||
const { getIcon } = useIcons();
|
const { getIcon } = useIcons();
|
||||||
|
|
||||||
const handleRemoveClick = () => {
|
const handleRemoveClick = () => {
|
||||||
removeCombinedViewFilter(viewFilter.id);
|
deleteCombinedViewFilter(viewFilter.id);
|
||||||
if (
|
if (
|
||||||
viewFilter.definition.label === 'Deleted' &&
|
viewFilter.definition.label === 'Deleted' &&
|
||||||
viewFilter.operand === 'isNotEmpty'
|
viewFilter.operand === 'isNotEmpty'
|
||||||
|
|||||||
@ -13,12 +13,12 @@ import { ViewBarFilterEffect } from '@/views/components/ViewBarFilterEffect';
|
|||||||
import { ViewBarPageTitle } from '@/views/components/ViewBarPageTitle';
|
import { ViewBarPageTitle } from '@/views/components/ViewBarPageTitle';
|
||||||
import { ViewBarSkeletonLoader } from '@/views/components/ViewBarSkeletonLoader';
|
import { ViewBarSkeletonLoader } from '@/views/components/ViewBarSkeletonLoader';
|
||||||
import { ViewBarSortEffect } from '@/views/components/ViewBarSortEffect';
|
import { ViewBarSortEffect } from '@/views/components/ViewBarSortEffect';
|
||||||
import { ViewScope } from '@/views/scopes/ViewScope';
|
|
||||||
import { GraphQLView } from '@/views/types/GraphQLView';
|
import { GraphQLView } from '@/views/types/GraphQLView';
|
||||||
import { ViewPickerDropdown } from '@/views/view-picker/components/ViewPickerDropdown';
|
import { ViewPickerDropdown } from '@/views/view-picker/components/ViewPickerDropdown';
|
||||||
|
|
||||||
import { ViewsHotkeyScope } from '../types/ViewsHotkeyScope';
|
import { ViewsHotkeyScope } from '../types/ViewsHotkeyScope';
|
||||||
|
|
||||||
|
import { ViewEventContext } from '@/views/events/contexts/ViewEventContext';
|
||||||
import { UpdateViewButtonGroup } from './UpdateViewButtonGroup';
|
import { UpdateViewButtonGroup } from './UpdateViewButtonGroup';
|
||||||
import { ViewBarDetails } from './ViewBarDetails';
|
import { ViewBarDetails } from './ViewBarDetails';
|
||||||
|
|
||||||
@ -41,15 +41,13 @@ export const ViewBar = ({
|
|||||||
const sortDropdownId = 'view-sort';
|
const sortDropdownId = 'view-sort';
|
||||||
|
|
||||||
const loading = useIsPrefetchLoading();
|
const loading = useIsPrefetchLoading();
|
||||||
|
|
||||||
if (!objectNamePlural) {
|
if (!objectNamePlural) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ViewScope
|
<ViewEventContext.Provider value={{ onCurrentViewChange }}>
|
||||||
viewScopeId={viewBarId}
|
|
||||||
onCurrentViewChange={onCurrentViewChange}
|
|
||||||
>
|
|
||||||
<ViewBarEffect viewBarId={viewBarId} />
|
<ViewBarEffect viewBarId={viewBarId} />
|
||||||
<ViewBarFilterEffect filterDropdownId={filterDropdownId} />
|
<ViewBarFilterEffect filterDropdownId={filterDropdownId} />
|
||||||
<ViewBarSortEffect sortDropdownId={sortDropdownId} />
|
<ViewBarSortEffect sortDropdownId={sortDropdownId} />
|
||||||
@ -95,6 +93,6 @@ export const ViewBar = ({
|
|||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</ViewScope>
|
</ViewEventContext.Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,20 +1,25 @@
|
|||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { ReactNode, useMemo } from 'react';
|
import { ReactNode, useMemo } from 'react';
|
||||||
import { useRecoilValue } from 'recoil';
|
|
||||||
|
|
||||||
import { AddObjectFilterFromDetailsButton } from '@/object-record/object-filter-dropdown/components/AddObjectFilterFromDetailsButton';
|
import { AddObjectFilterFromDetailsButton } from '@/object-record/object-filter-dropdown/components/AddObjectFilterFromDetailsButton';
|
||||||
import { ObjectFilterDropdownScope } from '@/object-record/object-filter-dropdown/scopes/ObjectFilterDropdownScope';
|
import { ObjectFilterDropdownScope } from '@/object-record/object-filter-dropdown/scopes/ObjectFilterDropdownScope';
|
||||||
import { Filter } from '@/object-record/object-filter-dropdown/types/Filter';
|
import { Filter } from '@/object-record/object-filter-dropdown/types/Filter';
|
||||||
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
|
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
|
||||||
|
import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2';
|
||||||
|
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||||
import { EditableFilterDropdownButton } from '@/views/components/EditableFilterDropdownButton';
|
import { EditableFilterDropdownButton } from '@/views/components/EditableFilterDropdownButton';
|
||||||
import { EditableSortChip } from '@/views/components/EditableSortChip';
|
import { EditableSortChip } from '@/views/components/EditableSortChip';
|
||||||
import { ViewBarFilterEffect } from '@/views/components/ViewBarFilterEffect';
|
import { ViewBarFilterEffect } from '@/views/components/ViewBarFilterEffect';
|
||||||
import { useViewFromQueryParams } from '@/views/hooks/internal/useViewFromQueryParams';
|
import { useViewFromQueryParams } from '@/views/hooks/internal/useViewFromQueryParams';
|
||||||
import { useViewStates } from '@/views/hooks/internal/useViewStates';
|
|
||||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||||
import { useResetCurrentView } from '@/views/hooks/useResetCurrentView';
|
import { useResetUnsavedViewStates } from '@/views/hooks/useResetUnsavedViewStates';
|
||||||
|
import { availableFilterDefinitionsComponentState } from '@/views/states/availableFilterDefinitionsComponentState';
|
||||||
|
import { availableSortDefinitionsComponentState } from '@/views/states/availableSortDefinitionsComponentState';
|
||||||
|
import { isViewBarExpandedComponentState } from '@/views/states/isViewBarExpandedComponentState';
|
||||||
|
import { canPersistViewComponentFamilySelector } from '@/views/states/selectors/canPersistViewComponentFamilySelector';
|
||||||
import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters';
|
import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters';
|
||||||
import { mapViewSortsToSorts } from '@/views/utils/mapViewSortsToSorts';
|
import { mapViewSortsToSorts } from '@/views/utils/mapViewSortsToSorts';
|
||||||
|
import { isDefined } from 'twenty-ui';
|
||||||
import { VariantFilterChip } from './VariantFilterChip';
|
import { VariantFilterChip } from './VariantFilterChip';
|
||||||
|
|
||||||
export type ViewBarDetailsProps = {
|
export type ViewBarDetailsProps = {
|
||||||
@ -99,26 +104,30 @@ export const ViewBarDetails = ({
|
|||||||
filterDropdownId,
|
filterDropdownId,
|
||||||
viewBarId,
|
viewBarId,
|
||||||
}: ViewBarDetailsProps) => {
|
}: ViewBarDetailsProps) => {
|
||||||
const {
|
|
||||||
canPersistViewSelector,
|
|
||||||
isViewBarExpandedState,
|
|
||||||
availableFilterDefinitionsState,
|
|
||||||
availableSortDefinitionsState,
|
|
||||||
} = useViewStates();
|
|
||||||
|
|
||||||
const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView();
|
const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView();
|
||||||
|
|
||||||
const isViewBarExpanded = useRecoilValue(isViewBarExpandedState);
|
const viewId = currentViewWithCombinedFiltersAndSorts?.id;
|
||||||
const { hasFiltersQueryParams } = useViewFromQueryParams();
|
|
||||||
const canPersistView = useRecoilValue(canPersistViewSelector());
|
const isViewBarExpanded = useRecoilComponentValueV2(
|
||||||
const availableFilterDefinitions = useRecoilValue(
|
isViewBarExpandedComponentState,
|
||||||
availableFilterDefinitionsState,
|
|
||||||
);
|
|
||||||
const availableSortDefinitions = useRecoilValue(
|
|
||||||
availableSortDefinitionsState,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const { resetCurrentView } = useResetCurrentView();
|
const { hasFiltersQueryParams } = useViewFromQueryParams();
|
||||||
|
|
||||||
|
const canPersistView = useRecoilComponentFamilyValueV2(
|
||||||
|
canPersistViewComponentFamilySelector,
|
||||||
|
{ viewId },
|
||||||
|
);
|
||||||
|
|
||||||
|
const availableFilterDefinitions = useRecoilComponentValueV2(
|
||||||
|
availableFilterDefinitionsComponentState,
|
||||||
|
);
|
||||||
|
|
||||||
|
const availableSortDefinitions = useRecoilComponentValueV2(
|
||||||
|
availableSortDefinitionsComponentState,
|
||||||
|
);
|
||||||
|
|
||||||
|
const { resetUnsavedViewStates } = useResetUnsavedViewStates();
|
||||||
const canResetView = canPersistView && !hasFiltersQueryParams;
|
const canResetView = canPersistView && !hasFiltersQueryParams;
|
||||||
|
|
||||||
const { otherViewFilters, defaultViewFilters } = useMemo(() => {
|
const { otherViewFilters, defaultViewFilters } = useMemo(() => {
|
||||||
@ -145,7 +154,9 @@ export const ViewBarDetails = ({
|
|||||||
}, [currentViewWithCombinedFiltersAndSorts]);
|
}, [currentViewWithCombinedFiltersAndSorts]);
|
||||||
|
|
||||||
const handleCancelClick = () => {
|
const handleCancelClick = () => {
|
||||||
resetCurrentView();
|
if (isDefined(viewId)) {
|
||||||
|
resetUnsavedViewStates(viewId);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const shouldExpandViewBar =
|
const shouldExpandViewBar =
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
import { isUndefined } from '@sniptt/guards';
|
import { isUndefined } from '@sniptt/guards';
|
||||||
import { useEffect, useState } from 'react';
|
import { useContext, useEffect, useState } from 'react';
|
||||||
import { useRecoilValue } from 'recoil';
|
|
||||||
|
|
||||||
import { useViewStates } from '@/views/hooks/internal/useViewStates';
|
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||||
|
import { ViewEventContext } from '@/views/events/contexts/ViewEventContext';
|
||||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||||
|
import { availableFilterDefinitionsComponentState } from '@/views/states/availableFilterDefinitionsComponentState';
|
||||||
|
import { isPersistingViewFieldsComponentState } from '@/views/states/isPersistingViewFieldsComponentState';
|
||||||
import { View } from '@/views/types/View';
|
import { View } from '@/views/types/View';
|
||||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||||
|
|
||||||
@ -14,21 +16,22 @@ type ViewBarEffectProps = {
|
|||||||
export const ViewBarEffect = ({ viewBarId }: ViewBarEffectProps) => {
|
export const ViewBarEffect = ({ viewBarId }: ViewBarEffectProps) => {
|
||||||
const { currentViewWithCombinedFiltersAndSorts } =
|
const { currentViewWithCombinedFiltersAndSorts } =
|
||||||
useGetCurrentView(viewBarId);
|
useGetCurrentView(viewBarId);
|
||||||
const {
|
|
||||||
onCurrentViewChangeState,
|
const { onCurrentViewChange } = useContext(ViewEventContext);
|
||||||
availableFilterDefinitionsState,
|
|
||||||
isPersistingViewFieldsState,
|
|
||||||
} = useViewStates(viewBarId);
|
|
||||||
|
|
||||||
const [currentViewSnapshot, setCurrentViewSnapshot] = useState<
|
const [currentViewSnapshot, setCurrentViewSnapshot] = useState<
|
||||||
View | undefined
|
View | undefined
|
||||||
>(undefined);
|
>(undefined);
|
||||||
|
|
||||||
const onCurrentViewChange = useRecoilValue(onCurrentViewChangeState);
|
const availableFilterDefinitions = useRecoilComponentValueV2(
|
||||||
const availableFilterDefinitions = useRecoilValue(
|
availableFilterDefinitionsComponentState,
|
||||||
availableFilterDefinitionsState,
|
viewBarId,
|
||||||
|
);
|
||||||
|
|
||||||
|
const isPersistingViewFields = useRecoilComponentValueV2(
|
||||||
|
isPersistingViewFieldsComponentState,
|
||||||
|
viewBarId,
|
||||||
);
|
);
|
||||||
const isPersistingViewFields = useRecoilValue(isPersistingViewFieldsState);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (
|
if (
|
||||||
|
|||||||
@ -1,12 +1,15 @@
|
|||||||
import { useEffect } from 'react';
|
|
||||||
import { isNonEmptyString } from '@sniptt/guards';
|
import { isNonEmptyString } from '@sniptt/guards';
|
||||||
|
import { useEffect } from 'react';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
|
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
|
||||||
import { Filter } from '@/object-record/object-filter-dropdown/types/Filter';
|
import { Filter } from '@/object-record/object-filter-dropdown/types/Filter';
|
||||||
import { useViewStates } from '@/views/hooks/internal/useViewStates';
|
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||||
import { useCombinedViewFilters } from '@/views/hooks/useCombinedViewFilters';
|
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||||
|
|
||||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||||
|
import { useUpsertCombinedViewFilters } from '@/views/hooks/useUpsertCombinedViewFilters';
|
||||||
|
import { availableFilterDefinitionsComponentState } from '@/views/states/availableFilterDefinitionsComponentState';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isDefined } from '~/utils/isDefined';
|
||||||
|
|
||||||
type ViewBarFilterEffectProps = {
|
type ViewBarFilterEffectProps = {
|
||||||
@ -16,17 +19,15 @@ type ViewBarFilterEffectProps = {
|
|||||||
export const ViewBarFilterEffect = ({
|
export const ViewBarFilterEffect = ({
|
||||||
filterDropdownId,
|
filterDropdownId,
|
||||||
}: ViewBarFilterEffectProps) => {
|
}: ViewBarFilterEffectProps) => {
|
||||||
const { availableFilterDefinitionsState } = useViewStates();
|
const { upsertCombinedViewFilter } = useUpsertCombinedViewFilters();
|
||||||
|
|
||||||
const { upsertCombinedViewFilter } = useCombinedViewFilters();
|
|
||||||
|
|
||||||
const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView();
|
const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView();
|
||||||
|
|
||||||
const availableFilterDefinitions = useRecoilValue(
|
const availableFilterDefinitions = useRecoilComponentValueV2(
|
||||||
availableFilterDefinitionsState,
|
availableFilterDefinitionsComponentState,
|
||||||
);
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
setAvailableFilterDefinitions,
|
|
||||||
setOnFilterSelect,
|
setOnFilterSelect,
|
||||||
filterDefinitionUsedInDropdownState,
|
filterDefinitionUsedInDropdownState,
|
||||||
setObjectFilterDropdownSelectedRecordIds,
|
setObjectFilterDropdownSelectedRecordIds,
|
||||||
@ -37,6 +38,12 @@ export const ViewBarFilterEffect = ({
|
|||||||
filterDefinitionUsedInDropdownState,
|
filterDefinitionUsedInDropdownState,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// TODO: verify this instance id works
|
||||||
|
const setAvailableFilterDefinitions = useSetRecoilComponentStateV2(
|
||||||
|
availableFilterDefinitionsComponentState,
|
||||||
|
filterDropdownId,
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isDefined(availableFilterDefinitions)) {
|
if (isDefined(availableFilterDefinitions)) {
|
||||||
setAvailableFilterDefinitions(availableFilterDefinitions);
|
setAvailableFilterDefinitions(availableFilterDefinitions);
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useRecoilValue, useSetRecoilState } from 'recoil';
|
import { useSetRecoilState } from 'recoil';
|
||||||
|
|
||||||
import { useSortDropdown } from '@/object-record/object-sort-dropdown/hooks/useSortDropdown';
|
import { useSortDropdown } from '@/object-record/object-sort-dropdown/hooks/useSortDropdown';
|
||||||
import { Sort } from '@/object-record/object-sort-dropdown/types/Sort';
|
import { Sort } from '@/object-record/object-sort-dropdown/types/Sort';
|
||||||
import { useViewStates } from '@/views/hooks/internal/useViewStates';
|
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||||
import { useCombinedViewSorts } from '@/views/hooks/useCombinedViewSorts';
|
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||||
|
import { useUpsertCombinedViewSorts } from '@/views/hooks/useUpsertCombinedViewSorts';
|
||||||
|
import { availableSortDefinitionsComponentState } from '@/views/states/availableSortDefinitionsComponentState';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isDefined } from '~/utils/isDefined';
|
||||||
|
|
||||||
type ViewBarSortEffectProps = {
|
type ViewBarSortEffectProps = {
|
||||||
@ -14,23 +16,23 @@ type ViewBarSortEffectProps = {
|
|||||||
export const ViewBarSortEffect = ({
|
export const ViewBarSortEffect = ({
|
||||||
sortDropdownId,
|
sortDropdownId,
|
||||||
}: ViewBarSortEffectProps) => {
|
}: ViewBarSortEffectProps) => {
|
||||||
const { availableSortDefinitionsState } = useViewStates();
|
const { upsertCombinedViewSort } = useUpsertCombinedViewSorts();
|
||||||
const { upsertCombinedViewSort } = useCombinedViewSorts();
|
|
||||||
|
|
||||||
const availableSortDefinitions = useRecoilValue(
|
// TDOO: verify this instance id works
|
||||||
availableSortDefinitionsState,
|
const availableSortDefinitions = useRecoilComponentValueV2(
|
||||||
|
availableSortDefinitionsComponentState,
|
||||||
);
|
);
|
||||||
|
|
||||||
const {
|
const { onSortSelectState } = useSortDropdown({
|
||||||
availableSortDefinitionsState: availableSortDefinitionsInSortDropdownState,
|
|
||||||
onSortSelectState,
|
|
||||||
} = useSortDropdown({
|
|
||||||
sortDropdownId,
|
sortDropdownId,
|
||||||
});
|
});
|
||||||
|
|
||||||
const setAvailableSortDefinitionsInSortDropdown = useSetRecoilState(
|
// TDOO: verify this instance id works
|
||||||
availableSortDefinitionsInSortDropdownState,
|
const setAvailableSortDefinitionsInSortDropdown =
|
||||||
);
|
useSetRecoilComponentStateV2(
|
||||||
|
availableSortDefinitionsComponentState,
|
||||||
|
sortDropdownId,
|
||||||
|
);
|
||||||
const setOnSortSelect = useSetRecoilState(onSortSelectState);
|
const setOnSortSelect = useSetRecoilState(onSortSelectState);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@ -0,0 +1,8 @@
|
|||||||
|
import { View } from '@/views/types/View';
|
||||||
|
import { createEventContext } from '~/utils/createEventContext';
|
||||||
|
|
||||||
|
type ViewEventContextType = {
|
||||||
|
onCurrentViewChange: (view: View | undefined) => void | Promise<void>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ViewEventContext = createEventContext<ViewEventContextType>();
|
||||||
@ -1,91 +0,0 @@
|
|||||||
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
|
|
||||||
import { extractComponentReadOnlySelector } from '@/ui/utilities/state/component-state/utils/extractComponentReadOnlySelector';
|
|
||||||
import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState';
|
|
||||||
import { availableFieldDefinitionsComponentState } from '@/views/states/availableFieldDefinitionsComponentState';
|
|
||||||
import { availableFilterDefinitionsComponentState } from '@/views/states/availableFilterDefinitionsComponentState';
|
|
||||||
import { availableSortDefinitionsComponentState } from '@/views/states/availableSortDefinitionsComponentState';
|
|
||||||
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
|
|
||||||
import { entityCountInCurrentViewComponentState } from '@/views/states/entityCountInCurrentViewComponentState';
|
|
||||||
import { isCurrentViewKeyIndexComponentState } from '@/views/states/isCurrentViewIndexComponentState';
|
|
||||||
import { isPersistingViewFieldsComponentState } from '@/views/states/isPersistingViewFieldsComponentState';
|
|
||||||
import { isViewBarExpandedComponentState } from '@/views/states/isViewBarExpandedComponentState';
|
|
||||||
import { onCurrentViewChangeComponentState } from '@/views/states/onCurrentViewChangeComponentState';
|
|
||||||
import { canPersistViewComponentSelector } from '@/views/states/selectors/canPersistViewComponentSelector';
|
|
||||||
import { unsavedToDeleteViewFilterIdsComponentState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentState';
|
|
||||||
import { unsavedToDeleteViewSortIdsComponentState } from '@/views/states/unsavedToDeleteViewSortIdsComponentState';
|
|
||||||
import { unsavedToUpsertViewFiltersComponentState } from '@/views/states/unsavedToUpsertViewFiltersComponentState';
|
|
||||||
import { unsavedToUpsertViewSortsComponentState } from '@/views/states/unsavedToUpsertViewSortsComponentState';
|
|
||||||
import { viewObjectMetadataIdComponentState } from '@/views/states/viewObjectMetadataIdComponentState';
|
|
||||||
|
|
||||||
import { ViewScopeInternalContext } from '../../scopes/scope-internal-context/ViewScopeInternalContext';
|
|
||||||
|
|
||||||
export const useViewStates = (viewComponentId?: string) => {
|
|
||||||
const componentId = useAvailableScopeIdOrThrow(
|
|
||||||
ViewScopeInternalContext,
|
|
||||||
viewComponentId,
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
componentId,
|
|
||||||
currentViewIdState: extractComponentState(
|
|
||||||
currentViewIdComponentState,
|
|
||||||
componentId,
|
|
||||||
),
|
|
||||||
availableFieldDefinitionsState: extractComponentState(
|
|
||||||
availableFieldDefinitionsComponentState,
|
|
||||||
componentId,
|
|
||||||
),
|
|
||||||
availableFilterDefinitionsState: extractComponentState(
|
|
||||||
availableFilterDefinitionsComponentState,
|
|
||||||
componentId,
|
|
||||||
),
|
|
||||||
availableSortDefinitionsState: extractComponentState(
|
|
||||||
availableSortDefinitionsComponentState,
|
|
||||||
componentId,
|
|
||||||
),
|
|
||||||
canPersistViewSelector: extractComponentReadOnlySelector(
|
|
||||||
canPersistViewComponentSelector,
|
|
||||||
componentId,
|
|
||||||
),
|
|
||||||
isViewBarExpandedState: extractComponentState(
|
|
||||||
isViewBarExpandedComponentState,
|
|
||||||
componentId,
|
|
||||||
),
|
|
||||||
onCurrentViewChangeState: extractComponentState(
|
|
||||||
onCurrentViewChangeComponentState,
|
|
||||||
componentId,
|
|
||||||
),
|
|
||||||
entityCountInCurrentViewState: extractComponentState(
|
|
||||||
entityCountInCurrentViewComponentState,
|
|
||||||
componentId,
|
|
||||||
),
|
|
||||||
viewObjectMetadataIdState: extractComponentState(
|
|
||||||
viewObjectMetadataIdComponentState,
|
|
||||||
componentId,
|
|
||||||
),
|
|
||||||
unsavedToUpsertViewFiltersState: extractComponentState(
|
|
||||||
unsavedToUpsertViewFiltersComponentState,
|
|
||||||
componentId,
|
|
||||||
),
|
|
||||||
unsavedToUpsertViewSortsState: extractComponentState(
|
|
||||||
unsavedToUpsertViewSortsComponentState,
|
|
||||||
componentId,
|
|
||||||
),
|
|
||||||
unsavedToDeleteViewFilterIdsState: extractComponentState(
|
|
||||||
unsavedToDeleteViewFilterIdsComponentState,
|
|
||||||
componentId,
|
|
||||||
),
|
|
||||||
unsavedToDeleteViewSortIdsState: extractComponentState(
|
|
||||||
unsavedToDeleteViewSortIdsComponentState,
|
|
||||||
componentId,
|
|
||||||
),
|
|
||||||
isPersistingViewFieldsState: extractComponentState(
|
|
||||||
isPersistingViewFieldsComponentState,
|
|
||||||
componentId,
|
|
||||||
),
|
|
||||||
isCurrentViewKeyIndexState: extractComponentState(
|
|
||||||
isCurrentViewKeyIndexComponentState,
|
|
||||||
componentId,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user