Home Reference Source

js/template/NotificationCategoryTemplate.js

import Template from '~/template/Template';
import LoadingIcon from '~/svg/LoadingIcon';
import SwappingTemplate from '~/template/SwappingTemplate';
import Notification from '~/models/Notification';
import NotificationItemTemplate from '~/template/NotificationItemTemplate';
import MarkNotificationStatus from '~/models/Request/MarkNotificationStatus';
import NotificationButtonTemplate from '~/template/NotificationButtonTemplate';
import { HandleUnhandledPromise } from '~/helpers/ErrorManager';

/**
 * A category of notifications w/ a header
 */
export default class NotificationCategoryTemplate extends Template {
    /**
     * @param {NotificationCategory} notificationCategory
     * @async
     */
    constructor(notificationCategory) {

        const root = <ul class="notification-category"/>;
        super(root);

        /** @type {NotificationGroupTemplate[]} */
        this.notificationGroupTemplates = [];

        return (async () => {
            const checkAllButton = await new NotificationButtonTemplate('Mark all as read', 'check-all');
            const checkButton = checkAllButton.unique();
            checkAllButton.delegate.didSetStateTo = (_, state) => {
                // TODO: mark category as fixed
            };

            // Check if all children are read.
            const unread = await notificationCategory.getStatus();

            /** @private */
            this.checkAll = new SwappingTemplate(checkButton);

            /** @private */
            this.checkWrapper = (
                <div class="notification-category__detail">
                    { unread ? checkButton : <DocumentFragment/> }
                </div>
            );

            /** @private */
            this.loadingSign = new Template(LoadingIcon.cloneNode(true));

            /** @private */
            this.markingRead = false;

            root.appendChild(
                <DocumentFragment>
                    <li class="notification-category__title notification-category__stack">
                        <h3 class="notification-category__stack__primary">{notificationCategory.name}</h3>
                        { this.checkWrapper }
                    </li>
                </DocumentFragment>
            );

            for (const notificationGroup of notificationCategory) {
                const notificationGroupTemplate = await new NotificationItemTemplate(notificationGroup);
                this.notificationGroupTemplates.push(notificationGroupTemplate);
                notificationGroupTemplate.loadInContext(root);
            }

            /** @type {NotificationCategory} */
            this.notificationCategory = notificationCategory;

            checkButton.addEventListener('click', () => {
                this.markRead()
                    .catch(HandleUnhandledPromise);
            });

            return this;
        })();
    }

    /**
     * Marks all things as read under this
     */
    async markRead() {
        if (this.markingRead) return;


        this.checkAll.controller.displayAlternate(this.loadingSign);
        this.markingRead = true;
        const NotificationStatus = await Notification.getStatuses();
        const markNotificationStatus = new MarkNotificationStatus(this.notificationCategory, NotificationStatus.read);
        await markNotificationStatus.run();

        for (const group of this.notificationGroupTemplates) {
            group.markedRead();
        }

        this.markingRead = false;

        if (this.checkWrapper.parentNode) {
            this.checkWrapper.parentNode.removeChild(this.checkWrapper);
        }
    }
}