@wordpress/editor 13.30.0 → 13.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/README.md +857 -0
- package/build/bindings/index.js +3 -1
- package/build/bindings/index.js.map +1 -1
- package/build/components/block-settings-menu/plugin-block-settings-menu-item.js +107 -0
- package/build/components/block-settings-menu/plugin-block-settings-menu-item.js.map +1 -0
- package/build/components/commands/index.js +1 -1
- package/build/components/commands/index.js.map +1 -1
- package/build/components/deprecated.js +158 -0
- package/build/components/deprecated.js.map +1 -1
- package/build/components/document-bar/index.js +7 -10
- package/build/components/document-bar/index.js.map +1 -1
- package/build/components/document-outline/index.js +1 -1
- package/build/components/document-outline/index.js.map +1 -1
- package/build/components/editor-canvas/edit-template-blocks-notification.js +2 -39
- package/build/components/editor-canvas/edit-template-blocks-notification.js.map +1 -1
- package/build/components/editor-canvas/index.js +3 -0
- package/build/components/editor-canvas/index.js.map +1 -1
- package/build/components/entities-saved-states/hooks/use-is-dirty.js +10 -16
- package/build/components/entities-saved-states/hooks/use-is-dirty.js.map +1 -1
- package/build/components/entities-saved-states/index.js +28 -88
- package/build/components/entities-saved-states/index.js.map +1 -1
- package/build/components/error-boundary/index.native.js +133 -0
- package/build/components/error-boundary/index.native.js.map +1 -0
- package/build/components/index.js +33 -8
- package/build/components/index.js.map +1 -1
- package/build/components/index.native.js +9 -1
- package/build/components/index.native.js.map +1 -1
- package/build/components/inserter-sidebar/index.js +5 -1
- package/build/components/inserter-sidebar/index.js.map +1 -1
- package/build/components/list-view-sidebar/index.js +2 -1
- package/build/components/list-view-sidebar/index.js.map +1 -1
- package/build/components/pattern-overrides-panel/index.js +30 -0
- package/build/components/pattern-overrides-panel/index.js.map +1 -0
- package/build/components/plugin-document-setting-panel/index.js +123 -0
- package/build/components/plugin-document-setting-panel/index.js.map +1 -0
- package/build/components/plugin-post-publish-panel/index.js +68 -0
- package/build/components/plugin-post-publish-panel/index.js.map +1 -0
- package/build/components/plugin-pre-publish-panel/index.js +71 -0
- package/build/components/plugin-pre-publish-panel/index.js.map +1 -0
- package/build/components/post-actions/actions.js +455 -0
- package/build/components/post-actions/actions.js.map +1 -0
- package/build/components/post-card-panel/index.js +93 -0
- package/build/components/post-card-panel/index.js.map +1 -0
- package/build/components/post-featured-image/index.js +3 -8
- package/build/components/post-featured-image/index.js.map +1 -1
- package/build/components/post-featured-image/panel.js +7 -3
- package/build/components/post-featured-image/panel.js.map +1 -1
- package/build/components/post-sync-status/index.js +0 -72
- package/build/components/post-sync-status/index.js.map +1 -1
- package/build/components/post-taxonomies/flat-term-selector.js +7 -3
- package/build/components/post-taxonomies/flat-term-selector.js.map +1 -1
- package/build/components/post-title/index.native.js +1 -1
- package/build/components/post-title/index.native.js.map +1 -1
- package/build/components/provider/disable-non-page-content-blocks.js +36 -20
- package/build/components/provider/disable-non-page-content-blocks.js.map +1 -1
- package/build/components/provider/index.js +1 -1
- package/build/components/provider/index.js.map +1 -1
- package/build/components/provider/use-block-editor-settings.js +8 -9
- package/build/components/provider/use-block-editor-settings.js.map +1 -1
- package/build/components/provider/use-hide-blocks-from-inserter.js +4 -3
- package/build/components/provider/use-hide-blocks-from-inserter.js.map +1 -1
- package/build/components/template-areas/index.js +70 -0
- package/build/components/template-areas/index.js.map +1 -0
- package/build/hooks/use-select-nearest-editable-block.js +87 -0
- package/build/hooks/use-select-nearest-editable-block.js.map +1 -0
- package/build/private-apis.js +6 -2
- package/build/private-apis.js.map +1 -1
- package/build/store/actions.js +46 -6
- package/build/store/actions.js.map +1 -1
- package/build/store/constants.js +3 -1
- package/build/store/constants.js.map +1 -1
- package/build/store/private-actions.js +80 -1
- package/build/store/private-actions.js.map +1 -1
- package/build/store/private-selectors.js +56 -3
- package/build/store/private-selectors.js.map +1 -1
- package/build/store/reducer.js +14 -1
- package/build/store/reducer.js.map +1 -1
- package/build/store/selectors.js +21 -11
- package/build/store/selectors.js.map +1 -1
- package/build/store/utils/get-filtered-template-parts.js +71 -0
- package/build/store/utils/get-filtered-template-parts.js.map +1 -0
- package/build-module/bindings/index.js +3 -1
- package/build-module/bindings/index.js.map +1 -1
- package/build-module/components/block-settings-menu/plugin-block-settings-menu-item.js +100 -0
- package/build-module/components/block-settings-menu/plugin-block-settings-menu-item.js.map +1 -0
- package/build-module/components/commands/index.js +1 -1
- package/build-module/components/commands/index.js.map +1 -1
- package/build-module/components/deprecated.js +159 -0
- package/build-module/components/deprecated.js.map +1 -1
- package/build-module/components/document-bar/index.js +8 -11
- package/build-module/components/document-bar/index.js.map +1 -1
- package/build-module/components/document-outline/index.js +1 -1
- package/build-module/components/document-outline/index.js.map +1 -1
- package/build-module/components/editor-canvas/edit-template-blocks-notification.js +4 -41
- package/build-module/components/editor-canvas/edit-template-blocks-notification.js.map +1 -1
- package/build-module/components/editor-canvas/index.js +3 -0
- package/build-module/components/editor-canvas/index.js.map +1 -1
- package/build-module/components/entities-saved-states/hooks/use-is-dirty.js +10 -16
- package/build-module/components/entities-saved-states/hooks/use-is-dirty.js.map +1 -1
- package/build-module/components/entities-saved-states/index.js +29 -89
- package/build-module/components/entities-saved-states/index.js.map +1 -1
- package/build-module/components/error-boundary/index.native.js +125 -0
- package/build-module/components/error-boundary/index.native.js.map +1 -0
- package/build-module/components/index.js +5 -1
- package/build-module/components/index.js.map +1 -1
- package/build-module/components/index.native.js +1 -0
- package/build-module/components/index.native.js.map +1 -1
- package/build-module/components/inserter-sidebar/index.js +5 -1
- package/build-module/components/inserter-sidebar/index.js.map +1 -1
- package/build-module/components/list-view-sidebar/index.js +2 -1
- package/build-module/components/list-view-sidebar/index.js.map +1 -1
- package/build-module/components/pattern-overrides-panel/index.js +23 -0
- package/build-module/components/pattern-overrides-panel/index.js.map +1 -0
- package/build-module/components/plugin-document-setting-panel/index.js +115 -0
- package/build-module/components/plugin-document-setting-panel/index.js.map +1 -0
- package/build-module/components/plugin-post-publish-panel/index.js +61 -0
- package/build-module/components/plugin-post-publish-panel/index.js.map +1 -0
- package/build-module/components/plugin-pre-publish-panel/index.js +64 -0
- package/build-module/components/plugin-pre-publish-panel/index.js.map +1 -0
- package/build-module/components/post-actions/actions.js +444 -0
- package/build-module/components/post-actions/actions.js.map +1 -0
- package/build-module/components/post-card-panel/index.js +85 -0
- package/build-module/components/post-card-panel/index.js.map +1 -0
- package/build-module/components/post-featured-image/index.js +4 -9
- package/build-module/components/post-featured-image/index.js.map +1 -1
- package/build-module/components/post-featured-image/panel.js +6 -2
- package/build-module/components/post-featured-image/panel.js.map +1 -1
- package/build-module/components/post-sync-status/index.js +2 -73
- package/build-module/components/post-sync-status/index.js.map +1 -1
- package/build-module/components/post-taxonomies/flat-term-selector.js +7 -3
- package/build-module/components/post-taxonomies/flat-term-selector.js.map +1 -1
- package/build-module/components/post-title/index.native.js +1 -1
- package/build-module/components/post-title/index.native.js.map +1 -1
- package/build-module/components/provider/disable-non-page-content-blocks.js +36 -20
- package/build-module/components/provider/disable-non-page-content-blocks.js.map +1 -1
- package/build-module/components/provider/index.js +1 -1
- package/build-module/components/provider/index.js.map +1 -1
- package/build-module/components/provider/use-block-editor-settings.js +9 -10
- package/build-module/components/provider/use-block-editor-settings.js.map +1 -1
- package/build-module/components/provider/use-hide-blocks-from-inserter.js +4 -3
- package/build-module/components/provider/use-hide-blocks-from-inserter.js.map +1 -1
- package/build-module/components/template-areas/index.js +63 -0
- package/build-module/components/template-areas/index.js.map +1 -0
- package/build-module/hooks/use-select-nearest-editable-block.js +80 -0
- package/build-module/hooks/use-select-nearest-editable-block.js.map +1 -0
- package/build-module/private-apis.js +6 -2
- package/build-module/private-apis.js.map +1 -1
- package/build-module/store/actions.js +37 -3
- package/build-module/store/actions.js.map +1 -1
- package/build-module/store/constants.js +2 -0
- package/build-module/store/constants.js.map +1 -1
- package/build-module/store/private-actions.js +78 -0
- package/build-module/store/private-actions.js.map +1 -1
- package/build-module/store/private-selectors.js +54 -3
- package/build-module/store/private-selectors.js.map +1 -1
- package/build-module/store/reducer.js +13 -1
- package/build-module/store/reducer.js.map +1 -1
- package/build-module/store/selectors.js +19 -10
- package/build-module/store/selectors.js.map +1 -1
- package/build-module/store/utils/get-filtered-template-parts.js +64 -0
- package/build-module/store/utils/get-filtered-template-parts.js.map +1 -0
- package/build-style/style-rtl.css +76 -33
- package/build-style/style.css +76 -33
- package/package.json +35 -33
- package/src/bindings/index.js +4 -1
- package/src/components/block-settings-menu/plugin-block-settings-menu-item.js +108 -0
- package/src/components/commands/index.js +1 -1
- package/src/components/deprecated.js +157 -0
- package/src/components/document-bar/index.js +12 -17
- package/src/components/document-bar/style.scss +9 -12
- package/src/components/document-outline/index.js +2 -1
- package/src/components/document-tools/style.scss +4 -11
- package/src/components/editor-canvas/edit-template-blocks-notification.js +6 -56
- package/src/components/editor-canvas/index.js +4 -0
- package/src/components/entities-saved-states/hooks/use-is-dirty.js +18 -22
- package/src/components/entities-saved-states/index.js +45 -121
- package/src/components/entities-saved-states/test/use-is-dirty.js +3 -0
- package/src/components/error-boundary/index.native.js +192 -0
- package/src/components/error-boundary/style.native.scss +116 -0
- package/src/components/index.js +5 -4
- package/src/components/index.native.js +1 -0
- package/src/components/inserter-sidebar/index.js +7 -1
- package/src/components/list-view-sidebar/index.js +1 -0
- package/src/components/list-view-sidebar/style.scss +1 -1
- package/src/components/pattern-overrides-panel/index.js +26 -0
- package/src/components/plugin-document-setting-panel/index.js +121 -0
- package/src/components/plugin-post-publish-panel/index.js +64 -0
- package/src/components/plugin-post-publish-panel/test/__snapshots__/index.js.snap +39 -0
- package/src/components/plugin-post-publish-panel/test/index.js +33 -0
- package/src/components/plugin-pre-publish-panel/index.js +67 -0
- package/src/components/plugin-pre-publish-panel/test/index.js +33 -0
- package/src/components/post-actions/actions.js +582 -0
- package/src/components/post-card-panel/index.js +108 -0
- package/src/components/post-card-panel/style.scss +32 -0
- package/src/components/post-featured-image/index.js +6 -15
- package/src/components/post-featured-image/panel.js +9 -3
- package/src/components/post-featured-image/style.scss +9 -13
- package/src/components/post-sync-status/index.js +1 -94
- package/src/components/post-taxonomies/flat-term-selector.js +13 -8
- package/src/components/post-title/index.native.js +1 -1
- package/src/components/provider/disable-non-page-content-blocks.js +40 -20
- package/src/components/provider/index.js +1 -1
- package/src/components/provider/test/disable-non-page-content-blocks.js +35 -14
- package/src/components/provider/use-block-editor-settings.js +11 -11
- package/src/components/provider/use-hide-blocks-from-inserter.js +5 -3
- package/src/components/template-areas/index.js +85 -0
- package/src/components/template-areas/style.scss +23 -0
- package/src/hooks/use-select-nearest-editable-block.js +95 -0
- package/src/private-apis.js +6 -2
- package/src/store/actions.js +37 -3
- package/src/store/constants.js +2 -0
- package/src/store/private-actions.js +111 -0
- package/src/store/private-selectors.js +105 -17
- package/src/store/reducer.js +13 -0
- package/src/store/selectors.js +50 -40
- package/src/store/utils/get-filtered-template-parts.js +69 -0
- package/src/store/utils/test/get-filtered-template-parts.js +189 -0
- package/src/style.scss +2 -0
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* WordPress dependencies
|
|
3
3
|
*/
|
|
4
|
-
import { useSelect
|
|
5
|
-
import { useEffect, useState
|
|
6
|
-
import { store as noticesStore } from '@wordpress/notices';
|
|
4
|
+
import { useSelect } from '@wordpress/data';
|
|
5
|
+
import { useEffect, useState } from '@wordpress/element';
|
|
7
6
|
import { __ } from '@wordpress/i18n';
|
|
8
7
|
import { __experimentalConfirmDialog as ConfirmDialog } from '@wordpress/components';
|
|
9
8
|
|
|
@@ -38,73 +37,22 @@ export default function EditTemplateBlocksNotification( { contentRef } ) {
|
|
|
38
37
|
};
|
|
39
38
|
}, [] );
|
|
40
39
|
|
|
41
|
-
const { getNotices } = useSelect( noticesStore );
|
|
42
|
-
|
|
43
|
-
const { createInfoNotice, removeNotice } = useDispatch( noticesStore );
|
|
44
|
-
|
|
45
40
|
const [ isDialogOpen, setIsDialogOpen ] = useState( false );
|
|
46
41
|
|
|
47
|
-
const lastNoticeId = useRef( 0 );
|
|
48
|
-
|
|
49
42
|
useEffect( () => {
|
|
50
|
-
const handleClick = async ( event ) => {
|
|
51
|
-
if ( ! event.target.classList.contains( 'is-root-container' ) ) {
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const isNoticeAlreadyShowing = getNotices().some(
|
|
56
|
-
( notice ) => notice.id === lastNoticeId.current
|
|
57
|
-
);
|
|
58
|
-
if ( isNoticeAlreadyShowing ) {
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const { notice } = await createInfoNotice(
|
|
63
|
-
__( 'Edit your template to edit this block.' ),
|
|
64
|
-
{
|
|
65
|
-
isDismissible: true,
|
|
66
|
-
type: 'snackbar',
|
|
67
|
-
actions: [
|
|
68
|
-
{
|
|
69
|
-
label: __( 'Edit template' ),
|
|
70
|
-
onClick: () =>
|
|
71
|
-
onNavigateToEntityRecord( {
|
|
72
|
-
postId: templateId,
|
|
73
|
-
postType: 'wp_template',
|
|
74
|
-
} ),
|
|
75
|
-
},
|
|
76
|
-
],
|
|
77
|
-
}
|
|
78
|
-
);
|
|
79
|
-
lastNoticeId.current = notice.id;
|
|
80
|
-
};
|
|
81
|
-
|
|
82
43
|
const handleDblClick = ( event ) => {
|
|
83
44
|
if ( ! event.target.classList.contains( 'is-root-container' ) ) {
|
|
84
45
|
return;
|
|
85
46
|
}
|
|
86
|
-
if ( lastNoticeId.current ) {
|
|
87
|
-
removeNotice( lastNoticeId.current );
|
|
88
|
-
}
|
|
89
47
|
setIsDialogOpen( true );
|
|
90
48
|
};
|
|
91
49
|
|
|
92
50
|
const canvas = contentRef.current;
|
|
93
|
-
canvas?.addEventListener( 'click', handleClick );
|
|
94
51
|
canvas?.addEventListener( 'dblclick', handleDblClick );
|
|
95
52
|
return () => {
|
|
96
|
-
canvas?.removeEventListener( 'click', handleClick );
|
|
97
53
|
canvas?.removeEventListener( 'dblclick', handleDblClick );
|
|
98
54
|
};
|
|
99
|
-
}, [
|
|
100
|
-
lastNoticeId,
|
|
101
|
-
contentRef,
|
|
102
|
-
getNotices,
|
|
103
|
-
createInfoNotice,
|
|
104
|
-
onNavigateToEntityRecord,
|
|
105
|
-
templateId,
|
|
106
|
-
removeNotice,
|
|
107
|
-
] );
|
|
55
|
+
}, [ contentRef ] );
|
|
108
56
|
|
|
109
57
|
return (
|
|
110
58
|
<ConfirmDialog
|
|
@@ -119,7 +67,9 @@ export default function EditTemplateBlocksNotification( { contentRef } ) {
|
|
|
119
67
|
} }
|
|
120
68
|
onCancel={ () => setIsDialogOpen( false ) }
|
|
121
69
|
>
|
|
122
|
-
{ __(
|
|
70
|
+
{ __(
|
|
71
|
+
'You’ve tried to select a block that is part of a template, which may be used on other posts and pages.'
|
|
72
|
+
) }
|
|
123
73
|
</ConfirmDialog>
|
|
124
74
|
);
|
|
125
75
|
}
|
|
@@ -29,6 +29,7 @@ import PostTitle from '../post-title';
|
|
|
29
29
|
import { store as editorStore } from '../../store';
|
|
30
30
|
import { unlock } from '../../lock-unlock';
|
|
31
31
|
import EditTemplateBlocksNotification from './edit-template-blocks-notification';
|
|
32
|
+
import useSelectNearestEditableBlock from '../../hooks/use-select-nearest-editable-block';
|
|
32
33
|
|
|
33
34
|
const {
|
|
34
35
|
LayoutStyle,
|
|
@@ -313,6 +314,9 @@ function EditorCanvas( {
|
|
|
313
314
|
useFlashEditableBlocks( {
|
|
314
315
|
isEnabled: renderingMode === 'template-locked',
|
|
315
316
|
} ),
|
|
317
|
+
useSelectNearestEditableBlock( {
|
|
318
|
+
isEnabled: renderingMode === 'template-locked',
|
|
319
|
+
} ),
|
|
316
320
|
] );
|
|
317
321
|
|
|
318
322
|
return (
|
|
@@ -4,29 +4,24 @@
|
|
|
4
4
|
import { useSelect } from '@wordpress/data';
|
|
5
5
|
import { store as coreStore } from '@wordpress/core-data';
|
|
6
6
|
import { useMemo, useState } from '@wordpress/element';
|
|
7
|
-
import { __ } from '@wordpress/i18n';
|
|
8
|
-
|
|
9
|
-
const TRANSLATED_SITE_PROPERTIES = {
|
|
10
|
-
title: __( 'Title' ),
|
|
11
|
-
description: __( 'Tagline' ),
|
|
12
|
-
site_logo: __( 'Logo' ),
|
|
13
|
-
site_icon: __( 'Icon' ),
|
|
14
|
-
show_on_front: __( 'Show on front' ),
|
|
15
|
-
page_on_front: __( 'Page on front' ),
|
|
16
|
-
posts_per_page: __( 'Maximum posts per page' ),
|
|
17
|
-
default_comment_status: __( 'Allow comments on new posts' ),
|
|
18
|
-
};
|
|
19
7
|
|
|
20
8
|
export const useIsDirty = () => {
|
|
21
|
-
const { editedEntities, siteEdits } = useSelect(
|
|
22
|
-
|
|
23
|
-
|
|
9
|
+
const { editedEntities, siteEdits, siteEntityConfig } = useSelect(
|
|
10
|
+
( select ) => {
|
|
11
|
+
const {
|
|
12
|
+
__experimentalGetDirtyEntityRecords,
|
|
13
|
+
getEntityRecordEdits,
|
|
14
|
+
getEntityConfig,
|
|
15
|
+
} = select( coreStore );
|
|
24
16
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
17
|
+
return {
|
|
18
|
+
editedEntities: __experimentalGetDirtyEntityRecords(),
|
|
19
|
+
siteEdits: getEntityRecordEdits( 'root', 'site' ),
|
|
20
|
+
siteEntityConfig: getEntityConfig( 'root', 'site' ),
|
|
21
|
+
};
|
|
22
|
+
},
|
|
23
|
+
[]
|
|
24
|
+
);
|
|
30
25
|
|
|
31
26
|
const dirtyEntityRecords = useMemo( () => {
|
|
32
27
|
// Remove site object and decouple into its edited pieces.
|
|
@@ -34,18 +29,19 @@ export const useIsDirty = () => {
|
|
|
34
29
|
( record ) => ! ( record.kind === 'root' && record.name === 'site' )
|
|
35
30
|
);
|
|
36
31
|
|
|
32
|
+
const siteEntityLabels = siteEntityConfig?.meta?.labels ?? {};
|
|
37
33
|
const editedSiteEntities = [];
|
|
38
34
|
for ( const property in siteEdits ) {
|
|
39
35
|
editedSiteEntities.push( {
|
|
40
36
|
kind: 'root',
|
|
41
37
|
name: 'site',
|
|
42
|
-
title:
|
|
38
|
+
title: siteEntityLabels[ property ] || property,
|
|
43
39
|
property,
|
|
44
40
|
} );
|
|
45
41
|
}
|
|
46
42
|
|
|
47
43
|
return [ ...editedEntitiesWithoutSite, ...editedSiteEntities ];
|
|
48
|
-
}, [ editedEntities, siteEdits ] );
|
|
44
|
+
}, [ editedEntities, siteEdits, siteEntityConfig ] );
|
|
49
45
|
|
|
50
46
|
// Unchecked entities to be ignored by save function.
|
|
51
47
|
const [ unselectedEntities, _setUnselectedEntities ] = useState( [] );
|
|
@@ -3,38 +3,40 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { Button, Flex, FlexItem } from '@wordpress/components';
|
|
5
5
|
import { __, _n, sprintf } from '@wordpress/i18n';
|
|
6
|
-
import { useSelect, useDispatch } from '@wordpress/data';
|
|
7
6
|
import {
|
|
8
7
|
useCallback,
|
|
9
8
|
useRef,
|
|
10
9
|
createInterpolateElement,
|
|
11
10
|
} from '@wordpress/element';
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
import {
|
|
12
|
+
__experimentalUseDialog as useDialog,
|
|
13
|
+
useInstanceId,
|
|
14
|
+
} from '@wordpress/compose';
|
|
15
|
+
import { useDispatch } from '@wordpress/data';
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Internal dependencies
|
|
19
19
|
*/
|
|
20
20
|
import EntityTypeList from './entity-type-list';
|
|
21
21
|
import { useIsDirty } from './hooks/use-is-dirty';
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
{
|
|
25
|
-
kind: 'postType',
|
|
26
|
-
name: 'wp_navigation',
|
|
27
|
-
},
|
|
28
|
-
];
|
|
22
|
+
import { store as editorStore } from '../../store';
|
|
23
|
+
import { unlock } from '../../lock-unlock';
|
|
29
24
|
|
|
30
25
|
function identity( values ) {
|
|
31
26
|
return values;
|
|
32
27
|
}
|
|
33
28
|
|
|
34
|
-
export default function EntitiesSavedStates( {
|
|
29
|
+
export default function EntitiesSavedStates( {
|
|
30
|
+
close,
|
|
31
|
+
renderDialog = undefined,
|
|
32
|
+
} ) {
|
|
35
33
|
const isDirtyProps = useIsDirty();
|
|
36
34
|
return (
|
|
37
|
-
<EntitiesSavedStatesExtensible
|
|
35
|
+
<EntitiesSavedStatesExtensible
|
|
36
|
+
close={ close }
|
|
37
|
+
renderDialog={ renderDialog }
|
|
38
|
+
{ ...isDirtyProps }
|
|
39
|
+
/>
|
|
38
40
|
);
|
|
39
41
|
}
|
|
40
42
|
|
|
@@ -44,25 +46,14 @@ export function EntitiesSavedStatesExtensible( {
|
|
|
44
46
|
onSave = identity,
|
|
45
47
|
saveEnabled: saveEnabledProp = undefined,
|
|
46
48
|
saveLabel = __( 'Save' ),
|
|
47
|
-
|
|
49
|
+
renderDialog = undefined,
|
|
48
50
|
dirtyEntityRecords,
|
|
49
51
|
isDirty,
|
|
50
52
|
setUnselectedEntities,
|
|
51
53
|
unselectedEntities,
|
|
52
54
|
} ) {
|
|
53
55
|
const saveButtonRef = useRef();
|
|
54
|
-
const {
|
|
55
|
-
editEntityRecord,
|
|
56
|
-
saveEditedEntityRecord,
|
|
57
|
-
__experimentalSaveSpecifiedEntityEdits: saveSpecifiedEntityEdits,
|
|
58
|
-
} = useDispatch( coreStore );
|
|
59
|
-
|
|
60
|
-
const { __unstableMarkLastChangeAsPersistent } =
|
|
61
|
-
useDispatch( blockEditorStore );
|
|
62
|
-
|
|
63
|
-
const { createSuccessNotice, createErrorNotice, removeNotice } =
|
|
64
|
-
useDispatch( noticesStore );
|
|
65
|
-
|
|
56
|
+
const { saveDirtyEntities } = unlock( useDispatch( editorStore ) );
|
|
66
57
|
// To group entities by type.
|
|
67
58
|
const partitionedSavables = dirtyEntityRecords.reduce( ( acc, record ) => {
|
|
68
59
|
const { name } = record;
|
|
@@ -88,94 +79,6 @@ export function EntitiesSavedStatesExtensible( {
|
|
|
88
79
|
].filter( Array.isArray );
|
|
89
80
|
|
|
90
81
|
const saveEnabled = saveEnabledProp ?? isDirty;
|
|
91
|
-
|
|
92
|
-
const { homeUrl } = useSelect( ( select ) => {
|
|
93
|
-
const {
|
|
94
|
-
getUnstableBase, // Site index.
|
|
95
|
-
} = select( coreStore );
|
|
96
|
-
return {
|
|
97
|
-
homeUrl: getUnstableBase()?.home,
|
|
98
|
-
};
|
|
99
|
-
}, [] );
|
|
100
|
-
|
|
101
|
-
const saveCheckedEntities = () => {
|
|
102
|
-
const saveNoticeId = 'site-editor-save-success';
|
|
103
|
-
removeNotice( saveNoticeId );
|
|
104
|
-
const entitiesToSave = dirtyEntityRecords.filter(
|
|
105
|
-
( { kind, name, key, property } ) => {
|
|
106
|
-
return ! unselectedEntities.some(
|
|
107
|
-
( elt ) =>
|
|
108
|
-
elt.kind === kind &&
|
|
109
|
-
elt.name === name &&
|
|
110
|
-
elt.key === key &&
|
|
111
|
-
elt.property === property
|
|
112
|
-
);
|
|
113
|
-
}
|
|
114
|
-
);
|
|
115
|
-
|
|
116
|
-
close( entitiesToSave );
|
|
117
|
-
|
|
118
|
-
const siteItemsToSave = [];
|
|
119
|
-
const pendingSavedRecords = [];
|
|
120
|
-
entitiesToSave.forEach( ( { kind, name, key, property } ) => {
|
|
121
|
-
if ( 'root' === kind && 'site' === name ) {
|
|
122
|
-
siteItemsToSave.push( property );
|
|
123
|
-
} else {
|
|
124
|
-
if (
|
|
125
|
-
PUBLISH_ON_SAVE_ENTITIES.some(
|
|
126
|
-
( typeToPublish ) =>
|
|
127
|
-
typeToPublish.kind === kind &&
|
|
128
|
-
typeToPublish.name === name
|
|
129
|
-
)
|
|
130
|
-
) {
|
|
131
|
-
editEntityRecord( kind, name, key, { status: 'publish' } );
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
pendingSavedRecords.push(
|
|
135
|
-
saveEditedEntityRecord( kind, name, key )
|
|
136
|
-
);
|
|
137
|
-
}
|
|
138
|
-
} );
|
|
139
|
-
if ( siteItemsToSave.length ) {
|
|
140
|
-
pendingSavedRecords.push(
|
|
141
|
-
saveSpecifiedEntityEdits(
|
|
142
|
-
'root',
|
|
143
|
-
'site',
|
|
144
|
-
undefined,
|
|
145
|
-
siteItemsToSave
|
|
146
|
-
)
|
|
147
|
-
);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
__unstableMarkLastChangeAsPersistent();
|
|
151
|
-
|
|
152
|
-
Promise.all( pendingSavedRecords )
|
|
153
|
-
.then( ( values ) => {
|
|
154
|
-
return onSave( values );
|
|
155
|
-
} )
|
|
156
|
-
.then( ( values ) => {
|
|
157
|
-
if (
|
|
158
|
-
values.some( ( value ) => typeof value === 'undefined' )
|
|
159
|
-
) {
|
|
160
|
-
createErrorNotice( __( 'Saving failed.' ) );
|
|
161
|
-
} else {
|
|
162
|
-
createSuccessNotice( __( 'Site updated.' ), {
|
|
163
|
-
type: 'snackbar',
|
|
164
|
-
id: saveNoticeId,
|
|
165
|
-
actions: [
|
|
166
|
-
{
|
|
167
|
-
label: __( 'View site' ),
|
|
168
|
-
url: homeUrl,
|
|
169
|
-
},
|
|
170
|
-
],
|
|
171
|
-
} );
|
|
172
|
-
}
|
|
173
|
-
} )
|
|
174
|
-
.catch( ( error ) =>
|
|
175
|
-
createErrorNotice( `${ __( 'Saving failed.' ) } ${ error }` )
|
|
176
|
-
);
|
|
177
|
-
};
|
|
178
|
-
|
|
179
82
|
// Explicitly define this with no argument passed. Using `close` on
|
|
180
83
|
// its own will use the event object in place of the expected saved entities.
|
|
181
84
|
const dismissPanel = useCallback( () => close(), [ close ] );
|
|
@@ -183,12 +86,20 @@ export function EntitiesSavedStatesExtensible( {
|
|
|
183
86
|
const [ saveDialogRef, saveDialogProps ] = useDialog( {
|
|
184
87
|
onClose: () => dismissPanel(),
|
|
185
88
|
} );
|
|
89
|
+
const dialogLabel = useInstanceId( EntitiesSavedStatesExtensible, 'label' );
|
|
90
|
+
const dialogDescription = useInstanceId(
|
|
91
|
+
EntitiesSavedStatesExtensible,
|
|
92
|
+
'description'
|
|
93
|
+
);
|
|
186
94
|
|
|
187
95
|
return (
|
|
188
96
|
<div
|
|
189
97
|
ref={ saveDialogRef }
|
|
190
98
|
{ ...saveDialogProps }
|
|
191
99
|
className="entities-saved-states__panel"
|
|
100
|
+
role={ renderDialog ? 'dialog' : undefined }
|
|
101
|
+
aria-labelledby={ renderDialog ? dialogLabel : undefined }
|
|
102
|
+
aria-describedby={ renderDialog ? dialogDescription : undefined }
|
|
192
103
|
>
|
|
193
104
|
<Flex className="entities-saved-states__panel-header" gap={ 2 }>
|
|
194
105
|
<FlexItem
|
|
@@ -197,7 +108,15 @@ export function EntitiesSavedStatesExtensible( {
|
|
|
197
108
|
ref={ saveButtonRef }
|
|
198
109
|
variant="primary"
|
|
199
110
|
disabled={ ! saveEnabled }
|
|
200
|
-
|
|
111
|
+
__experimentalIsFocusable
|
|
112
|
+
onClick={ () =>
|
|
113
|
+
saveDirtyEntities( {
|
|
114
|
+
onSave,
|
|
115
|
+
dirtyEntityRecords,
|
|
116
|
+
entitiesToSkip: unselectedEntities,
|
|
117
|
+
close,
|
|
118
|
+
} )
|
|
119
|
+
}
|
|
201
120
|
className="editor-entities-saved-states__save-button"
|
|
202
121
|
>
|
|
203
122
|
{ saveLabel }
|
|
@@ -213,11 +132,16 @@ export function EntitiesSavedStatesExtensible( {
|
|
|
213
132
|
</Flex>
|
|
214
133
|
|
|
215
134
|
<div className="entities-saved-states__text-prompt">
|
|
216
|
-
<
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
135
|
+
<div
|
|
136
|
+
className="entities-saved-states__text-prompt--header-wrapper"
|
|
137
|
+
id={ renderDialog ? dialogLabel : undefined }
|
|
138
|
+
>
|
|
139
|
+
<strong className="entities-saved-states__text-prompt--header">
|
|
140
|
+
{ __( 'Are you ready to save?' ) }
|
|
141
|
+
</strong>
|
|
142
|
+
{ additionalPrompt }
|
|
143
|
+
</div>
|
|
144
|
+
<p id={ renderDialog ? dialogDescription : undefined }>
|
|
221
145
|
{ isDirty
|
|
222
146
|
? createInterpolateElement(
|
|
223
147
|
sprintf(
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { ScrollView, Text, TouchableOpacity, View } from 'react-native';
|
|
5
|
+
import Clipboard from '@react-native-clipboard/clipboard';
|
|
6
|
+
import { SafeAreaView } from 'react-native-safe-area-context';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* WordPress dependencies
|
|
10
|
+
*/
|
|
11
|
+
import { Component } from '@wordpress/element';
|
|
12
|
+
import { __ } from '@wordpress/i18n';
|
|
13
|
+
import { select } from '@wordpress/data';
|
|
14
|
+
import { logException } from '@wordpress/react-native-bridge';
|
|
15
|
+
import {
|
|
16
|
+
usePreferredColorSchemeStyle,
|
|
17
|
+
withPreferredColorScheme,
|
|
18
|
+
} from '@wordpress/compose';
|
|
19
|
+
import { warning } from '@wordpress/icons';
|
|
20
|
+
import { Icon } from '@wordpress/components';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Internal dependencies
|
|
24
|
+
*/
|
|
25
|
+
import { store as editorStore } from '../../store';
|
|
26
|
+
import styles from './style.scss';
|
|
27
|
+
|
|
28
|
+
function getContent() {
|
|
29
|
+
try {
|
|
30
|
+
// While `select` in a component is generally discouraged, it is
|
|
31
|
+
// used here because it (a) reduces the chance of data loss in the
|
|
32
|
+
// case of additional errors by performing a direct retrieval and
|
|
33
|
+
// (b) avoids the performance cost associated with unnecessary
|
|
34
|
+
// content serialization throughout the lifetime of a non-erroring
|
|
35
|
+
// application.
|
|
36
|
+
return select( editorStore ).getEditedPostContent();
|
|
37
|
+
} catch ( error ) {}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function CopyButton( {
|
|
41
|
+
text,
|
|
42
|
+
label,
|
|
43
|
+
accessibilityLabel,
|
|
44
|
+
accessibilityHint,
|
|
45
|
+
secondary = false,
|
|
46
|
+
} ) {
|
|
47
|
+
const containerStyle = usePreferredColorSchemeStyle(
|
|
48
|
+
styles[ 'copy-button__container' ],
|
|
49
|
+
styles[ 'copy-button__container--dark' ]
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
const containerSecondaryStyle = usePreferredColorSchemeStyle(
|
|
53
|
+
styles[ 'copy-button__container--secondary' ],
|
|
54
|
+
styles[ 'copy-button__container--secondary-dark' ]
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const textStyle = usePreferredColorSchemeStyle(
|
|
58
|
+
styles[ 'copy-button__text' ],
|
|
59
|
+
styles[ 'copy-button__text--dark' ]
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
const textSecondaryStyle = usePreferredColorSchemeStyle(
|
|
63
|
+
styles[ 'copy-button__text--secondary' ],
|
|
64
|
+
styles[ 'copy-button__text--secondary-dark' ]
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<TouchableOpacity
|
|
69
|
+
activeOpacity={ 0.5 }
|
|
70
|
+
accessibilityLabel={ accessibilityLabel }
|
|
71
|
+
style={ [ containerStyle, secondary && containerSecondaryStyle ] }
|
|
72
|
+
accessibilityRole={ 'button' }
|
|
73
|
+
accessibilityHint={ accessibilityHint }
|
|
74
|
+
onPress={ () => {
|
|
75
|
+
Clipboard.setString(
|
|
76
|
+
typeof text === 'function' ? text() : text || ''
|
|
77
|
+
);
|
|
78
|
+
} }
|
|
79
|
+
>
|
|
80
|
+
<Text style={ [ textStyle, secondary && textSecondaryStyle ] }>
|
|
81
|
+
{ label }
|
|
82
|
+
</Text>
|
|
83
|
+
</TouchableOpacity>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
class ErrorBoundary extends Component {
|
|
88
|
+
constructor() {
|
|
89
|
+
super( ...arguments );
|
|
90
|
+
|
|
91
|
+
this.state = {
|
|
92
|
+
error: null,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
componentDidCatch( error ) {
|
|
97
|
+
logException( error, {
|
|
98
|
+
context: {
|
|
99
|
+
component_stack: error.componentStack,
|
|
100
|
+
},
|
|
101
|
+
isHandled: true,
|
|
102
|
+
handledBy: 'Editor-level Error Boundary',
|
|
103
|
+
} );
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
static getDerivedStateFromError( error ) {
|
|
107
|
+
return { error };
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
render() {
|
|
111
|
+
const { error } = this.state;
|
|
112
|
+
if ( ! error ) {
|
|
113
|
+
return this.props.children;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const { getStylesFromColorScheme } = this.props;
|
|
117
|
+
|
|
118
|
+
const iconContainerStyle = getStylesFromColorScheme(
|
|
119
|
+
styles[ 'error-boundary__icon-container' ],
|
|
120
|
+
styles[ 'error-boundary__icon-container--dark' ]
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
const titleStyle = getStylesFromColorScheme(
|
|
124
|
+
styles[ 'error-boundary__title' ],
|
|
125
|
+
styles[ 'error-boundary__title--dark' ]
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
const messageStyle = getStylesFromColorScheme(
|
|
129
|
+
styles[ 'error-boundary__message' ],
|
|
130
|
+
styles[ 'error-boundary__message--dark' ]
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
return (
|
|
134
|
+
<SafeAreaView>
|
|
135
|
+
<ScrollView
|
|
136
|
+
style={ styles[ 'error-boundary__scroll' ] }
|
|
137
|
+
contentContainerStyle={
|
|
138
|
+
styles[ 'error-boundary__scroll-container' ]
|
|
139
|
+
}
|
|
140
|
+
>
|
|
141
|
+
<View style={ styles[ 'error-boundary__container' ] }>
|
|
142
|
+
<View style={ iconContainerStyle }>
|
|
143
|
+
<Icon
|
|
144
|
+
icon={ warning }
|
|
145
|
+
{ ...styles[ 'error-boundary__icon' ] }
|
|
146
|
+
/>
|
|
147
|
+
</View>
|
|
148
|
+
<Text style={ titleStyle }>
|
|
149
|
+
{ __(
|
|
150
|
+
'The editor has encountered an unexpected error'
|
|
151
|
+
) }
|
|
152
|
+
</Text>
|
|
153
|
+
<Text style={ messageStyle }>
|
|
154
|
+
{ __(
|
|
155
|
+
'You can copy your post text in case your content is impacted. Copy error details to debug and share with support.'
|
|
156
|
+
) }
|
|
157
|
+
</Text>
|
|
158
|
+
<View
|
|
159
|
+
style={
|
|
160
|
+
styles[ 'error-boundary__actions-container' ]
|
|
161
|
+
}
|
|
162
|
+
>
|
|
163
|
+
<CopyButton
|
|
164
|
+
label={ __( 'Copy post text' ) }
|
|
165
|
+
accessibilityLabel={ __(
|
|
166
|
+
'Button to copy post text'
|
|
167
|
+
) }
|
|
168
|
+
accessibilityHint={ __(
|
|
169
|
+
'Tap here to copy post text'
|
|
170
|
+
) }
|
|
171
|
+
text={ getContent }
|
|
172
|
+
/>
|
|
173
|
+
<CopyButton
|
|
174
|
+
label={ __( 'Copy error details' ) }
|
|
175
|
+
accessibilityLabel={ __(
|
|
176
|
+
'Button to copy error details'
|
|
177
|
+
) }
|
|
178
|
+
accessibilityHint={ __(
|
|
179
|
+
'Tap here to copy error details'
|
|
180
|
+
) }
|
|
181
|
+
text={ error.stack }
|
|
182
|
+
secondary
|
|
183
|
+
/>
|
|
184
|
+
</View>
|
|
185
|
+
</View>
|
|
186
|
+
</ScrollView>
|
|
187
|
+
</SafeAreaView>
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export default withPreferredColorScheme( ErrorBoundary );
|