PluginProbe ʕ •ᴥ•ʔ
Starter Sites & Templates by Neve / trunk
Starter Sites & Templates by Neve vtrunk
1.4.0 1.3.0 1.2.29 1.2.28 1.2.6 1.2.7 1.2.8 1.2.9 trunk 1.0.10 1.0.11 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.1.10 1.1.11 1.1.12 1.1.13 1.1.14 1.1.15 1.1.16 1.1.17 1.1.18 1.1.19 1.1.2 1.1.20 1.1.21 1.1.22 1.1.23 1.1.24 1.1.25 1.1.26 1.1.27 1.1.28 1.1.29 1.1.3 1.1.30 1.1.31 1.1.32 1.1.33 1.1.34 1.1.35 1.1.36 1.1.37 1.1.38 1.1.39 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 1.1.9 1.2.0 1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.15 1.2.16 1.2.17 1.2.18 1.2.19 1.2.2 1.2.20 1.2.21 1.2.22 1.2.23 1.2.24 1.2.25 1.2.26 1.2.27 1.2.3 1.2.4 1.2.5
templates-patterns-collection / assets / src / Components / CloudLibrary / ImportTemplatesModal.js
templates-patterns-collection / assets / src / Components / CloudLibrary Last commit date
DemoSiteTemplatesImport.js 3 years ago FeedbackNotice.js 1 year ago Filters.js 1 year ago ImportTemplatesModal.js 1 year ago Library.js 1 year ago ListItem.js 1 year ago PreviewFrame.js 1 year ago common.js 2 years ago
ImportTemplatesModal.js
461 lines
1 import { parseEntities } from 'parse-entities';
2 import { withDispatch, withSelect } from '@wordpress/data';
3 import { Button, Icon, Modal } from '@wordpress/components';
4 import { __, sprintf } from '@wordpress/i18n';
5 import { compose } from '@wordpress/compose';
6 import { page as pageIcon } from '@wordpress/icons';
7 import { useEffect, useState } from '@wordpress/element';
8
9 import {
10 activateTheme,
11 importTemplates,
12 importFseTemplate,
13 installTheme,
14 } from '../../utils/site-import';
15 import { fetchBulkData, getUserTemplateData } from './common';
16 import classnames from 'classnames';
17
18 const ImportTemplatesModal = ( {
19 templatesData,
20 cancel,
21 siteData,
22 themeData,
23 setModal,
24 isUserTemplate = false,
25 generalTemplates = false,
26 } ) => {
27 const [ fetching, setFetching ] = useState( true );
28 const [ templates, setTemplates ] = useState( [] );
29 const [ importing, setImporting ] = useState( false );
30 const [ imported, setImported ] = useState( [] );
31 const [ error, setError ] = useState( false );
32
33 const isSingle = templatesData.length === 1;
34
35 useEffect( () => {
36 if ( isUserTemplate && isSingle ) {
37 getUserTemplateData( templatesData[ 0 ].template_id ).then(
38 ( r ) => {
39 if ( ! r.success ) {
40 if ( r.message ) {
41 setError( r.message );
42 } else {
43 setError( true );
44 }
45 setFetching( false );
46 }
47 setTemplates( r.templates );
48 setFetching( false );
49 }
50 );
51 } else {
52 fetchBulkData( templatesData.map( ( i ) => i.template_id ) ).then(
53 ( r ) => {
54 if ( ! r.success ) {
55 if ( r.message ) {
56 setError( r.message );
57 } else {
58 setError( true );
59 }
60 setFetching( false );
61 return false;
62 }
63 setTemplates( r.templates );
64 setFetching( false );
65 }
66 );
67 }
68 }, [ templatesData ] );
69
70 const Mock = () => {
71 return (
72 <>
73 <div className="modal-body">
74 <div className="header">
75 { /* eslint-disable-next-line jsx-a11y/heading-has-content */ }
76 <h1
77 className="is-loading"
78 style={ {
79 height: 30,
80 marginBottom: 30,
81 width: '70%',
82 } }
83 />
84 <p className="description is-loading" />
85 <p className="description is-loading" />
86 <p
87 className="description is-loading"
88 style={ { width: '40%' } }
89 />
90 </div>
91 </div>
92 <div className="modal-footer" style={ { marginTop: 50 } }>
93 <span className="is-loading link" />
94 <span
95 className="is-loading button"
96 style={ {
97 width: '150px',
98 marginLeft: 'auto',
99 } }
100 />
101 </div>
102 </>
103 );
104 };
105
106 const launchImport = ( e ) => {
107 e.preventDefault();
108 setModal( true );
109 };
110
111 const runTemplatesImport = () => {
112 setImporting( true );
113
114 /**
115 * Please note that templatesData is an array of objects, but currently we only send one template at a time.
116 * In the future we might send more than one template to bulk-import templates.
117 */
118 const { fseTemplates, otherTemplates } = templatesData.reduce(
119 ( acc, item, index ) => {
120 const templateType = item.template_type;
121 const mergedTemplate = { ...item, ...templates[ index ] };
122
123 if ( templateType === 'fse' ) {
124 acc.fseTemplates.push( mergedTemplate );
125 } else {
126 acc.otherTemplates.push( mergedTemplate );
127 }
128
129 return acc;
130 },
131 { fseTemplates: [], otherTemplates: [] }
132 );
133
134 /**
135 * Function to import templates that are not FSE.
136 */
137 const callbackImportTemplate = () => {
138 if ( ! otherTemplates ) {
139 return;
140 }
141
142 try {
143 importTemplates( otherTemplates ).then( ( r ) => {
144 if ( ! r.success ) {
145 // eslint-disable-next-line no-console
146 console.log( r.message );
147 return false;
148 }
149
150 setImported( r.pages );
151 setImporting( 'done' );
152 } );
153 } catch ( e ) {
154 // eslint-disable-next-line no-console
155 console.log( e );
156 }
157 };
158
159 /**
160 * Function to import FSE templates.
161 */
162 const callbackImportFse = () => {
163 if ( ! fseTemplates ) {
164 return;
165 }
166
167 try {
168 importFseTemplate( fseTemplates ).then( ( r ) => {
169 if ( ! r.success ) {
170 // eslint-disable-next-line no-console
171 setError( r.message );
172 return false;
173 }
174
175 // setImported( r.pages );
176 setImporting( 'done' );
177 } );
178 } catch ( e ) {
179 // eslint-disable-next-line no-console
180 console.log( e );
181 }
182 };
183
184 if (
185 ! themeData ||
186 ( otherTemplates[ 0 ]?.template_site_slug === 'general' &&
187 otherTemplates[ 0 ]?.premade === 'yes' )
188 ) {
189 callbackImportTemplate();
190 return false;
191 }
192
193 const callbackError = ( err ) => {
194 // eslint-disable-next-line no-console
195 console.error( err );
196 };
197
198 // skip activation or install for user templates
199 if ( isUserTemplate ) {
200 callbackImportTemplate();
201 callbackImportFse();
202 return false;
203 }
204
205 if ( themeData.action === 'install' ) {
206 installTheme(
207 'neve',
208 () => {
209 activateTheme(
210 themeData,
211 callbackImportTemplate,
212 callbackError
213 );
214 },
215 callbackError
216 );
217 return false;
218 }
219
220 activateTheme( themeData, callbackImportTemplate, callbackError );
221 };
222
223 const ImportDone = () => {
224 return (
225 <>
226 <div className="modal-body">
227 <div className="header">
228 <h1>
229 { __(
230 'Import done!',
231 'templates-patterns-collection'
232 ) }
233 </h1>
234 <p className="description">
235 { isSingle
236 ? __(
237 'Template was successfully imported!',
238 'templates-patterns-collection'
239 )
240 : __(
241 'Templates were successfully imported!',
242 'templates-patterns-collection'
243 ) }
244 </p>
245 </div>
246 { imported && (
247 <ul className="modal-toggles">
248 { imported.map( ( page, index ) => {
249 return (
250 <li className="option-row" key={ index }>
251 <Icon
252 icon={ pageIcon }
253 className="active"
254 />
255 <span>
256 { parseEntities( page.title ) }
257 </span>
258 <div className="actions">
259 <Button
260 isTertiary
261 href={ page.url }
262 >
263 { __(
264 'Visit',
265 'templates-patterns-collection'
266 ) }
267 </Button>
268 <Button
269 isTertiary
270 href={ page.edit }
271 >
272 { __(
273 'Edit',
274 'templates-patterns-collection'
275 ) }
276 </Button>
277 </div>
278 </li>
279 );
280 } ) }
281 </ul>
282 ) }
283 </div>
284 <div className="modal-footer">
285 <Button isPrimary className="import" onClick={ cancel }>
286 { __( 'Close', 'templates-patterns-collection' ) }
287 </Button>
288 </div>
289 </>
290 );
291 };
292
293 const Error = () => {
294 return (
295 <>
296 <div className="modal-body">
297 <div className="header">
298 <h1>
299 { __(
300 'An error occurred!',
301 'templates-patterns-collection'
302 ) }
303 </h1>
304 <p className="description">
305 { error === true
306 ? __( 'Please refresh the page and try again.', 'templates-patterns-collection' )
307 : error }
308 </p>
309 </div>
310 </div>
311 <div className="modal-footer">
312 <Button
313 isPrimary
314 className="import"
315 onClick={ () => {
316 setError( false );
317 cancel();
318 } }
319 >
320 { __( 'Close', 'templates-patterns-collection' ) }
321 </Button>
322 </div>
323 </>
324 );
325 };
326
327 const description = () => {
328 const {
329 template_name: templateName,
330 template_type: templateType,
331 } = templatesData[ 0 ];
332
333 if ( templateType === 'fse' ) {
334 return __(
335 'This import will add a new Full Site Editing template to your site.',
336 'templates-patterns-collection'
337 );
338 }
339
340 return isSingle
341 ? sprintf(
342 /* translators: %s the name of the template */
343 __(
344 'The %s template will be imported as a page into your site. This import will install & activate the page builder plugin if not already installed.',
345 'templates-patterns-collection'
346 ),
347 templateName
348 )
349 : __(
350 'All the templates that are included in this starter site, will be imported as pages. This import will install & activate the page builder plugin if not already installed.',
351 'templates-patterns-collection'
352 );
353 };
354
355 const ModalContent = ( props ) => {
356 if ( fetching ) {
357 return <Mock />;
358 }
359
360 if ( props.error ) {
361 return <Error />;
362 }
363
364 return (
365 <>
366 <div className="modal-body">
367 <div className="header">
368 <h1>
369 { sprintf(
370 isSingle
371 ? /* translators: name of starter site */
372 __(
373 'Import the %s template',
374 'templates-patterns-collection'
375 )
376 : /* translators: name of template */
377 __(
378 'Import all templates from %s',
379 'templates-patterns-collection'
380 ),
381 isSingle
382 ? templatesData[ 0 ].template_name
383 : siteData.title
384 ) }
385 </h1>
386 <p className="description">{ description() }</p>
387 </div>
388 </div>
389 <div className="modal-footer">
390 { ! generalTemplates && (
391 <Button
392 className="import-templates"
393 isLink
394 disabled={ importing }
395 onClick={ launchImport }
396 >
397 { __(
398 'I want to import the entire site',
399 'templates-patterns-collection'
400 ) }
401 </Button>
402 ) }
403 <Button
404 isPrimary
405 className="import"
406 disabled={ importing }
407 onClick={ runTemplatesImport }
408 >
409 { importing
410 ? __( 'Importing', 'templates-patterns-collection' ) + '...'
411 : isSingle
412 ? __( 'Import', 'templates-patterns-collection' )
413 : __( 'Import All Pages', 'templates-patterns-collection' ) }
414 </Button>
415 </div>
416 </>
417 );
418 };
419
420 return (
421 <Modal
422 className={ classnames( [ 'ob-import-modal', { fetching } ] ) }
423 onRequestClose={ cancel }
424 shouldCloseOnClickOutside={
425 ( ! importing || importing === 'done' ) && ! fetching
426 }
427 isDismissible={
428 ( ! importing || importing === 'done' ) && ! fetching
429 }
430 >
431 { importing === 'done' && ! error ? (
432 <ImportDone />
433 ) : (
434 <ModalContent error={ error } />
435 ) }
436 </Modal>
437 );
438 };
439
440 export default compose(
441 withSelect( ( select ) => {
442 const { getThemeAction, getCurrentSite } = select( 'neve-onboarding' );
443 return {
444 siteData: getCurrentSite(),
445 themeData: getThemeAction() || false,
446 };
447 } ),
448 withDispatch( ( dispatch ) => {
449 const { setTemplateModal, setImportModalStatus } = dispatch(
450 'neve-onboarding'
451 );
452
453 return {
454 cancel: () => {
455 setTemplateModal( null );
456 },
457 setModal: ( status ) => setImportModalStatus( status ),
458 };
459 } )
460 )( ImportTemplatesModal );
461