webstaff: Z39.50 - more improvements
authorGalen Charlton <gmc@esilibrary.com>
Thu, 23 Jul 2015 17:52:33 +0000 (17:52 +0000)
committerJason Stephenson <jstephenson@mvlc.org>
Wed, 19 Aug 2015 17:39:19 +0000 (13:39 -0400)
* add grid actions
* fix markup
* add view MARC action
* improve name of check for disabling actions that
  require at least one result to be selected
* display cover image on view MARC modal
* add Z39.50 raw search capability
* implement selecting local record for overlay
* implement record overlay with confirm

Signed-off-by: Galen Charlton <gmc@esilibrary.com>
Signed-off-by: Jason Stephenson <jstephenson@mvlc.org>
Open-ILS/src/templates/staff/cat/z3950/t_list.tt2
Open-ILS/src/templates/staff/cat/z3950/t_marc_html.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/cat/z3950/t_overlay.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/cat/z3950/t_raw_search.tt2 [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/cat/services/z3950.js
Open-ILS/web/js/ui/default/staff/cat/z3950/app.js

index 91719d7..23349b9 100644 (file)
 
                 <input type="reset" class="btn btn-primary" ng-click="clearForm()"
                 value="[% l('Clear Form') %]"/>
+                <button class="btn btn-default" ng-click="showRawSearchForm()"
+                        ng-disabled="raw_search_impossible()">
+                    [% l('Raw Search') %]
+                </button>
         </div>
     </form>
 </div>
 
+<div class="text-right" ng-if="local_overlay_target">
+[% l('Record with TCN [_1] marked for overlay.', '{{local_overlay_target}}') %]"
+</div>
+<div class="text-right" ng-if="!local_overlay_target">
+[% l('No record marked for overlay.') %]
+</div>
+
+
 <eg-grid
   id-field="index"
   idl-class="mvr"
   persist-key="cat.z3950_results">
 
   <eg-grid-menu-item handler="showInCatalog" disabled="cant_showInCatalog"
-    label="[% l('Show in Catalog') %]"></eg-grid-menu>
-  <eg-grid-menu-item handler="import" disabled="cant_import"
-    label="[% l('Import') %]"></eg-grid-menu>
-  <eg-grid-menu-item handler="spawn_editor" disabled="cant_import"
-    label="[% l('Edit then Import') %]"></eg-grid-menu>
+    label="[% l('Show in Catalog') %]"></eg-grid-menu-item>
+  <eg-grid-menu-item handler="import" disabled="need_one_selected"
+    label="[% l('Import') %]"></eg-grid-menu-item>
+  <eg-grid-menu-item handler="spawn_editor" disabled="need_one_selected"
+    label="[% l('Edit then Import') %]"></eg-grid-menu-item>
+  <eg-grid-menu-item handler="view_marc" disabled="need_one_selected"
+    label="[% l('View MARC') %]"></eg-grid-menu-item>
+  <eg-grid-menu-item handler="mark_as_overlay_target" disabled="cant_showInCatalog"
+    label="[% l('Mark Local Result As Overlay Target') %]"></eg-grid-menu-item>
+  <eg-grid-menu-item handler="overlay_record" disabled="cant_overlay"
+    label="[% l('Overlay') %]"></eg-grid-menu-item>
+
+  <eg-grid-action handler="showInCatalog" disabled="cant_showInCatalog"
+    label="[% l('Show in Catalog') %]"></eg-grid-action>
+  <eg-grid-action handler="import" disabled="need_one_selected"
+    label="[% l('Import') %]"></eg-grid-action>
+  <eg-grid-action handler="spawn_editor" disabled="need_one_selected"
+    label="[% l('Edit then Import') %]"></eg-grid-action>
+  <eg-grid-action handler="view_marc" disabled="need_one_selected"
+    label="[% l('View MARC') %]"></eg-grid-action>
+  <eg-grid-action handler="mark_as_overlay_target" disabled="cant_showInCatalog"
+    label="[% l('Mark Local Result As Overlay Target') %]"></eg-grid-action>
+  <eg-grid-action handler="overlay_record" disabled="cant_overlay"
+    label="[% l('Overlay') %]"></eg-grid-action>
 
     <!-- 
       FIXME: it would be nice to make this column link
diff --git a/Open-ILS/src/templates/staff/cat/z3950/t_marc_html.tt2 b/Open-ILS/src/templates/staff/cat/z3950/t_marc_html.tt2
new file mode 100644 (file)
index 0000000..a305172
--- /dev/null
@@ -0,0 +1,14 @@
+<div>
+  <div class="modal-header">
+    <button type="button" class="close"
+      ng-click="cancel()" aria-hidden="true">&times;</button>
+    <h4 class="modal-title">[% l('View MARC') %]</h4>
+  </div>
+  <div class="modal-body">
+    <img ng-src="/opac/extras/ac/jacket/large/{{isbn}}"></img>
+    <eg-record-html marc-xml="{{marc_xml}}" />
+  </div>
+  <div class="modal-footer">
+    <button class="btn btn-warning" ng-click="cancel()">[% l('Cancel') %]</button>
+  </div>
+</div>
diff --git a/Open-ILS/src/templates/staff/cat/z3950/t_overlay.tt2 b/Open-ILS/src/templates/staff/cat/z3950/t_overlay.tt2
new file mode 100644 (file)
index 0000000..c7290b1
--- /dev/null
@@ -0,0 +1,26 @@
+<form class="form-validated" novalidate name="form" ng-submit="ok(args)">
+  <div>
+    <div class="modal-header">
+      <button type="button" class="close"
+        ng-click="cancel()" aria-hidden="true">&times;</button>
+      <h4 class="modal-title">[% l('Overlay record?') %]</h4>
+    </div>
+    <div class="modal-body">
+        <div class="row">
+            <div class="col-xs-6">
+                <div>[% l('Replace TCN [_1] ...', '{{overlay_target}}') %]</div>
+                <eg-record-html record-id="overlay_target" />
+            </div>
+            <div class="col-xs-6">
+                <div>[% l('With this?') %]</div>
+                <eg-record-html marc-xml="{{marc_xml}}" />
+            </div>
+        </div>
+    </div>
+    <div class="modal-footer">
+      <input type="submit" ng-disabled="form.$invalid"
+          class="btn btn-primary" value="[% l('Overlay') %]"/>
+      <button class="btn btn-warning" ng-click="cancel()">[% l('Cancel') %]</button>
+    </div>
+  </div>
+</form>
diff --git a/Open-ILS/src/templates/staff/cat/z3950/t_raw_search.tt2 b/Open-ILS/src/templates/staff/cat/z3950/t_raw_search.tt2
new file mode 100644 (file)
index 0000000..3ce559c
--- /dev/null
@@ -0,0 +1,22 @@
+<form class="form-validated" novalidate name="form" ng-submit="ok(args)">
+  <div>
+    <div class="modal-header">
+      <button type="button" class="close"
+        ng-click="cancel()" aria-hidden="true">&times;</button>
+      <h4 class="modal-title">[% l('Raw Z39.50 Search') %]</h4>
+    </div>
+    <div class="modal-body">
+      <div class="alert alert-warning">[% l('This is not a simple keyword search.') %]</div>
+      <div class="form-group">
+        <label for="raw-search-string">[% l('Raw Z39.50 PQN search string') %]</label>
+        <input type="text" class="form-control" focus-me='focusMe' required
+          id="raw-seasrch-string" ng-model="args.raw_search" />
+      </div>
+    </div>
+    <div class="modal-footer">
+      <input type="submit" ng-disabled="form.$invalid"
+          class="btn btn-primary" value="[% l('Search') %]"/>
+      <button class="btn btn-warning" ng-click="cancel()">[% l('Cancel') %]</button>
+    </div>
+  </div>
+</form>
index 4ef7e70..45969be 100644 (file)
@@ -5,7 +5,8 @@ function($q,   egCore,   egAuth) {
     
     var service = {
         targets : [ ],
-        searchFields : { }
+        searchFields : { },
+        raw_search : ''
     };
     
     service.loadTargets = function() {
@@ -88,13 +89,34 @@ function($q,   egCore,   egAuth) {
                 query.password.push(target.password);
             }
         });
-        angular.forEach(service.searchFields, function(value, key) {
-            if (value.query && value.query.trim()) {
-                query.search[key] = value.query.trim();
+        if (service.raw_search) {
+            query.raw_search = service.raw_search;
+        } else {
+            angular.forEach(service.searchFields, function(value, key) {
+                if (value.query && value.query.trim()) {
+                    query.search[key] = value.query.trim();
+                }
+            });
+        }
+        return query;
+    }
+
+    // raw search can be done only if exactly one
+    // (real) Z39.50 target is selected
+    service.rawSearchImpossible = function() {
+        var z_selected = 0;
+        for (var i in service.targets) {
+            if (service.targets[i].code == 'native-evergreen-catalog') {
+                if (service.targets[i].selected) return true;
+            } else {
+                if (service.targets[i].selected) z_selected++;
             }
-        });
+        }
+        return !(z_selected == 1);
+    }
 
-        return query;
+    service.setRawSearch = function(raw_search) {
+        service.raw_search = raw_search;
     }
 
     return service;
index d08946a..ffc0866 100644 (file)
@@ -39,17 +39,30 @@ function($scope , $q , $location , $timeout , $window,  egCore , egGridDataProvi
         var deferred = $q.defer();
 
         var query = egZ3950TargetSvc.currentQuery();
-        if (Object.keys(query.search).length == 0) {
+        if (!query.raw_search && Object.keys(query.search).length == 0) {
             return $q.when();
         }
 
+        var method = query.raw_search ?
+                       'open-ils.search.z3950.search_service' :
+                       'open-ils.search.z3950.search_class';
+
+        if (query.raw_search) {
+            query.query = query.raw_search;
+            delete query['search'];
+            delete query['raw_search'];
+            query.service = query.service[0];
+            query.username = query.username[0];
+            query.password = query.password[0];
+        }
+
         query['limit'] = count;
         query['offset'] = offset;
 
         var resultIndex = offset;
         egCore.net.request(
             'open-ils.search',
-            'open-ils.search.z3950.search_class',
+            method,
             egCore.auth.token(),
             query
         ).then(
@@ -86,6 +99,28 @@ function($scope , $q , $location , $timeout , $window,  egCore , egGridDataProvi
         display_form = !display_form;
     }
 
+    $scope.raw_search_impossible = function() {
+        return egZ3950TargetSvc.rawSearchImpossible();
+    }
+    $scope.showRawSearchForm = function() {
+        $modal.open({
+            templateUrl: './cat/z3950/t_raw_search',
+            size: 'md',
+            controller:
+                ['$scope', '$modalInstance', function($scope, $modalInstance) {
+                egZ3950TargetSvc.setRawSearch('');
+                $scope.focusMe = true;
+                $scope.ok = function(args) { $modalInstance.close(args) }
+                $scope.cancel = function () { $modalInstance.dismiss() }
+            }]
+        }).result.then(function (args) {
+            if (!args || !args.raw_search) return;
+            $scope.clearForm();
+            egZ3950TargetSvc.setRawSearch(args.raw_search);
+            $scope.z3950SearchGridProvider.refresh();
+        });
+    }
+
     $scope.showInCatalog = function() {
         var items = $scope.gridControls.selectedItems();
         // relying on cant_showInCatalog to protect us
@@ -100,6 +135,26 @@ function($scope , $q , $location , $timeout , $window,  egCore , egGridDataProvi
         return true;
     };
 
+    $scope.local_overlay_target = 0;
+    $scope.mark_as_overlay_target = function() {
+        var items = $scope.gridControls.selectedItems();
+        if ($scope.local_overlay_target == items[0].tcn()) {
+            $scope.local_overlay_target = 0;
+        } else {
+            $scope.local_overlay_target = items[0].tcn();
+        }
+    }
+    $scope.cant_overlay = function() {
+        if (!$scope.local_overlay_target) return true;
+        var items = $scope.gridControls.selectedItems();
+        if (items.length != 1) return true;
+        if (
+                items[0]['service'] == 'native-evergreen-catalog' &&
+                items[0].tcn() == $scope.local_overlay_target
+           ) return true;
+        return false;
+    }
+
     $scope.import = function() {
         var deferred = $q.defer();
         var items = $scope.gridControls.selectedItems();
@@ -119,7 +174,7 @@ function($scope , $q , $location , $timeout , $window,  egCore , egGridDataProvi
 
         return deferred.promise;
     };
-    $scope.cant_import = function() {
+    $scope.need_one_selected = function() {
         var items = $scope.gridControls.selectedItems();
         if (items.length == 1) return false;
         return true;
@@ -132,7 +187,6 @@ function($scope , $q , $location , $timeout , $window,  egCore , egGridDataProvi
             size: 'lg',
             controller:
                 ['$scope', '$modalInstance', function($scope, $modalInstance) {
-console.debug('calling modal controller');
                 $scope.focusMe = true;
                 $scope.record_id = 0;
                 $scope.dirty_flag = false;
@@ -144,4 +198,52 @@ console.debug('calling modal controller');
             if (!args || !args.name) return;
         });
     }
+
+    $scope.view_marc = function() {
+        var items = $scope.gridControls.selectedItems();
+        $modal.open({
+            templateUrl: './cat/z3950/t_marc_html',
+            size: 'lg',
+            controller:
+                ['$scope', '$modalInstance', function($scope, $modalInstance) {
+                $scope.focusMe = true;
+                $scope.marc_xml = items[0]['marcxml'];
+                $scope.isbn = (items[0].isbn() || '').replace(/ .*/, '');
+                $scope.ok = function(args) { $modalInstance.close(args) }
+                $scope.cancel = function () { $modalInstance.dismiss() }
+            }]
+        }).result.then(function (args) {
+            if (!args || !args.name) return;
+        });
+    }
+
+    $scope.overlay_record = function() {
+        var items = $scope.gridControls.selectedItems();
+        var overlay_target = $scope.local_overlay_target;
+        $modal.open({
+            templateUrl: './cat/z3950/t_overlay',
+            size: 'lg',
+            controller:
+                ['$scope', '$modalInstance', function($scope, $modalInstance) {
+                $scope.focusMe = true;
+                $scope.overlay_target = overlay_target;
+                $scope.marc_xml = items[0]['marcxml'];
+                $scope.ok = function(args) { $modalInstance.close(args) }
+                $scope.cancel = function () { $modalInstance.dismiss() }
+            }]
+        }).result.then(function (args) {
+            egCore.net.request(
+                'open-ils.cat',
+                'open-ils.cat.biblio.record.marc.replace',
+                egCore.auth.token(),
+                overlay_target,
+                items[0]['marcxml']
+                // FIXME and more
+            ).then(
+                function(result) {
+                    console.debug('overlay complete');
+                }
+            );            
+        });
+    }
 }])