Cover attributes based on inputType (#3945)
* Cover attributes based on inputType * Changeset * Remove logs * Lint
This commit is contained in:
parent
9a3c9de817
commit
4e8942f90e
8 changed files with 119 additions and 21 deletions
5
.changeset/rude-walls-tell.md
Normal file
5
.changeset/rude-walls-tell.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"saleor-dashboard": minor
|
||||
---
|
||||
|
||||
Cover attributes based on input type
|
|
@ -1,3 +1,6 @@
|
|||
import { AttributeInputTypeEnum } from "@dashboard/graphql";
|
||||
|
||||
import { createBoleanOption } from "../constants";
|
||||
import { AttributeInputType } from "../FilterElement/ConditionOptions";
|
||||
import { ItemOption } from "../FilterElement/ConditionValue";
|
||||
import { UrlToken } from "../ValueProvider/UrlToken";
|
||||
|
@ -46,12 +49,19 @@ export class InitialStateResponse implements InitialState {
|
|||
}
|
||||
|
||||
public filterByUrlToken(token: UrlToken) {
|
||||
if (token.isAttribute()) {
|
||||
if (token.isAttribute() && token.hasDynamicValues()) {
|
||||
return this.attribute[token.name].choices.filter(({ value }) =>
|
||||
token.value.includes(value),
|
||||
);
|
||||
}
|
||||
|
||||
if (token.isAttribute()) {
|
||||
const attr = this.attribute[token.name]
|
||||
return attr.inputType === "BOOLEAN"
|
||||
? createBoleanOption(token.value === "true", AttributeInputTypeEnum.BOOLEAN)
|
||||
: token.value
|
||||
}
|
||||
|
||||
if (!token.isLoadable()) {
|
||||
return [token.value] as string[];
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { ApolloClient, useApolloClient } from "@apollo/client";
|
||||
import { AttributeInputTypeEnum } from "@dashboard/graphql";
|
||||
|
||||
import { RowType } from "../constants";
|
||||
import { FilterContainer, FilterElement } from "../FilterElement";
|
||||
|
@ -46,6 +47,23 @@ const createAPIHandler = (
|
|||
): Handler => {
|
||||
const rowType = selectedRow.rowType()
|
||||
|
||||
if (rowType === "attribute" && selectedRow.value.type === "BOOLEAN") {
|
||||
return new BooleanValuesHandler([
|
||||
{
|
||||
label: "Yes",
|
||||
value: "true",
|
||||
type: AttributeInputTypeEnum.BOOLEAN,
|
||||
slug: "true"
|
||||
},
|
||||
{
|
||||
label: "No",
|
||||
value: "false",
|
||||
type: AttributeInputTypeEnum.BOOLEAN,
|
||||
slug: "false"
|
||||
}
|
||||
])
|
||||
}
|
||||
|
||||
if (rowType === "attribute") {
|
||||
return new AttributeChoicesHandler(
|
||||
client,
|
||||
|
|
|
@ -85,7 +85,10 @@ export const createInitialStateFromData = (
|
|||
(acc, { node }) => ({
|
||||
...acc,
|
||||
[node.slug ?? ""]: {
|
||||
choices: createOptionsFromAPI(node.choices?.edges ?? []),
|
||||
choices:
|
||||
node.inputType === "BOOLEAN"
|
||||
? createBooleanOptions()
|
||||
: createOptionsFromAPI(node.choices?.edges ?? []),
|
||||
slug: node?.slug,
|
||||
value: node?.id,
|
||||
label: node?.name,
|
||||
|
|
|
@ -4,6 +4,7 @@ import { LeftOperand } from "../LeftOperandsProvider";
|
|||
import { UrlToken } from "./../ValueProvider/UrlToken";
|
||||
import { ConditionOptions } from "./ConditionOptions";
|
||||
import { ConditionSelected } from "./ConditionSelected";
|
||||
import { ItemOption } from "./ConditionValue";
|
||||
|
||||
export class Condition {
|
||||
private constructor(
|
||||
|
@ -46,7 +47,7 @@ export class Condition {
|
|||
if (ConditionOptions.isStaticName(token.name)) {
|
||||
const staticOptions = ConditionOptions.fromStaticElementName(token.name);
|
||||
const selectedOption = staticOptions.findByLabel(token.conditionKind);
|
||||
const valueItems = response.filterByUrlToken(token);
|
||||
const valueItems = response.filterByUrlToken(token) as ItemOption[];
|
||||
const value =
|
||||
selectedOption?.type === "multiselect" && valueItems.length > 0
|
||||
? valueItems
|
||||
|
@ -66,11 +67,12 @@ export class Condition {
|
|||
if (token.isAttribute()) {
|
||||
const attribute = response.attributeByName(token.name);
|
||||
const options = ConditionOptions.fromAtributeType(attribute.inputType);
|
||||
const option = options.find(item => item.label === token.conditionKind)!
|
||||
const value = response.filterByUrlToken(token);
|
||||
|
||||
return new Condition(
|
||||
options,
|
||||
ConditionSelected.fromConditionItemAndValue(options.first(), value),
|
||||
ConditionSelected.fromConditionItemAndValue(option, value),
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { UrlToken } from "../UrlToken";
|
||||
import { TokenType, UrlToken } from "../UrlToken";
|
||||
|
||||
export interface FetchingParams {
|
||||
category: string[];
|
||||
|
@ -20,6 +20,10 @@ export const emptyFetchingParams: FetchingParams = {
|
|||
|
||||
const unique = <T>(array: Iterable<T>) => Array.from(new Set(array));
|
||||
|
||||
const includedInParams = (c: UrlToken) =>
|
||||
TokenType.ATTRIBUTE_DROPDOWN === c.type
|
||||
|| TokenType.ATTRIBUTE_MULTISELECT === c.type
|
||||
|
||||
export const toFetchingParams = (p: FetchingParams, c: UrlToken) => {
|
||||
const key = c.name as FetchingParamsKeys;
|
||||
|
||||
|
@ -31,12 +35,18 @@ export const toFetchingParams = (p: FetchingParams, c: UrlToken) => {
|
|||
p.attribute[c.name] = [];
|
||||
}
|
||||
|
||||
if (c.isAttribute()) {
|
||||
if (c.isAttribute() && includedInParams(c)) {
|
||||
p.attribute[c.name] = unique(p.attribute[c.name].concat(c.value));
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
if (c.isAttribute() && !includedInParams(c)) {
|
||||
p.attribute[c.name] = []
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
p[key] = unique(p[key].concat(c.value));
|
||||
|
||||
return p;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { ParsedQs } from "qs";
|
||||
|
||||
import { getAtributeInputType } from "../constants";
|
||||
import { ConditionSelected } from "../FilterElement/ConditionSelected";
|
||||
import { slugFromConditionValue } from "../FilterElement/ConditionValue";
|
||||
|
||||
|
@ -18,12 +19,28 @@ const STATIC_TO_LOAD = [
|
|||
];
|
||||
|
||||
export const TokenType = {
|
||||
ATTRIBUTE: "a",
|
||||
ATTRIBUTE_DROPDOWN: "o",
|
||||
ATTRIBUTE_MULTISELECT: "m",
|
||||
ATTRIBUTE_NUMERIC: "n",
|
||||
ATTRIBUTE_DATE_TIME: "t",
|
||||
ATTRIBUTE_DATE: "d",
|
||||
ATTRIBUTE_BOOLEAN: "b",
|
||||
STATIC: "s",
|
||||
} as const;
|
||||
|
||||
|
||||
export type TokenTypeValue = (typeof TokenType)[keyof typeof TokenType];
|
||||
|
||||
const resolveTokenType = (name: string): TokenTypeValue => {
|
||||
const key = `ATTRIBUTE_${name}` as keyof typeof TokenType
|
||||
|
||||
if (key in TokenType) {
|
||||
return TokenType[key]
|
||||
}
|
||||
|
||||
return TokenType.STATIC
|
||||
}
|
||||
|
||||
export class UrlEntry {
|
||||
constructor(key: string, value: string | string[]) {
|
||||
(this as unknown as Record<string, string | string[]>)[key] = value;
|
||||
|
@ -37,10 +54,13 @@ export class UrlEntry {
|
|||
}
|
||||
|
||||
public static forAttribute(condition: ConditionSelected, paramName: string) {
|
||||
const inputType = getAtributeInputType(condition.conditionValue)
|
||||
const tokenSlug = resolveTokenType(inputType || "")
|
||||
|
||||
return UrlEntry.fromConditionSelected(
|
||||
condition,
|
||||
paramName,
|
||||
TokenType.ATTRIBUTE,
|
||||
tokenSlug,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -100,7 +120,15 @@ export class UrlToken {
|
|||
}
|
||||
|
||||
public isAttribute() {
|
||||
return this.type === TokenType.ATTRIBUTE;
|
||||
const result = Object.entries(TokenType)
|
||||
.find(([_, slug]) => slug === this.type)
|
||||
|
||||
return result && result[0].includes("ATTRIBUTE")
|
||||
}
|
||||
|
||||
public hasDynamicValues() {
|
||||
return TokenType.ATTRIBUTE_DROPDOWN === this.type
|
||||
|| TokenType.ATTRIBUTE_MULTISELECT === this.type
|
||||
}
|
||||
|
||||
public isLoadable() {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { ConditionItem } from "./FilterElement/ConditionOptions";
|
||||
import { ItemOption } from "./FilterElement/ConditionValue";
|
||||
import { LeftOperand } from "./LeftOperandsProvider";
|
||||
|
||||
|
@ -58,18 +59,39 @@ export const ATTRIBUTE_INPUT_TYPE_CONDITIONS = {
|
|||
SWATCH: [{ type: "multiselect", label: "in", value: "input-2" }],
|
||||
};
|
||||
|
||||
export const getAtributeInputType = (item: ConditionItem | null) => {
|
||||
const result = Object.entries(ATTRIBUTE_INPUT_TYPE_CONDITIONS)
|
||||
.find(([_, value]) =>
|
||||
value.find(entry => entry.type === item?.type && entry.label === item.label)
|
||||
)
|
||||
|
||||
return result && result[0]
|
||||
}
|
||||
|
||||
|
||||
export type RowType = keyof typeof STATIC_CONDITIONS | "attribute"
|
||||
|
||||
export const createBooleanOptions = (): ItemOption[] => [
|
||||
{
|
||||
label: "Yes",
|
||||
value: "true",
|
||||
slug: "true"
|
||||
},
|
||||
{
|
||||
label: "No",
|
||||
value: "false",
|
||||
slug: "false"
|
||||
}
|
||||
]
|
||||
export const booleanOptionTrue = (type?: string) => ({
|
||||
label: "Yes",
|
||||
value: "true",
|
||||
slug: "true",
|
||||
...({ type })
|
||||
})
|
||||
|
||||
export const booleanOptionFalse = (type?: string) => ({
|
||||
label: "No",
|
||||
value: "false",
|
||||
slug: "false",
|
||||
...({ type })
|
||||
})
|
||||
|
||||
export const createBooleanOptions = (type?: string): ItemOption[] => [
|
||||
booleanOptionTrue(type),
|
||||
booleanOptionFalse(type)
|
||||
]
|
||||
|
||||
export const createBoleanOption = (flag: boolean, type?: string): ItemOption => {
|
||||
if (flag) return booleanOptionTrue(type)
|
||||
|
||||
return booleanOptionFalse(type)
|
||||
}
|
Loading…
Reference in a new issue