diff --git a/locale/defaultMessages.json b/locale/defaultMessages.json index d003b874a55..1c9ec66ec84 100644 --- a/locale/defaultMessages.json +++ b/locale/defaultMessages.json @@ -853,57 +853,17 @@ "context": "dialog content", "string": "Are you sure you want to delete {attributeName}?" }, - "src_dot_attributes_dot_components_dot_AttributeDetails_dot_125992234": { - "context": "numeric attribute unit", - "string": "Unit" - }, - "src_dot_attributes_dot_components_dot_AttributeDetails_dot_1390397602": { - "context": "numeric attribute unit system", - "string": "System" - }, - "src_dot_attributes_dot_components_dot_AttributeDetails_dot_157021805": { - "context": "numeric attribute units of", - "string": "Units of" - }, - "src_dot_attributes_dot_components_dot_AttributeDetails_dot_1576912740": { - "context": "area units type", - "string": "Area" - }, - "src_dot_attributes_dot_components_dot_AttributeDetails_dot_1963548912": { - "context": "imperial unit system", - "string": "Imperial" - }, - "src_dot_attributes_dot_components_dot_AttributeDetails_dot_2262354018": { + "src_dot_attributes_dot_components_dot_AttributeDetails_dot_acreFt": { "context": "acre-ft unit", "string": "acre-ft" }, - "src_dot_attributes_dot_components_dot_AttributeDetails_dot_2947839983": { - "context": "metric unit system", - "string": "Metric" - }, - "src_dot_attributes_dot_components_dot_AttributeDetails_dot_3595883383": { - "context": "volume units types", - "string": "Volume" - }, - "src_dot_attributes_dot_components_dot_AttributeDetails_dot_3723486670": { - "context": "pint unit", - "string": "pint" - }, - "src_dot_attributes_dot_components_dot_AttributeDetails_dot_3863978694": { + "src_dot_attributes_dot_components_dot_AttributeDetails_dot_acreInch": { "context": "acre-inch unit", "string": "acre-inch" }, - "src_dot_attributes_dot_components_dot_AttributeDetails_dot_3889193046": { - "context": "distance units type", - "string": "Distance" - }, - "src_dot_attributes_dot_components_dot_AttributeDetails_dot_746695941": { - "context": "weight units type", - "string": "Weight" - }, - "src_dot_attributes_dot_components_dot_AttributeDetails_dot_935262293": { - "context": "check to require numeric attribute unit", - "string": "Select unit" + "src_dot_attributes_dot_components_dot_AttributeDetails_dot_area": { + "context": "area units type", + "string": "Area" }, "src_dot_attributes_dot_components_dot_AttributeDetails_dot_attributeLabel": { "context": "attribute's label", @@ -917,6 +877,10 @@ "context": "attribute slug input field helper text", "string": "This is used internally. Make sure you don’t use spaces" }, + "src_dot_attributes_dot_components_dot_AttributeDetails_dot_distance": { + "context": "distance units type", + "string": "Distance" + }, "src_dot_attributes_dot_components_dot_AttributeDetails_dot_dropdown": { "context": "product attribute type", "string": "Dropdown" @@ -929,10 +893,18 @@ "context": "file attribute type", "string": "File" }, + "src_dot_attributes_dot_components_dot_AttributeDetails_dot_imperial": { + "context": "imperial unit system", + "string": "Imperial" + }, "src_dot_attributes_dot_components_dot_AttributeDetails_dot_inputType": { "context": "attribute's editor component", "string": "Catalog Input type for Store Owner" }, + "src_dot_attributes_dot_components_dot_AttributeDetails_dot_metric": { + "context": "metric unit system", + "string": "Metric" + }, "src_dot_attributes_dot_components_dot_AttributeDetails_dot_multiselect": { "context": "product attribute type", "string": "Multiple Select" @@ -945,6 +917,10 @@ "context": "page attribute entity type", "string": "Pages" }, + "src_dot_attributes_dot_components_dot_AttributeDetails_dot_pint": { + "context": "pint unit", + "string": "pint" + }, "src_dot_attributes_dot_components_dot_AttributeDetails_dot_product": { "context": "product attribute entity type", "string": "Products" @@ -953,14 +929,38 @@ "context": "references attribute type", "string": "References" }, + "src_dot_attributes_dot_components_dot_AttributeDetails_dot_selectUnit": { + "context": "check to require numeric attribute unit", + "string": "Select unit" + }, "src_dot_attributes_dot_components_dot_AttributeDetails_dot_text": { "context": "text attribute type", "string": "Text" }, + "src_dot_attributes_dot_components_dot_AttributeDetails_dot_unit": { + "context": "numeric attribute unit", + "string": "Unit" + }, + "src_dot_attributes_dot_components_dot_AttributeDetails_dot_unitOf": { + "context": "numeric attribute units of", + "string": "Units of" + }, + "src_dot_attributes_dot_components_dot_AttributeDetails_dot_unitSystem": { + "context": "numeric attribute unit system", + "string": "System" + }, "src_dot_attributes_dot_components_dot_AttributeDetails_dot_valueRequired": { "context": "check to require attribute to have value", "string": "Value Required" }, + "src_dot_attributes_dot_components_dot_AttributeDetails_dot_volume": { + "context": "volume units types", + "string": "Volume" + }, + "src_dot_attributes_dot_components_dot_AttributeDetails_dot_weight": { + "context": "weight units type", + "string": "Weight" + }, "src_dot_attributes_dot_components_dot_AttributeListPage_dot_2417065806": { "context": "tab name", "string": "All Attributes" diff --git a/schema.graphql b/schema.graphql index 42c765d560c..9b54e9d0459 100644 --- a/schema.graphql +++ b/schema.graphql @@ -4215,10 +4215,10 @@ enum ProductFieldEnum { PRODUCT_WEIGHT COLLECTIONS CHARGE_TAXES - PRODUCT_IMAGES + PRODUCT_MEDIA VARIANT_SKU VARIANT_WEIGHT - VARIANT_IMAGES + VARIANT_MEDIA } input ProductFilterInput { diff --git a/src/attributes/components/AttributeDetails/NumericUnits.tsx b/src/attributes/components/AttributeDetails/NumericUnits.tsx index c1697d032dc..0620eb16e87 100644 --- a/src/attributes/components/AttributeDetails/NumericUnits.tsx +++ b/src/attributes/components/AttributeDetails/NumericUnits.tsx @@ -2,13 +2,15 @@ import { AttributePageFormData } from "@saleor/attributes/components/AttributePa import ControlledCheckbox from "@saleor/components/ControlledCheckbox"; import SingleSelectField from "@saleor/components/SingleSelectField"; import { UseFormResult } from "@saleor/hooks/useForm"; +import { commonMessages } from "@saleor/intl"; import { makeStyles } from "@saleor/theme"; import { MeasurementUnitsEnum } from "@saleor/types/globalTypes"; -import React, { useEffect, useState } from "react"; +import React, { useEffect, useMemo, useState } from "react"; +import { useIntl } from "react-intl"; import * as M from "./messages"; import { - unitChoices, + getUnitChoices, unitMapping, UnitSystem, unitSystemChoices, @@ -19,11 +21,11 @@ import { const useStyles = makeStyles( theme => ({ unitsRow: { - columnGap: theme.spacing(2) + "px", + columnGap: theme.spacing(2), display: "flex", [theme.breakpoints.down("sm")]: { flexFlow: "wrap", - rowGap: theme.spacing(3) + "px" + rowGap: theme.spacing(3) } }, hr: { @@ -38,9 +40,9 @@ const useStyles = makeStyles( ); interface UnitData { - unit: MeasurementUnitsEnum; - system: UnitSystem; - type: UnitType; + unit?: MeasurementUnitsEnum; + system?: UnitSystem; + type?: UnitType; } interface NumericUnitsProps @@ -59,40 +61,63 @@ export const NumericUnits: React.FC = ({ setError, clearErrors }) => { + const { formatMessage } = useIntl(); const classes = useStyles(); - const [unitData, setUnitData] = useState>({ + const [unitData, setUnitData] = useState({ unit: data.unit }); const { unit, system, type } = unitData; - const errorProps = { error: !!errors.unit, hint: M.required }; + const errorProps = { + error: !!errors.unit, + hint: formatMessage(commonMessages.requiredField) + }; + const [typeChoices, systemChoices, unitChoices] = useMemo( + () => [ + unitTypeChoices.map(choice => ({ + ...choice, + label: formatMessage(choice.label) + })), + unitSystemChoices.map(choice => ({ + ...choice, + label: formatMessage(choice.label) + })), + getUnitChoices(formatMessage) + ], + [] + ); useEffect(() => set({ unit }), [unit]); useEffect(() => { if (data.unit) { - const initialData = { unit: data.unit } as UnitData; + const selectInitialUnitData = () => { + const initialData: UnitData = { unit: data.unit }; - Object.entries(unitChoices).find(([system, types]) => { - const systemMatch = Object.entries(types).find(([type, units]) => { - const unitMatch = units.find(({ value }) => value === data.unit); - if (unitMatch) { - initialData.type = type as UnitType; + Object.entries(unitChoices).some(([system, types]) => { + const systemMatch = Object.entries(types).some(([type, units]) => { + const unitMatch = units.some(({ value }) => value === data.unit); + if (unitMatch) { + initialData.type = type as UnitType; + } + return unitMatch; + }); + if (systemMatch) { + initialData.system = system as UnitSystem; } - return unitMatch; + return systemMatch; }); - if (systemMatch) { - initialData.system = system as UnitSystem; - } - return systemMatch; - }); - setUnitData(initialData); + + return initialData; + }; + + setUnitData(selectInitialUnitData()); } }, []); useEffect(() => { if (unit === undefined && !errors.unit) { - setError("unit", M.required); + setError("unit", formatMessage(commonMessages.requiredField)); } if (errors.unit && (unit || unit === null)) { clearErrors("unit"); @@ -105,7 +130,7 @@ export const NumericUnits: React.FC = ({ setUnitData({ unit: target.value ? undefined : null }) @@ -117,19 +142,24 @@ export const NumericUnits: React.FC = ({ setUnitData({ system: target.value })} + label={formatMessage(M.messages.unitSystem)} + choices={systemChoices} + onChange={({ target }: React.ChangeEvent) => + setUnitData({ system: target.value as UnitSystem }) + } value={system} disabled={disabled} /> - setUnitData(({ system }) => ({ system, type: target.value })) + label={formatMessage(M.messages.unitOf)} + choices={typeChoices} + onChange={({ target }: React.ChangeEvent) => + setUnitData(({ system }) => ({ + system, + type: target.value as UnitType + })) } disabled={!system || disabled} value={type} @@ -137,10 +167,13 @@ export const NumericUnits: React.FC = ({ - setUnitData(p => ({ ...p, unit: target.value })) + onChange={({ target }: React.ChangeEvent) => + setUnitData(data => ({ + ...data, + unit: target.value as MeasurementUnitsEnum + })) } disabled={!type || disabled} value={ diff --git a/src/attributes/components/AttributeDetails/messages.tsx b/src/attributes/components/AttributeDetails/messages.tsx index a20aefdd89c..e9a2c23b428 100644 --- a/src/attributes/components/AttributeDetails/messages.tsx +++ b/src/attributes/components/AttributeDetails/messages.tsx @@ -1,6 +1,5 @@ -import { commonMessages } from "@saleor/intl"; import React from "react"; -import { defineMessages, FormattedMessage } from "react-intl"; +import { defineMessages } from "react-intl"; export const messages = defineMessages({ attributeLabel: { @@ -26,6 +25,25 @@ export const messages = defineMessages({ valueRequired: { defaultMessage: "Value Required", description: "check to require attribute to have value" + }, + selectUnit: { + defaultMessage: "Select unit", + description: "check to require numeric attribute unit" + }, + + unitSystem: { + defaultMessage: "System", + description: "numeric attribute unit system" + }, + + unitOf: { + defaultMessage: "Units of", + description: "numeric attribute units of" + }, + + unit: { + defaultMessage: "Unit", + description: "numeric attribute unit" } }); @@ -56,71 +74,42 @@ export const inputTypeMessages = defineMessages({ } }); -export const selectUnit = ( - -); - -export const unitSystem = ( - -); - -export const unitOf = ( - -); - -export const unit = ( - -); - -export const required = ; - -/** - * Unit System - */ -export const metric = ( - -); - -export const imperial = ( - -); - -/** - * Unit type - */ -export const volume = ( - -); +export const unitSystemMessages = defineMessages({ + metric: { + defaultMessage: "Metric", + description: "metric unit system" + }, + imperial: { + defaultMessage: "Imperial", + description: "imperial unit system" + } +}); -export const distance = ( - -); +export const unitTypeMessages = defineMessages({ + volume: { + defaultMessage: "Volume", + description: "volume units types" + }, -export const weight = ( - -); + distance: { + defaultMessage: "Distance", + description: "distance units type" + }, + weight: { + defaultMessage: "Weight", + description: "weight units type" + }, + area: { + defaultMessage: "Area", + description: "area units type" + } +}); -export const area = ( - -); +export const unitMessages = defineMessages({ + pint: { defaultMessage: "pint", description: "pint unit" }, + acreInch: { defaultMessage: "acre-inch", description: "acre-inch unit" }, + acreFt: { defaultMessage: "acre-ft", description: "acre-ft unit" } +}); export const units = { cubicCentimeter: <>cm³, @@ -141,13 +130,9 @@ export const units = { cubicYard: <>yd³, qt: "qt", flOz: "fl. oz", - pint: , - acreInch: ( - - ), - acreFt: ( - - ), + pint: unitMessages.pint, + acreInch: unitMessages.acreInch, + acreFt: unitMessages.acreFt, ft: "ft", yd: "yd", inch: "in", diff --git a/src/attributes/components/AttributeDetails/utils.ts b/src/attributes/components/AttributeDetails/utils.ts index 8a62ed18022..9936a2c4a8d 100644 --- a/src/attributes/components/AttributeDetails/utils.ts +++ b/src/attributes/components/AttributeDetails/utils.ts @@ -1,70 +1,81 @@ import { Choice } from "@saleor/components/SingleSelectField"; import { MeasurementUnitsEnum } from "@saleor/types/globalTypes"; +import React from "react"; +import { IntlShape, MessageDescriptor } from "react-intl"; import * as M from "./messages"; export type UnitSystem = "imperial" | "metric"; export type UnitType = "volume" | "weight" | "area" | "distance"; -export const getMeasurementUnitMessage = (unit: MeasurementUnitsEnum) => - ({ - [MeasurementUnitsEnum.CUBIC_FOOT]: M.units.cubicFoot, - [MeasurementUnitsEnum.CUBIC_INCH]: M.units.cubicInch, - [MeasurementUnitsEnum.CUBIC_YARD]: M.units.cubicYard, - [MeasurementUnitsEnum.QT]: M.units.qt, - [MeasurementUnitsEnum.FL_OZ]: M.units.flOz, - [MeasurementUnitsEnum.PINT]: M.units.pint, - [MeasurementUnitsEnum.ACRE_IN]: M.units.acreInch, - [MeasurementUnitsEnum.ACRE_FT]: M.units.acreFt, - [MeasurementUnitsEnum.FT]: M.units.ft, - [MeasurementUnitsEnum.YD]: M.units.yd, - [MeasurementUnitsEnum.INCH]: M.units.inch, - [MeasurementUnitsEnum.LB]: M.units.lbs, - [MeasurementUnitsEnum.OZ]: M.units.oz, - [MeasurementUnitsEnum.SQ_FT]: M.units.squareFt, - [MeasurementUnitsEnum.SQ_YD]: M.units.squareYd, - [MeasurementUnitsEnum.SQ_INCH]: M.units.squareInch, - [MeasurementUnitsEnum.CUBIC_CENTIMETER]: M.units.cubicCentimeter, - [MeasurementUnitsEnum.CUBIC_DECIMETER]: M.units.cubicDecimeter, - [MeasurementUnitsEnum.CUBIC_METER]: M.units.cubicMeter, - [MeasurementUnitsEnum.LITER]: M.units.liter, - [MeasurementUnitsEnum.CM]: M.units.centimeter, - [MeasurementUnitsEnum.M]: M.units.meter, - [MeasurementUnitsEnum.KM]: M.units.kilometer, - [MeasurementUnitsEnum.G]: M.units.gram, - [MeasurementUnitsEnum.KG]: M.units.kilogram, - [MeasurementUnitsEnum.TONNE]: M.units.tonne, - [MeasurementUnitsEnum.SQ_CM]: M.units.squareCentimeter, - [MeasurementUnitsEnum.SQ_M]: M.units.squareMeter, - [MeasurementUnitsEnum.SQ_KM]: M.units.squareKilometer - }[unit]); +const UNIT_MESSAGES_MAPPING = { + [MeasurementUnitsEnum.CUBIC_FOOT]: M.units.cubicFoot, + [MeasurementUnitsEnum.CUBIC_INCH]: M.units.cubicInch, + [MeasurementUnitsEnum.CUBIC_YARD]: M.units.cubicYard, + [MeasurementUnitsEnum.QT]: M.units.qt, + [MeasurementUnitsEnum.FL_OZ]: M.units.flOz, + [MeasurementUnitsEnum.PINT]: M.units.pint, + [MeasurementUnitsEnum.ACRE_IN]: M.units.acreInch, + [MeasurementUnitsEnum.ACRE_FT]: M.units.acreFt, + [MeasurementUnitsEnum.FT]: M.units.ft, + [MeasurementUnitsEnum.YD]: M.units.yd, + [MeasurementUnitsEnum.INCH]: M.units.inch, + [MeasurementUnitsEnum.LB]: M.units.lbs, + [MeasurementUnitsEnum.OZ]: M.units.oz, + [MeasurementUnitsEnum.SQ_FT]: M.units.squareFt, + [MeasurementUnitsEnum.SQ_YD]: M.units.squareYd, + [MeasurementUnitsEnum.SQ_INCH]: M.units.squareInch, + [MeasurementUnitsEnum.CUBIC_CENTIMETER]: M.units.cubicCentimeter, + [MeasurementUnitsEnum.CUBIC_DECIMETER]: M.units.cubicDecimeter, + [MeasurementUnitsEnum.CUBIC_METER]: M.units.cubicMeter, + [MeasurementUnitsEnum.LITER]: M.units.liter, + [MeasurementUnitsEnum.CM]: M.units.centimeter, + [MeasurementUnitsEnum.M]: M.units.meter, + [MeasurementUnitsEnum.KM]: M.units.kilometer, + [MeasurementUnitsEnum.G]: M.units.gram, + [MeasurementUnitsEnum.KG]: M.units.kilogram, + [MeasurementUnitsEnum.TONNE]: M.units.tonne, + [MeasurementUnitsEnum.SQ_CM]: M.units.squareCentimeter, + [MeasurementUnitsEnum.SQ_M]: M.units.squareMeter, + [MeasurementUnitsEnum.SQ_KM]: M.units.squareKilometer +}; + +export const getMeasurementUnitMessage = ( + unit: MeasurementUnitsEnum, + formatMessage: IntlShape["formatMessage"] +): MessageDescriptor | React.ReactNode => { + const message = UNIT_MESSAGES_MAPPING[unit]; + return typeof message === "string" || React.isValidElement(message) + ? message + : formatMessage(message); +}; -export const unitSystemChoices: Array> = [ +export const unitSystemChoices: Array> = [ { - label: M.metric, + label: M.unitSystemMessages.metric, value: "metric" }, { - label: M.imperial, + label: M.unitSystemMessages.imperial, value: "imperial" } ]; -export const unitTypeChoices: Array> = [ +export const unitTypeChoices: Array> = [ { - label: M.volume, + label: M.unitTypeMessages.volume, value: "volume" }, { - label: M.distance, + label: M.unitTypeMessages.distance, value: "distance" }, { - label: M.weight, + label: M.unitTypeMessages.weight, value: "weight" }, { - label: M.area, + label: M.unitTypeMessages.area, value: "area" } ]; @@ -118,24 +129,38 @@ export const unitMapping = { } }; -export const unitChoices = (() => - Object.entries(unitMapping).reduce( - (acc, [system, type]) => ({ +const extractTypeChoices = ( + typeEnums: { + [key in UnitType]: MeasurementUnitsEnum[]; + }, + formatMessage: IntlShape["formatMessage"] +) => + Object.entries(typeEnums).reduce( + (acc, [type, units]) => ({ ...acc, - [system]: Object.entries(type).reduce( - (acc, [type, units]) => ({ - ...acc, - [type]: units.map(unit => ({ - value: unit, - label: getMeasurementUnitMessage(unit) - })) - }), - {} - ) + [type]: units.map(unit => ({ + value: unit, + label: getMeasurementUnitMessage(unit, formatMessage) + })) }), {} - ))() as { + ); + +export const getUnitChoices = ( + formatMessage: IntlShape["formatMessage"] +): { [key in UnitSystem]: { [key in UnitType]: Array>; }; -}; +} => + Object.entries(unitMapping).reduce( + (acc, [system, typeEnums]) => ({ + ...acc, + [system]: extractTypeChoices(typeEnums, formatMessage) + }), + {} + ) as { + [key in UnitSystem]: { + [key in UnitType]: Array>; + }; + }; diff --git a/src/attributes/components/AttributePage/AttributePage.tsx b/src/attributes/components/AttributePage/AttributePage.tsx index ea5dbfc5a5f..02dac4c8d29 100644 --- a/src/attributes/components/AttributePage/AttributePage.tsx +++ b/src/attributes/components/AttributePage/AttributePage.tsx @@ -118,7 +118,7 @@ const AttributePage: React.FC = ({ storefrontSearchPosition: attribute?.storefrontSearchPosition.toString() ?? "", type: attribute?.type || AttributeTypeEnum.PRODUCT_TYPE, - valueRequired: attribute?.valueRequired ?? true, + valueRequired: !!attribute?.valueRequired ?? true, visibleInStorefront: attribute?.visibleInStorefront ?? true, unit: attribute?.unit || null }; diff --git a/src/components/Attributes/AttributeRow.tsx b/src/components/Attributes/AttributeRow.tsx index ef0b460dea9..0e575b7cf6d 100644 --- a/src/components/Attributes/AttributeRow.tsx +++ b/src/components/Attributes/AttributeRow.tsx @@ -177,7 +177,10 @@ const AttributeRow: React.FC = ({ attribute.data.unit && { endAdornment: ( - {getMeasurementUnitMessage(attribute.data.unit)} + {getMeasurementUnitMessage( + attribute.data.unit, + intl.formatMessage + )} ) } diff --git a/src/components/SingleSelectField/SingleSelectField.tsx b/src/components/SingleSelectField/SingleSelectField.tsx index a92ce25cf17..25de8186c08 100644 --- a/src/components/SingleSelectField/SingleSelectField.tsx +++ b/src/components/SingleSelectField/SingleSelectField.tsx @@ -28,9 +28,9 @@ const useStyles = makeStyles( { name: "SingleSelectField" } ); -export interface Choice { +export interface Choice { value: T; - label: string | React.ReactNode; + label: L; } export type Choices = Choice[]; diff --git a/src/fragments/pages.ts b/src/fragments/pages.ts index b9f49c980b1..fc887643563 100644 --- a/src/fragments/pages.ts +++ b/src/fragments/pages.ts @@ -23,6 +23,7 @@ export const pageAttributesFragment = gql` inputType entityType valueRequired + unit values { ...AttributeValueFragment } diff --git a/src/fragments/types/PageAttributesFragment.ts b/src/fragments/types/PageAttributesFragment.ts index aabe979d47a..625a5b7627e 100644 --- a/src/fragments/types/PageAttributesFragment.ts +++ b/src/fragments/types/PageAttributesFragment.ts @@ -3,7 +3,7 @@ // @generated // This file was automatically generated and should not be edited. -import { AttributeInputTypeEnum, AttributeEntityTypeEnum } from "./../../types/globalTypes"; +import { AttributeInputTypeEnum, AttributeEntityTypeEnum, MeasurementUnitsEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL fragment: PageAttributesFragment @@ -33,6 +33,7 @@ export interface PageAttributesFragment_attributes_attribute { inputType: AttributeInputTypeEnum | null; entityType: AttributeEntityTypeEnum | null; valueRequired: boolean; + unit: MeasurementUnitsEnum | null; values: (PageAttributesFragment_attributes_attribute_values | null)[] | null; } diff --git a/src/fragments/types/PageDetailsFragment.ts b/src/fragments/types/PageDetailsFragment.ts index 20bce742b19..45719c1c2a8 100644 --- a/src/fragments/types/PageDetailsFragment.ts +++ b/src/fragments/types/PageDetailsFragment.ts @@ -3,7 +3,7 @@ // @generated // This file was automatically generated and should not be edited. -import { AttributeInputTypeEnum, AttributeEntityTypeEnum } from "./../../types/globalTypes"; +import { AttributeInputTypeEnum, AttributeEntityTypeEnum, MeasurementUnitsEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL fragment: PageDetailsFragment @@ -33,6 +33,7 @@ export interface PageDetailsFragment_attributes_attribute { inputType: AttributeInputTypeEnum | null; entityType: AttributeEntityTypeEnum | null; valueRequired: boolean; + unit: MeasurementUnitsEnum | null; values: (PageDetailsFragment_attributes_attribute_values | null)[] | null; } diff --git a/src/hooks/useForm.ts b/src/hooks/useForm.ts index ca13f813fdd..5fb19376dd4 100644 --- a/src/hooks/useForm.ts +++ b/src/hooks/useForm.ts @@ -1,5 +1,6 @@ import { toggle } from "@saleor/utils/lists"; import isEqual from "lodash-es/isEqual"; +import omit from "lodash/omit"; import React from "react"; import { useState } from "react"; @@ -136,16 +137,13 @@ function useForm( const setError = (field: keyof T, error: string | React.ReactNode) => setErrors(e => ({ ...e, [field]: error })); - const clearErrors = (field: keyof T | Array) => { + const clearErrors = (field?: keyof T | Array) => { if (!field) { setErrors({}); } else { - setErrors(e => { - (Array.isArray(field) ? field : [field]).forEach(name => { - delete e[name]; - }); - return e; - }); + setErrors(errors => + omit>(errors, Array.isArray(field) ? field : [field]) + ); } }; diff --git a/src/pages/fixtures.ts b/src/pages/fixtures.ts index 39d6dd409ab..dd89b685044 100644 --- a/src/pages/fixtures.ts +++ b/src/pages/fixtures.ts @@ -48,6 +48,7 @@ export const page: PageDetails_page = { entityType: null, inputType: AttributeInputTypeEnum.DROPDOWN, valueRequired: false, + unit: null, values: [ { id: "QXR0cmlidXRlVmFsdWU6ODc=", @@ -100,6 +101,7 @@ export const page: PageDetails_page = { entityType: null, inputType: AttributeInputTypeEnum.MULTISELECT, valueRequired: false, + unit: null, values: [ { id: "QXR0cmlidXRlVmFsdWU6OTA=", diff --git a/src/pages/types/PageCreate.ts b/src/pages/types/PageCreate.ts index 437d089ec42..326d6c78212 100644 --- a/src/pages/types/PageCreate.ts +++ b/src/pages/types/PageCreate.ts @@ -3,7 +3,7 @@ // @generated // This file was automatically generated and should not be edited. -import { PageCreateInput, PageErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum } from "./../../types/globalTypes"; +import { PageCreateInput, PageErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, MeasurementUnitsEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: PageCreate @@ -41,6 +41,7 @@ export interface PageCreate_pageCreate_page_attributes_attribute { inputType: AttributeInputTypeEnum | null; entityType: AttributeEntityTypeEnum | null; valueRequired: boolean; + unit: MeasurementUnitsEnum | null; values: (PageCreate_pageCreate_page_attributes_attribute_values | null)[] | null; } diff --git a/src/pages/types/PageDetails.ts b/src/pages/types/PageDetails.ts index 1cb8238deb3..a2c33a4e1a0 100644 --- a/src/pages/types/PageDetails.ts +++ b/src/pages/types/PageDetails.ts @@ -3,7 +3,7 @@ // @generated // This file was automatically generated and should not be edited. -import { AttributeInputTypeEnum, AttributeEntityTypeEnum } from "./../../types/globalTypes"; +import { AttributeInputTypeEnum, AttributeEntityTypeEnum, MeasurementUnitsEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL query operation: PageDetails @@ -33,6 +33,7 @@ export interface PageDetails_page_attributes_attribute { inputType: AttributeInputTypeEnum | null; entityType: AttributeEntityTypeEnum | null; valueRequired: boolean; + unit: MeasurementUnitsEnum | null; values: (PageDetails_page_attributes_attribute_values | null)[] | null; } diff --git a/src/pages/types/PageUpdate.ts b/src/pages/types/PageUpdate.ts index 74e6cfc5d21..38849430411 100644 --- a/src/pages/types/PageUpdate.ts +++ b/src/pages/types/PageUpdate.ts @@ -3,7 +3,7 @@ // @generated // This file was automatically generated and should not be edited. -import { PageInput, PageErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum } from "./../../types/globalTypes"; +import { PageInput, PageErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, MeasurementUnitsEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: PageUpdate @@ -40,6 +40,7 @@ export interface PageUpdate_pageUpdate_page_attributes_attribute { inputType: AttributeInputTypeEnum | null; entityType: AttributeEntityTypeEnum | null; valueRequired: boolean; + unit: MeasurementUnitsEnum | null; values: (PageUpdate_pageUpdate_page_attributes_attribute_values | null)[] | null; } diff --git a/src/pages/utils/data.ts b/src/pages/utils/data.ts index 083383dfe28..63b850332d4 100644 --- a/src/pages/utils/data.ts +++ b/src/pages/utils/data.ts @@ -15,7 +15,8 @@ export function getAttributeInputFromPage( inputType: attribute.attribute.inputType, isRequired: attribute.attribute.valueRequired, selectedValues: attribute.values, - values: attribute.attribute.values + values: attribute.attribute.values, + unit: attribute.attribute.unit }, id: attribute.attribute.id, label: attribute.attribute.name, diff --git a/src/productTypes/fixtures.ts b/src/productTypes/fixtures.ts index cb412f85073..7fccb75a23c 100644 --- a/src/productTypes/fixtures.ts +++ b/src/productTypes/fixtures.ts @@ -22,6 +22,7 @@ export const attributes: ProductType_productType_productAttributes[] = [ name: "Author", slug: "author", valueRequired: true, + unit: null, values: [ { __typename: "AttributeValue" as "AttributeValue", @@ -59,6 +60,7 @@ export const attributes: ProductType_productType_productAttributes[] = [ name: "Box Size", slug: "box-size", valueRequired: true, + unit: null, values: [ { __typename: "AttributeValue" as "AttributeValue", @@ -120,6 +122,7 @@ export const attributes: ProductType_productType_productAttributes[] = [ name: "Brand", slug: "brand", valueRequired: true, + unit: null, values: [ { __typename: "AttributeValue" as "AttributeValue", @@ -145,6 +148,7 @@ export const attributes: ProductType_productType_productAttributes[] = [ name: "Candy Box Size", slug: "candy-box-size", valueRequired: true, + unit: null, values: [ { __typename: "AttributeValue" as "AttributeValue", @@ -194,6 +198,7 @@ export const attributes: ProductType_productType_productAttributes[] = [ name: "Coffee Genre", slug: "coffee-genre", valueRequired: true, + unit: null, values: [ { __typename: "AttributeValue" as "AttributeValue", @@ -231,6 +236,7 @@ export const attributes: ProductType_productType_productAttributes[] = [ name: "Collar", slug: "collar", valueRequired: true, + unit: null, values: [ { __typename: "AttributeValue" as "AttributeValue", @@ -280,6 +286,7 @@ export const attributes: ProductType_productType_productAttributes[] = [ name: "Color", slug: "color", valueRequired: true, + unit: null, values: [ { __typename: "AttributeValue" as "AttributeValue", @@ -317,6 +324,7 @@ export const attributes: ProductType_productType_productAttributes[] = [ name: "Cover", slug: "cover", valueRequired: true, + unit: null, values: [ { __typename: "AttributeValue" as "AttributeValue", @@ -402,6 +410,7 @@ export const attributes: ProductType_productType_productAttributes[] = [ name: "Flavor", slug: "flavor", valueRequired: true, + unit: null, values: [ { __typename: "AttributeValue" as "AttributeValue", @@ -439,6 +448,7 @@ export const attributes: ProductType_productType_productAttributes[] = [ name: "Language", slug: "language", valueRequired: true, + unit: null, values: [ { __typename: "AttributeValue" as "AttributeValue", @@ -476,6 +486,7 @@ export const attributes: ProductType_productType_productAttributes[] = [ name: "Publisher", slug: "publisher", valueRequired: true, + unit: null, values: [ { __typename: "AttributeValue" as "AttributeValue", @@ -513,6 +524,7 @@ export const attributes: ProductType_productType_productAttributes[] = [ name: "Size", slug: "size", valueRequired: true, + unit: null, values: [ { __typename: "AttributeValue" as "AttributeValue", @@ -680,6 +692,7 @@ export const productTypes: Array = ({ fields={[ ProductFieldEnum.DESCRIPTION, ProductFieldEnum.NAME, - ProductFieldEnum.PRODUCT_IMAGES, - ProductFieldEnum.VARIANT_IMAGES + ProductFieldEnum.PRODUCT_MEDIA, + ProductFieldEnum.VARIANT_MEDIA ]} onChange={handleFieldChange} onToggleAll={handleToggleAllFields} diff --git a/src/products/components/ProductExportDialog/messages.ts b/src/products/components/ProductExportDialog/messages.ts index e5dd38442c4..2e983fa1058 100644 --- a/src/products/components/ProductExportDialog/messages.ts +++ b/src/products/components/ProductExportDialog/messages.ts @@ -30,7 +30,7 @@ function useProductExportFieldMessages() { description: "product field", id: "productExportFieldName" }), - [ProductFieldEnum.PRODUCT_IMAGES]: intl.formatMessage({ + [ProductFieldEnum.PRODUCT_MEDIA]: intl.formatMessage({ defaultMessage: "Product Images", description: "product field", id: "productExportFieldProductImages" @@ -45,7 +45,7 @@ function useProductExportFieldMessages() { description: "product field", id: "productExportFieldProductWeight" }), - [ProductFieldEnum.VARIANT_IMAGES]: intl.formatMessage({ + [ProductFieldEnum.VARIANT_MEDIA]: intl.formatMessage({ defaultMessage: "Variant Images", description: "product field", id: "productExportFieldVariantImages" diff --git a/src/products/queries.ts b/src/products/queries.ts index d5cd3c7641e..30b53aa0f79 100644 --- a/src/products/queries.ts +++ b/src/products/queries.ts @@ -219,6 +219,7 @@ const productTypeQuery = gql` slug name valueRequired + unit values { ...AttributeValueFragment } diff --git a/src/products/types/ProductType.ts b/src/products/types/ProductType.ts index 9f829698ce9..4f65a8c14c5 100644 --- a/src/products/types/ProductType.ts +++ b/src/products/types/ProductType.ts @@ -3,7 +3,7 @@ // @generated // This file was automatically generated and should not be edited. -import { AttributeInputTypeEnum, AttributeEntityTypeEnum } from "./../../types/globalTypes"; +import { AttributeInputTypeEnum, AttributeEntityTypeEnum, MeasurementUnitsEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL query operation: ProductType @@ -33,6 +33,7 @@ export interface ProductType_productType_productAttributes { slug: string | null; name: string | null; valueRequired: boolean; + unit: MeasurementUnitsEnum | null; values: (ProductType_productType_productAttributes_values | null)[] | null; } diff --git a/src/products/utils/data.ts b/src/products/utils/data.ts index b66ac294cfa..b9d7400bcf8 100644 --- a/src/products/utils/data.ts +++ b/src/products/utils/data.ts @@ -52,7 +52,8 @@ export function getAttributeInputFromProduct( inputType: attribute.attribute.inputType, isRequired: attribute.attribute.valueRequired, selectedValues: attribute.values, - values: attribute.attribute.values + values: attribute.attribute.values, + unit: attribute.attribute.unit }, id: attribute.attribute.id, label: attribute.attribute.name, @@ -70,7 +71,8 @@ export function getAttributeInputFromProductType( entityType: attribute.entityType, inputType: attribute.inputType, isRequired: attribute.valueRequired, - values: attribute.values + values: attribute.values, + unit: attribute.unit }, id: attribute.id, label: attribute.name, diff --git a/src/storybook/__snapshots__/Stories.test.ts.snap b/src/storybook/__snapshots__/Stories.test.ts.snap index 9ef7446e397..0fe52f73c53 100644 --- a/src/storybook/__snapshots__/Stories.test.ts.snap +++ b/src/storybook/__snapshots__/Stories.test.ts.snap @@ -36368,14 +36368,13 @@ exports[`Storyshots Views / Attributes / Attribute details loading 1`] = ` > - diff --git a/src/types/globalTypes.ts b/src/types/globalTypes.ts index 632ee13b42e..ae31a90f4b7 100644 --- a/src/types/globalTypes.ts +++ b/src/types/globalTypes.ts @@ -843,10 +843,10 @@ export enum ProductFieldEnum { COLLECTIONS = "COLLECTIONS", DESCRIPTION = "DESCRIPTION", NAME = "NAME", - PRODUCT_IMAGES = "PRODUCT_IMAGES", + PRODUCT_MEDIA = "PRODUCT_MEDIA", PRODUCT_TYPE = "PRODUCT_TYPE", PRODUCT_WEIGHT = "PRODUCT_WEIGHT", - VARIANT_IMAGES = "VARIANT_IMAGES", + VARIANT_MEDIA = "VARIANT_MEDIA", VARIANT_SKU = "VARIANT_SKU", VARIANT_WEIGHT = "VARIANT_WEIGHT", VISIBLE = "VISIBLE",