Allow no attribute values in variant creator (#1739)

* Allow no attribute values in variant creator

* Update test snapshots
This commit is contained in:
Dawid Tarasiuk 2022-01-25 11:56:40 +01:00 committed by GitHub
parent b13ecfc197
commit 53a391eebc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 112 additions and 13 deletions

View file

@ -90,6 +90,7 @@ export const attributes: Array<AttributeList_attributes_edges_node &
slug: "author",
type: AttributeTypeEnum.PRODUCT_TYPE,
inputType: AttributeInputTypeEnum.DROPDOWN,
valueRequired: false,
unit: null,
choices: {
__typename: "AttributeValueCountableConnection" as "AttributeValueCountableConnection",
@ -152,6 +153,7 @@ export const attributes: Array<AttributeList_attributes_edges_node &
slug: "box-size",
type: AttributeTypeEnum.PRODUCT_TYPE,
inputType: AttributeInputTypeEnum.DROPDOWN,
valueRequired: false,
unit: null,
choices: {
__typename: "AttributeValueCountableConnection" as "AttributeValueCountableConnection",
@ -250,6 +252,7 @@ export const attributes: Array<AttributeList_attributes_edges_node &
slug: "brand",
type: AttributeTypeEnum.PRODUCT_TYPE,
inputType: AttributeInputTypeEnum.DROPDOWN,
valueRequired: false,
unit: null,
choices: {
__typename: "AttributeValueCountableConnection" as "AttributeValueCountableConnection",
@ -294,6 +297,7 @@ export const attributes: Array<AttributeList_attributes_edges_node &
slug: "candy-box-size",
type: AttributeTypeEnum.PRODUCT_TYPE,
inputType: AttributeInputTypeEnum.DROPDOWN,
valueRequired: false,
unit: null,
choices: {
__typename: "AttributeValueCountableConnection" as "AttributeValueCountableConnection",
@ -374,6 +378,7 @@ export const attributes: Array<AttributeList_attributes_edges_node &
slug: "coffee-genre",
type: AttributeTypeEnum.PRODUCT_TYPE,
inputType: AttributeInputTypeEnum.DROPDOWN,
valueRequired: false,
unit: null,
choices: {
__typename: "AttributeValueCountableConnection" as "AttributeValueCountableConnection",
@ -436,6 +441,7 @@ export const attributes: Array<AttributeList_attributes_edges_node &
slug: "collar",
type: AttributeTypeEnum.PRODUCT_TYPE,
inputType: AttributeInputTypeEnum.DROPDOWN,
valueRequired: false,
unit: null,
choices: {
__typename: "AttributeValueCountableConnection" as "AttributeValueCountableConnection",
@ -516,6 +522,7 @@ export const attributes: Array<AttributeList_attributes_edges_node &
slug: "color",
type: AttributeTypeEnum.PRODUCT_TYPE,
inputType: AttributeInputTypeEnum.DROPDOWN,
valueRequired: false,
unit: null,
choices: {
__typename: "AttributeValueCountableConnection" as "AttributeValueCountableConnection",
@ -578,6 +585,7 @@ export const attributes: Array<AttributeList_attributes_edges_node &
slug: "cover",
type: AttributeTypeEnum.PRODUCT_TYPE,
inputType: AttributeInputTypeEnum.DROPDOWN,
valueRequired: false,
unit: null,
choices: {
__typename: "AttributeValueCountableConnection" as "AttributeValueCountableConnection",
@ -712,6 +720,7 @@ export const attributes: Array<AttributeList_attributes_edges_node &
slug: "flavor",
type: AttributeTypeEnum.PRODUCT_TYPE,
inputType: AttributeInputTypeEnum.DROPDOWN,
valueRequired: false,
unit: null,
choices: {
__typename: "AttributeValueCountableConnection" as "AttributeValueCountableConnection",
@ -774,6 +783,7 @@ export const attributes: Array<AttributeList_attributes_edges_node &
slug: "language",
type: AttributeTypeEnum.PRODUCT_TYPE,
inputType: AttributeInputTypeEnum.DROPDOWN,
valueRequired: false,
unit: null,
choices: {
__typename: "AttributeValueCountableConnection" as "AttributeValueCountableConnection",
@ -836,6 +846,7 @@ export const attributes: Array<AttributeList_attributes_edges_node &
slug: "publisher",
type: AttributeTypeEnum.PRODUCT_TYPE,
inputType: AttributeInputTypeEnum.DROPDOWN,
valueRequired: false,
unit: null,
choices: {
__typename: "AttributeValueCountableConnection" as "AttributeValueCountableConnection",
@ -899,6 +910,7 @@ export const attributes: Array<AttributeList_attributes_edges_node &
type: AttributeTypeEnum.PRODUCT_TYPE,
unit: null,
inputType: AttributeInputTypeEnum.DROPDOWN,
valueRequired: false,
choices: {
__typename: "AttributeValueCountableConnection" as "AttributeValueCountableConnection",
pageInfo: {

View file

@ -163,6 +163,7 @@ export const productVariantAttributesFragment = gql`
id
name
inputType
valueRequired
unit
choices(
first: $firstValues

View file

@ -132,6 +132,7 @@ export interface Product_productType_variantAttributes {
id: string;
name: string | null;
inputType: AttributeInputTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
choices: Product_productType_variantAttributes_choices | null;
}

View file

@ -132,6 +132,7 @@ export interface ProductVariantAttributesFragment_productType_variantAttributes
id: string;
name: string | null;
inputType: AttributeInputTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
choices: ProductVariantAttributesFragment_productType_variantAttributes_choices | null;
}

View file

@ -59,6 +59,7 @@ const stock: Stock = {
const dataAttributes = selectedAttributes.map(attribute => ({
id: attribute.id,
valueRequired: attribute.valueRequired,
values: attribute.choices.edges
.map(value => ({
slug: value.node.slug,

View file

@ -47,7 +47,9 @@ function canHitNext(
switch (step) {
case ProductVariantCreatorStep.values:
return (
data.attributes.every(attribute => attribute.values.length > 0) &&
data.attributes.every(
attribute => !attribute.valueRequired || attribute.values.length > 0
) &&
(variantsLeft === null || getVariantsNumber(data) <= variantsLeft)
);
case ProductVariantCreatorStep.prices:

View file

@ -5,6 +5,7 @@ Object {
"attributes": Array [
Object {
"id": "attr-1",
"valueRequired": false,
"values": Array [
Object {
"slug": "val-1-1",
@ -42,6 +43,7 @@ Object {
},
Object {
"id": "attr-2",
"valueRequired": false,
"values": Array [
Object {
"slug": "val-2-2",
@ -79,6 +81,7 @@ Object {
},
Object {
"id": "attr-4",
"valueRequired": false,
"values": Array [
Object {
"slug": "val-4-1",
@ -650,6 +653,7 @@ Object {
"attributes": Array [
Object {
"id": "attr-1",
"valueRequired": false,
"values": Array [
Object {
"slug": "val-1-1",
@ -687,6 +691,7 @@ Object {
},
Object {
"id": "attr-2",
"valueRequired": false,
"values": Array [
Object {
"slug": "val-2-2",
@ -724,6 +729,7 @@ Object {
},
Object {
"id": "attr-4",
"valueRequired": false,
"values": Array [
Object {
"slug": "val-4-1",
@ -1295,6 +1301,7 @@ Object {
"attributes": Array [
Object {
"id": "attr-1",
"valueRequired": false,
"values": Array [
Object {
"slug": "val-1-1",
@ -1332,6 +1339,7 @@ Object {
},
Object {
"id": "attr-2",
"valueRequired": false,
"values": Array [
Object {
"slug": "val-2-2",
@ -1369,6 +1377,7 @@ Object {
},
Object {
"id": "attr-4",
"valueRequired": false,
"values": Array [
Object {
"slug": "val-4-1",
@ -1440,6 +1449,7 @@ Object {
"attributes": Array [
Object {
"id": "attr-1",
"valueRequired": false,
"values": Array [
Object {
"slug": "val-1-1",
@ -1477,6 +1487,7 @@ Object {
},
Object {
"id": "attr-2",
"valueRequired": false,
"values": Array [
Object {
"slug": "val-2-2",
@ -1514,6 +1525,7 @@ Object {
},
Object {
"id": "attr-4",
"valueRequired": false,
"values": Array [
Object {
"slug": "val-4-1",
@ -2036,6 +2048,7 @@ Object {
"attributes": Array [
Object {
"id": "attr-1",
"valueRequired": false,
"values": Array [
Object {
"slug": "val-1-1",
@ -2073,6 +2086,7 @@ Object {
},
Object {
"id": "attr-2",
"valueRequired": false,
"values": Array [
Object {
"slug": "val-2-2",
@ -2110,6 +2124,7 @@ Object {
},
Object {
"id": "attr-4",
"valueRequired": false,
"values": Array [
Object {
"slug": "val-4-1",
@ -2587,6 +2602,7 @@ Object {
"attributes": Array [
Object {
"id": "attr-1",
"valueRequired": false,
"values": Array [
Object {
"slug": "val-1-1",
@ -2624,6 +2640,7 @@ Object {
},
Object {
"id": "attr-2",
"valueRequired": false,
"values": Array [
Object {
"slug": "val-2-2",
@ -2661,6 +2678,7 @@ Object {
},
Object {
"id": "attr-4",
"valueRequired": false,
"values": Array [
Object {
"slug": "val-4-1",
@ -3183,6 +3201,7 @@ Object {
"attributes": Array [
Object {
"id": "attr-1",
"valueRequired": false,
"values": Array [
Object {
"slug": "val-1-1",
@ -3220,6 +3239,7 @@ Object {
},
Object {
"id": "attr-2",
"valueRequired": false,
"values": Array [
Object {
"slug": "val-2-2",
@ -3257,6 +3277,7 @@ Object {
},
Object {
"id": "attr-4",
"valueRequired": false,
"values": Array [
Object {
"slug": "val-4-1",
@ -3696,6 +3717,7 @@ Object {
"attributes": Array [
Object {
"id": "attr-1",
"valueRequired": false,
"values": Array [
Object {
"slug": "val-1-1",
@ -3733,6 +3755,7 @@ Object {
},
Object {
"id": "attr-2",
"valueRequired": false,
"values": Array [
Object {
"slug": "val-2-2",
@ -3770,6 +3793,7 @@ Object {
},
Object {
"id": "attr-4",
"valueRequired": false,
"values": Array [
Object {
"slug": "val-4-1",

View file

@ -1,4 +1,7 @@
import { ProductVariantBulkCreateInput } from "@saleor/types/globalTypes";
import {
BulkAttributeValueInput,
ProductVariantBulkCreateInput
} from "@saleor/types/globalTypes";
import {
Attribute,
@ -10,7 +13,7 @@ import {
interface CreateVariantAttributeValueInput {
attributeId: string;
attributeValueSlug: string;
attributeValueSlug: string | null;
attributeBooleanValue: boolean | null;
}
@ -81,6 +84,23 @@ function getPriceFromMode(
}
}
function getAttributeFromAttributeValueInput({
attributeId,
attributeBooleanValue,
attributeValueSlug
}: CreateVariantAttributeValueInput): BulkAttributeValueInput {
if (attributeBooleanValue === null) {
return {
id: attributeId,
values: attributeValueSlug === null ? [] : [attributeValueSlug]
};
}
return {
id: attributeId,
boolean: attributeBooleanValue
};
}
function createVariant(
data: ProductVariantCreateFormData,
attributes: CreateVariantInput
@ -97,12 +117,7 @@ function createVariant(
);
return {
attributes: attributes.map(attribute => ({
id: attribute.attributeId,
...(attribute.attributeBooleanValue === null
? { values: [attribute.attributeValueSlug] }
: { boolean: attribute.attributeBooleanValue })
})),
attributes: attributes.map(getAttributeFromAttributeValueInput),
channelListings: price,
sku: "",
stocks: stocks.map((quantity, stockIndex) => ({
@ -116,6 +131,18 @@ function addAttributeToVariant(
attribute: Attribute,
variant: CreateVariantInput
): CreateVariantInput[] {
if (attribute.values.length === 0) {
return [
[
...variant,
{
attributeId: attribute.id,
attributeValueSlug: null,
attributeBooleanValue: null
}
]
];
}
return attribute.values.map(attributeValue => [
...variant,
{

View file

@ -18,6 +18,7 @@ export const channels: ChannelPriceData[] = [
export const attributes = [
{
id: "attr-1",
valueRequired: false,
values: Array(9)
.fill(0)
.map((_, index) => ({
@ -39,6 +40,7 @@ export const attributes = [
},
{
id: "attr-2",
valueRequired: false,
values: Array(6)
.fill(0)
.map((_, index) => ({
@ -60,6 +62,7 @@ export const attributes = [
},
{
id: "attr-3",
valueRequired: false,
values: Array(4)
.fill(0)
.map((_, index) => ({
@ -81,6 +84,7 @@ export const attributes = [
},
{
id: "attr-4",
valueRequired: false,
values: Array(11)
.fill(0)
.map((_, index) => ({
@ -130,14 +134,17 @@ export const secondStep: ProductVariantCreateFormData = {
attributes: [
{
id: attributes[0].id,
valueRequired: attributes[0].valueRequired,
values: []
},
{
id: attributes[1].id,
valueRequired: attributes[1].valueRequired,
values: []
},
{
id: attributes[3].id,
valueRequired: attributes[3].valueRequired,
values: []
}
]
@ -148,14 +155,17 @@ export const thirdStep: ProductVariantCreateFormData = {
attributes: [
{
id: attributes[0].id,
valueRequired: attributes[0].valueRequired,
values: [0, 6].map(index => attributes[0].values[index])
},
{
id: attributes[1].id,
valueRequired: attributes[1].valueRequired,
values: [1, 3].map(index => attributes[1].values[index])
},
{
id: attributes[3].id,
valueRequired: attributes[3].valueRequired,
values: [0, 4].map(index => attributes[3].values[index])
}
],

View file

@ -29,6 +29,7 @@ export interface Stock {
}
export interface Attribute {
id: string;
valueRequired: boolean;
values: Array<AttributeValue<Partial<AttributeValueFragment>>>;
}
export interface ProductVariantCreateFormData {
@ -52,6 +53,7 @@ export const createInitialForm = (
return {
attributes: attributes.map(attribute => ({
id: attribute.id,
valueRequired: attribute.valueRequired,
values: []
})),
price: {

View file

@ -94,6 +94,7 @@ function selectValue(
const updatedAttributes = add(
{
id: attributeId,
valueRequired: attribute.valueRequired,
values
},
remove(attribute, prevState.attributes, (a, b) => a.id === b.id)
@ -417,9 +418,21 @@ function deleteVariant(
state: ProductVariantCreateFormData,
variantIndex: number
): ProductVariantCreateFormData {
const variants = removeAtIndex(state.variants, variantIndex);
return {
...state,
variants: removeAtIndex(state.variants, variantIndex)
variants: variants.length
? variants
: createVariants({
...state,
attributes: state.attributes.map(attribute => ({
id: attribute.id,
valueRequired: attribute.valueRequired,
values: []
})),
variants
})
};
}

View file

@ -472,6 +472,7 @@ export const product: (
id: "isdugfhud",
name: "Attachment",
inputType: AttributeInputTypeEnum.DROPDOWN,
valueRequired: false,
unit: null,
choices: {
__typename: "AttributeValueCountableConnection",
@ -512,6 +513,7 @@ export const product: (
id: "pta18161",
name: "Color",
inputType: AttributeInputTypeEnum.DROPDOWN,
valueRequired: false,
unit: null,
choices: {
__typename: "AttributeValueCountableConnection",

View file

@ -132,6 +132,7 @@ export interface CreateMultipleVariantsData_product_productType_variantAttribute
id: string;
name: string | null;
inputType: AttributeInputTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
choices: CreateMultipleVariantsData_product_productType_variantAttributes_choices | null;
}

View file

@ -132,6 +132,7 @@ export interface ProductDetails_product_productType_variantAttributes {
id: string;
name: string | null;
inputType: AttributeInputTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
choices: ProductDetails_product_productType_variantAttributes_choices | null;
}

View file

@ -139,6 +139,7 @@ export interface ProductUpdate_productUpdate_product_productType_variantAttribut
id: string;
name: string | null;
inputType: AttributeInputTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
choices: ProductUpdate_productUpdate_product_productType_variantAttributes_choices | null;
}

View file

@ -139,6 +139,7 @@ export interface SimpleProductUpdate_productUpdate_product_productType_variantAt
id: string;
name: string | null;
inputType: AttributeInputTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
choices: SimpleProductUpdate_productUpdate_product_productType_variantAttributes_choices | null;
}

View file

@ -180484,10 +180484,9 @@ exports[`Storyshots Views / Products / Create multiple variants interactive 1`]
class="PageHeader-root-id"
>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-contained-id ProductVariantCreatePage-button-id MuiButton-containedPrimary-id MuiButton-disabled-id MuiButtonBase-disabled-id"
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-contained-id ProductVariantCreatePage-button-id MuiButton-containedPrimary-id"
data-test-id="next-step"
disabled=""
tabindex="-1"
tabindex="0"
type="button"
>
<span