mirror of
https://github.com/twentyhq/twenty.git
synced 2024-12-28 06:46:24 +03:00
chore(front): Refactor the SnackBar component to use the new scope architecture (#2578)
* chore(front): Refactor the SnackBar component to use the new scope architecture Co-authored-by: v1b3m <vibenjamin6@gmail.com> Co-authored-by: Thiago Nascimbeni <tnascimbeni@gmail.com> * Rename useSnackBarManager Co-authored-by: v1b3m <vibenjamin6@gmail.com> Co-authored-by: Thiago Nascimbeni <tnascimbeni@gmail.com> --------- Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com> Co-authored-by: v1b3m <vibenjamin6@gmail.com> Co-authored-by: Thiago Nascimbeni <tnascimbeni@gmail.com> Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
parent
ff42526a09
commit
ee8f6899fc
@ -12,7 +12,7 @@ import { AppPath } from '@/types/AppPath';
|
|||||||
import { PageHotkeyScope } from '@/types/PageHotkeyScope';
|
import { PageHotkeyScope } from '@/types/PageHotkeyScope';
|
||||||
import { SettingsPath } from '@/types/SettingsPath';
|
import { SettingsPath } from '@/types/SettingsPath';
|
||||||
import { IconCheckbox } from '@/ui/display/icon';
|
import { IconCheckbox } from '@/ui/display/icon';
|
||||||
import { useSnackBar } from '@/ui/feedback/snack-bar/hooks/useSnackBar';
|
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||||
import { TableHotkeyScope } from '@/ui/object/record-table/types/TableHotkeyScope';
|
import { TableHotkeyScope } from '@/ui/object/record-table/types/TableHotkeyScope';
|
||||||
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
||||||
import { useGetWorkspaceFromInviteHashLazyQuery } from '~/generated/graphql';
|
import { useGetWorkspaceFromInviteHashLazyQuery } from '~/generated/graphql';
|
||||||
|
@ -11,7 +11,8 @@ import { ApolloMetadataClientProvider } from '@/object-metadata/components/Apoll
|
|||||||
import { ObjectMetadataItemsProvider } from '@/object-metadata/components/ObjectMetadataItemsProvider';
|
import { ObjectMetadataItemsProvider } from '@/object-metadata/components/ObjectMetadataItemsProvider';
|
||||||
import { DialogManager } from '@/ui/feedback/dialog-manager/components/DialogManager';
|
import { DialogManager } from '@/ui/feedback/dialog-manager/components/DialogManager';
|
||||||
import { DialogManagerScope } from '@/ui/feedback/dialog-manager/scopes/DialogManagerScope';
|
import { DialogManagerScope } from '@/ui/feedback/dialog-manager/scopes/DialogManagerScope';
|
||||||
import { SnackBarProvider } from '@/ui/feedback/snack-bar/components/SnackBarProvider';
|
import { SnackBarProvider } from '@/ui/feedback/snack-bar-manager/components/SnackBarProvider';
|
||||||
|
import { SnackBarProviderScope } from '@/ui/feedback/snack-bar-manager/scopes/SnackBarProviderScope';
|
||||||
import { AppThemeProvider } from '@/ui/theme/components/AppThemeProvider';
|
import { AppThemeProvider } from '@/ui/theme/components/AppThemeProvider';
|
||||||
import { ThemeType } from '@/ui/theme/constants/theme';
|
import { ThemeType } from '@/ui/theme/constants/theme';
|
||||||
import { UserProvider } from '@/users/components/UserProvider';
|
import { UserProvider } from '@/users/components/UserProvider';
|
||||||
@ -37,20 +38,22 @@ root.render(
|
|||||||
<ClientConfigProvider>
|
<ClientConfigProvider>
|
||||||
<UserProvider>
|
<UserProvider>
|
||||||
<ApolloMetadataClientProvider>
|
<ApolloMetadataClientProvider>
|
||||||
<ObjectMetadataItemsProvider>
|
<SnackBarProviderScope snackBarManagerScopeId="snack-bar-manager">
|
||||||
<PageChangeEffect />
|
<ObjectMetadataItemsProvider>
|
||||||
<AppThemeProvider>
|
<PageChangeEffect />
|
||||||
<SnackBarProvider>
|
<AppThemeProvider>
|
||||||
<DialogManagerScope dialogManagerScopeId="dialog-manager">
|
<SnackBarProvider>
|
||||||
<DialogManager>
|
<DialogManagerScope dialogManagerScopeId="dialog-manager">
|
||||||
<StrictMode>
|
<DialogManager>
|
||||||
<App />
|
<StrictMode>
|
||||||
</StrictMode>
|
<App />
|
||||||
</DialogManager>
|
</StrictMode>
|
||||||
</DialogManagerScope>
|
</DialogManager>
|
||||||
</SnackBarProvider>
|
</DialogManagerScope>
|
||||||
</AppThemeProvider>
|
</SnackBarProvider>
|
||||||
</ObjectMetadataItemsProvider>
|
</AppThemeProvider>
|
||||||
|
</ObjectMetadataItemsProvider>
|
||||||
|
</SnackBarProviderScope>
|
||||||
</ApolloMetadataClientProvider>
|
</ApolloMetadataClientProvider>
|
||||||
</UserProvider>
|
</UserProvider>
|
||||||
</ClientConfigProvider>
|
</ClientConfigProvider>
|
||||||
|
@ -9,7 +9,7 @@ import { authProvidersState } from '@/client-config/states/authProvidersState';
|
|||||||
import { isSignInPrefilledState } from '@/client-config/states/isSignInPrefilledState';
|
import { isSignInPrefilledState } from '@/client-config/states/isSignInPrefilledState';
|
||||||
import { AppPath } from '@/types/AppPath';
|
import { AppPath } from '@/types/AppPath';
|
||||||
import { PageHotkeyScope } from '@/types/PageHotkeyScope';
|
import { PageHotkeyScope } from '@/types/PageHotkeyScope';
|
||||||
import { useSnackBar } from '@/ui/feedback/snack-bar/hooks/useSnackBar';
|
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||||
import { useGetWorkspaceFromInviteHashQuery } from '~/generated/graphql';
|
import { useGetWorkspaceFromInviteHashQuery } from '~/generated/graphql';
|
||||||
import { useIsMatchingLocation } from '~/hooks/useIsMatchingLocation';
|
import { useIsMatchingLocation } from '~/hooks/useIsMatchingLocation';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { useCallback, useContext, useState } from 'react';
|
import { useCallback, useContext, useState } from 'react';
|
||||||
|
|
||||||
import { useSnackBar } from '@/ui/feedback/snack-bar/hooks/useSnackBar';
|
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||||
import { relationPickerSearchFilterScopedState } from '@/ui/input/relation-picker/states/relationPickerSearchFilterScopedState';
|
import { relationPickerSearchFilterScopedState } from '@/ui/input/relation-picker/states/relationPickerSearchFilterScopedState';
|
||||||
import { RelationPickerHotkeyScope } from '@/ui/input/relation-picker/types/RelationPickerHotkeyScope';
|
import { RelationPickerHotkeyScope } from '@/ui/input/relation-picker/types/RelationPickerHotkeyScope';
|
||||||
import { NewButton } from '@/ui/layout/board/components/NewButton';
|
import { NewButton } from '@/ui/layout/board/components/NewButton';
|
||||||
|
@ -3,7 +3,7 @@ import { useQuery } from '@apollo/client';
|
|||||||
import { useRecoilCallback } from 'recoil';
|
import { useRecoilCallback } from 'recoil';
|
||||||
|
|
||||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||||
import { useSnackBar } from '@/ui/feedback/snack-bar/hooks/useSnackBar';
|
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||||
import {
|
import {
|
||||||
FieldFilter,
|
FieldFilter,
|
||||||
ObjectFilter,
|
ObjectFilter,
|
||||||
|
@ -0,0 +1,74 @@
|
|||||||
|
import { useMemo } from 'react';
|
||||||
|
import { useQuery } from '@apollo/client';
|
||||||
|
|
||||||
|
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||||
|
import {
|
||||||
|
ObjectFilter,
|
||||||
|
ObjectMetadataItemsQuery,
|
||||||
|
ObjectMetadataItemsQueryVariables,
|
||||||
|
} from '~/generated-metadata/graphql';
|
||||||
|
import { logError } from '~/utils/logError';
|
||||||
|
|
||||||
|
import { FIND_MANY_METADATA_OBJECTS } from '../graphql/queries';
|
||||||
|
import { mapPaginatedObjectMetadataItemsToObjectMetadataItems } from '../utils/mapPaginatedObjectMetadataItemsToObjectMetadataItems';
|
||||||
|
|
||||||
|
import { useApolloMetadataClient } from './useApolloMetadataClient';
|
||||||
|
|
||||||
|
// TODO: test fetchMore
|
||||||
|
export const useFindManyObjectMetadataItems = ({
|
||||||
|
skip,
|
||||||
|
filter,
|
||||||
|
}: { skip?: boolean; filter?: ObjectFilter } = {}) => {
|
||||||
|
const apolloMetadataClient = useApolloMetadataClient();
|
||||||
|
|
||||||
|
const { enqueueSnackBar } = useSnackBar();
|
||||||
|
|
||||||
|
const {
|
||||||
|
data,
|
||||||
|
fetchMore: fetchMoreInternal,
|
||||||
|
loading,
|
||||||
|
error,
|
||||||
|
} = useQuery<ObjectMetadataItemsQuery, ObjectMetadataItemsQueryVariables>(
|
||||||
|
FIND_MANY_METADATA_OBJECTS,
|
||||||
|
{
|
||||||
|
variables: {
|
||||||
|
objectFilter: filter,
|
||||||
|
},
|
||||||
|
client: apolloMetadataClient ?? undefined,
|
||||||
|
skip: skip || !apolloMetadataClient,
|
||||||
|
onError: (error) => {
|
||||||
|
logError('useFindManyObjectMetadataItems error : ' + error);
|
||||||
|
enqueueSnackBar(
|
||||||
|
`Error during useFindManyObjectMetadataItems, ${error.message}`,
|
||||||
|
{
|
||||||
|
variant: 'error',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onCompleted: () => {},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const hasMore = data?.objects?.pageInfo?.hasNextPage;
|
||||||
|
|
||||||
|
const fetchMore = () =>
|
||||||
|
fetchMoreInternal({
|
||||||
|
variables: {
|
||||||
|
afterCursor: data?.objects?.pageInfo?.endCursor,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const objectMetadataItems = useMemo(() => {
|
||||||
|
return mapPaginatedObjectMetadataItemsToObjectMetadataItems({
|
||||||
|
pagedObjectMetadataItems: data,
|
||||||
|
});
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
objectMetadataItems,
|
||||||
|
hasMore,
|
||||||
|
fetchMore,
|
||||||
|
loading,
|
||||||
|
error,
|
||||||
|
};
|
||||||
|
};
|
@ -6,7 +6,7 @@ import { useRecoilState } from 'recoil';
|
|||||||
|
|
||||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||||
import { ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier';
|
import { ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier';
|
||||||
import { useSnackBar } from '@/ui/feedback/snack-bar/hooks/useSnackBar';
|
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||||
import { logError } from '~/utils/logError';
|
import { logError } from '~/utils/logError';
|
||||||
import { capitalize } from '~/utils/string/capitalize';
|
import { capitalize } from '~/utils/string/capitalize';
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { CompanyProgressPicker } from '@/companies/components/CompanyProgressPicker';
|
import { CompanyProgressPicker } from '@/companies/components/CompanyProgressPicker';
|
||||||
import { PageHotkeyScope } from '@/types/PageHotkeyScope';
|
import { PageHotkeyScope } from '@/types/PageHotkeyScope';
|
||||||
import { IconPlus } from '@/ui/display/icon/index';
|
import { IconPlus } from '@/ui/display/icon/index';
|
||||||
import { useSnackBar } from '@/ui/feedback/snack-bar/hooks/useSnackBar';
|
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||||
import { IconButton } from '@/ui/input/button/components/IconButton';
|
import { IconButton } from '@/ui/input/button/components/IconButton';
|
||||||
import { EntityForSelect } from '@/ui/input/relation-picker/types/EntityForSelect';
|
import { EntityForSelect } from '@/ui/input/relation-picker/types/EntityForSelect';
|
||||||
import { RelationPickerHotkeyScope } from '@/ui/input/relation-picker/types/RelationPickerHotkeyScope';
|
import { RelationPickerHotkeyScope } from '@/ui/input/relation-picker/types/RelationPickerHotkeyScope';
|
||||||
|
@ -2,7 +2,7 @@ import { useTheme } from '@emotion/react';
|
|||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
import { IconCopy } from '@/ui/display/icon';
|
import { IconCopy } from '@/ui/display/icon';
|
||||||
import { useSnackBar } from '@/ui/feedback/snack-bar/hooks/useSnackBar';
|
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||||
import { Button } from '@/ui/input/button/components/Button';
|
import { Button } from '@/ui/input/button/components/Button';
|
||||||
import { TextInput } from '@/ui/input/components/TextInput';
|
import { TextInput } from '@/ui/input/components/TextInput';
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ import { useRecoilState } from 'recoil';
|
|||||||
|
|
||||||
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||||
import { useUpdateOneObjectRecord } from '@/object-record/hooks/useUpdateOneObjectRecord';
|
import { useUpdateOneObjectRecord } from '@/object-record/hooks/useUpdateOneObjectRecord';
|
||||||
import { useSnackBar } from '@/ui/feedback/snack-bar/hooks/useSnackBar';
|
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||||
import { Toggle } from '@/ui/input/components/Toggle';
|
import { Toggle } from '@/ui/input/components/Toggle';
|
||||||
|
|
||||||
export const ToggleField = () => {
|
export const ToggleField = () => {
|
||||||
|
@ -12,7 +12,7 @@ import { setColumn } from '@/spreadsheet-import/utils/setColumn';
|
|||||||
import { setIgnoreColumn } from '@/spreadsheet-import/utils/setIgnoreColumn';
|
import { setIgnoreColumn } from '@/spreadsheet-import/utils/setIgnoreColumn';
|
||||||
import { setSubColumn } from '@/spreadsheet-import/utils/setSubColumn';
|
import { setSubColumn } from '@/spreadsheet-import/utils/setSubColumn';
|
||||||
import { useDialogManager } from '@/ui/feedback/dialog-manager/hooks/useDialogManager';
|
import { useDialogManager } from '@/ui/feedback/dialog-manager/hooks/useDialogManager';
|
||||||
import { useSnackBar } from '@/ui/feedback/snack-bar/hooks/useSnackBar';
|
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||||
import { Modal } from '@/ui/layout/modal/components/Modal';
|
import { Modal } from '@/ui/layout/modal/components/Modal';
|
||||||
|
|
||||||
import { ColumnGrid } from './components/ColumnGrid';
|
import { ColumnGrid } from './components/ColumnGrid';
|
||||||
|
@ -8,7 +8,7 @@ import { RawData } from '@/spreadsheet-import/types';
|
|||||||
import { exceedsMaxRecords } from '@/spreadsheet-import/utils/exceedsMaxRecords';
|
import { exceedsMaxRecords } from '@/spreadsheet-import/utils/exceedsMaxRecords';
|
||||||
import { mapWorkbook } from '@/spreadsheet-import/utils/mapWorkbook';
|
import { mapWorkbook } from '@/spreadsheet-import/utils/mapWorkbook';
|
||||||
import { CircularProgressBar } from '@/ui/feedback/progress-bar/components/CircularProgressBar';
|
import { CircularProgressBar } from '@/ui/feedback/progress-bar/components/CircularProgressBar';
|
||||||
import { useSnackBar } from '@/ui/feedback/snack-bar/hooks/useSnackBar';
|
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||||
import { Modal } from '@/ui/layout/modal/components/Modal';
|
import { Modal } from '@/ui/layout/modal/components/Modal';
|
||||||
|
|
||||||
import { MatchColumnsStep } from './MatchColumnsStep/MatchColumnsStep';
|
import { MatchColumnsStep } from './MatchColumnsStep/MatchColumnsStep';
|
||||||
|
@ -5,7 +5,7 @@ import * as XLSX from 'xlsx-ugnis';
|
|||||||
|
|
||||||
import { useSpreadsheetImportInternal } from '@/spreadsheet-import/hooks/useSpreadsheetImportInternal';
|
import { useSpreadsheetImportInternal } from '@/spreadsheet-import/hooks/useSpreadsheetImportInternal';
|
||||||
import { readFileAsync } from '@/spreadsheet-import/utils/readFilesAsync';
|
import { readFileAsync } from '@/spreadsheet-import/utils/readFilesAsync';
|
||||||
import { useSnackBar } from '@/ui/feedback/snack-bar/hooks/useSnackBar';
|
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||||
import { MainButton } from '@/ui/input/button/components/MainButton';
|
import { MainButton } from '@/ui/input/button/components/MainButton';
|
||||||
|
|
||||||
const StyledContainer = styled.div`
|
const StyledContainer = styled.div`
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { motion, useReducedMotion } from 'framer-motion';
|
import { motion, useReducedMotion } from 'framer-motion';
|
||||||
import { useRecoilState } from 'recoil';
|
|
||||||
|
|
||||||
import { snackBarInternalState } from '../states/snackBarState';
|
import { useSnackBarManagerScopedStates } from '@/ui/feedback/snack-bar-manager/hooks/internal/useSnackBarManagerScopedStates';
|
||||||
|
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||||
|
|
||||||
import { SnackBar } from './SnackBar';
|
import { SnackBar } from './SnackBar';
|
||||||
|
|
||||||
const StyledSnackBarContainer = styled.div`
|
const StyledSnackBarContainer = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -53,17 +52,8 @@ const reducedVariants = {
|
|||||||
export const SnackBarProvider = ({ children }: React.PropsWithChildren) => {
|
export const SnackBarProvider = ({ children }: React.PropsWithChildren) => {
|
||||||
const reducedMotion = useReducedMotion();
|
const reducedMotion = useReducedMotion();
|
||||||
|
|
||||||
const [snackBarInternal, setSnackBarInternal] = useRecoilState(
|
const { snackBarInternal } = useSnackBarManagerScopedStates();
|
||||||
snackBarInternalState,
|
const { handleSnackBarClose } = useSnackBar();
|
||||||
);
|
|
||||||
|
|
||||||
// Handle snackbar close event
|
|
||||||
const handleSnackBarClose = (id: string) => {
|
|
||||||
setSnackBarInternal((prevState) => ({
|
|
||||||
...prevState,
|
|
||||||
queue: prevState.queue.filter((snackBar) => snackBar.id !== id),
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
@ -0,0 +1,24 @@
|
|||||||
|
import { SnackBarManagerScopeInternalContext } from '@/ui/feedback/snack-bar-manager/scopes/scope-internal-context/SnackBarManagerScopeInternalContext';
|
||||||
|
import { snackBarInternalScopedState } from '@/ui/feedback/snack-bar-manager/states/snackBarInternalScopedState';
|
||||||
|
import { useRecoilScopedStateV2 } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedStateV2';
|
||||||
|
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
|
||||||
|
|
||||||
|
type useSnackBarManagerScopedStatesProps = {
|
||||||
|
snackBarManagerScopeId?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useSnackBarManagerScopedStates = (
|
||||||
|
props?: useSnackBarManagerScopedStatesProps,
|
||||||
|
) => {
|
||||||
|
const scopeId = useAvailableScopeIdOrThrow(
|
||||||
|
SnackBarManagerScopeInternalContext,
|
||||||
|
props?.snackBarManagerScopeId,
|
||||||
|
);
|
||||||
|
|
||||||
|
const [snackBarInternal, setSnackBarInternal] = useRecoilScopedStateV2(
|
||||||
|
snackBarInternalScopedState,
|
||||||
|
scopeId,
|
||||||
|
);
|
||||||
|
|
||||||
|
return { snackBarInternal, setSnackBarInternal };
|
||||||
|
};
|
@ -0,0 +1,53 @@
|
|||||||
|
import { useRecoilCallback } from 'recoil';
|
||||||
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
|
import { SnackBarManagerScopeInternalContext } from '@/ui/feedback/snack-bar-manager/scopes/scope-internal-context/SnackBarManagerScopeInternalContext';
|
||||||
|
import {
|
||||||
|
snackBarInternalScopedState,
|
||||||
|
SnackBarOptions,
|
||||||
|
} from '@/ui/feedback/snack-bar-manager/states/snackBarInternalScopedState';
|
||||||
|
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
|
||||||
|
|
||||||
|
export const useSnackBar = () => {
|
||||||
|
const scopeId = useAvailableScopeIdOrThrow(
|
||||||
|
SnackBarManagerScopeInternalContext,
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleSnackBarClose = useRecoilCallback(({ set }) => (id: string) => {
|
||||||
|
set(snackBarInternalScopedState({ scopeId }), (prevState) => ({
|
||||||
|
...prevState,
|
||||||
|
queue: prevState.queue.filter((snackBar) => snackBar.id !== id),
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
const setSnackBarQueue = useRecoilCallback(
|
||||||
|
({ set }) =>
|
||||||
|
(newValue) =>
|
||||||
|
set(snackBarInternalScopedState({ scopeId }), (prev) => {
|
||||||
|
if (prev.queue.length >= prev.maxQueue) {
|
||||||
|
return {
|
||||||
|
...prev,
|
||||||
|
queue: [...prev.queue.slice(1), newValue] as SnackBarOptions[],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...prev,
|
||||||
|
queue: [...prev.queue, newValue] as SnackBarOptions[],
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
const enqueueSnackBar = (
|
||||||
|
message: string,
|
||||||
|
options?: Omit<SnackBarOptions, 'message' | 'id'>,
|
||||||
|
) => {
|
||||||
|
setSnackBarQueue({
|
||||||
|
id: uuidv4(),
|
||||||
|
message,
|
||||||
|
...options,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return { handleSnackBarClose, enqueueSnackBar };
|
||||||
|
};
|
@ -0,0 +1,23 @@
|
|||||||
|
import { ReactNode } from 'react';
|
||||||
|
|
||||||
|
import { SnackBarManagerScopeInternalContext } from './scope-internal-context/SnackBarManagerScopeInternalContext';
|
||||||
|
|
||||||
|
type SnackBarProviderScopeProps = {
|
||||||
|
children: ReactNode;
|
||||||
|
snackBarManagerScopeId: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const SnackBarProviderScope = ({
|
||||||
|
children,
|
||||||
|
snackBarManagerScopeId,
|
||||||
|
}: SnackBarProviderScopeProps) => {
|
||||||
|
return (
|
||||||
|
<SnackBarManagerScopeInternalContext.Provider
|
||||||
|
value={{
|
||||||
|
scopeId: snackBarManagerScopeId,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</SnackBarManagerScopeInternalContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,7 @@
|
|||||||
|
import { ScopedStateKey } from '@/ui/utilities/recoil-scope/scopes-internal/types/ScopedStateKey';
|
||||||
|
import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext';
|
||||||
|
|
||||||
|
type SnackBarManagerScopeInternalContextProps = ScopedStateKey;
|
||||||
|
|
||||||
|
export const SnackBarManagerScopeInternalContext =
|
||||||
|
createScopeInternalContext<SnackBarManagerScopeInternalContextProps>();
|
@ -0,0 +1,20 @@
|
|||||||
|
import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState';
|
||||||
|
|
||||||
|
import { SnackBarProps } from '../components/SnackBar';
|
||||||
|
|
||||||
|
export type SnackBarOptions = SnackBarProps & {
|
||||||
|
id: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type SnackBarState = {
|
||||||
|
maxQueue: number;
|
||||||
|
queue: SnackBarOptions[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const snackBarInternalScopedState = createScopedState<SnackBarState>({
|
||||||
|
key: 'snackBarState',
|
||||||
|
defaultValue: {
|
||||||
|
maxQueue: 3,
|
||||||
|
queue: [],
|
||||||
|
},
|
||||||
|
});
|
@ -1,24 +0,0 @@
|
|||||||
import { useSetRecoilState } from 'recoil';
|
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
|
||||||
|
|
||||||
import {
|
|
||||||
SnackBarOptions,
|
|
||||||
snackBarSetQueueState,
|
|
||||||
} from '../states/snackBarState';
|
|
||||||
|
|
||||||
export const useSnackBar = () => {
|
|
||||||
const setSnackBarQueue = useSetRecoilState(snackBarSetQueueState);
|
|
||||||
|
|
||||||
const enqueueSnackBar = (
|
|
||||||
message: string,
|
|
||||||
options?: Omit<SnackBarOptions, 'message' | 'id'>,
|
|
||||||
) => {
|
|
||||||
setSnackBarQueue({
|
|
||||||
id: uuidv4(),
|
|
||||||
message,
|
|
||||||
...options,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return { enqueueSnackBar };
|
|
||||||
};
|
|
@ -1,40 +0,0 @@
|
|||||||
import { atom, selector } from 'recoil';
|
|
||||||
|
|
||||||
import { SnackBarProps } from '../components/SnackBar';
|
|
||||||
|
|
||||||
export type SnackBarOptions = SnackBarProps & {
|
|
||||||
id: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type SnackBarState = {
|
|
||||||
maxQueue: number;
|
|
||||||
queue: SnackBarOptions[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export const snackBarInternalState = atom<SnackBarState>({
|
|
||||||
key: 'snackBarState',
|
|
||||||
default: {
|
|
||||||
maxQueue: 3,
|
|
||||||
queue: [],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO: use a recoil callback
|
|
||||||
export const snackBarSetQueueState = selector<SnackBarOptions | null>({
|
|
||||||
key: 'snackBarQueueState',
|
|
||||||
get: ({ get: _get }) => null, // We don't care about getting the value
|
|
||||||
set: ({ set }, newValue) =>
|
|
||||||
set(snackBarInternalState, (prev) => {
|
|
||||||
if (prev.queue.length >= prev.maxQueue) {
|
|
||||||
return {
|
|
||||||
...prev,
|
|
||||||
queue: [...prev.queue.slice(1), newValue] as SnackBarOptions[],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
...prev,
|
|
||||||
queue: [...prev.queue, newValue] as SnackBarOptions[],
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
});
|
|
@ -8,7 +8,7 @@ import {
|
|||||||
IconPencil,
|
IconPencil,
|
||||||
IconPlus,
|
IconPlus,
|
||||||
} from '@/ui/display/icon';
|
} from '@/ui/display/icon';
|
||||||
import { useSnackBar } from '@/ui/feedback/snack-bar/hooks/useSnackBar';
|
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||||
import { relationPickerSearchFilterScopedState } from '@/ui/input/relation-picker/states/relationPickerSearchFilterScopedState';
|
import { relationPickerSearchFilterScopedState } from '@/ui/input/relation-picker/states/relationPickerSearchFilterScopedState';
|
||||||
import { EntityForSelect } from '@/ui/input/relation-picker/types/EntityForSelect';
|
import { EntityForSelect } from '@/ui/input/relation-picker/types/EntityForSelect';
|
||||||
import { RelationPickerHotkeyScope } from '@/ui/input/relation-picker/types/RelationPickerHotkeyScope';
|
import { RelationPickerHotkeyScope } from '@/ui/input/relation-picker/types/RelationPickerHotkeyScope';
|
||||||
|
@ -2,7 +2,7 @@ import { useTheme } from '@emotion/react';
|
|||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
import { IconCopy, IconLink } from '@/ui/display/icon';
|
import { IconCopy, IconLink } from '@/ui/display/icon';
|
||||||
import { useSnackBar } from '@/ui/feedback/snack-bar/hooks/useSnackBar';
|
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||||
import { Button } from '@/ui/input/button/components/Button';
|
import { Button } from '@/ui/input/button/components/Button';
|
||||||
import { TextInput } from '@/ui/input/components/TextInput';
|
import { TextInput } from '@/ui/input/components/TextInput';
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ import { useUpdateOneObjectRecord } from '@/object-record/hooks/useUpdateOneObje
|
|||||||
import { ProfilePictureUploader } from '@/settings/profile/components/ProfilePictureUploader';
|
import { ProfilePictureUploader } from '@/settings/profile/components/ProfilePictureUploader';
|
||||||
import { PageHotkeyScope } from '@/types/PageHotkeyScope';
|
import { PageHotkeyScope } from '@/types/PageHotkeyScope';
|
||||||
import { H2Title } from '@/ui/display/typography/components/H2Title';
|
import { H2Title } from '@/ui/display/typography/components/H2Title';
|
||||||
import { useSnackBar } from '@/ui/feedback/snack-bar/hooks/useSnackBar';
|
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||||
import { MainButton } from '@/ui/input/button/components/MainButton';
|
import { MainButton } from '@/ui/input/button/components/MainButton';
|
||||||
import { TextInput } from '@/ui/input/components/TextInput';
|
import { TextInput } from '@/ui/input/components/TextInput';
|
||||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||||
|
@ -14,7 +14,7 @@ import { OnboardingStatus } from '@/auth/utils/getOnboardingStatus';
|
|||||||
import { WorkspaceLogoUploader } from '@/settings/workspace/components/WorkspaceLogoUploader';
|
import { WorkspaceLogoUploader } from '@/settings/workspace/components/WorkspaceLogoUploader';
|
||||||
import { PageHotkeyScope } from '@/types/PageHotkeyScope';
|
import { PageHotkeyScope } from '@/types/PageHotkeyScope';
|
||||||
import { H2Title } from '@/ui/display/typography/components/H2Title';
|
import { H2Title } from '@/ui/display/typography/components/H2Title';
|
||||||
import { useSnackBar } from '@/ui/feedback/snack-bar/hooks/useSnackBar';
|
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||||
import { MainButton } from '@/ui/input/button/components/MainButton';
|
import { MainButton } from '@/ui/input/button/components/MainButton';
|
||||||
import { TextInput } from '@/ui/input/components/TextInput';
|
import { TextInput } from '@/ui/input/components/TextInput';
|
||||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||||
|
Loading…
Reference in New Issue
Block a user