Skip to content

Commit 3caec34

Browse files
authored
Revert refactoring hierarchical term selector using the data module (#11395)
1 parent 94d2b7f commit 3caec34

File tree

5 files changed

+136
-114
lines changed

5 files changed

+136
-114
lines changed

docs/data/data-core-editor.md

-9
Original file line numberDiff line numberDiff line change
@@ -1769,15 +1769,6 @@ Returns an action object used to signal that post saving is unlocked.
17691769

17701770
* lockName: The lock name.
17711771

1772-
### addTermToEditedPost
1773-
1774-
Returns an action object signaling that a new term is added to the edited post.
1775-
1776-
*Parameters*
1777-
1778-
* slug: Taxonomy slug.
1779-
* term: Term object.
1780-
17811772
### createNotice
17821773

17831774
### fetchReusableBlocks

packages/editor/src/components/post-taxonomies/hierarchical-term-selector.js

+136-44
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* External dependencies
33
*/
4-
import { get, unescape as unescapeString, without, find, some } from 'lodash';
4+
import { get, unescape as unescapeString, without, find, some, invoke } from 'lodash';
55

66
/**
77
* WordPress dependencies
@@ -11,6 +11,8 @@ import { Component } from '@wordpress/element';
1111
import { TreeSelect, withSpokenMessages, withFilters, Button } from '@wordpress/components';
1212
import { withSelect, withDispatch } from '@wordpress/data';
1313
import { withInstanceId, compose } from '@wordpress/compose';
14+
import apiFetch from '@wordpress/api-fetch';
15+
import { addQueryArgs } from '@wordpress/url';
1416

1517
/**
1618
* Internal dependencies
@@ -24,6 +26,7 @@ const DEFAULT_QUERY = {
2426
per_page: -1,
2527
orderby: 'name',
2628
order: 'asc',
29+
_fields: 'id,name,parent',
2730
};
2831

2932
const MIN_TERMS_COUNT_FOR_FILTER = 8;
@@ -38,7 +41,12 @@ class HierarchicalTermSelector extends Component {
3841
this.onAddTerm = this.onAddTerm.bind( this );
3942
this.onToggleForm = this.onToggleForm.bind( this );
4043
this.setFilterValue = this.setFilterValue.bind( this );
44+
this.sortBySelected = this.sortBySelected.bind( this );
4145
this.state = {
46+
loading: true,
47+
availableTermsTree: [],
48+
availableTerms: [],
49+
adding: false,
4250
formName: '',
4351
formParent: '',
4452
showForm: false,
@@ -48,13 +56,13 @@ class HierarchicalTermSelector extends Component {
4856
}
4957

5058
onChange( event ) {
51-
const { onUpdateTerms, terms = [] } = this.props;
59+
const { onUpdateTerms, terms = [], taxonomy } = this.props;
5260
const termId = parseInt( event.target.value, 10 );
5361
const hasTerm = terms.indexOf( termId ) !== -1;
5462
const newTerms = hasTerm ?
5563
without( terms, termId ) :
5664
[ ...terms, termId ];
57-
onUpdateTerms( newTerms );
65+
onUpdateTerms( newTerms, taxonomy.rest_base );
5866
}
5967

6068
onChangeFormName( event ) {
@@ -81,9 +89,9 @@ class HierarchicalTermSelector extends Component {
8189

8290
onAddTerm( event ) {
8391
event.preventDefault();
84-
const { onUpdateTerms, addTermToEditedPost, terms, availableTerms } = this.props;
85-
const { formName, formParent } = this.state;
86-
if ( formName === '' ) {
92+
const { onUpdateTerms, taxonomy, terms, slug } = this.props;
93+
const { formName, formParent, adding, availableTerms } = this.state;
94+
if ( formName === '' || adding ) {
8795
return;
8896
}
8997

@@ -92,7 +100,7 @@ class HierarchicalTermSelector extends Component {
92100
if ( existingTerm ) {
93101
// if the term we are adding exists but is not selected select it
94102
if ( ! some( terms, ( term ) => term === existingTerm.id ) ) {
95-
onUpdateTerms( [ ...terms, existingTerm.id ] );
103+
onUpdateTerms( [ ...terms, existingTerm.id ], taxonomy.rest_base );
96104
}
97105
this.setState( {
98106
formName: '',
@@ -101,14 +109,113 @@ class HierarchicalTermSelector extends Component {
101109
return;
102110
}
103111

104-
addTermToEditedPost( {
105-
name: formName,
106-
parent: formParent ? formParent : undefined,
107-
} );
108112
this.setState( {
109-
formName: '',
110-
formParent: '',
113+
adding: true,
114+
} );
115+
this.addRequest = apiFetch( {
116+
path: `/wp/v2/${ taxonomy.rest_base }`,
117+
method: 'POST',
118+
data: {
119+
name: formName,
120+
parent: formParent ? formParent : undefined,
121+
},
122+
} );
123+
// Tries to create a term or fetch it if it already exists
124+
const findOrCreatePromise = this.addRequest
125+
.catch( ( error ) => {
126+
const errorCode = error.code;
127+
if ( errorCode === 'term_exists' ) {
128+
// search the new category created since last fetch
129+
this.addRequest = apiFetch( {
130+
path: addQueryArgs(
131+
`/wp/v2/${ taxonomy.rest_base }`,
132+
{ ...DEFAULT_QUERY, parent: formParent || 0, search: formName }
133+
),
134+
} );
135+
return this.addRequest
136+
.then( ( searchResult ) => {
137+
return this.findTerm( searchResult, formParent, formName );
138+
} );
139+
}
140+
return Promise.reject( error );
141+
} );
142+
findOrCreatePromise
143+
.then( ( term ) => {
144+
const hasTerm = !! find( this.state.availableTerms, ( availableTerm ) => availableTerm.id === term.id );
145+
const newAvailableTerms = hasTerm ? this.state.availableTerms : [ term, ...this.state.availableTerms ];
146+
const termAddedMessage = sprintf(
147+
_x( '%s added', 'term' ),
148+
get(
149+
this.props.taxonomy,
150+
[ 'labels', 'singular_name' ],
151+
slug === 'category' ? __( 'Category' ) : __( 'Term' )
152+
)
153+
);
154+
this.props.speak( termAddedMessage, 'assertive' );
155+
this.addRequest = null;
156+
this.setState( {
157+
adding: false,
158+
formName: '',
159+
formParent: '',
160+
availableTerms: newAvailableTerms,
161+
availableTermsTree: this.sortBySelected( buildTermsTree( newAvailableTerms ) ),
162+
} );
163+
onUpdateTerms( [ ...terms, term.id ], taxonomy.rest_base );
164+
}, ( xhr ) => {
165+
if ( xhr.statusText === 'abort' ) {
166+
return;
167+
}
168+
this.addRequest = null;
169+
this.setState( {
170+
adding: false,
171+
} );
172+
} );
173+
}
174+
175+
componentDidMount() {
176+
this.fetchTerms();
177+
}
178+
179+
componentWillUnmount() {
180+
invoke( this.fetchRequest, [ 'abort' ] );
181+
invoke( this.addRequest, [ 'abort' ] );
182+
}
183+
184+
componentDidUpdate( prevProps ) {
185+
if ( this.props.taxonomy !== prevProps.taxonomy ) {
186+
this.fetchTerms();
187+
}
188+
}
189+
190+
fetchTerms() {
191+
const { taxonomy } = this.props;
192+
if ( ! taxonomy ) {
193+
return;
194+
}
195+
this.fetchRequest = apiFetch( {
196+
path: addQueryArgs( `/wp/v2/${ taxonomy.rest_base }`, DEFAULT_QUERY ),
111197
} );
198+
this.fetchRequest.then(
199+
( terms ) => { // resolve
200+
const availableTermsTree = this.sortBySelected( buildTermsTree( terms ) );
201+
202+
this.fetchRequest = null;
203+
this.setState( {
204+
loading: false,
205+
availableTermsTree,
206+
availableTerms: terms,
207+
} );
208+
},
209+
( xhr ) => { // reject
210+
if ( xhr.statusText === 'abort' ) {
211+
return;
212+
}
213+
this.fetchRequest = null;
214+
this.setState( {
215+
loading: false,
216+
} );
217+
}
218+
);
112219
}
113220

114221
sortBySelected( termsTree ) {
@@ -149,7 +256,7 @@ class HierarchicalTermSelector extends Component {
149256
}
150257

151258
setFilterValue( event ) {
152-
const { availableTermsTree } = this.props;
259+
const { availableTermsTree } = this.state;
153260
const filterValue = event.target.value;
154261
const filteredTermsTree = availableTermsTree.map( this.getFilterMatcher( filterValue ) ).filter( ( term ) => term );
155262
const getResultCount = ( terms ) => {
@@ -162,10 +269,12 @@ class HierarchicalTermSelector extends Component {
162269
}
163270
return count;
164271
};
165-
this.setState( {
166-
filterValue,
167-
filteredTermsTree,
168-
} );
272+
this.setState(
273+
{
274+
filterValue,
275+
filteredTermsTree,
276+
}
277+
);
169278

170279
const resultCount = getResultCount( filteredTermsTree );
171280
const resultsFoundMessage = sprintf(
@@ -230,21 +339,13 @@ class HierarchicalTermSelector extends Component {
230339
}
231340

232341
render() {
233-
const {
234-
slug,
235-
taxonomy,
236-
instanceId,
237-
hasCreateAction,
238-
hasAssignAction,
239-
availableTermsTree,
240-
availableTerms,
241-
} = this.props;
342+
const { slug, taxonomy, instanceId, hasCreateAction, hasAssignAction } = this.props;
242343

243344
if ( ! hasAssignAction ) {
244345
return null;
245346
}
246347

247-
const { filteredTermsTree, formName, formParent, isRequestingTerms, showForm, filterValue } = this.state;
348+
const { availableTermsTree, availableTerms, filteredTermsTree, formName, formParent, loading, showForm, filterValue } = this.state;
248349
const labelWithFallback = ( labelProperty, fallbackIsCategory, fallbackIsNotCategory ) => get(
249350
taxonomy,
250351
[ 'labels', labelProperty ],
@@ -285,7 +386,7 @@ class HierarchicalTermSelector extends Component {
285386
slug === 'category' ? __( 'Categories' ) : __( 'Terms' )
286387
)
287388
);
288-
const showFilter = availableTerms && ( availableTerms.length >= MIN_TERMS_COUNT_FOR_FILTER );
389+
const showFilter = availableTerms.length >= MIN_TERMS_COUNT_FOR_FILTER;
289390

290391
return [
291392
showFilter && <label
@@ -308,9 +409,9 @@ class HierarchicalTermSelector extends Component {
308409
role="group"
309410
aria-label={ groupLabel }
310411
>
311-
{ this.renderTerms( '' !== filterValue ? filteredTermsTree : this.sortBySelected( availableTermsTree ) ) }
412+
{ this.renderTerms( '' !== filterValue ? filteredTermsTree : availableTermsTree ) }
312413
</div>,
313-
! isRequestingTerms && hasCreateAction && (
414+
! loading && hasCreateAction && (
314415
<Button
315416
key="term-add-button"
316417
onClick={ this.onToggleForm }
@@ -363,27 +464,18 @@ class HierarchicalTermSelector extends Component {
363464
export default compose( [
364465
withSelect( ( select, { slug } ) => {
365466
const { getCurrentPost } = select( 'core/editor' );
366-
const { getTaxonomy, getEntityRecords } = select( 'core' );
367-
const { isResolving } = select( 'core/data' );
467+
const { getTaxonomy } = select( 'core' );
368468
const taxonomy = getTaxonomy( slug );
369-
const availableTerms = getEntityRecords( 'taxonomy', slug, DEFAULT_QUERY );
370-
const availableTermsTree = buildTermsTree( availableTerms );
371469
return {
372470
hasCreateAction: taxonomy ? get( getCurrentPost(), [ '_links', 'wp:action-create-' + taxonomy.rest_base ], false ) : false,
373471
hasAssignAction: taxonomy ? get( getCurrentPost(), [ '_links', 'wp:action-assign-' + taxonomy.rest_base ], false ) : false,
374472
terms: taxonomy ? select( 'core/editor' ).getEditedPostAttribute( taxonomy.rest_base ) : [],
375-
isRequestingTerms: isResolving( 'core', 'getEntityRecords', [ 'taxonomy', slug, DEFAULT_QUERY ] ),
376473
taxonomy,
377-
availableTerms,
378-
availableTermsTree,
379474
};
380475
} ),
381-
withDispatch( ( dispatch, { slug, taxonomy } ) => ( {
382-
onUpdateTerms( terms ) {
383-
dispatch( 'core/editor' ).editPost( { [ taxonomy.rest_base ]: terms } );
384-
},
385-
addTermToEditedPost( term ) {
386-
return dispatch( 'core/editor' ).addTermToEditedPost( slug, term );
476+
withDispatch( ( dispatch ) => ( {
477+
onUpdateTerms( terms, restBase ) {
478+
dispatch( 'core/editor' ).editPost( { [ restBase ]: terms } );
387479
},
388480
} ) ),
389481
withSpokenMessages,

packages/editor/src/store/actions.js

-16
Original file line numberDiff line numberDiff line change
@@ -779,22 +779,6 @@ export function unlockPostSaving( lockName ) {
779779
};
780780
}
781781

782-
/**
783-
* Returns an action object signaling that a new term is added to the edited post.
784-
*
785-
* @param {string} slug Taxonomy slug.
786-
* @param {Object} term Term object.
787-
*
788-
* @return {Object} Action object.
789-
*/
790-
export function addTermToEditedPost( slug, term ) {
791-
return {
792-
type: 'ADD_TERM_TO_EDITED_POST',
793-
slug,
794-
term,
795-
};
796-
}
797-
798782
//
799783
// Deprecated
800784
//

packages/editor/src/store/effects.js

-6
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,6 @@ import {
5252
trashPostFailure,
5353
refreshPost,
5454
} from './effects/posts';
55-
import {
56-
addTermToEditedPost,
57-
} from './effects/terms';
5855

5956
/**
6057
* Block validity is a function of blocks state (at the point of a
@@ -261,7 +258,4 @@ export default {
261258
REPLACE_BLOCKS: [
262259
ensureDefaultBlock,
263260
],
264-
ADD_TERM_TO_EDITED_POST: ( action ) => {
265-
addTermToEditedPost( action );
266-
},
267261
};

packages/editor/src/store/effects/terms.js

-39
This file was deleted.

0 commit comments

Comments
 (0)