+4
-2
@@ -1,12 +1,14 @@
|
||||
import { dialogInternalComponentState } from '@/ui/feedback/dialog-manager/states/dialogInternalComponentState';
|
||||
import { useDialogManager } from '@/ui/feedback/dialog-manager/hooks/useDialogManager';
|
||||
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
import { Dialog } from './Dialog';
|
||||
import { DialogManagerEffect } from './DialogManagerEffect';
|
||||
|
||||
export const DialogManager = ({ children }: React.PropsWithChildren) => {
|
||||
const dialogInternal = useRecoilComponentValue(dialogInternalComponentState);
|
||||
const dialogInternal = useRecoilComponentValueV2(
|
||||
dialogInternalComponentState,
|
||||
);
|
||||
const { closeDialog } = useDialogManager();
|
||||
|
||||
return (
|
||||
|
||||
+4
-2
@@ -5,10 +5,12 @@ import { usePushFocusItemToFocusStack } from '@/ui/utilities/focus/hooks/usePush
|
||||
import { FocusComponentType } from '@/ui/utilities/focus/types/FocusComponentType';
|
||||
|
||||
import { dialogInternalComponentState } from '@/ui/feedback/dialog-manager/states/dialogInternalComponentState';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
|
||||
export const DialogManagerEffect = () => {
|
||||
const dialogInternal = useRecoilComponentValue(dialogInternalComponentState);
|
||||
const dialogInternal = useRecoilComponentValueV2(
|
||||
dialogInternalComponentState,
|
||||
);
|
||||
|
||||
const { pushFocusItemToFocusStack } = usePushFocusItemToFocusStack();
|
||||
|
||||
|
||||
+18
-7
@@ -1,4 +1,5 @@
|
||||
import { act, renderHook } from '@testing-library/react';
|
||||
import { Provider as JotaiProvider } from 'jotai';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
@@ -6,7 +7,11 @@ import { DialogComponentInstanceContext } from '@/ui/feedback/dialog-manager/con
|
||||
import { useDialogManager } from '@/ui/feedback/dialog-manager/hooks/useDialogManager';
|
||||
import { dialogInternalComponentState } from '@/ui/feedback/dialog-manager/states/dialogInternalComponentState';
|
||||
import { type DialogOptions } from '@/ui/feedback/dialog-manager/types/DialogOptions';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
import {
|
||||
jotaiStore,
|
||||
resetJotaiStore,
|
||||
} from '@/ui/utilities/state/jotai/jotaiStore';
|
||||
|
||||
const mockedUuid = 'mocked-uuid';
|
||||
jest.mock('uuid');
|
||||
@@ -15,11 +20,13 @@ jest.mock('uuid');
|
||||
|
||||
const Wrapper = ({ children }: { children: React.ReactNode }) => (
|
||||
<RecoilRoot>
|
||||
<DialogComponentInstanceContext.Provider
|
||||
value={{ instanceId: 'dialog-manager' }}
|
||||
>
|
||||
{children}
|
||||
</DialogComponentInstanceContext.Provider>
|
||||
<JotaiProvider store={jotaiStore}>
|
||||
<DialogComponentInstanceContext.Provider
|
||||
value={{ instanceId: 'dialog-manager' }}
|
||||
>
|
||||
{children}
|
||||
</DialogComponentInstanceContext.Provider>
|
||||
</JotaiProvider>
|
||||
</RecoilRoot>
|
||||
);
|
||||
|
||||
@@ -77,7 +84,7 @@ const renderHooks = () => {
|
||||
const { result } = renderHook(
|
||||
() => ({
|
||||
dialogManager: useDialogManager(),
|
||||
dialogInternal: useRecoilComponentValue(dialogInternalComponentState),
|
||||
dialogInternal: useRecoilComponentValueV2(dialogInternalComponentState),
|
||||
}),
|
||||
renderHookConfig,
|
||||
);
|
||||
@@ -95,6 +102,10 @@ const expectedReturnFromEnqueue = (
|
||||
};
|
||||
|
||||
describe('useDialogManager', () => {
|
||||
beforeEach(() => {
|
||||
resetJotaiStore();
|
||||
});
|
||||
|
||||
describe('tests for useDialogManager - enqueueDialog', () => {
|
||||
it('Should enqueueDialog', () => {
|
||||
const result = renderHooks();
|
||||
|
||||
+36
-35
@@ -1,4 +1,4 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { useCallback } from 'react';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { DIALOG_FOCUS_ID } from '@/ui/feedback/dialog-manager/constants/DialogFocusId';
|
||||
@@ -8,55 +8,56 @@ import { DialogComponentInstanceContext } from '@/ui/feedback/dialog-manager/con
|
||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||
import { dialogInternalComponentState } from '@/ui/feedback/dialog-manager/states/dialogInternalComponentState';
|
||||
import { type DialogOptions } from '@/ui/feedback/dialog-manager/types/DialogOptions';
|
||||
import { useStore } from 'jotai';
|
||||
|
||||
export const useDialogManager = () => {
|
||||
const componentInstanceId = useAvailableComponentInstanceIdOrThrow(
|
||||
DialogComponentInstanceContext,
|
||||
);
|
||||
|
||||
const store = useStore();
|
||||
|
||||
const { removeFocusItemFromFocusStackById } =
|
||||
useRemoveFocusItemFromFocusStackById();
|
||||
|
||||
const closeDialog = useRecoilCallback(
|
||||
({ set }) =>
|
||||
(id: string) => {
|
||||
set(
|
||||
dialogInternalComponentState.atomFamily({
|
||||
instanceId: componentInstanceId,
|
||||
}),
|
||||
(prevState) => ({
|
||||
...prevState,
|
||||
queue: prevState.queue.filter((dialog) => dialog.id !== id),
|
||||
}),
|
||||
);
|
||||
const closeDialog = useCallback(
|
||||
(id: string) => {
|
||||
store.set(
|
||||
dialogInternalComponentState.atomFamily({
|
||||
instanceId: componentInstanceId,
|
||||
}),
|
||||
(prevState) => ({
|
||||
...prevState,
|
||||
queue: prevState.queue.filter((dialog) => dialog.id !== id),
|
||||
}),
|
||||
);
|
||||
|
||||
removeFocusItemFromFocusStackById({ focusId: DIALOG_FOCUS_ID });
|
||||
},
|
||||
[componentInstanceId, removeFocusItemFromFocusStackById],
|
||||
removeFocusItemFromFocusStackById({ focusId: DIALOG_FOCUS_ID });
|
||||
},
|
||||
[componentInstanceId, removeFocusItemFromFocusStackById, store],
|
||||
);
|
||||
|
||||
const setDialogQueue = useRecoilCallback(
|
||||
({ set }) =>
|
||||
(newValue) =>
|
||||
set(
|
||||
dialogInternalComponentState.atomFamily({
|
||||
instanceId: componentInstanceId,
|
||||
}),
|
||||
(prev) => {
|
||||
if (prev.queue.length >= prev.maxQueue) {
|
||||
return {
|
||||
...prev,
|
||||
queue: [...prev.queue.slice(1), newValue] as DialogOptions[],
|
||||
};
|
||||
}
|
||||
|
||||
const setDialogQueue = useCallback(
|
||||
(newValue: DialogOptions) =>
|
||||
store.set(
|
||||
dialogInternalComponentState.atomFamily({
|
||||
instanceId: componentInstanceId,
|
||||
}),
|
||||
(prev) => {
|
||||
if (prev.queue.length >= prev.maxQueue) {
|
||||
return {
|
||||
...prev,
|
||||
queue: [...prev.queue, newValue] as DialogOptions[],
|
||||
queue: [...prev.queue.slice(1), newValue],
|
||||
};
|
||||
},
|
||||
),
|
||||
[componentInstanceId],
|
||||
}
|
||||
|
||||
return {
|
||||
...prev,
|
||||
queue: [...prev.queue, newValue],
|
||||
};
|
||||
},
|
||||
),
|
||||
[componentInstanceId, store],
|
||||
);
|
||||
|
||||
const enqueueDialog = (options?: Omit<DialogOptions, 'id'>) => {
|
||||
|
||||
+10
-8
@@ -1,5 +1,5 @@
|
||||
import { DialogComponentInstanceContext } from '@/ui/feedback/dialog-manager/contexts/DialogComponentInstanceContext';
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/jotai/utils/createComponentStateV2';
|
||||
import { type DialogOptions } from '@/ui/feedback/dialog-manager/types/DialogOptions';
|
||||
|
||||
type DialogState = {
|
||||
@@ -7,11 +7,13 @@ type DialogState = {
|
||||
queue: DialogOptions[];
|
||||
};
|
||||
|
||||
export const dialogInternalComponentState = createComponentState<DialogState>({
|
||||
key: 'dialogInternalComponentState',
|
||||
defaultValue: {
|
||||
maxQueue: 2,
|
||||
queue: [],
|
||||
export const dialogInternalComponentState = createComponentStateV2<DialogState>(
|
||||
{
|
||||
key: 'dialogInternalComponentState',
|
||||
defaultValue: {
|
||||
maxQueue: 2,
|
||||
queue: [],
|
||||
},
|
||||
componentInstanceContext: DialogComponentInstanceContext,
|
||||
},
|
||||
componentInstanceContext: DialogComponentInstanceContext,
|
||||
});
|
||||
);
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@ import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
||||
|
||||
import { snackBarInternalComponentState } from '@/ui/feedback/snack-bar-manager/states/snackBarInternalComponentState';
|
||||
import { RootStackingContextZIndices } from '@/ui/layout/constants/RootStackingContextZIndices';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
import { MOBILE_VIEWPORT } from 'twenty-ui/theme';
|
||||
import { SnackBar } from './SnackBar';
|
||||
|
||||
@@ -27,7 +27,7 @@ const StyledSnackBarContainer = styled.div`
|
||||
`;
|
||||
|
||||
export const SnackBarProvider = ({ children }: React.PropsWithChildren) => {
|
||||
const snackBarInternal = useRecoilComponentValue(
|
||||
const snackBarInternal = useRecoilComponentValueV2(
|
||||
snackBarInternalComponentState,
|
||||
);
|
||||
|
||||
|
||||
+42
-42
@@ -1,5 +1,4 @@
|
||||
import { useCallback } from 'react';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
||||
@@ -12,6 +11,7 @@ import { buildErrorAction } from '@/ui/feedback/snack-bar-manager/utils/build-er
|
||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||
import { type ApolloError } from '@apollo/client';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useStore } from 'jotai';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { getErrorMessageFromApolloError } from '~/utils/get-error-message-from-apollo-error.util';
|
||||
|
||||
@@ -20,53 +20,53 @@ export const useSnackBar = () => {
|
||||
SnackBarComponentInstanceContext,
|
||||
);
|
||||
|
||||
const handleSnackBarClose = useRecoilCallback(
|
||||
({ set }) =>
|
||||
(id: string) => {
|
||||
set(
|
||||
snackBarInternalComponentState.atomFamily({
|
||||
instanceId: componentInstanceId,
|
||||
}),
|
||||
(prevState) => ({
|
||||
...prevState,
|
||||
queue: prevState.queue.filter((snackBar) => snackBar.id !== id),
|
||||
}),
|
||||
);
|
||||
},
|
||||
[componentInstanceId],
|
||||
const store = useStore();
|
||||
|
||||
const handleSnackBarClose = useCallback(
|
||||
(id: string) => {
|
||||
store.set(
|
||||
snackBarInternalComponentState.atomFamily({
|
||||
instanceId: componentInstanceId,
|
||||
}),
|
||||
(prevState) => ({
|
||||
...prevState,
|
||||
queue: prevState.queue.filter((snackBar) => snackBar.id !== id),
|
||||
}),
|
||||
);
|
||||
},
|
||||
[componentInstanceId, store],
|
||||
);
|
||||
|
||||
const setSnackBarQueue = useRecoilCallback(
|
||||
({ set }) =>
|
||||
(newValue: SnackBarOptions) =>
|
||||
set(
|
||||
snackBarInternalComponentState.atomFamily({
|
||||
instanceId: componentInstanceId,
|
||||
}),
|
||||
(prev) => {
|
||||
if (
|
||||
isDefined(newValue.dedupeKey) &&
|
||||
prev.queue.some(
|
||||
(snackBar) => snackBar.dedupeKey === newValue.dedupeKey,
|
||||
)
|
||||
) {
|
||||
return prev;
|
||||
}
|
||||
|
||||
if (prev.queue.length >= prev.maxQueue) {
|
||||
return {
|
||||
...prev,
|
||||
queue: [...prev.queue.slice(1), newValue] as SnackBarOptions[],
|
||||
};
|
||||
}
|
||||
const setSnackBarQueue = useCallback(
|
||||
(newValue: SnackBarOptions) =>
|
||||
store.set(
|
||||
snackBarInternalComponentState.atomFamily({
|
||||
instanceId: componentInstanceId,
|
||||
}),
|
||||
(prev) => {
|
||||
if (
|
||||
isDefined(newValue.dedupeKey) &&
|
||||
prev.queue.some(
|
||||
(snackBar) => snackBar.dedupeKey === newValue.dedupeKey,
|
||||
)
|
||||
) {
|
||||
return prev;
|
||||
}
|
||||
|
||||
if (prev.queue.length >= prev.maxQueue) {
|
||||
return {
|
||||
...prev,
|
||||
queue: [...prev.queue, newValue] as SnackBarOptions[],
|
||||
queue: [...prev.queue.slice(1), newValue] as SnackBarOptions[],
|
||||
};
|
||||
},
|
||||
),
|
||||
[componentInstanceId],
|
||||
}
|
||||
|
||||
return {
|
||||
...prev,
|
||||
queue: [...prev.queue, newValue] as SnackBarOptions[],
|
||||
};
|
||||
},
|
||||
),
|
||||
[componentInstanceId, store],
|
||||
);
|
||||
|
||||
const enqueueSuccessSnackBar = useCallback(
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { SnackBarComponentInstanceContext } from '@/ui/feedback/snack-bar-manager/contexts/SnackBarComponentInstanceContext';
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/jotai/utils/createComponentStateV2';
|
||||
import { type SnackBarProps } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
||||
|
||||
export type SnackBarOptions = SnackBarProps & {
|
||||
@@ -12,7 +12,7 @@ export type SnackBarState = {
|
||||
};
|
||||
|
||||
export const snackBarInternalComponentState =
|
||||
createComponentState<SnackBarState>({
|
||||
createComponentStateV2<SnackBarState>({
|
||||
key: 'snackBarState',
|
||||
defaultValue: {
|
||||
maxQueue: 3,
|
||||
|
||||
Reference in New Issue
Block a user