homeflowjs 0.6.2 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/actions/search.actions.js +5 -0
- package/actions/search.types.js +1 -0
- package/package.json +1 -1
- package/properties/sort-order-select/sort-order-select.component.jsx +14 -7
- package/reducers/search.reducer.js +10 -0
- package/search/index.js +2 -0
- package/search/location-input/location-input.component.jsx +1 -1
- package/search/property-search/property-search.js +9 -12
- package/search/radius-select/radius-select.component.jsx +51 -21
- package/search/search-form/search-form.component.jsx +14 -4
|
@@ -6,6 +6,11 @@ export const setSearch = (payload) => ({
|
|
|
6
6
|
payload,
|
|
7
7
|
});
|
|
8
8
|
|
|
9
|
+
export const setInitialSearch = (payload) => ({
|
|
10
|
+
type: SearchActionTypes.SET_INITIAL_SEARCH,
|
|
11
|
+
payload,
|
|
12
|
+
});
|
|
13
|
+
|
|
9
14
|
export const setSuggestions = (payload) => ({
|
|
10
15
|
type: SearchActionTypes.SET_SUGGESTIONS,
|
|
11
16
|
payload,
|
package/actions/search.types.js
CHANGED
package/package.json
CHANGED
|
@@ -18,14 +18,14 @@ const SortOrderSelect = (props) => {
|
|
|
18
18
|
|
|
19
19
|
const { sorted } = search;
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
|
|
21
|
+
if (reactSelect) {
|
|
22
|
+
const handleChange = ({ value }) => {
|
|
23
|
+
const newSearch = { ...search };
|
|
24
|
+
newSearch.sorted = value;
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
propertySearch(newSearch);
|
|
27
|
+
};
|
|
27
28
|
|
|
28
|
-
if (reactSelect) {
|
|
29
29
|
const options = children.map((option) => {
|
|
30
30
|
const { value, children } = option.props;
|
|
31
31
|
return { value, label: children };
|
|
@@ -48,8 +48,15 @@ const SortOrderSelect = (props) => {
|
|
|
48
48
|
);
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
const handleChange = (e) => {
|
|
52
|
+
const newSearch = { ...search };
|
|
53
|
+
newSearch.sorted = e.target.value;
|
|
54
|
+
|
|
55
|
+
propertySearch(newSearch);
|
|
56
|
+
};
|
|
57
|
+
|
|
51
58
|
return (
|
|
52
|
-
<select onChange={handleChange} className={className}>
|
|
59
|
+
<select value={sorted} onChange={handleChange} className={className}>
|
|
53
60
|
{children}
|
|
54
61
|
</select>
|
|
55
62
|
);
|
|
@@ -10,6 +10,7 @@ const INITIAL_STATE = {
|
|
|
10
10
|
suggestions: [],
|
|
11
11
|
tags: [],
|
|
12
12
|
},
|
|
13
|
+
initialSearch: {}, // original search when the page first loads
|
|
13
14
|
savedSearches: [],
|
|
14
15
|
};
|
|
15
16
|
|
|
@@ -22,6 +23,14 @@ const searchReducer = (state = INITIAL_STATE, action) => {
|
|
|
22
23
|
...action.payload,
|
|
23
24
|
},
|
|
24
25
|
};
|
|
26
|
+
case SearchActionTypes.SET_INITIAL_SEARCH:
|
|
27
|
+
return {
|
|
28
|
+
...state,
|
|
29
|
+
initialSearch: {
|
|
30
|
+
...state.initialSearch,
|
|
31
|
+
...action.payload,
|
|
32
|
+
},
|
|
33
|
+
};
|
|
25
34
|
case SearchActionTypes.SET_SUGGESTIONS:
|
|
26
35
|
return {
|
|
27
36
|
...state,
|
|
@@ -60,6 +69,7 @@ const searchReducer = (state = INITIAL_STATE, action) => {
|
|
|
60
69
|
return {
|
|
61
70
|
...state,
|
|
62
71
|
currentSearch: {
|
|
72
|
+
...state.currentSearch,
|
|
63
73
|
tags: newTags,
|
|
64
74
|
},
|
|
65
75
|
};
|
package/search/index.js
CHANGED
|
@@ -10,6 +10,7 @@ import GenericSearchField from './generic-search-field/generic-search-field.comp
|
|
|
10
10
|
import GeolocateButton from './geolocate-button/geolocate-button.component';
|
|
11
11
|
import SaveSearchButton from './save-search-button/save-search-button.component';
|
|
12
12
|
import SavedSearch from './saved-search/saved-search.component';
|
|
13
|
+
import propertySearch from './property-search/property-search';
|
|
13
14
|
|
|
14
15
|
export {
|
|
15
16
|
SearchForm,
|
|
@@ -24,4 +25,5 @@ export {
|
|
|
24
25
|
GeolocateButton,
|
|
25
26
|
SaveSearchButton,
|
|
26
27
|
SavedSearch,
|
|
28
|
+
propertySearch,
|
|
27
29
|
}
|
|
@@ -14,7 +14,7 @@ class LocationInput extends Component {
|
|
|
14
14
|
super(props);
|
|
15
15
|
|
|
16
16
|
this.onLocationChange = this.onLocationChange.bind(this);
|
|
17
|
-
// wait
|
|
17
|
+
// wait half a second after typing stops before fetching results
|
|
18
18
|
this.debouncedLoadSuggestions = debounce(this.loadSuggestions, 500);
|
|
19
19
|
}
|
|
20
20
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { camelToSnakeCase } from '../../utils';
|
|
2
2
|
import base64 from '../../utils/base64';
|
|
3
3
|
import { FRAGMENT_BOOKENDS } from './constants';
|
|
4
|
+
import store from '../../store';
|
|
4
5
|
|
|
5
6
|
const fragmentize = (key, value) => {
|
|
6
7
|
const pattern = FRAGMENT_BOOKENDS[key];
|
|
@@ -9,19 +10,8 @@ const fragmentize = (key, value) => {
|
|
|
9
10
|
|
|
10
11
|
if (key === 'tags') return `${pattern[0]}${value.join(',')}`;
|
|
11
12
|
|
|
12
|
-
// let polyTest = "}`juHnrWzKaOpNrHdI|[?~j@{Krt@{M|pCoJlq@{KkSwCa]U}sB";
|
|
13
|
-
|
|
14
13
|
if (key === 'poly') return pattern[0] + base64.encode(value);
|
|
15
14
|
|
|
16
|
-
// let poly = "}`juHnrWzKaOpNrHdI|[?~j@{Krt@{M|pCoJlq@{KkSwCa]U}sB"
|
|
17
|
-
// undefined
|
|
18
|
-
// base64.encode(poly)
|
|
19
|
-
// "fWBqdUhucld6S2FPcE5ySGRJfFs_fmpAe0tydEB7TXxwQ29KbHFAe0trU3dDYV1VfXNC"
|
|
20
|
-
// btoa(poly)
|
|
21
|
-
// "fWBqdUhucld6S2FPcE5ySGRJfFs/fmpAe0tydEB7TXxwQ29KbHFAe0trU3dDYV1VfXNC"
|
|
22
|
-
// btoa(unescape(encodeURIComponent(poly)));
|
|
23
|
-
// "fWBqdUhucld6S2FPcE5ySGRJfFs/fmpAe0tydEB7TXxwQ29KbHFAe0trU3dDYV1VfXNC"
|
|
24
|
-
|
|
25
15
|
if (typeof pattern === 'string') return pattern;
|
|
26
16
|
return `${pattern[0] ? pattern[0] : ''}${value}${pattern[1] ? pattern[1] : ''}`;
|
|
27
17
|
};
|
|
@@ -52,6 +42,13 @@ export const buildQueryString = (search) => {
|
|
|
52
42
|
};
|
|
53
43
|
|
|
54
44
|
export default (search) => {
|
|
55
|
-
|
|
45
|
+
let searchToRun = search;
|
|
46
|
+
|
|
47
|
+
// if no search is passed, use current search from Redux store
|
|
48
|
+
if (!searchToRun) {
|
|
49
|
+
searchToRun = store.getState().search.currentSearch;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const query = buildQueryString(searchToRun);
|
|
56
53
|
window.location.assign(`/search?${query}`);
|
|
57
54
|
};
|
|
@@ -5,6 +5,7 @@ import Select from 'react-dropdown';
|
|
|
5
5
|
|
|
6
6
|
import 'react-dropdown/style.css';
|
|
7
7
|
|
|
8
|
+
import propertySearch from '../property-search/property-search';
|
|
8
9
|
import { setSearchField } from '../../actions/search.actions';
|
|
9
10
|
|
|
10
11
|
const defaultOptions = [
|
|
@@ -25,15 +26,30 @@ const ReactSelect = (props) => {
|
|
|
25
26
|
const {
|
|
26
27
|
type,
|
|
27
28
|
setSearchField,
|
|
29
|
+
searchOnSelection,
|
|
28
30
|
options = defaultOptions,
|
|
29
31
|
placeholder,
|
|
30
32
|
className,
|
|
31
33
|
styles,
|
|
32
34
|
value,
|
|
35
|
+
search,
|
|
33
36
|
} = props;
|
|
34
37
|
|
|
35
38
|
if (value) options.unshift({ value: '', label: 'Distance' });
|
|
36
39
|
|
|
40
|
+
const handleChange = ({ value }) => {
|
|
41
|
+
setSearchField({ within: value || null });
|
|
42
|
+
|
|
43
|
+
if (searchOnSelection) {
|
|
44
|
+
const newSearch = {
|
|
45
|
+
...search,
|
|
46
|
+
within: value,
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
propertySearch(newSearch);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
37
53
|
return (
|
|
38
54
|
<Select
|
|
39
55
|
classNamePrefix="react-select"
|
|
@@ -45,11 +61,7 @@ const ReactSelect = (props) => {
|
|
|
45
61
|
setValue={() => value}
|
|
46
62
|
isSearchable={false}
|
|
47
63
|
data-testid="select"
|
|
48
|
-
onChange={
|
|
49
|
-
setSearchField({
|
|
50
|
-
within: value || null,
|
|
51
|
-
});
|
|
52
|
-
}}
|
|
64
|
+
onChange={handleChange}
|
|
53
65
|
/>
|
|
54
66
|
);
|
|
55
67
|
};
|
|
@@ -57,23 +69,40 @@ const ReactSelect = (props) => {
|
|
|
57
69
|
const NormalSelect = ({
|
|
58
70
|
within,
|
|
59
71
|
setSearchField,
|
|
72
|
+
searchOnSelection,
|
|
60
73
|
options = defaultOptions,
|
|
61
74
|
placeholder,
|
|
75
|
+
search,
|
|
62
76
|
...otherProps
|
|
63
|
-
}) =>
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
+
}) => {
|
|
78
|
+
const handleChange = (e) => {
|
|
79
|
+
setSearchField({ within: e.target.value || null });
|
|
80
|
+
|
|
81
|
+
if (searchOnSelection) {
|
|
82
|
+
const newSearch = {
|
|
83
|
+
...search,
|
|
84
|
+
within: e.target.value,
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
propertySearch(newSearch);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
return (
|
|
92
|
+
<select
|
|
93
|
+
value={search.within}
|
|
94
|
+
name="within"
|
|
95
|
+
onChange={handleChange}
|
|
96
|
+
{...otherProps}
|
|
97
|
+
data-testid="select"
|
|
98
|
+
>
|
|
99
|
+
<option value="">{placeholder}</option>
|
|
100
|
+
{options.map((option) => (
|
|
101
|
+
<option value={option.value} key={option.value}>{option.label}</option>
|
|
102
|
+
))}
|
|
103
|
+
</select>
|
|
104
|
+
);
|
|
105
|
+
};
|
|
77
106
|
|
|
78
107
|
const RadiusSelect = (props) => {
|
|
79
108
|
const { reactSelect } = props;
|
|
@@ -86,17 +115,18 @@ const RadiusSelect = (props) => {
|
|
|
86
115
|
};
|
|
87
116
|
|
|
88
117
|
RadiusSelect.propTypes = {
|
|
89
|
-
within: PropTypes.string,
|
|
90
118
|
setSearchField: PropTypes.func.isRequired,
|
|
91
119
|
placeholder: PropTypes.string,
|
|
120
|
+
searchOnSelection: PropTypes.bool,
|
|
92
121
|
};
|
|
93
122
|
|
|
94
123
|
RadiusSelect.defaultProps = {
|
|
95
124
|
placeholder: 'Distance',
|
|
125
|
+
searchOnSelection: false,
|
|
96
126
|
};
|
|
97
127
|
|
|
98
128
|
const mapStateToProps = state => ({
|
|
99
|
-
|
|
129
|
+
search: state.search.currentSearch,
|
|
100
130
|
});
|
|
101
131
|
|
|
102
132
|
const mapDispatchToProps = {
|
|
@@ -2,7 +2,7 @@ import React, { Component } from 'react';
|
|
|
2
2
|
import { connect } from 'react-redux';
|
|
3
3
|
import PropTypes from 'prop-types';
|
|
4
4
|
|
|
5
|
-
import { setSearch, setSearchField, setPlace } from '../../actions/search.actions';
|
|
5
|
+
import { setSearch, setInitialSearch, setSearchField, setPlace } from '../../actions/search.actions';
|
|
6
6
|
import propertySearch from '../property-search/property-search';
|
|
7
7
|
import parseFragment from '../property-search/parse-fragment';
|
|
8
8
|
import { isEmpty } from '../../utils';
|
|
@@ -16,16 +16,24 @@ class SearchForm extends Component {
|
|
|
16
16
|
defaultChannel,
|
|
17
17
|
search,
|
|
18
18
|
setSearch,
|
|
19
|
+
setInitialSearch,
|
|
19
20
|
setSearchField,
|
|
20
21
|
setPlace,
|
|
21
22
|
} = this.props;
|
|
22
23
|
|
|
23
24
|
const searchFromFragment = parseFragment(window.location.pathname);
|
|
24
25
|
|
|
25
|
-
if (!isEmpty(searchFromFragment))
|
|
26
|
+
if (!isEmpty(searchFromFragment)) {
|
|
27
|
+
setInitialSearch(searchFromFragment);
|
|
28
|
+
setSearch(searchFromFragment);
|
|
29
|
+
}
|
|
26
30
|
|
|
27
|
-
|
|
28
|
-
|
|
31
|
+
const place = Homeflow.get('place');
|
|
32
|
+
if (place) {
|
|
33
|
+
setPlace(place);
|
|
34
|
+
setInitialSearch({
|
|
35
|
+
q: place.name + (place.county_name ? `, ${place.county_name}` : ''),
|
|
36
|
+
});
|
|
29
37
|
}
|
|
30
38
|
|
|
31
39
|
if (defaultSort && !search.order) setSearchField({ order: defaultSort });
|
|
@@ -55,6 +63,7 @@ class SearchForm extends Component {
|
|
|
55
63
|
setSearchField,
|
|
56
64
|
setPlace,
|
|
57
65
|
children,
|
|
66
|
+
setInitialSearch,
|
|
58
67
|
...otherProps
|
|
59
68
|
} = this.props;
|
|
60
69
|
|
|
@@ -88,6 +97,7 @@ const mapStateToProps = state => ({
|
|
|
88
97
|
const mapDispatchToProps = {
|
|
89
98
|
setSearch,
|
|
90
99
|
setSearchField,
|
|
100
|
+
setInitialSearch,
|
|
91
101
|
setPlace,
|
|
92
102
|
};
|
|
93
103
|
|