@wordpress/edit-post 6.16.0 → 6.18.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 (107) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/build/components/block-manager/category.js +2 -2
  3. package/build/components/block-manager/category.js.map +1 -1
  4. package/build/components/block-manager/index.js +1 -1
  5. package/build/components/block-manager/index.js.map +1 -1
  6. package/build/components/device-preview/index.js +3 -0
  7. package/build/components/device-preview/index.js.map +1 -1
  8. package/build/components/header/header-toolbar/index.js +0 -6
  9. package/build/components/header/header-toolbar/index.js.map +1 -1
  10. package/build/components/header/index.js +52 -8
  11. package/build/components/header/index.js.map +1 -1
  12. package/build/components/header/writing-menu/index.js +49 -1
  13. package/build/components/header/writing-menu/index.js.map +1 -1
  14. package/build/components/keyboard-shortcut-help-modal/shortcut.js +1 -7
  15. package/build/components/keyboard-shortcut-help-modal/shortcut.js.map +1 -1
  16. package/build/components/keyboard-shortcuts/index.js +41 -2
  17. package/build/components/keyboard-shortcuts/index.js.map +1 -1
  18. package/build/components/layout/index.js +9 -8
  19. package/build/components/layout/index.js.map +1 -1
  20. package/build/components/preferences-modal/index.js +27 -8
  21. package/build/components/preferences-modal/index.js.map +1 -1
  22. package/build/components/preferences-modal/options/enable-feature.js +6 -2
  23. package/build/components/preferences-modal/options/enable-feature.js.map +1 -1
  24. package/build/components/secondary-sidebar/list-view-outline.js +119 -0
  25. package/build/components/secondary-sidebar/list-view-outline.js.map +1 -0
  26. package/build/components/secondary-sidebar/list-view-sidebar.js +36 -11
  27. package/build/components/secondary-sidebar/list-view-sidebar.js.map +1 -1
  28. package/build/components/visual-editor/index.js +4 -1
  29. package/build/components/visual-editor/index.js.map +1 -1
  30. package/build/editor.js +5 -5
  31. package/build/editor.js.map +1 -1
  32. package/build/editor.native.js +1 -1
  33. package/build/editor.native.js.map +1 -1
  34. package/build/store/actions.js +23 -34
  35. package/build/store/actions.js.map +1 -1
  36. package/build/store/reducer.js +30 -9
  37. package/build/store/reducer.js.map +1 -1
  38. package/build-module/components/block-manager/category.js +3 -3
  39. package/build-module/components/block-manager/category.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/device-preview/index.js +3 -0
  43. package/build-module/components/device-preview/index.js.map +1 -1
  44. package/build-module/components/header/header-toolbar/index.js +1 -7
  45. package/build-module/components/header/header-toolbar/index.js.map +1 -1
  46. package/build-module/components/header/index.js +51 -8
  47. package/build-module/components/header/index.js.map +1 -1
  48. package/build-module/components/header/writing-menu/index.js +47 -2
  49. package/build-module/components/header/writing-menu/index.js.map +1 -1
  50. package/build-module/components/keyboard-shortcut-help-modal/shortcut.js +1 -6
  51. package/build-module/components/keyboard-shortcut-help-modal/shortcut.js.map +1 -1
  52. package/build-module/components/keyboard-shortcuts/index.js +39 -2
  53. package/build-module/components/keyboard-shortcuts/index.js.map +1 -1
  54. package/build-module/components/layout/index.js +10 -9
  55. package/build-module/components/layout/index.js.map +1 -1
  56. package/build-module/components/preferences-modal/index.js +26 -8
  57. package/build-module/components/preferences-modal/index.js.map +1 -1
  58. package/build-module/components/preferences-modal/options/enable-feature.js +6 -2
  59. package/build-module/components/preferences-modal/options/enable-feature.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 +34 -12
  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/editor.js +6 -6
  67. package/build-module/editor.js.map +1 -1
  68. package/build-module/editor.native.js +2 -2
  69. package/build-module/editor.native.js.map +1 -1
  70. package/build-module/store/actions.js +22 -32
  71. package/build-module/store/actions.js.map +1 -1
  72. package/build-module/store/reducer.js +31 -8
  73. package/build-module/store/reducer.js.map +1 -1
  74. package/build-style/style-rtl.css +92 -6
  75. package/build-style/style.css +92 -6
  76. package/package.json +27 -27
  77. package/src/components/block-manager/category.js +4 -5
  78. package/src/components/block-manager/index.js +2 -2
  79. package/src/components/device-preview/index.js +2 -0
  80. package/src/components/editor-initialization/test/listener-hooks.js +47 -49
  81. package/src/components/header/fullscreen-mode-close/test/__snapshots__/index.js.snap +26 -0
  82. package/src/components/header/fullscreen-mode-close/test/index.js +10 -12
  83. package/src/components/header/header-toolbar/index.js +0 -8
  84. package/src/components/header/index.js +33 -11
  85. package/src/components/header/style.scss +43 -0
  86. package/src/components/header/writing-menu/index.js +53 -2
  87. package/src/components/keyboard-shortcut-help-modal/shortcut.js +15 -18
  88. package/src/components/keyboard-shortcuts/index.js +46 -2
  89. package/src/components/layout/index.js +10 -7
  90. package/src/components/layout/style.scss +7 -0
  91. package/src/components/preferences-modal/index.js +35 -19
  92. package/src/components/preferences-modal/options/enable-feature.js +5 -2
  93. package/src/components/preferences-modal/options/test/__snapshots__/enable-custom-fields.js.snap +128 -132
  94. package/src/components/preferences-modal/options/test/enable-custom-fields.js +35 -30
  95. package/src/components/preferences-modal/test/__snapshots__/index.js.snap +9 -9
  96. package/src/components/preferences-modal/test/index.js +3 -3
  97. package/src/components/secondary-sidebar/list-view-outline.js +98 -0
  98. package/src/components/secondary-sidebar/list-view-sidebar.js +47 -8
  99. package/src/components/secondary-sidebar/style.scss +64 -8
  100. package/src/components/sidebar/plugin-post-status-info/test/__snapshots__/index.js.snap +6 -4
  101. package/src/components/sidebar/plugin-post-status-info/test/index.js +4 -4
  102. package/src/components/visual-editor/index.js +9 -3
  103. package/src/editor.js +7 -8
  104. package/src/editor.native.js +3 -4
  105. package/src/store/actions.js +17 -23
  106. package/src/store/reducer.js +29 -9
  107. package/src/store/test/reducer.js +32 -2
