PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.11.10
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.11.10
4.0.8 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 All 149 releases
← All changes | classes/Visualizer/Gutenberg/src/Editor.js +258 -47 3.1.33.11.10 View file →
@@ -6,9 +6,9 @@
6 6 import ChartSelect from './Components/ChartSelect.js';
7 7
8 8 import ChartRender from './Components/ChartRender.js';
9 9
10 -import { CSVToArray } from './utils.js';
10 +import { CSVToArray, buildChartPopup, tryGetPublishedChartData } from './utils.js';
11 11
12 12 /**
13 13 * WordPress dependencies
14 14 */
@@ -28,8 +28,9 @@
28 28 Button,
29 29 ButtonGroup,
30 30 Dashicon,
31 31 Placeholder,
32 + Notice,
32 33 Spinner
33 34 } = wp.components;
34 35
35 36 class Editor extends Component {
@@ -42,12 +43,21 @@
42 43 this.editPermissions = this.editPermissions.bind( this );
43 44 this.readUploadedFile = this.readUploadedFile.bind( this );
44 45 this.editURL = this.editURL.bind( this );
45 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 );
46 55 this.uploadData = this.uploadData.bind( this );
47 56 this.getChartData = this.getChartData.bind( this );
48 57 this.editChartData = this.editChartData.bind( this );
49 58 this.updateChart = this.updateChart.bind( this );
59 + this.createChart = this.createChart.bind( this );
50 60
51 61 this.state = {
52 62
53 63 /**
@@ -69,13 +79,22 @@
69 79 async componentDidMount() {
70 80
71 81 // Fetch review again if block loaded after saving.
72 82 if ( this.props.attributes.id ) {
73 - let result = await apiFetch({ path: `wp/v2/visualizer/${this.props.attributes.id}` });
83 + let result = await apiFetch({ path: `wp/v2/visualizer/${this.props.attributes.id}` }).catch( function( error ) {
84 + });
74 85
75 - this.setState({
76 - chart: result['chart_data']
77 - });
86 + if ( result ) {
87 + this.setState({
88 + chart: result['chart_data']
89 + });
90 + } else {
91 +
92 + // if the chart is not found.
93 + this.setState({
94 + route: 'error'
95 + });
96 + }
78 97 }
79 98 }
80 99
81 100 async getChart( id ) {
@@ -82,19 +101,27 @@
82 101 await this.setState({
83 102 isLoading: 'getChart'
84 103 });
85 104
86 - let result = await apiFetch({ path: `wp/v2/visualizer/${id}` });
105 + const chartDataRequest = await tryGetPublishedChartData( id );
87 106
107 + if ( 'publish' !== chartDataRequest.chartStatus ) {
108 + this.setState({ route: 'showCharts', isLoading: false });
109 + this.props.setAttributes({ route: 'showCharts' });
110 + return;
111 + }
112 +
88 113 this.setState({
89 114 route: 'chartSelect',
90 - chart: result['chart_data'],
91 - isLoading: false
115 + chart: chartDataRequest.result['chart_data'],
116 + isLoading: true,
117 + isModified: true
92 118 });
93 119
94 120 this.props.setAttributes({
95 121 id,
96 - route: 'chartSelect'
122 + route: 'chartSelect',
123 + lazy: -1
97 124 });
98 125 }
99 126
100 127 editChart() {
@@ -103,8 +130,11 @@
103 130 }
104 131
105 132 editSettings( settings ) {
106 133 let chart = { ...this.state.chart };
134 + if ( '1' !== settings.pagination ) {
135 + delete settings.pageSize;
136 + }
107 137 chart['visualizer-settings'] = settings;
108 138 this.setState({
109 139 chart,
110 140 isModified: true
@@ -138,11 +168,83 @@
138 168
139 169 editSchedule( schedule ) {
140 170 let chart = { ...this.state.chart };
141 171 chart['visualizer-chart-schedule'] = schedule;
172 + this.setState({
173 + chart,
174 + isModified: true
175 + });
176 + }
177 +
178 + editJSONSchedule( schedule ) {
179 + let chart = { ...this.state.chart };
180 + chart['visualizer-json-schedule'] = schedule;
181 + this.setState({
182 + chart,
183 + isModified: true
184 + });
185 + }
186 +
187 + editJSONURL( url ) {
188 + let chart = { ...this.state.chart };
189 + chart['visualizer-json-url'] = url;
142 190 this.setState({ chart });
143 191 }
144 192
193 + editJSONHeaders( headers ) {
194 + let chart = { ...this.state.chart };
195 + delete headers.username;
196 + delete headers.password;
197 + chart['visualizer-json-headers'] = headers;
198 + this.setState({ chart });
199 + }
200 +
201 + editJSONRoot( root ) {
202 + let chart = { ...this.state.chart };
203 + chart['visualizer-json-root'] = root;
204 + this.setState({ chart });
205 + }
206 +
207 + editJSONPaging( root ) {
208 + let chart = { ...this.state.chart };
209 + chart['visualizer-json-paging'] = root;
210 + this.setState({ chart });
211 + }
212 +
213 + JSONImportData( name, series, data ) {
214 + let chart = { ...this.state.chart };
215 + chart['visualizer-source'] = name;
216 + chart['visualizer-default-data'] = 0;
217 + chart['visualizer-series'] = series;
218 + chart['visualizer-data'] = data;
219 + this.setState({
220 + chart,
221 + isModified: true
222 + });
223 + }
224 +
225 + editDatabaseSchedule( schedule ) {
226 + let chart = { ...this.state.chart };
227 + chart['visualizer-db-schedule'] = schedule;
228 + this.setState({
229 + chart,
230 + isModified: true
231 + });
232 + }
233 +
234 + databaseImportData( query, name, series, data ) {
235 + let chart = { ...this.state.chart };
236 + chart['visualizer-source'] = name;
237 + chart['visualizer-default-data'] = 0;
238 + chart['visualizer-series'] = series;
239 + chart['visualizer-data'] = data;
240 + chart['visualizer-db-query'] = query;
241 + this.setState({
242 + chart,
243 + isModified: true
244 + });
245 + }
246 +
145 247 uploadData( scheduled = false ) {
146 248 this.setState({
147 249 isLoading: 'uploadData',
148 250 isScheduled: scheduled
@@ -230,13 +332,13 @@
230 332 chart
231 333 });
232 334 }
233 335
234 - editChartData( chartData, type ) {
336 + editChartData( chartData, source ) {
235 337 let chart = { ...this.state.chart };
236 338 let series = [];
237 339 let settings = { ...chart['visualizer-settings'] };
238 -
340 + let type = chart['visualizer-chart-type'];
239 341 chartData[0].map( ( i, index ) => {
240 342 series[index] = {
241 343 label: i,
242 344 type: chartData[1][index]
@@ -247,32 +349,64 @@
247 349
248 350 let map = series;
249 351 let fieldName = 'series';
250 352
251 - if ( 'pie' === chart['visualizer-chart-type']) {
252 - map = chartData;
253 - fieldName = 'slices';
254 - }
353 + switch ( type ) {
354 + case 'pie':
355 + map = chartData;
356 + fieldName = 'slices';
255 357
358 + // pie charts are finicky about a number being a number
359 + // and editing a number makes it a string
360 + // so let's convert it back into a number.
361 + chartData.map( ( i, index ) => {
362 + switch ( series[1].type ) {
363 + case 'number':
364 + i[1] = parseFloat( i[1]);
365 + break;
366 + }
367 + });
368 + break;
369 + case 'tabular':
370 +
371 + // table charts are finicky about a boolean being a boolean
372 + // and editing a boolean makes it a string
373 + // so let's convert it back into a boolean.
374 + chartData.map( ( i, index ) => {
375 + series.map( ( seriesObject, seriesIndex ) => {
376 + switch ( seriesObject.type ) {
377 + case 'boolean':
378 + if ( 'string' === typeof i[seriesIndex]) {
379 + i[seriesIndex] = 'true' === i[seriesIndex];
380 + }
381 + break;
382 + }
383 + });
384 + });
385 + break;
386 + }
387 +
256 388 map.map( ( i, index ) => {
257 - if ( 'pie' !== chart['visualizer-chart-type'] && 0 === index ) {
258 - return;
389 + if ( 'pie' !== type && 0 === index ) {
390 + return;
259 391 }
260 392
261 - const seriesIndex = 'pie' !== chart['visualizer-chart-type'] ? index - 1 : index;
393 + const seriesIndex = 'pie' !== type ? index - 1 : index;
262 394
263 - if ( settings[fieldName][seriesIndex] === undefined ) {
264 - settings[fieldName][seriesIndex] = {};
395 + if ( Array.isArray( settings[fieldName]) && settings[fieldName][seriesIndex] === undefined ) {
396 + settings[fieldName][seriesIndex] = {};
265 397 settings[fieldName][seriesIndex].temp = 1;
266 - }
398 + }
267 399 });
268 400
269 - settings[fieldName] = settings[fieldName].filter( ( i, index ) => {
270 - const length = 'pie' !== chart['visualizer-chart-type'] ? map.length - 1 : map.length;
271 - return index < length;
272 - });
401 + if ( Array.isArray( settings[fieldName]) ) {
402 + settings[fieldName] = settings[fieldName].filter( ( i, index ) => {
403 + const length = -1 >= [ 'pie', 'tabular', 'dataTable' ].indexOf( type ) ? map.length - 1 : map.length;
404 + return index < length;
405 + });
406 + }
273 407
274 - chart['visualizer-source'] = type;
408 + chart['visualizer-source'] = source;
275 409 chart['visualizer-default-data'] = 0;
276 410 chart['visualizer-data'] = chartData;
277 411 chart['visualizer-series'] = series;
278 412 chart['visualizer-settings'] = settings;
@@ -293,25 +427,31 @@
293 427 if ( false === this.state.isScheduled ) {
294 428 data['visualizer-chart-schedule'] = '';
295 429 }
296 430
297 - let fieldName = 'series';
431 + let dataChartStylingOption = 'series';
298 432
299 433 if ( 'pie' === data['visualizer-chart-type']) {
300 - fieldName = 'slices';
434 + dataChartStylingOption = 'slices';
301 435 }
302 436
303 - Object.keys( data['visualizer-settings'][fieldName])
304 - .map( i => {
305 - if ( data['visualizer-settings'][fieldName][i] !== undefined ) {
306 - if ( data['visualizer-settings'][fieldName][i].temp !== undefined ) {
307 - delete data['visualizer-settings'][fieldName][i].temp;
308 - }
309 - }
310 - }
311 - );
437 + // no series for bubble and timeline charts.
438 + if (
439 + undefined !== data['visualizer-settings'][dataChartStylingOption] &&
440 + -1 >= [ 'bubble', 'timeline' ].indexOf( data['visualizer-chart-type'])
441 + ) {
442 + Object.keys( data['visualizer-settings'][dataChartStylingOption])
443 + .map( i => {
444 + if ( data['visualizer-settings'][dataChartStylingOption][i] !== undefined ) {
445 + if ( data['visualizer-settings'][dataChartStylingOption][i].temp !== undefined ) {
446 + delete data['visualizer-settings'][dataChartStylingOption][i].temp;
447 + }
448 + }
449 + }
450 + );
451 + }
312 452
313 - apiRequest({ path: `/visualizer/v1/update-chart?id=${this.props.attributes.id}`, method: 'POST', data: data }).then(
453 + apiRequest({ path: `/visualizer/v1/update-chart?id=${ this.props.attributes.id }`, method: 'POST', data: data }).then(
314 454 ( data ) => {
315 455
316 456 this.setState({
317 457 isLoading: false,
@@ -325,12 +465,66 @@
325 465 }
326 466 );
327 467 }
328 468
469 + /**
470 + * Create a new chart via popup.
471 + *
472 + * @returns {void}
473 + */
474 + async createChart() {
475 +
476 + // Use the same popup like in Chart Library.
477 + const createChartPopup = new ( buildChartPopup() )({
478 + action: visualizerLocalize.createChart
479 + });
480 +
481 + // eslint-disable-next-line camelcase
482 + window.send_to_editor = () => {
483 + createChartPopup.close();
484 + };
485 +
486 + window.parent.addEventListener( 'message', ( event ) => {
487 + if ( 'visualizer:mediaframe:close' === event.data ) {
488 + createChartPopup.close();
489 + } else if ( event.data.chartID && null === this.state.chart ) {
490 + const chartID = parseInt( event.data.chartID, 10 );
491 + this.getChart( chartID );
492 + }
493 + }, false );
494 +
495 + createChartPopup.open();
496 + }
497 +
329 498 render() {
499 + if ( 'error' === this.state.route ) {
500 + return (
501 + <Notice
502 + status="error"
503 + isDismissible={ false }
504 + >
505 + <Dashicon icon="chart-pie" />
506 + { __( 'This chart is not available; it might have been deleted. Please delete this block and resubmit your chart.' ) }
507 + </Notice>
508 + );
509 + }
510 +
511 + if ( '1' === visualizerLocalize.isFullSiteEditor ) {
512 + return (
513 + <Notice
514 + status="error"
515 + isDismissible={ false }
516 + >
517 + <Dashicon icon="chart-pie" />
518 + { __( 'Visualizer block charts are currently not available for selection here, you must visit the library, get the shortcode, and add the chart here in a shortcode tag.' ) }
519 + </Notice>
520 + );
521 + }
522 +
330 523 if ( 'renderChart' === this.state.route && null !== this.state.chart ) {
331 524 return (
332 525 <ChartRender
526 + id={ this.props.attributes.id }
333 527 chart={ this.state.chart }
334 528 className={ this.props.className }
335 529 editChart={ this.editChart }
336 530 />
@@ -348,24 +542,29 @@
348 542 </div>
349 543
350 544 { 'home' === this.state.route && (
351 545 <div className="visualizer-settings__content">
352 -
353 546 <div className="visualizer-settings__content-description">
354 547 { __( 'Make a new chart or display an existing one?' ) }
355 548 </div>
356 549
357 - <div className="visualizer-settings__content-option locked">
550 + { /* You can apply "locked" class to lock any of the following list items. */ }
358 551
552 + <a
553 + onClick={ this.createChart }
554 + target="_blank"
555 + className="visualizer-settings__content-option"
556 + >
557 +
359 558 <span className="visualizer-settings__content-option-title">
360 - { __( 'Create a new chart (coming soon)' ) }
559 + { __( 'Create a new chart' ) }
361 560 </span>
362 561
363 562 <div className="visualizer-settings__content-option-icon">
364 - <Dashicon icon="lock" />
563 + <Dashicon icon="arrow-right-alt2" />
365 564 </div>
366 565
367 - </div>
566 + </a>
368 567
369 568 <div
370 569 className="visualizer-settings__content-option"
371 570 onClick={ () => {
@@ -396,8 +595,10 @@
396 595 { ( 'showCharts' === this.state.route && false === this.state.isLoading ) && <Charts getChart={ this.getChart }/> }
397 596
398 597 { ( 'chartSelect' === this.state.route && null !== this.state.chart ) &&
399 598 <ChartSelect
599 + id={ this.props.attributes.id }
600 + attributes={ this.props.attributes }
400 601 chart={ this.state.chart }
401 602 editSettings={ this.editSettings }
402 603 editPermissions={ this.editPermissions }
403 604 url={ this.state.url }
@@ -403,8 +604,16 @@
403 604 url={ this.state.url }
404 605 readUploadedFile={ this.readUploadedFile }
405 606 editURL={ this.editURL }
406 607 editSchedule={ this.editSchedule }
608 + editJSONURL={ this.editJSONURL }
609 + editJSONHeaders={ this.editJSONHeaders }
610 + editJSONSchedule={ this.editJSONSchedule }
611 + editJSONRoot={ this.editJSONRoot }
612 + editJSONPaging={ this.editJSONPaging }
613 + JSONImportData={ this.JSONImportData }
614 + editDatabaseSchedule={ this.editDatabaseSchedule }
615 + databaseImportData={ this.databaseImportData }
407 616 uploadData={ this.uploadData }
408 617 getChartData={ this.getChartData }
409 618 editChartData={ this.editChartData }
410 619 isLoading={ this.state.isLoading }
@@ -416,9 +625,9 @@
416 625 { ( 'showCharts' === this.state.route || 'chartSelect' === this.state.route ) &&
417 626 <ButtonGroup>
418 627
419 628 <Button
420 - isDefault
629 + variant="secondary"
421 630 isLarge
422 631 onClick={ () => {
423 632 let route;
424 633 if ( 'showCharts' === this.state.route ) {
@@ -425,9 +634,9 @@
425 634 route = 'home';
426 635 } else if ( 'chartSelect' === this.state.route ) {
427 636 route = 'showCharts';
428 637 }
429 - this.setState({ route });
638 + this.setState({ route, isLoading: false });
430 639 this.props.setAttributes({ route });
431 640 } }
432 641 >
433 642 { __( 'Back' ) }
@@ -437,12 +646,13 @@
437 646 <Fragment>
438 647
439 648 { false === this.state.isModified ?
440 649 <Button
441 - isDefault
650 + variant="secondary"
442 651 isLarge
652 + className="visualizer-bttn-done"
443 653 onClick={ () => {
444 - this.setState({ route: 'renderChart' });
654 + this.setState({ route: 'renderChart', isModified: true });
445 655 this.props.setAttributes({ route: 'renderChart' });
446 656 } }
447 657 >
448 658 { __( 'Done' ) }
@@ -449,8 +659,9 @@
449 659 </Button> :
450 660 <Button
451 661 isPrimary
452 662 isLarge
663 + className="visualizer-bttn-save"
453 664 isBusy={ 'updateChart' === this.state.isLoading }
454 665 disabled={ 'updateChart' === this.state.isLoading }
455 666 onClick={ this.updateChart }
456 667 >