Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Home onboarding logic with env setup #5274

Merged
merged 33 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
08722ad
feature: Dashboard UI onboarding component
Cloud11PL Nov 19, 2024
588683f
i18n
Cloud11PL Nov 19, 2024
da8228b
feature: Dashboard UI onboarding component
Cloud11PL Nov 20, 2024
e82de3d
i18n
Cloud11PL Nov 20, 2024
f56f3d0
Merge branch 'main' into MERX-1262-onboarding-component-accordion
michalina-graczyk Nov 20, 2024
b821746
Merge branch 'main' into MERX-1262-onboarding-component-accordion
michalina-graczyk Nov 20, 2024
613263b
Fetch dateJoined from user query
poulch Nov 21, 2024
15146c5
Add handle check threshold date for new users
poulch Nov 21, 2024
53325b4
Refactor onboarding logic
poulch Nov 21, 2024
354a38e
Add onboarding step complete triggers
poulch Nov 22, 2024
c6c4736
Add permissions checks to buttons
poulch Nov 22, 2024
04c06de
Fix links in buttons
poulch Nov 22, 2024
bee45ef
Fix test and improve logic
poulch Nov 22, 2024
14e007f
add test to step modifications and small refactor
poulch Nov 22, 2024
c8679af
add toggle handling when step exists during toggling
poulch Nov 22, 2024
ba9375d
Add example env
poulch Nov 22, 2024
d5bc4d6
Improve toggle accordion logic and tests
poulch Nov 23, 2024
8f03937
Withdraw auth changes
poulch Nov 23, 2024
211affd
Add changeset
poulch Nov 23, 2024
b712dde
Extract messages
poulch Nov 23, 2024
1e401d3
Simplify code
poulch Nov 23, 2024
34cb229
Final fixes, refactors and tests
poulch Nov 24, 2024
80450cd
Fix calulcate expanded id
poulch Nov 24, 2024
b42f485
Merge branch 'main' into merx-1263-onboarding-state
poulch Nov 25, 2024
f61021e
Add ONBOARDING_USER_JOINED_DATE_THRESHOLD to workflow
poulch Nov 25, 2024
a2b2db5
Fix include
poulch Nov 25, 2024
ef2346e
Extract messages
poulch Nov 25, 2024
acec794
Use vars instead of secrets
poulch Nov 25, 2024
a983c02
Merge branch 'main' into merx-1263-onboarding-state
poulch Nov 25, 2024
ef10a3a
Merge branch 'main' into merx-1263-onboarding-state
poulch Nov 25, 2024
4244f08
Remove env from pipelines
poulch Nov 25, 2024
60dd7d5
Add fallback to env date
poulch Nov 25, 2024
1e1d72c
Remove duplicated useOnboardingData.tsx
poulch Nov 26, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fresh-ears-buy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"saleor-dashboard": patch
---

User onboardng steps are now checking when user does required actions
4 changes: 3 additions & 1 deletion .env.template
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ MAILPITURL=xxxx #For playwright
E2E_USER_NAME=xxxx
E2E_USER_PASSWORD=xxxx
E2E_PERMISSIONS_USERS_PASSWORD=xxxx
BASE_URL=http://localhost:9000/
BASE_URL=http://localhost:9000/

