From 752b75b325d58e459125008a435dc766c2a9e1aa Mon Sep 17 00:00:00 2001 From: Ezerous Date: Fri, 26 Feb 2021 16:50:07 +0200 Subject: [PATCH] feat: add pagination to Profile TopicList --- .../src/components/CustomLoadingTabPane.jsx | 2 +- .../src/components/TopicList/index.jsx | 21 ++--- .../src/layouts/RegisterLayout/styles.css | 3 +- .../src/views/Home/HomeTopicList/index.jsx | 10 +-- .../views/Profile/ProfileTopicList/index.jsx | 89 +++++++++++++++++++ .../concordia-app/src/views/Profile/index.jsx | 13 +-- .../concordia-contracts/contracts/Forum.sol | 8 +- 7 files changed, 112 insertions(+), 34 deletions(-) create mode 100644 packages/concordia-app/src/views/Profile/ProfileTopicList/index.jsx diff --git a/packages/concordia-app/src/components/CustomLoadingTabPane.jsx b/packages/concordia-app/src/components/CustomLoadingTabPane.jsx index 1b363a8..ac48a93 100644 --- a/packages/concordia-app/src/components/CustomLoadingTabPane.jsx +++ b/packages/concordia-app/src/components/CustomLoadingTabPane.jsx @@ -40,7 +40,7 @@ const CustomLoadingTabPane = (props) => { CustomLoadingTabPane.propTypes = { loading: PropTypes.bool, loadingMessage: PropTypes.string, - children: PropTypes.element.isRequired, + children: PropTypes.element, }; export default CustomLoadingTabPane; diff --git a/packages/concordia-app/src/components/TopicList/index.jsx b/packages/concordia-app/src/components/TopicList/index.jsx index 8ebde2a..7cb9912 100644 --- a/packages/concordia-app/src/components/TopicList/index.jsx +++ b/packages/concordia-app/src/components/TopicList/index.jsx @@ -2,7 +2,6 @@ import React, { useEffect, useMemo, useState, } from 'react'; import PropTypes from 'prop-types'; -import { useSelector } from 'react-redux'; import { List } from 'semantic-ui-react'; import { FORUM_CONTRACT } from 'concordia-shared/src/constants/contracts/ContractNames'; import TopicListRow from './TopicListRow'; @@ -15,20 +14,16 @@ const { contracts: { [FORUM_CONTRACT]: { methods: { getTopic: { cacheCall: getTo const TopicList = (props) => { const { topicIds, numberOfItems, onPageChange } = props; const [getTopicCallHashes, setGetTopicCallHashes] = useState([]); - const drizzleInitialized = useSelector((state) => state.drizzleStatus.initialized); - const drizzleInitializationFailed = useSelector((state) => state.drizzleStatus.failed); useEffect(() => { - if (drizzleInitialized && !drizzleInitializationFailed) { - setGetTopicCallHashes( - topicIds - .map((topicId) => ({ - id: topicId, - hash: getTopicChainData(topicId), - })), - ); - } - }, [drizzleInitializationFailed, drizzleInitialized, topicIds]); + setGetTopicCallHashes( + topicIds + .map((topicId) => ({ + id: topicId, + hash: getTopicChainData(topicId), + })), + ); + }, [topicIds]); const topics = useMemo(() => topicIds .map((topicId) => { diff --git a/packages/concordia-app/src/layouts/RegisterLayout/styles.css b/packages/concordia-app/src/layouts/RegisterLayout/styles.css index 9892747..454bfbc 100644 --- a/packages/concordia-app/src/layouts/RegisterLayout/styles.css +++ b/packages/concordia-app/src/layouts/RegisterLayout/styles.css @@ -1,7 +1,8 @@ .particles { position: fixed; - right: 0; + top: 0; bottom: 0; + right: 0; left: 0; background: var(--secondary-color); } diff --git a/packages/concordia-app/src/views/Home/HomeTopicList/index.jsx b/packages/concordia-app/src/views/Home/HomeTopicList/index.jsx index 5db1a3c..f41bb2f 100644 --- a/packages/concordia-app/src/views/Home/HomeTopicList/index.jsx +++ b/packages/concordia-app/src/views/Home/HomeTopicList/index.jsx @@ -19,8 +19,6 @@ const { } = drizzle; const HomeTopicList = () => { - const drizzleInitialized = useSelector((state) => state.drizzleStatus.initialized); - const drizzleInitializationFailed = useSelector((state) => state.drizzleStatus.failed); const [pageNumber, setPageNumber] = useState(1); const [numTopics, setNumTopics] = useState(null); const [topicIds, setTopicIds] = useState([]); @@ -29,17 +27,17 @@ const HomeTopicList = () => { const numTopicsResult = useSelector((state) => state.contracts[FORUM_CONTRACT].numTopics[numTopicsCallHash]); useEffect(() => { - if (drizzleInitialized && !drizzleInitializationFailed && numTopicsCallHash === null) { + if (numTopicsCallHash === null) { setNumTopicsCallHash(numTopicsChainData()); } - }, [drizzleInitializationFailed, drizzleInitialized, numTopicsCallHash]); + }, [numTopicsCallHash]); useEffect(() => { - if (drizzleInitialized && !drizzleInitializationFailed && numTopics !== null) { + if (numTopics !== null) { setTopicIds(_.rangeRight(Math.max(numTopics - ITEMS_PER_PAGE * pageNumber, 0), numTopics - ITEMS_PER_PAGE * (pageNumber - 1))); } - }, [drizzleInitializationFailed, drizzleInitialized, numTopics, pageNumber]); + }, [numTopics, pageNumber]); useEffect(() => { if (numTopicsResult) { diff --git a/packages/concordia-app/src/views/Profile/ProfileTopicList/index.jsx b/packages/concordia-app/src/views/Profile/ProfileTopicList/index.jsx new file mode 100644 index 0000000..0450cc5 --- /dev/null +++ b/packages/concordia-app/src/views/Profile/ProfileTopicList/index.jsx @@ -0,0 +1,89 @@ +import React, { + useEffect, useMemo, useState, +} from 'react'; +import { useSelector } from 'react-redux'; +import { useTranslation } from 'react-i18next'; +import { FORUM_CONTRACT } from 'concordia-shared/src/constants/contracts/ContractNames'; +import { Header } from 'semantic-ui-react'; +import { drizzle } from '../../../redux/store'; +import { ITEMS_PER_PAGE } from '../../../components/PaginationComponent'; +import TopicList from '../../../components/TopicList'; + +const { + contracts: { + [FORUM_CONTRACT]: { + methods: { + getUserTopicCount: { cacheCall: getUserTopicCountChainData }, + getUserTopics: { cacheCall: getUserTopicsChainData }, + }, + }, + }, +} = drizzle; + +const ProfileTopicList = (props) => { + const { username, profileAddress } = props; + const [pageNumber, setPageNumber] = useState(1); + + const [userTopicCount, setUserTopicCount] = useState(null); + const [topicIds, setTopicIds] = useState([]); + + const [getUserTopicCountCallHash, setGetUserTopicCountCallHash] = useState(null); + const [getUserTopicsCallHash, setGetUserTopicsCallHash] = useState(null); + + const getUserTopicCountResult = useSelector((state) => state.contracts[FORUM_CONTRACT].getUserTopicCount[getUserTopicCountCallHash]); + const getUserTopicsResult = useSelector((state) => state.contracts[FORUM_CONTRACT].getUserTopics[getUserTopicsCallHash]); + + const { t } = useTranslation(); + + useEffect(() => { + if (getUserTopicCountCallHash === null) { + setGetUserTopicCountCallHash(getUserTopicCountChainData(profileAddress)); + } + }, [getUserTopicCountCallHash, profileAddress]); + + useEffect(() => { + if (userTopicCount !== null && userTopicCount !== 0) { + const startIndex = Math.max(userTopicCount - ITEMS_PER_PAGE * pageNumber, 0); + const endIndex = userTopicCount - ITEMS_PER_PAGE * (pageNumber - 1) - 1; + setGetUserTopicsCallHash(getUserTopicsChainData(profileAddress, startIndex, endIndex)); + } + }, [pageNumber, profileAddress, userTopicCount]); + + useEffect(() => { + if (getUserTopicCountResult) { + setUserTopicCount(parseInt(getUserTopicCountResult.value, 10)); + } + }, [getUserTopicCountResult, userTopicCount]); + + useEffect(() => { + if (getUserTopicsResult) { + setTopicIds(getUserTopicsResult.value.slice().reverse().map(Number)); + } + }, [getUserTopicsResult, userTopicCount]); + + const handlePageChange = (event, data) => { + setPageNumber(data.activePage); + }; + + return useMemo(() => { + if (topicIds.length && topicIds.length !== 0) { + return ( + + ); + } + if (userTopicCount === 0) { + return ( +
+ {t('profile.user.has.no.topics.header.message', { user: username })} +
+ ); + } + return null; + }, [t, topicIds, userTopicCount, username]); +}; + +export default ProfileTopicList; diff --git a/packages/concordia-app/src/views/Profile/index.jsx b/packages/concordia-app/src/views/Profile/index.jsx index 50aff6b..65090ad 100644 --- a/packages/concordia-app/src/views/Profile/index.jsx +++ b/packages/concordia-app/src/views/Profile/index.jsx @@ -8,7 +8,7 @@ import { useTranslation } from 'react-i18next'; import { FORUM_CONTRACT } from 'concordia-shared/src/constants/contracts/ContractNames'; import { drizzle } from '../../redux/store'; import CustomLoadingTabPane from '../../components/CustomLoadingTabPane'; -import TopicList from '../../components/TopicList'; +import ProfileTopicList from './ProfileTopicList'; import PostList from '../../components/PostList'; import GeneralTab from './GeneralTab'; import { GENERAL_TAB, POSTS_TAB, TOPICS_TAB } from '../../constants/ProfileTabs'; @@ -76,14 +76,9 @@ const Profile = () => { loading, profileAddress, self.address, userPostIds.length, userRegistrationTimestamp, userTopicIds.length, username, ]); - const topicsTab = useMemo(() => (userTopicIds.length > 0 - ? () - : ( -
- {t('profile.user.has.no.topics.header.message', { user: username })} -
- ) - ), [t, userTopicIds, username]); + const topicsTab = useMemo(() => ( + + ), [profileAddress, username]); const postsTab = useMemo(() => (userPostIds.length > 0 ? () diff --git a/packages/concordia-contracts/contracts/Forum.sol b/packages/concordia-contracts/contracts/Forum.sol index 1e93c46..12ab81a 100644 --- a/packages/concordia-contracts/contracts/Forum.sol +++ b/packages/concordia-contracts/contracts/Forum.sol @@ -94,14 +94,14 @@ contract Forum { return userPosts; } - function getAllUserTopics(address userAddress) public view returns (uint[] memory) { + function getUserTopicCount(address userAddress) public view returns (uint) { require(hasUserSignedUp(userAddress), USER_HAS_NOT_SIGNED_UP); - return users[userAddress].topicIDs; + return users[userAddress].topicIDs.length; } - function getAllUserPosts(address userAddress) public view returns (uint[] memory) { + function getUserPostCount(address userAddress) public view returns (uint) { require(hasUserSignedUp(userAddress), USER_HAS_NOT_SIGNED_UP); - return users[userAddress].postIDs; + return users[userAddress].postIDs.length; } function getUserDateOfRegister(address userAddress) public view returns (uint) {