Skip to content

Commit

Permalink
Site Editor: Add Dropdown to Create Generic Templates (#26284)
Browse files Browse the repository at this point in the history
Add a very basic interface to create generic templates from the Site Editor navigation sidebar.
Clicking on the + button will open a dropdown listing all missing generic templates, filling them with the hierarchically closest template content, plus a "General" template that creates a blank template.
  • Loading branch information
Copons committed Oct 23, 2020
1 parent 4aae879 commit 9518819
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 13 deletions.
4 changes: 3 additions & 1 deletion packages/components/src/navigation/menu/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,12 @@ export default function NavigationMenu( props ) {
className,
hasSearch,
menu = ROOT_MENU,
onBackButtonClick,
onSearch: setControlledSearch,
parentMenu,
search: controlledSearch,
title,
onBackButtonClick,
titleAction,
} = props;
const [ uncontrolledSearch, setUncontrolledSearch ] = useState( '' );
useNavigationTreeMenu( props );
Expand Down Expand Up @@ -76,6 +77,7 @@ export default function NavigationMenu( props ) {
onSearch={ onSearch }
search={ search }
title={ title }
titleAction={ titleAction }
/>

<NavigableMenu>
Expand Down
33 changes: 22 additions & 11 deletions packages/components/src/navigation/menu/menu-title.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ import { Icon, search as searchIcon } from '@wordpress/icons';
import Animate from '../../animate';
import Button from '../../button';
import MenuTitleSearch from './menu-title-search';
import { MenuTitleHeadingUI, MenuTitleUI } from '../styles/navigation-styles';
import {
MenuTitleActionsUI,
MenuTitleHeadingUI,
MenuTitleUI,
} from '../styles/navigation-styles';
import { useNavigationMenuContext } from './context';
import { SEARCH_FOCUS_DELAY } from '../constants';

Expand All @@ -20,6 +24,7 @@ export default function NavigationMenuTitle( {
onSearch,
search,
title,
titleAction,
} ) {
const [ isSearching, setIsSearching ] = useState( false );
const { menu } = useNavigationMenuContext();
Expand Down Expand Up @@ -53,16 +58,22 @@ export default function NavigationMenuTitle( {
>
<span id={ menuTitleId }>{ title }</span>

{ hasSearch && (
<Button
isSmall
isTertiary
label={ searchButtonLabel }
onClick={ () => setIsSearching( true ) }
ref={ searchButtonRef }
>
<Icon icon={ searchIcon } />
</Button>
{ ( hasSearch || titleAction ) && (
<MenuTitleActionsUI>
{ titleAction }

{ hasSearch && (
<Button
isSmall
isTertiary
label={ searchButtonLabel }
onClick={ () => setIsSearching( true ) }
ref={ searchButtonRef }
>
<Icon icon={ searchIcon } />
</Button>
) }
</MenuTitleActionsUI>
) }
</MenuTitleHeadingUI>
) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ export const MenuTitleHeadingUI = styled( Text )`
justify-content: space-between;
margin-bottom: ${ space( 1 ) };
padding: ${ space( 0.5 ) } 0 ${ space( 0.5 ) } ${ space( 2 ) };
`;

export const MenuTitleActionsUI = styled.span`
height: ${ space( 3 ) }; // 24px, same height as the buttons inside
.components-button.is-small {
color: ${ G2.lightGray.ui };
Expand All @@ -84,7 +88,7 @@ export const MenuTitleSearchUI = styled.div`
position: relative;
input {
height: 36px; // Same height as MenuTitle
height: ${ space( 4.5 ) }; // 36px, same height as MenuTitle
margin-bottom: ${ space( 1 ) };
padding-left: 30px; // Leave room for the search icon
padding-right: 30px; // Leave room for the close search button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
} from '../constants';
import { useSelect } from '@wordpress/data';
import TemplatesAllMenu from './templates-all';
import NewTemplateDropdown from '../new-template-dropdown';

export default function TemplatesMenu( { onActivateItem } ) {
const templates = useSelect(
Expand All @@ -42,6 +43,7 @@ export default function TemplatesMenu( { onActivateItem } ) {
<NavigationMenu
menu={ MENU_TEMPLATES }
title={ __( 'Templates' ) }
titleAction={ <NewTemplateDropdown /> }
parentMenu={ MENU_ROOT }
>
<NavigationItem
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/**
* External dependencies
*/
import { map, omit } from 'lodash';

/**
* WordPress dependencies
*/
import {
DropdownMenu,
MenuGroup,
MenuItem,
NavigableMenu,
} from '@wordpress/components';
import { useDispatch, useSelect } from '@wordpress/data';
import { __ } from '@wordpress/i18n';
import { Icon, plus } from '@wordpress/icons';

/**
* Internal dependencies
*/
import getClosestAvailableTemplate from '../../../utils/get-closest-available-template';
import { TEMPLATES_DEFAULT_DETAILS } from '../../../utils/get-template-info/constants';

export default function NewTemplateDropdown() {
const templates = useSelect(
( select ) =>
select( 'core' ).getEntityRecords( 'postType', 'wp_template', {
status: [ 'publish', 'auto-draft' ],
per_page: -1,
} ),
[]
);
const { addTemplate } = useDispatch( 'core/edit-site' );

const createTemplate = ( slug ) => {
const closestAvailableTemplate = getClosestAvailableTemplate(
slug,
templates
);
addTemplate( {
content: closestAvailableTemplate.content.raw,
slug,
title: slug,
status: 'draft',
} );
};

const missingTemplates = omit(
TEMPLATES_DEFAULT_DETAILS,
map( templates, 'slug' )
);

return (
<DropdownMenu
className="edit-site-navigation-panel__new-template-dropdown"
icon={ null }
label={ __( 'Add Template' ) }
popoverProps={ {
noArrow: false,
} }
toggleProps={ {
children: <Icon icon={ plus } />,
isSmall: true,
isTertiary: true,
} }
>
{ ( { onClose } ) => (
<NavigableMenu>
<MenuGroup label={ __( 'Add Template' ) }>
{ map(
missingTemplates,
( { title, description }, slug ) => (
<MenuItem
info={ description }
key={ slug }
onClick={ () => {
createTemplate( slug );
onClose();
} }
>
{ title }
</MenuItem>
)
) }
</MenuGroup>
</NavigableMenu>
) }
</DropdownMenu>
);
}
23 changes: 23 additions & 0 deletions packages/edit-site/src/utils/get-closest-available-template.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* External dependencies
*/
import { find } from 'lodash';

export default function getClosestAvailableTemplate( slug, templates ) {
if ( 'front-page' === slug ) {
const homeTemplate = find( templates, { slug: 'home' } );
if ( homeTemplate ) {
return homeTemplate;
}
}

if ( 'single' === slug || 'page' === slug ) {
const singularTemplate = find( templates, { slug: 'singular' } );
if ( singularTemplate ) {
return singularTemplate;
}
}

const indexTemplate = find( templates, { slug: 'index' } );
return indexTemplate;
}

0 comments on commit 9518819

Please sign in to comment.