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

index 2bf392e..eb59755 100644 (file)
   [% IF input_type == 'checkbox' %]
 
     <div class='checkbox'>
-      <input type='checkbox' ng-model='[% model %]'/>
+      <input type='checkbox' 
+        ng-blur="handle_field_changed(patron, '[% field %]')"
+        ng-model='[% model %]'/>
     </div>
 
   [% ELSE %]
       <button class="btn btn-default" ng-click="generate_password()">
         [% l('Generate Password') %]</button>
 
+    [% ELSIF field == 'usrname' %]
+
+      <div ng-show="dupe_username" class="patron-reg-validation-alert">
+        <span>[% l('Username is already in use') %]</span>
+      </div>
+
     [% ELSE %]
 
       <!-- invalidate buttons -->
   <div class="col-md-3 reg-field-input">
     <input eg-date-input 
       ng-change="field_modified()" 
+      ng-blur="handle_field_changed(patron, 'dob')"
       class="form-control" ng-model="patron.dob"/>
   </div>
 </div>
       </button>
       <ul class="dropdown-menu">
         <li ng-repeat="type in ident_types">
-          <a href ng-click="patron.ident_type = type; field_modified()">
+          <a href ng-click="patron.ident_type = type; handle_field_changed(patron, 'ident_type')">
             {{type.name()}}
           </a>
         </li>
       src='[% DOC_IMG %]'></img>
     </div>
     <div class="col-md-3 reg-field-input">
-      <eg-org-selector selected="patron.home_ou" onchange="field_modified">
+      <eg-org-selector selected="patron.home_ou" onchange="handle_home_org_changed">
       </eg-org-selector>
   </div>
 </div>
   </div>
   <div class="col-md-3 reg-field-input">
     <input eg-date-input 
-      ng-change="field_modified()" 
+      ng-blur="handle_field_changed(patron, 'expire_date')"
       class="form-control" ng-model="patron.expire_date"/>
   </div>
   <div class="col-md-3">
       <ul class="dropdown-menu">
         <li ng-repeat="level in net_access_levels">
           <a href 
-            ng-click="patron.net_access_level = level">{{level.name()}}</a>
+            ng-click="patron.net_access_level = level; handle_field_changed(patron, 'net_access_level')">
+              {{level.name()}}
+          </a>
         </li>
       </ul>
     </div>
index e381543..9efbe7b 100644 (file)
@@ -151,6 +151,13 @@ but the ones I'm finding aren't quite cutting it..*/
   font-weight: bold;
 }
 
+/* Bootstrap alert panes are too stylized/padded/etc. in this case,
+ * but consider revisiting. */
+.patron-reg-validation-alert {
+  font-weight: bold;
+  color: red;
+}
+
 /* -- end patron registration -- */
 
 [%# 
index ac9a474..a140d33 100644 (file)
@@ -109,6 +109,13 @@ angular.module('egCoreMod')
         return last + ', ' + first + (middle ? ' ' + middle : '');
     }
 
+    service.check_dupe_username = function(usrname) {
+        return egCore.net.request(
+            'open-ils.actor',
+            'open-ils.actor.username.exists',
+            egCore.auth.token(), usrname);
+    }
+
     //service.check_grp_app_perm = function(grp_id) {
 
     // determine which user groups our user is not allowed to modify
