From a9f48c492c307ea02ffc3e36068bd5612720bbb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chy=C5=82a?= Date: Wed, 27 Nov 2024 13:12:14 +0100 Subject: [PATCH] Store onboarding state in user metadata (#5280) * feature: Dashboard UI onboarding component * i18n * feature: Dashboard UI onboarding component * i18n * Base logic for store onboarding state in metadata * Fix saving metadata * Wait for user load * Add debouncing * Add test to store * Move ff condition inside onbarding context * Improve loading state from API * Update tests * Add changeset * CR fixes * Update mutation to eliminate problem with permissions --------- Co-authored-by: Wojciech --- .changeset/dirty-bugs-sort.md | 5 + src/components/DevModePanel/DevModePanel.tsx | 4 +- src/custom-apps/views/CustomAppList.tsx | 6 +- src/graphql/hooks.generated.ts | 36 +++++ src/graphql/types.generated.ts | 8 ++ src/index.tsx | 5 +- .../hooks/useOnboardingData.tsx | 4 +- .../onboardingContext/OnboardingContext.tsx | 29 ++-- .../onboardingContext/OnboardingStorage.ts | 33 ----- .../homeOnboarding/onboardingContext/types.ts | 3 +- .../useOnboardingStorage.test.ts | 127 ++++++++++++++++++ .../onboardingContext/useOnboardingStorage.ts | 83 ++++++++++++ src/newHome/mutations.ts | 11 ++ src/orders/views/OrderList/OrderList.tsx | 6 +- .../views/ProductCreate/ProductCreate.tsx | 4 +- src/staff/views/StaffList/StaffList.tsx | 10 +- 16 files changed, 298 insertions(+), 76 deletions(-) create mode 100644 .changeset/dirty-bugs-sort.md delete mode 100644 src/newHome/homeOnboarding/onboardingContext/OnboardingStorage.ts create mode 100644 src/newHome/homeOnboarding/onboardingContext/useOnboardingStorage.test.ts create mode 100644 src/newHome/homeOnboarding/onboardingContext/useOnboardingStorage.ts create mode 100644 src/newHome/mutations.ts diff --git a/.changeset/dirty-bugs-sort.md b/.changeset/dirty-bugs-sort.md new file mode 100644 index 0000000000..23a5b2a57d --- /dev/null +++ b/.changeset/dirty-bugs-sort.md @@ -0,0 +1,5 @@ +--- +"saleor-dashboard": patch +--- + +Onboarding state is now stored in user metadata, that means that onboarding state is persisted between logins on different machines diff --git a/src/components/DevModePanel/DevModePanel.tsx b/src/components/DevModePanel/DevModePanel.tsx index 92d20c9245..fd1aa335d8 100644 --- a/src/components/DevModePanel/DevModePanel.tsx +++ b/src/components/DevModePanel/DevModePanel.tsx @@ -1,7 +1,6 @@ // @ts-strict-ignore import { useDashboardTheme } from "@dashboard/components/GraphiQL/styles"; import { DashboardModal } from "@dashboard/components/Modal"; -import { useFlag } from "@dashboard/featureFlags"; import { useOnboarding } from "@dashboard/newHome/homeOnboarding/onboardingContext"; import { createGraphiQLFetcher, FetcherOpts, FetcherParams } from "@graphiql/toolkit"; import { createFetch } from "@saleor/sdk"; @@ -18,14 +17,13 @@ export const DevModePanel: React.FC = () => { const intl = useIntl(); const { rootStyle } = useDashboardTheme(); const { markOnboardingStepAsCompleted } = useOnboarding(); - const newHomePageFlag = useFlag("new_home_page"); const { isDevModeVisible, variables, devModeContent, setDevModeVisibility } = useDevModeContext(); const baseFetcher = createGraphiQLFetcher({ url: process.env.API_URL, fetch: authorizedFetch, }); const fetcher = async (graphQLParams: FetcherParams, opts: FetcherOpts) => { - if (graphQLParams.operationName !== "IntrospectionQuery" && newHomePageFlag.enabled) { + if (graphQLParams.operationName !== "IntrospectionQuery") { markOnboardingStepAsCompleted("graphql-playground"); } diff --git a/src/custom-apps/views/CustomAppList.tsx b/src/custom-apps/views/CustomAppList.tsx index 021b6eb56c..3b81a63b53 100644 --- a/src/custom-apps/views/CustomAppList.tsx +++ b/src/custom-apps/views/CustomAppList.tsx @@ -3,7 +3,6 @@ import { useApolloClient } from "@apollo/client"; import AppDeleteDialog from "@dashboard/apps/components/AppDeleteDialog"; import { EXTENSION_LIST_QUERY } from "@dashboard/apps/queries"; import { WindowTitle } from "@dashboard/components/WindowTitle"; -import { useFlag } from "@dashboard/featureFlags"; import { AppSortField, AppTypeEnum, @@ -35,12 +34,9 @@ export const CustomAppList: React.FC = ({ params }) => { const intl = useIntl(); const client = useApolloClient(); const { markOnboardingStepAsCompleted } = useOnboarding(); - const newHomePageFlag = useFlag("new_home_page"); useEffect(() => { - if (newHomePageFlag) { - markOnboardingStepAsCompleted("view-webhooks"); - } + markOnboardingStepAsCompleted("view-webhooks"); }, []); const [openModal, closeModal] = createDialogActionHandlers< diff --git a/src/graphql/hooks.generated.ts b/src/graphql/hooks.generated.ts index 6f34781fb1..e271c89973 100644 --- a/src/graphql/hooks.generated.ts +++ b/src/graphql/hooks.generated.ts @@ -10148,6 +10148,42 @@ export function useMenuDetailsLazyQuery(baseOptions?: ApolloReactHooks.LazyQuery export type MenuDetailsQueryHookResult = ReturnType; export type MenuDetailsLazyQueryHookResult = ReturnType; export type MenuDetailsQueryResult = Apollo.QueryResult; +export const UpdateUserMetadataDocument = gql` + mutation UpdateUserMetadata($id: ID!, $input: [MetadataInput!]!) { + updateMetadata(id: $id, input: $input) { + errors { + ...MetadataError + } + } +} + ${MetadataErrorFragmentDoc}`; +export type UpdateUserMetadataMutationFn = Apollo.MutationFunction; + +/** + * __useUpdateUserMetadataMutation__ + * + * To run a mutation, you first call `useUpdateUserMetadataMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useUpdateUserMetadataMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [updateUserMetadataMutation, { data, loading, error }] = useUpdateUserMetadataMutation({ + * variables: { + * id: // value for 'id' + * input: // value for 'input' + * }, + * }); + */ +export function useUpdateUserMetadataMutation(baseOptions?: ApolloReactHooks.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return ApolloReactHooks.useMutation(UpdateUserMetadataDocument, options); + } +export type UpdateUserMetadataMutationHookResult = ReturnType; +export type UpdateUserMetadataMutationResult = Apollo.MutationResult; +export type UpdateUserMetadataMutationOptions = Apollo.BaseMutationOptions; export const WelcomePageActivitiesDocument = gql` query WelcomePageActivities($hasPermissionToManageOrders: Boolean!) { activities: homepageEvents(last: 10) @include(if: $hasPermissionToManageOrders) { diff --git a/src/graphql/types.generated.ts b/src/graphql/types.generated.ts index 2e61ff84f3..8a781f161f 100644 --- a/src/graphql/types.generated.ts +++ b/src/graphql/types.generated.ts @@ -10745,6 +10745,14 @@ export type MenuDetailsQueryVariables = Exact<{ export type MenuDetailsQuery = { __typename: 'Query', menu: { __typename: 'Menu', id: string, name: string, items: Array<{ __typename: 'MenuItem', id: string, level: number, name: string, url: string | null, children: Array<{ __typename: 'MenuItem', id: string, level: number, name: string, url: string | null, children: Array<{ __typename: 'MenuItem', id: string, level: number, name: string, url: string | null, children: Array<{ __typename: 'MenuItem', id: string, level: number, name: string, url: string | null, children: Array<{ __typename: 'MenuItem', id: string, level: number, name: string, url: string | null, children: Array<{ __typename: 'MenuItem', id: string, level: number, name: string, url: string | null, children: Array<{ __typename: 'MenuItem', id: string, level: number, name: string, url: string | null, category: { __typename: 'Category', id: string, name: string } | null, collection: { __typename: 'Collection', id: string, name: string } | null, page: { __typename: 'Page', id: string, title: string } | null }> | null, category: { __typename: 'Category', id: string, name: string } | null, collection: { __typename: 'Collection', id: string, name: string } | null, page: { __typename: 'Page', id: string, title: string } | null }> | null, category: { __typename: 'Category', id: string, name: string } | null, collection: { __typename: 'Collection', id: string, name: string } | null, page: { __typename: 'Page', id: string, title: string } | null }> | null, category: { __typename: 'Category', id: string, name: string } | null, collection: { __typename: 'Collection', id: string, name: string } | null, page: { __typename: 'Page', id: string, title: string } | null }> | null, category: { __typename: 'Category', id: string, name: string } | null, collection: { __typename: 'Collection', id: string, name: string } | null, page: { __typename: 'Page', id: string, title: string } | null }> | null, category: { __typename: 'Category', id: string, name: string } | null, collection: { __typename: 'Collection', id: string, name: string } | null, page: { __typename: 'Page', id: string, title: string } | null }> | null, category: { __typename: 'Category', id: string, name: string } | null, collection: { __typename: 'Collection', id: string, name: string } | null, page: { __typename: 'Page', id: string, title: string } | null }> | null } | null }; +export type UpdateUserMetadataMutationVariables = Exact<{ + id: Scalars['ID']; + input: Array | MetadataInput; +}>; + + +export type UpdateUserMetadataMutation = { __typename: 'Mutation', updateMetadata: { __typename: 'UpdateMetadata', errors: Array<{ __typename: 'MetadataError', code: MetadataErrorCode, field: string | null, message: string | null }> } | null }; + export type WelcomePageActivitiesQueryVariables = Exact<{ hasPermissionToManageOrders: Scalars['Boolean']; }>; diff --git a/src/index.tsx b/src/index.tsx index 99d4cf8e8b..bd8214cef4 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -64,7 +64,6 @@ import NavigationSection from "./navigation"; import { navigationSection } from "./navigation/urls"; import { HomePage } from "./newHome"; import { OnboardingProvider } from "./newHome/homeOnboarding/onboardingContext/OnboardingContext"; -import { OnboardingStorage } from "./newHome/homeOnboarding/onboardingContext/OnboardingStorage"; import { NotFound } from "./NotFound"; import OrdersSection from "./orders"; import PageSection from "./pages"; @@ -89,8 +88,6 @@ if (GTM_ID) { errorTracker.init(history); -const onboardingStorage = new OnboardingStorage(); - /* Handle legacy theming toggle. Since we use new and old macaw, we need to handle both theme swticher for a while. @@ -129,7 +126,7 @@ const App: React.FC = () => ( - + diff --git a/src/newHome/homeOnboarding/hooks/useOnboardingData.tsx b/src/newHome/homeOnboarding/hooks/useOnboardingData.tsx index 02ccc651e5..f08ec7af26 100644 --- a/src/newHome/homeOnboarding/hooks/useOnboardingData.tsx +++ b/src/newHome/homeOnboarding/hooks/useOnboardingData.tsx @@ -181,9 +181,7 @@ export const useOnboardingData = () => { const steps = getStepsData({ intl, isStepCompleted: (step: OnboardingStepsIDs) => onboardingState.stepsCompleted.includes(step), - onStepComplete: (step: OnboardingStepsIDs) => { - markOnboardingStepAsCompleted(step); - }, + onStepComplete: markOnboardingStepAsCompleted, }); return { diff --git a/src/newHome/homeOnboarding/onboardingContext/OnboardingContext.tsx b/src/newHome/homeOnboarding/onboardingContext/OnboardingContext.tsx index ce15815a6c..a83f231bc5 100644 --- a/src/newHome/homeOnboarding/onboardingContext/OnboardingContext.tsx +++ b/src/newHome/homeOnboarding/onboardingContext/OnboardingContext.tsx @@ -1,8 +1,9 @@ +import { useFlag } from "@dashboard/featureFlags"; import { handleStateChangeAfterStepCompleted, handleStateChangeAfterToggle, } from "@dashboard/newHome/homeOnboarding/onboardingContext/utils"; -import React from "react"; +import React, { useRef } from "react"; import { useNewUserCheck } from "../hooks/useNewUserCheck"; import { @@ -17,47 +18,53 @@ import { OnboardingStepsIDs, } from "./types"; import { useExpandedOnboardingId } from "./useExpandedOnboardingId"; +import { useOnboardingStorage } from "./useOnboardingStorage"; const OnboardingContext = React.createContext(null); -export const OnboardingProvider = ({ children, storageService }: OnboardingProviderProps) => { +export const OnboardingProvider = ({ children }: OnboardingProviderProps) => { const [onboardingState, setOnboardingState] = React.useState({ onboardingExpanded: true, stepsCompleted: [], stepsExpanded: {} as OnboardingState["stepsExpanded"], }); - const [loaded, setLoaded] = React.useState(false); + const loaded = useRef(false); const { isNewUser, isUserLoading } = useNewUserCheck(); + const newHomePageFlag = useFlag("new_home_page"); + + const storageService = useOnboardingStorage(); React.useEffect(() => { - if (loaded || isUserLoading) return; + if (loaded.current || isUserLoading) return; - const onboardingStateLS = storageService.getOnboardingState(); + const onboardingStateFromUserMetadata = storageService.getOnboardingState(); // When first time load there is not data in local storage, so use initial state - if (!onboardingStateLS) { + if (!onboardingStateFromUserMetadata) { setOnboardingState(getInitialOnboardingState(isNewUser)); } else { - setOnboardingState(onboardingStateLS); + setOnboardingState(onboardingStateFromUserMetadata); } - setLoaded(true); + loaded.current = true; }, [isNewUser, isUserLoading, loaded, storageService]); React.useEffect(() => { - if (loaded) { + if (loaded.current) { storageService.saveOnboardingState(onboardingState); } - }, [loaded, onboardingState, storageService]); + }, [onboardingState]); // For old users, onboarding is always completed, for new one we need to calculate it const isOnboardingCompleted = isNewUser ? onboardingState.stepsCompleted.length === TOTAL_STEPS_COUNT : true; - const extendedStepId = useExpandedOnboardingId(onboardingState, loaded); + const extendedStepId = useExpandedOnboardingId(onboardingState, loaded.current); const markOnboardingStepAsCompleted = (id: OnboardingStepsIDs) => { + if (!newHomePageFlag.enabled || onboardingState.stepsCompleted.includes(id)) return; + setOnboardingState(prevOnboardingState => handleStateChangeAfterStepCompleted(prevOnboardingState, id), ); diff --git a/src/newHome/homeOnboarding/onboardingContext/OnboardingStorage.ts b/src/newHome/homeOnboarding/onboardingContext/OnboardingStorage.ts deleted file mode 100644 index 8ae9a06b1c..0000000000 --- a/src/newHome/homeOnboarding/onboardingContext/OnboardingStorage.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { OnboardingState, StorageService } from "./types"; - -const ONBOARDING_STATE_KEY = "onboardingState"; - -export class OnboardingStorage implements StorageService { - getOnboardingState() { - try { - const onboardingState = localStorage.getItem(ONBOARDING_STATE_KEY); - - if (!onboardingState) { - return undefined; - } - - const parsed = JSON.parse(onboardingState); - - return parsed; - } catch (error) { - // eslint-disable-next-line no-console - console.warn("Could not get onboarding state from localStorage", { error }); - - return undefined; - } - } - - saveOnboardingState(onboardingState: OnboardingState) { - try { - localStorage.setItem(ONBOARDING_STATE_KEY, JSON.stringify(onboardingState)); - } catch (error) { - // eslint-disable-next-line no-console - console.warn("Could not save onboarding state to localStorage"); - } - } -} diff --git a/src/newHome/homeOnboarding/onboardingContext/types.ts b/src/newHome/homeOnboarding/onboardingContext/types.ts index 4ad0d325cb..56c3f182d4 100644 --- a/src/newHome/homeOnboarding/onboardingContext/types.ts +++ b/src/newHome/homeOnboarding/onboardingContext/types.ts @@ -22,7 +22,7 @@ export type OnboardingState = { export interface StorageService { getOnboardingState(): OnboardingState | undefined; - saveOnboardingState(onboardingState: OnboardingState): void; + saveOnboardingState(onboardingState: OnboardingState): Promise; } export interface OnboardingContextType { @@ -38,5 +38,4 @@ export interface OnboardingContextType { export interface OnboardingProviderProps { children: React.ReactNode; - storageService: StorageService; } diff --git a/src/newHome/homeOnboarding/onboardingContext/useOnboardingStorage.test.ts b/src/newHome/homeOnboarding/onboardingContext/useOnboardingStorage.test.ts new file mode 100644 index 0000000000..2b9f15555a --- /dev/null +++ b/src/newHome/homeOnboarding/onboardingContext/useOnboardingStorage.test.ts @@ -0,0 +1,127 @@ +import { useUser } from "@dashboard/auth"; +import { useUpdateUserMetadataMutation } from "@dashboard/graphql"; +import { OnboardingStepsIDs } from "@dashboard/newHome/homeOnboarding/onboardingContext/types"; +import { act } from "@testing-library/react"; +import { renderHook } from "@testing-library/react-hooks"; + +import { useOnboardingStorage } from "./useOnboardingStorage"; + +jest.mock("@dashboard/auth", () => ({ + __esModule: true, + useUser: jest.fn(), +})); + +jest.mock("@dashboard/graphql"); + +jest.useFakeTimers(); + +jest.mock("lodash/debounce", () => jest.fn(fn => fn)); + +describe("useOnboardingStorage", () => { + describe("getOnboardingState", () => { + it("should return undefined when there is no onboarding in user metadata", () => { + // Arrange + (useUser as jest.Mock).mockImplementation(() => ({ + user: { metadata: [{ key1: "value1" }, { key2: "value2" }] }, + })); + (useUpdateUserMetadataMutation as jest.Mock).mockReturnValue([jest.fn(), {}]); + + const { getOnboardingState } = renderHook(() => useOnboardingStorage()).result.current; + + // Act + const result = getOnboardingState(); + + // Assert + expect(result).toBeUndefined(); + }); + + it("should return onboarding state from user metadata", () => { + // Arrange + (useUser as jest.Mock).mockImplementation(() => ({ + user: { + metadata: [ + { + key: "onboarding", + value: JSON.stringify({ steps: [], onboardingExpanded: true }), + }, + ], + }, + })); + (useUpdateUserMetadataMutation as jest.Mock).mockReturnValue([jest.fn(), {}]); + + const { getOnboardingState } = renderHook(() => useOnboardingStorage()).result.current; + + // Act + const result = getOnboardingState(); + + // Assert + expect(result).toEqual({ steps: [], onboardingExpanded: true }); + }); + }); + + describe("saveOnboardingState", () => { + it("should not save onboarding state when there is no user", async () => { + // Arrange + (useUser as jest.Mock).mockImplementation(() => ({ user: null })); + + const updateMetadataMock = jest.fn(); + + (useUpdateUserMetadataMutation as jest.Mock).mockReturnValue([updateMetadataMock, {}]); + + const { result } = renderHook(() => useOnboardingStorage()); + + // Act + const returnValue = await act(async () => { + return await result.current.saveOnboardingState({ + stepsCompleted: [], + stepsExpanded: {} as Record, + onboardingExpanded: true, + }); + }); + + // Assert + expect(returnValue).toBeUndefined(); + expect(updateMetadataMock).not.toHaveBeenCalled(); + }); + + it("should save onboarding state to user metadata and be called only once", async () => { + // Arrange + (useUser as jest.Mock).mockImplementation(() => ({ user: { id: "1", metadata: [] } })); + + const updateMetadataMock = jest.fn(); + + (useUpdateUserMetadataMutation as jest.Mock).mockReturnValue([updateMetadataMock, {}]); + + const { result } = renderHook(() => useOnboardingStorage()); + + // Act + await act(async () => { + await result.current.saveOnboardingState({ + stepsCompleted: [], + stepsExpanded: {} as Record, + onboardingExpanded: true, + }); + }); + + jest.runAllTimers(); + + // Assert + expect(updateMetadataMock).toHaveBeenCalledTimes(1); + expect(updateMetadataMock).toHaveBeenCalledWith({ + variables: { + id: "1", + input: [ + { + key: "onboarding", + value: JSON.stringify({ + stepsCompleted: [], + stepsExpanded: {} as Record, + onboardingExpanded: true, + }), + }, + ], + }, + }); + }); + }); +}); diff --git a/src/newHome/homeOnboarding/onboardingContext/useOnboardingStorage.ts b/src/newHome/homeOnboarding/onboardingContext/useOnboardingStorage.ts new file mode 100644 index 0000000000..b8d8fa2f3f --- /dev/null +++ b/src/newHome/homeOnboarding/onboardingContext/useOnboardingStorage.ts @@ -0,0 +1,83 @@ +import { useUser } from "@dashboard/auth"; +import { MetadataInput, useUpdateUserMetadataMutation } from "@dashboard/graphql"; +import { + OnboardingState, + StorageService, +} from "@dashboard/newHome/homeOnboarding/onboardingContext/types"; +import debounce from "lodash/debounce"; +import { useCallback, useMemo } from "react"; + +const METADATA_KEY = "onboarding"; + +export const useOnboardingStorage = (): StorageService => { + const { user } = useUser(); + const [updateMetadata] = useUpdateUserMetadataMutation({}); + + const getOnboardingState: StorageService["getOnboardingState"] = () => { + try { + const metadata = user?.metadata.find(m => m.key === METADATA_KEY); + + if (!metadata) { + return undefined; + } + + return JSON.parse(metadata.value); + } catch (error) { + // eslint-disable-next-line no-console + console.warn("Could not get onboarding state from metadata", { error }); + + return undefined; + } + }; + + const saveOnboardingState: StorageService["saveOnboardingState"] = useCallback( + async (onboardingState: OnboardingState) => { + if (!user) { + return; + } + + try { + const userMetadata: MetadataInput[] = + user?.metadata?.map(data => ({ + key: data.key, + value: data.value, + })) ?? []; + const metadataValue = JSON.stringify(onboardingState); + const metadataIndex = userMetadata.findIndex(m => m.key === METADATA_KEY); + + if (metadataIndex !== -1) { + userMetadata[metadataIndex] = { + key: METADATA_KEY, + value: metadataValue, + }; + } else { + userMetadata.push({ + key: METADATA_KEY, + value: metadataValue, + }); + } + + await updateMetadata({ + variables: { + id: user.id, + input: userMetadata, + }, + }); + } catch (error) { + // eslint-disable-next-line no-console + console.warn("Could not save onboarding state to metadata"); + } + }, + [updateMetadata, user], + ); + + const debouncedSaveOnboardingState = useMemo( + () => debounce(saveOnboardingState, 1000), + [saveOnboardingState], + ) as StorageService["saveOnboardingState"]; + + return { + getOnboardingState, + saveOnboardingState: debouncedSaveOnboardingState, + }; +}; diff --git a/src/newHome/mutations.ts b/src/newHome/mutations.ts new file mode 100644 index 0000000000..11e4f5221a --- /dev/null +++ b/src/newHome/mutations.ts @@ -0,0 +1,11 @@ +import { gql } from "@apollo/client"; + +export const updateUserMetadata = gql` + mutation UpdateUserMetadata($id: ID!, $input: [MetadataInput!]!) { + updateMetadata(id: $id, input: $input) { + errors { + ...MetadataError + } + } + } +`; diff --git a/src/orders/views/OrderList/OrderList.tsx b/src/orders/views/OrderList/OrderList.tsx index 5a4803e901..a93cf9d168 100644 --- a/src/orders/views/OrderList/OrderList.tsx +++ b/src/orders/views/OrderList/OrderList.tsx @@ -6,7 +6,6 @@ import { useConditionalFilterContext } from "@dashboard/components/ConditionalFi import DeleteFilterTabDialog from "@dashboard/components/DeleteFilterTabDialog"; import SaveFilterTabDialog from "@dashboard/components/SaveFilterTabDialog"; import { useShopLimitsQuery } from "@dashboard/components/Shop/queries"; -import { useFlag } from "@dashboard/featureFlags"; import { useOrderDraftCreateMutation, useOrderListQuery } from "@dashboard/graphql"; import { useFilterHandlers } from "@dashboard/hooks/useFilterHandlers"; import { useFilterPresets } from "@dashboard/hooks/useFilterPresets"; @@ -49,12 +48,9 @@ export const OrderList: React.FC = ({ params }) => { const { valueProvider } = useConditionalFilterContext(); const { markOnboardingStepAsCompleted } = useOnboarding(); - const newHomePageFlag = useFlag("new_home_page"); useEffect(() => { - if (newHomePageFlag) { - markOnboardingStepAsCompleted("explore-orders"); - } + markOnboardingStepAsCompleted("explore-orders"); }, []); const { diff --git a/src/products/views/ProductCreate/ProductCreate.tsx b/src/products/views/ProductCreate/ProductCreate.tsx index 54ef9dbc21..af2329a6af 100644 --- a/src/products/views/ProductCreate/ProductCreate.tsx +++ b/src/products/views/ProductCreate/ProductCreate.tsx @@ -5,7 +5,6 @@ import { AttributeInput } from "@dashboard/components/Attributes"; import ChannelsAvailabilityDialog from "@dashboard/components/ChannelsAvailabilityDialog"; import { WindowTitle } from "@dashboard/components/WindowTitle"; import { DEFAULT_INITIAL_SEARCH_DATA, VALUES_PAGINATE_BY } from "@dashboard/config"; -import { useFlag } from "@dashboard/featureFlags"; import { ProductChannelListingErrorFragment, ProductErrorWithAttributesFragment, @@ -62,7 +61,6 @@ export const ProductCreateView: React.FC = ({ params }) => { const notify = useNotifier(); const shop = useShop(); const { markOnboardingStepAsCompleted } = useOnboarding(); - const newHomePageFlag = useFlag("new_home_page"); const intl = useIntl(); const [productCreateComplete, setProductCreateComplete] = React.useState(false); const selectedProductTypeId = params["product-type-id"]; @@ -211,7 +209,7 @@ export const ProductCreateView: React.FC = ({ params }) => { )(data); if (!errors?.length) { - newHomePageFlag.enabled && markOnboardingStepAsCompleted("create-product"); + markOnboardingStepAsCompleted("create-product"); setProductCreateComplete(true); } diff --git a/src/staff/views/StaffList/StaffList.tsx b/src/staff/views/StaffList/StaffList.tsx index d24ae2d086..cf476f2882 100644 --- a/src/staff/views/StaffList/StaffList.tsx +++ b/src/staff/views/StaffList/StaffList.tsx @@ -3,7 +3,6 @@ import DeleteFilterTabDialog from "@dashboard/components/DeleteFilterTabDialog"; import SaveFilterTabDialog from "@dashboard/components/SaveFilterTabDialog"; import { useShopLimitsQuery } from "@dashboard/components/Shop/queries"; import { DEFAULT_INITIAL_SEARCH_DATA } from "@dashboard/config"; -import { useFlag } from "@dashboard/featureFlags"; import { useStaffListQuery, useStaffMemberAddMutation } from "@dashboard/graphql"; import { useFilterPresets } from "@dashboard/hooks/useFilterPresets"; import useListSettings from "@dashboard/hooks/useListSettings"; @@ -49,7 +48,6 @@ export const StaffList: React.FC = ({ params }) => { const { updateListSettings, settings } = useListSettings(ListViews.STAFF_MEMBERS_LIST); const intl = useIntl(); const { markOnboardingStepAsCompleted } = useOnboarding(); - const newHomePageFlag = useFlag("new_home_page"); usePaginationReset(staffListUrl, params, settings.rowNumber); @@ -74,6 +72,7 @@ export const StaffList: React.FC = ({ params }) => { const [addStaffMember, addStaffMemberData] = useStaffMemberAddMutation({ onCompleted: data => { if (data?.staffCreate?.errors?.length === 0) { + markOnboardingStepAsCompleted("invite-staff"); notify({ status: "success", text: intl.formatMessage(commonMessages.savedChanges), @@ -121,10 +120,8 @@ export const StaffList: React.FC = ({ params }) => { } = usePermissionGroupSearch({ variables: DEFAULT_INITIAL_SEARCH_DATA, }); - const handleStaffMemberAdd = (variables: AddMemberFormData) => { - newHomePageFlag.enabled && markOnboardingStepAsCompleted("invite-staff"); - - return addStaffMember({ + const handleStaffMemberAdd = (variables: AddMemberFormData) => + addStaffMember({ variables: { input: { addGroups: variables.permissionGroups, @@ -139,7 +136,6 @@ export const StaffList: React.FC = ({ params }) => { }, }, }); - }; return (