New filters for the product listing page (prototype) (#3811)
* Expression filters * Filters * Tokenizing * Tokenizing * feat: fetch inital state from API * fix: integrate with code * Loading * feat: add attribute name & label * feat: move input type * Loading * feat: update left operator + condition * feat: fetch inital options on focus * feat: fetch right options on autocomplete * Flags * Refactor * fix: add loading state * fix: after changes * fix: remove debugger * fix: proper selected setting * Refactor * Display properly * Display properly * Display properly * feat: fetch left options * Persist * feat: add loading state * feat: refactor getAPIOptions * feat: add additional checks to filter element * feat: use debounce * FilterArray * FilterArray * Modeling * fix: filters in popover * feat: use new macaw ui version * Types * Feature flag * fix: type errors * Alignment * Fix api * feat: add slug * feat: add slug * feat: add slug for the last time * fix: return slug from left options * Fix combobox * Force slug * Changeset * fix: serialize value --------- Co-authored-by: Krzysztof Żuraw <9116238+krzysztofzuraw@users.noreply.github.com>
This commit is contained in:
parent
a08d034e75
commit
198341cb41
27 changed files with 2200 additions and 49 deletions
5
.changeset/olive-bikes-switch.md
Normal file
5
.changeset/olive-bikes-switch.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"saleor-dashboard": minor
|
||||
---
|
||||
|
||||
Prototype of the new filters for product listing page
|
14
package-lock.json
generated
14
package-lock.json
generated
|
@ -27,7 +27,7 @@
|
|||
"@material-ui/lab": "^4.0.0-alpha.61",
|
||||
"@material-ui/styles": "^4.11.4",
|
||||
"@reach/auto-id": "^0.16.0",
|
||||
"@saleor/macaw-ui": "0.8.0-pre.98",
|
||||
"@saleor/macaw-ui": "0.8.0-pre.101",
|
||||
"@saleor/sdk": "0.6.0",
|
||||
"@sentry/react": "^6.0.0",
|
||||
"@types/faker": "^5.1.6",
|
||||
|
@ -7840,9 +7840,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@saleor/macaw-ui": {
|
||||
"version": "0.8.0-pre.98",
|
||||
"resolved": "https://registry.npmjs.org/@saleor/macaw-ui/-/macaw-ui-0.8.0-pre.98.tgz",
|
||||
"integrity": "sha512-W/KCjRoVVr751JxPET/ebXt9im5lleCGAtydFcuDwmxoU11wTlyxHM25owsJJBpTq1L+jdrMyXO/vZ1FL06Osg==",
|
||||
"version": "0.8.0-pre.101",
|
||||
"resolved": "https://registry.npmjs.org/@saleor/macaw-ui/-/macaw-ui-0.8.0-pre.101.tgz",
|
||||
"integrity": "sha512-q68uQs33L8CEjQkZyfRIaljOiRNV6dyIMR211VYdWtAs60jsozwfwnoifPMz3m1DBBJbbaHjwsC7dD9AdlaR2w==",
|
||||
"dependencies": {
|
||||
"@dessert-box/react": "^0.4.0",
|
||||
"@floating-ui/react-dom-interactions": "^0.5.0",
|
||||
|
@ -40651,9 +40651,9 @@
|
|||
}
|
||||
},
|
||||
"@saleor/macaw-ui": {
|
||||
"version": "0.8.0-pre.98",
|
||||
"resolved": "https://registry.npmjs.org/@saleor/macaw-ui/-/macaw-ui-0.8.0-pre.98.tgz",
|
||||
"integrity": "sha512-W/KCjRoVVr751JxPET/ebXt9im5lleCGAtydFcuDwmxoU11wTlyxHM25owsJJBpTq1L+jdrMyXO/vZ1FL06Osg==",
|
||||
"version": "0.8.0-pre.101",
|
||||
"resolved": "https://registry.npmjs.org/@saleor/macaw-ui/-/macaw-ui-0.8.0-pre.101.tgz",
|
||||
"integrity": "sha512-q68uQs33L8CEjQkZyfRIaljOiRNV6dyIMR211VYdWtAs60jsozwfwnoifPMz3m1DBBJbbaHjwsC7dD9AdlaR2w==",
|
||||
"requires": {
|
||||
"@dessert-box/react": "^0.4.0",
|
||||
"@floating-ui/react-dom-interactions": "^0.5.0",
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
"@material-ui/lab": "^4.0.0-alpha.61",
|
||||
"@material-ui/styles": "^4.11.4",
|
||||
"@reach/auto-id": "^0.16.0",
|
||||
"@saleor/macaw-ui": "0.8.0-pre.98",
|
||||
"@saleor/macaw-ui": "0.8.0-pre.101",
|
||||
"@saleor/sdk": "0.6.0",
|
||||
"@sentry/react": "^6.0.0",
|
||||
"@types/faker": "^5.1.6",
|
||||
|
@ -96,8 +96,6 @@
|
|||
"use-react-router": "^1.0.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@changesets/changelog-github": "^0.4.8",
|
||||
"@changesets/cli": "^2.26.1",
|
||||
"@babel/cli": "^7.5.5",
|
||||
"@babel/core": "^7.7.7",
|
||||
"@babel/plugin-proposal-class-properties": "^7.5.0",
|
||||
|
@ -110,6 +108,8 @@
|
|||
"@babel/preset-react": "^7.7.4",
|
||||
"@babel/preset-typescript": "^7.13.0",
|
||||
"@babel/runtime": "^7.7.6",
|
||||
"@changesets/changelog-github": "^0.4.8",
|
||||
"@changesets/cli": "^2.26.1",
|
||||
"@editorjs/embed": "^2.5.3",
|
||||
"@esbuild-plugins/node-globals-polyfill": "^0.1.1",
|
||||
"@formatjs/cli": "^4.5.0",
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
import { FilterErrorMessages, IFilter } from "@dashboard/components/Filter";
|
||||
import { useFlag } from "@dashboard/featureFlags";
|
||||
import { FilterProps, SearchPageProps } from "@dashboard/types";
|
||||
import { Box } from "@saleor/macaw-ui/next";
|
||||
import React, { ReactNode } from "react";
|
||||
|
||||
import { ExpressionFilters } from "./components/ExpressionFilters";
|
||||
import { FiltersSelect } from "./components/FiltersSelect";
|
||||
import SearchInput from "./components/SearchInput";
|
||||
|
||||
|
@ -25,7 +27,12 @@ export const ListFilters = ({
|
|||
onFilterAttributeFocus,
|
||||
errorMessages,
|
||||
actions,
|
||||
}: ListFiltersProps) => (
|
||||
}: ListFiltersProps) => {
|
||||
const isProductPage = window.location.pathname.includes("/products");
|
||||
const productListingPageFiltersFlag = useFlag("product_filters");
|
||||
const filtersEnabled = isProductPage && productListingPageFiltersFlag.enabled;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box
|
||||
display="grid"
|
||||
|
@ -35,6 +42,9 @@ export const ListFilters = ({
|
|||
paddingX={6}
|
||||
>
|
||||
<Box display="flex" alignItems="center" gap={4}>
|
||||
{filtersEnabled ? (
|
||||
<ExpressionFilters />
|
||||
) : (
|
||||
<FiltersSelect
|
||||
errorMessages={errorMessages}
|
||||
menu={filterStructure}
|
||||
|
@ -42,7 +52,7 @@ export const ListFilters = ({
|
|||
onFilterAdd={onFilterChange}
|
||||
onFilterAttributeFocus={onFilterAttributeFocus}
|
||||
/>
|
||||
|
||||
)}
|
||||
<Box __width="320px">
|
||||
<SearchInput
|
||||
initialSearch={initialSearch}
|
||||
|
@ -57,4 +67,5 @@ export const ListFilters = ({
|
|||
</Box>
|
||||
</>
|
||||
);
|
||||
};
|
||||
ListFilters.displayName = "FilterBar";
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
import { ConditionalFilters } from "@dashboard/components/ConditionalFilter";
|
||||
import { Box, Button, Popover } from "@saleor/macaw-ui/next";
|
||||
import React from "react";
|
||||
|
||||
export const ExpressionFilters = () => (
|
||||
<Popover>
|
||||
<Popover.Trigger>
|
||||
<Button>Show filters</Button>
|
||||
</Popover.Trigger>
|
||||
<Popover.Content align="start">
|
||||
<Box __minWidth="200px" __minHeight="100px" paddingX={4} paddingY={3}>
|
||||
<Popover.Arrow />
|
||||
<ConditionalFilters />
|
||||
</Box>
|
||||
</Popover.Content>
|
||||
</Popover>
|
||||
);
|
56
src/components/ConditionalFilter/API/InitialStateResponse.ts
Normal file
56
src/components/ConditionalFilter/API/InitialStateResponse.ts
Normal file
|
@ -0,0 +1,56 @@
|
|||
import { AttributeInputType } from "../FilterElement/ConditionOptions";
|
||||
import { ItemOption } from "../FilterElement/ConditionSelected";
|
||||
import { UrlToken } from "../ValueProvider/UrlToken";
|
||||
|
||||
interface AttributeDTO {
|
||||
choices: Array<{ label: string; value: string; slug: string }>;
|
||||
inputType: AttributeInputType;
|
||||
label: string;
|
||||
slug: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export class InitialStateResponse {
|
||||
constructor(
|
||||
public category: ItemOption[],
|
||||
public attribute: Record<string, AttributeDTO>,
|
||||
public channel: ItemOption[],
|
||||
public collection: ItemOption[],
|
||||
public producttype: ItemOption[],
|
||||
) {}
|
||||
|
||||
public attributeByName(name: string) {
|
||||
return this.attribute[name];
|
||||
}
|
||||
|
||||
public filterByUrlToken(token: UrlToken) {
|
||||
if (token.isAttribute()) {
|
||||
return this.attribute[token.name].choices.filter(({ value }) =>
|
||||
token.value.includes(value),
|
||||
);
|
||||
}
|
||||
|
||||
if (!token.isLoadable()) {
|
||||
return [token.value] as string[];
|
||||
}
|
||||
|
||||
return this.getEntryByname(token.name).filter(
|
||||
({ slug }) => slug && token.value.includes(slug),
|
||||
);
|
||||
}
|
||||
|
||||
private getEntryByname(name: string) {
|
||||
switch (name) {
|
||||
case "category":
|
||||
return this.category;
|
||||
case "collection":
|
||||
return this.collection;
|
||||
case "producttype":
|
||||
return this.producttype;
|
||||
case "channel":
|
||||
return this.channel;
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
211
src/components/ConditionalFilter/API/getAPIOptions.tsx
Normal file
211
src/components/ConditionalFilter/API/getAPIOptions.tsx
Normal file
|
@ -0,0 +1,211 @@
|
|||
// @ts-strict-ignore
|
||||
import { ApolloClient } from "@apollo/client";
|
||||
import {
|
||||
_GetAttributeChoicesDocument,
|
||||
_GetCategoriesChoicesDocument,
|
||||
_GetChannelOperandsDocument,
|
||||
_GetCollectionsChoicesDocument,
|
||||
_GetDynamicLeftOperandsDocument,
|
||||
_GetProductTypesChoicesDocument,
|
||||
} from "@dashboard/graphql";
|
||||
|
||||
import { FilterElement } from "../FilterElement";
|
||||
import { FilterContainer } from "../useFilterContainer";
|
||||
|
||||
const getFilterElement = (value: any, index: number): FilterElement => {
|
||||
const possibleFilterElement = value[index];
|
||||
return typeof possibleFilterElement != "string"
|
||||
? possibleFilterElement
|
||||
: null;
|
||||
};
|
||||
|
||||
export const getInitialRightOperatorOptions = async (
|
||||
client: ApolloClient<any>,
|
||||
position: string,
|
||||
value: FilterContainer,
|
||||
) => {
|
||||
const index = parseInt(position, 10);
|
||||
const filterElement = getFilterElement(value, index);
|
||||
|
||||
if (filterElement.isAttribute()) {
|
||||
const { data } = await client.query({
|
||||
query: _GetAttributeChoicesDocument,
|
||||
variables: {
|
||||
slug: filterElement.value.value,
|
||||
first: 5,
|
||||
query: "",
|
||||
},
|
||||
});
|
||||
return data.attribute.choices.edges.map(({ node }) => ({
|
||||
label: node.name,
|
||||
value: node.id,
|
||||
slug: node.slug,
|
||||
}));
|
||||
}
|
||||
|
||||
if (filterElement.isCollection()) {
|
||||
const { data } = await client.query({
|
||||
query: _GetCollectionsChoicesDocument,
|
||||
variables: {
|
||||
first: 5,
|
||||
query: "",
|
||||
},
|
||||
});
|
||||
|
||||
return data.collections.edges.map(({ node }) => ({
|
||||
label: node.name,
|
||||
value: node.id,
|
||||
slug: node.slug,
|
||||
}));
|
||||
}
|
||||
|
||||
if (filterElement.isCategory()) {
|
||||
const { data } = await client.query({
|
||||
query: _GetCategoriesChoicesDocument,
|
||||
variables: {
|
||||
first: 5,
|
||||
query: "",
|
||||
},
|
||||
});
|
||||
|
||||
return data.categories.edges.map(({ node }) => ({
|
||||
label: node.name,
|
||||
value: node.id,
|
||||
slug: node.slug,
|
||||
}));
|
||||
}
|
||||
|
||||
if (filterElement.isProductType()) {
|
||||
const { data } = await client.query({
|
||||
query: _GetProductTypesChoicesDocument,
|
||||
variables: {
|
||||
first: 5,
|
||||
query: "",
|
||||
},
|
||||
});
|
||||
|
||||
return data.productTypes.edges.map(({ node }) => ({
|
||||
label: node.name,
|
||||
value: node.id,
|
||||
slug: node.slug,
|
||||
}));
|
||||
}
|
||||
|
||||
if (filterElement.isChannel()) {
|
||||
const { data } = await client.query({
|
||||
query: _GetChannelOperandsDocument,
|
||||
});
|
||||
|
||||
return data.channels.map(({ id, name, slug }) => ({
|
||||
label: name,
|
||||
value: id,
|
||||
slug,
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
export const getRightOperatorOptionsByQuery = async (
|
||||
client: ApolloClient<any>,
|
||||
position: string,
|
||||
value: FilterContainer,
|
||||
inputValue: string,
|
||||
) => {
|
||||
const index = parseInt(position, 10);
|
||||
const filterElement = getFilterElement(value, index);
|
||||
|
||||
if (filterElement.isAttribute()) {
|
||||
const { data } = await client.query({
|
||||
query: _GetAttributeChoicesDocument,
|
||||
variables: {
|
||||
slug: filterElement.value.value,
|
||||
first: 5,
|
||||
query: inputValue,
|
||||
},
|
||||
});
|
||||
return data.attribute.choices.edges.map(({ node }) => ({
|
||||
label: node.name,
|
||||
value: node.id,
|
||||
}));
|
||||
}
|
||||
|
||||
if (filterElement.isCollection()) {
|
||||
const { data } = await client.query({
|
||||
query: _GetCollectionsChoicesDocument,
|
||||
variables: {
|
||||
first: 5,
|
||||
query: inputValue,
|
||||
},
|
||||
});
|
||||
|
||||
return data.collections.edges.map(({ node }) => ({
|
||||
label: node.name,
|
||||
value: node.id,
|
||||
slug: node.slug,
|
||||
}));
|
||||
}
|
||||
|
||||
if (filterElement.isCategory()) {
|
||||
const { data } = await client.query({
|
||||
query: _GetCategoriesChoicesDocument,
|
||||
variables: {
|
||||
first: 5,
|
||||
query: inputValue,
|
||||
},
|
||||
});
|
||||
|
||||
return data.categories.edges.map(({ node }) => ({
|
||||
label: node.name,
|
||||
value: node.id,
|
||||
slug: node.slug,
|
||||
}));
|
||||
}
|
||||
|
||||
if (filterElement.isProductType()) {
|
||||
const { data } = await client.query({
|
||||
query: _GetProductTypesChoicesDocument,
|
||||
variables: {
|
||||
first: 5,
|
||||
query: inputValue,
|
||||
},
|
||||
});
|
||||
|
||||
return data.productTypes.edges.map(({ node }) => ({
|
||||
label: node.name,
|
||||
value: node.id,
|
||||
}));
|
||||
}
|
||||
|
||||
if (filterElement.isChannel()) {
|
||||
const { data } = await client.query({
|
||||
query: _GetChannelOperandsDocument,
|
||||
});
|
||||
const options = data.channels.map(({ id, name, slug }) => ({
|
||||
label: name,
|
||||
value: id,
|
||||
slug,
|
||||
}));
|
||||
|
||||
return options.filter(({ label }) =>
|
||||
label.toLowerCase().includes(inputValue.toLowerCase()),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const getLeftOperatorOptions = async (
|
||||
client: any,
|
||||
inputValue: string,
|
||||
) => {
|
||||
const { data } = await client.query({
|
||||
query: _GetDynamicLeftOperandsDocument,
|
||||
variables: {
|
||||
first: 5,
|
||||
query: inputValue,
|
||||
},
|
||||
});
|
||||
return data.attributes.edges.map(({ node }) => ({
|
||||
label: node.name,
|
||||
value: node.id,
|
||||
type: node.inputType,
|
||||
slug: node.slug,
|
||||
}));
|
||||
};
|
177
src/components/ConditionalFilter/API/getInitalAPIState.tsx
Normal file
177
src/components/ConditionalFilter/API/getInitalAPIState.tsx
Normal file
|
@ -0,0 +1,177 @@
|
|||
// @ts-strict-ignore
|
||||
import { useApolloClient } from "@apollo/client";
|
||||
import {
|
||||
_GetChannelOperandsDocument,
|
||||
_SearchAttributeOperandsDocument,
|
||||
_SearchCategoriesOperandsDocument,
|
||||
_SearchCollectionsOperandsDocument,
|
||||
_SearchProductTypesOperandsDocument,
|
||||
} from "@dashboard/graphql";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
import { InitialStateResponse } from "./InitialStateResponse";
|
||||
|
||||
interface Props {
|
||||
category?: string[];
|
||||
collection?: string[];
|
||||
channel?: string[];
|
||||
producttype?: string[];
|
||||
attribute?: {
|
||||
[attribute: string]: string[];
|
||||
};
|
||||
}
|
||||
|
||||
export const useInitialAPIState = ({
|
||||
category = [],
|
||||
collection = [],
|
||||
producttype = [],
|
||||
channel = [],
|
||||
attribute = {},
|
||||
}: Props) => {
|
||||
const client = useApolloClient();
|
||||
const [data, setData] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
const queriesToRun = [];
|
||||
|
||||
const fetchQueries = async () => {
|
||||
const data = await Promise.all(queriesToRun);
|
||||
setData(data);
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
if (channel.length > 0) {
|
||||
queriesToRun.push(
|
||||
client.query({
|
||||
query: _GetChannelOperandsDocument,
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
queriesToRun.push({});
|
||||
}
|
||||
|
||||
if (collection.length > 0) {
|
||||
queriesToRun.push(
|
||||
client.query({
|
||||
query: _SearchCollectionsOperandsDocument,
|
||||
variables: {
|
||||
collectionsSlugs: collection,
|
||||
first: collection.length,
|
||||
},
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
queriesToRun.push({});
|
||||
}
|
||||
|
||||
if (category.length > 0) {
|
||||
queriesToRun.push(
|
||||
client.query({
|
||||
query: _SearchCategoriesOperandsDocument,
|
||||
variables: {
|
||||
categoriesSlugs: category,
|
||||
first: category.length,
|
||||
},
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
queriesToRun.push({});
|
||||
}
|
||||
|
||||
if (producttype.length > 0) {
|
||||
queriesToRun.push(
|
||||
client.query({
|
||||
query: _SearchProductTypesOperandsDocument,
|
||||
variables: {
|
||||
productTypesSlugs: producttype,
|
||||
first: producttype.length,
|
||||
},
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
queriesToRun.push({});
|
||||
}
|
||||
|
||||
if (Object.keys(attribute).length > 0) {
|
||||
queriesToRun.push(
|
||||
client.query({
|
||||
query: _SearchAttributeOperandsDocument,
|
||||
variables: {
|
||||
attributesSlugs: Object.keys(attribute),
|
||||
choicesIds: Object.values(attribute).flat(),
|
||||
first: Object.keys(attribute).length,
|
||||
},
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
queriesToRun.push({});
|
||||
}
|
||||
|
||||
fetchQueries();
|
||||
}, []);
|
||||
|
||||
const [
|
||||
channelData,
|
||||
collectionData,
|
||||
categoryData,
|
||||
productTypesData,
|
||||
attributesData,
|
||||
] = data;
|
||||
|
||||
const channelPicks =
|
||||
channelData?.data?.channels
|
||||
?.filter(({ slug }) => channel.includes(slug))
|
||||
.map(({ id, name }) => ({ label: name, value: id })) ?? [];
|
||||
|
||||
const collectionPicks =
|
||||
collectionData?.data?.search?.edges.map(({ node }) => ({
|
||||
label: node?.name,
|
||||
value: node?.id,
|
||||
slug: node?.slug,
|
||||
})) ?? [];
|
||||
|
||||
const categoryPicks =
|
||||
categoryData?.data?.search?.edges.map(({ node }) => ({
|
||||
label: node?.name,
|
||||
value: node?.id,
|
||||
slug: node?.slug,
|
||||
})) ?? [];
|
||||
|
||||
const productTypePicks =
|
||||
productTypesData?.data?.search?.edges.map(({ node }) => ({
|
||||
label: node?.name,
|
||||
value: node?.id,
|
||||
slug: node?.slug,
|
||||
})) ?? [];
|
||||
|
||||
const attributePicks =
|
||||
attributesData?.data?.search?.edges.reduce(
|
||||
(acc, { node }) => ({
|
||||
...acc,
|
||||
[node?.slug]: {
|
||||
choices: node?.choices.edges.map(({ node }) => ({
|
||||
label: node?.name,
|
||||
value: node?.id,
|
||||
slug: node?.slug,
|
||||
})),
|
||||
slug: node?.slug,
|
||||
value: node?.id,
|
||||
label: node?.name,
|
||||
inputType: node?.inputType,
|
||||
},
|
||||
}),
|
||||
{},
|
||||
) ?? {};
|
||||
|
||||
return {
|
||||
data: new InitialStateResponse(
|
||||
categoryPicks,
|
||||
attributePicks,
|
||||
channelPicks,
|
||||
collectionPicks,
|
||||
productTypePicks,
|
||||
),
|
||||
loading,
|
||||
};
|
||||
};
|
156
src/components/ConditionalFilter/API/queries.ts
Normal file
156
src/components/ConditionalFilter/API/queries.ts
Normal file
|
@ -0,0 +1,156 @@
|
|||
import { gql } from "@apollo/client";
|
||||
|
||||
export const initialDynamicLeftOperands = gql`
|
||||
query _GetDynamicLeftOperands($first: Int!, $query: String!) {
|
||||
attributes(first: $first, filter: { type: PRODUCT_TYPE, search: $query }) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
name
|
||||
slug
|
||||
inputType
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const initialDynamicOperands = gql`
|
||||
query _GetChannelOperands {
|
||||
channels {
|
||||
id
|
||||
name
|
||||
slug
|
||||
}
|
||||
}
|
||||
|
||||
query _SearchCollectionsOperands($first: Int!, $collectionsSlugs: [String!]) {
|
||||
search: collections(first: $first, filter: { slugs: $collectionsSlugs }) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
name
|
||||
slug
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
query _SearchCategoriesOperands(
|
||||
$after: String
|
||||
$first: Int!
|
||||
$categoriesSlugs: [String!]
|
||||
) {
|
||||
search: categories(
|
||||
after: $after
|
||||
first: $first
|
||||
filter: { slugs: $categoriesSlugs }
|
||||
) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
name
|
||||
slug
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
query _SearchProductTypesOperands(
|
||||
$after: String
|
||||
$first: Int!
|
||||
$productTypesSlugs: [String!]
|
||||
) {
|
||||
search: productTypes(
|
||||
after: $after
|
||||
first: $first
|
||||
filter: { slugs: $productTypesSlugs }
|
||||
) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
name
|
||||
slug
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
query _SearchAttributeOperands(
|
||||
$attributesSlugs: [String!]
|
||||
$choicesIds: [ID!]
|
||||
$first: Int!
|
||||
) {
|
||||
search: attributes(first: $first, filter: { slugs: $attributesSlugs }) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
name
|
||||
slug
|
||||
inputType
|
||||
choices(first: 5, filter: { ids: $choicesIds }) {
|
||||
edges {
|
||||
node {
|
||||
slug: id
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const dynamicOperandsQueries = gql`
|
||||
query _GetAttributeChoices($slug: String!, $first: Int!, $query: String!) {
|
||||
attribute(slug: $slug) {
|
||||
choices(first: $first, filter: { search: $query }) {
|
||||
edges {
|
||||
node {
|
||||
slug: id
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
query _GetCollectionsChoices($first: Int!, $query: String!) {
|
||||
collections(first: $first, filter: { search: $query }) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
name
|
||||
slug
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
query _GetCategoriesChoices($first: Int!, $query: String!) {
|
||||
categories(first: $first, filter: { search: $query }) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
name
|
||||
slug
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
query _GetProductTypesChoices($first: Int!, $query: String!) {
|
||||
productTypes(first: $first, filter: { search: $query }) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
name
|
||||
slug
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
80
src/components/ConditionalFilter/FilterElement/Condition.ts
Normal file
80
src/components/ConditionalFilter/FilterElement/Condition.ts
Normal file
|
@ -0,0 +1,80 @@
|
|||
/* eslint-disable @typescript-eslint/member-ordering */
|
||||
import { InitialStateResponse } from "../API/InitialStateResponse";
|
||||
import { LeftOperand } from "./../useLeftOperands";
|
||||
import { UrlToken } from "./../ValueProvider/UrlToken";
|
||||
import { ConditionOptions } from "./ConditionOptions";
|
||||
import { ConditionSelected } from "./ConditionSelected";
|
||||
|
||||
export class Condition {
|
||||
private constructor(
|
||||
public options: ConditionOptions,
|
||||
public selected: ConditionSelected,
|
||||
public loading: boolean,
|
||||
) {}
|
||||
|
||||
public enableLoading() {
|
||||
this.loading = true;
|
||||
}
|
||||
|
||||
public disableLoading() {
|
||||
this.loading = false;
|
||||
}
|
||||
|
||||
public isLoading() {
|
||||
return this.loading;
|
||||
}
|
||||
|
||||
public static createEmpty() {
|
||||
return new Condition(
|
||||
ConditionOptions.empty(),
|
||||
ConditionSelected.empty(),
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
public static emptyFromLeftOperand(operand: LeftOperand) {
|
||||
const options = ConditionOptions.fromName(operand.type);
|
||||
|
||||
return new Condition(
|
||||
options,
|
||||
ConditionSelected.fromConditionItem(options.first()),
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
public static fromUrlToken(token: UrlToken, response: InitialStateResponse) {
|
||||
if (ConditionOptions.isStaticName(token.name)) {
|
||||
const staticOptions = ConditionOptions.fromStaticElementName(token.name);
|
||||
const selectedOption = staticOptions.findByLabel(token.conditionKind);
|
||||
const valueItems = response.filterByUrlToken(token);
|
||||
const value =
|
||||
selectedOption?.type === "multiselect" && valueItems.length > 0
|
||||
? valueItems
|
||||
: valueItems[0];
|
||||
|
||||
if (!selectedOption) {
|
||||
return Condition.createEmpty();
|
||||
}
|
||||
|
||||
return new Condition(
|
||||
staticOptions,
|
||||
ConditionSelected.fromConditionItemAndValue(selectedOption, value),
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
if (token.isAttribute()) {
|
||||
const attribute = response.attributeByName(token.name);
|
||||
const options = ConditionOptions.fromAtributeType(attribute.inputType);
|
||||
const value = response.filterByUrlToken(token);
|
||||
|
||||
return new Condition(
|
||||
options,
|
||||
ConditionSelected.fromConditionItemAndValue(options.first(), value),
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
return Condition.createEmpty();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
import {
|
||||
ATTRIBUTE_INPUT_TYPE_CONDITIONS,
|
||||
STATIC_CONDITIONS,
|
||||
} from "../constants";
|
||||
|
||||
export type StaticElementName = keyof typeof STATIC_CONDITIONS;
|
||||
export type AttributeInputType = keyof typeof ATTRIBUTE_INPUT_TYPE_CONDITIONS;
|
||||
|
||||
export interface ConditionItem {
|
||||
type: string;
|
||||
label: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export class ConditionOptions extends Array<ConditionItem> {
|
||||
private constructor(options: ConditionItem[] | number) {
|
||||
if (Array.isArray(options)) {
|
||||
super(...options);
|
||||
return;
|
||||
}
|
||||
|
||||
super(options);
|
||||
}
|
||||
|
||||
public static isStaticName(name: string): name is StaticElementName {
|
||||
return name in STATIC_CONDITIONS;
|
||||
}
|
||||
|
||||
public static isAttributeInputType(name: string): name is AttributeInputType {
|
||||
return name in ATTRIBUTE_INPUT_TYPE_CONDITIONS;
|
||||
}
|
||||
|
||||
public static fromAtributeType(inputType: AttributeInputType) {
|
||||
const options = ATTRIBUTE_INPUT_TYPE_CONDITIONS[inputType];
|
||||
|
||||
if (!options) {
|
||||
throw new Error(`Unsupported attribute input type "${inputType}"`);
|
||||
}
|
||||
|
||||
return new ConditionOptions(options);
|
||||
}
|
||||
public static fromStaticElementName(name: StaticElementName) {
|
||||
const options = STATIC_CONDITIONS[name];
|
||||
|
||||
if (!options) {
|
||||
throw new Error(`Unsupported static element "${name}"`);
|
||||
}
|
||||
|
||||
return new ConditionOptions(options);
|
||||
}
|
||||
|
||||
public static fromName(name: AttributeInputType | StaticElementName) {
|
||||
const optionsStatic = this.isStaticName(name) && STATIC_CONDITIONS[name];
|
||||
const optionsAttribute =
|
||||
this.isAttributeInputType(name) && ATTRIBUTE_INPUT_TYPE_CONDITIONS[name];
|
||||
|
||||
if (optionsStatic) {
|
||||
return new ConditionOptions(optionsStatic);
|
||||
}
|
||||
|
||||
if (optionsAttribute) {
|
||||
return new ConditionOptions(optionsAttribute);
|
||||
}
|
||||
|
||||
throw new Error(`Unsupported condition element "${name}"`);
|
||||
}
|
||||
|
||||
public static empty() {
|
||||
return new ConditionOptions([]);
|
||||
}
|
||||
|
||||
public findByLabel(label: string) {
|
||||
return this.find(f => f.label === label);
|
||||
}
|
||||
|
||||
public first() {
|
||||
return this[0];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
import { getDefaultByControlName } from "../controlsType";
|
||||
import { ConditionItem } from "./ConditionOptions";
|
||||
|
||||
export interface ItemOption {
|
||||
label: string;
|
||||
value: string;
|
||||
slug?: string;
|
||||
}
|
||||
|
||||
export type ConditionOption =
|
||||
| ItemOption
|
||||
| ItemOption[]
|
||||
| string
|
||||
| string[]
|
||||
| [string, string];
|
||||
|
||||
export class ConditionSelected {
|
||||
private constructor(
|
||||
public value: ConditionOption,
|
||||
public conditionValue: ConditionItem | null,
|
||||
public options: ConditionOption[],
|
||||
public loading: boolean,
|
||||
) {}
|
||||
|
||||
public static empty() {
|
||||
return new ConditionSelected("", null, [], false);
|
||||
}
|
||||
|
||||
public static fromConditionItem(conditionItem: ConditionItem) {
|
||||
return new ConditionSelected(
|
||||
getDefaultByControlName(conditionItem.type),
|
||||
conditionItem,
|
||||
[],
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
public static fromConditionItemAndValue(
|
||||
conditionItem: ConditionItem,
|
||||
value: ConditionOption,
|
||||
) {
|
||||
return new ConditionSelected(value, conditionItem, [], false);
|
||||
}
|
||||
|
||||
public enableLoading() {
|
||||
this.loading = true;
|
||||
}
|
||||
|
||||
public disableLoading() {
|
||||
this.loading = false;
|
||||
}
|
||||
|
||||
public isLoading() {
|
||||
return this.loading;
|
||||
}
|
||||
|
||||
public setValue(value: ConditionOption) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public setOptions(options: ConditionOption[]) {
|
||||
this.options = options;
|
||||
|
||||
if (this.conditionValue) {
|
||||
this.value = getDefaultByControlName(this.conditionValue.type);
|
||||
}
|
||||
}
|
||||
}
|
179
src/components/ConditionalFilter/FilterElement/FilterElement.ts
Normal file
179
src/components/ConditionalFilter/FilterElement/FilterElement.ts
Normal file
|
@ -0,0 +1,179 @@
|
|||
/* eslint-disable @typescript-eslint/member-ordering */
|
||||
import { InitialStateResponse } from "../API/InitialStateResponse";
|
||||
import { LeftOperand } from "./../useLeftOperands";
|
||||
import { CONDITIONS, UrlEntry, UrlToken } from "./../ValueProvider/UrlToken";
|
||||
import { Condition } from "./Condition";
|
||||
import { ConditionItem, ConditionOptions } from "./ConditionOptions";
|
||||
import { ConditionOption, ConditionSelected } from "./ConditionSelected";
|
||||
|
||||
interface ExpressionValue {
|
||||
value: string;
|
||||
label: string;
|
||||
type: string;
|
||||
}
|
||||
|
||||
const createStaticEntry = (rawEntry: ConditionOption) => {
|
||||
if (typeof rawEntry === "string") {
|
||||
return rawEntry;
|
||||
}
|
||||
|
||||
if (Array.isArray(rawEntry)) {
|
||||
return rawEntry.map(el => (typeof el === "string" ? el : el.slug));
|
||||
}
|
||||
|
||||
return rawEntry.slug;
|
||||
};
|
||||
|
||||
const createAttributeEntry = (rawEntry: ConditionOption) => {
|
||||
if (typeof rawEntry === "string") {
|
||||
return rawEntry;
|
||||
}
|
||||
|
||||
if (Array.isArray(rawEntry)) {
|
||||
return rawEntry.map(el => (typeof el === "string" ? el : el.slug));
|
||||
}
|
||||
|
||||
return rawEntry.slug;
|
||||
};
|
||||
|
||||
export class FilterElement {
|
||||
private constructor(
|
||||
public value: ExpressionValue,
|
||||
public condition: Condition,
|
||||
public loading: boolean,
|
||||
) {}
|
||||
|
||||
public enableLoading() {
|
||||
this.loading = true;
|
||||
}
|
||||
|
||||
public disableLoading() {
|
||||
this.loading = false;
|
||||
}
|
||||
|
||||
public isLoading() {
|
||||
return this.loading;
|
||||
}
|
||||
|
||||
public updateLeftOperator(leftOperand: LeftOperand) {
|
||||
this.value = {
|
||||
value: leftOperand.slug,
|
||||
label: leftOperand.label,
|
||||
type: leftOperand.type,
|
||||
};
|
||||
this.condition = Condition.emptyFromLeftOperand(leftOperand);
|
||||
}
|
||||
|
||||
public updateLeftLoadingState(loading: boolean) {
|
||||
this.loading = loading;
|
||||
}
|
||||
|
||||
public updateCondition(conditionValue: ConditionItem) {
|
||||
this.condition.selected =
|
||||
ConditionSelected.fromConditionItem(conditionValue);
|
||||
}
|
||||
|
||||
public updateRightOperator(value: ConditionOption) {
|
||||
this.condition.selected.setValue(value);
|
||||
}
|
||||
|
||||
public updateRightOptions(options: ConditionOption[]) {
|
||||
this.condition.selected.setOptions(options);
|
||||
}
|
||||
|
||||
public updateRightLoadingState(loading: boolean) {
|
||||
if (loading) {
|
||||
this.condition.selected.enableLoading();
|
||||
return;
|
||||
}
|
||||
|
||||
this.condition.selected.disableLoading();
|
||||
}
|
||||
|
||||
public isEmpty() {
|
||||
return this.value.type === "e";
|
||||
}
|
||||
|
||||
public isStatic() {
|
||||
return ConditionOptions.isStaticName(this.value.type);
|
||||
}
|
||||
|
||||
public isAttribute() {
|
||||
return ConditionOptions.isAttributeInputType(this.value.type);
|
||||
}
|
||||
|
||||
public isCollection() {
|
||||
return this.value.value === "collection";
|
||||
}
|
||||
|
||||
public isCategory() {
|
||||
return this.value.value === "category";
|
||||
}
|
||||
|
||||
public isProductType() {
|
||||
return this.value.value === "producttype";
|
||||
}
|
||||
|
||||
public isChannel() {
|
||||
return this.value.value === "channel";
|
||||
}
|
||||
|
||||
public asUrlEntry(): UrlEntry {
|
||||
const { conditionValue } = this.condition.selected;
|
||||
const conditionIndex = CONDITIONS.findIndex(
|
||||
el => conditionValue && el === conditionValue.label,
|
||||
);
|
||||
|
||||
if (this.isAttribute()) {
|
||||
return {
|
||||
[`a${conditionIndex}.${this.value.value}`]: createAttributeEntry(
|
||||
this.condition.selected.value,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
[`s${conditionIndex}.${this.value.value}`]: createStaticEntry(
|
||||
this.condition.selected.value,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
public static fromValueEntry(valueEntry: any) {
|
||||
return new FilterElement(valueEntry.value, valueEntry.condition, false);
|
||||
}
|
||||
|
||||
public static createEmpty() {
|
||||
return new FilterElement(
|
||||
{ value: "", label: "", type: "s" },
|
||||
Condition.createEmpty(),
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
public static fromUrlToken(token: UrlToken, response: InitialStateResponse) {
|
||||
if (token.isStatic()) {
|
||||
return new FilterElement(
|
||||
{ value: token.name, label: token.name, type: token.name },
|
||||
Condition.fromUrlToken(token, response),
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
if (token.isAttribute()) {
|
||||
const attribute = response.attributeByName(token.name);
|
||||
|
||||
return new FilterElement(
|
||||
{
|
||||
value: token.name,
|
||||
label: attribute.label,
|
||||
type: attribute.inputType,
|
||||
},
|
||||
Condition.fromUrlToken(token, response),
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
2
src/components/ConditionalFilter/FilterElement/index.ts
Normal file
2
src/components/ConditionalFilter/FilterElement/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
|||
export { FilterElement } from "./FilterElement"
|
||||
export { Condition } from "./Condition"
|
7
src/components/ConditionalFilter/FilterValueProvider.ts
Normal file
7
src/components/ConditionalFilter/FilterValueProvider.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { FilterContainer } from "./useFilterContainer";
|
||||
|
||||
export interface FilterValueProvider {
|
||||
value: FilterContainer;
|
||||
loading: boolean;
|
||||
persist: (newValue: FilterContainer) => void;
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
// @ts-strict-ignore
|
||||
import { UrlToken } from "../UrlToken";
|
||||
|
||||
export interface FetchingParams {
|
||||
category: string[];
|
||||
collection: string[];
|
||||
channel: string[];
|
||||
producttype: [];
|
||||
attribute: Record<string, string[]>;
|
||||
}
|
||||
|
||||
export const emptyFetchingParams: FetchingParams = {
|
||||
category: [],
|
||||
collection: [],
|
||||
channel: [],
|
||||
producttype: [],
|
||||
attribute: {},
|
||||
};
|
||||
|
||||
const unique = <T>(array: Iterable<T>) => Array.from(new Set(array));
|
||||
|
||||
export const toFetchingParams = (p: FetchingParams, c: UrlToken) => {
|
||||
if (!c.isAttribute() && !p[c.name]) {
|
||||
p[c.name] = [];
|
||||
}
|
||||
|
||||
if (c.isAttribute() && !p.attribute[c.name]) {
|
||||
p.attribute[c.name] = [];
|
||||
}
|
||||
|
||||
if (c.isAttribute()) {
|
||||
p.attribute[c.name] = unique(p.attribute[c.name].concat(c.value));
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
p[c.name] = unique(p[c.name].concat(c.value));
|
||||
|
||||
return p;
|
||||
};
|
|
@ -0,0 +1,106 @@
|
|||
// @ts-strict-ignore
|
||||
|
||||
import { parse, ParsedQs } from "qs";
|
||||
import { useRef } from "react";
|
||||
|
||||
import { InitialStateResponse } from "../../API/InitialStateResponse";
|
||||
import { FilterElement } from "../../FilterElement";
|
||||
import { FilterContainer } from "../../useFilterContainer";
|
||||
import { UrlToken } from "../UrlToken";
|
||||
import {
|
||||
emptyFetchingParams,
|
||||
FetchingParams,
|
||||
toFetchingParams,
|
||||
} from "./fetchingParams";
|
||||
|
||||
const toFlatUrlTokens = (p: UrlToken[], c: TokenArray[number]) => {
|
||||
if (typeof c == "string") {
|
||||
return p;
|
||||
}
|
||||
|
||||
if (Array.isArray(c)) {
|
||||
return p.concat(flatenate(c));
|
||||
}
|
||||
|
||||
return p.concat(c);
|
||||
};
|
||||
|
||||
const flatenate = (tokens: TokenArray): UrlToken[] =>
|
||||
tokens.reduce<UrlToken[]>(toFlatUrlTokens, []);
|
||||
|
||||
const mapToTokens = (urlEntries: Array<ParsedQs | string>): TokenArray =>
|
||||
urlEntries.map(entry => {
|
||||
if (typeof entry === "string") {
|
||||
return entry;
|
||||
}
|
||||
|
||||
if (Array.isArray(entry)) {
|
||||
return mapToTokens(entry);
|
||||
}
|
||||
|
||||
return UrlToken.fromUrlEntry(entry);
|
||||
}) as TokenArray;
|
||||
|
||||
const tokenizeUrl = (urlParams: string) => {
|
||||
const parsedUrl = Object.values(parse(urlParams)) as Array<ParsedQs | string>;
|
||||
|
||||
return mapToTokens(parsedUrl);
|
||||
};
|
||||
|
||||
const mapUrlTokensToFilterValues = (
|
||||
urlTokens: TokenArray,
|
||||
response: InitialStateResponse,
|
||||
) =>
|
||||
urlTokens.map(el => {
|
||||
if (typeof el === "string") {
|
||||
return el;
|
||||
}
|
||||
|
||||
if (Array.isArray(el)) {
|
||||
return mapUrlTokensToFilterValues(el, response);
|
||||
}
|
||||
|
||||
return FilterElement.fromUrlToken(el, response);
|
||||
});
|
||||
|
||||
export class TokenArray extends Array<string | UrlToken | TokenArray> {
|
||||
constructor(url: string) {
|
||||
super(...tokenizeUrl(url));
|
||||
}
|
||||
|
||||
public getFetchingParams() {
|
||||
return this.asFlatArray()
|
||||
.filter(token => token.isLoadable())
|
||||
.reduce<FetchingParams>(toFetchingParams, emptyFetchingParams);
|
||||
}
|
||||
|
||||
public asFlatArray() {
|
||||
return flatenate(this);
|
||||
}
|
||||
|
||||
public asFilterValuesFromResponse(
|
||||
response: InitialStateResponse,
|
||||
): FilterContainer {
|
||||
return this.map(el => {
|
||||
if (typeof el === "string") {
|
||||
return el;
|
||||
}
|
||||
|
||||
if (Array.isArray(el)) {
|
||||
return mapUrlTokensToFilterValues(el, response);
|
||||
}
|
||||
|
||||
return FilterElement.fromUrlToken(el, response);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const useTokenArray = (url: string) => {
|
||||
const instance = useRef<TokenArray>(null);
|
||||
|
||||
if (!instance.current) {
|
||||
instance.current = new TokenArray(url);
|
||||
}
|
||||
|
||||
return instance.current;
|
||||
};
|
47
src/components/ConditionalFilter/ValueProvider/UrlToken.ts
Normal file
47
src/components/ConditionalFilter/ValueProvider/UrlToken.ts
Normal file
|
@ -0,0 +1,47 @@
|
|||
// @ts-strict-ignore
|
||||
|
||||
export const CONDITIONS = ["is", "equals", "in", "between", "lower", "greater"];
|
||||
|
||||
const STATIC_TO_LOAD = ["category", "collection", "channel", "producttype"];
|
||||
|
||||
type TokenType = "a" | "s";
|
||||
|
||||
// export type UrlEntry = Record<string, string | string[]>
|
||||
|
||||
export class UrlEntry {
|
||||
constructor(key: string, value: string | string[]) {
|
||||
this[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
export class UrlToken {
|
||||
private constructor(
|
||||
public name: string,
|
||||
public value: string | string[],
|
||||
public type: TokenType,
|
||||
public conditionKind: string,
|
||||
) {}
|
||||
|
||||
public static fromUrlEntry(entry: UrlEntry) {
|
||||
const [key, value] = Object.entries(entry)[0] as [
|
||||
string,
|
||||
string | string[],
|
||||
];
|
||||
const [identifier, entryName] = key.split(".");
|
||||
const [type, control] = identifier.split("") as [TokenType, string];
|
||||
|
||||
return new UrlToken(entryName, value, type, CONDITIONS[control]);
|
||||
}
|
||||
|
||||
public isStatic() {
|
||||
return this.type === "s";
|
||||
}
|
||||
|
||||
public isAttribute() {
|
||||
return this.type === "a";
|
||||
}
|
||||
|
||||
public isLoadable() {
|
||||
return STATIC_TO_LOAD.includes(this.name) || this.isAttribute();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
// @ts-strict-ignore
|
||||
|
||||
import { stringify } from "qs";
|
||||
import useRouter from "use-react-router";
|
||||
|
||||
import { useInitialAPIState } from "../API/getInitalAPIState";
|
||||
import { FilterValueProvider } from "../FilterValueProvider";
|
||||
import { FilterContainer } from "../useFilterContainer";
|
||||
import { useTokenArray } from "./TokenArray";
|
||||
|
||||
const prepareStructure = filterValue =>
|
||||
filterValue.map(f => {
|
||||
if (typeof f === "string") {
|
||||
return f;
|
||||
}
|
||||
|
||||
if (Array.isArray(f)) {
|
||||
return prepareStructure(f);
|
||||
}
|
||||
|
||||
return f.asUrlEntry();
|
||||
});
|
||||
|
||||
/*
|
||||
exampple url: http://localhost:9000/dashboard/products/?0%5Bs2.category%5D%5B0%5D=accessories&0%5Bs2.category%5D%5B1%5D=groceries&1=o&2%5Ba2.abv%5D%5B0%5D=QXR0cmlidXRlVmFsdWU6Njg%3D&3=a&4%5Bs2.collection%5D%5B0%5D=featured-products&5=a&6%5Bs2.producttype%5D%5B0%5D=beer&7=a&8%5B0%5D%5Bs2.category%5D%5B0%5D=apparel&8%5B1%5D=o&8%5B2%5D%5Ba2.bottle-size%5D%5B0%5D=QXR0cmlidXRlVmFsdWU6NDY%3D&8%5B2%5D%5Ba2.bottle-size%5D%5B1%5D=QXR0cmlidXRlVmFsdWU6NDc%3D&asc=true&sort=name
|
||||
*/
|
||||
export const useUrlValueProvider = (): FilterValueProvider => {
|
||||
const router = useRouter();
|
||||
const params = new URLSearchParams(router.location.search);
|
||||
params.delete("asc");
|
||||
params.delete("sort");
|
||||
|
||||
const tokenizedUrl = useTokenArray(params.toString());
|
||||
const fetchingParams = tokenizedUrl.getFetchingParams();
|
||||
const { data, loading } = useInitialAPIState(fetchingParams);
|
||||
const value = loading ? [] : tokenizedUrl.asFilterValuesFromResponse(data);
|
||||
|
||||
|
||||
const persist = (filterValue: FilterContainer) => {
|
||||
router.history.replace({
|
||||
pathname: router.location.pathname,
|
||||
search: stringify(prepareStructure(filterValue)),
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
value,
|
||||
loading,
|
||||
persist,
|
||||
};
|
||||
};
|
30
src/components/ConditionalFilter/constants.ts
Normal file
30
src/components/ConditionalFilter/constants.ts
Normal file
|
@ -0,0 +1,30 @@
|
|||
export const STATIC_CONDITIONS = {
|
||||
category: [
|
||||
{ type: "combobox", label: "is", value: "input-1" },
|
||||
{ type: "multiselect", label: "in", value: "input-2" },
|
||||
],
|
||||
price: [
|
||||
{ type: "number", label: "is", value: "input-1" },
|
||||
{ type: "number", label: "lower", value: "input-2" },
|
||||
{ type: "number", label: "greater", value: "input-3" },
|
||||
{ type: "number.range", label: "between", value: "input-4" },
|
||||
],
|
||||
collection: [{ type: "multiselect", label: "in", value: "input-4" }],
|
||||
producttype: [{ type: "multiselect", label: "in", value: "input-4" }],
|
||||
channel: [{ type: "select", label: "is", value: "input-5" }],
|
||||
};
|
||||
|
||||
export const ATTRIBUTE_INPUT_TYPE_CONDITIONS = {
|
||||
DROPDOWN: [{ type: "multiselect", label: "in", value: "input-2" }],
|
||||
MULTISELECT: [{ type: "multiselect", label: "in", value: "input-2" }],
|
||||
BOOLEAN: [{ type: "select", label: "is", value: "input-5" }],
|
||||
NUMERIC: [
|
||||
{ type: "number", label: "is", value: "input-1" },
|
||||
{ type: "number", label: "lower", value: "input-2" },
|
||||
{ type: "number", label: "greater", value: "input-3" },
|
||||
{ type: "number.range", label: "between", value: "input-4" },
|
||||
],
|
||||
DATE_TIME: [{ type: "date", label: "is", value: "input-1" }],
|
||||
DATE: [{ type: "date", label: "is", value: "input-1" }],
|
||||
SWATCH: [{ type: "multiselect", label: "in", value: "input-2" }],
|
||||
};
|
14
src/components/ConditionalFilter/controlsType.ts
Normal file
14
src/components/ConditionalFilter/controlsType.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
// @ts-strict-ignore
|
||||
import { ConditionOption } from "./FilterElement/ConditionSelected";
|
||||
|
||||
export const CONTROL_DEFAULTS = {
|
||||
text: "",
|
||||
number: "",
|
||||
"number.range": [] as unknown as [string, string],
|
||||
multiselect: [] as ConditionOption[],
|
||||
select: "",
|
||||
combobox: "",
|
||||
};
|
||||
|
||||
export const getDefaultByControlName = (name: string): ConditionOption =>
|
||||
CONTROL_DEFAULTS[name];
|
142
src/components/ConditionalFilter/index.tsx
Normal file
142
src/components/ConditionalFilter/index.tsx
Normal file
|
@ -0,0 +1,142 @@
|
|||
// @ts-strict-ignore
|
||||
import { useApolloClient } from "@apollo/client";
|
||||
import useDebounce from "@dashboard/hooks/useDebounce";
|
||||
import { _ExperimentalFilters, Box, Text } from "@saleor/macaw-ui/next";
|
||||
import React from "react";
|
||||
|
||||
import {
|
||||
getInitialRightOperatorOptions,
|
||||
getLeftOperatorOptions,
|
||||
getRightOperatorOptionsByQuery,
|
||||
} from "./API/getAPIOptions";
|
||||
import { useFilterContainer } from "./useFilterContainer";
|
||||
import { useLeftOperands } from "./useLeftOperands";
|
||||
import { useUrlValueProvider } from "./ValueProvider/useUrlValueProvider";
|
||||
|
||||
const FiltersArea = ({ provider, onConfirm }) => {
|
||||
const client = useApolloClient();
|
||||
|
||||
const {
|
||||
value,
|
||||
addEmpty,
|
||||
removeAt,
|
||||
updateLeftOperator,
|
||||
updateRightOperator,
|
||||
updateCondition,
|
||||
updateRightOptions,
|
||||
updateRightLoadingState,
|
||||
updateLeftLoadingState,
|
||||
} = useFilterContainer(provider);
|
||||
|
||||
const { operands, setOperands } = useLeftOperands();
|
||||
|
||||
const handleLeftOperatorInputValueChange = (event: any) => {
|
||||
const fetchAPI = async () => {
|
||||
const options = await getLeftOperatorOptions(client, event.value);
|
||||
setOperands(options);
|
||||
};
|
||||
updateLeftLoadingState(event.path, true);
|
||||
fetchAPI();
|
||||
updateLeftLoadingState(event.path, false);
|
||||
};
|
||||
|
||||
const handleLeftOperatorInputValueChangeDebounced = useDebounce(
|
||||
handleLeftOperatorInputValueChange,
|
||||
500,
|
||||
);
|
||||
|
||||
const handleRightOperatorInputValueChange = (event: any) => {
|
||||
const fetchAPI = async () => {
|
||||
const options = await getRightOperatorOptionsByQuery(
|
||||
client,
|
||||
event.path.split(".")[0],
|
||||
value,
|
||||
event.value,
|
||||
);
|
||||
updateRightOptions(event.path.split(".")[0], options);
|
||||
};
|
||||
updateRightLoadingState(event.path.split(".")[0], true);
|
||||
fetchAPI();
|
||||
updateRightLoadingState(event.path.split(".")[0], false);
|
||||
};
|
||||
|
||||
const handleRightOperatorInputValueChangeDebounced = useDebounce(
|
||||
handleRightOperatorInputValueChange,
|
||||
500,
|
||||
);
|
||||
|
||||
const handleStateChange = async event => {
|
||||
if (event.type === "row.add") {
|
||||
addEmpty();
|
||||
}
|
||||
|
||||
if (event.type === "row.remove") {
|
||||
removeAt(event.path);
|
||||
}
|
||||
|
||||
if (event.type === "leftOperator.onChange") {
|
||||
updateLeftOperator(event.path, event.value);
|
||||
}
|
||||
|
||||
if (event.type === "condition.onChange") {
|
||||
updateCondition(event.path.split(".")[0], event.value);
|
||||
}
|
||||
|
||||
if (event.type === "rightOperator.onChange") {
|
||||
updateRightOperator(event.path.split(".")[0], event.value);
|
||||
}
|
||||
|
||||
if (event.type === "rightOperator.onFocus") {
|
||||
const path = event.path.split(".")[0];
|
||||
updateRightLoadingState(path, true);
|
||||
const options = await getInitialRightOperatorOptions(client, path, value);
|
||||
updateRightOptions(path, options);
|
||||
updateRightLoadingState(path, false);
|
||||
}
|
||||
|
||||
if (event.type === "rightOperator.onInputValueChange") {
|
||||
handleRightOperatorInputValueChangeDebounced(event);
|
||||
}
|
||||
|
||||
if (event.type === "leftOperator.onInputValueChange") {
|
||||
handleLeftOperatorInputValueChangeDebounced(event);
|
||||
}
|
||||
};
|
||||
|
||||
const handleConfirm = () => onConfirm(value);
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<_ExperimentalFilters
|
||||
leftOptions={operands}
|
||||
// @ts-ignore
|
||||
value={value}
|
||||
onChange={handleStateChange}
|
||||
>
|
||||
<_ExperimentalFilters.Footer>
|
||||
<_ExperimentalFilters.AddRowButton>
|
||||
Add new row
|
||||
</_ExperimentalFilters.AddRowButton>
|
||||
<_ExperimentalFilters.ConfirmButton onClick={handleConfirm}>
|
||||
Confirm
|
||||
</_ExperimentalFilters.ConfirmButton>
|
||||
</_ExperimentalFilters.Footer>
|
||||
</_ExperimentalFilters>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export const ConditionalFilters = () => {
|
||||
const provider = useUrlValueProvider();
|
||||
|
||||
return (
|
||||
<Box>
|
||||
{provider.loading ? (
|
||||
<Text>Loading...</Text>
|
||||
) : (
|
||||
// @ts-ignore
|
||||
<FiltersArea provider={provider.value} onConfirm={provider.persist} />
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
};
|
125
src/components/ConditionalFilter/useFilterContainer.ts
Normal file
125
src/components/ConditionalFilter/useFilterContainer.ts
Normal file
|
@ -0,0 +1,125 @@
|
|||
// @ts-strict-ignore
|
||||
import { useState } from "react";
|
||||
|
||||
import { FilterElement } from "./FilterElement";
|
||||
|
||||
export type FilterContainer = Array<string | FilterElement | FilterContainer>;
|
||||
|
||||
export const useFilterContainer = (initialValue: FilterContainer) => {
|
||||
const [value, setValue] = useState(initialValue);
|
||||
|
||||
const addEmpty = () => {
|
||||
const newValue = [];
|
||||
if (value.length > 0) {
|
||||
newValue.push("OR");
|
||||
}
|
||||
|
||||
newValue.push(FilterElement.createEmpty());
|
||||
|
||||
setValue(v => v.concat(newValue));
|
||||
};
|
||||
|
||||
const removeAt = (position: string) => {
|
||||
const index = parseInt(position, 10);
|
||||
|
||||
if (value.length > 0) {
|
||||
setValue(v =>
|
||||
v.filter((_, elIndex) => ![index - 1, index].includes(elIndex)),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
setValue(v => v.filter((_, elIndex) => ![index].includes(elIndex)));
|
||||
};
|
||||
|
||||
const updateLeftOperator = (position: string, leftOperator: any) => {
|
||||
const index = parseInt(position, 10);
|
||||
setValue(v =>
|
||||
v.map((el, elIndex) => {
|
||||
if (elIndex === index && typeof el != "string" && !Array.isArray(el)) {
|
||||
el.updateLeftOperator(leftOperator);
|
||||
}
|
||||
|
||||
return el;
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const updateLeftLoadingState = (position: string, loading: boolean) => {
|
||||
const index = parseInt(position, 10);
|
||||
setValue(v =>
|
||||
v.map((el, elIndex) => {
|
||||
if (elIndex === index && typeof el != "string" && !Array.isArray(el)) {
|
||||
el.updateLeftLoadingState(loading);
|
||||
}
|
||||
|
||||
return el;
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const updateRightOperator = (position: string, leftOperator: any) => {
|
||||
const index = parseInt(position, 10);
|
||||
setValue(v =>
|
||||
v.map((el, elIndex) => {
|
||||
if (elIndex === index && typeof el != "string" && !Array.isArray(el)) {
|
||||
el.updateRightOperator(leftOperator);
|
||||
}
|
||||
|
||||
return el;
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const updateRightOptions = (position: string, options: any) => {
|
||||
const index = parseInt(position, 10);
|
||||
setValue(v =>
|
||||
v.map((el, elIndex) => {
|
||||
if (elIndex === index && typeof el != "string" && !Array.isArray(el)) {
|
||||
el.updateRightOptions(options);
|
||||
}
|
||||
|
||||
return el;
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const updateRightLoadingState = (position: string, loading: boolean) => {
|
||||
const index = parseInt(position, 10);
|
||||
setValue(v =>
|
||||
v.map((el, elIndex) => {
|
||||
if (elIndex === index && typeof el != "string" && !Array.isArray(el)) {
|
||||
el.updateRightLoadingState(loading);
|
||||
}
|
||||
|
||||
return el;
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const updateCondition = (position: string, conditionValue: any) => {
|
||||
const index = parseInt(position, 10);
|
||||
|
||||
setValue(v =>
|
||||
v.map((el, elIndex) => {
|
||||
if (elIndex === index && typeof el != "string" && !Array.isArray(el)) {
|
||||
el.updateCondition(conditionValue);
|
||||
}
|
||||
|
||||
return el;
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
return {
|
||||
value,
|
||||
addEmpty,
|
||||
removeAt,
|
||||
updateLeftOperator,
|
||||
updateRightOperator,
|
||||
updateCondition,
|
||||
updateRightOptions,
|
||||
updateRightLoadingState,
|
||||
updateLeftLoadingState,
|
||||
};
|
||||
};
|
34
src/components/ConditionalFilter/useLeftOperands.ts
Normal file
34
src/components/ConditionalFilter/useLeftOperands.ts
Normal file
|
@ -0,0 +1,34 @@
|
|||
import { useState } from "react";
|
||||
|
||||
import {
|
||||
AttributeInputType,
|
||||
StaticElementName,
|
||||
} from "./FilterElement/ConditionOptions";
|
||||
|
||||
export interface LeftOperand {
|
||||
type: AttributeInputType | StaticElementName;
|
||||
label: string;
|
||||
value: string;
|
||||
slug: string;
|
||||
}
|
||||
|
||||
const STATIC_OPTIONS: LeftOperand[] = [
|
||||
{ value: "price", label: "Price", type: "price", slug: "price" },
|
||||
{ value: "category", label: "Category", type: "category", slug: "category" },
|
||||
{
|
||||
value: "collection",
|
||||
label: "Collection",
|
||||
type: "collection",
|
||||
slug: "collection",
|
||||
},
|
||||
{ value: "channel", label: "Channel", type: "channel", slug: "channel" },
|
||||
];
|
||||
|
||||
export const useLeftOperands = () => {
|
||||
const [operands, setOperands] = useState<LeftOperand[]>(STATIC_OPTIONS);
|
||||
|
||||
return {
|
||||
operands,
|
||||
setOperands,
|
||||
};
|
||||
};
|
|
@ -24,16 +24,10 @@ const AVAILABLE_FLAGS = [
|
|||
*/
|
||||
|
||||
{
|
||||
name: "flag1",
|
||||
displayName: "Flag 1",
|
||||
description: "some description",
|
||||
content: { enabled: false, payload: "default" },
|
||||
} as const,
|
||||
{
|
||||
name: "flag2",
|
||||
displayName: "Flag 2",
|
||||
description: "some description 2",
|
||||
content: { enabled: false, payload: "default2" },
|
||||
name: "product_filters",
|
||||
displayName: "Product filters",
|
||||
description: "New filters on product listing page",
|
||||
content: { enabled: false, payload: "" },
|
||||
} as const,
|
||||
] satisfies FlagDefinition[];
|
||||
|
||||
|
|
|
@ -5417,6 +5417,445 @@ export function useAddressValidationRulesLazyQuery(baseOptions?: ApolloReactHook
|
|||
export type AddressValidationRulesQueryHookResult = ReturnType<typeof useAddressValidationRulesQuery>;
|
||||
export type AddressValidationRulesLazyQueryHookResult = ReturnType<typeof useAddressValidationRulesLazyQuery>;
|
||||
export type AddressValidationRulesQueryResult = Apollo.QueryResult<Types.AddressValidationRulesQuery, Types.AddressValidationRulesQueryVariables>;
|
||||
export const _GetDynamicLeftOperandsDocument = gql`
|
||||
query _GetDynamicLeftOperands($first: Int!, $query: String!) {
|
||||
attributes(first: $first, filter: {type: PRODUCT_TYPE, search: $query}) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
name
|
||||
slug
|
||||
inputType
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __use_GetDynamicLeftOperandsQuery__
|
||||
*
|
||||
* To run a query within a React component, call `use_GetDynamicLeftOperandsQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `use_GetDynamicLeftOperandsQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||
* you can use to render your UI.
|
||||
*
|
||||
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||
*
|
||||
* @example
|
||||
* const { data, loading, error } = use_GetDynamicLeftOperandsQuery({
|
||||
* variables: {
|
||||
* first: // value for 'first'
|
||||
* query: // value for 'query'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function use_GetDynamicLeftOperandsQuery(baseOptions: ApolloReactHooks.QueryHookOptions<Types._GetDynamicLeftOperandsQuery, Types._GetDynamicLeftOperandsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return ApolloReactHooks.useQuery<Types._GetDynamicLeftOperandsQuery, Types._GetDynamicLeftOperandsQueryVariables>(_GetDynamicLeftOperandsDocument, options);
|
||||
}
|
||||
export function use_GetDynamicLeftOperandsLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<Types._GetDynamicLeftOperandsQuery, Types._GetDynamicLeftOperandsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return ApolloReactHooks.useLazyQuery<Types._GetDynamicLeftOperandsQuery, Types._GetDynamicLeftOperandsQueryVariables>(_GetDynamicLeftOperandsDocument, options);
|
||||
}
|
||||
export type _GetDynamicLeftOperandsQueryHookResult = ReturnType<typeof use_GetDynamicLeftOperandsQuery>;
|
||||
export type _GetDynamicLeftOperandsLazyQueryHookResult = ReturnType<typeof use_GetDynamicLeftOperandsLazyQuery>;
|
||||
export type _GetDynamicLeftOperandsQueryResult = Apollo.QueryResult<Types._GetDynamicLeftOperandsQuery, Types._GetDynamicLeftOperandsQueryVariables>;
|
||||
export const _GetChannelOperandsDocument = gql`
|
||||
query _GetChannelOperands {
|
||||
channels {
|
||||
id
|
||||
name
|
||||
slug
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __use_GetChannelOperandsQuery__
|
||||
*
|
||||
* To run a query within a React component, call `use_GetChannelOperandsQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `use_GetChannelOperandsQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||
* you can use to render your UI.
|
||||
*
|
||||
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||
*
|
||||
* @example
|
||||
* const { data, loading, error } = use_GetChannelOperandsQuery({
|
||||
* variables: {
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function use_GetChannelOperandsQuery(baseOptions?: ApolloReactHooks.QueryHookOptions<Types._GetChannelOperandsQuery, Types._GetChannelOperandsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return ApolloReactHooks.useQuery<Types._GetChannelOperandsQuery, Types._GetChannelOperandsQueryVariables>(_GetChannelOperandsDocument, options);
|
||||
}
|
||||
export function use_GetChannelOperandsLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<Types._GetChannelOperandsQuery, Types._GetChannelOperandsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return ApolloReactHooks.useLazyQuery<Types._GetChannelOperandsQuery, Types._GetChannelOperandsQueryVariables>(_GetChannelOperandsDocument, options);
|
||||
}
|
||||
export type _GetChannelOperandsQueryHookResult = ReturnType<typeof use_GetChannelOperandsQuery>;
|
||||
export type _GetChannelOperandsLazyQueryHookResult = ReturnType<typeof use_GetChannelOperandsLazyQuery>;
|
||||
export type _GetChannelOperandsQueryResult = Apollo.QueryResult<Types._GetChannelOperandsQuery, Types._GetChannelOperandsQueryVariables>;
|
||||
export const _SearchCollectionsOperandsDocument = gql`
|
||||
query _SearchCollectionsOperands($first: Int!, $collectionsSlugs: [String!]) {
|
||||
search: collections(first: $first, filter: {slugs: $collectionsSlugs}) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
name
|
||||
slug
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __use_SearchCollectionsOperandsQuery__
|
||||
*
|
||||
* To run a query within a React component, call `use_SearchCollectionsOperandsQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `use_SearchCollectionsOperandsQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||
* you can use to render your UI.
|
||||
*
|
||||
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||
*
|
||||
* @example
|
||||
* const { data, loading, error } = use_SearchCollectionsOperandsQuery({
|
||||
* variables: {
|
||||
* first: // value for 'first'
|
||||
* collectionsSlugs: // value for 'collectionsSlugs'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function use_SearchCollectionsOperandsQuery(baseOptions: ApolloReactHooks.QueryHookOptions<Types._SearchCollectionsOperandsQuery, Types._SearchCollectionsOperandsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return ApolloReactHooks.useQuery<Types._SearchCollectionsOperandsQuery, Types._SearchCollectionsOperandsQueryVariables>(_SearchCollectionsOperandsDocument, options);
|
||||
}
|
||||
export function use_SearchCollectionsOperandsLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<Types._SearchCollectionsOperandsQuery, Types._SearchCollectionsOperandsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return ApolloReactHooks.useLazyQuery<Types._SearchCollectionsOperandsQuery, Types._SearchCollectionsOperandsQueryVariables>(_SearchCollectionsOperandsDocument, options);
|
||||
}
|
||||
export type _SearchCollectionsOperandsQueryHookResult = ReturnType<typeof use_SearchCollectionsOperandsQuery>;
|
||||
export type _SearchCollectionsOperandsLazyQueryHookResult = ReturnType<typeof use_SearchCollectionsOperandsLazyQuery>;
|
||||
export type _SearchCollectionsOperandsQueryResult = Apollo.QueryResult<Types._SearchCollectionsOperandsQuery, Types._SearchCollectionsOperandsQueryVariables>;
|
||||
export const _SearchCategoriesOperandsDocument = gql`
|
||||
query _SearchCategoriesOperands($after: String, $first: Int!, $categoriesSlugs: [String!]) {
|
||||
search: categories(
|
||||
after: $after
|
||||
first: $first
|
||||
filter: {slugs: $categoriesSlugs}
|
||||
) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
name
|
||||
slug
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __use_SearchCategoriesOperandsQuery__
|
||||
*
|
||||
* To run a query within a React component, call `use_SearchCategoriesOperandsQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `use_SearchCategoriesOperandsQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||
* you can use to render your UI.
|
||||
*
|
||||
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||
*
|
||||
* @example
|
||||
* const { data, loading, error } = use_SearchCategoriesOperandsQuery({
|
||||
* variables: {
|
||||
* after: // value for 'after'
|
||||
* first: // value for 'first'
|
||||
* categoriesSlugs: // value for 'categoriesSlugs'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function use_SearchCategoriesOperandsQuery(baseOptions: ApolloReactHooks.QueryHookOptions<Types._SearchCategoriesOperandsQuery, Types._SearchCategoriesOperandsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return ApolloReactHooks.useQuery<Types._SearchCategoriesOperandsQuery, Types._SearchCategoriesOperandsQueryVariables>(_SearchCategoriesOperandsDocument, options);
|
||||
}
|
||||
export function use_SearchCategoriesOperandsLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<Types._SearchCategoriesOperandsQuery, Types._SearchCategoriesOperandsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return ApolloReactHooks.useLazyQuery<Types._SearchCategoriesOperandsQuery, Types._SearchCategoriesOperandsQueryVariables>(_SearchCategoriesOperandsDocument, options);
|
||||
}
|
||||
export type _SearchCategoriesOperandsQueryHookResult = ReturnType<typeof use_SearchCategoriesOperandsQuery>;
|
||||
export type _SearchCategoriesOperandsLazyQueryHookResult = ReturnType<typeof use_SearchCategoriesOperandsLazyQuery>;
|
||||
export type _SearchCategoriesOperandsQueryResult = Apollo.QueryResult<Types._SearchCategoriesOperandsQuery, Types._SearchCategoriesOperandsQueryVariables>;
|
||||
export const _SearchProductTypesOperandsDocument = gql`
|
||||
query _SearchProductTypesOperands($after: String, $first: Int!, $productTypesSlugs: [String!]) {
|
||||
search: productTypes(
|
||||
after: $after
|
||||
first: $first
|
||||
filter: {slugs: $productTypesSlugs}
|
||||
) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
name
|
||||
slug
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __use_SearchProductTypesOperandsQuery__
|
||||
*
|
||||
* To run a query within a React component, call `use_SearchProductTypesOperandsQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `use_SearchProductTypesOperandsQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||
* you can use to render your UI.
|
||||
*
|
||||
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||
*
|
||||
* @example
|
||||
* const { data, loading, error } = use_SearchProductTypesOperandsQuery({
|
||||
* variables: {
|
||||
* after: // value for 'after'
|
||||
* first: // value for 'first'
|
||||
* productTypesSlugs: // value for 'productTypesSlugs'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function use_SearchProductTypesOperandsQuery(baseOptions: ApolloReactHooks.QueryHookOptions<Types._SearchProductTypesOperandsQuery, Types._SearchProductTypesOperandsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return ApolloReactHooks.useQuery<Types._SearchProductTypesOperandsQuery, Types._SearchProductTypesOperandsQueryVariables>(_SearchProductTypesOperandsDocument, options);
|
||||
}
|
||||
export function use_SearchProductTypesOperandsLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<Types._SearchProductTypesOperandsQuery, Types._SearchProductTypesOperandsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return ApolloReactHooks.useLazyQuery<Types._SearchProductTypesOperandsQuery, Types._SearchProductTypesOperandsQueryVariables>(_SearchProductTypesOperandsDocument, options);
|
||||
}
|
||||
export type _SearchProductTypesOperandsQueryHookResult = ReturnType<typeof use_SearchProductTypesOperandsQuery>;
|
||||
export type _SearchProductTypesOperandsLazyQueryHookResult = ReturnType<typeof use_SearchProductTypesOperandsLazyQuery>;
|
||||
export type _SearchProductTypesOperandsQueryResult = Apollo.QueryResult<Types._SearchProductTypesOperandsQuery, Types._SearchProductTypesOperandsQueryVariables>;
|
||||
export const _SearchAttributeOperandsDocument = gql`
|
||||
query _SearchAttributeOperands($attributesSlugs: [String!], $choicesIds: [ID!], $first: Int!) {
|
||||
search: attributes(first: $first, filter: {slugs: $attributesSlugs}) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
name
|
||||
slug
|
||||
inputType
|
||||
choices(first: 5, filter: {ids: $choicesIds}) {
|
||||
edges {
|
||||
node {
|
||||
slug: id
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __use_SearchAttributeOperandsQuery__
|
||||
*
|
||||
* To run a query within a React component, call `use_SearchAttributeOperandsQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `use_SearchAttributeOperandsQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||
* you can use to render your UI.
|
||||
*
|
||||
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||
*
|
||||
* @example
|
||||
* const { data, loading, error } = use_SearchAttributeOperandsQuery({
|
||||
* variables: {
|
||||
* attributesSlugs: // value for 'attributesSlugs'
|
||||
* choicesIds: // value for 'choicesIds'
|
||||
* first: // value for 'first'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function use_SearchAttributeOperandsQuery(baseOptions: ApolloReactHooks.QueryHookOptions<Types._SearchAttributeOperandsQuery, Types._SearchAttributeOperandsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return ApolloReactHooks.useQuery<Types._SearchAttributeOperandsQuery, Types._SearchAttributeOperandsQueryVariables>(_SearchAttributeOperandsDocument, options);
|
||||
}
|
||||
export function use_SearchAttributeOperandsLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<Types._SearchAttributeOperandsQuery, Types._SearchAttributeOperandsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return ApolloReactHooks.useLazyQuery<Types._SearchAttributeOperandsQuery, Types._SearchAttributeOperandsQueryVariables>(_SearchAttributeOperandsDocument, options);
|
||||
}
|
||||
export type _SearchAttributeOperandsQueryHookResult = ReturnType<typeof use_SearchAttributeOperandsQuery>;
|
||||
export type _SearchAttributeOperandsLazyQueryHookResult = ReturnType<typeof use_SearchAttributeOperandsLazyQuery>;
|
||||
export type _SearchAttributeOperandsQueryResult = Apollo.QueryResult<Types._SearchAttributeOperandsQuery, Types._SearchAttributeOperandsQueryVariables>;
|
||||
export const _GetAttributeChoicesDocument = gql`
|
||||
query _GetAttributeChoices($slug: String!, $first: Int!, $query: String!) {
|
||||
attribute(slug: $slug) {
|
||||
choices(first: $first, filter: {search: $query}) {
|
||||
edges {
|
||||
node {
|
||||
slug: id
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __use_GetAttributeChoicesQuery__
|
||||
*
|
||||
* To run a query within a React component, call `use_GetAttributeChoicesQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `use_GetAttributeChoicesQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||
* you can use to render your UI.
|
||||
*
|
||||
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||
*
|
||||
* @example
|
||||
* const { data, loading, error } = use_GetAttributeChoicesQuery({
|
||||
* variables: {
|
||||
* slug: // value for 'slug'
|
||||
* first: // value for 'first'
|
||||
* query: // value for 'query'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function use_GetAttributeChoicesQuery(baseOptions: ApolloReactHooks.QueryHookOptions<Types._GetAttributeChoicesQuery, Types._GetAttributeChoicesQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return ApolloReactHooks.useQuery<Types._GetAttributeChoicesQuery, Types._GetAttributeChoicesQueryVariables>(_GetAttributeChoicesDocument, options);
|
||||
}
|
||||
export function use_GetAttributeChoicesLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<Types._GetAttributeChoicesQuery, Types._GetAttributeChoicesQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return ApolloReactHooks.useLazyQuery<Types._GetAttributeChoicesQuery, Types._GetAttributeChoicesQueryVariables>(_GetAttributeChoicesDocument, options);
|
||||
}
|
||||
export type _GetAttributeChoicesQueryHookResult = ReturnType<typeof use_GetAttributeChoicesQuery>;
|
||||
export type _GetAttributeChoicesLazyQueryHookResult = ReturnType<typeof use_GetAttributeChoicesLazyQuery>;
|
||||
export type _GetAttributeChoicesQueryResult = Apollo.QueryResult<Types._GetAttributeChoicesQuery, Types._GetAttributeChoicesQueryVariables>;
|
||||
export const _GetCollectionsChoicesDocument = gql`
|
||||
query _GetCollectionsChoices($first: Int!, $query: String!) {
|
||||
collections(first: $first, filter: {search: $query}) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
name
|
||||
slug
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __use_GetCollectionsChoicesQuery__
|
||||
*
|
||||
* To run a query within a React component, call `use_GetCollectionsChoicesQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `use_GetCollectionsChoicesQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||
* you can use to render your UI.
|
||||
*
|
||||
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||
*
|
||||
* @example
|
||||
* const { data, loading, error } = use_GetCollectionsChoicesQuery({
|
||||
* variables: {
|
||||
* first: // value for 'first'
|
||||
* query: // value for 'query'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function use_GetCollectionsChoicesQuery(baseOptions: ApolloReactHooks.QueryHookOptions<Types._GetCollectionsChoicesQuery, Types._GetCollectionsChoicesQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return ApolloReactHooks.useQuery<Types._GetCollectionsChoicesQuery, Types._GetCollectionsChoicesQueryVariables>(_GetCollectionsChoicesDocument, options);
|
||||
}
|
||||
export function use_GetCollectionsChoicesLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<Types._GetCollectionsChoicesQuery, Types._GetCollectionsChoicesQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return ApolloReactHooks.useLazyQuery<Types._GetCollectionsChoicesQuery, Types._GetCollectionsChoicesQueryVariables>(_GetCollectionsChoicesDocument, options);
|
||||
}
|
||||
export type _GetCollectionsChoicesQueryHookResult = ReturnType<typeof use_GetCollectionsChoicesQuery>;
|
||||
export type _GetCollectionsChoicesLazyQueryHookResult = ReturnType<typeof use_GetCollectionsChoicesLazyQuery>;
|
||||
export type _GetCollectionsChoicesQueryResult = Apollo.QueryResult<Types._GetCollectionsChoicesQuery, Types._GetCollectionsChoicesQueryVariables>;
|
||||
export const _GetCategoriesChoicesDocument = gql`
|
||||
query _GetCategoriesChoices($first: Int!, $query: String!) {
|
||||
categories(first: $first, filter: {search: $query}) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
name
|
||||
slug
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __use_GetCategoriesChoicesQuery__
|
||||
*
|
||||
* To run a query within a React component, call `use_GetCategoriesChoicesQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `use_GetCategoriesChoicesQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||
* you can use to render your UI.
|
||||
*
|
||||
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||
*
|
||||
* @example
|
||||
* const { data, loading, error } = use_GetCategoriesChoicesQuery({
|
||||
* variables: {
|
||||
* first: // value for 'first'
|
||||
* query: // value for 'query'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function use_GetCategoriesChoicesQuery(baseOptions: ApolloReactHooks.QueryHookOptions<Types._GetCategoriesChoicesQuery, Types._GetCategoriesChoicesQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return ApolloReactHooks.useQuery<Types._GetCategoriesChoicesQuery, Types._GetCategoriesChoicesQueryVariables>(_GetCategoriesChoicesDocument, options);
|
||||
}
|
||||
export function use_GetCategoriesChoicesLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<Types._GetCategoriesChoicesQuery, Types._GetCategoriesChoicesQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return ApolloReactHooks.useLazyQuery<Types._GetCategoriesChoicesQuery, Types._GetCategoriesChoicesQueryVariables>(_GetCategoriesChoicesDocument, options);
|
||||
}
|
||||
export type _GetCategoriesChoicesQueryHookResult = ReturnType<typeof use_GetCategoriesChoicesQuery>;
|
||||
export type _GetCategoriesChoicesLazyQueryHookResult = ReturnType<typeof use_GetCategoriesChoicesLazyQuery>;
|
||||
export type _GetCategoriesChoicesQueryResult = Apollo.QueryResult<Types._GetCategoriesChoicesQuery, Types._GetCategoriesChoicesQueryVariables>;
|
||||
export const _GetProductTypesChoicesDocument = gql`
|
||||
query _GetProductTypesChoices($first: Int!, $query: String!) {
|
||||
productTypes(first: $first, filter: {search: $query}) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
name
|
||||
slug
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __use_GetProductTypesChoicesQuery__
|
||||
*
|
||||
* To run a query within a React component, call `use_GetProductTypesChoicesQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `use_GetProductTypesChoicesQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||
* you can use to render your UI.
|
||||
*
|
||||
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||
*
|
||||
* @example
|
||||
* const { data, loading, error } = use_GetProductTypesChoicesQuery({
|
||||
* variables: {
|
||||
* first: // value for 'first'
|
||||
* query: // value for 'query'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function use_GetProductTypesChoicesQuery(baseOptions: ApolloReactHooks.QueryHookOptions<Types._GetProductTypesChoicesQuery, Types._GetProductTypesChoicesQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return ApolloReactHooks.useQuery<Types._GetProductTypesChoicesQuery, Types._GetProductTypesChoicesQueryVariables>(_GetProductTypesChoicesDocument, options);
|
||||
}
|
||||
export function use_GetProductTypesChoicesLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<Types._GetProductTypesChoicesQuery, Types._GetProductTypesChoicesQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return ApolloReactHooks.useLazyQuery<Types._GetProductTypesChoicesQuery, Types._GetProductTypesChoicesQueryVariables>(_GetProductTypesChoicesDocument, options);
|
||||
}
|
||||
export type _GetProductTypesChoicesQueryHookResult = ReturnType<typeof use_GetProductTypesChoicesQuery>;
|
||||
export type _GetProductTypesChoicesLazyQueryHookResult = ReturnType<typeof use_GetProductTypesChoicesLazyQuery>;
|
||||
export type _GetProductTypesChoicesQueryResult = Apollo.QueryResult<Types._GetProductTypesChoicesQuery, Types._GetProductTypesChoicesQueryVariables>;
|
||||
export const TriggerWebhookDryRunDocument = gql`
|
||||
mutation TriggerWebhookDryRun($objectId: ID!, $query: String!) {
|
||||
webhookDryRun(objectId: $objectId, query: $query) {
|
||||
|
|
|
@ -8323,6 +8323,87 @@ export type AddressValidationRulesQueryVariables = Exact<{
|
|||
|
||||
export type AddressValidationRulesQuery = { __typename: 'Query', addressValidationRules: { __typename: 'AddressValidationData', allowedFields: Array<string>, countryAreaChoices: Array<{ __typename: 'ChoiceValue', raw: string | null, verbose: string | null }> } | null };
|
||||
|
||||
export type _GetDynamicLeftOperandsQueryVariables = Exact<{
|
||||
first: Scalars['Int'];
|
||||
query: Scalars['String'];
|
||||
}>;
|
||||
|
||||
|
||||
export type _GetDynamicLeftOperandsQuery = { __typename: 'Query', attributes: { __typename: 'AttributeCountableConnection', edges: Array<{ __typename: 'AttributeCountableEdge', node: { __typename: 'Attribute', id: string, name: string | null, slug: string | null, inputType: AttributeInputTypeEnum | null } }> } | null };
|
||||
|
||||
export type _GetChannelOperandsQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type _GetChannelOperandsQuery = { __typename: 'Query', channels: Array<{ __typename: 'Channel', id: string, name: string, slug: string }> | null };
|
||||
|
||||
export type _SearchCollectionsOperandsQueryVariables = Exact<{
|
||||
first: Scalars['Int'];
|
||||
collectionsSlugs?: InputMaybe<Array<Scalars['String']> | Scalars['String']>;
|
||||
}>;
|
||||
|
||||
|
||||
export type _SearchCollectionsOperandsQuery = { __typename: 'Query', search: { __typename: 'CollectionCountableConnection', edges: Array<{ __typename: 'CollectionCountableEdge', node: { __typename: 'Collection', id: string, name: string, slug: string } }> } | null };
|
||||
|
||||
export type _SearchCategoriesOperandsQueryVariables = Exact<{
|
||||
after?: InputMaybe<Scalars['String']>;
|
||||
first: Scalars['Int'];
|
||||
categoriesSlugs?: InputMaybe<Array<Scalars['String']> | Scalars['String']>;
|
||||
}>;
|
||||
|
||||
|
||||
export type _SearchCategoriesOperandsQuery = { __typename: 'Query', search: { __typename: 'CategoryCountableConnection', edges: Array<{ __typename: 'CategoryCountableEdge', node: { __typename: 'Category', id: string, name: string, slug: string } }> } | null };
|
||||
|
||||
export type _SearchProductTypesOperandsQueryVariables = Exact<{
|
||||
after?: InputMaybe<Scalars['String']>;
|
||||
first: Scalars['Int'];
|
||||
productTypesSlugs?: InputMaybe<Array<Scalars['String']> | Scalars['String']>;
|
||||
}>;
|
||||
|
||||
|
||||
export type _SearchProductTypesOperandsQuery = { __typename: 'Query', search: { __typename: 'ProductTypeCountableConnection', edges: Array<{ __typename: 'ProductTypeCountableEdge', node: { __typename: 'ProductType', id: string, name: string, slug: string } }> } | null };
|
||||
|
||||
export type _SearchAttributeOperandsQueryVariables = Exact<{
|
||||
attributesSlugs?: InputMaybe<Array<Scalars['String']> | Scalars['String']>;
|
||||
choicesIds?: InputMaybe<Array<Scalars['ID']> | Scalars['ID']>;
|
||||
first: Scalars['Int'];
|
||||
}>;
|
||||
|
||||
|
||||
export type _SearchAttributeOperandsQuery = { __typename: 'Query', search: { __typename: 'AttributeCountableConnection', edges: Array<{ __typename: 'AttributeCountableEdge', node: { __typename: 'Attribute', id: string, name: string | null, slug: string | null, inputType: AttributeInputTypeEnum | null, choices: { __typename: 'AttributeValueCountableConnection', edges: Array<{ __typename: 'AttributeValueCountableEdge', node: { __typename: 'AttributeValue', id: string, name: string | null, slug: string } }> } | null } }> } | null };
|
||||
|
||||
export type _GetAttributeChoicesQueryVariables = Exact<{
|
||||
slug: Scalars['String'];
|
||||
first: Scalars['Int'];
|
||||
query: Scalars['String'];
|
||||
}>;
|
||||
|
||||
|
||||
export type _GetAttributeChoicesQuery = { __typename: 'Query', attribute: { __typename: 'Attribute', choices: { __typename: 'AttributeValueCountableConnection', edges: Array<{ __typename: 'AttributeValueCountableEdge', node: { __typename: 'AttributeValue', id: string, name: string | null, slug: string } }> } | null } | null };
|
||||
|
||||
export type _GetCollectionsChoicesQueryVariables = Exact<{
|
||||
first: Scalars['Int'];
|
||||
query: Scalars['String'];
|
||||
}>;
|
||||
|
||||
|
||||
export type _GetCollectionsChoicesQuery = { __typename: 'Query', collections: { __typename: 'CollectionCountableConnection', edges: Array<{ __typename: 'CollectionCountableEdge', node: { __typename: 'Collection', id: string, name: string, slug: string } }> } | null };
|
||||
|
||||
export type _GetCategoriesChoicesQueryVariables = Exact<{
|
||||
first: Scalars['Int'];
|
||||
query: Scalars['String'];
|
||||
}>;
|
||||
|
||||
|
||||
export type _GetCategoriesChoicesQuery = { __typename: 'Query', categories: { __typename: 'CategoryCountableConnection', edges: Array<{ __typename: 'CategoryCountableEdge', node: { __typename: 'Category', id: string, name: string, slug: string } }> } | null };
|
||||
|
||||
export type _GetProductTypesChoicesQueryVariables = Exact<{
|
||||
first: Scalars['Int'];
|
||||
query: Scalars['String'];
|
||||
}>;
|
||||
|
||||
|
||||
export type _GetProductTypesChoicesQuery = { __typename: 'Query', productTypes: { __typename: 'ProductTypeCountableConnection', edges: Array<{ __typename: 'ProductTypeCountableEdge', node: { __typename: 'ProductType', id: string, name: string, slug: string } }> } | null };
|
||||
|
||||
export type TriggerWebhookDryRunMutationVariables = Exact<{
|
||||
objectId: Scalars['ID'];
|
||||
query: Scalars['String'];
|
||||
|
|
Loading…
Reference in a new issue