ONBOARDING_USER_JOINED_DATE_THRESHOLD=2024-07-01
1 change: 1 addition & 0 deletions .github/workflows/deploy-cloud.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ jobs:
IS_CLOUD_INSTANCE: true
POSTHOG_KEY: ${{ secrets.POSTHOG_KEY }}
POSTHOG_HOST: ${{ secrets.POSTHOG_HOST }}
ONBOARDING_USER_JOINED_DATE_THRESHOLD: ${{ secrets.ONBOARDING_USER_JOINED_DATE_THRESHOLD }}
poulch marked this conversation as resolved.
Show resolved Hide resolved
steps:
- name: Check region
if: ${{ !contains(fromJSON('["eu", "us"]'), env.REGION) }}
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/deploy-dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ jobs:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
APPS_MARKETPLACE_API_URL: "https://apps.staging.saleor.io/api/v2/saleor-apps"
IS_CLOUD_INSTANCE: true
ONBOARDING_USER_JOINED_DATE_THRESHOLD: ${{ secrets.ONBOARDING_USER_JOINED_DATE_THRESHOLD }}
steps:
- uses: actions/checkout@v2
with:
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/deploy-master-staging.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ jobs:
IS_CLOUD_INSTANCE: true
POSTHOG_KEY: ${{ secrets.POSTHOG_KEY }}
POSTHOG_HOST: ${{ secrets.POSTHOG_HOST }}
ONBOARDING_USER_JOINED_DATE_THRESHOLD: ${{ secrets.ONBOARDING_USER_JOINED_DATE_THRESHOLD }}
steps:
- uses: actions/checkout@v2
- name: Set custom version
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/deploy-staging-and-prepare-release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ jobs:
IS_CLOUD_INSTANCE: true
POSTHOG_KEY: ${{ secrets.POSTHOG_KEY }}
POSTHOG_HOST: ${{ secrets.POSTHOG_HOST }}
ONBOARDING_USER_JOINED_DATE_THRESHOLD: ${{ secrets.ONBOARDING_USER_JOINED_DATE_THRESHOLD }}
steps:
- uses: actions/checkout@v4
with:
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/pr-automation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ jobs:
APP_MOUNT_URI: /
STATIC_URL: /
IS_CLOUD_INSTANCE: true
ONBOARDING_USER_JOINED_DATE_THRESHOLD: ${{ secrets.ONBOARDING_USER_JOINED_DATE_THRESHOLD }}
run: npm run build

