Proyectos de Subversion Moodle

Rev

Autoría | Ultima modificación | Ver Log |

{"version":3,"file":"modal_event_form.min.js","sources":["../src/modal_event_form.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Contain the logic for the quick add or update event modal.\n *\n * @module     core_calendar/modal_event_form\n * @copyright  2017 Ryan Wyllie <ryan@moodle.com>\n * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from 'jquery';\nimport * as CustomEvents from 'core/custom_interaction_events';\nimport Modal from 'core/modal';\nimport * as FormEvents from 'core_form/events';\nimport CalendarEvents from './events';\nimport * as Str from 'core/str';\nimport * as Notification from 'core/notification';\nimport * as Fragment from 'core/fragment';\nimport * as Repository from 'core_calendar/repository';\n\nconst SELECTORS = {\n    SAVE_BUTTON: '[data-action=\"save\"]',\n    LOADING_ICON_CONTAINER: '[data-region=\"loading-icon-container\"]',\n};\n\nexport default class ModalEventForm extends Modal {\n    static TYPE = 'core_calendar-modal_event_form';\n    static TEMPLATE = 'calendar/modal_event_form';\n\n    /**\n     * Constructor for the Modal.\n     *\n     * @param {object} root The root jQuery element for the modal\n     */\n    constructor(root) {\n        super(root);\n\n        this.eventId = null;\n        this.startTime = null;\n        this.courseId = null;\n        this.categoryId = null;\n        this.contextId = null;\n        this.reloadingBody = false;\n        this.reloadingTitle = false;\n        this.saveButton = this.getFooter().find(SELECTORS.SAVE_BUTTON);\n    }\n\n    configure(modalConfig) {\n        modalConfig.large = true;\n        super.configure(modalConfig);\n    }\n\n    /**\n     * Set the context id to the given value.\n     *\n     * @method setContextId\n     * @param {Number} id The event id\n     */\n    setContextId(id) {\n        this.contextId = id;\n    }\n\n    /**\n     * Retrieve the current context id, if any.\n     *\n     * @method getContextId\n     * @return {Number|null} The event id\n     */\n    getContextId() {\n        return this.contextId;\n    }\n\n    /**\n     * Set the course id to the given value.\n     *\n     * @method setCourseId\n     * @param {Number} id The event id\n     */\n    setCourseId(id) {\n        this.courseId = id;\n    }\n\n    /**\n     * Retrieve the current course id, if any.\n     *\n     * @method getCourseId\n     * @return {Number|null} The event id\n     */\n    getCourseId() {\n        return this.courseId;\n    }\n\n    /**\n     * Set the category id to the given value.\n     *\n     * @method setCategoryId\n     * @param {Number} id The event id\n     */\n    setCategoryId(id) {\n        this.categoryId = id;\n    }\n\n    /**\n     * Retrieve the current category id, if any.\n     *\n     * @method getCategoryId\n     * @return {Number|null} The event id\n     */\n    getCategoryId() {\n        return this.categoryId;\n    }\n\n    /**\n     * Check if the modal has an course id.\n     *\n     * @method hasCourseId\n     * @return {bool}\n     */\n    hasCourseId() {\n        return this.courseId !== null;\n    }\n\n    /**\n     * Check if the modal has an category id.\n     *\n     * @method hasCategoryId\n     * @return {bool}\n     */\n    hasCategoryId() {\n        return this.categoryId !== null;\n    }\n\n    /**\n     * Set the event id to the given value.\n     *\n     * @method setEventId\n     * @param {Number} id The event id\n     */\n    setEventId(id) {\n        this.eventId = id;\n    }\n\n    /**\n     * Retrieve the current event id, if any.\n     *\n     * @method getEventId\n     * @return {Number|null} The event id\n     */\n    getEventId() {\n        return this.eventId;\n    }\n\n    /**\n     * Check if the modal has an event id.\n     *\n     * @method hasEventId\n     * @return {bool}\n     */\n    hasEventId() {\n        return this.eventId !== null;\n    }\n\n    /**\n     * Set the start time to the given value.\n     *\n     * @method setStartTime\n     * @param {Number} time The start time\n     */\n    setStartTime(time) {\n        this.startTime = time;\n    }\n\n    /**\n     * Retrieve the current start time, if any.\n     *\n     * @method getStartTime\n     * @return {Number|null} The start time\n     */\n    getStartTime() {\n        return this.startTime;\n    }\n\n    /**\n     * Check if the modal has start time.\n     *\n     * @method hasStartTime\n     * @return {bool}\n     */\n    hasStartTime() {\n        return this.startTime !== null;\n    }\n\n    /**\n     * Get the form element from the modal.\n     *\n     * @method getForm\n     * @return {object}\n     */\n    getForm() {\n        return this.getBody().find('form');\n    }\n\n    /**\n     * Disable the buttons in the footer.\n     *\n     * @method disableButtons\n     */\n    disableButtons() {\n        this.saveButton.prop('disabled', true);\n    }\n\n    /**\n     * Enable the buttons in the footer.\n     *\n     * @method enableButtons\n     */\n    enableButtons() {\n        this.saveButton.prop('disabled', false);\n    }\n\n    /**\n     * Reload the title for the modal to the appropriate value\n     * depending on whether we are creating a new event or\n     * editing an existing event.\n     *\n     * @method reloadTitleContent\n     * @return {object} A promise resolved with the new title text\n     */\n    reloadTitleContent() {\n        if (this.reloadingTitle) {\n            return this.titlePromise;\n        }\n\n        this.reloadingTitle = true;\n\n        if (this.hasEventId()) {\n            this.titlePromise = Str.get_string('editevent', 'calendar');\n        } else {\n            this.titlePromise = Str.get_string('newevent', 'calendar');\n        }\n\n        this.titlePromise.then((string) => {\n            this.setTitle(string);\n            return string;\n        })\n        .catch(Notification.exception)\n        .always(() => {\n            this.reloadingTitle = false;\n            return;\n        });\n\n        return this.titlePromise;\n    }\n\n    /**\n     * Send a request to the server to get the event_form in a fragment\n     * and render the result in the body of the modal.\n     *\n     * If serialised form data is provided then it will be sent in the\n     * request to the server to have the form rendered with the data. This\n     * is used when the form had a server side error and we need the server\n     * to re-render it for us to display the error to the user.\n     *\n     * @method reloadBodyContent\n     * @param {string} formData The serialised form data\n     * @return {object} A promise resolved with the fragment html and js from\n     */\n    reloadBodyContent(formData) {\n        if (this.reloadingBody) {\n            return this.bodyPromise;\n        }\n\n        this.reloadingBody = true;\n        this.disableButtons();\n\n        const args = {};\n\n        if (this.hasEventId()) {\n            args.eventid = this.getEventId();\n        }\n\n        if (this.hasStartTime()) {\n            args.starttime = this.getStartTime();\n        }\n\n        if (this.hasCourseId()) {\n            args.courseid = this.getCourseId();\n        }\n\n        if (this.hasCategoryId()) {\n            args.categoryid = this.getCategoryId();\n        }\n\n        if (typeof formData !== 'undefined') {\n            args.formdata = formData;\n        }\n\n        this.bodyPromise = Fragment.loadFragment('calendar', 'event_form', this.getContextId(), args);\n\n        this.setBody(this.bodyPromise);\n\n        this.bodyPromise.then(() => {\n            this.enableButtons();\n            return;\n        })\n        .catch(Notification.exception)\n        .always(() => {\n            this.reloadingBody = false;\n            return;\n        });\n\n        return this.bodyPromise;\n    }\n\n    /**\n     * Reload both the title and body content.\n     *\n     * @method reloadAllContent\n     * @return {object} promise\n     */\n    reloadAllContent() {\n        return $.when(this.reloadTitleContent(), this.reloadBodyContent());\n    }\n\n    /**\n     * Kick off a reload the modal content before showing it. This\n     * is to allow us to re-use the same modal for creating and\n     * editing different events within the page.\n     *\n     * We do the reload when showing the modal rather than hiding it\n     * to save a request to the server if the user closes the modal\n     * and never re-opens it.\n     *\n     * @method show\n     */\n    show() {\n        this.reloadAllContent();\n        super.show(this);\n    }\n\n    /**\n     * Clear the event id from the modal when it's closed so\n     * that it is loaded fresh next time it's displayed.\n     *\n     * The event id will be set by the calling code if it wants\n     * to edit a specific event.\n     *\n     * @method hide\n     */\n    hide() {\n        super.hide(this);\n        this.setEventId(null);\n        this.setStartTime(null);\n        this.setCourseId(null);\n        this.setCategoryId(null);\n    }\n\n    /**\n     * Get the serialised form data.\n     *\n     * @method getFormData\n     * @return {string} serialised form data\n     */\n    getFormData() {\n        return this.getForm().serialize();\n    }\n\n    /**\n     * Send the form data to the server to create or update\n     * an event.\n     *\n     * If there is a server side validation error then we re-request the\n     * rendered form (with the data) from the server in order to get the\n     * server side errors to display.\n     *\n     * On success the modal is hidden and the page is reloaded so that the\n     * new event will display.\n     *\n     * @method save\n     * @return {object} A promise\n     */\n    save() {\n        const loadingContainer = this.saveButton.find(SELECTORS.LOADING_ICON_CONTAINER);\n\n        // Now the change events have run, see if there are any \"invalid\" form fields.\n        const invalid = this.getForm().find('[aria-invalid=\"true\"]');\n\n        // If we found invalid fields, focus on the first one and do not submit via ajax.\n        if (invalid.length) {\n            invalid.first().focus();\n            return Promise.resolve();\n        }\n\n        loadingContainer.removeClass('hidden');\n        this.disableButtons();\n\n        const formData = this.getFormData();\n        // Send the form data to the server for processing.\n        return Repository.submitCreateUpdateForm(formData)\n            .then((response) => {\n                if (response.validationerror) {\n                    // If there was a server side validation error then\n                    // we need to re-request the rendered form from the server\n                    // in order to display the error for the user.\n                    this.reloadBodyContent(formData);\n                    return;\n                } else {\n                    // Check whether this was a new event or not.\n                    // The hide function unsets the form data so grab this before the hide.\n                    const isExisting = this.hasEventId();\n\n                    // No problemo! Our work here is done.\n                    this.hide();\n\n                    // Trigger the appropriate calendar event so that the view can be updated.\n                    if (isExisting) {\n                        $('body').trigger(CalendarEvents.updated, [response.event]);\n                    } else {\n                        $('body').trigger(CalendarEvents.created, [response.event]);\n                    }\n                }\n\n                return;\n            })\n            .catch(Notification.exception)\n            .always(() => {\n                // Regardless of success or error we should always stop\n                // the loading icon and re-enable the buttons.\n                loadingContainer.addClass('hidden');\n                this.enableButtons();\n\n                return;\n            });\n    }\n\n    /**\n     * Set up all of the event handling for the modal.\n     *\n     * @method registerEventListeners\n     * @fires event:uploadStarted\n     * @fires event:formSubmittedByJavascript\n     */\n    registerEventListeners() {\n        // Apply parent event listeners.\n        super.registerEventListeners(this);\n\n        // When the user clicks the save button we trigger the form submission. We need to\n        // trigger an actual submission because there is some JS code in the form that is\n        // listening for this event and doing some stuff (e.g. saving draft areas etc).\n        this.getModal().on(CustomEvents.events.activate, SELECTORS.SAVE_BUTTON, (e, data) => {\n            this.getForm().submit();\n            data.originalEvent.preventDefault();\n            e.stopPropagation();\n        });\n\n        // Catch the submit event before it is actually processed by the browser and\n        // prevent the submission. We'll take it from here.\n        this.getModal().on('submit', (e) => {\n            FormEvents.notifyFormSubmittedByJavascript(this.getForm()[0]);\n\n            this.save();\n\n            // Stop the form from actually submitting and prevent it's\n            // propagation because we have already handled the event.\n            e.preventDefault();\n            e.stopPropagation();\n        });\n    }\n}\n\nModalEventForm.registerModalType();\n"],"names":["SELECTORS","ModalEventForm","Modal","constructor","root","eventId","startTime","courseId","categoryId","contextId","reloadingBody","reloadingTitle","saveButton","this","getFooter","find","configure","modalConfig","large","setContextId","id","getContextId","setCourseId","getCourseId","setCategoryId","getCategoryId","hasCourseId","hasCategoryId","setEventId","getEventId","hasEventId","setStartTime","time","getStartTime","hasStartTime","getForm","getBody","disableButtons","prop","enableButtons","reloadTitleContent","titlePromise","Str","get_string","then","string","setTitle","catch","Notification","exception","always","reloadBodyContent","formData","bodyPromise","args","eventid","starttime","courseid","categoryid","formdata","Fragment","loadFragment","setBody","reloadAllContent","$","when","show","hide","getFormData","serialize","save","loadingContainer","invalid","length","first","focus","Promise","resolve","removeClass","Repository","submitCreateUpdateForm","response","validationerror","isExisting","trigger","CalendarEvents","updated","event","created","addClass","registerEventListeners","getModal","on","CustomEvents","events","activate","e","data","submit","originalEvent","preventDefault","stopPropagation","FormEvents","notifyFormSubmittedByJavascript","registerModalType"],"mappings":"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"}