Patron reg field validation (WIP)
authorBill Erickson <berickxx@gmail.com>
Mon, 29 Feb 2016 20:22:59 +0000 (15:22 -0500)
committerBill Erickson <berickxx@gmail.com>
Mon, 29 Feb 2016 20:22:59 +0000 (15:22 -0500)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/src/templates/staff/circ/patron/t_edit.tt2
Open-ILS/web/js/ui/default/staff/circ/patron/regctl.js

index d9dda61..5a0aa9d 100644 (file)
@@ -112,6 +112,7 @@ within the "form" by name for validation.
         name="barcode"
         ng-model="patron.card.barcode"
         ng-class="{'patron-reg-invalid-field' : field_is_invalid('barcode')}"
+        ng-pattern="field_pattern('ac', 'barcode')"
         ng-required="true"
         focus-me="focus_bc"
         ng-change="field_modified()" 
@@ -139,6 +140,7 @@ within the "form" by name for validation.
       ng-required="true"
       focus-me="focus_usrname"
       ng-change="field_modified()" 
+      ng-pattern="field_pattern('au', 'usrname')"
       ng-blur="handle_field_changed(patron, 'usrname')"
       class="form-control" 
       ng-model="patron.usrname"/>
@@ -158,7 +160,7 @@ within the "form" by name for validation.
     <input type="text" 
       name='passwd'
       ng-class="{'patron-reg-invalid-field' : field_is_invalid('passwd')}"
-      ng-pattern="patterns.au.passwd"
+      ng-pattern="field_pattern('au', 'passwd')"
       ng-required="true"
       ng-change="field_modified()" 
       ng-blur="handle_field_changed(patron, 'passwd')"
@@ -180,6 +182,8 @@ within the "form" by name for validation.
       ng-change="field_modified()" 
       class="form-control" 
       name="prefix"
+      ng-blur="handle_field_changed(patron, 'prefix')"
+      ng-pattern="field_pattern('au', 'prefix')"
       ng-class="{'patron-reg-invalid-field' : field_is_invalid('prefix')}"
       ng-required="org_settings['ui.patron.edit.au.prefix.require']"
       ng-model="patron.prefix"/>
@@ -198,6 +202,9 @@ within the "form" by name for validation.
   <div class="col-md-3 reg-field-input">
     <input type="text" 
       ng-change="field_modified()" 
+      name="first_given_name"
+      ng-pattern="field_pattern('au', 'first_given_name')"
+      ng-class="{'patron-reg-invalid-field' : field_is_invalid('first_given_name')}"
       ng-blur="handle_field_changed(patron, 'first_given_name')"
       class="form-control" ng-model="patron.first_given_name"/>
   </div>
@@ -214,7 +221,10 @@ within the "form" by name for validation.
   [% draw_field_label('au', 'second_given_name') %]
   <div class="col-md-3 reg-field-input"> <!-- field form input -->
     <input type="text" 
+      name="second_given_name"
       ng-change="field_modified()" 
+      ng-class="{'patron-reg-invalid-field' : field_is_invalid('second_given_name')}"
+      ng-pattern="field_pattern('au', 'second_given_name')"
       class="form-control" ng-model="patron.second_given_name"/>
   </div>
   <div class="col-md-6 patron-reg-example">
@@ -231,7 +241,10 @@ within the "form" by name for validation.
   [% draw_field_label('au', 'family_name') %]
   <div class="col-md-3 reg-field-input"> <!-- field form input -->
     <input type="text" 
+      name="family_name"
       ng-change="field_modified()" 
+      ng-pattern="field_pattern('au', 'family_name')"
+      ng-class="{'patron-reg-invalid-field' : field_is_invalid('family_name')}"
       ng-blur="handle_field_changed(patron, 'family_name')"
       class="form-control" ng-model="patron.family_name"/>
   </div>
@@ -249,8 +262,11 @@ within the "form" by name for validation.
   [% draw_field_label('au', 'suffix') %]
   <div class="col-md-3 reg-field-input"> <!-- field form input -->
     <input type="text" 
+      name="suffix"
       ng-change="field_modified()" 
       ng-blur="handle_field_changed(patron, 'suffix')"
+      ng-pattern="field_pattern('au', 'suffix')"
+      ng-class="{'patron-reg-invalid-field' : field_is_invalid('suffix')}"
       class="form-control" 
       ng-model="patron.suffix"/>
   </div>
@@ -268,8 +284,11 @@ within the "form" by name for validation.
   [% draw_field_label('au', 'alias') %]
   <div class="col-md-3 reg-field-input"> <!-- field form input -->
     <input type="text" 
