Merge pull request #180 from mirumee/add/attribute-sort
Allow sorting products by attribute
This commit is contained in:
commit
eb0f60cc88
11 changed files with 456 additions and 38 deletions
|
@ -28,3 +28,4 @@ All notable, unreleased changes to this project will be documented in this file.
|
||||||
- Add testcafe tags to attributes, categories, collections and product types - #178 by @dominik-zeglen
|
- Add testcafe tags to attributes, categories, collections and product types - #178 by @dominik-zeglen
|
||||||
- Fix input error style - #183 by @benekex2
|
- Fix input error style - #183 by @benekex2
|
||||||
- Fix staff return link - #190 by @dominik-zeglen
|
- Fix staff return link - #190 by @dominik-zeglen
|
||||||
|
- Allow sorting products by attribute - #180 by @dominik-zeglen
|
||||||
|
|
391
schema.graphql
391
schema.graphql
File diff suppressed because it is too large
Load diff
|
@ -480,5 +480,8 @@ export function findInEnum<TEnum extends object>(
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseBoolean(a: string): boolean {
|
export function parseBoolean(a: string): boolean {
|
||||||
|
if (a === undefined) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return a === "true";
|
return a === "true";
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,12 +101,14 @@ interface ProductListProps
|
||||||
ListActions,
|
ListActions,
|
||||||
SortPage<ProductListUrlSortField>,
|
SortPage<ProductListUrlSortField>,
|
||||||
WithStyles<typeof styles> {
|
WithStyles<typeof styles> {
|
||||||
|
activeAttributeSortId: string;
|
||||||
gridAttributes: AvailableInGridAttributes_grid_edges_node[];
|
gridAttributes: AvailableInGridAttributes_grid_edges_node[];
|
||||||
products: ProductList_products_edges_node[];
|
products: ProductList_products_edges_node[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ProductList = withStyles(styles, { name: "ProductList" })(
|
export const ProductList = withStyles(styles, { name: "ProductList" })(
|
||||||
({
|
({
|
||||||
|
activeAttributeSortId,
|
||||||
classes,
|
classes,
|
||||||
settings,
|
settings,
|
||||||
disabled,
|
disabled,
|
||||||
|
@ -219,23 +221,35 @@ export const ProductList = withStyles(styles, { name: "ProductList" })(
|
||||||
/>
|
/>
|
||||||
</TableCellHeader>
|
</TableCellHeader>
|
||||||
</DisplayColumn>
|
</DisplayColumn>
|
||||||
{gridAttributesFromSettings.map(gridAttributeFromSettings => (
|
{gridAttributesFromSettings.map(gridAttributeFromSettings => {
|
||||||
<TableCell
|
const attributeId = getAttributeIdFromColumnValue(
|
||||||
className={classes.colAttribute}
|
gridAttributeFromSettings
|
||||||
key={gridAttributeFromSettings}
|
);
|
||||||
>
|
|
||||||
{maybe<React.ReactNode>(
|
return (
|
||||||
() =>
|
<TableCellHeader
|
||||||
gridAttributes.find(
|
className={classes.colAttribute}
|
||||||
gridAttribute =>
|
direction={
|
||||||
getAttributeIdFromColumnValue(
|
sort.sort === ProductListUrlSortField.attribute &&
|
||||||
gridAttributeFromSettings
|
attributeId === activeAttributeSortId
|
||||||
) === gridAttribute.id
|
? getArrowDirection(sort.asc)
|
||||||
).name,
|
: undefined
|
||||||
<Skeleton />
|
}
|
||||||
)}
|
onClick={() =>
|
||||||
</TableCell>
|
onSort(ProductListUrlSortField.attribute, attributeId)
|
||||||
))}
|
}
|
||||||
|
key={gridAttributeFromSettings}
|
||||||
|
>
|
||||||
|
{maybe<React.ReactNode>(
|
||||||
|
() =>
|
||||||
|
gridAttributes.find(
|
||||||
|
gridAttribute => attributeId === gridAttribute.id
|
||||||
|
).name,
|
||||||
|
<Skeleton />
|
||||||
|
)}
|
||||||
|
</TableCellHeader>
|
||||||
|
);
|
||||||
|
})}
|
||||||
<DisplayColumn column="price" displayColumns={settings.columns}>
|
<DisplayColumn column="price" displayColumns={settings.columns}>
|
||||||
<TableCellHeader
|
<TableCellHeader
|
||||||
className={classes.colPrice}
|
className={classes.colPrice}
|
||||||
|
|
|
@ -34,6 +34,7 @@ export interface ProductListPageProps
|
||||||
FilterPageProps<ProductFilterKeys>,
|
FilterPageProps<ProductFilterKeys>,
|
||||||
FetchMoreProps,
|
FetchMoreProps,
|
||||||
SortPage<ProductListUrlSortField> {
|
SortPage<ProductListUrlSortField> {
|
||||||
|
activeAttributeSortId: string;
|
||||||
availableInGridAttributes: AvailableInGridAttributes_availableInGrid_edges_node[];
|
availableInGridAttributes: AvailableInGridAttributes_availableInGrid_edges_node[];
|
||||||
currencySymbol: string;
|
currencySymbol: string;
|
||||||
gridAttributes: AvailableInGridAttributes_grid_edges_node[];
|
gridAttributes: AvailableInGridAttributes_grid_edges_node[];
|
||||||
|
|
|
@ -31,18 +31,22 @@ export enum ProductListUrlFiltersEnum {
|
||||||
}
|
}
|
||||||
export type ProductListUrlFilters = Filters<ProductListUrlFiltersEnum>;
|
export type ProductListUrlFilters = Filters<ProductListUrlFiltersEnum>;
|
||||||
export enum ProductListUrlSortField {
|
export enum ProductListUrlSortField {
|
||||||
|
attribute = "attribute",
|
||||||
name = "name",
|
name = "name",
|
||||||
productType = "productType",
|
productType = "productType",
|
||||||
status = "status",
|
status = "status",
|
||||||
price = "price"
|
price = "price"
|
||||||
}
|
}
|
||||||
export type ProductListUrlSort = Sort<ProductListUrlSortField>;
|
export type ProductListUrlSort = Sort<ProductListUrlSortField>;
|
||||||
export type ProductListUrlQueryParams = BulkAction &
|
export interface ProductListUrlQueryParams
|
||||||
Dialog<ProductListUrlDialog> &
|
extends BulkAction,
|
||||||
ProductListUrlFilters &
|
Dialog<ProductListUrlDialog>,
|
||||||
ProductListUrlSort &
|
ProductListUrlFilters,
|
||||||
Pagination &
|
ProductListUrlSort,
|
||||||
ActiveTab;
|
Pagination,
|
||||||
|
ActiveTab {
|
||||||
|
attributeId?: string;
|
||||||
|
}
|
||||||
export const productListUrl = (params?: ProductListUrlQueryParams): string =>
|
export const productListUrl = (params?: ProductListUrlQueryParams): string =>
|
||||||
productListPath + "?" + stringifyQs(params);
|
productListPath + "?" + stringifyQs(params);
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ import {
|
||||||
ProductListUrlDialog,
|
ProductListUrlDialog,
|
||||||
ProductListUrlFilters,
|
ProductListUrlFilters,
|
||||||
ProductListUrlQueryParams,
|
ProductListUrlQueryParams,
|
||||||
|
ProductListUrlSortField,
|
||||||
productUrl
|
productUrl
|
||||||
} from "../../urls";
|
} from "../../urls";
|
||||||
import {
|
import {
|
||||||
|
@ -153,6 +154,15 @@ export const ProductList: React.StatelessComponent<ProductListProps> = ({
|
||||||
handleTabChange(tabs.length + 1);
|
handleTabChange(tabs.length + 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleSort = (field: ProductListUrlSortField, attributeId?: string) =>
|
||||||
|
navigate(
|
||||||
|
productListUrl({
|
||||||
|
...params,
|
||||||
|
...getSortUrlVariables(field, params),
|
||||||
|
attributeId
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
const paginationState = createPaginationState(settings.rowNumber, params);
|
const paginationState = createPaginationState(settings.rowNumber, params);
|
||||||
const currencySymbol = maybe(() => shop.defaultCurrency, "USD");
|
const currencySymbol = maybe(() => shop.defaultCurrency, "USD");
|
||||||
const filter = getFilterVariables(params);
|
const filter = getFilterVariables(params);
|
||||||
|
@ -230,18 +240,12 @@ export const ProductList: React.StatelessComponent<ProductListProps> = ({
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ProductListPage
|
<ProductListPage
|
||||||
|
activeAttributeSortId={params.attributeId}
|
||||||
sort={{
|
sort={{
|
||||||
asc: params.asc,
|
asc: params.asc,
|
||||||
sort: params.sort
|
sort: params.sort
|
||||||
}}
|
}}
|
||||||
onSort={field =>
|
onSort={handleSort}
|
||||||
navigate(
|
|
||||||
productListUrl({
|
|
||||||
...params,
|
|
||||||
...getSortUrlVariables(field, params)
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
availableInGridAttributes={maybe(
|
availableInGridAttributes={maybe(
|
||||||
() =>
|
() =>
|
||||||
attributes.data.availableInGrid.edges.map(
|
attributes.data.availableInGrid.edges.map(
|
||||||
|
|
|
@ -17,12 +17,20 @@ export function getSortQueryField(
|
||||||
return ProductOrderField.TYPE;
|
return ProductOrderField.TYPE;
|
||||||
case ProductListUrlSortField.status:
|
case ProductListUrlSortField.status:
|
||||||
return ProductOrderField.PUBLISHED;
|
return ProductOrderField.PUBLISHED;
|
||||||
|
default:
|
||||||
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getSortQueryVariables(
|
export function getSortQueryVariables(
|
||||||
params: ProductListUrlQueryParams
|
params: ProductListUrlQueryParams
|
||||||
): ProductOrder {
|
): ProductOrder {
|
||||||
|
if (params.sort === ProductListUrlSortField.attribute) {
|
||||||
|
return {
|
||||||
|
attributeId: params.attributeId,
|
||||||
|
direction: getOrderDirection(params.asc)
|
||||||
|
};
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
direction: getOrderDirection(params.asc),
|
direction: getOrderDirection(params.asc),
|
||||||
field: getSortQueryField(params.sort)
|
field: getSortQueryField(params.sort)
|
||||||
|
|
|
@ -34,6 +34,7 @@ const props: ProductListPageProps = {
|
||||||
sort: ProductListUrlSortField.name
|
sort: ProductListUrlSortField.name
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
activeAttributeSortId: undefined,
|
||||||
availableInGridAttributes: attributes,
|
availableInGridAttributes: attributes,
|
||||||
defaultSettings: defaultListSettings[ListViews.PRODUCT_LIST],
|
defaultSettings: defaultListSettings[ListViews.PRODUCT_LIST],
|
||||||
gridAttributes: attributes,
|
gridAttributes: attributes,
|
||||||
|
|
|
@ -50,7 +50,7 @@ export interface ListProps<TColumns extends string = string> {
|
||||||
|
|
||||||
export interface SortPage<TSortKey extends string> {
|
export interface SortPage<TSortKey extends string> {
|
||||||
sort: Sort<TSortKey>;
|
sort: Sort<TSortKey>;
|
||||||
onSort: (field: TSortKey) => void;
|
onSort: (field: TSortKey, id?: string) => void;
|
||||||
}
|
}
|
||||||
export interface ListActionsWithoutToolbar {
|
export interface ListActionsWithoutToolbar {
|
||||||
toggle: (id: string) => void;
|
toggle: (id: string) => void;
|
||||||
|
|
|
@ -589,7 +589,8 @@ export interface ProductFilterInput {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProductOrder {
|
export interface ProductOrder {
|
||||||
field: ProductOrderField;
|
field?: ProductOrderField | null;
|
||||||
|
attributeId?: string | null;
|
||||||
direction: OrderDirection;
|
direction: OrderDirection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue