FEATURE: improve "blank page syndrome" on the user notifications page (#14103)

FEATURE: improve “blank page syndrome” on the user notifications page (#14103)

diff --git a/app/assets/javascripts/discourse/app/controllers/user-notifications.js b/app/assets/javascripts/discourse/app/controllers/user-notifications.js
index 3f2b3a4..90ed44a 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 14638f5..436f4fa 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}}
   </div>
-{{/if}}
-
-<div class="user-notifications-filter-select-kit">
-  {{notifications-filter value=filter onChange=(action (mut filter))}}
-</div>
-
-{{#if hasFilteredNotifications}}
-  {{user-notifications-large notifications=model filter=filter}}
-  {{conditional-loading-spinner condition=loading}}
+{{else if doesNotHaveNotifications}}
+  <div class="empty-state">
+    <span class="empty-state-title">{{i18n "user.no_notifications_page_title"}}</span>
+    <div class="empty-state-body">
+      <p>{{emptyStateBody}}</p>
+    </div>
+  </div>
 {{else}}
-  <div class="alert alert-info">{{i18n "notifications.empty"}}</div>
+  <div class="user-notifications-filter-select-kit">
+    {{notifications-filter value=filter onChange=(action (mut filter))}}
+  </div>
+
+  {{#if nothingFound}}
+    <div class="alert alert-info">{{i18n "notifications.empty"}}</div>
+  {{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 42946e0..53f00b9 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 96aba1a..f88b860 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 <b>@mentions</b> 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.
         <br><br>
         Look for the %{icon} to decide which specific topics, categories and tags you want to be notified about. For more, see your <a href='%{preferencesUrl}'>notification preferences</a>.
+      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 <b>@mentions</b> 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.
+        <br><br>
+        Look for the %{icon} to decide which specific topics, categories and tags you want to be notified about. For more, see your <a href='%{preferencesUrl}'>notification preferences</a>.
       first_notification: "Your first notification! Select it to begin."
       dynamic_favicon: "Show counts on browser icon"
       skip_new_user_tips:

GitHub sha: 506a5dc60797851dcc3a63649d7cee076236d5c1

This commit appears in #14103 which was approved by jjaffeux. It was merged by AndrewPrigorshnev.