Numeric attributes (#1065)

* Update schema, types

* Add numeric unit control

* Improvements, tests

* Cleanup

* Add messages

* Small fixes

* Add test id's

* Improve useForm, logic

* Use short names

* Review corrections

* Small improvements
This commit is contained in:
Piotr Grundas 2021-04-29 10:58:03 +02:00 committed by GitHub
parent 074c0f7a6c
commit 2a21609eae
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
80 changed files with 1209 additions and 189 deletions

View file

@ -33,6 +33,7 @@ All notable, unreleased changes to this project will be documented in this file.
- Add multiline field plugins - #974 by @dominik-zeglen
- Handle limit reached error - #990 by @dominik-zeglen
- Display Cloud limits - #1004 by @dominik-zeglen
- Introducing numeric attributes - #1065 by @piotrgrundas
- Add shipping method description - #1058 by @jwm0
- Fix voucher and sales sorting errors - #1063 by @orzechdev
- Fix custom currency formatting - #1067 by @orzechdev

View file

@ -869,6 +869,18 @@
"context": "dialog content",
"string": "Are you sure you want to delete {attributeName}?"
},
"src_dot_attributes_dot_components_dot_AttributeDetails_dot_acreFt": {
"context": "acre-ft unit",
"string": "acre-ft"
},
"src_dot_attributes_dot_components_dot_AttributeDetails_dot_acreInch": {
"context": "acre-inch unit",
"string": "acre-inch"
},
"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",
"string": "Default Label"
@ -881,6 +893,10 @@
"context": "attribute slug input field helper text",
"string": "This is used internally. Make sure you dont 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"
@ -893,18 +909,34 @@
"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"
},
"src_dot_attributes_dot_components_dot_AttributeDetails_dot_numeric": {
"context": "numeric attribute type",
"string": "Numeric"
},
"src_dot_attributes_dot_components_dot_AttributeDetails_dot_page": {
"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"
@ -913,14 +945,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"

6
package-lock.json generated
View file

@ -2802,7 +2802,6 @@
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
"dev": true,
"optional": true,
"requires": {
"is-extendable": "^0.1.0"
}
@ -2848,7 +2847,6 @@
"resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
"integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
"dev": true,
"optional": true,
"requires": {
"kind-of": "^3.0.2"
}
@ -2858,7 +2856,6 @@
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
"dev": true,
"optional": true,
"requires": {
"is-buffer": "^1.1.5"
}
@ -27839,7 +27836,6 @@
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
"dev": true,
"optional": true,
"requires": {
"is-extendable": "^0.1.0"
}
@ -27885,7 +27881,6 @@
"resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
"integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
"dev": true,
"optional": true,
"requires": {
"kind-of": "^3.0.2"
}
@ -27895,7 +27890,6 @@
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
"dev": true,
"optional": true,
"requires": {
"is-buffer": "^1.1.5"
}

View file

@ -382,6 +382,15 @@ type AppUpdate {
app: App
}
enum AreaUnitsEnum {
SQ_CM
SQ_M
SQ_KM
SQ_FT
SQ_YD
SQ_INCH
}
type AssignNavigation {
menu: Menu
menuErrors: [MenuError!]! @deprecated(reason: "Use errors field instead. This field will be removed in Saleor 4.0.")
@ -399,6 +408,7 @@ type Attribute implements Node & ObjectWithMetadata {
name: String
slug: String
type: AttributeTypeEnum
unit: MeasurementUnitsEnum
values: [AttributeValue]
valueRequired: Boolean!
visibleInStorefront: Boolean!
@ -438,6 +448,7 @@ input AttributeCreateInput {
name: String!
slug: String
type: AttributeTypeEnum!
unit: MeasurementUnitsEnum
values: [AttributeValueCreateInput]
valueRequired: Boolean
isVariantOnly: Boolean
@ -493,6 +504,7 @@ input AttributeFilterInput {
input AttributeInput {
slug: String!
values: [String]
valuesRange: IntRangeInput
}
enum AttributeInputTypeEnum {
@ -500,6 +512,7 @@ enum AttributeInputTypeEnum {
MULTISELECT
FILE
REFERENCE
NUMERIC
RICH_TEXT
}
@ -559,6 +572,7 @@ type AttributeUpdate {
input AttributeUpdateInput {
name: String
slug: String
unit: MeasurementUnitsEnum
removeValues: [ID]
addValues: [AttributeValueCreateInput]
valueRequired: Boolean
@ -1781,6 +1795,15 @@ enum DiscountValueTypeEnum {
PERCENTAGE
}
enum DistanceUnitsEnum {
CM
M
KM
FT
YD
INCH
}
type Domain {
host: String!
sslEnabled: Boolean!
@ -2367,6 +2390,39 @@ type Margin {
stop: Int
}
enum MeasurementUnitsEnum {
CM
M
KM
FT
YD
INCH
SQ_CM
SQ_M
SQ_KM
SQ_FT
SQ_YD
SQ_INCH
CUBIC_MILLIMETER
CUBIC_CENTIMETER
CUBIC_DECIMETER
CUBIC_METER
LITER
CUBIC_FOOT
CUBIC_INCH
CUBIC_YARD
QT
PINT
FL_OZ
ACRE_IN
ACRE_FT
G
LB
OZ
KG
TONNE
}
type Menu implements Node & ObjectWithMetadata {
id: ID!
name: String!
@ -5637,6 +5693,22 @@ type VerifyToken {
errors: [AccountError!]!
}
enum VolumeUnitsEnum {
CUBIC_MILLIMETER
CUBIC_CENTIMETER
CUBIC_DECIMETER
CUBIC_METER
LITER
CUBIC_FOOT
CUBIC_INCH
CUBIC_YARD
QT
PINT
FL_OZ
ACRE_IN
ACRE_FT
}
type Voucher implements Node {
id: ID!
name: String
@ -6043,10 +6115,11 @@ type Weight {
scalar WeightScalar
enum WeightUnitsEnum {
KG
G
LB
OZ
G
KG
TONNE
}
scalar _Any

View file

@ -1,11 +1,13 @@
import Card from "@material-ui/core/Card";
import CardContent from "@material-ui/core/CardContent";
import TextField from "@material-ui/core/TextField";
import { NumericUnits } from "@saleor/attributes/components/AttributeDetails/NumericUnits";
import CardTitle from "@saleor/components/CardTitle";
import ControlledCheckbox from "@saleor/components/ControlledCheckbox";
import FormSpacer from "@saleor/components/FormSpacer";
import SingleSelectField from "@saleor/components/SingleSelectField";
import { AttributeErrorFragment } from "@saleor/fragments/types/AttributeErrorFragment";
import { UseFormResult } from "@saleor/hooks/useForm";
import { commonMessages } from "@saleor/intl";
import { makeStyles } from "@saleor/theme";
import {
@ -20,56 +22,7 @@ import slugify from "slugify";
import { getAttributeSlugErrorMessage } from "../../errors";
import { AttributePageFormData } from "../AttributePage";
const messages = defineMessages({
attributeLabel: {
defaultMessage: "Default Label",
description: "attribute's label"
},
attributeSlug: {
defaultMessage: "Attribute Code",
description: "attribute's slug short code label"
},
attributeSlugHelperText: {
defaultMessage: "This is used internally. Make sure you dont use spaces",
description: "attribute slug input field helper text"
},
entityType: {
defaultMessage: "Entity",
description: "attribute's editor component entity"
},
inputType: {
defaultMessage: "Catalog Input type for Store Owner",
description: "attribute's editor component"
},
valueRequired: {
defaultMessage: "Value Required",
description: "check to require attribute to have value"
}
});
const inputTypeMessages = defineMessages({
dropdown: {
defaultMessage: "Dropdown",
description: "product attribute type"
},
file: {
defaultMessage: "File",
description: "file attribute type"
},
multiselect: {
defaultMessage: "Multiple Select",
description: "product attribute type"
},
references: {
defaultMessage: "References",
description: "references attribute type"
},
text: {
defaultMessage: "Text",
description: "text attribute type"
}
});
import { inputTypeMessages, messages } from "./messages";
const entityTypeMessages = defineMessages({
page: {
@ -96,16 +49,29 @@ const useStyles = makeStyles(
{ name: "AttributeDetails" }
);
export interface AttributeDetailsProps {
export interface AttributeDetailsProps
extends Pick<
UseFormResult<AttributePageFormData>,
"set" | "setError" | "data" | "clearErrors" | "errors"
> {
canChangeType: boolean;
data: AttributePageFormData;
disabled: boolean;
errors: AttributeErrorFragment[];
apiErrors: AttributeErrorFragment[];
onChange: (event: React.ChangeEvent<any>) => void;
}
const AttributeDetails: React.FC<AttributeDetailsProps> = props => {
const { canChangeType, data, disabled, errors, onChange } = props;
const {
canChangeType,
errors,
clearErrors,
setError,
data,
disabled,
apiErrors,
onChange,
set
} = props;
const classes = useStyles(props);
const intl = useIntl();
const inputTypeChoices = [
@ -128,6 +94,10 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = props => {
{
label: intl.formatMessage(inputTypeMessages.text),
value: AttributeInputTypeEnum.RICH_TEXT
},
{
label: intl.formatMessage(inputTypeMessages.numeric),
value: AttributeInputTypeEnum.NUMERIC
}
];
const entityTypeChoices = [
@ -141,9 +111,9 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = props => {
}
];
const formErrors = getFormErrors(
["name", "slug", "inputType", "entityType"],
errors
const formApiErrors = getFormErrors(
["name", "slug", "inputType", "entityType", "unit"],
apiErrors
);
return (
@ -154,24 +124,24 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = props => {
<CardContent>
<TextField
disabled={disabled}
error={!!formErrors.name}
error={!!formApiErrors.name}
label={intl.formatMessage(messages.attributeLabel)}
name={"name" as keyof AttributePageFormData}
fullWidth
helperText={getAttributeErrorMessage(formErrors.name, intl)}
helperText={getAttributeErrorMessage(formApiErrors.name, intl)}
value={data.name}
onChange={onChange}
/>
<FormSpacer />
<TextField
disabled={disabled}
error={!!formErrors.slug}
error={!!formApiErrors.slug}
label={intl.formatMessage(messages.attributeSlug)}
name={"slug" as keyof AttributePageFormData}
placeholder={slugify(data.name).toLowerCase()}
fullWidth
helperText={
getAttributeSlugErrorMessage(formErrors.slug, intl) ||
getAttributeSlugErrorMessage(formApiErrors.slug, intl) ||
intl.formatMessage(messages.attributeSlugHelperText)
}
value={data.slug}
@ -182,8 +152,8 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = props => {
<SingleSelectField
choices={inputTypeChoices}
disabled={disabled || !canChangeType}
error={!!formErrors.inputType}
hint={getAttributeErrorMessage(formErrors.inputType, intl)}
error={!!formApiErrors.inputType}
hint={getAttributeErrorMessage(formApiErrors.inputType, intl)}
label={intl.formatMessage(messages.inputType)}
name="inputType"
onChange={onChange}
@ -193,8 +163,8 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = props => {
<SingleSelectField
choices={entityTypeChoices}
disabled={disabled || !canChangeType}
error={!!formErrors.entityType}
hint={getAttributeErrorMessage(formErrors.entityType, intl)}
error={!!formApiErrors.entityType}
hint={getAttributeErrorMessage(formApiErrors.entityType, intl)}
label={intl.formatMessage(messages.entityType)}
name="entityType"
onChange={onChange}
@ -210,6 +180,16 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = props => {
onChange={onChange}
disabled={disabled}
/>
{data.inputType === AttributeInputTypeEnum.NUMERIC && (
<NumericUnits
data={data}
errors={errors}
disabled={disabled}
clearErrors={clearErrors}
setError={setError}
set={set}
/>
)}
</CardContent>
</Card>
);

View file

@ -0,0 +1,189 @@
import { AttributePageFormData } from "@saleor/attributes/components/AttributePage";
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, useMemo, useState } from "react";
import { useIntl } from "react-intl";
import * as M from "./messages";
import {
getUnitChoices,
unitMapping,
UnitSystem,
unitSystemChoices,
UnitType,
unitTypeChoices
} from "./utils";
const useStyles = makeStyles(
theme => ({
unitsRow: {
columnGap: theme.spacing(2),
display: "flex",
[theme.breakpoints.down("sm")]: {
flexFlow: "wrap",
rowGap: theme.spacing(3)
}
},
hr: {
border: "none",
borderTop: `1px solid ${theme.palette.divider}`,
height: 0,
margin: "0.5rem 0",
width: "100%"
}
}),
{ name: "NumericUnits" }
);
interface UnitData {
unit?: MeasurementUnitsEnum;
system?: UnitSystem;
type?: UnitType;
}
interface NumericUnitsProps
extends Pick<
UseFormResult<AttributePageFormData>,
"set" | "setError" | "data" | "errors" | "clearErrors"
> {
disabled: boolean;
}
export const NumericUnits: React.FC<NumericUnitsProps> = ({
data,
disabled,
errors,
set,
setError,
clearErrors
}) => {
const { formatMessage } = useIntl();
const classes = useStyles();
const [unitData, setUnitData] = useState<UnitData>({
unit: data.unit ?? null
});
const { unit, system, type } = unitData;
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 selectInitialUnitData = () => {
const initialData: UnitData = { unit: data.unit };
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 systemMatch;
});
return initialData;
};
setUnitData(selectInitialUnitData());
}
}, []);
useEffect(() => {
if (unit === undefined && !errors.unit) {
setError("unit", formatMessage(commonMessages.requiredField));
}
if (errors.unit && (unit || unit === null)) {
clearErrors("unit");
}
}, [unitData, errors]);
return (
<div>
<div className={classes.hr} />
<ControlledCheckbox
data-test="numeric-with-unit"
name="selectUnit"
label={formatMessage(M.messages.selectUnit)}
checked={data.unit !== null}
onChange={({ target }) =>
setUnitData({ unit: target.value ? undefined : null })
}
disabled={disabled}
/>
{data.unit !== null && (
<div className={classes.unitsRow}>
<SingleSelectField
{...(!system && errorProps)}
testId="unit-system"
label={formatMessage(M.messages.unitSystem)}
choices={systemChoices}
onChange={({ target }: React.ChangeEvent<HTMLSelectElement>) =>
setUnitData({ system: target.value as UnitSystem })
}
value={system}
disabled={disabled}
/>
<SingleSelectField
{...(system && !type && errorProps)}
testId="unit-of"
label={formatMessage(M.messages.unitOf)}
choices={typeChoices}
onChange={({ target }: React.ChangeEvent<HTMLSelectElement>) =>
setUnitData(({ system }) => ({
system,
type: target.value as UnitType
}))
}
disabled={!system || disabled}
value={type}
/>
<SingleSelectField
{...(type && !unit && errorProps)}
testId="unit"
label={formatMessage(M.messages.unit)}
choices={type ? unitChoices[system][type] : []}
onChange={({ target }: React.ChangeEvent<HTMLSelectElement>) =>
setUnitData(data => ({
...data,
unit: target.value as MeasurementUnitsEnum
}))
}
disabled={!type || disabled}
value={
type && unitMapping[system][type].includes(unit)
? unit
: undefined
}
/>
</div>
)}
</div>
);
};

View file

@ -0,0 +1,142 @@
import React from "react";
import { defineMessages } from "react-intl";
export const messages = defineMessages({
attributeLabel: {
defaultMessage: "Default Label",
description: "attribute's label"
},
attributeSlug: {
defaultMessage: "Attribute Code",
description: "attribute's slug short code label"
},
attributeSlugHelperText: {
defaultMessage: "This is used internally. Make sure you dont use spaces",
description: "attribute slug input field helper text"
},
entityType: {
defaultMessage: "Entity",
description: "attribute's editor component entity"
},
inputType: {
defaultMessage: "Catalog Input type for Store Owner",
description: "attribute's editor component"
},
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"
}
});
export const inputTypeMessages = defineMessages({
dropdown: {
defaultMessage: "Dropdown",
description: "product attribute type"
},
file: {
defaultMessage: "File",
description: "file attribute type"
},
multiselect: {
defaultMessage: "Multiple Select",
description: "product attribute type"
},
references: {
defaultMessage: "References",
description: "references attribute type"
},
text: {
defaultMessage: "Text",
description: "text attribute type"
},
numeric: {
defaultMessage: "Numeric",
description: "numeric attribute type"
}
});
export const unitSystemMessages = defineMessages({
metric: {
defaultMessage: "Metric",
description: "metric unit system"
},
imperial: {
defaultMessage: "Imperial",
description: "imperial unit system"
}
});
export const unitTypeMessages = defineMessages({
volume: {
defaultMessage: "Volume",
description: "volume units types"
},
distance: {
defaultMessage: "Distance",
description: "distance units type"
},
weight: {
defaultMessage: "Weight",
description: "weight units type"
},
area: {
defaultMessage: "Area",
description: "area units type"
}
});
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&sup3;</>,
cubicDecimeter: <>dm&sup3;</>,
cubicMeter: <>m&sup3;</>,
liter: "l",
centimeter: "cm",
meter: "m",
kilometer: "km",
gram: "g",
kilogram: "kg",
tonne: "t",
squareCentimeter: <>cm&sup2;</>,
squareMeter: <>m&sup2;</>,
squareKilometer: <>km&sup2;</>,
cubicFoot: <>ft&sup3;</>,
cubicInch: <>in&sup3;</>,
cubicYard: <>yd&sup3;</>,
qt: "qt",
flOz: "fl. oz",
pint: unitMessages.pint,
acreInch: unitMessages.acreInch,
acreFt: unitMessages.acreFt,
ft: "ft",
yd: "yd",
inch: "in",
oz: "oz",
lbs: "lbs",
squareFt: <>ft&sup2;</>,
squareYd: <>yd&sup2;</>,
squareInch: <>in&sup2;</>
};

View file

@ -0,0 +1,166 @@
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";
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<Choice<UnitSystem, MessageDescriptor>> = [
{
label: M.unitSystemMessages.metric,
value: "metric"
},
{
label: M.unitSystemMessages.imperial,
value: "imperial"
}
];
export const unitTypeChoices: Array<Choice<UnitType, MessageDescriptor>> = [
{
label: M.unitTypeMessages.volume,
value: "volume"
},
{
label: M.unitTypeMessages.distance,
value: "distance"
},
{
label: M.unitTypeMessages.weight,
value: "weight"
},
{
label: M.unitTypeMessages.area,
value: "area"
}
];
export const unitMapping = {
imperial: {
volume: [
MeasurementUnitsEnum.CUBIC_FOOT,
MeasurementUnitsEnum.CUBIC_INCH,
MeasurementUnitsEnum.CUBIC_YARD,
MeasurementUnitsEnum.QT,
MeasurementUnitsEnum.FL_OZ,
MeasurementUnitsEnum.PINT,
MeasurementUnitsEnum.ACRE_IN,
MeasurementUnitsEnum.ACRE_FT
],
distance: [
MeasurementUnitsEnum.FT,
MeasurementUnitsEnum.YD,
MeasurementUnitsEnum.INCH
],
weight: [MeasurementUnitsEnum.LB, MeasurementUnitsEnum.OZ],
area: [
MeasurementUnitsEnum.SQ_FT,
MeasurementUnitsEnum.SQ_YD,
MeasurementUnitsEnum.SQ_INCH
]
},
metric: {
volume: [
MeasurementUnitsEnum.CUBIC_CENTIMETER,
MeasurementUnitsEnum.CUBIC_DECIMETER,
MeasurementUnitsEnum.CUBIC_METER,
MeasurementUnitsEnum.LITER
],
distance: [
MeasurementUnitsEnum.CM,
MeasurementUnitsEnum.M,
MeasurementUnitsEnum.KM
],
weight: [
MeasurementUnitsEnum.G,
MeasurementUnitsEnum.KG,
MeasurementUnitsEnum.TONNE
],
area: [
MeasurementUnitsEnum.SQ_CM,
MeasurementUnitsEnum.SQ_M,
MeasurementUnitsEnum.SQ_KM
]
}
};
const extractTypeChoices = (
typeEnums: {
[key in UnitType]: MeasurementUnitsEnum[];
},
formatMessage: IntlShape["formatMessage"]
) =>
Object.entries(typeEnums).reduce(
(acc, [type, units]) => ({
...acc,
[type]: units.map(unit => ({
value: unit,
label: getMeasurementUnitMessage(unit, formatMessage)
}))
}),
{}
);
export const getUnitChoices = (
formatMessage: IntlShape["formatMessage"]
): {
[key in UnitSystem]: {
[key in UnitType]: Array<Choice<MeasurementUnitsEnum>>;
};
} =>
Object.entries(unitMapping).reduce(
(acc, [system, typeEnums]) => ({
...acc,
[system]: extractTypeChoices(typeEnums, formatMessage)
}),
{}
) as {
[key in UnitSystem]: {
[key in UnitType]: Array<Choice<MeasurementUnitsEnum>>;
};
};

View file

@ -20,7 +20,8 @@ import { ReorderAction } from "@saleor/types";
import {
AttributeEntityTypeEnum,
AttributeInputTypeEnum,
AttributeTypeEnum
AttributeTypeEnum,
MeasurementUnitsEnum
} from "@saleor/types/globalTypes";
import { mapMetadataItemToInput } from "@saleor/utils/maps";
import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger";
@ -59,13 +60,14 @@ export interface AttributePageFormData extends MetadataFormData {
slug: string;
storefrontSearchPosition: string;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null | undefined;
visibleInStorefront: boolean;
}
const AttributePage: React.FC<AttributePageProps> = ({
attribute,
disabled,
errors,
errors: apiErrors,
saveButtonBarState,
values,
onBack,
@ -98,36 +100,27 @@ const AttributePage: React.FC<AttributePageProps> = ({
storefrontSearchPosition: "",
type: AttributeTypeEnum.PRODUCT_TYPE,
valueRequired: true,
visibleInStorefront: true
visibleInStorefront: true,
unit: undefined
}
: {
availableInGrid: maybe(() => attribute.availableInGrid, true),
availableInGrid: attribute?.availableInGrid ?? true,
entityType: attribute?.entityType ?? null,
filterableInDashboard: maybe(
() => attribute.filterableInDashboard,
true
),
filterableInStorefront: maybe(
() => attribute.filterableInStorefront,
true
),
inputType: maybe(
() => attribute.inputType,
AttributeInputTypeEnum.DROPDOWN
),
filterableInDashboard: attribute?.filterableInDashboard ?? true,
filterableInStorefront: attribute?.filterableInStorefront ?? true,
inputType: attribute?.inputType ?? AttributeInputTypeEnum.DROPDOWN,
metadata: attribute?.metadata?.map(mapMetadataItemToInput),
name: maybe(() => attribute.name, ""),
name: attribute?.name ?? "",
privateMetadata: attribute?.privateMetadata?.map(
mapMetadataItemToInput
),
slug: maybe(() => attribute.slug, ""),
storefrontSearchPosition: maybe(
() => attribute.storefrontSearchPosition.toString(),
""
),
slug: attribute?.slug ?? "",
storefrontSearchPosition:
attribute?.storefrontSearchPosition.toString() ?? "",
type: attribute?.type || AttributeTypeEnum.PRODUCT_TYPE,
valueRequired: maybe(() => attribute.valueRequired, true),
visibleInStorefront: maybe(() => attribute.visibleInStorefront, true)
valueRequired: !!attribute?.valueRequired ?? true,
visibleInStorefront: attribute?.visibleInStorefront ?? true,
unit: attribute?.unit || null
};
const handleSubmit = (data: AttributePageFormData) => {
@ -150,7 +143,16 @@ const AttributePage: React.FC<AttributePageProps> = ({
return (
<Form initial={initialForm} onSubmit={handleSubmit}>
{({ change, data, hasChanged, submit }) => {
{({
change,
set,
data,
hasChanged,
submit,
errors,
setError,
clearErrors
}) => {
const changeMetadata = makeMetadataChangeHandler(change);
return (
@ -174,8 +176,12 @@ const AttributePage: React.FC<AttributePageProps> = ({
canChangeType={attribute === null}
data={data}
disabled={disabled}
errors={errors}
apiErrors={apiErrors}
onChange={change}
set={set}
errors={errors}
setError={setError}
clearErrors={clearErrors}
/>
{ATTRIBUTE_TYPES_WITH_DEDICATED_VALUES.includes(
data.inputType
@ -205,7 +211,7 @@ const AttributePage: React.FC<AttributePageProps> = ({
<CardSpacer />
<AttributeProperties
data={data}
errors={errors}
errors={apiErrors}
disabled={disabled}
onChange={change}
/>

View file

@ -28,6 +28,7 @@ export const attribute: AttributeDetailsFragment = {
storefrontSearchPosition: 2,
type: AttributeTypeEnum.PRODUCT_TYPE,
valueRequired: true,
unit: null,
values: [
{
__typename: "AttributeValue" as "AttributeValue",
@ -62,6 +63,7 @@ export const attributes: Array<AttributeList_attributes_edges_node &
name: "Author",
slug: "author",
type: AttributeTypeEnum.PRODUCT_TYPE,
unit: null,
values: [
{
__typename: "AttributeValue" as "AttributeValue",
@ -98,6 +100,7 @@ export const attributes: Array<AttributeList_attributes_edges_node &
name: "Box Size",
slug: "box-size",
type: AttributeTypeEnum.PRODUCT_TYPE,
unit: null,
values: [
{
__typename: "AttributeValue" as "AttributeValue",
@ -156,6 +159,7 @@ export const attributes: Array<AttributeList_attributes_edges_node &
name: "Brand",
slug: "brand",
type: AttributeTypeEnum.PRODUCT_TYPE,
unit: null,
values: [
{
__typename: "AttributeValue" as "AttributeValue",
@ -181,6 +185,7 @@ export const attributes: Array<AttributeList_attributes_edges_node &
name: "Candy Box Size",
slug: "candy-box-size",
type: AttributeTypeEnum.PRODUCT_TYPE,
unit: null,
values: [
{
__typename: "AttributeValue" as "AttributeValue",
@ -228,6 +233,7 @@ export const attributes: Array<AttributeList_attributes_edges_node &
name: "Coffee Genre",
slug: "coffee-genre",
type: AttributeTypeEnum.PRODUCT_TYPE,
unit: null,
values: [
{
__typename: "AttributeValue" as "AttributeValue",
@ -264,6 +270,7 @@ export const attributes: Array<AttributeList_attributes_edges_node &
name: "Collar",
slug: "collar",
type: AttributeTypeEnum.PRODUCT_TYPE,
unit: null,
values: [
{
__typename: "AttributeValue" as "AttributeValue",
@ -311,6 +318,7 @@ export const attributes: Array<AttributeList_attributes_edges_node &
name: "Color",
slug: "color",
type: AttributeTypeEnum.PRODUCT_TYPE,
unit: null,
values: [
{
__typename: "AttributeValue" as "AttributeValue",
@ -347,6 +355,7 @@ export const attributes: Array<AttributeList_attributes_edges_node &
name: "Cover",
slug: "cover",
type: AttributeTypeEnum.PRODUCT_TYPE,
unit: null,
values: [
{
__typename: "AttributeValue" as "AttributeValue",
@ -427,6 +436,7 @@ export const attributes: Array<AttributeList_attributes_edges_node &
name: "Flavor",
slug: "flavor",
type: AttributeTypeEnum.PRODUCT_TYPE,
unit: null,
values: [
{
__typename: "AttributeValue" as "AttributeValue",
@ -463,6 +473,7 @@ export const attributes: Array<AttributeList_attributes_edges_node &
name: "Language",
slug: "language",
type: AttributeTypeEnum.PRODUCT_TYPE,
unit: null,
values: [
{
__typename: "AttributeValue" as "AttributeValue",
@ -499,6 +510,7 @@ export const attributes: Array<AttributeList_attributes_edges_node &
name: "Publisher",
slug: "publisher",
type: AttributeTypeEnum.PRODUCT_TYPE,
unit: null,
values: [
{
__typename: "AttributeValue" as "AttributeValue",
@ -535,6 +547,7 @@ export const attributes: Array<AttributeList_attributes_edges_node &
name: "Size",
slug: "size",
type: AttributeTypeEnum.PRODUCT_TYPE,
unit: null,
values: [
{
__typename: "AttributeValue" as "AttributeValue",

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { AttributeCreateInput, AttributeTypeEnum, AttributeInputTypeEnum, AttributeEntityTypeEnum, AttributeErrorCode } from "./../../types/globalTypes";
import { AttributeCreateInput, AttributeTypeEnum, MeasurementUnitsEnum, AttributeInputTypeEnum, AttributeEntityTypeEnum, AttributeErrorCode } from "./../../types/globalTypes";
// ====================================================
// GraphQL mutation operation: AttributeCreate
@ -46,6 +46,7 @@ export interface AttributeCreate_attributeCreate_attribute {
visibleInStorefront: boolean;
filterableInDashboard: boolean;
filterableInStorefront: boolean;
unit: MeasurementUnitsEnum | null;
metadata: (AttributeCreate_attributeCreate_attribute_metadata | null)[];
privateMetadata: (AttributeCreate_attributeCreate_attribute_privateMetadata | null)[];
availableInGrid: boolean;

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { AttributeTypeEnum, AttributeInputTypeEnum, AttributeEntityTypeEnum } from "./../../types/globalTypes";
import { AttributeTypeEnum, MeasurementUnitsEnum, AttributeInputTypeEnum, AttributeEntityTypeEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL query operation: AttributeDetails
@ -46,6 +46,7 @@ export interface AttributeDetails_attribute {
visibleInStorefront: boolean;
filterableInDashboard: boolean;
filterableInStorefront: boolean;
unit: MeasurementUnitsEnum | null;
metadata: (AttributeDetails_attribute_metadata | null)[];
privateMetadata: (AttributeDetails_attribute_privateMetadata | null)[];
availableInGrid: boolean;

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { AttributeFilterInput, AttributeSortingInput, AttributeTypeEnum } from "./../../types/globalTypes";
import { AttributeFilterInput, AttributeSortingInput, AttributeTypeEnum, MeasurementUnitsEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL query operation: AttributeList
@ -25,6 +25,7 @@ export interface AttributeList_attributes_edges_node {
visibleInStorefront: boolean;
filterableInDashboard: boolean;
filterableInStorefront: boolean;
unit: MeasurementUnitsEnum | null;
values: (AttributeList_attributes_edges_node_values | null)[] | null;
}

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { AttributeUpdateInput, AttributeTypeEnum, AttributeInputTypeEnum, AttributeEntityTypeEnum, AttributeErrorCode } from "./../../types/globalTypes";
import { AttributeUpdateInput, AttributeTypeEnum, MeasurementUnitsEnum, AttributeInputTypeEnum, AttributeEntityTypeEnum, AttributeErrorCode } from "./../../types/globalTypes";
// ====================================================
// GraphQL mutation operation: AttributeUpdate
@ -46,6 +46,7 @@ export interface AttributeUpdate_attributeUpdate_attribute {
visibleInStorefront: boolean;
filterableInDashboard: boolean;
filterableInStorefront: boolean;
unit: MeasurementUnitsEnum | null;
metadata: (AttributeUpdate_attributeUpdate_attribute_metadata | null)[];
privateMetadata: (AttributeUpdate_attributeUpdate_attribute_privateMetadata | null)[];
availableInGrid: boolean;

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { AttributeValueCreateInput, AttributeTypeEnum, AttributeInputTypeEnum, AttributeEntityTypeEnum, AttributeErrorCode } from "./../../types/globalTypes";
import { AttributeValueCreateInput, AttributeTypeEnum, MeasurementUnitsEnum, AttributeInputTypeEnum, AttributeEntityTypeEnum, AttributeErrorCode } from "./../../types/globalTypes";
// ====================================================
// GraphQL mutation operation: AttributeValueCreate
@ -46,6 +46,7 @@ export interface AttributeValueCreate_attributeValueCreate_attribute {
visibleInStorefront: boolean;
filterableInDashboard: boolean;
filterableInStorefront: boolean;
unit: MeasurementUnitsEnum | null;
metadata: (AttributeValueCreate_attributeValueCreate_attribute_metadata | null)[];
privateMetadata: (AttributeValueCreate_attributeValueCreate_attribute_privateMetadata | null)[];
availableInGrid: boolean;

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { AttributeTypeEnum, AttributeInputTypeEnum, AttributeEntityTypeEnum, AttributeErrorCode } from "./../../types/globalTypes";
import { AttributeTypeEnum, MeasurementUnitsEnum, AttributeInputTypeEnum, AttributeEntityTypeEnum, AttributeErrorCode } from "./../../types/globalTypes";
// ====================================================
// GraphQL mutation operation: AttributeValueDelete
@ -46,6 +46,7 @@ export interface AttributeValueDelete_attributeValueDelete_attribute {
visibleInStorefront: boolean;
filterableInDashboard: boolean;
filterableInStorefront: boolean;
unit: MeasurementUnitsEnum | null;
metadata: (AttributeValueDelete_attributeValueDelete_attribute_metadata | null)[];
privateMetadata: (AttributeValueDelete_attributeValueDelete_attribute_privateMetadata | null)[];
availableInGrid: boolean;

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { AttributeValueCreateInput, AttributeTypeEnum, AttributeInputTypeEnum, AttributeEntityTypeEnum, AttributeErrorCode } from "./../../types/globalTypes";
import { AttributeValueCreateInput, AttributeTypeEnum, MeasurementUnitsEnum, AttributeInputTypeEnum, AttributeEntityTypeEnum, AttributeErrorCode } from "./../../types/globalTypes";
// ====================================================
// GraphQL mutation operation: AttributeValueUpdate
@ -46,6 +46,7 @@ export interface AttributeValueUpdate_attributeValueUpdate_attribute {
visibleInStorefront: boolean;
filterableInDashboard: boolean;
filterableInStorefront: boolean;
unit: MeasurementUnitsEnum | null;
metadata: (AttributeValueUpdate_attributeValueUpdate_attribute_metadata | null)[];
privateMetadata: (AttributeValueUpdate_attributeValueUpdate_attribute_privateMetadata | null)[];
availableInGrid: boolean;

View file

@ -77,13 +77,19 @@ export function getSelectedAttributeValues(
| ProductDetails_product_attributes
| SelectedVariantAttributeFragment
) {
if (attribute.attribute.inputType === AttributeInputTypeEnum.REFERENCE) {
switch (attribute.attribute.inputType) {
case AttributeInputTypeEnum.REFERENCE:
return attribute.values.map(value => value.reference);
}
if (attribute.attribute.inputType === AttributeInputTypeEnum.RICH_TEXT) {
case AttributeInputTypeEnum.RICH_TEXT:
return [attribute.values[0]?.richText];
}
case AttributeInputTypeEnum.NUMERIC:
return [attribute.values[0]?.name];
default:
return attribute.values.map(value => value.slug);
}
}
export const isFileValueUnused = (

View file

@ -1,4 +1,6 @@
import { InputAdornment, TextField } from "@material-ui/core";
import makeStyles from "@material-ui/core/styles/makeStyles";
import { getMeasurementUnitMessage } from "@saleor/attributes/components/AttributeDetails/utils";
import { AttributeInput } from "@saleor/components/Attributes/Attributes";
import BasicAttributeRow from "@saleor/components/Attributes/BasicAttributeRow";
import ExtendedAttributeRow from "@saleor/components/Attributes/ExtendedAttributeRow";
@ -158,6 +160,34 @@ const AttributeRow: React.FC<AttributeRowProps> = ({
/>
</BasicAttributeRow>
);
case AttributeInputTypeEnum.NUMERIC:
return (
<BasicAttributeRow label={attribute.label}>
<TextField
fullWidth
disabled={disabled}
error={!!error}
helperText={getErrorMessage(error, intl)}
label={intl.formatMessage(messages.valueLabel)}
name={`attribute:${attribute.label}`}
onChange={event => onChange(attribute.id, event.target.value)}
type="number"
value={attribute.value[0]}
InputProps={
attribute.data.unit && {
endAdornment: (
<InputAdornment position="end">
{getMeasurementUnitMessage(
attribute.data.unit,
intl.formatMessage
)}
</InputAdornment>
)
}
}
/>
</BasicAttributeRow>
);
default:
return (
<BasicAttributeRow label={attribute.label}>

View file

@ -13,7 +13,8 @@ import { FormsetAtomicData } from "@saleor/hooks/useFormset";
import { makeStyles } from "@saleor/theme";
import {
AttributeEntityTypeEnum,
AttributeInputTypeEnum
AttributeInputTypeEnum,
MeasurementUnitsEnum
} from "@saleor/types/globalTypes";
import classNames from "classnames";
import React from "react";
@ -25,6 +26,7 @@ import { VariantAttributeScope } from "./types";
export interface AttributeInputData {
inputType: AttributeInputTypeEnum;
entityType?: AttributeEntityTypeEnum;
unit?: MeasurementUnitsEnum | null;
variantAttributeScope?: VariantAttributeScope;
isRequired: boolean;
values: AttributeValueFragment[];

View file

@ -20,7 +20,7 @@ const useStyles = makeStyles(
);
interface BasicAttributeRowProps {
label: string;
label: string | React.ReactNode;
}
const BasicAttributeRow: React.FC<BasicAttributeRowProps> = props => {

View file

@ -193,12 +193,34 @@ const RICH_TEXT_ATTRIBUTE: AttributeInput = {
value: []
};
const NUMERIC_ATTRIBUTE: AttributeInput = {
data: {
inputType: AttributeInputTypeEnum.NUMERIC,
isRequired: true,
values: [
{
__typename: "AttributeValue",
file: null,
id: "QXR0cmlidXRlVmFsdWU6MTAx",
name: "12cm",
reference: null,
richText: null,
slug: "319_35"
}
]
},
id: "QXR0cmlidXRlOjM1",
label: "Numeric Attribute",
value: []
};
export const ATTRIBUTES: AttributeInput[] = [
DROPDOWN_ATTRIBUTE,
MULTISELECT_ATTRIBUTE,
FILE_ATTRIBUTE,
REFERENCE_ATTRIBUTE,
RICH_TEXT_ATTRIBUTE
RICH_TEXT_ATTRIBUTE,
NUMERIC_ATTRIBUTE
];
export const ATTRIBUTES_SELECTED: AttributeInput[] = [
@ -228,5 +250,9 @@ export const ATTRIBUTES_SELECTED: AttributeInput[] = [
{
...RICH_TEXT_ATTRIBUTE,
value: [RICH_TEXT_ATTRIBUTE.data.values[0].richText]
},
{
...NUMERIC_ATTRIBUTE,
value: [NUMERIC_ATTRIBUTE.data.values[0].name]
}
];

View file

@ -28,9 +28,9 @@ const useStyles = makeStyles(
{ name: "SingleSelectField" }
);
export interface Choice {
value: string;
label: string | React.ReactNode;
export interface Choice<T = string, L = string | React.ReactNode> {
value: T;
label: L;
}
export type Choices = Choice[];
@ -40,8 +40,8 @@ interface SingleSelectFieldProps {
className?: string;
disabled?: boolean;
error?: boolean;
hint?: string;
label?: string;
hint?: string | React.ReactNode;
label?: string | React.ReactNode;
name?: string;
selectProps?: SelectProps;
placeholder?: string;

View file

@ -26,6 +26,7 @@ export const attributeFragment = gql`
visibleInStorefront
filterableInDashboard
filterableInStorefront
unit
}
`;
@ -39,6 +40,7 @@ export const attributeDetailsFragment = gql`
availableInGrid
inputType
entityType
unit
storefrontSearchPosition
valueRequired
values {

View file

@ -23,6 +23,7 @@ export const pageAttributesFragment = gql`
inputType
entityType
valueRequired
unit
values {
...AttributeValueFragment
}

View file

@ -127,6 +127,7 @@ export const productVariantAttributesFragment = gql`
inputType
entityType
valueRequired
unit
values {
...AttributeValueFragment
}
@ -239,6 +240,7 @@ export const variantAttributeFragment = gql`
inputType
entityType
valueRequired
unit
values {
...AttributeValueFragment
}

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { AttributeTypeEnum, AttributeInputTypeEnum, AttributeEntityTypeEnum } from "./../../types/globalTypes";
import { AttributeTypeEnum, MeasurementUnitsEnum, AttributeInputTypeEnum, AttributeEntityTypeEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL fragment: AttributeDetailsFragment
@ -46,6 +46,7 @@ export interface AttributeDetailsFragment {
visibleInStorefront: boolean;
filterableInDashboard: boolean;
filterableInStorefront: boolean;
unit: MeasurementUnitsEnum | null;
metadata: (AttributeDetailsFragment_metadata | null)[];
privateMetadata: (AttributeDetailsFragment_privateMetadata | null)[];
availableInGrid: boolean;

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { AttributeTypeEnum } from "./../../types/globalTypes";
import { AttributeTypeEnum, MeasurementUnitsEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL fragment: AttributeFragment
@ -18,4 +18,5 @@ export interface AttributeFragment {
visibleInStorefront: boolean;
filterableInDashboard: boolean;
filterableInStorefront: boolean;
unit: MeasurementUnitsEnum | null;
}

View file

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

View file

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

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { AttributeTypeEnum } from "./../../types/globalTypes";
import { AttributeTypeEnum, MeasurementUnitsEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL fragment: PageTypeDetailsFragment
@ -30,6 +30,7 @@ export interface PageTypeDetailsFragment_attributes {
visibleInStorefront: boolean;
filterableInDashboard: boolean;
filterableInStorefront: boolean;
unit: MeasurementUnitsEnum | null;
}
export interface PageTypeDetailsFragment {

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { AttributeInputTypeEnum, AttributeEntityTypeEnum, ProductMediaType, WeightUnitsEnum } from "./../../types/globalTypes";
import { AttributeInputTypeEnum, AttributeEntityTypeEnum, MeasurementUnitsEnum, ProductMediaType, WeightUnitsEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL fragment: Product
@ -33,6 +33,7 @@ export interface Product_attributes_attribute {
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (Product_attributes_attribute_values | null)[] | null;
}

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { AttributeTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes";
import { AttributeTypeEnum, MeasurementUnitsEnum, WeightUnitsEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL fragment: ProductTypeDetailsFragment
@ -36,6 +36,7 @@ export interface ProductTypeDetailsFragment_productAttributes {
visibleInStorefront: boolean;
filterableInDashboard: boolean;
filterableInStorefront: boolean;
unit: MeasurementUnitsEnum | null;
}
export interface ProductTypeDetailsFragment_variantAttributes {
@ -47,6 +48,7 @@ export interface ProductTypeDetailsFragment_variantAttributes {
visibleInStorefront: boolean;
filterableInDashboard: boolean;
filterableInStorefront: boolean;
unit: MeasurementUnitsEnum | null;
}
export interface ProductTypeDetailsFragment_weight {

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { AttributeInputTypeEnum, AttributeEntityTypeEnum, ProductMediaType, WeightUnitsEnum } from "./../../types/globalTypes";
import { AttributeInputTypeEnum, AttributeEntityTypeEnum, MeasurementUnitsEnum, ProductMediaType, WeightUnitsEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL fragment: ProductVariant
@ -45,6 +45,7 @@ export interface ProductVariant_selectionAttributes_attribute {
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (ProductVariant_selectionAttributes_attribute_values | null)[] | null;
}
@ -94,6 +95,7 @@ export interface ProductVariant_nonSelectionAttributes_attribute {
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (ProductVariant_nonSelectionAttributes_attribute_values | null)[] | null;
}

View file

@ -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: ProductVariantAttributesFragment
@ -33,6 +33,7 @@ export interface ProductVariantAttributesFragment_attributes_attribute {
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (ProductVariantAttributesFragment_attributes_attribute_values | null)[] | null;
}

View file

@ -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: SelectedVariantAttributeFragment
@ -33,6 +33,7 @@ export interface SelectedVariantAttributeFragment_attribute {
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (SelectedVariantAttributeFragment_attribute_values | null)[] | null;
}

View file

@ -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: VariantAttributeFragment
@ -33,5 +33,6 @@ export interface VariantAttributeFragment {
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (VariantAttributeFragment_values | null)[] | null;
}

View file

@ -1,5 +1,7 @@
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";
import useStateFromProps from "./useStateFromProps";
@ -14,6 +16,10 @@ export type SubmitPromise = Promise<any[]>;
export type FormChange = (event: ChangeEvent, cb?: () => void) => void;
export type FormErrors<T> = {
[field in keyof T]?: string | React.ReactNode;
};
export interface UseFormResult<T> {
change: FormChange;
data: T;
@ -23,6 +29,9 @@ export interface UseFormResult<T> {
submit: () => void;
triggerChange: () => void;
toggleValue: FormChange;
errors: FormErrors<T>;
setError: (name: keyof T, error: string | React.ReactNode) => void;
clearErrors: (name?: keyof T | Array<keyof T>) => void;
}
type FormData = Record<string, any | any[]>;
@ -55,6 +64,7 @@ function useForm<T extends FormData>(
onSubmit?: (data: T) => SubmitPromise | void
): UseFormResult<T> {
const [hasChanged, setChanged] = useState(false);
const [errors, setErrors] = useState<FormErrors<T>>({});
const [data, setData] = useStateFromProps(initial, {
mergeFunc: merge,
onRefresh: newData => handleRefresh(data, newData, setChanged)
@ -109,7 +119,7 @@ function useForm<T extends FormData>(
}
async function submit() {
if (typeof onSubmit === "function") {
if (typeof onSubmit === "function" && !Object.keys(errors).length) {
const result = onSubmit(data);
if (result) {
const errors = await result;
@ -124,8 +134,24 @@ function useForm<T extends FormData>(
setChanged(true);
}
const setError = (field: keyof T, error: string | React.ReactNode) =>
setErrors(e => ({ ...e, [field]: error }));
const clearErrors = (field?: keyof T | Array<keyof T>) => {
if (!field) {
setErrors({});
} else {
setErrors(errors =>
omit<FormErrors<T>>(errors, Array.isArray(field) ? field : [field])
);
}
};
return {
setError,
errors,
change,
clearErrors,
data,
hasChanged,
reset,

View file

@ -46,7 +46,8 @@ export const pageType: PageTypeDetails_pageType = {
visibleInStorefront: true,
filterableInDashboard: true,
filterableInStorefront: true,
type: AttributeTypeEnum.PAGE_TYPE
type: AttributeTypeEnum.PAGE_TYPE,
unit: null
},
{
__typename: "Attribute" as "Attribute",
@ -56,7 +57,8 @@ export const pageType: PageTypeDetails_pageType = {
visibleInStorefront: true,
filterableInDashboard: true,
filterableInStorefront: true,
type: AttributeTypeEnum.PAGE_TYPE
type: AttributeTypeEnum.PAGE_TYPE,
unit: null
},
{
__typename: "Attribute" as "Attribute",
@ -66,7 +68,8 @@ export const pageType: PageTypeDetails_pageType = {
visibleInStorefront: true,
filterableInDashboard: true,
filterableInStorefront: true,
type: AttributeTypeEnum.PAGE_TYPE
type: AttributeTypeEnum.PAGE_TYPE,
unit: null
}
],
privateMetadata: []

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { PageErrorCode, AttributeTypeEnum } from "./../../types/globalTypes";
import { PageErrorCode, AttributeTypeEnum, MeasurementUnitsEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL mutation operation: AssignPageAttribute
@ -36,6 +36,7 @@ export interface AssignPageAttribute_pageAttributeAssign_pageType_attributes {
visibleInStorefront: boolean;
filterableInDashboard: boolean;
filterableInStorefront: boolean;
unit: MeasurementUnitsEnum | null;
}
export interface AssignPageAttribute_pageAttributeAssign_pageType {

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { ReorderInput, PageErrorCode, AttributeTypeEnum } from "./../../types/globalTypes";
import { ReorderInput, PageErrorCode, AttributeTypeEnum, MeasurementUnitsEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL mutation operation: PageTypeAttributeReorder
@ -36,6 +36,7 @@ export interface PageTypeAttributeReorder_pageTypeReorderAttributes_pageType_att
visibleInStorefront: boolean;
filterableInDashboard: boolean;
filterableInStorefront: boolean;
unit: MeasurementUnitsEnum | null;
}
export interface PageTypeAttributeReorder_pageTypeReorderAttributes_pageType {

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { PageTypeCreateInput, PageErrorCode, AttributeTypeEnum } from "./../../types/globalTypes";
import { PageTypeCreateInput, PageErrorCode, AttributeTypeEnum, MeasurementUnitsEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL mutation operation: PageTypeCreate
@ -36,6 +36,7 @@ export interface PageTypeCreate_pageTypeCreate_pageType_attributes {
visibleInStorefront: boolean;
filterableInDashboard: boolean;
filterableInStorefront: boolean;
unit: MeasurementUnitsEnum | null;
}
export interface PageTypeCreate_pageTypeCreate_pageType {

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { AttributeTypeEnum } from "./../../types/globalTypes";
import { AttributeTypeEnum, MeasurementUnitsEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL query operation: PageTypeDetails
@ -30,6 +30,7 @@ export interface PageTypeDetails_pageType_attributes {
visibleInStorefront: boolean;
filterableInDashboard: boolean;
filterableInStorefront: boolean;
unit: MeasurementUnitsEnum | null;
}
export interface PageTypeDetails_pageType {

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { PageTypeUpdateInput, PageErrorCode, AttributeTypeEnum } from "./../../types/globalTypes";
import { PageTypeUpdateInput, PageErrorCode, AttributeTypeEnum, MeasurementUnitsEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL mutation operation: PageTypeUpdate
@ -36,6 +36,7 @@ export interface PageTypeUpdate_pageTypeUpdate_pageType_attributes {
visibleInStorefront: boolean;
filterableInDashboard: boolean;
filterableInStorefront: boolean;
unit: MeasurementUnitsEnum | null;
}
export interface PageTypeUpdate_pageTypeUpdate_pageType {

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { PageErrorCode, AttributeTypeEnum } from "./../../types/globalTypes";
import { PageErrorCode, AttributeTypeEnum, MeasurementUnitsEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL mutation operation: UnassignPageAttribute
@ -36,6 +36,7 @@ export interface UnassignPageAttribute_pageAttributeUnassign_pageType_attributes
visibleInStorefront: boolean;
filterableInDashboard: boolean;
filterableInStorefront: boolean;
unit: MeasurementUnitsEnum | null;
}
export interface UnassignPageAttribute_pageAttributeUnassign_pageType {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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<SearchProductTypes_search_edges_node &
__typename: "ProductType" as "ProductType",
...productType
}));
export const productType: ProductTypeDetails_productType = {
__typename: "ProductType" as "ProductType",
hasVariants: false,
@ -703,7 +716,8 @@ export const productType: ProductTypeDetails_productType = {
name: "Author",
slug: "author",
type: AttributeTypeEnum.PRODUCT_TYPE,
visibleInStorefront: true
visibleInStorefront: true,
unit: null
},
{
__typename: "Attribute" as "Attribute",
@ -713,7 +727,8 @@ export const productType: ProductTypeDetails_productType = {
name: "Language",
slug: "language",
type: AttributeTypeEnum.PRODUCT_TYPE,
visibleInStorefront: true
visibleInStorefront: true,
unit: null
},
{
__typename: "Attribute" as "Attribute",
@ -723,7 +738,8 @@ export const productType: ProductTypeDetails_productType = {
name: "Publisher",
slug: "publisher",
type: AttributeTypeEnum.PRODUCT_TYPE,
visibleInStorefront: true
visibleInStorefront: true,
unit: null
}
],
taxType: {
@ -737,14 +753,16 @@ export const productType: ProductTypeDetails_productType = {
filterableInDashboard: true,
filterableInStorefront: false,
type: AttributeTypeEnum.PRODUCT_TYPE,
visibleInStorefront: true
visibleInStorefront: true,
unit: null
},
{
...attributes[6],
filterableInDashboard: true,
filterableInStorefront: false,
type: AttributeTypeEnum.PRODUCT_TYPE,
visibleInStorefront: true
visibleInStorefront: true,
unit: null
}
],
weight: {

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { ProductAttributeAssignInput, AttributeTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes";
import { ProductAttributeAssignInput, AttributeTypeEnum, MeasurementUnitsEnum, WeightUnitsEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL mutation operation: AssignProductAttribute
@ -42,6 +42,7 @@ export interface AssignProductAttribute_productAttributeAssign_productType_produ
visibleInStorefront: boolean;
filterableInDashboard: boolean;
filterableInStorefront: boolean;
unit: MeasurementUnitsEnum | null;
}
export interface AssignProductAttribute_productAttributeAssign_productType_variantAttributes {
@ -53,6 +54,7 @@ export interface AssignProductAttribute_productAttributeAssign_productType_varia
visibleInStorefront: boolean;
filterableInDashboard: boolean;
filterableInStorefront: boolean;
unit: MeasurementUnitsEnum | null;
}
export interface AssignProductAttribute_productAttributeAssign_productType_weight {

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { ReorderInput, ProductAttributeType, AttributeTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes";
import { ReorderInput, ProductAttributeType, AttributeTypeEnum, MeasurementUnitsEnum, WeightUnitsEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL mutation operation: ProductTypeAttributeReorder
@ -42,6 +42,7 @@ export interface ProductTypeAttributeReorder_productTypeReorderAttributes_produc
visibleInStorefront: boolean;
filterableInDashboard: boolean;
filterableInStorefront: boolean;
unit: MeasurementUnitsEnum | null;
}
export interface ProductTypeAttributeReorder_productTypeReorderAttributes_productType_variantAttributes {
@ -53,6 +54,7 @@ export interface ProductTypeAttributeReorder_productTypeReorderAttributes_produc
visibleInStorefront: boolean;
filterableInDashboard: boolean;
filterableInStorefront: boolean;
unit: MeasurementUnitsEnum | null;
}
export interface ProductTypeAttributeReorder_productTypeReorderAttributes_productType_weight {

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { ProductTypeInput, AttributeTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes";
import { ProductTypeInput, AttributeTypeEnum, MeasurementUnitsEnum, WeightUnitsEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL mutation operation: ProductTypeCreate
@ -42,6 +42,7 @@ export interface ProductTypeCreate_productTypeCreate_productType_productAttribut
visibleInStorefront: boolean;
filterableInDashboard: boolean;
filterableInStorefront: boolean;
unit: MeasurementUnitsEnum | null;
}
export interface ProductTypeCreate_productTypeCreate_productType_variantAttributes {
@ -53,6 +54,7 @@ export interface ProductTypeCreate_productTypeCreate_productType_variantAttribut
visibleInStorefront: boolean;
filterableInDashboard: boolean;
filterableInStorefront: boolean;
unit: MeasurementUnitsEnum | null;
}
export interface ProductTypeCreate_productTypeCreate_productType_weight {

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { AttributeTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes";
import { AttributeTypeEnum, MeasurementUnitsEnum, WeightUnitsEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL query operation: ProductTypeDetails
@ -36,6 +36,7 @@ export interface ProductTypeDetails_productType_productAttributes {
visibleInStorefront: boolean;
filterableInDashboard: boolean;
filterableInStorefront: boolean;
unit: MeasurementUnitsEnum | null;
}
export interface ProductTypeDetails_productType_variantAttributes {
@ -47,6 +48,7 @@ export interface ProductTypeDetails_productType_variantAttributes {
visibleInStorefront: boolean;
filterableInDashboard: boolean;
filterableInStorefront: boolean;
unit: MeasurementUnitsEnum | null;
}
export interface ProductTypeDetails_productType_weight {

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { ProductTypeInput, AttributeTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes";
import { ProductTypeInput, AttributeTypeEnum, MeasurementUnitsEnum, WeightUnitsEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL mutation operation: ProductTypeUpdate
@ -42,6 +42,7 @@ export interface ProductTypeUpdate_productTypeUpdate_productType_productAttribut
visibleInStorefront: boolean;
filterableInDashboard: boolean;
filterableInStorefront: boolean;
unit: MeasurementUnitsEnum | null;
}
export interface ProductTypeUpdate_productTypeUpdate_productType_variantAttributes {
@ -53,6 +54,7 @@ export interface ProductTypeUpdate_productTypeUpdate_productType_variantAttribut
visibleInStorefront: boolean;
filterableInDashboard: boolean;
filterableInStorefront: boolean;
unit: MeasurementUnitsEnum | null;
}
export interface ProductTypeUpdate_productTypeUpdate_productType_weight {

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { AttributeTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes";
import { AttributeTypeEnum, MeasurementUnitsEnum, WeightUnitsEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL mutation operation: UnassignProductAttribute
@ -42,6 +42,7 @@ export interface UnassignProductAttribute_productAttributeUnassign_productType_p
visibleInStorefront: boolean;
filterableInDashboard: boolean;
filterableInStorefront: boolean;
unit: MeasurementUnitsEnum | null;
}
export interface UnassignProductAttribute_productAttributeUnassign_productType_variantAttributes {
@ -53,6 +54,7 @@ export interface UnassignProductAttribute_productAttributeUnassign_productType_v
visibleInStorefront: boolean;
filterableInDashboard: boolean;
filterableInStorefront: boolean;
unit: MeasurementUnitsEnum | null;
}
export interface UnassignProductAttribute_productAttributeUnassign_productType_weight {

View file

@ -29,6 +29,7 @@ export const product: (
name: "Borders",
slug: "Borders",
valueRequired: false,
unit: null,
values: [
{
__typename: "AttributeValue",
@ -72,6 +73,7 @@ export const product: (
name: "Legacy",
slug: "Legacy",
valueRequired: true,
unit: null,
values: [
{
__typename: "AttributeValue",
@ -289,6 +291,7 @@ export const product: (
name: "Attachment",
slug: "attachment",
valueRequired: true,
unit: null,
values: [
{
__typename: "AttributeValue",
@ -315,6 +318,7 @@ export const product: (
name: "Color",
slug: "color",
valueRequired: true,
unit: null,
values: [
{
__typename: "AttributeValue",
@ -2778,6 +2782,7 @@ export const variant = (placeholderImage: string): ProductVariant => ({
name: "Attachment",
slug: "attachment",
valueRequired: true,
unit: null,
values: [
{
__typename: "AttributeValue",
@ -3046,6 +3051,7 @@ export const variant = (placeholderImage: string): ProductVariant => ({
name: "Borders",
slug: "Borders",
valueRequired: true,
unit: null,
values: [
{
__typename: "AttributeValue",
@ -3089,6 +3095,7 @@ export const variant = (placeholderImage: string): ProductVariant => ({
name: "Legacy",
slug: "Legacy",
valueRequired: true,
unit: null,
values: [
{
__typename: "AttributeValue",

View file

@ -219,6 +219,7 @@ const productTypeQuery = gql`
slug
name
valueRequired
unit
values {
...AttributeValueFragment
}

View file

@ -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: CreateMultipleVariantsData
@ -33,6 +33,7 @@ export interface CreateMultipleVariantsData_product_attributes_attribute {
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (CreateMultipleVariantsData_product_attributes_attribute_values | null)[] | null;
}

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { ProductChannelListingUpdateInput, AttributeInputTypeEnum, AttributeEntityTypeEnum, ProductMediaType, WeightUnitsEnum, ProductErrorCode } from "./../../types/globalTypes";
import { ProductChannelListingUpdateInput, AttributeInputTypeEnum, AttributeEntityTypeEnum, MeasurementUnitsEnum, ProductMediaType, WeightUnitsEnum, ProductErrorCode } from "./../../types/globalTypes";
// ====================================================
// GraphQL mutation operation: ProductChannelListingUpdate
@ -33,6 +33,7 @@ export interface ProductChannelListingUpdate_productChannelListingUpdate_product
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (ProductChannelListingUpdate_productChannelListingUpdate_product_attributes_attribute_values | null)[] | null;
}

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { ProductCreateInput, ProductErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, ProductMediaType, WeightUnitsEnum } from "./../../types/globalTypes";
import { ProductCreateInput, ProductErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, MeasurementUnitsEnum, ProductMediaType, WeightUnitsEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL mutation operation: ProductCreate
@ -40,6 +40,7 @@ export interface ProductCreate_productCreate_product_attributes_attribute {
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (ProductCreate_productCreate_product_attributes_attribute_values | null)[] | null;
}

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { AttributeInputTypeEnum, AttributeEntityTypeEnum, ProductMediaType, WeightUnitsEnum } from "./../../types/globalTypes";
import { AttributeInputTypeEnum, AttributeEntityTypeEnum, MeasurementUnitsEnum, ProductMediaType, WeightUnitsEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL query operation: ProductDetails
@ -33,6 +33,7 @@ export interface ProductDetails_product_attributes_attribute {
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (ProductDetails_product_attributes_attribute_values | null)[] | null;
}

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { ProductErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, ProductMediaType, WeightUnitsEnum } from "./../../types/globalTypes";
import { ProductErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, MeasurementUnitsEnum, ProductMediaType, WeightUnitsEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL mutation operation: ProductMediaCreate
@ -39,6 +39,7 @@ export interface ProductMediaCreate_productMediaCreate_product_attributes_attrib
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (ProductMediaCreate_productMediaCreate_product_attributes_attribute_values | null)[] | null;
}

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { ProductErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, ProductMediaType, WeightUnitsEnum } from "./../../types/globalTypes";
import { ProductErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, MeasurementUnitsEnum, ProductMediaType, WeightUnitsEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL mutation operation: ProductMediaUpdate
@ -39,6 +39,7 @@ export interface ProductMediaUpdate_productMediaUpdate_product_attributes_attrib
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (ProductMediaUpdate_productMediaUpdate_product_attributes_attribute_values | null)[] | null;
}

View file

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

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { ProductInput, ProductErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, ProductMediaType, WeightUnitsEnum } from "./../../types/globalTypes";
import { ProductInput, ProductErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, MeasurementUnitsEnum, ProductMediaType, WeightUnitsEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL mutation operation: ProductUpdate
@ -40,6 +40,7 @@ export interface ProductUpdate_productUpdate_product_attributes_attribute {
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (ProductUpdate_productUpdate_product_attributes_attribute_values | null)[] | null;
}

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { ProductVariantChannelListingAddInput, AttributeInputTypeEnum, AttributeEntityTypeEnum, ProductMediaType, WeightUnitsEnum, ProductErrorCode } from "./../../types/globalTypes";
import { ProductVariantChannelListingAddInput, AttributeInputTypeEnum, AttributeEntityTypeEnum, MeasurementUnitsEnum, ProductMediaType, WeightUnitsEnum, ProductErrorCode } from "./../../types/globalTypes";
// ====================================================
// GraphQL mutation operation: ProductVariantChannelListingUpdate
@ -45,6 +45,7 @@ export interface ProductVariantChannelListingUpdate_productVariantChannelListing
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (ProductVariantChannelListingUpdate_productVariantChannelListingUpdate_variant_selectionAttributes_attribute_values | null)[] | null;
}
@ -94,6 +95,7 @@ export interface ProductVariantChannelListingUpdate_productVariantChannelListing
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (ProductVariantChannelListingUpdate_productVariantChannelListingUpdate_variant_nonSelectionAttributes_attribute_values | null)[] | null;
}

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { AttributeInputTypeEnum, AttributeEntityTypeEnum, ProductMediaType } from "./../../types/globalTypes";
import { AttributeInputTypeEnum, AttributeEntityTypeEnum, MeasurementUnitsEnum, ProductMediaType } from "./../../types/globalTypes";
// ====================================================
// GraphQL query operation: ProductVariantCreateData
@ -52,6 +52,7 @@ export interface ProductVariantCreateData_product_productType_selectionVariantAt
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (ProductVariantCreateData_product_productType_selectionVariantAttributes_values | null)[] | null;
}
@ -79,6 +80,7 @@ export interface ProductVariantCreateData_product_productType_nonSelectionVarian
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (ProductVariantCreateData_product_productType_nonSelectionVariantAttributes_values | null)[] | null;
}

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { AttributeInputTypeEnum, AttributeEntityTypeEnum, ProductMediaType, WeightUnitsEnum } from "./../../types/globalTypes";
import { AttributeInputTypeEnum, AttributeEntityTypeEnum, MeasurementUnitsEnum, ProductMediaType, WeightUnitsEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL query operation: ProductVariantDetails
@ -45,6 +45,7 @@ export interface ProductVariantDetails_productVariant_selectionAttributes_attrib
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (ProductVariantDetails_productVariant_selectionAttributes_attribute_values | null)[] | null;
}
@ -94,6 +95,7 @@ export interface ProductVariantDetails_productVariant_nonSelectionAttributes_att
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (ProductVariantDetails_productVariant_nonSelectionAttributes_attribute_values | null)[] | null;
}

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { ReorderInput, ProductErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, ProductMediaType, WeightUnitsEnum } from "./../../types/globalTypes";
import { ReorderInput, ProductErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, MeasurementUnitsEnum, ProductMediaType, WeightUnitsEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL mutation operation: ProductVariantReorder
@ -39,6 +39,7 @@ export interface ProductVariantReorder_productVariantReorder_product_attributes_
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (ProductVariantReorder_productVariantReorder_product_attributes_attribute_values | null)[] | null;
}

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { ProductErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, ProductMediaType, WeightUnitsEnum } from "./../../types/globalTypes";
import { ProductErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, MeasurementUnitsEnum, ProductMediaType, WeightUnitsEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL mutation operation: ProductVariantSetDefault
@ -39,6 +39,7 @@ export interface ProductVariantSetDefault_productVariantSetDefault_product_attri
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (ProductVariantSetDefault_productVariantSetDefault_product_attributes_attribute_values | null)[] | null;
}

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { ProductInput, ProductVariantInput, StockInput, ProductErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, ProductMediaType, WeightUnitsEnum, StockErrorCode } from "./../../types/globalTypes";
import { ProductInput, ProductVariantInput, StockInput, ProductErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, MeasurementUnitsEnum, ProductMediaType, WeightUnitsEnum, StockErrorCode } from "./../../types/globalTypes";
// ====================================================
// GraphQL mutation operation: SimpleProductUpdate
@ -40,6 +40,7 @@ export interface SimpleProductUpdate_productUpdate_product_attributes_attribute
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (SimpleProductUpdate_productUpdate_product_attributes_attribute_values | null)[] | null;
}
@ -336,6 +337,7 @@ export interface SimpleProductUpdate_productVariantUpdate_productVariant_selecti
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (SimpleProductUpdate_productVariantUpdate_productVariant_selectionAttributes_attribute_values | null)[] | null;
}
@ -385,6 +387,7 @@ export interface SimpleProductUpdate_productVariantUpdate_productVariant_nonSele
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (SimpleProductUpdate_productVariantUpdate_productVariant_nonSelectionAttributes_attribute_values | null)[] | null;
}
@ -625,6 +628,7 @@ export interface SimpleProductUpdate_productVariantStocksCreate_productVariant_s
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (SimpleProductUpdate_productVariantStocksCreate_productVariant_selectionAttributes_attribute_values | null)[] | null;
}
@ -674,6 +678,7 @@ export interface SimpleProductUpdate_productVariantStocksCreate_productVariant_n
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (SimpleProductUpdate_productVariantStocksCreate_productVariant_nonSelectionAttributes_attribute_values | null)[] | null;
}
@ -913,6 +918,7 @@ export interface SimpleProductUpdate_productVariantStocksDelete_productVariant_s
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (SimpleProductUpdate_productVariantStocksDelete_productVariant_selectionAttributes_attribute_values | null)[] | null;
}
@ -962,6 +968,7 @@ export interface SimpleProductUpdate_productVariantStocksDelete_productVariant_n
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (SimpleProductUpdate_productVariantStocksDelete_productVariant_nonSelectionAttributes_attribute_values | null)[] | null;
}
@ -1202,6 +1209,7 @@ export interface SimpleProductUpdate_productVariantStocksUpdate_productVariant_s
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (SimpleProductUpdate_productVariantStocksUpdate_productVariant_selectionAttributes_attribute_values | null)[] | null;
}
@ -1251,6 +1259,7 @@ export interface SimpleProductUpdate_productVariantStocksUpdate_productVariant_n
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (SimpleProductUpdate_productVariantStocksUpdate_productVariant_nonSelectionAttributes_attribute_values | null)[] | null;
}

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { ProductVariantCreateInput, ProductErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, ProductMediaType, WeightUnitsEnum } from "./../../types/globalTypes";
import { ProductVariantCreateInput, ProductErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, MeasurementUnitsEnum, ProductMediaType, WeightUnitsEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL mutation operation: VariantCreate
@ -52,6 +52,7 @@ export interface VariantCreate_productVariantCreate_productVariant_selectionAttr
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (VariantCreate_productVariantCreate_productVariant_selectionAttributes_attribute_values | null)[] | null;
}
@ -101,6 +102,7 @@ export interface VariantCreate_productVariantCreate_productVariant_nonSelectionA
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (VariantCreate_productVariantCreate_productVariant_nonSelectionAttributes_attribute_values | null)[] | null;
}

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { ProductErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, ProductMediaType, WeightUnitsEnum } from "./../../types/globalTypes";
import { ProductErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, MeasurementUnitsEnum, ProductMediaType, WeightUnitsEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL mutation operation: VariantMediaAssign
@ -51,6 +51,7 @@ export interface VariantMediaAssign_variantMediaAssign_productVariant_selectionA
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (VariantMediaAssign_variantMediaAssign_productVariant_selectionAttributes_attribute_values | null)[] | null;
}
@ -100,6 +101,7 @@ export interface VariantMediaAssign_variantMediaAssign_productVariant_nonSelecti
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (VariantMediaAssign_variantMediaAssign_productVariant_nonSelectionAttributes_attribute_values | null)[] | null;
}

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { ProductErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, ProductMediaType, WeightUnitsEnum } from "./../../types/globalTypes";
import { ProductErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, MeasurementUnitsEnum, ProductMediaType, WeightUnitsEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL mutation operation: VariantMediaUnassign
@ -51,6 +51,7 @@ export interface VariantMediaUnassign_variantMediaUnassign_productVariant_select
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (VariantMediaUnassign_variantMediaUnassign_productVariant_selectionAttributes_attribute_values | null)[] | null;
}
@ -100,6 +101,7 @@ export interface VariantMediaUnassign_variantMediaUnassign_productVariant_nonSel
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (VariantMediaUnassign_variantMediaUnassign_productVariant_nonSelectionAttributes_attribute_values | null)[] | null;
}

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { StockInput, AttributeValueInput, ProductErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, ProductMediaType, WeightUnitsEnum, StockErrorCode } from "./../../types/globalTypes";
import { StockInput, AttributeValueInput, ProductErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, MeasurementUnitsEnum, ProductMediaType, WeightUnitsEnum, StockErrorCode } from "./../../types/globalTypes";
// ====================================================
// GraphQL mutation operation: VariantUpdate
@ -52,6 +52,7 @@ export interface VariantUpdate_productVariantUpdate_productVariant_selectionAttr
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (VariantUpdate_productVariantUpdate_productVariant_selectionAttributes_attribute_values | null)[] | null;
}
@ -101,6 +102,7 @@ export interface VariantUpdate_productVariantUpdate_productVariant_nonSelectionA
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (VariantUpdate_productVariantUpdate_productVariant_nonSelectionAttributes_attribute_values | null)[] | null;
}
@ -341,6 +343,7 @@ export interface VariantUpdate_productVariantStocksUpdate_productVariant_selecti
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (VariantUpdate_productVariantStocksUpdate_productVariant_selectionAttributes_attribute_values | null)[] | null;
}
@ -390,6 +393,7 @@ export interface VariantUpdate_productVariantStocksUpdate_productVariant_nonSele
inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean;
unit: MeasurementUnitsEnum | null;
values: (VariantUpdate_productVariantStocksUpdate_productVariant_nonSelectionAttributes_attribute_values | null)[] | null;
}

View file

@ -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,
@ -88,6 +90,7 @@ export function getAttributeInputFromAttributes(
inputType: attribute.inputType,
isRequired: attribute.valueRequired,
values: attribute.values,
unit: attribute.unit,
variantAttributeScope
},
id: attribute.id,
@ -107,6 +110,7 @@ export function getAttributeInputFromSelectedAttributes(
isRequired: attribute.attribute.valueRequired,
selectedValues: attribute.values,
values: attribute.attribute.values,
unit: attribute.attribute.unit,
variantAttributeScope
},
id: attribute.attribute.id,

View file

@ -61,7 +61,7 @@ exports[`Storyshots Attributes / Attributes default 1`] = `
<div
class="MuiTypography-root-id Attributes-expansionBarLabel-id MuiTypography-caption-id"
>
5 Attributes
6 Attributes
</div>
</div>
<button
@ -366,6 +366,59 @@ exports[`Storyshots Attributes / Attributes default 1`] = `
</div>
</div>
</div>
<hr
class="Hr-root-id"
/>
<div
class="BasicAttributeRow-attributeSection-id Grid-root-id Grid-uniform-id"
>
<div
class="BasicAttributeRow-attributeSectionLabel-id"
data-test="attribute-label"
>
<div
class="MuiTypography-root-id MuiTypography-body1-id"
>
Numeric Attribute
</div>
</div>
<div
data-test="attribute-value"
>
<div
class="MuiFormControl-root-id MuiTextField-root-id MuiFormControl-fullWidth-id"
>
<label
class="MuiFormLabel-root-id MuiInputLabel-root-id MuiInputLabel-formControl-id MuiInputLabel-animated-id MuiInputLabel-outlined-id"
data-shrink="false"
>
Value
</label>
<div
class="MuiInputBase-root-id MuiOutlinedInput-root-id MuiInputBase-fullWidth-id MuiInputBase-formControl-id"
>
<input
aria-invalid="false"
class="MuiInputBase-input-id MuiOutlinedInput-input-id"
name="attribute:Numeric Attribute"
type="number"
/>
<fieldset
aria-hidden="true"
class="PrivateNotchedOutline-root-id MuiOutlinedInput-notchedOutline-id"
>
<legend
class="PrivateNotchedOutline-legendLabelled-id"
>
<span>
Value
</span>
</legend>
</fieldset>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@ -408,7 +461,7 @@ exports[`Storyshots Attributes / Attributes disabled 1`] = `
<div
class="MuiTypography-root-id Attributes-expansionBarLabel-id MuiTypography-caption-id"
>
5 Attributes
6 Attributes
</div>
</div>
<button
@ -717,6 +770,60 @@ exports[`Storyshots Attributes / Attributes disabled 1`] = `
</div>
</div>
</div>
<hr
class="Hr-root-id"
/>
<div
class="BasicAttributeRow-attributeSection-id Grid-root-id Grid-uniform-id"
>
<div
class="BasicAttributeRow-attributeSectionLabel-id"
data-test="attribute-label"
>
<div
class="MuiTypography-root-id MuiTypography-body1-id"
>
Numeric Attribute
</div>
</div>
<div
data-test="attribute-value"
>
<div
class="MuiFormControl-root-id MuiTextField-root-id MuiFormControl-fullWidth-id"
>
<label
class="MuiFormLabel-root-id MuiInputLabel-root-id MuiInputLabel-formControl-id MuiInputLabel-animated-id MuiInputLabel-outlined-id MuiFormLabel-disabled-id MuiInputLabel-disabled-id"
data-shrink="false"
>
Value
</label>
<div
class="MuiInputBase-root-id MuiOutlinedInput-root-id MuiInputBase-disabled-id MuiOutlinedInput-disabled-id MuiInputBase-fullWidth-id MuiInputBase-formControl-id"
>
<input
aria-invalid="false"
class="MuiInputBase-input-id MuiOutlinedInput-input-id MuiInputBase-disabled-id MuiOutlinedInput-disabled-id"
disabled=""
name="attribute:Numeric Attribute"
type="number"
/>
<fieldset
aria-hidden="true"
class="PrivateNotchedOutline-root-id MuiOutlinedInput-notchedOutline-id"
>
<legend
class="PrivateNotchedOutline-legendLabelled-id"
>
<span>
Value
</span>
</legend>
</fieldset>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@ -759,7 +866,7 @@ exports[`Storyshots Attributes / Attributes selected 1`] = `
<div
class="MuiTypography-root-id Attributes-expansionBarLabel-id MuiTypography-caption-id"
>
5 Attributes
6 Attributes
</div>
</div>
<button
@ -1330,6 +1437,60 @@ exports[`Storyshots Attributes / Attributes selected 1`] = `
</div>
</div>
</div>
<hr
class="Hr-root-id"
/>
<div
class="BasicAttributeRow-attributeSection-id Grid-root-id Grid-uniform-id"
>
<div
class="BasicAttributeRow-attributeSectionLabel-id"
data-test="attribute-label"
>
<div
class="MuiTypography-root-id MuiTypography-body1-id"
>
Numeric Attribute
</div>
</div>
<div
data-test="attribute-value"
>
<div
class="MuiFormControl-root-id MuiTextField-root-id MuiFormControl-fullWidth-id"
>
<label
class="MuiFormLabel-root-id MuiInputLabel-root-id MuiInputLabel-formControl-id MuiInputLabel-animated-id MuiInputLabel-shrink-id MuiInputLabel-outlined-id MuiFormLabel-filled-id"
data-shrink="true"
>
Value
</label>
<div
class="MuiInputBase-root-id MuiOutlinedInput-root-id MuiInputBase-fullWidth-id MuiInputBase-formControl-id"
>
<input
aria-invalid="false"
class="MuiInputBase-input-id MuiOutlinedInput-input-id"
name="attribute:Numeric Attribute"
type="number"
value="12cm"
/>
<fieldset
aria-hidden="true"
class="PrivateNotchedOutline-root-id MuiOutlinedInput-notchedOutline-id"
>
<legend
class="PrivateNotchedOutline-legendLabelled-id PrivateNotchedOutline-legendNotched-id"
>
<span>
Value
</span>
</legend>
</fieldset>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@ -36223,14 +36384,13 @@ exports[`Storyshots Views / Attributes / Attribute details loading 1`] = `
>
<span
aria-disabled="true"
class="MuiButtonBase-root-id MuiIconButton-root-id PrivateSwitchBase-root-id MuiCheckbox-root-id MuiCheckbox-colorPrimary-id PrivateSwitchBase-checked-id MuiCheckbox-checked-id PrivateSwitchBase-disabled-id MuiCheckbox-disabled-id MuiIconButton-colorPrimary-id MuiIconButton-disabled-id MuiButtonBase-disabled-id"
class="MuiButtonBase-root-id MuiIconButton-root-id PrivateSwitchBase-root-id MuiCheckbox-root-id MuiCheckbox-colorPrimary-id PrivateSwitchBase-disabled-id MuiCheckbox-disabled-id MuiIconButton-colorPrimary-id MuiIconButton-disabled-id MuiButtonBase-disabled-id"
tabindex="-1"
>
<span
class="MuiIconButton-label-id"
>
<input
checked=""
class="PrivateSwitchBase-input-id"
data-indeterminate="false"
disabled=""
@ -36244,18 +36404,13 @@ exports[`Storyshots Views / Attributes / Attribute details loading 1`] = `
viewBox="0 0 24 24"
>
<rect
fill="currentColor"
fill="none"
height="14"
stroke="currentColor"
width="14"
x="5"
y="5"
/>
<path
clip-rule="evenodd"
d="M 16.7527 9.33783 L 10.86618 15.7595 L 8 12.32006 L 8.76822 11.67988 L 10.90204 14.24046 L 16.0155 8.66211 L 16.7527 9.33783 Z"
fill="white"
fill-rule="evenodd"
/>
</svg>
</span>
</span>

View file

@ -89,6 +89,7 @@ export enum AttributeInputTypeEnum {
DROPDOWN = "DROPDOWN",
FILE = "FILE",
MULTISELECT = "MULTISELECT",
NUMERIC = "NUMERIC",
REFERENCE = "REFERENCE",
RICH_TEXT = "RICH_TEXT",
}
@ -530,6 +531,39 @@ export enum LanguageCodeEnum {
ZH_HANT = "ZH_HANT",
}
export enum MeasurementUnitsEnum {
ACRE_FT = "ACRE_FT",
ACRE_IN = "ACRE_IN",
CM = "CM",
CUBIC_CENTIMETER = "CUBIC_CENTIMETER",
CUBIC_DECIMETER = "CUBIC_DECIMETER",
CUBIC_FOOT = "CUBIC_FOOT",
CUBIC_INCH = "CUBIC_INCH",
CUBIC_METER = "CUBIC_METER",
CUBIC_MILLIMETER = "CUBIC_MILLIMETER",
CUBIC_YARD = "CUBIC_YARD",
FL_OZ = "FL_OZ",
FT = "FT",
G = "G",
INCH = "INCH",
KG = "KG",
KM = "KM",
LB = "LB",
LITER = "LITER",
M = "M",
OZ = "OZ",
PINT = "PINT",
QT = "QT",
SQ_CM = "SQ_CM",
SQ_FT = "SQ_FT",
SQ_INCH = "SQ_INCH",
SQ_KM = "SQ_KM",
SQ_M = "SQ_M",
SQ_YD = "SQ_YD",
TONNE = "TONNE",
YD = "YD",
}
export enum MenuErrorCode {
CANNOT_ASSIGN_NODE = "CANNOT_ASSIGN_NODE",
GRAPHQL_ERROR = "GRAPHQL_ERROR",
@ -1025,6 +1059,7 @@ export enum WeightUnitsEnum {
KG = "KG",
LB = "LB",
OZ = "OZ",
TONNE = "TONNE",
}
export interface AddressInput {
@ -1075,6 +1110,7 @@ export interface AttributeCreateInput {
name: string;
slug?: string | null;
type: AttributeTypeEnum;
unit?: MeasurementUnitsEnum | null;
values?: (AttributeValueCreateInput | null)[] | null;
valueRequired?: boolean | null;
isVariantOnly?: boolean | null;
@ -1104,6 +1140,7 @@ export interface AttributeFilterInput {
export interface AttributeInput {
slug: string;
values?: (string | null)[] | null;
valuesRange?: IntRangeInput | null;
}
export interface AttributeSortingInput {
@ -1114,6 +1151,7 @@ export interface AttributeSortingInput {
export interface AttributeUpdateInput {
name?: string | null;
slug?: string | null;
unit?: MeasurementUnitsEnum | null;
removeValues?: (string | null)[] | null;
addValues?: (AttributeValueCreateInput | null)[] | null;
valueRequired?: boolean | null;