@wordpress/edit-post 6.17.0 → 6.19.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.
Files changed (103) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/build/components/block-manager/category.js +4 -12
  3. package/build/components/block-manager/category.js.map +1 -1
  4. package/build/components/block-manager/checklist.js +4 -3
  5. package/build/components/block-manager/checklist.js.map +1 -1
  6. package/build/components/block-manager/index.js +1 -1
  7. package/build/components/block-manager/index.js.map +1 -1
  8. package/build/components/header/header-toolbar/index.js +2 -8
  9. package/build/components/header/header-toolbar/index.js.map +1 -1
  10. package/build/components/header/index.js +5 -4
  11. package/build/components/header/index.js.map +1 -1
  12. package/build/components/header/more-menu/index.js +1 -3
  13. package/build/components/header/more-menu/index.js.map +1 -1
  14. package/build/components/header/writing-menu/index.js +13 -14
  15. package/build/components/header/writing-menu/index.js.map +1 -1
  16. package/build/components/keyboard-shortcut-help-modal/config.js +12 -0
  17. package/build/components/keyboard-shortcut-help-modal/config.js.map +1 -1
  18. package/build/components/keyboard-shortcut-help-modal/shortcut.js +1 -7
  19. package/build/components/keyboard-shortcut-help-modal/shortcut.js.map +1 -1
  20. package/build/components/keyboard-shortcuts/index.js +71 -5
  21. package/build/components/keyboard-shortcuts/index.js.map +1 -1
  22. package/build/components/layout/index.js +2 -7
  23. package/build/components/layout/index.js.map +1 -1
  24. package/build/components/preferences-modal/index.js +1 -1
  25. package/build/components/preferences-modal/index.js.map +1 -1
  26. package/build/components/secondary-sidebar/list-view-outline.js +119 -0
  27. package/build/components/secondary-sidebar/list-view-outline.js.map +1 -0
  28. package/build/components/secondary-sidebar/list-view-sidebar.js +38 -13
  29. package/build/components/secondary-sidebar/list-view-sidebar.js.map +1 -1
  30. package/build/components/visual-editor/index.js +4 -1
  31. package/build/components/visual-editor/index.js.map +1 -1
  32. package/build/store/actions.js +24 -41
  33. package/build/store/actions.js.map +1 -1
  34. package/build/store/reducer.js +29 -8
  35. package/build/store/reducer.js.map +1 -1
  36. package/build-module/components/block-manager/category.js +5 -13
  37. package/build-module/components/block-manager/category.js.map +1 -1
  38. package/build-module/components/block-manager/checklist.js +5 -4
  39. package/build-module/components/block-manager/checklist.js.map +1 -1
  40. package/build-module/components/block-manager/index.js +2 -2
  41. package/build-module/components/block-manager/index.js.map +1 -1
  42. package/build-module/components/header/header-toolbar/index.js +3 -9
  43. package/build-module/components/header/header-toolbar/index.js.map +1 -1
  44. package/build-module/components/header/index.js +5 -4
  45. package/build-module/components/header/index.js.map +1 -1
  46. package/build-module/components/header/more-menu/index.js +1 -3
  47. package/build-module/components/header/more-menu/index.js.map +1 -1
  48. package/build-module/components/header/writing-menu/index.js +13 -14
  49. package/build-module/components/header/writing-menu/index.js.map +1 -1
  50. package/build-module/components/keyboard-shortcut-help-modal/config.js +12 -0
  51. package/build-module/components/keyboard-shortcut-help-modal/config.js.map +1 -1
  52. package/build-module/components/keyboard-shortcut-help-modal/shortcut.js +1 -6
  53. package/build-module/components/keyboard-shortcut-help-modal/shortcut.js.map +1 -1
  54. package/build-module/components/keyboard-shortcuts/index.js +71 -6
  55. package/build-module/components/keyboard-shortcuts/index.js.map +1 -1
  56. package/build-module/components/layout/index.js +2 -7
  57. package/build-module/components/layout/index.js.map +1 -1
  58. package/build-module/components/preferences-modal/index.js +1 -1
  59. package/build-module/components/preferences-modal/index.js.map +1 -1
  60. package/build-module/components/secondary-sidebar/list-view-outline.js +108 -0
  61. package/build-module/components/secondary-sidebar/list-view-outline.js.map +1 -0
  62. package/build-module/components/secondary-sidebar/list-view-sidebar.js +36 -14
  63. package/build-module/components/secondary-sidebar/list-view-sidebar.js.map +1 -1
  64. package/build-module/components/visual-editor/index.js +3 -1
  65. package/build-module/components/visual-editor/index.js.map +1 -1
  66. package/build-module/store/actions.js +22 -37
  67. package/build-module/store/actions.js.map +1 -1
  68. package/build-module/store/reducer.js +30 -7
  69. package/build-module/store/reducer.js.map +1 -1
  70. package/build-style/style-rtl.css +96 -40
  71. package/build-style/style.css +96 -40
  72. package/package.json +27 -27
  73. package/src/components/block-manager/category.js +5 -12
  74. package/src/components/block-manager/checklist.js +3 -6
  75. package/src/components/block-manager/index.js +2 -2
  76. package/src/components/block-manager/style.scss +4 -15
  77. package/src/components/header/fullscreen-mode-close/test/__snapshots__/index.js.snap +26 -0
  78. package/src/components/header/fullscreen-mode-close/test/index.js +10 -12
  79. package/src/components/header/header-toolbar/index.js +2 -10
  80. package/src/components/header/index.js +4 -1
  81. package/src/components/header/more-menu/index.js +1 -1
  82. package/src/components/header/style.scss +3 -9
  83. package/src/components/header/writing-menu/index.js +13 -11
  84. package/src/components/keyboard-shortcut-help-modal/config.js +10 -0
  85. package/src/components/keyboard-shortcut-help-modal/shortcut.js +15 -18
  86. package/src/components/keyboard-shortcut-help-modal/test/__snapshots__/index.js.snap +70 -0
  87. package/src/components/keyboard-shortcuts/index.js +77 -8
  88. package/src/components/layout/index.js +2 -9
  89. package/src/components/layout/style.scss +12 -1
  90. package/src/components/preferences-modal/index.js +1 -1
  91. package/src/components/preferences-modal/test/__snapshots__/index.js.snap +52 -47
  92. package/src/components/secondary-sidebar/list-view-outline.js +98 -0
  93. package/src/components/secondary-sidebar/list-view-sidebar.js +49 -10
  94. package/src/components/secondary-sidebar/style.scss +67 -11
  95. package/src/components/sidebar/plugin-post-status-info/test/__snapshots__/index.js.snap +6 -4
  96. package/src/components/sidebar/plugin-post-status-info/test/index.js +1 -1
  97. package/src/components/sidebar/plugin-pre-publish-panel/test/index.js +8 -6
  98. package/src/components/visual-editor/index.js +9 -3
  99. package/src/components/visual-editor/test/index.native.js +13 -13
  100. package/src/store/actions.js +21 -35
  101. package/src/store/reducer.js +28 -8
  102. package/src/store/test/reducer.js +32 -2
  103. package/src/components/sidebar/plugin-pre-publish-panel/test/__snapshots__/index.js.snap +0 -3
