diff --git a/app/assets/javascripts/discourse/app/components/user-notifications-large.js b/app/assets/javascripts/discourse/app/components/user-notifications-large.js index 5f508780999cdb..a81412266a1b13 100644 --- a/app/assets/javascripts/discourse/app/components/user-notifications-large.js +++ b/app/assets/javascripts/discourse/app/components/user-notifications-large.js @@ -4,20 +4,18 @@ import { observes } from "discourse-common/utils/decorators"; export default MountWidget.extend({ widget: "user-notifications-large", notifications: null, - filter: null, args: null, init() { this._super(...arguments); - this.args = { notifications: this.notifications, filter: this.filter }; + this.args = { notifications: this.notifications }; }, - @observes("notifications.length", "notifications.@each.read", "filter") + @observes("notifications.length", "notifications.@each.read") _triggerRefresh() { this.set("args", { - notifications: this.notifications, - filter: this.filter + notifications: this.notifications }); this.queueRerender(); diff --git a/app/assets/javascripts/discourse/app/controllers/user-notifications.js b/app/assets/javascripts/discourse/app/controllers/user-notifications.js index c0761e70dcb04f..6f6012c090ef88 100644 --- a/app/assets/javascripts/discourse/app/controllers/user-notifications.js +++ b/app/assets/javascripts/discourse/app/controllers/user-notifications.js @@ -6,6 +6,7 @@ import { inject as service } from "@ember/service"; export default Controller.extend({ application: controller(), + queryParams: ["filter"], router: service(), currentPath: readOnly("router._router.currentPath"), filter: "all", @@ -15,13 +16,8 @@ export default Controller.extend({ this.set("application.showFooter", !this.get("model.canLoadMore")); }, - @discourseComputed("model.content.length", "filter") - hasFilteredNotifications(length, filter) { - if (filter === "read") { - return this.model.filterBy("read", true).length > 0; - } else if (filter === "unread") { - return this.model.filterBy("read", false).length > 0; - } + @discourseComputed("model.content.length") + hasFilteredNotifications(length) { return length > 0; }, @@ -41,10 +37,6 @@ export default Controller.extend({ loadMore() { this.model.loadMore(); - }, - - filterNotifications(value) { - this.set("filter", value); } } }); diff --git a/app/assets/javascripts/discourse/app/routes/user-notifications.js b/app/assets/javascripts/discourse/app/routes/user-notifications.js index 3feb837746c3f9..040cacb8c47200 100644 --- a/app/assets/javascripts/discourse/app/routes/user-notifications.js +++ b/app/assets/javascripts/discourse/app/routes/user-notifications.js @@ -2,6 +2,9 @@ import DiscourseRoute from "discourse/routes/discourse"; import ViewingActionType from "discourse/mixins/viewing-action-type"; export default DiscourseRoute.extend(ViewingActionType, { + controllerName: "user-notifications", + queryParams: { filter: { refreshModel: true } }, + renderTemplate() { this.render("user/notifications"); }, @@ -13,14 +16,17 @@ export default DiscourseRoute.extend(ViewingActionType, { } }, - model() { + model(params) { const username = this.modelFor("user").get("username"); if ( this.get("currentUser.username") === username || this.get("currentUser.admin") ) { - return this.store.find("notification", { username }); + return this.store.find("notification", { + username: username, + filter: params.filter + }); } }, 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 b2c9185ec47c4b..14638f5f781cac 100644 --- a/app/assets/javascripts/discourse/app/templates/user/notifications-index.hbs +++ b/app/assets/javascripts/discourse/app/templates/user/notifications-index.hbs @@ -8,8 +8,9 @@ {{/if}} -{{notifications-filter value=filter onChange=(action "filterNotifications")}} - +
+ {{notifications-filter value=filter onChange=(action (mut filter))}} +
{{#if hasFilteredNotifications}} {{user-notifications-large notifications=model filter=filter}} diff --git a/app/assets/javascripts/discourse/app/widgets/user-notifications-large.js b/app/assets/javascripts/discourse/app/widgets/user-notifications-large.js index 53a4d3ad527862..76bf1da6875996 100644 --- a/app/assets/javascripts/discourse/app/widgets/user-notifications-large.js +++ b/app/assets/javascripts/discourse/app/widgets/user-notifications-large.js @@ -30,13 +30,9 @@ createWidget("large-notification-item", { export default createWidget("user-notifications-large", { html(attrs) { - let notifications = attrs.notifications; + const notifications = attrs.notifications; const username = notifications.findArgs.username; - if (attrs.filter === "read") { - notifications = notifications.filterBy("read", true); - } else if (attrs.filter === "unread") { - notifications = notifications.filterBy("read", false); - } + return notifications.map(n => { n.username = username; return this.attach("large-notification-item", n); diff --git a/app/assets/stylesheets/common/base/user.scss b/app/assets/stylesheets/common/base/user.scss index 4d5e9f42886703..c42df5ea8181a1 100644 --- a/app/assets/stylesheets/common/base/user.scss +++ b/app/assets/stylesheets/common/base/user.scss @@ -65,10 +65,10 @@ color: $love; } - .user-notifications-filter-separator { + .user-notifications-filter-select-kit { display: block; width: 100%; - border: 0.5px solid $primary-low; + border-bottom: 0.5px solid $primary-low; } } diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb index a928b493bc5a08..1d28fb4caf0112 100644 --- a/app/controllers/notifications_controller.rb +++ b/app/controllers/notifications_controller.rb @@ -44,12 +44,16 @@ def index .includes(:topic) .order(created_at: :desc) + notifications = notifications.where(read: true) if params[:filter] == "read" + + notifications = notifications.where(read: false) if params[:filter] == "unread" + total_rows = notifications.dup.count notifications = notifications.offset(offset).limit(60) render_json_dump(notifications: serialize_data(notifications, NotificationSerializer), total_rows_notifications: total_rows, seen_notification_id: user.seen_notification_id, - load_more_notifications: notifications_path(username: user.username, offset: offset + 60)) + load_more_notifications: notifications_path(username: user.username, offset: offset + 60, filter: params[:filter])) end end diff --git a/spec/requests/notifications_controller_spec.rb b/spec/requests/notifications_controller_spec.rb index 4270afb728cb76..495ae5afbe5c11 100644 --- a/spec/requests/notifications_controller_spec.rb +++ b/spec/requests/notifications_controller_spec.rb @@ -74,6 +74,24 @@ def delete_notification(resp_code, matcher) Discourse.clear_redis_readonly! end + it "get notifications with all filters" do + notification = Fabricate(:notification, user: user) + notification2 = Fabricate(:notification, user: user) + put "/notifications/mark-read.json", params: { id: notification.id } + expect(response.status).to eq(200) + + get "/notifications.json" + expect(JSON.parse(response.body)['notifications'].length).to be >= 2 + + get "/notifications.json", params: { filter: "read" } + expect(JSON.parse(response.body)['notifications'].length).to be >= 1 + expect(JSON.parse(response.body)['notifications'][0]['read']).to eq(true) + + get "/notifications.json", params: { filter: "unread" } + expect(JSON.parse(response.body)['notifications'].length).to be >= 1 + expect(JSON.parse(response.body)['notifications'][0]['read']).to eq(false) + end + context 'when username params is not valid' do it 'should raise the right error' do get "/notifications.json", params: { username: 'somedude' } diff --git a/test/javascripts/acceptance/notifications-filter-test.js b/test/javascripts/acceptance/notifications-filter-test.js new file mode 100644 index 00000000000000..76234f3f6533ab --- /dev/null +++ b/test/javascripts/acceptance/notifications-filter-test.js @@ -0,0 +1,32 @@ +import { acceptance } from "helpers/qunit-helpers"; +import selectKit from "helpers/select-kit-helper"; + +acceptance("NotificationsFilter", { + loggedIn: true +}); + +test("Notifications filter true", async assert => { + await visit("/u/eviltrout/notifications"); + + assert.ok(find(".large-notification").length >= 0); +}); + +test("Notifications filter read", async assert => { + await visit("/u/eviltrout/notifications"); + + const dropdown = selectKit(".notifications-filter"); + await dropdown.expand(); + await dropdown.selectRowByValue("read"); + + assert.ok(find(".large-notification").length >= 0); +}); + +test("Notifications filter unread", async assert => { + await visit("/u/eviltrout/notifications"); + + const dropdown = selectKit(".notifications-filter"); + await dropdown.expand(); + await dropdown.selectRowByValue("unread"); + + assert.ok(find(".large-notification").length >= 0); +});