From b93ca37b8616c261bc7526cc061167445bd2113b Mon Sep 17 00:00:00 2001 From: Ezerous Date: Sat, 27 Feb 2021 20:03:04 +0200 Subject: [PATCH] feat: add pagination to topic's posts --- .../src/components/PostList/index.jsx | 10 ++- .../Topic/TopicView/TopicPostList/index.jsx | 82 +++++++++++++++++++ .../src/views/Topic/TopicView/index.jsx | 12 +-- .../src/views/Topic/TopicView/styles.css | 1 + .../concordia-contracts/contracts/Forum.sol | 17 +++- 5 files changed, 108 insertions(+), 14 deletions(-) create mode 100644 packages/concordia-app/src/views/Topic/TopicView/TopicPostList/index.jsx diff --git a/packages/concordia-app/src/components/PostList/index.jsx b/packages/concordia-app/src/components/PostList/index.jsx index 9b118c3..c42a8c6 100644 --- a/packages/concordia-app/src/components/PostList/index.jsx +++ b/packages/concordia-app/src/components/PostList/index.jsx @@ -51,11 +51,13 @@ const PostList = (props) => { }, [focusOnPost, getPostCallHashes, loading, postIds]); return ( - - - {posts} + <> + + + {posts} + - + ); }; diff --git a/packages/concordia-app/src/views/Topic/TopicView/TopicPostList/index.jsx b/packages/concordia-app/src/views/Topic/TopicView/TopicPostList/index.jsx new file mode 100644 index 0000000..1b5a771 --- /dev/null +++ b/packages/concordia-app/src/views/Topic/TopicView/TopicPostList/index.jsx @@ -0,0 +1,82 @@ +import React, { + useEffect, useMemo, useState, +} from 'react'; +import { useSelector } from 'react-redux'; +import { FORUM_CONTRACT } from 'concordia-shared/src/constants/contracts/ContractNames'; +import PostList from '../../../../components/PostList'; +import { ITEMS_PER_PAGE } from '../../../../components/PaginationComponent'; +import { drizzle } from '../../../../redux/store'; + +const { + contracts: { + [FORUM_CONTRACT]: { + methods: { + getTopicPostCount: { cacheCall: getTopicPostCountChainData }, + getTopicPosts: { cacheCall: getTopicPostsChainData }, + }, + }, + }, +} = drizzle; + +const TopicPostList = (props) => { + const { + topicId, loading, focusOnPost, + } = props; + const [pageNumber, setPageNumber] = useState(1); + + const [topicPostCount, setTopicPostCount] = useState(null); + const [postIds, setPostIds] = useState([]); + + const [getTopicPostCountCallHash, setGetTopicPostCountCallHash] = useState(null); + const [getTopicPostsCallHash, setGetTopicPostsCallHash] = useState(null); + + const getTopicPostCountResult = useSelector((state) => state.contracts[FORUM_CONTRACT].getTopicPostCount[getTopicPostCountCallHash]); + const getTopicPostsResult = useSelector((state) => state.contracts[FORUM_CONTRACT].getTopicPosts[getTopicPostsCallHash]); + + useEffect(() => { + if (getTopicPostCountCallHash === null) { + setGetTopicPostCountCallHash(getTopicPostCountChainData(topicId)); + } + }, [getTopicPostCountCallHash, topicId]); + + useEffect(() => { + if (topicPostCount !== null && topicPostCount !== 0) { + const startIndex = Math.max(topicPostCount - ITEMS_PER_PAGE * pageNumber, 0); + const endIndex = topicPostCount - ITEMS_PER_PAGE * (pageNumber - 1) - 1; + setGetTopicPostsCallHash(getTopicPostsChainData(topicId, startIndex, endIndex)); + } + }, [pageNumber, topicId, topicPostCount]); + + useEffect(() => { + if (getTopicPostCountResult) { + setTopicPostCount(parseInt(getTopicPostCountResult.value, 10)); + } + }, [getTopicPostCountResult, topicPostCount]); + + useEffect(() => { + if (getTopicPostsResult) { + setPostIds(getTopicPostsResult.value.slice().reverse().map(Number)); + } + }, [getTopicPostsResult, topicPostCount]); + + const handlePageChange = (event, data) => { + setPageNumber(data.activePage); + }; + + return useMemo(() => { + if (postIds.length && postIds.length !== 0) { + return ( + + ); + } + return null; + }, [postIds, topicPostCount, loading, focusOnPost]); +}; + +export default TopicPostList; diff --git a/packages/concordia-app/src/views/Topic/TopicView/index.jsx b/packages/concordia-app/src/views/Topic/TopicView/index.jsx index f77715a..a602db3 100644 --- a/packages/concordia-app/src/views/Topic/TopicView/index.jsx +++ b/packages/concordia-app/src/views/Topic/TopicView/index.jsx @@ -11,7 +11,7 @@ import { TOPICS_DATABASE, USER_DATABASE } from 'concordia-shared/src/constants/o import { breeze, drizzle } from '../../../redux/store'; import { FETCH_USER_DATABASE } from '../../../redux/actions/peerDbReplicationActions'; import './styles.css'; -import PostList from '../../../components/PostList'; +import TopicPostList from './TopicPostList'; import determineKVAddress from '../../../utils/orbitUtils'; import { TOPIC_SUBJECT } from '../../../constants/orbit/TopicsDatabaseKeys'; import PostCreate from '../../../components/PostCreate'; @@ -24,8 +24,6 @@ const TopicView = (props) => { topicId, topicAuthorAddress: initialTopicAuthorAddress, topicAuthor: initialTopicAuthor, timestamp: initialTimestamp, postIds: initialPostIds, focusOnPost, } = props; - const drizzleInitialized = useSelector((state) => state.drizzleStatus.initialized); - const drizzleInitializationFailed = useSelector((state) => state.drizzleStatus.failed); const userAddress = useSelector((state) => state.user.address); const hasSignedUp = useSelector((state) => state.user.hasSignedUp); const getTopicResults = useSelector((state) => state.contracts[FORUM_CONTRACT].getTopic); @@ -47,12 +45,10 @@ const TopicView = (props) => { || timestamp === null || postIds === null; - if (drizzleInitialized && !drizzleInitializationFailed && shouldGetTopicDataFromChain) { + if (shouldGetTopicDataFromChain) { setGetTopicCallHash(getTopicChainData(topicId)); } - }, [ - drizzleInitializationFailed, drizzleInitialized, postIds, timestamp, topicAuthor, topicAuthorAddress, topicId, - ]); + }, [postIds, timestamp, topicAuthor, topicAuthorAddress, topicId]); useEffect(() => { if (getTopicCallHash && getTopicResults && getTopicResults[getTopicCallHash]) { @@ -149,7 +145,7 @@ const TopicView = (props) => { - + {topicSubject !== null && postIds !== null && hasSignedUp && ( diff --git a/packages/concordia-app/src/views/Topic/TopicView/styles.css b/packages/concordia-app/src/views/Topic/TopicView/styles.css index bea6ab3..2b3a8d0 100644 --- a/packages/concordia-app/src/views/Topic/TopicView/styles.css +++ b/packages/concordia-app/src/views/Topic/TopicView/styles.css @@ -1,5 +1,6 @@ #topic-container { height: auto !important; + text-align: center; } #topic-header { diff --git a/packages/concordia-contracts/contracts/Forum.sol b/packages/concordia-contracts/contracts/Forum.sol index 12ab81a..7f04d33 100644 --- a/packages/concordia-contracts/contracts/Forum.sol +++ b/packages/concordia-contracts/contracts/Forum.sol @@ -188,9 +188,22 @@ contract Forum { ); } - function getTopicPosts(uint topicID) public view returns (uint[] memory) { + function getTopicPostCount(uint topicID) public view returns (uint) { require(topicExists(topicID), TOPIC_DOES_NOT_EXIST); - return topics[topicID].postIDs; + return topics[topicID].postIDs.length; + } + + function getTopicPosts(uint topicID, uint startIndex, uint endIndex) public view returns (uint[] memory) { + require(topicExists(topicID), TOPIC_DOES_NOT_EXIST); + require(startIndex <= endIndex && topics[topicID].postIDs.length > endIndex, INVALID_RANGE); + uint length = endIndex - startIndex + 1; + uint[] memory topicPosts = new uint[](length); + uint counter = 0; + for (uint i = startIndex; i <= endIndex; i++) { + topicPosts[counter] = topics[topicID].postIDs[i]; + counter++; + } + return topicPosts; } function getTopicAuthor(uint topicID) public view returns (address) {