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

Related Posts Block #10

Closed
4 of 5 tasks
gregrickaby opened this issue Feb 15, 2018 · 18 comments
Closed
4 of 5 tasks

Related Posts Block #10

gregrickaby opened this issue Feb 15, 2018 · 18 comments
Assignees
Labels
R4R Issue or PR ready for review

Comments

@gregrickaby
Copy link
Contributor

gregrickaby commented Feb 15, 2018

Duplicate our current Related Post Block functionality as a Gutenblock.

http://gutenberg.wdslab.com/acf-blocks-page/

Requirements

  • Background Image, Video, and Color
  • Title
  • Manual Post Selector (up to 3)
  • Font Color
  • Custom CSS Class

Screenshot

screenshot

@gregrickaby gregrickaby added this to the Initial Blocks milestone Feb 15, 2018
@coreymcollins
Copy link
Contributor

I spent some time messing around with grabbing posts from the API today and trying to manipulate them, but didn't come up with any substantial breakthroughs here. I started with Zac Gordon's Dynamic and Dynamic Alt blocks (https://github.com/zgordon/gutenberg-course/tree/master/jsforwp-blocks/blocks/examples) as a basis for grabbing posts.

Ideally, this would look and work exactly how ACF works where you have a list of posts on the left side with a search input; you can type something in the input to search posts; and clicking the post on the left side would add it to the right side, where the posts would then be sortable.

I know Human Made created a component for Post Search and Select (https://github.com/humanmade/hm-gutenberg-tools) so maybe we can take some cues from that as well.

This one's a doozy!

@coreymcollins
Copy link
Contributor

I started working on a bit of something for this today, basically taking the _s_display_block_options from wd_s and bringing it into the plugin to use for dynamic blocks.

Will try to push something up to a branch before EOD/after FED scrum!

@coreymcollins
Copy link
Contributor

Pushed this up to https://github.com/WebDevStudios/wds-gutenberg/commits/feature/%2310-related-posts-block

This is essentially all we need to replicate how wd_s adds inline styles/options to blocks. It needs some fine-tuning still, as background images aren't working, but this is a start.

Block Options render: https://github.com/WebDevStudios/wds-gutenberg/blob/5226937088bbd460120ce977b5fca51dfcb530c5/src/block-options.php

Then, to use this in a dynamic block:

<?php
/**
 * Displays the Related Posts block.
 *
 * @package WDS_Gutenberg
 * @since NEXT
 */

namespace WDS_Gutenberg\Src\Related_Posts;

/**
 * Render block: Related Posts.
 *
 * @param array $attributes The attributes passed in from the Related Post block settings.
 * @return string The block markup.
 *
 * @since NEXT
 */
function render_block( $attributes ) {

	ob_start(); ?>

	<!-- wp:wds/related-posts -->
	<?php \WDS_Gutenberg\Src\Block_Options\display_block_options( $attributes ); ?>
		this is the block content
	</section>
	<!-- /wp:wds/related-posts -->
	<?php

	return ob_get_clean();
}
register_block_type( 'wds/related-posts', [ 'render_callback' => __NAMESPACE__ . '\\render_block' ] );

@coreymcollins
Copy link
Contributor

This is started here: https://github.com/WebDevStudios/wds-gutenberg/tree/feature/%2310-related-posts-block

No PR as of yet, just a progress update. I think we should be all good to go on the dynamic background elements which mimic wd_s with some adjustments here and there.

This will allow blocks not built out in JS to utilize the background image, video, and color; text color; and animation properties.

Once complete, this will be able to be utilized on #9 and any other future blocks built dynamically in PHP.

Screenshots, in order:

  • Image background
  • Video background
  • Color background
  • No background (just text color)
  • No custom options (at the very bottom, clipped)

If there is a background element in place, the block automatically gets padding via a has-custom-background class.

@coreymcollins
Copy link
Contributor

coreymcollins commented Mar 8, 2018

Merged master in here and added the BlockTitle to the starter for Related Posts.

Creates a function to display the block title via PHP render:
d47b359

What's left next is the big piece - the manual post selector. Would love to maybe chat in the morning with @kellenmace and @gregrickaby (and @jomurgel if he's going to be involved) about the best way to approach this and build a cool post selector.

@kellenmace
Copy link
Contributor

@coreymcollins It looks like this PostControl component by Human Made may provide the post selection functionality that's needed for this block:
https://github.com/humanmade/hm-gutenberg-tools/wiki/Post-Select-Control

And info on its underlying PostSelectButton component is here: https://github.com/humanmade/hm-gutenberg-tools/wiki/Post-Select-Button

@coreymcollins
Copy link
Contributor

How do we feel about requiring another plugin to get our Gutenblocks to work? Or, are you suggesting we dig into that code to pull out what we need for ourselves?

@kellenmace
Copy link
Contributor

@coreymcollins yeah, I was thinking along the lines of pulling out what we need from the components they've built. As long as we like how they work - I haven't actually installed and played around with theirs yet.

@coreymcollins
Copy link
Contributor

If anyone else wants to jump in here, I'd love an extra pair of hands (or multiple pairs of hands).

Been swimming around the HM code and trying to parse out what's what and how we can craft a solution based on what they've built, but I may be hitting my wall at this moment.

cc: @gregrickaby @efuller @jomurgel @kellenmace

@jomurgel
Copy link
Contributor

jomurgel commented Mar 16, 2018

Made a little progress here.

New Block — Related Posts

Rather than overwriting anything that was worked on by @kellenmace or @coreymcollins I added a new block called New Related Posts.

Right now I'm pulling in 100 posts and only the Posts CPT and I'm only outputting the Title and a list of linked titles.

I've broken the block into several components.

index.js

Handles the block registration and edit/save functions. Utilizes the EditComponent.

edit.js

Our edit function has been built out into it's own function. Handles the API request on componentWillMount

item.js

Stateless functional component for a single list item from posts with an onClick handler. This needs a keyboard bind, something like onKeyDown={this.handleKeyDown} to be compliant

Usage

<Item
    key={ `${ result.id }-${ index }` }
    postName={ result.title.rendered }
    post={ result }
    handleClick={ handleEvent }
/>

output.js

Stateless functional component for handling the output for each column. Title, list of posts (imported or selected).

Usage

<Output
    title="Posts"
    className="related-left-column"
    key=""
    posts={ this.state.allPosts }
    handleEvent={ this.handleEvent }
/>

New Global Component —— Loader

A component than outputs a loader image container. Nothing fancy.

Usage

import Loader from '../../components/loader';

<Loader className="STRING" loader="URL" width="INT" height="INT" />
// or
<Loader />

The default class name is wp-block-loader, the default spinner is /wp-includes/images/spinner-2x.gif, and the height and width both default to 25.

kapture 2018-03-16 at 14 27 02

Result

Render

kapture 2018-03-16 at 13 52 07

Output

screenshot 2018-03-16 13 51 21

Roadmap

  • Build Search Component (perhaps to handle the api request completely)
  • Better API Handling
  • Support for Custom Post Types + Taxonomies
  • Support max post count +metabox notice if trying to add more.
  • Add meta box notice if post trying to save 0 selected posts.
  • Add default background/styling from global WDS components.
  • Output built markup instead of just a list of linked titles.
  • Bind keyboard to item onKeyDown={this.handleKeyDown}.

@jomurgel
Copy link
Contributor

jomurgel commented Mar 19, 2018

Still working out some bugs and request issues, but taking a stab at better API handling with pagination and searching.

Pen: https://codepen.io/jomurgel/pen/MVjdgW?editors=0010

UPDATE: codepen's Search component has been rolled to handle the search and should be self-sufficient. Will roll into global components in WDS-Gutenberg and configure to work in the next steps :)

@jomurgel
Copy link
Contributor

jomurgel commented Mar 23, 2018

The search component referenced above has been rolled into this block.

Added

  • Search queries the API and puts results into the "Posts" left container.
  • Posts are requested on scroll page by page until reach end. If all posts are fetched we stop the ability to receive or fetch saving us from a 400 response.
  • Pen was updated to show new component structure as well, Pen: https://codepen.io/jomurgel/pen/MVjdgW?editors=0010
  • Added className props to search component.
  • Added a few styles to get things in order.

screenshot 2018-03-23 18 00 52

ToDo

Still, a bit to do here along with the few items above not finished.

  • Add selected posts from search query to attributes. Currently, this does not append to our props and won't render to the front end.
  • Address issues with posts selection that appear in the allPosts state AND the queriedPosts showing up in multiple places, and/or being allowed to be selected twice.
  • If queried post is selected, it should no longer appear in the allPosts array.

Feels like a step back here, but I think this is a move in the right direction.

Search comonent usage

Import

import Search from '../../components/search';

Call

<Search onQueryChange={ this.returnQueryData } />

onQueryChange is a callback function that will set our state with data passed up from our Search component.

// responseQuery = array of posts
returnQueryData( responseQuery ) {
    this.setState( { queriedPosts: responseQuery } );
}

The search component itself is making a simple api request from this.apiQueryURL = ( query ) => wpApiSettings.root + wp/v2/posts?search=${ query }&filter[posts_per_page]=-1; which makes a simple search query. The results of which are passed up and recieved using that function above.

@jomurgel
Copy link
Contributor

jomurgel commented Mar 24, 2018

I may have worked out a potential fix for the issue above, but need a little more digging. Might also think about seeing if there is a better way to handle data from our posts query, our search query, and selected. 👍

  • Rework data structure
  • Pass query string up to parent from search component? May add a valid data point to compare against.

@jomurgel
Copy link
Contributor

jomurgel commented Mar 25, 2018

Built out the search and related posts components to handle data a little more gracefully. Tackled a few tasks from above.

I rewrote the search handling and post output handling to add data rather than removing data from one array to another array.

This may basically complete #28. Essentially our <Output> component will, if an item has been selected (onClick Handler) pass the post object to a selectedPosts array in our state.

I also added some checks to disable clicking and adjust styles on click if our post was moved from our main posts query to our selectedPosts array.

This check also handles the search results query.

  • Rework data structure
  • Pass query string up to parent from search component? May add a valid data point to compare against.
  • Add selected posts from search query to attributes. Currently, this does not append to our props and won't render to the front end.
  • Address issues with posts selection that appear in the allPosts state AND the queriedPosts showing up in multiple places, and/or being allowed to be selected twice.
  • If queried post is selected, it should no longer appear in the allPosts array.

kapture 2018-03-25 at 15 38 36

New Pending on this task

  • Support for Custom Post Types + Taxonomies
  • Support max post count +metabox notice if trying to add more.
  • Add meta box notice if post trying to save 0 selected posts.
  • Add default background/styling from global WDS components.
  • Output built markup instead of just a list of linked titles.
  • Bind keyboard to item onKeyDown={this.handleKeyDown}.

Might roll some of these ^^ into a search component update.

@jomurgel
Copy link
Contributor

jomurgel commented Apr 9, 2018

Made some updates this weekend to fix some problems that arose as a result of the recent Gutenberg update.

@coreymcollins
Copy link
Contributor

Been working on this a little bit to try and get the frontend and backend visual markup in place. I have it somewhat working, but it breaks once you refresh the page:

Since it's non-working at the moment, I want to wait before committing anything to the repo - but this is a work in progress at the moment.

@coreymcollins
Copy link
Contributor

Got some more work in on this today. I started by reverting back to the original block and realized that it, too, would error when reloading the page in the dashboard so I'm evidently not doing anything new by breaking that as we build out the markup.

I did clean up a bunch of duplicate key warnings that were being thrown in the console, which doesn't help smooth out the display of the markup at all but gets us passed getting a bunch of warnings when the block is added to a page.

Going to wait, again, before pushing the changes I have committed locally as Jo is going to first try and do a little bit of testing on the branch as it exists now. I'm running into some errors he isn't sure he saw before, so perhaps we'll be able to narrow those down a bit.

jomurgel added a commit that referenced this issue Apr 13, 2018
…udios/wds-gutenberg into feature/#10-related-posts-block
@jomurgel
Copy link
Contributor

Made several updates here to ensure that our posts content and saved state are identical when reloading the page. Essentially we converted our post objects to JSON to save as a string in our post content attributes object for recall on reload.

We added a new attribute — string — for holding the JSON and utilize that on load to render our block. On save the attribute and post content should be identical.

This also might be a workaround or a solution for #32 or accessing anything other than a string in the php render_callback function.

Will be rolling in work Corey did (above) with the new code added today.

@jomurgel jomurgel added the R4R Issue or PR ready for review label Apr 17, 2018
@efuller efuller mentioned this issue Apr 24, 2018
7 tasks
gregrickaby pushed a commit that referenced this issue Apr 25, 2018
* Start to build out post selection fields component

* Make use of the Dashicon and UrlInput components in our PostSearch component

* Adjusts post search component to find and save a post URL

* Builds

* Re-builds

* Adds loader component to global components

Usage: <Loader className="" loader="URL" width="INT" height="INT" />

Defaults to WP loader.

* adds new related posts block import

* removes margin from h2 to clean up output of block title

* adds editor and front-end block styles (basics)

* registers new related posts block type and sets up attributes, edit and save functions

would like to add the deprecation function later

* updates title

* builds

* outputs edit function as component — handles two columns, api request, and sorting

* adds item component — needs to add something like onKeyDown={this.handleKeyDown} to pass linting requirements

* adds output component for columns

* convers output, item and loader class components to stateless functional components — bruh

* builds

* adds fragment and removes console logs from testing

* updates block icon and builds

* adds global search component

* Rolls search component into edit component and adds scroll Event listender to posts ul to fetch posts on scroll

* converts Output component to stateful component to take advantage of ref for scroll event listener in parent

* adds props for className to search component and passess from related posts

* adds base styles for searchform in related posts component

* targets search more directly

* adds placeholder functions for dealing with data between allPosts, queriedPosts and Selected Posts

* corrects typo

* doesn't make another request if query string is emtpy

* adds activeClass props from parent

* removes pointer events if selected and adds is-selected styles

* adds search query callback into state and reworks the basic functionality of the multi-select functionality

* adds an `is-selected` class to item if ... selected ...

* removes console.logging, and unused vars

* changes title of the post container if queried

* disables sass linting on some objects

* adds selected class to item if item also exists in selected posts array

* builds

* setsState on new array instead of relying on splice — prevents 1-item delay

* updates isActive to filter state

* updates cursor styles

* builds

* adds empty deprecation array for later use

* Changes block title default to an empty string, not null, to fix an error

* builds

* adds JSON placeholder to state

* separates post object and id on click handler and does comparison to id not post object in array

* adds setState to set value of prop.attributes for render to output same markup as stored in post content

* adds attribtue set for selectedPostsJSON for update to postContent attribute object

* adds new attribute for supplying JSON to post content

* renders post output with JSON data instead of post object to ensure JSON and post content are identical

* adds post.js from Corey's branch

* imports post.js component

* replaces markup for save function with new component — post.js

* replaces markup for save function with new component — post.js

* adds basic styles for related posts editor output when not focused

* imports new post js

* updates post query to include the _embed flag

* adds fallback for selectedPostsJSON check to empty array for new blocks (no json data yet)

* wraps event listener in focus check to make sure that we're not checking when the block isn't present

* replaces render function with work corey did on his branch

* refactors post.js a little bit

* show selection container if nothing is selected

* updates selection check to check attributes not state.

* removes justify-content space-between and relies (for now) on margins and nth-child fix

* builds

* removes original related posts block

* renames new related posts related posts

* adds background, text and other options attributes

* registeres inspector controls

* adds background/text options to block

* reworks some classnames for change in block name

* sets styles to output

* remove unused components

* removes new related posts — now just related posts

* updates block styles for output

* adds text/background options to output (heading/list items)

* builds

* removes related post render php file — no longer needed

* adjusts line heights on p and h3s

* increases bottom margin on blocks

* builds css

* adds value check for `post._embedded` object before render attempt on `wp:featuredmedia`

* builds

* adds video option only on focus

* bulids

* updates check to confirm that array object exists

* adds tabindex for accessibility

* adds keypress handler to list items for accessibility

* builds

* rolls out deprecated array function

* builds

* adds loaded prop return to search component

* removes console logging

* builds

* adds post renderer component which makes api request

* adds classname to post output container wrapper

* reworks edit component to display updated posts (in the event that posts get updated between saving/updated)

* builds

* deletes post.js

* updates map return on post-render to output item instead of item.id (new data structure)

* adds render php

* converts to stateless component

* removes save function and attributes — now using render callback function

* sets a min height to selected posts container

* sets up edit function to pull in selected posts and set state with api request on load

* bind setAttributes inside returnLayout function to avoide being called durnign state transition

* builds

* utilize withAPIData function using state and not attributes

* resolves error with warning on update during state transition

Warning: Cannot update during an existing state transition (such as within render or another component's constructor). Render methods should be a pure function of props and state; constructor side-effects are an anti-pattern, but can be moved to componentWillMount.

* builds

* makes sure that links are the same color as text

* sets link color to inherit

* adds _embed argument to API call to pull in images

* adds classname to ul

* updates posts to show

* adds eventListener on componentDidUpdate and rolls event listener function into external callback function

* builds

* Removes duplicate `handleScroll` function

* Change orderby to `post__in` to order by the order in which posts are added/saved

* If no posts are manually selected, only pull 3 posts

* Adds the entry-content class to the content container

* Build

* Builds

* Fixes an issue with multiple section containers + default class name
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
R4R Issue or PR ready for review
Projects
None yet
Development

No branches or pull requests

4 participants