@@ -451,15 +458,14 @@ angular.module('egCoreMod')
     service.dupe_patron_search = function(patron, type, value) {
         var search;
 
-        console.log('Dupe search called with "' + 
-            type +"' and value " + value);
+        console.log('Dupe search called with "'+ type +'" and value '+ value);
 
         switch (type) {
 
             case 'name':
                 var fname = patron.first_given_name;   
                 var lname = patron.family_name;   
-                if (!(fname && lname)) return;
+                if (!(fname && lname)) return $q.when({count:0});
                 search = {
                     first_given_name : {value : fname, group : 0},
                     family_name : {value : lname, group : 0}
@@ -976,15 +982,6 @@ function PatronRegCtrl($scope, $routeParams,
 
     // 0=all, 1=suggested, 2=all
     $scope.edit_passthru.vis_level = 0; 
-    // TODO: add save/clone handlers here
-
-    $scope.field_modified = function() {
-        // Call attach with every field change, regardless of whether
-        // it's been called before.  This will allow for re-attach after
-        // the user clicks through the unload warning. egUnloadPrompt
-        // will ensure we only attach once.
-        egUnloadPrompt.attach($scope);
-    }
 
     // Apply default values for new patrons during initial registration
     // prs is shorthand for patronSvc
@@ -1019,13 +1016,6 @@ function PatronRegCtrl($scope, $routeParams,
         }
     }
 
-    function handle_home_org_changed() {
-        org_id = $scope.patron.home_ou.id();
-
-        patronRegSvc.has_group_link_perms(org_id)
-        .then(function(bool) {$scope.has_group_link_perm = bool});
-    }
-
     $q.all([
 
         $scope.initTab ? // initTab comes from patron app
@@ -1063,7 +1053,7 @@ function PatronRegCtrl($scope, $routeParams,
         });
 
         extract_hold_notify();
-        handle_home_org_changed();
+        $scope.handle_home_org_changed();
 
         if ($scope.org_settings['ui.patron.edit.default_suggested'])
             $scope.edit_passthru.vis_level = 1;
@@ -1072,7 +1062,6 @@ function PatronRegCtrl($scope, $routeParams,
             set_new_patron_defaults(prs);
 
         $scope.page_data_loaded = true;
-
     });
 
     // update the currently displayed field documentation
@@ -1099,7 +1088,6 @@ function PatronRegCtrl($scope, $routeParams,
         'ac.barcode' : 2,
         'au.usrname' : 2,
         'au.passwd' :  2,
-        // TODO passwd2 2,
         'au.first_given_name' : 2,
         'au.family_name' : 2,
         'au.ident_type' : 2,
@@ -1399,12 +1387,38 @@ function PatronRegCtrl($scope, $routeParams,
         patronRegSvc.dupe_patron_search($scope.patron, type, value)
         .then(function(res) {
             $scope.dupe_counts[type] = res.count;
-            $scope.dupe_search_encoded = 
-                encodeURIComponent(js2JSON(res.search));
+            if (res.count) {
+                $scope.dupe_search_encoded = 
+                    encodeURIComponent(js2JSON(res.search));
+            } else {
+                $scope.dupe_search_encoded = '';
+            }
         });
     }
 
+    // TODO: check edit perms
+    $scope.handle_home_org_changed = function() {
+        org_id = $scope.patron.home_ou.id();
+        patronRegSvc.has_group_link_perms(org_id)
+        .then(function(bool) {$scope.has_group_link_perm = bool});
+    }
+
+    // This is called with every character typed in a form field,
+    // since that's the only way to gaurantee something has changed.
+    // See handle_field_changed for ng-change vs. ng-blur.
+    $scope.field_modified = function() {
+        // Call attach with every field change, regardless of whether
+        // it's been called before.  This will allow for re-attach after
+        // the user clicks through the unload warning. egUnloadPrompt
+        // will ensure we only attach once.
+        egUnloadPrompt.attach($scope);
+    }
+
     // obj could be the patron, an address, etc.
+    // This is called any time a form field achieves then loses focus.
+    // It does not necessarily mean the field has changed.
+    // The alternative is ng-change, but it's called with each character
+    // typed, which would be overkill for many of the actions called here.
     $scope.handle_field_changed = function(obj, field_name) {
 
         var cls = obj.classname; // set by egIdl
@@ -1450,13 +1464,23 @@ function PatronRegCtrl($scope, $routeParams,
                 break;
 
             case 'usrname':
-                // TODO: check dupe usernames
+                patronRegSvc.check_dupe_username(value)
+                .then(function(yes) {$scope.dupe_username = Boolean(yes)});
                 break;
 
             case 'barcode':
+                // TODO: finish barcode_changed handler.
                 $scope.barcode_changed(value);
                 break;
+
+            case 'dob':
+                // TODO: very date is valid; update juvenile.
+                break;
         }
+
+        // Not every form field has an on-change handler. 
+        // Fire it here to cover those.
+        $scope.field_modified();
     }