Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tiled galleries: Consistent layouts #29559

Merged
merged 96 commits into from
Dec 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
96 commits
Select commit Hold shift + click to select a range
9deb375
Overhaul layout
sirreal Dec 18, 2018
d96bdae
Sort layout styles
sirreal Dec 18, 2018
79d1d0a
Add image dimensions
sirreal Dec 18, 2018
5f1655f
Square layouts with image w/h
sirreal Dec 18, 2018
cca129b
Save work
sirreal Dec 18, 2018
12576e8
Remove obsolete layouts
sirreal Dec 18, 2018
3225346
Add comment about rendering images
sirreal Dec 19, 2018
5061034
Use array paths for pick
sirreal Dec 19, 2018
d833055
Adding square duplication mosaic
sirreal Dec 19, 2018
49d94e3
Fix handlers
sirreal Dec 19, 2018
b85e4dc
Add ratio to images
sirreal Dec 19, 2018
df5f9ce
Revert ratio (calculate on the fly)
sirreal Dec 19, 2018
a42b55d
Mosaic work
sirreal Dec 19, 2018
f0cdcd3
Prep mosaic layout
sirreal Dec 19, 2018
1a444c4
Implement some mosaic shapes
sirreal Dec 19, 2018
eaef90c
More shapes
sirreal Dec 19, 2018
73c9d62
isWide
sirreal Dec 19, 2018
01125d9
Fix curried fns
sirreal Dec 19, 2018
cc891ab
Fix arrow func
sirreal Dec 19, 2018
b055ad1
Fix isNotRecentShape check
sirreal Dec 19, 2018
f76c9b5
Add margin between images in a column
sirreal Dec 20, 2018
adade54
Adding tests (broken)
sirreal Dec 20, 2018
20f3266
Organize mosaic
sirreal Dec 20, 2018
244904b
Add ratios snapshot test
sirreal Dec 20, 2018
c486395
Pull partial application to top level
sirreal Dec 20, 2018
4867f9e
Add docs
sirreal Dec 20, 2018
e4677ed
Pull out complex conditions
sirreal Dec 20, 2018
f137403
Save works 🎉
sirreal Dec 20, 2018
0ccfd7b
Remove placeholder from figcaption save
sirreal Dec 20, 2018
53b2526
Don't treat photonized URL as primary image URL
sirreal Dec 20, 2018
628fd3c
Ratio calculations
sirreal Dec 21, 2018
95baec9
Update mosaic tests
sirreal Dec 21, 2018
9cb4596
Remove JS from view.js
simison Dec 21, 2018
39d457c
Revert "Update mosaic tests"
sirreal Dec 21, 2018
7c98fa0
Revert "Ratio calculations"
sirreal Dec 21, 2018
307ebec
Remove crop feature
simison Dec 21, 2018
5bd414e
Fix upload button visuals
simison Dec 21, 2018
1b6f0f1
Rename upload class and add wrapper
simison Dec 21, 2018
628140b
Make upload button span across block width
simison Dec 21, 2018
0cdc65d
Fix image size async loading
sirreal Dec 21, 2018
e00fb62
Add photon max resize
sirreal Dec 21, 2018
30c055c
Override default figure margin
sirreal Dec 21, 2018
9a6ebe0
Fix is-selected outline
simison Dec 21, 2018
c88721e
Add gutter over upload button
simison Dec 21, 2018
0881a21
Remove un-used caption styles
simison Dec 21, 2018
4282093
Ensure IDs are integers
simison Dec 21, 2018
a725a4b
Fix caption colors
simison Dec 21, 2018
dae6744
Disable columns control for unsupported layouts
simison Dec 21, 2018
7516e4f
Mosaic 😎😎😎😎😎😎😎😎 💥😁
sirreal Dec 21, 2018
879414f
Naively throw it in the editor
sirreal Dec 21, 2018
f34c371
Hide media placeholder in style preview
simison Dec 21, 2018
42d6601
Set default style classname on componentDidMount
simison Dec 21, 2018
10dcd08
Resize rows on view side with ResizeObserver 🎉
simison Dec 21, 2018
75ec6ef
Resize rows on edit side with ResizeObserver 🎉🎉
simison Dec 21, 2018
5e16162
Remove extra margin between rows
simison Dec 21, 2018
16fd31c
Add missing default style class also on save, not only on edit
simison Dec 22, 2018
15e4db5
Disable custom classnames so that folks don't fiddle with `is-style-`…
simison Dec 22, 2018
973d30e
Clean out un-used componentDidUpdate
simison Dec 22, 2018
ba51209
Don't set `wp-block-jetpack-tiled-gallery` twice on block
simison Dec 22, 2018
ff90e24
Don't observe without something to observe
simison Dec 22, 2018
e39a9bf
Correct hasStyleClass
sirreal Dec 27, 2018
7cfb62c
Fix Aria label translation function
simison Dec 27, 2018
01c3e8e
ABC imports
simison Dec 27, 2018
bdb5667
Add ResizeObserver polyfill in edit.jsx to fix Observer in non-Firefo…
simison Dec 27, 2018
145145b
Resize in mosaic layout
sirreal Dec 27, 2018
99d87c9
Test origUrl for isBlobURL, not Photonized URL
simison Dec 27, 2018
cb06f4c
Do not Photonize blob URLs
simison Dec 27, 2018
53cd9b8
Add is-transient background color
simison Dec 27, 2018
84183c7
Rename core-gallery CSS class names to tiled gallery
simison Dec 27, 2018
4c93b73
Match transient image styles with core-gallery
simison Dec 27, 2018
540ba75
Import ResizeObserver polyfill in mosaic layout
simison Dec 27, 2018
6525686
Inline static className
sirreal Dec 27, 2018
3a6c0b4
Resize on isWide change
sirreal Dec 27, 2018
8a8fe47
Drop weakMap memoization
sirreal Dec 27, 2018
a2a252c
Restore selected img delete interactions
sirreal Dec 27, 2018
2e3eff4
fixup! Restore selected img delete interactions
sirreal Dec 27, 2018
52b57ac
fixup! Resize on isWide change
sirreal Dec 27, 2018
f044ca7
Resize on align change
sirreal Dec 27, 2018
8773e1b
Use the observer to observe 🙄
sirreal Dec 27, 2018
5ce19db
Clean and simplify styling
sirreal Dec 27, 2018
930a22e
Remove negative top/right from remove-button
simison Dec 27, 2018
1205a54
Fix hidden inline caption toolbar
sirreal Dec 27, 2018
38783a8
Restore space between rows
sirreal Dec 27, 2018
1530807
Use DEFAULT_LAYOUT in LAYOUT_STYLES
sirreal Dec 27, 2018
017d518
Remove class recalculation
sirreal Dec 27, 2018
b4be374
Disable columns layout
sirreal Dec 27, 2018
d15cf07
Add custom align support
sirreal Dec 27, 2018
406d309
fixup! Add custom align support
sirreal Dec 27, 2018
dae31a0
Add className attribute default
sirreal Dec 27, 2018
ae19224
Resize images 💅😁
sirreal Dec 27, 2018
4028ee5
Try: fix column gutter miscalc
sirreal Dec 27, 2018
59c76a7
Revert "Try: fix column gutter miscalc"
sirreal Dec 27, 2018
92a0591
Improve fit
sirreal Dec 27, 2018
229d9e1
update snapshots
sirreal Dec 27, 2018
14a47ce
Remove tiled-grid
sirreal Dec 27, 2018
d17b7b2
Update deps
sirreal Dec 27, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions client/gutenberg/extensions/tiled-gallery/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,24 @@ export const DEFAULT_GALLERY_WIDTH = 580;
export const DEFAULT_LAYOUT = 'rectangular';
export const LAYOUT_STYLES = [
{
label: _x( 'Tiled mosaic', 'Tiled gallery layout' ),
name: 'rectangular',
isDefault: true,
label: _x( 'Tiled mosaic', 'Tiled gallery layout' ),
name: DEFAULT_LAYOUT,
},
{
label: _x( 'Tiled columns', 'Tiled gallery layout' ),
name: 'columns',
label: _x( 'Circles', 'Tiled gallery layout' ),
name: 'circle',
},
{
label: _x( 'Square tiles', 'Tiled gallery layout' ),
name: 'square',
},
/* Unimplemented
{
label: _x( 'Circles', 'Tiled gallery layout' ),
name: 'circle',
label: _x( 'Tiled columns', 'Tiled gallery layout' ),
name: 'columns',
},
*/
];
export const LAYOUTS = [ 'rectangular', 'columns', 'square', 'circle' ];
export const MAX_COLUMNS = 20;
export const TILE_MARGIN = 2;
245 changes: 111 additions & 134 deletions client/gutenberg/extensions/tiled-gallery/edit.jsx
Original file line number Diff line number Diff line change
@@ -1,51 +1,56 @@
/** @format */

