Browse Source

Add Navbar title, Scroll to post requested in the url

develop
Apostolos Fanakis 7 years ago
parent
commit
810e3a5a20
  1. 20
      src/assets/css/App.css
  2. 10
      src/components/NavBar.js
  3. 151
      src/components/Post.js
  4. 1
      src/components/PostList.js
  5. 8
      src/components/ProfileInformation.js
  6. 23
      src/containers/ProfileContainer.js
  7. 11
      src/containers/TopicContainer.js
  8. 2
      src/containers/UsernameFormContainer.js
  9. 12
      src/redux/actions/userInterfaceActions.js
  10. 13
      src/redux/reducer/userInterfaceReducer.js

20
src/assets/css/App.css

@ -66,6 +66,22 @@ strong {
/* MISC */
.navBarText {
height: 61px;
width: 1192px;
position: absolute;
left: calc(50% - 596px);
text-align: center;
}
.navBarText span {
color: #00b5ad;
height: 61px;
line-height: 61px;
vertical-align: middle;
font-size: 1.5em;
}
.form-textarea-required {
color: rgb(159, 58, 56) !important;
outline-color: rgb(159, 58, 56) !important;
@ -168,7 +184,3 @@ a {
width: 100%;
height: 100%;
}
.vis { /* For UX developing */
border: 1px solid red;
}

10
src/components/NavBar.js

@ -41,6 +41,9 @@ class NavBar extends Component {
</Menu.Item>
</Menu.Menu>
}
<div className="navBarText">
{this.props.navBarTitle !== '' && <span>{this.props.navBarTitle}</span>}
</div>
</Menu>
);
}
@ -51,9 +54,10 @@ NavBar.contextTypes = {
};
const mapStateToProps = state => {
return {
hasSignedUp: state.user.hasSignedUp
}
return {
hasSignedUp: state.user.hasSignedUp,
navBarTitle: state.interface.navBarTitle
}
};
export default drizzleConnect(NavBar, mapStateToProps);

151
src/components/Post.js

