diff --git a/.changeset/whole-groups-happen.md b/.changeset/whole-groups-happen.md new file mode 100644 index 00000000000..4b9cc8c97ce --- /dev/null +++ b/.changeset/whole-groups-happen.md @@ -0,0 +1,12 @@ +--- +"saleor-dashboard": patch +--- + +Redesigned toast notifications for better user experience: + +- **Notifications now stack compactly** instead of flooding the screen +- **Refined visual design** that's less disruptive and better aligned with the dashboard aesthetic +- **Long messages expand on hover** with "Show more/less" toggle instead of being truncated +- **Error notifications persist** until manually dismissed + +**Next up:** Refining notification message copy for clarity and consistency across the dashboard. diff --git a/locale/defaultMessages.json b/locale/defaultMessages.json index bf709926e1e..a48d6c8c425 100644 --- a/locale/defaultMessages.json +++ b/locale/defaultMessages.json @@ -2159,10 +2159,6 @@ "Bl6896": { "string": "Refund amount" }, - "BnB/7Y": { - "context": "callout, title", - "string": "Info" - }, "Bphmwe": { "context": "header", "string": "Translation Collection \"{collectionName}\" - {languageCode}" @@ -5276,10 +5272,6 @@ "context": "filters error messages unknown error", "string": "Unknown error occurred" }, - "UUVUyy": { - "context": "callout, title", - "string": "Warning" - }, "UVDfTs": { "context": "discount type shipping", "string": "Shipping" @@ -9058,10 +9050,6 @@ "context": "search label", "string": "Search products" }, - "s8FlDW": { - "context": "hide error log label in notification", - "string": "Hide log" - }, "s9sOcC": { "context": "button", "string": "OK" @@ -9759,10 +9747,6 @@ "w7jT4W": { "string": "No channels selected" }, - "w9xgN9": { - "context": "see error log label in notification", - "string": "See error log" - }, "wAGThK": { "context": "dialog header", "string": "Delete structures" @@ -9826,6 +9810,9 @@ "wbsq7O": { "string": "Usage" }, + "we4Lby": { + "string": "Info" + }, "werrDz": { "context": "refunded event title", "string": "Products were refunded" diff --git a/package.json b/package.json index 43a86bd654e..a552bb88b2a 100644 --- a/package.json +++ b/package.json @@ -134,6 +134,7 @@ "react-sortable-hoc": "^1.11.0", "react-transition-group": "4.4.5", "slugify": "^1.6.6", + "sonner": "^2.0.7", "tslib": "^2.8.1", "url-join": "^4.0.1", "use-react-router": "^1.0.7", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f39f03402e9..97173b3649f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -246,6 +246,9 @@ importers: slugify: specifier: ^1.6.6 version: 1.6.6 + sonner: + specifier: ^2.0.7 + version: 2.0.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) tslib: specifier: ^2.8.1 version: 2.8.1 @@ -11791,6 +11794,15 @@ packages: integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==, } + sonner@2.0.7: + resolution: + { + integrity: sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==, + } + peerDependencies: + react: ^18.0.0 || ^19.0.0 || ^19.0.0-rc + react-dom: ^18.0.0 || ^19.0.0 || ^19.0.0-rc + sort-object-keys@1.1.3: resolution: { @@ -21659,6 +21671,11 @@ snapshots: dot-case: 3.0.4 tslib: 2.8.1 + sonner@2.0.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + sort-object-keys@1.1.3: {} sort-package-json@3.4.0: diff --git a/src/attributes/components/AttributeSwatchField/useFileProcessing.test.tsx b/src/attributes/components/AttributeSwatchField/useFileProcessing.test.tsx index 3b00cf49f15..f12814aca80 100644 --- a/src/attributes/components/AttributeSwatchField/useFileProcessing.test.tsx +++ b/src/attributes/components/AttributeSwatchField/useFileProcessing.test.tsx @@ -14,7 +14,9 @@ jest.mock("@dashboard/intl", () => ({ }, })); -jest.mock("@dashboard/hooks/useNotifier", () => () => jest.fn()); +jest.mock("@dashboard/hooks/useNotifier", () => ({ + useNotifier: () => jest.fn(), +})); describe("useFileProcessing", () => { const mockUploadFile = jest.fn(); diff --git a/src/attributes/components/AttributeSwatchField/useFileProcessing.ts b/src/attributes/components/AttributeSwatchField/useFileProcessing.ts index e993ff9f2ac..5974ecf0fb3 100644 --- a/src/attributes/components/AttributeSwatchField/useFileProcessing.ts +++ b/src/attributes/components/AttributeSwatchField/useFileProcessing.ts @@ -1,6 +1,6 @@ import { AttributeValueEditDialogFormData } from "@dashboard/attributes/utils/data"; import { useFileUploadMutation } from "@dashboard/graphql"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { errorMessages } from "@dashboard/intl"; import { useState } from "react"; import { useIntl } from "react-intl"; diff --git a/src/attributes/views/AttributeCreate/AttributeCreate.tsx b/src/attributes/views/AttributeCreate/AttributeCreate.tsx index 005ad9321e2..c478ad47c8e 100644 --- a/src/attributes/views/AttributeCreate/AttributeCreate.tsx +++ b/src/attributes/views/AttributeCreate/AttributeCreate.tsx @@ -9,7 +9,7 @@ import { import useListSettings from "@dashboard/hooks/useListSettings"; import useLocalPageInfo, { getMaxPage } from "@dashboard/hooks/useLocalPageInfo"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { getMutationErrors, getStringOrPlaceholder } from "@dashboard/misc"; import { ListViews, ReorderEvent } from "@dashboard/types"; import createDialogActionHandlers from "@dashboard/utils/handlers/dialogActionHandlers"; diff --git a/src/attributes/views/AttributeDetails/AttributeDetails.tsx b/src/attributes/views/AttributeDetails/AttributeDetails.tsx index d9de8cc3a8a..1fd33ccb987 100644 --- a/src/attributes/views/AttributeDetails/AttributeDetails.tsx +++ b/src/attributes/views/AttributeDetails/AttributeDetails.tsx @@ -13,7 +13,7 @@ import { import useListSettings from "@dashboard/hooks/useListSettings"; import useLocalPaginator, { useLocalPaginationState } from "@dashboard/hooks/useLocalPaginator"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { commonMessages } from "@dashboard/intl"; import { extractMutationErrors, getStringOrPlaceholder } from "@dashboard/misc"; import { ListViews, ReorderEvent } from "@dashboard/types"; diff --git a/src/attributes/views/AttributeList/AttributeList.tsx b/src/attributes/views/AttributeList/AttributeList.tsx index c25e7773a76..6b4b8ef65c9 100644 --- a/src/attributes/views/AttributeList/AttributeList.tsx +++ b/src/attributes/views/AttributeList/AttributeList.tsx @@ -11,7 +11,7 @@ import { useAttributeBulkDeleteMutation, useAttributeListQuery } from "@dashboar import { useFilterPresets } from "@dashboard/hooks/useFilterPresets"; import useListSettings from "@dashboard/hooks/useListSettings"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { usePaginationReset } from "@dashboard/hooks/usePaginationReset"; import usePaginator, { createPaginationState, diff --git a/src/auth/AuthProvider.test.tsx b/src/auth/AuthProvider.test.tsx index e57bbff22c3..e629cba14e9 100644 --- a/src/auth/AuthProvider.test.tsx +++ b/src/auth/AuthProvider.test.tsx @@ -1,6 +1,6 @@ import { useApolloClient } from "@apollo/client"; import { useUserDetailsQuery } from "@dashboard/graphql"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { useAuth, useAuthState } from "@saleor/sdk"; import { act, renderHook } from "@testing-library/react-hooks"; import { useIntl } from "react-intl"; @@ -71,8 +71,7 @@ jest.mock("@dashboard/graphql", () => ({ })), })); jest.mock("@dashboard/hooks/useNotifier", () => ({ - __esModule: true, - default: jest.fn(() => () => undefined), + useNotifier: jest.fn(() => () => undefined), })); jest.mock("@dashboard/hooks/useNavigator", () => ({ __esModule: true, diff --git a/src/auth/AuthProvider.tsx b/src/auth/AuthProvider.tsx index 399c9ef55d5..2cdd1185a83 100644 --- a/src/auth/AuthProvider.tsx +++ b/src/auth/AuthProvider.tsx @@ -1,5 +1,5 @@ import { useApolloClient } from "@apollo/client"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { PropsWithChildren } from "react"; import { useIntl } from "react-intl"; diff --git a/src/auth/hooks/useAuthProvider.ts b/src/auth/hooks/useAuthProvider.ts index 8b4b0d00da9..b1c3d1fa05e 100644 --- a/src/auth/hooks/useAuthProvider.ts +++ b/src/auth/hooks/useAuthProvider.ts @@ -1,5 +1,5 @@ import { ApolloClient, ApolloError } from "@apollo/client"; -import { IMessageContext } from "@dashboard/components/messages"; +import { INotificationCallback } from "@dashboard/components/notifications"; import { AccountErrorCode, useUserDetailsQuery } from "@dashboard/graphql"; import useLocalStorage from "@dashboard/hooks/useLocalStorage"; import useNavigator from "@dashboard/hooks/useNavigator"; @@ -29,7 +29,7 @@ import { useLastLoginMethod } from "./useLastLoginMethod"; interface UseAuthProviderOpts { intl: IntlShape; - notify: IMessageContext; + notify: INotificationCallback; apolloClient: ApolloClient; } type AuthErrorCodes = `${AccountErrorCode}`; diff --git a/src/auth/utils.ts b/src/auth/utils.ts index 61bf6cb9584..61fc3dd29bb 100644 --- a/src/auth/utils.ts +++ b/src/auth/utils.ts @@ -1,5 +1,5 @@ import { ApolloError, ServerError } from "@apollo/client/core"; -import { IMessageContext } from "@dashboard/components/messages"; +import { INotification, INotificationCallback } from "@dashboard/components/notifications"; import { commonMessages } from "@dashboard/intl"; import { getMutationErrors, parseLogMessage } from "@dashboard/misc"; import { getAppMountUriForRedirect } from "@dashboard/utils/urls"; @@ -41,7 +41,7 @@ export const showAllErrors = ({ notify, error, }: { - notify: IMessageContext; + notify: INotificationCallback; error: ApolloError; }) => { getAllErrorMessages(error).forEach(message => { @@ -60,7 +60,7 @@ export const handleNestedMutationErrors = ({ }: { data: any; intl: IntlShape; - notify: IMessageContext; + notify: (notification: INotification) => void; }) => { const mutationErrors = getMutationErrors({ data }); @@ -82,7 +82,7 @@ export const handleNestedMutationErrors = ({ export async function handleQueryAuthError( error: ApolloError, - notify: IMessageContext, + notify: INotificationCallback, logout: () => void, intl: IntlShape, ) { diff --git a/src/categories/views/CategoryCreate.tsx b/src/categories/views/CategoryCreate.tsx index ec7ddc266ea..2691d111e20 100644 --- a/src/categories/views/CategoryCreate.tsx +++ b/src/categories/views/CategoryCreate.tsx @@ -6,7 +6,7 @@ import { useUpdatePrivateMetadataMutation, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { getMutationErrors } from "@dashboard/misc"; import createMetadataCreateHandler from "@dashboard/utils/handlers/metadataCreateHandler"; import { getParsedDataForJsonStringField } from "@dashboard/utils/richText/misc"; diff --git a/src/categories/views/CategoryDetails.tsx b/src/categories/views/CategoryDetails.tsx index 4dd2671ebfd..b1752084611 100644 --- a/src/categories/views/CategoryDetails.tsx +++ b/src/categories/views/CategoryDetails.tsx @@ -19,7 +19,7 @@ import useLocalPaginator, { useSectionLocalPaginationState, } from "@dashboard/hooks/useLocalPaginator"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { PaginatorContext } from "@dashboard/hooks/usePaginator"; import { useRowSelection } from "@dashboard/hooks/useRowSelection"; import { commonMessages, errorMessages } from "@dashboard/intl"; diff --git a/src/channels/views/ChannelCreate/ChannelCreate.tsx b/src/channels/views/ChannelCreate/ChannelCreate.tsx index 0b6a5c543bf..708fbd46c02 100644 --- a/src/channels/views/ChannelCreate/ChannelCreate.tsx +++ b/src/channels/views/ChannelCreate/ChannelCreate.tsx @@ -12,7 +12,7 @@ import { import { ChannelCreateInput as ChannelCreateInputWithAllowLegacyGiftCardUse } from "@dashboard/graphql/staging"; import { getSearchFetchMoreProps } from "@dashboard/hooks/makeTopLevelSearch/utils"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import useShop from "@dashboard/hooks/useShop"; import { commonMessages } from "@dashboard/intl"; import getChannelsErrorMessage from "@dashboard/utils/errors/channels"; diff --git a/src/channels/views/ChannelDetails/ChannelDetails.tsx b/src/channels/views/ChannelDetails/ChannelDetails.tsx index 9c16d01edb3..ddabb760d84 100644 --- a/src/channels/views/ChannelDetails/ChannelDetails.tsx +++ b/src/channels/views/ChannelDetails/ChannelDetails.tsx @@ -24,7 +24,7 @@ import { } from "@dashboard/graphql/staging"; import { getSearchFetchMoreProps } from "@dashboard/hooks/makeTopLevelSearch/utils"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { getDefaultNotifierSuccessErrorData } from "@dashboard/hooks/useNotifier/utils"; import useShop from "@dashboard/hooks/useShop"; import { extractMutationErrors } from "@dashboard/misc"; diff --git a/src/channels/views/ChannelDetails/useChannelWarehouseReorder.ts b/src/channels/views/ChannelDetails/useChannelWarehouseReorder.ts index c27dcd4a959..34e2fdbe177 100644 --- a/src/channels/views/ChannelDetails/useChannelWarehouseReorder.ts +++ b/src/channels/views/ChannelDetails/useChannelWarehouseReorder.ts @@ -1,7 +1,7 @@ import { ChannelWarehouse } from "@dashboard/channels/pages/ChannelDetailsPage/types"; import { calculateItemsOrderMoves } from "@dashboard/channels/views/ChannelDetails/handlers"; import { useChannelReorderWarehousesMutation, WarehouseFragment } from "@dashboard/graphql"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import getChannelsErrorMessage from "@dashboard/utils/errors/channels"; import { useIntl } from "react-intl"; diff --git a/src/channels/views/ChannelsList/ChannelsList.tsx b/src/channels/views/ChannelsList/ChannelsList.tsx index 430741af570..c6dcbf59ea1 100644 --- a/src/channels/views/ChannelsList/ChannelsList.tsx +++ b/src/channels/views/ChannelsList/ChannelsList.tsx @@ -7,7 +7,7 @@ import { useChannelsQuery, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import getChannelsErrorMessage from "@dashboard/utils/errors/channels"; import createDialogActionHandlers from "@dashboard/utils/handlers/dialogActionHandlers"; import { useIntl } from "react-intl"; diff --git a/src/collections/components/CollectionProducts/CollectionProducts.tsx b/src/collections/components/CollectionProducts/CollectionProducts.tsx index ecc49bc0d3e..c3a7c50ecf1 100644 --- a/src/collections/components/CollectionProducts/CollectionProducts.tsx +++ b/src/collections/components/CollectionProducts/CollectionProducts.tsx @@ -23,7 +23,7 @@ import useBulkActions from "@dashboard/hooks/useBulkActions"; import useListSettings from "@dashboard/hooks/useListSettings"; import useLocalPaginator, { useLocalPaginationState } from "@dashboard/hooks/useLocalPaginator"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { PaginatorContext } from "@dashboard/hooks/usePaginator"; import useProductSearch from "@dashboard/searches/useProductSearch"; import { Container } from "@dashboard/types"; diff --git a/src/collections/components/CollectionProducts/useProductReorder.test.ts b/src/collections/components/CollectionProducts/useProductReorder.test.ts index 5b207a606e1..5d77a9730b8 100644 --- a/src/collections/components/CollectionProducts/useProductReorder.test.ts +++ b/src/collections/components/CollectionProducts/useProductReorder.test.ts @@ -1,6 +1,6 @@ import { useReorderProductsInCollectionMutation } from "@dashboard/graphql"; import { useLocalPaginationState } from "@dashboard/hooks/useLocalPaginator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { act, renderHook } from "@testing-library/react-hooks"; import { Product } from "./types"; @@ -23,7 +23,9 @@ jest.mock("./useCollectionId", () => ({ useCollectionId: jest.fn(() => "collection-id-1"), })); -jest.mock("@dashboard/hooks/useNotifier", () => jest.fn()); +jest.mock("@dashboard/hooks/useNotifier", () => ({ + useNotifier: jest.fn(), +})); describe("CollectionProducts/useProductReorder", () => { const mockReorder = jest.fn(); diff --git a/src/collections/components/CollectionProducts/useProductReorder.ts b/src/collections/components/CollectionProducts/useProductReorder.ts index 133c2f80c5d..2d82a77089f 100644 --- a/src/collections/components/CollectionProducts/useProductReorder.ts +++ b/src/collections/components/CollectionProducts/useProductReorder.ts @@ -1,6 +1,6 @@ import { useReorderProductsInCollectionMutation } from "@dashboard/graphql"; import { PaginationState } from "@dashboard/hooks/useLocalPaginator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { useIntl } from "react-intl"; import { Product } from "./types"; diff --git a/src/collections/views/CollectionCreate.tsx b/src/collections/views/CollectionCreate.tsx index 155a30357ae..e6a7eaa50c4 100644 --- a/src/collections/views/CollectionCreate.tsx +++ b/src/collections/views/CollectionCreate.tsx @@ -13,7 +13,7 @@ import { } from "@dashboard/graphql"; import useChannels from "@dashboard/hooks/useChannels"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { commonMessages } from "@dashboard/intl"; import { getMutationErrors } from "@dashboard/misc"; import createDialogActionHandlers from "@dashboard/utils/handlers/dialogActionHandlers"; diff --git a/src/collections/views/CollectionDetails.tsx b/src/collections/views/CollectionDetails.tsx index 226008870c1..d296c5013e0 100644 --- a/src/collections/views/CollectionDetails.tsx +++ b/src/collections/views/CollectionDetails.tsx @@ -18,7 +18,7 @@ import { import useChannels from "@dashboard/hooks/useChannels"; import useLocalStorage from "@dashboard/hooks/useLocalStorage"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { commonMessages, errorMessages } from "@dashboard/intl"; import { arrayDiff } from "@dashboard/utils/arrays"; import createDialogActionHandlers from "@dashboard/utils/handlers/dialogActionHandlers"; diff --git a/src/collections/views/CollectionList/CollectionList.tsx b/src/collections/views/CollectionList/CollectionList.tsx index 16bc0df4945..aafff5c2d8d 100644 --- a/src/collections/views/CollectionList/CollectionList.tsx +++ b/src/collections/views/CollectionList/CollectionList.tsx @@ -9,7 +9,7 @@ import { useCollectionBulkDeleteMutation, useCollectionListQuery } from "@dashbo import { useFilterPresets } from "@dashboard/hooks/useFilterPresets"; import useListSettings from "@dashboard/hooks/useListSettings"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { usePaginationReset } from "@dashboard/hooks/usePaginationReset"; import usePaginator, { createPaginationState, diff --git a/src/components/Callout/messages.ts b/src/components/Callout/messages.ts index 029f5fce83d..33c76528603 100644 --- a/src/components/Callout/messages.ts +++ b/src/components/Callout/messages.ts @@ -1,16 +1,7 @@ -import { defineMessages } from "react-intl"; +import { commonMessages } from "@dashboard/intl"; // Re-export common messages for backward compatibility -// TODO: Remove and use `commonMessages` from @dashboard/intl -export const calloutTitleMessages = defineMessages({ - info: { - defaultMessage: "Info", - description: "callout, title", - id: "BnB/7Y", - }, - warning: { - defaultMessage: "Warning", - description: "callout, title", - id: "UUVUyy", - }, -}); +export const calloutTitleMessages = { + info: commonMessages.info, + warning: commonMessages.warning, +}; diff --git a/src/components/ConditionalFilter/API/initialState/product/useProductInitialAPIState.tsx b/src/components/ConditionalFilter/API/initialState/product/useProductInitialAPIState.tsx index 657078fb7d8..99105441d69 100644 --- a/src/components/ConditionalFilter/API/initialState/product/useProductInitialAPIState.tsx +++ b/src/components/ConditionalFilter/API/initialState/product/useProductInitialAPIState.tsx @@ -26,7 +26,7 @@ import { _SearchProductVariantOperandsQueryVariables, AttributeEntityTypeEnum, } from "@dashboard/graphql"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { useCallback, useState } from "react"; import { useIntl } from "react-intl"; diff --git a/src/components/Form/useExitFormDialog.test.tsx b/src/components/Form/useExitFormDialog.test.tsx index 95680950f0b..72f7709255a 100644 --- a/src/components/Form/useExitFormDialog.test.tsx +++ b/src/components/Form/useExitFormDialog.test.tsx @@ -8,7 +8,9 @@ import { ExitFormDialogContext } from "./ExitFormDialogProvider"; import { useExitFormDialog } from "./useExitFormDialog"; import { useExitFormDialogProvider } from "./useExitFormDialogProvider"; -jest.mock("../../hooks/useNotifier", () => undefined); +jest.mock("../../hooks/useNotifier", () => ({ + useNotifier: () => jest.fn(), +})); const MockExitFormDialogProvider = ({ children }) => { const { providerData } = useExitFormDialogProvider(); diff --git a/src/components/MetadataDialog/useHandleMetadataSubmit.test.ts b/src/components/MetadataDialog/useHandleMetadataSubmit.test.ts index 14649681497..4be1e84b431 100644 --- a/src/components/MetadataDialog/useHandleMetadataSubmit.test.ts +++ b/src/components/MetadataDialog/useHandleMetadataSubmit.test.ts @@ -13,7 +13,9 @@ import { useHandleMetadataSubmit } from "./useHandleMetadataSubmit"; // Mocks const mockNotify = jest.fn(); -jest.mock("@dashboard/hooks/useNotifier", () => () => mockNotify); +jest.mock("@dashboard/hooks/useNotifier", () => ({ + useNotifier: () => mockNotify, +})); jest.mock("@apollo/client", () => ({ ...(jest.requireActual("@apollo/client") as {}), diff --git a/src/components/MetadataDialog/useHandleMetadataSubmit.ts b/src/components/MetadataDialog/useHandleMetadataSubmit.ts index 64741e66870..932ed738f5e 100644 --- a/src/components/MetadataDialog/useHandleMetadataSubmit.ts +++ b/src/components/MetadataDialog/useHandleMetadataSubmit.ts @@ -1,7 +1,7 @@ import { DocumentNode, useApolloClient } from "@apollo/client"; import { MetadataFormData } from "@dashboard/components/Metadata"; import { useUpdateMetadataMutation, useUpdatePrivateMetadataMutation } from "@dashboard/graphql"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { commonMessages } from "@dashboard/intl"; import createMetadataUpdateHandler from "@dashboard/utils/handlers/metadataUpdateHandler"; import { useMemo, useRef } from "react"; diff --git a/src/components/messages/Container.tsx b/src/components/messages/Container.tsx deleted file mode 100644 index 41803c7259e..00000000000 --- a/src/components/messages/Container.tsx +++ /dev/null @@ -1,10 +0,0 @@ -// @ts-strict-ignore -import { useStyles } from "./styles"; - -const Container = ({ children }) => { - const classes = useStyles({}); - - return !!children.length &&
{children}
; -}; - -export default Container; diff --git a/src/components/messages/MessageDisplay.tsx b/src/components/messages/MessageDisplay.tsx deleted file mode 100644 index ba7969464a4..00000000000 --- a/src/components/messages/MessageDisplay.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import { commonMessages } from "@dashboard/intl"; -import { Portal } from "@radix-ui/react-portal"; -import { ApiMessageData, Notification } from "@saleor/macaw-ui"; -import { useIntl } from "react-intl"; -import { TransitionGroup } from "react-transition-group"; - -import Container from "./Container"; -import { messages as notificationMessages } from "./messages"; -import { useStyles } from "./styles"; -import Transition from "./Transition"; -import { MessageComponentValues } from "./useMessageState"; - -export const MessageDisplay = ({ - notifications, - pauseTimer, - resumeTimer, -}: MessageComponentValues) => { - const classes = useStyles(); - const intl = useIntl(); - - return ( - - - {notifications?.map(notification => ( - - pauseTimer(notification), - onMouseLeave: () => resumeTimer(notification), - } - : {})} - onClose={notification.close} - title={ - (notification.message.apiMessage && !notification.message.title - ? intl.formatMessage(commonMessages.defaultErrorTitle) - : notification.message.title) as string - } - type={notification.message.status || "info"} - content={notification.message.text} - apiMessage={ - (notification.message.apiMessage && { - apiMessageContent: ( -
-                      {notification.message.apiMessage}
-                    
- ), - hideApiLabel: intl.formatMessage(notificationMessages.hideError), - showApiLabel: intl.formatMessage(notificationMessages.seeError), - }) as ApiMessageData - } - {...(notification.message.actionBtn - ? { - action: { - label: notification.message.actionBtn.label, - onClick: notification.message.actionBtn.action, - }, - } - : {})} - className={classes.notification} - /> -
- ))} -
-
- ); -}; diff --git a/src/components/messages/MessageManagerProvider.test.tsx b/src/components/messages/MessageManagerProvider.test.tsx deleted file mode 100644 index fbaad5b10d9..00000000000 --- a/src/components/messages/MessageManagerProvider.test.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { renderHook } from "@testing-library/react-hooks"; -import { PropsWithChildren, useContext } from "react"; - -import { MessageContext } from "."; -import MessageManagerProvider from "./MessageManagerProvider"; - -// Mock MessageDisplay component since we're not testing its functionality -jest.mock("./MessageDisplay", () => ({ - MessageDisplay: () =>
Message Display
, -})); - -describe("MessageManagerProvider", () => { - test("should provide MessageContext to children", () => { - // Arrange - const { result } = renderHook(() => useContext(MessageContext), { - wrapper: ({ children }: PropsWithChildren) => ( - {children} - ), - }); - - // Assert: context exists - expect(result.current).toBeTruthy(); - expect(typeof result.current?.show).toBe("function"); - expect(typeof result.current?.remove).toBe("function"); - expect(typeof result.current?.clearErrorNotifications).toBe("function"); - }); -}); diff --git a/src/components/messages/MessageManagerProvider.tsx b/src/components/messages/MessageManagerProvider.tsx deleted file mode 100644 index ee5754ebda9..00000000000 --- a/src/components/messages/MessageManagerProvider.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { PropsWithChildren } from "react"; - -import { MessageContext } from "."; -import { MessageDisplay } from "./MessageDisplay"; -import { useMessageState } from "./useMessageState"; - -const MessageManagerProvider = ({ children }: PropsWithChildren) => { - const { context, componentState } = useMessageState(); - - return ( - <> - {/* This component is used in main `App` component, to pass context */} - {children} - - - ); -}; - -export default MessageManagerProvider; diff --git a/src/components/messages/Transition.tsx b/src/components/messages/Transition.tsx deleted file mode 100644 index afa4cd0aa9f..00000000000 --- a/src/components/messages/Transition.tsx +++ /dev/null @@ -1,28 +0,0 @@ -// @ts-strict-ignore -import { Transition as MessageManagerTransition } from "react-transition-group"; - -const duration = 250; -const defaultStyle = { - opacity: 0, - transition: `opacity ${duration}ms ease`, -}; -const transitionStyles = { - entered: { opacity: 1 }, - entering: { opacity: 0 }, -}; -const Transition = ({ children, ...props }) => ( - - {state => ( -
- {children} -
- )} -
-); - -export default Transition; diff --git a/src/components/messages/index.ts b/src/components/messages/index.ts deleted file mode 100644 index a0e50a179aa..00000000000 --- a/src/components/messages/index.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { createContext } from "react"; - -type Status = "success" | "error" | "info" | "warning"; -export interface IMessage { - actionBtn?: { - label: string; - action: () => void; - }; - autohide?: number; - expandText?: string; - title?: string; - text?: React.ReactNode; - onUndo?: () => void; - status?: Status; - apiMessage?: string; -} - -export interface INotification { - id: number; - message: IMessage; - timeout: number; - close: () => void; -} - -export interface ITimer { - id: number; - notification: INotification; - remaining: number; - start: number; - timeoutId: number; -} - -export interface INotificationContext { - show: (message: IMessage, timeout?: number | null) => void; - remove: (notificationId: number) => void; - clearErrorNotifications: () => void; -} - -export type IMessageContext = (message: IMessage) => void; -export const MessageContext = createContext(null); - -export * from "./MessageManagerProvider"; -export { default } from "./MessageManagerProvider"; diff --git a/src/components/messages/messages.ts b/src/components/messages/messages.ts deleted file mode 100644 index 4928db95848..00000000000 --- a/src/components/messages/messages.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { defineMessages } from "react-intl"; - -export const messages = defineMessages({ - seeError: { - id: "w9xgN9", - defaultMessage: "See error log", - description: "see error log label in notification", - }, - hideError: { - id: "s8FlDW", - defaultMessage: "Hide log", - description: "hide error log label in notification", - }, -}); diff --git a/src/components/messages/styles.ts b/src/components/messages/styles.ts deleted file mode 100644 index 07658bda2b3..00000000000 --- a/src/components/messages/styles.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { makeStyles } from "@saleor/macaw-ui"; - -export const useStyles = makeStyles( - theme => ({ - container: { - display: "grid", - justifyContent: "end", - right: 0, - pointerEvents: "auto", - position: "fixed", - top: 0, - width: "auto", - maxHeight: "100vh", - overflowY: "auto", - zIndex: 10000, - }, - notification: { - // Parent container has disabled pointer events so we need to turn them on - // for action and timer pausing to work - pointerEvents: "all", - margin: theme.spacing(2), - }, - }), - { name: "MessageManager" }, -); diff --git a/src/components/messages/useMessageState.test.tsx b/src/components/messages/useMessageState.test.tsx deleted file mode 100644 index d35e42aca8f..00000000000 --- a/src/components/messages/useMessageState.test.tsx +++ /dev/null @@ -1,121 +0,0 @@ -import { DEFAULT_NOTIFICATION_SHOW_TIME } from "@dashboard/config"; -import { act, renderHook } from "@testing-library/react-hooks"; - -import { useMessageState } from "./useMessageState"; - -describe("useMessageState", () => { - beforeEach(() => { - jest.useFakeTimers(); - }); - - afterEach(() => { - jest.useRealTimers(); - }); - - test("should initialize with empty notifications", () => { - // Arrange - const { result } = renderHook(() => useMessageState()); - - // Assert - expect(result.current.componentState.notifications).toEqual([]); - }); - - test("should add a notification when show is called", () => { - // Arrange - const { result } = renderHook(() => useMessageState()); - - // Act - act(() => { - result.current.context.show({ text: "Test notification" }); - }); - - // Assert - expect(result.current.componentState.notifications).toHaveLength(1); - expect(result.current.componentState.notifications[0].message.text).toBe("Test notification"); - }); - - test("should remove a notification when remove is called", () => { - // Arrange - const { result } = renderHook(() => useMessageState()); - - // Act - act(() => { - result.current.context.show({ text: "Test notification" }); - }); - - act(() => { - result.current.context.remove(result.current.componentState.notifications[0].id); - }); - - // Assert - expect(result.current.componentState.notifications).toHaveLength(0); - }); - - test("should auto-remove notification after timeout", () => { - // Arrange - const { result } = renderHook(() => useMessageState()); - - // Act - act(() => { - result.current.context.show({ text: "Test notification" }, 1000); - }); - - // Assert - expect(result.current.componentState.notifications).toHaveLength(1); - - // Act - act(() => { - jest.advanceTimersByTime(1000); - }); - - // Assert - expect(result.current.componentState.notifications).toHaveLength(0); - }); - - test("should pause and resume timer correctly", () => { - // Arrange - const { result } = renderHook(() => useMessageState()); - - // Act - act(() => { - result.current.context.show({ text: "Test notification" }, 2000); - }); - - act(() => { - // Advance time partially - jest.advanceTimersByTime(10); - }); - - // Assert: Notification should still be there - expect(result.current.componentState.notifications).toHaveLength(1); - - // Act - act(() => { - // Pause the timer - result.current.componentState.pauseTimer(result.current.componentState.notifications[0]); - }); - - act(() => { - // Advance time beyond original timeout - jest.advanceTimersByTime(DEFAULT_NOTIFICATION_SHOW_TIME); - }); - - // Assert: Notification should still be there because timer was paused - expect(result.current.componentState.notifications).toHaveLength(1); - - // Act - act(() => { - // Resume the timer - result.current.componentState.resumeTimer(result.current.componentState.notifications[0]); - }); - - // Act - act(() => { - // Advance time to complete the remaining time - jest.advanceTimersByTime(DEFAULT_NOTIFICATION_SHOW_TIME); - }); - - // Assert: Notification should be removed now - expect(result.current.componentState.notifications).toHaveLength(0); - }); -}); diff --git a/src/components/messages/useMessageState.tsx b/src/components/messages/useMessageState.tsx deleted file mode 100644 index d7892887636..00000000000 --- a/src/components/messages/useMessageState.tsx +++ /dev/null @@ -1,108 +0,0 @@ -import { DEFAULT_NOTIFICATION_SHOW_TIME } from "@dashboard/config"; -import { useCallback, useEffect, useRef, useState } from "react"; - -import { INotification, INotificationContext, ITimer } from "."; - -export type MessageComponentValues = ReturnType["componentState"]; - -export const useMessageState = () => { - const timer = useRef(0); - const timersArr = useRef([]); - const [notifications, setNotifications] = useState([]); - - useEffect(() => { - const timersArrRef = timersArr.current; - - return () => { - timersArrRef.forEach(timer => clearTimeout(timer.timeoutId)); - }; - }, []); - - const timerCallback = (notification: INotification) => { - remove(notification.id); - timersArr.current = timersArr.current.filter(timer => timer.id !== notification.id); - }; - const remove = useCallback((notificationId: number) => { - setNotifications(currentNotifications => - currentNotifications.filter(n => n.id !== notificationId), - ); - }, []); - const clearErrorNotifications = useCallback(() => { - setNotifications(notifications => - notifications.filter(notification => notification.message.status !== "error"), - ); - }, []); - - const show = useCallback((message = {}, timeout = DEFAULT_NOTIFICATION_SHOW_TIME) => { - const id = timer.current; - - timer.current += 1; - - const notification = { - close: () => remove(id), - id, - message, - timeout, - }; - - if (timeout !== null) { - const timeoutId = window.setTimeout(() => { - timerCallback(notification); - }, timeout); - - timersArr.current.push({ - id: notification.id, - notification, - remaining: timeout, - start: new Date().getTime(), - timeoutId, - }); - } - - setNotifications(state => [notification, ...state]); - - return notification; - }, []); - - const getCurrentTimer = (notification: INotification) => { - const currentTimerIndex = timersArr.current.findIndex(timer => timer.id === notification.id); - - return timersArr.current[currentTimerIndex]; - }; - const pauseTimer = (notification: INotification) => { - const currentTimer = getCurrentTimer(notification); - - if (currentTimer) { - currentTimer.remaining = currentTimer.remaining - (new Date().getTime() - currentTimer.start); - window.clearTimeout(currentTimer.timeoutId); - } - }; - const resumeTimer = (notification: INotification) => { - const currentTimer = getCurrentTimer(notification); - - if (currentTimer) { - currentTimer.start = new Date().getTime(); - currentTimer.timeoutId = window.setTimeout( - () => timerCallback(notification), - currentTimer.remaining, - ); - } - }; - - const context = { - remove, - show, - clearErrorNotifications, - } as INotificationContext; - - const componentState = { - pauseTimer, - resumeTimer, - notifications, - }; - - return { - context, - componentState, - } as const; -}; diff --git a/src/components/notifications/NotificationProvider.test.tsx b/src/components/notifications/NotificationProvider.test.tsx new file mode 100644 index 00000000000..6837d16fd4f --- /dev/null +++ b/src/components/notifications/NotificationProvider.test.tsx @@ -0,0 +1,33 @@ +import { ThemeProvider } from "@saleor/macaw-ui-next"; +import { renderHook } from "@testing-library/react-hooks"; +import { PropsWithChildren, useContext } from "react"; + +import { NotificationContext } from "."; +import NotificationProvider from "./NotificationProvider"; + +// Mock sonner +jest.mock("sonner", () => ({ + toast: { + custom: jest.fn(), + dismiss: jest.fn(), + }, + Toaster: () => null, +})); + +describe("NotificationProvider", () => { + const wrapper = ({ children }: PropsWithChildren) => ( + + {children} + + ); + + test("should provide NotificationContext to children", () => { + // Arrange & Act + const { result } = renderHook(() => useContext(NotificationContext), { wrapper }); + + // Assert + expect(result.current).toBeTruthy(); + expect(typeof result.current?.remove).toBe("function"); + expect(typeof result.current?.clearErrorNotifications).toBe("function"); + }); +}); diff --git a/src/components/notifications/NotificationProvider.tsx b/src/components/notifications/NotificationProvider.tsx new file mode 100644 index 00000000000..424c105246d --- /dev/null +++ b/src/components/notifications/NotificationProvider.tsx @@ -0,0 +1,27 @@ +import { PropsWithChildren, useMemo } from "react"; +import { toast, Toaster } from "sonner"; + +import { INotificationContext, NotificationContext } from "."; + +const NotificationProvider = ({ children }: PropsWithChildren) => { + const context = useMemo( + () => ({ + remove: (id: number) => { + toast.dismiss(id); + }, + clearErrorNotifications: () => { + toast.dismiss(); + }, + }), + [], + ); + + return ( + + {children} + + + ); +}; + +export default NotificationProvider; diff --git a/src/components/notifications/Toast.test.tsx b/src/components/notifications/Toast.test.tsx new file mode 100644 index 00000000000..b4f5b53325a --- /dev/null +++ b/src/components/notifications/Toast.test.tsx @@ -0,0 +1,226 @@ +import { ThemeProvider } from "@saleor/macaw-ui-next"; +import { fireEvent, render, screen, waitFor } from "@testing-library/react"; +import { toast } from "sonner"; + +import { Toast, ToastProps } from "./Toast"; + +jest.mock("sonner", () => ({ + toast: { + dismiss: jest.fn(), + }, +})); + +const mockToastDismiss = toast.dismiss as jest.Mock; + +const defaultProps: ToastProps = { + id: "test-toast-1", + type: "info", + title: "Test Title", +}; + +const renderToast = (props: Partial = {}) => + render( + + + , + ); + +describe("Toast", () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe("rendering", () => { + it("renders toast with title", () => { + // Arrange & Act + renderToast({ title: "Success Message" }); + + // Assert + expect(screen.getByText("Success Message")).toBeInTheDocument(); + }); + + it("renders toast with description", () => { + // Arrange & Act + renderToast({ + title: "Title", + description: "This is a detailed description", + }); + + // Assert + expect(screen.getByText("This is a detailed description")).toBeInTheDocument(); + }); + + it("renders without description when not provided", () => { + // Arrange & Act + renderToast({ title: "Title Only" }); + + // Assert + expect(screen.getByText("Title Only")).toBeInTheDocument(); + expect(screen.queryByText("description")).not.toBeInTheDocument(); + }); + + it("renders action button when action is provided", () => { + // Arrange & Act + renderToast({ + action: { + label: "Undo", + onClick: jest.fn(), + }, + }); + + // Assert + expect(screen.getByRole("button", { name: "Undo" })).toBeInTheDocument(); + }); + + it("does not render action button when action is not provided", () => { + // Arrange & Act + renderToast(); + + // Assert + expect(screen.queryByRole("button", { name: "Undo" })).not.toBeInTheDocument(); + }); + }); + + describe("toast types", () => { + it.each([ + ["success", "Success"], + ["error", "Error"], + ["warning", "Warning"], + ["info", "Info"], + ] as const)("renders %s toast with title", (type, title) => { + // Arrange & Act + renderToast({ type, title }); + + // Assert + expect(screen.getByText(title)).toBeInTheDocument(); + }); + }); + + describe("close functionality", () => { + it("calls toast.dismiss when close button is clicked", () => { + // Arrange + renderToast({ id: "dismiss-test-id" }); + + // Act + const closeButtons = screen.getAllByRole("button"); + const closeButton = closeButtons.find(btn => btn.querySelector("svg")); + + fireEvent.click(closeButton!); + + // Assert + expect(mockToastDismiss).toHaveBeenCalledWith("dismiss-test-id"); + }); + }); + + describe("action button", () => { + it("calls action onClick when action button is clicked", () => { + // Arrange + const onClickMock = jest.fn(); + + renderToast({ + action: { + label: "Retry", + onClick: onClickMock, + }, + }); + + // Act + const actionButton = screen.getByRole("button", { name: "Retry" }); + + fireEvent.click(actionButton); + + // Assert + expect(onClickMock).toHaveBeenCalledTimes(1); + }); + + it("dismisses toast after action button is clicked", () => { + // Arrange + const onClickMock = jest.fn(); + + renderToast({ + id: "action-dismiss-test", + action: { + label: "Retry", + onClick: onClickMock, + }, + }); + + // Act + const actionButton = screen.getByRole("button", { name: "Retry" }); + + fireEvent.click(actionButton); + + // Assert + expect(mockToastDismiss).toHaveBeenCalledWith("action-dismiss-test"); + }); + }); + + describe("description truncation", () => { + it("renders long description", () => { + // Arrange + const longDescription = + "This is a very long description that might get truncated when displayed in the toast notification. It contains multiple sentences to ensure it exceeds the maximum allowed lines for display."; + + // Act + renderToast({ description: longDescription }); + + // Assert + expect(screen.getByText(longDescription)).toBeInTheDocument(); + }); + + it("renders description container with overflow styles", () => { + // Arrange + const longDescription = "This is a very long description that spans multiple lines. ".repeat( + 10, + ); + + // Act + renderToast({ description: longDescription.trim() }); + + // Assert - verify the container has the truncation styles applied + const descriptionElement = screen.getByText(longDescription.trim()); + + expect(descriptionElement).toBeInTheDocument(); + expect(descriptionElement).toHaveStyle({ overflow: "hidden" }); + }); + + it("responds to mouse enter events on description container", async () => { + // Arrange + const description = "A description that can be hovered"; + + renderToast({ description }); + + // Act + const descriptionElement = screen.getByText(description); + const descriptionContainer = descriptionElement.closest('[class*="_18fs8ps"]'); + + if (descriptionContainer) { + fireEvent.mouseEnter(descriptionContainer); + fireEvent.mouseLeave(descriptionContainer); + } + + // Assert - the component handles mouse events without errors + await waitFor(() => { + expect(descriptionElement).toBeInTheDocument(); + }); + }); + }); + + describe("ReactNode description", () => { + it("renders JSX elements as description", () => { + // Arrange + const jsxDescription = ( + + Bold and italic text + + ); + + // Act + renderToast({ description: jsxDescription }); + + // Assert + expect(screen.getByText("Bold")).toBeInTheDocument(); + expect(screen.getByText("italic")).toBeInTheDocument(); + }); + }); +}); diff --git a/src/components/notifications/Toast.tsx b/src/components/notifications/Toast.tsx new file mode 100644 index 00000000000..449af681b83 --- /dev/null +++ b/src/components/notifications/Toast.tsx @@ -0,0 +1,253 @@ +import { Box, Button, Text, useTheme } from "@saleor/macaw-ui-next"; +import { AlertTriangle, CheckCircle2, Info, LucideIcon, X, XCircle } from "lucide-react"; +import { ReactNode, useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { toast } from "sonner"; + +type ToastType = "success" | "error" | "warning" | "info"; + +interface ToastStyleConfig { + iconColor: "success1" | "critical1" | "warning1" | "default1"; + Icon: LucideIcon; +} + +const TOAST_STYLES: Record = { + success: { iconColor: "success1", Icon: CheckCircle2 }, + error: { iconColor: "critical1", Icon: XCircle }, + warning: { iconColor: "warning1", Icon: AlertTriangle }, + info: { iconColor: "default1", Icon: Info }, +}; + +const MAX_LINES = 2; +const COLLAPSED_MAX_HEIGHT = "3.2em"; +const EXPANDED_MAX_HEIGHT = "500px"; +const ANIMATION_TIMING = "0.15s cubic-bezier(0.4, 0, 0.2, 1)"; + +export interface ToastProps { + id: string | number; + type: ToastType; + title: string; + description?: ReactNode; + action?: { + label: string; + onClick: () => void; + }; +} + +export const Toast = ({ id, type, title, description, action }: ToastProps) => { + const { theme, themeValues } = useTheme(); + const { iconColor, Icon } = TOAST_STYLES[type]; + + const [isExpanded, setIsExpanded] = useState(false); + const [isTruncated, setIsTruncated] = useState(false); + const [isHovering, setIsHovering] = useState(false); + const [isToggleHovering, setIsToggleHovering] = useState(false); + + const containerRef = useRef(null); + const textRef = useRef(null); + + const isDark = theme === "defaultDark"; + + const backgroundColor = useMemo(() => { + if (type === "success") { + return isDark ? "oklch(25% 0.04 145)" : "oklch(97% 0.04 145)"; + } + + return themeValues?.colors.background.default1; + }, [type, isDark, themeValues]); + + const handleDismiss = useCallback(() => { + toast.dismiss(id); + }, [id]); + + const handleExpand = useCallback(() => { + if (isTruncated && !isExpanded) { + setIsExpanded(true); + } + }, [isTruncated, isExpanded]); + + const handleToggleExpand = useCallback((e: React.MouseEvent) => { + e.stopPropagation(); + setIsExpanded(prev => !prev); + }, []); + + const handleActionClick = useCallback(() => { + action?.onClick(); + handleDismiss(); + }, [action, handleDismiss]); + + const handleMouseEnter = useCallback(() => setIsHovering(true), []); + const handleMouseLeave = useCallback(() => setIsHovering(false), []); + const handleToggleMouseEnter = useCallback(() => setIsToggleHovering(true), []); + const handleToggleMouseLeave = useCallback(() => setIsToggleHovering(false), []); + + // Check if description text is truncated + useEffect(() => { + const textEl = textRef.current; + + if (!textEl) return; + + requestAnimationFrame(() => { + const isOverflowing = textEl.scrollHeight > textEl.clientHeight + 1; + + if (isOverflowing) { + setIsTruncated(true); + } + }); + }, [description]); + + // Auto-collapse text when Sonner stack collapses (peek mode) + useEffect(() => { + const toastWrapper = containerRef.current?.closest("[data-sonner-toast]"); + + if (!toastWrapper) return; + + const observer = new MutationObserver(mutations => { + for (const mutation of mutations) { + if (mutation.attributeName === "data-expanded") { + const isStackExpanded = toastWrapper.getAttribute("data-expanded") === "true"; + + if (!isStackExpanded) { + setIsExpanded(false); + } + } + } + }); + + observer.observe(toastWrapper, { attributes: true }); + + return () => observer.disconnect(); + }, []); + + const showToggle = (isTruncated && isHovering) || isExpanded; + + return ( + + {/* Icon */} + + + + + {/* Content */} + + + {title} + + + {description && ( + + } + size={2} + color="default2" + style={{ + transition: `opacity ${ANIMATION_TIMING}`, + opacity: isTruncated && !isExpanded && isHovering ? 0.7 : 1, + ...(!isExpanded && { + display: "-webkit-box", + WebkitLineClamp: MAX_LINES, + WebkitBoxOrient: "vertical" as const, + overflow: "hidden", + }), + }} + > + {description} + + + {isTruncated && !isExpanded && ( + + )} + + {showToggle && ( + + + {isExpanded ? "Show less" : "Show more"} + + + )} + + )} + + {action && ( + + + + )} + + + {/* Close button */} + + + + + ); +}; diff --git a/src/components/notifications/index.ts b/src/components/notifications/index.ts new file mode 100644 index 00000000000..d0454c821a7 --- /dev/null +++ b/src/components/notifications/index.ts @@ -0,0 +1,28 @@ +import { createContext } from "react"; + +type Status = "success" | "error" | "info" | "warning"; + +export interface INotification { + actionBtn?: { + label: string; + action: () => void; + }; + autohide?: number; + title?: string; + text?: React.ReactNode; + status?: Status; + apiMessage?: string; +} + +export interface INotificationContext { + remove: (notificationId: number) => void; + clearErrorNotifications: () => void; +} + +export type INotificationCallback = (notification: INotification) => void; +export const NotificationContext = createContext(null); + +export * from "./NotificationProvider"; +export { default } from "./NotificationProvider"; +export type { ToastProps } from "./Toast"; +export { Toast } from "./Toast"; diff --git a/src/containers/BackgroundTasks/BackgroundTasksProvider.tsx b/src/containers/BackgroundTasks/BackgroundTasksProvider.tsx index 41ec289b81e..fe0e38505c4 100644 --- a/src/containers/BackgroundTasks/BackgroundTasksProvider.tsx +++ b/src/containers/BackgroundTasks/BackgroundTasksProvider.tsx @@ -1,7 +1,7 @@ // @ts-strict-ignore import { ApolloClient, useApolloClient } from "@apollo/client"; -import { IMessageContext } from "@dashboard/components/messages"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { INotificationCallback } from "@dashboard/components/notifications"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { ReactNode, useEffect, useRef } from "react"; import { IntlShape, useIntl } from "react-intl"; @@ -14,7 +14,7 @@ export const backgroundTasksRefreshTime = 15 * 1000; export function useBackgroundTasks( apolloClient: Pick, "query">, - notify: IMessageContext, + notify: INotificationCallback, intl: IntlShape, ) { const idCounter = useRef(0); diff --git a/src/containers/BackgroundTasks/tasks.ts b/src/containers/BackgroundTasks/tasks.ts index 64e50ba8ea9..790b7014a8e 100644 --- a/src/containers/BackgroundTasks/tasks.ts +++ b/src/containers/BackgroundTasks/tasks.ts @@ -1,6 +1,6 @@ // @ts-strict-ignore import { ApolloQueryResult } from "@apollo/client"; -import { IMessageContext } from "@dashboard/components/messages"; +import { INotificationCallback } from "@dashboard/components/notifications"; import { CheckExportFileStatusQuery, CheckOrderInvoicesStatusQuery, @@ -76,7 +76,7 @@ export function queueInvoiceGenerate( generateInvoice: InvoiceGenerateParams, tasks: React.MutableRefObject, fetch: () => Promise>, - notify: IMessageContext, + notify: INotificationCallback, intl: IntlShape, ) { if (!generateInvoice) { @@ -117,7 +117,7 @@ export function queueExport( id: number, tasks: React.MutableRefObject, fetch: () => Promise>, - notify: IMessageContext, + notify: INotificationCallback, intl: IntlShape, ) { tasks.current = [ diff --git a/src/customers/views/CustomerAddresses.tsx b/src/customers/views/CustomerAddresses.tsx index b96bd24ce18..f307a5a36af 100644 --- a/src/customers/views/CustomerAddresses.tsx +++ b/src/customers/views/CustomerAddresses.tsx @@ -9,7 +9,7 @@ import { useUpdateCustomerAddressMutation, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import useShop from "@dashboard/hooks/useShop"; import { commonMessages } from "@dashboard/intl"; import createDialogActionHandlers from "@dashboard/utils/handlers/dialogActionHandlers"; diff --git a/src/customers/views/CustomerCreate.tsx b/src/customers/views/CustomerCreate.tsx index 2236c021e92..a87fac6b67c 100644 --- a/src/customers/views/CustomerCreate.tsx +++ b/src/customers/views/CustomerCreate.tsx @@ -2,7 +2,7 @@ import { WindowTitle } from "@dashboard/components/WindowTitle"; import { useCreateCustomerMutation, useCustomerCreateDataQuery } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { useIntl } from "react-intl"; import { extractMutationErrors, maybe } from "../../misc"; diff --git a/src/customers/views/CustomerDetails.tsx b/src/customers/views/CustomerDetails.tsx index 65aec5b5b88..cbbd0db04c2 100644 --- a/src/customers/views/CustomerDetails.tsx +++ b/src/customers/views/CustomerDetails.tsx @@ -4,7 +4,7 @@ import NotFoundPage from "@dashboard/components/NotFoundPage"; import { WindowTitle } from "@dashboard/components/WindowTitle"; import { useRemoveCustomerMutation, useUpdateCustomerMutation } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { commonMessages } from "@dashboard/intl"; import { extractMutationErrors, getStringOrPlaceholder } from "@dashboard/misc"; import { FormattedMessage, useIntl } from "react-intl"; diff --git a/src/customers/views/CustomerList/CustomerList.tsx b/src/customers/views/CustomerList/CustomerList.tsx index 92580de7d90..f51be5f1d40 100644 --- a/src/customers/views/CustomerList/CustomerList.tsx +++ b/src/customers/views/CustomerList/CustomerList.tsx @@ -8,7 +8,7 @@ import { useBulkRemoveCustomersMutation, useListCustomersQuery } from "@dashboar import { useFilterPresets } from "@dashboard/hooks/useFilterPresets"; import useListSettings from "@dashboard/hooks/useListSettings"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { usePaginationReset } from "@dashboard/hooks/usePaginationReset"; import usePaginator, { createPaginationState, diff --git a/src/discounts/components/DiscountRules/DiscountRules.test.tsx b/src/discounts/components/DiscountRules/DiscountRules.test.tsx index 860bd39b70c..926a5a9e500 100644 --- a/src/discounts/components/DiscountRules/DiscountRules.test.tsx +++ b/src/discounts/components/DiscountRules/DiscountRules.test.tsx @@ -18,8 +18,7 @@ import { DiscountRules } from "./DiscountRules"; import { catalogComplexRules, catalogRules, channels, orderRules } from "./mocksData"; jest.mock("@dashboard/hooks/useNotifier", () => ({ - __esModule: true, - default: jest.fn(() => () => undefined), + useNotifier: jest.fn(() => () => undefined), })); jest.mock("@dashboard/discounts/views/DiscountDetails/context/context", () => ({ __esModule: true, diff --git a/src/discounts/components/DiscountSavebar/DiscountSavebar.tsx b/src/discounts/components/DiscountSavebar/DiscountSavebar.tsx index 1fc79ab1021..d1504d9dd92 100644 --- a/src/discounts/components/DiscountSavebar/DiscountSavebar.tsx +++ b/src/discounts/components/DiscountSavebar/DiscountSavebar.tsx @@ -1,6 +1,6 @@ import { ConfirmButtonTransitionState } from "@dashboard/components/ConfirmButton"; import { Savebar } from "@dashboard/components/Savebar"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { commonMessages } from "@dashboard/intl"; import { useFormContext } from "react-hook-form"; import { useIntl } from "react-intl"; diff --git a/src/discounts/views/DiscountCreate/DiscountCreate.tsx b/src/discounts/views/DiscountCreate/DiscountCreate.tsx index df7d73374dd..f222b11d418 100644 --- a/src/discounts/views/DiscountCreate/DiscountCreate.tsx +++ b/src/discounts/views/DiscountCreate/DiscountCreate.tsx @@ -4,7 +4,7 @@ import { DiscountCreatePage } from "@dashboard/discounts/components/DiscountCrea import { discountListUrl, discountUrl } from "@dashboard/discounts/discountsUrls"; import { usePromotionCreateMutation } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { commonMessages } from "@dashboard/intl"; import { getMutationErrors } from "@dashboard/misc"; import { useIntl } from "react-intl"; diff --git a/src/discounts/views/DiscountDetails/hooks/usePromotionDelete.ts b/src/discounts/views/DiscountDetails/hooks/usePromotionDelete.ts index 9f90c3ada33..05167dd47f7 100644 --- a/src/discounts/views/DiscountDetails/hooks/usePromotionDelete.ts +++ b/src/discounts/views/DiscountDetails/hooks/usePromotionDelete.ts @@ -1,7 +1,7 @@ import { discountListUrl } from "@dashboard/discounts/discountsUrls"; import { usePromotionDeleteMutation } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { useIntl } from "react-intl"; export const usePromotionDelete = () => { diff --git a/src/discounts/views/DiscountDetails/hooks/usePromotionRuleCreate.ts b/src/discounts/views/DiscountDetails/hooks/usePromotionRuleCreate.ts index adc7a8ca16d..451b4cdfd95 100644 --- a/src/discounts/views/DiscountDetails/hooks/usePromotionRuleCreate.ts +++ b/src/discounts/views/DiscountDetails/hooks/usePromotionRuleCreate.ts @@ -6,7 +6,7 @@ import { PromotionRuleDetailsFragment, usePromotionRuleCreateMutation, } from "@dashboard/graphql"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { commonMessages } from "@dashboard/intl"; import { useIntl } from "react-intl"; diff --git a/src/discounts/views/DiscountDetails/hooks/usePromotionRuleDelete.ts b/src/discounts/views/DiscountDetails/hooks/usePromotionRuleDelete.ts index b6e180dd636..319cf3b2dad 100644 --- a/src/discounts/views/DiscountDetails/hooks/usePromotionRuleDelete.ts +++ b/src/discounts/views/DiscountDetails/hooks/usePromotionRuleDelete.ts @@ -6,7 +6,7 @@ import { PromotionRuleDetailsFragment, usePromotionRuleDeleteMutation, } from "@dashboard/graphql"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { commonMessages } from "@dashboard/intl"; import { useIntl } from "react-intl"; diff --git a/src/discounts/views/DiscountDetails/hooks/usePromotionRuleUpdate.ts b/src/discounts/views/DiscountDetails/hooks/usePromotionRuleUpdate.ts index a222f0993c0..c07a76a83e4 100644 --- a/src/discounts/views/DiscountDetails/hooks/usePromotionRuleUpdate.ts +++ b/src/discounts/views/DiscountDetails/hooks/usePromotionRuleUpdate.ts @@ -6,7 +6,7 @@ import { PromotionRuleUpdateMutation, usePromotionRuleUpdateMutation, } from "@dashboard/graphql"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { commonMessages } from "@dashboard/intl"; import { useIntl } from "react-intl"; diff --git a/src/discounts/views/DiscountDetails/hooks/usePromotionUpdate.ts b/src/discounts/views/DiscountDetails/hooks/usePromotionUpdate.ts index 14b72e55d08..f3c2035634e 100644 --- a/src/discounts/views/DiscountDetails/hooks/usePromotionUpdate.ts +++ b/src/discounts/views/DiscountDetails/hooks/usePromotionUpdate.ts @@ -3,7 +3,7 @@ import { PromotionDetailsFragment, usePromotionUpdateMutation, } from "@dashboard/graphql"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { commonMessages } from "@dashboard/intl"; import { useIntl } from "react-intl"; diff --git a/src/discounts/views/VoucherCreate/VoucherCreate.tsx b/src/discounts/views/VoucherCreate/VoucherCreate.tsx index 6a169b6d497..9c902089548 100644 --- a/src/discounts/views/VoucherCreate/VoucherCreate.tsx +++ b/src/discounts/views/VoucherCreate/VoucherCreate.tsx @@ -14,7 +14,7 @@ import { import useBulkActions from "@dashboard/hooks/useBulkActions"; import useChannels from "@dashboard/hooks/useChannels"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import useShop from "@dashboard/hooks/useShop"; import { sectionNames } from "@dashboard/intl"; import { useCategoryWithTotalProductsSearch } from "@dashboard/searches/useCategorySearch"; diff --git a/src/discounts/views/VoucherDetails/VoucherDetails.tsx b/src/discounts/views/VoucherDetails/VoucherDetails.tsx index 64a2d476bc0..0332f318096 100644 --- a/src/discounts/views/VoucherDetails/VoucherDetails.tsx +++ b/src/discounts/views/VoucherDetails/VoucherDetails.tsx @@ -48,7 +48,7 @@ import useLocalPaginator, { useSectionLocalPaginationState, } from "@dashboard/hooks/useLocalPaginator"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { PaginatorContext } from "@dashboard/hooks/usePaginator"; import useShop from "@dashboard/hooks/useShop"; import { commonMessages, sectionNames } from "@dashboard/intl"; diff --git a/src/discounts/views/VoucherList/VoucherList.tsx b/src/discounts/views/VoucherList/VoucherList.tsx index ab1302f2515..fb6b4761d98 100644 --- a/src/discounts/views/VoucherList/VoucherList.tsx +++ b/src/discounts/views/VoucherList/VoucherList.tsx @@ -10,7 +10,7 @@ import { useVoucherBulkDeleteMutation, useVoucherListQuery } from "@dashboard/gr import { useFilterPresets } from "@dashboard/hooks/useFilterPresets"; import useListSettings from "@dashboard/hooks/useListSettings"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { usePaginationReset } from "@dashboard/hooks/usePaginationReset"; import usePaginator, { createPaginationState, diff --git a/src/extensions/views/AddCustomExtension/AddCustomExtension.test.tsx b/src/extensions/views/AddCustomExtension/AddCustomExtension.test.tsx index 885f3bc4cda..9d1b9a27865 100644 --- a/src/extensions/views/AddCustomExtension/AddCustomExtension.test.tsx +++ b/src/extensions/views/AddCustomExtension/AddCustomExtension.test.tsx @@ -1,3 +1,4 @@ +import { ThemeProvider } from "@saleor/macaw-ui-next"; import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import * as React from "react"; @@ -8,6 +9,10 @@ import { usePermissions } from "./hooks/usePermissions"; import { useUserAppCreationPermissions } from "./hooks/useUserAppCreationPermissions"; import { useUserPermissionSet } from "./hooks/useUserPermissionMap"; +const Wrapper = ({ children }: React.PropsWithChildren<{}>) => ( + {children} +); + // Mock ResizeObserver used by Radix checkbox class ResizeObserverMock { observe() { @@ -66,7 +71,7 @@ describe("AddCustomExtension", () => { it("renders the component with all required elements", () => { // Arrange - render(); + render(, { wrapper: Wrapper }); // Assert expect(screen.getByPlaceholderText("Extension Name")).toBeInTheDocument(); @@ -78,7 +83,7 @@ describe("AddCustomExtension", () => { it("displays validation error when submitting empty form", async () => { // Arrange - render(); + render(, { wrapper: Wrapper }); // Act await userEvent.click(screen.getByText("save")); @@ -89,7 +94,7 @@ describe("AddCustomExtension", () => { it("creates app without permissions", async () => { // Arrange - render(); + render(, { wrapper: Wrapper }); const appNameInput = screen.getByPlaceholderText("Extension Name"); @@ -112,7 +117,7 @@ describe("AddCustomExtension", () => { it("creates app with some permissions when checked by user", async () => { // Arrange - render(); + render(, { wrapper: Wrapper }); const appNameInput = screen.getByPlaceholderText("Extension Name"); const ordersCheckbox = screen.getByLabelText(/Manage Orders/i); @@ -140,7 +145,7 @@ describe("AddCustomExtension", () => { it("creates app with all permissions when toggled 'Grant full access'", async () => { // Arrange - render(); + render(, { wrapper: Wrapper }); const appNameInput = screen.getByPlaceholderText("Extension Name"); const fullAccessCheckbox = screen.getByRole("checkbox", { @@ -171,7 +176,7 @@ describe("AddCustomExtension", () => { it("creates app with no permissions when toggling between 'Grant full access'", async () => { // Arrange - render(); + render(, { wrapper: Wrapper }); const appNameInput = screen.getByPlaceholderText("Extension Name"); const fullAccessCheckbox = screen.getByRole("checkbox", { @@ -216,7 +221,7 @@ describe("AddCustomExtension", () => { (useUserAppCreationPermissions as jest.Mock).mockReturnValue(true); // Act - render(); + render(, { wrapper: Wrapper }); // Assert expect(screen.getByText(/warning/i)).toBeInTheDocument(); @@ -230,7 +235,7 @@ describe("AddCustomExtension", () => { const availablePermissions = new Set(["MANAGE_ORDERS"]); (useUserPermissionSet as jest.Mock).mockReturnValue(availablePermissions); - render(); + render(, { wrapper: Wrapper }); const appNameInput = screen.getByPlaceholderText("Extension Name"); const ordersCheckbox = screen.getByLabelText(/Manage Orders/i); diff --git a/src/extensions/views/AddCustomExtension/hooks/useHandleCreateAppSubmit.test.ts b/src/extensions/views/AddCustomExtension/hooks/useHandleCreateAppSubmit.test.ts index a45449babe9..b87f3b8b7f1 100644 --- a/src/extensions/views/AddCustomExtension/hooks/useHandleCreateAppSubmit.test.ts +++ b/src/extensions/views/AddCustomExtension/hooks/useHandleCreateAppSubmit.test.ts @@ -19,7 +19,9 @@ jest.mock("@dashboard/hooks/useNavigator", () => () => jest.fn()); const mockNotify = jest.fn(); -jest.mock("@dashboard/hooks/useNotifier", () => () => mockNotify); +jest.mock("@dashboard/hooks/useNotifier", () => ({ + useNotifier: () => mockNotify, +})); const mockUseAppCreateMutation = useAppCreateMutation as jest.MockedFunction< typeof useAppCreateMutation diff --git a/src/extensions/views/AddCustomExtension/hooks/useHandleCreateAppSubmit.ts b/src/extensions/views/AddCustomExtension/hooks/useHandleCreateAppSubmit.ts index 23358d57cdb..160e236d694 100644 --- a/src/extensions/views/AddCustomExtension/hooks/useHandleCreateAppSubmit.ts +++ b/src/extensions/views/AddCustomExtension/hooks/useHandleCreateAppSubmit.ts @@ -1,7 +1,7 @@ import { ExtensionsUrls } from "@dashboard/extensions/urls"; import { AppErrorCode, PermissionEnum, useAppCreateMutation } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { commonMessages } from "@dashboard/intl"; import { SubmitHandler, UseFormSetError } from "react-hook-form"; import { useIntl } from "react-intl"; diff --git a/src/extensions/views/AddCustomExtensionWebhook/AddCustomExtensionWebhook.tsx b/src/extensions/views/AddCustomExtensionWebhook/AddCustomExtensionWebhook.tsx index bef12121cdb..f8ce747760a 100644 --- a/src/extensions/views/AddCustomExtensionWebhook/AddCustomExtensionWebhook.tsx +++ b/src/extensions/views/AddCustomExtensionWebhook/AddCustomExtensionWebhook.tsx @@ -6,7 +6,7 @@ import { WebhookEventTypeAsyncEnum, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { commonMessages } from "@dashboard/intl"; import { extractMutationErrors } from "@dashboard/misc"; import { useIntl } from "react-intl"; diff --git a/src/extensions/views/EditCustomExtension/EditCustomApp.tsx b/src/extensions/views/EditCustomExtension/EditCustomApp.tsx index 2db1f393c0f..a8ff073d479 100644 --- a/src/extensions/views/EditCustomExtension/EditCustomApp.tsx +++ b/src/extensions/views/EditCustomExtension/EditCustomApp.tsx @@ -24,7 +24,7 @@ import { } from "@dashboard/graphql"; import { useHasManagedAppsPermission } from "@dashboard/hooks/useHasManagedAppsPermission"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import useShop from "@dashboard/hooks/useShop"; import { commonMessages } from "@dashboard/intl"; import { extractMutationErrors, getStringOrPlaceholder, parseLogMessage } from "@dashboard/misc"; diff --git a/src/extensions/views/EditCustomExtension/components/TokenCreateDialog/useClipboardCopy.ts b/src/extensions/views/EditCustomExtension/components/TokenCreateDialog/useClipboardCopy.ts index bb2b73befcd..8946c541810 100644 --- a/src/extensions/views/EditCustomExtension/components/TokenCreateDialog/useClipboardCopy.ts +++ b/src/extensions/views/EditCustomExtension/components/TokenCreateDialog/useClipboardCopy.ts @@ -1,5 +1,5 @@ import { ConfirmButtonTransitionState } from "@dashboard/components/ConfirmButton"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { useEffect, useRef, useState } from "react"; import { useIntl } from "react-intl"; diff --git a/src/extensions/views/EditCustomExtensionWebhook/EditCustomExtensionWebhook.tsx b/src/extensions/views/EditCustomExtensionWebhook/EditCustomExtensionWebhook.tsx index 328abf18fdb..e051b3bcb6f 100644 --- a/src/extensions/views/EditCustomExtensionWebhook/EditCustomExtensionWebhook.tsx +++ b/src/extensions/views/EditCustomExtensionWebhook/EditCustomExtensionWebhook.tsx @@ -6,7 +6,7 @@ import { useWebhookUpdateMutation, WebhookEventTypeAsyncEnum, } from "@dashboard/graphql"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { commonMessages } from "@dashboard/intl"; import { extractMutationErrors, getStringOrPlaceholder } from "@dashboard/misc"; import { useIntl } from "react-intl"; diff --git a/src/extensions/views/EditManifestExtension/AppManageView.tsx b/src/extensions/views/EditManifestExtension/AppManageView.tsx index 3b9d2688297..ae5b6761835 100644 --- a/src/extensions/views/EditManifestExtension/AppManageView.tsx +++ b/src/extensions/views/EditManifestExtension/AppManageView.tsx @@ -19,7 +19,7 @@ import { } from "@dashboard/graphql"; import { useHasManagedAppsPermission } from "@dashboard/hooks/useHasManagedAppsPermission"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import getAppErrorMessage from "@dashboard/utils/errors/app"; import createDialogActionHandlers from "@dashboard/utils/handlers/dialogActionHandlers"; import { useIntl } from "react-intl"; diff --git a/src/extensions/views/EditManifestExtension/components/AppPermissionsDialog/AppPermissionsDialog.tsx b/src/extensions/views/EditManifestExtension/components/AppPermissionsDialog/AppPermissionsDialog.tsx index 9d623492253..71b4466ff06 100644 --- a/src/extensions/views/EditManifestExtension/components/AppPermissionsDialog/AppPermissionsDialog.tsx +++ b/src/extensions/views/EditManifestExtension/components/AppPermissionsDialog/AppPermissionsDialog.tsx @@ -2,7 +2,7 @@ import { DashboardModal } from "@dashboard/components/Modal"; import { getCustomAppErrorMessage } from "@dashboard/extensions/utils"; import { useGetAvailableAppPermissions } from "@dashboard/extensions/views/EditManifestExtension/hooks/useGetAvailableAppPermissions"; import { PermissionEnum, useAppQuery, useAppUpdatePermissionsMutation } from "@dashboard/graphql"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { Box, Skeleton, Text } from "@saleor/macaw-ui-next"; import { useEffect } from "react"; import { useIntl } from "react-intl"; diff --git a/src/extensions/views/EditPluginExtension/EditPluginExtension.tsx b/src/extensions/views/EditPluginExtension/EditPluginExtension.tsx index f3faaf13e3f..8b5a4a1c58e 100644 --- a/src/extensions/views/EditPluginExtension/EditPluginExtension.tsx +++ b/src/extensions/views/EditPluginExtension/EditPluginExtension.tsx @@ -9,7 +9,7 @@ import { usePluginUpdateMutation, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import useStateFromProps from "@dashboard/hooks/useStateFromProps"; import { commonMessages } from "@dashboard/intl"; import { extractMutationErrors } from "@dashboard/misc"; diff --git a/src/extensions/views/InstallCustomExtension/hooks/useInstallApp.test.ts b/src/extensions/views/InstallCustomExtension/hooks/useInstallApp.test.ts index 1a84e638760..f98ffb94b5e 100644 --- a/src/extensions/views/InstallCustomExtension/hooks/useInstallApp.test.ts +++ b/src/extensions/views/InstallCustomExtension/hooks/useInstallApp.test.ts @@ -1,7 +1,7 @@ import { AppManifestFragment, PermissionEnum, useAppInstallMutation } from "@dashboard/graphql"; import useLocalStorage from "@dashboard/hooks/useLocalStorage"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { extractMutationErrors } from "@dashboard/misc"; import { act, renderHook } from "@testing-library/react-hooks"; import { useIntl } from "react-intl"; @@ -19,7 +19,9 @@ jest.mock("@dashboard/graphql", () => { jest.mock("@dashboard/hooks/useLocalStorage", () => jest.fn()); jest.mock("@dashboard/hooks/useNavigator", () => jest.fn()); -jest.mock("@dashboard/hooks/useNotifier", () => jest.fn()); +jest.mock("@dashboard/hooks/useNotifier", () => ({ + useNotifier: jest.fn(), +})); jest.mock("@dashboard/misc", () => ({ extractMutationErrors: jest.fn(), })); diff --git a/src/extensions/views/InstallCustomExtension/hooks/useInstallApp.ts b/src/extensions/views/InstallCustomExtension/hooks/useInstallApp.ts index 1b59a3c297c..f2c50889016 100644 --- a/src/extensions/views/InstallCustomExtension/hooks/useInstallApp.ts +++ b/src/extensions/views/InstallCustomExtension/hooks/useInstallApp.ts @@ -2,7 +2,7 @@ import { getAppInstallErrorMessage } from "@dashboard/extensions/utils"; import { useAppInstallMutation } from "@dashboard/graphql"; import useLocalStorage from "@dashboard/hooks/useLocalStorage"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { extractMutationErrors } from "@dashboard/misc"; import { UseFormGetValues } from "react-hook-form"; import { useIntl } from "react-intl"; diff --git a/src/extensions/views/InstalledExtensions/hooks/useInstallationNotify.ts b/src/extensions/views/InstalledExtensions/hooks/useInstallationNotify.ts index b891d180dea..4ce88db1281 100644 --- a/src/extensions/views/InstalledExtensions/hooks/useInstallationNotify.ts +++ b/src/extensions/views/InstalledExtensions/hooks/useInstallationNotify.ts @@ -1,5 +1,5 @@ import { notifyMessages } from "@dashboard/extensions/messages"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { useIntl } from "react-intl"; export const useInstallationNotify = () => { diff --git a/src/extensions/views/ViewManifestExtension/ViewManifestExtensionIframe.tsx b/src/extensions/views/ViewManifestExtension/ViewManifestExtensionIframe.tsx index 6e679090a58..5a09d7fb9bb 100644 --- a/src/extensions/views/ViewManifestExtension/ViewManifestExtensionIframe.tsx +++ b/src/extensions/views/ViewManifestExtension/ViewManifestExtensionIframe.tsx @@ -4,7 +4,7 @@ import { ExtensionsUrls } from "@dashboard/extensions/urls"; import { useAppQuery } from "@dashboard/graphql"; import { useHasManagedAppsPermission } from "@dashboard/hooks/useHasManagedAppsPermission"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { useCallback } from "react"; import { useIntl } from "react-intl"; import { useLocation } from "react-router"; diff --git a/src/extensions/views/ViewManifestExtension/components/AppFrame/appActionsHandler.test.ts b/src/extensions/views/ViewManifestExtension/components/AppFrame/appActionsHandler.test.ts index 21278b39a11..735fc4f0965 100644 --- a/src/extensions/views/ViewManifestExtension/components/AppFrame/appActionsHandler.test.ts +++ b/src/extensions/views/ViewManifestExtension/components/AppFrame/appActionsHandler.test.ts @@ -1,5 +1,4 @@ import * as dashboardConfig from "@dashboard/config"; -import { UseNotifierResult } from "@dashboard/hooks/useNotifier"; import { renderHook } from "@testing-library/react-hooks"; import * as ReactIntl from "react-intl"; import { IntlShape } from "react-intl"; @@ -20,7 +19,9 @@ jest.mock("../ExternalAppContext/ExternalAppContext"); const mockNotify = jest.fn(); const mockCloseExternalApp = jest.fn(); -jest.mock("@dashboard/hooks/useNotifier", (): UseNotifierResult => () => mockNotify); +jest.mock("@dashboard/hooks/useNotifier", () => ({ + useNotifier: () => mockNotify, +})); jest.spyOn(ExternalAppContext, "useExternalApp").mockImplementation(() => ({ close: mockCloseExternalApp, openApp: jest.fn(), diff --git a/src/extensions/views/ViewManifestExtension/components/AppFrame/appActionsHandler.ts b/src/extensions/views/ViewManifestExtension/components/AppFrame/appActionsHandler.ts index f4343327d92..1778317e3f9 100644 --- a/src/extensions/views/ViewManifestExtension/components/AppFrame/appActionsHandler.ts +++ b/src/extensions/views/ViewManifestExtension/components/AppFrame/appActionsHandler.ts @@ -2,7 +2,7 @@ import { getAppMountUri } from "@dashboard/config"; import { useActiveAppExtension } from "@dashboard/extensions/components/AppExtensionContext/AppExtensionContextProvider"; import { ExtensionsUrls, LegacyAppPaths } from "@dashboard/extensions/urls"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { DashboardEventFactory, DispatchResponseEvent, diff --git a/src/extensions/views/ViewManifestExtension/components/AppFrame/useAppActions.test.ts b/src/extensions/views/ViewManifestExtension/components/AppFrame/useAppActions.test.ts index ebb9f3a0b3e..542339819e5 100644 --- a/src/extensions/views/ViewManifestExtension/components/AppFrame/useAppActions.test.ts +++ b/src/extensions/views/ViewManifestExtension/components/AppFrame/useAppActions.test.ts @@ -14,7 +14,9 @@ jest.mock("@sentry/react", () => ({ const mockNotifier = jest.fn(); -jest.mock("@dashboard/hooks/useNotifier", () => (): jest.Mock => mockNotifier); +jest.mock("@dashboard/hooks/useNotifier", () => ({ + useNotifier: (): jest.Mock => mockNotifier, +})); jest.mock("./usePostToExtension"); diff --git a/src/extensions/views/ViewManifestExtension/components/AppFrame/useAppActions.ts b/src/extensions/views/ViewManifestExtension/components/AppFrame/useAppActions.ts index e6cf6cfc1c9..ba35e62734b 100644 --- a/src/extensions/views/ViewManifestExtension/components/AppFrame/useAppActions.ts +++ b/src/extensions/views/ViewManifestExtension/components/AppFrame/useAppActions.ts @@ -1,4 +1,4 @@ -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { Actions, DispatchResponseEvent } from "@saleor/app-sdk/app-bridge"; import { captureMessage } from "@sentry/react"; import { useEffect, useState } from "react"; diff --git a/src/giftCards/GiftCardBulkCreateDialog/GiftCardBulkCreateDialog.tsx b/src/giftCards/GiftCardBulkCreateDialog/GiftCardBulkCreateDialog.tsx index 034df35c95d..0923e2754ba 100644 --- a/src/giftCards/GiftCardBulkCreateDialog/GiftCardBulkCreateDialog.tsx +++ b/src/giftCards/GiftCardBulkCreateDialog/GiftCardBulkCreateDialog.tsx @@ -1,8 +1,8 @@ -import { IMessage } from "@dashboard/components/messages"; import { DashboardModal } from "@dashboard/components/Modal"; +import { INotification } from "@dashboard/components/notifications"; import { GiftCardBulkCreateInput, useGiftCardBulkCreateMutation } from "@dashboard/graphql"; import { useCurrentDate } from "@dashboard/hooks/useCurrentDate"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { DialogProps } from "@dashboard/types"; import { getFormErrors } from "@dashboard/utils/errors"; import { useEffect, useState } from "react"; @@ -54,7 +54,7 @@ export const GiftCardBulkCreateDialog = ({ onClose, open }: DialogProps) => { onCompleted: data => { const errors = data?.giftCardBulkCreate?.errors; const cardsAmount = data?.giftCardBulkCreate?.giftCards?.length || 0; - const giftCardsBulkIssueSuccessMessage: IMessage = { + const giftCardsBulkIssueSuccessMessage: INotification = { status: "success", title: intl.formatMessage(messages.createdSuccessAlertTitle), text: intl.formatMessage(messages.createdSuccessAlertDescription, { diff --git a/src/giftCards/GiftCardCreateDialog/GiftCardCreateDialogCodeContent.tsx b/src/giftCards/GiftCardCreateDialog/GiftCardCreateDialogCodeContent.tsx index 08611f9a134..2cc466e2f8f 100644 --- a/src/giftCards/GiftCardCreateDialog/GiftCardCreateDialogCodeContent.tsx +++ b/src/giftCards/GiftCardCreateDialog/GiftCardCreateDialogCodeContent.tsx @@ -1,6 +1,6 @@ import { DashboardModal } from "@dashboard/components/Modal"; import { useClipboard } from "@dashboard/hooks/useClipboard"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { buttonMessages } from "@dashboard/intl"; import { Button, Text } from "@saleor/macaw-ui-next"; import { useIntl } from "react-intl"; diff --git a/src/giftCards/GiftCardCreateDialog/GiftCardCreateDialogContent.tsx b/src/giftCards/GiftCardCreateDialog/GiftCardCreateDialogContent.tsx index 615abb428f6..ecfc9dedfb6 100644 --- a/src/giftCards/GiftCardCreateDialog/GiftCardCreateDialogContent.tsx +++ b/src/giftCards/GiftCardCreateDialog/GiftCardCreateDialogContent.tsx @@ -2,7 +2,7 @@ import { DashboardModal } from "@dashboard/components/Modal"; import { GiftCardCreateInput, useGiftCardCreateMutation } from "@dashboard/graphql"; import { useCurrentDate } from "@dashboard/hooks/useCurrentDate"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { DialogProps } from "@dashboard/types"; import { useState } from "react"; import { useIntl } from "react-intl"; diff --git a/src/giftCards/GiftCardCreateDialog/utils.ts b/src/giftCards/GiftCardCreateDialog/utils.ts index 1623e0bc7d6..1714e1ce9a5 100644 --- a/src/giftCards/GiftCardCreateDialog/utils.ts +++ b/src/giftCards/GiftCardCreateDialog/utils.ts @@ -1,5 +1,5 @@ // @ts-strict-ignore -import { IMessage } from "@dashboard/components/messages"; +import { INotification } from "@dashboard/components/notifications"; import { GiftCardCreateMutation, TimePeriodTypeEnum } from "@dashboard/graphql"; import commonErrorMessages from "@dashboard/utils/errors/common"; import moment from "moment-timezone"; @@ -34,7 +34,7 @@ export const getExpiryPeriodTerminationDate = ( } }; -const getGiftCardExpiryError = (intl: IntlShape): IMessage => ({ +const getGiftCardExpiryError = (intl: IntlShape): INotification => ({ title: intl.formatMessage(giftCardUpdateFormMessages.giftCardInvalidExpiryDateHeader), text: intl.formatMessage(giftCardUpdateFormMessages.giftCardInvalidExpiryDateContent), status: "error", @@ -43,8 +43,8 @@ const getGiftCardExpiryError = (intl: IntlShape): IMessage => ({ export const getGiftCardCreateOnCompletedMessage = ( errors: GiftCardCreateMutation["giftCardCreate"]["errors"], intl: IntlShape, - successMessage?: IMessage, -): IMessage => { + successMessage?: INotification, +): INotification => { const hasExpiryError = errors.some(error => error.field === "expiryDate"); const successGiftCardMessage = successMessage || { status: "success", diff --git a/src/giftCards/GiftCardExportDialogContent/GiftCardExportDialogContent.tsx b/src/giftCards/GiftCardExportDialogContent/GiftCardExportDialogContent.tsx index 75afa29de99..7b30e25beec 100644 --- a/src/giftCards/GiftCardExportDialogContent/GiftCardExportDialogContent.tsx +++ b/src/giftCards/GiftCardExportDialogContent/GiftCardExportDialogContent.tsx @@ -4,7 +4,7 @@ import { Task } from "@dashboard/containers/BackgroundTasks/types"; import { useExportGiftCardsMutation, useGiftCardTotalCountQuery } from "@dashboard/graphql"; import useBackgroundTask from "@dashboard/hooks/useBackgroundTask"; import useForm from "@dashboard/hooks/useForm"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import ExportDialogSettings from "@dashboard/products/components/ProductExportDialog/ExportDialogSettings"; import { ExportSettingsFormData, diff --git a/src/giftCards/GiftCardUpdate/GiftCardHistory/GiftCardHistory.tsx b/src/giftCards/GiftCardUpdate/GiftCardHistory/GiftCardHistory.tsx index deb029a4c7f..6fccd88ef64 100644 --- a/src/giftCards/GiftCardUpdate/GiftCardHistory/GiftCardHistory.tsx +++ b/src/giftCards/GiftCardUpdate/GiftCardHistory/GiftCardHistory.tsx @@ -6,7 +6,7 @@ import { TimelineNote } from "@dashboard/components/Timeline/TimelineNote"; import { toActor } from "@dashboard/components/Timeline/utils"; import { useGiftCardDetails } from "@dashboard/giftCards/GiftCardUpdate/providers/GiftCardDetailsProvider"; import { GiftCardEventsEnum, useGiftCardAddNoteMutation } from "@dashboard/graphql"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { HistoryComponentLoader } from "@dashboard/orders/components/OrderHistory/HistoryComponentLoader"; import { FormattedMessage, useIntl } from "react-intl"; diff --git a/src/giftCards/GiftCardUpdate/GiftCardResendCodeDialog/GiftCardResendCodeDialog.tsx b/src/giftCards/GiftCardUpdate/GiftCardResendCodeDialog/GiftCardResendCodeDialog.tsx index 427b068d284..a105190a5b4 100644 --- a/src/giftCards/GiftCardUpdate/GiftCardResendCodeDialog/GiftCardResendCodeDialog.tsx +++ b/src/giftCards/GiftCardUpdate/GiftCardResendCodeDialog/GiftCardResendCodeDialog.tsx @@ -1,11 +1,11 @@ // @ts-strict-ignore import ActionDialog from "@dashboard/components/ActionDialog"; import { useChannelsSearch } from "@dashboard/components/ChannelsAvailabilityDialog/utils"; -import { IMessage } from "@dashboard/components/messages"; +import { INotification } from "@dashboard/components/notifications"; import { useGiftCardPermissions } from "@dashboard/giftCards/hooks/useGiftCardPermissions"; import { useChannelsQuery, useGiftCardResendMutation } from "@dashboard/graphql"; import useForm from "@dashboard/hooks/useForm"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { getBySlug } from "@dashboard/misc"; import { DialogProps } from "@dashboard/types"; import commonErrorMessages from "@dashboard/utils/errors/common"; @@ -70,7 +70,7 @@ const GiftCardResendCodeDialog = ({ open, onClose }: DialogProps) => { const [resendGiftCardCode, resendGiftCardCodeOpts] = useGiftCardResendMutation({ onCompleted: data => { const errors = data?.giftCardResend?.errors; - const notifierData: IMessage = errors?.length + const notifierData: INotification = errors?.length ? { status: "error", text: intl.formatMessage(commonErrorMessages.unknownError), diff --git a/src/giftCards/GiftCardUpdate/GiftCardUpdateBalanceDialog/GiftCardUpdateBalanceDialog.tsx b/src/giftCards/GiftCardUpdate/GiftCardUpdateBalanceDialog/GiftCardUpdateBalanceDialog.tsx index d92abf0c630..10110b3b412 100644 --- a/src/giftCards/GiftCardUpdate/GiftCardUpdateBalanceDialog/GiftCardUpdateBalanceDialog.tsx +++ b/src/giftCards/GiftCardUpdate/GiftCardUpdateBalanceDialog/GiftCardUpdateBalanceDialog.tsx @@ -1,11 +1,11 @@ // @ts-strict-ignore import ActionDialog from "@dashboard/components/ActionDialog"; import CardSpacer from "@dashboard/components/CardSpacer"; -import { IMessage } from "@dashboard/components/messages"; +import { INotification } from "@dashboard/components/notifications"; import { useGiftCardPermissions } from "@dashboard/giftCards/hooks/useGiftCardPermissions"; import { useGiftCardUpdateMutation } from "@dashboard/graphql"; import useForm from "@dashboard/hooks/useForm"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { DialogProps } from "@dashboard/types"; import commonErrorMessages from "@dashboard/utils/errors/common"; import { Input, Text } from "@saleor/macaw-ui-next"; @@ -37,7 +37,7 @@ const GiftCardUpdateBalanceDialog = ({ open, onClose }: DialogProps) => { const [updateGiftCardBalance, updateGiftCardBalanceOpts] = useGiftCardUpdateMutation({ onCompleted: data => { const errors = data?.giftCardUpdate?.errors; - const notifierData: IMessage = errors?.length + const notifierData: INotification = errors?.length ? { status: "error", text: intl.formatMessage(commonErrorMessages.unknownError), diff --git a/src/giftCards/GiftCardUpdate/GiftCardUpdatePageHeader/hooks/useGiftCardActivateToggle.ts b/src/giftCards/GiftCardUpdate/GiftCardUpdatePageHeader/hooks/useGiftCardActivateToggle.ts index dac18ae4d21..f5a77eb40b5 100644 --- a/src/giftCards/GiftCardUpdate/GiftCardUpdatePageHeader/hooks/useGiftCardActivateToggle.ts +++ b/src/giftCards/GiftCardUpdate/GiftCardUpdatePageHeader/hooks/useGiftCardActivateToggle.ts @@ -1,5 +1,5 @@ import { useGiftCardActivateMutation, useGiftCardDeactivateMutation } from "@dashboard/graphql"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import commonErrorMessages from "@dashboard/utils/errors/common"; import { useIntl } from "react-intl"; diff --git a/src/giftCards/GiftCardUpdate/providers/GiftCardUpdateFormProvider/GiftCardUpdateFormProvider.tsx b/src/giftCards/GiftCardUpdate/providers/GiftCardUpdateFormProvider/GiftCardUpdateFormProvider.tsx index 2abfe35b805..d02dfece0f5 100644 --- a/src/giftCards/GiftCardUpdate/providers/GiftCardUpdateFormProvider/GiftCardUpdateFormProvider.tsx +++ b/src/giftCards/GiftCardUpdate/providers/GiftCardUpdateFormProvider/GiftCardUpdateFormProvider.tsx @@ -12,7 +12,7 @@ import { import { MutationResultWithOpts } from "@dashboard/hooks/makeMutation"; import useForm, { FormChange, UseFormResult } from "@dashboard/hooks/useForm"; import useHandleFormSubmit from "@dashboard/hooks/useHandleFormSubmit"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { getDefaultNotifierSuccessErrorData } from "@dashboard/hooks/useNotifier/utils"; import { getFormErrors } from "@dashboard/utils/errors"; import createMetadataUpdateHandler from "@dashboard/utils/handlers/metadataUpdateHandler"; diff --git a/src/giftCards/GiftCardsList/GiftCardListBulkActions/GiftCardListBulkActions.tsx b/src/giftCards/GiftCardsList/GiftCardListBulkActions/GiftCardListBulkActions.tsx index 36d6c2eb65a..a44fda9c928 100644 --- a/src/giftCards/GiftCardsList/GiftCardListBulkActions/GiftCardListBulkActions.tsx +++ b/src/giftCards/GiftCardsList/GiftCardListBulkActions/GiftCardListBulkActions.tsx @@ -1,10 +1,10 @@ import { ConfirmButton } from "@dashboard/components/ConfirmButton"; -import { IMessage } from "@dashboard/components/messages"; +import { INotification } from "@dashboard/components/notifications"; import { useGiftCardBulkActivateMutation, useGiftCardBulkDeactivateMutation, } from "@dashboard/graphql"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { getByIds } from "@dashboard/orders/components/OrderReturnPage/utils"; import { useIntl } from "react-intl"; @@ -30,7 +30,7 @@ export const GiftCardListBulkActions = () => { .every(({ isActive }) => !isActive); const [activateGiftCards, activateGiftCardsOpts] = useGiftCardBulkActivateMutation({ onCompleted: data => { - const notifierData: IMessage = data?.giftCardBulkActivate?.errors?.length + const notifierData: INotification = data?.giftCardBulkActivate?.errors?.length ? { status: "error", text: intl.formatMessage(messages.errorActivateAlertText, { @@ -54,7 +54,7 @@ export const GiftCardListBulkActions = () => { }); const [deactivateGiftCards, deactivateGiftCardsOpts] = useGiftCardBulkDeactivateMutation({ onCompleted: data => { - const notifierData: IMessage = data?.giftCardBulkDeactivate?.errors?.length + const notifierData: INotification = data?.giftCardBulkDeactivate?.errors?.length ? { status: "error", text: intl.formatMessage(messages.errorDeactivateAlertText, { diff --git a/src/giftCards/GiftCardsList/providers/GiftCardListProvider/GiftCardListProvider.tsx b/src/giftCards/GiftCardsList/providers/GiftCardListProvider/GiftCardListProvider.tsx index eb271541d44..dd6eb8fae2d 100644 --- a/src/giftCards/GiftCardsList/providers/GiftCardListProvider/GiftCardListProvider.tsx +++ b/src/giftCards/GiftCardsList/providers/GiftCardListProvider/GiftCardListProvider.tsx @@ -13,7 +13,7 @@ import { import { UseFilterPresets, useFilterPresets } from "@dashboard/hooks/useFilterPresets"; import useListSettings, { UseListSettings } from "@dashboard/hooks/useListSettings"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { usePaginationReset } from "@dashboard/hooks/usePaginationReset"; import { createPaginationState, PageInfo, PaginationState } from "@dashboard/hooks/usePaginator"; import { UseRowSelection, useRowSelection } from "@dashboard/hooks/useRowSelection"; diff --git a/src/giftCards/components/GiftCardDeleteDialog/useGiftCardBulkDelete.tsx b/src/giftCards/components/GiftCardDeleteDialog/useGiftCardBulkDelete.tsx index e97ad3ee56a..1c0ad5a0c23 100644 --- a/src/giftCards/components/GiftCardDeleteDialog/useGiftCardBulkDelete.tsx +++ b/src/giftCards/components/GiftCardDeleteDialog/useGiftCardBulkDelete.tsx @@ -1,7 +1,7 @@ import { useGiftCardList } from "@dashboard/giftCards/GiftCardsList/providers/GiftCardListProvider"; import { BulkDeleteGiftCardMutation, useBulkDeleteGiftCardMutation } from "@dashboard/graphql"; import { MutationResultWithOpts } from "@dashboard/hooks/makeMutation"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import commonErrorMessages from "@dashboard/utils/errors/common"; import { useIntl } from "react-intl"; diff --git a/src/giftCards/components/GiftCardDeleteDialog/useGiftCardSingleDelete.tsx b/src/giftCards/components/GiftCardDeleteDialog/useGiftCardSingleDelete.tsx index e60197e693e..0c0106295a1 100644 --- a/src/giftCards/components/GiftCardDeleteDialog/useGiftCardSingleDelete.tsx +++ b/src/giftCards/components/GiftCardDeleteDialog/useGiftCardSingleDelete.tsx @@ -2,7 +2,7 @@ import { getGiftCardErrorMessage } from "@dashboard/giftCards/GiftCardUpdate/messages"; import { DeleteGiftCardMutation, useDeleteGiftCardMutation } from "@dashboard/graphql"; import { MutationResultWithOpts } from "@dashboard/hooks/makeMutation"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { useIntl } from "react-intl"; import { giftCardDeleteDialogMessages as messages } from "./messages"; diff --git a/src/hooks/makeMutation.ts b/src/hooks/makeMutation.ts index 4d48e8abae8..bc96acd4438 100644 --- a/src/hooks/makeMutation.ts +++ b/src/hooks/makeMutation.ts @@ -15,7 +15,7 @@ import { GqlErrors, hasError } from "@dashboard/utils/api"; import { DocumentNode } from "graphql"; import { useIntl } from "react-intl"; -import useNotifier from "./useNotifier"; +import { useNotifier } from "./useNotifier"; export type MutationResultWithOpts = MutationResult & MutationResultAdditionalProps; diff --git a/src/hooks/makeQuery.ts b/src/hooks/makeQuery.ts index 609d0b53a82..629bf40ee3c 100644 --- a/src/hooks/makeQuery.ts +++ b/src/hooks/makeQuery.ts @@ -17,7 +17,7 @@ import { useEffect } from "react"; import { useIntl } from "react-intl"; import useAppState from "./useAppState"; -import useNotifier from "./useNotifier"; +import { useNotifier } from "./useNotifier"; export { useLazyQuery } from "@apollo/client"; diff --git a/src/hooks/useHandleFormSubmit.ts b/src/hooks/useHandleFormSubmit.ts index 6368652e731..0ccc6b97715 100644 --- a/src/hooks/useHandleFormSubmit.ts +++ b/src/hooks/useHandleFormSubmit.ts @@ -1,5 +1,5 @@ import { FormId, useExitFormDialog } from "@dashboard/components/Form"; -import { MessageContext } from "@dashboard/components/messages"; +import { NotificationContext } from "@dashboard/components/notifications"; import { SubmitPromise } from "@dashboard/hooks/useForm"; import { useContext } from "react"; @@ -15,13 +15,13 @@ function useHandleFormSubmit({ const { setIsSubmitting, setIsDirty } = useExitFormDialog({ formId, }); - const messageContext = useContext(MessageContext); + const notificationContext = useContext(NotificationContext); async function handleFormSubmit(data: TData): Promise { setIsSubmitting(true); - if (messageContext?.clearErrorNotifications) { - messageContext.clearErrorNotifications(); + if (notificationContext?.clearErrorNotifications) { + notificationContext.clearErrorNotifications(); } const result = onSubmit ? onSubmit(data) : null; diff --git a/src/hooks/useNotifier/index.ts b/src/hooks/useNotifier/index.ts index 4f87156dc75..a9f065e4a4b 100644 --- a/src/hooks/useNotifier/index.ts +++ b/src/hooks/useNotifier/index.ts @@ -1,2 +1,2 @@ -export { default } from "./useNotifier"; -export * from "./useNotifier"; +export type { UseNotifierResult } from "./useNotifier"; +export { useNotifier } from "./useNotifier"; diff --git a/src/hooks/useNotifier/useNotifier.test.tsx b/src/hooks/useNotifier/useNotifier.test.tsx new file mode 100644 index 00000000000..8c73e75c7ec --- /dev/null +++ b/src/hooks/useNotifier/useNotifier.test.tsx @@ -0,0 +1,401 @@ +import { INotification } from "@dashboard/components/notifications"; +import { DEFAULT_NOTIFICATION_SHOW_TIME } from "@dashboard/config"; +import { ThemeProvider } from "@saleor/macaw-ui-next"; +import { act, renderHook } from "@testing-library/react-hooks"; +import { PropsWithChildren } from "react"; +import { IntlProvider } from "react-intl"; +import { toast } from "sonner"; + +import { useNotifier } from "./useNotifier"; + +jest.mock("sonner", () => ({ + toast: { + custom: jest.fn(), + }, +})); + +const mockToastCustom = toast.custom as jest.Mock; + +const wrapper = ({ children }: PropsWithChildren) => ( + + {children} + +); + +describe("useNotifier", () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe("basic functionality", () => { + it("returns notify function", () => { + // Arrange & Act + const { result } = renderHook(() => useNotifier(), { wrapper }); + + // Assert + expect(typeof result.current).toBe("function"); + }); + + it("calls toast.custom when notify is invoked", () => { + // Arrange + const { result } = renderHook(() => useNotifier(), { wrapper }); + const notification: INotification = { + title: "Test", + status: "success", + }; + + // Act + act(() => { + result.current(notification); + }); + + // Assert + expect(mockToastCustom).toHaveBeenCalledTimes(1); + }); + }); + + describe("duration handling", () => { + it("uses DEFAULT_NOTIFICATION_SHOW_TIME for success notifications", () => { + // Arrange + const { result } = renderHook(() => useNotifier(), { wrapper }); + + // Act + act(() => { + result.current({ status: "success", title: "Success" }); + }); + + // Assert + expect(mockToastCustom).toHaveBeenCalledWith(expect.any(Function), { + duration: DEFAULT_NOTIFICATION_SHOW_TIME, + }); + }); + + it("uses Infinity duration for error notifications", () => { + // Arrange + const { result } = renderHook(() => useNotifier(), { wrapper }); + + // Act + act(() => { + result.current({ status: "error", title: "Error" }); + }); + + // Assert + expect(mockToastCustom).toHaveBeenCalledWith(expect.any(Function), { + duration: Infinity, + }); + }); + + it("uses custom autohide value when provided", () => { + // Arrange + const { result } = renderHook(() => useNotifier(), { wrapper }); + const customAutohide = 5000; + + // Act + act(() => { + result.current({ + status: "success", + title: "Custom Duration", + autohide: customAutohide, + }); + }); + + // Assert + expect(mockToastCustom).toHaveBeenCalledWith(expect.any(Function), { + duration: customAutohide, + }); + }); + + it("uses DEFAULT_NOTIFICATION_SHOW_TIME for info notifications", () => { + // Arrange + const { result } = renderHook(() => useNotifier(), { wrapper }); + + // Act + act(() => { + result.current({ status: "info", title: "Info" }); + }); + + // Assert + expect(mockToastCustom).toHaveBeenCalledWith(expect.any(Function), { + duration: DEFAULT_NOTIFICATION_SHOW_TIME, + }); + }); + + it("uses DEFAULT_NOTIFICATION_SHOW_TIME for warning notifications", () => { + // Arrange + const { result } = renderHook(() => useNotifier(), { wrapper }); + + // Act + act(() => { + result.current({ status: "warning", title: "Warning" }); + }); + + // Assert + expect(mockToastCustom).toHaveBeenCalledWith(expect.any(Function), { + duration: DEFAULT_NOTIFICATION_SHOW_TIME, + }); + }); + }); + + describe("title fallback", () => { + it("uses provided title when given", () => { + // Arrange + const { result } = renderHook(() => useNotifier(), { wrapper }); + + // Act + act(() => { + result.current({ title: "Custom Title", status: "success" }); + }); + + // Assert + const renderFn = mockToastCustom.mock.calls[0][0]; + const renderedElement = renderFn("test-id"); + + expect(renderedElement.props.title).toBe("Custom Title"); + }); + + it("falls back to 'Success' for success status without title", () => { + // Arrange + const { result } = renderHook(() => useNotifier(), { wrapper }); + + // Act + act(() => { + result.current({ status: "success" }); + }); + + // Assert + const renderFn = mockToastCustom.mock.calls[0][0]; + const renderedElement = renderFn("test-id"); + + expect(renderedElement.props.title).toBe("Success"); + }); + + it("falls back to 'Error' for error status without title", () => { + // Arrange + const { result } = renderHook(() => useNotifier(), { wrapper }); + + // Act + act(() => { + result.current({ status: "error" }); + }); + + // Assert + const renderFn = mockToastCustom.mock.calls[0][0]; + const renderedElement = renderFn("test-id"); + + expect(renderedElement.props.title).toBe("Error"); + }); + + it("falls back to 'Warning' for warning status without title", () => { + // Arrange + const { result } = renderHook(() => useNotifier(), { wrapper }); + + // Act + act(() => { + result.current({ status: "warning" }); + }); + + // Assert + const renderFn = mockToastCustom.mock.calls[0][0]; + const renderedElement = renderFn("test-id"); + + expect(renderedElement.props.title).toBe("Warning"); + }); + + it("falls back to 'Info' for info status without title", () => { + // Arrange + const { result } = renderHook(() => useNotifier(), { wrapper }); + + // Act + act(() => { + result.current({ status: "info" }); + }); + + // Assert + const renderFn = mockToastCustom.mock.calls[0][0]; + const renderedElement = renderFn("test-id"); + + expect(renderedElement.props.title).toBe("Info"); + }); + + it("falls back to 'Info' when no status is provided", () => { + // Arrange + const { result } = renderHook(() => useNotifier(), { wrapper }); + + // Act + act(() => { + result.current({}); + }); + + // Assert + const renderFn = mockToastCustom.mock.calls[0][0]; + const renderedElement = renderFn("test-id"); + + expect(renderedElement.props.title).toBe("Info"); + }); + }); + + describe("description handling", () => { + it("uses text as description when provided", () => { + // Arrange + const { result } = renderHook(() => useNotifier(), { wrapper }); + + // Act + act(() => { + result.current({ + title: "Title", + text: "Description text", + status: "info", + }); + }); + + // Assert + const renderFn = mockToastCustom.mock.calls[0][0]; + const renderedElement = renderFn("test-id"); + + expect(renderedElement.props.description).toBe("Description text"); + }); + + it("uses apiMessage as description fallback when text is not provided", () => { + // Arrange + const { result } = renderHook(() => useNotifier(), { wrapper }); + + // Act + act(() => { + result.current({ + title: "Title", + apiMessage: "API error message", + status: "error", + }); + }); + + // Assert + const renderFn = mockToastCustom.mock.calls[0][0]; + const renderedElement = renderFn("test-id"); + + expect(renderedElement.props.description).toBe("API error message"); + }); + + it("prefers text over apiMessage when both are provided", () => { + // Arrange + const { result } = renderHook(() => useNotifier(), { wrapper }); + + // Act + act(() => { + result.current({ + title: "Title", + text: "Primary description", + apiMessage: "Fallback description", + status: "info", + }); + }); + + // Assert + const renderFn = mockToastCustom.mock.calls[0][0]; + const renderedElement = renderFn("test-id"); + + expect(renderedElement.props.description).toBe("Primary description"); + }); + }); + + describe("action button", () => { + it("passes action configuration to Toast", () => { + // Arrange + const { result } = renderHook(() => useNotifier(), { wrapper }); + const actionFn = jest.fn(); + + // Act + act(() => { + result.current({ + title: "Title", + status: "info", + actionBtn: { + label: "Undo", + action: actionFn, + }, + }); + }); + + // Assert + const renderFn = mockToastCustom.mock.calls[0][0]; + const renderedElement = renderFn("test-id"); + + expect(renderedElement.props.action).toEqual({ + label: "Undo", + onClick: actionFn, + }); + }); + + it("does not pass action when actionBtn is not provided", () => { + // Arrange + const { result } = renderHook(() => useNotifier(), { wrapper }); + + // Act + act(() => { + result.current({ title: "Title", status: "info" }); + }); + + // Assert + const renderFn = mockToastCustom.mock.calls[0][0]; + const renderedElement = renderFn("test-id"); + + expect(renderedElement.props.action).toBeUndefined(); + }); + }); + + describe("toast type mapping", () => { + it.each([ + ["success", "success"], + ["error", "error"], + ["warning", "warning"], + ["info", "info"], + ] as const)("maps status '%s' to toast type '%s'", (status, expectedType) => { + // Arrange + const { result } = renderHook(() => useNotifier(), { wrapper }); + + // Act + act(() => { + result.current({ title: "Test", status }); + }); + + // Assert + const renderFn = mockToastCustom.mock.calls[0][0]; + const renderedElement = renderFn("test-id"); + + expect(renderedElement.props.type).toBe(expectedType); + }); + + it("defaults to 'info' type when status is not provided", () => { + // Arrange + const { result } = renderHook(() => useNotifier(), { wrapper }); + + // Act + act(() => { + result.current({ title: "Test" }); + }); + + // Assert + const renderFn = mockToastCustom.mock.calls[0][0]; + const renderedElement = renderFn("test-id"); + + expect(renderedElement.props.type).toBe("info"); + }); + }); + + describe("toast id", () => { + it("passes toast id to Toast component", () => { + // Arrange + const { result } = renderHook(() => useNotifier(), { wrapper }); + + // Act + act(() => { + result.current({ title: "Test", status: "success" }); + }); + + // Assert + const renderFn = mockToastCustom.mock.calls[0][0]; + const renderedElement = renderFn("unique-toast-id"); + + expect(renderedElement.props.id).toBe("unique-toast-id"); + }); + }); +}); diff --git a/src/hooks/useNotifier/useNotifier.ts b/src/hooks/useNotifier/useNotifier.ts deleted file mode 100644 index 78acba1b29c..00000000000 --- a/src/hooks/useNotifier/useNotifier.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { IMessage, IMessageContext, MessageContext } from "@dashboard/components/messages"; -import { useContext } from "react"; - -export type UseNotifierResult = IMessageContext; - -function useNotifier(): UseNotifierResult { - const notificationContext = useContext(MessageContext); - const notify = (options: IMessage) => { - const timeout = options.status === "error" ? null : options.autohide; - - notificationContext?.show(options, timeout); - }; - - return notify; -} -export default useNotifier; diff --git a/src/hooks/useNotifier/useNotifier.tsx b/src/hooks/useNotifier/useNotifier.tsx new file mode 100644 index 00000000000..19b0487ea9d --- /dev/null +++ b/src/hooks/useNotifier/useNotifier.tsx @@ -0,0 +1,70 @@ +import { INotification, INotificationCallback } from "@dashboard/components/notifications"; +import { Toast } from "@dashboard/components/notifications/Toast"; +import { DEFAULT_NOTIFICATION_SHOW_TIME } from "@dashboard/config"; +import { commonMessages } from "@dashboard/intl"; +import { useCallback } from "react"; +import { useIntl } from "react-intl"; +import { toast } from "sonner"; + +export type UseNotifierResult = INotificationCallback; + +function useNotifier(): UseNotifierResult { + const intl = useIntl(); + + const notify = useCallback( + (options: INotification) => { + const duration = + options.status === "error" + ? Infinity + : (options.autohide ?? DEFAULT_NOTIFICATION_SHOW_TIME); + + // Build description - use apiMessage as fallback if no text + const description = options.text || options.apiMessage; + + // Determine title with fallback to localized default + const getDefaultTitle = () => { + switch (options.status) { + case "success": + return intl.formatMessage(commonMessages.success); + case "error": + return intl.formatMessage(commonMessages.error); + case "warning": + return intl.formatMessage(commonMessages.warning); + case "info": + default: + return intl.formatMessage(commonMessages.info); + } + }; + + const title = options.title || getDefaultTitle(); + const type = options.status || "info"; + + toast.custom( + id => ( + + ), + { + duration, + }, + ); + }, + [intl], + ); + + return notify; +} + +export { useNotifier }; diff --git a/src/hooks/useNotifier/utils.ts b/src/hooks/useNotifier/utils.ts index 9c4ab96cca3..8e8ad37ea0f 100644 --- a/src/hooks/useNotifier/utils.ts +++ b/src/hooks/useNotifier/utils.ts @@ -1,9 +1,12 @@ -import { IMessage } from "@dashboard/components/messages"; +import { INotification } from "@dashboard/components/notifications"; import { commonMessages } from "@dashboard/intl"; import commonErrorMessages from "@dashboard/utils/errors/common"; import { IntlShape } from "react-intl"; -export const getDefaultNotifierSuccessErrorData = (errors: any[], intl: IntlShape): IMessage => +export const getDefaultNotifierSuccessErrorData = ( + errors: any[], + intl: IntlShape, +): INotification => !errors.length ? { status: "success", diff --git a/src/hooks/useOnSetDefaultVariant.ts b/src/hooks/useOnSetDefaultVariant.ts index a6752dfa59b..22575db8d43 100644 --- a/src/hooks/useOnSetDefaultVariant.ts +++ b/src/hooks/useOnSetDefaultVariant.ts @@ -1,5 +1,5 @@ import { Node, useProductVariantSetDefaultMutation } from "@dashboard/graphql"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { getProductErrorMessage } from "@dashboard/utils/errors"; import { useIntl } from "react-intl"; diff --git a/src/index.tsx b/src/index.tsx index f31ad94f014..9958740f7ce 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -35,8 +35,8 @@ import ErrorPage from "./components/ErrorPage"; import ExitFormDialogProvider from "./components/Form/ExitFormDialogProvider"; import { legacyRedirects } from "./components/LegacyRedirects"; import { LocaleProvider } from "./components/Locale"; -import MessageManagerProvider from "./components/messages"; import { NavigatorSearchProvider } from "./components/NavigatorSearch/NavigatorSearchProvider"; +import NotificationProvider from "./components/notifications"; import { ProductAnalytics } from "./components/ProductAnalytics"; import { SavebarRefProvider } from "./components/Savebar/SavebarRefContext"; import { ShopProvider } from "./components/Shop"; @@ -99,7 +99,7 @@ errorTracker.init(history); Handle legacy theming toggle. Since we use new and old macaw, we need to handle both theme swticher for a while. */ -const handleLegacyTheming = () => { +const handleLegacyTheming = (): void => { const activeTheme = localStorage.getItem("activeMacawUITheme"); if (activeTheme === "defaultDark") { @@ -113,7 +113,7 @@ const handleLegacyTheming = () => { handleLegacyTheming(); -const App = () => ( +const App = (): JSX.Element => ( // @ts-expect-error legacy types @@ -122,7 +122,7 @@ const App = () => ( - + @@ -148,7 +148,7 @@ const App = () => ( - + diff --git a/src/intl.ts b/src/intl.ts index 7d1d0ef715e..bfb56b4d71e 100644 --- a/src/intl.ts +++ b/src/intl.ts @@ -5,6 +5,18 @@ export const commonMessages = defineMessages({ id: "hOxIeP", defaultMessage: "Availability", }, + success: { + id: "xrKHS6", + defaultMessage: "Success", + }, + info: { + id: "we4Lby", + defaultMessage: "Info", + }, + warning: { + id: "3SVI5p", + defaultMessage: "Warning", + }, products: { id: "7NFfmz", defaultMessage: "Products", diff --git a/src/modelTypes/views/PageTypeCreate.tsx b/src/modelTypes/views/PageTypeCreate.tsx index 55a358bd4b7..660b80e8bfa 100644 --- a/src/modelTypes/views/PageTypeCreate.tsx +++ b/src/modelTypes/views/PageTypeCreate.tsx @@ -6,7 +6,7 @@ import { useUpdatePrivateMetadataMutation, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { getMutationErrors } from "@dashboard/misc"; import createMetadataCreateHandler from "@dashboard/utils/handlers/metadataCreateHandler"; import { useIntl } from "react-intl"; diff --git a/src/modelTypes/views/PageTypeDetails.tsx b/src/modelTypes/views/PageTypeDetails.tsx index 01d654c39c8..a2b65052c12 100644 --- a/src/modelTypes/views/PageTypeDetails.tsx +++ b/src/modelTypes/views/PageTypeDetails.tsx @@ -20,7 +20,7 @@ import { import useBulkActions from "@dashboard/hooks/useBulkActions"; import { useListSelectedItems } from "@dashboard/hooks/useListSelectedItems"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { commonMessages } from "@dashboard/intl"; import { getStringOrPlaceholder } from "@dashboard/misc"; import { ReorderEvent } from "@dashboard/types"; diff --git a/src/modelTypes/views/PageTypeList/PageTypeList.tsx b/src/modelTypes/views/PageTypeList/PageTypeList.tsx index fc94c7f925c..c85b793afb7 100644 --- a/src/modelTypes/views/PageTypeList/PageTypeList.tsx +++ b/src/modelTypes/views/PageTypeList/PageTypeList.tsx @@ -8,7 +8,7 @@ import useBulkActions from "@dashboard/hooks/useBulkActions"; import { useFilterPresets } from "@dashboard/hooks/useFilterPresets"; import useListSettings from "@dashboard/hooks/useListSettings"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { usePaginationReset } from "@dashboard/hooks/usePaginationReset"; import usePaginator, { createPaginationState, diff --git a/src/modeling/views/PageCreate.tsx b/src/modeling/views/PageCreate.tsx index 5fc64ac05eb..32c23bb517a 100644 --- a/src/modeling/views/PageCreate.tsx +++ b/src/modeling/views/PageCreate.tsx @@ -17,7 +17,7 @@ import { } from "@dashboard/graphql"; import { getSearchFetchMoreProps } from "@dashboard/hooks/makeTopLevelSearch/utils"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { getMutationErrors } from "@dashboard/misc"; import useCategorySearch from "@dashboard/searches/useCategorySearch"; import useCollectionSearch from "@dashboard/searches/useCollectionSearch"; diff --git a/src/modeling/views/PageDetails.tsx b/src/modeling/views/PageDetails.tsx index 8bb58b1eb92..8da6d15a340 100644 --- a/src/modeling/views/PageDetails.tsx +++ b/src/modeling/views/PageDetails.tsx @@ -29,7 +29,7 @@ import { useUpdatePrivateMetadataMutation, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { commonMessages } from "@dashboard/intl"; import useCategorySearch from "@dashboard/searches/useCategorySearch"; import useCollectionSearch from "@dashboard/searches/useCollectionSearch"; diff --git a/src/modeling/views/PageList/PageList.tsx b/src/modeling/views/PageList/PageList.tsx index f990a711b22..6e1301635d2 100644 --- a/src/modeling/views/PageList/PageList.tsx +++ b/src/modeling/views/PageList/PageList.tsx @@ -14,7 +14,7 @@ import { getSearchFetchMoreProps } from "@dashboard/hooks/makeTopLevelSearch/uti import { useFilterPresets } from "@dashboard/hooks/useFilterPresets"; import useListSettings from "@dashboard/hooks/useListSettings"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { usePaginationReset } from "@dashboard/hooks/usePaginationReset"; import usePaginator, { createPaginationState, diff --git a/src/orders/components/OrderLineMetadataDialog/useHandleSubmit.ts b/src/orders/components/OrderLineMetadataDialog/useHandleSubmit.ts index 66e61a0cb10..276d4509d91 100644 --- a/src/orders/components/OrderLineMetadataDialog/useHandleSubmit.ts +++ b/src/orders/components/OrderLineMetadataDialog/useHandleSubmit.ts @@ -4,7 +4,7 @@ import { useUpdateMetadataMutation, useUpdatePrivateMetadataMutation, } from "@dashboard/graphql"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { commonMessages } from "@dashboard/intl"; import createMetadataUpdateHandler from "@dashboard/utils/handlers/metadataUpdateHandler"; import { useMemo, useRef, useState } from "react"; diff --git a/src/orders/components/OrderManualTransactionRefundPage/OrderManualTransactionRefundPage.test.tsx b/src/orders/components/OrderManualTransactionRefundPage/OrderManualTransactionRefundPage.test.tsx index 3393c509072..61f0d0f7b7d 100644 --- a/src/orders/components/OrderManualTransactionRefundPage/OrderManualTransactionRefundPage.test.tsx +++ b/src/orders/components/OrderManualTransactionRefundPage/OrderManualTransactionRefundPage.test.tsx @@ -6,7 +6,7 @@ import { TransactionActionEnum, TransactionItemFragment, } from "@dashboard/graphql"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { ThemeProvider as LegacyThemeProvider } from "@saleor/macaw-ui"; import { ThemeProvider } from "@saleor/macaw-ui-next"; import { render, screen } from "@testing-library/react"; @@ -20,8 +20,7 @@ jest.mock("@dashboard/hooks/useNavigator", () => () => jest.fn); jest.mock("@dashboard/components/Savebar"); jest.mock("@dashboard/hooks/useNotifier", () => ({ - __esModule: true, - default: jest.fn(() => () => undefined), + useNotifier: jest.fn(() => () => undefined), })); mockResizeObserver(); diff --git a/src/orders/components/OrderManualTransactionRefundPage/components/OrderManualTransactionRefundForm/OrderManualTransactionRefundForm.tsx b/src/orders/components/OrderManualTransactionRefundPage/components/OrderManualTransactionRefundForm/OrderManualTransactionRefundForm.tsx index e97b5e72533..fc0c565b2c6 100644 --- a/src/orders/components/OrderManualTransactionRefundPage/components/OrderManualTransactionRefundForm/OrderManualTransactionRefundForm.tsx +++ b/src/orders/components/OrderManualTransactionRefundPage/components/OrderManualTransactionRefundForm/OrderManualTransactionRefundForm.tsx @@ -6,7 +6,7 @@ import { useOrderTransactionRequestActionMutation, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { refundSavebarMessages } from "@dashboard/orders/components/OrderTransactionRefundPage/messages"; import { orderUrl } from "@dashboard/orders/urls"; import { diff --git a/src/orders/views/OrderDetails/OrderDetails.tsx b/src/orders/views/OrderDetails/OrderDetails.tsx index cdfb1b2f3e5..9a84b31d09f 100644 --- a/src/orders/views/OrderDetails/OrderDetails.tsx +++ b/src/orders/views/OrderDetails/OrderDetails.tsx @@ -13,7 +13,7 @@ import { } from "@dashboard/graphql"; import useBackgroundTask from "@dashboard/hooks/useBackgroundTask"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { commonMessages } from "@dashboard/intl"; import { createOrderMetadataIdSchema } from "@dashboard/orders/components/OrderDetailsPage/utils"; import getOrderErrorMessage from "@dashboard/utils/errors/order"; diff --git a/src/orders/views/OrderDetails/OrderDetailsMessages.tsx b/src/orders/views/OrderDetails/OrderDetailsMessages.tsx index 0df2de6e706..159e2da6265 100644 --- a/src/orders/views/OrderDetails/OrderDetailsMessages.tsx +++ b/src/orders/views/OrderDetails/OrderDetailsMessages.tsx @@ -28,7 +28,7 @@ import { } from "@dashboard/graphql"; import useLocale from "@dashboard/hooks/useLocale"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import getOrderErrorMessage from "@dashboard/utils/errors/order"; import { getOrderTransactionErrorMessage, diff --git a/src/orders/views/OrderDraftList/OrderDraftList.tsx b/src/orders/views/OrderDraftList/OrderDraftList.tsx index b7d8e5e9eef..acf9e43010a 100644 --- a/src/orders/views/OrderDraftList/OrderDraftList.tsx +++ b/src/orders/views/OrderDraftList/OrderDraftList.tsx @@ -12,7 +12,7 @@ import { useOrderDraftCreateMutation, useOrderDraftListQuery } from "@dashboard/ import { useFilterPresets } from "@dashboard/hooks/useFilterPresets"; import useListSettings from "@dashboard/hooks/useListSettings"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { usePaginationReset } from "@dashboard/hooks/usePaginationReset"; import usePaginator, { createPaginationState, diff --git a/src/orders/views/OrderDraftList/useBulkDeletion.ts b/src/orders/views/OrderDraftList/useBulkDeletion.ts index d54dcac42bb..7dcc0321f8b 100644 --- a/src/orders/views/OrderDraftList/useBulkDeletion.ts +++ b/src/orders/views/OrderDraftList/useBulkDeletion.ts @@ -1,5 +1,5 @@ import { useOrderDraftBulkCancelMutation } from "@dashboard/graphql"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { useIntl } from "react-intl"; export const useBulkDeletion = (onComplete: () => void) => { diff --git a/src/orders/views/OrderEditGrantRefund/OrderEditGrantRefund.tsx b/src/orders/views/OrderEditGrantRefund/OrderEditGrantRefund.tsx index db72ee6dadd..80a4a96ae79 100644 --- a/src/orders/views/OrderEditGrantRefund/OrderEditGrantRefund.tsx +++ b/src/orders/views/OrderEditGrantRefund/OrderEditGrantRefund.tsx @@ -6,7 +6,7 @@ import { useOrderGrantRefundEditMutation, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { extractMutationErrors } from "@dashboard/misc"; import OrderGrantRefundPage from "@dashboard/orders/components/OrderGrantRefundPage"; import { OrderGrantRefundFormData } from "@dashboard/orders/components/OrderGrantRefundPage/form"; diff --git a/src/orders/views/OrderFulfill/OrderFulfill.tsx b/src/orders/views/OrderFulfill/OrderFulfill.tsx index 58bee106c40..6bfaf5331fd 100644 --- a/src/orders/views/OrderFulfill/OrderFulfill.tsx +++ b/src/orders/views/OrderFulfill/OrderFulfill.tsx @@ -7,7 +7,7 @@ import { useOrderFulfillSettingsQuery, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { getMutationErrors } from "@dashboard/misc"; import OrderFulfillPage, { OrderFulfillSubmitData, diff --git a/src/orders/views/OrderGrantRefund/OrderGrantRefund.tsx b/src/orders/views/OrderGrantRefund/OrderGrantRefund.tsx index e4c63e6e470..91cb093398f 100644 --- a/src/orders/views/OrderGrantRefund/OrderGrantRefund.tsx +++ b/src/orders/views/OrderGrantRefund/OrderGrantRefund.tsx @@ -4,7 +4,7 @@ import { useOrderGrantRefundAddMutation, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { extractMutationErrors } from "@dashboard/misc"; import OrderGrantRefundPage from "@dashboard/orders/components/OrderGrantRefundPage"; import { OrderGrantRefundFormData } from "@dashboard/orders/components/OrderGrantRefundPage/form"; diff --git a/src/orders/views/OrderList/OrderList.tsx b/src/orders/views/OrderList/OrderList.tsx index 181ba2f7172..ad26d44b0f5 100644 --- a/src/orders/views/OrderList/OrderList.tsx +++ b/src/orders/views/OrderList/OrderList.tsx @@ -12,7 +12,7 @@ import { useFilterHandlers } from "@dashboard/hooks/useFilterHandlers"; import { useFilterPresets } from "@dashboard/hooks/useFilterPresets"; import useListSettings from "@dashboard/hooks/useListSettings"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { usePaginationReset } from "@dashboard/hooks/usePaginationReset"; import usePaginator, { createPaginationState, diff --git a/src/orders/views/OrderRefund/OrderRefund.tsx b/src/orders/views/OrderRefund/OrderRefund.tsx index d4be4351d33..4774fec94c7 100644 --- a/src/orders/views/OrderRefund/OrderRefund.tsx +++ b/src/orders/views/OrderRefund/OrderRefund.tsx @@ -5,7 +5,7 @@ import { useOrderRefundMutation, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { extractMutationErrors } from "@dashboard/misc"; import OrderRefundPage from "@dashboard/orders/components/OrderRefundPage"; import { diff --git a/src/orders/views/OrderReturn/OrderReturn.tsx b/src/orders/views/OrderReturn/OrderReturn.tsx index 58cfd2550d1..c94e22dbe3e 100644 --- a/src/orders/views/OrderReturn/OrderReturn.tsx +++ b/src/orders/views/OrderReturn/OrderReturn.tsx @@ -4,7 +4,7 @@ import { useOrderDetailsQuery, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { extractMutationErrors } from "@dashboard/misc"; import OrderReturnPage from "@dashboard/orders/components/OrderReturnPage"; import { OrderReturnFormData } from "@dashboard/orders/components/OrderReturnPage/form"; diff --git a/src/orders/views/OrderSendRefund/OrderSendRefund.tsx b/src/orders/views/OrderSendRefund/OrderSendRefund.tsx index 1825914ebc5..5d40958386d 100644 --- a/src/orders/views/OrderSendRefund/OrderSendRefund.tsx +++ b/src/orders/views/OrderSendRefund/OrderSendRefund.tsx @@ -4,7 +4,7 @@ import { useCreateManualTransactionRefundMutation, useOrderDetailsQuery, } from "@dashboard/graphql"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import OrderSendRefundPage from "@dashboard/orders/components/OrderSendRefundPage"; import { getTransactionCreateErrorMessage } from "@dashboard/utils/errors/transaction"; import { defineMessages, useIntl } from "react-intl"; diff --git a/src/orders/views/OrderSettings.tsx b/src/orders/views/OrderSettings.tsx index f74f604ff7a..2b224ff83a6 100644 --- a/src/orders/views/OrderSettings.tsx +++ b/src/orders/views/OrderSettings.tsx @@ -1,6 +1,6 @@ // @ts-strict-ignore import { useOrderSettingsQuery, useOrderSettingsUpdateMutation } from "@dashboard/graphql"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { commonMessages } from "@dashboard/intl"; import { extractMutationErrors, getMutationState } from "@dashboard/misc"; import OrderSettingsPage from "@dashboard/orders/components/OrderSettingsPage"; diff --git a/src/orders/views/OrderTransactionRefundCreate/OrderTransactionRefundCreate.tsx b/src/orders/views/OrderTransactionRefundCreate/OrderTransactionRefundCreate.tsx index c95c35c85ad..5ee8d09b9f2 100644 --- a/src/orders/views/OrderTransactionRefundCreate/OrderTransactionRefundCreate.tsx +++ b/src/orders/views/OrderTransactionRefundCreate/OrderTransactionRefundCreate.tsx @@ -4,7 +4,7 @@ import { useRefundSettingsQuery, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import OrderTransactionRefundPage, { OrderTransactionRefundError, OrderTransactionRefundPageFormData, diff --git a/src/orders/views/OrderTransactionRefundCreate/handlers.ts b/src/orders/views/OrderTransactionRefundCreate/handlers.ts index d776ebf53af..0caef0888d8 100644 --- a/src/orders/views/OrderTransactionRefundCreate/handlers.ts +++ b/src/orders/views/OrderTransactionRefundCreate/handlers.ts @@ -1,4 +1,4 @@ -import { IMessage } from "@dashboard/components/messages"; +import { INotification } from "@dashboard/components/notifications"; import { OrderDetailsGrantRefundQuery, OrderGrantRefundAddMutation, @@ -25,7 +25,7 @@ export const handleRefundCreateComplete = ({ orderId, }: { submitData: OrderGrantRefundAddMutation; - notify: (message: IMessage) => void; + notify: (notification: INotification) => void; setLinesErrors: (value: React.SetStateAction) => void; navigate: UseNavigatorResult; intl: IntlShape; diff --git a/src/orders/views/OrderTransactionRefundEdit/OrderTransactionRefundEdit.tsx b/src/orders/views/OrderTransactionRefundEdit/OrderTransactionRefundEdit.tsx index fbfeb164ee0..03b1ed630ea 100644 --- a/src/orders/views/OrderTransactionRefundEdit/OrderTransactionRefundEdit.tsx +++ b/src/orders/views/OrderTransactionRefundEdit/OrderTransactionRefundEdit.tsx @@ -8,7 +8,7 @@ import { useRefundSettingsQuery, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { extractMutationErrors } from "@dashboard/misc"; import OrderTransactionRefundPage, { OrderTransactionRefundError, diff --git a/src/orders/views/OrderTransactionRefundEdit/handlers.ts b/src/orders/views/OrderTransactionRefundEdit/handlers.ts index 611b3afa340..3de42687af5 100644 --- a/src/orders/views/OrderTransactionRefundEdit/handlers.ts +++ b/src/orders/views/OrderTransactionRefundEdit/handlers.ts @@ -1,4 +1,4 @@ -import { IMessage } from "@dashboard/components/messages"; +import { INotification } from "@dashboard/components/notifications"; import { OrderGrantRefundEditMutation, OrderGrantRefundUpdateErrorCode, @@ -16,7 +16,7 @@ export const handleRefundEditComplete = ({ intl, }: { submitData: OrderGrantRefundEditMutation; - notify: (message: IMessage) => void; + notify: (notification: INotification) => void; setLinesErrors: (value: React.SetStateAction) => void; intl: IntlShape; orderId: string; diff --git a/src/permissionGroups/views/PermissionGroupCreate/PermissionGroupCreate.tsx b/src/permissionGroups/views/PermissionGroupCreate/PermissionGroupCreate.tsx index dad48727a09..43a68b456d0 100644 --- a/src/permissionGroups/views/PermissionGroupCreate/PermissionGroupCreate.tsx +++ b/src/permissionGroups/views/PermissionGroupCreate/PermissionGroupCreate.tsx @@ -3,7 +3,7 @@ import useAppChannel from "@dashboard/components/AppLayout/AppChannelContext"; import { WindowTitle } from "@dashboard/components/WindowTitle"; import { usePermissionGroupCreateMutation } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import useShop from "@dashboard/hooks/useShop"; import { extractMutationErrors } from "@dashboard/misc"; import { PermissionData } from "@dashboard/permissionGroups/components/PermissionGroupDetailsPage"; diff --git a/src/permissionGroups/views/PermissionGroupDetails/PermissionGroupDetails.tsx b/src/permissionGroups/views/PermissionGroupDetails/PermissionGroupDetails.tsx index ffe5cd886f1..3af709e39a5 100644 --- a/src/permissionGroups/views/PermissionGroupDetails/PermissionGroupDetails.tsx +++ b/src/permissionGroups/views/PermissionGroupDetails/PermissionGroupDetails.tsx @@ -11,7 +11,7 @@ import { } from "@dashboard/graphql"; import useBulkActions from "@dashboard/hooks/useBulkActions"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import useShop from "@dashboard/hooks/useShop"; import useStateFromProps from "@dashboard/hooks/useStateFromProps"; import { commonMessages } from "@dashboard/intl"; diff --git a/src/productTypes/views/ProductTypeCreate.tsx b/src/productTypes/views/ProductTypeCreate.tsx index 048f57417d9..34bd22703ad 100644 --- a/src/productTypes/views/ProductTypeCreate.tsx +++ b/src/productTypes/views/ProductTypeCreate.tsx @@ -8,7 +8,7 @@ import { useUpdatePrivateMetadataMutation, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { useTaxClassFetchMore } from "@dashboard/taxes/utils/useTaxClassFetchMore"; import createMetadataCreateHandler from "@dashboard/utils/handlers/metadataCreateHandler"; import { useIntl } from "react-intl"; diff --git a/src/productTypes/views/ProductTypeList/ProductTypeList.tsx b/src/productTypes/views/ProductTypeList/ProductTypeList.tsx index b3d7fc77f0a..ebcd33854b0 100644 --- a/src/productTypes/views/ProductTypeList/ProductTypeList.tsx +++ b/src/productTypes/views/ProductTypeList/ProductTypeList.tsx @@ -8,7 +8,7 @@ import useBulkActions from "@dashboard/hooks/useBulkActions"; import { useFilterPresets } from "@dashboard/hooks/useFilterPresets"; import useListSettings from "@dashboard/hooks/useListSettings"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { usePaginationReset } from "@dashboard/hooks/usePaginationReset"; import usePaginator, { createPaginationState, diff --git a/src/productTypes/views/ProductTypeUpdate/index.tsx b/src/productTypes/views/ProductTypeUpdate/index.tsx index 058efae97d1..c48eddfdc82 100644 --- a/src/productTypes/views/ProductTypeUpdate/index.tsx +++ b/src/productTypes/views/ProductTypeUpdate/index.tsx @@ -22,7 +22,7 @@ import { import useBulkActions from "@dashboard/hooks/useBulkActions"; import { useListSelectedItems } from "@dashboard/hooks/useListSelectedItems"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { commonMessages } from "@dashboard/intl"; import { getStringOrPlaceholder, maybe } from "@dashboard/misc"; import useProductTypeDelete from "@dashboard/productTypes/hooks/useProductTypeDelete"; diff --git a/src/products/components/OrderDiscountProviders/OrderDiscountProvider.tsx b/src/products/components/OrderDiscountProviders/OrderDiscountProvider.tsx index b2e3c8ea5e9..fc12f2dc077 100644 --- a/src/products/components/OrderDiscountProviders/OrderDiscountProvider.tsx +++ b/src/products/components/OrderDiscountProviders/OrderDiscountProvider.tsx @@ -7,7 +7,7 @@ import { useOrderDiscountDeleteMutation, useOrderDiscountUpdateMutation, } from "@dashboard/graphql"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { getDefaultNotifierSuccessErrorData } from "@dashboard/hooks/useNotifier/utils"; import { OrderDiscountCommonInput } from "@dashboard/orders/components/OrderDiscountCommonModal/types"; import { createContext } from "react"; diff --git a/src/products/components/OrderDiscountProviders/OrderLineDiscountProvider.tsx b/src/products/components/OrderDiscountProviders/OrderLineDiscountProvider.tsx index c6c6b1ee972..c3262364ff7 100644 --- a/src/products/components/OrderDiscountProviders/OrderLineDiscountProvider.tsx +++ b/src/products/components/OrderDiscountProviders/OrderLineDiscountProvider.tsx @@ -6,7 +6,7 @@ import { useOrderLineDiscountRemoveMutation, useOrderLineDiscountUpdateMutation, } from "@dashboard/graphql"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { getDefaultNotifierSuccessErrorData } from "@dashboard/hooks/useNotifier/utils"; import { getById } from "@dashboard/misc"; import { OrderDiscountCommonInput } from "@dashboard/orders/components/OrderDiscountCommonModal/types"; diff --git a/src/products/views/ProductCreate/ProductCreate.tsx b/src/products/views/ProductCreate/ProductCreate.tsx index 21861acf22f..4f2a944defb 100644 --- a/src/products/views/ProductCreate/ProductCreate.tsx +++ b/src/products/views/ProductCreate/ProductCreate.tsx @@ -21,7 +21,7 @@ import { import { getSearchFetchMoreProps } from "@dashboard/hooks/makeTopLevelSearch/utils"; import useChannels from "@dashboard/hooks/useChannels"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import useShop from "@dashboard/hooks/useShop"; import { getMutationErrors } from "@dashboard/misc"; import ProductCreatePage, { diff --git a/src/products/views/ProductImage.tsx b/src/products/views/ProductImage.tsx index 53ab18418f8..4666e315839 100644 --- a/src/products/views/ProductImage.tsx +++ b/src/products/views/ProductImage.tsx @@ -7,7 +7,7 @@ import { useProductMediaUpdateMutation, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { commonMessages } from "@dashboard/intl"; import { FormattedMessage, useIntl } from "react-intl"; diff --git a/src/products/views/ProductList/ProductList.tsx b/src/products/views/ProductList/ProductList.tsx index d70a908e1b7..5e3639d8f33 100644 --- a/src/products/views/ProductList/ProductList.tsx +++ b/src/products/views/ProductList/ProductList.tsx @@ -28,7 +28,7 @@ import { useFilterHandlers } from "@dashboard/hooks/useFilterHandlers"; import { useFilterPresets } from "@dashboard/hooks/useFilterPresets"; import useListSettings from "@dashboard/hooks/useListSettings"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { usePaginationReset } from "@dashboard/hooks/usePaginationReset"; import usePaginator, { createPaginationState, diff --git a/src/products/views/ProductUpdate/ProductUpdate.tsx b/src/products/views/ProductUpdate/ProductUpdate.tsx index 68c72234032..4e8e75af1b8 100644 --- a/src/products/views/ProductUpdate/ProductUpdate.tsx +++ b/src/products/views/ProductUpdate/ProductUpdate.tsx @@ -18,7 +18,7 @@ import { } from "@dashboard/graphql"; import { getSearchFetchMoreProps } from "@dashboard/hooks/makeTopLevelSearch/utils"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { commonMessages, errorMessages } from "@dashboard/intl"; import { useSearchAttributeValuesSuggestions } from "@dashboard/searches/useAttributeValueSearch"; import useCategorySearch from "@dashboard/searches/useCategorySearch"; diff --git a/src/products/views/ProductUpdate/handlers/useProductUpdateHandler.ts b/src/products/views/ProductUpdate/handlers/useProductUpdateHandler.ts index 84d11db0c4d..cb38d9bbe26 100644 --- a/src/products/views/ProductUpdate/handlers/useProductUpdateHandler.ts +++ b/src/products/views/ProductUpdate/handlers/useProductUpdateHandler.ts @@ -26,7 +26,7 @@ import { useUpdateMetadataMutation, useUpdatePrivateMetadataMutation, } from "@dashboard/graphql"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { commonMessages } from "@dashboard/intl"; import { getMutationErrors } from "@dashboard/misc"; import { ProductUpdateSubmitData } from "@dashboard/products/components/ProductUpdatePage/types"; diff --git a/src/products/views/ProductVariant/ProductVariant.tsx b/src/products/views/ProductVariant/ProductVariant.tsx index 1bdecc88449..31123431335 100644 --- a/src/products/views/ProductVariant/ProductVariant.tsx +++ b/src/products/views/ProductVariant/ProductVariant.tsx @@ -30,7 +30,7 @@ import { useVariantUpdateMutation, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import useOnSetDefaultVariant from "@dashboard/hooks/useOnSetDefaultVariant"; import useShop from "@dashboard/hooks/useShop"; import { commonMessages } from "@dashboard/intl"; diff --git a/src/products/views/ProductVariantCreate.tsx b/src/products/views/ProductVariantCreate.tsx index 896be9b4a01..5d73be19a97 100644 --- a/src/products/views/ProductVariantCreate.tsx +++ b/src/products/views/ProductVariantCreate.tsx @@ -18,7 +18,7 @@ import { useVariantCreateMutation, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import useShop from "@dashboard/hooks/useShop"; import useCategorySearch from "@dashboard/searches/useCategorySearch"; import useCollectionSearch from "@dashboard/searches/useCollectionSearch"; diff --git a/src/refundsSettings/components/RefundsSettingsPage/RefundsSettingsPage.tsx b/src/refundsSettings/components/RefundsSettingsPage/RefundsSettingsPage.tsx index a779e2247a9..ffd9e364b9d 100644 --- a/src/refundsSettings/components/RefundsSettingsPage/RefundsSettingsPage.tsx +++ b/src/refundsSettings/components/RefundsSettingsPage/RefundsSettingsPage.tsx @@ -12,7 +12,7 @@ import { useRefundSettingsUpdateMutation, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { pageCreateUrl } from "@dashboard/modeling/urls"; import { pageTypeAddUrl, pageTypeUrl } from "@dashboard/modelTypes/urls"; import { refundsSettingsPageMessages } from "@dashboard/refundsSettings/components/RefundsSettingsPage/messages"; diff --git a/src/shipping/handlers.ts b/src/shipping/handlers.ts index 3cb50dd7369..3a54deb1a02 100644 --- a/src/shipping/handlers.ts +++ b/src/shipping/handlers.ts @@ -14,7 +14,7 @@ import { useShippingMethodChannelListingUpdateMutation, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { commonMessages } from "@dashboard/intl"; import { extractMutationErrors, getMutationState } from "@dashboard/misc"; import { getParsedDataForJsonStringField } from "@dashboard/utils/richText/misc"; diff --git a/src/shipping/views/RateUpdate.tsx b/src/shipping/views/RateUpdate.tsx index f48d09a6bfd..2dad2053601 100644 --- a/src/shipping/views/RateUpdate.tsx +++ b/src/shipping/views/RateUpdate.tsx @@ -26,7 +26,7 @@ import useBulkActions from "@dashboard/hooks/useBulkActions"; import useChannels from "@dashboard/hooks/useChannels"; import useLocalPaginator, { useLocalPaginationState } from "@dashboard/hooks/useLocalPaginator"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { PaginatorContext } from "@dashboard/hooks/usePaginator"; import { commonMessages, sectionNames } from "@dashboard/intl"; import { getById, getByUnmatchingId } from "@dashboard/misc"; diff --git a/src/shipping/views/ShippingZoneCreate.tsx b/src/shipping/views/ShippingZoneCreate.tsx index c2e9f88c945..67fbcbe8674 100644 --- a/src/shipping/views/ShippingZoneCreate.tsx +++ b/src/shipping/views/ShippingZoneCreate.tsx @@ -1,7 +1,7 @@ // @ts-strict-ignore import { useCreateShippingZoneMutation, useShopCountriesQuery } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import useShop from "@dashboard/hooks/useShop"; import { commonMessages } from "@dashboard/intl"; import { extractMutationErrors } from "@dashboard/misc"; diff --git a/src/shipping/views/ShippingZoneDetails/index.tsx b/src/shipping/views/ShippingZoneDetails/index.tsx index 66150a449c2..96e3efcc776 100644 --- a/src/shipping/views/ShippingZoneDetails/index.tsx +++ b/src/shipping/views/ShippingZoneDetails/index.tsx @@ -18,7 +18,7 @@ import { } from "@dashboard/graphql"; import { useLocalPaginationState } from "@dashboard/hooks/useLocalPaginator"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import useShop from "@dashboard/hooks/useShop"; import { commonMessages } from "@dashboard/intl"; import { diff --git a/src/shipping/views/ShippingZonesList.tsx b/src/shipping/views/ShippingZonesList.tsx index ce492f0a8ef..767c3060f2b 100644 --- a/src/shipping/views/ShippingZonesList.tsx +++ b/src/shipping/views/ShippingZonesList.tsx @@ -7,7 +7,7 @@ import { } from "@dashboard/graphql"; import useListSettings from "@dashboard/hooks/useListSettings"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { usePaginationReset } from "@dashboard/hooks/usePaginationReset"; import usePaginator, { createPaginationState, diff --git a/src/siteSettings/views/index.tsx b/src/siteSettings/views/index.tsx index 3439259556c..f8cc103c758 100644 --- a/src/siteSettings/views/index.tsx +++ b/src/siteSettings/views/index.tsx @@ -4,7 +4,7 @@ import { useShopSettingsUpdateMutation, useSiteSettingsQuery, } from "@dashboard/graphql"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { commonMessages, sectionNames } from "@dashboard/intl"; import { useIntl } from "react-intl"; diff --git a/src/staff/components/StaffPasswordResetDialog/StaffPasswordResetDialog.test.tsx b/src/staff/components/StaffPasswordResetDialog/StaffPasswordResetDialog.test.tsx index 76fda419959..6638f7d843a 100644 --- a/src/staff/components/StaffPasswordResetDialog/StaffPasswordResetDialog.test.tsx +++ b/src/staff/components/StaffPasswordResetDialog/StaffPasswordResetDialog.test.tsx @@ -29,8 +29,7 @@ jest.mock("@dashboard/graphql", () => ({ })); jest.mock("@dashboard/hooks/useNotifier", () => ({ - __esModule: true, - default: jest.fn(() => jest.fn()), + useNotifier: jest.fn(() => jest.fn()), })); jest.mock("@dashboard/auth/utils", () => ({ diff --git a/src/staff/components/StaffPasswordResetDialog/StaffPasswordResetDialog.tsx b/src/staff/components/StaffPasswordResetDialog/StaffPasswordResetDialog.tsx index 6f55585bd68..8299a1360e9 100644 --- a/src/staff/components/StaffPasswordResetDialog/StaffPasswordResetDialog.tsx +++ b/src/staff/components/StaffPasswordResetDialog/StaffPasswordResetDialog.tsx @@ -5,7 +5,7 @@ import BackButton from "@dashboard/components/BackButton"; import { ConfirmButton } from "@dashboard/components/ConfirmButton"; import { DashboardModal } from "@dashboard/components/Modal"; import { useRequestPasswordResetMutation } from "@dashboard/graphql"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { DialogProps } from "@dashboard/types"; import { Box, Input, Paragraph } from "@saleor/macaw-ui-next"; import React from "react"; diff --git a/src/staff/hooks/useProfileOperations.ts b/src/staff/hooks/useProfileOperations.ts index c679f32688c..9df6d82e809 100644 --- a/src/staff/hooks/useProfileOperations.ts +++ b/src/staff/hooks/useProfileOperations.ts @@ -5,7 +5,7 @@ import { useUserAvatarUpdateMutation, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { commonMessages, errorMessages } from "@dashboard/intl"; import { useIntl } from "react-intl"; diff --git a/src/staff/hooks/useStaffUserOperations.ts b/src/staff/hooks/useStaffUserOperations.ts index eb97db3dbe9..285ac9317f1 100644 --- a/src/staff/hooks/useStaffUserOperations.ts +++ b/src/staff/hooks/useStaffUserOperations.ts @@ -1,6 +1,6 @@ import { useStaffMemberDeleteMutation, useStaffMemberUpdateMutation } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { commonMessages } from "@dashboard/intl"; import { useIntl } from "react-intl"; diff --git a/src/staff/views/StaffList/StaffList.tsx b/src/staff/views/StaffList/StaffList.tsx index 7092883a070..ee0d63e1a3c 100644 --- a/src/staff/views/StaffList/StaffList.tsx +++ b/src/staff/views/StaffList/StaffList.tsx @@ -9,7 +9,7 @@ import { useStaffListQuery, useStaffMemberAddMutation } from "@dashboard/graphql import { useFilterPresets } from "@dashboard/hooks/useFilterPresets"; import useListSettings from "@dashboard/hooks/useListSettings"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { usePaginationReset } from "@dashboard/hooks/usePaginationReset"; import usePaginator, { createPaginationState, diff --git a/src/structures/views/MenuDetails/index.tsx b/src/structures/views/MenuDetails/index.tsx index d03f1131df1..9e45db192bf 100644 --- a/src/structures/views/MenuDetails/index.tsx +++ b/src/structures/views/MenuDetails/index.tsx @@ -11,7 +11,7 @@ import { useMenuUpdateMutation, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { pageUrl } from "@dashboard/modeling/urls"; import { languageEntityUrl, TranslatableEntities } from "@dashboard/translations/urls"; import { useCachedLocales } from "@dashboard/translations/useCachedLocales"; diff --git a/src/structures/views/MenuList/MenuList.tsx b/src/structures/views/MenuList/MenuList.tsx index 03bf534afe5..9a7cd6be118 100644 --- a/src/structures/views/MenuList/MenuList.tsx +++ b/src/structures/views/MenuList/MenuList.tsx @@ -10,7 +10,7 @@ import { import useBulkActions from "@dashboard/hooks/useBulkActions"; import useListSettings from "@dashboard/hooks/useListSettings"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { usePaginationReset } from "@dashboard/hooks/usePaginationReset"; import usePaginator, { createPaginationState, diff --git a/src/taxes/views/TaxChannelsList.tsx b/src/taxes/views/TaxChannelsList.tsx index 08fac27743e..e073fa87117 100644 --- a/src/taxes/views/TaxChannelsList.tsx +++ b/src/taxes/views/TaxChannelsList.tsx @@ -4,7 +4,7 @@ import { useTaxConfigurationUpdateMutation, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import useShop from "@dashboard/hooks/useShop"; import { commonMessages } from "@dashboard/intl"; import createDialogActionHandlers from "@dashboard/utils/handlers/dialogActionHandlers"; diff --git a/src/taxes/views/TaxClassesList.tsx b/src/taxes/views/TaxClassesList.tsx index b3052b85b77..47d6c5a65dd 100644 --- a/src/taxes/views/TaxClassesList.tsx +++ b/src/taxes/views/TaxClassesList.tsx @@ -11,7 +11,7 @@ import { useUpdatePrivateMetadataMutation, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { commonMessages } from "@dashboard/intl"; import createMetadataCreateHandler, { CreateMetadataHandlerFunctionResult, diff --git a/src/taxes/views/TaxCountriesList.tsx b/src/taxes/views/TaxCountriesList.tsx index 573f8bbc3a6..a06f1fa5ee8 100644 --- a/src/taxes/views/TaxCountriesList.tsx +++ b/src/taxes/views/TaxCountriesList.tsx @@ -8,7 +8,7 @@ import { useTaxCountryConfigurationUpdateMutation, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import useShop from "@dashboard/hooks/useShop"; import { commonMessages } from "@dashboard/intl"; import createDialogActionHandlers from "@dashboard/utils/handlers/dialogActionHandlers"; diff --git a/src/translations/views/TranslationsAttributes.tsx b/src/translations/views/TranslationsAttributes.tsx index 7d6886ed93a..0ff4cef8520 100644 --- a/src/translations/views/TranslationsAttributes.tsx +++ b/src/translations/views/TranslationsAttributes.tsx @@ -8,7 +8,7 @@ import { import useListSettings from "@dashboard/hooks/useListSettings"; import useLocalPaginator, { useLocalPaginationState } from "@dashboard/hooks/useLocalPaginator"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { PaginatorContext } from "@dashboard/hooks/usePaginator"; import useShop from "@dashboard/hooks/useShop"; import { commonMessages } from "@dashboard/intl"; diff --git a/src/translations/views/TranslationsCategories.tsx b/src/translations/views/TranslationsCategories.tsx index 8f3e87f5945..5eb962c58a9 100644 --- a/src/translations/views/TranslationsCategories.tsx +++ b/src/translations/views/TranslationsCategories.tsx @@ -5,7 +5,7 @@ import { useUpdateCategoryTranslationsMutation, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import useShop from "@dashboard/hooks/useShop"; import { commonMessages } from "@dashboard/intl"; import { extractMutationErrors } from "@dashboard/misc"; diff --git a/src/translations/views/TranslationsCollections.tsx b/src/translations/views/TranslationsCollections.tsx index a09b37f0153..acfce5f8052 100644 --- a/src/translations/views/TranslationsCollections.tsx +++ b/src/translations/views/TranslationsCollections.tsx @@ -5,7 +5,7 @@ import { useUpdateCollectionTranslationsMutation, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import useShop from "@dashboard/hooks/useShop"; import { commonMessages } from "@dashboard/intl"; import { stringifyQs } from "@dashboard/utils/urls"; diff --git a/src/translations/views/TranslationsMenuItem.tsx b/src/translations/views/TranslationsMenuItem.tsx index 54d563ca815..b694fd4479d 100644 --- a/src/translations/views/TranslationsMenuItem.tsx +++ b/src/translations/views/TranslationsMenuItem.tsx @@ -5,7 +5,7 @@ import { useUpdateMenuItemTranslationsMutation, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import useShop from "@dashboard/hooks/useShop"; import { commonMessages } from "@dashboard/intl"; import { extractMutationErrors } from "@dashboard/misc"; diff --git a/src/translations/views/TranslationsPages.tsx b/src/translations/views/TranslationsPages.tsx index c985db236c9..8ca0d9e1abb 100644 --- a/src/translations/views/TranslationsPages.tsx +++ b/src/translations/views/TranslationsPages.tsx @@ -6,7 +6,7 @@ import { useUpdatePageTranslationsMutation, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import useShop from "@dashboard/hooks/useShop"; import { commonMessages } from "@dashboard/intl"; import { extractMutationErrors } from "@dashboard/misc"; diff --git a/src/translations/views/TranslationsProductVariants.tsx b/src/translations/views/TranslationsProductVariants.tsx index ca26db933ad..db739134c25 100644 --- a/src/translations/views/TranslationsProductVariants.tsx +++ b/src/translations/views/TranslationsProductVariants.tsx @@ -6,7 +6,7 @@ import { useUpdateProductVariantTranslationsMutation, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import useShop from "@dashboard/hooks/useShop"; import { commonMessages } from "@dashboard/intl"; import { OutputData } from "@editorjs/editorjs"; diff --git a/src/translations/views/TranslationsProducts.tsx b/src/translations/views/TranslationsProducts.tsx index f0243fb77cc..27a70e08679 100644 --- a/src/translations/views/TranslationsProducts.tsx +++ b/src/translations/views/TranslationsProducts.tsx @@ -6,7 +6,7 @@ import { useUpdateProductTranslationsMutation, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import useShop from "@dashboard/hooks/useShop"; import { commonMessages } from "@dashboard/intl"; import { getMultipleUrlValues, stringifyQs } from "@dashboard/utils/urls"; diff --git a/src/translations/views/TranslationsSales.tsx b/src/translations/views/TranslationsSales.tsx index 6729b146ff0..cb405323007 100644 --- a/src/translations/views/TranslationsSales.tsx +++ b/src/translations/views/TranslationsSales.tsx @@ -5,7 +5,7 @@ import { useUpdateSaleTranslationsMutation, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import useShop from "@dashboard/hooks/useShop"; import { commonMessages } from "@dashboard/intl"; import { extractMutationErrors } from "@dashboard/misc"; diff --git a/src/translations/views/TranslationsShippingMethod.tsx b/src/translations/views/TranslationsShippingMethod.tsx index 4561c7fc0e1..ed2f51e8879 100644 --- a/src/translations/views/TranslationsShippingMethod.tsx +++ b/src/translations/views/TranslationsShippingMethod.tsx @@ -5,7 +5,7 @@ import { useUpdateShippingMethodTranslationsMutation, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import useShop from "@dashboard/hooks/useShop"; import { commonMessages } from "@dashboard/intl"; import { extractMutationErrors } from "@dashboard/misc"; diff --git a/src/translations/views/TranslationsVouchers.tsx b/src/translations/views/TranslationsVouchers.tsx index 0800f80c1d3..bf3ef17e613 100644 --- a/src/translations/views/TranslationsVouchers.tsx +++ b/src/translations/views/TranslationsVouchers.tsx @@ -5,7 +5,7 @@ import { useVoucherTranslationDetailsQuery, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import useShop from "@dashboard/hooks/useShop"; import { commonMessages } from "@dashboard/intl"; import { stringifyQs } from "@dashboard/utils/urls"; diff --git a/src/warehouses/views/WarehouseCreate/WarehouseCreate.tsx b/src/warehouses/views/WarehouseCreate/WarehouseCreate.tsx index 3f5d84d3904..20e838dc961 100644 --- a/src/warehouses/views/WarehouseCreate/WarehouseCreate.tsx +++ b/src/warehouses/views/WarehouseCreate/WarehouseCreate.tsx @@ -1,7 +1,7 @@ import { WindowTitle } from "@dashboard/components/WindowTitle"; import { CountryCode, useWarehouseCreateMutation } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import useShop from "@dashboard/hooks/useShop"; import { commonMessages } from "@dashboard/intl"; import { extractMutationErrors, findValueInEnum, getMutationStatus } from "@dashboard/misc"; diff --git a/src/warehouses/views/WarehouseDetails/WarehouseDetails.tsx b/src/warehouses/views/WarehouseDetails/WarehouseDetails.tsx index b464d020ac5..b08f1b32c61 100644 --- a/src/warehouses/views/WarehouseDetails/WarehouseDetails.tsx +++ b/src/warehouses/views/WarehouseDetails/WarehouseDetails.tsx @@ -7,7 +7,7 @@ import { useWarehouseUpdateMutation, } from "@dashboard/graphql"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import useShop from "@dashboard/hooks/useShop"; import { commonMessages } from "@dashboard/intl"; import { diff --git a/src/warehouses/views/WarehouseList/WarehouseList.tsx b/src/warehouses/views/WarehouseList/WarehouseList.tsx index 4c193fc5fc0..5caf83272f7 100644 --- a/src/warehouses/views/WarehouseList/WarehouseList.tsx +++ b/src/warehouses/views/WarehouseList/WarehouseList.tsx @@ -6,7 +6,7 @@ import { useWarehouseDeleteMutation, useWarehouseListQuery } from "@dashboard/gr import { useFilterPresets } from "@dashboard/hooks/useFilterPresets"; import useListSettings from "@dashboard/hooks/useListSettings"; import useNavigator from "@dashboard/hooks/useNavigator"; -import useNotifier from "@dashboard/hooks/useNotifier"; +import { useNotifier } from "@dashboard/hooks/useNotifier"; import { usePaginationReset } from "@dashboard/hooks/usePaginationReset"; import usePaginator, { createPaginationState, diff --git a/src/welcomePage/WelcomePageSidebar/WelcmePageSidebar.test.tsx b/src/welcomePage/WelcomePageSidebar/WelcmePageSidebar.test.tsx index 991c97bab31..f1cc4eb6379 100644 --- a/src/welcomePage/WelcomePageSidebar/WelcmePageSidebar.test.tsx +++ b/src/welcomePage/WelcomePageSidebar/WelcmePageSidebar.test.tsx @@ -32,8 +32,7 @@ jest.mock("./components/WelcomePageStocksAnalytics/useWelcomePageStocksAnalytics })); jest.mock("@dashboard/hooks/useNotifier", () => ({ - __esModule: true, - default: jest.fn(() => () => undefined), + useNotifier: jest.fn(() => () => undefined), })); afterEach(() => {