Feat/improve new views (#2298)

* POC new recoil injected scoped states

* Finished useViewScopedState refactor

* Finished refactor

* Renamed mappers

* Fixed update view fields bug

* Post merge

* Complete refactor

* Fix tests

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Lucas Bordeau
2023-11-04 09:28:55 +01:00
committed by GitHub
parent e70ef58f97
commit 53072298bc
42 changed files with 1018 additions and 885 deletions

View File

@ -1,5 +1,5 @@
import { useContext, useRef, useState } from 'react';
import { useRecoilState } from 'recoil';
import { useRecoilState, useRecoilValue } from 'recoil';
import { Key } from 'ts-key-enum';
import { v4 } from 'uuid';
@ -24,8 +24,8 @@ import { ThemeColor } from '@/ui/theme/constants/colors';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { ViewFieldsVisibilityDropdownSection } from '@/views/components/ViewFieldsVisibilityDropdownSection';
import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates';
import { useView } from '@/views/hooks/useView';
import { useViewGetStates } from '@/views/hooks/useViewGetStates';
import { useBoardCardFields } from '../hooks/useBoardCardFields';
import { boardColumnsState } from '../states/boardColumnsState';
@ -52,9 +52,12 @@ export const BoardOptionsDropdownContent = ({
onStageAdd,
}: BoardOptionsDropdownContentProps) => {
const { setViewEditMode, handleViewNameSubmit } = useView();
const { viewEditMode, currentView } = useViewGetStates();
const { viewEditModeState, currentViewSelector } = useViewScopedStates();
const { BoardRecoilScopeContext } = useContext(BoardContext);
const viewEditMode = useRecoilValue(viewEditModeState);
const currentView = useRecoilValue(currentViewSelector);
const stageInputRef = useRef<HTMLInputElement>(null);
const viewEditInputRef = useRef<HTMLInputElement>(null);

View File

@ -10,6 +10,7 @@ import { isFieldEmail } from '../../types/guards/isFieldEmail';
import { isFieldMoney } from '../../types/guards/isFieldMoney';
import { isFieldNumber } from '../../types/guards/isFieldNumber';
import { isFieldPhone } from '../../types/guards/isFieldPhone';
import { isFieldProbability } from '../../types/guards/isFieldProbability';
import { isFieldRelation } from '../../types/guards/isFieldRelation';
import { isFieldRelationValue } from '../../types/guards/isFieldRelationValue';
import { isFieldText } from '../../types/guards/isFieldText';
@ -34,6 +35,7 @@ export const isEntityFieldEmptyFamilySelector = selectorFamily({
isFieldURL(fieldDefinition) ||
isFieldDate(fieldDefinition) ||
isFieldNumber(fieldDefinition) ||
isFieldProbability(fieldDefinition) ||
isFieldMoney(fieldDefinition) ||
isFieldEmail(fieldDefinition) ||
isFieldBoolean(fieldDefinition) ||

View File

@ -1,5 +1,6 @@
import { useCallback, useRef, useState } from 'react';
import { OnDragEndResponder } from '@hello-pangea/dnd';
import { useRecoilValue } from 'recoil';
import { Key } from 'ts-key-enum';
import { IconChevronLeft, IconFileImport, IconTag } from '@/ui/display/icon';
@ -12,8 +13,8 @@ import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { ViewFieldsVisibilityDropdownSection } from '@/views/components/ViewFieldsVisibilityDropdownSection';
import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates';
import { useView } from '@/views/hooks/useView';
import { useViewGetStates } from '@/views/hooks/useViewGetStates';
import { useTableColumns } from '../../hooks/useTableColumns';
import { TableRecoilScopeContext } from '../../states/recoil-scope-contexts/TableRecoilScopeContext';
@ -29,7 +30,10 @@ export const TableOptionsDropdownContent = ({
onImport?: () => void;
}) => {
const { setViewEditMode, handleViewNameSubmit } = useView();
const { viewEditMode, currentView } = useViewGetStates();
const { viewEditModeState, currentViewSelector } = useViewScopedStates();
const viewEditMode = useRecoilValue(viewEditModeState);
const currentView = useRecoilValue(currentViewSelector);
const { closeDropdown } = useDropdown();

View File

@ -0,0 +1,7 @@
import { RecoilValueReadOnly } from 'recoil';
import { ScopedStateKey } from '../scopes-internal/types/ScopedStateKey';
export type RecoilScopedSelector<StateType> = (
scopedKey: ScopedStateKey,
) => RecoilValueReadOnly<StateType>;

View File

@ -0,0 +1,7 @@
import { RecoilState } from 'recoil';
import { ScopedStateKey } from '../scopes-internal/types/ScopedStateKey';
export type RecoilScopedState<StateType> = (
scopedKey: ScopedStateKey,
) => RecoilState<StateType>;

View File

@ -0,0 +1,30 @@
import {
GetCallback,
GetRecoilValue,
Loadable,
RecoilValue,
selectorFamily,
WrappedValue,
} from 'recoil';
import { ScopedStateKey } from '../scopes-internal/types/ScopedStateKey';
type SelectorGetter<T, P> = (
param: P,
) => (opts: {
get: GetRecoilValue;
getCallback: GetCallback;
}) => Promise<T> | RecoilValue<T> | Loadable<T> | WrappedValue<T> | T;
export const createScopedSelector = <ValueType>({
key,
get,
}: {
key: string;
get: SelectorGetter<ValueType, ScopedStateKey>;
}) => {
return selectorFamily<ValueType, ScopedStateKey>({
key,
get,
});
};

View File

@ -0,0 +1,19 @@
import { RecoilState, SerializableParam } from 'recoil';
import { ScopedFamilyStateKey } from '../scopes-internal/types/ScopedFamilyStateKey';
export const getScopedFamilyState = <
StateType,
FamilyKey extends SerializableParam,
>(
recoilState: (
scopedFamilyKey: ScopedFamilyStateKey<FamilyKey>,
) => RecoilState<StateType>,
scopeId: string,
familyKey: FamilyKey,
) => {
return recoilState({
scopeId,
familyKey: familyKey || ('' as FamilyKey),
});
};

View File

@ -0,0 +1,10 @@
import { RecoilScopedSelector } from '../types/RecoilScopedSelector';
export const getScopedSelector = <StateType>(
recoilScopedState: RecoilScopedSelector<StateType>,
scopeId: string,
) => {
return recoilScopedState({
scopeId,
});
};

View File

@ -0,0 +1,10 @@
import { RecoilScopedState } from '../types/RecoilScopedState';
export const getScopedState = <StateType>(
recoilScopedState: RecoilScopedState<StateType>,
scopeId: string,
) => {
return recoilScopedState({
scopeId,
});
};

View File

@ -0,0 +1,15 @@
import { Snapshot } from 'recoil';
import { RecoilScopedSelector } from '../types/RecoilScopedSelector';
import { getScopedSelector } from './getScopedSelector';
export const getSnapshotScopedSelector = <StateType>(
snapshot: Snapshot,
scopedState: RecoilScopedSelector<StateType>,
scopeId: string,
) => {
return snapshot
.getLoadable(getScopedSelector(scopedState, scopeId))
.getValue();
};

View File

@ -0,0 +1,13 @@
import { Snapshot } from 'recoil';
import { RecoilScopedState } from '../types/RecoilScopedState';
import { getScopedState } from './getScopedState';
export const getSnapshotScopedValue = <StateType>(
snapshot: Snapshot,
scopedState: RecoilScopedState<StateType>,
scopeId: string,
) => {
return snapshot.getLoadable(getScopedState(scopedState, scopeId)).getValue();
};

View File

@ -0,0 +1,8 @@
import { RecoilState, RecoilValueReadOnly, Snapshot } from 'recoil';
export const getSnapshotValue = <StateType>(
snapshot: Snapshot,
state: RecoilState<StateType> | RecoilValueReadOnly<StateType>,
) => {
return snapshot.getLoadable(state).getValue();
};