Browse Source

Fixes for propTypes, Minro UI improvements

develop
Apostolos Fanakis 6 years ago
parent
commit
9d481fc162
  1. 28
      app/src/CustomPropTypes.js
  2. 164
      app/src/containers/PlaceholderContainer.js
  3. 88
      app/src/containers/Post.js
  4. 44
      app/src/containers/PostList.js
  5. 6
      app/src/containers/ProfileContainer.js
  6. 106
      app/src/containers/ProfileInformation.js
  7. 5
      app/src/containers/Topic.js
  8. 2
      app/src/containers/TopicContainer.js
  9. 8
      app/src/containers/TopicList.js
  10. 4
      app/src/containers/UsernameFormContainer.js

28
app/src/CustomPropTypes.js

@ -2,11 +2,27 @@ import PropTypes from 'prop-types';
//TODO: Move this file
const GetTopicResult = PropTypes.PropTypes.shape({
0: PropTypes.string,
1: PropTypes.string,
2: PropTypes.string,
3: PropTypes.string,
4: PropTypes.arrayOf(PropTypes.number)
userAddress: PropTypes.string.isRequired,
fullOrbitAddress: PropTypes.string.isRequired,
userName: PropTypes.string.isRequired,
timestamp: PropTypes.number.isRequired,
numberOfReplies: PropTypes.number.isRequired
});
export { GetTopicResult };
const GetPostResult = PropTypes.PropTypes.shape({
userAddress: PropTypes.string.isRequired,
fullOrbitAddress: PropTypes.string.isRequired,
userName: PropTypes.string.isRequired,
timestamp: PropTypes.number.isRequired,
topicID: PropTypes.string.isRequired
});
const TopicPlaceholderExtra = PropTypes.PropTypes.shape({
topicID: PropTypes.number.isRequired,
});
const PostPlaceholderExtra = PropTypes.PropTypes.shape({
postIndex: PropTypes.number.isRequired,
});
export { GetTopicResult, GetPostResult, TopicPlaceholderExtra, PostPlaceholderExtra };

164
app/src/containers/PlaceholderContainer.js

@ -0,0 +1,164 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { withRouter } from 'react-router-dom';
import { TopicPlaceholderExtra, PostPlaceholderExtra } from '../CustomPropTypes'
import ContentLoader from 'react-content-loader';
import { Card, Button, Divider, Grid, Icon, Label } from 'semantic-ui-react';
class PlaceholderContainer extends Component {
render() {
const { placeholderType, extra, history } = this.props;
switch (placeholderType) {
case 'Topic':
return(
<Card
link
className="card"
onClick={() => {
history.push(`/topic/${extra.topicID}`);
}}
>
<Card.Content>
<div>
<ContentLoader
height={5.8}
width={300}
speed={2}
primaryColor="#b2e8e6"
secondaryColor="#00b5ad"
>
<rect x="0" y="0" rx="3" ry="3" width="150" height="5.5" />
</ContentLoader>
</div>
<hr />
<div className="topic-meta">
<p className="no-margin">
<ContentLoader
height={5.8}
width={300}
speed={2}
primaryColor="#b2e8e6"
secondaryColor="#00b5ad"
>
<rect x="0" y="0" rx="3" ry="3" width="60" height="5.5" />
</ContentLoader>
</p>
<p className="no-margin">
<ContentLoader
height={5.8}
width={300}
speed={2}
primaryColor="#b2e8e6"
secondaryColor="#00b5ad"
>
<rect x="0" y="0" rx="3" ry="3" width="70" height="5.5" />
</ContentLoader>
</p>
<p className="topic-date grey-text">
<ContentLoader
height={5.8}
width={300}
speed={2}
primaryColor="#b2e8e6"
secondaryColor="#00b5ad"
>
<rect x="260" y="0" rx="3" ry="3" width="40" height="5.5" />
</ContentLoader>
</p>
</div>
</Card.Content>
</Card>
);
case 'Post':
return(
<div className="post">
<Divider horizontal>
<span className="grey-text">
#
{extra.postIndex}
</span>
</Divider>
<Grid>
<Grid.Row columns={16} stretched>
<Grid.Column width={1} className="user-avatar">
<div className="user-avatar">
<ContentLoader
height={52}
width={52}
speed={2}
primaryColor="#b2e8e6"
secondaryColor="#00b5ad"
>
<circle cx="26" cy="26" r="26" />
</ContentLoader>
</div>
</Grid.Column>
<Grid.Column width={15}>
<div className="">
<div className="stretch-space-between">
<span className='grey-text'>
<strong>Username</strong>
</span>
<span className="grey-text">
<ContentLoader height={5.8} width={300} speed={2} primaryColor="#b2e8e6"
secondaryColor="#00b5ad" >
<rect x="280" y="0" rx="3" ry="3" width="20" height="5.5" />
</ContentLoader>
</span>
</div>
<div className="stretch-space-between">
<span className='grey-text' >
<strong>
<ContentLoader height={5.8} width={300} speed={2} primaryColor="#b2e8e6"
secondaryColor="#00b5ad" >
<rect x="0" y="0" rx="3" ry="3" width="75" height="5.5" />
</ContentLoader>
</strong>
</span>
</div>
<div className="post-content">
<ContentLoader height={11.2} width={300} speed={2}
primaryColor="#b2e8e6" secondaryColor="#00b5ad" >
<rect x="0" y="0" rx="3" ry="3" width="180" height="4.0" />
<rect x="0" y="6.5" rx="3" ry="3" width="140" height="4.0" />
</ContentLoader>
</div>
</div>
</Grid.Column>
</Grid.Row>
<Grid.Row>
<Grid.Column floated="right" textAlign="right">
<Button icon size="mini" disabled
style={{
marginRight: '0px'
}}
>
<Icon name="chevron up" />
</Button>
<Label color="teal">Loading...</Label>
<Button icon size="mini" disabled >
<Icon name="chevron down" />
</Button>
<Button icon size="mini" disabled >
<Icon name="linkify" />
</Button>
</Grid.Column>
</Grid.Row>
</Grid>
</div>
);
}
}
}
PlaceholderContainer.propTypes = {
placeholderType: PropTypes.string.isRequired,
extra: PropTypes.oneOfType([
TopicPlaceholderExtra.isRequired,
PostPlaceholderExtra.isRequired
])
};
export default withRouter(PlaceholderContainer);

