DEV: Unify behavior of category and tag links in sidebar in new new view experiment (#20488)

Follow up to a509441148

This commit makes category and tag link in the sidebar consistent with the Everything link when the new New view experiment is enabled. In particular:

1. Category and tag links navigate to the per-category (or tag) `/new` view if there's at least one topic, and to `/latest` if there are no topics
2. Category and tag links only show the count of topics in `/new` without text
3. The Everything link navigates to the global `/new` view if there's at least one topic there, and to `/latest` if there are no topics in `/new`.

Internal topic: t/77234.
This commit is contained in:
Osama Sayegh 2023-03-03 17:52:02 +03:00 committed by GitHub
parent 6b0aeced7e
commit aad0d5fcfb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 562 additions and 19 deletions

View File

@ -9,7 +9,6 @@ export default class EverythingSectionLink extends BaseSectionLink {
@tracked totalNew = 0;
@tracked hideCount =
this.currentUser?.sidebarListDestination !== UNREAD_LIST_DESTINATION;
linkToNew = !!this.currentUser?.new_new_view_enabled;
constructor() {
super(...arguments);
@ -27,7 +26,7 @@ export default class EverythingSectionLink extends BaseSectionLink {
this.totalUnread = this.topicTrackingState.countUnread();
if (this.totalUnread === 0 || this.linkToNew) {
if (this.totalUnread === 0 || this.#linkToNew) {
this.totalNew = this.topicTrackingState.countNew();
}
}
@ -49,16 +48,15 @@ export default class EverythingSectionLink extends BaseSectionLink {
}
get currentWhen() {
if (this.linkToNew) {
return "discovery.new";
} else {
return "discovery.latest discovery.new discovery.unread discovery.top";
}
return "discovery.latest discovery.new discovery.unread discovery.top";
}
get badgeText() {
if (this.linkToNew && this.#unreadAndNewCount > 0) {
return this.#unreadAndNewCount.toString();
if (this.#linkToNew) {
if (this.#unreadAndNewCount > 0) {
return this.#unreadAndNewCount.toString();
}
return;
}
if (this.hideCount) {
return;
@ -75,8 +73,12 @@ export default class EverythingSectionLink extends BaseSectionLink {
}
get route() {
if (this.linkToNew) {
return "discovery.new";
if (this.#linkToNew) {
if (this.#unreadAndNewCount > 0) {
return "discovery.new";
} else {
return "discovery.latest";
}
} else if (
this.currentUser?.sidebarListDestination === UNREAD_LIST_DESTINATION
) {
@ -106,7 +108,7 @@ export default class EverythingSectionLink extends BaseSectionLink {
if (
this.hideCount &&
(this.totalUnread || this.totalNew) &&
!this.linkToNew
!this.#linkToNew
) {
return "circle";
}
@ -115,4 +117,8 @@ export default class EverythingSectionLink extends BaseSectionLink {
get #unreadAndNewCount() {
return this.totalUnread + this.totalNew;
}
get #linkToNew() {
return !!this.currentUser?.new_new_view_enabled;
}
}

View File

@ -7,6 +7,17 @@ import { bind } from "discourse-common/utils/decorators";
import Category from "discourse/models/category";
import { UNREAD_LIST_DESTINATION } from "discourse/controllers/preferences/sidebar";
const UNREAD_AND_NEW_COUNTABLE = {
propertyName: "unreadAndNewCount",
badgeTextFunction: (count) => count.toString(),
route: "discovery.newCategory",
refreshCountFunction: ({ topicTrackingState, category }) => {
return topicTrackingState.countNewAndUnread({
categoryId: category.id,
});
},
};
const DEFAULT_COUNTABLES = [
{
propertyName: "totalUnread",
@ -74,7 +85,13 @@ export default class CategorySectionLink {
}
#countables() {
const countables = [...DEFAULT_COUNTABLES];
const countables = [];
if (this.#linkToNew) {
countables.push(UNREAD_AND_NEW_COUNTABLE);
} else {
countables.push(...DEFAULT_COUNTABLES);
}
if (customCountables.length > 0) {
customCountables.forEach((customCountable) => {
@ -157,7 +174,7 @@ export default class CategorySectionLink {
}
get badgeText() {
if (this.hideCount) {
if (this.hideCount && !this.#linkToNew) {
return;
}
@ -171,7 +188,10 @@ export default class CategorySectionLink {
}
get route() {
if (this.currentUser?.sidebarListDestination === UNREAD_LIST_DESTINATION) {
if (
this.currentUser?.sidebarListDestination === UNREAD_LIST_DESTINATION ||
this.#linkToNew
) {
const activeCountable = this.activeCountable;
if (activeCountable) {
@ -201,8 +221,12 @@ export default class CategorySectionLink {
}
get suffixValue() {
if (this.hideCount && this.activeCountable) {
if (this.hideCount && this.activeCountable && !this.#linkToNew) {
return "circle";
}
}
get #linkToNew() {
return !!this.currentUser?.new_new_view_enabled;
}
}

View File

@ -25,7 +25,7 @@ export default class TagSectionLink extends BaseTagSectionLink {
tagId: this.tagName,
});
if (this.totalUnread === 0) {
if (this.totalUnread === 0 || this.#linkToNew) {
this.totalNew = this.topicTrackingState.countNew({
tagId: this.tagName,
});
@ -37,6 +37,13 @@ export default class TagSectionLink extends BaseTagSectionLink {
}
get route() {
if (this.#linkToNew) {
if (this.#unreadAndNewCount > 0) {
return "tag.showNew";
} else {
return "tag.show";
}
}
if (this.currentUser?.sidebarListDestination === UNREAD_LIST_DESTINATION) {
if (this.totalUnread > 0) {
return "tag.showUnread";
@ -53,6 +60,13 @@ export default class TagSectionLink extends BaseTagSectionLink {
}
get badgeText() {
if (this.#linkToNew) {
if (this.#unreadAndNewCount > 0) {
return this.#unreadAndNewCount.toString();
}
return;
}
if (this.hideCount) {
return;
}
@ -76,8 +90,20 @@ export default class TagSectionLink extends BaseTagSectionLink {
}
get suffixValue() {
if (this.hideCount && (this.totalUnread || this.totalNew)) {
if (
this.hideCount &&
(this.totalUnread || this.totalNew) &&
!this.#linkToNew
) {
return "circle";
}
}
get #unreadAndNewCount() {
return this.totalUnread + this.totalNew;
}
get #linkToNew() {
return !!this.currentUser?.new_new_view_enabled;
}
}

View File

@ -27,6 +27,10 @@ function isUnread(topic) {
);
}
function isNewOrUnread(topic) {
return isUnread(topic) || isNew(topic);
}
function isUnseen(topic) {
return !topic.is_seen;
}
@ -552,7 +556,22 @@ const TopicTrackingState = EmberObject.extend({
const mutedCategoryIds = this.currentUser?.muted_category_ids?.concat(
this.currentUser.indirectly_muted_category_ids
);
let filterFn = type === "new" ? isNew : isUnread;
let filterFn;
switch (type) {
case "new":
filterFn = isNew;
break;
case "unread":
filterFn = isUnread;
break;
case "new_and_unread":
case "unread_and_new":
filterFn = isNewOrUnread;
break;
default:
throw new Error(`Unkown filter type ${type}`);
}
return Array.from(this.states.values()).filter((topic) => {
if (!filterFn(topic)) {
@ -599,6 +618,21 @@ const TopicTrackingState = EmberObject.extend({
});
},
countNewAndUnread({
categoryId,
tagId,
noSubcategories,
customFilterFn,
} = {}) {
return this.countCategoryByState({
type: "new_and_unread",
categoryId,
tagId,
noSubcategories,
customFilterFn,
});
},
/**
* Calls the provided callback for each of the currently tracked topics
* we have in state.

View File

@ -947,3 +947,171 @@ acceptance("Sidebar - Logged on user - Categories Section", function (needs) {
);
});
});
acceptance(
"Sidebar - Logged on user - Categories Section - New new view experiment enabled",
function (needs) {
needs.settings({
navigation_menu: "sidebar",
});
needs.user({ new_new_view_enabled: true });
test("count shown next to category link", async function (assert) {
const categories = Site.current().categories;
const category1 = categories[0];
const category2 = categories[1];
const category3 = categories[2];
updateCurrentUser({
sidebar_category_ids: [category1.id, category2.id, category3.id],
});
this.container.lookup("service:topic-tracking-state").loadStates([
{
topic_id: 1,
highest_post_number: 1,
last_read_post_number: null,
created_at: "2022-05-11T03:09:31.959Z",
category_id: category1.id,
notification_level: null,
created_in_new_period: true,
treat_as_new_topic_start_date: "2022-05-09T03:17:34.286Z",
},
{
topic_id: 2,
highest_post_number: 12,
last_read_post_number: 11,
created_at: "2020-02-09T09:40:02.672Z",
category_id: category1.id,
notification_level: 2,
created_in_new_period: false,
treat_as_new_topic_start_date: "2022-05-09T03:17:34.286Z",
},
{
topic_id: 3,
highest_post_number: 15,
last_read_post_number: 15,
created_at: "2021-06-14T12:41:02.477Z",
category_id: category1.id,
notification_level: 2,
created_in_new_period: false,
treat_as_new_topic_start_date: "2022-05-09T03:17:34.286Z",
},
{
topic_id: 4,
highest_post_number: 10,
last_read_post_number: null,
created_at: "2022-05-11T03:09:31.959Z",
category_id: category2.id,
notification_level: null,
created_in_new_period: true,
treat_as_new_topic_start_date: "2022-05-09T03:17:34.286Z",
},
{
topic_id: 5,
highest_post_number: 19,
last_read_post_number: 18,
created_at: "2021-06-14T12:41:02.477Z",
category_id: category3.id,
notification_level: 2,
created_in_new_period: false,
treat_as_new_topic_start_date: "2022-05-09T03:17:34.286Z",
},
]);
await visit("/");
assert.strictEqual(
query(
`.sidebar-section-link[data-category-id="${category1.id}"] .sidebar-section-link-content-badge`
).textContent.trim(),
"2",
"count for category1 is 2 because it has 1 unread topic and 1 new topic"
);
assert.strictEqual(
query(
`.sidebar-section-link[data-category-id="${category2.id}"] .sidebar-section-link-content-badge`
).textContent.trim(),
"1",
"count for category2 is 1 because it has 1 new topic"
);
assert.strictEqual(
query(
`.sidebar-section-link[data-category-id="${category3.id}"] .sidebar-section-link-content-badge`
).textContent.trim(),
"1",
"count for category3 is 1 because it has 1 unread topic"
);
});
test("category link href", async function (assert) {
const categories = Site.current().categories;
const category1 = categories[0];
const category2 = categories[1];
const category3 = categories[2];
updateCurrentUser({
sidebar_category_ids: [category1.id, category2.id, category3.id],
});
this.container.lookup("service:topic-tracking-state").loadStates([
{
topic_id: 1,
highest_post_number: 1,
last_read_post_number: null,
created_at: "2022-05-11T03:09:31.959Z",
category_id: category1.id,
notification_level: null,
created_in_new_period: true,
treat_as_new_topic_start_date: "2022-05-09T03:17:34.286Z",
},
{
topic_id: 2,
highest_post_number: 12,
last_read_post_number: 11,
created_at: "2020-02-09T09:40:02.672Z",
category_id: category2.id,
notification_level: 2,
created_in_new_period: false,
treat_as_new_topic_start_date: "2022-05-09T03:17:34.286Z",
},
{
topic_id: 3,
highest_post_number: 4,
last_read_post_number: 4,
created_at: "2020-02-09T09:40:02.672Z",
category_id: category3.id,
notification_level: 2,
created_in_new_period: false,
treat_as_new_topic_start_date: "2022-05-09T03:17:34.286Z",
},
]);
await visit("/");
assert.true(
query(
`.sidebar-section-link[data-category-id="${category1.id}"]`
).href.endsWith("/c/meta/3/l/new"),
"links to the new topics list for the category because there's 1 new topic"
);
assert.true(
query(
`.sidebar-section-link[data-category-id="${category2.id}"]`
).href.endsWith("/c/howto/10/l/new"),
"links to the new topics list for the category because there's 1 unread topic"
);
assert.true(
query(
`.sidebar-section-link[data-category-id="${category3.id}"]`
).href.endsWith("/c/feature/spec/26"),
"links to the latest topics list for the category because there are no unread or new topics"
);
});
}
);

View File

@ -1037,3 +1037,143 @@ acceptance("Sidebar - Logged on user - Community Section", function (needs) {
assert.ok(teardownCalled, "section link teardown callback was called");
});
});
acceptance(
"Sidebar - Logged on user - Community Section - New new view experiment enabled",
function (needs) {
needs.user({
new_new_view_enabled: true,
});
needs.settings({
navigation_menu: "sidebar",
});
test("count shown next to the everything link", async function (assert) {
this.container.lookup("service:topic-tracking-state").loadStates([
{
topic_id: 1,
highest_post_number: 1,
last_read_post_number: null,
created_at: "2022-05-11T03:09:31.959Z",
category_id: 1,
notification_level: null,
created_in_new_period: true,
treat_as_new_topic_start_date: "2022-05-09T03:17:34.286Z",
},
{
topic_id: 2,
highest_post_number: 12,
last_read_post_number: 11,
created_at: "2020-02-09T09:40:02.672Z",
category_id: 2,
notification_level: 2,
created_in_new_period: false,
treat_as_new_topic_start_date: "2022-05-09T03:17:34.286Z",
},
{
topic_id: 3,
highest_post_number: 12,
last_read_post_number: 12,
created_at: "2020-02-09T09:40:02.672Z",
category_id: 2,
notification_level: 2,
created_in_new_period: false,
treat_as_new_topic_start_date: "2022-05-09T03:17:34.286Z",
},
]);
await visit("/");
assert.strictEqual(
query(
".sidebar-section-community .sidebar-section-link-everything .sidebar-section-link-content-badge"
).textContent.trim(),
"2",
"count is 2 because there's 1 unread topic and 1 new topic"
);
});
test("everything link href", async function (assert) {
this.container.lookup("service:topic-tracking-state").loadStates([
{
topic_id: 1,
highest_post_number: 1,
last_read_post_number: null,
created_at: "2022-05-11T03:09:31.959Z",
category_id: 1,
notification_level: null,
created_in_new_period: true,
treat_as_new_topic_start_date: "2022-05-09T03:17:34.286Z",
},
{
topic_id: 2,
highest_post_number: 12,
last_read_post_number: 11,
created_at: "2020-02-09T09:40:02.672Z",
category_id: 2,
notification_level: 2,
created_in_new_period: false,
treat_as_new_topic_start_date: "2022-05-09T03:17:34.286Z",
},
]);
await visit("/");
assert.true(
query(
".sidebar-section-community .sidebar-section-link-everything"
).href.endsWith("/new"),
"links to /new because there are 1 new and 1 unread topics"
);
await publishToMessageBus("/unread", {
topic_id: 1,
message_type: "read",
payload: {
last_read_post_number: 3,
highest_post_number: 3,
},
});
assert.true(
query(
".sidebar-section-community .sidebar-section-link-everything"
).href.endsWith("/new"),
"links to /new because there is 1 unread topic"
);
await publishToMessageBus("/unread", {
topic_id: 2,
message_type: "read",
payload: {
last_read_post_number: 12,
highest_post_number: 12,
},
});
assert.true(
query(
".sidebar-section-community .sidebar-section-link-everything"
).href.endsWith("/latest"),
"links to /latest because there are no unread or new topics"
);
await publishToMessageBus("/unread", {
topic_id: 1,
message_type: "read",
payload: {
last_read_post_number: null,
highest_post_number: 34,
},
});
assert.true(
query(
".sidebar-section-community .sidebar-section-link-everything"
).href.endsWith("/new"),
"links to /new because there is 1 new topic"
);
});
}
);

View File

@ -657,3 +657,148 @@ acceptance("Sidebar - Logged on user - Tags section", function (needs) {
);
});
});
acceptance(
"Sidebar - Logged on user - Tags section - New new view enabled",
function (needs) {
needs.settings({
tagging_enabled: true,
navigation_menu: "sidebar",
});
needs.user({
new_new_view_enabled: true,
display_sidebar_tags: true,
sidebar_tags: [
{ name: "tag2", pm_only: false },
{ name: "tag1", pm_only: false },
{ name: "tag3", pm_only: false },
],
});
test("count shown next to tag link", async function (assert) {
this.container.lookup("service:topic-tracking-state").loadStates([
{
topic_id: 1,
highest_post_number: 1,
last_read_post_number: null,
created_at: "2022-05-11T03:09:31.959Z",
category_id: 1,
notification_level: null,
created_in_new_period: true,
treat_as_new_topic_start_date: "2022-05-09T03:17:34.286Z",
tags: ["tag1", "tag3"],
},
{
topic_id: 2,
highest_post_number: 12,
last_read_post_number: 11,
created_at: "2020-02-09T09:40:02.672Z",
category_id: 2,
notification_level: 2,
created_in_new_period: false,
treat_as_new_topic_start_date: "2022-05-09T03:17:34.286Z",
tags: ["tag1", "tag2"],
},
{
topic_id: 3,
highest_post_number: 15,
last_read_post_number: 15,
created_at: "2021-06-14T12:41:02.477Z",
category_id: 3,
notification_level: 2,
created_in_new_period: false,
treat_as_new_topic_start_date: "2022-05-09T03:17:34.286Z",
tags: ["tag1"],
},
]);
await visit("/");
assert.strictEqual(
query(
'.sidebar-section-link[data-tag-name="tag1"] .sidebar-section-link-content-badge'
).textContent.trim(),
"2",
"count for tag1 is 2 because it has 1 unread topic and 1 new topic"
);
assert.strictEqual(
query(
'.sidebar-section-link[data-tag-name="tag2"] .sidebar-section-link-content-badge'
).textContent.trim(),
"1",
"count for tag2 is 1 because it has 1 unread topic"
);
assert.strictEqual(
query(
'.sidebar-section-link[data-tag-name="tag3"] .sidebar-section-link-content-badge'
).textContent.trim(),
"1",
"count for tag3 is 1 because it has 1 new topic"
);
});
test("tag link href", async function (assert) {
this.container.lookup("service:topic-tracking-state").loadStates([
{
topic_id: 1,
highest_post_number: 1,
last_read_post_number: null,
created_at: "2022-05-11T03:09:31.959Z",
category_id: 1,
notification_level: null,
created_in_new_period: true,
treat_as_new_topic_start_date: "2022-05-09T03:17:34.286Z",
tags: ["tag1"],
},
{
topic_id: 2,
highest_post_number: 12,
last_read_post_number: 11,
created_at: "2020-02-09T09:40:02.672Z",
category_id: 2,
notification_level: 2,
created_in_new_period: false,
treat_as_new_topic_start_date: "2022-05-09T03:17:34.286Z",
tags: ["tag2"],
},
{
topic_id: 3,
highest_post_number: 15,
last_read_post_number: 15,
created_at: "2021-06-14T12:41:02.477Z",
category_id: 3,
notification_level: 2,
created_in_new_period: false,
treat_as_new_topic_start_date: "2022-05-09T03:17:34.286Z",
tags: ["tag3"],
},
]);
await visit("/");
assert.true(
query('.sidebar-section-link[data-tag-name="tag1"]').href.endsWith(
"/tag/tag1/l/new"
),
"links to the new topics list for the tag because there's 1 new topic"
);
assert.true(
query('.sidebar-section-link[data-tag-name="tag2"]').href.endsWith(
"/tag/tag2/l/new"
),
"links to the new topics list for the tag because there's 1 unread topic"
);
assert.true(
query('.sidebar-section-link[data-tag-name="tag3"]').href.endsWith(
"/tag/tag3"
),
"links to the latest topics list for the tag because there are no unread or new topics"
);
});
}
);