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

Add success and error snackbars to the templates list page #36808

Merged
merged 12 commits into from Nov 26, 2021
11 changes: 1 addition & 10 deletions package-lock.json

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

1 change: 1 addition & 0 deletions packages/edit-site/package.json
Expand Up @@ -52,6 +52,7 @@
"@wordpress/primitives": "file:../primitives",
"@wordpress/reusable-blocks": "file:../reusable-blocks",
"@wordpress/url": "file:../url",
"@wordpress/viewport": "file:../viewport",
"classnames": "^2.3.1",
"downloadjs": "^1.4.7",
"file-saver": "^2.0.2",
Expand Down
Expand Up @@ -7,9 +7,12 @@ import { kebabCase } from 'lodash';
* WordPress dependencies
*/
import { useState } from '@wordpress/element';
import { useDispatch } from '@wordpress/data';
import { Button } from '@wordpress/components';
import { addQueryArgs } from '@wordpress/url';
import apiFetch from '@wordpress/api-fetch';
import { __, sprintf } from '@wordpress/i18n';
import { store as noticesStore } from '@wordpress/notices';

/**
* Internal dependencies
Expand All @@ -18,31 +21,54 @@ import CreateTemplatePartModal from '../create-template-part-modal';

export default function NewTemplatePart( { postType } ) {
const [ isModalOpen, setIsModalOpen ] = useState( false );
const { createSuccessNotice, createErrorNotice } = useDispatch(
noticesStore
);

async function createTemplatePart( { title, area } ) {
if ( ! title ) {
createErrorNotice( __( 'Title is not defined.' ), {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would this happen? 🙂 I guess it's okay to leave it just in case.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it will never happen for regular users. Maybe we should just remove this check altogether.

type: 'snackbar',
} );
return;
}

const templatePart = await apiFetch( {
path: '/wp/v2/template-parts',
method: 'POST',
data: {
slug: kebabCase( title ),
title,
content: '',
area,
},
} );
try {
const templatePart = await apiFetch( {
path: '/wp/v2/template-parts',
method: 'POST',
data: {
slug: kebabCase( title ),
title,
content: '',
area,
},
} );

createSuccessNotice(
sprintf(
/* translators: The template part title. */
__( '"%s" created! Navigating to the editor…' ),
talldan marked this conversation as resolved.
Show resolved Hide resolved
title
),
{
type: 'snackbar',
}
);

// Navigate to the created template part editor.
window.location.href = addQueryArgs( window.location.href, {
postId: templatePart.id,
postType: 'wp_template_part',
} );
// Navigate to the created template part editor.
window.location.href = addQueryArgs( window.location.href, {
postId: templatePart.id,
postType: 'wp_template_part',
} );
} catch ( error ) {
const errorMessage =
error.message && error.code !== 'unknown_error'
? error.message
: __( 'Creating failed.' );
kevin940726 marked this conversation as resolved.
Show resolved Hide resolved

// Wait for async navigation to happen before closing the modal.
await new Promise( () => {} );
createErrorNotice( errorMessage, { type: 'snackbar' } );
}
}

return (
Expand Down
59 changes: 41 additions & 18 deletions packages/edit-site/src/components/add-new-template/new-template.js
Expand Up @@ -12,11 +12,13 @@ import {
MenuItem,
NavigableMenu,
} from '@wordpress/components';
import { useSelect } from '@wordpress/data';
import { useSelect, useDispatch } from '@wordpress/data';
import { store as coreStore } from '@wordpress/core-data';
import { store as editorStore } from '@wordpress/editor';
import { addQueryArgs } from '@wordpress/url';
import apiFetch from '@wordpress/api-fetch';
import { __ } from '@wordpress/i18n';
import { store as noticesStore } from '@wordpress/notices';

const DEFAULT_TEMPLATE_SLUGS = [
'front-page',
Expand All @@ -42,27 +44,48 @@ export default function NewTemplate( { postType } ) {
} ),
[]
);
const { createSuccessNotice, createErrorNotice } = useDispatch(
noticesStore
);

async function createTemplate( { slug } ) {
const { title, description } = find( defaultTemplateTypes, { slug } );
try {
const { title, description } = find( defaultTemplateTypes, {
slug,
} );

const template = await apiFetch( {
path: '/wp/v2/templates',
method: 'POST',
data: {
excerpt: description,
// Slugs need to be strings, so this is for template `404`
slug: slug.toString(),
status: 'publish',
title,
},
} );

createSuccessNotice(
__( 'Template created! Navigating to the editor…' ),
{ type: 'snackbar' }
);

const template = await apiFetch( {
path: '/wp/v2/templates',
method: 'POST',
data: {
excerpt: description,
// Slugs need to be strings, so this is for template `404`
slug: slug.toString(),
status: 'publish',
title,
},
} );
// Navigate to the created template editor.
window.location.href = addQueryArgs( window.location.href, {
postId: template.id,
postType: 'wp_template',
} );
} catch ( error ) {
const errorMessage =
error.message && error.code !== 'unknown_error'
? error.message
: __( 'Creating failed.' );
kevin940726 marked this conversation as resolved.
Show resolved Hide resolved

// Navigate to the created template editor.
window.location.href = addQueryArgs( window.location.href, {
postId: template.id,
postType: 'wp_template',
} );
createErrorNotice( errorMessage, {
type: 'snackbar',
} );
}
}

