diff --git a/web/client/actions/catalog.js b/web/client/actions/catalog.js
index 392afa79a4..9b9c58d5ea 100644
--- a/web/client/actions/catalog.js
+++ b/web/client/actions/catalog.js
@@ -90,7 +90,7 @@ function textSearch(format, url, startPosition, maxRecords, text, options) {
function addLayerAndDescribe(layer) {
return (dispatch, getState) => {
const state = getState();
- const layers = state && state.layers;
+ const layers = state && state.layers && state.layers.flat;
const id = LayersUtils.getLayerId(layer, layers || []);
dispatch(addLayer({...layer, id}));
if (layer.type === 'wms') {
diff --git a/web/client/actions/queryform.js b/web/client/actions/queryform.js
index d2219f193e..74541a2992 100644
--- a/web/client/actions/queryform.js
+++ b/web/client/actions/queryform.js
@@ -17,6 +17,7 @@ const EXPAND_ATTRIBUTE_PANEL = 'EXPAND_ATTRIBUTE_PANEL';
const EXPAND_SPATIAL_PANEL = 'EXPAND_SPATIAL_PANEL';
const SELECT_SPATIAL_METHOD = 'SELECT_SPATIAL_METHOD';
const SELECT_SPATIAL_OPERATION = 'SELECT_SPATIAL_OPERATION';
+const CHANGE_SPATIAL_ATTRIBUTE = 'CHANGE_SPATIAL_ATTRIBUTE';
const REMOVE_SPATIAL_SELECT = 'REMOVE_SPATIAL_SELECT';
const SHOW_SPATIAL_DETAILS = 'SHOW_SPATIAL_DETAILS';
// const QUERY_FORM_SEARCH = 'QUERY_FORM_SEARCH';
@@ -133,6 +134,13 @@ function selectSpatialOperation(operation, fieldName) {
};
}
+function changeSpatialAttribute(attribute) {
+ return {
+ type: CHANGE_SPATIAL_ATTRIBUTE,
+ attribute
+ };
+}
+
function removeSpatialSelection() {
return {
type: REMOVE_SPATIAL_SELECT
@@ -159,7 +167,6 @@ function changeDwithinValue(distance) {
response: response
};
}
-
function wfsLoadError(e) {
return {
type: WFS_LOAD_ERROR,
@@ -297,6 +304,7 @@ module.exports = {
EXPAND_SPATIAL_PANEL,
SELECT_SPATIAL_METHOD,
SELECT_SPATIAL_OPERATION,
+ CHANGE_SPATIAL_ATTRIBUTE,
REMOVE_SPATIAL_SELECT,
SHOW_SPATIAL_DETAILS,
// QUERY_FORM_SEARCH,
@@ -333,6 +341,7 @@ module.exports = {
expandSpatialFilterPanel,
selectSpatialMethod,
selectSpatialOperation,
+ changeSpatialAttribute,
removeSpatialSelection,
showSpatialSelectionDetails,
query,
diff --git a/web/client/actions/wfsquery.js b/web/client/actions/wfsquery.js
index c27a8feef0..ac601462d5 100644
--- a/web/client/actions/wfsquery.js
+++ b/web/client/actions/wfsquery.js
@@ -76,26 +76,6 @@ function queryError(error) {
};
}
-function describeFeatureType(baseUrl, typeName) {
- return (dispatch) => {
- return axios.get(baseUrl + '?service=WFS&version=1.1.0&request=DescribeFeatureType&typeName=' + typeName + '&outputFormat=application/json').then((response) => {
- if (typeof response.data === 'object') {
- dispatch(featureTypeLoaded(typeName, response.data));
- } else {
- try {
- JSON.parse(response.data);
- } catch(e) {
- dispatch(featureTypeError(typeName, 'Error from WFS: ' + e.message));
- }
-
- }
-
- }).catch((e) => {
- dispatch(featureTypeError(typeName, e));
- });
- };
-}
-
function loadFeature(baseUrl, typeName) {
return (dispatch) => {
return axios.get(baseUrl + '?service=WFS&version=1.1.0&request=GetFeature&typeName=' + typeName + '&outputFormat=application/json').then((response) => {
@@ -196,7 +176,8 @@ module.exports = {
QUERY_ERROR,
RESET_QUERY,
featureTypeSelected,
- describeFeatureType,
+ featureTypeLoaded,
+ featureTypeError,
loadFeature,
createQuery,
query,
diff --git a/web/client/components/data/query/QueryBuilder.jsx b/web/client/components/data/query/QueryBuilder.jsx
index aa5a723d10..33786527ee 100644
--- a/web/client/components/data/query/QueryBuilder.jsx
+++ b/web/client/components/data/query/QueryBuilder.jsx
@@ -87,8 +87,7 @@ const QueryBuilder = React.createClass({
onUpdateLogicCombo: () => {},
onRemoveGroupField: () => {},
onChangeCascadingValue: () => {},
- onExpandAttributeFilterPanel: () => {},
- onLoadFeatureTypeConfig: () => {}
+ onExpandAttributeFilterPanel: () => {}
},
spatialFilterActions: {
onExpandSpatialFilterPanel: () => {},
@@ -107,19 +106,6 @@ const QueryBuilder = React.createClass({
}
};
},
- componentDidMount() {
- if (this.props.featureTypeConfigUrl && this.props.attributes.length < 1) {
- this.props.attributeFilterActions.onLoadFeatureTypeConfig(
- this.props.featureTypeConfigUrl, this.props.params);
- }
- },
- componentWillReceiveProps(props) {
- let url = props.featureTypeConfigUrl;
- let params = props.params !== this.props.params ? props.params : this.props.params;
- if (url !== this.props.featureTypeConfigUrl) {
- this.props.attributeFilterActions.onLoadFeatureTypeConfig(url, params);
- }
- },
render() {
if (this.props.featureTypeError !== "") {
return (
{this.props.featureTypeErrorText}
);
diff --git a/web/client/components/data/query/__tests__/QueryBuilder-test.jsx b/web/client/components/data/query/__tests__/QueryBuilder-test.jsx
index 1ad5fdaffe..734add2b4b 100644
--- a/web/client/components/data/query/__tests__/QueryBuilder-test.jsx
+++ b/web/client/components/data/query/__tests__/QueryBuilder-test.jsx
@@ -145,20 +145,13 @@ describe('QueryBuilder', () => {
it('creates the QueryBuilder component in error state', () => {
- let attributeFilterActions = {
- onLoadFeatureTypeConfig: () => {}
- };
- let spy = expect.spyOn(attributeFilterActions, 'onLoadFeatureTypeConfig');
-
const querybuilder = ReactDOM.render(,
document.getElementById("container"));
expect(querybuilder).toExist();
- expect(spy.calls.length).toEqual(1);
});
it('creates the QueryBuilder component with empty filter support', () => {
diff --git a/web/client/epics/wfsquery.js b/web/client/epics/wfsquery.js
new file mode 100644
index 0000000000..fe37e2b15b
--- /dev/null
+++ b/web/client/epics/wfsquery.js
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2017, 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.
+ */
+
+const Rx = require('rxjs');
+const axios = require('../libs/ajax');
+const {changeSpatialAttribute} = require('../actions/queryform');
+const {FEATURE_TYPE_SELECTED, featureTypeLoaded, featureTypeError} = require('../actions/wfsquery');
+
+const types = {
+ 'xsd:string': 'string',
+ 'xsd:dateTime': 'date',
+ 'xsd:number': 'number',
+ 'xsd:int': 'number'
+};
+const fieldConfig = {};
+const extractInfo = (data) => {
+ return {
+ geometry: data.featureTypes[0].properties
+ .filter((attribute) => attribute.type.indexOf('gml:') === 0)
+ .map((attribute) => {
+ let conf = {
+ label: attribute.name,
+ attribute: attribute.name,
+ type: 'geometry',
+ valueId: "id",
+ valueLabel: "name",
+ values: []
+ };
+ conf = fieldConfig[attribute.name] ? {...conf, ...fieldConfig[attribute.name]} : conf;
+ return conf;
+ }),
+ attributes: data.featureTypes[0].properties
+ .filter((attribute) => attribute.type.indexOf('gml:') !== 0)
+ .map((attribute) => {
+ let conf = {
+ label: attribute.name,
+ attribute: attribute.name,
+ type: types[attribute.type],
+ valueId: "id",
+ valueLabel: "name",
+ values: []
+ };
+ conf = fieldConfig[attribute.name] ? {...conf, ...fieldConfig[attribute.name]} : conf;
+ return conf;
+ })
+ };
+};
+
+const featureTypeSelectedEpic = action$ =>
+ action$.ofType(FEATURE_TYPE_SELECTED).switchMap(action => {
+ return Rx.Observable.defer( () =>
+ axios.get(action.url + '?service=WFS&version=1.1.0&request=DescribeFeatureType&typeName=' + action.typeName + '&outputFormat=application/json'))
+ .map((response) => {
+ if (typeof response.data === 'object' && response.data.featureTypes && response.data.featureTypes[0]) {
+ const info = extractInfo(response.data);
+ const geometry = info.geometry[0] && info.geometry[0].attribute ? info.geometry[0].attribute : 'the_geom';
+ return Rx.Observable.from([featureTypeLoaded(action.typeName, info), changeSpatialAttribute(geometry)]);
+ }
+ try {
+ JSON.parse(response.data);
+ } catch(e) {
+ return Rx.Observable.from([featureTypeError(action.typeName, 'Error from WFS: ' + e.message)]);
+ }
+ return Rx.Observable.from([featureTypeError(action.typeName, 'Error: feature types are empty')]);
+ })
+ .mergeAll()
+ .catch(e => Rx.Observable.of(featureTypeError(action.typeName, e.message)));
+ });
+
+module.exports = {
+ featureTypeSelectedEpic
+};
diff --git a/web/client/plugins/QueryPanel.jsx b/web/client/plugins/QueryPanel.jsx
index 492665f7b6..b506e16cef 100644
--- a/web/client/plugins/QueryPanel.jsx
+++ b/web/client/plugins/QueryPanel.jsx
@@ -24,6 +24,8 @@ const LayersUtils = require('../utils/LayersUtils');
// include application component
const QueryBuilder = require('../components/data/query/QueryBuilder');
+const {featureTypeSelectedEpic} = require('../epics/wfsquery');
+
const {bindActionCreators} = require('redux');
const {
// QueryBuilder action functions
@@ -234,5 +236,6 @@ module.exports = {
reducers: {
queryform: require('../reducers/queryform'),
query: require('../reducers/query')
- }
+ },
+ epics: {featureTypeSelectedEpic}
};
diff --git a/web/client/plugins/TOC.jsx b/web/client/plugins/TOC.jsx
index 6bc20641fa..f61d991c5f 100644
--- a/web/client/plugins/TOC.jsx
+++ b/web/client/plugins/TOC.jsx
@@ -52,7 +52,7 @@ const {
zoneChange
} = require('../actions/queryform');
-const {createQuery, toggleQueryPanel, describeFeatureType} = require('../actions/wfsquery');
+const {createQuery, toggleQueryPanel} = require('../actions/wfsquery');
const {
changeDrawingStatus,
@@ -92,9 +92,6 @@ const SmartQueryForm = connect((state) => {
return {
attributeFilterActions: bindActionCreators({
- onLoadFeatureTypeConfig: (url, params) => {
- return describeFeatureType(url, params.typeName);
- },
onAddGroupField: addGroupField,
onAddFilterField: addFilterField,
onRemoveFilterField: removeFilterField,
diff --git a/web/client/reducers/query.js b/web/client/reducers/query.js
index 1f47ef5be0..a77565356c 100644
--- a/web/client/reducers/query.js
+++ b/web/client/reducers/query.js
@@ -24,32 +24,6 @@ const {RESET_CONTROLS} = require('../actions/controls');
const assign = require('object-assign');
-const types = {
- 'xsd:string': 'string',
- 'xsd:dateTime': 'date',
- 'xsd:number': 'number',
- 'xsd:int': 'number'
-};
-const fieldConfig = {};
-const extractInfo = (featureType) => {
- return {
- attributes: featureType.featureTypes[0].properties
- .filter((attribute) => attribute.type.indexOf('gml:') !== 0)
- .map((attribute) => {
- let conf = {
- label: attribute.name,
- attribute: attribute.name,
- type: types[attribute.type],
- valueId: "id",
- valueLabel: "name",
- values: []
- };
- conf = fieldConfig[attribute.name] ? {...conf, ...fieldConfig[attribute.name]} : conf;
- return conf;
- })
- };
-};
-
const extractData = (feature) => {
return ['STATE_NAME', 'STATE_ABBR', 'SUB_REGION', 'STATE_FIPS' ].map((attribute) => ({
attribute,
@@ -86,7 +60,7 @@ function query(state = initialState, action) {
}
case FEATURE_TYPE_LOADED: {
return assign({}, state, {
- featureTypes: assign({}, state.featureTypes, {[action.typeName]: extractInfo(action.featureType)})
+ featureTypes: assign({}, state.featureTypes, {[action.typeName]: action.featureType})
});
}
case FEATURE_TYPE_ERROR: {
diff --git a/web/client/reducers/queryform.js b/web/client/reducers/queryform.js
index fe658a75f2..0ed268517c 100644
--- a/web/client/reducers/queryform.js
+++ b/web/client/reducers/queryform.js
@@ -19,6 +19,7 @@ const {
EXPAND_SPATIAL_PANEL,
SELECT_SPATIAL_METHOD,
SELECT_SPATIAL_OPERATION,
+ CHANGE_SPATIAL_ATTRIBUTE,
REMOVE_SPATIAL_SELECT,
SHOW_SPATIAL_DETAILS,
QUERY_FORM_RESET,
@@ -167,6 +168,9 @@ function queryform(state = initialState, action) {
case SELECT_SPATIAL_OPERATION: {
return assign({}, state, {spatialField: assign({}, state.spatialField, {[action.fieldName]: action.operation})});
}
+ case CHANGE_SPATIAL_ATTRIBUTE: {
+ return assign({}, state, { spatialField: assign({}, state.spatialField, {attribute: action.attribute}) });
+ }
case CHANGE_DRAWING_STATUS: {
if (action.owner === "queryform" && action.status === "start") {
return assign({}, state, {toolbarEnabled: false});