+      name="alias"
       ng-change="field_modified()" 
       ng-blur="handle_field_changed(patron, 'alias')"
+      ng-pattern="field_pattern('au', 'alias')"
+      ng-class="{'patron-reg-invalid-field' : field_is_invalid('alias')}"
       class="form-control" 
       ng-model="patron.alias"/>
   </div>
@@ -287,8 +306,10 @@ within the "form" by name for validation.
   [% draw_field_label('au', 'dob') %]
   <div class="col-md-3 reg-field-input">
     <input eg-date-input 
+      name="dob"
       ng-change="field_modified()" 
       ng-blur="handle_field_changed(patron, 'dob')"
+      ng-class="{'patron-reg-invalid-field' : field_is_invalid('dob')}"
       class="form-control" ng-model="patron.dob"/>
   </div>
   <div class="col-md-6 patron-reg-example">
@@ -305,7 +326,10 @@ within the "form" by name for validation.
   [% draw_field_label('au', 'juvenile') %]
   <div class="col-md-3 reg-field-input">
     <input type="checkbox"
+      name="juvenile"
       ng-change="field_modified()" 
+      ng-pattern="field_pattern('au', 'juvenile')"
+      ng-class="{'patron-reg-invalid-field' : field_is_invalid('juvenile')}"
       ng-blur="handle_field_changed(patron, 'juvenile')"
       class="form-control" ng-model="patron.juvenile"/>
   </div>
@@ -341,7 +365,10 @@ within the "form" by name for validation.
   <div class="col-md-3 reg-field-input">
     <input type="text" 
       ng-change="field_modified()" 
+      name="ident_value"
       ng-blur="handle_field_changed(patron, 'ident_value')"
+      ng-class="{'patron-reg-invalid-field' : field_is_invalid('ident_value')}"
+      ng-pattern="field_pattern('au', 'ident_value')"
       class="form-control" 
       ng-model="patron.ident_value"/>
   </div>
@@ -358,7 +385,10 @@ within the "form" by name for validation.
   [% draw_field_label('au', 'ident_value2') %]
   <div class="col-md-3 reg-field-input">
     <input type="text" 
+      name="ident_value2"
       ng-change="field_modified()" 
+      ng-pattern="field_pattern('au', 'ident_valued')"
+      ng-class="{'patron-reg-invalid-field' : field_is_invalid('ident_value2')}"
       ng-blur="handle_field_changed(patron, 'ident_value2')"
       class="form-control" 
       ng-model="patron.ident_value2"/>
@@ -377,7 +407,10 @@ within the "form" by name for validation.
   [% draw_field_label('au', 'ident_value2') %]
   <div class="col-md-3 reg-field-input">
     <input type="email" 
+      name="email"
       ng-change="field_modified()" 
+      ng-pattern="field_pattern('au', 'email')"
+      ng-class="{'patron-reg-invalid-field' : field_is_invalid('email')}"
       ng-blur="handle_field_changed(patron, 'email')"
       class="form-control" ng-model="patron.email"/>
   </div>
@@ -398,8 +431,11 @@ within the "form" by name for validation.
   [% draw_field_label('au', 'day_phone') %]
   <div class="col-md-3 reg-field-input">
     <input type="text" 
+      name="day_phone"
       ng-blur="handle_field_changed(patron, 'day_phone')"
       ng-change="field_modified()" 
+      ng-pattern="field_pattern('au', 'day_phone')"
+      ng-class="{'patron-reg-invalid-field' : field_is_invalid('day_phone')}"
       class="form-control" ng-model="patron.day_phone"/>
   </div>
   <div class="col-md-6 patron-reg-example">
@@ -424,7 +460,10 @@ within the "form" by name for validation.
   [% draw_field_label('au', 'evening_phone') %]
   <div class="col-md-3 reg-field-input">
     <input type="text" 
+      name="evening_phone"
+      ng-pattern="field_pattern('au', 'evening_phone')"
       ng-blur="handle_field_changed(patron, 'evening_phone')"
+      ng-class="{'patron-reg-invalid-field' : field_is_invalid('evening_phone')}"
       ng-change="field_modified()" 
       class="form-control" ng-model="patron.evening_phone"/>
   </div>
@@ -450,7 +489,10 @@ within the "form" by name for validation.
   [% draw_field_label('au', 'other_phone') %]
   <div class="col-md-3 reg-field-input">
     <input type="text" 
+      name="other_phone"
       ng-blur="handle_field_changed(patron, 'other_phone')"
+      ng-pattern="field_pattern('au', 'other_phone')"
+      ng-class="{'patron-reg-invalid-field' : field_is_invalid('other_phone')}"
       ng-change="field_modified()" 
       class="form-control" ng-model="patron.other_phone"/>
   </div>