@@ -1,3 +1,8 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import classnames from 'classnames';
5
+
1
6
  /**
2
7
  * WordPress dependencies
3
8
  */
@@ -6,18 +11,19 @@ import { Button } from '@wordpress/components';
6
11
  import {
7
12
  useFocusOnMount,
8
13
  useFocusReturn,
9
- useInstanceId,
10
14
  useMergeRefs,
11
15
  } from '@wordpress/compose';
12
16
  import { useDispatch } from '@wordpress/data';
13
17
  import { __ } from '@wordpress/i18n';
14
18
  import { closeSmall } from '@wordpress/icons';
15
19
  import { ESCAPE } from '@wordpress/keycodes';
20
+ import { useState } from '@wordpress/element';
16
21
 
17
22
  /**
18
23
  * Internal dependencies
19
24
  */
20
25
  import { store as editPostStore } from '../../store';
26
+ import ListViewOutline from './list-view-outline';
21
27
 
22
28
  export default function ListViewSidebar() {
23
29
  const { setIsListViewOpened } = useDispatch( editPostStore );
@@ -32,35 +38,68 @@ export default function ListViewSidebar() {
32
38
  }
33
39
  }
34
40
 
35
- const instanceId = useInstanceId( ListViewSidebar );
36
- const labelId = `edit-post-editor__list-view-panel-label-${ instanceId }`;
41
+ const [ tab, setTab ] = useState( 'list-view' );
37
42
 
