Proyectos de Subversion Moodle

Rev

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

{"version":3,"file":"grading_navigation.min.js","sources":["../src/grading_navigation.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 * Javascript to handle changing users via the user selector in the header.\n *\n * @module     mod_assign/grading_navigation\n * @copyright  2016 Damyon Wiese <damyon@moodle.com>\n * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since      3.1\n */\ndefine(['jquery', 'core/notification', 'core/str', 'core/form-autocomplete',\n        'core/ajax', 'core_user/repository', 'mod_assign/grading_form_change_checker'],\n       function($, notification, str, autocomplete, ajax, UserRepository, checker) {\n\n    /**\n     * GradingNavigation class.\n     *\n     * @class mod_assign/grading_navigation\n     * @param {String} selector The selector for the page region containing the user navigation.\n     */\n    var GradingNavigation = function(selector) {\n        this._regionSelector = selector;\n        this._region = $(selector);\n        this._filters = [];\n        this._users = [];\n        this._filteredUsers = [];\n        this._lastXofYUpdate = 0;\n        this._firstLoadUsers = true;\n\n        let url = new URL(window.location);\n        if (parseInt(url.searchParams.get('treset')) > 0) {\n            // Remove 'treset' url parameter to make sure that\n            // table preferences won't be reset on page refresh.\n            url.searchParams.delete('treset');\n            window.history.replaceState({}, \"\", url);\n        }\n\n        // Get the current user list from a webservice.\n        this._loadAllUsers();\n\n        // We do not allow navigation while ajax requests are pending.\n        // Attach listeners to the select and arrow buttons.\n\n        this._region.find('[data-action=\"previous-user\"]').on('click', this._handlePreviousUser.bind(this));\n        this._region.find('[data-action=\"next-user\"]').on('click', this._handleNextUser.bind(this));\n        this._region.find('[data-action=\"change-user\"]').on('change', this._handleChangeUser.bind(this));\n        this._region.find('[data-region=\"user-filters\"]').on('click', this._toggleExpandFilters.bind(this));\n        this._region.find('[data-region=\"user-resettable\"]').on('click', this._toggleResetTable.bind());\n\n        $(document).on('user-changed', this._refreshSelector.bind(this));\n        $(document).on('done-saving-show-next', this._handleNextUser.bind(this));\n\n        // Position the configure filters panel under the link that expands it.\n        var toggleLink = this._region.find('[data-region=\"user-filters\"]');\n        var configPanel = $(document.getElementById(toggleLink.attr('aria-controls')));\n\n        configPanel.on('change', 'select', this._filterChanged.bind(this));\n\n        var userid = $('[data-region=\"grading-navigation-panel\"]').data('first-userid');\n        if (userid) {\n            this._selectUserById(userid);\n        }\n\n        str.get_string('changeuser', 'mod_assign').done(function(s) {\n                autocomplete.enhance('[data-action=change-user]', false, 'mod_assign/participant_selector', s);\n            }\n        ).fail(notification.exception);\n\n        $(document).bind(\"start-loading-user\", function() {\n            this._isLoading = true;\n        }.bind(this));\n        $(document).bind(\"finish-loading-user\", function() {\n            this._isLoading = false;\n        }.bind(this));\n    };\n\n    /** @property {Boolean} Boolean tracking active ajax requests. */\n    GradingNavigation.prototype._isLoading = false;\n\n    /** @property {String} Selector for the page region containing the user navigation. */\n    GradingNavigation.prototype._regionSelector = null;\n\n    /** @property {Array} The list of active filter keys */\n    GradingNavigation.prototype._filters = null;\n\n    /** @property {Array} The list of users */\n    GradingNavigation.prototype._users = null;\n\n    /** @property {JQuery} JQuery node for the page region containing the user navigation. */\n    GradingNavigation.prototype._region = null;\n\n    /** @property {String} Last active filters */\n    GradingNavigation.prototype._lastFilters = '';\n\n    /**\n     * Load the list of all users for this assignment.\n     *\n     * @private\n     * @method _loadAllUsers\n     * @return {Boolean} True if the user list was fetched.\n     */\n    GradingNavigation.prototype._loadAllUsers = function() {\n        var select = this._region.find('[data-action=change-user]');\n        var assignmentid = select.attr('data-assignmentid');\n        var groupid = select.attr('data-groupid');\n\n        var filterPanel = this._region.find('[data-region=\"configure-filters\"]');\n        var filter = filterPanel.find('select[name=\"filter\"]').val();\n        var workflowFilter = filterPanel.find('select[name=\"workflowfilter\"]');\n        if (workflowFilter) {\n            filter += ',' + workflowFilter.val();\n        }\n        var markerFilter = filterPanel.find('select[name=\"markerfilter\"]');\n        if (markerFilter) {\n            filter += ',' + markerFilter.val();\n        }\n\n        if (this._lastFilters == filter) {\n            return false;\n        }\n        this._lastFilters = filter;\n\n        ajax.call([{\n            methodname: 'mod_assign_list_participants',\n            args: {assignid: assignmentid, groupid: groupid, filter: '', onlyids: true, tablesort: true},\n            done: this._usersLoaded.bind(this),\n            fail: notification.exception\n        }]);\n        return true;\n    };\n\n    /**\n     * Call back to rebuild the user selector and x of y info when the user list is updated.\n     *\n     * @private\n     * @method _usersLoaded\n     * @param {Array} users\n     */\n    GradingNavigation.prototype._usersLoaded = function(users) {\n        this._firstLoadUsers = false;\n        this._filteredUsers = this._users = users;\n        if (this._users.length) {\n            // Position the configure filters panel under the link that expands it.\n            var toggleLink = this._region.find('[data-region=\"user-filters\"]');\n            var configPanel = $(document.getElementById(toggleLink.attr('aria-controls')));\n\n            configPanel.find('select[name=\"filter\"]').trigger('change');\n        } else {\n            this._selectNoUser();\n        }\n        this._triggerNextUserEvent();\n    };\n\n    /**\n     * Close the configure filters panel if a click is detected outside of it.\n     *\n     * @private\n     * @method _checkClickOutsideConfigureFilters\n     * @param {Event} event\n     */\n    GradingNavigation.prototype._checkClickOutsideConfigureFilters = function(event) {\n        var configPanel = this._region.find('[data-region=\"configure-filters\"]');\n\n        if (!configPanel.is(event.target) && configPanel.has(event.target).length === 0) {\n            var toggleLink = this._region.find('[data-region=\"user-filters\"]');\n\n            configPanel.hide();\n            configPanel.attr('aria-hidden', 'true');\n            toggleLink.attr('aria-expanded', 'false');\n            $(document).unbind('click.mod_assign_grading_navigation');\n        }\n    };\n\n    /**\n     * Close the configure filters panel if a click is detected outside of it.\n     *\n     * @private\n     * @method _updateFilterPreference\n     * @param {Number} userId The current user id.\n     * @param {Array} filterList The list of current filter values.\n     * @param {Array} preferenceNames The names of the preferences to update\n     * @return {Promise} Resolved when all the preferences are updated.\n     */\n    GradingNavigation.prototype._updateFilterPreferences = function(userId, filterList, preferenceNames) {\n        var preferences = [],\n            i = 0;\n\n        if (filterList.length == 0 || this._firstLoadUsers) {\n            // Nothing to update.\n            var deferred = $.Deferred();\n            deferred.resolve();\n            return deferred;\n        }\n        // General filter.\n        // Set the user preferences to the current filters.\n        for (i = 0; i < filterList.length; i++) {\n            var newValue = filterList[i];\n            if (newValue == 'none') {\n                newValue = '';\n            }\n\n            preferences.push({\n                userid: userId,\n                name: preferenceNames[i],\n                value: newValue\n            });\n        }\n\n        return UserRepository.setUserPreferences(preferences);\n    };\n    /**\n     * Turn a filter on or off.\n     *\n     * @private\n     * @method _filterChanged\n     */\n    GradingNavigation.prototype._filterChanged = function() {\n        // There are 3 types of filter right now.\n        var filterPanel = this._region.find('[data-region=\"configure-filters\"]');\n        var filters = filterPanel.find('select');\n        var preferenceNames = [];\n\n        this._filters = [];\n        filters.each(function(idx, ele) {\n            var element = $(ele);\n            this._filters.push(element.val());\n            preferenceNames.push('assign_' + element.prop('name'));\n        }.bind(this));\n\n        // Update the active filter string.\n        var filterlist = [];\n        filterPanel.find('option:checked').each(function(idx, ele) {\n            filterlist[filterlist.length] = $(ele).text();\n        });\n        if (filterlist.length) {\n            this._region.find('[data-region=\"user-filters\"] span').text(filterlist.join(', '));\n        } else {\n            str.get_string('nofilters', 'mod_assign').done(function(s) {\n                this._region.find('[data-region=\"user-filters\"] span').text(s);\n            }.bind(this)).fail(notification.exception);\n        }\n\n        var select = this._region.find('[data-action=change-user]');\n        var currentUserID = select.data('currentuserid');\n        this._updateFilterPreferences(currentUserID, this._filters, preferenceNames).done(function() {\n            // Reload the list of users to apply the new filters.\n            if (!this._loadAllUsers()) {\n                var userid = parseInt(select.attr('data-selected'));\n                let foundIndex = null;\n                // Search the returned users for the current selection.\n                $.each(this._filteredUsers, function(index, user) {\n                    if (userid == user.id) {\n                        foundIndex = index;\n                    }\n                });\n\n                if (this._filteredUsers.length && foundIndex !== null) {\n                    this._selectUserById(this._filteredUsers[foundIndex].id);\n                } else {\n                    this._selectNoUser();\n                }\n\n            }\n        }.bind(this)).fail(notification.exception);\n        this._refreshCount();\n    };\n\n    /**\n     * Select no users, because no users match the filters.\n     *\n     * @private\n     * @method _selectNoUser\n     */\n    GradingNavigation.prototype._selectNoUser = function() {\n        // Detect unsaved changes, and offer to save them - otherwise change user right now.\n        if (this._isLoading) {\n            return;\n        }\n        if (checker.checkFormForChanges('[data-region=\"grade-panel\"] .gradeform')) {\n            // Form has changes, so we need to confirm before switching users.\n            str.get_strings([\n                {key: 'unsavedchanges', component: 'mod_assign'},\n                {key: 'unsavedchangesquestion', component: 'mod_assign'},\n                {key: 'saveandcontinue', component: 'mod_assign'},\n                {key: 'cancel', component: 'core'},\n            ]).done(function(strs) {\n                notification.confirm(strs[0], strs[1], strs[2], strs[3], function() {\n                    $(document).trigger('save-changes', -1);\n                });\n            });\n        } else {\n            $(document).trigger('user-changed', -1);\n        }\n    };\n\n    /**\n     * Select the specified user by id.\n     *\n     * @private\n     * @method _selectUserById\n     * @param {Number} userid\n     */\n    GradingNavigation.prototype._selectUserById = function(userid) {\n        var select = this._region.find('[data-action=change-user]');\n        var useridnumber = parseInt(userid, 10);\n\n        // Detect unsaved changes, and offer to save them - otherwise change user right now.\n        if (this._isLoading) {\n            return;\n        }\n        if (checker.checkFormForChanges('[data-region=\"grade-panel\"] .gradeform')) {\n            // Form has changes, so we need to confirm before switching users.\n            str.get_strings([\n                {key: 'unsavedchanges', component: 'mod_assign'},\n                {key: 'unsavedchangesquestion', component: 'mod_assign'},\n                {key: 'saveandcontinue', component: 'mod_assign'},\n                {key: 'cancel', component: 'core'},\n            ]).done(function(strs) {\n                notification.confirm(strs[0], strs[1], strs[2], strs[3], function() {\n                    $(document).trigger('save-changes', useridnumber);\n                });\n            });\n        } else {\n            select.attr('data-selected', userid);\n\n            // If we have some filtered users, and userid is specified, then trigger change.\n            if (this._filteredUsers.length > 0 && !isNaN(useridnumber) && useridnumber > 0) {\n                $(document).trigger('user-changed', useridnumber);\n            }\n        }\n    };\n\n    /**\n     * Expand or collapse the filter config panel.\n     *\n     * @private\n     * @method _toggleExpandFilters\n     * @param {Event} event\n     */\n    GradingNavigation.prototype._toggleExpandFilters = function(event) {\n        event.preventDefault();\n        var toggleLink = $(event.target).closest('[data-region=\"user-filters\"]');\n        var expanded = toggleLink.attr('aria-expanded') == 'true';\n        var configPanel = $(document.getElementById(toggleLink.attr('aria-controls')));\n\n        if (expanded) {\n            configPanel.hide();\n            configPanel.attr('aria-hidden', 'true');\n            toggleLink.attr('aria-expanded', 'false');\n            $(document).unbind('click.mod_assign_grading_navigation');\n        } else {\n            configPanel.css('display', 'inline-block');\n            configPanel.attr('aria-hidden', 'false');\n            toggleLink.attr('aria-expanded', 'true');\n            event.stopPropagation();\n            $(document).on('click.mod_assign_grading_navigation', this._checkClickOutsideConfigureFilters.bind(this));\n        }\n    };\n\n    /**\n     * Reset table preferences.\n     *\n     * @private\n     * @method _toggleResetTable\n     */\n    GradingNavigation.prototype._toggleResetTable = function() {\n        let url = new URL(window.location);\n        url.searchParams.set('treset', '1');\n        window.location.href = url;\n    };\n\n    /**\n     * Change to the previous user in the grading list.\n     *\n     * @private\n     * @method _handlePreviousUser\n     * @param {Event} e\n     */\n    GradingNavigation.prototype._handlePreviousUser = function(e) {\n        e.preventDefault();\n        var select = this._region.find('[data-action=change-user]');\n        var currentUserId = select.attr('data-selected');\n        var i = 0;\n        var currentIndex = 0;\n\n        for (i = 0; i < this._filteredUsers.length; i++) {\n            if (this._filteredUsers[i].id == currentUserId) {\n                currentIndex = i;\n                break;\n            }\n        }\n\n        var count = this._filteredUsers.length;\n        var newIndex = (currentIndex - 1);\n        if (newIndex < 0) {\n            newIndex = count - 1;\n        }\n\n        if (count) {\n            this._selectUserById(this._filteredUsers[newIndex].id);\n        }\n    };\n\n    /**\n     * Change to the next user in the grading list.\n     *\n     * @param {Event} e\n     * @param {Boolean} saved Has the form already been saved? Skips checking for changes if true.\n     */\n    GradingNavigation.prototype._handleNextUser = function(e, saved) {\n        e.preventDefault();\n        var select = this._region.find('[data-action=change-user]');\n        var currentUserId = select.attr('data-selected');\n        var i = 0;\n        var currentIndex = 0;\n\n        for (i = 0; i < this._filteredUsers.length; i++) {\n            if (this._filteredUsers[i].id == currentUserId) {\n                currentIndex = i;\n                break;\n            }\n        }\n\n        var count = this._filteredUsers.length;\n        var newIndex = (currentIndex + 1) % count;\n\n        if (saved && count) {\n            // If we've already saved the grade, skip checking if we've made any changes.\n            var userid = this._filteredUsers[newIndex].id;\n            var useridnumber = parseInt(userid, 10);\n            select.attr('data-selected', userid);\n            if (!isNaN(useridnumber) && useridnumber > 0) {\n                $(document).trigger('user-changed', userid);\n            }\n        } else if (count) {\n            this._selectUserById(this._filteredUsers[newIndex].id);\n        }\n    };\n\n    /**\n     * Set count string. This method only sets the value for the last time it was ever called to deal\n     * with promises that return in a non-predictable order.\n     *\n     * @private\n     * @method _setCountString\n     * @param {Number} x\n     * @param {Number} y\n     */\n    GradingNavigation.prototype._setCountString = function(x, y) {\n        var updateNumber = 0;\n        this._lastXofYUpdate++;\n        updateNumber = this._lastXofYUpdate;\n\n        var param = {x: x, y: y};\n        str.get_string('xofy', 'mod_assign', param).done(function(s) {\n            if (updateNumber == this._lastXofYUpdate) {\n                this._region.find('[data-region=\"user-count-summary\"]').text(s);\n            }\n        }.bind(this)).fail(notification.exception);\n    };\n\n    /**\n     * Rebuild the x of y string.\n     *\n     * @private\n     * @method _refreshCount\n     */\n    GradingNavigation.prototype._refreshCount = function() {\n        var select = this._region.find('[data-action=change-user]');\n        var userid = select.attr('data-selected');\n        var i = 0;\n        var currentIndex = 0;\n\n        if (isNaN(userid) || userid <= 0) {\n            this._region.find('[data-region=\"user-count\"]').hide();\n        } else {\n            this._region.find('[data-region=\"user-count\"]').show();\n\n            for (i = 0; i < this._filteredUsers.length; i++) {\n                if (this._filteredUsers[i].id == userid) {\n                    currentIndex = i;\n                    break;\n                }\n            }\n            var count = this._filteredUsers.length;\n            if (count) {\n                currentIndex += 1;\n            }\n            this._setCountString(currentIndex, count);\n            // Update window URL\n            if (currentIndex > 0) {\n                var url = new URL(window.location);\n                if (parseInt(url.searchParams.get('blindid')) > 0) {\n                    var newid = this._filteredUsers[currentIndex - 1].recordid;\n                    url.searchParams.set('blindid', newid);\n                } else {\n                    url.searchParams.set('userid', userid);\n                }\n                // We do this so a browser refresh will return to the same user.\n                window.history.replaceState({}, \"\", url);\n            }\n        }\n    };\n\n    /**\n     * Respond to a user-changed event by updating the selector.\n     *\n     * @private\n     * @method _refreshSelector\n     * @param {Event} event\n     * @param {String} userid\n     */\n    GradingNavigation.prototype._refreshSelector = function(event, userid) {\n        var select = this._region.find('[data-action=change-user]');\n        userid = parseInt(userid, 10);\n\n        if (!isNaN(userid) && userid > 0) {\n            select.attr('data-selected', userid);\n        }\n        this._refreshCount();\n    };\n\n    /**\n     * Trigger the next user event depending on the number of filtered users\n     *\n     * @private\n     * @method _triggerNextUserEvent\n     */\n    GradingNavigation.prototype._triggerNextUserEvent = function() {\n        if (this._filteredUsers.length > 1) {\n            $(document).trigger('next-user', {nextUserId: null, nextUser: true});\n        } else {\n            $(document).trigger('next-user', {nextUser: false});\n        }\n    };\n\n    /**\n     * Change to a different user in the grading list.\n     *\n     * @private\n     * @method _handleChangeUser\n     */\n    GradingNavigation.prototype._handleChangeUser = function() {\n        var select = this._region.find('[data-action=change-user]');\n        var userid = parseInt(select.val(), 10);\n\n        if (this._isLoading) {\n            return;\n        }\n        if (checker.checkFormForChanges('[data-region=\"grade-panel\"] .gradeform')) {\n            // Form has changes, so we need to confirm before switching users.\n            str.get_strings([\n                {key: 'unsavedchanges', component: 'mod_assign'},\n                {key: 'unsavedchangesquestion', component: 'mod_assign'},\n                {key: 'saveandcontinue', component: 'mod_assign'},\n                {key: 'cancel', component: 'core'},\n            ]).done(function(strs) {\n                notification.confirm(strs[0], strs[1], strs[2], strs[3], function() {\n                    $(document).trigger('save-changes', userid);\n                });\n            });\n        } else {\n            if (!isNaN(userid) && userid > 0) {\n                select.attr('data-selected', userid);\n\n                $(document).trigger('user-changed', userid);\n            }\n        }\n    };\n\n    return GradingNavigation;\n});\n"],"names":["define","$","notification","str","autocomplete","ajax","UserRepository","checker","GradingNavigation","selector","_regionSelector","_region","_filters","_users","_filteredUsers","_lastXofYUpdate","_firstLoadUsers","url","URL","window","location","parseInt","searchParams","get","delete","history","replaceState","_loadAllUsers","find","on","this","_handlePreviousUser","bind","_handleNextUser","_handleChangeUser","_toggleExpandFilters","_toggleResetTable","document","_refreshSelector","toggleLink","getElementById","attr","_filterChanged","userid","data","_selectUserById","get_string","done","s","enhance","fail","exception","_isLoading","prototype","_lastFilters","select","assignmentid","groupid","filterPanel","filter","val","workflowFilter","markerFilter","call","methodname","args","assignid","onlyids","tablesort","_usersLoaded","users","length","trigger","_selectNoUser","_triggerNextUserEvent","_checkClickOutsideConfigureFilters","event","configPanel","is","target","has","hide","unbind","_updateFilterPreferences","userId","filterList","preferenceNames","preferences","i","deferred","Deferred","resolve","newValue","push","name","value","setUserPreferences","filters","each","idx","ele","element","prop","filterlist","text","join","currentUserID","foundIndex","index","user","id","_refreshCount","checkFormForChanges","get_strings","key","component","strs","confirm","useridnumber","isNaN","preventDefault","closest","expanded","css","stopPropagation","set","href","e","currentUserId","currentIndex","count","newIndex","saved","_setCountString","x","y","updateNumber","param","show","newid","recordid","nextUserId","nextUser"],"mappings":"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"}