-
Notifications
You must be signed in to change notification settings - Fork 409
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
#10514 - FeatureEditor filter by geometric area #10515
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,8 +11,9 @@ import {get, head, isEmpty, find, castArray, includes, reduce} from 'lodash'; | |
import { LOCATION_CHANGE } from 'connected-react-router'; | ||
import axios from '../libs/ajax'; | ||
import bbox from '@turf/bbox'; | ||
import booleanIntersects from "@turf/boolean-intersects"; | ||
import { fidFilter } from '../utils/ogc/Filter/filter'; | ||
import { getDefaultFeatureProjection, getPagesToLoad, gridUpdateToQueryUpdate, updatePages } from '../utils/FeatureGridUtils'; | ||
import { getDefaultFeatureProjection, getPagesToLoad, gridUpdateToQueryUpdate, rawAsGeoJson, updatePages } from '../utils/FeatureGridUtils'; | ||
|
||
import assign from 'object-assign'; | ||
import { | ||
|
@@ -25,6 +26,7 @@ import { | |
import requestBuilder from '../utils/ogc/WFST/RequestBuilder'; | ||
import { findGeometryProperty } from '../utils/ogc/WFS/base'; | ||
import { FEATURE_INFO_CLICK, HIDE_MAPINFO_MARKER, closeIdentify, hideMapinfoMarker } from '../actions/mapInfo'; | ||
import { LOGIN_SUCCESS, LOGOUT } from "../actions/security"; | ||
|
||
import { | ||
query, | ||
|
@@ -110,7 +112,8 @@ import { | |
setPagination, | ||
launchUpdateFilterFunc, | ||
LAUNCH_UPDATE_FILTER_FUNC, SET_LAYER, | ||
SET_VIEWPORT_FILTER, setViewportFilter | ||
SET_VIEWPORT_FILTER, setViewportFilter, | ||
setRestrictedArea | ||
} from '../actions/featuregrid'; | ||
|
||
import { | ||
|
@@ -144,7 +147,10 @@ import { | |
getAttributeFilters, | ||
selectedLayerSelector, | ||
multiSelect, | ||
paginationSelector, isViewportFilterActive, viewportFilter | ||
paginationSelector, isViewportFilterActive, viewportFilter, | ||
restrictedAreaSrcSelector, | ||
restrictedAreaSelector, | ||
additionnalGridFilters | ||
} from '../selectors/featuregrid'; | ||
|
||
import { error, warning } from '../actions/notifications'; | ||
|
@@ -169,6 +175,7 @@ import {dockPanelsSelector} from "../selectors/maplayout"; | |
import {shutdownToolOnAnotherToolDrawing} from "../utils/ControlUtils"; | ||
import {mapTypeSelector} from "../selectors/maptype"; | ||
import { MapLibraries } from '../utils/MapTypeUtils'; | ||
import { isAdminUserSelector, isLoggedIn } from '../selectors/security'; | ||
|
||
const setupDrawSupport = (state, original) => { | ||
const defaultFeatureProj = getDefaultFeatureProjection(); | ||
|
@@ -205,7 +212,15 @@ const setupDrawSupport = (state, original) => { | |
}); | ||
|
||
// Remove features with geometry null or id "empty_row" | ||
const cleanFeatures = features.filter(ft => ft.geometry !== null || ft.id !== 'empty_row'); | ||
const cleanFeatures = features.filter(ft => { | ||
const restrictedArea = restrictedAreaSelector(state); | ||
let isValidFeature = ft.geometry !== null || ft.id !== 'empty_row'; | ||
if (isValidFeature && !isEmpty(restrictedArea)) { | ||
// allow only feature inside restricted area | ||
isValidFeature = booleanIntersects(restrictedArea, ft.geometry); | ||
} | ||
return isValidFeature; | ||
}); | ||
|
||
if (cleanFeatures.length > 0) { | ||
return Rx.Observable.from([ | ||
|
@@ -262,7 +277,7 @@ const createLoadPageFlow = (store) => ({page, size, reason} = {}) => { | |
wfsURL(state), | ||
addPagination({ | ||
...(wfsFilter(state)), | ||
...viewportFilter(state) | ||
...additionnalGridFilters(state) | ||
}, | ||
getPagination(state, {page, size}) | ||
), | ||
|
@@ -298,7 +313,7 @@ const updateFilterFunc = (store) => ({update = {}, append} = {}) => { | |
// If an advanced filter is present it's filterFields should be composed with the action' | ||
const {id} = selectedLayerSelector(store.getState()); | ||
const filterObj = {...get(store.getState(), `featuregrid.advancedFilters["${id}"]`)}; | ||
if (filterObj) { | ||
if (filterObj && !isEmpty(filterObj)) { | ||
// TODO: make append with advanced filters work | ||
const attributesFilter = getAttributeFilters(store.getState()) || {}; | ||
const columnsFilters = reduce(attributesFilter, (cFilters, value, attribute) => { | ||
|
@@ -1283,3 +1298,34 @@ export const resetViewportFilter = (action$, store) => | |
return viewportFilter(store.getState()) !== null ? Rx.Observable.of(setViewportFilter(null)) | ||
: Rx.Observable.empty(); | ||
}); | ||
|
||
export const requestRestrictedArea = (action$, store) => | ||
action$.ofType(OPEN_FEATURE_GRID, LOGIN_SUCCESS) | ||
.filter(() => { | ||
return !isAdminUserSelector(store.getState()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This makes the restriction not be applied for anonymous users. Only for logged, not-admin. I think we should at least apply the same restrictedArea to the anonymous users? Maybe a configuration inside the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indeed, we have think avout authenticated users (to works with geOrchestra restricted org area) first and forget anonymous users. To apply this restriction, we needs to confirm if restricted area is apply in edit mode only or not as explain in global review comment. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
After discussion, we will also apply the restriction to anonymous users to be compliant with MapStore2 behavior. |
||
&& isLoggedIn(store.getState()) | ||
&& !isEmpty(restrictedAreaSrcSelector(store.getState())); | ||
}) | ||
.switchMap(() => { | ||
const src = restrictedAreaSrcSelector(store.getState()); | ||
if (src.url) { | ||
return Rx.Observable.defer(() => fetch(src?.url).then(r => r?.json?.())) | ||
.switchMap(result => { | ||
return Rx.Observable.of( | ||
setRestrictedArea(rawAsGeoJson(result)), | ||
changePage(0) | ||
); | ||
}); | ||
} | ||
return Rx.Observable.of( | ||
setRestrictedArea(rawAsGeoJson(src.raw) || {}), | ||
changePage(0) | ||
); | ||
}); | ||
|
||
export const resetRestrictedArea = (action$, store) => | ||
action$.ofType(LOGOUT, CLOSE_FEATURE_GRID) | ||
.filter(() => !isEmpty(restrictedAreaSrcSelector(store.getState()))) | ||
.switchMap(() => Rx.Observable.of( | ||
setRestrictedArea({}) | ||
)); |
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -79,6 +79,9 @@ import {isViewportFilterActive} from "../selectors/featuregrid"; | |||||||||||||
* @prop {array} cfg.showFilterByViewportTool Show button to toggle filter by viewport in toolbar. | ||||||||||||||
* @prop {object} cfg.dateFormats Allows to specify custom date formats ( in [ISO_8601](https://en.wikipedia.org/wiki/ISO_8601) format) to use to display dates in the table. `date` `date-time` and `time` are the supported entries for the date format. Example: | ||||||||||||||
* @prop {boolean} cfg.showPopoverSync default false. Hide the popup of map sync if false, shows the popup of map sync if true | ||||||||||||||
* @prop {string} cfg.restrictedArea.url Geometry definition as WKT or GeoJSON loaded from URL or path. | ||||||||||||||
* @prop {string} cfg.restrictedArea.raw Geometry definition as WKT or GeoJSON. | ||||||||||||||
* @prop {string} cfg.restrictedArea.operator Spatial operation to performed between features and the given geometry. | ||||||||||||||
Comment on lines
+82
to
+84
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||
* ``` | ||||||||||||||
* "dateFormats": { | ||||||||||||||
* "date-time": "MM DD YYYY - HH:mm:ss", | ||||||||||||||
|
@@ -114,6 +117,11 @@ import {isViewportFilterActive} from "../selectors/featuregrid"; | |||||||||||||
* }, | ||||||||||||||
* "editingAllowedRoles": ["ADMIN"], | ||||||||||||||
* "snapTool": true, | ||||||||||||||
* "restrictedArea": { | ||||||||||||||
* "url": "/wkt_or_geojson_geometry", | ||||||||||||||
* "raw": "POLYGON ((-64.8 32.3, -65.5 18.3, -80.3 25.2, -64.8 32.3))", | ||||||||||||||
* "operator": "WITHIN" | ||||||||||||||
* }, | ||||||||||||||
* "snapConfig": { | ||||||||||||||
* "vertex": true, | ||||||||||||||
* "edge": true, | ||||||||||||||
|
@@ -175,7 +183,9 @@ const EditorPlugin = connect( | |||||||||||||
virtualScroll: this.props.virtualScroll ?? true, | ||||||||||||||
editingAllowedRoles: this.props.editingAllowedRoles, | ||||||||||||||
editingAllowedGroups: this.props.editingAllowedGroups, | ||||||||||||||
maxStoredPages: this.props.maxStoredPages | ||||||||||||||
maxStoredPages: this.props.maxStoredPages, | ||||||||||||||
restrictedAreaUrl: this.props.restrictedAreaUrl, | ||||||||||||||
restrictedArea: this.props.restrictedArea | ||||||||||||||
}); | ||||||||||||||
}, | ||||||||||||||
componentDidUpdate(prevProps) { | ||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here the
tooltipId
but the tooltip is not present in translation file.Moreover the property do not exist for normal bootstrap button. In order to use it you should use TButton (created for feature grid) or Button with tooltip enhancer.
I noticed that
bsStyle
property anyway is overridden by the TButton.So in order to have a tooltip here you should:
TButton
like this (putting bsStyle after the forced one).Note: I removed "disabled" flag for a better aspect.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. This change will be made.