MDL-68612 user: Set the initial filter on page load

This commit is contained in:
Andrew Nicols 2020-05-22 18:59:41 +08:00 committed by Michael Hawkins
parent 5187e7c515
commit 084c955e49
12 changed files with 160 additions and 22 deletions

View file

@ -1,2 +1,2 @@
define ("core_user/local/participantsfilter/filter",["exports","core/form-autocomplete","./selectors","core/str"],function(a,b,c,d){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;b=e(b);c=e(c);function e(a){return a&&a.__esModule?a:{default:a}}function f(a,b,c,d,e,f,g){try{var h=a[f](g),i=h.value}catch(a){c(a);return}if(h.done){b(i)}else{Promise.resolve(i).then(d,e)}}function g(a){return function(){var b=this,c=arguments;return new Promise(function(d,e){var i=a.apply(b,c);function g(a){f(i,d,e,g,h,"next",a)}function h(a){f(i,d,e,g,h,"throw",a)}g(void 0)})}}function h(a,b){if(!(a instanceof b)){throw new TypeError("Cannot call a class as a function")}}function i(a,b){for(var c=0,d;c<b.length;c++){d=b[c];d.enumerable=d.enumerable||!1;d.configurable=!0;if("value"in d)d.writable=!0;Object.defineProperty(a,d.key,d)}}function j(a,b,c){if(b)i(a.prototype,b);if(c)i(a,c);return a}var k=function(a){return a.querySelectorAll(":checked")},l=function(){function a(b,c){h(this,a);this.filterType=b;this.rootNode=c;this.addValueSelector()}j(a,[{key:"tearDown",value:function tearDown(){}},{key:"addValueSelector",value:function(){var a=g(regeneratorRuntime.mark(function a(){var c,d;return regeneratorRuntime.wrap(function(a){while(1){switch(a.prev=a.next){case 0:c=this.getFilterValueNode();c.innerHTML=this.getSourceDataForFilter().outerHTML;d=c.querySelector("select");a.t0=b.default;a.t1=d;a.t2="1"==d.dataset.allowCustom;a.next=8;return this.placeholder;case 8:a.t3=a.sent;a.t4=this.showSuggestions;a.t5=!d.multiple;a.t6={items:"core_user/local/participantsfilter/autocomplete_selection_items",layout:"core_user/local/participantsfilter/autocomplete_layout",selection:"core_user/local/participantsfilter/autocomplete_selection"};a.t0.enhance.call(a.t0,a.t1,a.t2,null,a.t3,!1,a.t4,null,a.t5,a.t6);case 13:case"end":return a.stop();}}},a,this)}));return function addValueSelector(){return a.apply(this,arguments)}}()},{key:"getSourceDataForFilter",value:function getSourceDataForFilter(){var a=this.rootNode.querySelector(c.default.filterset.regions.datasource);return a.querySelector(c.default.data.fields.byName(this.filterType))}},{key:"getFilterValueNode",value:function getFilterValueNode(){return this.filterRoot.querySelector(c.default.filter.regions.values)}},{key:"placeholder",get:function get(){return(0,d.get_string)("placeholdertypeorselect","core_user")}},{key:"showSuggestions",get:function get(){return!0}},{key:"filterRoot",get:function get(){return this.rootNode.querySelector(c.default.filter.byName(this.filterType))}},{key:"name",get:function get(){return this.filterType}},{key:"jointype",get:function get(){return this.filterRoot.querySelector(c.default.filter.fields.join).value}},{key:"rawValues",get:function get(){var a=this.getFilterValueNode(),b=a.querySelector("select");return Object.values(k(b)).map(function(a){return a.value})}},{key:"values",get:function get(){return this.rawValues.map(function(a){return parseInt(a,10)})}},{key:"filterValue",get:function get(){return{name:this.name,jointype:this.jointype,values:this.values}}}]);return a}();a.default=l;return a.default});
define ("core_user/local/participantsfilter/filter",["exports","core/form-autocomplete","./selectors","core/str"],function(a,b,c,d){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;b=e(b);c=e(c);function e(a){return a&&a.__esModule?a:{default:a}}function f(a,b,c,d,e,f,g){try{var h=a[f](g),i=h.value}catch(a){c(a);return}if(h.done){b(i)}else{Promise.resolve(i).then(d,e)}}function g(a){return function(){var b=this,c=arguments;return new Promise(function(d,e){var i=a.apply(b,c);function g(a){f(i,d,e,g,h,"next",a)}function h(a){f(i,d,e,g,h,"throw",a)}g(void 0)})}}function h(a,b){if(!(a instanceof b)){throw new TypeError("Cannot call a class as a function")}}function i(a,b){for(var c=0,d;c<b.length;c++){d=b[c];d.enumerable=d.enumerable||!1;d.configurable=!0;if("value"in d)d.writable=!0;Object.defineProperty(a,d.key,d)}}function j(a,b,c){if(b)i(a.prototype,b);if(c)i(a,c);return a}var k=function(a){return a.querySelectorAll(":checked")},l=function(){function a(b,c,d){h(this,a);this.filterType=b;this.rootNode=c;this.addValueSelector(d)}j(a,[{key:"tearDown",value:function tearDown(){}},{key:"addValueSelector",value:function(){var a=g(regeneratorRuntime.mark(function a(){var c=this,d,e,f,g=arguments;return regeneratorRuntime.wrap(function(a){while(1){switch(a.prev=a.next){case 0:d=0<g.length&&g[0]!==void 0?g[0]:[];e=this.getFilterValueNode();e.innerHTML=this.getSourceDataForFilter().outerHTML;f=e.querySelector("select");d.forEach(function(a){var b=f.querySelector("option[value=\"".concat(a,"\"]"));if(b){b.selected=!0}else if(!c.showSuggestions){b=document.createElement("option");b.value=a;b.innerHTML=a;b.selected=!0;f.append(b)}});a.t0=b.default;a.t1=f;a.t2="1"==f.dataset.allowCustom;a.next=10;return this.placeholder;case 10:a.t3=a.sent;a.t4=this.showSuggestions;a.t5=!f.multiple;a.t6={items:"core_user/local/participantsfilter/autocomplete_selection_items",layout:"core_user/local/participantsfilter/autocomplete_layout",selection:"core_user/local/participantsfilter/autocomplete_selection"};a.t0.enhance.call(a.t0,a.t1,a.t2,null,a.t3,!1,a.t4,null,a.t5,a.t6);case 15:case"end":return a.stop();}}},a,this)}));return function addValueSelector(){return a.apply(this,arguments)}}()},{key:"getSourceDataForFilter",value:function getSourceDataForFilter(){var a=this.rootNode.querySelector(c.default.filterset.regions.datasource);return a.querySelector(c.default.data.fields.byName(this.filterType))}},{key:"getFilterValueNode",value:function getFilterValueNode(){return this.filterRoot.querySelector(c.default.filter.regions.values)}},{key:"placeholder",get:function get(){return(0,d.get_string)("placeholdertypeorselect","core_user")}},{key:"showSuggestions",get:function get(){return!0}},{key:"filterRoot",get:function get(){return this.rootNode.querySelector(c.default.filter.byName(this.filterType))}},{key:"name",get:function get(){return this.filterType}},{key:"jointype",get:function get(){return this.filterRoot.querySelector(c.default.filter.fields.join).value}},{key:"rawValues",get:function get(){var a=this.getFilterValueNode(),b=a.querySelector("select");return Object.values(k(b)).map(function(a){return a.value})}},{key:"values",get:function get(){return this.rawValues.map(function(a){return parseInt(a,10)})}},{key:"filterValue",get:function get(){return{name:this.name,jointype:this.jointype,values:this.values}}}]);return a}();a.default=l;return a.default});
//# sourceMappingURL=filter.min.js.map

