Add global channel picker (#841)
* Move theme switch to user menu * Add global channel picker * Fix picker styles * Use app channel state * Improve prop naming to indicate id vs slug * Disable picker if no reason to pick channel * Remove settings modal leftovers * Remove channel settings dialog * Remove unused props * Skip channel fetching if user is not authenticated * Remove channel selection from components * Update messages * Fix e2e tests * Remove channel picker leftover * Revert ChannelSettingsDialog deletion * Update snapshots * Update messages
This commit is contained in:
parent
607eba6a10
commit
a175fb9497
88 changed files with 501 additions and 1809 deletions
|
@ -1,6 +1,5 @@
|
|||
import { LEFT_MENU_SELECTORS } from "../elements/account/left-menu/left-menu-selectors";
|
||||
import { PRODUCTS_SELECTORS } from "../elements/catalog/product-selectors";
|
||||
import { BUTTON_SELECTORS } from "../elements/shared/button-selectors";
|
||||
|
||||
// <reference types="cypress" />
|
||||
describe("Products", () => {
|
||||
|
@ -14,8 +13,6 @@ describe("Products", () => {
|
|||
.click()
|
||||
.get(PRODUCTS_SELECTORS.products)
|
||||
.click()
|
||||
.get(BUTTON_SELECTORS.submit)
|
||||
.click()
|
||||
.get(PRODUCTS_SELECTORS.createProductBtn)
|
||||
.click()
|
||||
.get(PRODUCTS_SELECTORS.productNameInput)
|
||||
|
|
|
@ -1325,10 +1325,6 @@
|
|||
"context": "field is optional",
|
||||
"string": "(Optional)"
|
||||
},
|
||||
"src_dot_collections_dot_components_dot_CollectionListPage_dot_1391686013": {
|
||||
"context": "button",
|
||||
"string": "Settings"
|
||||
},
|
||||
"src_dot_collections_dot_components_dot_CollectionListPage_dot_1631917001": {
|
||||
"context": "tab name",
|
||||
"string": "All Collections"
|
||||
|
@ -1651,10 +1647,6 @@
|
|||
"context": "section header button",
|
||||
"string": "Manage"
|
||||
},
|
||||
"src_dot_components_dot_ChannelsSelect_dot_4183335632": {
|
||||
"context": "channel select label",
|
||||
"string": "Channel:"
|
||||
},
|
||||
"src_dot_components_dot_ColumnPicker_dot_1483881697": {
|
||||
"context": "button",
|
||||
"string": "Reset"
|
||||
|
@ -2062,6 +2054,10 @@
|
|||
"context": "button",
|
||||
"string": "Account Settings"
|
||||
},
|
||||
"src_dot_components_dot_UserChip_dot_85001470": {
|
||||
"context": "button",
|
||||
"string": "Enable Dark Mode"
|
||||
},
|
||||
"src_dot_components_dot_VisibilityCard_dot_1311467573": {
|
||||
"string": "Show in product listings"
|
||||
},
|
||||
|
@ -2496,10 +2492,6 @@
|
|||
"context": "sale name",
|
||||
"string": "Name"
|
||||
},
|
||||
"src_dot_discounts_dot_components_dot_SaleListPage_dot_1391686013": {
|
||||
"context": "button",
|
||||
"string": "Settings"
|
||||
},
|
||||
"src_dot_discounts_dot_components_dot_SaleListPage_dot_1866913828": {
|
||||
"string": "Search Sale"
|
||||
},
|
||||
|
@ -2660,10 +2652,6 @@
|
|||
"context": "tab name",
|
||||
"string": "All Vouchers"
|
||||
},
|
||||
"src_dot_discounts_dot_components_dot_VoucherListPage_dot_1391686013": {
|
||||
"context": "button",
|
||||
"string": "Settings"
|
||||
},
|
||||
"src_dot_discounts_dot_components_dot_VoucherListPage_dot_1930485532": {
|
||||
"string": "Search Voucher"
|
||||
},
|
||||
|
@ -3004,9 +2992,6 @@
|
|||
"src_dot_home_dot_components_dot_HomeActivityCard_dot_placed": {
|
||||
"string": "Order #{orderId} was placed"
|
||||
},
|
||||
"src_dot_home_dot_components_dot_HomeHeader_dot_4019698341": {
|
||||
"string": "Channel"
|
||||
},
|
||||
"src_dot_hooks_dot_3382262667": {
|
||||
"string": "Variant {name} has been set as default."
|
||||
},
|
||||
|
@ -3163,10 +3148,6 @@
|
|||
"context": "button",
|
||||
"string": "Add products"
|
||||
},
|
||||
"src_dot_orders_dot_components_dot_OrderDraftListPage_dot_1391686013": {
|
||||
"context": "button",
|
||||
"string": "Settings"
|
||||
},
|
||||
"src_dot_orders_dot_components_dot_OrderDraftListPage_dot_2826235371": {
|
||||
"context": "button",
|
||||
"string": "Create order"
|
||||
|
@ -3491,10 +3472,6 @@
|
|||
"context": "generate invoice button",
|
||||
"string": "Generate"
|
||||
},
|
||||
"src_dot_orders_dot_components_dot_OrderListPage_dot_1391686013": {
|
||||
"context": "button",
|
||||
"string": "Settings"
|
||||
},
|
||||
"src_dot_orders_dot_components_dot_OrderListPage_dot_2826235371": {
|
||||
"context": "button",
|
||||
"string": "Create order"
|
||||
|
@ -4561,10 +4538,6 @@
|
|||
"context": "product price",
|
||||
"string": "Price"
|
||||
},
|
||||
"src_dot_products_dot_components_dot_ProductListPage_dot_1391686013": {
|
||||
"context": "button",
|
||||
"string": "Settings"
|
||||
},
|
||||
"src_dot_products_dot_components_dot_ProductListPage_dot_1542417144": {
|
||||
"context": "button",
|
||||
"string": "Create Product"
|
||||
|
@ -5296,10 +5269,6 @@
|
|||
"context": "header",
|
||||
"string": "Shipping"
|
||||
},
|
||||
"src_dot_shipping_dot_components_dot_ShippingZonesListPage_dot_1391686013": {
|
||||
"context": "button",
|
||||
"string": "Settings"
|
||||
},
|
||||
"src_dot_shipping_dot_components_dot_ShippingZonesList_dot_120574110": {
|
||||
"context": "sort shipping methods by zone, section header",
|
||||
"string": "Shipping By Zone"
|
||||
|
|
|
@ -14,7 +14,7 @@ import TableCellAvatar, {
|
|||
import TableHead from "@saleor/components/TableHead";
|
||||
import TablePagination from "@saleor/components/TablePagination";
|
||||
import { maybe, renderCollection } from "@saleor/misc";
|
||||
import { ListActions, ListProps } from "@saleor/types";
|
||||
import { ChannelProps, ListActions, ListProps } from "@saleor/types";
|
||||
import React from "react";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
|
@ -70,9 +70,11 @@ const useStyles = makeStyles(
|
|||
}
|
||||
);
|
||||
|
||||
interface CategoryProductListProps extends ListProps, ListActions {
|
||||
interface CategoryProductListProps
|
||||
extends ListProps,
|
||||
ListActions,
|
||||
ChannelProps {
|
||||
channelsCount: number;
|
||||
selectedChannel: string;
|
||||
products: CategoryDetails_category_products_edges_node[];
|
||||
}
|
||||
|
||||
|
@ -90,7 +92,7 @@ export const CategoryProductList: React.FC<CategoryProductListProps> = props =>
|
|||
onNextPage,
|
||||
onPreviousPage,
|
||||
onRowClick,
|
||||
selectedChannel
|
||||
selectedChannelId
|
||||
} = props;
|
||||
|
||||
const classes = useStyles(props);
|
||||
|
@ -158,7 +160,7 @@ export const CategoryProductList: React.FC<CategoryProductListProps> = props =>
|
|||
product => {
|
||||
const isSelected = product ? isChecked(product.id) : false;
|
||||
const channel = product?.channelListings.find(
|
||||
listing => listing.channel.id === selectedChannel
|
||||
listing => listing.channel.id === selectedChannelId
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
@ -1,36 +1,25 @@
|
|||
import Button from "@material-ui/core/Button";
|
||||
import Card from "@material-ui/core/Card";
|
||||
import CardContent from "@material-ui/core/CardContent";
|
||||
import { makeStyles } from "@material-ui/core/styles";
|
||||
import CardTitle from "@saleor/components/CardTitle";
|
||||
import { ChannelsSelect } from "@saleor/components/ChannelsSelect";
|
||||
import { SingleAutocompleteChoiceType } from "@saleor/components/SingleAutocompleteSelectField";
|
||||
import useStateFromProps from "@saleor/hooks/useStateFromProps";
|
||||
import React from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
|
||||
import { ListActions, PageListProps } from "../../../types";
|
||||
import { ChannelProps, ListActions, PageListProps } from "../../../types";
|
||||
import { CategoryDetails_category_products_edges_node } from "../../types/CategoryDetails";
|
||||
import CategoryProductList from "../CategoryProductList";
|
||||
|
||||
interface CategoryProductsProps extends PageListProps, ListActions {
|
||||
interface CategoryProductsProps
|
||||
extends PageListProps,
|
||||
ListActions,
|
||||
ChannelProps {
|
||||
products: CategoryDetails_category_products_edges_node[];
|
||||
channelChoices: SingleAutocompleteChoiceType[];
|
||||
channelsCount: number;
|
||||
categoryName: string;
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(
|
||||
theme => ({
|
||||
channelsSelectContainer: {
|
||||
paddingTop: theme.spacing(2)
|
||||
}
|
||||
}),
|
||||
{ name: "CategoryProducts" }
|
||||
);
|
||||
|
||||
export const CategoryProducts: React.FC<CategoryProductsProps> = ({
|
||||
channelChoices,
|
||||
channelsCount,
|
||||
products,
|
||||
disabled,
|
||||
|
@ -42,16 +31,12 @@ export const CategoryProducts: React.FC<CategoryProductsProps> = ({
|
|||
categoryName,
|
||||
isChecked,
|
||||
selected,
|
||||
selectedChannelId,
|
||||
toggle,
|
||||
toggleAll,
|
||||
toolbar
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const classes = useStyles({});
|
||||
|
||||
const [channelChoice, setChannelChoice] = useStateFromProps(
|
||||
channelChoices?.length ? channelChoices[0]?.value : ""
|
||||
);
|
||||
|
||||
return (
|
||||
<Card>
|
||||
|
@ -72,16 +57,9 @@ export const CategoryProducts: React.FC<CategoryProductsProps> = ({
|
|||
</Button>
|
||||
}
|
||||
/>
|
||||
<CardContent className={classes.channelsSelectContainer}>
|
||||
<ChannelsSelect
|
||||
channelChoice={channelChoice}
|
||||
channelChoices={channelChoices}
|
||||
setChannelChoice={setChannelChoice}
|
||||
/>
|
||||
</CardContent>
|
||||
<CategoryProductList
|
||||
channelsCount={channelsCount}
|
||||
selectedChannel={channelChoice}
|
||||
selectedChannelId={selectedChannelId}
|
||||
products={products}
|
||||
disabled={disabled}
|
||||
pageInfo={pageInfo}
|
||||
|
|
|
@ -18,7 +18,7 @@ import React from "react";
|
|||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
|
||||
import { maybe } from "../../../misc";
|
||||
import { TabListActions } from "../../../types";
|
||||
import { ChannelProps, TabListActions } from "../../../types";
|
||||
import CategoryDetailsForm from "../../components/CategoryDetailsForm";
|
||||
import CategoryList from "../../components/CategoryList";
|
||||
import {
|
||||
|
@ -36,7 +36,8 @@ export enum CategoryPageTab {
|
|||
}
|
||||
|
||||
export interface CategoryUpdatePageProps
|
||||
extends TabListActions<"productListToolbar" | "subcategoryListToolbar"> {
|
||||
extends TabListActions<"productListToolbar" | "subcategoryListToolbar">,
|
||||
ChannelProps {
|
||||
changeTab: (index: CategoryPageTab) => void;
|
||||
currentTab: CategoryPageTab;
|
||||
errors: ProductErrorFragment[];
|
||||
|
@ -93,6 +94,7 @@ export const CategoryUpdatePage: React.FC<CategoryUpdatePageProps> = ({
|
|||
isChecked,
|
||||
productListToolbar,
|
||||
selected,
|
||||
selectedChannelId,
|
||||
subcategoryListToolbar,
|
||||
toggle,
|
||||
toggleAll
|
||||
|
@ -216,6 +218,7 @@ export const CategoryUpdatePage: React.FC<CategoryUpdatePageProps> = ({
|
|||
toggle={toggle}
|
||||
toggleAll={toggleAll}
|
||||
selected={selected}
|
||||
selectedChannelId={selectedChannelId}
|
||||
isChecked={isChecked}
|
||||
toolbar={productListToolbar}
|
||||
/>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import DialogContentText from "@material-ui/core/DialogContentText";
|
||||
import IconButton from "@material-ui/core/IconButton";
|
||||
import DeleteIcon from "@material-ui/icons/Delete";
|
||||
import { useChannelsList } from "@saleor/channels/queries";
|
||||
import ActionDialog from "@saleor/components/ActionDialog";
|
||||
import useAppChannel from "@saleor/components/AppLayout/AppChannelContext";
|
||||
import NotFoundPage from "@saleor/components/NotFoundPage";
|
||||
import { WindowTitle } from "@saleor/components/WindowTitle";
|
||||
import useBulkActions from "@saleor/hooks/useBulkActions";
|
||||
|
@ -14,6 +14,7 @@ import usePaginator, {
|
|||
import { commonMessages } from "@saleor/intl";
|
||||
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
||||
import createMetadataUpdateHandler from "@saleor/utils/handlers/metadataUpdateHandler";
|
||||
import { mapNodeToChoice } from "@saleor/utils/maps";
|
||||
import {
|
||||
useMetadataUpdate,
|
||||
usePrivateMetadataUpdate
|
||||
|
@ -79,12 +80,9 @@ export const CategoryDetails: React.FC<CategoryDetailsProps> = ({
|
|||
variables: { ...paginationState, id }
|
||||
});
|
||||
|
||||
const { data: channelsData } = useChannelsList({});
|
||||
const { availableChannels, channel } = useAppChannel();
|
||||
|
||||
const channelChoices = channelsData?.channels?.map(channel => ({
|
||||
label: channel.name,
|
||||
value: channel.id
|
||||
}));
|
||||
const channelChoices = mapNodeToChoice(availableChannels);
|
||||
|
||||
const category = data?.category;
|
||||
|
||||
|
@ -213,7 +211,7 @@ export const CategoryDetails: React.FC<CategoryDetailsProps> = ({
|
|||
<>
|
||||
<WindowTitle title={maybe(() => data.category.name)} />
|
||||
<CategoryUpdatePage
|
||||
channelsCount={channelsData?.channels?.length}
|
||||
channelsCount={availableChannels.length}
|
||||
channelChoices={channelChoices}
|
||||
changeTab={changeTab}
|
||||
currentTab={params.activeTab}
|
||||
|
@ -258,6 +256,7 @@ export const CategoryDetails: React.FC<CategoryDetailsProps> = ({
|
|||
data.category.products.edges.map(edge => edge.node)
|
||||
)}
|
||||
saveButtonBarState={updateResult.status}
|
||||
selectedChannelId={channel.id}
|
||||
subcategories={maybe(() =>
|
||||
data.category.children.edges.map(edge => edge.node)
|
||||
)}
|
||||
|
|
|
@ -8,10 +8,10 @@
|
|||
|
||||
export interface Channel_channel {
|
||||
__typename: "Channel";
|
||||
id: string;
|
||||
isActive: boolean;
|
||||
name: string;
|
||||
slug: string;
|
||||
id: string;
|
||||
isActive: boolean;
|
||||
currencyCode: string;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,10 +10,10 @@ import { ChannelErrorCode } from "./../../types/globalTypes";
|
|||
|
||||
export interface ChannelActivate_channelActivate_channel {
|
||||
__typename: "Channel";
|
||||
id: string;
|
||||
isActive: boolean;
|
||||
name: string;
|
||||
slug: string;
|
||||
id: string;
|
||||
isActive: boolean;
|
||||
currencyCode: string;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,10 +10,10 @@ import { ChannelCreateInput, ChannelErrorCode } from "./../../types/globalTypes"
|
|||
|
||||
export interface ChannelCreate_channelCreate_channel {
|
||||
__typename: "Channel";
|
||||
id: string;
|
||||
isActive: boolean;
|
||||
name: string;
|
||||
slug: string;
|
||||
id: string;
|
||||
isActive: boolean;
|
||||
currencyCode: string;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,10 +10,10 @@ import { ChannelErrorCode } from "./../../types/globalTypes";
|
|||
|
||||
export interface ChannelDeactivate_channelDeactivate_channel {
|
||||
__typename: "Channel";
|
||||
id: string;
|
||||
isActive: boolean;
|
||||
name: string;
|
||||
slug: string;
|
||||
id: string;
|
||||
isActive: boolean;
|
||||
currencyCode: string;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,10 +10,10 @@ import { ChannelDeleteInput, ChannelErrorCode } from "./../../types/globalTypes"
|
|||
|
||||
export interface ChannelDelete_channelDelete_channel {
|
||||
__typename: "Channel";
|
||||
id: string;
|
||||
isActive: boolean;
|
||||
name: string;
|
||||
slug: string;
|
||||
id: string;
|
||||
isActive: boolean;
|
||||
currencyCode: string;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,10 +10,10 @@ import { ChannelUpdateInput, ChannelErrorCode } from "./../../types/globalTypes"
|
|||
|
||||
export interface ChannelUpdate_channelUpdate_channel {
|
||||
__typename: "Channel";
|
||||
id: string;
|
||||
isActive: boolean;
|
||||
name: string;
|
||||
slug: string;
|
||||
id: string;
|
||||
isActive: boolean;
|
||||
currencyCode: string;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,10 +8,10 @@
|
|||
|
||||
export interface Channels_channels {
|
||||
__typename: "Channel";
|
||||
id: string;
|
||||
isActive: boolean;
|
||||
name: string;
|
||||
slug: string;
|
||||
id: string;
|
||||
isActive: boolean;
|
||||
currencyCode: string;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import { RequireOnlyOne } from "@saleor/misc";
|
|||
import { ProductDetails_product } from "@saleor/products/types/ProductDetails";
|
||||
import { ProductVariantDetails_productVariant } from "@saleor/products/types/ProductVariantDetails";
|
||||
import { ShippingZone_shippingZone_shippingMethods_channelListings } from "@saleor/shipping/types/ShippingZone";
|
||||
import { uniqBy } from "lodash";
|
||||
import uniqBy from "lodash-es/uniqBy";
|
||||
|
||||
export interface Channel {
|
||||
id: string;
|
||||
|
|
|
@ -16,14 +16,17 @@ import { sectionNames } from "@saleor/intl";
|
|||
import React from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
import { ListActions, PageListProps } from "../../../types";
|
||||
import { ChannelProps, ListActions, PageListProps } from "../../../types";
|
||||
import { CollectionDetails_collection } from "../../types/CollectionDetails";
|
||||
import CollectionDetails from "../CollectionDetails/CollectionDetails";
|
||||
import { CollectionImage } from "../CollectionImage/CollectionImage";
|
||||
import CollectionProducts from "../CollectionProducts/CollectionProducts";
|
||||
import CollectionUpdateForm, { CollectionUpdateData } from "./form";
|
||||
|
||||
export interface CollectionDetailsPageProps extends PageListProps, ListActions {
|
||||
export interface CollectionDetailsPageProps
|
||||
extends PageListProps,
|
||||
ListActions,
|
||||
ChannelProps {
|
||||
channelsCount: number;
|
||||
channelsErrors: CollectionChannelListingErrorFragment[];
|
||||
collection: CollectionDetails_collection;
|
||||
|
@ -31,7 +34,6 @@ export interface CollectionDetailsPageProps extends PageListProps, ListActions {
|
|||
errors: CollectionErrorFragment[];
|
||||
hasChannelChanged: boolean;
|
||||
saveButtonBarState: ConfirmButtonTransitionState;
|
||||
selectedChannel: string;
|
||||
onBack: () => void;
|
||||
onCollectionRemove: () => void;
|
||||
onImageDelete: () => void;
|
||||
|
@ -51,7 +53,7 @@ const CollectionDetailsPage: React.FC<CollectionDetailsPageProps> = ({
|
|||
errors,
|
||||
hasChannelChanged,
|
||||
saveButtonBarState,
|
||||
selectedChannel,
|
||||
selectedChannelId,
|
||||
onBack,
|
||||
onCollectionRemove,
|
||||
onImageDelete,
|
||||
|
@ -99,7 +101,7 @@ const CollectionDetailsPage: React.FC<CollectionDetailsPageProps> = ({
|
|||
<CollectionProducts
|
||||
disabled={disabled}
|
||||
channelsCount={channelsCount}
|
||||
selectedChannel={selectedChannel}
|
||||
selectedChannelId={selectedChannelId}
|
||||
collection={collection}
|
||||
{...collectionProductsProps}
|
||||
/>
|
||||
|
|
|
@ -12,7 +12,7 @@ import TableCellHeader from "@saleor/components/TableCellHeader";
|
|||
import TableHead from "@saleor/components/TableHead";
|
||||
import TablePagination from "@saleor/components/TablePagination";
|
||||
import { maybe, renderCollection } from "@saleor/misc";
|
||||
import { ListActions, ListProps, SortPage } from "@saleor/types";
|
||||
import { ChannelProps, ListActions, ListProps, SortPage } from "@saleor/types";
|
||||
import { getArrowDirection } from "@saleor/utils/sort";
|
||||
import React from "react";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
@ -47,10 +47,10 @@ const useStyles = makeStyles(
|
|||
interface CollectionListProps
|
||||
extends ListProps,
|
||||
ListActions,
|
||||
SortPage<CollectionListUrlSortField> {
|
||||
SortPage<CollectionListUrlSortField>,
|
||||
ChannelProps {
|
||||
collections: CollectionList_collections_edges_node[];
|
||||
channelsCount: number;
|
||||
selectedChannel: string;
|
||||
}
|
||||
|
||||
const numberOfColumns = 4;
|
||||
|
@ -70,7 +70,7 @@ const CollectionList: React.FC<CollectionListProps> = props => {
|
|||
pageInfo,
|
||||
isChecked,
|
||||
selected,
|
||||
selectedChannel,
|
||||
selectedChannelId,
|
||||
toggle,
|
||||
toggleAll,
|
||||
toolbar
|
||||
|
@ -147,7 +147,7 @@ const CollectionList: React.FC<CollectionListProps> = props => {
|
|||
collection => {
|
||||
const isSelected = collection ? isChecked(collection.id) : false;
|
||||
const channel = collection?.channelListings.find(
|
||||
listing => listing.channel.id === selectedChannel
|
||||
listing => listing.channel.id === selectedChannelId
|
||||
);
|
||||
return (
|
||||
<TableRow
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
import Button from "@material-ui/core/Button";
|
||||
import Card from "@material-ui/core/Card";
|
||||
import makeStyles from "@material-ui/core/styles/makeStyles";
|
||||
import { CollectionListUrlSortField } from "@saleor/collections/urls";
|
||||
import CardMenu from "@saleor/components/CardMenu";
|
||||
import { Container } from "@saleor/components/Container";
|
||||
import PageHeader from "@saleor/components/PageHeader";
|
||||
import SearchBar from "@saleor/components/SearchBar";
|
||||
import { sectionNames } from "@saleor/intl";
|
||||
import {
|
||||
ChannelProps,
|
||||
ListActions,
|
||||
PageListProps,
|
||||
SearchPageProps,
|
||||
|
@ -25,22 +24,12 @@ export interface CollectionListPageProps
|
|||
ListActions,
|
||||
SearchPageProps,
|
||||
SortPage<CollectionListUrlSortField>,
|
||||
TabPageProps {
|
||||
TabPageProps,
|
||||
ChannelProps {
|
||||
collections: CollectionList_collections_edges_node[];
|
||||
channelsCount: number;
|
||||
selectedChannel: string;
|
||||
onSettingsOpen?: () => void;
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(
|
||||
theme => ({
|
||||
settings: {
|
||||
marginRight: theme.spacing(2)
|
||||
}
|
||||
}),
|
||||
{ name: "CollectionListPage" }
|
||||
);
|
||||
|
||||
const CollectionListPage: React.FC<CollectionListPageProps> = ({
|
||||
channelsCount,
|
||||
currentTab,
|
||||
|
@ -49,34 +38,18 @@ const CollectionListPage: React.FC<CollectionListPageProps> = ({
|
|||
onAdd,
|
||||
onAll,
|
||||
onSearchChange,
|
||||
onSettingsOpen,
|
||||
onTabChange,
|
||||
onTabDelete,
|
||||
onTabSave,
|
||||
selectedChannel,
|
||||
selectedChannelId,
|
||||
tabs,
|
||||
...listProps
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const classes = useStyles({});
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<PageHeader title={intl.formatMessage(sectionNames.collections)}>
|
||||
{!!onSettingsOpen && (
|
||||
<CardMenu
|
||||
className={classes.settings}
|
||||
menuItems={[
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: "Settings",
|
||||
description: "button"
|
||||
}),
|
||||
onSelect: onSettingsOpen
|
||||
}
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
<Button
|
||||
color="primary"
|
||||
disabled={disabled}
|
||||
|
@ -110,7 +83,7 @@ const CollectionListPage: React.FC<CollectionListPageProps> = ({
|
|||
<CollectionList
|
||||
disabled={disabled}
|
||||
channelsCount={channelsCount}
|
||||
selectedChannel={selectedChannel}
|
||||
selectedChannelId={selectedChannelId}
|
||||
{...listProps}
|
||||
/>
|
||||
</Card>
|
||||
|
|
|
@ -21,7 +21,7 @@ import React from "react";
|
|||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
|
||||
import { maybe, renderCollection } from "../../../misc";
|
||||
import { ListActions, PageListProps } from "../../../types";
|
||||
import { ChannelProps, ListActions, PageListProps } from "../../../types";
|
||||
import { CollectionDetails_collection } from "../../types/CollectionDetails";
|
||||
|
||||
const useStyles = makeStyles(
|
||||
|
@ -55,10 +55,12 @@ const useStyles = makeStyles(
|
|||
{ name: "CollectionProducts" }
|
||||
);
|
||||
|
||||
export interface CollectionProductsProps extends PageListProps, ListActions {
|
||||
export interface CollectionProductsProps
|
||||
extends PageListProps,
|
||||
ListActions,
|
||||
ChannelProps {
|
||||
collection: CollectionDetails_collection;
|
||||
channelsCount: number;
|
||||
selectedChannel: string;
|
||||
onProductUnassign: (id: string, event: React.MouseEvent<any>) => void;
|
||||
}
|
||||
|
||||
|
@ -75,7 +77,7 @@ const CollectionProducts: React.FC<CollectionProductsProps> = props => {
|
|||
onProductUnassign,
|
||||
onRowClick,
|
||||
pageInfo,
|
||||
selectedChannel,
|
||||
selectedChannelId,
|
||||
isChecked,
|
||||
selected,
|
||||
toggle,
|
||||
|
@ -167,7 +169,7 @@ const CollectionProducts: React.FC<CollectionProductsProps> = props => {
|
|||
const isSelected = product ? isChecked(product.id) : false;
|
||||
const channel =
|
||||
product?.channelListings.find(
|
||||
listing => listing.channel.id === selectedChannel
|
||||
listing => listing.channel.id === selectedChannelId
|
||||
) || product?.channelListings[0];
|
||||
|
||||
return (
|
||||
|
|
|
@ -19,7 +19,7 @@ export enum CollectionListUrlFiltersEnum {
|
|||
query = "query"
|
||||
}
|
||||
export type CollectionListUrlFilters = Filters<CollectionListUrlFiltersEnum>;
|
||||
export type CollectionListUrlDialog = "remove" | "settings" | TabActionDialog;
|
||||
export type CollectionListUrlDialog = "remove" | TabActionDialog;
|
||||
export enum CollectionListUrlSortField {
|
||||
name = "name",
|
||||
available = "available",
|
||||
|
|
|
@ -336,7 +336,7 @@ export const CollectionDetails: React.FC<CollectionDetailsProps> = ({
|
|||
collectionChannelsChoices?.length !== currentChannels?.length
|
||||
}
|
||||
channelsCount={channelsData?.channels?.length}
|
||||
selectedChannel={selectedChannel}
|
||||
selectedChannelId={selectedChannel}
|
||||
openChannelsModal={handleChannelsModalOpen}
|
||||
onChannelsChange={setCurrentChannels}
|
||||
/>
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
import DialogContentText from "@material-ui/core/DialogContentText";
|
||||
import IconButton from "@material-ui/core/IconButton";
|
||||
import DeleteIcon from "@material-ui/icons/Delete";
|
||||
import ChannelSettingsDialog from "@saleor/channels/components/ChannelSettingsDialog";
|
||||
import ActionDialog from "@saleor/components/ActionDialog";
|
||||
import useAppChannel from "@saleor/components/AppLayout/AppChannelContext";
|
||||
import DeleteFilterTabDialog from "@saleor/components/DeleteFilterTabDialog";
|
||||
import SaveFilterTabDialog, {
|
||||
SaveFilterTabDialogFormData
|
||||
} from "@saleor/components/SaveFilterTabDialog";
|
||||
import useBulkActions from "@saleor/hooks/useBulkActions";
|
||||
import useChannelsSettings from "@saleor/hooks/useChannelsSettings";
|
||||
import useListSettings from "@saleor/hooks/useListSettings";
|
||||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
import useNotifier from "@saleor/hooks/useNotifier";
|
||||
|
@ -90,6 +89,9 @@ export const CollectionList: React.FC<CollectionListProps> = ({ params }) => {
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
const { availableChannels, channel } = useAppChannel();
|
||||
|
||||
const tabs = getFilterTabs();
|
||||
|
||||
const currentTab =
|
||||
|
@ -114,12 +116,6 @@ export const CollectionList: React.FC<CollectionListProps> = ({ params }) => {
|
|||
CollectionListUrlQueryParams
|
||||
>(navigate, collectionListUrl, params);
|
||||
|
||||
const {
|
||||
channelChoices,
|
||||
handleChannelSelectConfirm,
|
||||
selectedChannel
|
||||
} = useChannelsSettings("collectionListChannel", { closeModal, openModal });
|
||||
|
||||
const handleTabChange = (tab: number) => {
|
||||
reset();
|
||||
navigate(
|
||||
|
@ -151,16 +147,6 @@ export const CollectionList: React.FC<CollectionListProps> = ({ params }) => {
|
|||
|
||||
return (
|
||||
<>
|
||||
{!!channelChoices?.length && (
|
||||
<ChannelSettingsDialog
|
||||
channelsChoices={channelChoices}
|
||||
defaultChoice={selectedChannel}
|
||||
open={params.action === "settings"}
|
||||
confirmButtonState="default"
|
||||
onClose={closeModal}
|
||||
onConfirm={handleChannelSelectConfirm}
|
||||
/>
|
||||
)}
|
||||
<CollectionListPage
|
||||
currentTab={currentTab}
|
||||
initialSearch={params.query || ""}
|
||||
|
@ -197,11 +183,8 @@ export const CollectionList: React.FC<CollectionListProps> = ({ params }) => {
|
|||
selected={listElements.length}
|
||||
toggle={toggle}
|
||||
toggleAll={toggleAll}
|
||||
channelsCount={channelChoices?.length}
|
||||
selectedChannel={selectedChannel}
|
||||
onSettingsOpen={
|
||||
!!channelChoices?.length ? () => openModal("settings") : undefined
|
||||
}
|
||||
channelsCount={availableChannels?.length}
|
||||
selectedChannelId={channel.id}
|
||||
/>
|
||||
<ActionDialog
|
||||
open={params.action === "remove" && maybe(() => params.ids.length > 0)}
|
||||
|
|
75
src/components/AppLayout/AppChannelContext.tsx
Normal file
75
src/components/AppLayout/AppChannelContext.tsx
Normal file
|
@ -0,0 +1,75 @@
|
|||
import { useAuth } from "@saleor/auth/AuthProvider";
|
||||
import { useChannelsList } from "@saleor/channels/queries";
|
||||
import { ChannelDetailsFragment } from "@saleor/fragments/types/ChannelDetailsFragment";
|
||||
import useLocalStorage from "@saleor/hooks/useLocalStorage";
|
||||
import React from "react";
|
||||
|
||||
interface UseAppChannel {
|
||||
availableChannels: ChannelDetailsFragment[];
|
||||
channel: ChannelDetailsFragment;
|
||||
isPickerActive: boolean;
|
||||
refreshChannels: () => void;
|
||||
setChannel: (id: string) => void;
|
||||
}
|
||||
export interface AppChannelContextData extends UseAppChannel {
|
||||
setPickerActive: (isActive: boolean) => void;
|
||||
}
|
||||
|
||||
const AppChannelContext = React.createContext<AppChannelContextData>({
|
||||
availableChannels: [],
|
||||
channel: undefined,
|
||||
isPickerActive: false,
|
||||
refreshChannels: () => undefined,
|
||||
setChannel: () => undefined,
|
||||
setPickerActive: () => undefined
|
||||
});
|
||||
|
||||
export const AppChannelProvider: React.FC = ({ children }) => {
|
||||
const { isAuthenticated } = useAuth();
|
||||
const [selectedChannel, setSelectedChannel] = useLocalStorage("channel", "");
|
||||
const { data: channelData, refetch } = useChannelsList({
|
||||
skip: !isAuthenticated
|
||||
});
|
||||
const [isPickerActive, setPickerActive] = React.useState(false);
|
||||
React.useEffect(() => {
|
||||
if (!selectedChannel) {
|
||||
setSelectedChannel(channelData?.channels[0].id);
|
||||
}
|
||||
}, [channelData]);
|
||||
|
||||
const availableChannels = channelData?.channels || [];
|
||||
const channel = availableChannels.find(
|
||||
channel => channel.id === selectedChannel
|
||||
);
|
||||
|
||||
return (
|
||||
<AppChannelContext.Provider
|
||||
value={{
|
||||
availableChannels,
|
||||
channel,
|
||||
isPickerActive,
|
||||
refreshChannels: refetch,
|
||||
setChannel: setSelectedChannel,
|
||||
setPickerActive
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</AppChannelContext.Provider>
|
||||
);
|
||||
};
|
||||
AppChannelProvider.displayName = "AppChannelProvider";
|
||||
|
||||
function useAppChannel(enablePicker = true): UseAppChannel {
|
||||
const { setPickerActive, ...data } = React.useContext(AppChannelContext);
|
||||
React.useEffect(() => {
|
||||
if (enablePicker) {
|
||||
setPickerActive(true);
|
||||
}
|
||||
|
||||
return () => setPickerActive(false);
|
||||
}, [enablePicker]);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
export default useAppChannel;
|
51
src/components/AppLayout/AppChannelSelect.tsx
Normal file
51
src/components/AppLayout/AppChannelSelect.tsx
Normal file
|
@ -0,0 +1,51 @@
|
|||
import makeStyles from "@material-ui/core/styles/makeStyles";
|
||||
import { ChannelDetailsFragment } from "@saleor/fragments/types/ChannelDetailsFragment";
|
||||
import { ChannelProps } from "@saleor/types";
|
||||
import { mapNodeToChoice } from "@saleor/utils/maps";
|
||||
import React from "react";
|
||||
|
||||
import SingleSelectField from "../SingleSelectField";
|
||||
|
||||
const useStyles = makeStyles(
|
||||
theme => ({
|
||||
root: {
|
||||
"&& fieldset": {
|
||||
borderColor: theme.palette.divider
|
||||
},
|
||||
marginRight: theme.spacing(2),
|
||||
width: 192
|
||||
}
|
||||
}),
|
||||
{
|
||||
name: "AppChannelSelect"
|
||||
}
|
||||
);
|
||||
|
||||
export interface AppChannelSelectProps extends ChannelProps {
|
||||
channels: ChannelDetailsFragment[];
|
||||
disabled: boolean;
|
||||
onChannelSelect: (id: string) => void;
|
||||
}
|
||||
|
||||
const AppChannelSelect: React.FC<AppChannelSelectProps> = ({
|
||||
channels,
|
||||
disabled,
|
||||
onChannelSelect,
|
||||
selectedChannelId
|
||||
}) => {
|
||||
const classes = useStyles({});
|
||||
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<SingleSelectField
|
||||
choices={mapNodeToChoice(channels)}
|
||||
disabled={disabled}
|
||||
value={selectedChannelId}
|
||||
onChange={event => onChannelSelect(event.target.value)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
AppChannelSelect.displayName = "AppChannelSelect";
|
||||
export default AppChannelSelect;
|
|
@ -20,10 +20,11 @@ import SideBar from "../SideBar";
|
|||
import SideBarDrawer from "../SideBarDrawer/SideBarDrawer";
|
||||
import UserChip from "../UserChip";
|
||||
import AppActionContext from "./AppActionContext";
|
||||
import useAppChannel from "./AppChannelContext";
|
||||
import AppChannelSelect from "./AppChannelSelect";
|
||||
import AppHeaderContext from "./AppHeaderContext";
|
||||
import { appLoaderHeight } from "./consts";
|
||||
import createMenuStructure from "./menuStructure";
|
||||
import ThemeSwitch from "./ThemeSwitch";
|
||||
|
||||
const useStyles = makeStyles(
|
||||
theme => ({
|
||||
|
@ -128,6 +129,12 @@ const AppLayout: React.FC<AppLayoutProps> = ({ children }) => {
|
|||
const [isNavigatorVisible, setNavigatorVisibility] = React.useState(false);
|
||||
const isMdUp = useMediaQuery((theme: Theme) => theme.breakpoints.up("md"));
|
||||
const [docked, setDocked] = React.useState(true);
|
||||
const {
|
||||
availableChannels,
|
||||
channel,
|
||||
isPickerActive,
|
||||
setChannel
|
||||
} = useAppChannel(false);
|
||||
|
||||
const menuStructure = createMenuStructure(intl);
|
||||
const configurationMenu = createConfigurationMenu(intl);
|
||||
|
@ -202,23 +209,26 @@ const AppLayout: React.FC<AppLayoutProps> = ({ children }) => {
|
|||
)}
|
||||
<div className={classes.spacer} />
|
||||
<div className={classes.userBar}>
|
||||
<ThemeSwitch
|
||||
className={classes.darkThemeSwitch}
|
||||
checked={isDark}
|
||||
onClick={toggleTheme}
|
||||
/>
|
||||
<NavigatorButton
|
||||
isMac={navigator.platform
|
||||
.toLowerCase()
|
||||
.includes("mac")}
|
||||
onClick={() => setNavigatorVisibility(true)}
|
||||
/>
|
||||
<AppChannelSelect
|
||||
channels={availableChannels}
|
||||
disabled={!isPickerActive}
|
||||
selectedChannelId={channel.id}
|
||||
onChannelSelect={setChannel}
|
||||
/>
|
||||
<UserChip
|
||||
isDarkThemeEnabled={isDark}
|
||||
user={user}
|
||||
onLogout={logout}
|
||||
onProfileClick={() =>
|
||||
navigate(staffMemberDetailsUrl(user.id))
|
||||
}
|
||||
user={user}
|
||||
onThemeToggle={toggleTheme}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
import { makeStyles } from "@material-ui/core/styles";
|
||||
import Switch, { SwitchProps } from "@material-ui/core/Switch";
|
||||
import React from "react";
|
||||
|
||||
import MoonIcon from "../../icons/Moon";
|
||||
import SunIcon from "../../icons/Sun";
|
||||
|
||||
const useStyles = makeStyles(
|
||||
theme => ({
|
||||
checked: {
|
||||
"& svg": {
|
||||
background: theme.palette.primary.main,
|
||||
color: theme.palette.background.paper
|
||||
}
|
||||
},
|
||||
colorPrimary: {},
|
||||
root: {
|
||||
"& svg": {
|
||||
background: theme.palette.primary.main,
|
||||
borderRadius: "100%",
|
||||
height: 20,
|
||||
width: 20
|
||||
}
|
||||
},
|
||||
track: {
|
||||
"$colorPrimary$checked + &": {
|
||||
backgroundColor: theme.palette.background.paper
|
||||
},
|
||||
background: theme.palette.background.paper
|
||||
}
|
||||
}),
|
||||
{
|
||||
name: "ThemeSwitch"
|
||||
}
|
||||
);
|
||||
const ThemeSwitch: React.FC<SwitchProps> = props => {
|
||||
const classes = useStyles(props);
|
||||
|
||||
return (
|
||||
<Switch
|
||||
{...props}
|
||||
classes={classes}
|
||||
color="primary"
|
||||
icon={<SunIcon />}
|
||||
checkedIcon={<MoonIcon />}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
ThemeSwitch.displayName = "ThemeSwitch";
|
||||
export default ThemeSwitch;
|
|
@ -1,22 +0,0 @@
|
|||
import { product as productFixture } from "@saleor/products/fixtures";
|
||||
import Decorator from "@saleor/storybook/Decorator";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import React from "react";
|
||||
|
||||
import ChannelsSelect, { ChannelsSelectProps } from "./ChannelsSelect";
|
||||
|
||||
const product = productFixture("");
|
||||
const channelChoices = product.channelListings.map(listing => ({
|
||||
label: listing.channel.name,
|
||||
value: listing.channel.id
|
||||
}));
|
||||
|
||||
const props: ChannelsSelectProps = {
|
||||
channelChoice: channelChoices[0].value,
|
||||
channelChoices,
|
||||
setChannelChoice: () => undefined
|
||||
};
|
||||
|
||||
storiesOf("Generics / ChannelsSelect", module)
|
||||
.addDecorator(Decorator)
|
||||
.add("default", () => <ChannelsSelect {...props} />);
|
|
@ -1,53 +0,0 @@
|
|||
import { makeStyles } from "@material-ui/core/styles";
|
||||
import Typography from "@material-ui/core/Typography";
|
||||
import LinkChoice from "@saleor/components/LinkChoice";
|
||||
import { SingleAutocompleteChoiceType } from "@saleor/components/SingleAutocompleteSelectField";
|
||||
import { FormChange } from "@saleor/hooks/useForm";
|
||||
import React from "react";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
export interface ChannelsSelectProps {
|
||||
channelChoices: SingleAutocompleteChoiceType[];
|
||||
channelChoice: string;
|
||||
setChannelChoice: FormChange;
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(
|
||||
theme => ({
|
||||
label: {
|
||||
display: "inline-block",
|
||||
marginRight: theme.spacing(1)
|
||||
},
|
||||
select: {
|
||||
display: "inline-block"
|
||||
}
|
||||
}),
|
||||
{ name: "ChannelsSelect" }
|
||||
);
|
||||
|
||||
export const ChannelsSelect: React.FC<ChannelsSelectProps> = ({
|
||||
channelChoice,
|
||||
channelChoices,
|
||||
setChannelChoice
|
||||
}) => {
|
||||
const classes = useStyles({});
|
||||
|
||||
return channelChoices?.length ? (
|
||||
<>
|
||||
<Typography className={classes.label}>
|
||||
<FormattedMessage
|
||||
defaultMessage="Channel:"
|
||||
description="channel select label"
|
||||
/>
|
||||
</Typography>
|
||||
<LinkChoice
|
||||
className={classes.select}
|
||||
choices={channelChoices}
|
||||
name="channels"
|
||||
value={channelChoice}
|
||||
onChange={event => setChannelChoice(event.target.value)}
|
||||
/>
|
||||
</>
|
||||
) : null;
|
||||
};
|
||||
export default ChannelsSelect;
|
|
@ -1,2 +0,0 @@
|
|||
export * from "./ChannelsSelect";
|
||||
export { default } from "./ChannelsSelect";
|
|
@ -1,6 +1,7 @@
|
|||
import Avatar from "@material-ui/core/Avatar";
|
||||
import Chip from "@material-ui/core/Chip";
|
||||
import ClickAwayListener from "@material-ui/core/ClickAwayListener";
|
||||
import FormControlLabel from "@material-ui/core/FormControlLabel";
|
||||
import Grow from "@material-ui/core/Grow";
|
||||
import Hidden from "@material-ui/core/Hidden";
|
||||
import MenuItem from "@material-ui/core/MenuItem";
|
||||
|
@ -8,12 +9,13 @@ import Menu from "@material-ui/core/MenuList";
|
|||
import Paper from "@material-ui/core/Paper";
|
||||
import Popper from "@material-ui/core/Popper";
|
||||
import makeStyles from "@material-ui/core/styles/makeStyles";
|
||||
import Switch from "@material-ui/core/Switch";
|
||||
import { User } from "@saleor/fragments/types/User";
|
||||
import ArrowDropdown from "@saleor/icons/ArrowDropdown";
|
||||
import { getUserInitials, getUserName } from "@saleor/misc";
|
||||
import classNames from "classnames";
|
||||
import React from "react";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
|
||||
const useStyles = makeStyles(
|
||||
theme => ({
|
||||
|
@ -46,11 +48,16 @@ const useStyles = makeStyles(
|
|||
},
|
||||
popover: {
|
||||
marginTop: theme.spacing(2),
|
||||
zIndex: 1
|
||||
zIndex: 10
|
||||
},
|
||||
rotate: {
|
||||
transform: "rotate(180deg)"
|
||||
},
|
||||
switch: {
|
||||
"&&:hover": {
|
||||
background: "transparent"
|
||||
}
|
||||
},
|
||||
userChip: {
|
||||
[theme.breakpoints.down("sm")]: {
|
||||
height: 48
|
||||
|
@ -74,19 +81,24 @@ const useStyles = makeStyles(
|
|||
);
|
||||
|
||||
export interface UserChipProps {
|
||||
isDarkThemeEnabled: boolean;
|
||||
user: User;
|
||||
onLogout: () => void;
|
||||
onProfileClick: () => void;
|
||||
onThemeToggle: () => void;
|
||||
}
|
||||
|
||||
const UserChip: React.FC<UserChipProps> = ({
|
||||
isDarkThemeEnabled,
|
||||
user,
|
||||
onLogout,
|
||||
onProfileClick
|
||||
onProfileClick,
|
||||
onThemeToggle
|
||||
}) => {
|
||||
const classes = useStyles({});
|
||||
const [isMenuOpened, setMenuState] = React.useState(false);
|
||||
const anchor = React.useRef<HTMLDivElement>();
|
||||
const intl = useIntl();
|
||||
|
||||
const handleLogout = () => {
|
||||
setMenuState(false);
|
||||
|
@ -170,6 +182,29 @@ const UserChip: React.FC<UserChipProps> = ({
|
|||
description="button"
|
||||
/>
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
className={classes.userMenuItem}
|
||||
data-test="themeSwitch"
|
||||
data-test-is-dark={isDarkThemeEnabled}
|
||||
>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Switch
|
||||
classes={{
|
||||
switchBase: classes.switch
|
||||
}}
|
||||
checked={isDarkThemeEnabled}
|
||||
color="primary"
|
||||
disableRipple
|
||||
/>
|
||||
}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Enable Dark Mode",
|
||||
description: "button"
|
||||
})}
|
||||
onChange={onThemeToggle}
|
||||
/>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</ClickAwayListener>
|
||||
</Paper>
|
||||
|
|
|
@ -21,14 +21,16 @@ import React from "react";
|
|||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
|
||||
import { maybe, renderCollection } from "../../../misc";
|
||||
import { ListActions, ListProps } from "../../../types";
|
||||
import { ChannelProps, ListActions, ListProps } from "../../../types";
|
||||
import { SaleDetails_sale } from "../../types/SaleDetails";
|
||||
import { VoucherDetails_voucher } from "../../types/VoucherDetails";
|
||||
|
||||
export interface SaleProductsProps extends ListProps, ListActions {
|
||||
export interface SaleProductsProps
|
||||
extends ListProps,
|
||||
ListActions,
|
||||
ChannelProps {
|
||||
discount: SaleDetails_sale | VoucherDetails_voucher;
|
||||
channelsCount: number;
|
||||
selectedChannel: string;
|
||||
onProductAssign: () => void;
|
||||
onProductUnassign: (id: string) => void;
|
||||
}
|
||||
|
@ -79,7 +81,7 @@ const DiscountProducts: React.FC<SaleProductsProps> = props => {
|
|||
onNextPage,
|
||||
isChecked,
|
||||
selected,
|
||||
selectedChannel,
|
||||
selectedChannelId,
|
||||
toggle,
|
||||
toggleAll,
|
||||
toolbar
|
||||
|
@ -156,7 +158,7 @@ const DiscountProducts: React.FC<SaleProductsProps> = props => {
|
|||
const isSelected = product ? isChecked(product.id) : false;
|
||||
const channel =
|
||||
product?.channelListings.find(
|
||||
listing => listing.channel.id === selectedChannel
|
||||
listing => listing.channel.id === selectedChannelId
|
||||
) || product?.channelListings[0];
|
||||
return (
|
||||
<TableRow
|
||||
|
|
|
@ -17,7 +17,7 @@ import React from "react";
|
|||
import { useIntl } from "react-intl";
|
||||
|
||||
import { maybe, splitDateTime } from "../../../misc";
|
||||
import { ListProps, TabListActions } from "../../../types";
|
||||
import { ChannelProps, ListProps, TabListActions } from "../../../types";
|
||||
import { SaleType as SaleTypeEnum } from "../../../types/globalTypes";
|
||||
import { SaleDetails_sale } from "../../types/SaleDetails";
|
||||
import DiscountCategories from "../DiscountCategories";
|
||||
|
@ -57,11 +57,11 @@ export interface SaleDetailsPageProps
|
|||
extends Pick<ListProps, Exclude<keyof ListProps, "onRowClick">>,
|
||||
TabListActions<
|
||||
"categoryListToolbar" | "collectionListToolbar" | "productListToolbar"
|
||||
> {
|
||||
>,
|
||||
ChannelProps {
|
||||
activeTab: SaleDetailsPageTab;
|
||||
errors: DiscountErrorFragment[];
|
||||
sale: SaleDetails_sale;
|
||||
selectedChannel: string;
|
||||
allChannelsCount: number;
|
||||
channelListings: ChannelSaleData[];
|
||||
hasChannelChanged: boolean;
|
||||
|
@ -119,7 +119,7 @@ const SaleDetailsPage: React.FC<SaleDetailsPageProps> = ({
|
|||
productListToolbar,
|
||||
isChecked,
|
||||
selected,
|
||||
selectedChannel,
|
||||
selectedChannelId,
|
||||
toggle,
|
||||
toggleAll
|
||||
}) => {
|
||||
|
@ -270,7 +270,7 @@ const SaleDetailsPage: React.FC<SaleDetailsPageProps> = ({
|
|||
pageInfo={pageInfo}
|
||||
discount={sale}
|
||||
channelsCount={allChannelsCount}
|
||||
selectedChannel={selectedChannel}
|
||||
selectedChannelId={selectedChannelId}
|
||||
isChecked={isChecked}
|
||||
selected={selected}
|
||||
toggle={toggle}
|
||||
|
@ -287,7 +287,10 @@ const SaleDetailsPage: React.FC<SaleDetailsPageProps> = ({
|
|||
/>
|
||||
</div>
|
||||
<div>
|
||||
<SaleSummary selectedChannel={selectedChannel} sale={sale} />
|
||||
<SaleSummary
|
||||
selectedChannelId={selectedChannelId}
|
||||
sale={sale}
|
||||
/>
|
||||
<CardSpacer />
|
||||
<ChannelsAvailability
|
||||
selectedChannelsCount={data.channelListings.length}
|
||||
|
|
|
@ -14,7 +14,7 @@ import TableHead from "@saleor/components/TableHead";
|
|||
import TablePagination from "@saleor/components/TablePagination";
|
||||
import { SaleListUrlSortField } from "@saleor/discounts/urls";
|
||||
import { maybe, renderCollection } from "@saleor/misc";
|
||||
import { ListActions, ListProps, SortPage } from "@saleor/types";
|
||||
import { ChannelProps, ListActions, ListProps, SortPage } from "@saleor/types";
|
||||
import { SaleType } from "@saleor/types/globalTypes";
|
||||
import { getArrowDirection } from "@saleor/utils/sort";
|
||||
import React from "react";
|
||||
|
@ -25,9 +25,9 @@ import { SaleList_sales_edges_node } from "../../types/SaleList";
|
|||
export interface SaleListProps
|
||||
extends ListProps,
|
||||
ListActions,
|
||||
SortPage<SaleListUrlSortField> {
|
||||
SortPage<SaleListUrlSortField>,
|
||||
ChannelProps {
|
||||
sales: SaleList_sales_edges_node[];
|
||||
selectedChannel: string;
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(
|
||||
|
@ -76,7 +76,7 @@ const SaleList: React.FC<SaleListProps> = props => {
|
|||
onSort,
|
||||
pageInfo,
|
||||
sales,
|
||||
selectedChannel,
|
||||
selectedChannelId,
|
||||
isChecked,
|
||||
selected,
|
||||
sort,
|
||||
|
@ -170,7 +170,7 @@ const SaleList: React.FC<SaleListProps> = props => {
|
|||
sale => {
|
||||
const isSelected = sale ? isChecked(sale.id) : false;
|
||||
const channel = sale?.channelListings?.find(
|
||||
lisiting => lisiting.channel.id === selectedChannel
|
||||
lisiting => lisiting.channel.id === selectedChannelId
|
||||
);
|
||||
return (
|
||||
<TableRow
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
import Button from "@material-ui/core/Button";
|
||||
import Card from "@material-ui/core/Card";
|
||||
import makeStyles from "@material-ui/core/styles/makeStyles";
|
||||
import CardMenu from "@saleor/components/CardMenu";
|
||||
import Container from "@saleor/components/Container";
|
||||
import FilterBar from "@saleor/components/FilterBar";
|
||||
import PageHeader from "@saleor/components/PageHeader";
|
||||
import { SaleListUrlSortField } from "@saleor/discounts/urls";
|
||||
import { sectionNames } from "@saleor/intl";
|
||||
import {
|
||||
ChannelProps,
|
||||
FilterPageProps,
|
||||
ListActions,
|
||||
PageListProps,
|
||||
|
@ -30,19 +29,10 @@ export interface SaleListPageProps
|
|||
ListActions,
|
||||
FilterPageProps<SaleFilterKeys, SaleListFilterOpts>,
|
||||
SortPage<SaleListUrlSortField>,
|
||||
TabPageProps {
|
||||
TabPageProps,
|
||||
ChannelProps {
|
||||
sales: SaleList_sales_edges_node[];
|
||||
selectedChannel: string;
|
||||
onSettingsOpen?: () => void;
|
||||
}
|
||||
const useStyles = makeStyles(
|
||||
theme => ({
|
||||
settings: {
|
||||
marginRight: theme.spacing(2)
|
||||
}
|
||||
}),
|
||||
{ name: "SaleListPage" }
|
||||
);
|
||||
|
||||
const SaleListPage: React.FC<SaleListPageProps> = ({
|
||||
currentTab,
|
||||
|
@ -52,7 +42,6 @@ const SaleListPage: React.FC<SaleListPageProps> = ({
|
|||
onAll,
|
||||
onFilterChange,
|
||||
onSearchChange,
|
||||
onSettingsOpen,
|
||||
onTabChange,
|
||||
onTabDelete,
|
||||
onTabSave,
|
||||
|
@ -60,26 +49,11 @@ const SaleListPage: React.FC<SaleListPageProps> = ({
|
|||
...listProps
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const classes = useStyles({});
|
||||
const structure = createFilterStructure(intl, filterOpts);
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<PageHeader title={intl.formatMessage(sectionNames.sales)}>
|
||||
{!!onSettingsOpen && (
|
||||
<CardMenu
|
||||
className={classes.settings}
|
||||
menuItems={[
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: "Settings",
|
||||
description: "button"
|
||||
}),
|
||||
onSelect: onSettingsOpen
|
||||
}
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
<Button onClick={onAdd} variant="contained" color="primary">
|
||||
<FormattedMessage defaultMessage="Create Sale" description="button" />
|
||||
</Button>
|
||||
|
|
|
@ -10,6 +10,7 @@ import Money from "@saleor/components/Money";
|
|||
import Percent from "@saleor/components/Percent";
|
||||
import Skeleton from "@saleor/components/Skeleton";
|
||||
import { commonMessages } from "@saleor/intl";
|
||||
import { ChannelProps } from "@saleor/types";
|
||||
import React from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
|
||||
|
@ -17,16 +18,18 @@ import { maybe } from "../../../misc";
|
|||
import { SaleType } from "../../../types/globalTypes";
|
||||
import { SaleDetails_sale } from "../../types/SaleDetails";
|
||||
|
||||
export interface SaleSummaryProps {
|
||||
selectedChannel: string;
|
||||
export interface SaleSummaryProps extends ChannelProps {
|
||||
sale: SaleDetails_sale;
|
||||
}
|
||||
|
||||
const SaleSummary: React.FC<SaleSummaryProps> = ({ selectedChannel, sale }) => {
|
||||
const SaleSummary: React.FC<SaleSummaryProps> = ({
|
||||
selectedChannelId,
|
||||
sale
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
|
||||
const channel = sale?.channelListings?.find(
|
||||
listing => listing.channel.id === selectedChannel
|
||||
listing => listing.channel.id === selectedChannelId
|
||||
);
|
||||
return (
|
||||
<Card>
|
||||
|
|
|
@ -20,7 +20,7 @@ import React from "react";
|
|||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
|
||||
import { maybe, splitDateTime } from "../../../misc";
|
||||
import { ListProps, TabListActions } from "../../../types";
|
||||
import { ChannelProps, ListProps, TabListActions } from "../../../types";
|
||||
import {
|
||||
DiscountValueTypeEnum,
|
||||
VoucherTypeEnum
|
||||
|
@ -73,12 +73,12 @@ export interface VoucherDetailsPageProps
|
|||
extends Pick<ListProps, Exclude<keyof ListProps, "onRowClick">>,
|
||||
TabListActions<
|
||||
"categoryListToolbar" | "collectionListToolbar" | "productListToolbar"
|
||||
> {
|
||||
>,
|
||||
ChannelProps {
|
||||
activeTab: VoucherDetailsPageTab;
|
||||
errors: DiscountErrorFragment[];
|
||||
saveButtonBarState: ConfirmButtonTransitionState;
|
||||
voucher: VoucherDetails_voucher;
|
||||
selectedChannel: string;
|
||||
allChannelsCount: number;
|
||||
channelListings: ChannelVoucherData[];
|
||||
hasChannelChanged: boolean;
|
||||
|
@ -137,7 +137,7 @@ const VoucherDetailsPage: React.FC<VoucherDetailsPageProps> = ({
|
|||
toggle,
|
||||
toggleAll,
|
||||
selected,
|
||||
selectedChannel,
|
||||
selectedChannelId,
|
||||
isChecked,
|
||||
categoryListToolbar,
|
||||
collectionListToolbar,
|
||||
|
@ -145,7 +145,7 @@ const VoucherDetailsPage: React.FC<VoucherDetailsPageProps> = ({
|
|||
}) => {
|
||||
const intl = useIntl();
|
||||
const channel = voucher?.channelListings?.find(
|
||||
listing => listing.channel.id === selectedChannel
|
||||
listing => listing.channel.id === selectedChannelId
|
||||
);
|
||||
let requirementsPickerInitValue;
|
||||
if (voucher?.minCheckoutItemsQuantity > 0) {
|
||||
|
@ -331,7 +331,7 @@ const VoucherDetailsPage: React.FC<VoucherDetailsPageProps> = ({
|
|||
onRowClick={onProductClick}
|
||||
pageInfo={pageInfo}
|
||||
discount={voucher}
|
||||
selectedChannel={selectedChannel}
|
||||
selectedChannelId={selectedChannelId}
|
||||
channelsCount={allChannelsCount}
|
||||
isChecked={isChecked}
|
||||
selected={selected}
|
||||
|
@ -391,7 +391,7 @@ const VoucherDetailsPage: React.FC<VoucherDetailsPageProps> = ({
|
|||
<div>
|
||||
<VoucherSummary
|
||||
voucher={voucher}
|
||||
selectedChannel={selectedChannel}
|
||||
selectedChannelId={selectedChannelId}
|
||||
/>
|
||||
<CardSpacer />
|
||||
<ChannelsAvailability
|
||||
|
|
|
@ -14,7 +14,7 @@ import TableHead from "@saleor/components/TableHead";
|
|||
import TablePagination from "@saleor/components/TablePagination";
|
||||
import { VoucherListUrlSortField } from "@saleor/discounts/urls";
|
||||
import { maybe, renderCollection } from "@saleor/misc";
|
||||
import { ListActions, ListProps, SortPage } from "@saleor/types";
|
||||
import { ChannelProps, ListActions, ListProps, SortPage } from "@saleor/types";
|
||||
import { DiscountValueTypeEnum } from "@saleor/types/globalTypes";
|
||||
import { getArrowDirection } from "@saleor/utils/sort";
|
||||
import { getFooterColSpanWithBulkActions } from "@saleor/utils/tables";
|
||||
|
@ -26,9 +26,9 @@ import { VoucherList_vouchers_edges_node } from "../../types/VoucherList";
|
|||
export interface VoucherListProps
|
||||
extends ListProps,
|
||||
ListActions,
|
||||
SortPage<VoucherListUrlSortField> {
|
||||
SortPage<VoucherListUrlSortField>,
|
||||
ChannelProps {
|
||||
vouchers: VoucherList_vouchers_edges_node[];
|
||||
selectedChannel: string;
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(
|
||||
|
@ -94,7 +94,7 @@ const VoucherList: React.FC<VoucherListProps> = props => {
|
|||
vouchers,
|
||||
isChecked,
|
||||
selected,
|
||||
selectedChannel,
|
||||
selectedChannelId,
|
||||
sort,
|
||||
toggle,
|
||||
toggleAll,
|
||||
|
@ -219,7 +219,7 @@ const VoucherList: React.FC<VoucherListProps> = props => {
|
|||
voucher => {
|
||||
const isSelected = voucher ? isChecked(voucher.id) : false;
|
||||
const channel = voucher?.channelListings?.find(
|
||||
listing => listing.channel.id === selectedChannel
|
||||
listing => listing.channel.id === selectedChannelId
|
||||
);
|
||||
const hasChannelsLoaded = voucher?.channelListings?.length;
|
||||
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
import Button from "@material-ui/core/Button";
|
||||
import Card from "@material-ui/core/Card";
|
||||
import makeStyles from "@material-ui/core/styles/makeStyles";
|
||||
import CardMenu from "@saleor/components/CardMenu";
|
||||
import Container from "@saleor/components/Container";
|
||||
import FilterBar from "@saleor/components/FilterBar";
|
||||
import PageHeader from "@saleor/components/PageHeader";
|
||||
import { VoucherListUrlSortField } from "@saleor/discounts/urls";
|
||||
import { sectionNames } from "@saleor/intl";
|
||||
import {
|
||||
ChannelProps,
|
||||
FilterPageProps,
|
||||
ListActions,
|
||||
PageListProps,
|
||||
|
@ -30,20 +29,10 @@ export interface VoucherListPageProps
|
|||
ListActions,
|
||||
FilterPageProps<VoucherFilterKeys, VoucherListFilterOpts>,
|
||||
SortPage<VoucherListUrlSortField>,
|
||||
TabPageProps {
|
||||
TabPageProps,
|
||||
ChannelProps {
|
||||
vouchers: VoucherList_vouchers_edges_node[];
|
||||
selectedChannel: string;
|
||||
onSettingsOpen?: () => void;
|
||||
}
|
||||
const useStyles = makeStyles(
|
||||
theme => ({
|
||||
settings: {
|
||||
marginRight: theme.spacing(2)
|
||||
}
|
||||
}),
|
||||
{ name: "VoucherListPage" }
|
||||
);
|
||||
|
||||
const VoucherListPage: React.FC<VoucherListPageProps> = ({
|
||||
currentTab,
|
||||
filterOpts,
|
||||
|
@ -52,7 +41,6 @@ const VoucherListPage: React.FC<VoucherListPageProps> = ({
|
|||
onAll,
|
||||
onFilterChange,
|
||||
onSearchChange,
|
||||
onSettingsOpen,
|
||||
onTabChange,
|
||||
onTabDelete,
|
||||
onTabSave,
|
||||
|
@ -60,26 +48,11 @@ const VoucherListPage: React.FC<VoucherListPageProps> = ({
|
|||
...listProps
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const classes = useStyles({});
|
||||
const structure = createFilterStructure(intl, filterOpts);
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<PageHeader title={intl.formatMessage(sectionNames.vouchers)}>
|
||||
{onSettingsOpen && (
|
||||
<CardMenu
|
||||
className={classes.settings}
|
||||
menuItems={[
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: "Settings",
|
||||
description: "button"
|
||||
}),
|
||||
onSelect: onSettingsOpen
|
||||
}
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
<Button onClick={onAdd} variant="contained" color="primary">
|
||||
<FormattedMessage
|
||||
defaultMessage="Create voucher"
|
||||
|
|
|
@ -10,6 +10,7 @@ import Money from "@saleor/components/Money";
|
|||
import Percent from "@saleor/components/Percent";
|
||||
import Skeleton from "@saleor/components/Skeleton";
|
||||
import { commonMessages } from "@saleor/intl";
|
||||
import { ChannelProps } from "@saleor/types";
|
||||
import React from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
|
||||
|
@ -18,20 +19,19 @@ import { DiscountValueTypeEnum } from "../../../types/globalTypes";
|
|||
import { translateVoucherTypes } from "../../translations";
|
||||
import { VoucherDetails_voucher } from "../../types/VoucherDetails";
|
||||
|
||||
export interface VoucherSummaryProps {
|
||||
export interface VoucherSummaryProps extends ChannelProps {
|
||||
voucher: VoucherDetails_voucher;
|
||||
selectedChannel: string;
|
||||
}
|
||||
|
||||
const VoucherSummary: React.FC<VoucherSummaryProps> = ({
|
||||
selectedChannel,
|
||||
selectedChannelId,
|
||||
voucher
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
|
||||
const translatedVoucherTypes = translateVoucherTypes(intl);
|
||||
const channel = voucher?.channelListings?.find(
|
||||
listing => listing.channel.id === selectedChannel
|
||||
listing => listing.channel.id === selectedChannelId
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
@ -29,7 +29,7 @@ export enum SaleListUrlFiltersWithMultipleValues {
|
|||
}
|
||||
export type SaleListUrlFilters = Filters<SaleListUrlFiltersEnum> &
|
||||
FiltersWithMultipleValues<SaleListUrlFiltersWithMultipleValues>;
|
||||
export type SaleListUrlDialog = "remove" | "settings" | TabActionDialog;
|
||||
export type SaleListUrlDialog = "remove" | TabActionDialog;
|
||||
export enum SaleListUrlSortField {
|
||||
name = "name",
|
||||
endDate = "end-date",
|
||||
|
@ -79,7 +79,7 @@ export enum VoucherListUrlFiltersWithMultipleValues {
|
|||
}
|
||||
export type VoucherListUrlFilters = Filters<VoucherListUrlFiltersEnum> &
|
||||
FiltersWithMultipleValues<VoucherListUrlFiltersWithMultipleValues>;
|
||||
export type VoucherListUrlDialog = "remove" | "settings" | TabActionDialog;
|
||||
export type VoucherListUrlDialog = "remove" | TabActionDialog;
|
||||
export enum VoucherListUrlSortField {
|
||||
code = "code",
|
||||
endDate = "end-date",
|
||||
|
|
|
@ -279,7 +279,7 @@ export const SaleDetails: React.FC<SaleDetailsProps> = ({ id, params }) => {
|
|||
...(updateChannelsOpts.data
|
||||
?.saleChannelListingUpdate.errors || [])
|
||||
]}
|
||||
selectedChannel={selectedChannel}
|
||||
selectedChannelId={selectedChannel}
|
||||
pageInfo={pageInfo}
|
||||
openChannelsModal={handleChannelsModalOpen}
|
||||
onChannelsChange={setCurrentChannels}
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
import DialogContentText from "@material-ui/core/DialogContentText";
|
||||
import IconButton from "@material-ui/core/IconButton";
|
||||
import DeleteIcon from "@material-ui/icons/Delete";
|
||||
import ChannelSettingsDialog from "@saleor/channels/components/ChannelSettingsDialog";
|
||||
import ActionDialog from "@saleor/components/ActionDialog";
|
||||
import useAppChannel from "@saleor/components/AppLayout/AppChannelContext";
|
||||
import DeleteFilterTabDialog from "@saleor/components/DeleteFilterTabDialog";
|
||||
import SaveFilterTabDialog, {
|
||||
SaveFilterTabDialogFormData
|
||||
} from "@saleor/components/SaveFilterTabDialog";
|
||||
import { WindowTitle } from "@saleor/components/WindowTitle";
|
||||
import useBulkActions from "@saleor/hooks/useBulkActions";
|
||||
import useChannelsSettings from "@saleor/hooks/useChannelsSettings";
|
||||
import useListSettings from "@saleor/hooks/useListSettings";
|
||||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
import useNotifier from "@saleor/hooks/useNotifier";
|
||||
|
@ -64,18 +63,13 @@ export const SaleList: React.FC<SaleListProps> = ({ params }) => {
|
|||
ListViews.SALES_LIST
|
||||
);
|
||||
const intl = useIntl();
|
||||
const { channel } = useAppChannel();
|
||||
|
||||
const [openModal, closeModal] = createDialogActionHandlers<
|
||||
SaleListUrlDialog,
|
||||
SaleListUrlQueryParams
|
||||
>(navigate, saleListUrl, params);
|
||||
|
||||
const {
|
||||
channelChoices,
|
||||
handleChannelSelectConfirm,
|
||||
selectedChannel
|
||||
} = useChannelsSettings("salesListChannel", { closeModal, openModal });
|
||||
|
||||
const paginationState = createPaginationState(settings.rowNumber, params);
|
||||
const queryVariables = React.useMemo(
|
||||
() => ({
|
||||
|
@ -167,16 +161,6 @@ export const SaleList: React.FC<SaleListProps> = ({ params }) => {
|
|||
return (
|
||||
<>
|
||||
<WindowTitle title={intl.formatMessage(sectionNames.sales)} />
|
||||
{!!channelChoices?.length && (
|
||||
<ChannelSettingsDialog
|
||||
channelsChoices={channelChoices}
|
||||
defaultChoice={selectedChannel}
|
||||
open={params.action === "settings"}
|
||||
confirmButtonState="default"
|
||||
onClose={closeModal}
|
||||
onConfirm={handleChannelSelectConfirm}
|
||||
/>
|
||||
)}
|
||||
<SaleListPage
|
||||
currentTab={currentTab}
|
||||
filterOpts={getFilterOpts(params)}
|
||||
|
@ -215,12 +199,7 @@ export const SaleList: React.FC<SaleListProps> = ({ params }) => {
|
|||
<DeleteIcon />
|
||||
</IconButton>
|
||||
}
|
||||
selectedChannel={selectedChannel}
|
||||
onSettingsOpen={
|
||||
!!channelChoices?.length
|
||||
? () => openModal("settings")
|
||||
: undefined
|
||||
}
|
||||
selectedChannelId={channel.id}
|
||||
/>
|
||||
<ActionDialog
|
||||
confirmButtonState={saleBulkDeleteOpts.status}
|
||||
|
|
|
@ -7,6 +7,7 @@ import {
|
|||
createSortedChannelsDataFromVoucher
|
||||
} from "@saleor/channels/utils";
|
||||
import ActionDialog from "@saleor/components/ActionDialog";
|
||||
import useAppChannel from "@saleor/components/AppLayout/AppChannelContext";
|
||||
import AssignCategoriesDialog from "@saleor/components/AssignCategoryDialog";
|
||||
import AssignCollectionDialog from "@saleor/components/AssignCollectionDialog";
|
||||
import AssignProductDialog from "@saleor/components/AssignProductDialog";
|
||||
|
@ -37,7 +38,6 @@ import {
|
|||
} from "@saleor/discounts/urls";
|
||||
import useBulkActions from "@saleor/hooks/useBulkActions";
|
||||
import useChannels from "@saleor/hooks/useChannels";
|
||||
import useLocalStorage from "@saleor/hooks/useLocalStorage";
|
||||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
import useNotifier from "@saleor/hooks/useNotifier";
|
||||
import usePaginator, {
|
||||
|
@ -145,8 +145,7 @@ export const VoucherDetails: React.FC<VoucherDetailsProps> = ({
|
|||
const [updateChannels, updateChannelsOpts] = useVoucherChannelListingUpdate(
|
||||
{}
|
||||
);
|
||||
|
||||
const [selectedChannel] = useLocalStorage("vouchersListChannel", "");
|
||||
const { channel } = useAppChannel();
|
||||
|
||||
const handleVoucherDelete = (data: VoucherDelete) => {
|
||||
if (data.voucherDelete.errors.length === 0) {
|
||||
|
@ -295,7 +294,7 @@ export const VoucherDetails: React.FC<VoucherDetailsProps> = ({
|
|||
...(updateChannelsOpts.data
|
||||
?.voucherChannelListingUpdate.errors || [])
|
||||
]}
|
||||
selectedChannel={selectedChannel}
|
||||
selectedChannelId={channel.id}
|
||||
pageInfo={pageInfo}
|
||||
onNextPage={loadNextPage}
|
||||
onPreviousPage={loadPreviousPage}
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
import DialogContentText from "@material-ui/core/DialogContentText";
|
||||
import IconButton from "@material-ui/core/IconButton";
|
||||
import DeleteIcon from "@material-ui/icons/Delete";
|
||||
import ChannelSettingsDialog from "@saleor/channels/components/ChannelSettingsDialog";
|
||||
import ActionDialog from "@saleor/components/ActionDialog";
|
||||
import useAppChannel from "@saleor/components/AppLayout/AppChannelContext";
|
||||
import DeleteFilterTabDialog from "@saleor/components/DeleteFilterTabDialog";
|
||||
import SaveFilterTabDialog, {
|
||||
SaveFilterTabDialogFormData
|
||||
} from "@saleor/components/SaveFilterTabDialog";
|
||||
import { WindowTitle } from "@saleor/components/WindowTitle";
|
||||
import useBulkActions from "@saleor/hooks/useBulkActions";
|
||||
import useChannelsSettings from "@saleor/hooks/useChannelsSettings";
|
||||
import useListSettings from "@saleor/hooks/useListSettings";
|
||||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
import useNotifier from "@saleor/hooks/useNotifier";
|
||||
|
@ -65,17 +64,13 @@ export const VoucherList: React.FC<VoucherListProps> = ({ params }) => {
|
|||
);
|
||||
const intl = useIntl();
|
||||
|
||||
const { channel } = useAppChannel();
|
||||
|
||||
const [openModal, closeModal] = createDialogActionHandlers<
|
||||
VoucherListUrlDialog,
|
||||
VoucherListUrlQueryParams
|
||||
>(navigate, voucherListUrl, params);
|
||||
|
||||
const {
|
||||
channelChoices,
|
||||
handleChannelSelectConfirm,
|
||||
selectedChannel
|
||||
} = useChannelsSettings("vouchersListChannel", { closeModal, openModal });
|
||||
|
||||
const paginationState = createPaginationState(settings.rowNumber, params);
|
||||
const queryVariables = React.useMemo(
|
||||
() => ({
|
||||
|
@ -167,16 +162,6 @@ export const VoucherList: React.FC<VoucherListProps> = ({ params }) => {
|
|||
return (
|
||||
<>
|
||||
<WindowTitle title={intl.formatMessage(sectionNames.vouchers)} />
|
||||
{!!channelChoices?.length && (
|
||||
<ChannelSettingsDialog
|
||||
channelsChoices={channelChoices}
|
||||
defaultChoice={selectedChannel}
|
||||
open={params.action === "settings"}
|
||||
confirmButtonState="default"
|
||||
onClose={closeModal}
|
||||
onConfirm={handleChannelSelectConfirm}
|
||||
/>
|
||||
)}
|
||||
<VoucherListPage
|
||||
currentTab={currentTab}
|
||||
filterOpts={getFilterOpts(params)}
|
||||
|
@ -215,12 +200,7 @@ export const VoucherList: React.FC<VoucherListProps> = ({ params }) => {
|
|||
<DeleteIcon />
|
||||
</IconButton>
|
||||
}
|
||||
selectedChannel={selectedChannel}
|
||||
onSettingsOpen={
|
||||
!!channelChoices?.length
|
||||
? () => openModal("settings")
|
||||
: undefined
|
||||
}
|
||||
selectedChannelId={channel.id}
|
||||
/>
|
||||
<ActionDialog
|
||||
confirmButtonState={voucherBulkDeleteOpts.status}
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
import { makeStyles } from "@material-ui/core/styles";
|
||||
import Typography from "@material-ui/core/Typography";
|
||||
import SingleSelectField, {
|
||||
Choices
|
||||
} from "@saleor/components/SingleSelectField";
|
||||
import Skeleton from "@saleor/components/Skeleton";
|
||||
import React from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
const useStyles = makeStyles(
|
||||
theme => ({
|
||||
|
@ -27,16 +24,12 @@ const useStyles = makeStyles(
|
|||
|
||||
interface HomeOrdersCardProps {
|
||||
userName: string;
|
||||
channelChoices: Choices;
|
||||
channelValue: string;
|
||||
onChannelChange: (value: string) => void;
|
||||
}
|
||||
|
||||
const HomeOrdersCard: React.FC<HomeOrdersCardProps> = props => {
|
||||
const { userName, channelChoices, channelValue, onChannelChange } = props;
|
||||
const { userName } = props;
|
||||
|
||||
const classes = useStyles(props);
|
||||
const intl = useIntl();
|
||||
|
||||
return (
|
||||
<div className={classes.headerContainer} data-test="home-header">
|
||||
|
@ -71,20 +64,6 @@ const HomeOrdersCard: React.FC<HomeOrdersCardProps> = props => {
|
|||
)}
|
||||
</Typography>
|
||||
</div>
|
||||
<div>
|
||||
{!!channelChoices?.length && (
|
||||
<SingleSelectField
|
||||
name="channel"
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Channel"
|
||||
})}
|
||||
choices={channelChoices}
|
||||
value={channelValue}
|
||||
onChange={e => onChannelChange(e.target.value)}
|
||||
data-test="channel-select"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -4,7 +4,6 @@ import Container from "@saleor/components/Container";
|
|||
import Grid from "@saleor/components/Grid";
|
||||
import Money from "@saleor/components/Money";
|
||||
import RequirePermissions from "@saleor/components/RequirePermissions";
|
||||
import { Choices } from "@saleor/components/SingleSelectField";
|
||||
import Skeleton from "@saleor/components/Skeleton";
|
||||
import { UserPermissionProps } from "@saleor/types";
|
||||
import { PermissionEnum } from "@saleor/types/globalTypes";
|
||||
|
@ -54,9 +53,6 @@ export interface HomePageProps extends UserPermissionProps {
|
|||
sales: Home_salesToday_gross;
|
||||
topProducts: Home_productTopToday_edges_node[];
|
||||
userName: string;
|
||||
channelChoices: Choices;
|
||||
channelValue: string;
|
||||
onChannelChange: (value: string) => void;
|
||||
onOrdersToCaptureClick: () => void;
|
||||
onOrdersToFulfillClick: () => void;
|
||||
onProductClick: (productId: string, variantId: string) => void;
|
||||
|
@ -65,8 +61,6 @@ export interface HomePageProps extends UserPermissionProps {
|
|||
|
||||
const HomePage: React.FC<HomePageProps> = props => {
|
||||
const {
|
||||
channelChoices,
|
||||
channelValue,
|
||||
userName,
|
||||
orders,
|
||||
sales,
|
||||
|
@ -78,7 +72,6 @@ const HomePage: React.FC<HomePageProps> = props => {
|
|||
onProductsOutOfStockClick,
|
||||
ordersToCapture,
|
||||
ordersToFulfill,
|
||||
onChannelChange,
|
||||
productsOutOfStock,
|
||||
userPermissions
|
||||
} = props;
|
||||
|
@ -87,12 +80,7 @@ const HomePage: React.FC<HomePageProps> = props => {
|
|||
|
||||
return (
|
||||
<Container>
|
||||
<HomeHeader
|
||||
userName={userName}
|
||||
channelValue={channelValue}
|
||||
channelChoices={channelChoices}
|
||||
onChannelChange={onChannelChange}
|
||||
/>
|
||||
<HomeHeader userName={userName} />
|
||||
<CardSpacer />
|
||||
<Grid>
|
||||
<div>
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import { useChannelsList } from "@saleor/channels/queries";
|
||||
import useLocalStorage from "@saleor/hooks/useLocalStorage";
|
||||
import useAppChannel from "@saleor/components/AppLayout/AppChannelContext";
|
||||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
import useUser from "@saleor/hooks/useUser";
|
||||
import React, { useCallback, useEffect } from "react";
|
||||
import React from "react";
|
||||
|
||||
import { getUserName, maybe } from "../../misc";
|
||||
import { orderListUrl } from "../../orders/urls";
|
||||
|
@ -14,29 +13,10 @@ import { HomePageQuery } from "../queries";
|
|||
const HomeSection = () => {
|
||||
const navigate = useNavigator();
|
||||
const { user } = useUser();
|
||||
const { data: channelsData } = useChannelsList({});
|
||||
|
||||
const channelChoices =
|
||||
channelsData?.channels?.map(channel => ({
|
||||
label: channel.name,
|
||||
value: channel.slug
|
||||
})) || [];
|
||||
|
||||
const [channelChoice, setChannelChoice] = useLocalStorage(
|
||||
"homepageChannelChoice",
|
||||
channelChoices?.length ? channelChoices[0]?.value : ""
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!channelChoice && channelChoices[0]) {
|
||||
setChannelChoice(channelChoices[0].value);
|
||||
}
|
||||
}, [channelChoices]);
|
||||
|
||||
const handleChannelChange = useCallback(value => setChannelChoice(value), []);
|
||||
const { channel } = useAppChannel();
|
||||
|
||||
return (
|
||||
<HomePageQuery displayLoader variables={{ channel: channelChoice }}>
|
||||
<HomePageQuery displayLoader variables={{ channel: channel.slug }}>
|
||||
{({ data }) => (
|
||||
<HomePage
|
||||
activities={maybe(() =>
|
||||
|
@ -47,9 +27,6 @@ const HomeSection = () => {
|
|||
topProducts={maybe(() =>
|
||||
data.productTopToday.edges.map(edge => edge.node)
|
||||
)}
|
||||
channelChoices={channelChoices}
|
||||
channelValue={channelChoice}
|
||||
onChannelChange={handleChannelChange}
|
||||
onProductClick={(productId, variantId) =>
|
||||
navigate(productVariantEditUrl(productId, variantId))
|
||||
}
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
import { useChannelsList } from "@saleor/channels/queries";
|
||||
import useLocalStorage from "@saleor/hooks/useLocalStorage";
|
||||
import { useEffect } from "react";
|
||||
|
||||
interface Actions {
|
||||
openModal: (value: string) => void;
|
||||
closeModal: () => void;
|
||||
}
|
||||
|
||||
function useChannelsSettings(key: string, { openModal, closeModal }: Actions) {
|
||||
const { data: channelsData } = useChannelsList({});
|
||||
const channelChoices = channelsData?.channels?.map(channel => ({
|
||||
label: channel.name,
|
||||
value: channel.id
|
||||
}));
|
||||
|
||||
const [selectedChannel, setSelectedChannel] = useLocalStorage(key, "");
|
||||
|
||||
const handleChannelSelectConfirm = (channel: string) => {
|
||||
setSelectedChannel(channel);
|
||||
closeModal();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!selectedChannel) {
|
||||
openModal("settings");
|
||||
}
|
||||
}, [selectedChannel]);
|
||||
|
||||
const channel = channelsData?.channels?.find(
|
||||
channel => channel.id === selectedChannel
|
||||
);
|
||||
|
||||
return {
|
||||
channel,
|
||||
channelChoices,
|
||||
channels: channelsData?.channels,
|
||||
handleChannelSelectConfirm,
|
||||
selectedChannel,
|
||||
slug: channel?.slug
|
||||
};
|
||||
}
|
||||
|
||||
export default useChannelsSettings;
|
|
@ -7,14 +7,26 @@ export default function useLocalStorage<T>(
|
|||
initialValue: T
|
||||
): [T, SetLocalStorage<T>] {
|
||||
const [storedValue, setStoredValue] = useState<T>(() => {
|
||||
const item = window.localStorage.getItem(key);
|
||||
return item ? JSON.parse(item) : initialValue;
|
||||
let result: T;
|
||||
try {
|
||||
const item = window.localStorage.getItem(key);
|
||||
result = item ? JSON.parse(item) : initialValue;
|
||||
} catch {
|
||||
result = initialValue;
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
const setValue = (value: SetLocalStorageValue<T>) => {
|
||||
const valueToStore = value instanceof Function ? value(storedValue) : value;
|
||||
setStoredValue(valueToStore);
|
||||
window.localStorage.setItem(key, JSON.stringify(valueToStore));
|
||||
|
||||
try {
|
||||
window.localStorage.setItem(key, JSON.stringify(valueToStore));
|
||||
} catch {
|
||||
console.warn(`Could not save ${key} to localStorage`);
|
||||
}
|
||||
};
|
||||
|
||||
return [storedValue, setValue];
|
||||
|
|
|
@ -27,6 +27,9 @@ import ChannelsSection from "./channels";
|
|||
import { channelsSection } from "./channels/urls";
|
||||
import CollectionSection from "./collections";
|
||||
import AppLayout from "./components/AppLayout";
|
||||
import useAppChannel, {
|
||||
AppChannelProvider
|
||||
} from "./components/AppLayout/AppChannelContext";
|
||||
import { DateProvider } from "./components/Date";
|
||||
import { LocaleProvider } from "./components/Locale";
|
||||
import MessageManagerProvider from "./components/messages";
|
||||
|
@ -60,7 +63,7 @@ import { PermissionEnum } from "./types/globalTypes";
|
|||
import WarehouseSection from "./warehouses";
|
||||
import { warehouseSection } from "./warehouses/urls";
|
||||
|
||||
if (process.env.GTM_ID !== undefined) {
|
||||
if (process.env.GTM_ID) {
|
||||
TagManager.initialize({ gtmId: GTM_ID });
|
||||
}
|
||||
|
||||
|
@ -111,7 +114,9 @@ const App: React.FC = () => {
|
|||
<AppStateProvider>
|
||||
<ShopProvider>
|
||||
<AuthProvider>
|
||||
<Routes />
|
||||
<AppChannelProvider>
|
||||
<Routes />
|
||||
</AppChannelProvider>
|
||||
</AuthProvider>
|
||||
</ShopProvider>
|
||||
</AppStateProvider>
|
||||
|
@ -135,11 +140,15 @@ const Routes: React.FC = () => {
|
|||
tokenVerifyLoading,
|
||||
user
|
||||
} = useAuth();
|
||||
const { channel } = useAppChannel(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<WindowTitle title={intl.formatMessage(commonMessages.dashboard)} />
|
||||
{isAuthenticated && !tokenAuthLoading && !tokenVerifyLoading ? (
|
||||
{channel &&
|
||||
isAuthenticated &&
|
||||
!tokenAuthLoading &&
|
||||
!tokenVerifyLoading ? (
|
||||
<AppLayout>
|
||||
<ErrorBoundary
|
||||
onError={() =>
|
||||
|
@ -271,7 +280,7 @@ const Routes: React.FC = () => {
|
|||
</Switch>
|
||||
</ErrorBoundary>
|
||||
</AppLayout>
|
||||
) : hasToken && tokenVerifyLoading ? (
|
||||
) : (isAuthenticated && !channel) || (hasToken && tokenVerifyLoading) ? (
|
||||
<LoginLoading />
|
||||
) : (
|
||||
<Auth />
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import Button from "@material-ui/core/Button";
|
||||
import Card from "@material-ui/core/Card";
|
||||
import makeStyles from "@material-ui/core/styles/makeStyles";
|
||||
import CardMenu from "@saleor/components/CardMenu";
|
||||
import Container from "@saleor/components/Container";
|
||||
import FilterBar from "@saleor/components/FilterBar";
|
||||
import PageHeader from "@saleor/components/PageHeader";
|
||||
|
@ -32,18 +30,8 @@ export interface OrderDraftListPageProps
|
|||
SortPage<OrderDraftListUrlSortField>,
|
||||
TabPageProps {
|
||||
orders: OrderDraftList_draftOrders_edges_node[];
|
||||
onSettingsOpen?: () => void;
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(
|
||||
theme => ({
|
||||
settings: {
|
||||
marginRight: theme.spacing(2)
|
||||
}
|
||||
}),
|
||||
{ name: "OrderDraftListPage" }
|
||||
);
|
||||
|
||||
const OrderDraftListPage: React.FC<OrderDraftListPageProps> = ({
|
||||
currentTab,
|
||||
disabled,
|
||||
|
@ -53,7 +41,6 @@ const OrderDraftListPage: React.FC<OrderDraftListPageProps> = ({
|
|||
onAll,
|
||||
onFilterChange,
|
||||
onSearchChange,
|
||||
onSettingsOpen,
|
||||
onTabChange,
|
||||
onTabDelete,
|
||||
onTabSave,
|
||||
|
@ -61,26 +48,11 @@ const OrderDraftListPage: React.FC<OrderDraftListPageProps> = ({
|
|||
...listProps
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const classes = useStyles({});
|
||||
const structure = createFilterStructure(intl, filterOpts);
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<PageHeader title={intl.formatMessage(sectionNames.draftOrders)}>
|
||||
{!!onSettingsOpen && (
|
||||
<CardMenu
|
||||
className={classes.settings}
|
||||
menuItems={[
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: "Settings",
|
||||
description: "button"
|
||||
}),
|
||||
onSelect: onSettingsOpen
|
||||
}
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
<Button
|
||||
color="primary"
|
||||
variant="contained"
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import Button from "@material-ui/core/Button";
|
||||
import Card from "@material-ui/core/Card";
|
||||
import makeStyles from "@material-ui/core/styles/makeStyles";
|
||||
import CardMenu from "@saleor/components/CardMenu";
|
||||
import Container from "@saleor/components/Container";
|
||||
import FilterBar from "@saleor/components/FilterBar";
|
||||
import PageHeader from "@saleor/components/PageHeader";
|
||||
|
@ -24,18 +22,8 @@ export interface OrderListPageProps
|
|||
FilterPageProps<OrderFilterKeys, OrderListFilterOpts>,
|
||||
SortPage<OrderListUrlSortField> {
|
||||
orders: OrderList_orders_edges_node[];
|
||||
onSettingsOpen?: () => void;
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(
|
||||
theme => ({
|
||||
settings: {
|
||||
marginRight: theme.spacing(2)
|
||||
}
|
||||
}),
|
||||
{ name: "OrderListPage" }
|
||||
);
|
||||
|
||||
const OrderListPage: React.FC<OrderListPageProps> = ({
|
||||
currentTab,
|
||||
initialSearch,
|
||||
|
@ -44,7 +32,6 @@ const OrderListPage: React.FC<OrderListPageProps> = ({
|
|||
onAdd,
|
||||
onAll,
|
||||
onSearchChange,
|
||||
onSettingsOpen,
|
||||
onFilterChange,
|
||||
onTabChange,
|
||||
onTabDelete,
|
||||
|
@ -52,26 +39,11 @@ const OrderListPage: React.FC<OrderListPageProps> = ({
|
|||
...listProps
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const classes = useStyles({});
|
||||
const filterStructure = createFilterStructure(intl, filterOpts);
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<PageHeader title={intl.formatMessage(sectionNames.orders)}>
|
||||
{!!onSettingsOpen && (
|
||||
<CardMenu
|
||||
className={classes.settings}
|
||||
menuItems={[
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: "Settings",
|
||||
description: "button"
|
||||
}),
|
||||
onSelect: onSettingsOpen
|
||||
}
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
<Button color="primary" variant="contained" onClick={onAdd}>
|
||||
<FormattedMessage
|
||||
defaultMessage="Create order"
|
||||
|
|
|
@ -24,7 +24,7 @@ import useModalDialogOpen from "@saleor/hooks/useModalDialogOpen";
|
|||
import useSearchQuery from "@saleor/hooks/useSearchQuery";
|
||||
import { buttonMessages } from "@saleor/intl";
|
||||
import { maybe, renderCollection } from "@saleor/misc";
|
||||
import { FetchMoreProps } from "@saleor/types";
|
||||
import { ChannelProps, FetchMoreProps } from "@saleor/types";
|
||||
import getOrderErrorMessage from "@saleor/utils/errors/order";
|
||||
import React from "react";
|
||||
import InfiniteScroll from "react-infinite-scroller";
|
||||
|
@ -87,12 +87,13 @@ type SetVariantsAction = (
|
|||
data: SearchOrderVariant_search_edges_node_variants[]
|
||||
) => void;
|
||||
|
||||
export interface OrderProductAddDialogProps extends FetchMoreProps {
|
||||
export interface OrderProductAddDialogProps
|
||||
extends FetchMoreProps,
|
||||
ChannelProps {
|
||||
confirmButtonState: ConfirmButtonTransitionState;
|
||||
errors: OrderErrorFragment[];
|
||||
open: boolean;
|
||||
products: SearchOrderVariant_search_edges_node[];
|
||||
selectedChannel: string;
|
||||
onClose: () => void;
|
||||
onFetch: (query: string) => void;
|
||||
onSubmit: (data: SearchOrderVariant_search_edges_node_variants[]) => void;
|
||||
|
@ -169,7 +170,7 @@ const OrderProductAddDialog: React.FC<OrderProductAddDialogProps> = props => {
|
|||
loading,
|
||||
hasMore,
|
||||
products,
|
||||
selectedChannel,
|
||||
selectedChannelId,
|
||||
onFetch,
|
||||
onFetchMore,
|
||||
onClose,
|
||||
|
@ -257,7 +258,7 @@ const OrderProductAddDialog: React.FC<OrderProductAddDialogProps> = props => {
|
|||
(product, productIndex) =>
|
||||
product.variants.some(variant =>
|
||||
variant.channelListings.some(
|
||||
listing => listing.channel.id === selectedChannel
|
||||
listing => listing.channel.id === selectedChannelId
|
||||
)
|
||||
) ? (
|
||||
<React.Fragment key={product ? product.id : "skeleton"}>
|
||||
|
@ -293,7 +294,7 @@ const OrderProductAddDialog: React.FC<OrderProductAddDialogProps> = props => {
|
|||
{maybe(() => product.variants, []).map(
|
||||
(variant, variantIndex) =>
|
||||
variant.channelListings.some(
|
||||
listing => listing.channel.id === selectedChannel
|
||||
listing => listing.channel.id === selectedChannelId
|
||||
) ? (
|
||||
<TableRow key={variant.id}>
|
||||
<TableCell />
|
||||
|
|
|
@ -31,7 +31,10 @@ import {
|
|||
OrderDraftCancel,
|
||||
OrderDraftCancelVariables
|
||||
} from "./types/OrderDraftCancel";
|
||||
import { OrderDraftCreate } from "./types/OrderDraftCreate";
|
||||
import {
|
||||
OrderDraftCreate,
|
||||
OrderDraftCreateVariables
|
||||
} from "./types/OrderDraftCreate";
|
||||
import {
|
||||
OrderDraftFinalize,
|
||||
OrderDraftFinalizeVariables
|
||||
|
@ -371,9 +374,10 @@ const orderDraftCreateMutation = gql`
|
|||
}
|
||||
}
|
||||
`;
|
||||
export const useOrderDraftCreateMutation = makeMutation<OrderDraftCreate, {}>(
|
||||
orderDraftCreateMutation
|
||||
);
|
||||
export const useOrderDraftCreateMutation = makeMutation<
|
||||
OrderDraftCreate,
|
||||
OrderDraftCreateVariables
|
||||
>(orderDraftCreateMutation);
|
||||
|
||||
const orderLineDeleteMutation = gql`
|
||||
${fragmentOrderDetails}
|
||||
|
|
|
@ -28,7 +28,7 @@ export enum OrderListUrlFiltersWithMultipleValuesEnum {
|
|||
}
|
||||
export type OrderListUrlFilters = Filters<OrderListUrlFiltersEnum> &
|
||||
FiltersWithMultipleValues<OrderListUrlFiltersWithMultipleValuesEnum>;
|
||||
export type OrderListUrlDialog = "cancel" | "settings" | TabActionDialog;
|
||||
export type OrderListUrlDialog = "cancel" | TabActionDialog;
|
||||
export enum OrderListUrlSortField {
|
||||
number = "number",
|
||||
customer = "customer",
|
||||
|
@ -61,7 +61,7 @@ export enum OrderDraftListUrlFiltersEnum {
|
|||
query = "query"
|
||||
}
|
||||
export type OrderDraftListUrlFilters = Filters<OrderDraftListUrlFiltersEnum>;
|
||||
export type OrderDraftListUrlDialog = "remove" | "settings" | TabActionDialog;
|
||||
export type OrderDraftListUrlDialog = "remove" | TabActionDialog;
|
||||
export enum OrderDraftListUrlSortField {
|
||||
number = "number",
|
||||
customer = "customer",
|
||||
|
|
|
@ -561,7 +561,7 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
|
|||
products={variantSearchOpts.data?.search.edges.map(
|
||||
edge => edge.node
|
||||
)}
|
||||
selectedChannel={order?.channel?.id}
|
||||
selectedChannelId={order?.channel?.id}
|
||||
onClose={closeModal}
|
||||
onFetch={variantSearch}
|
||||
onFetchMore={loadMore}
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
import DialogContentText from "@material-ui/core/DialogContentText";
|
||||
import IconButton from "@material-ui/core/IconButton";
|
||||
import DeleteIcon from "@material-ui/icons/Delete";
|
||||
import ChannelSettingsDialog from "@saleor/channels/components/ChannelSettingsDialog";
|
||||
import ActionDialog from "@saleor/components/ActionDialog";
|
||||
import useAppChannel from "@saleor/components/AppLayout/AppChannelContext";
|
||||
import DeleteFilterTabDialog from "@saleor/components/DeleteFilterTabDialog";
|
||||
import SaveFilterTabDialog, {
|
||||
SaveFilterTabDialogFormData
|
||||
} from "@saleor/components/SaveFilterTabDialog";
|
||||
import useBulkActions from "@saleor/hooks/useBulkActions";
|
||||
import useChannelsSettings from "@saleor/hooks/useChannelsSettings";
|
||||
import useListSettings from "@saleor/hooks/useListSettings";
|
||||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
import useNotifier from "@saleor/hooks/useNotifier";
|
||||
|
@ -80,6 +79,8 @@ export const OrderDraftList: React.FC<OrderDraftListProps> = ({ params }) => {
|
|||
onCompleted: handleCreateOrderCreateSuccess
|
||||
});
|
||||
|
||||
const { channel } = useAppChannel();
|
||||
|
||||
const tabs = getFilterTabs();
|
||||
|
||||
const currentTab =
|
||||
|
@ -106,12 +107,6 @@ export const OrderDraftList: React.FC<OrderDraftListProps> = ({ params }) => {
|
|||
OrderDraftListUrlQueryParams
|
||||
>(navigate, orderDraftListUrl, params);
|
||||
|
||||
const {
|
||||
channelChoices,
|
||||
handleChannelSelectConfirm,
|
||||
selectedChannel
|
||||
} = useChannelsSettings("ordersDraftListChannel", { closeModal, openModal });
|
||||
|
||||
const handleTabChange = (tab: number) => {
|
||||
reset();
|
||||
navigate(
|
||||
|
@ -171,16 +166,6 @@ export const OrderDraftList: React.FC<OrderDraftListProps> = ({ params }) => {
|
|||
|
||||
return (
|
||||
<>
|
||||
{!!channelChoices?.length && (
|
||||
<ChannelSettingsDialog
|
||||
channelsChoices={channelChoices}
|
||||
defaultChoice={selectedChannel}
|
||||
open={params.action === "settings"}
|
||||
confirmButtonState="default"
|
||||
onClose={closeModal}
|
||||
onConfirm={handleChannelSelectConfirm}
|
||||
/>
|
||||
)}
|
||||
<TypedOrderDraftBulkCancelMutation
|
||||
onCompleted={handleOrderDraftBulkCancel}
|
||||
>
|
||||
|
@ -214,7 +199,7 @@ export const OrderDraftList: React.FC<OrderDraftListProps> = ({ params }) => {
|
|||
onAdd={() =>
|
||||
createOrder({
|
||||
variables: {
|
||||
input: { channel: selectedChannel }
|
||||
input: { channel: channel.id }
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -240,11 +225,6 @@ export const OrderDraftList: React.FC<OrderDraftListProps> = ({ params }) => {
|
|||
<DeleteIcon />
|
||||
</IconButton>
|
||||
}
|
||||
onSettingsOpen={
|
||||
!!channelChoices?.length
|
||||
? () => openModal("settings")
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
<ActionDialog
|
||||
confirmButtonState={orderDraftBulkDeleteOpts.status}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import ChannelSettingsDialog from "@saleor/channels/components/ChannelSettingsDialog";
|
||||
import useAppChannel from "@saleor/components/AppLayout/AppChannelContext";
|
||||
import DeleteFilterTabDialog from "@saleor/components/DeleteFilterTabDialog";
|
||||
import SaveFilterTabDialog, {
|
||||
SaveFilterTabDialogFormData
|
||||
} from "@saleor/components/SaveFilterTabDialog";
|
||||
import useChannelsSettings from "@saleor/hooks/useChannelsSettings";
|
||||
import useListSettings from "@saleor/hooks/useListSettings";
|
||||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
import useNotifier from "@saleor/hooks/useNotifier";
|
||||
|
@ -68,6 +67,8 @@ export const OrderList: React.FC<OrderListProps> = ({ params }) => {
|
|||
onCompleted: handleCreateOrderCreateSuccess
|
||||
});
|
||||
|
||||
const { channel } = useAppChannel();
|
||||
|
||||
const tabs = getFilterTabs();
|
||||
|
||||
const currentTab =
|
||||
|
@ -93,12 +94,6 @@ export const OrderList: React.FC<OrderListProps> = ({ params }) => {
|
|||
OrderListUrlQueryParams
|
||||
>(navigate, orderListUrl, params);
|
||||
|
||||
const {
|
||||
channelChoices,
|
||||
handleChannelSelectConfirm,
|
||||
selectedChannel
|
||||
} = useChannelsSettings("ordersListChannel", { closeModal, openModal });
|
||||
|
||||
const handleTabChange = (tab: number) =>
|
||||
navigate(
|
||||
orderListUrl({
|
||||
|
@ -142,16 +137,6 @@ export const OrderList: React.FC<OrderListProps> = ({ params }) => {
|
|||
|
||||
return (
|
||||
<>
|
||||
{!!channelChoices?.length && (
|
||||
<ChannelSettingsDialog
|
||||
channelsChoices={channelChoices}
|
||||
defaultChoice={selectedChannel}
|
||||
open={params.action === "settings"}
|
||||
confirmButtonState="default"
|
||||
onClose={closeModal}
|
||||
onConfirm={handleChannelSelectConfirm}
|
||||
/>
|
||||
)}
|
||||
<OrderListPage
|
||||
settings={settings}
|
||||
currentTab={currentTab}
|
||||
|
@ -163,7 +148,7 @@ export const OrderList: React.FC<OrderListProps> = ({ params }) => {
|
|||
onAdd={() =>
|
||||
createOrder({
|
||||
variables: {
|
||||
input: { channel: selectedChannel }
|
||||
input: { channel: channel.id }
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -180,9 +165,6 @@ export const OrderList: React.FC<OrderListProps> = ({ params }) => {
|
|||
initialSearch={params.query || ""}
|
||||
tabs={getFilterTabs().map(tab => tab.name)}
|
||||
onAll={resetFilters}
|
||||
onSettingsOpen={
|
||||
!!channelChoices?.length ? () => openModal("settings") : undefined
|
||||
}
|
||||
/>
|
||||
<SaveFilterTabDialog
|
||||
open={params.action === "save-search"}
|
||||
|
|
|
@ -24,7 +24,7 @@ import {
|
|||
import { GridAttributes_grid_edges_node } from "@saleor/products/types/GridAttributes";
|
||||
import { ProductList_products_edges_node } from "@saleor/products/types/ProductList";
|
||||
import { ProductListUrlSortField } from "@saleor/products/urls";
|
||||
import { ListActions, ListProps, SortPage } from "@saleor/types";
|
||||
import { ChannelProps, ListActions, ListProps, SortPage } from "@saleor/types";
|
||||
import TDisplayColumn, {
|
||||
DisplayColumnProps
|
||||
} from "@saleor/utils/columns/DisplayColumn";
|
||||
|
@ -99,12 +99,12 @@ const DisplayColumn = TDisplayColumn as React.FunctionComponent<
|
|||
interface ProductListProps
|
||||
extends ListProps<ProductListColumns>,
|
||||
ListActions,
|
||||
SortPage<ProductListUrlSortField> {
|
||||
SortPage<ProductListUrlSortField>,
|
||||
ChannelProps {
|
||||
activeAttributeSortId: string;
|
||||
gridAttributes: GridAttributes_grid_edges_node[];
|
||||
products: ProductList_products_edges_node[];
|
||||
loading: boolean;
|
||||
selectedChannel: string;
|
||||
channelsCount: number;
|
||||
}
|
||||
|
||||
|
@ -128,7 +128,7 @@ export const ProductList: React.FC<ProductListProps> = props => {
|
|||
onUpdateListSettings,
|
||||
onRowClick,
|
||||
onSort,
|
||||
selectedChannel
|
||||
selectedChannelId
|
||||
} = props;
|
||||
|
||||
const classes = useStyles(props);
|
||||
|
@ -286,7 +286,7 @@ export const ProductList: React.FC<ProductListProps> = props => {
|
|||
product => {
|
||||
const isSelected = product ? isChecked(product.id) : false;
|
||||
const channel = product?.channelListings.find(
|
||||
listing => listing.channel.id === selectedChannel
|
||||
listing => listing.channel.id === selectedChannelId
|
||||
);
|
||||
|
||||
return (
|
||||
|
@ -362,9 +362,7 @@ export const ProductList: React.FC<ProductListProps> = props => {
|
|||
) : product?.channelListings !== undefined ? (
|
||||
<ChannelsAvailabilityDropdown
|
||||
allChannelsCount={channelsCount}
|
||||
currentChannel={
|
||||
channel || product?.channelListings[0]
|
||||
}
|
||||
currentChannel={channel}
|
||||
channels={product?.channelListings}
|
||||
/>
|
||||
) : (
|
||||
|
|
|
@ -16,6 +16,7 @@ import {
|
|||
} from "@saleor/products/types/GridAttributes";
|
||||
import { ProductList_products_edges_node } from "@saleor/products/types/ProductList";
|
||||
import {
|
||||
ChannelProps,
|
||||
FetchMoreProps,
|
||||
FilterPageProps,
|
||||
ListActions,
|
||||
|
@ -38,7 +39,8 @@ export interface ProductListPageProps
|
|||
ListActions,
|
||||
FilterPageProps<ProductFilterKeys, ProductListFilterOpts>,
|
||||
FetchMoreProps,
|
||||
SortPage<ProductListUrlSortField> {
|
||||
SortPage<ProductListUrlSortField>,
|
||||
ChannelProps {
|
||||
activeAttributeSortId: string;
|
||||
availableInGridAttributes: GridAttributes_availableInGrid_edges_node[];
|
||||
channelsCount: number;
|
||||
|
@ -47,8 +49,6 @@ export interface ProductListPageProps
|
|||
totalGridAttributes: number;
|
||||
products: ProductList_products_edges_node[];
|
||||
onExport: () => void;
|
||||
selectedChannel: string;
|
||||
onSettingsOpen?: () => void;
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(
|
||||
|
@ -84,12 +84,11 @@ export const ProductListPage: React.FC<ProductListPageProps> = props => {
|
|||
onFetchMore,
|
||||
onFilterChange,
|
||||
onSearchChange,
|
||||
onSettingsOpen,
|
||||
onTabChange,
|
||||
onTabDelete,
|
||||
onTabSave,
|
||||
onUpdateListSettings,
|
||||
selectedChannel,
|
||||
selectedChannelId,
|
||||
...listProps
|
||||
} = props;
|
||||
const intl = useIntl();
|
||||
|
@ -134,13 +133,6 @@ export const ProductListPage: React.FC<ProductListPageProps> = props => {
|
|||
}),
|
||||
onSelect: onExport,
|
||||
testId: "export"
|
||||
},
|
||||
onSettingsOpen && {
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: "Settings",
|
||||
description: "button"
|
||||
}),
|
||||
onSelect: onSettingsOpen
|
||||
}
|
||||
]}
|
||||
data-test="menu"
|
||||
|
@ -199,7 +191,7 @@ export const ProductListPage: React.FC<ProductListPageProps> = props => {
|
|||
gridAttributes={gridAttributes}
|
||||
settings={settings}
|
||||
channelsCount={channelsCount}
|
||||
selectedChannel={selectedChannel}
|
||||
selectedChannelId={selectedChannelId}
|
||||
onUpdateListSettings={onUpdateListSettings}
|
||||
/>
|
||||
</Card>
|
||||
|
|
|
@ -58,6 +58,7 @@ const props: ProductUpdatePageProps = {
|
|||
placeholderImage,
|
||||
product,
|
||||
saveButtonBarState: "default",
|
||||
selectedChannelId: "123",
|
||||
taxTypes,
|
||||
variants: product.variants,
|
||||
warehouses: warehouseList
|
||||
|
|
|
@ -22,7 +22,12 @@ import { maybe } from "@saleor/misc";
|
|||
import ProductVariantPrice from "@saleor/products/components/ProductVariantPrice";
|
||||
import { SearchCategories_search_edges_node } from "@saleor/searches/types/SearchCategories";
|
||||
import { SearchCollections_search_edges_node } from "@saleor/searches/types/SearchCollections";
|
||||
import { FetchMoreProps, ListActions, ReorderAction } from "@saleor/types";
|
||||
import {
|
||||
ChannelProps,
|
||||
FetchMoreProps,
|
||||
ListActions,
|
||||
ReorderAction
|
||||
} from "@saleor/types";
|
||||
import React from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
|
@ -42,7 +47,7 @@ import ProductTaxes from "../ProductTaxes";
|
|||
import ProductVariants from "../ProductVariants";
|
||||
import ProductUpdateForm from "./form";
|
||||
|
||||
export interface ProductUpdatePageProps extends ListActions {
|
||||
export interface ProductUpdatePageProps extends ListActions, ChannelProps {
|
||||
defaultWeightUnit: string;
|
||||
errors: ProductErrorWithAttributesFragment[];
|
||||
channelsErrors: ProductChannelListingErrorFragment[];
|
||||
|
@ -83,7 +88,9 @@ export interface ProductUpdatePageProps extends ListActions {
|
|||
onWarehouseConfigure();
|
||||
}
|
||||
|
||||
export interface ProductUpdatePageSubmitData extends ProductUpdatePageFormData {
|
||||
export interface ProductUpdatePageSubmitData
|
||||
extends ProductUpdatePageFormData,
|
||||
ChannelProps {
|
||||
addStocks: ProductStockInput[];
|
||||
attributes: ProductAttributeInput[];
|
||||
collections: string[];
|
||||
|
@ -96,7 +103,6 @@ export const ProductUpdatePage: React.FC<ProductUpdatePageProps> = ({
|
|||
defaultWeightUnit,
|
||||
disabled,
|
||||
categories: categoryChoiceList,
|
||||
channelChoices,
|
||||
channelsErrors,
|
||||
allChannelsCount,
|
||||
currentChannels = [],
|
||||
|
@ -133,6 +139,7 @@ export const ProductUpdatePage: React.FC<ProductUpdatePageProps> = ({
|
|||
onWarehouseConfigure,
|
||||
isChecked,
|
||||
selected,
|
||||
selectedChannelId,
|
||||
toggle,
|
||||
toggleAll,
|
||||
toolbar
|
||||
|
@ -235,7 +242,6 @@ export const ProductUpdatePage: React.FC<ProductUpdatePageProps> = ({
|
|||
disabled={disabled}
|
||||
variants={variants}
|
||||
product={product}
|
||||
channelChoices={channelChoices}
|
||||
onRowClick={onVariantShow}
|
||||
onVariantAdd={onVariantAdd}
|
||||
onVariantsAdd={onVariantsAdd}
|
||||
|
@ -244,6 +250,7 @@ export const ProductUpdatePage: React.FC<ProductUpdatePageProps> = ({
|
|||
toolbar={toolbar}
|
||||
isChecked={isChecked}
|
||||
selected={selected}
|
||||
selectedChannelId={selectedChannelId}
|
||||
toggle={toggle}
|
||||
toggleAll={toggleAll}
|
||||
/>
|
||||
|
|
|
@ -7,7 +7,6 @@ import { fade } from "@material-ui/core/styles/colorManipulator";
|
|||
import TableCell from "@material-ui/core/TableCell";
|
||||
import Typography from "@material-ui/core/Typography";
|
||||
import CardTitle from "@saleor/components/CardTitle";
|
||||
import { ChannelsSelect } from "@saleor/components/ChannelsSelect";
|
||||
import Checkbox from "@saleor/components/Checkbox";
|
||||
import LinkChoice from "@saleor/components/LinkChoice";
|
||||
import Money from "@saleor/components/Money";
|
||||
|
@ -19,12 +18,11 @@ import {
|
|||
SortableTableRow
|
||||
} from "@saleor/components/SortableTable";
|
||||
import TableHead from "@saleor/components/TableHead";
|
||||
import useStateFromProps from "@saleor/hooks/useStateFromProps";
|
||||
import React from "react";
|
||||
import { FormattedMessage, IntlShape, useIntl } from "react-intl";
|
||||
|
||||
import { maybe, renderCollection } from "../../../misc";
|
||||
import { ListActions, ReorderAction } from "../../../types";
|
||||
import { ChannelProps, ListActions, ReorderAction } from "../../../types";
|
||||
import {
|
||||
ProductDetails_product,
|
||||
ProductDetails_product_variants,
|
||||
|
@ -84,9 +82,6 @@ const useStyles = makeStyles(
|
|||
width: 200
|
||||
}
|
||||
},
|
||||
channelSelect: {
|
||||
marginRight: theme.spacing(1)
|
||||
},
|
||||
colGrab: {
|
||||
width: 60
|
||||
},
|
||||
|
@ -183,12 +178,11 @@ function getAvailabilityLabel(
|
|||
}
|
||||
}
|
||||
|
||||
interface ProductVariantsProps extends ListActions {
|
||||
interface ProductVariantsProps extends ListActions, ChannelProps {
|
||||
disabled: boolean;
|
||||
product: ProductDetails_product;
|
||||
variants: ProductDetails_product_variants[];
|
||||
onVariantReorder: ReorderAction;
|
||||
channelChoices: SingleAutocompleteChoiceType[];
|
||||
onRowClick: (id: string) => () => void;
|
||||
onSetDefaultVariant(variant: ProductDetails_product_variants);
|
||||
onVariantAdd?();
|
||||
|
@ -199,7 +193,6 @@ const numberOfColumns = 7;
|
|||
|
||||
export const ProductVariants: React.FC<ProductVariantsProps> = props => {
|
||||
const {
|
||||
channelChoices,
|
||||
disabled,
|
||||
variants,
|
||||
product,
|
||||
|
@ -210,6 +203,7 @@ export const ProductVariants: React.FC<ProductVariantsProps> = props => {
|
|||
onSetDefaultVariant,
|
||||
isChecked,
|
||||
selected,
|
||||
selectedChannelId,
|
||||
toggle,
|
||||
toggleAll,
|
||||
toolbar
|
||||
|
@ -218,9 +212,6 @@ export const ProductVariants: React.FC<ProductVariantsProps> = props => {
|
|||
|
||||
const intl = useIntl();
|
||||
const [warehouse, setWarehouse] = React.useState<string>(null);
|
||||
const [channelChoice, setChannelChoice] = useStateFromProps(
|
||||
channelChoices[0]?.value
|
||||
);
|
||||
const hasVariants = maybe(() => variants.length > 0, true);
|
||||
|
||||
return (
|
||||
|
@ -261,11 +252,6 @@ export const ProductVariants: React.FC<ProductVariantsProps> = props => {
|
|||
|
||||
{variants.length > 0 ? (
|
||||
<CardContent className={classes.warehouseSelectContainer}>
|
||||
<ChannelsSelect
|
||||
channelChoice={channelChoice}
|
||||
channelChoices={channelChoices}
|
||||
setChannelChoice={setChannelChoice}
|
||||
/>
|
||||
<Typography className={classes.warehouseLabel}>
|
||||
<FormattedMessage
|
||||
defaultMessage="Available inventory at:"
|
||||
|
@ -345,7 +331,7 @@ export const ProductVariants: React.FC<ProductVariantsProps> = props => {
|
|||
)
|
||||
: null;
|
||||
const channel = variant.channelListings.find(
|
||||
listing => listing.channel.id === channelChoice
|
||||
listing => listing.channel.id === selectedChannelId
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
@ -19,11 +19,7 @@ export const productAddPath = urlJoin(productSection, "add");
|
|||
export const productAddUrl = productAddPath;
|
||||
|
||||
export const productListPath = productSection;
|
||||
export type ProductListUrlDialog =
|
||||
| "settings"
|
||||
| "delete"
|
||||
| "export"
|
||||
| TabActionDialog;
|
||||
export type ProductListUrlDialog = "delete" | "export" | TabActionDialog;
|
||||
export enum ProductListUrlFiltersEnum {
|
||||
priceFrom = "priceFrom",
|
||||
priceTo = "priceTo",
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import DialogContentText from "@material-ui/core/DialogContentText";
|
||||
import IconButton from "@material-ui/core/IconButton";
|
||||
import DeleteIcon from "@material-ui/icons/Delete";
|
||||
import ChannelSettingsDialog from "@saleor/channels/components/ChannelSettingsDialog";
|
||||
import ActionDialog from "@saleor/components/ActionDialog";
|
||||
import useAppChannel from "@saleor/components/AppLayout/AppChannelContext";
|
||||
import DeleteFilterTabDialog from "@saleor/components/DeleteFilterTabDialog";
|
||||
import SaveFilterTabDialog, {
|
||||
SaveFilterTabDialogFormData
|
||||
|
@ -16,7 +16,6 @@ import {
|
|||
import { Task } from "@saleor/containers/BackgroundTasks/types";
|
||||
import useBackgroundTask from "@saleor/hooks/useBackgroundTask";
|
||||
import useBulkActions from "@saleor/hooks/useBulkActions";
|
||||
import useChannelsSettings from "@saleor/hooks/useChannelsSettings";
|
||||
import useListSettings from "@saleor/hooks/useListSettings";
|
||||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
import useNotifier from "@saleor/hooks/useNotifier";
|
||||
|
@ -126,33 +125,25 @@ export const ProductList: React.FC<ProductListProps> = ({ params }) => {
|
|||
first: 100
|
||||
}
|
||||
});
|
||||
const { availableChannels, channel } = useAppChannel();
|
||||
|
||||
const [openModal, closeModal] = createDialogActionHandlers<
|
||||
ProductListUrlDialog,
|
||||
ProductListUrlQueryParams
|
||||
>(navigate, productListUrl, params);
|
||||
|
||||
const {
|
||||
channel,
|
||||
channels,
|
||||
channelChoices,
|
||||
handleChannelSelectConfirm,
|
||||
selectedChannel,
|
||||
slug
|
||||
} = useChannelsSettings("productsListChannel", { closeModal, openModal });
|
||||
|
||||
React.useEffect(() => {
|
||||
const action = selectedChannel
|
||||
? {}
|
||||
: { action: "settings" as ProductListUrlDialog };
|
||||
navigate(
|
||||
productListUrl({
|
||||
...{ ...params, ...action },
|
||||
...DEFAULT_INITIAL_PAGINATION_DATA
|
||||
}),
|
||||
true
|
||||
);
|
||||
}, [settings.rowNumber]);
|
||||
// Reset pagination
|
||||
React.useEffect(
|
||||
() =>
|
||||
navigate(
|
||||
productListUrl({
|
||||
...params,
|
||||
...DEFAULT_INITIAL_PAGINATION_DATA
|
||||
}),
|
||||
true
|
||||
),
|
||||
[settings.rowNumber]
|
||||
);
|
||||
|
||||
const tabs = getFilterTabs();
|
||||
|
||||
|
@ -231,13 +222,13 @@ export const ProductList: React.FC<ProductListProps> = ({ params }) => {
|
|||
);
|
||||
|
||||
const paginationState = createPaginationState(settings.rowNumber, params);
|
||||
const filter = getFilterVariables(params, slug);
|
||||
const sort = getSortQueryVariables(params, slug);
|
||||
const filter = getFilterVariables(params, channel.slug);
|
||||
const sort = getSortQueryVariables(params, channel.slug);
|
||||
const queryVariables = React.useMemo<ProductListVariables>(
|
||||
() => ({
|
||||
...paginationState,
|
||||
filter,
|
||||
...(slug ? { sort } : {})
|
||||
sort
|
||||
}),
|
||||
[params, settings.rowNumber]
|
||||
);
|
||||
|
@ -388,22 +379,9 @@ export const ProductList: React.FC<ProductListProps> = ({ params }) => {
|
|||
initialSearch={params.query || ""}
|
||||
tabs={getFilterTabs().map(tab => tab.name)}
|
||||
onExport={() => openModal("export")}
|
||||
channelsCount={channelChoices?.length}
|
||||
selectedChannel={selectedChannel}
|
||||
onSettingsOpen={
|
||||
!!channelChoices?.length ? () => openModal("settings") : undefined
|
||||
}
|
||||
channelsCount={availableChannels?.length}
|
||||
selectedChannelId={channel.id}
|
||||
/>
|
||||
{!!channelChoices?.length && (
|
||||
<ChannelSettingsDialog
|
||||
channelsChoices={channelChoices}
|
||||
defaultChoice={selectedChannel}
|
||||
open={params.action === "settings"}
|
||||
confirmButtonState="default"
|
||||
onClose={closeModal}
|
||||
onConfirm={handleChannelSelectConfirm}
|
||||
/>
|
||||
)}
|
||||
<ActionDialog
|
||||
open={params.action === "delete"}
|
||||
confirmButtonState={productBulkDeleteOpts.status}
|
||||
|
@ -449,7 +427,7 @@ export const ProductList: React.FC<ProductListProps> = ({ params }) => {
|
|||
warehouses={
|
||||
warehouses.data?.warehouses.edges.map(edge => edge.node) || []
|
||||
}
|
||||
channels={channels}
|
||||
channels={availableChannels}
|
||||
onClose={closeModal}
|
||||
onSubmit={data =>
|
||||
exportProducts({
|
||||
|
|
|
@ -9,6 +9,7 @@ import {
|
|||
createSortedChannelsDataFromProduct
|
||||
} from "@saleor/channels/utils";
|
||||
import ActionDialog from "@saleor/components/ActionDialog";
|
||||
import useAppChannel from "@saleor/components/AppLayout/AppChannelContext";
|
||||
import ChannelsAvailabilityDialog from "@saleor/components/ChannelsAvailabilityDialog";
|
||||
import NotFoundPage from "@saleor/components/NotFoundPage";
|
||||
import { WindowTitle } from "@saleor/components/WindowTitle";
|
||||
|
@ -114,6 +115,7 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = ({ id, params }) => {
|
|||
displayLoader: true,
|
||||
variables: { id }
|
||||
});
|
||||
const { channel } = useAppChannel();
|
||||
|
||||
const handleUpdate = (data: ProductUpdateMutationResult) => {
|
||||
if (data.productUpdate.errors.length === 0) {
|
||||
|
@ -404,6 +406,7 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = ({ id, params }) => {
|
|||
loading: searchCollectionsOpts.loading,
|
||||
onFetchMore: loadMoreCollections
|
||||
}}
|
||||
selectedChannelId={channel.id}
|
||||
openChannelsModal={handleChannelsModalOpen}
|
||||
onChannelsChange={setCurrentChannels}
|
||||
/>
|
||||
|
|
|
@ -21,7 +21,7 @@ import React from "react";
|
|||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
|
||||
import { getStringOrPlaceholder } from "../../../misc";
|
||||
import { FetchMoreProps, SearchProps } from "../../../types";
|
||||
import { ChannelProps, FetchMoreProps, SearchProps } from "../../../types";
|
||||
import { ShippingMethodTypeEnum } from "../../../types/globalTypes";
|
||||
import ShippingZoneInfo from "../ShippingZoneInfo";
|
||||
import ShippingZoneRates from "../ShippingZoneRates";
|
||||
|
@ -34,11 +34,11 @@ export interface FormData {
|
|||
|
||||
export interface ShippingZoneDetailsPageProps
|
||||
extends FetchMoreProps,
|
||||
SearchProps {
|
||||
SearchProps,
|
||||
ChannelProps {
|
||||
disabled: boolean;
|
||||
errors: ShippingErrorFragment[];
|
||||
saveButtonBarState: ConfirmButtonTransitionState;
|
||||
selectedChannel: string;
|
||||
shippingZone: ShippingZoneDetailsFragment;
|
||||
warehouses: ShippingZoneDetailsFragment_warehouses[];
|
||||
onBack: () => void;
|
||||
|
@ -82,7 +82,7 @@ const ShippingZoneDetailsPage: React.FC<ShippingZoneDetailsPageProps> = ({
|
|||
onWeightRateAdd,
|
||||
onWeightRateEdit,
|
||||
saveButtonBarState,
|
||||
selectedChannel,
|
||||
selectedChannelId,
|
||||
shippingZone,
|
||||
warehouses
|
||||
}) => {
|
||||
|
@ -160,7 +160,7 @@ const ShippingZoneDetailsPage: React.FC<ShippingZoneDetailsPageProps> = ({
|
|||
method => method.type === ShippingMethodTypeEnum.PRICE
|
||||
)}
|
||||
variant="price"
|
||||
selectedChannel={selectedChannel}
|
||||
selectedChannelId={selectedChannelId}
|
||||
/>
|
||||
<CardSpacer />
|
||||
<ShippingZoneRates
|
||||
|
@ -172,7 +172,7 @@ const ShippingZoneDetailsPage: React.FC<ShippingZoneDetailsPageProps> = ({
|
|||
method => method.type === ShippingMethodTypeEnum.WEIGHT
|
||||
)}
|
||||
variant="weight"
|
||||
selectedChannel={selectedChannel}
|
||||
selectedChannelId={selectedChannelId}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
|
|
|
@ -15,16 +15,16 @@ import ResponsiveTable from "@saleor/components/ResponsiveTable";
|
|||
import Skeleton from "@saleor/components/Skeleton";
|
||||
import WeightRange from "@saleor/components/WeightRange";
|
||||
import { ShippingZoneDetailsFragment_shippingMethods } from "@saleor/fragments/types/ShippingZoneDetailsFragment";
|
||||
import { ChannelProps } from "@saleor/types";
|
||||
import React from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
|
||||
import { maybe, renderCollection } from "../../../misc";
|
||||
import { ICONBUTTON_SIZE } from "../../../theme";
|
||||
|
||||
export interface ShippingZoneRatesProps {
|
||||
export interface ShippingZoneRatesProps extends ChannelProps {
|
||||
disabled: boolean;
|
||||
rates: ShippingZoneDetailsFragment_shippingMethods[];
|
||||
selectedChannel: string;
|
||||
variant: "price" | "weight";
|
||||
onRateAdd: () => void;
|
||||
onRateEdit: (id: string) => void;
|
||||
|
@ -56,7 +56,7 @@ const ShippingZoneRates: React.FC<ShippingZoneRatesProps> = props => {
|
|||
onRateEdit,
|
||||
onRateRemove,
|
||||
rates,
|
||||
selectedChannel,
|
||||
selectedChannelId,
|
||||
variant
|
||||
} = props;
|
||||
|
||||
|
@ -122,7 +122,7 @@ const ShippingZoneRates: React.FC<ShippingZoneRatesProps> = props => {
|
|||
rates,
|
||||
rate => {
|
||||
const channel = rate?.channelListings?.find(
|
||||
listing => listing.channel.id === selectedChannel
|
||||
listing => listing.channel.id === selectedChannelId
|
||||
);
|
||||
return (
|
||||
<TableRow
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import AppHeader from "@saleor/components/AppHeader";
|
||||
import CardMenu from "@saleor/components/CardMenu";
|
||||
import Container from "@saleor/components/Container";
|
||||
import Grid from "@saleor/components/Grid";
|
||||
import PageHeader from "@saleor/components/PageHeader";
|
||||
|
@ -23,8 +22,6 @@ export interface ShippingZonesListPageProps
|
|||
onBack: () => void;
|
||||
onRemove: (id: string) => void;
|
||||
onSubmit: (unit: WeightUnitsEnum) => void;
|
||||
selectedChannel: string;
|
||||
onSettingsOpen: () => void;
|
||||
}
|
||||
|
||||
const ShippingZonesListPage: React.FC<ShippingZonesListPageProps> = ({
|
||||
|
@ -32,7 +29,6 @@ const ShippingZonesListPage: React.FC<ShippingZonesListPageProps> = ({
|
|||
disabled,
|
||||
userPermissions,
|
||||
onBack,
|
||||
onSettingsOpen,
|
||||
onSubmit,
|
||||
...listProps
|
||||
}) => {
|
||||
|
@ -48,19 +44,7 @@ const ShippingZonesListPage: React.FC<ShippingZonesListPageProps> = ({
|
|||
defaultMessage: "Shipping",
|
||||
description: "header"
|
||||
})}
|
||||
>
|
||||
<CardMenu
|
||||
menuItems={[
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: "Settings",
|
||||
description: "button"
|
||||
}),
|
||||
onSelect: onSettingsOpen
|
||||
}
|
||||
]}
|
||||
/>
|
||||
</PageHeader>
|
||||
/>
|
||||
<Grid>
|
||||
<div>
|
||||
<ShippingZonesList disabled={disabled} {...listProps} />
|
||||
|
|
|
@ -7,7 +7,7 @@ import { ShippingMethodTypeEnum } from "../types/globalTypes";
|
|||
export const shippingSection = "/shipping/";
|
||||
|
||||
export const shippingZonesListPath = shippingSection;
|
||||
export type ShippingZonesListUrlDialog = "remove" | "remove-many" | "settings";
|
||||
export type ShippingZonesListUrlDialog = "remove" | "remove-many";
|
||||
export type ShippingZonesListUrlQueryParams = BulkAction &
|
||||
Dialog<ShippingZonesListUrlDialog> &
|
||||
Pagination &
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import DialogContentText from "@material-ui/core/DialogContentText";
|
||||
import ActionDialog from "@saleor/components/ActionDialog";
|
||||
import useAppChannel from "@saleor/components/AppLayout/AppChannelContext";
|
||||
import NotFoundPage from "@saleor/components/NotFoundPage";
|
||||
import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config";
|
||||
import useLocalStorage from "@saleor/hooks/useLocalStorage";
|
||||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
import useNotifier from "@saleor/hooks/useNotifier";
|
||||
import useShop from "@saleor/hooks/useShop";
|
||||
|
@ -63,8 +63,7 @@ const ShippingZoneDetails: React.FC<ShippingZoneDetailsProps> = ({
|
|||
displayLoader: true,
|
||||
variables: { id }
|
||||
});
|
||||
|
||||
const [selectedChannel] = useLocalStorage("shippingListChannel", "");
|
||||
const { channel } = useAppChannel();
|
||||
|
||||
const [openModal, closeModal] = createDialogActionHandlers<
|
||||
ShippingZoneUrlDialog,
|
||||
|
@ -183,7 +182,7 @@ const ShippingZoneDetails: React.FC<ShippingZoneDetailsProps> = ({
|
|||
loading={searchWarehousesOpts.loading}
|
||||
onFetchMore={loadMore}
|
||||
onSearchChange={search}
|
||||
selectedChannel={selectedChannel}
|
||||
selectedChannelId={channel.id}
|
||||
/>
|
||||
<DeleteShippingRateDialog
|
||||
confirmButtonState={deleteShippingRateOpts.status}
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
import DialogContentText from "@material-ui/core/DialogContentText";
|
||||
import IconButton from "@material-ui/core/IconButton";
|
||||
import DeleteIcon from "@material-ui/icons/Delete";
|
||||
import ChannelSettingsDialog from "@saleor/channels/components/ChannelSettingsDialog";
|
||||
import ActionDialog from "@saleor/components/ActionDialog";
|
||||
import { configurationMenuUrl } from "@saleor/configuration";
|
||||
import useBulkActions from "@saleor/hooks/useBulkActions";
|
||||
import useChannelsSettings from "@saleor/hooks/useChannelsSettings";
|
||||
import useListSettings from "@saleor/hooks/useListSettings";
|
||||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
import useNotifier from "@saleor/hooks/useNotifier";
|
||||
|
@ -63,12 +61,6 @@ export const ShippingZonesList: React.FC<ShippingZonesListProps> = ({
|
|||
ShippingZonesListUrlQueryParams
|
||||
>(navigate, shippingZonesListUrl, params);
|
||||
|
||||
const {
|
||||
channelChoices,
|
||||
handleChannelSelectConfirm,
|
||||
selectedChannel
|
||||
} = useChannelsSettings("shippingListChannel", { closeModal, openModal });
|
||||
|
||||
const { data, loading, refetch } = useShippingZoneList({
|
||||
displayLoader: true,
|
||||
variables: paginationState
|
||||
|
@ -125,14 +117,6 @@ export const ShippingZonesList: React.FC<ShippingZonesListProps> = ({
|
|||
);
|
||||
return (
|
||||
<>
|
||||
<ChannelSettingsDialog
|
||||
channelsChoices={channelChoices}
|
||||
defaultChoice={selectedChannel}
|
||||
open={params.action === "settings"}
|
||||
confirmButtonState="default"
|
||||
onClose={closeModal}
|
||||
onConfirm={handleChannelSelectConfirm}
|
||||
/>
|
||||
<ShippingZonesListPage
|
||||
defaultWeightUnit={shop?.defaultWeightUnit}
|
||||
settings={settings}
|
||||
|
@ -178,8 +162,6 @@ export const ShippingZonesList: React.FC<ShippingZonesListProps> = ({
|
|||
</IconButton>
|
||||
}
|
||||
userPermissions={user?.userPermissions || []}
|
||||
selectedChannel={selectedChannel}
|
||||
onSettingsOpen={() => openModal("settings")}
|
||||
/>
|
||||
|
||||
<ActionDialog
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -47,6 +47,7 @@ const updateProps: Omit<CategoryUpdatePageProps, "classes"> = {
|
|||
productListToolbar: null,
|
||||
products: category.products.edges.map(edge => edge.node),
|
||||
saveButtonBarState: "default",
|
||||
selectedChannelId: "123",
|
||||
subcategories: category.children.edges.map(edge => edge.node),
|
||||
subcategoryListToolbar: null,
|
||||
...listActionsProps
|
||||
|
|
|
@ -38,7 +38,7 @@ const props: Omit<CollectionDetailsPageProps, "classes"> = {
|
|||
onSubmit: () => undefined,
|
||||
openChannelsModal: () => undefined,
|
||||
saveButtonBarState: "default",
|
||||
selectedChannel: "123"
|
||||
selectedChannelId: "123"
|
||||
};
|
||||
|
||||
storiesOf("Views / Collections / Collection details", module)
|
||||
|
|
|
@ -27,7 +27,7 @@ const props: CollectionListPageProps = {
|
|||
},
|
||||
...tabPageProps,
|
||||
collections,
|
||||
selectedChannel: "123"
|
||||
selectedChannelId: "123"
|
||||
};
|
||||
|
||||
storiesOf("Views / Collections / Collection list", module)
|
||||
|
|
|
@ -47,7 +47,7 @@ const props: SaleDetailsPageProps = {
|
|||
productListToolbar: null,
|
||||
sale,
|
||||
saveButtonBarState: "default",
|
||||
selectedChannel: "123",
|
||||
selectedChannelId: "123",
|
||||
...listActionsProps
|
||||
};
|
||||
|
||||
|
|
|
@ -42,9 +42,8 @@ const props: SaleListPageProps = {
|
|||
value: [DiscountStatusEnum.ACTIVE]
|
||||
}
|
||||
},
|
||||
onSettingsOpen: () => undefined,
|
||||
sales: saleList,
|
||||
selectedChannel: "123",
|
||||
selectedChannelId: "123",
|
||||
sort: {
|
||||
...sortPageProps.sort,
|
||||
sort: SaleListUrlSortField.name
|
||||
|
@ -60,7 +59,6 @@ storiesOf("Views / Discounts / Sale list", module)
|
|||
<SaleListPage
|
||||
{...props}
|
||||
sales={saleList.map(sale => ({ ...sale, channelListings: [] }))}
|
||||
selectedChannel=""
|
||||
onSettingsOpen={undefined}
|
||||
selectedChannelId=""
|
||||
/>
|
||||
));
|
||||
|
|
|
@ -47,7 +47,7 @@ const props: VoucherDetailsPageProps = {
|
|||
openChannelsModal: () => undefined,
|
||||
productListToolbar: null,
|
||||
saveButtonBarState: "default",
|
||||
selectedChannel: "123",
|
||||
selectedChannelId: "123",
|
||||
voucher: voucherDetails
|
||||
};
|
||||
|
||||
|
|
|
@ -51,8 +51,7 @@ const props: VoucherListPageProps = {
|
|||
}
|
||||
}
|
||||
},
|
||||
onSettingsOpen: () => undefined,
|
||||
selectedChannel: "123",
|
||||
selectedChannelId: "123",
|
||||
sort: {
|
||||
...sortPageProps.sort,
|
||||
sort: VoucherListUrlSortField.code
|
||||
|
@ -68,8 +67,7 @@ storiesOf("Views / Discounts / Voucher list", module)
|
|||
.add("no channels", () => (
|
||||
<VoucherListPage
|
||||
{...props}
|
||||
selectedChannel=""
|
||||
onSettingsOpen={undefined}
|
||||
selectedChannelId=""
|
||||
vouchers={voucherList.map(voucher => ({
|
||||
...voucher,
|
||||
channelListings: []
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import placeholderImage from "@assets/images/placeholder60x60.png";
|
||||
import { Omit } from "@material-ui/core";
|
||||
import { channelsList } from "@saleor/channels/fixtures";
|
||||
import { adminUserPermissions } from "@saleor/fixtures";
|
||||
import { PermissionEnum } from "@saleor/types/globalTypes";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
|
@ -11,16 +10,9 @@ import { shop as shopFixture } from "../../../home/fixtures";
|
|||
import Decorator from "../../Decorator";
|
||||
|
||||
const shop = shopFixture(placeholderImage);
|
||||
const channelChoices = channelsList.map(channel => ({
|
||||
label: channel.name,
|
||||
value: channel.slug
|
||||
}));
|
||||
|
||||
const homePageProps: Omit<HomePageProps, "classes"> = {
|
||||
activities: shop.activities.edges.map(edge => edge.node),
|
||||
channelChoices,
|
||||
channelValue: channelChoices[0].value,
|
||||
onChannelChange: () => undefined,
|
||||
onOrdersToCaptureClick: () => undefined,
|
||||
onOrdersToFulfillClick: () => undefined,
|
||||
onProductClick: () => undefined,
|
||||
|
|
|
@ -37,7 +37,6 @@ const props: OrderDraftListPageProps = {
|
|||
}
|
||||
},
|
||||
onAdd: () => undefined,
|
||||
onSettingsOpen: () => undefined,
|
||||
orders,
|
||||
sort: {
|
||||
...sortPageProps.sort,
|
||||
|
|
|
@ -21,7 +21,7 @@ const props: OrderProductAddDialogProps = {
|
|||
onSubmit: () => undefined,
|
||||
open: true,
|
||||
products,
|
||||
selectedChannel: products[0].variants[0].channelListings[0].channel.id
|
||||
selectedChannelId: products[0].variants[0].channelListings[0].channel.id
|
||||
};
|
||||
|
||||
storiesOf("Orders / OrderProductAddDialog", module)
|
||||
|
|
|
@ -42,9 +42,8 @@ const props: ProductListPageProps = {
|
|||
filterOpts: productListFilterOpts,
|
||||
gridAttributes: attributes,
|
||||
onExport: () => undefined,
|
||||
onSettingsOpen: () => undefined,
|
||||
products,
|
||||
selectedChannel: "123",
|
||||
selectedChannelId: "123",
|
||||
settings: {
|
||||
...pageListProps.default.settings,
|
||||
columns: ["availability", "productType", "price"]
|
||||
|
@ -69,8 +68,7 @@ storiesOf("Views / Products / Product list", module)
|
|||
<ProductListPage
|
||||
{...props}
|
||||
channelsCount={0}
|
||||
onSettingsOpen={undefined}
|
||||
selectedChannel={""}
|
||||
selectedChannelId={""}
|
||||
products={products.map(product => ({ ...product, channelListings: [] }))}
|
||||
/>
|
||||
));
|
||||
|
|
|
@ -58,6 +58,7 @@ const props: ProductUpdatePageProps = {
|
|||
placeholderImage,
|
||||
product,
|
||||
saveButtonBarState: "default",
|
||||
selectedChannelId: "123",
|
||||
taxTypes,
|
||||
variants: product.variants,
|
||||
warehouses: warehouseList
|
||||
|
|
|
@ -27,7 +27,7 @@ const props: ShippingZoneDetailsPageProps = {
|
|||
onWeightRateAdd: () => undefined,
|
||||
onWeightRateEdit: () => undefined,
|
||||
saveButtonBarState: "default",
|
||||
selectedChannel: "12345",
|
||||
selectedChannelId: "12345",
|
||||
shippingZone,
|
||||
warehouses: warehouseList
|
||||
};
|
||||
|
|
|
@ -20,9 +20,7 @@ const props: ShippingZonesListPageProps = {
|
|||
onAdd: () => undefined,
|
||||
onBack: () => undefined,
|
||||
onRemove: () => undefined,
|
||||
onSettingsOpen: () => undefined,
|
||||
onSubmit: () => undefined,
|
||||
selectedChannel: "123",
|
||||
shippingZones,
|
||||
userPermissions: adminUserPermissions
|
||||
};
|
||||
|
|
|
@ -117,6 +117,10 @@ export interface TabPageProps {
|
|||
onTabSave: () => void;
|
||||
}
|
||||
|
||||
export interface ChannelProps {
|
||||
selectedChannelId: string;
|
||||
}
|
||||
|
||||
export interface PartialMutationProviderOutput<
|
||||
TData extends {} = {},
|
||||
TVariables extends {} = {}
|
||||
|
|
|
@ -1,21 +1,32 @@
|
|||
import { User } from "@saleor/fragments/types/User";
|
||||
|
||||
export const isSupported =
|
||||
navigator.credentials && navigator.credentials.preventSilentAccess;
|
||||
export const isSupported = !!(
|
||||
navigator?.credentials?.preventSilentAccess && PasswordCredential
|
||||
);
|
||||
|
||||
export function login<T>(loginFn: (id: string, password: string) => T): T {
|
||||
if (isSupported) {
|
||||
navigator.credentials.get({ password: true }).then(credential => {
|
||||
if (credential instanceof PasswordCredential) {
|
||||
return loginFn(credential.id, credential.password);
|
||||
}
|
||||
});
|
||||
export async function login<T>(
|
||||
loginFn: (id: string, password: string) => T
|
||||
): Promise<T | null> {
|
||||
let result: T;
|
||||
|
||||
try {
|
||||
const credential = await navigator.credentials.get({ password: true });
|
||||
if (credential instanceof PasswordCredential) {
|
||||
result = loginFn(credential.id, credential.password);
|
||||
}
|
||||
} catch {
|
||||
result = null;
|
||||
}
|
||||
|
||||
return null;
|
||||
return result;
|
||||
}
|
||||
|
||||
export function saveCredentials(user: User, password: string) {
|
||||
export function saveCredentials(
|
||||
user: User,
|
||||
password: string
|
||||
): Promise<CredentialType | null> {
|
||||
let result: Promise<CredentialType | null>;
|
||||
|
||||
if (isSupported) {
|
||||
const cred = new PasswordCredential({
|
||||
iconURL: user.avatar ? user.avatar.url : undefined,
|
||||
|
@ -23,6 +34,14 @@ export function saveCredentials(user: User, password: string) {
|
|||
name: user.firstName ? `${user.firstName} ${user.lastName}` : undefined,
|
||||
password
|
||||
});
|
||||
navigator.credentials.store(cred);
|
||||
try {
|
||||
result = navigator.credentials.store(cred);
|
||||
} catch {
|
||||
result = null;
|
||||
}
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue