Cover attributes based on inputType (#3945)

* Cover attributes based on inputType

* Changeset

* Remove logs

* Lint
This commit is contained in:
Patryk Andrzejewski 2023-07-18 14:55:56 +02:00 committed by GitHub
parent 9a3c9de817
commit 4e8942f90e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 119 additions and 21 deletions

View file

@ -0,0 +1,5 @@
---
"saleor-dashboard": minor
---
Cover attributes based on input type

View file

@ -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[];
}

View file

@ -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,

View file

@ -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,

View file

@ -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,
);
}

View file

@ -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;

View file

@ -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() {

View file

@ -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)
}