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

fix #9098 dashboard filter capabilities #9514

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
38 changes: 38 additions & 0 deletions docs/developer-guide/mapstore-migration-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,44 @@ This is a list of things to check if you want to update from a previous version

## Migration from 2023.02.xx to 2024.01.00

### Adding spatial filter to dashboard widgets

In order to enable the possibility to add in and the spatial filter to the widgets [#9098](https://github.com/geosolutions-it/MapStore2/issues/9098) you have to edit the QueryPanel config in `localConfig.json` file adding:
MV88 marked this conversation as resolved.
Show resolved Hide resolved

- **useEmbeddedMap** flag,
- **spatialOperations**
- **spatialMethodOptions**
MV88 marked this conversation as resolved.
Show resolved Hide resolved

*Note: these props can vary, for example you can limit the spatial filtering operation to intersect only*
MV88 marked this conversation as resolved.
Show resolved Hide resolved

```json
...
dashboard: [
MV88 marked this conversation as resolved.
Show resolved Hide resolved
...
{
"name": "QueryPanel",
"cfg": {
"toolsOptions": {
"hideCrossLayer": true,
"useEmbeddedMap": true
},
"spatialPanelExpanded": false,
"spatialOperations": [
{"id": "INTERSECTS", "name": "queryform.spatialfilter.operations.intersects"},
{"id": "CONTAINS", "name": "queryform.spatialfilter.operations.contains"},
{"id": "WITHIN", "name": "queryform.spatialfilter.operations.within"}
],
"spatialMethodOptions": [
{"id": "BBOX", "name": "queryform.spatialfilter.methods.box"},
{"id": "Circle", "name": "queryform.spatialfilter.methods.circle"},
{"id": "Polygon", "name": "queryform.spatialfilter.methods.poly"}
],
offtherailz marked this conversation as resolved.
Show resolved Hide resolved
"containerPosition": "columns"
}
}

```

### MapFish Print update

The **MapFish Print** library has been updated to work with the latest GeoTools version and Java 11 as well as being aligned with the same dependency used by the official GeoServer printing extension (see this issue <https://github.com/geosolutions-it/mapfish-print/issues/65>)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,14 +140,14 @@ const ColorClassModal = ({

ColorClassModal.propTypes = {
modalClassName: PropTypes.string,
show: PropTypes.boolean,
show: PropTypes.bool,
onClose: PropTypes.func,
onSaveClassification: PropTypes.func,
onChangeClassAttribute: PropTypes.func,
classificationAttribute: PropTypes.string,
onUpdateClasses: PropTypes.func,
options: PropTypes.array,
placeHolder: PropTypes.string,
placeHolder: PropTypes.oneOfType(PropTypes.string, PropTypes.object),
classification: PropTypes.array,
rangeClassification: PropTypes.array,
defaultCustomColor: PropTypes.string,
Expand Down
1 change: 0 additions & 1 deletion web/client/configs/localConfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -823,7 +823,6 @@
{"id": "WITHIN", "name": "queryform.spatialfilter.operations.within"}
],
"spatialMethodOptions": [
{"id": "Viewport", "name": "queryform.spatialfilter.methods.viewport"},
{"id": "BBOX", "name": "queryform.spatialfilter.methods.box"},
{"id": "Circle", "name": "queryform.spatialfilter.methods.circle"},
{"id": "Polygon", "name": "queryform.spatialfilter.methods.poly"}
Expand Down
86 changes: 1 addition & 85 deletions web/client/epics/__tests__/widgets-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,9 @@ import {
updateLayerOnLayerPropertiesChange,
updateLayerOnLoadingErrorChange,
updateDependenciesMapOnMapSwitch,
onWidgetCreationFromMap,
onLayerSelectedEpic
onWidgetCreationFromMap
} from '../widgets';

import {
CHANGE_MAP_EDITOR
} from '../../actions/queryform';

import {
CLEAR_WIDGETS,
insertWidget,
Expand All @@ -46,9 +41,6 @@ import { onLocationChanged } from 'connected-react-router';
import { ActionsObservable } from 'redux-observable';
import Rx from 'rxjs';

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


describe('widgets Epics', () => {
it('clearWidgetsOnLocationChange triggers CLEAR_WIDGETS on LOCATION_CHANGE', (done) => {
const checkActions = actions => {
Expand Down Expand Up @@ -675,80 +667,4 @@ describe('widgets Epics', () => {
[onEditorChange("widgetType", "chart")],
checkActions, state);
});
it('onLayerSelectedEpic by selecting a map', (done) => {
const checkActions = actions => {
expect(actions.length).toBe(1);
expect(actions[0].type).toBe(CHANGE_MAP_EDITOR);
expect(actions[0].mapData).toEqual({
...DEFAULT_MAP_SETTINGS,
center: {
crs: "EPSG:4326",
x: 0,
y: 0
},
zoom: 21
});
done();
};
const state = {
layers: {
flat: [{
id: "1",
name: "layer",
bbox: {
crs: "EPSG:4326",
bounds: {
minx: -18, miny: -9, maxx: 18, maxy: 9
}
}
}, {
id: "2",
name: "layer2"
}, {
id: "3",
name: "layer3"
}],
selected: ["1"]
},
dashboard: {
editor: {
layer: {
bbox: {
crs: "EPSG:4326",
bounds: {
minx: -18, miny: -9, maxx: 18, maxy: 9
}
}
},
available: false
},
editing: true
}
};
testEpic(onLayerSelectedEpic,
1,
[onEditorChange("chart-layers", {})],
checkActions, state);
});
it('onLayerSelectedEpic by clearing map state used by queryform in dashboard', (done) => {
const checkActions = actions => {
expect(actions.length).toBe(1);
expect(actions[0].type).toBe(CHANGE_MAP_EDITOR);
expect(actions[0].mapData).toEqual(null);
done();
};
const state = {
layers: {},
dashboard: {
editor: {
available: false
},
editing: true
}
};
testEpic(onLayerSelectedEpic,
1,
[onEditorChange("chart-layers")],
checkActions, state);
});
});
64 changes: 26 additions & 38 deletions web/client/epics/widgets.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,13 @@ import {
replaceWidgets,
WIDGETS_MAPS_REGEX,
EDITOR_CHANGE,
EDIT
OPEN_FILTER_EDITOR
} from '../actions/widgets';

import { changeMapEditor } from '../actions/queryform';
import { MAP_CONFIG_LOADED } from '../actions/config';
import { TOGGLE_CONTROL } from '../actions/controls';
import { queryPanelSelector } from '../selectors/controls';

import {
availableDependenciesSelector,
Expand All @@ -51,9 +53,9 @@ import { DASHBOARD_LOADED } from '../actions/dashboard';
import { LOCATION_CHANGE } from 'connected-react-router';
import { saveAs } from 'file-saver';
import {downloadCanvasDataURL} from '../utils/FileUtils';
import {transformExtentToArray} from '../utils/CoordinatesUtils';
import {reprojectBbox} from '../utils/CoordinatesUtils';
import converter from 'json-2-csv';
import { getZoomForExtent } from '../utils/MapUtils';
import { defaultGetZoomForExtent } from '../utils/MapUtils';
import { updateDependenciesMapOfMapList, DEFAULT_MAP_SETTINGS } from "../utils/WidgetsUtils";

const updateDependencyMap = (active, targetId, { dependenciesMap, mappings}) => {
Expand Down Expand Up @@ -322,44 +324,30 @@ export const onWidgetCreationFromMap = (action$, store) =>
});


const getMapConfig = (layer) => {
return {
...DEFAULT_MAP_SETTINGS,
// bbox: layer.bbox,
zoom: getZoomForExtent(transformExtentToArray(layer.bbox), DEFAULT_MAP_SETTINGS.size, 0, 21),
center: {
crs: layer.bbox.crs,
x: (layer.bbox.bounds.maxx + layer.bbox.bounds.minx) / 2,
y: (layer.bbox.bounds.maxy + layer.bbox.bounds.miny) / 2
}
};
};
export const onLayerSelectedEpic = (action$, store) =>
action$.ofType(EDITOR_CHANGE)
.filter(({key}) => key === 'chart-layers' && isDashboardEditing(store.getState()))
export const onOpenFilterEditorEpic = (action$, store) =>
action$.ofType(OPEN_FILTER_EDITOR)
.switchMap(() => {
const state = store.getState();
const layer = getWidgetLayer(state);
if (layer?.bbox) {
return Rx.Observable.of(
changeMapEditor(getMapConfig(layer))
);
}
return Rx.Observable.of(
changeMapEditor(null)
);
const zoom = defaultGetZoomForExtent(reprojectBbox(layer.bbox.bounds, "EPSG:4326", "EPSG:3857", true), DEFAULT_MAP_SETTINGS.size, 0, 21, 96, DEFAULT_MAP_SETTINGS.resolutions);
const map = {
...DEFAULT_MAP_SETTINGS,
zoom,
center: {
crs: layer.bbox.crs,
x: (layer.bbox.bounds.maxx + layer.bbox.bounds.minx) / 2,
y: (layer.bbox.bounds.maxy + layer.bbox.bounds.miny) / 2
}
};
const mapData = layer?.bbox ? map : null;
return Rx.Observable.of( changeMapEditor(mapData) );
});
export const onEditWidgetEpic = (action$, store) =>
action$.ofType(EDIT)
.filter(() => isDashboardEditing(store.getState()))


export const onResetMapEpic = (action$, store) =>
action$.ofType(TOGGLE_CONTROL)
.filter((type, control) => !queryPanelSelector(store.getState()) && control === "queryPanel" || isDashboardEditing(store.getState()))
MV88 marked this conversation as resolved.
Show resolved Hide resolved
.switchMap(() => {
const state = store.getState();
const layer = getWidgetLayer(state);
if (layer?.bbox) {
return Rx.Observable.of(
changeMapEditor(getMapConfig(layer))
);
}
return Rx.Observable.of(
changeMapEditor(null)
);
Expand All @@ -375,6 +363,6 @@ export default {
updateLayerOnLoadingErrorChange,
updateDependenciesMapOnMapSwitch,
onWidgetCreationFromMap,
onLayerSelectedEpic,
onEditWidgetEpic
onOpenFilterEditorEpic,
onResetMapEpic
};
2 changes: 1 addition & 1 deletion web/client/plugins/QueryPanel.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ class QueryPanel extends React.Component {
}

UNSAFE_componentWillReceiveProps(newProps) {
if (newProps.queryPanelEnabled === true && this.props.queryPanelEnabled === false) {
if (!newProps.toolsOptions.useEmbeddedMap && newProps.queryPanelEnabled === true && this.props.queryPanelEnabled === false) {
MV88 marked this conversation as resolved.
Show resolved Hide resolved
this.props.onInit();
}
}
Expand Down
7 changes: 6 additions & 1 deletion web/client/plugins/querypanel/SpatialFilterMap.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ import {
import {
getMapConfigSelector
} from '../../selectors/queryform';
import {
initQueryPanel
} from '../../actions/wfsquery';

/**
* Component connected to the widgetLayer
Expand All @@ -35,7 +38,9 @@ export const MapComponent = connect(
mapStateSource: "wizardMap"
};
}
), {} )(MapWithDraw);
), {
onMapReady: initQueryPanel
} )(MapWithDraw);

export default withContainer((props) => {
const {
Expand Down
19 changes: 5 additions & 14 deletions web/client/reducers/queryform.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,11 @@ import {
UPDATE_CROSS_LAYER_FILTER_FIELD_OPTIONS,
UPSERT_FILTERS,
REMOVE_FILTERS,
CHANGE_MAP_EDITOR
CHANGE_MAP_EDITOR,
QUERY_FORM_SEARCH
} from '../actions/queryform';

import { END_DRAWING, CHANGE_DRAWING_STATUS } from '../actions/draw';
import { INSERT } from '../actions/widgets';
import { SET_EDITING } from '../actions/dashboard';
import assign from 'object-assign';
import union from 'turf-union';
import bbox from 'turf-bbox';
Expand Down Expand Up @@ -112,21 +111,12 @@ function queryform(state = initialState, action) {
map: action.mapData
};
}
case INSERT: {
case QUERY_FORM_SEARCH: {
return {
...state,
map: null
};
}
case SET_EDITING: {
if (!action.editing) {
return {
...state,
map: null
};
}
return state;
}
case ADD_FILTER_FIELD: {
//
// Calculate the key number, this should be different for each new element
Expand Down Expand Up @@ -393,7 +383,8 @@ function queryform(state = initialState, action) {
return assign({}, state, initialState, {
spatialField,
crossLayerFilter,
filters: []
filters: [],
map: state.map
});
}
case SHOW_GENERATED_FILTER: {
Expand Down
1 change: 1 addition & 0 deletions web/client/translations/data.de-DE.json
Original file line number Diff line number Diff line change
Expand Up @@ -2150,6 +2150,7 @@
},
"mapSync": "Live-Filter nach Ansichtsfenster",
"displayLegend": {
"default": "Legende anzeigen",
"line": "Legende anzeigen",
"pie": "Legende anzeigen",
"bar": "Legende anzeigen",
Expand Down
1 change: 1 addition & 0 deletions web/client/translations/data.en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -2113,6 +2113,7 @@
},
"mapSync": "Live Filter by viewport",
"displayLegend": {
"default": "Display Legend",
"line": "Display Legend",
"pie": "Display Legend",
"bar": "Display Legend",
Expand Down
1 change: 1 addition & 0 deletions web/client/translations/data.es-ES.json
Original file line number Diff line number Diff line change
Expand Up @@ -2113,6 +2113,7 @@
},
"mapSync": "Filtro dinámico por extensión de la vista actual",
"displayLegend": {
"default": "Mostrar leyenda",
"line": "Mostrar leyenda",
"pie": "Mostrar leyenda",
"bar": "Mostrar leyenda",
Expand Down
1 change: 1 addition & 0 deletions web/client/translations/data.fr-FR.json
Original file line number Diff line number Diff line change
Expand Up @@ -2113,6 +2113,7 @@
},
"mapSync": "Live Filter par viewport",
"displayLegend": {
"default": "Afficher la légende",
"line": "Afficher la légende",
"pie": "Afficher la légende",
"bar": "Afficher la légende",
Expand Down
1 change: 1 addition & 0 deletions web/client/translations/data.it-IT.json
Original file line number Diff line number Diff line change
Expand Up @@ -2114,6 +2114,7 @@
},
"mapSync": "Filtra dati sull'area visibile",
"displayLegend": {
"default": "Mostra legenda",
"line": "Mostra legenda",
"pie": "Mostra legenda",
"bar": "Mostra legenda",
Expand Down
Loading
Loading