@ -3,6 +3,7 @@ import { Link, withRouter } from 'react-router';
import { drizzleConnect } from 'drizzle-react';
import PropTypes from 'prop-types';
import { Transition } from 'semantic-ui-react'
import { Grid, Divider, Button, Icon, Label } from 'semantic-ui-react'
import TimeAgo from 'react-timeago';
@ -15,12 +16,18 @@ class Post extends Component {
super(props);
this.fetchPost = this.fetchPost.bind(this);
if (props.getFocus){
this.postRef = React.createRef();
}
this.orbitPostData = {
content: "",
subject: ""
};
this.orbitPostDataFetchStatus = "pending";
this.state = {
animateOnToggle: true
}
}
async fetchPost(postID) {
@ -44,6 +51,7 @@ class Post extends Component {
}
}
this.orbitPostDataFetchStatus = "fetched";
this.readyForAnimation = true;
}
render(){
@ -57,74 +65,76 @@ class Post extends Component {
);
return (
<div className="post">
<Divider horizontal>
<span className="grey-text">#{this.props.postIndex}</span>
</Divider>
<Grid>
<Grid.Row columns={16} stretched>
<Grid.Column width={1} className="user-avatar">
{this.props.blockchainData[0].returnData !== null
?<Link to={"/profile/" + this.props.blockchainData[0].returnData[1]
+ "/" + this.props.blockchainData[0].returnData[2]}
onClick={(event) => {event.stopPropagation()}}>
{avatarView}
</Link>
:avatarView
}
</Grid.Column>
<Grid.Column width={15}>
<div className="">
<div className="stretch-space-between">
<span className={this.props.blockchainData[0].returnData !== null ? "" : "grey-text"}>
<strong>
{this.props.blockchainData[0].returnData !== null
?this.props.blockchainData[0].returnData[2]
:"Username"
<Transition animation='tada' duration={500} visible={this.state.animateOnToggle}>
<div className="post" ref={this.postRef ? this.postRef : null}>
<Divider horizontal>
<span className="grey-text">#{this.props.postIndex}</span>
</Divider>
<Grid>
<Grid.Row columns={16} stretched>
<Grid.Column width={1} className="user-avatar">
{this.props.blockchainData[0].returnData !== null
?<Link to={"/profile/" + this.props.blockchainData[0].returnData[1]
+ "/" + this.props.blockchainData[0].returnData[2]}
onClick={(event) => {event.stopPropagation()}}>
{avatarView}
</Link>
:avatarView
}
</Grid.Column>
<Grid.Column width={15}>
<div className="">
<div className="stretch-space-between">
<span className={this.props.blockchainData[0].returnData !== null ? "" : "grey-text"}>
<strong>
{this.props.blockchainData[0].returnData !== null
?this.props.blockchainData[0].returnData[2]
:"Username"
}
</strong>
</span>
<span className="grey-text">
{this.props.blockchainData[0].returnData !== null &&
<TimeAgo date={epochTimeConverter(this.props.blockchainData[0].returnData[3])}/>
}
</strong>
</span>
<span className="grey-text">
{this.props.blockchainData[0].returnData !== null &&
<TimeAgo date={epochTimeConverter(this.props.blockchainData[0].returnData[3])}/>
</span>
</div>
<div className="stretch-space-between">
<span className={this.orbitPostData.subject ? "" : "grey-text"}>
<strong>
Subject: {this.orbitPostData.subject}
</strong>
</span>
</div>
<div className="post-content">
{this.orbitPostData.content
? <ReactMarkdown source={this.orbitPostData.content} />
: <p className="grey-text">Post content...</p>
}
</span>
</div>
<div className="stretch-space-between">
<span className={this.orbitPostData.subject ? "" : "grey-text"}>
<strong>
Subject: {this.orbitPostData.subject}
</strong>
</span>
</div>
</div>
<div className="post-content">
{this.orbitPostData.content
? <ReactMarkdown source={this.orbitPostData.content} />
: <p className="grey-text">Post content...</p>
}
</div>
</div>
</Grid.Column>
</Grid.Row>
<Grid.Row>
<Grid.Column floated="right" textAlign="right">
<Button icon size='mini' style={{marginRight: "0px"}}>
<Icon name='chevron up' />
</Button>
<Label color="teal">8000</Label>
<Button icon size='mini'>
<Icon name='chevron down' />
</Button>
<Button icon size='mini'
onClick={() => { this.context.router.push("/topic/"
+ this.props.blockchainData[0].returnData[4] + "/"
+ this.props.postID)}}>
<Icon name='linkify' />
</Button>
</Grid.Column>
</Grid.Row>
</Grid>
</div>
</Grid.Column>
</Grid.Row>
<Grid.Row>
<Grid.Column floated="right" textAlign="right">
<Button icon size='mini' style={{marginRight: "0px"}}>
<Icon name='chevron up' />
</Button>
<Label color="teal">8000</Label>
<Button icon size='mini'>
<Icon name='chevron down' />
</Button>
<Button icon size='mini'
onClick={() => { this.context.router.push("/topic/"
+ this.props.blockchainData[0].returnData[4] + "/"
+ this.props.postID)}}>
<Icon name='linkify' />
</Button>
</Grid.Column>
</Grid.Row>
</Grid>
</div>
</Transition>
);
}
@ -133,6 +143,17 @@ class Post extends Component {
&& this.orbitPostDataFetchStatus === "pending") {
this.fetchPost(this.props.postID);
}
if (this.readyForAnimation){
if (this.postRef){
setTimeout(() => {
this.postRef.current.scrollIntoView({ block: 'start', behavior: 'smooth' });
setTimeout(() => {
this.setState({ animateOnToggle: false });
}, 300);
}, 100);
this.readyForAnimation = false;
}
}
}
};

1
src/components/PostList.js

@ -17,6 +17,7 @@ const PostList = (props) => {
avatarUrl={""}
postIndex={index}
postID={postID}
getFocus={props.focusOnPost === postID ? true : false}
key={postID}
/>
);

8
src/components/ProfileInformation.js

@ -7,10 +7,6 @@ import UsernameFormContainer from '../containers/UsernameFormContainer';
const ProfileInformation = (props) => {
let transaction = props.blockchainData
.find(transaction => transaction.callInfo.method === "getUsername");
let username = transaction ? transaction.returnData : "";
transaction = props.blockchainData
.find(transaction => transaction.callInfo.method === "getUserDateOfRegister");
let dateOfRegister = transaction ? transaction.returnData : "";
@ -24,12 +20,12 @@ const ProfileInformation = (props) => {
size="40"
className="inline user-avatar"
src={props.avatarUrl}
name={username}/>}
name={props.username}/>}
<table className="highlight centered responsive-table">
<tbody>
<tr>
<td><strong>Username:</strong></td>
<td>{username}</td>
<td>{props.username}</td>
</tr>
<tr>
<td><strong>Account address:</strong></td>

23
src/containers/ProfileContainer.js