File diff suppressed because one or more lines are too long

View file

@ -1,2 +1,2 @@
define ("core_user/local/participantsfilter/filtertypes/keyword",["exports","../filter","core/str"],function(a,b,c){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;b=function(a){return a&&a.__esModule?a:{default:a}}(b);function d(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){d=function(a){return typeof a}}else{d=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return d(a)}function e(a,b){if(!(a instanceof b)){throw new TypeError("Cannot call a class as a function")}}function f(a,b){for(var c=0,d;c<b.length;c++){d=b[c];d.enumerable=d.enumerable||!1;d.configurable=!0;if("value"in d)d.writable=!0;Object.defineProperty(a,d.key,d)}}function g(a,b,c){if(b)f(a.prototype,b);if(c)f(a,c);return a}function h(a,b){if("function"!=typeof b&&null!==b){throw new TypeError("Super expression must either be null or a function")}a.prototype=Object.create(b&&b.prototype,{constructor:{value:a,writable:!0,configurable:!0}});if(b)i(a,b)}function i(a,b){i=Object.setPrototypeOf||function(a,b){a.__proto__=b;return a};return i(a,b)}function j(a){return function(){var b=n(a),c;if(m()){var d=n(this).constructor;c=Reflect.construct(b,arguments,d)}else{c=b.apply(this,arguments)}return k(this,c)}}function k(a,b){if(b&&("object"===d(b)||"function"==typeof b)){return b}return l(a)}function l(a){if(void 0===a){throw new ReferenceError("this hasn't been initialised - super() hasn't been called")}return a}function m(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{Date.prototype.toString.call(Reflect.construct(Date,[],function(){}));return!0}catch(a){return!1}}function n(a){n=Object.setPrototypeOf?Object.getPrototypeOf:function(a){return a.__proto__||Object.getPrototypeOf(a)};return n(a)}var o=function(a){h(b,a);var d=j(b);function b(a,c){e(this,b);return d.call(this,a,c)}g(b,[{key:"values",get:function get(){return this.rawValues}},{key:"placeholder",get:function get(){return(0,c.get_string)("placeholdertype","core_user")}},{key:"showSuggestions",get:function get(){return!1}}]);return b}(b.default);a.default=o;return a.default});
define ("core_user/local/participantsfilter/filtertypes/keyword",["exports","../filter","core/str"],function(a,b,c){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;b=function(a){return a&&a.__esModule?a:{default:a}}(b);function d(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){d=function(a){return typeof a}}else{d=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return d(a)}function e(a,b){if(!(a instanceof b)){throw new TypeError("Cannot call a class as a function")}}function f(a,b){for(var c=0,d;c<b.length;c++){d=b[c];d.enumerable=d.enumerable||!1;d.configurable=!0;if("value"in d)d.writable=!0;Object.defineProperty(a,d.key,d)}}function g(a,b,c){if(b)f(a.prototype,b);if(c)f(a,c);return a}function h(a,b){if("function"!=typeof b&&null!==b){throw new TypeError("Super expression must either be null or a function")}a.prototype=Object.create(b&&b.prototype,{constructor:{value:a,writable:!0,configurable:!0}});if(b)i(a,b)}function i(a,b){i=Object.setPrototypeOf||function(a,b){a.__proto__=b;return a};return i(a,b)}function j(a){return function(){var b=n(a),c;if(m()){var d=n(this).constructor;c=Reflect.construct(b,arguments,d)}else{c=b.apply(this,arguments)}return k(this,c)}}function k(a,b){if(b&&("object"===d(b)||"function"==typeof b)){return b}return l(a)}function l(a){if(void 0===a){throw new ReferenceError("this hasn't been initialised - super() hasn't been called")}return a}function m(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{Date.prototype.toString.call(Reflect.construct(Date,[],function(){}));return!0}catch(a){return!1}}function n(a){n=Object.setPrototypeOf?Object.getPrototypeOf:function(a){return a.__proto__||Object.getPrototypeOf(a)};return n(a)}var o=function(a){h(b,a);var d=j(b);function b(){e(this,b);return d.apply(this,arguments)}g(b,[{key:"values",get:function get(){return this.rawValues}},{key:"placeholder",get:function get(){return(0,c.get_string)("placeholdertype","core_user")}},{key:"showSuggestions",get:function get(){return!1}}]);return b}(b.default);a.default=o;return a.default});
//# sourceMappingURL=keyword.min.js.map

