Skip to content

Commit

Permalink
Add pagination to feature Grid (#1367)
Browse files Browse the repository at this point in the history
First version of the pagination for the FeatureGrid plugin (#1320)
 - Renamed state variables in consistend way
 - Fixed pagination (no virtual pagination for now)
 - Add pagination disabled mode
  • Loading branch information
offtherailz authored Jan 9, 2017
1 parent 5f1edc2 commit c95bab9
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 62 deletions.
32 changes: 26 additions & 6 deletions web/client/actions/wfsquery.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ const FEATURE_TYPE_LOADED = 'FEATURE_TYPE_LOADED';
const FEATURE_LOADED = 'FEATURE_LOADED';
const FEATURE_TYPE_ERROR = 'FEATURE_TYPE_ERROR';
const FEATURE_ERROR = 'FEATURE_ERROR';
const QUERY_CREATE = 'QUERY_CREATE';
const QUERY_RESULT = 'QUERY_RESULT';
const QUERY_ERROR = 'QUERY_ERROR';
const RESET_QUERY = 'RESET_QUERY';

const axios = require('../libs/ajax');

const {toggleControl, setControlProperty} = require('./controls');

const FilterUtils = require('../utils/FilterUtils');
function featureTypeSelected(url, typeName) {
return {
type: FEATURE_TYPE_SELECTED,
Expand Down Expand Up @@ -57,9 +57,11 @@ function featureError(typeName, error) {
};
}

function querySearchResponse(result) {
function querySearchResponse(result, searchUrl, filterObj) {
return {
type: QUERY_RESULT,
searchUrl,
filterObj,
result
};
}
Expand Down Expand Up @@ -110,14 +112,30 @@ function loadFeature(baseUrl, typeName) {
});
};
}
function createQuery(searchUrl, filterObj) {
return {
type: QUERY_CREATE,
searchUrl,
filterObj
};
}

function query(seachURL, data) {
function query(searchUrl, filterObj) {
createQuery(searchUrl, filterObj);
let data;
if (typeof filterObj === 'string') {
data = filterObj;
} else {
data = filterObj.filterType === "OGC" ?
FilterUtils.toOGCFilter(filterObj.featureTypeName, filterObj, filterObj.ogcVersion, filterObj.sortOptions, filterObj.hits) :
FilterUtils.toCQLFilter(filterObj);
}
return (dispatch) => {
return axios.post(seachURL + '?service=WFS&&outputFormat=json', data, {
return axios.post(searchUrl + '?service=WFS&&outputFormat=json', data, {
timeout: 60000,
headers: {'Accept': 'application/json', 'Content-Type': 'application/json'}
}).then((response) => {
dispatch(querySearchResponse(response.data));
dispatch(querySearchResponse(response.data, searchUrl, filterObj));
}).catch((e) => {
dispatch(queryError(e));
});
Expand Down Expand Up @@ -145,12 +163,14 @@ module.exports = {
FEATURE_LOADED,
FEATURE_TYPE_ERROR,
FEATURE_ERROR,
QUERY_CREATE,
QUERY_RESULT,
QUERY_ERROR,
RESET_QUERY,
featureTypeSelected,
describeFeatureType,
loadFeature,
createQuery,
query,
resetQuery,
toggleQueryPanel
Expand Down
71 changes: 30 additions & 41 deletions web/client/components/data/featuregrid/DockedFeatureGrid.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const {head} = require('lodash');
const I18N = require('../../../components/I18N/I18N');
const Spinner = require('react-spinkit');
const assign = require('object-assign');
const {isEqual} = require('lodash');

require("./featuregrid.css");

Expand Down Expand Up @@ -48,13 +49,11 @@ const DockedFeatureGrid = React.createClass({
selectFeatures: React.PropTypes.func,
totalFeatures: React.PropTypes.number,
pagination: React.PropTypes.bool,
filterFields: React.PropTypes.array,
groupFields: React.PropTypes.array,
spatialField: React.PropTypes.object,
featureTypeName: React.PropTypes.string,
ogcVersion: React.PropTypes.string,
onQuery: React.PropTypes.func,
searchUrl: React.PropTypes.string,
filterObj: React.PropTypes.object,
dataSourceOptions: React.PropTypes.object,
withMap: React.PropTypes.bool.isRequired,
onConfigureQuery: React.PropTypes.func,
Expand Down Expand Up @@ -85,15 +84,15 @@ const DockedFeatureGrid = React.createClass({
featureTypeName: null,
ogcVersion: "2.0",
columnsDef: [],
pagination: false,
pagination: true,
params: {},
groupFields: [],
filterFields: [],
spatialField: {},
searchUrl: null,
dataSourceOptions: {
rowCount: -1,
pageSize: 10
pageSize: 20
},
initWidth: 600,
withMap: true,
Expand All @@ -113,15 +112,6 @@ const DockedFeatureGrid = React.createClass({
componentWillMount() {
let height = getWindowSize().maxHeight - 108;
this.setState({width: `calc( ${this.props.initWidth} - 30px)`, height});
if (this.props.pagination && this.props.dataSourceOptions.pageSize) {
this.dataSource = this.getDataSource(this.props.dataSourceOptions);
}else if ( this.props.pagination && !this.props.dataSourceOptions.pageSize) {
let newFilter = FilterUtils.getOgcAllPropertyValue(this.props.featureTypeName, this.props.attributes[0].attribute);
this.props.onConfigureQuery(this.props.searchUrl, newFilter, this.props.params, {
"maxFeatures": 15,
"startIndex": 0
});
}
},
shouldComponentUpdate(nextProps) {
return Object.keys(this.props).reduce((prev, prop) => {
Expand All @@ -135,10 +125,18 @@ const DockedFeatureGrid = React.createClass({
if (!nextProps.loadingGrid && nextProps.pagination && (nextProps.dataSourceOptions !== this.props.dataSourceOptions)) {
this.dataSource = this.getDataSource(nextProps.dataSourceOptions);
}
if (!nextProps.loadingGrid && this.featureLoaded && nextProps.features !== this.props.features && Object.keys(nextProps.features).length > 0) {
let rowsThisPage = nextProps.features[this.getRequestId(this.featureLoaded)] || [];
this.featureLoaded.successCallback(rowsThisPage, nextProps.totalFeatures);
this.featureLoaded = null;
if (!nextProps.loadingGrid && this.featureLoaded && nextProps.features !== this.props.features) {
let rowsThisPage = nextProps.features || [];
if (rowsThisPage) {
this.featureLoaded.successCallback(rowsThisPage, nextProps.totalFeatures);
}
}
},
componentDidUpdate(prevProps) {
if (!this.props.loadingGrid && !this.featureLoaded && !this.props.pagination && this.props.searchUrl) {
if (this.props.filterObj && !isEqual(prevProps.filterObj, this.props.filterObj)) {
this.getFeatures();
}
}
},
onGridClose(filter) {
Expand All @@ -164,31 +162,24 @@ const DockedFeatureGrid = React.createClass({
return params.sortModel.reduce((o, m) => ({sortBy: this.getSortAttribute(m.colId), sortOrder: m.sort}), {});
},
getFeatures(params) {
if (!this.props.loadingGrid) {
let reqId = this.getRequestId(params);
let rowsThisPage = this.props.features[reqId];
if (rowsThisPage) {
params.successCallback(rowsThisPage, this.props.totalFeatures);
}else {
let pagination = {startIndex: params.startRow, maxFeatures: params.endRow - params.startRow};
let filterObj = {
groupFields: this.props.groupFields,
filterFields: this.props.filterFields.filter((field) => field.value),
spatialField: this.props.spatialField,
if (!this.props.loadingGrid && this.props.searchUrl) {
let pagination = this.props.pagination ? {startIndex: params.startRow, maxFeatures: params.endRow - params.startRow} : null;
let filterObj = {
...this.props.filterObj,
sortOptions: params && params.sortModel && this.getSortOptions(params) || null,
pagination
};
let filter = FilterUtils.toOGCFilter(this.props.featureTypeName, filterObj, this.props.ogcVersion, this.getSortOptions(params));
this.featureLoaded = params;
this.sortModel = params.sortModel;
this.props.onQuery(this.props.searchUrl, filter, this.props.params, reqId);
}
};
this.featureLoaded = params;
this.sortModel = params && params.sortModel;
this.props.onQuery(this.props.searchUrl, filterObj, this.props.params);

}
},
getDataSource(dataSourceOptions) {
return {
rowCount: dataSourceOptions.rowCount,
getRows: this.getFeatures,
pageSize: dataSourceOptions.pageSize,
pageSize: this.props.pagination ? dataSourceOptions.pageSize : 10000000,
overflowSize: 20
};
},
Expand Down Expand Up @@ -242,9 +233,9 @@ const DockedFeatureGrid = React.createClass({
});
}

let gridConf = this.props.pagination ? {dataSource: this.dataSource, features: []} : {features: this.props.features};
let gridConf = this.props.pagination ? {dataSource: this.getDataSource(this.props.dataSourceOptions), features: []} : {features: this.props.features};

if (this.props.features && this.props.features.length > 0) {
if (this.props.filterObj) {
return (
<Dock
position={"bottom" /* 'left', 'top', 'right', 'bottom' */}
Expand Down Expand Up @@ -306,9 +297,7 @@ const DockedFeatureGrid = React.createClass({
selectAll(select) {
if (select) {
let filterObj = {
groupFields: this.props.groupFields,
filterFields: this.props.filterFields.filter((field) => field.value),
spatialField: this.props.spatialField
...this.props.filterObj
};
let SLD_BODY = FilterUtils.getSLD(this.props.featureTypeName, filterObj, '1.0');
this.props.selectAllToggle(this.props.featureTypeName, SLD_BODY);
Expand Down
4 changes: 2 additions & 2 deletions web/client/components/data/featuregrid/FeatureGrid.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ const FeatureGrid = React.createClass({
virtualPaging: false,
paging: false,
overflowSize: 10,
pageSize: 15,
pageSize: 10,
agGridOptions: {},
columnDefaultOptions: {
width: 125
Expand Down Expand Up @@ -150,7 +150,7 @@ const FeatureGrid = React.createClass({
}

if (this.props.toolbar.selectAll) {
let nOfFeatures = this.props.features.length;
let nOfFeatures = this.props.features && this.props.features.length;
if (this.props.paging && this.api) {
nOfFeatures = 0;
this.api.forEachNode(() => {nOfFeatures++; });
Expand Down
15 changes: 7 additions & 8 deletions web/client/components/data/query/QueryToolbar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ const React = require('react');
const {Button, Glyphicon, ButtonToolbar, Modal} = require('react-bootstrap');

const I18N = require('../../I18N/I18N');
const FilterUtils = require('../../../utils/FilterUtils');

const QueryToolbar = React.createClass({
propTypes: {
Expand Down Expand Up @@ -94,17 +93,17 @@ const QueryToolbar = React.createClass({
},
search() {
let filterObj = {
featureTypeName: this.props.featureTypeName,
groupFields: this.props.groupFields,
filterFields: this.props.filterFields.filter((field) => field.value),
spatialField: this.props.spatialField,
pagination: this.props.pagination
pagination: this.props.pagination,
filterType: this.props.filterType,
ogcVersion: this.props.ogcVersion,
sortOptions: this.props.sortOptions,
hits: this.props.hits
};

let filter = this.props.filterType === "OGC" ?
FilterUtils.toOGCFilter(this.props.featureTypeName, filterObj, this.props.ogcVersion, this.props.sortOptions, this.props.hits) :
FilterUtils.toCQLFilter(filterObj);

this.props.actions.onQuery(this.props.searchUrl, filter, this.props.params);
this.props.actions.onQuery(this.props.searchUrl, filterObj, this.props.params);
},
reset() {
this.props.actions.onChangeDrawingStatus('clean', null, "queryform", []);
Expand Down
7 changes: 6 additions & 1 deletion web/client/plugins/FeatureGrid.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@
*/
const {connect} = require('react-redux');
const {updateHighlighted} = require('../actions/highlight');
const {query} = require('../actions/wfsquery');

module.exports = {
FeatureGridPlugin: connect((state) => ({
features: state.query && state.query.result && state.query.result.features,
filterObj: state.query && state.query.filterObj,
searchUrl: state.query && state.query.searchUrl,
initWidth: "100%",
columnsDef: state.query && state.query.typeName && state.query.featureTypes
&& state.query.featureTypes[state.query.typeName]
Expand All @@ -21,9 +24,11 @@ module.exports = {
headerName: attr.label,
field: attr.attribute
})),
query: state.query && state.query.queryObj,
totalFeatures: state.query && state.query.result && state.query.result.totalFeatures
}),
{
selectFeatures: updateHighlighted
selectFeatures: updateHighlighted,
onQuery: query
})(require('../components/data/featuregrid/DockedFeatureGrid'))
};
4 changes: 2 additions & 2 deletions web/client/plugins/QueryPanel.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const {
zoneChange
} = require('../actions/queryform');

const {query} = require('../actions/wfsquery');
const {createQuery} = require('../actions/wfsquery');

const {
changeDrawingStatus,
Expand Down Expand Up @@ -104,7 +104,7 @@ const SmartQueryForm = connect((state) => {
zoneChange
}, dispatch),
queryToolbarActions: bindActionCreators({
onQuery: query,
onQuery: createQuery,
onReset: reset,
onChangeDrawingStatus: changeDrawingStatus
}, dispatch)
Expand Down
4 changes: 2 additions & 2 deletions web/client/plugins/TOC.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const {
zoneChange
} = require('../actions/queryform');

const {query, toggleQueryPanel, describeFeatureType} = require('../actions/wfsquery');
const {createQuery, toggleQueryPanel, describeFeatureType} = require('../actions/wfsquery');

const {
changeDrawingStatus,
Expand Down Expand Up @@ -114,7 +114,7 @@ const SmartQueryForm = connect((state) => {
zoneChange
}, dispatch),
queryToolbarActions: bindActionCreators({
onQuery: query,
onQuery: createQuery,
onReset: reset,
onChangeDrawingStatus: changeDrawingStatus
}, dispatch)
Expand Down
14 changes: 14 additions & 0 deletions web/client/reducers/query.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const {
FEATURE_TYPE_ERROR,
FEATURE_LOADED,
FEATURE_ERROR,
QUERY_CREATE,
QUERY_RESULT,
QUERY_ERROR,
RESET_QUERY
Expand Down Expand Up @@ -100,9 +101,17 @@ function query(state = initialState, action) {
featureTypes: assign({}, state.data, {[action.typeName]: {error: action.error}})
});
}
case QUERY_CREATE: {
return assign({}, state, {
searchUrl: action.searchUrl,
filterObj: action.filterObj
});
}
case QUERY_RESULT: {
return assign({}, state, {
result: action.result,
searchUrl: action.searchUrl,
filterObj: action.filterObj,
resultError: null
});
}
Expand All @@ -113,6 +122,11 @@ function query(state = initialState, action) {
});
}
case QUERY_FORM_RESET:
return assign({}, state, {
result: null,
filterObj: null,
searchUrl: null
});
case RESET_QUERY: {
return assign({}, state, {
result: null,
Expand Down

0 comments on commit c95bab9

Please sign in to comment.