Home Reference Source

js/template/WritePost/Tab/Submit.js

import Template from '~/template/Template';
import HeaderTemplate from '~/template/HeaderTemplate';
import { ButtonColor } from '~/template/ButtonTemplate';
import SwappingTemplate from '~/template/SwappingTemplate';
import ProgressButtonTemplate from '~/template/ProgressButtonTemplate';
import { HandleUnhandledPromise } from '~/helpers/ErrorManager';

import * as PreviewKey from '~/helpers/PreviewKey';
import LoadingIcon from '~/svg/LoadingIcon';

export const NO_TITLE = do {
    const header = new HeaderTemplate('No Title.')
    header.isDimmed = true;
    header
};

export const NO_BODY = (
    <div class="preview-no-body">
        <svg namespace="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
            <path namespace="http://www.w3.org/2000/svg" d="M 4 2 L 4 11 L 2 11 L 2 12.5 C 2 13.328 2.672 14 3.5 14 L 11.5 14 C 11.909962 14 12.301599 13.855814 12.578125 13.580078 C 12.854651 13.304342 13 12.912335 13 12.5 L 13 2 L 4 2 z M 5 3 L 12 3 L 12 12.5 C 12 12.690665 11.94482 12.79758 11.871094 12.871094 C 11.79737 12.944607 11.689038 13 11.5 13 C 11.172 13 11 12.686 11 12.375 L 11 11 L 5 11 L 5 3 z" />
        </svg>
        <h3>Live Post Preview</h3>
        <span>Preview will be automatically refreshed as you type.</span>
    </div>
);

export default class WritePostTabSubmit extends Template {
    /**
     * Creates in context
     * @param {WritePostTemplate} writePostTemplate
     */
    constructor(writePostTemplate) {
        super(<div/>);

        /** @type {ButtonTemplate} */
        this.submitButton = new ProgressButtonTemplate({
            text: 'Submit',
            color: ButtonColor.green,
        });

        this.submitButton.isWide = true;
        this.submitButton.hasPaddedTop = true;
        this.submitButton.hasPaddedHorizontal = true;

        /** @type {WritePostTemplate} */
        this.writePostTemplate = writePostTemplate;

        /** @type {SwappingTemplate} */
        this.previewSwapper = new SwappingTemplate();

        this.underlyingNode.appendChild(
            <DocumentFragment>
                { new HeaderTemplate('Submit.', { subtitle: 'Preview your post and prepare it for submission.' }).unique() }
                { new HeaderTemplate('Final Preview', { level: 3 }).unique() }
                <div class="content-offset content-offset--pad-horizontal">
                    { this.previewSwapper.unique() }
                </div>
                { this.submitButton.unique() }
            </DocumentFragment>
        );

        this.submitButton.delegate.didSetStateTo = async (button, _) => {
            await this.submit();
        };

        this.writePostTemplate.foreignChildInteractor.watchTick(() => {
            this.submitButton.setIsDisabled(!writePostTemplate.isComplete, 'Complete all fields correctly.');
        });
    }

    /** @override */
    willLoad() {
        this.submitButton.setIsDisabled(!this.writePostTemplate.isComplete, 'Complete all fields correctly.');
    }

    /** @override */
    didLoad() {
        this.previewSwapper.controller.displayAlternate(new Template(
            <div class="template--root">
                { LoadingIcon.cloneNode(true) }
                <h3>Loading...</h3>
            </div>
        ));

        this.loadPreview()
            .catch(HandleUnhandledPromise);
    }

    /** @private */
    async submit() {
        const request = this.writePostTemplate.postRequest;
        const postUrl = await request.run();
        window.location.href = postUrl;
    }

    /** @private */
    async loadPreview() {
        const markdown = await import('#/markdown-renderer');

        const header = new HeaderTemplate('Untitled', {});
        const body = new SwappingTemplate(NO_BODY);

        this.previewSwapper.controller.displayAlternate(new Template(
            <div>
                { header.unique() }
                { body.unique() }
            </div>
        ));

        this.writePostTemplate.foreignChildInteractor.watch(PreviewKey.Title, (newTitle) => {
            if (newTitle) {
                header.title = newTitle;
                header.isDimmed = false;
            } else {
                header.title = 'No Title.';
                header.isDimmed = true;
            }
        });

        this.writePostTemplate.foreignChildInteractor.watch(PreviewKey.Body, (newBody) => {
            if (newBody) body.controller.displayAlternate(
                Template.fromInnerHTML(<div class="main body"/>, markdown.render(newBody)));
            else body.controller.restoreOriginal();
        });
    }
}