Source: forms/common-forms/page-form.js


import {gettext}        from '$qui/base/i18n.js'
import {mix}            from '$qui/base/mixwith.js'
import StockIcon        from '$qui/icons/stock-icon.js'
import PageMixin        from '$qui/pages/page.js'
import * as Sections    from '$qui/sections/sections.js'
import * as ObjectUtils from '$qui/utils/object.js'
import * as Window      from '$qui/window.js'

import Form from '../form.js'


/**
 * A form that can be used as a page.
 * @alias qui.forms.commonforms.PageForm
 * @extends qui.forms.Form
 * @mixes qui.pages.PageMixin
 */
class PageForm extends mix(Form).with(PageMixin) {

    /**
     * @constructs
     * @param {Boolean} [preventUnappliedClose] if set to `true`, the form will try to prevent losing unapplied data
     * when closed, by asking the user for confirmation
     * @param {...*} args parent class parameters
     */
    constructor({preventUnappliedClose = false, ...args} = {}) {
        ObjectUtils.setDefault(args, 'transparent', !Window.isSmallScreen())
        super(args)

        this._preventUnappliedClose = preventUnappliedClose
    }

    prepareIcon(icon) {
        /* Popup page views should normally have the default foreground icon color, even on small screens */
        if (this.isPopup() && (icon instanceof StockIcon)) {
            icon = icon.alterDefault({variant: 'foreground'})
        }

        return super.prepareIcon(icon)
    }

    canClose() {
        if (!this._preventUnappliedClose) {
            return super.canClose()
        }

        let changedFields = this.getChangedFieldNames()
        if (!changedFields.length) {
            return super.canClose()
        }

        /* Dynamically import common-message-forms.js here, because it depends itself on PageForm */
        return import('$qui/messages/common-message-forms/common-message-forms.js').then(function (CommonMessageForms) {
            let message = gettext('Discard changes?')
            return new CommonMessageForms.ConfirmMessageForm({message: message}).show().asPromise()
        })
    }

    handleBecomeCurrent() {
        super.handleBecomeCurrent()
        this._updateVertScroll()
    }

    handleVertScroll() {
        super.handleVertScroll()
        this._updateVertScroll()
    }

    handleResize() {
        super.handleResize()
        this._updateVertScroll()
    }

    _updateVertScroll() {
        let params = this.getVertScrollParams()
        let fixedBottom = (params.maxOffset > 0) && Window.isSmallScreen()
        let fullyScrolled = (params.maxOffset - params.offset <= 1) && Window.isSmallScreen()

        /* Place progress widget in the viewport by pushing it down a bit */
        this.getProgressWidget().css('margin-top', `${params.offset}px`)

        /* Make form buttons always visible */
        this.getHTML().toggleClass('fixed-bottom', fixedBottom)
        this.getHTML().toggleClass('fully-scrolled', fullyScrolled)
    }

    static init() {
        Window.closeSignal.connect(function () {
            /* Go through all current pages and collect page forms. Then see if they have changed fields and, if any of
             * them does and has preventUnappliedClose flag set, try to prevent navigating away from the page */

            let currentSection = Sections.getCurrent()
            if (!currentSection) {
                return
            }

            let context = currentSection.getPagesContext()
            if (!context) {
                return
            }

            let pages = context.getPages()
            let pageForms = pages.filter(p => p instanceof PageForm)

            if (pageForms.some(f => f.getChangedFieldNames().length > 0 && f._preventUnappliedClose)) {
                return false
            }
        })
    }

}


export default PageForm