Fix configuration page
This commit is contained in:
parent
78132229af
commit
ad4975bd84
6 changed files with 196 additions and 331 deletions
|
@ -173,6 +173,13 @@ const MenuList = withStyles(styles, { name: "MenuList" })(
|
||||||
});
|
});
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
|
const configutationMenu = createConfigurationMenu(intl).map(menu => {
|
||||||
|
menu.menuItems.map(item => {
|
||||||
|
return user.permissions
|
||||||
|
.map(perm => perm.code)
|
||||||
|
.includes(item.permission);
|
||||||
|
});
|
||||||
|
});
|
||||||
const handleSubMenu = itemLabel => {
|
const handleSubMenu = itemLabel => {
|
||||||
setActiveSubMenu({
|
setActiveSubMenu({
|
||||||
isActive:
|
isActive:
|
||||||
|
@ -304,12 +311,7 @@ const MenuList = withStyles(styles, { name: "MenuList" })(
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
{renderConfigure &&
|
{renderConfigure && configutationMenu.length > 0 && (
|
||||||
createConfigurationMenu(intl).filter(menuItem =>
|
|
||||||
user.permissions
|
|
||||||
.map(perm => perm.code)
|
|
||||||
.includes(menuItem.permission)
|
|
||||||
).length > 0 && (
|
|
||||||
<a
|
<a
|
||||||
className={classes.menuListItem}
|
className={classes.menuListItem}
|
||||||
href={createHref(configurationMenuUrl)}
|
href={createHref(configurationMenuUrl)}
|
||||||
|
|
|
@ -61,8 +61,7 @@ const styles = (theme: Theme) =>
|
||||||
paddingRight: theme.spacing.unit
|
paddingRight: theme.spacing.unit
|
||||||
},
|
},
|
||||||
chipLabel: {
|
chipLabel: {
|
||||||
color: theme.palette.common.white,
|
color: theme.palette.primary.contrastText
|
||||||
fontSize: "16px"
|
|
||||||
},
|
},
|
||||||
container: {
|
container: {
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
|
@ -276,7 +275,7 @@ export const MultiAutocompleteSelectFieldComponent = withStyles(styles, {
|
||||||
{displayValues.map(value => (
|
{displayValues.map(value => (
|
||||||
<div className={classes.chip} key={value.value}>
|
<div className={classes.chip} key={value.value}>
|
||||||
<div className={classes.chipInner}>
|
<div className={classes.chipInner}>
|
||||||
<Typography className={classes.chipLabel} variant="caption">
|
<Typography className={classes.chipLabel}>
|
||||||
{value.label}
|
{value.label}
|
||||||
</Typography>
|
</Typography>
|
||||||
<IconButton
|
<IconButton
|
||||||
|
|
|
@ -12,20 +12,24 @@ import { useIntl } from "react-intl";
|
||||||
|
|
||||||
import { IconProps } from "@material-ui/core/Icon";
|
import { IconProps } from "@material-ui/core/Icon";
|
||||||
import { sectionNames } from "@saleor/intl";
|
import { sectionNames } from "@saleor/intl";
|
||||||
import { ConfigurationCategoryEnum } from "@saleor/types";
|
import { hasPermission } from "../auth/misc";
|
||||||
import { User } from "../auth/types/User";
|
import { User } from "../auth/types/User";
|
||||||
import Container from "../components/Container";
|
import Container from "../components/Container";
|
||||||
import PageHeader from "../components/PageHeader";
|
import PageHeader from "../components/PageHeader";
|
||||||
import { PermissionEnum } from "../types/globalTypes";
|
import { PermissionEnum } from "../types/globalTypes";
|
||||||
|
|
||||||
export interface MenuItem {
|
export interface MenuItem {
|
||||||
category: ConfigurationCategoryEnum;
|
label: string;
|
||||||
|
menuItems: [
|
||||||
|
{
|
||||||
description: string;
|
description: string;
|
||||||
icon: React.ReactElement<IconProps>;
|
icon: React.ReactElement<IconProps>;
|
||||||
permission: PermissionEnum;
|
permission: PermissionEnum;
|
||||||
title: string;
|
title: string;
|
||||||
url?: string;
|
url?: string;
|
||||||
}
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
const styles = (theme: Theme) =>
|
const styles = (theme: Theme) =>
|
||||||
createStyles({
|
createStyles({
|
||||||
|
@ -70,6 +74,9 @@ const styles = (theme: Theme) =>
|
||||||
configurationLabel: {
|
configurationLabel: {
|
||||||
paddingBottom: 20
|
paddingBottom: 20
|
||||||
},
|
},
|
||||||
|
header: {
|
||||||
|
margin: 0
|
||||||
|
},
|
||||||
icon: {
|
icon: {
|
||||||
color: theme.palette.primary.main,
|
color: theme.palette.primary.main,
|
||||||
fontSize: 48
|
fontSize: 48
|
||||||
|
@ -99,191 +106,45 @@ export const ConfigurationPage = withStyles(styles, {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<PageHeader title={intl.formatMessage(sectionNames.configuration)} />
|
<PageHeader
|
||||||
|
className={classes.header}
|
||||||
|
title={intl.formatMessage(sectionNames.configuration)}
|
||||||
|
/>
|
||||||
|
{menu
|
||||||
|
.filter(menu =>
|
||||||
|
menu.menuItems.map(item => hasPermission(item.permission, user))
|
||||||
|
)
|
||||||
|
.map((menu, menuIndex) => (
|
||||||
<div className={classes.configurationCategory}>
|
<div className={classes.configurationCategory}>
|
||||||
<div className={classes.configurationLabel}>
|
<div className={classes.configurationLabel}>
|
||||||
<Typography>
|
<Typography>{menu.label}</Typography>
|
||||||
{intl.formatMessage({
|
|
||||||
defaultMessage: "Attributes and Product Types",
|
|
||||||
description: "configuration category"
|
|
||||||
})}
|
|
||||||
</Typography>
|
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.configurationItem}>
|
<div className={classes.configurationItem}>
|
||||||
{menu
|
{menu.menuItems.map(item => (
|
||||||
.filter(menuItem =>
|
|
||||||
user.permissions
|
|
||||||
.map(perm => perm.code)
|
|
||||||
.includes(menuItem.permission)
|
|
||||||
)
|
|
||||||
.map(
|
|
||||||
(menuItem, menuItemIndex) =>
|
|
||||||
menuItem.category ===
|
|
||||||
ConfigurationCategoryEnum.ATTRUBUTES_PRODUCT_TYPES && (
|
|
||||||
<Card
|
<Card
|
||||||
className={
|
className={item.url ? classes.card : classes.cardDisabled}
|
||||||
menuItem.url ? classes.card : classes.cardDisabled
|
onClick={() => onSectionClick(item.url)}
|
||||||
}
|
key={menuIndex}
|
||||||
onClick={() => onSectionClick(menuItem.url)}
|
|
||||||
key={menuItemIndex}
|
|
||||||
>
|
>
|
||||||
<CardContent className={classes.cardContent}>
|
<CardContent className={classes.cardContent}>
|
||||||
<div className={classes.icon}>{menuItem.icon}</div>
|
<div className={classes.icon}>{item.icon}</div>
|
||||||
<div>
|
<div>
|
||||||
<Typography
|
<Typography
|
||||||
className={classes.sectionTitle}
|
className={classes.sectionTitle}
|
||||||
color="primary"
|
color="primary"
|
||||||
>
|
>
|
||||||
{menuItem.title}
|
{item.title}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography className={classes.sectionDescription}>
|
<Typography className={classes.sectionDescription}>
|
||||||
{menuItem.description}
|
{item.description}
|
||||||
</Typography>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
)
|
))}
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className={classes.configurationCategory}>
|
|
||||||
<div className={classes.configurationLabel}>
|
|
||||||
<Typography>
|
|
||||||
{intl.formatMessage({
|
|
||||||
defaultMessage: "Product Settings",
|
|
||||||
description: "configuration category"
|
|
||||||
})}
|
|
||||||
</Typography>
|
|
||||||
</div>
|
|
||||||
<div className={classes.configurationItem}>
|
|
||||||
{menu
|
|
||||||
.filter(menuItem =>
|
|
||||||
user.permissions
|
|
||||||
.map(perm => perm.code)
|
|
||||||
.includes(menuItem.permission)
|
|
||||||
)
|
|
||||||
.map(
|
|
||||||
(menuItem, menuItemIndex) =>
|
|
||||||
menuItem.category ===
|
|
||||||
ConfigurationCategoryEnum.PRODUCT_SETTINGS && (
|
|
||||||
<Card
|
|
||||||
className={
|
|
||||||
menuItem.url ? classes.card : classes.cardDisabled
|
|
||||||
}
|
|
||||||
onClick={() => onSectionClick(menuItem.url)}
|
|
||||||
key={menuItemIndex}
|
|
||||||
>
|
|
||||||
<CardContent className={classes.cardContent}>
|
|
||||||
<div className={classes.icon}>{menuItem.icon}</div>
|
|
||||||
<div>
|
|
||||||
<Typography
|
|
||||||
className={classes.sectionTitle}
|
|
||||||
color="primary"
|
|
||||||
>
|
|
||||||
{menuItem.title}
|
|
||||||
</Typography>
|
|
||||||
<Typography className={classes.sectionDescription}>
|
|
||||||
{menuItem.description}
|
|
||||||
</Typography>
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className={classes.configurationCategory}>
|
|
||||||
<div className={classes.configurationLabel}>
|
|
||||||
<Typography>
|
|
||||||
{intl.formatMessage({
|
|
||||||
defaultMessage: "Staff Settings",
|
|
||||||
description: "configuration category"
|
|
||||||
})}
|
|
||||||
</Typography>
|
|
||||||
</div>
|
|
||||||
<div className={classes.configurationItem}>
|
|
||||||
{menu
|
|
||||||
.filter(menuItem =>
|
|
||||||
user.permissions
|
|
||||||
.map(perm => perm.code)
|
|
||||||
.includes(menuItem.permission)
|
|
||||||
)
|
|
||||||
.map(
|
|
||||||
(menuItem, menuItemIndex) =>
|
|
||||||
menuItem.category ===
|
|
||||||
ConfigurationCategoryEnum.STAFF_SETTINGS && (
|
|
||||||
<Card
|
|
||||||
className={
|
|
||||||
menuItem.url ? classes.card : classes.cardDisabled
|
|
||||||
}
|
|
||||||
onClick={() => onSectionClick(menuItem.url)}
|
|
||||||
key={menuItemIndex}
|
|
||||||
>
|
|
||||||
<CardContent className={classes.cardContent}>
|
|
||||||
<div className={classes.icon}>{menuItem.icon}</div>
|
|
||||||
<div>
|
|
||||||
<Typography
|
|
||||||
className={classes.sectionTitle}
|
|
||||||
color="primary"
|
|
||||||
>
|
|
||||||
{menuItem.title}
|
|
||||||
</Typography>
|
|
||||||
<Typography className={classes.sectionDescription}>
|
|
||||||
{menuItem.description}
|
|
||||||
</Typography>
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className={classes.configurationCategory}>
|
|
||||||
<div className={classes.configurationLabel}>
|
|
||||||
<Typography>
|
|
||||||
{intl.formatMessage({
|
|
||||||
defaultMessage: "Miscellaneous",
|
|
||||||
description: "configuration category"
|
|
||||||
})}
|
|
||||||
</Typography>
|
|
||||||
</div>
|
|
||||||
<div className={classes.configurationItem}>
|
|
||||||
{menu
|
|
||||||
.filter(menuItem =>
|
|
||||||
user.permissions
|
|
||||||
.map(perm => perm.code)
|
|
||||||
.includes(menuItem.permission)
|
|
||||||
)
|
|
||||||
.map(
|
|
||||||
(menuItem, menuItemIndex) =>
|
|
||||||
menuItem.category ===
|
|
||||||
ConfigurationCategoryEnum.MISCELLANEOUS && (
|
|
||||||
<Card
|
|
||||||
className={
|
|
||||||
menuItem.url ? classes.card : classes.cardDisabled
|
|
||||||
}
|
|
||||||
onClick={() => onSectionClick(menuItem.url)}
|
|
||||||
key={menuItemIndex}
|
|
||||||
>
|
|
||||||
<CardContent className={classes.cardContent}>
|
|
||||||
<div className={classes.icon}>{menuItem.icon}</div>
|
|
||||||
<div>
|
|
||||||
<Typography
|
|
||||||
className={classes.sectionTitle}
|
|
||||||
color="primary"
|
|
||||||
>
|
|
||||||
{menuItem.title}
|
|
||||||
</Typography>
|
|
||||||
<Typography className={classes.sectionDescription}>
|
|
||||||
{menuItem.description}
|
|
||||||
</Typography>
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
))}
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,14 +24,15 @@ import { shippingZonesListUrl } from "@saleor/shipping/urls";
|
||||||
import { siteSettingsUrl } from "@saleor/siteSettings/urls";
|
import { siteSettingsUrl } from "@saleor/siteSettings/urls";
|
||||||
import { staffListUrl } from "@saleor/staff/urls";
|
import { staffListUrl } from "@saleor/staff/urls";
|
||||||
import { taxSection } from "@saleor/taxes/urls";
|
import { taxSection } from "@saleor/taxes/urls";
|
||||||
import { ConfigurationCategoryEnum } from "@saleor/types";
|
|
||||||
import { PermissionEnum } from "@saleor/types/globalTypes";
|
import { PermissionEnum } from "@saleor/types/globalTypes";
|
||||||
import ConfigurationPage, { MenuItem } from "./ConfigurationPage";
|
import ConfigurationPage, { MenuItem } from "./ConfigurationPage";
|
||||||
|
|
||||||
export function createConfigurationMenu(intl: IntlShape): MenuItem[] {
|
export function createConfigurationMenu(intl: IntlShape): MenuItem[] {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
category: ConfigurationCategoryEnum.ATTRUBUTES_PRODUCT_TYPES,
|
label: "Attributes and Product Types",
|
||||||
|
menuItems: [
|
||||||
|
{
|
||||||
description: intl.formatMessage({
|
description: intl.formatMessage({
|
||||||
defaultMessage: "Determine attributes used to create product types",
|
defaultMessage: "Determine attributes used to create product types",
|
||||||
id: "configurationMenuAttributes"
|
id: "configurationMenuAttributes"
|
||||||
|
@ -42,7 +43,6 @@ export function createConfigurationMenu(intl: IntlShape): MenuItem[] {
|
||||||
url: attributeListUrl()
|
url: attributeListUrl()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
category: ConfigurationCategoryEnum.ATTRUBUTES_PRODUCT_TYPES,
|
|
||||||
description: intl.formatMessage({
|
description: intl.formatMessage({
|
||||||
defaultMessage: "Define types of products you sell",
|
defaultMessage: "Define types of products you sell",
|
||||||
id: "configurationMenuProductTypes"
|
id: "configurationMenuProductTypes"
|
||||||
|
@ -51,20 +51,13 @@ export function createConfigurationMenu(intl: IntlShape): MenuItem[] {
|
||||||
permission: PermissionEnum.MANAGE_PRODUCTS,
|
permission: PermissionEnum.MANAGE_PRODUCTS,
|
||||||
title: intl.formatMessage(sectionNames.productTypes),
|
title: intl.formatMessage(sectionNames.productTypes),
|
||||||
url: productTypeListUrl()
|
url: productTypeListUrl()
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
category: ConfigurationCategoryEnum.STAFF_SETTINGS,
|
label: "Product Settings",
|
||||||
description: intl.formatMessage({
|
menuItems: [
|
||||||
defaultMessage: "Manage your employees and their permissions",
|
|
||||||
id: "configurationMenuStaff"
|
|
||||||
}),
|
|
||||||
icon: <StaffMembers fontSize="inherit" viewBox="0 0 44 44" />,
|
|
||||||
permission: PermissionEnum.MANAGE_STAFF,
|
|
||||||
title: intl.formatMessage(sectionNames.staff),
|
|
||||||
url: staffListUrl()
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
category: ConfigurationCategoryEnum.PRODUCT_SETTINGS,
|
|
||||||
description: intl.formatMessage({
|
description: intl.formatMessage({
|
||||||
defaultMessage: "Manage how you ship out orders",
|
defaultMessage: "Manage how you ship out orders",
|
||||||
id: "configurationMenuShipping"
|
id: "configurationMenuShipping"
|
||||||
|
@ -75,7 +68,6 @@ export function createConfigurationMenu(intl: IntlShape): MenuItem[] {
|
||||||
url: shippingZonesListUrl()
|
url: shippingZonesListUrl()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
category: ConfigurationCategoryEnum.PRODUCT_SETTINGS,
|
|
||||||
description: intl.formatMessage({
|
description: intl.formatMessage({
|
||||||
defaultMessage: "Manage how your store charges tax",
|
defaultMessage: "Manage how your store charges tax",
|
||||||
id: "configurationMenuTaxes"
|
id: "configurationMenuTaxes"
|
||||||
|
@ -84,9 +76,28 @@ export function createConfigurationMenu(intl: IntlShape): MenuItem[] {
|
||||||
permission: PermissionEnum.MANAGE_PRODUCTS,
|
permission: PermissionEnum.MANAGE_PRODUCTS,
|
||||||
title: intl.formatMessage(sectionNames.taxes),
|
title: intl.formatMessage(sectionNames.taxes),
|
||||||
url: taxSection
|
url: taxSection
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
category: ConfigurationCategoryEnum.MISCELLANEOUS,
|
label: "Staff Settings",
|
||||||
|
menuItems: [
|
||||||
|
{
|
||||||
|
description: intl.formatMessage({
|
||||||
|
defaultMessage: "Manage your employees and their permissions",
|
||||||
|
id: "configurationMenuStaff"
|
||||||
|
}),
|
||||||
|
icon: <StaffMembers fontSize="inherit" viewBox="0 0 44 44" />,
|
||||||
|
permission: PermissionEnum.MANAGE_STAFF,
|
||||||
|
title: intl.formatMessage(sectionNames.staff),
|
||||||
|
url: staffListUrl()
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Miscellaneous",
|
||||||
|
menuItems: [
|
||||||
|
{
|
||||||
description: intl.formatMessage({
|
description: intl.formatMessage({
|
||||||
defaultMessage: "Define how users can navigate through your store",
|
defaultMessage: "Define how users can navigate through your store",
|
||||||
id: "configurationMenuNavigation"
|
id: "configurationMenuNavigation"
|
||||||
|
@ -97,7 +108,6 @@ export function createConfigurationMenu(intl: IntlShape): MenuItem[] {
|
||||||
url: menuListUrl()
|
url: menuListUrl()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
category: ConfigurationCategoryEnum.MISCELLANEOUS,
|
|
||||||
description: intl.formatMessage({
|
description: intl.formatMessage({
|
||||||
defaultMessage: "View and update your site settings",
|
defaultMessage: "View and update your site settings",
|
||||||
id: "configurationMenuSiteSettings"
|
id: "configurationMenuSiteSettings"
|
||||||
|
@ -108,7 +118,6 @@ export function createConfigurationMenu(intl: IntlShape): MenuItem[] {
|
||||||
url: siteSettingsUrl()
|
url: siteSettingsUrl()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
category: ConfigurationCategoryEnum.MISCELLANEOUS,
|
|
||||||
description: intl.formatMessage({
|
description: intl.formatMessage({
|
||||||
defaultMessage: "Manage and add additional pages",
|
defaultMessage: "Manage and add additional pages",
|
||||||
id: "configurationMenuPages"
|
id: "configurationMenuPages"
|
||||||
|
@ -119,7 +128,6 @@ export function createConfigurationMenu(intl: IntlShape): MenuItem[] {
|
||||||
url: pageListUrl()
|
url: pageListUrl()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
category: ConfigurationCategoryEnum.MISCELLANEOUS,
|
|
||||||
description: intl.formatMessage({
|
description: intl.formatMessage({
|
||||||
defaultMessage: "View and update your plugins and their settings.",
|
defaultMessage: "View and update your plugins and their settings.",
|
||||||
id: "configurationPluginsPages"
|
id: "configurationPluginsPages"
|
||||||
|
@ -135,6 +143,8 @@ export function createConfigurationMenu(intl: IntlShape): MenuItem[] {
|
||||||
title: intl.formatMessage(sectionNames.plugins),
|
title: intl.formatMessage(sectionNames.plugins),
|
||||||
url: pluginsListUrl()
|
url: pluginsListUrl()
|
||||||
}
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -227,8 +227,8 @@ const Routes: React.FC = () => {
|
||||||
path={attributeSection}
|
path={attributeSection}
|
||||||
component={AttributeSection}
|
component={AttributeSection}
|
||||||
/>
|
/>
|
||||||
{createConfigurationMenu(intl).filter(menuItem =>
|
{createConfigurationMenu(intl).filter(menu =>
|
||||||
hasPermission(menuItem.permission, user)
|
menu.menuItems.map(item => hasPermission(item.permission, user))
|
||||||
).length > 0 && (
|
).length > 0 && (
|
||||||
<SectionRoute
|
<SectionRoute
|
||||||
exact
|
exact
|
||||||
|
|
|
@ -134,10 +134,3 @@ export interface FetchMoreProps {
|
||||||
hasMore: boolean;
|
hasMore: boolean;
|
||||||
onFetchMore: () => void;
|
onFetchMore: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ConfigurationCategoryEnum {
|
|
||||||
ATTRUBUTES_PRODUCT_TYPES = "ATTRUBUTES_PRODUCT_TYPES",
|
|
||||||
PRODUCT_SETTINGS = "PRODUCT_SETTINGS",
|
|
||||||
STAFF_SETTINGS = "STAFF_SETTINGS",
|
|
||||||
MISCELLANEOUS = "MISCELLANEOUS"
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue