docbrown/app/javascript/chat/article.jsx
Ali Spittel 52c60ce37e Feature/refactored onboarding (#3333)
* set up refactored onboarding

* create onboarding page

* add in first slide and change slide functionality

* fix test suite

* profile refactor

* profile refactor

* refactor to api

* add checkbox fields

* add checkbox fields

* remove puts

* add basic css

* add styling

* add redirect

* hide back and next at first and last slides

* test refactored onboarding

* test refactored onboarding

* remove article edits

* Fix schema

* Add deleted file back in

* Add default value for checked_t&c column

* Adjust HTML structure to keep nav buttons in place

* Fix ESLint issues on Onboarding.jsx file

* Handling for undefined or empty followedTags on getUserTags

* Fix codeclimate issues

* Fix codeclimate issues

* Fix more codeclimate issues

* Fix more codeclimate issues

* Update Onboarding snapshots

* Uncheck the CoC and T&C checkboxes on render

* Update snapshots

* Return false instead of raising error

* Update spec to use new onboarding

* Redirect to onboarding if haven't seen it yet

* Prevent redirect to onboarding from /signout_confirm

* Use assign_attributes instead of saving twice

* Move COC and T&C checkbox page to second slide

* Add 'go back to original page' functionality

* Reuse ready prototype logic

* Keep track of the last visited onboarding page

* Fix email subscription bug

* Fix overflow issue for tags page

* Remove height to prevent page container scrolling

* Check for CoC and T&C for displaying onboarding

* Add InstantClick redirect and preserve referrer in client

* Fix async update + check by using localStorage

* Turn off onboarding for tests

* Finalize design for onboarding

* Finalize design for onboarding

* Make bulk follows during onboarding

* Fix bulk follow test
2019-07-26 15:53:32 -04:00

200 lines
5.6 KiB
JavaScript

import { h, Component } from 'preact';
import heartImage from 'images/emoji/emoji-one-heart.png';
import unicornImage from 'images/emoji/emoji-one-unicorn.png';
import bookmarkImage from 'images/emoji/emoji-one-bookmark.png';
import openLink from 'images/external-link-logo.svg';
export default class Article extends Component {
constructor(props) {
super(props);
this.state = {
reactionCounts: [],
userReactions: [],
optimisticUserReaction: null,
};
}
componentDidMount() {
fetch(`/reactions?article_id=${this.props.resource.id}`, {
Accept: 'application/json',
'Content-Type': 'application/json',
credentials: 'same-origin',
})
.then(response => response.json())
.then(this.displayReactions)
.catch(this.displayReactionsFailure);
}
displayReactions = response => {
this.setState({ userReactions: response.reactions });
};
displayReactionsFailure = response => {
console.log(response);
};
handleNewReactionResponse = response => {
let oldUserReactions = this.state.userReactions;
const foundReactions = oldUserReactions.filter(obj => {
return obj.category === response.category;
});
if (foundReactions.length === 0 && response.result === 'create') {
oldUserReactions.push({ category: response.category });
} else {
oldUserReactions = oldUserReactions.filter(obj => {
return obj.category != response.category;
});
}
this.setState({
userReactions: oldUserReactions,
optimisticUserReaction: null,
});
};
handleNewReactionFailure = response => {
console.log(response);
};
handleReactionClick = e => {
e.preventDefault();
const { target } = e;
this.setState({ optimisticUserReaction: target.dataset.category });
const article = this.props.resource;
fetch('/reactions', {
method: 'POST',
headers: {
Accept: 'application/json',
'X-CSRF-Token': window.csrfToken,
'Content-Type': 'application/json',
},
body: JSON.stringify({
reactable_type: 'Article',
reactable_id: article.id,
category: target.dataset.category,
}),
credentials: 'same-origin',
})
.then(response => response.json())
.then(this.handleNewReactionResponse)
.catch(this.handleNewReactionFailure);
};
actionButton = props => {
const types = {
heart: ['heart-reaction-button', 'like', heartImage],
unicorn: ['unicorn-reaction-button', 'unicorn', unicornImage],
readinglist: [
'readinglist-reaction-button',
'readinglist',
bookmarkImage,
],
};
const curType = types[props.reaction];
return (
<button
className={`${curType[0]} ${props.reactedClass}`}
onClick={this.handleReactionClick}
data-category={curType[1]}
>
<img
src={curType[2]}
data-category={curType[1]}
alt={`${curType[1]} reaction`}
/>
</button>
);
};
render() {
const article = this.props.resource;
let heartReactedClass = '';
let unicornReactedClass = '';
let bookmarkReactedClass = '';
const { state } = this;
state.userReactions.forEach(reaction => {
if (
reaction.category === 'like' ||
state.optimisticUserReaction === 'like'
) {
heartReactedClass = 'active';
}
if (
reaction.category === 'unicorn' ||
state.optimisticUserReaction === 'unicorn'
) {
unicornReactedClass = 'active';
}
if (
reaction.category === 'readinglist' ||
state.optimisticUserReaction === 'readinglist'
) {
bookmarkReactedClass = 'active';
}
});
let coverImage = '';
if (article.cover_image) {
coverImage = (
<section>
<div
className="image image-final"
style={{ backgroundImage: `url(${article.cover_image}` }}
/>
</section>
);
}
return (
<div className="activechatchannel__activeArticle">
<div className="activechatchannel__activeArticleDetails">
<a href={article.path} target="_blank" rel="noopener noreferrer">
<span className="activechatchannel__activeArticleDetailsPath">
{article.path}
</span>
</a>
</div>
<div className="container">
{coverImage}
<div className="title">
<h1>{article.title}</h1>
<h3>
<a
href={`/${article.user.username}`}
className="author"
data-content={`/users/${article.user.id}`}
>
<img
className="profile-pic"
src={article.user.profile_image_90}
alt={article.user.username}
/>
<span>{article.user.name} </span>
<span className="published-at">
{' '}
| {article.readable_publish_date}
</span>
</a>
</h3>
</div>
<div className="body">
<div dangerouslySetInnerHTML={{ __html: article.body_html }} />
</div>
</div>
<div className="activechatchannel__activeArticleActions">
<this.actionButton
reaction="heart"
reactedClass={heartReactedClass}
/>
<this.actionButton
reaction="unicorn"
reactedClass={unicornReactedClass}
/>
<this.actionButton
reaction="readinglist"
reactedClass={bookmarkReactedClass}
/>
</div>
</div>
);
}
}