Browse Source

feat: add pagination to Profile TopicList

develop
Ezerous 4 years ago
parent
commit
752b75b325
  1. 2
      packages/concordia-app/src/components/CustomLoadingTabPane.jsx
  2. 7
      packages/concordia-app/src/components/TopicList/index.jsx
  3. 3
      packages/concordia-app/src/layouts/RegisterLayout/styles.css
  4. 10
      packages/concordia-app/src/views/Home/HomeTopicList/index.jsx
  5. 89
      packages/concordia-app/src/views/Profile/ProfileTopicList/index.jsx
  6. 13
      packages/concordia-app/src/views/Profile/index.jsx
  7. 8
      packages/concordia-contracts/contracts/Forum.sol

2
packages/concordia-app/src/components/CustomLoadingTabPane.jsx

@ -40,7 +40,7 @@ const CustomLoadingTabPane = (props) => {
CustomLoadingTabPane.propTypes = { CustomLoadingTabPane.propTypes = {
loading: PropTypes.bool, loading: PropTypes.bool,
loadingMessage: PropTypes.string, loadingMessage: PropTypes.string,
children: PropTypes.element.isRequired, children: PropTypes.element,
}; };
export default CustomLoadingTabPane; export default CustomLoadingTabPane;

7
packages/concordia-app/src/components/TopicList/index.jsx

@ -2,7 +2,6 @@ import React, {
useEffect, useMemo, useState, useEffect, useMemo, useState,
} from 'react'; } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { useSelector } from 'react-redux';
import { List } from 'semantic-ui-react'; import { List } from 'semantic-ui-react';
import { FORUM_CONTRACT } from 'concordia-shared/src/constants/contracts/ContractNames'; import { FORUM_CONTRACT } from 'concordia-shared/src/constants/contracts/ContractNames';
import TopicListRow from './TopicListRow'; import TopicListRow from './TopicListRow';
@ -15,11 +14,8 @@ const { contracts: { [FORUM_CONTRACT]: { methods: { getTopic: { cacheCall: getTo
const TopicList = (props) => { const TopicList = (props) => {
const { topicIds, numberOfItems, onPageChange } = props; const { topicIds, numberOfItems, onPageChange } = props;
const [getTopicCallHashes, setGetTopicCallHashes] = useState([]); const [getTopicCallHashes, setGetTopicCallHashes] = useState([]);
const drizzleInitialized = useSelector((state) => state.drizzleStatus.initialized);
const drizzleInitializationFailed = useSelector((state) => state.drizzleStatus.failed);
useEffect(() => { useEffect(() => {
if (drizzleInitialized && !drizzleInitializationFailed) {
setGetTopicCallHashes( setGetTopicCallHashes(
topicIds topicIds
.map((topicId) => ({ .map((topicId) => ({
@ -27,8 +23,7 @@ const TopicList = (props) => {
hash: getTopicChainData(topicId), hash: getTopicChainData(topicId),
})), })),
); );
} }, [topicIds]);
}, [drizzleInitializationFailed, drizzleInitialized, topicIds]);
const topics = useMemo(() => topicIds const topics = useMemo(() => topicIds
.map((topicId) => { .map((topicId) => {

3
packages/concordia-app/src/layouts/RegisterLayout/styles.css

@ -1,7 +1,8 @@
.particles { .particles {
position: fixed; position: fixed;
right: 0; top: 0;
bottom: 0; bottom: 0;
right: 0;
left: 0; left: 0;
background: var(--secondary-color); background: var(--secondary-color);
} }

10
packages/concordia-app/src/views/Home/HomeTopicList/index.jsx

@ -19,8 +19,6 @@ const {
} = drizzle; } = drizzle;
const HomeTopicList = () => { const HomeTopicList = () => {
const drizzleInitialized = useSelector((state) => state.drizzleStatus.initialized);
const drizzleInitializationFailed = useSelector((state) => state.drizzleStatus.failed);
const [pageNumber, setPageNumber] = useState(1); const [pageNumber, setPageNumber] = useState(1);
const [numTopics, setNumTopics] = useState(null); const [numTopics, setNumTopics] = useState(null);
const [topicIds, setTopicIds] = useState([]); const [topicIds, setTopicIds] = useState([]);
@ -29,17 +27,17 @@ const HomeTopicList = () => {
const numTopicsResult = useSelector((state) => state.contracts[FORUM_CONTRACT].numTopics[numTopicsCallHash]); const numTopicsResult = useSelector((state) => state.contracts[FORUM_CONTRACT].numTopics[numTopicsCallHash]);
useEffect(() => { useEffect(() => {
if (drizzleInitialized && !drizzleInitializationFailed && numTopicsCallHash === null) { if (numTopicsCallHash === null) {
setNumTopicsCallHash(numTopicsChainData()); setNumTopicsCallHash(numTopicsChainData());
} }
}, [drizzleInitializationFailed, drizzleInitialized, numTopicsCallHash]); }, [numTopicsCallHash]);
useEffect(() => { useEffect(() => {
if (drizzleInitialized && !drizzleInitializationFailed && numTopics !== null) { if (numTopics !== null) {
setTopicIds(_.rangeRight(Math.max(numTopics - ITEMS_PER_PAGE * pageNumber, 0), setTopicIds(_.rangeRight(Math.max(numTopics - ITEMS_PER_PAGE * pageNumber, 0),
numTopics - ITEMS_PER_PAGE * (pageNumber - 1))); numTopics - ITEMS_PER_PAGE * (pageNumber - 1)));
} }
}, [drizzleInitializationFailed, drizzleInitialized, numTopics, pageNumber]); }, [numTopics, pageNumber]);
useEffect(() => { useEffect(() => {
if (numTopicsResult) { if (numTopicsResult) {

89
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 (
<TopicList
topicIds={topicIds}
numberOfItems={userTopicCount}
onPageChange={handlePageChange}
/>
);
}
if (userTopicCount === 0) {
return (
<Header textAlign="center" as="h2">
{t('profile.user.has.no.topics.header.message', { user: username })}
</Header>
);
}
return null;
}, [t, topicIds, userTopicCount, username]);
};
export default ProfileTopicList;

13
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 { FORUM_CONTRACT } from 'concordia-shared/src/constants/contracts/ContractNames';
import { drizzle } from '../../redux/store'; import { drizzle } from '../../redux/store';
import CustomLoadingTabPane from '../../components/CustomLoadingTabPane'; import CustomLoadingTabPane from '../../components/CustomLoadingTabPane';
import TopicList from '../../components/TopicList'; import ProfileTopicList from './ProfileTopicList';
import PostList from '../../components/PostList'; import PostList from '../../components/PostList';
import GeneralTab from './GeneralTab'; import GeneralTab from './GeneralTab';
import { GENERAL_TAB, POSTS_TAB, TOPICS_TAB } from '../../constants/ProfileTabs'; 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, loading, profileAddress, self.address, userPostIds.length, userRegistrationTimestamp, userTopicIds.length, username,
]); ]);
const topicsTab = useMemo(() => (userTopicIds.length > 0 const topicsTab = useMemo(() => (
? (<TopicList topicIds={userTopicIds} />) <ProfileTopicList username={username} profileAddress={profileAddress} />
: ( ), [profileAddress, username]);
<Header textAlign="center" as="h2">
{t('profile.user.has.no.topics.header.message', { user: username })}
</Header>
)
), [t, userTopicIds, username]);
const postsTab = useMemo(() => (userPostIds.length > 0 const postsTab = useMemo(() => (userPostIds.length > 0
? (<PostList postIds={userPostIds} />) ? (<PostList postIds={userPostIds} />)

8
packages/concordia-contracts/contracts/Forum.sol

@ -94,14 +94,14 @@ contract Forum {
return userPosts; 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); 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); 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) { function getUserDateOfRegister(address userAddress) public view returns (uint) {

Loading…
Cancel
Save