@shopgate/engage 7.32.0-beta.13 → 7.32.0-beta.15
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/admin-preview/constants/index.d.ts +9 -1
- package/admin-preview/constants/index.d.ts.map +1 -1
- package/admin-preview/constants/index.js +10 -2
- package/admin-preview/helpers/_internal/origins.d.ts +20 -0
- package/admin-preview/helpers/_internal/origins.d.ts.map +1 -0
- package/admin-preview/helpers/_internal/origins.js +72 -0
- package/admin-preview/helpers/index.d.ts +13 -0
- package/admin-preview/helpers/index.d.ts.map +1 -1
- package/admin-preview/helpers/index.js +17 -1
- package/admin-preview/hooks/index.d.ts +9 -7
- package/admin-preview/hooks/index.d.ts.map +1 -1
- package/admin-preview/hooks/index.js +21 -18
- package/admin-preview/initialization/awaitInitialFrontendSettings.d.ts +4 -3
- package/admin-preview/initialization/awaitInitialFrontendSettings.d.ts.map +1 -1
- package/admin-preview/initialization/awaitInitialFrontendSettings.js +13 -9
- package/filter/components/FilterItem/index.js +9 -2
- package/filter/components/FilterPageContent/components/ApplyButton/index.d.ts +21 -0
- package/filter/components/FilterPageContent/components/ApplyButton/index.d.ts.map +1 -0
- package/filter/components/FilterPageContent/components/ApplyButton/index.js +25 -52
- package/filter/components/FilterPageContent/components/FilterButtonBar/index.d.ts +8 -0
- package/filter/components/FilterPageContent/components/FilterButtonBar/index.d.ts.map +1 -0
- package/filter/components/FilterPageContent/components/FilterButtonBar/index.js +63 -0
- package/filter/components/FilterPageContent/components/ResetButton/index.d.ts +17 -0
- package/filter/components/FilterPageContent/components/ResetButton/index.d.ts.map +1 -0
- package/filter/components/FilterPageContent/components/ResetButton/index.js +24 -46
- package/filter/components/FilterPageContent/components/Selector/components/Selected/index.d.ts +19 -0
- package/filter/components/FilterPageContent/components/Selector/components/Selected/index.d.ts.map +1 -0
- package/filter/components/FilterPageContent/components/Selector/components/Selected/index.js +25 -46
- package/filter/components/FilterPageContent/components/Selector/components/Toggle/index.d.ts +14 -0
- package/filter/components/FilterPageContent/components/Selector/components/Toggle/index.d.ts.map +1 -0
- package/filter/components/FilterPageContent/components/Selector/components/Toggle/index.js +13 -46
- package/filter/components/FilterPageContent/components/Selector/components/ValueCheckbox/index.d.ts +25 -0
- package/filter/components/FilterPageContent/components/Selector/components/ValueCheckbox/index.d.ts.map +1 -0
- package/filter/components/FilterPageContent/components/Selector/components/ValueCheckbox/index.js +77 -0
- package/filter/components/FilterPageContent/components/Selector/index.d.ts +43 -0
- package/filter/components/FilterPageContent/components/Selector/index.d.ts.map +1 -0
- package/filter/components/FilterPageContent/components/Selector/index.js +52 -40
- package/filter/components/FilterPageContent/index.d.ts +16 -0
- package/filter/components/FilterPageContent/index.d.ts.map +1 -0
- package/filter/components/FilterPageContent/index.js +51 -57
- package/filter/components/PriceSlider/components/Label/index.js +69 -94
- package/filter/components/PriceSlider/index.js +43 -33
- package/filter/helpers/buildFilterParamsForFetchFiltersRequest.d.ts +8 -0
- package/filter/helpers/buildFilterParamsForFetchFiltersRequest.d.ts.map +1 -0
- package/filter/helpers/buildInitialFilters.d.ts +7 -0
- package/filter/helpers/buildInitialFilters.d.ts.map +1 -0
- package/filter/helpers/buildUpdatedFilters.d.ts +7 -0
- package/filter/helpers/buildUpdatedFilters.d.ts.map +1 -0
- package/filter/helpers/index.d.ts +5 -0
- package/filter/helpers/index.d.ts.map +1 -0
- package/filter/helpers/translateFilterLabel.d.ts +8 -0
- package/filter/helpers/translateFilterLabel.d.ts.map +1 -0
- package/filter/providers/FilterPageProvider.context.d.ts +157 -0
- package/filter/providers/FilterPageProvider.context.d.ts.map +1 -0
- package/filter/providers/FilterPageProvider.d.ts +24 -0
- package/filter/providers/FilterPageProvider.d.ts.map +1 -0
- package/filter/providers/FilterPageProvider.js +77 -132
- package/locations/components/GlobalLocationSwitcher/GlobalLocationSwitcherBar.js +4 -2
- package/package.json +7 -7
- package/page/components/Widgets/hooks.d.ts.map +1 -1
- package/page/components/Widgets/hooks.js +5 -1
- package/product/components/FilterBar/components/Content/components/FilterButton/index.js +38 -46
- package/product/components/FilterBar/components/Content/components/FilterChips/components/FilterChip/index.d.ts +38 -0
- package/product/components/FilterBar/components/Content/components/FilterChips/components/FilterChip/index.d.ts.map +1 -0
- package/product/components/FilterBar/components/Content/components/FilterChips/components/FilterChip/index.js +88 -0
- package/product/components/FilterBar/components/Content/components/FilterChips/index.js +54 -35
- package/product/components/FilterBar/components/Content/components/Sort/index.js +1 -1
- package/product/components/FilterBar/components/Content/index.js +7 -3
- package/product/components/FilterBar/index.js +11 -22
- package/product/components/ProductFilters/index.js +2 -6
- package/filter/components/FilterPageContent/components/Selector/components/ValueButton/index.js +0 -69
- package/product/components/FilterBar/components/Content/components/FilterChips/connector.js +0 -22
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
export default context;
|
|
2
|
+
export type APIFilterValue = {
|
|
3
|
+
/**
|
|
4
|
+
* Filter value id
|
|
5
|
+
*/
|
|
6
|
+
id: string;
|
|
7
|
+
/**
|
|
8
|
+
* Filter value label
|
|
9
|
+
*/
|
|
10
|
+
label: string;
|
|
11
|
+
/**
|
|
12
|
+
* Number of hits for the filter value
|
|
13
|
+
*/
|
|
14
|
+
hits: number;
|
|
15
|
+
};
|
|
16
|
+
export type APIFilter = {
|
|
17
|
+
/**
|
|
18
|
+
* Filter id
|
|
19
|
+
*/
|
|
20
|
+
id: string;
|
|
21
|
+
/**
|
|
22
|
+
* Filter label
|
|
23
|
+
*/
|
|
24
|
+
label: string;
|
|
25
|
+
/**
|
|
26
|
+
* Filter type
|
|
27
|
+
*/
|
|
28
|
+
type: "range" | "multiselect" | "single_select";
|
|
29
|
+
/**
|
|
30
|
+
* Filter source
|
|
31
|
+
*/
|
|
32
|
+
source?: string | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* Minimum value for a range filter
|
|
35
|
+
*/
|
|
36
|
+
minimum?: number | undefined;
|
|
37
|
+
/**
|
|
38
|
+
* Maximum value for a range filter
|
|
39
|
+
*/
|
|
40
|
+
maximum?: number | undefined;
|
|
41
|
+
values: APIFilterValue[];
|
|
42
|
+
};
|
|
43
|
+
export type RouteFilterValue = {
|
|
44
|
+
/**
|
|
45
|
+
* Filter value id
|
|
46
|
+
*/
|
|
47
|
+
id: string;
|
|
48
|
+
/**
|
|
49
|
+
* Filter value label
|
|
50
|
+
*/
|
|
51
|
+
label: string;
|
|
52
|
+
};
|
|
53
|
+
export type RouteFilter = {
|
|
54
|
+
/**
|
|
55
|
+
* Filter id
|
|
56
|
+
*/
|
|
57
|
+
id: string;
|
|
58
|
+
/**
|
|
59
|
+
* Filter label
|
|
60
|
+
*/
|
|
61
|
+
label: string;
|
|
62
|
+
/**
|
|
63
|
+
* Filter source
|
|
64
|
+
*/
|
|
65
|
+
source: string;
|
|
66
|
+
/**
|
|
67
|
+
* Filter type
|
|
68
|
+
*/
|
|
69
|
+
type: "range" | "multiselect" | "single_select";
|
|
70
|
+
/**
|
|
71
|
+
* Selected values for the filter
|
|
72
|
+
*/
|
|
73
|
+
values: RouteFilterValue[];
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Object with the active filters for a route with filtered product list
|
|
77
|
+
*/
|
|
78
|
+
export type RouteFilters = {
|
|
79
|
+
[x: string]: RouteFilter;
|
|
80
|
+
};
|
|
81
|
+
export type GetSelectedFilterValuesFn = (filterId: string) => any;
|
|
82
|
+
export type UpdateSelectedFilterValuesFn = (filterId: string, selectedValues: string[]) => void;
|
|
83
|
+
export type FilterPageContext = {
|
|
84
|
+
/**
|
|
85
|
+
* Whether the filter selection has changed since the filters page
|
|
86
|
+
* was opened
|
|
87
|
+
*/
|
|
88
|
+
hasChanged: boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Whether a reset of the active filters is possible
|
|
91
|
+
*/
|
|
92
|
+
resetPossible: boolean;
|
|
93
|
+
/**
|
|
94
|
+
* List of available filters from the API
|
|
95
|
+
*/
|
|
96
|
+
apiFilters: APIFilter[];
|
|
97
|
+
/**
|
|
98
|
+
* Object that represents the current state of all filters
|
|
99
|
+
*/
|
|
100
|
+
filters: RouteFilters;
|
|
101
|
+
/**
|
|
102
|
+
* Resets all filters which have been changed by the
|
|
103
|
+
* user
|
|
104
|
+
*/
|
|
105
|
+
resetAllFilters: () => void;
|
|
106
|
+
/**
|
|
107
|
+
* Resets all filters which have been changed by the
|
|
108
|
+
* user since the filters page was opened
|
|
109
|
+
*/
|
|
110
|
+
resetChangedFilters: () => void;
|
|
111
|
+
/**
|
|
112
|
+
* Applies the current filter selection to the parent route
|
|
113
|
+
* with a product list to be filtered
|
|
114
|
+
*/
|
|
115
|
+
applyFilters: () => void;
|
|
116
|
+
/**
|
|
117
|
+
* Retrieves a list of currently
|
|
118
|
+
* selected values for a filter
|
|
119
|
+
*/
|
|
120
|
+
getSelectedFilterValues: GetSelectedFilterValuesFn;
|
|
121
|
+
/**
|
|
122
|
+
* Updates the selection for a
|
|
123
|
+
* filter
|
|
124
|
+
*/
|
|
125
|
+
updateSelectedFilterValues: UpdateSelectedFilterValuesFn;
|
|
126
|
+
};
|
|
127
|
+
/**
|
|
128
|
+
* @callback GetSelectedFilterValuesFn
|
|
129
|
+
* @param {string} filterId The id of the filter
|
|
130
|
+
*/
|
|
131
|
+
/**
|
|
132
|
+
* @callback UpdateSelectedFilterValuesFn
|
|
133
|
+
* @param {string} filterId The id of the filter to be updated
|
|
134
|
+
* @param {string[]} selectedValues The updated selected values
|
|
135
|
+
* @returns {void}
|
|
136
|
+
*/
|
|
137
|
+
/**
|
|
138
|
+
* @typedef {Object} FilterPageContext
|
|
139
|
+
* @property {boolean} hasChanged Whether the filter selection has changed since the filters page
|
|
140
|
+
* was opened
|
|
141
|
+
* @property {boolean} resetPossible Whether a reset of the active filters is possible
|
|
142
|
+
* @property {APIFilter[]} apiFilters List of available filters from the API
|
|
143
|
+
* @property {RouteFilters} filters Object that represents the current state of all filters
|
|
144
|
+
* @property {function():void} resetAllFilters Resets all filters which have been changed by the
|
|
145
|
+
* user
|
|
146
|
+
* @property {function():void} resetChangedFilters Resets all filters which have been changed by the
|
|
147
|
+
* user since the filters page was opened
|
|
148
|
+
* @property {function():void} applyFilters Applies the current filter selection to the parent route
|
|
149
|
+
* with a product list to be filtered
|
|
150
|
+
* @property {GetSelectedFilterValuesFn} getSelectedFilterValues Retrieves a list of currently
|
|
151
|
+
* selected values for a filter
|
|
152
|
+
* @property {UpdateSelectedFilterValuesFn} updateSelectedFilterValues Updates the selection for a
|
|
153
|
+
* filter
|
|
154
|
+
*/
|
|
155
|
+
/** @type {import('react').Context<FilterPageContext>} */
|
|
156
|
+
declare const context: import("react").Context<FilterPageContext>;
|
|
157
|
+
//# sourceMappingURL=FilterPageProvider.context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FilterPageProvider.context.d.ts","sourceRoot":"","sources":["../../../filter/providers/FilterPageProvider.context.js"],"names":[],"mappings":";;;;;QAKc,MAAM;;;;WACN,MAAM;;;;UACN,MAAM;;;;;;QAMN,MAAM;;;;WACN,MAAM;;;;UACN,OAAO,GAAC,aAAa,GAAC,eAAe;;;;;;;;;;;;;YAIrC,cAAc,EAAE;;;;;;QAMhB,MAAM;;;;WACN,MAAM;;;;;;QAKN,MAAM;;;;WACN,MAAM;;;;YACN,MAAM;;;;UACN,OAAO,GAAC,aAAa,GAAC,eAAe;;;;YACrC,gBAAgB,EAAE;;;;;;;;mDAWrB,MAAM;sDAKN,MAAM,kBACN,MAAM,EAAE,KACN,IAAI;;;;;;gBAIH,OAAO;;;;mBAEP,OAAO;;;;gBACP,SAAS,EAAE;;;;aACX,YAAY;;;;;qBACZ,MAAW,IAAI;;;;;yBAEf,MAAW,IAAI;;;;;kBAEf,MAAW,IAAI;;;;;6BAEf,yBAAyB;;;;;gCAEzB,4BAA4B;;AA1B1C;;;GAGG;AAEH;;;;;GAKG;AACH;;;;;;;;;;;;;;;;;GAiBG;AAEH,yDAAyD;AACzD,uBADW,OAAO,OAAO,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAWlD"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { APIFilter, RouteFilters } from './FilterPageProvider.context';
|
|
3
|
+
interface FilterPageProviderProps {
|
|
4
|
+
/** Array of available filters, injected from Redux. */
|
|
5
|
+
filters?: APIFilter[] | null;
|
|
6
|
+
/** Object with the active filters for a filtered product list. */
|
|
7
|
+
activeFilters?: RouteFilters | null;
|
|
8
|
+
/** Id of the route with the product list that's supposed to be filtered. */
|
|
9
|
+
parentRouteId?: string | null;
|
|
10
|
+
/** Callback invoked when users pressed the apply button. */
|
|
11
|
+
onApply?: (filters: RouteFilters | null) => void;
|
|
12
|
+
/** Provider children. */
|
|
13
|
+
children?: ReactNode;
|
|
14
|
+
}
|
|
15
|
+
declare const _default: import("react-redux").ConnectedComponent<({ filters: filtersProp, activeFilters: activeFiltersProp, parentRouteId, onApply, children, }: FilterPageProviderProps) => import("react").JSX.Element, {
|
|
16
|
+
children?: ReactNode;
|
|
17
|
+
activeFilters?: (RouteFilters | null) | undefined;
|
|
18
|
+
parentRouteId?: string | null | undefined;
|
|
19
|
+
onApply?: ((filters: RouteFilters | null) => void) | undefined;
|
|
20
|
+
context?: import("react-redux/es/components/Context").ReactReduxContextInstance | undefined;
|
|
21
|
+
store?: import("redux").Store | undefined;
|
|
22
|
+
}>;
|
|
23
|
+
export default _default;
|
|
24
|
+
//# sourceMappingURL=FilterPageProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FilterPageProvider.d.ts","sourceRoot":"","sources":["../../../filter/providers/FilterPageProvider.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAkB,SAAS,EAAE,MAAM,OAAO,CAAC;AASvD,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAyC5E,UAAU,uBAAuB;IAC/B,uDAAuD;IACvD,OAAO,CAAC,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;IAC7B,kEAAkE;IAClE,aAAa,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IACpC,4EAA4E;IAC5E,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,4DAA4D;IAC5D,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,KAAK,IAAI,CAAC;IACjD,yBAAyB;IACzB,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;iKAoCE,uBAAuB;;qBA3CR,YAAY,GAAG,IAAI;oBAEnB,MAAM,GAAG,IAAI;eAEnB,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,KAAK,IAAI;;;;AAiQlD,wBAKsB"}
|
|
@@ -1,28 +1,40 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import "core-js/modules/es.array.includes.js";
|
|
2
|
+
import "core-js/modules/es.string.replace.js";
|
|
3
|
+
import { useMemo, useState, useEffect, useCallback } from 'react';
|
|
3
4
|
import { connect } from 'react-redux';
|
|
4
5
|
import debounce from 'lodash/debounce';
|
|
5
6
|
import isEqual from 'lodash/isEqual';
|
|
6
7
|
import { router } from '@shopgate/engage/core';
|
|
8
|
+
import { useRoute } from '@shopgate/engage/core/hooks';
|
|
9
|
+
import { parseObjectToQueryString } from '@shopgate/engage/core/helpers';
|
|
7
10
|
import { getFiltersByHash } from '@shopgate/engage/filter';
|
|
8
|
-
|
|
9
|
-
import Context, { APIFilter, RouteFilters } from "./FilterPageProvider.context";
|
|
11
|
+
import Context from "./FilterPageProvider.context";
|
|
10
12
|
import { buildInitialFilters, buildUpdatedFilters } from "../helpers";
|
|
13
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
14
|
+
const FILTER_PATH_SUFFIX = '/filter';
|
|
11
15
|
|
|
12
16
|
/**
|
|
13
|
-
*
|
|
14
|
-
|
|
15
|
-
|
|
17
|
+
* A single stored filter value carrying id and label.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* A filter as kept in the provider's internal state. `value` holds either the selected values of a
|
|
22
|
+
* list filter or the `[min, max]` tuple of a range filter.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
const buildInitialFiltersTyped = buildInitialFilters;
|
|
26
|
+
const buildUpdatedFiltersTyped = buildUpdatedFilters;
|
|
27
|
+
/**
|
|
28
|
+
* Maps the available filters from the application state onto the provider props.
|
|
29
|
+
* @returns The mapped state props.
|
|
16
30
|
*/
|
|
17
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
18
31
|
const mapStateToProps = (state, props) => ({
|
|
19
32
|
filters: getFiltersByHash(state, props)
|
|
20
33
|
});
|
|
21
34
|
|
|
22
35
|
/**
|
|
23
|
-
*
|
|
24
|
-
* @
|
|
25
|
-
* @returns {boolean}
|
|
36
|
+
* Compares the mapped state props to decide whether the connected component needs to re-render.
|
|
37
|
+
* @returns Whether the state props are considered equal.
|
|
26
38
|
*/
|
|
27
39
|
const areStatePropsEqual = (next, prev) => {
|
|
28
40
|
if (!prev.filters && next.filters || !isEqual(prev.filters, next.filters)) {
|
|
@@ -34,25 +46,19 @@ const areStatePropsEqual = (next, prev) => {
|
|
|
34
46
|
/**
|
|
35
47
|
* The FilterPageProvider component provides all relevant data and callbacks to represent and modify
|
|
36
48
|
* the current state of the "filter" page.
|
|
37
|
-
* @
|
|
38
|
-
* @param {APIFilter[]} props.filters Array of available filters
|
|
39
|
-
* @param {RouteFilters} props.activeFilters Object with the active filters for a filtered product
|
|
40
|
-
* list
|
|
41
|
-
* @param {string} props.parentRouteId Id of the route with the product list that's supposed to be
|
|
42
|
-
* filtered
|
|
43
|
-
* @param {Function} [props.onApply] Callback invoked when users pressed the apply button
|
|
44
|
-
* @param {string} [props.categoryId] A category to be used for filter selection from Redux
|
|
45
|
-
* @param {string} [props.searchPhrase] A search phrase to be used for filter selection from Redux
|
|
46
|
-
* @param {NodeList} children Provider children
|
|
47
|
-
* @returns {JSX.Element}
|
|
49
|
+
* @returns The rendered component.
|
|
48
50
|
*/
|
|
49
51
|
const FilterPageProvider = ({
|
|
50
|
-
filters: filtersProp,
|
|
51
|
-
activeFilters: activeFiltersProp,
|
|
52
|
-
parentRouteId,
|
|
53
|
-
onApply,
|
|
54
|
-
children
|
|
52
|
+
filters: filtersProp = null,
|
|
53
|
+
activeFilters: activeFiltersProp = null,
|
|
54
|
+
parentRouteId = null,
|
|
55
|
+
onApply = () => setTimeout(router.pop, 250),
|
|
56
|
+
children = null
|
|
55
57
|
}) => {
|
|
58
|
+
const {
|
|
59
|
+
pathname,
|
|
60
|
+
query
|
|
61
|
+
} = useRoute();
|
|
56
62
|
const [currentFilters, setCurrentFilters] = useState(activeFiltersProp || {});
|
|
57
63
|
|
|
58
64
|
/**
|
|
@@ -60,7 +66,7 @@ const FilterPageProvider = ({
|
|
|
60
66
|
* It's created from the "filters" array that contains all available filters, and the
|
|
61
67
|
* "activeFilters" object that represents filters with an active value selection.
|
|
62
68
|
*/
|
|
63
|
-
const [initialFilters, setInitialFilters] = useState(
|
|
69
|
+
const [initialFilters, setInitialFilters] = useState(buildInitialFiltersTyped(filtersProp, activeFiltersProp));
|
|
64
70
|
|
|
65
71
|
/**
|
|
66
72
|
* Storage that hosts an object that represents the a partial state of the filters page with
|
|
@@ -82,7 +88,7 @@ const FilterPageProvider = ({
|
|
|
82
88
|
if (Object.keys(currentState).length > 0) {
|
|
83
89
|
return currentState;
|
|
84
90
|
}
|
|
85
|
-
return
|
|
91
|
+
return buildInitialFiltersTyped(filtersProp, activeFiltersProp);
|
|
86
92
|
});
|
|
87
93
|
}, [activeFiltersProp, filtersProp]);
|
|
88
94
|
|
|
@@ -91,37 +97,23 @@ const FilterPageProvider = ({
|
|
|
91
97
|
*
|
|
92
98
|
* Reset is possible whenever filters where selected by the user before, or when filters where
|
|
93
99
|
* modified since the filters page was opened.
|
|
94
|
-
* @type {boolean}
|
|
95
100
|
*/
|
|
96
101
|
const resetPossible = useMemo(() => !!(Object.keys(currentFilters).length || Object.keys(changedFilters).length), [changedFilters, currentFilters]);
|
|
97
102
|
|
|
98
103
|
/**
|
|
99
104
|
* Whether the filter selection has changed since the filters page was opened
|
|
100
|
-
* @type {boolean}
|
|
101
105
|
*/
|
|
102
106
|
const hasChanged = useMemo(() => Object.keys(changedFilters).length > 0 || !!(Object.keys(currentFilters).length === 0 && activeFiltersProp), [activeFiltersProp, changedFilters, currentFilters]);
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Retrieves a list of currently selected values for a filter
|
|
106
|
-
* @callback getSelectedFilterValues
|
|
107
|
-
* @param {string} filterId The id of the filter
|
|
108
|
-
* @returns {string[]}
|
|
109
|
-
*/
|
|
110
|
-
const getSelectedFilterValues = useCallback(
|
|
111
|
-
/**
|
|
112
|
-
* @param {string} filterId The id of the filter
|
|
113
|
-
* @returns {string[]}
|
|
114
|
-
*/
|
|
115
|
-
filterId => {
|
|
107
|
+
const getSelectedFilterValues = useCallback(filterId => {
|
|
116
108
|
const value = changedFilters[filterId] ? changedFilters[filterId].value : initialFilters[filterId]?.value || [];
|
|
117
|
-
return value.map(entry => entry.id
|
|
109
|
+
return value.map(entry => typeof entry === 'object' ? entry.id : entry);
|
|
118
110
|
}, [changedFilters, initialFilters]);
|
|
119
111
|
|
|
120
112
|
/**
|
|
121
113
|
* Resets all filters which have been changed by the user
|
|
122
114
|
*/
|
|
123
115
|
const resetAllFilters = useCallback(() => {
|
|
124
|
-
setInitialFilters(
|
|
116
|
+
setInitialFilters(buildInitialFiltersTyped(filtersProp, {}));
|
|
125
117
|
setCurrentFilters({});
|
|
126
118
|
setChangedFilters({});
|
|
127
119
|
}, [filtersProp]);
|
|
@@ -132,77 +124,33 @@ const FilterPageProvider = ({
|
|
|
132
124
|
const resetChangedFilters = useCallback(() => {
|
|
133
125
|
setChangedFilters({});
|
|
134
126
|
}, []);
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Adds or updates the selection for a changed filter
|
|
138
|
-
* @callback updateChangedFilterInternal
|
|
139
|
-
* @param {string} filterId The id of the filter to be updated
|
|
140
|
-
* @param {string[]} selectedValues The updated selected values
|
|
141
|
-
*/
|
|
142
|
-
const updateChangedFilterInternal = useCallback(
|
|
143
|
-
/**
|
|
144
|
-
* @param {string} filterId The id of the filter to be updated
|
|
145
|
-
* @param {string[]} selectedValues The updated selected values
|
|
146
|
-
*/
|
|
147
|
-
(filterId, selectedValues) => {
|
|
127
|
+
const updateChangedFilterInternal = useCallback((filterId, selectedValues) => {
|
|
148
128
|
setChangedFilters(currentState => ({
|
|
149
129
|
...currentState,
|
|
150
130
|
[filterId]: selectedValues
|
|
151
131
|
}));
|
|
152
132
|
}, []);
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Removes a changed filter
|
|
156
|
-
* @callback removeChangedFilterInternal
|
|
157
|
-
* @param {string} filterId The id of the filter to be updated
|
|
158
|
-
* @param {string[]} selectedValues The updated selected values
|
|
159
|
-
*/
|
|
160
|
-
const removeChangedFilterInternal = useCallback(
|
|
161
|
-
/**
|
|
162
|
-
* @param {string} filterId The id of the filter to be removed
|
|
163
|
-
*/
|
|
164
|
-
filterId => {
|
|
133
|
+
const removeChangedFilterInternal = useCallback(filterId => {
|
|
165
134
|
setChangedFilters(currentState => {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
} = currentState;
|
|
135
|
+
const remainingFilters = {
|
|
136
|
+
...currentState
|
|
137
|
+
};
|
|
138
|
+
delete remainingFilters[filterId];
|
|
171
139
|
return remainingFilters;
|
|
172
140
|
});
|
|
173
141
|
}, []);
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
* @param {string[]} selectedValues The updated selected values
|
|
180
|
-
*/
|
|
181
|
-
const updateSelectedFilterValues = useCallback(debounce(
|
|
182
|
-
/**
|
|
183
|
-
* @param {string} filterId The id of the filter to be updated
|
|
184
|
-
* @param {string[]} selectedValues The updated selected values
|
|
185
|
-
*/
|
|
186
|
-
(filterId, selectedValues) => {
|
|
187
|
-
// Retrieve data of filter to be updated from the filters array.
|
|
188
|
-
const filter = filtersProp.find(entry => entry.id === filterId);
|
|
189
|
-
|
|
190
|
-
// Retrieve the values for the updated filter that where set when the filter page was opened
|
|
142
|
+
const updateSelectedFilterValues = useCallback(debounce((filterId, selectedValues) => {
|
|
143
|
+
const filter = (filtersProp || []).find(entry => entry.id === filterId);
|
|
144
|
+
if (!filter) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
191
147
|
const {
|
|
192
148
|
value: initialValues
|
|
193
149
|
} = initialFilters[filterId];
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* No initial values where set for this filter, and the update contains no values. So we
|
|
200
|
-
* can remove the filter from the changedFilters storage.
|
|
201
|
-
*/
|
|
202
|
-
if (initialValues.length === 0 && selectedValues.length === 0) {
|
|
203
|
-
removeChangedFilterInternal(filterId);
|
|
204
|
-
return;
|
|
205
|
-
}
|
|
150
|
+
const hasValueList = Array.isArray(filter.values);
|
|
151
|
+
const orderByFilter = ids => hasValueList ? filter.values.filter(entry => ids.includes(entry.id)).map(entry => entry.id) : ids;
|
|
152
|
+
const selectedValueIds = orderByFilter(selectedValues);
|
|
153
|
+
const initialValueIds = orderByFilter(initialValues.map(entry => typeof entry === 'object' ? entry.id : entry));
|
|
206
154
|
|
|
207
155
|
/**
|
|
208
156
|
* When the filter update would recreate the state that the filter initially had, we
|
|
@@ -210,25 +158,21 @@ const FilterPageProvider = ({
|
|
|
210
158
|
*
|
|
211
159
|
* That enables proper behavior for the "reset" and "update" button states.
|
|
212
160
|
*/
|
|
213
|
-
if (
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
161
|
+
if (initialValueIds.length === selectedValueIds.length && initialValueIds.every((initial, i) => initial === selectedValueIds[i])) {
|
|
162
|
+
removeChangedFilterInternal(filterId);
|
|
163
|
+
return;
|
|
218
164
|
}
|
|
219
|
-
|
|
165
|
+
let stateValue = [].concat(selectedValueIds);
|
|
166
|
+
if (hasValueList) {
|
|
220
167
|
/**
|
|
221
168
|
* The selectedValues array only contains a list of ids.
|
|
222
169
|
* For the getProducts request that's dispatched after the current filter selection was
|
|
223
170
|
* applied, id and label is required at the filter values level.
|
|
224
171
|
*/
|
|
225
|
-
stateValue =
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
label: match.label
|
|
230
|
-
};
|
|
231
|
-
});
|
|
172
|
+
stateValue = selectedValueIds.map(valueId => filter.values.find(entry => entry.id === valueId)).filter(match => Boolean(match)).map(match => ({
|
|
173
|
+
id: match.id,
|
|
174
|
+
label: match.label
|
|
175
|
+
}));
|
|
232
176
|
}
|
|
233
177
|
updateChangedFilterInternal(filterId, {
|
|
234
178
|
id: filterId,
|
|
@@ -242,15 +186,27 @@ const FilterPageProvider = ({
|
|
|
242
186
|
}, 50), [filtersProp, initialFilters, removeChangedFilterInternal, updateChangedFilterInternal]);
|
|
243
187
|
|
|
244
188
|
/**
|
|
245
|
-
* Applies the current filter selection to the parent route with a product list to be filtered
|
|
189
|
+
* Applies the current filter selection to the parent route with a product list to be filtered.
|
|
190
|
+
* When the filter page was entered directly, no parent route exists in the history stack. In
|
|
191
|
+
* that case the product list route is derived from the current pathname and replaces the
|
|
192
|
+
* filter page.
|
|
246
193
|
*/
|
|
247
194
|
const applyFilters = useCallback(() => {
|
|
248
|
-
const filters =
|
|
195
|
+
const filters = buildUpdatedFiltersTyped(currentFilters, changedFilters);
|
|
196
|
+
if (!parentRouteId) {
|
|
197
|
+
router.replace({
|
|
198
|
+
pathname: `${pathname.slice(0, -FILTER_PATH_SUFFIX.length)}${parseObjectToQueryString(query)}`,
|
|
199
|
+
state: {
|
|
200
|
+
filters
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
249
205
|
router.update(parentRouteId, {
|
|
250
206
|
filters
|
|
251
207
|
});
|
|
252
208
|
onApply(filters);
|
|
253
|
-
}, [changedFilters, currentFilters, onApply, parentRouteId]);
|
|
209
|
+
}, [changedFilters, currentFilters, onApply, parentRouteId, pathname, query]);
|
|
254
210
|
const value = useMemo(() => ({
|
|
255
211
|
resetPossible,
|
|
256
212
|
hasChanged,
|
|
@@ -267,17 +223,6 @@ const FilterPageProvider = ({
|
|
|
267
223
|
children: children
|
|
268
224
|
});
|
|
269
225
|
};
|
|
270
|
-
FilterPageProvider.defaultProps = {
|
|
271
|
-
children: null,
|
|
272
|
-
activeFilters: null,
|
|
273
|
-
parentRouteId: null,
|
|
274
|
-
filters: null,
|
|
275
|
-
onApply: () => setTimeout(router.pop, 250)
|
|
276
|
-
};
|
|
277
|
-
|
|
278
|
-
/**
|
|
279
|
-
* @type FilterPageProvider
|
|
280
|
-
*/
|
|
281
226
|
export default connect(mapStateToProps, null, null, {
|
|
282
227
|
areStatePropsEqual
|
|
283
228
|
})(FilterPageProvider);
|
|
@@ -8,7 +8,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
8
8
|
const useStyles = makeStyles()(theme => ({
|
|
9
9
|
wrapper: {
|
|
10
10
|
color: theme.palette.text.primary,
|
|
11
|
-
background: theme.palette.background.
|
|
11
|
+
background: theme.palette.background.surface
|
|
12
12
|
},
|
|
13
13
|
inner: {
|
|
14
14
|
display: 'flex',
|
|
@@ -16,7 +16,8 @@ const useStyles = makeStyles()(theme => ({
|
|
|
16
16
|
margin: theme.spacing(0, 2),
|
|
17
17
|
borderBottom: `1px solid ${theme.components.border.light}`,
|
|
18
18
|
alignItems: 'center',
|
|
19
|
-
height: theme.components.filterBar.height
|
|
19
|
+
height: theme.components.filterBar.height,
|
|
20
|
+
justifyContent: 'space-between'
|
|
20
21
|
},
|
|
21
22
|
innerStandalone: {
|
|
22
23
|
borderBottom: 'none'
|
|
@@ -26,6 +27,7 @@ const useStyles = makeStyles()(theme => ({
|
|
|
26
27
|
},
|
|
27
28
|
button: {
|
|
28
29
|
marginLeft: theme.spacing(2),
|
|
30
|
+
marginTop: theme.spacing(0.5),
|
|
29
31
|
textTransform: 'none'
|
|
30
32
|
}
|
|
31
33
|
}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shopgate/engage",
|
|
3
|
-
"version": "7.32.0-beta.
|
|
3
|
+
"version": "7.32.0-beta.15",
|
|
4
4
|
"description": "Shopgate's ENGAGE library.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Shopgate <support@shopgate.com>",
|
|
@@ -18,12 +18,12 @@
|
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@emotion/react": "^11.14.0",
|
|
20
20
|
"@shopgate/native-modules": "1.0.0-beta.34",
|
|
21
|
-
"@shopgate/pwa-common": "7.32.0-beta.
|
|
22
|
-
"@shopgate/pwa-common-commerce": "7.32.0-beta.
|
|
23
|
-
"@shopgate/pwa-core": "7.32.0-beta.
|
|
24
|
-
"@shopgate/pwa-ui-ios": "7.32.0-beta.
|
|
25
|
-
"@shopgate/pwa-ui-material": "7.32.0-beta.
|
|
26
|
-
"@shopgate/pwa-ui-shared": "7.32.0-beta.
|
|
21
|
+
"@shopgate/pwa-common": "7.32.0-beta.15",
|
|
22
|
+
"@shopgate/pwa-common-commerce": "7.32.0-beta.15",
|
|
23
|
+
"@shopgate/pwa-core": "7.32.0-beta.15",
|
|
24
|
+
"@shopgate/pwa-ui-ios": "7.32.0-beta.15",
|
|
25
|
+
"@shopgate/pwa-ui-material": "7.32.0-beta.15",
|
|
26
|
+
"@shopgate/pwa-ui-shared": "7.32.0-beta.15",
|
|
27
27
|
"@stripe/react-stripe-js": "^1.16.5",
|
|
28
28
|
"@stripe/stripe-js": "^1.44.1",
|
|
29
29
|
"@virtuous/conductor": "~2.5.0",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../../page/components/Widgets/hooks.ts"],"names":[],"mappings":"AAcA,OAAO,EAEL,KAAK,yBAAyB,EAC/B,MAAM,yBAAyB,CAAC;AAoBjC;;;GAGG;AACH,eAAO,MAAM,6BAA6B,GAAI,kBAAgB,
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../../page/components/Widgets/hooks.ts"],"names":[],"mappings":"AAcA,OAAO,EAEL,KAAK,yBAAyB,EAC/B,MAAM,yBAAyB,CAAC;AAoBjC;;;GAGG;AACH,eAAO,MAAM,6BAA6B,GAAI,kBAAgB,SA8G7D,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,QAAO,yBAA8D,CAAC"}
|
|
@@ -36,6 +36,10 @@ export const usePreviewIframeCommunication = (isActive = false) => {
|
|
|
36
36
|
const {
|
|
37
37
|
sendToParent
|
|
38
38
|
} = useIframeMessenger(data => {
|
|
39
|
+
// Allowed parents can also emit unrelated messages with arbitrary payloads.
|
|
40
|
+
if (typeof data !== 'object' || data === null) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
39
43
|
if (data.type === 'receivePageConfig') {
|
|
40
44
|
// Page preview config received from the parent window.
|
|
41
45
|
dispatch(receivePageConfigV2({
|
|
@@ -110,7 +114,7 @@ export const usePreviewIframeCommunication = (isActive = false) => {
|
|
|
110
114
|
});
|
|
111
115
|
}
|
|
112
116
|
}
|
|
113
|
-
}, ALLOWED_ADMIN_PREVIEW_ORIGINS);
|
|
117
|
+
}, ALLOWED_ADMIN_PREVIEW_ORIGINS, isActive);
|
|
114
118
|
useWidgetPreviewEvent('widget-clicked', e => {
|
|
115
119
|
if (!isActive) {
|
|
116
120
|
return;
|