LP#1673857: interface for applying tags from copy buckets
authorGalen Charlton <gmc@equinoxinitiative.org>
Fri, 31 Mar 2017 22:31:52 +0000 (18:31 -0400)
committerGalen Charlton <gmc@equinoxinitiative.org>
Mon, 24 Jul 2017 15:29:13 +0000 (11:29 -0400)
The copy buckets interface now includes an 'Apply Tags'
action that can be used to map tags to a set of selected
copies. Note that interface cannot be used to remove
tag mappings; the volume/copy editor is needed to do that.

Signed-off-by: Galen Charlton <gmc@equinoxinitiative.org>
Signed-off-by: Josh Stompro <stomproj@larl.org>
Signed-off-by: Galen Charlton <gmc@equinoxinitiative.org>
Open-ILS/src/templates/staff/cat/bucket/copy/t_apply_tags.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/cat/bucket/copy/t_view.tt2
Open-ILS/web/js/ui/default/staff/cat/bucket/copy/app.js

diff --git a/Open-ILS/src/templates/staff/cat/bucket/copy/t_apply_tags.tt2 b/Open-ILS/src/templates/staff/cat/bucket/copy/t_apply_tags.tt2
new file mode 100644 (file)
index 0000000..00d6db7
--- /dev/null
@@ -0,0 +1,39 @@
+<form ng-submit="ok(note)" role="form">
+    <div class="modal-header">
+      <button type="button" class="close" ng-click="cancel()" 
+        aria-hidden="true">&times;</button>
+      <h4 class="modal-title">[% l('Apply Copy Tags') %]</h4>
+    </div>
+    <div class="modal-body">
+      <ul>
+        <li ng-repeat="map in tag_map" ng-show="!map.isdeleted()">
+            <span class="copy_tag_label">{{map.tag().label()}}</span>
+            <button type="button" ng-click="map.isdeleted(1)" class="btn btn-xs btn-warning">[% ('Remove') %]</button>
+        </li>
+      </ul>
+      <div class="row">
+        <div class="col-md-12 form-inline">
+          <div class="form-group">
+            <label for="tagType">[% l('Tag Type') %]</label>
+            <select class="form-control" name="tagType" ng-model="tag_type"
+                    ng-options="t.code() as t.label() for t in tag_types"></select>
+          </div>
+          <div class="form-group">
+            <label for="tagLabel">[% l('Tag') %]</label>
+            <input name="tabLabel" type="text" ng-model="selectedLabel" placeholder="[% l('Enter tag label...') %]"
+                uib-typeahead="tag for tag in getTags($viewValue)" typeahead-editable="false"
+                class="form-control"></input>
+          </div>
+          <button type="button" class="btn btn-sm btn-default" ng-click="addTag()">[% l('Add Tag') %]</button>
+        </div>
+      </div>
+    </div>
+    <div class="modal-footer">
+      <div class="row">
+        <div class="col-md-12 pull-right">
+          <input type="submit" class="btn btn-primary" value="[% l('OK') %]"/>
+          <button class="btn btn-warning" ng-click="cancel($event)">[% l('Cancel') %]</button>
+        </div>
+      </div>
+    </div>
+</form>
index 655e785..c2daf27 100644 (file)
@@ -20,6 +20,8 @@
     handler="transferCopies"></eg-grid-action>
   <eg-grid-action label="[% l('Delete Selected Copies from Catalog') %]" 
     handler="deleteCopiesFromCatalog"></eg-grid-action>
+  <eg-grid-action label="[% l('Apply Tags') %]" 
+    handler="applyTags"></eg-grid-action>
 
   <eg-grid-field path="id" required hidden></eg-grid-field>
   <eg-grid-field path="call_number.record.id" required hidden></eg-grid-field>
index fc78a77..7eea044 100644 (file)
@@ -656,6 +656,84 @@ function($scope,  $q , $routeParams , $timeout , $window , $uibModal , bucketSvc
         }
     }
 
+    $scope.applyTags = function(copies) {
+        return $uibModal.open({
+            templateUrl: './cat/bucket/copy/t_apply_tags',
+            animation: true,
+            controller:
+                   ['$scope','$uibModalInstance',
+            function($scope , $uibModalInstance) {
+
+                $scope.tag_map = [];
+
+                egCore.pcrud.retrieveAll('cctt', {order_by : { cctt : 'label' }}, {atomic : true}).then(function(list) {
+                    $scope.tag_types = list;
+                    $scope.tag_type = $scope.tag_types[0].code(); // just pick a default
+                });
+
+                $scope.getTags = function(val) {
+                    return egCore.pcrud.search('acpt',
+                        {
+                            owner :  egCore.org.fullPath(egCore.auth.user().ws_ou(), true),
+                            label : { 'startwith' : {
+                                        transform: 'evergreen.lowercase',
+                                        value : [ 'evergreen.lowercase', val ]
+                                    }},
+                            tag_type : $scope.tag_type
+                        },
+                        { order_by : { 'acpt' : ['label'] } }, { atomic: true }
+                    ).then(function(list) {
+                        return list.map(function(item) {
+                            return item.label();
+                        });
+                    });
+                }
+
+                $scope.addTag = function() {
+                    var tagLabel = $scope.selectedLabel;
+                    // clear the typeahead
+                    $scope.selectedLabel = "";
+
+                    egCore.pcrud.search('acpt',
+                        {
+                            owner : egCore.org.fullPath(egCore.auth.user().ws_ou(), true),
+                            label : tagLabel,
+                            tag_type : $scope.tag_type
+                        },
+                        { order_by : { 'acpt' : ['label'] } }, { atomic: true }
+                    ).then(function(list) {
+                        if (list.length > 0) {
+                            var newMap = new egCore.idl.acptcm();
+                            newMap.isnew(1);
+                            newMap.tag(egCore.idl.Clone(list[0]));
+                            $scope.tag_map.push(newMap);
+                        }
+                    });
+                }
+
+                $scope.ok = function() {
+                    var promises = [];
+                    angular.forEach($scope.tag_map, function(map) {
+                        if (map.isdeleted()) return;
+                        angular.forEach(copies, function (cp) {
+                            var m = new egCore.idl.acptcm();
+                            m.isnew(1);
+                            m.copy(cp.id);
+                            m.tag(map.tag().id());
+                            promises.push(egCore.pcrud.create(m));
+                        });
+                    });
+                    return $q.all(promises).then(function(){$uibModalInstance.close()});
+                }
+
+                $scope.cancel = function($event) {
+                    $uibModalInstance.dismiss();
+                    $event.preventDefault();
+                }
+            }]
+        });
+    }
+
     // fetch the bucket;  on error show the not-allowed message
     if ($scope.bucketId) 
         drawBucket()['catch'](function() { $scope.forbidden = true });