/**
* External Dependencies
*/
import { filter, pick } from 'lodash';
import { Component, Fragment } from '@wordpress/element';
import { filter, get, pick } from 'lodash';
import {
BlockControls,
InspectorControls,
MediaPlaceholder,
MediaUpload,
mediaUpload,
} from '@wordpress/editor';
import {
DropZone,
FormFileUpload,
IconButton,
PanelBody,
RangeControl,
SelectControl,
ToggleControl,
Toolbar,
withNotices,
} from '@wordpress/components';
import {
BlockControls,
InspectorControls,
MediaPlaceholder,
mediaUpload,
MediaUpload,
} from '@wordpress/editor';
import { create } from '@wordpress/rich-text';

/**
* Internal dependencies
*/
import Layout from './layout';
import { __ } from 'gutenberg/extensions/presets/jetpack/utils/i18n';
import { ALLOWED_MEDIA_TYPES, MAX_COLUMNS, DEFAULT_COLUMNS } from './constants';
import GalleryGrid from './gallery-grid';
import GalleryImage from './gallery-image';
import { getActiveStyleName } from './layouts';
import { ALLOWED_MEDIA_TYPES, LAYOUT_STYLES, MAX_COLUMNS } from './constants';
import { getActiveStyleName } from 'gutenberg/extensions/utils';

