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 3d2a2112b5..35cdf06a20 100644
--- a/app/assets/javascripts/discourse/app/components/user-notifications-large.js
+++ b/app/assets/javascripts/discourse/app/components/user-notifications-large.js
@@ -6,11 +6,15 @@ export default MountWidget.extend({
init() {
this._super(...arguments);
- this.args = { notifications: this.notifications };
+ this.args = { notifications: this.notifications, filter: this.filter };
},
- @observes("notifications.length", "notifications.@each.read")
+ @observes("notifications.length", "notifications.@each.read", "filter")
_triggerRefresh() {
+ this.set("args", {
+ notifications: this.notifications,
+ filter: this.filter
+ });
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 dc9147105e..e821b68364 100644
--- a/app/assets/javascripts/discourse/app/controllers/user-notifications.js
+++ b/app/assets/javascripts/discourse/app/controllers/user-notifications.js
@@ -8,14 +8,20 @@ export default Controller.extend({
application: controller(),
router: service(),
currentPath: readOnly("router._router.currentPath"),
+ filter: "all",
@observes("model.canLoadMore")
_showFooter() {
this.set("application.showFooter", !this.get("model.canLoadMore"));
},
- @discourseComputed("model.content.length")
- hasNotifications(length) {
+ @discourseComputed("model.content.length", "filter")
+ hasNotifications(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;
+ }
return length > 0;
},
@@ -35,6 +41,10 @@ export default Controller.extend({
loadMore() {
this.model.loadMore();
+ },
+
+ filterNotifications(value) {
+ this.set("filter", value);
}
}
});
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 a44a96e8d9..578f376348 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,11 @@
{{/if}}
+{{notifications-filter value=filter onChange=(action "filterNotifications")}}
+
+
{{#if hasNotifications}}
- {{user-notifications-large notifications=model}}
+ {{user-notifications-large notifications=model filter=filter}}
{{conditional-loading-spinner condition=loading}}
{{else}}
{{i18n "notifications.empty"}}
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 76bf1da687..53a4d3ad52 100644
--- a/app/assets/javascripts/discourse/app/widgets/user-notifications-large.js
+++ b/app/assets/javascripts/discourse/app/widgets/user-notifications-large.js
@@ -30,9 +30,13 @@ createWidget("large-notification-item", {
export default createWidget("user-notifications-large", {
html(attrs) {
- const notifications = attrs.notifications;
+ let 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/javascripts/select-kit/components/notifications-filter.js b/app/assets/javascripts/select-kit/components/notifications-filter.js
new file mode 100644
index 0000000000..3432f49e7a
--- /dev/null
+++ b/app/assets/javascripts/select-kit/components/notifications-filter.js
@@ -0,0 +1,25 @@
+import DropdownSelectBoxComponent from "select-kit/components/dropdown-select-box";
+import { computed } from "@ember/object";
+
+export default DropdownSelectBoxComponent.extend({
+ classNames: ["notifications-filter"],
+ content: computed(function() {
+ return [
+ {
+ id: "all",
+ label: I18n.t("user.user_notifications.filters.all")
+ },
+ {
+ id: "read",
+ label: I18n.t("user.user_notifications.filters.read")
+ },
+ {
+ id: "unread",
+ label: I18n.t("user.user_notifications.filters.unread")
+ }
+ ];
+ }),
+ selectKitOptions: {
+ headerComponent: "notifications-filter/notifications-filter-header"
+ }
+});
diff --git a/app/assets/javascripts/select-kit/components/notifications-filter/notifications-filter-header.js b/app/assets/javascripts/select-kit/components/notifications-filter/notifications-filter-header.js
new file mode 100644
index 0000000000..b615470433
--- /dev/null
+++ b/app/assets/javascripts/select-kit/components/notifications-filter/notifications-filter-header.js
@@ -0,0 +1,18 @@
+import DropdownSelectBoxHeaderComponent from "select-kit/components/dropdown-select-box/dropdown-select-box-header";
+import discourseComputed from "discourse-common/utils/decorators";
+
+export default DropdownSelectBoxHeaderComponent.extend({
+ layoutName:
+ "select-kit/templates/components/notifications-filter/notifications-filter-header",
+ classNames: ["notifications-filter-header"],
+
+ @discourseComputed("value")
+ label(value) {
+ return `user.user_notifications.filters.${value}`;
+ },
+
+ @discourseComputed("selectKit.isExpanded")
+ caretIcon(isExpanded) {
+ return isExpanded ? "caret-up" : "caret-down";
+ }
+});
diff --git a/app/assets/javascripts/select-kit/templates/components/notifications-filter/notifications-filter-header.hbs b/app/assets/javascripts/select-kit/templates/components/notifications-filter/notifications-filter-header.hbs
new file mode 100644
index 0000000000..21cee39d91
--- /dev/null
+++ b/app/assets/javascripts/select-kit/templates/components/notifications-filter/notifications-filter-header.hbs
@@ -0,0 +1,7 @@
+
+
+{{d-icon caretIcon class="caret-icon"}}
diff --git a/app/assets/stylesheets/common/base/user.scss b/app/assets/stylesheets/common/base/user.scss
index 805b6bc8d0..869635a250 100644
--- a/app/assets/stylesheets/common/base/user.scss
+++ b/app/assets/stylesheets/common/base/user.scss
@@ -64,6 +64,12 @@
.d-icon-heart {
color: $love;
}
+
+ .user-notifications-filter-separator {
+ display: block;
+ width: 100%;
+ border: 0.5px solid $primary-low;
+ }
}
.user-main {
diff --git a/app/assets/stylesheets/common/select-kit/notifications-filter.scss b/app/assets/stylesheets/common/select-kit/notifications-filter.scss
new file mode 100644
index 0000000000..680622f8aa
--- /dev/null
+++ b/app/assets/stylesheets/common/select-kit/notifications-filter.scss
@@ -0,0 +1,43 @@
+.select-kit {
+ &.dropdown-select-box {
+ &.notifications-filter {
+ display: inline-flex;
+ position: relative;
+
+ .select-kit-collection {
+ padding: 5px;
+ }
+
+ .notifications-filter-header {
+ padding: 0 0.5em 0 0.5em;
+ background: none;
+ border: none;
+ justify-content: flex-start;
+ width: auto;
+ height: auto;
+ label.filter-text {
+ margin-right: 15px;
+ color: $primary-medium;
+ }
+
+ label.header-text {
+ color: dark-light-choose($tertiary, $tertiary);
+ }
+
+ .d-icon {
+ color: $primary-medium;
+ opacity: 1;
+ margin: 5px 0 10px 5px;
+ font-size: $font-up-3;
+ }
+
+ &.is-focused,
+ &:hover {
+ background: none;
+ border: none;
+ outline: none;
+ }
+ }
+ }
+ }
+}
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index 1b8fb7c65a..5c3211a53b 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -835,6 +835,11 @@ en:
private_message: "Message"
private_messages: "Messages"
user_notifications:
+ filters:
+ filter_by: "Filter By"
+ all: "All"
+ read: "Read"
+ unread: "Unread"
ignore_duration_title: "Ignore Timer"
ignore_duration_username: "Username"
ignore_duration_when: "Duration:"