PluginProbe
Sight – Professional Image Gallery and Portfolio / 1.0.6
Sight – Professional Image Gallery and Portfolio v1.0.6
trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8
sight / gutenberg / jsx / components / server-side-render / server-side-render.jsx

server-side-render.jsx in Sight – Professional Image Gallery and Portfolio 1.0.6, at gutenberg/jsx/components/server-side-render/server-side-render.jsx

211 lines 4.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /*
2 * This is a copy of Gutenberg component https://github.com/WordPress/gutenberg/blob/master/packages/server-side-render/src/server-side-render.js
3 * With the changes in our component:
4 * - callbacks before and after new content render
5 * - slightly different rendering process - don't remove previously rendered content. So, we will not see page jumps after every attribute change.
6 */
7
8 /**
9 * External dependencies
10 */
11 import classnames from 'classnames';
12 const { isEqual, debounce } = window.lodash;
13
14 /**
15 * Internal dependencies
16 */
17 import './style.scss';
18
19 /**
20 * WordPress dependencies
21 */
22 const {
23 Component,
24 RawHTML,
25 } = wp.element;
26
27 const { __, sprintf } = wp.i18n;
28
29 const apiFetch = wp.apiFetch;
30
31 const { addQueryArgs } = wp.url;
32
33 const {
34 Placeholder,
35 Spinner,
36 } = wp.components;
37
38 const {
39 doAction,
40 } = wp.hooks;
41
42 export function rendererPath( block, attributes = null, urlQueryArgs = {} ) {
43 return addQueryArgs( `/wp/v2/sight-renderer/${ block }`, {
44 context: 'edit',
45 ...( null !== attributes ? { attributes } : {} ),
46 ...urlQueryArgs,
47 } );
48 }
49
50 export class ServerSideRender extends Component {
51 constructor( props ) {
52 super( props );
53 this.state = {
54 response: null,
55 prevResponse: null,
56 };
57 }
58
59 componentDidMount() {
60 this.isStillMounted = true;
61 this.fetch( this.props );
62 // Only debounce once the initial fetch occurs to ensure that the first
63 // renders show data as soon as possible.
64 this.fetch = debounce( this.fetch, 500 );
65 }
66
67 componentWillUnmount() {
68 this.isStillMounted = false;
69 }
70
71 componentDidUpdate( prevProps ) {
72 const prevAttributes = prevProps.attributes;
73 const curAttributes = this.props.attributes;
74
75 if ( ! isEqual( prevAttributes, curAttributes ) ) {
76 this.fetch( this.props );
77 }
78 }
79
80 fetch( props ) {
81 if ( ! this.isStillMounted ) {
82 return;
83 }
84
85 const {
86 block,
87 attributes = null,
88 urlQueryArgs = {},
89 onBeforeChange = () => {},
90 onChange = () => {},
91 } = props;
92
93 if ( null !== this.state.response ) {
94 this.setState( {
95 response: null,
96 prevResponse: this.state.response,
97 } );
98 }
99
100 const path = rendererPath( block );
101
102 // Store the latest fetch request so that when we process it, we can
103 // check if it is the current request, to avoid race conditions on slow networks.
104 const fetchRequest = this.currentFetchRequest = apiFetch( { method: 'POST', path, data: { attributes: attributes } } )
105 .then( ( response ) => {
106 if ( this.isStillMounted && fetchRequest === this.currentFetchRequest && response ) {
107 onBeforeChange();
108 doAction( 'sight.components.serverSideRender.onBeforeChange', this.props );
109
110 this.setState( {
111 response: response.rendered,
112 prevResponse: null,
113 }, () => {
114 onChange();
115 doAction( 'sight.components.serverSideRender.onChange', this.props );
116 } );
117 }
118 } )
119 .catch( ( error ) => {
120 if ( this.isStillMounted && fetchRequest === this.currentFetchRequest ) {
121 onBeforeChange();
122 doAction( 'sight.components.serverSideRender.onBeforeChange', this.props );
123
124 this.setState( {
125 response: {
126 error: true,
127 errorMsg: error.message,
128 },
129 prevResponse: null,
130 }, () => {
131 onChange();
132 doAction( 'sight.components.serverSideRender.onChange', this.props );
133 } );
134 }
135 } );
136 return fetchRequest;
137 }
138
139 render() {
140 const {
141 response,
142 prevResponse,
143 } = this.state;
144
145 let { className } = this.props;
146
147 className = classnames(
148 className,
149 'sight-component-server-side-render'
150 );
151
152 if ( response === '' ) {
153 return (
154 <Placeholder
155 className={ className }
156 >
157 { __( 'Block rendered as empty.' ) }
158 </Placeholder>
159 );
160 } else if ( ! response && prevResponse ) {
161 className = classnames(
162 className,
163 'sight-component-server-side-render-loading'
164 );
165
166 return (
167 <div className={ className }>
168 <Spinner />
169 <RawHTML
170 key="html"
171 className="sight-component-server-side-render-content"
172 >
173 { prevResponse }
174 </RawHTML>
175 </div>
176 );
177 } else if ( ! response ) {
178 return (
179 <Placeholder
180 className={ className }
181 >
182 <Spinner />
183 </Placeholder>
184 );
185 } else if ( response.error ) {
186 // translators: %s: error message describing the problem
187 const errorMessage = sprintf( __( 'Error loading block: %s' ), response.errorMsg );
188 return (
189 <Placeholder
190 className={ className }
191 >
192 { errorMessage }
193 </Placeholder>
194 );
195 }
196
197 return (
198 <div className={ className }>
199 <RawHTML
200 key="html"
201 className="sight-component-server-side-render-content"
202 >
203 { response }
204 </RawHTML>
205 </div>
206 );
207 }
208 }
209
210 export default ServerSideRender;
211