diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b0ec0154..727424e47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,3 +22,4 @@ All notable, unreleased changes to this project will be documented in this file. - Fix en locale matching - #165 by @dominik-zeglen - Implement the Credential Management API - #158 by @patrys - Add search bars - #172 by @dominik-zeglen +- Add sorting to product list - #173 by @dominik-zeglen diff --git a/locale/messages.pot b/locale/messages.pot index a054058f8..ab156d25a 100644 --- a/locale/messages.pot +++ b/locale/messages.pot @@ -1,6 +1,6 @@ msgid "" msgstr "" -"POT-Creation-Date: 2019-09-12T15:12:49.543Z\n" +"POT-Creation-Date: 2019-09-16T15:25:09.340Z\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "MIME-Version: 1.0\n" @@ -131,22 +131,6 @@ msgctxt "create new menu item, header" msgid "Add Item" msgstr "" -#: build/locale/src/navigation/components/MenuCreateDialog/MenuCreateDialog.json -#. [menuCreateDialogHeader] - dialog header -#. defaultMessage is: -#. Add Menu -msgctxt "dialog header" -msgid "Add Menu" -msgstr "" - -#: build/locale/src/navigation/components/MenuListPage/MenuListPage.json -#. [menuListPageAddMenu] - button -#. defaultMessage is: -#. Add Menu -msgctxt "button" -msgid "Add Menu" -msgstr "" - #: build/locale/src/siteSettings/components/SiteSettingsKeyDialog/SiteSettingsKeyDialog.json #. [src.siteSettings.components.SiteSettingsKeyDialog.1238948746] - dialog header #. defaultMessage is: @@ -155,14 +139,6 @@ msgctxt "dialog header" msgid "Add New Authorization Key" msgstr "" -#: build/locale/src/pages/components/PageDetailsPage/PageDetailsPage.json -#. [src.pages.components.PageDetailsPage.755314116] - page header -#. defaultMessage is: -#. Add Page -msgctxt "page header" -msgid "Add Page" -msgstr "" - #: build/locale/src/shipping/components/ShippingZoneRateDialog/ShippingZoneRateDialog.json #. [src.shipping.components.ShippingZoneRateDialog.2892088870] - dialog header #. defaultMessage is: @@ -171,38 +147,6 @@ msgctxt "dialog header" msgid "Add Price Rate" msgstr "" -#: build/locale/src/orders/components/OrderProductAddDialog/OrderProductAddDialog.json -#. [src.orders.components.OrderProductAddDialog.2775402904] - dialog header -#. defaultMessage is: -#. Add Product -msgctxt "dialog header" -msgid "Add Product" -msgstr "" - -#: build/locale/src/products/components/ProductListPage/ProductListPage.json -#. [src.products.components.ProductListPage.2775402904] - button -#. defaultMessage is: -#. Add Product -msgctxt "button" -msgid "Add Product" -msgstr "" - -#: build/locale/src/discounts/components/SaleListPage/SaleListPage.json -#. [src.discounts.components.SaleListPage.1742771332] - button -#. defaultMessage is: -#. Add Sale -msgctxt "button" -msgid "Add Sale" -msgstr "" - -#: build/locale/src/staff/components/StaffAddMemberDialog/StaffAddMemberDialog.json -#. [src.staff.components.StaffAddMemberDialog.3490059488] - dialog header -#. defaultMessage is: -#. Add Staff Member -msgctxt "dialog header" -msgid "Add Staff Member" -msgstr "" - #: build/locale/src/attributes/components/AttributeValueEditDialog/AttributeValueEditDialog.json #. [src.attributes.components.AttributeValueEditDialog.1841790893] - add attribute value #. defaultMessage is: @@ -211,14 +155,6 @@ msgctxt "add attribute value" msgid "Add Value" msgstr "" -#: build/locale/src/products/views/ProductVariantCreate.json -#. [src.products.views.2178905289] - header -#. defaultMessage is: -#. Add Variant -msgctxt "header" -msgid "Add Variant" -msgstr "" - #: build/locale/src/shipping/components/ShippingZoneRateDialog/ShippingZoneRateDialog.json #. [src.shipping.components.ShippingZoneRateDialog.1397795758] - add weight based shipping method, dialog header #. defaultMessage is: @@ -235,14 +171,6 @@ msgctxt "button" msgid "Add address" msgstr "" -#: build/locale/src/attributes/components/AttributeListPage/AttributeListPage.json -#. [src.attributes.components.AttributeListPage.350498821] - button -#. defaultMessage is: -#. Add attribute -msgctxt "button" -msgid "Add attribute" -msgstr "" - #: build/locale/src/siteSettings/components/SiteSettingsKeyDialog/SiteSettingsKeyDialog.json #. [src.siteSettings.components.SiteSettingsKeyDialog.50561933] - button #. defaultMessage is: @@ -251,14 +179,6 @@ msgctxt "button" msgid "Add authentication" msgstr "" -#: build/locale/src/categories/components/CategoryListPage/CategoryListPage.json -#. [src.categories.components.CategoryListPage.228151782] - button -#. defaultMessage is: -#. Add category -msgctxt "button" -msgid "Add category" -msgstr "" - #: build/locale/src/collections/components/CollectionCreatePage/CollectionCreatePage.json #. [src.collections.components.CollectionCreatePage.3958681866] - page header #. defaultMessage is: @@ -267,14 +187,6 @@ msgctxt "page header" msgid "Add collection" msgstr "" -#: build/locale/src/collections/components/CollectionListPage/CollectionListPage.json -#. [src.collections.components.CollectionListPage.3958681866] - button -#. defaultMessage is: -#. Add collection -msgctxt "button" -msgid "Add collection" -msgstr "" - #: build/locale/src/customers/components/CustomerCreatePage/CustomerCreatePage.json #. [src.customers.components.CustomerCreatePage.1934221653] - page header #. defaultMessage is: @@ -307,14 +219,6 @@ msgctxt "button" msgid "Add key" msgstr "" -#: build/locale/src/navigation/components/MenuItems/MenuItems.json -#. [menuItemsAddItem] - add new menu item -#. defaultMessage is: -#. Add new item -msgctxt "add new menu item" -msgid "Add new item" -msgstr "" - #: build/locale/src/navigation/components/MenuItems/MenuItems.json #. [menuItemsPlaceholder] #. defaultMessage is: @@ -347,14 +251,6 @@ msgctxt "button" msgid "Add or Edit Link" msgstr "" -#: build/locale/src/pages/components/PageListPage/PageListPage.json -#. [src.pages.components.PageListPage.1767905232] - button -#. defaultMessage is: -#. Add page -msgctxt "button" -msgid "Add page" -msgstr "" - #: build/locale/src/categories/components/CategoryProducts/CategoryProducts.json #. [src.categories.components.CategoryProducts.3554578821] - button #. defaultMessage is: @@ -363,14 +259,6 @@ msgctxt "button" msgid "Add product" msgstr "" -#: build/locale/src/productTypes/components/ProductTypeListPage/ProductTypeListPage.json -#. [src.productTypes.components.ProductTypeListPage.889729490] - button -#. defaultMessage is: -#. Add product type -msgctxt "button" -msgid "Add product type" -msgstr "" - #: build/locale/src/orders/components/OrderDraftDetails/OrderDraftDetails.json #. [src.orders.components.OrderDraftDetails.2528459381] - button #. defaultMessage is: @@ -379,14 +267,6 @@ msgctxt "button" msgid "Add products" msgstr "" -#: build/locale/src/shipping/components/ShippingZoneRates/ShippingZoneRates.json -#. [src.shipping.components.ShippingZoneRates.352297149] - button -#. defaultMessage is: -#. Add rate -msgctxt "button" -msgid "Add rate" -msgstr "" - #: build/locale/src/categories/components/CategoryCreatePage/CategoryCreatePage.json #. [src.categories.components.CategoryCreatePage.2563994280] #. defaultMessage is: @@ -439,30 +319,6 @@ msgctxt "button" msgid "Add shipping carrier" msgstr "" -#: build/locale/src/shipping/components/ShippingZonesList/ShippingZonesList.json -#. [src.shipping.components.ShippingZonesList.2474410767] - button -#. defaultMessage is: -#. Add shipping zone -msgctxt "button" -msgid "Add shipping zone" -msgstr "" - -#: build/locale/src/staff/components/StaffListPage/StaffListPage.json -#. [src.staff.components.StaffListPage.802625341] - button -#. defaultMessage is: -#. Add staff member -msgctxt "button" -msgid "Add staff member" -msgstr "" - -#: build/locale/src/categories/components/CategoryUpdatePage/CategoryUpdatePage.json -#. [src.categories.components.CategoryUpdatePage.435697837] - button -#. defaultMessage is: -#. Add subcategory -msgctxt "button" -msgid "Add subcategory" -msgstr "" - #: build/locale/src/attributes/components/AttributeProperties/AttributeProperties.json #. [src.attributes.components.AttributeProperties.673770329] - add attribute as column in product list table #. defaultMessage is: @@ -487,34 +343,14 @@ msgctxt "dialog header" msgid "Add tracking code" msgstr "" -#: build/locale/src/attributes/components/AttributeValues/AttributeValues.json -#. [src.attributes.components.AttributeValues.254756045] - add attribute value button -#. defaultMessage is: -#. Add value -msgctxt "add attribute value button" -msgid "Add value" -msgstr "" - #: build/locale/src/products/components/ProductVariantNavigation/ProductVariantNavigation.json #. [src.products.components.ProductVariantNavigation.2845381934] - button #. defaultMessage is: #. Add variant -#: build/locale/src/products/components/ProductVariants/ProductVariants.json -#. [src.products.components.ProductVariants.2845381934] - button -#. defaultMessage is: -#. Add variant msgctxt "button" msgid "Add variant" msgstr "" -#: build/locale/src/discounts/components/VoucherListPage/VoucherListPage.json -#. [src.discounts.components.VoucherListPage.1536809153] - button -#. defaultMessage is: -#. Add voucher -msgctxt "button" -msgid "Add voucher" -msgstr "" - #: build/locale/src/attributes/views/AttributeDetails/AttributeDetails.json #. [src.attributes.views.AttributeDetails.634268988] - added new attribute value #. defaultMessage is: @@ -571,14 +407,6 @@ msgctxt "description" msgid "Address line 2" msgstr "" -#: build/locale/src/customers/components/CustomerAddress/CustomerAddress.json -#. [src.customers.components.CustomerAddress.1320082647] - addres card header -#. defaultMessage is: -#. Address {addressNumber} -msgctxt "addres card header" -msgid "Address {addressNumber}" -msgstr "" - #: build/locale/src/attributes/components/AttributeValues/AttributeValues.json #. [src.attributes.components.AttributeValues.1565474525] - attribute values list: slug column header #. defaultMessage is: @@ -827,6 +655,14 @@ msgctxt "description" msgid "Are you sure you want to delete collection's image?" msgstr "" +#: build/locale/src/orders/components/OrderDraftCancelDialog/OrderDraftCancelDialog.json +#. [src.orders.components.OrderDraftCancelDialog.36681973] +#. defaultMessage is: +#. Are you sure you want to delete draft #{number}? +msgctxt "description" +msgid "Are you sure you want to delete draft #{number}?" +msgstr "" + #: build/locale/src/navigation/views/MenuDetails/index.json #. [menuDetailsDeleteMenuContent] #. defaultMessage is: @@ -843,6 +679,14 @@ msgctxt "description" msgid "Are you sure you want to delete this address from users address book?" msgstr "" +#: build/locale/src/products/views/ProductImage.json +#. [src.products.views.2880386427] +#. defaultMessage is: +#. Are you sure you want to delete this image? +msgctxt "description" +msgid "Are you sure you want to delete this image?" +msgstr "" + #: build/locale/src/attributes/components/AttributeDeleteDialog/AttributeDeleteDialog.json #. [src.attributes.components.AttributeDeleteDialog.3738429348] - dialog content #. defaultMessage is: @@ -995,6 +839,22 @@ msgctxt "dialog content" msgid "Are you sure you want to delete {counter,plural,one{this voucher} other{{displayQuantity} vouchers}}?" msgstr "" +#: build/locale/src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.json +#. [src.shipping.views.ShippingZoneDetails.131963671] - unassign country +#. defaultMessage is: +#. Are you sure you want to delete {countryName} from this shipping zone? +msgctxt "unassign country" +msgid "Are you sure you want to delete {countryName} from this shipping zone?" +msgstr "" + +#: build/locale/src/staff/views/StaffDetails.json +#. [src.staff.views.8878988] +#. defaultMessage is: +#. Are you sure you want to delete {email} from staff members? +msgctxt "description" +msgid "Are you sure you want to delete {email} from staff members?" +msgstr "" + #: build/locale/src/customers/views/CustomerDetails.json #. [src.customers.views.1927691511] - delete customer, dialog content #. defaultMessage is: @@ -1131,30 +991,6 @@ msgctxt "dialog content" msgid "Are you sure you want to publish {counter,plural,one{this product} other{{displayQuantity} products}}?" msgstr "" -#: build/locale/src/orders/components/OrderDraftCancelDialog/OrderDraftCancelDialog.json -#. [src.orders.components.OrderDraftCancelDialog.3199827590] -#. defaultMessage is: -#. Are you sure you want to remove draft #{number}? -msgctxt "description" -msgid "Are you sure you want to remove draft #{number}?" -msgstr "" - -#: build/locale/src/products/views/ProductImage.json -#. [src.products.views.672103788] -#. defaultMessage is: -#. Are you sure you want to remove this image? -msgctxt "description" -msgid "Are you sure you want to remove this image?" -msgstr "" - -#: build/locale/src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.json -#. [src.shipping.views.ShippingZoneDetails.1790261672] - unassign country -#. defaultMessage is: -#. Are you sure you want to remove {countryName} from this shipping zone? -msgctxt "unassign country" -msgid "Are you sure you want to remove {countryName} from this shipping zone?" -msgstr "" - #: build/locale/src/staff/views/StaffDetails.json #. [src.staff.views.3945766678] #. defaultMessage is: @@ -1163,14 +999,6 @@ msgctxt "description" msgid "Are you sure you want to remove {email} avatar?" msgstr "" -#: build/locale/src/staff/views/StaffDetails.json -#. [src.staff.views.2728048444] -#. defaultMessage is: -#. Are you sure you want to remove {email} from staff members? -msgctxt "description" -msgid "Are you sure you want to remove {email} from staff members?" -msgstr "" - #: build/locale/src/productTypes/components/ProductTypeAttributeUnassignDialog/ProductTypeAttributeUnassignDialog.json #. [src.productTypes.components.ProductTypeAttributeUnassignDialog.722498450] #. defaultMessage is: @@ -1383,6 +1211,14 @@ msgctxt "button" msgid "Assign products" msgstr "" +#: build/locale/src/attributes/components/AttributeValues/AttributeValues.json +#. [src.attributes.components.AttributeValues.351422234] - assign attribute value button +#. defaultMessage is: +#. Assign value +msgctxt "assign attribute value button" +msgid "Assign value" +msgstr "" + #: build/locale/src/attributes/components/AttributeDetails/AttributeDetails.json #. [src.attributes.components.AttributeDetails.3605174225] - attribute's slug short code label #. defaultMessage is: @@ -1459,6 +1295,14 @@ msgctxt "product attributes, section header" msgid "Attributes" msgstr "" +#: build/locale/src/configuration/index.json +#. [src.configuration.2326418019] +#. defaultMessage is: +#. Attributes and Product Typess +msgctxt "description" +msgid "Attributes and Product Typess" +msgstr "" + #: build/locale/src/attributes/views/AttributeList/AttributeList.json #. [src.attributes.views.AttributeList.3218248395] - deleted multiple attributes #. defaultMessage is: @@ -2227,6 +2071,22 @@ msgctxt "description" msgid "Country area" msgstr "" +#: build/locale/src/navigation/components/MenuCreateDialog/MenuCreateDialog.json +#. [menuCreateDialogHeader] - dialog header +#. defaultMessage is: +#. Create Menu +msgctxt "dialog header" +msgid "Create Menu" +msgstr "" + +#: build/locale/src/navigation/components/MenuListPage/MenuListPage.json +#. [menuListPageAddMenu] - button +#. defaultMessage is: +#. Create Menu +msgctxt "button" +msgid "Create Menu" +msgstr "" + #: build/locale/src/attributes/components/AttributePage/AttributePage.json #. [src.attributes.components.AttributePage.2855501559] - page title #. defaultMessage is: @@ -2251,6 +2111,30 @@ msgctxt "header" msgid "Create New Shipping Zone" msgstr "" +#: build/locale/src/pages/components/PageDetailsPage/PageDetailsPage.json +#. [src.pages.components.PageDetailsPage.1068617485] - page header +#. defaultMessage is: +#. Create Page +msgctxt "page header" +msgid "Create Page" +msgstr "" + +#: build/locale/src/orders/components/OrderProductAddDialog/OrderProductAddDialog.json +#. [src.orders.components.OrderProductAddDialog.1542417144] - dialog header +#. defaultMessage is: +#. Create Product +msgctxt "dialog header" +msgid "Create Product" +msgstr "" + +#: build/locale/src/products/components/ProductListPage/ProductListPage.json +#. [src.products.components.ProductListPage.1542417144] - button +#. defaultMessage is: +#. Create Product +msgctxt "button" +msgid "Create Product" +msgstr "" + #: build/locale/src/products/views/ProductCreate.json #. [src.products.views.1542417144] - window title #. defaultMessage is: @@ -2283,11 +2167,19 @@ msgctxt "page header" msgid "Create Sale" msgstr "" +#: build/locale/src/discounts/components/SaleListPage/SaleListPage.json +#. [src.discounts.components.SaleListPage.3866518732] - button +#. defaultMessage is: +#. Create Sale +msgctxt "button" +msgid "Create Sale" +msgstr "" + #: build/locale/src/products/views/ProductVariantCreate.json -#. [src.products.views.2362587265] - window title +#. [src.products.views.2362587265] - header #. defaultMessage is: #. Create Variant -msgctxt "window title" +msgctxt "header" msgid "Create Variant" msgstr "" @@ -2299,6 +2191,22 @@ msgctxt "page header" msgid "Create Voucher" msgstr "" +#: build/locale/src/attributes/components/AttributeListPage/AttributeListPage.json +#. [src.attributes.components.AttributeListPage.3824684885] - button +#. defaultMessage is: +#. Create attribute +msgctxt "button" +msgid "Create attribute" +msgstr "" + +#: build/locale/src/categories/components/CategoryListPage/CategoryListPage.json +#. [src.categories.components.CategoryListPage.1140231710] - button +#. defaultMessage is: +#. Create category +msgctxt "button" +msgid "Create category" +msgstr "" + #: build/locale/src/categories/views/CategoryCreate.json #. [src.categories.views.1140231710] - window title #. defaultMessage is: @@ -2307,6 +2215,14 @@ msgctxt "window title" msgid "Create category" msgstr "" +#: build/locale/src/collections/components/CollectionListPage/CollectionListPage.json +#. [src.collections.components.CollectionListPage.686910896] - button +#. defaultMessage is: +#. Create collection +msgctxt "button" +msgid "Create collection" +msgstr "" + #: build/locale/src/collections/views/CollectionCreate.json #. [src.collections.views.686910896] - window title #. defaultMessage is: @@ -2323,6 +2239,14 @@ msgctxt "window title" msgid "Create customer" msgstr "" +#: build/locale/src/navigation/components/MenuItems/MenuItems.json +#. [menuItemsAddItem] - add new menu item +#. defaultMessage is: +#. Create new item +msgctxt "add new menu item" +msgid "Create new item" +msgstr "" + #: build/locale/src/orders/components/OrderDraftListPage/OrderDraftListPage.json #. [src.orders.components.OrderDraftListPage.2826235371] - button #. defaultMessage is: @@ -2335,6 +2259,14 @@ msgctxt "button" msgid "Create order" msgstr "" +#: build/locale/src/pages/components/PageListPage/PageListPage.json +#. [src.pages.components.PageListPage.3785394515] - button +#. defaultMessage is: +#. Create page +msgctxt "button" +msgid "Create page" +msgstr "" + #: build/locale/src/pages/views/PageCreate.json #. [src.pages.views.3785394515] - header #. defaultMessage is: @@ -2347,10 +2279,54 @@ msgstr "" #. [src.shipping.components.ShippingZoneRateDialog.16061680] - button #. defaultMessage is: #. Create rate +#: build/locale/src/shipping/components/ShippingZoneRates/ShippingZoneRates.json +#. [src.shipping.components.ShippingZoneRates.16061680] - button +#. defaultMessage is: +#. Create rate msgctxt "button" msgid "Create rate" msgstr "" +#: build/locale/src/shipping/components/ShippingZonesList/ShippingZonesList.json +#. [src.shipping.components.ShippingZonesList.2673544109] - button +#. defaultMessage is: +#. Create shipping zone +msgctxt "button" +msgid "Create shipping zone" +msgstr "" + +#: build/locale/src/categories/components/CategoryUpdatePage/CategoryUpdatePage.json +#. [src.categories.components.CategoryUpdatePage.770296100] - button +#. defaultMessage is: +#. Create subcategory +msgctxt "button" +msgid "Create subcategory" +msgstr "" + +#: build/locale/src/products/components/ProductVariants/ProductVariants.json +#. [src.products.components.ProductVariants.3989383405] - button +#. defaultMessage is: +#. Create variant +msgctxt "button" +msgid "Create variant" +msgstr "" + +#: build/locale/src/products/views/ProductVariantCreate.json +#. [src.products.views.3989383405] - window title +#. defaultMessage is: +#. Create variant +msgctxt "window title" +msgid "Create variant" +msgstr "" + +#: build/locale/src/discounts/components/VoucherListPage/VoucherListPage.json +#. [src.discounts.components.VoucherListPage.614836274] - button +#. defaultMessage is: +#. Create voucher +msgctxt "button" +msgid "Create voucher" +msgstr "" + #: build/locale/src/collections/views/CollectionCreate.json #. [src.collections.views.1597339737] #. defaultMessage is: @@ -2647,6 +2623,14 @@ msgctxt "dialog title" msgid "Delete Collection" msgstr "" +#: build/locale/src/products/views/ProductImage.json +#. [src.products.views.1731766393] - dialog header +#. defaultMessage is: +#. Delete Image +msgctxt "dialog header" +msgid "Delete Image" +msgstr "" + #: build/locale/src/orders/views/OrderDraftList/OrderDraftList.json #. [src.orders.views.OrderDraftList.1161115149] - dialog header #. defaultMessage is: @@ -2887,6 +2871,22 @@ msgctxt "dialog header" msgid "Delete customers" msgstr "" +#: build/locale/src/orders/components/OrderDraftCancelDialog/OrderDraftCancelDialog.json +#. [src.orders.components.OrderDraftCancelDialog.632633254] - dialog header +#. defaultMessage is: +#. Delete draft order +msgctxt "dialog header" +msgid "Delete draft order" +msgstr "" + +#: build/locale/src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.json +#. [src.shipping.views.ShippingZoneDetails.1947090060] - unassign country, dialog header +#. defaultMessage is: +#. Delete from shipping zone +msgctxt "unassign country, dialog header" +msgid "Delete from shipping zone" +msgstr "" + #: build/locale/src/collections/views/CollectionDetails.json #. [src.collections.views.942133001] - dialog title #. defaultMessage is: @@ -2947,6 +2947,14 @@ msgctxt "description" msgid "Deleted collection" msgstr "" +#: build/locale/src/orders/views/OrderDraftList/OrderDraftList.json +#. [src.orders.views.OrderDraftList.1648805446] +#. defaultMessage is: +#. Deleted draft orders +msgctxt "description" +msgid "Deleted draft orders" +msgstr "" + #: build/locale/src/navigation/views/MenuList.json #. [menuListDeletedMenu] #. defaultMessage is: @@ -3688,11 +3696,11 @@ msgid "If empty, the preview shows what will be autogenerated." msgstr "" #: build/locale/src/attributes/components/AttributeProperties/AttributeProperties.json -#. [src.attributes.components.AttributeProperties.2519239682] +#. [src.attributes.components.AttributeProperties.4048785456] #. defaultMessage is: -#. If enable this attribute can be used as a column in product table. +#. If enabled this attribute can be used as a column in product table. msgctxt "description" -msgid "If enable this attribute can be used as a column in product table." +msgid "If enabled this attribute can be used as a column in product table." msgstr "" #: build/locale/src/attributes/components/AttributeProperties/AttributeProperties.json @@ -3787,6 +3795,22 @@ msgctxt "product variant stock" msgid "Inventory" msgstr "" +#: build/locale/src/staff/components/StaffAddMemberDialog/StaffAddMemberDialog.json +#. [src.staff.components.StaffAddMemberDialog.1481503299] - dialog header +#. defaultMessage is: +#. Invite Staff Member +msgctxt "dialog header" +msgid "Invite Staff Member" +msgstr "" + +#: build/locale/src/staff/components/StaffListPage/StaffListPage.json +#. [src.staff.components.StaffListPage.797461521] - button +#. defaultMessage is: +#. Invite staff member +msgctxt "button" +msgid "Invite staff member" +msgstr "" + #: build/locale/src/productTypes/components/ProductTypeShipping/ProductTypeShipping.json #. [src.productTypes.components.ProductTypeShipping.2143413921] - switch button #. defaultMessage is: @@ -4131,6 +4155,14 @@ msgctxt "voucher requirement" msgid "Minimum quantity of items" msgstr "" +#: build/locale/src/configuration/index.json +#. [src.configuration.1233229030] +#. defaultMessage is: +#. Miscellaneous +msgctxt "description" +msgid "Miscellaneous" +msgstr "" + #: build/locale/src/attributes/components/AttributeDetails/AttributeDetails.json #. [src.attributes.components.AttributeDetails.3334509011] - product attribute type #. defaultMessage is: @@ -5631,6 +5663,14 @@ msgctxt "description" msgid "Product Name" msgstr "" +#: build/locale/src/configuration/index.json +#. [src.configuration.3655543906] +#. defaultMessage is: +#. Product Settings +msgctxt "description" +msgid "Product Settings" +msgstr "" + #: build/locale/src/discounts/components/DiscountProducts/DiscountProducts.json #. [src.discounts.components.DiscountProducts.4257289053] #. defaultMessage is: @@ -5784,11 +5824,11 @@ msgid "Products were added to draft order" msgstr "" #: build/locale/src/orders/components/OrderHistory/OrderHistory.json -#. [src.orders.components.OrderHistory.2574162126] - order history message +#. [src.orders.components.OrderHistory.4067959693] - order history message #. defaultMessage is: -#. Products were removed from draft order +#. Products were deleted from draft order msgctxt "order history message" -msgid "Products were removed from draft order" +msgid "Products were deleted from draft order" msgstr "" #: build/locale/src/intl.json @@ -6083,14 +6123,6 @@ msgctxt "switch button" msgid "Release all stock allocated to this order" msgstr "" -#: build/locale/src/auth/components/LoginPage/LoginPage.json -#. [src.auth.components.LoginPage.3182284913] - login -#. defaultMessage is: -#. Remember me -msgctxt "login" -msgid "Remember me" -msgstr "" - #: build/locale/src/categories/views/CategoryDetails.json #. [src.categories.views.3488150607] #. defaultMessage is: @@ -6111,38 +6143,6 @@ msgctxt "button" msgid "Remove" msgstr "" -#: build/locale/src/products/views/ProductImage.json -#. [src.products.views.490753666] - dialog header -#. defaultMessage is: -#. Remove Image -msgctxt "dialog header" -msgid "Remove Image" -msgstr "" - -#: build/locale/src/orders/components/OrderDraftCancelDialog/OrderDraftCancelDialog.json -#. [src.orders.components.OrderDraftCancelDialog.500287069] - dialog header -#. defaultMessage is: -#. Remove draft order -msgctxt "dialog header" -msgid "Remove draft order" -msgstr "" - -#: build/locale/src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.json -#. [src.shipping.views.ShippingZoneDetails.254167659] - unassign country, dialog header -#. defaultMessage is: -#. Remove from shipping zone -msgctxt "unassign country, dialog header" -msgid "Remove from shipping zone" -msgstr "" - -#: build/locale/src/orders/views/OrderDraftList/OrderDraftList.json -#. [src.orders.views.OrderDraftList.3880993240] -#. defaultMessage is: -#. Removed draft orders -msgctxt "description" -msgid "Removed draft orders" -msgstr "" - #: build/locale/src/pages/views/PageDetails.json #. [src.pages.views.1457312643] #. defaultMessage is: @@ -6779,6 +6779,14 @@ msgctxt "description" msgid "Set plugin as Active" msgstr "" +#: build/locale/src/components/VisibilityCard/VisibilityCard.json +#. [src.components.VisibilityCard.292404896] +#. defaultMessage is: +#. Set publication date +msgctxt "description" +msgid "Set publication date" +msgstr "" + #: build/locale/src/discounts/translations.json #. [src.discounts.shipment] - voucher discount #. defaultMessage is: @@ -7039,6 +7047,14 @@ msgctxt "staff section name" msgid "Staff Members" msgstr "" +#: build/locale/src/configuration/index.json +#. [src.configuration.3140151600] +#. defaultMessage is: +#. Staff Settings +msgctxt "description" +msgid "Staff Settings" +msgstr "" + #: build/locale/src/misc.json #. [src.standard] - tax rate #. defaultMessage is: @@ -8491,6 +8507,22 @@ msgctxt "description" msgid "ZIP / Postal code" msgstr "" +#: build/locale/src/productTypes/components/ProductTypeListPage/ProductTypeListPage.json +#. [src.productTypes.components.ProductTypeListPage.3479705616] - button +#. defaultMessage is: +#. create product type +msgctxt "button" +msgid "create product type" +msgstr "" + +#: build/locale/src/staff/views/StaffDetails.json +#. [src.staff.views.1308770978] - dialog header +#. defaultMessage is: +#. delete Staff User +msgctxt "dialog header" +msgid "delete Staff User" +msgstr "" + #: build/locale/src/orders/components/OrderPayment/OrderPayment.json #. [orderPaymentVATDoesNotApply] - vat not included in order price #. defaultMessage is: @@ -8563,19 +8595,35 @@ msgctxt "product status is set as" msgid "is set as" msgstr "" -#: build/locale/src/staff/views/StaffDetails.json -#. [src.staff.views.2240444792] - dialog header -#. defaultMessage is: -#. remove Staff User -msgctxt "dialog header" -msgid "remove Staff User" -msgstr "" - -#: build/locale/src/components/VisibilityCard/VisibilityCard.json -#. [src.components.VisibilityCard.1815688500] +#: build/locale/src/collections/components/CollectionCreatePage/CollectionCreatePage.json +#. [src.collections.components.CollectionCreatePage.1815688500] - collection #. defaultMessage is: #. since {date} -msgctxt "description" +#: build/locale/src/collections/components/CollectionDetailsPage/CollectionDetailsPage.json +#. [src.collections.components.CollectionDetailsPage.1815688500] - collection +#. defaultMessage is: +#. since {date} +msgctxt "collection" +msgid "since {date}" +msgstr "" + +#: build/locale/src/pages/components/PageDetailsPage/PageDetailsPage.json +#. [src.pages.components.PageDetailsPage.1815688500] - page +#. defaultMessage is: +#. since {date} +msgctxt "page" +msgid "since {date}" +msgstr "" + +#: build/locale/src/products/components/ProductCreatePage/ProductCreatePage.json +#. [src.products.components.ProductCreatePage.1815688500] - product +#. defaultMessage is: +#. since {date} +#: build/locale/src/products/components/ProductUpdatePage/ProductUpdatePage.json +#. [src.products.components.ProductUpdatePage.1815688500] - product +#. defaultMessage is: +#. since {date} +msgctxt "product" msgid "since {date}" msgstr "" @@ -8603,11 +8651,35 @@ msgctxt "weight" msgid "to {value} {unit}" msgstr "" -#: build/locale/src/components/VisibilityCard/VisibilityCard.json -#. [src.components.VisibilityCard.2001551496] +#: build/locale/src/collections/components/CollectionCreatePage/CollectionCreatePage.json +#. [src.collections.components.CollectionCreatePage.2001551496] - collection #. defaultMessage is: #. will be visible from {date} -msgctxt "description" +#: build/locale/src/collections/components/CollectionDetailsPage/CollectionDetailsPage.json +#. [src.collections.components.CollectionDetailsPage.2001551496] - collection +#. defaultMessage is: +#. will be visible from {date} +msgctxt "collection" +msgid "will be visible from {date}" +msgstr "" + +#: build/locale/src/pages/components/PageDetailsPage/PageDetailsPage.json +#. [src.pages.components.PageDetailsPage.2001551496] - page +#. defaultMessage is: +#. will be visible from {date} +msgctxt "page" +msgid "will be visible from {date}" +msgstr "" + +#: build/locale/src/products/components/ProductCreatePage/ProductCreatePage.json +#. [src.products.components.ProductCreatePage.2001551496] - product +#. defaultMessage is: +#. will be visible from {date} +#: build/locale/src/products/components/ProductUpdatePage/ProductUpdatePage.json +#. [src.products.components.ProductUpdatePage.2001551496] - product +#. defaultMessage is: +#. will be visible from {date} +msgctxt "product" msgid "will be visible from {date}" msgstr "" diff --git a/schema.graphql b/schema.graphql index 2329832e6..8c8d128f4 100644 --- a/schema.graphql +++ b/schema.graphql @@ -3303,7 +3303,7 @@ type ShippingZoneUpdate { type Shop { geolocalization: Geolocalization authorizationKeys: [AuthorizationKey]! - countries: [CountryDisplay]! + countries(languageCode: LanguageCodeEnum): [CountryDisplay]! currencies: [String]! defaultCurrency: String! defaultCountry: CountryDisplay diff --git a/src/components/TableCellHeader/TableCellHeader.stories.tsx b/src/components/TableCellHeader/TableCellHeader.stories.tsx new file mode 100644 index 000000000..f2d609822 --- /dev/null +++ b/src/components/TableCellHeader/TableCellHeader.stories.tsx @@ -0,0 +1,83 @@ +import Card from "@material-ui/core/Card"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableHead from "@material-ui/core/TableHead"; +import TableRow from "@material-ui/core/TableRow"; +import { storiesOf } from "@storybook/react"; +import React from "react"; + +import Decorator from "../../storybook/Decorator"; +import TableCellHeader, { + TableCellHeaderArrowDirection +} from "./TableCellHeader"; + +type Field = "name" | "type"; +interface StoryProps { + direction: TableCellHeaderArrowDirection; + field?: Field; + onHeaderClick?: (field: Field) => void; +} + +const Story: React.FC = ({ + direction, + field = "name", + onHeaderClick = () => undefined +}) => ( + + + + + onHeaderClick("name")} + > + Name + + onHeaderClick("type")} + > + Type + + + + + + Apple Juice + Juice + + +
+
+); +const InteractiveStory: React.FC = () => { + const [direction, setDirection] = React.useState< + TableCellHeaderArrowDirection + >("asc"); + const [field, setField] = React.useState("name"); + + const handleHeaderClick = (selectedField: Field) => { + if (field === selectedField) { + setDirection(direction === "asc" ? "desc" : "asc"); + } else { + setField(selectedField); + setDirection("asc"); + } + }; + + return ( + + ); +}; + +storiesOf("Generics / Table header", module) + .addDecorator(Decorator) + .add("ascending", () => ) + .add("descending", () => ) + .add("interactive", () => ); diff --git a/src/components/TableCellHeader/TableCellHeader.tsx b/src/components/TableCellHeader/TableCellHeader.tsx new file mode 100644 index 000000000..4da908fae --- /dev/null +++ b/src/components/TableCellHeader/TableCellHeader.tsx @@ -0,0 +1,97 @@ +import { Theme } from "@material-ui/core/styles"; +import TableCell, { TableCellProps } from "@material-ui/core/TableCell"; +import makeStyles from "@material-ui/styles/makeStyles"; +import classNames from "classnames"; +import React from "react"; + +import ArrowSort from "../../icons/ArrowSort"; + +const useStyles = makeStyles((theme: Theme) => ({ + arrow: { + transition: theme.transitions.duration.short + "ms" + }, + arrowLeft: { + marginLeft: -24 + }, + arrowUp: { + transform: "rotate(180deg)" + }, + label: { + alignSelf: "center", + display: "inline-block" + }, + labelContainer: { + "&:hover": { + color: theme.palette.text.primary + }, + display: "flex", + height: 24 + }, + labelContainerActive: { + color: theme.palette.text.primary + }, + labelContainerCenter: { + justifyContent: "center" + }, + labelContainerRight: { + justifyContent: "flex-end" + }, + root: { + cursor: "pointer" + } +})); + +export type TableCellHeaderArrowDirection = "asc" | "desc"; +export type TableCellHeaderArrowPosition = "left" | "right"; +export interface TableCellHeaderProps extends TableCellProps { + arrowPosition?: TableCellHeaderArrowPosition; + direction?: TableCellHeaderArrowDirection; + textAlign?: "left" | "center" | "right"; +} + +const TableCellHeader: React.FC = props => { + const classes = useStyles(props); + const { + arrowPosition, + children, + className, + direction, + textAlign, + ...rest + } = props; + + return ( + +
+ {!!direction && arrowPosition === "left" && ( + + )} +
{children}
+ {!!direction && arrowPosition === "right" && ( + + )} +
+
+ ); +}; + +TableCellHeader.displayName = "TableCellHeader"; +TableCellHeader.defaultProps = { + arrowPosition: "left", + textAlign: "left" +}; +export default TableCellHeader; diff --git a/src/components/TableCellHeader/index.ts b/src/components/TableCellHeader/index.ts new file mode 100644 index 000000000..cfd465863 --- /dev/null +++ b/src/components/TableCellHeader/index.ts @@ -0,0 +1,2 @@ +export { default } from "./TableCellHeader"; +export * from "./TableCellHeader"; diff --git a/src/fixtures.ts b/src/fixtures.ts index e0c4676db..d76e1d667 100644 --- a/src/fixtures.ts +++ b/src/fixtures.ts @@ -5,6 +5,7 @@ import { ListActions, PageListProps, SearchPageProps, + SortPage, TabPageProps } from "./types"; @@ -141,3 +142,10 @@ export const fetchMoreProps: FetchMoreProps = { loading: false, onFetchMore: () => undefined }; + +export const sortPageProps: SortPage = { + onSort: () => undefined, + sort: { + asc: true + } +}; diff --git a/src/icons/Navigation.tsx b/src/icons/Navigation.tsx index c0eb5e4c2..37056dad9 100644 --- a/src/icons/Navigation.tsx +++ b/src/icons/Navigation.tsx @@ -4,8 +4,8 @@ import React from "react"; export const Navigation = createSvgIcon( <> diff --git a/src/icons/Orders.tsx b/src/icons/Orders.tsx index 7a655a2e9..40cba08f6 100644 --- a/src/icons/Orders.tsx +++ b/src/icons/Orders.tsx @@ -4,8 +4,8 @@ import React from "react"; export const Orders = createSvgIcon( <> diff --git a/src/icons/Pages.tsx b/src/icons/Pages.tsx index 1eb46ada9..6db2775af 100644 --- a/src/icons/Pages.tsx +++ b/src/icons/Pages.tsx @@ -4,8 +4,8 @@ import React from "react"; export const Pages = createSvgIcon( <> diff --git a/src/icons/ProductTypes.tsx b/src/icons/ProductTypes.tsx index 2b218491d..54fdbda6a 100644 --- a/src/icons/ProductTypes.tsx +++ b/src/icons/ProductTypes.tsx @@ -4,8 +4,8 @@ import React from "react"; export const ProductTypes = createSvgIcon( <> diff --git a/src/icons/Sales.tsx b/src/icons/Sales.tsx index b3276b05a..7b9525679 100644 --- a/src/icons/Sales.tsx +++ b/src/icons/Sales.tsx @@ -4,8 +4,8 @@ import React from "react"; export const Sales = createSvgIcon( <> diff --git a/src/icons/ShippingMethods.tsx b/src/icons/ShippingMethods.tsx index eeb1db2f1..4ee47bf8f 100644 --- a/src/icons/ShippingMethods.tsx +++ b/src/icons/ShippingMethods.tsx @@ -4,8 +4,8 @@ import React from "react"; export const ShippingMethods = createSvgIcon( <> diff --git a/src/icons/SiteSettings.tsx b/src/icons/SiteSettings.tsx index f8590aea4..53cc0388a 100644 --- a/src/icons/SiteSettings.tsx +++ b/src/icons/SiteSettings.tsx @@ -4,8 +4,8 @@ import React from "react"; export const SiteSettings = createSvgIcon( <> diff --git a/src/icons/StaffMembers.tsx b/src/icons/StaffMembers.tsx index 99a1de1f7..2b1e0a05b 100644 --- a/src/icons/StaffMembers.tsx +++ b/src/icons/StaffMembers.tsx @@ -4,8 +4,8 @@ import React from "react"; export const StaffMembers = createSvgIcon( <> diff --git a/src/icons/Taxes.tsx b/src/icons/Taxes.tsx index 970d8d349..7e3ba83cd 100644 --- a/src/icons/Taxes.tsx +++ b/src/icons/Taxes.tsx @@ -4,8 +4,8 @@ import React from "react"; export const Taxes = createSvgIcon( <> diff --git a/src/misc.ts b/src/misc.ts index 517e1a00e..74f410669 100644 --- a/src/misc.ts +++ b/src/misc.ts @@ -478,3 +478,7 @@ export function findInEnum( throw new Error(`Key ${needle} not found in enum`); } + +export function parseBoolean(a: string): boolean { + return a === "true"; +} diff --git a/src/products/components/ProductList/ProductList.tsx b/src/products/components/ProductList/ProductList.tsx index 88508d18a..a69c7b877 100644 --- a/src/products/components/ProductList/ProductList.tsx +++ b/src/products/components/ProductList/ProductList.tsx @@ -20,6 +20,7 @@ import StatusLabel from "@saleor/components/StatusLabel"; import TableCellAvatar, { AVATAR_MARGIN } from "@saleor/components/TableCellAvatar"; +import TableCellHeader from "@saleor/components/TableCellHeader"; import TableHead from "@saleor/components/TableHead"; import TablePagination from "@saleor/components/TablePagination"; import { ProductListColumns } from "@saleor/config"; @@ -30,8 +31,12 @@ import { } from "@saleor/products/components/ProductListPage/utils"; import { AvailableInGridAttributes_grid_edges_node } from "@saleor/products/types/AvailableInGridAttributes"; import { ProductList_products_edges_node } from "@saleor/products/types/ProductList"; -import { ListActions, ListProps } from "@saleor/types"; -import TDisplayColumn from "@saleor/utils/columns/DisplayColumn"; +import { ProductListUrlSortField } from "@saleor/products/urls"; +import { ListActions, ListProps, SortPage } from "@saleor/types"; +import TDisplayColumn, { + DisplayColumnProps +} from "@saleor/utils/columns/DisplayColumn"; +import { getArrowDirection } from "@saleor/utils/sort"; const styles = (theme: Theme) => createStyles({ @@ -87,9 +92,14 @@ const styles = (theme: Theme) => } }); +const DisplayColumn = TDisplayColumn as React.FunctionComponent< + DisplayColumnProps +>; + interface ProductListProps extends ListProps, ListActions, + SortPage, WithStyles { gridAttributes: AvailableInGridAttributes_grid_edges_node[]; products: ProductList_products_edges_node[]; @@ -105,19 +115,18 @@ export const ProductList = withStyles(styles, { name: "ProductList" })( pageInfo, products, selected, + sort, toggle, toggleAll, toolbar, onNextPage, onPreviousPage, onUpdateListSettings, - onRowClick + onRowClick, + onSort }: ProductListProps) => { const intl = useIntl(); - const DisplayColumn: React.FC<{ column: ProductListColumns }> = props => ( - - ); const gridAttributesFromSettings = settings.columns.filter( isAttributeColumnValue ); @@ -129,16 +138,22 @@ export const ProductList = withStyles(styles, { name: "ProductList" })( - + - + {gridAttributesFromSettings.map(gridAttribute => ( ))} - + @@ -150,30 +165,59 @@ export const ProductList = withStyles(styles, { name: "ProductList" })( toggleAll={toggleAll} toolbar={toolbar} > - 4 })} + direction={ + sort.sort === ProductListUrlSortField.name + ? getArrowDirection(sort.asc) + : undefined + } + onClick={() => onSort(ProductListUrlSortField.name)} > - - - + + + onSort(ProductListUrlSortField.productType)} + > - + - - + + onSort(ProductListUrlSortField.status)} + > - + {gridAttributesFromSettings.map(gridAttributeFromSettings => ( ))} - - + + onSort(ProductListUrlSortField.price)} + > - + @@ -246,7 +299,10 @@ export const ProductList = withStyles(styles, { name: "ProductList" })( > {maybe(() => product.name, )} - + {product && product.productType ? ( product.productType.name @@ -255,7 +311,10 @@ export const ProductList = withStyles(styles, { name: "ProductList" })( )} - + {product && maybe(() => product.isAvailable !== undefined) ? ( @@ -299,7 +358,10 @@ export const ProductList = withStyles(styles, { name: "ProductList" })( }, )} ))} - + {maybe(() => product.basePrice) && maybe(() => product.basePrice.amount) !== undefined && diff --git a/src/products/components/ProductListPage/ProductListPage.tsx b/src/products/components/ProductListPage/ProductListPage.tsx index 7f89ff158..61ba40a77 100644 --- a/src/products/components/ProductListPage/ProductListPage.tsx +++ b/src/products/components/ProductListPage/ProductListPage.tsx @@ -1,7 +1,6 @@ import Button from "@material-ui/core/Button"; import Card from "@material-ui/core/Card"; import { Theme } from "@material-ui/core/styles"; - import makeStyles from "@material-ui/styles/makeStyles"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; @@ -22,8 +21,10 @@ import { FetchMoreProps, FilterPageProps, ListActions, - PageListProps + PageListProps, + SortPage } from "@saleor/types"; +import { ProductListUrlSortField } from "../../urls"; import ProductList from "../ProductList"; import ProductListFilter, { ProductFilterKeys } from "../ProductListFilter"; @@ -31,7 +32,8 @@ export interface ProductListPageProps extends PageListProps, ListActions, FilterPageProps, - FetchMoreProps { + FetchMoreProps, + SortPage { availableInGridAttributes: AvailableInGridAttributes_availableInGrid_edges_node[]; currencySymbol: string; gridAttributes: AvailableInGridAttributes_grid_edges_node[]; diff --git a/src/products/index.tsx b/src/products/index.tsx index 0a8a1e767..ca16a2e59 100644 --- a/src/products/index.tsx +++ b/src/products/index.tsx @@ -4,6 +4,7 @@ import { useIntl } from "react-intl"; import { Route, RouteComponentProps, Switch } from "react-router-dom"; import { sectionNames } from "@saleor/intl"; +import { findInEnum, parseBoolean } from "@saleor/misc"; import { WindowTitle } from "../components/WindowTitle"; import { productAddPath, @@ -11,6 +12,7 @@ import { ProductImageUrlQueryParams, productListPath, ProductListUrlQueryParams, + ProductListUrlSortField, productPath, ProductUrlQueryParams, productVariantAddPath, @@ -28,7 +30,13 @@ const ProductList: React.StatelessComponent> = ({ location }) => { const qs = parseQs(location.search.substr(1)); - const params: ProductListUrlQueryParams = qs; + const params: ProductListUrlQueryParams = { + ...qs, + asc: parseBoolean(qs.asc), + sort: qs.sort + ? findInEnum(qs.sort, ProductListUrlSortField) + : ProductListUrlSortField.name + }; return ; }; diff --git a/src/products/queries.ts b/src/products/queries.ts index 5d5086ec4..65c5948d7 100644 --- a/src/products/queries.ts +++ b/src/products/queries.ts @@ -218,6 +218,7 @@ const productListQuery = gql` $last: Int $before: String $filter: ProductFilterInput + $sort: ProductOrder ) { products( before: $before @@ -225,6 +226,7 @@ const productListQuery = gql` first: $first last: $last filter: $filter + sortBy: $sort ) { edges { node { diff --git a/src/products/types/ProductList.ts b/src/products/types/ProductList.ts index ae5de0235..ab392aa3e 100644 --- a/src/products/types/ProductList.ts +++ b/src/products/types/ProductList.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { ProductFilterInput } from "./../../types/globalTypes"; +import { ProductFilterInput, ProductOrder } from "./../../types/globalTypes"; // ==================================================== // GraphQL query operation: ProductList @@ -82,4 +82,5 @@ export interface ProductListVariables { last?: number | null; before?: string | null; filter?: ProductFilterInput | null; + sort?: ProductOrder | null; } diff --git a/src/products/urls.ts b/src/products/urls.ts index 7c0348d3f..7a408857d 100644 --- a/src/products/urls.ts +++ b/src/products/urls.ts @@ -7,6 +7,7 @@ import { Dialog, Filters, Pagination, + Sort, TabActionDialog } from "../types"; @@ -29,9 +30,17 @@ export enum ProductListUrlFiltersEnum { query = "query" } export type ProductListUrlFilters = Filters; +export enum ProductListUrlSortField { + name = "name", + productType = "productType", + status = "status", + price = "price" +} +export type ProductListUrlSort = Sort; export type ProductListUrlQueryParams = BulkAction & Dialog & ProductListUrlFilters & + ProductListUrlSort & Pagination & ActiveTab; export const productListUrl = (params?: ProductListUrlQueryParams): string => diff --git a/src/products/views/ProductList/ProductList.tsx b/src/products/views/ProductList/ProductList.tsx index a15798fa7..366834bfc 100644 --- a/src/products/views/ProductList/ProductList.tsx +++ b/src/products/views/ProductList/ProductList.tsx @@ -22,7 +22,9 @@ import usePaginator, { import useShop from "@saleor/hooks/useShop"; import { commonMessages } from "@saleor/intl"; import { getMutationState, maybe } from "@saleor/misc"; +import { ProductListVariables } from "@saleor/products/types/ProductList"; import { ListViews } from "@saleor/types"; +import { getSortUrlVariables } from "@saleor/utils/sort"; import ProductListPage from "../../components/ProductListPage"; import { TypedProductBulkDeleteMutation, @@ -52,6 +54,7 @@ import { getFilterVariables, saveFilterTab } from "./filters"; +import { getSortQueryVariables } from "./sort"; interface ProductListProps { params: ProductListUrlQueryParams; @@ -152,10 +155,13 @@ export const ProductList: React.StatelessComponent = ({ const paginationState = createPaginationState(settings.rowNumber, params); const currencySymbol = maybe(() => shop.defaultCurrency, "USD"); - const queryVariables = React.useMemo( + const filter = getFilterVariables(params); + const sort = getSortQueryVariables(params); + const queryVariables = React.useMemo( () => ({ ...paginationState, - filter: getFilterVariables(params) + filter, + sort }), [params, settings.rowNumber] ); @@ -224,6 +230,18 @@ export const ProductList: React.StatelessComponent = ({ return ( <> + navigate( + productListUrl({ + ...params, + ...getSortUrlVariables(field, params) + }) + ) + } availableInGridAttributes={maybe( () => attributes.data.availableInGrid.edges.map( diff --git a/src/products/views/ProductList/sort.ts b/src/products/views/ProductList/sort.ts new file mode 100644 index 000000000..e5cbbe905 --- /dev/null +++ b/src/products/views/ProductList/sort.ts @@ -0,0 +1,30 @@ +import { + ProductListUrlQueryParams, + ProductListUrlSortField +} from "@saleor/products/urls"; +import { ProductOrder, ProductOrderField } from "@saleor/types/globalTypes"; +import { getOrderDirection } from "@saleor/utils/sort"; + +export function getSortQueryField( + sort: ProductListUrlSortField +): ProductOrderField { + switch (sort) { + case ProductListUrlSortField.name: + return ProductOrderField.NAME; + case ProductListUrlSortField.price: + return ProductOrderField.PRICE; + case ProductListUrlSortField.productType: + return ProductOrderField.TYPE; + case ProductListUrlSortField.status: + return ProductOrderField.PUBLISHED; + } +} + +export function getSortQueryVariables( + params: ProductListUrlQueryParams +): ProductOrder { + return { + direction: getOrderDirection(params.asc), + field: getSortQueryField(params.sort) + }; +} diff --git a/src/storybook/__snapshots__/Stories.test.ts.snap b/src/storybook/__snapshots__/Stories.test.ts.snap index e25d6d037..ff25993c7 100644 --- a/src/storybook/__snapshots__/Stories.test.ts.snap +++ b/src/storybook/__snapshots__/Stories.test.ts.snap @@ -4591,6 +4591,273 @@ exports[`Storyshots Generics / StatusLabel when success 1`] = ` `; +exports[`Storyshots Generics / Table header ascending 1`] = ` +
+
+ + + + + + + + + + + + + +
+
+
+ Name +
+ +
+
+
+
+ Type +
+
+
+ Apple Juice + + Juice +
+
+
+`; + +exports[`Storyshots Generics / Table header descending 1`] = ` +
+
+ + + + + + + + + + + + + +
+
+
+ Name +
+ +
+
+
+
+ Type +
+
+
+ Apple Juice + + Juice +
+
+
+`; + +exports[`Storyshots Generics / Table header interactive 1`] = ` +
+
+ + + + + + + + + + + + + +
+
+
+ Name +
+ +
+
+
+
+ Type +
+
+
+ Apple Juice + + Juice +
+
+
+`; + exports[`Storyshots Generics / TablePagination both previous and next pages are available 1`] = `
- - Name - +
+ + Name + +
+ +
- Type +
+
+ Type +
+
- Published +
+
+ Published +
+
- Price +
+
+ Price +
+
@@ -95157,32 +95475,83 @@ exports[`Storyshots Views / Products / Product list loading 1`] = ` - - Name - +
+ + Name + +
+ + - Type +
+
+ Type +
+
- Published +
+
+ Published +
+
- Price +
+
+ Price +
+
@@ -95618,32 +95987,83 @@ exports[`Storyshots Views / Products / Product list no data 1`] = ` class="MuiTableRow-root-id MuiTableRow-head-id" > - - Name - +
+ + Name + +
+ + - Type +
+
+ Type +
+
- Published +
+
+ Published +
+
- Price +
+
+ Price +
+
@@ -96475,32 +96895,83 @@ exports[`Storyshots Views / Products / Product list with custom filters 1`] = ` - - Name - +
+ + Name + +
+ + - Type +
+
+ Type +
+
- Published +
+
+ Published +
+
- Price +
+
+ Price +
+
diff --git a/src/storybook/stories/products/ProductListPage.tsx b/src/storybook/stories/products/ProductListPage.tsx index d5f792e97..f9203dac4 100644 --- a/src/storybook/stories/products/ProductListPage.tsx +++ b/src/storybook/stories/products/ProductListPage.tsx @@ -4,6 +4,7 @@ import React from "react"; import placeholderImage from "@assets/images/placeholder255x255.png"; import { defaultListSettings } from "@saleor/config"; import { products as productListFixture } from "@saleor/products/fixtures"; +import { ProductListUrlSortField } from "@saleor/products/urls"; import { attributes } from "@saleor/productTypes/fixtures"; import { ListViews } from "@saleor/types"; import { @@ -11,7 +12,8 @@ import { filterPageProps, filters, listActionsProps, - pageListProps + pageListProps, + sortPageProps } from "../../../fixtures"; import ProductListPage, { ProductListPageProps @@ -25,6 +27,13 @@ const props: ProductListPageProps = { ...pageListProps.default, ...filterPageProps, ...fetchMoreProps, + ...{ + ...sortPageProps, + sort: { + ...sortPageProps.sort, + sort: ProductListUrlSortField.name + } + }, availableInGridAttributes: attributes, defaultSettings: defaultListSettings[ListViews.PRODUCT_LIST], gridAttributes: attributes, diff --git a/src/types.ts b/src/types.ts index f47628fa7..1ff50fea8 100644 --- a/src/types.ts +++ b/src/types.ts @@ -47,6 +47,11 @@ export interface ListProps { ) => void; onListSettingsReset?: () => void; } + +export interface SortPage { + sort: Sort; + onSort: (field: TSortKey) => void; +} export interface ListActionsWithoutToolbar { toggle: (id: string) => void; toggleAll: (items: React.ReactNodeArray, selected: number) => void; @@ -131,6 +136,10 @@ export type FiltersWithMultipleValues = Partial< export type SingleAction = Partial<{ id: string; }>; +export type Sort = Partial<{ + asc: boolean; + sort: TSort; +}>; export type BulkAction = Partial<{ ids: string[]; }>; diff --git a/src/types/globalTypes.ts b/src/types/globalTypes.ts index 420441a4f..e4d1e84ac 100644 --- a/src/types/globalTypes.ts +++ b/src/types/globalTypes.ts @@ -112,6 +112,11 @@ export enum OrderAction { VOID = "VOID", } +export enum OrderDirection { + ASC = "ASC", + DESC = "DESC", +} + export enum OrderEventsEmailsEnum { DIGITAL_LINKS = "DIGITAL_LINKS", FULFILLMENT_CONFIRMATION = "FULFILLMENT_CONFIRMATION", @@ -187,6 +192,15 @@ export enum PermissionEnum { MANAGE_USERS = "MANAGE_USERS", } +export enum ProductOrderField { + DATE = "DATE", + MINIMAL_PRICE = "MINIMAL_PRICE", + NAME = "NAME", + PRICE = "PRICE", + PUBLISHED = "PUBLISHED", + TYPE = "TYPE", +} + export enum ProductTypeConfigurable { CONFIGURABLE = "CONFIGURABLE", SIMPLE = "SIMPLE", @@ -574,6 +588,11 @@ export interface ProductFilterInput { minimalPrice?: PriceRangeInput | null; } +export interface ProductOrder { + field: ProductOrderField; + direction: OrderDirection; +} + export interface ProductTypeFilterInput { search?: string | null; configurable?: ProductTypeConfigurable | null; diff --git a/src/utils/columns/DisplayColumn.tsx b/src/utils/columns/DisplayColumn.tsx index 72dd32898..af48b0f93 100644 --- a/src/utils/columns/DisplayColumn.tsx +++ b/src/utils/columns/DisplayColumn.tsx @@ -12,12 +12,12 @@ const DisplayColumn: React.FC = ({ children, column }) => { - const displayColumn = React.useCallback( - (column: string) => isSelected(column, displayColumns, (a, b) => a === b), - [displayColumns] + const display = React.useMemo( + () => isSelected(column, displayColumns, (a, b) => a === b), + [column, displayColumns] ); - return <>{displayColumn(column) && children}; + return <>{display && children}; }; DisplayColumn.displayName = "DisplayColumn"; diff --git a/src/utils/sort.ts b/src/utils/sort.ts new file mode 100644 index 000000000..f5eabbd33 --- /dev/null +++ b/src/utils/sort.ts @@ -0,0 +1,28 @@ +import { TableCellHeaderArrowDirection } from "../components/TableCellHeader"; +import { Sort } from "../types"; +import { OrderDirection } from "../types/globalTypes"; + +export function getSortUrlVariables( + field: TSortKey, + params: Sort +): Sort { + if (field === params.sort) { + return { + asc: !params.asc, + sort: field + }; + } + + return { + asc: true, + sort: field + }; +} + +export function getOrderDirection(asc: boolean): OrderDirection { + return asc ? OrderDirection.ASC : OrderDirection.DESC; +} + +export function getArrowDirection(asc: boolean): TableCellHeaderArrowDirection { + return asc ? "asc" : "desc"; +}