homeflowjs 1.0.54 → 1.0.56

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "homeflowjs",
3
- "version": "1.0.54",
3
+ "version": "1.0.56",
4
4
  "sideEffects": [
5
5
  "modal/**/*",
6
6
  "user/default-profile/**/*",
@@ -5,52 +5,126 @@ import PropTypes from 'prop-types';
5
5
  import { loadNext } from '../../actions/properties.actions';
6
6
  import DefaultLoader from '../../shared/loader.component';
7
7
  import { addSearchToLocalStorage } from '../../app/user-history';
8
+ import { Link } from 'react-router-dom';
8
9
 
9
10
  const LoadMoreButton = (props) => {
10
11
  const dispatch = useDispatch();
11
12
  const currentSearch = useSelector((state) => state.search?.currentSearch);
12
13
  const pagination = useSelector((state) => state.properties?.pagination);
13
14
 
15
+ if (!pagination.has_next_page) return null;
16
+
14
17
  const {
18
+ isRouterLink,
15
19
  children,
16
20
  Loader,
21
+ isHidden,
17
22
  ...otherProps
18
23
  } = props;
19
24
 
20
25
  const [loading, setLoading] = useState(false);
26
+ const [targetURL, setTargetURL] = useState(window.location.href);
21
27
 
22
- if (!pagination.has_next_page) return null;
28
+ // Updating the url for the link to follow the next page,
29
+ // replacing the page with current page with the next page value
30
+ // to avoid duplicated pages in url pattern such as page-2/page-3.
31
+ const updatePageLink = (url) => {
32
+ if (url.includes('page-')) {
33
+ return url.replace(/page-\d+/, `page-${pagination.current_page + 1}`);
34
+ } else {
35
+ // Fix for the page-2 when the url does not have a value for page-1
36
+ return url + (url.endsWith('/') ? '' : '/') + `page-${pagination.current_page + 1}`;
37
+ }
38
+ }
39
+
40
+ const handleClick = (e) => {
41
+ e.preventDefault();
42
+ e.stopPropagation();
43
+ e.currentTarget.blur();
44
+ setLoading(true);
45
+ dispatch(loadNext())
46
+ .then(() => {
47
+ setLoading(false);
48
+ const pageNumber = currentSearch?.page ? currentSearch?.page + 1 : 2;
49
+ const searchToLocal = { ...currentSearch, page: pageNumber };
50
+ addSearchToLocalStorage(searchToLocal);
51
+ })
52
+ .then(() => {
53
+ // Add set timeout, waiting target url to set location.href.
54
+ // By doing that we avoid links have wrong page numbers
55
+ // e.g. when you are on page-2, the url updates first and then change it for following page
56
+ setTimeout(() => {
57
+ setTargetURL(window.location.href);
58
+ }, 200);
59
+ })
60
+ return false;
61
+ }
62
+
63
+ {/* Load More Button component uses Link from react-router-dom to avoid navigating pages for themes using the component inside a react router wrapper. */}
64
+ const RouterLinkComponent = () => {
65
+ return (
66
+ <Link
67
+ onClick={(e) => handleClick(e)}
68
+ to={{ pathname: `page-${pagination.current_page + 1}` }}
69
+ {...otherProps}
70
+ >
71
+ {children}
72
+ </Link>
73
+ )
74
+ }
75
+
76
+ const LinkComponent = () => {
77
+ return (
78
+ <a
79
+ onClick={(e) => handleClick(e)}
80
+ href={updatePageLink(targetURL)}
81
+ {...otherProps}
82
+ >
83
+ {children}
84
+ </a>
85
+ )
86
+ };
87
+
88
+ {/* Hidden link for themes using InfiniteScroll: allows Googlebot to discover the Next page link for indexing, while users trigger infinite scroll without actual navigation. */}
89
+ const HiddenLinkComponent = () => {
90
+ return (
91
+ <a
92
+ style={{ display: 'none' }}
93
+ href={updatePageLink(targetURL)}
94
+ >
95
+ Next
96
+ </a>
97
+ );
98
+ };
99
+
100
+ const renderComponent = () => {
101
+ if (loading) return <Loader height="24px" />;
102
+
103
+ if (isHidden) {
104
+ return <HiddenLinkComponent />;
105
+ }
106
+
107
+ if (isRouterLink) {
108
+ return <RouterLinkComponent />;
109
+ }
110
+
111
+ return <LinkComponent />;
112
+ };
23
113
 
24
- if (loading) return <Loader height="24px" />;
25
-
26
- return (
27
- <button
28
- type="button"
29
- onClick={(e) => {
30
- e.currentTarget.blur();
31
- setLoading(true);
32
- dispatch(loadNext())
33
- .then(() => {
34
- setLoading(false);
35
- const pageNumber = currentSearch?.page ? currentSearch?.page + 1 : 2;
36
- const searchToLocal = {...currentSearch, page: pageNumber };
37
- addSearchToLocalStorage(searchToLocal);
38
- });
39
- }}
40
- {...otherProps}
41
- >
42
- {children}
43
- </button>
44
- );
114
+ return renderComponent();
45
115
  };
46
116
 
47
117
  LoadMoreButton.propTypes = {
48
118
  children: PropTypes.node.isRequired,
49
119
  Loader: PropTypes.elementType,
120
+ isHidden: PropTypes.bool,
121
+ isRouterLink: PropTypes.bool,
50
122
  };
51
123
 
52
124
  LoadMoreButton.defaultProps = {
53
125
  Loader: DefaultLoader,
126
+ isHidden: false,
127
+ isRouterLink: false,
54
128
  };
55
129
 
56
130
  export default LoadMoreButton;
@@ -22,6 +22,15 @@ const PropertiesDisplay = ({
22
22
  ...other
23
23
  }) => {
24
24
  if (!properties?.length) {
25
+ if (inserts.length > 0) {
26
+ return (
27
+ <>
28
+ {noResultsMessage}
29
+ {inserts[0]?.component}
30
+ </>
31
+ );
32
+ }
33
+
25
34
  return noResultsMessage;
26
35
  }
27
36
 
@@ -73,25 +82,22 @@ const PropertiesDisplay = ({
73
82
  && loadingNextProperties;
74
83
 
75
84
  const insertsAvailable = Array.isArray(inserts) && inserts.length > 0;
76
- const insertsFrequency =
77
- insertsAvailable && inserts[0]?.frequency > 0 ? inserts[0].frequency : null;
78
-
85
+ const insertsFrequency = insertsAvailable && inserts[0]?.frequency > 0
86
+ ? inserts[0].frequency
87
+ : null;
88
+
79
89
  const { propertiesInsertsMap, insertablePropertiesIDList } = useMemo(() => {
80
90
  const propertiesLength = properties.length;
81
- const validInserts = insertsAvailable
82
- ? inserts.filter(({ index }) => index >= 0 && index < propertiesLength)
83
- : null;
84
- if (validInserts) {
85
- const propertiesInsertsMap = new Map();
86
- for (const insert of validInserts) {
87
- const property = properties[insert.index];
88
- propertiesInsertsMap.set(property.property_id, insert);
89
- };
90
- const insertablePropertiesIDList = Array.from(propertiesInsertsMap.keys());
91
-
92
- return { propertiesInsertsMap, insertablePropertiesIDList };
93
- }
94
- return {};
91
+ const propertiesInsertsMap = new Map();
92
+
93
+ inserts.forEach((insert) => {
94
+ const property = properties[insert.index - 1] || properties[propertiesLength - 1];
95
+ propertiesInsertsMap.set(property.property_id, insert);
96
+ });
97
+
98
+ const insertablePropertiesIDList = Array.from(propertiesInsertsMap.keys());
99
+
100
+ return { propertiesInsertsMap, insertablePropertiesIDList };
95
101
  }, [properties]);
96
102
 
97
103
  const handleListElementClick = (id = null) => {
@@ -140,8 +146,8 @@ const PropertiesDisplay = ({
140
146
  if (findResult) {
141
147
  return (
142
148
  <React.Fragment key={property.property_id}>
143
- {findResult.component}
144
149
  <Item property={property} onClick={() => visitPropertyUpdate(property.property_id)} {...other} />
150
+ {findResult.component}
145
151
  </React.Fragment>
146
152
  );
147
153
  }
@@ -199,7 +205,7 @@ PropertiesDisplay.propTypes = {
199
205
  };
200
206
 
201
207
  PropertiesDisplay.defaultProps = {
202
- inserts: null,
208
+ inserts: [],
203
209
  InfiniteScrollLoader: null,
204
210
  includePreviousBtn: false,
205
211
  noResultsMessage: <p>There were no properties matching your search.</p>,
@@ -120,7 +120,7 @@ PropertyResults.defaultProps = {
120
120
  infiniteScroll: false,
121
121
  infiniteScrollLoader: null,
122
122
  noMap: false,
123
- inserts: null,
123
+ inserts: [],
124
124
  };
125
125
 
126
126
  export default PropertyResults;