From e84f8df7454d725e0fdb4e02d36746c64834bb66 Mon Sep 17 00:00:00 2001
From: Kyle Huckins <khuckins@catalyte.io>
Date: Fri, 17 Nov 2017 23:54:53 +0000
Subject: [PATCH] lp1635386 Items Column & Styles for Bill Item Status

- CSS classes for red, dark red, and orange eg-grid-cells.
- New parameter for eg-grid 'rowClass' to take an object with a function
to set the class of a cell, allowing such customizations as coloring based
on item fields.
- Implementation of 'rowClass' on the Patron Bills interface to display
colors indicating current Fines Stop reason, based on XUL client.
- New parameter for eg-grid 'statusCell' to take an object with a function
to programattically add status icons to a new "Status Icon" column. Said
column requires a boolean in the object in order to display.
- Implementation of 'statusCell' on the Patron Bills interface to display
glyphicons based on if the bill is for a circ that is lost, overdue, or long
overdue.

Signed-off-by: Kyle Huckins <khuckins@catalyte.io>

 Changes to be committed:
	modified:   Open-ILS/src/templates/staff/circ/patron/t_bills_list.tt2
	modified:   Open-ILS/src/templates/staff/css/style.css.tt2
	modified:   Open-ILS/src/templates/staff/share/t_autogrid.tt2
	modified:   Open-ILS/web/js/ui/default/staff/circ/patron/bills.js
	modified:   Open-ILS/web/js/ui/default/staff/services/grid.js

Signed-off-by: Kathy Lussier <klussier@masslnc.org>
Signed-off-by: Dan Wells <dbw2@calvin.edu>
Signed-off-by: Dawn Dale <ddale@georgialibraries.org>
---
 .../templates/staff/circ/patron/t_bills_list.tt2   |  8 +++-
 Open-ILS/src/templates/staff/css/style.css.tt2     | 36 ++++++++++++++++-
 Open-ILS/src/templates/staff/share/t_autogrid.tt2  | 19 +++++++--
 .../web/js/ui/default/staff/circ/patron/bills.js   | 46 ++++++++++++++++++++++
 Open-ILS/web/js/ui/default/staff/services/grid.js  | 11 ++++++
 5 files changed, 113 insertions(+), 7 deletions(-)

diff --git a/Open-ILS/src/templates/staff/circ/patron/t_bills_list.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_bills_list.tt2
index a6be0ccfe7..ad1db1925f 100644
--- a/Open-ILS/src/templates/staff/circ/patron/t_bills_list.tt2
+++ b/Open-ILS/src/templates/staff/circ/patron/t_bills_list.tt2
@@ -6,7 +6,9 @@
   grid-controls="gridControls"
   revision="gridRevision"
   persist-key="circ.patron.bills"
-  dateformat="{{$root.egDateAndTimeFormat}}">
+  dateformat="{{$root.egDateAndTimeFormat}}"
+  row-class="colorizeBillsList"
+  status-cell="statusIconColumn">
 
   <eg-grid-menu-item label="[% l('Bill Patron') %]" 
     handler="showBillDialog"></eg-grid-menu-item>
@@ -48,7 +50,7 @@
   <eg-grid-action label="[% l('Full Details') %]" 
     handler="showFullDetails"></eg-grid-action>
 
-  <eg-grid-field label="[% l('Balance Owed') %]" path='summary.balance_owed'></eg-grid-field>
+  <eg-grid-field label="[% l('Balance Owed') %]" path='summary.balance_owed' required></eg-grid-field>
   <eg-grid-field label="[% l('Bill #') %]" path='id'></eg-grid-field>
   <eg-grid-field label="[% l('Start') %]" path='xact_start' datatype="timestamp"></eg-grid-field>
   <eg-grid-field label="[% l('Total Billed') %]" path='summary.total_owed'></eg-grid-field>
@@ -101,6 +103,8 @@
   <eg-grid-field path='circulation.circ_lib' required hidden></eg-grid-field>
   <eg-grid-field path='circulation.duration' required hidden></eg-grid-field>
   <eg-grid-field path='circulation.due_date' dateonlyinterval="circulation.duration" datecontext="circulation.circ_lib" required hidden></eg-grid-field>
+  <eg-grid-field label="[% l('Stop Fines') %]" path="circulation.stop_fines" hidden required>  </eg-grid-field>
+  <eg-grid-field path="circulation.checkin_time" hidden required></eg-grid-field>
   <eg-grid-field path='circulation.*' hidden> </eg-grid-field>
   <eg-grid-field label="[% l('Checkout / Renewal Library') %]"
     path='circulation.circ_lib.shortname' required hidden> </eg-grid-field>
