Implemented query panel in latest posts block.#3198
Conversation
1ccd40e to
fc9e2da
Compare
d6618c4 to
f11d90e
Compare
aduth
left a comment
There was a problem hiding this comment.
Personally I'd have preferred to see the Latest Posts block updated to use withAPIData before enhancing it to handle additional data attributes.
There was a problem hiding this comment.
Minor: Alignment on the arrow (for consistency at least)
There was a problem hiding this comment.
Trying to think through localization impact here; would this be translated differently by language? We might consider at least including a translator comment to explain the intent here:
There was a problem hiding this comment.
For styling consistency I'd recommend not ending lines with the opening tag of an element and rather having these on their own line. Especially in the case of the line below with <SelectControl it helps readability to associate props with the opening tag and not losing context with the condition in which it renders.
return (
<div>
{ ( onOrderChange || onOrderByChange ) && (
<SelectControl
label={ __( 'Order by' ) }There was a problem hiding this comment.
We could probably test truthiness of the callback in the condition on the line above and avoid the dependency on noop. This also reads a little "clever".
There was a problem hiding this comment.
You might consider Lodash's flatMap which I recently found in #3185 to perform much better than Array#reduce + Array#concat.
Further, we can use array spread syntax to simplify this a bit:
function getSelectOptions( terms, level = 0 ) {
return flatMap( terms, ( term ) => [
{
value: term.id,
label: repeat( '\u00A0', level * 3 ) + unescapeString( term.name ),
},
...getSelectOptions( term.children, level + 1 ),
] );
}There was a problem hiding this comment.
This is a long line and difficult to read, I would suggest breaking it down a bit.
const options = (
noOptionLabel ?
[ { value: '', label: noOptionLabel } ] :
[]
).concat( getSelectOptions( termsTree ) );You could also use Lodash's compact to drop falsey values:
const options = compact( [
noOptionLabel && { value: '', label: noOptionLabel },
...getSelectOptions( termsTree ),
] );There was a problem hiding this comment.
Can we get some unit tests for this?
There was a problem hiding this comment.
Added :) they were missing at the time because I was not certain if a utils function was right for this case.
2290356 to
dcb3e7a
Compare
|
Thank you for your suggestions @aduth. I think I addressed all of them excluding an alignment in a php file. I made some changes to make things look better, but type item in categories is still not aligned with other types of other attributes, as the other type elements are not siblings (they are "cousins") if we add more spaces we break a phpcs rule. Regarding the refactoring to withAPIData in latest posts, as postsCollection.fetch supported exactly the parameters we needed, I would prefer to do this change in a separate PR. |
| const { setAttributes } = this.props; | ||
|
|
||
| if ( postToShowCurrent === postToShowNext ) { | ||
| if ( this.props.attributes === nextProps.attributes ) { |
There was a problem hiding this comment.
I don't think we want to rely on a strict equality check here; these two objects may in fact be different references while containing the same values for postsToShow, order, orderBy, categories. If we need to, we can use Lodash's _.isEqual for a deep equality comparison.
| categories: '/wp/v2/categories', | ||
| } ) ); | ||
|
|
||
| export default flowRight( [ |
There was a problem hiding this comment.
The flowRight here is unnecessary at this point (with a single higher-order component) and could be written as:
export default applyWithAPIData( CategorySelect );| onOrderByChange, | ||
| } ) { | ||
| return ( | ||
| <div> |
There was a problem hiding this comment.
If the div is not serving a purpose on its own, wondering if we ought to just return as an array, with the only gotcha being we'd have to add keys to each rendered element, but this would reduce the total number of DOM nodes on the screen and reduce indentation in the component:
return [
<SelectControl
key="..."
// ...
];dcb3e7a to
521f28b
Compare
|
Hi @aduth, thank you for your feedback 👍 , I rebased and addressed all the points. |
aduth
left a comment
There was a problem hiding this comment.
Requests incurred from unrelated attribute changes should be addressed.
There was a problem hiding this comment.
Why was this changed to put array opening on a line of its own? This isn't a style I've seen common to WordPress, and adds quite a bit of excessive indentation and awkward arrow spacing.
There was a problem hiding this comment.
It was a try to make things look more aligned while respecting phpcs rules. I reverted this change but unfortunately, I'm not seeing a way to make things more aligned and respect phpcs.
There was a problem hiding this comment.
Just noting that we really want to check that a change in the attributes specific to the fetching of posts are the only ones we want to trigger a new request for; as implemented, a change to the block's alignment, columns, layout will trigger a new request.
There was a problem hiding this comment.
Kinda feel we can drop the rest of the comment after the first comma, that's really up to the translator to judge for themselves, and the first bit should be sufficient for understanding the intent of the string.
There was a problem hiding this comment.
Personal preference would be to drop the newline prior to this comment, feels in line with this ESLint rule we have enabled:
There was a problem hiding this comment.
Inconsistency here with the previous condition, and also tabbed at least once more than necessary. Would suggest:
onNumberOfItemsChange && (
<RangeControl
key="query-panel-range-control"
label={ __( 'Number of items' ) }
value={ numberOfItems }
onChange={ onNumberOfItemsChange }
min={ minItems }
max={ maxItems }
/>
),448d807 to
3109a67
Compare
karmatosed
left a comment
There was a problem hiding this comment.
Design wise approving. I did find a bug though in changing the number of items. It got stuck after going to higher number then 1.
3109a67 to
8aacd1a
Compare
Codecov Report
@@ Coverage Diff @@
## master #3198 +/- ##
==========================================
- Coverage 37.85% 37.65% -0.21%
==========================================
Files 279 283 +4
Lines 6778 6748 -30
Branches 1240 1227 -13
==========================================
- Hits 2566 2541 -25
+ Misses 3547 3545 -2
+ Partials 665 662 -3
Continue to review full report at Codecov.
|
|
Hi @karmatosed, I was able to replicate something similar to what you described. When increasing number of posts to show the posts were not refreshing, leaving the user to be stuck in one post if a value of one was set before. It was introduced by a typo I made while addressing the last reviews and was fixed. Thank you for reporting the problem and for reviewing the design :) |
mcsf
left a comment
There was a problem hiding this comment.
I need to run, so here's a more drive-by review.
| if ( isEqual( | ||
| pick( this.props.attributes, attrsTriggerRefresh ), | ||
| pick( nextProps.attributes, attrsTriggerRefresh ) | ||
| ) ) { |
There was a problem hiding this comment.
Personally not a fan of the name attrsTriggerRefresh vs. e.g. queryKeys/queryProps. Though the name could be skipped altogether:
const shouldRefetch = [ 'a', 'b' ].some( ( queryKey ) =>
this.props.attributes[ queryKey ] !== nextProps.attributes[ queryKey ] );(or the converse with shouldSkip and Array#every)
| }; | ||
|
|
||
| const ret = fillWithChildren( termsByParent[ 0 ] || [] ); | ||
| return ret; |
| return ( | ||
| <TermTreeSelect | ||
| { ...{ label, noOptionLabel } } | ||
| termsTree={ buildTermsTree( categories.data ) } |
There was a problem hiding this comment.
What happens while we're waiting for the data request? Should we do an early null return?
| */ | ||
| import { unescape as unescapeString, repeat, flatMap, compact } from 'lodash'; | ||
|
|
||
| import SelectControl from '../inspector-controls/select-control'; |
There was a problem hiding this comment.
Missing Internal dependencies comment (also, if you want to be really consistent, the External one should use lowercase d 😅 ).
| function CategorySelect( { label, noOptionLabel, categories, selectedCategory, onChange } ) { | ||
| return ( | ||
| <TermTreeSelect | ||
| { ...{ label, noOptionLabel } } |
There was a problem hiding this comment.
Since you have this spread, you can throw in onChange.
| } | ||
|
|
||
| register_block_type( 'core/latest-posts', array( | ||
| register_block_type('core/latest-posts', array( |
There was a problem hiding this comment.
Should restore that space before the string 'core/latest-posts'.
| if ( newOrder !== order && 'function' === typeof onOrderChange ) { | ||
| onOrderChange( newOrder ); | ||
| } | ||
| if ( newOrderBy !== orderBy && 'function' === typeof onOrderByChange ) { |
There was a problem hiding this comment.
If onOrderChange and onOrderByChange default to Lodash's noop, the function checks here can be dropped.
| } ); | ||
| }; | ||
|
|
||
| const ret = fillWithChildren( termsByParent[ 0 ] || [] ); |
There was a problem hiding this comment.
Would termsByParent[ '0' ] be more correct? Since it's dict key.
5f30b3e to
b4e7465
Compare
|
Hi @mcsf, thank you a lot for your review, your feedback was applied. |
| import { buildTermsTree } from '../terms'; | ||
|
|
||
| describe( 'buildTermsTree()', () => { | ||
| describe( 'isHorizontalEdge', () => { |
There was a problem hiding this comment.
Some copy-paste that went wrong? 😄
eebf4c0 to
dfe86f8
Compare
| * Returns a Promise with the latest posts or an error on failure. | ||
| * | ||
| * @param {Number} postsToShow Number of posts to display. | ||
| * @param {String} order Sort attribute ascending or descending. |
There was a problem hiding this comment.
I recommend enumerating the two options: desc, asc and rephrasing to something like: Whether to sort in ascending or descending order: 'asc'|'desc'.
| * | ||
| * @param {Number} postsToShow Number of posts to display. | ||
| * @param {String} order Sort attribute ascending or descending. | ||
| * @param {String} orderBy Attribute specifying how to sort the posts. |
There was a problem hiding this comment.
Post parameter by which to sort posts.
| /** | ||
| * Internal dependencies | ||
| */ | ||
| import { buildTermsTree } from '../../editor/utils/terms'; |
There was a problem hiding this comment.
buildTermsTree is in @wordpress/editor, this should be a WordPress dependency.
There was a problem hiding this comment.
Moved to @wordpress/utils :)
There was a problem hiding this comment.
Good catch @mcsf, blocks library shouldn't depend on the editor. 👍
988ae68 to
81189ae
Compare
81189ae to
e17bef4
Compare
e17bef4 to
ee07318
Compare
Description
Ths PR aims to implement the query panel specified in issue #2662.
The panel is added to latest posts block. But this leaves a discussion point, it allows, for example, to show 8 oldest posts by setting sorting from oldest to newest.
To solve this we need to make a decision :
We rename this block to "Posts" allowing to show the most recent ones or oldest or other option the user chooses.
Or we maintain the most recent posts concept, we always retrieve from the database the N most recent posts and then we sort this recent posts in accordance with the sorting criteria the user selected.
Feel free to share your options.
How Has This Been Tested?
Try to change the values of the 3 different options in the query panel. Verify that the posts in the editor update in accordance with the option selected. Save the post on each option change, and open the post, verify the server side render also shows the selected option correctly.
Screenshots (jpeg or gifs if applicable):
Notes
There is a bug where component looks like loading forever if there are no posts that become more visible with this changes (because we can more easily select options without posts). A fix is being issued in #3180.
The function buildTermsTree in utils was extracted from HierarchicalTermSelector component. As a future PR, this component will be refactored to make use of the utils function (removing the duplicate version) and will also be simplified/refactored to make use of the new component TermTreeSelect created in this PR.