wip
This commit is contained in:
parent
0dcf4b2c5f
commit
bc2c6a9c71
8 changed files with 293 additions and 57 deletions
|
@ -33,10 +33,14 @@ const ColumnPicker: React.FC<ColumnPickerProps> = props => {
|
||||||
const {
|
const {
|
||||||
className,
|
className,
|
||||||
columns,
|
columns,
|
||||||
|
hasMore,
|
||||||
initial = false,
|
initial = false,
|
||||||
|
loading,
|
||||||
selectedColumns,
|
selectedColumns,
|
||||||
|
total,
|
||||||
onCancel,
|
onCancel,
|
||||||
onColumnToggle,
|
onColumnToggle,
|
||||||
|
onFetchMore,
|
||||||
onReset,
|
onReset,
|
||||||
onSave
|
onSave
|
||||||
} = props;
|
} = props;
|
||||||
|
@ -86,9 +90,13 @@ const ColumnPicker: React.FC<ColumnPickerProps> = props => {
|
||||||
>
|
>
|
||||||
<ColumnPickerContent
|
<ColumnPickerContent
|
||||||
columns={columns}
|
columns={columns}
|
||||||
|
hasMore={hasMore}
|
||||||
|
loading={loading}
|
||||||
selectedColumns={selectedColumns}
|
selectedColumns={selectedColumns}
|
||||||
|
total={total}
|
||||||
onCancel={handleCancel}
|
onCancel={handleCancel}
|
||||||
onColumnToggle={onColumnToggle}
|
onColumnToggle={onColumnToggle}
|
||||||
|
onFetchMore={onFetchMore}
|
||||||
onReset={onReset}
|
onReset={onReset}
|
||||||
onSave={handleSave}
|
onSave={handleSave}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
import Button from "@material-ui/core/Button";
|
import Button from "@material-ui/core/Button";
|
||||||
import Card from "@material-ui/core/Card";
|
import Card from "@material-ui/core/Card";
|
||||||
import CardContent from "@material-ui/core/CardContent";
|
import CardContent from "@material-ui/core/CardContent";
|
||||||
|
import CircularProgress from "@material-ui/core/CircularProgress";
|
||||||
import { Theme } from "@material-ui/core/styles";
|
import { Theme } from "@material-ui/core/styles";
|
||||||
import Typography from "@material-ui/core/Typography";
|
import Typography from "@material-ui/core/Typography";
|
||||||
import makeStyles from "@material-ui/styles/makeStyles";
|
import makeStyles from "@material-ui/styles/makeStyles";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import InfiniteScroll from "react-infinite-scroller";
|
||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
|
|
||||||
import useElementScroll from "@saleor/hooks/useElementScroll";
|
import useElementScroll from "@saleor/hooks/useElementScroll";
|
||||||
import { buttonMessages } from "@saleor/intl";
|
import { buttonMessages } from "@saleor/intl";
|
||||||
|
import { FetchMoreProps } from "@saleor/types";
|
||||||
import { isSelected } from "@saleor/utils/lists";
|
import { isSelected } from "@saleor/utils/lists";
|
||||||
import ControlledCheckbox from "../ControlledCheckbox";
|
import ControlledCheckbox from "../ControlledCheckbox";
|
||||||
import Hr from "../Hr";
|
import Hr from "../Hr";
|
||||||
|
@ -18,9 +21,10 @@ export interface ColumnPickerChoice {
|
||||||
label: string;
|
label: string;
|
||||||
value: string;
|
value: string;
|
||||||
}
|
}
|
||||||
export interface ColumnPickerContentProps {
|
export interface ColumnPickerContentProps extends Partial<FetchMoreProps> {
|
||||||
columns: ColumnPickerChoice[];
|
columns: ColumnPickerChoice[];
|
||||||
selectedColumns: string[];
|
selectedColumns: string[];
|
||||||
|
total?: number;
|
||||||
onCancel: () => void;
|
onCancel: () => void;
|
||||||
onColumnToggle: (column: string) => void;
|
onColumnToggle: (column: string) => void;
|
||||||
onReset: () => void;
|
onReset: () => void;
|
||||||
|
@ -50,15 +54,26 @@ const useStyles = makeStyles((theme: Theme) => ({
|
||||||
},
|
},
|
||||||
dropShadow: {
|
dropShadow: {
|
||||||
boxShadow: `0px -5px 10px 0px ${theme.overrides.MuiCard.root.borderColor}`
|
boxShadow: `0px -5px 10px 0px ${theme.overrides.MuiCard.root.borderColor}`
|
||||||
|
},
|
||||||
|
loadMoreLoaderContainer: {
|
||||||
|
alignItems: "center",
|
||||||
|
display: "flex",
|
||||||
|
gridColumnEnd: "span 3",
|
||||||
|
height: theme.spacing.unit * 3,
|
||||||
|
justifyContent: "center"
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const ColumnPickerContent: React.FC<ColumnPickerContentProps> = props => {
|
const ColumnPickerContent: React.FC<ColumnPickerContentProps> = props => {
|
||||||
const {
|
const {
|
||||||
columns,
|
columns,
|
||||||
|
hasMore,
|
||||||
|
loading,
|
||||||
selectedColumns,
|
selectedColumns,
|
||||||
|
total,
|
||||||
onCancel,
|
onCancel,
|
||||||
onColumnToggle,
|
onColumnToggle,
|
||||||
|
onFetchMore,
|
||||||
onReset,
|
onReset,
|
||||||
onSave
|
onSave
|
||||||
} = props;
|
} = props;
|
||||||
|
@ -80,12 +95,44 @@ const ColumnPickerContent: React.FC<ColumnPickerContentProps> = props => {
|
||||||
description="pick columns to display"
|
description="pick columns to display"
|
||||||
values={{
|
values={{
|
||||||
numberOfSelected: selectedColumns.length,
|
numberOfSelected: selectedColumns.length,
|
||||||
numberOfTotal: columns.length
|
numberOfTotal: total || columns.length
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Typography>
|
</Typography>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
<Hr />
|
<Hr />
|
||||||
|
{hasMore && onFetchMore ? (
|
||||||
|
<InfiniteScroll
|
||||||
|
pageStart={0}
|
||||||
|
loadMore={onFetchMore}
|
||||||
|
hasMore={hasMore}
|
||||||
|
useWindow={false}
|
||||||
|
threshold={100}
|
||||||
|
key="infinite-scroll"
|
||||||
|
>
|
||||||
|
<CardContent className={classes.contentContainer}>
|
||||||
|
<div className={classes.content} ref={anchor}>
|
||||||
|
{columns.map(column => (
|
||||||
|
<ControlledCheckbox
|
||||||
|
checked={isSelected(
|
||||||
|
column.value,
|
||||||
|
selectedColumns,
|
||||||
|
(a, b) => a === b
|
||||||
|
)}
|
||||||
|
name={column.value}
|
||||||
|
label={column.label}
|
||||||
|
onChange={() => onColumnToggle(column.value)}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
{loading && (
|
||||||
|
<div className={classes.loadMoreLoaderContainer}>
|
||||||
|
<CircularProgress size={16} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</InfiniteScroll>
|
||||||
|
) : (
|
||||||
<CardContent className={classes.contentContainer}>
|
<CardContent className={classes.contentContainer}>
|
||||||
<div className={classes.content} ref={anchor}>
|
<div className={classes.content} ref={anchor}>
|
||||||
{columns.map(column => (
|
{columns.map(column => (
|
||||||
|
@ -102,6 +149,7 @@ const ColumnPickerContent: React.FC<ColumnPickerContentProps> = props => {
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
)}
|
||||||
<Hr />
|
<Hr />
|
||||||
<CardContent
|
<CardContent
|
||||||
className={classNames(classes.actionBarContainer, {
|
className={classNames(classes.actionBarContainer, {
|
||||||
|
|
|
@ -16,7 +16,13 @@ import ProductList from "@saleor/components/ProductList";
|
||||||
import { ProductListColumns } from "@saleor/config";
|
import { ProductListColumns } from "@saleor/config";
|
||||||
import useStateFromProps from "@saleor/hooks/useStateFromProps";
|
import useStateFromProps from "@saleor/hooks/useStateFromProps";
|
||||||
import { sectionNames } from "@saleor/intl";
|
import { sectionNames } from "@saleor/intl";
|
||||||
import { FilterPageProps, ListActions, PageListProps } from "@saleor/types";
|
import { AvailableInGridAttributes_attributes_edges_node } from "@saleor/products/types/AvailableInGridAttributes";
|
||||||
|
import {
|
||||||
|
FetchMoreProps,
|
||||||
|
FilterPageProps,
|
||||||
|
ListActions,
|
||||||
|
PageListProps
|
||||||
|
} from "@saleor/types";
|
||||||
import { toggle } from "@saleor/utils/lists";
|
import { toggle } from "@saleor/utils/lists";
|
||||||
import { ProductListUrlFilters } from "../../urls";
|
import { ProductListUrlFilters } from "../../urls";
|
||||||
import ProductListFilter from "../ProductListFilter";
|
import ProductListFilter from "../ProductListFilter";
|
||||||
|
@ -24,8 +30,11 @@ import ProductListFilter from "../ProductListFilter";
|
||||||
export interface ProductListPageProps
|
export interface ProductListPageProps
|
||||||
extends PageListProps<ProductListColumns>,
|
extends PageListProps<ProductListColumns>,
|
||||||
ListActions,
|
ListActions,
|
||||||
FilterPageProps<ProductListUrlFilters> {
|
FilterPageProps<ProductListUrlFilters>,
|
||||||
|
FetchMoreProps {
|
||||||
currencySymbol: string;
|
currencySymbol: string;
|
||||||
|
gridAttributes: AvailableInGridAttributes_attributes_edges_node[];
|
||||||
|
totalGridAttributes: number;
|
||||||
products: CategoryDetails_category_products_edges_node[];
|
products: CategoryDetails_category_products_edges_node[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,10 +51,15 @@ export const ProductListPage: React.FC<ProductListPageProps> = props => {
|
||||||
defaultSettings,
|
defaultSettings,
|
||||||
filtersList,
|
filtersList,
|
||||||
filterTabs,
|
filterTabs,
|
||||||
|
gridAttributes,
|
||||||
|
hasMore,
|
||||||
initialSearch,
|
initialSearch,
|
||||||
|
loading,
|
||||||
settings,
|
settings,
|
||||||
|
totalGridAttributes,
|
||||||
onAdd,
|
onAdd,
|
||||||
onAll,
|
onAll,
|
||||||
|
onFetchMore,
|
||||||
onSearchChange,
|
onSearchChange,
|
||||||
onFilterAdd,
|
onFilterAdd,
|
||||||
onFilterSave,
|
onFilterSave,
|
||||||
|
@ -95,7 +109,11 @@ export const ProductListPage: React.FC<ProductListPageProps> = props => {
|
||||||
description: "product type"
|
description: "product type"
|
||||||
}),
|
}),
|
||||||
value: "productType" as ProductListColumns
|
value: "productType" as ProductListColumns
|
||||||
}
|
},
|
||||||
|
...gridAttributes.map(attribute => ({
|
||||||
|
label: attribute.name,
|
||||||
|
value: `attribute:${attribute.id}`
|
||||||
|
}))
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -104,9 +122,13 @@ export const ProductListPage: React.FC<ProductListPageProps> = props => {
|
||||||
<ColumnPicker
|
<ColumnPicker
|
||||||
className={classes.columnPicker}
|
className={classes.columnPicker}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
|
hasMore={hasMore}
|
||||||
|
loading={loading}
|
||||||
selectedColumns={selectedColumns}
|
selectedColumns={selectedColumns}
|
||||||
|
total={columns.length + totalGridAttributes}
|
||||||
onColumnToggle={handleColumnToggle}
|
onColumnToggle={handleColumnToggle}
|
||||||
onCancel={handleCancel}
|
onCancel={handleCancel}
|
||||||
|
onFetchMore={onFetchMore}
|
||||||
onReset={handleReset}
|
onReset={handleReset}
|
||||||
onSave={handleSave}
|
onSave={handleSave}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
import gql from "graphql-tag";
|
import gql from "graphql-tag";
|
||||||
|
|
||||||
import { TypedQuery } from "../queries";
|
import { pageInfoFragment, TypedQuery } from "../queries";
|
||||||
|
import {
|
||||||
|
AvailableInGridAttributes,
|
||||||
|
AvailableInGridAttributesVariables
|
||||||
|
} from "./types/AvailableInGridAttributes";
|
||||||
import { ProductCreateData } from "./types/ProductCreateData";
|
import { ProductCreateData } from "./types/ProductCreateData";
|
||||||
import {
|
import {
|
||||||
ProductDetails,
|
ProductDetails,
|
||||||
|
@ -225,6 +229,15 @@ const productListQuery = gql`
|
||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
...ProductFragment
|
...ProductFragment
|
||||||
|
attributes {
|
||||||
|
attribute {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
values {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pageInfo {
|
pageInfo {
|
||||||
|
@ -361,3 +374,29 @@ export const TypedProductImageQuery = TypedQuery<
|
||||||
ProductImageById,
|
ProductImageById,
|
||||||
ProductImageByIdVariables
|
ProductImageByIdVariables
|
||||||
>(productImageQuery);
|
>(productImageQuery);
|
||||||
|
|
||||||
|
const availableInGridAttributes = gql`
|
||||||
|
${pageInfoFragment}
|
||||||
|
query AvailableInGridAttributes($first: Int!, $after: String) {
|
||||||
|
attributes(
|
||||||
|
first: $first
|
||||||
|
after: $after
|
||||||
|
filter: { availableInGrid: true }
|
||||||
|
) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pageInfo {
|
||||||
|
...PageInfoFragment
|
||||||
|
}
|
||||||
|
totalCount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export const AvailableInGridAttributesQuery = TypedQuery<
|
||||||
|
AvailableInGridAttributes,
|
||||||
|
AvailableInGridAttributesVariables
|
||||||
|
>(availableInGridAttributes);
|
||||||
|
|
42
src/products/types/AvailableInGridAttributes.ts
Normal file
42
src/products/types/AvailableInGridAttributes.ts
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// This file was automatically generated and should not be edited.
|
||||||
|
|
||||||
|
// ====================================================
|
||||||
|
// GraphQL query operation: AvailableInGridAttributes
|
||||||
|
// ====================================================
|
||||||
|
|
||||||
|
export interface AvailableInGridAttributes_attributes_edges_node {
|
||||||
|
__typename: "Attribute";
|
||||||
|
id: string;
|
||||||
|
name: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AvailableInGridAttributes_attributes_edges {
|
||||||
|
__typename: "AttributeCountableEdge";
|
||||||
|
node: AvailableInGridAttributes_attributes_edges_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AvailableInGridAttributes_attributes_pageInfo {
|
||||||
|
__typename: "PageInfo";
|
||||||
|
endCursor: string | null;
|
||||||
|
hasNextPage: boolean;
|
||||||
|
hasPreviousPage: boolean;
|
||||||
|
startCursor: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AvailableInGridAttributes_attributes {
|
||||||
|
__typename: "AttributeCountableConnection";
|
||||||
|
edges: AvailableInGridAttributes_attributes_edges[];
|
||||||
|
pageInfo: AvailableInGridAttributes_attributes_pageInfo;
|
||||||
|
totalCount: number | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AvailableInGridAttributes {
|
||||||
|
attributes: AvailableInGridAttributes_attributes | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AvailableInGridAttributesVariables {
|
||||||
|
first: number;
|
||||||
|
after?: string | null;
|
||||||
|
}
|
|
@ -25,6 +25,23 @@ export interface ProductList_products_edges_node_productType {
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ProductList_products_edges_node_attributes_attribute {
|
||||||
|
__typename: "Attribute";
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ProductList_products_edges_node_attributes_values {
|
||||||
|
__typename: "AttributeValue";
|
||||||
|
id: string;
|
||||||
|
name: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ProductList_products_edges_node_attributes {
|
||||||
|
__typename: "SelectedAttribute";
|
||||||
|
attribute: ProductList_products_edges_node_attributes_attribute;
|
||||||
|
values: (ProductList_products_edges_node_attributes_values | null)[];
|
||||||
|
}
|
||||||
|
|
||||||
export interface ProductList_products_edges_node {
|
export interface ProductList_products_edges_node {
|
||||||
__typename: "Product";
|
__typename: "Product";
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -33,6 +50,7 @@ export interface ProductList_products_edges_node {
|
||||||
isAvailable: boolean | null;
|
isAvailable: boolean | null;
|
||||||
basePrice: ProductList_products_edges_node_basePrice | null;
|
basePrice: ProductList_products_edges_node_basePrice | null;
|
||||||
productType: ProductList_products_edges_node_productType;
|
productType: ProductList_products_edges_node_productType;
|
||||||
|
attributes: ProductList_products_edges_node_attributes[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProductList_products_edges {
|
export interface ProductList_products_edges {
|
||||||
|
|
|
@ -20,6 +20,7 @@ import usePaginator, {
|
||||||
createPaginationState
|
createPaginationState
|
||||||
} from "@saleor/hooks/usePaginator";
|
} from "@saleor/hooks/usePaginator";
|
||||||
import useShop from "@saleor/hooks/useShop";
|
import useShop from "@saleor/hooks/useShop";
|
||||||
|
import { commonMessages } from "@saleor/intl";
|
||||||
import { getMutationState, maybe } from "@saleor/misc";
|
import { getMutationState, maybe } from "@saleor/misc";
|
||||||
import { ListViews } from "@saleor/types";
|
import { ListViews } from "@saleor/types";
|
||||||
import ProductListPage from "../../components/ProductListPage";
|
import ProductListPage from "../../components/ProductListPage";
|
||||||
|
@ -27,7 +28,10 @@ import {
|
||||||
TypedProductBulkDeleteMutation,
|
TypedProductBulkDeleteMutation,
|
||||||
TypedProductBulkPublishMutation
|
TypedProductBulkPublishMutation
|
||||||
} from "../../mutations";
|
} from "../../mutations";
|
||||||
import { TypedProductListQuery } from "../../queries";
|
import {
|
||||||
|
AvailableInGridAttributesQuery,
|
||||||
|
TypedProductListQuery
|
||||||
|
} from "../../queries";
|
||||||
import { productBulkDelete } from "../../types/productBulkDelete";
|
import { productBulkDelete } from "../../types/productBulkDelete";
|
||||||
import { productBulkPublish } from "../../types/productBulkPublish";
|
import { productBulkPublish } from "../../types/productBulkPublish";
|
||||||
import {
|
import {
|
||||||
|
@ -145,6 +149,8 @@ export const ProductList: React.StatelessComponent<ProductListProps> = ({
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<AvailableInGridAttributesQuery variables={{ first: 6 }}>
|
||||||
|
{gridAttributes => (
|
||||||
<TypedProductListQuery displayLoader variables={queryVariables}>
|
<TypedProductListQuery displayLoader variables={queryVariables}>
|
||||||
{({ data, loading, refetch }) => {
|
{({ data, loading, refetch }) => {
|
||||||
const { loadNextPage, loadPreviousPage, pageInfo } = paginate(
|
const { loadNextPage, loadPreviousPage, pageInfo } = paginate(
|
||||||
|
@ -157,9 +163,7 @@ export const ProductList: React.StatelessComponent<ProductListProps> = ({
|
||||||
if (data.productBulkDelete.errors.length === 0) {
|
if (data.productBulkDelete.errors.length === 0) {
|
||||||
closeModal();
|
closeModal();
|
||||||
notify({
|
notify({
|
||||||
text: intl.formatMessage({
|
text: intl.formatMessage(commonMessages.savedChanges)
|
||||||
defaultMessage: "Products removed"
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
reset();
|
reset();
|
||||||
refetch();
|
refetch();
|
||||||
|
@ -170,10 +174,7 @@ export const ProductList: React.StatelessComponent<ProductListProps> = ({
|
||||||
if (data.productBulkPublish.errors.length === 0) {
|
if (data.productBulkPublish.errors.length === 0) {
|
||||||
closeModal();
|
closeModal();
|
||||||
notify({
|
notify({
|
||||||
text: intl.formatMessage({
|
text: intl.formatMessage(commonMessages.savedChanges)
|
||||||
defaultMessage: "Changed publication status",
|
|
||||||
description: "product status update notification"
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
reset();
|
reset();
|
||||||
refetch();
|
refetch();
|
||||||
|
@ -183,13 +184,16 @@ export const ProductList: React.StatelessComponent<ProductListProps> = ({
|
||||||
return (
|
return (
|
||||||
<TypedProductBulkDeleteMutation onCompleted={handleBulkDelete}>
|
<TypedProductBulkDeleteMutation onCompleted={handleBulkDelete}>
|
||||||
{(productBulkDelete, productBulkDeleteOpts) => (
|
{(productBulkDelete, productBulkDeleteOpts) => (
|
||||||
<TypedProductBulkPublishMutation onCompleted={handleBulkPublish}>
|
<TypedProductBulkPublishMutation
|
||||||
|
onCompleted={handleBulkPublish}
|
||||||
|
>
|
||||||
{(productBulkPublish, productBulkPublishOpts) => {
|
{(productBulkPublish, productBulkPublishOpts) => {
|
||||||
const bulkDeleteMutationState = getMutationState(
|
const bulkDeleteMutationState = getMutationState(
|
||||||
productBulkDeleteOpts.called,
|
productBulkDeleteOpts.called,
|
||||||
productBulkDeleteOpts.loading,
|
productBulkDeleteOpts.loading,
|
||||||
maybe(
|
maybe(
|
||||||
() => productBulkDeleteOpts.data.productBulkDelete.errors
|
() =>
|
||||||
|
productBulkDeleteOpts.data.productBulkDelete.errors
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -198,7 +202,8 @@ export const ProductList: React.StatelessComponent<ProductListProps> = ({
|
||||||
productBulkPublishOpts.loading,
|
productBulkPublishOpts.loading,
|
||||||
maybe(
|
maybe(
|
||||||
() =>
|
() =>
|
||||||
productBulkPublishOpts.data.productBulkPublish.errors
|
productBulkPublishOpts.data.productBulkPublish
|
||||||
|
.errors
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -210,7 +215,25 @@ export const ProductList: React.StatelessComponent<ProductListProps> = ({
|
||||||
defaultSettings={
|
defaultSettings={
|
||||||
defaultListSettings[ListViews.PRODUCT_LIST]
|
defaultListSettings[ListViews.PRODUCT_LIST]
|
||||||
}
|
}
|
||||||
|
gridAttributes={maybe(
|
||||||
|
() =>
|
||||||
|
gridAttributes.data.attributes.edges.map(
|
||||||
|
edge => edge.node
|
||||||
|
),
|
||||||
|
[]
|
||||||
|
)}
|
||||||
|
totalGridAttributes={maybe(
|
||||||
|
() => gridAttributes.data.attributes.totalCount,
|
||||||
|
0
|
||||||
|
)}
|
||||||
settings={settings}
|
settings={settings}
|
||||||
|
loading={gridAttributes.loading}
|
||||||
|
hasMore={maybe(
|
||||||
|
() =>
|
||||||
|
gridAttributes.data.attributes.pageInfo
|
||||||
|
.hasNextPage,
|
||||||
|
false
|
||||||
|
)}
|
||||||
filtersList={createFilterChips(
|
filtersList={createFilterChips(
|
||||||
params,
|
params,
|
||||||
{
|
{
|
||||||
|
@ -225,6 +248,34 @@ export const ProductList: React.StatelessComponent<ProductListProps> = ({
|
||||||
products={maybe(() =>
|
products={maybe(() =>
|
||||||
data.products.edges.map(edge => edge.node)
|
data.products.edges.map(edge => edge.node)
|
||||||
)}
|
)}
|
||||||
|
onFetchMore={() =>
|
||||||
|
gridAttributes.loadMore(
|
||||||
|
(prev, next) => {
|
||||||
|
if (
|
||||||
|
prev.attributes.pageInfo.endCursor ===
|
||||||
|
next.attributes.pageInfo.endCursor
|
||||||
|
) {
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...prev,
|
||||||
|
attributes: {
|
||||||
|
...prev.attributes,
|
||||||
|
edges: [
|
||||||
|
...prev.attributes.edges,
|
||||||
|
...next.attributes.edges
|
||||||
|
],
|
||||||
|
pageInfo: next.attributes.pageInfo
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
{
|
||||||
|
after:
|
||||||
|
gridAttributes.data.attributes.pageInfo
|
||||||
|
.endCursor
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
onNextPage={loadNextPage}
|
onNextPage={loadNextPage}
|
||||||
onPreviousPage={loadPreviousPage}
|
onPreviousPage={loadPreviousPage}
|
||||||
onUpdateListSettings={updateListSettings}
|
onUpdateListSettings={updateListSettings}
|
||||||
|
|
|
@ -42,4 +42,12 @@ storiesOf("Generics / Column picker", module)
|
||||||
))
|
))
|
||||||
.addDecorator(CardDecorator)
|
.addDecorator(CardDecorator)
|
||||||
.addDecorator(Decorator)
|
.addDecorator(Decorator)
|
||||||
.add("default", () => <ColumnPicker {...props} />);
|
.add("default", () => <ColumnPicker {...props} />)
|
||||||
|
.add("loading", () => (
|
||||||
|
<ColumnPicker
|
||||||
|
{...props}
|
||||||
|
loading={true}
|
||||||
|
hasMore={true}
|
||||||
|
onFetchMore={() => undefined}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
|
Loading…
Reference in a new issue