UNPKG

@wordpress/block-library

Version:
174 lines (150 loc) 4.12 kB
/** * WordPress dependencies */ import { __, _x, sprintf } from '@wordpress/i18n'; import { useMemo, useState } from '@wordpress/element'; import { useDispatch, useSelect, useRegistry } from '@wordpress/data'; import { Button, FlexBlock, FlexItem, SelectControl, __experimentalHStack as HStack, __experimentalSpacer as Spacer, } from '@wordpress/components'; import { store as coreStore } from '@wordpress/core-data'; import { store as noticesStore } from '@wordpress/notices'; /** * Internal dependencies */ import { useCreateTemplatePartFromBlocks } from './utils/hooks'; import { transformWidgetToBlock } from './utils/transformers'; const SIDEBARS_QUERY = { per_page: -1, _fields: 'id,name,description,status,widgets', }; export function TemplatePartImportControls( { area, setAttributes } ) { const [ selectedSidebar, setSelectedSidebar ] = useState( '' ); const [ isBusy, setIsBusy ] = useState( false ); const registry = useRegistry(); const { sidebars, hasResolved } = useSelect( ( select ) => { const { getSidebars, hasFinishedResolution } = select( coreStore ); return { sidebars: getSidebars( SIDEBARS_QUERY ), hasResolved: hasFinishedResolution( 'getSidebars', [ SIDEBARS_QUERY, ] ), }; }, [] ); const { createErrorNotice } = useDispatch( noticesStore ); const createFromBlocks = useCreateTemplatePartFromBlocks( area, setAttributes ); const options = useMemo( () => { const sidebarOptions = ( sidebars ?? [] ) .filter( ( widgetArea ) => widgetArea.id !== 'wp_inactive_widgets' && widgetArea.widgets.length > 0 ) .map( ( widgetArea ) => { return { value: widgetArea.id, label: widgetArea.name, }; } ); if ( ! sidebarOptions.length ) { return []; } return [ { value: '', label: __( 'Select widget area' ) }, ...sidebarOptions, ]; }, [ sidebars ] ); // Render an empty node while data is loading to avoid SlotFill re-positioning bug. // See: https://github.com/WordPress/gutenberg/issues/15641. if ( ! hasResolved ) { return <Spacer marginBottom="0" />; } if ( hasResolved && ! options.length ) { return null; } async function createFromWidgets( event ) { event.preventDefault(); if ( isBusy || ! selectedSidebar ) { return; } setIsBusy( true ); const sidebar = options.find( ( { value } ) => value === selectedSidebar ); const { getWidgets } = registry.resolveSelect( coreStore ); // The widgets API always returns a successful response. const widgets = await getWidgets( { sidebar: sidebar.value, _embed: 'about', } ); const skippedWidgets = new Set(); const blocks = widgets.flatMap( ( widget ) => { const block = transformWidgetToBlock( widget ); // Skip the block if we have no matching transformations. if ( ! block ) { skippedWidgets.add( widget.id_base ); return []; } return block; } ); await createFromBlocks( blocks, /* translators: %s: name of the widget area */ sprintf( __( 'Widget area: %s' ), sidebar.label ) ); if ( skippedWidgets.size ) { createErrorNotice( sprintf( /* translators: %s: the list of widgets */ __( 'Unable to import the following widgets: %s.' ), Array.from( skippedWidgets ).join( ', ' ) ), { type: 'snackbar', } ); } setIsBusy( false ); } return ( <Spacer marginBottom="4"> <HStack as="form" onSubmit={ createFromWidgets }> <FlexBlock> <SelectControl label={ __( 'Import widget area' ) } value={ selectedSidebar } options={ options } onChange={ ( value ) => setSelectedSidebar( value ) } disabled={ ! options.length } __next40pxDefaultSize __nextHasNoMarginBottom /> </FlexBlock> <FlexItem style={ { marginBottom: '8px', marginTop: 'auto', } } > <Button __next40pxDefaultSize variant="primary" type="submit" isBusy={ isBusy } aria-disabled={ isBusy || ! selectedSidebar } > { _x( 'Import', 'button label' ) } </Button> </FlexItem> </HStack> </Spacer> ); }