const existingTemplateSlugs = map( templates, 'slug' );
Expand Down
42 changes: 32 additions & 10 deletions packages/edit-site/src/components/list/index.js
@@ -1,3 +1,8 @@
/**
* External dependencies
*/
import classnames from 'classnames';

/**
* WordPress dependencies
*/
Expand All @@ -6,6 +11,7 @@ import { useSelect } from '@wordpress/data';
import { InterfaceSkeleton } from '@wordpress/interface';
import { __, sprintf } from '@wordpress/i18n';
import { store as keyboardShortcutsStore } from '@wordpress/keyboard-shortcuts';
import { EditorSnackbars } from '@wordpress/editor';

/**
* Internal dependencies
Expand All @@ -14,20 +20,27 @@ import useRegisterShortcuts from './use-register-shortcuts';
import Header from './header';
import NavigationSidebar from '../navigation-sidebar';
import Table from './table';
import { store as editSiteStore } from '../../store';

export default function List( { templateType } ) {
useRegisterShortcuts();

const { previousShortcut, nextShortcut } = useSelect( ( select ) => {
return {
previousShortcut: select(
keyboardShortcutsStore
).getAllShortcutKeyCombinations( 'core/edit-site/previous-region' ),
nextShortcut: select(
keyboardShortcutsStore
).getAllShortcutKeyCombinations( 'core/edit-site/next-region' ),
};
}, [] );
const { previousShortcut, nextShortcut, isNavigationOpen } = useSelect(
( select ) => {
return {
previousShortcut: select(
keyboardShortcutsStore
).getAllShortcutKeyCombinations(
'core/edit-site/previous-region'
),
nextShortcut: select(
keyboardShortcutsStore
).getAllShortcutKeyCombinations( 'core/edit-site/next-region' ),
isNavigationOpen: select( editSiteStore ).isNavigationOpened(),
};
},
[]
);

const postType = useSelect(
( select ) => select( coreStore ).getPostType( templateType ),
Expand Down Expand Up @@ -66,6 +79,15 @@ export default function List( { templateType } ) {
isDefaultOpen
/>
}
notices={
<div
className={ classnames( 'edit-site-list-snackbars', {
'is-navigation-open': isNavigationOpen,
kevin940726 marked this conversation as resolved.
Show resolved Hide resolved
} ) }
>
<EditorSnackbars />
</div>
}
content={
<main className="edit-site-list-main">
<Table templateType={ templateType } />
Expand Down
6 changes: 6 additions & 0 deletions packages/edit-site/src/components/list/style.scss
Expand Up @@ -114,3 +114,9 @@
border-top: none;
}
}

.edit-site-list-snackbars.is-navigation-open .components-snackbar-list {
@include break-medium() {
margin-left: $nav-sidebar-width;
}
}
25 changes: 9 additions & 16 deletions packages/edit-site/src/components/navigation-sidebar/index.js
@@ -1,13 +1,15 @@
/**
* WordPress dependencies
*/
import { useEffect, useState } from '@wordpress/element';
import { useEffect } from '@wordpress/element';
import { createSlotFill } from '@wordpress/components';
import { useViewportMatch } from '@wordpress/compose';
import { useDispatch } from '@wordpress/data';

/**
* Internal dependencies
*/
import { store as editSiteStore } from '../../store';
import NavigationPanel from './navigation-panel';
import NavigationToggle from './navigation-toggle';

Expand All @@ -21,33 +23,24 @@ export default function NavigationSidebar( {
activeTemplateType,
} ) {
const isDesktopViewport = useViewportMatch( 'medium' );
const [ isNavigationOpen, setIsNavigationOpen ] = useState(
isDefaultOpen && isDesktopViewport
);
const { setIsNavigationPanelOpened } = useDispatch( editSiteStore );

useEffect( () => {
// When transitioning to desktop open the navigation if `isDefaultOpen` is true.
if ( isDefaultOpen && isDesktopViewport ) {
setIsNavigationOpen( true );
setIsNavigationPanelOpened( true );
}

// When transitioning to mobile/tablet, close the navigation.
if ( ! isDesktopViewport ) {
setIsNavigationOpen( false );
setIsNavigationPanelOpened( false );
}
}, [ isDefaultOpen, isDesktopViewport ] );
}, [ isDefaultOpen, isDesktopViewport, setIsNavigationPanelOpened ] );

return (
<>
<NavigationToggle
isOpen={ isNavigationOpen }
setIsOpen={ setIsNavigationOpen }
/>
<NavigationPanel
isOpen={ isNavigationOpen }
setIsOpen={ setIsNavigationOpen }
activeItem={ activeTemplateType }
/>
<NavigationToggle />
<NavigationPanel activeItem={ activeTemplateType } />
<NavigationPanelPreviewSlot />
</>
);
Expand Down