View file

@ -1 +1 @@
{"version":3,"sources":["../../../../src/local/participantsfilter/filtertypes/keyword.js"],"names":["filterType","filterSet","rawValues","Filter"],"mappings":"mMAuBA,uD,gqDAII,WAAYA,CAAZ,CAAwBC,CAAxB,CAAmC,8BACzBD,CADyB,CACbC,CADa,CAElC,C,qCAOY,CACT,MAAO,MAAKC,SACf,C,uCAOiB,CACd,MAAO,iBAAU,iBAAV,CAA6B,WAA7B,CACV,C,2CAOqB,CAClB,QACH,C,cA9BwBC,S","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 * Keyword filter.\n *\n * @module core_user/local/participantsfilter/filtertypes/keyword\n * @package core_user\n * @copyright 2020 Andrew Nicols <andrew@nicols.co.uk>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Filter from '../filter';\nimport {get_string as getString} from 'core/str';\n\nexport default class extends Filter {\n constructor(filterType, filterSet) {\n super(filterType, filterSet);\n }\n\n /**\n * For keywords the final value is an Array of strings.\n *\n * @returns {Object}\n */\n get values() {\n return this.rawValues;\n }\n\n /**\n * Get the placeholder to use when showing the value selector.\n *\n * @return {Promise} Resolving to a String\n */\n get placeholder() {\n return getString('placeholdertype', 'core_user');\n }\n\n /**\n * Whether to show suggestions in the autocomplete.\n *\n * @return {Boolean}\n */\n get showSuggestions() {\n return false;\n }\n}\n"],"file":"keyword.min.js"}
{"version":3,"sources":["../../../../src/local/participantsfilter/filtertypes/keyword.js"],"names":["rawValues","Filter"],"mappings":"mMAuBA,uD,2vDASiB,CACT,MAAO,MAAKA,SACf,C,uCAOiB,CACd,MAAO,iBAAU,iBAAV,CAA6B,WAA7B,CACV,C,2CAOqB,CAClB,QACH,C,cA1BwBC,S","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 * Keyword filter.\n *\n * @module core_user/local/participantsfilter/filtertypes/keyword\n * @package core_user\n * @copyright 2020 Andrew Nicols <andrew@nicols.co.uk>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Filter from '../filter';\nimport {get_string as getString} from 'core/str';\n\nexport default class extends Filter {\n /**\n * For keywords the final value is an Array of strings.\n *\n * @returns {Object}\n */\n get values() {\n return this.rawValues;\n }\n\n /**\n * Get the placeholder to use when showing the value selector.\n *\n * @return {Promise} Resolving to a String\n */\n get placeholder() {\n return getString('placeholdertype', 'core_user');\n }\n\n /**\n * Whether to show suggestions in the autocomplete.\n *\n * @return {Boolean}\n */\n get showSuggestions() {\n return false;\n }\n}\n"],"file":"keyword.min.js"}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -44,12 +44,13 @@ export default class {
*
* @param {String} filterType The type of filter that this relates to
* @param {HTMLElement} rootNode The root node for the participants filterset
* @param {Array} initialValues The initial values for the selector
*/
constructor(filterType, rootNode) {
constructor(filterType, rootNode, initialValues) {
this.filterType = filterType;
this.rootNode = rootNode;
this.addValueSelector();
this.addValueSelector(initialValues);
}
/**
@ -79,8 +80,10 @@ export default class {
/**
* Add the value selector to the filter row.
*
* @param {Array} initialValues
*/
async addValueSelector() {
async addValueSelector(initialValues = []) {
const filterValueNode = this.getFilterValueNode();
// Copy the data in place.
@ -88,6 +91,21 @@ export default class {
const dataSource = filterValueNode.querySelector('select');
// If there are any initial values then attempt to apply them.
initialValues.forEach(filterValue => {
let selectedOption = dataSource.querySelector(`option[value="${filterValue}"]`);
if (selectedOption) {
selectedOption.selected = true;
} else if (!this.showSuggestions) {
selectedOption = document.createElement('option');
selectedOption.value = filterValue;
selectedOption.innerHTML = filterValue;
selectedOption.selected = true;
dataSource.append(selectedOption);
}
});
Autocomplete.enhance(
// The source select element.
dataSource,

View file

@ -25,10 +25,6 @@ import Filter from '../filter';
import {get_string as getString} from 'core/str';
export default class extends Filter {
constructor(filterType, filterSet) {
super(filterType, filterSet);
}
/**
* For keywords the final value is an Array of strings.
*

View file

@ -106,8 +106,10 @@ export const init = participantsRegionId => {
*
* @param {HTMLElement} filterRow
* @param {String} filterType
* @param {Array} initialFilterValues The initially selected values for the filter
* @returns {Filter}
*/
const addFilter = async(filterRow, filterType) => {
const addFilter = async(filterRow, filterType, initialFilterValues) => {
// Name the filter on the filter row.
filterRow.dataset.filterType = filterType;
@ -118,14 +120,17 @@ export const init = participantsRegionId => {
if (filterDataNode.dataset.filterTypeClass) {
Filter = await import(filterDataNode.dataset.filterTypeClass);
}
activeFilters[filterType] = new Filter(filterType, filterSet);
activeFilters[filterType] = new Filter(filterType, filterSet, initialFilterValues);
// Disable the select.
const typeField = filterRow.querySelector(Selectors.filter.fields.type);
typeField.value = filterType;
typeField.disabled = 'disabled';
// Update the list of available filter types.
updateFiltersOptions();
return activeFilters[filterType];
};
/**
@ -248,15 +253,28 @@ export const init = participantsRegionId => {
/**
* Remove all filters.
*
* @returns {Promise}
*/
const removeAllFilters = async() => {
const removeAllFilters = () => {
const filters = getFilterRegion().querySelectorAll(Selectors.filter.region);
filters.forEach((filterRow) => {
removeOrReplaceFilterRow(filterRow);
});
filters.forEach(filterRow => removeOrReplaceFilterRow(filterRow));
// Refresh the table.
updateTableFromFilter();
return updateTableFromFilter();
};
/**
* Remove any empty filters.
*/
const removeEmptyFilters = () => {
const filters = getFilterRegion().querySelectorAll(Selectors.filter.region);
filters.forEach(filterRow => {
const filterType = filterRow.querySelector(Selectors.filter.fields.type);
if (!filterType.value) {
removeOrReplaceFilterRow(filterRow);
}
});
};
/**
@ -298,6 +316,49 @@ export const init = participantsRegionId => {
}
};
/**
* Set the current filter options based on a provided configuration.
*
* @param {Object} config
* @param {Number} config.jointype
* @param {Object} config.filters
*/
const setFilterFromConfig = config => {
const filterConfig = Object.entries(config.filters);
if (!filterConfig.length) {
// There are no filters to set from.
return;
}
// Set the main join type.
filterSet.querySelector(Selectors.filterset.fields.join).value = config.jointype;
const filterPromises = filterConfig.map(([filterType, filterData]) => {
if (filterType === 'courseid') {
// The courseid is a special case.
return Promise.resolve();
}
const filterValues = filterData.values;
if (!filterValues.length) {
// There are no values for this filter.
// Skip it.
return Promise.resolve();
}
return addFilterRow().then(([filterRow]) => addFilter(filterRow, filterType, filterValues));
});
Promise.all(filterPromises).then(() => {
return removeEmptyFilters();
})
.then(updateFiltersOptions)
.then(updateTableFromFilter)
.catch();
};
/**
* Update the Dynamic table based upon the current filter.
*
@ -383,4 +444,11 @@ export const init = participantsRegionId => {
filterSet.querySelector(Selectors.filterset.fields.join).addEventListener('change', e => {
filterSet.dataset.filterverb = e.target.value;
});
const tableRoot = DynamicTable.getTableFromId(filterSet.dataset.tableRegion);
const initialFilters = DynamicTable.getFilters(tableRoot);
if (initialFilters) {
// Apply the initial filter configuration.
setFilterFromConfig(initialFilters);
}
};