const linkOptions = [
{ value: 'attachment', label: __( 'Attachment Page' ) },
{ value: 'media', label: __( 'Media File' ) },
{ value: 'none', label: __( 'None' ) },
];

// @TODO keep here or move to ./layout ?
function layoutSupportsColumns( layout ) {
return [ 'circle', 'square' ].includes( layout );
}

export function defaultColumnsNumber( attributes ) {
return Math.min( DEFAULT_COLUMNS, attributes.images.length );
return Math.min( 3, attributes.images.length );
}

const pickRelevantMediaFiles = image => {
let { caption } = image;

if ( typeof caption !== 'object' ) {
caption = create( { html: caption } );
}

return Object.assign( pick( image, [ [ 'alt' ], [ 'id' ], [ 'link' ], [ 'url' ] ] ), caption );
export const pickRelevantMediaFiles = image => {
const imageProps = pick( image, [ [ 'alt' ], [ 'id' ], [ 'link' ], [ 'caption' ] ] );
imageProps.url =
get( image, [ 'sizes', 'large', 'url' ] ) ||
get( image, [ 'media_details', 'sizes', 'large', 'source_url' ] ) ||
image.url;
return imageProps;
};

class TiledGalleryEdit extends Component {
Expand All @@ -61,101 +66,95 @@ class TiledGalleryEdit extends Component {
return null;
}

handleAddFiles = files => {
setAttributes( attributes ) {
if ( attributes.ids ) {
throw new Error(
'The "ids" attribute should not be changed directly. It is managed automatically when "images" attribute changes'
);
}

if ( attributes.images ) {
attributes = {
...attributes,
ids: attributes.images.map( ( { id } ) => parseInt( id, 10 ) ),
};
}

this.props.setAttributes( attributes );
}

addFiles = files => {
const currentImages = this.props.attributes.images || [];
const { noticeOperations, setAttributes } = this.props;
const { noticeOperations } = this.props;
mediaUpload( {
allowedTypes: ALLOWED_MEDIA_TYPES,
filesList: files,
onFileChange: images => {
const imagesNormalized = images.map( image => pickRelevantMediaFiles( image ) );
setAttributes( {
images: currentImages.concat( imagesNormalized ),
} );
this.setAttributes( { images: currentImages.concat( imagesNormalized ) } );
},
onError: noticeOperations.createErrorNotice,
} );
};

handleColumnCountChange = columns => this.props.setAttributes( { columns } );

handleCropImageToggle = () =>
this.props.setAttributes( { imageCrop: ! this.props.attributes.imageCrop } );

handleFormFileUpload = event => this.handleAddFiles( event.target.files );

handleLinkToChange = linkTo => this.props.setAttributes( { linkTo } );

handleRemveImageByIndex = index => () => {
onRemoveImage = index => () => {
const images = filter( this.props.attributes.images, ( img, i ) => index !== i );
const { columns } = this.props.attributes;
this.setState( { selectedImage: null } );
this.props.setAttributes( {
this.setState( {
selectedImage: null,
} );
this.setAttributes( {
images,
columns: columns ? Math.min( images.length, columns ) : columns,
} );
};

handleSelectImageByIndex = index => () => {
onSelectImage = index => () => {
if ( this.state.selectedImage !== index ) {
this.setState( {
selectedImage: index,
} );
}
};

handleSelectImages = images =>
this.props.setAttributes( {
images: images.map( image => pickRelevantMediaFiles( image ) ),
} );
onSelectImages = images =>
this.setAttributes( { images: images.map( image => pickRelevantMediaFiles( image ) ) } );

handleSetImageAttributesByIndex = index => newAttributes => {
const { attributes, setAttributes } = this.props;
const { images = [] } = attributes;
setColumnsNumber = value => this.setAttributes( { columns: value } );

setImageAttributes = index => attributes => {
const {
attributes: { images },
} = this.props;
if ( ! images[ index ] ) {
return;
}

setAttributes( {
this.setAttributes( {
images: [
...images.slice( 0, index ),
{
...images[ index ],
...newAttributes,
},
{ ...images[ index ], ...attributes },
...images.slice( index + 1 ),
],
} );
};

getImageCropHelp( checked ) {
return checked ? __( 'Thumbnails are cropped to align.' ) : __( 'Thumbnails are not cropped.' );
}
setLinkTo = value => this.setAttributes( { linkTo: value } );

uploadFromFiles = event => this.addFiles( event.target.files );

render() {
const { selectedImage } = this.state;

const { attributes, isSelected, className, noticeOperations, noticeUI } = this.props;
const { align, columns = defaultColumnsNumber( attributes ), images, linkTo } = attributes;

const {
images,
columns = defaultColumnsNumber( attributes ),
align,
imageCrop,
linkTo,
} = attributes;

const layoutsSupportingColumns = [ 'square', 'circle' ];

const dropZone = <DropZone onFilesDrop={ this.handleAddFiles } />;
const dropZone = <DropZone onFilesDrop={ this.addFiles } />;

const controls = (
<BlockControls>
{ !! images.length && (
<Toolbar>
<MediaUpload
onSelect={ this.handleSelectImages }
onSelect={ this.onSelectImages }
allowedTypes={ ALLOWED_MEDIA_TYPES }
multiple
gallery
Expand Down Expand Up @@ -185,7 +184,7 @@ class TiledGalleryEdit extends Component {
title: __( 'Tiled gallery' ),
name: __( 'images' ),
} }
onSelect={ this.handleSelectImages }
onSelect={ this.onSelectImages }
accept="image/*"
allowedTypes={ ALLOWED_MEDIA_TYPES }
multiple
Expand All @@ -196,86 +195,64 @@ class TiledGalleryEdit extends Component {
);
}

const renderGalleryImage = index => {
if ( ! images[ index ] ) {
return null;
}

const image = images[ index ];

return (
<GalleryImage
alt={ image.alt }
caption={ image.caption }
id={ image.id }
isSelected={ isSelected && selectedImage === index }
onRemove={ this.handleRemveImageByIndex( index ) }
onSelect={ this.handleSelectImageByIndex( index ) }
setAttributes={ this.handleSetImageAttributesByIndex( index ) }
url={ image.url }
/>
);
};

const layout = getActiveStyleName( this.props.className );
const layoutStyle = getActiveStyleName( LAYOUT_STYLES, attributes.className );

return (
<Fragment>
{ controls }
<InspectorControls>
<PanelBody title={ __( 'Tiled gallery settings' ) }>
{ images.length > 1 && (
<RangeControl
label={ __( 'Columns' ) }
value={ columns }
onChange={ this.handleColumnCountChange }
min={ 1 }
disabled={ ! layoutsSupportingColumns.includes( layout ) }
max={ Math.min( MAX_COLUMNS, images.length ) }
/>
) }
<ToggleControl
label={ __( 'Crop images' ) }
checked={ !! imageCrop }
onChange={ this.handleCropImageToggle }
help={ this.getImageCropHelp }
/>
{ /* @TODO disable with title comment, don't remove */ layoutSupportsColumns(
layoutStyle
) &&
images.length > 1 && (
<RangeControl
label={ __( 'Columns' ) }
value={ columns }
onChange={ this.setColumnsNumber }
min={ 1 }
max={ Math.min( MAX_COLUMNS, images.length ) }
/>
) }
<SelectControl
label={ __( 'Link to' ) }
label={ __( 'Link To' ) }
value={ linkTo }
onChange={ this.handleLinkToChange }
options={ [
{ value: 'attachment', label: __( 'Attachment page' ) },
{ value: 'media', label: __( 'Media file' ) },
{ value: 'none', label: __( 'None' ) },
] }
onChange={ this.setLinkTo }
options={ linkOptions }
/>
</PanelBody>
</InspectorControls>

{ noticeUI }
{ dropZone }
<GalleryGrid

<Layout
align={ align }
className={ className }
columns={ columns }
imageCrop={ imageCrop }
images={ images }
layout={ layout }
renderGalleryImage={ renderGalleryImage }
layoutStyle={ layoutStyle }
linkTo={ linkTo }
onRemoveImage={ this.onRemoveImage }
onSelectImage={ this.onSelectImage }
selectedImage={ isSelected ? selectedImage : null }
setImageAttributes={ this.setImageAttributes }
>
{ dropZone }
{ isSelected && (
<FormFileUpload
multiple
isLarge
className="block-library-gallery-add-item-button"
onChange={ this.handleFormFileUpload }
accept="image/*"
icon="insert"
>
{ __( 'Upload an image' ) }
</FormFileUpload>
<div className="tiled-gallery__add-item">
<FormFileUpload
multiple
isLarge
className="tiled-gallery__add-item-button"
onChange={ this.uploadFromFiles }
accept="image/*"
icon="insert"
>
{ __( 'Upload an image' ) }
</FormFileUpload>
</div>
) }
</GalleryGrid>
</Layout>
</Fragment>
);
}
Expand Down
Loading