From f9e91150fabefd6df8fc06a4bb8181c8818a876a Mon Sep 17 00:00:00 2001 From: senator <senator@dcc99617-32d9-48b4-a31d-7c20da2025e4> Date: Fri, 3 Dec 2010 00:18:30 +0000 Subject: [PATCH] Serials: In Alternate Serial Control interface, under Subscription Details within the Caption and Patterns tab, provide a new feature to import caption and pattern data from existing bib records and/or legacy serials data (serial.record_entry objects) git-svn-id: svn://svn.open-ils.org/ILS/trunk@18906 dcc99617-32d9-48b4-a31d-7c20da2025e4 --- .../src/perlmods/OpenILS/Application/Serial.pm | 109 +++++++++++++++++ Open-ILS/web/js/ui/default/serial/subscription.js | 4 + .../serial/subscription/caption_and_pattern.js | 132 +++++++++++++++++++++ .../web/templates/default/serial/subscription.tt2 | 6 +- .../serial/subscription/caption_and_pattern.tt2 | 32 ++++- 5 files changed, 280 insertions(+), 3 deletions(-) diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Serial.pm b/Open-ILS/src/perlmods/OpenILS/Application/Serial.pm index 1393a2ae22..c76004c7fd 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/Serial.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/Serial.pm @@ -2926,4 +2926,113 @@ sub replace_routing_list_users { undef; } +__PACKAGE__->register_method( + "method" => "get_records_with_marc_85x", + "api_name"=>"open-ils.serial.caption_and_pattern.find_legacy_by_bib_record", + "stream" => 1, + "signature" => { + "desc" => "Return the specified BRE itself and/or any related SRE ". + "whenever they have 853-855 tags", + "params" => [ + {"desc" => "Authtoken", "type" => "string"}, + {"desc" => "bib record ID", "type" => "number"}, + ], + "return" => { + "desc" => "objects, either bre or sre", "type" => "object" + } + } +); + +sub get_records_with_marc_85x { # specifically, 853-855 + my ($self, $client, $auth, $bre_id) = @_; + + my $e = new_editor("authtoken" => $auth); + return $e->die_event unless $e->checkauth; + + my $bre = $e->search_biblio_record_entry([ + {"id" => $bre_id, "deleted" => "f"}, { + "flesh" => 1, + "flesh_fields" => {"bre" => [qw/creator editor owner/]} + } + ]) or return $e->die_event; + + return undef unless @$bre; + $bre = $bre->[0]; + + my $record = MARC::Record->new_from_xml($bre->marc); + $client->respond($bre) if $record->field("85[3-5]"); + # XXX Is passing a regex to ->field() an abuse of MARC::Record ? + + my $sres = $e->search_serial_record_entry([ + {"record" => $bre_id, "deleted" => "f"}, { + "flesh" => 1, + "flesh_fields" => {"sre" => [qw/creator editor owning_lib/]} + } + ]) or return $e->die_event; + + $e->disconnect; + + foreach my $sre (@$sres) { + $client->respond($sre) if + MARC::Record->new_from_xml($sre->marc)->field("85[3-5]"); + } + + undef; +} + +__PACKAGE__->register_method( + "method" => "create_scaps_from_marcxml", + "api_name" => "open-ils.serial.caption_and_pattern.create_from_records", + "stream" => 1, + "signature" => { + "desc" => "Create caption and pattern objects from 853-855 tags " . + "in MARCXML documents", + "params" => [ + {"desc" => "Authtoken", "type" => "string"}, + {"desc" => "Subscription ID", "type" => "number"}, + {"desc" => "list of MARCXML documents as strings", + "type" => "array"}, + ], + "return" => { + "desc" => "Newly created caption and pattern objects", + "type" => "object", "class" => "scap" + } + } +); + +sub create_scaps_from_marcxml { + my ($self, $client, $auth, $sub_id, $docs) = @_; + + return undef unless ref $docs eq "ARRAY"; + + my $e = new_editor("authtoken" => $auth, "xact" => 1); + return $e->die_event unless $e->checkauth; + + # Retrieve the subscription just for perm checking (whether we can create + # scaps at the owning lib). + my $sub = $e->retrieve_serial_subscription($sub_id) or return $e->die_event; + return $e->die_event unless + $e->allowed("ADMIN_SERIAL_CAPTION_PATTERN", $sub->owning_lib); + + foreach my $record (map { MARC::Record->new_from_xml($_) } @$docs) { + foreach my $field ($record->field("85[3-5]")) { + my $scap = new Fieldmapper::serial::caption_and_pattern; + $scap->subscription($sub_id); + $scap->type($MFHD_NAMES_BY_TAG{$field->tag}); + $scap->pattern_code( + OpenSRF::Utils::JSON->perl2JSON( + [ $field->indicator(1), $field->indicator(2), + map { @$_ } $field->subfields ] # flattens nested array + ) + ); + $e->create_serial_caption_and_pattern($scap) or + return $e->die_event; + $client->respond($e->data); + } + } + + $e->commit or return $e->die_event; + undef; +} + 1; diff --git a/Open-ILS/web/js/ui/default/serial/subscription.js b/Open-ILS/web/js/ui/default/serial/subscription.js index 7c37a12b7c..873b4d411e 100644 --- a/Open-ILS/web/js/ui/default/serial/subscription.js +++ b/Open-ILS/web/js/ui/default/serial/subscription.js @@ -17,6 +17,10 @@ var cgi; var sub; var sub_id; +function node_by_name(name, ctx) { + return dojo.query("[name='" + name + "']", ctx)[0]; +} + /* typing save: add {get,set}Value() to all HTML <select> elements */ HTMLSelectElement.prototype.getValue = function() { return this.options[this.selectedIndex].value; diff --git a/Open-ILS/web/js/ui/default/serial/subscription/caption_and_pattern.js b/Open-ILS/web/js/ui/default/serial/subscription/caption_and_pattern.js index 116cae2bca..0174547e73 100644 --- a/Open-ILS/web/js/ui/default/serial/subscription/caption_and_pattern.js +++ b/Open-ILS/web/js/ui/default/serial/subscription/caption_and_pattern.js @@ -207,3 +207,135 @@ function SCAPEditor() { this.init.apply(this, arguments); } + +function SCAPImporter() { + var self = this; + + this.init = function(sub) { + this.sub = sub; + + this.template = dojo.byId("record_template"); + this.template = this.template.parentNode.removeChild(this.template); + this.template.removeAttribute("id"); + + dojo.byId("scaps_from_bib").onclick = function() { self.launch(); }; + }; + + this.launch = function() { + this.reset(); + progress_dialog.show(true); + + fieldmapper.standardRequest( + ["open-ils.serial", + "open-ils.serial.caption_and_pattern.find_legacy_by_bib_record"], { + "params": [openils.User.authtoken, this.sub.record_entry()], + "timeout": 10, /* sync */ + "onresponse": function(r) { + if (r = openils.Util.readResponse(r)) { + self.add_record(r); + } + } + } + ); + + progress_dialog.hide(); + if (this.any_records()) + scaps_from_bib_dialog.show(); + else /* XXX i18n */ + alert("No related records with any caption and pattern fields."); + }; + + this.reset = function() { + dojo.empty("record_holder"); + this._records = []; + }; + + this.any_records = function() { + return Boolean(this._records.length); + } + + this.add_record = function(obj) { + var row = dojo.clone(this.template); + + var checkbox = dojo.query("input[type='checkbox']", row)[0]; + obj._checkbox = checkbox; + + this._records.push(obj); + + if (obj.classname == "bre") { + /* XXX i18n */ + node_by_name("obj_class", row).innerHTML = "Bibliographic"; + node_by_name("obj_id", row).innerHTML = obj.tcn_value(); + if (obj.owner()) { + openils.Util.show( + node_by_name("obj_owner_container", row), "inline" + ); + node_by_name("obj_owner", row).innerHTML = obj.owner(); + } + } else { + /* XXX i18n */ + node_by_name("obj_class", row).innerHTML = "Legacy serial"; + node_by_name("obj_id", row).innerHTML = obj.id(); + node_by_name("obj_owner", row).innerHTML = obj.owning_lib(); + openils.Util.show( + node_by_name("obj_owner_container", row), "inline" + ); + } + + if (!openils.Util.isTrue(obj.active())) + openils.Util.show(node_by_name("obj_inactive", row), "inline"); + + node_by_name("obj_create", row).innerHTML = + /* XXX i18n */ + dojo.string.substitute( + "${0}, ${1} ${2}", [ + obj.creator().family_name(), + obj.creator().first_given_name(), + obj.creator().second_given_name(), + ].map(function(o) { return o || ""; }) + ) + " on " + openils.Util.timeStamp(obj.create_date()); + + node_by_name("obj_edit", row).innerHTML = + /* XXX i18n */ + dojo.string.substitute( + "${0}, ${1} ${2}", [ + obj.editor().family_name(), + obj.editor().first_given_name(), + obj.editor().second_given_name(), + ].map(function(o) { return o || ""; }) + ) + " on " + openils.Util.timeStamp(obj.edit_date()); + + dojo.place(row, "record_holder", "last"); + }; + + this.import = function() { + var documents = this._records.filter( + function(o) { return o._checkbox.checked; } + ).map( + function(o) { return o.marc(); } + ); + + if (!documents.length) { + /* XXX i18n */ + alert("You have selected no records from which to import."); + } else { + progress_dialog.show(true); + fieldmapper.standardRequest( + ["open-ils.serial", + "open-ils.serial.caption_and_pattern.create_from_records"],{ + "params": [openils.User.authtoken,this.sub.id(),documents], + "async": false, + "onresponse": function(r) { + if (r = openils.Util.readResponse(r)) { + cap_editor.add_row(r); + } + } + } + ); + progress_dialog.hide(); + } + + }; + + this.init.apply(this, arguments); +} diff --git a/Open-ILS/web/templates/default/serial/subscription.tt2 b/Open-ILS/web/templates/default/serial/subscription.tt2 index a147a58436..0112292992 100644 --- a/Open-ILS/web/templates/default/serial/subscription.tt2 +++ b/Open-ILS/web/templates/default/serial/subscription.tt2 @@ -1,6 +1,7 @@ [% WRAPPER "default/base.tt2" %] <script> var cap_editor; + var cap_importer; </script> <script src="[% ctx.media_prefix %]/js/ui/default/serial/subscription.js"> </script> @@ -78,7 +79,10 @@ <div dojoType="dijit.layout.ContentPane" title="Captions and Patterns" layoutAlign="client"> <script type="dojo/connect" event="onShow"> - if (!cap_editor) cap_editor = new SCAPEditor(sub_id); + if (!cap_editor) { + cap_editor = new SCAPEditor(sub_id); + cap_importer = new SCAPImporter(sub); + } </script> [% INCLUDE "default/serial/subscription/caption_and_pattern.tt2" %] </div> diff --git a/Open-ILS/web/templates/default/serial/subscription/caption_and_pattern.tt2 b/Open-ILS/web/templates/default/serial/subscription/caption_and_pattern.tt2 index 3802d3d814..17d8e9d8d7 100644 --- a/Open-ILS/web/templates/default/serial/subscription/caption_and_pattern.tt2 +++ b/Open-ILS/web/templates/default/serial/subscription/caption_and_pattern.tt2 @@ -43,10 +43,38 @@ </tbody> <tfoot> <tr> - <td colspan="7"> - <button name="add">Add Caption and Pattern</button> + <td colspan="7" align="center"> + <button name="add">Add New</button> + + <button id="scaps_from_bib"> + Import From Bibliographic or Legacy Serial Records + </button> </td> </tr> </tfoot> </table> </div> +<div class="hidden"> + <div id="record_template" style="padding-bottom: 0.5em;"> + <input type="checkbox" /> <span name="obj_class"></span> record + #<span name="obj_id"></span> + <span name="obj_owner_container" class="hidden"> + (<span name="obj_owner"></span>) + </span><br /> + Created by <span name="obj_create"></span><br /> + Edited by <span name="obj_edit"></span><br /> + <em class="hidden" name="obj_inactive">(Inactive)</em> + </div> + <div dojoType="dijit.Dialog" execute="cap_importer.import()" + jsId="scaps_from_bib_dialog"> + <div> + <em> + Select records from which to import caption and pattern fields. + </em> + </div> + <div id="record_holder" style="padding: 1em 0;"></div> + <button dojoType="dijit.form.Button" type="submit"> + Import + </button> + </div> +</div> -- 2.11.0