[open-ils-commits] [GIT] Evergreen ILS branch master updated. 140ff94d566acf262486152bad8395b32429ed4b

Evergreen Git git at git.evergreen-ils.org
Thu Sep 20 12:30:54 EDT 2018


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Evergreen ILS".

The branch, master has been updated
       via  140ff94d566acf262486152bad8395b32429ed4b (commit)
       via  443ed531a19fdea611a01f931252316cffbbce47 (commit)
       via  b98f8efea5a1937704c94b3de534d9028fd09d40 (commit)
      from  5f4b487477d6504b91991c042441209e28c8c30b (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 140ff94d566acf262486152bad8395b32429ed4b
Author: Mike Rylander <mrylander at gmail.com>
Date:   Fri Aug 3 17:25:33 2018 -0400

    LP#1732761: Chain the promises to avoid races
    
    It looks like there's a race condition gathering locations for larger copy
    sets.  Here we chain the promises to remove the race by serialization.
    
    Signed-off-by: Mike Rylander <mrylander at gmail.com>
    Signed-off-by: Kathy Lussier <klussier at masslnc.org>

diff --git a/Open-ILS/web/js/ui/default/staff/cat/volcopy/app.js b/Open-ILS/web/js/ui/default/staff/cat/volcopy/app.js
index df84424..04b1963 100644
--- a/Open-ILS/web/js/ui/default/staff/cat/volcopy/app.js
+++ b/Open-ILS/web/js/ui/default/staff/cat/volcopy/app.js
@@ -151,7 +151,7 @@ function(egCore , $q) {
         );
     };
 
