Skip to content

Commit

Permalink
Merge pull request #325 from wri/317-layer-filter
Browse files Browse the repository at this point in the history
Sprint 5 -  v1.3.4 Add layer filter field option to layer panel
  • Loading branch information
SwampGuzzler authored Mar 27, 2019
2 parents 7a0256e + 83b9312 commit 3ef3b38
Show file tree
Hide file tree
Showing 14 changed files with 581 additions and 13 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
build:
docker:
# specify the version you desire here
- image: circleci/node:6.11-browsers
- image: circleci/node:8.9-browsers

working_directory: ~/repo

Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,14 @@
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-0": "^6.24.1",
"vega": "^3.0.7",
"highcharts": "^6.0.4",
"jest": "^22.0.4",
"moment": "^2.20.0",
"pug": "^2.0.0-rc.4",
"react": "^15.6.2",
"react-dom": "^15.6.2",
"react-test-renderer": "^15"
"react-test-renderer": "^15",
"vega": "^3.0.7"
},
"devDependencies": {
"babel-eslint": "^5.0.0-beta6",
Expand Down Expand Up @@ -116,6 +116,7 @@
"rc-slider": "^8.5.0",
"react-datepicker": "^0.64.0",
"react-prerender": "0.0.3",
"react-select": "^2.3.0",
"requirejs": "^2.3.3",
"style-loader": "^0.19.0",
"stylus-loader": "^3.0.1",
Expand Down
20 changes: 20 additions & 0 deletions src/css/layerPanel.styl
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,26 @@ div.legend-icon
.react-datepicker__triangle
display none !important

.layer-field-filter
width 100%
max-width 250px
margin 8px 5px

.layer-field-filter:hover
cursor text

.layer-field-filter p
font-size 11px
margin 5px 0

.layer-field-filter-select .css-1ep9fjw
padding 0 6px

.layer-field-filter-select svg
width 15px
height 15px
cursor pointer

.layer-versions
margin 5px 0
width 100%
Expand Down
4 changes: 4 additions & 0 deletions src/js/actions/MapActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,10 @@ class MapActions {
return obj;
}

setActiveFilters(obj) {
return obj;
}

changeLayerVersion(obj) {
return obj;
}
Expand Down
152 changes: 152 additions & 0 deletions src/js/components/LayerPanel/LayerFieldFilter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
import React, {Component, PropTypes} from 'react';
import QueryTask from 'esri/tasks/QueryTask';
import Query from 'esri/tasks/query';
import Select from 'react-select';
import mapActions from 'actions/MapActions';

const customStyles = {
option: (provided, state) => ({
...provided,
fontSize: '12px',
color: 'rgb(51, 51, 51)',
cursor: 'pointer',
background: state.isSelected ? '#eee' : 'none',
'&:hover': {
background: '#eee'
}
}),
control: (provided, state) => ({
...provided,
fontSize: '12px',
padding: '0px',
cursor: 'text',
minHeight: '30px',
boxShadow: state.isFocused ? 0 : 0,
borderColor: state.isFocused
? '#f0ab00'
: 'grey',
'&:hover': {
borderColor: state.isFocused
? '#f0ab00'
: 'grey',
}
}),

};

export default class LayerFieldFilter extends Component {

static contextTypes = {
language: PropTypes.string.isRequired,
map: PropTypes.object.isRequired
};

constructor (props) {
super(props);
this.state = {
value: 'None Selected',
filters: []
};

}

componentWillMount() {
// Make request for dropdown options..
const { layer } = this.props;
const { filters } = this.state;
const { language } = this.context;

if (layer.type === 'feature') {
const url = layer.url;
const queryTask = new QueryTask(url);
const query = new Query();
query.where = '1=1';
query.returnGeometry = false;
query.outFields = [layer.filterField[language]];
query.returnDistinctValues = true;
queryTask.execute(query).then(res => {
res.features.forEach((feature) => {
filters.push({label: feature.attributes[layer.filterField[language]], value: feature.attributes[layer.filterField[language]]});
});

this.setState({ filters });
});
} else if (layer.type === 'dynamic') {
const promises = [];

layer.layerIds.forEach((id) => {
const url = layer.url + '/' + layer.layerIds[id];
const queryTask = new QueryTask(url);
const query = new Query();
query.where = '1=1';
query.returnGeometry = false;
query.outFields = [layer.filterField[language]];
query.returnDistinctValues = true;
promises.push(queryTask.execute(query));
});

Promise.all(promises).then(results => {
results.forEach((res) => {
res.features.forEach((feature) => {
if (!filters.find((filter) => filter.label === feature.attributes[layer.filterField[language]].trim().length)) {
filters.push({label: feature.attributes[layer.filterField[language]], value: feature.attributes[layer.filterField[language]]});
}
});
});
this.setState({ filters });

});
}

}


onSelectFilter = (option) => {

const value = option ? option.value : null;
const { map, language } = this.context;
const { layer } = this.props;
const defExpression = !value ? '1=1' : `${layer.filterField[language]} = '${value}'`;
const mapLayer = map.getLayer(layer.id);

if (layer.type === 'feature') {
mapLayer.setDefinitionExpression(defExpression);
} else if (layer.type === 'dynamic') {
const layerDefinitions = [];
layer.layerIds.forEach((id) => {
layerDefinitions[id] = defExpression;
});
mapLayer.setLayerDefinitions(layerDefinitions);
}

mapActions.setActiveFilters({layerId: layer.id, value});
}

render () {
const { filters } = this.state;
const { language } = this.context;
const { layer } = this.props;

return (
<div className='layer-field-filter'>
{ filters.length > 0 &&
<div>
<p>{layer.filterLabel[language]}</p>
<div className='layer-filter relative'>
<Select
styles={customStyles}
onChange={this.onSelectFilter}
options={filters}
placeholder={'None Selected'}
isSearchable={true}
className={'layer-field-filter-select'}
isClearable={true}
/>
</div>
</div>
}

</div>
);
}
}
6 changes: 5 additions & 1 deletion src/js/components/LayerPanel/LayerPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import LossControls from 'components/LayerPanel/LossControls';
import GladControls from 'components/LayerPanel/GladControls';
import FormaControls from 'components/LayerPanel/FormaControls';
import SadControls from 'components/LayerPanel/SadControls';
import LayerFieldFilter from 'components/LayerPanel/LayerFieldFilter';
import LayerGroup from 'components/LayerPanel/LayerGroup';
import RadioGroup from 'components/LayerPanel/RadioGroup';
import NestedGroup from 'components/LayerPanel/NestedGroup';
Expand Down Expand Up @@ -168,6 +169,7 @@ export default class LayerPanel extends Component {
const {language} = this.context;
let childComponent, editCallback, dynamicSublabel, layerLoading;

// Set child component based on layer id
switch (layer.id) {
case 'VIIRS_ACTIVE_FIRES':
childComponent = <FiresControls
Expand Down Expand Up @@ -238,7 +240,9 @@ export default class LayerPanel extends Component {
childComponent = <TerraIControls layer={layer} startDate={terraIStartDate} endDate={terraIEndDate}/>;
break;
default:
if (layer.versions && layer.versions.length > 0 && (layer.type === 'feature' || layer.type === 'dynamic')) {
if (layer.filterField && (layer.type === 'dynamic' || layer.type === 'feature')) {
childComponent = <LayerFieldFilter layer={layer} />;
} else if (layer.versions && layer.versions.length > 0 && (layer.type === 'feature' || layer.type === 'dynamic')) {
childComponent = <LayerVersions layer={layer}/>;
} else {
childComponent = null;
Expand Down
8 changes: 8 additions & 0 deletions src/js/components/Shared/ReportSubscribe.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export default class ReportSubscribeButtons extends Component {
viirsEndDate,
modisStartDate,
modisEndDate,
activeFilters,
activeVersions
} = mapStore.getState();

Expand All @@ -69,6 +70,7 @@ export default class ReportSubscribeButtons extends Component {
selectedFeature,
canopyDensity,
settings,
activeFilters: [],
activeVersions: []
};

Expand All @@ -88,6 +90,12 @@ export default class ReportSubscribeButtons extends Component {
payload.layerId = layerString;
}

if (Object.keys(activeFilters).length) {
Object.keys(activeFilters).forEach((key) => {
payload.activeFilters.push(`${key}|${activeFilters[key]}`);
});
}

if (Object.keys(activeVersions).length) {
Object.keys(activeVersions).forEach((key) => {
payload.activeVersions.push(`${key}|${activeVersions[key]}`);
Expand Down
7 changes: 7 additions & 0 deletions src/js/languages.js
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ strings.en.TOOL_ANALYSIS = 'Analysis';
strings.en.TOOL_TOGGLE = 'Toggle Panel';
strings.en.TOOL_RESET = 'Reset';


strings.en.ANALYSIS_CARBON_EMISSION = 'Gross carbon emissions';
strings.en.ANALYSIS_CARBON_LOSS = 'Tree cover loss';
strings.en.ANALYSIS_SLOPE_CHART_HEADER = 'Slope';
Expand Down Expand Up @@ -508,6 +509,7 @@ strings.ka.TOOL_TOGGLE = 'Toggle Panel (გადართვის პანე
strings.ka.TOOL_RESET = 'გადატვირთვა';



strings.ka.ANALYSIS_CARBON_EMISSION = 'კარბონის მთლიანი ემისიები';
strings.ka.ANALYSIS_CARBON_LOSS = 'კარბონის კარგვა';
strings.ka.ANALYSIS_SLOPE_CHART_HEADER = 'ფერდობი';
Expand Down Expand Up @@ -778,6 +780,7 @@ strings.fr.TOOL_ANALYSIS = 'Analyse';
strings.fr.TOOL_TOGGLE = 'Basculer panneau';
strings.fr.TOOL_RESET = 'Réinitialiser';


strings.fr.ANALYSIS_CARBON_EMISSION = 'Emissions de carbone brutes';
strings.fr.ANALYSIS_CARBON_LOSS = 'Perte en couvert arboré';
strings.fr.ANALYSIS_SLOPE_CHART_HEADER = 'Slope';
Expand Down Expand Up @@ -1049,6 +1052,7 @@ strings.es.TOOL_ANALYSIS = 'Análisis';
strings.es.TOOL_TOGGLE = 'Alternar Pane';
strings.es.TOOL_RESET = 'Reajustar';


strings.es.ANALYSIS_CARBON_EMISSION = 'Emisiones de dióxido de carbono';
strings.es.ANALYSIS_CARBON_LOSS = 'Pérdida de cobertura arbórea';
strings.es.ANALYSIS_SLOPE_CHART_HEADER = 'Slope';
Expand Down Expand Up @@ -1319,6 +1323,7 @@ strings.pt.TOOL_ANALYSIS = 'Análise';
strings.pt.TOOL_TOGGLE = 'Alternar Painel';
strings.pt.TOOL_RESET = 'Reiniciar';


strings.pt.ANALYSIS_CARBON_EMISSION = 'Taxa de emissões de carbono';
strings.pt.ANALYSIS_CARBON_LOSS = 'Perda de cobertura florestal';
strings.pt.ANALYSIS_SLOPE_CHART_HEADER = 'Slope';
Expand Down Expand Up @@ -1589,6 +1594,7 @@ strings.id.TOOL_ANALYSIS = 'Analysis';
strings.id.TOOL_TOGGLE = 'Toggle Panel';
strings.id.TOOL_RESET = 'Reset';


strings.id.ANALYSIS_CARBON_EMISSION = 'Gross carbon emissions';
strings.id.ANALYSIS_CARBON_LOSS = 'Tree cover loss';
strings.id.ANALYSIS_SLOPE_CHART_HEADER = 'Slope';
Expand Down Expand Up @@ -1860,6 +1866,7 @@ strings.zh.TOOL_ANALYSIS = '分析';
strings.zh.TOOL_TOGGLE = '控制面板';
strings.zh.TOOL_RESET = '重置';


strings.zh.ANALYSIS_CARBON_EMISSION = 'Gross carbon emissions';
strings.zh.ANALYSIS_CARBON_LOSS = 'Tree cover loss';
strings.zh.ANALYSIS_SLOPE_CHART_HEADER = 'Slope';
Expand Down
Loading

0 comments on commit 3ef3b38

Please sign in to comment.