Active/Primary Editing for Patron Cards
authorThomas Berezansky <tsbere@mvlc.org>
Tue, 1 Nov 2011 13:18:47 +0000 (09:18 -0400)
committerJason Etheridge <jason@esilibrary.com>
Thu, 1 Dec 2011 20:59:15 +0000 (15:59 -0500)
Changes "See All" into an editing interface, allowing for changing of the
active and primary state of each card.

Each requires a specific permission:

UPDATE_PATRON_ACTIVE_CARD
UPDATE_PATRON_PRIMARY_CARD

Without the appropriate permission the interface will show the green check
or red x instead of the editing elements. If you don't have either
permission then the Apply Changes button is hidden.

As the editing interface exists, also show the "See All" button when there
is only one card, but not when registering a new patron. This allows for
toggling the lone card's active flag, as well as replacing a card but
leaving the old one active.

To ensure that you can do the above, and to avoid some other errors, the
new card on a patron is saved to the editCard variable, rather than using
patron.card(). This both allows for "Replacing" a new non-primary card into
place as well as avoiding issues with editing the primary and active states
at the same time (the interface would try and update the new primary card
with the old primary card's barcode). Also, when checking for duplicate
barcodes, update the editCard with the barcode so the See All interface can
show the new card's barcode in the list properly.

Finally, included is localization for the All Cards interface headers and
buttons.

Signed-off-by: Thomas Berezansky <tsbere@mvlc.org>
Signed-off-by: Jason Etheridge <jason@esilibrary.com>
Open-ILS/src/templates/actor/user/register.tt2
Open-ILS/src/templates/actor/user/register_table.tt2
Open-ILS/web/js/dojo/openils/actor/nls/register.js
Open-ILS/web/js/ui/default/actor/user/register.js

index b03047b..379405f 100644 (file)
         <table class='oils-generic-table' style='margin:10px;'>
             <thead>
                 <tr>
-                    <th>Barcode</th>
-                    <th>Active</th>
+                    <th id='uedit-all-cards-barcode'>Barcode</th>
+                    <th id='uedit-all-cards-active'>Active</th>
+                    <th id='uedit-all-cards-primary'>Primary</th>
                 </tr>
             </thead>
             <tbody id='uedit-all-cards-tbody'>
                 <tr id='uedit-all-cards-tr-template'>
                     <td><div name='barcode'></div></td>
                     <td><div name='active'></div></td>
+                    <td><div name='primary'></div></td>
                 </tr>
             </tbody>
             <tbody>
                 <tr>
-                    <td colspan='2' style='text-align:center;'>
-                        <button dojoType='dijit.form.Button' onClick='allCardsDialog.hide()' scrollOnFocus='false'>Close</button>
+                    <td colspan='3' style='text-align:center;'>
+                        <button jsId='allCardsClose' dojoType='dijit.form.Button' onClick='allCardsDialog.hide()' scrollOnFocus='false'>Close</button>
+                        <span id='uedit-apply-card-changes'><button jsId='allCardsApply' dojoType='dijit.form.Button' onClick='applyCardChanges()' scrollOnFocus='false'>Apply Changes</button></span>
                     </td>
                 </tr>
             </tbody>
index 5528252..1a41295 100644 (file)
@@ -6,7 +6,7 @@
             <span id='uedit-dupe-barcode-warning' style='color:red; font-weight:bold' class='hidden'>
             </span>
         </td>
-        <td id='uedit-all-barcodes' class='hidden'>
+        <td id='uedit-all-barcodes'>
             <button dojoType='dijit.form.Button' jsId='allCards' scrollOnFocus='false'></button>
         </td>
     </tr>
index b16af89..3df6e1b 100644 (file)
     "SAVE_CLONE" : "Save &amp; Clone",
     "SHOW_REQUIRED" : "Show Only Required Fields",
     "SHOW_SUGGESTED" : "Show Suggested Fields",
-    "SHOW_ALL" : "Show All Fields"
+    "SHOW_ALL" : "Show All Fields",
+    "ALL_CARDS_BARCODE" : "Barcode",
+    "ALL_CARDS_ACTIVE" : "Active",
+    "ALL_CARDS_PRIMARY" : "Primary",
+    "ALL_CARDS_CLOSE" : "Close",
+    "ALL_CARDS_APPLY" : "Apply Changes"
 }
