UNPKG

5.77 kBJavaScriptView Raw
1/**
2 * External dependencies
3 */
4import { times, unescape } from 'lodash';
5
6/**
7 * WordPress dependencies
8 */
9import { PanelBody, Placeholder, Spinner, ToggleControl } from '@wordpress/components';
10import { compose, withInstanceId } from '@wordpress/compose';
11import { withSelect } from '@wordpress/data';
12import { InspectorControls } from '@wordpress/block-editor';
13import { Component, Fragment } from '@wordpress/element';
14import { __ } from '@wordpress/i18n';
15
16class CategoriesEdit extends Component {
17 constructor() {
18 super( ...arguments );
19
20 this.toggleDisplayAsDropdown = this.toggleDisplayAsDropdown.bind( this );
21 this.toggleShowPostCounts = this.toggleShowPostCounts.bind( this );
22 this.toggleShowHierarchy = this.toggleShowHierarchy.bind( this );
23 }
24
25 toggleDisplayAsDropdown() {
26 const { attributes, setAttributes } = this.props;
27 const { displayAsDropdown } = attributes;
28
29 setAttributes( { displayAsDropdown: ! displayAsDropdown } );
30 }
31
32 toggleShowPostCounts() {
33 const { attributes, setAttributes } = this.props;
34 const { showPostCounts } = attributes;
35
36 setAttributes( { showPostCounts: ! showPostCounts } );
37 }
38
39 toggleShowHierarchy() {
40 const { attributes, setAttributes } = this.props;
41 const { showHierarchy } = attributes;
42
43 setAttributes( { showHierarchy: ! showHierarchy } );
44 }
45
46 getCategories( parentId = null ) {
47 const categories = this.props.categories;
48 if ( ! categories || ! categories.length ) {
49 return [];
50 }
51
52 if ( parentId === null ) {
53 return categories;
54 }
55
56 return categories.filter( ( category ) => category.parent === parentId );
57 }
58
59 getCategoryListClassName( level ) {
60 return `wp-block-categories__list wp-block-categories__list-level-${ level }`;
61 }
62
63 renderCategoryName( category ) {
64 if ( ! category.name ) {
65 return __( '(Untitled)' );
66 }
67
68 return unescape( category.name ).trim();
69 }
70
71 renderCategoryList() {
72 const { showHierarchy } = this.props.attributes;
73 const parentId = showHierarchy ? 0 : null;
74 const categories = this.getCategories( parentId );
75
76 return (
77 <ul className={ this.getCategoryListClassName( 0 ) }>
78 { categories.map( ( category ) => this.renderCategoryListItem( category, 0 ) ) }
79 </ul>
80 );
81 }
82
83 renderCategoryListItem( category, level ) {
84 const { showHierarchy, showPostCounts } = this.props.attributes;
85 const childCategories = this.getCategories( category.id );
86
87 return (
88 <li key={ category.id }>
89 <a href={ category.link } target="_blank" rel="noreferrer noopener">{ this.renderCategoryName( category ) }</a>
90 { showPostCounts &&
91 <span className="wp-block-categories__post-count">
92 { ' ' }({ category.count })
93 </span>
94 }
95
96 {
97 showHierarchy &&
98 !! childCategories.length && (
99 <ul className={ this.getCategoryListClassName( level + 1 ) }>
100 { childCategories.map( ( childCategory ) => this.renderCategoryListItem( childCategory, level + 1 ) ) }
101 </ul>
102 )
103 }
104 </li>
105 );
106 }
107
108 renderCategoryDropdown() {
109 const { instanceId } = this.props;
110 const { showHierarchy } = this.props.attributes;
111 const parentId = showHierarchy ? 0 : null;
112 const categories = this.getCategories( parentId );
113 const selectId = `blocks-category-select-${ instanceId }`;
114 return (
115 <Fragment>
116 <label htmlFor={ selectId } className="screen-reader-text">
117 { __( 'Categories' ) }
118 </label>
119 <select id={ selectId } className="wp-block-categories__dropdown">
120 { categories.map( ( category ) => this.renderCategoryDropdownItem( category, 0 ) ) }
121 </select>
122 </Fragment>
123 );
124 }
125
126 renderCategoryDropdownItem( category, level ) {
127 const { showHierarchy, showPostCounts } = this.props.attributes;
128 const childCategories = this.getCategories( category.id );
129
130 return [
131 <option key={ category.id }>
132 { times( level * 3, () => '\xa0' ) }
133 { this.renderCategoryName( category ) }
134 {
135 !! showPostCounts ?
136 ` (${ category.count })` :
137 ''
138 }
139 </option>,
140 showHierarchy &&
141 !! childCategories.length && (
142 childCategories.map( ( childCategory ) => this.renderCategoryDropdownItem( childCategory, level + 1 ) )
143 ),
144 ];
145 }
146
147 render() {
148 const { attributes, isRequesting } = this.props;
149 const { displayAsDropdown, showHierarchy, showPostCounts } = attributes;
150
151 const inspectorControls = (
152 <InspectorControls>
153 <PanelBody title={ __( 'Categories Settings' ) }>
154 <ToggleControl
155 label={ __( 'Display as Dropdown' ) }
156 checked={ displayAsDropdown }
157 onChange={ this.toggleDisplayAsDropdown }
158 />
159 <ToggleControl
160 label={ __( 'Show Hierarchy' ) }
161 checked={ showHierarchy }
162 onChange={ this.toggleShowHierarchy }
163 />
164 <ToggleControl
165 label={ __( 'Show Post Counts' ) }
166 checked={ showPostCounts }
167 onChange={ this.toggleShowPostCounts }
168 />
169 </PanelBody>
170 </InspectorControls>
171 );
172
173 if ( isRequesting ) {
174 return (
175 <Fragment>
176 { inspectorControls }
177 <Placeholder
178 icon="admin-post"
179 label={ __( 'Categories' ) }
180 >
181 <Spinner />
182 </Placeholder>
183 </Fragment>
184 );
185 }
186
187 return (
188 <Fragment>
189 { inspectorControls }
190 <div className={ this.props.className }>
191 {
192 displayAsDropdown ?
193 this.renderCategoryDropdown() :
194 this.renderCategoryList()
195 }
196 </div>
197 </Fragment>
198 );
199 }
200}
201export default compose(
202 withSelect( ( select ) => {
203 const { getEntityRecords } = select( 'core' );
204 const { isResolving } = select( 'core/data' );
205 const query = { per_page: -1, hide_empty: true };
206
207 return {
208 categories: getEntityRecords( 'taxonomy', 'category', query ),
209 isRequesting: isResolving( 'core', 'getEntityRecords', [ 'taxonomy', 'category', query ] ),
210 };
211 } ),
212 withInstanceId
213)( CategoriesEdit );