Merge pull request #1309 from mirumee/fix-gift-cards-currencies-select

Fix gift cards currencies select and some minor bugs
This commit is contained in:
mmarkusik 2021-08-20 13:12:15 +02:00 committed by GitHub
commit 12e4ff35ca
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 136 additions and 34 deletions

View file

@ -28,7 +28,7 @@ export const useAuth = () => {
const isAuthenticated = !!user.user; const isAuthenticated = !!user.user;
return { return {
hasToken: !!getTokens(), hasToken: !!getTokens().auth,
isAuthenticated, isAuthenticated,
tokenAuthLoading: user.tokenAuthLoading, tokenAuthLoading: user.tokenAuthLoading,
tokenVerifyLoading: user.tokenVerifyLoading, tokenVerifyLoading: user.tokenVerifyLoading,

View file

@ -50,30 +50,33 @@ function createMenuStructure(intl: IntlShape, user: User): SidebarMenuItem[] {
ariaLabel: "products", ariaLabel: "products",
label: intl.formatMessage(sectionNames.products), label: intl.formatMessage(sectionNames.products),
id: "products", id: "products",
url: productListUrl() url: productListUrl(),
permissions: [PermissionEnum.MANAGE_PRODUCTS]
}, },
{ {
ariaLabel: "categories", ariaLabel: "categories",
label: intl.formatMessage(sectionNames.categories), label: intl.formatMessage(sectionNames.categories),
id: "categories", id: "categories",
url: categoryListUrl() url: categoryListUrl(),
permissions: [PermissionEnum.MANAGE_PRODUCTS]
}, },
{ {
ariaLabel: "collections", ariaLabel: "collections",
label: intl.formatMessage(sectionNames.collections), label: intl.formatMessage(sectionNames.collections),
id: "collections", id: "collections",
url: collectionListUrl() url: collectionListUrl(),
permissions: [PermissionEnum.MANAGE_PRODUCTS]
}, },
{ {
ariaLabel: "giftCards", ariaLabel: "giftCards",
label: intl.formatMessage(sectionNames.giftCards), label: intl.formatMessage(sectionNames.giftCards),
id: "giftCards", id: "giftCards",
url: giftCardsListUrl() url: giftCardsListUrl(),
permissions: [PermissionEnum.MANAGE_GIFT_CARD]
} }
], ],
iconSrc: catalogIcon, iconSrc: catalogIcon,
label: intl.formatMessage(commonMessages.catalog), label: intl.formatMessage(commonMessages.catalog),
permissions: [PermissionEnum.MANAGE_PRODUCTS],
id: "catalogue" id: "catalogue"
}, },
{ {
@ -160,12 +163,30 @@ function createMenuStructure(intl: IntlShape, user: User): SidebarMenuItem[] {
} }
]; ];
return menuItems.filter( const isMenuItemPermitted = (menuItem: FilterableMenuItem) =>
menuItem =>
!menuItem.permissions || !menuItem.permissions ||
(user?.userPermissions || []).some(permission => (user?.userPermissions || []).some(permission =>
menuItem.permissions.includes(permission.code) menuItem.permissions.includes(permission.code)
) );
const getFilteredMenuItems = (menuItems: FilterableMenuItem[]) =>
menuItems.filter(isMenuItemPermitted);
return menuItems.reduce(
(resultItems: FilterableMenuItem[], menuItem: FilterableMenuItem) => {
const { children } = menuItem;
if (!isMenuItemPermitted(menuItem)) {
return resultItems;
}
const filteredChildren = children
? getFilteredMenuItems(children)
: undefined;
return [...resultItems, { ...menuItem, children: filteredChildren }];
},
[] as FilterableMenuItem[]
); );
} }

View file

