2021-05-14 08:15:15 +00:00
|
|
|
import { Card, CardContent, IconButton, Typography } from "@material-ui/core";
|
2019-08-09 10:17:04 +00:00
|
|
|
import ArrowDropDownIcon from "@material-ui/icons/ArrowDropDown";
|
2021-01-20 16:37:36 +00:00
|
|
|
import { AttributeReference } from "@saleor/attributes/utils/data";
|
2019-08-09 10:17:04 +00:00
|
|
|
import CardTitle from "@saleor/components/CardTitle";
|
|
|
|
import Hr from "@saleor/components/Hr";
|
2020-12-16 10:53:28 +00:00
|
|
|
import { AttributeValueFragment } from "@saleor/fragments/types/AttributeValueFragment";
|
|
|
|
import { PageErrorWithAttributesFragment } from "@saleor/fragments/types/PageErrorWithAttributesFragment";
|
2020-10-03 09:52:59 +00:00
|
|
|
import { ProductErrorWithAttributesFragment } from "@saleor/fragments/types/ProductErrorWithAttributesFragment";
|
2021-04-09 07:51:49 +00:00
|
|
|
import { FormsetAtomicData } from "@saleor/hooks/useFormset";
|
2021-03-30 07:40:18 +00:00
|
|
|
import { makeStyles } from "@saleor/theme";
|
2021-01-20 16:37:36 +00:00
|
|
|
import {
|
|
|
|
AttributeEntityTypeEnum,
|
2021-04-29 08:58:03 +00:00
|
|
|
AttributeInputTypeEnum,
|
|
|
|
MeasurementUnitsEnum
|
2021-01-20 16:37:36 +00:00
|
|
|
} from "@saleor/types/globalTypes";
|
2020-05-14 09:30:32 +00:00
|
|
|
import classNames from "classnames";
|
|
|
|
import React from "react";
|
2021-04-09 07:51:49 +00:00
|
|
|
import { defineMessages, FormattedMessage, useIntl } from "react-intl";
|
2019-08-09 10:17:04 +00:00
|
|
|
|
2021-04-09 07:51:49 +00:00
|
|
|
import AttributeRow, { AttributeRowHandlers } from "./AttributeRow";
|
2020-12-16 10:53:28 +00:00
|
|
|
import { VariantAttributeScope } from "./types";
|
|
|
|
|
|
|
|
export interface AttributeInputData {
|
2019-08-09 10:17:04 +00:00
|
|
|
inputType: AttributeInputTypeEnum;
|
2021-01-20 16:37:36 +00:00
|
|
|
entityType?: AttributeEntityTypeEnum;
|
2021-04-29 08:58:03 +00:00
|
|
|
unit?: MeasurementUnitsEnum | null;
|
2020-12-16 10:53:28 +00:00
|
|
|
variantAttributeScope?: VariantAttributeScope;
|
2019-08-09 10:17:04 +00:00
|
|
|
isRequired: boolean;
|
2020-12-16 10:53:28 +00:00
|
|
|
values: AttributeValueFragment[];
|
|
|
|
selectedValues?: AttributeValueFragment[];
|
2021-01-20 16:37:36 +00:00
|
|
|
references?: AttributeReference[];
|
2019-08-09 10:17:04 +00:00
|
|
|
}
|
2020-12-16 10:53:28 +00:00
|
|
|
export type AttributeInput = FormsetAtomicData<AttributeInputData, string[]>;
|
|
|
|
export type AttributeFileInput = FormsetAtomicData<AttributeInputData, File[]>;
|
2021-04-09 07:51:49 +00:00
|
|
|
export interface AttributesProps extends AttributeRowHandlers {
|
2020-12-16 10:53:28 +00:00
|
|
|
attributes: AttributeInput[];
|
2019-08-09 10:17:04 +00:00
|
|
|
disabled: boolean;
|
2020-12-16 10:53:28 +00:00
|
|
|
loading: boolean;
|
|
|
|
errors: Array<
|
|
|
|
ProductErrorWithAttributesFragment | PageErrorWithAttributesFragment
|
|
|
|
>;
|
|
|
|
title?: React.ReactNode;
|
2019-08-09 10:17:04 +00:00
|
|
|
}
|
|
|
|
|
2019-12-03 15:28:40 +00:00
|
|
|
const useStyles = makeStyles(
|
|
|
|
theme => ({
|
|
|
|
attributeSection: {
|
|
|
|
"&:last-of-type": {
|
|
|
|
paddingBottom: 0
|
|
|
|
},
|
|
|
|
padding: theme.spacing(2, 0)
|
2019-08-09 10:17:04 +00:00
|
|
|
},
|
2019-12-03 15:28:40 +00:00
|
|
|
attributeSectionLabel: {
|
|
|
|
alignItems: "center",
|
|
|
|
display: "flex"
|
2019-08-09 10:17:04 +00:00
|
|
|
},
|
2019-12-03 15:28:40 +00:00
|
|
|
card: {
|
|
|
|
overflow: "visible"
|
|
|
|
},
|
|
|
|
cardContent: {
|
|
|
|
"&:last-child": {
|
|
|
|
paddingBottom: theme.spacing(1)
|
|
|
|
},
|
|
|
|
paddingTop: theme.spacing(1)
|
|
|
|
},
|
|
|
|
expansionBar: {
|
|
|
|
display: "flex"
|
|
|
|
},
|
|
|
|
expansionBarButton: {
|
|
|
|
marginBottom: theme.spacing(1)
|
|
|
|
},
|
|
|
|
expansionBarButtonIcon: {
|
|
|
|
transition: theme.transitions.duration.short + "ms"
|
|
|
|
},
|
|
|
|
expansionBarLabel: {
|
|
|
|
color: theme.palette.text.disabled,
|
|
|
|
fontSize: 14
|
|
|
|
},
|
|
|
|
expansionBarLabelContainer: {
|
|
|
|
alignItems: "center",
|
|
|
|
display: "flex",
|
|
|
|
flex: 1
|
|
|
|
},
|
|
|
|
rotate: {
|
|
|
|
transform: "rotate(180deg)"
|
2020-12-16 10:53:28 +00:00
|
|
|
},
|
|
|
|
uploadFileButton: {
|
|
|
|
float: "right"
|
|
|
|
},
|
|
|
|
uploadFileContent: {
|
|
|
|
color: theme.palette.primary.main,
|
|
|
|
float: "right",
|
|
|
|
fontSize: "1rem"
|
2019-12-03 15:28:40 +00:00
|
|
|
}
|
|
|
|
}),
|
2020-12-16 10:53:28 +00:00
|
|
|
{ name: "Attributes" }
|
2019-12-03 15:28:40 +00:00
|
|
|
);
|
2019-08-09 10:17:04 +00:00
|
|
|
|
2020-12-16 10:53:28 +00:00
|
|
|
const messages = defineMessages({
|
|
|
|
attributesNumber: {
|
|
|
|
defaultMessage: "{number} Attributes",
|
|
|
|
description: "number of attributes"
|
|
|
|
},
|
|
|
|
header: {
|
|
|
|
defaultMessage: "Attributes",
|
|
|
|
description: "attributes, section header"
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
const Attributes: React.FC<AttributesProps> = ({
|
2019-08-09 10:17:04 +00:00
|
|
|
attributes,
|
2020-09-29 14:31:17 +00:00
|
|
|
errors,
|
2020-12-16 10:53:28 +00:00
|
|
|
title,
|
2021-04-09 07:51:49 +00:00
|
|
|
...props
|
2019-08-09 10:17:04 +00:00
|
|
|
}) => {
|
2019-08-26 17:53:22 +00:00
|
|
|
const intl = useIntl();
|
2019-08-09 10:17:04 +00:00
|
|
|
const classes = useStyles({});
|
|
|
|
const [expanded, setExpansionStatus] = React.useState(true);
|
|
|
|
const toggleExpansion = () => setExpansionStatus(!expanded);
|
|
|
|
|
|
|
|
return (
|
|
|
|
<Card className={classes.card}>
|
2020-12-16 10:53:28 +00:00
|
|
|
<CardTitle title={title || intl.formatMessage(messages.header)} />
|
2019-08-09 10:17:04 +00:00
|
|
|
<CardContent className={classes.cardContent}>
|
|
|
|
<div className={classes.expansionBar}>
|
|
|
|
<div className={classes.expansionBarLabelContainer}>
|
|
|
|
<Typography className={classes.expansionBarLabel} variant="caption">
|
2019-08-26 17:53:22 +00:00
|
|
|
<FormattedMessage
|
2020-12-16 10:53:28 +00:00
|
|
|
{...messages.attributesNumber}
|
2019-08-26 17:53:22 +00:00
|
|
|
values={{
|
|
|
|
number: attributes.length
|
|
|
|
}}
|
|
|
|
/>
|
2019-08-09 10:17:04 +00:00
|
|
|
</Typography>
|
|
|
|
</div>
|
|
|
|
<IconButton
|
|
|
|
className={classes.expansionBarButton}
|
|
|
|
onClick={toggleExpansion}
|
2020-12-16 10:53:28 +00:00
|
|
|
data-test="attributes-expand"
|
2019-08-09 10:17:04 +00:00
|
|
|
>
|
|
|
|
<ArrowDropDownIcon
|
|
|
|
className={classNames(classes.expansionBarButtonIcon, {
|
|
|
|
[classes.rotate]: expanded
|
|
|
|
})}
|
|
|
|
/>
|
|
|
|
</IconButton>
|
|
|
|
</div>
|
|
|
|
{expanded && attributes.length > 0 && (
|
|
|
|
<>
|
|
|
|
<Hr />
|
2020-09-29 14:31:17 +00:00
|
|
|
{attributes.map((attribute, attributeIndex) => {
|
2020-10-03 09:52:59 +00:00
|
|
|
const error = errors.find(err =>
|
|
|
|
err.attributes?.includes(attribute.id)
|
2020-09-29 14:31:17 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
return (
|
|
|
|
<React.Fragment key={attribute.id}>
|
|
|
|
{attributeIndex > 0 && <Hr />}
|
2021-04-09 07:51:49 +00:00
|
|
|
<AttributeRow
|
|
|
|
attribute={attribute}
|
|
|
|
error={error}
|
|
|
|
{...props}
|
|
|
|
/>
|
2020-09-29 14:31:17 +00:00
|
|
|
</React.Fragment>
|
|
|
|
);
|
|
|
|
})}
|
2019-08-09 10:17:04 +00:00
|
|
|
</>
|
|
|
|
)}
|
|
|
|
</CardContent>
|
|
|
|
</Card>
|
|
|
|
);
|
|
|
|
};
|
2020-12-16 10:53:28 +00:00
|
|
|
Attributes.displayName = "Attributes";
|
|
|
|
export default Attributes;
|