88
app/src/containers/Post.js

@ -4,6 +4,7 @@ import { bindActionCreators } from 'redux';
import { push } from 'connected-react-router';
import { Link, withRouter } from 'react-router-dom';
import { connect } from 'react-redux';
import { GetPostResult } from '../CustomPropTypes'
import ContentLoader from 'react-content-loader';
import { Button, Divider, Grid, Icon, Label, Transition } from 'semantic-ui-react';
@ -65,7 +66,7 @@ class Post extends Component {
const { fetchPostDataStatus } = this.state;
const { postData, orbitDB, postID } = this.props;
if (postData && orbitDB.orbitdb && fetchPostDataStatus === 'pending') {
if (orbitDB.orbitdb && fetchPostDataStatus === 'pending') {
this.setState({
fetchPostDataStatus: 'fetching'
});
@ -77,10 +78,10 @@ class Post extends Component {
const { address, postData, orbitDB } = this.props;
let orbitPostData;
if (postData.value[1] === address) {
if (postData.userAddress === address) {
orbitPostData = orbitDB.postsDB.get(postID);
} else {
const fullAddress = `/orbitdb/${postData.value[0]}/posts`;
const fullAddress = `/orbitdb/${postData.fullOrbitAddress}/posts`;
const store = await orbitDB.orbitdb.keyvalue(fullAddress);
await store.load();
@ -107,30 +108,6 @@ class Post extends Component {
const { animateOnToggle, postSubject, postContent } = this.state;
const { avatarUrl, postIndex, navigateTo, postData, postID } = this.props;
const avatarView = (postData
? (
<UserAvatar
size="52"
className="inline"
src={avatarUrl}
name={postData.value[2]}
/>
)
: (
<div className="user-avatar">
<ContentLoader
height={52}
width={52}
speed={2}
primaryColor="#b2e8e6"
secondaryColor="#00b5ad"
>
<circle cx="26" cy="26" r="26" />
</ContentLoader>
</div>
)
);
return (
<Transition
animation="tada"
@ -147,48 +124,31 @@ class Post extends Component {
<Grid>
<Grid.Row columns={16} stretched>
<Grid.Column width={1} className="user-avatar">
{postData !== null
? (
<Link
to={`/profile/${postData.value[1]
}/${postData.value[2]}`}
onClick={(event) => { event.stopPropagation(); }}
>
{avatarView}
</Link>
)
: avatarView
}
<Link
to={`/profile/${postData.userAddress}/${postData.userName}`}
onClick={(event) => { event.stopPropagation(); }} >
<UserAvatar
size="52"
className="inline"
src={avatarUrl}
name={postData.userName}
/>
</Link>
</Grid.Column>
<Grid.Column width={15}>
<div className="">
<div className="stretch-space-between">
<span className={postData
!== null ? '' : 'grey-text'}
>
<span>
<strong>
{postData !== null
? postData.value[2]
: 'Username'
}
{postData.userName}
</strong>
</span>
<span className="grey-text">
{postData !== null
&& (
<TimeAgo date={
postData.value[3]*1000
}
/>
)
}
<TimeAgo date={postData.timestamp} />
</span>
</div>
<div className="stretch-space-between">
<span
className={postSubject
=== '' ? '' : 'grey-text'}
>
<span>
<strong>
{postSubject === ''
? (
@ -209,9 +169,8 @@ class Post extends Component {
/>
</ContentLoader>
)
: `Subject: ${
postSubject}`
}
: `Subject: ${postSubject}`
}
</strong>
</span>
</div>
@ -243,8 +202,7 @@ class Post extends Component {
height="4.0"
/>
</ContentLoader>
)
}
)}
</div>
</div>
</Grid.Column>
@ -270,7 +228,7 @@ class Post extends Component {
onClick={postData
? () => {
navigateTo(`/topic/${
postData.value[4]}/${
postData.topicID}/${
postID}`);
}
: () => {}}
@ -293,7 +251,7 @@ Post.propTypes = {
avatarUrl: PropTypes.string,
postIndex: PropTypes.number.isRequired,
navigateTo: PropTypes.func.isRequired,
postData: PropTypes.object,
postData: GetPostResult.isRequired,
postID: PropTypes.string.isRequired
};

44
app/src/containers/PostList.js

@ -4,6 +4,7 @@ import { connect } from 'react-redux';
import { drizzle } from '../index';
import Post from './Post';
import PlaceholderContainer from './PlaceholderContainer';
const contract = 'Forum';
const getPostMethod = 'getPost';
@ -56,19 +57,34 @@ class PostList extends Component {
const { dataKeys } = this.state;
const { postIDs, contracts, focusOnPost, recentToTheTop } = this.props;
const posts = postIDs.map((postID, index) => (
<Post
postData={(dataKeys[postID]
&& contracts[contract][getPostMethod][dataKeys[postID]])
? contracts[contract][getPostMethod][dataKeys[postID]]
: null}
avatarUrl=""
postIndex={index}
postID={postID}
getFocus={focusOnPost === postID}
key={postID}
/>
));
const posts = postIDs.map((postID, index) => {
let fetchedPostData;
if(dataKeys[postID])
fetchedPostData = contracts[contract][getPostMethod][dataKeys[postID]];
if(fetchedPostData) {
const postData = {
userAddress: fetchedPostData.value[1],
fullOrbitAddress: `/orbitdb/${fetchedPostData.value[0]}/posts`,
userName: fetchedPostData.value[2],
timestamp: fetchedPostData.value[3]*1000,
topicID: fetchedPostData.value[4]
};
return(
<Post
postData={postData}
avatarUrl=""
postIndex={index}
postID={postID}
getFocus={focusOnPost === postID}
key={postID}
/>
)
}
return (<PlaceholderContainer placeholderType='Post'
extra={{postIndex: index}} key={postID} />);
});
return (
<div>
@ -84,7 +100,7 @@ class PostList extends Component {
PostList.propTypes = {
drizzleStatus: PropTypes.object.isRequired,
postIDs: PropTypes.array.isRequired,
contracts: PropTypes.array.isRequired,
contracts: PropTypes.PropTypes.objectOf(PropTypes.object).isRequired,
focusOnPost: PropTypes.number,
recentToTheTop: PropTypes.bool
};

6
app/src/containers/ProfileContainer.js

@ -136,8 +136,8 @@ class ProfileContainer extends Component {
<ProfileInformation
address={userAddress}
username={username}
numberOfTopics={topicIDs && topicIDs.length}
numberOfPosts={postIDs && postIDs.length}
numberOfTopics={topicIDs ? topicIDs.length : -1}
numberOfPosts={postIDs ? postIDs.length : -1}
self={userAddress === user.address}
key="profileInfo"
/>
@ -200,7 +200,7 @@ class ProfileContainer extends Component {
ProfileContainer.propTypes = {
match: PropTypes.object.isRequired,
drizzleStatus: PropTypes.object.isRequired,
contracts: PropTypes.array.isRequired,
contracts: PropTypes.PropTypes.objectOf(PropTypes.object).isRequired,
navigateTo: PropTypes.func.isRequired,
user: PropTypes.object.isRequired,
setNavBarTitle: PropTypes.func.isRequired

106
app/src/containers/ProfileInformation.js

@ -6,7 +6,9 @@ import { drizzle } from '../index';
import epochTimeConverter from '../helpers/EpochTimeConverter';
import ContentLoader from 'react-content-loader';
import UsernameFormContainer from './UsernameFormContainer';
import { Table } from 'semantic-ui-react'
const callsInfo = [
{
@ -130,46 +132,76 @@ class ProfileInformation extends Component {
name={username}
/>
)}
<table className="highlight centered responsive-table">
<tbody>
<tr>
<td><strong>Username:</strong></td>
<td>{username}</td>
</tr>
<tr>
<td><strong>Account address:</strong></td>
<td>{address}</td>
</tr>
<tr>
<td><strong>OrbitDB:</strong></td>
<td>{orbitDBId}</td>
</tr>
<tr>
<td><strong>TopicsDB:</strong></td>
<td>{topicsDBId}</td>
</tr>
<tr>
<td><strong>PostsDB:</strong></td>
<td>{postsDBId}</td>
</tr>
<tr>
<td><strong>Number of topics created:</strong></td>
<td>{numberOfTopics}</td>
</tr>
<tr>
<td><strong>Number of posts:</strong></td>
<td>{numberOfPosts}</td>
</tr>
<Table basic='very' singleLine>
<Table.Body>
<Table.Row>
<Table.Cell><strong>Username:</strong></Table.Cell>
<Table.Cell>{username}</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell><strong>Account address:</strong></Table.Cell>
<Table.Cell>{address}</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell><strong>OrbitDB:</strong></Table.Cell>
<Table.Cell>{orbitDBId ? orbitDBId
: <ContentLoader height={5.8} width={300} speed={2}
primaryColor="#b2e8e6" secondaryColor="#00b5ad"
>
<rect x="0" y="0" rx="3" ry="3" width="80" height="5.5" />
</ContentLoader>
}</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell><strong>TopicsDB:</strong></Table.Cell>
<Table.Cell>{topicsDBId ? topicsDBId
: <ContentLoader height={5.8} width={300} speed={2}
primaryColor="#b2e8e6" secondaryColor="#00b5ad"
>
<rect x="0" y="0" rx="3" ry="3" width="80" height="5.5" />
</ContentLoader>
}</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell><strong>PostsDB:</strong></Table.Cell>
<Table.Cell>{postsDBId ? postsDBId
: <ContentLoader height={5.8} width={300} speed={2}
primaryColor="#b2e8e6" secondaryColor="#00b5ad"
>
<rect x="0" y="0" rx="3" ry="3" width="80" height="5.5" />
</ContentLoader>
}</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell><strong>Number of topics created:</strong></Table.Cell>
<Table.Cell>{numberOfTopics !== -1 ? numberOfTopics
: <ContentLoader height={5.8} width={300} speed={2}
primaryColor="#b2e8e6" secondaryColor="#00b5ad"
>
<rect x="0" y="0" rx="3" ry="3" width="15" height="5.5" />
</ContentLoader>
}</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell><strong>Number of posts:</strong></Table.Cell>
<Table.Cell>{numberOfPosts !== -1 ? numberOfPosts
: <ContentLoader height={5.8} width={300} speed={2}
primaryColor="#b2e8e6" secondaryColor="#00b5ad"
>
<rect x="0" y="0" rx="3" ry="3" width="15" height="5.5" />
</ContentLoader>
}</Table.Cell>
</Table.Row>
{dateOfRegister
&& (
<tr>
<td><strong>Member since:</strong></td>
<td>{epochTimeConverter(dateOfRegister)}</td>
</tr>
<Table.Row>
<Table.Cell><strong>Member since:</strong></Table.Cell>
<Table.Cell>{epochTimeConverter(dateOfRegister)}</Table.Cell>
</Table.Row>
)
}
</tbody>
</table>
</Table.Body>
</Table>
{self && <UsernameFormContainer />}
</div>
);
@ -178,7 +210,7 @@ class ProfileInformation extends Component {
ProfileInformation.propTypes = {
drizzleStatus: PropTypes.object.isRequired,
contracts: PropTypes.array.isRequired,
contracts: PropTypes.PropTypes.objectOf(PropTypes.object).isRequired,
avatarUrl: PropTypes.string,
username: PropTypes.string.isRequired,
address: PropTypes.string.isRequired,

5
app/src/containers/Topic.js

@ -2,6 +2,7 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom';
import { GetTopicResult } from '../CustomPropTypes'
import ContentLoader from 'react-content-loader';
import { Card } from 'semantic-ui-react';
@ -54,7 +55,7 @@ class Topic extends Component {
{topicData.userName}
</p>
<p className="no-margin">
Number of Replies: {topicData.nReplies}
Number of Replies: {topicData.numberOfReplies}
</p>
<p className="topic-date grey-text">
<TimeAgo date={topicData.timestamp}/>
@ -69,7 +70,7 @@ class Topic extends Component {
Topic.propTypes = {
userAddress: PropTypes.string.isRequired,
history: PropTypes.object.isRequired,
//TODO: topicData: GetTopicResult.isRequired,
topicData: GetTopicResult.isRequired,
orbitDB: PropTypes.object.isRequired,
topicID: PropTypes.number.isRequired
};

2
app/src/containers/TopicContainer.js

@ -191,7 +191,7 @@ TopicContainer.propTypes = {
drizzleStatus: PropTypes.object.isRequired,
orbitDB: PropTypes.object.isRequired,
setNavBarTitle: PropTypes.func.isRequired,
contracts: PropTypes.array.isRequired,
contracts: PropTypes.PropTypes.objectOf(PropTypes.object).isRequired,
user: PropTypes.object.isRequired,
match: PropTypes.object.isRequired,
navigateTo: PropTypes.func.isRequired

8
app/src/containers/TopicList.js

@ -4,6 +4,7 @@ import { connect } from 'react-redux';
import { drizzle } from '../index';
import Topic from './Topic';
import PlaceholderContainer from './PlaceholderContainer';
const contract = 'Forum';
const getTopicMethod = 'getTopic';
@ -62,11 +63,11 @@ class TopicList extends Component {
if(fetchedTopicData) {
const topicData = {
userAddress: fetchedTopicData.value[0],
userAddress: fetchedTopicData.value[1],
fullOrbitAddress: `/orbitdb/${fetchedTopicData.value[0]}/topics`,
userName: fetchedTopicData.value[2],
timestamp: fetchedTopicData.value[3]*1000,
nReplies: fetchedTopicData.value[4].length
numberOfReplies: fetchedTopicData.value[4].length
};
return(
<Topic
@ -77,7 +78,8 @@ class TopicList extends Component {
)
}
return (<div key={topicID}>TODO: Loading UI/fetching needs to be changed (?)</div>);
return (<PlaceholderContainer placeholderType='Topic'
extra={{topicID: topicID}} key={topicID} />);
});
//TODO: Return loading indicator instead of topics when not fully loaded (?)

4
app/src/containers/UsernameFormContainer.js

@ -213,8 +213,8 @@ UsernameFormContainer.propTypes = {
dispatch: PropTypes.func.isRequired,
account: PropTypes.string.isRequired,
transactionStack: PropTypes.array.isRequired,
transactions: PropTypes.array.isRequired,
contracts: PropTypes.array.isRequired,
transactions: PropTypes.PropTypes.objectOf(PropTypes.object).isRequired,
contracts: PropTypes.PropTypes.objectOf(PropTypes.object).isRequired,
user: PropTypes.object.isRequired
};

Loading…
Cancel
Save