homeflowjs 0.9.2 → 0.9.3
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.
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import Loader from '../shared/loader.component';
|
|
4
|
+
|
|
5
|
+
const ArticlesGrid = ({
|
|
6
|
+
handleIsLoading,
|
|
7
|
+
pageSize,
|
|
8
|
+
gridClass,
|
|
9
|
+
articleItem,
|
|
10
|
+
loadMoreButtonContainerClass,
|
|
11
|
+
loadMoreButtonClass,
|
|
12
|
+
loadMoreButtonText,
|
|
13
|
+
// eslint-disable-next-line react/prop-types
|
|
14
|
+
customLoader,
|
|
15
|
+
}) => {
|
|
16
|
+
const [pagination, setPagination] = useState({});
|
|
17
|
+
const [articles, setArticles] = useState([]);
|
|
18
|
+
const [page, setPage] = useState(1);
|
|
19
|
+
const [showMore, setShowMore] = useState(true);
|
|
20
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
21
|
+
const [loadingMore, setLoadingMore] = useState(false);
|
|
22
|
+
|
|
23
|
+
const agent = `${window.location.protocol}//${window.location.host}`;
|
|
24
|
+
const path = window.location.pathname;
|
|
25
|
+
const topicPath = '/articles/topic-';
|
|
26
|
+
|
|
27
|
+
const topic = path.includes(topicPath)
|
|
28
|
+
? `&topic=${path.slice(path.indexOf(topicPath) + topicPath.length).replace('#/', '')}`
|
|
29
|
+
: '';
|
|
30
|
+
const url = `${agent}/articles.ljson?page=${page}&page_size=${pageSize}${topic}`;
|
|
31
|
+
|
|
32
|
+
const loader = () => {
|
|
33
|
+
if (customLoader) return customLoader;
|
|
34
|
+
return <Loader containerClass={loadMoreButtonContainerClass} />;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const fetchArticles = (firstRender = false) => {
|
|
38
|
+
fetch(url)
|
|
39
|
+
.then((response) => response.json())
|
|
40
|
+
.then((json) => {
|
|
41
|
+
setArticles((prev) => [...prev, ...json.articles]);
|
|
42
|
+
setPagination(json.pagination);
|
|
43
|
+
setShowMore(json.pagination.has_next_page);
|
|
44
|
+
setPage(json.pagination.current_page + 1);
|
|
45
|
+
setIsLoading(false);
|
|
46
|
+
setLoadingMore(false);
|
|
47
|
+
if (handleIsLoading && firstRender) handleIsLoading(false);
|
|
48
|
+
})
|
|
49
|
+
.catch((e) => console.log('error', e));
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const loadMore = () => {
|
|
53
|
+
if (pagination.has_next_page) {
|
|
54
|
+
setLoadingMore(true);
|
|
55
|
+
fetchArticles();
|
|
56
|
+
}
|
|
57
|
+
return false;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
if (handleIsLoading) handleIsLoading(true);
|
|
62
|
+
fetchArticles(true);
|
|
63
|
+
}, []);
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<>
|
|
67
|
+
<div className={gridClass}>
|
|
68
|
+
{articles.map((article) => articleItem(article))}
|
|
69
|
+
</div>
|
|
70
|
+
<div className={loadMoreButtonContainerClass}>
|
|
71
|
+
{(showMore && !isLoading) && (
|
|
72
|
+
<>
|
|
73
|
+
{loadingMore ? (
|
|
74
|
+
loader()
|
|
75
|
+
) : (
|
|
76
|
+
<button
|
|
77
|
+
type="button"
|
|
78
|
+
onClick={loadMore}
|
|
79
|
+
className={loadMoreButtonClass}
|
|
80
|
+
>
|
|
81
|
+
{loadMoreButtonText}
|
|
82
|
+
</button>
|
|
83
|
+
)}
|
|
84
|
+
</>
|
|
85
|
+
)}
|
|
86
|
+
</div>
|
|
87
|
+
</>
|
|
88
|
+
);
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
ArticlesGrid.propTypes = {
|
|
92
|
+
gridClass: PropTypes.string.isRequired,
|
|
93
|
+
articleItem: PropTypes.elementType.isRequired,
|
|
94
|
+
handleIsLoading: PropTypes.elementType,
|
|
95
|
+
loadMoreButtonClass: PropTypes.string,
|
|
96
|
+
loadMoreButtonText: PropTypes.string,
|
|
97
|
+
loadMoreButtonContainerClass: PropTypes.string,
|
|
98
|
+
pageSize: PropTypes.number,
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
ArticlesGrid.defaultProps = {
|
|
102
|
+
loadMoreButtonClass: '',
|
|
103
|
+
loadMoreButtonContainerClass: '',
|
|
104
|
+
loadMoreButtonText: 'Load more',
|
|
105
|
+
handleIsLoading: null,
|
|
106
|
+
pageSize: 12,
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
export default ArticlesGrid;
|
package/package.json
CHANGED
|
@@ -1,17 +1,30 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
2
3
|
|
|
3
4
|
import './loader.styles.scss';
|
|
4
5
|
|
|
5
|
-
const Loader = ({ className, message }) => (
|
|
6
|
-
<div>
|
|
7
|
-
<div className={`la-ball-beat la-dark la-2x ${className
|
|
8
|
-
<div
|
|
9
|
-
<div
|
|
10
|
-
<div
|
|
6
|
+
const Loader = ({ containerClass, className, message }) => (
|
|
7
|
+
<div className={containerClass}>
|
|
8
|
+
<div className={`la-ball-beat la-dark la-2x ${className}`}>
|
|
9
|
+
<div />
|
|
10
|
+
<div />
|
|
11
|
+
<div />
|
|
11
12
|
</div>
|
|
12
13
|
|
|
13
14
|
{message && <p style={{ marginTop: '10px' }}>{message}</p>}
|
|
14
15
|
</div>
|
|
15
16
|
);
|
|
16
17
|
|
|
18
|
+
Loader.propTypes = {
|
|
19
|
+
className: PropTypes.string,
|
|
20
|
+
message: PropTypes.string,
|
|
21
|
+
containerClass: PropTypes.string,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
Loader.defaultProps = {
|
|
25
|
+
className: '',
|
|
26
|
+
message: '',
|
|
27
|
+
containerClass: '',
|
|
28
|
+
};
|
|
29
|
+
|
|
17
30
|
export default Loader;
|