diff --git a/packages/editor/src/components/post-comments/index.js b/packages/editor/src/components/post-comments/index.js index 85d9948575d05..694655092237c 100644 --- a/packages/editor/src/components/post-comments/index.js +++ b/packages/editor/src/components/post-comments/index.js @@ -2,7 +2,11 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { CheckboxControl } from '@wordpress/components'; +import { + RadioControl, + __experimentalText as Text, + __experimentalVStack as VStack, +} from '@wordpress/components'; import { useDispatch, useSelect } from '@wordpress/data'; /** @@ -10,6 +14,34 @@ import { useDispatch, useSelect } from '@wordpress/data'; */ import { store as editorStore } from '../../store'; +const COMMENT_OPTIONS = [ + { + label: ( + <> + { __( 'Open' ) } + + { __( 'Visitors can add new comments and replies.' ) } + + + ), + value: 'open', + }, + { + label: ( + <> + { __( 'Closed' ) } + + { __( 'Visitors cannot add new comments or replies.' ) } + + + { __( 'Existing comments remain visible.' ) } + + + ), + value: 'closed', + }, +]; + function PostComments() { const commentStatus = useSelect( ( select ) => @@ -18,18 +50,24 @@ function PostComments() { [] ); const { editPost } = useDispatch( editorStore ); - const onToggleComments = () => + const handleStatus = ( newCommentStatus ) => editPost( { - comment_status: commentStatus === 'open' ? 'closed' : 'open', + comment_status: newCommentStatus, } ); return ( - +
+ + + +
); } diff --git a/packages/editor/src/components/post-discussion/panel.js b/packages/editor/src/components/post-discussion/panel.js index 6ff022a2b8b52..f829ed01eebb9 100644 --- a/packages/editor/src/components/post-discussion/panel.js +++ b/packages/editor/src/components/post-discussion/panel.js @@ -2,8 +2,16 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { PanelBody, PanelRow } from '@wordpress/components'; -import { useDispatch, useSelect } from '@wordpress/data'; +import { + Dropdown, + Button, + __experimentalVStack as VStack, + __experimentalText as Text, +} from '@wordpress/components'; +import { useSelect } from '@wordpress/data'; +import { useState, useMemo } from '@wordpress/element'; +import { __experimentalInspectorPopoverHeader as InspectorPopoverHeader } from '@wordpress/block-editor'; +import { store as coreStore } from '@wordpress/core-data'; /** * Internal dependencies @@ -12,50 +20,119 @@ import { store as editorStore } from '../../store'; import PostTypeSupportCheck from '../post-type-support-check'; import PostComments from '../post-comments'; import PostPingbacks from '../post-pingbacks'; +import PostPanelRow from '../post-panel-row'; const PANEL_NAME = 'discussion-panel'; -function DiscussionPanel() { - const { isEnabled, isOpened } = useSelect( ( select ) => { - const { isEditorPanelEnabled, isEditorPanelOpened } = - select( editorStore ); +function ModalContents( { onClose } ) { + return ( +
+ + + + + + + + + +
+ ); +} + +function PostDiscussionToggle( { isOpen, onClick } ) { + const { + commentStatus, + pingStatus, + commentsSupported, + trackbacksSupported, + } = useSelect( ( select ) => { + const { getEditedPostAttribute } = select( editorStore ); + const { getPostType } = select( coreStore ); + const postType = getPostType( getEditedPostAttribute( 'type' ) ); return { - isEnabled: isEditorPanelEnabled( PANEL_NAME ), - isOpened: isEditorPanelOpened( PANEL_NAME ), + commentStatus: getEditedPostAttribute( 'comment_status' ) ?? 'open', + pingStatus: getEditedPostAttribute( 'ping_status' ) ?? 'open', + commentsSupported: !! postType.supports.comments, + trackbacksSupported: !! postType.supports.trackbacks, }; }, [] ); - - const { toggleEditorPanelOpened } = useDispatch( editorStore ); - - if ( ! isEnabled ) { - return null; + let label; + if ( commentStatus === 'open' ) { + if ( pingStatus === 'open' ) { + label = __( 'Open' ); + } else { + label = trackbacksSupported ? __( 'Comments only' ) : __( 'Open' ); + } + } else if ( pingStatus === 'open' ) { + label = commentsSupported ? __( 'Pings only' ) : __( 'Pings enabled' ); + } else { + label = __( 'Closed' ); } - return ( - toggleEditorPanelOpened( PANEL_NAME ) } + ); } export default function PostDiscussionPanel() { + const { isEnabled } = useSelect( ( select ) => { + const { isEditorPanelEnabled } = select( editorStore ); + return { + isEnabled: isEditorPanelEnabled( PANEL_NAME ), + }; + }, [] ); + + // Use internal state instead of a ref to make sure that the component + // re-renders when the popover's anchor updates. + const [ popoverAnchor, setPopoverAnchor ] = useState( null ); + // Memoize popoverProps to avoid returning a new object every time. + const popoverProps = useMemo( + () => ( { + // Anchor the popover to the middle of the entire row so that it doesn't + // move around when the label changes. + anchor: popoverAnchor, + placement: 'left-start', + offset: 36, + shift: true, + } ), + [ popoverAnchor ] + ); + + if ( ! isEnabled ) { + return null; + } + return ( - + + ( + + ) } + renderContent={ ( { onClose } ) => ( + + ) } + /> + ); } diff --git a/packages/editor/src/components/post-discussion/style.scss b/packages/editor/src/components/post-discussion/style.scss new file mode 100644 index 0000000000000..b1eae85140285 --- /dev/null +++ b/packages/editor/src/components/post-discussion/style.scss @@ -0,0 +1,26 @@ +.editor-post-discussion__panel-dialog .editor-post-discussion { + // sidebar width - popover padding - form margin + min-width: $sidebar-width - $grid-unit-20 - $grid-unit-20; + margin: $grid-unit-10; + + .components-radio-control__option { + align-items: flex-start; + } + + .components-radio-control__label .components-text { + display: block; + margin-top: $grid-unit-05; + } +} +.editor-post-discussion__panel-toggle { + &.components-button { + height: auto; + } + .components-text { + color: inherit; + } +} + +.editor-post-discussion__panel-dialog .components-popover__content { + min-width: 320px; +} diff --git a/packages/editor/src/components/post-pingbacks/index.js b/packages/editor/src/components/post-pingbacks/index.js index d6e1c419ee6f9..832088b86364a 100644 --- a/packages/editor/src/components/post-pingbacks/index.js +++ b/packages/editor/src/components/post-pingbacks/index.js @@ -2,7 +2,7 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { CheckboxControl } from '@wordpress/components'; +import { CheckboxControl, ExternalLink } from '@wordpress/components'; import { useDispatch, useSelect } from '@wordpress/data'; /** @@ -26,9 +26,18 @@ function PostPingbacks() { return ( + { __( 'Learn more about pingbacks & trackbacks' ) } + + } /> ); } diff --git a/packages/editor/src/components/sidebar/index.js b/packages/editor/src/components/sidebar/index.js index be516d5b51ee6..30d27a8c5db30 100644 --- a/packages/editor/src/components/sidebar/index.js +++ b/packages/editor/src/components/sidebar/index.js @@ -26,7 +26,6 @@ import PageAttributesPanel from '../page-attributes/panel'; import PatternOverridesPanel from '../pattern-overrides-panel'; import PluginDocumentSettingPanel from '../plugin-document-setting-panel'; import PluginSidebar from '../plugin-sidebar'; -import PostDiscussionPanel from '../post-discussion/panel'; import PostLastRevisionPanel from '../post-last-revision/panel'; import PostSummary from './post-summary'; import PostTaxonomiesPanel from '../post-taxonomies/panel'; @@ -120,7 +119,6 @@ const SidebarContent = ( { - { extraPanels } diff --git a/packages/editor/src/components/sidebar/post-summary.js b/packages/editor/src/components/sidebar/post-summary.js index a2d5a7cba18cb..807ff25c2d9ff 100644 --- a/packages/editor/src/components/sidebar/post-summary.js +++ b/packages/editor/src/components/sidebar/post-summary.js @@ -12,6 +12,7 @@ import PostActions from '../post-actions'; import PostAuthorPanel from '../post-author/panel'; import PostCardPanel from '../post-card-panel'; import PostContentInformation from '../post-content-information'; +import PostDiscussionPanel from '../post-discussion/panel'; import { PrivatePostExcerptPanel as PostExcerptPanel } from '../post-excerpt/panel'; import PostFeaturedImagePanel from '../post-featured-image/panel'; import PostFormatPanel from '../post-format/panel'; @@ -80,6 +81,7 @@ export default function PostSummary( { onActionPerformed } ) { + diff --git a/packages/editor/src/style.scss b/packages/editor/src/style.scss index 42597de342efa..c7d4aae8d8f43 100644 --- a/packages/editor/src/style.scss +++ b/packages/editor/src/style.scss @@ -18,6 +18,7 @@ @import "./components/post-actions/style.scss"; @import "./components/post-card-panel/style.scss"; @import "./components/post-content-information/style.scss"; +@import "./components/post-discussion/style.scss"; @import "./components/post-excerpt/style.scss"; @import "./components/post-featured-image/style.scss"; @import "./components/post-format/style.scss"; diff --git a/test/e2e/specs/editor/various/sidebar.spec.js b/test/e2e/specs/editor/various/sidebar.spec.js index 02004f0c458f4..ddd4bc01a8196 100644 --- a/test/e2e/specs/editor/various/sidebar.spec.js +++ b/test/e2e/specs/editor/various/sidebar.spec.js @@ -114,7 +114,6 @@ test.describe( 'Sidebar', () => { 'No Title', 'Categories', 'Tags', - 'Discussion', ] ); // Also check 'panels' that are not rendered as TabPanels. const postExcerptPanel = page.getByRole( 'button', { @@ -123,6 +122,9 @@ test.describe( 'Sidebar', () => { const postFeaturedImagePanel = page.getByRole( 'button', { name: 'Set featured image', } ); + const postDiscussionPanel = page.getByRole( 'button', { + name: 'Change discussion options', + } ); const postSummarySection = page.getByRole( 'checkbox', { name: 'Stick to the top of the blog', } ); @@ -130,6 +132,7 @@ test.describe( 'Sidebar', () => { await expect( postExcerptPanel ).toBeVisible(); await expect( postFeaturedImagePanel ).toBeVisible(); await expect( postSummarySection ).toBeVisible(); + await expect( postDiscussionPanel ).toHaveCount( 1 ); await page.evaluate( () => { const { removeEditorPanel } = @@ -147,5 +150,6 @@ test.describe( 'Sidebar', () => { await expect( postExcerptPanel ).toBeHidden(); await expect( postFeaturedImagePanel ).toBeHidden(); await expect( postSummarySection ).toBeHidden(); + await expect( postDiscussionPanel ).toHaveCount( 0 ); } ); } );