@blaze-cms/react-page-builder 0.113.0-alpha.8 → 0.114.0-alpha.1
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 +41 -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/SearchFilter.js +53 -20
- package/lib/components/SearchFilter/SearchFilter/SearchFilter.js.map +1 -1
- package/lib/components/SearchFilter/SearchFilterContainer.js +19 -12
- package/lib/components/SearchFilter/SearchFilterContainer.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 +1 -5
- package/lib/components/SearchFilter/helpers/build-query.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/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/SearchFilter.js +47 -21
- package/lib-es/components/SearchFilter/SearchFilter/SearchFilter.js.map +1 -1
- package/lib-es/components/SearchFilter/SearchFilterContainer.js +12 -9
- package/lib-es/components/SearchFilter/SearchFilterContainer.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 +1 -3
- package/lib-es/components/SearchFilter/helpers/build-query.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/helpers/get-generic-render-variables.js +22 -15
- package/lib-es/helpers/get-generic-render-variables.js.map +1 -1
- package/package.json +4 -4
- 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/SearchFilter.js +71 -25
- package/src/components/SearchFilter/SearchFilterContainer.js +15 -8
- package/src/components/SearchFilter/constants.js +14 -1
- package/src/components/SearchFilter/helpers/build-query.js +2 -3
- package/src/components/SearchFilter/helpers/get-responsive-filter-classnames.js +22 -0
- package/src/components/SearchFilter/helpers/index.js +2 -0
- 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/components/SearchFilter/__snapshots__/SearchFilterContainer.test.js.snap +7 -1
- 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';
|
|
@@ -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
|
|
|
@@ -111,6 +117,8 @@ const SearchFilter = ({
|
|
|
111
117
|
dispatch({ newValues, shouldSearch, type: 'update' });
|
|
112
118
|
};
|
|
113
119
|
|
|
120
|
+
const shouldGroup = !!(groupAfterDesktop || groupAfterMobile);
|
|
121
|
+
|
|
114
122
|
return (
|
|
115
123
|
<>
|
|
116
124
|
{isDesktopFormDisplayed || isMobileFormDisplayed ? (
|
|
@@ -132,7 +140,7 @@ const SearchFilter = ({
|
|
|
132
140
|
{isDesktopFormDisplayed && <ResetDesktopForm handleReset={handleReset} />}
|
|
133
141
|
|
|
134
142
|
<div className="filter__wrapper filter__wrapper--search-refine">
|
|
135
|
-
{!
|
|
143
|
+
{!shouldGroup && (
|
|
136
144
|
<FiltersList
|
|
137
145
|
data={data}
|
|
138
146
|
filters={filters}
|
|
@@ -143,37 +151,74 @@ const SearchFilter = ({
|
|
|
143
151
|
/>
|
|
144
152
|
)}
|
|
145
153
|
|
|
146
|
-
{
|
|
154
|
+
{shouldGroup && (
|
|
147
155
|
<>
|
|
148
156
|
<FiltersList
|
|
149
157
|
data={data}
|
|
150
|
-
filters={filters.slice(0,
|
|
158
|
+
filters={filters.slice(0, groupAfterMobile)}
|
|
151
159
|
hasUrl={hasUrl}
|
|
152
160
|
entity={entity}
|
|
153
161
|
filterValues={filterValues}
|
|
154
162
|
updateFilterValues={updateFilterValues}
|
|
155
163
|
/>
|
|
156
164
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
165
|
+
{!!groupAfterMobile && (
|
|
166
|
+
<button
|
|
167
|
+
className={moreFiltersMobileTogglerClass}
|
|
168
|
+
type="button"
|
|
169
|
+
onClick={() => setMoreFiltersMobileCollapsed(!moreFiltersMobileCollapsed)}>
|
|
170
|
+
Filters
|
|
171
|
+
</button>
|
|
172
|
+
)}
|
|
163
173
|
|
|
164
|
-
<div className={
|
|
165
|
-
<div className=
|
|
174
|
+
<div className={moreFiltersMobileWrapperClass}>
|
|
175
|
+
<div className={MORE_FILTERS_CLASSES.MOBILE_CONTENT}>
|
|
166
176
|
<FiltersList
|
|
167
177
|
data={data}
|
|
168
|
-
filters={filters.slice(
|
|
178
|
+
filters={filters.slice(
|
|
179
|
+
groupAfterMobile,
|
|
180
|
+
groupAfterDesktop ? groupAfterDesktop - 1 : 0
|
|
181
|
+
)}
|
|
169
182
|
hasUrl={hasUrl}
|
|
170
183
|
entity={entity}
|
|
171
184
|
filterValues={filterValues}
|
|
172
185
|
updateFilterValues={updateFilterValues}
|
|
173
186
|
/>
|
|
187
|
+
|
|
188
|
+
{!!groupAfterDesktop && (
|
|
189
|
+
<button
|
|
190
|
+
className={moreFiltersDesktopTogglerClass}
|
|
191
|
+
type="button"
|
|
192
|
+
onClick={() =>
|
|
193
|
+
setMoreFiltersDesktopCollapsed(!moreFiltersDesktopCollapsed)
|
|
194
|
+
}>
|
|
195
|
+
More filters
|
|
196
|
+
</button>
|
|
197
|
+
)}
|
|
198
|
+
|
|
199
|
+
<div className={moreFiltersDesktopWrapperClass}>
|
|
200
|
+
<div className={MORE_FILTERS_CLASSES.DESKTOP_CONTENT}>
|
|
201
|
+
<FiltersList
|
|
202
|
+
data={data}
|
|
203
|
+
filters={filters.slice(groupAfterDesktop)}
|
|
204
|
+
hasUrl={hasUrl}
|
|
205
|
+
entity={entity}
|
|
206
|
+
filterValues={filterValues}
|
|
207
|
+
updateFilterValues={updateFilterValues}
|
|
208
|
+
/>
|
|
209
|
+
</div>
|
|
210
|
+
|
|
211
|
+
<div className={MORE_FILTERS_CLASSES.DESKTOP_BUTTONS}>
|
|
212
|
+
<ResetDesktopForm handleReset={handleReset} />
|
|
213
|
+
|
|
214
|
+
<button className="button button--full-width" type="submit">
|
|
215
|
+
{SEARCH}
|
|
216
|
+
</button>
|
|
217
|
+
</div>
|
|
218
|
+
</div>
|
|
174
219
|
</div>
|
|
175
220
|
|
|
176
|
-
<div className=
|
|
221
|
+
<div className={MORE_FILTERS_CLASSES.MOBILE_BUTTONS}>
|
|
177
222
|
<ResetDesktopForm handleReset={handleReset} />
|
|
178
223
|
|
|
179
224
|
<button className="button button--full-width" type="submit">
|
|
@@ -224,7 +269,8 @@ SearchFilter.propTypes = {
|
|
|
224
269
|
displaySearchFilter: PropTypes.bool.isRequired,
|
|
225
270
|
setDisplaySearchFilter: PropTypes.func.isRequired,
|
|
226
271
|
isCollapsedOnResponsive: PropTypes.bool.isRequired,
|
|
227
|
-
|
|
272
|
+
groupAfterDesktop: PropTypes.number.isRequired,
|
|
273
|
+
groupAfterMobile: PropTypes.number.isRequired,
|
|
228
274
|
initialFilterValues: PropTypes.object.isRequired
|
|
229
275
|
};
|
|
230
276
|
|
|
@@ -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);
|
|
@@ -61,11 +62,14 @@ const SearchFilterContainer = ({
|
|
|
61
62
|
variables: { rawQueryStringified, limit: 0 }, // we only want aggs so limit=0 for no search results
|
|
62
63
|
skip: !rawQueryStringified
|
|
63
64
|
});
|
|
64
|
-
|
|
65
|
+
|
|
66
|
+
if (loading) return null;
|
|
65
67
|
if (error) return error.message;
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
68
|
+
if (!filters.length) return null;
|
|
69
|
+
|
|
70
|
+
const { searchPublishedContent: { rawResults: { aggregations: filterData = {} } = {} } = {} } =
|
|
71
|
+
data || {};
|
|
72
|
+
|
|
69
73
|
const initialFilterValues = getInitialFilterValues(filterData, filters, query);
|
|
70
74
|
|
|
71
75
|
const handleSearch = newQuery => {
|
|
@@ -110,7 +114,8 @@ const SearchFilterContainer = ({
|
|
|
110
114
|
isCollapsedOnResponsive={isCollapsedOnResponsive}
|
|
111
115
|
displaySearchFilter={displaySearchFilter}
|
|
112
116
|
setDisplaySearchFilter={setDisplaySearchFilter}
|
|
113
|
-
|
|
117
|
+
groupAfterMobile={groupAfterMobile}
|
|
118
|
+
groupAfterDesktop={groupAfterDesktop}
|
|
114
119
|
/>
|
|
115
120
|
);
|
|
116
121
|
};
|
|
@@ -121,7 +126,8 @@ SearchFilterContainer.propTypes = {
|
|
|
121
126
|
filters: PropTypes.array,
|
|
122
127
|
name: PropTypes.string.isRequired,
|
|
123
128
|
isCollapsedOnResponsive: PropTypes.bool,
|
|
124
|
-
|
|
129
|
+
groupAfterMobile: PropTypes.number,
|
|
130
|
+
groupAfterDesktop: PropTypes.number
|
|
125
131
|
};
|
|
126
132
|
|
|
127
133
|
SearchFilterContainer.defaultProps = {
|
|
@@ -129,7 +135,8 @@ SearchFilterContainer.defaultProps = {
|
|
|
129
135
|
filters: [],
|
|
130
136
|
entity: '',
|
|
131
137
|
isCollapsedOnResponsive: true,
|
|
132
|
-
|
|
138
|
+
groupAfterMobile: 0,
|
|
139
|
+
groupAfterDesktop: 0
|
|
133
140
|
};
|
|
134
141
|
|
|
135
142
|
export default withTitle(SearchFilterContainer);
|
|
@@ -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,11 @@ 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) return null;
|
|
15
15
|
if (parsedValue) newQuery.push(parsedValue);
|
|
16
|
-
return parsedValue;
|
|
17
16
|
});
|
|
18
17
|
});
|
|
19
18
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import classnames from 'classnames';
|
|
2
|
+
import { MORE_FILTERS_CLASSES } from '../constants';
|
|
3
|
+
|
|
4
|
+
const getResponsiveFilterClassnames = (
|
|
5
|
+
moreFiltersDesktopCollapsed,
|
|
6
|
+
moreFiltersMobileCollapsed
|
|
7
|
+
) => ({
|
|
8
|
+
moreFiltersMobileWrapperClass: classnames(MORE_FILTERS_CLASSES.MOBILE_WRAPPER, {
|
|
9
|
+
[`${MORE_FILTERS_CLASSES.MOBILE_WRAPPER}--open`]: !moreFiltersMobileCollapsed
|
|
10
|
+
}),
|
|
11
|
+
moreFiltersMobileTogglerClass: classnames(MORE_FILTERS_CLASSES.MOBILE_TOGGLER, {
|
|
12
|
+
[`${MORE_FILTERS_CLASSES.MOBILE_TOGGLER}--open`]: !moreFiltersMobileCollapsed
|
|
13
|
+
}),
|
|
14
|
+
moreFiltersDesktopWrapperClass: classnames(MORE_FILTERS_CLASSES.DESKTOP_WRAPPER, {
|
|
15
|
+
[`${MORE_FILTERS_CLASSES.DESKTOP_WRAPPER}--open`]: !moreFiltersDesktopCollapsed
|
|
16
|
+
}),
|
|
17
|
+
moreFiltersDesktopTogglerClass: classnames(MORE_FILTERS_CLASSES.DESKTOP_TOGGLER, {
|
|
18
|
+
[`${MORE_FILTERS_CLASSES.DESKTOP_TOGGLER}--open`]: !moreFiltersDesktopCollapsed
|
|
19
|
+
})
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
export default getResponsiveFilterClassnames;
|
|
@@ -2,6 +2,7 @@ import buildNewQuery from './build-new-query';
|
|
|
2
2
|
import buildRawQueryStringified from './build-raw-query-stringified';
|
|
3
3
|
import { decodeValue, encodeValue } from './decode-encode';
|
|
4
4
|
import checkIfRangeUpdated from './check-if-range-updated';
|
|
5
|
+
import getResponsiveFilterClassnames from './get-responsive-filter-classnames';
|
|
5
6
|
import getDisplayValue from './get-display-value';
|
|
6
7
|
import calculateStep from './calculate-step';
|
|
7
8
|
import calculateMinMax from './calculate-min-max';
|
|
@@ -20,6 +21,7 @@ export {
|
|
|
20
21
|
decodeValue,
|
|
21
22
|
encodeValue,
|
|
22
23
|
checkIfRangeUpdated,
|
|
24
|
+
getResponsiveFilterClassnames,
|
|
23
25
|
getDisplayValue,
|
|
24
26
|
calculateStep,
|
|
25
27
|
calculateMinMax,
|
|
@@ -1,31 +1,41 @@
|
|
|
1
|
-
import checkSortby from './check-sort-by';
|
|
2
1
|
import getSortbyFieldName from './get-sort-by-field-name';
|
|
3
2
|
import { DEFAULT_LIMIT, DEFAULT_OFFSET } from '../constants';
|
|
4
3
|
|
|
4
|
+
const buildSortValues = (sortFilters, relations, stringProps) => {
|
|
5
|
+
if (!sortFilters || !sortFilters.length) return { sort: [] };
|
|
6
|
+
const sortValues = sortFilters
|
|
7
|
+
.map(
|
|
8
|
+
({ sort, propsToDisplay }) =>
|
|
9
|
+
!!sort &&
|
|
10
|
+
!!propsToDisplay[0] &&
|
|
11
|
+
`${getSortbyFieldName(relations, propsToDisplay[0], stringProps)}:${sort.toLowerCase()}`
|
|
12
|
+
)
|
|
13
|
+
.filter(Boolean)
|
|
14
|
+
.join(',');
|
|
15
|
+
|
|
16
|
+
return { sort: sortValues };
|
|
17
|
+
};
|
|
5
18
|
const getCorrectSort = (relations, filterProps, stringProps, isTextSearchApplied) => {
|
|
6
19
|
if (isTextSearchApplied) {
|
|
7
20
|
return {};
|
|
8
21
|
}
|
|
9
|
-
const { sort, sortby } = filterProps;
|
|
10
|
-
|
|
11
|
-
const isSortbyArray = Array.isArray(sortby);
|
|
12
|
-
|
|
13
|
-
const hasSortFields = sort && checkSortby(sortby, isSortbyArray);
|
|
14
|
-
|
|
15
|
-
const sortValue = hasSortFields
|
|
16
|
-
? `${getSortbyFieldName(relations, sortby, stringProps, isSortbyArray)}:${sort.toLowerCase()}`
|
|
17
|
-
: '';
|
|
22
|
+
const { sort, sortby, sortProperties = [] } = filterProps;
|
|
18
23
|
|
|
19
|
-
return
|
|
24
|
+
return buildSortValues(
|
|
25
|
+
[{ sort, propsToDisplay: [sortby] }, ...sortProperties],
|
|
26
|
+
relations,
|
|
27
|
+
stringProps
|
|
28
|
+
);
|
|
20
29
|
};
|
|
21
30
|
|
|
22
31
|
const getGenericRenderVariables = (
|
|
23
32
|
relations,
|
|
24
|
-
|
|
33
|
+
filterProps = {},
|
|
25
34
|
stringProps = [],
|
|
26
35
|
rawQueryStringified = '',
|
|
27
36
|
isTextSearchFilterApplied = false
|
|
28
37
|
) => {
|
|
38
|
+
const { limit = DEFAULT_LIMIT, offset } = filterProps;
|
|
29
39
|
const sort = getCorrectSort(relations, filterProps, stringProps, isTextSearchFilterApplied);
|
|
30
40
|
const raw = rawQueryStringified ? { rawQueryStringified } : {};
|
|
31
41
|
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import getSortProps from '../../../../../../src/components/List/helpers/get-sort-props';
|
|
2
|
+
|
|
3
|
+
const property = 'updated';
|
|
4
|
+
const defaultProperty = 'name';
|
|
5
|
+
const asc = 'asc';
|
|
6
|
+
const desc = 'desc';
|
|
7
|
+
const sortProperties = [
|
|
8
|
+
{
|
|
9
|
+
propsToDisplay: [property],
|
|
10
|
+
sort: asc
|
|
11
|
+
}
|
|
12
|
+
];
|
|
13
|
+
const querySortBy = 'date';
|
|
14
|
+
const props = {
|
|
15
|
+
querySort: '',
|
|
16
|
+
sortProperties,
|
|
17
|
+
defaultSort: desc,
|
|
18
|
+
querySortBy: '',
|
|
19
|
+
defaultSortBy: [defaultProperty]
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
describe('getSortProps helper function', () => {
|
|
23
|
+
it('should ignore old sortby/sort and use sortProperties', () => {
|
|
24
|
+
const { sortbyFilters, updatedSortProperties } = getSortProps(props);
|
|
25
|
+
expect(sortbyFilters).toEqual([property]);
|
|
26
|
+
expect(updatedSortProperties).toEqual(sortProperties);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('should add query sort', () => {
|
|
30
|
+
const { sortbyFilters, updatedSortProperties } = getSortProps({
|
|
31
|
+
...props,
|
|
32
|
+
querySortBy,
|
|
33
|
+
querySort: desc
|
|
34
|
+
});
|
|
35
|
+
expect(sortbyFilters).toEqual([querySortBy, property]);
|
|
36
|
+
expect(updatedSortProperties).toEqual([
|
|
37
|
+
{
|
|
38
|
+
propsToDisplay: [querySortBy],
|
|
39
|
+
sort: desc
|
|
40
|
+
},
|
|
41
|
+
...sortProperties
|
|
42
|
+
]);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should use old style sort', () => {
|
|
46
|
+
const { sortbyFilters, updatedSortProperties } = getSortProps({
|
|
47
|
+
...props,
|
|
48
|
+
sortProperties: []
|
|
49
|
+
});
|
|
50
|
+
expect(sortbyFilters).toEqual([defaultProperty]);
|
|
51
|
+
expect(updatedSortProperties).toEqual([
|
|
52
|
+
{
|
|
53
|
+
propsToDisplay: [defaultProperty],
|
|
54
|
+
sort: desc
|
|
55
|
+
}
|
|
56
|
+
]);
|
|
57
|
+
});
|
|
58
|
+
});
|