UNPKG

5.96 kBJavaScriptView Raw
1/**
2 * External dependencies
3 */
4import { reduce } from 'lodash';
5
6/**
7 * WordPress dependencies
8 */
9import { select, subscribe, dispatch } from '@wordpress/data';
10import { speak } from '@wordpress/a11y';
11import { __ } from '@wordpress/i18n';
12import apiFetch from '@wordpress/api-fetch';
13
14/**
15 * Internal dependencies
16 */
17import {
18 metaBoxUpdatesSuccess,
19 requestMetaBoxUpdates,
20 openGeneralSidebar,
21 closeGeneralSidebar,
22} from './actions';
23import {
24 getActiveMetaBoxLocations,
25 getActiveGeneralSidebarName,
26} from './selectors';
27import { getMetaBoxContainer } from '../utils/meta-boxes';
28import { onChangeListener } from './utils';
29
30const VIEW_AS_LINK_SELECTOR = '#wp-admin-bar-view a';
31
32const effects = {
33 SET_META_BOXES_PER_LOCATIONS( action, store ) {
34 // Allow toggling metaboxes panels
35 // We need to wait for all scripts to load
36 // If the meta box loads the post script, it will already trigger this.
37 // After merge in Core, make sure to drop the timeout and update the postboxes script
38 // to avoid the double binding.
39 setTimeout( () => {
40 const postType = select( 'core/editor' ).getCurrentPostType();
41 if ( window.postboxes.page !== postType ) {
42 window.postboxes.add_postbox_toggles( postType );
43 }
44 } );
45
46 let wasSavingPost = select( 'core/editor' ).isSavingPost();
47 let wasAutosavingPost = select( 'core/editor' ).isAutosavingPost();
48 // Save metaboxes when performing a full save on the post.
49 subscribe( () => {
50 const isSavingPost = select( 'core/editor' ).isSavingPost();
51 const isAutosavingPost = select( 'core/editor' ).isAutosavingPost();
52 const hasActiveMetaBoxes = select( 'core/edit-post' ).hasMetaBoxes();
53
54 // Save metaboxes on save completion, except for autosaves that are not a post preview.
55 const shouldTriggerMetaboxesSave = (
56 hasActiveMetaBoxes && (
57 ( wasSavingPost && ! isSavingPost && ! wasAutosavingPost )
58 )
59 );
60
61 // Save current state for next inspection.
62 wasSavingPost = isSavingPost;
63 wasAutosavingPost = isAutosavingPost;
64
65 if ( shouldTriggerMetaboxesSave ) {
66 store.dispatch( requestMetaBoxUpdates() );
67 }
68 } );
69 },
70 REQUEST_META_BOX_UPDATES( action, store ) {
71 // Saves the wp_editor fields
72 if ( window.tinyMCE ) {
73 window.tinyMCE.triggerSave();
74 }
75
76 const state = store.getState();
77
78 // Additional data needed for backward compatibility.
79 // If we do not provide this data, the post will be overridden with the default values.
80 const post = select( 'core/editor' ).getCurrentPost( state );
81 const additionalData = [
82 post.comment_status ? [ 'comment_status', post.comment_status ] : false,
83 post.ping_status ? [ 'ping_status', post.ping_status ] : false,
84 post.sticky ? [ 'sticky', post.sticky ] : false,
85 [ 'post_author', post.author ],
86 ].filter( Boolean );
87
88 // We gather all the metaboxes locations data and the base form data
89 const baseFormData = new window.FormData( document.querySelector( '.metabox-base-form' ) );
90 const formDataToMerge = [
91 baseFormData,
92 ...getActiveMetaBoxLocations( state ).map( ( location ) => (
93 new window.FormData( getMetaBoxContainer( location ) )
94 ) ),
95 ];
96
97 // Merge all form data objects into a single one.
98 const formData = reduce( formDataToMerge, ( memo, currentFormData ) => {
99 for ( const [ key, value ] of currentFormData ) {
100 memo.append( key, value );
101 }
102 return memo;
103 }, new window.FormData() );
104 additionalData.forEach( ( [ key, value ] ) => formData.append( key, value ) );
105
106 // Save the metaboxes
107 apiFetch( {
108 url: window._wpMetaBoxUrl,
109 method: 'POST',
110 body: formData,
111 parse: false,
112 } )
113 .then( () => store.dispatch( metaBoxUpdatesSuccess() ) );
114 },
115 SWITCH_MODE( action ) {
116 // Unselect blocks when we switch to the code editor.
117 if ( action.mode !== 'visual' ) {
118 dispatch( 'core/block-editor' ).clearSelectedBlock();
119 }
120
121 const message = action.mode === 'visual' ? __( 'Visual editor selected' ) : __( 'Code editor selected' );
122 speak( message, 'assertive' );
123 },
124 INIT( _, store ) {
125 // Select the block settings tab when the selected block changes
126 subscribe( onChangeListener(
127 () => !! select( 'core/block-editor' ).getBlockSelectionStart(),
128 ( hasBlockSelection ) => {
129 if ( ! select( 'core/edit-post' ).isEditorSidebarOpened() ) {
130 return;
131 }
132 if ( hasBlockSelection ) {
133 store.dispatch( openGeneralSidebar( 'edit-post/block' ) );
134 } else {
135 store.dispatch( openGeneralSidebar( 'edit-post/document' ) );
136 }
137 } )
138 );
139
140 const isMobileViewPort = () => select( 'core/viewport' ).isViewportMatch( '< medium' );
141 const adjustSidebar = ( () => {
142 // contains the sidebar we close when going to viewport sizes lower than medium.
143 // This allows to reopen it when going again to viewport sizes greater than medium.
144 let sidebarToReOpenOnExpand = null;
145 return ( isSmall ) => {
146 if ( isSmall ) {
147 sidebarToReOpenOnExpand = getActiveGeneralSidebarName( store.getState() );
148 if ( sidebarToReOpenOnExpand ) {
149 store.dispatch( closeGeneralSidebar() );
150 }
151 } else if ( sidebarToReOpenOnExpand && ! getActiveGeneralSidebarName( store.getState() ) ) {
152 store.dispatch( openGeneralSidebar( sidebarToReOpenOnExpand ) );
153 }
154 };
155 } )();
156
157 adjustSidebar( isMobileViewPort() );
158
159 // Collapse sidebar when viewport shrinks.
160 // Reopen sidebar it if viewport expands and it was closed because of a previous shrink.
161 subscribe( onChangeListener( isMobileViewPort, adjustSidebar ) );
162
163 // Update View as link when currentPost link changes
164 const updateViewAsLink = ( newPermalink ) => {
165 if ( ! newPermalink ) {
166 return;
167 }
168
169 const nodeToUpdate = document.querySelector(
170 VIEW_AS_LINK_SELECTOR
171 );
172 if ( ! nodeToUpdate ) {
173 return;
174 }
175 nodeToUpdate.setAttribute( 'href', newPermalink );
176 };
177
178 subscribe( onChangeListener(
179 () => select( 'core/editor' ).getCurrentPost().link,
180 updateViewAsLink
181 ) );
182 },
183
184};
185
186export default effects;