$string['applyfilters'] = 'Apply filters';
$string['clearfilterrow'] = 'Remove filter row';
$string['clearfilters'] = 'Clear filters';
+$string['clearfilterselection'] = 'Remove "{$a}" from filter';
$string['countparticipantsfound'] = '{$a} participants found';
+$string['filterrowlegend'] = 'Filter {$a}';
$string['filtersetmatchdescription'] = 'How multiple filters should be combined';
$string['match'] = 'Match';
$string['matchofthefollowing'] = 'of the following:';
all: `${getFilterRegion('filtertypedata')} [data-field-name]`,
},
typeList: getFilterRegion('filtertypelist'),
+ typeListSelect: `select${getFilterRegion('filtertypelist')}`,
},
};
import CourseFilter from './local/participantsfilter/filtertypes/courseid';
import * as DynamicTable from 'core_table/dynamic';
import GenericFilter from './local/participantsfilter/filter';
+import {get_strings as getStrings} from 'core/str';
import Notification from 'core/notification';
import Selectors from './local/participantsfilter/selectors';
import Templates from 'core/templates';
* @return {Promise}
*/
const addFilterRow = () => {
- return Templates.renderForPromise('core_user/local/participantsfilter/filterrow', {})
+ const rownum = 1 + getFilterRegion().querySelectorAll(Selectors.filter.region).length;
+ return Templates.renderForPromise('core_user/local/participantsfilter/filterrow', {"rownumber": rownum})
.then(({html, js}) => {
const newContentNodes = Templates.appendNodeContents(getFilterRegion(), html, js);
*
* @param {HTMLElement} filterRow
*/
- const removeFilterRow = filterRow => {
+ const removeFilterRow = async filterRow => {
// Remove the filter object.
removeFilterObject(filterRow.dataset.filterType);
// Update the list of available filter types.
updateFiltersOptions();
+
+ // Update filter fieldset legends.
+ const filterLegends = await getAvailableFilterLegends();
+
+ getFilterRegion().querySelectorAll(Selectors.filter.region).forEach((filterRow, index) => {
+ filterRow.querySelector('legend').innerText = filterLegends[index];
+ });
+
};
/**
* Replace the specified filter row with a new one.
*
* @param {HTMLElement} filterRow
+ * @param {Number} rowNum The number used to label the filter fieldset legend (eg Row 1). Defaults to 1 (the first filter).
* @return {Promise}
*/
- const replaceFilterRow = filterRow => {
+ const replaceFilterRow = (filterRow, rowNum = 1) => {
// Remove the filter object.
removeFilterObject(filterRow.dataset.filterType);
- return Templates.renderForPromise('core_user/local/participantsfilter/filterrow', {})
+ return Templates.renderForPromise('core_user/local/participantsfilter/filterrow', {"rownumber": rowNum})
.then(({html, js}) => {
const newContentNodes = Templates.replaceNode(filterRow, html, js);
);
};
+ /**
+ * Fetch the strings used to populate the fieldset legends for the maximum number of filters possible.
+ *
+ * @return {array}
+ */
+ const getAvailableFilterLegends = async() => {
+ const maxFilters = document.querySelector(Selectors.data.typeListSelect).length - 1;
+ let requests = [];
+
+ [...Array(maxFilters)].forEach((_, rowIndex) => {
+ requests.push({
+ "key": "filterrowlegend",
+ "component": "core_user",
+ // Add 1 since rows begin at 1 (index begins at zero).
+ "param": rowIndex + 1
+ });
+ });
+
+ const legendStrings = await getStrings(requests)
+ .then(fetchedStrings => {
+ return fetchedStrings;
+ })
+ .catch(Notification.exception);
+
+ return legendStrings;
+ };
+
// Add listeners for the main actions.
filterSet.querySelector(Selectors.filterset.region).addEventListener('click', e => {
if (e.target.closest(Selectors.filterset.actions.addRow)) {
'tableregionid' => $this->tableregionid,
'courseid' => $this->context->instanceid,
'filtertypes' => $this->get_filtertypes(),
+ 'rownumber' => 1,
];
return $data;
{{#items}}
<span role="listitem" data-value="{{value}}" aria-selected="true"
class="badge badge-secondary clickable text-wrap text-break line-height-4 mr-2 my-1">
- {{label}}<i class="icon fa fa-times pl-2 mr-0"></i>
+ {{label}}
+ <button class="btn btn-link text-reset p-0" aria-label='{{#str}}clearfilterselection, core_user, {{label}}{{/str}}'>
+ <i class="icon fa fa-times pl-2 mr-0"></i>
+ </button>
</span>
{{/items}}
{{^items}}
"name": "status",
"title": "Status"
}
- ]
+ ],
+ "rownumber": 1
}
}}
<div data-filterregion="filter">
- <div class="border-radius my-2 p-2 bg-white border d-flex flex-column flex-md-row align-items-md-start">
- <div class="d-flex flex-column flex-md-row align-items-md-center">
- <label for="core_user-local-participantsfilter-filterrow-jointype-{{uniqid}}" class="mr-md-2 mb-md-0">{{#str}}match, core_user{{/str}}</label>
- <select class="custom-select mb-1 mb-md-0 mr-md-2" data-filterfield="join" id="core_user-local-participantsfilter-filterrow-jointype-{{uniqid}}">
- <option value="0">{{#str}}none{{/str}}</option>
- <option selected=selected value="1">{{#str}}any{{/str}}</option>
- <option value="2">{{#str}}all{{/str}}</option>
- </select>
- </div>
+ <fieldset>
+ <legend class="sr-only">{{#str}}filterrowlegend, core_user, {{rownumber}}{{/str}}</legend>
+ <div class="border-radius my-2 p-2 bg-white border d-flex flex-column flex-md-row align-items-md-start">
+ <div class="d-flex flex-column flex-md-row align-items-md-center">
+ <label for="core_user-local-participantsfilter-filterrow-jointype-{{uniqid}}" class="mr-md-2 mb-md-0">{{#str}}match, core_user{{/str}}</label>
+ <select class="custom-select mb-1 mb-md-0 mr-md-2" data-filterfield="join" id="core_user-local-participantsfilter-filterrow-jointype-{{uniqid}}">
+ <option value="0">{{#str}}none{{/str}}</option>
+ <option selected=selected value="1">{{#str}}any{{/str}}</option>
+ <option value="2">{{#str}}all{{/str}}</option>
+ </select>
+ </div>
- <label class="sr-only pt-2" for="core_user-local-participantsfilter-filterrow-filtertype-{{uniqid}}">filtertype</label>
- <select class="custom-select mb-1 mb-md-0 mr-md-2" data-filterfield="type" id="core_user-local-participantsfilter-filterrow-filtertype-{{uniqid}}">
- <option value="">{{#str}}selectfiltertype, core_user{{/str}}</option>
- {{#filtertypes}}
- <option value="{{name}}">{{title}}</option>
- {{/filtertypes}}
- </select>
+ <label class="sr-only pt-2" for="core_user-local-participantsfilter-filterrow-filtertype-{{uniqid}}">filtertype</label>
+ <select class="custom-select mb-1 mb-md-0 mr-md-2" data-filterfield="type" id="core_user-local-participantsfilter-filterrow-filtertype-{{uniqid}}">
+ <option value="">{{#str}}selectfiltertype, core_user{{/str}}</option>
+ {{#filtertypes}}
+ <option value="{{name}}">{{title}}</option>
+ {{/filtertypes}}
+ </select>
- <div data-filterregion="value" class="d-md-flex flex-column align-items-start flex-lg-row"></div>
+ <div data-filterregion="value" class="d-md-flex flex-column align-items-start flex-lg-row"></div>
- <button data-filteraction="remove" class="ml-auto icon-no-margin icon-size-4 btn text-reset" aria-label="{{#str}}clearfilterrow, core_user{{/str}}">
- <i class="icon fa fa-times-circle"></i>
- </button>
- </div>
- <div data-filterregion="joinadverb" class="pl-1 text-uppercase font-weight-bold">
- <div data-filterverbfor="0">{{#str}}adverbfor_andnot, core_user{{/str}}</div>
- <div data-filterverbfor="1">{{#str}}adverbfor_or, core_user{{/str}}</div>
- <div data-filterverbfor="2">{{#str}}adverbfor_and, core_user{{/str}}</div>
- </div>
+ <button data-filteraction="remove" class="ml-auto icon-no-margin icon-size-4 btn text-reset" aria-label="{{#str}}clearfilterrow, core_user{{/str}}">
+ <i class="icon fa fa-times-circle"></i>
+ </button>
+ </div>
+ <div data-filterregion="joinadverb" class="pl-1 text-uppercase font-weight-bold">
+ <div data-filterverbfor="0">{{#str}}adverbfor_andnot, core_user{{/str}}</div>
+ <div data-filterverbfor="1">{{#str}}adverbfor_or, core_user{{/str}}</div>
+ <div data-filterverbfor="2">{{#str}}adverbfor_and, core_user{{/str}}</div>
+ </div>
+ </fieldset>
</div>