Proyectos de Subversion Moodle

Rev

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

{"version":3,"file":"filters.min.js","sources":["../src/filters.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 * Module responsible for handling forum summary report filters.\n *\n * @module     forumreport_summary/filters\n * @copyright  2019 Michael Hawkins <michaelh@moodle.com>\n * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from 'jquery';\nimport {createPopper} from 'core/popper2';\nimport CustomEvents from 'core/custom_interaction_events';\nimport Selectors from 'forumreport_summary/selectors';\nimport Ajax from 'core/ajax';\nimport KeyCodes from 'core/key_codes';\nimport * as FormChangeChecker from 'core_form/changechecker';\n\nexport const init = (root) => {\n    let jqRoot = $(root);\n\n    // Hide loading spinner and show report once page is ready.\n    // This ensures filters can be applied when sorting by columns.\n    $(document).ready(function() {\n        $('.loading-icon').hide();\n        $('#summaryreport').removeClass('hidden');\n    });\n\n    // Generic filter handlers.\n\n    // Called to override click event to trigger a proper generate request with filtering.\n    const generateWithFilters = (event, getparams) => {\n        let currentLink = document.forms.filtersform.action,\n            newLink;\n\n        if (event) {\n            event.preventDefault();\n\n           let currentSplit = currentLink.split('?'),\n               currentstring = currentSplit[1],\n               newparamsarray = getparams.split('&'),\n               paramsstring = '',\n               paramkeys = [],\n               paramvalues = [];\n\n            // Separate out the existing action GET param string.\n            currentstring.split('&').forEach(function(param) {\n                let splitparam = param.split('=');\n                paramkeys.push(splitparam[0]);\n                paramvalues.push(splitparam[1]);\n            });\n\n            newparamsarray.forEach(function(paramstring) {\n                let newparam = paramstring.split('='),\n                    existingkey = paramkeys.indexOf(newparam[0]);\n\n                // Overwrite value if existing, otherwise add new param.\n                if (existingkey > -1) {\n                    paramvalues[existingkey] = newparam[1];\n                } else {\n                    paramkeys.push(newparam[0]);\n                    paramvalues.push(newparam[1]);\n                }\n            });\n\n            // Build URL.\n            paramkeys.forEach(function(name, key) {\n                paramsstring += `&${name}=${paramvalues[key]}`;\n            });\n\n            newLink = currentSplit[0] + '?' + paramsstring.substr(1);\n        } else {\n            newLink = currentLink;\n        }\n\n        document.forms.filtersform.action = newLink;\n        document.forms.filtersform.submit();\n    };\n\n    // Override 'reset table preferences' so it generates with filters.\n    $('.resettable').on(\"click\", \"a\", function(event) {\n        generateWithFilters(event, event.target.search.substr(1));\n    });\n\n    // Override table heading sort links so they generate with filters.\n    $('thead').on(\"click\", \"a\", function(event) {\n        generateWithFilters(event, event.target.search.substr(1));\n    });\n\n    // Override pagination page links so they generate with filters.\n    $('.pagination').on(\"click\", \"a\", function(event) {\n        generateWithFilters(event, event.target.search.substr(1));\n    });\n\n    // Override rows per page submission so it generates with filters.\n    if (document.forms.selectperpage) {\n        document.forms.selectperpage.onsubmit = (event) => {\n            let getparam = 'perpage=' + document.forms.selectperpage.elements.perpage.value;\n            generateWithFilters(event, getparam);\n        };\n    }\n\n    // Override download link so the file is generated with filters.\n    const downloadForm = document.getElementById('summaryreport').querySelector('form.dataformatselector');\n    if (downloadForm) {\n        downloadForm.onsubmit = (event) => {\n            const downloadType = downloadForm.querySelector('#downloadtype_download').value;\n            const getParams = `download=${downloadType}`;\n            const prevAction = document.forms.filtersform.action;\n\n            generateWithFilters(event, getParams);\n\n            // Revert action, so re-submitting the form via filter does not trigger a further download.\n            document.forms.filtersform.action = prevAction;\n        };\n    }\n\n    // Submit report via filter\n    const submitWithFilter = (containerelement) => {\n        // Disable the dates filter mform checker to prevent any changes triggering a warning to the user.\n        FormChangeChecker.unWatchForm(document.forms.filtersform);\n\n        // Close the container (eg popover).\n        $(containerelement).addClass('hidden');\n\n        // Submit the filter values and re-generate report.\n        generateWithFilters(false);\n    };\n\n    // Use popper to override date mform calendar position.\n    const updateCalendarPosition = (referenceid) => {\n        let referenceElement = document.querySelector(referenceid),\n            popperContent = document.querySelector(Selectors.filters.date.calendar);\n\n        popperContent.style.removeProperty(\"z-index\");\n        createPopper(referenceElement, popperContent, {placement: 'bottom-end'});\n    };\n\n    // Close the relevant filter.\n    const closeOpenFilters = (openFilterButton, openFilter) => {\n        openFilter.classList.add('hidden');\n        openFilter.setAttribute('data-openfilter', 'false');\n\n        openFilterButton.classList.add('btn-primary');\n        openFilterButton.classList.remove('btn-outline-primary');\n        openFilterButton.setAttribute('aria-expanded', false);\n    };\n\n    // Groups filter specific handlers.\n\n    // Event handler for clicking select all groups.\n    jqRoot.on(CustomEvents.events.activate, Selectors.filters.group.selectall, function() {\n        let deselected = root.querySelectorAll(Selectors.filters.group.checkbox + ':not(:checked)');\n        deselected.forEach(function(checkbox) {\n            checkbox.checked = true;\n        });\n    });\n\n    // Event handler for clearing filter by clicking option.\n    jqRoot.on(CustomEvents.events.activate, Selectors.filters.group.clear, function() {\n        // Clear checkboxes.\n        let selected = root.querySelectorAll(Selectors.filters.group.checkbox + ':checked');\n        selected.forEach(function(checkbox) {\n            checkbox.checked = false;\n        });\n    });\n\n    // Event handler for showing groups filter popover.\n    jqRoot.on(CustomEvents.events.activate, Selectors.filters.group.trigger, function() {\n        // Create popover.\n        let referenceElement = root.querySelector(Selectors.filters.group.trigger),\n            popperContent = root.querySelector(Selectors.filters.group.popover);\n\n        createPopper(referenceElement, popperContent, {placement: 'bottom-end'});\n\n        // Show popover.\n        popperContent.classList.remove('hidden');\n        popperContent.setAttribute('data-openfilter', 'true');\n\n        // Change to outlined button.\n        referenceElement.classList.add('btn-outline-primary');\n        referenceElement.classList.remove('btn-primary');\n\n        // Let screen readers know that it's now expanded.\n        referenceElement.setAttribute('aria-expanded', true);\n\n        // Add listeners to handle closing filter.\n        const closeListener = e => {\n            if (e.target.id !== referenceElement.id && popperContent !== e.target.closest('[data-openfilter=\"true\"]') &&\n                    (typeof e.keyCode === 'undefined' || e.keyCode === KeyCodes.enter || e.keyCode === KeyCodes.space)) {\n                closeOpenFilters(referenceElement, popperContent);\n                document.removeEventListener('click', closeListener);\n                document.removeEventListener('keyup', closeListener);\n                document.removeEventListener('keyup', escCloseListener);\n            }\n        };\n\n        document.addEventListener('click', closeListener);\n        document.addEventListener('keyup', closeListener);\n\n        const escCloseListener = e => {\n            if (e.keyCode === KeyCodes.escape) {\n                closeOpenFilters(referenceElement, popperContent);\n                document.removeEventListener('keyup', escCloseListener);\n                document.removeEventListener('click', closeListener);\n            }\n        };\n\n        document.addEventListener('keyup', escCloseListener);\n    });\n\n    // Event handler to click save groups filter.\n    jqRoot.on(CustomEvents.events.activate, Selectors.filters.group.save, function() {\n        // Copy the saved values into the form before submitting.\n        let popcheckboxes = root.querySelectorAll(Selectors.filters.group.checkbox);\n\n        popcheckboxes.forEach(function(popcheckbox) {\n            let filtersform = document.forms.filtersform,\n                saveid = popcheckbox.getAttribute('data-saveid');\n\n            filtersform.querySelector(`#${saveid}`).checked = popcheckbox.checked;\n        });\n\n        submitWithFilter('#filter-groups-popover');\n    });\n\n    // Listeners for export buttons.\n    // These allow fetching of the relevant export URL, before submitting the request with\n    // any POST data that is common to all of the export links. This allows filters to be\n    // applied that contain potentially a lot of data (eg discussion IDs for groups filtering).\n    document.querySelectorAll(Selectors.filters.exportlink.link).forEach(function(exportbutton) {\n        exportbutton.addEventListener('click', function(event) {\n            document.forms.exportlinkform.action = event.target.dataset.url;\n            document.forms.exportlinkform.submit();\n        });\n    });\n\n    // Dates filter specific handlers.\n\n   // Event handler for showing dates filter popover.\n    jqRoot.on(CustomEvents.events.activate, Selectors.filters.date.trigger, function() {\n\n        // Create popover.\n        let referenceElement = root.querySelector(Selectors.filters.date.trigger),\n            popperContent = root.querySelector(Selectors.filters.date.popover);\n\n        createPopper(referenceElement, popperContent, {placement: 'bottom-end'});\n\n        // Show popover and move focus.\n        popperContent.classList.remove('hidden');\n        popperContent.setAttribute('data-openfilter', 'true');\n        popperContent.querySelector('[name=\"filterdatefrompopover[enabled]\"]').focus();\n\n        // Change to outlined button.\n        referenceElement.classList.add('btn-outline-primary');\n        referenceElement.classList.remove('btn-primary');\n\n        // Let screen readers know that it's now expanded.\n        referenceElement.setAttribute('aria-expanded', true);\n\n        // Add listener to handle closing filter.\n        const closeListener = e => {\n            if (e.target.id !== referenceElement.id && popperContent !== e.target.closest('[data-openfilter=\"true\"]') &&\n                    (typeof e.keyCode === 'undefined' || e.keyCode === KeyCodes.enter || e.keyCode === KeyCodes.space)) {\n                closeOpenFilters(referenceElement, popperContent);\n                document.removeEventListener('click', closeListener);\n                document.removeEventListener('keyup', closeListener);\n                document.removeEventListener('keyup', escCloseListener);\n            }\n        };\n\n        document.addEventListener('click', closeListener);\n        document.addEventListener('keyup', closeListener);\n\n        const escCloseListener = e => {\n            if (e.keyCode === KeyCodes.escape) {\n                closeOpenFilters(referenceElement, popperContent);\n                document.removeEventListener('keyup', escCloseListener);\n                document.removeEventListener('click', closeListener);\n            }\n        };\n\n        document.addEventListener('keyup', escCloseListener);\n    });\n\n    // Event handler to save dates filter.\n    jqRoot.on(CustomEvents.events.activate, Selectors.filters.date.save, function() {\n        // Populate the hidden form inputs to submit the data.\n        let filtersForm = document.forms.filtersform;\n        const datesPopover = root.querySelector(Selectors.filters.date.popover);\n        const fromEnabled = datesPopover.querySelector('[name=\"filterdatefrompopover[enabled]\"]').checked ? 1 : 0;\n        const toEnabled = datesPopover.querySelector('[name=\"filterdatetopopover[enabled]\"]').checked ? 1 : 0;\n\n        if (!fromEnabled && !toEnabled) {\n            // Update the elements in the filter form.\n            filtersForm.elements['datefrom[timestamp]'].value = 0;\n            filtersForm.elements['datefrom[enabled]'].value = fromEnabled;\n            filtersForm.elements['dateto[timestamp]'].value = 0;\n            filtersForm.elements['dateto[enabled]'].value = toEnabled;\n\n            // Submit the filter values and re-generate report.\n            submitWithFilter('#filter-dates-popover');\n        } else {\n            let args = {data: []};\n\n            if (fromEnabled) {\n                args.data.push({\n                    'key': 'from',\n                    'year': datesPopover.querySelector('[name=\"filterdatefrompopover[year]\"]').value,\n                    'month': datesPopover.querySelector('[name=\"filterdatefrompopover[month]\"]').value,\n                    'day': datesPopover.querySelector('[name=\"filterdatefrompopover[day]\"]').value,\n                    'hour': 0,\n                    'minute': 0\n                });\n            }\n\n            if (toEnabled) {\n                args.data.push({\n                    'key': 'to',\n                    'year': datesPopover.querySelector('[name=\"filterdatetopopover[year]\"]').value,\n                    'month': datesPopover.querySelector('[name=\"filterdatetopopover[month]\"]').value,\n                    'day': datesPopover.querySelector('[name=\"filterdatetopopover[day]\"]').value,\n                    'hour': 23,\n                    'minute': 59\n                });\n            }\n\n            const request = {\n                methodname: 'core_calendar_get_timestamps',\n                args: args\n            };\n\n            Ajax.call([request])[0].done(function(result) {\n                let fromTimestamp = 0,\n                    toTimestamp = 0;\n\n                result.timestamps.forEach(function(data) {\n                    if (data.key === 'from') {\n                        fromTimestamp = data.timestamp;\n                    } else if (data.key === 'to') {\n                        toTimestamp = data.timestamp;\n                    }\n                });\n\n                // Display an error if the from date is later than the do date.\n                if (toTimestamp > 0 && fromTimestamp > toTimestamp) {\n                    const warningdiv = document.getElementById('dates-filter-warning');\n                    warningdiv.classList.remove('hidden');\n                    warningdiv.classList.add('d-block');\n                } else {\n                    filtersForm.elements['datefrom[timestamp]'].value = fromTimestamp;\n                    filtersForm.elements['datefrom[enabled]'].value = fromEnabled;\n                    filtersForm.elements['dateto[timestamp]'].value = toTimestamp;\n                    filtersForm.elements['dateto[enabled]'].value = toEnabled;\n\n                    // Submit the filter values and re-generate report.\n                    submitWithFilter('#filter-dates-popover');\n                }\n            });\n        }\n    });\n\n    jqRoot.on(CustomEvents.events.activate, Selectors.filters.date.calendariconfrom, function() {\n        updateCalendarPosition(Selectors.filters.date.calendariconfrom);\n    });\n\n    jqRoot.on(CustomEvents.events.activate, Selectors.filters.date.calendariconto, function() {\n        updateCalendarPosition(Selectors.filters.date.calendariconto);\n    });\n};\n"],"names":["root","jqRoot","document","ready","hide","removeClass","generateWithFilters","event","getparams","newLink","currentLink","forms","filtersform","action","preventDefault","currentSplit","split","currentstring","newparamsarray","paramsstring","paramkeys","paramvalues","forEach","param","splitparam","push","paramstring","newparam","existingkey","indexOf","name","key","substr","submit","on","target","search","selectperpage","onsubmit","getparam","elements","perpage","value","downloadForm","getElementById","querySelector","downloadType","getParams","prevAction","submitWithFilter","containerelement","FormChangeChecker","unWatchForm","addClass","updateCalendarPosition","referenceid","referenceElement","popperContent","Selectors","filters","date","calendar","style","removeProperty","placement","closeOpenFilters","openFilterButton","openFilter","classList","add","setAttribute","remove","CustomEvents","events","activate","group","selectall","querySelectorAll","checkbox","checked","clear","trigger","popover","closeListener","e","id","closest","keyCode","KeyCodes","enter","space","removeEventListener","escCloseListener","addEventListener","escape","save","popcheckbox","saveid","getAttribute","exportlink","link","exportbutton","exportlinkform","dataset","url","focus","filtersForm","datesPopover","fromEnabled","toEnabled","args","data","request","methodname","call","done","result","fromTimestamp","toTimestamp","timestamps","timestamp","warningdiv","calendariconfrom","calendariconto"],"mappings":"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"}