diff --git a/src/blocks/curated-list/edit.js b/src/blocks/curated-list/edit.js index dd6a68bd..0cb1bf41 100644 --- a/src/blocks/curated-list/edit.js +++ b/src/blocks/curated-list/edit.js @@ -5,18 +5,24 @@ import { __ } from '@wordpress/i18n'; import { createBlock } from '@wordpress/blocks'; import { InnerBlocks, InspectorControls, PanelColorSettings } from '@wordpress/block-editor'; import { + BaseControl, Button, ButtonGroup, PanelBody, PanelRow, RangeControl, + SelectControl, ToggleControl, - BaseControl, } from '@wordpress/components'; import { compose } from '@wordpress/compose'; import { withDispatch, withSelect } from '@wordpress/data'; import { Fragment, useEffect, useState } from '@wordpress/element'; +/** + * Internal dependencies + */ +import { getCuratedListClasses } from '../../editor/utils'; + const CuratedListEditorComponent = ( { attributes, canUseMapBlock, @@ -50,10 +56,7 @@ const CuratedListEditorComponent = ( { innerBlock => innerBlock.name === 'newspack-listings/list-container' ); const hasMap = innerBlocks.find( innerBlock => innerBlock.name === 'jetpack/map' ); - const classes = [ className, 'newspack-listings__curated-list' ]; - if ( showNumbers ) classes.push( 'show-numbers' ); - if ( showMap ) classes.push( 'show-map' ); - if ( showSortByDate ) classes.push( 'has-sort-by-date-ui' ); + const classes = getCuratedListClasses( className, attributes ); // Update locations in component state. This lets us keep the map block in sync with listing items. useEffect(() => { @@ -176,13 +179,26 @@ const CuratedListEditorComponent = ( { { showImage && ( - - setAttributes( { showCaption: ! showCaption } ) } + + + setAttributes( { showCaption: ! showCaption } ) } + /> + + setAttributes( { mediaPosition: value } ) } + options={ [ + { label: __( 'Top', 'newspack-listings' ), value: 'top' }, + { label: __( 'Left', 'newspack-listings' ), value: 'left' }, + { label: __( 'Right', 'newspack-listings' ), value: 'right' }, + { label: __( 'Behind', 'newspack-listings' ), value: 'behind' }, + ] } /> - + ) } { showImage && mediaPosition !== 'top' && mediaPosition !== 'behind' && ( diff --git a/src/blocks/curated-list/save.js b/src/blocks/curated-list/save.js index 691032ff..3794060b 100644 --- a/src/blocks/curated-list/save.js +++ b/src/blocks/curated-list/save.js @@ -3,28 +3,13 @@ */ import { InnerBlocks } from '@wordpress/block-editor'; -export const CuratedList = ( { attributes, className } ) => { - const { - showNumbers, - showMap, - showSortByDate, - // showExcerpt, - // showImage, - // showCaption, - // minHeight, - // showCategory, - // mediaPosition, - // typeScale, - // imageScale, - // mobileStack, - // textColor, - // showSubtitle, - } = attributes; +/** + * Internal dependencies + */ +import { getCuratedListClasses } from '../../editor/utils'; - const classes = [ className, 'newspack-listings__curated-list' ]; - if ( showNumbers ) classes.push( 'show-numbers' ); - if ( showMap ) classes.push( 'show-map' ); - if ( showSortByDate ) classes.push( 'has-sort-by-date-ui' ); +export const CuratedList = ( { attributes, className } ) => { + const classes = getCuratedListClasses( className, attributes ); return (
diff --git a/src/blocks/listing/edit.js b/src/blocks/listing/edit.js index e6c22b41..8ac0e9a8 100644 --- a/src/blocks/listing/edit.js +++ b/src/blocks/listing/edit.js @@ -4,7 +4,7 @@ import { __ } from '@wordpress/i18n'; import apiFetch from '@wordpress/api-fetch'; import { withSelect } from '@wordpress/data'; -import { RawHTML, useEffect, useState } from '@wordpress/element'; +import { Fragment, RawHTML, useEffect, useState } from '@wordpress/element'; import { Button, Notice, Spinner } from '@wordpress/components'; import { addQueryArgs } from '@wordpress/url'; @@ -27,8 +27,19 @@ const ListingEditorComponent = ( { const [ isEditingPost, setIsEditingPost ] = useState( false ); const { listing } = attributes; - // Get the parent Curated List block. - const parent = getBlock( getBlockParents( clientId )[ 0 ] ); + // Get the parent List Container block. + const parents = getBlockParents( clientId ); + const parent = parents.reduce( ( acc, outerBlock ) => { + const blockInfo = getBlock( outerBlock ); + + if ( 'newspack-listings/list-container' === blockInfo.name ) { + acc.listContainer = blockInfo; + } else if ( 'newspack-listings/curated-list' === blockInfo.name ) { + acc.curatedList = blockInfo; + } + + return acc; + }, {} ); // Parent Curated List block attributes. const { @@ -43,10 +54,10 @@ const ListingEditorComponent = ( { // mobileStack, // textColor, // showSubtitle, - } = parent.attributes; + } = parent.curatedList.attributes; // Build an array of just the listing post IDs that exist in the parent Curated List block. - const listItems = parent.innerBlocks.reduce( ( acc, innerBlock ) => { + const listItems = parent.listContainer.innerBlocks.reduce( ( acc, innerBlock ) => { if ( innerBlock.attributes.listing ) { acc.push( innerBlock.attributes.listing ); } @@ -70,8 +81,8 @@ const ListingEditorComponent = ( { // Sync parent attributes to listing attributes, so that we can use parent attributes in the PHP render callback. useEffect(() => { - setAttributes( { ...parent.attributes } ); - }, [ JSON.stringify( parent.attributes ) ]); + setAttributes( { ...parent.curatedList.attributes } ); + }, [ JSON.stringify( parent.curatedList.attributes ) ]); // Fetch listing post by listingId. const fetchPost = async listingId => { @@ -104,7 +115,7 @@ const ListingEditorComponent = ( { // Renders the autocomplete search field to select listings. Will only show listings of the type that matches the block. const renderSearch = () => { return ( -
+
- { error && ( - - { error } - - ) } - { post && post.title && ( -

- { post.title } -

- ) } - { showImage && post && post.media && post.media.image && ( -
- { - { showCaption && post.media.caption && ( -
- { post.media.caption } -
- ) } -
- ) } - { showExcerpt && post && post.excerpt && { post.excerpt } } + +
+ { error && ( + + { error } + + ) } + { showImage && post && post.media && post.media.image && ( +
+ { + { showCaption && post.media.caption && ( +
+ { post.media.caption } +
+ ) } +
+ ) } + { post && post.title && ( +
+

+ { post.title } +

+ { showExcerpt && post.excerpt && { post.excerpt } } +
+ ) } +
@@ -185,7 +200,7 @@ const ListingEditorComponent = ( { { __( 'Edit this listing', 'newspack-listing' ) } ) } -
+ ); }; diff --git a/src/blocks/listing/editor.scss b/src/blocks/listing/editor.scss index 5c111491..8d857517 100644 --- a/src/blocks/listing/editor.scss +++ b/src/blocks/listing/editor.scss @@ -1,3 +1,5 @@ +@import '../../listing-styles/shared/listing'; + .block-editor-block-list__layout { counter-reset: list; } @@ -37,9 +39,4 @@ &__error { margin: 1rem auto 2rem; } - - &__listing-featured-media { - margin: 1rem 0; - padding: 0; - } } diff --git a/src/blocks/listing/view.php b/src/blocks/listing/view.php index d3dec5d1..734feb61 100644 --- a/src/blocks/listing/view.php +++ b/src/blocks/listing/view.php @@ -71,9 +71,7 @@ function render_block( $attributes ) { ?>
  • -
  • diff --git a/src/editor/utils.js b/src/editor/utils.js index b38677cb..c6662fd6 100644 --- a/src/editor/utils.js +++ b/src/editor/utils.js @@ -5,7 +5,7 @@ /** * Check if the current post in the editor is a listing CPT. * - * @return {bool} + * @return {boolean} Whether or not the current post is a listing CPT. */ export const isListing = () => { if ( ! window.newspack_listings_data ) { @@ -22,3 +22,39 @@ export const isListing = () => { return false; }; + +/** + * Get array of class names for Curated List, based on attributes. + * + * @param {string} className The base class name for the block. + * @param {Object} attributes Block attributes. + * + * @return {Array} Array of class names for the block. + */ +export const getCuratedListClasses = ( className, attributes ) => { + const { + showNumbers, + showMap, + showSortByDate, + showImage, + mediaPosition, + // typeScale, + imageScale, + // mobileStack, + // textColor, + // showSubtitle, + } = attributes; + + const classes = [ className, 'newspack-listings__curated-list' ]; + + if ( showNumbers ) classes.push( 'show-numbers' ); + if ( showMap ) classes.push( 'show-map' ); + if ( showSortByDate ) classes.push( 'has-sort-by-date-ui' ); + if ( showImage ) { + classes.push( 'show-image' ); + classes.push( `media-position-${ mediaPosition }` ); + classes.push( `media-size-${ imageScale }` ); + } + + return classes; +}; diff --git a/src/listing-styles/listings/curated-list.scss b/src/listing-styles/front-end/curated-list.scss similarity index 100% rename from src/listing-styles/listings/curated-list.scss rename to src/listing-styles/front-end/curated-list.scss diff --git a/src/listing-styles/listings/listing.scss b/src/listing-styles/front-end/listing.scss similarity index 87% rename from src/listing-styles/listings/listing.scss rename to src/listing-styles/front-end/listing.scss index 87a1379a..8ae99fa2 100644 --- a/src/listing-styles/listings/listing.scss +++ b/src/listing-styles/front-end/listing.scss @@ -1,3 +1,5 @@ +@import '../shared/listing'; + .newspack-listings { // Target only .newspack-listings* when it's an `a` element @at-root a#{&} { diff --git a/src/listing-styles/listings/view.scss b/src/listing-styles/front-end/view.scss similarity index 100% rename from src/listing-styles/listings/view.scss rename to src/listing-styles/front-end/view.scss diff --git a/src/listing-styles/index.js b/src/listing-styles/index.js index ad5ef89c..b6d8f251 100644 --- a/src/listing-styles/index.js +++ b/src/listing-styles/index.js @@ -1,4 +1,4 @@ /** * Custom styles for listings pages. */ -import './listings/view.scss'; +import './front-end/view.scss'; diff --git a/src/listing-styles/shared/listing.scss b/src/listing-styles/shared/listing.scss new file mode 100644 index 00000000..19f785c0 --- /dev/null +++ b/src/listing-styles/shared/listing.scss @@ -0,0 +1,43 @@ +.newspack-listings { + &__listing-post { + .media-position-left &, + .media-position-right & { + display: flex; + } + } + + &__listing-featured-media { + flex-basis: 100%; + margin: 1rem 0; + max-width: 100%; + padding: 0; + + .media-position-right & { + order: 2; + } + + .media-size-1 & { + flex-basis: 25%; + } + + .media-size-2 & { + flex-basis: 50%; + } + + .media-size-3 & { + flex-basis: 75%; + } + } + + &__listing-meta { + flex-basis: 100%; + + .media-position-left & { + margin-left: 1rem; + } + + .media-position-right & { + margin-right: 1rem; + } + } +}