@@ -627,6 +669,7 @@ within the "form" by name for validation.
     <textarea 
       class="form-control" 
       ng-model="patron.alert_message"
+      ng-pattern="field_pattern('au', 'alert_message')"
       ng-change="field_modified()" 
       ng-blur="handle_field_changed(patron, 'alert_message')">
   </div>
@@ -785,6 +828,7 @@ within the "form" by name for validation.
     <div class="col-md-3 reg-field-input">
       <input type="text" 
         ng-change="field_modified()" 
+        ng-pattern="field_pattern('aua', 'address_type')"
         class="form-control" 
         ng-model="patron.addresses[$index].address_type"
         ng-blur="handle_field_changed(patron.addresses[$index], 'address_type')"/>
@@ -803,6 +847,7 @@ within the "form" by name for validation.
     <div class="col-md-3 reg-field-input">
       <input type="text" 
         ng-change="field_modified()" 
+        ng-pattern="field_pattern('aua', 'post_code')"
         class="form-control" 
         ng-model="patron.addresses[$index].post_code"
         ng-blur="handle_field_changed(patron.addresses[$index], 'post_code')"/>
@@ -821,6 +866,7 @@ within the "form" by name for validation.
     <div class="col-md-3 reg-field-input">
       <input type="text" 
         ng-change="field_modified()" 
+        ng-pattern="field_pattern('aua', 'street1')"
         class="form-control" 
         ng-model="patron.addresses[$index].street1"
         ng-blur="handle_field_changed(patron.addresses[$index], 'street1')"/>
@@ -839,6 +885,7 @@ within the "form" by name for validation.
     <div class="col-md-3 reg-field-input">
       <input type="text" 
         ng-change="field_modified()" 
+        ng-pattern="field_pattern('aua', 'street2')"
         class="form-control" 
         ng-model="patron.addresses[$index].street2"
         ng-blur="handle_field_changed(patron.addresses[$index], 'street2')"/>
@@ -857,6 +904,7 @@ within the "form" by name for validation.
     <div class="col-md-3 reg-field-input">
       <input type="text" 
         ng-change="field_modified()" 
+        ng-pattern="field_pattern('aua', 'city')"
         class="form-control" 
         ng-model="patron.addresses[$index].city"
         ng-blur="handle_field_changed(patron.addresses[$index], 'city')"/>
@@ -875,6 +923,7 @@ within the "form" by name for validation.
     <div class="col-md-3 reg-field-input">
       <input type="text" 
         ng-change="field_modified()" 
+        ng-pattern="field_pattern('aua', 'county')"
         class="form-control" 
         ng-model="patron.addresses[$index].county"
         ng-blur="handle_field_changed(patron.addresses[$index], 'county')"/>
@@ -893,6 +942,7 @@ within the "form" by name for validation.
     <div class="col-md-3 reg-field-input">
       <input type="text" 
         ng-change="field_modified()" 
+        ng-pattern="field_pattern('aua', 'state')"
         class="form-control" 
         ng-model="patron.addresses[$index].state"
         ng-blur="handle_field_changed(patron.addresses[$index], 'state')"/>
@@ -911,6 +961,7 @@ within the "form" by name for validation.
     <div class="col-md-3 reg-field-input">
       <input type="text" 
         ng-change="field_modified()" 
+        ng-pattern="field_pattern('aua', 'country')"
         class="form-control" 
         ng-model="patron.addresses[$index].country"
         ng-blur="handle_field_changed(patron.addresses[$index], 'country')"/>
index 9bc73a1..79bd673 100644 (file)
@@ -949,11 +949,53 @@ angular.module('egCoreMod')
             'open-ils.actor.patron.settings.update',
             egCore.auth.token(), new_user.id(), settings
         ).then(function(resp) {
-            console.log('settings returned ' + resp);
             return resp;
         });
     }
 
