diff --git a/app/assets/javascripts/discourse/components/notifications-button.js.es6 b/app/assets/javascripts/discourse/components/notifications-button.js.es6
index 7c329af4e68..998ce74e30f 100644
--- a/app/assets/javascripts/discourse/components/notifications-button.js.es6
+++ b/app/assets/javascripts/discourse/components/notifications-button.js.es6
@@ -1,73 +1,49 @@
import DropdownButton from 'discourse/components/dropdown-button';
-import NotificationLevels from 'discourse/lib/notification-levels';
+import { all, buttonDetails } from 'discourse/lib/notification-levels';
+import { iconHTML } from 'discourse/helpers/fa-icon';
+import computed from 'ember-addons/ember-computed-decorators';
-const NotificationsButton = DropdownButton.extend({
+export default DropdownButton.extend({
classNames: ['notification-options'],
title: '',
buttonIncludesText: true,
activeItem: Em.computed.alias('notificationLevel'),
i18nPrefix: '',
i18nPostfix: '',
- watchingClasses: 'fa fa-exclamation-circle watching',
- trackingClasses: 'fa fa-circle tracking',
- mutedClasses: 'fa fa-times-circle muted',
- regularClasses: 'fa fa-circle-o regular',
- options: function() {
- return [['WATCHING', 'watching', this.watchingClasses],
- ['TRACKING', 'tracking', this.trackingClasses],
- ['REGULAR', 'regular', this.regularClasses],
- ['MUTED', 'muted', this.mutedClasses]];
- }.property(),
+ @computed
+ dropDownContent() {
+ const prefix = this.get('i18nPrefix');
+ const postfix = this.get('i18nPostfix');
- dropDownContent: function() {
- const contents = [],
- prefix = this.get('i18nPrefix'),
- postfix = this.get('i18nPostfix');
-
- _.each(this.get('options'), function(pair) {
- if (postfix === '_pm' && pair[1] === 'regular') { return; }
- contents.push({
- id: NotificationLevels[pair[0]],
- title: I18n.t(prefix + '.' + pair[1] + postfix + '.title'),
- description: I18n.t(prefix + '.' + pair[1] + postfix + '.description'),
- styleClasses: pair[2]
- });
+ return all.map(l => {
+ const start = `${prefix}.${l.key}${postfix}`;
+ return {
+ id: l.id,
+ title: I18n.t(`${start}.title`),
+ description: I18n.t(`${start}.description`),
+ styleClasses: `${l.key} fa fa-${l.icon}`
+ };
});
+ },
- return contents;
- }.property(),
+ @computed('notificationLevel')
+ text(notificationLevel) {
+ const details = buttonDetails(notificationLevel);
+ const { key } = details;
+ const icon = iconHTML(details.icon, { class: key });
- text: function() {
- const self = this,
- prefix = this.get('i18nPrefix'),
- postfix = this.get('i18nPostfix');
-
- const key = (function() {
- switch (this.get('notificationLevel')) {
- case NotificationLevels.WATCHING: return 'watching';
- case NotificationLevels.TRACKING: return 'tracking';
- case NotificationLevels.MUTED: return 'muted';
- default: return 'regular';
- }
- }).call(this);
-
- const icon = (function() {
- switch (key) {
- case 'watching': return ' ';
- case 'tracking': return ' ';
- case 'muted': return ' ';
- default: return ' ';
- }
- })();
- return icon + ( this.get('buttonIncludesText') ? I18n.t(prefix + '.' + key + postfix + ".title") : '') + "";
- }.property('notificationLevel'),
+ if (this.get('buttonIncludesText')) {
+ const prefix = this.get('i18nPrefix');
+ const postfix = this.get('i18nPostfix');
+ const text = I18n.t(`${prefix}.${key}${postfix}.title`);
+ return `${icon} ${text}`;
+ } else {
+ return `${icon} `;
+ }
+ },
clicked(/* id */) {
// sub-class needs to implement this
}
-
});
-
-export default NotificationsButton;
-export { NotificationLevels };
diff --git a/app/assets/javascripts/discourse/lib/notification-levels.js.es6 b/app/assets/javascripts/discourse/lib/notification-levels.js.es6
index f6830ec7d30..e2173e560b9 100644
--- a/app/assets/javascripts/discourse/lib/notification-levels.js.es6
+++ b/app/assets/javascripts/discourse/lib/notification-levels.js.es6
@@ -1,6 +1,24 @@
-export default {
+const NotificationLevels = {
WATCHING: 3,
TRACKING: 2,
REGULAR: 1,
MUTED: 0
};
+export default NotificationLevels;
+
+export function buttonDetails(level) {
+ switch(level) {
+ case NotificationLevels.WATCHING:
+ return { id: NotificationLevels.WATCHING, key: 'watching', icon: 'exclamation-circle' };
+ case NotificationLevels.TRACKING:
+ return { id: NotificationLevels.TRACKING, key: 'tracking', icon: 'circle' };
+ case NotificationLevels.MUTED:
+ return { id: NotificationLevels.MUTED, key: 'muted', icon: 'times-circle' };
+ default:
+ return { id: NotificationLevels.REGULAR, key: 'regular', icon: 'circle-o' };
+ }
+}
+export const all = [ NotificationLevels.WATCHING,
+ NotificationLevels.TRACKING,
+ NotificationLevels.MUTED,
+ NotificationLevels.DEFAULT ].map(buttonDetails);
diff --git a/app/assets/javascripts/discourse/widgets/button.js.es6 b/app/assets/javascripts/discourse/widgets/button.js.es6
index e9fd29d70de..8b8ae46dc1d 100644
--- a/app/assets/javascripts/discourse/widgets/button.js.es6
+++ b/app/assets/javascripts/discourse/widgets/button.js.es6
@@ -30,12 +30,11 @@ export default createWidget('button', {
html(attrs) {
const contents = [];
-
const left = !attrs.iconRight;
- if (attrs.icon && left) { contents.push(iconNode(attrs.icon)); }
+ if (attrs.icon && left) { contents.push(iconNode(attrs.icon, { class: attrs.iconClass })); }
if (attrs.label) { contents.push(I18n.t(attrs.label, attrs.labelOptions)); }
if (attrs.contents) { contents.push(attrs.contents); }
- if (attrs.icon && !left) { contents.push(iconNode(attrs.icon)); }
+ if (attrs.icon && !left) { contents.push(iconNode(attrs.icon, { class: attrs.iconClass })); }
return contents;
},
diff --git a/app/assets/javascripts/discourse/widgets/topic-notifications-button.js.es6 b/app/assets/javascripts/discourse/widgets/topic-notifications-button.js.es6
new file mode 100644
index 00000000000..c9bc98642d5
--- /dev/null
+++ b/app/assets/javascripts/discourse/widgets/topic-notifications-button.js.es6
@@ -0,0 +1,69 @@
+import { createWidget } from 'discourse/widgets/widget';
+import { all, buttonDetails } from 'discourse/lib/notification-levels';
+import { h } from 'virtual-dom';
+
+createWidget('notification-option', {
+ buildKey: attrs => `topic-notifications-button-${attrs.id}`,
+ tagName: 'li',
+
+ html(attrs) {
+ return h('a', [
+ h('span.icon', { className: `fa fa-${attrs.icon} ${attrs.key}`}),
+ h('div', [
+ h('span.title', I18n.t(`topic.notifications.${attrs.key}.title`)),
+ h('span', I18n.t(`topic.notifications.${attrs.key}.description`)),
+ ])
+ ]);
+ },
+
+ click() {
+ this.sendWidgetAction('notificationLevelChanged', this.attrs.id);
+ }
+});
+
+export default createWidget('topic-notifications-button', {
+ tagName: 'span.btn-group.notification-options',
+ buildKey: () => `topic-notifications-button`,
+
+ defaultState() {
+ return { expanded: false };
+ },
+
+ buildClasses(attrs, state) {
+ if (state.expanded) { return "open"; }
+ },
+
+ buttonFor(level) {
+ const details = buttonDetails(level);
+ return this.attach('button', {
+ className: `btn no-text`,
+ icon: details.icon,
+ action: 'toggleDropdown',
+ iconClass: details.key
+ });
+ },
+
+ html(attrs, state) {
+ const result = [ this.buttonFor(attrs.topic.get('details.notification_level')) ];
+ if (state.expanded) {
+ result.push(h('ul.dropdown-menu', all.map(l => this.attach('notification-option', l))));
+ }
+
+ return result;
+ },
+
+ toggleDropdown() {
+ this.state.expanded = !this.state.expanded;
+ },
+
+ clickOutside() {
+ if (this.state.expanded) {
+ this.sendWidgetAction('toggleDropdown');
+ }
+ },
+
+ notificationLevelChanged(id) {
+ this.state.expanded = false;
+ return this.attrs.topic.get('details').updateNotifications(id);
+ }
+});
diff --git a/app/assets/javascripts/discourse/widgets/topic-timeline.js.es6 b/app/assets/javascripts/discourse/widgets/topic-timeline.js.es6
index 5d1a4a2e175..9061c60ca25 100644
--- a/app/assets/javascripts/discourse/widgets/topic-timeline.js.es6
+++ b/app/assets/javascripts/discourse/widgets/topic-timeline.js.es6
@@ -225,7 +225,10 @@ export default createWidget('topic-timeline', {
const { currentUser } = this;
if (currentUser && currentUser.get('canManageTopic')) {
- controls.push(this.attach('topic-admin-menu-button', { topic }));
+ if (currentUser.get('canManageTopic')) {
+ controls.push(this.attach('topic-admin-menu-button', { topic }));
+ }
+ controls.push(this.attach('topic-notifications-button', { topic }));
}
return [ h('div.timeline-controls', controls),