Product variants enhancements (#1918)

* Remove savebar docking

* Hide attributes if empty

* Select text in autocomplete after initial click

* Update snapshots

* Use stable macaw version

* Remove maybes

* Add util filter function
This commit is contained in:
Dominik Żegleń 2022-03-16 10:45:15 +01:00 committed by GitHub
parent 3e96a68a6e
commit ac4a219023
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 191 additions and 291 deletions

5
package-lock.json generated
View file

@ -4828,8 +4828,9 @@
} }
}, },
"@saleor/macaw-ui": { "@saleor/macaw-ui": {
"version": "github:saleor/macaw-ui#1f78f97748c00a64ca46973c32eacc4d9a1ac2ac", "version": "0.3.3",
"from": "github:saleor/macaw-ui#SALEOR-5840-button-states", "resolved": "https://registry.npmjs.org/@saleor/macaw-ui/-/macaw-ui-0.3.3.tgz",
"integrity": "sha512-b2dLlOAXDe2OSmYeZSFKwiRMrJc+YkGhvvQCHQXHHP89TZbGZlWP0F13ycCI3OJSfYbCWZlQGM+alMiE31HOuA==",
"requires": { "requires": {
"clsx": "^1.1.1", "clsx": "^1.1.1",
"lodash": "^4.17.21", "lodash": "^4.17.21",

View file

@ -28,7 +28,7 @@
"@material-ui/icons": "^4.11.2", "@material-ui/icons": "^4.11.2",
"@material-ui/lab": "^4.0.0-alpha.58", "@material-ui/lab": "^4.0.0-alpha.58",
"@material-ui/styles": "^4.11.4", "@material-ui/styles": "^4.11.4",
"@saleor/macaw-ui": "github:saleor/macaw-ui#SALEOR-5840-button-states", "@saleor/macaw-ui": "^0.3.3",
"@saleor/sdk": "^0.4.2", "@saleor/sdk": "^0.4.2",
"@sentry/react": "^6.0.0", "@sentry/react": "^6.0.0",
"@types/faker": "^5.1.6", "@types/faker": "^5.1.6",

View file

@ -13,7 +13,6 @@ import {
} from "@saleor/macaw-ui"; } from "@saleor/macaw-ui";
import { isDarkTheme } from "@saleor/misc"; import { isDarkTheme } from "@saleor/misc";
import { staffMemberDetailsUrl } from "@saleor/staff/urls"; import { staffMemberDetailsUrl } from "@saleor/staff/urls";
import classNames from "classnames";
import React from "react"; import React from "react";
import { useIntl } from "react-intl"; import { useIntl } from "react-intl";
import useRouter from "use-react-router"; import useRouter from "use-react-router";
@ -41,9 +40,6 @@ const useStyles = makeStyles(
position: "sticky", position: "sticky",
zIndex: 10 zIndex: 10
}, },
appActionDocked: {
position: "static"
},
appLoader: { appLoader: {
height: appLoaderHeight, height: appLoaderHeight,
marginBottom: theme.spacing(4), marginBottom: theme.spacing(4),
@ -123,7 +119,7 @@ interface AppLayoutProps {
const AppLayout: React.FC<AppLayoutProps> = ({ children }) => { const AppLayout: React.FC<AppLayoutProps> = ({ children }) => {
const classes = useStyles({}); const classes = useStyles({});
const { themeType, setTheme } = useTheme(); const { themeType, setTheme } = useTheme();
const { anchor: appActionAnchor, docked } = useActionBar(); const { anchor: appActionAnchor } = useActionBar();
const appHeaderAnchor = useBacklink(); const appHeaderAnchor = useBacklink();
const { logout, user } = useUser(); const { logout, user } = useUser();
const navigate = useNavigator(); const navigate = useNavigator();
@ -234,12 +230,7 @@ const AppLayout: React.FC<AppLayoutProps> = ({ children }) => {
: children} : children}
</main> </main>
</div> </div>
<div <div className={classes.appAction} ref={appActionAnchor} />
className={classNames(classes.appAction, {
[classes.appActionDocked]: docked
})}
ref={appActionAnchor}
/>
</div> </div>
</div> </div>
</> </>

View file

@ -90,7 +90,8 @@ const SingleAutocompleteSelectFieldComponent: React.FC<SingleAutocompleteSelectF
...rest ...rest
} = props; } = props;
const classes = useStyles(props); const classes = useStyles(props);
const anchor = React.useRef<HTMLInputElement | null>(null); const anchor = React.useRef<HTMLDivElement | null>(null);
const input = React.useRef<HTMLInputElement | null>(null);
const handleChange = (item: string) => { const handleChange = (item: string) => {
onChange({ onChange({
@ -188,6 +189,7 @@ const SingleAutocompleteSelectFieldComponent: React.FC<SingleAutocompleteSelectF
if (fetchOnFocus) { if (fetchOnFocus) {
fetchChoices(inputValue); fetchChoices(inputValue);
} }
input.current.select();
} }
}; };
@ -224,6 +226,7 @@ const SingleAutocompleteSelectFieldComponent: React.FC<SingleAutocompleteSelectF
fullWidth={true} fullWidth={true}
onBlur={onBlur} onBlur={onBlur}
ref={anchor} ref={anchor}
inputRef={input}
/> />
{isOpen && (!!inputValue || !!choices.length) && ( {isOpen && (!!inputValue || !!choices.length) && (
<Popper <Popper

View file

@ -29,7 +29,6 @@ import { FetchMoreProps, RelayToFlat, ReorderAction } from "@saleor/types";
import React from "react"; import React from "react";
import { defineMessages, useIntl } from "react-intl"; import { defineMessages, useIntl } from "react-intl";
import { maybe } from "../../../misc";
import ProductShipping from "../ProductShipping/ProductShipping"; import ProductShipping from "../ProductShipping/ProductShipping";
import ProductStocks, { ProductStockInput } from "../ProductStocks"; import ProductStocks, { ProductStockInput } from "../ProductStocks";
import ProductVariantCheckoutSettings from "../ProductVariantCheckoutSettings/ProductVariantCheckoutSettings"; import ProductVariantCheckoutSettings from "../ProductVariantCheckoutSettings/ProductVariantCheckoutSettings";
@ -73,6 +72,11 @@ export interface ProductVariantPageSubmitData
removeStocks: string[]; removeStocks: string[];
} }
function byAttributeScope(scope: VariantAttributeScope) {
return (attribute: AttributeInput) =>
attribute.data.variantAttributeScope === scope;
}
interface ProductVariantPageProps { interface ProductVariantPageProps {
assignReferencesAttributeId?: string; assignReferencesAttributeId?: string;
defaultVariantId?: string; defaultVariantId?: string;
@ -223,17 +227,23 @@ const ProductVariantPage: React.FC<ProductVariantPageProps> = ({
handlers, handlers,
hasChanged, hasChanged,
submit submit
}) => ( }) => {
const nonSelectionAttributes = data.attributes.filter(
byAttributeScope(VariantAttributeScope.NOT_VARIANT_SELECTION)
);
const selectionAttributes = data.attributes.filter(
byAttributeScope(VariantAttributeScope.VARIANT_SELECTION)
);
return (
<> <>
<Grid variant="inverted"> <Grid variant="inverted">
<div> <div>
<ProductVariantNavigation <ProductVariantNavigation
current={variant ? variant.id : undefined} current={variant?.id}
defaultVariantId={defaultVariantId} defaultVariantId={defaultVariantId}
fallbackThumbnail={maybe( fallbackThumbnail={variant?.product.thumbnail.url}
() => variant.product.thumbnail.url variants={variant?.product.variants}
)}
variants={maybe(() => variant.product.variants)}
onAdd={onAdd} onAdd={onAdd}
onRowClick={(variantId: string) => { onRowClick={(variantId: string) => {
if (variant) { if (variant) {
@ -245,14 +255,14 @@ const ProductVariantPage: React.FC<ProductVariantPageProps> = ({
</div> </div>
<div> <div>
<VariantDetailsChannelsAvailabilityCard variant={variant} /> <VariantDetailsChannelsAvailabilityCard variant={variant} />
{nonSelectionAttributes.length > 0 && (
<>
<Attributes <Attributes
entityId={variant?.id} entityId={variant?.id}
title={intl.formatMessage(messages.nonSelectionAttributes)} title={intl.formatMessage(
attributes={data.attributes.filter( messages.nonSelectionAttributes
attribute =>
attribute.data.variantAttributeScope ===
VariantAttributeScope.NOT_VARIANT_SELECTION
)} )}
attributes={nonSelectionAttributes}
attributeValues={attributeValues} attributeValues={attributeValues}
loading={loading} loading={loading}
disabled={loading} disabled={loading}
@ -268,16 +278,16 @@ const ProductVariantPage: React.FC<ProductVariantPageProps> = ({
onAttributeSelectBlur={onAttributeSelectBlur} onAttributeSelectBlur={onAttributeSelectBlur}
/> />
<CardSpacer /> <CardSpacer />
</>
)}
{selectionAttributes.length > 0 && (
<>
<Attributes <Attributes
entityId={variant?.id} entityId={variant?.id}
title={intl.formatMessage( title={intl.formatMessage(
messages.selectionAttributesHeader messages.selectionAttributesHeader
)} )}
attributes={data.attributes.filter( attributes={selectionAttributes}
attribute =>
attribute.data.variantAttributeScope ===
VariantAttributeScope.VARIANT_SELECTION
)}
attributeValues={attributeValues} attributeValues={attributeValues}
loading={loading} loading={loading}
disabled={loading} disabled={loading}
@ -293,6 +303,8 @@ const ProductVariantPage: React.FC<ProductVariantPageProps> = ({
onAttributeSelectBlur={onAttributeSelectBlur} onAttributeSelectBlur={onAttributeSelectBlur}
/> />
<CardSpacer /> <CardSpacer />
</>
)}
<ProductVariantMedia <ProductVariantMedia
disabled={loading} disabled={loading}
media={media} media={media}
@ -391,7 +403,8 @@ const ProductVariantPage: React.FC<ProductVariantPageProps> = ({
/> />
)} )}
</> </>
)} );
}}
</ProductVariantUpdateForm> </ProductVariantUpdateForm>
</Container> </Container>
{variant && ( {variant && (
@ -400,7 +413,7 @@ const ProductVariantPage: React.FC<ProductVariantPageProps> = ({
onMediaSelect={onMediaSelect} onMediaSelect={onMediaSelect}
open={isModalOpened} open={isModalOpened}
media={productMedia} media={productMedia}
selectedMedia={maybe(() => variant.media.map(image => image.id))} selectedMedia={variant?.media.map(image => image.id)}
/> />
)} )}
{!!variant?.preorder && ( {!!variant?.preorder && (

View file

@ -225170,114 +225170,6 @@ exports[`Storyshots Views / Products / Product variant details when loading data
<div <div
class="CardSpacer-spacer-id" class="CardSpacer-spacer-id"
/> />
<div
class="MuiPaper-root-id MuiCard-root-id Attributes-card-id MuiPaper-elevation0-id MuiPaper-rounded-id"
>
<div
class="MuiCardHeader-root-id"
>
<div
class="MuiCardHeader-content-id"
>
<span
class="MuiTypography-root-id MuiCardHeader-title-id MuiTypography-h5-id MuiTypography-displayBlock-id"
>
Variant Attributes
</span>
</div>
</div>
<div
class="MuiCardContent-root-id Attributes-cardContent-id"
>
<div
class="Attributes-expansionBar-id"
>
<div
class="Attributes-expansionBarLabelContainer-id"
>
<div
class="MuiTypography-root-id Attributes-expansionBarLabel-id MuiTypography-caption-id"
>
0 Attributes
</div>
</div>
<button
class="MuiButtonBase-root-id IconButton-secondary-id Attributes-expansionBarButton-id IconButton-hoverOutline-id"
data-test-id="attributes-expand"
tabindex="0"
type="button"
>
<svg
aria-hidden="true"
class="MuiSvgIcon-root-id Attributes-expansionBarButtonIcon-id Attributes-rotate-id"
focusable="false"
viewBox="0 0 24 24"
>
<path
d="M7 10l5 5 5-5z"
/>
</svg>
</button>
</div>
</div>
</div>
<div
class="CardSpacer-spacer-id"
/>
<div
class="MuiPaper-root-id MuiCard-root-id Attributes-card-id MuiPaper-elevation0-id MuiPaper-rounded-id"
>
<div
class="MuiCardHeader-root-id"
>
<div
class="MuiCardHeader-content-id"
>
<span
class="MuiTypography-root-id MuiCardHeader-title-id MuiTypography-h5-id MuiTypography-displayBlock-id"
>
Variant Selection Attributes
</span>
</div>
</div>
<div
class="MuiCardContent-root-id Attributes-cardContent-id"
>
<div
class="Attributes-expansionBar-id"
>
<div
class="Attributes-expansionBarLabelContainer-id"
>
<div
class="MuiTypography-root-id Attributes-expansionBarLabel-id MuiTypography-caption-id"
>
0 Attributes
</div>
</div>
<button
class="MuiButtonBase-root-id IconButton-secondary-id Attributes-expansionBarButton-id IconButton-hoverOutline-id"
data-test-id="attributes-expand"
tabindex="0"
type="button"
>
<svg
aria-hidden="true"
class="MuiSvgIcon-root-id Attributes-expansionBarButtonIcon-id Attributes-rotate-id"
focusable="false"
viewBox="0 0 24 24"
>
<path
d="M7 10l5 5 5-5z"
/>
</svg>
</button>
</div>
</div>
</div>
<div
class="CardSpacer-spacer-id"
/>
<div <div
class="MuiPaper-root-id MuiCard-root-id MuiPaper-elevation0-id MuiPaper-rounded-id" class="MuiPaper-root-id MuiCard-root-id MuiPaper-elevation0-id MuiPaper-rounded-id"
> >