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:
parent
f4f3e8c401
commit
bcc80e0ea8
|
@ -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));
|
||||
|
|
|
@ -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 });
|
||||
},
|
||||
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
import DiscourseRoute from "discourse/routes/discourse";
|
||||
|
||||
export default DiscourseRoute.extend({
|
||||
queryParams: {
|
||||
q: { replace: true }
|
||||
},
|
||||
|
||||
redirect() {
|
||||
this.transitionTo("userActivity.bookmarks");
|
||||
}
|
||||
|
|
|
@ -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}}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddBookmarkNameIndex < ActiveRecord::Migration[6.0]
|
||||
def change
|
||||
add_index :bookmarks, :name
|
||||
end
|
||||
end
|
|
@ -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
|
||||
|
|
|
@ -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])
|
||||
|
|
Loading…
Reference in New Issue