Skip to content

Commit

Permalink
SAK-50526 conversations Improve upvoting and reactions
Browse files Browse the repository at this point in the history
  • Loading branch information
adrianfish committed Dec 16, 2024
1 parent 1e038f4 commit 866e18f
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ public class ConversationsPost implements PersistableEntity<String> {
@Column(name = "NUMBER_OF_THREAD_REACTIONS")
private Integer numberOfThreadReactions = 0;

@Column(name = "NUMBER_OF_THREAD_UPVOTES")
private Integer numberOfThreadUpvotes = 0;

@Column(name = "DEPTH")
private Integer depth = 1;

Expand All @@ -100,6 +103,9 @@ public class ConversationsPost implements PersistableEntity<String> {
@Column(name = "UPVOTES")
private Integer upvotes = 0;

@Column(name = "REACTION_COUNT")
private Integer reactionCount = 0;

@Column(name = "PRIVATE_POST")
private Boolean privatePost = Boolean.FALSE;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ answer_this_question=Answer this question
answered=Answered
answered_tooltip=This question topic has an accepted answer
answers=Answers
ascending_by_author=Ascending by Author
asked=asked
availability=Availability
make_available_now=Make Available Now
Expand Down Expand Up @@ -62,6 +63,7 @@ delete=Delete
delete_this_comment=Delete this comment.
delete_this_post=Delete this post.
delete_topic_tooltip=Delete this topic
descending_by_author=Descending by Author
details=Details
disabled=disabled
discussion_tooltip=This is a discussion topic
Expand Down Expand Up @@ -116,6 +118,7 @@ instructors=Instructors in this site
instructors_answer=Instructor's Answer
invalid_lock_date=You've entered an invalid lock or accept until date. Those dates MUST be later than the due date.
late=late
least_active=Least Active
loading_1=Loading the data ...
loading_2=This may take a few seconds.
lock=Lock
Expand All @@ -128,6 +131,8 @@ moderator_hidden_message=This post has been hidden. You can see the content beca
moderator_topic_locked=This topic is locked and no changes can be made. Click 'Unlock' in the options menu to unlock it.
more_answers=View more answers
more_replies=View more replies
most_active=Most Active
most_recent=Most Recent
my_list=My List
name_header=Name
new=new
Expand All @@ -140,6 +145,7 @@ nothing_selected=Select a discussion or question to read, or create a new one
nothing_selected_no_create=Select a discussion or question to read
numberposts_tooltip=This is how many post have been made to this topic
off=Off
oldest=Oldest
on=On
permissions=Permissions
pin=Pin
Expand Down Expand Up @@ -188,7 +194,7 @@ can continue but the topic will not be visible until it is already due!
show_comments_tooltip=Show the comments for this post
show_topic_tooltip=Show this topic
soft_delete_this_post=Soft delete this post. You will be able to restore it later.
sort_by_author=Sort by author
sort_by_author=Sort by Author
sort_by_created_posts=Sort by the number of posts created
sort_by_created_topics=Sort by the number of topics created
sort_by_reactions_made=Sort by the number of reactions made
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1001,7 +1001,6 @@ public TopicTransferBean unUpvoteTopic(String siteId, String topicId) throws Con
return TopicTransferBean.of(topicRepository.save(topic));
}


public Optional<PostTransferBean> getPost(String postId) throws ConversationsPermissionsException {
return postRepository.findById(postId).map(PostTransferBean::of);
}
Expand Down Expand Up @@ -1076,7 +1075,7 @@ public PostTransferBean savePost(PostTransferBean postBean, boolean sendMessage)

thread.setNumberOfThreadReplies(thread.getNumberOfThreadReplies() + 1);
postRepository.save(thread);
updateThreadHowActiveScore(thread);
updatePostHowActiveScore(thread);
});
}
this.markPostViewed(postBean.topic, post, currentUserId);
Expand Down Expand Up @@ -1269,15 +1268,19 @@ private void sendMessage(Set<User> users, String siteId, Map<String, Object> rep
Arrays.asList(new MessageMedium[] {MessageMedium.EMAIL}), replacements, NotificationService.NOTI_OPTIONAL);
}

