MDL-68169 user: Limit the number of filter conditions
authorAndrew Nicols <andrew@nicols.co.uk>
Wed, 15 Apr 2020 05:59:21 +0000 (13:59 +0800)
committerAndrew Nicols <andrew@nicols.co.uk>
Wed, 27 May 2020 02:49:44 +0000 (10:49 +0800)
Part of MDL-67743

13 files changed:
lang/en/user.php
lib/table/classes/external/dynamic/fetch.php
theme/boost/scss/moodle/user.scss
theme/boost/style/moodle.css
theme/classic/style/moodle.css
user/amd/build/local/participantsfilter/selectors.min.js
user/amd/build/local/participantsfilter/selectors.min.js.map
user/amd/build/participantsfilter.min.js
user/amd/build/participantsfilter.min.js.map
user/amd/src/local/participantsfilter/selectors.js
user/amd/src/participantsfilter.js
user/templates/local/participantsfilter/filterrow.mustache
user/templates/participantsfilter.mustache

index 1f832af..50560fe 100644 (file)
@@ -23,6 +23,9 @@
  */
 
 $string['addcondition'] = 'Add condition';
+$string['adverbfor_and'] = 'and';
+$string['adverbfor_andnot'] = 'and';
+$string['adverbfor_or'] = 'or';
 $string['applyfilters'] = 'Apply filters';
 $string['clearfilterrow'] = 'Remove filter row';
 $string['clearfilters'] = 'Clear filters';
index b63c6c2..ad2fcda 100644 (file)
@@ -217,6 +217,7 @@ class fetch extends external_api {
         }
 
         $filterset = new $filtersetclass();
+        $filterset->set_join_type($jointype);
         foreach ($filters as $rawfilter) {
             $filterset->add_filter_from_params(
                 $rawfilter['name'],
index 2f847c6..bfbbfe0 100644 (file)
 .user-enroller-panel {
     width: 600px;
 }
+
+[data-filterverbfor],
+[data-filterregion="filter"]:last-child [data-filterregion="joinadverb"] {
+    display: none;
+}
+
+[data-filterverb="0"] [data-filterverbfor="0"],
+[data-filterverb="1"] [data-filterverbfor="1"],
+[data-filterverb="2"] [data-filterverbfor="2"] {
+    display: block;
+}
index 9d14485..afd3486 100644 (file)
@@ -15952,6 +15952,15 @@ body.path-question-type .mform fieldset.hidden {
 .user-enroller-panel {
   width: 600px; }
 
+[data-filterverbfor],
+[data-filterregion="filter"]:last-child [data-filterregion="joinadverb"] {
+  display: none; }
+
+[data-filterverb="0"] [data-filterverbfor="0"],
+[data-filterverb="1"] [data-filterverbfor="1"],
+[data-filterverb="2"] [data-filterverbfor="2"] {
+  display: block; }
+
 .search-results .result {
   margin-left: 0;
   margin-right: 0; }
index e131ec7..00b7fb8 100644 (file)
@@ -16176,6 +16176,15 @@ body.path-question-type .mform fieldset.hidden {
 .user-enroller-panel {
   width: 600px; }
 
+[data-filterverbfor],
+[data-filterregion="filter"]:last-child [data-filterregion="joinadverb"] {
+  display: none; }
+
+[data-filterverb="0"] [data-filterverbfor="0"],
+[data-filterverb="1"] [data-filterverbfor="1"],
+[data-filterverb="2"] [data-filterverbfor="2"] {
+  display: block; }
+
 .search-results .result {
   margin-left: 0;
   margin-right: 0; }
index 1f1dcc5..21be665 100644 (file)
Binary files a/user/amd/build/local/participantsfilter/selectors.min.js and b/user/amd/build/local/participantsfilter/selectors.min.js differ
index 31cd5e6..023c1a6 100644 (file)
Binary files a/user/amd/build/local/participantsfilter/selectors.min.js.map and b/user/amd/build/local/participantsfilter/selectors.min.js.map differ
index 31b031a..bbb20c6 100644 (file)
Binary files a/user/amd/build/participantsfilter.min.js and b/user/amd/build/participantsfilter.min.js differ
index 1a05bb3..214f7dc 100644 (file)
Binary files a/user/amd/build/participantsfilter.min.js.map and b/user/amd/build/participantsfilter.min.js.map differ
index d17b28e..3d0ef29 100644 (file)
@@ -49,13 +49,18 @@ export default {
             resetFilters: getFilterAction('reset'),
         },
         regions: {
+            filtermatch: getFilterRegion('filtermatch'),
             filterlist: getFilterRegion('filters'),
             datasource: getFilterRegion('filtertypedata'),
         },
+        fields: {
+            join: `${getFilterRegion('filtermatch')} ${getFilterField('join')}`,
+        },
     },
     data: {
         fields: {
             byName: name => `[data-field-name="${name}"]`,
+            all: `${getFilterRegion('filtertypedata')} [data-field-name]`,
         },
         typeList: getFilterRegion('filtertypelist'),
     },
index 23e5432..3dcdb88 100644 (file)
@@ -268,6 +268,23 @@ export const init = participantsRegionId => {
                 }
             });
         });