+    // Applies field-specific validation regex's from org settings 
+    // to form fields.  Be careful not remove any pattern data we
+    // are not explicitly over-writing in the provided patterns obj.
+    service.set_field_patterns = function(patterns) {
+        if (service.org_settings['opac.username_regex']) {
+            patterns.au.usrname = 
+                new RegExp(service.org_settings['opac.username_regex']);
+        }
+
+        if (service.org_settings['opac.barcode_regex']) {
+            patterns.ac.barcode = 
+                new RegExp(service.org_settings['opac.barcode_regex']);
+        }
+
+        if (service.org_settings['global.password_regex']) {
+            patterns.au.passwd = 
+                new RegExp(service.org_settings['global.password_regex']);
+        }
+
+        var phone_reg = service.org_settings['ui.patron.edit.phone.regex'];
+        if (phone_reg) {
+            // apply generic phone regex first, replace below as needed.
+            console.log(phone_reg);
+            patterns.au.day_phone = new RegExp(phone_reg);
+            patterns.au.evening_phone = new RegExp(phone_reg);
+            patterns.au.other_phone = new RegExp(phone_reg);
+        }
+
+        // the remaining patterns fit a well-known key name pattern
+
+        angular.forEach(service.org_settings, function(val, key) {
+            if (!val) return;
+            var parts = key.match(/ui.patron.edit\.(\w+)\.(\w+)\.regex/);
+            if (!parts) return;
+            var cls = parts[1];
+            var name = parts[2];
+            patterns[cls][name] = new RegExp(val);
+        });
+
+        console.log('day phone ' + patterns.au.day_phone);
+    }
+
+
     return service;
 }]);
 
@@ -1016,50 +1058,21 @@ function PatronRegCtrl($scope, $routeParams,
         }
     }
 
-    // Loads field regex's into the scope for field validation.
-    function inject_field_patterns() {
-        $scope.patterns = {au : {}, aua : {}, ac : {}};
-
-        if ($scope.org_settings['opac.username_regex']) {
-            $scope.patterns.au.usrname = 
-                new RegExp($scope.org_settings['opac.username_regex']);
-        }
-
-        if ($scope.org_settings['opac.barcode_regex']) {
-            $scope.patterns.ac.barcode = 
-                new RegExp($scope.org_settings['opac.barcode_regex']);
-        }
-
-        if ($scope.org_settings['global.password_regex']) {
-            $scope.patterns.au.passwd = 
-                new RegExp($scope.org_settings['global.password_regex']);
-        }
-
-        console.log($scope.patterns.au.passwd);
-
-        if ($scope.org_settings['ui.patron.edit.phone.regex']) {
-            // apply generic phone regex first, replace below as needed.
-
-            $scope.patterns.au.day_phone = 
-                new RegExp($scope.org_settings['ui.patron.edit.phone.regex']);
-            $scope.patterns.au.evening_phone = 
-                new RegExp($scope.org_settings['ui.patron.edit.phone.regex']);
-            $scope.patterns.au.other_phone = 
-                new RegExp($scope.org_settings['ui.patron.edit.phone.regex']);
-        }
-
-        // the remaining patterns fit a well-known key name pattern
-
-        angular.forEach($scope.org_settings, function(val, key) {
-            if (!val) return;
-            var parts = key.match(/ui.patron.edit\.(\w+)\.(\w+)\.regex/);
-            if (!parts) return;
-            var cls = parts[1];
-            var name = parts[2];
-            $scope.patterns[cls][name] = new RegExp(val);
-        });
+    // A null or undefined pattern leads to exceptions.  Before the
+    // patterns are loaded from the server, default all patterns
+    // to an innocuous regex.  To avoid re-creating numerous
+    // RegExp objects, cache the stub RegExp after initial creation.
+    // note: angular docs say ng-pattern accepts a regexp or string,
+    // but as of writing, it only works with a regexp object.
+    // (Likely an angular 1.2 vs. 1.4 issue).
+    var field_patterns = {au : {}, ac : {}, aua : {}};
+    $scope.field_pattern = function(cls, field) { 
+        if (!field_patterns[cls][field])
+            field_patterns[cls][field] = new RegExp('.*');
+        return field_patterns[cls][field];
     }
 
+    // Main page load function.  Kicks off tab init and data loading.
     $q.all([
 
         $scope.initTab ? // initTab comes from patron app
@@ -1107,7 +1120,7 @@ function PatronRegCtrl($scope, $routeParams,
 
         $scope.page_data_loaded = true;
 
-        inject_field_patterns();
+        prs.set_field_patterns(field_patterns);
     });
 
     // update the currently displayed field documentation
@@ -1260,7 +1273,6 @@ function PatronRegCtrl($scope, $routeParams,
     }
 
     $scope.day_phone_changed = function(phone) {
-        console.log('patron day phone changed to ' + phone);
         if (phone && $scope.patron.isnew && 
             $scope.org_settings['patron.password.use_phone']) {
             $scope.patron.passwd = phone.substr(-4);
@@ -1536,11 +1548,10 @@ function PatronRegCtrl($scope, $routeParams,
             $scope.reg_form[field_name].$error.required === true 
             ||
             // valid will be undefined if no pattern is set.
-            $scope.reg_form[field_name].$error.valid === false
+            $scope.reg_form[field_name].$valid === false
         );
     }
 
-
     $scope.edit_passthru.save = function(save_args) {
         if (!save_args) save_args = {};