summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorDessalines <tyhou13@gmx.com>2020-01-20 10:11:50 -0500
committerDessalines <tyhou13@gmx.com>2020-01-20 10:11:50 -0500
commite31090c9bd2ac2c1a411026add0a3e36631cf8cd (patch)
tree8b28501446288f0c15463c41de6c819364d88381 /ui
parentf020e89a8c8b5a8dafc41cf40dc9fb6f881778fb (diff)
Adding comment and post vote loading indicators. Fixes #449
Diffstat (limited to 'ui')
-rw-r--r--ui/src/components/comment-node.tsx93
-rw-r--r--ui/src/components/post-listing.tsx74
-rw-r--r--ui/src/components/post.tsx8
-rw-r--r--ui/src/interfaces.ts4
4 files changed, 93 insertions, 86 deletions
diff --git a/ui/src/components/comment-node.tsx b/ui/src/components/comment-node.tsx
index e6efcf9f..baaf63e9 100644
--- a/ui/src/components/comment-node.tsx
+++ b/ui/src/components/comment-node.tsx
@@ -47,8 +47,8 @@ interface CommentNodeState {
showConfirmAppointAsAdmin: boolean;
collapsed: boolean;
viewSource: boolean;
- my_vote: number;
- score: number;
+ upvoteLoading: boolean;
+ downvoteLoading: boolean;
}
interface CommentNodeProps {
@@ -78,8 +78,8 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
showConfirmTransferCommunity: false,
showConfirmAppointAsMod: false,
showConfirmAppointAsAdmin: false,
- my_vote: this.props.node.comment.my_vote,
- score: this.props.node.comment.score,
+ upvoteLoading: this.props.node.comment.upvoteLoading,
+ downvoteLoading: this.props.node.comment.downvoteLoading,
};
constructor(props: any, context: any) {
@@ -87,18 +87,18 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this.state = this.emptyState;
this.handleReplyCancel = this.handleReplyCancel.bind(this);
- this.handleCommentLike = this.handleCommentLike.bind(this);
- this.handleCommentDisLike = this.handleCommentDisLike.bind(this);
+ this.handleCommentUpvote = this.handleCommentUpvote.bind(this);
+ this.handleCommentDownvote = this.handleCommentDownvote.bind(this);
}
- componentDidUpdate(prevProps: CommentNodeProps) {
+ componentWillReceiveProps(nextProps: CommentNodeProps) {
if (
- prevProps.node.comment.my_vote !== this.props.node.comment.my_vote ||
- this.state.score !== this.props.node.comment.score
+ nextProps.node.comment.upvoteLoading !== this.state.upvoteLoading ||
+ nextProps.node.comment.downvoteLoading !== this.state.downvoteLoading
) {
this.setState({
- my_vote: this.props.node.comment.my_vote,
- score: this.props.node.comment.score,
+ upvoteLoading: false,
+ downvoteLoading: false,
});
}
}
@@ -119,26 +119,40 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
<button
disabled={!UserService.Instance.user}
className={`btn p-0 ${
- this.state.my_vote == 1 ? 'text-info' : 'text-muted'
+ node.comment.my_vote == 1 ? 'text-info' : 'text-muted'
}`}
- onClick={linkEvent(node, this.handleCommentLike)}
+ onClick={linkEvent(node, this.handleCommentUpvote)}
>
- <svg class="icon upvote">
- <use xlinkHref="#icon-arrow-up"></use>
- </svg>
+ {this.state.upvoteLoading ? (
+ <svg class="icon icon-spinner spin upvote">
+ <use xlinkHref="#icon-spinner"></use>
+ </svg>
+ ) : (
+ <svg class="icon upvote">
+ <use xlinkHref="#icon-arrow-up"></use>
+ </svg>
+ )}
</button>
- <div class={`font-weight-bold text-muted`}>{this.state.score}</div>
+ <div class={`font-weight-bold text-muted`}>
+ {node.comment.score}
+ </div>
{WebSocketService.Instance.site.enable_downvotes && (
<button
disabled={!UserService.Instance.user}
className={`btn p-0 ${
- this.state.my_vote == -1 ? 'text-danger' : 'text-muted'
+ node.comment.my_vote == -1 ? 'text-danger' : 'text-muted'
}`}
- onClick={linkEvent(node, this.handleCommentDisLike)}
+ onClick={linkEvent(node, this.handleCommentDownvote)}
>
- <svg class="icon downvote">
- <use xlinkHref="#icon-arrow-down"></use>
- </svg>
+ {this.state.downvoteLoading ? (
+ <svg class="icon icon-spinner spin downvote">
+ <use xlinkHref="#icon-spinner"></use>
+ </svg>
+ ) : (
+ <svg class="icon downvote">
+ <use xlinkHref="#icon-arrow-down"></use>
+ </svg>
+ )}
</button>
)}
</div>
@@ -736,41 +750,26 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this.setState(this.state);
}
- handleCommentLike(i: CommentNodeI) {
- this.state.my_vote = i.comment.my_vote == 1 ? 0 : 1;
- let add = 1;
- if (i.comment.my_vote == 1) {
- add = -1;
- } else if (i.comment.my_vote == -1) {
- add = 2;
- }
-
- this.state.score = i.comment.score + add;
- this.setState(this.state);
-
+ handleCommentUpvote(i: CommentNodeI) {
+ this.setState({
+ upvoteLoading: true,
+ });
let form: CommentLikeForm = {
comment_id: i.comment.id,
post_id: i.comment.post_id,
- score: this.state.my_vote,
+ score: i.comment.my_vote == 1 ? 0 : 1,
};
WebSocketService.Instance.likeComment(form);
}
- handleCommentDisLike(i: CommentNodeI) {
- this.state.my_vote = i.comment.my_vote == -1 ? 0 : -1;
- let add = -1;
- if (i.comment.my_vote == 1) {
- add = -2;
- } else if (i.comment.my_vote == -1) {
- add = 1;
- }
- this.state.score = i.comment.score + add;
- this.setState(this.state);
-
+ handleCommentDownvote(i: CommentNodeI) {
+ this.setState({
+ downvoteLoading: true,
+ });
let form: CommentLikeForm = {
comment_id: i.comment.id,
post_id: i.comment.post_id,
- score: this.state.my_vote,
+ score: i.comment.my_vote == -1 ? 0 : -1,
};
WebSocketService.Instance.likeComment(form);
}
diff --git a/ui/src/components/post-listing.tsx b/ui/src/components/post-listing.tsx
index 0c6d44b4..96825753 100644
--- a/ui/src/components/post-listing.tsx
+++ b/ui/src/components/post-listing.tsx
@@ -44,8 +44,8 @@ interface PostListingState {
showConfirmTransferCommunity: boolean;
imageExpanded: boolean;
viewSource: boolean;
- my_vote: number;
- score: number;
+ upvoteLoading: boolean;
+ downvoteLoading: boolean;
}
interface PostListingProps {
@@ -70,8 +70,8 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
showConfirmTransferCommunity: false,
imageExpanded: false,
viewSource: false,
- my_vote: this.props.post.my_vote,
- score: this.props.post.score,
+ upvoteLoading: this.props.post.upvoteLoading,
+ downvoteLoading: this.props.post.downvoteLoading,
};
constructor(props: any, context: any) {
@@ -84,11 +84,14 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
this.handleEditCancel = this.handleEditCancel.bind(this);
}
- componentDidUpdate(prevProps: PostListingProps) {
- if (prevProps.post.my_vote !== this.props.post.my_vote) {
+ componentWillReceiveProps(nextProps: PostListingProps) {
+ if (
+ nextProps.post.upvoteLoading !== this.state.upvoteLoading ||
+ nextProps.post.downvoteLoading !== this.state.downvoteLoading
+ ) {
this.setState({
- my_vote: this.props.post.my_vote,
- score: this.props.post.score,
+ upvoteLoading: false,
+ downvoteLoading: false,
});
}
}
@@ -122,26 +125,38 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
<button
disabled={!UserService.Instance.user}
className={`btn p-0 ${
- this.state.my_vote == 1 ? 'text-info' : 'text-muted'
+ post.my_vote == 1 ? 'text-info' : 'text-muted'
}`}
onClick={linkEvent(this, this.handlePostLike)}
>
- <svg class="icon upvote">
- <use xlinkHref="#icon-arrow-up"></use>
- </svg>
+ {this.state.upvoteLoading ? (
+ <svg class="icon icon-spinner spin upvote">
+ <use xlinkHref="#icon-spinner"></use>
+ </svg>
+ ) : (
+ <svg class="icon upvote">
+ <use xlinkHref="#icon-arrow-up"></use>
+ </svg>
+ )}
</button>
- <div class={`font-weight-bold text-muted`}>{this.state.score}</div>
+ <div class={`font-weight-bold text-muted`}>{post.score}</div>
{WebSocketService.Instance.site.enable_downvotes && (
<button
disabled={!UserService.Instance.user}
className={`btn p-0 ${
- this.state.my_vote == -1 ? 'text-danger' : 'text-muted'
+ post.my_vote == -1 ? 'text-danger' : 'text-muted'
}`}
onClick={linkEvent(this, this.handlePostDisLike)}
>
- <svg class="icon downvote">
- <use xlinkHref="#icon-arrow-down"></use>
- </svg>
+ {this.state.downvoteLoading ? (
+ <svg class="icon icon-spinner spin downvote">
+ <use xlinkHref="#icon-spinner"></use>
+ </svg>
+ ) : (
+ <svg class="icon downvote">
+ <use xlinkHref="#icon-arrow-down"></use>
+ </svg>
+ )}
</button>
)}
</div>
@@ -731,38 +746,21 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
}
handlePostLike(i: PostListing) {
- this.state.my_vote = i.props.post.my_vote == 1 ? 0 : 1;
- let add = 1;
- if (i.props.post.my_vote == 1) {
- add = -1;
- } else if (i.props.post.my_vote == -1) {
- add = 2;
- }
-
- this.state.score = i.props.post.score + add;
- this.setState(this.state);
+ i.setState({ upvoteLoading: true });
let form: CreatePostLikeForm = {
post_id: i.props.post.id,
- score: this.state.my_vote,
+ score: i.props.post.my_vote == 1 ? 0 : 1,
};
WebSocketService.Instance.likePost(form);
}
handlePostDisLike(i: PostListing) {
- this.state.my_vote = i.props.post.my_vote == -1 ? 0 : -1;
- let add = -1;
- if (i.props.post.my_vote == 1) {
- add = -2;
- } else if (i.props.post.my_vote == -1) {
- add = 1;
- }
- this.state.score = i.props.post.score + add;
- this.setState(this.state);
+ i.setState({ downvoteLoading: true });
let form: CreatePostLikeForm = {
post_id: i.props.post.id,
- score: this.state.my_vote,
+ score: i.props.post.my_vote == -1 ? 0 : -1,
};
WebSocketService.Instance.likePost(form);
}
diff --git a/ui/src/components/post.tsx b/ui/src/components/post.tsx
index c4bfccee..2005cc17 100644
--- a/ui/src/components/post.tsx
+++ b/ui/src/components/post.tsx
@@ -400,7 +400,11 @@ export class Post extends Component<any, PostState> {
found.score = res.comment.score;
found.upvotes = res.comment.upvotes;
found.downvotes = res.comment.downvotes;
- if (res.comment.my_vote !== null) found.my_vote = res.comment.my_vote;
+ if (res.comment.my_vote !== null) {
+ found.my_vote = res.comment.my_vote;
+ found.upvoteLoading = false;
+ found.downvoteLoading = false;
+ }
this.setState(this.state);
} else if (op == UserOperation.CreatePostLike) {
let res: CreatePostLikeResponse = msg;
@@ -408,6 +412,8 @@ export class Post extends Component<any, PostState> {
this.state.post.score = res.post.score;
this.state.post.upvotes = res.post.upvotes;
this.state.post.downvotes = res.post.downvotes;
+ this.state.post.upvoteLoading = false;
+ this.state.post.downvoteLoading = false;
this.setState(this.state);
} else if (op == UserOperation.EditPost) {
let res: PostResponse = msg;
diff --git a/ui/src/interfaces.ts b/ui/src/interfaces.ts
index 7fc7a252..232d1388 100644
--- a/ui/src/interfaces.ts
+++ b/ui/src/interfaces.ts
@@ -164,6 +164,8 @@ export interface Post {
subscribed?: boolean;
read?: boolean;
saved?: boolean;
+ upvoteLoading?: boolean;
+ downvoteLoading?: boolean;
}
export interface Comment {
@@ -190,6 +192,8 @@ export interface Comment {
saved?: boolean;
user_mention_id?: number; // For mention type
recipient_id?: number;
+ upvoteLoading?: boolean;
+ downvoteLoading?: boolean;
}
export interface Category {