Add trailing commas (#2062)
* Require trailing commas * Add trailing commas * Add trailing commas in testUtils dir * Add trailing commas
This commit is contained in:
parent
8bd7824f27
commit
d5c9a3dae8
1539 changed files with 18628 additions and 18574 deletions
|
@ -76,7 +76,7 @@
|
|||
"camelcase": "off",
|
||||
"capitalized-comments": "off",
|
||||
"chai-friendly/no-unused-expressions": "error",
|
||||
"comma-dangle": "off",
|
||||
"comma-dangle": ["error", "always-multiline"],
|
||||
"complexity": "off",
|
||||
"constructor-super": "error",
|
||||
"curly": "error",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"arrowParens": "avoid",
|
||||
"trailingComma": "none"
|
||||
"trailingComma": "all"
|
||||
}
|
||||
|
|
|
@ -5,10 +5,10 @@ import { extensionList } from "./queries";
|
|||
export const mocks: MockedResponse[] = [
|
||||
{
|
||||
request: {
|
||||
query: extensionList
|
||||
query: extensionList,
|
||||
},
|
||||
result: {
|
||||
data: []
|
||||
}
|
||||
}
|
||||
data: [],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
|
|
@ -9,7 +9,7 @@ const props: AppActivateDialogProps = {
|
|||
name: "App",
|
||||
onClose: () => undefined,
|
||||
onConfirm: () => undefined,
|
||||
open: true
|
||||
open: true,
|
||||
};
|
||||
|
||||
storiesOf("Views / Apps / Activate app", module)
|
||||
|
|
|
@ -18,7 +18,7 @@ const AppActivateDialog: React.FC<AppActivateDialogProps> = ({
|
|||
open,
|
||||
name,
|
||||
onClose,
|
||||
onConfirm
|
||||
onConfirm,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
|
||||
|
@ -27,7 +27,7 @@ const AppActivateDialog: React.FC<AppActivateDialogProps> = ({
|
|||
confirmButtonLabel={intl.formatMessage({
|
||||
id: "D3E2b5",
|
||||
defaultMessage: "Activate",
|
||||
description: "button label"
|
||||
description: "button label",
|
||||
})}
|
||||
confirmButtonState={confirmButtonState}
|
||||
open={open}
|
||||
|
@ -36,7 +36,7 @@ const AppActivateDialog: React.FC<AppActivateDialogProps> = ({
|
|||
title={intl.formatMessage({
|
||||
id: "YHNozE",
|
||||
defaultMessage: "Activate App",
|
||||
description: "dialog header"
|
||||
description: "dialog header",
|
||||
})}
|
||||
variant="default"
|
||||
>
|
||||
|
@ -53,7 +53,7 @@ const AppActivateDialog: React.FC<AppActivateDialogProps> = ({
|
|||
defaultMessage="Are you sure you want to activate {name}? Activating will start gathering events."
|
||||
description="activate app"
|
||||
values={{
|
||||
name: <strong>{getStringOrPlaceholder(name)}</strong>
|
||||
name: <strong>{getStringOrPlaceholder(name)}</strong>,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
|
|
@ -3,7 +3,7 @@ import { storiesOf } from "@storybook/react";
|
|||
import React from "react";
|
||||
|
||||
import AppDeactivateDialog, {
|
||||
AppDeactivateDialogProps
|
||||
AppDeactivateDialogProps,
|
||||
} from "./AppDeactivateDialog";
|
||||
|
||||
const props: AppDeactivateDialogProps = {
|
||||
|
@ -11,7 +11,7 @@ const props: AppDeactivateDialogProps = {
|
|||
name: "App",
|
||||
onClose: () => undefined,
|
||||
onConfirm: () => undefined,
|
||||
open: true
|
||||
open: true,
|
||||
};
|
||||
|
||||
storiesOf("Views / Apps / Deactivate app", module)
|
||||
|
|
|
@ -22,7 +22,7 @@ const AppDeactivateDialog: React.FC<AppDeactivateDialogProps> = ({
|
|||
name,
|
||||
thirdParty = true,
|
||||
onClose,
|
||||
onConfirm
|
||||
onConfirm,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
|
||||
|
@ -31,7 +31,7 @@ const AppDeactivateDialog: React.FC<AppDeactivateDialogProps> = ({
|
|||
confirmButtonLabel={intl.formatMessage({
|
||||
id: "W+AFZY",
|
||||
defaultMessage: "Deactivate",
|
||||
description: "button label"
|
||||
description: "button label",
|
||||
})}
|
||||
confirmButtonState={confirmButtonState}
|
||||
open={open}
|
||||
|
@ -40,7 +40,7 @@ const AppDeactivateDialog: React.FC<AppDeactivateDialogProps> = ({
|
|||
title={intl.formatMessage({
|
||||
id: "yMi8I8",
|
||||
defaultMessage: "Dectivate App",
|
||||
description: "dialog header"
|
||||
description: "dialog header",
|
||||
})}
|
||||
variant="delete"
|
||||
>
|
||||
|
@ -55,7 +55,7 @@ const AppDeactivateDialog: React.FC<AppDeactivateDialogProps> = ({
|
|||
? msgs.deactivateNamedApp
|
||||
: msgs.deactivateLocalNamedApp)}
|
||||
values={{
|
||||
name: <strong>{getStringOrPlaceholder(name)}</strong>
|
||||
name: <strong>{getStringOrPlaceholder(name)}</strong>,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
|
|
@ -5,24 +5,24 @@ export default defineMessages({
|
|||
id: "73RU3R",
|
||||
defaultMessage:
|
||||
"Are you sure you want to disable this app? Your data will be kept until you reactivate the app. You will be still billed for the app.",
|
||||
description: "deactivate app"
|
||||
description: "deactivate app",
|
||||
},
|
||||
deactivateNamedApp: {
|
||||
id: "w6Gau0",
|
||||
defaultMessage:
|
||||
"Are you sure you want to disable {name}? Your data will be kept until you reactivate the app. You will be still billed for the app.",
|
||||
description: "deactivate named app"
|
||||
description: "deactivate named app",
|
||||
},
|
||||
deactivateLocalApp: {
|
||||
id: "7O2EsY",
|
||||
defaultMessage:
|
||||
"Are you sure you want to disable this app? Your data will be kept until you reactivate the app.",
|
||||
description: "deactivate local app"
|
||||
description: "deactivate local app",
|
||||
},
|
||||
deactivateLocalNamedApp: {
|
||||
id: "Np7J92",
|
||||
defaultMessage:
|
||||
"Are you sure you want to disable {name}? Your data will be kept until you reactivate the app.",
|
||||
description: "deactivate local named app"
|
||||
}
|
||||
description: "deactivate local named app",
|
||||
},
|
||||
});
|
||||
|
|
|
@ -10,7 +10,7 @@ const props: AppDeleteDialogProps = {
|
|||
onClose: () => undefined,
|
||||
onConfirm: () => undefined,
|
||||
open: true,
|
||||
type: "EXTERNAL"
|
||||
type: "EXTERNAL",
|
||||
};
|
||||
|
||||
storiesOf("Views / Apps / Delete app", module)
|
||||
|
|
|
@ -20,7 +20,7 @@ const AppDeleteDialog: React.FC<AppDeleteDialogProps> = ({
|
|||
name,
|
||||
onClose,
|
||||
onConfirm,
|
||||
type
|
||||
type,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
|
||||
|
@ -33,7 +33,7 @@ const AppDeleteDialog: React.FC<AppDeleteDialogProps> = ({
|
|||
title={intl.formatMessage({
|
||||
id: "zQX6xO",
|
||||
defaultMessage: "Delete App",
|
||||
description: "dialog header"
|
||||
description: "dialog header",
|
||||
})}
|
||||
variant="delete"
|
||||
>
|
||||
|
@ -50,7 +50,7 @@ const AppDeleteDialog: React.FC<AppDeleteDialogProps> = ({
|
|||
defaultMessage="Deleting {name}, you will remove installation of the app. If you are paying for app subscription, remember to unsubscribe from the app in Saleor Marketplace. Are you sure you want to delete the app?"
|
||||
description="delete app"
|
||||
values={{
|
||||
name: <strong>{getStringOrPlaceholder(name)}</strong>
|
||||
name: <strong>{getStringOrPlaceholder(name)}</strong>,
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
|
@ -59,7 +59,7 @@ const AppDeleteDialog: React.FC<AppDeleteDialogProps> = ({
|
|||
defaultMessage="Deleting {name}, you will delete all the data and webhooks regarding this app. Are you sure you want to do that?"
|
||||
description="delete custom app"
|
||||
values={{
|
||||
name: <strong>{getStringOrPlaceholder(name)}</strong>
|
||||
name: <strong>{getStringOrPlaceholder(name)}</strong>,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
|
|
@ -10,7 +10,7 @@ const props: AppDetailsPageProps = {
|
|||
loading: false,
|
||||
navigateToApp: () => undefined,
|
||||
onAppActivateOpen: () => undefined,
|
||||
onAppDeactivateOpen: () => undefined
|
||||
onAppDeactivateOpen: () => undefined,
|
||||
};
|
||||
|
||||
storiesOf("Views / Apps / App details", module)
|
||||
|
|
|
@ -33,7 +33,7 @@ export const AppDetailsPage: React.FC<AppDetailsPageProps> = ({
|
|||
loading,
|
||||
navigateToApp,
|
||||
onAppActivateOpen,
|
||||
onAppDeactivateOpen
|
||||
onAppDeactivateOpen,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const classes = useStyles({});
|
||||
|
@ -105,7 +105,7 @@ export const AppDetailsPage: React.FC<AppDetailsPageProps> = ({
|
|||
title={intl.formatMessage({
|
||||
id: "jDIRQV",
|
||||
defaultMessage: "About this app",
|
||||
description: "section header"
|
||||
description: "section header",
|
||||
})}
|
||||
/>
|
||||
<CardContent>
|
||||
|
@ -118,7 +118,7 @@ export const AppDetailsPage: React.FC<AppDetailsPageProps> = ({
|
|||
title={intl.formatMessage({
|
||||
id: "VsGcdP",
|
||||
defaultMessage: "App permissions",
|
||||
description: "section header"
|
||||
description: "section header",
|
||||
})}
|
||||
/>
|
||||
<CardContent>
|
||||
|
@ -152,7 +152,7 @@ export const AppDetailsPage: React.FC<AppDetailsPageProps> = ({
|
|||
title={intl.formatMessage({
|
||||
id: "a55zOn",
|
||||
defaultMessage: "Data privacy",
|
||||
description: "section header"
|
||||
description: "section header",
|
||||
})}
|
||||
/>
|
||||
<CardContent>
|
||||
|
|
|
@ -4,7 +4,7 @@ import {
|
|||
DialogProps,
|
||||
DialogTitle,
|
||||
IconButton,
|
||||
Typography
|
||||
Typography,
|
||||
} from "@material-ui/core";
|
||||
import CloseIcon from "@material-ui/icons/Close";
|
||||
import React from "react";
|
||||
|
|
|
@ -5,15 +5,15 @@ export const useStyles = makeStyles(
|
|||
header: {
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center"
|
||||
alignItems: "center",
|
||||
},
|
||||
content: {
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
overflow: "hidden",
|
||||
width: 600,
|
||||
height: 600
|
||||
}
|
||||
height: 600,
|
||||
},
|
||||
}),
|
||||
{ name: "AppDialog" }
|
||||
{ name: "AppDialog" },
|
||||
);
|
||||
|
|
|
@ -24,7 +24,7 @@ export const AppFrame: React.FC<Props> = ({
|
|||
appId,
|
||||
className,
|
||||
onLoad,
|
||||
onError
|
||||
onError,
|
||||
}) => {
|
||||
const shop = useShop();
|
||||
const frameRef = React.useRef<HTMLIFrameElement>();
|
||||
|
@ -38,8 +38,8 @@ export const AppFrame: React.FC<Props> = ({
|
|||
type: "handshake",
|
||||
payload: {
|
||||
token: appToken,
|
||||
version: 1
|
||||
}
|
||||
version: 1,
|
||||
},
|
||||
});
|
||||
sendThemeToExtension();
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@ export const useStyles = makeStyles(
|
|||
iframe: {
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
border: "none"
|
||||
}
|
||||
border: "none",
|
||||
},
|
||||
}),
|
||||
{ name: "AppFrame" }
|
||||
{ name: "AppFrame" },
|
||||
);
|
||||
|
|
|
@ -7,25 +7,25 @@ import { useExternalApp } from "../ExternalAppContext";
|
|||
|
||||
const sendResponseStatus = (
|
||||
actionId: string,
|
||||
ok: boolean
|
||||
ok: boolean,
|
||||
): DispatchResponseEvent => ({
|
||||
type: "response",
|
||||
payload: {
|
||||
actionId,
|
||||
ok
|
||||
}
|
||||
ok,
|
||||
},
|
||||
});
|
||||
|
||||
export const useAppActions = (
|
||||
frameEl: React.MutableRefObject<HTMLIFrameElement>,
|
||||
appOrigin: string
|
||||
appOrigin: string,
|
||||
) => {
|
||||
const navigate = useNavigator();
|
||||
const { closeApp } = useExternalApp();
|
||||
const intl = useIntl();
|
||||
|
||||
const actionReducer = (
|
||||
action: Actions | undefined
|
||||
action: Actions | undefined,
|
||||
): DispatchResponseEvent => {
|
||||
switch (action?.type) {
|
||||
case "redirect": {
|
||||
|
@ -48,8 +48,8 @@ export const useAppActions = (
|
|||
intl.formatMessage({
|
||||
id: "MSItJD",
|
||||
defaultMessage:
|
||||
"You are about to leave the Dashboard. Do you want to continue?"
|
||||
})
|
||||
"You are about to leave the Dashboard. Do you want to continue?",
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -92,6 +92,6 @@ export const useAppActions = (
|
|||
}, []);
|
||||
|
||||
return {
|
||||
postToExtension
|
||||
postToExtension,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -3,7 +3,7 @@ import { storiesOf } from "@storybook/react";
|
|||
import React from "react";
|
||||
|
||||
import AppInProgressDeleteDialog, {
|
||||
AppInProgressDeleteDialogProps
|
||||
AppInProgressDeleteDialogProps,
|
||||
} from "./AppInProgressDeleteDialog";
|
||||
|
||||
const props: AppInProgressDeleteDialogProps = {
|
||||
|
@ -11,7 +11,7 @@ const props: AppInProgressDeleteDialogProps = {
|
|||
name: "App",
|
||||
onClose: () => undefined,
|
||||
onConfirm: () => undefined,
|
||||
open: true
|
||||
open: true,
|
||||
};
|
||||
|
||||
storiesOf("Views / Apps / Delete app failed installation", module)
|
||||
|
|
|
@ -18,7 +18,7 @@ const AppInProgressDeleteDialog: React.FC<AppInProgressDeleteDialogProps> = ({
|
|||
open,
|
||||
name,
|
||||
onClose,
|
||||
onConfirm
|
||||
onConfirm,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
|
||||
|
@ -31,7 +31,7 @@ const AppInProgressDeleteDialog: React.FC<AppInProgressDeleteDialogProps> = ({
|
|||
title={intl.formatMessage({
|
||||
id: "zQX6xO",
|
||||
defaultMessage: "Delete App",
|
||||
description: "dialog header"
|
||||
description: "dialog header",
|
||||
})}
|
||||
variant="delete"
|
||||
>
|
||||
|
@ -48,7 +48,7 @@ const AppInProgressDeleteDialog: React.FC<AppInProgressDeleteDialogProps> = ({
|
|||
defaultMessage="Deleting {name}, you will remove installation of the app. If you are paying for app subscription, remember to unsubscribe from the app in Saleor Marketplace. Are you sure you want to delete the app?"
|
||||
description="delete app"
|
||||
values={{
|
||||
name: <strong>{getStringOrPlaceholder(name)}</strong>
|
||||
name: <strong>{getStringOrPlaceholder(name)}</strong>,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
|
|
@ -12,7 +12,7 @@ interface AppInstallErrorPageProps {
|
|||
}
|
||||
|
||||
export const AppInstallErrorPage: React.FC<AppInstallErrorPageProps> = ({
|
||||
onBack
|
||||
onBack,
|
||||
}) => {
|
||||
const classes = useStyles({});
|
||||
|
||||
|
|
|
@ -4,23 +4,23 @@ export const useStyles = makeStyles(
|
|||
theme => ({
|
||||
button: {
|
||||
marginTop: theme.spacing(2),
|
||||
padding: theme.spacing(1.5, 2)
|
||||
padding: theme.spacing(1.5, 2),
|
||||
},
|
||||
root: {
|
||||
"& > div": {
|
||||
minHeight: "80vh"
|
||||
minHeight: "80vh",
|
||||
},
|
||||
"& h3": {
|
||||
fontWeight: 600,
|
||||
marginBottom: theme.spacing(3),
|
||||
maxWidth: theme.spacing(60)
|
||||
maxWidth: theme.spacing(60),
|
||||
},
|
||||
"& img": {
|
||||
maxWidth: "100%"
|
||||
}
|
||||
}
|
||||
maxWidth: "100%",
|
||||
},
|
||||
},
|
||||
}),
|
||||
{
|
||||
name: "AppInstallErrorPage"
|
||||
}
|
||||
name: "AppInstallErrorPage",
|
||||
},
|
||||
);
|
||||
|
|
|
@ -9,7 +9,7 @@ const props: AppInstallPageProps = {
|
|||
data: installApp,
|
||||
loading: false,
|
||||
navigateToAppsList: () => undefined,
|
||||
onSubmit: () => undefined
|
||||
onSubmit: () => undefined,
|
||||
};
|
||||
|
||||
storiesOf("Views / Apps / Install App", module)
|
||||
|
|
|
@ -27,7 +27,7 @@ export const AppInstallPage: React.FC<AppInstallPageProps> = ({
|
|||
data,
|
||||
loading,
|
||||
navigateToAppsList,
|
||||
onSubmit
|
||||
onSubmit,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const classes = useStyles({});
|
||||
|
@ -47,9 +47,9 @@ export const AppInstallPage: React.FC<AppInstallPageProps> = ({
|
|||
{
|
||||
id: "Id7C0X",
|
||||
defaultMessage: `You are about to install {name}`,
|
||||
description: "section header"
|
||||
description: "section header",
|
||||
},
|
||||
{ name }
|
||||
{ name },
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ export const AppInstallPage: React.FC<AppInstallPageProps> = ({
|
|||
<div
|
||||
className={classNames(
|
||||
classes.installIcon,
|
||||
classes.installSaleorIcon
|
||||
classes.installSaleorIcon,
|
||||
)}
|
||||
>
|
||||
<img src={saleorDarkLogoSmall} alt="" />
|
||||
|
@ -81,7 +81,7 @@ export const AppInstallPage: React.FC<AppInstallPageProps> = ({
|
|||
title={intl.formatMessage({
|
||||
id: "VsGcdP",
|
||||
defaultMessage: "App permissions",
|
||||
description: "section header"
|
||||
description: "section header",
|
||||
})}
|
||||
/>
|
||||
<CardContent>
|
||||
|
|
|
@ -9,7 +9,7 @@ const props: AppPageProps = {
|
|||
data: appDetails,
|
||||
url: appDetails.appUrl,
|
||||
aboutHref: "",
|
||||
onError: () => undefined
|
||||
onError: () => undefined,
|
||||
};
|
||||
|
||||
storiesOf("Views / Apps / App", module)
|
||||
|
|
|
@ -27,7 +27,7 @@ export const AppPage: React.FC<AppPageProps> = ({
|
|||
data,
|
||||
url,
|
||||
aboutHref,
|
||||
onError
|
||||
onError,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const classes = useStyles({});
|
||||
|
@ -44,7 +44,7 @@ export const AppPage: React.FC<AppPageProps> = ({
|
|||
<Typography
|
||||
className={classNames(
|
||||
classes.breadcrumb,
|
||||
classes.breadcrumbDisabled
|
||||
classes.breadcrumbDisabled,
|
||||
)}
|
||||
variant="h5"
|
||||
>
|
||||
|
|
|
@ -5,12 +5,12 @@ export const useStyles = makeStyles(
|
|||
appSettingsHeader: {
|
||||
"& > button, & > a": {
|
||||
"&:last-child": {
|
||||
marginRight: 0
|
||||
marginRight: 0,
|
||||
},
|
||||
marginRight: theme.spacing(2)
|
||||
marginRight: theme.spacing(2),
|
||||
},
|
||||
display: "flex",
|
||||
justifyContent: "flex-end"
|
||||
justifyContent: "flex-end",
|
||||
},
|
||||
breadcrumb: {
|
||||
"&:not(:last-child)": {
|
||||
|
@ -19,28 +19,28 @@ export const useStyles = makeStyles(
|
|||
display: "block",
|
||||
position: "absolute",
|
||||
right: theme.spacing(-2),
|
||||
top: 0
|
||||
top: 0,
|
||||
},
|
||||
"&:not(:first-child):hover": {
|
||||
cursor: "pointer",
|
||||
textDecoration: "underline"
|
||||
}
|
||||
textDecoration: "underline",
|
||||
},
|
||||
},
|
||||
marginRight: theme.spacing(3),
|
||||
position: "relative"
|
||||
position: "relative",
|
||||
},
|
||||
breadcrumbContainer: {
|
||||
alignItems: "center",
|
||||
display: "flex"
|
||||
display: "flex",
|
||||
},
|
||||
breadcrumbDisabled: {
|
||||
"&:hover": {
|
||||
textDecoration: "none"
|
||||
textDecoration: "none",
|
||||
},
|
||||
color: theme.palette.text.disabled
|
||||
color: theme.palette.text.disabled,
|
||||
},
|
||||
breadcrumbs: {
|
||||
display: "flex"
|
||||
display: "flex",
|
||||
},
|
||||
hr: {
|
||||
border: "none",
|
||||
|
@ -48,15 +48,15 @@ export const useStyles = makeStyles(
|
|||
height: 0,
|
||||
marginBottom: 0,
|
||||
marginTop: 0,
|
||||
width: "100%"
|
||||
width: "100%",
|
||||
},
|
||||
iframeContainer: {
|
||||
"& > iframe": {
|
||||
border: "none",
|
||||
minHeight: "75vh",
|
||||
width: "100%"
|
||||
}
|
||||
}
|
||||
width: "100%",
|
||||
},
|
||||
},
|
||||
}),
|
||||
{ name: "AppPage" }
|
||||
{ name: "AppPage" },
|
||||
);
|
||||
|
|
|
@ -5,7 +5,7 @@ import {
|
|||
ExtensionMessageEvent,
|
||||
ExtensionMessageType,
|
||||
sendMessageToExtension,
|
||||
useExtensionMessage
|
||||
useExtensionMessage,
|
||||
} from "@saleor/macaw-ui";
|
||||
import { useState } from "react";
|
||||
|
||||
|
@ -14,7 +14,7 @@ function useSettingsBreadcrumbs(): UseSettingsBreadcrumbs {
|
|||
const [breadcrumbs, setBreadcrumbs] = useState<Breadcrumb[]>([]);
|
||||
|
||||
const handleBreadcrumbSet = (
|
||||
event: ExtensionMessageEvent<BreadcrumbChangeMessage>
|
||||
event: ExtensionMessageEvent<BreadcrumbChangeMessage>,
|
||||
) => {
|
||||
if (event.data.type === ExtensionMessageType.BREADCRUMB_SET) {
|
||||
setBreadcrumbs(event.data.breadcrumbs);
|
||||
|
@ -27,9 +27,9 @@ function useSettingsBreadcrumbs(): UseSettingsBreadcrumbs {
|
|||
sendMessageToExtension<BreadcrumbClickMessage>(
|
||||
{
|
||||
breadcrumb: value,
|
||||
type: ExtensionMessageType.BREADCRUMB_CLICK
|
||||
type: ExtensionMessageType.BREADCRUMB_CLICK,
|
||||
},
|
||||
"*"
|
||||
"*",
|
||||
);
|
||||
|
||||
return [breadcrumbs, handleBreadcrumbClick];
|
||||
|
|
|
@ -3,7 +3,7 @@ import {
|
|||
IconButton,
|
||||
makeStyles,
|
||||
PermissionsIcon,
|
||||
Tooltip
|
||||
Tooltip,
|
||||
} from "@saleor/macaw-ui";
|
||||
import React from "react";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
@ -12,10 +12,10 @@ const useStyles = makeStyles(
|
|||
() => ({
|
||||
list: {
|
||||
margin: 0,
|
||||
paddingLeft: "16px"
|
||||
}
|
||||
paddingLeft: "16px",
|
||||
},
|
||||
}),
|
||||
{ name: "AppPermissions" }
|
||||
{ name: "AppPermissions" },
|
||||
);
|
||||
|
||||
interface AppPermissionsProps {
|
||||
|
|
|
@ -4,7 +4,7 @@ import {
|
|||
TableBody,
|
||||
TableCell,
|
||||
TableRow,
|
||||
Typography
|
||||
Typography,
|
||||
} from "@material-ui/core";
|
||||
import { Button } from "@saleor/components/Button";
|
||||
import CardTitle from "@saleor/components/CardTitle";
|
||||
|
@ -16,7 +16,7 @@ import {
|
|||
Indicator,
|
||||
ResponsiveTable,
|
||||
Tooltip,
|
||||
TooltipMountWrapper
|
||||
TooltipMountWrapper,
|
||||
} from "@saleor/macaw-ui";
|
||||
import { renderCollection } from "@saleor/misc";
|
||||
import classNames from "classnames";
|
||||
|
@ -48,7 +48,7 @@ const AppsInProgress: React.FC<AppsInProgressProps> = ({
|
|||
title={intl.formatMessage({
|
||||
id: "nIrjSR",
|
||||
defaultMessage: "Ongoing Installations",
|
||||
description: "section header"
|
||||
description: "section header",
|
||||
})}
|
||||
/>
|
||||
<ResponsiveTable>
|
||||
|
@ -62,7 +62,7 @@ const AppsInProgress: React.FC<AppsInProgressProps> = ({
|
|||
<TableCell
|
||||
className={classNames(
|
||||
classes.colAction,
|
||||
classes.colInstallAction
|
||||
classes.colInstallAction,
|
||||
)}
|
||||
>
|
||||
<Typography variant="body2" className={classes.text}>
|
||||
|
@ -81,7 +81,7 @@ const AppsInProgress: React.FC<AppsInProgressProps> = ({
|
|||
<TableCell
|
||||
className={classNames(
|
||||
classes.colAction,
|
||||
classes.colInstallAction
|
||||
classes.colInstallAction,
|
||||
)}
|
||||
>
|
||||
<Typography variant="body2" className={classes.error}>
|
||||
|
|
|
@ -4,7 +4,7 @@ import {
|
|||
pageListProps,
|
||||
searchPageProps,
|
||||
sortPageProps,
|
||||
tabPageProps
|
||||
tabPageProps,
|
||||
} from "@saleor/fixtures";
|
||||
import Decorator from "@saleor/storybook/Decorator";
|
||||
import { PaginatorContextDecorator } from "@saleor/storybook/PaginatorContextDecorator";
|
||||
|
@ -22,7 +22,7 @@ const props: AppsListPageProps = {
|
|||
...tabPageProps,
|
||||
appsInProgressList: {
|
||||
__typename: "Query",
|
||||
appsInstallations: appsInProgress
|
||||
appsInstallations: appsInProgress,
|
||||
},
|
||||
customAppsList,
|
||||
disabled: false,
|
||||
|
@ -32,7 +32,7 @@ const props: AppsListPageProps = {
|
|||
onAppInProgressRemove: () => undefined,
|
||||
onAppInstallRetry: () => undefined,
|
||||
onCustomAppRemove: () => undefined,
|
||||
onInstalledAppRemove: () => undefined
|
||||
onInstalledAppRemove: () => undefined,
|
||||
};
|
||||
|
||||
storiesOf("Views / Apps / Apps list", module)
|
||||
|
|
|
@ -9,7 +9,7 @@ import Savebar from "@saleor/components/Savebar";
|
|||
import {
|
||||
AppErrorFragment,
|
||||
PermissionEnum,
|
||||
PermissionFragment
|
||||
PermissionFragment,
|
||||
} from "@saleor/graphql";
|
||||
import { SubmitPromise } from "@saleor/hooks/useForm";
|
||||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
|
@ -33,7 +33,7 @@ export interface CustomAppCreatePageProps {
|
|||
permissions: PermissionFragment[];
|
||||
saveButtonBarState: ConfirmButtonTransitionState;
|
||||
onSubmit: (
|
||||
data: CustomAppCreatePageFormData
|
||||
data: CustomAppCreatePageFormData,
|
||||
) => SubmitPromise<AppErrorFragment[]>;
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ const CustomAppCreatePage: React.FC<CustomAppCreatePageProps> = props => {
|
|||
const initialForm: CustomAppCreatePageFormData = {
|
||||
hasFullAccess: false,
|
||||
name: "",
|
||||
permissions: []
|
||||
permissions: [],
|
||||
};
|
||||
|
||||
const formErrors = getFormErrors(["permissions"], errors || []);
|
||||
|
@ -67,7 +67,7 @@ const CustomAppCreatePage: React.FC<CustomAppCreatePageProps> = props => {
|
|||
title={intl.formatMessage({
|
||||
id: "GjH9uy",
|
||||
defaultMessage: "Create New App",
|
||||
description: "header"
|
||||
description: "header",
|
||||
})}
|
||||
/>
|
||||
<Grid>
|
||||
|
@ -89,13 +89,13 @@ const CustomAppCreatePage: React.FC<CustomAppCreatePageProps> = props => {
|
|||
fullAccessLabel={intl.formatMessage({
|
||||
id: "D4nzdD",
|
||||
defaultMessage: "Grant this app full access to the store",
|
||||
description: "checkbox label"
|
||||
description: "checkbox label",
|
||||
})}
|
||||
description={intl.formatMessage({
|
||||
id: "flP8Hj",
|
||||
defaultMessage:
|
||||
"Expand or restrict app permissions to access certain part of Saleor system.",
|
||||
description: "card description"
|
||||
description: "card description",
|
||||
})}
|
||||
/>
|
||||
</Grid>
|
||||
|
|
|
@ -41,7 +41,7 @@ const CustomAppDefaultToken: React.FC<CustomAppDefaultTokenProps> = props => {
|
|||
<Link href={apiUri} onClick={onApiUriClick}>
|
||||
{apiUri}
|
||||
</Link>
|
||||
)
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</Typography>
|
||||
|
|
|
@ -4,35 +4,35 @@ import { makeStyles } from "@saleor/macaw-ui";
|
|||
export const useStyles = makeStyles(
|
||||
theme => ({
|
||||
cancel: {
|
||||
marginRight: theme.spacing(1)
|
||||
marginRight: theme.spacing(1),
|
||||
},
|
||||
closeContainer: {
|
||||
display: "flex",
|
||||
justifyContent: "flex-end",
|
||||
position: "relative",
|
||||
right: theme.spacing(-1),
|
||||
top: theme.spacing(-1)
|
||||
top: theme.spacing(-1),
|
||||
},
|
||||
content: {
|
||||
display: "grid",
|
||||
gridColumnGap: theme.spacing(3),
|
||||
gridTemplateColumns: "1fr 60px",
|
||||
marginBottom: theme.spacing(3)
|
||||
marginBottom: theme.spacing(3),
|
||||
},
|
||||
copy: {
|
||||
marginTop: theme.spacing(),
|
||||
position: "relative",
|
||||
right: theme.spacing(1)
|
||||
right: theme.spacing(1),
|
||||
},
|
||||
paper: {
|
||||
background: fade(theme.palette.primary.main, 0.05),
|
||||
padding: theme.spacing(2, 3)
|
||||
padding: theme.spacing(2, 3),
|
||||
},
|
||||
root: {
|
||||
boxShadow: "0px 5px 10px rgba(0, 0, 0, 0.05)"
|
||||
}
|
||||
boxShadow: "0px 5px 10px rgba(0, 0, 0, 0.05)",
|
||||
},
|
||||
}),
|
||||
{
|
||||
name: "CustomAppTokenCreateDialog"
|
||||
}
|
||||
name: "CustomAppTokenCreateDialog",
|
||||
},
|
||||
);
|
||||
|
|
|
@ -11,7 +11,7 @@ import {
|
|||
AppErrorFragment,
|
||||
AppUpdateMutation,
|
||||
PermissionEnum,
|
||||
ShopInfoQuery
|
||||
ShopInfoQuery,
|
||||
} from "@saleor/graphql";
|
||||
import { SubmitPromise } from "@saleor/hooks/useForm";
|
||||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
|
@ -48,7 +48,7 @@ export interface CustomAppDetailsPageProps {
|
|||
onTokenClose: () => void;
|
||||
onTokenCreate: () => void;
|
||||
onSubmit: (
|
||||
data: CustomAppDetailsPageFormData
|
||||
data: CustomAppDetailsPageFormData,
|
||||
) => SubmitPromise<AppErrorFragment[]>;
|
||||
webhookCreateHref: string;
|
||||
onWebhookRemove: (id: string) => void;
|
||||
|
@ -73,7 +73,7 @@ const CustomAppDetailsPage: React.FC<CustomAppDetailsPageProps> = props => {
|
|||
webhookCreateHref,
|
||||
onWebhookRemove,
|
||||
onAppActivateOpen,
|
||||
onAppDeactivateOpen
|
||||
onAppDeactivateOpen,
|
||||
} = props;
|
||||
const intl = useIntl();
|
||||
const classes = useStyles({});
|
||||
|
@ -89,11 +89,11 @@ const CustomAppDetailsPage: React.FC<CustomAppDetailsPageProps> = props => {
|
|||
permissions?.filter(
|
||||
perm =>
|
||||
app?.permissions?.filter(userPerm => userPerm.code === perm.code)
|
||||
.length === 0
|
||||
.length === 0,
|
||||
).length === 0 || false,
|
||||
isActive: !!app?.isActive,
|
||||
name: app?.name || "",
|
||||
permissions: app?.permissions?.map(perm => perm.code) || []
|
||||
permissions: app?.permissions?.map(perm => perm.code) || [],
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -174,13 +174,13 @@ const CustomAppDetailsPage: React.FC<CustomAppDetailsPageProps> = props => {
|
|||
fullAccessLabel={intl.formatMessage({
|
||||
id: "D4nzdD",
|
||||
defaultMessage: "Grant this app full access to the store",
|
||||
description: "checkbox label"
|
||||
description: "checkbox label",
|
||||
})}
|
||||
description={intl.formatMessage({
|
||||
id: "flP8Hj",
|
||||
defaultMessage:
|
||||
"Expand or restrict app permissions to access certain part of Saleor system.",
|
||||
description: "card description"
|
||||
description: "card description",
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -20,7 +20,7 @@ const CustomAppInformation: React.FC<CustomAppInfoProps> = ({
|
|||
data,
|
||||
disabled,
|
||||
errors,
|
||||
onChange
|
||||
onChange,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
|
||||
|
@ -32,7 +32,7 @@ const CustomAppInformation: React.FC<CustomAppInfoProps> = ({
|
|||
title={intl.formatMessage({
|
||||
id: "imYxM9",
|
||||
defaultMessage: "App Information",
|
||||
description: "header"
|
||||
description: "header",
|
||||
})}
|
||||
/>
|
||||
<CardContent>
|
||||
|
@ -42,7 +42,7 @@ const CustomAppInformation: React.FC<CustomAppInfoProps> = ({
|
|||
label={intl.formatMessage({
|
||||
id: "foNlhn",
|
||||
defaultMessage: "App Name",
|
||||
description: "custom app name"
|
||||
description: "custom app name",
|
||||
})}
|
||||
helperText={getAppErrorMessage(formErrors.name, intl)}
|
||||
fullWidth
|
||||
|
|
|
@ -3,7 +3,7 @@ import {
|
|||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableRow
|
||||
TableRow,
|
||||
} from "@material-ui/core";
|
||||
import { Button } from "@saleor/components/Button";
|
||||
import CardTitle from "@saleor/components/CardTitle";
|
||||
|
@ -36,7 +36,7 @@ const CustomAppTokens: React.FC<CustomAppTokensProps> = props => {
|
|||
title={intl.formatMessage({
|
||||
id: "0Mg8o5",
|
||||
defaultMessage: "Tokens",
|
||||
description: "header"
|
||||
description: "header",
|
||||
})}
|
||||
toolbar={
|
||||
<Button
|
||||
|
@ -105,7 +105,7 @@ const CustomAppTokens: React.FC<CustomAppTokensProps> = props => {
|
|||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)
|
||||
),
|
||||
)}
|
||||
</TableBody>
|
||||
</ResponsiveTable>
|
||||
|
|
|
@ -4,20 +4,20 @@ export const useStyles = makeStyles(
|
|||
theme => ({
|
||||
[theme.breakpoints.down("md")]: {
|
||||
colNote: {
|
||||
width: 200
|
||||
}
|
||||
width: 200,
|
||||
},
|
||||
},
|
||||
colActions: {
|
||||
textAlign: "right",
|
||||
width: 100
|
||||
width: 100,
|
||||
},
|
||||
colKey: {
|
||||
width: 200
|
||||
width: 200,
|
||||
},
|
||||
colNote: {},
|
||||
table: {
|
||||
tableLayout: "fixed"
|
||||
}
|
||||
tableLayout: "fixed",
|
||||
},
|
||||
}),
|
||||
{ name: "CustomAppTokens" }
|
||||
{ name: "CustomAppTokens" },
|
||||
);
|
||||
|
|
|
@ -3,7 +3,7 @@ import {
|
|||
TableBody,
|
||||
TableCell,
|
||||
TableRow,
|
||||
Typography
|
||||
Typography,
|
||||
} from "@material-ui/core";
|
||||
import { customAppAddUrl } from "@saleor/apps/urls";
|
||||
import { Button } from "@saleor/components/Button";
|
||||
|
@ -30,7 +30,7 @@ export interface CustomAppsProps {
|
|||
const CustomApps: React.FC<CustomAppsProps> = ({
|
||||
appsList,
|
||||
onRemove,
|
||||
getCustomAppHref
|
||||
getCustomAppHref,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const classes = useStyles({});
|
||||
|
@ -101,7 +101,7 @@ const CustomApps: React.FC<CustomAppsProps> = ({
|
|||
</Typography>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)
|
||||
),
|
||||
)}
|
||||
</TableBody>
|
||||
</ResponsiveTable>
|
||||
|
|
|
@ -13,14 +13,14 @@ export const useStyles = makeStyles(
|
|||
position: "absolute",
|
||||
top: "50%",
|
||||
transform: "translateY(-50%)",
|
||||
width: 8
|
||||
width: 8,
|
||||
},
|
||||
color: theme.palette.error.main,
|
||||
display: "inline-block",
|
||||
marginLeft: theme.spacing(1.5),
|
||||
paddingLeft: theme.spacing(2),
|
||||
position: "relative"
|
||||
}
|
||||
position: "relative",
|
||||
},
|
||||
}),
|
||||
{ name: "DeactivatedText" }
|
||||
{ name: "DeactivatedText" },
|
||||
);
|
||||
|
|
|
@ -8,10 +8,10 @@ export interface HorizontalSpacerProps {
|
|||
const useStyles = makeStyles(
|
||||
theme => ({
|
||||
container: ({ spacing }: HorizontalSpacerProps) => ({
|
||||
width: theme.spacing(spacing)
|
||||
})
|
||||
width: theme.spacing(spacing),
|
||||
}),
|
||||
}),
|
||||
{ name: "HorizontalSpacer" }
|
||||
{ name: "HorizontalSpacer" },
|
||||
);
|
||||
|
||||
const HorizontalSpacer: React.FC<HorizontalSpacerProps> = ({ spacing = 1 }) => {
|
||||
|
|
|
@ -4,7 +4,7 @@ import {
|
|||
TableBody,
|
||||
TableCell,
|
||||
TableRow,
|
||||
Typography
|
||||
Typography,
|
||||
} from "@material-ui/core";
|
||||
import { useAppListContext } from "@saleor/apps/context";
|
||||
import { appUrl } from "@saleor/apps/urls";
|
||||
|
@ -55,7 +55,7 @@ const InstalledApps: React.FC<InstalledAppsProps> = ({
|
|||
title={intl.formatMessage({
|
||||
id: "BvmnJq",
|
||||
defaultMessage: "Third Party Apps",
|
||||
description: "section header"
|
||||
description: "section header",
|
||||
})}
|
||||
/>
|
||||
<ResponsiveTable>
|
||||
|
@ -116,7 +116,7 @@ const InstalledApps: React.FC<InstalledAppsProps> = ({
|
|||
</Typography>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)
|
||||
),
|
||||
)}
|
||||
</TableBody>
|
||||
</ResponsiveTable>
|
||||
|
|
|
@ -18,7 +18,7 @@ const Marketplace: React.FC<MarketplaceProps> = ({ link }) => {
|
|||
title={intl.formatMessage({
|
||||
id: "SwISVH",
|
||||
defaultMessage: "Saleor Marketplace",
|
||||
description: "section header"
|
||||
description: "section header",
|
||||
})}
|
||||
/>
|
||||
<CardContent>
|
||||
|
|
|
@ -5,7 +5,7 @@ import {
|
|||
DialogTitle,
|
||||
Paper,
|
||||
TextField,
|
||||
Typography
|
||||
Typography,
|
||||
} from "@material-ui/core";
|
||||
import BackButton from "@saleor/components/BackButton";
|
||||
import { Button } from "@saleor/components/Button";
|
||||
|
@ -49,7 +49,7 @@ const TokenCreateDialog: React.FC<TokenCreateDialogProps> = props => {
|
|||
}, [token]);
|
||||
|
||||
useModalDialogOpen(open, {
|
||||
onClose: () => setStep("form")
|
||||
onClose: () => setStep("form"),
|
||||
});
|
||||
|
||||
return (
|
||||
|
@ -77,7 +77,7 @@ const TokenCreateDialog: React.FC<TokenCreateDialogProps> = props => {
|
|||
<TextField
|
||||
label={intl.formatMessage({
|
||||
id: "0DRBjg",
|
||||
defaultMessage: "Token Note"
|
||||
defaultMessage: "Token Note",
|
||||
})}
|
||||
value={data.name}
|
||||
onChange={change}
|
||||
|
|
|
@ -4,19 +4,19 @@ import { makeStyles } from "@saleor/macaw-ui";
|
|||
export const useStyles = makeStyles(
|
||||
theme => ({
|
||||
cancel: {
|
||||
marginRight: theme.spacing(1)
|
||||
marginRight: theme.spacing(1),
|
||||
},
|
||||
copy: {
|
||||
marginTop: theme.spacing(),
|
||||
position: "relative",
|
||||
right: theme.spacing(1)
|
||||
right: theme.spacing(1),
|
||||
},
|
||||
paper: {
|
||||
background: fade(theme.palette.primary.main, 0.05),
|
||||
padding: theme.spacing(2, 3)
|
||||
}
|
||||
padding: theme.spacing(2, 3),
|
||||
},
|
||||
}),
|
||||
{
|
||||
name: "TokenCreateDialog"
|
||||
}
|
||||
name: "TokenCreateDialog",
|
||||
},
|
||||
);
|
||||
|
|
|
@ -9,7 +9,7 @@ const props: TokenDeleteDialogProps = {
|
|||
name: "Slack",
|
||||
onClose: () => undefined,
|
||||
onConfirm: () => undefined,
|
||||
open: true
|
||||
open: true,
|
||||
};
|
||||
|
||||
storiesOf("Views / Apps / Custom app details / Token delete", module)
|
||||
|
|
|
@ -17,7 +17,7 @@ const TokenDeleteDialog: React.FC<TokenDeleteDialogProps> = ({
|
|||
confirmButtonState,
|
||||
onClose,
|
||||
onConfirm,
|
||||
open
|
||||
open,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
|
||||
|
@ -31,7 +31,7 @@ const TokenDeleteDialog: React.FC<TokenDeleteDialogProps> = ({
|
|||
title={intl.formatMessage({
|
||||
id: "quV5zH",
|
||||
defaultMessage: "Delete Token",
|
||||
description: "dialog title"
|
||||
description: "dialog title",
|
||||
})}
|
||||
>
|
||||
<DialogContentText>
|
||||
|
@ -40,7 +40,7 @@ const TokenDeleteDialog: React.FC<TokenDeleteDialogProps> = ({
|
|||
defaultMessage="Are you sure you want to delete token {token}?"
|
||||
description="delete token"
|
||||
values={{
|
||||
token: <strong>{name}</strong>
|
||||
token: <strong>{name}</strong>,
|
||||
}}
|
||||
/>
|
||||
</DialogContentText>
|
||||
|
|
|
@ -8,10 +8,10 @@ export interface VerticalSpacerProps {
|
|||
const useStyles = makeStyles(
|
||||
theme => ({
|
||||
container: ({ spacing }: VerticalSpacerProps) => ({
|
||||
height: theme.spacing(spacing)
|
||||
})
|
||||
height: theme.spacing(spacing),
|
||||
}),
|
||||
}),
|
||||
{ name: "VerticalSpacer" }
|
||||
{ name: "VerticalSpacer" },
|
||||
);
|
||||
|
||||
const VerticalSpacer: React.FC<VerticalSpacerProps> = ({ spacing = 1 }) => {
|
||||
|
|
|
@ -5,7 +5,7 @@ import {
|
|||
AppsListQuery,
|
||||
AppTypeEnum,
|
||||
JobStatusEnum,
|
||||
PermissionEnum
|
||||
PermissionEnum,
|
||||
} from "@saleor/graphql";
|
||||
|
||||
export const appsList: AppsListQuery["apps"]["edges"] = [
|
||||
|
@ -22,10 +22,10 @@ export const appsList: AppsListQuery["apps"]["edges"] = [
|
|||
{
|
||||
__typename: "Permission",
|
||||
code: PermissionEnum.MANAGE_USERS,
|
||||
name: "Manage customers."
|
||||
}
|
||||
]
|
||||
}
|
||||
name: "Manage customers.",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: "AppCountableEdge",
|
||||
|
@ -40,16 +40,16 @@ export const appsList: AppsListQuery["apps"]["edges"] = [
|
|||
{
|
||||
__typename: "Permission",
|
||||
code: PermissionEnum.MANAGE_ORDERS,
|
||||
name: "Manage orders."
|
||||
name: "Manage orders.",
|
||||
},
|
||||
{
|
||||
__typename: "Permission",
|
||||
code: PermissionEnum.MANAGE_USERS,
|
||||
name: "Manage customers."
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
name: "Manage customers.",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export const customAppsList: AppsListQuery["apps"]["edges"] = [
|
||||
|
@ -66,16 +66,16 @@ export const customAppsList: AppsListQuery["apps"]["edges"] = [
|
|||
{
|
||||
__typename: "Permission",
|
||||
code: PermissionEnum.MANAGE_ORDERS,
|
||||
name: "Manage orders."
|
||||
name: "Manage orders.",
|
||||
},
|
||||
{
|
||||
__typename: "Permission",
|
||||
code: PermissionEnum.MANAGE_USERS,
|
||||
name: "Manage customers."
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
name: "Manage customers.",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export const appsInProgress: AppsInstallationsQuery["appsInstallations"] = [
|
||||
|
@ -85,7 +85,7 @@ export const appsInProgress: AppsInstallationsQuery["appsInstallations"] = [
|
|||
id: "QXBwSW5zdGFsbGF0aW9uOjk2",
|
||||
manifestUrl: "http://localhost:3000/manifest",
|
||||
message: "Failed to connect to app. Try later or contact with app support.",
|
||||
status: JobStatusEnum.FAILED
|
||||
status: JobStatusEnum.FAILED,
|
||||
},
|
||||
{
|
||||
__typename: "AppInstallation",
|
||||
|
@ -93,7 +93,7 @@ export const appsInProgress: AppsInstallationsQuery["appsInstallations"] = [
|
|||
id: "QXBwSW5zdGFsbGF0aW9uOjk2",
|
||||
manifestUrl: "http://localhost:3000/manifest",
|
||||
message: "Pending.",
|
||||
status: JobStatusEnum.PENDING
|
||||
status: JobStatusEnum.PENDING,
|
||||
},
|
||||
{
|
||||
__typename: "AppInstallation",
|
||||
|
@ -101,8 +101,8 @@ export const appsInProgress: AppsInstallationsQuery["appsInstallations"] = [
|
|||
id: "QXBwSW5zdGFsbGF0aW9uOjk2",
|
||||
manifestUrl: "http://localhost:3000/manifest",
|
||||
message: "Success.",
|
||||
status: JobStatusEnum.SUCCESS
|
||||
}
|
||||
status: JobStatusEnum.SUCCESS,
|
||||
},
|
||||
];
|
||||
|
||||
export const appDetails: AppQuery["app"] = {
|
||||
|
@ -123,20 +123,20 @@ export const appDetails: AppQuery["app"] = {
|
|||
{
|
||||
__typename: "Permission",
|
||||
code: PermissionEnum.MANAGE_ORDERS,
|
||||
name: "Manage orders."
|
||||
name: "Manage orders.",
|
||||
},
|
||||
{
|
||||
__typename: "Permission",
|
||||
code: PermissionEnum.MANAGE_USERS,
|
||||
name: "Manage customers."
|
||||
}
|
||||
name: "Manage customers.",
|
||||
},
|
||||
],
|
||||
privateMetadata: [],
|
||||
supportUrl: "http://localhost:8888/support",
|
||||
tokens: [],
|
||||
type: AppTypeEnum.THIRDPARTY,
|
||||
version: "1.0.0",
|
||||
webhooks: []
|
||||
webhooks: [],
|
||||
};
|
||||
|
||||
export const installApp: AppFetchMutation["appFetchManifest"]["manifest"] = {
|
||||
|
@ -153,15 +153,15 @@ export const installApp: AppFetchMutation["appFetchManifest"]["manifest"] = {
|
|||
{
|
||||
__typename: "Permission",
|
||||
code: PermissionEnum.MANAGE_USERS,
|
||||
name: "Manage users"
|
||||
name: "Manage users",
|
||||
},
|
||||
{
|
||||
__typename: "Permission",
|
||||
code: PermissionEnum.MANAGE_ORDERS,
|
||||
name: "Manage orders"
|
||||
}
|
||||
name: "Manage orders",
|
||||
},
|
||||
],
|
||||
supportUrl: null,
|
||||
tokenTargetUrl: null,
|
||||
version: "1.0"
|
||||
version: "1.0",
|
||||
};
|
||||
|
|
|
@ -17,7 +17,7 @@ import {
|
|||
appsListPath,
|
||||
customAppAddPath,
|
||||
customAppPath,
|
||||
CustomAppUrlQueryParams
|
||||
CustomAppUrlQueryParams,
|
||||
} from "./urls";
|
||||
import AppView from "./views/App";
|
||||
import AppDetailsView from "./views/AppDetails";
|
||||
|
@ -28,7 +28,7 @@ import CustomAppCreateView from "./views/CustomAppCreate";
|
|||
import CustomAppDetailsView from "./views/CustomAppDetails";
|
||||
|
||||
const AppDetails: React.FC<RouteComponentProps<{ id: string }>> = ({
|
||||
match
|
||||
match,
|
||||
}) => {
|
||||
const qs = parseQs(location.search.substr(1));
|
||||
const params: AppDetailsUrlQueryParams = qs;
|
||||
|
@ -39,7 +39,7 @@ const AppDetails: React.FC<RouteComponentProps<{ id: string }>> = ({
|
|||
};
|
||||
|
||||
const AppSettings: React.FC<RouteComponentProps<{ id: string }>> = ({
|
||||
match
|
||||
match,
|
||||
}) => <AppSettingsView id={decodeURIComponent(match.params.id)} />;
|
||||
|
||||
const App: React.FC<RouteComponentProps<{ id: string }>> = ({ match }) => (
|
||||
|
@ -61,7 +61,7 @@ interface CustomAppDetailsProps extends RouteComponentProps<{ id?: string }> {
|
|||
const CustomAppDetails: React.FC<CustomAppDetailsProps> = ({
|
||||
match,
|
||||
token,
|
||||
onTokenClose
|
||||
onTokenClose,
|
||||
}) => {
|
||||
const qs = parseQs(location.search.substr(1));
|
||||
const params: CustomAppUrlQueryParams = qs;
|
||||
|
|
|
@ -4,16 +4,16 @@ export const appMessages = defineMessages({
|
|||
failedToFetchAppSettings: {
|
||||
id: "ac+Y98",
|
||||
defaultMessage: "Failed to fetch app settings",
|
||||
description: "app settings error"
|
||||
description: "app settings error",
|
||||
},
|
||||
appActivated: {
|
||||
id: "D/+84n",
|
||||
defaultMessage: "App activated",
|
||||
description: "snackbar text"
|
||||
description: "snackbar text",
|
||||
},
|
||||
appDeactivated: {
|
||||
id: "USO8PB",
|
||||
defaultMessage: "App deactivated",
|
||||
description: "snackbar text"
|
||||
}
|
||||
description: "snackbar text",
|
||||
},
|
||||
});
|
||||
|
|
|
@ -5,89 +5,89 @@ export const useStyles = makeStyles(
|
|||
[theme.breakpoints.up("lg")]: {
|
||||
colName: {
|
||||
"&&": {
|
||||
width: "auto"
|
||||
}
|
||||
}
|
||||
width: "auto",
|
||||
},
|
||||
},
|
||||
},
|
||||
alignRight: {
|
||||
textAlign: "right"
|
||||
textAlign: "right",
|
||||
},
|
||||
apps: {
|
||||
marginBottom: theme.spacing(4)
|
||||
marginBottom: theme.spacing(4),
|
||||
},
|
||||
appContent: {
|
||||
"&:last-child": {
|
||||
padding: "0!important"
|
||||
padding: "0!important",
|
||||
},
|
||||
padding: 0
|
||||
padding: 0,
|
||||
},
|
||||
appHeader: {
|
||||
marginBottom: theme.spacing(3)
|
||||
marginBottom: theme.spacing(3),
|
||||
},
|
||||
appHeaderLinks: {
|
||||
"& img": {
|
||||
marginRight: theme.spacing(1)
|
||||
marginRight: theme.spacing(1),
|
||||
},
|
||||
alignItems: "center",
|
||||
display: "flex",
|
||||
padding: theme.spacing(2, 0)
|
||||
padding: theme.spacing(2, 0),
|
||||
},
|
||||
appName: {
|
||||
color: theme.palette.primary.main
|
||||
color: theme.palette.primary.main,
|
||||
},
|
||||
colAction: {
|
||||
"&&": {
|
||||
paddingRight: theme.spacing(3),
|
||||
textAlign: "right"
|
||||
textAlign: "right",
|
||||
},
|
||||
alignItems: "center",
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
justifyContent: "flex-end",
|
||||
textAlign: "right"
|
||||
textAlign: "right",
|
||||
},
|
||||
colInstallAction: {
|
||||
"& > *": {
|
||||
display: "inline-flex"
|
||||
}
|
||||
display: "inline-flex",
|
||||
},
|
||||
},
|
||||
colName: {
|
||||
paddingLeft: 0,
|
||||
width: theme.spacing(30)
|
||||
width: theme.spacing(30),
|
||||
},
|
||||
colSpinner: {
|
||||
"& svg": {
|
||||
textAlign: "right"
|
||||
textAlign: "right",
|
||||
},
|
||||
paddingLeft: theme.spacing(3),
|
||||
paddingRight: theme.spacing(2)
|
||||
paddingRight: theme.spacing(2),
|
||||
},
|
||||
customApps: {
|
||||
marginBottom: theme.spacing(4)
|
||||
marginBottom: theme.spacing(4),
|
||||
},
|
||||
customTooltip: {
|
||||
"& > div": {
|
||||
backgroundColor: theme.palette.error.main,
|
||||
borderRadius: theme.spacing(1),
|
||||
color: theme.palette.primary.contrastText,
|
||||
padding: theme.spacing(2)
|
||||
padding: theme.spacing(2),
|
||||
},
|
||||
padding: "0!important"
|
||||
padding: "0!important",
|
||||
},
|
||||
error: {
|
||||
"& button": {
|
||||
marginLeft: theme.spacing(0.6)
|
||||
marginLeft: theme.spacing(0.6),
|
||||
},
|
||||
color: theme.palette.error.main,
|
||||
marginRight: theme.spacing(1),
|
||||
alignItems: "flex-end"
|
||||
alignItems: "flex-end",
|
||||
},
|
||||
headerLinkContainer: {
|
||||
"& svg": {
|
||||
marginRight: theme.spacing()
|
||||
marginRight: theme.spacing(),
|
||||
},
|
||||
"& span": {
|
||||
fontWeight: 500
|
||||
fontWeight: 500,
|
||||
},
|
||||
alignItems: "center",
|
||||
color: theme.palette.text.primary,
|
||||
|
@ -97,7 +97,7 @@ export const useStyles = makeStyles(
|
|||
lineHeight: 1.2,
|
||||
marginRight: theme.spacing(3),
|
||||
padding: 0,
|
||||
textTransform: "none"
|
||||
textTransform: "none",
|
||||
},
|
||||
hr: {
|
||||
border: "none",
|
||||
|
@ -105,20 +105,20 @@ export const useStyles = makeStyles(
|
|||
height: 0,
|
||||
marginBottom: 0,
|
||||
marginTop: 0,
|
||||
width: "100%"
|
||||
width: "100%",
|
||||
},
|
||||
installAppContainer: {
|
||||
"& > div": {
|
||||
position: "relative"
|
||||
position: "relative",
|
||||
},
|
||||
"& img": {
|
||||
position: "relative"
|
||||
position: "relative",
|
||||
},
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
padding: theme.spacing(2, 0),
|
||||
position: "relative",
|
||||
width: theme.spacing(35)
|
||||
width: theme.spacing(35),
|
||||
},
|
||||
installCard: {
|
||||
"&:before": {
|
||||
|
@ -128,11 +128,11 @@ export const useStyles = makeStyles(
|
|||
position: "absolute",
|
||||
top: "50%",
|
||||
transform: "translateY(-50%)",
|
||||
width: theme.spacing(30)
|
||||
width: theme.spacing(30),
|
||||
},
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
position: "relative"
|
||||
position: "relative",
|
||||
},
|
||||
installIcon: {
|
||||
alignItems: "center",
|
||||
|
@ -143,76 +143,76 @@ export const useStyles = makeStyles(
|
|||
height: theme.spacing(9),
|
||||
justifyContent: "center",
|
||||
overflow: "hidden",
|
||||
width: theme.spacing(9)
|
||||
width: theme.spacing(9),
|
||||
},
|
||||
installPermissionTitle: {
|
||||
fontWeight: 500
|
||||
fontWeight: 500,
|
||||
},
|
||||
installPrivacyText: {
|
||||
"& a": {
|
||||
color: theme.palette.primary.main,
|
||||
textDecoration: "none"
|
||||
textDecoration: "none",
|
||||
},
|
||||
color: theme.palette.text.hint,
|
||||
marginTop: theme.spacing(1)
|
||||
marginTop: theme.spacing(1),
|
||||
},
|
||||
installSaleorIcon: {
|
||||
backgroundColor: theme.palette.secondary.main,
|
||||
border: "none"
|
||||
border: "none",
|
||||
},
|
||||
installSpacer: {
|
||||
margin: theme.spacing(2, 0)
|
||||
margin: theme.spacing(2, 0),
|
||||
},
|
||||
installText: {
|
||||
color: theme.palette.primary.contrastText
|
||||
color: theme.palette.primary.contrastText,
|
||||
},
|
||||
linkContainer: {
|
||||
fontWeight: 500,
|
||||
marginTop: theme.spacing(1.5)
|
||||
marginTop: theme.spacing(1.5),
|
||||
},
|
||||
marketplaceContent: {
|
||||
"& button": {
|
||||
marginTop: theme.spacing(1)
|
||||
marginTop: theme.spacing(1),
|
||||
},
|
||||
"&:last-child": {
|
||||
padding: theme.spacing(2, 3, 2, 3)
|
||||
padding: theme.spacing(2, 3, 2, 3),
|
||||
},
|
||||
padding: theme.spacing(1)
|
||||
padding: theme.spacing(1),
|
||||
},
|
||||
permissionsContainer: {
|
||||
"& li": {
|
||||
"&:last-child": {
|
||||
marginBottom: 0
|
||||
marginBottom: 0,
|
||||
},
|
||||
marginBottom: theme.spacing(1)
|
||||
marginBottom: theme.spacing(1),
|
||||
},
|
||||
paddingLeft: theme.spacing(2)
|
||||
paddingLeft: theme.spacing(2),
|
||||
},
|
||||
retryBtnCol: {
|
||||
paddingRight: theme.spacing(1),
|
||||
width: theme.spacing(14)
|
||||
width: theme.spacing(14),
|
||||
},
|
||||
statusWrapper: {
|
||||
display: "inline-block",
|
||||
marginLeft: theme.spacing(2.5)
|
||||
marginLeft: theme.spacing(2.5),
|
||||
},
|
||||
table: {
|
||||
tableLayout: "fixed"
|
||||
tableLayout: "fixed",
|
||||
},
|
||||
tableRow: {
|
||||
cursor: "pointer"
|
||||
cursor: "pointer",
|
||||
},
|
||||
text: {
|
||||
color: theme.palette.text.secondary
|
||||
color: theme.palette.text.secondary,
|
||||
},
|
||||
activateButton: {
|
||||
"& img": {
|
||||
marginRight: theme.spacing(1)
|
||||
}
|
||||
marginRight: theme.spacing(1),
|
||||
},
|
||||
},
|
||||
appUrl: {
|
||||
marginRight: theme.spacing(1)
|
||||
}
|
||||
marginRight: theme.spacing(1),
|
||||
},
|
||||
}),
|
||||
{ name: "AppList" }
|
||||
{ name: "AppList" },
|
||||
);
|
||||
|
|
|
@ -26,7 +26,7 @@ export type AppInstallUrlQueryParams = Partial<{ [MANIFEST_ATTR]: string }>;
|
|||
|
||||
export enum AppListUrlSortField {
|
||||
name = "name",
|
||||
active = "active"
|
||||
active = "active",
|
||||
}
|
||||
|
||||
export type CustomAppUrlDialog =
|
||||
|
@ -60,20 +60,20 @@ export const appUrl = (id: string, params?: AppDetailsUrlQueryParams) =>
|
|||
export const appDeepUrl = (
|
||||
id: string,
|
||||
subPath: string,
|
||||
params?: AppDetailsUrlQueryParams
|
||||
params?: AppDetailsUrlQueryParams,
|
||||
) => appDeepPath(encodeURIComponent(id), subPath) + "?" + stringifyQs(params);
|
||||
|
||||
export const getAppCompleteUrlFromDashboardUrl = (
|
||||
dashboardUrl: string,
|
||||
appUrl?: string,
|
||||
appId?: string
|
||||
appId?: string,
|
||||
) => {
|
||||
if (!appUrl || !appId) {
|
||||
return appUrl;
|
||||
}
|
||||
const deepSubPath = dashboardUrl.replace(
|
||||
appPath(encodeURIComponent(appId)),
|
||||
""
|
||||
"",
|
||||
);
|
||||
const appCompleteUrl = urlJoin(appUrl, deepSubPath);
|
||||
return appCompleteUrl;
|
||||
|
@ -81,7 +81,7 @@ export const getAppCompleteUrlFromDashboardUrl = (
|
|||
export const getDashboardUrFromAppCompleteUrl = (
|
||||
appCompleteUrl: string,
|
||||
appUrl?: string,
|
||||
appId?: string
|
||||
appId?: string,
|
||||
) => {
|
||||
if (!appUrl || !appId) {
|
||||
return appUrl;
|
||||
|
|
|
@ -3,7 +3,7 @@ import {
|
|||
AppExtensionMountEnum,
|
||||
ExtensionListQuery,
|
||||
PermissionEnum,
|
||||
useExtensionListQuery
|
||||
useExtensionListQuery,
|
||||
} from "@saleor/graphql";
|
||||
import { RelayToFlat } from "@saleor/types";
|
||||
import { mapEdgesToItems } from "@saleor/utils/maps";
|
||||
|
@ -23,11 +23,11 @@ export interface Extension {
|
|||
export const extensionMountPoints = {
|
||||
PRODUCT_LIST: [
|
||||
AppExtensionMountEnum.PRODUCT_OVERVIEW_CREATE,
|
||||
AppExtensionMountEnum.PRODUCT_OVERVIEW_MORE_ACTIONS
|
||||
AppExtensionMountEnum.PRODUCT_OVERVIEW_MORE_ACTIONS,
|
||||
],
|
||||
ORDER_LIST: [
|
||||
AppExtensionMountEnum.ORDER_OVERVIEW_CREATE,
|
||||
AppExtensionMountEnum.ORDER_OVERVIEW_MORE_ACTIONS
|
||||
AppExtensionMountEnum.ORDER_OVERVIEW_MORE_ACTIONS,
|
||||
],
|
||||
ORDER_DETAILS: [AppExtensionMountEnum.ORDER_DETAILS_MORE_ACTIONS],
|
||||
PRODUCT_DETAILS: [AppExtensionMountEnum.PRODUCT_DETAILS_MORE_ACTIONS],
|
||||
|
@ -37,13 +37,13 @@ export const extensionMountPoints = {
|
|||
AppExtensionMountEnum.NAVIGATION_DISCOUNTS,
|
||||
AppExtensionMountEnum.NAVIGATION_ORDERS,
|
||||
AppExtensionMountEnum.NAVIGATION_PAGES,
|
||||
AppExtensionMountEnum.NAVIGATION_TRANSLATIONS
|
||||
]
|
||||
AppExtensionMountEnum.NAVIGATION_TRANSLATIONS,
|
||||
],
|
||||
};
|
||||
|
||||
const filterAndMapToTarget = (
|
||||
extensions: RelayToFlat<ExtensionListQuery["appExtensions"]>,
|
||||
openApp: (appData: AppData) => void
|
||||
openApp: (appData: AppData) => void,
|
||||
): Extension[] =>
|
||||
extensions.map(
|
||||
({ id, accessToken, permissions, url, label, mount, target, app }) => ({
|
||||
|
@ -55,44 +55,44 @@ const filterAndMapToTarget = (
|
|||
label,
|
||||
mount,
|
||||
open: () =>
|
||||
openApp({ id: app.id, appToken: accessToken, src: url, label, target })
|
||||
})
|
||||
openApp({ id: app.id, appToken: accessToken, src: url, label, target }),
|
||||
}),
|
||||
);
|
||||
|
||||
export const mapToMenuItems = (extensions: Extension[]) =>
|
||||
extensions.map(({ label, id, open }) => ({
|
||||
label,
|
||||
testId: `extension-${id}`,
|
||||
onSelect: open
|
||||
onSelect: open,
|
||||
}));
|
||||
|
||||
export const useExtensions = <T extends AppExtensionMountEnum>(
|
||||
mountList: T[]
|
||||
mountList: T[],
|
||||
): Record<T, Extension[]> => {
|
||||
const { openApp } = useExternalApp();
|
||||
const permissions = useUserPermissions();
|
||||
const extensionsPermissions = permissions?.find(
|
||||
perm => perm.code === PermissionEnum.MANAGE_APPS
|
||||
perm => perm.code === PermissionEnum.MANAGE_APPS,
|
||||
);
|
||||
|
||||
const { data } = useExtensionListQuery({
|
||||
fetchPolicy: "cache-first",
|
||||
variables: {
|
||||
filter: {
|
||||
mount: mountList
|
||||
}
|
||||
mount: mountList,
|
||||
},
|
||||
},
|
||||
skip: !extensionsPermissions
|
||||
skip: !extensionsPermissions,
|
||||
});
|
||||
|
||||
const extensions = filterAndMapToTarget(
|
||||
mapEdgesToItems(data?.appExtensions) || [],
|
||||
openApp
|
||||
openApp,
|
||||
);
|
||||
|
||||
const extensionsMap = mountList.reduce(
|
||||
(extensionsMap, mount) => ({ ...extensionsMap, [mount]: [] }),
|
||||
{} as Record<T, Extension[]>
|
||||
{} as Record<T, Extension[]>,
|
||||
);
|
||||
|
||||
return extensions.reduce(
|
||||
|
@ -100,9 +100,9 @@ export const useExtensions = <T extends AppExtensionMountEnum>(
|
|||
...prevExtensionsMap,
|
||||
[extension.mount]: [
|
||||
...(prevExtensionsMap[extension.mount] || []),
|
||||
extension
|
||||
]
|
||||
extension,
|
||||
],
|
||||
}),
|
||||
extensionsMap
|
||||
extensionsMap,
|
||||
);
|
||||
};
|
||||
|
|
|
@ -11,7 +11,7 @@ import AppPage from "../../components/AppPage";
|
|||
import {
|
||||
appDetailsUrl,
|
||||
appsListPath,
|
||||
getAppCompleteUrlFromDashboardUrl
|
||||
getAppCompleteUrlFromDashboardUrl,
|
||||
} from "../../urls";
|
||||
|
||||
interface AppProps {
|
||||
|
@ -22,7 +22,7 @@ export const App: React.FC<AppProps> = ({ id }) => {
|
|||
const location = useLocation();
|
||||
const { data } = useAppQuery({
|
||||
displayLoader: true,
|
||||
variables: { id }
|
||||
variables: { id },
|
||||
});
|
||||
|
||||
const appExists = data?.app !== null;
|
||||
|
@ -38,7 +38,7 @@ export const App: React.FC<AppProps> = ({ id }) => {
|
|||
const appCompleteUrl = getAppCompleteUrlFromDashboardUrl(
|
||||
location.pathname,
|
||||
data?.app.appUrl,
|
||||
id
|
||||
id,
|
||||
);
|
||||
|
||||
return (
|
||||
|
@ -49,7 +49,7 @@ export const App: React.FC<AppProps> = ({ id }) => {
|
|||
onError={() =>
|
||||
notify({
|
||||
status: "error",
|
||||
text: intl.formatMessage(appMessages.failedToFetchAppSettings)
|
||||
text: intl.formatMessage(appMessages.failedToFetchAppSettings),
|
||||
})
|
||||
}
|
||||
/>
|
||||
|
|
|
@ -3,7 +3,7 @@ import NotFoundPage from "@saleor/components/NotFoundPage";
|
|||
import {
|
||||
useAppActivateMutation,
|
||||
useAppDeactivateMutation,
|
||||
useAppQuery
|
||||
useAppQuery,
|
||||
} from "@saleor/graphql";
|
||||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
import useNotifier from "@saleor/hooks/useNotifier";
|
||||
|
@ -20,7 +20,7 @@ import {
|
|||
AppDetailsUrlDialog,
|
||||
AppDetailsUrlQueryParams,
|
||||
appsListPath,
|
||||
appUrl
|
||||
appUrl,
|
||||
} from "../../urls";
|
||||
|
||||
interface AppDetailsProps {
|
||||
|
@ -31,7 +31,7 @@ interface AppDetailsProps {
|
|||
export const AppDetails: React.FC<AppDetailsProps> = ({ id, params }) => {
|
||||
const { data, loading, refetch } = useAppQuery({
|
||||
displayLoader: true,
|
||||
variables: { id }
|
||||
variables: { id },
|
||||
});
|
||||
|
||||
const appExists = data?.app !== null;
|
||||
|
@ -46,7 +46,7 @@ export const AppDetails: React.FC<AppDetailsProps> = ({ id, params }) => {
|
|||
if (errors?.length === 0) {
|
||||
notify({
|
||||
status: "success",
|
||||
text: intl.formatMessage(appMessages.appActivated)
|
||||
text: intl.formatMessage(appMessages.appActivated),
|
||||
});
|
||||
refetch();
|
||||
closeModal();
|
||||
|
@ -55,12 +55,12 @@ export const AppDetails: React.FC<AppDetailsProps> = ({ id, params }) => {
|
|||
errors.forEach(error =>
|
||||
notify({
|
||||
status: "error",
|
||||
text: getAppErrorMessage(error, intl)
|
||||
})
|
||||
text: getAppErrorMessage(error, intl),
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
const [deactivateApp, deactivateAppResult] = useAppDeactivateMutation({
|
||||
onCompleted: data => {
|
||||
|
@ -68,7 +68,7 @@ export const AppDetails: React.FC<AppDetailsProps> = ({ id, params }) => {
|
|||
if (errors.length === 0) {
|
||||
notify({
|
||||
status: "success",
|
||||
text: intl.formatMessage(appMessages.appDeactivated)
|
||||
text: intl.formatMessage(appMessages.appDeactivated),
|
||||
});
|
||||
refetch();
|
||||
closeModal();
|
||||
|
@ -77,12 +77,12 @@ export const AppDetails: React.FC<AppDetailsProps> = ({ id, params }) => {
|
|||
errors.forEach(error =>
|
||||
notify({
|
||||
status: "error",
|
||||
text: getAppErrorMessage(error, intl)
|
||||
})
|
||||
text: getAppErrorMessage(error, intl),
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const [openModal, closeModal] = createDialogActionHandlers<
|
||||
|
|
|
@ -14,7 +14,7 @@ import AppInstallPage from "../../components/AppInstallPage";
|
|||
import {
|
||||
AppInstallUrlQueryParams,
|
||||
appsListUrl,
|
||||
MANIFEST_ATTR
|
||||
MANIFEST_ATTR,
|
||||
} from "../../urls";
|
||||
import { messages } from "./messages";
|
||||
|
||||
|
@ -22,7 +22,7 @@ interface InstallAppCreateProps extends RouteComponentProps {
|
|||
params: AppInstallUrlQueryParams;
|
||||
}
|
||||
export const InstallAppCreate: React.FC<InstallAppCreateProps> = ({
|
||||
params
|
||||
params,
|
||||
}) => {
|
||||
const [, setActiveInstallations] = useLocalStorage("activeInstallations", []);
|
||||
const navigate = useNavigator();
|
||||
|
@ -36,11 +36,11 @@ export const InstallAppCreate: React.FC<InstallAppCreateProps> = ({
|
|||
data.appFetchManifest.errors.forEach(error => {
|
||||
notify({
|
||||
status: "error",
|
||||
text: getAppErrorMessage(error, intl)
|
||||
text: getAppErrorMessage(error, intl),
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
const [installApp] = useAppInstallMutation({
|
||||
onCompleted: data => {
|
||||
|
@ -48,18 +48,18 @@ export const InstallAppCreate: React.FC<InstallAppCreateProps> = ({
|
|||
if (data.appInstall.errors.length === 0) {
|
||||
setActiveInstallations(activeInstallations => [
|
||||
...activeInstallations,
|
||||
{ id: installationData.id, name: installationData.appName }
|
||||
{ id: installationData.id, name: installationData.appName },
|
||||
]);
|
||||
navigateToAppsList();
|
||||
} else {
|
||||
data.appInstall.errors.forEach(error => {
|
||||
notify({
|
||||
status: "error",
|
||||
text: getAppErrorMessage(error, intl)
|
||||
text: getAppErrorMessage(error, intl),
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const navigateToAppsList = () => navigate(appsListUrl());
|
||||
|
@ -73,11 +73,11 @@ export const InstallAppCreate: React.FC<InstallAppCreateProps> = ({
|
|||
appName: manifest?.name,
|
||||
manifestUrl,
|
||||
permissions: manifest?.permissions.map(
|
||||
permission => permission.code
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
permission => permission.code,
|
||||
),
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -4,6 +4,6 @@ export const messages = defineMessages({
|
|||
installApp: {
|
||||
id: "2cjt25",
|
||||
defaultMessage: "Install App",
|
||||
description: "window title"
|
||||
}
|
||||
description: "window title",
|
||||
},
|
||||
});
|
||||
|
|
|
@ -15,7 +15,7 @@ interface AppSettingsProps {
|
|||
export const AppSettings: React.FC<AppSettingsProps> = ({ id }) => {
|
||||
const { data } = useAppQuery({
|
||||
displayLoader: true,
|
||||
variables: { id }
|
||||
variables: { id },
|
||||
});
|
||||
|
||||
const appExists = data?.app !== null;
|
||||
|
@ -35,7 +35,7 @@ export const AppSettings: React.FC<AppSettingsProps> = ({ id }) => {
|
|||
onError={() =>
|
||||
notify({
|
||||
status: "error",
|
||||
text: intl.formatMessage(appMessages.failedToFetchAppSettings)
|
||||
text: intl.formatMessage(appMessages.failedToFetchAppSettings),
|
||||
})
|
||||
}
|
||||
/>
|
||||
|
|
|
@ -15,7 +15,7 @@ import {
|
|||
useAppDeleteMutation,
|
||||
useAppRetryInstallMutation,
|
||||
useAppsInstallationsQuery,
|
||||
useAppsListQuery
|
||||
useAppsListQuery,
|
||||
} from "@saleor/graphql";
|
||||
import useListSettings from "@saleor/hooks/useListSettings";
|
||||
import useLocalStorage from "@saleor/hooks/useLocalStorage";
|
||||
|
@ -23,7 +23,7 @@ import useNavigator from "@saleor/hooks/useNavigator";
|
|||
import useNotifier from "@saleor/hooks/useNotifier";
|
||||
import usePaginator, {
|
||||
createPaginationState,
|
||||
PaginatorContext
|
||||
PaginatorContext,
|
||||
} from "@saleor/hooks/usePaginator";
|
||||
import { ListViews } from "@saleor/types";
|
||||
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
||||
|
@ -38,18 +38,18 @@ import {
|
|||
AppListUrlDialog,
|
||||
AppListUrlQueryParams,
|
||||
appsListUrl,
|
||||
customAppUrl
|
||||
customAppUrl,
|
||||
} from "../../urls";
|
||||
import { messages } from "./messages";
|
||||
|
||||
const getCurrentAppName = (
|
||||
id: string,
|
||||
collection?: AppsListQuery["apps"]["edges"]
|
||||
collection?: AppsListQuery["apps"]["edges"],
|
||||
) => collection?.find(edge => edge.node.id === id)?.node?.name;
|
||||
|
||||
const getAppInProgressName = (
|
||||
id: string,
|
||||
collection?: AppsInstallationsQuery["appsInstallations"]
|
||||
collection?: AppsInstallationsQuery["appsInstallations"],
|
||||
) => collection?.find(app => app.id === id)?.appName;
|
||||
interface AppsListProps {
|
||||
params: AppListUrlQueryParams;
|
||||
|
@ -69,22 +69,22 @@ export const AppsList: React.FC<AppsListProps> = ({ params }) => {
|
|||
const queryVariables = {
|
||||
sort: {
|
||||
direction: OrderDirection.DESC,
|
||||
field: AppSortField.CREATION_DATE
|
||||
}
|
||||
field: AppSortField.CREATION_DATE,
|
||||
},
|
||||
};
|
||||
const intervalId = useRef<null | number>(null);
|
||||
|
||||
const removeInstallation = (id: string) =>
|
||||
setActiveInstallations(installations =>
|
||||
installations.filter(item => item.id !== id)
|
||||
installations.filter(item => item.id !== id),
|
||||
);
|
||||
|
||||
const {
|
||||
data: appsInProgressData,
|
||||
loading: loadingAppsInProgress,
|
||||
refetch: appsInProgressRefetch
|
||||
refetch: appsInProgressRefetch,
|
||||
} = useAppsInstallationsQuery({
|
||||
displayLoader: false
|
||||
displayLoader: false,
|
||||
});
|
||||
const { data, loading, refetch } = useAppsListQuery({
|
||||
displayLoader: true,
|
||||
|
@ -92,35 +92,35 @@ export const AppsList: React.FC<AppsListProps> = ({ params }) => {
|
|||
...paginationState,
|
||||
...queryVariables,
|
||||
filter: {
|
||||
type: AppTypeEnum.THIRDPARTY
|
||||
}
|
||||
}
|
||||
type: AppTypeEnum.THIRDPARTY,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const paginationValues = usePaginator({
|
||||
pageInfo: data?.apps?.pageInfo,
|
||||
paginationState,
|
||||
queryString: params
|
||||
queryString: params,
|
||||
});
|
||||
|
||||
const {
|
||||
data: customAppsData,
|
||||
loading: customAppsLoading,
|
||||
refetch: customAppsRefetch
|
||||
refetch: customAppsRefetch,
|
||||
} = useAppsListQuery({
|
||||
displayLoader: true,
|
||||
variables: {
|
||||
first: 100,
|
||||
...queryVariables,
|
||||
filter: {
|
||||
type: AppTypeEnum.LOCAL
|
||||
}
|
||||
}
|
||||
type: AppTypeEnum.LOCAL,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const refetchExtensionList = () => {
|
||||
client.refetchQueries({
|
||||
include: [EXTENSION_LIST_QUERY]
|
||||
include: [EXTENSION_LIST_QUERY],
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -128,7 +128,7 @@ export const AppsList: React.FC<AppsListProps> = ({ params }) => {
|
|||
notify({
|
||||
status: "success",
|
||||
text: intl.formatMessage(messages.appReadyToUse, { name }),
|
||||
title: intl.formatMessage(messages.appInstalled)
|
||||
title: intl.formatMessage(messages.appInstalled),
|
||||
});
|
||||
};
|
||||
const [retryInstallApp] = useAppRetryInstallMutation({
|
||||
|
@ -137,34 +137,34 @@ export const AppsList: React.FC<AppsListProps> = ({ params }) => {
|
|||
const appInstallation = data.appRetryInstall.appInstallation;
|
||||
setActiveInstallations(installations => [
|
||||
...installations,
|
||||
{ id: appInstallation.id, name: appInstallation.appName }
|
||||
{ id: appInstallation.id, name: appInstallation.appName },
|
||||
]);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
const [activateApp, activateAppResult] = useAppActivateMutation({
|
||||
onCompleted: data => {
|
||||
if (!data?.appActivate?.errors?.length) {
|
||||
notify({
|
||||
status: "success",
|
||||
text: intl.formatMessage(messages.appActivated)
|
||||
text: intl.formatMessage(messages.appActivated),
|
||||
});
|
||||
refetch();
|
||||
closeModal();
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
const [deactivateApp, deactivateAppResult] = useAppDeactivateMutation({
|
||||
onCompleted: data => {
|
||||
if (!data?.appDeactivate?.errors?.length) {
|
||||
notify({
|
||||
status: "success",
|
||||
text: intl.formatMessage(messages.appDeactivated)
|
||||
text: intl.formatMessage(messages.appDeactivated),
|
||||
});
|
||||
refetch();
|
||||
closeModal();
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
const [openModal, closeModal] = createDialogActionHandlers<
|
||||
AppListUrlDialog,
|
||||
|
@ -183,11 +183,11 @@ export const AppsList: React.FC<AppsListProps> = ({ params }) => {
|
|||
refetchExtensionList();
|
||||
removeAppNotify();
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
const [
|
||||
deleteInProgressApp,
|
||||
deleteInProgressAppOpts
|
||||
deleteInProgressAppOpts,
|
||||
] = useAppDeleteFailedInstallationMutation({
|
||||
onCompleted: data => {
|
||||
if (!data?.appDeleteFailedInstallation?.errors?.length) {
|
||||
|
@ -195,7 +195,7 @@ export const AppsList: React.FC<AppsListProps> = ({ params }) => {
|
|||
appsInProgressRefetch();
|
||||
closeModal();
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -204,7 +204,7 @@ export const AppsList: React.FC<AppsListProps> = ({ params }) => {
|
|||
if (!intervalId.current) {
|
||||
intervalId.current = window.setInterval(
|
||||
() => appsInProgressRefetch(),
|
||||
2000
|
||||
2000,
|
||||
);
|
||||
}
|
||||
let newAppInstalled = false;
|
||||
|
@ -226,8 +226,8 @@ export const AppsList: React.FC<AppsListProps> = ({ params }) => {
|
|||
status: "error",
|
||||
text: item.message,
|
||||
title: intl.formatMessage(messages.appCouldntInstall, {
|
||||
name: item.appName
|
||||
})
|
||||
name: item.appName,
|
||||
}),
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -251,21 +251,21 @@ export const AppsList: React.FC<AppsListProps> = ({ params }) => {
|
|||
const handleRemoveInProgressConfirm = () =>
|
||||
deleteInProgressApp({
|
||||
variables: {
|
||||
id: params.id
|
||||
}
|
||||
id: params.id,
|
||||
},
|
||||
});
|
||||
|
||||
const handleRemoveConfirm = () =>
|
||||
deleteApp({
|
||||
variables: {
|
||||
id: params.id
|
||||
}
|
||||
id: params.id,
|
||||
},
|
||||
});
|
||||
|
||||
const removeAppNotify = () => {
|
||||
notify({
|
||||
status: "success",
|
||||
text: intl.formatMessage(messages.appRemoved)
|
||||
text: intl.formatMessage(messages.appRemoved),
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -284,9 +284,9 @@ export const AppsList: React.FC<AppsListProps> = ({ params }) => {
|
|||
const context: AppListContextValues = React.useMemo(
|
||||
() => ({
|
||||
activateApp: id => openModal("app-activate", { id }),
|
||||
deactivateApp: id => openModal("app-deactivate", { id })
|
||||
deactivateApp: id => openModal("app-deactivate", { id }),
|
||||
}),
|
||||
[activateApp, deactivateApp]
|
||||
[activateApp, deactivateApp],
|
||||
);
|
||||
|
||||
return (
|
||||
|
@ -296,7 +296,7 @@ export const AppsList: React.FC<AppsListProps> = ({ params }) => {
|
|||
confirmButtonState={deleteAppOpts.status}
|
||||
name={getCurrentAppName(
|
||||
params.id,
|
||||
action === "remove-app" ? installedApps : customApps
|
||||
action === "remove-app" ? installedApps : customApps,
|
||||
)}
|
||||
onClose={closeModal}
|
||||
onConfirm={handleRemoveConfirm}
|
||||
|
@ -321,7 +321,7 @@ export const AppsList: React.FC<AppsListProps> = ({ params }) => {
|
|||
confirmButtonState={deleteInProgressAppOpts.status}
|
||||
name={getAppInProgressName(
|
||||
params.id,
|
||||
appsInProgressData?.appsInstallations
|
||||
appsInProgressData?.appsInstallations,
|
||||
)}
|
||||
onClose={closeModal}
|
||||
onConfirm={handleRemoveInProgressConfirm}
|
||||
|
@ -339,17 +339,17 @@ export const AppsList: React.FC<AppsListProps> = ({ params }) => {
|
|||
getCustomAppHref={id => customAppUrl(id)}
|
||||
onInstalledAppRemove={id =>
|
||||
openModal("remove-app", {
|
||||
id
|
||||
id,
|
||||
})
|
||||
}
|
||||
onCustomAppRemove={id =>
|
||||
openModal("remove-custom-app", {
|
||||
id
|
||||
id,
|
||||
})
|
||||
}
|
||||
onAppInProgressRemove={id =>
|
||||
openModal("remove", {
|
||||
id
|
||||
id,
|
||||
})
|
||||
}
|
||||
/>
|
||||
|
|
|
@ -4,31 +4,31 @@ export const messages = defineMessages({
|
|||
appInstalled: {
|
||||
id: "0fM/pV",
|
||||
defaultMessage: "App installed",
|
||||
description: "message title"
|
||||
description: "message title",
|
||||
},
|
||||
appRemoved: {
|
||||
id: "uIPD1i",
|
||||
defaultMessage: "App successfully removed",
|
||||
description: "app has been removed"
|
||||
description: "app has been removed",
|
||||
},
|
||||
appReadyToUse: {
|
||||
id: "ZprV2g",
|
||||
defaultMessage: "{name} is ready to be used",
|
||||
description: "app has been installed"
|
||||
description: "app has been installed",
|
||||
},
|
||||
appCouldntInstall: {
|
||||
id: "5t/4um",
|
||||
defaultMessage: "Couldn’t Install {name}",
|
||||
description: "message title"
|
||||
description: "message title",
|
||||
},
|
||||
appActivated: {
|
||||
id: "D/+84n",
|
||||
defaultMessage: "App activated",
|
||||
description: "snackbar text"
|
||||
description: "snackbar text",
|
||||
},
|
||||
appDeactivated: {
|
||||
id: "USO8PB",
|
||||
defaultMessage: "App deactivated",
|
||||
description: "snackbar text"
|
||||
}
|
||||
description: "snackbar text",
|
||||
},
|
||||
});
|
||||
|
|
|
@ -9,7 +9,7 @@ import React from "react";
|
|||
import { useIntl } from "react-intl";
|
||||
|
||||
import CustomAppCreatePage, {
|
||||
CustomAppCreatePageFormData
|
||||
CustomAppCreatePageFormData,
|
||||
} from "../../components/CustomAppCreatePage";
|
||||
import { customAppUrl } from "../../urls";
|
||||
import { messages } from "./messages";
|
||||
|
@ -18,7 +18,7 @@ interface CustomAppCreateProps {
|
|||
setToken: (token: string) => void;
|
||||
}
|
||||
export const CustomAppCreate: React.FC<CustomAppCreateProps> = ({
|
||||
setToken
|
||||
setToken,
|
||||
}) => {
|
||||
const navigate = useNavigator();
|
||||
const notify = useNotifier();
|
||||
|
@ -29,7 +29,7 @@ export const CustomAppCreate: React.FC<CustomAppCreateProps> = ({
|
|||
if (data.appCreate.errors.length === 0) {
|
||||
notify({
|
||||
status: "success",
|
||||
text: intl.formatMessage(commonMessages.savedChanges)
|
||||
text: intl.formatMessage(commonMessages.savedChanges),
|
||||
});
|
||||
navigate(customAppUrl(data.appCreate.app.id));
|
||||
setToken(data.appCreate.authToken);
|
||||
|
@ -37,7 +37,7 @@ export const CustomAppCreate: React.FC<CustomAppCreateProps> = ({
|
|||
};
|
||||
|
||||
const [createApp, createAppOpts] = useAppCreateMutation({
|
||||
onCompleted: onSubmit
|
||||
onCompleted: onSubmit,
|
||||
});
|
||||
|
||||
const handleSubmit = async (data: CustomAppCreatePageFormData) =>
|
||||
|
@ -48,10 +48,10 @@ export const CustomAppCreate: React.FC<CustomAppCreateProps> = ({
|
|||
name: data.name,
|
||||
permissions: data.hasFullAccess
|
||||
? shop.permissions.map(permission => permission.code)
|
||||
: data.permissions
|
||||
}
|
||||
}
|
||||
})
|
||||
: data.permissions,
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
@ -4,6 +4,6 @@ export const messages = defineMessages({
|
|||
createApp: {
|
||||
id: "agZQkB",
|
||||
defaultMessage: "Create App",
|
||||
description: "window title"
|
||||
}
|
||||
description: "window title",
|
||||
},
|
||||
});
|
||||
|
|
|
@ -17,7 +17,7 @@ import {
|
|||
useAppTokenDeleteMutation,
|
||||
useAppUpdateMutation,
|
||||
useWebhookDeleteMutation,
|
||||
WebhookDeleteMutation
|
||||
WebhookDeleteMutation,
|
||||
} from "@saleor/graphql";
|
||||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
import useNotifier from "@saleor/hooks/useNotifier";
|
||||
|
@ -32,13 +32,13 @@ import React from "react";
|
|||
import { useIntl } from "react-intl";
|
||||
|
||||
import CustomAppDetailsPage, {
|
||||
CustomAppDetailsPageFormData
|
||||
CustomAppDetailsPageFormData,
|
||||
} from "../../components/CustomAppDetailsPage";
|
||||
import {
|
||||
appsListUrl,
|
||||
customAppUrl,
|
||||
CustomAppUrlDialog,
|
||||
CustomAppUrlQueryParams
|
||||
CustomAppUrlQueryParams,
|
||||
} from "../../urls";
|
||||
|
||||
interface OrderListProps {
|
||||
|
@ -52,7 +52,7 @@ export const CustomAppDetails: React.FC<OrderListProps> = ({
|
|||
id,
|
||||
params,
|
||||
token,
|
||||
onTokenClose
|
||||
onTokenClose,
|
||||
}) => {
|
||||
const navigate = useNavigator();
|
||||
const notify = useNotifier();
|
||||
|
@ -68,7 +68,7 @@ export const CustomAppDetails: React.FC<OrderListProps> = ({
|
|||
|
||||
const { data, loading, refetch } = useAppQuery({
|
||||
displayLoader: true,
|
||||
variables: { id }
|
||||
variables: { id },
|
||||
});
|
||||
const [activateApp, activateAppResult] = useAppActivateMutation({
|
||||
onCompleted: data => {
|
||||
|
@ -76,7 +76,7 @@ export const CustomAppDetails: React.FC<OrderListProps> = ({
|
|||
if (errors?.length === 0) {
|
||||
notify({
|
||||
status: "success",
|
||||
text: intl.formatMessage(appMessages.appActivated)
|
||||
text: intl.formatMessage(appMessages.appActivated),
|
||||
});
|
||||
refetch();
|
||||
closeModal();
|
||||
|
@ -84,11 +84,11 @@ export const CustomAppDetails: React.FC<OrderListProps> = ({
|
|||
errors.forEach(error =>
|
||||
notify({
|
||||
status: "error",
|
||||
text: getAppErrorMessage(error, intl)
|
||||
})
|
||||
text: getAppErrorMessage(error, intl),
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
const [deactivateApp, deactivateAppResult] = useAppDeactivateMutation({
|
||||
onCompleted: data => {
|
||||
|
@ -96,7 +96,7 @@ export const CustomAppDetails: React.FC<OrderListProps> = ({
|
|||
if (errors.length === 0) {
|
||||
notify({
|
||||
status: "success",
|
||||
text: intl.formatMessage(appMessages.appDeactivated)
|
||||
text: intl.formatMessage(appMessages.appDeactivated),
|
||||
});
|
||||
refetch();
|
||||
closeModal();
|
||||
|
@ -104,18 +104,18 @@ export const CustomAppDetails: React.FC<OrderListProps> = ({
|
|||
errors.forEach(error =>
|
||||
notify({
|
||||
status: "error",
|
||||
text: getAppErrorMessage(error, intl)
|
||||
})
|
||||
text: getAppErrorMessage(error, intl),
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const onWebhookDelete = (data: WebhookDeleteMutation) => {
|
||||
if (data.webhookDelete.errors.length === 0) {
|
||||
notify({
|
||||
status: "success",
|
||||
text: intl.formatMessage(commonMessages.savedChanges)
|
||||
text: intl.formatMessage(commonMessages.savedChanges),
|
||||
});
|
||||
navigate(customAppUrl(id));
|
||||
closeModal();
|
||||
|
@ -124,14 +124,14 @@ export const CustomAppDetails: React.FC<OrderListProps> = ({
|
|||
};
|
||||
|
||||
const [webhookDelete, webhookDeleteOpts] = useWebhookDeleteMutation({
|
||||
onCompleted: onWebhookDelete
|
||||
onCompleted: onWebhookDelete,
|
||||
});
|
||||
|
||||
const handleRemoveWebhookConfirm = () => {
|
||||
webhookDelete({
|
||||
variables: {
|
||||
id: params.id
|
||||
}
|
||||
id: params.id,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -139,7 +139,7 @@ export const CustomAppDetails: React.FC<OrderListProps> = ({
|
|||
if (data?.appUpdate?.errors?.length === 0) {
|
||||
notify({
|
||||
status: "success",
|
||||
text: intl.formatMessage(commonMessages.savedChanges)
|
||||
text: intl.formatMessage(commonMessages.savedChanges),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -158,7 +158,7 @@ export const CustomAppDetails: React.FC<OrderListProps> = ({
|
|||
if (data?.appTokenDelete?.errors.length === 0) {
|
||||
notify({
|
||||
status: "success",
|
||||
text: intl.formatMessage(commonMessages.savedChanges)
|
||||
text: intl.formatMessage(commonMessages.savedChanges),
|
||||
});
|
||||
refetch();
|
||||
closeModal();
|
||||
|
@ -166,13 +166,13 @@ export const CustomAppDetails: React.FC<OrderListProps> = ({
|
|||
};
|
||||
|
||||
const [updateApp, updateAppOpts] = useAppUpdateMutation({
|
||||
onCompleted: onAppUpdate
|
||||
onCompleted: onAppUpdate,
|
||||
});
|
||||
const [createToken, createTokenOpts] = useAppTokenCreateMutation({
|
||||
onCompleted: onTokenCreate
|
||||
onCompleted: onTokenCreate,
|
||||
});
|
||||
const [deleteToken, deleteTokenOpts] = useAppTokenDeleteMutation({
|
||||
onCompleted: onTokenDelete
|
||||
onCompleted: onTokenDelete,
|
||||
});
|
||||
|
||||
const handleSubmit = async (data: CustomAppDetailsPageFormData) =>
|
||||
|
@ -184,10 +184,10 @@ export const CustomAppDetails: React.FC<OrderListProps> = ({
|
|||
name: data.name,
|
||||
permissions: data.hasFullAccess
|
||||
? shop.permissions.map(permission => permission.code)
|
||||
: data.permissions
|
||||
}
|
||||
}
|
||||
})
|
||||
: data.permissions,
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
const handleTokenCreate = (name: string) =>
|
||||
|
@ -195,16 +195,16 @@ export const CustomAppDetails: React.FC<OrderListProps> = ({
|
|||
variables: {
|
||||
input: {
|
||||
app: id,
|
||||
name
|
||||
}
|
||||
}
|
||||
name,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const handleTokenDelete = () =>
|
||||
deleteToken({
|
||||
variables: {
|
||||
id: params.id
|
||||
}
|
||||
id: params.id,
|
||||
},
|
||||
});
|
||||
|
||||
const handleActivateConfirm = () => {
|
||||
|
@ -230,13 +230,13 @@ export const CustomAppDetails: React.FC<OrderListProps> = ({
|
|||
onTokenCreate={() => openModal("create-token")}
|
||||
onTokenDelete={id =>
|
||||
openModal("remove-token", {
|
||||
id
|
||||
id,
|
||||
})
|
||||
}
|
||||
webhookCreateHref={webhookAddPath(id)}
|
||||
onWebhookRemove={id =>
|
||||
openModal("remove-webhook", {
|
||||
id
|
||||
id,
|
||||
})
|
||||
}
|
||||
onAppActivateOpen={() => openModal("app-activate")}
|
||||
|
|
|
@ -17,7 +17,7 @@ const AttributeBulkDeleteDialog: React.FC<AttributeBulkDeleteDialogProps> = ({
|
|||
quantity,
|
||||
onClose,
|
||||
onConfirm,
|
||||
open
|
||||
open,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
|
||||
|
@ -30,7 +30,7 @@ const AttributeBulkDeleteDialog: React.FC<AttributeBulkDeleteDialogProps> = ({
|
|||
title={intl.formatMessage({
|
||||
id: "rKf4LU",
|
||||
defaultMessage: "Delete attributes",
|
||||
description: "dialog title"
|
||||
description: "dialog title",
|
||||
})}
|
||||
variant="delete"
|
||||
>
|
||||
|
@ -41,7 +41,7 @@ const AttributeBulkDeleteDialog: React.FC<AttributeBulkDeleteDialogProps> = ({
|
|||
description="dialog content"
|
||||
values={{
|
||||
counter: quantity,
|
||||
displayQuantity: <strong>{quantity}</strong>
|
||||
displayQuantity: <strong>{quantity}</strong>,
|
||||
}}
|
||||
/>
|
||||
</DialogContentText>
|
||||
|
|
|
@ -17,7 +17,7 @@ const AttributeDeleteDialog: React.FC<AttributeDeleteDialogProps> = ({
|
|||
confirmButtonState,
|
||||
onClose,
|
||||
onConfirm,
|
||||
open
|
||||
open,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
|
||||
|
@ -31,7 +31,7 @@ const AttributeDeleteDialog: React.FC<AttributeDeleteDialogProps> = ({
|
|||
title={intl.formatMessage({
|
||||
id: "JI2Xwp",
|
||||
defaultMessage: "Delete attribute",
|
||||
description: "dialog title"
|
||||
description: "dialog title",
|
||||
})}
|
||||
>
|
||||
<DialogContentText>
|
||||
|
@ -40,7 +40,7 @@ const AttributeDeleteDialog: React.FC<AttributeDeleteDialogProps> = ({
|
|||
defaultMessage="Are you sure you want to delete {attributeName}?"
|
||||
description="dialog content"
|
||||
values={{
|
||||
attributeName: <strong>{name}</strong>
|
||||
attributeName: <strong>{name}</strong>,
|
||||
}}
|
||||
/>
|
||||
</DialogContentText>
|
||||
|
|
|
@ -7,7 +7,7 @@ import SingleSelectField from "@saleor/components/SingleSelectField";
|
|||
import {
|
||||
AttributeEntityTypeEnum,
|
||||
AttributeErrorFragment,
|
||||
AttributeInputTypeEnum
|
||||
AttributeInputTypeEnum,
|
||||
} from "@saleor/graphql";
|
||||
import { UseFormResult } from "@saleor/hooks/useForm";
|
||||
import { commonMessages } from "@saleor/intl";
|
||||
|
@ -26,13 +26,13 @@ const entityTypeMessages = defineMessages({
|
|||
page: {
|
||||
id: "Iafyt5",
|
||||
defaultMessage: "Pages",
|
||||
description: "page attribute entity type"
|
||||
description: "page attribute entity type",
|
||||
},
|
||||
product: {
|
||||
id: "5TUpjG",
|
||||
defaultMessage: "Products",
|
||||
description: "product attribute entity type"
|
||||
}
|
||||
description: "product attribute entity type",
|
||||
},
|
||||
});
|
||||
|
||||
const useStyles = makeStyles(
|
||||
|
@ -42,11 +42,11 @@ const useStyles = makeStyles(
|
|||
display: "flex",
|
||||
[theme.breakpoints.down("md")]: {
|
||||
flexFlow: "wrap",
|
||||
rowGap: theme.spacing(3)
|
||||
}
|
||||
}
|
||||
rowGap: theme.spacing(3),
|
||||
},
|
||||
},
|
||||
}),
|
||||
{ name: "AttributeDetails" }
|
||||
{ name: "AttributeDetails" },
|
||||
);
|
||||
|
||||
export interface AttributeDetailsProps
|
||||
|
@ -70,66 +70,66 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = props => {
|
|||
disabled,
|
||||
apiErrors,
|
||||
onChange,
|
||||
set
|
||||
set,
|
||||
} = props;
|
||||
const classes = useStyles(props);
|
||||
const intl = useIntl();
|
||||
const inputTypeChoices = [
|
||||
{
|
||||
label: intl.formatMessage(inputTypeMessages.dropdown),
|
||||
value: AttributeInputTypeEnum.DROPDOWN
|
||||
value: AttributeInputTypeEnum.DROPDOWN,
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage(inputTypeMessages.multiselect),
|
||||
value: AttributeInputTypeEnum.MULTISELECT
|
||||
value: AttributeInputTypeEnum.MULTISELECT,
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage(inputTypeMessages.file),
|
||||
value: AttributeInputTypeEnum.FILE
|
||||
value: AttributeInputTypeEnum.FILE,
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage(inputTypeMessages.references),
|
||||
value: AttributeInputTypeEnum.REFERENCE
|
||||
value: AttributeInputTypeEnum.REFERENCE,
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage(inputTypeMessages.text),
|
||||
value: AttributeInputTypeEnum.RICH_TEXT
|
||||
value: AttributeInputTypeEnum.RICH_TEXT,
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage(inputTypeMessages.numeric),
|
||||
value: AttributeInputTypeEnum.NUMERIC
|
||||
value: AttributeInputTypeEnum.NUMERIC,
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage(inputTypeMessages.boolean),
|
||||
value: AttributeInputTypeEnum.BOOLEAN
|
||||
value: AttributeInputTypeEnum.BOOLEAN,
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage(inputTypeMessages.date),
|
||||
value: AttributeInputTypeEnum.DATE
|
||||
value: AttributeInputTypeEnum.DATE,
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage(inputTypeMessages.dateTime),
|
||||
value: AttributeInputTypeEnum.DATE_TIME
|
||||
value: AttributeInputTypeEnum.DATE_TIME,
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage(inputTypeMessages.swatch),
|
||||
value: AttributeInputTypeEnum.SWATCH
|
||||
}
|
||||
value: AttributeInputTypeEnum.SWATCH,
|
||||
},
|
||||
];
|
||||
const entityTypeChoices = [
|
||||
{
|
||||
label: intl.formatMessage(entityTypeMessages.page),
|
||||
value: AttributeEntityTypeEnum.PAGE
|
||||
value: AttributeEntityTypeEnum.PAGE,
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage(entityTypeMessages.product),
|
||||
value: AttributeEntityTypeEnum.PRODUCT
|
||||
}
|
||||
value: AttributeEntityTypeEnum.PRODUCT,
|
||||
},
|
||||
];
|
||||
|
||||
const formApiErrors = getFormErrors(
|
||||
["name", "slug", "inputType", "entityType", "unit"],
|
||||
apiErrors
|
||||
apiErrors,
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
@ -15,7 +15,7 @@ import {
|
|||
UnitSystem,
|
||||
unitSystemChoices,
|
||||
UnitType,
|
||||
unitTypeChoices
|
||||
unitTypeChoices,
|
||||
} from "./utils";
|
||||
|
||||
const useStyles = makeStyles(
|
||||
|
@ -25,18 +25,18 @@ const useStyles = makeStyles(
|
|||
display: "flex",
|
||||
[theme.breakpoints.down("sm")]: {
|
||||
flexFlow: "wrap",
|
||||
rowGap: theme.spacing(3)
|
||||
}
|
||||
rowGap: theme.spacing(3),
|
||||
},
|
||||
},
|
||||
hr: {
|
||||
border: "none",
|
||||
borderTop: `1px solid ${theme.palette.divider}`,
|
||||
height: 0,
|
||||
margin: "0.5rem 0",
|
||||
width: "100%"
|
||||
}
|
||||
width: "100%",
|
||||
},
|
||||
}),
|
||||
{ name: "NumericUnits" }
|
||||
{ name: "NumericUnits" },
|
||||
);
|
||||
|
||||
interface UnitData {
|
||||
|
@ -59,32 +59,32 @@ export const NumericUnits: React.FC<NumericUnitsProps> = ({
|
|||
errors,
|
||||
set,
|
||||
setError,
|
||||
clearErrors
|
||||
clearErrors,
|
||||
}) => {
|
||||
const { formatMessage } = useIntl();
|
||||
const classes = useStyles();
|
||||
const [unitData, setUnitData] = useState<UnitData>({
|
||||
unit: data.unit ?? null
|
||||
unit: data.unit ?? null,
|
||||
});
|
||||
|
||||
const { unit, system, type } = unitData;
|
||||
const errorProps = {
|
||||
error: !!errors.unit,
|
||||
hint: formatMessage(commonMessages.requiredField)
|
||||
hint: formatMessage(commonMessages.requiredField),
|
||||
};
|
||||
const [typeChoices, systemChoices, unitChoices] = useMemo(
|
||||
() => [
|
||||
unitTypeChoices.map(choice => ({
|
||||
...choice,
|
||||
label: formatMessage(choice.label)
|
||||
label: formatMessage(choice.label),
|
||||
})),
|
||||
unitSystemChoices.map(choice => ({
|
||||
...choice,
|
||||
label: formatMessage(choice.label)
|
||||
label: formatMessage(choice.label),
|
||||
})),
|
||||
getUnitChoices(formatMessage)
|
||||
getUnitChoices(formatMessage),
|
||||
],
|
||||
[]
|
||||
[],
|
||||
);
|
||||
|
||||
useEffect(() => set({ unit }), [unit]);
|
||||
|
@ -158,7 +158,7 @@ export const NumericUnits: React.FC<NumericUnitsProps> = ({
|
|||
onChange={({ target }: React.ChangeEvent<HTMLSelectElement>) =>
|
||||
setUnitData(({ system }) => ({
|
||||
system,
|
||||
type: target.value as UnitType
|
||||
type: target.value as UnitType,
|
||||
}))
|
||||
}
|
||||
disabled={!system || disabled}
|
||||
|
@ -172,7 +172,7 @@ export const NumericUnits: React.FC<NumericUnitsProps> = ({
|
|||
onChange={({ target }: React.ChangeEvent<HTMLSelectElement>) =>
|
||||
setUnitData(data => ({
|
||||
...data,
|
||||
unit: target.value as MeasurementUnitsEnum
|
||||
unit: target.value as MeasurementUnitsEnum,
|
||||
}))
|
||||
}
|
||||
disabled={!type || disabled}
|
||||
|
|
|
@ -5,144 +5,144 @@ export const messages = defineMessages({
|
|||
attributeLabel: {
|
||||
id: "xOEZjV",
|
||||
defaultMessage: "Default Label",
|
||||
description: "attribute's label"
|
||||
description: "attribute's label",
|
||||
},
|
||||
attributeSlug: {
|
||||
id: "P79U4b",
|
||||
defaultMessage: "Attribute Code",
|
||||
description: "attribute's slug short code label"
|
||||
description: "attribute's slug short code label",
|
||||
},
|
||||
attributeSlugHelperText: {
|
||||
id: "Q7uuDr",
|
||||
defaultMessage: "This is used internally. Make sure you don’t use spaces",
|
||||
description: "attribute slug input field helper text"
|
||||
description: "attribute slug input field helper text",
|
||||
},
|
||||
entityType: {
|
||||
id: "LnRlch",
|
||||
defaultMessage: "Entity",
|
||||
description: "attribute's editor component entity"
|
||||
description: "attribute's editor component entity",
|
||||
},
|
||||
inputType: {
|
||||
id: "oIvtua",
|
||||
defaultMessage: "Catalog Input type for Store Owner",
|
||||
description: "attribute's editor component"
|
||||
description: "attribute's editor component",
|
||||
},
|
||||
valueRequired: {
|
||||
id: "njBulj",
|
||||
defaultMessage: "Value Required",
|
||||
description: "check to require attribute to have value"
|
||||
description: "check to require attribute to have value",
|
||||
},
|
||||
selectUnit: {
|
||||
id: "PiSXjb",
|
||||
defaultMessage: "Select unit",
|
||||
description: "check to require numeric attribute unit"
|
||||
description: "check to require numeric attribute unit",
|
||||
},
|
||||
unitSystem: {
|
||||
id: "ghje1I",
|
||||
defaultMessage: "System",
|
||||
description: "numeric attribute unit system"
|
||||
description: "numeric attribute unit system",
|
||||
},
|
||||
|
||||
unitOf: {
|
||||
id: "zWM89r",
|
||||
defaultMessage: "Units of",
|
||||
description: "numeric attribute units of"
|
||||
description: "numeric attribute units of",
|
||||
},
|
||||
unit: {
|
||||
id: "Orgqv4",
|
||||
defaultMessage: "Unit",
|
||||
description: "numeric attribute unit"
|
||||
}
|
||||
description: "numeric attribute unit",
|
||||
},
|
||||
});
|
||||
|
||||
export const inputTypeMessages = defineMessages({
|
||||
dropdown: {
|
||||
id: "bZksto",
|
||||
defaultMessage: "Dropdown",
|
||||
description: "product attribute type"
|
||||
description: "product attribute type",
|
||||
},
|
||||
file: {
|
||||
id: "z1y9oL",
|
||||
defaultMessage: "File",
|
||||
description: "file attribute type"
|
||||
description: "file attribute type",
|
||||
},
|
||||
multiselect: {
|
||||
id: "cKjFfl",
|
||||
defaultMessage: "Multiple Select",
|
||||
description: "product attribute type"
|
||||
description: "product attribute type",
|
||||
},
|
||||
references: {
|
||||
id: "5dLpx0",
|
||||
defaultMessage: "References",
|
||||
description: "references attribute type"
|
||||
description: "references attribute type",
|
||||
},
|
||||
text: {
|
||||
id: "fdbqIs",
|
||||
defaultMessage: "Text",
|
||||
description: "text attribute type"
|
||||
description: "text attribute type",
|
||||
},
|
||||
numeric: {
|
||||
id: "SNiyXb",
|
||||
defaultMessage: "Numeric",
|
||||
description: "numeric attribute type"
|
||||
description: "numeric attribute type",
|
||||
},
|
||||
boolean: {
|
||||
id: "l5V0QT",
|
||||
defaultMessage: "Boolean",
|
||||
description: "boolean attribute type"
|
||||
description: "boolean attribute type",
|
||||
},
|
||||
date: {
|
||||
id: "fU+a9k",
|
||||
defaultMessage: "Date",
|
||||
description: "date attribute type"
|
||||
description: "date attribute type",
|
||||
},
|
||||
dateTime: {
|
||||
id: "DzPVnj",
|
||||
defaultMessage: "Date Time",
|
||||
description: "date time attribute type"
|
||||
description: "date time attribute type",
|
||||
},
|
||||
swatch: {
|
||||
id: "gx4wCT",
|
||||
defaultMessage: "Swatch",
|
||||
description: "swatch attribute type"
|
||||
}
|
||||
description: "swatch attribute type",
|
||||
},
|
||||
});
|
||||
|
||||
export const unitSystemMessages = defineMessages({
|
||||
metric: {
|
||||
id: "ZayvsI",
|
||||
defaultMessage: "Metric",
|
||||
description: "metric unit system"
|
||||
description: "metric unit system",
|
||||
},
|
||||
imperial: {
|
||||
id: "YgE6ga",
|
||||
defaultMessage: "Imperial",
|
||||
description: "imperial unit system"
|
||||
}
|
||||
description: "imperial unit system",
|
||||
},
|
||||
});
|
||||
|
||||
export const unitTypeMessages = defineMessages({
|
||||
volume: {
|
||||
id: "cy8sV7",
|
||||
defaultMessage: "Volume",
|
||||
description: "volume units types"
|
||||
description: "volume units types",
|
||||
},
|
||||
|
||||
distance: {
|
||||
id: "k/mTEl",
|
||||
defaultMessage: "Distance",
|
||||
description: "distance units type"
|
||||
description: "distance units type",
|
||||
},
|
||||
weight: {
|
||||
id: "Vdy5g7",
|
||||
defaultMessage: "Weight",
|
||||
description: "weight units type"
|
||||
description: "weight units type",
|
||||
},
|
||||
area: {
|
||||
id: "A9QSur",
|
||||
defaultMessage: "Area",
|
||||
description: "area units type"
|
||||
}
|
||||
description: "area units type",
|
||||
},
|
||||
});
|
||||
|
||||
export const unitMessages = defineMessages({
|
||||
|
@ -150,13 +150,13 @@ export const unitMessages = defineMessages({
|
|||
acreInch: {
|
||||
id: "jBu2yj",
|
||||
defaultMessage: "acre-inch",
|
||||
description: "acre-inch unit"
|
||||
description: "acre-inch unit",
|
||||
},
|
||||
acreFt: {
|
||||
id: "5XG1CO",
|
||||
defaultMessage: "acre-ft",
|
||||
description: "acre-ft unit"
|
||||
}
|
||||
description: "acre-ft unit",
|
||||
},
|
||||
});
|
||||
|
||||
export const units = {
|
||||
|
@ -188,5 +188,5 @@ export const units = {
|
|||
lbs: "lbs",
|
||||
squareFt: <>ft²</>,
|
||||
squareYd: <>yd²</>,
|
||||
squareInch: <>in²</>
|
||||
squareInch: <>in²</>,
|
||||
};
|
||||
|
|
|
@ -37,12 +37,12 @@ const UNIT_MESSAGES_MAPPING = {
|
|||
[MeasurementUnitsEnum.TONNE]: M.units.tonne,
|
||||
[MeasurementUnitsEnum.SQ_CM]: M.units.squareCentimeter,
|
||||
[MeasurementUnitsEnum.SQ_M]: M.units.squareMeter,
|
||||
[MeasurementUnitsEnum.SQ_KM]: M.units.squareKilometer
|
||||
[MeasurementUnitsEnum.SQ_KM]: M.units.squareKilometer,
|
||||
};
|
||||
|
||||
export const getMeasurementUnitMessage = (
|
||||
unit: MeasurementUnitsEnum,
|
||||
formatMessage: IntlShape["formatMessage"]
|
||||
formatMessage: IntlShape["formatMessage"],
|
||||
): MessageDescriptor | React.ReactNode => {
|
||||
const message = UNIT_MESSAGES_MAPPING[unit];
|
||||
return typeof message === "string" || React.isValidElement(message)
|
||||
|
@ -53,31 +53,31 @@ export const getMeasurementUnitMessage = (
|
|||
export const unitSystemChoices: Array<Choice<UnitSystem, MessageDescriptor>> = [
|
||||
{
|
||||
label: M.unitSystemMessages.metric,
|
||||
value: "metric"
|
||||
value: "metric",
|
||||
},
|
||||
{
|
||||
label: M.unitSystemMessages.imperial,
|
||||
value: "imperial"
|
||||
}
|
||||
value: "imperial",
|
||||
},
|
||||
];
|
||||
|
||||
export const unitTypeChoices: Array<Choice<UnitType, MessageDescriptor>> = [
|
||||
{
|
||||
label: M.unitTypeMessages.volume,
|
||||
value: "volume"
|
||||
value: "volume",
|
||||
},
|
||||
{
|
||||
label: M.unitTypeMessages.distance,
|
||||
value: "distance"
|
||||
value: "distance",
|
||||
},
|
||||
{
|
||||
label: M.unitTypeMessages.weight,
|
||||
value: "weight"
|
||||
value: "weight",
|
||||
},
|
||||
{
|
||||
label: M.unitTypeMessages.area,
|
||||
value: "area"
|
||||
}
|
||||
value: "area",
|
||||
},
|
||||
];
|
||||
|
||||
export const unitMapping = {
|
||||
|
@ -90,64 +90,64 @@ export const unitMapping = {
|
|||
MeasurementUnitsEnum.FL_OZ,
|
||||
MeasurementUnitsEnum.PINT,
|
||||
MeasurementUnitsEnum.ACRE_IN,
|
||||
MeasurementUnitsEnum.ACRE_FT
|
||||
MeasurementUnitsEnum.ACRE_FT,
|
||||
],
|
||||
distance: [
|
||||
MeasurementUnitsEnum.FT,
|
||||
MeasurementUnitsEnum.YD,
|
||||
MeasurementUnitsEnum.INCH
|
||||
MeasurementUnitsEnum.INCH,
|
||||
],
|
||||
weight: [MeasurementUnitsEnum.LB, MeasurementUnitsEnum.OZ],
|
||||
area: [
|
||||
MeasurementUnitsEnum.SQ_FT,
|
||||
MeasurementUnitsEnum.SQ_YD,
|
||||
MeasurementUnitsEnum.SQ_INCH
|
||||
]
|
||||
MeasurementUnitsEnum.SQ_INCH,
|
||||
],
|
||||
},
|
||||
metric: {
|
||||
volume: [
|
||||
MeasurementUnitsEnum.CUBIC_CENTIMETER,
|
||||
MeasurementUnitsEnum.CUBIC_DECIMETER,
|
||||
MeasurementUnitsEnum.CUBIC_METER,
|
||||
MeasurementUnitsEnum.LITER
|
||||
MeasurementUnitsEnum.LITER,
|
||||
],
|
||||
distance: [
|
||||
MeasurementUnitsEnum.CM,
|
||||
MeasurementUnitsEnum.M,
|
||||
MeasurementUnitsEnum.KM
|
||||
MeasurementUnitsEnum.KM,
|
||||
],
|
||||
weight: [
|
||||
MeasurementUnitsEnum.G,
|
||||
MeasurementUnitsEnum.KG,
|
||||
MeasurementUnitsEnum.TONNE
|
||||
MeasurementUnitsEnum.TONNE,
|
||||
],
|
||||
area: [
|
||||
MeasurementUnitsEnum.SQ_CM,
|
||||
MeasurementUnitsEnum.SQ_M,
|
||||
MeasurementUnitsEnum.SQ_KM
|
||||
]
|
||||
}
|
||||
MeasurementUnitsEnum.SQ_KM,
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const extractTypeChoices = (
|
||||
typeEnums: {
|
||||
[key in UnitType]: MeasurementUnitsEnum[];
|
||||
},
|
||||
formatMessage: IntlShape["formatMessage"]
|
||||
formatMessage: IntlShape["formatMessage"],
|
||||
) =>
|
||||
Object.entries(typeEnums).reduce(
|
||||
(acc, [type, units]) => ({
|
||||
...acc,
|
||||
[type]: units.map(unit => ({
|
||||
value: unit,
|
||||
label: getMeasurementUnitMessage(unit, formatMessage)
|
||||
}))
|
||||
label: getMeasurementUnitMessage(unit, formatMessage),
|
||||
})),
|
||||
}),
|
||||
{}
|
||||
{},
|
||||
);
|
||||
|
||||
export const getUnitChoices = (
|
||||
formatMessage: IntlShape["formatMessage"]
|
||||
formatMessage: IntlShape["formatMessage"],
|
||||
): {
|
||||
[key in UnitSystem]: {
|
||||
[key in UnitType]: Array<Choice<MeasurementUnitsEnum>>;
|
||||
|
@ -156,9 +156,9 @@ export const getUnitChoices = (
|
|||
Object.entries(unitMapping).reduce(
|
||||
(acc, [system, typeEnums]) => ({
|
||||
...acc,
|
||||
[system]: extractTypeChoices(typeEnums, formatMessage)
|
||||
[system]: extractTypeChoices(typeEnums, formatMessage),
|
||||
}),
|
||||
{}
|
||||
{},
|
||||
) as {
|
||||
[key in UnitSystem]: {
|
||||
[key in UnitType]: Array<Choice<MeasurementUnitsEnum>>;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { TableBody, TableCell, TableFooter, TableRow } from "@material-ui/core";
|
||||
import {
|
||||
AttributeListUrlSortField,
|
||||
attributeUrl
|
||||
attributeUrl,
|
||||
} from "@saleor/attributes/urls";
|
||||
import Checkbox from "@saleor/components/Checkbox";
|
||||
import ResponsiveTable from "@saleor/components/ResponsiveTable";
|
||||
|
@ -30,39 +30,39 @@ const useStyles = makeStyles(
|
|||
theme => ({
|
||||
[theme.breakpoints.up("lg")]: {
|
||||
colFaceted: {
|
||||
width: 180
|
||||
width: 180,
|
||||
},
|
||||
colName: {
|
||||
width: "auto"
|
||||
width: "auto",
|
||||
},
|
||||
colSearchable: {
|
||||
width: 180
|
||||
width: 180,
|
||||
},
|
||||
colSlug: {
|
||||
width: 200
|
||||
width: 200,
|
||||
},
|
||||
colVisible: {
|
||||
width: 180
|
||||
}
|
||||
width: 180,
|
||||
},
|
||||
},
|
||||
colFaceted: {
|
||||
textAlign: "center"
|
||||
textAlign: "center",
|
||||
},
|
||||
colName: {},
|
||||
colSearchable: {
|
||||
textAlign: "center"
|
||||
textAlign: "center",
|
||||
},
|
||||
colSlug: {
|
||||
paddingLeft: 0
|
||||
paddingLeft: 0,
|
||||
},
|
||||
colVisible: {
|
||||
textAlign: "center"
|
||||
textAlign: "center",
|
||||
},
|
||||
link: {
|
||||
cursor: "pointer"
|
||||
}
|
||||
cursor: "pointer",
|
||||
},
|
||||
}),
|
||||
{ name: "AttributeList" }
|
||||
{ name: "AttributeList" },
|
||||
);
|
||||
|
||||
const numberOfColumns = 6;
|
||||
|
@ -76,7 +76,7 @@ const AttributeList: React.FC<AttributeListProps> = ({
|
|||
toggle,
|
||||
toggleAll,
|
||||
toolbar,
|
||||
onSort
|
||||
onSort,
|
||||
}) => {
|
||||
const classes = useStyles({});
|
||||
const intl = useIntl();
|
||||
|
@ -216,7 +216,7 @@ const AttributeList: React.FC<AttributeListProps> = ({
|
|||
className={classes.colSearchable}
|
||||
data-test-id="searchable"
|
||||
data-test-searchable={maybe(
|
||||
() => attribute.filterableInDashboard
|
||||
() => attribute.filterableInDashboard,
|
||||
)}
|
||||
>
|
||||
{attribute ? (
|
||||
|
@ -229,7 +229,7 @@ const AttributeList: React.FC<AttributeListProps> = ({
|
|||
className={classes.colFaceted}
|
||||
data-test-id="use-in-faceted-search"
|
||||
data-test-use-in-faceted-search={maybe(
|
||||
() => attribute.filterableInStorefront
|
||||
() => attribute.filterableInStorefront,
|
||||
)}
|
||||
>
|
||||
{attribute ? (
|
||||
|
@ -250,7 +250,7 @@ const AttributeList: React.FC<AttributeListProps> = ({
|
|||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)
|
||||
),
|
||||
)}
|
||||
</TableBody>
|
||||
</ResponsiveTable>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { Card } from "@material-ui/core";
|
||||
import {
|
||||
attributeAddUrl,
|
||||
AttributeListUrlSortField
|
||||
AttributeListUrlSortField,
|
||||
} from "@saleor/attributes/urls";
|
||||
import { Backlink } from "@saleor/components/Backlink";
|
||||
import { Button } from "@saleor/components/Button";
|
||||
|
@ -19,13 +19,13 @@ import {
|
|||
ListActions,
|
||||
PageListProps,
|
||||
SortPage,
|
||||
TabPageProps
|
||||
TabPageProps,
|
||||
} from "../../../types";
|
||||
import AttributeList from "../AttributeList/AttributeList";
|
||||
import {
|
||||
AttributeFilterKeys,
|
||||
AttributeListFilterOpts,
|
||||
createFilterStructure
|
||||
createFilterStructure,
|
||||
} from "./filters";
|
||||
|
||||
export interface AttributeListPageProps
|
||||
|
@ -77,14 +77,14 @@ const AttributeListPage: React.FC<AttributeListPageProps> = ({
|
|||
allTabLabel={intl.formatMessage({
|
||||
id: "dKPMyh",
|
||||
defaultMessage: "All Attributes",
|
||||
description: "tab name"
|
||||
description: "tab name",
|
||||
})}
|
||||
currentTab={currentTab}
|
||||
filterStructure={structure}
|
||||
initialSearch={initialSearch}
|
||||
searchPlaceholder={intl.formatMessage({
|
||||
id: "1div9r",
|
||||
defaultMessage: "Search Attribute"
|
||||
defaultMessage: "Search Attribute",
|
||||
})}
|
||||
tabs={tabs}
|
||||
onAll={onAll}
|
||||
|
|
|
@ -8,7 +8,7 @@ export enum AttributeFilterKeys {
|
|||
filterableInStorefront = "filterableInStorefront",
|
||||
isVariantOnly = "isVariantOnly",
|
||||
valueRequired = "valueRequired",
|
||||
visibleInStorefront = "visibleInStorefront"
|
||||
visibleInStorefront = "visibleInStorefront",
|
||||
}
|
||||
|
||||
export interface AttributeListFilterOpts {
|
||||
|
@ -22,28 +22,28 @@ const messages = defineMessages({
|
|||
filterableInStorefront: {
|
||||
id: "PsRG+v",
|
||||
defaultMessage: "Filterable in Storefront",
|
||||
description: "use attribute in filtering"
|
||||
description: "use attribute in filtering",
|
||||
},
|
||||
isVariantOnly: {
|
||||
id: "rvk9ls",
|
||||
defaultMessage: "Variant Only",
|
||||
description: "attribute can be used only in variants"
|
||||
description: "attribute can be used only in variants",
|
||||
},
|
||||
valueRequired: {
|
||||
id: "HQR2y0",
|
||||
defaultMessage: "Value Required",
|
||||
description: "attribute value is required"
|
||||
description: "attribute value is required",
|
||||
},
|
||||
visibleInStorefront: {
|
||||
id: "cvbqJu",
|
||||
defaultMessage: "Visible on Product Page in Storefront",
|
||||
description: "attribute"
|
||||
}
|
||||
description: "attribute",
|
||||
},
|
||||
});
|
||||
|
||||
export function createFilterStructure(
|
||||
intl: IntlShape,
|
||||
opts: AttributeListFilterOpts
|
||||
opts: AttributeListFilterOpts,
|
||||
): IFilter<AttributeFilterKeys> {
|
||||
return [
|
||||
{
|
||||
|
@ -53,10 +53,10 @@ export function createFilterStructure(
|
|||
opts.filterableInStorefront.value,
|
||||
{
|
||||
negative: intl.formatMessage(commonMessages.no),
|
||||
positive: intl.formatMessage(commonMessages.yes)
|
||||
}
|
||||
positive: intl.formatMessage(commonMessages.yes),
|
||||
},
|
||||
),
|
||||
active: opts.filterableInStorefront.active
|
||||
active: opts.filterableInStorefront.active,
|
||||
},
|
||||
{
|
||||
...createBooleanField(
|
||||
|
@ -65,10 +65,10 @@ export function createFilterStructure(
|
|||
opts.isVariantOnly.value,
|
||||
{
|
||||
negative: intl.formatMessage(commonMessages.no),
|
||||
positive: intl.formatMessage(commonMessages.yes)
|
||||
}
|
||||
positive: intl.formatMessage(commonMessages.yes),
|
||||
},
|
||||
),
|
||||
active: opts.isVariantOnly.active
|
||||
active: opts.isVariantOnly.active,
|
||||
},
|
||||
{
|
||||
...createBooleanField(
|
||||
|
@ -77,10 +77,10 @@ export function createFilterStructure(
|
|||
opts.valueRequired.value,
|
||||
{
|
||||
negative: intl.formatMessage(commonMessages.no),
|
||||
positive: intl.formatMessage(commonMessages.yes)
|
||||
}
|
||||
positive: intl.formatMessage(commonMessages.yes),
|
||||
},
|
||||
),
|
||||
active: opts.valueRequired.active
|
||||
active: opts.valueRequired.active,
|
||||
},
|
||||
{
|
||||
...createBooleanField(
|
||||
|
@ -89,10 +89,10 @@ export function createFilterStructure(
|
|||
opts.visibleInStorefront.value,
|
||||
{
|
||||
negative: intl.formatMessage(commonMessages.no),
|
||||
positive: intl.formatMessage(commonMessages.yes)
|
||||
}
|
||||
positive: intl.formatMessage(commonMessages.yes),
|
||||
},
|
||||
),
|
||||
active: opts.visibleInStorefront.active
|
||||
}
|
||||
active: opts.visibleInStorefront.active,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
|
|
@ -19,29 +19,29 @@ const messages = defineMessages({
|
|||
contentAttribute: {
|
||||
id: "zbJHl7",
|
||||
defaultMessage: "Content Attribute",
|
||||
description: "attribute type"
|
||||
description: "attribute type",
|
||||
},
|
||||
productAttribute: {
|
||||
id: "qkRuT0",
|
||||
defaultMessage: "Product Attribute",
|
||||
description: "attribute type"
|
||||
}
|
||||
description: "attribute type",
|
||||
},
|
||||
});
|
||||
|
||||
const useStyles = makeStyles(
|
||||
theme => ({
|
||||
card: {
|
||||
overflow: "visible"
|
||||
overflow: "visible",
|
||||
},
|
||||
cardSubtitle: {
|
||||
fontSize: theme.typography.body1.fontSize,
|
||||
marginBottom: theme.spacing(0.5)
|
||||
marginBottom: theme.spacing(0.5),
|
||||
},
|
||||
label: {
|
||||
marginBottom: theme.spacing(0.5)
|
||||
}
|
||||
marginBottom: theme.spacing(0.5),
|
||||
},
|
||||
}),
|
||||
{ name: "AttributeOrganization" }
|
||||
{ name: "AttributeOrganization" },
|
||||
);
|
||||
|
||||
const AttributeOrganization: React.FC<AttributeOrganizationProps> = props => {
|
||||
|
@ -56,7 +56,7 @@ const AttributeOrganization: React.FC<AttributeOrganizationProps> = props => {
|
|||
title={intl.formatMessage({
|
||||
id: "nwvQPg",
|
||||
defaultMessage: "Organization",
|
||||
description: "section header"
|
||||
description: "section header",
|
||||
})}
|
||||
/>
|
||||
<CardContent>
|
||||
|
@ -65,12 +65,12 @@ const AttributeOrganization: React.FC<AttributeOrganizationProps> = props => {
|
|||
choices={[
|
||||
{
|
||||
label: intl.formatMessage(messages.productAttribute),
|
||||
value: AttributeTypeEnum.PRODUCT_TYPE
|
||||
value: AttributeTypeEnum.PRODUCT_TYPE,
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage(messages.contentAttribute),
|
||||
value: AttributeTypeEnum.PAGE_TYPE
|
||||
}
|
||||
value: AttributeTypeEnum.PAGE_TYPE,
|
||||
},
|
||||
]}
|
||||
disabled={disabled}
|
||||
label={
|
||||
|
|
|
@ -17,7 +17,7 @@ import {
|
|||
AttributeErrorFragment,
|
||||
AttributeInputTypeEnum,
|
||||
AttributeTypeEnum,
|
||||
MeasurementUnitsEnum
|
||||
MeasurementUnitsEnum,
|
||||
} from "@saleor/graphql";
|
||||
import { SubmitPromise } from "@saleor/hooks/useForm";
|
||||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
|
@ -91,7 +91,7 @@ const AttributePage: React.FC<AttributePageProps> = ({
|
|||
pageInfo,
|
||||
onNextPage,
|
||||
onPreviousPage,
|
||||
children
|
||||
children,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const navigate = useNavigator();
|
||||
|
@ -99,7 +99,7 @@ const AttributePage: React.FC<AttributePageProps> = ({
|
|||
const {
|
||||
isMetadataModified,
|
||||
isPrivateMetadataModified,
|
||||
makeChangeHandler: makeMetadataChangeHandler
|
||||
makeChangeHandler: makeMetadataChangeHandler,
|
||||
} = useMetadataChangeTrigger();
|
||||
|
||||
const initialForm: AttributePageFormData =
|
||||
|
@ -118,7 +118,7 @@ const AttributePage: React.FC<AttributePageProps> = ({
|
|||
type: AttributeTypeEnum.PRODUCT_TYPE,
|
||||
valueRequired: true,
|
||||
visibleInStorefront: true,
|
||||
unit: undefined
|
||||
unit: undefined,
|
||||
}
|
||||
: {
|
||||
availableInGrid: attribute?.availableInGrid ?? true,
|
||||
|
@ -129,7 +129,7 @@ const AttributePage: React.FC<AttributePageProps> = ({
|
|||
metadata: attribute?.metadata?.map(mapMetadataItemToInput),
|
||||
name: attribute?.name ?? "",
|
||||
privateMetadata: attribute?.privateMetadata?.map(
|
||||
mapMetadataItemToInput
|
||||
mapMetadataItemToInput,
|
||||
),
|
||||
slug: attribute?.slug ?? "",
|
||||
storefrontSearchPosition:
|
||||
|
@ -137,7 +137,7 @@ const AttributePage: React.FC<AttributePageProps> = ({
|
|||
type: attribute?.type || AttributeTypeEnum.PRODUCT_TYPE,
|
||||
valueRequired: !!attribute?.valueRequired ?? true,
|
||||
visibleInStorefront: attribute?.visibleInStorefront ?? true,
|
||||
unit: attribute?.unit || null
|
||||
unit: attribute?.unit || null,
|
||||
};
|
||||
|
||||
const handleSubmit = (data: AttributePageFormData) => {
|
||||
|
@ -154,7 +154,7 @@ const AttributePage: React.FC<AttributePageProps> = ({
|
|||
metadata,
|
||||
privateMetadata,
|
||||
slug: data.slug || slugify(data.name).toLowerCase(),
|
||||
type
|
||||
type,
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -173,7 +173,7 @@ const AttributePage: React.FC<AttributePageProps> = ({
|
|||
submit,
|
||||
errors,
|
||||
setError,
|
||||
clearErrors
|
||||
clearErrors,
|
||||
}) => {
|
||||
const changeMetadata = makeMetadataChangeHandler(change);
|
||||
|
||||
|
@ -189,7 +189,7 @@ const AttributePage: React.FC<AttributePageProps> = ({
|
|||
? intl.formatMessage({
|
||||
id: "8cUEPV",
|
||||
defaultMessage: "Create New Attribute",
|
||||
description: "page title"
|
||||
description: "page title",
|
||||
})
|
||||
: maybe(() => attribute.name)
|
||||
}
|
||||
|
@ -208,7 +208,7 @@ const AttributePage: React.FC<AttributePageProps> = ({
|
|||
clearErrors={clearErrors}
|
||||
/>
|
||||
{ATTRIBUTE_TYPES_WITH_DEDICATED_VALUES.includes(
|
||||
data.inputType
|
||||
data.inputType,
|
||||
) && (
|
||||
<>
|
||||
<CardSpacer />
|
||||
|
|
|
@ -17,55 +17,55 @@ const messages = defineMessages({
|
|||
availableInGrid: {
|
||||
id: "jswILH",
|
||||
defaultMessage: "Add to Column Options",
|
||||
description: "add attribute as column in product list table"
|
||||
description: "add attribute as column in product list table",
|
||||
},
|
||||
availableInGridCaption: {
|
||||
id: "AzMSmb",
|
||||
defaultMessage:
|
||||
"If enabled this attribute can be used as a column in product table.",
|
||||
description: "caption"
|
||||
description: "caption",
|
||||
},
|
||||
dashboardPropertiesTitle: {
|
||||
id: "lCxfDe",
|
||||
defaultMessage: "Dashboard Properties",
|
||||
description: "attribute properties regarding dashboard"
|
||||
description: "attribute properties regarding dashboard",
|
||||
},
|
||||
filterableInDashboard: {
|
||||
id: "RH+aOF",
|
||||
defaultMessage: "Use in Filtering",
|
||||
description: "use attribute in filtering"
|
||||
description: "use attribute in filtering",
|
||||
},
|
||||
filterableInDashboardCaption: {
|
||||
id: "Q9wTrz",
|
||||
defaultMessage:
|
||||
"If enabled, you’ll be able to use this attribute to filter products in product list.",
|
||||
description: "caption"
|
||||
description: "caption",
|
||||
},
|
||||
filterableInStorefront: {
|
||||
defaultMessage: "Use as filter",
|
||||
id: "e1vU/4",
|
||||
description: "attribute is filterable in storefront"
|
||||
description: "attribute is filterable in storefront",
|
||||
},
|
||||
storefrontPropertiesTitle: {
|
||||
id: "AgY5Mv",
|
||||
defaultMessage: "Storefront Properties",
|
||||
description: "attribute properties regarding storefront"
|
||||
description: "attribute properties regarding storefront",
|
||||
},
|
||||
storefrontSearchPosition: {
|
||||
id: "cJ5ASN",
|
||||
defaultMessage: "Position in faceted navigation",
|
||||
description: "attribute position in storefront filters"
|
||||
description: "attribute position in storefront filters",
|
||||
},
|
||||
visibleInStorefront: {
|
||||
id: "x8V/xS",
|
||||
defaultMessage: "Public",
|
||||
description: "attribute visibility in storefront"
|
||||
description: "attribute visibility in storefront",
|
||||
},
|
||||
visibleInStorefrontCaption: {
|
||||
id: "h2Hta6",
|
||||
defaultMessage: "If enabled, attribute will be accessible to customers.",
|
||||
description: "caption"
|
||||
}
|
||||
description: "caption",
|
||||
},
|
||||
});
|
||||
|
||||
export interface AttributePropertiesProps {
|
||||
|
@ -79,7 +79,7 @@ const AttributeProperties: React.FC<AttributePropertiesProps> = ({
|
|||
data,
|
||||
errors,
|
||||
disabled,
|
||||
onChange
|
||||
onChange,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
|
||||
|
@ -87,7 +87,7 @@ const AttributeProperties: React.FC<AttributePropertiesProps> = ({
|
|||
|
||||
const storefrontFacetedNavigationProperties =
|
||||
ATTRIBUTE_TYPES_WITH_CONFIGURABLE_FACED_NAVIGATION.includes(
|
||||
data.inputType
|
||||
data.inputType,
|
||||
) && data.type === AttributeTypeEnum.PRODUCT_TYPE;
|
||||
|
||||
return (
|
||||
|
@ -112,7 +112,7 @@ const AttributeProperties: React.FC<AttributePropertiesProps> = ({
|
|||
fullWidth
|
||||
helperText={getAttributeErrorMessage(
|
||||
formErrors.storefrontSearchPosition,
|
||||
intl
|
||||
intl,
|
||||
)}
|
||||
name={
|
||||
"storefrontSearchPosition" as keyof AttributePageFormData
|
||||
|
|
|
@ -32,7 +32,7 @@ const AttributeSwatchField: React.FC<AttributeSwatchFieldProps<
|
|||
const [processing, setProcessing] = useState(false);
|
||||
const [uploadFile] = useFileUploadMutation({});
|
||||
const [type, setType] = useState<SwatchType>(
|
||||
data.fileUrl ? "image" : "picker"
|
||||
data.fileUrl ? "image" : "picker",
|
||||
);
|
||||
|
||||
const handleColorChange = (hex: string) =>
|
||||
|
@ -42,20 +42,20 @@ const AttributeSwatchField: React.FC<AttributeSwatchFieldProps<
|
|||
setProcessing(true);
|
||||
|
||||
const {
|
||||
data: { fileUpload }
|
||||
data: { fileUpload },
|
||||
} = await uploadFile({ variables: { file } });
|
||||
|
||||
if (fileUpload.errors?.length) {
|
||||
notify({
|
||||
status: "error",
|
||||
title: intl.formatMessage(errorMessages.imgageUploadErrorTitle),
|
||||
text: intl.formatMessage(errorMessages.imageUploadErrorText)
|
||||
text: intl.formatMessage(errorMessages.imageUploadErrorText),
|
||||
});
|
||||
} else {
|
||||
set({
|
||||
fileUrl: fileUpload.uploadedFile.url,
|
||||
contentType: fileUpload.uploadedFile.contentType,
|
||||
value: undefined
|
||||
value: undefined,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,7 @@ const AttributeSwatchField: React.FC<AttributeSwatchFieldProps<
|
|||
set({
|
||||
fileUrl: undefined,
|
||||
contentType: undefined,
|
||||
value: undefined
|
||||
value: undefined,
|
||||
});
|
||||
|
||||
return (
|
||||
|
@ -76,12 +76,12 @@ const AttributeSwatchField: React.FC<AttributeSwatchFieldProps<
|
|||
choices={[
|
||||
{
|
||||
label: formatMessage(swatchFieldMessages.picker),
|
||||
value: "picker"
|
||||
value: "picker",
|
||||
},
|
||||
{
|
||||
label: formatMessage(swatchFieldMessages.image),
|
||||
value: "image"
|
||||
}
|
||||
value: "image",
|
||||
},
|
||||
]}
|
||||
variant="inline"
|
||||
label={<FormattedMessage {...inputTypeMessages.swatch} />}
|
||||
|
@ -99,7 +99,7 @@ const AttributeSwatchField: React.FC<AttributeSwatchFieldProps<
|
|||
onFileUpload={handleFileUpload}
|
||||
onFileDelete={handleFileDelete}
|
||||
inputProps={{
|
||||
accept: "image/*"
|
||||
accept: "image/*",
|
||||
}}
|
||||
/>
|
||||
|
||||
|
|
|
@ -4,11 +4,11 @@ export const swatchFieldMessages = defineMessages({
|
|||
image: {
|
||||
id: "I2wCwj",
|
||||
defaultMessage: "Image",
|
||||
description: "swatch attribute image label"
|
||||
description: "swatch attribute image label",
|
||||
},
|
||||
picker: {
|
||||
id: "0DgA8v",
|
||||
defaultMessage: "Picker",
|
||||
description: "swatch attribute color picker label"
|
||||
}
|
||||
description: "swatch attribute color picker label",
|
||||
},
|
||||
});
|
||||
|
|
|
@ -7,8 +7,8 @@ export const useStyles = makeStyles(
|
|||
width: 216,
|
||||
height: 216,
|
||||
backgroundSize: "cover",
|
||||
backgroundPosition: "center"
|
||||
}
|
||||
backgroundPosition: "center",
|
||||
},
|
||||
}),
|
||||
{ name: "AttributeSwatchField" }
|
||||
{ name: "AttributeSwatchField" },
|
||||
);
|
||||
|
|
|
@ -21,7 +21,7 @@ const AttributeValueDeleteDialog: React.FC<AttributeValueDeleteDialogProps> = ({
|
|||
useName,
|
||||
onClose,
|
||||
onConfirm,
|
||||
open
|
||||
open,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
|
||||
|
@ -35,7 +35,7 @@ const AttributeValueDeleteDialog: React.FC<AttributeValueDeleteDialogProps> = ({
|
|||
title={intl.formatMessage({
|
||||
id: "WWV8aZ",
|
||||
defaultMessage: "Delete attribute value",
|
||||
description: "dialog title"
|
||||
description: "dialog title",
|
||||
})}
|
||||
>
|
||||
<DialogContentText>
|
||||
|
@ -45,7 +45,7 @@ const AttributeValueDeleteDialog: React.FC<AttributeValueDeleteDialogProps> = ({
|
|||
defaultMessage='Are you sure you want to delete "{name}" value? If you delete it you won’t be able to assign it to any of the products with "{attributeName}" attribute.'
|
||||
values={{
|
||||
attributeName,
|
||||
name
|
||||
name,
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
|
@ -54,7 +54,7 @@ const AttributeValueDeleteDialog: React.FC<AttributeValueDeleteDialogProps> = ({
|
|||
defaultMessage='Are you sure you want to delete "{name}" value?'
|
||||
description="delete attribute value"
|
||||
values={{
|
||||
name
|
||||
name,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
|
|
@ -3,7 +3,7 @@ import {
|
|||
DialogActions,
|
||||
DialogContent,
|
||||
DialogTitle,
|
||||
TextField
|
||||
TextField,
|
||||
} from "@material-ui/core";
|
||||
import { getAttributeValueErrorMessage } from "@saleor/attributes/errors";
|
||||
import BackButton from "@saleor/components/BackButton";
|
||||
|
@ -11,7 +11,7 @@ import ConfirmButton from "@saleor/components/ConfirmButton";
|
|||
import Form from "@saleor/components/Form";
|
||||
import {
|
||||
AttributeErrorFragment,
|
||||
AttributeInputTypeEnum
|
||||
AttributeInputTypeEnum,
|
||||
} from "@saleor/graphql";
|
||||
import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors";
|
||||
import { buttonMessages } from "@saleor/intl";
|
||||
|
@ -42,19 +42,19 @@ const AttributeValueEditDialog: React.FC<AttributeValueEditDialogProps> = ({
|
|||
onClose,
|
||||
onSubmit,
|
||||
open,
|
||||
inputType
|
||||
inputType,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const attributeValueFields = attributeValue?.fileUrl
|
||||
? {
|
||||
fileUrl: attributeValue?.fileUrl,
|
||||
contentType: attributeValue?.contentType
|
||||
contentType: attributeValue?.contentType,
|
||||
}
|
||||
: { value: attributeValue?.value ?? "" };
|
||||
|
||||
const initialForm: AttributeValueEditDialogFormData = {
|
||||
name: attributeValue?.name ?? "",
|
||||
...attributeValueFields
|
||||
...attributeValueFields,
|
||||
};
|
||||
const errors = useModalDialogErrors(apiErrors, open);
|
||||
const formErrors = getFormErrors(["name"], errors);
|
||||
|
@ -89,13 +89,13 @@ const AttributeValueEditDialog: React.FC<AttributeValueEditDialogProps> = ({
|
|||
fullWidth
|
||||
helperText={getAttributeValueErrorMessage(
|
||||
formErrors.name,
|
||||
intl
|
||||
intl,
|
||||
)}
|
||||
name={"name" as keyof AttributeValueEditDialogFormData}
|
||||
label={intl.formatMessage({
|
||||
id: "UhcALJ",
|
||||
defaultMessage: "Name",
|
||||
description: "attribute name"
|
||||
description: "attribute name",
|
||||
})}
|
||||
value={data.name}
|
||||
onChange={change}
|
||||
|
|
|
@ -3,7 +3,7 @@ import {
|
|||
TableCell,
|
||||
TableFooter,
|
||||
TableHead,
|
||||
TableRow
|
||||
TableRow,
|
||||
} from "@material-ui/core";
|
||||
import { Button } from "@saleor/components/Button";
|
||||
import CardTitle from "@saleor/components/CardTitle";
|
||||
|
@ -11,12 +11,12 @@ import ResponsiveTable from "@saleor/components/ResponsiveTable";
|
|||
import Skeleton from "@saleor/components/Skeleton";
|
||||
import {
|
||||
SortableTableBody,
|
||||
SortableTableRow
|
||||
SortableTableRow,
|
||||
} from "@saleor/components/SortableTable";
|
||||
import TablePagination from "@saleor/components/TablePagination";
|
||||
import {
|
||||
AttributeInputTypeEnum,
|
||||
AttributeValueListFragment
|
||||
AttributeValueListFragment,
|
||||
} from "@saleor/graphql";
|
||||
import { DeleteIcon, IconButton, makeStyles } from "@saleor/macaw-ui";
|
||||
import { renderCollection, stopPropagation } from "@saleor/misc";
|
||||
|
@ -24,7 +24,7 @@ import {
|
|||
ListProps,
|
||||
PaginateListProps,
|
||||
RelayToFlat,
|
||||
ReorderAction
|
||||
ReorderAction,
|
||||
} from "@saleor/types";
|
||||
import React from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
|
@ -44,35 +44,35 @@ export interface AttributeValuesProps
|
|||
const useStyles = makeStyles(
|
||||
theme => ({
|
||||
columnSwatch: {
|
||||
width: 100
|
||||
width: 100,
|
||||
},
|
||||
columnAdmin: {
|
||||
width: 300
|
||||
width: 300,
|
||||
},
|
||||
columnDrag: {
|
||||
width: theme.spacing(6 + 1.5)
|
||||
width: theme.spacing(6 + 1.5),
|
||||
},
|
||||
columnStore: {
|
||||
width: "auto"
|
||||
width: "auto",
|
||||
},
|
||||
dragIcon: {
|
||||
cursor: "grab"
|
||||
cursor: "grab",
|
||||
},
|
||||
iconCell: {
|
||||
width: 84
|
||||
width: 84,
|
||||
},
|
||||
link: {
|
||||
cursor: "pointer"
|
||||
cursor: "pointer",
|
||||
},
|
||||
swatch: {
|
||||
width: 32,
|
||||
height: 32,
|
||||
borderRadius: 4,
|
||||
backgroundSize: "cover",
|
||||
backgroundPosition: "center"
|
||||
}
|
||||
backgroundPosition: "center",
|
||||
},
|
||||
}),
|
||||
{ name: "AttributeValues" }
|
||||
{ name: "AttributeValues" },
|
||||
);
|
||||
|
||||
const AttributeValues: React.FC<AttributeValuesProps> = ({
|
||||
|
@ -87,7 +87,7 @@ const AttributeValues: React.FC<AttributeValuesProps> = ({
|
|||
pageInfo,
|
||||
onNextPage,
|
||||
onPreviousPage,
|
||||
inputType
|
||||
inputType,
|
||||
}) => {
|
||||
const classes = useStyles({});
|
||||
const intl = useIntl();
|
||||
|
@ -101,7 +101,7 @@ const AttributeValues: React.FC<AttributeValuesProps> = ({
|
|||
title={intl.formatMessage({
|
||||
id: "J3uE0t",
|
||||
defaultMessage: "Attribute Values",
|
||||
description: "section header"
|
||||
description: "section header",
|
||||
})}
|
||||
toolbar={
|
||||
<Button
|
||||
|
@ -214,7 +214,7 @@ const AttributeValues: React.FC<AttributeValuesProps> = ({
|
|||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)
|
||||
),
|
||||
)}
|
||||
</SortableTableBody>
|
||||
</ResponsiveTable>
|
||||
|
|
|
@ -5,17 +5,17 @@ import { defineMessages, IntlShape } from "react-intl";
|
|||
const messages = defineMessages({
|
||||
attributeSlugUnique: {
|
||||
id: "eWV760",
|
||||
defaultMessage: "Attribute with this slug already exists"
|
||||
defaultMessage: "Attribute with this slug already exists",
|
||||
},
|
||||
attributeValueAlreadyExists: {
|
||||
id: "J/QqOI",
|
||||
defaultMessage: "This value already exists within this attribute"
|
||||
}
|
||||
defaultMessage: "This value already exists within this attribute",
|
||||
},
|
||||
});
|
||||
|
||||
export function getAttributeSlugErrorMessage(
|
||||
err: AttributeErrorFragment,
|
||||
intl: IntlShape
|
||||
intl: IntlShape,
|
||||
): string {
|
||||
switch (err?.code) {
|
||||
case AttributeErrorCode.UNIQUE:
|
||||
|
@ -27,7 +27,7 @@ export function getAttributeSlugErrorMessage(
|
|||
|
||||
export function getAttributeValueErrorMessage(
|
||||
err: AttributeErrorFragment,
|
||||
intl: IntlShape
|
||||
intl: IntlShape,
|
||||
): string {
|
||||
switch (err?.code) {
|
||||
case AttributeErrorCode.ALREADY_EXISTS:
|
||||
|
|
|
@ -4,7 +4,7 @@ import {
|
|||
AttributeInputTypeEnum,
|
||||
AttributeListQuery,
|
||||
AttributeTypeEnum,
|
||||
ProductDetailsQuery
|
||||
ProductDetailsQuery,
|
||||
} from "@saleor/graphql";
|
||||
|
||||
export const attribute: AttributeDetailsQuery["attribute"] = {
|
||||
|
@ -19,8 +19,8 @@ export const attribute: AttributeDetailsQuery["attribute"] = {
|
|||
{
|
||||
__typename: "MetadataItem",
|
||||
key: "integration.id",
|
||||
value: "100023123"
|
||||
}
|
||||
value: "100023123",
|
||||
},
|
||||
],
|
||||
name: "Author",
|
||||
privateMetadata: [],
|
||||
|
@ -36,7 +36,7 @@ export const attribute: AttributeDetailsQuery["attribute"] = {
|
|||
endCursor: "",
|
||||
hasNextPage: false,
|
||||
hasPreviousPage: false,
|
||||
startCursor: ""
|
||||
startCursor: "",
|
||||
},
|
||||
edges: [
|
||||
{
|
||||
|
@ -53,8 +53,8 @@ export const attribute: AttributeDetailsQuery["attribute"] = {
|
|||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null,
|
||||
value: null
|
||||
}
|
||||
value: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: "AttributeValueCountableEdge" as "AttributeValueCountableEdge",
|
||||
|
@ -70,12 +70,12 @@ export const attribute: AttributeDetailsQuery["attribute"] = {
|
|||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null,
|
||||
value: null
|
||||
}
|
||||
}
|
||||
]
|
||||
value: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
visibleInStorefront: true
|
||||
visibleInStorefront: true,
|
||||
};
|
||||
|
||||
export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["node"] &
|
||||
|
@ -99,7 +99,7 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
hasNextPage: false,
|
||||
hasPreviousPage: false,
|
||||
startCursor: "WyIwIiwgIjQ5Il0=",
|
||||
__typename: "PageInfo" as "PageInfo"
|
||||
__typename: "PageInfo" as "PageInfo",
|
||||
},
|
||||
edges: [
|
||||
{
|
||||
|
@ -117,8 +117,8 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: "AttributeValueCountableEdge" as "AttributeValueCountableEdge",
|
||||
|
@ -135,12 +135,12 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
}
|
||||
]
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
visibleInStorefront: true
|
||||
visibleInStorefront: true,
|
||||
},
|
||||
{
|
||||
__typename: "Attribute" as "Attribute",
|
||||
|
@ -161,7 +161,7 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
hasNextPage: false,
|
||||
hasPreviousPage: false,
|
||||
startCursor: "WyIwIiwgIjQ5Il0=",
|
||||
__typename: "PageInfo" as "PageInfo"
|
||||
__typename: "PageInfo" as "PageInfo",
|
||||
},
|
||||
edges: [
|
||||
{
|
||||
|
@ -179,8 +179,8 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: "AttributeValueCountableEdge" as "AttributeValueCountableEdge",
|
||||
|
@ -197,8 +197,8 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: "AttributeValueCountableEdge" as "AttributeValueCountableEdge",
|
||||
|
@ -215,8 +215,8 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: "AttributeValueCountableEdge" as "AttributeValueCountableEdge",
|
||||
|
@ -233,12 +233,12 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
}
|
||||
]
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
visibleInStorefront: false
|
||||
visibleInStorefront: false,
|
||||
},
|
||||
{
|
||||
__typename: "Attribute" as "Attribute",
|
||||
|
@ -259,7 +259,7 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
hasNextPage: false,
|
||||
hasPreviousPage: false,
|
||||
startCursor: "WyIwIiwgIjQ5Il0=",
|
||||
__typename: "PageInfo" as "PageInfo"
|
||||
__typename: "PageInfo" as "PageInfo",
|
||||
},
|
||||
edges: [
|
||||
{
|
||||
|
@ -277,12 +277,12 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
}
|
||||
]
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
visibleInStorefront: false
|
||||
visibleInStorefront: false,
|
||||
},
|
||||
{
|
||||
__typename: "Attribute" as "Attribute",
|
||||
|
@ -303,7 +303,7 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
hasNextPage: false,
|
||||
hasPreviousPage: false,
|
||||
startCursor: "WyIwIiwgIjQ5Il0=",
|
||||
__typename: "PageInfo" as "PageInfo"
|
||||
__typename: "PageInfo" as "PageInfo",
|
||||
},
|
||||
edges: [
|
||||
{
|
||||
|
@ -321,8 +321,8 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: "AttributeValueCountableEdge" as "AttributeValueCountableEdge",
|
||||
|
@ -339,8 +339,8 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: "AttributeValueCountableEdge" as "AttributeValueCountableEdge",
|
||||
|
@ -357,12 +357,12 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
}
|
||||
]
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
visibleInStorefront: false
|
||||
visibleInStorefront: false,
|
||||
},
|
||||
{
|
||||
__typename: "Attribute" as "Attribute",
|
||||
|
@ -383,7 +383,7 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
hasNextPage: false,
|
||||
hasPreviousPage: false,
|
||||
startCursor: "WyIwIiwgIjQ5Il0=",
|
||||
__typename: "PageInfo" as "PageInfo"
|
||||
__typename: "PageInfo" as "PageInfo",
|
||||
},
|
||||
edges: [
|
||||
{
|
||||
|
@ -401,8 +401,8 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: "AttributeValueCountableEdge" as "AttributeValueCountableEdge",
|
||||
|
@ -419,12 +419,12 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
}
|
||||
]
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
visibleInStorefront: true
|
||||
visibleInStorefront: true,
|
||||
},
|
||||
{
|
||||
__typename: "Attribute" as "Attribute",
|
||||
|
@ -445,7 +445,7 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
hasNextPage: false,
|
||||
hasPreviousPage: false,
|
||||
startCursor: "WyIwIiwgIjQ5Il0=",
|
||||
__typename: "PageInfo" as "PageInfo"
|
||||
__typename: "PageInfo" as "PageInfo",
|
||||
},
|
||||
edges: [
|
||||
{
|
||||
|
@ -463,8 +463,8 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: "AttributeValueCountableEdge" as "AttributeValueCountableEdge",
|
||||
|
@ -481,8 +481,8 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: "AttributeValueCountableEdge" as "AttributeValueCountableEdge",
|
||||
|
@ -499,12 +499,12 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
}
|
||||
]
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
visibleInStorefront: true
|
||||
visibleInStorefront: true,
|
||||
},
|
||||
{
|
||||
__typename: "Attribute" as "Attribute",
|
||||
|
@ -525,7 +525,7 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
hasNextPage: false,
|
||||
hasPreviousPage: false,
|
||||
startCursor: "WyIwIiwgIjQ5Il0=",
|
||||
__typename: "PageInfo" as "PageInfo"
|
||||
__typename: "PageInfo" as "PageInfo",
|
||||
},
|
||||
edges: [
|
||||
{
|
||||
|
@ -543,8 +543,8 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: "AttributeValueCountableEdge" as "AttributeValueCountableEdge",
|
||||
|
@ -561,12 +561,12 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
}
|
||||
]
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
visibleInStorefront: true
|
||||
visibleInStorefront: true,
|
||||
},
|
||||
{
|
||||
__typename: "Attribute" as "Attribute",
|
||||
|
@ -587,7 +587,7 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
hasNextPage: false,
|
||||
hasPreviousPage: false,
|
||||
startCursor: "WyIwIiwgIjQ5Il0=",
|
||||
__typename: "PageInfo" as "PageInfo"
|
||||
__typename: "PageInfo" as "PageInfo",
|
||||
},
|
||||
edges: [
|
||||
{
|
||||
|
@ -605,8 +605,8 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: "AttributeValueCountableEdge" as "AttributeValueCountableEdge",
|
||||
|
@ -623,8 +623,8 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: "AttributeValueCountableEdge" as "AttributeValueCountableEdge",
|
||||
|
@ -641,8 +641,8 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: "AttributeValueCountableEdge" as "AttributeValueCountableEdge",
|
||||
|
@ -659,8 +659,8 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: "AttributeValueCountableEdge" as "AttributeValueCountableEdge",
|
||||
|
@ -677,8 +677,8 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: "AttributeValueCountableEdge" as "AttributeValueCountableEdge",
|
||||
|
@ -695,12 +695,12 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
}
|
||||
]
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
visibleInStorefront: false
|
||||
visibleInStorefront: false,
|
||||
},
|
||||
{
|
||||
__typename: "Attribute" as "Attribute",
|
||||
|
@ -721,7 +721,7 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
hasNextPage: false,
|
||||
hasPreviousPage: false,
|
||||
startCursor: "WyIwIiwgIjQ5Il0=",
|
||||
__typename: "PageInfo" as "PageInfo"
|
||||
__typename: "PageInfo" as "PageInfo",
|
||||
},
|
||||
edges: [
|
||||
{
|
||||
|
@ -739,8 +739,8 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: "AttributeValueCountableEdge" as "AttributeValueCountableEdge",
|
||||
|
@ -757,12 +757,12 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
}
|
||||
]
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
visibleInStorefront: true
|
||||
visibleInStorefront: true,
|
||||
},
|
||||
{
|
||||
__typename: "Attribute" as "Attribute",
|
||||
|
@ -783,7 +783,7 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
hasNextPage: false,
|
||||
hasPreviousPage: false,
|
||||
startCursor: "WyIwIiwgIjQ5Il0=",
|
||||
__typename: "PageInfo" as "PageInfo"
|
||||
__typename: "PageInfo" as "PageInfo",
|
||||
},
|
||||
edges: [
|
||||
{
|
||||
|
@ -801,8 +801,8 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: "AttributeValueCountableEdge" as "AttributeValueCountableEdge",
|
||||
|
@ -819,12 +819,12 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
}
|
||||
]
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
visibleInStorefront: true
|
||||
visibleInStorefront: true,
|
||||
},
|
||||
{
|
||||
__typename: "Attribute" as "Attribute",
|
||||
|
@ -845,7 +845,7 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
hasNextPage: false,
|
||||
hasPreviousPage: false,
|
||||
startCursor: "WyIwIiwgIjQ5Il0=",
|
||||
__typename: "PageInfo" as "PageInfo"
|
||||
__typename: "PageInfo" as "PageInfo",
|
||||
},
|
||||
edges: [
|
||||
{
|
||||
|
@ -863,8 +863,8 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: "AttributeValueCountableEdge" as "AttributeValueCountableEdge",
|
||||
|
@ -881,12 +881,12 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
}
|
||||
]
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
visibleInStorefront: true
|
||||
visibleInStorefront: true,
|
||||
},
|
||||
{
|
||||
__typename: "Attribute" as "Attribute",
|
||||
|
@ -907,7 +907,7 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
hasNextPage: false,
|
||||
hasPreviousPage: false,
|
||||
startCursor: "WyIwIiwgIjQ5Il0=",
|
||||
__typename: "PageInfo" as "PageInfo"
|
||||
__typename: "PageInfo" as "PageInfo",
|
||||
},
|
||||
edges: [
|
||||
{
|
||||
|
@ -925,8 +925,8 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: "AttributeValueCountableEdge" as "AttributeValueCountableEdge",
|
||||
|
@ -943,8 +943,8 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: "AttributeValueCountableEdge" as "AttributeValueCountableEdge",
|
||||
|
@ -961,8 +961,8 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: "AttributeValueCountableEdge" as "AttributeValueCountableEdge",
|
||||
|
@ -979,8 +979,8 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: "AttributeValueCountableEdge" as "AttributeValueCountableEdge",
|
||||
|
@ -997,8 +997,8 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: "AttributeValueCountableEdge" as "AttributeValueCountableEdge",
|
||||
|
@ -1015,11 +1015,11 @@ export const attributes: Array<AttributeListQuery["attributes"]["edges"][0]["nod
|
|||
richText: null,
|
||||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null
|
||||
}
|
||||
}
|
||||
]
|
||||
dateTime: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
visibleInStorefront: true
|
||||
}
|
||||
visibleInStorefront: true,
|
||||
},
|
||||
];
|
||||
|
|
|
@ -13,7 +13,7 @@ import {
|
|||
AttributeListUrlQueryParams,
|
||||
AttributeListUrlSortField,
|
||||
attributePath,
|
||||
AttributeUrlQueryParams
|
||||
AttributeUrlQueryParams,
|
||||
} from "./urls";
|
||||
import AttributeCreateComponent from "./views/AttributeCreate";
|
||||
import AttributeDetailsComponent from "./views/AttributeDetails";
|
||||
|
@ -23,7 +23,7 @@ const AttributeList: React.FC<RouteComponentProps<{}>> = ({ location }) => {
|
|||
const qs = parseQs(location.search.substr(1));
|
||||
const params: AttributeListUrlQueryParams = asSortParams(
|
||||
qs,
|
||||
AttributeListUrlSortField
|
||||
AttributeListUrlSortField,
|
||||
);
|
||||
|
||||
return <AttributeListComponent params={params} />;
|
||||
|
@ -37,7 +37,7 @@ const AttributeCreate: React.FC<RouteComponentProps<{}>> = ({ location }) => {
|
|||
|
||||
const AttributeDetails: React.FC<RouteComponentProps<{ id: string }>> = ({
|
||||
location,
|
||||
match
|
||||
match,
|
||||
}) => {
|
||||
const qs = parseQs(location.search.substr(1));
|
||||
const params: AttributeUrlQueryParams = qs;
|
||||
|
|
|
@ -9,7 +9,7 @@ import {
|
|||
Pagination,
|
||||
SingleAction,
|
||||
Sort,
|
||||
TabActionDialog
|
||||
TabActionDialog,
|
||||
} from "../types";
|
||||
|
||||
export const attributeSection = "/attributes/";
|
||||
|
@ -19,7 +19,7 @@ export enum AttributeListUrlFiltersEnum {
|
|||
isVariantOnly = "isVariantOnly",
|
||||
valueRequired = "valueRequired",
|
||||
visibleInStorefront = "visibleInStorefront",
|
||||
query = "query"
|
||||
query = "query",
|
||||
}
|
||||
export type AttributeListUrlFilters = Filters<AttributeListUrlFiltersEnum>;
|
||||
export type AttributeListUrlDialog = "remove" | TabActionDialog;
|
||||
|
@ -28,7 +28,7 @@ export enum AttributeListUrlSortField {
|
|||
slug = "slug",
|
||||
visible = "visible",
|
||||
searchable = "searchable",
|
||||
useInFacetedSearch = "use-in-faceted-search"
|
||||
useInFacetedSearch = "use-in-faceted-search",
|
||||
}
|
||||
export type AttributeListUrlSort = Sort<AttributeListUrlSortField>;
|
||||
export type AttributeListUrlQueryParams = ActiveTab &
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { FetchResult } from "@apollo/client";
|
||||
import {
|
||||
AttributeInput,
|
||||
AttributeInputData
|
||||
AttributeInputData,
|
||||
} from "@saleor/components/Attributes";
|
||||
import {
|
||||
AttributeEntityTypeEnum,
|
||||
|
@ -19,19 +19,19 @@ import {
|
|||
SearchProductsQuery,
|
||||
SelectedVariantAttributeFragment,
|
||||
UploadErrorFragment,
|
||||
VariantAttributeFragment
|
||||
VariantAttributeFragment,
|
||||
} from "@saleor/graphql";
|
||||
import { FormsetData } from "@saleor/hooks/useFormset";
|
||||
import { RelayToFlat } from "@saleor/types";
|
||||
import {
|
||||
mapEdgesToItems,
|
||||
mapNodeToChoice,
|
||||
mapPagesToChoices
|
||||
mapPagesToChoices,
|
||||
} from "@saleor/utils/maps";
|
||||
import { RichTextContextValues } from "@saleor/utils/richText/context";
|
||||
import {
|
||||
GetRichTextValues,
|
||||
RichTextGetters
|
||||
RichTextGetters,
|
||||
} from "@saleor/utils/richText/useMultipleRichText";
|
||||
|
||||
import { AttributePageFormData } from "../components/AttributePage";
|
||||
|
@ -49,7 +49,7 @@ export interface RichTextProps {
|
|||
export const ATTRIBUTE_TYPES_WITH_DEDICATED_VALUES = [
|
||||
AttributeInputTypeEnum.DROPDOWN,
|
||||
AttributeInputTypeEnum.MULTISELECT,
|
||||
AttributeInputTypeEnum.SWATCH
|
||||
AttributeInputTypeEnum.SWATCH,
|
||||
];
|
||||
|
||||
export const ATTRIBUTE_TYPES_WITH_CONFIGURABLE_FACED_NAVIGATION = [
|
||||
|
@ -59,14 +59,14 @@ export const ATTRIBUTE_TYPES_WITH_CONFIGURABLE_FACED_NAVIGATION = [
|
|||
AttributeInputTypeEnum.DATE,
|
||||
AttributeInputTypeEnum.DATE_TIME,
|
||||
AttributeInputTypeEnum.NUMERIC,
|
||||
AttributeInputTypeEnum.SWATCH
|
||||
AttributeInputTypeEnum.SWATCH,
|
||||
];
|
||||
|
||||
export function filterable(
|
||||
attribute: Pick<AttributeFragment, "inputType">
|
||||
attribute: Pick<AttributeFragment, "inputType">,
|
||||
): boolean {
|
||||
return ATTRIBUTE_TYPES_WITH_CONFIGURABLE_FACED_NAVIGATION.includes(
|
||||
attribute.inputType
|
||||
attribute.inputType,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -83,19 +83,19 @@ export interface AttributeValueEditDialogFormData {
|
|||
}
|
||||
|
||||
export function attributeValueFragmentToFormData(
|
||||
data: AttributeValueFragment | null
|
||||
data: AttributeValueFragment | null,
|
||||
): AttributeValueEditDialogFormData {
|
||||
return {
|
||||
name: data?.name,
|
||||
value: data?.value,
|
||||
contentType: data?.file?.contentType,
|
||||
fileUrl: data?.file?.url
|
||||
fileUrl: data?.file?.url,
|
||||
};
|
||||
}
|
||||
|
||||
function getSimpleAttributeData(
|
||||
data: AttributePageFormData,
|
||||
values: AttributeValueEditDialogFormData[]
|
||||
values: AttributeValueEditDialogFormData[],
|
||||
) {
|
||||
return {
|
||||
...data,
|
||||
|
@ -103,8 +103,8 @@ function getSimpleAttributeData(
|
|||
privateMetadata: undefined,
|
||||
storefrontSearchPosition: parseInt(data.storefrontSearchPosition, 10),
|
||||
values: values.map(value => ({
|
||||
name: value.name
|
||||
}))
|
||||
name: value.name,
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -112,42 +112,42 @@ function getAttributeValueTypeFields({
|
|||
fileUrl,
|
||||
value,
|
||||
name,
|
||||
contentType
|
||||
contentType,
|
||||
}: AttributeValueEditDialogFormData) {
|
||||
return {
|
||||
name,
|
||||
...(fileUrl ? { fileUrl, contentType } : { value })
|
||||
...(fileUrl ? { fileUrl, contentType } : { value }),
|
||||
};
|
||||
}
|
||||
|
||||
function getSwatchAttributeData(
|
||||
data: AttributePageFormData,
|
||||
values: AttributeValueEditDialogFormData[]
|
||||
values: AttributeValueEditDialogFormData[],
|
||||
) {
|
||||
return {
|
||||
...data,
|
||||
metadata: undefined,
|
||||
privateMetadata: undefined,
|
||||
storefrontSearchPosition: parseInt(data.storefrontSearchPosition, 10),
|
||||
values: values.map(getAttributeValueTypeFields)
|
||||
values: values.map(getAttributeValueTypeFields),
|
||||
};
|
||||
}
|
||||
|
||||
function getFileOrReferenceAttributeData(
|
||||
data: AttributePageFormData,
|
||||
values: AttributeValueEditDialogFormData[]
|
||||
values: AttributeValueEditDialogFormData[],
|
||||
) {
|
||||
return {
|
||||
...getSimpleAttributeData(data, values),
|
||||
availableInGrid: undefined,
|
||||
filterableInDashboard: undefined,
|
||||
filterableInStorefront: undefined
|
||||
filterableInStorefront: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
export function getAttributeData(
|
||||
data: AttributePageFormData,
|
||||
values: AttributeValueEditDialogFormData[]
|
||||
values: AttributeValueEditDialogFormData[],
|
||||
) {
|
||||
if (data.inputType === AttributeInputTypeEnum.SWATCH) {
|
||||
return getSwatchAttributeData(data, values);
|
||||
|
@ -172,7 +172,7 @@ export function getSelectedAttributeValues(
|
|||
attribute:
|
||||
| PageSelectedAttributeFragment
|
||||
| ProductFragment["attributes"][0]
|
||||
| SelectedVariantAttributeFragment
|
||||
| SelectedVariantAttributeFragment,
|
||||
) {
|
||||
switch (attribute.attribute.inputType) {
|
||||
case AttributeInputTypeEnum.REFERENCE:
|
||||
|
@ -203,7 +203,7 @@ export const isFileValueUnused = (
|
|||
existingAttribute:
|
||||
| PageSelectedAttributeFragment
|
||||
| ProductFragment["attributes"][0]
|
||||
| SelectedVariantAttributeFragment
|
||||
| SelectedVariantAttributeFragment,
|
||||
) => {
|
||||
if (existingAttribute.attribute.inputType !== AttributeInputTypeEnum.FILE) {
|
||||
return false;
|
||||
|
@ -213,14 +213,14 @@ export const isFileValueUnused = (
|
|||
}
|
||||
|
||||
const modifiedAttribute = attributesWithNewFileValue.find(
|
||||
dataAttribute => dataAttribute.id === existingAttribute.attribute.id
|
||||
dataAttribute => dataAttribute.id === existingAttribute.attribute.id,
|
||||
);
|
||||
|
||||
return !!modifiedAttribute;
|
||||
};
|
||||
|
||||
export const mergeFileUploadErrors = (
|
||||
uploadFilesResult: Array<FetchResult<FileUploadMutation>>
|
||||
uploadFilesResult: Array<FetchResult<FileUploadMutation>>,
|
||||
): UploadErrorFragment[] =>
|
||||
uploadFilesResult.reduce((errors, uploadFileResult) => {
|
||||
const uploadErrors = uploadFileResult?.data?.fileUpload?.errors;
|
||||
|
@ -231,7 +231,7 @@ export const mergeFileUploadErrors = (
|
|||
}, []);
|
||||
|
||||
export const mergeAttributeValueDeleteErrors = (
|
||||
deleteAttributeValuesResult: Array<FetchResult<AttributeValueDeleteMutation>>
|
||||
deleteAttributeValuesResult: Array<FetchResult<AttributeValueDeleteMutation>>,
|
||||
): AttributeErrorFragment[] =>
|
||||
deleteAttributeValuesResult.reduce((errors, deleteValueResult) => {
|
||||
const deleteErrors = deleteValueResult?.data?.attributeValueDelete?.errors;
|
||||
|
@ -245,11 +245,11 @@ export const mergeChoicesWithValues = (
|
|||
attribute:
|
||||
| ProductFragment["attributes"][0]
|
||||
| PageSelectedAttributeFragment
|
||||
| SelectedVariantAttributeFragment
|
||||
| SelectedVariantAttributeFragment,
|
||||
) => {
|
||||
const choices = mapEdgesToItems(attribute.attribute.choices) || [];
|
||||
const valuesToConcat = attribute.values.filter(
|
||||
value => !choices.some(choice => choice.id === value.id)
|
||||
value => !choices.some(choice => choice.id === value.id),
|
||||
);
|
||||
|
||||
return choices.concat(valuesToConcat);
|
||||
|
@ -258,7 +258,7 @@ export const mergeChoicesWithValues = (
|
|||
export const mergeAttributeValues = (
|
||||
attributeId: string,
|
||||
attributeValues: string[],
|
||||
attributes: FormsetData<AttributeInputData, string[]>
|
||||
attributes: FormsetData<AttributeInputData, string[]>,
|
||||
) => {
|
||||
const attribute = attributes.find(attribute => attribute.id === attributeId);
|
||||
|
||||
|
@ -274,28 +274,29 @@ export const mergeAttributes = (
|
|||
const newAttributeIds = new Set(attributes.map(attr => attr.id));
|
||||
return [
|
||||
...prev.filter(attr => !newAttributeIds.has(attr.id)),
|
||||
...attributes
|
||||
...attributes,
|
||||
];
|
||||
}, []);
|
||||
|
||||
export function getRichTextAttributesFromMap(
|
||||
attributes: AttributeInput[],
|
||||
values: GetRichTextValues
|
||||
values: GetRichTextValues,
|
||||
): AttributeInput[] {
|
||||
return attributes
|
||||
.filter(({ data }) => data.inputType === AttributeInputTypeEnum.RICH_TEXT)
|
||||
.map(attribute => ({
|
||||
...attribute,
|
||||
value: [JSON.stringify(values[attribute.id])]
|
||||
value: [JSON.stringify(values[attribute.id])],
|
||||
}));
|
||||
}
|
||||
|
||||
export function getRichTextDataFromAttributes(
|
||||
attributes: AttributeInput[] = []
|
||||
attributes: AttributeInput[] = [],
|
||||
): Record<string, string> {
|
||||
const keyValuePairs = attributes
|
||||
.filter(
|
||||
attribute => attribute.data.inputType === AttributeInputTypeEnum.RICH_TEXT
|
||||
attribute =>
|
||||
attribute.data.inputType === AttributeInputTypeEnum.RICH_TEXT,
|
||||
)
|
||||
.map(attribute => [attribute.id, attribute.value[0]]);
|
||||
|
||||
|
@ -303,26 +304,26 @@ export function getRichTextDataFromAttributes(
|
|||
}
|
||||
|
||||
export const getFileValuesToUploadFromAttributes = (
|
||||
attributesWithNewFileValue: FormsetData<null, File>
|
||||
attributesWithNewFileValue: FormsetData<null, File>,
|
||||
) => attributesWithNewFileValue.filter(fileAttribute => !!fileAttribute.value);
|
||||
|
||||
export const getFileValuesRemovedFromAttributes = (
|
||||
attributesWithNewFileValue: FormsetData<null, File>
|
||||
attributesWithNewFileValue: FormsetData<null, File>,
|
||||
) => attributesWithNewFileValue.filter(attribute => !attribute.value);
|
||||
|
||||
export const getAttributesOfRemovedFiles = (
|
||||
fileAttributesRemoved: FormsetData<null, File>
|
||||
fileAttributesRemoved: FormsetData<null, File>,
|
||||
): AtributesOfFiles[] =>
|
||||
fileAttributesRemoved.map(attribute => ({
|
||||
file: undefined,
|
||||
id: attribute.id,
|
||||
contentType: attribute.value?.type,
|
||||
values: []
|
||||
values: [],
|
||||
}));
|
||||
|
||||
export const getAttributesOfUploadedFiles = (
|
||||
fileValuesToUpload: FormsetData<null, File>,
|
||||
uploadFilesResult: Array<FetchResult<FileUploadMutation>>
|
||||
uploadFilesResult: Array<FetchResult<FileUploadMutation>>,
|
||||
): AtributesOfFiles[] =>
|
||||
uploadFilesResult.map((uploadFileResult, index) => {
|
||||
const attribute = fileValuesToUpload[index];
|
||||
|
@ -331,25 +332,25 @@ export const getAttributesOfUploadedFiles = (
|
|||
file: uploadFileResult.data.fileUpload.uploadedFile.url,
|
||||
contentType: uploadFileResult.data.fileUpload.uploadedFile.contentType,
|
||||
id: attribute.id,
|
||||
values: []
|
||||
values: [],
|
||||
};
|
||||
});
|
||||
|
||||
export const getAttributesAfterFileAttributesUpdate = (
|
||||
attributesWithNewFileValue: FormsetData<null, File>,
|
||||
uploadFilesResult: Array<FetchResult<FileUploadMutation>>
|
||||
uploadFilesResult: Array<FetchResult<FileUploadMutation>>,
|
||||
): AttributeValueInput[] => {
|
||||
const removedFileValues = getFileValuesRemovedFromAttributes(
|
||||
attributesWithNewFileValue
|
||||
attributesWithNewFileValue,
|
||||
);
|
||||
const fileValuesToUpload = getFileValuesToUploadFromAttributes(
|
||||
attributesWithNewFileValue
|
||||
attributesWithNewFileValue,
|
||||
);
|
||||
|
||||
const removedFileAttributes = getAttributesOfRemovedFiles(removedFileValues);
|
||||
const uploadedFileAttributes = getAttributesOfUploadedFiles(
|
||||
fileValuesToUpload,
|
||||
uploadFilesResult
|
||||
uploadFilesResult,
|
||||
);
|
||||
|
||||
return uploadedFileAttributes.concat(removedFileAttributes);
|
||||
|
@ -357,10 +358,10 @@ export const getAttributesAfterFileAttributesUpdate = (
|
|||
|
||||
export const getFileAttributeDisplayData = (
|
||||
attribute: AttributeInput,
|
||||
attributesWithNewFileValue: FormsetData<null, File>
|
||||
attributesWithNewFileValue: FormsetData<null, File>,
|
||||
) => {
|
||||
const attributeWithNewFileValue = attributesWithNewFileValue.find(
|
||||
attributeWithNewFile => attribute.id === attributeWithNewFile.id
|
||||
attributeWithNewFile => attribute.id === attributeWithNewFile.id,
|
||||
);
|
||||
|
||||
if (attributeWithNewFileValue) {
|
||||
|
@ -368,7 +369,7 @@ export const getFileAttributeDisplayData = (
|
|||
...attribute,
|
||||
value: attributeWithNewFileValue?.value?.name
|
||||
? [attributeWithNewFileValue.value.name]
|
||||
: []
|
||||
: [],
|
||||
};
|
||||
}
|
||||
return attribute;
|
||||
|
@ -376,7 +377,7 @@ export const getFileAttributeDisplayData = (
|
|||
|
||||
export const getPageReferenceAttributeDisplayData = (
|
||||
attribute: AttributeInput,
|
||||
referencePages: RelayToFlat<SearchPagesQuery["search"]>
|
||||
referencePages: RelayToFlat<SearchPagesQuery["search"]>,
|
||||
) => ({
|
||||
...attribute,
|
||||
data: {
|
||||
|
@ -386,18 +387,18 @@ export const getPageReferenceAttributeDisplayData = (
|
|||
? mapPagesToChoices(
|
||||
attribute.value.map(value => {
|
||||
const reference = referencePages.find(
|
||||
reference => reference.id === value
|
||||
reference => reference.id === value,
|
||||
);
|
||||
return { ...reference };
|
||||
})
|
||||
}),
|
||||
)
|
||||
: []
|
||||
}
|
||||
: [],
|
||||
},
|
||||
});
|
||||
|
||||
export const getProductReferenceAttributeDisplayData = (
|
||||
attribute: AttributeInput,
|
||||
referenceProducts: RelayToFlat<SearchProductsQuery["search"]>
|
||||
referenceProducts: RelayToFlat<SearchProductsQuery["search"]>,
|
||||
) => ({
|
||||
...attribute,
|
||||
data: {
|
||||
|
@ -407,26 +408,26 @@ export const getProductReferenceAttributeDisplayData = (
|
|||
? mapNodeToChoice(
|
||||
attribute.value.map(value => {
|
||||
const reference = referenceProducts.find(
|
||||
reference => reference.id === value
|
||||
reference => reference.id === value,
|
||||
);
|
||||
return { ...reference };
|
||||
})
|
||||
}),
|
||||
)
|
||||
: []
|
||||
}
|
||||
: [],
|
||||
},
|
||||
});
|
||||
|
||||
export const getReferenceAttributeDisplayData = (
|
||||
attribute: AttributeInput,
|
||||
referencePages: RelayToFlat<SearchPagesQuery["search"]>,
|
||||
referenceProducts: RelayToFlat<SearchProductsQuery["search"]>
|
||||
referenceProducts: RelayToFlat<SearchProductsQuery["search"]>,
|
||||
) => {
|
||||
if (attribute.data.entityType === AttributeEntityTypeEnum.PAGE) {
|
||||
return getPageReferenceAttributeDisplayData(attribute, referencePages);
|
||||
} else if (attribute.data.entityType === AttributeEntityTypeEnum.PRODUCT) {
|
||||
return getProductReferenceAttributeDisplayData(
|
||||
attribute,
|
||||
referenceProducts
|
||||
referenceProducts,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
@ -435,14 +436,14 @@ export const getAttributesDisplayData = (
|
|||
attributes: AttributeInput[],
|
||||
attributesWithNewFileValue: FormsetData<null, File>,
|
||||
referencePages: RelayToFlat<SearchPagesQuery["search"]>,
|
||||
referenceProducts: RelayToFlat<SearchProductsQuery["search"]>
|
||||
referenceProducts: RelayToFlat<SearchProductsQuery["search"]>,
|
||||
) =>
|
||||
attributes.map(attribute => {
|
||||
if (attribute.data.inputType === AttributeInputTypeEnum.REFERENCE) {
|
||||
return getReferenceAttributeDisplayData(
|
||||
attribute,
|
||||
referencePages,
|
||||
referenceProducts
|
||||
referenceProducts,
|
||||
);
|
||||
}
|
||||
if (attribute.data.inputType === AttributeInputTypeEnum.FILE) {
|
||||
|
@ -453,28 +454,28 @@ export const getAttributesDisplayData = (
|
|||
|
||||
export const getSelectedReferencesFromAttribute = <T extends Node>(
|
||||
attribute?: AttributeInput,
|
||||
references?: T[]
|
||||
references?: T[],
|
||||
) =>
|
||||
references?.filter(
|
||||
value =>
|
||||
!attribute?.value?.some(selectedValue => selectedValue === value.id)
|
||||
!attribute?.value?.some(selectedValue => selectedValue === value.id),
|
||||
) || [];
|
||||
|
||||
export const getAttributeValuesFromReferences = (
|
||||
attributeId: string,
|
||||
attributes?: AttributeInput[],
|
||||
referencePages?: RelayToFlat<SearchPagesQuery["search"]>,
|
||||
referenceProducts?: RelayToFlat<SearchProductsQuery["search"]>
|
||||
referenceProducts?: RelayToFlat<SearchProductsQuery["search"]>,
|
||||
) => {
|
||||
const attribute = attributes?.find(attribute => attribute.id === attributeId);
|
||||
|
||||
if (attribute?.data?.entityType === AttributeEntityTypeEnum.PAGE) {
|
||||
return mapPagesToChoices(
|
||||
getSelectedReferencesFromAttribute(attribute, referencePages)
|
||||
getSelectedReferencesFromAttribute(attribute, referencePages),
|
||||
);
|
||||
} else if (attribute?.data?.entityType === AttributeEntityTypeEnum.PRODUCT) {
|
||||
return mapNodeToChoice(
|
||||
getSelectedReferencesFromAttribute(attribute, referenceProducts)
|
||||
getSelectedReferencesFromAttribute(attribute, referenceProducts),
|
||||
);
|
||||
}
|
||||
return [];
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import {
|
||||
createAttributeMultiChangeHandler,
|
||||
prepareAttributesInput
|
||||
prepareAttributesInput,
|
||||
} from "@saleor/attributes/utils/handlers";
|
||||
import {
|
||||
AttributeInput,
|
||||
AttributeInputData
|
||||
AttributeInputData,
|
||||
} from "@saleor/components/Attributes";
|
||||
import {
|
||||
AttributeInputTypeEnum,
|
||||
AttributeValueDetailsFragment
|
||||
AttributeValueDetailsFragment,
|
||||
} from "@saleor/graphql";
|
||||
import { FormsetData } from "@saleor/hooks/useFormset";
|
||||
|
||||
|
@ -29,13 +29,13 @@ const multipleValueAttributes: FormsetData<AttributeInputData, string[]> = [
|
|||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null,
|
||||
value: null
|
||||
}
|
||||
]
|
||||
value: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
id: "attr-1",
|
||||
label: "Attribute 1",
|
||||
value: []
|
||||
value: [],
|
||||
},
|
||||
{
|
||||
data: {
|
||||
|
@ -53,7 +53,7 @@ const multipleValueAttributes: FormsetData<AttributeInputData, string[]> = [
|
|||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null,
|
||||
value: null
|
||||
value: null,
|
||||
},
|
||||
{
|
||||
__typename: "AttributeValue",
|
||||
|
@ -66,7 +66,7 @@ const multipleValueAttributes: FormsetData<AttributeInputData, string[]> = [
|
|||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null,
|
||||
value: null
|
||||
value: null,
|
||||
},
|
||||
{
|
||||
__typename: "AttributeValue",
|
||||
|
@ -79,13 +79,13 @@ const multipleValueAttributes: FormsetData<AttributeInputData, string[]> = [
|
|||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null,
|
||||
value: null
|
||||
}
|
||||
]
|
||||
value: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
id: "attr-2",
|
||||
label: "Attribute 2",
|
||||
value: ["attr-2-v-3"]
|
||||
value: ["attr-2-v-3"],
|
||||
},
|
||||
{
|
||||
data: {
|
||||
|
@ -97,7 +97,7 @@ const multipleValueAttributes: FormsetData<AttributeInputData, string[]> = [
|
|||
file: {
|
||||
__typename: "File",
|
||||
contentType: "image/png",
|
||||
url: "some-non-existing-url"
|
||||
url: "some-non-existing-url",
|
||||
},
|
||||
id: "gdghdgdhkkdae",
|
||||
name: "File First Value",
|
||||
|
@ -107,14 +107,14 @@ const multipleValueAttributes: FormsetData<AttributeInputData, string[]> = [
|
|||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null,
|
||||
value: null
|
||||
}
|
||||
]
|
||||
value: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
id: "ifudbgidfsb",
|
||||
label: "File Attribute",
|
||||
value: []
|
||||
}
|
||||
value: [],
|
||||
},
|
||||
];
|
||||
|
||||
const ATTR_ID = "123" as const;
|
||||
|
@ -128,7 +128,7 @@ interface CreateAttribute {
|
|||
|
||||
const createAttribute = ({
|
||||
inputType,
|
||||
value
|
||||
value,
|
||||
}: CreateAttribute): AttributeInput => ({
|
||||
data: {
|
||||
entityType: null,
|
||||
|
@ -137,29 +137,29 @@ const createAttribute = ({
|
|||
// those values don't matter
|
||||
selectedValues: [],
|
||||
values: [],
|
||||
unit: null
|
||||
unit: null,
|
||||
},
|
||||
id: ATTR_ID,
|
||||
label: "MyAttribute",
|
||||
value: value !== null ? [value] : []
|
||||
value: value !== null ? [value] : [],
|
||||
});
|
||||
|
||||
const createSelectAttribute = (value: string) =>
|
||||
createAttribute({
|
||||
inputType: AttributeInputTypeEnum.DROPDOWN,
|
||||
value
|
||||
value,
|
||||
});
|
||||
|
||||
const createReferenceAttribute = (value: string) =>
|
||||
createAttribute({
|
||||
inputType: AttributeInputTypeEnum.REFERENCE,
|
||||
value
|
||||
value,
|
||||
});
|
||||
|
||||
const createBooleanAttribute = (value: string) =>
|
||||
createAttribute({
|
||||
inputType: AttributeInputTypeEnum.BOOLEAN,
|
||||
value
|
||||
value,
|
||||
});
|
||||
|
||||
const createRichTextAttribute = (value: string) =>
|
||||
|
@ -187,7 +187,7 @@ describe("Multiple select change handler", () => {
|
|||
const handler = createAttributeMultiChangeHandler(
|
||||
change,
|
||||
multipleValueAttributes,
|
||||
trigger
|
||||
trigger,
|
||||
);
|
||||
|
||||
handler("attr-2", "attr-2-v-1");
|
||||
|
@ -206,7 +206,7 @@ describe("Multiple select change handler", () => {
|
|||
const handler = createAttributeMultiChangeHandler(
|
||||
change,
|
||||
multipleValueAttributes,
|
||||
trigger
|
||||
trigger,
|
||||
);
|
||||
|
||||
handler("attr-2", "attr-2-v-3");
|
||||
|
@ -223,7 +223,7 @@ describe("Multiple select change handler", () => {
|
|||
const handler = createAttributeMultiChangeHandler(
|
||||
change,
|
||||
multipleValueAttributes,
|
||||
trigger
|
||||
trigger,
|
||||
);
|
||||
|
||||
handler("attr-2", "A Value");
|
||||
|
@ -255,13 +255,13 @@ describe("Sending only changed attributes", () => {
|
|||
const result = prepareAttributesInput({
|
||||
attributes: [attribute],
|
||||
prevAttributes: [prevAttribute],
|
||||
updatedFileAttributes: []
|
||||
updatedFileAttributes: [],
|
||||
});
|
||||
|
||||
const expectedResult =
|
||||
expected !== null ? [{ id: ATTR_ID, references: expected }] : [];
|
||||
expect(result).toEqual(expectedResult);
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
describe("works with select attributes", () => {
|
||||
|
@ -280,13 +280,13 @@ describe("Sending only changed attributes", () => {
|
|||
const result = prepareAttributesInput({
|
||||
attributes: [attribute],
|
||||
prevAttributes: [prevAttribute],
|
||||
updatedFileAttributes: []
|
||||
updatedFileAttributes: [],
|
||||
});
|
||||
|
||||
const expectedResult =
|
||||
expected !== null ? [{ id: ATTR_ID, values: expected }] : [];
|
||||
expect(result).toEqual(expectedResult);
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
describe("works with boolean attributes", () => {
|
||||
|
@ -308,13 +308,13 @@ describe("Sending only changed attributes", () => {
|
|||
const result = prepareAttributesInput({
|
||||
attributes: [attribute],
|
||||
prevAttributes: [prevAttribute],
|
||||
updatedFileAttributes: []
|
||||
updatedFileAttributes: [],
|
||||
});
|
||||
|
||||
const expectedResult =
|
||||
expected !== null ? [{ id: ATTR_ID, boolean: expected }] : [];
|
||||
expect(result).toEqual(expectedResult);
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
describe("works with rich text attributes", () => {
|
||||
|
@ -333,13 +333,13 @@ describe("Sending only changed attributes", () => {
|
|||
const result = prepareAttributesInput({
|
||||
attributes: [attribute],
|
||||
prevAttributes: [prevAttribute],
|
||||
updatedFileAttributes: []
|
||||
updatedFileAttributes: [],
|
||||
});
|
||||
|
||||
const expectedResult =
|
||||
expected !== null ? [{ id: ATTR_ID, richText: expected }] : [];
|
||||
expect(result).toEqual(expectedResult);
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
describe("works with date attributes", () => {
|
||||
|
@ -358,13 +358,13 @@ describe("Sending only changed attributes", () => {
|
|||
const result = prepareAttributesInput({
|
||||
attributes: [attribute],
|
||||
prevAttributes: [prevAttribute],
|
||||
updatedFileAttributes: []
|
||||
updatedFileAttributes: [],
|
||||
});
|
||||
|
||||
const expectedResult =
|
||||
expected !== null ? [{ id: ATTR_ID, date: expected }] : [];
|
||||
expect(result).toEqual(expectedResult);
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
describe("works with date time attributes", () => {
|
||||
|
@ -384,13 +384,13 @@ describe("Sending only changed attributes", () => {
|
|||
const result = prepareAttributesInput({
|
||||
attributes: [attribute],
|
||||
prevAttributes: [prevAttribute],
|
||||
updatedFileAttributes: []
|
||||
updatedFileAttributes: [],
|
||||
});
|
||||
|
||||
const expectedResult =
|
||||
expected !== null ? [{ id: ATTR_ID, dateTime: expected }] : [];
|
||||
expect(result).toEqual(expectedResult);
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
describe("works with swatch attributes", () => {
|
||||
|
@ -409,13 +409,13 @@ describe("Sending only changed attributes", () => {
|
|||
const result = prepareAttributesInput({
|
||||
attributes: [attribute],
|
||||
prevAttributes: [prevAttribute],
|
||||
updatedFileAttributes: []
|
||||
updatedFileAttributes: [],
|
||||
});
|
||||
|
||||
const expectedResult =
|
||||
expected !== null ? [{ id: ATTR_ID, values: expected }] : [];
|
||||
expect(result).toEqual(expectedResult);
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
describe("works with numeric attributes", () => {
|
||||
|
@ -434,13 +434,13 @@ describe("Sending only changed attributes", () => {
|
|||
const result = prepareAttributesInput({
|
||||
attributes: [attribute],
|
||||
prevAttributes: [prevAttribute],
|
||||
updatedFileAttributes: []
|
||||
updatedFileAttributes: [],
|
||||
});
|
||||
|
||||
const expectedResult =
|
||||
expected !== null ? [{ id: ATTR_ID, values: expected }] : [];
|
||||
expect(result).toEqual(expectedResult);
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
describe("works with file attributes", () => {
|
||||
|
@ -452,8 +452,8 @@ describe("Sending only changed attributes", () => {
|
|||
attributes: [attribute],
|
||||
prevAttributes: [prevAttribute],
|
||||
updatedFileAttributes: [
|
||||
{ file: undefined, id: ATTR_ID, contentType: undefined, values: [] }
|
||||
]
|
||||
{ file: undefined, id: ATTR_ID, contentType: undefined, values: [] },
|
||||
],
|
||||
});
|
||||
|
||||
// Files are deleted by using AttributeValueDetele mutation
|
||||
|
@ -472,17 +472,17 @@ describe("Sending only changed attributes", () => {
|
|||
file: uploadUrl,
|
||||
id: ATTR_ID,
|
||||
contentType: "image/jpeg",
|
||||
values: []
|
||||
}
|
||||
]
|
||||
values: [],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
expect(result).toEqual([
|
||||
{
|
||||
id: ATTR_ID,
|
||||
file: uploadUrl,
|
||||
contentType: "image/jpeg"
|
||||
}
|
||||
contentType: "image/jpeg",
|
||||
},
|
||||
]);
|
||||
});
|
||||
it("replaces existing image (bob.jpg -> juice.png)", () => {
|
||||
|
@ -498,17 +498,17 @@ describe("Sending only changed attributes", () => {
|
|||
file: uploadUrl,
|
||||
id: ATTR_ID,
|
||||
contentType: "image/png",
|
||||
values: []
|
||||
}
|
||||
]
|
||||
values: [],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
expect(result).toEqual([
|
||||
{
|
||||
id: ATTR_ID,
|
||||
file: uploadUrl,
|
||||
contentType: "image/png"
|
||||
}
|
||||
contentType: "image/png",
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { FetchResult } from "@apollo/client";
|
||||
import {
|
||||
AttributeInput,
|
||||
AttributeInputData
|
||||
AttributeInputData,
|
||||
} from "@saleor/components/Attributes";
|
||||
import {
|
||||
AttributeEntityTypeEnum,
|
||||
|
@ -13,12 +13,12 @@ import {
|
|||
FileUploadMutationVariables,
|
||||
PageSelectedAttributeFragment,
|
||||
ProductFragment,
|
||||
ProductVariantDetailsQuery
|
||||
ProductVariantDetailsQuery,
|
||||
} from "@saleor/graphql";
|
||||
import {
|
||||
FormsetAtomicData,
|
||||
FormsetChange,
|
||||
FormsetData
|
||||
FormsetData,
|
||||
} from "@saleor/hooks/useFormset";
|
||||
import { FetchMoreProps, ReorderEvent } from "@saleor/types";
|
||||
import { move, toggle } from "@saleor/utils/lists";
|
||||
|
@ -28,7 +28,7 @@ import { getFileValuesToUploadFromAttributes, isFileValueUnused } from "./data";
|
|||
|
||||
export function createAttributeChangeHandler(
|
||||
changeAttributeData: FormsetChange<string[]>,
|
||||
triggerChange: () => void
|
||||
triggerChange: () => void,
|
||||
): FormsetChange<string> {
|
||||
return (attributeId: string, value: string) => {
|
||||
triggerChange();
|
||||
|
@ -39,17 +39,17 @@ export function createAttributeChangeHandler(
|
|||
export function createAttributeMultiChangeHandler(
|
||||
changeAttributeData: FormsetChange<string[]>,
|
||||
attributes: FormsetData<AttributeInputData, string[]>,
|
||||
triggerChange: () => void
|
||||
triggerChange: () => void,
|
||||
): FormsetChange<string> {
|
||||
return (attributeId: string, value: string) => {
|
||||
const attribute = attributes.find(
|
||||
attribute => attribute.id === attributeId
|
||||
attribute => attribute.id === attributeId,
|
||||
);
|
||||
|
||||
const newAttributeValues = toggle(
|
||||
value,
|
||||
attribute.value,
|
||||
(a, b) => a === b
|
||||
(a, b) => a === b,
|
||||
);
|
||||
|
||||
triggerChange();
|
||||
|
@ -59,7 +59,7 @@ export function createAttributeMultiChangeHandler(
|
|||
|
||||
export function createAttributeReferenceChangeHandler(
|
||||
changeAttributeData: FormsetChange<string[]>,
|
||||
triggerChange: () => void
|
||||
triggerChange: () => void,
|
||||
): FormsetChange<string[]> {
|
||||
return (attributeId: string, values: string[]) => {
|
||||
changeAttributeData(attributeId, values);
|
||||
|
@ -71,11 +71,11 @@ export function createFetchReferencesHandler(
|
|||
attributes: FormsetData<AttributeInputData, string[]>,
|
||||
assignReferencesAttributeId: string,
|
||||
fetchReferencePages?: (data: string) => void,
|
||||
fetchReferenceProducts?: (data: string) => void
|
||||
fetchReferenceProducts?: (data: string) => void,
|
||||
) {
|
||||
return (value: string) => {
|
||||
const attribute = attributes?.find(
|
||||
attribute => attribute.id === assignReferencesAttributeId
|
||||
attribute => attribute.id === assignReferencesAttributeId,
|
||||
);
|
||||
|
||||
if (!attribute) {
|
||||
|
@ -100,10 +100,10 @@ export function createFetchMoreReferencesHandler(
|
|||
attributes: FormsetData<AttributeInputData, string[]>,
|
||||
assignReferencesAttributeId: string,
|
||||
fetchMoreReferencePages?: FetchMoreProps,
|
||||
fetchMoreReferenceProducts?: FetchMoreProps
|
||||
fetchMoreReferenceProducts?: FetchMoreProps,
|
||||
) {
|
||||
const attribute = attributes?.find(
|
||||
attribute => attribute.id === assignReferencesAttributeId
|
||||
attribute => attribute.id === assignReferencesAttributeId,
|
||||
);
|
||||
|
||||
if (!attribute) {
|
||||
|
@ -122,13 +122,13 @@ export function createAttributeFileChangeHandler(
|
|||
attributesWithNewFileValue: FormsetData<FormsetData<null, File>>,
|
||||
addAttributeNewFileValue: (data: FormsetAtomicData<null, File>) => void,
|
||||
changeAttributeNewFileValue: FormsetChange<File>,
|
||||
triggerChange: () => void
|
||||
triggerChange: () => void,
|
||||
): FormsetChange<File> {
|
||||
return (attributeId: string, value: File) => {
|
||||
triggerChange();
|
||||
|
||||
const newFileValueAssigned = attributesWithNewFileValue.find(
|
||||
attribute => attribute.id === attributeId
|
||||
attribute => attribute.id === attributeId,
|
||||
);
|
||||
|
||||
if (newFileValueAssigned) {
|
||||
|
@ -138,7 +138,7 @@ export function createAttributeFileChangeHandler(
|
|||
data: null,
|
||||
id: attributeId,
|
||||
label: null,
|
||||
value
|
||||
value,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -149,20 +149,20 @@ export function createAttributeFileChangeHandler(
|
|||
export function createAttributeValueReorderHandler(
|
||||
changeAttributeData: FormsetChange<string[]>,
|
||||
attributes: FormsetData<AttributeInputData, string[]>,
|
||||
triggerChange: () => void
|
||||
triggerChange: () => void,
|
||||
): FormsetChange<ReorderEvent> {
|
||||
return (attributeId: string, reorder: ReorderEvent) => {
|
||||
triggerChange();
|
||||
|
||||
const attribute = attributes.find(
|
||||
attribute => attribute.id === attributeId
|
||||
attribute => attribute.id === attributeId,
|
||||
);
|
||||
|
||||
const reorderedValues = move(
|
||||
attribute.value[reorder.oldIndex],
|
||||
attribute.value,
|
||||
(a, b) => a === b,
|
||||
reorder.newIndex
|
||||
reorder.newIndex,
|
||||
);
|
||||
|
||||
changeAttributeData(attributeId, reorderedValues);
|
||||
|
@ -171,37 +171,37 @@ export function createAttributeValueReorderHandler(
|
|||
|
||||
function getFileInput(
|
||||
attribute: AttributeInput,
|
||||
updatedFileAttributes: AttributeValueInput[]
|
||||
updatedFileAttributes: AttributeValueInput[],
|
||||
) {
|
||||
const updatedFileAttribute = updatedFileAttributes.find(
|
||||
attributeWithNewFile => attribute.id === attributeWithNewFile.id
|
||||
attributeWithNewFile => attribute.id === attributeWithNewFile.id,
|
||||
);
|
||||
|
||||
if (updatedFileAttribute) {
|
||||
return {
|
||||
file: updatedFileAttribute.file,
|
||||
id: updatedFileAttribute.id,
|
||||
contentType: updatedFileAttribute.contentType
|
||||
contentType: updatedFileAttribute.contentType,
|
||||
};
|
||||
}
|
||||
return {
|
||||
file: attribute.data.selectedValues?.[0]?.file?.url,
|
||||
contentType: attribute.data.selectedValues?.[0]?.file.contentType,
|
||||
id: attribute.id
|
||||
id: attribute.id,
|
||||
};
|
||||
}
|
||||
|
||||
function getBooleanInput(attribute: AttributeInput) {
|
||||
return {
|
||||
id: attribute.id,
|
||||
boolean: JSON.parse(attribute.value[0] ?? "false")
|
||||
boolean: JSON.parse(attribute.value[0] ?? "false"),
|
||||
};
|
||||
}
|
||||
|
||||
function getAttributesMap(attributes: AttributeInput[] | null) {
|
||||
if (attributes && attributes?.length !== 0) {
|
||||
return new Map(
|
||||
attributes.map(attribute => [attribute.id, attribute.value])
|
||||
attributes.map(attribute => [attribute.id, attribute.value]),
|
||||
);
|
||||
}
|
||||
return new Map();
|
||||
|
@ -216,7 +216,7 @@ interface AttributesArgs {
|
|||
export const prepareAttributesInput = ({
|
||||
attributes,
|
||||
prevAttributes,
|
||||
updatedFileAttributes
|
||||
updatedFileAttributes,
|
||||
}: AttributesArgs): AttributeValueInput[] => {
|
||||
const prevAttributesMap = getAttributesMap(prevAttributes);
|
||||
|
||||
|
@ -247,7 +247,7 @@ export const prepareAttributesInput = ({
|
|||
if (inputType === AttributeInputTypeEnum.RICH_TEXT) {
|
||||
attrInput.push({
|
||||
id: attr.id,
|
||||
richText: attr.value[0]
|
||||
richText: attr.value[0],
|
||||
});
|
||||
return attrInput;
|
||||
}
|
||||
|
@ -255,28 +255,28 @@ export const prepareAttributesInput = ({
|
|||
if (inputType === AttributeInputTypeEnum.REFERENCE) {
|
||||
attrInput.push({
|
||||
id: attr.id,
|
||||
references: attr.value
|
||||
references: attr.value,
|
||||
});
|
||||
return attrInput;
|
||||
}
|
||||
if (inputType === AttributeInputTypeEnum.DATE) {
|
||||
attrInput.push({
|
||||
id: attr.id,
|
||||
date: attr.value[0]
|
||||
date: attr.value[0],
|
||||
});
|
||||
return attrInput;
|
||||
}
|
||||
if (inputType === AttributeInputTypeEnum.DATE_TIME) {
|
||||
attrInput.push({
|
||||
id: attr.id,
|
||||
dateTime: attr.value[0]
|
||||
dateTime: attr.value[0],
|
||||
});
|
||||
return attrInput;
|
||||
}
|
||||
|
||||
attrInput.push({
|
||||
id: attr.id,
|
||||
values: attr.value
|
||||
values: attr.value,
|
||||
});
|
||||
|
||||
return attrInput;
|
||||
|
@ -286,16 +286,16 @@ export const prepareAttributesInput = ({
|
|||
export const handleUploadMultipleFiles = async (
|
||||
attributesWithNewFileValue: FormsetData<null, File>,
|
||||
uploadFile: (
|
||||
variables: FileUploadMutationVariables
|
||||
) => Promise<FetchResult<FileUploadMutation>>
|
||||
variables: FileUploadMutationVariables,
|
||||
) => Promise<FetchResult<FileUploadMutation>>,
|
||||
) =>
|
||||
Promise.all(
|
||||
getFileValuesToUploadFromAttributes(attributesWithNewFileValue).map(
|
||||
fileAttribute =>
|
||||
uploadFile({
|
||||
file: fileAttribute.value
|
||||
})
|
||||
)
|
||||
file: fileAttribute.value,
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
export const handleDeleteMultipleAttributeValues = async (
|
||||
|
@ -306,21 +306,21 @@ export const handleDeleteMultipleAttributeValues = async (
|
|||
| ProductVariantDetailsQuery["productVariant"]["nonSelectionAttributes"][0]
|
||||
>,
|
||||
deleteAttributeValue: (
|
||||
variables: AttributeValueDeleteMutationVariables
|
||||
) => Promise<FetchResult<AttributeValueDeleteMutation>>
|
||||
variables: AttributeValueDeleteMutationVariables,
|
||||
) => Promise<FetchResult<AttributeValueDeleteMutation>>,
|
||||
) =>
|
||||
Promise.all(
|
||||
attributes.map(existingAttribute => {
|
||||
const fileValueUnused = isFileValueUnused(
|
||||
attributesWithNewFileValue,
|
||||
existingAttribute
|
||||
existingAttribute,
|
||||
);
|
||||
|
||||
if (fileValueUnused) {
|
||||
return deleteAttributeValue({
|
||||
id: existingAttribute.values[0].id,
|
||||
firstValues: 20
|
||||
firstValues: 20,
|
||||
});
|
||||
}
|
||||
})
|
||||
}),
|
||||
);
|
||||
|
|
|
@ -3,7 +3,7 @@ import {
|
|||
AttributeErrorFragment,
|
||||
useAttributeCreateMutation,
|
||||
useUpdateMetadataMutation,
|
||||
useUpdatePrivateMetadataMutation
|
||||
useUpdatePrivateMetadataMutation,
|
||||
} from "@saleor/graphql";
|
||||
import useListSettings from "@saleor/hooks/useListSettings";
|
||||
import useLocalPageInfo, { getMaxPage } from "@saleor/hooks/useLocalPageInfo";
|
||||
|
@ -18,14 +18,14 @@ import {
|
|||
isSelected,
|
||||
move,
|
||||
remove,
|
||||
updateAtIndex
|
||||
updateAtIndex,
|
||||
} from "@saleor/utils/lists";
|
||||
import React from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
import slugify from "slugify";
|
||||
|
||||
import AttributePage, {
|
||||
AttributePageFormData
|
||||
AttributePageFormData,
|
||||
} from "../../components/AttributePage";
|
||||
import AttributeValueDeleteDialog from "../../components/AttributeValueDeleteDialog";
|
||||
import AttributeValueEditDialog from "../../components/AttributeValueEditDialog";
|
||||
|
@ -33,11 +33,11 @@ import {
|
|||
attributeAddUrl,
|
||||
AttributeAddUrlDialog,
|
||||
AttributeAddUrlQueryParams,
|
||||
attributeUrl
|
||||
attributeUrl,
|
||||
} from "../../urls";
|
||||
import {
|
||||
AttributeValueEditDialogFormData,
|
||||
getAttributeData
|
||||
getAttributeData,
|
||||
} from "../../utils/data";
|
||||
|
||||
interface AttributeDetailsProps {
|
||||
|
@ -48,12 +48,12 @@ const attributeValueAlreadyExistsError: AttributeErrorFragment = {
|
|||
__typename: "AttributeError",
|
||||
code: AttributeErrorCode.ALREADY_EXISTS,
|
||||
field: "name",
|
||||
message: ""
|
||||
message: "",
|
||||
};
|
||||
|
||||
function areValuesEqual(
|
||||
a: AttributeValueEditDialogFormData,
|
||||
b: AttributeValueEditDialogFormData
|
||||
b: AttributeValueEditDialogFormData,
|
||||
) {
|
||||
return a.name === b.name;
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = ({ params }) => {
|
|||
>([]);
|
||||
|
||||
const { updateListSettings, settings } = useListSettings(
|
||||
ListViews.ATTRIBUTE_VALUE_LIST
|
||||
ListViews.ATTRIBUTE_VALUE_LIST,
|
||||
);
|
||||
|
||||
const {
|
||||
|
@ -79,7 +79,7 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = ({ params }) => {
|
|||
pageValues,
|
||||
loadNextPage,
|
||||
loadPreviousPage,
|
||||
loadPage
|
||||
loadPage,
|
||||
} = useLocalPageInfo(values, settings?.rowNumber);
|
||||
|
||||
const [attributeCreate, attributeCreateOpts] = useAttributeCreateMutation({
|
||||
|
@ -89,12 +89,12 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = ({ params }) => {
|
|||
status: "success",
|
||||
text: intl.formatMessage({
|
||||
id: "jTifz+",
|
||||
defaultMessage: "Successfully created attribute"
|
||||
})
|
||||
defaultMessage: "Successfully created attribute",
|
||||
}),
|
||||
});
|
||||
navigate(attributeUrl(data.attributeCreate.attribute.id));
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
const [updateMetadata] = useUpdateMetadataMutation({});
|
||||
const [updatePrivateMetadata] = useUpdatePrivateMetadataMutation({});
|
||||
|
@ -150,27 +150,27 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = ({ params }) => {
|
|||
values[pageInfo.startCursor + oldIndex],
|
||||
values,
|
||||
areValuesEqual,
|
||||
pageInfo.startCursor + newIndex
|
||||
)
|
||||
pageInfo.startCursor + newIndex,
|
||||
),
|
||||
);
|
||||
|
||||
const handleCreate = async (data: AttributePageFormData) => {
|
||||
const result = await attributeCreate({
|
||||
variables: {
|
||||
input: getAttributeData(data, values)
|
||||
}
|
||||
input: getAttributeData(data, values),
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
id: result.data.attributeCreate?.attribute?.id || null,
|
||||
errors: getMutationErrors(result)
|
||||
errors: getMutationErrors(result),
|
||||
};
|
||||
};
|
||||
|
||||
const handleSubmit = createMetadataCreateHandler(
|
||||
handleCreate,
|
||||
updateMetadata,
|
||||
updatePrivateMetadata
|
||||
updatePrivateMetadata,
|
||||
);
|
||||
|
||||
return (
|
||||
|
@ -183,13 +183,13 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = ({ params }) => {
|
|||
onValueAdd={() => openModal("add-value")}
|
||||
onValueDelete={id =>
|
||||
openModal("remove-value", {
|
||||
id
|
||||
id,
|
||||
})
|
||||
}
|
||||
onValueReorder={handleValueReorder}
|
||||
onValueUpdate={id =>
|
||||
openModal("edit-value", {
|
||||
id
|
||||
id,
|
||||
})
|
||||
}
|
||||
saveButtonBarState={attributeCreateOpts.status}
|
||||
|
@ -200,7 +200,7 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = ({ params }) => {
|
|||
endCursor: "",
|
||||
hasNextPage: false,
|
||||
hasPreviousPage: false,
|
||||
startCursor: ""
|
||||
startCursor: "",
|
||||
},
|
||||
edges: pageValues.map((value, valueIndex) => ({
|
||||
__typename: "AttributeValueCountableEdge" as "AttributeValueCountableEdge",
|
||||
|
@ -211,7 +211,7 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = ({ params }) => {
|
|||
? {
|
||||
url: value.fileUrl,
|
||||
contentType: value.contentType,
|
||||
__typename: "File"
|
||||
__typename: "File",
|
||||
}
|
||||
: null,
|
||||
id: valueIndex.toString(),
|
||||
|
@ -223,9 +223,9 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = ({ params }) => {
|
|||
boolean: null,
|
||||
date: null,
|
||||
dateTime: null,
|
||||
...value
|
||||
}
|
||||
}))
|
||||
...value,
|
||||
},
|
||||
})),
|
||||
}}
|
||||
settings={settings}
|
||||
onUpdateListSettings={updateListSettings}
|
||||
|
|
|
@ -8,11 +8,11 @@ import {
|
|||
useAttributeValueReorderMutation,
|
||||
useAttributeValueUpdateMutation,
|
||||
useUpdateMetadataMutation,
|
||||
useUpdatePrivateMetadataMutation
|
||||
useUpdatePrivateMetadataMutation,
|
||||
} from "@saleor/graphql";
|
||||
import useListSettings from "@saleor/hooks/useListSettings";
|
||||
import useLocalPaginator, {
|
||||
useLocalPaginationState
|
||||
useLocalPaginationState,
|
||||
} from "@saleor/hooks/useLocalPaginator";
|
||||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
import useNotifier from "@saleor/hooks/useNotifier";
|
||||
|
@ -29,7 +29,7 @@ import { useIntl } from "react-intl";
|
|||
|
||||
import AttributeDeleteDialog from "../../components/AttributeDeleteDialog";
|
||||
import AttributePage, {
|
||||
AttributePageFormData
|
||||
AttributePageFormData,
|
||||
} from "../../components/AttributePage";
|
||||
import AttributeValueDeleteDialog from "../../components/AttributeValueDeleteDialog";
|
||||
import AttributeValueEditDialog from "../../components/AttributeValueEditDialog";
|
||||
|
@ -37,7 +37,7 @@ import {
|
|||
attributeListUrl,
|
||||
attributeUrl,
|
||||
AttributeUrlDialog,
|
||||
AttributeUrlQueryParams
|
||||
AttributeUrlQueryParams,
|
||||
} from "../../urls";
|
||||
|
||||
interface AttributeDetailsProps {
|
||||
|
@ -58,12 +58,12 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = ({ id, params }) => {
|
|||
>(navigate, params => attributeUrl(id, params), params);
|
||||
|
||||
const { updateListSettings, settings } = useListSettings(
|
||||
ListViews.ATTRIBUTE_VALUE_LIST
|
||||
ListViews.ATTRIBUTE_VALUE_LIST,
|
||||
);
|
||||
|
||||
const [
|
||||
valuesPaginationState,
|
||||
setValuesPaginationState
|
||||
setValuesPaginationState,
|
||||
] = useLocalPaginationState(settings?.rowNumber);
|
||||
|
||||
const { data, loading } = useAttributeDetailsQuery({
|
||||
|
@ -72,21 +72,21 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = ({ id, params }) => {
|
|||
firstValues: valuesPaginationState.first,
|
||||
lastValues: valuesPaginationState.last,
|
||||
afterValues: valuesPaginationState.after,
|
||||
beforeValues: valuesPaginationState.before
|
||||
beforeValues: valuesPaginationState.before,
|
||||
},
|
||||
skip: !settings
|
||||
skip: !settings,
|
||||
});
|
||||
|
||||
const paginateValues = useLocalPaginator(setValuesPaginationState);
|
||||
const { loadNextPage, loadPreviousPage, pageInfo } = paginateValues(
|
||||
data?.attribute?.choices?.pageInfo,
|
||||
valuesPaginationState
|
||||
valuesPaginationState,
|
||||
);
|
||||
|
||||
const notifySaved = () =>
|
||||
notify({
|
||||
status: "success",
|
||||
text: intl.formatMessage(commonMessages.savedChanges)
|
||||
text: intl.formatMessage(commonMessages.savedChanges),
|
||||
});
|
||||
|
||||
const [attributeDelete, attributeDeleteOpts] = useAttributeDeleteMutation({
|
||||
|
@ -96,17 +96,17 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = ({ id, params }) => {
|
|||
status: "success",
|
||||
text: intl.formatMessage({
|
||||
id: "V/VAHG",
|
||||
defaultMessage: "Attribute deleted"
|
||||
})
|
||||
defaultMessage: "Attribute deleted",
|
||||
}),
|
||||
});
|
||||
navigate(attributeListUrl());
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const [
|
||||
attributeValueDelete,
|
||||
attributeValueDeleteOpts
|
||||
attributeValueDeleteOpts,
|
||||
] = useAttributeValueDeleteMutation({
|
||||
onCompleted: data => {
|
||||
if (data?.attributeValueDelete.errors.length === 0) {
|
||||
|
@ -115,24 +115,24 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = ({ id, params }) => {
|
|||
text: intl.formatMessage({
|
||||
id: "7H2D5m",
|
||||
defaultMessage: "Value deleted",
|
||||
description: "attribute value deleted"
|
||||
})
|
||||
description: "attribute value deleted",
|
||||
}),
|
||||
});
|
||||
closeModal();
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const [
|
||||
attributeValueUpdate,
|
||||
attributeValueUpdateOpts
|
||||
attributeValueUpdateOpts,
|
||||
] = useAttributeValueUpdateMutation({
|
||||
onCompleted: data => {
|
||||
if (data?.attributeValueUpdate.errors.length === 0) {
|
||||
notifySaved();
|
||||
closeModal();
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const [attributeUpdate, attributeUpdateOpts] = useAttributeUpdateMutation({
|
||||
|
@ -140,12 +140,12 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = ({ id, params }) => {
|
|||
if (data?.attributeUpdate.errors.length === 0) {
|
||||
notifySaved();
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const [
|
||||
attributeValueCreate,
|
||||
attributeValueCreateOpts
|
||||
attributeValueCreateOpts,
|
||||
] = useAttributeValueCreateMutation({
|
||||
onCompleted: data => {
|
||||
if (data?.attributeValueCreate.errors.length === 0) {
|
||||
|
@ -154,12 +154,12 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = ({ id, params }) => {
|
|||
text: intl.formatMessage({
|
||||
id: "xVn5B0",
|
||||
defaultMessage: "Added new value",
|
||||
description: "added new attribute value"
|
||||
})
|
||||
description: "added new attribute value",
|
||||
}),
|
||||
});
|
||||
closeModal();
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const [attributeValueReorder] = useAttributeValueReorderMutation({
|
||||
|
@ -169,13 +169,13 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = ({ id, params }) => {
|
|||
status: "error",
|
||||
text: getAttributeErrorMessage(
|
||||
data?.attributeReorderValues.errors[0],
|
||||
intl
|
||||
)
|
||||
intl,
|
||||
),
|
||||
});
|
||||
} else {
|
||||
notifySaved();
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const handleValueReorder = ({ newIndex, oldIndex }: ReorderEvent) =>
|
||||
|
@ -189,30 +189,30 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = ({ id, params }) => {
|
|||
choices: {
|
||||
__typename: "AttributeValueCountableConnection",
|
||||
pageInfo: {
|
||||
...data?.attribute.choices.pageInfo
|
||||
...data?.attribute.choices.pageInfo,
|
||||
},
|
||||
edges: move(
|
||||
data?.attribute.choices.edges[oldIndex],
|
||||
data?.attribute.choices.edges,
|
||||
(a, b) => a.node.id === b.node.id,
|
||||
newIndex
|
||||
)
|
||||
}
|
||||
newIndex,
|
||||
),
|
||||
},
|
||||
},
|
||||
errors: []
|
||||
}
|
||||
errors: [],
|
||||
},
|
||||
},
|
||||
variables: {
|
||||
id,
|
||||
move: {
|
||||
id: data?.attribute.choices.edges[oldIndex].node.id,
|
||||
sortOrder: newIndex - oldIndex
|
||||
sortOrder: newIndex - oldIndex,
|
||||
},
|
||||
firstValues: valuesPaginationState.first,
|
||||
lastValues: valuesPaginationState.last,
|
||||
afterValues: valuesPaginationState.after,
|
||||
beforeValues: valuesPaginationState.before
|
||||
}
|
||||
beforeValues: valuesPaginationState.before,
|
||||
},
|
||||
});
|
||||
|
||||
const handleUpdate = async (data: AttributePageFormData) =>
|
||||
|
@ -225,22 +225,22 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = ({ id, params }) => {
|
|||
"entityType",
|
||||
"inputType",
|
||||
"metadata",
|
||||
"privateMetadata"
|
||||
"privateMetadata",
|
||||
]),
|
||||
storefrontSearchPosition: parseInt(
|
||||
data.storefrontSearchPosition,
|
||||
10
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
10,
|
||||
),
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
const handleSubmit = createMetadataUpdateHandler(
|
||||
data?.attribute,
|
||||
handleUpdate,
|
||||
variables => updateMetadata({ variables }),
|
||||
variables => updatePrivateMetadata({ variables })
|
||||
variables => updatePrivateMetadata({ variables }),
|
||||
);
|
||||
|
||||
return (
|
||||
|
@ -253,13 +253,13 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = ({ id, params }) => {
|
|||
onValueAdd={() => openModal("add-value")}
|
||||
onValueDelete={id =>
|
||||
openModal("remove-value", {
|
||||
id
|
||||
id,
|
||||
})
|
||||
}
|
||||
onValueReorder={handleValueReorder}
|
||||
onValueUpdate={id =>
|
||||
openModal("edit-value", {
|
||||
id
|
||||
id,
|
||||
})
|
||||
}
|
||||
saveButtonBarState={attributeUpdateOpts.status}
|
||||
|
@ -280,8 +280,8 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = ({ id, params }) => {
|
|||
onConfirm={() =>
|
||||
attributeDelete({
|
||||
variables: {
|
||||
id
|
||||
}
|
||||
id,
|
||||
},
|
||||
})
|
||||
}
|
||||
/>
|
||||
|
@ -290,8 +290,8 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = ({ id, params }) => {
|
|||
open={params.action === "remove-value"}
|
||||
name={getStringOrPlaceholder(
|
||||
data?.attribute?.choices?.edges?.find(
|
||||
value => params.id === value.node.id
|
||||
)?.node.name
|
||||
value => params.id === value.node.id,
|
||||
)?.node.name,
|
||||
)}
|
||||
useName={true}
|
||||
confirmButtonState={attributeValueDeleteOpts.status}
|
||||
|
@ -303,8 +303,8 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = ({ id, params }) => {
|
|||
firstValues: valuesPaginationState.first,
|
||||
lastValues: valuesPaginationState.last,
|
||||
afterValues: valuesPaginationState.after,
|
||||
beforeValues: valuesPaginationState.before
|
||||
}
|
||||
beforeValues: valuesPaginationState.before,
|
||||
},
|
||||
})
|
||||
}
|
||||
/>
|
||||
|
@ -326,8 +326,8 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = ({ id, params }) => {
|
|||
firstValues: valuesPaginationState.first,
|
||||
lastValues: valuesPaginationState.last,
|
||||
afterValues: valuesPaginationState.after,
|
||||
beforeValues: valuesPaginationState.before
|
||||
}
|
||||
beforeValues: valuesPaginationState.before,
|
||||
},
|
||||
})
|
||||
}
|
||||
/>
|
||||
|
@ -335,8 +335,8 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = ({ id, params }) => {
|
|||
inputType={attributeFormData.inputType}
|
||||
attributeValue={attributeValueFragmentToFormData(
|
||||
data?.attribute?.choices?.edges?.find(
|
||||
value => params.id === value.node.id
|
||||
)?.node
|
||||
value => params.id === value.node.id,
|
||||
)?.node,
|
||||
)}
|
||||
confirmButtonState={attributeValueUpdateOpts.status}
|
||||
disabled={loading}
|
||||
|
@ -349,14 +349,14 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = ({ id, params }) => {
|
|||
attributeValueUpdate({
|
||||
variables: {
|
||||
id: data?.attribute.choices.edges.find(
|
||||
value => params.id === value.node.id
|
||||
value => params.id === value.node.id,
|
||||
).node.id,
|
||||
input,
|
||||
firstValues: valuesPaginationState.first,
|
||||
lastValues: valuesPaginationState.last,
|
||||
afterValues: valuesPaginationState.after,
|
||||
beforeValues: valuesPaginationState.before
|
||||
}
|
||||
beforeValues: valuesPaginationState.before,
|
||||
},
|
||||
})
|
||||
}
|
||||
/>
|
||||
|
|
|
@ -5,21 +5,21 @@ import {
|
|||
getFiltersCurrentTab,
|
||||
getFilterTabs,
|
||||
getFilterVariables,
|
||||
saveFilterTab
|
||||
saveFilterTab,
|
||||
} from "@saleor/attributes/views/AttributeList/filters";
|
||||
import DeleteFilterTabDialog from "@saleor/components/DeleteFilterTabDialog";
|
||||
import SaveFilterTabDialog, {
|
||||
SaveFilterTabDialogFormData
|
||||
SaveFilterTabDialogFormData,
|
||||
} from "@saleor/components/SaveFilterTabDialog";
|
||||
import {
|
||||
useAttributeBulkDeleteMutation,
|
||||
useAttributeListQuery
|
||||
useAttributeListQuery,
|
||||
} from "@saleor/graphql";
|
||||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
import useNotifier from "@saleor/hooks/useNotifier";
|
||||
import usePaginator, {
|
||||
createPaginationState,
|
||||
PaginatorContext
|
||||
PaginatorContext,
|
||||
} from "@saleor/hooks/usePaginator";
|
||||
import { DeleteIcon, IconButton } from "@saleor/macaw-ui";
|
||||
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
||||
|
@ -38,7 +38,7 @@ import AttributeListPage from "../../components/AttributeListPage";
|
|||
import {
|
||||
attributeListUrl,
|
||||
AttributeListUrlDialog,
|
||||
AttributeListUrlQueryParams
|
||||
AttributeListUrlQueryParams,
|
||||
} from "../../urls";
|
||||
import { getFilterQueryParam } from "./filters";
|
||||
import { getSortQueryVariables } from "./sort";
|
||||
|
@ -51,7 +51,7 @@ const AttributeList: React.FC<AttributeListProps> = ({ params }) => {
|
|||
const navigate = useNavigator();
|
||||
const notify = useNotifier();
|
||||
const { isSelected, listElements, reset, toggle, toggleAll } = useBulkActions(
|
||||
params.ids
|
||||
params.ids,
|
||||
);
|
||||
const intl = useIntl();
|
||||
|
||||
|
@ -60,17 +60,17 @@ const AttributeList: React.FC<AttributeListProps> = ({ params }) => {
|
|||
() => ({
|
||||
...paginationState,
|
||||
filter: getFilterVariables(params),
|
||||
sort: getSortQueryVariables(params)
|
||||
sort: getSortQueryVariables(params),
|
||||
}),
|
||||
[params]
|
||||
[params],
|
||||
);
|
||||
const { data, loading, refetch } = useAttributeListQuery({
|
||||
variables: queryVariables
|
||||
variables: queryVariables,
|
||||
});
|
||||
|
||||
const [
|
||||
attributeBulkDelete,
|
||||
attributeBulkDeleteOpts
|
||||
attributeBulkDeleteOpts,
|
||||
] = useAttributeBulkDeleteMutation({
|
||||
onCompleted: data => {
|
||||
if (data.attributeBulkDelete.errors.length === 0) {
|
||||
|
@ -80,13 +80,13 @@ const AttributeList: React.FC<AttributeListProps> = ({ params }) => {
|
|||
text: intl.formatMessage({
|
||||
id: "lw9WIk",
|
||||
defaultMessage: "Attributes successfully delete",
|
||||
description: "deleted multiple attributes"
|
||||
})
|
||||
description: "deleted multiple attributes",
|
||||
}),
|
||||
});
|
||||
reset();
|
||||
refetch();
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const tabs = getFilterTabs();
|
||||
|
@ -101,13 +101,13 @@ const AttributeList: React.FC<AttributeListProps> = ({ params }) => {
|
|||
const [
|
||||
changeFilters,
|
||||
resetFilters,
|
||||
handleSearchChange
|
||||
handleSearchChange,
|
||||
] = createFilterHandlers({
|
||||
cleanupFn: reset,
|
||||
createUrl: attributeListUrl,
|
||||
getFilterQueryParam,
|
||||
navigate,
|
||||
params
|
||||
params,
|
||||
});
|
||||
|
||||
const handleTabChange = (tab: number) => {
|
||||
|
@ -115,8 +115,8 @@ const AttributeList: React.FC<AttributeListProps> = ({ params }) => {
|
|||
navigate(
|
||||
attributeListUrl({
|
||||
activeTab: tab.toString(),
|
||||
...getFilterTabs()[tab - 1].data
|
||||
})
|
||||
...getFilterTabs()[tab - 1].data,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -134,7 +134,7 @@ const AttributeList: React.FC<AttributeListProps> = ({ params }) => {
|
|||
const paginationValues = usePaginator({
|
||||
pageInfo: maybe(() => data.attributes.pageInfo),
|
||||
paginationState,
|
||||
queryString: params
|
||||
queryString: params,
|
||||
});
|
||||
|
||||
const handleSort = createSortHandler(navigate, attributeListUrl, params);
|
||||
|
@ -166,7 +166,7 @@ const AttributeList: React.FC<AttributeListProps> = ({ params }) => {
|
|||
color="primary"
|
||||
onClick={() =>
|
||||
openModal("remove", {
|
||||
ids: listElements
|
||||
ids: listElements,
|
||||
})
|
||||
}
|
||||
>
|
||||
|
|
|
@ -18,7 +18,7 @@ describe("Filtering query params", () => {
|
|||
|
||||
it("should not be empty object if params given", () => {
|
||||
const params: AttributeListUrlFilters = {
|
||||
isVariantOnly: true.toString()
|
||||
isVariantOnly: true.toString(),
|
||||
};
|
||||
const filterVariables = getFilterVariables(params);
|
||||
|
||||
|
@ -32,26 +32,26 @@ describe("Filtering URL params", () => {
|
|||
const filters = createFilterStructure(intl, {
|
||||
filterableInStorefront: {
|
||||
active: false,
|
||||
value: true
|
||||
value: true,
|
||||
},
|
||||
isVariantOnly: {
|
||||
active: false,
|
||||
value: true
|
||||
value: true,
|
||||
},
|
||||
valueRequired: {
|
||||
active: false,
|
||||
value: true
|
||||
value: true,
|
||||
},
|
||||
visibleInStorefront: {
|
||||
active: false,
|
||||
value: true
|
||||
}
|
||||
value: true,
|
||||
},
|
||||
});
|
||||
|
||||
it("should be empty if no active filters", () => {
|
||||
const filterQueryParams = getFilterQueryParams(
|
||||
filters,
|
||||
getFilterQueryParam
|
||||
getFilterQueryParam,
|
||||
);
|
||||
|
||||
expect(getExistingKeys(filterQueryParams)).toHaveLength(0);
|
||||
|
@ -60,7 +60,7 @@ describe("Filtering URL params", () => {
|
|||
it("should not be empty if active filters are present", () => {
|
||||
const filterQueryParams = getFilterQueryParams(
|
||||
setFilterOptsStatus(filters, true),
|
||||
getFilterQueryParam
|
||||
getFilterQueryParam,
|
||||
);
|
||||
|
||||
expect(filterQueryParams).toMatchSnapshot();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {
|
||||
AttributeFilterKeys,
|
||||
AttributeListFilterOpts
|
||||
AttributeListFilterOpts,
|
||||
} from "@saleor/attributes/components/AttributeListPage";
|
||||
import { FilterElement } from "@saleor/components/Filter";
|
||||
import { AttributeFilterInput } from "@saleor/graphql";
|
||||
|
@ -9,41 +9,41 @@ import { maybe, parseBoolean } from "@saleor/misc";
|
|||
import {
|
||||
createFilterTabUtils,
|
||||
createFilterUtils,
|
||||
getSingleValueQueryParam
|
||||
getSingleValueQueryParam,
|
||||
} from "../../../utils/filters";
|
||||
import {
|
||||
AttributeListUrlFilters,
|
||||
AttributeListUrlFiltersEnum,
|
||||
AttributeListUrlQueryParams
|
||||
AttributeListUrlQueryParams,
|
||||
} from "../../urls";
|
||||
|
||||
export const ATTRIBUTE_FILTERS_KEY = "attributeFilters";
|
||||
|
||||
export function getFilterOpts(
|
||||
params: AttributeListUrlFilters
|
||||
params: AttributeListUrlFilters,
|
||||
): AttributeListFilterOpts {
|
||||
return {
|
||||
filterableInStorefront: {
|
||||
active: params.filterableInStorefront !== undefined,
|
||||
value: maybe(() => parseBoolean(params.filterableInStorefront, true))
|
||||
value: maybe(() => parseBoolean(params.filterableInStorefront, true)),
|
||||
},
|
||||
isVariantOnly: {
|
||||
active: params.isVariantOnly !== undefined,
|
||||
value: maybe(() => parseBoolean(params.isVariantOnly, true))
|
||||
value: maybe(() => parseBoolean(params.isVariantOnly, true)),
|
||||
},
|
||||
valueRequired: {
|
||||
active: params.valueRequired !== undefined,
|
||||
value: maybe(() => parseBoolean(params.valueRequired, true))
|
||||
value: maybe(() => parseBoolean(params.valueRequired, true)),
|
||||
},
|
||||
visibleInStorefront: {
|
||||
active: params.visibleInStorefront !== undefined,
|
||||
value: maybe(() => parseBoolean(params.visibleInStorefront, true))
|
||||
}
|
||||
value: maybe(() => parseBoolean(params.visibleInStorefront, true)),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function getFilterVariables(
|
||||
params: AttributeListUrlFilters
|
||||
params: AttributeListUrlFilters,
|
||||
): AttributeFilterInput {
|
||||
return {
|
||||
filterableInStorefront:
|
||||
|
@ -62,12 +62,12 @@ export function getFilterVariables(
|
|||
visibleInStorefront:
|
||||
params.visibleInStorefront !== undefined
|
||||
? parseBoolean(params.visibleInStorefront, false)
|
||||
: undefined
|
||||
: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
export function getFilterQueryParam(
|
||||
filter: FilterElement<AttributeFilterKeys>
|
||||
filter: FilterElement<AttributeFilterKeys>,
|
||||
): AttributeListUrlFilters {
|
||||
const { name } = filter;
|
||||
|
||||
|
@ -75,25 +75,25 @@ export function getFilterQueryParam(
|
|||
case AttributeFilterKeys.filterableInStorefront:
|
||||
return getSingleValueQueryParam(
|
||||
filter,
|
||||
AttributeListUrlFiltersEnum.filterableInStorefront
|
||||
AttributeListUrlFiltersEnum.filterableInStorefront,
|
||||
);
|
||||
|
||||
case AttributeFilterKeys.isVariantOnly:
|
||||
return getSingleValueQueryParam(
|
||||
filter,
|
||||
AttributeListUrlFiltersEnum.isVariantOnly
|
||||
AttributeListUrlFiltersEnum.isVariantOnly,
|
||||
);
|
||||
|
||||
case AttributeFilterKeys.valueRequired:
|
||||
return getSingleValueQueryParam(
|
||||
filter,
|
||||
AttributeListUrlFiltersEnum.valueRequired
|
||||
AttributeListUrlFiltersEnum.valueRequired,
|
||||
);
|
||||
|
||||
case AttributeFilterKeys.visibleInStorefront:
|
||||
return getSingleValueQueryParam(
|
||||
filter,
|
||||
AttributeListUrlFiltersEnum.visibleInStorefront
|
||||
AttributeListUrlFiltersEnum.visibleInStorefront,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -101,13 +101,13 @@ export function getFilterQueryParam(
|
|||
export const {
|
||||
deleteFilterTab,
|
||||
getFilterTabs,
|
||||
saveFilterTab
|
||||
saveFilterTab,
|
||||
} = createFilterTabUtils<AttributeListUrlFilters>(ATTRIBUTE_FILTERS_KEY);
|
||||
|
||||
export const {
|
||||
areFiltersApplied,
|
||||
getActiveFilters,
|
||||
getFiltersCurrentTab
|
||||
getFiltersCurrentTab,
|
||||
} = createFilterUtils<AttributeListUrlQueryParams, AttributeListUrlFilters>(
|
||||
AttributeListUrlFiltersEnum
|
||||
AttributeListUrlFiltersEnum,
|
||||
);
|
||||
|
|
|
@ -3,7 +3,7 @@ import { AttributeSortField } from "@saleor/graphql";
|
|||
import { createGetSortQueryVariables } from "@saleor/utils/sort";
|
||||
|
||||
export function getSortQueryField(
|
||||
sort: AttributeListUrlSortField
|
||||
sort: AttributeListUrlSortField,
|
||||
): AttributeSortField {
|
||||
switch (sort) {
|
||||
case AttributeListUrlSortField.name:
|
||||
|
@ -22,5 +22,5 @@ export function getSortQueryField(
|
|||
}
|
||||
|
||||
export const getSortQueryVariables = createGetSortQueryVariables(
|
||||
getSortQueryField
|
||||
getSortQueryField,
|
||||
);
|
||||
|
|
|
@ -11,12 +11,12 @@ const apolloClient = setupApi();
|
|||
|
||||
function renderAuthProvider() {
|
||||
const intl = {
|
||||
formatMessage: ({ defaultMessage }) => defaultMessage
|
||||
formatMessage: ({ defaultMessage }) => defaultMessage,
|
||||
};
|
||||
const notify = jest.fn();
|
||||
const saleorClient = createSaleorClient({
|
||||
apiUrl: process.env.API_URI,
|
||||
channel: ""
|
||||
channel: "",
|
||||
});
|
||||
const wrapper = ({ children }) => (
|
||||
<IntlProvider defaultLocale="en" locale="en">
|
||||
|
@ -28,7 +28,7 @@ function renderAuthProvider() {
|
|||
|
||||
const { result } = renderHook(
|
||||
() => useAuthProvider({ intl: intl as any, notify, apolloClient }),
|
||||
{ wrapper }
|
||||
{ wrapper },
|
||||
);
|
||||
|
||||
return result;
|
||||
|
@ -37,12 +37,12 @@ function renderAuthProvider() {
|
|||
const adminCredentials = {
|
||||
email: "admin@example.com",
|
||||
password: "admin",
|
||||
token: null
|
||||
token: null,
|
||||
};
|
||||
|
||||
const nonStaffUserCredentials = {
|
||||
email: "client@example.com",
|
||||
password: "password"
|
||||
password: "password",
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
|
@ -57,7 +57,7 @@ xdescribe("User", () => {
|
|||
await act(async () => {
|
||||
const result = await hook.current.login(
|
||||
adminCredentials.email,
|
||||
adminCredentials.password
|
||||
adminCredentials.password,
|
||||
);
|
||||
expect(result.user?.email).toBe(adminCredentials.email);
|
||||
});
|
||||
|
@ -72,7 +72,7 @@ xdescribe("User", () => {
|
|||
await act(async () => {
|
||||
const result = await hook.current.login(
|
||||
adminCredentials.email,
|
||||
"NotAValidPassword123!"
|
||||
"NotAValidPassword123!",
|
||||
);
|
||||
expect(result.user).toBe(null);
|
||||
});
|
||||
|
@ -87,7 +87,7 @@ xdescribe("User", () => {
|
|||
await act(async () => {
|
||||
const result = await hook.current.login(
|
||||
nonStaffUserCredentials.email,
|
||||
nonStaffUserCredentials.password
|
||||
nonStaffUserCredentials.password,
|
||||
);
|
||||
expect(result.user).toBe(null);
|
||||
});
|
||||
|
|
|
@ -9,16 +9,16 @@ const useStyles = makeStyles(
|
|||
theme => ({
|
||||
footer: {
|
||||
position: "absolute",
|
||||
bottom: theme.spacing(4)
|
||||
bottom: theme.spacing(4),
|
||||
},
|
||||
logo: {
|
||||
display: "block",
|
||||
height: 40,
|
||||
marginBottom: theme.spacing(4)
|
||||
marginBottom: theme.spacing(4),
|
||||
},
|
||||
mainPanel: {
|
||||
[theme.breakpoints.down("sm")]: {
|
||||
padding: theme.spacing(2)
|
||||
padding: theme.spacing(2),
|
||||
},
|
||||
background: theme.palette.background.paper,
|
||||
display: "flex",
|
||||
|
@ -26,27 +26,27 @@ const useStyles = makeStyles(
|
|||
height: "100vh",
|
||||
justifyContent: "center",
|
||||
padding: theme.spacing(5, 6, 4, 6),
|
||||
width: "100%"
|
||||
width: "100%",
|
||||
},
|
||||
mainPanelContent: {
|
||||
[theme.breakpoints.up("xs")]: {
|
||||
width: "100%"
|
||||
width: "100%",
|
||||
},
|
||||
[theme.breakpoints.up("sm")]: {
|
||||
width: 328
|
||||
width: 328,
|
||||
},
|
||||
"@media (min-width: 1440px)": {
|
||||
width: 380
|
||||
width: 380,
|
||||
},
|
||||
margin: "auto",
|
||||
width: "100%"
|
||||
width: "100%",
|
||||
},
|
||||
root: {
|
||||
[theme.breakpoints.up("lg")]: {
|
||||
gridTemplateColumns: "560px 1fr"
|
||||
gridTemplateColumns: "560px 1fr",
|
||||
},
|
||||
"@media (min-width: 1440px)": {
|
||||
gridTemplateColumns: "780px 1fr"
|
||||
gridTemplateColumns: "780px 1fr",
|
||||
},
|
||||
display: "grid",
|
||||
gridTemplateColumns: "1fr",
|
||||
|
@ -54,24 +54,24 @@ const useStyles = makeStyles(
|
|||
height: "100vh",
|
||||
overflow: "hidden",
|
||||
position: "relative",
|
||||
width: "100vw"
|
||||
width: "100vw",
|
||||
},
|
||||
sidebar: {
|
||||
[theme.breakpoints.up("lg")]: {
|
||||
alignItems: "center",
|
||||
display: "flex"
|
||||
display: "flex",
|
||||
},
|
||||
display: "none"
|
||||
display: "none",
|
||||
},
|
||||
sidebarArt: {
|
||||
"& svg": {
|
||||
width: "100%"
|
||||
}
|
||||
}
|
||||
width: "100%",
|
||||
},
|
||||
},
|
||||
}),
|
||||
{
|
||||
name: "Layout"
|
||||
}
|
||||
name: "Layout",
|
||||
},
|
||||
);
|
||||
|
||||
const Layout: React.FC = props => {
|
||||
|
|
|
@ -8,10 +8,10 @@ const useStyles = makeStyles(
|
|||
alignItems: "center",
|
||||
display: "flex",
|
||||
height: "100vh",
|
||||
justifyContent: "center"
|
||||
}
|
||||
justifyContent: "center",
|
||||
},
|
||||
},
|
||||
{ name: "LoginLoading" }
|
||||
{ name: "LoginLoading" },
|
||||
);
|
||||
const LoginLoading: React.FC = props => {
|
||||
const classes = useStyles(props);
|
||||
|
|
|
@ -11,12 +11,12 @@ const props: Omit<LoginCardProps, "classes"> = {
|
|||
{
|
||||
__typename: "ExternalAuthentication",
|
||||
id: "auth.plugin.example",
|
||||
name: "Example auth plugin"
|
||||
}
|
||||
name: "Example auth plugin",
|
||||
},
|
||||
],
|
||||
loading: false,
|
||||
onExternalAuthentication: () => undefined,
|
||||
onSubmit: () => undefined
|
||||
onSubmit: () => undefined,
|
||||
};
|
||||
|
||||
storiesOf("Views / Authentication / Log in", module)
|
||||
|
|
|
@ -2,7 +2,7 @@ import {
|
|||
CircularProgress,
|
||||
Divider,
|
||||
TextField,
|
||||
Typography
|
||||
Typography,
|
||||
} from "@material-ui/core";
|
||||
import { UserContextError } from "@saleor/auth/types";
|
||||
import { passwordResetUrl } from "@saleor/auth/urls";
|
||||
|
@ -36,7 +36,7 @@ const LoginCard: React.FC<LoginCardProps> = props => {
|
|||
loading,
|
||||
externalAuthentications = [],
|
||||
onExternalAuthentication,
|
||||
onSubmit
|
||||
onSubmit,
|
||||
} = props;
|
||||
|
||||
const classes = useStyles(props);
|
||||
|
@ -76,7 +76,7 @@ const LoginCard: React.FC<LoginCardProps> = props => {
|
|||
onChange={handleChange}
|
||||
value={data.email}
|
||||
inputProps={{
|
||||
"data-test-id": "email"
|
||||
"data-test-id": "email",
|
||||
}}
|
||||
disabled={disabled}
|
||||
/>
|
||||
|
@ -87,14 +87,14 @@ const LoginCard: React.FC<LoginCardProps> = props => {
|
|||
autoComplete="password"
|
||||
label={intl.formatMessage({
|
||||
id: "5sg7KC",
|
||||
defaultMessage: "Password"
|
||||
defaultMessage: "Password",
|
||||
})}
|
||||
name="password"
|
||||
onChange={handleChange}
|
||||
type={showPassword ? "text" : "password"}
|
||||
value={data.password}
|
||||
inputProps={{
|
||||
"data-test-id": "password"
|
||||
"data-test-id": "password",
|
||||
}}
|
||||
disabled={disabled}
|
||||
/>
|
||||
|
|
|
@ -23,14 +23,14 @@ const getLoginFormData = () => {
|
|||
if (DEMO_MODE) {
|
||||
return {
|
||||
email: "admin@example.com",
|
||||
password: "admin"
|
||||
password: "admin",
|
||||
};
|
||||
}
|
||||
return { email: "", password: "" };
|
||||
};
|
||||
|
||||
function useLoginForm(
|
||||
onSubmit: (data: LoginFormData) => SubmitPromise
|
||||
onSubmit: (data: LoginFormData) => SubmitPromise,
|
||||
): UseLoginFormResult {
|
||||
const form = useForm(getLoginFormData());
|
||||
|
||||
|
@ -43,7 +43,7 @@ function useLoginForm(
|
|||
return {
|
||||
change,
|
||||
data,
|
||||
submit
|
||||
submit,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue