From cb3510792da2efed1064039690c0a979624dc55f Mon Sep 17 00:00:00 2001 From: Miu Razvan Date: Thu, 20 Nov 2025 17:54:51 +0200 Subject: [PATCH 1/3] fix: add back filters feature --- src/PlotlyComponent/PlotlyComponent.jsx | 40 ++++++++----------- src/PlotlyEditor/PlotlyEditor.jsx | 15 +++++-- src/helpers/transforms.js | 53 +++++++++++++++++++++++++ src/less/global.less | 7 ---- src/less/plotly.less | 16 ++++++++ 5 files changed, 97 insertions(+), 34 deletions(-) create mode 100644 src/helpers/transforms.js diff --git a/src/PlotlyComponent/PlotlyComponent.jsx b/src/PlotlyComponent/PlotlyComponent.jsx index 0911e5fd..bd7a5b81 100644 --- a/src/PlotlyComponent/PlotlyComponent.jsx +++ b/src/PlotlyComponent/PlotlyComponent.jsx @@ -18,6 +18,7 @@ import { updateTrace, updateDataSources, } from '@eeacms/volto-plotlycharts/helpers/plotly'; +import { applyFilters } from '@eeacms/volto-plotlycharts/helpers/transforms'; import { Toolbar } from '@eeacms/volto-plotlycharts/Utils'; import Plot from './Plot'; import Placeholder from './Placeholder'; @@ -112,40 +113,28 @@ function UnconnectedPlotlyComponent(props) { [provider_data, value.dataSources, selfProvided], ); + const filteredDataSources = useMemo( + () => applyFilters(dataSources, filters), + [dataSources, filters], + ); + const data = useMemo(() => { return (value.data || []).reduce((acc, trace) => { const updatedTrace = updateDataSources( updateTrace(trace), - dataSources, + filteredDataSources, constants.TRACE_SRC_ATTRIBUTES, ); - filters.forEach((filter) => { - if (!updatedTrace.transforms) { - updatedTrace.transforms = []; - } - updatedTrace.transforms.push({ - type: 'filter', - target: dataSources[filter.field], - targetsrc: filter.field, - meta: { - columnNames: { - target: filter.field, - }, - }, - value: filter.data?.value || null, - }); - }); - acc.push(updatedTrace); return acc; }, []); - }, [value.data, dataSources, filters, constants.TRACE_SRC_ATTRIBUTES]); + }, [value.data, filteredDataSources, constants.TRACE_SRC_ATTRIBUTES]); const layout = useMemo(() => { const baseLayout = updateDataSources( value.layout || {}, - dataSources, + filteredDataSources, constants.LAYOUT_SRC_ATTRIBUTES, ); @@ -159,7 +148,12 @@ function UnconnectedPlotlyComponent(props) { } return baseLayout; - }, [value.layout, dataSources, constants.LAYOUT_SRC_ATTRIBUTES, mobile]); + }, [ + value.layout, + filteredDataSources, + constants.LAYOUT_SRC_ATTRIBUTES, + mobile, + ]); const defaultHeight = useMemo(() => { return height || layout._height || layout.height || 450; @@ -174,13 +168,13 @@ function UnconnectedPlotlyComponent(props) { ...props.data.visualization, data, layout, - dataSources, + dataSources: filteredDataSources, columns: value.columns?.map((column) => column.key) || [], }, } : {}), }; - }, [props.data, data, layout, dataSources, value.columns]); + }, [props.data, data, layout, filteredDataSources, value.columns]); // Define the core scale update logic as a separate function const updateScaleCore = useCallback(() => { diff --git a/src/PlotlyEditor/PlotlyEditor.jsx b/src/PlotlyEditor/PlotlyEditor.jsx index 4e2ec3e3..8d51d344 100644 --- a/src/PlotlyEditor/PlotlyEditor.jsx +++ b/src/PlotlyEditor/PlotlyEditor.jsx @@ -19,11 +19,13 @@ import { updateTrace, updateDataSources, } from '@eeacms/volto-plotlycharts/helpers/plotly'; +import {} from '@eeacms/volto-plotlycharts/helpers/transforms'; import { TemplateSelector } from './widgets'; import DefaultEditor from './DefaultEditor'; import chartHelp from './chartHelp.json'; +import { applyFilters } from '../helpers/transforms'; const config = { editable: false, displayModeBar: false, responsive: true }; @@ -77,6 +79,11 @@ const UnconnectedPlotlyEditor = forwardRef((props, ref) => { [provider_data, value.dataSources], ); + const filteredDataSources = useMemo( + () => applyFilters(dataSources, value.filters), + [dataSources, value.filters], + ); + const dataSourceOptions = useMemo( () => Object.keys(dataSources).map((name) => ({ @@ -90,22 +97,22 @@ const UnconnectedPlotlyEditor = forwardRef((props, ref) => { return (value.data || []).reduce((acc, trace) => { const updatedTrace = updateDataSources( updateTrace(trace), - dataSources, + filteredDataSources, TRACE_SRC_ATTRIBUTES, ); acc.push(updatedTrace); return acc; }, []); - }, [value.data, dataSources, TRACE_SRC_ATTRIBUTES]); + }, [value.data, filteredDataSources, TRACE_SRC_ATTRIBUTES]); const layout = useMemo(() => { return updateDataSources( value.layout || {}, - dataSources, + filteredDataSources, LAYOUT_SRC_ATTRIBUTES, ); - }, [value.layout, dataSources, LAYOUT_SRC_ATTRIBUTES]); + }, [value.layout, filteredDataSources, LAYOUT_SRC_ATTRIBUTES]); const ctx = useMemo( () => ({ diff --git a/src/helpers/transforms.js b/src/helpers/transforms.js new file mode 100644 index 00000000..0143566e --- /dev/null +++ b/src/helpers/transforms.js @@ -0,0 +1,53 @@ +import { cloneDeep, keys, mapValues } from 'lodash'; + +export const applyFilters = (dataSources, filters) => { + // Early return if no filters or empty dataSources + if ( + !filters || + !Array.isArray(filters) || + filters.length === 0 || + !dataSources + ) { + return dataSources; + } + + // Clone to avoid mutating the original + const clonedDataSources = cloneDeep(dataSources); + + // Find the first key with data to determine indices + const firstKey = keys(clonedDataSources)[0]; + if (!firstKey || !Array.isArray(clonedDataSources[firstKey])) { + return clonedDataSources; + } + + // Collect indices that pass all filters + const okIndexes = []; + + (clonedDataSources[firstKey] || []).forEach((_, index) => { + let passesAllFilters = true; + + // Check each filter against the current index + for (const filter of filters) { + const filterValue = filter.data?.value || filter.defaultValue; + if ( + filterValue && + clonedDataSources[filter.field] && + clonedDataSources[filter.field][index] !== filterValue + ) { + passesAllFilters = false; + break; // Optimization: exit early once we know it fails + } + } + + if (passesAllFilters) { + okIndexes.push(index); + } + }); + + // Apply the filter to all data arrays + return mapValues(clonedDataSources, (values) => + Array.isArray(values) + ? values.filter((_, index) => okIndexes.includes(index)) + : values, + ); +}; diff --git a/src/less/global.less b/src/less/global.less index 8197fc78..f4caa7c8 100644 --- a/src/less/global.less +++ b/src/less/global.less @@ -64,13 +64,6 @@ // } // } -.plotly-component.filters_on_top { - .visualization-filters { - display: inline-block; - min-width: 200px; - } -} - .block.plotly_chart .block:not(.inner)::before { z-index: -1; // fix not clickable editor button } diff --git a/src/less/plotly.less b/src/less/plotly.less index 2bab8f8f..28d2b9f1 100644 --- a/src/less/plotly.less +++ b/src/less/plotly.less @@ -47,9 +47,25 @@ } .visualization-filters { + display: flex; + flex-flow: column; + row-gap: 1rem; margin-bottom: 1rem; } + &.filters_on_top { + .visualization-filters { + @media only screen and (min-width: 768px) { + flex-flow: row; + column-gap: 1rem; + + .field { + min-width: 160px; + } + } + } + } + &:not(.mobile) { &.filters_on_right { .visualization { From 76c3cfd9370adc38548237c7cca4820ff0a4eeb6 Mon Sep 17 00:00:00 2001 From: eea-jenkins Date: Thu, 20 Nov 2025 16:57:45 +0100 Subject: [PATCH 2/3] style: Automated code fix --- src/less/plotly.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/less/plotly.less b/src/less/plotly.less index 28d2b9f1..e8830044 100644 --- a/src/less/plotly.less +++ b/src/less/plotly.less @@ -49,8 +49,8 @@ .visualization-filters { display: flex; flex-flow: column; - row-gap: 1rem; margin-bottom: 1rem; + row-gap: 1rem; } &.filters_on_top { From 686afc90e5c62126b68dba197bea381e0a89951d Mon Sep 17 00:00:00 2001 From: EEA Jenkins <@users.noreply.github.com> Date: Thu, 20 Nov 2025 16:05:03 +0000 Subject: [PATCH 3/3] Automated release 13.3.6 --- CHANGELOG.md | 10 ++++++++++ package.json | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d983ada..0b4e231d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +### [13.3.6](https://github.com/eea/volto-plotlycharts/compare/13.3.5...13.3.6) - 20 November 2025 + +#### :bug: Bug Fixes + +- fix: add back filters feature [Miu Razvan - [`cb35107`](https://github.com/eea/volto-plotlycharts/commit/cb3510792da2efed1064039690c0a979624dc55f)] + +#### :house: Internal changes + +- style: Automated code fix [eea-jenkins - [`76c3cfd`](https://github.com/eea/volto-plotlycharts/commit/76c3cfd9370adc38548237c7cca4820ff0a4eeb6)] + ### [13.3.5](https://github.com/eea/volto-plotlycharts/compare/13.3.4...13.3.5) - 18 November 2025 ### [13.3.4](https://github.com/eea/volto-plotlycharts/compare/13.3.3...13.3.4) - 17 November 2025 diff --git a/package.json b/package.json index ebee986b..043121dc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@eeacms/volto-plotlycharts", - "version": "13.3.5", + "version": "13.3.6", "description": "Plotly Charts and Editor integration for Volto", "main": "src/index.js", "author": "European Environment Agency: IDM2 A-Team",