@shopgate/pwa-common-commerce 7.30.0 → 7.30.1-beta.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/cart/reducers/couponField.js +1 -3
- package/cart/reducers/data.js +1 -1
- package/category/reducers/categoriesById.js +1 -1
- package/category/reducers/childrenByCategoryId.js +1 -1
- package/category/reducers/rootCategories.js +1 -1
- package/favorites/reducers/lists.js +58 -63
- package/favorites/reducers/products.js +196 -201
- package/favorites/selectors/index.js +1 -2
- package/filter/reducers/resultsByHash.js +1 -1
- package/package.json +4 -4
- package/product/actions/fetchProductsById.d.ts +1 -3
- package/product/reducers/descriptionsByProductId.js +1 -1
- package/product/reducers/imagesByProductId.js +1 -1
- package/product/reducers/mediaByProductId.js +1 -1
- package/product/reducers/optionsByProductId.js +1 -1
- package/product/reducers/productRelationsByHash.js +1 -1
- package/product/reducers/productsById.js +1 -1
- package/product/reducers/propertiesByProductId.js +1 -1
- package/product/reducers/resultsByHash.js +1 -1
- package/product/reducers/shippingByProductId.js +1 -1
- package/product/reducers/variantsByProductId.js +1 -1
- package/product/selectors/product.js +6 -1
- package/reviews/reducers/reviewsByHash.js +1 -1
- package/reviews/reducers/reviewsById.js +1 -1
- package/reviews/reducers/reviewsByProductId.js +1 -1
- package/reviews/reducers/userReviewsByProductId.js +1 -1
- package/search/reducers/index.js +1 -1
|
@@ -11,8 +11,7 @@ const defaultState = {
|
|
|
11
11
|
* @param {Object} action The redux action.
|
|
12
12
|
* @returns {Object}
|
|
13
13
|
*/
|
|
14
|
-
export default (state = defaultState, action) => {
|
|
15
|
-
/* eslint-disable no-param-reassign */
|
|
14
|
+
export default (state = defaultState, action = {}) => {
|
|
16
15
|
const producer = produce(draft => {
|
|
17
16
|
switch (action.type) {
|
|
18
17
|
case SET_COUPON_FIELD_VALUE:
|
|
@@ -29,6 +28,5 @@ export default (state = defaultState, action) => {
|
|
|
29
28
|
break;
|
|
30
29
|
}
|
|
31
30
|
});
|
|
32
|
-
/* eslint-enable no-param-reassign */
|
|
33
31
|
return producer(state);
|
|
34
32
|
};
|
package/cart/reducers/data.js
CHANGED
|
@@ -16,7 +16,7 @@ const defaultState = {
|
|
|
16
16
|
* @param {Object} action The action object.
|
|
17
17
|
* @return {Object} The new state.
|
|
18
18
|
*/
|
|
19
|
-
export default (state = defaultState, action) => {
|
|
19
|
+
export default (state = defaultState, action = {}) => {
|
|
20
20
|
switch (action.type) {
|
|
21
21
|
case ADD_PRODUCTS_TO_CART:
|
|
22
22
|
case ERROR_ADD_PRODUCTS_TO_CART:
|
|
@@ -8,7 +8,7 @@ import handleCategoryCollection from "./helpers/handleCategoryCollection";
|
|
|
8
8
|
* @param {Object} action The action object.
|
|
9
9
|
* @return {Object} The new state.
|
|
10
10
|
*/
|
|
11
|
-
const categoriesById = (state = {}, action) => {
|
|
11
|
+
const categoriesById = (state = {}, action = {}) => {
|
|
12
12
|
switch (action.type) {
|
|
13
13
|
case REQUEST_CATEGORY:
|
|
14
14
|
return {
|
|
@@ -7,7 +7,7 @@ import { CATEGORY_LIFETIME, REQUEST_CATEGORY, RECEIVE_CATEGORY, REQUEST_CATEGORY
|
|
|
7
7
|
* @param {Object} action The action object.
|
|
8
8
|
* @returns {Object} The new state.
|
|
9
9
|
*/
|
|
10
|
-
const childrenByCategoryId = (state = {}, action) => {
|
|
10
|
+
const childrenByCategoryId = (state = {}, action = {}) => {
|
|
11
11
|
switch (action.type) {
|
|
12
12
|
case REQUEST_CATEGORY:
|
|
13
13
|
case REQUEST_CATEGORY_CHILDREN:
|
|
@@ -8,7 +8,7 @@ import handleReceivedCategories from "./helpers/handleReceivedCategories";
|
|
|
8
8
|
* @param {Object} action The action object.
|
|
9
9
|
* @return {Object} The store data.
|
|
10
10
|
*/
|
|
11
|
-
const rootCategories = (state = {}, action) => {
|
|
11
|
+
const rootCategories = (state = {}, action = {}) => {
|
|
12
12
|
switch (action.type) {
|
|
13
13
|
case REQUEST_ROOT_CATEGORIES:
|
|
14
14
|
return {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { produce } from 'immer';
|
|
2
|
-
import {
|
|
2
|
+
import { CLOSE_FAVORITE_COMMENT_DIALOG, CLOSE_FAVORITE_LIST_CHOOSER, FAVORITES_LIFETIME, OPEN_FAVORITE_COMMENT_DIALOG, OPEN_FAVORITE_LIST_CHOOSER, RECEIVE_FAVORITES_LISTS, SUCCESS_ADD_FAVORITES_LIST, SUCCESS_REMOVE_FAVORITES_LIST, SUCCESS_UPDATE_FAVORITES_LIST } from "../constants";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Favorites lists reducer.
|
|
@@ -12,67 +12,62 @@ const lists = (state = {
|
|
|
12
12
|
lists: [],
|
|
13
13
|
chooser: null,
|
|
14
14
|
commentDialog: null
|
|
15
|
-
}, action) => {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
withRelatives: action.withRelatives
|
|
24
|
-
};
|
|
25
|
-
break;
|
|
26
|
-
}
|
|
27
|
-
case CLOSE_FAVORITE_LIST_CHOOSER:
|
|
28
|
-
{
|
|
29
|
-
draft.chooser = null;
|
|
30
|
-
break;
|
|
31
|
-
}
|
|
32
|
-
case OPEN_FAVORITE_COMMENT_DIALOG:
|
|
33
|
-
{
|
|
34
|
-
draft.commentDialog = {
|
|
35
|
-
productId: action.productId,
|
|
36
|
-
listId: action.listId
|
|
37
|
-
};
|
|
38
|
-
break;
|
|
39
|
-
}
|
|
40
|
-
case CLOSE_FAVORITE_COMMENT_DIALOG:
|
|
41
|
-
{
|
|
42
|
-
draft.commentDialog = null;
|
|
43
|
-
break;
|
|
44
|
-
}
|
|
45
|
-
case RECEIVE_FAVORITES_LISTS:
|
|
46
|
-
{
|
|
47
|
-
draft.expires = Date.now() + FAVORITES_LIFETIME;
|
|
48
|
-
draft.lists = action.favoritesLists;
|
|
49
|
-
break;
|
|
50
|
-
}
|
|
51
|
-
case SUCCESS_ADD_FAVORITES_LIST:
|
|
52
|
-
{
|
|
53
|
-
draft.lists.push({
|
|
54
|
-
id: action.listId,
|
|
55
|
-
name: action.name
|
|
56
|
-
});
|
|
57
|
-
break;
|
|
58
|
-
}
|
|
59
|
-
case SUCCESS_UPDATE_FAVORITES_LIST:
|
|
60
|
-
{
|
|
61
|
-
const list = draft.lists.find(l => l.id === action.listId);
|
|
62
|
-
list.name = action.name;
|
|
63
|
-
break;
|
|
64
|
-
}
|
|
65
|
-
case SUCCESS_REMOVE_FAVORITES_LIST:
|
|
66
|
-
{
|
|
67
|
-
const listIndex = draft.lists.findIndex(l => l.id === action.listId);
|
|
68
|
-
draft.lists.splice(listIndex, 1);
|
|
69
|
-
break;
|
|
70
|
-
}
|
|
71
|
-
default:
|
|
15
|
+
}, action = {}) => produce(state, draft => {
|
|
16
|
+
switch (action.type) {
|
|
17
|
+
case OPEN_FAVORITE_LIST_CHOOSER:
|
|
18
|
+
{
|
|
19
|
+
draft.chooser = {
|
|
20
|
+
productId: action.productId,
|
|
21
|
+
withRelatives: action.withRelatives
|
|
22
|
+
};
|
|
72
23
|
break;
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
24
|
+
}
|
|
25
|
+
case CLOSE_FAVORITE_LIST_CHOOSER:
|
|
26
|
+
{
|
|
27
|
+
draft.chooser = null;
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
case OPEN_FAVORITE_COMMENT_DIALOG:
|
|
31
|
+
{
|
|
32
|
+
draft.commentDialog = {
|
|
33
|
+
productId: action.productId,
|
|
34
|
+
listId: action.listId
|
|
35
|
+
};
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
case CLOSE_FAVORITE_COMMENT_DIALOG:
|
|
39
|
+
{
|
|
40
|
+
draft.commentDialog = null;
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
case RECEIVE_FAVORITES_LISTS:
|
|
44
|
+
{
|
|
45
|
+
draft.expires = Date.now() + FAVORITES_LIFETIME;
|
|
46
|
+
draft.lists = action.favoritesLists;
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
case SUCCESS_ADD_FAVORITES_LIST:
|
|
50
|
+
{
|
|
51
|
+
draft.lists.push({
|
|
52
|
+
id: action.listId,
|
|
53
|
+
name: action.name
|
|
54
|
+
});
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
case SUCCESS_UPDATE_FAVORITES_LIST:
|
|
58
|
+
{
|
|
59
|
+
const list = draft.lists.find(l => l.id === action.listId);
|
|
60
|
+
list.name = action.name;
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
case SUCCESS_REMOVE_FAVORITES_LIST:
|
|
64
|
+
{
|
|
65
|
+
const listIndex = draft.lists.findIndex(l => l.id === action.listId);
|
|
66
|
+
draft.lists.splice(listIndex, 1);
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
default:
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
});
|
|
78
73
|
export default lists;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { produce } from 'immer';
|
|
2
2
|
import isNumber from 'lodash/isNumber';
|
|
3
3
|
import isString from 'lodash/isString';
|
|
4
|
-
import {
|
|
4
|
+
import { CANCEL_REQUEST_SYNC_FAVORITES, ERROR_ADD_FAVORITES, ERROR_FETCH_FAVORITES, ERROR_REMOVE_FAVORITES, ERROR_UPDATE_FAVORITES, FAVORITES_LIFETIME, RECEIVE_FAVORITES, RECEIVE_FAVORITES_LISTS, REQUEST_ADD_FAVORITES, REQUEST_FAVORITES, REQUEST_REMOVE_FAVORITES, REQUEST_UPDATE_FAVORITES, SUCCESS_ADD_FAVORITES, SUCCESS_ADD_FAVORITES_LIST, SUCCESS_REMOVE_FAVORITES, SUCCESS_REMOVE_FAVORITES_LIST, SUCCESS_UPDATE_FAVORITES } from "../constants";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Favorites reducer.
|
|
@@ -11,225 +11,220 @@ import { REQUEST_ADD_FAVORITES, SUCCESS_ADD_FAVORITES, CANCEL_REQUEST_SYNC_FAVOR
|
|
|
11
11
|
*/
|
|
12
12
|
const products = (state = {
|
|
13
13
|
byList: {}
|
|
14
|
-
}, action) => {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
{
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
};
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
existingList.isFetching = true;
|
|
34
|
-
existingList.expires = 0;
|
|
35
|
-
break;
|
|
14
|
+
}, action = {}) => produce(state, draft => {
|
|
15
|
+
switch (action.type) {
|
|
16
|
+
// Handle a new favorites request.
|
|
17
|
+
case REQUEST_FAVORITES:
|
|
18
|
+
{
|
|
19
|
+
const existingList = draft.byList[action.listId];
|
|
20
|
+
if (!existingList) {
|
|
21
|
+
draft.byList[action.listId] = {
|
|
22
|
+
isFetching: true,
|
|
23
|
+
lastChange: 0,
|
|
24
|
+
lastFetch: 0,
|
|
25
|
+
expires: 0,
|
|
26
|
+
items: [],
|
|
27
|
+
syncCount: 0
|
|
28
|
+
};
|
|
29
|
+
return;
|
|
36
30
|
}
|
|
31
|
+
existingList.isFetching = true;
|
|
32
|
+
existingList.expires = 0;
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
37
35
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
36
|
+
// Handle incoming favorite products.
|
|
37
|
+
case RECEIVE_FAVORITES:
|
|
38
|
+
{
|
|
39
|
+
const list = draft.byList[action.listId];
|
|
40
|
+
const isSynching = list.syncCount > 0;
|
|
41
|
+
const isOngoing = state.lastChange > action.requestTimestamp;
|
|
44
42
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
list.expires = Date.now() + FAVORITES_LIFETIME;
|
|
56
|
-
list.items = action.items.map(({
|
|
57
|
-
quantity,
|
|
58
|
-
notes,
|
|
59
|
-
product
|
|
60
|
-
}) => ({
|
|
61
|
-
quantity,
|
|
62
|
-
notes,
|
|
63
|
-
productId: product.id
|
|
64
|
-
}));
|
|
65
|
-
list.ready = true;
|
|
66
|
-
// `syncCount` stays untouched because this is not considered to be a sync.
|
|
67
|
-
break;
|
|
43
|
+
/**
|
|
44
|
+
* Note: When favorites are received, an add or remove request can be in progress. In this
|
|
45
|
+
* case only fetching state will be updated and the received data will be discarded.
|
|
46
|
+
* A new fetch request will be queued as soon as the sync is done, which will recover
|
|
47
|
+
* discarded data.
|
|
48
|
+
*/
|
|
49
|
+
list.isFetching = false;
|
|
50
|
+
if (list.ready && (isSynching || isOngoing)) {
|
|
51
|
+
return;
|
|
68
52
|
}
|
|
53
|
+
list.expires = Date.now() + FAVORITES_LIFETIME;
|
|
54
|
+
list.items = action.items.map(({
|
|
55
|
+
quantity,
|
|
56
|
+
notes,
|
|
57
|
+
product
|
|
58
|
+
}) => ({
|
|
59
|
+
quantity,
|
|
60
|
+
notes,
|
|
61
|
+
productId: product.id
|
|
62
|
+
}));
|
|
63
|
+
list.ready = true;
|
|
64
|
+
// `syncCount` stays untouched because this is not considered to be a sync.
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
69
67
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
68
|
+
// Handle failed fetching
|
|
69
|
+
case ERROR_FETCH_FAVORITES:
|
|
70
|
+
{
|
|
71
|
+
const list = draft.byList[action.listId];
|
|
72
|
+
list.isFetching = false;
|
|
73
|
+
list.expires = 0;
|
|
74
|
+
list.ready = true;
|
|
75
|
+
// `syncCount` stays untouched because this is not considered to be a sync.
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
80
78
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
list.lastChange = Date.now();
|
|
99
|
-
list.syncCount += 1;
|
|
100
|
-
break;
|
|
79
|
+
// Handle adding favorite list products.
|
|
80
|
+
case REQUEST_ADD_FAVORITES:
|
|
81
|
+
{
|
|
82
|
+
const list = draft.byList[action.listId];
|
|
83
|
+
const matchingItem = list.items.find(({
|
|
84
|
+
productId
|
|
85
|
+
}) => productId === action.productId);
|
|
86
|
+
if (matchingItem) {
|
|
87
|
+
matchingItem.notes = typeof action.notes === 'string' ? action.notes : matchingItem.notes;
|
|
88
|
+
matchingItem.quantity = typeof action.quantity === 'number' ? matchingItem.quantity + action.quantity : matchingItem.quantity + 1;
|
|
89
|
+
} else {
|
|
90
|
+
list.items.push({
|
|
91
|
+
notes: action.notes || '',
|
|
92
|
+
quantity: action.quantity || 1,
|
|
93
|
+
productId: action.productId
|
|
94
|
+
});
|
|
101
95
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
list.lastChange = Date.now();
|
|
116
|
-
list.syncCount += 1;
|
|
96
|
+
list.lastChange = Date.now();
|
|
97
|
+
list.syncCount += 1;
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
case REQUEST_UPDATE_FAVORITES:
|
|
101
|
+
{
|
|
102
|
+
const list = draft.byList[action.listId];
|
|
103
|
+
const matchingItem = list.items.find(({
|
|
104
|
+
productId
|
|
105
|
+
}) => productId === action.productId);
|
|
106
|
+
if (matchingItem) {
|
|
107
|
+
if (isNumber(action.quantity)) {
|
|
108
|
+
matchingItem.quantity = action.quantity;
|
|
117
109
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
// Handle removing favorite list products.
|
|
122
|
-
case REQUEST_REMOVE_FAVORITES:
|
|
123
|
-
{
|
|
124
|
-
const list = draft.byList[action.listId];
|
|
125
|
-
const matchingItemIndex = list.items.findIndex(({
|
|
126
|
-
productId
|
|
127
|
-
}) => productId === action.productId);
|
|
128
|
-
if (matchingItemIndex > -1) {
|
|
129
|
-
list.items.splice(matchingItemIndex, 1);
|
|
110
|
+
if (isString(action.notes)) {
|
|
111
|
+
matchingItem.notes = action.notes;
|
|
130
112
|
}
|
|
131
113
|
list.lastChange = Date.now();
|
|
132
114
|
list.syncCount += 1;
|
|
133
|
-
break;
|
|
134
|
-
}
|
|
135
|
-
// Handle cancellation of synchronization.
|
|
136
|
-
// Sync count needs to be updated, when an add or a remove favorites action is cancelled
|
|
137
|
-
// This recovers from invalid sync states when a backend call is detected to be redundant
|
|
138
|
-
case CANCEL_REQUEST_SYNC_FAVORITES:
|
|
139
|
-
{
|
|
140
|
-
const list = draft.byList[action.listId];
|
|
141
|
-
list.syncCount -= action.count;
|
|
142
|
-
break;
|
|
143
115
|
}
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
144
118
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
{
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
119
|
+
// Handle removing favorite list products.
|
|
120
|
+
case REQUEST_REMOVE_FAVORITES:
|
|
121
|
+
{
|
|
122
|
+
const list = draft.byList[action.listId];
|
|
123
|
+
const matchingItemIndex = list.items.findIndex(({
|
|
124
|
+
productId
|
|
125
|
+
}) => productId === action.productId);
|
|
126
|
+
if (matchingItemIndex > -1) {
|
|
127
|
+
list.items.splice(matchingItemIndex, 1);
|
|
154
128
|
}
|
|
129
|
+
list.lastChange = Date.now();
|
|
130
|
+
list.syncCount += 1;
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
// Handle cancellation of synchronization.
|
|
134
|
+
// Sync count needs to be updated, when an add or a remove favorites action is cancelled
|
|
135
|
+
// This recovers from invalid sync states when a backend call is detected to be redundant
|
|
136
|
+
case CANCEL_REQUEST_SYNC_FAVORITES:
|
|
137
|
+
{
|
|
138
|
+
const list = draft.byList[action.listId];
|
|
139
|
+
list.syncCount -= action.count;
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
155
142
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
list.syncCount -= 1;
|
|
167
|
-
break;
|
|
168
|
-
}
|
|
143
|
+
// Handle success of adding favorite list products.
|
|
144
|
+
case SUCCESS_ADD_FAVORITES:
|
|
145
|
+
case SUCCESS_UPDATE_FAVORITES:
|
|
146
|
+
case SUCCESS_REMOVE_FAVORITES:
|
|
147
|
+
{
|
|
148
|
+
const list = draft.byList[action.listId];
|
|
149
|
+
list.lastChange = Date.now();
|
|
150
|
+
list.syncCount -= 1;
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
169
153
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
}
|
|
184
|
-
case ERROR_UPDATE_FAVORITES:
|
|
185
|
-
{
|
|
186
|
-
const list = draft.byList[action.listId];
|
|
187
|
-
list.lastChange = Date.now();
|
|
188
|
-
list.syncCount -= 1;
|
|
189
|
-
break;
|
|
190
|
-
}
|
|
154
|
+
// Handle deletion failure by adding the product back in to the list.
|
|
155
|
+
case ERROR_REMOVE_FAVORITES:
|
|
156
|
+
{
|
|
157
|
+
const list = draft.byList[action.listId];
|
|
158
|
+
list.items.push({
|
|
159
|
+
productId: action.productId,
|
|
160
|
+
quantity: action.quantity || 1,
|
|
161
|
+
notes: action.notes || ''
|
|
162
|
+
});
|
|
163
|
+
list.lastChange = Date.now();
|
|
164
|
+
list.syncCount -= 1;
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
191
167
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
168
|
+
// Handle adding failure by removing the product from the list.
|
|
169
|
+
case ERROR_ADD_FAVORITES:
|
|
170
|
+
{
|
|
171
|
+
const list = draft.byList[action.listId];
|
|
172
|
+
const matchingItemIndex = list.items.findIndex(({
|
|
173
|
+
productId
|
|
174
|
+
}) => productId === action.productId);
|
|
175
|
+
if (matchingItemIndex > -1) {
|
|
176
|
+
list.items.splice(matchingItemIndex, 1);
|
|
197
177
|
}
|
|
178
|
+
list.lastChange = Date.now();
|
|
179
|
+
list.syncCount -= 1;
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
case ERROR_UPDATE_FAVORITES:
|
|
183
|
+
{
|
|
184
|
+
const list = draft.byList[action.listId];
|
|
185
|
+
list.lastChange = Date.now();
|
|
186
|
+
list.syncCount -= 1;
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
198
189
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
lastFetch: 0,
|
|
206
|
-
expires: 0,
|
|
207
|
-
items: [],
|
|
208
|
-
syncCount: 0,
|
|
209
|
-
ready: true
|
|
210
|
-
};
|
|
211
|
-
break;
|
|
212
|
-
}
|
|
190
|
+
// Handle cleanup after deletion of a list.
|
|
191
|
+
case SUCCESS_REMOVE_FAVORITES_LIST:
|
|
192
|
+
{
|
|
193
|
+
delete draft.byList[action.listId];
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
213
196
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
197
|
+
// Handle adding new lists.
|
|
198
|
+
case SUCCESS_ADD_FAVORITES_LIST:
|
|
199
|
+
{
|
|
200
|
+
draft.byList[action.listId] = {
|
|
201
|
+
isFetching: true,
|
|
202
|
+
lastChange: 0,
|
|
203
|
+
lastFetch: 0,
|
|
204
|
+
expires: 0,
|
|
205
|
+
items: [],
|
|
206
|
+
syncCount: 0,
|
|
207
|
+
ready: true
|
|
208
|
+
};
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Handle cleanup after lists are updated
|
|
213
|
+
case RECEIVE_FAVORITES_LISTS:
|
|
214
|
+
{
|
|
215
|
+
const listIds = action.favoritesLists.map(({
|
|
216
|
+
id
|
|
217
|
+
}) => id);
|
|
218
|
+
Object.keys(draft.byList).forEach(id => {
|
|
219
|
+
if (!listIds.includes(id)) {
|
|
220
|
+
// Remove list items that don't have a list anymore
|
|
221
|
+
delete draft.byList[id];
|
|
222
|
+
}
|
|
223
|
+
});
|
|
229
224
|
break;
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
};
|
|
225
|
+
}
|
|
226
|
+
default:
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
229
|
+
});
|
|
235
230
|
export default products;
|
|
@@ -3,8 +3,7 @@ import { createSelector } from 'reselect';
|
|
|
3
3
|
import uniq from 'lodash/uniq';
|
|
4
4
|
import appConfig from '@shopgate/pwa-common/helpers/config';
|
|
5
5
|
import { hasNewServices } from '@shopgate/engage/core/helpers';
|
|
6
|
-
import { getProducts, getProductId } from "../../product
|
|
7
|
-
import { getKnownRelatives } from "../../product/selectors/variants";
|
|
6
|
+
import { getProducts, getProductId, getKnownRelatives } from "../../product";
|
|
8
7
|
const defaultIds = [];
|
|
9
8
|
|
|
10
9
|
/**
|
|
@@ -8,7 +8,7 @@ import enrichFilters from "./helpers/enrichFilters";
|
|
|
8
8
|
* @param {Object} action The current redux action.
|
|
9
9
|
* @return {Object} The new state.
|
|
10
10
|
*/
|
|
11
|
-
export default function resultsByHash(state = {}, action) {
|
|
11
|
+
export default function resultsByHash(state = {}, action = {}) {
|
|
12
12
|
switch (action.type) {
|
|
13
13
|
case REQUEST_FILTERS:
|
|
14
14
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shopgate/pwa-common-commerce",
|
|
3
|
-
"version": "7.30.
|
|
3
|
+
"version": "7.30.1-beta.1",
|
|
4
4
|
"description": "Commerce library for the Shopgate Connect PWA.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Shopgate <support@shopgate.com>",
|
|
@@ -19,9 +19,9 @@
|
|
|
19
19
|
"reselect": "^4.1.8"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
|
-
"@shopgate/pwa-common": "7.30.
|
|
23
|
-
"@shopgate/pwa-core": "7.30.
|
|
24
|
-
"lodash": "^4.17.
|
|
22
|
+
"@shopgate/pwa-common": "7.30.1-beta.1",
|
|
23
|
+
"@shopgate/pwa-core": "7.30.1-beta.1",
|
|
24
|
+
"lodash": "^4.17.23",
|
|
25
25
|
"react": "^17.0.2",
|
|
26
26
|
"react-dom": "^17.0.2"
|
|
27
27
|
}
|
|
@@ -7,7 +7,7 @@ import { PRODUCT_LIFETIME, REQUEST_PRODUCT_DESCRIPTION, RECEIVE_PRODUCT_DESCRIPT
|
|
|
7
7
|
* @param {Object} action The action object.
|
|
8
8
|
* @return {Object} The new state.
|
|
9
9
|
*/
|
|
10
|
-
export default function descriptionsByProductId(state = {}, action) {
|
|
10
|
+
export default function descriptionsByProductId(state = {}, action = {}) {
|
|
11
11
|
switch (action.type) {
|
|
12
12
|
case REQUEST_PRODUCT_DESCRIPTION:
|
|
13
13
|
return {
|
|
@@ -7,7 +7,7 @@ import { PRODUCT_LIFETIME, REQUEST_PRODUCT_IMAGES, RECEIVE_PRODUCT_IMAGES, ERROR
|
|
|
7
7
|
* @param {Object} action The action object.
|
|
8
8
|
* @returns {Object}
|
|
9
9
|
*/
|
|
10
|
-
export default function imagesByProductId(state = {}, action) {
|
|
10
|
+
export default function imagesByProductId(state = {}, action = {}) {
|
|
11
11
|
switch (action.type) {
|
|
12
12
|
case REQUEST_PRODUCT_IMAGES:
|
|
13
13
|
return {
|
|
@@ -7,7 +7,7 @@ import { PRODUCT_LIFETIME, REQUEST_PRODUCT_MEDIA, RECEIVE_PRODUCT_MEDIA, ERROR_P
|
|
|
7
7
|
* @param {Object} action The action object.
|
|
8
8
|
* @return {Object} The new state.
|
|
9
9
|
*/
|
|
10
|
-
export default function mediaByProductId(state = {}, action) {
|
|
10
|
+
export default function mediaByProductId(state = {}, action = {}) {
|
|
11
11
|
switch (action.type) {
|
|
12
12
|
case REQUEST_PRODUCT_MEDIA:
|
|
13
13
|
return {
|
|
@@ -7,7 +7,7 @@ import formatOptions from "./helpers/formatOptions";
|
|
|
7
7
|
* @param {Object} action The action object.
|
|
8
8
|
* @return {Object} The new state.
|
|
9
9
|
*/
|
|
10
|
-
export default function optionsByProductId(state = {}, action) {
|
|
10
|
+
export default function optionsByProductId(state = {}, action = {}) {
|
|
11
11
|
switch (action.type) {
|
|
12
12
|
case REQUEST_PRODUCT_OPTIONS:
|
|
13
13
|
return {
|
|
@@ -6,7 +6,7 @@ import { REQUEST_PRODUCT_RELATIONS, RECEIVE_PRODUCT_RELATIONS, ERROR_PRODUCT_REL
|
|
|
6
6
|
* @param {Object} action Action.
|
|
7
7
|
* @returns {Object}
|
|
8
8
|
*/
|
|
9
|
-
const productRelationsByHash = (state = {}, action) => {
|
|
9
|
+
const productRelationsByHash = (state = {}, action = {}) => {
|
|
10
10
|
switch (action.type) {
|
|
11
11
|
case REQUEST_PRODUCT_RELATIONS:
|
|
12
12
|
return {
|
|
@@ -9,7 +9,7 @@ import handleProductCollection from "./helpers/handleProductCollection";
|
|
|
9
9
|
* @param {Object} action The action object.
|
|
10
10
|
* @return {Object} The new state.
|
|
11
11
|
*/
|
|
12
|
-
export default function productsById(state = {}, action) {
|
|
12
|
+
export default function productsById(state = {}, action = {}) {
|
|
13
13
|
switch (action.type) {
|
|
14
14
|
case RECEIVE_PRODUCTS:
|
|
15
15
|
return {
|
|
@@ -7,7 +7,7 @@ import { PRODUCT_LIFETIME, REQUEST_PRODUCT_PROPERTIES, RECEIVE_PRODUCT_PROPERTIE
|
|
|
7
7
|
* @param {Object} action The action object.
|
|
8
8
|
* @return {Object} The new state.
|
|
9
9
|
*/
|
|
10
|
-
export default function propertiesByProductId(state = {}, action) {
|
|
10
|
+
export default function propertiesByProductId(state = {}, action = {}) {
|
|
11
11
|
switch (action.type) {
|
|
12
12
|
case REQUEST_PRODUCT_PROPERTIES:
|
|
13
13
|
return {
|
|
@@ -11,7 +11,7 @@ import { PRODUCT_LIFETIME, REQUEST_PRODUCTS, RECEIVE_PRODUCTS, ERROR_PRODUCTS, E
|
|
|
11
11
|
* @param {Object} action The current redux action.
|
|
12
12
|
* @return {Object} The new state.
|
|
13
13
|
*/
|
|
14
|
-
export default function resultsByHash(state = {}, action) {
|
|
14
|
+
export default function resultsByHash(state = {}, action = {}) {
|
|
15
15
|
switch (action.type) {
|
|
16
16
|
case REQUEST_PRODUCTS:
|
|
17
17
|
return {
|
|
@@ -6,7 +6,7 @@ import { PRODUCT_LIFETIME, REQUEST_PRODUCT_SHIPPING, RECEIVE_PRODUCT_SHIPPING, E
|
|
|
6
6
|
* @param {Object} action The action object.
|
|
7
7
|
* @return {Object} The new state.
|
|
8
8
|
*/
|
|
9
|
-
export default function shippingByProductId(state = {}, action) {
|
|
9
|
+
export default function shippingByProductId(state = {}, action = {}) {
|
|
10
10
|
switch (action.type) {
|
|
11
11
|
case REQUEST_PRODUCT_SHIPPING:
|
|
12
12
|
return {
|
|
@@ -7,7 +7,7 @@ import { PRODUCT_LIFETIME, REQUEST_PRODUCT_VARIANTS, RECEIVE_PRODUCT_VARIANTS, E
|
|
|
7
7
|
* @param {Object} action The action object.
|
|
8
8
|
* @return {Object} The new state.
|
|
9
9
|
*/
|
|
10
|
-
export default function variantsByProductId(state = {}, action) {
|
|
10
|
+
export default function variantsByProductId(state = {}, action = {}) {
|
|
11
11
|
switch (action.type) {
|
|
12
12
|
case REQUEST_PRODUCT_VARIANTS:
|
|
13
13
|
return {
|
|
@@ -11,13 +11,18 @@ import { getIsLocationBasedShopping } from '@shopgate/engage/core/selectors/merc
|
|
|
11
11
|
import { getActiveFilters } from "../../filter/selectors";
|
|
12
12
|
import { filterProperties } from "../helpers";
|
|
13
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Shared empty product state to keep the fallback referentially stable.
|
|
16
|
+
*/
|
|
17
|
+
const EMPTY_PRODUCT_STATE = {};
|
|
18
|
+
|
|
14
19
|
/**
|
|
15
20
|
* Retrieves the product state from the store.
|
|
16
21
|
* @deprecated Also exists within @shopgate/engage/product/selectors/product
|
|
17
22
|
* @param {Object} state The current application state.
|
|
18
23
|
* @return {Object} The product state.
|
|
19
24
|
*/
|
|
20
|
-
export const getProductState = state => state.product ||
|
|
25
|
+
export const getProductState = state => state.product || EMPTY_PRODUCT_STATE;
|
|
21
26
|
|
|
22
27
|
/**
|
|
23
28
|
* Selects all products from the store.
|
|
@@ -7,7 +7,7 @@ import { REVIEWS_LIFETIME, REQUEST_REVIEWS, RECEIVE_REVIEWS, ERROR_REVIEWS } fro
|
|
|
7
7
|
* @param {Object} action The current redux action.
|
|
8
8
|
* @return {Object} The new state.
|
|
9
9
|
*/
|
|
10
|
-
function reviewsByHash(state = {}, action) {
|
|
10
|
+
function reviewsByHash(state = {}, action = {}) {
|
|
11
11
|
switch (action.type) {
|
|
12
12
|
case REQUEST_REVIEWS:
|
|
13
13
|
return {
|
|
@@ -7,7 +7,7 @@ import { RECEIVE_PRODUCT_REVIEWS, RECEIVE_REVIEWS, RECEIVE_USER_REVIEW, RECEIVE_
|
|
|
7
7
|
* @param {Object} action The current redux action.
|
|
8
8
|
* @return {Object} The new state.
|
|
9
9
|
*/
|
|
10
|
-
function reviewsById(state = {}, action) {
|
|
10
|
+
function reviewsById(state = {}, action = {}) {
|
|
11
11
|
switch (action.type) {
|
|
12
12
|
case RECEIVE_PRODUCT_REVIEWS:
|
|
13
13
|
case RECEIVE_REVIEWS:
|
|
@@ -6,7 +6,7 @@ import { REQUEST_PRODUCT_REVIEWS, RECEIVE_PRODUCT_REVIEWS, ERROR_PRODUCT_REVIEWS
|
|
|
6
6
|
* @param {Object} action The action object.
|
|
7
7
|
* @return {Object} The new state.
|
|
8
8
|
*/
|
|
9
|
-
export default function reviewsByProductId(state = {}, action) {
|
|
9
|
+
export default function reviewsByProductId(state = {}, action = {}) {
|
|
10
10
|
switch (action.type) {
|
|
11
11
|
case REQUEST_PRODUCT_REVIEWS:
|
|
12
12
|
return {
|
|
@@ -6,7 +6,7 @@ import { REQUEST_USER_REVIEW, REQUEST_SUBMIT_REVIEW, RECEIVE_USER_REVIEW, RECEIV
|
|
|
6
6
|
* @param {Object} action The action object.
|
|
7
7
|
* @return {Object} The new state.
|
|
8
8
|
*/
|
|
9
|
-
export default function userReviewsByProductId(state = {}, action) {
|
|
9
|
+
export default function userReviewsByProductId(state = {}, action = {}) {
|
|
10
10
|
switch (action.type) {
|
|
11
11
|
case REQUEST_USER_REVIEW:
|
|
12
12
|
return {
|
package/search/reducers/index.js
CHANGED
|
@@ -9,7 +9,7 @@ const initialState = {
|
|
|
9
9
|
* @param {Object} action The action object.
|
|
10
10
|
* @return {Object} The updated search suggestions data.
|
|
11
11
|
*/
|
|
12
|
-
const search = (state = initialState, action) => {
|
|
12
|
+
const search = (state = initialState, action = {}) => {
|
|
13
13
|
switch (action.type) {
|
|
14
14
|
case REQUEST_SEARCH_SUGGESTIONS:
|
|
15
15
|
return {
|