Skip to content
This repository has been archived by the owner on Aug 16, 2019. It is now read-only.

Commit

Permalink
New posts container (#17)
Browse files Browse the repository at this point in the history
* Remove clamp - serious performance hit in Firefox and Edge

* Rough styles and layout

* Fix position

* Shouldn't be absolute

* Clean

* New post preview design
  • Loading branch information
jrawsthorne committed May 20, 2018
1 parent e9ea574 commit 1bbd437
Show file tree
Hide file tree
Showing 9 changed files with 197 additions and 158 deletions.
36 changes: 17 additions & 19 deletions src/actions/postActions.js
Expand Up @@ -5,24 +5,21 @@ import { FETCH_POSTS, FETCH_POST } from './types';

// return only data we need
const getPostData = (steemPost, post) => ({
id: steemPost.id,
title: steemPost.title,
author: steemPost.author,
...steemPost,
url: `@${steemPost.author}/${steemPost.permlink}`,
permlink: steemPost.permlink,
body: steemPost.body,
postType: post.postType,
mediaType: post.mediaType,
type: post.type,
tmdbid: post.tmdbid,
mediaTitle: post.title,
backdropPath: post.backdropPath || undefined,
posterPath: post.posterPath || undefined,
episodePath: post.episodePath || undefined,
seasonPath: post.seasonPath || undefined,
seasonNum: post.seasonNum || undefined,
episodeNum: post.episodeNum || undefined,
rating: post.rating || undefined,
media: {
title: post.title,
mediaType: post.mediaType,
backdropPath: post.backdropPath || undefined,
posterPath: post.posterPath || undefined,
episodePath: post.episodePath || undefined,
seasonPath: post.seasonPath || undefined,
seasonNum: post.seasonNum || undefined,
episodeNum: post.episodeNum || undefined,
type: post.type,
tmdbid: post.tmdbid,
},
});

// fetch post from db and return steem and db info
Expand All @@ -43,7 +40,7 @@ export const fetchPost = (author, permlink) => ({

// add sortby options

export const fetchPosts = (posts, {
export const fetchPosts = ({
postType = 'all',
mediaType = undefined,
tmdbid = undefined,
Expand All @@ -53,13 +50,14 @@ export const fetchPosts = (posts, {
type = undefined,
author = undefined,
subscriptions = false,
}) => (dispatch) => {
}) => (dispatch, getState) => {
let query;
if (subscriptions) {
query = 'users/subscriptions';
query = 'subscriptions';
} else {
query = 'posts';
}
const posts = getState().posts.items;
dispatch({
type: FETCH_POSTS,
payload: axios.get(`${process.env.API_URL}/${query}`, {
Expand Down
40 changes: 20 additions & 20 deletions src/components/pages/HomePage.js
Expand Up @@ -6,6 +6,12 @@ import { Layout, Popover, Icon } from 'antd';
import PostsContainer from '../post/PostsContainer';

class HomePage extends React.Component {
static getDerivedStateFromProps(nextProps) {
const { filter } = nextProps.match.params;
return {
currentFilter: filter ? filter[0].toUpperCase() + filter.substr(1) : undefined,
};
}
state = {
visible: false,
currentFilter: undefined,
Expand All @@ -23,19 +29,12 @@ class HomePage extends React.Component {
});
}
}
componentWillReceiveProps(nextProps) {
const { filter } = nextProps.match.params;
if (filter) {
this.setState({
currentFilter: filter[0].toUpperCase() + filter.substr(1),
});
} else {
this.setState({
currentFilter: undefined,
});
}
if (this.props.isAuthenticated && !nextProps.isAuthenticated && filter === 'subscriptions') {
nextProps.history.push('/');
componentDidUpdate(prevProps) {
const { isAuthenticated, history: { push } } = this.props;
const { isAuthenticated: wasAuthenticated } = prevProps;
const { currentFilter } = this.state;
if (wasAuthenticated && !isAuthenticated && currentFilter === 'Subscriptions') {
push('/');
}
}
handleFilterClick = (key) => {
Expand All @@ -60,11 +59,13 @@ class HomePage extends React.Component {
const filters = ['All', 'Movies', 'Shows', 'Episodes'];
if (isAuthenticated) filters.push('Subscriptions');
const content = (
/* eslint-disable
jsx-a11y/click-events-have-key-events,jsx-a11y/no-noninteractive-element-interactions */
<div>{filters.map(f => <p onClick={() => this.handleFilterClick(f)} className="Filter__option" key={f.toLowerCase()}>{f}</p>)}</div>
/* eslint-enable
jsx-a11y/click-events-have-key-events,jsx-a11y/no-noninteractive-element-interactions */
<div>
{filters.map(f => (
<p role="presentation" onClick={() => this.handleFilterClick(f)} onKeyPress={() => this.handleFilterClick(f)} className="Filter__option" key={f.toLowerCase()}>
{f}
</p>
))}
</div>
);
let props;
if (filter === 'movies' || filter === 'episodes' || filter === 'shows') {
Expand All @@ -79,10 +80,9 @@ class HomePage extends React.Component {
<h2>
Latest
<Popover onVisibleChange={this.handleVisibleChange} visible={visible} placement="bottom" content={content} trigger="click">
<span className="Filter__dropdown">{currentFilter && currentFilter} <Icon type="down" style={{ fontSize: 15 }} /></span>
<span style={{ marginLeft: 5 }} className="Filter__dropdown"> {currentFilter && currentFilter} <Icon type="down" style={{ fontSize: 15 }} /></span>
</Popover>
</h2>
<p>These posts are real but just for testing.</p>
{(isAuthenticated || filter !== 'subscriptions') ? <PostsContainer {...props} /> : 'Not authenticated'}
</Layout>
);
Expand Down
11 changes: 6 additions & 5 deletions src/components/pages/PostPage.js
@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import _ from 'lodash';
import { Layout } from 'antd';
import { Layout, Divider } from 'antd';
import classNames from 'classnames';

import Loading from '../misc/Loading';
Expand Down Expand Up @@ -51,12 +51,13 @@ class PostPage extends React.Component {
<MediaContainer
noLoading
onLoad={this.onMediaLoad}
mediaType={post.mediaType}
tmdbid={`${post.tmdbid}`}
seasonNum={_.get(post, 'seasonNum') && post.seasonNum.toString()}
episodeNum={_.get(post, 'episodeNum') && post.episodeNum.toString()}
mediaType={post.media.mediaType}
tmdbid={`${post.media.tmdbid}`}
seasonNum={_.get(post.media, 'seasonNum') && post.media.seasonNum.toString()}
episodeNum={_.get(post.media, 'episodeNum') && post.media.episodeNum.toString()}
/>}
<Layout className={classNames('main-content', 'PostPage__post', { showPost: mediaStatus.loaded || postStatus.failed })}>
<Divider />
<PostContainer
noLoading
onLoad={this.onPostLoad}
Expand Down
1 change: 1 addition & 0 deletions src/components/pages/PostPage.less
@@ -1,5 +1,6 @@
.PostPage__post {
display: none;
padding-top: 0!important;
&.showPost {
display: block;
}
Expand Down
52 changes: 34 additions & 18 deletions src/components/post/PostPreview.js
@@ -1,12 +1,11 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Card } from 'antd';
import { Icon } from 'antd';
import { Link } from 'react-router-dom';
import BodyShort from './BodyShort';

import noImageFound from '../../images/no-image-found.jpg';

const { Meta } = Card;
import './PostPreview.less';

class PostPreview extends React.Component {
state = {
Expand All @@ -19,24 +18,41 @@ class PostPreview extends React.Component {
}
render() {
const {
url, posterPath, overview, title, mediaTitle, author, mediaUrl,
url,
posterPath,
overview,
title,
mediaTitle,
mediaUrl,
post,
} = this.props;
let imageSource;
if (this.state.imageError || !posterPath) {
imageSource = noImageFound;
} else {
imageSource = `https://image.tmdb.org/t/p/w780${posterPath}`;
}
const options = {
year: 'numeric', month: 'long', day: 'numeric',
};
let created = new Date(post.created);
created = created.toLocaleDateString('en-GB', options);
return (
<Card
hoverable
style={{ width: '100%' }}
cover={<Link to={url}><img onError={() => this.handleImageError()} alt="poster" height="auto" src={(this.state.imageError && noImageFound) || (posterPath && `https://image.tmdb.org/t/p/w780${posterPath}`) || noImageFound} /></Link>}
title={<Link to={mediaUrl}>{mediaTitle}</Link>}
>
<React.Fragment>
<Link to={url}>
<Meta
title={title}
description={<BodyShort body={overview} />}
/>
<div className="PostPreviewBackdrop" style={{ backgroundImage: `url(${imageSource})` }} />
</Link>
<Link to={`/@${author}`}><p style={{ marginTop: 15, marginBottom: 0 }}>By {author}</p></Link>
</Card>

<div className="PostPreviewBody">
<h2 style={{ marginBottom: 0 }}>
<Link to={mediaUrl}>{mediaTitle}</Link>
</h2>
<p style={{ marginBottom: '1em' }}>
<Icon style={{ fontSize: 12, marginRight: 5 }} type="clock-circle-o" /> {created}
</p>
<h3><Link to={url}>{title}</Link></h3>
<BodyShort body={overview} />
</div>
</React.Fragment>
);
}
}
Expand All @@ -47,8 +63,8 @@ PostPreview.propTypes = {
posterPath: PropTypes.string,
url: PropTypes.string.isRequired,
mediaTitle: PropTypes.string.isRequired,
author: PropTypes.string.isRequired,
mediaUrl: PropTypes.string.isRequired,
post: PropTypes.shape().isRequired,
};

PostPreview.defaultProps = {
Expand Down
27 changes: 27 additions & 0 deletions src/components/post/PostPreview.less
@@ -0,0 +1,27 @@
.postsLayout {
display: flex;
flex-wrap: wrap;
&__post {
width: 100%;
padding: 10px;
@media (min-width: 768px) {
width: 50%;
}
.PostPreviewBackdrop {
height: 200px;
background-size: cover;
}
.PostPreviewBody {
background: #fff;
padding: 20px;
margin-top: -25px;
width: 95%;
float: right;
}
}
}

.postsContainer {
margin-left: -10px;
margin-right: -10px;
}
50 changes: 50 additions & 0 deletions src/components/post/PostPreviewContainer.js
@@ -0,0 +1,50 @@
import React from 'react';
import PropTypes from 'prop-types';
import _ from 'lodash';
import { connect } from 'react-redux';

import Post from './PostPreview';

class NewPostsContainer extends React.Component {
static propTypes = {
post: PropTypes.shape().isRequired,
};
render() {
const { post } = this.props;
const { media } = post;
let { title } = media;
let mediaUrl = `/${media.type}/${media.tmdbid}`;
if (media.seasonNum) {
title += ` S${media.seasonNum}`;
mediaUrl += `/season/${media.seasonNum}`;
if (media.episodeNum) {
title += ` E${media.episodeNum}`;
mediaUrl += `/episode/${media.episodeNum}`;
}
}
const poster = media.episodePath || media.backdropPath || '';
return (
<div className="postsLayout__post">
<Post
overview={post.body}
id={post.id}
title={post.title}
permlink={post.permlink}
posterPath={poster}
mediaTitle={title}
author={post.author}
url={`/${post.url}`}
mediaUrl={mediaUrl}
handleLikeClick={this.handleLikeClick}
post={post}
/>
</div>
);
}
}

const mapStateToProps = (state, ownProps) => ({
post: _.get(state, `posts.items[${ownProps.postId}]`, {}),
});

export default connect(mapStateToProps, null)(NewPostsContainer);

0 comments on commit 1bbd437

Please sign in to comment.