diff --git a/Open-ILS/src/templates/staff/css/style.css.tt2 b/Open-ILS/src/templates/staff/css/style.css.tt2
index b70887b987..ebeab4ada0 100644
--- a/Open-ILS/src/templates/staff/css/style.css.tt2
+++ b/Open-ILS/src/templates/staff/css/style.css.tt2
@@ -301,12 +301,22 @@ table.list tr.selected td { /* deprecated? */
   text-align: center;
 }
 
-/* the conf header must be twice the stock flex */
+.eg-grid-cell-stock-status {
+  width: 4.4em;
+  text-align: center;
+}
+
+/* the conf header must be ~four times the stock flex */
 .eg-grid-cell-conf-header {
   width: 4.4em;
   font-weight: bold;
 }
 
+.eg-grid-cell-conf-header-status {
+  width: 8.8em;
+  font-weight: bold;
+}
+
 .eg-grid-row-selected {
   color: #000;
   background-color: rgb(201, 221, 225);
@@ -333,6 +343,30 @@ table.list tr.selected td { /* deprecated? */
   background: rgb(201, 221, 225);
   border-bottom: 1px solid #888;
 }
+
+/* patron bill row-highlighting */
+.red-row-highlight {
+  color: #FFF;
+  background-color: #FF0000;
+}
+.orange-row-highlight {
+  color: #FFF;
+  background-color: #FFA500 ;
+}
+.dark-red-row-highlight {
+  color: #FFF;
+  background-color: #800000;
+}
+.eg-grid-row-selected .red-row-highlight {
+  background-color: #CF0000;
+}
+.eg-grid-row-selected .orange-row-highlight {
+  background-color: #DE9000;
+}
+.eg-grid-row-selected .dark-red-row-highlight {
+  background-color: #5C0000;
+}
+
 .eg-grid-cell-content::selection {
   color: #000;
   background: rgb(201, 221, 225);
diff --git a/Open-ILS/src/templates/staff/share/t_autogrid.tt2 b/Open-ILS/src/templates/staff/share/t_autogrid.tt2
index 0519012098..21d602b87a 100644
--- a/Open-ILS/src/templates/staff/share/t_autogrid.tt2
+++ b/Open-ILS/src/templates/staff/share/t_autogrid.tt2
@@ -228,6 +228,9 @@
           type='checkbox' ng-model="selectAll"/> 
       </div>
     </div>
+    <div class="eg-grid-cell eg-grid-cell-stock-status" ng-show="statusCell.isEnabled">
+      <div title="[% l('Status Icon Column') %]">[% l('Status') %]</div>
+    </div>
     <div class="eg-grid-cell"
         eg-grid-column-drag-dest
         ng-class="{'eg-grid-column-last-mod' : isLastModifiedColumn(col)}"
@@ -257,7 +260,8 @@
 
   <!-- Inline grid configuration row -->
   <div class="eg-grid-row eg-grid-conf-row" ng-show="showGridConf">
-    <div class="eg-grid-cell eg-grid-cell-conf-header">
+    <div class="eg-grid-cell"
+      ng-class="statusicon.isEnabled ? 'eg-grid-cell-conf-header-status' : 'eg-grid-cell-conf-header'">
       <div class="eg-grid-conf-cell-entry">[% l('Expand') %]</div>
       <div class="eg-grid-conf-cell-entry">[% l('Shrink') %]</div>
     </div>
@@ -290,14 +294,16 @@
         ng-show="items.length > 0"
         ng-class="{'eg-grid-row-selected' : selected[indexValue(item)]}">
       <div class="eg-grid-cell eg-grid-cell-stock" ng-show="showIndex"
-        ng-click="handleRowClick($event, item)" title="[% l('Row Index') %]">
+        ng-click="handleRowClick($event, item)" title="[% l('Row Index') %]"
+          ng-class="rowClass.rowClass(item)">
         <a href ng-show="gridControls.activateItem" 
           ng-click="gridControls.activateItem(item)" style="font-weight:bold">
           {{$index + offset() + 1}}
         </a>
         <div ng-hide="gridControls.activateItem">{{$index + offset() + 1}}</div>
       </div>
-      <div class="eg-grid-cell eg-grid-cell-stock" ng-show="canMultiSelect">
+      <div class="eg-grid-cell eg-grid-cell-stock" ng-show="canMultiSelect"
+          ng-class="rowClass.rowClass(item)">
         <!-- ng-click=handleRowClick here has unintended 
              consequences and is unnecessary, avoid it -->
         <div>
@@ -306,12 +312,17 @@
             ng-model="selected[indexValue(item)]"/>
         </div>
       </div>
+      <div class="eg-grid-cell eg-grid-cell-stock-status" ng-show="statusCell.isEnabled"
+          ng-class="rowClass.rowClass(item)">
+          <span ng-bind-html="statusCell.template(item)"></span>
+      </div>
       <div class="eg-grid-cell eg-grid-cell-content"
           ng-click="handleRowClick($event, item)"
           ng-dblclick="gridControls.activateItem(item)"
           ng-repeat="col in columns"
           style="text-align:{{col.align}}; flex:{{col.flex}}"
-          ng-show="col.visible">
+          ng-show="col.visible"
+          ng-class="rowClass.rowClass(item)">
 
           <!-- if the cell comes with its own template,
                translate that content into HTML and insert it here -->
diff --git a/Open-ILS/web/js/ui/default/staff/circ/patron/bills.js b/Open-ILS/web/js/ui/default/staff/circ/patron/bills.js
index 89110aa859..a84ab2cdfc 100644
--- a/Open-ILS/web/js/ui/default/staff/circ/patron/bills.js
+++ b/Open-ILS/web/js/ui/default/staff/circ/patron/bills.js
@@ -219,6 +219,52 @@ function($scope , $q , $routeParams , egCore , egConfirmDialog , $location,
             return ['xact_start']; 
         }
     }
+    // -------------
+    // Apply coloring to rows based on fines stop reason
+    $scope.colorizeBillsList = {
+        rowClass: function(item) {
+            if (!item['circulation.checkin_time']) {
+                if (item['circulation.stop_fines'] == 'LOST') {
+                    return 'dark-red-row-highlight';
+                } else if (item['circulation.stop_fines'] == 'LONGOVERDUE') {
+                    return 'red-row-highlight';
+                } else if (item['circulation.due_date'] &&  // Still checked out - need feedback on this approach, feel like there's a better way
+                          !item['circulation.stop_fines']) {
+                    return 'orange-row-highlight';
+                }
+            }
+        }
+    }
+
+    // Status Icon Column definition
+    $scope.statusIconColumn = {
+        isEnabled: true,
+        template: function(item) {
+            var template = "";
+            var icons = [];
+            var now = new Date();
+
+            if (item['circulation.due_date'] &&
+                !item['circulation.checkin_time']) {
+                var due_date = new Date(item['circulation.due_date']);
+
+                if (item['circulation.stop_fines'] &&
+                    item['circulation.stop_fines'] == "LOST") {
+                    icons.push('glyphicon-question-sign');
+                } else if (item['circulation.stop_fines'] &&
+                    item['circulation.stop_fines'] == "LONGOVERDUE") {
+                    icons.push('glyphicon-exclamation-sign');
+                } else if (now >= due_date) {
+                    icons.push('glyphicon-time');
+                }
+            }
+
+            angular.forEach(icons, function(icon) {
+                template = template + "<i class='glyphicon " + icon + "'></i>"
+            });
+            return template;
+        }
+    }
 
     billSvc.fetchSummary().then(function(s) {$scope.summary = s});
 
diff --git a/Open-ILS/web/js/ui/default/staff/services/grid.js b/Open-ILS/web/js/ui/default/staff/services/grid.js
index 15d61f281d..71e271cd97 100644
--- a/Open-ILS/web/js/ui/default/staff/services/grid.js
+++ b/Open-ILS/web/js/ui/default/staff/services/grid.js
@@ -54,6 +54,14 @@ angular.module('egGridMod',
             //                 column
             features : '@',
 
+            // optional: object containing function to conditionally apply
+            //    class to each row.
+            rowClass : '=',
+
+            // optional: object that enables status icon field and contains
+            //    function to handle what status icons should exist and why.
+            statusCell : '=',
+
             // optional primary grid label
             mainLabel : '@',
 
@@ -110,6 +118,9 @@ angular.module('egGridMod',
             scope.handleAutoFields();
             scope.collect();
 
+            var statusCell = scope.statusCell;
+            var rowClass = scope.rowClass;
+
             scope.grid_element = element;
             $(element)
                 .find('.eg-grid-content-body')
-- 
2.11.0