homeflowjs 0.13.64 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,6 +3,7 @@ import PropertiesActionTypes from './properties.types';
3
3
  import { buildQueryString } from '../search/property-search/property-search';
4
4
  import { setSearch } from './search.actions';
5
5
  import { setLoading } from './app.actions';
6
+ import { getOfflineSavedProperties } from '../utils';
6
7
 
7
8
  export const setPropertyLinks = (payload) => ({
8
9
  type: PropertiesActionTypes.SET_PROPERTY_LINKS,
@@ -214,33 +215,36 @@ export const postLocalSavedProperties = () => (dispatch, getState) => {
214
215
  });
215
216
  };
216
217
 
218
+ const fetchSaveProperty = (data) => fetch('/saved_properties.ljson', {
219
+ method: 'POST',
220
+ headers: { 'Content-Type': 'application/json' },
221
+ body: JSON.stringify({ property_ids: data.toString() }),
222
+ });
223
+
217
224
  export const addSavedProperty = (payload) => (dispatch, getState) => {
218
225
  const userLoggedIn = !!getState().user.currentUser.user_id;
219
226
 
220
227
  dispatch(toggleSavedProperty({ propertyId: payload, userLoggedIn }));
221
228
 
222
229
  if (userLoggedIn) {
223
- fetch('/saved_properties.ljson', {
224
- method: 'POST',
225
- headers: { 'Content-Type': 'application/json' },
226
- body: JSON.stringify({ property_ids: payload.toString() }),
227
- });
230
+ fetchSaveProperty(payload);
228
231
  }
229
232
  };
230
233
 
234
+ const fetchRemoveProperties = (data) => fetch(`/saved_properties/${data}`, {
235
+ method: 'POST',
236
+ headers: {
237
+ 'X-Http-Method-Override': 'delete',
238
+ },
239
+ });
240
+
231
241
  export const removeSavedProperty = (payload) => (dispatch, getState) => {
232
242
  const userLoggedIn = !!getState().user.currentUser.user_id;
233
243
 
234
244
  dispatch(toggleSavedProperty({ propertyId: payload, userLoggedIn }));
235
245
 
236
246
  if (userLoggedIn) {
237
- fetch(`/saved_properties/${payload}`,
238
- {
239
- method: 'POST',
240
- headers: {
241
- 'X-Http-Method-Override': 'delete',
242
- },
243
- });
247
+ fetchRemoveProperties(payload);
244
248
  }
245
249
  };
246
250
 
@@ -249,17 +253,88 @@ export const setSavedProperties = (payload) => ({
249
253
  payload,
250
254
  });
251
255
 
256
+ const setPropertyDataLoadingStatus = (payload) => ({
257
+ type: PropertiesActionTypes.SET_PROPERTY_DATA_LOADING,
258
+ payload,
259
+ });
260
+
261
+ const getPropertyIdList = (properties) => properties.map((property) => property.id);
262
+ const filterMissingPropertiesInIdList = ({ propertyList, idList }) => propertyList
263
+ .filter((property) => !idList.includes(property.id));
264
+
265
+ const saveOfflineProperties = () => (dispatch) => {
266
+ const offlineSavedProperties = getOfflineSavedProperties();
267
+ if (offlineSavedProperties.length > 0) {
268
+ fetchSaveProperty(getPropertyIdList(offlineSavedProperties));
269
+ }
270
+ dispatch(setSavedProperties(offlineSavedProperties));
271
+ };
272
+
252
273
  export const fetchSavedProperties = () => (dispatch) => {
274
+ const offlineSavedProperties = getOfflineSavedProperties();
275
+ dispatch(setPropertyDataLoadingStatus(true));
276
+
253
277
  fetch('/saved_properties.ljson')
254
278
  .then((response) => response.json())
255
279
  .then((json) => {
256
280
  if (json) {
257
- dispatch(setSavedProperties(json.properties));
281
+ const requestedPropertyIds = getPropertyIdList(json.properties);
282
+ const offlinePropertyIds = getPropertyIdList(offlineSavedProperties);
283
+ const isCurrentSavedPropertyListSynced = localStorage.getItem('is_synced_saved_properties_list');
284
+
285
+ const propertiesToAddOnInit = filterMissingPropertiesInIdList({
286
+ propertyList: offlineSavedProperties,
287
+ idList: requestedPropertyIds,
288
+ });
289
+
290
+ if (propertiesToAddOnInit.length > 0) {
291
+ fetchSaveProperty(getPropertyIdList(propertiesToAddOnInit));
292
+ }
293
+
294
+ const propertiesToRemoveOnInit = [];
295
+
296
+ if (isCurrentSavedPropertyListSynced) {
297
+ filterMissingPropertiesInIdList({
298
+ propertyList: json.properties,
299
+ idList: offlinePropertyIds,
300
+ }).forEach((property) => {
301
+ propertiesToRemoveOnInit.push(property);
302
+ fetchRemoveProperties(property.id);
303
+ });
304
+ }
305
+
306
+ let userSavedProperties = [
307
+ ...json.properties,
308
+ ...propertiesToAddOnInit,
309
+ ];
310
+
311
+ if (propertiesToRemoveOnInit.length > 0) {
312
+ const propertyIdListToRemoveOnInit = getPropertyIdList(propertiesToRemoveOnInit);
313
+ userSavedProperties = userSavedProperties.reduce(
314
+ (updatedPropertyList, property) => (propertyIdListToRemoveOnInit.includes(property.id)
315
+ ? updatedPropertyList
316
+ : [
317
+ ...updatedPropertyList,
318
+ property,
319
+ ]),
320
+ [],
321
+ );
322
+ }
323
+
324
+ dispatch(setSavedProperties(userSavedProperties));
325
+
326
+ if (!isCurrentSavedPropertyListSynced) {
327
+ localStorage.setItem('is_synced_saved_properties_list', true);
328
+ localStorage.setItem('savedProperties', JSON.stringify(userSavedProperties));
329
+ }
258
330
  } else {
259
- dispatch(setSavedProperties([]));
331
+ dispatch(saveOfflineProperties());
260
332
  }
261
333
  })
262
- .catch(() => dispatch(setSavedProperties([])));
334
+ .catch(() => {
335
+ dispatch(saveOfflineProperties());
336
+ })
337
+ .finally(() => dispatch(setPropertyDataLoadingStatus(false)));
263
338
  };
