PluginProbe
Tag Groups is the Advanced Way to Display Your Taxonomy Terms / trunk
Tag Groups is the Advanced Way to Display Your Taxonomy Terms vtrunk
2.2.2 2.2.1 2.2.0 trunk 1.40.0 1.40.2 1.41.0 1.42.1 1.43.0 1.43.1 1.43.10 1.43.10.1 1.43.2 1.43.3 1.43.4 1.43.5 1.43.6 1.43.7 1.43.9 1.44.0 1.44.1 1.44.3 1.44.3.1 2.0.0 2.0.1 All 36 releases
tag-groups / src / components / tag-groups-render.js

tag-groups-render.js in Tag Groups is the Advanced Way to Display Your Taxonomy Terms trunk, at src/components/tag-groups-render.js

168 lines 4.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * External dependencies
3 */
4 import { isEqual, debounce } from 'lodash';
5
6 /**
7 * WordPress dependencies
8 */
9 import { Component, RawHTML, Fragment } from '@wordpress/element';
10 import { __, sprintf } from '@wordpress/i18n';
11 import apiFetch from '@wordpress/api-fetch';
12 import { addQueryArgs } from '@wordpress/url';
13 import { Placeholder, Spinner } from '@wordpress/components';
14
15 export function rendererPath(block, attributes = null, urlQueryArgs = {}) {
16 return addQueryArgs(`/wp/v2/block-renderer/${block}`, {
17 context: 'edit',
18 ...(null !== attributes ? { attributes } : {}),
19 ...urlQueryArgs,
20 });
21 }
22
23 export class TagGroupsServerSideRender extends Component {
24 constructor(props) {
25 super(props);
26 this.state = {
27 response: null,
28 prevResponse: null,
29 };
30 }
31
32 componentDidMount() {
33 this.isStillMounted = true;
34 this.fetch(this.props);
35 // Only debounce once the initial fetch occurs to ensure that the first
36 // renders show data as soon as possible.
37 this.fetch = debounce(this.fetch, 500);
38 }
39
40 componentWillUnmount() {
41 this.isStillMounted = false;
42 }
43
44 componentDidUpdate(prevProps) {
45 if (!isEqual(prevProps.attributes, this.props.attributes)) {
46 this.fetch(this.props);
47 }
48 }
49
50 fetch(props) {
51 if (!this.isStillMounted) {
52 return;
53 }
54 if (null !== this.state.response) {
55 this.setState({ response: null, prevResponse: this.state.response });
56 }
57 const { block, attributes = null, urlQueryArgs = {}, onFetched } = props;
58
59 const path = rendererPath(block, attributes, urlQueryArgs);
60 // Store the latest fetch request so that when we process it, we can
61 // check if it is the current request, to avoid race conditions on slow networks.
62 const fetchRequest = (this.currentFetchRequest = apiFetch({ path })
63 .then((response) => {
64 if (
65 this.isStillMounted &&
66 fetchRequest === this.currentFetchRequest &&
67 response
68 ) {
69 this.setState({ response: response.rendered });
70 if (props['onFetched']) {
71 props['onFetched']();
72 }
73 }
74 })
75 .catch((error) => {
76 if (this.isStillMounted && fetchRequest === this.currentFetchRequest) {
77 this.setState({
78 response: {
79 error: true,
80 errorMsg: error.message,
81 },
82 });
83 }
84 }));
85 return fetchRequest;
86 }
87
88 render() {
89 // inspiration from https://github.com/dgwyer/server-side-render-x/blob/master/server-side-render-x.js
90 const { right, top, unit } = this.props.spinnerLocation;
91 const response = this.state.response;
92 const prevResponse = this.state.prevResponse;
93
94 const {
95 className,
96 EmptyResponsePlaceholder,
97 ErrorResponsePlaceholder,
98 LoadingResponsePlaceholder,
99 } = this.props;
100
101 if (response === '') {
102 return <EmptyResponsePlaceholder response={response} {...this.props} />;
103 } else if (!response) {
104 return (
105 <LoadingResponsePlaceholder
106 right={right}
107 top={top}
108 unit={unit}
109 prevResponse={prevResponse}
110 />
111 );
112 } else if (response.error) {
113 return <ErrorResponsePlaceholder response={response} {...this.props} />;
114 }
115
116 return (
117 <RawHTML key='html' className={className}>
118 {response}
119 </RawHTML>
120 );
121 }
122 }
123
124 TagGroupsServerSideRender.defaultProps = {
125 spinnerLocation: { right: 0, top: 10, unit: 'px' },
126 EmptyResponsePlaceholder: ({ className }) => (
127 <Placeholder className={className}>
128 {__('Block rendered as empty.')}
129 </Placeholder>
130 ),
131 ErrorResponsePlaceholder: ({ response, className }) => {
132 const errorMessage = sprintf(
133 // translators: %s: error message describing the problem
134 __('Error loading block: %s'),
135 response.errorMsg
136 );
137 return <Placeholder className={className}>{errorMessage}</Placeholder>;
138 },
139 LoadingResponsePlaceholder: ({
140 className,
141 top,
142 right,
143 unit,
144 prevResponse,
145 }) => {
146 return (
147 <Fragment>
148 <div style={{ position: 'relative', minHeight: '100px' }}>
149 <div
150 style={{
151 position: 'absolute',
152 right: `${right}${unit}`,
153 top: `${top}${unit}`,
154 }}
155 >
156 <Spinner />
157 </div>
158 <RawHTML key='html' className={className}>
159 {prevResponse}
160 </RawHTML>
161 </div>
162 </Fragment>
163 );
164 },
165 };
166
167 export default TagGroupsServerSideRender;
168