3157 refactor scoped states to move to v3 (#3180)

* renaming

* renaming

* create getDropdownScopeInjectors

* update useDropdown

* create internal hooks folder

* update record-table states to be scoped states

* update record-table selectors to be scoped selectors

* create utils scope injector

* refactor record-table wip

* refactor record-table wip

* wip

* inject scopeId in selectors

* update intenal hooks

* update intenal hooks

* update intenal hooks

* update intenal hooks

* update intenal hooks

* update intenal hooks

* update internal hooks

* update internal hooks

* update internal hooks

* update internal hooks

* update useTableColumns

* update states and hooks

* refactoring

* refactoring

* refactoring

* refactoring

* refactoring

* refactoring

* refactoring

* refactoring

* refactoring

* fix scopeId not in context

* fix lint errors

* fix error in story

* fix errors: wip

* fix errors

* fix error

* fix jest test

* fix scopeId not defined

* fix jest test

* Bug fixes

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
bosiraphael
2024-01-03 19:45:14 +01:00
committed by GitHub
parent 65250839fb
commit b0d3e6d8d3
112 changed files with 1447 additions and 716 deletions

View File

@ -95,7 +95,7 @@ export const IconPicker = ({
setHotkeyScopeAndMemorizePreviousScope,
} = usePreviousHotkeyScope();
const { closeDropdown } = useDropdown({ dropdownScopeId });
const { closeDropdown } = useDropdown(dropdownScopeId);
const { getIcons, getIcon } = useIcons();
const icons = getIcons();

View File

@ -74,7 +74,7 @@ export const Select = <Value extends string | number | null>({
const selectedOption =
options.find(({ value: key }) => key === value) || options[0];
const { closeDropdown } = useDropdown({ dropdownScopeId });
const { closeDropdown } = useDropdown(dropdownScopeId);
const selectControl = (
<StyledControlContainer disabled={disabled} fullWidth={fullWidth}>

View File

@ -75,9 +75,7 @@ export const CountryPickerDropdownButton = ({
const [selectedCountry, setSelectedCountry] = useState<Country>();
const { isDropdownOpen, closeDropdown } = useDropdown({
dropdownScopeId: 'country-picker',
});
const { isDropdownOpen, closeDropdown } = useDropdown('country-picker');
const handleChange = (countryCode: string) => {
onChange(countryCode);

View File

@ -0,0 +1,31 @@
import { DropdownScopeInternalContext } from '@/ui/layout/dropdown/scopes/scope-internal-context/DropdownScopeInternalContext';
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
import { useScopedState } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useScopedState';
type UseDropdownScopedStatesProps = {
dropdownScopeId?: string;
};
export const useDropdownScopedStates = ({
dropdownScopeId,
}: UseDropdownScopedStatesProps) => {
const scopeId = useAvailableScopeIdOrThrow(
DropdownScopeInternalContext,
dropdownScopeId,
);
const {
getScopedState,
getScopedFamilyState,
getScopedSnapshotValue,
getScopedFamilySnapshotValue,
} = useScopedState(scopeId);
return {
scopeId,
injectStateWithDropdownScopeId: getScopedState,
injectFamilyStateWithDropdownScopeId: getScopedFamilyState,
injectSnapshotValueWithDropdownScopeId: getScopedSnapshotValue,
injectFamilySnapshotValueWithDropdownScopeId: getScopedFamilySnapshotValue,
};
};

View File

@ -1,44 +1,44 @@
import { useRecoilState } from 'recoil';
import { useDropdownScopedStates } from '@/ui/layout/dropdown/hooks/internal/useDropdownScopedStates';
import { getDropdownScopeInjectors } from '@/ui/layout/dropdown/utils/internal/getDropdownScopeInjectors';
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
import { DropdownScopeInternalContext } from '../scopes/scope-internal-context/DropdownScopeInternalContext';
export const useDropdown = (dropdownId?: string) => {
const { injectStateWithDropdownScopeId, scopeId } = useDropdownScopedStates({
dropdownScopeId: dropdownId,
});
import { useDropdownStates } from './useDropdownStates';
const {
dropdownHotkeyScopeScopeInjector,
dropdownWidthScopeInjector,
isDropdownOpenScopeInjector,
} = getDropdownScopeInjectors();
type UseDropdownProps = {
dropdownScopeId?: string;
};
export const useDropdown = (props?: UseDropdownProps) => {
const {
setHotkeyScopeAndMemorizePreviousScope,
goBackToPreviousHotkeyScope,
} = usePreviousHotkeyScope();
const scopeId = useAvailableScopeIdOrThrow(
DropdownScopeInternalContext,
props?.dropdownScopeId,
const [dropdownHotkeyScope, setDropdownHotkeyScope] = useRecoilState(
injectStateWithDropdownScopeId(dropdownHotkeyScopeScopeInjector),
);
const {
dropdownHotkeyScope,
setDropdownHotkeyScope,
isDropdownOpen,
setIsDropdownOpen,
dropdownWidth,
setDropdownWidth,
} = useDropdownStates({
scopeId,
});
const [dropdownWidth, setDropdownWidth] = useRecoilState(
injectStateWithDropdownScopeId(dropdownWidthScopeInjector),
);
const closeDropdownButton = () => {
const [isDropdownOpen, setIsDropdownOpen] = useRecoilState(
injectStateWithDropdownScopeId(isDropdownOpenScopeInjector),
);
const closeDropdown = () => {
goBackToPreviousHotkeyScope();
setIsDropdownOpen(false);
};
const openDropdownButton = () => {
const openDropdown = () => {
setIsDropdownOpen(true);
if (dropdownHotkeyScope) {
setHotkeyScopeAndMemorizePreviousScope(
dropdownHotkeyScope.scope,
@ -47,20 +47,20 @@ export const useDropdown = (props?: UseDropdownProps) => {
}
};
const toggleDropdownButton = () => {
const toggleDropdown = () => {
if (isDropdownOpen) {
closeDropdownButton();
closeDropdown();
} else {
openDropdownButton();
openDropdown();
}
};
return {
scopeId,
isDropdownOpen: isDropdownOpen,
closeDropdown: closeDropdownButton,
toggleDropdown: toggleDropdownButton,
openDropdown: openDropdownButton,
closeDropdown,
toggleDropdown,
openDropdown,
dropdownHotkeyScope,
setDropdownHotkeyScope,
dropdownWidth,

View File

@ -1,31 +0,0 @@
import { useRecoilScopedStateV2 } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedStateV2';
import { dropdownHotkeyScopeScopedState } from '../states/dropdownHotkeyScopeScopedState';
import { dropdownWidthScopedState } from '../states/dropdownWidthScopedState';
import { isDropdownOpenScopedState } from '../states/isDropdownOpenScopedState';
export const useDropdownStates = ({ scopeId }: { scopeId: string }) => {
const [isDropdownOpen, setIsDropdownOpen] = useRecoilScopedStateV2(
isDropdownOpenScopedState,
scopeId,
);
const [dropdownHotkeyScope, setDropdownHotkeyScope] = useRecoilScopedStateV2(
dropdownHotkeyScopeScopedState,
scopeId,
);
const [dropdownWidth, setDropdownWidth] = useRecoilScopedStateV2(
dropdownWidthScopedState,
scopeId,
);
return {
isDropdownOpen,
setIsDropdownOpen,
dropdownHotkeyScope,
setDropdownHotkeyScope,
dropdownWidth,
setDropdownWidth,
};
};

View File

@ -0,0 +1,22 @@
import { dropdownHotkeyScopeScopedState } from '@/ui/layout/dropdown/states/dropdownHotkeyScopeScopedState';
import { dropdownWidthScopedState } from '@/ui/layout/dropdown/states/dropdownWidthScopedState';
import { isDropdownOpenScopedState } from '@/ui/layout/dropdown/states/isDropdownOpenScopedState';
import { getScopeInjector } from '@/ui/utilities/recoil-scope/utils/getScopeInjector';
export const getDropdownScopeInjectors = () => {
const dropdownHotkeyScopeScopeInjector = getScopeInjector(
dropdownHotkeyScopeScopedState,
);
const dropdownWidthScopeInjector = getScopeInjector(dropdownWidthScopedState);
const isDropdownOpenScopeInjector = getScopeInjector(
isDropdownOpenScopedState,
);
return {
dropdownHotkeyScopeScopeInjector,
dropdownWidthScopeInjector,
isDropdownOpenScopeInjector,
};
};

View File

@ -27,11 +27,10 @@ export const useSelectableListHotKeys = (
}
};
const { getSelectableListScopedSnapshotValue } = useSelectableListScopedState(
{
const { injectSnapshotValueWithSelectableListScopeId } =
useSelectableListScopedState({
selectableListScopeId: scopeId,
},
);
});
const handleSelect = useRecoilCallback(
({ snapshot, set }) =>
@ -42,11 +41,11 @@ export const useSelectableListHotKeys = (
isSelectedItemIdFamilyScopeInjector,
} = getSelectableListScopeInjectors();
const selectedItemId = getSelectableListScopedSnapshotValue(
const selectedItemId = injectSnapshotValueWithSelectableListScopeId(
snapshot,
selectedItemIdScopeInjector,
);
const selectableItemIds = getSelectableListScopedSnapshotValue(
const selectableItemIds = injectSnapshotValueWithSelectableListScopeId(
snapshot,
selectableItemIdsScopeInjector,
);
@ -120,7 +119,7 @@ export const useSelectableListHotKeys = (
}
}
},
[getSelectableListScopedSnapshotValue, scopeId],
[injectSnapshotValueWithSelectableListScopeId, scopeId],
);
useScopedHotkeys(Key.ArrowUp, () => handleSelect('up'), hotkeyScope, []);
@ -145,12 +144,12 @@ export const useSelectableListHotKeys = (
selectedItemIdScopeInjector,
selectableListOnEnterScopeInjector,
} = getSelectableListScopeInjectors();
const selectedItemId = getSelectableListScopedSnapshotValue(
const selectedItemId = injectSnapshotValueWithSelectableListScopeId(
snapshot,
selectedItemIdScopeInjector,
);
const onEnter = getSelectableListScopedSnapshotValue(
const onEnter = injectSnapshotValueWithSelectableListScopeId(
snapshot,
selectableListOnEnterScopeInjector,
);
@ -159,7 +158,7 @@ export const useSelectableListHotKeys = (
onEnter?.(selectedItemId);
}
},
[getSelectableListScopedSnapshotValue],
[injectSnapshotValueWithSelectableListScopeId],
),
hotkeyScope,
[],

View File

@ -23,9 +23,10 @@ export const useSelectableListScopedState = ({
return {
scopeId,
getSelectableListScopedState: getScopedState,
getSelectableListScopedFamilyState: getScopedFamilyState,
getSelectableListScopedSnapshotValue: getScopedSnapshotValue,
getSelectableListScopedFamilySnapshotValue: getScopedFamilySnapshotValue,
injectStateWithSelectableListScopeId: getScopedState,
injectFamilyStateWithSelectableListScopeId: getScopedFamilyState,
injectSnapshotValueWithSelectableListScopeId: getScopedSnapshotValue,
injectFamilySnapshotValueWithSelectableListScopeId:
getScopedFamilySnapshotValue,
};
};

View File

@ -3,13 +3,13 @@ import { useResetRecoilState, useSetRecoilState } from 'recoil';
import { useSelectableListScopedState } from '@/ui/layout/selectable-list/hooks/internal/useSelectableListScopedState';
import { getSelectableListScopeInjectors } from '@/ui/layout/selectable-list/utils/internal/getSelectableListScopeInjectors';
export const useSelectableList = (selectableListScopeId?: string) => {
export const useSelectableList = (selectableListId?: string) => {
const {
getSelectableListScopedState,
getSelectableListScopedFamilyState,
injectStateWithSelectableListScopeId,
injectFamilyStateWithSelectableListScopeId,
scopeId,
} = useSelectableListScopedState({
selectableListScopeId,
selectableListScopeId: selectableListId,
});
const {
@ -20,17 +20,18 @@ export const useSelectableList = (selectableListScopeId?: string) => {
} = getSelectableListScopeInjectors();
const setSelectableItemIds = useSetRecoilState(
getSelectableListScopedState(selectableItemIdsScopeInjector),
injectStateWithSelectableListScopeId(selectableItemIdsScopeInjector),
);
const setSelectableListOnEnter = useSetRecoilState(
getSelectableListScopedState(selectableListOnEnterScopeInjector),
);
const isSelectedItemIdFamilyState = getSelectableListScopedFamilyState(
isSelectedItemIdFamilyScopeInjector,
injectStateWithSelectableListScopeId(selectableListOnEnterScopeInjector),
);
const isSelectedItemIdFamilyState =
injectFamilyStateWithSelectableListScopeId(
isSelectedItemIdFamilyScopeInjector,
);
const resetSelectedItemIdState = useResetRecoilState(
getSelectableListScopedState(selectedItemIdScopeInjector),
injectStateWithSelectableListScopeId(selectedItemIdScopeInjector),
);
const resetSelectedItem = () => {

View File

@ -23,9 +23,7 @@ export const ShowPageAddButton = ({
}: {
entity: ActivityTargetableEntity;
}) => {
const { closeDropdown, toggleDropdown } = useDropdown({
dropdownScopeId: 'add-show-page',
});
const { closeDropdown, toggleDropdown } = useDropdown('add-show-page');
const openCreateActivity = useOpenCreateActivityDrawer();
const handleSelect = (type: ActivityType) => {

View File

@ -26,9 +26,7 @@ export const ShowPageMoreButton = ({
recordId: string;
objectNameSingular: string;
}) => {
const { closeDropdown, toggleDropdown } = useDropdown({
dropdownScopeId: 'more-show-page',
});
const { closeDropdown, toggleDropdown } = useDropdown('more-show-page');
const navigationMemorizedUrl = useRecoilValue(navigationMemorizedUrlState);
const navigate = useNavigate();

View File

@ -67,10 +67,6 @@ export const useSetHotkeyScope = () =>
scopesToSet.push(AppHotkeyScope.CommandMenu);
}
if (newHotkeyScope.customScopes?.commandMenuOpen) {
scopesToSet.push(AppHotkeyScope.CommandMenuOpen);
}
if (newHotkeyScope?.customScopes?.goto) {
scopesToSet.push(AppHotkeyScope.Goto);
}

View File

@ -2,12 +2,17 @@ import { SerializableParam, Snapshot } from 'recoil';
import { FamilyScopeInjector } from '@/ui/utilities/recoil-scope/utils/getFamilyScopeInjector';
import { ScopeInjector } from '@/ui/utilities/recoil-scope/utils/getScopeInjector';
import { SelectorScopeInjector } from '@/ui/utilities/recoil-scope/utils/getSelectorScopeInjector';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
export const useScopedState = (scopeId: string) => {
const getScopedState = <StateType>(scopeInjector: ScopeInjector<StateType>) =>
scopeInjector(scopeId);
const getScopedSelector = <StateType>(
scopeInjector: SelectorScopeInjector<StateType>,
) => scopeInjector(scopeId);
const getScopedFamilyState =
<StateType, FamilyKey extends SerializableParam>(
familyScopeInjector: FamilyScopeInjector<StateType, FamilyKey>,
@ -16,23 +21,30 @@ export const useScopedState = (scopeId: string) => {
familyScopeInjector(scopeId, familyKey);
const getScopedSnapshotValue = <StateType>(
snashot: Snapshot,
snapshot: Snapshot,
scopeInjector: ScopeInjector<StateType>,
) => getSnapshotValue(snashot, scopeInjector(scopeId));
) => getSnapshotValue(snapshot, scopeInjector(scopeId));
const getScopedSelectorSnapshotValue = <StateType>(
snapshot: Snapshot,
scopeInjector: SelectorScopeInjector<StateType>,
) => getSnapshotValue(snapshot, scopeInjector(scopeId));
const getScopedFamilySnapshotValue =
<StateType, FamilyKey extends SerializableParam>(
snashot: Snapshot,
snapshot: Snapshot,
familyScopeInjector: FamilyScopeInjector<StateType, FamilyKey>,
) =>
(familyKey: FamilyKey) =>
getSnapshotValue(snashot, familyScopeInjector(scopeId, familyKey));
getSnapshotValue(snapshot, familyScopeInjector(scopeId, familyKey));
return {
scopeId,
getScopedState,
getScopedSelector,
getScopedFamilyState,
getScopedSnapshotValue,
getScopedSelectorSnapshotValue,
getScopedFamilySnapshotValue,
};
};

View File

@ -8,7 +8,7 @@ export type ScopeInjector<StateType> = (
export const getScopeInjector = <StateType>(
scopedState: RecoilScopedState<StateType>,
) => {
): ScopeInjector<StateType> => {
return (scopeId: string) =>
scopedState({
scopeId,

View File

@ -0,0 +1,16 @@
import { RecoilValueReadOnly } from 'recoil';
import { RecoilScopedSelector } from '@/ui/utilities/recoil-scope/types/RecoilScopedSelector';
export type SelectorScopeInjector<StateType> = (
scopeId: string,
) => RecoilValueReadOnly<StateType>;
export const getSelectorScopeInjector = <StateType>(
scopedSelector: RecoilScopedSelector<StateType>,
): SelectorScopeInjector<StateType> => {
return (scopeId: string) =>
scopedSelector({
scopeId,
});
};