264
339
 
265
340
  export const setSelectedMarker = (payload) => ({
@@ -9,6 +9,7 @@ const PropertiesActionTypes = {
9
9
  SET_PROPERTY_LINKS: 'SET_PROPERTY_LINKS',
10
10
  SET_SELECTED_MARKER: 'SET_SELECTED_MARKER',
11
11
  SET_GEONAMES: 'SET_GEONAMES',
12
+ SET_PROPERTY_DATA_LOADING: 'SET_PROPERTY_DATA_LOADING'
12
13
  };
13
14
 
14
15
  export default PropertiesActionTypes;
@@ -6,7 +6,7 @@ import { setLoading } from './app.actions';
6
6
  import { INITIAL_USER_DATA } from '../reducers/user.reducer';
7
7
 
8
8
  import { buildQueryString } from '../search/property-search/property-search';
9
- import { objectDiff, compact } from '../utils';
9
+ import { objectDiff, compact, getOfflineSavedProperties } from '../utils';
10
10
 
11
11
  export const setCurrentUser = (payload) => ({
12
12
  type: UserActionTypes.SET_CURRENT_USER,
@@ -163,12 +163,15 @@ export const signOutUser = () => (dispatch) => (
163
163
  },
164
164
  })
165
165
  .then((response) => {
166
+ const offlineSavedProperties = getOfflineSavedProperties();
167
+
166
168
  if (response.ok) {
167
169
  dispatch(setCurrentUser(INITIAL_USER_DATA));
168
170
  dispatch(setLocalUser(INITIAL_USER_DATA));
169
171
  dispatch(setUserCredentials({ email: '', password: '' }));
170
- dispatch(setSavedProperties([]));
172
+ dispatch(setSavedProperties(offlineSavedProperties));
171
173
  dispatch(setSavedSearches([]));
174
+ Homeflow.kickEvent('user_signed_out');
172
175
  }
173
176
 
174
177
  return response.ok;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "homeflowjs",
3
- "version": "0.13.64",
3
+ "version": "0.14.0",
4
4
  "sideEffects": [
5
5
  "modal/**/*",
6
6
  "user/default-profile/**/*",
@@ -6,6 +6,7 @@ const INITIAL_STATE = {
6
6
  savedProperties: [],
7
7
  pagination: {},
8
8
  selectedMarker: null,
9
+ isPropertyDataLoading: false,
9
10
  propertyLinks: {
10
11
  next: '',
11
12
  previous: '',
@@ -54,9 +55,7 @@ const propertiesReducer = (state = INITIAL_STATE, action) => {
54
55
  if (index > -1) {
55
56
  newSavedProperties.splice(index, 1);
56
57
 
57
- if (!action.payload.userLoggedIn) {
58
- localStorage.setItem('savedProperties', JSON.stringify(newSavedProperties));
59
- }
58
+ localStorage.setItem('savedProperties', JSON.stringify(newSavedProperties));
60
59
 
61
60
  return {
62
61
  ...state,
@@ -70,9 +69,7 @@ const propertiesReducer = (state = INITIAL_STATE, action) => {
70
69
 
71
70
  newSavedProperties.push(property || state.property);
72
71
 
73
- if (!action.payload.userLoggedIn) {
74
- localStorage.setItem('savedProperties', JSON.stringify(newSavedProperties));
75
- }
72
+ localStorage.setItem('savedProperties', JSON.stringify(newSavedProperties));
76
73
 
77
74
  return {
78
75
  ...state,
@@ -90,6 +87,11 @@ const propertiesReducer = (state = INITIAL_STATE, action) => {
90
87
  geonames: action.payload,
91
88
  }
92
89
  };
90
+ case PropertiesActionTypes.SET_PROPERTY_DATA_LOADING:
91
+ return {
92
+ ...state,
93
+ isPropertyDataLoading: action.payload,
94
+ }
93
95
  default:
94
96
  return state;
95
97
  }
@@ -31,7 +31,7 @@ const server = setupServer(
31
31
  res(ctx.json({ user }))
32
32
  )),
33
33
  rest.get('/saved_properties.ljson', (req, res, ctx) => (
34
- res(ctx.json({ properties: [] }))
34
+ res(ctx.json({ properties: '' }))
35
35
  )),
36
36
  rest.get('/saved_searches.ljson', (req, res, ctx) => (
37
37
  res(ctx.json([]))
package/utils/index.js CHANGED
@@ -133,4 +133,12 @@ export const uniqueGeonamesByNameAndArea = (geonames) => {
133
133
 
134
134
  // Finally remove if they have the same area
135
135
  return [...new Map(uniqueNamesOnly.map(item => [item['area'], item])).values()]
136
- };
136
+ };
137
+
138
+ export const getOfflineSavedProperties = () => {
139
+ const offlineSavedProperties = JSON.parse(localStorage.getItem('savedProperties'));
140
+
141
+ return Array.isArray(offlineSavedProperties)
142
+ ? offlineSavedProperties
143
+ : [];
144
+ }