38
43
  return (
39
44
  // eslint-disable-next-line jsx-a11y/no-static-element-interactions
40
45
  <div
41
- aria-labelledby={ labelId }
42
- className="edit-post-editor__list-view-panel"
46
+ aria-label={ __( 'Document Overview' ) }
47
+ className="edit-post-editor__document-overview-panel"
43
48
  onKeyDown={ closeOnEscape }
44
49
  >
45
50
  <div
46
- className="edit-post-editor__list-view-panel-header"
51
+ className="edit-post-editor__document-overview-panel-header components-panel__header edit-post-sidebar__panel-tabs"
47
52
  ref={ headerFocusReturnRef }
48
53
  >
49
- <strong id={ labelId }>{ __( 'List View' ) }</strong>
50
54
  <Button
51
55
  icon={ closeSmall }
52
- label={ __( 'Close List View Sidebar' ) }
56
+ label={ __( 'Close Document Overview Sidebar' ) }
53
57
  onClick={ () => setIsListViewOpened( false ) }
54
58
  />
59
+ <ul>
60
+ <li>
61
+ <Button
62
+ onClick={ () => {
63
+ setTab( 'list-view' );
64
+ } }
65
+ className={ classnames(
66
+ 'edit-post-sidebar__panel-tab',
67
+ { 'is-active': tab === 'list-view' }
68
+ ) }
69
+ aria-current={ tab === 'list-view' }
70
+ >
71
+ { __( 'List View' ) }
72
+ </Button>
73
+ </li>
74
+ <li>
75
+ <Button
76
+ onClick={ () => {
77
+ setTab( 'outline' );
78
+ } }
79
+ className={ classnames(
80
+ 'edit-post-sidebar__panel-tab',
81
+ { 'is-active': tab === 'outline' }
82
+ ) }
83
+ aria-current={ tab === 'outline' }
84
+ >
85
+ { __( 'Outline' ) }
86
+ </Button>
87
+ </li>
88
+ </ul>
55
89
  </div>
56
90
  <div
57
- className="edit-post-editor__list-view-panel-content"
58
91
  ref={ useMergeRefs( [
59
92
  contentFocusReturnRef,
60
93
  focusOnMountRef,
61
94
  ] ) }
95
+ className="edit-post-editor__list-view-container"
62
96
  >
63
- <ListView />
97
+ { tab === 'list-view' && (
98
+ <div className="edit-post-editor__list-view-panel-content">
99
+ <ListView />
100
+ </div>
101
+ ) }
102
+ { tab === 'outline' && <ListViewOutline /> }
64
103
  </div>
65
104
  </div>
66
105
  );
@@ -1,14 +1,19 @@
1
1
  .edit-post-editor__inserter-panel,
