Skip to content

Commit

Permalink
WIP: Navigation Link variations
Browse files Browse the repository at this point in the history
  • Loading branch information
noisysocks committed Aug 19, 2020
1 parent deec0ae commit b271299
Show file tree
Hide file tree
Showing 9 changed files with 159 additions and 41 deletions.
2 changes: 2 additions & 0 deletions packages/block-editor/src/components/link-control/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ function LinkControl( {
createSuggestion,
withCreateSuggestion,
inputValue: propInputValue = '',
suggestionsQuery = {},
} ) {
if ( withCreateSuggestion === undefined && createSuggestion ) {
withCreateSuggestion = true;
Expand Down Expand Up @@ -209,6 +210,7 @@ function LinkControl( {
showInitialSuggestions={ showInitialSuggestions }
allowDirectEntry={ ! noDirectEntry }
showSuggestions={ showSuggestions }
suggestionsQuery={ suggestionsQuery }
>
<div className="block-editor-link-control__search-actions">
<Button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,12 @@ const LinkControlSearchInput = forwardRef(
fetchSuggestions = null,
allowDirectEntry = true,
showInitialSuggestions = false,
suggestionsQuery = {},
},
ref
) => {
const genericSearchHandler = useSearchHandler(
suggestionsQuery,
allowDirectEntry,
withCreateSuggestion
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,18 @@ export const handleDirectEntry = ( val ) => {
] );
};

export const handleEntitySearch = async (
const handleEntitySearch = async (
val,
args,
{ isInitialSuggestions, type, subtype },
fetchSearchSuggestions,
directEntryHandler,
withCreateSuggestion
) => {
let results = await Promise.all( [
fetchSearchSuggestions( val, {
...( args.isInitialSuggestions ? { perPage: 3 } : {} ),
...( isInitialSuggestions
? { perPage: 3, type, subtype }
: { type, subtype } ),
} ),
directEntryHandler( val ),
] );
Expand All @@ -65,12 +67,12 @@ export const handleEntitySearch = async (
// just for good measure. That way once the actual results run out we always
// have a URL option to fallback on.
results =
couldBeURL && ! args.isInitialSuggestions
couldBeURL && ! isInitialSuggestions
? results[ 0 ].concat( results[ 1 ] )
: results[ 0 ];

// If displaying initial suggestions just return plain results.
if ( args.isInitialSuggestions ) {
if ( isInitialSuggestions ) {
return results;
}

Expand Down Expand Up @@ -101,6 +103,7 @@ export const handleEntitySearch = async (
};

export default function useSearchHandler(
{ type, subtype },
allowDirectEntry,
withCreateSuggestion
) {
Expand All @@ -117,12 +120,12 @@ export default function useSearchHandler(
: handleNoop;

return useCallback(
( val, args ) => {
( val, { isInitialSuggestions } ) => {
return isURLLike( val )
? directEntryHandler( val, args )
? directEntryHandler( val, { isInitialSuggestions } )
: handleEntitySearch(
val,
args,
{ isInitialSuggestions, type, subtype },
fetchSearchSuggestions,
directEntryHandler,
withCreateSuggestion
Expand Down
8 changes: 7 additions & 1 deletion packages/block-library/src/navigation-link/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,13 @@
"rel": {
"type": "string"
},
"id": {
"objectType": {
"type": "string"
},
"objectName": {
"type": "string"
},
"objectId": {
"type": "number"
},
"opensInNewTab": {
Expand Down
13 changes: 9 additions & 4 deletions packages/block-library/src/navigation-link/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ function NavigationLinkEdit( {
mergeBlocks,
onReplace,
} ) {
const { label, opensInNewTab, url, description, rel } = attributes;
const { label, opensInNewTab, url, description, rel, type } = attributes;
const link = {
url,
opensInNewTab,
Expand Down Expand Up @@ -119,8 +119,7 @@ function NavigationLinkEdit( {
}

async function handleCreatePage( pageTitle ) {
const type = 'page';
const page = await saveEntityRecord( 'postType', type, {
const page = await saveEntityRecord( 'postType', 'page', {
title: pageTitle,
status: 'publish',
} );
Expand Down Expand Up @@ -234,10 +233,14 @@ function NavigationLinkEdit( {
showInitialSuggestions={ true }
withCreateSuggestion={ userCanCreatePages }
createSuggestion={ handleCreatePage }
suggestionsQuery={ {
subtype: type,
} }
onChange={ ( {
title: newTitle = '',
url: newURL = '',
opensInNewTab: newOpensInNewTab,
type,
id,
} = {} ) =>
setAttributes( {
Expand Down Expand Up @@ -265,7 +268,9 @@ function NavigationLinkEdit( {
return escape( normalizedURL );
} )(),
opensInNewTab: newOpensInNewTab,
id,
objectType: 'post_type',
objectName: type,
objectId: id,
} )
}
/>
Expand Down
40 changes: 40 additions & 0 deletions packages/block-library/src/navigation-link/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,56 @@ export { metadata, name };

export const settings = {
title: __( 'Link' ),

icon,

description: __( 'Add a page, link, or another item to your navigation.' ),

variations: [
{
name: 'link',
isDefault: true,
title: __( 'Link' ),
description: __( 'A link to a URL.' ),
attributes: {},
},
{
name: 'post',
title: __( 'Post' ),
description: __( 'A link to a post.' ),
attributes: { type: 'post' },
},
{
name: 'page',
title: __( 'Page' ),
description: __( 'A link to a page.' ),
attributes: { type: 'page' },
},
// {
// name: 'category',
// title: __( 'Category' ),
// description: __( 'A link to a category.' ),
// attributes: { type: 'category' },
// },
// {
// name: 'tag',
// title: __( 'Tag' ),
// description: __( 'A link to a tag.' ),
// attributes: { type: 'tag' },
// },
],

__experimentalLabel: ( { label } ) => label,

merge( leftAttributes, { label: rightLabel = '' } ) {
return {
...leftAttributes,
label: leftAttributes.label + rightLabel,
};
},

edit,

save,

deprecated: [
Expand Down
24 changes: 21 additions & 3 deletions packages/block-library/src/navigation-link/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -132,15 +132,33 @@ function render_block_core_navigation_link( $attributes, $content, $block ) {
'<a class="wp-block-navigation-link__content" ';

// Start appending HTML attributes to anchor tag.
if ( isset( $attributes['url'] ) ) {
$html .= ' href="' . esc_url( $attributes['url'] ) . '"';

if (
isset( $attributes['objectType'] ) &&
isset( $attributes['objectName'] ) &&
isset( $attributes['objectId'] )
) {
if ( 'post_type' === $attributes['objectType'] ) {
$url = get_permalink( $attributes['objectId'] );
} elseif ( 'taxonomy' === $attributes['objectType'] ) {
$url = get_term_link( $attributes['objectId'] );
} elseif ( 'post_type_archive' === $attributes['objectType'] ) {
$url = get_post_type_archive_link( $attributes['objectName'] );
}
}

if ( ! isset( $url ) && isset( $attributes['url'] ) ) {
$url = $attributes['url'];
}

if ( isset( $url ) ) {
$html .= ' href="' . esc_url( $url ) . '"';
}

if ( isset( $attributes['opensInNewTab'] ) && true === $attributes['opensInNewTab'] ) {
$html .= ' target="_blank" ';
}

// Start appending HTML attributes to anchor tag.
if ( isset( $attributes['rel'] ) ) {
$html .= ' rel="' . esc_attr( $attributes['rel'] ) . '"';
} elseif ( isset( $attributes['nofollow'] ) && $attributes['nofollow'] ) {
Expand Down
77 changes: 56 additions & 21 deletions packages/block-library/src/navigation/placeholder.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
* External dependencies
*/

import { escape } from 'lodash';
import { escape, some } from 'lodash';
import classnames from 'classnames';

/**
* WordPress dependencies
*/
import { createBlock } from '@wordpress/blocks';
import { createBlock, parse } from '@wordpress/blocks';
import {
Button,
CustomSelectControl,
Expand Down Expand Up @@ -78,28 +78,63 @@ function getSelectedMenu( selectedCreateOption ) {
/**
* A recursive function that maps menu item nodes to blocks.
*
* @param {Object[]} nodes An array of menu items.
*
* @param {Object[]} menuItems An array of menu items.
* @return {WPBlock[]} An array of blocks.
*/
function mapMenuItemsToBlocks( nodes ) {
return nodes.map( ( { title, type, link: url, id, children } ) => {
const innerBlocks =
children && children.length ? mapMenuItemsToBlocks( children ) : [];
function mapMenuItemsToBlocks( menuItems ) {
return menuItems.map( ( menuItem ) => {
if ( menuItem.type === 'block' ) {
const [ block ] = parse( menuItem.content.raw );

return createBlock(
'core/navigation-link',
{
type,
id,
url,
label: ! title.rendered
? __( '(no title)' )
: escape( title.rendered ),
opensInNewTab: false,
},
innerBlocks
);
if ( ! block ) {
return createBlock( 'core/freeform', {
content: menuItem.content,
} );
}

return block;
}

const attributes = {
label: ! menuItem.title.rendered
? __( '(no title)' )
: escape( menuItem.title.rendered ),
opensInNewTab: menuItem.target === '_blank',
};

if ( menuItem.description ) {
attributes.description = menuItem.description;
}

if ( menuItem.xfn?.length && some( menuItem.xfn ) ) {
attributes.rel = menuItem.xfn.join( ' ' );
}

if ( menuItem.type ) {
attributes.objectType = menuItem.type;
}

if ( menuItem.object ) {
attributes.objectName = menuItem.object;
}

if ( menuItem.object_id ) {
attributes.objectId = menuItem.object_id;
}

if ( menuItem.classes?.length && some( menuItem.classes ) ) {
attributes.className = menuItem.classes.join( ' ' );
}

if ( menuItem.url ) {
attributes.url = menuItem.url;
}

const innerBlocks = menuItem.children?.length
? mapMenuItemsToBlocks( menuItem.children )
: [];

return createBlock( 'core/navigation-link', attributes, innerBlocks );
} );
}

Expand Down
15 changes: 11 additions & 4 deletions packages/editor/src/components/provider/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,23 @@ import ConvertToGroupButtons from '../convert-to-group-buttons';
* It seems like there is no suitable package to import this from. Ideally it would be either part of core-data.
* Until we refactor it, just copying the code is the simplest solution.
*
* @param {Object} search
* @param {number} perPage
* @param {string} search
* @param {Object} arguments
* @param {number} [arguments.perPage=20]
* @param {string} [arguments.type='post']
* @param {string} [arguments.subtype]
* @return {Promise<Object[]>} List of suggestions
*/
const fetchLinkSuggestions = async ( search, { perPage = 20 } = {} ) => {
const fetchLinkSuggestions = async (
search,
{ perPage = 20, type = 'post', subtype } = {}
) => {
const posts = await apiFetch( {
path: addQueryArgs( '/wp/v2/search', {
search,
per_page: perPage,
type: 'post',
type,
subtype,
} ),
} );

Expand Down

0 comments on commit b271299

Please sign in to comment.