-
Notifications
You must be signed in to change notification settings - Fork 416
/
Copy pathIdentify.jsx
318 lines (307 loc) · 12.3 KB
/
Identify.jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
/*
* Copyright 2016, GeoSolutions Sas.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/
import './identify/identify.css';
import { isUndefined } from 'lodash';
import assign from 'object-assign';
import React from 'react';
import { Glyphicon } from 'react-bootstrap';
import { connect } from 'react-redux';
import { compose, defaultProps } from 'recompose';
import { createSelector, createStructuredSelector } from 'reselect';
import { changeMousePointer, zoomToExtent } from '../actions/map';
import {
changeFormat,
changeMapInfoFormat,
changePage,
clearWarning,
setShowInMapPopup,
closeIdentify,
editLayerFeatures,
hideMapinfoMarker,
hideMapinfoRevGeocode,
purgeMapInfoResults,
setMapTrigger,
showMapinfoRevGeocode,
toggleHighlightFeature,
toggleMapInfoState,
toggleShowCoordinateEditor,
updateCenterToMarker,
updateFeatureInfoClickPoint,
checkIdentifyIsMounted,
onInitPlugin
} from '../actions/mapInfo';
import { enableHideEmptyPopupOption } from '../actions/mapPopups';
import DefaultViewerComp from '../components/data/identify/DefaultViewer';
import { defaultViewerDefaultProps, defaultViewerHandlers } from '../components/data/identify/enhancers/defaultViewer';
import { identifyLifecycle } from '../components/data/identify/enhancers/identify';
import zoomToFeatureHandler from '../components/data/identify/enhancers/zoomToFeatureHandler';
import IdentifyContainer from '../components/data/identify/IdentifyContainer';
import loadingState from '../components/misc/enhancers/loadingState';
import FeatureInfoFormatSelectorComp from '../components/misc/FeatureInfoFormatSelector';
import FeatureInfoTriggerSelectorComp from '../components/misc/FeatureInfoTriggerSelector';
import epics from '../epics/identify';
import mapInfo from '../reducers/mapInfo';
import mapPopups from '../reducers/mapPopups';
import { isEditingAllowedSelector } from '../selectors/featuregrid';
import { layersSelector } from '../selectors/layers';
import { currentLocaleSelector } from '../selectors/locale';
import { isMouseMoveIdentifyActiveSelector, mapSelector } from '../selectors/map';
import {
clickPointSelector,
currentFeatureCrsSelector,
currentFeatureSelector,
generalInfoFormatSelector,
indexSelector,
isHighlightEnabledSelector,
isLoadedResponseSelector,
requestsSelector,
responsesSelector,
showEmptyMessageGFISelector,
validResponsesSelector,
hoverEnabledSelector,
mapInfoEnabledSelector
} from '../selectors/mapInfo';
import { mapLayoutValuesSelector } from '../selectors/maplayout';
import { isCesium, mapTypeSelector } from '../selectors/maptype';
import ConfigUtils from '../utils/ConfigUtils';
import { getDefaultInfoFormatValue, getValidator } from '../utils/MapInfoUtils';
import getFeatureButtons from './identify/featureButtons';
import getToolButtons from './identify/toolButtons';
import Message from './locale/Message';
const selector = createStructuredSelector({
enabled: (state) => mapInfoEnabledSelector(state) || state.controls && state.controls.info && state.controls.info.enabled || false,
responses: responsesSelector,
validResponses: validResponsesSelector,
requests: requestsSelector,
format: generalInfoFormatSelector,
map: mapSelector,
layers: layersSelector,
point: clickPointSelector,
showModalReverse: (state) => state.mapInfo && state.mapInfo.showModalReverse,
reverseGeocodeData: (state) => state.mapInfo && state.mapInfo.reverseGeocodeData,
warning: (state) => state.mapInfo && state.mapInfo.warning,
currentLocale: currentLocaleSelector,
dockStyle: (state) => mapLayoutValuesSelector(state, { height: true, right: true }, true),
formatCoord: (state) => state.mapInfo && state.mapInfo.formatCoord || ConfigUtils.getConfigProp('defaultCoordinateFormat'),
showCoordinateEditor: (state) => state.mapInfo && state.mapInfo.showCoordinateEditor,
showEmptyMessageGFI: state => showEmptyMessageGFISelector(state),
isEditingAllowed: isEditingAllowedSelector,
isCesium,
floatingIdentifyEnabled: (state) => isMouseMoveIdentifyActiveSelector(state)
});
// result panel
/*
* Enhancer to enable set index only if Component has not header in viewerOptions props
*/
const identifyIndex = compose(
connect(
createSelector(indexSelector, isLoadedResponseSelector, (state) => state.browser && state.browser.mobile, (index, loaded, isMobile) => ({ index, loaded, isMobile })),
{
setIndex: changePage
}
)
);
const DefaultViewer = compose(
identifyIndex,
defaultViewerDefaultProps,
defaultViewerHandlers,
loadingState(({ loaded }) => isUndefined(loaded))
)(DefaultViewerComp);
const identifyDefaultProps = defaultProps({
formatCoord: "decimal",
enabled: false,
draggable: true,
collapsible: false,
format: getDefaultInfoFormatValue(),
requests: [],
responses: [],
viewerOptions: {},
viewer: DefaultViewer,
purgeResults: () => { },
hideMarker: () => { },
clearWarning: () => { },
changeMousePointer: () => { },
showRevGeocode: () => { },
checkIdentifyIsMounted: () => {},
hideRevGeocode: () => { },
containerProps: {
continuous: false
},
enabledCoordEditorButton: true,
showCoordinateEditor: false,
showModalReverse: false,
reverseGeocodeData: {},
enableRevGeocode: true,
wrapRevGeocode: false,
style: {},
point: {},
layer: null,
map: {},
layers: [],
panelClassName: "modal-dialog info-panel modal-content",
headerClassName: "modal-header",
bodyClassName: "modal-body info-wrap",
dock: true,
headerGlyph: "",
closeGlyph: "1-close",
className: "square-button",
currentLocale: 'en-US',
fullscreen: false,
showTabs: true,
showCoords: true,
showLayerTitle: true,
showMoreInfo: true,
showEdit: false,
position: 'right',
size: 550,
getToolButtons,
getFeatureButtons,
showFullscreen: false,
validResponses: [],
validator: getValidator, // TODO: move all validation from the components to the selectors
zIndex: 1050
});
/**
* This plugin allows get information about clicked point. It can be configured to have a mobile or a desktop flavor.
*
* You can configure some of the features of this plugin by setting up the initial mapInfo state, then you need to update the "initialState.defaultState", or by the plugin configuration
* ```
* "mapInfo": {
* "enabled": true, // enabled by default
* "disabledAlwaysOn": false, // if true, disable always on setup
* "configuration": {
* "showEmptyMessageGFI": false // allow or deny the visibility of message when you have no results from identify request
* "infoFormat": "text/plain" // default infoformat value, other values are "text/html" for text only or "application/json" for properties
* }
* }
* ```
*
* @class Identify
* @memberof plugins
* @static
*
* @prop showIn {string[]} List of the plugins where to show the plugin
* @prop cfg.dock {bool} true shows dock panel, false shows modal
* @prop cfg.draggable {boolean} draggable info window, when modal
* @prop cfg.showHighlightFeatureButton {boolean} show the highlight feature button if the interrogation returned valid features (openlayers only)
* @prop cfg.hidePopupIfNoResults {boolean} hide/show the identify popup in case of no results
* @prop cfg.highlightEnabledFromTheStart {boolean} the highlight feature button will be activated by default if true
* @prop cfg.viewerOptions.container {expression} the container of the viewer, expression from the context
* @prop cfg.viewerOptions.header {expression} the header of the viewer, expression from the context{expression}
* @prop cfg.disableCenterToMarker {bool} disable zoom to marker action
* @prop cfg.showAllResponses {bool} if true it will include invalid/empty responses and it will always select the first request/layer
* @prop cfg.zIndex {number} component z index order
* @prop cfg.showInMapPopup {boolean} if true show the identify as popup
* @prop cfg.maxItems {number} the number of features returned by this tool
* @prop cfg.showMoreInfo {boolean} if true shows the more info icon which allow user to show/hide Geocode viewer as popup (true by default)
* @prop cfg.showEdit {boolean} if true, and when the FeatureEditor plugin is present, shows and edit button to edit the current feature(s) clicked in the grid.
* @prop cfg.enableInfoForSelectedLayers {boolean} if true, if some layer is selected in the TOC, the feature info is performed only on the selected ones. if false, the info is queried for all the layers, independently from selection. (default is true).
* @prop cfg.disableCoordinatesRow {boolean} if true the coordinates row is disabled
*
* @example
* {
* "name": "Identify",
* "showIn": ["Settings"],
* "cfg": {
* "draggable": false,
* "dock": true,
* "viewerOptions": {
* "container": "{context.ReactSwipe}",
* "header": "{context.SwipeHeader}"
* }
* }
* }
*
*/
const IdentifyPlugin = compose(
connect(selector, {
onInitPlugin,
purgeResults: purgeMapInfoResults,
closeIdentify,
onSubmitClickPoint: updateFeatureInfoClickPoint,
onToggleShowCoordinateEditor: toggleShowCoordinateEditor,
onChangeFormat: changeFormat,
changeMousePointer,
clearWarning,
hideMarker: hideMapinfoMarker,
showRevGeocode: showMapinfoRevGeocode,
hideRevGeocode: hideMapinfoRevGeocode,
onEnableCenterToMarker: updateCenterToMarker.bind(null, 'enabled'),
onEdit: editLayerFeatures,
checkIdentifyIsMounted
}, (stateProps, dispatchProps, ownProps) => ({
...ownProps,
...stateProps,
...dispatchProps,
enabled: stateProps.enabled && (stateProps.isCesium || !ownProps.showInMapPopup) && !stateProps.floatingIdentifyEnabled
})),
// highlight support
compose(
connect(
createStructuredSelector({
highlight: isHighlightEnabledSelector,
currentFeature: currentFeatureSelector,
currentFeatureCrs: currentFeatureCrsSelector
}), {
toggleHighlightFeature,
zoomToExtent
}
),
zoomToFeatureHandler
),
// disable with not supported mapTypes. TODO: remove when reproject (leaflet) and features draw available (cesium)
connect(createSelector(mapTypeSelector, mapType => ({mapType})), {}, ({mapType}, _, { showHighlightFeatureButton, ...props }) => ({...props, showHighlightFeatureButton: mapType === 'openlayers' && showHighlightFeatureButton}) ),
identifyDefaultProps,
identifyIndex,
defaultViewerHandlers,
connect(() => ({}), {
setShowInMapPopup,
enableHideEmptyPopupOption
}),
identifyLifecycle
)(IdentifyContainer);
// configuration UI
const FeatureInfoFormatSelector = connect((state) => ({
infoFormat: generalInfoFormatSelector(state)
}), {
onInfoFormatChange: changeMapInfoFormat
})(FeatureInfoFormatSelectorComp);
const FeatureInfoTriggerSelector = connect((state) => ({
trigger: isMouseMoveIdentifyActiveSelector(state) ? 'hover' : 'click',
hoverEnabled: hoverEnabledSelector(state)
}), {
onSetMapTrigger: setMapTrigger,
onPurgeMapInfoResults: purgeMapInfoResults,
onHideMapinfoMarker: hideMapinfoMarker
})(FeatureInfoTriggerSelectorComp);
export default {
IdentifyPlugin: assign(IdentifyPlugin, {
Toolbar: {
name: 'info',
position: 6,
tooltip: "info.tooltip",
icon: <Glyphicon glyph="map-marker" />,
help: <Message msgId="helptexts.infoButton" />,
action: toggleMapInfoState,
selector: (state) => ({
bsStyle: state.mapInfo && state.mapInfo.enabled ? "success" : "primary",
active: !!(state.mapInfo && state.mapInfo.enabled)
})
},
Settings: {
tool: [<FeatureInfoFormatSelector
key="featureinfoformat"
label={<Message msgId="infoFormatLbl" />
} />, <FeatureInfoTriggerSelector
key="featureinfotrigger" />],
position: 3
}
}),
reducers: { mapInfo, mapPopups },
epics
};