Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Backport 2024.02.xx] - Dashboards - no longer shows counter widgets #10708 #10714 #10720

Merged
merged 1 commit into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ describe('wpsChart enhancer', () => {
};
ReactDOM.render(<Sink {...props} />, document.getElementById("container"));
});
it('wpsCounter with mapSync and dependencies', (done) => {
it('wpsCounter with mapSync with mapWidget and dependencies', (done) => {
const Sink = wpsCounter(createSink( ({data, loading} = {}) => {
if (!loading) {
expect(data).toExist();
Expand All @@ -76,6 +76,46 @@ describe('wpsChart enhancer', () => {
dependencies: {
viewport: "..."
},
dependenciesMap: {
mapSync: 'widgets[456].mapSync'
},
widgets: [
{
id: "123",
widgetType: 'table'
},
{
id: "456",
widgetType: 'map'
}
],
layer: {
name: "test",
url: 'base/web/client/test-resources/widgetbuilder/aggregate',
wpsUrl: 'base/web/client/test-resources/widgetbuilder/aggregate',
search: {url: 'base/web/client/test-resources/widgetbuilder/aggregate'}},
options: {
aggregateFunction: "Count",
aggregationAttribute: "test"
}
};
ReactDOM.render(<Sink {...props} />, document.getElementById("container"));
});
it('wpsCounter with mapSync standard Map', (done) => {
const Sink = wpsCounter(createSink( ({data, loading} = {}) => {
if (!loading) {
expect(data).toExist();
done();
}
}));
const props = {
mapSync: true,
dependencies: {
viewport: "..."
},
dependenciesMap: {
mapSync: 'map.mapSync'
},
layer: {
name: "test",
url: 'base/web/client/test-resources/widgetbuilder/aggregate',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,51 @@ describe('triggerFetch stream', () => {
}
);
});
it('triggerFetch with mapSync and dependencies.viewport', (done) => {
it('triggerFetch with mapSync with mapWidget and dependencies.viewport', (done) => {
const base = {
layer: { name: "TEST" },
mapSync: true
mapSync: true,
dependenciesMap: {
mapSync: 'widgets[456].mapSync'
},
widgets: [
{
id: "123",
widgetType: 'table'
},
{
id: "456",
widgetType: 'map'
}
]
};
const propsChanges = [
base, // does not trigger fetch
{...base, dependencies: { viewport: true }}, // triggers fetch (p1)
{...base, dependencies: { viewport: false }}, // does not trigger fetch
{...base, mapSync: false, filter: "changed"} // triggers fetch (p2) (the filter changes due to the viewport)
];
triggerFetch(Rx.Observable.from(propsChanges))
.bufferCount(4)
.subscribe(
([p1, p2, p3, p4]) => {
expect(p1?.dependencies?.viewport).toBe(true);
expect(p2).toExist();
expect(p3).toNotExist();
expect(p4).toNotExist();
done();
}
);
});
it('triggerFetch with mapSync with Standard Map and dependencies.viewport', (done) => {
const base = {
layer: { name: "TEST" },
mapSync: true,
widgets: [
],
dependenciesMap: {
mapSync: 'map.mapSync'
}
};
const propsChanges = [
base, // does not trigger fetch
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
* LICENSE file in the root directory of this source tree.
*/

import { checkMapSyncWithWidgetOfMapType } from '../../../../utils/WidgetsUtils';

require('rxjs');
// const { getSearchUrl } = require('../../../../utils/LayersUtils');
const sameFilter = (f1, f2) => f1 === f2;
Expand All @@ -22,11 +24,11 @@ const sameSortOptions = (o1 = {}, o2 = {}) =>
* @return {Observable} Stream of props to trigger the data fetch
*/
export default ($props) =>
$props.filter(({ layer = {}, mapSync, dependencies }) => {
// Check if mapSync is enabled (true) and dependencies.viewport is null or falsy
$props.filter(({ layer = {}, mapSync, dependencies, dependenciesMap, widgets }) => {
// Check if mapSync is enabled (true), dependencyMap has mapSync dependency to Map widget and dependencies.viewport is null or falsy
// If this condition is true, return false to filter out the event.
// This prevents an extra API call from being triggered when the viewport is not available.
if (mapSync && !dependencies?.viewport) {
if (mapSync && checkMapSyncWithWidgetOfMapType(widgets, dependenciesMap) && !dependencies?.viewport) {
return false;
}
return layer.name;
Expand Down
8 changes: 5 additions & 3 deletions web/client/components/widgets/enhancers/wpsCounter.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ const sameOptions = (o1 = {}, o2 = {}) =>
&& o1.aggregationAttribute === o2.aggregationAttribute
&& o1.viewParams === o2.viewParams;
import { getWpsUrl } from '../../../utils/LayersUtils';
import { checkMapSyncWithWidgetOfMapType } from '../../../utils/WidgetsUtils';


/**
* Stream of props -> props to retrieve data from WPS aggregate process on params changes.
Expand All @@ -30,11 +32,11 @@ import { getWpsUrl } from '../../../utils/LayersUtils';
*/
const dataStreamFactory = ($props) =>
$props
.filter(({layer = {}, options, dependencies, mapSync}) => {
// Check if mapSync is enabled (true) and dependencies.viewport is null or falsy
.filter(({layer = {}, options, dependencies, mapSync, dependenciesMap, widgets}) => {
// Check if mapSync is enabled (true), dependencyMap has mapSync dependency to Map widget and dependencies.viewport is null or falsy
// If this condition is true, return false to filter out the event.
// This prevents an extra API call from being triggered when the viewport is not available.
if (mapSync && !dependencies?.viewport) {
if (mapSync && checkMapSyncWithWidgetOfMapType(widgets, dependenciesMap) && !dependencies?.viewport) {
return false;
}
return layer.name && getWpsUrl(layer) && options && options.aggregateFunction && options.aggregationAttribute;
Expand Down
46 changes: 46 additions & 0 deletions web/client/utils/WidgetsUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -992,3 +992,49 @@ export const canTableWidgetBeDependency = (widget, dependencyTableWidget) => {
const layerPresent = editingLayer.includes(get(dependencyTableWidget, 'layer.name'));
return isChart ? layerPresent && isChartCompatibleWithTableWidget(widget, dependencyTableWidget) : layerPresent;
};

function findWidgetById(widgets, widgetId) {
return widgets?.find(widget => widget.id === widgetId);
}

/**
* Checks if a widget, referenced by `mapSync` in the `dependenciesMap`, has `widgetType` set to `'map'`.
* If the widget has a `dependenciesMap`, it will be checked recursively.
*
* @param {Array<Object>} widgets - List of widget objects, each containing an `id`, `widgetType`, and optionally `dependenciesMap`.
* @param {Object} dependenciesMap - An object containing a `mapSync` reference to another widget's `mapSync` (e.g., "widgets[widgetId].mapSync").
* @returns {boolean} - Returns boolean
*
* @example
* checkMapSyncWithWidgetOfMapType(widgets, { mapSync: 'widgets[40fdb720-b228-11ef-974d-8115935269b7].mapSync' });
*/
export function checkMapSyncWithWidgetOfMapType(widgets, dependenciesMap) {
const mapSyncDependencies = dependenciesMap?.mapSync;

if (!mapSyncDependencies) {
return false;
}
if (mapSyncDependencies.includes("map.mapSync")) {
return true;
}
// Extract widget ID
const widgetId = mapSyncDependencies.match?.(/\[([^\]]+)\]/)?.[1];
if (!widgetId) {
return false;
}
// Find the widget using the extracted widgetId
const widget = findWidgetById(widgets, widgetId);
if (!widget) {
return false;
}
// Check if the widget has widgetType 'map'
if (widget.widgetType === 'map') {
return true;
}
// If widget has its own dependenciesMap, recursively check that map
if (widget.dependenciesMap) {
return checkMapSyncWithWidgetOfMapType(widgets, widget.dependenciesMap);
}
// If no match found, return false
return false;
}
42 changes: 41 additions & 1 deletion web/client/utils/__tests__/WidgetsUtils-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ import {
enableBarChartStack,
getWidgetLayersNames,
isChartCompatibleWithTableWidget,
canTableWidgetBeDependency
canTableWidgetBeDependency,
checkMapSyncWithWidgetOfMapType
} from '../WidgetsUtils';
import * as simpleStatistics from 'simple-statistics';
import { createClassifyGeoJSONSync } from '../../api/GeoJSONClassification';
Expand Down Expand Up @@ -757,4 +758,43 @@ describe('Test WidgetsUtils', () => {
expect(canTableWidgetBeDependency({widgetType: 'chart', charts: [{chartId: "1", traces: [{layer: {name: "layer_1"}}, {layer: {name: "layer_1"}}]}]}, dependencyTableWidget2)).toBeFalsy();
expect(canTableWidgetBeDependency({widgetType: 'chart', charts: [{chartId: "1", traces: [{layer: {name: "layer_1"}}, {layer: {name: "layer_2"}}]}]}, dependencyTableWidget2)).toBeFalsy();
});

it("MapSync dependency to mapWidget", () => {
const parameters = {
dependenciesMap: {
mapSync: 'widgets[456].mapSync'
},
widgets: [
{
id: "123",
widgetType: 'table'
},
{
id: "456",
widgetType: 'map'
}
]
};
const result = checkMapSyncWithWidgetOfMapType(parameters.widgets, parameters.dependenciesMap);
expect(result).toEqual(true);
});
it("MapSync dependency not in map widget", () => {
const parameters = {
dependenciesMap: {
mapSync: 'widgets[123].mapSync'
},
widgets: [
{
id: "123",
widgetType: 'table'
},
{
id: "456",
widgetType: 'map'
}
]
};
const result = checkMapSyncWithWidgetOfMapType(parameters.widgets, parameters.dependenciesMap);
expect(result).toEqual(false);
});
});
Loading