@ -9,6 +9,7 @@ import ProfileInformation from '../components/ProfileInformation';
import TopicList from '../components/TopicList';
import PostList from '../components/PostList';
import LoadingSpinner from '../components/LoadingSpinner';
import { setNavBarTitle } from '../redux/actions/userInterfaceActions';
class Profile extends Component {
constructor(props, context) {
@ -34,10 +35,6 @@ class Profile extends Component {
(<WithBlockchainData
component={ProfileInformation}
callsInfo={[{
contract: 'Forum',
method: 'getUsername',
params: [this.state.userAddress]
},{
contract: 'Forum',
method: 'getUserDateOfRegister',
params: [this.state.userAddress]
@ -47,6 +44,7 @@ class Profile extends Component {
params: [this.state.userAddress]
}]}
address={this.state.userAddress}
username={this.username}
numberOfTopics={this.topicIDs && this.topicIDs.length}
numberOfPosts={this.postIDs && this.postIDs.length}
self={this.state.userAddress === this.props.user.address}
@ -102,6 +100,13 @@ class Profile extends Component {
}
propsToView(){
if (!this.username){
let transaction = this.props.blockchainData
.find(transaction => transaction.callInfo.method === "getUsername");
if (transaction.returnData){
this.username = transaction.returnData;
}
}
if (!this.topicIDs){
let transaction = this.props.blockchainData
.find(transaction => transaction.callInfo.method === "getUserTopics");
@ -117,6 +122,12 @@ class Profile extends Component {
}
}
}
componentDidUpdate(){
if (this.username){
this.props.store.dispatch(setNavBarTitle(this.username));
}
}
}
Profile.contextTypes = {
@ -145,6 +156,10 @@ class ProfileContainer extends Component {
this.profile = <WithBlockchainData
component={drizzleConnect(Profile, mapStateToProps)}
callsInfo={[{
contract: 'Forum',
method: 'getUsername',
params: [userAddress]
},{
contract: 'Forum',
method: 'getUserTopics',
params: [userAddress]

11
src/containers/TopicContainer.js

@ -6,7 +6,11 @@ import PostList from '../components/PostList';
import NewPost from '../components/NewPost';
import FloatingButton from '../components/FloatingButton';
import { showProgressBar, hideProgressBar } from '../redux/actions/userInterfaceActions';
import {
showProgressBar,
hideProgressBar,
setNavBarTitle
} from '../redux/actions/userInterfaceActions';
class Topic extends Component {
constructor(props) {
@ -50,6 +54,7 @@ class Topic extends Component {
}
this.props.store.dispatch(hideProgressBar());
this.props.store.dispatch(setNavBarTitle(orbitData['subject']));
this.setState({
'topicSubject': orbitData['subject'],
fetchTopicSubjectStatus: "fetched"
@ -69,7 +74,6 @@ class Topic extends Component {
this.setState(prevState => ({
posting: false
}));
//TODO reload topic
}
render() {
@ -77,7 +81,8 @@ class Topic extends Component {
if (this.props.blockchainData[0].status === "success") {
topicContents = (
(<div>
<PostList postIDs={this.props.blockchainData[0].returnData[4]}/>
<PostList postIDs={this.props.blockchainData[0].returnData[4]}
focusOnPost={this.state.postFocus ? this.state.postFocus : null}/>
{this.state.posting &&
<NewPost topicID={this.state.topicID}
subject={this.state.topicSubject}

2
src/containers/UsernameFormContainer.js

@ -92,7 +92,7 @@ class UsernameFormContainer extends Component {
</Form>
<Dimmer active={this.state.signingUp} page>
<Header as='h2' inverted>
<Loader size='large'>Magic elfs are processing your nobel request.</Loader>
<Loader size='large'>Magic elves are processing your noble request.</Loader>
</Header>
</Dimmer>
</div>

12
src/redux/actions/userInterfaceActions.js

@ -2,11 +2,19 @@
export const SHOW_PROGRESS_BAR = 'SHOW_PROGRESS_BAR';
export const HIDE_PROGRESS_BAR = 'HIDE_PROGRESS_BAR';
export const SET_NAVBAR_TITLE = 'SET_NAVBAR_TITLE';
export function showProgressBar(){
return { type: 'SHOW_PROGRESS_BAR'};
return { type: SHOW_PROGRESS_BAR};
}
export function hideProgressBar(){
return { type: 'HIDE_PROGRESS_BAR'};
return { type: HIDE_PROGRESS_BAR};
}
export function setNavBarTitle(newTitle){
return {
type: SET_NAVBAR_TITLE,
title: newTitle
};
}

13
src/redux/reducer/userInterfaceReducer.js

@ -1,7 +1,12 @@
import { SHOW_PROGRESS_BAR, HIDE_PROGRESS_BAR } from '../actions/userInterfaceActions';
import {
SHOW_PROGRESS_BAR,
HIDE_PROGRESS_BAR,
SET_NAVBAR_TITLE
} from '../actions/userInterfaceActions';
const initialState = {
displayProgressBar: false
displayProgressBar: false,
navBarTitle: ''
};
const userInterfaceReducer = (state = initialState, action) => {
@ -14,6 +19,10 @@ const userInterfaceReducer = (state = initialState, action) => {
return {
displayProgressBar: false
};
case SET_NAVBAR_TITLE:
return {
navBarTitle: action.title
}
default:
return state;
}

Loading…
Cancel
Save