FEATURE: Add search to user bookmark list (#10230)

User bookmarks can now be searched by name or post raw content. The q querystring param is hooked up from the Ember router as well.
This commit is contained in:
Martin Brennan 2020-07-14 14:43:41 +10:00 committed by GitHub
parent f4f3e8c401
commit bcc80e0ea8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 78 additions and 8 deletions

View File

@ -14,6 +14,10 @@ export default Controller.extend({
content: null,
loading: false,
noResultsHelp: null,
searchTerm: null,
q: null,
queryParams: ["q"],
loadItems() {
this.setProperties({
@ -22,8 +26,12 @@ export default Controller.extend({
noResultsHelp: null
});
if (this.q && !this.searchTerm) {
this.set("searchTerm", this.q);
}
return this.model
.loadItems()
.loadItems({ q: this.searchTerm })
.then(response => this._processLoadResponse(response))
.catch(() => this._bookmarksListDenied())
.finally(() =>
@ -43,6 +51,12 @@ export default Controller.extend({
this.content.removeObject(bookmark);
},
@action
search() {
this.set("q", this.searchTerm);
this.loadItems();
},
@action
removeBookmark(bookmark) {
const deleteBookmark = () => {
@ -86,7 +100,7 @@ export default Controller.extend({
this.set("loadingMore", true);
return this.model
.loadMore()
.loadMore({ q: this.searchTerm })
.then(response => this._processLoadResponse(response))
.catch(() => this._bookmarksListDenied())
.finally(() => this.set("loadingMore", false));

View File

@ -120,11 +120,17 @@ const Bookmark = RestModel.extend({
).capitalize();
},
loadItems() {
return ajax(`/u/${this.user.username}/bookmarks.json`, { cache: "false" });
loadItems(params) {
let url = `/u/${this.user.username}/bookmarks.json`;
if (params) {
url += "?" + $.param(params);
}
return ajax(url, { cache: "false" });
},
loadMore() {
loadMore(additionalParams) {
if (!this.more_bookmarks_url) {
return Promise.resolve();
}
@ -136,7 +142,15 @@ const Bookmark = RestModel.extend({
if (params) {
moreUrl += "?" + params;
}
if (additionalParams) {
if (moreUrl.includes("?")) {
moreUrl += "&" + $.param(additionalParams);
} else {
moreUrl += "?" + $.param(additionalParams);
}
}
}
return ajax({ url: moreUrl });
},

View File

@ -1,6 +1,10 @@
import DiscourseRoute from "discourse/routes/discourse";
export default DiscourseRoute.extend({
queryParams: {
q: { replace: true }
},
redirect() {
this.transitionTo("userActivity.bookmarks");
}

View File

@ -1,3 +1,15 @@
<div class="form-horizontal" style="margin-bottom: 1em">
{{input type="text"
value=searchTerm
placeholder=(i18n "bookmarks.search_placeholder")
enter=(action "search")
id="bookmark-search" autocomplete="discourse"}}
{{d-button
class="btn-primary"
action=(action "search")
type="button"
label="bookmarks.search"}}
</div>
{{#if noContent}}
<div class="alert alert-info">{{noResultsHelp}}</div>
{{else}}

View File

@ -6,6 +6,6 @@ class UserBookmarkListSerializer < ApplicationSerializer
has_many :bookmarks, serializer: UserBookmarkSerializer, embed: :objects
def include_more_bookmarks_url?
object.bookmarks.size == object.per_page
@include_more_bookmarks_url ||= object.bookmarks.size == object.per_page
end
end

View File

@ -320,6 +320,8 @@ en:
invalid_custom_datetime: "The date and time you provided is invalid, please try again."
list_permission_denied: "You do not have permission to view this user's bookmarks."
delete_when_reminder_sent: "Delete this bookmark when the reminder notification is sent."
search_placeholder: "Search bookmarks by name or post content"
search: "Search"
reminders:
at_desktop: "Next time I'm at my desktop"
later_today: "Later today"

View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
class AddBookmarkNameIndex < ActiveRecord::Migration[6.0]
def change
add_index :bookmarks, :name
end
end

View File

@ -35,6 +35,10 @@ class BookmarkQuery
results = results.merge(Post.secured(@guardian))
if @params[:q].present?
results = results.where("bookmarks.name ILIKE :q OR posts.raw ILIKE :q", q: "%#{@params[:q]}%")
end
if @page.positive?
results = results.offset(@page * @params[:per_page])
end

View File

@ -11,8 +11,9 @@ RSpec.describe BookmarkQuery do
end
describe "#list_all" do
fab!(:bookmark1) { Fabricate(:bookmark, user: user) }
fab!(:bookmark2) { Fabricate(:bookmark, user: user) }
fab!(:post) { Fabricate(:post, raw: "Some post content here") }
fab!(:bookmark1) { Fabricate(:bookmark, user: user, name: "Check up later") }
fab!(:bookmark2) { Fabricate(:bookmark, user: user, post: post, topic: post.topic) }
it "returns all the bookmarks for a user" do
expect(bookmark_query.list_all.count).to eq(2)
@ -37,6 +38,18 @@ RSpec.describe BookmarkQuery do
expect(preloaded_bookmarks.any?).to eq(true)
end
context "when q param is provided" do
it "can search by post content" do
bookmarks = bookmark_query(params: { q: 'content' }).list_all
expect(bookmarks.map(&:id)).to eq([bookmark2.id])
end
it "can search by bookmark name" do
bookmarks = bookmark_query(params: { q: 'check' }).list_all
expect(bookmarks.map(&:id)).to eq([bookmark1.id])
end
end
context "for a whispered post" do
before do
bookmark1.post.update(post_type: Post.types[:whisper])