-    service.get_locations = function(orgs) {
+    service.get_locations_by_org = function(orgs) {
         return egCore.pcrud.search('acpl',
             {owning_lib : orgs, deleted : 'f'},
             {
@@ -1623,17 +1623,17 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore ,
             }
 
         }).then( function() {
-            $scope.data = itemSvc;
-            $scope.workingGridDataProvider.refresh();
 
             return itemSvc.fetch_locations(
-                $scope.data.copies.map(function(cp){
+                itemSvc.copies.map(function(cp){
                     return cp.location();
                 }).filter(function(e,i,a){
                     return a.lastIndexOf(e) === i;
                 })
             ).then(function(list){
+                $scope.data = itemSvc;
                 $scope.location_list = list;
+                $scope.workingGridDataProvider.refresh();
             });
 
         });
@@ -1807,45 +1807,45 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore ,
                 if ($scope.location_orgs.toString() != final_orgs.toString()) {
                     $scope.location_orgs = final_orgs;
                     if ($scope.location_orgs.length) {
-                        itemSvc.get_locations($scope.location_orgs).then(function(list){
+                        itemSvc.get_locations_by_org($scope.location_orgs).then(function(list){
                             angular.forEach(list, function(l) {
                                 $scope.location_cache[ ''+l.id() ] = l;
                             });
                             $scope.location_list = list;
-                        });
-
-                        $scope.statcat_filter_list = [];
-                        angular.forEach($scope.location_orgs, function (o) {
-                            $scope.statcat_filter_list.push(egCore.org.get(o));
-                        });
+                        }).then(function() {
+                            $scope.statcat_filter_list = [];
+                            angular.forEach($scope.location_orgs, function (o) {
+                                $scope.statcat_filter_list.push(egCore.org.get(o));
+                            });
 
-                        itemSvc.get_statcats($scope.location_orgs).then(function(list){
-                            $scope.statcats = list;
-                            angular.forEach($scope.statcats, function (s) {
+                            itemSvc.get_statcats($scope.location_orgs).then(function(list){
+                                $scope.statcats = list;
+                                angular.forEach($scope.statcats, function (s) {
 
-                                if (!$scope.working)
-                                    $scope.working = { statcats_multi: {}, statcats: {}, statcat_filter: undefined};
-                                if (!$scope.working.statcats_multi)
-                                    $scope.working.statcats_multi = {};
-                                if (!$scope.working.statcats)
-                                    $scope.working.statcats = {};
+                                    if (!$scope.working)
+                                        $scope.working = { statcats_multi: {}, statcats: {}, statcat_filter: undefined};
+                                    if (!$scope.working.statcats_multi)
+                                        $scope.working.statcats_multi = {};
+                                    if (!$scope.working.statcats)
+                                        $scope.working.statcats = {};
 
-                                if (!$scope.in_item_select) {
-                                    $scope.working.statcats[s.id()] = undefined;
-                                }
-                                createStatcatUpdateWatcher(s.id());
+                                    if (!$scope.in_item_select) {
+                                        $scope.working.statcats[s.id()] = undefined;
+                                    }
+                                    createStatcatUpdateWatcher(s.id());
+                                });
+                                $scope.in_item_select = false;
+                                // do a refresh here to work around a race
+                                // condition that can result in stat cats
+                                // not being selected.
+                                $scope.workingGridDataProvider.refresh();
                             });
-                            $scope.in_item_select = false;
-                            // do a refresh here to work around a race
-                            // condition that can result in stat cats
-                            // not being selected.
-                            $scope.workingGridDataProvider.refresh();
                         });
                     }
                 }
+            } else {
+                $scope.workingGridDataProvider.refresh();
             }
-
-            $scope.workingGridDataProvider.refresh();
         });
 
         $scope.statcat_visible = function (sc_owner) {
@@ -2530,7 +2530,7 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore ,
                 $scope.location_cache = {};
             
                 $scope.location_list = [];
-                itemSvc.get_locations(
+                itemSvc.get_locations_by_org(
                     egCore.org.fullPath( egCore.auth.user().ws_ou(), true )
                 ).then(function(list){
                     $scope.location_list = list;

commit 443ed531a19fdea611a01f931252316cffbbce47
Author: Mike Rylander <mrylander at gmail.com>
Date:   Mon Jul 9 16:31:50 2018 -0400

    LP#1732761: Fetch locations immediately for display
    
    This commit closes a race condition where location labels cannot be rendered
    for the "multiple locations" widget because fetching them takes longer than
    the initial render of the attribute editor.
    
    Signed-off-by: Mike Rylander <mrylander at gmail.com>
    Signed-off-by: Kathy Lussier <klussier at masslnc.org>

diff --git a/Open-ILS/web/js/ui/default/staff/cat/volcopy/app.js b/Open-ILS/web/js/ui/default/staff/cat/volcopy/app.js
index 2efb600..df84424 100644
--- a/Open-ILS/web/js/ui/default/staff/cat/volcopy/app.js
+++ b/Open-ILS/web/js/ui/default/staff/cat/volcopy/app.js
@@ -165,6 +165,20 @@ function(egCore , $q) {
         );
     };
 
+    service.fetch_locations = function(locs) {
+        return egCore.pcrud.search('acpl',
+            {id : locs},
+            {
+                flesh : 1,
+                flesh_fields : {
+                    acpl : ['owning_lib']
+                },
+                order_by : { acpl : 'name' }
+            },
+            {atomic : true}
+        );
+    };
+
     service.get_suffixes = function(org) {
         return egCore.pcrud.search('acns',
             {owning_lib : egCore.org.fullPath(org, true)},
@@ -1611,6 +1625,17 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore ,
         }).then( function() {
             $scope.data = itemSvc;
             $scope.workingGridDataProvider.refresh();
+
+            return itemSvc.fetch_locations(
+                $scope.data.copies.map(function(cp){
+                    return cp.location();
+                }).filter(function(e,i,a){
+                    return a.lastIndexOf(e) === i;
+                })
+            ).then(function(list){
+                $scope.location_list = list;
+            });
+
         });
 
         $scope.can_save = false;
@@ -1852,9 +1877,6 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore ,
         });
 
         $scope.location_list = [];
-        itemSvc.get_locations().then(function(list){
-            $scope.location_list = list;
-        });
         createSimpleUpdateWatcher('location');
 
         $scope.status_list = [];

commit b98f8efea5a1937704c94b3de534d9028fd09d40
Author: Mike Rylander <mrylander at gmail.com>
Date:   Tue Jul 3 16:57:27 2018 -0400

    LP#1732761: Batch item edit and multiple values per field
    
    Previous to this commit, the display of multiple different values for a field
    in the item attribute editor was simply to display no value.  Here we add a UI
    component that presents the list of unique values, the number of selected
    copies that use each value, and the ability to select just those copies using
    a particular value by clicking on the desired value.
    
    Signed-off-by: Mike Rylander <mrylander at gmail.com>
    Signed-off-by: Kathy Lussier <klussier at masslnc.org>
    
    Conflicts:
    	Open-ILS/src/templates/staff/cat/volcopy/index.tt2
    	Open-ILS/src/templates/staff/cat/volcopy/t_attr_edit.tt2

diff --git a/Open-ILS/src/templates/staff/cat/volcopy/index.tt2 b/Open-ILS/src/templates/staff/cat/volcopy/index.tt2
index 385c904..d50b450 100644
--- a/Open-ILS/src/templates/staff/cat/volcopy/index.tt2
+++ b/Open-ILS/src/templates/staff/cat/volcopy/index.tt2
@@ -15,6 +15,14 @@
 angular.module('egCoreMod').run(['egStrings', function(s) {
     s.VOL_COPY_TEMPLATE_SUCCESS_SAVE = "[% l('Saved holdings template(s)') %]";
     s.VOL_COPY_TEMPLATE_SUCCESS_DELETE = "[% l('Deleted holdings template') %]";
+    s.SHORT = "[% l('Short') %]";
+    s.LOW = "[% l('Low') %]";
+    s.NORMAL = "[% l('Normal') %]";
+    s.EXTENDED = "[% l('Extended') %]";
+    s.HIGH = "[% l('High') %]";
+    s.UNSET = "[% l('UNSET') %]";
+    s.YES = "[% l('Yes') %]";
+    s.NO = "[% l('No') %]";
     [%# Note the "~" characters escape the gettext brackets %]
     s.COPY_NOTE_INITIALS = 
       "[% l('[_1] ~[ [_2] @ [_3] ~]', '{{value}}', '{{initials}}', '{{ws_ou}}') %]"
diff --git a/Open-ILS/src/templates/staff/cat/volcopy/t_attr_edit.tt2 b/Open-ILS/src/templates/staff/cat/volcopy/t_attr_edit.tt2
index ffbaeba..b133c7a 100644
--- a/Open-ILS/src/templates/staff/cat/volcopy/t_attr_edit.tt2
+++ b/Open-ILS/src/templates/staff/cat/volcopy/t_attr_edit.tt2
@@ -120,12 +120,18 @@
                             </label>
                         </div>
                     </div>
+                    <div class="container" ng-show="working.MultiMap.circulate.length > 1 && working.circulate === undefined">
+                        <eg-list-counts label="[% l('Multiple values') %]" list="working.MultiMap.circulate" render="labelYesNo" on-select="select_by_circulate"></eg-list-counts>
+                    </div>
                 </div>
                 <div class="col-md-6" ng-class="{'bg-success': working.status !== undefined}">
                     <select class="form-control"
                         ng-disabled="!defaults.attributes.status" ng-model="working.status"
                         ng-options="s.id() as s.name() disable when magic_status_list.indexOf(s.id(),0) > -1 for s in status_list">
                     </select>
+                    <div class="container" ng-show="working.MultiMap.status.length > 1 && working.status === undefined">
+                        <eg-list-counts label="[% l('Multiple statuses') %]" list="working.MultiMap.status" render="statusName" on-select="select_by_status"></eg-list-counts>
+                    </div>
                 </div>
             </div>
 
@@ -149,6 +155,9 @@
                         label="[% l('(Unset)') %]"
                         disable-test="cant_have_vols"
                     ></eg-org-selector>
+                    <div class="container" ng-show="working.MultiMap.circ_lib.length > 1 && working.circ_lib === undefined">
+                        <eg-list-counts label="[% l('Multiple values') %]" list="working.MultiMap.circ_lib" render="orgShortname" on-select="select_by_circ_lib"></eg-list-counts>
+                    </div>
                 </div>
                 <div class="col-md-6" ng-class="{'bg-success': working.ref !== undefined}">
                     <div class="row">
@@ -165,6 +174,9 @@
                             </label>
                         </div>
                     </div>
+                    <div class="container" ng-show="working.MultiMap.ref.length > 1 && working.ref === undefined">
+                        <eg-list-counts label="[% l('Multiple values') %]" list="working.MultiMap.ref" render="labelYesNo" on-select="select_by_ref"></eg-list-counts>
+                    </div>
                 </div>
             </div>
 
@@ -185,6 +197,9 @@
                         ng-disabled="!defaults.attributes.location" ng-model="working.location"
                         ng-options="l.id() as i18n.ou_qualified_location_name(l) for l in location_list"
                     ></select>
+                    <div class="container" ng-show="working.MultiMap.location.length > 1 && working.location === undefined">
+                        <eg-list-counts label="[% l('Multiple locations') %]" list="working.MultiMap.location" render="locationName" on-select="select_by_location"></eg-list-counts>
+                    </div>
                 </div>
                 <div class="col-md-6" ng-class="{'bg-success': working.opac_visible !== undefined}">
                     <div class="row">
@@ -201,6 +216,9 @@
                             </label>
                         </div>
                     </div>
+                    <div class="container" ng-show="working.MultiMap.opac_visible.length > 1 && working.opac_visible === undefined">
+                        <eg-list-counts label="[% l('Multiple values') %]" list="working.MultiMap.opac_visible" render="labelYesNo" on-select="select_by_opac_visible"></eg-list-counts>
+                    </div>
                 </div>
             </div>
 
@@ -223,9 +241,15 @@
                     >
                         <option value="">[% l('<NONE>') %]</option>
                     </select>
+                    <div class="container" ng-show="working.MultiMap.circ_modifier.length > 1 && working.circ_modifier === undefined">
+                        <eg-list-counts label="[% l('Multiple modifiers') %]" list="working.MultiMap.circ_modifier" render="circmodName" on-select="select_by_circ_modifier"></eg-list-counts>
+                    </div>
                 </div>
                 <div class="col-md-6" ng-class="{'bg-success': working.price !== undefined}">
                     <input class="form-control" ng-disabled="!defaults.attributes.price" str-to-float ng-model="working.price" type="number" step="0.01"/>
+                    <div class="container" ng-show="working.MultiMap.price.length > 1 && working.price === undefined">
+                        <eg-list-counts label="[% l('Multiple prices') %]" list="working.MultiMap.price" on-select="select_by_price"></eg-list-counts>
+                    </div>
                 </div>
             </div>
 
@@ -247,9 +271,15 @@
                         <option value="2" selected>[% l('Normal') %]</option>
                         <option value="3">[% l('Extended') %]</option>
                     </select>
+                    <div class="container" ng-show="working.MultiMap.loan_duration.length > 1 && working.loan_duration === undefined">
+                        <eg-list-counts label="[% l('Multiple durations') %]" list="working.MultiMap.loan_duration" render="durationLabel" on-select="select_by_loan_duration"></eg-list-counts>
+                    </div>
                 </div>
                 <div class="col-md-6" ng-class="{'bg-success': working.cost !== undefined}">
                     <input class="form-control" ng-disabled="!defaults.attributes.cost" str-to-float ng-model="working.cost" type="number" step="0.01"/>
+                    <div class="container" ng-show="working.MultiMap.cost.length > 1 && working.cost === undefined">
+                        <eg-list-counts label="[% l('Multiple costs') %]" list="working.MultiMap.cost" on-select="select_by_cost"></eg-list-counts>
+                    </div>
                 </div>
             </div>
 
@@ -271,6 +301,9 @@
                         ng-options="t.code() as t.value() for t in circ_type_list">
                       <option value="">[% l('<NONE>') %]</option>
                     </select>
+                    <div class="container" ng-show="working.MultiMap.circ_as_type.length > 1 && working.circ_as_type === undefined">
+                        <eg-list-counts label="[% l('Multiple types') %]" list="working.MultiMap.circ_as_type" render="circTypeValue" on-select="select_by_circ_as_type"></eg-list-counts>
+                    </div>
                 </div>
                 <div class="col-md-6" ng-class="{'bg-success': working.deposit !== undefined}">
                     <div class="row">
@@ -287,6 +320,9 @@
                             </label>
                         </div>
                     </div>
+                    <div class="container" ng-show="working.MultiMap.deposit.length > 1 && working.deposit === undefined">
+                        <eg-list-counts label="[% l('Multiple values') %]" list="working.MultiMap.deposit" render="labelYesNo" on-select="select_by_deposit"></eg-list-counts>
+                    </div>
                 </div>
             </div>
 
@@ -317,9 +353,15 @@
                             </label>
                         </div>
                     </div>
+                    <div class="container" ng-show="working.MultiMap.holdable.length > 1 && working.holdable === undefined">
+                        <eg-list-counts label="[% l('Multiple values') %]" list="working.MultiMap.holdable" render="labelYesNo" on-select="select_by_holdable"></eg-list-counts>
+                    </div>
                 </div>
                 <div class="col-md-6" ng-class="{'bg-success': working.deposit_amount !== undefined}">
                     <input class="form-control" ng-disabled="!defaults.attributes.deposit_amount" str-to-float ng-model="working.deposit_amount" type="number" step="0.01"/>
+                    <div class="container" ng-show="working.MultiMap.deposit_amount.length > 1 && working.deposit_amount === undefined">
+                        <eg-list-counts label="[% l('Multiple amounts') %]" list="working.MultiMap.deposit_amount" on-select="select_by_deposit_amount"></eg-list-counts>
+                    </div>
                 </div>
             </div>
 
@@ -341,6 +383,9 @@
                         ng-options="a.id() as a.name() for a in age_protect_list">
                       <option value="">[% l('<NONE>') %]</option>
                     </select>
+                    <div class="container" ng-show="working.MultiMap.age_protect.length > 1 && working.age_protect === undefined">
+                        <eg-list-counts label="[% l('Multiple values') %]" list="working.MultiMap.age_protect" render="ageprotectName" on-select="select_by_age_protect"></eg-list-counts>
+                    </div>
                 </div>
                 <div class="col-md-6" ng-class="{'bg-success': working.mint_condition !== undefined}">
                     <div class="row">
@@ -357,6 +402,9 @@
                             </label>
                         </div>
                     </div>
+                    <div class="container" ng-show="working.MultiMap.mint_condition.length > 1 && working.mint_condition === undefined">
+                        <eg-list-counts label="[% l('Multiple values') %]" list="working.MultiMap.mint_condition" render="labelYesNo" on-select="select_by_mint_condition"></eg-list-counts>
+                    </div>
                 </div>
             </div>
 
@@ -375,6 +423,9 @@
                         <option value="2" selected>[% l('Normal') %]</option>
                         <option value="3">[% l('High') %]</option>
                     </select>
+                    <div class="container" ng-show="working.MultiMap.fine_level.length > 1 && working.fine_level === undefined">
+                        <eg-list-counts label="[% l('Multiple levels') %]" list="working.MultiMap.fine_level" render="fineLabel" on-select="select_by_fine_level"></eg-list-counts>
+                    </div>
                 </div>
                 <div class="col-md-6">
                     <button
@@ -409,6 +460,9 @@
                         ng-options="a.id() as a.name() for a in floating_list">
                       <option value="">[% l('<NONE>') %]</option>
                     </select>
+                    <div class="container" ng-show="working.MultiMap.floating.length > 1 && working.floating === undefined">
+                        <eg-list-counts label="[% l('Multiple values') %]" list="working.MultiMap.floating" render="floatingName" on-select="select_by_floating"></eg-list-counts>
+                    </div>
                 </div>
                 <div class="col-md-6">
                     <button
diff --git a/Open-ILS/src/templates/staff/share/t_listcounts.tt2 b/Open-ILS/src/templates/staff/share/t_listcounts.tt2
new file mode 100644
index 0000000..e32d061
--- /dev/null
+++ b/Open-ILS/src/templates/staff/share/t_listcounts.tt2
@@ -0,0 +1,11 @@
+<div class="btn-group" uib-dropdown>
+    <button type="button" class="btn btn-default" uib-dropdown-toggle>
+        {{label}}
+        <span class="caret"></span>
+    </button>
+    <ul uib-dropdown-menu class="uib-dropdown-menu">
+        <li ng-repeat="item in count_hash">
+            <a href ng-click="selectValue(item.original)">{{item.value}} ({{item.count}})</a>
+        </li>
+    </ul>
+</div>
diff --git a/Open-ILS/web/js/ui/default/staff/cat/volcopy/app.js b/Open-ILS/web/js/ui/default/staff/cat/volcopy/app.js
index ec42207..2efb600 100644
--- a/Open-ILS/web/js/ui/default/staff/cat/volcopy/app.js
+++ b/Open-ILS/web/js/ui/default/staff/cat/volcopy/app.js
@@ -1121,6 +1121,7 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore ,
             var newval = $scope.working[field];
 
             if (typeof newval != 'undefined') {
+                delete $scope.working.MultiMap[field];
                 if (angular.isObject(newval)) { // we'll use the pkey
                     if (newval.id) newval = newval.id();
                     else if (newval.code) newval = newval.code();
@@ -1152,6 +1153,7 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore ,
     }
 
     $scope.working = {
+        MultiMap: {},
         statcats: {},
         statcats_multi: {},
         statcat_filter: undefined
@@ -1312,6 +1314,7 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore ,
                     });
                 }
             });
+            delete $scope.working.MultiMap[k];
             egCore.hatch.setItem('cat.copy.last_template', n);
         }
 
@@ -1395,6 +1398,87 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore ,
         $scope.add_vols_copies = false;
         $scope.is_fast_add = false;
 
+        // Generate some functions for selecting items by column value in the working grid
+        angular.forEach(
+            ['circulate','status','circ_lib','ref','location','opac_visible','circ_modifier','price',
+             'loan_duration','cost','circ_as_type','deposit','holdable','deposit_amount','age_protect',
+             'mint_condition','fine_level','floating'],
+            function (field) {
+                $scope['select_by_' + field] = function (x) {
+                    $scope.workingGridControls.selectItemsByValue(field,x);
+                }
+            }
+        );
+
+        var truthy = /^t|1/;
+        $scope.labelYesNo = function (x) {
+            return truthy.test(x) ? egCore.strings.YES : egCore.strings.NO;
+        }
+
+        $scope.orgShortname = function (x) {
+            return egCore.org.get(x).shortname();
+        }
+
+        $scope.statusName = function (x) {
+            var s = $scope.status_list.filter(function(y) {
+                return y.id() == x;
+            });
+
+            return s[0].name();
+        }
+
+        $scope.locationName = function (x) {
+            var s = $scope.location_list.filter(function(y) {
+                return y.id() == x;
+            });
+
+            return $scope.i18n.ou_qualified_location_name(s[0]);
+        }
+
+        $scope.durationLabel = function (x) {
+            return [egCore.strings.SHORT, egCore.strings.NORMAL, egCore.strings.EXTENDED][-1 + x]
+        }
+
+        $scope.fineLabel = function (x) {
+            return [egCore.strings.LOW, egCore.strings.NORMAL, egCore.strings.HIGH][-1 + x]
+        }
+
+        $scope.circTypeValue = function (x) {
+            if (x === null) return egCore.strings.UNSET;
+            var s = $scope.circ_type_list.filter(function(y) {
+                return y.code() == x;
+            });
+
+            return s[0].value();
+        }
+
+        $scope.ageprotectName = function (x) {
+            if (x === null) return egCore.strings.UNSET;
+            var s = $scope.age_protect_list.filter(function(y) {
+                return y.id() == x;
+            });
+
+            return s[0].name();
+        }
+
+        $scope.floatingName = function (x) {
+            if (x === null) return egCore.strings.UNSET;
+            var s = $scope.floating_list.filter(function(y) {
+                return y.id() == x;
+            });
+
+            return s[0].name();
+        }
+
+        $scope.circmodName = function (x) {
+            if (x === null) return egCore.strings.UNSET;
+            var s = $scope.circ_modifier_list.filter(function(y) {
+                return y.code() == x;
+            });
+
+            return s[0].name();
+        }
+
         egNet.request(
             'open-ils.actor',
             'open-ils.actor.anon_cache.get_value',
@@ -1600,6 +1684,7 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore ,
                 angular.forEach(Object.keys($scope.defaults.attributes), function (attr) {
 
                     var value_hash = {};
+                    var value_list = [];
                     angular.forEach(item_list, function (item) {
                         if (item[attr]) {
                             var v = item[attr]()
@@ -1607,10 +1692,13 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore ,
                                 if (v.id) v = v.id();
                                 else if (v.code) v = v.code();
                             }
+                            value_list.push(v);
                             value_hash[v] = 1;
                         }
                     });
 
+                    $scope.working.MultiMap[attr] = value_list;
+
                     if (Object.keys(value_hash).length == 1) {
                         if (attr == 'circ_lib') {
                             $scope.working[attr] = egCore.org.get(item_list[0][attr]());
@@ -2401,6 +2489,7 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore ,
 
                 $scope.clearWorking = function () {
                     angular.forEach($scope.working, function (v,k,o) {
+                        $scope.working.MultiMap[k] = [];
                         if (!angular.isObject(v)) {
                             if (typeof v != 'undefined')
                                 $scope.working[k] = undefined;
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 47690ca..a1f8d5f 100644
--- a/Open-ILS/web/js/ui/default/staff/services/grid.js
+++ b/Open-ILS/web/js/ui/default/staff/services/grid.js
@@ -283,6 +283,10 @@ angular.module('egGridMod',
                     return grid.getSelectedItems()
                 }
 
+                controls.selectItemsByValue = function(c,v) {
+                    return grid.selectItemsByValue(c,v)
+                }
+
                 controls.allItems = function() {
                     return $scope.items;
                 }
@@ -743,6 +747,21 @@ angular.module('egGridMod',
                 $scope.selected[index] = true;
             }
 
+            // selects items by a column value, first clearing selected list.
+            // we overwrite the object so that we can watch $scope.selected
+            grid.selectItemsByValue = function(column, value) {
+                $scope.selected = {};
+                angular.forEach($scope.items, function(item) {
+                    var col_value;
+                    if (angular.isFunction(item[column]))
+                        col_value = item[column]();
+                    else
+                        col_value = item[column];
+
+                    if (value == col_value) $scope.selected[grid.indexValue(item)] = true
+                }); 
+            }
+
             // selects or deselects an item, without affecting the others.
             // returns true if the item is selected; false if de-selected.
             // we overwrite the object so that we can watch $scope.selected
diff --git a/Open-ILS/web/js/ui/default/staff/services/ui.js b/Open-ILS/web/js/ui/default/staff/services/ui.js
index 8f38e1c..ed5f84f 100644
--- a/Open-ILS/web/js/ui/default/staff/services/ui.js
+++ b/Open-ILS/web/js/ui/default/staff/services/ui.js
@@ -1003,6 +1003,50 @@ function($uibModal , $interpolate , egCore) {
     };
 })
 
+.directive('egListCounts', function() {
+    return {
+        restrict: 'E',
+        replace: true,
+        scope: {
+            label: "@",
+            list: "=", // list of things
+            render: "=", // function to turn thing into string; default to stringification
+            onSelect: "=" // function to fire when option selected. passed one copy of the selected value
+        },
+        templateUrl: './share/t_listcounts',
+        controller: ['$scope','$timeout',
+            function( $scope , $timeout ) {
+
+                $scope.isopen = false;
+                $scope.count_hash = {};
+
+                $scope.renderer = $scope.render ? $scope.render : function (x) { return ""+x };
+
+                $scope.$watchCollection('list',function() {
+                    $scope.count_hash = {};
+                    angular.forEach($scope.list, function (item) {
+                        var str = $scope.renderer(item);
+                        if (!$scope.count_hash[str]) {
+                            $scope.count_hash[str] = {
+                                count : 1,
+                                value : str,
+                                original : item
+                            };
+                        } else {
+                            $scope.count_hash[str].count++;
+                        }
+                    });
+                });
+
+                $scope.selectValue = function (item) {
+                    if ($scope.onSelect) $scope.onSelect(item);
+                }
+
+            }
+        ]
+    };
+})
+
 /**
  * Nested org unit selector modeled as a Bootstrap dropdown button.
  */

-----------------------------------------------------------------------

Summary of changes:
 Open-ILS/src/templates/staff/cat/volcopy/index.tt2 |    8 +
 .../templates/staff/cat/volcopy/t_attr_edit.tt2    |   54 ++++++
 .../src/templates/staff/share/t_listcounts.tt2     |   11 ++
 .../web/js/ui/default/staff/cat/volcopy/app.js     |  179 ++++++++++++++++----
 Open-ILS/web/js/ui/default/staff/services/grid.js  |   19 ++
 Open-ILS/web/js/ui/default/staff/services/ui.js    |   44 +++++
 6 files changed, 281 insertions(+), 34 deletions(-)
 create mode 100644 Open-ILS/src/templates/staff/share/t_listcounts.tt2


hooks/post-receive
-- 
Evergreen ILS


More information about the open-ils-commits mailing list