Skip to content
Snippets Groups Projects
Commit 7787456f authored by Esko Ikkala's avatar Esko Ikkala
Browse files

Add result fetching

Co-authored-by Heino Erkki <erkki.heino@aalto.fi>
parent 44877509
No related branches found
No related tags found
No related merge requests found
......@@ -6,6 +6,7 @@ export const FETCH_SUGGESTIONS_FAILED = 'FETCH_SUGGESTIONS_FAILED';
export const UPDATE_SUGGESTIONS = 'UPDATE_SUGGESTIONS';
export const CLEAR_SUGGESTIONS = 'CLEAR_SUGGESTIONS';
export const FETCH_RESULTS = 'FETCH_RESULTS';
export const FETCH_RESULTS_FAILED = 'FETCH_RESULTS_FAILED';
export const UPDATE_RESULTS = 'UPDATE_RESULTS';
export const CLEAR_RESULTS = 'CLEAR_RESULTS';
export const CLEAR_ERROR = 'CLEAR_ERROR';
......@@ -34,6 +35,11 @@ export const fetchSuggestionsFailed = (error) => ({
error
});
export const fetchResultsFailed = (error) => ({
type: FETCH_RESULTS_FAILED,
error
});
export const updateSuggestions = ({ results }) => ({
type: UPDATE_SUGGESTIONS,
results
......
......@@ -74,6 +74,7 @@ const styles = theme => ({
const IntegrationAutosuggest = (props) => {
const handleOnChange = (event, { newValue }) => props.updateQuery(newValue);
const handleOnSuggestionSelected = (event, { suggestion }) => props.fetchResults(suggestion);
const { classes } = props;
......@@ -96,6 +97,7 @@ const IntegrationAutosuggest = (props) => {
renderSuggestionsContainer={renderSuggestionsContainer}
getSuggestionValue={getSuggestionValue}
renderSuggestion={renderSuggestion}
onSuggestionSelected={handleOnSuggestionSelected}
inputProps={{
classes,
placeholder: 'Search place names',
......@@ -112,6 +114,7 @@ IntegrationAutosuggest.propTypes = {
updateQuery: PropTypes.func.isRequired,
fetchSuggestions: PropTypes.func.isRequired,
clearSuggestions: PropTypes.func.isRequired,
fetchResults: PropTypes.func.isRequired,
};
export default withStyles(styles)(IntegrationAutosuggest);
......@@ -12,7 +12,7 @@ import IconButton from 'material-ui/IconButton';
import MenuIcon from '@material-ui/icons/Menu';
import IntegrationAutosuggest from '../components/IntegrationAutosuggest';
import LeafletMapContainer from '../components/LeafletMapContainer';
import { updateQuery, updateDatasets, fetchSuggestions, clearSuggestions } from '../actions';
import { updateQuery, updateDatasets, fetchSuggestions, clearSuggestions, fetchResults } from '../actions';
import Message from '../components/Message';
......@@ -50,14 +50,19 @@ let FullWidthGrid = (props) => {
<MenuIcon />
</IconButton>
<Grid item xs={3}>
<IntegrationAutosuggest search={props.search} updateQuery={props.updateQuery}
fetchSuggestions={props.fetchSuggestions} clearSuggestions={props.clearSuggestions} />
<IntegrationAutosuggest
search={props.search}
updateQuery={props.updateQuery}
fetchSuggestions={props.fetchSuggestions}
clearSuggestions={props.clearSuggestions}
fetchResults={props.fetchResults}
/>
</Grid>
</Toolbar>
</AppBar>
</Grid>
<Grid item xs={12}>
<LeafletMapContainer />
<LeafletMapContainer places={props.search.results} />
</Grid>
</Grid>
</div>
......@@ -74,6 +79,7 @@ const mapDispatchToProps = ({
updateDatasets,
fetchSuggestions,
clearSuggestions,
fetchResults,
});
FullWidthGrid.propTypes = {
......@@ -83,6 +89,7 @@ FullWidthGrid.propTypes = {
updateQuery: PropTypes.func.isRequired,
fetchSuggestions: PropTypes.func.isRequired,
clearSuggestions: PropTypes.func.isRequired,
fetchResults: PropTypes.func.isRequired,
};
FullWidthGrid = connect(
......
......@@ -3,10 +3,17 @@ import _ from 'lodash';
import { ajax } from 'rxjs/observable/dom/ajax';
import { combineEpics } from 'redux-observable';
import { Observable } from 'rxjs/Observable';
import { updateSuggestions, FETCH_SUGGESTIONS, FETCH_SUGGESTIONS_FAILED } from '../actions';
import {
updateSuggestions,
updateResults,
FETCH_SUGGESTIONS,
FETCH_SUGGESTIONS_FAILED,
FETCH_RESULTS,
FETCH_RESULTS_FAILED,
} from '../actions';
const getSuggestionsEpic = (action$, store) => {
const searchUrl = 'http://localhost:3000/search';
const searchUrl = 'http://localhost:3000/suggest';
return action$.ofType(FETCH_SUGGESTIONS)
.debounceTime(500)
......@@ -27,6 +34,27 @@ const getSuggestionsEpic = (action$, store) => {
});
};
const rootEpic = combineEpics(getSuggestionsEpic);
const getResultsEpic = (action$, store) => {
const searchUrl = 'http://localhost:3000/search';
return action$.ofType(FETCH_RESULTS)
.switchMap(() => {
const { query, datasets } = store.getState().search;
if (query.length < 3) {
return [];
}
const dsParams = _.map(datasets, ds => `dataset=${ds}`).join('&');
const requestUrl = `${searchUrl}?q=${query}&${dsParams}`;
return ajax.getJSON(requestUrl)
.map(response => updateResults({ results: response }))
.catch(error => Observable.of({
type: FETCH_RESULTS_FAILED,
error: error,
}));
});
};
const rootEpic = combineEpics(getSuggestionsEpic, getResultsEpic);
export default rootEpic;
import {
UPDATE_RESULTS,
CLEAR_RESULTS,
} from '../actions';
const results = (state = [], action) => {
switch (action.type) {
case UPDATE_RESULTS:
return action.results;
case CLEAR_RESULTS:
return [];
default:
return state;
}
};
export default results;
......@@ -3,13 +3,17 @@ import {
UPDATE_DATASETS,
UPDATE_SUGGESTIONS,
CLEAR_SUGGESTIONS,
UPDATE_RESULTS,
CLEAR_RESULTS
} from '../actions';
import suggestions from './suggestions';
import results from './results';
export const INITIAL_STATE = {
query: '',
datasets: ['warsa_karelian_places', 'warsa_municipalities'],
suggestions: [],
results: []
};
const search = (state = INITIAL_STATE, action) => {
......@@ -21,6 +25,9 @@ const search = (state = INITIAL_STATE, action) => {
case CLEAR_SUGGESTIONS:
case UPDATE_SUGGESTIONS:
return { ...state, suggestions: suggestions(state.suggestions, action) };
case CLEAR_RESULTS:
case UPDATE_RESULTS:
return { ...state, results: results(state.results, action) };
default:
return state;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment