Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/curly-penguins-vanish.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"saleor-dashboard": patch
---

Product types list page uses now new filters. New filters are under feature flag and are enabled by default.
46 changes: 30 additions & 16 deletions .featureFlags/generated.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,36 @@
// @ts-nocheck

import W24585 from "./images/collection-filters.jpg"
import L16463 from "./images/customers-filters.png"
import L94878 from "./images/discounts-list.png"
import E09437 from "./images/draft-orders-filters.png"
import E78766 from "./images/gift-cards-filters.png"
import X68306 from "./images/improved_refunds.png"
import E85468 from "./images/page-filters.png"
import B37301 from "./images/vouchers-filters.png"
import B52941 from "./images/collection-filters.jpg"
import N65883 from "./images/customers-filters.png"
import M49541 from "./images/discounts-list.png"
import J34031 from "./images/draft-orders-filters.png"
import A69414 from "./images/gift-cards-filters.png"
import Y18806 from "./images/improved_refunds.png"
import V51684 from "./images/page-filters.png"
import D27626 from "./images/product-types-filters.png"
import M01387 from "./images/vouchers-filters.png"

const collection_filters = () => (<><p><img src={W24585} alt="new filters"/>
const collection_filters = () => (<><p><img src={B52941} alt="new filters"/>
Experience the new look and enhanced abilities of new filtering mechanism.
Easily combine any criteria you want, and quickly browse their values.</p>
</>)
const customers_filters = () => (<><p><img src={L16463} alt="new filters"/>
const customers_filters = () => (<><p><img src={N65883} alt="new filters"/>
Experience the new look and enhanced abilities of new fitering mechanism.
Easily combine any criteria you want, and quickly browse their values.</p>
</>)
const discounts_rules = () => (<><p><img src={L94878} alt="Discount rules"/></p>
const discounts_rules = () => (<><p><img src={M49541} alt="Discount rules"/></p>
<p>Apply the new discounts rules to narrow your promotions audience.
Set up conditions and channels that must be fulfilled to apply defined reward.</p>
</>)
const draft_orders_filters = () => (<><p><img src={E09437} alt="new filters"/>
const draft_orders_filters = () => (<><p><img src={J34031} alt="new filters"/>
Experience the new look and enhanced abilities of new fitering mechanism.
Easily combine any criteria you want, and quickly browse their values.</p>
</>)
const gift_cards_filters = () => (<><p><img src={E78766} alt="new filters"/>
const gift_cards_filters = () => (<><p><img src={A69414} alt="new filters"/>
Experience the new look and enhanced abilities of new fitering mechanism.
Easily combine any criteria you want, and quickly browse their values.</p>
</>)
const improved_refunds = () => (<><p><img src={X68306} alt="Improved refunds"/></p>
const improved_refunds = () => (<><p><img src={Y18806} alt="Improved refunds"/></p>
<h3 id="enable-the-enhanced-refund-feature-to-streamline-your-refund-process">Enable the enhanced refund feature to streamline your refund process:</h3>
<ul>
<li><p>• Choose between automatic calculations based on selected items or enter refund amounts directly for overcharges and custom adjustments.</p>
Expand All @@ -39,11 +40,15 @@ const improved_refunds = () => (<><p><img src={X68306} alt="Improved refunds"/><
</ul>

</>)
const pages_filters = () => (<><p><img src={E85468} alt="new filters"/>
const pages_filters = () => (<><p><img src={V51684} alt="new filters"/>
Experience the new look and enhanced abilities of new fitering mechanism.
Easily combine any criteria you want, and quickly browse their values.</p>
</>)
const vouchers_filters = () => (<><p><img src={B37301} alt="new filters"/>
const product_types_filters = () => (<><p><img src={D27626} alt="new filters"/>
Experience the new look and enhanced abilities of new fitering mechanism.
Easily combine any criteria you want, and quickly browse their values.</p>
</>)
const vouchers_filters = () => (<><p><img src={M01387} alt="new filters"/>
Experience the new look and enhanced abilities of new fitering mechanism.
Easily combine any criteria you want, and quickly browse their values.</p>
</>)
Expand Down Expand Up @@ -111,6 +116,15 @@ export const AVAILABLE_FLAGS = [{
enabled: true,
payload: "default",
}
},{
name: "product_types_filters",
displayName: "Product types filtering",
component: product_types_filters,
visible: true,
content: {
enabled: true,
payload: "default",
}
},{
name: "vouchers_filters",
displayName: "Vouchers filtering",
Expand Down
Binary file added .featureFlags/images/product-types-filters.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions .featureFlags/product_types_filters.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
name: product_types_filters
displayName: Product types filtering
enabled: true
payload: "default"
visible: true
---

![new filters](./images/product-types-filters.png)
Experience the new look and enhanced abilities of new fitering mechanism.
Easily combine any criteria you want, and quickly browse their values.
8 changes: 8 additions & 0 deletions locale/defaultMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -3742,6 +3742,10 @@
"M59JhX": {
"string": "Manual"
},
"M61TN/": {
"context": "product type shippable",
"string": "Shippable"
},
"M6mWHL": {
"context": "tooltip helper text",
"string": "You do not have permissions to create a manual refund."
Expand Down Expand Up @@ -4781,6 +4785,10 @@
"SceSNp": {
"string": "Remove following permissions:"
},
"SgFE10": {
"context": "product type digital",
"string": "Digital"
},
"Sjd7wm": {
"context": "product filter label",
"string": "Product"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { UrlEntry, UrlToken } from "../../../ValueProvider/UrlToken";
import { InitialProductTypesStateResponse } from "./InitialProductTypesState";

describe("ConditionalFilter / API / Page / InitialProductTypesState", () => {
it("should filter by product type", () => {
// Arrange
const initialPageState = InitialProductTypesStateResponse.empty();

initialPageState.typeOfProduct = [
{
label: "Type 1",
value: "type-1",
slug: "type-1",
},
{
label: "Type 2",
value: "type-2",
slug: "type-2",
},
];

const token = UrlToken.fromUrlEntry(new UrlEntry("s0.typeOfProduct", "type-2"));
const expectedOutput = [
{
label: "Type 2",
value: "type-2",
slug: "type-2",
},
];

// Act
const result = initialPageState.filterByUrlToken(token);

// Assert
expect(result).toEqual(expectedOutput);
});

it("should filter by configurable", () => {
// Arrange
const initialPageState = InitialProductTypesStateResponse.empty();

initialPageState.configurable = [
{
label: "Yes",
value: "CONFIGURABLE",
slug: "yes",
},
{
label: "No",
value: "SIMPLE",
slug: "no",
},
];

const token = UrlToken.fromUrlEntry(new UrlEntry("s0.configurable", "no"));
const expectedOutput = [
{
label: "No",
value: "SIMPLE",
slug: "no",
},
];

// Act
const result = initialPageState.filterByUrlToken(token);

// Assert
expect(result).toEqual(expectedOutput);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { ItemOption } from "@dashboard/components/ConditionalFilter/FilterElement/ConditionValue";
import { UrlToken } from "@dashboard/components/ConditionalFilter/ValueProvider/UrlToken";

export interface InitialProductTypesState {
typeOfProduct: ItemOption[];
configurable: ItemOption[];
}

export class InitialProductTypesStateResponse implements InitialProductTypesState {
constructor(
public typeOfProduct: ItemOption[] = [],
public configurable: ItemOption[] = [],
) {}

public static empty() {
return new InitialProductTypesStateResponse();
}

public filterByUrlToken(token: UrlToken) {
const entry = this.getEntryByName(token.name);

if (!token.isLoadable()) {
return [token.value] as string[];

Check warning on line 23 in src/components/ConditionalFilter/API/initialState/productTypes/InitialProductTypesState.ts

View check run for this annotation

Codecov / codecov/patch

src/components/ConditionalFilter/API/initialState/productTypes/InitialProductTypesState.ts#L23

Added line #L23 was not covered by tests
}

return (entry as ItemOption[]).filter(({ slug }) => slug && token.value.includes(slug));
}

private getEntryByName(name: string): ItemOption[] {
switch (name) {
case "typeOfProduct":
return this.typeOfProduct;
case "configurable":
return this.configurable;
default:
return [];

Check warning on line 36 in src/components/ConditionalFilter/API/initialState/productTypes/InitialProductTypesState.ts

View check run for this annotation

Codecov / codecov/patch

src/components/ConditionalFilter/API/initialState/productTypes/InitialProductTypesState.ts#L35-L36

Added lines #L35 - L36 were not covered by tests
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { InitialProductTypesStateResponse } from "@dashboard/components/ConditionalFilter/API/initialState/productTypes/InitialProductTypesState";
import { ProductTypeConfigurable, ProductTypeEnum } from "@dashboard/graphql";
import { useState } from "react";
import { useIntl } from "react-intl";

import { ProductTypesFetchingParams } from "../../../ValueProvider/TokenArray/fetchingParams";
import { BooleanValuesHandler, EnumValuesHandler } from "../../Handler";

export interface InitialProductTypesAPIState {
data: InitialProductTypesStateResponse;
loading: boolean;
fetchQueries: (params: ProductTypesFetchingParams) => Promise<void>;
}

export const useInitialProductTypesState = (): InitialProductTypesAPIState => {
const intl = useIntl();
const [data, setData] = useState<InitialProductTypesStateResponse>(

Check warning on line 17 in src/components/ConditionalFilter/API/initialState/productTypes/useInitialProdutTypesState.ts

View check run for this annotation

Codecov / codecov/patch

src/components/ConditionalFilter/API/initialState/productTypes/useInitialProdutTypesState.ts#L16-L17

Added lines #L16 - L17 were not covered by tests
InitialProductTypesStateResponse.empty(),
);
const [loading, setLoading] = useState(true);

Check warning on line 20 in src/components/ConditionalFilter/API/initialState/productTypes/useInitialProdutTypesState.ts

View check run for this annotation

Codecov / codecov/patch

src/components/ConditionalFilter/API/initialState/productTypes/useInitialProdutTypesState.ts#L20

Added line #L20 was not covered by tests

const fetchQueries = async ({ typeOfProduct }: ProductTypesFetchingParams) => {
const typeOfProductInit = new EnumValuesHandler(

Check warning on line 23 in src/components/ConditionalFilter/API/initialState/productTypes/useInitialProdutTypesState.ts

View check run for this annotation

Codecov / codecov/patch

src/components/ConditionalFilter/API/initialState/productTypes/useInitialProdutTypesState.ts#L22-L23

Added lines #L22 - L23 were not covered by tests
ProductTypeEnum,
"typeOfProduct",
intl,
typeOfProduct,
);

const configurableInit = new BooleanValuesHandler([

Check warning on line 30 in src/components/ConditionalFilter/API/initialState/productTypes/useInitialProdutTypesState.ts

View check run for this annotation

Codecov / codecov/patch

src/components/ConditionalFilter/API/initialState/productTypes/useInitialProdutTypesState.ts#L30

Added line #L30 was not covered by tests
{
label: "Yes",
value: ProductTypeConfigurable.CONFIGURABLE,
type: "configurable",
slug: "true",
},
{
label: "No",
value: ProductTypeConfigurable.SIMPLE,
type: "configurable",
slug: "false",
},
]);

const initialState = {

Check warning on line 45 in src/components/ConditionalFilter/API/initialState/productTypes/useInitialProdutTypesState.ts

View check run for this annotation

Codecov / codecov/patch

src/components/ConditionalFilter/API/initialState/productTypes/useInitialProdutTypesState.ts#L45

Added line #L45 was not covered by tests
typeOfProduct: await typeOfProductInit.fetch(),
configurable: await configurableInit.fetch(),
};

setData(

Check warning on line 50 in src/components/ConditionalFilter/API/initialState/productTypes/useInitialProdutTypesState.ts

View check run for this annotation

Codecov / codecov/patch

src/components/ConditionalFilter/API/initialState/productTypes/useInitialProdutTypesState.ts#L50

Added line #L50 was not covered by tests
new InitialProductTypesStateResponse(initialState.typeOfProduct, initialState.configurable),
);
setLoading(false);

Check warning on line 53 in src/components/ConditionalFilter/API/initialState/productTypes/useInitialProdutTypesState.ts

View check run for this annotation

Codecov / codecov/patch

src/components/ConditionalFilter/API/initialState/productTypes/useInitialProdutTypesState.ts#L53

Added line #L53 was not covered by tests
};

return {

Check warning on line 56 in src/components/ConditionalFilter/API/initialState/productTypes/useInitialProdutTypesState.ts

View check run for this annotation

Codecov / codecov/patch

src/components/ConditionalFilter/API/initialState/productTypes/useInitialProdutTypesState.ts#L56

Added line #L56 was not covered by tests
data,
loading,
fetchQueries,
};
};
15 changes: 15 additions & 0 deletions src/components/ConditionalFilter/API/intl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
OrderChargeStatusEnum,
OrderStatusFilter,
PaymentChargeStatusEnum,
ProductTypeEnum,
VoucherDiscountType,
} from "@dashboard/graphql";
import { transformOrderStatus, transformPaymentStatus } from "@dashboard/misc";
Expand All @@ -16,6 +17,7 @@
chargeStatusMessages,
collectionFilterMessages,
discountTypeMessages,
productTypeMessages,
voucherStatusMessages,
} from "./messages";

Expand Down Expand Up @@ -94,6 +96,17 @@
}
};

export const getProductTypeLabel = (type: ProductTypeEnum, intl: IntlShape) => {
switch (type) {
case ProductTypeEnum.DIGITAL:
return intl.formatMessage(productTypeMessages.digital);
case ProductTypeEnum.SHIPPABLE:
return intl.formatMessage(productTypeMessages.shippable);
default:
return type;

Check warning on line 106 in src/components/ConditionalFilter/API/intl.ts

View check run for this annotation

Codecov / codecov/patch

src/components/ConditionalFilter/API/intl.ts#L101-L106

Added lines #L101 - L106 were not covered by tests
}
};

export const getLocalizedLabel = (rowType: LeftOperand["type"], value: string, intl: IntlShape) => {
switch (rowType) {
case "paymentStatus":
Expand All @@ -110,6 +123,8 @@
return getDiscountTypeLabel(value as VoucherDiscountType, intl);
case "voucherStatus":
return getVoucherStatusLabel(value as DiscountStatusEnum, intl);
case "typeOfProduct":
return getProductTypeLabel(value as ProductTypeEnum, intl);

Check warning on line 127 in src/components/ConditionalFilter/API/intl.ts

View check run for this annotation

Codecov / codecov/patch

src/components/ConditionalFilter/API/intl.ts#L126-L127

Added lines #L126 - L127 were not covered by tests
default:
return value;
}
Expand Down
13 changes: 13 additions & 0 deletions src/components/ConditionalFilter/API/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,16 @@ export const collectionFilterMessages = defineMessages({
id: "ThUvIL",
},
});

export const productTypeMessages = defineMessages({
digital: {
defaultMessage: "Digital",
description: "product type digital",
id: "SgFE10",
},
shippable: {
defaultMessage: "Shippable",
description: "product type shippable",
id: "M61TN/",
},
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,8 @@ import { IntlShape, useIntl } from "react-intl";
import { FilterContainer, FilterElement } from "../../FilterElement";
import { FilterAPIProvider } from "../FilterAPIProvider";
import { ChannelHandler, EnumValuesHandler, Handler, NoopValuesHandler } from "../Handler";
import { getFilterElement } from "../utils";

const getFilterElement = (value: FilterContainer, index: number): FilterElement => {
const possibleFilterElement = value[index];

if (typeof possibleFilterElement !== "string" && !Array.isArray(possibleFilterElement)) {
return possibleFilterElement;
}

throw new Error("Unknown filter element used to create API handler");
};
const createAPIHandler = (
selectedRow: FilterElement,
client: ApolloClient<unknown>,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FilterAPIProvider } from "@dashboard/components/ConditionalFilter/API/FilterAPIProvider";
import { FilterAPIProvider } from "../FilterAPIProvider";

export const useDiscountFilterAPIProvider = (): FilterAPIProvider => {
const fetchRightOptions = async () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FilterAPIProvider } from "@dashboard/components/ConditionalFilter/API/FilterAPIProvider";
import { FilterAPIProvider } from "../FilterAPIProvider";

export const useDraftOrderFilterAPIProvider = (): FilterAPIProvider => {
const fetchRightOptions = async () => {
Expand Down
Loading
Loading