FEATURE: Add review link to community section for logged in user (#18374)

When there are pending reviewables, the review section link is displayed
in the main section. When there are no pending reviewables, the review
section link is displayed under the more links drawer.

Internal ref: /t/74210
This commit is contained in:
Alan Guo Xiang Tan 2022-09-28 09:58:07 +08:00 committed by GitHub
parent bc97f3d1c1
commit 4b561277a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 192 additions and 28 deletions

View File

@ -151,11 +151,11 @@ export default Component.extend({
// "fast track" to update the current user's reviewable count before the message bus finds out.
if (performResult.reviewable_count !== undefined) {
this.currentUser.set(
"reviewable_count",
this.currentUser.updateReviewableCount(
performResult.reviewable_count
);
}
if (performResult.unseen_reviewable_count !== undefined) {
this.currentUser.set(
"unseen_reviewable_count",

View File

@ -1,5 +1,6 @@
import Component from "@glimmer/component";
import { inject as service } from "@ember/service";
import { tracked } from "@glimmer/tracking";
import {
customSectionLinks,
@ -13,29 +14,18 @@ export default class SidebarCommunitySection extends Component {
@service appEvents;
@service siteSettings;
@tracked sectionLinks;
@tracked moreSectionLinks;
@tracked moreSecondarySectionLinks;
callbackId;
headerActionsIcon;
headerActions;
sectionLinks;
moreSectionLinks;
moreSecondarySectionLinks;
callbackId;
constructor() {
super(...arguments);
this.moreSectionLinks = this.#initializeSectionLinks([
...this.defaultMoreSectionLinks,
...customSectionLinks,
]);
this.moreSecondarySectionLinks = this.#initializeSectionLinks([
...this.defaultMoreSecondarySectionLinks,
...secondaryCustomSectionLinks,
]);
this.sectionLinks = this.#initializeSectionLinks(
this.defaultMainSectionLinks
);
this.refreshSectionLinks();
this.callbackId = this.topicTrackingState.onStateChange(() => {
this.sectionLinks.forEach((sectionLink) => {
@ -64,6 +54,22 @@ export default class SidebarCommunitySection extends Component {
return [];
}
refreshSectionLinks() {
this.moreSectionLinks = this.#initializeSectionLinks([
...this.defaultMoreSectionLinks,
...customSectionLinks,
]);
this.moreSecondarySectionLinks = this.#initializeSectionLinks([
...this.defaultMoreSecondarySectionLinks,
...secondaryCustomSectionLinks,
]);
this.sectionLinks = this.#initializeSectionLinks(
this.defaultMainSectionLinks
);
}
#initializeSectionLinks(sectionLinkClasses) {
return sectionLinkClasses.reduce((links, sectionLinkClass) => {
const sectionLink = this.#initializeSectionLink(sectionLinkClass);

View File

@ -12,7 +12,7 @@
{{did-insert this.registerClickListener}}
{{will-destroy this.unregisterClickListener}} >
<div class="sidebar-more-section-link-details-content">
<div class="sidebar-more-section-links-details-content">
<div class="sidebar-more-section-links-details-content-main">
{{#each this.sectionLinks as |sectionLink|}}
<Sidebar::MoreSectionLink @sectionLink={{sectionLink}} />

View File

@ -1,5 +1,6 @@
import I18n from "I18n";
import { bind } from "discourse-common/utils/decorators";
import Composer from "discourse/models/composer";
import { getOwner } from "discourse-common/lib/get-owner";
import PermissionType from "discourse/models/permission-type";
@ -12,6 +13,7 @@ import AboutSectionLink from "discourse/lib/sidebar/common/community-section/abo
import FAQSectionLink from "discourse/lib/sidebar/common/community-section/faq-section-link";
import AdminSectionLink from "discourse/lib/sidebar/user/community-section/admin-section-link";
import BadgesSectionLink from "discourse/lib/sidebar/common/community-section/badges-section-link";
import ReviewSectionLink from "discourse/lib/sidebar/user/community-section/review-section-link";
import SidebarCommonCommunitySection from "discourse/components/sidebar/common/community-section";
import { action } from "@ember/object";
@ -29,19 +31,48 @@ export default class SidebarUserCommunitySection extends SidebarCommonCommunityS
title: I18n.t("sidebar.sections.community.header_action_title"),
},
];
this.appEvents.on(
"user-reviewable-count:changed",
this._refreshSectionLinks
);
}
willDestroy() {
this.appEvents.off(
"user-reviewable-count:changed",
this._refreshSectionLinks
);
}
@bind
_refreshSectionLinks() {
return this.refreshSectionLinks();
}
get defaultMainSectionLinks() {
return [
const links = [
EverythingSectionLink,
TrackedSectionLink,
MyPostsSectionLink,
AdminSectionLink,
];
if (this.currentUser.reviewable_count > 0) {
links.push(ReviewSectionLink);
}
return links;
}
get defaultMoreSectionLinks() {
return [GroupsSectionLink, UsersSectionLink, BadgesSectionLink];
const links = [GroupsSectionLink, UsersSectionLink, BadgesSectionLink];
if (this.currentUser.reviewable_count === 0) {
links.push(ReviewSectionLink);
}
return links;
}
get defaultMoreSecondarySectionLinks() {

View File

@ -28,10 +28,12 @@ export default {
const channel = user.enable_redesigned_user_menu
? `/reviewable_counts/${user.id}`
: "/reviewable_counts";
bus.subscribe(channel, (data) => {
if (data.reviewable_count >= 0) {
user.set("reviewable_count", data.reviewable_count);
user.updateReviewableCount(data.reviewable_count);
}
if (user.redesigned_user_menu_enabled) {
user.set("unseen_reviewable_count", data.unseen_reviewable_count);
}

View File

@ -0,0 +1,33 @@
import I18n from "I18n";
import BaseSectionLink from "discourse/lib/sidebar/base-community-section-link";
export default class ReviewSectionLink extends BaseSectionLink {
get name() {
return "review";
}
get route() {
return "review";
}
get title() {
return I18n.t("sidebar.sections.community.links.review.title");
}
get text() {
return I18n.t("sidebar.sections.community.links.review.content");
}
get shouldDisplay() {
return this.currentUser.can_review;
}
get badgeText() {
if (this.currentUser.reviewable_count > 0) {
return I18n.t("sidebar.sections.community.links.review.pending_count", {
count: this.currentUser.reviewable_count,
});
}
}
}

View File

@ -1059,6 +1059,11 @@ const User = RestModel.extend({
this.appEvents.trigger("user-drafts:changed");
},
updateReviewableCount(count) {
this.set("reviewable_count", count);
this.appEvents.trigger("user-reviewable-count:changed", count);
},
isInDoNotDisturb() {
return (
this.do_not_disturb_until &&

View File

@ -68,6 +68,7 @@ export default DiscourseRoute.extend({
const channel = this.currentUser.enable_redesigned_user_menu
? `/reviewable_counts/${this.currentUser.id}`
: "/reviewable_counts";
this.messageBus.subscribe(channel, (data) => {
if (data.updates) {
this.controller.reviewables.forEach((reviewable) => {
@ -82,10 +83,6 @@ export default DiscourseRoute.extend({
deactivate() {
this.messageBus.unsubscribe("/reviewable_claimed");
const channel = this.currentUser.enable_redesigned_user_menu
? `/reviewable_counts/${this.currentUser.id}`
: "/reviewable_counts";
this.messageBus.unsubscribe(channel);
},
@action

View File

@ -710,6 +710,86 @@ acceptance("Sidebar - Logged on user - Community Section", function (needs) {
);
});
test("review link is not shown when user cannot review", async function (assert) {
updateCurrentUser({ can_review: false });
await visit("/");
assert.notOk(
exists(".sidebar-section-community .sidebar-section-link-review"),
"review link is not shown"
);
await click(
".sidebar-section-community .sidebar-more-section-links-details-summary"
);
assert.notOk(
exists(".sidebar-section-community .sidebar-section-link-review"),
"review link is not shown"
);
});
test("review link when user can review", async function (assert) {
updateCurrentUser({
can_review: true,
reviewable_count: 0,
});
await visit("/reivew");
assert.notOk(
exists(".sidebar-section-community .sidebar-section-link-review.active"),
"review link is shown as active when visiting the review route even if there are no pending reviewables"
);
await visit("/");
assert.notOk(
exists(".sidebar-section-community .sidebar-section-link-review"),
"review link is not shown as part of the main section links"
);
await click(
".sidebar-section-community .sidebar-more-section-links-details-summary"
);
assert.ok(
exists(
".sidebar-section-community .sidebar-more-section-links-details-content .sidebar-section-link-review"
),
"review link is displayed in the more drawer"
);
await publishToMessageBus("/reviewable_counts", {
reviewable_count: 34,
});
assert.ok(
exists(".sidebar-section-community .sidebar-section-link-review"),
"review link is shown as part of the main section links"
);
assert.strictEqual(
query(
".sidebar-section-community .sidebar-section-link-review .sidebar-section-link-content-badge"
).textContent.trim(),
"34 pending",
"displays the pending reviewable count"
);
await click(
".sidebar-section-community .sidebar-more-section-links-details-summary"
);
assert.notOk(
exists(
".sidebar-section-community .sidebar-more-section-links-details-content .sidebar-section-link-review"
),
"review link is not displayed in the more drawer"
);
});
test("new and unread count for tracked link", async function (assert) {
const categories = Site.current().categories;

View File

@ -29,7 +29,7 @@
background: transparent;
}
.sidebar-more-section-link-details-content {
.sidebar-more-section-links-details-content {
background-color: var(--secondary);
box-shadow: shadow("dropdown");
margin: 0 calc(var(--d-sidebar-row-horizontal-padding) * 2 / 3);

View File

@ -71,6 +71,12 @@
}
}
.sidebar-section-link-review {
.sidebar-section-link-content-badge {
color: var(--danger);
}
}
.sidebar-section-link-prefix {
flex-shrink: 0;

View File

@ -4196,6 +4196,10 @@ en:
draft_count:
one: "%{count} draft"
other: "%{count} drafts"
review:
content: "Review"
title: "review"
pending_count: "%{count} pending"
welcome_topic_banner:
title: "Create your Welcome Topic"