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

Edit Site: Implement post switcher and integrate with "navigate to link". #22543

Merged
merged 7 commits into from
May 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

66 changes: 37 additions & 29 deletions packages/block-editor/src/components/link-control/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import {
Fragment,
useEffect,
createElement,
useMemo,
} from '@wordpress/element';
import {
safeDecodeURI,
Expand Down Expand Up @@ -143,6 +142,7 @@ const makeCancelable = ( promise ) => {
* @property {WPLinkControlValue=} value Current link value.
* @property {WPLinkControlOnChangeProp=} onChange Value change handler, called with the updated value if
* the user selects a new link or updates settings.
* @property {boolean=} noDirectEntry Whether to disable direct entries or not.
* @property {boolean=} showSuggestions Whether to present suggestions when typing the URL.
* @property {boolean=} showInitialSuggestions Whether to present initial suggestions immediately.
* @property {WPLinkControlCreateSuggestionProp=} createSuggestion Handler to manage creation of link value from suggestion.
Expand All @@ -156,9 +156,11 @@ const makeCancelable = ( promise ) => {
* @param {WPLinkControlProps} props Component props.
*/
function LinkControl( {
searchInputPlaceholder,
value,
settings,
onChange = noop,
noDirectEntry = false,
showSuggestions = true,
showInitialSuggestions,
forceIsEditingLink,
Expand Down Expand Up @@ -250,32 +252,34 @@ function LinkControl( {
setInputValue( val );
};

const handleDirectEntry = ( val ) => {
let type = 'URL';
const handleDirectEntry = noDirectEntry
? () => Promise.resolve( [] )
: ( val ) => {
let type = 'URL';

const protocol = getProtocol( val ) || '';
const protocol = getProtocol( val ) || '';

if ( protocol.includes( 'mailto' ) ) {
type = 'mailto';
}
if ( protocol.includes( 'mailto' ) ) {
type = 'mailto';
}

if ( protocol.includes( 'tel' ) ) {
type = 'tel';
}
if ( protocol.includes( 'tel' ) ) {
type = 'tel';
}

if ( startsWith( val, '#' ) ) {
type = 'internal';
}
if ( startsWith( val, '#' ) ) {
type = 'internal';
}

return Promise.resolve( [
{
id: val,
title: val,
url: type === 'URL' ? prependHTTP( val ) : val,
type,
},
] );
};
return Promise.resolve( [
{
id: val,
title: val,
url: type === 'URL' ? prependHTTP( val ) : val,
type,
},
] );
};

const handleEntitySearch = async ( val, args ) => {
let results = await Promise.all( [
Expand Down Expand Up @@ -408,7 +412,11 @@ function LinkControl( {

const handleSelectSuggestion = ( suggestion, _value = {} ) => {
setIsEditingLink( false );
onChange( { ..._value, ...suggestion } );
const __value = { ..._value };
// Some direct entries don't have types or IDs, and we still need to clear the previous ones.
delete __value.type;
delete __value.id;
onChange( { ...__value, ...suggestion } );
};

// Render Components
Expand Down Expand Up @@ -530,10 +538,6 @@ function LinkControl( {
);
};

const viewerSlotFillProps = useMemo(
() => ( { url: value && value.url } ),
[ value && value.url ]
);
return (
noahtallen marked this conversation as resolved.
Show resolved Hide resolved
<div
tabIndex={ -1 }
Expand All @@ -548,12 +552,16 @@ function LinkControl( {

{ ( isEditingLink || ! value ) && ! isResolvingLink && (
<LinkControlSearchInput
placeholder={ searchInputPlaceholder }
value={ inputValue }
onChange={ onInputChange }
onSelect={ async ( suggestion ) => {
if ( CREATE_TYPE === suggestion.type ) {
await handleOnCreate( inputValue );
} else {
} else if (
! noDirectEntry ||
Object.keys( suggestion ).length > 1
) {
handleSelectSuggestion( suggestion, value );
stopEditing();
}
Expand Down Expand Up @@ -600,7 +608,7 @@ function LinkControl( {
>
{ __( 'Edit' ) }
</Button>
<ViewerSlot fillProps={ viewerSlotFillProps } />
<ViewerSlot fillProps={ value } />
</div>
</Fragment>
) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { keyboardReturn } from '@wordpress/icons';
import { URLInput } from '../';

const LinkControlSearchInput = ( {
placeholder,
value,
onChange,
onSelect,
Expand Down Expand Up @@ -50,7 +51,7 @@ const LinkControlSearchInput = ( {
className="block-editor-link-control__search-input"
value={ value }
onChange={ selectItemHandler }
placeholder={ __( 'Search or type url' ) }
placeholder={ placeholder ?? __( 'Search or type url' ) }
__experimentalRenderSuggestions={ renderSuggestions }
__experimentalFetchLinkSuggestions={ fetchSuggestions }
__experimentalHandleURLSuggestions={ true }
Expand Down
11 changes: 7 additions & 4 deletions packages/core-data/src/entity-provider.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
createContext,
useContext,
useCallback,
useEffect,
useMemo,
} from '@wordpress/element';
import { useSelect, useDispatch } from '@wordpress/data';
Expand Down Expand Up @@ -156,20 +157,22 @@ export function useEntityBlockEditor(
);

const { editEntityRecord } = useDispatch( 'core' );
const initialBlocks = useMemo( () => {
useEffect( () => {
if ( initialEdits ) {
editEntityRecord( kind, type, id, initialEdits, {
undoIgnore: true,
} );
}

}, [ id ] );
const initialBlocks = useMemo( () => {
// Guard against other instances that might have
// set content to a function already.
if ( typeof content !== 'function' ) {
if ( content && typeof content !== 'function' ) {
const parsedContent = parse( content );
return parsedContent.length ? parsedContent : [];
}
}, [ id ] ); // Reset when the provided entity record changes.
return [];
}, [ content ] );
const [ blocks = initialBlocks, onInput ] = useEntityProp(
kind,
type,
Expand Down
2 changes: 2 additions & 0 deletions packages/edit-site/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
],
"dependencies": {
"@babel/runtime": "^7.9.2",
"@wordpress/api-fetch": "file:../api-fetch",
"@wordpress/block-editor": "file:../block-editor",
"@wordpress/block-library": "file:../block-library",
"@wordpress/blocks": "file:../blocks",
Expand All @@ -35,6 +36,7 @@
"@wordpress/editor": "file:../editor",
"@wordpress/element": "file:../element",
"@wordpress/hooks": "file:../hooks",
"@wordpress/html-entities": "file:../html-entities",
"@wordpress/i18n": "file:../i18n",
"@wordpress/icons": "file:../icons",
"@wordpress/interface": "file:../interface",
Expand Down
16 changes: 9 additions & 7 deletions packages/edit-site/src/components/block-editor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,12 @@ export default function BlockEditor() {
'postType',
settings.templateType
);

const setActiveTemplateId = useCallback(
( newTemplateId ) =>
const setActivePageAndTemplateId = useCallback(
( { page, templateId } ) =>
setSettings( ( prevSettings ) => ( {
...prevSettings,
templateId: newTemplateId,
page,
noahtallen marked this conversation as resolved.
Show resolved Hide resolved
templateId,
templateType: 'wp_template',
} ) ),
[]
Expand All @@ -89,11 +89,13 @@ export default function BlockEditor() {
( fillProps ) => (
<NavigateToLink
{ ...fillProps }
activeId={ settings.templateId }
onActiveIdChange={ setActiveTemplateId }
activePage={ settings.page }
onActivePageAndTemplateIdChange={
setActivePageAndTemplateId
}
/>
),
[ settings.templateId, setActiveTemplateId ]
[ settings.page, setActivePageAndTemplateId ]
) }
</__experimentalLinkControl.ViewerFill>
<Sidebar.InspectorFill>
Expand Down
1 change: 1 addition & 0 deletions packages/edit-site/src/components/header/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ export default function Header( {
...prevSettings,
page: newPage,
templateId: newTemplateId,
templateType: 'wp_template',
} ) );
}
} catch ( err ) {}
Expand Down
64 changes: 47 additions & 17 deletions packages/edit-site/src/components/navigate-to-link/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/**
* WordPress dependencies
*/
import { getPath, getQueryString, addQueryArgs } from '@wordpress/url';
import { useState, useEffect, useMemo } from '@wordpress/element';
import { addQueryArgs } from '@wordpress/url';
import { select } from '@wordpress/data';
import { __experimentalResolveSelect as resolveSelect } from '@wordpress/data';
import { Button } from '@wordpress/components';
import { __ } from '@wordpress/i18n';

Expand All @@ -12,7 +12,22 @@ import { __ } from '@wordpress/i18n';
*/
const { fetch } = window;

export default function NavigateToLink( { url, activeId, onActiveIdChange } ) {
function getPathFromLink( link ) {
// TODO: Explore abstracting this into `@wordpress/url`.
const path = getPath( link );
const queryString = getQueryString( link );
let value = '/';
if ( path ) value += path;
if ( queryString ) value += `?${ queryString }`;
return value;
}
export default function NavigateToLink( {
url,
type,
id,
activePage,
onActivePageAndTemplateIdChange,
} ) {
const [ templateId, setTemplateId ] = useState();
useEffect( () => {
const effect = async () => {
Expand All @@ -23,15 +38,16 @@ export default function NavigateToLink( { url, activeId, onActiveIdChange } ) {
if ( success ) {
let newTemplateId = data.ID;
if ( newTemplateId === null ) {
const { getEntityRecords } = select( 'core' );
newTemplateId = getEntityRecords(
'postType',
'wp_template',
{
resolved: true,
slug: data.post_name,
}
)[ 0 ].id;
newTemplateId = (
noahtallen marked this conversation as resolved.
Show resolved Hide resolved
await resolveSelect( 'core' ).getEntityRecords(
'postType',
'wp_template',
{
resolved: true,
slug: data.post_name,
}
)
)[ 0 ].id;
}
setTemplateId( newTemplateId );
} else {
Expand All @@ -44,11 +60,25 @@ export default function NavigateToLink( { url, activeId, onActiveIdChange } ) {
effect();
}, [ url ] );
const onClick = useMemo( () => {
if ( ! templateId || templateId === activeId ) {
return null;
}
return () => onActiveIdChange( templateId );
}, [ templateId, activeId, onActiveIdChange ] );
if ( ! templateId || ! type || ! id || type === 'URL' ) return null;
const path = getPathFromLink( url );
if ( path === activePage.path ) return null;
return () =>
onActivePageAndTemplateIdChange( {
page: {
path,
context: { postType: type, postId: id },
},
templateId,
} );
}, [
templateId,
type,
id,
getPathFromLink,
url,
onActivePageAndTemplateIdChange,
] );
return (
onClick && (
<Button
Expand Down
Loading