LP#1452950 Unload prompts more handlers / dupe styling
authorBill Erickson <berickxx@gmail.com>
Mon, 21 Dec 2015 00:51:01 +0000 (19:51 -0500)
committerGalen Charlton <gmc@esilibrary.com>
Thu, 25 Feb 2016 22:32:00 +0000 (17:32 -0500)
Link in remaining unload onchange handlers.  Use bootstrap alert styles
for dupe patron links.

Signed-off-by: Bill Erickson <berickxx@gmail.com>
Signed-off-by: Galen Charlton <gmc@esilibrary.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
Open-ILS/web/js/ui/default/staff/services/ui.js

index 0879eb4..4a804f9 100644 (file)
 
        <div id="reg-dupe-links">
                [%# dupe_search_encoded is uri escaped in the JS %]
-               <div>
-                       <a target="_blank" ng-show="dupe_counts.name"
-                               href="/eg/staff/circ/patron/search?search={{dupe_search_encoded}}" >
+               <div class="alert alert-danger" ng-show="dupe_counts.name">
+                       <a target="_blank"
+                               href="/eg/staff/circ/patron/search?search={{dupe_search_encoded}}">
                        [% l('[_1] patron(s) with same name', '{{dupe_counts.name}}') %]
                        </a>
                </div>
-               <div>
-                       <a target="_blank" ng-show="dupe_counts.email"
-                               href="/eg/staff/circ/patron/search?search={{dupe_search_encoded}}" >
+               <div class="alert alert-danger" ng-show="dupe_counts.email">
+                       <a target="_blank"
+                               href="/eg/staff/circ/patron/search?search={{dupe_search_encoded}}">
                                [% l('[_1] patron(s) with same email', 
                                '{{dupe_counts.email}}') %]</a>
                </div>
-               <div>
-                       <a target="_blank" ng-show="dupe_counts.ident"
-                               href="/eg/staff/circ/patron/search?search={{dupe_search_encoded}}" >
+               <div class="alert alert-danger" ng-show="dupe_counts.ident">
+                       <a target="_blank" 
+                               href="/eg/staff/circ/patron/search?search={{dupe_search_encoded}}">
                                [% l('[_1] patron(s) with same identification', 
                                '{{dupe_counts.ident}}') %]</a>
                </div>
-               <div>
-                       <a target="_blank" ng-show="dupe_counts.phone"
-                               href="/eg/staff/circ/patron/search?search={{dupe_search_encoded}}" >
+               <div class="alert alert-danger" ng-show="dupe_counts.phone">
+                       <a target="_blank" 
+                               href="/eg/staff/circ/patron/search?search={{dupe_search_encoded}}">
                                [% l('[_1] patron(s) with same phone', 
                                '{{dupe_counts.phone}}') %]</a>
                </div>
-               <div>
-                       <a target="_blank" ng-show="dupe_counts.address"
+               <div class="alert alert-danger" ng-show="dupe_counts.address">
+                       <a target="_blank" 
                                href="/eg/staff/circ/patron/search?search={{dupe_search_encoded}}" >
                                [% l('[_1] patron(s) with same address', 
                                '{{dupe_counts.address}}') %]</a>
        </div>
 
        <!-- IDL field documentation window -->
-       <fieldset id="reg-field-doc" ng-show="selected_field_doc">
-               <legend>
-               {{idl_fields[selected_field_doc.fm_class()][selected_field_doc.field()].label}}
-               </legend>
-               <div>{{selected_field_doc.string()}}</div>
-       </fieldset>
+  <div class="alert alert-info" ng-show="selected_field_doc">
+    <fieldset id="reg-field-doc">
+      <legend>
+      {{idl_fields[selected_field_doc.fm_class()][selected_field_doc.field()].label}}
+      </legend>
+      <div>{{selected_field_doc.string()}}</div>
+    </fieldset>
+  </div>
 </div>
 
 
     <!-- text / number input -->
 
     [% IF field == 'alert_message' %]
-      <textarea class="form-control" ng-model="[% model %]"/>
+      <textarea ng-change="field_modified()" 
+        class="form-control" ng-model="[% model %]"/>
     [% ELSIF field == 'post_code' %]
-      <input type="text" ng-blur="post_code_changed(patron.[% path %])"
+      <input type="text" ng-change="field_modified()" 
+        ng-blur="post_code_changed(patron.[% path %])"
         class="form-control" ng-model="[% model %]"/>
     [% ELSIF field == 'barcode' %]
       <input type="text" 
         focus-me="focus_bc"
+        ng-change="field_modified()" 
         ng-disabled="disable_bc"
         ng-blur="barcode_changed(patron.card.barcode)"
         class="form-control" ng-model="[% model %]"/>
     [% ELSIF field == 'usrname' %]
       <input type="text" 
         focus-me="focus_usrname"
+        ng-change="field_modified()" 
         ng-blur="usrname_changed(patron.usrname)"
         class="form-control" ng-model="[% model %]"/>
     [% ELSIF field == 'day_phone' %]
       <input type="text" 
         ng-blur="day_phone_changed(patron.day_phone)"
+        ng-change="field_modified()" 
         class="form-control" ng-model="[% model %]"/>
     [% ELSIF field.match('phone') %]
       <input type="text" 
+        ng-change="field_modified()" 
         ng-blur="dupe_value_changed('phone', patron.[% field %])"
         class="form-control" ng-model="[% model %]"/>
     [% ELSIF field.match('ident_value') %]
       <input type="text" 
+        ng-change="field_modified()" 
         ng-blur="dupe_value_changed('ident', patron.[% field %])"
         class="form-control" ng-model="[% model %]"/>
     [% ELSIF field == 'first_given_name' OR field == 'family_name' %]
       <input type="text" 
+        ng-change="field_modified()" 
         ng-blur="dupe_value_changed('name', patron.[% field %])"
         class="form-control" ng-model="[% model %]"/>
     [% ELSIF field == 'email' %]
       <input type="[% input_type %]" 
+        ng-change="field_modified()" 
         ng-blur="dupe_value_changed('email', patron.email)"
         class="form-control" ng-model="[% model %]"/>
     [% ELSIF field.match('street') OR field == 'city' %]
       <!-- note: passing address object to dupe_value_changed -->
       <input type="[% input_type %]" 
+        ng-change="field_modified()" 
         ng-blur="dupe_value_changed('address', patron.[% path %])"
         class="form-control" ng-model="[% model %]"/>
     [% ELSE %]
       <input type="[% input_type %]" 
+        ng-change="field_modified()" 
         class="form-control" ng-model="[% model %]"/>
     [% END %]
   [% END %]
   </div>
   <div class="col-md-3 reg-field-input">
     <input eg-date-input 
+      ng-change="field_modified()" 
       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">{{type.name()}}</a>
+          <a href ng-click="patron.ident_type = type; field_modified()">
+            {{type.name()}}
+          </a>
         </li>
       </ul>
     </div>
       src='[% DOC_IMG %]'></img>
     </div>
     <div class="col-md-3 reg-field-input">
-      <eg-org-selector selected="patron.home_ou" onchange="">
+      <eg-org-selector selected="patron.home_ou" onchange="field_modified">
       </eg-org-selector>
   </div>
 </div>
   </div>
   <div class="col-md-3 reg-field-input">
     <input eg-date-input 
+      ng-change="field_modified()" 
       class="form-control" ng-model="patron.expire_date"/>
   </div>
   <div class="col-md-3">
     <label>{{user_setting_types['opac.default_phone'].label()}}</label>
   </div>
   <div class="col-md-3 reg-field-input">
-    <input type='text' ng-model="user_settings['opac.default_phone']"/>
+    <input 
+      ng-change="field_modified()" 
+      type='text' ng-model="user_settings['opac.default_phone']"/>
   </div>
 </div>
 
     <label>{{user_setting_types['opac.default_pickup_location'].label()}}</label>
   </div>
   <div class="col-md-3 reg-field-input">
-    <eg-org-selector selected="patron.home_ou" onchange=""></eg-org-selector>
+    <eg-org-selector 
+      xonchange="field_modified" 
+      selected="patron.home_ou"></eg-org-selector>
   </div>
 </div>
 
   </div>
   <div class="col-md-3 reg-field-input">
     <div class='checkbox'>
-      <input type='checkbox' ng-model="user_settings['circ.holds_behind_desk']"/>
+      <input 
+        ng-change="field_modified()" 
+        type='checkbox' ng-model="user_settings['circ.holds_behind_desk']"/>
     </div>
   </div>
 </div>
   </div>
   <div class="col-md-3 reg-field-input flex-row">
     <div class='flex-cell'>
-      <input type='checkbox' ng-model="hold_notify_phone"/>
+      <input 
+        ng-change="field_modified()" 
+        type='checkbox' ng-model="hold_notify_phone"/>
       [% l('Phone') %]
     </div>
     <div class='flex-cell'>
-      <input type='checkbox' ng-model="hold_notify_email"/>
+      <input 
+        ng-change="field_modified()" 
+        type='checkbox' ng-model="hold_notify_email"/>
       [% l('Email') %]
     </div>
     <div class='flex-cell' ng-if="org_settings['sms.enable']">
-      <input type='checkbox' ng-model="hold_notify_sms"/>
+      <input 
+        ng-change="field_modified()" 
+        type='checkbox' ng-model="hold_notify_sms"/>
       [% l('SMS') %]
     </div>
   </div>
     <label>[% l('Default SMS/Text Number') %]</label>
   </div>
   <div class="col-md-3 reg-field-input">
-    <input type='text'/>
+    <input 
+      ng-change="field_modified()" 
+      type='text'/>
   </div>
 </div>
 
       <ul class="dropdown-menu">
         <li ng-repeat="carrier in sms_carriers">
           <a href 
-            ng-click="user_settings['opac.default_sms_carrier'] = carrier">
+            ng-click="field_modified();user_settings['opac.default_sms_carrier'] = carrier">
                 {{carrier.name()}}
           </a>
         </li>
     <label>{{type.label()}}</label>
   </div>
   <div class="col-md-3 reg-field-input">
-    <input type='checkbox' ng-model="user_settings[type.name()]"/>
+    <input 
+      ng-change="field_modified()" 
+      type='checkbox' ng-model="user_settings[type.name()]"/>
   </div>
 </div>
 
       <div class="col-md-3">
           <span class='pad-all-min'>
             [% l('Mailing') %] <input type='checkbox' 
-              ng-change="set_addr_type(addr, 'mailing')" 
+              ng-change="field_modified();set_addr_type(addr, 'mailing')" 
               ng-model="addr._is_mailing"/>
           </span>
           <span class='pad-all-min'>
             [% l('Physical') %] <input type='checkbox' 
-              ng-change="set_addr_type(addr, 'billing')" 
+              ng-change="field_modified();set_addr_type(addr, 'billing')" 
               ng-model="addr._is_billing"/>
           </span>
           <span class='pad-all-min'>
-            <button type="button" ng-click="delete_address(addr.id)" 
+            <button type="button" 
+              ng-click="field_modified();delete_address(addr.id)" 
               class="btn btn-danger">[% l('X') %]</button>
           </span>
       </div>
   </div>
   <div class="col-md-3 reg-field-input">
     <div ng-if="cat.entries().length == 0">
-      <input type="text" class="form-control"/>
+      <input 
+        ng-change="field_modified()" 
+        type="text" class="form-control"/>
     </div>
     <div ng-if="cat.entries().length != 0">
       <div class="btn-group" dropdown>
         </button>
         <ul class="dropdown-menu">
           <li ng-repeat="entry in cat.entries()">
-            <a href ng-click="stat_cat_entry_maps[cat.id()]=entry"> 
+            <a href 
+              ng-click="field_modified();stat_cat_entry_maps[cat.id()]=entry"> 
               {{entry.value()}}
             </a>
           </li>
           </button>
           <ul class="dropdown-menu">
             <li ng-repeat="answer in question.answers()">
-              <a href ng-click="survey_responses[question.id()] = answer"> 
+              <a href 
+                ng-click="field_modified();survey_responses[question.id()] = answer"> 
                 {{answer.answer()}} 
               </a>
             </li>
index f101d5c..e381543 100644 (file)
@@ -102,8 +102,10 @@ but the ones I'm finding aren't quite cutting it..*/
     position: fixed;
     top:160px;
     right:20px;
-    /*border:2px dashed #d9e8f9;*/
+    /*
+    border:2px dashed #d9e8f9;
     -moz-border-radius: 10px;
+    */
     font-weight: bold;
     padding: 20px;
     margin-top: 20px;
index f03a4eb..d9dc78f 100644 (file)
@@ -706,8 +706,12 @@ function PatronRegCtrl($scope, $routeParams,
     $scope.edit_passthru.vis_level = 0; 
     // TODO: add save/clone handlers here
 
-    // TODO: call attach() on the first instance of a modified value
-    //egUnloadPrompt.attach($scope);
+    var modify_tracked = false;
+    $scope.field_modified = function() {
+        if (modify_tracked) return;
+        modify_tracked = true;
+        egUnloadPrompt.attach($scope);
+    }
 
     // Apply default values for new patrons during initial registration
     // prs is shorthand for patronSvc
@@ -881,6 +885,7 @@ function PatronRegCtrl($scope, $routeParams,
     $scope.set_profile = function(grp) {
         $scope.patron.profile = grp;
         $scope.set_expire_date();
+        $scope.field_modified();
     }
 
     $scope.new_address = function() {
@@ -1118,6 +1123,9 @@ function PatronRegCtrl($scope, $routeParams,
 
     $scope.edit_passthru.save = function() {
 
+        // remove page unload warning prompt
+        egUnloadPrompt.clear();
+
         // toss the deleted addresses back into the patron's list of
         // addresses so it's included in the update
         $scope.patron.addresses = 
index e2c6b93..2ffbc22 100644 (file)
@@ -186,7 +186,8 @@ function($modal, $interpolate) {
 
 /**
  * Warn on page unload and give the user a chance to avoid navigating
- * away from the current page.
+ * away from the current page.  
+ * Only one handler is supported per page.
  * NOTE: we can't use an egUnloadDialog as the dialog builder, because
  * it renders asynchronously, which allows the page to redirect before
  * the dialog appears.
@@ -196,6 +197,7 @@ function($modal, $interpolate) {
 function($window , egStrings) {
     var service = {};
 
+    // attach a page/scope unload prompt
     service.attach = function($scope, msg) {
 
         // handle page change
@@ -203,12 +205,24 @@ function($window , egStrings) {
             return msg || egStrings.EG_UNLOAD_PAGE_PROMPT_MSG;
         });
 
-        // handle controller change (e.g. tabbed navigation)
-        $scope.$on('$locationChangeStart', function(evt, next, current) {
+        if (!$scope) return;
+
+        // If a scope was provided, attach a scope-change handler,
+        // similar to the page-page prompt.
+        service.locChangeCancel = 
+            $scope.$on('$locationChangeStart', function(evt, next, current) {
             if (!confirm(msg || egStrings.EG_UNLOAD_CTRL_PROMPT_MSG)) 
                 evt.preventDefault();
         });
     };
+
+    // remove the page unload prompt
+    service.clear = function() {
+        $($window).off('beforeunload');
+        if (service.locChangeCancel)
+            service.locChangeCancel();
+    }
+
     return service;
 }])