PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.4.5
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.4.5
4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.1.2 3.1.3 3.10.0 3.10.1 3.10.10 3.10.11 3.10.12 3.10.13 3.10.14 3.10.15 3.10.2 3.10.3 3.10.4 All 148 releases
visualizer / classes / Visualizer / Gutenberg / src / Editor.js

Editor.js in Visualizer – Tables & Charts Manager with Built-in AI Generator 3.4.5, at classes/Visualizer/Gutenberg/src/Editor.js

609 lines 15.3 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 Charts from './Components/Charts.js';
5
6 import ChartSelect from './Components/ChartSelect.js';
7
8 import ChartRender from './Components/ChartRender.js';
9
10 import { CSVToArray } from './utils.js';
11
12 /**
13 * WordPress dependencies
14 */
15 const { __ } = wp.i18n;
16
17 const {
18 apiFetch,
19 apiRequest
20 } = wp;
21
22 const {
23 Component,
24 Fragment
25 } = wp.element;
26
27 const {
28 Button,
29 ButtonGroup,
30 Dashicon,
31 Placeholder,
32 Notice,
33 Spinner
34 } = wp.components;
35
36 class Editor extends Component {
37 constructor() {
38 super( ...arguments );
39
40 this.getChart = this.getChart.bind( this );
41 this.editChart = this.editChart.bind( this );
42 this.editSettings = this.editSettings.bind( this );
43 this.editPermissions = this.editPermissions.bind( this );
44 this.readUploadedFile = this.readUploadedFile.bind( this );
45 this.editURL = this.editURL.bind( this );
46 this.editSchedule = this.editSchedule.bind( this );
47 this.editJSONSchedule = this.editJSONSchedule.bind( this );
48 this.editJSONURL = this.editJSONURL.bind( this );
49 this.editJSONHeaders = this.editJSONHeaders.bind( this );
50 this.editJSONRoot = this.editJSONRoot.bind( this );
51 this.editJSONPaging = this.editJSONPaging.bind( this );
52 this.JSONImportData = this.JSONImportData.bind( this );
53 this.editDatabaseSchedule = this.editDatabaseSchedule.bind( this );
54 this.databaseImportData = this.databaseImportData.bind( this );
55 this.uploadData = this.uploadData.bind( this );
56 this.getChartData = this.getChartData.bind( this );
57 this.editChartData = this.editChartData.bind( this );
58 this.updateChart = this.updateChart.bind( this );
59
60 this.state = {
61
62 /**
63 * Block Route Status
64 *
65 * home - Initial screen.
66 * showCharts - Display list of charts to pick.
67 * chartSelect - Chart selected.
68 * renderChart - Chart render.
69 */
70 route: ( this.props.attributes.route ? this.props.attributes.route : 'home' ),
71 chart: null,
72 isModified: false,
73 isLoading: false,
74 isScheduled: false
75 };
76 }
77
78 async componentDidMount() {
79
80 // Fetch review again if block loaded after saving.
81 if ( this.props.attributes.id ) {
82 let result = await apiFetch({ path: `wp/v2/visualizer/${this.props.attributes.id}` }).catch( function( error ) {
83 });
84
85 if ( result ) {
86 this.setState({
87 chart: result['chart_data']
88 });
89 } else {
90
91 // if the chart is not found.
92 this.setState({
93 route: 'error'
94 });
95 }
96 }
97 }
98
99 async getChart( id ) {
100 await this.setState({
101 isLoading: 'getChart'
102 });
103
104 let result = await apiFetch({ path: `wp/v2/visualizer/${id}` });
105
106 this.setState({
107 route: 'chartSelect',
108 chart: result['chart_data'],
109 isLoading: false
110 });
111
112 this.props.setAttributes({
113 id,
114 route: 'chartSelect',
115 lazy: -1
116 });
117 }
118
119 editChart() {
120 this.setState({ route: 'chartSelect' });
121 this.props.setAttributes({ route: 'chartSelect' });
122 }
123
124 editSettings( settings ) {
125 let chart = { ...this.state.chart };
126 chart['visualizer-settings'] = settings;
127 this.setState({
128 chart,
129 isModified: true
130 });
131 }
132
133 editPermissions( permissions ) {
134 let chart = { ...this.state.chart };
135 chart['visualizer-permissions'] = permissions;
136 this.setState({
137 chart,
138 isModified: true
139 });
140 }
141
142 readUploadedFile( e ) {
143 const fileTobeRead = e.current.files[0];
144 const fileReader = new FileReader();
145 fileReader.onload = () => {
146 const data = CSVToArray( fileReader.result );
147 this.editChartData( data, 'Visualizer_Source_Csv' );
148 };
149 fileReader.readAsText( fileTobeRead );
150 }
151
152 editURL( url ) {
153 let chart = { ...this.state.chart };
154 chart['visualizer-chart-url'] = url;
155 this.setState({ chart });
156 }
157
158 editSchedule( schedule ) {
159 let chart = { ...this.state.chart };
160 chart['visualizer-chart-schedule'] = schedule;
161 this.setState({
162 chart,
163 isModified: true
164 });
165 }
166
167 editJSONSchedule( schedule ) {
168 let chart = { ...this.state.chart };
169 chart['visualizer-json-schedule'] = schedule;
170 this.setState({
171 chart,
172 isModified: true
173 });
174 }
175
176 editJSONURL( url ) {
177 let chart = { ...this.state.chart };
178 chart['visualizer-json-url'] = url;
179 this.setState({ chart });
180 }
181
182 editJSONHeaders( headers ) {
183 let chart = { ...this.state.chart };
184 delete headers.username;
185 delete headers.password;
186 chart['visualizer-json-headers'] = headers;
187 this.setState({ chart });
188 }
189
190 editJSONRoot( root ) {
191 let chart = { ...this.state.chart };
192 chart['visualizer-json-root'] = root;
193 this.setState({ chart });
194 }
195
196 editJSONPaging( root ) {
197 let chart = { ...this.state.chart };
198 chart['visualizer-json-paging'] = root;
199 this.setState({ chart });
200 }
201
202 JSONImportData( name, series, data ) {
203 let chart = { ...this.state.chart };
204 chart['visualizer-source'] = name;
205 chart['visualizer-default-data'] = 0;
206 chart['visualizer-series'] = series;
207 chart['visualizer-data'] = data;
208 this.setState({
209 chart,
210 isModified: true
211 });
212 }
213
214 editDatabaseSchedule( schedule ) {
215 let chart = { ...this.state.chart };
216 chart['visualizer-db-schedule'] = schedule;
217 this.setState({
218 chart,
219 isModified: true
220 });
221 }
222
223 databaseImportData( query, name, series, data ) {
224 let chart = { ...this.state.chart };
225 chart['visualizer-source'] = name;
226 chart['visualizer-default-data'] = 0;
227 chart['visualizer-series'] = series;
228 chart['visualizer-data'] = data;
229 chart['visualizer-db-query'] = query;
230 this.setState({
231 chart,
232 isModified: true
233 });
234 }
235
236 uploadData( scheduled = false ) {
237 this.setState({
238 isLoading: 'uploadData',
239 isScheduled: scheduled
240 });
241
242 apiRequest({ path: `/visualizer/v1/upload-data?url=${this.state.chart['visualizer-chart-url']}`, method: 'POST' }).then(
243 ( data ) => {
244 if ( 2 <= Object.keys( data ).length ) {
245 let chart = { ...this.state.chart };
246
247 chart['visualizer-source'] = 'Visualizer_Source_Csv_Remote';
248 chart['visualizer-default-data'] = 0;
249 chart['visualizer-series'] = data.series;
250 chart['visualizer-data'] = data.data;
251
252 let series = chart['visualizer-series'];
253 let settings = chart['visualizer-settings'];
254 let map = series;
255 let fieldName = 'series';
256
257 if ( 'pie' === chart['visualizer-chart-type']) {
258 map = chart['visualizer-data'];
259 fieldName = 'slices';
260 }
261
262 map.map( ( i, index ) => {
263 if ( 'pie' !== chart['visualizer-chart-type'] && 0 === index ) {
264 return;
265 }
266
267 const seriesIndex = 'pie' !== chart['visualizer-chart-type'] ? index - 1 : index;
268
269 if ( settings[fieldName][seriesIndex] === undefined ) {
270 settings[fieldName][seriesIndex] = {};
271 settings[fieldName][seriesIndex].temp = 1;
272 }
273 });
274
275 settings[fieldName] = settings[fieldName].filter( ( i, index ) => {
276 const length = 'pie' !== chart['visualizer-chart-type'] ? map.length - 1 : map.length;
277 return index < length;
278 });
279
280 chart['visualizer-settings'] = settings;
281
282 this.setState({
283 chart,
284 isModified: true,
285 isLoading: false
286 });
287
288 return data;
289 }
290
291 this.setState({
292 isLoading: false
293 });
294 },
295 ( err ) => {
296 this.setState({
297 isLoading: false
298 });
299
300 return err;
301 }
302 );
303 }
304
305 async getChartData( id ) {
306 await this.setState({
307 isLoading: 'getChartData'
308 });
309
310 let result = await apiFetch({ path: `wp/v2/visualizer/${id}` });
311
312 let chart = { ...this.state.chart };
313
314 chart['visualizer-source'] = 'Visualizer_Source_Csv';
315 chart['visualizer-default-data'] = 0;
316 chart['visualizer-series'] = result['chart_data']['visualizer-series'];
317 chart['visualizer-data'] = result['chart_data']['visualizer-data'];
318
319 this.setState({
320 isLoading: false,
321 chart
322 });
323 }
324
325 editChartData( chartData, source ) {
326 let chart = { ...this.state.chart };
327 let series = [];
328 let settings = { ...chart['visualizer-settings'] };
329 let type = chart['visualizer-chart-type'];
330 chartData[0].map( ( i, index ) => {
331 series[index] = {
332 label: i,
333 type: chartData[1][index]
334 };
335 });
336
337 chartData.splice( 0, 2 );
338
339 let map = series;
340 let fieldName = 'series';
341
342 if ( 'pie' === type ) {
343 map = chartData;
344 fieldName = 'slices';
345
346 // pie charts are finicky about a number being a number
347 // and editing a number makes it a string
348 // so let's convert it back into a number.
349 chartData.map( ( i, index ) => {
350 switch ( series[1].type ) {
351 case 'number':
352 i[1] = parseFloat( i[1]);
353 break;
354 }
355 });
356 }
357
358 map.map( ( i, index ) => {
359 if ( 'pie' !== type && 0 === index ) {
360 return;
361 }
362
363 const seriesIndex = 'pie' !== type ? index - 1 : index;
364
365 if ( settings[fieldName][seriesIndex] === undefined ) {
366 settings[fieldName][seriesIndex] = {};
367 settings[fieldName][seriesIndex].temp = 1;
368 }
369 });
370
371 settings[fieldName] = settings[fieldName].filter( ( i, index ) => {
372 const length = -1 >= [ 'pie', 'tabular', 'dataTable' ].indexOf( type ) ? map.length - 1 : map.length;
373 return index < length;
374 });
375
376 chart['visualizer-source'] = source;
377 chart['visualizer-default-data'] = 0;
378 chart['visualizer-data'] = chartData;
379 chart['visualizer-series'] = series;
380 chart['visualizer-settings'] = settings;
381 chart['visualizer-chart-url'] = '';
382
383 this.setState({
384 chart,
385 isModified: true,
386 isScheduled: false
387 });
388 }
389
390 updateChart() {
391 this.setState({ isLoading: 'updateChart' });
392
393 const data = this.state.chart;
394
395 if ( false === this.state.isScheduled ) {
396 data['visualizer-chart-schedule'] = '';
397 }
398
399 let fieldName = 'series';
400
401 if ( 'pie' === data['visualizer-chart-type']) {
402 fieldName = 'slices';
403 }
404
405 // no series for bubble and timeline charts.
406 if ( -1 >= [ 'bubble', 'timeline' ].indexOf( data['visualizer-chart-type']) ) {
407 Object.keys( data['visualizer-settings'][fieldName])
408 .map( i => {
409 if ( data['visualizer-settings'][fieldName][i] !== undefined ) {
410 if ( data['visualizer-settings'][fieldName][i].temp !== undefined ) {
411 delete data['visualizer-settings'][fieldName][i].temp;
412 }
413 }
414 }
415 );
416 }
417
418 apiRequest({ path: `/visualizer/v1/update-chart?id=${ this.props.attributes.id }`, method: 'POST', data: data }).then(
419 ( data ) => {
420
421 this.setState({
422 isLoading: false,
423 isModified: false
424 });
425
426 return data;
427 },
428 ( err ) => {
429 return err;
430 }
431 );
432 }
433
434 render() {
435 if ( 'error' === this.state.route ) {
436 return (
437 <Notice
438 status="error"
439 isDismissible={ false }
440 >
441 <Dashicon icon="chart-pie" />
442 { __( 'This chart is not available; it might have been deleted. Please delete this block and resubmit your chart.' ) }
443 </Notice>
444 );
445 }
446
447 if ( 'renderChart' === this.state.route && null !== this.state.chart ) {
448 return (
449 <ChartRender
450 id={ this.props.attributes.id }
451 chart={ this.state.chart }
452 className={ this.props.className }
453 editChart={ this.editChart }
454 />
455 );
456 }
457
458 return (
459 <div className="visualizer-settings">
460
461 <div className="visualizer-settings__title">
462
463 <Dashicon icon="chart-pie" />
464 { __( 'Visualizer' ) }
465
466 </div>
467
468 { 'home' === this.state.route && (
469 <div className="visualizer-settings__content">
470 <div className="visualizer-settings__content-description">
471 { __( 'Make a new chart or display an existing one?' ) }
472 </div>
473
474 { /* You can apply "locked" class to lock any of the following list items. */ }
475
476 <a
477 href={ visualizerLocalize.adminPage }
478 target="_blank"
479 className="visualizer-settings__content-option"
480 >
481
482 <span className="visualizer-settings__content-option-title">
483 { __( 'Create a new chart' ) }
484 </span>
485
486 <div className="visualizer-settings__content-option-icon">
487 <Dashicon icon="arrow-right-alt2" />
488 </div>
489
490 </a>
491
492 <div
493 className="visualizer-settings__content-option"
494 onClick={ () => {
495 this.setState({ route: 'showCharts' });
496 this.props.setAttributes({ route: 'showCharts' });
497 } }
498 >
499
500 <span className="visualizer-settings__content-option-title">
501 { __( 'Display an existing chart' ) }
502 </span>
503
504 <div className="visualizer-settings__content-option-icon">
505 <Dashicon icon="arrow-right-alt2" />
506 </div>
507
508 </div>
509
510 </div>
511 ) }
512
513 { ( ( 'getChart' === this.state.isLoading ) || ( 'chartSelect' === this.state.route && null === this.state.chart ) || ( 'renderChart' === this.state.route && null === this.state.chart ) ) && (
514 <Placeholder>
515 <Spinner/>
516 </Placeholder>
517 ) }
518
519 { ( 'showCharts' === this.state.route && false === this.state.isLoading ) && <Charts getChart={ this.getChart }/> }
520
521 { ( 'chartSelect' === this.state.route && null !== this.state.chart ) &&
522 <ChartSelect
523 id={ this.props.attributes.id }
524 attributes={ this.props.attributes }
525 chart={ this.state.chart }
526 editSettings={ this.editSettings }
527 editPermissions={ this.editPermissions }
528 url={ this.state.url }
529 readUploadedFile={ this.readUploadedFile }
530 editURL={ this.editURL }
531 editSchedule={ this.editSchedule }
532 editJSONURL={ this.editJSONURL }
533 editJSONHeaders={ this.editJSONHeaders }
534 editJSONSchedule={ this.editJSONSchedule }
535 editJSONRoot={ this.editJSONRoot }
536 editJSONPaging={ this.editJSONPaging }
537 JSONImportData={ this.JSONImportData }
538 editDatabaseSchedule={ this.editDatabaseSchedule }
539 databaseImportData={ this.databaseImportData }
540 uploadData={ this.uploadData }
541 getChartData={ this.getChartData }
542 editChartData={ this.editChartData }
543 isLoading={ this.state.isLoading }
544 />
545 }
546
547 <div className="visualizer-settings__controls">
548
549 { ( 'showCharts' === this.state.route || 'chartSelect' === this.state.route ) &&
550 <ButtonGroup>
551
552 <Button
553 isDefault
554 isLarge
555 onClick={ () => {
556 let route;
557 if ( 'showCharts' === this.state.route ) {
558 route = 'home';
559 } else if ( 'chartSelect' === this.state.route ) {
560 route = 'showCharts';
561 }
562 this.setState({ route });
563 this.props.setAttributes({ route });
564 } }
565 >
566 { __( 'Back' ) }
567 </Button>
568
569 { 'chartSelect' === this.state.route &&
570 <Fragment>
571
572 { false === this.state.isModified ?
573 <Button
574 isDefault
575 isLarge
576 className="visualizer-bttn-done"
577 onClick={ () => {
578 this.setState({ route: 'renderChart' });
579 this.props.setAttributes({ route: 'renderChart' });
580 } }
581 >
582 { __( 'Done' ) }
583 </Button> :
584 <Button
585 isPrimary
586 isLarge
587 className="visualizer-bttn-save"
588 isBusy={ 'updateChart' === this.state.isLoading }
589 disabled={ 'updateChart' === this.state.isLoading }
590 onClick={ this.updateChart }
591 >
592 { __( 'Save' ) }
593 </Button>
594 }
595
596 </Fragment>
597 }
598
599 </ButtonGroup>
600 }
601
602 </div>
603 </div>
604 );
605 }
606 }
607
608 export default Editor;
609