index 30359fe..42bf177 100644 (file)
@@ -46,6 +46,8 @@ var optInSettings;
 var allCardsTemplate;
 var uEditCloneCopyAddr; // if true, copy addrs on clone instead of link
 var homeOuTypes = {};
+var cardPerms = {};
+var editCard;
 
 var dupeUsrname = false;
 var dupeBarcode = false;
@@ -76,6 +78,11 @@ function load() {
     dojo.byId('parentGuardian').innerHTML = localeStrings.PARENT_OR_GUARDIAN;
     dojo.byId('userSettings').innerHTML = localeStrings.USER_SETTINGS;
     dojo.byId('statCats').innerHTML = localeStrings.STAT_CATS;
+    dojo.byId('uedit-all-cards-barcode').innerHTML = localeStrings.ALL_CARDS_BARCODE;
+    dojo.byId('uedit-all-cards-active').innerHTML = localeStrings.ALL_CARDS_ACTIVE;
+    dojo.byId('uedit-all-cards-primary').innerHTML = localeStrings.ALL_CARDS_PRIMARY;
+    allCardsClose.attr("label", localeStrings.ALL_CARDS_CLOSE);
+    allCardsApply.attr("label", localeStrings.ALL_CARDS_APPLY);
 
     dojo.query("td[name='addressHeader']").forEach( function(item) { item.innerHTML = localeStrings.ADDRESS_HEADER; });
     dojo.query("span[name='mailingAddress']").forEach( function(item) { item.innerHTML = localeStrings.ADDRESS_MAILING; });
@@ -231,8 +238,28 @@ function load() {
 
     dojo.connect(replaceBarcode, 'onClick', replaceCardHandler);
     dojo.connect(allCards, 'onClick', drawAllCards);
-    if(patron.cards().length > 1)
-        dojo.removeClass(dojo.byId('uedit-all-barcodes'), 'hidden');
+    if(patron.isnew()) {
+        dojo.addClass(dojo.byId('uedit-all-barcodes'), 'hidden');
+    } else {
+        new openils.User().getPermOrgList(
+            'UPDATE_PATRON_ACTIVE_CARD',
+            function(orgList) { 
+                if(orgList.indexOf(patron.home_ou()) != -1) 
+                    cardPerms['UPDATE_PATRON_ACTIVE_CARD'] = true;
+            },
+            true, 
+            true
+        );
+        new openils.User().getPermOrgList(
+            'UPDATE_PATRON_PRIMARY_CARD',
+            function(orgList) { 
+                if(orgList.indexOf(patron.home_ou()) != -1) 
+                    cardPerms['UPDATE_PATRON_PRIMARY_CARD'] = true;
+            },
+            true, 
+            true
+        );
+    }
 
     var input = findWidget('ac', 'barcode');
     if (patron.isnew()) {
@@ -313,22 +340,50 @@ function drawAllCards() {
             tbody.removeChild(tbody.childNodes[0]);
     }
 
+    if(cardPerms['UPDATE_PATRON_ACTIVE_CARD'] || cardPerms['UPDATE_PATRON_PRIMARY_CARD']) {
+        dojo.removeClass(dojo.byId('uedit-apply-card-changes'), 'hidden');
+    } else {
+        dojo.addClass(dojo.byId('uedit-apply-card-changes'), 'hidden');
+    }
+
     var first = true;
     dojo.forEach(
-        [patron.card()].concat(patron.cards()), // grab the main card first
+        patron.cards().filter(function(c) { return c.id() == patron.card().id(); }).concat(patron.cards()), // grab the main card first
         function(card) {
             if(!first) {
                 if(card.id() == patron.card().id())
                     return;
             }
             var row = allCardsTemplate.cloneNode(true);
+            row.setAttribute("cardid", card.id());
+            row.card = card;
             getByName(row, 'barcode').innerHTML = card.barcode();
-            getByName(row, 'active').appendChild(
-                openils.Util.isTrue(card.active()) ? 
-                    dojo.byId('true').cloneNode(true) :
-                    dojo.byId('false').cloneNode(true)
-            ); 
-
+            if(cardPerms['UPDATE_PATRON_ACTIVE_CARD']) {
+                row.active_checkbox = new dijit.form.CheckBox({
+                    scrollOnFocus:false,
+                    checked: openils.Util.isTrue(card.active())
+                }, getByName(row, 'active'));
+            } else {
+                getByName(row, 'active').appendChild(
+                    openils.Util.isTrue(card.active()) ? 
+                        dojo.byId('true').cloneNode(true) :
+                        dojo.byId('false').cloneNode(true)
+                );
+            }
+            if(cardPerms['UPDATE_PATRON_PRIMARY_CARD']) {
+                row.primary_radiobutton = new dijit.form.RadioButton({
+                    scrollOnFocus:false,
+                    checked: card.id() == patron.card().id(),
+                    value: card.id(),
+                    name: 'card_primary'
+                }, getByName(row, 'primary'));
+            } else {
+                getByName(row, 'primary').appendChild(
+                    openils.Util.isTrue(card.id() == patron.card().id()) ? 
+                        dojo.byId('true').cloneNode(true) :
+                        dojo.byId('false').cloneNode(true)
+                );
+            }
             tbody.appendChild(row);
             first = false;
         }
@@ -337,6 +392,27 @@ function drawAllCards() {
     allCardsDialog.show();
 }
 
+function applyCardChanges() {
+    var cardrows = dojo.query('[cardid]', allCardsDialog.domNode);
+    dojo.forEach(cardrows,
+        function(row) {
+            if(cardPerms['UPDATE_PATRON_ACTIVE_CARD']) {
+                var active = row.active_checkbox.checked ? 't' : 'f'
+                if(row.card.active() != active) {
+                    row.card.active(active);
+                    row.card.ischanged(1);
+                }
+            }
+            if(cardPerms['UPDATE_PATRON_PRIMARY_CARD']) {
+                if(row.primary_radiobutton.checked && row.card.id() != patron.card().id()) {
+                    patron.card(row.card);
+                }
+            }
+        }
+    );
+    allCardsDialog.hide();
+}
+
 /**
  * Mark the current card inactive, create a new primary card
  */
@@ -357,6 +433,7 @@ function replaceCardHandler() {
     newc.isnew(1);
     newc.active('t');
     patron.card(newc);
+    editCard = newc;
     var t = patron.cards();
         if (!t) { t = []; }
         t.push(newc);
@@ -747,7 +824,7 @@ function fleshFMRow(row, fmcls, args) {
     var fmObject = null;
     switch(fmcls) {
         case 'au' : fmObject = patron; break;
-        case 'ac' : fmObject = patron.card(); break;
+        case 'ac' : if(!editCard) editCard = patron.card(); fmObject = editCard; break;
         case 'aua' : 
             fmObject = patron.addresses().filter(
                 function(i) { return (i.id() == args.addr) })[0];
@@ -995,6 +1072,7 @@ function attachWidgetEvents(fmcls, fmfield, widget) {
                                 } else {
                                     dupeBarcode = false;
                                     dojo.addClass(dojo.byId('uedit-dupe-barcode-warning'), 'hidden');
+                                    editCard.barcode(barcode); // Keep the "All" interface up to date
                                     var un = findWidget('au', 'usrname');
                                     if(!un.widget.attr('value'))
                                         un.widget.attr('value', barcode);
@@ -1387,7 +1465,8 @@ function _uEditSave(doClone) {
                 break;
 
             case 'ac':
-                patron.card()[w._fmfield](val);
+                if(!editCard) editCard = patron.card();
+                editCard[w._fmfield](val);
                 break;
 
             case 'aua':