2
- .edit-post-editor__list-view-panel {
2
+ .edit-post-editor__document-overview-panel {
3
3
  height: 100%;
4
4
  display: flex;
5
5
  flex-direction: column;
6
6
  }
7
7
 
8
- .edit-post-editor__list-view-panel {
8
+ .edit-post-editor__document-overview-panel {
9
9
  // Same width as the Inserter.
10
10
  // @see packages/block-editor/src/components/inserter/style.scss
11
- min-width: 350px;
11
+ // Width of the list view panel.
12
+ width: 350px;
13
+
14
+ .edit-post-sidebar__panel-tabs {
15
+ flex-direction: row-reverse;
16
+ }
12
17
  }
13
18
 
14
19
  .edit-post-editor__inserter-panel-header {
@@ -18,30 +23,81 @@
18
23
  justify-content: flex-end;
19
24
  }
20
25
 
21
- .edit-post-editor__inserter-panel-content,
22
- .edit-post-editor__list-view-panel-content {
26
+ .edit-post-editor__inserter-panel-content {
23
27
  // Leave space for the close button
24
28
  height: calc(100% - #{$button-size} - #{$grid-unit-10});
25
- }
26
-
27
- .edit-post-editor__inserter-panel-content {
28
29
  @include break-medium() {
29
30
  height: 100%;
30
31
  }
31
32
  }
32
33
 
33
- .edit-post-editor__list-view-panel-header {
34
- align-items: center;
34
+ .edit-post-editor__document-overview-panel-header {
35
35
  border-bottom: $border-width solid $gray-300;
36
36
  display: flex;
37
37
  justify-content: space-between;
38
38
  height: $grid-unit-60;
39
39
  padding-left: $grid-unit-20;
40
40
  padding-right: $grid-unit-05;
41
+ ul {
42
+ width: calc(100% - #{ $grid-unit-50 });
43
+ }
44
+ li {
45
+ width: 50%;
46
+ button {
47
+ width: 100%;
48
+ text-align: initial;
49
+ }
50
+ }
51
+ li:only-child {
52
+ width: 100%;
53
+ }
41
54
  }
42
55
 
43
- .edit-post-editor__list-view-panel-content {
56
+ .edit-post-editor__list-view-panel-content,
57
+ .edit-post-editor__list-view-container > .document-outline,
58
+ .edit-post-editor__list-view-empty-headings {
59
+ overflow-x: hidden;
44
60
  overflow-y: auto;
61
+ height: 100%;
45
62
  // The table cells use an extra pixels of space left and right. We compensate for that here.
46
63
  padding: $grid-unit-10 ($grid-unit-10 - $border-width - $border-width);
47
64
  }
65
+
66
+ .edit-post-editor__list-view-empty-headings {
67
+ & > svg {
68
+ margin-top: $grid-unit-30 + $grid-unit-05;
69
+ }
70
+ & > p {
71
+ padding-left: $grid-unit-40;
72
+ padding-right: $grid-unit-40;
73
+ }
74
+ text-align: center;
75
+ color: $gray-700;
76
+ }
77
+
78
+ .edit-post-editor__list-view-overview {
79
+ & > div > span:first-child {
80
+ // Width of the text information fields.
81
+ width: 90px;
82
+ display: inline-block;
83
+ }
84
+ border-top: $border-width solid $gray-300;
85
+ width: calc(100% - #{ $grid-unit-40 });
86
+ padding: $grid-unit-20;
87
+ & > div {
88
+ padding: 0 0 $grid-unit-10;
89
+ & > span {
90
+ font-size: $helptext-font-size;
91
+ line-height: $default-line-height;
92
+ color: $gray-700;
93
+ }
94
+ }
95
+ // Height of the overview container.
96
+ height: 72px;
97
+ }
98
+
99
+ .edit-post-editor__list-view-container {
100
+ display: flex;
101
+ flex-direction: column;
102
+ height: calc(100% - #{$grid-unit-60});
103
+ }
@@ -1,9 +1,11 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
3
  exports[`PluginPostStatusInfo renders fill properly 1`] = `
4
- <div
5
- class="components-panel__row my-plugin-post-status-info"
6
- >
7
- My plugin post status info
4
+ <div>
5
+ <div
6
+ class="components-panel__row my-plugin-post-status-info"
7
+ >
8
+ My plugin post status info
9
+ </div>
8
10
  </div>
9
11
  `;
@@ -24,6 +24,6 @@ describe( 'PluginPostStatusInfo', () => {
24
24
  </SlotFillProvider>
25
25
  );
26
26
 
27
- expect( container.firstChild ).toMatchSnapshot();
27
+ expect( container ).toMatchSnapshot();
28
28
  } );
29
29
  } );
@@ -1,8 +1,12 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import { render, screen } from '@testing-library/react';
5
+
1
6
  /**
2
7
  * WordPress dependencies
3
8
  */
4
9
  import { SlotFillProvider } from '@wordpress/components';
5
- import { render } from '@wordpress/element';
6
10
 
7
11
  /**
8
12
  * Internal dependencies
@@ -11,21 +15,19 @@ import PluginPrePublishPanel from '../';
11
15
 
12
16
  describe( 'PluginPrePublishPanel', () => {
13
17
  test( 'renders fill properly', () => {
14
- const div = document.createElement( 'div' );
15
18
  render(
16
19
  <SlotFillProvider>
17
20
  <PluginPrePublishPanel
18
21
  className="my-plugin-pre-publish-panel"
19
22
  title="My panel title"
20
- initialOpen={ true }
23
+ initialOpen
21
24
  >
22
25
  My panel content
23
26
  </PluginPrePublishPanel>
24
27
  <PluginPrePublishPanel.Slot />
25
- </SlotFillProvider>,
26
- div
28
+ </SlotFillProvider>
27
29
  );
28
30
 
29
- expect( div.innerHTML ).toMatchSnapshot();
31
+ expect( screen.getByText( 'My panel title' ) ).toBeVisible();
30
32
  } );
31
33
  } );
@@ -38,6 +38,7 @@ import { useMergeRefs } from '@wordpress/compose';
38
38
  import { arrowLeft } from '@wordpress/icons';
39
39
  import { __ } from '@wordpress/i18n';
40
40
  import { parse } from '@wordpress/blocks';
41
+ import { store as coreStore } from '@wordpress/core-data';
41
42
 
42
43
  /**
43
44
  * Internal dependencies
@@ -137,6 +138,10 @@ export default function VisualEditor( { styles } ) {
137
138
  }
138
139
 
139
140
  const supportsTemplateMode = getEditorSettings().supportsTemplateMode;
141
+ const canEditTemplate = select( coreStore ).canUser(
142
+ 'create',
143
+ 'templates'
144
+ );
140
145
 
141
146
  return {
142
147
  deviceType: __experimentalGetPreviewDeviceType(),
@@ -144,9 +149,10 @@ export default function VisualEditor( { styles } ) {
144
149
  isTemplateMode: _isTemplateMode,
145
150
  // Post template fetch returns a 404 on classic themes, which
146
151
  // messes with e2e tests, so we check it's a block theme first.
147
- editedPostTemplate: supportsTemplateMode
148
- ? getEditedPostTemplate()
149
- : {},
152
+ editedPostTemplate:
153
+ supportsTemplateMode && canEditTemplate
154
+ ? getEditedPostTemplate()
155
+ : undefined,
150
156
  wrapperBlockName: _wrapperBlockName,
151
157
  wrapperUniqueId: getCurrentPostId(),
152
158
  };
@@ -38,24 +38,24 @@ describe( 'when title is focused', () => {
38
38
  } );
39
39
 
40
40
  // Focus first block
41
- fireEvent.press( screen.getByA11yLabel( /Paragraph Block. Row 1/ ) );
41
+ fireEvent.press( screen.getByLabelText( /Paragraph Block. Row 1/ ) );
42
42
 
43
43
  // Focus title
44
44
  fireEvent(
45
- screen.getAllByA11yLabel( 'Post title. test' )[ 0 ],
45
+ screen.getAllByLabelText( 'Post title. test' )[ 0 ],
46
46
  'select'
47
47
  );
48
48
 
49
49
  // Add new Heading block
50
- fireEvent.press( screen.getByA11yLabel( 'Add block' ) );
50
+ fireEvent.press( screen.getByLabelText( 'Add block' ) );
51
51
  fireEvent.press( screen.getByText( 'Heading' ) );
52
52
 
53
- expect( screen.getByA11yLabel( /Heading Block. Row 1/ ) ).toBeDefined();
53
+ expect( screen.getByLabelText( /Heading Block. Row 1/ ) ).toBeDefined();
54
54
  expect(
55
- screen.getByA11yLabel( /Paragraph Block. Row 2/ )
55
+ screen.getByLabelText( /Paragraph Block. Row 2/ )
56
56
  ).toBeDefined();
57
57
  expect(
58
- screen.getByA11yLabel( /Paragraph Block. Row 3/ )
58
+ screen.getByLabelText( /Paragraph Block. Row 3/ )
59
59
  ).toBeDefined();
60
60
  } );
61
61
  } );
@@ -67,27 +67,27 @@ describe( 'when title is no longer focused', () => {
67
67
  } );
68
68
 
69
69
  // Focus first block
70
- fireEvent.press( screen.getByA11yLabel( /Paragraph Block. Row 1/ ) );
70
+ fireEvent.press( screen.getByLabelText( /Paragraph Block. Row 1/ ) );
71
71
 
72
72
  // Focus title
73
73
  fireEvent(
74
- screen.getAllByA11yLabel( 'Post title. test' )[ 0 ],
74
+ screen.getAllByLabelText( 'Post title. test' )[ 0 ],
75
75
  'select'
76
76
  );
77
77
 
78
78
  // Focus last block
79
- fireEvent.press( screen.getByA11yLabel( /Paragraph Block. Row 2/ ) );
79
+ fireEvent.press( screen.getByLabelText( /Paragraph Block. Row 2/ ) );
80
80
 
81
81
  // Add new Heading block
82
- fireEvent.press( screen.getByA11yLabel( 'Add block' ) );
82
+ fireEvent.press( screen.getByLabelText( 'Add block' ) );
83
83
  fireEvent.press( screen.getByText( 'Heading' ) );
84
84
 
85
85
  expect(
86
- screen.getByA11yLabel( /Paragraph Block. Row 1/ )
86
+ screen.getByLabelText( /Paragraph Block. Row 1/ )
87
87
  ).toBeDefined();
88
88
  expect(
89
- screen.getByA11yLabel( /Paragraph Block. Row 2/ )
89
+ screen.getByLabelText( /Paragraph Block. Row 2/ )
90
90
  ).toBeDefined();
91
- expect( screen.getByA11yLabel( /Heading Block. Row 3/ ) ).toBeDefined();
91
+ expect( screen.getByLabelText( /Heading Block. Row 3/ ) ).toBeDefined();
92
92
  } );
93
93
  } );
@@ -1,8 +1,3 @@
1
- /**
2
- * External dependencies
3
- */
4
- import { castArray, reduce } from 'lodash';
5
-
6
1
  /**
7
2
  * WordPress dependencies
8
3
  */
@@ -296,7 +291,10 @@ export const showBlockTypes =
296
291
  .get( 'core/edit-post', 'hiddenBlockTypes' ) ?? [];
297
292
 
298
293
  const newBlockNames = existingBlockNames.filter(
299
- ( type ) => ! castArray( blockNames ).includes( type )
294
+ ( type ) =>
295
+ ! (
296
+ Array.isArray( blockNames ) ? blockNames : [ blockNames ]
297
+ ).includes( type )
300
298
  );
301
299
 
302
300
  registry
@@ -319,7 +317,7 @@ export const hideBlockTypes =
319
317
 
320
318
  const mergedBlockNames = new Set( [
321
319
  ...existingBlockNames,
322
- ...castArray( blockNames ),
320
+ ...( Array.isArray( blockNames ) ? blockNames : [ blockNames ] ),
323
321
  ] );
324
322
 
325
323
  registry
@@ -330,18 +328,16 @@ export const hideBlockTypes =
330
328
  };
331
329
 
332
330
  /**
333
- * Returns an action object used in signaling
334
- * what Meta boxes are available in which location.
331
+ * Stores info about which Meta boxes are available in which location.
335
332
  *
336
333
  * @param {Object} metaBoxesPerLocation Meta boxes per location.
337
334
  */
338
- export const setAvailableMetaBoxesPerLocation =
339
- ( metaBoxesPerLocation ) =>
340
- ( { dispatch } ) =>
341
- dispatch( {
342
- type: 'SET_META_BOXES_PER_LOCATIONS',
343
- metaBoxesPerLocation,
344
- } );
335
+ export function setAvailableMetaBoxesPerLocation( metaBoxesPerLocation ) {
336
+ return {
337
+ type: 'SET_META_BOXES_PER_LOCATIONS',
338
+ metaBoxesPerLocation,
339
+ };
340
+ }
345
341
 
346
342
  /**
347
343
  * Update a metabox.
@@ -384,16 +380,12 @@ export const requestMetaBoxUpdates =
384
380
  ];
385
381
 
386
382
  // Merge all form data objects into a single one.
387
- const formData = reduce(
388
- formDataToMerge,
389
- ( memo, currentFormData ) => {
390
- for ( const [ key, value ] of currentFormData ) {
391
- memo.append( key, value );
392
- }
393
- return memo;
394
- },
395
- new window.FormData()
396
- );
383
+ const formData = formDataToMerge.reduce( ( memo, currentFormData ) => {
384
+ for ( const [ key, value ] of currentFormData ) {
385
+ memo.append( key, value );
386
+ }
387
+ return memo;
388
+ }, new window.FormData() );
397
389
  additionalData.forEach( ( [ key, value ] ) =>
398
390
  formData.append( key, value )
399
391
  );
@@ -566,7 +558,6 @@ export const initializeMetaBoxes =
566
558
  let wasAutosavingPost = registry
567
559
  .select( editorStore )
568
560
  .isAutosavingPost();
569
- const hasMetaBoxes = select.hasMetaBoxes();
570
561
 
571
562
  // Save metaboxes when performing a full save on the post.
572
563
  registry.subscribe( async () => {
@@ -575,17 +566,12 @@ export const initializeMetaBoxes =
575
566
  .select( editorStore )
576
567
  .isAutosavingPost();
577
568
 
578
- // Save metaboxes on save completion, except for autosaves that are not a post preview.
579
- //
580
- // Meta boxes are initialized once at page load. It is not necessary to
581
- // account for updates on each state change.
582
- //
583
- // See: https://github.com/WordPress/WordPress/blob/5.1.1/wp-admin/includes/post.php#L2307-L2309.
569
+ // Save metaboxes on save completion, except for autosaves.
584
570
  const shouldTriggerMetaboxesSave =
585
- hasMetaBoxes &&
586
571
  wasSavingPost &&
572
+ ! wasAutosavingPost &&
587
573
  ! isSavingPost &&
588
- ! wasAutosavingPost;
574
+ select.hasMetaBoxes();
589
575
 
590
576
  // Save current state for next inspection.
591
577
  wasSavingPost = isSavingPost;
@@ -1,8 +1,3 @@
1
- /**
2
- * External dependencies
3
- */
4
- import { includes } from 'lodash';
5
-
6
1
  /**
7
2
  * WordPress dependencies
8
3
  */
@@ -19,7 +14,7 @@ import { combineReducers } from '@wordpress/data';
19
14
  export function removedPanels( state = [], action ) {
20
15
  switch ( action.type ) {
21
16
  case 'REMOVE_PANEL':
22
- if ( ! includes( state, action.panelName ) ) {
17
+ if ( ! state.includes( action.panelName ) ) {
23
18
  return [ ...state, action.panelName ];
24
19
  }
25
20
  }
@@ -80,6 +75,21 @@ export function isSavingMetaBoxes( state = false, action ) {
80
75
  }
81
76
  }
82
77
 
78
+ function mergeMetaboxes( metaboxes = [], newMetaboxes ) {
79
+ const mergedMetaboxes = [ ...metaboxes ];
80
+ for ( const metabox of newMetaboxes ) {
81
+ const existing = mergedMetaboxes.findIndex(
82
+ ( box ) => box.id === metabox.id
83
+ );
84
+ if ( existing !== -1 ) {
85
+ mergedMetaboxes[ existing ] = metabox;
86
+ } else {
87
+ mergedMetaboxes.push( metabox );
88
+ }
89
+ }
90
+ return mergedMetaboxes;
91
+ }
92
+
83
93
  /**
84
94
  * Reducer keeping track of the meta boxes per location.
85
95
  *
@@ -90,8 +100,18 @@ export function isSavingMetaBoxes( state = false, action ) {
90
100
  */
91
101
  export function metaBoxLocations( state = {}, action ) {
92
102
  switch ( action.type ) {
93
- case 'SET_META_BOXES_PER_LOCATIONS':
94
- return action.metaBoxesPerLocation;
103
+ case 'SET_META_BOXES_PER_LOCATIONS': {
104
+ const newState = { ...state };
105
+ for ( const [ location, metaboxes ] of Object.entries(
106
+ action.metaBoxesPerLocation
107
+ ) ) {
108
+ newState[ location ] = mergeMetaboxes(
109
+ newState[ location ],
110
+ metaboxes
111
+ );
112
+ }
113
+ return newState;
114
+ }
95
115
  }
96
116
 
97
117
  return state;
@@ -78,14 +78,44 @@ describe( 'state', () => {
78
78
  const action = {
79
79
  type: 'SET_META_BOXES_PER_LOCATIONS',
80
80
  metaBoxesPerLocation: {
81
- normal: [ 'postcustom' ],
81
+ normal: [ { id: 'postcustom' } ],
82
82
  },
83
83
  };
84
84
 
85
85
  const state = metaBoxLocations( undefined, action );
86
86
 
87
87
  expect( state ).toEqual( {
88
- normal: [ 'postcustom' ],
88
+ normal: [ { id: 'postcustom' } ],
89
+ } );
90
+ } );
91
+
92
+ it( 'should merge new meta box locations into the existing ones', () => {
93
+ const oldState = {
94
+ normal: [
95
+ { id: 'a', title: 'A' },
96
+ { id: 'b', title: 'B' },
97
+ ],
98
+ side: [ { id: 's', title: 'S' } ],
99
+ };
100
+ const action = {
101
+ type: 'SET_META_BOXES_PER_LOCATIONS',
102
+ metaBoxesPerLocation: {
103
+ normal: [
104
+ { id: 'b', title: 'B-updated' },
105
+ { id: 'c', title: 'C' },
106
+ ],
107
+ advanced: [ { id: 'd', title: 'D' } ],
108
+ },
109
+ };
110
+ const newState = metaBoxLocations( oldState, action );
111
+ expect( newState ).toEqual( {
112
+ normal: [
113
+ { id: 'a', title: 'A' },
114
+ { id: 'b', title: 'B-updated' },
115
+ { id: 'c', title: 'C' },
116
+ ],
117
+ advanced: [ { id: 'd', title: 'D' } ],
118
+ side: [ { id: 's', title: 'S' } ],
89
119
  } );
90
120
  } );
91
121
  } );
@@ -1,3 +0,0 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`PluginPrePublishPanel renders fill properly 1`] = `"<div class=\\"components-panel__body my-plugin-pre-publish-panel is-opened\\"><h2 class=\\"components-panel__body-title\\"><button type=\\"button\\" aria-expanded=\\"true\\" class=\\"components-button components-panel__body-toggle\\"><span aria-hidden=\\"true\\"><svg viewBox=\\"0 0 24 24\\" xmlns=\\"http://www.w3.org/2000/svg\\" width=\\"24\\" height=\\"24\\" class=\\"components-panel__arrow\\" aria-hidden=\\"true\\" focusable=\\"false\\"><path d=\\"M6.5 12.4L12 8l5.5 4.4-.9 1.2L12 10l-4.5 3.6-1-1.2z\\"></path></svg></span>My panel title</button></h2>My panel content</div>"`;