WIP: Add notifications button to timeline
This commit is contained in:
parent
1e3e4a95fd
commit
9e1021dfa3
|
@ -1,73 +1,49 @@
|
||||||
import DropdownButton from 'discourse/components/dropdown-button';
|
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'],
|
classNames: ['notification-options'],
|
||||||
title: '',
|
title: '',
|
||||||
buttonIncludesText: true,
|
buttonIncludesText: true,
|
||||||
activeItem: Em.computed.alias('notificationLevel'),
|
activeItem: Em.computed.alias('notificationLevel'),
|
||||||
i18nPrefix: '',
|
i18nPrefix: '',
|
||||||
i18nPostfix: '',
|
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() {
|
@computed
|
||||||
return [['WATCHING', 'watching', this.watchingClasses],
|
dropDownContent() {
|
||||||
['TRACKING', 'tracking', this.trackingClasses],
|
const prefix = this.get('i18nPrefix');
|
||||||
['REGULAR', 'regular', this.regularClasses],
|
const postfix = this.get('i18nPostfix');
|
||||||
['MUTED', 'muted', this.mutedClasses]];
|
|
||||||
}.property(),
|
|
||||||
|
|
||||||
dropDownContent: function() {
|
return all.map(l => {
|
||||||
const contents = [],
|
const start = `${prefix}.${l.key}${postfix}`;
|
||||||
prefix = this.get('i18nPrefix'),
|
return {
|
||||||
postfix = this.get('i18nPostfix');
|
id: l.id,
|
||||||
|
title: I18n.t(`${start}.title`),
|
||||||
_.each(this.get('options'), function(pair) {
|
description: I18n.t(`${start}.description`),
|
||||||
if (postfix === '_pm' && pair[1] === 'regular') { return; }
|
styleClasses: `${l.key} fa fa-${l.icon}`
|
||||||
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 contents;
|
@computed('notificationLevel')
|
||||||
}.property(),
|
text(notificationLevel) {
|
||||||
|
const details = buttonDetails(notificationLevel);
|
||||||
|
const { key } = details;
|
||||||
|
const icon = iconHTML(details.icon, { class: key });
|
||||||
|
|
||||||
text: function() {
|
if (this.get('buttonIncludesText')) {
|
||||||
const self = this,
|
const prefix = this.get('i18nPrefix');
|
||||||
prefix = this.get('i18nPrefix'),
|
const postfix = this.get('i18nPostfix');
|
||||||
postfix = this.get('i18nPostfix');
|
const text = I18n.t(`${prefix}.${key}${postfix}.title`);
|
||||||
|
return `${icon} ${text}<span class='caret'></span>`;
|
||||||
const key = (function() {
|
} else {
|
||||||
switch (this.get('notificationLevel')) {
|
return `${icon} <span class='caret'></span>`;
|
||||||
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 '<i class="' + self.watchingClasses + '"></i> ';
|
|
||||||
case 'tracking': return '<i class="' + self.trackingClasses + '"></i> ';
|
|
||||||
case 'muted': return '<i class="' + self.mutedClasses + '"></i> ';
|
|
||||||
default: return '<i class="' + self.regularClasses + '"></i> ';
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
return icon + ( this.get('buttonIncludesText') ? I18n.t(prefix + '.' + key + postfix + ".title") : '') + "<span class='caret'></span>";
|
|
||||||
}.property('notificationLevel'),
|
|
||||||
|
|
||||||
clicked(/* id */) {
|
clicked(/* id */) {
|
||||||
// sub-class needs to implement this
|
// sub-class needs to implement this
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default NotificationsButton;
|
|
||||||
export { NotificationLevels };
|
|
||||||
|
|
|
@ -1,6 +1,24 @@
|
||||||
export default {
|
const NotificationLevels = {
|
||||||
WATCHING: 3,
|
WATCHING: 3,
|
||||||
TRACKING: 2,
|
TRACKING: 2,
|
||||||
REGULAR: 1,
|
REGULAR: 1,
|
||||||
MUTED: 0
|
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);
|
||||||
|
|
|
@ -30,12 +30,11 @@ export default createWidget('button', {
|
||||||
|
|
||||||
html(attrs) {
|
html(attrs) {
|
||||||
const contents = [];
|
const contents = [];
|
||||||
|
|
||||||
const left = !attrs.iconRight;
|
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.label) { contents.push(I18n.t(attrs.label, attrs.labelOptions)); }
|
||||||
if (attrs.contents) { contents.push(attrs.contents); }
|
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;
|
return contents;
|
||||||
},
|
},
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
});
|
|
@ -225,8 +225,11 @@ export default createWidget('topic-timeline', {
|
||||||
|
|
||||||
const { currentUser } = this;
|
const { currentUser } = this;
|
||||||
if (currentUser && currentUser.get('canManageTopic')) {
|
if (currentUser && currentUser.get('canManageTopic')) {
|
||||||
|
if (currentUser.get('canManageTopic')) {
|
||||||
controls.push(this.attach('topic-admin-menu-button', { topic }));
|
controls.push(this.attach('topic-admin-menu-button', { topic }));
|
||||||
}
|
}
|
||||||
|
controls.push(this.attach('topic-notifications-button', { topic }));
|
||||||
|
}
|
||||||
|
|
||||||
return [ h('div.timeline-controls', controls),
|
return [ h('div.timeline-controls', controls),
|
||||||
this.attach('link', {
|
this.attach('link', {
|
||||||
|
|
Loading…
Reference in New Issue