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

Feature: add support for a Tiled Gallery layout (Square Tiles) as a Gutenberg block #9903

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
30f366a
prototype separate jetpack tiled gallery block, render in php (placeh…
haszari Apr 1, 2018
0b948f3
remove dangling comma
haszari Apr 3, 2018
72d4f6e
remove php render code - focus on js render (more "Gutenbergy", and u…
haszari Apr 4, 2018
34b7f50
(work in progress - fails gutenberg validation?) render gallery block…
haszari Apr 4, 2018
35e2612
fix jetpack/gallery attribute definition; attributes were disappearin…
haszari Apr 7, 2018
af8991d
refactor jetpack/gallery to use same component for rendering images i…
haszari Apr 7, 2018
6816e28
implement column-tiled jetpack/gallery using css column-count approach
haszari Apr 7, 2018
6cfe3cb
tweak styling so gallery layout is consistent across editor/frontend:
haszari Apr 7, 2018
174271c
fix jetpack gallery transform to/from core gallery: correctly pass at…
haszari Apr 7, 2018
2217959
add upload button prompt text
haszari Apr 8, 2018
cdc0bf9
basic gallery item item component - rough markup (port php tiled gall…
haszari Apr 14, 2018
3eaea6f
update classname in attribute spec to ensure block attributes are pre…
haszari Apr 15, 2018
0bdd760
get image dimensions from store/api and render in markup
haszari Apr 15, 2018
01979a4
ensure that all child TiledGalleryItems have a key
haszari Apr 15, 2018
c705d05
set width & height attributes and render them in front-end markup (so…
haszari Apr 19, 2018
f468a92
add columns attribute (param for various tiled layouts)
haszari Apr 19, 2018
18e3301
enqueue tiled gallery js (and css) by default, so we can use it for o…
haszari Apr 19, 2018
82b840a
remove width/height elements from visible display (remnant of dev/inv…
haszari Apr 19, 2018
6589f07
new placeholder react component for "Square Tiles" layout, use it by …
haszari Apr 19, 2018
81773dc
initial port of square tiled layout algorithm – rough markup structure
haszari Apr 19, 2018
f5466c7
remove jetpack-tiled-gallery class to avoid clashes with column-count…
haszari Apr 19, 2018
4ff864f
square layout roughly working – render calculated layout width as sty…
haszari Apr 19, 2018
505c4c9
hard code content width to 520 for now (is appropriate for my current…
haszari Apr 21, 2018
97b9e68
implement basic square-tiles layout - render appropriate classes and …
haszari Apr 21, 2018
6126491
fix tiled-gallery image spacing – override (reset) figure margin
haszari Apr 21, 2018
a1e0d02
capitalise tiled gallery block "save" component, consistent with othe…
haszari Apr 22, 2018
cabb462
check setAttributes prop in TiledGalleryImage before use
haszari Apr 22, 2018
b525bc4
WYSIWYG editor preview for jetpack tiled galleries in Gutenberg editor
haszari Apr 22, 2018
31430d1
remove tiled gallery block file upload button (until we find a nice w…
haszari Apr 23, 2018
25bd5fb
enqueue existing/legacy tiled gallery scripts & styles for in `enqueu…
haszari Apr 23, 2018
250b3e4
Gutenberg Tiled Gallery: add support for editing column count attribu…
haszari Apr 25, 2018
fb13e61
Gutenberg Tiled Gallery: fix issue with column count not displaying i…
haszari Apr 25, 2018
13c974f
Gutenberg Tiled Gallery: render captions if they are set for the imag…
haszari Apr 26, 2018
0ca6533
Gutenberg Tiled Gallery: implement "link to.." author option ("..atta…
haszari Apr 26, 2018
7259673
Gutenberg Tiled Gallery: fix "link to..attachment page" - `link` prop…
haszari Apr 26, 2018
f65f730
Gutenberg Tiled Gallery: tidy up edit component, remove methods that …
haszari Apr 26, 2018
c77d9a2
Gutenberg Tiled Gallery: disable linkTo when editing, to avoid risk o…
haszari Apr 26, 2018
f3d33bc
Gutenberg Tiled Gallery: remove style.css (unused, left over from col…
haszari Apr 27, 2018
9ccc306
Gutenberg Tiled Gallery: remove unused image component
haszari Apr 27, 2018
223ff77
Gutenberg Tiled Gallery: switch out `album` icon for `format-gallery`…
haszari Apr 27, 2018
766105b
Gutenberg Tiled Gallery: consistent capitalisation for save component
haszari Apr 27, 2018
843bcfd
Gutenberg Tiled Gallery: tidy/clarify comments
haszari Apr 27, 2018
309baa5
Gutenberg Tiled Gallery: avoid fragile relative paths when enqueing g…
haszari May 12, 2018
f0efb90
Gutenberg Tiled Gallery: use "Jetpack Gallery" in empty-gallery place…
haszari May 12, 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
217 changes: 217 additions & 0 deletions modules/tiled-gallery/block-edit.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
/*global wp*/

/**
* External Dependencies
*/
import React from 'react';
import pick from 'lodash/pick';

/**
* WordPress dependencies (npm)
*/
const { Component } = wp.element;
const { __ } = wp.i18n;
const { mediaUpload } = wp.utils;

/**
* WordPress dependencies
*/
const {
IconButton,
DropZone,
Toolbar,
PanelBody,
RangeControl,
SelectControl,
} = wp.components;
const {
MediaUpload,
ImagePlaceholder,
InspectorControls,
BlockControls,
} = wp.blocks;

/**
* Internal dependencies
*/
import JetpackGalleryBlockSave from './block-save.jsx';

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

class JetpackGalleryBlockEditor extends Component {
constructor() {
super( ...arguments );

this.onSelectImage = this.onSelectImage.bind( this );
this.onSelectImages = this.onSelectImages.bind( this );
this.setLinkTo = this.setLinkTo.bind( this );
this.setColumnsNumber = this.setColumnsNumber.bind( this );
this.setImageAttributes = this.setImageAttributes.bind( this );
this.addFiles = this.addFiles.bind( this );

this.state = {
selectedImage: null,
};
}

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

onSelectImages( images ) {
this.props.setAttributes( {
images: images.map( ( image ) => pick( image, [ 'alt', 'caption', 'id', 'url', 'link' ] ) ),
} );
}

setLinkTo( value ) {
this.props.setAttributes( { linkTo: value } );
}

setColumnsNumber( value ) {
this.props.setAttributes( { columns: value } );
}

setImageAttributes( index, attributes ) {
const { attributes: { images }, setAttributes } = this.props;
if ( ! images[ index ] ) {
return;
}
setAttributes( {
images: [
...images.slice( 0, index ),
{
...images[ index ],
...attributes,
},
...images.slice( index + 1 ),
],
} );
}

addFiles( files ) {
const currentImages = this.props.attributes.images || [];
const { setAttributes } = this.props;
mediaUpload(
files,
( images ) => {
setAttributes( {
images: currentImages.concat( images ),
} );
},
'image',
);
}

componentWillReceiveProps( nextProps ) {
// Deselect images when deselecting the block
if ( ! nextProps.isSelected && this.props.isSelected ) {
this.setState( {
selectedImage: null,
captionSelected: false,
} );
}
}

render() {
const { attributes, isSelected, className } = this.props;
const { images, columns, linkTo } = attributes;

const dropZone = (
<DropZone key="item-dropzone"
onFilesDrop={ this.addFiles }
/>
);

const controls = (
isSelected && (
<BlockControls key="controls">
{ !! images.length && (
<Toolbar>
<MediaUpload
onSelect={ this.onSelectImages }
type="image"
multiple
gallery
value={ images.map( ( img ) => img.id ) }
render={ function( { open } ) {
return (
<IconButton
className="components-toolbar__control"
label={ __( 'Edit Gallery' ) }
icon="edit"
onClick={ open }
/>
);
}
}
/>
</Toolbar>
) }
</BlockControls>
)
);

if ( images.length === 0 ) {
return [
controls,
<ImagePlaceholder key="gallery-placeholder"
className={ className }
icon="format-gallery"
label={ __( 'Jetpack Gallery' ) }
onSelectImage={ this.onSelectImages }
multiple
/>,
];
}

// To avoid users accidentally navigating out of Gutenberg by clicking an image, we disable linkTo in the editor view here by forcing 'none'.
const imageTiles = (
<JetpackGalleryBlockSave
attributes={ {
images: images,
columns: columns,
linkTo: 'none',
} }
/>
);

return [
controls,
isSelected && (
<InspectorControls key="inspector">
<PanelBody title={ __( 'Jetpack Gallery Settings' ) }>
{ images.length > 1 && <RangeControl
label={ __( 'Columns' ) }
value={ columns }
onChange={ this.setColumnsNumber }
min={ 1 }
max={ Math.min( MAX_COLUMNS, images.length ) }
/> }
<SelectControl
label={ __( 'Link to' ) }
value={ linkTo }
onChange={ this.setLinkTo }
options={ linkOptions }
/>
</PanelBody>
</InspectorControls>
),
imageTiles,
dropZone,
];
}
}

export default JetpackGalleryBlockEditor;
18 changes: 18 additions & 0 deletions modules/tiled-gallery/block-save.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* External Dependencies
*/
import React from 'react';

/**
* Internal dependencies
*/
import TiledGalleryLayoutSquare from './block/components/tiled-gallery-layout-square.jsx';

function JetpackGalleryBlockSave( { attributes } ) {
return (
<TiledGalleryLayoutSquare { ...attributes } />
);
}

export default JetpackGalleryBlockSave;

104 changes: 104 additions & 0 deletions modules/tiled-gallery/block.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*global wp*/

/**
* WordPress dependencies
*/
const { __ } = wp.i18n;

/**
* Internal dependencies
*/
import JetpackGalleryBlockEditor from './block-edit.jsx';
import JetpackGalleryBlockSave from './block-save.jsx';

const JetpackGalleryBlockType = 'jetpack/gallery';

const settings = {
title: __( 'Jetpack Gallery' ),
icon: 'format-gallery',
category: 'layout',

attributes: {
columns: {
type: 'integer',
'default': 3,
},
linkTo: {
type: 'string',
'default': 'none',
},
images: {
type: 'array',
'default': [],
source: 'query',
selector: '.tiled-gallery-item',
query: {
width: {
source: 'attribute',
selector: 'img',
attribute: 'data-original-width',
},
height: {
source: 'attribute',
selector: 'img',
attribute: 'data-original-height',
},
url: {
source: 'attribute',
selector: 'img',
attribute: 'src',
},
link: {
source: 'attribute',
selector: 'img',
attribute: 'data-link',
},
alt: {
source: 'attribute',
selector: 'img',
attribute: 'alt',
'default': '',
},
id: {
source: 'attribute',
selector: 'img',
attribute: 'data-id',
},
caption: {
type: 'array',
source: 'children',
selector: 'figcaption',
},
},
},
},

transforms: {
from: [
{
type: 'block',
blocks: [ 'core/gallery' ],
transform: function( content ) {
return wp.blocks.createBlock( JetpackGalleryBlockType, content );
},
},
],
to: [
{
type: 'block',
blocks: [ 'core/gallery' ],
transform: function( content ) {
return wp.blocks.createBlock( 'core/gallery', content );
},
},
],
},

edit: JetpackGalleryBlockEditor,
save: JetpackGalleryBlockSave
};

wp.blocks.registerBlockType(
JetpackGalleryBlockType,
settings
);
Loading