From 506a5dc60797851dcc3a63649d7cee076236d5c1 Mon Sep 17 00:00:00 2001 From: Andrei Prigorshnev Date: Wed, 25 Aug 2021 20:57:27 +0400 Subject: [PATCH] FEATURE: improve "blank page syndrome" on the user notifications page (#14103) --- .../app/controllers/user-notifications.js | 27 ++++++++++++++++--- .../templates/user/notifications-index.hbs | 27 ++++++++++++------- .../tests/acceptance/notifications-test.js | 27 +++++++++++++++++++ config/locales/client.en.yml | 5 ++++ 4 files changed, 73 insertions(+), 13 deletions(-) diff --git a/app/assets/javascripts/discourse/app/controllers/user-notifications.js b/app/assets/javascripts/discourse/app/controllers/user-notifications.js index 3f2b3a47342..90ed44a99ab 100644 --- a/app/assets/javascripts/discourse/app/controllers/user-notifications.js +++ b/app/assets/javascripts/discourse/app/controllers/user-notifications.js @@ -1,6 +1,9 @@ import Controller, { inject as controller } from "@ember/controller"; import discourseComputed, { observes } from "discourse-common/utils/decorators"; import { ajax } from "discourse/lib/ajax"; +import { iconHTML } from "discourse-common/lib/icon-library"; +import getURL from "discourse-common/lib/get-url"; +import I18n from "I18n"; export default Controller.extend({ application: controller(), @@ -12,9 +15,9 @@ export default Controller.extend({ this.set("application.showFooter", !this.get("model.canLoadMore")); }, - @discourseComputed("model.content.length") - hasFilteredNotifications(length) { - return length > 0; + @discourseComputed("filter") + isFiltered() { + return this.filter && this.filter !== "all"; }, @discourseComputed("model.content.@each.read") @@ -24,6 +27,24 @@ export default Controller.extend({ ); }, + @discourseComputed("isFiltered", "model.content.length") + doesNotHaveNotifications(isFiltered, contentLength) { + return !isFiltered && contentLength === 0; + }, + + @discourseComputed("isFiltered", "model.content.length") + nothingFound(isFiltered, contentLength) { + return isFiltered && contentLength === 0; + }, + + @discourseComputed() + emptyStateBody() { + return I18n.t("user.no_notifications_page_body", { + preferencesUrl: getURL("/my/preferences/notifications"), + icon: iconHTML("bell"), + }).htmlSafe(); + }, + actions: { resetNew() { ajax("/notifications/mark-read", { type: "PUT" }).then(() => { diff --git a/app/assets/javascripts/discourse/app/templates/user/notifications-index.hbs b/app/assets/javascripts/discourse/app/templates/user/notifications-index.hbs index 14638f5f781..436f4fa2bc7 100644 --- a/app/assets/javascripts/discourse/app/templates/user/notifications-index.hbs +++ b/app/assets/javascripts/discourse/app/templates/user/notifications-index.hbs @@ -6,15 +6,22 @@ {{i18n "errors.desc.unknown"}} {{/if}} -{{/if}} - -
- {{notifications-filter value=filter onChange=(action (mut filter))}} -
- -{{#if hasFilteredNotifications}} - {{user-notifications-large notifications=model filter=filter}} - {{conditional-loading-spinner condition=loading}} +{{else if doesNotHaveNotifications}} +
+ {{i18n "user.no_notifications_page_title"}} +
+

{{emptyStateBody}}

+
+
{{else}} -
{{i18n "notifications.empty"}}
+
+ {{notifications-filter value=filter onChange=(action (mut filter))}} +
+ + {{#if nothingFound}} +
{{i18n "notifications.empty"}}
+ {{else}} + {{user-notifications-large notifications=model filter=filter}} + {{conditional-loading-spinner condition=loading}} + {{/if}} {{/if}} diff --git a/app/assets/javascripts/discourse/tests/acceptance/notifications-test.js b/app/assets/javascripts/discourse/tests/acceptance/notifications-test.js index 42946e0786e..53f00b9df23 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/notifications-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/notifications-test.js @@ -2,6 +2,7 @@ import { visit } from "@ember/test-helpers"; import { acceptance, count, + exists, publishToMessageBus, query, queryAll, @@ -198,3 +199,29 @@ acceptance("User Notifications", function (needs) { ]); }); }); + +acceptance( + "User Notifications - there is no notifications yet", + function (needs) { + needs.user(); + + needs.pretender((server, helper) => { + server.get("/notifications", () => { + return helper.response({ + notifications: [], + }); + }); + }); + + test("It renders the empty state panel", async function (assert) { + await visit("/u/eviltrout/notifications"); + assert.ok(exists("div.empty-state")); + }); + + test("It does not render filter", async function (assert) { + await visit("/u/eviltrout/notifications"); + + assert.notOk(exists("div.user-notifications-filter-select-kit")); + }); + } +); diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 96aba1a02ce..f88b8605738 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -1073,6 +1073,11 @@ en: You will be notified in this panel about activity directly relevant to you, including replies to your topics and posts, when someone @mentions you or quotes you, and replies to topics you are watching. Notifications will also be sent to your email when you haven’t logged in for a while.

Look for the %{icon} to decide which specific topics, categories and tags you want to be notified about. For more, see your notification preferences. + no_notifications_page_title: "You don’t have any notifications yet" + no_notifications_page_body: > + You will be notified about activity directly relevant to you, including replies to your topics and posts, when someone @mentions you or quotes you, and replies to topics you are watching. Notifications will also be sent to your email when you haven’t logged in for a while. +

+ Look for the %{icon} to decide which specific topics, categories and tags you want to be notified about. For more, see your notification preferences. first_notification: "Your first notification! Select it to begin." dynamic_favicon: "Show counts on browser icon" skip_new_user_tips: