From 740348eea4726b712d451fa643579f7db8821ce7 Mon Sep 17 00:00:00 2001 From: AlasDiablo <25723276+AlasDiablo@users.noreply.github.com> Date: Thu, 14 Sep 2023 15:53:57 +0200 Subject: [PATCH 01/37] feat: add an advanced mode to bar chart --- src/app/js/formats/chartsUtils.js | 16 + .../component/bar-chart/BarChartAdmin.js | 501 ++++++++++-------- .../component/bar-chart/BarChartView.js | 24 +- .../js/formats/vega-lite/models/BarChart.js | 63 ++- 4 files changed, 367 insertions(+), 237 deletions(-) diff --git a/src/app/js/formats/chartsUtils.js b/src/app/js/formats/chartsUtils.js index 8a0653880..121bf2cfd 100644 --- a/src/app/js/formats/chartsUtils.js +++ b/src/app/js/formats/chartsUtils.js @@ -73,3 +73,19 @@ export const lodexOrderToIdOrder = orderBy => { return INVALID_VALUE; } }; + +/** + * Convert text value to code value + * @param direction{'vertical' | 'horizontal'} + * @returns {number} + */ +export const lodexDirectionToIdDirection = direction => { + switch (direction) { + case 'vertical': + return AXIS_VERTICAL; + case 'horizontal': + return AXIS_HORIZONTAL; + default: + return INVALID_VALUE; + } +}; diff --git a/src/app/js/formats/vega-lite/component/bar-chart/BarChartAdmin.js b/src/app/js/formats/vega-lite/component/bar-chart/BarChartAdmin.js index 09d4c4829..a4d566585 100644 --- a/src/app/js/formats/vega-lite/component/bar-chart/BarChartAdmin.js +++ b/src/app/js/formats/vega-lite/component/bar-chart/BarChartAdmin.js @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React, { useEffect, useMemo } from 'react'; import PropTypes from 'prop-types'; import { TextField, @@ -6,6 +6,9 @@ import { Checkbox, FormControlLabel, Box, + Switch, + FormGroup, + Button, } from '@mui/material'; import translate from 'redux-polyglot/translate'; @@ -15,12 +18,22 @@ import RoutineParamsAdmin from '../../../shared/RoutineParamsAdmin'; import ColorPickerParamsAdmin from '../../../shared/ColorPickerParamsAdmin'; import { MULTICHROMATIC_DEFAULT_COLORSET } from '../../../colorUtils'; import ToolTips from '../../../shared/ToolTips'; +import BarChart from '../../models/BarChart'; +import { + AXIS_X, + AXIS_Y, + lodexDirectionToIdDirection, + lodexOrderToIdOrder, + lodexScaleToIdScale, +} from '../../../chartsUtils'; export const defaultArgs = { params: { maxSize: 200, orderBy: 'value/asc', }, + advanceMode: false, + advanceModeSpec: null, colors: MULTICHROMATIC_DEFAULT_COLORSET, axisRoundValue: true, diagonalCategoryAxis: false, @@ -35,251 +48,317 @@ export const defaultArgs = { barSize: 20, }; -class BarChartAdmin extends Component { - static propTypes = { - args: PropTypes.shape({ - params: PropTypes.shape({ - maxSize: PropTypes.number, - maxValue: PropTypes.number, - minValue: PropTypes.number, - orderBy: PropTypes.string, - }), - colors: PropTypes.string, - axisRoundValue: PropTypes.bool, - diagonalCategoryAxis: PropTypes.bool, - diagonalValueAxis: PropTypes.bool, - scale: PropTypes.oneOf(['log', 'linear']), - direction: PropTypes.oneOf(['horizontal', 'vertical']), - barSize: PropTypes.number, - tooltip: PropTypes.bool, - tooltipCategory: PropTypes.string, - tooltipValue: PropTypes.string, - labels: PropTypes.bool, - labelOverlap: PropTypes.bool, - }), - onChange: PropTypes.func.isRequired, - p: polyglotPropTypes.isRequired, - showMaxSize: PropTypes.bool.isRequired, - showMaxValue: PropTypes.bool.isRequired, - showMinValue: PropTypes.bool.isRequired, - showOrderBy: PropTypes.bool.isRequired, +const BarChartAdmin = props => { + const { + p: polyglot, + args, + showMaxSize, + showMaxValue, + showMinValue, + showOrderBy, + } = props; + const { + advanceMode, + advanceModeSpec, + params, + tooltip, + tooltipCategory, + tooltipValue, + labels, + barSize, + diagonalCategoryAxis, + diagonalValueAxis, + scale, + direction, + axisRoundValue, + labelOverlap, + } = args; + + const colors = useMemo(() => { + return args.colors || defaultArgs.colors; + }, [args.colors]); + + const spec = useMemo(() => { + if (!advanceMode) { + return null; + } + + if (advanceModeSpec !== null) { + return advanceModeSpec; + } + + const specBuilder = new BarChart(); + specBuilder.setAxisDirection(lodexDirectionToIdDirection(direction)); + specBuilder.setOrderBy(lodexOrderToIdOrder(params.orderBy)); + specBuilder.setScale(lodexScaleToIdScale(scale)); + specBuilder.setColor(colors); + specBuilder.setRoundValue(axisRoundValue); + specBuilder.setTooltip(tooltip); + specBuilder.setTooltipCategory(tooltipCategory); + specBuilder.setTooltipValue(tooltipValue); + specBuilder.setLabels(labels); + specBuilder.setLabelOverlap(labelOverlap); + specBuilder.setSize(barSize); + if (diagonalCategoryAxis) { + specBuilder.setLabelAngle(AXIS_X, -45); + } + if (diagonalValueAxis) { + specBuilder.setLabelAngle(AXIS_Y, -45); + } + + return JSON.stringify(specBuilder.buildSpec(null, null, true), null, 2); + }, [advanceMode, advanceModeSpec]); + + useEffect(() => { + if (!advanceMode) { + return; + } + updateAdminArgs('advanceModeSpec', spec, props); + }, [advanceMode, advanceModeSpec]); + + const toggleAdvanceMode = () => { + updateAdminArgs('advanceMode', !args.advanceMode, props); }; - static defaultProps = { - args: defaultArgs, - showMaxSize: true, - showMaxValue: true, - showMinValue: true, - showOrderBy: true, + const handleAdvanceModeSpec = event => { + updateAdminArgs('advanceModeSpec', event.target.value, props); }; - constructor(props) { - super(props); - this.setColors = this.setColors.bind(this); - this.setTooltipValue = this.setTooltipValue.bind(this); - this.setTooltipCategory = this.setTooltipCategory.bind(this); - this.state = { - colors: this.props.args.colors || defaultArgs.colors, - }; - } + const clearAdvanceModeSpec = () => { + updateAdminArgs('advanceModeSpec', null, props); + }; - setParams = params => updateAdminArgs('params', params, this.props); + const handleParams = params => { + updateAdminArgs('params', params, props); + }; - setColors(colors) { + const handleColors = colors => { updateAdminArgs('colors', colors || defaultArgs.colors, this.props); - } + }; - setAxisRoundValue = () => { - updateAdminArgs( - 'axisRoundValue', - !this.props.args.axisRoundValue, - this.props, - ); + const handleAxisRoundValue = () => { + updateAdminArgs('axisRoundValue', !args.axisRoundValue, props); }; - setScale = e => { - updateAdminArgs('scale', e.target.value, this.props); + const handleScale = event => { + updateAdminArgs('scale', event.target.value, props); }; - setDirection = e => { - updateAdminArgs('direction', e.target.value, this.props); + const handleDirection = event => { + updateAdminArgs('direction', event.target.value, props); }; - toggleDiagonalValueAxis = () => { - updateAdminArgs( - 'diagonalValueAxis', - !this.props.args.diagonalValueAxis, - this.props, - ); + const toggleDiagonalValueAxis = () => { + updateAdminArgs('diagonalValueAxis', !args.diagonalValueAxis, props); }; - toggleDiagonalCategoryAxis = () => { + const toggleDiagonalCategoryAxis = () => { updateAdminArgs( 'diagonalCategoryAxis', - !this.props.args.diagonalCategoryAxis, - this.props, + !args.diagonalCategoryAxis, + props, ); }; - setBarSize = e => { - updateAdminArgs('barSize', e.target.value, this.props); + const handleBarSize = event => { + updateAdminArgs('barSize', event.target, props); }; - toggleTooltip = () => { - updateAdminArgs('tooltip', !this.props.args.tooltip, this.props); + const toggleTooltip = () => { + updateAdminArgs('tooltip', args.tooltip, props); }; - toggleLabels = () => { - updateAdminArgs('labels', !this.props.args.labels, this.props); + const toggleLabels = () => { + updateAdminArgs('labels', args.labels, props); }; - toggleLabelOverlap = () => { - updateAdminArgs( - 'labelOverlap', - !this.props.args.labelOverlap, - this.props, - ); + const toggleLabelOverlap = () => { + updateAdminArgs('labelOverlap', !args.labelOverlap, props); }; - setTooltipCategory(tooltipCategory) { - updateAdminArgs('tooltipCategory', tooltipCategory, this.props); - } - - setTooltipValue(tooltipValue) { - updateAdminArgs('tooltipValue', tooltipValue, this.props); - } + const handleTooltipCategory = category => { + updateAdminArgs('tooltipCategory', category, props); + }; - render() { - const { - p: polyglot, - args: { - params, - axisRoundValue, - diagonalValueAxis, - diagonalCategoryAxis, - scale, - direction, - barSize, - tooltip, - tooltipCategory, - tooltipValue, - labels, - labelOverlap, - }, - showMaxSize, - showMaxValue, - showMinValue, - showOrderBy, - } = this.props; + const handleTooltipValue = value => { + updateAdminArgs('tooltipValue', value, props); + }; - return ( - - - - - - - {polyglot.t('horizontal')} - - - {polyglot.t('vertical')} - - - - } - label={polyglot.t('diagonal_category_axis')} - /> - - } - label={polyglot.t('diagonal_value_axis')} - /> - - } - label={polyglot.t('axis_round_value')} - /> + return ( + + } - label={polyglot.t('toggle_labels')} + label={polyglot.t('advancedMode')} /> - - } - label={polyglot.t('toggle_label_overlap')} - /> - - {polyglot.t('linear')} - {polyglot.t('log')} - - - - ); - } -} + + + {!advanceMode ? ( + <> + + + + + {polyglot.t('horizontal')} + + + {polyglot.t('vertical')} + + + + } + label={polyglot.t('diagonal_category_axis')} + /> + + } + label={polyglot.t('diagonal_value_axis')} + /> + + } + label={polyglot.t('axis_round_value')} + /> + + } + label={polyglot.t('toggle_labels')} + /> + + } + label={polyglot.t('toggle_label_overlap')} + /> + + + {polyglot.t('linear')} + + {polyglot.t('log')} + + + + ) : ( + <> + + + + )} + + ); +}; + +BarChartAdmin.defaultProps = { + args: defaultArgs, + showMaxSize: true, + showMaxValue: true, + showMinValue: true, + showOrderBy: true, +}; + +BarChartAdmin.propTypes = { + args: PropTypes.shape({ + params: PropTypes.shape({ + maxSize: PropTypes.number, + maxValue: PropTypes.number, + minValue: PropTypes.number, + orderBy: PropTypes.string, + }), + advanceMode: PropTypes.bool, + advanceModeSpec: PropTypes.string, + colors: PropTypes.string, + axisRoundValue: PropTypes.bool, + diagonalCategoryAxis: PropTypes.bool, + diagonalValueAxis: PropTypes.bool, + scale: PropTypes.oneOf(['log', 'linear']), + direction: PropTypes.oneOf(['horizontal', 'vertical']), + barSize: PropTypes.number, + tooltip: PropTypes.bool, + tooltipCategory: PropTypes.string, + tooltipValue: PropTypes.string, + labels: PropTypes.bool, + labelOverlap: PropTypes.bool, + }), + onChange: PropTypes.func.isRequired, + p: polyglotPropTypes.isRequired, + showMaxSize: PropTypes.bool.isRequired, + showMaxValue: PropTypes.bool.isRequired, + showMinValue: PropTypes.bool.isRequired, + showOrderBy: PropTypes.bool.isRequired, +}; export default translate(BarChartAdmin); diff --git a/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js b/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js index ca195e6cf..f2bf72e16 100644 --- a/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js +++ b/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js @@ -17,6 +17,8 @@ import { import BarChart from '../../models/BarChart'; import { CustomActionVegaLite } from '../vega-lite-component'; import deepClone from 'lodash.clonedeep'; +import InvalidFormat from '../../../InvalidFormat'; +import { VEGA_ACTIONS_WIDTH } from '../vega-lite-component/VegaLiteComponent'; const styles = { container: { @@ -27,6 +29,7 @@ const styles = { class BarChartView extends Component { render() { const data = this.props.data; + const { advanceMode, advanceModeSpec, field } = this.props; // Create a new bar chart instance @@ -56,16 +59,27 @@ class BarChartView extends Component { if (this.props.diagonalValueAxis) barChartSpec.setLabelAngle(AXIS_Y, -45); + let advanceSpec; + + try { + advanceSpec = JSON.parse(advanceModeSpec); + } catch (e) { + return ; + } + // return the finish chart return (
{/* Make the chart responsive */} {({ width }) => { - const spec = barChartSpec.buildSpec( - width, - data.values.length, - ); + const spec = advanceMode + ? { + ...advanceSpec, + width: width - VEGA_ACTIONS_WIDTH, + } + : barChartSpec.buildSpec(width, data.values.length); + console.log(spec, advanceSpec); return ( = width) { - encoding.size = { - value: width / (dataNumber + 1), - }; + if (!editMode) { + if (this.direction === AXIS_VERTICAL) { + width = widthIn - VEGA_ACTIONS_WIDTH; + height = 300; + if (dataNumber * (parseInt(this.size) + 4) >= width) { + encoding.size = { + value: width / (dataNumber + 1), + }; + } else { + encoding.size = { + value: parseInt(this.size), + }; + } } else { - encoding.size = { - value: parseInt(this.size), - }; + width = widthIn - VEGA_ACTIONS_WIDTH; + height = { step: parseInt(this.size) }; } - } else { - width = widthIn - VEGA_ACTIONS_WIDTH; - height = { step: parseInt(this.size) }; } if (!this.labels) { - return { + const toReturn = { mark: model.mark, encoding: encoding, padding: this.padding, - width: width, - height: height, autosize: this.autosize, }; + + if (editMode) { + return toReturn; + } + return { + ...toReturn, + width, + height, + }; } else { const mark = labelsModel.mark; if (this.direction !== AXIS_VERTICAL) { @@ -290,7 +301,7 @@ class BarChart extends BasicChart { mark.align = 'center'; } - return { + const toReturn = { layer: [ { mark: model.mark, @@ -305,10 +316,18 @@ class BarChart extends BasicChart { config: { view: { strokeWidth: 0 }, }, - width: width, - height: height, autosize: this.autosize, }; + + if (editMode) { + return toReturn; + } + + return { + ...toReturn, + width, + height, + }; } } } From 29efdd959a836a185345a097e3ba685554c8568a Mon Sep 17 00:00:00 2001 From: AlasDiablo <25723276+AlasDiablo@users.noreply.github.com> Date: Fri, 15 Sep 2023 07:49:29 +0200 Subject: [PATCH 02/37] refactor: rename variable and tweak some code --- .../component/bar-chart/BarChartAdmin.js | 52 +++++++++---------- .../component/bar-chart/BarChartView.js | 11 ++-- .../js/formats/vega-lite/models/BarChart.js | 11 ++-- .../js/formats/vega-lite/models/BasicChart.js | 5 ++ 4 files changed, 41 insertions(+), 38 deletions(-) diff --git a/src/app/js/formats/vega-lite/component/bar-chart/BarChartAdmin.js b/src/app/js/formats/vega-lite/component/bar-chart/BarChartAdmin.js index a4d566585..1ef451986 100644 --- a/src/app/js/formats/vega-lite/component/bar-chart/BarChartAdmin.js +++ b/src/app/js/formats/vega-lite/component/bar-chart/BarChartAdmin.js @@ -32,8 +32,8 @@ export const defaultArgs = { maxSize: 200, orderBy: 'value/asc', }, - advanceMode: false, - advanceModeSpec: null, + advancedMode: false, + advancedModeSpec: null, colors: MULTICHROMATIC_DEFAULT_COLORSET, axisRoundValue: true, diagonalCategoryAxis: false, @@ -58,8 +58,8 @@ const BarChartAdmin = props => { showOrderBy, } = props; const { - advanceMode, - advanceModeSpec, + advancedMode, + advancedModeSpec, params, tooltip, tooltipCategory, @@ -79,12 +79,12 @@ const BarChartAdmin = props => { }, [args.colors]); const spec = useMemo(() => { - if (!advanceMode) { + if (!advancedMode) { return null; } - if (advanceModeSpec !== null) { - return advanceModeSpec; + if (advancedModeSpec !== null) { + return advancedModeSpec; } const specBuilder = new BarChart(); @@ -105,27 +105,27 @@ const BarChartAdmin = props => { if (diagonalValueAxis) { specBuilder.setLabelAngle(AXIS_Y, -45); } - - return JSON.stringify(specBuilder.buildSpec(null, null, true), null, 2); - }, [advanceMode, advanceModeSpec]); + specBuilder.setEditMode(true); + return JSON.stringify(specBuilder.buildSpec(), null, 2); + }, [advancedMode, advancedModeSpec]); useEffect(() => { - if (!advanceMode) { + if (!advancedMode) { return; } - updateAdminArgs('advanceModeSpec', spec, props); - }, [advanceMode, advanceModeSpec]); + updateAdminArgs('advancedModeSpec', spec, props); + }, [advancedMode, advancedModeSpec]); - const toggleAdvanceMode = () => { - updateAdminArgs('advanceMode', !args.advanceMode, props); + const toggleAdvancedMode = () => { + updateAdminArgs('advancedMode', !args.advancedMode, props); }; - const handleAdvanceModeSpec = event => { - updateAdminArgs('advanceModeSpec', event.target.value, props); + const handleAdvancedModeSpec = event => { + updateAdminArgs('advancedModeSpec', event.target.value, props); }; - const clearAdvanceModeSpec = () => { - updateAdminArgs('advanceModeSpec', null, props); + const clearAdvancedModeSpec = () => { + updateAdminArgs('advancedModeSpec', null, props); }; const handleParams = params => { @@ -195,8 +195,8 @@ const BarChartAdmin = props => { } label={polyglot.t('advancedMode')} @@ -211,7 +211,7 @@ const BarChartAdmin = props => { showMinValue={showMinValue} showOrderBy={showOrderBy} /> - {!advanceMode ? ( + {!advancedMode ? ( <> { ) : ( <> - ; } @@ -73,13 +73,12 @@ class BarChartView extends Component { {/* Make the chart responsive */} {({ width }) => { - const spec = advanceMode + const spec = advancedMode ? { ...advanceSpec, width: width - VEGA_ACTIONS_WIDTH, } : barChartSpec.buildSpec(width, data.values.length); - console.log(spec, advanceSpec); return ( Date: Fri, 15 Sep 2023 08:03:04 +0200 Subject: [PATCH 03/37] refactor: convert PieChartAdmin Component into a FunctionComponent --- .../component/pie-chart/PieChartAdmin.js | 201 +++++++++--------- 1 file changed, 95 insertions(+), 106 deletions(-) diff --git a/src/app/js/formats/vega-lite/component/pie-chart/PieChartAdmin.js b/src/app/js/formats/vega-lite/component/pie-chart/PieChartAdmin.js index 2038dcde7..d9a13c3e9 100644 --- a/src/app/js/formats/vega-lite/component/pie-chart/PieChartAdmin.js +++ b/src/app/js/formats/vega-lite/component/pie-chart/PieChartAdmin.js @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React, { useMemo } from 'react'; import PropTypes from 'prop-types'; import translate from 'redux-polyglot/translate'; import { Box, Checkbox, FormControlLabel } from '@mui/material'; @@ -22,122 +22,111 @@ export const defaultArgs = { labels: false, }; -class PieChartAdmin extends Component { - static propTypes = { - args: PropTypes.shape({ - params: PropTypes.shape({ - maxSize: PropTypes.number, - maxValue: PropTypes.number, - minValue: PropTypes.number, - orderBy: PropTypes.string, - }), - colors: PropTypes.string, - tooltip: PropTypes.bool, - tooltipCategory: PropTypes.string, - tooltipValue: PropTypes.string, - labels: PropTypes.bool, - }), - onChange: PropTypes.func.isRequired, - p: polyglotPropTypes.isRequired, - showMaxSize: PropTypes.bool.isRequired, - showMaxValue: PropTypes.bool.isRequired, - showMinValue: PropTypes.bool.isRequired, - showOrderBy: PropTypes.bool.isRequired, - }; +const PieChartAdmin = props => { + const { + p: polyglot, + args, + showMaxSize, + showMaxValue, + showMinValue, + showOrderBy, + } = props; - static defaultProps = { - args: defaultArgs, - showMaxSize: true, - showMaxValue: true, - showMinValue: true, - showOrderBy: true, - }; + const { params, tooltip, tooltipCategory, tooltipValue, labels } = args; - constructor(props) { - super(props); - this.setColors = this.setColors.bind(this); - this.setTooltipValue = this.setTooltipValue.bind(this); - this.setTooltipCategory = this.setTooltipCategory.bind(this); - this.state = { - colors: this.props.args.colors || defaultArgs.colors, - }; - } + const colors = useMemo(() => { + return args.colors || defaultArgs.colors; + }, [args.colors]); - setParams = params => updateAdminArgs('params', params, this.props); + const handleParams = params => updateAdminArgs('params', params, props); - setColors(colors) { - updateAdminArgs('colors', colors || defaultArgs.colors, this.props); - } + const handleColors = colors => { + updateAdminArgs('colors', colors || defaultArgs.colors, props); + }; - toggleLabels = () => { - updateAdminArgs('labels', !this.props.args.labels, this.props); + const toggleLabels = () => { + updateAdminArgs('labels', !args.labels, props); }; - toggleTooltip = () => { - updateAdminArgs('tooltip', !this.props.args.tooltip, this.props); + const toggleTooltip = () => { + updateAdminArgs('tooltip', !args.tooltip, props); }; - setTooltipCategory(tooltipCategory) { - updateAdminArgs('tooltipCategory', tooltipCategory, this.props); - } + const handleTooltipCategory = tooltipCategory => { + updateAdminArgs('tooltipCategory', tooltipCategory, props); + }; - setTooltipValue(tooltipValue) { - updateAdminArgs('tooltipValue', tooltipValue, this.props); - } + const handleTooltipValue = tooltipValue => { + updateAdminArgs('tooltipValue', tooltipValue, props); + }; - render() { - const { - p: polyglot, - args: { params, tooltip, tooltipCategory, tooltipValue, labels }, - showMaxSize, - showMaxValue, - showMinValue, - showOrderBy, - } = this.props; + return ( + + + } + label={polyglot.t('toggle_labels')} + /> + + + + ); +}; + +PieChartAdmin.defaultProps = { + args: defaultArgs, + showMaxSize: true, + showMaxValue: true, + showMinValue: true, + showOrderBy: true, +}; - return ( - - - - } - label={polyglot.t('toggle_labels')} - /> - - - - ); - } -} +PieChartAdmin.propTypes = { + args: PropTypes.shape({ + params: PropTypes.shape({ + maxSize: PropTypes.number, + maxValue: PropTypes.number, + minValue: PropTypes.number, + orderBy: PropTypes.string, + }), + colors: PropTypes.string, + tooltip: PropTypes.bool, + tooltipCategory: PropTypes.string, + tooltipValue: PropTypes.string, + labels: PropTypes.bool, + }), + onChange: PropTypes.func.isRequired, + p: polyglotPropTypes.isRequired, + showMaxSize: PropTypes.bool.isRequired, + showMaxValue: PropTypes.bool.isRequired, + showMinValue: PropTypes.bool.isRequired, + showOrderBy: PropTypes.bool.isRequired, +}; export default translate(PieChartAdmin); From 642713e9b8b03ea38acebbb535315aa151f7b671 Mon Sep 17 00:00:00 2001 From: AlasDiablo <25723276+AlasDiablo@users.noreply.github.com> Date: Fri, 15 Sep 2023 08:18:05 +0200 Subject: [PATCH 04/37] refactor: convert HeatMapAdmin Component into a FunctionComponent --- .../component/heatmap/HeatMapAdmin.js | 226 +++++++++--------- 1 file changed, 108 insertions(+), 118 deletions(-) diff --git a/src/app/js/formats/vega-lite/component/heatmap/HeatMapAdmin.js b/src/app/js/formats/vega-lite/component/heatmap/HeatMapAdmin.js index 6910ddeae..c44eb8b7d 100644 --- a/src/app/js/formats/vega-lite/component/heatmap/HeatMapAdmin.js +++ b/src/app/js/formats/vega-lite/component/heatmap/HeatMapAdmin.js @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React from 'react'; import translate from 'redux-polyglot/translate'; import { schemeOrRd } from 'd3-scale-chromatic'; import PropTypes from 'prop-types'; @@ -23,140 +23,130 @@ export const defaultArgs = { tooltipWeight: 'Weight', }; -class HeatMapAdmin extends Component { - static propTypes = { - args: PropTypes.shape({ - params: PropTypes.shape({ - maxSize: PropTypes.number, - maxValue: PropTypes.number, - minValue: PropTypes.number, - orderBy: PropTypes.string, - }), - colorScheme: PropTypes.arrayOf(PropTypes.string), - flipAxis: PropTypes.bool, - tooltip: PropTypes.bool, - tooltipSource: PropTypes.string, - tooltipTarget: PropTypes.string, - tooltipWeight: PropTypes.string, - }), - onChange: PropTypes.func.isRequired, - p: polyglotPropTypes.isRequired, - showMaxSize: PropTypes.bool.isRequired, - showMaxValue: PropTypes.bool.isRequired, - showMinValue: PropTypes.bool.isRequired, - showOrderBy: PropTypes.bool.isRequired, - }; - - static defaultProps = { - args: defaultArgs, - showMaxSize: true, - showMaxValue: true, - showMinValue: true, - showOrderBy: true, - }; +const HeatMapAdmin = props => { + const { + p: polyglot, + args, + showMaxSize, + showMaxValue, + showMinValue, + showOrderBy, + } = props; - constructor(props) { - super(props); - this.setTooltipSource = this.setTooltipSource.bind(this); - this.setTooltipTarget = this.setTooltipTarget.bind(this); - this.setTooltipWeight = this.setTooltipWeight.bind(this); - } + const { + params, + colorScheme, + flipAxis, + tooltip, + tooltipSource, + tooltipTarget, + tooltipWeight, + } = args; - setParams = params => { - updateAdminArgs('params', params, this.props); + const handleParams = params => { + updateAdminArgs('params', params, props); }; - handleColorSchemeChange = (_, colorScheme) => { + const handleColorSchemeChange = (_, colorScheme) => { updateAdminArgs( 'colorScheme', colorScheme.props.value.split(','), - this.props, + props, ); }; - toggleFlipAxis = () => { - updateAdminArgs('flipAxis', !this.props.args.flipAxis, this.props); + const toggleFlipAxis = () => { + updateAdminArgs('flipAxis', !flipAxis, props); }; - toggleTooltip = () => { - updateAdminArgs('tooltip', !this.props.args.tooltip, this.props); + const toggleTooltip = () => { + updateAdminArgs('tooltip', !tooltip, props); }; - setTooltipSource(tooltipSource) { - updateAdminArgs('tooltipSource', tooltipSource, this.props); - } + const handleTooltipSource = tooltipSource => { + updateAdminArgs('tooltipSource', tooltipSource, props); + }; - setTooltipTarget(tooltipTarget) { - updateAdminArgs('tooltipTarget', tooltipTarget, this.props); - } + const handleTooltipTarget = tooltipTarget => { + updateAdminArgs('tooltipTarget', tooltipTarget, props); + }; - setTooltipWeight(tooltipWeight) { - updateAdminArgs('tooltipWeight', tooltipWeight, this.props); - } + const handleTooltipWeight = tooltipWeight => { + updateAdminArgs('tooltipWeight', tooltipWeight, props); + }; - render() { - const { - p: polyglot, - args: { - params, - colorScheme, - flipAxis, - tooltip, - tooltipSource, - tooltipTarget, - tooltipWeight, - }, - showMaxSize, - showMaxValue, - showMinValue, - showOrderBy, - } = this.props; + return ( + + + + + + } + label={polyglot.t('flip_axis')} + /> + + ); +}; - return ( - - - - - - } - label={polyglot.t('flip_axis')} - /> - - ); - } -} +HeatMapAdmin.propTypes = { + args: PropTypes.shape({ + params: PropTypes.shape({ + maxSize: PropTypes.number, + maxValue: PropTypes.number, + minValue: PropTypes.number, + orderBy: PropTypes.string, + }), + colorScheme: PropTypes.arrayOf(PropTypes.string), + flipAxis: PropTypes.bool, + tooltip: PropTypes.bool, + tooltipSource: PropTypes.string, + tooltipTarget: PropTypes.string, + tooltipWeight: PropTypes.string, + }), + onChange: PropTypes.func.isRequired, + p: polyglotPropTypes.isRequired, + showMaxSize: PropTypes.bool.isRequired, + showMaxValue: PropTypes.bool.isRequired, + showMinValue: PropTypes.bool.isRequired, + showOrderBy: PropTypes.bool.isRequired, +}; + +HeatMapAdmin.defaultProps = { + args: defaultArgs, + showMaxSize: true, + showMaxValue: true, + showMinValue: true, + showOrderBy: true, +}; export default translate(HeatMapAdmin); From b8790bcf8bbf2e379741c2e0ead7a944f30c4a53 Mon Sep 17 00:00:00 2001 From: AlasDiablo <25723276+AlasDiablo@users.noreply.github.com> Date: Fri, 15 Sep 2023 08:33:10 +0200 Subject: [PATCH 05/37] refactor: convert CartographyAdmin Component into a FunctionComponent --- .../component/cartography/CartographyAdmin.js | 229 +++++++++--------- 1 file changed, 111 insertions(+), 118 deletions(-) diff --git a/src/app/js/formats/vega-lite/component/cartography/CartographyAdmin.js b/src/app/js/formats/vega-lite/component/cartography/CartographyAdmin.js index fc0e708be..6cc07fdb6 100644 --- a/src/app/js/formats/vega-lite/component/cartography/CartographyAdmin.js +++ b/src/app/js/formats/vega-lite/component/cartography/CartographyAdmin.js @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React from 'react'; import PropTypes from 'prop-types'; import translate from 'redux-polyglot/translate'; import { schemeOrRd } from 'd3-scale-chromatic'; @@ -23,137 +23,130 @@ export const defaultArgs = { worldPosition: MAP_WORLD, }; -class CartographyAdmin extends Component { - static propTypes = { - args: PropTypes.shape({ - params: PropTypes.shape({ - maxSize: PropTypes.number, - maxValue: PropTypes.number, - minValue: PropTypes.number, - orderBy: PropTypes.string, - }), - colorScheme: PropTypes.arrayOf(PropTypes.string), - tooltip: PropTypes.bool, - tooltipCategory: PropTypes.string, - tooltipValue: PropTypes.string, - worldPosition: PropTypes.oneOf([MAP_WORLD, MAP_EUROPE, MAP_FRANCE]), - }), - onChange: PropTypes.func.isRequired, - p: polyglotPropTypes.isRequired, - showMaxSize: PropTypes.bool.isRequired, - showMaxValue: PropTypes.bool.isRequired, - showMinValue: PropTypes.bool.isRequired, - showOrderBy: PropTypes.bool.isRequired, - }; - - static defaultProps = { - args: defaultArgs, - showMaxSize: true, - showMaxValue: true, - showMinValue: true, - showOrderBy: true, - }; +const CartographyAdmin = props => { + const { + p: polyglot, + args, + showMaxSize, + showMaxValue, + showMinValue, + showOrderBy, + } = props; + const { + params, + colorScheme, + tooltip, + tooltipCategory, + tooltipValue, + worldPosition, + } = args; - constructor(props) { - super(props); - this.setTooltipValue = this.setTooltipValue.bind(this); - this.setTooltipCategory = this.setTooltipCategory.bind(this); - } + const handleParams = params => updateAdminArgs('params', params, props); - setParams = params => updateAdminArgs('params', params, this.props); - - setWorldPosition = e => { - updateAdminArgs('worldPosition', e.target.value, this.props); + const handleWorldPosition = e => { + updateAdminArgs('worldPosition', e.target.value, props); }; - setColorScheme = (_, colorScheme) => { + const handleColorScheme = (_, colorScheme) => { updateAdminArgs( 'colorScheme', colorScheme.props.value.split(','), - this.props, + props, ); }; - toggleTooltip = () => { - updateAdminArgs('tooltip', !this.props.args.tooltip, this.props); + const toggleTooltip = () => { + updateAdminArgs('tooltip', !tooltip, props); }; - setTooltipCategory(tooltipCategory) { - updateAdminArgs('tooltipCategory', tooltipCategory, this.props); - } - - setTooltipValue(tooltipValue) { - updateAdminArgs('tooltipValue', tooltipValue, this.props); - } + const handleTooltipCategory = tooltipCategory => { + updateAdminArgs('tooltipCategory', tooltipCategory, props); + }; - render() { - const { - p: polyglot, - args: { - params, - colorScheme, - tooltip, - tooltipCategory, - tooltipValue, - worldPosition, - }, - showMaxSize, - showMaxValue, - showMinValue, - showOrderBy, - } = this.props; + const handleTooltipValue = tooltipValue => { + updateAdminArgs('tooltipValue', tooltipValue, props); + }; - return ( - + + - - - - {polyglot.t('world_position_world')} - - - {polyglot.t('world_position_europe')} - - - {polyglot.t('world_position_france')} - - - - - - ); - } -} + + {polyglot.t('world_position_world')} + + + {polyglot.t('world_position_europe')} + + + {polyglot.t('world_position_france')} + + + + + + ); +}; + +CartographyAdmin.propTypes = { + args: PropTypes.shape({ + params: PropTypes.shape({ + maxSize: PropTypes.number, + maxValue: PropTypes.number, + minValue: PropTypes.number, + orderBy: PropTypes.string, + }), + colorScheme: PropTypes.arrayOf(PropTypes.string), + tooltip: PropTypes.bool, + tooltipCategory: PropTypes.string, + tooltipValue: PropTypes.string, + worldPosition: PropTypes.oneOf([MAP_WORLD, MAP_EUROPE, MAP_FRANCE]), + }), + onChange: PropTypes.func.isRequired, + p: polyglotPropTypes.isRequired, + showMaxSize: PropTypes.bool.isRequired, + showMaxValue: PropTypes.bool.isRequired, + showMinValue: PropTypes.bool.isRequired, + showOrderBy: PropTypes.bool.isRequired, +}; + +CartographyAdmin.defaultProps = { + args: defaultArgs, + showMaxSize: true, + showMaxValue: true, + showMinValue: true, + showOrderBy: true, +}; export default translate(CartographyAdmin); From ddedebe2f58e97436eb0228d4d6b214405d2c6e5 Mon Sep 17 00:00:00 2001 From: AlasDiablo <25723276+AlasDiablo@users.noreply.github.com> Date: Fri, 15 Sep 2023 09:21:09 +0200 Subject: [PATCH 06/37] refactor: convert BubblePlotAdmin Component into a FunctionComponent --- .../component/bubble-plot/BubblePlotAdmin.js | 231 +++++++++--------- 1 file changed, 110 insertions(+), 121 deletions(-) diff --git a/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotAdmin.js b/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotAdmin.js index c35b6ea48..73080bb2d 100644 --- a/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotAdmin.js +++ b/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotAdmin.js @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React, { useMemo } from 'react'; import translate from 'redux-polyglot/translate'; import PropTypes from 'prop-types'; import { Box, Checkbox, FormControlLabel } from '@mui/material'; @@ -23,139 +23,128 @@ export const defaultArgs = { tooltipWeight: 'Weight', }; -class BubblePlotAdmin extends Component { - static propTypes = { - args: PropTypes.shape({ - params: PropTypes.shape({ - maxSize: PropTypes.number, - maxValue: PropTypes.number, - minValue: PropTypes.number, - orderBy: PropTypes.string, - }), - colors: PropTypes.string, - flipAxis: PropTypes.bool, - tooltip: PropTypes.bool, - tooltipSource: PropTypes.string, - tooltipTarget: PropTypes.string, - tooltipWeight: PropTypes.string, - }), - onChange: PropTypes.func.isRequired, - p: polyglotPropTypes.isRequired, - showMaxSize: PropTypes.bool.isRequired, - showMaxValue: PropTypes.bool.isRequired, - showMinValue: PropTypes.bool.isRequired, - showOrderBy: PropTypes.bool.isRequired, - }; +const BubblePlotAdmin = props => { + const { + p: polyglot, + args, + showMaxSize, + showMaxValue, + showMinValue, + showOrderBy, + } = props; + const { + params, + flipAxis, + tooltip, + tooltipSource, + tooltipTarget, + tooltipWeight, + } = args; - static defaultProps = { - args: defaultArgs, - showMaxSize: true, - showMaxValue: true, - showMinValue: true, - showOrderBy: true, - }; + const colors = useMemo(() => { + return args.colors || defaultArgs.colors; + }, [args.colors]); - constructor(props) { - super(props); - this.setColors = this.setColors.bind(this); - this.setTooltipSource = this.setTooltipSource.bind(this); - this.setTooltipTarget = this.setTooltipTarget.bind(this); - this.setTooltipWeight = this.setTooltipWeight.bind(this); - this.state = { - colors: this.props.args.colors || defaultArgs.colors, - }; - } + const handleColors = colors => { + updateAdminArgs('colors', colors || defaultArgs.colors, props); + }; - setColors(colors) { - updateAdminArgs('colors', colors || defaultArgs.colors, this.props); - } + const handleParams = params => { + updateAdminArgs('params', params, props); + }; - setParams = params => { - updateAdminArgs('params', params, this.props); + const toggleFlipAxis = () => { + updateAdminArgs('flipAxis', !flipAxis, props); }; - toggleFlipAxis = () => { - updateAdminArgs('flipAxis', !this.props.args.flipAxis, this.props); + const toggleTooltip = () => { + updateAdminArgs('tooltip', !tooltip, props); }; - toggleTooltip = () => { - updateAdminArgs('tooltip', !this.props.args.tooltip, this.props); + const handleTooltipSource = tooltipSource => { + updateAdminArgs('tooltipSource', tooltipSource, props); }; - setTooltipSource(tooltipSource) { - updateAdminArgs('tooltipSource', tooltipSource, this.props); - } + const handleTooltipTarget = tooltipTarget => { + updateAdminArgs('tooltipTarget', tooltipTarget, props); + }; - setTooltipTarget(tooltipTarget) { - updateAdminArgs('tooltipTarget', tooltipTarget, this.props); - } + const handleTooltipWeight = tooltipWeight => { + updateAdminArgs('tooltipWeight', tooltipWeight, props); + }; - setTooltipWeight(tooltipWeight) { - updateAdminArgs('tooltipWeight', tooltipWeight, this.props); - } + return ( + + + + } + label={polyglot.t('flip_axis')} + /> + + + + ); +}; - render() { - const { - p: polyglot, - args: { - params, - flipAxis, - tooltip, - tooltipSource, - tooltipTarget, - tooltipWeight, - }, - showMaxSize, - showMaxValue, - showMinValue, - showOrderBy, - } = this.props; +BubblePlotAdmin.propTypes = { + args: PropTypes.shape({ + params: PropTypes.shape({ + maxSize: PropTypes.number, + maxValue: PropTypes.number, + minValue: PropTypes.number, + orderBy: PropTypes.string, + }), + colors: PropTypes.string, + flipAxis: PropTypes.bool, + tooltip: PropTypes.bool, + tooltipSource: PropTypes.string, + tooltipTarget: PropTypes.string, + tooltipWeight: PropTypes.string, + }), + onChange: PropTypes.func.isRequired, + p: polyglotPropTypes.isRequired, + showMaxSize: PropTypes.bool.isRequired, + showMaxValue: PropTypes.bool.isRequired, + showMinValue: PropTypes.bool.isRequired, + showOrderBy: PropTypes.bool.isRequired, +}; - return ( - - - - } - label={polyglot.t('flip_axis')} - /> - - - - ); - } -} +BubblePlotAdmin.defaultProps = { + args: defaultArgs, + showMaxSize: true, + showMaxValue: true, + showMinValue: true, + showOrderBy: true, +}; export default translate(BubblePlotAdmin); From 03baeec742c9527a8ed6d6c102db357167f3b221 Mon Sep 17 00:00:00 2001 From: AlasDiablo <25723276+AlasDiablo@users.noreply.github.com> Date: Fri, 15 Sep 2023 11:50:07 +0200 Subject: [PATCH 07/37] feat: update model to use editMode variable --- src/app/js/formats/vega-lite/models/BubblePlot.js | 10 ++++++++-- src/app/js/formats/vega-lite/models/Cartography.js | 14 ++++++++++---- src/app/js/formats/vega-lite/models/HeatMap.js | 10 ++++++---- src/app/js/formats/vega-lite/models/PieChart.js | 12 +++++++----- 4 files changed, 31 insertions(+), 15 deletions(-) diff --git a/src/app/js/formats/vega-lite/models/BubblePlot.js b/src/app/js/formats/vega-lite/models/BubblePlot.js index 5b1721a98..2400e9beb 100644 --- a/src/app/js/formats/vega-lite/models/BubblePlot.js +++ b/src/app/js/formats/vega-lite/models/BubblePlot.js @@ -6,14 +6,20 @@ class BubblePlot extends HeatMap { this.model = require('./json/bubble_plot.vl.json'); } - buildSpec(widthIn) { + /** + * @param widthIn{number | null} + */ + buildSpec(widthIn = null) { this.model.encoding.color.scale.range = this.colors; this.model.encoding.x.axis.labelAngle = -35; this.commonWithBubblePlot(); - this.model.width = widthIn * 0.6; + if (!this.editMode) { + this.model.width = widthIn * 0.6; + } + return this.model; } } diff --git a/src/app/js/formats/vega-lite/models/Cartography.js b/src/app/js/formats/vega-lite/models/Cartography.js index c51ed30fa..cb31b28e8 100644 --- a/src/app/js/formats/vega-lite/models/Cartography.js +++ b/src/app/js/formats/vega-lite/models/Cartography.js @@ -26,9 +26,9 @@ class Cartography extends BasicChart { /** * Function use for rebuild the edited spec - * @param widthIn + * @param widthIn{number | null} */ - buildSpec(widthIn) { + buildSpec(widthIn = null) { this.model.encoding.color.scale.range = this.colors; if (this.tooltip.toggle) { @@ -59,6 +59,10 @@ class Cartography extends BasicChart { } } + if (this.editMode) { + widthIn = 600; + } + switch (this.worldPosition) { case MAP_EUROPE: { @@ -127,8 +131,10 @@ class Cartography extends BasicChart { break; } - this.model.width = widthIn - VEGA_ACTIONS_WIDTH; - this.model.height = widthIn * 0.6; + if (!this.editMode) { + this.model.width = widthIn - VEGA_ACTIONS_WIDTH; + this.model.height = widthIn * 0.6; + } this.model.autosize = this.autosize; return this.model; diff --git a/src/app/js/formats/vega-lite/models/HeatMap.js b/src/app/js/formats/vega-lite/models/HeatMap.js index 346d33a99..5a204fe30 100644 --- a/src/app/js/formats/vega-lite/models/HeatMap.js +++ b/src/app/js/formats/vega-lite/models/HeatMap.js @@ -112,9 +112,9 @@ class HeatMap extends BasicChart { /** * Function use for rebuild the edited spec - * @param widthIn + * @param widthIn{number | null} */ - buildSpec(widthIn) { + buildSpec(widthIn = null) { this.model.layer.forEach(e => { if (e.mark.type === 'rect') { e.encoding.color.scale.range = this.colors; @@ -128,8 +128,10 @@ class HeatMap extends BasicChart { this.commonWithBubblePlot(); - this.model.width = this.model.height = - widthIn * (widthIn <= 920 ? 0.5 : 0.7); + if (!this.editMode) { + this.model.width = this.model.height = + widthIn * (widthIn <= 920 ? 0.5 : 0.7); + } return this.model; } diff --git a/src/app/js/formats/vega-lite/models/PieChart.js b/src/app/js/formats/vega-lite/models/PieChart.js index 4d41e8301..c2fc54e3d 100644 --- a/src/app/js/formats/vega-lite/models/PieChart.js +++ b/src/app/js/formats/vega-lite/models/PieChart.js @@ -20,9 +20,9 @@ class PieChart extends BasicChart { /** * Function use for rebuild the edited spec - * @param widthIn + * @param widthIn{number | null} */ - buildSpec(widthIn) { + buildSpec(widthIn = null) { this.model.encoding.color.scale.range = this.colors; if (this.labels) { @@ -37,10 +37,12 @@ class PieChart extends BasicChart { this.tooltip.value, ]; - this.model.width = widthIn * (widthIn <= 920 ? 0.5 : 0.7); + if (!this.editMode) { + this.model.width = widthIn * (widthIn <= 920 ? 0.5 : 0.7); - this.model.encoding.color.legend.legendX = - widthIn * (widthIn <= 920 ? 0.5 : 0.7); + this.model.encoding.color.legend.legendX = + widthIn * (widthIn <= 920 ? 0.5 : 0.7); + } this.model.height = 300; From 05956a2aa79e6b3f882ea065290b713a0feef20e Mon Sep 17 00:00:00 2001 From: AlasDiablo <25723276+AlasDiablo@users.noreply.github.com> Date: Fri, 15 Sep 2023 11:52:44 +0200 Subject: [PATCH 08/37] feat: update props type --- .../vega-lite/component/bubble-plot/BubblePlotAdmin.js | 4 ++++ .../formats/vega-lite/component/bubble-plot/BubblePlotView.js | 2 ++ .../vega-lite/component/cartography/CartographyAdmin.js | 4 ++++ .../vega-lite/component/cartography/CartographyView.js | 2 ++ .../js/formats/vega-lite/component/heatmap/HeatMapAdmin.js | 4 ++++ src/app/js/formats/vega-lite/component/heatmap/HeatMapView.js | 2 ++ .../js/formats/vega-lite/component/pie-chart/PieChartAdmin.js | 4 ++++ .../js/formats/vega-lite/component/pie-chart/PieChartView.js | 2 ++ 8 files changed, 24 insertions(+) diff --git a/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotAdmin.js b/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotAdmin.js index 73080bb2d..f013800d1 100644 --- a/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotAdmin.js +++ b/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotAdmin.js @@ -15,6 +15,8 @@ export const defaultArgs = { maxSize: 200, orderBy: 'value/asc', }, + advancedMode: false, + advancedModeSpec: null, colors: MULTICHROMATIC_DEFAULT_COLORSET, flipAxis: false, tooltip: false, @@ -124,6 +126,8 @@ BubblePlotAdmin.propTypes = { minValue: PropTypes.number, orderBy: PropTypes.string, }), + advancedMode: PropTypes.bool, + advancedModeSpec: PropTypes.string, colors: PropTypes.string, flipAxis: PropTypes.bool, tooltip: PropTypes.bool, diff --git a/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotView.js b/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotView.js index 0ed01c6cc..32921975e 100644 --- a/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotView.js +++ b/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotView.js @@ -69,6 +69,8 @@ BubblePlotView.propTypes = { tooltipSource: PropTypes.string.isRequired, tooltipTarget: PropTypes.string.isRequired, tooltipWeight: PropTypes.string.isRequired, + advancedMode: PropTypes.bool, + advancedModeSpec: PropTypes.string, }; BubblePlotView.defaultProps = { diff --git a/src/app/js/formats/vega-lite/component/cartography/CartographyAdmin.js b/src/app/js/formats/vega-lite/component/cartography/CartographyAdmin.js index 6cc07fdb6..f3b1125b7 100644 --- a/src/app/js/formats/vega-lite/component/cartography/CartographyAdmin.js +++ b/src/app/js/formats/vega-lite/component/cartography/CartographyAdmin.js @@ -16,6 +16,8 @@ export const defaultArgs = { maxSize: 200, orderBy: 'value/asc', }, + advancedMode: false, + advancedModeSpec: null, colorScheme: schemeOrRd[9], tooltip: false, tooltipCategory: 'Category', @@ -127,6 +129,8 @@ CartographyAdmin.propTypes = { minValue: PropTypes.number, orderBy: PropTypes.string, }), + advancedMode: PropTypes.bool, + advancedModeSpec: PropTypes.string, colorScheme: PropTypes.arrayOf(PropTypes.string), tooltip: PropTypes.bool, tooltipCategory: PropTypes.string, diff --git a/src/app/js/formats/vega-lite/component/cartography/CartographyView.js b/src/app/js/formats/vega-lite/component/cartography/CartographyView.js index 7b3c3a4d1..56b9597ef 100644 --- a/src/app/js/formats/vega-lite/component/cartography/CartographyView.js +++ b/src/app/js/formats/vega-lite/component/cartography/CartographyView.js @@ -75,6 +75,8 @@ CartographyView.propTypes = { tooltipValue: PropTypes.string.isRequired, colorScheme: PropTypes.arrayOf(PropTypes.string).isRequired, worldPosition: PropTypes.string.isRequired, + advancedMode: PropTypes.bool, + advancedModeSpec: PropTypes.string, }; const mapStateToProps = (state, { formatData }) => { diff --git a/src/app/js/formats/vega-lite/component/heatmap/HeatMapAdmin.js b/src/app/js/formats/vega-lite/component/heatmap/HeatMapAdmin.js index c44eb8b7d..875f4d67b 100644 --- a/src/app/js/formats/vega-lite/component/heatmap/HeatMapAdmin.js +++ b/src/app/js/formats/vega-lite/component/heatmap/HeatMapAdmin.js @@ -15,6 +15,8 @@ export const defaultArgs = { maxSize: 200, orderBy: 'value/asc', }, + advancedMode: false, + advancedModeSpec: null, colorScheme: schemeOrRd[9], flipAxis: false, tooltip: false, @@ -126,6 +128,8 @@ HeatMapAdmin.propTypes = { minValue: PropTypes.number, orderBy: PropTypes.string, }), + advancedMode: PropTypes.bool, + advancedModeSpec: PropTypes.string, colorScheme: PropTypes.arrayOf(PropTypes.string), flipAxis: PropTypes.bool, tooltip: PropTypes.bool, diff --git a/src/app/js/formats/vega-lite/component/heatmap/HeatMapView.js b/src/app/js/formats/vega-lite/component/heatmap/HeatMapView.js index 946707225..945a64521 100644 --- a/src/app/js/formats/vega-lite/component/heatmap/HeatMapView.js +++ b/src/app/js/formats/vega-lite/component/heatmap/HeatMapView.js @@ -69,6 +69,8 @@ HeatMapView.propTypes = { tooltipSource: PropTypes.string.isRequired, tooltipTarget: PropTypes.string.isRequired, tooltipWeight: PropTypes.string.isRequired, + advancedMode: PropTypes.bool, + advancedModeSpec: PropTypes.string, }; HeatMapView.defaultProps = { diff --git a/src/app/js/formats/vega-lite/component/pie-chart/PieChartAdmin.js b/src/app/js/formats/vega-lite/component/pie-chart/PieChartAdmin.js index d9a13c3e9..d900ec39b 100644 --- a/src/app/js/formats/vega-lite/component/pie-chart/PieChartAdmin.js +++ b/src/app/js/formats/vega-lite/component/pie-chart/PieChartAdmin.js @@ -15,6 +15,8 @@ export const defaultArgs = { maxSize: 200, orderBy: 'value/asc', }, + advancedMode: false, + advancedModeSpec: null, colors: MULTICHROMATIC_DEFAULT_COLORSET, tooltip: false, tooltipCategory: 'Category', @@ -115,6 +117,8 @@ PieChartAdmin.propTypes = { minValue: PropTypes.number, orderBy: PropTypes.string, }), + advancedMode: PropTypes.bool, + advancedModeSpec: PropTypes.string, colors: PropTypes.string, tooltip: PropTypes.bool, tooltipCategory: PropTypes.string, diff --git a/src/app/js/formats/vega-lite/component/pie-chart/PieChartView.js b/src/app/js/formats/vega-lite/component/pie-chart/PieChartView.js index 1ae790a8c..e61edd99f 100644 --- a/src/app/js/formats/vega-lite/component/pie-chart/PieChartView.js +++ b/src/app/js/formats/vega-lite/component/pie-chart/PieChartView.js @@ -69,6 +69,8 @@ PieChartView.propTypes = { tooltipCategory: PropTypes.string.isRequired, tooltipValue: PropTypes.string.isRequired, labels: PropTypes.bool.isRequired, + advancedMode: PropTypes.bool, + advancedModeSpec: PropTypes.string, }; PieChartView.defaultProps = { From 718fc935e5fd6a40fb95e7fc13eab34980f0c44e Mon Sep 17 00:00:00 2001 From: AlasDiablo <25723276+AlasDiablo@users.noreply.github.com> Date: Fri, 15 Sep 2023 13:41:34 +0200 Subject: [PATCH 09/37] refactor: update model import --- .../vega-lite/component/bar-chart/BarChartView.js | 3 +-- .../vega-lite/component/bubble-plot/BubblePlotView.js | 3 +-- .../vega-lite/component/cartography/CartographyView.js | 3 +-- .../formats/vega-lite/component/heatmap/HeatMapView.js | 3 +-- .../vega-lite/component/pie-chart/PieChartView.js | 3 +-- src/app/js/formats/vega-lite/models/BarChart.js | 9 ++++++--- src/app/js/formats/vega-lite/models/BubblePlot.js | 4 +++- src/app/js/formats/vega-lite/models/Cartography.js | 6 ++++-- src/app/js/formats/vega-lite/models/HeatMap.js | 6 ++++-- src/app/js/formats/vega-lite/models/PieChart.js | 9 ++++++--- 10 files changed, 28 insertions(+), 21 deletions(-) diff --git a/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js b/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js index dde456d5a..fd29597d5 100644 --- a/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js +++ b/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js @@ -16,7 +16,6 @@ import { } from '../../../chartsUtils'; import BarChart from '../../models/BarChart'; import { CustomActionVegaLite } from '../vega-lite-component'; -import deepClone from 'lodash.clonedeep'; import InvalidFormat from '../../../InvalidFormat'; import { VEGA_ACTIONS_WIDTH } from '../vega-lite-component/VegaLiteComponent'; @@ -33,7 +32,7 @@ class BarChartView extends Component { // Create a new bar chart instance - const barChartSpec = deepClone(new BarChart()); + const barChartSpec = new BarChart(); // Set all bar chart parameter the chosen by the administrator diff --git a/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotView.js b/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotView.js index 32921975e..648b68883 100644 --- a/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotView.js +++ b/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotView.js @@ -6,7 +6,6 @@ import compose from 'recompose/compose'; import { field as fieldPropTypes } from '../../../../propTypes'; import PropTypes from 'prop-types'; import ContainerDimensions from 'react-container-dimensions'; -import deepClone from 'lodash.clonedeep'; import { lodexOrderToIdOrder, VEGA_LITE_DATA_INJECT_TYPE_A, @@ -25,7 +24,7 @@ class BubblePlotView extends Component { // Create a new bubble plot instance - const bubblePlot = deepClone(new BubblePlot()); + const bubblePlot = new BubblePlot(); // Set all bubble plot parameter the chosen by the administrator diff --git a/src/app/js/formats/vega-lite/component/cartography/CartographyView.js b/src/app/js/formats/vega-lite/component/cartography/CartographyView.js index 56b9597ef..9148294ef 100644 --- a/src/app/js/formats/vega-lite/component/cartography/CartographyView.js +++ b/src/app/js/formats/vega-lite/component/cartography/CartographyView.js @@ -2,7 +2,6 @@ import React, { Component } from 'react'; import { connect } from 'react-redux'; import PropTypes from 'prop-types'; import compose from 'recompose/compose'; -import deepClone from 'lodash.clonedeep'; import ContainerDimensions from 'react-container-dimensions'; import { CustomActionVegaLite } from '../vega-lite-component'; import { @@ -27,7 +26,7 @@ class CartographyView extends Component { // Create a new cartography instance - const cartography = deepClone(new Cartography()); + const cartography = new Cartography(); // Set all cartography parameter the chosen by the administrator diff --git a/src/app/js/formats/vega-lite/component/heatmap/HeatMapView.js b/src/app/js/formats/vega-lite/component/heatmap/HeatMapView.js index 945a64521..56b2d7de9 100644 --- a/src/app/js/formats/vega-lite/component/heatmap/HeatMapView.js +++ b/src/app/js/formats/vega-lite/component/heatmap/HeatMapView.js @@ -7,7 +7,6 @@ import HeatMap from '../../models/HeatMap'; import { field as fieldPropTypes } from '../../../../propTypes'; import PropTypes from 'prop-types'; import ContainerDimensions from 'react-container-dimensions'; -import deepClone from 'lodash.clonedeep'; import { lodexOrderToIdOrder, VEGA_LITE_DATA_INJECT_TYPE_A, @@ -25,7 +24,7 @@ class HeatMapView extends Component { // Create a new heat map instance - const heatMap = deepClone(new HeatMap()); + const heatMap = new HeatMap(); // Set all heat map parameter the chosen by the administrator diff --git a/src/app/js/formats/vega-lite/component/pie-chart/PieChartView.js b/src/app/js/formats/vega-lite/component/pie-chart/PieChartView.js index e61edd99f..af3878ee2 100644 --- a/src/app/js/formats/vega-lite/component/pie-chart/PieChartView.js +++ b/src/app/js/formats/vega-lite/component/pie-chart/PieChartView.js @@ -8,7 +8,6 @@ import ContainerDimensions from 'react-container-dimensions'; import PieChart from '../../models/PieChart'; import { CustomActionVegaLite } from '../vega-lite-component'; import { VEGA_LITE_DATA_INJECT_TYPE_A } from '../../../chartsUtils'; -import deepClone from 'lodash.clonedeep'; const styles = { container: { @@ -22,7 +21,7 @@ class PieChartView extends Component { // Create a new pie chart instance - const pieChart = deepClone(new PieChart()); + const pieChart = new PieChart(); // enable the orderBy in vega-lite diff --git a/src/app/js/formats/vega-lite/models/BarChart.js b/src/app/js/formats/vega-lite/models/BarChart.js index 3351096e7..139b3ffd7 100644 --- a/src/app/js/formats/vega-lite/models/BarChart.js +++ b/src/app/js/formats/vega-lite/models/BarChart.js @@ -14,9 +14,12 @@ import { } from '../../chartsUtils'; import { VEGA_ACTIONS_WIDTH } from '../component/vega-lite-component/VegaLiteComponent'; import BasicChart from './BasicChart'; +import barChartVL from './json/bar_chart.vl.json'; +import barChartLabelsVL from './json/bar_chart_labels.vl.json'; +import deepClone from 'lodash.clonedeep'; /** - * Class use for create bar chart spec + * Class used to create bar chart spec */ class BarChart extends BasicChart { /** @@ -30,8 +33,8 @@ class BarChart extends BasicChart { top: 10, bottom: 0, }; - this.model = require('./json/bar_chart.vl.json'); - this.labelsModel = require('./json/bar_chart_labels.vl.json'); + this.model = deepClone(barChartVL); + this.labelsModel = deepClone(barChartLabelsVL); this.scale = 'linear'; this.labelAngle = { x: 0, diff --git a/src/app/js/formats/vega-lite/models/BubblePlot.js b/src/app/js/formats/vega-lite/models/BubblePlot.js index 2400e9beb..05c779d0a 100644 --- a/src/app/js/formats/vega-lite/models/BubblePlot.js +++ b/src/app/js/formats/vega-lite/models/BubblePlot.js @@ -1,9 +1,11 @@ import HeatMap from './HeatMap'; +import bubblePlotVL from './json/bubble_plot.vl.json'; +import deepClone from 'lodash.clonedeep'; class BubblePlot extends HeatMap { constructor() { super(); - this.model = require('./json/bubble_plot.vl.json'); + this.model = deepClone(bubblePlotVL); } /** diff --git a/src/app/js/formats/vega-lite/models/Cartography.js b/src/app/js/formats/vega-lite/models/Cartography.js index cb31b28e8..df5100fc8 100644 --- a/src/app/js/formats/vega-lite/models/Cartography.js +++ b/src/app/js/formats/vega-lite/models/Cartography.js @@ -1,9 +1,11 @@ import BasicChart from './BasicChart'; import { MAP_EUROPE, MAP_FRANCE, MAP_WORLD } from '../../chartsUtils'; import { VEGA_ACTIONS_WIDTH } from '../component/vega-lite-component/VegaLiteComponent'; +import cartographyVL from './json/cartography.vl.json'; +import deepClone from 'lodash.clonedeep'; /** - * Class use for create cartography spec + * Class used to create cartography spec */ class Cartography extends BasicChart { /** @@ -11,7 +13,7 @@ class Cartography extends BasicChart { */ constructor() { super(); - this.model = require('./json/cartography.vl.json'); + this.model = deepClone(cartographyVL); this.tooltip.category.field = 'properties.name'; this.worldPosition = 'world'; this.autosize = { diff --git a/src/app/js/formats/vega-lite/models/HeatMap.js b/src/app/js/formats/vega-lite/models/HeatMap.js index 5a204fe30..0382b4ea3 100644 --- a/src/app/js/formats/vega-lite/models/HeatMap.js +++ b/src/app/js/formats/vega-lite/models/HeatMap.js @@ -1,8 +1,10 @@ import BasicChart from './BasicChart'; import { LABEL_ASC, LABEL_DESC } from '../../chartsUtils'; +import heatmapVL from './json/heatmap.vl.json'; +import deepClone from 'lodash.clonedeep'; /** - * Class use for create heatmap spec + * Class used to create heatmap spec */ class HeatMap extends BasicChart { /** @@ -10,7 +12,7 @@ class HeatMap extends BasicChart { */ constructor() { super(); - this.model = require('./json/heatmap.vl.json'); + this.model = deepClone(heatmapVL); this.flip = false; this.padding = { left: 10, diff --git a/src/app/js/formats/vega-lite/models/PieChart.js b/src/app/js/formats/vega-lite/models/PieChart.js index c2fc54e3d..5d4f2a888 100644 --- a/src/app/js/formats/vega-lite/models/PieChart.js +++ b/src/app/js/formats/vega-lite/models/PieChart.js @@ -1,7 +1,10 @@ import BasicChart from './BasicChart'; +import pieChartVL from './json/pie_chart.vl.json'; +import pieChartLabelsVL from './json/pie_chart_labels.vl.json'; +import deepClone from 'lodash.clonedeep'; /** - * Class use for create pie chart spec + * Class used to create pie chart spec */ class PieChart extends BasicChart { /** @@ -9,8 +12,8 @@ class PieChart extends BasicChart { */ constructor() { super(); - this.model = require('./json/pie_chart.vl.json'); - this.modelLabels = require('./json/pie_chart_labels.vl.json'); + this.model = deepClone(pieChartVL); + this.modelLabels = deepClone(pieChartLabelsVL); this.labels = false; } From c453011b0e1596ddd94bed60a119e07bf921dc90 Mon Sep 17 00:00:00 2001 From: AlasDiablo <25723276+AlasDiablo@users.noreply.github.com> Date: Fri, 15 Sep 2023 14:35:47 +0200 Subject: [PATCH 10/37] feat: add advanced mode to all vega lite chart --- .../component/bar-chart/BarChartView.js | 3 +- .../component/bubble-plot/BubblePlotAdmin.js | 133 +++++++++++++--- .../component/bubble-plot/BubblePlotView.js | 19 ++- .../component/cartography/CartographyAdmin.js | 148 ++++++++++++++---- .../component/cartography/CartographyView.js | 20 ++- .../component/heatmap/HeatMapAdmin.js | 134 +++++++++++++--- .../component/heatmap/HeatMapView.js | 19 ++- .../component/pie-chart/PieChartAdmin.js | 133 +++++++++++++--- .../component/pie-chart/PieChartView.js | 19 ++- .../formats/vega-lite/models/Cartography.js | 48 +++--- 10 files changed, 536 insertions(+), 140 deletions(-) diff --git a/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js b/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js index fd29597d5..b7118af6b 100644 --- a/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js +++ b/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js @@ -27,8 +27,7 @@ const styles = { class BarChartView extends Component { render() { - const data = this.props.data; - const { advancedMode, advancedModeSpec, field } = this.props; + const { advancedMode, advancedModeSpec, field, data } = this.props; // Create a new bar chart instance diff --git a/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotAdmin.js b/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotAdmin.js index f013800d1..15076b315 100644 --- a/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotAdmin.js +++ b/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotAdmin.js @@ -1,7 +1,15 @@ -import React, { useMemo } from 'react'; +import React, { useEffect, useMemo } from 'react'; import translate from 'redux-polyglot/translate'; import PropTypes from 'prop-types'; -import { Box, Checkbox, FormControlLabel } from '@mui/material'; +import { + Box, + Button, + Checkbox, + FormControlLabel, + FormGroup, + Switch, + TextField, +} from '@mui/material'; import { polyglot as polyglotPropTypes } from '../../../../propTypes'; import updateAdminArgs from '../../../shared/updateAdminArgs'; @@ -9,6 +17,8 @@ import RoutineParamsAdmin from '../../../shared/RoutineParamsAdmin'; import ToolTips from '../../../shared/ToolTips'; import ColorPickerParamsAdmin from '../../../shared/ColorPickerParamsAdmin'; import { MULTICHROMATIC_DEFAULT_COLORSET } from '../../../colorUtils'; +import BubblePlot from '../../models/BubblePlot'; +import { lodexOrderToIdOrder } from '../../../chartsUtils'; export const defaultArgs = { params: { @@ -35,6 +45,8 @@ const BubblePlotAdmin = props => { showOrderBy, } = props; const { + advancedMode, + advancedModeSpec, params, flipAxis, tooltip, @@ -47,6 +59,47 @@ const BubblePlotAdmin = props => { return args.colors || defaultArgs.colors; }, [args.colors]); + const spec = useMemo(() => { + if (!advancedMode) { + return null; + } + + if (advancedModeSpec !== null) { + return advancedModeSpec; + } + + const specBuilder = new BubblePlot(); + + specBuilder.setColor(colors); + specBuilder.setOrderBy(lodexOrderToIdOrder(params.orderBy)); + specBuilder.flipAxis(flipAxis); + specBuilder.setTooltip(tooltip); + specBuilder.setTooltipCategory(tooltipSource); + specBuilder.setTooltipTarget(tooltipTarget); + specBuilder.setTooltipValue(tooltipWeight); + + return JSON.stringify(specBuilder.buildSpec(), null, 2); + }, [advancedMode, advancedModeSpec]); + + useEffect(() => { + if (!advancedMode) { + return; + } + updateAdminArgs('advancedModeSpec', spec, props); + }, [advancedMode, advancedModeSpec]); + + const toggleAdvancedMode = () => { + updateAdminArgs('advancedMode', !args.advancedMode, props); + }; + + const handleAdvancedModeSpec = event => { + updateAdminArgs('advancedModeSpec', event.target.value, props); + }; + + const clearAdvancedModeSpec = () => { + updateAdminArgs('advancedModeSpec', null, props); + }; + const handleColors = colors => { updateAdminArgs('colors', colors || defaultArgs.colors, props); }; @@ -82,6 +135,17 @@ const BubblePlotAdmin = props => { justifyContent="space-between" gap={2} > + + + } + label={polyglot.t('advancedMode')} + /> + { showMinValue={showMinValue} showOrderBy={showOrderBy} /> - - } - label={polyglot.t('flip_axis')} - /> - - + {!advancedMode ? ( + <> + + } + label={polyglot.t('flip_axis')} + /> + + + + ) : ( + <> + + + + )} ); }; diff --git a/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotView.js b/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotView.js index 648b68883..c51a1f63d 100644 --- a/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotView.js +++ b/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotView.js @@ -11,6 +11,8 @@ import { VEGA_LITE_DATA_INJECT_TYPE_A, } from '../../../chartsUtils'; import BubblePlot from '../../models/BubblePlot'; +import InvalidFormat from '../../../InvalidFormat'; +import { VEGA_ACTIONS_WIDTH } from '../vega-lite-component/VegaLiteComponent'; const styles = { container: { @@ -20,7 +22,7 @@ const styles = { class BubblePlotView extends Component { render() { - const data = this.props.data; + const { advancedMode, advancedModeSpec, field, data } = this.props; // Create a new bubble plot instance @@ -36,13 +38,26 @@ class BubblePlotView extends Component { bubblePlot.setTooltipTarget(this.props.tooltipTarget); bubblePlot.setTooltipValue(this.props.tooltipWeight); + let advanceSpec; + + try { + advanceSpec = JSON.parse(advancedModeSpec); + } catch (e) { + return ; + } + // return the finish chart return (
{/* Make the chart responsive */} {({ width }) => { - const spec = bubblePlot.buildSpec(width); + const spec = advancedMode + ? { + ...advanceSpec, + width: width - VEGA_ACTIONS_WIDTH, + } + : bubblePlot.buildSpec(width); return ( { showOrderBy, } = props; const { + advancedMode, + advancedModeSpec, params, colorScheme, tooltip, @@ -43,6 +55,47 @@ const CartographyAdmin = props => { worldPosition, } = args; + const spec = useMemo(() => { + if (!advancedMode) { + return null; + } + + if (advancedModeSpec !== null) { + return advancedModeSpec; + } + + const specBuilder = new Cartography(); + + specBuilder.setTooltip(tooltip); + specBuilder.setTooltipCategory(tooltipCategory); + specBuilder.setTooltipValue(tooltipValue); + specBuilder.setWorldPosition(worldPosition); + specBuilder.setColor( + colorScheme !== undefined ? colorScheme.join(' ') : schemeOrRd[9], + ); + + return JSON.stringify(specBuilder.buildSpec(), null, 2); + }, [advancedMode, advancedModeSpec]); + + useEffect(() => { + if (!advancedMode) { + return; + } + updateAdminArgs('advancedModeSpec', spec, props); + }, [advancedMode, advancedModeSpec]); + + const toggleAdvancedMode = () => { + updateAdminArgs('advancedMode', !args.advancedMode, props); + }; + + const handleAdvancedModeSpec = event => { + updateAdminArgs('advancedModeSpec', event.target.value, props); + }; + + const clearAdvancedModeSpec = () => { + updateAdminArgs('advancedModeSpec', null, props); + }; + const handleParams = params => updateAdminArgs('params', params, props); const handleWorldPosition = e => { @@ -76,6 +129,17 @@ const CartographyAdmin = props => { justifyContent="space-between" gap={2} > + + + } + label={polyglot.t('advancedMode')} + /> + { showMinValue={showMinValue} showOrderBy={showOrderBy} /> - - - {polyglot.t('world_position_world')} - - - {polyglot.t('world_position_europe')} - - - {polyglot.t('world_position_france')} - - - - + {!advancedMode ? ( + <> + + + {polyglot.t('world_position_world')} + + + {polyglot.t('world_position_europe')} + + + {polyglot.t('world_position_france')} + + + + + + ) : ( + <> + + + + )} ); }; diff --git a/src/app/js/formats/vega-lite/component/cartography/CartographyView.js b/src/app/js/formats/vega-lite/component/cartography/CartographyView.js index 9148294ef..ddd8a6053 100644 --- a/src/app/js/formats/vega-lite/component/cartography/CartographyView.js +++ b/src/app/js/formats/vega-lite/component/cartography/CartographyView.js @@ -13,6 +13,8 @@ import { field as fieldPropTypes } from '../../../../propTypes'; import injectData from '../../../injectData'; import Cartography from '../../models/Cartography'; import { schemeOrRd } from 'd3-scale-chromatic'; +import InvalidFormat from '../../../InvalidFormat'; +import { VEGA_ACTIONS_WIDTH } from '../vega-lite-component/VegaLiteComponent'; const styles = { container: { @@ -22,7 +24,7 @@ const styles = { class CartographyView extends Component { render() { - const data = this.props.data; + const { advancedMode, advancedModeSpec, field, data } = this.props; // Create a new cartography instance @@ -40,13 +42,27 @@ class CartographyView extends Component { : schemeOrRd[9], ); + let advanceSpec; + + try { + advanceSpec = JSON.parse(advancedModeSpec); + } catch (e) { + return ; + } + // return the finish chart return (
{/* Make the chart responsive */} {({ width }) => { - const spec = cartography.buildSpec(width); + const spec = advancedMode + ? { + ...advanceSpec, + width: width - VEGA_ACTIONS_WIDTH, + height: (width - VEGA_ACTIONS_WIDTH) * 0.6, + } + : cartography.buildSpec(width); return ( { } = props; const { + advancedMode, + advancedModeSpec, params, colorScheme, flipAxis, @@ -45,6 +58,47 @@ const HeatMapAdmin = props => { tooltipWeight, } = args; + const spec = useMemo(() => { + if (!advancedMode) { + return null; + } + + if (advancedModeSpec !== null) { + return advancedModeSpec; + } + + const specBuilder = new HeatMap(); + + specBuilder.setColor(colorScheme.join(' ')); + specBuilder.setOrderBy(lodexOrderToIdOrder(params.orderBy)); + specBuilder.flipAxis(flipAxis); + specBuilder.setTooltip(tooltip); + specBuilder.setTooltipCategory(tooltipSource); + specBuilder.setTooltipTarget(tooltipTarget); + specBuilder.setTooltipValue(tooltipWeight); + + return JSON.stringify(specBuilder.buildSpec(), null, 2); + }, [advancedMode, advancedModeSpec]); + + useEffect(() => { + if (!advancedMode) { + return; + } + updateAdminArgs('advancedModeSpec', spec, props); + }, [advancedMode, advancedModeSpec]); + + const toggleAdvancedMode = () => { + updateAdminArgs('advancedMode', !args.advancedMode, props); + }; + + const handleAdvancedModeSpec = event => { + updateAdminArgs('advancedModeSpec', event.target.value, props); + }; + + const clearAdvancedModeSpec = () => { + updateAdminArgs('advancedModeSpec', null, props); + }; + const handleParams = params => { updateAdminArgs('params', params, props); }; @@ -84,6 +138,17 @@ const HeatMapAdmin = props => { justifyContent="space-between" gap={2} > + + + } + label={polyglot.t('advancedMode')} + /> + { showMinValue={showMinValue} showOrderBy={showOrderBy} /> - - - - } - label={polyglot.t('flip_axis')} - /> + {!advancedMode ? ( + <> + + + + } + label={polyglot.t('flip_axis')} + /> + + ) : ( + <> + + + + )} ); }; diff --git a/src/app/js/formats/vega-lite/component/heatmap/HeatMapView.js b/src/app/js/formats/vega-lite/component/heatmap/HeatMapView.js index 56b2d7de9..324bb47eb 100644 --- a/src/app/js/formats/vega-lite/component/heatmap/HeatMapView.js +++ b/src/app/js/formats/vega-lite/component/heatmap/HeatMapView.js @@ -11,6 +11,8 @@ import { lodexOrderToIdOrder, VEGA_LITE_DATA_INJECT_TYPE_A, } from '../../../chartsUtils'; +import InvalidFormat from '../../../InvalidFormat'; +import { VEGA_ACTIONS_WIDTH } from '../vega-lite-component/VegaLiteComponent'; const styles = { container: { @@ -20,7 +22,7 @@ const styles = { class HeatMapView extends Component { render() { - const data = this.props.data; + const { advancedMode, advancedModeSpec, field, data } = this.props; // Create a new heat map instance @@ -36,13 +38,26 @@ class HeatMapView extends Component { heatMap.setTooltipTarget(this.props.tooltipTarget); heatMap.setTooltipValue(this.props.tooltipWeight); + let advanceSpec; + + try { + advanceSpec = JSON.parse(advancedModeSpec); + } catch (e) { + return ; + } + // return the finish chart return (
{/* Make the chart responsive */} {({ width }) => { - const spec = heatMap.buildSpec(width); + const spec = advancedMode + ? { + ...advanceSpec, + width: width - VEGA_ACTIONS_WIDTH, + } + : heatMap.buildSpec(width); return ( { showOrderBy, } = props; - const { params, tooltip, tooltipCategory, tooltipValue, labels } = args; + const { + advancedMode, + advancedModeSpec, + params, + tooltip, + tooltipCategory, + tooltipValue, + labels, + } = args; + + const spec = useMemo(() => { + if (!advancedMode) { + return null; + } + + if (advancedModeSpec !== null) { + return advancedModeSpec; + } + + const specBuilder = new PieChart(); + + specBuilder.setTooltip(tooltip); + specBuilder.setTooltipCategory(tooltipCategory); + specBuilder.setTooltipValue(tooltipValue); + specBuilder.setColor(colors); + specBuilder.setLabels(labels); + + return JSON.stringify(specBuilder.buildSpec(), null, 2); + }, [advancedMode, advancedModeSpec]); + + useEffect(() => { + if (!advancedMode) { + return; + } + updateAdminArgs('advancedModeSpec', spec, props); + }, [advancedMode, advancedModeSpec]); + + const toggleAdvancedMode = () => { + updateAdminArgs('advancedMode', !args.advancedMode, props); + }; + + const handleAdvancedModeSpec = event => { + updateAdminArgs('advancedModeSpec', event.target.value, props); + }; + + const clearAdvancedModeSpec = () => { + updateAdminArgs('advancedModeSpec', null, props); + }; const colors = useMemo(() => { return args.colors || defaultArgs.colors; @@ -69,6 +126,17 @@ const PieChartAdmin = props => { justifyContent="space-between" gap={2} > + + + } + label={polyglot.t('advancedMode')} + /> + { showMinValue={showMinValue} showOrderBy={showOrderBy} /> - } - label={polyglot.t('toggle_labels')} - /> - - + {!advancedMode ? ( + <> + + } + label={polyglot.t('toggle_labels')} + /> + + + + ) : ( + <> + + + + )} ); }; diff --git a/src/app/js/formats/vega-lite/component/pie-chart/PieChartView.js b/src/app/js/formats/vega-lite/component/pie-chart/PieChartView.js index af3878ee2..0cb8bfb44 100644 --- a/src/app/js/formats/vega-lite/component/pie-chart/PieChartView.js +++ b/src/app/js/formats/vega-lite/component/pie-chart/PieChartView.js @@ -8,6 +8,8 @@ import ContainerDimensions from 'react-container-dimensions'; import PieChart from '../../models/PieChart'; import { CustomActionVegaLite } from '../vega-lite-component'; import { VEGA_LITE_DATA_INJECT_TYPE_A } from '../../../chartsUtils'; +import InvalidFormat from '../../../InvalidFormat'; +import { VEGA_ACTIONS_WIDTH } from '../vega-lite-component/VegaLiteComponent'; const styles = { container: { @@ -17,7 +19,7 @@ const styles = { class PieChartView extends Component { render() { - const data = this.props.data; + const { advancedMode, advancedModeSpec, field, data } = this.props; // Create a new pie chart instance @@ -38,13 +40,26 @@ class PieChartView extends Component { pieChart.setColor(this.props.colors); pieChart.setLabels(this.props.labels); + let advanceSpec; + + try { + advanceSpec = JSON.parse(advancedModeSpec); + } catch (e) { + return ; + } + // return the finish chart return (
{/* Make the chart responsive */} {({ width }) => { - const spec = pieChart.buildSpec(width); + const spec = advancedMode + ? { + ...advanceSpec, + width: width - VEGA_ACTIONS_WIDTH, + } + : pieChart.buildSpec(width); return ( = 850) { this.model.projection.scale = 300 - 225 * (450 / widthIn); @@ -90,14 +86,8 @@ class Cartography extends BasicChart { 545 - 260 * (450 / widthIn), ]; } - this.model.data.url = - 'https://raw.githubusercontent.com/Inist-CNRS/lodex/master/src/app/js/formats/vega-lite/models/topojson/europe.min.json'; - this.model.data.format.feature = - 'continent_Europe_subunits'; - } - break; - case MAP_FRANCE: - { + break; + case MAP_FRANCE: if (widthIn >= 850) { this.model.projection.scale = 1800 - 100 * (450 / widthIn); @@ -120,16 +110,26 @@ class Cartography extends BasicChart { 1275 - 510 * (450 / widthIn), ]; } - this.model.data.url = - 'https://raw.githubusercontent.com/Inist-CNRS/lodex/master/src/app/js/formats/vega-lite/models/topojson/fr-departments.min.json'; - this.model.data.format.feature = 'FRA_adm2'; + break; + } + } - this.model.transform.forEach(e => { - if (e.lookup === 'id') { - e.lookup = 'properties.HASC_2'; - } - }); - } + switch (this.worldPosition) { + case MAP_EUROPE: + this.model.data.url = + 'https://raw.githubusercontent.com/Inist-CNRS/lodex/master/src/app/js/formats/vega-lite/models/topojson/europe.min.json'; + this.model.data.format.feature = 'continent_Europe_subunits'; + break; + case MAP_FRANCE: + this.model.data.url = + 'https://raw.githubusercontent.com/Inist-CNRS/lodex/master/src/app/js/formats/vega-lite/models/topojson/fr-departments.min.json'; + this.model.data.format.feature = 'FRA_adm2'; + + this.model.transform.forEach(e => { + if (e.lookup === 'id') { + e.lookup = 'properties.HASC_2'; + } + }); break; } From 65c0104f84e85399e5bb023acc72e41ad737b987 Mon Sep 17 00:00:00 2001 From: AlasDiablo <25723276+AlasDiablo@users.noreply.github.com> Date: Mon, 18 Sep 2023 09:04:04 +0200 Subject: [PATCH 11/37] refactor: generify advance mode --- src/app/custom/translations.tsv | 2 + src/app/js/formats/shared/VegaAdvancedMode.js | 84 +++++++++++++++++++ .../component/bar-chart/BarChartAdmin.js | 22 ++--- .../component/bubble-plot/BubblePlotAdmin.js | 23 ++--- .../component/cartography/CartographyAdmin.js | 23 ++--- .../component/heatmap/HeatMapAdmin.js | 24 ++---- .../component/pie-chart/PieChartAdmin.js | 24 ++---- 7 files changed, 126 insertions(+), 76 deletions(-) create mode 100644 src/app/js/formats/shared/VegaAdvancedMode.js diff --git a/src/app/custom/translations.tsv b/src/app/custom/translations.tsv index 8a1f0fda1..3cc714160 100644 --- a/src/app/custom/translations.tsv +++ b/src/app/custom/translations.tsv @@ -956,3 +956,5 @@ "r-sub-resources-co-occurrences_description" "Identifies sub-resources that co-occur with a given sub-resource and calculates the number of these co-occurrences." "Identifie les sous-ressources co-occurrentes avec une sous-ressource donnée et calcule le nombre de ces co-occurrences." "r-close-by_title" "close-by" "close-by" "r-close-by_description" "Is used to create the graph aster plot." "Est utilisée pour créer le graphique aster plot." +regenerate_vega_lite_spec Regenerate Vega Lite specifications Régénérer la spécifications Vega Lite +regenerate_vega_spec Regenerate Vega specifications Régénérer la spécifications Vega diff --git a/src/app/js/formats/shared/VegaAdvancedMode.js b/src/app/js/formats/shared/VegaAdvancedMode.js new file mode 100644 index 000000000..03eb234f9 --- /dev/null +++ b/src/app/js/formats/shared/VegaAdvancedMode.js @@ -0,0 +1,84 @@ +import React, { useEffect, useMemo, useState } from 'react'; +import translate from 'redux-polyglot/translate'; +import PropTypes from 'prop-types'; +import { Button, TextField, Typography } from '@mui/material'; +import ReportProblemIcon from '@mui/icons-material/ReportProblem'; +import CachedIcon from '@mui/icons-material/Cached'; +import isEqual from 'lodash.isequal'; + +import { polyglot as polyglotPropTypes } from '../../propTypes'; + +const VegaAdvancedMode = ({ p, value, onChange, onClear }) => { + const [currentValue, setCurrentValue] = useState(value || '{}'); + const [error, setError] = useState(null); + + const valueObject = useMemo(() => { + try { + return JSON.parse(value); + } catch (e) { + return null; + } + }, [value]); + + const currentValueObject = useMemo(() => { + try { + const json = JSON.parse(currentValue); + setError(null); + return json; + } catch (e) { + setError(e); + return null; + } + }, [currentValue]); + + useEffect(() => { + if (valueObject === null || currentValueObject === null) return; + if (!isEqual(currentValueObject, valueObject)) { + onChange(currentValue); + } + }, [currentValueObject, valueObject]); + + const handleChange = event => { + setCurrentValue(event.target.value); + }; + + return ( + <> + + {error ? ( + + + {error.message} + + ) : null} + + + ); +}; + +VegaAdvancedMode.propTypes = { + p: polyglotPropTypes.isRequired, + value: PropTypes.string.isRequired, + onChange: PropTypes.func.isRequired, + onClear: PropTypes.func.isRequired, +}; + +export default translate(VegaAdvancedMode); diff --git a/src/app/js/formats/vega-lite/component/bar-chart/BarChartAdmin.js b/src/app/js/formats/vega-lite/component/bar-chart/BarChartAdmin.js index 1ef451986..46415af49 100644 --- a/src/app/js/formats/vega-lite/component/bar-chart/BarChartAdmin.js +++ b/src/app/js/formats/vega-lite/component/bar-chart/BarChartAdmin.js @@ -8,7 +8,6 @@ import { Box, Switch, FormGroup, - Button, } from '@mui/material'; import translate from 'redux-polyglot/translate'; @@ -26,6 +25,7 @@ import { lodexOrderToIdOrder, lodexScaleToIdScale, } from '../../../chartsUtils'; +import VegaAdvancedMode from '../../../shared/VegaAdvancedMode'; export const defaultArgs = { params: { @@ -120,8 +120,8 @@ const BarChartAdmin = props => { updateAdminArgs('advancedMode', !args.advancedMode, props); }; - const handleAdvancedModeSpec = event => { - updateAdminArgs('advancedModeSpec', event.target.value, props); + const handleAdvancedModeSpec = newSpec => { + updateAdminArgs('advancedModeSpec', newSpec, props); }; const clearAdvancedModeSpec = () => { @@ -306,17 +306,11 @@ const BarChartAdmin = props => { /> ) : ( - <> - - - + )} ); diff --git a/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotAdmin.js b/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotAdmin.js index 15076b315..72f3e5fed 100644 --- a/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotAdmin.js +++ b/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotAdmin.js @@ -3,12 +3,10 @@ import translate from 'redux-polyglot/translate'; import PropTypes from 'prop-types'; import { Box, - Button, Checkbox, FormControlLabel, FormGroup, Switch, - TextField, } from '@mui/material'; import { polyglot as polyglotPropTypes } from '../../../../propTypes'; @@ -19,6 +17,7 @@ import ColorPickerParamsAdmin from '../../../shared/ColorPickerParamsAdmin'; import { MULTICHROMATIC_DEFAULT_COLORSET } from '../../../colorUtils'; import BubblePlot from '../../models/BubblePlot'; import { lodexOrderToIdOrder } from '../../../chartsUtils'; +import VegaAdvancedMode from '../../../shared/VegaAdvancedMode'; export const defaultArgs = { params: { @@ -92,8 +91,8 @@ const BubblePlotAdmin = props => { updateAdminArgs('advancedMode', !args.advancedMode, props); }; - const handleAdvancedModeSpec = event => { - updateAdminArgs('advancedModeSpec', event.target.value, props); + const handleAdvancedModeSpec = newSpec => { + updateAdminArgs('advancedModeSpec', newSpec, props); }; const clearAdvancedModeSpec = () => { @@ -185,17 +184,11 @@ const BubblePlotAdmin = props => { /> ) : ( - <> - - - + )} ); diff --git a/src/app/js/formats/vega-lite/component/cartography/CartographyAdmin.js b/src/app/js/formats/vega-lite/component/cartography/CartographyAdmin.js index 0e0ab38a8..266c69840 100644 --- a/src/app/js/formats/vega-lite/component/cartography/CartographyAdmin.js +++ b/src/app/js/formats/vega-lite/component/cartography/CartographyAdmin.js @@ -4,7 +4,6 @@ import translate from 'redux-polyglot/translate'; import { schemeOrRd } from 'd3-scale-chromatic'; import { Box, - Button, FormControlLabel, FormGroup, MenuItem, @@ -18,8 +17,8 @@ import updateAdminArgs from '../../../shared/updateAdminArgs'; import RoutineParamsAdmin from '../../../shared/RoutineParamsAdmin'; import ToolTips from '../../../shared/ToolTips'; import { MAP_EUROPE, MAP_FRANCE, MAP_WORLD } from '../../../chartsUtils'; -import BubblePlot from '../../models/BubblePlot'; import Cartography from '../../models/Cartography'; +import VegaAdvancedMode from '../../../shared/VegaAdvancedMode'; export const defaultArgs = { params: { @@ -88,8 +87,8 @@ const CartographyAdmin = props => { updateAdminArgs('advancedMode', !args.advancedMode, props); }; - const handleAdvancedModeSpec = event => { - updateAdminArgs('advancedModeSpec', event.target.value, props); + const handleAdvancedModeSpec = newSpec => { + updateAdminArgs('advancedModeSpec', newSpec, props); }; const clearAdvancedModeSpec = () => { @@ -185,17 +184,11 @@ const CartographyAdmin = props => { /> ) : ( - <> - - - + )} ); diff --git a/src/app/js/formats/vega-lite/component/heatmap/HeatMapAdmin.js b/src/app/js/formats/vega-lite/component/heatmap/HeatMapAdmin.js index d2649d53b..03cf97d9a 100644 --- a/src/app/js/formats/vega-lite/component/heatmap/HeatMapAdmin.js +++ b/src/app/js/formats/vega-lite/component/heatmap/HeatMapAdmin.js @@ -6,8 +6,6 @@ import { Checkbox, FormControlLabel, Box, - Button, - TextField, Switch, FormGroup, } from '@mui/material'; @@ -17,9 +15,9 @@ import updateAdminArgs from '../../../shared/updateAdminArgs'; import RoutineParamsAdmin from '../../../shared/RoutineParamsAdmin'; import { GradientSchemeSelector } from '../../../../lib/components/ColorSchemeSelector'; import ToolTips from '../../../shared/ToolTips'; -import BubblePlot from '../../models/BubblePlot'; import HeatMap from '../../models/HeatMap'; import { lodexOrderToIdOrder } from '../../../chartsUtils'; +import VegaAdvancedMode from '../../../shared/VegaAdvancedMode'; export const defaultArgs = { params: { @@ -91,8 +89,8 @@ const HeatMapAdmin = props => { updateAdminArgs('advancedMode', !args.advancedMode, props); }; - const handleAdvancedModeSpec = event => { - updateAdminArgs('advancedModeSpec', event.target.value, props); + const handleAdvancedModeSpec = newSpec => { + updateAdminArgs('advancedModeSpec', newSpec, props); }; const clearAdvancedModeSpec = () => { @@ -188,17 +186,11 @@ const HeatMapAdmin = props => { /> ) : ( - <> - - - + )} ); diff --git a/src/app/js/formats/vega-lite/component/pie-chart/PieChartAdmin.js b/src/app/js/formats/vega-lite/component/pie-chart/PieChartAdmin.js index 13e2721a8..e5b3cb9e6 100644 --- a/src/app/js/formats/vega-lite/component/pie-chart/PieChartAdmin.js +++ b/src/app/js/formats/vega-lite/component/pie-chart/PieChartAdmin.js @@ -3,12 +3,10 @@ import PropTypes from 'prop-types'; import translate from 'redux-polyglot/translate'; import { Box, - Button, Checkbox, FormControlLabel, FormGroup, Switch, - TextField, } from '@mui/material'; import { polyglot as polyglotPropTypes } from '../../../../propTypes'; @@ -17,8 +15,8 @@ import RoutineParamsAdmin from '../../../shared/RoutineParamsAdmin'; import ColorPickerParamsAdmin from '../../../shared/ColorPickerParamsAdmin'; import { MULTICHROMATIC_DEFAULT_COLORSET } from '../../../colorUtils'; import ToolTips from '../../../shared/ToolTips'; -import BubblePlot from '../../models/BubblePlot'; import PieChart from '../../models/PieChart'; +import VegaAdvancedMode from '../../../shared/VegaAdvancedMode'; export const defaultArgs = { params: { @@ -85,8 +83,8 @@ const PieChartAdmin = props => { updateAdminArgs('advancedMode', !args.advancedMode, props); }; - const handleAdvancedModeSpec = event => { - updateAdminArgs('advancedModeSpec', event.target.value, props); + const handleAdvancedModeSpec = newSpec => { + updateAdminArgs('advancedModeSpec', newSpec, props); }; const clearAdvancedModeSpec = () => { @@ -174,17 +172,11 @@ const PieChartAdmin = props => { /> ) : ( - <> - - - + )} ); From 994124ec5f95061cf20e3f72037739537b398045 Mon Sep 17 00:00:00 2001 From: AlasDiablo <25723276+AlasDiablo@users.noreply.github.com> Date: Mon, 18 Sep 2023 09:42:18 +0200 Subject: [PATCH 12/37] refactor: update vega model to handle advance mode --- src/app/js/formats/vega/models/BasicChartVG.js | 16 ++++++++++++++++ src/app/js/formats/vega/models/FlowMap.js | 16 +++++++++++----- src/app/js/formats/vega/models/RadarChart.js | 14 ++++++++++---- 3 files changed, 37 insertions(+), 9 deletions(-) create mode 100644 src/app/js/formats/vega/models/BasicChartVG.js diff --git a/src/app/js/formats/vega/models/BasicChartVG.js b/src/app/js/formats/vega/models/BasicChartVG.js new file mode 100644 index 000000000..3b80fc535 --- /dev/null +++ b/src/app/js/formats/vega/models/BasicChartVG.js @@ -0,0 +1,16 @@ +class BasicChartVG { + constructor() { + this.editMode = false; + } + + setEditMode(bool) { + this.editMode = bool; + } + + // eslint-disable-next-line no-unused-vars + buildSpec(widthIn) { + throw new Error("The builder can't be use at the state"); + } +} + +export default BasicChartVG; diff --git a/src/app/js/formats/vega/models/FlowMap.js b/src/app/js/formats/vega/models/FlowMap.js index 68d7bd080..5558e4603 100644 --- a/src/app/js/formats/vega/models/FlowMap.js +++ b/src/app/js/formats/vega/models/FlowMap.js @@ -1,15 +1,19 @@ import { schemeBlues } from 'd3-scale-chromatic'; import { VEGA_ACTIONS_WIDTH } from '../../vega-lite/component/vega-lite-component/VegaLiteComponent'; +import flowMapVG from './json/flow_map.vg.json'; +import deepClone from 'lodash.clonedeep'; +import BasicChartVG from './BasicChartVG'; /** * Class use for create radar chart spec */ -class FlowMap { +class FlowMap extends BasicChartVG { /** * Init all required parameters */ constructor() { - this.model = require('./json/flow_map.vg.json'); + super(); + this.model = deepClone(flowMapVG); this.color = '#000000'; this.colors = schemeBlues[9]; this.tooltip = { @@ -64,11 +68,13 @@ class FlowMap { * @param widthIn */ buildSpec(widthIn) { - this.model.width = widthIn - VEGA_ACTIONS_WIDTH; - this.model.height = widthIn * 0.6; + if (!this.editMode) { + this.model.width = widthIn - VEGA_ACTIONS_WIDTH; + this.model.height = widthIn * 0.6; + } this.model.marks.forEach(e => { - if (e.type === 'text') { + if (e.type === 'text' && !this.editMode) { e.encode.encode.x.value = this.model.width - 5; } if (e.name === 'route') { diff --git a/src/app/js/formats/vega/models/RadarChart.js b/src/app/js/formats/vega/models/RadarChart.js index f412631ee..ccb3ea553 100644 --- a/src/app/js/formats/vega/models/RadarChart.js +++ b/src/app/js/formats/vega/models/RadarChart.js @@ -1,15 +1,19 @@ import { MONOCHROMATIC_DEFAULT_COLORSET } from '../../colorUtils'; import { SCALE_LINEAR } from '../../chartsUtils'; +import radarChartVG from './json/radar_chart.vg.json'; +import deepClone from 'lodash.clonedeep'; +import BasicChartVG from './BasicChartVG'; /** * Class use for create radar chart spec */ -class RadarChart { +class RadarChart extends BasicChartVG { /** * Init all required parameters */ constructor() { - this.model = require('./json/radar_chart.vg.json'); + super(); + this.model = deepClone(radarChartVG); this.colors = MONOCHROMATIC_DEFAULT_COLORSET.split(' '); this.tooltip = { toggle: false, @@ -90,8 +94,10 @@ class RadarChart { } }); - this.model.width = widthIn - widthIn * 0.06; - this.model.height = widthIn - widthIn * 0.24; + if (!this.editMode) { + this.model.width = widthIn - widthIn * 0.06; + this.model.height = widthIn - widthIn * 0.24; + } this.model.padding = { left: 120, From fcd97211574feecb85500296707906b6f3e6e14b Mon Sep 17 00:00:00 2001 From: AlasDiablo <25723276+AlasDiablo@users.noreply.github.com> Date: Mon, 18 Sep 2023 09:54:11 +0200 Subject: [PATCH 13/37] feat: add advanced mode to all vega chart --- .../vega/component/flow-map/FlowMapAdmin.js | 285 ++++++++++------ .../vega/component/flow-map/FlowMapView.js | 30 +- .../component/radar-chart/RadarChartAdmin.js | 323 +++++++++++------- .../component/radar-chart/RadarChartView.js | 29 +- 4 files changed, 417 insertions(+), 250 deletions(-) diff --git a/src/app/js/formats/vega/component/flow-map/FlowMapAdmin.js b/src/app/js/formats/vega/component/flow-map/FlowMapAdmin.js index 53ce9ce09..531003703 100644 --- a/src/app/js/formats/vega/component/flow-map/FlowMapAdmin.js +++ b/src/app/js/formats/vega/component/flow-map/FlowMapAdmin.js @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React, { useEffect, useMemo } from 'react'; import PropTypes from 'prop-types'; import translate from 'redux-polyglot/translate'; import { polyglot as polyglotPropTypes } from '../../../../propTypes'; @@ -8,13 +8,17 @@ import ToolTips from '../../../shared/ToolTips'; import ColorPickerParamsAdmin from '../../../shared/ColorPickerParamsAdmin'; import { schemeBlues } from 'd3-scale-chromatic'; import { GradientSchemeSelector } from '../../../../lib/components/ColorSchemeSelector'; -import { Box } from '@mui/material'; +import { Box, FormControlLabel, FormGroup, Switch } from '@mui/material'; +import FlowMap from '../../models/FlowMap'; +import VegaAdvancedMode from '../../../shared/VegaAdvancedMode'; export const defaultArgs = { params: { maxSize: undefined, orderBy: 'value/asc', }, + advancedMode: false, + advancedModeSpec: null, tooltip: false, tooltipCategory: 'Category', tooltipValue: 'Value', @@ -22,135 +26,194 @@ export const defaultArgs = { colorScheme: schemeBlues[9], }; -class FlowMapAdmin extends Component { - static propTypes = { - args: PropTypes.shape({ - params: PropTypes.shape({ - maxSize: PropTypes.number, - maxValue: PropTypes.number, - minValue: PropTypes.number, - orderBy: PropTypes.string, - }), - tooltip: PropTypes.bool, - tooltipCategory: PropTypes.string, - tooltipValue: PropTypes.string, - color: PropTypes.string, - colorScheme: PropTypes.arrayOf(PropTypes.string), - }), - onChange: PropTypes.func.isRequired, - p: polyglotPropTypes.isRequired, - showMaxSize: PropTypes.bool.isRequired, - showMaxValue: PropTypes.bool.isRequired, - showMinValue: PropTypes.bool.isRequired, - showOrderBy: PropTypes.bool.isRequired, +const FlowMapAdmin = props => { + const { + p: polyglot, + showMaxSize, + showMaxValue, + showMinValue, + showOrderBy, + args, + } = props; + const { + advancedMode, + advancedModeSpec, + params, + tooltip, + tooltipValue, + tooltipCategory, + colorScheme, + } = args; + + const color = useMemo(() => { + return args.color || defaultArgs.color; + }, [args.color]); + + const spec = useMemo(() => { + if (!advancedMode) { + return null; + } + + if (advancedModeSpec !== null) { + return advancedModeSpec; + } + + const specBuilder = new FlowMap(); + + specBuilder.setTooltip(this.props.tooltip); + specBuilder.setTooltipCategory(this.props.tooltipCategory); + specBuilder.setTooltipValue(this.props.tooltipValue); + specBuilder.setColor(this.props.color.split(' ')[0]); + specBuilder.setColorScheme( + colorScheme !== undefined ? colorScheme : schemeBlues[9].split(' '), + ); + specBuilder.setEditMode(true); + return JSON.stringify(specBuilder.buildSpec(), null, 2); + }, [advancedMode, advancedModeSpec]); + + useEffect(() => { + if (!advancedMode) { + return; + } + updateAdminArgs('advancedModeSpec', spec, props); + }, [advancedMode, advancedModeSpec]); + + const toggleAdvancedMode = () => { + updateAdminArgs('advancedMode', !args.advancedMode, props); + }; + + const handleAdvancedModeSpec = newSpec => { + updateAdminArgs('advancedModeSpec', newSpec, props); }; - static defaultProps = { - args: defaultArgs, - showMaxSize: true, - showMaxValue: true, - showMinValue: true, - showOrderBy: true, + const clearAdvancedModeSpec = () => { + updateAdminArgs('advancedModeSpec', null, props); }; - constructor(props) { - super(props); - this.setColor = this.setColor.bind(this); - this.setTooltipValue = this.setTooltipValue.bind(this); - this.setTooltipCategory = this.setTooltipCategory.bind(this); - this.state = { - color: this.props.args.color || defaultArgs.color, - }; - } - - setParams = params => { - updateAdminArgs('params', params, this.props); + const handleParams = params => { + updateAdminArgs('params', params, props); }; - setColor(color) { + const handleColor = color => { updateAdminArgs( 'color', color.split(' ')[0] || defaultArgs.color, - this.props, + props, ); - } + }; - setColorScheme = (_, colorScheme) => { + const handleColorScheme = (_, colorScheme) => { updateAdminArgs( 'colorScheme', colorScheme.props.value.split(','), - this.props, + props, ); }; - toggleTooltip = () => { - updateAdminArgs('tooltip', !this.props.args.tooltip, this.props); + const toggleTooltip = () => { + updateAdminArgs('tooltip', !tooltip, props); }; - setTooltipCategory(tooltipCategory) { - updateAdminArgs('tooltipCategory', tooltipCategory, this.props); - } - - setTooltipValue(tooltipValue) { - updateAdminArgs('tooltipValue', tooltipValue, this.props); - } - - render() { - const { - p: polyglot, - showMaxSize, - showMaxValue, - showMinValue, - showOrderBy, - } = this.props; - const { - params, - tooltip, - tooltipValue, - tooltipCategory, - colorScheme, - } = this.props.args; - - return ( - - - - { + updateAdminArgs('tooltipCategory', tooltipCategory, props); + }; + + const handleTooltipValue = tooltipValue => { + updateAdminArgs('tooltipValue', tooltipValue, props); + }; + + return ( + + + + } + label={polyglot.t('advancedMode')} /> - + + {advancedMode ? ( + - - ); - } -} + ) : ( + <> + + + + + )} + + ); +}; + +FlowMapAdmin.propTypes = { + args: PropTypes.shape({ + params: PropTypes.shape({ + maxSize: PropTypes.number, + maxValue: PropTypes.number, + minValue: PropTypes.number, + orderBy: PropTypes.string, + }), + advancedMode: PropTypes.bool, + advancedModeSpec: PropTypes.string, + tooltip: PropTypes.bool, + tooltipCategory: PropTypes.string, + tooltipValue: PropTypes.string, + color: PropTypes.string, + colorScheme: PropTypes.arrayOf(PropTypes.string), + }), + onChange: PropTypes.func.isRequired, + p: polyglotPropTypes.isRequired, + showMaxSize: PropTypes.bool.isRequired, + showMaxValue: PropTypes.bool.isRequired, + showMinValue: PropTypes.bool.isRequired, + showOrderBy: PropTypes.bool.isRequired, +}; + +FlowMapAdmin.defaultProps = { + args: defaultArgs, + showMaxSize: true, + showMaxValue: true, + showMinValue: true, + showOrderBy: true, +}; export default translate(FlowMapAdmin); diff --git a/src/app/js/formats/vega/component/flow-map/FlowMapView.js b/src/app/js/formats/vega/component/flow-map/FlowMapView.js index be7d7d57b..b0b0b51fb 100644 --- a/src/app/js/formats/vega/component/flow-map/FlowMapView.js +++ b/src/app/js/formats/vega/component/flow-map/FlowMapView.js @@ -2,15 +2,19 @@ import React, { Component } from 'react'; import injectData from '../../../injectData'; import { connect } from 'react-redux'; import compose from 'recompose/compose'; -import { field as fieldPropTypes, polyglot as polyglotPropTypes } from '../../../../propTypes'; +import { + field as fieldPropTypes, + polyglot as polyglotPropTypes, +} from '../../../../propTypes'; import PropTypes from 'prop-types'; import ContainerDimensions from 'react-container-dimensions'; import { CustomActionVega } from '../vega-component'; -import deepClone from 'lodash.clonedeep'; import FlowMap from '../../models/FlowMap'; import { VEGA_DATA_INJECT_TYPE_B } from '../../../chartsUtils'; import { schemeBlues } from 'd3-scale-chromatic'; import MouseIcon from '../../../shared/MouseIcon'; +import InvalidFormat from '../../../InvalidFormat'; +import { VEGA_ACTIONS_WIDTH } from '../../../vega-lite/component/vega-lite-component/VegaLiteComponent'; const styles = { container: { @@ -21,11 +25,11 @@ const styles = { class FlowMapView extends Component { render() { - const data = this.props.data; + const { advancedMode, advancedModeSpec, field, data } = this.props; // Create a new flow map instance - const flowMap = deepClone(new FlowMap()); + const flowMap = new FlowMap(); // Set all flow map parameter the chosen by the administrator @@ -39,13 +43,27 @@ class FlowMapView extends Component { : schemeBlues[9].split(' '), ); + let advanceSpec; + + try { + advanceSpec = JSON.parse(advancedModeSpec); + } catch (e) { + return ; + } + // return the finish chart return (
{/* Make the chart responsive */} {({ width }) => { - const spec = flowMap.buildSpec(width); + const spec = advancedMode + ? { + ...advanceSpec, + width: width - VEGA_ACTIONS_WIDTH, + height: width * 0.6, + } + : flowMap.buildSpec(width, data.values.length); return ( { + const { + p: polyglot, + showMaxSize, + showMaxValue, + showMinValue, + showOrderBy, + args, + } = props; + + const { + advancedMode, + advancedModeSpec, + params, + axisRoundValue, + scale, + tooltip, + tooltipValue, + tooltipCategory, + } = args; + + const colors = useMemo(() => { + return args.colors || defaultArgs.colors; + }, [args.colors]); + + const spec = useMemo(() => { + if (!advancedMode) { + return null; + } + + if (advancedModeSpec !== null) { + return advancedModeSpec; + } + + const specBuilder = new RadarChart(); + + specBuilder.setColors(colors.split(' ')); + specBuilder.setTooltip(tooltip); + specBuilder.setTooltipCategory(tooltipCategory); + specBuilder.setTooltipValue(tooltipValue); + specBuilder.setScale(lodexScaleToIdScale(scale)); + + specBuilder.setEditMode(true); + return JSON.stringify(specBuilder.buildSpec(), null, 2); + }, [advancedMode, advancedModeSpec]); + + useEffect(() => { + if (!advancedMode) { + return; + } + updateAdminArgs('advancedModeSpec', spec, props); + }, [advancedMode, advancedModeSpec]); + + const toggleAdvancedMode = () => { + updateAdminArgs('advancedMode', !args.advancedMode, props); }; - static defaultProps = { - args: defaultArgs, - showMaxSize: true, - showMaxValue: true, - showMinValue: true, - showOrderBy: true, + const handleAdvancedModeSpec = newSpec => { + updateAdminArgs('advancedModeSpec', newSpec, props); }; - constructor(props) { - super(props); - this.setColors = this.setColors.bind(this); - this.setTooltipValue = this.setTooltipValue.bind(this); - this.setTooltipCategory = this.setTooltipCategory.bind(this); - this.state = { - colors: this.props.args.colors || defaultArgs.colors, - }; - } - - setParams = params => { - updateAdminArgs('params', params, this.props); + const clearAdvancedModeSpec = () => { + updateAdminArgs('advancedModeSpec', null, props); }; - setAxisRoundValue = () => { - updateAdminArgs( - 'axisRoundValue', - !this.props.args.axisRoundValue, - this.props, - ); + const handleParams = params => { + updateAdminArgs('params', params, props); }; - setScale = e => { - updateAdminArgs('scale', e.target.value, this.props); + const handleAxisRoundValue = () => { + updateAdminArgs('axisRoundValue', !axisRoundValue, props); }; - setColors(colors) { + const handleScale = e => { + updateAdminArgs('scale', e.target.value, props); + }; + + const handleColors = colors => { updateAdminArgs( 'colors', colors.split(' ')[0] || defaultArgs.colors, - this.props, + props, ); - } + }; - toggleTooltip = () => { - updateAdminArgs('tooltip', !this.props.args.tooltip, this.props); + const toggleTooltip = () => { + updateAdminArgs('tooltip', !tooltip, props); }; - setTooltipCategory(tooltipCategory) { - updateAdminArgs('tooltipCategory', tooltipCategory, this.props); - } - - setTooltipValue(tooltipValue) { - updateAdminArgs('tooltipValue', tooltipValue, this.props); - } - - render() { - const { - p: polyglot, - showMaxSize, - showMaxValue, - showMinValue, - showOrderBy, - } = this.props; - - const { - params, - axisRoundValue, - scale, - tooltip, - tooltipValue, - tooltipCategory, - } = this.props.args; - - return ( - - - - + const handleTooltipCategory = tooltipCategory => { + updateAdminArgs('tooltipCategory', tooltipCategory, props); + }; + + const handleTooltipValue = tooltipValue => { + updateAdminArgs('tooltipValue', tooltipValue, props); + }; + + return ( + + } - label={polyglot.t('axis_round_value')} + label={polyglot.t('advancedMode')} /> - - {polyglot.t('linear')} - {polyglot.t('log')} - - - ); - } -} + + + {advancedMode ? ( + + ) : ( + <> + + + + } + label={polyglot.t('axis_round_value')} + /> + + + {polyglot.t('linear')} + + {polyglot.t('log')} + + + )} + + ); +}; + +RadarChartAdmin.propTypes = { + args: PropTypes.shape({ + params: PropTypes.shape({ + maxSize: PropTypes.number, + maxValue: PropTypes.number, + minValue: PropTypes.number, + orderBy: PropTypes.string, + }), + advancedMode: PropTypes.bool, + advancedModeSpec: PropTypes.string, + colors: PropTypes.string, + axisRoundValue: PropTypes.bool, + scale: PropTypes.oneOf(['log', 'linear']), + tooltip: PropTypes.bool, + tooltipCategory: PropTypes.string, + tooltipValue: PropTypes.string, + }), + onChange: PropTypes.func.isRequired, + p: polyglotPropTypes.isRequired, + showMaxSize: PropTypes.bool.isRequired, + showMaxValue: PropTypes.bool.isRequired, + showMinValue: PropTypes.bool.isRequired, + showOrderBy: PropTypes.bool.isRequired, +}; + +RadarChartAdmin.defaultProps = { + args: defaultArgs, + showMaxSize: true, + showMaxValue: true, + showMinValue: true, + showOrderBy: true, +}; export default translate(RadarChartAdmin); diff --git a/src/app/js/formats/vega/component/radar-chart/RadarChartView.js b/src/app/js/formats/vega/component/radar-chart/RadarChartView.js index ad595e1d2..b394da43e 100644 --- a/src/app/js/formats/vega/component/radar-chart/RadarChartView.js +++ b/src/app/js/formats/vega/component/radar-chart/RadarChartView.js @@ -4,11 +4,16 @@ import { connect } from 'react-redux'; import compose from 'recompose/compose'; import { field as fieldPropTypes } from '../../../../propTypes'; import PropTypes from 'prop-types'; +import deepClone from 'lodash.clonedeep'; import ContainerDimensions from 'react-container-dimensions'; import { CustomActionVega } from '../vega-component'; import RadarChart from '../../models/RadarChart'; -import { lodexScaleToIdScale, VEGA_DATA_INJECT_TYPE_A } from '../../../chartsUtils'; -import deepClone from 'lodash.clonedeep'; +import { + lodexScaleToIdScale, + VEGA_DATA_INJECT_TYPE_A, +} from '../../../chartsUtils'; + +import InvalidFormat from '../../../InvalidFormat'; const styles = { container: { @@ -19,7 +24,7 @@ const styles = { class RadarChartView extends Component { render() { - const data = this.props.data; + const { advancedMode, advancedModeSpec, field, data } = this.props; // format the data for the vega template @@ -41,13 +46,27 @@ class RadarChartView extends Component { radarChart.setTooltipValue(this.props.tooltipValue); radarChart.setScale(lodexScaleToIdScale(this.props.scale)); + let advanceSpec; + + try { + advanceSpec = JSON.parse(advancedModeSpec); + } catch (e) { + return ; + } + // return the finish chart return (
{/* Make the chart responsive */} {({ width }) => { - const spec = radarChart.buildSpec(width); + const spec = advancedMode + ? { + ...advanceSpec, + width: width - width * 0.06, + height: width - width * 0.24, + } + : radarChart.buildSpec(width, data.values.length); return ( Date: Mon, 18 Sep 2023 15:34:48 +0200 Subject: [PATCH 14/37] Update src/app/custom/translations.tsv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: François Parmentier --- src/app/custom/translations.tsv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/custom/translations.tsv b/src/app/custom/translations.tsv index 3cc714160..0da3fadfb 100644 --- a/src/app/custom/translations.tsv +++ b/src/app/custom/translations.tsv @@ -956,5 +956,5 @@ "r-sub-resources-co-occurrences_description" "Identifies sub-resources that co-occur with a given sub-resource and calculates the number of these co-occurrences." "Identifie les sous-ressources co-occurrentes avec une sous-ressource donnée et calcule le nombre de ces co-occurrences." "r-close-by_title" "close-by" "close-by" "r-close-by_description" "Is used to create the graph aster plot." "Est utilisée pour créer le graphique aster plot." -regenerate_vega_lite_spec Regenerate Vega Lite specifications Régénérer la spécifications Vega Lite +regenerate_vega_lite_spec Regenerate Vega Lite specifications Régénérer la spécification Vega Lite regenerate_vega_spec Regenerate Vega specifications Régénérer la spécifications Vega From 5f2e279a786837f0fefe2c2f603f304fa740ca5a Mon Sep 17 00:00:00 2001 From: AlasDiablo <25723276+AlasDiablo@users.noreply.github.com> Date: Mon, 18 Sep 2023 15:34:57 +0200 Subject: [PATCH 15/37] Update src/app/custom/translations.tsv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: François Parmentier --- src/app/custom/translations.tsv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/custom/translations.tsv b/src/app/custom/translations.tsv index 0da3fadfb..f6514c47b 100644 --- a/src/app/custom/translations.tsv +++ b/src/app/custom/translations.tsv @@ -957,4 +957,4 @@ "r-close-by_title" "close-by" "close-by" "r-close-by_description" "Is used to create the graph aster plot." "Est utilisée pour créer le graphique aster plot." regenerate_vega_lite_spec Regenerate Vega Lite specifications Régénérer la spécification Vega Lite -regenerate_vega_spec Regenerate Vega specifications Régénérer la spécifications Vega +regenerate_vega_spec Regenerate Vega specifications Régénérer la spécification Vega From 0b6fc885a9c6017689cce2d2be6c7d12635f053c Mon Sep 17 00:00:00 2001 From: AlasDiablo <25723276+AlasDiablo@users.noreply.github.com> Date: Wed, 20 Sep 2023 07:29:58 +0200 Subject: [PATCH 16/37] refactor: rename variable and add comment --- .../component/bar-chart/BarChartAdmin.js | 30 +++++++++---------- .../component/bar-chart/BarChartView.js | 6 ++-- .../component/bubble-plot/BubblePlotAdmin.js | 18 ++++++----- .../component/bubble-plot/BubblePlotView.js | 6 ++-- .../component/cartography/CartographyAdmin.js | 18 ++++++----- .../component/cartography/CartographyView.js | 6 ++-- .../component/heatmap/HeatMapAdmin.js | 18 ++++++----- .../component/heatmap/HeatMapView.js | 6 ++-- .../component/pie-chart/PieChartAdmin.js | 30 ++++++++++--------- .../component/pie-chart/PieChartView.js | 6 ++-- .../vega/component/flow-map/FlowMapAdmin.js | 2 ++ .../vega/component/flow-map/FlowMapView.js | 14 +++++++-- .../component/radar-chart/RadarChartAdmin.js | 2 ++ .../component/radar-chart/RadarChartView.js | 8 ++--- 14 files changed, 94 insertions(+), 76 deletions(-) diff --git a/src/app/js/formats/vega-lite/component/bar-chart/BarChartAdmin.js b/src/app/js/formats/vega-lite/component/bar-chart/BarChartAdmin.js index 46415af49..da8e658c5 100644 --- a/src/app/js/formats/vega-lite/component/bar-chart/BarChartAdmin.js +++ b/src/app/js/formats/vega-lite/component/bar-chart/BarChartAdmin.js @@ -109,6 +109,8 @@ const BarChartAdmin = props => { return JSON.stringify(specBuilder.buildSpec(), null, 2); }, [advancedMode, advancedModeSpec]); + // Save the new spec when we first use the advanced mode or when we reset the generated spec + // details: Update advancedModeSpec props arguments when spec is generated or regenerated useEffect(() => { if (!advancedMode) { return; @@ -117,7 +119,7 @@ const BarChartAdmin = props => { }, [advancedMode, advancedModeSpec]); const toggleAdvancedMode = () => { - updateAdminArgs('advancedMode', !args.advancedMode, props); + updateAdminArgs('advancedMode', !advancedMode, props); }; const handleAdvancedModeSpec = newSpec => { @@ -133,11 +135,11 @@ const BarChartAdmin = props => { }; const handleColors = colors => { - updateAdminArgs('colors', colors || defaultArgs.colors, this.props); + updateAdminArgs('colors', colors || defaultArgs.colors, props); }; const handleAxisRoundValue = () => { - updateAdminArgs('axisRoundValue', !args.axisRoundValue, props); + updateAdminArgs('axisRoundValue', !axisRoundValue, props); }; const handleScale = event => { @@ -149,15 +151,11 @@ const BarChartAdmin = props => { }; const toggleDiagonalValueAxis = () => { - updateAdminArgs('diagonalValueAxis', !args.diagonalValueAxis, props); + updateAdminArgs('diagonalValueAxis', !diagonalValueAxis, props); }; const toggleDiagonalCategoryAxis = () => { - updateAdminArgs( - 'diagonalCategoryAxis', - !args.diagonalCategoryAxis, - props, - ); + updateAdminArgs('diagonalCategoryAxis', !diagonalCategoryAxis, props); }; const handleBarSize = event => { @@ -211,7 +209,13 @@ const BarChartAdmin = props => { showMinValue={showMinValue} showOrderBy={showOrderBy} /> - {!advancedMode ? ( + {advancedMode ? ( + + ) : ( <> { value={barSize} /> - ) : ( - )} ); diff --git a/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js b/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js index b7118af6b..eb2c1a260 100644 --- a/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js +++ b/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js @@ -57,10 +57,10 @@ class BarChartView extends Component { if (this.props.diagonalValueAxis) barChartSpec.setLabelAngle(AXIS_Y, -45); - let advanceSpec; + let advancedSpec; try { - advanceSpec = JSON.parse(advancedModeSpec); + advancedSpec = JSON.parse(advancedModeSpec); } catch (e) { return ; } @@ -73,7 +73,7 @@ class BarChartView extends Component { {({ width }) => { const spec = advancedMode ? { - ...advanceSpec, + ...advancedSpec, width: width - VEGA_ACTIONS_WIDTH, } : barChartSpec.buildSpec(width, data.values.length); diff --git a/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotAdmin.js b/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotAdmin.js index 72f3e5fed..e0b297aea 100644 --- a/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotAdmin.js +++ b/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotAdmin.js @@ -80,6 +80,8 @@ const BubblePlotAdmin = props => { return JSON.stringify(specBuilder.buildSpec(), null, 2); }, [advancedMode, advancedModeSpec]); + // Save the new spec when we first use the advanced mode or when we reset the generated spec + // details: Update advancedModeSpec props arguments when spec is generated or regenerated useEffect(() => { if (!advancedMode) { return; @@ -88,7 +90,7 @@ const BubblePlotAdmin = props => { }, [advancedMode, advancedModeSpec]); const toggleAdvancedMode = () => { - updateAdminArgs('advancedMode', !args.advancedMode, props); + updateAdminArgs('advancedMode', !advancedMode, props); }; const handleAdvancedModeSpec = newSpec => { @@ -154,7 +156,13 @@ const BubblePlotAdmin = props => { showMinValue={showMinValue} showOrderBy={showOrderBy} /> - {!advancedMode ? ( + {advancedMode ? ( + + ) : ( <> { polyglot={polyglot} /> - ) : ( - )} ); diff --git a/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotView.js b/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotView.js index c51a1f63d..f72914339 100644 --- a/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotView.js +++ b/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotView.js @@ -38,10 +38,10 @@ class BubblePlotView extends Component { bubblePlot.setTooltipTarget(this.props.tooltipTarget); bubblePlot.setTooltipValue(this.props.tooltipWeight); - let advanceSpec; + let advancedSpec; try { - advanceSpec = JSON.parse(advancedModeSpec); + advancedSpec = JSON.parse(advancedModeSpec); } catch (e) { return ; } @@ -54,7 +54,7 @@ class BubblePlotView extends Component { {({ width }) => { const spec = advancedMode ? { - ...advanceSpec, + ...advancedSpec, width: width - VEGA_ACTIONS_WIDTH, } : bubblePlot.buildSpec(width); diff --git a/src/app/js/formats/vega-lite/component/cartography/CartographyAdmin.js b/src/app/js/formats/vega-lite/component/cartography/CartographyAdmin.js index 266c69840..5086a3996 100644 --- a/src/app/js/formats/vega-lite/component/cartography/CartographyAdmin.js +++ b/src/app/js/formats/vega-lite/component/cartography/CartographyAdmin.js @@ -76,6 +76,8 @@ const CartographyAdmin = props => { return JSON.stringify(specBuilder.buildSpec(), null, 2); }, [advancedMode, advancedModeSpec]); + // Save the new spec when we first use the advanced mode or when we reset the generated spec + // details: Update advancedModeSpec props arguments when spec is generated or regenerated useEffect(() => { if (!advancedMode) { return; @@ -84,7 +86,7 @@ const CartographyAdmin = props => { }, [advancedMode, advancedModeSpec]); const toggleAdvancedMode = () => { - updateAdminArgs('advancedMode', !args.advancedMode, props); + updateAdminArgs('advancedMode', !advancedMode, props); }; const handleAdvancedModeSpec = newSpec => { @@ -148,7 +150,13 @@ const CartographyAdmin = props => { showMinValue={showMinValue} showOrderBy={showOrderBy} /> - {!advancedMode ? ( + {advancedMode ? ( + + ) : ( <> { thirdValue={false} /> - ) : ( - )} ); diff --git a/src/app/js/formats/vega-lite/component/cartography/CartographyView.js b/src/app/js/formats/vega-lite/component/cartography/CartographyView.js index ddd8a6053..5dc65159c 100644 --- a/src/app/js/formats/vega-lite/component/cartography/CartographyView.js +++ b/src/app/js/formats/vega-lite/component/cartography/CartographyView.js @@ -42,10 +42,10 @@ class CartographyView extends Component { : schemeOrRd[9], ); - let advanceSpec; + let advancedSpec; try { - advanceSpec = JSON.parse(advancedModeSpec); + advancedSpec = JSON.parse(advancedModeSpec); } catch (e) { return ; } @@ -58,7 +58,7 @@ class CartographyView extends Component { {({ width }) => { const spec = advancedMode ? { - ...advanceSpec, + ...advancedSpec, width: width - VEGA_ACTIONS_WIDTH, height: (width - VEGA_ACTIONS_WIDTH) * 0.6, } diff --git a/src/app/js/formats/vega-lite/component/heatmap/HeatMapAdmin.js b/src/app/js/formats/vega-lite/component/heatmap/HeatMapAdmin.js index 03cf97d9a..b975fd6d6 100644 --- a/src/app/js/formats/vega-lite/component/heatmap/HeatMapAdmin.js +++ b/src/app/js/formats/vega-lite/component/heatmap/HeatMapAdmin.js @@ -78,6 +78,8 @@ const HeatMapAdmin = props => { return JSON.stringify(specBuilder.buildSpec(), null, 2); }, [advancedMode, advancedModeSpec]); + // Save the new spec when we first use the advanced mode or when we reset the generated spec + // details: Update advancedModeSpec props arguments when spec is generated or regenerated useEffect(() => { if (!advancedMode) { return; @@ -86,7 +88,7 @@ const HeatMapAdmin = props => { }, [advancedMode, advancedModeSpec]); const toggleAdvancedMode = () => { - updateAdminArgs('advancedMode', !args.advancedMode, props); + updateAdminArgs('advancedMode', !advancedMode, props); }; const handleAdvancedModeSpec = newSpec => { @@ -156,7 +158,13 @@ const HeatMapAdmin = props => { showMinValue={showMinValue} showOrderBy={showOrderBy} /> - {!advancedMode ? ( + {advancedMode ? ( + + ) : ( <> { label={polyglot.t('flip_axis')} /> - ) : ( - )} ); diff --git a/src/app/js/formats/vega-lite/component/heatmap/HeatMapView.js b/src/app/js/formats/vega-lite/component/heatmap/HeatMapView.js index 324bb47eb..797d1d0eb 100644 --- a/src/app/js/formats/vega-lite/component/heatmap/HeatMapView.js +++ b/src/app/js/formats/vega-lite/component/heatmap/HeatMapView.js @@ -38,10 +38,10 @@ class HeatMapView extends Component { heatMap.setTooltipTarget(this.props.tooltipTarget); heatMap.setTooltipValue(this.props.tooltipWeight); - let advanceSpec; + let advancedSpec; try { - advanceSpec = JSON.parse(advancedModeSpec); + advancedSpec = JSON.parse(advancedModeSpec); } catch (e) { return ; } @@ -54,7 +54,7 @@ class HeatMapView extends Component { {({ width }) => { const spec = advancedMode ? { - ...advanceSpec, + ...advancedSpec, width: width - VEGA_ACTIONS_WIDTH, } : heatMap.buildSpec(width); diff --git a/src/app/js/formats/vega-lite/component/pie-chart/PieChartAdmin.js b/src/app/js/formats/vega-lite/component/pie-chart/PieChartAdmin.js index e5b3cb9e6..f71be59c9 100644 --- a/src/app/js/formats/vega-lite/component/pie-chart/PieChartAdmin.js +++ b/src/app/js/formats/vega-lite/component/pie-chart/PieChartAdmin.js @@ -52,6 +52,10 @@ const PieChartAdmin = props => { labels, } = args; + const colors = useMemo(() => { + return args.colors || defaultArgs.colors; + }, [args.colors]); + const spec = useMemo(() => { if (!advancedMode) { return null; @@ -72,6 +76,8 @@ const PieChartAdmin = props => { return JSON.stringify(specBuilder.buildSpec(), null, 2); }, [advancedMode, advancedModeSpec]); + // Save the new spec when we first use the advanced mode or when we reset the generated spec + // details: Update advancedModeSpec props arguments when spec is generated or regenerated useEffect(() => { if (!advancedMode) { return; @@ -80,7 +86,7 @@ const PieChartAdmin = props => { }, [advancedMode, advancedModeSpec]); const toggleAdvancedMode = () => { - updateAdminArgs('advancedMode', !args.advancedMode, props); + updateAdminArgs('advancedMode', !advancedMode, props); }; const handleAdvancedModeSpec = newSpec => { @@ -91,10 +97,6 @@ const PieChartAdmin = props => { updateAdminArgs('advancedModeSpec', null, props); }; - const colors = useMemo(() => { - return args.colors || defaultArgs.colors; - }, [args.colors]); - const handleParams = params => updateAdminArgs('params', params, props); const handleColors = colors => { @@ -102,11 +104,11 @@ const PieChartAdmin = props => { }; const toggleLabels = () => { - updateAdminArgs('labels', !args.labels, props); + updateAdminArgs('labels', !labels, props); }; const toggleTooltip = () => { - updateAdminArgs('tooltip', !args.tooltip, props); + updateAdminArgs('tooltip', !tooltip, props); }; const handleTooltipCategory = tooltipCategory => { @@ -144,7 +146,13 @@ const PieChartAdmin = props => { showMinValue={showMinValue} showOrderBy={showOrderBy} /> - {!advancedMode ? ( + {advancedMode ? ( + + ) : ( <> { polyglot={polyglot} /> - ) : ( - )} ); diff --git a/src/app/js/formats/vega-lite/component/pie-chart/PieChartView.js b/src/app/js/formats/vega-lite/component/pie-chart/PieChartView.js index 0cb8bfb44..e7792ebe8 100644 --- a/src/app/js/formats/vega-lite/component/pie-chart/PieChartView.js +++ b/src/app/js/formats/vega-lite/component/pie-chart/PieChartView.js @@ -40,10 +40,10 @@ class PieChartView extends Component { pieChart.setColor(this.props.colors); pieChart.setLabels(this.props.labels); - let advanceSpec; + let advancedSpec; try { - advanceSpec = JSON.parse(advancedModeSpec); + advancedSpec = JSON.parse(advancedModeSpec); } catch (e) { return ; } @@ -56,7 +56,7 @@ class PieChartView extends Component { {({ width }) => { const spec = advancedMode ? { - ...advanceSpec, + ...advancedSpec, width: width - VEGA_ACTIONS_WIDTH, } : pieChart.buildSpec(width); diff --git a/src/app/js/formats/vega/component/flow-map/FlowMapAdmin.js b/src/app/js/formats/vega/component/flow-map/FlowMapAdmin.js index 531003703..e77bbedcd 100644 --- a/src/app/js/formats/vega/component/flow-map/FlowMapAdmin.js +++ b/src/app/js/formats/vega/component/flow-map/FlowMapAdmin.js @@ -71,6 +71,8 @@ const FlowMapAdmin = props => { return JSON.stringify(specBuilder.buildSpec(), null, 2); }, [advancedMode, advancedModeSpec]); + // Save the new spec when we first use the advanced mode or when we reset the generated spec + // details: Update advancedModeSpec props arguments when spec is generated or regenerated useEffect(() => { if (!advancedMode) { return; diff --git a/src/app/js/formats/vega/component/flow-map/FlowMapView.js b/src/app/js/formats/vega/component/flow-map/FlowMapView.js index b0b0b51fb..04b94f8d4 100644 --- a/src/app/js/formats/vega/component/flow-map/FlowMapView.js +++ b/src/app/js/formats/vega/component/flow-map/FlowMapView.js @@ -23,6 +23,14 @@ const styles = { }, }; +// const FlowMapView = (props) => { +// const { advancedMode, advancedModeSpec, field, data } = props; +// +// const spec = useMemo(() => { +// +// }, []); +// } + class FlowMapView extends Component { render() { const { advancedMode, advancedModeSpec, field, data } = this.props; @@ -43,10 +51,10 @@ class FlowMapView extends Component { : schemeBlues[9].split(' '), ); - let advanceSpec; + let advancedSpec; try { - advanceSpec = JSON.parse(advancedModeSpec); + advancedSpec = JSON.parse(advancedModeSpec); } catch (e) { return ; } @@ -59,7 +67,7 @@ class FlowMapView extends Component { {({ width }) => { const spec = advancedMode ? { - ...advanceSpec, + ...advancedSpec, width: width - VEGA_ACTIONS_WIDTH, height: width * 0.6, } diff --git a/src/app/js/formats/vega/component/radar-chart/RadarChartAdmin.js b/src/app/js/formats/vega/component/radar-chart/RadarChartAdmin.js index 034db777a..f33f01873 100644 --- a/src/app/js/formats/vega/component/radar-chart/RadarChartAdmin.js +++ b/src/app/js/formats/vega/component/radar-chart/RadarChartAdmin.js @@ -82,6 +82,8 @@ const RadarChartAdmin = props => { return JSON.stringify(specBuilder.buildSpec(), null, 2); }, [advancedMode, advancedModeSpec]); + // Save the new spec when we first use the advanced mode or when we reset the generated spec + // details: Update advancedModeSpec props arguments when spec is generated or regenerated useEffect(() => { if (!advancedMode) { return; diff --git a/src/app/js/formats/vega/component/radar-chart/RadarChartView.js b/src/app/js/formats/vega/component/radar-chart/RadarChartView.js index b394da43e..84127c35e 100644 --- a/src/app/js/formats/vega/component/radar-chart/RadarChartView.js +++ b/src/app/js/formats/vega/component/radar-chart/RadarChartView.js @@ -36,7 +36,7 @@ class RadarChartView extends Component { // Create a new radar chart instance - const radarChart = deepClone(new RadarChart()); + const radarChart = new RadarChart(); // Set all radar chart parameter the chosen by the administrator @@ -46,10 +46,10 @@ class RadarChartView extends Component { radarChart.setTooltipValue(this.props.tooltipValue); radarChart.setScale(lodexScaleToIdScale(this.props.scale)); - let advanceSpec; + let advancedSpec; try { - advanceSpec = JSON.parse(advancedModeSpec); + advancedSpec = JSON.parse(advancedModeSpec); } catch (e) { return ; } @@ -62,7 +62,7 @@ class RadarChartView extends Component { {({ width }) => { const spec = advancedMode ? { - ...advanceSpec, + ...advancedSpec, width: width - width * 0.06, height: width - width * 0.24, } From 40335dcc17478dbe05b0aa87fd1be480301ee537 Mon Sep 17 00:00:00 2001 From: AlasDiablo <25723276+AlasDiablo@users.noreply.github.com> Date: Wed, 20 Sep 2023 08:11:04 +0200 Subject: [PATCH 17/37] fix: remove the use of this in FlowMapAdmin function component --- .../js/formats/vega/component/flow-map/FlowMapAdmin.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/js/formats/vega/component/flow-map/FlowMapAdmin.js b/src/app/js/formats/vega/component/flow-map/FlowMapAdmin.js index e77bbedcd..ef41c4628 100644 --- a/src/app/js/formats/vega/component/flow-map/FlowMapAdmin.js +++ b/src/app/js/formats/vega/component/flow-map/FlowMapAdmin.js @@ -60,10 +60,10 @@ const FlowMapAdmin = props => { const specBuilder = new FlowMap(); - specBuilder.setTooltip(this.props.tooltip); - specBuilder.setTooltipCategory(this.props.tooltipCategory); - specBuilder.setTooltipValue(this.props.tooltipValue); - specBuilder.setColor(this.props.color.split(' ')[0]); + specBuilder.setTooltip(tooltip); + specBuilder.setTooltipCategory(tooltipCategory); + specBuilder.setTooltipValue(tooltipValue); + specBuilder.setColor(color.split(' ')[0]); specBuilder.setColorScheme( colorScheme !== undefined ? colorScheme : schemeBlues[9].split(' '), ); From a267fe20a7945fe7b5c6dda42aa95f4fed38fd94 Mon Sep 17 00:00:00 2001 From: AlasDiablo <25723276+AlasDiablo@users.noreply.github.com> Date: Wed, 20 Sep 2023 08:11:52 +0200 Subject: [PATCH 18/37] refactor: convert FlowMapView to a function component --- .../vega/component/flow-map/FlowMapView.js | 129 ++++++++++-------- 1 file changed, 73 insertions(+), 56 deletions(-) diff --git a/src/app/js/formats/vega/component/flow-map/FlowMapView.js b/src/app/js/formats/vega/component/flow-map/FlowMapView.js index 04b94f8d4..f07fb804e 100644 --- a/src/app/js/formats/vega/component/flow-map/FlowMapView.js +++ b/src/app/js/formats/vega/component/flow-map/FlowMapView.js @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React, { useEffect, useMemo, useRef, useState } from 'react'; import injectData from '../../../injectData'; import { connect } from 'react-redux'; import compose from 'recompose/compose'; @@ -7,7 +7,6 @@ import { polyglot as polyglotPropTypes, } from '../../../../propTypes'; import PropTypes from 'prop-types'; -import ContainerDimensions from 'react-container-dimensions'; import { CustomActionVega } from '../vega-component'; import FlowMap from '../../models/FlowMap'; import { VEGA_DATA_INJECT_TYPE_B } from '../../../chartsUtils'; @@ -23,69 +22,87 @@ const styles = { }, }; -// const FlowMapView = (props) => { -// const { advancedMode, advancedModeSpec, field, data } = props; -// -// const spec = useMemo(() => { -// -// }, []); -// } +const FlowMapView = props => { + const { + advancedMode, + advancedModeSpec, + field, + data, + tooltip, + tooltipCategory, + tooltipValue, + color, + colorScheme, + } = props; + const ref = useRef(null); + const [width, setWidth] = useState(0); + const [error, setError] = useState(''); -class FlowMapView extends Component { - render() { - const { advancedMode, advancedModeSpec, field, data } = this.props; - - // Create a new flow map instance - - const flowMap = new FlowMap(); + const spec = useMemo(() => { + if (advancedMode) { + try { + const advancedSpec = JSON.parse(advancedModeSpec); + return { + ...advancedSpec, + width: width - VEGA_ACTIONS_WIDTH, + height: width * 0.6, + }; + } catch (e) { + setError(e.message); + return null; + } + } - // Set all flow map parameter the chosen by the administrator + const specBuilder = new FlowMap(); - flowMap.setTooltip(this.props.tooltip); - flowMap.setTooltipCategory(this.props.tooltipCategory); - flowMap.setTooltipValue(this.props.tooltipValue); - flowMap.setColor(this.props.color.split(' ')[0]); - flowMap.setColorScheme( - this.props.colorScheme !== undefined - ? this.props.colorScheme - : schemeBlues[9].split(' '), + specBuilder.setTooltip(tooltip); + specBuilder.setTooltipCategory(tooltipCategory); + specBuilder.setTooltipValue(tooltipValue); + specBuilder.setColor(color.split(' ')[0]); + specBuilder.setColorScheme( + colorScheme !== undefined ? colorScheme : schemeBlues[9].split(' '), ); - let advancedSpec; + return specBuilder.buildSpec(width, data.values.length); + }, [ + width, + data.values, + advancedMode, + advancedModeSpec, + tooltip, + tooltipCategory, + tooltipValue, + color, + colorScheme, + ]); - try { - advancedSpec = JSON.parse(advancedModeSpec); - } catch (e) { - return ; + useEffect(() => { + if (!ref.current) { + return; } - // return the finish chart - return ( -
- {/* Make the chart responsive */} - - {({ width }) => { - const spec = advancedMode - ? { - ...advancedSpec, - width: width - VEGA_ACTIONS_WIDTH, - height: width * 0.6, - } - : flowMap.buildSpec(width, data.values.length); - return ( - - ); - }} - - -
- ); + const resizeObserver = new ResizeObserver(() => { + setWidth(ref.current.offsetWidth); + }); + + resizeObserver.observe(ref.current); + }, [ref.current]); + + if (spec === null) { + return ; } -} + + return ( +
+ + +
+ ); +}; FlowMapView.propTypes = { field: fieldPropTypes.isRequired, From 2e8b8d29104c38b2b10a9d9af1780826a0e4fa29 Mon Sep 17 00:00:00 2001 From: AlasDiablo <25723276+AlasDiablo@users.noreply.github.com> Date: Wed, 20 Sep 2023 08:12:15 +0200 Subject: [PATCH 19/37] refactor: convert BarChartView to a function component --- .../component/bar-chart/BarChartView.js | 138 ++++++++++-------- 1 file changed, 80 insertions(+), 58 deletions(-) diff --git a/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js b/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js index eb2c1a260..fa9b6e9d3 100644 --- a/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js +++ b/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js @@ -1,10 +1,9 @@ -import React, { Component } from 'react'; +import React, { useEffect, useMemo, useRef, useState } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import compose from 'recompose/compose'; import injectData from '../../../injectData'; import { field as fieldPropTypes } from '../../../../propTypes'; -import ContainerDimensions from 'react-container-dimensions'; import { AXIS_HORIZONTAL, AXIS_VERTICAL, @@ -25,71 +24,94 @@ const styles = { }, }; -class BarChartView extends Component { - render() { - const { advancedMode, advancedModeSpec, field, data } = this.props; +const BarChartView = props => { + const { + advancedMode, + advancedModeSpec, + field, + data, + direction, + params, + scale, + colors, + axisRoundValue, + tooltip, + tooltipCategory, + tooltipValue, + labels, + labelOverlap, + barSize, + diagonalCategoryAxis, + diagonalValueAxis, + } = props; - // Create a new bar chart instance + const ref = useRef(null); + const [width, setWidth] = useState(0); + const [error, setError] = useState(''); - const barChartSpec = new BarChart(); + const spec = useMemo(() => { + if (advancedMode) { + try { + const advancedSpec = JSON.parse(advancedModeSpec); + return { + ...advancedSpec, + width: width - VEGA_ACTIONS_WIDTH, + }; + } catch (e) { + setError(e.message); + return null; + } + } - // Set all bar chart parameter the chosen by the administrator + const specBuilder = new BarChart(); - barChartSpec.setAxisDirection( - this.props.direction === 'vertical' - ? AXIS_VERTICAL - : AXIS_HORIZONTAL, + specBuilder.setAxisDirection( + direction === 'vertical' ? AXIS_VERTICAL : AXIS_HORIZONTAL, ); - barChartSpec.setOrderBy(lodexOrderToIdOrder(this.props.params.orderBy)); - barChartSpec.setScale(lodexScaleToIdScale(this.props.scale)); - barChartSpec.setColor(this.props.colors); - barChartSpec.setRoundValue(this.props.axisRoundValue); - barChartSpec.setTooltip(this.props.tooltip); - barChartSpec.setTooltipCategory(this.props.tooltipCategory); - barChartSpec.setTooltipValue(this.props.tooltipValue); - barChartSpec.setLabels(this.props.labels); - barChartSpec.setLabelOverlap(this.props.labelOverlap); - barChartSpec.setSize(this.props.barSize); - - if (this.props.diagonalCategoryAxis) - barChartSpec.setLabelAngle(AXIS_X, -45); - if (this.props.diagonalValueAxis) - barChartSpec.setLabelAngle(AXIS_Y, -45); - - let advancedSpec; - - try { - advancedSpec = JSON.parse(advancedModeSpec); - } catch (e) { - return ; + specBuilder.setOrderBy(lodexOrderToIdOrder(params.orderBy)); + specBuilder.setScale(lodexScaleToIdScale(scale)); + specBuilder.setColor(colors); + specBuilder.setRoundValue(axisRoundValue); + specBuilder.setTooltip(tooltip); + specBuilder.setTooltipCategory(tooltipCategory); + specBuilder.setTooltipValue(tooltipValue); + specBuilder.setLabels(labels); + specBuilder.setLabelOverlap(labelOverlap); + specBuilder.setSize(barSize); + + if (diagonalCategoryAxis) specBuilder.setLabelAngle(AXIS_X, -45); + if (diagonalValueAxis) specBuilder.setLabelAngle(AXIS_Y, -45); + + return specBuilder.buildSpec(width, data.values.length); + }, [width, advancedMode, advancedModeSpec, field, data.values]); + + useEffect(() => { + if (!ref.current) { + return; } - // return the finish chart - return ( -
- {/* Make the chart responsive */} - - {({ width }) => { - const spec = advancedMode - ? { - ...advancedSpec, - width: width - VEGA_ACTIONS_WIDTH, - } - : barChartSpec.buildSpec(width, data.values.length); - return ( - - ); - }} - -
- ); + const resizeObserver = new ResizeObserver(() => { + setWidth(ref.current.offsetWidth); + }); + + resizeObserver.observe(ref.current); + }, [ref.current]); + + if (!spec) { + return ; } -} + + return ( +
+ +
+ ); +}; BarChartView.propTypes = { field: fieldPropTypes.isRequired, From ba56ed29590767e9900a9ecbee822de1bcce231d Mon Sep 17 00:00:00 2001 From: AlasDiablo <25723276+AlasDiablo@users.noreply.github.com> Date: Wed, 20 Sep 2023 08:21:19 +0200 Subject: [PATCH 20/37] fix: use correct call to polyglot props value --- src/app/js/formats/vega/component/flow-map/FlowMapView.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/app/js/formats/vega/component/flow-map/FlowMapView.js b/src/app/js/formats/vega/component/flow-map/FlowMapView.js index f07fb804e..5fd08e2b7 100644 --- a/src/app/js/formats/vega/component/flow-map/FlowMapView.js +++ b/src/app/js/formats/vega/component/flow-map/FlowMapView.js @@ -26,6 +26,7 @@ const FlowMapView = props => { const { advancedMode, advancedModeSpec, + p, field, data, tooltip, @@ -99,7 +100,7 @@ const FlowMapView = props => { data={data} injectType={VEGA_DATA_INJECT_TYPE_B} /> - +
); }; From 213e8a3a5d1b78acd5156533b87d2f7bbd0a2221 Mon Sep 17 00:00:00 2001 From: AlasDiablo <25723276+AlasDiablo@users.noreply.github.com> Date: Wed, 20 Sep 2023 08:22:00 +0200 Subject: [PATCH 21/37] refactor: convert RadarChartView to a function component --- .../component/radar-chart/RadarChartView.js | 140 +++++++++++------- 1 file changed, 87 insertions(+), 53 deletions(-) diff --git a/src/app/js/formats/vega/component/radar-chart/RadarChartView.js b/src/app/js/formats/vega/component/radar-chart/RadarChartView.js index 84127c35e..48a9ceefb 100644 --- a/src/app/js/formats/vega/component/radar-chart/RadarChartView.js +++ b/src/app/js/formats/vega/component/radar-chart/RadarChartView.js @@ -1,11 +1,9 @@ -import React, { Component } from 'react'; +import React, { useEffect, useMemo, useRef, useState } from 'react'; import injectData from '../../../injectData'; import { connect } from 'react-redux'; import compose from 'recompose/compose'; import { field as fieldPropTypes } from '../../../../propTypes'; import PropTypes from 'prop-types'; -import deepClone from 'lodash.clonedeep'; -import ContainerDimensions from 'react-container-dimensions'; import { CustomActionVega } from '../vega-component'; import RadarChart from '../../models/RadarChart'; import { @@ -22,64 +20,100 @@ const styles = { }, }; -class RadarChartView extends Component { - render() { - const { advancedMode, advancedModeSpec, field, data } = this.props; - - // format the data for the vega template - - if (data !== undefined) { - data.values.forEach(e => { - e.category = 0; - }); +const RadarChartView = props => { + const { + advancedMode, + advancedModeSpec, + field, + colors, + tooltip, + tooltipCategory, + tooltipValue, + scale, + } = props; + + const data = useMemo(() => { + if (!props.data) { + return props.data; } - // Create a new radar chart instance - - const radarChart = new RadarChart(); + const formattedData = { + ...props.data, + }; - // Set all radar chart parameter the chosen by the administrator + formattedData.values.forEach(value => { + value.category = 0; + }); + + return formattedData; + }, [props.data]); + + const ref = useRef(null); + const [width, setWidth] = useState(0); + const [error, setError] = useState(''); + + const spec = useMemo(() => { + if (advancedMode) { + try { + const advancedSpec = JSON.parse(advancedModeSpec); + return { + ...advancedSpec, + width: width - width * 0.06, + height: width - width * 0.24, + }; + } catch (e) { + setError(e.message); + return null; + } + } - radarChart.setColors(this.props.colors.split(' ')); - radarChart.setTooltip(this.props.tooltip); - radarChart.setTooltipCategory(this.props.tooltipCategory); - radarChart.setTooltipValue(this.props.tooltipValue); - radarChart.setScale(lodexScaleToIdScale(this.props.scale)); + const specBuilder = new RadarChart(); + + specBuilder.setColors(colors.split(' ')); + specBuilder.setTooltip(tooltip); + specBuilder.setTooltipCategory(tooltipCategory); + specBuilder.setTooltipValue(tooltipValue); + specBuilder.setScale(lodexScaleToIdScale(scale)); + + return specBuilder.buildSpec(width, data.values.length); + }, [ + width, + data.values, + advancedMode, + advancedModeSpec, + colors, + tooltip, + tooltipCategory, + tooltipValue, + scale, + ]); + + useEffect(() => { + if (!ref.current) { + return; + } - let advancedSpec; + const resizeObserver = new ResizeObserver(() => { + setWidth(ref.current.offsetWidth); + }); - try { - advancedSpec = JSON.parse(advancedModeSpec); - } catch (e) { - return ; - } + resizeObserver.observe(ref.current); + }, [ref.current]); - // return the finish chart - return ( -
- {/* Make the chart responsive */} - - {({ width }) => { - const spec = advancedMode - ? { - ...advancedSpec, - width: width - width * 0.06, - height: width - width * 0.24, - } - : radarChart.buildSpec(width, data.values.length); - return ( - - ); - }} - -
- ); + if (spec === null) { + return ; } -} + + return ( +
+ +
+ ); +}; RadarChartView.propTypes = { field: fieldPropTypes.isRequired, From 3b4354f0fd1449998877481c053d6e54ce15de00 Mon Sep 17 00:00:00 2001 From: AlasDiablo <25723276+AlasDiablo@users.noreply.github.com> Date: Wed, 20 Sep 2023 09:57:31 +0200 Subject: [PATCH 22/37] refactor: optimize vega / vega lite pre render components --- .../vega-lite-component/VegaLiteComponent.js | 81 +++++++++-------- .../component/vega-component/VegaComponent.js | 89 +++++++++---------- 2 files changed, 86 insertions(+), 84 deletions(-) diff --git a/src/app/js/formats/vega-lite/component/vega-lite-component/VegaLiteComponent.js b/src/app/js/formats/vega-lite/component/vega-lite-component/VegaLiteComponent.js index e196216c7..378be62fb 100644 --- a/src/app/js/formats/vega-lite/component/vega-lite-component/VegaLiteComponent.js +++ b/src/app/js/formats/vega-lite/component/vega-lite-component/VegaLiteComponent.js @@ -1,5 +1,5 @@ import { Vega } from 'react-vega'; -import React from 'react'; +import React, { useMemo } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { isAdmin } from '../../../../user'; @@ -9,28 +9,21 @@ import { VEGA_LITE_DATA_INJECT_TYPE_B, VEGA_LITE_DATA_INJECT_TYPE_C, } from '../../../chartsUtils'; +import set from 'lodash.set'; export const VEGA_ACTIONS_WIDTH = 40; /** * small component use to handle vega lite display - * @param props args taken by the component + * @param user + * @param injectType + * @param data + * @param spec * @returns {*} React-Vega component */ -function CustomActionVegaLite(props) { - let actions; - if (isAdmin(props.user)) { - actions = { - export: { - svg: true, - png: true, - }, - source: true, - compiled: true, - editor: true, - }; - } else { - actions = { +const CustomActionVegaLite = ({ user, injectType, data, spec }) => { + const actions = useMemo(() => { + const defaultActions = { export: { svg: true, png: true, @@ -39,34 +32,48 @@ function CustomActionVegaLite(props) { compiled: false, editor: false, }; - } + if (isAdmin(user)) { + return { + ...defaultActions, + source: true, + compiled: true, + editor: true, + }; + } + return defaultActions; + }, [user]); - const spec = props.spec; + const specWithData = useMemo(() => { + const tmpSpec = deepClone(spec); - switch (props.injectType) { - case VEGA_LITE_DATA_INJECT_TYPE_A: - spec.data = props.data; - break; - case VEGA_LITE_DATA_INJECT_TYPE_B: - spec.transform.forEach(e => { - if (e.lookup === 'id') { - e.from.data.values = props.data.values; + if (injectType === VEGA_LITE_DATA_INJECT_TYPE_A) { + set(tmpSpec, 'data', data); + return tmpSpec; + } + + if (injectType === VEGA_LITE_DATA_INJECT_TYPE_B) { + tmpSpec.transform.forEach(entry => { + if (entry.lookup === 'id') { + set(entry, 'from.data.values', data.values); } }); - break; - case VEGA_LITE_DATA_INJECT_TYPE_C: - spec.transform.forEach(e => { - if (e.lookup === 'properties.HASC_2') { - e.from.data.values = props.data.values; + return tmpSpec; + } + + if (injectType === VEGA_LITE_DATA_INJECT_TYPE_C) { + tmpSpec.transform.forEach(entry => { + if (entry.lookup === 'properties.HASC_2') { + set(entry, 'from.data.values', data.values); } }); - break; - default: - throw new Error('Invalid data injection type'); - } + return tmpSpec; + } - return ; -} + return tmpSpec; + }, [injectType, spec, data]); + + return ; +}; /** * Element required in the props diff --git a/src/app/js/formats/vega/component/vega-component/VegaComponent.js b/src/app/js/formats/vega/component/vega-component/VegaComponent.js index 7421f75d7..fd5b89f5d 100644 --- a/src/app/js/formats/vega/component/vega-component/VegaComponent.js +++ b/src/app/js/formats/vega/component/vega-component/VegaComponent.js @@ -1,5 +1,5 @@ import { Vega } from 'react-vega'; -import React from 'react'; +import React, { useMemo } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { isAdmin } from '../../../../user'; @@ -8,26 +8,16 @@ import { VEGA_DATA_INJECT_TYPE_A, VEGA_DATA_INJECT_TYPE_B, } from '../../../chartsUtils'; +import set from 'lodash.set'; /** * small component use to handle vega lite display * @param props args taken by the component * @returns {*} React-Vega component */ -function CustomActionVega(props) { - let actions; - if (isAdmin(props.user)) { - actions = { - export: { - svg: true, - png: true, - }, - source: true, - compiled: true, - editor: true, - }; - } else { - actions = { +const CustomActionVega = ({ user, data, spec, injectType }) => { + const actions = useMemo(() => { + const defaultActions = { export: { svg: true, png: true, @@ -36,43 +26,48 @@ function CustomActionVega(props) { compiled: false, editor: false, }; - } + if (isAdmin(user)) { + return { + ...defaultActions, + source: true, + compiled: true, + editor: true, + }; + } + return defaultActions; + }, [user]); - const spec = props.spec; + const specWithData = useMemo(() => { + const tmpSpec = deepClone(spec); - switch (props.injectType) { - case VEGA_DATA_INJECT_TYPE_A: - spec.data.forEach(e => { - if (e.name === 'table') { - e.values = props.data.values; + if (injectType === VEGA_DATA_INJECT_TYPE_A) { + tmpSpec.data.forEach(entry => { + if (entry.name === 'table') { + set(entry, 'values', data.values); } }); - break; - case VEGA_DATA_INJECT_TYPE_B: - { - let data = { - values: [], - }; - props.data.values.forEach(e => { - data.values.push({ - origin: e.source, - destination: e.target, - count: e.weight, - }); - }); - spec.data.forEach(e => { - if (e.name === 'routes' || e.name === 'link_data') { - e.values = data.values; - } - }); - } - break; - default: - throw new Error('Invalid data injection type'); - } + return tmpSpec; + } - return ; -} + if (injectType === VEGA_DATA_INJECT_TYPE_B) { + const mappedData = data.values.map(entry => ({ + origin: entry.source, + destination: entry.target, + count: entry.weight, + })); + tmpSpec.data.forEach(entry => { + if (entry.name === 'routes' || entry.name === 'link_data') { + set(entry, 'values', mappedData); + } + }); + return tmpSpec; + } + + return tmpSpec; + }, [injectType, spec, data]); + + return ; +}; /** * Element required in the props From 31fb00d966cfa9a61fdb4cb33f4db6cdcedbeee2 Mon Sep 17 00:00:00 2001 From: AlasDiablo <25723276+AlasDiablo@users.noreply.github.com> Date: Wed, 20 Sep 2023 09:58:09 +0200 Subject: [PATCH 23/37] fix: add missing deps in BarChartView spec builder --- .../component/bar-chart/BarChartView.js | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js b/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js index fa9b6e9d3..884f3b4e8 100644 --- a/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js +++ b/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js @@ -84,7 +84,26 @@ const BarChartView = props => { if (diagonalValueAxis) specBuilder.setLabelAngle(AXIS_Y, -45); return specBuilder.buildSpec(width, data.values.length); - }, [width, advancedMode, advancedModeSpec, field, data.values]); + }, [ + width, + advancedMode, + advancedModeSpec, + field, + data.values, + direction, + params, + scale, + colors, + axisRoundValue, + tooltip, + tooltipCategory, + tooltipValue, + labels, + labelOverlap, + barSize, + diagonalCategoryAxis, + diagonalValueAxis, + ]); useEffect(() => { if (!ref.current) { From 9dbb5ad09ef39ed37dd6dbe56aff156da52e685c Mon Sep 17 00:00:00 2001 From: AlasDiablo <25723276+AlasDiablo@users.noreply.github.com> Date: Wed, 20 Sep 2023 09:58:46 +0200 Subject: [PATCH 24/37] refactor: convert CartographyView to a function component --- .../component/cartography/CartographyView.js | 126 +++++++++++------- 1 file changed, 76 insertions(+), 50 deletions(-) diff --git a/src/app/js/formats/vega-lite/component/cartography/CartographyView.js b/src/app/js/formats/vega-lite/component/cartography/CartographyView.js index 5dc65159c..61585c1c7 100644 --- a/src/app/js/formats/vega-lite/component/cartography/CartographyView.js +++ b/src/app/js/formats/vega-lite/component/cartography/CartographyView.js @@ -1,8 +1,7 @@ -import React, { Component } from 'react'; +import React, { useEffect, useMemo, useRef, useState } from 'react'; import { connect } from 'react-redux'; import PropTypes from 'prop-types'; import compose from 'recompose/compose'; -import ContainerDimensions from 'react-container-dimensions'; import { CustomActionVegaLite } from '../vega-lite-component'; import { MAP_FRANCE, @@ -22,64 +21,91 @@ const styles = { }, }; -class CartographyView extends Component { - render() { - const { advancedMode, advancedModeSpec, field, data } = this.props; +const CartographyView = props => { + const { + advancedMode, + advancedModeSpec, + field, + data, + tooltip, + tooltipCategory, + tooltipValue, + worldPosition, + colorScheme, + } = props; - // Create a new cartography instance + const ref = useRef(null); + const [width, setWidth] = useState(0); + const [error, setError] = useState(''); - const cartography = new Cartography(); + const spec = useMemo(() => { + if (advancedMode) { + try { + const advancedSpec = JSON.parse(advancedModeSpec); + return { + ...advancedSpec, + width: width - VEGA_ACTIONS_WIDTH, + height: (width - VEGA_ACTIONS_WIDTH) * 0.6, + }; + } catch (e) { + setError(e.message); + return null; + } + } - // Set all cartography parameter the chosen by the administrator + const specBuilder = new Cartography(); - cartography.setTooltip(this.props.tooltip); - cartography.setTooltipCategory(this.props.tooltipCategory); - cartography.setTooltipValue(this.props.tooltipValue); - cartography.setWorldPosition(this.props.worldPosition); - cartography.setColor( - this.props.colorScheme !== undefined - ? this.props.colorScheme.join(' ') - : schemeOrRd[9], + specBuilder.setTooltip(tooltip); + specBuilder.setTooltipCategory(tooltipCategory); + specBuilder.setTooltipValue(tooltipValue); + specBuilder.setWorldPosition(worldPosition); + specBuilder.setColor( + colorScheme !== undefined ? colorScheme.join(' ') : schemeOrRd[9], ); - let advancedSpec; + return specBuilder.buildSpec(width); + }, [ + width, + advancedMode, + advancedModeSpec, + field, + tooltip, + tooltipCategory, + tooltipValue, + worldPosition, + colorScheme, + ]); - try { - advancedSpec = JSON.parse(advancedModeSpec); - } catch (e) { - return ; + useEffect(() => { + if (!ref.current) { + return; } - // return the finish chart - return ( -
- {/* Make the chart responsive */} - - {({ width }) => { - const spec = advancedMode - ? { - ...advancedSpec, - width: width - VEGA_ACTIONS_WIDTH, - height: (width - VEGA_ACTIONS_WIDTH) * 0.6, - } - : cartography.buildSpec(width); - return ( - - ); - }} - -
- ); + const resizeObserver = new ResizeObserver(() => { + setWidth(ref.current.offsetWidth); + }); + + resizeObserver.observe(ref.current); + }, [ref.current]); + + if (!spec) { + return ; } -} + + return ( +
+ +
+ ); +}; CartographyView.propTypes = { field: fieldPropTypes.isRequired, From 2c875a69b422d2fc44aeefcdfde91bbe99ac386c Mon Sep 17 00:00:00 2001 From: AlasDiablo <25723276+AlasDiablo@users.noreply.github.com> Date: Wed, 20 Sep 2023 09:59:02 +0200 Subject: [PATCH 25/37] refactor: convert BubblePlotView to a function component --- .../component/bubble-plot/BubblePlotView.js | 120 +++++++++++------- 1 file changed, 76 insertions(+), 44 deletions(-) diff --git a/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotView.js b/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotView.js index f72914339..0d833611b 100644 --- a/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotView.js +++ b/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotView.js @@ -1,11 +1,10 @@ -import React, { Component } from 'react'; +import React, { useEffect, useMemo, useRef, useState } from 'react'; import { CustomActionVegaLite } from '../vega-lite-component'; import injectData from '../../../injectData'; import { connect } from 'react-redux'; import compose from 'recompose/compose'; import { field as fieldPropTypes } from '../../../../propTypes'; import PropTypes from 'prop-types'; -import ContainerDimensions from 'react-container-dimensions'; import { lodexOrderToIdOrder, VEGA_LITE_DATA_INJECT_TYPE_A, @@ -20,57 +19,90 @@ const styles = { }, }; -class BubblePlotView extends Component { - render() { - const { advancedMode, advancedModeSpec, field, data } = this.props; +const BubblePlotView = props => { + const { + advancedMode, + advancedModeSpec, + field, + data, + colors, + params, + flipAxis, + tooltip, + tooltipSource, + tooltipTarget, + tooltipWeight, + } = props; - // Create a new bubble plot instance + const ref = useRef(null); + const [width, setWidth] = useState(0); + const [error, setError] = useState(''); - const bubblePlot = new BubblePlot(); + const spec = useMemo(() => { + if (advancedMode) { + try { + const advancedSpec = JSON.parse(advancedModeSpec); + return { + ...advancedSpec, + width: width - VEGA_ACTIONS_WIDTH, + }; + } catch (e) { + setError(e.message); + return null; + } + } - // Set all bubble plot parameter the chosen by the administrator + const specBuilder = new BubblePlot(); - bubblePlot.setColor(this.props.colors); - bubblePlot.setOrderBy(lodexOrderToIdOrder(this.props.params.orderBy)); - bubblePlot.flipAxis(this.props.flipAxis); - bubblePlot.setTooltip(this.props.tooltip); - bubblePlot.setTooltipCategory(this.props.tooltipSource); - bubblePlot.setTooltipTarget(this.props.tooltipTarget); - bubblePlot.setTooltipValue(this.props.tooltipWeight); + specBuilder.setColor(colors); + specBuilder.setOrderBy(lodexOrderToIdOrder(params.orderBy)); + specBuilder.flipAxis(flipAxis); + specBuilder.setTooltip(tooltip); + specBuilder.setTooltipCategory(tooltipSource); + specBuilder.setTooltipTarget(tooltipTarget); + specBuilder.setTooltipValue(tooltipWeight); - let advancedSpec; + return specBuilder.buildSpec(width); + }, [ + width, + advancedMode, + advancedModeSpec, + field, + colors, + params, + flipAxis, + tooltip, + tooltipSource, + tooltipTarget, + tooltipWeight, + ]); - try { - advancedSpec = JSON.parse(advancedModeSpec); - } catch (e) { - return ; + useEffect(() => { + if (!ref.current) { + return; } - // return the finish chart - return ( -
- - {/* Make the chart responsive */} - {({ width }) => { - const spec = advancedMode - ? { - ...advancedSpec, - width: width - VEGA_ACTIONS_WIDTH, - } - : bubblePlot.buildSpec(width); - return ( - - ); - }} - -
- ); + const resizeObserver = new ResizeObserver(() => { + setWidth(ref.current.offsetWidth); + }); + + resizeObserver.observe(ref.current); + }, [ref.current]); + + if (!spec) { + return ; } -} + + return ( +
+ +
+ ); +}; BubblePlotView.propTypes = { field: fieldPropTypes.isRequired, From 670a7d8576e1caa5ba37b694b5d1d3a6f27ee2cb Mon Sep 17 00:00:00 2001 From: AlasDiablo <25723276+AlasDiablo@users.noreply.github.com> Date: Wed, 20 Sep 2023 11:11:38 +0200 Subject: [PATCH 26/37] refactor: cleanup object deconstruction --- .../component/bar-chart/BarChartView.js | 40 ++++++++--------- .../component/bubble-plot/BubblePlotView.js | 28 ++++++------ .../component/cartography/CartographyView.js | 24 +++++----- .../vega/component/flow-map/FlowMapView.js | 25 +++++------ .../component/radar-chart/RadarChartView.js | 45 +++++++++---------- 5 files changed, 77 insertions(+), 85 deletions(-) diff --git a/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js b/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js index 884f3b4e8..e5f5a89c7 100644 --- a/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js +++ b/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js @@ -24,27 +24,25 @@ const styles = { }, }; -const BarChartView = props => { - const { - advancedMode, - advancedModeSpec, - field, - data, - direction, - params, - scale, - colors, - axisRoundValue, - tooltip, - tooltipCategory, - tooltipValue, - labels, - labelOverlap, - barSize, - diagonalCategoryAxis, - diagonalValueAxis, - } = props; - +const BarChartView = ({ + advancedMode, + advancedModeSpec, + field, + data, + direction, + params, + scale, + colors, + axisRoundValue, + tooltip, + tooltipCategory, + tooltipValue, + labels, + labelOverlap, + barSize, + diagonalCategoryAxis, + diagonalValueAxis, +}) => { const ref = useRef(null); const [width, setWidth] = useState(0); const [error, setError] = useState(''); diff --git a/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotView.js b/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotView.js index 0d833611b..53ec8ddb5 100644 --- a/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotView.js +++ b/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotView.js @@ -19,21 +19,19 @@ const styles = { }, }; -const BubblePlotView = props => { - const { - advancedMode, - advancedModeSpec, - field, - data, - colors, - params, - flipAxis, - tooltip, - tooltipSource, - tooltipTarget, - tooltipWeight, - } = props; - +const BubblePlotView = ({ + advancedMode, + advancedModeSpec, + field, + data, + colors, + params, + flipAxis, + tooltip, + tooltipSource, + tooltipTarget, + tooltipWeight, +}) => { const ref = useRef(null); const [width, setWidth] = useState(0); const [error, setError] = useState(''); diff --git a/src/app/js/formats/vega-lite/component/cartography/CartographyView.js b/src/app/js/formats/vega-lite/component/cartography/CartographyView.js index 61585c1c7..027d0dec3 100644 --- a/src/app/js/formats/vega-lite/component/cartography/CartographyView.js +++ b/src/app/js/formats/vega-lite/component/cartography/CartographyView.js @@ -21,19 +21,17 @@ const styles = { }, }; -const CartographyView = props => { - const { - advancedMode, - advancedModeSpec, - field, - data, - tooltip, - tooltipCategory, - tooltipValue, - worldPosition, - colorScheme, - } = props; - +const CartographyView = ({ + advancedMode, + advancedModeSpec, + field, + data, + tooltip, + tooltipCategory, + tooltipValue, + worldPosition, + colorScheme, +}) => { const ref = useRef(null); const [width, setWidth] = useState(0); const [error, setError] = useState(''); diff --git a/src/app/js/formats/vega/component/flow-map/FlowMapView.js b/src/app/js/formats/vega/component/flow-map/FlowMapView.js index 5fd08e2b7..e1eeea17f 100644 --- a/src/app/js/formats/vega/component/flow-map/FlowMapView.js +++ b/src/app/js/formats/vega/component/flow-map/FlowMapView.js @@ -22,19 +22,18 @@ const styles = { }, }; -const FlowMapView = props => { - const { - advancedMode, - advancedModeSpec, - p, - field, - data, - tooltip, - tooltipCategory, - tooltipValue, - color, - colorScheme, - } = props; +const FlowMapView = ({ + advancedMode, + advancedModeSpec, + p, + field, + data, + tooltip, + tooltipCategory, + tooltipValue, + color, + colorScheme, +}) => { const ref = useRef(null); const [width, setWidth] = useState(0); const [error, setError] = useState(''); diff --git a/src/app/js/formats/vega/component/radar-chart/RadarChartView.js b/src/app/js/formats/vega/component/radar-chart/RadarChartView.js index 48a9ceefb..15c198f21 100644 --- a/src/app/js/formats/vega/component/radar-chart/RadarChartView.js +++ b/src/app/js/formats/vega/component/radar-chart/RadarChartView.js @@ -20,33 +20,32 @@ const styles = { }, }; -const RadarChartView = props => { - const { - advancedMode, - advancedModeSpec, - field, - colors, - tooltip, - tooltipCategory, - tooltipValue, - scale, - } = props; - - const data = useMemo(() => { - if (!props.data) { - return props.data; +const RadarChartView = ({ + advancedMode, + advancedModeSpec, + field, + data, + colors, + tooltip, + tooltipCategory, + tooltipValue, + scale, +}) => { + const formattedData = useMemo(() => { + if (!data) { + return data; } - const formattedData = { - ...props.data, + const tmpData = { + ...data, }; - formattedData.values.forEach(value => { + tmpData.values.forEach(value => { value.category = 0; }); - return formattedData; - }, [props.data]); + return tmpData; + }, [data]); const ref = useRef(null); const [width, setWidth] = useState(0); @@ -75,10 +74,10 @@ const RadarChartView = props => { specBuilder.setTooltipValue(tooltipValue); specBuilder.setScale(lodexScaleToIdScale(scale)); - return specBuilder.buildSpec(width, data.values.length); + return specBuilder.buildSpec(width, formattedData.values.length); }, [ width, - data.values, + formattedData.values, advancedMode, advancedModeSpec, colors, @@ -108,7 +107,7 @@ const RadarChartView = props => {
From c953b981097a018a32b93fa2219e98d4cf4d6e2b Mon Sep 17 00:00:00 2001 From: AlasDiablo <25723276+AlasDiablo@users.noreply.github.com> Date: Wed, 20 Sep 2023 11:12:22 +0200 Subject: [PATCH 27/37] refactor: convert HeatMapView Component into a FunctionComponent --- .../component/heatmap/HeatMapView.js | 120 +++++++++++------- 1 file changed, 75 insertions(+), 45 deletions(-) diff --git a/src/app/js/formats/vega-lite/component/heatmap/HeatMapView.js b/src/app/js/formats/vega-lite/component/heatmap/HeatMapView.js index 797d1d0eb..a3e434cdb 100644 --- a/src/app/js/formats/vega-lite/component/heatmap/HeatMapView.js +++ b/src/app/js/formats/vega-lite/component/heatmap/HeatMapView.js @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React, { useEffect, useMemo, useRef, useState } from 'react'; import { CustomActionVegaLite } from '../vega-lite-component'; import injectData from '../../../injectData'; import { connect } from 'react-redux'; @@ -6,7 +6,6 @@ import compose from 'recompose/compose'; import HeatMap from '../../models/HeatMap'; import { field as fieldPropTypes } from '../../../../propTypes'; import PropTypes from 'prop-types'; -import ContainerDimensions from 'react-container-dimensions'; import { lodexOrderToIdOrder, VEGA_LITE_DATA_INJECT_TYPE_A, @@ -20,57 +19,88 @@ const styles = { }, }; -class HeatMapView extends Component { - render() { - const { advancedMode, advancedModeSpec, field, data } = this.props; +const HeatMapView = ({ + advancedMode, + advancedModeSpec, + field, + data, + colorScheme, + params, + flipAxis, + tooltip, + tooltipSource, + tooltipTarget, + tooltipWeight, +}) => { + const ref = useRef(null); + const [width, setWidth] = useState(0); + const [error, setError] = useState(''); - // Create a new heat map instance - - const heatMap = new HeatMap(); + const spec = useMemo(() => { + if (advancedMode) { + try { + const advancedSpec = JSON.parse(advancedModeSpec); + return { + ...advancedSpec, + width: width - VEGA_ACTIONS_WIDTH, + }; + } catch (e) { + setError(e.message); + return null; + } + } - // Set all heat map parameter the chosen by the administrator + const specBuilder = new HeatMap(); - heatMap.setColor(this.props.colorScheme.join(' ')); - heatMap.setOrderBy(lodexOrderToIdOrder(this.props.params.orderBy)); - heatMap.flipAxis(this.props.flipAxis); - heatMap.setTooltip(this.props.tooltip); - heatMap.setTooltipCategory(this.props.tooltipSource); - heatMap.setTooltipTarget(this.props.tooltipTarget); - heatMap.setTooltipValue(this.props.tooltipWeight); + specBuilder.setColor(colorScheme.join(' ')); + specBuilder.setOrderBy(lodexOrderToIdOrder(params.orderBy)); + specBuilder.flipAxis(flipAxis); + specBuilder.setTooltip(tooltip); + specBuilder.setTooltipCategory(tooltipSource); + specBuilder.setTooltipTarget(tooltipTarget); + specBuilder.setTooltipValue(tooltipWeight); - let advancedSpec; + return specBuilder.buildSpec(width); + }, [ + width, + advancedMode, + advancedModeSpec, + field, + colorScheme, + params, + flipAxis, + tooltip, + tooltipSource, + tooltipTarget, + tooltipWeight, + ]); - try { - advancedSpec = JSON.parse(advancedModeSpec); - } catch (e) { - return ; + useEffect(() => { + if (!ref.current) { + return; } - // return the finish chart - return ( -
- - {/* Make the chart responsive */} - {({ width }) => { - const spec = advancedMode - ? { - ...advancedSpec, - width: width - VEGA_ACTIONS_WIDTH, - } - : heatMap.buildSpec(width); - return ( - - ); - }} - -
- ); + const resizeObserver = new ResizeObserver(() => { + setWidth(ref.current.offsetWidth); + }); + + resizeObserver.observe(ref.current); + }, [ref.current]); + + if (!spec) { + return ; } -} + + return ( +
+ +
+ ); +}; HeatMapView.propTypes = { field: fieldPropTypes.isRequired, From 3b0988ac9b59d950a062eef041bb6957ad423ce3 Mon Sep 17 00:00:00 2001 From: AlasDiablo <25723276+AlasDiablo@users.noreply.github.com> Date: Wed, 20 Sep 2023 11:12:46 +0200 Subject: [PATCH 28/37] refactor: convert PieChartView Component into a FunctionComponent --- .../component/pie-chart/PieChartView.js | 117 +++++++++++------- 1 file changed, 71 insertions(+), 46 deletions(-) diff --git a/src/app/js/formats/vega-lite/component/pie-chart/PieChartView.js b/src/app/js/formats/vega-lite/component/pie-chart/PieChartView.js index e7792ebe8..55452ddcd 100644 --- a/src/app/js/formats/vega-lite/component/pie-chart/PieChartView.js +++ b/src/app/js/formats/vega-lite/component/pie-chart/PieChartView.js @@ -3,8 +3,7 @@ import PropTypes from 'prop-types'; import compose from 'recompose/compose'; import injectData from '../../../injectData'; import { connect } from 'react-redux'; -import React, { Component } from 'react'; -import ContainerDimensions from 'react-container-dimensions'; +import React, { useEffect, useMemo, useRef, useState } from 'react'; import PieChart from '../../models/PieChart'; import { CustomActionVegaLite } from '../vega-lite-component'; import { VEGA_LITE_DATA_INJECT_TYPE_A } from '../../../chartsUtils'; @@ -17,62 +16,88 @@ const styles = { }, }; -class PieChartView extends Component { - render() { - const { advancedMode, advancedModeSpec, field, data } = this.props; +const PieChartView = ({ + advancedMode, + advancedModeSpec, + field, + data, + tooltip, + tooltipCategory, + tooltipValue, + colors, + labels, +}) => { + const ref = useRef(null); + const [width, setWidth] = useState(0); + const [error, setError] = useState(''); - // Create a new pie chart instance + const spec = useMemo(() => { + if (advancedMode) { + try { + const advancedSpec = JSON.parse(advancedModeSpec); + return { + ...advancedSpec, + width: width - VEGA_ACTIONS_WIDTH, + }; + } catch (e) { + setError(e.message); + return null; + } + } - const pieChart = new PieChart(); + const specBuilder = new PieChart(); // enable the orderBy in vega-lite - let count = 1; - data.values.forEach(e => { - e.order = count++; + data.values.forEach(entry => { + entry.order = count++; }); - // Set all pie chart parameter the chosen by the administrator + specBuilder.setTooltip(tooltip); + specBuilder.setTooltipCategory(tooltipCategory); + specBuilder.setTooltipValue(tooltipValue); + specBuilder.setColor(colors); + specBuilder.setLabels(labels); - pieChart.setTooltip(this.props.tooltip); - pieChart.setTooltipCategory(this.props.tooltipCategory); - pieChart.setTooltipValue(this.props.tooltipValue); - pieChart.setColor(this.props.colors); - pieChart.setLabels(this.props.labels); + return specBuilder.buildSpec(width); + }, [ + width, + advancedMode, + advancedModeSpec, + field, + tooltip, + tooltipCategory, + tooltipValue, + colors, + labels, + ]); - let advancedSpec; - - try { - advancedSpec = JSON.parse(advancedModeSpec); - } catch (e) { - return ; + useEffect(() => { + if (!ref.current) { + return; } - // return the finish chart - return ( -
- {/* Make the chart responsive */} - - {({ width }) => { - const spec = advancedMode - ? { - ...advancedSpec, - width: width - VEGA_ACTIONS_WIDTH, - } - : pieChart.buildSpec(width); - return ( - - ); - }} - -
- ); + const resizeObserver = new ResizeObserver(() => { + setWidth(ref.current.offsetWidth); + }); + + resizeObserver.observe(ref.current); + }, [ref.current]); + + if (!spec) { + return ; } -} + + return ( +
+ +
+ ); +}; PieChartView.propTypes = { field: fieldPropTypes.isRequired, From 5d4720e183fd214ca9b7078fa14e043d822f2353 Mon Sep 17 00:00:00 2001 From: AlasDiablo <25723276+AlasDiablo@users.noreply.github.com> Date: Thu, 21 Sep 2023 09:13:54 +0200 Subject: [PATCH 29/37] fix: roll-back Vega(Lite)Component to avoid side effect and fix null value access --- .../component/bar-chart/BarChartView.js | 7 +- .../component/bubble-plot/BubblePlotView.js | 7 +- .../component/cartography/CartographyView.js | 7 +- .../component/heatmap/HeatMapView.js | 7 +- .../component/pie-chart/PieChartView.js | 7 +- .../vega-lite-component/VegaLiteComponent.js | 83 ++++++++--------- .../vega/component/flow-map/FlowMapView.js | 7 +- .../component/radar-chart/RadarChartView.js | 7 +- .../component/vega-component/VegaComponent.js | 89 ++++++++++--------- 9 files changed, 120 insertions(+), 101 deletions(-) diff --git a/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js b/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js index e5f5a89c7..b93c274b5 100644 --- a/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js +++ b/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js @@ -104,12 +104,15 @@ const BarChartView = ({ ]); useEffect(() => { - if (!ref.current) { + if (!ref || !ref.current) { return; } const resizeObserver = new ResizeObserver(() => { - setWidth(ref.current.offsetWidth); + try { + setWidth(ref.current.offsetWidth); + // eslint-disable-next-line no-empty + } catch (e) {} }); resizeObserver.observe(ref.current); diff --git a/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotView.js b/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotView.js index 53ec8ddb5..360b981a5 100644 --- a/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotView.js +++ b/src/app/js/formats/vega-lite/component/bubble-plot/BubblePlotView.js @@ -76,12 +76,15 @@ const BubblePlotView = ({ ]); useEffect(() => { - if (!ref.current) { + if (!ref || !ref.current) { return; } const resizeObserver = new ResizeObserver(() => { - setWidth(ref.current.offsetWidth); + try { + setWidth(ref.current.offsetWidth); + // eslint-disable-next-line no-empty + } catch (e) {} }); resizeObserver.observe(ref.current); diff --git a/src/app/js/formats/vega-lite/component/cartography/CartographyView.js b/src/app/js/formats/vega-lite/component/cartography/CartographyView.js index 027d0dec3..3d1bd7de1 100644 --- a/src/app/js/formats/vega-lite/component/cartography/CartographyView.js +++ b/src/app/js/formats/vega-lite/component/cartography/CartographyView.js @@ -75,12 +75,15 @@ const CartographyView = ({ ]); useEffect(() => { - if (!ref.current) { + if (!ref || !ref.current) { return; } const resizeObserver = new ResizeObserver(() => { - setWidth(ref.current.offsetWidth); + try { + setWidth(ref.current.offsetWidth); + // eslint-disable-next-line no-empty + } catch (e) {} }); resizeObserver.observe(ref.current); diff --git a/src/app/js/formats/vega-lite/component/heatmap/HeatMapView.js b/src/app/js/formats/vega-lite/component/heatmap/HeatMapView.js index a3e434cdb..9de8f3c9a 100644 --- a/src/app/js/formats/vega-lite/component/heatmap/HeatMapView.js +++ b/src/app/js/formats/vega-lite/component/heatmap/HeatMapView.js @@ -76,12 +76,15 @@ const HeatMapView = ({ ]); useEffect(() => { - if (!ref.current) { + if (!ref || !ref.current) { return; } const resizeObserver = new ResizeObserver(() => { - setWidth(ref.current.offsetWidth); + try { + setWidth(ref.current.offsetWidth); + // eslint-disable-next-line no-empty + } catch (e) {} }); resizeObserver.observe(ref.current); diff --git a/src/app/js/formats/vega-lite/component/pie-chart/PieChartView.js b/src/app/js/formats/vega-lite/component/pie-chart/PieChartView.js index 55452ddcd..b78f6e5e5 100644 --- a/src/app/js/formats/vega-lite/component/pie-chart/PieChartView.js +++ b/src/app/js/formats/vega-lite/component/pie-chart/PieChartView.js @@ -73,12 +73,15 @@ const PieChartView = ({ ]); useEffect(() => { - if (!ref.current) { + if (!ref || !ref.current) { return; } const resizeObserver = new ResizeObserver(() => { - setWidth(ref.current.offsetWidth); + try { + setWidth(ref.current.offsetWidth); + // eslint-disable-next-line no-empty + } catch (e) {} }); resizeObserver.observe(ref.current); diff --git a/src/app/js/formats/vega-lite/component/vega-lite-component/VegaLiteComponent.js b/src/app/js/formats/vega-lite/component/vega-lite-component/VegaLiteComponent.js index 378be62fb..cdc6d634f 100644 --- a/src/app/js/formats/vega-lite/component/vega-lite-component/VegaLiteComponent.js +++ b/src/app/js/formats/vega-lite/component/vega-lite-component/VegaLiteComponent.js @@ -1,29 +1,36 @@ import { Vega } from 'react-vega'; -import React, { useMemo } from 'react'; +import React from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { isAdmin } from '../../../../user'; -import deepClone from 'lodash.clonedeep'; import { VEGA_LITE_DATA_INJECT_TYPE_A, VEGA_LITE_DATA_INJECT_TYPE_B, VEGA_LITE_DATA_INJECT_TYPE_C, } from '../../../chartsUtils'; -import set from 'lodash.set'; +import deepClone from 'lodash.clonedeep'; export const VEGA_ACTIONS_WIDTH = 40; /** * small component use to handle vega lite display - * @param user - * @param injectType - * @param data - * @param spec + * @param props args taken by the component * @returns {*} React-Vega component */ -const CustomActionVegaLite = ({ user, injectType, data, spec }) => { - const actions = useMemo(() => { - const defaultActions = { +function CustomActionVegaLite(props) { + let actions; + if (isAdmin(props.user)) { + actions = { + export: { + svg: true, + png: true, + }, + source: true, + compiled: true, + editor: true, + }; + } else { + actions = { export: { svg: true, png: true, @@ -32,48 +39,34 @@ const CustomActionVegaLite = ({ user, injectType, data, spec }) => { compiled: false, editor: false, }; - if (isAdmin(user)) { - return { - ...defaultActions, - source: true, - compiled: true, - editor: true, - }; - } - return defaultActions; - }, [user]); - - const specWithData = useMemo(() => { - const tmpSpec = deepClone(spec); + } - if (injectType === VEGA_LITE_DATA_INJECT_TYPE_A) { - set(tmpSpec, 'data', data); - return tmpSpec; - } + const spec = props.spec; - if (injectType === VEGA_LITE_DATA_INJECT_TYPE_B) { - tmpSpec.transform.forEach(entry => { - if (entry.lookup === 'id') { - set(entry, 'from.data.values', data.values); + switch (props.injectType) { + case VEGA_LITE_DATA_INJECT_TYPE_A: + spec.data = props.data; + break; + case VEGA_LITE_DATA_INJECT_TYPE_B: + spec.transform.forEach(e => { + if (e.lookup === 'id') { + e.from.data.values = props.data.values; } }); - return tmpSpec; - } - - if (injectType === VEGA_LITE_DATA_INJECT_TYPE_C) { - tmpSpec.transform.forEach(entry => { - if (entry.lookup === 'properties.HASC_2') { - set(entry, 'from.data.values', data.values); + break; + case VEGA_LITE_DATA_INJECT_TYPE_C: + spec.transform.forEach(e => { + if (e.lookup === 'properties.HASC_2') { + e.from.data.values = props.data.values; } }); - return tmpSpec; - } + break; + default: + throw new Error('Invalid data injection type'); + } - return tmpSpec; - }, [injectType, spec, data]); - - return ; -}; + return ; +} /** * Element required in the props diff --git a/src/app/js/formats/vega/component/flow-map/FlowMapView.js b/src/app/js/formats/vega/component/flow-map/FlowMapView.js index e1eeea17f..6cb5963a7 100644 --- a/src/app/js/formats/vega/component/flow-map/FlowMapView.js +++ b/src/app/js/formats/vega/component/flow-map/FlowMapView.js @@ -77,12 +77,15 @@ const FlowMapView = ({ ]); useEffect(() => { - if (!ref.current) { + if (!ref || !ref.current) { return; } const resizeObserver = new ResizeObserver(() => { - setWidth(ref.current.offsetWidth); + try { + setWidth(ref.current.offsetWidth); + // eslint-disable-next-line no-empty + } catch (e) {} }); resizeObserver.observe(ref.current); diff --git a/src/app/js/formats/vega/component/radar-chart/RadarChartView.js b/src/app/js/formats/vega/component/radar-chart/RadarChartView.js index 15c198f21..582bc1667 100644 --- a/src/app/js/formats/vega/component/radar-chart/RadarChartView.js +++ b/src/app/js/formats/vega/component/radar-chart/RadarChartView.js @@ -88,12 +88,15 @@ const RadarChartView = ({ ]); useEffect(() => { - if (!ref.current) { + if (!ref || !ref.current) { return; } const resizeObserver = new ResizeObserver(() => { - setWidth(ref.current.offsetWidth); + try { + setWidth(ref.current.offsetWidth); + // eslint-disable-next-line no-empty + } catch (e) {} }); resizeObserver.observe(ref.current); diff --git a/src/app/js/formats/vega/component/vega-component/VegaComponent.js b/src/app/js/formats/vega/component/vega-component/VegaComponent.js index fd5b89f5d..7421f75d7 100644 --- a/src/app/js/formats/vega/component/vega-component/VegaComponent.js +++ b/src/app/js/formats/vega/component/vega-component/VegaComponent.js @@ -1,5 +1,5 @@ import { Vega } from 'react-vega'; -import React, { useMemo } from 'react'; +import React from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { isAdmin } from '../../../../user'; @@ -8,16 +8,26 @@ import { VEGA_DATA_INJECT_TYPE_A, VEGA_DATA_INJECT_TYPE_B, } from '../../../chartsUtils'; -import set from 'lodash.set'; /** * small component use to handle vega lite display * @param props args taken by the component * @returns {*} React-Vega component */ -const CustomActionVega = ({ user, data, spec, injectType }) => { - const actions = useMemo(() => { - const defaultActions = { +function CustomActionVega(props) { + let actions; + if (isAdmin(props.user)) { + actions = { + export: { + svg: true, + png: true, + }, + source: true, + compiled: true, + editor: true, + }; + } else { + actions = { export: { svg: true, png: true, @@ -26,48 +36,43 @@ const CustomActionVega = ({ user, data, spec, injectType }) => { compiled: false, editor: false, }; - if (isAdmin(user)) { - return { - ...defaultActions, - source: true, - compiled: true, - editor: true, - }; - } - return defaultActions; - }, [user]); + } - const specWithData = useMemo(() => { - const tmpSpec = deepClone(spec); + const spec = props.spec; - if (injectType === VEGA_DATA_INJECT_TYPE_A) { - tmpSpec.data.forEach(entry => { - if (entry.name === 'table') { - set(entry, 'values', data.values); + switch (props.injectType) { + case VEGA_DATA_INJECT_TYPE_A: + spec.data.forEach(e => { + if (e.name === 'table') { + e.values = props.data.values; } }); - return tmpSpec; - } + break; + case VEGA_DATA_INJECT_TYPE_B: + { + let data = { + values: [], + }; + props.data.values.forEach(e => { + data.values.push({ + origin: e.source, + destination: e.target, + count: e.weight, + }); + }); + spec.data.forEach(e => { + if (e.name === 'routes' || e.name === 'link_data') { + e.values = data.values; + } + }); + } + break; + default: + throw new Error('Invalid data injection type'); + } - if (injectType === VEGA_DATA_INJECT_TYPE_B) { - const mappedData = data.values.map(entry => ({ - origin: entry.source, - destination: entry.target, - count: entry.weight, - })); - tmpSpec.data.forEach(entry => { - if (entry.name === 'routes' || entry.name === 'link_data') { - set(entry, 'values', mappedData); - } - }); - return tmpSpec; - } - - return tmpSpec; - }, [injectType, spec, data]); - - return ; -}; + return ; +} /** * Element required in the props From 55ed6c975a6f16741053fea6fb01749727ddd807 Mon Sep 17 00:00:00 2001 From: AlasDiablo <25723276+AlasDiablo@users.noreply.github.com> Date: Thu, 21 Sep 2023 09:18:11 +0200 Subject: [PATCH 30/37] test: update test to take in cause ResizeObserver error caused by rendering --- cypress/integration/graph_page.spec.js | 7 +++++++ cypress/integration/model.spec.js | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/cypress/integration/graph_page.spec.js b/cypress/integration/graph_page.spec.js index deee692c7..68d72a16a 100644 --- a/cypress/integration/graph_page.spec.js +++ b/cypress/integration/graph_page.spec.js @@ -6,6 +6,13 @@ import * as searchDrawer from '../support/searchDrawer'; describe('Graph Page', () => { beforeEach(() => { + // ResizeObserver don't like when the app has to many renders / re-renders + // and throw an exception to say I wait for the next paint + // https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver#observation_errors + cy.on('uncaught:exception', error => { + return !error.message.includes('ResizeObserver'); + }); + teardown(); menu.openAdvancedDrawer(); menu.goToAdminDashboard(); diff --git a/cypress/integration/model.spec.js b/cypress/integration/model.spec.js index 08b993ce3..d3cf590c1 100644 --- a/cypress/integration/model.spec.js +++ b/cypress/integration/model.spec.js @@ -9,6 +9,13 @@ import * as searchDrawer from '../support/searchDrawer'; describe('Model Page', () => { describe('handling old models', () => { beforeEach(() => { + // ResizeObserver don't like when the app has to many renders / re-renders + // and throw an exception to say I wait for the next paint + // https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver#observation_errors + cy.on('uncaught:exception', error => { + return !error.message.includes('ResizeObserver'); + }); + teardown(); menu.openAdvancedDrawer(); menu.goToAdminDashboard(); From 3e181e1f77fdc047438128c6bbd6e05e57f435af Mon Sep 17 00:00:00 2001 From: AlasDiablo <25723276+AlasDiablo@users.noreply.github.com> Date: Tue, 26 Sep 2023 08:26:31 +0200 Subject: [PATCH 31/37] docs: fix typo --- src/app/js/formats/vega-lite/models/BarChart.js | 2 +- src/app/js/formats/vega-lite/models/HeatMap.js | 2 +- src/app/js/formats/vega-lite/models/PieChart.js | 2 +- src/app/js/formats/vega/models/FlowMap.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/js/formats/vega-lite/models/BarChart.js b/src/app/js/formats/vega-lite/models/BarChart.js index 139b3ffd7..9a3fe2793 100644 --- a/src/app/js/formats/vega-lite/models/BarChart.js +++ b/src/app/js/formats/vega-lite/models/BarChart.js @@ -174,7 +174,7 @@ class BarChart extends BasicChart { } /** - * Function use for rebuild the edited spec + * Rebuild the edited spec * @param widthIn{number | null} * @param dataNumber{number | null} */ diff --git a/src/app/js/formats/vega-lite/models/HeatMap.js b/src/app/js/formats/vega-lite/models/HeatMap.js index 0382b4ea3..61d0d4fdf 100644 --- a/src/app/js/formats/vega-lite/models/HeatMap.js +++ b/src/app/js/formats/vega-lite/models/HeatMap.js @@ -113,7 +113,7 @@ class HeatMap extends BasicChart { } /** - * Function use for rebuild the edited spec + * Rebuild the edited spec * @param widthIn{number | null} */ buildSpec(widthIn = null) { diff --git a/src/app/js/formats/vega-lite/models/PieChart.js b/src/app/js/formats/vega-lite/models/PieChart.js index 5d4f2a888..29b983bdf 100644 --- a/src/app/js/formats/vega-lite/models/PieChart.js +++ b/src/app/js/formats/vega-lite/models/PieChart.js @@ -22,7 +22,7 @@ class PieChart extends BasicChart { } /** - * Function use for rebuild the edited spec + * Rebuild the edited spec * @param widthIn{number | null} */ buildSpec(widthIn = null) { diff --git a/src/app/js/formats/vega/models/FlowMap.js b/src/app/js/formats/vega/models/FlowMap.js index 5558e4603..0a2d5c86c 100644 --- a/src/app/js/formats/vega/models/FlowMap.js +++ b/src/app/js/formats/vega/models/FlowMap.js @@ -5,7 +5,7 @@ import deepClone from 'lodash.clonedeep'; import BasicChartVG from './BasicChartVG'; /** - * Class use for create radar chart spec + * Class use for create "flow map" chart spec */ class FlowMap extends BasicChartVG { /** From 14bfd05ae9af3617c85d2e0894b39e46b7968261 Mon Sep 17 00:00:00 2001 From: AlasDiablo <25723276+AlasDiablo@users.noreply.github.com> Date: Tue, 26 Sep 2023 08:28:15 +0200 Subject: [PATCH 32/37] docs: fix typo --- src/app/js/formats/vega-lite/models/Cartography.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/js/formats/vega-lite/models/Cartography.js b/src/app/js/formats/vega-lite/models/Cartography.js index e505becb4..533d582d8 100644 --- a/src/app/js/formats/vega-lite/models/Cartography.js +++ b/src/app/js/formats/vega-lite/models/Cartography.js @@ -27,7 +27,7 @@ class Cartography extends BasicChart { } /** - * Function use for rebuild the edited spec + * Rebuild the edited spec * @param widthIn{number | null} */ buildSpec(widthIn = null) { From c49a224cc25bbcd2b165bdd60599f23afd1e4229 Mon Sep 17 00:00:00 2001 From: AlasDiablo <25723276+AlasDiablo@users.noreply.github.com> Date: Mon, 2 Oct 2023 09:24:29 +0200 Subject: [PATCH 33/37] fix: update docs and refactor some code --- cypress/integration/graph_page.spec.js | 4 ++-- cypress/integration/model.spec.js | 4 ++-- src/app/js/formats/shared/VegaAdvancedMode.js | 2 ++ .../formats/vega-lite/component/bar-chart/BarChartView.js | 7 ++----- .../component/vega-lite-component/VegaLiteComponent.js | 2 +- src/app/js/formats/vega/models/FlowMap.js | 2 +- 6 files changed, 10 insertions(+), 11 deletions(-) diff --git a/cypress/integration/graph_page.spec.js b/cypress/integration/graph_page.spec.js index 68d72a16a..b7dc8f270 100644 --- a/cypress/integration/graph_page.spec.js +++ b/cypress/integration/graph_page.spec.js @@ -6,8 +6,8 @@ import * as searchDrawer from '../support/searchDrawer'; describe('Graph Page', () => { beforeEach(() => { - // ResizeObserver don't like when the app has to many renders / re-renders - // and throw an exception to say I wait for the next paint + // ResizeObserver doesn't like when the app has to many renders / re-renders + // and throws an exception to say, "I wait for the next paint" // https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver#observation_errors cy.on('uncaught:exception', error => { return !error.message.includes('ResizeObserver'); diff --git a/cypress/integration/model.spec.js b/cypress/integration/model.spec.js index 1c7f8cbc5..635833ba4 100644 --- a/cypress/integration/model.spec.js +++ b/cypress/integration/model.spec.js @@ -7,8 +7,8 @@ import * as searchDrawer from '../support/searchDrawer'; describe('Model Page', () => { describe('handling old models', () => { beforeEach(() => { - // ResizeObserver don't like when the app has to many renders / re-renders - // and throw an exception to say I wait for the next paint + // ResizeObserver doesn't like when the app has to many renders / re-renders + // and throws an exception to say, "I wait for the next paint" // https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver#observation_errors cy.on('uncaught:exception', error => { return !error.message.includes('ResizeObserver'); diff --git a/src/app/js/formats/shared/VegaAdvancedMode.js b/src/app/js/formats/shared/VegaAdvancedMode.js index 03eb234f9..5654bf0bb 100644 --- a/src/app/js/formats/shared/VegaAdvancedMode.js +++ b/src/app/js/formats/shared/VegaAdvancedMode.js @@ -61,6 +61,8 @@ const VegaAdvancedMode = ({ p, value, onChange, onClear }) => { verticalAlign: 'text-bottom', }} /> + {/* TODO: Do a clean ux to display error message */} + {p('vega_json_error')} {error.message} ) : null} diff --git a/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js b/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js index b93c274b5..4b7bf7a7d 100644 --- a/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js +++ b/src/app/js/formats/vega-lite/component/bar-chart/BarChartView.js @@ -5,10 +5,9 @@ import compose from 'recompose/compose'; import injectData from '../../../injectData'; import { field as fieldPropTypes } from '../../../../propTypes'; import { - AXIS_HORIZONTAL, - AXIS_VERTICAL, AXIS_X, AXIS_Y, + lodexDirectionToIdDirection, lodexOrderToIdOrder, lodexScaleToIdScale, VEGA_LITE_DATA_INJECT_TYPE_A, @@ -63,9 +62,7 @@ const BarChartView = ({ const specBuilder = new BarChart(); - specBuilder.setAxisDirection( - direction === 'vertical' ? AXIS_VERTICAL : AXIS_HORIZONTAL, - ); + specBuilder.setAxisDirection(lodexDirectionToIdDirection(direction)); specBuilder.setOrderBy(lodexOrderToIdOrder(params.orderBy)); specBuilder.setScale(lodexScaleToIdScale(scale)); diff --git a/src/app/js/formats/vega-lite/component/vega-lite-component/VegaLiteComponent.js b/src/app/js/formats/vega-lite/component/vega-lite-component/VegaLiteComponent.js index cdc6d634f..60c1a72e5 100644 --- a/src/app/js/formats/vega-lite/component/vega-lite-component/VegaLiteComponent.js +++ b/src/app/js/formats/vega-lite/component/vega-lite-component/VegaLiteComponent.js @@ -2,13 +2,13 @@ import { Vega } from 'react-vega'; import React from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; +import deepClone from 'lodash.clonedeep'; import { isAdmin } from '../../../../user'; import { VEGA_LITE_DATA_INJECT_TYPE_A, VEGA_LITE_DATA_INJECT_TYPE_B, VEGA_LITE_DATA_INJECT_TYPE_C, } from '../../../chartsUtils'; -import deepClone from 'lodash.clonedeep'; export const VEGA_ACTIONS_WIDTH = 40; diff --git a/src/app/js/formats/vega/models/FlowMap.js b/src/app/js/formats/vega/models/FlowMap.js index 0a2d5c86c..3753fd886 100644 --- a/src/app/js/formats/vega/models/FlowMap.js +++ b/src/app/js/formats/vega/models/FlowMap.js @@ -5,7 +5,7 @@ import deepClone from 'lodash.clonedeep'; import BasicChartVG from './BasicChartVG'; /** - * Class use for create "flow map" chart spec + * Class use for create flow map chart spec */ class FlowMap extends BasicChartVG { /** From c04426c0fec75ee5cc5da53006955c218ead0071 Mon Sep 17 00:00:00 2001 From: AlasDiablo <25723276+AlasDiablo@users.noreply.github.com> Date: Mon, 2 Oct 2023 10:04:45 +0200 Subject: [PATCH 34/37] feat: make clean error message --- src/app/custom/translations.tsv | 2 + src/app/js/formats/shared/VegaAdvancedMode.js | 47 ++++++++++++++----- 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/src/app/custom/translations.tsv b/src/app/custom/translations.tsv index a30a6cf31..ee40d50bd 100644 --- a/src/app/custom/translations.tsv +++ b/src/app/custom/translations.tsv @@ -960,3 +960,5 @@ "r-close-by_description" "Is used to create the graph aster plot." "Est utilisée pour créer le graphique aster plot." regenerate_vega_lite_spec Regenerate Vega Lite specifications Régénérer la spécification Vega Lite regenerate_vega_spec Regenerate Vega specifications Régénérer la spécification Vega +vega_json_error The json syntax of Vega Lite specification is wrong! La syntaxe json de la spécification Vega Lite est erroné ! +vega_json_error_raw Raw json error: Erreur json brute : diff --git a/src/app/js/formats/shared/VegaAdvancedMode.js b/src/app/js/formats/shared/VegaAdvancedMode.js index 5654bf0bb..2089bc146 100644 --- a/src/app/js/formats/shared/VegaAdvancedMode.js +++ b/src/app/js/formats/shared/VegaAdvancedMode.js @@ -8,6 +8,30 @@ import isEqual from 'lodash.isequal'; import { polyglot as polyglotPropTypes } from '../../propTypes'; +const styles = { + error: { + container: { + marginLeft: 'auto', + marginRight: 'auto', + }, + message: { + container: { + display: 'flex', + flexDirection: 'row', + }, + icon: { + marginTop: 'auto', + marginBottom: 'auto', + marginRight: '10px', + }, + message: { + borderLeft: 'solid 1px red', + paddingLeft: '10px', + }, + }, + }, +}; + const VegaAdvancedMode = ({ p, value, onChange, onClear }) => { const [currentValue, setCurrentValue] = useState(value || '{}'); const [error, setError] = useState(null); @@ -53,17 +77,18 @@ const VegaAdvancedMode = ({ p, value, onChange, onClear }) => { {p.t('regenerate_vega_lite_spec')} {error ? ( - - - {/* TODO: Do a clean ux to display error message */} - {p('vega_json_error')} - {error.message} + +
+
+ +
+
+

{p.t('vega_json_error')}

+

+ {p.t('vega_json_error_raw')} {error.message} +

+
+
) : null} Date: Mon, 2 Oct 2023 14:19:29 +0200 Subject: [PATCH 35/37] refactor: change error messages to increase user experience --- src/app/custom/translations.tsv | 3 +- src/app/js/formats/shared/VegaAdvancedMode.js | 104 ++++++++++++++---- 2 files changed, 81 insertions(+), 26 deletions(-) diff --git a/src/app/custom/translations.tsv b/src/app/custom/translations.tsv index ee40d50bd..c7d4c238f 100644 --- a/src/app/custom/translations.tsv +++ b/src/app/custom/translations.tsv @@ -960,5 +960,4 @@ "r-close-by_description" "Is used to create the graph aster plot." "Est utilisée pour créer le graphique aster plot." regenerate_vega_lite_spec Regenerate Vega Lite specifications Régénérer la spécification Vega Lite regenerate_vega_spec Regenerate Vega specifications Régénérer la spécification Vega -vega_json_error The json syntax of Vega Lite specification is wrong! La syntaxe json de la spécification Vega Lite est erroné ! -vega_json_error_raw Raw json error: Erreur json brute : +vega_json_error The json syntax of Vega Lite specification is wrong! La syntaxe json de la spécification Vega Lite est erronée ! diff --git a/src/app/js/formats/shared/VegaAdvancedMode.js b/src/app/js/formats/shared/VegaAdvancedMode.js index 2089bc146..08d17b0d3 100644 --- a/src/app/js/formats/shared/VegaAdvancedMode.js +++ b/src/app/js/formats/shared/VegaAdvancedMode.js @@ -1,7 +1,7 @@ import React, { useEffect, useMemo, useState } from 'react'; import translate from 'redux-polyglot/translate'; import PropTypes from 'prop-types'; -import { Button, TextField, Typography } from '@mui/material'; +import { Button, TextField, Tooltip } from '@mui/material'; import ReportProblemIcon from '@mui/icons-material/ReportProblem'; import CachedIcon from '@mui/icons-material/Cached'; import isEqual from 'lodash.isequal'; @@ -12,7 +12,8 @@ const styles = { error: { container: { marginLeft: 'auto', - marginRight: 'auto', + marginRight: '24px', + color: 'red', }, message: { container: { @@ -32,6 +33,32 @@ const styles = { }, }; +const VegaAdvancedModeError = ({ message, p, isTooltip }) => { + return ( +
+ {!isTooltip ? ( +
+ +
+ ) : null} +
+

{p.t('vega_json_error')}

+

{message}

+
+
+ ); +}; + +VegaAdvancedModeError.defaultProps = { + isTooltip: false, +}; + +VegaAdvancedModeError.propTypes = { + p: polyglotPropTypes.isRequired, + message: PropTypes.string.isRequired, + isTooltip: PropTypes.bool, +}; + const VegaAdvancedMode = ({ p, value, onChange, onClear }) => { const [currentValue, setCurrentValue] = useState(value || '{}'); const [error, setError] = useState(null); @@ -68,35 +95,64 @@ const VegaAdvancedMode = ({ p, value, onChange, onClear }) => { return ( <> - +
+
- {p.t('regenerate_vega_lite_spec')} - - {error ? ( - -
-
- -
-
-

{p.t('vega_json_error')}

-

- {p.t('vega_json_error_raw')} {error.message} -

-
-
-
- ) : null} + > + {error ? ( + + } + > + + + ) : null} +
+
+ {error ? ( +
+ +
+ ) : null} ); }; From f35b513e2d0a6befa89e6f7337e96be46530a32d Mon Sep 17 00:00:00 2001 From: AlasDiablo <25723276+AlasDiablo@users.noreply.github.com> Date: Wed, 4 Oct 2023 07:42:33 +0200 Subject: [PATCH 36/37] refactor: remove abstract components, enable json saving when error --- src/app/js/formats/shared/VegaAdvancedMode.js | 51 +++++++------------ 1 file changed, 17 insertions(+), 34 deletions(-) diff --git a/src/app/js/formats/shared/VegaAdvancedMode.js b/src/app/js/formats/shared/VegaAdvancedMode.js index 08d17b0d3..e4261f20a 100644 --- a/src/app/js/formats/shared/VegaAdvancedMode.js +++ b/src/app/js/formats/shared/VegaAdvancedMode.js @@ -33,40 +33,17 @@ const styles = { }, }; -const VegaAdvancedModeError = ({ message, p, isTooltip }) => { - return ( -
- {!isTooltip ? ( -
- -
- ) : null} -
-

{p.t('vega_json_error')}

-

{message}

-
-
- ); -}; - -VegaAdvancedModeError.defaultProps = { - isTooltip: false, -}; - -VegaAdvancedModeError.propTypes = { - p: polyglotPropTypes.isRequired, - message: PropTypes.string.isRequired, - isTooltip: PropTypes.bool, -}; - const VegaAdvancedMode = ({ p, value, onChange, onClear }) => { const [currentValue, setCurrentValue] = useState(value || '{}'); const [error, setError] = useState(null); const valueObject = useMemo(() => { try { - return JSON.parse(value); + const json = JSON.parse(value); + setError(null); + return json; } catch (e) { + setError(e); return null; } }, [value]); @@ -83,7 +60,6 @@ const VegaAdvancedMode = ({ p, value, onChange, onClear }) => { }, [currentValue]); useEffect(() => { - if (valueObject === null || currentValueObject === null) return; if (!isEqual(currentValueObject, valueObject)) { onChange(currentValue); } @@ -125,11 +101,10 @@ const VegaAdvancedMode = ({ p, value, onChange, onClear }) => { {error ? ( +
+

{p.t('vega_json_error')}

+

{error.message}

+
} > { /> {error ? (
- +
+
+ +
+
+

{p.t('vega_json_error')}

+

{error.message}

+
+
) : null} From 32c158f29a9c82831f5cfc859ec542b047d9b80b Mon Sep 17 00:00:00 2001 From: AlasDiablo <25723276+AlasDiablo@users.noreply.github.com> Date: Mon, 9 Oct 2023 10:00:49 +0200 Subject: [PATCH 37/37] docs: remove comments --- src/app/js/formats/vega-lite/models/BarChart.js | 3 --- src/app/js/formats/vega-lite/models/BasicChart.js | 3 --- src/app/js/formats/vega-lite/models/Cartography.js | 3 --- src/app/js/formats/vega-lite/models/HeatMap.js | 3 --- src/app/js/formats/vega-lite/models/PieChart.js | 3 --- src/app/js/formats/vega/models/FlowMap.js | 3 --- src/app/js/formats/vega/models/RadarChart.js | 3 --- 7 files changed, 21 deletions(-) diff --git a/src/app/js/formats/vega-lite/models/BarChart.js b/src/app/js/formats/vega-lite/models/BarChart.js index 9a3fe2793..169a5b897 100644 --- a/src/app/js/formats/vega-lite/models/BarChart.js +++ b/src/app/js/formats/vega-lite/models/BarChart.js @@ -18,9 +18,6 @@ import barChartVL from './json/bar_chart.vl.json'; import barChartLabelsVL from './json/bar_chart_labels.vl.json'; import deepClone from 'lodash.clonedeep'; -/** - * Class used to create bar chart spec - */ class BarChart extends BasicChart { /** * Init all required parameters diff --git a/src/app/js/formats/vega-lite/models/BasicChart.js b/src/app/js/formats/vega-lite/models/BasicChart.js index 64fac50c2..0a4e93e69 100644 --- a/src/app/js/formats/vega-lite/models/BasicChart.js +++ b/src/app/js/formats/vega-lite/models/BasicChart.js @@ -1,8 +1,5 @@ import { MULTICHROMATIC_DEFAULT_COLORSET } from '../../colorUtils'; -/** - * Very basic impl of the vega lite charts (common class for all chart) - */ class BasicChart { /** * Init all required parameters diff --git a/src/app/js/formats/vega-lite/models/Cartography.js b/src/app/js/formats/vega-lite/models/Cartography.js index 533d582d8..76cc8fd51 100644 --- a/src/app/js/formats/vega-lite/models/Cartography.js +++ b/src/app/js/formats/vega-lite/models/Cartography.js @@ -4,9 +4,6 @@ import { VEGA_ACTIONS_WIDTH } from '../component/vega-lite-component/VegaLiteCom import cartographyVL from './json/cartography.vl.json'; import deepClone from 'lodash.clonedeep'; -/** - * Class used to create cartography spec - */ class Cartography extends BasicChart { /** * Init all required parameters diff --git a/src/app/js/formats/vega-lite/models/HeatMap.js b/src/app/js/formats/vega-lite/models/HeatMap.js index 61d0d4fdf..f90270ade 100644 --- a/src/app/js/formats/vega-lite/models/HeatMap.js +++ b/src/app/js/formats/vega-lite/models/HeatMap.js @@ -3,9 +3,6 @@ import { LABEL_ASC, LABEL_DESC } from '../../chartsUtils'; import heatmapVL from './json/heatmap.vl.json'; import deepClone from 'lodash.clonedeep'; -/** - * Class used to create heatmap spec - */ class HeatMap extends BasicChart { /** * Init all required parameters diff --git a/src/app/js/formats/vega-lite/models/PieChart.js b/src/app/js/formats/vega-lite/models/PieChart.js index 29b983bdf..8b027390e 100644 --- a/src/app/js/formats/vega-lite/models/PieChart.js +++ b/src/app/js/formats/vega-lite/models/PieChart.js @@ -3,9 +3,6 @@ import pieChartVL from './json/pie_chart.vl.json'; import pieChartLabelsVL from './json/pie_chart_labels.vl.json'; import deepClone from 'lodash.clonedeep'; -/** - * Class used to create pie chart spec - */ class PieChart extends BasicChart { /** * Init all required parameters diff --git a/src/app/js/formats/vega/models/FlowMap.js b/src/app/js/formats/vega/models/FlowMap.js index 3753fd886..ec165d73c 100644 --- a/src/app/js/formats/vega/models/FlowMap.js +++ b/src/app/js/formats/vega/models/FlowMap.js @@ -4,9 +4,6 @@ import flowMapVG from './json/flow_map.vg.json'; import deepClone from 'lodash.clonedeep'; import BasicChartVG from './BasicChartVG'; -/** - * Class use for create flow map chart spec - */ class FlowMap extends BasicChartVG { /** * Init all required parameters diff --git a/src/app/js/formats/vega/models/RadarChart.js b/src/app/js/formats/vega/models/RadarChart.js index ccb3ea553..112c3b5fa 100644 --- a/src/app/js/formats/vega/models/RadarChart.js +++ b/src/app/js/formats/vega/models/RadarChart.js @@ -4,9 +4,6 @@ import radarChartVG from './json/radar_chart.vg.json'; import deepClone from 'lodash.clonedeep'; import BasicChartVG from './BasicChartVG'; -/** - * Class use for create radar chart spec - */ class RadarChart extends BasicChartVG { /** * Init all required parameters