FEATURE: Unseen feature indicator in admin sidebar (#28397)

This commit adds a blue dot next to the "What's New"
link in the admin sidebar if the user has not seen the
new features yet, as a followup to 3e5976f843
which removed the tab on the dashboard that had this same
functionality.

When the admin visits the "What's New" page they count
as having seen all the features straight away. This could
be something we want to change, but for now this keeps the
same functionality.
This commit is contained in:
Martin Brennan 2024-08-19 14:50:30 +10:00 committed by GitHub
parent 32195ed77e
commit 31a6d24053
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 92 additions and 5 deletions

View File

@ -0,0 +1,10 @@
import { inject as service } from "@ember/service";
import DiscourseRoute from "discourse/routes/discourse";
export default class AdminWhatsNew extends DiscourseRoute {
@service currentUser;
activate() {
this.currentUser.set("has_unseen_features", false);
}
}

View File

@ -19,9 +19,15 @@ export function clearAdditionalAdminSidebarSectionLinks() {
}
class SidebarAdminSectionLink extends BaseCustomSidebarSectionLink {
constructor({ adminSidebarNavLink, adminSidebarStateManager, router }) {
constructor({
adminSidebarNavLink,
adminSidebarStateManager,
router,
currentUser,
}) {
super(...arguments);
this.router = router;
this.currentUser = currentUser;
this.adminSidebarNavLink = adminSidebarNavLink;
this.adminSidebarStateManager = adminSidebarStateManager;
}
@ -90,12 +96,38 @@ class SidebarAdminSectionLink extends BaseCustomSidebarSectionLink {
}
);
}
get suffixType() {
if (this.#hasUnseenFeatures) {
return "icon";
}
}
get suffixValue() {
if (this.#hasUnseenFeatures) {
return "circle";
}
}
get suffixCSSClass() {
if (this.#hasUnseenFeatures) {
return "admin-sidebar-nav-link__dot";
}
}
get #hasUnseenFeatures() {
return (
this.adminSidebarNavLink.name === "admin_whats_new" &&
this.currentUser.hasUnseenFeatures
);
}
}
function defineAdminSection(
adminNavSectionData,
adminSidebarStateManager,
router
router,
currentUser
) {
const AdminNavSection = class extends BaseCustomSidebarSection {
constructor() {
@ -130,6 +162,7 @@ function defineAdminSection(
adminSidebarNavLink: sectionLinkData,
adminSidebarStateManager: this.adminSidebarStateManager,
router,
currentUser,
})
);
}
@ -349,7 +382,8 @@ export default class AdminSidebarPanel extends BaseCustomSidebarPanel {
return defineAdminSection(
adminNavSectionData,
this.adminSidebarStateManager,
router
router,
currentUser
);
});
}

View File

@ -250,6 +250,11 @@ export default class User extends RestModel.extend(Evented) {
// prevents staff property to be overridden
set staff(value) {}
@computed("has_unseen_features")
get hasUnseenFeatures() {
return this.staff && this.get("has_unseen_features");
}
destroySession() {
return ajax(`/session/${this.username}`, { type: "DELETE" });
}

View File

@ -4,3 +4,7 @@
font-weight: bold;
}
}
.admin-sidebar-nav-link__dot {
color: var(--tertiary-med-or-tertiary);
}

View File

@ -77,7 +77,8 @@ class CurrentUserSerializer < BasicUserSerializer
:can_view_raw_email,
:use_glimmer_topic_list?,
:login_method,
:render_experimental_about_page
:render_experimental_about_page,
:has_unseen_features
delegate :user_stat, to: :object, private: true
delegate :any_posts, :draft_count, :pending_posts_count, :read_faq?, to: :user_stat
@ -142,6 +143,14 @@ class CurrentUserSerializer < BasicUserSerializer
object.staff?
end
def has_unseen_features
DiscourseUpdates.has_unseen_features?(object.id)
end
def include_has_unseen_features?
object.staff?
end
def render_experimental_about_page
object.in_any_groups?(SiteSetting.experimental_redesigned_about_page_groups_map)
end

View File

@ -2,9 +2,17 @@
describe "Admin New Features Page", type: :system do
let(:new_features_page) { PageObjects::Pages::AdminNewFeatures.new }
let(:sidebar) { PageObjects::Components::NavigationMenu::Sidebar.new }
fab!(:admin)
before { sign_in(admin) }
before do
SiteSetting.navigation_menu = "sidebar"
SiteSetting.admin_sidebar_enabled_groups = [
Group::AUTO_GROUPS[:admins],
Group::AUTO_GROUPS[:moderators],
]
sign_in(admin)
end
it "displays new features with screenshot taking precedence over emoji" do
DiscourseUpdates.stubs(:new_features).returns(
@ -81,4 +89,17 @@ describe "Admin New Features Page", type: :system do
expect(new_features_page).to have_emoji
expect(new_features_page).to have_no_screenshot
end
it "displays a new feature indicator on the sidebar and clears it when navigating to what's new" do
DiscourseUpdates.stubs(:has_unseen_features?).returns(true)
visit "/admin"
sidebar.toggle_all_sections
expect(sidebar.find_section_link("admin_whats_new")).to have_css(
".sidebar-section-link-suffix.admin-sidebar-nav-link__dot",
)
sidebar.find_section_link("admin_whats_new").click
expect(sidebar.find_section_link("admin_whats_new")).to have_no_css(
".sidebar-section-link-suffix.admin-sidebar-nav-link__dot",
)
end
end

View File

@ -132,6 +132,10 @@ module PageObjects
expect(section_link["title"]).to eq(title)
end
def find_section_link(name)
find(".#{SIDEBAR_SECTION_LINK_SELECTOR}[data-link-name='#{name}']")
end
def primary_section_links(slug)
all("[data-section-name='#{slug}'] .sidebar-section-link-wrapper").map(&:text)
end