Home Reference Source

js/template/ProfileSettings/ProfileSettingsViewProfile.js

import ProfileSettingsView from '~/template/ProfileSettings/ProfileSettingsView';
import { ButtonColor, ButtonStyle } from '~/template/ButtonTemplate';
import ProgressButtonTemplate from '~/template/ProgressButtonTemplate';
import ModifyUser from '~/models/Request/ModifyUser';

import TextInputTemplate, { TextInputType } from '~/template/Form/TextInputTemplate';
import CheckboxInputTemplate from '~/template/Form/CheckboxInputTemplate';
import Data, { Key, EnvKey } from '~/models/Data';
import FormConstraint from '~/controllers/Form/FormConstraint';
import LabelGroup from '~/template/Form/LabelGroup';
import Theme from '~/models/Theme';

import { combineLatest } from 'rxjs/index';
import { withLatestFrom, exhaustMap, tap, distinctUntilChanged, map, startWith, share } from 'rxjs/operators';

/**
 * Main profile setting page
 */
export default class ProfileSettingsViewProfile extends ProfileSettingsView {
    /** @override */
    constructor(data) {
        const root = <div/>,
            saveButton = new ProgressButtonTemplate({
                text: 'Save',
                color: ButtonColor.green,
                style: ButtonStyle.plain,
            });

        super(data, root, {
            button: saveButton
        });

        /**
         * Root template
         * @type {HTMLDivElement}
         */
        this.root = root;

        /**
         * Status of the current view's validation
         * @type {?Observable<boolean>}
         */
        this.observeValidation = null;

        /** @type {ButtonTemplate} */
        this.saveButton = saveButton;
    }

    /** @override */
    async didInitialLoad() {
        await super.didInitialLoad();

        const displayNameInput = new LabelGroup(
            'Name',
            new TextInputTemplate(TextInputType.Name, 'John Doe', {
                initialValue: this.user.name,
            }),
            {
                tooltip: 'This is your display name seen by everyone',
                liveConstraint: new FormConstraint()
                    .length(
                        Data.shared.envValueForKey(EnvKey.minUsernameLength),
                        Data.shared.envValueForKey(EnvKey.maxUsernameLength)
                    )
            }
        );
        displayNameInput.loadInContext(this.root);

        const emailInput = new LabelGroup(
            'Email',
            new TextInputTemplate(TextInputType.Email, 'johnd@example.com', {
                initialValue: Data.shared.valueForKey(Key.userEmail),
            }),
            {
                tooltip: 'This is your email which is private and only used for administrative purposes.',
                liveConstraint: new FormConstraint()
                    .or(
                        new FormConstraint().isEmail(),
                        new FormConstraint().isEmpty()
                    )
            }
        );
        emailInput.loadInContext(this.root);

        const receiveNotificationsInput = new LabelGroup(
            'Receive Notifications',
            new CheckboxInputTemplate({isEnabled: Data.shared.valueForKey(Key.userReceiveNotifications) == 1}),
            {
                isHorizontalStyle: true,
                tooltip: 'Choose whether or not you want to receive notifications about updates to your content.',
            }
        );
        receiveNotificationsInput.loadInContext(this.root);

        this.observeValidation = FormConstraint.observeValidation(
            displayNameInput.observeValidation(),
            emailInput.observeValidation()
        );

        // Add save button
        this.saveButton
            .observeClick()
            .pipe(
                withLatestFrom(
                    combineLatest(
                        displayNameInput.observeValue(),
                        emailInput.observeValue(),
                        receiveNotificationsInput.observeValue(),
                        (name, email, notifications) => ({ name, email, notifications })),
                    (click, data) => data),
                exhaustMap(async ({ name, email, notifications }) => {
                    this.saveButton.controller.setLoadingState(true);

                    const modifyUser = new ModifyUser({
                        name,
                        email,
                        notifications
                    });

                    await modifyUser.run();

                    this.saveButton.controller.setLoadingState(false);
                    return true;
                }))
            .subscribe((status) => {
                window.location.reload();
            });

        this.observeValidation
            .pipe(
                map(isValid => !isValid),
                distinctUntilChanged())
            .subscribe(isInvalid => this.saveButton.setIsDisabled(isInvalid, 'Ensure all fields are correctly completed'))
    }
}