- name: Configure AWS credentials
Expand Down
14 changes: 10 additions & 4 deletions locale/defaultMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -3474,6 +3474,9 @@
"context": "tooltip",
"string": "This feature is in a preview state and can be subject to changes at later point"
},
"KHI/qv": {
"string": "You don't have permission to manage products"
},
"KHZlmi": {
"string": "Discount Type"
},
Expand Down Expand Up @@ -4492,10 +4495,6 @@
"context": "info text",
"string": "Set up an end date of preorder. When end date will be reached product will be automatically taken from preorder to standard selling"
},
"RFXT9O": {
"context": "tooltip message",
"string": "You don't have permission to invite staff members"
},
"RH+aOF": {
"context": "use attribute in filtering",
"string": "Use in Filtering"
Expand Down Expand Up @@ -6879,6 +6878,10 @@
"grkY2V": {
"string": "You don't have access to any channels"
},
"gt05TH": {
"context": "tooltip message",
"string": "You don't have permission to manage staff"
},
"gvOzOl": {
"string": "Page Title"
},
Expand Down Expand Up @@ -9381,6 +9384,9 @@
"context": "dialog title",
"string": "Delete category"
},
"xol6jX": {
"string": "You don't have permission to manage orders"
},
"xoyCZ/": {
"context": "error message",
"string": "Improper value"
Expand Down
17 changes: 15 additions & 2 deletions src/components/DevModePanel/DevModePanel.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// @ts-strict-ignore
import { useDashboardTheme } from "@dashboard/components/GraphiQL/styles";
import { DashboardModal } from "@dashboard/components/Modal";
import { createGraphiQLFetcher } from "@graphiql/toolkit";
import { useFlag } from "@dashboard/featureFlags";
import { useOnboarding } from "@dashboard/newHome/homeOnboarding/onboardingContext";
import { createGraphiQLFetcher, FetcherOpts, FetcherParams } from "@graphiql/toolkit";
import { createFetch } from "@saleor/sdk";
import React from "react";
import { useIntl } from "react-intl";
Expand All @@ -15,11 +17,22 @@ const authorizedFetch = createFetch();
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 fetcher = createGraphiQLFetcher({
const baseFetcher = createGraphiQLFetcher({
url: process.env.API_URL,
fetch: authorizedFetch,
});
const fetcher = async (graphQLParams: FetcherParams, opts: FetcherOpts) => {
if (graphQLParams.operationName !== "IntrospectionQuery" && newHomePageFlag.enabled) {
markOnboardingStepAsCompleted("graphql-playground");
}

const result = await baseFetcher(graphQLParams, opts); // Call the base fetcher

return result;
};
const overwriteCodeMirrorCSSVariables = {
__html: `
.graphiql-container, .CodeMirror-info, .CodeMirror-lint-tooltip, reach-portal{
Expand Down
13 changes: 12 additions & 1 deletion src/custom-apps/views/CustomAppList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ 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,
Expand All @@ -14,9 +15,10 @@ import useNavigator from "@dashboard/hooks/useNavigator";
import useNotifier from "@dashboard/hooks/useNotifier";
import { sectionNames } from "@dashboard/intl";
import { findById } from "@dashboard/misc";
import { useOnboarding } from "@dashboard/newHome/homeOnboarding/onboardingContext";
import createDialogActionHandlers from "@dashboard/utils/handlers/dialogActionHandlers";
import { mapEdgesToItems } from "@dashboard/utils/maps";
import React from "react";
import React, { useEffect } from "react";
import { useIntl } from "react-intl";

import CustomAppListPage from "../components/CustomAppListPage";
Expand All @@ -32,6 +34,15 @@ export const CustomAppList: React.FC<CustomAppListProps> = ({ params }) => {
const notify = useNotifier();
const intl = useIntl();
const client = useApolloClient();
const { markOnboardingStepAsCompleted } = useOnboarding();
const newHomePageFlag = useFlag("new_home_page");

useEffect(() => {
if (newHomePageFlag) {
markOnboardingStepAsCompleted("view-webhooks");
}
}, []);

const [openModal, closeModal] = createDialogActionHandlers<
CustomAppListUrlDialog,
CustomAppListUrlQueryParams
Expand Down
1 change: 1 addition & 0 deletions src/fragments/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export const fragmentUser = gql`
firstName
lastName
isStaff
dateJoined
metadata {
key
value
Expand Down
1 change: 1 addition & 0 deletions src/graphql/hooks.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ export const UserFragmentDoc = gql`
firstName
lastName
isStaff
dateJoined
metadata {
key
value
Expand Down
4 changes: 2 additions & 2 deletions src/graphql/types.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9172,7 +9172,7 @@ export type AvailableExternalAuthenticationsQuery = { __typename: 'Query', shop:
export type UserDetailsQueryVariables = Exact<{ [key: string]: never; }>;


export type UserDetailsQuery = { __typename: 'Query', me: { __typename: 'User', id: string, email: string, firstName: string, lastName: string, isStaff: boolean, restrictedAccessToChannels: boolean, metadata: Array<{ __typename: 'MetadataItem', key: string, value: string }>, userPermissions: Array<{ __typename: 'UserPermission', code: PermissionEnum, name: string }> | null, avatar: { __typename: 'Image', url: string } | null, accessibleChannels: Array<{ __typename: 'Channel', id: string, isActive: boolean, name: string, slug: string, currencyCode: string, defaultCountry: { __typename: 'CountryDisplay', code: string, country: string }, stockSettings: { __typename: 'StockSettings', allocationStrategy: AllocationStrategyEnum } }> | null } | null };
export type UserDetailsQuery = { __typename: 'Query', me: { __typename: 'User', id: string, email: string, firstName: string, lastName: string, isStaff: boolean, dateJoined: any, restrictedAccessToChannels: boolean, metadata: Array<{ __typename: 'MetadataItem', key: string, value: string }>, userPermissions: Array<{ __typename: 'UserPermission', code: PermissionEnum, name: string }> | null, avatar: { __typename: 'Image', url: string } | null, accessibleChannels: Array<{ __typename: 'Channel', id: string, isActive: boolean, name: string, slug: string, currencyCode: string, defaultCountry: { __typename: 'CountryDisplay', code: string, country: string }, stockSettings: { __typename: 'StockSettings', allocationStrategy: AllocationStrategyEnum } }> | null } | null };

export type CategoryDeleteMutationVariables = Exact<{
id: Scalars['ID'];
Expand Down Expand Up @@ -9996,7 +9996,7 @@ export type UserPermissionFragment = { __typename: 'UserPermission', code: Permi

export type UserUserPermissionWithSourcePermissionGroupsFragment = { __typename: 'UserPermission', code: PermissionEnum, name: string, sourcePermissionGroups: Array<{ __typename: 'Group', id: string }> | null };

export type UserFragment = { __typename: 'User', id: string, email: string, firstName: string, lastName: string, isStaff: boolean, restrictedAccessToChannels: boolean, metadata: Array<{ __typename: 'MetadataItem', key: string, value: string }>, userPermissions: Array<{ __typename: 'UserPermission', code: PermissionEnum, name: string }> | null, avatar: { __typename: 'Image', url: string } | null, accessibleChannels: Array<{ __typename: 'Channel', id: string, isActive: boolean, name: string, slug: string, currencyCode: string, defaultCountry: { __typename: 'CountryDisplay', code: string, country: string }, stockSettings: { __typename: 'StockSettings', allocationStrategy: AllocationStrategyEnum } }> | null };
export type UserFragment = { __typename: 'User', id: string, email: string, firstName: string, lastName: string, isStaff: boolean, dateJoined: any, restrictedAccessToChannels: boolean, metadata: Array<{ __typename: 'MetadataItem', key: string, value: string }>, userPermissions: Array<{ __typename: 'UserPermission', code: PermissionEnum, name: string }> | null, avatar: { __typename: 'Image', url: string } | null, accessibleChannels: Array<{ __typename: 'Channel', id: string, isActive: boolean, name: string, slug: string, currencyCode: string, defaultCountry: { __typename: 'CountryDisplay', code: string, country: string }, stockSettings: { __typename: 'StockSettings', allocationStrategy: AllocationStrategyEnum } }> | null };

export type UserBaseFragment = { __typename: 'User', id: string, firstName: string, lastName: string };

Expand Down
34 changes: 1 addition & 33 deletions src/newHome/homeOnboarding/HomeCheckGraphQLButton.tsx
Original file line number Diff line number Diff line change
@@ -1,42 +1,10 @@
import { useDevModeContext } from "@dashboard/components/DevModePanel/hooks";
import { Button, Tooltip } from "@saleor/macaw-ui-next";
import { Button } from "@saleor/macaw-ui-next";
import React from "react";
import { FormattedMessage } from "react-intl";

import { HomeFakeDisabledButton } from "./HomeFakeDisabledButton";

export const HomeCheckGraphQLButton = () => {
const context = useDevModeContext();
const getTooltipContent = () => {
return {
reason: "",
message: "",
};
};

const canViewGraphQLPlayground = true;

if (!canViewGraphQLPlayground) {
const { message } = getTooltipContent();

return (
<Tooltip>
<Tooltip.Trigger>
<HomeFakeDisabledButton>
<FormattedMessage
defaultMessage="Go to GraphQL Playground"
id="2xkzcr"
description="btn label"
/>
</HomeFakeDisabledButton>
</Tooltip.Trigger>
<Tooltip.Content>
<Tooltip.Arrow />
{message}
</Tooltip.Content>
</Tooltip>
);
}

return (
<Button
Expand Down
42 changes: 19 additions & 23 deletions src/newHome/homeOnboarding/HomeCreateProductButton.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
import { useUser } from "@dashboard/auth";
import { hasPermissions } from "@dashboard/components/RequirePermissions";
import { PermissionEnum } from "@dashboard/graphql";
import { productListUrl } from "@dashboard/products/urls";
import { Button, Tooltip } from "@saleor/macaw-ui-next";
import React from "react";
import { FormattedMessage } from "react-intl";
import { Link } from "react-router-dom";

import { HomeFakeDisabledButton } from "./HomeFakeDisabledButton";

export const HomeCreateProductButton = () => {
const getTooltipContent = () => {
return {
reason: "",
message: "",
};
};

const canViewProducts = true;

if (!canViewProducts) {
const { message } = getTooltipContent();
const { user } = useUser();
const userPermissions = user?.userPermissions || [];
const hasPermissionToManageProducts = hasPermissions(userPermissions, [
PermissionEnum.MANAGE_PRODUCTS,
]);

if (!hasPermissionToManageProducts) {
return (
<Tooltip>
<Tooltip.Trigger>
Expand All @@ -31,23 +30,20 @@ export const HomeCreateProductButton = () => {
</Tooltip.Trigger>
<Tooltip.Content>
<Tooltip.Arrow />
{message}
<FormattedMessage
defaultMessage="You don't have permission to manage products"
id="KHI/qv"
/>
</Tooltip.Content>
</Tooltip>
);
}

const goToAllProductsUrl = productListUrl();

return (
<Button
as="a"
href={goToAllProductsUrl}
target="_blank"
rel="noreferrer noopener"
variant="primary"
>
<FormattedMessage defaultMessage="Go to all products" id="XZpRr8" description="btn label" />
</Button>
<Link to={productListUrl()}>
<Button variant="primary">
<FormattedMessage defaultMessage="Go to all products" id="XZpRr8" description="btn label" />
</Button>
</Link>
);
};
19 changes: 11 additions & 8 deletions src/newHome/homeOnboarding/HomeInviteStaffButton.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { staffListPath } from "@dashboard/staff/urls";
import { useUser } from "@dashboard/auth";
import { hasPermissions } from "@dashboard/components/RequirePermissions";
import { PermissionEnum } from "@dashboard/graphql";
import { staffListUrl } from "@dashboard/staff/urls";
import { Button, Tooltip } from "@saleor/macaw-ui-next";
import React from "react";
import { FormattedMessage } from "react-intl";
Expand All @@ -7,9 +10,11 @@ import { Link } from "react-router-dom";
import { HomeFakeDisabledButton } from "./HomeFakeDisabledButton";

export const HomeInviteStaffButton = () => {
const canInviteStaffMembers = true;
const { user } = useUser();
const userPermissions = user?.userPermissions || [];
const hasPermissionToManageStaff = hasPermissions(userPermissions, [PermissionEnum.MANAGE_STAFF]);

if (!canInviteStaffMembers) {
if (!hasPermissionToManageStaff) {
return (
<Tooltip>
<Tooltip.Trigger>
Expand All @@ -20,19 +25,17 @@ export const HomeInviteStaffButton = () => {
<Tooltip.Content>
<Tooltip.Arrow />
<FormattedMessage
defaultMessage="You don't have permission to invite staff members"
id="RFXT9O"
defaultMessage="You don't have permission to manage staff"
id="gt05TH"
description="tooltip message"
/>
</Tooltip.Content>
</Tooltip>
);
}

const inviteTeamMembersPath = staffListPath;

return (
<Link to={inviteTeamMembersPath}>
<Link to={staffListUrl({ action: "add" })}>
<Button variant="primary">
<FormattedMessage defaultMessage="Invite members" id="BBt3jD" description="btn label" />
</Button>
Expand Down
6 changes: 3 additions & 3 deletions src/newHome/homeOnboarding/HomeOnboarding.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { DashboardCard } from "@dashboard/components/Card";
import { TOTAL_STEPS_COUNT } from "@dashboard/newHome/homeOnboarding/onboardingContext/initialOnboardingState";
import { Accordion, Box, Button, ChervonDownIcon, sprinkles, Text } from "@saleor/macaw-ui-next";
import * as React from "react";
import { FormattedMessage } from "react-intl";
Expand All @@ -20,13 +21,12 @@ const HomeOnboarding = () => {

const isOnboardingExpanded = onboardingState.onboardingExpanded;
const status = {
done: onboardingState.steps.filter(step => step.completed).length,
total: onboardingState.steps.length,
done: onboardingState.stepsCompleted.length,
total: TOTAL_STEPS_COUNT,
};

const handleMarkAllAsCompleted = () => {
markAllAsCompleted();
toggleOnboarding(false);
};

return (
Expand Down
2 changes: 1 addition & 1 deletion src/newHome/homeOnboarding/HomeOnboardingAccordion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { Accordion, Box, ChervonDownIcon, Skeleton, Text } from "@saleor/macaw-u
import React from "react";
import SVG from "react-inlinesvg";

import { useOnboardingData } from "./hooks/useOnboardingData";
import { useOnboarding } from "./onboardingContext/OnboardingContext";
import { useOnboardingData } from "./useOnboardingData";

export const HomeOnboardingAccordion = () => {
const { toggleExpandedOnboardingStep, extendedStepId, loading } = useOnboarding();
Expand Down
Loading
Loading