Add sorting products by update at date (#1581)

* Add sorting products by update at date

* Update messages

* Change columns order in product list view

* Display updated date column by default
This commit is contained in:
Dawid Tarasiuk 2021-11-17 13:49:22 +01:00 committed by GitHub
parent c3cc2b03de
commit b50225aaa2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 113 additions and 44 deletions

View file

@ -6013,18 +6013,10 @@
"context": "modal button",
"string": "Upload URL"
},
"src_dot_products_dot_components_dot_ProductListPage_dot_1134347598": {
"context": "product price",
"string": "Price"
},
"src_dot_products_dot_components_dot_ProductListPage_dot_1542417144": {
"context": "button",
"string": "Create Product"
},
"src_dot_products_dot_components_dot_ProductListPage_dot_1952810469": {
"context": "product type",
"string": "Type"
},
"src_dot_products_dot_components_dot_ProductListPage_dot_2059406063": {
"context": "export products to csv file, button",
"string": "Export Products"
@ -6078,10 +6070,6 @@
"context": "product is visible",
"string": "Visible"
},
"src_dot_products_dot_components_dot_ProductList_dot_1134347598": {
"context": "product price",
"string": "Price"
},
"src_dot_products_dot_components_dot_ProductList_dot_150865454": {
"context": "product type",
"string": "Simple"
@ -6089,30 +6077,38 @@
"src_dot_products_dot_components_dot_ProductList_dot_1657559629": {
"string": "No products found"
},
"src_dot_products_dot_components_dot_ProductList_dot_1952810469": {
"context": "product type",
"string": "Type"
},
"src_dot_products_dot_components_dot_ProductList_dot_2754779425": {
"context": "product type",
"string": "Configurable"
},
"src_dot_products_dot_components_dot_ProductList_dot_3326160357": {
"context": "product channels",
"string": "Availability"
},
"src_dot_products_dot_components_dot_ProductList_dot_636461959": {
"context": "product",
"string": "Name"
},
"src_dot_products_dot_components_dot_ProductList_dot_availability": {
"context": "product channels",
"string": "Availability"
},
"src_dot_products_dot_components_dot_ProductList_dot_price": {
"context": "product price",
"string": "Price"
},
"src_dot_products_dot_components_dot_ProductList_dot_published": {
"context": "product publication date",
"string": "Published on {date}"
},
"src_dot_products_dot_components_dot_ProductList_dot_type": {
"context": "product type",
"string": "Type"
},
"src_dot_products_dot_components_dot_ProductList_dot_unpublished": {
"context": "product publication date",
"string": "Unpublished"
},
"src_dot_products_dot_components_dot_ProductList_dot_updatedAt": {
"context": "product updated at",
"string": "Last updated"
},
"src_dot_products_dot_components_dot_ProductList_dot_willBePublished": {
"context": "product publication date",
"string": "Becomes published on {date}"

View file

@ -22,7 +22,11 @@ export const DEFAULT_INITIAL_PAGINATION_DATA: Pagination = {
export const PAGINATE_BY = 20;
export const VALUES_PAGINATE_BY = 10;
export type ProductListColumns = "productType" | "availability" | "price";
export type ProductListColumns =
| "productType"
| "availability"
| "price"
| "date";
export interface AppListViewSettings {
[ListViews.APPS_LIST]: ListSettings;
@ -79,7 +83,7 @@ export const defaultListSettings: AppListViewSettings = {
rowNumber: PAGINATE_BY
},
[ListViews.PRODUCT_LIST]: {
columns: ["availability", "price", "productType"],
columns: ["availability", "price", "productType", "date"],
rowNumber: PAGINATE_BY
},
[ListViews.SALES_LIST]: {

View file

@ -13,6 +13,7 @@ export interface ProductAttributeAssignmentUpdate_productAttributeAssignmentUpda
__typename: "ProductError";
field: string | null;
message: string | null;
attributes: string[] | null;
}
export interface ProductAttributeAssignmentUpdate_productAttributeAssignmentUpdate_productType_taxType {

View file

@ -8,6 +8,7 @@ import {
import AvailabilityStatusLabel from "@saleor/components/AvailabilityStatusLabel";
import { ChannelsAvailabilityDropdown } from "@saleor/components/ChannelsAvailabilityDropdown";
import Checkbox from "@saleor/components/Checkbox";
import Date from "@saleor/components/Date";
import MoneyRange from "@saleor/components/MoneyRange";
import ResponsiveTable from "@saleor/components/ResponsiveTable";
import Skeleton from "@saleor/components/Skeleton";
@ -36,7 +37,7 @@ import classNames from "classnames";
import React from "react";
import { FormattedMessage } from "react-intl";
import { messages } from "./messages";
import { columnsMessages, messages } from "./messages";
const useStyles = makeStyles(
theme => ({
@ -52,6 +53,9 @@ const useStyles = makeStyles(
},
colType: {
width: 200
},
colDate: {
width: 200
}
},
colAttribute: {
@ -160,6 +164,9 @@ export const ProductList: React.FC<ProductListProps> = props => {
{gridAttributesFromSettings.map(gridAttribute => (
<col className={classes.colAttribute} key={gridAttribute} />
))}
<DisplayColumn column="date" displayColumns={settings.columns}>
<col className={classes.colDate} />
</DisplayColumn>
<DisplayColumn column="price" displayColumns={settings.columns}>
<col className={classes.colPrice} />
</DisplayColumn>
@ -200,10 +207,7 @@ export const ProductList: React.FC<ProductListProps> = props => {
}
onClick={() => onSort(ProductListUrlSortField.productType)}
>
<FormattedMessage
defaultMessage="Type"
description="product type"
/>
<FormattedMessage {...columnsMessages.type} />
</TableCellHeader>
</DisplayColumn>
<DisplayColumn
@ -226,10 +230,7 @@ export const ProductList: React.FC<ProductListProps> = props => {
)
}
>
<FormattedMessage
defaultMessage="Availability"
description="product channels"
/>
<FormattedMessage {...columnsMessages.availability} />
</TableCellHeader>
</DisplayColumn>
{gridAttributesFromSettings.map(gridAttributeFromSettings => {
@ -261,6 +262,20 @@ export const ProductList: React.FC<ProductListProps> = props => {
</TableCellHeader>
);
})}
<DisplayColumn column="date" displayColumns={settings.columns}>
<TableCellHeader
data-test-id="colDateHeader"
className={classes.colDate}
direction={
sort.sort === ProductListUrlSortField.date
? getArrowDirection(sort.asc)
: undefined
}
onClick={() => onSort(ProductListUrlSortField.date)}
>
<FormattedMessage {...columnsMessages.updatedAt} />
</TableCellHeader>
</DisplayColumn>
<DisplayColumn column="price" displayColumns={settings.columns}>
<TableCellHeader
data-test-id="colPriceHeader"
@ -276,10 +291,7 @@ export const ProductList: React.FC<ProductListProps> = props => {
!canBeSorted(ProductListUrlSortField.price, !!selectedChannelId)
}
>
<FormattedMessage
defaultMessage="Price"
description="product price"
/>
<FormattedMessage {...columnsMessages.price} />
</TableCellHeader>
</DisplayColumn>
</TableHead>
@ -413,6 +425,18 @@ export const ProductList: React.FC<ProductListProps> = props => {
}, <Skeleton />)}
</TableCell>
))}
<DisplayColumn
column="date"
displayColumns={settings.columns}
>
<TableCell className={classes.colDate} data-test="date">
{product?.updatedAt ? (
<Date date={product.updatedAt} />
) : (
<Skeleton />
)}
</TableCell>
</DisplayColumn>
<DisplayColumn
column="price"
displayColumns={settings.columns}

View file

@ -14,3 +14,22 @@ export const messages = defineMessages({
description: "product publication date"
}
});
export const columnsMessages = defineMessages({
availability: {
defaultMessage: "Availability",
description: "product channels"
},
price: {
defaultMessage: "Price",
description: "product price"
},
type: {
defaultMessage: "Type",
description: "product type"
},
updatedAt: {
defaultMessage: "Last updated",
description: "product updated at"
}
});

View file

@ -34,6 +34,7 @@ import { FormattedMessage, useIntl } from "react-intl";
import { ProductListUrlSortField } from "../../urls";
import ProductList from "../ProductList";
import { columnsMessages } from "../ProductList/messages";
import {
createFilterStructure,
ProductFilterKeys,
@ -115,19 +116,17 @@ export const ProductListPage: React.FC<ProductListPageProps> = props => {
const columns: ColumnPickerChoice[] = [
{
label: intl.formatMessage({
defaultMessage: "Price",
description: "product price"
}),
label: intl.formatMessage(columnsMessages.price),
value: "price" as ProductListColumns
},
{
label: intl.formatMessage({
defaultMessage: "Type",
description: "product type"
}),
label: intl.formatMessage(columnsMessages.type),
value: "productType" as ProductListColumns
},
{
label: intl.formatMessage(columnsMessages.updatedAt),
value: "date" as ProductListColumns
},
...availableInGridAttributes.map(attribute => ({
label: attribute.name,
value: `attribute:${attribute.id}`

View file

@ -740,6 +740,7 @@ export const products = (
): ProductList_products_edges_node[] => [
{
__typename: "Product",
updatedAt: "2020-06-22T13:52:05.094636+00:00",
attributes: [],
channelListings: [
{
@ -830,6 +831,7 @@ export const products = (
},
{
__typename: "Product",
updatedAt: "2020-06-22T13:52:05.094636+00:00",
attributes: [],
channelListings: [
{
@ -920,6 +922,7 @@ export const products = (
},
{
__typename: "Product",
updatedAt: "2020-06-22T13:52:05.094636+00:00",
attributes: [],
channelListings: [
{
@ -1010,6 +1013,7 @@ export const products = (
},
{
__typename: "Product",
updatedAt: "2020-06-22T13:52:05.094636+00:00",
attributes: [
{
__typename: "SelectedAttribute",
@ -1123,6 +1127,7 @@ export const products = (
},
{
__typename: "Product",
updatedAt: "2020-06-22T13:52:05.094636+00:00",
attributes: [
{
__typename: "SelectedAttribute",
@ -1236,6 +1241,7 @@ export const products = (
},
{
__typename: "Product",
updatedAt: "2020-06-22T13:52:05.094636+00:00",
attributes: [
{
__typename: "SelectedAttribute",
@ -1350,6 +1356,7 @@ export const products = (
},
{
__typename: "Product",
updatedAt: "2020-06-22T13:52:05.094636+00:00",
attributes: [
{
__typename: "SelectedAttribute",
@ -1463,6 +1470,7 @@ export const products = (
},
{
__typename: "Product",
updatedAt: "2020-06-22T13:52:05.094636+00:00",
attributes: [
{
__typename: "SelectedAttribute",
@ -1576,6 +1584,7 @@ export const products = (
},
{
__typename: "Product",
updatedAt: "2020-06-22T13:52:05.094636+00:00",
attributes: [
{
__typename: "SelectedAttribute",
@ -1689,6 +1698,7 @@ export const products = (
},
{
__typename: "Product",
updatedAt: "2020-06-22T13:52:05.094636+00:00",
attributes: [
{
__typename: "SelectedAttribute",
@ -1802,6 +1812,7 @@ export const products = (
},
{
__typename: "Product",
updatedAt: "2020-06-22T13:52:05.094636+00:00",
attributes: [
{
__typename: "SelectedAttribute",
@ -1915,6 +1926,7 @@ export const products = (
},
{
__typename: "Product",
updatedAt: "2020-06-22T13:52:05.094636+00:00",
attributes: [
{
__typename: "SelectedAttribute",
@ -2028,6 +2040,7 @@ export const products = (
},
{
__typename: "Product",
updatedAt: "2020-06-22T13:52:05.094636+00:00",
attributes: [
{
__typename: "SelectedAttribute",
@ -2141,6 +2154,7 @@ export const products = (
},
{
__typename: "Product",
updatedAt: "2020-06-22T13:52:05.094636+00:00",
attributes: [
{
__typename: "SelectedAttribute",
@ -2254,6 +2268,7 @@ export const products = (
},
{
__typename: "Product",
updatedAt: "2020-06-22T13:52:05.094636+00:00",
attributes: [
{
__typename: "SelectedAttribute",
@ -2367,6 +2382,7 @@ export const products = (
},
{
__typename: "Product",
updatedAt: "2020-06-22T13:52:05.094636+00:00",
attributes: [
{
__typename: "SelectedAttribute",
@ -2480,6 +2496,7 @@ export const products = (
},
{
__typename: "Product",
updatedAt: "2020-06-22T13:52:05.094636+00:00",
attributes: [
{
__typename: "SelectedAttribute",
@ -2593,6 +2610,7 @@ export const products = (
},
{
__typename: "Product",
updatedAt: "2020-06-22T13:52:05.094636+00:00",
attributes: [
{
__typename: "SelectedAttribute",
@ -2706,6 +2724,7 @@ export const products = (
},
{
__typename: "Product",
updatedAt: "2020-06-22T13:52:05.094636+00:00",
attributes: [
{
__typename: "SelectedAttribute",
@ -2819,6 +2838,7 @@ export const products = (
},
{
__typename: "Product",
updatedAt: "2020-06-22T13:52:05.094636+00:00",
attributes: [
{
__typename: "SelectedAttribute",

View file

@ -158,6 +158,7 @@ const productListQuery = gql`
edges {
node {
...ProductFragment
updatedAt
attributes {
attribute {
id

View file

@ -110,6 +110,7 @@ export interface ProductList_products_edges_node {
thumbnail: ProductList_products_edges_node_thumbnail | null;
productType: ProductList_products_edges_node_productType;
channelListings: ProductList_products_edges_node_channelListings[] | null;
updatedAt: any | null;
attributes: ProductList_products_edges_node_attributes[];
}

View file

@ -50,7 +50,8 @@ export enum ProductListUrlSortField {
productType = "productType",
status = "status",
price = "price",
rank = "rank"
rank = "rank",
date = "date"
}
export type ProductListUrlSort = Sort<ProductListUrlSortField>;
export interface ProductListUrlQueryParams

View file

@ -16,6 +16,7 @@ export function canBeSorted(
case ProductListUrlSortField.productType:
case ProductListUrlSortField.attribute:
case ProductListUrlSortField.rank:
case ProductListUrlSortField.date:
return true;
case ProductListUrlSortField.price:
case ProductListUrlSortField.status:
@ -39,6 +40,8 @@ export function getSortQueryField(
return ProductOrderField.PUBLISHED;
case ProductListUrlSortField.rank:
return ProductOrderField.RANK;
case ProductListUrlSortField.date:
return ProductOrderField.DATE;
default:
return undefined;
}