FIX: empty state message on the user bookmarks page (#14257)

FIX: empty state message on the user bookmarks page (#14257)

After adding an empty state banner to the user bookmarks page, we have found the bug. Steps to reproduce:

  • Go to the user bookmarks page
  • Search for something that doesn’t exist in bookmarks
  • Click again Bookmarked on the sidebar or View All Bookmarks on the user menu again
diff --git a/app/assets/javascripts/discourse/app/controllers/user-activity-bookmarks.js b/app/assets/javascripts/discourse/app/controllers/user-activity-bookmarks.js
index c80cfc0..2ee0251 100644
--- a/app/assets/javascripts/discourse/app/controllers/user-activity-bookmarks.js
+++ b/app/assets/javascripts/discourse/app/controllers/user-activity-bookmarks.js
@@ -3,42 +3,31 @@ import { iconHTML } from "discourse-common/lib/icon-library";
 import Bookmark from "discourse/models/bookmark";
 import I18n from "I18n";
 import { Promise } from "rsvp";
-import EmberObject, { action } from "@ember/object";
+import EmberObject, { action, computed } from "@ember/object";
 import discourseComputed from "discourse-common/utils/decorators";
-import { notEmpty } from "@ember/object/computed";
+import { equal, notEmpty } from "@ember/object/computed";
+import { ajax } from "discourse/lib/ajax";
 
 export default Controller.extend({
   queryParams: ["q"],
+  q: null,
 
   application: controller(),
   user: controller(),
-
-  content: null,
   loading: false,
+  loadingMore: false,
   permissionDenied: false,
-  searchTerm: null,
-  q: null,
   inSearchMode: notEmpty("q"),
+  noContent: equal("model.bookmarks.length", 0),
 
-  loadItems() {
-    this.setProperties({
-      content: [],
-      loading: true,
-      permissionDenied: false,
-      searchTerm: this.q,
-    });
-
-    return this.model
-      .loadItems({ q: this.q })
-      .then((response) => this._processLoadResponse(response))
-      .catch(() => this._bookmarksListDenied())
-      .finally(() => {
-        this.setProperties({
-          loaded: true,
-          loading: false,
-        });
-      });
-  },
+  searchTerm: computed("q", {
+    get() {
+      return this.q;
+    },
+    set(key, value) {
+      return value;
+    },
+  }),
 
   @discourseComputed()
   emptyStateBody() {
@@ -57,20 +46,16 @@ export default Controller.extend({
     return inSearchMode && noContent;
   },
 
-  @discourseComputed("loaded", "content.length")
-  noContent(loaded, contentLength) {
-    return loaded && contentLength === 0;
-  },
-
   @action
   search() {
-    this.set("q", this.searchTerm);
-    this.loadItems();
+    this.transitionToRoute({
+      queryParams: { q: this.searchTerm },
+    });
   },
 
   @action
   reload() {
-    this.loadItems();
+    this.send("triggerRefresh");
   },
 
   @action
@@ -81,13 +66,27 @@ export default Controller.extend({
 
     this.set("loadingMore", true);
 
-    return this.model
-      .loadMore({ q: this.q })
+    return this._loadMoreBookmarks(this.q)
       .then((response) => this._processLoadResponse(response))
       .catch(() => this._bookmarksListDenied())
       .finally(() => this.set("loadingMore", false));
   },
 
+  _loadMoreBookmarks(searchQuery) {
+    if (!this.model.loadMoreUrl) {
+      return Promise.resolve();
+    }
+
+    let moreUrl = this.model.loadMoreUrl;
+    if (searchQuery) {
+      const delimiter = moreUrl.includes("?") ? "&" : "?";
+      const q = encodeURIComponent(searchQuery);
+      moreUrl += `${delimiter}q=${q}`;
+    }
+
+    return ajax({ url: moreUrl });
+  },
+
   _bookmarksListDenied() {
     this.set("permissionDenied", true);
   },
@@ -98,22 +97,24 @@ export default Controller.extend({
     }
 
     response = response.user_bookmark_list;
-    this.model.more_bookmarks_url = response.more_bookmarks_url;
+    this.model.loadMoreUrl = response.more_bookmarks_url;
 
     if (response.bookmarks) {
-      const bookmarkModels = response.bookmarks.map((bookmark) => {
-        const bookmarkModel = Bookmark.create(bookmark);
-        bookmarkModel.topicStatus = EmberObject.create({
-          closed: bookmark.closed,
-          archived: bookmark.archived,
-          is_warning: bookmark.is_warning,
-          pinned: false,
-          unpinned: false,
-          invisible: bookmark.invisible,
-        });
-        return bookmarkModel;
-      });
-      this.content.pushObjects(bookmarkModels);
+      const bookmarkModels = response.bookmarks.map(this.transform);
+      this.model.bookmarks.pushObjects(bookmarkModels);
     }
   },
+
+  transform(bookmark) {
+    const bookmarkModel = Bookmark.create(bookmark);
+    bookmarkModel.topicStatus = EmberObject.create({
+      closed: bookmark.closed,
+      archived: bookmark.archived,
+      is_warning: bookmark.is_warning,
+      pinned: false,
+      unpinned: false,
+      invisible: bookmark.invisible,
+    });
+    return bookmarkModel;
+  },
 });
diff --git a/app/assets/javascripts/discourse/app/models/bookmark.js b/app/assets/javascripts/discourse/app/models/bookmark.js
index 97d45b2..735e7d0 100644
--- a/app/assets/javascripts/discourse/app/models/bookmark.js
+++ b/app/assets/javascripts/discourse/app/models/bookmark.js
@@ -141,40 +141,6 @@ const Bookmark = RestModel.extend({
     });
   },
 
-  loadItems(params) {
-    let url = `/u/${this.user.username}/bookmarks.json`;
-
-    if (params) {
-      url += "?" + $.param(params);
-    }
-
-    return ajax(url);
-  },
-
-  loadMore(additionalParams) {
-    if (!this.more_bookmarks_url) {
-      return Promise.resolve();
-    }
-
-    let moreUrl = this.more_bookmarks_url;
-    if (moreUrl) {
-      let [url, params] = moreUrl.split("?");
-      moreUrl = url;
-      if (params) {
-        moreUrl += "?" + params;
-      }
-      if (additionalParams) {
-        if (moreUrl.includes("?")) {
-          moreUrl += "&" + $.param(additionalParams);
-        } else {
-          moreUrl += "?" + $.param(additionalParams);
-        }
-      }
-    }
-
-    return ajax({ url: moreUrl });
-  },
-
   @discourseComputed(
     "post_user_username",
     "post_user_avatar_template",
diff --git a/app/assets/javascripts/discourse/app/routes/user-activity-bookmarks.js b/app/assets/javascripts/discourse/app/routes/user-activity-bookmarks.js
index 00ae1a9..a5e4be7 100644
--- a/app/assets/javascripts/discourse/app/routes/user-activity-bookmarks.js
+++ b/app/assets/javascripts/discourse/app/routes/user-activity-bookmarks.js
@@ -1,27 +1,63 @@
 import DiscourseRoute from "discourse/routes/discourse";
+import { ajax } from "discourse/lib/ajax";
+import { action } from "@ember/object";
 
 export default DiscourseRoute.extend({
   queryParams: {
     acting_username: { refreshModel: true },
+    q: { refreshModel: true },
   },
 
-  model() {
-    return this.modelFor("user").get("bookmarks");
+  model(params) {
+    const controller = this.controllerFor("user-activity-bookmarks");
+
+    return this._loadBookmarks(params)
+      .then((response) => {
+        if (!response.user_bookmark_list) {
+          return { bookmarks: [] };
+        }
+
+        const bookmarks = response.user_bookmark_list.bookmarks.map(
+          controller.transform
+        );
+        const loadMoreUrl = response.user_bookmark_list.more_bookmarks_url;
+
+        return { bookmarks, loadMoreUrl };
+      })
+      .catch(() => controller.set("permissionDenied", true));
   },
 
   renderTemplate() {
     this.render("user_bookmarks");
   },
 
-  setupController(controller, model) {
-    controller.set("model", model);
-    controller.loadItems();
+  @action
+  didTransition() {
+    this.controllerFor("user-activity")._showFooter();
+    return true;
+  },
+
+  @action
+  loading(transition) {
+    let controller = this.controllerFor("user-activity-bookmarks");
+    controller.set("loading", true);
+    transition.promise.finally(function () {
+      controller.set("loading", false);
+    });
   },
 
-  actions: {
-    didTransition() {
-      this.controllerFor("user-activity")._showFooter();
-      return true;
-    },
+  @action
+  triggerRefresh() {
+    this.refresh();
+  },
+
+  _loadBookmarks(params) {
+    let url = `/u/${this.modelFor("user").username}/bookmarks.json`;
+
+    if (params) {
+      url += "?" + $.param(params);
+    }
+
+    return ajax(url);
   },
 });

[... diff too long, it was truncated ...]

GitHub sha: 9f626f27356b0f623c9b4b1b55c077eea286e2ad

This commit appears in #14257 which was approved by martin. It was merged by AndrewPrigorshnev.