Add permission-based restrictions in Customer views (#1879)

* Update customer queries - add permissions

* Filter the customer filter by permissions

* Code refactor + optionally render components based on permissions

* Update stories

* Minor code refactor

* Move useUserPermissions to RequirePermissions component

* Change user provider component name

* Change macaw-ui version
This commit is contained in:
Wojciech Mista 2022-03-01 09:38:23 +01:00 committed by GitHub
parent 8ab05ab8e1
commit 9a7c9a3bc3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
33 changed files with 257 additions and 453 deletions

View file

@ -28,7 +28,7 @@
"@material-ui/icons": "^4.11.2", "@material-ui/icons": "^4.11.2",
"@material-ui/lab": "^4.0.0-alpha.58", "@material-ui/lab": "^4.0.0-alpha.58",
"@material-ui/styles": "^4.11.4", "@material-ui/styles": "^4.11.4",
"@saleor/macaw-ui": "^0.3.1", "@saleor/macaw-ui": "0.3.1",
"@saleor/sdk": "^0.4.2", "@saleor/sdk": "^0.4.2",
"@sentry/react": "^6.0.0", "@sentry/react": "^6.0.0",
"@types/faker": "^5.1.6", "@types/faker": "^5.1.6",

View file

@ -0,0 +1,3 @@
import { useUser } from "..";
export const useUserPermissions = () => useUser().user?.userPermissions;

View file

@ -1,5 +1,4 @@
import { Card, CardContent, Typography } from "@material-ui/core"; import { Card, CardContent, Typography } from "@material-ui/core";
import { useUser } from "@saleor/auth";
import CardTitle from "@saleor/components/CardTitle"; import CardTitle from "@saleor/components/CardTitle";
import Hr from "@saleor/components/Hr"; import Hr from "@saleor/components/Hr";
import RequirePermissions from "@saleor/components/RequirePermissions"; import RequirePermissions from "@saleor/components/RequirePermissions";
@ -28,7 +27,6 @@ export const ChannelsAvailabilityWrapper: React.FC<ChannelsAvailabilityWrapperPr
} = props; } = props;
const intl = useIntl(); const intl = useIntl();
const classes = useStyles({}); const classes = useStyles({});
const { user } = useUser();
const channelsAvailabilityText = intl.formatMessage( const channelsAvailabilityText = intl.formatMessage(
{ {
defaultMessage: defaultMessage:
@ -51,10 +49,7 @@ export const ChannelsAvailabilityWrapper: React.FC<ChannelsAvailabilityWrapperPr
description: "section header" description: "section header"
})} })}
toolbar={ toolbar={
<RequirePermissions <RequirePermissions requiredPermissions={managePermissions}>
userPermissions={user?.userPermissions || []}
requiredPermissions={managePermissions}
>
<Button <Button
onClick={openModal} onClick={openModal}
data-test-id="channels-availability-manage-button" data-test-id="channels-availability-manage-button"

View file

@ -1,4 +1,5 @@
import { FetchMoreProps, SearchPageProps } from "@saleor/types"; import { FetchMoreProps, SearchPageProps } from "@saleor/types";
import { PermissionEnum } from "@saleor/types/globalTypes";
import { MessageDescriptor } from "react-intl"; import { MessageDescriptor } from "react-intl";
import { MultiAutocompleteChoiceType } from "../MultiAutocompleteSelectField"; import { MultiAutocompleteChoiceType } from "../MultiAutocompleteSelectField";
@ -34,6 +35,7 @@ export interface IFilterElement<T extends string = string>
multipleFields?: IFilterElement[]; multipleFields?: IFilterElement[];
id?: string; id?: string;
dependencies?: string[]; dependencies?: string[];
permissions?: PermissionEnum[];
} }
export interface FilterBaseFieldProps<T extends string = string> { export interface FilterBaseFieldProps<T extends string = string> {

View file

@ -1,3 +1,4 @@
import { useUserPermissions } from "@saleor/auth/hooks/useUserPermissions";
import { User_userPermissions } from "@saleor/fragments/types/User"; import { User_userPermissions } from "@saleor/fragments/types/User";
import { PermissionEnum } from "@saleor/types/globalTypes"; import { PermissionEnum } from "@saleor/types/globalTypes";
import React from "react"; import React from "react";
@ -16,15 +17,19 @@ export function hasPermissions(
export interface RequirePermissionsProps { export interface RequirePermissionsProps {
children: React.ReactNode | React.ReactNodeArray; children: React.ReactNode | React.ReactNodeArray;
requiredPermissions: PermissionEnum[]; requiredPermissions: PermissionEnum[];
userPermissions: User_userPermissions[];
} }
const RequirePermissions: React.FC<RequirePermissionsProps> = ({ const RequirePermissions: React.FC<RequirePermissionsProps> = ({
children, children,
requiredPermissions, requiredPermissions
userPermissions }) => {
}) => const userPermissions = useUserPermissions();
hasPermissions(userPermissions, requiredPermissions) ? <>{children}</> : null;
return userPermissions &&
hasPermissions(userPermissions, requiredPermissions) ? (
<>{children}</>
) : null;
};
RequirePermissions.displayName = "RequirePermissions"; RequirePermissions.displayName = "RequirePermissions";
export default RequirePermissions; export default RequirePermissions;

View file

@ -5,6 +5,7 @@ import Grid from "@saleor/components/Grid";
import Metadata from "@saleor/components/Metadata/Metadata"; import Metadata from "@saleor/components/Metadata/Metadata";
import { MetadataFormData } from "@saleor/components/Metadata/types"; import { MetadataFormData } from "@saleor/components/Metadata/types";
import PageHeader from "@saleor/components/PageHeader"; import PageHeader from "@saleor/components/PageHeader";
import RequirePermissions from "@saleor/components/RequirePermissions";
import Savebar from "@saleor/components/Savebar"; import Savebar from "@saleor/components/Savebar";
import { UpdateCustomer_customerUpdate_errors } from "@saleor/customers/types/UpdateCustomer"; import { UpdateCustomer_customerUpdate_errors } from "@saleor/customers/types/UpdateCustomer";
import { AccountErrorFragment } from "@saleor/fragments/types/AccountErrorFragment"; import { AccountErrorFragment } from "@saleor/fragments/types/AccountErrorFragment";
@ -13,6 +14,7 @@ import { SubmitPromise } from "@saleor/hooks/useForm";
import { sectionNames } from "@saleor/intl"; import { sectionNames } from "@saleor/intl";
import { ConfirmButtonTransitionState } from "@saleor/macaw-ui"; import { ConfirmButtonTransitionState } from "@saleor/macaw-ui";
import { Backlink } from "@saleor/macaw-ui"; import { Backlink } from "@saleor/macaw-ui";
import { PermissionEnum } from "@saleor/types/globalTypes";
import { mapEdgesToItems, mapMetadataItemToInput } from "@saleor/utils/maps"; import { mapEdgesToItems, mapMetadataItemToInput } from "@saleor/utils/maps";
import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger"; import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger";
import React from "react"; import React from "react";
@ -105,12 +107,16 @@ const CustomerDetailsPage: React.FC<CustomerDetailsPageProps> = ({
onChange={change} onChange={change}
/> />
<CardSpacer /> <CardSpacer />
<CustomerOrders <RequirePermissions
orders={mapEdgesToItems(customer?.orders)} requiredPermissions={[PermissionEnum.MANAGE_ORDERS]}
onViewAllOrdersClick={onViewAllOrdersClick} >
onRowClick={onRowClick} <CustomerOrders
/> orders={mapEdgesToItems(customer?.orders)}
<CardSpacer /> onViewAllOrdersClick={onViewAllOrdersClick}
onRowClick={onRowClick}
/>
<CardSpacer />
</RequirePermissions>
<Metadata data={data} onChange={changeMetadata} /> <Metadata data={data} onChange={changeMetadata} />
</div> </div>
<div> <div>
@ -122,7 +128,11 @@ const CustomerDetailsPage: React.FC<CustomerDetailsPageProps> = ({
<CardSpacer /> <CardSpacer />
<CustomerStats customer={customer} /> <CustomerStats customer={customer} />
<CardSpacer /> <CardSpacer />
<CustomerGiftCardsCard /> <RequirePermissions
requiredPermissions={[PermissionEnum.MANAGE_GIFT_CARD]}
>
<CustomerGiftCardsCard />
</RequirePermissions>
</div> </div>
</Grid> </Grid>
<Savebar <Savebar

View file

@ -1,5 +1,9 @@
import { TableBody, TableCell, TableFooter, TableRow } from "@material-ui/core"; import { TableBody, TableCell, TableFooter, TableRow } from "@material-ui/core";
import { useUserPermissions } from "@saleor/auth/hooks/useUserPermissions";
import Checkbox from "@saleor/components/Checkbox"; import Checkbox from "@saleor/components/Checkbox";
import RequirePermissions, {
hasPermissions
} from "@saleor/components/RequirePermissions";
import ResponsiveTable from "@saleor/components/ResponsiveTable"; import ResponsiveTable from "@saleor/components/ResponsiveTable";
import Skeleton from "@saleor/components/Skeleton"; import Skeleton from "@saleor/components/Skeleton";
import TableCellHeader from "@saleor/components/TableCellHeader"; import TableCellHeader from "@saleor/components/TableCellHeader";
@ -7,8 +11,9 @@ import TableHead from "@saleor/components/TableHead";
import TablePagination from "@saleor/components/TablePagination"; import TablePagination from "@saleor/components/TablePagination";
import { CustomerListUrlSortField } from "@saleor/customers/urls"; import { CustomerListUrlSortField } from "@saleor/customers/urls";
import { makeStyles } from "@saleor/macaw-ui"; import { makeStyles } from "@saleor/macaw-ui";
import { getUserName, maybe, renderCollection } from "@saleor/misc"; import { getUserName, renderCollection } from "@saleor/misc";
import { ListActions, ListProps, SortPage } from "@saleor/types"; import { ListActions, ListProps, SortPage } from "@saleor/types";
import { PermissionEnum } from "@saleor/types/globalTypes";
import { getArrowDirection } from "@saleor/utils/sort"; import { getArrowDirection } from "@saleor/utils/sort";
import React from "react"; import React from "react";
import { FormattedMessage } from "react-intl"; import { FormattedMessage } from "react-intl";
@ -45,7 +50,7 @@ export interface CustomerListProps
customers: ListCustomers_customers_edges_node[]; customers: ListCustomers_customers_edges_node[];
} }
const numberOfColumns = 4; const numberOfColumns = 3;
const CustomerList: React.FC<CustomerListProps> = props => { const CustomerList: React.FC<CustomerListProps> = props => {
const { const {
@ -66,12 +71,18 @@ const CustomerList: React.FC<CustomerListProps> = props => {
isChecked isChecked
} = props; } = props;
const userPermissions = useUserPermissions();
const classes = useStyles(props); const classes = useStyles(props);
return ( return (
<ResponsiveTable> <ResponsiveTable>
<TableHead <TableHead
colSpan={numberOfColumns} colSpan={
hasPermissions(userPermissions, [PermissionEnum.MANAGE_ORDERS])
? numberOfColumns
: numberOfColumns - 1
}
selected={selected} selected={selected}
disabled={disabled} disabled={disabled}
items={customers} items={customers}
@ -101,18 +112,22 @@ const CustomerList: React.FC<CustomerListProps> = props => {
> >
<FormattedMessage defaultMessage="Customer Email" /> <FormattedMessage defaultMessage="Customer Email" />
</TableCellHeader> </TableCellHeader>
<TableCellHeader <RequirePermissions
direction={ requiredPermissions={[PermissionEnum.MANAGE_ORDERS]}
sort.sort === CustomerListUrlSortField.orders
? getArrowDirection(sort.asc)
: undefined
}
textAlign="center"
onClick={() => onSort(CustomerListUrlSortField.orders)}
className={classes.colOrders}
> >
<FormattedMessage defaultMessage="No. of Orders" /> <TableCellHeader
</TableCellHeader> direction={
sort.sort === CustomerListUrlSortField.orders
? getArrowDirection(sort.asc)
: undefined
}
textAlign="center"
onClick={() => onSort(CustomerListUrlSortField.orders)}
className={classes.colOrders}
>
<FormattedMessage defaultMessage="No. of Orders" />
</TableCellHeader>
</RequirePermissions>
</TableHead> </TableHead>
<TableFooter> <TableFooter>
<TableRow> <TableRow>
@ -155,14 +170,15 @@ const CustomerList: React.FC<CustomerListProps> = props => {
{getUserName(customer)} {getUserName(customer)}
</TableCell> </TableCell>
<TableCell className={classes.colEmail}> <TableCell className={classes.colEmail}>
{maybe<React.ReactNode>(() => customer.email, <Skeleton />)} {customer?.email ?? <Skeleton />}
</TableCell>
<TableCell className={classes.colOrders}>
{maybe<React.ReactNode>(
() => customer.orders.totalCount,
<Skeleton />
)}
</TableCell> </TableCell>
<RequirePermissions
requiredPermissions={[PermissionEnum.MANAGE_ORDERS]}
>
<TableCell className={classes.colOrders}>
{customer?.orders?.totalCount ?? <Skeleton />}
</TableCell>
</RequirePermissions>
</TableRow> </TableRow>
); );
}, },

View file

@ -1,4 +1,5 @@
import { Card } from "@material-ui/core"; import { Card } from "@material-ui/core";
import { useUserPermissions } from "@saleor/auth/hooks/useUserPermissions";
import Container from "@saleor/components/Container"; import Container from "@saleor/components/Container";
import FilterBar from "@saleor/components/FilterBar"; import FilterBar from "@saleor/components/FilterBar";
import PageHeader from "@saleor/components/PageHeader"; import PageHeader from "@saleor/components/PageHeader";
@ -48,7 +49,8 @@ const CustomerListPage: React.FC<CustomerListPageProps> = ({
}) => { }) => {
const intl = useIntl(); const intl = useIntl();
const structure = createFilterStructure(intl, filterOpts); const userPermissions = useUserPermissions();
const structure = createFilterStructure(intl, filterOpts, userPermissions);
return ( return (
<Container> <Container>

View file

@ -1,5 +1,8 @@
import { IFilter } from "@saleor/components/Filter"; import { IFilter } from "@saleor/components/Filter";
import { hasPermissions } from "@saleor/components/RequirePermissions";
import { User_userPermissions } from "@saleor/fragments/types/User";
import { FilterOpts, MinMax } from "@saleor/types"; import { FilterOpts, MinMax } from "@saleor/types";
import { PermissionEnum } from "@saleor/types/globalTypes";
import { import {
createDateField, createDateField,
createNumberField createNumberField
@ -28,7 +31,8 @@ const messages = defineMessages({
export function createFilterStructure( export function createFilterStructure(
intl: IntlShape, intl: IntlShape,
opts: CustomerListFilterOpts opts: CustomerListFilterOpts,
userPermissions: User_userPermissions[]
): IFilter<CustomerFilterKeys> { ): IFilter<CustomerFilterKeys> {
return [ return [
{ {
@ -45,7 +49,8 @@ export function createFilterStructure(
intl.formatMessage(messages.numberOfOrders), intl.formatMessage(messages.numberOfOrders),
opts.numberOfOrders.value opts.numberOfOrders.value
), ),
active: opts.numberOfOrders.active active: opts.numberOfOrders.active,
permissions: [PermissionEnum.MANAGE_ORDERS]
} }
]; ].filter(filter => hasPermissions(userPermissions, filter.permissions ?? []));
} }

View file

@ -2,12 +2,13 @@ import { Card, CardContent, Typography } from "@material-ui/core";
import CardTitle from "@saleor/components/CardTitle"; import CardTitle from "@saleor/components/CardTitle";
import { DateTime } from "@saleor/components/Date"; import { DateTime } from "@saleor/components/Date";
import { Hr } from "@saleor/components/Hr"; import { Hr } from "@saleor/components/Hr";
import RequirePermissions from "@saleor/components/RequirePermissions";
import Skeleton from "@saleor/components/Skeleton"; import Skeleton from "@saleor/components/Skeleton";
import { makeStyles } from "@saleor/macaw-ui"; import { makeStyles } from "@saleor/macaw-ui";
import { PermissionEnum } from "@saleor/types/globalTypes";
import React from "react"; import React from "react";
import { FormattedMessage, useIntl } from "react-intl"; import { FormattedMessage, useIntl } from "react-intl";
import { maybe } from "../../../misc";
import { CustomerDetails_user } from "../../types/CustomerDetails"; import { CustomerDetails_user } from "../../types/CustomerDetails";
const useStyles = makeStyles( const useStyles = makeStyles(
@ -44,26 +45,25 @@ const CustomerStats: React.FC<CustomerStatsProps> = props => {
<Typography className={classes.label} variant="caption"> <Typography className={classes.label} variant="caption">
<FormattedMessage defaultMessage="Last login" /> <FormattedMessage defaultMessage="Last login" />
</Typography> </Typography>
{maybe( {customer ? (
() => ( <Typography variant="h6" className={classes.value}>
<Typography variant="h6" className={classes.value}> {customer.lastLogin === null ? (
{customer.lastLogin === null ? ( "-"
"-" ) : (
) : ( <DateTime date={customer.lastLogin} />
<DateTime date={customer.lastLogin} /> )}
)} </Typography>
</Typography> ) : (
),
<Skeleton /> <Skeleton />
)} )}
</CardContent> </CardContent>
<Hr /> <RequirePermissions requiredPermissions={[PermissionEnum.MANAGE_ORDERS]}>
<CardContent> <Hr />
<Typography className={classes.label} variant="caption"> <CardContent>
<FormattedMessage defaultMessage="Last order" /> <Typography className={classes.label} variant="caption">
</Typography> <FormattedMessage defaultMessage="Last order" />
{maybe( </Typography>
() => ( {customer && customer.lastPlacedOrder ? (
<Typography variant="h6" className={classes.value}> <Typography variant="h6" className={classes.value}>
{customer.lastPlacedOrder.edges.length === 0 ? ( {customer.lastPlacedOrder.edges.length === 0 ? (
"-" "-"
@ -73,10 +73,11 @@ const CustomerStats: React.FC<CustomerStatsProps> = props => {
/> />
)} )}
</Typography> </Typography>
), ) : (
<Skeleton /> <Skeleton />
)} )}
</CardContent> </CardContent>
</RequirePermissions>
</Card> </Card>
); );
}; };

View file

@ -27,6 +27,7 @@ const customerList = gql`
$last: Int $last: Int
$filter: CustomerFilterInput $filter: CustomerFilterInput
$sort: UserSortingInput $sort: UserSortingInput
$PERMISSION_MANAGE_ORDERS: Boolean!
) { ) {
customers( customers(
after: $after after: $after
@ -39,7 +40,7 @@ const customerList = gql`
edges { edges {
node { node {
...CustomerFragment ...CustomerFragment
orders { orders @include(if: $PERMISSION_MANAGE_ORDERS) {
totalCount totalCount
} }
} }
@ -60,10 +61,10 @@ export const useCustomerListQuery = makeQuery<
const customerDetails = gql` const customerDetails = gql`
${customerDetailsFragment} ${customerDetailsFragment}
query CustomerDetails($id: ID!) { query CustomerDetails($id: ID!, $PERMISSION_MANAGE_ORDERS: Boolean!) {
user(id: $id) { user(id: $id) {
...CustomerDetailsFragment ...CustomerDetailsFragment
orders(last: 5) { orders(last: 5) @include(if: $PERMISSION_MANAGE_ORDERS) {
edges { edges {
node { node {
id id
@ -79,7 +80,7 @@ const customerDetails = gql`
} }
} }
} }
lastPlacedOrder: orders(last: 1) { lastPlacedOrder: orders(last: 1) @include(if: $PERMISSION_MANAGE_ORDERS) {
edges { edges {
node { node {
id id

View file

@ -135,4 +135,5 @@ export interface CustomerDetails {
export interface CustomerDetailsVariables { export interface CustomerDetailsVariables {
id: string; id: string;
PERMISSION_MANAGE_ORDERS: boolean;
} }

View file

@ -53,4 +53,5 @@ export interface ListCustomersVariables {
last?: number | null; last?: number | null;
filter?: CustomerFilterInput | null; filter?: CustomerFilterInput | null;
sort?: UserSortingInput | null; sort?: UserSortingInput | null;
PERMISSION_MANAGE_ORDERS: boolean;
} }

View file

@ -1,6 +1,7 @@
import { createFilterStructure } from "@saleor/customers/components/CustomerListPage"; import { createFilterStructure } from "@saleor/customers/components/CustomerListPage";
import { CustomerListUrlFilters } from "@saleor/customers/urls"; import { CustomerListUrlFilters } from "@saleor/customers/urls";
import { date } from "@saleor/fixtures"; import { date } from "@saleor/fixtures";
import { PermissionEnum } from "@saleor/types/globalTypes";
import { getFilterQueryParams } from "@saleor/utils/filters"; import { getFilterQueryParams } from "@saleor/utils/filters";
import { stringifyQs } from "@saleor/utils/urls"; import { stringifyQs } from "@saleor/utils/urls";
import { getExistingKeys, setFilterOptsStatus } from "@test/filters"; import { getExistingKeys, setFilterOptsStatus } from "@test/filters";
@ -31,22 +32,37 @@ describe("Filtering query params", () => {
describe("Filtering URL params", () => { describe("Filtering URL params", () => {
const intl = createIntl(config); const intl = createIntl(config);
const filters = createFilterStructure(intl, { const filters = createFilterStructure(
joined: { intl,
active: false, {
value: { joined: {
max: date.to, active: false,
min: date.from value: {
max: date.to,
min: date.from
}
},
numberOfOrders: {
active: false,
value: {
max: "5",
min: "1"
}
} }
}, },
numberOfOrders: { [
active: false, {
value: { code: PermissionEnum.MANAGE_USERS,
max: "5", name: "Manage customers.",
min: "1" __typename: "UserPermission"
},
{
code: PermissionEnum.MANAGE_ORDERS,
name: "Manage orders..",
__typename: "UserPermission"
} }
} ]
}); );
it("should be empty if no active filters", () => { it("should be empty if no active filters", () => {
const filterQueryParams = getFilterQueryParams( const filterQueryParams = getFilterQueryParams(

View file

@ -10,7 +10,6 @@ import RequirePermissions from "@saleor/components/RequirePermissions";
import ResponsiveTable from "@saleor/components/ResponsiveTable"; import ResponsiveTable from "@saleor/components/ResponsiveTable";
import Skeleton from "@saleor/components/Skeleton"; import Skeleton from "@saleor/components/Skeleton";
import { makeStyles } from "@saleor/macaw-ui"; import { makeStyles } from "@saleor/macaw-ui";
import { UserPermissionProps } from "@saleor/types";
import { PermissionEnum } from "@saleor/types/globalTypes"; import { PermissionEnum } from "@saleor/types/globalTypes";
import React from "react"; import React from "react";
import { useIntl } from "react-intl"; import { useIntl } from "react-intl";
@ -33,7 +32,7 @@ const useStyles = makeStyles(
{ name: "HomeNotificationTable" } { name: "HomeNotificationTable" }
); );
interface HomeNotificationTableProps extends UserPermissionProps { interface HomeNotificationTableProps {
ordersToCapture: number; ordersToCapture: number;
ordersToFulfill: number; ordersToFulfill: number;
productsOutOfStock: number; productsOutOfStock: number;
@ -53,7 +52,6 @@ const HomeNotificationTable: React.FC<HomeNotificationTableProps> = props => {
ordersToCapture, ordersToCapture,
ordersToFulfill, ordersToFulfill,
productsOutOfStock, productsOutOfStock,
userPermissions,
noChannel noChannel
} = props; } = props;
@ -67,7 +65,6 @@ const HomeNotificationTable: React.FC<HomeNotificationTableProps> = props => {
<TableBody className={classes.tableRow}> <TableBody className={classes.tableRow}>
{noChannel && ( {noChannel && (
<RequirePermissions <RequirePermissions
userPermissions={userPermissions}
requiredPermissions={[PermissionEnum.MANAGE_CHANNELS]} requiredPermissions={[PermissionEnum.MANAGE_CHANNELS]}
> >
<TableRow hover={true} onClick={onCreateNewChannelClick}> <TableRow hover={true} onClick={onCreateNewChannelClick}>
@ -83,7 +80,6 @@ const HomeNotificationTable: React.FC<HomeNotificationTableProps> = props => {
</RequirePermissions> </RequirePermissions>
)} )}
<RequirePermissions <RequirePermissions
userPermissions={userPermissions}
requiredPermissions={[PermissionEnum.MANAGE_ORDERS]} requiredPermissions={[PermissionEnum.MANAGE_ORDERS]}
> >
<TableRow hover={true} onClick={onOrdersToFulfillClick}> <TableRow hover={true} onClick={onOrdersToFulfillClick}>
@ -128,7 +124,6 @@ const HomeNotificationTable: React.FC<HomeNotificationTableProps> = props => {
</TableRow> </TableRow>
</RequirePermissions> </RequirePermissions>
<RequirePermissions <RequirePermissions
userPermissions={userPermissions}
requiredPermissions={[PermissionEnum.MANAGE_PRODUCTS]} requiredPermissions={[PermissionEnum.MANAGE_PRODUCTS]}
> >
<TableRow hover={true} onClick={onProductsOutOfStockClick}> <TableRow hover={true} onClick={onProductsOutOfStockClick}>

View file

@ -5,7 +5,6 @@ import Money from "@saleor/components/Money";
import RequirePermissions from "@saleor/components/RequirePermissions"; import RequirePermissions from "@saleor/components/RequirePermissions";
import Skeleton from "@saleor/components/Skeleton"; import Skeleton from "@saleor/components/Skeleton";
import { makeStyles } from "@saleor/macaw-ui"; import { makeStyles } from "@saleor/macaw-ui";
import { UserPermissionProps } from "@saleor/types";
import { PermissionEnum } from "@saleor/types/globalTypes"; import { PermissionEnum } from "@saleor/types/globalTypes";
import React from "react"; import React from "react";
@ -44,7 +43,7 @@ const useStyles = makeStyles(
{ name: "HomePage" } { name: "HomePage" }
); );
export interface HomePageProps extends UserPermissionProps { export interface HomePageProps {
activities: Home_activities_edges_node[]; activities: Home_activities_edges_node[];
orders: number | null; orders: number | null;
ordersToCapture: number | null; ordersToCapture: number | null;
@ -76,7 +75,6 @@ const HomePage: React.FC<HomePageProps> = props => {
ordersToCapture = 0, ordersToCapture = 0,
ordersToFulfill = 0, ordersToFulfill = 0,
productsOutOfStock = 0, productsOutOfStock = 0,
userPermissions = [],
noChannel noChannel
} = props; } = props;
@ -89,7 +87,6 @@ const HomePage: React.FC<HomePageProps> = props => {
<Grid> <Grid>
<div> <div>
<RequirePermissions <RequirePermissions
userPermissions={userPermissions}
requiredPermissions={[PermissionEnum.MANAGE_ORDERS]} requiredPermissions={[PermissionEnum.MANAGE_ORDERS]}
> >
<div className={classes.cardContainer}> <div className={classes.cardContainer}>
@ -141,13 +138,11 @@ const HomePage: React.FC<HomePageProps> = props => {
ordersToCapture={ordersToCapture} ordersToCapture={ordersToCapture}
ordersToFulfill={ordersToFulfill} ordersToFulfill={ordersToFulfill}
productsOutOfStock={productsOutOfStock} productsOutOfStock={productsOutOfStock}
userPermissions={userPermissions}
noChannel={noChannel} noChannel={noChannel}
/> />
<CardSpacer /> <CardSpacer />
{topProducts && ( {topProducts && (
<RequirePermissions <RequirePermissions
userPermissions={userPermissions}
requiredPermissions={[ requiredPermissions={[
PermissionEnum.MANAGE_ORDERS, PermissionEnum.MANAGE_ORDERS,
PermissionEnum.MANAGE_PRODUCTS PermissionEnum.MANAGE_PRODUCTS
@ -165,7 +160,6 @@ const HomePage: React.FC<HomePageProps> = props => {
{activities && ( {activities && (
<div> <div>
<RequirePermissions <RequirePermissions
userPermissions={userPermissions}
requiredPermissions={[PermissionEnum.MANAGE_ORDERS]} requiredPermissions={[PermissionEnum.MANAGE_ORDERS]}
> >
<HomeActivityCard <HomeActivityCard

View file

@ -65,7 +65,6 @@ const HomeSection = () => {
ordersToFulfill={data?.ordersToFulfill?.totalCount} ordersToFulfill={data?.ordersToFulfill?.totalCount}
productsOutOfStock={data?.productsOutOfStock.totalCount} productsOutOfStock={data?.productsOutOfStock.totalCount}
userName={getUserName(user, true)} userName={getUserName(user, true)}
userPermissions={user?.userPermissions}
noChannel={noChannel} noChannel={noChannel}
/> />
); );

View file

@ -12,7 +12,7 @@ import useStateFromProps from "@saleor/hooks/useStateFromProps";
import { buttonMessages } from "@saleor/intl"; import { buttonMessages } from "@saleor/intl";
import { Button, makeStyles } from "@saleor/macaw-ui"; import { Button, makeStyles } from "@saleor/macaw-ui";
import { SearchCustomers_search_edges_node } from "@saleor/searches/types/SearchCustomers"; import { SearchCustomers_search_edges_node } from "@saleor/searches/types/SearchCustomers";
import { FetchMoreProps, UserPermissionProps } from "@saleor/types"; import { FetchMoreProps } from "@saleor/types";
import { PermissionEnum } from "@saleor/types/globalTypes"; import { PermissionEnum } from "@saleor/types/globalTypes";
import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler"; import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler";
import React from "react"; import React from "react";
@ -55,9 +55,7 @@ export interface CustomerEditData {
prevUserEmail?: string; prevUserEmail?: string;
} }
export interface OrderCustomerProps export interface OrderCustomerProps extends Partial<FetchMoreProps> {
extends Partial<FetchMoreProps>,
UserPermissionProps {
order: OrderDetails_order; order: OrderDetails_order;
users?: SearchCustomers_search_edges_node[]; users?: SearchCustomers_search_edges_node[];
loading?: boolean; loading?: boolean;
@ -79,7 +77,6 @@ const OrderCustomer: React.FC<OrderCustomerProps> = props => {
loading, loading,
order, order,
users, users,
userPermissions,
onCustomerEdit, onCustomerEdit,
onBillingAddressEdit, onBillingAddressEdit,
onFetchMore: onFetchMoreUsers, onFetchMore: onFetchMoreUsers,
@ -131,7 +128,6 @@ const OrderCustomer: React.FC<OrderCustomerProps> = props => {
toolbar={ toolbar={
!!canEditCustomer && ( !!canEditCustomer && (
<RequirePermissions <RequirePermissions
userPermissions={userPermissions}
requiredPermissions={[PermissionEnum.MANAGE_ORDERS]} requiredPermissions={[PermissionEnum.MANAGE_ORDERS]}
> >
<Button <Button
@ -209,7 +205,6 @@ const OrderCustomer: React.FC<OrderCustomerProps> = props => {
{user.email} {user.email}
</Typography> </Typography>
<RequirePermissions <RequirePermissions
userPermissions={userPermissions}
requiredPermissions={[PermissionEnum.MANAGE_USERS]} requiredPermissions={[PermissionEnum.MANAGE_USERS]}
> >
<div> <div>

View file

@ -15,7 +15,6 @@ import { ConfirmButtonTransitionState } from "@saleor/macaw-ui";
import { Backlink } from "@saleor/macaw-ui"; import { Backlink } from "@saleor/macaw-ui";
import { makeStyles } from "@saleor/macaw-ui"; import { makeStyles } from "@saleor/macaw-ui";
import OrderChannelSectionCard from "@saleor/orders/components/OrderChannelSectionCard"; import OrderChannelSectionCard from "@saleor/orders/components/OrderChannelSectionCard";
import { UserPermissionProps } from "@saleor/types";
import { mapMetadataItemToInput } from "@saleor/utils/maps"; import { mapMetadataItemToInput } from "@saleor/utils/maps";
import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger"; import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger";
import React from "react"; import React from "react";
@ -55,7 +54,7 @@ const useStyles = makeStyles(
} }
); );
export interface OrderDetailsPageProps extends UserPermissionProps { export interface OrderDetailsPageProps {
order: OrderDetails_order; order: OrderDetails_order;
shop: OrderDetails_shop; shop: OrderDetails_shop;
shippingMethods?: Array<{ shippingMethods?: Array<{
@ -114,7 +113,6 @@ const OrderDetailsPage: React.FC<OrderDetailsPageProps> = props => {
order, order,
shop, shop,
saveButtonBarState, saveButtonBarState,
userPermissions,
onBack, onBack,
onBillingAddressEdit, onBillingAddressEdit,
onFulfillmentApprove, onFulfillmentApprove,
@ -299,7 +297,6 @@ const OrderDetailsPage: React.FC<OrderDetailsPageProps> = props => {
canEditAddresses={canEditAddresses} canEditAddresses={canEditAddresses}
canEditCustomer={false} canEditCustomer={false}
order={order} order={order}
userPermissions={userPermissions}
onBillingAddressEdit={onBillingAddressEdit} onBillingAddressEdit={onBillingAddressEdit}
onShippingAddressEdit={onShippingAddressEdit} onShippingAddressEdit={onShippingAddressEdit}
onProfileView={onProfileView} onProfileView={onProfileView}

View file

@ -14,7 +14,7 @@ import { Backlink } from "@saleor/macaw-ui";
import { makeStyles } from "@saleor/macaw-ui"; import { makeStyles } from "@saleor/macaw-ui";
import DraftOrderChannelSectionCard from "@saleor/orders/components/DraftOrderChannelSectionCard"; import DraftOrderChannelSectionCard from "@saleor/orders/components/DraftOrderChannelSectionCard";
import { SearchCustomers_search_edges_node } from "@saleor/searches/types/SearchCustomers"; import { SearchCustomers_search_edges_node } from "@saleor/searches/types/SearchCustomers";
import { FetchMoreProps, UserPermissionProps } from "@saleor/types"; import { FetchMoreProps } from "@saleor/types";
import React from "react"; import React from "react";
import { useIntl } from "react-intl"; import { useIntl } from "react-intl";
@ -37,9 +37,7 @@ const useStyles = makeStyles(
{ name: "OrderDraftPage" } { name: "OrderDraftPage" }
); );
export interface OrderDraftPageProps export interface OrderDraftPageProps extends FetchMoreProps {
extends FetchMoreProps,
UserPermissionProps {
disabled: boolean; disabled: boolean;
order: OrderDetails_order; order: OrderDetails_order;
users: SearchCustomers_search_edges_node[]; users: SearchCustomers_search_edges_node[];
@ -85,8 +83,7 @@ const OrderDraftPage: React.FC<OrderDraftPageProps> = props => {
onProfileView, onProfileView,
order, order,
users, users,
usersLoading, usersLoading
userPermissions
} = props; } = props;
const classes = useStyles(props); const classes = useStyles(props);
@ -147,7 +144,6 @@ const OrderDraftPage: React.FC<OrderDraftPageProps> = props => {
loading={usersLoading} loading={usersLoading}
order={order} order={order}
users={users} users={users}
userPermissions={userPermissions}
onBillingAddressEdit={onBillingAddressEdit} onBillingAddressEdit={onBillingAddressEdit}
onCustomerEdit={onCustomerEdit} onCustomerEdit={onCustomerEdit}
onFetchMore={onFetchMore} onFetchMore={onFetchMore}

View file

@ -1,4 +1,3 @@
import { useUser } from "@saleor/auth";
import { WindowTitle } from "@saleor/components/WindowTitle"; import { WindowTitle } from "@saleor/components/WindowTitle";
import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config"; import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config";
import { useCustomerAddressesQuery } from "@saleor/customers/queries"; import { useCustomerAddressesQuery } from "@saleor/customers/queries";
@ -84,7 +83,6 @@ export const OrderDraftDetails: React.FC<OrderDraftDetailsProps> = ({
}) => { }) => {
const order = data.order; const order = data.order;
const navigate = useNavigator(); const navigate = useNavigator();
const { user } = useUser();
const { const {
loadMore, loadMore,
@ -214,7 +212,6 @@ export const OrderDraftDetails: React.FC<OrderDraftDetailsProps> = ({
} }
saveButtonBarState="default" saveButtonBarState="default"
onProfileView={() => navigate(customerUrl(order.user.id))} onProfileView={() => navigate(customerUrl(order.user.id))}
userPermissions={user?.userPermissions || []}
/> />
</OrderLineDiscountProvider> </OrderLineDiscountProvider>
</OrderDiscountProvider> </OrderDiscountProvider>

View file

@ -1,4 +1,3 @@
import { useUser } from "@saleor/auth";
import { WindowTitle } from "@saleor/components/WindowTitle"; import { WindowTitle } from "@saleor/components/WindowTitle";
import { useCustomerAddressesQuery } from "@saleor/customers/queries"; import { useCustomerAddressesQuery } from "@saleor/customers/queries";
import useNavigator from "@saleor/hooks/useNavigator"; import useNavigator from "@saleor/hooks/useNavigator";
@ -95,7 +94,6 @@ export const OrderNormalDetails: React.FC<OrderNormalDetailsProps> = ({
const order = data?.order; const order = data?.order;
const shop = data?.shop; const shop = data?.shop;
const navigate = useNavigator(); const navigate = useNavigator();
const { user } = useUser();
const warehouses = useWarehouseList({ const warehouses = useWarehouseList({
displayLoader: true, displayLoader: true,
@ -168,7 +166,6 @@ export const OrderNormalDetails: React.FC<OrderNormalDetailsProps> = ({
] ]
)} )}
shippingMethods={data?.order?.shippingMethods || []} shippingMethods={data?.order?.shippingMethods || []}
userPermissions={user?.userPermissions || []}
onOrderCancel={() => openModal("cancel")} onOrderCancel={() => openModal("cancel")}
onOrderFulfill={() => navigate(orderFulfillUrl(id))} onOrderFulfill={() => navigate(orderFulfillUrl(id))}
onFulfillmentApprove={fulfillmentId => onFulfillmentApprove={fulfillmentId =>

View file

@ -1,4 +1,3 @@
import { useUser } from "@saleor/auth";
import { WindowTitle } from "@saleor/components/WindowTitle"; import { WindowTitle } from "@saleor/components/WindowTitle";
import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config"; import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config";
import { useCustomerAddressesQuery } from "@saleor/customers/queries"; import { useCustomerAddressesQuery } from "@saleor/customers/queries";
@ -109,7 +108,6 @@ export const OrderUnconfirmedDetails: React.FC<OrderUnconfirmedDetailsProps> = (
const order = data.order; const order = data.order;
const shop = data.shop; const shop = data.shop;
const navigate = useNavigator(); const navigate = useNavigator();
const { user } = useUser();
const { const {
loadMore, loadMore,
@ -201,7 +199,6 @@ export const OrderUnconfirmedDetails: React.FC<OrderUnconfirmedDetailsProps> = (
] ]
)} )}
shippingMethods={data?.order?.shippingMethods || []} shippingMethods={data?.order?.shippingMethods || []}
userPermissions={user?.userPermissions || []}
onOrderCancel={() => openModal("cancel")} onOrderCancel={() => openModal("cancel")}
onOrderFulfill={() => navigate(orderFulfillUrl(id))} onOrderFulfill={() => navigate(orderFulfillUrl(id))}
onFulfillmentApprove={fulfillmentId => onFulfillmentApprove={fulfillmentId =>

View file

@ -28,7 +28,6 @@ export interface ShippingZonesListPageProps
const ShippingZonesListPage: React.FC<ShippingZonesListPageProps> = ({ const ShippingZonesListPage: React.FC<ShippingZonesListPageProps> = ({
defaultWeightUnit, defaultWeightUnit,
disabled, disabled,
userPermissions,
onBack, onBack,
onSubmit, onSubmit,
...listProps ...listProps
@ -52,7 +51,6 @@ const ShippingZonesListPage: React.FC<ShippingZonesListPageProps> = ({
</div> </div>
<div> <div>
<RequirePermissions <RequirePermissions
userPermissions={userPermissions}
requiredPermissions={[PermissionEnum.MANAGE_SETTINGS]} requiredPermissions={[PermissionEnum.MANAGE_SETTINGS]}
> >
<ShippingWeightUnitForm <ShippingWeightUnitForm

View file

@ -73323,7 +73323,7 @@ exports[`Storyshots Views / Customers / Customer list default 1`] = `
> >
<td <td
class="MuiTableCell-root-id MuiTableCell-footer-id" class="MuiTableCell-root-id MuiTableCell-footer-id"
colspan="4" colspan="3"
> >
<div <div
class="MuiToolbar-root-id MuiToolbar-regular-id Pagination-toolbar-id" class="MuiToolbar-root-id MuiToolbar-regular-id Pagination-toolbar-id"
@ -74994,7 +74994,7 @@ exports[`Storyshots Views / Customers / Customer list loading 1`] = `
> >
<td <td
class="MuiTableCell-root-id MuiTableCell-footer-id" class="MuiTableCell-root-id MuiTableCell-footer-id"
colspan="4" colspan="3"
> >
<div <div
class="MuiToolbar-root-id MuiToolbar-regular-id Pagination-toolbar-id" class="MuiToolbar-root-id MuiToolbar-regular-id Pagination-toolbar-id"
@ -75348,7 +75348,7 @@ exports[`Storyshots Views / Customers / Customer list no data 1`] = `
> >
<td <td
class="MuiTableCell-root-id MuiTableCell-footer-id" class="MuiTableCell-root-id MuiTableCell-footer-id"
colspan="4" colspan="3"
> >
<div <div
class="MuiToolbar-root-id MuiToolbar-regular-id Pagination-toolbar-id" class="MuiToolbar-root-id MuiToolbar-regular-id Pagination-toolbar-id"
@ -75420,7 +75420,7 @@ exports[`Storyshots Views / Customers / Customer list no data 1`] = `
> >
<td <td
class="MuiTableCell-root-id MuiTableCell-body-id" class="MuiTableCell-root-id MuiTableCell-body-id"
colspan="4" colspan="3"
> >
No customers found No customers found
</td> </td>
@ -235532,107 +235532,7 @@ exports[`Storyshots Views / Shipping / Shipping zones list default 1`] = `
</div> </div>
</div> </div>
</div> </div>
<div> <div />
<form>
<div
class="MuiPaper-root-id MuiCard-root-id MuiPaper-elevation0-id MuiPaper-rounded-id"
>
<div
class="MuiCardHeader-root-id"
>
<div
class="MuiCardHeader-content-id"
>
<span
class="MuiTypography-root-id MuiCardHeader-title-id MuiTypography-h5-id MuiTypography-displayBlock-id"
>
Configuration
</span>
</div>
</div>
<div
class="MuiCardContent-root-id"
>
<div
class="MuiFormControl-root-id SingleSelectField-formControl-id"
>
<label
class="MuiFormLabel-root-id MuiInputLabel-root-id SingleSelectField-label-id MuiInputLabel-formControl-id MuiInputLabel-animated-id MuiInputLabel-shrink-id MuiInputLabel-filled-id MuiFormLabel-filled-id"
data-shrink="true"
>
Shipping Weight Unit
</label>
<div
class="MuiInputBase-root-id MuiOutlinedInput-root-id MuiInputBase-fullWidth-id MuiInputBase-formControl-id"
>
<div
aria-haspopup="listbox"
aria-labelledby="mui-component-select-unit"
class="MuiSelect-root-id MuiSelect-select-id MuiSelect-selectMenu-id MuiSelect-outlined-id MuiInputBase-input-id MuiOutlinedInput-input-id"
id="mui-component-select-unit"
role="button"
tabindex="0"
>
KG
</div>
<input
aria-hidden="true"
class="MuiSelect-nativeInput-id"
name="unit"
tabindex="-1"
value="KG"
/>
<svg
aria-hidden="true"
class="MuiSvgIcon-root-id MuiSelect-icon-id MuiSelect-iconOutlined-id"
focusable="false"
viewBox="0 0 24 24"
>
<path
d="M7 10l5 5 5-5z"
/>
</svg>
<fieldset
aria-hidden="true"
class="PrivateNotchedOutline-root-id MuiOutlinedInput-notchedOutline-id"
style="padding-left:8px"
>
<legend
class="PrivateNotchedOutline-legend-id"
style="width:143px"
>
<span>
</span>
</legend>
</fieldset>
</div>
<p
class="MuiFormHelperText-root-id MuiFormHelperText-contained-id MuiFormHelperText-filled-id"
>
This unit will be used as default shipping weight
</p>
</div>
</div>
<div
class="MuiCardActions-root-id MuiCardActions-spacing-id"
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-outlined-id MuiButton-outlinedPrimary-id MuiButton-outlinedSizeSmall-id MuiButton-sizeSmall-id"
data-test-id="save-unit"
tabindex="0"
type="button"
>
<span
class="MuiButton-label-id"
>
Save
</span>
</button>
</div>
</div>
</form>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -235953,107 +235853,7 @@ exports[`Storyshots Views / Shipping / Shipping zones list loading 1`] = `
</div> </div>
</div> </div>
</div> </div>
<div> <div />
<form>
<div
class="MuiPaper-root-id MuiCard-root-id MuiPaper-elevation0-id MuiPaper-rounded-id"
>
<div
class="MuiCardHeader-root-id"
>
<div
class="MuiCardHeader-content-id"
>
<span
class="MuiTypography-root-id MuiCardHeader-title-id MuiTypography-h5-id MuiTypography-displayBlock-id"
>
Configuration
</span>
</div>
</div>
<div
class="MuiCardContent-root-id"
>
<div
class="MuiFormControl-root-id SingleSelectField-formControl-id"
>
<label
class="MuiFormLabel-root-id MuiInputLabel-root-id SingleSelectField-label-id MuiInputLabel-formControl-id MuiInputLabel-animated-id MuiInputLabel-shrink-id MuiInputLabel-filled-id MuiFormLabel-disabled-id MuiInputLabel-disabled-id MuiFormLabel-filled-id"
data-shrink="true"
>
Shipping Weight Unit
</label>
<div
class="MuiInputBase-root-id MuiOutlinedInput-root-id MuiInputBase-disabled-id MuiOutlinedInput-disabled-id MuiInputBase-fullWidth-id MuiInputBase-formControl-id"
>
<div
aria-disabled="true"
aria-haspopup="listbox"
aria-labelledby="mui-component-select-unit"
class="MuiSelect-root-id MuiSelect-select-id MuiSelect-selectMenu-id MuiSelect-outlined-id MuiInputBase-input-id MuiOutlinedInput-input-id MuiInputBase-disabled-id MuiOutlinedInput-disabled-id MuiSelect-disabled-id"
id="mui-component-select-unit"
role="button"
>
KG
</div>
<input
aria-hidden="true"
class="MuiSelect-nativeInput-id"
name="unit"
tabindex="-1"
value="KG"
/>
<svg
aria-hidden="true"
class="MuiSvgIcon-root-id MuiSelect-icon-id MuiSelect-iconOutlined-id MuiSelect-disabled-id"
focusable="false"
viewBox="0 0 24 24"
>
<path
d="M7 10l5 5 5-5z"
/>
</svg>
<fieldset
aria-hidden="true"
class="PrivateNotchedOutline-root-id MuiOutlinedInput-notchedOutline-id"
style="padding-left:8px"
>
<legend
class="PrivateNotchedOutline-legend-id"
style="width:143px"
>
<span>
</span>
</legend>
</fieldset>
</div>
<p
class="MuiFormHelperText-root-id MuiFormHelperText-contained-id MuiFormHelperText-disabled-id MuiFormHelperText-filled-id"
>
This unit will be used as default shipping weight
</p>
</div>
</div>
<div
class="MuiCardActions-root-id MuiCardActions-spacing-id"
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-outlined-id MuiButton-outlinedPrimary-id MuiButton-outlinedSizeSmall-id MuiButton-sizeSmall-id"
data-test-id="save-unit"
tabindex="0"
type="button"
>
<span
class="MuiButton-label-id"
>
Save
</span>
</button>
</div>
</div>
</form>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -236255,107 +236055,7 @@ exports[`Storyshots Views / Shipping / Shipping zones list no data 1`] = `
</div> </div>
</div> </div>
</div> </div>
<div> <div />
<form>
<div
class="MuiPaper-root-id MuiCard-root-id MuiPaper-elevation0-id MuiPaper-rounded-id"
>
<div
class="MuiCardHeader-root-id"
>
<div
class="MuiCardHeader-content-id"
>
<span
class="MuiTypography-root-id MuiCardHeader-title-id MuiTypography-h5-id MuiTypography-displayBlock-id"
>
Configuration
</span>
</div>
</div>
<div
class="MuiCardContent-root-id"
>
<div
class="MuiFormControl-root-id SingleSelectField-formControl-id"
>
<label
class="MuiFormLabel-root-id MuiInputLabel-root-id SingleSelectField-label-id MuiInputLabel-formControl-id MuiInputLabel-animated-id MuiInputLabel-shrink-id MuiInputLabel-filled-id MuiFormLabel-filled-id"
data-shrink="true"
>
Shipping Weight Unit
</label>
<div
class="MuiInputBase-root-id MuiOutlinedInput-root-id MuiInputBase-fullWidth-id MuiInputBase-formControl-id"
>
<div
aria-haspopup="listbox"
aria-labelledby="mui-component-select-unit"
class="MuiSelect-root-id MuiSelect-select-id MuiSelect-selectMenu-id MuiSelect-outlined-id MuiInputBase-input-id MuiOutlinedInput-input-id"
id="mui-component-select-unit"
role="button"
tabindex="0"
>
KG
</div>
<input
aria-hidden="true"
class="MuiSelect-nativeInput-id"
name="unit"
tabindex="-1"
value="KG"
/>
<svg
aria-hidden="true"
class="MuiSvgIcon-root-id MuiSelect-icon-id MuiSelect-iconOutlined-id"
focusable="false"
viewBox="0 0 24 24"
>
<path
d="M7 10l5 5 5-5z"
/>
</svg>
<fieldset
aria-hidden="true"
class="PrivateNotchedOutline-root-id MuiOutlinedInput-notchedOutline-id"
style="padding-left:8px"
>
<legend
class="PrivateNotchedOutline-legend-id"
style="width:143px"
>
<span>
</span>
</legend>
</fieldset>
</div>
<p
class="MuiFormHelperText-root-id MuiFormHelperText-contained-id MuiFormHelperText-filled-id"
>
This unit will be used as default shipping weight
</p>
</div>
</div>
<div
class="MuiCardActions-root-id MuiCardActions-spacing-id"
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-outlined-id MuiButton-outlinedPrimary-id MuiButton-outlinedSizeSmall-id MuiButton-sizeSmall-id"
data-test-id="save-unit"
tabindex="0"
type="button"
>
<span
class="MuiButton-label-id"
>
Save
</span>
</button>
</div>
</div>
</form>
</div>
</div> </div>
</div> </div>
</div> </div>

View file

@ -1,8 +1,15 @@
import ActionDialog from "@saleor/components/ActionDialog"; import ActionDialogComponent from "@saleor/components/ActionDialog";
import { storiesOf } from "@storybook/react"; import { storiesOf } from "@storybook/react";
import React from "react"; import React from "react";
import Decorator from "../../Decorator"; import Decorator from "../../Decorator";
import { MockedUserProvider } from "../customers/MockedUserProvider";
const ActionDialog = props => (
<MockedUserProvider>
<ActionDialogComponent {...props} />
</MockedUserProvider>
);
storiesOf("Generics / ActionDialog", module) storiesOf("Generics / ActionDialog", module)
.addDecorator(Decorator) .addDecorator(Decorator)

View file

@ -2,11 +2,12 @@ import { AccountErrorCode } from "@saleor/types/globalTypes";
import { storiesOf } from "@storybook/react"; import { storiesOf } from "@storybook/react";
import React from "react"; import React from "react";
import CustomerDetailsPage, { import CustomerDetailsPageComponent, {
CustomerDetailsPageProps CustomerDetailsPageProps
} from "../../../customers/components/CustomerDetailsPage"; } from "../../../customers/components/CustomerDetailsPage";
import { customer } from "../../../customers/fixtures"; import { customer } from "../../../customers/fixtures";
import Decorator from "../../Decorator"; import Decorator from "../../Decorator";
import { MockedUserProvider } from "./MockedUserProvider";
const props: Omit<CustomerDetailsPageProps, "classes"> = { const props: Omit<CustomerDetailsPageProps, "classes"> = {
customer, customer,
@ -28,6 +29,12 @@ interface CustomerDetailsPageErrors {
note: string; note: string;
} }
const CustomerDetailsPage = props => (
<MockedUserProvider>
<CustomerDetailsPageComponent {...props} />
</MockedUserProvider>
);
storiesOf("Views / Customers / Customer details", module) storiesOf("Views / Customers / Customer details", module)
.addDecorator(Decorator) .addDecorator(Decorator)
.add("default", () => <CustomerDetailsPage {...props} />) .add("default", () => <CustomerDetailsPage {...props} />)

View file

@ -2,7 +2,7 @@ import { CustomerListUrlSortField } from "@saleor/customers/urls";
import { storiesOf } from "@storybook/react"; import { storiesOf } from "@storybook/react";
import React from "react"; import React from "react";
import CustomerListPage, { import CustomerListPageComponent, {
CustomerListPageProps CustomerListPageProps
} from "../../../customers/components/CustomerListPage"; } from "../../../customers/components/CustomerListPage";
import { customerList } from "../../../customers/fixtures"; import { customerList } from "../../../customers/fixtures";
@ -15,6 +15,7 @@ import {
tabPageProps tabPageProps
} from "../../../fixtures"; } from "../../../fixtures";
import Decorator from "../../Decorator"; import Decorator from "../../Decorator";
import { MockedUserProvider } from "./MockedUserProvider";
const props: CustomerListPageProps = { const props: CustomerListPageProps = {
...filterPageProps, ...filterPageProps,
@ -46,6 +47,12 @@ const props: CustomerListPageProps = {
} }
}; };
const CustomerListPage = props => (
<MockedUserProvider>
<CustomerListPageComponent {...props} />
</MockedUserProvider>
);
storiesOf("Views / Customers / Customer list", module) storiesOf("Views / Customers / Customer list", module)
.addDecorator(Decorator) .addDecorator(Decorator)
.add("default", () => <CustomerListPage {...props} />) .add("default", () => <CustomerListPage {...props} />)

View file

@ -0,0 +1,31 @@
import { UserContext } from "@saleor/auth";
import { adminUserPermissions } from "@saleor/fixtures";
import { User_userPermissions } from "@saleor/fragments/types/User";
import * as React from "react";
export const MockedUserProvider: React.FC<{
customPermissions?: User_userPermissions[];
}> = ({ customPermissions, children }) => (
<UserContext.Provider
value={{
login: undefined,
loginByExternalPlugin: undefined,
logout: undefined,
requestLoginByExternalPlugin: undefined,
authenticating: false,
authenticated: false,
user: {
id: "0",
email: "email@email.me",
firstName: "user",
lastName: "user",
isStaff: true,
userPermissions: customPermissions ?? adminUserPermissions,
avatar: null,
__typename: "User"
}
}}
>
{children}
</UserContext.Provider>
);

View file

@ -5,9 +5,12 @@ import { mapEdgesToItems } from "@saleor/utils/maps";
import { storiesOf } from "@storybook/react"; import { storiesOf } from "@storybook/react";
import React from "react"; import React from "react";
import HomePage, { HomePageProps } from "../../../home/components/HomePage"; import HomePageComponent, {
HomePageProps
} from "../../../home/components/HomePage";
import { shop as shopFixture } from "../../../home/fixtures"; import { shop as shopFixture } from "../../../home/fixtures";
import Decorator from "../../Decorator"; import Decorator from "../../Decorator";
import { MockedUserProvider } from "../customers/MockedUserProvider";
const shop = shopFixture(placeholderImage); const shop = shopFixture(placeholderImage);
@ -25,8 +28,17 @@ const homePageProps: Omit<HomePageProps, "classes"> = {
productsOutOfStock: shop.productsOutOfStock.totalCount, productsOutOfStock: shop.productsOutOfStock.totalCount,
sales: shop.salesToday.gross, sales: shop.salesToday.gross,
topProducts: mapEdgesToItems(shop.productTopToday), topProducts: mapEdgesToItems(shop.productTopToday),
userName: "admin@example.com", userName: "admin@example.com"
userPermissions: adminUserPermissions };
const HomePage = props => {
const customPermissions = props?.customPermissions;
return (
<MockedUserProvider customPermissions={customPermissions}>
<HomePageComponent {...props} />
</MockedUserProvider>
);
}; };
storiesOf("Views / HomePage", module) storiesOf("Views / HomePage", module)
@ -49,12 +61,12 @@ storiesOf("Views / HomePage", module)
<HomePage {...homePageProps} topProducts={[]} activities={[]} /> <HomePage {...homePageProps} topProducts={[]} activities={[]} />
)) ))
.add("no permissions", () => ( .add("no permissions", () => (
<HomePage {...homePageProps} userPermissions={[]} /> <HomePage {...homePageProps} customPermissions={[]} />
)) ))
.add("product permissions", () => ( .add("product permissions", () => (
<HomePage <HomePage
{...homePageProps} {...homePageProps}
userPermissions={adminUserPermissions.filter( customPermissions={adminUserPermissions.filter(
perm => perm.code === PermissionEnum.MANAGE_PRODUCTS perm => perm.code === PermissionEnum.MANAGE_PRODUCTS
)} )}
/> />
@ -62,7 +74,7 @@ storiesOf("Views / HomePage", module)
.add("order permissions", () => ( .add("order permissions", () => (
<HomePage <HomePage
{...homePageProps} {...homePageProps}
userPermissions={adminUserPermissions.filter( customPermissions={adminUserPermissions.filter(
perm => perm.code === PermissionEnum.MANAGE_ORDERS perm => perm.code === PermissionEnum.MANAGE_ORDERS
)} )}
/> />

View file

@ -1,12 +1,12 @@
import { adminUserPermissions } from "@saleor/fixtures";
import { storiesOf } from "@storybook/react"; import { storiesOf } from "@storybook/react";
import React from "react"; import React from "react";
import OrderCustomer, { import OrderCustomerComponent, {
OrderCustomerProps OrderCustomerProps
} from "../../../orders/components/OrderCustomer"; } from "../../../orders/components/OrderCustomer";
import { clients, order as orderFixture } from "../../../orders/fixtures"; import { clients, order as orderFixture } from "../../../orders/fixtures";
import Decorator from "../../Decorator"; import Decorator from "../../Decorator";
import { MockedUserProvider } from "../customers/MockedUserProvider";
const order = orderFixture(""); const order = orderFixture("");
@ -19,10 +19,19 @@ const props: Omit<OrderCustomerProps, "classes"> = {
onProfileView: () => undefined, onProfileView: () => undefined,
onShippingAddressEdit: undefined, onShippingAddressEdit: undefined,
order, order,
userPermissions: adminUserPermissions,
users: clients users: clients
}; };
const OrderCustomer = props => {
const customPermissions = props?.customPermissions;
return (
<MockedUserProvider customPermissions={customPermissions}>
<OrderCustomerComponent {...props} />
</MockedUserProvider>
);
};
storiesOf("Orders / OrderCustomer", module) storiesOf("Orders / OrderCustomer", module)
.addDecorator(Decorator) .addDecorator(Decorator)
.add("default", () => <OrderCustomer {...props} />) .add("default", () => <OrderCustomer {...props} />)
@ -40,5 +49,5 @@ storiesOf("Orders / OrderCustomer", module)
<OrderCustomer {...props} canEditAddresses={true} canEditCustomer={true} /> <OrderCustomer {...props} canEditAddresses={true} canEditCustomer={true} />
)) ))
.add("no user permissions", () => ( .add("no user permissions", () => (
<OrderCustomer {...props} userPermissions={[]} /> <OrderCustomer {...props} customPermissions={[]} />
)); ));

View file

@ -1,5 +1,4 @@
import placeholderImage from "@assets/images/placeholder60x60.png"; import placeholderImage from "@assets/images/placeholder60x60.png";
import { adminUserPermissions } from "@saleor/fixtures";
import { storiesOf } from "@storybook/react"; import { storiesOf } from "@storybook/react";
import React from "react"; import React from "react";
@ -43,8 +42,7 @@ const props: Omit<OrderDetailsPageProps, "classes"> = {
onSubmit: () => undefined, onSubmit: () => undefined,
order, order,
shop: shopFixture, shop: shopFixture,
saveButtonBarState: "default", saveButtonBarState: "default"
userPermissions: adminUserPermissions
}; };
storiesOf("Views / Orders / Order details", module) storiesOf("Views / Orders / Order details", module)

View file

@ -1,13 +1,14 @@
import placeholderImage from "@assets/images/placeholder60x60.png"; import placeholderImage from "@assets/images/placeholder60x60.png";
import { adminUserPermissions, fetchMoreProps } from "@saleor/fixtures"; import { fetchMoreProps } from "@saleor/fixtures";
import { storiesOf } from "@storybook/react"; import { storiesOf } from "@storybook/react";
import React from "react"; import React from "react";
import OrderDraftPage, { import OrderDraftPageComponent, {
OrderDraftPageProps OrderDraftPageProps
} from "../../../../orders/components/OrderDraftPage"; } from "../../../../orders/components/OrderDraftPage";
import { clients, draftOrder } from "../../../../orders/fixtures"; import { clients, draftOrder } from "../../../../orders/fixtures";
import Decorator from "../../../Decorator"; import Decorator from "../../../Decorator";
import { MockedUserProvider } from "../../customers/MockedUserProvider";
import { getDiscountsProvidersWrapper } from "./utils"; import { getDiscountsProvidersWrapper } from "./utils";
const order = draftOrder(placeholderImage); const order = draftOrder(placeholderImage);
@ -31,13 +32,22 @@ const props: Omit<OrderDraftPageProps, "classes"> = {
onShippingMethodEdit: undefined, onShippingMethodEdit: undefined,
order, order,
saveButtonBarState: "default", saveButtonBarState: "default",
userPermissions: adminUserPermissions,
users: clients, users: clients,
usersLoading: false usersLoading: false
}; };
const DiscountsDecorator = getDiscountsProvidersWrapper(order); const DiscountsDecorator = getDiscountsProvidersWrapper(order);
const OrderDraftPage = props => {
const customPermissions = props?.customPermissions;
return (
<MockedUserProvider customPermissions={customPermissions}>
<OrderDraftPageComponent {...props} />
</MockedUserProvider>
);
};
storiesOf("Views / Orders / Order draft", module) storiesOf("Views / Orders / Order draft", module)
.addDecorator(Decorator) .addDecorator(Decorator)
.addDecorator(DiscountsDecorator) .addDecorator(DiscountsDecorator)
@ -49,5 +59,5 @@ storiesOf("Views / Orders / Order draft", module)
<OrderDraftPage {...props} order={{ ...order, lines: [] }} /> <OrderDraftPage {...props} order={{ ...order, lines: [] }} />
)) ))
.add("no user permissions", () => ( .add("no user permissions", () => (
<OrderDraftPage {...props} userPermissions={[]} /> <OrderDraftPage {...props} customPermissions={[]} />
)); ));