@ -42,7 +42,7 @@ const Skeleton: React.FC<SkeletonProps> = props => {
const classes = useStyles(props); const classes = useStyles(props);
return children ? ( return children ? (
(children as React.ReactElement) <>{children}</>
) : ( ) : (
<span <span
data-test-id="skeleton" data-test-id="skeleton"

View file

@ -0,0 +1,39 @@
import { CircularProgress } from "@material-ui/core";
import { makeStyles } from "@saleor/macaw-ui";
import classNames from "classnames";
import React from "react";
interface ContentWithProgressProps {
containerClassName?: string;
}
export const useStyles = makeStyles(
theme => ({
container: {
display: "flex",
alignItems: "center",
justifyContent: "center",
height: "100%",
width: "100%",
padding: theme.spacing
}
}),
{ name: "ContentWithProgress" }
);
const ContentWithProgress: React.FC<ContentWithProgressProps> = ({
containerClassName,
children
}) => {
const classes = useStyles({});
return children ? (
<>{children}</>
) : (
<div className={classNames(classes.container, containerClassName)}>
<CircularProgress />
</div>
);
};
export default ContentWithProgress;

View file

@ -6,12 +6,14 @@ import commonErrorMessages from "@saleor/utils/errors/common";
import React, { useState } from "react"; import React, { useState } from "react";
import { useIntl } from "react-intl"; import { useIntl } from "react-intl";
import ContentWithProgress from "./ContentWithProgress";
import GiftCardCreateDialogCodeContent from "./GiftCardCreateDialogCodeContent"; import GiftCardCreateDialogCodeContent from "./GiftCardCreateDialogCodeContent";
import GiftCardCreateDialogForm, { import GiftCardCreateDialogForm, {
GiftCardCreateFormData GiftCardCreateFormData
} from "./GiftCardCreateDialogForm"; } from "./GiftCardCreateDialogForm";
import { giftCardCreateDialogMessages as messages } from "./messages"; import { giftCardCreateDialogMessages as messages } from "./messages";
import { useGiftCardCreateMutation } from "./mutations"; import { useGiftCardCreateMutation } from "./mutations";
import { useChannelCurrencies } from "./queries";
import { GiftCardCreate } from "./types/GiftCardCreate"; import { GiftCardCreate } from "./types/GiftCardCreate";
import { getGiftCardExpirySettingsInputData } from "./utils"; import { getGiftCardExpirySettingsInputData } from "./utils";
@ -27,6 +29,11 @@ const GiftCardCreateDialog: React.FC<GiftCardCreateDialogProps> = ({
const intl = useIntl(); const intl = useIntl();
const notify = useNotifier(); const notify = useNotifier();
const {
data: channelCurrenciesData,
loading: loadingChannelCurrencies
} = useChannelCurrencies({});
const [cardCode, setCardCode] = useState(null); const [cardCode, setCardCode] = useState(null);
const onCompleted = (data: GiftCardCreate) => { const onCompleted = (data: GiftCardCreate) => {
@ -94,19 +101,23 @@ const GiftCardCreateDialog: React.FC<GiftCardCreateDialogProps> = ({
return ( return (
<Dialog open={open} maxWidth="sm"> <Dialog open={open} maxWidth="sm">
<DialogTitle>{intl.formatMessage(messages.title)}</DialogTitle> <DialogTitle>{intl.formatMessage(messages.title)}</DialogTitle>
{cardCode ? ( <ContentWithProgress>
{!loadingChannelCurrencies &&
(cardCode ? (
<GiftCardCreateDialogCodeContent <GiftCardCreateDialogCodeContent
cardCode={cardCode} cardCode={cardCode}
onClose={handleClose} onClose={handleClose}
/> />
) : ( ) : (
<GiftCardCreateDialogForm <GiftCardCreateDialogForm
channelCurrencies={channelCurrenciesData?.shop?.channelCurrencies}
opts={createGiftCardOpts} opts={createGiftCardOpts}
onClose={handleClose} onClose={handleClose}
apiErrors={createGiftCardOpts?.data?.giftCardCreate?.errors} apiErrors={createGiftCardOpts?.data?.giftCardCreate?.errors}
onSubmit={handleSubmit} onSubmit={handleSubmit}
/> />
)} ))}
</ContentWithProgress>
</Dialog> </Dialog>
); );
}; };

View file

@ -7,7 +7,6 @@ import { GiftCardError } from "@saleor/fragments/types/GiftCardError";
import GiftCardExpirySelect from "@saleor/giftCards/components/GiftCardExpirySelect"; import GiftCardExpirySelect from "@saleor/giftCards/components/GiftCardExpirySelect";
import GiftCardTagInput from "@saleor/giftCards/components/GiftCardTagInput"; import GiftCardTagInput from "@saleor/giftCards/components/GiftCardTagInput";
import useForm from "@saleor/hooks/useForm"; import useForm from "@saleor/hooks/useForm";
import useShop from "@saleor/hooks/useShop";
import { commonMessages } from "@saleor/intl"; import { commonMessages } from "@saleor/intl";
import { ConfirmButtonTransitionState } from "@saleor/macaw-ui"; import { ConfirmButtonTransitionState } from "@saleor/macaw-ui";
import Label from "@saleor/orders/components/OrderHistory/Label"; import Label from "@saleor/orders/components/OrderHistory/Label";
@ -49,20 +48,20 @@ interface GiftCardCreateDialogFormProps {
apiErrors: GiftCardError[]; apiErrors: GiftCardError[];
onSubmit: (data: GiftCardCreateFormData) => void; onSubmit: (data: GiftCardCreateFormData) => void;
onClose: () => void; onClose: () => void;
channelCurrencies: string[];
} }
const GiftCardCreateDialogForm: React.FC<GiftCardCreateDialogFormProps> = ({ const GiftCardCreateDialogForm: React.FC<GiftCardCreateDialogFormProps> = ({
onSubmit, onSubmit,
opts, opts,
onClose, onClose,
apiErrors apiErrors,
channelCurrencies
}) => { }) => {
const intl = useIntl(); const intl = useIntl();
const classes = useStyles({}); const classes = useStyles({});
const shop = useShop();
// TEMP const initialCurrency = channelCurrencies[0];
const initialCurrency = shop?.channelCurrencies?.[0];
const [selectedCustomer, setSelectedCustomer] = useState< const [selectedCustomer, setSelectedCustomer] = useState<
GiftCardCreateFormCustomer GiftCardCreateFormCustomer
@ -105,7 +104,7 @@ const GiftCardCreateDialogForm: React.FC<GiftCardCreateDialogFormProps> = ({
isError={!!formErrors?.balance} isError={!!formErrors?.balance}
helperText={getGiftCardErrorMessage(formErrors?.balance, intl)} helperText={getGiftCardErrorMessage(formErrors?.balance, intl)}
change={change} change={change}
choices={mapSingleValueNodeToChoice(shop?.channelCurrencies)} choices={mapSingleValueNodeToChoice(channelCurrencies)}
containerClassName={classes.balanceContainer} containerClassName={classes.balanceContainer}
textFieldProps={{ textFieldProps={{
type: "number", type: "number",

View file

@ -0,0 +1,15 @@
import makeQuery from "@saleor/hooks/makeQuery";
import gql from "graphql-tag";
import { ChannelCurrencies } from "./types/ChannelCurrencies";
const channelCurrencies = gql`
query ChannelCurrencies {
shop {
channelCurrencies
}
}
`;
export const useChannelCurrencies = makeQuery<ChannelCurrencies, {}>(
channelCurrencies
);

View file

@ -0,0 +1,17 @@
/* tslint:disable */
/* eslint-disable */
// @generated
// This file was automatically generated and should not be edited.
// ====================================================
// GraphQL query operation: ChannelCurrencies
// ====================================================
export interface ChannelCurrencies_shop {
__typename: "Shop";
channelCurrencies: string[];
}
export interface ChannelCurrencies {
shop: ChannelCurrencies_shop;
}

View file

@ -144,6 +144,7 @@ const Routes: React.FC = () => {
tokenVerifyLoading, tokenVerifyLoading,
user user
} = useAuth(); } = useAuth();
const { channel } = useAppChannel(false); const { channel } = useAppChannel(false);
const channelLoaded = typeof channel !== "undefined"; const channelLoaded = typeof channel !== "undefined";
@ -193,8 +194,7 @@ const Routes: React.FC = () => {
component={CustomerSection} component={CustomerSection}
/> />
<SectionRoute <SectionRoute
/* add after backend adds the permission to schema */ permissions={[PermissionEnum.MANAGE_GIFT_CARD]}
// permissions={[]}
path={giftCardsSectionUrlName} path={giftCardsSectionUrlName}
component={GiftCardSection} component={GiftCardSection}
/> />