mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-29 05:00:43 +10:00
Use Image variants instead of sizes
This commit is contained in:
parent
f7cc195ecc
commit
946cf7f53c
32 changed files with 454 additions and 654 deletions
|
|
@ -55,11 +55,7 @@ const ThumbnailWrapper = props => {
|
|||
rootClassName={css.rootForImage}
|
||||
image={image}
|
||||
alt={savedImageAltText}
|
||||
nameSet={[
|
||||
{ name: 'landscape-crop', size: '400w' },
|
||||
{ name: 'landscape-crop2x', size: '800w' },
|
||||
]}
|
||||
sizes="100%"
|
||||
variants={['landscape-crop', 'landscape-crop2x']}
|
||||
/>
|
||||
</div>
|
||||
<RemoveImageButton onClick={handleRemoveClick} />
|
||||
|
|
|
|||
|
|
@ -38,20 +38,20 @@ const userWithProfileImage = {
|
|||
id: new UUID('profile-image'),
|
||||
type: 'image',
|
||||
attributes: {
|
||||
sizes: [
|
||||
{
|
||||
name: 'square-xlarge2x',
|
||||
variants: {
|
||||
'square-small': {
|
||||
name: 'square-small',
|
||||
width: 240,
|
||||
height: 240,
|
||||
url: 'https://lorempixel.com/240/240/people/',
|
||||
},
|
||||
{
|
||||
name: 'square-xlarge4x',
|
||||
'square-small2x': {
|
||||
name: 'square-small2x',
|
||||
width: 480,
|
||||
height: 480,
|
||||
url: 'https://lorempixel.com/480/480/people/',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { string, oneOfType, bool } from 'prop-types';
|
||||
import { injectIntl, intlShape } from 'react-intl';
|
||||
import classNames from 'classnames';
|
||||
import { propTypes } from '../../util/types';
|
||||
|
|
@ -13,8 +13,21 @@ import { ResponsiveImage, IconBannedUser, NamedLink } from '../../components/';
|
|||
|
||||
import css from './Avatar.css';
|
||||
|
||||
// Responsive image sizes hint
|
||||
const AVATAR_SIZES = '40px';
|
||||
const AVATAR_SIZES_MEDIUM = '60px';
|
||||
const AVATAR_SIZES_LARGE = '96px';
|
||||
|
||||
const AVATAR_IMAGE_VARIANTS = [
|
||||
// 240x240
|
||||
'square-small',
|
||||
|
||||
// 480x480
|
||||
'square-small2x',
|
||||
];
|
||||
|
||||
export const AvatarComponent = props => {
|
||||
const { rootClassName, className, user, disableProfileLink, intl } = props;
|
||||
const { rootClassName, className, user, renderSizes, disableProfileLink, intl } = props;
|
||||
const classes = classNames(rootClassName || css.root, className);
|
||||
|
||||
const userIsCurrentUser = user && user.type === 'currentUser';
|
||||
|
|
@ -49,10 +62,8 @@ export const AvatarComponent = props => {
|
|||
rootClassName={css.avatarImage}
|
||||
alt={displayName}
|
||||
image={avatarUser.profileImage}
|
||||
nameSet={[
|
||||
{ name: 'square-xlarge2x', size: '1x' },
|
||||
{ name: 'square-xlarge4x', size: '2x' },
|
||||
]}
|
||||
variants={AVATAR_IMAGE_VARIANTS}
|
||||
sizes={renderSizes}
|
||||
/>
|
||||
</NamedLink>
|
||||
);
|
||||
|
|
@ -63,10 +74,8 @@ export const AvatarComponent = props => {
|
|||
rootClassName={css.avatarImage}
|
||||
alt={displayName}
|
||||
image={avatarUser.profileImage}
|
||||
nameSet={[
|
||||
{ name: 'square-xlarge2x', size: '1x' },
|
||||
{ name: 'square-xlarge4x', size: '2x' },
|
||||
]}
|
||||
variants={AVATAR_IMAGE_VARIANTS}
|
||||
sizes={renderSizes}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
|
@ -91,16 +100,16 @@ AvatarComponent.defaultProps = {
|
|||
className: null,
|
||||
rootClassName: null,
|
||||
user: null,
|
||||
renderSizes: AVATAR_SIZES,
|
||||
disableProfileLink: false,
|
||||
};
|
||||
|
||||
const { string, oneOfType, bool } = PropTypes;
|
||||
|
||||
AvatarComponent.propTypes = {
|
||||
rootClassName: string,
|
||||
className: string,
|
||||
user: oneOfType([propTypes.user, propTypes.currentUser]),
|
||||
|
||||
renderSizes: string,
|
||||
disableProfileLink: bool,
|
||||
|
||||
// from injectIntl
|
||||
|
|
@ -111,8 +120,12 @@ const Avatar = injectIntl(AvatarComponent);
|
|||
|
||||
export default Avatar;
|
||||
|
||||
export const AvatarMedium = props => <Avatar rootClassName={css.mediumAvatar} {...props} />;
|
||||
export const AvatarMedium = props => (
|
||||
<Avatar rootClassName={css.mediumAvatar} renderSizes={AVATAR_SIZES_MEDIUM} {...props} />
|
||||
);
|
||||
AvatarMedium.displayName = 'AvatarMedium';
|
||||
|
||||
export const AvatarLarge = props => <Avatar rootClassName={css.largeAvatar} {...props} />;
|
||||
export const AvatarLarge = props => (
|
||||
<Avatar rootClassName={css.largeAvatar} renderSizes={AVATAR_SIZES_LARGE} {...props} />
|
||||
);
|
||||
AvatarLarge.displayName = 'AvatarLarge';
|
||||
|
|
|
|||
|
|
@ -13,32 +13,32 @@ const imageSquare = {
|
|||
id: new UUID('image-square'),
|
||||
type: 'image',
|
||||
attributes: {
|
||||
sizes: [
|
||||
{
|
||||
variants: {
|
||||
[imageName]: {
|
||||
name: imageName,
|
||||
width: 400,
|
||||
height: 400,
|
||||
url: 'https://via.placeholder.com/400x400',
|
||||
},
|
||||
{
|
||||
[imageName2x]: {
|
||||
name: imageName2x,
|
||||
width: 800,
|
||||
height: 800,
|
||||
url: 'https://via.placeholder.com/800x800',
|
||||
},
|
||||
{
|
||||
[imageName4x]: {
|
||||
name: imageName4x,
|
||||
width: 1600,
|
||||
height: 1600,
|
||||
url: 'https://via.placeholder.com/1600x1600',
|
||||
},
|
||||
{
|
||||
[imageName6x]: {
|
||||
name: imageName6x,
|
||||
width: 2400,
|
||||
height: 2400,
|
||||
url: 'https://via.placeholder.com/2400x2400',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -46,64 +46,64 @@ const imagePortrait = {
|
|||
id: new UUID('image-portrait'),
|
||||
type: 'image',
|
||||
attributes: {
|
||||
sizes: [
|
||||
{
|
||||
variants: {
|
||||
[imageName]: {
|
||||
name: imageName,
|
||||
width: 400,
|
||||
height: 800,
|
||||
url: 'https://via.placeholder.com/400x800',
|
||||
},
|
||||
{
|
||||
[imageName2x]: {
|
||||
name: imageName2x,
|
||||
width: 800,
|
||||
height: 1600,
|
||||
url: 'https://via.placeholder.com/800x1600',
|
||||
},
|
||||
{
|
||||
[imageName4x]: {
|
||||
name: imageName4x,
|
||||
width: 800,
|
||||
height: 1600,
|
||||
url: 'https://via.placeholder.com/800x1600',
|
||||
},
|
||||
{
|
||||
[imageName6x]: {
|
||||
name: imageName6x,
|
||||
width: 1200,
|
||||
height: 2400,
|
||||
url: 'https://via.placeholder.com/1200x2400',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
const imageLandscape = {
|
||||
id: new UUID('image-landscape'),
|
||||
type: 'image',
|
||||
attributes: {
|
||||
sizes: [
|
||||
{
|
||||
variants: {
|
||||
[imageName]: {
|
||||
name: imageName,
|
||||
width: 400,
|
||||
height: 200,
|
||||
url: 'https://via.placeholder.com/400x200',
|
||||
},
|
||||
{
|
||||
[imageName2x]: {
|
||||
name: imageName2x,
|
||||
width: 800,
|
||||
height: 400,
|
||||
url: 'https://via.placeholder.com/800x400',
|
||||
},
|
||||
{
|
||||
[imageName4x]: {
|
||||
name: imageName4x,
|
||||
width: 1600,
|
||||
height: 800,
|
||||
url: 'https://via.placeholder.com/1600x800',
|
||||
},
|
||||
{
|
||||
[imageName6x]: {
|
||||
name: imageName6x,
|
||||
width: 2400,
|
||||
height: 1200,
|
||||
url: 'https://via.placeholder.com/2400x1200',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -10,11 +10,6 @@ import css from './ImageCarousel.css';
|
|||
const KEY_CODE_LEFT_ARROW = 37;
|
||||
const KEY_CODE_RIGHT_ARROW = 39;
|
||||
|
||||
const imageScaledSmall = 'scaled-small'; // width 320
|
||||
const imageScaledMedium = 'scaled-medium'; // width 750
|
||||
const imageScaledLarge = 'scaled-large'; // width 1024
|
||||
const imageScaledXLarge = 'scaled-xlarge'; // width 2400
|
||||
|
||||
class ImageCarousel extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
|
@ -112,12 +107,7 @@ class ImageCarousel extends Component {
|
|||
image={images[this.state.selectedImageIndex]}
|
||||
onLoad={markImageLoaded(this.state.selectedImageIndex)}
|
||||
onError={markImageLoaded(this.state.selectedImageIndex)}
|
||||
nameSet={[
|
||||
{ name: imageScaledSmall, size: '320w' },
|
||||
{ name: imageScaledMedium, size: '750w' },
|
||||
{ name: imageScaledLarge, size: '1024w' },
|
||||
{ name: imageScaledXLarge, size: '2400w' },
|
||||
]}
|
||||
variants={['scaled-small', 'scaled-medium', 'scaled-large', 'scaled-xlarge']}
|
||||
sizes="(max-width: 767px) 100vw, 80vw"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ const priceData = (price, intl) => {
|
|||
};
|
||||
|
||||
export const ListingCardComponent = props => {
|
||||
const { className, rootClassName, intl, listing, setActiveListing } = props;
|
||||
const { className, rootClassName, intl, listing, renderSizes, setActiveListing } = props;
|
||||
const classes = classNames(rootClassName || css.root, className);
|
||||
const currentListing = ensureListing(listing);
|
||||
const id = currentListing.id.uuid;
|
||||
|
|
@ -59,10 +59,8 @@ export const ListingCardComponent = props => {
|
|||
rootClassName={css.rootForImage}
|
||||
alt={title}
|
||||
image={firstImage}
|
||||
nameSet={[
|
||||
{ name: 'landscape-crop', size: '1x' },
|
||||
{ name: 'landscape-crop2x', size: '2x' },
|
||||
]}
|
||||
variants={['landscape-crop', 'landscape-crop2x']}
|
||||
sizes={renderSizes}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -98,6 +96,7 @@ export const ListingCardComponent = props => {
|
|||
ListingCardComponent.defaultProps = {
|
||||
className: null,
|
||||
rootClassName: null,
|
||||
renderSizes: null,
|
||||
setActiveListing: () => null,
|
||||
};
|
||||
|
||||
|
|
@ -106,6 +105,10 @@ ListingCardComponent.propTypes = {
|
|||
rootClassName: string,
|
||||
intl: intlShape.isRequired,
|
||||
listing: propTypes.listing.isRequired,
|
||||
|
||||
// Responsive image sizes hint
|
||||
renderSizes: string,
|
||||
|
||||
setActiveListing: func,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -20,21 +20,15 @@ exports[`ListingCard matches snapshot 1`] = `
|
|||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "1x",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "2x",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes={null}
|
||||
variants={
|
||||
Array [
|
||||
"landscape-crop",
|
||||
"landscape-crop2x",
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ export const ManageListingCardComponent = props => {
|
|||
onCloseListing,
|
||||
onOpenListing,
|
||||
onToggleMenu,
|
||||
renderSizes,
|
||||
} = props;
|
||||
const classes = classNames(rootClassName || css.root, className);
|
||||
const currentListing = ensureOwnListing(listing);
|
||||
|
|
@ -237,10 +238,8 @@ export const ManageListingCardComponent = props => {
|
|||
rootClassName={css.rootForImage}
|
||||
alt={title}
|
||||
image={firstImage}
|
||||
nameSet={[
|
||||
{ name: 'landscape-crop', size: '1x' },
|
||||
{ name: 'landscape-crop2x', size: '2x' },
|
||||
]}
|
||||
variants={['landscape-crop', 'landscape-crop2x']}
|
||||
sizes={renderSizes}
|
||||
/>
|
||||
</div>
|
||||
<div className={classNames(css.menuOverlayWrapper, { [css.menuOverlayOpen]: isMenuOpen })}>
|
||||
|
|
@ -323,6 +322,7 @@ ManageListingCardComponent.defaultProps = {
|
|||
className: null,
|
||||
rootClassName: null,
|
||||
actionsInProgressListingId: null,
|
||||
renderSizes: null,
|
||||
};
|
||||
|
||||
const { bool, func, shape, string } = PropTypes;
|
||||
|
|
@ -340,6 +340,9 @@ ManageListingCardComponent.propTypes = {
|
|||
onOpenListing: func.isRequired,
|
||||
onToggleMenu: func.isRequired,
|
||||
|
||||
// Responsive image sizes hint
|
||||
renderSizes: string,
|
||||
|
||||
// from withRouter
|
||||
history: shape({
|
||||
push: func.isRequired,
|
||||
|
|
|
|||
|
|
@ -12,21 +12,15 @@ exports[`ManageListingCard matches snapshot 1`] = `
|
|||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "1x",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "2x",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes={null}
|
||||
variants={
|
||||
Array [
|
||||
"landscape-crop",
|
||||
"landscape-crop2x",
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -33,32 +33,23 @@ export const Image2X = {
|
|||
id: new UUID('empty'),
|
||||
type: 'image',
|
||||
attributes: {
|
||||
sizes: [
|
||||
{
|
||||
variants: {
|
||||
crop: {
|
||||
name: 'crop',
|
||||
width: 200,
|
||||
height: 133,
|
||||
url: 'https://via.placeholder.com/200x133',
|
||||
},
|
||||
{
|
||||
crop2x: {
|
||||
name: 'crop2x',
|
||||
width: 400,
|
||||
height: 266,
|
||||
url: 'https://via.placeholder.com/400x266',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
nameSet: [
|
||||
{
|
||||
name: 'crop',
|
||||
size: '1x',
|
||||
},
|
||||
{
|
||||
name: 'crop2x',
|
||||
size: '2x',
|
||||
},
|
||||
],
|
||||
variants: ['crop', 'crop2x'],
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -71,32 +62,23 @@ export const Image2XAspect = {
|
|||
id: new UUID('empty'),
|
||||
type: 'image',
|
||||
attributes: {
|
||||
sizes: [
|
||||
{
|
||||
variants: {
|
||||
crop: {
|
||||
name: 'crop',
|
||||
width: 200,
|
||||
height: 133,
|
||||
url: 'https://via.placeholder.com/200x133',
|
||||
},
|
||||
{
|
||||
crop2x: {
|
||||
name: 'crop2x',
|
||||
width: 400,
|
||||
height: 266,
|
||||
url: 'https://via.placeholder.com/400x266',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
nameSet: [
|
||||
{
|
||||
name: 'crop',
|
||||
size: '1x',
|
||||
},
|
||||
{
|
||||
name: 'crop2x',
|
||||
size: '2x',
|
||||
},
|
||||
],
|
||||
variants: ['crop', 'crop2x'],
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -109,32 +91,23 @@ export const Image2XWrongAspect = {
|
|||
id: new UUID('empty'),
|
||||
type: 'image',
|
||||
attributes: {
|
||||
sizes: [
|
||||
{
|
||||
variants: {
|
||||
crop: {
|
||||
name: 'crop',
|
||||
width: 200,
|
||||
height: 133,
|
||||
url: 'https://via.placeholder.com/200x200',
|
||||
url: 'https://via.placeholder.com/200x133',
|
||||
},
|
||||
{
|
||||
crop2x: {
|
||||
name: 'crop2x',
|
||||
width: 400,
|
||||
height: 266,
|
||||
url: 'https://via.placeholder.com/400x400',
|
||||
url: 'https://via.placeholder.com/400x266',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
nameSet: [
|
||||
{
|
||||
name: 'crop',
|
||||
size: '1x',
|
||||
},
|
||||
{
|
||||
name: 'crop2x',
|
||||
size: '2x',
|
||||
},
|
||||
],
|
||||
variants: ['crop', 'crop2x'],
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -146,32 +119,23 @@ export const Image2XWrongAspectNoWrapper = {
|
|||
id: new UUID('empty'),
|
||||
type: 'image',
|
||||
attributes: {
|
||||
sizes: [
|
||||
{
|
||||
variants: {
|
||||
crop: {
|
||||
name: 'crop',
|
||||
width: 200,
|
||||
height: 133,
|
||||
url: 'https://via.placeholder.com/200x200',
|
||||
url: 'https://via.placeholder.com/200x133',
|
||||
},
|
||||
{
|
||||
crop2x: {
|
||||
name: 'crop2x',
|
||||
width: 400,
|
||||
height: 266,
|
||||
url: 'https://via.placeholder.com/400x400',
|
||||
url: 'https://via.placeholder.com/400x266',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
nameSet: [
|
||||
{
|
||||
name: 'crop',
|
||||
size: '1x',
|
||||
},
|
||||
{
|
||||
name: 'crop2x',
|
||||
size: '2x',
|
||||
},
|
||||
],
|
||||
variants: ['crop', 'crop2x'],
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -181,6 +145,7 @@ export const ImageEmpty = {
|
|||
props: {
|
||||
alt: 'img',
|
||||
image: null,
|
||||
variants: ['crop', 'crop2x'],
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -190,6 +155,7 @@ export const ImageEmptyWithAspect = {
|
|||
props: {
|
||||
alt: 'img',
|
||||
image: null,
|
||||
variants: ['crop', 'crop2x'],
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -210,32 +176,23 @@ export const ImageWithSizes = {
|
|||
id: new UUID('empty'),
|
||||
type: 'image',
|
||||
attributes: {
|
||||
sizes: [
|
||||
{
|
||||
variants: {
|
||||
crop: {
|
||||
name: 'crop',
|
||||
width: 200,
|
||||
height: 133,
|
||||
url: 'https://via.placeholder.com/200x133',
|
||||
},
|
||||
{
|
||||
crop2x: {
|
||||
name: 'crop2x',
|
||||
width: 400,
|
||||
height: 266,
|
||||
url: 'https://via.placeholder.com/400x266',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
nameSet: [
|
||||
{
|
||||
name: 'crop',
|
||||
size: '200w',
|
||||
},
|
||||
{
|
||||
name: 'crop2x',
|
||||
size: '400w',
|
||||
},
|
||||
],
|
||||
variants: ['crop', 'crop2x'],
|
||||
sizes: '(max-width: 600px) 200px, 400px',
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,19 +3,19 @@
|
|||
* <ResponsiveImage
|
||||
* alt="ListingX"
|
||||
* image={imageDataFromSDK}
|
||||
* nameSet={[{ name: 'landscape-crop', size: '1x'}, { name: 'landscape-crop2x', size: '2x'}]}
|
||||
* variants={['landscape-crop', 'landscape-crop2x']}
|
||||
* />
|
||||
* // produces:
|
||||
* <img
|
||||
* alt="ListingX"
|
||||
* src="url/to/landscape-crop.jpg"
|
||||
* srcSet="url/to/landscape-crop.jpg 1x, url/to/landscape-crop2x.jpg 2x" />
|
||||
* srcSet="url/to/landscape-crop.jpg 400w, url/to/landscape-crop2x.jpg 800w" />
|
||||
*
|
||||
* Usage with sizes:
|
||||
* <ResponsiveImage
|
||||
* alt="ListingX"
|
||||
* image={imageDataFromSDK}
|
||||
* nameSet={[{ name: 'landscape-crop', size: '400w'}, { name: 'landscape-crop2x', size: '800w'}]}
|
||||
* variants={['landscape-crop', 'landscape-crop2x']}
|
||||
* sizes="(max-width: 600px) 100vw, 50vw"
|
||||
* />
|
||||
* // produces:
|
||||
|
|
@ -28,10 +28,13 @@
|
|||
* // This means that below 600px image will take as many pixels there are available on current
|
||||
* // viewport width (100vw) - and above that image will only take 50% of the page width.
|
||||
* // Browser decides which image it will fetch based on current screen size.
|
||||
*
|
||||
* NOTE: for all the possible image variant names and their respective
|
||||
* sizes, see the API documentation.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { arrayOf, string } from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { propTypes } from '../../util/types';
|
||||
|
|
@ -40,10 +43,10 @@ import NoImageIcon from './NoImageIcon';
|
|||
import css from './ResponsiveImage.css';
|
||||
|
||||
const ResponsiveImage = props => {
|
||||
const { className, rootClassName, alt, noImageMessage, image, nameSet, sizes, ...rest } = props;
|
||||
const { className, rootClassName, alt, noImageMessage, image, variants, ...rest } = props;
|
||||
const classes = classNames(rootClassName || css.root, className);
|
||||
|
||||
if (image == null || nameSet.length === 0) {
|
||||
if (image == null || variants.length === 0) {
|
||||
const noImageClasses = classNames(rootClassName || css.root, css.noImageContainer, className);
|
||||
|
||||
// NoImageMessage is needed for listing images on top the map (those component lose context)
|
||||
|
|
@ -61,43 +64,37 @@ const ResponsiveImage = props => {
|
|||
/* eslint-enable jsx-a11y/img-redundant-alt */
|
||||
}
|
||||
|
||||
const imageSizes = image.attributes.sizes;
|
||||
const imageVariants = image.attributes.variants;
|
||||
|
||||
const srcSet = nameSet
|
||||
.map(v => {
|
||||
const variant = imageVariants ? imageVariants[v.name] : null;
|
||||
const srcSet = variants
|
||||
.map(variantName => {
|
||||
const variant = imageVariants[variantName];
|
||||
|
||||
// deprecated
|
||||
// for backwards compatibility only
|
||||
const size = imageSizes ? imageSizes.find(i => i.name === v.name) : null;
|
||||
|
||||
if (variant || size) {
|
||||
const url = (variant || size).url;
|
||||
return `${url} ${v.size}`;
|
||||
} else {
|
||||
// Handle case where the requested variant doesn't exist, for
|
||||
// example because it hasn't been loaded yet.
|
||||
// Return null, which will be filtered out.
|
||||
if (!variant) {
|
||||
// Variant not available (most like just not loaded yet)
|
||||
return null;
|
||||
}
|
||||
return `${variant.url} ${variant.width}w`;
|
||||
})
|
||||
.filter(v => v != null)
|
||||
.join(', ');
|
||||
|
||||
const sizesProp = sizes ? { sizes } : {};
|
||||
const imgProps = {
|
||||
className: classes,
|
||||
alt,
|
||||
srcSet,
|
||||
...rest,
|
||||
};
|
||||
|
||||
return <img alt={alt} className={classes} srcSet={srcSet} {...rest} {...sizesProp} />;
|
||||
// alt prop already defined above
|
||||
// eslint-disable-next-line jsx-a11y/alt-text
|
||||
return <img {...imgProps} />;
|
||||
};
|
||||
|
||||
const { arrayOf, shape, string } = PropTypes;
|
||||
|
||||
ResponsiveImage.defaultProps = {
|
||||
className: null,
|
||||
rootClassName: null,
|
||||
image: null,
|
||||
nameSet: [],
|
||||
sizes: null,
|
||||
noImageMessage: null,
|
||||
};
|
||||
|
||||
|
|
@ -106,13 +103,7 @@ ResponsiveImage.propTypes = {
|
|||
rootClassName: string,
|
||||
alt: string.isRequired,
|
||||
image: propTypes.image,
|
||||
nameSet: arrayOf(
|
||||
shape({
|
||||
name: string.isRequired,
|
||||
size: string.isRequired,
|
||||
})
|
||||
),
|
||||
sizes: string,
|
||||
variants: arrayOf(string).isRequired,
|
||||
noImageMessage: string,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -85,10 +85,8 @@ const ListingCard = props => {
|
|||
alt={title}
|
||||
noImageMessage={intl.formatMessage({ id: 'SearchMapInfoCard.noImage' })}
|
||||
image={firstImage}
|
||||
nameSet={[
|
||||
{ name: 'landscape-crop', size: '1x' },
|
||||
{ name: 'landscape-crop2x', size: '2x' },
|
||||
]}
|
||||
variants={['landscape-crop', 'landscape-crop2x']}
|
||||
sizes="250px"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -19,6 +19,16 @@ const SearchResultsPanel = props => {
|
|||
/>
|
||||
) : null;
|
||||
|
||||
// Panel width relative to the viewport
|
||||
const panelMediumWidth = 50;
|
||||
const panelLargeWidth = 62.5;
|
||||
const cardRenderSizes = [
|
||||
'(max-width: 767px) 100vw',
|
||||
`(max-width: 1023px) ${panelMediumWidth}vw`,
|
||||
`(max-width: 1920px) ${panelLargeWidth / 2}vw`,
|
||||
`${panelLargeWidth / 3}vw`,
|
||||
].join(', ');
|
||||
|
||||
return (
|
||||
<div className={classes}>
|
||||
<div className={css.listingCards}>
|
||||
|
|
@ -27,6 +37,7 @@ const SearchResultsPanel = props => {
|
|||
className={css.listingCard}
|
||||
key={l.id.uuid}
|
||||
listing={l}
|
||||
renderSizes={cardRenderSizes}
|
||||
setActiveListing={setActiveListing}
|
||||
/>
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -220,11 +220,7 @@ export class TransactionPanelComponent extends Component {
|
|||
rootClassName={css.rootForImage}
|
||||
alt={listingTitle}
|
||||
image={firstImage}
|
||||
nameSet={[
|
||||
{ name: 'landscape-crop', size: '400w' },
|
||||
{ name: 'landscape-crop2x', size: '800w' },
|
||||
]}
|
||||
sizes="100vw"
|
||||
variants={['landscape-crop', 'landscape-crop2x']}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -301,11 +297,7 @@ export class TransactionPanelComponent extends Component {
|
|||
rootClassName={css.rootForImage}
|
||||
alt={listingTitle}
|
||||
image={firstImage}
|
||||
nameSet={[
|
||||
{ name: 'landscape-crop', size: '400w' },
|
||||
{ name: 'landscape-crop2x', size: '800w' },
|
||||
]}
|
||||
sizes="100%"
|
||||
variants={['landscape-crop', 'landscape-crop2x']}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -12,21 +12,14 @@ exports[`TransactionPanel - Order accepted matches snapshot 1`] = `
|
|||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100vw"
|
||||
variants={
|
||||
Array [
|
||||
"landscape-crop",
|
||||
"landscape-crop2x",
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -845,21 +838,14 @@ exports[`TransactionPanel - Order accepted matches snapshot 1`] = `
|
|||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100%"
|
||||
variants={
|
||||
Array [
|
||||
"landscape-crop",
|
||||
"landscape-crop2x",
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1172,21 +1158,14 @@ exports[`TransactionPanel - Order autodeclined matches snapshot 1`] = `
|
|||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100vw"
|
||||
variants={
|
||||
Array [
|
||||
"landscape-crop",
|
||||
"landscape-crop2x",
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -2005,21 +1984,14 @@ exports[`TransactionPanel - Order autodeclined matches snapshot 1`] = `
|
|||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100%"
|
||||
variants={
|
||||
Array [
|
||||
"landscape-crop",
|
||||
"landscape-crop2x",
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -2332,21 +2304,14 @@ exports[`TransactionPanel - Order canceled matches snapshot 1`] = `
|
|||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100vw"
|
||||
variants={
|
||||
Array [
|
||||
"landscape-crop",
|
||||
"landscape-crop2x",
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -3165,21 +3130,14 @@ exports[`TransactionPanel - Order canceled matches snapshot 1`] = `
|
|||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100%"
|
||||
variants={
|
||||
Array [
|
||||
"landscape-crop",
|
||||
"landscape-crop2x",
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -3492,21 +3450,14 @@ exports[`TransactionPanel - Order declined matches snapshot 1`] = `
|
|||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100vw"
|
||||
variants={
|
||||
Array [
|
||||
"landscape-crop",
|
||||
"landscape-crop2x",
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -4325,21 +4276,14 @@ exports[`TransactionPanel - Order declined matches snapshot 1`] = `
|
|||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100%"
|
||||
variants={
|
||||
Array [
|
||||
"landscape-crop",
|
||||
"landscape-crop2x",
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -4652,21 +4596,14 @@ exports[`TransactionPanel - Order delivered matches snapshot 1`] = `
|
|||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100vw"
|
||||
variants={
|
||||
Array [
|
||||
"landscape-crop",
|
||||
"landscape-crop2x",
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -5485,21 +5422,14 @@ exports[`TransactionPanel - Order delivered matches snapshot 1`] = `
|
|||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100%"
|
||||
variants={
|
||||
Array [
|
||||
"landscape-crop",
|
||||
"landscape-crop2x",
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -5812,21 +5742,14 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = `
|
|||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100vw"
|
||||
variants={
|
||||
Array [
|
||||
"landscape-crop",
|
||||
"landscape-crop2x",
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -6645,21 +6568,14 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = `
|
|||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100%"
|
||||
variants={
|
||||
Array [
|
||||
"landscape-crop",
|
||||
"landscape-crop2x",
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -6972,21 +6888,14 @@ exports[`TransactionPanel - Order preauthorized matches snapshot 1`] = `
|
|||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100vw"
|
||||
variants={
|
||||
Array [
|
||||
"landscape-crop",
|
||||
"landscape-crop2x",
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -7805,21 +7714,14 @@ exports[`TransactionPanel - Order preauthorized matches snapshot 1`] = `
|
|||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100%"
|
||||
variants={
|
||||
Array [
|
||||
"landscape-crop",
|
||||
"landscape-crop2x",
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -8132,21 +8034,14 @@ exports[`TransactionPanel - Sale accepted matches snapshot 1`] = `
|
|||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100vw"
|
||||
variants={
|
||||
Array [
|
||||
"landscape-crop",
|
||||
"landscape-crop2x",
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -8898,21 +8793,14 @@ exports[`TransactionPanel - Sale accepted matches snapshot 1`] = `
|
|||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100%"
|
||||
variants={
|
||||
Array [
|
||||
"landscape-crop",
|
||||
"landscape-crop2x",
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -9200,21 +9088,14 @@ exports[`TransactionPanel - Sale autodeclined matches snapshot 1`] = `
|
|||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100vw"
|
||||
variants={
|
||||
Array [
|
||||
"landscape-crop",
|
||||
"landscape-crop2x",
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -9966,21 +9847,14 @@ exports[`TransactionPanel - Sale autodeclined matches snapshot 1`] = `
|
|||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100%"
|
||||
variants={
|
||||
Array [
|
||||
"landscape-crop",
|
||||
"landscape-crop2x",
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -10268,21 +10142,14 @@ exports[`TransactionPanel - Sale canceled matches snapshot 1`] = `
|
|||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100vw"
|
||||
variants={
|
||||
Array [
|
||||
"landscape-crop",
|
||||
"landscape-crop2x",
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -11034,21 +10901,14 @@ exports[`TransactionPanel - Sale canceled matches snapshot 1`] = `
|
|||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100%"
|
||||
variants={
|
||||
Array [
|
||||
"landscape-crop",
|
||||
"landscape-crop2x",
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -11336,21 +11196,14 @@ exports[`TransactionPanel - Sale declined matches snapshot 1`] = `
|
|||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100vw"
|
||||
variants={
|
||||
Array [
|
||||
"landscape-crop",
|
||||
"landscape-crop2x",
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -12102,21 +11955,14 @@ exports[`TransactionPanel - Sale declined matches snapshot 1`] = `
|
|||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100%"
|
||||
variants={
|
||||
Array [
|
||||
"landscape-crop",
|
||||
"landscape-crop2x",
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -12404,21 +12250,14 @@ exports[`TransactionPanel - Sale delivered matches snapshot 1`] = `
|
|||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100vw"
|
||||
variants={
|
||||
Array [
|
||||
"landscape-crop",
|
||||
"landscape-crop2x",
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -13170,21 +13009,14 @@ exports[`TransactionPanel - Sale delivered matches snapshot 1`] = `
|
|||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100%"
|
||||
variants={
|
||||
Array [
|
||||
"landscape-crop",
|
||||
"landscape-crop2x",
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -13472,21 +13304,14 @@ exports[`TransactionPanel - Sale enquired matches snapshot 1`] = `
|
|||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100vw"
|
||||
variants={
|
||||
Array [
|
||||
"landscape-crop",
|
||||
"landscape-crop2x",
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -14238,21 +14063,14 @@ exports[`TransactionPanel - Sale enquired matches snapshot 1`] = `
|
|||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100%"
|
||||
variants={
|
||||
Array [
|
||||
"landscape-crop",
|
||||
"landscape-crop2x",
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -14540,21 +14358,14 @@ exports[`TransactionPanel - Sale preauthorized matches snapshot 1`] = `
|
|||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100vw"
|
||||
variants={
|
||||
Array [
|
||||
"landscape-crop",
|
||||
"landscape-crop2x",
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -15306,21 +15117,14 @@ exports[`TransactionPanel - Sale preauthorized matches snapshot 1`] = `
|
|||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100%"
|
||||
variants={
|
||||
Array [
|
||||
"landscape-crop",
|
||||
"landscape-crop2x",
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -50,20 +50,20 @@ export const WithProfileImageAndBio = {
|
|||
id: new UUID('profile-image'),
|
||||
type: 'image',
|
||||
attributes: {
|
||||
sizes: [
|
||||
{
|
||||
name: 'square-xlarge2x',
|
||||
variants: {
|
||||
'square-small': {
|
||||
name: 'square-small',
|
||||
width: 240,
|
||||
height: 240,
|
||||
url: 'https://lorempixel.com/240/240/people/',
|
||||
},
|
||||
{
|
||||
name: 'square-xlarge4x',
|
||||
'square-small2x': {
|
||||
name: 'square-small2x',
|
||||
width: 480,
|
||||
height: 480,
|
||||
url: 'https://lorempixel.com/480/480/people/',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -340,11 +340,7 @@ export class CheckoutPageComponent extends Component {
|
|||
rootClassName={css.rootForImage}
|
||||
alt={listingTitle}
|
||||
image={firstImage}
|
||||
nameSet={[
|
||||
{ name: 'landscape-crop', size: '400w' },
|
||||
{ name: 'landscape-crop2x', size: '800w' },
|
||||
]}
|
||||
sizes="100vw"
|
||||
variants={['landscape-crop', 'landscape-crop2x']}
|
||||
/>
|
||||
</div>
|
||||
<div className={classNames(css.avatarWrapper, css.avatarMobile)}>
|
||||
|
|
@ -394,11 +390,7 @@ export class CheckoutPageComponent extends Component {
|
|||
rootClassName={css.rootForImage}
|
||||
alt={listingTitle}
|
||||
image={firstImage}
|
||||
nameSet={[
|
||||
{ name: 'landscape-crop', size: '400w' },
|
||||
{ name: 'landscape-crop2x', size: '800w' },
|
||||
]}
|
||||
sizes="100%"
|
||||
variants={['landscape-crop', 'landscape-crop2x']}
|
||||
/>
|
||||
</div>
|
||||
<div className={css.avatarWrapper}>
|
||||
|
|
|
|||
|
|
@ -28,21 +28,14 @@ exports[`CheckoutPage matches snapshot 1`] = `
|
|||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100vw"
|
||||
variants={
|
||||
Array [
|
||||
"landscape-crop",
|
||||
"landscape-crop2x",
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
|
|
@ -109,21 +102,14 @@ exports[`CheckoutPage matches snapshot 1`] = `
|
|||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100%"
|
||||
variants={
|
||||
Array [
|
||||
"landscape-crop",
|
||||
"landscape-crop2x",
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
|
|
|
|||
|
|
@ -275,7 +275,13 @@ export function requestCreateListing(data) {
|
|||
// Modify store to understand that we have created listing and can redirect away
|
||||
dispatch(createListingSuccess(response));
|
||||
// Fetch listing data so that redirection is smooth
|
||||
dispatch(requestShowListing({ id, include: ['author', 'images'] }));
|
||||
dispatch(
|
||||
requestShowListing({
|
||||
id,
|
||||
include: ['author', 'images'],
|
||||
'fields.image': ['variants.landscape-crop', 'variants.landscape-crop2x'],
|
||||
})
|
||||
);
|
||||
return response;
|
||||
})
|
||||
.then(response => {
|
||||
|
|
@ -316,7 +322,11 @@ export function requestUpdateListing(tab, data) {
|
|||
.update(data)
|
||||
.then(response => {
|
||||
updateResponse = response;
|
||||
const payload = { id, include: ['author', 'images'] };
|
||||
const payload = {
|
||||
id,
|
||||
include: ['author', 'images'],
|
||||
'fields.image': ['variants.landscape-crop', 'variants.landscape-crop2x'],
|
||||
};
|
||||
return dispatch(requestShowListing(payload));
|
||||
})
|
||||
.then(() => {
|
||||
|
|
@ -343,6 +353,7 @@ export function loadData(params) {
|
|||
const payload = {
|
||||
id: new UUID(id),
|
||||
include: ['author', 'images'],
|
||||
'fields.image': ['variants.landscape-crop', 'variants.landscape-crop2x'],
|
||||
};
|
||||
return dispatch(requestShowListing(payload));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ export const loadData = (params, search) => (dispatch, getState, sdk) => {
|
|||
const apiQueryParams = {
|
||||
only: onlyFilter,
|
||||
include: ['provider', 'provider.profileImage', 'customer', 'customer.profileImage', 'booking'],
|
||||
'fields.image': ['variants.square-small', 'variants.square-small2x'],
|
||||
page,
|
||||
per_page: INBOX_PAGE_SIZE,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -124,8 +124,8 @@ export const showListing = (listingId, isOwn = false) => (dispatch, getState, sd
|
|||
'variants.scaled-xlarge',
|
||||
|
||||
// Avatars
|
||||
'variants.square-xlarge2x',
|
||||
'variants.square-xlarge4x',
|
||||
'variants.square-small',
|
||||
'variants.square-small2x',
|
||||
],
|
||||
};
|
||||
|
||||
|
|
@ -143,7 +143,12 @@ export const showListing = (listingId, isOwn = false) => (dispatch, getState, sd
|
|||
|
||||
export const fetchReviews = listingId => (dispatch, getState, sdk) => {
|
||||
return sdk.reviews
|
||||
.query({ listing_id: listingId, state: 'public', include: ['author', 'author.profileImage'] })
|
||||
.query({
|
||||
listing_id: listingId,
|
||||
state: 'public',
|
||||
include: ['author', 'author.profileImage'],
|
||||
'fields.image': ['variants.square-small', 'variants.square-small2x'],
|
||||
})
|
||||
.then(response => {
|
||||
const reviews = denormalisedResponseEntities(response);
|
||||
dispatch(fetchReviewsSuccess(reviews));
|
||||
|
|
|
|||
|
|
@ -116,8 +116,8 @@ describe('ListingPage', () => {
|
|||
'variants.scaled-xlarge',
|
||||
|
||||
// Avatars
|
||||
'variants.square-xlarge2x',
|
||||
'variants.square-xlarge4x',
|
||||
'variants.square-small',
|
||||
'variants.square-small2x',
|
||||
],
|
||||
},
|
||||
],
|
||||
|
|
@ -163,8 +163,8 @@ describe('ListingPage', () => {
|
|||
'variants.scaled-xlarge',
|
||||
|
||||
// Avatars
|
||||
'variants.square-xlarge2x',
|
||||
'variants.square-xlarge4x',
|
||||
'variants.square-small',
|
||||
'variants.square-small2x',
|
||||
],
|
||||
},
|
||||
],
|
||||
|
|
|
|||
|
|
@ -46,13 +46,12 @@ const SectionImages = props => {
|
|||
rootClassName={css.rootForImage}
|
||||
alt={title}
|
||||
image={firstImage}
|
||||
nameSet={[
|
||||
{ name: 'landscape-crop', size: '400w' },
|
||||
{ name: 'landscape-crop2x', size: '800w' },
|
||||
{ name: 'landscape-crop4x', size: '1600w' },
|
||||
{ name: 'landscape-crop6x', size: '2400w' },
|
||||
variants={[
|
||||
'landscape-crop',
|
||||
'landscape-crop2x',
|
||||
'landscape-crop4x',
|
||||
'landscape-crop6x',
|
||||
]}
|
||||
sizes="100vw"
|
||||
/>
|
||||
{viewPhotosButton}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -216,10 +216,11 @@ export const queryListingsError = e => ({
|
|||
export const queryOwnListings = queryParams => (dispatch, getState, sdk) => {
|
||||
dispatch(queryListingsRequest(queryParams));
|
||||
|
||||
const { include = [], page, perPage } = queryParams;
|
||||
const { perPage, ...rest } = queryParams;
|
||||
const params = { ...rest, per_page: perPage };
|
||||
|
||||
return sdk.ownListings
|
||||
.query({ include, page, per_page: perPage })
|
||||
.query(params)
|
||||
.then(response => {
|
||||
dispatch(addOwnEntities(response));
|
||||
dispatch(queryListingsSuccess(response));
|
||||
|
|
|
|||
|
|
@ -112,6 +112,14 @@ export class ManageListingsPageComponent extends Component {
|
|||
|
||||
const title = intl.formatMessage({ id: 'ManageListingsPage.title' });
|
||||
|
||||
const panelWidth = 62.5;
|
||||
// Render hints for responsive image
|
||||
const renderSizes = [
|
||||
`(max-width: 767px) 100vw`,
|
||||
`(max-width: 1920px) ${panelWidth / 2}vw`,
|
||||
`${panelWidth / 3}vw`,
|
||||
].join(', ');
|
||||
|
||||
return (
|
||||
<Page title={title} scrollingDisabled={scrollingDisabled}>
|
||||
<LayoutSingleColumn>
|
||||
|
|
@ -137,6 +145,7 @@ export class ManageListingsPageComponent extends Component {
|
|||
onOpenListing={onOpenListing}
|
||||
hasOpeningError={openingErrorListingId.uuid === l.id.uuid}
|
||||
hasClosingError={closingErrorListingId.uuid === l.id.uuid}
|
||||
renderSizes={renderSizes}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
|
@ -234,6 +243,8 @@ ManageListingsPage.loadData = (params, search) => {
|
|||
page,
|
||||
perPage: RESULT_PAGE_SIZE,
|
||||
include: ['images'],
|
||||
'fields.image': ['variants.landscape-crop', 'variants.landscape-crop2x'],
|
||||
'limit.images': 1,
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -124,7 +124,11 @@ export const queryReviewsError = e => ({
|
|||
export const queryUserListings = userId => (dispatch, getState, sdk) => {
|
||||
dispatch(queryListingsRequest(userId));
|
||||
return sdk.listings
|
||||
.query({ author_id: userId, include: ['author', 'images'] })
|
||||
.query({
|
||||
author_id: userId,
|
||||
include: ['author', 'images'],
|
||||
'fields.image': ['variants.landscape-crop', 'variants.landscape-crop2x'],
|
||||
})
|
||||
.then(response => {
|
||||
// Pick only the id and type properties from the response listings
|
||||
const listingRefs = response.data.data.map(({ id, type }) => ({ id, type }));
|
||||
|
|
@ -137,7 +141,12 @@ export const queryUserListings = userId => (dispatch, getState, sdk) => {
|
|||
|
||||
export const queryUserReviews = userId => (dispatch, getState, sdk) => {
|
||||
sdk.reviews
|
||||
.query({ subject_id: userId, state: 'public', include: ['author', 'author.profileImage'] })
|
||||
.query({
|
||||
subject_id: userId,
|
||||
state: 'public',
|
||||
include: ['author', 'author.profileImage'],
|
||||
'fields.image': ['variants.square-small', 'variants.square-small2x'],
|
||||
})
|
||||
.then(response => {
|
||||
const reviews = denormalisedResponseEntities(response);
|
||||
dispatch(queryReviewsSuccess(reviews));
|
||||
|
|
@ -148,7 +157,11 @@ export const queryUserReviews = userId => (dispatch, getState, sdk) => {
|
|||
export const showUser = userId => (dispatch, getState, sdk) => {
|
||||
dispatch(showUserRequest(userId));
|
||||
return sdk.users
|
||||
.show({ id: userId, include: ['profileImage'] })
|
||||
.show({
|
||||
id: userId,
|
||||
include: ['profileImage'],
|
||||
'fields.image': ['variants.square-small', 'variants.square-small2x'],
|
||||
})
|
||||
.then(response => {
|
||||
dispatch(addMarketplaceEntities(response));
|
||||
dispatch(showUserSuccess());
|
||||
|
|
|
|||
|
|
@ -191,7 +191,12 @@ class ProfileSettingsFormComponent extends Component {
|
|||
});
|
||||
const avatarComponent =
|
||||
!fileUploadInProgress && profileImage.imageId ? (
|
||||
<Avatar className={avatarClasses} user={transientUser} disableProfileLink />
|
||||
<Avatar
|
||||
className={avatarClasses}
|
||||
renderSizes="(max-width: 767px) 96px, 240px"
|
||||
user={transientUser}
|
||||
disableProfileLink
|
||||
/>
|
||||
) : null;
|
||||
|
||||
const chooseAvatarLabel =
|
||||
|
|
|
|||
|
|
@ -115,8 +115,16 @@ export function uploadImage(actionPayload) {
|
|||
const id = actionPayload.id;
|
||||
dispatch(uploadImageRequest(actionPayload));
|
||||
|
||||
const bodyParams = {
|
||||
image: actionPayload.file,
|
||||
};
|
||||
const queryParams = {
|
||||
expand: true,
|
||||
'fields.image': ['variants.square-small', 'variants.square-small2x'],
|
||||
};
|
||||
|
||||
return sdk.images
|
||||
.uploadProfileImage({ image: actionPayload.file }, { expand: true })
|
||||
.uploadProfileImage(bodyParams, queryParams)
|
||||
.then(resp => {
|
||||
const uploadedImage = resp.data.data;
|
||||
dispatch(uploadImageSuccess({ data: { id, uploadedImage } }));
|
||||
|
|
@ -129,8 +137,14 @@ export const updateProfile = actionPayload => {
|
|||
return (dispatch, getState, sdk) => {
|
||||
dispatch(updateProfileRequest());
|
||||
|
||||
const queryParams = {
|
||||
expand: true,
|
||||
include: ['profileImage'],
|
||||
'fields.image': ['variants.square-small', 'variants.square-small2x'],
|
||||
};
|
||||
|
||||
return sdk.currentUser
|
||||
.updateProfile(actionPayload, { expand: true, include: ['profileImage'] })
|
||||
.updateProfile(actionPayload, queryParams)
|
||||
.then(response => {
|
||||
dispatch(updateProfileSuccess(response));
|
||||
|
||||
|
|
|
|||
|
|
@ -218,6 +218,7 @@ export const fetchTransaction = id => (dispatch, getState, sdk) => {
|
|||
'reviews.author',
|
||||
'reviews.subject',
|
||||
],
|
||||
...IMAGE_VARIANTS,
|
||||
},
|
||||
{ expand: true }
|
||||
)
|
||||
|
|
@ -235,6 +236,7 @@ export const fetchTransaction = id => (dispatch, getState, sdk) => {
|
|||
return sdk.listings.show({
|
||||
id: listingId,
|
||||
include: ['author', 'author.profileImage', 'images'],
|
||||
...IMAGE_VARIANTS,
|
||||
});
|
||||
} else {
|
||||
return response;
|
||||
|
|
@ -305,7 +307,12 @@ const fetchMessages = (txId, page) => (dispatch, getState, sdk) => {
|
|||
dispatch(fetchMessagesRequest());
|
||||
|
||||
return sdk.messages
|
||||
.query({ transaction_id: txId, include: ['sender', 'sender.profileImage'], ...paging })
|
||||
.query({
|
||||
transaction_id: txId,
|
||||
include: ['sender', 'sender.profileImage'],
|
||||
...IMAGE_VARIANTS,
|
||||
...paging,
|
||||
})
|
||||
.then(response => {
|
||||
const messages = denormalisedResponseEntities(response);
|
||||
const { totalItems, totalPages, page: fetchedPage } = response.data.meta;
|
||||
|
|
@ -375,6 +382,17 @@ export const sendMessage = (txId, message) => (dispatch, getState, sdk) => {
|
|||
};
|
||||
|
||||
const REVIEW_TX_INCLUDES = ['reviews', 'reviews.author', 'reviews.subject'];
|
||||
const IMAGE_VARIANTS = {
|
||||
'fields.image': [
|
||||
// Profile images
|
||||
'variants.square-small',
|
||||
'variants.square-small2x',
|
||||
|
||||
// Listing images:
|
||||
'variants.landscape-crop',
|
||||
'variants.landscape-crop2x',
|
||||
],
|
||||
};
|
||||
|
||||
// If other party has already sent a review, we need to make transition to
|
||||
// TRANSITION_REVIEW_2_BY_<CUSTOMER/PROVIDER>
|
||||
|
|
@ -385,7 +403,7 @@ const sendReviewAsSecond = (id, params, role, dispatch, sdk) => {
|
|||
const include = REVIEW_TX_INCLUDES;
|
||||
|
||||
return sdk.transactions
|
||||
.transition({ id, transition, params }, { expand: true, include })
|
||||
.transition({ id, transition, params }, { expand: true, include, ...IMAGE_VARIANTS })
|
||||
.then(response => {
|
||||
dispatch(addMarketplaceEntities(response));
|
||||
dispatch(sendReviewSuccess());
|
||||
|
|
@ -411,7 +429,7 @@ const sendReviewAsFirst = (id, params, role, dispatch, sdk) => {
|
|||
const include = REVIEW_TX_INCLUDES;
|
||||
|
||||
return sdk.transactions
|
||||
.transition({ id, transition, params }, { expand: true, include })
|
||||
.transition({ id, transition, params }, { expand: true, include, ...IMAGE_VARIANTS })
|
||||
.then(response => {
|
||||
dispatch(addMarketplaceEntities(response));
|
||||
dispatch(sendReviewSuccess());
|
||||
|
|
|
|||
|
|
@ -332,8 +332,13 @@ export const fetchCurrentUser = () => (dispatch, getState, sdk) => {
|
|||
return Promise.resolve({});
|
||||
}
|
||||
|
||||
const params = {
|
||||
include: ['profileImage'],
|
||||
'fields.image': ['variants.square-small', 'variants.square-small2x'],
|
||||
};
|
||||
|
||||
return sdk.currentUser
|
||||
.show({ include: ['profileImage'] })
|
||||
.show(params)
|
||||
.then(response => {
|
||||
const entities = denormalisedResponseEntities(response);
|
||||
if (entities.length !== 1) {
|
||||
|
|
|
|||
|
|
@ -60,20 +60,21 @@ export const createImage = id => ({
|
|||
id: new UUID(id),
|
||||
type: 'image',
|
||||
attributes: {
|
||||
sizes: [
|
||||
{
|
||||
variants: {
|
||||
// TODO: add all possible variants here
|
||||
square: {
|
||||
name: 'square',
|
||||
height: 408,
|
||||
width: 408,
|
||||
url: 'https://via.placeholder.com/408x408',
|
||||
},
|
||||
{
|
||||
square2x: {
|
||||
name: 'square2x',
|
||||
height: 816,
|
||||
width: 816,
|
||||
url: 'https://via.placeholder.com/816x816',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -80,14 +80,6 @@ propTypes.image = shape({
|
|||
id: propTypes.uuid.isRequired,
|
||||
type: propTypes.value('image').isRequired,
|
||||
attributes: shape({
|
||||
sizes: arrayOf(
|
||||
shape({
|
||||
width: number.isRequired,
|
||||
height: number.isRequired,
|
||||
name: string.isRequired,
|
||||
url: string.isRequired,
|
||||
})
|
||||
),
|
||||
variants: objectOf(
|
||||
shape({
|
||||
width: number.isRequired,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue