If a range filter action had an empty from/to field, the range
filter could still be applied. This was confusing, as an invalid
filter range caused all records to display, even though a filter
appeared to have been applied (by the highlighted state of
the filter button).

Change the state of the "Apply" button, disabling it if the radio
button for a range filter action is selected but the range is
incomplete (from or to field is empty).

When a non-range filter is selected, the "Apply" button always
enable the "Apply" button.

[YOCTO #8738]

Signed-off-by: Elliot Smith <[email protected]>
---
 bitbake/lib/toaster/toastergui/static/js/table.js  | 77 ++++++++++++++++------
 .../toastergui/templates/toastertable-filter.html  |  4 +-
 2 files changed, 59 insertions(+), 22 deletions(-)

diff --git a/bitbake/lib/toaster/toastergui/static/js/table.js 
b/bitbake/lib/toaster/toastergui/static/js/table.js
index 9384386..87cac60 100644
--- a/bitbake/lib/toaster/toastergui/static/js/table.js
+++ b/bitbake/lib/toaster/toastergui/static/js/table.js
@@ -397,6 +397,8 @@ function tableInit(ctx){
    * filterActionData: (object)
    * filterActionData.count: (number) The number of items this filter will
    * show when selected
+   *
+   * NB this triggers a filtervalue event each time its radio button is checked
    */
   function createActionRadio(filterName, filterActionData) {
     var hasNoRecords = (Number(filterActionData.count) == 0);
@@ -420,7 +422,17 @@ function tableInit(ctx){
                  '</label>' +
                  '</div>';
 
-    return $(actionStr);
+    var action = $(actionStr);
+
+    // fire the filtervalue event from this action when the radio button
+    // is active so that the apply button can be enabled
+    action.find('[type="radio"]').change(function () {
+      if ($(this).is(':checked')) {
+        action.trigger('filtervalue', 'on');
+      }
+    });
+
+    return action;
   }
 
   /**
@@ -437,6 +449,8 @@ function tableInit(ctx){
    * datetime format
    * filterActionData.min: (string) minimum date for the pickers, ISO 8601
    * datetime
+   *
+   * NB this triggers a filtervalue event each time its radio button is checked
    */
   function createActionDateRange(filterName, filterValue, filterActionData) {
     var action = $('<div class="radio">' +
@@ -492,9 +506,26 @@ function tableInit(ctx){
     inputTo.val(selectedTo);
 
     // set filter_value based on date pickers when
-    // one of their values changes
+    // one of their values changes; if either from or to are unset,
+    // the new value is null;
+    // this triggers a 'filter_value-change' event on the action's element,
+    // which is used to determine the disabled/enabled state of the "Apply"
+    // button
     var changeHandler = function () {
-      value.val(inputFrom.val() + ',' + inputTo.val());
+      var fromValue = inputFrom.val();
+      var toValue = inputTo.val();
+
+      var newValue = undefined;
+      if (fromValue !== '' && toValue !== '') {
+        newValue = fromValue + ',' + toValue;
+      }
+
+      value.val(newValue);
+
+      // if this action is selected, fire an event for the new range
+      if (radio.is(':checked')) {
+        action.trigger('filtervalue', newValue);
+      }
     };
 
     inputFrom.change(changeHandler);
@@ -503,6 +534,10 @@ function tableInit(ctx){
     // check the associated radio button on clicking a date picker
     var checkRadio = function () {
       radio.prop('checked', 'checked');
+
+      // checking the radio button this way doesn't cause the "change"
+      // event to fire, so we manually call the changeHandler
+      changeHandler();
     };
 
     inputFrom.focus(checkRadio);
@@ -518,23 +553,9 @@ function tableInit(ctx){
       inputFrom.datepicker('option', 'maxDate', inputTo.val());
     });
 
-    // if the radio button is checked and one or both of the datepickers are
-    // empty, populate them with today's date
-    radio.change(function () {
-      var now = new Date();
-
-      if (inputFrom.val() === '') {
-        inputFrom.datepicker('setDate', now);
-      }
-
-      if (inputTo.val() === '') {
-        inputTo.datepicker('setDate', now);
-      }
-
-      // setting the date like this doesn't fire the changeHandler to
-      // update the filter_value, so do that manually instead
-      changeHandler()
-    });
+    // checking the radio input causes the "Apply" button disabled state to
+    // change, depending on which from/to dates are supplied
+    radio.change(changeHandler);
 
     return action;
   }
@@ -589,6 +610,16 @@ function tableInit(ctx){
             queryset on the table
           */
           var filterActionRadios = $('#filter-actions-' + ctx.tableName);
+          var filterApplyBtn = $('[data-role="filter-apply"]');
+
+          var setApplyButtonState = function (e, filterActionValue) {
+            if (filterActionValue !== undefined) {
+              filterApplyBtn.removeAttr('disabled');
+            }
+            else {
+              filterApplyBtn.attr('disabled', 'disabled');
+            }
+          };
 
           $('#filter-modal-title-' + ctx.tableName).text(filterData.title);
 
@@ -624,10 +655,14 @@ function tableInit(ctx){
               if ((tableParams.filter &&
                   tableParams.filter === radioInput.val()) ||
                   filterActionData.action_name == 'all') {
-                  radioInput.attr("checked", "checked");
+                  radioInput.prop("checked", "checked");
               }
 
               filterActionRadios.append(action);
+
+              // if the action's filter_value changes but is falsy, disable
+              // the "Apply" button
+              action.on('filtervalue', setApplyButtonState);
             }
           }
 
diff --git a/bitbake/lib/toaster/toastergui/templates/toastertable-filter.html 
b/bitbake/lib/toaster/toastergui/templates/toastertable-filter.html
index 7c8dc49..4d28793 100644
--- a/bitbake/lib/toaster/toastergui/templates/toastertable-filter.html
+++ b/bitbake/lib/toaster/toastergui/templates/toastertable-filter.html
@@ -10,7 +10,9 @@
       <span id="filter-actions-{{table_name}}"></span>
     </div>
     <div class="modal-footer">
-      <button class="btn btn-primary" type="submit">Apply</button>
+      <button class="btn btn-primary" type="submit" data-role="filter-apply">
+        Apply
+      </button>
     </div>
   </form>
 </div>
-- 
Elliot Smith
Software Engineer
Intel OTC

---------------------------------------------------------------------
Intel Corporation (UK) Limited
Registered No. 1134945 (England)
Registered Office: Pipers Way, Swindon SN3 1RJ
VAT No: 860 2173 47

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

-- 
_______________________________________________
toaster mailing list
[email protected]
https://lists.yoctoproject.org/listinfo/toaster

Reply via email to