From 11be87644c6db104e1b79f848af646d76ea36398 Mon Sep 17 00:00:00 2001 From: Igor Melnykov Date: Tue, 20 Oct 2020 12:51:51 -0500 Subject: [PATCH 01/12] Update custom attributes container proposal to account for attributes with multiple values --- .../custom-attributes-container.md | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/design-documents/graph-ql/coverage/custom-attributes/custom-attributes-container.md b/design-documents/graph-ql/coverage/custom-attributes/custom-attributes-container.md index 3b22cf763..c8ad12c70 100644 --- a/design-documents/graph-ql/coverage/custom-attributes/custom-attributes-container.md +++ b/design-documents/graph-ql/coverage/custom-attributes/custom-attributes-container.md @@ -8,11 +8,41 @@ One workaround for "getting all fields" is based on schema introspection, it all # Proposed solution -To account for dynamic nature of EAV attributes and the need of "getting all fields" in product search queries, `custom_attributes: [CustomAttribute]!` container will be introduced. +To account for dynamic nature of EAV attributes and the need of "getting all fields" in product search queries,we can introduce `custom_attributes: [CustomAttribute]!` container. ```graphql type CustomAttribute { code: String! + value: [String]! # We want to account fo attributes that have single (text, dropdown) and multiple values (checkbox, multiselect) +} + +# We could also make value complex type to be able add more fields in the future +type CustomAttribute { + code: String! + value: [CustomAttributeValue]! +} + +type CustomAttributeValue { + value: String! +} +``` + +Alternative approach would be is to introduce an interface `custom_attributes: [CustomAttributeInterface]!`. + +```graphql +type CustomAttributeInterface { + code: String! +} + +type CustomAttribute extends CustomAttributeInterface { + value: CustomAttributeValue! +} + +type CustomAttributeMulti extends CustomAttributeInterface { + values: [CustomAttributeValue]! +} + +type CustomAttributeValue { value: String! } ``` From 72a22380e47d6cd93c5ce61a4a9c7efe95c28877 Mon Sep 17 00:00:00 2001 From: Igor Melnykov Date: Tue, 20 Oct 2020 13:01:57 -0500 Subject: [PATCH 02/12] Update custom attributes container proposal to account for attributes with multiple values --- .../custom-attributes-container.md | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/design-documents/graph-ql/coverage/custom-attributes/custom-attributes-container.md b/design-documents/graph-ql/coverage/custom-attributes/custom-attributes-container.md index c8ad12c70..ab34f55b3 100644 --- a/design-documents/graph-ql/coverage/custom-attributes/custom-attributes-container.md +++ b/design-documents/graph-ql/coverage/custom-attributes/custom-attributes-container.md @@ -13,13 +13,16 @@ To account for dynamic nature of EAV attributes and the need of "getting all fie ```graphql type CustomAttribute { code: String! - value: [String]! # We want to account fo attributes that have single (text, dropdown) and multiple values (checkbox, multiselect) + values: [String]! # We want to account fo attributes that have single (text, dropdown) and multiple values (checkbox, multiselect) } +``` + +We could also make value complex type to be able add more fields in the future, but this doesn't seem necessary at this point. -# We could also make value complex type to be able add more fields in the future +```graphql type CustomAttribute { code: String! - value: [CustomAttributeValue]! + values: [CustomAttributeValue]! } type CustomAttributeValue { @@ -34,16 +37,12 @@ type CustomAttributeInterface { code: String! } -type CustomAttribute extends CustomAttributeInterface { - value: CustomAttributeValue! -} - -type CustomAttributeMulti extends CustomAttributeInterface { - values: [CustomAttributeValue]! +type SingleValueCustomAttribute extends CustomAttributeInterface { + value: String! } -type CustomAttributeValue { - value: String! +type MultipleValuesCustomAttribute extends CustomAttributeInterface { + values: [String]! } ``` From 3205dd0cbfbe59b77be530e414625dcfdc7b459b Mon Sep 17 00:00:00 2001 From: Igor Melnykov Date: Tue, 20 Oct 2020 14:04:58 -0500 Subject: [PATCH 03/12] Update custom attributes container proposal to account for attributes with multiple values --- .../coverage/custom-attributes/custom-attributes-container.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/design-documents/graph-ql/coverage/custom-attributes/custom-attributes-container.md b/design-documents/graph-ql/coverage/custom-attributes/custom-attributes-container.md index ab34f55b3..07bfbb509 100644 --- a/design-documents/graph-ql/coverage/custom-attributes/custom-attributes-container.md +++ b/design-documents/graph-ql/coverage/custom-attributes/custom-attributes-container.md @@ -8,7 +8,7 @@ One workaround for "getting all fields" is based on schema introspection, it all # Proposed solution -To account for dynamic nature of EAV attributes and the need of "getting all fields" in product search queries,we can introduce `custom_attributes: [CustomAttribute]!` container. +To account for dynamic nature of EAV attributes and the need of "getting all fields" in product search queries, we can introduce `custom_attributes: [CustomAttribute]!` container (recommended approach). ```graphql type CustomAttribute { @@ -30,7 +30,7 @@ type CustomAttributeValue { } ``` -Alternative approach would be is to introduce an interface `custom_attributes: [CustomAttributeInterface]!`. +Alternative approach would be is to introduce an interface `custom_attributes: [CustomAttributeInterface]!`, but it seems more complicated. ```graphql type CustomAttributeInterface { From 7a191b52f5bae6548595c268f6d9640a5cbc951a Mon Sep 17 00:00:00 2001 From: Cristian Partica Date: Thu, 4 Feb 2021 22:34:50 -0600 Subject: [PATCH 04/12] modifying proposal --- .../custom-attributes/attributes-metadata.md | 56 +++++++++++++++++-- .../custom-attributes-container.md | 44 +++++++++------ 2 files changed, 78 insertions(+), 22 deletions(-) diff --git a/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.md b/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.md index 9d4b868c5..68b24e08b 100644 --- a/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.md +++ b/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.md @@ -29,16 +29,62 @@ type CustomAttributeMetadata { } type Attribute { + uid: String attribute_code: String + label: String + attribute_type: String @deprecated(reason: "use `attribute_data_type` instead") + attribute_data_type: ObjectDataType + entity_type: EntityType + input_type: UiInputType + sort_order: Int + metadata_values: [AttributeMetadataValue] attribute_options: [AttributeOption] - attribute_type: String - entity_type: String - input_type: String +} + +enum ObjectDataType { + STRING + FLOAT + INT +} + +enum EntityType { + customer + customer_address + catalog_category + catalog_product + order + invoice + creditmemo + shipment + rma_item +} + +enum UiInputType { + text + dropdown + swatch + file + multi_line + #.... +} + +enum MetadataType { + Values_Unique + Values_validation + #... +} + +type AttributeMetadataValue { + label: String + values: [String] + metadata_type: MetadataType } type AttributeOption { - label: String - value: String + uid: ID! + value: String @deprecated(reason: "use `uid` instead") + label + is_default } ``` diff --git a/design-documents/graph-ql/coverage/custom-attributes/custom-attributes-container.md b/design-documents/graph-ql/coverage/custom-attributes/custom-attributes-container.md index 07bfbb509..3e29bbdee 100644 --- a/design-documents/graph-ql/coverage/custom-attributes/custom-attributes-container.md +++ b/design-documents/graph-ql/coverage/custom-attributes/custom-attributes-container.md @@ -8,40 +8,50 @@ One workaround for "getting all fields" is based on schema introspection, it all # Proposed solution -To account for dynamic nature of EAV attributes and the need of "getting all fields" in product search queries, we can introduce `custom_attributes: [CustomAttribute]!` container (recommended approach). +To account for dynamic nature of EAV attributes and the need of "getting all fields" in product search queries, we can introduce `stored_attributes: [StoredAttribute]!` container (recommended approach). +The container will return the list of attributes plus the actual values stored for each entity. ```graphql -type CustomAttribute { - code: String! - values: [String]! # We want to account fo attributes that have single (text, dropdown) and multiple values (checkbox, multiselect) +type StoredAttribute { + selected_attributes: [SelectedAttribute] # used to store unique options values + entered_attributes: [EnteredAttribute] # used to store the freetype entered values like texts + available_attributes: [Attribute] # metadata of the actual attribute not related to the stored Entity-Attribute value +} + +type SelectedAttribute { + attribute: Attribute # existing type for metadata + options_uids: [ID] +} + +type EnteredAttribute { + attribute: Attribute # existing type for metadata + value: String } ``` -We could also make value complex type to be able add more fields in the future, but this doesn't seem necessary at this point. +We could also make value complex type to be able add more complex fields values in the future, but this doesn't seem necessary at this point. +This is also aligned with the Selected, Entered values from customizable options, or configurable product. + +Alternative approach would be is to introduce a type or an interface `custom_attributes: [CustomAttribute]!`. ```graphql type CustomAttribute { code: String! - values: [CustomAttributeValue]! -} - -type CustomAttributeValue { - value: String! + values: [String]! # We want to account fo attributes that have single (text, dropdown) and multiple values (checkbox, multiselect) } ``` - -Alternative approach would be is to introduce an interface `custom_attributes: [CustomAttributeInterface]!`, but it seems more complicated. +Or to introduce a type or an interface `custom_attributes: [CustomAttributeInterface]!`, but it seems more complicated. ```graphql -type CustomAttributeInterface { +interface CustomAttributeInterface { code: String! } -type SingleValueCustomAttribute extends CustomAttributeInterface { +type SingleValueCustomAttribute implements CustomAttributeInterface { value: String! } -type MultipleValuesCustomAttribute extends CustomAttributeInterface { +type MultipleValuesCustomAttribute implements CustomAttributeInterface { values: [String]! } ``` @@ -71,7 +81,7 @@ Current implementation allows the following query Let's assume the response will be -```graphql +```json { "data": { "products": { @@ -114,7 +124,7 @@ With the proposed changes the above mentioned queries will still be supported. I ``` Note that color and size are not applicable to some products in the search result. In the previous example they were returned as `null`. In the following example they are not returned at all -```graphql +```json { "data": { "products": { From c12eb3eef79175f38ae8f41e41f7478fd0efef0c Mon Sep 17 00:00:00 2001 From: Cristian Partica Date: Tue, 9 Feb 2021 19:57:09 -0600 Subject: [PATCH 05/12] adding interfaces on inputs --- .../attributes-metadata.graphqls | 211 ++++++++++++++++++ .../custom-attributes/attributes-metadata.md | 163 +++++++++----- 2 files changed, 323 insertions(+), 51 deletions(-) create mode 100644 design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.graphqls diff --git a/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.graphqls b/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.graphqls new file mode 100644 index 000000000..d942eacd9 --- /dev/null +++ b/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.graphqls @@ -0,0 +1,211 @@ +type AttributeInput { + attribute_code: String + entity_type: String + uid: ID +} + +type CustomAttributeMetadata { + items: [AttributeMetadataInterface] +} + +#base metadata common to all attributes +interface AttributeMetadataInterface { + uid: ID # base64Encode(entityID/codeID) + label: String + data_type: ObjectDataTypeEnum # string, int, float, boolean etc + sort_order: Int +} + +interface AttributeMetadataEntityTypeInterface { + entity_type: EntityTypeEnum +} + +interface AttributeMetadataUiTypeInterface { + ui_input_type: UiInputTypeEnum +} + +type CustomerAttributeMetadata implements AttributeMetadataInterface, AttributeMetadataEntityTypeInterface, AttributeMetadataUiTypeInterface { + ui_input_type: UiInputTypeInterface! + forms_to_use_in: [CustomAttributesListingsEnum] +} + +type CustomerAddressAttributeMetadata implements AttributeMetadataInterface { +} + +type ProductAttributeMetadata implements AttributeMetadataInterface { +} + +# interfaces for different types used in inputs-------------- + +interface UiInputTypeInterface { + ui_input_type: EntityTypeEnum + value_required: Boolean! +} + +interface InputFilterInterface { + filter: InputValidationFilterEnum +} + +interface InputValidationInterface { + input_validation_type: InputValidationTypeEnum +} + +interface AttributeOptionsInterface { + attribute_options: [AttributeOptionInterface] +} + +# -------------- +type TextInputType implements UiInputTypeInterface, InputFilterInterface, InputFilterInterface { + default_value: String +} + +type InputValidationNone implements InputValidationInterface { +} + +type InputValidationLength implements InputValidationInterface { + minimum_text_length: Int + maximum_text_length: Int +} + +#-------------- + +type TextAreaInputType implements UiInputTypeInterface, InputFilterInterface { + default_value: String +} + +type MultipleLineInputType implements UiInputTypeInterface, InputValidationInterface, InputFilterInterface { + default_value: String + lines_count: Int +} + +type DateInputType implements UiInputTypeInterface, InputValidationInterface { + default_value: String + minimum_date_allowed: String + maximum_date_allowed: String +} + +type FileInputType implements UiInputTypeInterface, InputValidationInterface { + default_value: String + maximum_file_size: Int # bytes + allowed_file_extensions: [String] +} + +type ImageInputType implements UiInputTypeInterface, InputValidationInterface { + default_value: String + maximum_file_size: Int # bytes + allowed_file_extensions: [String] + maximum_image_width: Int # in pixels + maximum_image_height: Int # in pixels +} + +type DropDownInputType implements UiInputTypeInterface, InputValidationInterface, AttributeOptionsInterface { + default_value: String +} + +#other types for other entities here + + +type AttributeOptionInterface { + uid: ID! # base64Encode(entityID/codeID/OptionID) + is_default: Boolean # marks if an option should be default +} + +# base type of an option existing type +type AttributeOption implements AttributeOptionInterface { + # UID and is_default is imported + value: String @deprecated(reason: "use `uid` instead") + label: String +} + +# extended type of an option as it would look like for visual swatches +type AttributeOptionSwatch implements AttributeOptionInterface { + swatch: SwatchOptionInterface +} + +interface SwatchOptionInterface { +} + +type SwatchOptionColor implements SwatchOptionInterface { + color: String # html hex code format +} + +type SwatchOptionImage implements SwatchOptionInterface { + image_path: String # relative path +} +# end of swatches variation + +#enums to support above queries +enum ObjectDataTypeEnum { + STRING + FLOAT + INT + BOOLEAN +} + +enum EntityTypeEnum { + CUSTOMER + CUSTOMER_ADDRESS + CATALOG_CATEGORY + CATALOG_PRODUCT + ORDER + INVOICE + CREDITMEMO + SHIPMENT + RMA_ITEM + GENERIC +} + +enum UiInputTypeEnum { + TEXT + TEXTAREA + MULTILINE + DATE + DATETIME + SELECT + MULTISELECT + BOOLEAN + FILE + IMAGE + SWATCH_VISUAL + SWATCH_TEXT + PRICE + MEDIA_IMAGE + WEEE +} + +enum InputValidationTypeEnum { + ALPHANUMERIC + ALPHANUMERIC_WITH_SPACES + NUMERIC_ONLY + ALLPHA_ONLY + DATE + URL + EMAIL + LENGTH_ONLY +} + +enum InputValidationFilterEnum { + STRIPTAGS + ESCAPEHTML + DATE +} + +enum CustomerAttributeFormsEnum { + CUSTOMER_ACCOUNT_CREATE + CUSTOMER_ACCOUNT_EDIT + ADMINHTML_CHECKOUT +} + +type Query { + customAttributesListings( + listing_type: CustomAttributesListingsEnum + ): CustomAttributeMetadata +} +enum CustomAttributesListingsEnum { + PRODUCTS_COMPARE + PRODUCTS_LISTING + ADVANCED_CATALOG_SEARCH + RMA_FORM + CUSTOMER_REGISTRATION_FORM + CUSTOMER_ADDRESS_FORM +} diff --git a/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.md b/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.md index 68b24e08b..7b6032de7 100644 --- a/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.md +++ b/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.md @@ -11,95 +11,156 @@ Additionally, there should be a way to retrieve metadata for all storefront cust # Proposed solution -Relaxing signature of existing `customAttributeMetadata` query by making its `attriubtes` argument optional will allow to fetch all storefront attributes metadata. +Relaxing signature of existing `customAttributeMetadata` query by making its `attributes` argument optional will allow to fetch all storefront attributes metadata. Existing schema: ```graphql -Query.customAttributeMetadata( +Query.customAttributesMetadata( attributes: [AttributeInput!]! ): CustomAttributeMetadata +``` + +Added schema: +```graphql +#adding to existing type a choice of uid or code and type AttributeInput { - attribute_code: String - entity_type: String + attribute_code: String #deprecated + entity_type: String #deprecated + uid: ID # we will use either uid or a (attribute_code, entity_type) pair. } type CustomAttributeMetadata { - items: [Attribute] + items: [AttributeMetadataInterface] } -type Attribute { - uid: String - attribute_code: String +#base metadata common to all attributes +interface AttributeMetadataInterface { + uid: ID # base64Encode(entityID/codeID) + attribute_code: String @deprecated(reason: "Use `uid` instead") label: String - attribute_type: String @deprecated(reason: "use `attribute_data_type` instead") - attribute_data_type: ObjectDataType - entity_type: EntityType - input_type: UiInputType + data_type: ObjectDataTypeEnum # string, int, float, boolean etc sort_order: Int - metadata_values: [AttributeMetadataValue] - attribute_options: [AttributeOption] } -enum ObjectDataType { - STRING - FLOAT - INT +interface AttributeMetadataEntityTypeInterface { + entity_type: EntityTypeEnum +} + +interface AttributeMetadataUiTypeInterface { + ui_input_type: UiInputTypeEnum +} + +type CustomerAttributeMetadata implements AttributeMetadataInterface, AttributeMetadataEntityTypeInterface, AttributeMetadataUiTypeInterface { + ui_input_type: UiInputTypeInterface! + forms_to_use_in: [CustomAttributesListingsEnum] +} + +type CustomerAddressAttributeMetadata implements AttributeMetadataInterface { +} + +type ProductAttributeMetadata implements AttributeMetadataInterface { +} + +# interfaces for different types used in inputs-------------- + +interface UiInputTypeInterface { + ui_input_type: EntityTypeEnum + value_required: Boolean! +} + +interface InputFilterInterface { + filter: InputValidationFilterEnum +} + +interface InputValidationInterface { + input_validation_type: InputValidationTypeEnum } -enum EntityType { - customer - customer_address - catalog_category - catalog_product - order - invoice - creditmemo - shipment - rma_item +interface AttributeOptionsInterface { + attribute_options: [AttributeOptionInterface] } -enum UiInputType { - text - dropdown - swatch - file - multi_line - #.... +# -------------- +type TextInputType implements UiInputTypeInterface, InputFilterInterface, InputFilterInterface { + default_value: String } -enum MetadataType { - Values_Unique - Values_validation - #... +type InputValidationNone implements InputValidationInterface { } -type AttributeMetadataValue { - label: String - values: [String] - metadata_type: MetadataType +type InputValidationLength implements InputValidationInterface { + minimum_text_length: Int + maximum_text_length: Int } -type AttributeOption { - uid: ID! +#-------------- + +type TextAreaInputType implements UiInputTypeInterface, InputFilterInterface { + default_value: String +} + +type MultipleLineInputType implements UiInputTypeInterface, InputValidationInterface, InputFilterInterface { + default_value: String + lines_count: Int +} + +type FileInputType implements UiInputTypeInterface, InputValidationInterface { + default_value: String + maximum_file_size: Int # bytes + allowed_file_extensions: [String] +} + +type DropDownInputType implements UiInputTypeInterface, InputValidationInterface, AttributeOptionsInterface { + default_value: String +} + +#other types for other entities here + +type AttributeOptionInterface { + uid: ID! # base64Encode(entityID/codeID/OptionID) + is_default: Boolean # marks if an option should be default +} + +# base type of an option existing type +type AttributeOption implements AttributeOptionInterface { + # UID and is_default is imported value: String @deprecated(reason: "use `uid` instead") - label - is_default + label: String +} + +# extended type of an option as it would look like for visual swatches +type AttributeOptionSwatch implements AttributeOptionInterface { + swatch: SwatchOptionInterface +} + +interface SwatchOptionInterface { +} + +type SwatchOptionColor implements SwatchOptionInterface { + color: String # html hex code format +} + +type SwatchOptionImage implements SwatchOptionInterface { + image_path: String # relative path } ``` Additional fields should be added to the metadata response (`Attribute` type), for example `is_dynamic`, `use_in_compare_products`, `display_in_product_listing`, `use_in_advanced_search`, `advanced_search_input_type`. The exact list of fields must be discussed and approved separately. -Introduction of the following query will allow fetching lists of attributes applicable to specific pages: +Introduction of the following query will allow fetching lists of attributes applicable to specific artifacts/listings: ```graphql -pageSpecificCustomAttributes( - page_type: CustomAttributesPageEnum +customAttributesListings( + listing_type: CustomAttributesListingsEnum ): CustomAttributeMetadata -enum CustomAttributesPageEnum { +enum CustomAttributesListingsEnum { PRODUCTS_COMPARE PRODUCTS_LISTING ADVANCED_CATALOG_SEARCH + RMA_FORM + CUSTOMER_REGISTRATION_FORM + CUSTOMER_ADDRESS_FORM } ``` From c711235355733a0052751ffc0c1a0631b5072002 Mon Sep 17 00:00:00 2001 From: Cristian Partica Date: Wed, 10 Feb 2021 10:45:07 -0600 Subject: [PATCH 06/12] refactor some things on product attributes --- .../attributes-metadata.graphqls | 58 +++++++++++-------- .../custom-attributes/attributes-metadata.md | 48 +++++++++------ 2 files changed, 62 insertions(+), 44 deletions(-) diff --git a/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.graphqls b/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.graphqls index d942eacd9..cac70d21c 100644 --- a/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.graphqls +++ b/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.graphqls @@ -1,14 +1,12 @@ -type AttributeInput { - attribute_code: String - entity_type: String - uid: ID +type AttributeMetadataInput { + attribute_uid: ID } type CustomAttributeMetadata { items: [AttributeMetadataInterface] } -#base metadata common to all attributes +# base metadata common to all attributes interface AttributeMetadataInterface { uid: ID # base64Encode(entityID/codeID) label: String @@ -21,25 +19,27 @@ interface AttributeMetadataEntityTypeInterface { } interface AttributeMetadataUiTypeInterface { - ui_input_type: UiInputTypeEnum + ui_input: UiInputTypeInterface! } type CustomerAttributeMetadata implements AttributeMetadataInterface, AttributeMetadataEntityTypeInterface, AttributeMetadataUiTypeInterface { - ui_input_type: UiInputTypeInterface! - forms_to_use_in: [CustomAttributesListingsEnum] + # ui_input_type: UiInputTypeInterface! + # entity_type: EntityTypeEnum + forms_to_use_in: [CustomAttributesListsEnum] } type CustomerAddressAttributeMetadata implements AttributeMetadataInterface { } type ProductAttributeMetadata implements AttributeMetadataInterface { + lists_to_use_in: [CustomAttributesListsEnum] } -# interfaces for different types used in inputs-------------- +# interfaces for different types used in inputs -------------- interface UiInputTypeInterface { ui_input_type: EntityTypeEnum - value_required: Boolean! + is_value_required: Boolean! } interface InputFilterInterface { @@ -48,6 +48,8 @@ interface InputFilterInterface { interface InputValidationInterface { input_validation_type: InputValidationTypeEnum + minimum_text_length: Int + maximum_text_length: Int } interface AttributeOptionsInterface { @@ -55,21 +57,13 @@ interface AttributeOptionsInterface { } # -------------- -type TextInputType implements UiInputTypeInterface, InputFilterInterface, InputFilterInterface { +type TextInputType implements UiInputTypeInterface, InputValidationInterface, InputFilterInterface { default_value: String } -type InputValidationNone implements InputValidationInterface { -} - -type InputValidationLength implements InputValidationInterface { - minimum_text_length: Int - maximum_text_length: Int -} - #-------------- -type TextAreaInputType implements UiInputTypeInterface, InputFilterInterface { +type TextAreaInputType implements UiInputTypeInterface, InputValidationInterface, InputFilterInterface { default_value: String } @@ -98,8 +92,18 @@ type ImageInputType implements UiInputTypeInterface, InputValidationInterface { maximum_image_height: Int # in pixels } -type DropDownInputType implements UiInputTypeInterface, InputValidationInterface, AttributeOptionsInterface { - default_value: String +type DropDownInputType implements UiInputTypeInterface, AttributeOptionsInterface { + default_option: ID +} + +type MultipleSelectInputType implements UiInputTypeInterface, AttributeOptionsInterface { + default_options: [ID] +} + +type SwatchInputType implements UiInputTypeInterface, AttributeOptionsInterface { + default_options: [ID] + update_product_preview_image: Boolean + use_product_image_for_swatch_if_possible: Boolean } #other types for other entities here @@ -197,14 +201,18 @@ enum CustomerAttributeFormsEnum { } type Query { - customAttributesListings( - listing_type: CustomAttributesListingsEnum + customAttributesLists( + list_type: CustomAttributesListsEnum ): CustomAttributeMetadata } -enum CustomAttributesListingsEnum { +enum CustomAttributesListsEnum { PRODUCTS_COMPARE PRODUCTS_LISTING ADVANCED_CATALOG_SEARCH + PRODUCT_SORT + PRODUCT_FILTER + PRODUCT_SEARCH_RESULTS + PRODUCT_AGGREGATIONS RMA_FORM CUSTOMER_REGISTRATION_FORM CUSTOMER_ADDRESS_FORM diff --git a/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.md b/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.md index 7b6032de7..48799430b 100644 --- a/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.md +++ b/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.md @@ -23,11 +23,13 @@ Query.customAttributesMetadata( Added schema: ```graphql +Query.customAttributesMetadataV2( + attributes: [AttributeInput!]! +): CustomAttributeMetadata + #adding to existing type a choice of uid or code and -type AttributeInput { - attribute_code: String #deprecated - entity_type: String #deprecated - uid: ID # we will use either uid or a (attribute_code, entity_type) pair. +type AttributeMetadataInput { + attribute_uid: ID } type CustomAttributeMetadata { @@ -37,10 +39,9 @@ type CustomAttributeMetadata { #base metadata common to all attributes interface AttributeMetadataInterface { uid: ID # base64Encode(entityID/codeID) - attribute_code: String @deprecated(reason: "Use `uid` instead") label: String data_type: ObjectDataTypeEnum # string, int, float, boolean etc - sort_order: Int + sort_order: Int } interface AttributeMetadataEntityTypeInterface { @@ -48,7 +49,7 @@ interface AttributeMetadataEntityTypeInterface { } interface AttributeMetadataUiTypeInterface { - ui_input_type: UiInputTypeEnum + ui_input: UiInputTypeEnum } type CustomerAttributeMetadata implements AttributeMetadataInterface, AttributeMetadataEntityTypeInterface, AttributeMetadataUiTypeInterface { @@ -66,7 +67,7 @@ type ProductAttributeMetadata implements AttributeMetadataInterface { interface UiInputTypeInterface { ui_input_type: EntityTypeEnum - value_required: Boolean! + is_value_required: Boolean! } interface InputFilterInterface { @@ -75,6 +76,8 @@ interface InputFilterInterface { interface InputValidationInterface { input_validation_type: InputValidationTypeEnum + minimum_text_length: Int + maximum_text_length: Int } interface AttributeOptionsInterface { @@ -82,18 +85,10 @@ interface AttributeOptionsInterface { } # -------------- -type TextInputType implements UiInputTypeInterface, InputFilterInterface, InputFilterInterface { +type TextInputType implements UiInputTypeInterface, InputValidationInterface, InputFilterInterface { default_value: String } -type InputValidationNone implements InputValidationInterface { -} - -type InputValidationLength implements InputValidationInterface { - minimum_text_length: Int - maximum_text_length: Int -} - #-------------- type TextAreaInputType implements UiInputTypeInterface, InputFilterInterface { @@ -111,8 +106,18 @@ type FileInputType implements UiInputTypeInterface, InputValidationInterface { allowed_file_extensions: [String] } -type DropDownInputType implements UiInputTypeInterface, InputValidationInterface, AttributeOptionsInterface { - default_value: String +type DropDownInputType implements UiInputTypeInterface, AttributeOptionsInterface { + default_option: ID +} + +type MultipleSelectInputType implements UiInputTypeInterface, AttributeOptionsInterface { + default_options: [ID] +} + +type SwatchInputType implements UiInputTypeInterface, AttributeOptionsInterface { + default_options: [ID] + update_product_preview_image: Boolean + use_product_image_for_swatch_if_possible: Boolean } #other types for other entities here @@ -144,6 +149,11 @@ type SwatchOptionColor implements SwatchOptionInterface { type SwatchOptionImage implements SwatchOptionInterface { image_path: String # relative path } + +type SwatchOptionText implements SwatchOptionInterface { + title: String + description: String +} ``` Additional fields should be added to the metadata response (`Attribute` type), for example `is_dynamic`, `use_in_compare_products`, `display_in_product_listing`, `use_in_advanced_search`, `advanced_search_input_type`. The exact list of fields must be discussed and approved separately. From 763fd6d3260479d586aee78fdb0694c45636e954 Mon Sep 17 00:00:00 2001 From: Cristian Partica Date: Wed, 10 Feb 2021 14:46:39 -0600 Subject: [PATCH 07/12] - refactor options --- .../attributes-metadata.graphqls | 44 +++++++++++-------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.graphqls b/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.graphqls index cac70d21c..0a766d8a3 100644 --- a/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.graphqls +++ b/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.graphqls @@ -56,6 +56,11 @@ interface AttributeOptionsInterface { attribute_options: [AttributeOptionInterface] } +interface AttributeOptionInterface { + uid: ID! + is_default: Boolean +} + # -------------- type TextInputType implements UiInputTypeInterface, InputValidationInterface, InputFilterInterface { default_value: String @@ -100,42 +105,44 @@ type MultipleSelectInputType implements UiInputTypeInterface, AttributeOptionsIn default_options: [ID] } -type SwatchInputType implements UiInputTypeInterface, AttributeOptionsInterface { - default_options: [ID] +type VisualSwatchInputType implements UiInputTypeInterface, AttributeOptionsInterface { + default_option: [ID] update_product_preview_image: Boolean use_product_image_for_swatch_if_possible: Boolean } -#other types for other entities here - - -type AttributeOptionInterface { - uid: ID! # base64Encode(entityID/codeID/OptionID) - is_default: Boolean # marks if an option should be default +type TextSwatchInputType implements UiInputTypeInterface, AttributeOptionsInterface { + default_option: [ID] + update_product_preview_image: Boolean } -# base type of an option existing type + +#other types definitions for other entities ------- type AttributeOption implements AttributeOptionInterface { - # UID and is_default is imported value: String @deprecated(reason: "use `uid` instead") label: String } # extended type of an option as it would look like for visual swatches -type AttributeOptionSwatch implements AttributeOptionInterface { - swatch: SwatchOptionInterface -} +#type AttributeOptionSwatch implements AttributeOptionInterface { +# swatch: SwatchOptionInterface +#} -interface SwatchOptionInterface { -} - -type SwatchOptionColor implements SwatchOptionInterface { +type ColorSwatchAttributeOption implements AttributeOptionInterface { color: String # html hex code format + label: String } -type SwatchOptionImage implements SwatchOptionInterface { +type ImageSwatchAttributeOption implements AttributeOptionInterface { image_path: String # relative path + label: String } + +type TextSwatchAttributeOption implements AttributeOptionInterface { + title: String + description: String +} + # end of swatches variation #enums to support above queries @@ -205,6 +212,7 @@ type Query { list_type: CustomAttributesListsEnum ): CustomAttributeMetadata } + enum CustomAttributesListsEnum { PRODUCTS_COMPARE PRODUCTS_LISTING From c2d29e24a73154229a93fbdf627fe219a2df8f8c Mon Sep 17 00:00:00 2001 From: Cristian Partica Date: Thu, 4 Mar 2021 20:50:57 -0600 Subject: [PATCH 08/12] - reactor types --- .../attributes-metadata.graphqls | 33 ++++++----------- .../custom-attributes/attributes-metadata.md | 37 +++++++++++-------- 2 files changed, 33 insertions(+), 37 deletions(-) diff --git a/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.graphqls b/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.graphqls index 0a766d8a3..94776f181 100644 --- a/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.graphqls +++ b/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.graphqls @@ -1,13 +1,17 @@ +type Query { + customAttributeMetadataV2(attributes: [AttributeMetadataInput!]!): CustomAttributeMetadata + customAttributesLists(listType: CustomAttributesListsEnum): CustomAttributeMetadata +} + type AttributeMetadataInput { attribute_uid: ID } -type CustomAttributeMetadata { +type CustomAttributeMetadata { # this replaces existing Attribute type items: [AttributeMetadataInterface] } -# base metadata common to all attributes -interface AttributeMetadataInterface { +interface AttributeMetadataInterface { # base metadata common to all attributes uid: ID # base64Encode(entityID/codeID) label: String data_type: ObjectDataTypeEnum # string, int, float, boolean etc @@ -23,8 +27,8 @@ interface AttributeMetadataUiTypeInterface { } type CustomerAttributeMetadata implements AttributeMetadataInterface, AttributeMetadataEntityTypeInterface, AttributeMetadataUiTypeInterface { - # ui_input_type: UiInputTypeInterface! - # entity_type: EntityTypeEnum + # ui_input_type: UiInputTypeInterface! #imported + # entity_type: EntityTypeEnum #imported forms_to_use_in: [CustomAttributesListsEnum] } @@ -106,13 +110,13 @@ type MultipleSelectInputType implements UiInputTypeInterface, AttributeOptionsIn } type VisualSwatchInputType implements UiInputTypeInterface, AttributeOptionsInterface { - default_option: [ID] + default_options: [ID] update_product_preview_image: Boolean - use_product_image_for_swatch_if_possible: Boolean + use_product_image: Boolean # use product image for swatch if possible } type TextSwatchInputType implements UiInputTypeInterface, AttributeOptionsInterface { - default_option: [ID] + default_options: [ID] update_product_preview_image: Boolean } @@ -123,11 +127,6 @@ type AttributeOption implements AttributeOptionInterface { label: String } -# extended type of an option as it would look like for visual swatches -#type AttributeOptionSwatch implements AttributeOptionInterface { -# swatch: SwatchOptionInterface -#} - type ColorSwatchAttributeOption implements AttributeOptionInterface { color: String # html hex code format label: String @@ -143,8 +142,6 @@ type TextSwatchAttributeOption implements AttributeOptionInterface { description: String } -# end of swatches variation - #enums to support above queries enum ObjectDataTypeEnum { STRING @@ -207,12 +204,6 @@ enum CustomerAttributeFormsEnum { ADMINHTML_CHECKOUT } -type Query { - customAttributesLists( - list_type: CustomAttributesListsEnum - ): CustomAttributeMetadata -} - enum CustomAttributesListsEnum { PRODUCTS_COMPARE PRODUCTS_LISTING diff --git a/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.md b/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.md index 48799430b..16a1aa80b 100644 --- a/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.md +++ b/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.md @@ -24,7 +24,7 @@ Added schema: ```graphql Query.customAttributesMetadataV2( - attributes: [AttributeInput!]! + attributes: [AttributeMetadataInput!]! ): CustomAttributeMetadata #adding to existing type a choice of uid or code and @@ -114,10 +114,15 @@ type MultipleSelectInputType implements UiInputTypeInterface, AttributeOptionsIn default_options: [ID] } -type SwatchInputType implements UiInputTypeInterface, AttributeOptionsInterface { +type VisualSwatchInputType implements UiInputTypeInterface, AttributeOptionsInterface { + default_options: [ID] + update_product_preview_image: Boolean + use_product_image: Boolean +} + +type TextSwatchInputType implements UiInputTypeInterface, AttributeOptionsInterface { default_options: [ID] update_product_preview_image: Boolean - use_product_image_for_swatch_if_possible: Boolean } #other types for other entities here @@ -134,23 +139,17 @@ type AttributeOption implements AttributeOptionInterface { label: String } -# extended type of an option as it would look like for visual swatches -type AttributeOptionSwatch implements AttributeOptionInterface { - swatch: SwatchOptionInterface -} - -interface SwatchOptionInterface { -} - -type SwatchOptionColor implements SwatchOptionInterface { +type ColorSwatchAttributeOption implements AttributeOptionInterface { color: String # html hex code format + label: String } -type SwatchOptionImage implements SwatchOptionInterface { +type ImageSwatchAttributeOption implements AttributeOptionInterface { image_path: String # relative path + label: String } -type SwatchOptionText implements SwatchOptionInterface { +type TextSwatchAttributeOption implements AttributeOptionInterface { title: String description: String } @@ -160,20 +159,26 @@ Additional fields should be added to the metadata response (`Attribute` type), Introduction of the following query will allow fetching lists of attributes applicable to specific artifacts/listings: ```graphql -customAttributesListings( - listing_type: CustomAttributesListingsEnum +customAttributesLists( + listType: CustomAttributesListingsEnum ): CustomAttributeMetadata enum CustomAttributesListingsEnum { PRODUCTS_COMPARE PRODUCTS_LISTING ADVANCED_CATALOG_SEARCH + PRODUCT_SORT + PRODUCT_FILTER + PRODUCT_SEARCH_RESULTS + PRODUCT_AGGREGATIONS RMA_FORM CUSTOMER_REGISTRATION_FORM CUSTOMER_ADDRESS_FORM } ``` +See full schema [attributes-metadata.graphqls](attributes-metadata.graphqls) + # Alternative solutions GraphQL schema supports [directives](https://graphql.github.io/graphql-spec/June2018/#sec-Language.Directives) which can be used to describe additional information for types, fields, fragments and operations. Since all EAV attributes are automatically added to GraphQL schema in flat structure as fields of the respective types, it is possible to use directives to expose necessary attribute metadata for the client application. From 27243fb375b8049d9d8bd8cde8515cf1b69b9ec4 Mon Sep 17 00:00:00 2001 From: Cristian Partica Date: Thu, 4 Mar 2021 22:21:04 -0600 Subject: [PATCH 09/12] - refactor container explanation --- .../custom-attributes-container.md | 169 +++++++++++++++--- 1 file changed, 147 insertions(+), 22 deletions(-) diff --git a/design-documents/graph-ql/coverage/custom-attributes/custom-attributes-container.md b/design-documents/graph-ql/coverage/custom-attributes/custom-attributes-container.md index 3e29bbdee..b79fa550e 100644 --- a/design-documents/graph-ql/coverage/custom-attributes/custom-attributes-container.md +++ b/design-documents/graph-ql/coverage/custom-attributes/custom-attributes-container.md @@ -8,39 +8,164 @@ One workaround for "getting all fields" is based on schema introspection, it all # Proposed solution -To account for dynamic nature of EAV attributes and the need of "getting all fields" in product search queries, we can introduce `stored_attributes: [StoredAttribute]!` container (recommended approach). +To account for dynamic nature of EAV attributes and the need of "getting all fields" in product search queries, we can introduce `custom_attributes: [CustomAttribute]!` container (recommended approach). The container will return the list of attributes plus the actual values stored for each entity. ```graphql -type StoredAttribute { - selected_attributes: [SelectedAttribute] # used to store unique options values - entered_attributes: [EnteredAttribute] # used to store the freetype entered values like texts - available_attributes: [Attribute] # metadata of the actual attribute not related to the stored Entity-Attribute value +type CustomAttribute { + selected_attribute_options: [SelectedAttributeOption] # used to store unique options values + entered_attribute_value: EnteredAttributeValue # used to store the freetype entered values like texts + attribute_metadata: AttributeMetadataInterface # metadata of the actual attribute not related to the stored Entity-Attribute value } -type SelectedAttribute { - attribute: Attribute # existing type for metadata - options_uids: [ID] +type SelectedAttributeOption { + attribute_option: AttributeOptionInterface + attribute_metadata: AttributeMetadataInterface } -type EnteredAttribute { - attribute: Attribute # existing type for metadata - value: String +type EnteredAttributeValue { + attribute_metadata: AttributeMetadataInterface + value: String } ``` We could also make value complex type to be able add more complex fields values in the future, but this doesn't seem necessary at this point. This is also aligned with the Selected, Entered values from customizable options, or configurable product. -Alternative approach would be is to introduce a type or an interface `custom_attributes: [CustomAttribute]!`. +As for the attribute we would define a concrete type for each entity, because each entity's attributes are different and values of attributes are also complext +For this reason interfaces on multiple levels are the best approach for composability purposes and satisfying values needs like swatches. + +```graphql +type EntityAttributeMetadata implements AttributeMetadataInterface, AttributeMetadataEntityTypeInterface, AttributeMetadataUiTypeInterface { + ui_input_type: UiInputTypeInterface! + forms_to_use_in: [CustomAttributesListingsEnum] +} +# -------- +interface AttributeMetadataInterface { + uid: ID # base64Encode(entityID/codeID) + label: String + data_type: ObjectDataTypeEnum # string, int, float, boolean etc + sort_order: Int +} + +interface AttributeMetadataEntityTypeInterface { + entity_type: EntityTypeEnum +} +interface AttributeMetadataUiTypeInterface { + ui_input: UiInputTypeEnum +} +``` +#### Sample queries for this alternative +```graphql +{ + customner { + custom_attributes { + selected_attribute_options { + attribute_option { + uid + is_default + ... on AttributeOption { + label + is_default + } + } + attribute_metadata { + uid + code + label + } + } + entered_attribute_value { + attribute_metadata { + uid + code + label + } + value + } + attribute_metadata { + uid + code + label # all attributes have a label per store + data_type # enum : string, int, float etc + sort_order # needed for ordering + ... on CustomerAttributeMetadata { + entity_type # enum + forms_to_use_in # only in CustomerAttributeMetadata + ui_input { + ui_input_type + is_value_required + ... on DropDownInputType { + default_option_id #id + attribute_options { + uid + is_default + ... on AttributeOption { + label + } + } + } + ... on TextInputType { + default_value #sting + filter + input_validation { + input_validation_type + minimum_text_length + maximum_text_length + } + } + } + } + ... on ProductAttributeMetadata { + entity_type # enum + lists_to_use_in # only in ProductAttributeMetadata. As opposed to Customer which only had forms + ui_input { + ui_input_type + is_value_required + ... on VisualSwatchInputType { + default_option_id #id + update_product_preview_image + use_product_image_for_swatch_if_possible + attribute_options { + uid + is_default + ... on ColorSwatchAttributeOption { + color + label + } + ... on ImageSwatchAttributeOption { + image_path + label + } + } + } + ... on TextSwatchInputType { + default_option_id #id + update_product_preview_image + attribute_options { + uid + is_default + ... on SwatchOptionText { + title + description + } + } + } + } + } + } + } + } +} +``` +### Alternatives considered ```graphql type CustomAttribute { code: String! values: [String]! # We want to account fo attributes that have single (text, dropdown) and multiple values (checkbox, multiselect) } ``` -Or to introduce a type or an interface `custom_attributes: [CustomAttributeInterface]!`, but it seems more complicated. ```graphql interface CustomAttributeInterface { @@ -62,7 +187,7 @@ Flat representation of custom attributes in `ProductInterface` (and other EAV en It is necessary to keep in mind that with `custom_attributes` it is not possible to query product EAV attributes selectively, which may lead to performance degradation. -### Sample queries +#### Sample queries for this alternative Current implementation allows the following query ```graphql @@ -90,14 +215,14 @@ Let's assume the response will be "name": "Test Simple Product", "sku": "testSimpleProduct", "color": "Red", - "manufacturer": "Company A" + "manufacturer": "Company A", "size": null }, { "name": "Test Configurable Product", "sku": "testConfigProduct", "color": null, - "manufacturer": "Company B" + "manufacturer": "Company B", "size": "XXL" } ] @@ -134,11 +259,11 @@ Note that color and size are not applicable to some products in the search resul "sku": "testSimpleProduct", "custom_attributes": [ { - "code": "color" + "code": "color", "value": "Red" }, { - "code": "manufacturer" + "code": "manufacturer", "value": "Company A" } ] @@ -148,22 +273,22 @@ Note that color and size are not applicable to some products in the search resul "sku": "testConfigProduct", "custom_attributes": [ { - "code": "manufacturer" + "code": "manufacturer", "value": "Company B" }, { - "code": "size" + "code": "size", "value": "XXL" } ] - }, + } ] } } } ``` -# Alternatives considered +### Other Alternatives considered 1. [Persisted queries](https://github.com/magento/graphql-ce/issues/781) can be leveraged to mitigate described issue with the increased size of the request. 1. To improve flexibility and allow support of complex structures, `type` can be added to the definition of `CustomAttribute` in the future, if there are valid use cases. From 49ed7128b4052a7186655a556517631162283499 Mon Sep 17 00:00:00 2001 From: Cristian Partica Date: Thu, 4 Mar 2021 22:47:03 -0600 Subject: [PATCH 10/12] - rename option ids --- .../attributes-metadata.graphqls | 32 +++++++++++-------- .../custom-attributes/attributes-metadata.md | 29 ++++++++++------- 2 files changed, 35 insertions(+), 26 deletions(-) diff --git a/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.graphqls b/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.graphqls index 94776f181..f9fa29f59 100644 --- a/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.graphqls +++ b/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.graphqls @@ -66,34 +66,34 @@ interface AttributeOptionInterface { } # -------------- -type TextInputType implements UiInputTypeInterface, InputValidationInterface, InputFilterInterface { +type TextUiInputType implements UiInputTypeInterface, InputValidationInterface, InputFilterInterface { default_value: String } #-------------- -type TextAreaInputType implements UiInputTypeInterface, InputValidationInterface, InputFilterInterface { +type TextAreaUiInputType implements UiInputTypeInterface, InputValidationInterface, InputFilterInterface { default_value: String } -type MultipleLineInputType implements UiInputTypeInterface, InputValidationInterface, InputFilterInterface { +type MultipleLineUiInputType implements UiInputTypeInterface, InputValidationInterface, InputFilterInterface { default_value: String lines_count: Int } -type DateInputType implements UiInputTypeInterface, InputValidationInterface { +type DateUiInputType implements UiInputTypeInterface, InputValidationInterface { default_value: String minimum_date_allowed: String maximum_date_allowed: String } -type FileInputType implements UiInputTypeInterface, InputValidationInterface { +type FileUiInputType implements UiInputTypeInterface, InputValidationInterface { default_value: String maximum_file_size: Int # bytes allowed_file_extensions: [String] } -type ImageInputType implements UiInputTypeInterface, InputValidationInterface { +type ImageUiInputType implements UiInputTypeInterface, InputValidationInterface { default_value: String maximum_file_size: Int # bytes allowed_file_extensions: [String] @@ -101,22 +101,26 @@ type ImageInputType implements UiInputTypeInterface, InputValidationInterface { maximum_image_height: Int # in pixels } -type DropDownInputType implements UiInputTypeInterface, AttributeOptionsInterface { - default_option: ID +interface SingleSelectionUiInputTypeInterface { + default_option_id: ID } -type MultipleSelectInputType implements UiInputTypeInterface, AttributeOptionsInterface { - default_options: [ID] +interface MultipleSelectionUiInputTypeInterface { + default_options_ids: [ID] } -type VisualSwatchInputType implements UiInputTypeInterface, AttributeOptionsInterface { - default_options: [ID] +type DropDownUiInputType implements UiInputTypeInterface, AttributeOptionsInterface, SingleSelectionUiInputTypeInterface { +} + +type MultipleSelectUiInputType implements UiInputTypeInterface, AttributeOptionsInterface, MultipleSelectionUiInputTypeInterface { +} + +type VisualSwatchUiInputType implements UiInputTypeInterface, AttributeOptionsInterface, SingleSelectionUiInputTypeInterface { update_product_preview_image: Boolean use_product_image: Boolean # use product image for swatch if possible } -type TextSwatchInputType implements UiInputTypeInterface, AttributeOptionsInterface { - default_options: [ID] +type TextSwatchUiInputType implements UiInputTypeInterface, AttributeOptionsInterface, SingleSelectionUiInputTypeInterface { update_product_preview_image: Boolean } diff --git a/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.md b/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.md index 16a1aa80b..075988910 100644 --- a/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.md +++ b/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.md @@ -85,43 +85,48 @@ interface AttributeOptionsInterface { } # -------------- -type TextInputType implements UiInputTypeInterface, InputValidationInterface, InputFilterInterface { +type TextUiInputType implements UiInputTypeInterface, InputValidationInterface, InputFilterInterface { default_value: String } #-------------- -type TextAreaInputType implements UiInputTypeInterface, InputFilterInterface { +type TextAreaUiInputType implements UiInputTypeInterface, InputFilterInterface { default_value: String } -type MultipleLineInputType implements UiInputTypeInterface, InputValidationInterface, InputFilterInterface { +type MultipleLineUiInputType implements UiInputTypeInterface, InputValidationInterface, InputFilterInterface { default_value: String lines_count: Int } -type FileInputType implements UiInputTypeInterface, InputValidationInterface { +type FileUiInputType implements UiInputTypeInterface, InputValidationInterface { default_value: String maximum_file_size: Int # bytes allowed_file_extensions: [String] } -type DropDownInputType implements UiInputTypeInterface, AttributeOptionsInterface { - default_option: ID +interface SingleSelectionUiInputTypeInterface { + default_option_id: ID } -type MultipleSelectInputType implements UiInputTypeInterface, AttributeOptionsInterface { - default_options: [ID] +interface MultipleSelectionUiInputTypeInterface { + default_options_ids: [ID] } -type VisualSwatchInputType implements UiInputTypeInterface, AttributeOptionsInterface { - default_options: [ID] +type DropDownUiInputType implements UiInputTypeInterface, AttributeOptionsInterface, MultipleSelectionUiInputTypeInterface { + default_option_id: ID +} + +type MultipleSelectUiInputType implements UiInputTypeInterface, AttributeOptionsInterface, SingleSelectionUiInputTypeInterface { +} + +type VisualSwatchUiInputType implements UiInputTypeInterface, AttributeOptionsInterface, SingleSelectionUiInputTypeInterface { update_product_preview_image: Boolean use_product_image: Boolean } -type TextSwatchInputType implements UiInputTypeInterface, AttributeOptionsInterface { - default_options: [ID] +type TextSwatchUiInputType implements UiInputTypeInterface, AttributeOptionsInterface, SingleSelectionUiInputTypeInterface { update_product_preview_image: Boolean } From 74fd87e7c1c8a8c752a20f5731684a7bcf309734 Mon Sep 17 00:00:00 2001 From: Cristian Partica Date: Fri, 12 Mar 2021 21:06:59 -0600 Subject: [PATCH 11/12] refactoring to simplify query and schema --- .../attributes-metadata.graphqls | 80 +++++------ .../custom-attributes/attributes-metadata.md | 95 ++++--------- .../custom-attributes-container.md | 133 ++++++++---------- 3 files changed, 120 insertions(+), 188 deletions(-) diff --git a/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.graphqls b/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.graphqls index f9fa29f59..19c857376 100644 --- a/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.graphqls +++ b/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.graphqls @@ -16,19 +16,11 @@ interface AttributeMetadataInterface { # base metadata common to all attributes label: String data_type: ObjectDataTypeEnum # string, int, float, boolean etc sort_order: Int -} - -interface AttributeMetadataEntityTypeInterface { entity_type: EntityTypeEnum -} - -interface AttributeMetadataUiTypeInterface { ui_input: UiInputTypeInterface! } -type CustomerAttributeMetadata implements AttributeMetadataInterface, AttributeMetadataEntityTypeInterface, AttributeMetadataUiTypeInterface { - # ui_input_type: UiInputTypeInterface! #imported - # entity_type: EntityTypeEnum #imported +type CustomerAttributeMetadata implements AttributeMetadataInterface { forms_to_use_in: [CustomAttributesListsEnum] } @@ -46,14 +38,12 @@ interface UiInputTypeInterface { is_value_required: Boolean! } -interface InputFilterInterface { +interface ValidationTextInputTypeInterface { filter: InputValidationFilterEnum } -interface InputValidationInterface { - input_validation_type: InputValidationTypeEnum - minimum_text_length: Int - maximum_text_length: Int +interface FilterableTextInputTypeInterface { + input_validation: FilterableText } interface AttributeOptionsInterface { @@ -63,86 +53,88 @@ interface AttributeOptionsInterface { interface AttributeOptionInterface { uid: ID! is_default: Boolean + label: String } -# -------------- -type TextUiInputType implements UiInputTypeInterface, InputValidationInterface, InputFilterInterface { +interface SelectableInputTypeInterface { + +} + +interface TextInputTypeInterface { default_value: String } -#-------------- +type FilterableText { + input_validation_type: InputValidationTypeEnum + minimum_text_length: Int + maximum_text_length: Int +} + +type TextUiInputType implements UiInputTypeInterface, TextInputTypeInterface, FilterableTextInputTypeInterface, ValidationTextInputTypeInterface { -type TextAreaUiInputType implements UiInputTypeInterface, InputValidationInterface, InputFilterInterface { - default_value: String } -type MultipleLineUiInputType implements UiInputTypeInterface, InputValidationInterface, InputFilterInterface { - default_value: String +type TextAreaUiInputType implements UiInputTypeInterface, TextInputTypeInterface, FilterableTextInputTypeInterface, ValidationTextInputTypeInterface { + +} + +type MultipleLineUiInputType implements UiInputTypeInterface, TextInputTypeInterface, FilterableTextInputTypeInterface, ValidationTextInputTypeInterface { lines_count: Int } -type DateUiInputType implements UiInputTypeInterface, InputValidationInterface { - default_value: String +type DateUiInputType implements UiInputTypeInterface, TextInputTypeInterface, FilterableTextInputTypeInterface { minimum_date_allowed: String maximum_date_allowed: String } -type FileUiInputType implements UiInputTypeInterface, InputValidationInterface { - default_value: String +type FileUiInputType implements UiInputTypeInterface, TextInputTypeInterface, FilterableTextInputTypeInterface { maximum_file_size: Int # bytes allowed_file_extensions: [String] } -type ImageUiInputType implements UiInputTypeInterface, InputValidationInterface { - default_value: String +type ImageUiInputType implements UiInputTypeInterface, TextInputTypeInterface, FilterableTextInputTypeInterface { maximum_file_size: Int # bytes allowed_file_extensions: [String] maximum_image_width: Int # in pixels maximum_image_height: Int # in pixels } -interface SingleSelectionUiInputTypeInterface { - default_option_id: ID +type DropDownUiInputType implements UiInputTypeInterface, SelectableInputTypeInterface, AttributeOptionsInterface { } -interface MultipleSelectionUiInputTypeInterface { - default_options_ids: [ID] +type MultipleSelectUiInputType implements UiInputTypeInterface, SelectableInputTypeInterface, AttributeOptionsInterface { } -type DropDownUiInputType implements UiInputTypeInterface, AttributeOptionsInterface, SingleSelectionUiInputTypeInterface { +interface SwatchInputTypeInterface { + update_product_preview_image: Boolean } -type MultipleSelectUiInputType implements UiInputTypeInterface, AttributeOptionsInterface, MultipleSelectionUiInputTypeInterface { +type VisualSwatchUiInputType implements UiInputTypeInterface, SelectableInputTypeInterface, AttributeOptionsInterface, SwatchInputTypeInterface { + use_product_image_for_swatch_if_possible: Boolean } -type VisualSwatchUiInputType implements UiInputTypeInterface, AttributeOptionsInterface, SingleSelectionUiInputTypeInterface { - update_product_preview_image: Boolean - use_product_image: Boolean # use product image for swatch if possible -} +type TextSwatchUiInputType implements UiInputTypeInterface, SelectableInputTypeInterface, AttributeOptionsInterface, SwatchInputTypeInterface { -type TextSwatchUiInputType implements UiInputTypeInterface, AttributeOptionsInterface, SingleSelectionUiInputTypeInterface { - update_product_preview_image: Boolean } - -#other types definitions for other entities ------- type AttributeOption implements AttributeOptionInterface { value: String @deprecated(reason: "use `uid` instead") label: String } +interface SelectableInputTypeInterface { + +} + type ColorSwatchAttributeOption implements AttributeOptionInterface { color: String # html hex code format - label: String } type ImageSwatchAttributeOption implements AttributeOptionInterface { image_path: String # relative path - label: String } type TextSwatchAttributeOption implements AttributeOptionInterface { - title: String description: String } diff --git a/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.md b/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.md index 075988910..7185bec1c 100644 --- a/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.md +++ b/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.md @@ -32,136 +32,99 @@ type AttributeMetadataInput { attribute_uid: ID } -type CustomAttributeMetadata { +type CustomAttributeMetadata { # this replaces existing Attribute type items: [AttributeMetadataInterface] } -#base metadata common to all attributes -interface AttributeMetadataInterface { +interface AttributeMetadataInterface { # base metadata common to all attributes uid: ID # base64Encode(entityID/codeID) label: String data_type: ObjectDataTypeEnum # string, int, float, boolean etc - sort_order: Int -} - -interface AttributeMetadataEntityTypeInterface { + sort_order: Int entity_type: EntityTypeEnum + ui_input: UiInputTypeInterface! } -interface AttributeMetadataUiTypeInterface { - ui_input: UiInputTypeEnum -} - -type CustomerAttributeMetadata implements AttributeMetadataInterface, AttributeMetadataEntityTypeInterface, AttributeMetadataUiTypeInterface { - ui_input_type: UiInputTypeInterface! - forms_to_use_in: [CustomAttributesListingsEnum] +type CustomerAttributeMetadata implements AttributeMetadataInterface { + forms_to_use_in: [CustomAttributesListsEnum] } type CustomerAddressAttributeMetadata implements AttributeMetadataInterface { } type ProductAttributeMetadata implements AttributeMetadataInterface { + lists_to_use_in: [CustomAttributesListsEnum] } -# interfaces for different types used in inputs-------------- - -interface UiInputTypeInterface { - ui_input_type: EntityTypeEnum - is_value_required: Boolean! -} - -interface InputFilterInterface { - filter: InputValidationFilterEnum -} +type TextUiInputType implements UiInputTypeInterface, TextInputTypeInterface, FilterableTextInputTypeInterface, ValidationTextInputTypeInterface { -interface InputValidationInterface { - input_validation_type: InputValidationTypeEnum - minimum_text_length: Int - maximum_text_length: Int } -interface AttributeOptionsInterface { - attribute_options: [AttributeOptionInterface] -} +type TextAreaUiInputType implements UiInputTypeInterface, TextInputTypeInterface, FilterableTextInputTypeInterface, ValidationTextInputTypeInterface { -# -------------- -type TextUiInputType implements UiInputTypeInterface, InputValidationInterface, InputFilterInterface { - default_value: String } -#-------------- - -type TextAreaUiInputType implements UiInputTypeInterface, InputFilterInterface { - default_value: String +type MultipleLineUiInputType implements UiInputTypeInterface, TextInputTypeInterface, FilterableTextInputTypeInterface, ValidationTextInputTypeInterface { + lines_count: Int } -type MultipleLineUiInputType implements UiInputTypeInterface, InputValidationInterface, InputFilterInterface { - default_value: String - lines_count: Int +type DateUiInputType implements UiInputTypeInterface, TextInputTypeInterface, FilterableTextInputTypeInterface { + minimum_date_allowed: String + maximum_date_allowed: String } -type FileUiInputType implements UiInputTypeInterface, InputValidationInterface { - default_value: String +type FileUiInputType implements UiInputTypeInterface, TextInputTypeInterface, FilterableTextInputTypeInterface { maximum_file_size: Int # bytes allowed_file_extensions: [String] } -interface SingleSelectionUiInputTypeInterface { - default_option_id: ID -} - -interface MultipleSelectionUiInputTypeInterface { - default_options_ids: [ID] +type ImageUiInputType implements UiInputTypeInterface, TextInputTypeInterface, FilterableTextInputTypeInterface { + maximum_file_size: Int # bytes + allowed_file_extensions: [String] + maximum_image_width: Int # in pixels + maximum_image_height: Int # in pixels } -type DropDownUiInputType implements UiInputTypeInterface, AttributeOptionsInterface, MultipleSelectionUiInputTypeInterface { - default_option_id: ID +type DropDownUiInputType implements UiInputTypeInterface, SelectableInputTypeInterface, AttributeOptionsInterface { } -type MultipleSelectUiInputType implements UiInputTypeInterface, AttributeOptionsInterface, SingleSelectionUiInputTypeInterface { +type MultipleSelectUiInputType implements UiInputTypeInterface, SelectableInputTypeInterface, AttributeOptionsInterface { } -type VisualSwatchUiInputType implements UiInputTypeInterface, AttributeOptionsInterface, SingleSelectionUiInputTypeInterface { +interface SwatchInputTypeInterface { update_product_preview_image: Boolean - use_product_image: Boolean } -type TextSwatchUiInputType implements UiInputTypeInterface, AttributeOptionsInterface, SingleSelectionUiInputTypeInterface { - update_product_preview_image: Boolean +type VisualSwatchUiInputType implements UiInputTypeInterface, SelectableInputTypeInterface, AttributeOptionsInterface, SwatchInputTypeInterface { + use_product_image_for_swatch_if_possible: Boolean } -#other types for other entities here +type TextSwatchUiInputType implements UiInputTypeInterface, SelectableInputTypeInterface, AttributeOptionsInterface, SwatchInputTypeInterface { -type AttributeOptionInterface { - uid: ID! # base64Encode(entityID/codeID/OptionID) - is_default: Boolean # marks if an option should be default } -# base type of an option existing type type AttributeOption implements AttributeOptionInterface { - # UID and is_default is imported value: String @deprecated(reason: "use `uid` instead") label: String } type ColorSwatchAttributeOption implements AttributeOptionInterface { color: String # html hex code format - label: String } type ImageSwatchAttributeOption implements AttributeOptionInterface { image_path: String # relative path - label: String } type TextSwatchAttributeOption implements AttributeOptionInterface { - title: String description: String } ``` Additional fields should be added to the metadata response (`Attribute` type), for example `is_dynamic`, `use_in_compare_products`, `display_in_product_listing`, `use_in_advanced_search`, `advanced_search_input_type`. The exact list of fields must be discussed and approved separately. +See full schema [attributes-metadata.graphqls](attributes-metadata.graphqls) + Introduction of the following query will allow fetching lists of attributes applicable to specific artifacts/listings: ```graphql customAttributesLists( @@ -182,8 +145,6 @@ enum CustomAttributesListingsEnum { } ``` -See full schema [attributes-metadata.graphqls](attributes-metadata.graphqls) - # Alternative solutions GraphQL schema supports [directives](https://graphql.github.io/graphql-spec/June2018/#sec-Language.Directives) which can be used to describe additional information for types, fields, fragments and operations. Since all EAV attributes are automatically added to GraphQL schema in flat structure as fields of the respective types, it is possible to use directives to expose necessary attribute metadata for the client application. diff --git a/design-documents/graph-ql/coverage/custom-attributes/custom-attributes-container.md b/design-documents/graph-ql/coverage/custom-attributes/custom-attributes-container.md index b79fa550e..afd20409d 100644 --- a/design-documents/graph-ql/coverage/custom-attributes/custom-attributes-container.md +++ b/design-documents/graph-ql/coverage/custom-attributes/custom-attributes-container.md @@ -41,18 +41,13 @@ type EntityAttributeMetadata implements AttributeMetadataInterface, AttributeMet forms_to_use_in: [CustomAttributesListingsEnum] } # -------- -interface AttributeMetadataInterface { +interface AttributeMetadataInterface { # base metadata common to all attributes uid: ID # base64Encode(entityID/codeID) label: String data_type: ObjectDataTypeEnum # string, int, float, boolean etc - sort_order: Int -} - -interface AttributeMetadataEntityTypeInterface { + sort_order: Int entity_type: EntityTypeEnum -} -interface AttributeMetadataUiTypeInterface { - ui_input: UiInputTypeEnum + ui_input: UiInputTypeInterface! } ``` #### Sample queries for this alternative @@ -84,75 +79,59 @@ interface AttributeMetadataUiTypeInterface { value } attribute_metadata { - uid - code - label # all attributes have a label per store - data_type # enum : string, int, float etc - sort_order # needed for ordering - ... on CustomerAttributeMetadata { - entity_type # enum - forms_to_use_in # only in CustomerAttributeMetadata - ui_input { - ui_input_type - is_value_required - ... on DropDownInputType { - default_option_id #id - attribute_options { - uid - is_default - ... on AttributeOption { - label - } - } - } - ... on TextInputType { - default_value #sting - filter - input_validation { - input_validation_type - minimum_text_length - maximum_text_length - } - } - } - } - ... on ProductAttributeMetadata { - entity_type # enum - lists_to_use_in # only in ProductAttributeMetadata. As opposed to Customer which only had forms - ui_input { - ui_input_type - is_value_required - ... on VisualSwatchInputType { - default_option_id #id - update_product_preview_image - use_product_image_for_swatch_if_possible - attribute_options { - uid - is_default - ... on ColorSwatchAttributeOption { - color - label - } - ... on ImageSwatchAttributeOption { - image_path - label - } - } - } - ... on TextSwatchInputType { - default_option_id #id - update_product_preview_image - attribute_options { - uid - is_default - ... on SwatchOptionText { - title - description - } - } - } - } - } + uid + code + label # all attributes have a label per store + data_type # enum : string, int, float etc + sort_order # needed for ordering + + entity_type # enum + ... on CustomerAttributeMetadata { + forms_to_use_in # only in CustomerAttributeMetadata + } + ... on ProductAttributeMetadata { + lists_to_use_in # only in ProductAttributeMetadata. As opposed to Customer which only had forms + } + ui_input { + __typename + ui_input_type + is_value_required + ... on SelectableInputTypeInterface { + ... on SwatchInputTypeInterface { + update_product_preview_image + } + ... on VisualSwatchInputType { + use_product_image_for_swatch_if_possible + } + attribute_options { + uid + is_default + label + ... on ColorSwatchAttributeOption { + color + } + ... on ImageSwatchAttributeOption { + image_path + } + ... on TextSwatchAttributeOption { + description + } + } + } + ... on TextInputTypeInterface { + default_value # string + ... on FilterableTextInputTypeInterface { + filter # enum + } + ... on ValidationTextInputTypeInterface { + input_validation { + input_validation_type + minimum_text_length + maximum_text_length + } + } + } + } } } } From b36547489ddc802c6114338b0bc107a5376c6197 Mon Sep 17 00:00:00 2001 From: Cristian Partica Date: Fri, 12 Mar 2021 21:11:19 -0600 Subject: [PATCH 12/12] refactoring to simplify query and schema --- .../coverage/custom-attributes/attributes-metadata.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.md b/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.md index 7185bec1c..3a1d64047 100644 --- a/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.md +++ b/design-documents/graph-ql/coverage/custom-attributes/attributes-metadata.md @@ -24,11 +24,11 @@ Added schema: ```graphql Query.customAttributesMetadataV2( - attributes: [AttributeMetadataInput!]! + attributes: [AttributeMetadataInput!] ): CustomAttributeMetadata #adding to existing type a choice of uid or code and -type AttributeMetadataInput { +input AttributeMetadataInput { attribute_uid: ID }