@wordpress/block-library
Version:
Block library for the WordPress editor.
181 lines (165 loc) • 4.54 kB
JavaScript
/**
* WordPress dependencies
*/
import {
Button,
TextControl,
Notice,
CheckboxControl,
__experimentalVStack as VStack,
__experimentalHStack as HStack,
} from '@wordpress/components';
import { __, sprintf } from '@wordpress/i18n';
import { useSelect, useDispatch } from '@wordpress/data';
import { store as coreStore } from '@wordpress/core-data';
import { store as noticesStore } from '@wordpress/notices';
import { decodeEntities } from '@wordpress/html-entities';
import { useState } from '@wordpress/element';
/**
* Internal dependencies
*/
import DialogWrapper from './dialog-wrapper';
/**
* Component for creating new pages within the Navigation Link UI.
*
* @param {Object} props Component props.
* @param {string} props.postType The post type to create.
* @param {Function} props.onBack Callback when user wants to go back.
* @param {Function} props.onPageCreated Callback when page is successfully created.
* @param {string} [props.initialTitle] Initial title to pre-fill the form.
*/
export function LinkUIPageCreator( {
postType,
onBack,
onPageCreated,
initialTitle = '',
} ) {
const [ title, setTitle ] = useState( initialTitle );
const [ shouldPublish, setShouldPublish ] = useState( false );
// Check if the title is valid for submission
const isTitleValid = title.trim().length > 0;
// Get the last created entity record (without ID) to track creation state
const { lastError, isSaving } = useSelect(
( select ) => ( {
lastError: select( coreStore ).getLastEntitySaveError(
'postType',
postType
),
isSaving: select( coreStore ).isSavingEntityRecord(
'postType',
postType
),
} ),
[ postType ]
);
const { saveEntityRecord } = useDispatch( coreStore );
const { createSuccessNotice, createErrorNotice } =
useDispatch( noticesStore );
async function createPage( event ) {
event.preventDefault();
if ( isSaving || ! isTitleValid ) {
return;
}
try {
const savedRecord = await saveEntityRecord(
'postType',
postType,
{
title,
status: shouldPublish ? 'publish' : 'draft',
},
{ throwOnError: true }
);
if ( savedRecord ) {
// Create the page link object from the saved record
const pageLink = {
id: savedRecord.id,
type: postType,
title: decodeEntities( savedRecord.title.rendered ),
url: savedRecord.link,
kind: 'post-type',
};
// Show success notice
createSuccessNotice(
sprintf(
// translators: %s: the name of the new page being created.
__( '%s page created successfully.' ),
decodeEntities( savedRecord.title.rendered )
),
{
type: 'snackbar',
id: 'page-created-success',
}
);
onPageCreated( pageLink );
}
} catch ( error ) {
// Show error notice
createErrorNotice(
__( 'Failed to create page. Please try again.' ),
{
type: 'snackbar',
id: 'page-created-error',
}
);
}
}
const isSubmitDisabled = isSaving || ! isTitleValid;
return (
<DialogWrapper
className="link-ui-page-creator"
title={ __( 'Create page' ) }
description={ __( 'Create a new page to add to your Navigation.' ) }
onBack={ onBack }
>
<VStack className="link-ui-page-creator__inner" spacing={ 4 }>
<form onSubmit={ createPage }>
<VStack spacing={ 4 }>
<TextControl
__next40pxDefaultSize
__nextHasNoMarginBottom
label={ __( 'Title' ) }
onChange={ setTitle }
placeholder={ __( 'No title' ) }
value={ title }
/>
<CheckboxControl
__nextHasNoMarginBottom
label={ __( 'Publish immediately' ) }
help={ __(
'If unchecked, the page will be created as a draft.'
) }
checked={ shouldPublish }
onChange={ setShouldPublish }
/>
{ lastError && (
<Notice status="error" isDismissible={ false }>
{ lastError.message }
</Notice>
) }
<HStack spacing={ 2 } justify="flex-end">
<Button
__next40pxDefaultSize
variant="tertiary"
onClick={ onBack }
disabled={ isSaving }
accessibleWhenDisabled
>
{ __( 'Cancel' ) }
</Button>
<Button
__next40pxDefaultSize
variant="primary"
type="submit"
isBusy={ isSaving }
aria-disabled={ isSubmitDisabled }
>
{ __( 'Create page' ) }
</Button>
</HStack>
</VStack>
</form>
</VStack>
</DialogWrapper>
);
}