@blaze-cms/react-page-builder 0.113.1 → 0.114.0-alpha.3
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/CHANGELOG.md +68 -0
- package/README.md +5 -8
- package/lib/components/Card/CardRender.js +61 -17
- package/lib/components/Card/CardRender.js.map +1 -1
- package/lib/components/Card/helpers/filter-query-setup.js.map +1 -1
- package/lib/components/List/ListBuilder.js +11 -6
- package/lib/components/List/ListBuilder.js.map +1 -1
- package/lib/components/List/ListFactory.js +20 -7
- package/lib/components/List/ListFactory.js.map +1 -1
- package/lib/components/List/helpers/get-sort-props.js +46 -0
- package/lib/components/List/helpers/get-sort-props.js.map +1 -0
- package/lib/components/List/helpers/index.js +8 -0
- package/lib/components/List/helpers/index.js.map +1 -1
- package/lib/components/SearchFilter/SearchFilter/FiltersList.js +11 -5
- package/lib/components/SearchFilter/SearchFilter/FiltersList.js.map +1 -1
- package/lib/components/SearchFilter/SearchFilter/SearchFilter.js +60 -22
- package/lib/components/SearchFilter/SearchFilter/SearchFilter.js.map +1 -1
- package/lib/components/SearchFilter/SearchFilterContainer.js +8 -4
- package/lib/components/SearchFilter/SearchFilterContainer.js.map +1 -1
- package/lib/components/SearchFilter/components/Checkbox.js +5 -2
- package/lib/components/SearchFilter/components/Checkbox.js.map +1 -1
- package/lib/components/SearchFilter/components/Range.js +7 -3
- package/lib/components/SearchFilter/components/Range.js.map +1 -1
- package/lib/components/SearchFilter/components/Select.js +5 -2
- package/lib/components/SearchFilter/components/Select.js.map +1 -1
- package/lib/components/SearchFilter/constants.js +13 -1
- package/lib/components/SearchFilter/constants.js.map +1 -1
- package/lib/components/SearchFilter/helpers/build-query.js +6 -5
- package/lib/components/SearchFilter/helpers/build-query.js.map +1 -1
- package/lib/components/SearchFilter/helpers/get-range-value.js +6 -4
- package/lib/components/SearchFilter/helpers/get-range-value.js.map +1 -1
- package/lib/components/SearchFilter/helpers/get-responsive-filter-classnames.js +29 -0
- package/lib/components/SearchFilter/helpers/get-responsive-filter-classnames.js.map +1 -0
- package/lib/components/SearchFilter/helpers/index.js +8 -0
- package/lib/components/SearchFilter/helpers/index.js.map +1 -1
- package/lib/components/SearchFilter/helpers/is-device-desktop.js +1 -1
- package/lib/components/SearchFilter/helpers/is-device-desktop.js.map +1 -1
- package/lib/helpers/get-generic-render-variables.js +32 -22
- package/lib/helpers/get-generic-render-variables.js.map +1 -1
- package/lib-es/components/Card/CardRender.js +32 -5
- package/lib-es/components/Card/CardRender.js.map +1 -1
- package/lib-es/components/Card/helpers/filter-query-setup.js.map +1 -1
- package/lib-es/components/List/ListBuilder.js +11 -6
- package/lib-es/components/List/ListBuilder.js.map +1 -1
- package/lib-es/components/List/ListFactory.js +20 -8
- package/lib-es/components/List/ListFactory.js.map +1 -1
- package/lib-es/components/List/helpers/get-sort-props.js +26 -0
- package/lib-es/components/List/helpers/get-sort-props.js.map +1 -0
- package/lib-es/components/List/helpers/index.js +1 -0
- package/lib-es/components/List/helpers/index.js.map +1 -1
- package/lib-es/components/SearchFilter/SearchFilter/FiltersList.js +11 -5
- package/lib-es/components/SearchFilter/SearchFilter/FiltersList.js.map +1 -1
- package/lib-es/components/SearchFilter/SearchFilter/SearchFilter.js +54 -23
- package/lib-es/components/SearchFilter/SearchFilter/SearchFilter.js.map +1 -1
- package/lib-es/components/SearchFilter/SearchFilterContainer.js +8 -4
- package/lib-es/components/SearchFilter/SearchFilterContainer.js.map +1 -1
- package/lib-es/components/SearchFilter/components/Checkbox.js +5 -2
- package/lib-es/components/SearchFilter/components/Checkbox.js.map +1 -1
- package/lib-es/components/SearchFilter/components/Range.js +7 -3
- package/lib-es/components/SearchFilter/components/Range.js.map +1 -1
- package/lib-es/components/SearchFilter/components/Select.js +5 -2
- package/lib-es/components/SearchFilter/components/Select.js.map +1 -1
- package/lib-es/components/SearchFilter/constants.js +12 -1
- package/lib-es/components/SearchFilter/constants.js.map +1 -1
- package/lib-es/components/SearchFilter/helpers/build-query.js +5 -4
- package/lib-es/components/SearchFilter/helpers/build-query.js.map +1 -1
- package/lib-es/components/SearchFilter/helpers/get-range-value.js +1 -1
- package/lib-es/components/SearchFilter/helpers/get-range-value.js.map +1 -1
- package/lib-es/components/SearchFilter/helpers/get-responsive-filter-classnames.js +20 -0
- package/lib-es/components/SearchFilter/helpers/get-responsive-filter-classnames.js.map +1 -0
- package/lib-es/components/SearchFilter/helpers/index.js +2 -1
- package/lib-es/components/SearchFilter/helpers/index.js.map +1 -1
- package/lib-es/components/SearchFilter/helpers/is-device-desktop.js +1 -1
- package/lib-es/components/SearchFilter/helpers/is-device-desktop.js.map +1 -1
- package/lib-es/helpers/get-generic-render-variables.js +22 -15
- package/lib-es/helpers/get-generic-render-variables.js.map +1 -1
- package/package.json +2 -2
- package/src/components/Card/CardRender.js +24 -6
- package/src/components/Card/helpers/filter-query-setup.js +1 -0
- package/src/components/List/ListBuilder.js +11 -6
- package/src/components/List/ListFactory.js +18 -8
- package/src/components/List/helpers/get-sort-props.js +17 -0
- package/src/components/List/helpers/index.js +1 -0
- package/src/components/SearchFilter/SearchFilter/FiltersList.js +15 -2
- package/src/components/SearchFilter/SearchFilter/SearchFilter.js +78 -27
- package/src/components/SearchFilter/SearchFilterContainer.js +8 -4
- package/src/components/SearchFilter/components/Checkbox.js +4 -2
- package/src/components/SearchFilter/components/Range.js +7 -3
- package/src/components/SearchFilter/components/Select.js +4 -2
- package/src/components/SearchFilter/constants.js +14 -1
- package/src/components/SearchFilter/helpers/build-query.js +5 -4
- package/src/components/SearchFilter/helpers/get-range-value.js +3 -1
- package/src/components/SearchFilter/helpers/get-responsive-filter-classnames.js +22 -0
- package/src/components/SearchFilter/helpers/index.js +2 -0
- package/src/components/SearchFilter/helpers/is-device-desktop.js +2 -1
- package/src/helpers/get-generic-render-variables.js +22 -12
- package/tests/unit/src/components/List/helpers/get-sort-props.test.js +58 -0
- package/tests/unit/src/components/SearchFilter/SearchFilter/SearchFilter.test.js +29 -3
- package/tests/unit/src/components/SearchFilter/SearchFilter/__snapshots__/SearchFilter.test.js.snap +304 -6
- package/tests/unit/src/helpers/build-raw-query.test.js +2 -1
- package/tests/unit/src/helpers/get-generic-render-variables.test.js +5 -11
- package/lib/helpers/check-sort-by.js +0 -16
- package/lib/helpers/check-sort-by.js.map +0 -1
- package/lib-es/helpers/check-sort-by.js +0 -4
- package/lib-es/helpers/check-sort-by.js.map +0 -1
- package/src/helpers/check-sort-by.js +0 -4
|
@@ -9,26 +9,45 @@ import { useGetEntitySchemasAsObj, useGetImages } from '../../hooks';
|
|
|
9
9
|
import {
|
|
10
10
|
getUpdatedFilterBy,
|
|
11
11
|
getEntityData,
|
|
12
|
+
getRequiredSchemas,
|
|
12
13
|
sortResponseData,
|
|
13
14
|
getUnpublishedEntityName,
|
|
14
15
|
renderChildren,
|
|
15
16
|
splitChildren,
|
|
16
17
|
removeExtraItems,
|
|
17
|
-
getRequiredSchemas,
|
|
18
18
|
appendImages
|
|
19
19
|
} from '../../helpers';
|
|
20
20
|
import { filtersSetup, filterQuerySetup, shouldSkipSingleQuery, shouldReturn } from './helpers';
|
|
21
21
|
|
|
22
22
|
const CardContainer = dynamic(() => import('./CardContainer'));
|
|
23
23
|
|
|
24
|
-
const CardRender = ({ entity, entityFields, itemsToDisplay, children, ...
|
|
24
|
+
const CardRender = ({ entity, entityFields, itemsToDisplay, children, ...otherProps }) => {
|
|
25
25
|
const {
|
|
26
26
|
parent: { itemId, itemEntity },
|
|
27
27
|
filterBy = [],
|
|
28
28
|
filterByProperty = [],
|
|
29
|
-
sortby
|
|
29
|
+
sortby,
|
|
30
|
+
sort,
|
|
31
|
+
sortProperties = [],
|
|
30
32
|
operator: filterOperator = AND
|
|
31
|
-
} =
|
|
33
|
+
} = otherProps;
|
|
34
|
+
|
|
35
|
+
const updatedSortProperties = [...sortProperties];
|
|
36
|
+
if (!updatedSortProperties.length && sort) {
|
|
37
|
+
updatedSortProperties.unshift({ sort, propsToDisplay: sortby });
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const sortbyFilters = updatedSortProperties
|
|
41
|
+
.map(({ propsToDisplay }) => propsToDisplay)
|
|
42
|
+
.filter(Boolean)
|
|
43
|
+
.flat();
|
|
44
|
+
|
|
45
|
+
const variableProps = {
|
|
46
|
+
...otherProps,
|
|
47
|
+
sortProperties: updatedSortProperties,
|
|
48
|
+
sort: null,
|
|
49
|
+
sortby: null
|
|
50
|
+
};
|
|
32
51
|
|
|
33
52
|
const itemEntityUpdated = getUnpublishedEntityName(itemEntity);
|
|
34
53
|
const { data: mainSchemas = {}, loading: _loading, error: _error } = useGetEntitySchemasAsObj([
|
|
@@ -70,7 +89,7 @@ const CardRender = ({ entity, entityFields, itemsToDisplay, children, ...variabl
|
|
|
70
89
|
loading: schemaLoading,
|
|
71
90
|
error: schemaError
|
|
72
91
|
} = useGetEntitySchemasAsObj(
|
|
73
|
-
getRequiredSchemas([...filterByProperty, ...
|
|
92
|
+
getRequiredSchemas([...filterByProperty, ...sortbyFilters], filterEntitySchema),
|
|
74
93
|
_loading
|
|
75
94
|
);
|
|
76
95
|
|
|
@@ -94,7 +113,6 @@ const CardRender = ({ entity, entityFields, itemsToDisplay, children, ...variabl
|
|
|
94
113
|
itemsToDisplay,
|
|
95
114
|
entitySameAsCurrentItemEntity
|
|
96
115
|
});
|
|
97
|
-
|
|
98
116
|
const { data, error: cardsError, loading: cardsLoading } = useQuery(action, {
|
|
99
117
|
variables,
|
|
100
118
|
skip: shouldReturn(!updatedFilterBy, _loading, _load, schemaLoading, _error, _err, schemaError)
|
|
@@ -51,14 +51,15 @@ const ListBuilder = props => {
|
|
|
51
51
|
filterEntitySchema,
|
|
52
52
|
requiredSchema,
|
|
53
53
|
searchValues,
|
|
54
|
-
azFilter
|
|
54
|
+
azFilter,
|
|
55
|
+
sortProperties
|
|
55
56
|
} = props;
|
|
56
57
|
const isInfinite = paginationType === INFINITE;
|
|
57
58
|
const listComponent = getListComponent(isCard, paginationType);
|
|
58
59
|
const propsToDisplayValues = checkPropsToUse(propsToDisplay);
|
|
59
60
|
const entityFields = buildPropsQuery(entitySchema, propsToDisplayValues, props) || '';
|
|
60
61
|
const limitToUse = limit || itemsToDisplay.length;
|
|
61
|
-
const shouldApplyDefaultSort = !
|
|
62
|
+
const shouldApplyDefaultSort = !sortProperties || !sortProperties.length;
|
|
62
63
|
const itemsPerPageToUse = getItemsPerPageToUse(itemsPerPage, limitToUse);
|
|
63
64
|
const initialOffset = getCurrentOffset(offset, itemsPerPageToUse, paginationIndex, limitToUse);
|
|
64
65
|
const { entityType, docType } = getEntityData(entity);
|
|
@@ -105,7 +106,8 @@ const ListBuilder = props => {
|
|
|
105
106
|
limit: itemsPerPageToUse,
|
|
106
107
|
offset: initialOffset,
|
|
107
108
|
sort,
|
|
108
|
-
sortby
|
|
109
|
+
sortby,
|
|
110
|
+
sortProperties
|
|
109
111
|
},
|
|
110
112
|
stringProps,
|
|
111
113
|
JSON.stringify(azRawQuery),
|
|
@@ -147,7 +149,8 @@ const ListBuilder = props => {
|
|
|
147
149
|
limit: itemsPerPageToUse,
|
|
148
150
|
offset: initialOffset,
|
|
149
151
|
sort,
|
|
150
|
-
sortby
|
|
152
|
+
sortby,
|
|
153
|
+
sortProperties
|
|
151
154
|
},
|
|
152
155
|
stringProps,
|
|
153
156
|
JSON.stringify(rawQuery),
|
|
@@ -198,7 +201,8 @@ ListBuilder.propTypes = {
|
|
|
198
201
|
operator: PropTypes.string.isRequired,
|
|
199
202
|
filterOperator: PropTypes.string.isRequired,
|
|
200
203
|
paginationType: PropTypes.string,
|
|
201
|
-
azFilter: PropTypes.string
|
|
204
|
+
azFilter: PropTypes.string,
|
|
205
|
+
sortProperties: PropTypes.array
|
|
202
206
|
};
|
|
203
207
|
|
|
204
208
|
ListBuilder.defaultProps = {
|
|
@@ -209,7 +213,8 @@ ListBuilder.defaultProps = {
|
|
|
209
213
|
offset: 0,
|
|
210
214
|
paginationType: 'infinite',
|
|
211
215
|
inheritedFilters: [],
|
|
212
|
-
azFilter: ''
|
|
216
|
+
azFilter: '',
|
|
217
|
+
sortProperties: []
|
|
213
218
|
};
|
|
214
219
|
|
|
215
220
|
export default ListBuilder;
|
|
@@ -7,7 +7,7 @@ import { MainContext } from '@blaze-cms/nextjs-components';
|
|
|
7
7
|
import { getSingleEntitySchema, generateSingleItemQuery } from '../../application/query';
|
|
8
8
|
import ListBuilder from './ListBuilder';
|
|
9
9
|
import { AZ_LIST_TYPE } from './constants';
|
|
10
|
-
import { getAzQueryFilter } from './helpers';
|
|
10
|
+
import { getAzQueryFilter, getSortProps } from './helpers';
|
|
11
11
|
import {
|
|
12
12
|
getGenericProps,
|
|
13
13
|
getRequiredSchemas,
|
|
@@ -36,7 +36,8 @@ const ListFactory = props => {
|
|
|
36
36
|
sortby: defaultSortBy,
|
|
37
37
|
sort: defaultSort,
|
|
38
38
|
searchFilter,
|
|
39
|
-
operator: filterOperator
|
|
39
|
+
operator: filterOperator,
|
|
40
|
+
sortProperties
|
|
40
41
|
} = props;
|
|
41
42
|
|
|
42
43
|
const { isPreview } = useContext(MainContext);
|
|
@@ -46,8 +47,14 @@ const ListFactory = props => {
|
|
|
46
47
|
const { query, url, query: { sort: querySort, sortby: querySortBy } = {} } = parseUrl(
|
|
47
48
|
parsedQuery
|
|
48
49
|
);
|
|
49
|
-
const
|
|
50
|
-
|
|
50
|
+
const { sortbyFilters, updatedSortProperties } = getSortProps({
|
|
51
|
+
querySort,
|
|
52
|
+
sortProperties,
|
|
53
|
+
defaultSort,
|
|
54
|
+
querySortBy,
|
|
55
|
+
defaultSortBy
|
|
56
|
+
});
|
|
57
|
+
|
|
51
58
|
const { itemEntity, itemId } = parent;
|
|
52
59
|
const itemEntityUpdated = getUnpublishedEntityName(itemEntity);
|
|
53
60
|
const paginationIndex = getPaginationIndex(query, name);
|
|
@@ -75,7 +82,7 @@ const ListFactory = props => {
|
|
|
75
82
|
loading: requiredSchemaLoading,
|
|
76
83
|
error: requiredSchemaError
|
|
77
84
|
} = useGetEntitySchemasAsObj(
|
|
78
|
-
getRequiredSchemas([...filterByProperty, ...
|
|
85
|
+
getRequiredSchemas([...filterByProperty, ...sortbyFilters], filterEntitySchema),
|
|
79
86
|
schemasLoading
|
|
80
87
|
);
|
|
81
88
|
const inheritedFilters = getInheritedFilters(filterBy, filterByProperty);
|
|
@@ -126,8 +133,9 @@ const ListFactory = props => {
|
|
|
126
133
|
isAZ,
|
|
127
134
|
router,
|
|
128
135
|
entitySchema,
|
|
129
|
-
sort,
|
|
130
|
-
sortby,
|
|
136
|
+
sort: null,
|
|
137
|
+
sortby: null,
|
|
138
|
+
sortProperties: updatedSortProperties,
|
|
131
139
|
azFilter,
|
|
132
140
|
searchValues,
|
|
133
141
|
filterEntitySchema,
|
|
@@ -156,7 +164,8 @@ ListFactory.propTypes = {
|
|
|
156
164
|
name: PropTypes.string,
|
|
157
165
|
sortby: PropTypes.array,
|
|
158
166
|
sort: PropTypes.string,
|
|
159
|
-
searchFilter: PropTypes.object
|
|
167
|
+
searchFilter: PropTypes.object,
|
|
168
|
+
sortProperties: PropTypes.array
|
|
160
169
|
};
|
|
161
170
|
|
|
162
171
|
ListFactory.defaultProps = {
|
|
@@ -165,6 +174,7 @@ ListFactory.defaultProps = {
|
|
|
165
174
|
omitWrappers: false,
|
|
166
175
|
name: '',
|
|
167
176
|
sortby: [],
|
|
177
|
+
sortProperties: [],
|
|
168
178
|
sort: '',
|
|
169
179
|
operator: AND,
|
|
170
180
|
searchFilter: {}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const getSortProps = ({ querySort, sortProperties, defaultSort, querySortBy, defaultSortBy }) => {
|
|
2
|
+
const sort = querySort || (sortProperties.length ? null : defaultSort);
|
|
3
|
+
let sortby = null;
|
|
4
|
+
if (querySortBy) sortby = [querySortBy];
|
|
5
|
+
else if (!sortProperties.length) sortby = defaultSortBy;
|
|
6
|
+
|
|
7
|
+
const updatedSortProperties = [...sortProperties];
|
|
8
|
+
if (sort) updatedSortProperties.unshift({ sort, propsToDisplay: sortby });
|
|
9
|
+
|
|
10
|
+
const sortbyFilters = updatedSortProperties
|
|
11
|
+
.map(({ propsToDisplay: filterProps }) => filterProps)
|
|
12
|
+
.filter(Boolean)
|
|
13
|
+
.flat();
|
|
14
|
+
return { sortbyFilters, updatedSortProperties };
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export default getSortProps;
|
|
@@ -4,3 +4,4 @@ export { default as buildAzAggregations } from './build-az-aggregations';
|
|
|
4
4
|
export { default as buildAzUrl } from './build-az-url';
|
|
5
5
|
export { default as sortAggs } from './sort-aggs';
|
|
6
6
|
export { default as getItemsPerPageToUse } from './get-items-per-page-to-use';
|
|
7
|
+
export { default as getSortProps } from './get-sort-props';
|
|
@@ -4,7 +4,15 @@ import { MainContext } from '@blaze-cms/nextjs-components';
|
|
|
4
4
|
import { TextSearch, Checkbox, SelectFilter, Range } from '../components';
|
|
5
5
|
import { CHECKBOX, SELECT, TEXT_SEARCH, RANGE, SEARCH_TERM } from '../constants';
|
|
6
6
|
|
|
7
|
-
const FiltersList = ({
|
|
7
|
+
const FiltersList = ({
|
|
8
|
+
data,
|
|
9
|
+
filters,
|
|
10
|
+
hasUrl,
|
|
11
|
+
entity,
|
|
12
|
+
filterValues,
|
|
13
|
+
updateFilterValues,
|
|
14
|
+
shouldSearch
|
|
15
|
+
}) => {
|
|
8
16
|
const { itemId } = useContext(MainContext);
|
|
9
17
|
|
|
10
18
|
return filters.map(({ type, label, propsToDisplay, rangeInterval, elementTitle }, index) => {
|
|
@@ -46,6 +54,7 @@ const FiltersList = ({ data, filters, hasUrl, entity, filterValues, updateFilter
|
|
|
46
54
|
hasUrl={hasUrl}
|
|
47
55
|
filterValues={filterValues}
|
|
48
56
|
updateFilterValues={updateFilterValues}
|
|
57
|
+
shouldSearch={shouldSearch}
|
|
49
58
|
/>
|
|
50
59
|
</div>
|
|
51
60
|
)
|
|
@@ -64,6 +73,7 @@ const FiltersList = ({ data, filters, hasUrl, entity, filterValues, updateFilter
|
|
|
64
73
|
hasUrl={hasUrl}
|
|
65
74
|
filterValues={filterValues}
|
|
66
75
|
updateFilterValues={updateFilterValues}
|
|
76
|
+
shouldSearch={shouldSearch}
|
|
67
77
|
/>
|
|
68
78
|
</div>
|
|
69
79
|
)
|
|
@@ -81,6 +91,7 @@ const FiltersList = ({ data, filters, hasUrl, entity, filterValues, updateFilter
|
|
|
81
91
|
entity={entity}
|
|
82
92
|
filterValues={filterValues}
|
|
83
93
|
updateFilterValues={updateFilterValues}
|
|
94
|
+
shouldSearch={shouldSearch}
|
|
84
95
|
/>
|
|
85
96
|
</div>
|
|
86
97
|
)
|
|
@@ -97,10 +108,12 @@ FiltersList.propTypes = {
|
|
|
97
108
|
filterValues: PropTypes.object.isRequired,
|
|
98
109
|
updateFilterValues: PropTypes.func.isRequired,
|
|
99
110
|
data: PropTypes.object,
|
|
100
|
-
filters: PropTypes.array
|
|
111
|
+
filters: PropTypes.array,
|
|
112
|
+
shouldSearch: PropTypes.bool
|
|
101
113
|
};
|
|
102
114
|
|
|
103
115
|
FiltersList.defaultProps = {
|
|
116
|
+
shouldSearch: false,
|
|
104
117
|
data: {},
|
|
105
118
|
filters: []
|
|
106
119
|
};
|
|
@@ -3,11 +3,16 @@ import PropTypes from 'prop-types';
|
|
|
3
3
|
import classnames from 'classnames';
|
|
4
4
|
import debounce from 'lodash.debounce';
|
|
5
5
|
import FiltersList from './FiltersList';
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
isDeviceDesktop,
|
|
8
|
+
buildQuery,
|
|
9
|
+
getInitialFilterValues,
|
|
10
|
+
getResponsiveFilterClassnames
|
|
11
|
+
} from '../helpers';
|
|
7
12
|
import CloseMobileForm from './CloseMobileForm';
|
|
8
13
|
import ResetDesktopForm from './ResetDesktopForm';
|
|
9
14
|
import MobileFormToolbar from './MobileFormToolbar';
|
|
10
|
-
import { SEARCH, REFINE } from '../constants';
|
|
15
|
+
import { SEARCH, REFINE, MORE_FILTERS_CLASSES } from '../constants';
|
|
11
16
|
|
|
12
17
|
const reducer = (state, action) => {
|
|
13
18
|
const { newValues, type, shouldSearch = true } = action;
|
|
@@ -36,11 +41,13 @@ const SearchFilter = ({
|
|
|
36
41
|
displaySearchFilter,
|
|
37
42
|
setDisplaySearchFilter,
|
|
38
43
|
initialFilterValues,
|
|
39
|
-
|
|
44
|
+
groupAfterDesktop,
|
|
45
|
+
groupAfterMobile
|
|
40
46
|
}) => {
|
|
41
47
|
const [isDesktop, setIsDesktop] = useState(true);
|
|
42
48
|
const [pageWidth, setPageWidth] = useState(null);
|
|
43
|
-
const [
|
|
49
|
+
const [moreFiltersMobileCollapsed, setMoreFiltersMobileCollapsed] = useState(true);
|
|
50
|
+
const [moreFiltersDesktopCollapsed, setMoreFiltersDesktopCollapsed] = useState(true);
|
|
44
51
|
const [filterValues, dispatch] = useReducer(reducer, initialFilterValues);
|
|
45
52
|
|
|
46
53
|
const handleSubmit = debounce(newValues => {
|
|
@@ -91,13 +98,12 @@ const SearchFilter = ({
|
|
|
91
98
|
'filter__form filter__form--mobile': isMobileFormDisplayed
|
|
92
99
|
});
|
|
93
100
|
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
});
|
|
101
|
+
const {
|
|
102
|
+
moreFiltersMobileWrapperClass,
|
|
103
|
+
moreFiltersMobileTogglerClass,
|
|
104
|
+
moreFiltersDesktopWrapperClass,
|
|
105
|
+
moreFiltersDesktopTogglerClass
|
|
106
|
+
} = getResponsiveFilterClassnames(moreFiltersDesktopCollapsed, moreFiltersMobileCollapsed);
|
|
101
107
|
|
|
102
108
|
const formId = `filter-${name}-form`;
|
|
103
109
|
|
|
@@ -107,10 +113,13 @@ const SearchFilter = ({
|
|
|
107
113
|
dispatch({ newValues, type: 'reset' });
|
|
108
114
|
};
|
|
109
115
|
|
|
110
|
-
const updateFilterValues = (newValues,
|
|
111
|
-
dispatch({ newValues, shouldSearch, type: 'update' });
|
|
116
|
+
const updateFilterValues = (newValues, shouldSubmit) => {
|
|
117
|
+
dispatch({ newValues, shouldSearch: shouldSubmit, type: 'update' });
|
|
112
118
|
};
|
|
113
119
|
|
|
120
|
+
const shouldGroup = !!(groupAfterDesktop || groupAfterMobile);
|
|
121
|
+
const shouldSearch = !hasUrl;
|
|
122
|
+
|
|
114
123
|
return (
|
|
115
124
|
<>
|
|
116
125
|
{isDesktopFormDisplayed || isMobileFormDisplayed ? (
|
|
@@ -132,8 +141,9 @@ const SearchFilter = ({
|
|
|
132
141
|
{isDesktopFormDisplayed && <ResetDesktopForm handleReset={handleReset} />}
|
|
133
142
|
|
|
134
143
|
<div className="filter__wrapper filter__wrapper--search-refine">
|
|
135
|
-
{!
|
|
144
|
+
{!shouldGroup && (
|
|
136
145
|
<FiltersList
|
|
146
|
+
shouldSearch={shouldSearch}
|
|
137
147
|
data={data}
|
|
138
148
|
filters={filters}
|
|
139
149
|
hasUrl={hasUrl}
|
|
@@ -143,37 +153,77 @@ const SearchFilter = ({
|
|
|
143
153
|
/>
|
|
144
154
|
)}
|
|
145
155
|
|
|
146
|
-
{
|
|
156
|
+
{shouldGroup && (
|
|
147
157
|
<>
|
|
148
158
|
<FiltersList
|
|
159
|
+
shouldSearch={shouldSearch}
|
|
149
160
|
data={data}
|
|
150
|
-
filters={filters.slice(0,
|
|
161
|
+
filters={filters.slice(0, groupAfterMobile)}
|
|
151
162
|
hasUrl={hasUrl}
|
|
152
163
|
entity={entity}
|
|
153
164
|
filterValues={filterValues}
|
|
154
165
|
updateFilterValues={updateFilterValues}
|
|
155
166
|
/>
|
|
156
167
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
168
|
+
{!!groupAfterMobile && (
|
|
169
|
+
<button
|
|
170
|
+
className={moreFiltersMobileTogglerClass}
|
|
171
|
+
type="button"
|
|
172
|
+
onClick={() => setMoreFiltersMobileCollapsed(!moreFiltersMobileCollapsed)}>
|
|
173
|
+
Filters
|
|
174
|
+
</button>
|
|
175
|
+
)}
|
|
163
176
|
|
|
164
|
-
<div className={
|
|
165
|
-
<div className=
|
|
177
|
+
<div className={moreFiltersMobileWrapperClass}>
|
|
178
|
+
<div className={MORE_FILTERS_CLASSES.MOBILE_CONTENT}>
|
|
166
179
|
<FiltersList
|
|
180
|
+
shouldSearch={shouldSearch && isDeviceDesktop()}
|
|
167
181
|
data={data}
|
|
168
|
-
filters={filters.slice(
|
|
182
|
+
filters={filters.slice(
|
|
183
|
+
groupAfterMobile,
|
|
184
|
+
groupAfterDesktop ? groupAfterDesktop - 1 : 0
|
|
185
|
+
)}
|
|
169
186
|
hasUrl={hasUrl}
|
|
170
187
|
entity={entity}
|
|
171
188
|
filterValues={filterValues}
|
|
172
189
|
updateFilterValues={updateFilterValues}
|
|
173
190
|
/>
|
|
191
|
+
|
|
192
|
+
{!!groupAfterDesktop && (
|
|
193
|
+
<button
|
|
194
|
+
className={moreFiltersDesktopTogglerClass}
|
|
195
|
+
type="button"
|
|
196
|
+
onClick={() =>
|
|
197
|
+
setMoreFiltersDesktopCollapsed(!moreFiltersDesktopCollapsed)
|
|
198
|
+
}>
|
|
199
|
+
More filters
|
|
200
|
+
</button>
|
|
201
|
+
)}
|
|
202
|
+
|
|
203
|
+
<div className={moreFiltersDesktopWrapperClass}>
|
|
204
|
+
<div className={MORE_FILTERS_CLASSES.DESKTOP_CONTENT}>
|
|
205
|
+
<FiltersList
|
|
206
|
+
shouldSearch={false}
|
|
207
|
+
data={data}
|
|
208
|
+
filters={filters.slice(groupAfterDesktop)}
|
|
209
|
+
hasUrl={hasUrl}
|
|
210
|
+
entity={entity}
|
|
211
|
+
filterValues={filterValues}
|
|
212
|
+
updateFilterValues={updateFilterValues}
|
|
213
|
+
/>
|
|
214
|
+
</div>
|
|
215
|
+
|
|
216
|
+
<div className={MORE_FILTERS_CLASSES.DESKTOP_BUTTONS}>
|
|
217
|
+
<ResetDesktopForm handleReset={handleReset} />
|
|
218
|
+
|
|
219
|
+
<button className="button button--full-width" type="submit">
|
|
220
|
+
{SEARCH}
|
|
221
|
+
</button>
|
|
222
|
+
</div>
|
|
223
|
+
</div>
|
|
174
224
|
</div>
|
|
175
225
|
|
|
176
|
-
<div className=
|
|
226
|
+
<div className={MORE_FILTERS_CLASSES.MOBILE_BUTTONS}>
|
|
177
227
|
<ResetDesktopForm handleReset={handleReset} />
|
|
178
228
|
|
|
179
229
|
<button className="button button--full-width" type="submit">
|
|
@@ -224,7 +274,8 @@ SearchFilter.propTypes = {
|
|
|
224
274
|
displaySearchFilter: PropTypes.bool.isRequired,
|
|
225
275
|
setDisplaySearchFilter: PropTypes.func.isRequired,
|
|
226
276
|
isCollapsedOnResponsive: PropTypes.bool.isRequired,
|
|
227
|
-
|
|
277
|
+
groupAfterDesktop: PropTypes.number.isRequired,
|
|
278
|
+
groupAfterMobile: PropTypes.number.isRequired,
|
|
228
279
|
initialFilterValues: PropTypes.object.isRequired
|
|
229
280
|
};
|
|
230
281
|
|
|
@@ -23,7 +23,8 @@ const SearchFilterContainer = ({
|
|
|
23
23
|
filters,
|
|
24
24
|
name,
|
|
25
25
|
isCollapsedOnResponsive,
|
|
26
|
-
|
|
26
|
+
groupAfterMobile,
|
|
27
|
+
groupAfterDesktop
|
|
27
28
|
}) => {
|
|
28
29
|
const router = useRouter();
|
|
29
30
|
const searchFilterRef = useRef(null);
|
|
@@ -113,7 +114,8 @@ const SearchFilterContainer = ({
|
|
|
113
114
|
isCollapsedOnResponsive={isCollapsedOnResponsive}
|
|
114
115
|
displaySearchFilter={displaySearchFilter}
|
|
115
116
|
setDisplaySearchFilter={setDisplaySearchFilter}
|
|
116
|
-
|
|
117
|
+
groupAfterMobile={groupAfterMobile}
|
|
118
|
+
groupAfterDesktop={groupAfterDesktop}
|
|
117
119
|
/>
|
|
118
120
|
);
|
|
119
121
|
};
|
|
@@ -124,7 +126,8 @@ SearchFilterContainer.propTypes = {
|
|
|
124
126
|
filters: PropTypes.array,
|
|
125
127
|
name: PropTypes.string.isRequired,
|
|
126
128
|
isCollapsedOnResponsive: PropTypes.bool,
|
|
127
|
-
|
|
129
|
+
groupAfterMobile: PropTypes.number,
|
|
130
|
+
groupAfterDesktop: PropTypes.number
|
|
128
131
|
};
|
|
129
132
|
|
|
130
133
|
SearchFilterContainer.defaultProps = {
|
|
@@ -132,7 +135,8 @@ SearchFilterContainer.defaultProps = {
|
|
|
132
135
|
filters: [],
|
|
133
136
|
entity: '',
|
|
134
137
|
isCollapsedOnResponsive: true,
|
|
135
|
-
|
|
138
|
+
groupAfterMobile: 0,
|
|
139
|
+
groupAfterDesktop: 0
|
|
136
140
|
};
|
|
137
141
|
|
|
138
142
|
export default withTitle(SearchFilterContainer);
|
|
@@ -8,7 +8,7 @@ import { LIMIT_MIN, LIMIT_MAX, MORE, LESS, DOWN, UP } from '../constants';
|
|
|
8
8
|
|
|
9
9
|
const getButtonInfo = isMore => (isMore ? { icon: DOWN, text: MORE } : { icon: UP, text: LESS });
|
|
10
10
|
|
|
11
|
-
const Checkbox = ({ data, prop, updateFilterValues, filterValues, label }) => {
|
|
11
|
+
const Checkbox = ({ data, prop, updateFilterValues, filterValues, label, shouldSearch }) => {
|
|
12
12
|
const [checkboxLimit, setCheckboxLimit] = useState(null);
|
|
13
13
|
|
|
14
14
|
const handleCheckboxOptions = () => {
|
|
@@ -64,7 +64,7 @@ const Checkbox = ({ data, prop, updateFilterValues, filterValues, label }) => {
|
|
|
64
64
|
const newCheckboxValues = eData
|
|
65
65
|
.filter(({ checked }) => checked)
|
|
66
66
|
.map(({ value }) => value);
|
|
67
|
-
updateFilterValues({ [prop]: newCheckboxValues },
|
|
67
|
+
updateFilterValues({ [prop]: newCheckboxValues }, shouldSearch);
|
|
68
68
|
}}
|
|
69
69
|
/>
|
|
70
70
|
{data[prop].buckets.length > LIMIT_MIN && (
|
|
@@ -82,10 +82,12 @@ Checkbox.propTypes = {
|
|
|
82
82
|
prop: PropTypes.string.isRequired,
|
|
83
83
|
filterValues: PropTypes.object.isRequired,
|
|
84
84
|
updateFilterValues: PropTypes.func.isRequired,
|
|
85
|
+
shouldSearch: PropTypes.bool,
|
|
85
86
|
label: PropTypes.string
|
|
86
87
|
};
|
|
87
88
|
|
|
88
89
|
Checkbox.defaultProps = {
|
|
90
|
+
shouldSearch: false,
|
|
89
91
|
label: ''
|
|
90
92
|
};
|
|
91
93
|
|
|
@@ -16,9 +16,11 @@ const Range = ({
|
|
|
16
16
|
entity,
|
|
17
17
|
propsToDisplay,
|
|
18
18
|
updateFilterValues,
|
|
19
|
-
filterValues
|
|
19
|
+
filterValues,
|
|
20
|
+
shouldSearch
|
|
20
21
|
}) => {
|
|
21
22
|
const router = useRouter();
|
|
23
|
+
const debounceAmount = shouldSearch ? 1200 : 100;
|
|
22
24
|
const { query } = parseUrl(decodeValue(router.asPath));
|
|
23
25
|
const hasMultipleOptions = propsToDisplay.length > 1;
|
|
24
26
|
const initialRangeOption = getIntersectedProp(query, propsToDisplay) || propsToDisplay[0];
|
|
@@ -39,8 +41,8 @@ const Range = ({
|
|
|
39
41
|
const shouldShowRange = rangeOption && min !== max;
|
|
40
42
|
|
|
41
43
|
const handleChange = debounce((option, value) => {
|
|
42
|
-
updateFilterValues({ [option]: { ...value, selectedOption: rangeOption } },
|
|
43
|
-
},
|
|
44
|
+
updateFilterValues({ [option]: { ...value, selectedOption: rangeOption } }, shouldSearch);
|
|
45
|
+
}, debounceAmount);
|
|
44
46
|
|
|
45
47
|
return (
|
|
46
48
|
<>
|
|
@@ -86,11 +88,13 @@ Range.propTypes = {
|
|
|
86
88
|
entity: PropTypes.string.isRequired,
|
|
87
89
|
filterValues: PropTypes.object.isRequired,
|
|
88
90
|
updateFilterValues: PropTypes.func.isRequired,
|
|
91
|
+
shouldSearch: PropTypes.bool,
|
|
89
92
|
rangeInterval: PropTypes.number,
|
|
90
93
|
label: PropTypes.string
|
|
91
94
|
};
|
|
92
95
|
|
|
93
96
|
Range.defaultProps = {
|
|
97
|
+
shouldSearch: false,
|
|
94
98
|
rangeInterval: 1,
|
|
95
99
|
label: ''
|
|
96
100
|
};
|
|
@@ -4,7 +4,7 @@ import Select from '@blaze-react/select';
|
|
|
4
4
|
import { withTitle } from '../../../HOC';
|
|
5
5
|
import { DEFAULT_OPTION } from '../constants';
|
|
6
6
|
|
|
7
|
-
const SelectFilter = ({ data, label, prop, updateFilterValues, filterValues }) => {
|
|
7
|
+
const SelectFilter = ({ data, label, prop, updateFilterValues, filterValues, shouldSearch }) => {
|
|
8
8
|
const filterValue = filterValues[prop] || '';
|
|
9
9
|
|
|
10
10
|
const options = data[prop].buckets
|
|
@@ -21,7 +21,7 @@ const SelectFilter = ({ data, label, prop, updateFilterValues, filterValues }) =
|
|
|
21
21
|
id={prop}
|
|
22
22
|
options={optionsJoined}
|
|
23
23
|
onChange={({ value }) => {
|
|
24
|
-
updateFilterValues({ [prop]: value },
|
|
24
|
+
updateFilterValues({ [prop]: value }, shouldSearch);
|
|
25
25
|
}}
|
|
26
26
|
/>
|
|
27
27
|
);
|
|
@@ -32,10 +32,12 @@ SelectFilter.propTypes = {
|
|
|
32
32
|
prop: PropTypes.string.isRequired,
|
|
33
33
|
filterValues: PropTypes.object.isRequired,
|
|
34
34
|
updateFilterValues: PropTypes.func.isRequired,
|
|
35
|
+
shouldSearch: PropTypes.bool,
|
|
35
36
|
label: PropTypes.string
|
|
36
37
|
};
|
|
37
38
|
|
|
38
39
|
SelectFilter.defaultProps = {
|
|
40
|
+
shouldSearch: false,
|
|
39
41
|
label: ''
|
|
40
42
|
};
|
|
41
43
|
|
|
@@ -24,6 +24,18 @@ const SEARCH = 'Search';
|
|
|
24
24
|
const REFINE = `Refine Search`;
|
|
25
25
|
const MOBILE_REFINEMENT_TITLE = 'Search refinement';
|
|
26
26
|
|
|
27
|
+
const MORE_FILTERS_CLASSES_BASE = 'filter__more-filters';
|
|
28
|
+
const MORE_FILTERS_CLASSES = {
|
|
29
|
+
MOBILE_WRAPPER: `${MORE_FILTERS_CLASSES_BASE}-mobile-wrapper`,
|
|
30
|
+
MOBILE_CONTENT: `${MORE_FILTERS_CLASSES_BASE}-mobile-content`,
|
|
31
|
+
MOBILE_TOGGLER: `${MORE_FILTERS_CLASSES_BASE}-mobile-toggler`,
|
|
32
|
+
MOBILE_BUTTONS: `${MORE_FILTERS_CLASSES_BASE}-mobile-buttons`,
|
|
33
|
+
DESKTOP_WRAPPER: `${MORE_FILTERS_CLASSES_BASE}-desktop-wrapper`,
|
|
34
|
+
DESKTOP_CONTENT: `${MORE_FILTERS_CLASSES_BASE}-desktop-content`,
|
|
35
|
+
DESKTOP_TOGGLER: `${MORE_FILTERS_CLASSES_BASE}-desktop-toggler`,
|
|
36
|
+
DESKTOP_BUTTONS: `${MORE_FILTERS_CLASSES_BASE}-desktop-buttons`
|
|
37
|
+
};
|
|
38
|
+
|
|
27
39
|
export {
|
|
28
40
|
CHECKBOX,
|
|
29
41
|
SELECT,
|
|
@@ -49,5 +61,6 @@ export {
|
|
|
49
61
|
RESET,
|
|
50
62
|
SEARCH,
|
|
51
63
|
REFINE,
|
|
52
|
-
MOBILE_REFINEMENT_TITLE
|
|
64
|
+
MOBILE_REFINEMENT_TITLE,
|
|
65
|
+
MORE_FILTERS_CLASSES
|
|
53
66
|
};
|
|
@@ -8,12 +8,13 @@ const buildQuery = (filterValues, filters) => {
|
|
|
8
8
|
|
|
9
9
|
filters.forEach(({ propsToDisplay, type }) => {
|
|
10
10
|
if (type === TEXT_SEARCH) return;
|
|
11
|
-
|
|
11
|
+
|
|
12
|
+
propsToDisplay.forEach(prop => {
|
|
12
13
|
const value = filterValues[prop];
|
|
13
14
|
const parsedValue = parseFilterValue(prop, type, value);
|
|
14
|
-
if (!parsedValue)
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
if (parsedValue && !newQuery.includes(parsedValue)) {
|
|
16
|
+
newQuery.push(parsedValue);
|
|
17
|
+
}
|
|
17
18
|
});
|
|
18
19
|
});
|
|
19
20
|
|
|
@@ -4,7 +4,9 @@ const getRangeValue = (rawQueryProp, rangeInterval, _min, _max) => {
|
|
|
4
4
|
const { min, max } = calculateMinMax({ min: _min, max: _max }, rangeInterval);
|
|
5
5
|
|
|
6
6
|
if (rawQueryProp) {
|
|
7
|
-
const [queryParamMin, queryParamMax] =
|
|
7
|
+
const [queryParamMin, queryParamMax] = Array.isArray(rawQueryProp)
|
|
8
|
+
? rawQueryProp[0].split('-')
|
|
9
|
+
: rawQueryProp.split('-');
|
|
8
10
|
const updatedMinValue = Number(queryParamMin);
|
|
9
11
|
const updatedMaxValue = Number(queryParamMax);
|
|
10
12
|
|