@@ -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 }
46
+ aria-label={ __( 'List View' ) }
42
47
  className="edit-post-editor__list-view-panel"
43
48
  onKeyDown={ closeOnEscape }
44
49
  >
45
50
  <div
46
- className="edit-post-editor__list-view-panel-header"
51
+ className="edit-post-editor__list-view-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
56
  label={ __( 'Close List View 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
  );
@@ -8,7 +8,12 @@
8
8
  .edit-post-editor__list-view-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
34
  .edit-post-editor__list-view-panel-header {
34
- align-items: center;
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
- className="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
  `;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import ReactTestRenderer from 'react-test-renderer';
4
+ import { render } from '@testing-library/react';
5
5
 
6
6
  /**
7
7
  * WordPress dependencies
@@ -15,15 +15,15 @@ import PluginPostStatusInfo from '../';
15
15
 
16
16
  describe( 'PluginPostStatusInfo', () => {
17
17
  test( 'renders fill properly', () => {
18
- const tree = ReactTestRenderer.create(
18
+ const { container } = render(
19
19
  <SlotFillProvider>
20
20
  <PluginPostStatusInfo className="my-plugin-post-status-info">
21
21
  My plugin post status info
22
22
  </PluginPostStatusInfo>
23
23
  <PluginPostStatusInfo.Slot />
24
24
  </SlotFillProvider>
25
- ).toJSON();
25
+ );
26
26
 
27
- expect( tree ).toMatchSnapshot();
27
+ expect( container ).toMatchSnapshot();
28
28
  } );
29
29
  } );
@@ -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
  };
package/src/editor.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { map, without } from 'lodash';
4
+ import { map } from 'lodash';
5
5
 
6
6
  /**
7
7
  * WordPress dependencies
@@ -38,7 +38,7 @@ function Editor( {
38
38
  const {
39
39
  hasFixedToolbar,
40
40
  focusMode,
41
- hasReducedUI,
41
+ isDistractionFree,
42
42
  hasInlineToolbar,
43
43
  hasThemeStyles,
44
44
  post,
@@ -85,7 +85,7 @@ function Editor( {
85
85
  isFeatureActive( 'fixedToolbar' ) ||
86
86
  __experimentalGetPreviewDeviceType() !== 'Desktop',
87
87
  focusMode: isFeatureActive( 'focusMode' ),
88
- hasReducedUI: isFeatureActive( 'reducedUI' ),
88
+ isDistractionFree: isFeatureActive( 'distractionFree' ),
89
89
  hasInlineToolbar: isFeatureActive( 'inlineToolbar' ),
90
90
  hasThemeStyles: isFeatureActive( 'themeStyles' ),
91
91
  preferredStyleVariations: select( preferencesStore ).get(
@@ -118,7 +118,7 @@ function Editor( {
118
118
  },
119
119
  hasFixedToolbar,
120
120
  focusMode,
121
- hasReducedUI,
121
+ isDistractionFree,
122
122
  hasInlineToolbar,
123
123
 
124
124
  // This is marked as experimental to give time for the quick inserter to mature.
@@ -139,9 +139,8 @@ function Editor( {
139
139
  ? map( blockTypes, 'name' )
140
140
  : settings.allowedBlockTypes || [];
141
141
 
142
- result.allowedBlockTypes = without(
143
- defaultAllowedBlockTypes,
144
- ...hiddenBlockTypes
142
+ result.allowedBlockTypes = defaultAllowedBlockTypes.filter(
143
+ ( type ) => ! hiddenBlockTypes.includes( type )
145
144
  );
146
145
  }
147
146
 
@@ -150,7 +149,7 @@ function Editor( {
150
149
  settings,
151
150
  hasFixedToolbar,
152
151
  focusMode,
153
- hasReducedUI,
152
+ isDistractionFree,
154
153
  hiddenBlockTypes,
155
154
  blockTypes,
156
155
  preferredStyleVariations,
@@ -2,7 +2,7 @@
2
2
  * External dependencies
3
3
  */
4
4
  import memize from 'memize';
5
- import { map, without } from 'lodash';
5
+ import { map } from 'lodash';
6
6
  import { I18nManager } from 'react-native';
7
7
 
8
8
  /**
@@ -76,9 +76,8 @@ class Editor extends Component {
76
76
  ? map( blockTypes, 'name' )
77
77
  : settings.allowedBlockTypes || [];
78
78
 
79
- settings.allowedBlockTypes = without(
80
- defaultAllowedBlockTypes,
81
- ...hiddenBlockTypes
79
+ settings.allowedBlockTypes = defaultAllowedBlockTypes.filter(
80
+ ( type ) => ! hiddenBlockTypes.includes( type )
82
81
  );
83
82
  }
84
83
 
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { castArray, reduce, without } from 'lodash';
4
+ import { reduce } from 'lodash';
5
5
 
6
6
  /**
7
7
  * WordPress dependencies
@@ -295,9 +295,11 @@ export const showBlockTypes =
295
295
  .select( preferencesStore )
296
296
  .get( 'core/edit-post', 'hiddenBlockTypes' ) ?? [];
297
297
 
298
- const newBlockNames = without(
299
- existingBlockNames,
300
- ...castArray( blockNames )
298
+ const newBlockNames = existingBlockNames.filter(
299
+ ( type ) =>
300
+ ! (
301
+ Array.isArray( blockNames ) ? blockNames : [ blockNames ]
302
+ ).includes( type )
301
303
  );
302
304
 
303
305
  registry
@@ -320,7 +322,7 @@ export const hideBlockTypes =
320
322
 
321
323
  const mergedBlockNames = new Set( [
322
324
  ...existingBlockNames,
323
- ...castArray( blockNames ),
325
+ ...( Array.isArray( blockNames ) ? blockNames : [ blockNames ] ),
324
326
  ] );
325
327
 
326
328
  registry
@@ -331,18 +333,16 @@ export const hideBlockTypes =
331
333
  };
332
334
 
333
335
  /**
334
- * Returns an action object used in signaling
335
- * what Meta boxes are available in which location.
336
+ * Stores info about which Meta boxes are available in which location.
336
337
  *
337
338
  * @param {Object} metaBoxesPerLocation Meta boxes per location.
338
339
  */
339
- export const setAvailableMetaBoxesPerLocation =
340
- ( metaBoxesPerLocation ) =>
341
- ( { dispatch } ) =>
342
- dispatch( {
343
- type: 'SET_META_BOXES_PER_LOCATIONS',
344
- metaBoxesPerLocation,
345
- } );
340
+ export function setAvailableMetaBoxesPerLocation( metaBoxesPerLocation ) {
341
+ return {
342
+ type: 'SET_META_BOXES_PER_LOCATIONS',
343
+ metaBoxesPerLocation,
344
+ };
345
+ }
346
346
 
347
347
  /**
348
348
  * Update a metabox.
@@ -567,7 +567,6 @@ export const initializeMetaBoxes =
567
567
  let wasAutosavingPost = registry
568
568
  .select( editorStore )
569
569
  .isAutosavingPost();
570
- const hasMetaBoxes = select.hasMetaBoxes();
571
570
 
572
571
  // Save metaboxes when performing a full save on the post.
573
572
  registry.subscribe( async () => {
@@ -576,17 +575,12 @@ export const initializeMetaBoxes =
576
575
  .select( editorStore )
577
576
  .isAutosavingPost();
578
577
 
579
- // Save metaboxes on save completion, except for autosaves that are not a post preview.
580
- //
581
- // Meta boxes are initialized once at page load. It is not necessary to
582
- // account for updates on each state change.
583
- //
584
- // See: https://github.com/WordPress/WordPress/blob/5.1.1/wp-admin/includes/post.php#L2307-L2309.
578
+ // Save metaboxes on save completion, except for autosaves.
585
579
  const shouldTriggerMetaboxesSave =
586
- hasMetaBoxes &&
587
580
  wasSavingPost &&
581
+ ! wasAutosavingPost &&
588
582
  ! isSavingPost &&
589
- ! wasAutosavingPost;
583
+ select.hasMetaBoxes();
590
584
 
591
585
  // Save current state for next inspection.
592
586
  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;
@@ -153,7 +173,7 @@ export function listViewPanel( state = false, action ) {
153
173
  }
154
174
 
155
175
  /**
156
- * Reducer tracking whether the inserter is open.
176
+ * Reducer tracking whether template editing is on or off.
157
177
  *
158
178
  * @param {boolean} state
159
179
  * @param {Object} action
@@ -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
  } );