import Component from '../../common/Component'; import listItems from '../../common/helpers/listItems'; import Button from '../../common/components/Button'; import Link from '../../common/components/Link'; import LoadingIndicator from '../../common/components/LoadingIndicator'; import Discussion from '../../common/models/Discussion'; /** * The `NotificationList` component displays a list of the logged-in user's * notifications, grouped by discussion. */ export default class NotificationList extends Component { view() { const state = this.attrs.state; const pages = state.getNotificationPages(); return (
{Button.component({ className: 'Button Button--icon Button--link', icon: 'fas fa-check', title: app.translator.trans('core.forum.notifications.mark_all_as_read_tooltip'), onclick: state.markAllAsRead.bind(state), })}

{app.translator.trans('core.forum.notifications.title')}

{pages.length ? pages.map((notifications) => { const groups = []; const discussions = {}; notifications.forEach((notification) => { const subject = notification.subject(); if (typeof subject === 'undefined') return; // Get the discussion that this notification is related to. If it's not // directly related to a discussion, it may be related to a post or // other entity which is related to a discussion. let discussion = false; if (subject instanceof Discussion) discussion = subject; else if (subject && subject.discussion) discussion = subject.discussion(); // If the notification is not related to a discussion directly or // indirectly, then we will assign it to a neutral group. const key = discussion ? discussion.id() : 0; discussions[key] = discussions[key] || { discussion: discussion, notifications: [] }; discussions[key].notifications.push(notification); if (groups.indexOf(discussions[key]) === -1) { groups.push(discussions[key]); } }); return groups.map((group) => { const badges = group.discussion && group.discussion.badges().toArray(); return (
{group.discussion ? ( {badges && badges.length ?
    {listItems(badges)}
: ''} {group.discussion.title()} ) : (
{app.forum.attribute('title')}
)}
    {group.notifications.map((notification) => { const NotificationComponent = app.notificationComponents[notification.contentType()]; return NotificationComponent ?
  • {NotificationComponent.component({ notification })}
  • : ''; })}
); }); }) : ''} {state.isLoading() ? ( ) : pages.length ? ( '' ) : (
{app.translator.trans('core.forum.notifications.empty_text')}
)}
); } oncreate(vnode) { super.oncreate(vnode); this.$notifications = this.$('.NotificationList-content'); this.$scrollParent = this.$notifications.css('overflow') === 'auto' ? this.$notifications : $(window); this.boundScrollHandler = this.scrollHandler.bind(this); this.$scrollParent.on('scroll', this.boundScrollHandler); } onremove() { this.$scrollParent.off('scroll', this.boundScrollHandler); } scrollHandler() { const state = this.attrs.state; const scrollTop = this.$scrollParent.scrollTop(); const viewportHeight = this.$scrollParent.height(); const contentTop = this.$scrollParent === this.$notifications ? 0 : this.$notifications.offset().top; const contentHeight = this.$notifications[0].scrollHeight; if (state.hasMoreResults() && !state.isLoading() && scrollTop + viewportHeight >= contentTop + contentHeight) { state.loadMore(); } } }