diff --git a/app/assets/stylesheets/chat.scss b/app/assets/stylesheets/chat.scss
index ec0371f24..adb63e88f 100644
--- a/app/assets/stylesheets/chat.scss
+++ b/app/assets/stylesheets/chat.scss
@@ -377,6 +377,59 @@
top:-4px;
}
+.activechatchannel__activeArticle{
+ position: absolute;
+ top: 38px; left: 0; right: 0; bottom: 0;
+ border-top: 1px solid $light-medium-gray !important;
+}
+
+.chat .activechatchannel__activeArticle .container {
+ position: absolute;
+ top: 0px; left: 0; right: 0; bottom: 30px;
+ overflow-y: scroll;
+ border-radius: 0px;
+ margin-top: 0px !important;
+ pre{
+ width:97%;
+ margin-left:-3%;
+ padding-left:4%;
+ padding-right:7%;
+ }
+}
+
+.activechatchannel__activeArticleActions{
+ position:absolute;
+ bottom:0;
+ left:0px;
+ right:0px;
+ padding: 19px;
+ background: white;
+ z-index: 20;
+ border-top: 1px solid $light-medium-gray;
+ button {
+ border: 1px solid $light-medium-gray;
+ padding: 3px 20px;
+ border-radius: 3px;
+ margin-right: 15px;
+ &.active {
+ border: 2px solid $black;
+ padding: 2px 19px;
+ background-color:$green;
+ &.unicorn-reaction-button{
+ background-color:$purple;
+ }
+ &.readinglist-reaction-button{
+ background: lighten($bold-blue, 32%);
+ }
+ }
+ img {
+ width: 22px;
+ height: 22px;
+ }
+ }
+}
+
+
.activecontent__githubrepo{
}
diff --git a/app/controllers/reactions_controller.rb b/app/controllers/reactions_controller.rb
index eb81f827e..ad85a697c 100644
--- a/app/controllers/reactions_controller.rb
+++ b/app/controllers/reactions_controller.rb
@@ -60,7 +60,7 @@ class ReactionsController < ApplicationController
)
@result = "create"
end
- render json: { result: @result }
+ render json: { result: @result, category: params[:category] || "like" }
end
def cached_user_positive_reactions(user)
diff --git a/app/javascript/chat/article.jsx b/app/javascript/chat/article.jsx
new file mode 100644
index 000000000..9fd04693d
--- /dev/null
+++ b/app/javascript/chat/article.jsx
@@ -0,0 +1,138 @@
+
+
+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';
+
+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;
+ let 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.target;
+ console.log(target.dataset.category)
+ 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);
+
+ }
+
+ render() {
+ const article = this.props.resource;
+ let heartReactedClass = ''
+ let unicornReactedClass = ''
+ let bookmarkReactedClass = ''
+ const state = this.state;
+ 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 =