+
+        // Configure the state of the "Add row" button.
+        // This button is disabled when there is a filter row available for each condition.
+        const addRowButton = filterSet.querySelector(Selectors.filterset.actions.addRow);
+        const filterDataNode = filterSet.querySelectorAll(Selectors.data.fields.all);
+        if (filterDataNode.length <= filters.length) {
+            addRowButton.setAttribute('disabled', 'disabled');
+        } else {
+            addRowButton.removeAttribute('disabled');
+        }
+
+        if (filters.length === 1) {
+            filterSet.querySelector(Selectors.filterset.regions.filtermatch).classList.add('hidden');
+            filterSet.querySelector(Selectors.filterset.fields.join).value = 1;
+        } else {
+            filterSet.querySelector(Selectors.filterset.regions.filtermatch).classList.remove('hidden');
+        }
     };
 
     /**
@@ -276,14 +293,11 @@ export const init = participantsRegionId => {
      * @return {Promise}
      */
     const updateTableFromFilter = () => {
-        // TODO The main join type does not exist yet.
-        const joinType = 1;
-
         return DynamicTable.setFilters(
             DynamicTable.getTableFromId(filterSet.dataset.tableRegion),
             {
                 filters: Object.values(activeFilters).map(filter => filter.filterValue),
-                jointype: joinType,
+                jointype: filterSet.querySelector(Selectors.filterset.fields.join).value,
             }
         );
     };
@@ -327,4 +341,8 @@ export const init = participantsRegionId => {
             addFilter(filter, typeField.value);
         }
     });
+
+    filterSet.querySelector(Selectors.filterset.fields.join).addEventListener('change', e => {
+        filterSet.dataset.filterverb = e.target.value;
+    });
 };
index c97bab5..089fb8b 100644 (file)
         ]
     }
 }}
-<div data-filterregion="filter" class="rounded mb-3 p-2 bg-white border border-secondary d-flex align-items-center">
-    <label for="core_user-local-participantsfilter-filterrow-jointype-{{uniqid}}" class="pt-2">{{#str}}match, core_user{{/str}}</label>
-    <select class="custom-select" 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>
-
-    <label class="sr-only pt-2" for="core_user-local-participantsfilter-filterrow-filtertype-{{uniqid}}">filtertype</label>
-    <select class="custom-select" 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"></div>
-
-    <button data-filteraction="remove" class="ml-auto btn btn-link text-reset" aria-label="{{#str}}clearfilterrow, core_user{{/str}}">
-        <i class="icon fa fa-times-circle pt-2"></i>
-    </button>
+<div data-filterregion="filter">
+    <div class="rounded mb-3 p-2 bg-white border border-secondary d-flex align-items-center">
+        <label for="core_user-local-participantsfilter-filterrow-jointype-{{uniqid}}" class="pt-2">{{#str}}match, core_user{{/str}}</label>
+        <select class="custom-select" 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>
+
+        <label class="sr-only pt-2" for="core_user-local-participantsfilter-filterrow-filtertype-{{uniqid}}">filtertype</label>
+        <select class="custom-select" 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"></div>
+
+        <button data-filteraction="remove" class="ml-auto btn btn-link text-reset" aria-label="{{#str}}clearfilterrow, core_user{{/str}}">
+            <i class="icon fa fa-times-circle pt-2"></i>
+        </button>
+    </div>
+    <div data-filterregion="joinadverb">
+        <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>
 </div>
index 15a26ba..82500ad 100644 (file)
     }
 }}
 
-<div id="core_user-participantsfilter-{{uniqid}}" class="filter-group mt-5 p-3 rounded border border-secondary" data-table-region="{{tableregionid}}" data-table-course-id="{{courseid}}">
+<div id="core_user-participantsfilter-{{uniqid}}" class="filter-group mt-5 p-3 rounded border border-secondary" data-table-region="{{tableregionid}}" data-table-course-id="{{courseid}}" data-filterverb="1">
+    <div data-filterregion="filtermatch" class="hidden">
+        <label for="core_user-local-participantsfilter-jointype-{{uniqid}}" class="pt-2">{{#str}}match, core_user{{/str}}</label>
+        <select class="custom-select" data-filterfield="join" id="core_user-local-participantsfilter-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>
+
     <div data-filterregion="filters">
         {{> core_user/local/participantsfilter/filterrow }}
     </div>