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/sharp-plants-dance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"saleor-dashboard": patch
---

Gift cards list page use now new filters. New filters are under feature flag and are enabled by default.
34 changes: 24 additions & 10 deletions .featureFlags/generated.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
// @ts-nocheck

import V92679 from "./images/discounts-list.png"
import Z34507 from "./images/draft-orders-filters.png"
import R14220 from "./images/improved_refunds.png"
import T12026 from "./images/page-filters.png"
import Q15387 from "./images/vouchers-filters.png"
import K01586 from "./images/discounts-list.png"
import J60656 from "./images/draft-orders-filters.png"
import W15309 from "./images/gift-cards-filters.png"
import P14884 from "./images/improved_refunds.png"
import J91775 from "./images/page-filters.png"
import F54595 from "./images/vouchers-filters.png"

const discounts_rules = () => (<><p><img src={V92679} alt="Discount rules"/></p>
const discounts_rules = () => (<><p><img src={K01586} 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={Z34507} alt="new filters"/>
const draft_orders_filters = () => (<><p><img src={J60656} 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={R14220} alt="Improved refunds"/></p>
const gift_cards_filters = () => (<><p><img src={W15309} 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={P14884} 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 @@ -24,11 +29,11 @@ const improved_refunds = () => (<><p><img src={R14220} alt="Improved refunds"/><
</ul>

</>)
const pages_filters = () => (<><p><img src={T12026} alt="new filters"/>
const pages_filters = () => (<><p><img src={J91775} 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={Q15387} alt="new filters"/>
const vouchers_filters = () => (<><p><img src={F54595} 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 All @@ -51,6 +56,15 @@ export const AVAILABLE_FLAGS = [{
enabled: true,
payload: "default",
}
},{
name: "gift_cards_filters",
displayName: "Gift cards filtering",
component: gift_cards_filters,
visible: true,
content: {
enabled: true,
payload: "default",
}
},{
name: "improved_refunds",
displayName: "Improved refunds",
Expand Down
11 changes: 11 additions & 0 deletions .featureFlags/gift-cards-new-filters.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
name: gift_cards_filters
displayName: Gift cards filtering
enabled: true
payload: "default"
visible: true
---

![new filters](./images/gift-cards-filters.png)
Experience the new look and enhanced abilities of new fitering mechanism.
Easily combine any criteria you want, and quickly browse their values.
Binary file added .featureFlags/images/gift-cards-filters.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { ApolloClient, useApolloClient } from "@apollo/client";
import { FilterAPIProvider } from "@dashboard/components/ConditionalFilter/API/FilterAPIProvider";
import {
BooleanValuesHandler,
CurrencyHandler,
CustomerHandler,
GiftCardTagsHandler,
Handler,
ProductsHandler,
} from "@dashboard/components/ConditionalFilter/API/Handler";
import {
FilterContainer,
FilterElement,
} from "@dashboard/components/ConditionalFilter/FilterElement";

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>,
inputValue: string,
): Handler => {
const rowType = selectedRow.rowType();

if (rowType === "currency") {
return new CurrencyHandler(client, inputValue);
}

if (rowType === "products") {
return new ProductsHandler(client, inputValue);
}

if (rowType === "tags") {
return new GiftCardTagsHandler(client, inputValue);
}

if (rowType === "usedBy") {
return new CustomerHandler(client, inputValue);
}

if (rowType === "isActive") {
return new BooleanValuesHandler([
{
label: "Yes",
value: "true",
type: rowType,
slug: "true",
},
{
label: "No",
value: "false",
type: rowType,
slug: "false",
},
]);
}

throw new Error(`Unknown filter element: "${rowType}"`);
};

export const useGiftCardsFiltersAPIProvider = (): FilterAPIProvider => {
const client = useApolloClient();

const fetchRightOptions = async (
position: string,
value: FilterContainer,
inputValue: string,
) => {
const index = parseInt(position, 10);
const filterElement = getFilterElement(value, index);

const handler = createAPIHandler(filterElement, client, inputValue);

return handler.fetch();
};
const fetchLeftOptions = async () => {
return [];
};

return {
fetchRightOptions,
fetchLeftOptions,
};
};
130 changes: 130 additions & 0 deletions src/components/ConditionalFilter/API/Handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,28 @@ import {
_GetCollectionsChoicesDocument,
_GetCollectionsChoicesQuery,
_GetCollectionsChoicesQueryVariables,
_GetCustomersChoicesDocument,
_GetCustomersChoicesQuery,
_GetCustomersChoicesQueryVariables,
_GetDynamicLeftOperandsDocument,
_GetDynamicLeftOperandsQuery,
_GetDynamicLeftOperandsQueryVariables,
_GetGiftCardTagsChoicesDocument,
_GetGiftCardTagsChoicesQuery,
_GetGiftCardTagsChoicesQueryVariables,
_GetLegacyChannelOperandsDocument,
_GetPageTypesChoicesDocument,
_GetPageTypesChoicesQuery,
_GetPageTypesChoicesQueryVariables,
_GetProductChoicesDocument,
_GetProductChoicesQuery,
_GetProductChoicesQueryVariables,
_GetProductTypesChoicesDocument,
_GetProductTypesChoicesQuery,
_GetProductTypesChoicesQueryVariables,
ChannelCurrenciesDocument,
ChannelCurrenciesQuery,
ChannelCurrenciesQueryVariables,
} from "@dashboard/graphql";
import { IntlShape } from "react-intl";

Expand Down Expand Up @@ -50,6 +62,25 @@ export const createOptionsFromAPI = (
originalSlug: node.originalSlug,
}));

export const createCustomerOptionsFromAPI = (
data: Array<{
node: {
id: string;
email: string;
firstName: string;
lastName: string;
};
}>,
) => {
return (
data.map(({ node }) => ({
label: node?.firstName && node?.lastName ? `${node.firstName} ${node.lastName}` : node.email,
value: node.id,
slug: node.id,
})) ?? []
);
};

export class AttributeChoicesHandler implements Handler {
constructor(
public client: ApolloClient<unknown>,
Expand Down Expand Up @@ -97,6 +128,33 @@ export class CollectionHandler implements Handler {
};
}

export class CurrencyHandler implements Handler {
constructor(
public client: ApolloClient<unknown>,
public query: string,
) {}

fetch = async () => {
const { data } = await this.client.query<
ChannelCurrenciesQuery,
ChannelCurrenciesQueryVariables
>({
query: ChannelCurrenciesDocument,
variables: {},
});

return data.shop.channelCurrencies
.map(currency => ({
label: currency,
value: currency,
slug: currency,
}))
.filter(({ label }) => {
return label.toLowerCase().includes(this.query.toLowerCase());
});
};
}

export class CategoryHandler implements Handler {
constructor(
public client: ApolloClient<unknown>,
Expand Down Expand Up @@ -141,6 +199,56 @@ export class ProductTypeHandler implements Handler {
};
}

export class ProductsHandler implements Handler {
constructor(
public client: ApolloClient<unknown>,
public query: string,
) {}

fetch = async () => {
const { data } = await this.client.query<
_GetProductChoicesQuery,
_GetProductChoicesQueryVariables
>({
query: _GetProductChoicesDocument,
variables: {
first: 5,
query: this.query,
},
});

return createOptionsFromAPI(data.products?.edges ?? []);
};
}

export class GiftCardTagsHandler implements Handler {
constructor(
public client: ApolloClient<unknown>,
public query: string,
) {}

fetch = async () => {
const { data } = await this.client.query<
_GetGiftCardTagsChoicesQuery,
_GetGiftCardTagsChoicesQueryVariables
>({
query: _GetGiftCardTagsChoicesDocument,
variables: {
first: 5,
query: this.query,
},
});

return (
data?.giftCardTags?.edges.map(({ node }) => ({
label: node.name,
value: node.name,
slug: node.name,
})) ?? []
);
};
}

export class ChannelHandler implements Handler {
constructor(
public client: ApolloClient<unknown>,
Expand All @@ -166,6 +274,28 @@ export class ChannelHandler implements Handler {
};
}

export class CustomerHandler implements Handler {
constructor(
public client: ApolloClient<unknown>,
public query: string,
) {}

fetch = async () => {
const { data } = await this.client.query<
_GetCustomersChoicesQuery,
_GetCustomersChoicesQueryVariables
>({
query: _GetCustomersChoicesDocument,
variables: {
first: 5,
query: this.query,
},
});

return createCustomerOptionsFromAPI(data.customers?.edges ?? []);
};
}

// 'Orders' filter required channel ID, not slug
export class LegacyChannelHandler implements Handler {
constructor(
Expand Down
Loading
Loading