private void updateThreadHowActiveScore(ConversationsPost thread) {
@Transactional
private void updatePostHowActiveScore(ConversationsPost post) {

int numberOfReplies = thread.getNumberOfThreadReplies();
int numberOfReactions = thread.getNumberOfThreadReactions();
int howActive = 0;

int active = numberOfReplies + numberOfReactions;
if (post.getNumberOfThreadReplies() != null) howActive += post.getNumberOfThreadReplies();
if (post.getReactionCount() != null) howActive += post.getReactionCount();
if (post.getNumberOfThreadReactions() != null) howActive += post.getNumberOfThreadReactions();
if (post.getUpvotes() != null) howActive += post.getUpvotes();
if (post.getNumberOfThreadUpvotes() != null) howActive += post.getNumberOfThreadUpvotes();

thread.setHowActive(active);
postRepository.save(thread);
post.setHowActive(howActive);
postRepository.save(post);
}

private boolean canUserViewPost(ConversationsPost post, String currentUserId) {
Expand Down Expand Up @@ -1671,8 +1674,14 @@ public Map<Reaction, Integer> savePostReactions(String topicId, String postId, M
// Do we need to uncache posts if it's just a reaction?
postsCache.remove(topicId);

return postReactionTotalRepository.findByPostId(postId)
Map<Reaction, Integer> reactionTotals = postReactionTotalRepository.findByPostId(postId)
.stream().collect(Collectors.toMap(rt -> rt.getReaction(), rt -> rt.getTotal()));

post.setReactionCount(reactionTotals.values().stream().mapToInt(t -> t).sum());

updatePostHowActiveScore(post);

return reactionTotals;
}

public void markPostsViewed(Set<String> postIds, String topicId) throws ConversationsPermissionsException {
Expand Down Expand Up @@ -2099,6 +2108,16 @@ public PostTransferBean upvotePost(String siteId, String topicId, String postId)
post.setUpvotes(post.getUpvotes() + 1);
}

if (StringUtils.isNotBlank(post.getParentThreadId())) {
postRepository.findById(post.getParentThreadId()).ifPresent(thread -> {

thread.setNumberOfThreadUpvotes(thread.getNumberOfThreadUpvotes() - 1);
updatePostHowActiveScore(thread);
});
} else {
updatePostHowActiveScore(post);
}

postsCache.remove(topicId);

return PostTransferBean.of(postRepository.save(post));
Expand Down Expand Up @@ -2132,6 +2151,16 @@ public PostTransferBean unUpvotePost(String siteId, String postId) throws Conver
postStatusRepository.save(status);
post.setUpvotes(post.getUpvotes() - 1);

if (StringUtils.isNotBlank(post.getParentThreadId())) {
postRepository.findById(post.getParentThreadId()).ifPresent(thread -> {

thread.setNumberOfThreadUpvotes(thread.getNumberOfThreadUpvotes() - 1);
updatePostHowActiveScore(thread);
});
} else {
updatePostHowActiveScore(post);
}

postsCache.remove(post.getTopic().getId());

return PostTransferBean.of(postRepository.save(post));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,7 @@ export class SakaiPost extends reactionsAndUpvotingMixin(SakaiElement) {
<div class="discussion-post-right-column">
<div class="discussion-post-content-wrapper ${!this.post.viewed ? "new" : nothing }">
<div class="discussion-post-content-wrapper ${!this.post.viewed ? "new" : ""}">
<div id="post-${this.post.id}" class="discussion-post-content" data-post-id="${this.post.id}">
${this._renderAuthorDetails()}
<div>
Expand Down Expand Up @@ -656,10 +656,11 @@ export class SakaiPost extends reactionsAndUpvotingMixin(SakaiElement) {
<sakai-post
post="${JSON.stringify(p)}"
postType="${this.postType}"
?is-instructor="${this.isInstructor}"
?can-view-anonymous="${this.canViewAnonymous}"
?can-view-deleted="${this.canViewDeleted}"
site-id="${this.siteId}"
?is-instructor=${this.isInstructor}
?can-view-anonymous=${this.canViewAnonymous}
?can-view-deleted=${this.canViewDeleted}
?reactions-allowed=${this.reactionsAllowed}
@comment-deleted=${this._commentDeleted}>
</sakai-post>
`)}
Expand Down Expand Up @@ -705,31 +706,33 @@ export class SakaiPost extends reactionsAndUpvotingMixin(SakaiElement) {
${this._editing ? html`
${this._renderEditor()}
` : html`
${this.renderReactionsBar(this.post)}
<div class="mb-1 d-flex">
<div class="conversations-actions-block d-flex mb-1">
${this._renderReactionsBlock(this.post)}
${this._renderUpvoteBlock(this.post)}
</div>
<div class="ms-auto">
${this.post.numberOfComments > 0 ? html`
<a href="javascript:;"
aria-label="${this._showingComments ? this._i18n.hide_comments_tooltip : this._i18n.show_comments_tooltip}"
title="${this._showingComments ? this._i18n.hide_comments_tooltip : this._i18n.show_comments_tooltip}"
@click=${this._toggleShowingComments}>
<div class="d-flex ms-auto fs-6">
<div class="post-comment-toggle-icon">
<sakai-icon
type="${this._showingComments ? "chevron-down" : "chevron-up"}"
size="small">
</sakai-icon>
${this.reactionsAllowed ? html`
${this.renderReactionsBar(this.post)}
` : nothing}
<div class="mb-1 d-flex">
<div class="conversations-actions-block d-flex mb-1">
${this._renderReactionsBlock(this.post)}
${this._renderUpvoteBlock(this.post)}
</div>
<div class="ms-auto">
${this.post.numberOfComments > 0 ? html`
<a href="javascript:;"
aria-label="${this._showingComments ? this._i18n.hide_comments_tooltip : this._i18n.show_comments_tooltip}"
title="${this._showingComments ? this._i18n.hide_comments_tooltip : this._i18n.show_comments_tooltip}"
@click=${this._toggleShowingComments}>
<div class="d-flex ms-auto fs-6">
<div class="post-comment-toggle-icon">
<sakai-icon
type="${this._showingComments ? "chevron-down" : "chevron-up"}"
size="small">
</sakai-icon>
</div>
<div>${this.post.numberOfComments} ${this.post.numberOfComments == 1 ? this._i18n.comment : this._i18n.comments}</div>
</div>
<div>${this.post.numberOfComments} ${this.post.numberOfComments == 1 ? this._i18n.comment : this._i18n.comments}</div>
</div>
</a>
` : nothing }
</a>
` : nothing }
</div>
</div>
</div>
`}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,16 +83,7 @@ export class SakaiTopic extends reactionsAndUpvotingMixin(SakaiElement) {

this.myReactions = value.myReactions || {};

const sortAndUpdate = () => {

if (this.topic.type === QUESTION) {
this.topic.posts.sort((p1, p2) => {

if (p1.isInstructor && p2.isInstructor) return 0;
if (p1.isInstructor && !p2.isInstructor) return -1;
return 1;
});
}
const update = () => {

this.page = 0;

Expand Down Expand Up @@ -127,11 +118,11 @@ export class SakaiTopic extends reactionsAndUpvotingMixin(SakaiElement) {
// We've clicked on a topic and it has no posts. Ergo, it has been "viewed".
if (!this.topic.posts.length) this.topic.viewed = true;

sortAndUpdate();
update();
this.dispatchEvent(new CustomEvent("topic-updated", { detail: { topic: this.topic, dontUpdateCurrent: true }, bubbles: true }));
});
} else {
sortAndUpdate();
update();
}
}

Expand Down Expand Up @@ -759,18 +750,16 @@ export class SakaiTopic extends reactionsAndUpvotingMixin(SakaiElement) {
${!this.topic.continued ? html`
<div class="topic-posts-header">
<div>${this.topic.type === QUESTION ? this._i18n.answers : this._i18n.responses}</div>
${this.topic.type === DISCUSSION ? html`
<div>
<select @change=${this._postSortSelected}>
<option value="${SORT_OLDEST}">oldest</option>
<option value="${SORT_NEWEST}">most recent</option>
<option value="${SORT_ASC_CREATOR}">ascending author</option>
<option value="${SORT_DESC_CREATOR}">descending author</option>
<option value="${SORT_MOST_ACTIVE}">most active</option>
<option value="${SORT_LEAST_ACTIVE}">least active</option>
<option value="${SORT_OLDEST}">${this._i18n.oldest}</option>
<option value="${SORT_NEWEST}">${this._i18n.most_recent}</option>
<option value="${SORT_ASC_CREATOR}">${this._i18n.ascending_by_author}</option>
<option value="${SORT_DESC_CREATOR}">${this._i18n.descending_by_author}</option>
<option value="${SORT_MOST_ACTIVE}">${this._i18n.most_active}</option>
<option value="${SORT_LEAST_ACTIVE}">${this._i18n.least_active}</option>
</select>
</div>
` : nothing }
</div>
` : nothing }
Expand All @@ -787,10 +776,10 @@ export class SakaiTopic extends reactionsAndUpvotingMixin(SakaiElement) {
<sakai-post
post="${JSON.stringify(p)}"
postType="${this.topic.type}"
?is-instructor="${this.isInstructor}"
?can-view-anonymous="${this.canViewAnonymous}"
?can-view-deleted="${this.canViewDeleted}"
?reactions-allowed="${this.reactionsAllowed}"
?is-instructor=${this.isInstructor}
?can-view-anonymous=${this.canViewAnonymous}
?can-view-deleted=${this.canViewDeleted}
?reactions-allowed=${this.reactionsAllowed}
grading-item-id=${ifDefined(this.topic.gradingItemId)}
max-grade-points=${ifDefined(this.topic.gradingPoints)}
site-id="${this.topic.siteId}"
Expand Down

0 comments on commit 866e18f

Please sign in to comment.