<class id="svr" controller="open-ils.cstore" oils_obj:fieldmapper="serial::virtual_record" oils_persist:virtual="true" reporter:label="Serial Virtual Record">
<fields>
- <field name="id" oils_persist:virtual="true" />
+ <field name="sre_id" oils_persist:virtual="true" />
<field name="location" oils_persist:virtual="true" />
<field name="owning_lib" oils_persist:virtual="true" />
- <field name="holdings" oils_persist:virtual="true" />
- <field name="current_holdings" oils_persist:virtual="true" />
- <field name="supplements" oils_persist:virtual="true" />
- <field name="current_supplements" oils_persist:virtual="true" />
- <field name="indexes" oils_persist:virtual="true" />
- <field name="current_indexes" oils_persist:virtual="true" />
+ <field name="basic_holdings" oils_persist:virtual="true" />
+ <field name="basic_holdings_add" oils_persist:virtual="true" />
+ <field name="supplement_holdings" oils_persist:virtual="true" />
+ <field name="supplement_holdings_add" oils_persist:virtual="true" />
+ <field name="index_holdings" oils_persist:virtual="true" />
+ <field name="index_holdings_add" oils_persist:virtual="true" />
<field name="online" oils_persist:virtual="true" />
<field name="missing" oils_persist:virtual="true" />
<field name="incomplete" oils_persist:virtual="true" />
</class>
<class id="sssum" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="serial::supplement_summary" oils_persist:tablename="serial.supplement_summary" reporter:label="Supplemental Issue Summary">
- <fields oils_persist:primary="id" oils_persist:sequence="serial.sup_summary_id_seq">
+ <fields oils_persist:primary="id" oils_persist:sequence="serial.supplement_summary_id_seq">
<field name="id" reporter:datatype="id" />
<field name="distribution" reporter:datatype="link"/>
<field name="generated_coverage" reporter:datatype="text"/>
<link field="circ_lib" reltype="has_a" key="id" map="" class="aou"/>
</links>
<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
+ <actions>
+ <create permission="ADMIN_ASSET_COPY_TEMPLATE" global_required="true"/>
+ <retrieve />
+ <update permission="ADMIN_ASSET_COPY_TEMPLATE" global_required="true"/>
+ <delete permission="ADMIN_ASSET_COPY_TEMPLATE" global_required="true"/>
+ </actions>
</permacrud>
</class>
</app_settings>
</open-ils.vandelay>
+ <open-ils.serial>
+ <keepalive>3</keepalive>
+ <stateless>1</stateless>
+ <language>perl</language>
+ <implementation>OpenILS::Application::Serial</implementation>
+ <max_requests>17</max_requests>
+ <unix_config>
+ <unix_sock>open-ils.serial_unix.sock</unix_sock>
+ <unix_pid>open-ils.serial_unix.pid</unix_pid>
+ <max_requests>1000</max_requests>
+ <unix_log>open-ils.serial_unix.log</unix_log>
+ <min_children>5</min_children>
+ <max_children>15</max_children>
+ <min_spare_children>3</min_spare_children>
+ <max_spare_children>5</max_spare_children>
+ </unix_config>
+ <app_settings>
+ </app_settings>
+ </open-ils.serial>
+
</apps>
</default>
<appname>open-ils.trigger</appname>
<appname>open-ils.fielder</appname>
<appname>open-ils.vandelay</appname>
+ <appname>open-ils.serial</appname>
</activeapps>
</localhost>
</hosts>
<service>open-ils.search</service>
<service>open-ils.supercat</service>
<service>open-ils.vandelay</service>
+ <service>open-ils.serial</service>
</services>
</router>
<!-- ================================================================ -->
+ <event code='11000' textcode='SERIAL_SUBSCRIPTION_NOT_EMPTY'>
+ <desc xml:lang="en-US">The subscription still has dependent objects</desc>
+ </event>
+
+ <event code='11001' textcode='SERIAL_CAPTION_AND_PATTERN_HAS_ISSUANCES'>
+ <desc xml:lang="en-US">The caption/pattern still has dependent issuances</desc>
+ </event>
+
+ <!-- ================================================================ -->
+
</ils_events>
=cut
-sub bib_to_mfhd_hash {
+# DEFUNCT ?
+#sub bib_to_mfhd_hash {
+# my ($self, $client, $bib) = @_;
+#
+# my $mfhd_hash;
+#
+# # XXX perhaps this? --miker
+## my $e = OpenILS::Utils::CStoreEditor->new();
+## my $mfhd = $e->search_serial_record_entry({ record => $bib });
+## return $u->generate_svr( $mfhd->[0] ) if (ref $mfhd);
+## return undef;
+#
+# my @mfhd = $U->cstorereq( "open-ils.cstore.json_query.atomic", {
+# select => { sre => 'marc' },
+# from => 'sre',
+# where => { record => $bib, deleted => 'f' },
+# distinct => 1
+# });
+#
+# if (!@mfhd or scalar(@mfhd) == 0) {
+# return undef;
+# }
+#
+# my $u = OpenILS::Utils::MFHDParser->new();
+# $mfhd_hash = $u->generate_svr( $mfhd[0][0]->{id}, $mfhd[0][0]->{marc}, $mfhd[0][0]->{owning_lib} );
+#
+# return $mfhd_hash;
+#}
+#
+#__PACKAGE__->register_method(
+# method => "bib_to_mfhd_hash",
+# api_name => "open-ils.search.serial.record.bib_to_mfhd.retrieve",
+# argc => 1,
+# note => "Given a bibliographic record ID, return MFHD holdings"
+#);
+
+sub bib_to_svr {
my ($self, $client, $bib) = @_;
- my $mfhd_hash;
-
- # XXX perhaps this? --miker
-# my $e = OpenILS::Utils::CStoreEditor->new();
-# my $mfhd = $e->search_serial_record_entry({ record => $bib });
-# return $u->generate_svr( $mfhd->[0] ) if (ref $mfhd);
-# return undef;
-
- my @mfhd = $U->cstorereq( "open-ils.cstore.json_query.atomic", {
- select => { sre => 'marc' },
- from => 'sre',
- where => { record => $bib, deleted => 'f' },
- distinct => 1
- });
-
- if (!@mfhd or scalar(@mfhd) == 0) {
- return undef;
- }
-
- my $u = OpenILS::Utils::MFHDParser->new();
- $mfhd_hash = $u->generate_svr( $mfhd[0][0]->{id}, $mfhd[0][0]->{marc}, $mfhd[0][0]->{owning_lib} );
-
- return $mfhd_hash;
-}
-
-__PACKAGE__->register_method(
- method => "bib_to_mfhd_hash",
- api_name => "open-ils.search.serial.record.bib_to_mfhd.retrieve",
- argc => 1,
- note => "Given a bibliographic record ID, return MFHD holdings"
-);
-
-sub bib_to_mfhd {
- my ($self, $client, $bib) = @_;
-
- my $mfhd;
+ my $svrs;
my $e = OpenILS::Utils::CStoreEditor->new();
- my $serials = $e->search_serial_record_entry({ record => $bib, deleted => 'f' });
- if (!ref $serials) {
+ # TODO: 'deleted' ssub support
+ my $sdists = $e->search_serial_distribution([{ "+ssub" => {"record_entry" => $bib} }, { "flesh" => 1, "flesh_fields" => {'sdist' => [ "record_entry", "holding_lib", "basic_summary", "supplement_summary", "index_summary" ]}, "join" => {"ssub" => {}} }]);
+ my $sres = $e->search_serial_record_entry([{ record => $bib, deleted => 'f', "+sdist" => {"id" => undef} }, { "join" => {"sdist" => { 'type' => 'left' }} }]);
+ if (!ref $sres and !ref $sdists) {
return undef;
}
- my $u = OpenILS::Utils::MFHDParser->new();
- foreach (@$serials) {
- push(@$mfhd, $u->generate_svr($_->id, $_->marc, $_->owning_lib));
+ my $mfhd_parser = OpenILS::Utils::MFHDParser->new();
+ foreach (@$sdists) {
+ my $svr;
+ if (ref $_->record_entry) {
+ $svr = $mfhd_parser->generate_svr($_->record_entry->id, $_->record_entry->marc, $_->record_entry->owning_lib);
+ } else {
+ $svr = Fieldmapper::serial::virtual_record->new;
+ $svr->sre_id(-1);
+ $svr->location($_->holding_lib->name);
+ $svr->owning_lib($_->holding_lib);
+ $svr->basic_holdings([]);
+ $svr->supplement_holdings([]);
+ $svr->index_holdings([]);
+ $svr->basic_holdings_add([]);
+ $svr->supplement_holdings_add([]);
+ $svr->index_holdings_add([]);
+ $svr->online([]);
+ $svr->missing([]);
+ $svr->incomplete([]);
+ }
+ if (ref $_->basic_summary) { #TODO: 'show-generated' boolean on summaries
+ if ($_->basic_summary->generated_coverage) {
+ push(@{$svr->basic_holdings}, $_->basic_summary->generated_coverage);
+ }
+ if ($_->basic_summary->textual_holdings) {
+ push(@{$svr->basic_holdings_add}, $_->basic_summary->textual_holdings);
+ }
+ }
+ if (ref $_->supplement_summary) {
+ if ($_->supplement_summary->generated_coverage) {
+ push(@{$svr->supplement_holdings}, $_->supplement_summary->generated_coverage);
+ }
+ if ($_->supplement_summary->textual_holdings) {
+ push(@{$svr->supplement_holdings_add}, $_->supplement_summary->textual_holdings);
+ }
+ }
+ if (ref $_->index_summary) {
+ if ($_->index_summary->generated_coverage) {
+ push(@{$svr->index_holdings}, $_->index_summary->generated_coverage);
+ }
+ if ($_->index_summary->textual_holdings) {
+ push(@{$svr->index_holdings_add}, $_->index_summary->textual_holdings);
+ }
+ }
+ push(@$svrs, $svr);
}
+ foreach (@$sres) {
+ push(@$svrs, $mfhd_parser->generate_svr($_->id, $_->marc, $_->owning_lib));
+ }
+
+ # do a basic location sort for simple predictability
+ @$svrs = sort { $a->location cmp $b->location } @$svrs;
- return $mfhd;
+ return $svrs;
}
__PACKAGE__->register_method(
- method => "bib_to_mfhd",
+ method => "bib_to_svr",
api_name => "open-ils.search.serial.record.bib.retrieve",
argc => 1,
- note => "Given a bibliographic record ID, return MFHD holdings"
+ note => "Given a bibliographic record ID, return holdings in svr form"
);
1;
--- /dev/null
+#!/usr/bin/perl
+
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+=head1 NAME
+
+OpenILS::Application::Serial - Performs serials-related tasks such as receiving issues and generating predictions
+
+=head1 SYNOPSIS
+
+TBD
+
+=head1 DESCRIPTION
+
+TBD
+
+=head1 AUTHOR
+
+Dan Wells, dbw2@calvin.edu
+
+=cut
+
+package OpenILS::Application::Serial;
+
+use strict;
+use warnings;
+
+use OpenILS::Application;
+use base qw/OpenILS::Application/;
+use OpenILS::Application::AppUtils;
+use OpenSRF::AppSession;
+use OpenSRF::Utils qw/:datetime/;;
+use OpenSRF::Utils::Logger qw($logger);
+use OpenILS::Utils::CStoreEditor q/:funcs/;
+use OpenILS::Utils::MFHD;
+use MARC::File::XML (BinaryEncoding => 'utf8');
+my $U = 'OpenILS::Application::AppUtils';
+my @MFHD_NAMES = ('basic','supplement','index');
+my %MFHD_NAMES_BY_TAG = ( '853' => $MFHD_NAMES[0],
+ '863' => $MFHD_NAMES[0],
+ '854' => $MFHD_NAMES[1],
+ '864' => $MFHD_NAMES[1],
+ '855' => $MFHD_NAMES[2],
+ '865' => $MFHD_NAMES[2] );
+my %MFHD_TAGS_BY_NAME = ( $MFHD_NAMES[0] => '853',
+ $MFHD_NAMES[1] => '854',
+ $MFHD_NAMES[2] => '855');
+
+
+# helper method for conforming dates to ISO8601
+sub _cleanse_dates {
+ my $item = shift;
+ my $fields = shift;
+
+ foreach my $field (@$fields) {
+ $item->$field(OpenSRF::Utils::clense_ISO8601($item->$field)) if $item->$field;
+ }
+ return 0;
+}
+
+
+##########################################################################
+# item methods
+#
+__PACKAGE__->register_method(
+ method => 'fleshed_item_alter',
+ api_name => 'open-ils.serial.item.fleshed.batch.update',
+ api_level => 1,
+ argc => 2,
+ signature => {
+ desc => 'Receives an array of one or more items and updates the database as needed',
+ 'params' => [ {
+ name => 'authtoken',
+ desc => 'Authtoken for current user session',
+ type => 'string'
+ },
+ {
+ name => 'items',
+ desc => 'Array of fleshed items',
+ type => 'array'
+ }
+
+ ],
+ 'return' => {
+ desc => 'Returns 1 if successful, event if failed',
+ type => 'mixed'
+ }
+ }
+);
+
+sub fleshed_item_alter {
+ my( $self, $conn, $auth, $items ) = @_;
+ return 1 unless ref $items;
+ my( $reqr, $evt ) = $U->checkses($auth);
+ return $evt if $evt;
+ my $editor = new_editor(requestor => $reqr, xact => 1);
+ my $override = $self->api_name =~ /override/;
+
+# TODO: permission check
+# return $editor->event unless
+# $editor->allowed('UPDATE_COPY', $class->copy_perm_org($vol, $copy));
+
+ for my $item (@$items) {
+
+ my $itemid = $item->id;
+ $item->editor($editor->requestor->id);
+ $item->edit_date('now');
+
+ if( $item->isdeleted ) {
+ $evt = _delete_sitem( $editor, $override, $item);
+ } elsif( $item->isnew ) {
+ # TODO: reconsider this
+ # if the item has a new issuance, create the issuance first
+ if (ref $item->issuance eq 'Fieldmapper::serial::issuance' and $item->issuance->isnew) {
+ fleshed_issuance_alter($self, $conn, $auth, [$item->issuance]);
+ }
+ _cleanse_dates($item, ['date_expected','date_received']);
+ $evt = _create_sitem( $editor, $item );
+ } else {
+ _cleanse_dates($item, ['date_expected','date_received']);
+ $evt = _update_sitem( $editor, $override, $item );
+ }
+ }
+
+ if( $evt ) {
+ $logger->info("fleshed item-alter failed with event: ".OpenSRF::Utils::JSON->perl2JSON($evt));
+ $editor->rollback;
+ return $evt;
+ }
+ $logger->debug("item-alter: done updating item batch");
+ $editor->commit;
+ $logger->info("fleshed item-alter successfully updated ".scalar(@$items)." items");
+ return 1;
+}
+
+sub _delete_sitem {
+ my ($editor, $override, $item) = @_;
+ $logger->info("item-alter: delete item ".OpenSRF::Utils::JSON->perl2JSON($item));
+ return $editor->event unless $editor->delete_serial_item($item);
+ return 0;
+}
+
+sub _create_sitem {
+ my ($editor, $item) = @_;
+
+ $item->creator($editor->requestor->id);
+ $item->create_date('now');
+
+ $logger->info("item-alter: new item ".OpenSRF::Utils::JSON->perl2JSON($item));
+ return $editor->event unless $editor->create_serial_item($item);
+ return 0;
+}
+
+sub _update_sitem {
+ my ($editor, $override, $item) = @_;
+
+ $logger->info("item-alter: retrieving item ".$item->id);
+ my $orig_item = $editor->retrieve_serial_item($item->id);
+
+ $logger->info("item-alter: original item ".OpenSRF::Utils::JSON->perl2JSON($orig_item));
+ $logger->info("item-alter: updated item ".OpenSRF::Utils::JSON->perl2JSON($item));
+ return $editor->event unless $editor->update_serial_item($item);
+ return 0;
+}
+
+__PACKAGE__->register_method(
+ method => "fleshed_serial_item_retrieve_batch",
+ authoritative => 1,
+ api_name => "open-ils.serial.item.fleshed.batch.retrieve"
+);
+
+sub fleshed_serial_item_retrieve_batch {
+ my( $self, $client, $ids ) = @_;
+# FIXME: permissions?
+ $logger->info("Fetching fleshed serial items @$ids");
+ return $U->cstorereq(
+ "open-ils.cstore.direct.serial.item.search.atomic",
+ { id => $ids },
+ { flesh => 2,
+ flesh_fields => {sitem => [ qw/issuance creator editor stream unit notes/ ], sstr => ["distribution"], sunit => ["call_number"], siss => [qw/creator editor subscription/]}
+ });
+}
+
+
+##########################################################################
+# issuance methods
+#
+__PACKAGE__->register_method(
+ method => 'fleshed_issuance_alter',
+ api_name => 'open-ils.serial.issuance.fleshed.batch.update',
+ api_level => 1,
+ argc => 2,
+ signature => {
+ desc => 'Receives an array of one or more issuances and updates the database as needed',
+ 'params' => [ {
+ name => 'authtoken',
+ desc => 'Authtoken for current user session',
+ type => 'string'
+ },
+ {
+ name => 'issuances',
+ desc => 'Array of fleshed issuances',
+ type => 'array'
+ }
+
+ ],
+ 'return' => {
+ desc => 'Returns 1 if successful, event if failed',
+ type => 'mixed'
+ }
+ }
+);
+
+sub fleshed_issuance_alter {
+ my( $self, $conn, $auth, $issuances ) = @_;
+ return 1 unless ref $issuances;
+ my( $reqr, $evt ) = $U->checkses($auth);
+ return $evt if $evt;
+ my $editor = new_editor(requestor => $reqr, xact => 1);
+ my $override = $self->api_name =~ /override/;
+
+# TODO: permission support
+# return $editor->event unless
+# $editor->allowed('UPDATE_COPY', $class->copy_perm_org($vol, $copy));
+
+ for my $issuance (@$issuances) {
+ my $issuanceid = $issuance->id;
+ $issuance->editor($editor->requestor->id);
+ $issuance->edit_date('now');
+
+ if( $issuance->isdeleted ) {
+ $evt = _delete_siss( $editor, $override, $issuance);
+ } elsif( $issuance->isnew ) {
+ _cleanse_dates($issuance, ['date_published']);
+ $evt = _create_siss( $editor, $issuance );
+ } else {
+ _cleanse_dates($issuance, ['date_published']);
+ $evt = _update_siss( $editor, $override, $issuance );
+ }
+ }
+
+ if( $evt ) {
+ $logger->info("fleshed issuance-alter failed with event: ".OpenSRF::Utils::JSON->perl2JSON($evt));
+ $editor->rollback;
+ return $evt;
+ }
+ $logger->debug("issuance-alter: done updating issuance batch");
+ $editor->commit;
+ $logger->info("fleshed issuance-alter successfully updated ".scalar(@$issuances)." issuances");
+ return 1;
+}
+
+sub _delete_siss {
+ my ($editor, $override, $issuance) = @_;
+ $logger->info("issuance-alter: delete issuance ".OpenSRF::Utils::JSON->perl2JSON($issuance));
+ return $editor->event unless $editor->delete_serial_issuance($issuance);
+ return 0;
+}
+
+sub _create_siss {
+ my ($editor, $issuance) = @_;
+
+ $issuance->creator($editor->requestor->id);
+ $issuance->create_date('now');
+
+ $logger->info("issuance-alter: new issuance ".OpenSRF::Utils::JSON->perl2JSON($issuance));
+ return $editor->event unless $editor->create_serial_issuance($issuance);
+ return 0;
+}
+
+sub _update_siss {
+ my ($editor, $override, $issuance) = @_;
+
+ $logger->info("issuance-alter: retrieving issuance ".$issuance->id);
+ my $orig_issuance = $editor->retrieve_serial_issuance($issuance->id);
+
+ $logger->info("issuance-alter: original issuance ".OpenSRF::Utils::JSON->perl2JSON($orig_issuance));
+ $logger->info("issuance-alter: updated issuance ".OpenSRF::Utils::JSON->perl2JSON($issuance));
+ return $editor->event unless $editor->update_serial_issuance($issuance);
+ return 0;
+}
+
+__PACKAGE__->register_method(
+ method => "fleshed_serial_issuance_retrieve_batch",
+ authoritative => 1,
+ api_name => "open-ils.serial.issuance.fleshed.batch.retrieve"
+);
+
+sub fleshed_serial_issuance_retrieve_batch {
+ my( $self, $client, $ids ) = @_;
+# FIXME: permissions?
+ $logger->info("Fetching fleshed serial issuances @$ids");
+ return $U->cstorereq(
+ "open-ils.cstore.direct.serial.issuance.search.atomic",
+ { id => $ids },
+ { flesh => 1,
+ flesh_fields => {siss => [ qw/creator editor subscription/ ]}
+ });
+}
+
+
+##########################################################################
+# unit methods
+#
+__PACKAGE__->register_method(
+ method => 'fleshed_sunit_alter',
+ api_name => 'open-ils.serial.sunit.fleshed.batch.update',
+ api_level => 1,
+ argc => 2,
+ signature => {
+ desc => 'Receives an array of one or more Units and updates the database as needed',
+ 'params' => [ {
+ name => 'authtoken',
+ desc => 'Authtoken for current user session',
+ type => 'string'
+ },
+ {
+ name => 'sunits',
+ desc => 'Array of fleshed Units',
+ type => 'array'
+ }
+
+ ],
+ 'return' => {
+ desc => 'Returns 1 if successful, event if failed',
+ type => 'mixed'
+ }
+ }
+);
+
+sub fleshed_sunit_alter {
+ my( $self, $conn, $auth, $sunits ) = @_;
+ return 1 unless ref $sunits;
+ my( $reqr, $evt ) = $U->checkses($auth);
+ return $evt if $evt;
+ my $editor = new_editor(requestor => $reqr, xact => 1);
+ my $override = $self->api_name =~ /override/;
+
+# TODO: permission support
+# return $editor->event unless
+# $editor->allowed('UPDATE_COPY', $class->copy_perm_org($vol, $copy));
+
+ for my $sunit (@$sunits) {
+ if( $sunit->isdeleted ) {
+ $evt = _delete_sunit( $editor, $override, $sunit );
+ } else {
+ $sunit->default_location( $sunit->default_location->id ) if ref $sunit->default_location;
+
+ if( $sunit->isnew ) {
+ $evt = _create_sunit( $editor, $sunit );
+ } else {
+ $evt = _update_sunit( $editor, $override, $sunit );
+ }
+ }
+ }
+
+ if( $evt ) {
+ $logger->info("fleshed sunit-alter failed with event: ".OpenSRF::Utils::JSON->perl2JSON($evt));
+ $editor->rollback;
+ return $evt;
+ }
+ $logger->debug("sunit-alter: done updating sunit batch");
+ $editor->commit;
+ $logger->info("fleshed sunit-alter successfully updated ".scalar(@$sunits)." Units");
+ return 1;
+}
+
+sub _delete_sunit {
+ my ($editor, $override, $sunit) = @_;
+ $logger->info("sunit-alter: delete sunit ".OpenSRF::Utils::JSON->perl2JSON($sunit));
+ return $editor->event unless $editor->delete_serial_unit($sunit);
+ return 0;
+}
+
+sub _create_sunit {
+ my ($editor, $sunit) = @_;
+
+ $logger->info("sunit-alter: new Unit ".OpenSRF::Utils::JSON->perl2JSON($sunit));
+ return $editor->event unless $editor->create_serial_unit($sunit);
+ return 0;
+}
+
+sub _update_sunit {
+ my ($editor, $override, $sunit) = @_;
+
+ $logger->info("sunit-alter: retrieving sunit ".$sunit->id);
+ my $orig_sunit = $editor->retrieve_serial_unit($sunit->id);
+
+ $logger->info("sunit-alter: original sunit ".OpenSRF::Utils::JSON->perl2JSON($orig_sunit));
+ $logger->info("sunit-alter: updated sunit ".OpenSRF::Utils::JSON->perl2JSON($sunit));
+ return $editor->event unless $editor->update_serial_unit($sunit);
+ return 0;
+}
+
+__PACKAGE__->register_method(
+ method => "retrieve_unit_list",
+ authoritative => 1,
+ api_name => "open-ils.serial.unit_list.retrieve"
+);
+
+sub retrieve_unit_list {
+
+ my( $self, $client, @sdist_ids ) = @_;
+
+ if(ref($sdist_ids[0])) { @sdist_ids = @{$sdist_ids[0]}; }
+
+ my $e = new_editor();
+
+ my $query = {
+ 'select' =>
+ { 'sunit' => [ 'id', 'summary_contents', 'sort_key' ],
+ 'sitem' => ['stream'],
+ 'sstr' => ['distribution'],
+ 'sdist' => [{'column' => 'label', 'alias' => 'sdist_label'}]
+ },
+ 'from' =>
+ { 'sdist' =>
+ { 'sstr' =>
+ { 'join' =>
+ { 'sitem' =>
+ { 'join' => { 'sunit' => {} } }
+ }
+ }
+ }
+ },
+ 'distinct' => 'true',
+ 'where' => { '+sdist' => {'id' => \@sdist_ids} },
+ 'order_by' => [{'class' => 'sunit', 'field' => 'sort_key'}]
+ };
+
+ my $unit_list_entries = $e->json_query($query);
+
+ my @entries;
+ foreach my $entry (@$unit_list_entries) {
+ my $value = {'sunit' => $entry->{id}, 'sstr' => $entry->{stream}, 'sdist' => $entry->{distribution}};
+ my $label = $entry->{summary_contents};
+ if (length($label) > 100) {
+ $label = substr($label, 0, 100) . '...'; # limited space in dropdown / menu
+ }
+ $label = "[$entry->{sdist_label}/$entry->{stream} #$entry->{id}] " . $label;
+ push (@entries, [$label, OpenSRF::Utils::JSON->perl2JSON($value)]);
+ }
+
+ return \@entries;
+}
+
+
+
+##########################################################################
+# predict and receive methods
+#
+__PACKAGE__->register_method(
+ method => 'make_predictions',
+ api_name => 'open-ils.serial.make_predictions',
+ api_level => 1,
+ argc => 1,
+ signature => {
+ desc => 'Receives an ssub id and populates the issuance and item tables',
+ 'params' => [ {
+ name => 'ssub_id',
+ desc => 'Serial Subscription ID',
+ type => 'int'
+ }
+ ]
+ }
+);
+
+sub make_predictions {
+ my ($self, $conn, $authtoken, $args) = @_;
+
+ my $editor = OpenILS::Utils::CStoreEditor->new();
+ my $ssub_id = $args->{ssub_id};
+ my $mfhd = MFHD->new(MARC::Record->new());
+
+ my $ssub = $editor->retrieve_serial_subscription([$ssub_id]);
+ my $scaps = $editor->search_serial_caption_and_pattern({ subscription => $ssub_id, active => 't'});
+ my $sdists = $editor->search_serial_distribution( [{ subscription => $ssub->id }, { flesh => 1,
+ flesh_fields => {sdist => [ qw/ streams / ]}, limit => 1 }] ); #TODO: 'deleted' support?
+
+ my @predictions;
+ my $link_id = 1;
+ foreach my $scap (@$scaps) {
+ my $caption_field = _revive_caption($scap);
+ $caption_field->update('8' => $link_id);
+ $mfhd->append_fields($caption_field);
+ my $options = {
+ 'caption' => $caption_field,
+ 'scap_id' => $scap->id,
+ 'num_to_predict' => $args->{num_to_predict}
+ };
+ if ($args->{base_issuance}) { # predict from a given issuance
+ $options->{predict_from} = _revive_holding($args->{base_issuance}->holding_code, $caption_field, 1); # fresh MFHD Record, so we simply default to 1 for seqno
+ } else { # default to predicting from last published
+ my $last_published = $editor->search_serial_issuance([
+ {'caption_and_pattern' => $scap->id,
+ 'subscription' => $ssub_id},
+ {limit => 1, order_by => { siss => "date_published DESC" }}]
+ );
+ if ($last_published->[0]) {
+ my $last_siss = $last_published->[0];
+ $options->{predict_from} = _revive_holding($last_siss->holding_code, $caption_field, 1);
+ } else {
+ #TODO: throw event (can't predict from nothing!)
+ }
+ }
+ push( @predictions, _generate_issuance_values($mfhd, $options) );
+ $link_id++;
+ }
+
+ my @issuances;
+ foreach my $prediction (@predictions) {
+ my $issuance = new Fieldmapper::serial::issuance;
+ $issuance->isnew(1);
+ $issuance->label($prediction->{label});
+ $issuance->date_published($prediction->{date_published}->strftime('%F'));
+ $issuance->holding_code(OpenSRF::Utils::JSON->perl2JSON($prediction->{holding_code}));
+ $issuance->holding_type($prediction->{holding_type});
+ $issuance->caption_and_pattern($prediction->{caption_and_pattern});
+ $issuance->subscription($ssub->id);
+ push (@issuances, $issuance);
+ }
+
+ fleshed_issuance_alter($self, $conn, $authtoken, \@issuances); # FIXME: catch events
+
+ my @items;
+ for (my $i = 0; $i < @issuances; $i++) {
+ my $date_expected = $predictions[$i]->{date_published}->add(seconds => interval_to_seconds($ssub->expected_date_offset))->strftime('%F');
+ my $issuance = $issuances[$i];
+ #$issuance->label(interval_to_seconds($ssub->expected_date_offset));
+ foreach my $sdist (@$sdists) {
+ my $streams = $sdist->streams;
+ foreach my $stream (@$streams) {
+ my $item = new Fieldmapper::serial::item;
+ $item->isnew(1);
+ $item->stream($stream->id);
+ $item->date_expected($date_expected);
+ $item->issuance($issuance->id);
+ push (@items, $item);
+ }
+ }
+ }
+ fleshed_item_alter($self, $conn, $authtoken, \@items); # FIXME: catch events
+ return \@items;
+}
+
+#
+# _generate_issuance_values() is an initial attempt at a function which can be used
+# to populate an issuance table with a list of predicted issues. It accepts
+# a hash ref of options initially defined as:
+# caption : the caption field to predict on
+# num_to_predict : the number of issues you wish to predict
+# last_rec_date : the date of the last received issue, to be used as an offset
+# for predicting future issues
+#
+# The basic method is to first convert to a single holding if compressed, then
+# increment the holding and save the resulting values to @issuances.
+#
+# returns @issuance_values, an array of hashrefs containing (formatted
+# label, formatted chronology date, formatted estimated arrival date, and an
+# array ref of holding subfields as (key, value, key, value ...)) (not a hash
+# to protect order and possible duplicate keys), and a holding type.
+#
+sub _generate_issuance_values {
+ my ($mfhd, $options) = @_;
+ my $caption = $options->{caption};
+ my $scap_id = $options->{scap_id};
+ my $num_to_predict = $options->{num_to_predict};
+ my $predict_from = $options->{predict_from}; # issuance to predict from
+ #my $last_rec_date = $options->{last_rec_date}; # expected or actual
+
+ # TODO: add support for predicting serials with no chronology by passing in
+ # a last_pub_date option?
+
+
+# Only needed for 'real' MFHD records, not our temp records
+# my $link_id = $caption->link_id;
+# if(!$predict_from) {
+# my $htag = $caption->tag;
+# $htag =~ s/^85/86/;
+# my @holdings = $mfhd->holdings($htag, $link_id);
+# my $last_holding = $holdings[-1];
+#
+# #if ($last_holding->is_compressed) {
+# # $last_holding->compressed_to_last; # convert to last in range
+# #}
+# $predict_from = $last_holding;
+# }
+#
+
+ $predict_from->notes('public', []);
+# add a note marker for system use (?)
+ $predict_from->notes('private', ['AUTOGEN']);
+
+ my $strp = new DateTime::Format::Strptime(pattern => '%F');
+ my $pub_date;
+ my @issuance_values;
+ my @predictions = $mfhd->generate_predictions({'base_holding' => $predict_from, 'num_to_predict' => $num_to_predict});
+ foreach my $prediction (@predictions) {
+ $pub_date = $strp->parse_datetime($prediction->chron_to_date);
+ push(
+ @issuance_values,
+ {
+ #$link_id,
+ label => $prediction->format,
+ date_published => $pub_date,
+ #date_expected => $date_expected->strftime('%F'),
+ holding_code => [$prediction->indicator(1),$prediction->indicator(2),$prediction->subfields_list],
+ holding_type => $MFHD_NAMES_BY_TAG{$caption->tag},
+ caption_and_pattern => $scap_id
+ }
+ );
+ }
+
+ return @issuance_values;
+}
+
+sub _revive_caption {
+ my $scap = shift;
+
+ my $pattern_code = $scap->pattern_code;
+
+ # build MARC::Field
+ my $pattern_parts = OpenSRF::Utils::JSON->JSON2perl($pattern_code);
+ unshift(@$pattern_parts, $MFHD_TAGS_BY_NAME{$scap->type});
+ my $pattern_field = new MARC::Field(@$pattern_parts);
+
+ # build MFHD::Caption
+ return new MFHD::Caption($pattern_field);
+}
+
+sub _revive_holding {
+ my $holding_code = shift;
+ my $caption_field = shift;
+ my $seqno = shift;
+
+ # build MARC::Field
+ my $holding_parts = OpenSRF::Utils::JSON->JSON2perl($holding_code);
+ my $captag = $caption_field->tag;
+ $captag =~ s/^85/86/;
+ unshift(@$holding_parts, $captag);
+ my $holding_field = new MARC::Field(@$holding_parts);
+
+ # build MFHD::Holding
+ return new MFHD::Holding($seqno, $holding_field, $caption_field);
+}
+
+__PACKAGE__->register_method(
+ method => 'unitize_items',
+ api_name => 'open-ils.serial.receive_items',
+ api_level => 1,
+ argc => 1,
+ signature => {
+ desc => 'Marks an item as received, updates the shelving unit (creating a new shelving unit if needed), and updates the summaries',
+ 'params' => [ {
+ name => 'items',
+ desc => 'array of serial items',
+ type => 'array'
+ }
+ ],
+ 'return' => {
+ desc => 'Returns number of received items',
+ type => 'int'
+ }
+ }
+);
+
+sub unitize_items {
+ my ($self, $conn, $auth, $items) = @_;
+
+ my( $reqr, $evt ) = $U->checkses($auth);
+ return $evt if $evt;
+ my $editor = new_editor(requestor => $reqr, xact => 1);
+ $self->api_name =~ /serial\.(\w*)_items/;
+ my $mode = $1;
+
+ my %found_unit_ids;
+ my %found_stream_ids;
+ my %found_types;
+
+ my %stream_ids_by_unit_id;
+
+ my %unit_map;
+ my %sdist_by_unit_id;
+ my %sdist_by_stream_id;
+
+ my $new_unit_id; # id for '-2' units to share
+ foreach my $item (@$items) {
+ # for debugging only, TODO: delete
+ if (!ref $item) { # hopefully we got an id instead
+ $item = $editor->retrieve_serial_item($item);
+ }
+ # get ids
+ my $unit_id = ref($item->unit) ? $item->unit->id : $item->unit;
+ my $stream_id = ref($item->stream) ? $item->stream->id : $item->stream;
+ my $issuance_id = ref($item->issuance) ? $item->issuance->id : $item->issuance;
+ #TODO: evt on any missing ids
+
+ if ($mode eq 'receive') {
+ $item->date_received('now');
+ $item->status('Received');
+ } else {
+ $item->status('Bindery');
+ }
+
+ # check for types to trigger summary updates
+ my $scap;
+ if (!ref $item->issuance) {
+ my $scaps = $editor->search_serial_caption_and_pattern([{"+siss" => {"id" => $issuance_id}}, { "join" => {"siss" => {}} }]);
+ $scap = $scaps->[0];
+ } elsif (!ref $item->issuance->caption_and_pattern) {
+ $scap = $editor->retrieve_serial_caption_and_pattern($item->issuance->caption_and_pattern);
+ } else {
+ $scap = $editor->issuance->caption_and_pattern;
+ }
+ if (!exists($found_types{$stream_id})) {
+ $found_types{$stream_id} = {};
+ }
+ $found_types{$stream_id}->{$scap->type} = 1;
+
+ # create unit if needed
+ if ($unit_id == -1 or (!$new_unit_id and $unit_id == -2)) { # create unit per item
+ my $unit;
+ my $sdists = $editor->search_serial_distribution([{"+sstr" => {"id" => $stream_id}}, { "join" => {"sstr" => {}} }]);
+ $unit = _build_unit($editor, $sdists->[0], $mode);
+ my $evt = _create_sunit($editor, $unit);
+ return $evt if $evt;
+ if ($unit_id == -2) {
+ $new_unit_id = $unit->id;
+ $unit_id = $new_unit_id;
+ } else {
+ $unit_id = $unit->id;
+ }
+ $item->unit($unit_id);
+
+ # get unit with 'DEFAULT's and save unit and sdist for later use
+ $unit = $editor->retrieve_serial_unit($unit->id);
+ $unit_map{$unit_id} = $unit;
+ $sdist_by_unit_id{$unit_id} = $sdists->[0];
+ $sdist_by_stream_id{$stream_id} = $sdists->[0];
+ } elsif ($unit_id == -2) { # create one unit for all '-2' items
+ $unit_id = $new_unit_id;
+ $item->unit($unit_id);
+ }
+
+ $found_unit_ids{$unit_id} = 1;
+ $found_stream_ids{$stream_id} = 1;
+
+ # save the stream_id for this unit_id
+ # TODO: prevent items from different streams in same unit? (perhaps in interface)
+ $stream_ids_by_unit_id{$unit_id} = $stream_id;
+
+ my $evt = _update_sitem($editor, undef, $item);
+ return $evt if $evt;
+ }
+
+ # deal with unit level labels
+ foreach my $unit_id (keys %found_unit_ids) {
+
+ # get all the needed issuances for unit
+ my $issuances = $editor->search_serial_issuance([ {"+sitem" => {"unit" => $unit_id, "status" => "Received"}}, {"join" => {"sitem" => {}}, "order_by" => {"siss" => "date_published"}} ]);
+ #TODO: evt on search failure
+
+ my ($mfhd, $formatted_parts) = _summarize_contents($editor, $issuances);
+
+ # special case for single formatted_part (may have summarized version)
+ if (@$formatted_parts == 1) {
+ #TODO: MFHD.pm should have a 'format_summary' method for this
+ }
+
+ # retrieve and update unit contents
+ my $sunit;
+ my $sdist;
+
+ # if we just created the unit, we will already have it and the distribution stored
+ if (exists $unit_map{$unit_id}) {
+ $sunit = $unit_map{$unit_id};
+ $sdist = $sdist_by_unit_id{$unit_id};
+ } else {
+ $sunit = $editor->retrieve_serial_unit($unit_id);
+ $sdist = $editor->search_serial_distribution([{"+sstr" => {"id" => $stream_ids_by_unit_id{$unit_id}}}, { "join" => {"sstr" => {}} }]);
+ $sdist = $sdist->[0];
+ }
+
+ $sunit->detailed_contents($sdist->unit_label_prefix . ' '
+ . join(', ', @$formatted_parts) . ' '
+ . $sdist->unit_label_suffix);
+
+ $sunit->summary_contents($sunit->detailed_contents); #TODO: change this when real summary contents are available
+
+ # create sort_key by left padding numbers to 6 digits
+ my $sort_key = $sunit->detailed_contents;
+ $sort_key =~ s/(\d+)/sprintf '%06d', $1/eg; # this may need improvement
+ $sunit->sort_key($sort_key);
+
+ if ($mode eq 'bind') {
+ $sunit->status(2); # set to 'Bindery' status
+ }
+
+ my $evt = _update_sunit($editor, undef, $sunit);
+ return $evt if $evt;
+ }
+
+ # TODO: cleanup 'dead' units (units which are now emptied of their items)
+
+ if ($mode eq 'receive') { # the summary holdings do not change when binding
+ # deal with stream level summaries
+ # summaries will be built from the "primary" stream only, that is, the stream with the lowest ID per distribution
+ # (TODO: consider direct designation)
+ my %primary_streams_by_sdist;
+ my %streams_by_sdist;
+
+ # see if we have primary streams, and if so, associate them with their distributions
+ foreach my $stream_id (keys %found_stream_ids) {
+ my $sdist;
+ if (exists $sdist_by_stream_id{$stream_id}) {
+ $sdist = $sdist_by_stream_id{$stream_id};
+ } else {
+ $sdist = $editor->search_serial_distribution([{"+sstr" => {"id" => $stream_id}}, { "join" => {"sstr" => {}} }]);
+ $sdist = $sdist->[0];
+ }
+ my $streams;
+ if (!exists($streams_by_sdist{$sdist->id})) {
+ $streams = $editor->search_serial_stream([{"distribution" => $sdist->id}, {"order_by" => {"sstr" => "id"}}]);
+ $streams_by_sdist{$sdist->id} = $streams;
+ } else {
+ $streams = $streams_by_sdist{$sdist->id};
+ }
+ $primary_streams_by_sdist{$sdist->id} = $streams->[0] if ($stream_id == $streams->[0]->id);
+ }
+
+ # retrieve and update summaries for each affected primary stream's distribution
+ foreach my $sdist_id (keys %primary_streams_by_sdist) {
+ my $stream = $primary_streams_by_sdist{$sdist_id};
+ my $stream_id = $stream->id;
+ # get all the needed issuances for stream
+ # FIXME: search in Bindery/Bound/Not Published? as well as Received
+ foreach my $type (keys %{$found_types{$stream_id}}) {
+ my $issuances = $editor->search_serial_issuance([ {"+sitem" => {"stream" => $stream_id, "status" => "Received"}, "+scap" => {"type" => $type}}, {"join" => {"sitem" => {}, "scap" => {}}, "order_by" => {"siss" => "date_published"}} ]);
+ #TODO: evt on search failure
+
+ my ($mfhd, $formatted_parts) = _summarize_contents($editor, $issuances);
+
+ # retrieve and update the generated_coverage of the summary
+ my $search_method = "search_serial_${type}_summary";
+ my $summary = $editor->$search_method([{"distribution" => $sdist_id}]);
+ $summary = $summary->[0];
+ $summary->generated_coverage(join(', ', @$formatted_parts));
+ my $update_method = "update_serial_${type}_summary";
+ return $editor->event unless $editor->$update_method($summary);
+ }
+ }
+ }
+
+ $editor->commit;
+ return {'num_items_received' => scalar @$items, 'new_unit_id' => $new_unit_id};
+}
+
+sub _build_unit {
+ my $editor = shift;
+ my $sdist = shift;
+ my $mode = shift;
+
+ my $attr = $mode . '_unit_template';
+ my $template = $editor->retrieve_asset_copy_template($sdist->$attr);
+
+ my @parts = qw( status location loan_duration fine_level age_protect circulate deposit ref holdable deposit_amount price circ_modifier circ_as_type alert_message opac_visible floating mint_condition );
+
+ my $unit = new Fieldmapper::serial::unit;
+ foreach my $part (@parts) {
+ my $value = $template->$part;
+ next if !defined($value);
+ $unit->$part($value);
+ }
+
+ # ignore circ_lib in template, set to distribution holding_lib
+ $unit->circ_lib($sdist->holding_lib);
+ $unit->creator($editor->requestor->id);
+ $unit->editor($editor->requestor->id);
+ $attr = $mode . '_call_number';
+ $unit->call_number($sdist->$attr);
+ $unit->barcode('AUTO');
+ $unit->sort_key('');
+ $unit->summary_contents('');
+ $unit->detailed_contents('');
+
+ return $unit;
+}
+
+
+sub _summarize_contents {
+ my $editor = shift;
+ my $issuances = shift;
+
+ # create MFHD record
+ my $mfhd = MFHD->new(MARC::Record->new());
+ my %scaps;
+ my %scap_fields;
+ my @scap_fields_ordered;
+ my $seqno = 1;
+ my $link_id = 1;
+ foreach my $issuance (@$issuances) {
+ my $scap_id = $issuance->caption_and_pattern;
+ next if (!$scap_id); # skip issuances with no caption/pattern
+
+ my $scap;
+ my $scap_field;
+ # if this is the first appearance of this scap, retrieve it and add it to the temporary record
+ if (!exists $scaps{$issuance->caption_and_pattern}) {
+ $scaps{$scap_id} = $editor->retrieve_serial_caption_and_pattern($scap_id);
+ $scap = $scaps{$scap_id};
+ $scap_field = _revive_caption($scap);
+ $scap_fields{$scap_id} = $scap_field;
+ push(@scap_fields_ordered, $scap_field);
+ $scap_field->update('8' => $link_id);
+ $mfhd->append_fields($scap_field);
+ $link_id++;
+ } else {
+ $scap = $scaps{$scap_id};
+ $scap_field = $scap_fields{$scap_id};
+ }
+
+ $mfhd->append_fields(_revive_holding($issuance->holding_code, $scap_field, $seqno));
+ $seqno++;
+ }
+
+ my @formatted_parts;
+ foreach my $scap_field (@scap_fields_ordered) { #TODO: use generic MFHD "summarize" method, once available
+ my @updated_holdings = $mfhd->get_compressed_holdings($scap_field);
+ foreach my $holding (@updated_holdings) {
+ push(@formatted_parts, $holding->format);
+ }
+ }
+
+ return ($mfhd, \@formatted_parts);
+}
+
+##########################################################################
+# note methods
+#
+__PACKAGE__->register_method(
+ method => 'fetch_notes',
+ api_name => 'open-ils.serial.item_note.retrieve.all',
+ signature => q/
+ Returns an array of copy note objects.
+ @param args A named hash of parameters including:
+ authtoken : Required if viewing non-public notes
+ item_id : The id of the item whose notes we want to retrieve
+ pub : True if all the caller wants are public notes
+ @return An array of note objects
+ /
+);
+
+__PACKAGE__->register_method(
+ method => 'fetch_notes',
+ api_name => 'open-ils.serial.subscription_note.retrieve.all',
+ signature => q/
+ Returns an array of copy note objects.
+ @param args A named hash of parameters including:
+ authtoken : Required if viewing non-public notes
+ subscription_id : The id of the item whose notes we want to retrieve
+ pub : True if all the caller wants are public notes
+ @return An array of note objects
+ /
+);
+
+__PACKAGE__->register_method(
+ method => 'fetch_notes',
+ api_name => 'open-ils.serial.distribution_note.retrieve.all',
+ signature => q/
+ Returns an array of copy note objects.
+ @param args A named hash of parameters including:
+ authtoken : Required if viewing non-public notes
+ distribution_id : The id of the item whose notes we want to retrieve
+ pub : True if all the caller wants are public notes
+ @return An array of note objects
+ /
+);
+
+# TODO: revisit this method to consider replacing cstore direct calls
+sub fetch_notes {
+ my( $self, $connection, $args ) = @_;
+
+ $self->api_name =~ /serial\.(\w*)_note/;
+ my $type = $1;
+
+ my $id = $$args{object_id};
+ my $authtoken = $$args{authtoken};
+ my( $r, $evt);
+
+ if( $$args{pub} ) {
+ return $U->cstorereq(
+ 'open-ils.cstore.direct.serial.'.$type.'_note.search.atomic',
+ { $type => $id, pub => 't' } );
+ } else {
+ # FIXME: restore perm check
+ # ( $r, $evt ) = $U->checksesperm($authtoken, 'VIEW_COPY_NOTES');
+ # return $evt if $evt;
+ return $U->cstorereq(
+ 'open-ils.cstore.direct.serial.'.$type.'_note.search.atomic', {$type => $id} );
+ }
+
+ return undef;
+}
+
+__PACKAGE__->register_method(
+ method => 'create_note',
+ api_name => 'open-ils.serial.item_note.create',
+ signature => q/
+ Creates a new item note
+ @param authtoken The login session key
+ @param note The note object to create
+ @return The id of the new note object
+ /
+);
+
+__PACKAGE__->register_method(
+ method => 'create_note',
+ api_name => 'open-ils.serial.subscription_note.create',
+ signature => q/
+ Creates a new subscription note
+ @param authtoken The login session key
+ @param note The note object to create
+ @return The id of the new note object
+ /
+);
+
+__PACKAGE__->register_method(
+ method => 'create_note',
+ api_name => 'open-ils.serial.distribution_note.create',
+ signature => q/
+ Creates a new distribution note
+ @param authtoken The login session key
+ @param note The note object to create
+ @return The id of the new note object
+ /
+);
+
+sub create_note {
+ my( $self, $connection, $authtoken, $note ) = @_;
+
+ $self->api_name =~ /serial\.(\w*)_note/;
+ my $type = $1;
+
+ my $e = new_editor(xact=>1, authtoken=>$authtoken);
+ return $e->event unless $e->checkauth;
+
+ # FIXME: restore permission support
+# my $item = $e->retrieve_serial_item(
+# [
+# $note->item
+# ]
+# );
+#
+# return $e->event unless
+# $e->allowed('CREATE_COPY_NOTE', $item->call_number->owning_lib);
+
+ $note->create_date('now');
+ $note->creator($e->requestor->id);
+ $note->pub( ($U->is_true($note->pub)) ? 't' : 'f' );
+ $note->clear_id;
+
+ my $method = "create_serial_${type}_note";
+ $e->$method($note) or return $e->event;
+ $e->commit;
+ return $note->id;
+}
+
+__PACKAGE__->register_method(
+ method => 'delete_note',
+ api_name => 'open-ils.serial.item_note.delete',
+ signature => q/
+ Deletes an existing item note
+ @param authtoken The login session key
+ @param noteid The id of the note to delete
+ @return 1 on success - Event otherwise.
+ /
+);
+
+__PACKAGE__->register_method(
+ method => 'delete_note',
+ api_name => 'open-ils.serial.subscription_note.delete',
+ signature => q/
+ Deletes an existing subscription note
+ @param authtoken The login session key
+ @param noteid The id of the note to delete
+ @return 1 on success - Event otherwise.
+ /
+);
+
+__PACKAGE__->register_method(
+ method => 'delete_note',
+ api_name => 'open-ils.serial.distribution_note.delete',
+ signature => q/
+ Deletes an existing distribution note
+ @param authtoken The login session key
+ @param noteid The id of the note to delete
+ @return 1 on success - Event otherwise.
+ /
+);
+
+sub delete_note {
+ my( $self, $conn, $authtoken, $noteid ) = @_;
+
+ $self->api_name =~ /serial\.(\w*)_note/;
+ my $type = $1;
+
+ my $e = new_editor(xact=>1, authtoken=>$authtoken);
+ return $e->die_event unless $e->checkauth;
+
+ my $method = "retrieve_serial_${type}_note";
+ my $note = $e->$method([
+ $noteid,
+ ]) or return $e->die_event;
+
+# FIXME: restore permissions check
+# if( $note->creator ne $e->requestor->id ) {
+# return $e->die_event unless
+# $e->allowed('DELETE_COPY_NOTE', $note->item->call_number->owning_lib);
+# }
+
+ $method = "delete_serial_${type}_note";
+ $e->$method($note) or return $e->die_event;
+ $e->commit;
+ return 1;
+}
+
+
+##########################################################################
+# subscription methods
+#
+__PACKAGE__->register_method(
+ method => 'fleshed_ssub_alter',
+ api_name => 'open-ils.serial.subscription.fleshed.batch.update',
+ api_level => 1,
+ argc => 2,
+ signature => {
+ desc => 'Receives an array of one or more subscriptions and updates the database as needed',
+ 'params' => [ {
+ name => 'authtoken',
+ desc => 'Authtoken for current user session',
+ type => 'string'
+ },
+ {
+ name => 'subscriptions',
+ desc => 'Array of fleshed subscriptions',
+ type => 'array'
+ }
+
+ ],
+ 'return' => {
+ desc => 'Returns 1 if successful, event if failed',
+ type => 'mixed'
+ }
+ }
+);
+
+sub fleshed_ssub_alter {
+ my( $self, $conn, $auth, $ssubs ) = @_;
+ return 1 unless ref $ssubs;
+ my( $reqr, $evt ) = $U->checkses($auth);
+ return $evt if $evt;
+ my $editor = new_editor(requestor => $reqr, xact => 1);
+ my $override = $self->api_name =~ /override/;
+
+# TODO: permission check
+# return $editor->event unless
+# $editor->allowed('UPDATE_COPY', $class->copy_perm_org($vol, $copy));
+
+ for my $ssub (@$ssubs) {
+
+ my $ssubid = $ssub->id;
+
+ if( $ssub->isdeleted ) {
+ $evt = _delete_ssub( $editor, $override, $ssub);
+ } elsif( $ssub->isnew ) {
+ _cleanse_dates($ssub, ['start_date','end_date']);
+ $evt = _create_ssub( $editor, $ssub );
+ } else {
+ _cleanse_dates($ssub, ['start_date','end_date']);
+ $evt = _update_ssub( $editor, $override, $ssub );
+ }
+ }
+
+ if( $evt ) {
+ $logger->info("fleshed subscription-alter failed with event: ".OpenSRF::Utils::JSON->perl2JSON($evt));
+ $editor->rollback;
+ return $evt;
+ }
+ $logger->debug("subscription-alter: done updating subscription batch");
+ $editor->commit;
+ $logger->info("fleshed subscription-alter successfully updated ".scalar(@$ssubs)." subscriptions");
+ return 1;
+}
+
+sub _delete_ssub {
+ my ($editor, $override, $ssub) = @_;
+ $logger->info("subscription-alter: delete subscription ".OpenSRF::Utils::JSON->perl2JSON($ssub));
+ my $sdists = $editor->search_serial_distribution(
+ { subscription => $ssub->id }, { limit => 1 } ); #TODO: 'deleted' support?
+ my $cps = $editor->search_serial_caption_and_pattern(
+ { subscription => $ssub->id }, { limit => 1 } ); #TODO: 'deleted' support?
+ my $sisses = $editor->search_serial_issuance(
+ { subscription => $ssub->id }, { limit => 1 } ); #TODO: 'deleted' support?
+ return OpenILS::Event->new(
+ 'SERIAL_SUBSCRIPTION_NOT_EMPTY', payload => $ssub->id ) if (@$sdists or @$cps or @$sisses);
+
+ return $editor->event unless $editor->delete_serial_subscription($ssub);
+ return 0;
+}
+
+sub _create_ssub {
+ my ($editor, $ssub) = @_;
+
+ $logger->info("subscription-alter: new subscription ".OpenSRF::Utils::JSON->perl2JSON($ssub));
+ return $editor->event unless $editor->create_serial_subscription($ssub);
+ return 0;
+}
+
+sub _update_ssub {
+ my ($editor, $override, $ssub) = @_;
+
+ $logger->info("subscription-alter: retrieving subscription ".$ssub->id);
+ my $orig_ssub = $editor->retrieve_serial_subscription($ssub->id);
+
+ $logger->info("subscription-alter: original subscription ".OpenSRF::Utils::JSON->perl2JSON($orig_ssub));
+ $logger->info("subscription-alter: updated subscription ".OpenSRF::Utils::JSON->perl2JSON($ssub));
+ return $editor->event unless $editor->update_serial_subscription($ssub);
+ return 0;
+}
+
+__PACKAGE__->register_method(
+ method => "fleshed_serial_subscription_retrieve_batch",
+ authoritative => 1,
+ api_name => "open-ils.serial.subscription.fleshed.batch.retrieve"
+);
+
+sub fleshed_serial_subscription_retrieve_batch {
+ my( $self, $client, $ids ) = @_;
+# FIXME: permissions?
+ $logger->info("Fetching fleshed subscriptions @$ids");
+ return $U->cstorereq(
+ "open-ils.cstore.direct.serial.subscription.search.atomic",
+ { id => $ids },
+ { flesh => 1,
+ flesh_fields => {ssub => [ qw/owning_lib notes/ ]}
+ });
+}
+
+__PACKAGE__->register_method(
+ method => "retrieve_sub_tree",
+ authoritative => 1,
+ api_name => "open-ils.serial.subscription_tree.retrieve"
+);
+
+__PACKAGE__->register_method(
+ method => "retrieve_sub_tree",
+ api_name => "open-ils.serial.subscription_tree.global.retrieve"
+);
+
+sub retrieve_sub_tree {
+
+ my( $self, $client, $user_session, $docid, @org_ids ) = @_;
+
+ if(ref($org_ids[0])) { @org_ids = @{$org_ids[0]}; }
+
+ $docid = "$docid";
+
+ # TODO: permission support
+ if(!@org_ids and $user_session) {
+ my $user_obj =
+ OpenILS::Application::AppUtils->check_user_session( $user_session ); #throws EX on error
+ @org_ids = ($user_obj->home_ou);
+ }
+
+ if( $self->api_name =~ /global/ ) {
+ return _build_subs_list( { record_entry => $docid } ); # TODO: filter for !deleted, or active?
+
+ } else {
+
+ my @all_subs;
+ for my $orgid (@org_ids) {
+ my $subs = _build_subs_list(
+ { record_entry => $docid, owning_lib => $orgid } );# TODO: filter for !deleted, or active?
+ push( @all_subs, @$subs );
+ }
+
+ return \@all_subs;
+ }
+
+ return undef;
+}
+
+sub _build_subs_list {
+ my $search_hash = shift;
+
+ #$search_hash->{deleted} = 'f';
+ my $e = new_editor();
+
+ my $subs = $e->search_serial_subscription([$search_hash, { 'order_by' => {'ssub' => 'id'} }]);
+
+ my @built_subs;
+
+ for my $sub (@$subs) {
+
+ # TODO: filter on !deleted?
+ my $dists = $e->search_serial_distribution(
+ [{ subscription => $sub->id }, { 'order_by' => {'sdist' => 'label'} }]
+ );
+
+ #$dists = [ sort { $a->label cmp $b->label } @$dists ];
+
+ $sub->distributions($dists);
+
+ # TODO: filter on !deleted?
+ my $issuances = $e->search_serial_issuance(
+ [{ subscription => $sub->id }, { 'order_by' => {'siss' => 'label'} }]
+ );
+
+ #$issuances = [ sort { $a->label cmp $b->label } @$issuances ];
+ $sub->issuances($issuances);
+
+ # TODO: filter on !deleted?
+ my $scaps = $e->search_serial_caption_and_pattern(
+ [{ subscription => $sub->id }, { 'order_by' => {'scap' => 'id'} }]
+ );
+
+ #$scaps = [ sort { $a->id cmp $b->id } @$scaps ];
+ $sub->scaps($scaps);
+ push( @built_subs, $sub );
+ }
+
+ return \@built_subs;
+
+}
+
+__PACKAGE__->register_method(
+ method => "subscription_orgs_for_title",
+ authoritative => 1,
+ api_name => "open-ils.serial.subscription.retrieve_orgs_by_title"
+);
+
+sub subscription_orgs_for_title {
+ my( $self, $client, $record_id ) = @_;
+
+ my $subs = $U->simple_scalar_request(
+ "open-ils.cstore",
+ "open-ils.cstore.direct.serial.subscription.search.atomic",
+ { record_entry => $record_id }); # TODO: filter on !deleted?
+
+ my $orgs = { map {$_->owning_lib => 1 } @$subs };
+ return [ keys %$orgs ];
+}
+
+
+##########################################################################
+# distribution methods
+#
+__PACKAGE__->register_method(
+ method => 'fleshed_sdist_alter',
+ api_name => 'open-ils.serial.distribution.fleshed.batch.update',
+ api_level => 1,
+ argc => 2,
+ signature => {
+ desc => 'Receives an array of one or more distributions and updates the database as needed',
+ 'params' => [ {
+ name => 'authtoken',
+ desc => 'Authtoken for current user session',
+ type => 'string'
+ },
+ {
+ name => 'distributions',
+ desc => 'Array of fleshed distributions',
+ type => 'array'
+ }
+
+ ],
+ 'return' => {
+ desc => 'Returns 1 if successful, event if failed',
+ type => 'mixed'
+ }
+ }
+);
+
+sub fleshed_sdist_alter {
+ my( $self, $conn, $auth, $sdists ) = @_;
+ return 1 unless ref $sdists;
+ my( $reqr, $evt ) = $U->checkses($auth);
+ return $evt if $evt;
+ my $editor = new_editor(requestor => $reqr, xact => 1);
+ my $override = $self->api_name =~ /override/;
+
+# TODO: permission check
+# return $editor->event unless
+# $editor->allowed('UPDATE_COPY', $class->copy_perm_org($vol, $copy));
+
+ for my $sdist (@$sdists) {
+ my $sdistid = $sdist->id;
+
+ if( $sdist->isdeleted ) {
+ $evt = _delete_sdist( $editor, $override, $sdist);
+ } elsif( $sdist->isnew ) {
+ $evt = _create_sdist( $editor, $sdist );
+ } else {
+ $evt = _update_sdist( $editor, $override, $sdist );
+ }
+ }
+
+ if( $evt ) {
+ $logger->info("fleshed distribution-alter failed with event: ".OpenSRF::Utils::JSON->perl2JSON($evt));
+ $editor->rollback;
+ return $evt;
+ }
+ $logger->debug("distribution-alter: done updating distribution batch");
+ $editor->commit;
+ $logger->info("fleshed distribution-alter successfully updated ".scalar(@$sdists)." distributions");
+ return 1;
+}
+
+sub _delete_sdist {
+ my ($editor, $override, $sdist) = @_;
+ $logger->info("distribution-alter: delete distribution ".OpenSRF::Utils::JSON->perl2JSON($sdist));
+ return $editor->event unless $editor->delete_serial_distribution($sdist);
+ return 0;
+}
+
+sub _create_sdist {
+ my ($editor, $sdist) = @_;
+
+ $logger->info("distribution-alter: new distribution ".OpenSRF::Utils::JSON->perl2JSON($sdist));
+ return $editor->event unless $editor->create_serial_distribution($sdist);
+
+ # create summaries too
+ my $summary = new Fieldmapper::serial::basic_summary;
+ $summary->distribution($sdist->id);
+ $summary->generated_coverage('');
+ return $editor->event unless $editor->create_serial_basic_summary($summary);
+ $summary = new Fieldmapper::serial::supplement_summary;
+ $summary->distribution($sdist->id);
+ $summary->generated_coverage('');
+ return $editor->event unless $editor->create_serial_supplement_summary($summary);
+ $summary = new Fieldmapper::serial::index_summary;
+ $summary->distribution($sdist->id);
+ $summary->generated_coverage('');
+ return $editor->event unless $editor->create_serial_index_summary($summary);
+
+ # create a starter stream (TODO: reconsider this)
+ my $stream = new Fieldmapper::serial::stream;
+ $stream->distribution($sdist->id);
+ return $editor->event unless $editor->create_serial_stream($stream);
+
+ return 0;
+}
+
+sub _update_sdist {
+ my ($editor, $override, $sdist) = @_;
+
+ $logger->info("distribution-alter: retrieving distribution ".$sdist->id);
+ my $orig_sdist = $editor->retrieve_serial_distribution($sdist->id);
+
+ $logger->info("distribution-alter: original distribution ".OpenSRF::Utils::JSON->perl2JSON($orig_sdist));
+ $logger->info("distribution-alter: updated distribution ".OpenSRF::Utils::JSON->perl2JSON($sdist));
+ return $editor->event unless $editor->update_serial_distribution($sdist);
+ return 0;
+}
+
+__PACKAGE__->register_method(
+ method => "fleshed_serial_distribution_retrieve_batch",
+ authoritative => 1,
+ api_name => "open-ils.serial.distribution.fleshed.batch.retrieve"
+);
+
+sub fleshed_serial_distribution_retrieve_batch {
+ my( $self, $client, $ids ) = @_;
+# FIXME: permissions?
+ $logger->info("Fetching fleshed distributions @$ids");
+ return $U->cstorereq(
+ "open-ils.cstore.direct.serial.distribution.search.atomic",
+ { id => $ids },
+ { flesh => 1,
+ flesh_fields => {sdist => [ qw/ holding_lib receive_call_number receive_unit_template bind_call_number bind_unit_template streams / ]}
+ });
+}
+
+##########################################################################
+# caption and pattern methods
+#
+__PACKAGE__->register_method(
+ method => 'scap_alter',
+ api_name => 'open-ils.serial.caption_and_pattern.batch.update',
+ api_level => 1,
+ argc => 2,
+ signature => {
+ desc => 'Receives an array of one or more caption and patterns and updates the database as needed',
+ 'params' => [ {
+ name => 'authtoken',
+ desc => 'Authtoken for current user session',
+ type => 'string'
+ },
+ {
+ name => 'scaps',
+ desc => 'Array of caption and patterns',
+ type => 'array'
+ }
+
+ ],
+ 'return' => {
+ desc => 'Returns 1 if successful, event if failed',
+ type => 'mixed'
+ }
+ }
+);
+
+sub scap_alter {
+ my( $self, $conn, $auth, $scaps ) = @_;
+ return 1 unless ref $scaps;
+ my( $reqr, $evt ) = $U->checkses($auth);
+ return $evt if $evt;
+ my $editor = new_editor(requestor => $reqr, xact => 1);
+ my $override = $self->api_name =~ /override/;
+
+# TODO: permission check
+# return $editor->event unless
+# $editor->allowed('UPDATE_COPY', $class->copy_perm_org($vol, $copy));
+
+ for my $scap (@$scaps) {
+ my $scapid = $scap->id;
+
+ if( $scap->isdeleted ) {
+ $evt = _delete_scap( $editor, $override, $scap);
+ } elsif( $scap->isnew ) {
+ $evt = _create_scap( $editor, $scap );
+ } else {
+ $evt = _update_scap( $editor, $override, $scap );
+ }
+ }
+
+ if( $evt ) {
+ $logger->info("caption_and_pattern-alter failed with event: ".OpenSRF::Utils::JSON->perl2JSON($evt));
+ $editor->rollback;
+ return $evt;
+ }
+ $logger->debug("caption_and_pattern-alter: done updating caption_and_pattern batch");
+ $editor->commit;
+ $logger->info("caption_and_pattern-alter successfully updated ".scalar(@$scaps)." caption_and_patterns");
+ return 1;
+}
+
+sub _delete_scap {
+ my ($editor, $override, $scap) = @_;
+ $logger->info("caption_and_pattern-alter: delete caption_and_pattern ".OpenSRF::Utils::JSON->perl2JSON($scap));
+ my $sisses = $editor->search_serial_issuance(
+ { caption_and_pattern => $scap->id }, { limit => 1 } ); #TODO: 'deleted' support?
+ return OpenILS::Event->new(
+ 'SERIAL_CAPTION_AND_PATTERN_HAS_ISSUANCES', payload => $scap->id ) if (@$sisses);
+
+ return $editor->event unless $editor->delete_serial_caption_and_pattern($scap);
+ return 0;
+}
+
+sub _create_scap {
+ my ($editor, $scap) = @_;
+
+ $logger->info("caption_and_pattern-alter: new caption_and_pattern ".OpenSRF::Utils::JSON->perl2JSON($scap));
+ return $editor->event unless $editor->create_serial_caption_and_pattern($scap);
+ return 0;
+}
+
+sub _update_scap {
+ my ($editor, $override, $scap) = @_;
+
+ $logger->info("caption_and_pattern-alter: retrieving caption_and_pattern ".$scap->id);
+ my $orig_scap = $editor->retrieve_serial_caption_and_pattern($scap->id);
+
+ $logger->info("caption_and_pattern-alter: original caption_and_pattern ".OpenSRF::Utils::JSON->perl2JSON($orig_scap));
+ $logger->info("caption_and_pattern-alter: updated caption_and_pattern ".OpenSRF::Utils::JSON->perl2JSON($scap));
+ return $editor->event unless $editor->update_serial_caption_and_pattern($scap);
+ return 0;
+}
+
+__PACKAGE__->register_method(
+ method => "serial_caption_and_pattern_retrieve_batch",
+ authoritative => 1,
+ api_name => "open-ils.serial.caption_and_pattern.batch.retrieve"
+);
+
+sub serial_caption_and_pattern_retrieve_batch {
+ my( $self, $client, $ids ) = @_;
+ $logger->info("Fetching caption_and_patterns @$ids");
+ return $U->cstorereq(
+ "open-ils.cstore.direct.serial.caption_and_pattern.search.atomic",
+ { id => $ids }
+ );
+}
+
+1;
use DateTime::Format::Strptime;
use Data::Dumper;
+# for inherited methods to work properly, we need to force a
+# MARC::Record version greater than 2.0.0
+use MARC::Record 2.0.1;
use base 'MARC::Record';
use OpenILS::Utils::MFHD::Caption;
return sort keys %{$self->{_mfhd_CAPTIONS}->{$field}};
}
+# optional argument to get back a 'hashref' or an 'array' (default)
sub captions {
my $self = shift;
- my $field = shift;
+ my $tag = shift;
+ my $return_type = shift;
# TODO: add support for caption types as argument? (base, index, supplement)
- my @captions;
- my @sorted_ids = $self->caption_link_ids($field);
+ my @sorted_ids = $self->caption_link_ids($tag);
+
+ if (defined($return_type) and $return_type eq 'hashref') {
+ my %captions;
+ foreach my $link_id (@sorted_ids) {
+ $captions{$link_id} = $self->{_mfhd_CAPTIONS}{$tag}{$link_id};
+ }
+ return \%captions;
+ } else {
+ my @captions;
+ foreach my $link_id (@sorted_ids) {
+ push(@captions, $self->{_mfhd_CAPTIONS}{$tag}{$link_id});
+ }
+ return @captions;
+ }
+}
+
+sub append_fields {
+ my $self = shift;
+
+ my $field_count = $self->SUPER::append_fields(@_);
+ if ($field_count) {
+ foreach my $field (@_) {
+ $self->_avoid_link_collision($field);
+ my $field_type = ref $field;
+ if ($field_type eq 'MFHD::Holding') {
+ $self->{_mfhd_HOLDINGS}{$field->tag}{$field->caption->link_id}{$field->seqno} = $field;
+ } elsif ($field_type eq 'MFHD::Caption') {
+ $self->{_mfhd_CAPTIONS}{$field->tag}{$field->link_id} = $field;
+ }
+ }
+ return $field_count;
+ } else {
+ return;
+ }
+}
+
+sub delete_field {
+ my $self = shift;
+ my $field = shift;
+
+ my $field_count = $self->SUPER::delete_field($field);
+ if ($field_count) {
+ my $field_type = ref($field);
+ if ($field_type eq 'MFHD::Holding') {
+ delete($self->{_mfhd_HOLDINGS}{$field->tag}{$field->caption->link_id}{$field->seqno});
+ } elsif ($field_type eq 'MFHD::Caption') {
+ delete($self->{_mfhd_CAPTIONS}{$field->tag}{$field->link_id});
+ }
+ return $field_count;
+ } else {
+ return;
+ }
+}
+
+sub insert_fields_before {
+ my $self = shift;
+ my $before = shift;
+
+ my $field_count = $self->SUPER::insert_fields_before($before, @_);
+ if ($field_count) {
+ foreach my $field (@_) {
+ $self->_avoid_link_collision($field);
+ my $field_type = ref $field;
+ if ($field_type eq 'MFHD::Holding') {
+ $self->{_mfhd_HOLDINGS}{$field->tag}{$field->caption->link_id}{$field->seqno} = $field;
+ } elsif ($field_type eq 'MFHD::Caption') {
+ $self->{_mfhd_CAPTIONS}{$field->tag}{$field->link_id} = $field;
+ }
+ }
+ return $field_count;
+ } else {
+ return;
+ }
+}
- foreach my $link_id (@sorted_ids) {
- push(@captions, $self->{_mfhd_CAPTIONS}{$field}{$link_id});
+sub insert_fields_after {
+ my $self = shift;
+ my $after = shift;
+
+ my $field_count = $self->SUPER::insert_fields_after($after, @_);
+ if ($field_count) {
+ foreach my $field (@_) {
+ $self->_avoid_link_collision($field);
+ my $field_type = ref $field;
+ if ($field_type eq 'MFHD::Holding') {
+ $self->{_mfhd_HOLDINGS}{$field->tag}{$field->caption->link_id}{$field->seqno} = $field;
+ } elsif ($field_type eq 'MFHD::Caption') {
+ $self->{_mfhd_CAPTIONS}{$field->tag}{$field->link_id} = $field;
+ }
+ }
+ return $field_count;
+ } else {
+ return;
}
+}
- return @captions;
+sub _avoid_link_collision {
+ my $self = shift;
+ my $field = shift;
+
+ my $fieldref = ref($field);
+ if ($fieldref eq 'MFHD::Holding') {
+ my $seqno = $field->seqno;
+ my $changed_seqno = 0;
+ if (exists($self->{_mfhd_HOLDINGS}{$field->tag}{$field->caption->link_id}{$seqno})) {
+ $changed_seqno = 1;
+ do {
+ $seqno++;
+ } while (exists($self->{_mfhd_HOLDINGS}{$field->tag}{$field->caption->link_id}{$seqno}));
+ }
+ $field->seqno($seqno) if $changed_seqno;
+ } elsif ($fieldref eq 'MFHD::Caption') {
+ my $link_id = $field->link_id;
+ my $changed_link_id = 0;
+ if (exists($self->{_mfhd_CAPTIONS}{$field->tag}{$link_id})) {
+ $link_id++;
+ $changed_link_id = 1;
+ do {
+ $link_id++;
+ } while (exists($self->{_mfhd_CAPTIONS}{$field->tag}{$link_id}));
+ }
+ $field->link_id($link_id) if $changed_link_id;
+ }
}
sub active_captions {
my $self = shift;
- my $field = shift;
+ my $tag = shift;
- # TODO: add support for caption types as argument? (base, index, supplement)
+ # TODO: add support for caption types as argument? (basic, index, supplement)
my @captions;
my @active_captions;
- @captions = $self->captions($field);
+ @captions = $self->captions($tag);
# TODO: for now, we will assume the last 85X field is active
# and the rest are historical. The standard is hazy about
}
#
-# generate_predictions() is an initial attempt at a function which can be used
-# to populate an issuance table with a list of predicted issues. It accepts
-# a hash ref of options initially defined as:
-# field : the caption field to predict on (853, 854, or 855)
+# generate_predictions()
+# Accepts a hash ref of options initially defined as:
+# base_holding : reference to the holding field to predict from
# num_to_predict : the number of issues you wish to predict
-# last_rec_date : the date of the last received issue, to be used as an offset
-# for predicting future issues
+# OR
+# end_holding : holding field ref, keep predicting until you meet or exceed it
#
# The basic method is to first convert to a single holding if compressed, then
# increment the holding and save the resulting values to @predictions.
#
-# returns @preditions, an array of array refs containing (link id, formatted
-# label, formatted chronology date, formatted estimated arrival date, and an
-# array ref of holding subfields as (key, value, key, value ...)) (not a hash
-# to protect order and possible duplicate keys).
-#
+# returns @predictions, an array of holding field refs (including end_holding
+# if applicable but NOT base_holding)
+#
sub generate_predictions {
my ($self, $options) = @_;
- my $field = $options->{field};
- my $num_to_predict = $options->{num_to_predict};
- my $last_rec_date =
- $options->{last_rec_date}; # expected or actual, according to preference
- # TODO: add support for predicting serials with no chronology by passing in
- # a last_pub_date option?
+ my $base_holding = $options->{base_holding};
+ my $num_to_predict = $options->{num_to_predict};
+ my $end_holding = $options->{end_holding};
+ my $max_to_predict = $options->{max_to_predict} || 10000; # fail-safe
- my $strp = new DateTime::Format::Strptime(pattern => '%F');
+ if (!defined($base_holding)) {
+ carp("Base holding not defined in generate_predictions, returning empty set");
+ return ();
+ }
+ if ($base_holding->is_compressed) {
+ carp("Ambiguous compressed base holding in generate_predictions, returning empty set");
+ return ();
+ }
+ my $curr_holding = $base_holding->clone; # prevent side-effects
+
+ my @predictions;
+
+ if ($num_to_predict) {
+ for (my $i = 0; $i < $num_to_predict; $i++) {
+ push(@predictions, $curr_holding->increment->clone);
+ }
+ } elsif (defined($end_holding)) {
+ $end_holding = $end_holding->clone; # prevent side-effects
+ my $next_holding = $curr_holding->increment->clone;
+ my $num_predicted = 0;
+ while ($next_holding le $end_holding) {
+ push(@predictions, $next_holding);
+ $num_predicted++;
+ if ($num_predicted >= $max_to_predict) {
+ carp("Maximum prediction count exceeded");
+ last;
+ }
+ $next_holding = $curr_holding->increment->clone;
+ }
+ }
- my $receival_date = $strp->parse_datetime($last_rec_date);
+ return @predictions;
+}
- my @active_captions = $self->active_captions($field);
+#
+# create an array of compressed holdings from all holdings for a given caption,
+# compressing as needed
+#
+# Optionally you can skip sorting, but the resulting compression will be compromised
+# if the current holdings are out of order
+#
+# TODO: gap marking, gap preservation
+#
+# TODO: some of this could be moved to the Caption object to allow for
+# decompression in the absense of an overarching MFHD object
+#
+sub get_compressed_holdings {
+ my $self = shift;
+ my $caption = shift;
+ my $opts = shift;
+ my $skip_sort = $opts->{'skip_sort'};
+
+ # make sure none are compressed
+ my @decomp_holdings;
+ if ($skip_sort) {
+ @decomp_holdings = $self->get_decompressed_holdings($caption, {'skip_sort' => 1});
+ } else {
+ # sort for best algorithm
+ @decomp_holdings = $self->get_decompressed_holdings($caption, {'dedupe' => 1});
+ }
- my @predictions;
- foreach my $caption (@active_captions) {
- my $htag = $caption->tag;
- my $link_id = $caption->link_id;
- $htag =~ s/^85/86/;
- my @holdings = $self->holdings($htag, $link_id);
- my $last_holding = $holdings[-1];
-
- if ($last_holding->is_compressed) {
- $last_holding->compressed_to_last; # convert to last in range
+ my $runner = $decomp_holdings[0]->clone->increment;
+ my $curr_holding = shift(@decomp_holdings);
+ $curr_holding = $curr_holding->clone;
+ my $seqno = 1;
+ $curr_holding->seqno($seqno);
+ my @comp_holdings;
+# my $last_holding;
+ foreach my $holding (@decomp_holdings) {
+ if ($runner eq $holding) {
+ $curr_holding->extend;
+ $runner->increment;
+# } elsif ($holding eq $last_holding) {
+# carp("Found duplicate holding in compression set, skipping");
+ } elsif ($runner gt $holding) { # should not happen unless holding is not in series
+ carp("Found unexpected holding, skipping");
+ } else {
+ push(@comp_holdings, $curr_holding);
+ while ($runner le $holding) {
+ $runner->increment;
+ }
+ $curr_holding = $holding->clone;
+ $seqno++;
+ $curr_holding->seqno($seqno);
}
+# $last_holding = $holding;
+ }
+ push(@comp_holdings, $curr_holding);
- my $pub_date = $strp->parse_datetime($last_holding->chron_to_date);
- my $date_diff = $receival_date - $pub_date;
+ return @comp_holdings;
+}
+
+#
+# create an array of single holdings from all holdings for a given caption,
+# decompressing as needed
+#
+# resulting array is returned as they come in the record, unsorted
+#
+# optional argument will reorder and renumber the holdings before returning
+#
+# TODO: some of this could be moved to the Caption (and/or Holding) object to
+# allow for decompression in the absense of an overarching MFHD object
+#
+sub get_decompressed_holdings {
+ my $self = shift;
+ my $caption = shift;
+ my $opts = shift;
+ my $skip_sort = $opts->{'skip_sort'};
+ my $dedupe = $opts->{'dedupe'};
- $last_holding->notes('public', []);
- # add a note marker for system use
- $last_holding->notes('private', ['AUTOGEN']);
+ if ($dedupe and $skip_sort) {
+ carp("Attempted deduplication without sorting, failure likely");
+ }
- for (my $i = 0; $i < $num_to_predict; $i++) {
- $last_holding->increment;
- $pub_date = $strp->parse_datetime($last_holding->chron_to_date);
- my $arrival_date = $pub_date + $date_diff;
- push(
- @predictions,
- [
- $link_id,
- $last_holding->format,
- $pub_date->strftime('%F'),
- $arrival_date->strftime('%F'),
- [$last_holding->subfields_list]
- ]
- );
+ my $htag = $caption->tag;
+ my $link_id = $caption->link_id;
+ $htag =~ s/^85/86/;
+ my @holdings = $self->holdings($htag, $link_id);
+ my @decomp_holdings;
+
+ foreach my $holding (@holdings) {
+ if (!$holding->is_compressed) {
+ push(@decomp_holdings, $holding->clone);
+ } else {
+ my $base_holding = $holding->clone->compressed_to_first;
+ my @new_holdings = $self->generate_predictions(
+ {'base_holding' => $base_holding,
+ 'end_holding' => $holding->clone->compressed_to_last});
+ push(@decomp_holdings, $base_holding, @new_holdings);
}
}
- return @predictions;
+
+ unless ($skip_sort) {
+ my @temp_holdings = sort {$a cmp $b} @decomp_holdings;
+ @decomp_holdings = @temp_holdings;
+ }
+
+ my @return_holdings = (shift(@decomp_holdings));
+ $return_holdings[0]->seqno(1);
+ my $seqno = 2;
+ foreach my $holding (@decomp_holdings) { # renumber sequence
+ if ($holding eq $return_holdings[-1] and $dedupe) {
+ carp("Found duplicate holding in decompression set, discarding");
+ next;
+ }
+ $holding->seqno($seqno);
+ $seqno++;
+ push(@return_holdings, $holding);
+ }
+
+ return @return_holdings;
}
#
my ($key, $val) = @$subfield;
if ($key =~ /[a-m]/) {
+ if (exists($self->{_mfhdh_FIELDS}->{$key})) {
+ carp("Duplicate, non-repeatable subfield '$key' found, ignoring");
+ next;
+ }
if ($self->{_mfhdh_COMPRESSED}) {
$self->{_mfhdh_FIELDS}->{$key}{HOLDINGS} = [split(/\-/, $val)];
} else {
# Replace a single holding with it's next prediction
# and return itself
#
-# If the holding is compressed, the range is expanded
-#
sub increment {
my $self = shift;
if ($self->is_open_ended) {
carp "Holding is open-ended, cannot increment";
return $self;
+ } elsif ($self->is_compressed) {
+ carp "Incrementing a compressed holding is deprecated, use extend instead";
+ return $self->extend;
}
my $next = $self->next();
- if ($self->is_compressed) { # expand range
- foreach my $key (keys %{$next}) {
- my @values = @{$self->field_values($key)};
- $values[1] = $next->{$key};
- $self->fields->{$key}{HOLDINGS} = \@values;
- $next->{$key} = join('-', @values);
- }
- } else {
- foreach my $key (keys %{$next}) {
- $self->fields->{$key}{HOLDINGS}[0] = $next->{$key};
- }
+ foreach my $key (keys %{$next}) {
+ $self->fields->{$key}{HOLDINGS}[0] = $next->{$key};
}
$self->seqno($self->seqno + 1);
}
#
+# Extends a holding (compressing if needed) to include the next
+# prediction and returns itself
+#
+sub extend {
+ my $self = shift;
+
+ if ($self->is_open_ended) {
+ carp "Holding is open-ended, cannot extend";
+ return $self;
+ }
+
+ my $next = $self->next();
+
+ if (!$self->is_compressed) {
+ $self->is_compressed(1); # add compressed state
+ }
+
+ foreach my $key (keys %{$next}) {
+ my @values = @{$self->field_values($key)};
+ $values[1] = $next->{$key};
+ $self->fields->{$key}{HOLDINGS} = \@values;
+ $next->{$key} = join('-', @values);
+ }
+
+ $self->update(%{$next}); # update underlying subfields
+ return $self;
+}
+
+#
+# Turns a compressed holding into the singular form of the first member
+# in the range
+#
+sub compressed_to_first {
+ my $self = shift;
+
+ if (!$self->is_compressed) {
+ carp "Holding not compressed, cannot convert to first member";
+ return $self;
+ }
+
+ my %changes;
+ foreach my $key (keys %{$self->fields}) {
+ my @values = @{$self->field_values($key)};
+ $self->fields->{$key}{HOLDINGS} = [$values[0]];
+ $changes{$key} = $values[0];
+ }
+
+ $self->update(%changes); # update underlying subfields
+ $self->is_compressed(0); # remove compressed state
+
+ return $self;
+}
+
+#
# Turns a compressed holding into the singular form of the last member
# in the range
#
my @parts = split('/', $combo);
return $parts[$pos];
}
+
+#
+# Overload string comparison operators
+#
+# We are not overloading '<=>' because '==' is used liberally in MARC::Record
+# to compare field identity (i.e. is this the same exact Field object?), not value
+#
+# Other string operators are auto-generated from 'cmp'
+#
+# Please note that this comparison is based on what the holding represents,
+# not whether it is strictly identical (e.g. the seqno and link may vary)
+#
+use overload ('cmp' => \&_compare,
+ 'fallback' => 1);
+sub _compare {
+ my ($holding_1, $holding_2) = @_;
+
+ # TODO: this needs some more consideration
+ # fall back to 'built-in' comparison
+ if (!UNIVERSAL::isa($holding_2, ref $holding_1)) {
+ if (defined $holding_2) {
+ carp("Use of non-holding in holding comparison operation");
+ return ( "$holding_1" cmp "$holding_2" );
+ } else {
+ carp("Use of undefined value in holding comparison operation");
+ return 1; # similar to built-in, something is "greater than" nothing
+ }
+ }
+
+ # special cases for compressed holdings
+ my ($holding_1_first, $holding_1_last, $holding_2_first, $holding_2_last, $found_compressed);
+ # 0 for no compressed, 1 for first compressed, 2 for second compressed, 3 for both compressed
+ $found_compressed = 0;
+ if ($holding_1->is_compressed) {
+ $holding_1_last = $holding_1->clone->compressed_to_last;
+ $found_compressed += 1;
+ } else {
+ $holding_1_first = $holding_1;
+ $holding_1_last = $holding_1;
+ }
+ if ($holding_2->is_compressed) {
+ $holding_2_first = $holding_2->clone->compressed_to_first;
+ $found_compressed += 2;
+ } else {
+ $holding_2_first = $holding_2;
+ $holding_2_last = $holding_2;
+ }
+
+ if ($found_compressed) {
+ my $cmp = ($holding_1_last cmp $holding_2_first); # 1 ends before 2 starts
+ if ($cmp == -1) {
+ return -1; # 1 is fully lt
+ } elsif ($cmp == 0) {
+ carp("Overlapping holdings in comparison, lt and gt based on start value only");
+ return -1;
+ } else { # check the opposite, 2 ends before 1 starts
+ # clone is expensive, wait until we need it (here)
+ if (!defined($holding_2_last)) {
+ $holding_2_last = $holding_2->clone->compressed_to_last;
+ }
+ if (!defined($holding_1_first)) {
+ $holding_1_first = $holding_1->clone->compressed_to_first;
+ }
+ $cmp = ($holding_2_last cmp $holding_1_first);
+ if ($cmp == -1) {
+ return 1; # 1 is fully gt
+ } elsif ($cmp == 0) {
+ carp("Overlapping holdings in comparison, lt and gt based on start value only");
+ return 1;
+ } else {
+ $cmp = ($holding_1_first cmp $holding_2_first);
+ if (!$cmp) { # they are not equal
+ carp("Overlapping holdings in comparison, lt and gt based on start value only");
+ return $cmp;
+ } elsif ($found_compressed == 1) {
+ carp("Compressed holding found with start equal to non-compressed holding");
+ return 1; # compressed (first holding) is 'greater than' non-compressed
+ } elsif ($found_compressed == 2) {
+ carp("Compressed holding found with start equal to non-compressed holding");
+ return -1; # compressed (second holding) is 'greater than' non-compressed
+ } else { # both holdings compressed, check for full equality
+ $cmp = ($holding_1_last cmp $holding_2_last);
+ if (!$cmp) { # they are not equal
+ carp("Compressed holdings in comparison have equal starts, lt and gt based on end value only");
+ return $cmp;
+ } else {
+ return 0; # both are compressed, both ends are equal
+ }
+ }
+ }
+ }
+ }
+
+ # start doing the actual comparison
+ my $result;
+ foreach my $key ('a'..'f') {
+ if (defined($holding_1->field_values($key))) {
+ if (!defined($holding_2->field_values($key))) {
+ return 1; # more details equals 'greater' (?)
+ } else {
+ $result = $holding_1->field_values($key)->[0] <=> $holding_2->field_values($key)->[0];
+ }
+ } elsif (defined($holding_2->field_values($key))) {
+ return -1; # more details equals 'greater' (?)
+ }
+
+ return $result if $result;
+ }
+
+ # got through, return 0 for equal
+ return 0;
+}
+
1;
$field = MARC::Field->new(
$fieldno, $inds[0], $inds[1],
- a => 'scratch',
@subfields
);
my $marc;
my $mfhd;
- my $location = '';
- my $holdings = [];
- my $supplements = [];
- my $indexes = [];
- my $current_holdings = [];
- my $current_supplements = [];
- my $current_indexes = [];
- my $online = []; # Laurentian extension to MFHD standard
- my $missing = []; # Laurentian extension to MFHD standard
- my $incomplete = []; # Laurentian extension to MFHD standard
+ my $location = '';
+ my $basic_holdings = [];
+ my $supplement_holdings = [];
+ my $index_holdings = [];
+ my $basic_holdings_add = [];
+ my $supplement_holdings_add = [];
+ my $index_holdings_add = [];
+ my $online = []; # Laurentian extension to MFHD standard
+ my $missing = []; # Laurentian extension to MFHD standard
+ my $incomplete = []; # Laurentian extension to MFHD standard
try {
$marc = MARC::Record->new_from_xml($mfhd_xml);
$location =~ s/ -- $//;
+ # TODO: for now, we will assume that textual holdings are in addition to the
+ # computable holdings (that is, they have link IDs greater than the 85X fields)
+ # or that they fully replace the computable holdings (checking for link ID '0').
+ # Eventually this may be handled better by format_holdings() in MFHD.pm
+ my %skip_computable;
try {
foreach my $field ($marc->field('866')) {
my $textual_holdings = $self->format_textual_holdings($field);
if ($textual_holdings) {
- push @$holdings, $textual_holdings;
+ push @$basic_holdings_add, $textual_holdings;
+ if ($field->subfield('8') eq '0') {
+ $skip_computable{'basic'} = 1; # link ID 0 trumps computable fields
+ }
}
}
foreach my $field ($marc->field('867')) {
my $textual_holdings = $self->format_textual_holdings($field);
if ($textual_holdings) {
- push @$supplements, $textual_holdings;
+ push @$supplement_holdings_add, $textual_holdings;
+ if ($field->subfield('8') eq '0') {
+ $skip_computable{'supplement'} = 1; # link ID 0 trumps computable fields
+ }
}
}
foreach my $field ($marc->field('868')) {
my $textual_holdings = $self->format_textual_holdings($field);
if ($textual_holdings) {
- push @$indexes, $textual_holdings;
+ push @$index_holdings_add, $textual_holdings;
+ if ($field->subfield('8') eq '0') {
+ $skip_computable{'index'} = 1; # link ID 0 trumps computable fields
+ }
}
}
- foreach my $cap_id ($mfhd->caption_link_ids('853')) {
- my @curr_holdings = $mfhd->holdings('863', $cap_id);
- next unless scalar @curr_holdings;
- foreach (@curr_holdings) {
- push @$current_holdings, $_->format();
+ if (!exists($skip_computable{'basic'})) {
+ foreach my $cap_id ($mfhd->caption_link_ids('853')) {
+ my @holdings = $mfhd->holdings('863', $cap_id);
+ next unless scalar @holdings;
+ foreach (@holdings) {
+ push @$basic_holdings, $_->format();
+ }
}
+ if (!@$basic_holdings) { # no computed holdings found
+ $basic_holdings = $basic_holdings_add;
+ $basic_holdings_add = [];
+ }
+ } else { # textual are non additional, but primary
+ $basic_holdings = $basic_holdings_add;
+ $basic_holdings_add = [];
}
- foreach my $cap_id ($mfhd->caption_link_ids('854')) {
- my @curr_supplements = $mfhd->holdings('864', $cap_id);
- next unless scalar @curr_supplements;
- foreach (@curr_supplements) {
- push @$current_supplements, $_->format();
+ if (!exists($skip_computable{'supplement'})) {
+ foreach my $cap_id ($mfhd->caption_link_ids('854')) {
+ my @supplements = $mfhd->holdings('864', $cap_id);
+ next unless scalar @supplements;
+ foreach (@supplements) {
+ push @$supplement_holdings, $_->format();
+ }
+ }
+ if (!@$supplement_holdings) { # no computed holdings found
+ $supplement_holdings = $supplement_holdings_add;
+ $supplement_holdings_add = [];
}
+ } else { # textual are non additional, but primary
+ $supplement_holdings = $supplement_holdings_add;
+ $supplement_holdings_add = [];
}
- foreach my $cap_id ($mfhd->caption_link_ids('855')) {
- my @curr_indexes = $mfhd->holdings('865', $cap_id);
- next unless scalar @curr_indexes;
- foreach (@curr_indexes) {
- push @$current_indexes, $_->format();
+ if (!exists($skip_computable{'index'})) {
+ foreach my $cap_id ($mfhd->caption_link_ids('855')) {
+ my @indexes = $mfhd->holdings('865', $cap_id);
+ next unless scalar @indexes;
+ foreach (@indexes) {
+ push @$index_holdings, $_->format();
+ }
+ }
+ if (!@$index_holdings) { # no computed holdings found
+ $index_holdings = $index_holdings_add;
+ $index_holdings_add = [];
}
+ } else { # textual are non additional, but primary
+ $index_holdings = $index_holdings_add;
+ $index_holdings_add = [];
}
# Laurentian extensions
};
return {
- location => $location,
- holdings => $holdings,
- current_holdings => $current_holdings,
- supplements => $supplements,
- current_supplements => $current_supplements,
- indexes => $indexes,
- current_indexes => $current_indexes,
- missing => $missing,
- incomplete => $incomplete,
+ location => $location,
+ basic_holdings => $basic_holdings,
+ basic_holdings_add => $basic_holdings_add,
+ supplement_holdings => $supplement_holdings,
+ supplement_holdings_add => $supplement_holdings_add,
+ index_holdings => $index_holdings,
+ index_holdings_add => $index_holdings_add,
+ missing => $missing,
+ incomplete => $incomplete,
+ online => $online
};
}
sub init_holdings_virtual_record {
my $record = Fieldmapper::serial::virtual_record->new;
- $record->id();
+ $record->sre_id();
$record->location();
$record->owning_lib();
- $record->holdings([]);
- $record->current_holdings([]);
- $record->supplements([]);
- $record->current_supplements([]);
- $record->indexes([]);
- $record->current_indexes([]);
+ $record->basic_holdings([]);
+ $record->basic_holdings_add([]);
+ $record->supplement_holdings([]);
+ $record->supplement_holdings_add([]);
+ $record->index_holdings([]);
+ $record->index_holdings_add([]);
$record->online([]);
$record->missing([]);
$record->incomplete([]);
my $record = init_holdings_virtual_record();
my $holdings = $self->mfhd_to_hash($mfhd);
- $record->id($id);
+ $record->sre_id($id);
$record->owning_lib($owning_lib);
if (!$holdings) {
}
$record->location($holdings->{location});
- $record->holdings($holdings->{holdings});
- $record->current_holdings($holdings->{current_holdings});
- $record->supplements($holdings->{supplements});
- $record->current_supplements($holdings->{current_supplements});
- $record->indexes($holdings->{indexes});
- $record->current_indexes($holdings->{current_indexes});
+ $record->basic_holdings($holdings->{basic_holdings});
+ $record->basic_holdings_add($holdings->{basic_holdings_add});
+ $record->supplement_holdings($holdings->{supplement_holdings});
+ $record->supplement_holdings_add($holdings->{supplement_holdings_add});
+ $record->index_holdings($holdings->{index_holdings});
+ $record->index_holdings_add($holdings->{index_holdings_add});
$record->online($holdings->{online});
$record->missing($holdings->{missing});
$record->incomplete($holdings->{incomplete});
install_date TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
);
-INSERT INTO config.upgrade_log (version) VALUES ('0370'); -- miker
+INSERT INTO config.upgrade_log (version) VALUES ('0371'); -- senator
CREATE TABLE config.bib_source (
id SERIAL PRIMARY KEY,
--- /dev/null
+-- If these two fail, they're already renamed (DB built after 0352), so
+-- we're good.
+ALTER SEQUENCE serial.sup_summary_id_seq RENAME TO supplement_summary_id_seq;
+ALTER SEQUENCE serial.bib_summary_id_seq RENAME TO basic_summary_id_seq;
+
+BEGIN; -- but we still need to consume an upgrade number :-/
+
+INSERT INTO config.upgrade_log (version) VALUES ('0371'); -- senator
+
+COMMIT;
"EDIT_MFHD_RECORD": "Edit Record",
"EDIT_MFHD_MENU": "Edit Holdings",
"EDIT_PROPERTIES": "Edit Propeties",
- "HOLDINGS": "Previous volumes",
- "INDEXES": "Previous indexes",
+ "BASIC_HOLDINGS": "Volumes",
+ "BASIC_HOLDINGS_ADD": "Additional Volume Information",
+ "INDEX_HOLDINGS": "Indexes",
+ "INDEX_HOLDINGS_ADD": "Additional Index Information",
"CURRENT_HOLDINGS": "Current volume",
"CURRENT_INDEXES": "Current indexes",
"CURRENT_SUPPLEMENTS": "Current supplements",
"MISSING_VOLUMES": "Missing volumes",
"ONLINE_VOLUMES": "Online volumes",
"SAVE_MFHD_LABEL": "Save MFHD",
- "SUPPLEMENTS": "Previous supplements"
+ "SUPPLEMENT_HOLDINGS": "Supplements",
+ "SUPPLEMENT_HOLDINGS_ADD": "Additional Supplement Information"
}
<!ENTITY staff.record_list.title "Title">
<!ENTITY staff.record_list.win_title "Cataloging">
<!ENTITY staff.retrieving.record "Retrieving...">
+<!ENTITY staff.serial.mfhd_menu.label "MFHD Holdings">
+<!ENTITY staff.serial.mfhd_menu.add.label "Add MFHD Record">
+<!ENTITY staff.serial.mfhd_menu.edit.label "Edit MFHD Record">
+<!ENTITY staff.serial.mfhd_menu.delete.label "Delete MFHD Record">
+<!ENTITY staff.serial.scap_editor.modify "Modify Caption and Pattern(s)">
+<!ENTITY staff.serial.scap_editor.modify.accesskey "M">
+<!ENTITY staff.serial.scap_editor.create "Create Caption and Pattern(s)">
+<!ENTITY staff.serial.scap_editor.create.accesskey "C">
+<!ENTITY staff.serial.scap_editor.notes "Caption and Pattern Notes">
+<!ENTITY staff.serial.scap_editor.notes.accesskey "N">
+<!ENTITY staff.serial.sdist_editor.modify "Modify Distribution(s)">
+<!ENTITY staff.serial.sdist_editor.modify.accesskey "M">
+<!ENTITY staff.serial.sdist_editor.create "Create Distribution(s)">
+<!ENTITY staff.serial.sdist_editor.create.accesskey "C">
+<!ENTITY staff.serial.sdist_editor.notes "Distribution Notes">
+<!ENTITY staff.serial.sdist_editor.notes.accesskey "N">
+<!ENTITY staff.serial.serctrl_view.label "Serial Control View">
+<!ENTITY staff.serial.siss_editor.modify "Modify Issuance(s)">
+<!ENTITY staff.serial.siss_editor.modify.accesskey "M">
+<!ENTITY staff.serial.siss_editor.create "Create Issuance(s)">
+<!ENTITY staff.serial.siss_editor.create.accesskey "C">
+<!ENTITY staff.serial.siss_editor.notes "Issuance Notes">
+<!ENTITY staff.serial.siss_editor.notes.accesskey "N">
+<!ENTITY staff.serial.sitem_editor.modify "Modify Item(s)">
+<!ENTITY staff.serial.sitem_editor.modify.accesskey "M">
+<!ENTITY staff.serial.sitem_editor.create "Create Item(s)">
+<!ENTITY staff.serial.sitem_editor.create.accesskey "C">
+<!ENTITY staff.serial.sitem_editor.notes "Item Notes">
+<!ENTITY staff.serial.sitem_editor.notes.accesskey "N">
+<!ENTITY staff.serial.ssub_editor.modify "Modify Subscription(s)">
+<!ENTITY staff.serial.ssub_editor.modify.accesskey "M">
+<!ENTITY staff.serial.ssub_editor.create "Create Subscription(s)">
+<!ENTITY staff.serial.ssub_editor.create.accesskey "C">
+<!ENTITY staff.serial.ssub_editor.notes "Subscription Notes">
+<!ENTITY staff.serial.ssub_editor.notes.accesskey "N">
<!ENTITY staff.survey.wizard.page1 "Initial Settings">
<!ENTITY staff.survey.wizard.page2 "Add Questions for Survey:">
<!ENTITY staff.survey.wizard.title "Add a Survey Wizard">
var rdetailStart = null;
var rdetailEnd = null;
+var mfhdDetails = [];
+
/* serials are currently the only use of Dojo strings in the OPAC */
if (rdetailDisplaySerialHoldings) {
dojo.require("dijit.Menu");
dojo.forEach(holdings, _holdingsDrawMFHD);
+ // Populate XUL menus
+ if (isXUL()) {
+ runEvt('rdetail','MFHDDrawn');
+ }
}
function _holdingsDrawMFHD(holdings, entryNum) {
}
}
- var hh = holdings.holdings();
- var hch = holdings.current_holdings();
- var hs = holdings.supplements();
- var hcs = holdings.current_supplements();
- var hi = holdings.indexes();
- var hci = holdings.current_indexes();
+ var hb = holdings.basic_holdings();
+ var hba = holdings.basic_holdings_add();
+ var hs = holdings.supplement_holdings();
+ var hsa = holdings.supplement_holdings_add();
+ var hi = holdings.index_holdings();
+ var hia = holdings.index_holdings_add();
var ho = holdings.online();
var hm = holdings.missing();
var hinc = holdings.incomplete();
var hloc = holdings.location() || 'MFHD';
- if ( hh.length == 0 && hch.length == 0 && hs.length == 0 &&
- hcs.length == 0 && hi.length == 0 && hci.length == 0 &&
+ if ( hb.length == 0 && hba.length == 0 && hs.length == 0 &&
+ hsa.length == 0 && hi.length == 0 && hia.length == 0 &&
ho.length == 0 && hm.length == 0 && hinc.length == 0
) {
* record is likely empty or corrupt. This gives cataloguers a
* chance to add holdings or correct the record
*/
- hh = 'PLACEHOLDER';
+ hb = ['PLACEHOLDER'];
} else {
return null;
}
}
- dojo.place("<table style='width: 100%;'><caption id='mfhdHoldingsCaption" + entryNum + "' class='rdetail_header color_1'>" +
- dojo.string.substitute(opac_strings.HOLDINGS_TABLE_CAPTION, [hloc]) +
+ // Show entryNum + 1 in staff client for better menu correlation
+ // Maybe this should be holdings.sre_id() instead? (which could get long after time)
+ var entryNumString = '';
+ if (isXUL()) {
+ var entryNumInc = entryNum + 1;
+ entryNumString = ' [Entry #'+entryNumInc+'] ';
+ }
+
+ var refNode;
+ if (entryNum > 0) {
+ refNode = 'rdetail_holdings_table_' + (entryNum - 1);
+ } else {
+ refNode = 'rdetail_details_table';
+ }
+
+ dojo.place("<table style='width: 100%;' id='rdetail_holdings_table_"+entryNum+"'><caption id='mfhdHoldingsCaption" + entryNum + "' class='rdetail_header color_1'>" +
+ dojo.string.substitute(opac_strings.HOLDINGS_TABLE_CAPTION, [hloc]) + entryNumString +
"</caption><tbody id='rdetail_holdings_tbody_" + entryNum +
- "'></tbody></table>", "rdetail_details_table", "after"
+ "'></tbody></table>", refNode, "after"
);
- if (hh.length > 0) { _holdingsDrawMFHDEntry(entryNum, opac_strings.HOLDINGS, hh); }
- if (hch.length > 0) { _holdingsDrawMFHDEntry(entryNum, opac_strings.CURRENT_HOLDINGS, hch); }
- if (hs.length > 0) { _holdingsDrawMFHDEntry(entryNum, opac_strings.SUPPLEMENTS, hs); }
- if (hcs.length > 0) { _holdingsDrawMFHDEntry(entryNum, opac_strings.CURRENT_SUPPLEMENTS, hcs); }
- if (hi.length > 0) { _holdingsDrawMFHDEntry(entryNum, opac_strings.INDEXES, hi); }
- if (hci.length > 0) { _holdingsDrawMFHDEntry(entryNum, opac_strings.CURRENT_INDEXES, hci); }
+ if (hb.length > 0) { _holdingsDrawMFHDEntry(entryNum, opac_strings.BASIC_HOLDINGS, hb); }
+ if (hba.length > 0) { _holdingsDrawMFHDEntry(entryNum, opac_strings.BASIC_HOLDINGS_ADD, hba); }
+ if (hs.length > 0) { _holdingsDrawMFHDEntry(entryNum, opac_strings.SUPPLEMENT_HOLDINGS, hs); }
+ if (hsa.length > 0) { _holdingsDrawMFHDEntry(entryNum, opac_strings.SUPPLEMENT_HOLDINGS_ADD, hsa); }
+ if (hi.length > 0) { _holdingsDrawMFHDEntry(entryNum, opac_strings.INDEX_HOLDINGS, hi); }
+ if (hia.length > 0) { _holdingsDrawMFHDEntry(entryNum, opac_strings.INDEX_HOLDINGS_ADD, hia); }
if (ho.length > 0) { _holdingsDrawMFHDEntry(entryNum, opac_strings.ONLINE_VOLUMES, ho); }
if (hm.length > 0) { _holdingsDrawMFHDEntry(entryNum, opac_strings.MISSING_VOLUMES, hm); }
if (hinc.length > 0) { _holdingsDrawMFHDEntry(entryNum, opac_strings.INCOMPLETE_VOLUMES, hinc); }
if (isXUL()) {
+ mfhdDetails.push({ 'id' : holdings.sre_id(), 'label' : hloc, 'entryNum' : entryNum, 'owning_lib' : holdings.owning_lib() });
dojo.require('openils.Event');
dojo.require('openils.PermaCrud');
var mfhd_edit = new dijit.Menu({});
- new dijit.MenuItem({onClick: function(){loadMarcEditor(holdings.id())}, label:opac_strings.EDIT_MFHD_RECORD}).placeAt(mfhd_edit, "first");
+ new dijit.MenuItem({onClick: function(){loadMarcEditor(holdings.sre_id())}, label:opac_strings.EDIT_MFHD_RECORD}).placeAt(mfhd_edit, "first");
new dijit.MenuItem({onClick:function(){
var pcrud = new openils.PermaCrud({"authtoken": G.user.session});
- var mfhd_rec = pcrud.retrieve("sre", holdings.id());
+ var mfhd_rec = pcrud.retrieve("sre", holdings.sre_id());
if (mfhd_rec) {
pcrud.eliminate(mfhd_rec);
- alert(dojo.string.substitute(opac_strings.DELETED_MFHD_RECORD, [holdings.id()]));
+ alert(dojo.string.substitute(opac_strings.DELETED_MFHD_RECORD, [holdings.sre_id()]));
}
}, label:opac_strings.DELETE_MFHD}).placeAt(mfhd_edit, "last");
- // new dijit.MenuItem({onClick:function(){alert("Edit properties " + holdings.id());}, label:opac_strings.EDIT_PROPERTIES}).placeAt(mfhd_edit, "last");
+ // new dijit.MenuItem({onClick:function(){alert("Edit properties " + holdings.sre_id());}, label:opac_strings.EDIT_PROPERTIES}).placeAt(mfhd_edit, "last");
var mfhd_mb = new dijit.form.DropDownButton({dropDown: mfhd_edit, label:opac_strings.EDIT_MFHD_MENU, style:"float:right"});
mfhd_mb.placeAt("mfhdHoldingsCaption" + entryNum, "last");
mfhd_edit.startup();
var copy_browser_reset = true;
var hold_browser_reset = true;
var acq_orders_reset = true;
+var serctrl_view_reset = true;
function $(id) { return document.getElementById(id); }
}
}
);
+
+ $('mfhd_add').setAttribute('oncommand','create_mfhd()');
+ var mfhd_edit_menu = $('mfhd_edit');
+ var mfhd_delete_menu = $('mfhd_delete');
+
+ // clear menus on subsequent loads
+ if (mfhd_edit_menu.firstChild) {
+ mfhd_edit_menu.removeChild(mfhd_edit_menu.firstChild);
+ mfhd_delete_menu.removeChild(mfhd_delete_menu.firstChild);
+ }
+
+ mfhd_edit_menu.disabled = true;
+ mfhd_delete_menu.disabled = true;
+
+ win.attachEvt("rdetail", "MFHDDrawn",
+ function() {
+ if (win.mfhdDetails && win.mfhdDetails.length > 0) {
+ g.mfhd = {};
+ g.mfhd.details = win.mfhdDetails;
+ mfhd_edit_menu.disabled = false;
+ mfhd_delete_menu.disabled = false;
+ for (var i = 0; i < win.mfhdDetails.length; i++) {
+ var mfhd_details = win.mfhdDetails[i];
+ var num = mfhd_details.entryNum;
+ num++;
+ var label = mfhd_details.label + ' (' + num + ')';
+ var item = mfhd_edit_menu.appendItem(label);
+ item.setAttribute('oncommand','open_mfhd_editor('+mfhd_details.id+')');
+ item = mfhd_delete_menu.appendItem(label);
+ item.setAttribute('oncommand','delete_mfhd('+mfhd_details.id+')');
+ }
+ }
+ }
+ );
},
'url_prefix' : xulG.url_prefix,
};
bottom_pane.get_contentWindow().addEventListener('load',opac_wrapper_set_help_context,false);
}
+function set_serctrl_view() {
+ g.view = 'serctrl_view';
+ if (serctrl_view_reset) {
+ bottom_pane.reset_iframe( xulG.url_prefix( urls.XUL_SERIAL_SERCTRL_MAIN ) + '?docid=' + window.escape(docid), {}, xulG);
+ serctrl_view_reset =false;
+ } else {
+ bottom_pane.set_iframe( xulG.url_prefix( urls.XUL_SERIAL_SERCTRL_MAIN ) + '?docid=' + window.escape(docid), {}, xulG);
+ }
+}
+
+function create_mfhd() {
+ try {
+ g.data.create_mfhd_aou = '';
+ JSAN.use('util.window'); var win = new util.window();
+ win.open(
+ xulG.url_prefix(urls.XUL_SERIAL_SELECT_AOU),
+ 'sel_bucket_win' + win.window_name_increment(),
+ 'chrome,resizable,modal,centerscreen'
+ );
+ if (!g.data.create_mfhd_aou) {
+ return;
+ }
+ var r = g.network.simple_request(
+ 'MFHD_XML_RECORD_CREATE',
+ [ ses(), 1, g.data.create_mfhd_aou, docid ]
+ );
+ if (typeof r.ilsevent != 'undefined') {
+ throw(r);
+ }
+ alert("MFHD record created."); //TODO: better success message
+ //TODO: refresh opac display
+ } catch(E) {
+ g.error.standard_unexpected_error_alert("Create MFHD failed", E); //TODO: better error handling
+ }
+}
+
+function delete_mfhd(sre_id) {
+ if (g.error.yns_alert(
+ document.getElementById('offlineStrings').getFormattedString('serial.delete_record.confirm', [sre_id]),
+ document.getElementById('offlineStrings').getString('cat.opac.delete_record'),
+ document.getElementById('offlineStrings').getString('cat.opac.delete'),
+ document.getElementById('offlineStrings').getString('cat.opac.cancel'),
+ null,
+ document.getElementById('offlineStrings').getString('cat.opac.record_deleted.confirm')) == 0) {
+ var robj = g.network.request(
+ 'open-ils.permacrud',
+ 'open-ils.permacrud.delete.sre',
+ [ses(),sre_id]);
+ if (typeof robj.ilsevent != 'undefined') {
+ alert(document.getElementById('offlineStrings').getFormattedString('cat.opac.record_deleted.error', [docid, robj.textcode, robj.desc]) + '\n');
+ } else {
+ alert(document.getElementById('offlineStrings').getString('cat.opac.record_deleted'));
+ //TODO: refresh opac display
+ }
+ }
+}
+
+function open_mfhd_editor(sre_id) {
+ try {
+ var r = g.network.simple_request(
+ 'FM_SRE_RETRIEVE',
+ [ ses(), sre_id ]
+ );
+ if (typeof r.ilsevent != 'undefined') {
+ throw(r);
+ }
+ open_marc_editor(r, 'MFHD');
+ } catch(E) {
+ g.error.standard_unexpected_error_alert("Create MFHD failed", E); //TODO: better error handling
+ }
+}
+
+function open_marc_editor(rec, label) {
+ win = window.open( xulG.url_prefix('/xul/server/cat/marcedit.xul') );
+
+ win.xulG = {
+ record : {marc : rec.marc()},
+ save : {
+ label: 'Save ' + label,
+ func: function(xmlString) { // TODO: switch to pcrud, or define an sre update method in Serial.pm?
+ var method = 'open-ils.permacrud.update.' + rec.classname;
+ rec.marc(xmlString);
+ g.network.request(
+ 'open-ils.permacrud', method,
+ [ses(), rec]
+ );
+ }
+ }
+ };
+}
+
function bib_in_new_tab() {
try {
var url = browser_frame.contentWindow.g.browser.controller.view.browser_browser.contentWindow.wrappedJSObject.location.href;
win.open(
xulG.url_prefix(urls.XUL_RECORD_BUCKETS_QUICK),
'sel_bucket_win' + win.window_name_increment(),
- 'chrome,resizable,modal,center',
+ 'chrome,resizable,modal,centerscreen',
{
record_ids: [ docid ]
}
case 'copy_browser' : set_copy_browser(); break;
case 'hold_browser' : set_hold_browser(); break;
case 'acq_orders' : set_acq_orders(); break;
+ case 'serctrl_view' : set_serctrl_view(); break;
case 'opac' :
default: set_opac(); break;
}
<menuseparator/>
<menuitem label="&staff.cat.opac.default.label;" id="default" oncommand="set_default();"/>
<menuitem label="&staff.cat.opac.refresh_me.label;" id="refresh_me" oncommand="refresh_display(docid);"/>
+ <menuseparator/>
+ <menu id="mfhd_menu" label="&staff.serial.mfhd_menu.label;">
+ <menupopup id="mfhd_popup">
+ <menuitem id="mfhd_add" label="&staff.serial.mfhd_menu.add.label;"/>
+ <menu id="mfhd_edit" label="&staff.serial.mfhd_menu.edit.label;"/>
+ <menu id="mfhd_delete" label="&staff.serial.mfhd_menu.delete.label;"/>
+ </menupopup>
+ </menu>
+ <menuitem id="serctrl_view" label="&staff.serial.serctrl_view.label;" oncommand="set_serctrl_view();"/>
</menupopup>
</menu>
</menubar>
'MARC_HTML_RETRIEVE' : { 'app' : 'open-ils.search', 'method' : 'open-ils.search.biblio.record.html', 'secure' : false },
'FM_BLOB_RETRIEVE_VIA_Z3950_SEARCH' : { 'app' : 'open-ils.search', 'method' : 'open-ils.search.z3950.search_class' },
'FM_BLOB_RETRIEVE_VIA_Z3950_RAW_SEARCH' : { 'app' : 'open-ils.search', 'method' : 'open-ils.search.z3950.search_service' },
+ 'FM_SCAP_BATCH_RETRIEVE' : { 'app' : 'open-ils.serial', 'method' : 'open-ils.serial.caption_and_pattern.batch.retrieve', 'secure' : false },
+ 'FM_SCAP_BATCH_RETRIEVE.authoritative' : { 'app' : 'open-ils.serial', 'method' : 'open-ils.serial.caption_and_pattern.batch.retrieve', 'secure' : false },
+ 'FM_SDIST_FLESHED_BATCH_RETRIEVE' : { 'app' : 'open-ils.serial', 'method' : 'open-ils.serial.distribution.fleshed.batch.retrieve', 'secure' : false },
+ 'FM_SDIST_FLESHED_BATCH_RETRIEVE.authoritative' : { 'app' : 'open-ils.serial', 'method' : 'open-ils.serial.distribution.fleshed.batch.retrieve.authoritative', 'secure' : false },
+ 'FM_SDIST_ID_LIST' : { 'app' : 'open-ils.pcrud', 'method' : 'open-ils.pcrud.id_list.sdist'},
+ 'FM_SDIST_RETRIEVE' : { 'app' : 'open-ils.pcrud', 'method' : 'open-ils.pcrud.retrieve.sdist'},
+ 'FM_SDIST_SEARCH' : { 'app' : 'open-ils.pcrud', 'method' : 'open-ils.pcrud.search.sdist'},
+ 'FM_SDISTN_CREATE' : { 'app' : 'open-ils.serial', 'method' : 'open-ils.serial.distribution_note.create' },
+ 'FM_SDISTN_DELETE' : { 'app' : 'open-ils.serial', 'method' : 'open-ils.serial.distribution_note.delete', 'secure' : false },
+ 'FM_SDISTN_RETRIEVE_ALL' : { 'app' : 'open-ils.serial', 'method' : 'open-ils.serial.distribution_note.retrieve.all', 'secure' : false },
+ 'FM_SIN_CREATE' : { 'app' : 'open-ils.serial', 'method' : 'open-ils.serial.item_note.create' },
+ 'FM_SIN_DELETE' : { 'app' : 'open-ils.serial', 'method' : 'open-ils.serial.item_note.delete', 'secure' : false },
+ 'FM_SIN_RETRIEVE_ALL' : { 'app' : 'open-ils.serial', 'method' : 'open-ils.serial.item_note.retrieve.all', 'secure' : false },
+ 'FM_SISS_FLESHED_BATCH_RETRIEVE' : { 'app' : 'open-ils.serial', 'method' : 'open-ils.serial.issuance.fleshed.batch.retrieve', 'secure' : false },
+ 'FM_SISS_FLESHED_BATCH_RETRIEVE.authoritative' : { 'app' : 'open-ils.serial', 'method' : 'open-ils.serial.issuance.fleshed.batch.retrieve.authoritative', 'secure' : false },
+ 'FM_SITEM_FLESHED_BATCH_RETRIEVE' : { 'app' : 'open-ils.serial', 'method' : 'open-ils.serial.item.fleshed.batch.retrieve', 'secure' : false },
+ 'FM_SITEM_FLESHED_BATCH_RETRIEVE.authoritative' : { 'app' : 'open-ils.serial', 'method' : 'open-ils.serial.item.fleshed.batch.retrieve.authoritative', 'secure' : false },
+ 'FM_SITEM_ID_LIST' : { 'app' : 'open-ils.pcrud', 'method' : 'open-ils.pcrud.id_list.sitem'},
+ 'FM_SITEM_RETRIEVE' : { 'app' : 'open-ils.pcrud', 'method' : 'open-ils.pcrud.retrieve.sitem'},
+ 'FM_SITEM_SEARCH' : { 'app' : 'open-ils.pcrud', 'method' : 'open-ils.pcrud.search.sitem'},
+ 'FM_SRE_RETRIEVE' : { 'app' : 'open-ils.pcrud', 'method' : 'open-ils.pcrud.retrieve.sre'},
+ 'FM_SRE_SEARCH' : { 'app' : 'open-ils.pcrud', 'method' : 'open-ils.pcrud.search.sre'},
+ 'FM_SSUB_AOU_IDS_RETRIEVE_VIA_RECORD_ID' : { 'app' : 'open-ils.serial', 'method' : 'open-ils.serial.subscription.retrieve_orgs_by_title', 'secure' : false },
+ 'FM_SSUB_AOU_IDS_RETRIEVE_VIA_RECORD_ID.authoritative' : { 'app' : 'open-ils.serial', 'method' : 'open-ils.serial.subscription.retrieve_orgs_by_title.authoritative', 'secure' : false },
+ 'FM_SSUB_FLESHED_BATCH_RETRIEVE' : { 'app' : 'open-ils.serial', 'method' : 'open-ils.serial.subscription.fleshed.batch.retrieve', 'secure' : false },
+ 'FM_SSUB_FLESHED_BATCH_RETRIEVE.authoritative' : { 'app' : 'open-ils.serial', 'method' : 'open-ils.serial.subscription.fleshed.batch.retrieve.authoritative', 'secure' : false },
+ 'FM_SSUB_TREE_LIST_RETRIEVE_VIA_RECORD_ID_AND_ORG_IDS' : { 'app' : 'open-ils.serial', 'method' : 'open-ils.serial.subscription_tree.retrieve', 'secure' : false },
+ 'FM_SSUB_TREE_LIST_RETRIEVE_VIA_RECORD_ID_AND_ORG_IDS.authoritative' : { 'app' : 'open-ils.serial', 'method' : 'open-ils.serial.subscription_tree.retrieve.authoritative', 'secure' : false },
+ 'FM_SSUBN_CREATE' : { 'app' : 'open-ils.serial', 'method' : 'open-ils.serial.subscription_note.create' },
+ 'FM_SSUBN_DELETE' : { 'app' : 'open-ils.serial', 'method' : 'open-ils.serial.subscription_note.delete', 'secure' : false },
+ 'FM_SSUBN_RETRIEVE_ALL' : { 'app' : 'open-ils.serial', 'method' : 'open-ils.serial.subscription_note.retrieve.all', 'secure' : false },
'RETRIEVE_Z3950_SERVICES' : { 'app' : 'open-ils.search', 'method' : 'open-ils.search.z3950.retrieve_services', 'secure' : false },
'MARK_ITEM_DAMAGED' : { 'app' : 'open-ils.circ', 'method' : 'open-ils.circ.mark_item_damaged' },
'MARK_ITEM_MISSING_PIECES' : { 'app' : 'open-ils.circ', 'method' : 'open-ils.circ.mark_item_missing_pieces' },
'XUL_RECORD_BUCKETS' : '/xul/server/cat/record_buckets.xul',
'XUL_RECORD_BUCKETS_QUICK' : '/xul/server/cat/record_buckets_quick.xul',
'XUL_REMOTE_BROWSER' : '/xul/server/util/rbrowser.xul',
+ 'XUL_SERIAL_ITEM_EDITOR' : '/xul/server/serial/sitem_editor.xul',
+ 'XUL_SERIAL_NOTES' : '/xul/server/serial/notes.xul',
+ 'XUL_SERIAL_SELECT_AOU' : '/xul/server/serial/select_aou.xul',
+ 'XUL_SERIAL_SELECT_UNIT' : '/xul/server/serial/select_unit.xul',
+ 'XUL_SERIAL_SERCTRL_MAIN' : '/xul/server/serial/serctrl_main.xul',
'XUL_SPINE_LABEL' : '/xul/server/cat/spine_labels.xul',
'XUL_STAGED_PATRONS' : '/xul/server/patron/staged.xul',
'XUL_STANDALONE' : 'chrome://open_ils_staff_client/content/circ/offline.xul',
--- /dev/null
+staff.serial.editor_base.handle_update.error=serial update error:
+staff.serial.editor_base.handle_update.success=Save Successful
+staff.serial.scap_editor.count=1 caption and pattern
+staff.serial.scap_editor.count.plural=%1$s caption and patterns
+staff.serial.scap_editor.create=Create Caption and Pattern(s)
+staff.serial.scap_editor.create.accesskey=C
+staff.serial.scap_editor.modify=Modify Caption and Pattern(s)
+staff.serial.scap_editor.modify.accesskey=M
+staff.serial.scap_editor.notes=Caption and Pattern Notes
+staff.serial.sdist_editor.count=1 distribution
+staff.serial.sdist_editor.count.plural=%1$s distributions
+staff.serial.sdist_editor.create=Create Distribution(s)
+staff.serial.sdist_editor.create.accesskey=C
+staff.serial.sdist_editor.modify=Modify Distribution(s)
+staff.serial.sdist_editor.modify.accesskey=M
+staff.serial.sdist_editor.notes=Distribution Notes
+staff.serial.siss_editor.count=1 issuance
+staff.serial.siss_editor.count.plural=%1$s issuances
+staff.serial.siss_editor.create=Create Issuance(s)
+staff.serial.siss_editor.create.accesskey=C
+staff.serial.siss_editor.modify=Modify Issuance(s)
+staff.serial.siss_editor.modify.accesskey=M
+staff.serial.siss_editor.notes=Issuance Notes
+staff.serial.sitem_editor.count=1 item
+staff.serial.sitem_editor.count.plural=%1$s items
+staff.serial.sitem_editor.create=Create Item(s)
+staff.serial.sitem_editor.create.accesskey=C
+staff.serial.sitem_editor.modify=Modify Item(s)
+staff.serial.sitem_editor.modify.accesskey=M
+staff.serial.sitem_editor.notes=Item Notes
+staff.serial.ssub_editor.count=1 subscription
+staff.serial.ssub_editor.count.plural=%1$s subscriptions
+staff.serial.ssub_editor.create=Create Subscription(s)
+staff.serial.ssub_editor.create.accesskey=C
+staff.serial.ssub_editor.modify=Modify Subscription(s)
+staff.serial.ssub_editor.modify.accesskey=M
+staff.serial.ssub_editor.notes=Subscription Notes
+staff.serial.manage_subs.add.error=error adding object in manage_subs.js:
+staff.serial.manage_subs.delete.error=error deleting object in manage_subs.js:
+staff.serial.manage_subs.delete_scap.confirm=Are you sure you would like to delete this caption and pattern?
+staff.serial.manage_subs.delete_scap.confirm.plural=Are you sure you would like to delete these %1$s caption and patterns?
+staff.serial.manage_subs.delete_scap.title=Delete Caption and Patterns?
+staff.serial.manage_subs.delete_scap.override=Override Delete Failure? Doing so will delete all attached issuances and items as well!
+staff.serial.manage_subs.delete_sdist.confirm=Are you sure you would like to delete this distribution?
+staff.serial.manage_subs.delete_sdist.confirm.plural=Are you sure you would like to delete these %1$s distributions?
+staff.serial.manage_subs.delete_sdist.title=Delete Distributions?
+staff.serial.manage_subs.delete_sdist.override=Override Delete Failure?
+staff.serial.manage_subs.delete_siss.confirm=Are you sure you would like to delete this issuance?
+staff.serial.manage_subs.delete_siss.confirm.plural=Are you sure you would like to delete these %1$s issuances?
+staff.serial.manage_subs.delete_siss.title=Delete Issuances?
+staff.serial.manage_subs.delete_siss.override=Override Delete Failure? Doing so will delete all attached items as well!
+staff.serial.manage_subs.delete_ssub.confirm=Are you sure you would like to delete this subscription?
+staff.serial.manage_subs.delete_ssub.confirm.plural=Are you sure you would like to delete these %1$s subscriptions?
+staff.serial.manage_subs.delete_ssub.title=Delete Subscriptions?
+staff.serial.manage_subs.delete_ssub.override=Override Delete Failure? Doing so will delete all related data as well!
--- /dev/null
+dump('entering serial/editor_base.js\n');
+// vim:noet:sw=4:ts=4:
+
+if (typeof serial == 'undefined') serial = {};
+
+serial.editor_base = {
+
+ 'editor_base_init' : function (params) {
+ var obj = this;
+ try {
+ /******************************************************************************************************/
+ /* setup JSAN and some initial libraries */
+
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ if (typeof JSAN == 'undefined') {
+ throw( $('commonStrings').getString('common.jsan.missing') );
+ }
+ JSAN.errorLevel = "die"; // none, warn, or die
+ JSAN.addRepository('/xul/server/');
+ JSAN.use('util.error'); obj.error = new util.error();
+ obj.error.sdump('D_TRACE','my_init() for serial/editor_base.js');
+
+ JSAN.use('util.functional');
+ JSAN.use('OpenILS.data'); obj.data = new OpenILS.data(); obj.data.init({'via':'stash'});
+ JSAN.use('util.network'); obj.network = new util.network();
+
+
+ /******************************************************************************************************/
+ /* base vars */
+
+ obj.docid = xul_param('docid',{'modal_xulG':true});
+
+ if (typeof params.handle_update == 'undefined') {
+ obj.handle_update = xul_param('handle_update',{'modal_xulG':true});
+ } else {
+ obj.handle_update = params.handle_update;
+ }
+
+ obj.trigger_refresh = params.trigger_refresh;
+ obj.refresh_command = params.refresh_command;
+ var fm_type = obj.fm_type;
+ var fm_type_plural = obj.fm_type_plural;
+ var retrieve_function = params.retrieve_function;
+ var retrieve_params = params.retrieve_params;
+ if (!retrieve_params) {
+ retrieve_params = [];
+ }
+
+ /******************************************************************************************************/
+ /* Get the fm_type ids from various sources and flesh them */
+
+ var fm_type_ids = params[fm_type + '_ids'];
+ if (!fm_type_ids) fm_type_ids = xul_param(fm_type + '_ids',{'concat':true,'JSON2js_if_cgi':true,'JSON2js_if_xulG':true,'JSON2js_if_xpcom':true,'stash_name':'temp_' + fm_type + '_ids','clear_xpcom':true,'modal_xulG':true});
+ if (!fm_type_ids) fm_type_ids = [];
+
+ obj[fm_type_plural] = [];
+ retrieve_params.push(fm_type_ids);
+ if (fm_type_ids.length > 0) obj[fm_type_plural] = obj.network.simple_request(
+ retrieve_function,
+ retrieve_params
+ );
+
+
+ /******************************************************************************************************/
+ /* And other fleshed copies if any */
+
+ if (!obj[fm_type_plural]) obj[fm_type_plural] = [];
+ var fms = params[fm_type_plural];
+ if (!fms) fms = xul_param(fm_type_plural,{'concat':true,'JSON2js_if_cgi':true,'JSON2js_if_xpcom':true,'stash_name':'temp_' + fm_type_plural,'clear_xpcom':true,'modal_xulG':true})
+ if (fms) obj[fm_type_plural] = obj[fm_type_plural].concat(fms);
+
+
+ // If we have just one, wrap in array
+ if (!obj[fm_type_plural].length) {
+ obj[fm_type_plural] = [obj[fm_type_plural]];
+ }
+
+
+ /******************************************************************************************************/
+
+ //obj.init_panes0();
+ obj.init_panes();
+
+ /******************************************************************************************************/
+ /* Is the interface an editor or a viewer, single or multi copy, existing copies or new copies? */
+
+ var do_edit;
+ if (typeof params.do_edit == 'undefined') {
+ do_edit = xul_param('do_edit',{'modal_xulG':true});
+ } else {
+ do_edit = params.do_edit;
+ }
+
+ if (do_edit) {
+
+ // Editor desired, but let's check permissions
+ obj.do_edit = false;
+
+ try {
+ /* FIXME: add permission check
+ var check = obj.network.simple_request(
+ 'PERM_MULTI_ORG_CHECK',
+ [
+ ses(),
+ obj.data.list.au[0].id(),
+ util.functional.map_list(
+ obj[fm_type_plural],
+ function (o) {
+ var lib;
+ var cn_id = o.call_number();
+ if (cn_id == -1) {
+ lib = o.circ_lib(); // base perms on circ_lib instead of owning_lib if pre-cat
+ } else {
+ if (! obj.map_acn[ cn_id ]) {
+ var req = obj.network.simple_request('FM_ACN_RETRIEVE.authoritative',[ cn_id ]);
+ if (typeof req.ilsevent == 'undefined') {
+ obj.map_acn[ cn_id ] = req;
+ lib = obj.map_acn[ cn_id ].owning_lib();
+ } else {
+ lib = o.circ_lib();
+ }
+ } else {
+ lib = obj.map_acn[ cn_id ].owning_lib();
+ }
+ }
+ return typeof lib == 'object' ? lib.id() : lib;
+ }
+ ),
+ obj[fm_type_plural].length == 1 ? [ 'UPDATE_COPY' ] : [ 'UPDATE_COPY', 'UPDATE_BATCH_COPY' ]
+ ]
+ ); */
+ var check = [];
+ obj.do_edit = check.length == 0;
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert('batch permission check',E);
+ }
+
+ if (obj.do_edit) {
+ $(fm_type + '_save').setAttribute('hidden','false');
+ } else {
+ $('top_nav').setAttribute('hidden','true');
+ }
+ } else {
+ $('top_nav').setAttribute('hidden','true');
+ }
+
+
+ if (obj[fm_type_plural].length > 0 && obj[fm_type_plural][0].isnew()) {
+ obj.mode = 'create';
+ if (obj.can_have_notes) $(fm_type + '_notes').setAttribute('hidden','true');
+ $(fm_type + '_save').setAttribute('label', $('serialStrings').getString('staff.serial.' + fm_type + '_editor.create'));
+ $(fm_type + '_save').setAttribute('accesskey', $('serialStrings').getString('staff.serial.' + fm_type + '_editor.create.accesskey'));
+ } else if (obj.mode == 'create') { // switching from create to modify
+ obj.mode = 'modify';
+ if (obj.can_have_notes) $(fm_type + '_notes').setAttribute('hidden','false');
+ $(fm_type + '_save').setAttribute('label', $('serialStrings').getString('staff.serial.' + fm_type + '_editor.modify'));
+ $(fm_type + '_save').setAttribute('accesskey', $('serialStrings').getString('staff.serial.' + fm_type + '_editor.modify.accesskey'));
+ }
+/*else {
+ obj.panes_and_field_names.left_pane =
+ [
+ [
+ $('catStrings').getString('staff.cat.copy_editor.status'),
+ {
+ render: 'typeof fm.status() == "object" ? fm.status().name() : obj.data.hash.ccs[ fm.status() ].name()',
+ input: obj.safe_to_edit_copy_status() ? 'c = function(v){ obj.apply("status",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( obj.data.list.ccs, function(obj) { return [ obj.name(), obj.id(), typeof my_constants.magical_statuses[obj.id()] != "undefined" ? true : false ]; } ).sort() ); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);' : undefined,
+ //input: 'c = function(v){ obj.apply("status",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( util.functional.filter_list( obj.data.list.ccs, function(obj) { return typeof my_constants.magical_statuses[obj.id()] == "undefined"; } ), function(obj) { return [ obj.name(), obj.id() ]; } ).sort() ); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+ }
+ ]
+ ].concat(obj.panes_and_field_names.left_pane);
+ }*/
+
+ if (obj[fm_type_plural].length != 1) {
+ document.getElementById(fm_type + '_notes').setAttribute('hidden','true');
+ }
+
+ // clear change markers
+ obj.changed = {};
+
+ /******************************************************************************************************/
+ /* Show the Record Details? (only for 'in_modal' mode)*/
+
+ var bdb;
+ if (xul_param('in_modal',{'modal_xulG':true}) && obj.docid) {
+ bdb = document.getElementById('brief_display_box'); while(bdb.firstChild) bdb.removeChild(bdb.lastChild);
+ var brief_display = document.createElement('iframe'); bdb.appendChild(brief_display);
+ brief_display.setAttribute( 'src', urls.XUL_BIB_BRIEF + '?docid=' + obj.docid); // this is a modal window, so can't push in xulG
+ brief_display.setAttribute( 'flex','1' );
+ }
+
+ /******************************************************************************************************/
+ /* Backup copies :) */
+
+ obj['original_' + fm_type_plural] = js2JSON( obj[fm_type_plural] );
+
+ } catch(E) {
+ var err_msg = $("commonStrings").getFormattedString('common.exception', ['serial/' + fm_type +'_editor.js - init', E]);
+ try { obj.error.sdump('D_ERROR',err_msg); } catch(E) { dump(err_msg); dump(js2JSON(E)); }
+ alert(err_msg);
+ }
+ },
+
+ /******************************************************************************************************/
+ /* Restore backup copies */
+
+ 'editor_base_reset' : function() {
+ var obj = this;
+ var fm_type_plural = obj.fm_type_plural;
+
+ obj.changed = {};
+ obj[fm_type_plural] = JSON2js( obj['original_' + fm_type_plural] );
+ obj.summarize( obj[fm_type_plural] );
+ obj.render();
+ },
+
+ /******************************************************************************************************/
+ /* Apply a value to a specific field on all the copies being edited */
+ /* Don't forget to use util.money.sanitize if dealing with money values */
+
+ 'editor_base_apply' : function(field, value, loop_func) {
+ var obj = this;
+ var fm_type_plural = obj.fm_type_plural;
+
+ var do_loop_func = (typeof loop_func == 'function');
+
+ obj.error.sdump('D_TRACE','applying field = <' + field + '> value = <' + value + '>\n');
+ if (value == '<HACK:KLUDGE:NULL>') value = null;
+ for (var i = 0; i < obj[fm_type_plural].length; i++) {
+ var fm = obj[fm_type_plural][i];
+ try {
+ fm[field]( value ); fm.ischanged('1');
+ if (do_loop_func) {
+ loop_func(fm);
+ }
+ } catch(E) {
+ alert(E);
+ }
+ }
+ },
+
+
+ /******************************************************************************************************/
+ /* This loops through all our fieldnames and all the copies, tallying up counts for the different values */
+
+ 'editor_base_summarize' : function(my_fms) {
+ var obj = this;
+ /******************************************************************************************************/
+ /* Setup */
+
+ JSAN.use('util.date'); JSAN.use('util.money');
+ obj.summary = {};
+ obj.field_names = [];
+ for (var i in obj.panes_and_field_names) {
+ obj.field_names = obj.field_names.concat( obj.panes_and_field_names[i] );
+ }
+
+ /******************************************************************************************************/
+ /* Loop through the field names */
+
+ for (var i = 0; i < obj.field_names.length; i++) {
+
+ var field_name = obj.field_names[i][0];
+ var render = obj.field_names[i][1].render;
+ var attr = obj.field_names[i][1].attr;
+ var value_key = obj.field_names[i][1].value_key;
+ var dropdown_key = obj.field_names[i][1].dropdown_key;
+ obj.summary[ field_name ] = {};
+
+ /******************************************************************************************************/
+ /* Loop through the copies */
+
+ for (var j = 0; j < my_fms.length; j++) {
+
+ var fm = my_fms[j];
+ var cmd = render || ('fm.' + field_name + '();');
+ var value = '???';
+
+ /**********************************************************************************************/
+ /* Try to retrieve the value for this field for this copy */
+
+ try {
+ value = eval( cmd );
+ if (typeof(value) == 'undefined') {
+ value = "";
+ }
+ if (dropdown_key) {
+ obj.editor_values[value_key] = eval(dropdown_key);
+ } else if (value_key) {
+ obj.editor_values[value_key] = value;
+ }
+ if (value == "") {
+ value = "<Unset>";
+ }
+ } catch(E) {
+ obj.error.sdump('D_ERROR','Attempted ' + cmd + '\n' + E + '\n');
+ }
+ if (typeof value == 'object' && value != null) {
+ alert('FIXME: field_name = <' + field_name + '> value = <' + js2JSON(value) + '>\n');
+ }
+
+ /**********************************************************************************************/
+ /* Tally the count */
+
+ if (obj.summary[ field_name ][ value ]) {
+ obj.summary[ field_name ][ value ]++;
+ } else {
+ obj.summary[ field_name ][ value ] = 1;
+ }
+ }
+ }
+ obj.error.sdump('D_TRACE','summary = ' + js2JSON(obj.summary) + '\n');
+ },
+
+ /******************************************************************************************************/
+ /* Display the summarized data and inputs for editing */
+
+ 'editor_base_render' : function() {
+ var obj = this;
+ var fm_type = obj.fm_type;
+
+ /******************************************************************************************************/
+ /* Library setup and clear any existing interface */
+
+ JSAN.use('util.widgets'); JSAN.use('util.date'); JSAN.use('util.money'); JSAN.use('util.functional');
+
+ for (var i in obj.panes_and_field_names) {
+ var p = document.getElementById(i);
+ if (p) util.widgets.remove_children(p);
+ }
+
+ /******************************************************************************************************/
+ /* Prepare the panes */
+
+ var groupbox; var caption; var vbox; var grid; var rows;
+
+ /******************************************************************************************************/
+ /* Loop through the field names */
+
+ for (h in obj.panes_and_field_names) {
+ if (!document.getElementById(h)) continue;
+ for (var i = 0; i < obj.panes_and_field_names[h].length; i++) {
+ try {
+ var f = obj.panes_and_field_names[h][i]; var fn = f[0]; var attr = f[1].attr;
+ groupbox = document.createElement('groupbox'); document.getElementById(h).appendChild(groupbox);
+ if (attr) {
+ for (var a in attr) {
+ groupbox.setAttribute(a,attr[a]);
+ }
+ }
+ if (typeof obj.changed[fn] != 'undefined') {
+ groupbox.setAttribute('class','copy_editor_field_changed');
+ }
+ caption = document.createElement('caption'); groupbox.appendChild(caption);
+ caption.setAttribute('label',fn); caption.setAttribute('id','caption_'+fn);
+ vbox = document.createElement('vbox'); groupbox.appendChild(vbox);
+ grid = util.widgets.make_grid( [ { 'flex' : 1 }, {}, {} ] ); vbox.appendChild(grid);
+ grid.setAttribute('flex','1');
+ rows = grid.lastChild;
+ var row;
+
+ /**************************************************************************************/
+ /* Loop through each value for the field */
+
+ for (var j in obj.summary[fn]) {
+ var value = j; var count = obj.summary[fn][j];
+ row = document.createElement('row'); rows.appendChild(row);
+ var label1 = document.createElement('description'); row.appendChild(label1);
+ label1.setAttribute('id',fn + '_label');
+ //if (obj.special_exception[ fn ]) {
+ // obj.special_exception[ fn ]( label1, value );
+ //} else {
+ label1.appendChild( document.createTextNode(value) );
+ //}
+ var label2 = document.createElement('description'); row.appendChild(label2);
+ var fm_count;
+ if (count == 1) {
+ fm_count = $('serialStrings').getString('staff.serial.' + fm_type +'_editor.count');
+ } else {
+ fm_count = $('serialStrings').getFormattedString('staff.serial.' + fm_type +'_editor.count.plural', [count]);
+ }
+ label2.appendChild( document.createTextNode(fm_count) );
+ }
+ var hbox = document.createElement('hbox');
+ hbox.setAttribute('id',fn);
+ groupbox.appendChild(hbox);
+ var hbox2 = document.createElement('hbox');
+ groupbox.appendChild(hbox2);
+
+ /**************************************************************************************/
+ /* Render the input widget */
+
+ if (f[1].input && obj.do_edit) {
+ obj.render_input(hbox,f[1]);
+ }
+
+ } catch(E) {
+ obj.error.sdump('D_ERROR','copy editor: ' + E + '\n');
+ }
+ }
+ }
+
+
+ /******************************************************************************************************/
+ /* Synchronize stat cat visibility with library filter menu, and default template selection */
+ JSAN.use('util.file');
+ var file = new util.file(fm_type + '_editor_prefs.'+obj.data.server_unadorned);
+ obj[fm_type + '_editor_prefs'] = util.widgets.load_attributes(file);
+ for (var i in obj[fm_type + '_editor_prefs']) {
+ if (i.match(/filter_/) && obj[fm_type + '_editor_prefs'][i].checked == '') {
+ try {
+ obj.toggle_stat_cat_display( document.getElementById(i) );
+ } catch(E) { alert(E); }
+ }
+ }
+ if (obj.template_menu) obj.template_menu.value = obj.template_menu.getAttribute('value');
+
+ },
+
+ /******************************************************************************************************/
+ /* This actually draws the change button and input widget for a given field */
+ 'editor_base_render_input' : function(node, blob) {
+ var obj = this;
+ var fm_type_plural = obj.fm_type_plural;
+
+ try {
+ // node = hbox ; groupbox -> hbox, hbox
+
+ var groupbox = node.parentNode;
+ var caption = groupbox.firstChild;
+ var vbox = node.previousSibling;
+ var hbox = node;
+ var hbox2 = node.nextSibling;
+
+ var input_cmd = blob.input;
+ var render_cmd = blob.render;
+ var attr = blob.attr;
+
+ var block = false; var first = true;
+
+ function on_mouseover(ev) {
+ groupbox.setAttribute('style','background: white');
+ }
+
+ function on_mouseout(ev) {
+ groupbox.setAttribute('style','');
+ }
+
+ vbox.addEventListener('mouseover',on_mouseover,false);
+ vbox.addEventListener('mouseout',on_mouseout,false);
+ groupbox.addEventListener('mouseover',on_mouseover,false);
+ groupbox.addEventListener('mouseout',on_mouseout,false);
+ groupbox.firstChild.addEventListener('mouseover',on_mouseover,false);
+ groupbox.firstChild.addEventListener('mouseout',on_mouseout,false);
+
+ function on_click(ev){
+ try {
+ if (block) return; block = true;
+
+ function post_c(v, unchanged) {
+ try {
+ /* dbw2 not needed?
+ var t = input_cmd.match('apply_stat_cat') ? 'stat_cat' : ( input_cmd.match('apply_owning_lib') ? 'owning_lib' : 'attribute' );
+ var f;
+ switch(t) {
+ case 'attribute' :
+ f = input_cmd.match(/apply.?\("(.+?)",/)[1];
+ break;
+ case 'stat_cat' :
+ f = input_cmd.match(/apply_stat_cat\((.+?),/)[1];
+ break;
+ case 'owning_lib' :
+ f = null;
+ break;
+ }
+ obj.changed[ hbox.id ] = { 'type' : t, 'field' : f, 'value' : v }; */
+ if (!unchanged) {
+ obj.changed[ hbox.id ] = true;
+ }
+ block = false;
+ setTimeout(
+ function() {
+ obj.summarize( obj[fm_type_plural] );
+ obj.render();
+ document.getElementById(caption.id).focus();
+ }, 0
+ );
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert('post_c',E);
+ }
+ }
+ var x; var c; eval( input_cmd );
+ if (x) {
+ util.widgets.remove_children(vbox);
+ util.widgets.remove_children(hbox);
+ util.widgets.remove_children(hbox2);
+ hbox.appendChild(x);
+ var apply = document.createElement('button');
+ apply.setAttribute('label', $('catStrings').getString('staff.cat.copy_editor.apply.label'));
+ apply.setAttribute('accesskey', $('catStrings').getString('staff.cat.copy_editor.apply.accesskey'));
+ hbox2.appendChild(apply);
+ apply.addEventListener('command',function() { c(x.value); },false);
+ var cancel = document.createElement('button');
+ cancel.setAttribute('label', $('catStrings').getString('staff.cat.copy_editor.cancel.label'));
+ cancel.addEventListener('command',function() { setTimeout( function() { obj.summarize( obj[fm_type_plural] ); obj.render(); document.getElementById(caption.id).focus(); }, 0); }, false);
+ hbox2.appendChild(cancel);
+ setTimeout( function() { x.focus(); }, 0 );
+ }
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert('render_input',E);
+ }
+ }
+ vbox.addEventListener('click',on_click, false);
+ hbox.addEventListener('click',on_click, false);
+ caption.addEventListener('click',on_click, false);
+ caption.addEventListener('keypress',function(ev) {
+ if (ev.keyCode == 13 /* enter */ || ev.keyCode == 77 /* mac enter */) on_click();
+ }, false);
+ caption.setAttribute('style','-moz-user-focus: normal');
+ caption.setAttribute('onfocus','this.setAttribute("class","outline_me")');
+ caption.setAttribute('onblur','this.setAttribute("class","")');
+
+ } catch(E) {
+ obj.error.sdump('D_ERROR',E + '\n');
+ }
+ },
+
+ /******************************************************************************************************/
+ /* save or store the updated fms as appropriate */
+
+ 'editor_base_save' : function(update_method) {
+ var obj = this;
+ var fm_type_plural = obj.fm_type_plural;
+ var fm_type= obj.fm_type;
+
+ try {
+ if (obj.handle_update) {
+ try {
+ //send fms to the update function
+ var r = obj.network.request(
+ 'open-ils.serial',
+ update_method,
+ [ ses(), obj[fm_type_plural] ]
+ );
+ if (typeof r.ilsevent != 'undefined') {
+ obj.error.standard_unexpected_error_alert('serial ' + fm_type + ' update',r);
+ } else {
+ alert($('serialStrings').getString('staff.serial.editor_base.handle_update.success'));
+ obj.changed = {};
+ if (obj.trigger_refresh) {
+ obj.refresh_command();
+ } else {
+ obj.render();
+ }
+ }
+ /* FIXME -- revisit the return value here */
+ } catch(E) {
+ alert($('serialStrings').getString('staff.serial.editor_base.handle_update.error') + ' ' + js2JSON(E));
+ }
+ } else if (xul_param('in_modal',{'modal_xulG':true})) {
+ // TODO: this is to perhaps allow this editor to be called
+ // in a modal window, but is unfinished functionality
+ var xulG = {};
+ xulG[fm_type_plural] = obj[fm_type_plural];
+ update_modal_xulG(xulG);
+ } else {
+ obj.data['temp_' + fm_type_plural] = js2JSON( obj[fm_type_plural] );
+ obj.data.stash('temp_' + fm_type_plural);
+ }
+
+ if (xul_param('in_modal',{'modal_xulG':true})) {
+ window.close();
+ }
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert(fm_type + '_editor save',E);
+ }
+ },
+
+ /******************************************************************************************************/
+ 'editor_base_save_attributes' : function() {
+ var obj = this;
+ var fm_type = obj.fm_type;
+
+ JSAN.use('util.widgets'); JSAN.use('util.file'); var file = new util.file(fm_type + '_editor_prefs.'+obj.data.server_unadorned);
+ var what_to_save = {};
+ for (var i in obj[fm_type + '_editor_prefs']) {
+ what_to_save[i] = [];
+ for (var j in obj[fm_type + '_editor_prefs'][i]) what_to_save[i].push(j);
+ }
+ util.widgets.save_attributes(file, what_to_save );
+ }
+};
+
+dump('exiting serial/editor_base.js\n');
--- /dev/null
+dump('entering manage_items.js\n');
+
+function $(id) { return document.getElementById(id); }
+
+if (typeof serial == 'undefined') serial = {};
+serial.manage_items = function (params) {
+
+ JSAN.use('util.error'); this.error = new util.error();
+ JSAN.use('util.network'); this.network = new util.network();
+ JSAN.use('OpenILS.data'); this.data = new OpenILS.data(); this.data.init({'via':'stash'});
+
+ this.current_sunit_id = -1; //default to **AUTO**
+ this.mode = 'receive';
+
+}
+
+serial.manage_items.prototype = {
+
+ 'list_sitem_map' : {},
+
+ 'set_sdist_ids' : function () {
+ var obj = this;
+
+ try {
+ obj.holding_lib = $('serial_item_lib_menu').value;
+ var robj = obj.network.request(
+ 'open-ils.pcrud',
+ 'open-ils.pcrud.id_list.sdist',
+ [ ses(), {"holding_lib" : obj.holding_lib, "+ssub":{"record_entry" : obj.docid}}, {"join":"ssub"} ]
+ );
+ if (robj != null) {
+ if (typeof robj.ilsevent != 'undefined') throw(robj);
+ obj.sdist_ids = robj.length ? robj : [robj];
+ } else {
+ obj.sdist_ids = [];
+ }
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert('set_sdist_ids failed!',E);
+ }
+ },
+
+ 'build_menus' : function () {
+ var obj = this;
+
+ // draw library drop-down
+ obj.org_ids = obj.network.simple_request('FM_SSUB_AOU_IDS_RETRIEVE_VIA_RECORD_ID.authoritative',[ obj.docid ]);
+ if (typeof obj.org_ids.ilsevent != 'undefined') throw(obj.org_ids);
+ JSAN.use('util.functional');
+ obj.org_ids = util.functional.map_list( obj.org_ids, function (o) { return Number(o); });
+
+ var org = obj.data.hash.aou[ obj.data.list.au[0].ws_ou() ];
+
+ JSAN.use('util.file'); JSAN.use('util.widgets');
+
+ var file; var list_data; var ml;
+
+ file = new util.file('offline_ou_list');
+ if (file._file.exists()) {
+ list_data = file.get_object(); file.close();
+ ml = util.widgets.make_menulist( list_data[0], list_data[1] );
+ ml.setAttribute('id','serial_item_lib_menu'); document.getElementById('serial_item_lib_menu_box').appendChild(ml);
+ //TODO: class this menu properly
+ for (var i = 0; i < obj.org_ids.length; i++) {
+ ml.getElementsByAttribute('value',obj.org_ids[i])[0].setAttribute('class','has_distributions');
+ }
+ /*TODO: add/enable this legend?
+ ml.firstChild.addEventListener(
+ 'popupshown',
+ function(ev) {
+ document.getElementById('legend').setAttribute('hidden','false');
+ },
+ false
+ );
+ ml.firstChild.addEventListener(
+ 'popuphidden',
+ function(ev) {
+ document.getElementById('legend').setAttribute('hidden','true');
+ },
+ false
+ );*/
+ ml.addEventListener(
+ 'command',
+ function(ev) {
+ //if (document.getElementById('serial_item_refresh_button')) document.getElementById('serial_item_refresh_button').focus();
+ obj.save_settings();
+ // get latest sdist id list based on library drowdown
+ obj.set_sdist_ids();
+ obj.refresh_list('main');
+ obj.refresh_list('workarea');
+ },
+ false
+ );
+
+ } else {
+ throw(document.getElementById('catStrings').getString('staff.cat.copy_browser.missing_library') + '\n');
+ }
+ file = new util.file('serial_items_prefs.'+obj.data.server_unadorned);
+ util.widgets.load_attributes(file);
+ ml.value = ml.getAttribute('value');
+ if (! ml.value) {
+ ml.value = org.id();
+ ml.setAttribute('value',ml.value);
+ }
+
+ // deal with mode radio selectedIndex, as load_attributes is setting a "read-only" value
+ if ($('mode_receive').getAttribute('selected')) {
+ $('serial_manage_items_mode').selectedIndex = 0;
+ } else {
+ $('serial_manage_items_mode').selectedIndex = 1;
+ }
+
+ // setup recent sunits list
+ var recent_sunits_file = new util.file('serial_items_recent_sunits_'+obj.docid+'.'+obj.data.server_unadorned);
+ util.widgets.load_attributes(recent_sunits_file);
+ var recent_sunits_popup = $('serial_items_recent_sunits');
+ obj.sunit_entries = JSON2js(recent_sunits_popup.getAttribute('sunit_json'));
+ for (i = 0; i < obj.sunit_entries.length; i++) {
+ var sunit_info = obj.sunit_entries[i];
+ var new_menu_item = recent_sunits_popup.appendItem(sunit_info.label);
+ new_menu_item.setAttribute('id', 'serial_items_recent_sunits_entry_'+sunit_info.id);
+ new_menu_item.setAttribute('sunit_id', sunit_info.id);
+ new_menu_item.setAttribute('command', 'cmd_set_sunit');
+ }
+ },
+
+ 'init' : function( params ) {
+ var obj = this;
+
+ obj.docid = params['docid'];
+
+ obj.build_menus();
+ obj.set_sunit($('serial_items_current_sunit').getAttribute('sunit_id'), $('serial_items_current_sunit').getAttribute('sunit_label'), $('serial_items_current_sunit').getAttribute('sdist_id'), $('serial_items_current_sunit').getAttribute('sstr_id'));
+ obj.set_sdist_ids();
+ obj.init_lists();
+
+ var mode_radio_group = $('serial_manage_items_mode');
+ obj.set_mode(mode_radio_group.selectedItem.id.substr(5));
+ mode_radio_group.addEventListener(
+ 'command',
+ function(ev) {
+ obj.save_settings();
+ var mode = ev.target.id.substr(5); //strip out 'mode_'
+ obj.set_mode(mode);
+ obj.refresh_list('main');
+ obj.refresh_list('workarea');
+ },
+ false
+ );
+ $('serial_manage_items_show_all').addEventListener(
+ 'command',
+ function(ev) {
+ obj.save_settings();
+ obj.set_mode();
+ obj.refresh_list('main');
+ obj.refresh_list('workarea');
+ },
+ false
+ );
+
+ JSAN.use('util.controller'); obj.controller = new util.controller();
+ obj.controller.init(
+ {
+ 'control_map' : {
+ 'save_columns' : [ [ 'command' ], function() { obj.lists.main.save_columns(); } ],
+ 'cmd_broken' : [ ['command'], function() { alert('Not Yet Implemented'); } ],
+ 'sel_clip' : [ ['command'], function() { obj.lists.main.clipboard(); } ],
+ 'cmd_add_item' : [
+ ['command'],
+ function() {
+ try {
+ var new_item = new sitem();
+ new_item.issuance(new siss());
+ new_item.stream(1); //FIXME: hard-coded stream
+ new_item.issuance().subscription(1); //FIXME: hard-coded subscription
+ new_item.isnew(1);
+ new_item.issuance().isnew(1);
+ spawn_sitem_editor( {'sitems' : [new_item], 'do_edit' : 1 } );
+
+ obj.refresh_list('main');
+
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.edit_items.error'),E);
+ }
+ }
+ ],
+ 'cmd_edit_items' : [
+ ['command'],
+ function() {
+ try {
+ if (!obj.retrieve_ids || obj.retrieve_ids.length == 0) return;
+
+ JSAN.use('util.functional');
+ var list = util.functional.map_list(
+ obj.retrieve_ids,
+ function (o) {
+ return o.sitem_id;
+ }
+ );
+
+ spawn_sitem_editor( { 'sitem_ids' : list, 'do_edit' : 1 } );
+
+ obj.refresh_list(obj.selected_list);
+
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.edit_items.error'),E);
+ }
+ }
+ ],
+ 'cmd_delete_items' : [
+ ['command'],
+ function() {
+ try {
+ JSAN.use('util.functional');
+ var list = util.functional.map_list(
+ obj.retrieve_ids,
+ function (o) {
+ return obj.list_sitem_map[o.sitem_id];
+ }
+ );
+ var delete_msg;
+ if (list.length != 1) {
+ delete_msg = document.getElementById('catStrings').getFormattedString('staff.cat.copy_browser.delete_items.confirm.plural', [list.length]);
+ } else {
+ delete_msg = document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_items.confirm');
+ }
+ var r = obj.error.yns_alert(
+ delete_msg,
+ document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_items.title'),
+ document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_items.delete'),
+ document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_items.cancel'),
+ null,
+ document.getElementById('commonStrings').getString('common.confirm')
+ );
+
+ if (r == 0) {
+ for (var i = 0; i < list.length; i++) {
+ list[i].isdeleted('1');
+ }
+ var robj = obj.network.request(
+ 'open-ils.serial',
+ 'open-ils.serial.item.fleshed.batch.update',
+ [ ses(), list, true ],
+ null,
+ {
+ 'title' : document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_items.override'),
+ 'overridable_events' : [ // FIXME: replace or delete these events
+ 1208 /* TITLE_LAST_COPY */,
+ 1227 /* COPY_DELETE_WARNING */,
+ ]
+ }
+ );
+ if (robj == null) throw(robj);
+ if (typeof robj.ilsevent != 'undefined') {
+ if ( (robj.ilsevent != 0) && (robj.ilsevent != 1227 /* COPY_DELETE_WARNING */) && (robj.ilsevent != 1208 /* TITLE_LAST_COPY */) ) throw(robj);
+ }
+ obj.refresh_list(obj.selected_list);
+ }
+
+
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert('staff.serial.manage_items.delete_items.error',E);
+ obj.refresh_list();
+ }
+ }
+ ],
+ 'cmd_set_sunit' : [
+ ['command'],
+ function(evt) {
+ try {
+ var target = evt.explicitOriginalTarget;
+ var label = target.label;
+ var sunit_id = target.getAttribute('sunit_id');
+ var sdist_id = target.getAttribute('sdist_id');
+ var sstr_id = target.getAttribute('sstr_id');
+ obj.set_sunit(sunit_id, label, sdist_id, sstr_id);
+ obj.save_sunit(sunit_id, label, sdist_id, sstr_id);
+ if (obj.mode == 'bind') obj.refresh_list('workarea');
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert('cmd_set_sunit failed!',E);
+ }
+ }
+ ],
+ 'cmd_set_other_sunit' : [
+ ['command'],
+ function() {
+ obj.set_other_sunit();
+ if (obj.mode == 'bind') obj.refresh_list('workarea');
+ }
+ ],
+ 'cmd_predict_items' : [
+ ['command'],
+ function() {
+ alert('Subscription selection needed here'); //FIXME: make this prompt, or discard this feature
+ }
+ ],
+ 'cmd_receive_items' : [
+ ['command'],
+ function() {
+ try {
+ JSAN.use('util.functional');
+ var list = util.functional.map_list(
+ obj.retrieve_ids,
+ function (o) {
+ var item = obj.list_sitem_map[o.sitem_id];
+ item.unit(obj.current_sunit_id);
+ return item;
+ }
+ );
+
+ var method; var success_label;
+ if (obj.mode == 'receive') {
+ method = 'open-ils.serial.receive_items';
+ success_label = 'received';
+ } else { // bind mode
+ method = 'open-ils.serial.bind_items';
+ success_label = 'bound';
+ }
+
+ // deal with barcodes for *NEW* units
+ var barcodes = {};
+ if (obj.current_sunit_id < 0) { // **AUTO** or **NEW** units
+ new_unit_barcode = '';
+ for (var i = 0; i < list.length; i++) {
+ var item = list[i];
+ if (new_unit_barcode) {
+ barcodes[item.id()] = new_unit_barcode;
+ continue;
+ }
+ var prompt_text;
+ if (obj.current_sunit_id == -1) {
+ prompt_text = 'Please enter a barcode for '+item.issuance().label()+ ' from Distribution: '+item.stream().distribution().label()+'/'+item.stream().id()+':';
+ } else { // must be -2
+ prompt_text = 'Please enter a barcode for new unit:';
+ }
+ var barcode = window.prompt(prompt_text,
+ '',
+ 'Unit Barcode Prompt');
+ barcode = String( barcode ).replace(/\s/g,'');
+ /* Casting a possibly null input value to a String turns it into "null" */
+ if (!barcode || barcode == 'null') {
+ alert('Invalid barcode entered, defaulting to system-generated.');
+ barcode = 'auto';
+ }
+
+ var test = obj.network.simple_request('FM_ACP_RETRIEVE_VIA_BARCODE',[ barcode ]);
+ if (typeof test.ilsevent == 'undefined') {
+ alert('Another copy has barcode "' + barcode + '", defaulting to system-generated.');
+ barcode = 'auto';
+ }
+ barcodes[item.id()] = barcode;
+ if (obj.current_sunit_id == -2) {
+ new_unit_barcode = barcode;
+ }
+ }
+ }
+
+ var robj = obj.network.request(
+ 'open-ils.serial',
+ method,
+ [ ses(), list, barcodes ]
+ );
+ if (typeof robj.ilsevent != 'undefined') throw(robj); //TODO: catch for override
+
+ alert('Successfully '+success_label+' '+robj.num_items+' item(s)');
+
+ if (obj.current_sunit_id == -2) {
+ obj.current_sunit_id = robj.new_unit_id;
+ }
+
+ obj.rebuild_current_sunit(list[0].stream().distribution().label(), list[0].stream().distribution().id(), list[0].stream().id());
+ obj.refresh_list('main');
+ obj.refresh_list('workarea');
+
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert('cmd_receive_items failed!',E);
+ }
+ }
+ ],
+ 'cmd_edit_sunit' : [
+ ['command'],
+ function() {
+ try {
+ /*if (!obj.retrieve_ids || obj.retrieve_ids.length == 0) return;
+
+ JSAN.use('util.functional');
+ var list = util.functional.map_list(
+ obj.retrieve_ids,
+ function (o) {
+ return o.sitem_id;
+ }
+ );
+*/
+ spawn_sunit_editor( { 'sunit_ids' : [1], 'edit' : 1 } ); //FIXME: hard-coded sunit
+
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert('cmd_edit_sunit failed!',E);
+ }
+ }
+ ],
+
+ 'cmd_items_print' : [ ['command'], function() { obj.items_print(obj.selected_list); } ],
+ 'cmd_items_export' : [ ['command'], function() { obj.items_export(obj.selected_list); } ],
+ 'cmd_refresh_list' : [ ['command'], function() { obj.set_sdist_ids(); obj.refresh_list('main'); obj.refresh_list('workarea'); } ]
+ }
+ }
+ );
+
+ obj.retrieve('main'); // retrieve main list
+ obj.retrieve('workarea'); // retrieve shelving unit list
+
+ obj.controller.view.sel_clip.setAttribute('disabled','true');
+
+ },
+
+ 'items_print' : function(which) {
+ var obj = this;
+ try {
+ var list = obj.lists[which];
+/* FIXME: serial items print template? JSAN.use('patron.util');
+ var params = {
+ 'patron' : patron.util.retrieve_fleshed_au_via_id(ses(),obj.patron_id),
+ 'template' : 'items_out'
+ }; */
+ list.print( params );
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert('manage_items printing',E);
+ }
+ },
+
+ 'items_export' : function(which) {
+ var obj = this;
+ try {
+ var list = obj.lists[which];
+ list.dump_csv_to_clipboard();
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert('manage_items export',E);
+ }
+ },
+
+ 'rebuild_current_sunit' : function(sdist_label, sdist_id, sstr_id) {
+ var obj = this;
+ try {
+ var robj = obj.network.request(
+ 'open-ils.pcrud',
+ 'open-ils.pcrud.retrieve.sunit',
+ [ ses(), obj.current_sunit_id]
+ );
+ if (!robj) return; // current sunit is NEW or AUTO
+
+ var label = '[' + sdist_label + '/' + sstr_id + ' #' + obj.current_sunit_id + '] ' + robj.summary_contents();
+ obj.set_sunit(obj.current_sunit_id, label, sdist_id, sstr_id);
+ obj.save_sunit(obj.current_sunit_id, label, sdist_id, sstr_id);
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert('serial items set_sunit',E);
+ }
+ },
+
+ 'set_sunit' : function(sunit_id, label, sdist_id, sstr_id) {
+ var obj = this;
+ try {
+ obj.current_sunit_id = sunit_id;
+ obj.current_sunit_sdist_id = sdist_id;
+ obj.current_sunit_sstr_id = sstr_id;
+ if (sunit_id < 0) {
+ $('serial_workarea_sunit_desc').firstChild.nodeValue = '**' + label + '**';
+ } else {
+ $('serial_workarea_sunit_desc').firstChild.nodeValue = label;
+ obj.add_sunit_to_menu(sunit_id, label, sdist_id, sstr_id);
+ }
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert('serial items set_sunit',E);
+ }
+ },
+
+ 'save_sunit' : function(sunit_id, label, sdist_id, sstr_id) {
+ var obj = this;
+ try {
+ $('serial_items_current_sunit').setAttribute('sunit_id', sunit_id);
+ $('serial_items_current_sunit').setAttribute('sunit_label', label);
+ if (sunit_id > 0) {
+ $('serial_items_current_sunit').setAttribute('sdist_id', sdist_id);
+ $('serial_items_current_sunit').setAttribute('sstr_id', sstr_id);
+ }
+ var recent_sunits_file = new util.file('serial_items_recent_sunits_'+obj.docid+'.'+obj.data.server_unadorned);
+ util.widgets.save_attributes(recent_sunits_file, { 'serial_items_recent_sunits' : [ 'sunit_json' ], 'serial_items_current_sunit' : [ 'sunit_id', 'sunit_label', 'sdist_id', 'sstr_id' ] });
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert('serial items save_sunit',E);
+ }
+ },
+
+ 'set_other_sunit' : function() {
+ var obj = this;
+ try {
+ g.serial_items_sunit_select = '';
+ g.serial_items_sdist_ids = obj.sdist_ids;
+ JSAN.use('util.window'); var win = new util.window();
+ win.open(
+ xulG.url_prefix(urls.XUL_SERIAL_SELECT_UNIT),
+ 'sel_serial_sunit_win_' + win.window_name_increment(),
+ 'chrome,resizable,modal,centerscreen'
+ );
+ if (!g.serial_items_sunit_select) {
+ return;
+ }
+
+ var selection = g.serial_items_sunit_select;
+ var sunit_id = selection.sunit;
+ var sdist_id = selection.sdist;
+ var sstr_id = selection.sstr;
+ var label = selection.label;
+
+ obj.set_sunit(sunit_id, label, sdist_id, sstr_id);
+ obj.save_sunit(sunit_id, label, sdist_id, sstr_id);
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert('serial items set_other_sunit',E);
+ }
+ },
+
+ 'add_sunit_to_menu' : function(sunit_id, label, sdist_id, sstr_id) {
+ var obj = this;
+ try {
+ if (sunit_id > 0) {
+ // check if it is already in sunit_entries, remove it
+ for (i = 0; i < obj.sunit_entries.length; i++) {
+ if (obj.sunit_entries[i].id == sunit_id) {
+ obj.sunit_entries.splice(i,1);
+ var menu_item = $('serial_items_recent_sunits_entry_'+sunit_id);
+ menu_item.parentNode.removeChild(menu_item);
+ i--;
+ }
+ }
+ // add to front of array
+ obj.sunit_entries.unshift({"id" : sunit_id, "label" : label, "sdist_id" : sdist_id, "sstr_id" : sstr_id});
+ var recent_sunits_popup = $('serial_items_recent_sunits');
+ var new_menu_item = recent_sunits_popup.insertItemAt(0,label);
+ new_menu_item.setAttribute('id', 'serial_items_recent_sunits_entry_'+sunit_id);
+ new_menu_item.setAttribute('sunit_id', sunit_id);
+ new_menu_item.setAttribute('sdist_id', sdist_id);
+ new_menu_item.setAttribute('sstr_id', sstr_id);
+ new_menu_item.setAttribute('command', 'cmd_set_sunit');
+
+ // pop off from sunit_entries if it already has 10 sunits
+ if (obj.sunit_entries.length > 10) {
+ var sunit_info = obj.sunit_entries.pop();
+ var menu_item = $('serial_items_recent_sunits_entry_'+sunit_info.id);
+ menu_item.parentNode.removeChild(menu_item);
+ }
+
+ recent_sunits_popup.setAttribute('sunit_json', js2JSON(obj.sunit_entries));
+ }
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert('serial items add_sunit_to_menu',E);
+ }
+ },
+
+ 'set_mode' : function(mode) {
+ var obj = this;
+
+ if (!mode) {
+ mode = obj.mode;
+ } else {
+ obj.mode = mode;
+ }
+
+ if (mode == 'receive') {
+ $('serial_workarea_mode_label').value = 'Recently Received';
+ if ($('serial_manage_items_show_all').checked) {
+ obj.lists.main.sitem_retrieve_params = {};
+ } else {
+ obj.lists.main.sitem_retrieve_params = {'date_received' : null };
+ }
+ obj.lists.main.sitem_extra_params ={'order_by' : {'sitem' : 'date_expected ASC, stream ASC'}};
+
+ obj.lists.workarea.sitem_retrieve_params = {'date_received' : {"!=" : null}};
+ obj.lists.workarea.sitem_extra_params ={'order_by' : {'sitem' : 'date_received DESC'}, 'limit' : 30};
+ } else { // bind mode
+ $('serial_workarea_mode_label').value = 'Bound Items in Current Working Unit';
+ if ($('serial_manage_items_show_all').checked) {
+ obj.lists.main.sitem_retrieve_params = {};
+ } else {
+ obj.lists.main.sitem_retrieve_params = {'date_received' : {'!=' : null}, 'status' : {'!=' : 'Bindery'} };
+ }
+ obj.lists.main.sitem_extra_params ={'order_by' : {'sitem' : 'date_expected ASC, stream ASC'}};
+
+ obj.lists.workarea.sitem_retrieve_params = {'status' : 'Bindery'}; // unit set dynamically in 'retrieve'
+ obj.lists.workarea.sitem_extra_params ={'order_by' : {'sitem' : 'date_received DESC'}};
+
+ // default to **NEW UNIT**
+ obj.set_sunit(-2, 'New Unit', '', '');
+ }
+ },
+
+ 'save_settings' : function() {
+ var obj = this;
+
+ JSAN.use('util.file'); var file = new util.file('serial_items_prefs.'+obj.data.server_unadorned);
+ util.widgets.save_attributes(file, { 'serial_item_lib_menu' : [ 'value' ], 'mode_receive' : [ 'selected' ], 'mode_bind' : [ 'selected' ], 'serial_manage_items_show_all' : [ 'checked' ] });
+ },
+
+ 'init_lists' : function() {
+ var obj = this;
+
+ JSAN.use('circ.util');
+ var columns = item_columns({});
+
+ function retrieve_row(params) {
+ try {
+ var row = params.row;
+ obj.network.simple_request(
+ 'FM_SITEM_FLESHED_BATCH_RETRIEVE.authoritative',
+ [[row.my.sitem_id]],
+ //[ ses(), row.my.sitem_id, {"flesh":2,"flesh_fields":{"sitem":["creator","editor","issuance","stream","unit","notes"], "sunit":["call_number"], "sstr":["distribution"]}}],
+ function(req) {
+ try {
+ var robj = req.getResultObject();
+ if (typeof robj.ilsevent != 'undefined') throw(robj);
+ if (typeof robj.ilsevent == 'null') throw('null result');
+ var sitem = robj[0];
+ obj.list_sitem_map[sitem.id()] = sitem;
+ row.my.sitem = sitem;
+ //params.row_node.setAttribute( 'retrieve_id', js2JSON({'copy_id':copy_id,'circ_id':row.my.circ.id(),'barcode':row.my.acp.barcode(),'doc_id': ( row.my.record ? row.my.record.id() : null ) }) );
+ params.row_node.setAttribute( 'retrieve_id', js2JSON({'sitem_id':sitem.id()}) );
+ dump('dumping... ' + js2JSON(obj.list_sitem_map[sitem.id()]));
+ if (typeof params.on_retrieve == 'function') {
+ params.on_retrieve(row);
+ }
+
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert('staff.serial.manage_items.retrieve_row.callback_error', E);
+ }
+ }
+ );
+ return row;
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert('staff.serial.manage_items.retrieve_row.error_in_retrieve_row',E);
+ return params.row;
+ }
+ }
+
+ JSAN.use('util.list');
+
+ obj.lists = {};
+ obj.lists.main = new util.list('item_tree');
+ obj.lists.main.init(
+ {
+ 'columns' : columns,
+ 'map_row_to_columns' : circ.util.std_map_row_to_columns(),
+ 'retrieve_row' : retrieve_row,
+ 'on_select' : function(ev) {
+ obj.selected_list = 'main';
+ JSAN.use('util.functional');
+ var sel = obj.lists.main.retrieve_selection();
+ obj.controller.view.sel_clip.setAttribute('disabled',sel.length < 1);
+ var list = util.functional.map_list(
+ sel,
+ function(o) { return JSON2js( o.getAttribute('retrieve_id') ); }
+ );
+ if (typeof obj.on_select == 'function') {
+ obj.on_select(list);
+ }
+ if (typeof window.xulG == 'object' && typeof window.xulG.on_select == 'function') {
+ obj.error.sdump('D_CAT','manage_items: Calling external .on_select()\n');
+ window.xulG.on_select(list);
+ }
+ }
+ }
+ );
+
+ obj.lists.workarea = new util.list('workarea_tree');
+ obj.lists.workarea.init(
+ {
+ 'columns' : columns,
+ 'map_row_to_columns' : circ.util.std_map_row_to_columns(),
+ 'retrieve_row' : retrieve_row,
+ 'on_select' : function(ev) {
+ obj.selected_list = 'workarea';
+ JSAN.use('util.functional');
+ var sel = obj.lists.workarea.retrieve_selection();
+ obj.controller.view.sel_clip.setAttribute('disabled',sel.length < 1);
+ var list = util.functional.map_list(
+ sel,
+ function(o) { return JSON2js( o.getAttribute('retrieve_id') ); }
+ );
+ if (typeof obj.on_select == 'function') {
+ obj.on_select(list);
+ }
+ if (typeof window.xulG == 'object' && typeof window.xulG.on_select == 'function') {
+ obj.error.sdump('D_CAT','serctrl: Calling external .on_select()\n');
+ window.xulG.on_select(list);
+ } else {
+ obj.error.sdump('D_CAT','serctrl: No external .on_select()\n');
+ }
+ }
+ }
+ );
+ },
+
+ 'refresh_list' : function(list_name) {
+ var obj = this;
+
+ //TODO Optimize this?
+ obj.retrieve(list_name);
+ },
+
+ 'retrieve' : function(list_name) {
+ var obj = this;
+ var list = obj.lists[list_name];
+
+ list.clear();
+
+ if (!obj.sdist_ids.length) { // no sdists to retrieve items for
+ return;
+ }
+
+ var rparams = list.sitem_retrieve_params;
+ var robj;
+ rparams['+sstr'] = { "distribution" : obj.sdist_ids };
+
+ if (obj.mode == 'bind' && list_name == 'workarea') {
+ rparams['unit'] = obj.current_sunit_id;
+ }
+
+ var other_params = list.sitem_extra_params;
+ other_params.join = 'sstr';
+
+ robj = obj.network.simple_request(
+ 'FM_SITEM_ID_LIST',
+ [ ses(), rparams, other_params ]
+ );
+ if (!robj) {
+ robj = [];
+ } else if (typeof robj.ilsevent!='undefined') {
+ obj.error.standard_unexpected_error_alert('Failed to retrieve serial item ID list',E);
+ } else if (!robj.length) {
+ robj = [robj];
+ }
+
+ for (i = 0; i < robj.length; i++) {
+ list.append( { 'row' : { 'my' : { 'sitem_id' : robj[i] } }, 'to_bottom' : true, 'no_auto_select' : true } );
+ }
+ },
+
+ 'on_select' : function(list) {
+
+ dump('manage_items.on_select list = ' + js2JSON(list) + '\n');
+
+ var obj = this;
+
+ /*obj.controller.view.cmd_items_claimed_returned.setAttribute('disabled','false');
+ obj.controller.view.sel_mark_items_missing.setAttribute('disabled','false');*/
+
+ obj.retrieve_ids = list;
+ }
+}
+
+function item_columns(modify,params) {
+
+ JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
+ //JSAN.use('util.network'); var network = new util.network();
+
+ var c = [
+ {
+ 'id' : 'sitem_id',
+ 'label' : 'Item ID',
+ 'flex' : 1,
+ 'primary' : false,
+ 'hidden' : false,
+ 'render' : function(my) { return my.sitem.id(); },
+ 'persist' : 'hidden width ordinal'
+ },
+ {
+ 'id' : 'label',
+ 'label' : 'Issuance Label',
+ 'flex' : 1,
+ 'primary' : false,
+ 'hidden' : false,
+ 'render' : function(my) { return my.sitem.issuance().label(); },
+ 'persist' : 'hidden width ordinal'
+ },
+ {
+ 'id' : 'distribution',
+ 'label' : 'Distribution',
+ 'flex' : 1,
+ 'primary' : false,
+ 'hidden' : false,
+ 'persist' : 'hidden width ordinal',
+ 'render' : function(my) { return my.sitem.stream().distribution().label(); }
+ },
+ {
+ 'id' : 'stream_id',
+ 'label' : 'Stream ID',
+ 'flex' : 1,
+ 'primary' : false,
+ 'hidden' : false,
+ 'persist' : 'hidden width ordinal',
+ 'render' : function(my) { return my.sitem.stream().id(); }
+ },
+ {
+ 'id' : 'date_published',
+ 'label' : 'Date Published',
+ 'flex' : 1,
+ 'primary' : false,
+ 'hidden' : false,
+ 'render' : function(my) { return my.sitem.issuance().date_published().substr(0,10); },
+ 'persist' : 'hidden width ordinal'
+ },
+ {
+ 'id' : 'date_expected',
+ 'label' : 'Date Expected',
+ 'flex' : 1,
+ 'primary' : false,
+ 'hidden' : false,
+ 'render' : function(my) { return my.sitem.date_expected().substr(0,10); },
+ 'persist' : 'hidden width ordinal'
+ },
+ {
+ 'id' : 'date_received',
+ 'label' : 'Date Received',
+ 'flex' : 1,
+ 'primary' : false,
+ 'hidden' : false,
+ 'render' : function(my) { return my.sitem.date_received().substr(0,10); },
+ 'persist' : 'hidden width ordinal'
+ },
+ {
+ 'id' : 'notes',
+ 'label' : 'Notes',
+ 'flex' : 1,
+ 'primary' : false,
+ 'hidden' : false,
+ 'render' : function(my) { return my.sitem.notes().length; },
+ 'persist' : 'hidden width ordinal'
+ },
+ {
+ 'id' : 'call_number',
+ 'label' : 'Call Number',
+ 'flex' : 1,
+ 'primary' : false,
+ 'hidden' : false,
+ 'persist' : 'hidden width ordinal',
+ 'render' : function(my) { return my.sitem.unit().call_number().label(); }
+ },
+ {
+ 'id' : 'unit_id_contents',
+ 'label' : 'Unit ID / Contents',
+ 'flex' : 1,
+ 'primary' : false,
+ 'hidden' : false,
+ 'render' : function(my) { return '[' + my.sitem.unit().id() + '] ' + my.sitem.unit().summary_contents() ; },
+ 'persist' : 'hidden width ordinal'
+ },
+ {
+ 'id' : 'creator',
+ 'label' : 'Creator',
+ 'flex' : 1,
+ 'primary' : false,
+ 'hidden' : true,
+ 'persist' : 'hidden width ordinal',
+ 'render' : function(my) { return my.sitem.creator().usrname(); }
+ },
+ {
+ 'id' : 'create_date',
+ 'label' : document.getElementById('circStrings').getString('staff.circ.utils.create_date'),
+ 'flex' : 1,
+ 'primary' : false,
+ 'hidden' : true,
+ 'persist' : 'hidden width ordinal',
+ 'render' : function(my) { return my.sitem.create_date().substr(0,10); }
+ },
+ {
+ 'id' : 'editor',
+ 'label' : 'Editor',
+ 'flex' : 1,
+ 'primary' : false,
+ 'hidden' : true,
+ 'persist' : 'hidden width ordinal',
+ 'render' : function(my) { return my.sitem.editor().usrname(); }
+ },
+ {
+ 'id' : 'edit_date',
+ 'label' : document.getElementById('circStrings').getString('staff.circ.utils.edit_date'),
+ 'flex' : 1,
+ 'primary' : false,
+ 'hidden' : false,
+ 'persist' : 'hidden width ordinal',
+ 'render' : function(my) { return my.sitem.edit_date().substr(0,10); }
+ },
+ {
+ 'id' : 'holding_code',
+ 'label' : 'Holding Code',
+ 'flex' : 1,
+ 'primary' : false,
+ 'hidden' : true,
+ 'render' : function(my) { return my.sitem.issuance().holding_code(); },
+ 'persist' : 'hidden width ordinal'
+ },
+ {
+ 'id' : 'holding_type',
+ 'label' : 'Holding Type',
+ 'flex' : 1,
+ 'primary' : false,
+ 'hidden' : true,
+ 'render' : function(my) { return my.sitem.issuance().holding_type(); },
+ 'persist' : 'hidden width ordinal'
+ },
+ {
+ 'id' : 'holding_link_id',
+ 'label' : 'Holding Link ID',
+ 'flex' : 1,
+ 'primary' : false,
+ 'hidden' : true,
+ 'render' : function(my) { return my.sitem.issuance().holding_link_id(); },
+ 'persist' : 'hidden width ordinal'
+ }
+ ];
+ for (var i = 0; i < c.length; i++) {
+ if (modify[ c[i].id ]) {
+ for (var j in modify[ c[i].id ]) {
+ c[i][j] = modify[ c[i].id ][j];
+ }
+ }
+ }
+ if (params) {
+ if (params.just_these) {
+ JSAN.use('util.functional');
+ var new_c = [];
+ for (var i = 0; i < params.just_these.length; i++) {
+ var x = util.functional.find_list(c,function(d){return(d.id==params.just_these[i]);});
+ new_c.push( function(y){ return y; }( x ) );
+ }
+ c = new_c;
+ }
+ if (params.except_these) {
+ JSAN.use('util.functional');
+ var new_c = [];
+ for (var i = 0; i < c.length; i++) {
+ var x = util.functional.find_list(params.except_these,function(d){return(d==c[i].id);});
+ if (!x) new_c.push(c[i]);
+ }
+ c = new_c;
+ }
+ }
+ //return c.sort( function(a,b) { if (a.label < b.label) return -1; if (a.label > b.label) return 1; return 0; } );
+ return c;
+};
+
+spawn_sitem_editor = function(params) {
+ try {
+ if (!params.sitem_ids && !params.sitems) return;
+ if (params.sitem_ids && params.sitem_ids.length == 0) return;
+ if (params.sitems && params.sitems.length == 0) return;
+ if (params.sitem_ids) params.sitem_ids = js2JSON(params.sitem_ids); // legacy
+ if (!params.caller_handles_update) params.handle_update = 1; // legacy
+
+ var obj = {};
+ JSAN.use('util.network'); obj.network = new util.network();
+ JSAN.use('util.error'); obj.error = new util.error();
+
+ var title = '';
+ if (params.sitem_ids && params.sitem_ids.length > 1 && params.do_edit == 1)
+ title = 'Batch Edit Items';
+ else /* if(params.sitems && params.sitems.length > 1 && params.do_edit == 1)
+ title = 'Batch View Items';
+ else if(params.sitem_ids && params.sitem_ids.length == 1) */
+ title = 'Edit Item';/*
+ else
+ title = 'View Item';*/
+
+ JSAN.use('util.window'); var win = new util.window();
+ params.in_modal = true;
+ var my_xulG = win.open(
+ (urls.XUL_SERIAL_ITEM_EDITOR),
+ title,
+ 'chrome,modal,resizable',
+ params
+ );
+ if (my_xulG.sitems && params.do_edit) {
+ return my_xulG.sitems;
+ } else {
+ return [];
+ }
+ } catch(E) {
+ JSAN.use('util.error'); var error = new util.error();
+ error.standard_unexpected_error_alert('error in spawn_sitem_editor',E);
+ }
+}
+
+dump('exiting manage_items.js\n');
--- /dev/null
+<?xml version="1.0"?>
+<!-- Application: Evergreen Staff Client -->
+<!-- Screen: Manage Items Overlay -->
+<!--
+vim:noet:sw=4:ts=4:
+-->
+<!DOCTYPE overlay PUBLIC "" ""[
+ <!--#include virtual="/opac/locale/${locale}/lang.dtd"-->
+]>
+
+<overlay id="serial_manage_items_overlay"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script type="text/javascript" src="/xul/server/serial/manage_items.js"/>
+ <script>
+ <![CDATA[
+ function my_init() {
+ try {
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ if (typeof JSAN == 'undefined') {
+ throw( document.getElementById("commonStrings").getString('common.jsan.missing') );
+ }
+ JSAN.errorLevel = "die"; // none, warn, or die
+ JSAN.addRepository('/xul/server/');
+ JSAN.use('util.error'); g.error = new util.error();
+ g.error.sdump('D_TRACE','my_init() for manage_items.xul');
+
+ JSAN.use('serial.manage_items'); g.manage_items = new serial.manage_items();
+
+ //g.manage_items.init( { 'sre_id' : xul_param('sre_id'), 'sdist_id' : xul_param('sdist_id') } );
+ g.manage_items.init( { 'docid' : xul_param('docid') } );
+
+ } catch(E) {
+ var err_msg = document.getElementById("commonStrings").getFormattedString('common.exception', ['serial/manage_items.xul', E]);
+ try { g.error.sdump('D_ERROR',err_msg); } catch(E) { dump(err_msg); }
+ alert(err_msg);
+ }
+ }
+
+ ]]>
+ </script>
+ <popupset>
+ <popup id="serial_manage_items_popup">
+ <menuitem command="cmd_edit_items" label="Edit Item Attributes" accesskey="&staff.cat.copy_browser.actions.cmd_edit_items.accesskey;"/>
+ <menuitem command="cmd_delete_items" label="Delete Item" accesskey="&staff.cat.copy_browser.actions.cmd_delete_items.accesskey;"/>
+ </popup>
+ </popupset>
+ <tabpanel id="serial_manage_items" orient="vertical" flex="1">
+ <hbox align="center">
+ <hbox id="serial_item_lib_menu_box"/>
+ <label value="Mode:" control="mode_receive"/><radiogroup id="serial_manage_items_mode" orient="horizontal"><radio id="mode_receive" label="Receive"/><radio id="mode_bind" label="Bind"/></radiogroup><checkbox id="serial_manage_items_show_all" label="Show All" />
+ <button id="refresh_button" label="&staff.cat.copy_browser.holdings_maintenance.refresh_button.label;" command="cmd_refresh_list" />
+ <spacer flex="1"/>
+ <menubar>
+ <!--
+ <menu label="Actions for this Serial Control" accesskey="C">
+ <menupopup>
+ <menuitem command="cmd_predict_items" label="Predict Items"/>
+ <menuitem command="cmd_add_item" label="Add Custom Item"/>
+ <menuitem command="cmd_edit_mfhd" label="Edit MFHD Record"/>
+ </menupopup>
+ </menu>
+ -->
+ <menu label="&staff.cat.copy_browser.holdings_maintenance.actions.label;" accesskey="&staff.cat.copy_browser.holdings_maintenance.actions.accesskey;">
+ <menupopup>
+ <menuitem command="cmd_edit_items" label="Edit Item Attributes" accesskey="&staff.cat.copy_browser.actions.cmd_edit_items.accesskey;"/>
+ <menuitem command="cmd_delete_items" label="Delete Item" accesskey="&staff.cat.copy_browser.actions.cmd_delete_items.accesskey;"/>
+ <menuseparator/>
+ <menuitem command="cmd_refresh_list" label="&staff.cat.copy_browser.holdings_maintenance.cmd_refresh_list.label;" accesskey="&staff.cat.copy_browser.holdings_maintenance.cmd_refresh_list.accesskey;"/>
+ <menuitem command="save_columns" label="&staff.cat.copy_browser.holdings_maintenance.save_columns.label;"/>
+ <!-- <menuitem command="sel_clip" label="&staff.cat.copy_browser.holdings_maintenance.sel_clip.label;" accesskey="&staff.cat.copy_browser.holdings_maintenance.sel_clip.accesskey;"/>
+ <menuitem command="cmd_transfer_items" label="&staff.cat.copy_browser.holdings_maintenance.cmd_transfer_items.label;" accesskey="&staff.cat.copy_browser.holdings_maintenance.cmd_transfer_items.accesskey;"/>
+ <menuseparator/>
+ <menuitem command="cmd_add_volumes" label="&staff.cat.copy_browser.holdings_maintenance.cmd_add_volumes.label;" accesskey="&staff.cat.copy_browser.holdings_maintenance.cmd_add_volumes.accesskey;"/>
+ <menuitem command="cmd_edit_volumes" label="&staff.cat.copy_browser.holdings_maintenance.cmd_edit_volumes.label;" accesskey="&staff.cat.copy_browser.holdings_maintenance.cmd_edit_volumes.accesskey;"/>
+ <menuitem command="cmd_mark_volume" label="&staff.cat.copy_browser.holdings_maintenance.cmd_mark_volume.label;" accesskey="&staff.cat.copy_browser.holdings_maintenance.cmd_mark_volume.accesskey;"/>
+ <menuitem command="cmd_transfer_volume" label="&staff.cat.copy_browser.holdings_maintenance.cmd_transfer_volume.label;" accesskey="&staff.cat.copy_browser.holdings_maintenance.cmd_transfer_volume.accesskey;"/>
+ <menuitem command="cmd_delete_volumes" label="&staff.cat.copy_browser.holdings_maintenance.cmd_delete_volumes.label;" accesskey=""/>
+ <menuseparator/>
+ <menuitem command="cmd_print_spine_labels" label="&staff.cat.copy_browser.holdings_maintenance.cmd_print_spine_labels.label;" accesskey="&staff.cat.copy_browser.holdings_maintenance.cmd_print_spine_labels.accesskey;"/>
+ <menuitem command="cmd_replace_barcode" label="&staff.cat.copy_browser.holdings_maintenance.cmd_replace_barcode.label;" accesskey=""/> -->
+ </menupopup>
+ </menu>
+ </menubar>
+ </hbox>
+ <tree id="item_tree" flex="2" enableColumnDrag="true" context="serial_manage_items_popup"/>
+ <splitter state="open" collapse="after" resizebefore="closest" resizeafter="farthest"/>
+ <hbox align="center">
+ <label style="font-weight: bold" value="Showing: "/>
+ <label id="serial_workarea_mode_label" value="Recently Received"/>
+ <spacer flex="1"/>
+ <button label="Receive/Move Selected ↓" command="cmd_receive_items"/>
+ </hbox>
+ <hbox align="center">
+ <label style="font-weight: bold" value="Current Working Unit: "/>
+ <description flex="1" id="serial_workarea_sunit_desc">**Auto per Item**</description>
+ <spacer flex="1"/>
+ <menubar>
+ <menu label="Set Current Unit" id="serial_items_current_sunit" sunit_id="-1" sunit_label="Auto per Item" sdist_id="" sstr_id="">
+ <menupopup>
+ <menuitem command="cmd_set_sunit" label="New Unit" sunit_id="-2" sdist_id="" sstr_id=""/>
+ <menuitem command="cmd_set_sunit" label="Auto per Item" sunit_id="-1" sdist_id="" sstr_id=""/>
+ <menu label="Recent" id="serial_items_recent_sunits" sunit_json='[]'/>
+ <menuitem command="cmd_set_other_sunit" label="Other..."/>
+ </menupopup>
+ </menu>
+ <button command="cmd_broken" label="Edit Current Unit..."/>
+ </menubar>
+ </hbox>
+ <tree id="workarea_tree" flex="1" enableColumnDrag="true" context="serial_manage_items_popup"/>
+ </tabpanel>
+
+</overlay>
--- /dev/null
+dump('entering serial/manage_subs.js\n');
+// vim:noet:sw=4:ts=4:
+
+if (typeof serial == 'undefined') serial = {};
+serial.manage_subs = function (params) {
+ try {
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ JSAN.use('util.error'); this.error = new util.error();
+ } catch(E) {
+ dump('serial/manage_subs: ' + E + '\n');
+ }
+};
+
+serial.manage_subs.prototype = {
+
+ 'map_tree' : {},
+ 'map_ssub' : {},
+ 'map_sdist' : {},
+ 'map_siss' : {},
+ 'map_scap' : {},
+ 'sel_list' : [],
+ 'funcs' : [],
+ 'editor_indexes' : { 'ssub' : 1, 'sdist' : 2, 'siss' : 3, 'scap' : 4 },
+
+ 'ids_from_sel_list' : function(type) {
+ var obj = this;
+ JSAN.use('util.functional');
+
+ var list = util.functional.map_list(
+ util.functional.filter_list(
+ obj.sel_list,
+ function (o) {
+ return o.split(/_/)[0] == type;
+ }
+ ),
+ function (o) {
+ return o.split(/_/)[1];
+ }
+ );
+
+ return list;
+ },
+
+ 'editor_init' : function(type, mode, params) {
+ var obj = this;
+ try {
+ $('serial_manage_subs_editor_deck').selectedIndex = obj.editor_indexes[type];
+ var editor_type = type + '_editor';
+ if (typeof obj[editor_type] == 'undefined') {
+ JSAN.use('serial.' + editor_type);
+ obj[editor_type] = new serial[editor_type]();
+ }
+
+ params.do_edit = true;
+ params.handle_update = true;
+ if (mode == 'add') {
+ params.trigger_refresh = true;
+ params.refresh_command = function () {obj.refresh_list();};
+ }
+ obj[editor_type].init(params);
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert('editor_init() error',E);
+ }
+ },
+
+ 'do_delete' : function(type, method, overridable_events) {
+ var obj = this;
+ try {
+ JSAN.use('util.functional');
+
+ var list = util.functional.filter_list(
+ obj.sel_list,
+ function (o) {
+ return o.split(/_/)[0] == type;
+ }
+ );
+
+ list = util.functional.map_list(
+ list,
+ function (o) {
+ return JSON2js( js2JSON( obj['map_' + type][ type + '_' + o.split(/_/)[1] ] ) );
+ }
+ );
+
+ //TODO: proper messages
+ var delete_msg;
+ if (list.length != 1) {
+ delete_msg = document.getElementById('serialStrings').getFormattedString('staff.serial.manage_subs.delete_' + type + '.confirm.plural', [list.length]);
+ } else {
+ delete_msg = document.getElementById('serialStrings').getString('staff.serial.manage_subs.delete_' + type + '.confirm');
+ }
+ var r = obj.error.yns_alert(
+ delete_msg,
+ document.getElementById('serialStrings').getString('staff.serial.manage_subs.delete_' + type + '.title'),
+ document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_items.delete'),
+ document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_items.cancel'),
+ null,
+ document.getElementById('commonStrings').getString('common.confirm')
+ );
+
+ if (r == 0) {
+ for (var i = 0; i < list.length; i++) {
+ list[i].isdeleted('1');
+ }
+ var robj = obj.network.request(
+ 'open-ils.serial',
+ method,
+ [ ses(), list, true ],
+ null,
+ {
+ 'title' : document.getElementById('serialStrings').getString('staff.serial.manage_subs.delete_' + type + '.override'),
+ 'overridable_events' : overridable_events
+ }
+ );
+ if (robj == null) throw(robj);
+ if (typeof robj.ilsevent != 'undefined') {
+ if (robj.ilsevent != 0) {
+ var overridable = false;
+ for (i = 0; i < overridable_events.length; i++) {
+ if (overridable_events[i] == robj.ilsevent) {
+ overridable = true;
+ break;
+ }
+ }
+ if (!overridable) throw(robj);
+ }
+ }
+ obj.refresh_list();
+ }
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert(document.getElementById('serialStrings').getString('staff.serial.manage_subs.delete.error'),E);
+ obj.refresh_list();
+ }
+ },
+
+ 'init' : function( params ) {
+
+ try {
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ var obj = this;
+
+ obj.docid = params.docid;
+
+ JSAN.use('util.network'); obj.network = new util.network();
+ JSAN.use('OpenILS.data'); obj.data = new OpenILS.data(); obj.data.init({'via':'stash'});
+ JSAN.use('util.controller'); obj.controller = new util.controller();
+ obj.controller.init(
+ {
+ control_map : {
+ 'save_columns' : [ [ 'command' ], function() { obj.list.save_columns(); } ],
+ 'sel_clip' : [
+ ['command'],
+ function() { obj.list.clipboard(); }
+ ],
+ 'cmd_broken' : [
+ ['command'],
+ function() {
+ alert(document.getElementById('commonStrings').getString('common.unimplemented'));
+ }
+ ],
+ 'cmd_show_my_libs' : [
+ ['command'],
+ function() {
+ obj.show_my_libs();
+ }
+ ],
+ 'cmd_show_all_libs' : [
+ ['command'],
+ function() {
+ obj.show_all_libs();
+ }
+ ],
+ 'cmd_show_libs_with_distributions' : [
+ ['command'],
+ function() {
+ obj.show_libs_with_distributions();
+ }
+ ],
+ 'cmd_clear' : [
+ ['command'],
+ function() {
+ obj.map_tree = {};
+ obj.list.clear();
+ }
+ ],
+ 'cmd_add_scap' : [
+ ['command'],
+ function() {
+ try {
+ var list = obj.ids_from_sel_list('ssub');
+ if (list.length == 0) list = obj.ids_from_sel_list('scap-group');
+ if (list.length == 0) return;
+
+ /*TODO: permission check?
+ //populate 'list' with owning_libs of subs, TODO
+ var edit = 0;
+ try {
+ edit = obj.network.request(
+ api.PERM_MULTI_ORG_CHECK.app,
+ api.PERM_MULTI_ORG_CHECK.method,
+ [
+ ses(),
+ obj.data.list.au[0].id(),
+ list,
+ [ 'CREATE_COPY' ]
+ ]
+ ).length == 0 ? 1 : 0;
+ } catch(E) {
+ obj.error.sdump('D_ERROR','batch permission check: ' + E);
+ }
+
+ if (edit==0) return; // no read-only view for this interface */
+ var new_scap = new scap();
+ new_scap.subscription(list[0]);//TODO: add multiple at once support?
+ new_scap.isnew(1);
+ var params = {};
+ params.scaps = [new_scap];
+ obj.editor_init('scap', 'add', params);
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert(document.getElementById('serialStrings').getString('staff.serial.manage_subs.add.error'),E);
+ }
+ }
+ ],
+ 'cmd_add_siss' : [
+ ['command'],
+ function() {
+ try {
+ var list = obj.ids_from_sel_list('ssub');
+ if (list.length == 0) list = obj.ids_from_sel_list('siss-group');
+ if (list.length == 0) return;
+
+ /*TODO: permission check?
+ //populate 'list' with owning_libs of subs, TODO
+ var edit = 0;
+ try {
+ edit = obj.network.request(
+ api.PERM_MULTI_ORG_CHECK.app,
+ api.PERM_MULTI_ORG_CHECK.method,
+ [
+ ses(),
+ obj.data.list.au[0].id(),
+ list,
+ [ 'CREATE_COPY' ]
+ ]
+ ).length == 0 ? 1 : 0;
+ } catch(E) {
+ obj.error.sdump('D_ERROR','batch permission check: ' + E);
+ }
+
+ if (edit==0) return; // no read-only view for this interface */
+ var new_siss = new siss();
+ new_siss.subscription(list[0]);//TODO: add multiple at once support?
+ new_siss.isnew(1);
+ var params = {};
+ params.sisses = [new_siss];
+ obj.editor_init('siss', 'add', params);
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert(document.getElementById('serialStrings').getString('staff.serial.manage_subs.add.error'),E);
+ }
+ }
+ ],
+ 'cmd_add_sdist' : [
+ ['command'],
+ function() {
+ try {
+ var list = obj.ids_from_sel_list('ssub');
+ if (list.length == 0) list = obj.ids_from_sel_list('sdist-group');
+ if (list.length == 0) return;
+
+ /*TODO: permission check?
+ //populate 'list' with owning_libs of subs, TODO
+ var edit = 0;
+ try {
+ edit = obj.network.request(
+ api.PERM_MULTI_ORG_CHECK.app,
+ api.PERM_MULTI_ORG_CHECK.method,
+ [
+ ses(),
+ obj.data.list.au[0].id(),
+ list,
+ [ 'CREATE_COPY' ]
+ ]
+ ).length == 0 ? 1 : 0;
+ } catch(E) {
+ obj.error.sdump('D_ERROR','batch permission check: ' + E);
+ }
+
+ if (edit==0) return; // no read-only view for this interface */
+ var new_sdist = new sdist();
+ new_sdist.subscription(list[0]);//TODO: add multiple at once support?
+ new_sdist.holding_lib(obj.map_ssub['ssub_' + list[0]].owning_lib());//default to sub owning lib
+ new_sdist.label('Default');
+ new_sdist.isnew(1);
+ var params = {};
+ params.sdists = [new_sdist];
+ obj.editor_init('sdist', 'add', params);
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert(document.getElementById('serialStrings').getString('staff.serial.manage_subs.add.error'),E);
+ }
+ }
+ ],
+ 'cmd_delete_scap' : [
+ ['command'],
+ function() {
+ var overridable_events = [
+ 11001 // SERIAL_CAPTION_AND_PATTERN_HAS_ISSUANCES
+ ];
+ obj.do_delete('scap', 'open-ils.serial.caption_and_pattern.batch.update', overridable_events);
+ }
+ ],
+ 'cmd_delete_sdist' : [
+ ['command'],
+ function() {
+ var overridable_events = [ //TODO: proper overrides
+ ];
+ obj.do_delete('sdist', 'open-ils.serial.distribution.fleshed.batch.update', overridable_events);
+ }
+ ],
+ 'cmd_delete_siss' : [
+ ['command'],
+ function() {
+ var overridable_events = [ //TODO: proper overrides
+ ];
+ obj.do_delete('siss', 'open-ils.serial.issuance.fleshed.batch.update', overridable_events);
+ }
+ ],
+ 'cmd_delete_ssub' : [
+ ['command'],
+ function() {
+ var overridable_events = [
+ 11000 // SERIAL_SUBSCRIPTION_NOT_EMPTY
+ ];
+ obj.do_delete('ssub', 'open-ils.serial.subscription.fleshed.batch.update', overridable_events);
+ }
+ ],
+ /*dbw2 'cmd_delete_ssub' : [
+ ['command'],
+ function() {
+ try {
+ JSAN.use('util.functional');
+
+ var list = util.functional.filter_list(
+ obj.sel_list,
+ function (o) {
+ return o.split(/_/)[0] == 'ssub';
+ }
+ );
+
+ list = util.functional.map_list(
+ list,
+ function (o) {
+ return JSON2js( js2JSON( obj.map_ssub[ 'ssub_' + o.split(/_/)[1] ] ) );
+ }
+ );
+
+ var del_prompt;
+ if (list.length == 1) {
+ //TODO: correct prompts
+ del_prompt = document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_volume.prompt');
+ } else {
+ del_prompt = document.getElementById('catStrings').getFormattedString('staff.cat.copy_browser.delete_volume.prompt.plural', [list.length]);
+ }
+
+ var r = obj.error.yns_alert(
+ del_prompt,
+ document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_volume.title'),
+ document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_volume.delete'),
+ document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_volume.cancel'),
+ null,
+ document.getElementById('commonStrings').getString('common.confirm')
+ );
+
+ if (r == 0) {
+ for (var i = 0; i < list.length; i++) {
+ list[i].isdeleted('1');
+ }
+ var robj = obj.network.simple_request(
+ 'FM_ACN_TREE_UPDATE',
+ [ ses(), list, true ],
+ null,
+ {
+ 'title' : document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_volume.override'),
+ 'overridable_events' : [
+ ]
+ }
+ );
+ if (robj == null) throw(robj);
+ if (typeof robj.ilsevent != 'undefined') {
+ if (robj.ilsevent == 1206 ) { // VOLUME_NOT_EMPTY
+ alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_volume.copies_remain'));
+ return;
+ }
+ if (robj.ilsevent != 0) throw(robj);
+ }
+ alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_volume.success'));
+ obj.refresh_list();
+ }
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_volume.exception'),E);
+ obj.refresh_list();
+ }
+
+ }
+ ], dbw2*/
+ 'cmd_mark_library' : [
+ ['command'],
+ function() {
+ try {
+ var list = obj.ids_from_sel_list('aou');
+ if (list.length == 1) {
+ obj.data.marked_library = { 'lib' : list[0], 'docid' : obj.docid };
+ obj.data.stash('marked_library');
+ alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.mark_library.alert'));
+ } else {
+ obj.error.yns_alert(
+ document.getElementById('catStrings').getString('staff.cat.copy_browser.mark_library.prompt'),
+ document.getElementById('catStrings').getString('staff.cat.copy_browser.mark_library.title'),
+ document.getElementById('commonStrings').getString('common.ok'),
+ null,
+ null,
+ document.getElementById('commonStrings').getString('common.confirm')
+ );
+ }
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert('manage_subs.js -> mark library',E);
+ }
+ }
+ ],
+
+ 'cmd_mark_subscription' : [
+ ['command'],
+ function() {
+ try {
+ var list = obj.ids_from_sel_list('ssub');
+ if (list.length == 1) {
+ obj.data.marked_subscription = list[0];
+ obj.data.stash('marked_subscription');
+ alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.mark_volume.alert'));
+ } else {
+ obj.error.yns_alert(
+ document.getElementById('catStrings').getString('staff.cat.copy_browser.mark_volume.prompt'),
+ document.getElementById('catStrings').getString('staff.cat.copy_browser.mark_volume.title'),
+ document.getElementById('commonStrings').getString('common.ok'),
+ null,
+ null,
+ document.getElementById('commonStrings').getString('common.confirm')
+ );
+ }
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert('manage_subs.js -> mark subscription',E);
+ }
+ }
+ ],
+ 'cmd_add_subscriptions' : [
+ ['command'],
+ function() {
+ try {
+ var list = obj.ids_from_sel_list('aou');
+ if (list.length == 0) return;
+ //TODO: permission check?
+ /*var edit = 0;
+ try {
+ edit = obj.network.request(
+ api.PERM_MULTI_ORG_CHECK.app,
+ api.PERM_MULTI_ORG_CHECK.method,
+ [
+ ses(),
+ obj.data.list.au[0].id(),
+ list,
+ [ 'CREATE_VOLUME', 'CREATE_COPY' ]
+ ]
+ ).length == 0 ? 1 : 0;
+ } catch(E) {
+ obj.error.sdump('D_ERROR','batch permission check: ' + E);
+ }
+
+ if (edit==0) {
+ alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.add_volume.permission_error'));
+ return; // no read-only view for this interface
+ } */
+ var new_ssub = new ssub();
+ new_ssub.owning_lib(list[0]);//TODO: add multiple at once support?
+ new_ssub.isnew(1);
+ new_ssub.record_entry(obj.docid);
+ var params = {};
+ params.ssubs = [new_ssub];
+ obj.editor_init('ssub', 'add', params);
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert(document.getElementById('serialStrings').getString('staff.serial.manage_subs.add.error'),E);
+ }
+ }
+ ],
+ 'cmd_transfer_subscription' : [
+ ['command'],
+ function() {
+ try {
+ obj.data.stash_retrieve();
+ if (!obj.data.marked_library) {
+ alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer_volume.alert'));
+ return;
+ }
+
+ var list = obj.ids_from_sel_list('ssub');
+
+ netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
+
+ JSAN.use('util.functional');
+
+ var ssub_list = util.functional.map_list(
+ list,
+ function (o) {
+ return obj.map_ssub[ 'ssub_' + o ].start_date();
+ }
+ ).join(document.getElementById('commonStrings').getString('common.grouping_string'));
+
+ var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: auto">';
+ xml += '<description>';
+ xml += document.getElementById('catStrings').getFormattedString('staff.cat.copy_browser.transfer.prompt', [ssub_list, obj.data.hash.aou[ obj.data.marked_library.lib ].shortname()]);
+ xml += '</description>';
+ xml += '<hbox><button label="' + document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer.submit.label') + '" name="fancy_submit"/>';
+ xml += '<button label="'
+ + document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer.cancel.label')
+ + '" accesskey="'
+ + document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer.cancel.accesskey')
+ + '" name="fancy_cancel"/></hbox>';
+ xml += '<iframe style="overflow: scroll" flex="1" src="' + urls.XUL_BIB_BRIEF + '?docid=' + obj.data.marked_library.docid + '"/>';
+ xml += '</vbox>';
+ JSAN.use('OpenILS.data');
+ var data = new OpenILS.data(); data.init({'via':'stash'});
+ //data.temp_transfer = xml; data.stash('temp_transfer');
+ JSAN.use('util.window'); var win = new util.window();
+ var fancy_prompt_data = win.open(
+ urls.XUL_FANCY_PROMPT,
+ //+ '?xml_in_stash=temp_transfer'
+ //+ '&title=' + window.escape('Volume Transfer'),
+ 'fancy_prompt', 'chrome,resizable,modal,width=500,height=300',
+ {
+ 'xml' : xml,
+ 'title' : document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer.title')
+ }
+ );
+
+ if (fancy_prompt_data.fancy_status == 'incomplete') {
+ alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer.incomplete'));
+ return;
+ }
+
+ var robj = obj.network.simple_request(
+ 'FM_ACN_TRANSFER',
+ [ ses(), { 'docid' : obj.data.marked_library.docid, 'lib' : obj.data.marked_library.lib, 'subscriptions' : list } ],
+ null,
+ {
+ 'title' : document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer.override.failure'),
+ 'overridable_events' : [
+ 1208, // TITLE_LAST_COPY
+ 1219, // COPY_REMOTE_CIRC_LIB
+ ],
+ }
+ );
+
+ if (typeof robj.ilsevent != 'undefined') {
+ if (robj.ilsevent == 1221) { // ORG_CANNOT_HAVE_VOLS
+ alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer.ineligible_destination'));
+ } else {
+ throw(robj);
+ }
+ } else {
+ alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer.success'));
+ }
+
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer.unexpected_error'),E);
+ }
+ obj.refresh_list();
+ }
+ ],
+
+ 'cmd_transfer_sdists' : [
+ ['command'],
+ function() {
+ try {
+ obj.data.stash_retrieve();
+ if (!obj.data.marked_subscription) {
+ alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer_items.missing_volume'));
+ return;
+ }
+
+ JSAN.use('util.functional');
+
+ var list = obj.ids_from_sel_list('sdist');
+ var subscription = obj.network.simple_request('FM_ACN_RETRIEVE.authoritative',[ obj.data.marked_subscription ]);
+
+ JSAN.use('cat.util'); cat.util.transfer_copies( {
+ 'distribution_ids' : list,
+ 'docid' : subscription.record(),
+ 'subscription_label' : subscription.start_date(),
+ 'owning_lib' : subscription.owning_lib(),
+ } );
+
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.transfer_items.unexpected_error'),E);
+ }
+ obj.refresh_list();
+ }
+ ],
+ 'cmd_refresh_list' : [
+ ['command'],
+ function() {
+ obj.refresh_list();
+ }
+ ],
+ 'cmd_make_predictions' : [
+ ['command'],
+ function() {
+ try {
+ var list = obj.ids_from_sel_list('ssub');
+ if (list.length == 0) {
+ alert('You must select a subscription before predicting issuances.'); //TODO: better error
+ return;
+ }
+
+ var num_to_predict = prompt('How many items would you like to predict?',
+ '12',
+ 'Number of Predicted Items');
+ num_to_predict = String( num_to_predict ).replace(/\D/g,'');
+ if (num_to_predict == '') {
+ alert('Invalid number entered!'); //TODO: better error
+ return;
+ }
+
+ for (i = 0; i < list.length; i++) {
+ var robj = obj.network.request(
+ 'open-ils.serial',
+ 'open-ils.serial.make_predictions',
+ [ ses(), {"ssub_id":list[i], "num_to_predict":num_to_predict, "last_rec_date":"2010-07-07"}]
+ );
+ util.functional.map_list(
+ robj,
+ function(o) {
+ alert('debug: ' + o.date_expected());
+ }
+ );
+ }
+ return;
+
+ /*JSAN.use('util.functional');
+ var list = util.functional.map_list(
+ robj,
+ function (o) {
+ o.distribution(obj.sdist_id);
+ return o;
+ }
+ );*/
+
+ var robj = obj.network.request(
+ 'open-ils.serial',
+ 'open-ils.serial.item.fleshed.batch.update',
+ [ ses(), list ]
+ );
+
+ //obj.refresh_list('main');
+
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert('cmd_make_predictions failed!',E);
+ }
+ }
+ ],
+/*dbw2 'sel_distribution_details' : [
+ ['command'],
+ function() {
+ JSAN.use('util.functional');
+
+ var list = util.functional.filter_list(
+ obj.sel_list,
+ function (o) {
+ return o.split(/_/)[0] == 'sdist';
+ }
+ );
+
+ list = util.functional.map_list(
+ list,
+ function (o) {
+ return o.split(/_/)[1];
+ }
+ );
+
+ JSAN.use('circ.util');
+ for (var i = 0; i < list.length; i++) {
+ circ.util.show_copy_details( list[i] );
+ }
+ }
+ ],
+ 'cmd_edit_sdists' : [
+ ['command'],
+ function() {
+ try {
+ JSAN.use('util.functional');
+
+ var list = util.functional.filter_list(
+ obj.sel_list,
+ function (o) {
+ return o.split(/_/)[0] == 'sdist';
+ }
+ );
+
+ list = util.functional.map_list(
+ list,
+ function (o) {
+ return o.split(/_/)[1];
+ }
+ );
+
+ JSAN.use('cat.util'); cat.util.spawn_copy_editor( { 'copy_ids' : list, 'edit' : 1 } );
+ obj.refresh_list();
+
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.edit_items.error'),E);
+ }
+ }
+ ], dbw2*/
+
+/*dbw2 'cmd_print_spine_labels' : [
+ ['command'],
+ function() {
+ try {
+ JSAN.use('util.functional');
+
+ var list = util.functional.filter_list(
+ obj.sel_list,
+ function (o) {
+ return o.split(/_/)[0] == 'sdist';
+ }
+ );
+
+ list = util.functional.map_list(
+ list,
+ function (o) {
+ return obj.map_sdist[ o ];
+ }
+ );
+
+ obj.data.temp_barcodes_for_labels = util.functional.map_list( list, function(o){return o.barcode();}) ;
+ obj.data.stash('temp_barcodes_for_labels');
+ xulG.new_tab(
+ xulG.url_prefix( urls.XUL_SPINE_LABEL ),
+ { 'tab_name' : document.getElementById('catStrings').getString('staff.cat.copy_browser.print_spine.tab') },
+ {}
+ );
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.print_spine.error'),E);
+ }
+ }
+ ],
+ 'cmd_edit_subscriptions' : [
+ ['command'],
+ function() {
+ try {
+ JSAN.use('util.functional');
+ var list = util.functional.map_list(
+ util.functional.filter_list(
+ obj.sel_list,
+ function (o) {
+ return o.split(/_/)[0] == 'ssub';
+ }
+ ),
+ function (o) {
+ return o.split(/_/)[1];
+ }
+ );
+ if (list.length == 0) return;
+
+ var edit = 0;
+ try {
+ edit = obj.network.request(
+ api.PERM_MULTI_ORG_CHECK.app,
+ api.PERM_MULTI_ORG_CHECK.method,
+ [
+ ses(),
+ obj.data.list.au[0].id(),
+ util.functional.map_list(
+ list,
+ function (o) {
+ return obj.map_ssub[ 'ssub_' + o ].owning_lib();
+ }
+ ),
+ [ 'UPDATE_VOLUME' ]
+ ]
+ ).length == 0 ? 1 : 0;
+ } catch(E) {
+ obj.error.sdump('D_ERROR','batch permission check: ' + E);
+ }
+
+ if (edit==0) {
+ alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.edit_volume.permission_error'));
+ return; // no read-only view for this interface
+ }
+
+ list = util.functional.map_list(
+ list,
+ function (o) {
+ var my_ssub = obj.map_ssub['ssub_' + o];
+ return function(r){return r;}(my_ssub);
+ }
+ );
+
+ var title;
+ if (list.length == 1) {
+ title = document.getElementById('catStrings').getString('staff.cat.copy_browser.edit_volume.title');
+ } else {
+ title = document.getElementById('catStrings').getString('staff.cat.copy_browser.edit_volume.title.plural');
+ }
+
+ JSAN.use('util.window'); var win = new util.window();
+ //obj.data.volumes_temp = js2JSON( list );
+ //obj.data.stash('volumes_temp');
+ var my_xulG = win.open(
+ window.xulG.url_prefix(urls.XUL_VOLUME_EDITOR),
+ title,
+ 'chrome,modal,resizable',
+ { 'subscriptions' : JSON2js(js2JSON(list)) }
+ );
+
+ // FIXME -- need to unique the temp space, and not rely on modalness of window
+ //obj.data.stash_retrieve();
+ if (typeof my_xulG.update_these_subscriptions == 'undefined') { return; }
+ var subscriptions = my_xulG.subscriptions;
+ if (!subscriptions) return;
+
+ subscriptions = util.functional.filter_list(
+ subscriptions,
+ function (o) {
+ return o.ischanged() == '1';
+ }
+ );
+
+ subscriptions = util.functional.map_list(
+ subscriptions,
+ function (o) {
+ o.record( obj.docid ); // staff client 2 did not do this. Does it matter?
+ return o;
+ }
+ );
+
+ if (subscriptions.length == 0) return;
+
+ try {
+ var r = obj.network.request(
+ api.FM_ACN_TREE_UPDATE.app,
+ api.FM_ACN_TREE_UPDATE.method,
+ [ ses(), subscriptions, true ]
+ );
+ if (typeof r.ilsevent != 'undefined') {
+ switch(Number(r.ilsevent)) {
+ case 1705 : // VOLUME_LABEL_EXISTS
+ alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.edit_volume.failed'));
+ break;
+ default: throw(r);
+ }
+ } else {
+ alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.edit_volume.success'));
+ }
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.edit_volume.error'),E);
+ }
+ obj.refresh_list();
+
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.edit_volume.exception'),E);
+ }
+ }
+ ], dbw2*/
+ }
+ }
+ );
+
+ obj.list_init(params);
+
+ obj.org_ids = obj.network.simple_request('FM_SSUB_AOU_IDS_RETRIEVE_VIA_RECORD_ID.authoritative',[ obj.docid ]);
+ if (typeof obj.org_ids.ilsevent != 'undefined') throw(obj.org_ids);
+ JSAN.use('util.functional');
+ obj.org_ids = util.functional.map_list( obj.org_ids, function (o) { return Number(o); });
+
+ var org = obj.data.hash.aou[ obj.data.list.au[0].ws_ou() ];
+ //obj.show_libs( org );
+
+ //obj.show_my_libs();
+
+ JSAN.use('util.file'); JSAN.use('util.widgets');
+
+ var file; var list_data; var ml;
+
+ file = new util.file('offline_ou_list');
+ if (file._file.exists()) {
+ list_data = file.get_object(); file.close();
+ ml = util.widgets.make_menulist( list_data[0], list_data[1] );
+ ml.setAttribute('id','lib_menu'); document.getElementById('serial_sub_lib_menu').appendChild(ml);
+ //TODO: class this menu properly
+ for (var i = 0; i < obj.org_ids.length; i++) {
+ ml.getElementsByAttribute('value',obj.org_ids[i])[0].setAttribute('class','has_distributions');
+ }
+ ml.firstChild.addEventListener(
+ 'popupshown',
+ function(ev) {
+ document.getElementById('legend').setAttribute('hidden','false');
+ },
+ false
+ );
+ ml.firstChild.addEventListener(
+ 'popuphidden',
+ function(ev) {
+ document.getElementById('legend').setAttribute('hidden','true');
+ },
+ false
+ );
+ ml.addEventListener(
+ 'command',
+ function(ev) {
+ if (document.getElementById('refresh_button')) document.getElementById('refresh_button').focus();
+ JSAN.use('util.file'); var file = new util.file('manage_subs_prefs.'+obj.data.server_unadorned);
+ util.widgets.save_attributes(file, { 'lib_menu' : [ 'value' ], 'show_ssubs' : [ 'checked' ], 'show_groups' : [ 'checked' ] });
+ obj.refresh_list();
+ },
+ false
+ );
+ } else {
+ throw(document.getElementById('catStrings').getString('staff.cat.copy_browser.missing_library') + '\n');
+ }
+
+ file = new util.file('manage_subs_prefs.'+obj.data.server_unadorned);
+ util.widgets.load_attributes(file);
+ ml.value = ml.getAttribute('value');
+ if (! ml.value) {
+ ml.value = org.id();
+ ml.setAttribute('value',ml.value);
+ }
+
+ document.getElementById('show_ssubs').addEventListener(
+ 'command',
+ function(ev) {
+ JSAN.use('util.file'); var file = new util.file('manage_subs_prefs.'+obj.data.server_unadorned);
+ util.widgets.save_attributes(file, { 'lib_menu' : [ 'value' ], 'show_ssubs' : [ 'checked' ], 'show_groups' : [ 'checked' ] });
+ },
+ false
+ );
+
+ document.getElementById('show_groups').addEventListener(
+ 'command',
+ function(ev) {
+ JSAN.use('util.file'); var file = new util.file('manage_subs_prefs.'+obj.data.server_unadorned);
+ util.widgets.save_attributes(file, { 'lib_menu' : [ 'value' ], 'show_ssubs' : [ 'checked' ], 'show_groups' : [ 'checked' ] });
+ },
+ false
+ );
+
+ obj.show_my_libs( ml.value );
+
+ JSAN.use('util.exec'); var exec = new util.exec(20); exec.timer(obj.funcs,100);
+
+ obj.toggle_actions(); // disable menus initially
+
+ } catch(E) {
+ this.error.standard_unexpected_error_alert('serial/manage_subs.init: ',E);
+ }
+ },
+
+ 'show_my_libs' : function(org) {
+ var obj = this;
+ try {
+ if (!org) {
+ org = obj.data.hash.aou[ obj.data.list.au[0].ws_ou() ];
+ } else {
+ if (typeof org != 'object') org = obj.data.hash.aou[ org ];
+ }
+ obj.show_libs( org, false );
+
+ var p_org = obj.data.hash.aou[ org.parent_ou() ];
+ if (p_org) {
+ obj.funcs.push( function() {
+ document.getElementById('cmd_refresh_list').setAttribute('disabled','true');
+ document.getElementById('cmd_show_libs_with_distributions').setAttribute('disabled','true');
+ document.getElementById('lib_menu').setAttribute('disabled','true');
+ } );
+ for (var i = 0; i < p_org.children().length; i++) {
+ obj.funcs.push(
+ function(o) {
+ return function() {
+ obj.show_libs( o, false );
+ }
+ }( p_org.children()[i] )
+ );
+ }
+ obj.funcs.push( function() {
+ document.getElementById('cmd_refresh_list').setAttribute('disabled','false');
+ document.getElementById('cmd_show_libs_with_distributions').setAttribute('disabled','false');
+ document.getElementById('lib_menu').setAttribute('disabled','false');
+ } );
+ }
+ } catch(E) {
+ alert(E);
+ }
+ },
+
+ 'show_all_libs' : function() {
+ var obj = this;
+ try {
+ obj.show_my_libs();
+
+ obj.show_libs( obj.data.tree.aou );
+
+ obj.funcs.push( function() {
+ document.getElementById('cmd_refresh_list').setAttribute('disabled','true');
+ document.getElementById('cmd_show_libs_with_distributions').setAttribute('disabled','true');
+ document.getElementById('lib_menu').setAttribute('disabled','true');
+ } );
+
+ for (var i = 0; i < obj.data.tree.aou.children().length; i++) {
+ obj.funcs.push(
+ function(o) {
+ return function() {
+ obj.show_libs( o );
+ }
+ }( obj.data.tree.aou.children()[i] )
+ );
+ }
+ obj.funcs.push( function() {
+ document.getElementById('cmd_refresh_list').setAttribute('disabled','false');
+ document.getElementById('cmd_show_libs_with_distributions').setAttribute('disabled','false');
+ document.getElementById('lib_menu').setAttribute('disabled','false');
+ } );
+
+ } catch(E) {
+ alert(E);
+ }
+ },
+
+ 'show_libs_with_distributions' : function() {
+ var obj = this;
+ try {
+ JSAN.use('util.functional');
+
+ var orgs = util.functional.map_list(
+ obj.org_ids,
+ function(id) { return obj.data.hash.aou[id]; }
+ ).sort(
+ function( a, b ) {
+ if (a.shortname() < b.shortname()) return -1;
+ if (a.shortname() > b.shortname()) return 1;
+ return 0;
+ }
+ );
+ obj.funcs.push( function() {
+ document.getElementById('cmd_refresh_list').setAttribute('disabled','true');
+ document.getElementById('cmd_show_libs_with_distributions').setAttribute('disabled','true');
+ document.getElementById('lib_menu').setAttribute('disabled','true');
+ } );
+
+ for (var i = 0; i < orgs.length; i++) {
+ obj.funcs.push(
+ function(o) {
+ return function() {
+ obj.show_libs(o,false);
+ }
+ }( orgs[i] )
+ );
+ }
+ obj.funcs.push( function() {
+ document.getElementById('cmd_refresh_list').setAttribute('disabled','false');
+ document.getElementById('cmd_show_libs_with_distributions').setAttribute('disabled','false');
+ document.getElementById('lib_menu').setAttribute('disabled','false');
+ } );
+
+ } catch(E) {
+ alert(E);
+ }
+ },
+
+ 'show_libs' : function(start_aou,show_open) {
+ var obj = this;
+ try {
+ if (!start_aou) throw('show_libs: Need a start_aou');
+ JSAN.use('OpenILS.data'); obj.data = new OpenILS.data(); obj.data.init({'via':'stash'});
+ JSAN.use('util.functional');
+
+ var parents = [];
+ var temp_aou = start_aou;
+ while ( temp_aou.parent_ou() ) {
+ temp_aou = obj.data.hash.aou[ temp_aou.parent_ou() ];
+ parents.push( temp_aou );
+ }
+ parents.reverse();
+
+ for (var i = 0; i < parents.length; i++) {
+ obj.funcs.push(
+ function(o,p) {
+ return function() {
+ obj.append_org(o,p,{'container':'true','open':'true'});
+ };
+ }(parents[i], obj.data.hash.aou[ parents[i].parent_ou() ])
+ );
+ }
+
+ obj.funcs.push(
+ function(o,p) {
+ return function() { obj.append_org(o,p); };
+ }(start_aou,obj.data.hash.aou[ start_aou.parent_ou() ])
+ );
+
+ obj.funcs.push(
+ function() {
+ if (start_aou.children()) {
+ var x = obj.map_tree[ 'aou_' + start_aou.id() ];
+ x.setAttribute('container','true');
+ if (show_open) x.setAttribute('open','true');
+ for (var i = 0; i < start_aou.children().length; i++) {
+ obj.funcs.push(
+ function(o,p) {
+ return function() { obj.append_org(o,p); };
+ }( start_aou.children()[i], start_aou )
+ );
+ }
+ }
+ }
+ );
+
+ } catch(E) {
+ alert(E);
+ }
+ },
+
+ 'on_select' : function(list,twisty) {
+ var obj = this;
+ var sel_lists = {};
+
+ for (var i = 0; i < list.length; i++) {
+ var row_type = list[i].split('_')[0];
+ var id = list[i].split('_')[1];
+
+ if (!sel_lists[row_type]) sel_lists[row_type] = [];
+ sel_lists[row_type].push(id);
+
+ if (twisty) {
+ switch(row_type) {
+ case 'aou' : obj.on_click_aou(id,twisty); break;
+ case 'ssub' : obj.on_select_ssub(id,twisty); break;
+ default: break;
+ }
+ }
+ }
+
+ if (!obj.focused_node_retrieve_id) return;
+
+ var row_type = obj.focused_node_retrieve_id.split('_')[0];
+ var id = obj.focused_node_retrieve_id.split('_')[1];
+
+ if (sel_lists[row_type]) { // the type focused is in the selection (usually the case)
+ switch(row_type) {
+ case 'aou' : obj.on_click_aou(id,twisty); break;
+ default: if (obj['on_click_' + row_type]) obj['on_click_' + row_type](sel_lists[row_type],twisty);
+ }
+ }
+ },
+
+ 'on_select_ssub' : function(ssub_id,twisty) {
+ var obj = this;
+ try {
+ //typo? var ssub_tree = obj.map_sdist[ 'ssub_' + ssub_id ];
+ var ssub_tree = obj.map_ssub[ 'ssub_' + ssub_id ];
+ obj.funcs.push( function() {
+ document.getElementById('cmd_refresh_list').setAttribute('disabled','true');
+ document.getElementById('cmd_show_libs_with_distributions').setAttribute('disabled','true');
+ document.getElementById('lib_menu').setAttribute('disabled','true');
+ } );
+ if (ssub_tree.distributions()) {
+ for (var i = 0; i < ssub_tree.distributions().length; i++) {
+ obj.funcs.push(
+ function(c,a) {
+ return function() {
+ obj.append_member(c,a,[],'sdist');
+ }
+ }( ssub_tree.distributions()[i], ssub_tree )
+ )
+ }
+ }
+ if (ssub_tree.issuances()) {
+ for (var i = 0; i < ssub_tree.issuances().length; i++) {
+ obj.funcs.push(
+ function(c,a) {
+ return function() {
+ obj.append_member(c,a,[],'siss');
+ }
+ }( ssub_tree.issuances()[i], ssub_tree )
+ )
+ }
+ }
+ if (ssub_tree.scaps()) {
+ for (var i = 0; i < ssub_tree.scaps().length; i++) {
+ obj.funcs.push(
+ function(c,a) {
+ return function() {
+ obj.append_member(c,a,[],'scap');
+ }
+ }( ssub_tree.scaps()[i], ssub_tree )
+ )
+ }
+ }
+ obj.funcs.push( function() {
+ document.getElementById('cmd_refresh_list').setAttribute('disabled','false');
+ document.getElementById('cmd_show_libs_with_distributions').setAttribute('disabled','false');
+ document.getElementById('lib_menu').setAttribute('disabled','false');
+ } );
+ } catch(E) {
+ alert(E);
+ }
+ },
+
+ 'on_click_ssub' : function(ssub_ids,twisty) {
+ var obj = this;
+ try {
+ // draw sdist editor
+ if (typeof twisty == 'undefined') {
+ var params = {};
+ params.ssub_ids = ssub_ids;
+ obj.editor_init('ssub', 'edit', params);
+ }
+ } catch(E) {
+ alert(E);
+ }
+ },
+
+ 'on_click_sdist' : function(sdist_ids,twisty) {
+ var obj = this;
+ try {
+ // draw sdist editor
+ if (typeof twisty == 'undefined') {
+ var params = {};
+ params.sdist_ids = sdist_ids;
+ obj.editor_init('sdist', 'edit', params);
+ }
+ } catch(E) {
+ alert(E);
+ }
+ },
+
+ 'on_click_siss' : function(siss_ids,twisty) {
+ var obj = this;
+ try {
+ // draw siss editor
+ if (typeof twisty == 'undefined') {
+ var params = {};
+ params.siss_ids = siss_ids;
+ obj.editor_init('siss', 'edit', params);
+ }
+ } catch(E) {
+ alert(E);
+ }
+ },
+
+ 'on_click_scap' : function(scap_ids,twisty) {
+ var obj = this;
+ try {
+ // draw scap editor
+ if (typeof twisty == 'undefined') {
+ var params = {};
+ params.scap_ids = scap_ids;
+ obj.editor_init('scap', 'edit', params);
+ }
+ } catch(E) {
+ alert(E);
+ }
+ },
+
+ 'on_click_aou' : function(org_id,twisty) {
+ var obj = this;
+ var org = obj.data.hash.aou[ org_id ];
+ obj.funcs.push( function() {
+ document.getElementById('cmd_refresh_list').setAttribute('disabled','true');
+ document.getElementById('cmd_show_libs_with_distributions').setAttribute('disabled','true');
+ document.getElementById('lib_menu').setAttribute('disabled','true');
+ } );
+ if (org.children()) {
+ for (var i = 0; i < org.children().length; i++) {
+ obj.funcs.push(
+ function(o,p) {
+ return function() {
+ obj.append_org(o,p)
+ }
+ }(org.children()[i],org)
+ );
+ }
+ }
+ if (obj.map_ssub[ 'aou_' + org_id ]) {
+ for (var i = 0; i < obj.map_ssub[ 'aou_' + org_id ].length; i++) {
+ obj.funcs.push(
+ function(o,a) {
+ return function() {
+ obj.append_ssub(o,a);
+ }
+ }( org, obj.map_ssub[ 'aou_' + org_id ][i] )
+ );
+ }
+ }
+ obj.funcs.push( function() {
+ document.getElementById('cmd_refresh_list').setAttribute('disabled','false');
+ document.getElementById('cmd_show_libs_with_distributions').setAttribute('disabled','false');
+ document.getElementById('lib_menu').setAttribute('disabled','false');
+ } );
+
+ // remove current editor
+ if (typeof twisty == 'undefined') {
+ document.getElementById('serial_manage_subs_editor_deck').selectedIndex = 0;
+ }
+ },
+
+ 'append_org' : function (org,parent_org,params) {
+ var obj = this;
+ try {
+ if (obj.map_tree[ 'aou_' + org.id() ]) {
+ var x = obj.map_tree[ 'aou_' + org.id() ];
+ if (params) {
+ for (var i in params) {
+ x.setAttribute(i,params[i]);
+ }
+ }
+ return x;
+ }
+
+ var data = {
+ 'row' : {
+ 'my' : {
+ 'aou' : org,
+ }
+ },
+ 'skip_all_columns_except' : [0,1,2],
+ 'retrieve_id' : 'aou_' + org.id(),
+ 'to_bottom' : true,
+ 'no_auto_select' : true,
+ };
+
+ var ssub_tree_list;
+ if ( obj.org_ids.indexOf( Number( org.id() ) ) == -1 ) {
+ if ( get_bool( obj.data.hash.aout[ org.ou_type() ].can_have_vols() ) ) {
+ data.row.my.subscription_count = '0';
+ //data.row.my.distribution_count = '<0>';
+ } else {
+ data.row.my.subscription_count = '';
+ //data.row.my.distribution_count = '';
+ }
+ } else {
+ var v_count = 0; var d_count = 0;
+ ssub_tree_list = obj.network.simple_request(
+ 'FM_SSUB_TREE_LIST_RETRIEVE_VIA_RECORD_ID_AND_ORG_IDS.authoritative',
+ [ ses(), obj.docid, [ org.id() ] ]
+ );
+ for (var i = 0; i < ssub_tree_list.length; i++) {
+ v_count++;
+ obj.map_ssub[ 'ssub_' + ssub_tree_list[i].id() ] = function(r){return r;}(ssub_tree_list[i]);
+ var distributions = ssub_tree_list[i].distributions();
+ //if (distributions) d_count += distributions.length;
+ for (var j = 0; j < distributions.length; j++) {
+ obj.map_sdist[ 'sdist_' + distributions[j].id() ] = function(r){return r;}(distributions[j]);
+ }
+ var issuances = ssub_tree_list[i].issuances();
+ for (var j = 0; j < issuances.length; j++) {
+ obj.map_siss[ 'siss_' + issuances[j].id() ] = function(r){return r;}(issuances[j]);
+ }
+ var scaps = ssub_tree_list[i].scaps();
+ for (var j = 0; j < scaps.length; j++) {
+ obj.map_scap[ 'scap_' + scaps[j].id() ] = function(r){return r;}(scaps[j]);
+ }
+ }
+ data.row.my.subscription_count = v_count;
+ //data.row.my.distribution_count = '<' + d_count + '>';
+ }
+ if (parent_org) {
+ data.node = obj.map_tree[ 'aou_' + parent_org.id() ];
+ }
+ var nparams = obj.list.append(data);
+ var node = nparams.my_node;
+ if (params) {
+ for (var i in params) {
+ node.setAttribute(i,params[i]);
+ }
+ }
+ obj.map_tree[ 'aou_' + org.id() ] = node;
+
+ if (org.children()) {
+ node.setAttribute('container','true');
+ }
+
+ if (parent_org) {
+ if ( obj.data.hash.aou[ obj.data.list.au[0].ws_ou() ].parent_ou() == parent_org.id() ) {
+ data.node.setAttribute('open','true');
+ }
+ } else {
+ obj.map_tree[ 'aou_' + org.id() ].setAttribute('open','true');
+ }
+
+ if (ssub_tree_list) {
+ obj.map_ssub[ 'aou_' + org.id() ] = ssub_tree_list;
+ node.setAttribute('container','true');
+ }
+
+ if (document.getElementById('show_ssubs').checked) {
+ obj.funcs.push( function() { obj.on_click_aou( org.id() ); } );
+ node.setAttribute('open','true');
+ }
+
+ } catch(E) {
+ dump(E+'\n');
+ alert(E);
+ }
+ },
+
+ 'append_ssub' : function( org, ssub_tree, params ) {
+ var obj = this;
+ try {
+ if (obj.map_tree[ 'ssub_' + ssub_tree.id() ]) {
+ var x = obj.map_tree[ 'ssub_' + ssub_tree.id() ];
+ if (params) {
+ for (var i in params) {
+ x.setAttribute(i,params[i]);
+ }
+ }
+ return x;
+ }
+
+ var parent_node = obj.map_tree[ 'aou_' + org.id() ];
+ var data = {
+ 'row' : {
+ 'my' : {
+ 'aou' : org,
+ 'ssub' : ssub_tree,
+ 'subscription_count' : '',
+ //'distribution_count' : ssub_tree.distributions() ? ssub_tree.distributions().length : '0',
+ }
+ },
+ 'skip_all_columns_except' : [0,1,2],
+ 'retrieve_id' : 'ssub_' + ssub_tree.id(),
+ 'node' : parent_node,
+ 'to_bottom' : true,
+ 'no_auto_select' : true,
+ };
+ var nparams = obj.list.append(data);
+ var node = nparams.my_node;
+ obj.map_tree[ 'ssub_' + ssub_tree.id() ] = node;
+ if (params) {
+ for (var i in params) {
+ node.setAttribute(i,params[i]);
+ }
+ }
+ if (ssub_tree.distributions() || ssub_tree.scaps() || ssub_tree.issuances()) {
+ //did this support a later typo? obj.map_sdist[ 'ssub_' + ssub_tree.id() ] = ssub_tree;
+ node.setAttribute('container','true');
+ }
+ if (document.getElementById('show_groups').checked) {
+ node.setAttribute('open','true');
+ obj.funcs.push( function() { obj.on_select_ssub( ssub_tree.id(), true ); } );
+ }
+ var sdist_group_node_data = {
+ 'row' : {
+ 'my' : {
+ 'label' : 'Distributions',
+ }
+ },
+ 'retrieve_id' : 'sdist-group_' + ssub_tree.id(),
+ 'node' : node,
+ 'to_bottom' : true,
+ 'no_auto_select' : true,
+ };
+ nparams = obj.list.append(sdist_group_node_data);
+ obj.map_tree[ 'ssub_sdist_group_' + ssub_tree.id() ] = nparams.my_node;
+
+ var siss_group_node_data = {
+ 'row' : {
+ 'my' : {
+ 'label' : 'Issuances',
+ }
+ },
+ 'retrieve_id' : 'siss-group_' + ssub_tree.id(),
+ 'node' : node,
+ 'to_bottom' : true,
+ 'no_auto_select' : true,
+ };
+ nparams = obj.list.append(siss_group_node_data);
+ obj.map_tree[ 'ssub_siss_group_' + ssub_tree.id() ] = nparams.my_node;
+
+ var scap_group_node_data = {
+ 'row' : {
+ 'my' : {
+ 'label' : 'Captions/Patterns',
+ }
+ },
+ 'retrieve_id' : 'scap-group_' + ssub_tree.id(),
+ 'node' : node,
+ 'to_bottom' : true,
+ 'no_auto_select' : true,
+ };
+ nparams = obj.list.append(scap_group_node_data);
+ obj.map_tree[ 'ssub_scap_group_' + ssub_tree.id() ] = nparams.my_node;
+ } catch(E) {
+ dump(E+'\n');
+ alert(E);
+ }
+ },
+
+ 'append_member' : function( item, ssub_tree, attributes, type ) {
+ var obj = this;
+ try {
+ if (obj.map_tree[ type + '_' + item.id() ]) {
+ var x = obj.map_tree[ type + '_' + item.id() ];
+ if (attributes) {
+ for (var i in attributes) {
+ x.setAttribute(i,attributes[i]);
+ }
+ }
+ return x;
+ }
+
+ var parent_node = obj.map_tree[ 'ssub_' + type + '_group_' + ssub_tree.id() ];
+ var data = {
+ 'row' : {
+ 'my' : {
+ 'aou' : obj.data.hash.aou[ ssub_tree.owning_lib() ],
+ 'ssub' : ssub_tree,
+ 'subscription_count' : '',
+ //'distribution_count' : '',
+ }
+ },
+ 'retrieve_id' : type + '_' + item.id(),
+ 'node' : parent_node,
+ 'to_bottom' : true,
+ 'no_auto_select' : true,
+ };
+ data['row']['my'][type] = item; // TODO: future optimization: get only the IDs of these leaves, then fetch the full row in 'retrieve_row'
+ var nparams = obj.list.append(data);
+ var node = nparams.my_node;
+ obj.map_tree[ type + '_' + item.id() ] = node;
+ if (attributes) {
+ for (var i in attributes) {
+ node.setAttribute(i,attributes[i]);
+ }
+ }
+
+ } catch(E) {
+ dump(E+'\n');
+ alert(E);
+ }
+ },
+
+ 'list_init' : function( params ) {
+
+ try {
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ var obj = this;
+
+ JSAN.use('circ.util');
+ var columns = [
+ {
+ 'id' : 'tree_location',
+ 'label' : document.getElementById('catStrings').getString('staff.cat.copy_browser.list_init.tree_location'),
+ 'flex' : 1, 'primary' : true, 'hidden' : false,
+ 'render' : function(my) { return my.sdist ? my.sdist.label() : my.siss ? my.siss.label() : my.scap ? 'C/P : #' + my.scap.id() : my.ssub ? 'Subscription : #' + my.ssub.id() : my.aou ? my.aou.shortname() + " : " + my.aou.name() : my.label ? my.label : "???"; },
+ },
+ {
+ 'id' : 'subscription_count',
+ 'label' : 'Subscriptions',
+ 'flex' : 0, 'primary' : false, 'hidden' : false,
+ 'render' : function(my) { return my.subscription_count; },
+ },
+ /*{
+ 'id' : 'distribution_count',
+ 'label' : 'Members',
+ 'flex' : 0,
+ 'primary' : false, 'hidden' : false,
+ 'render' : function(my) { return my.distribution_count; },
+ },*/
+ ];
+ JSAN.use('util.list'); obj.list = new util.list('subs_tree');
+ obj.list.init(
+ {
+ 'no_auto_select' : true,
+ 'columns' : columns,
+ 'map_row_to_columns' : circ.util.std_map_row_to_columns(' '),
+ 'retrieve_row' : function(params) {
+
+ var row = params.row;
+ obj.funcs.push(
+ function() {
+
+ if (typeof params.on_retrieve == 'function') {
+ params.on_retrieve(row);
+ }
+
+ }
+ );
+
+ return row;
+ },
+ 'on_click' : function(ev) {
+ netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserRead');
+ var row = {}; var col = {}; var nobj = {};
+ obj.list.node.treeBoxObject.getCellAt(ev.clientX,ev.clientY,row,col,nobj);
+ if ((row.value == -1)||(nobj.value != 'twisty')) { return; } // on_click runs for twistys only
+
+ var node = obj.list.node.contentView.getItemAtIndex(row.value);
+ var list = [ node.getAttribute('retrieve_id') ];
+ if (typeof obj.on_select == 'function') {
+ obj.on_select(list,true);
+ }
+ if (typeof window.xulG == 'object' && typeof window.xulG.on_select == 'function') {
+ window.xulG.on_select(list);
+ }
+ },
+ 'on_select' : function(ev) {
+ JSAN.use('util.functional');
+
+ // get the actual node clicked to determine which editor to use
+ if (obj.list.node.view.selection.currentIndex > -1) {
+ var node = obj.list.node.contentView.getItemAtIndex(obj.list.node.view.selection.currentIndex);
+ obj.focused_node_retrieve_id = node.getAttribute('retrieve_id');
+ }
+
+ var sel = obj.list.retrieve_selection();
+ obj.controller.view.sel_clip.disabled = sel.length < 1;
+ obj.sel_list = util.functional.map_list(
+ sel,
+ function(o) { return o.getAttribute('retrieve_id'); }
+ );
+ obj.toggle_actions();
+ if (typeof obj.on_select == 'function') {
+ obj.on_select(obj.sel_list);
+ }
+ if (typeof window.xulG == 'object' && typeof window.xulG.on_select == 'function') {
+ window.xulG.on_select(obj.sel_list);
+ }
+ },
+ }
+ );
+
+ obj.controller.render();
+
+ } catch(E) {
+ this.error.sdump('D_ERROR','serial/manage_subs.list_init: ' + E + '\n');
+ alert(E);
+ }
+ },
+
+ 'toggle_actions' : function() {
+ var obj = this;
+ try {
+ var found_aou = false; var found_ssub = false; var found_sdist = false; var found_siss = false; var found_scap = false; var found_sdist_group = false; var found_siss_group = false; var found_scap_group = false;
+ for (var i = 0; i < obj.sel_list.length; i++) {
+ var type = obj.sel_list[i].split(/_/)[0];
+ switch(type) {
+ case 'aou' :
+ found_aou = true;
+ break;
+ case 'ssub' : found_ssub = true; break;
+ case 'sdist' : found_sdist = true; break;
+ case 'siss' : found_siss = true; break;
+ case 'scap' : found_scap = true; break;
+ case 'sdist-group' : found_sdist_group = true; break;
+ case 'siss-group' : found_siss_group = true; break;
+ case 'scap-group' : found_scap_group = true; break;
+ }
+ }
+ obj.controller.view.cmd_add_sdist.setAttribute('disabled','true');
+ obj.controller.view.cmd_add_siss.setAttribute('disabled','true');
+ obj.controller.view.cmd_add_scap.setAttribute('disabled','true');
+ obj.controller.view.cmd_make_predictions.setAttribute('disabled','true');
+ obj.controller.view.cmd_delete_sdist.setAttribute('disabled','true');
+ obj.controller.view.cmd_delete_siss.setAttribute('disabled','true');
+ obj.controller.view.cmd_delete_scap.setAttribute('disabled','true');
+ obj.controller.view.cmd_add_subscriptions.setAttribute('disabled','true');
+ obj.controller.view.cmd_mark_library.setAttribute('disabled','true');
+ obj.controller.view.cmd_delete_ssub.setAttribute('disabled','true');
+ obj.controller.view.cmd_mark_subscription.setAttribute('disabled','true');
+ obj.controller.view.cmd_transfer_subscription.setAttribute('disabled','true');
+ obj.controller.view.cmd_transfer_sdists.setAttribute('disabled','true');
+ if (found_aou) {
+ obj.controller.view.cmd_add_subscriptions.setAttribute('disabled','false');
+ obj.controller.view.cmd_mark_library.setAttribute('disabled','false');
+ }
+ if (found_ssub) {
+ obj.controller.view.cmd_delete_ssub.setAttribute('disabled','false');
+ obj.controller.view.cmd_mark_subscription.setAttribute('disabled','false');
+ obj.controller.view.cmd_add_sdist.setAttribute('disabled','false');
+ obj.controller.view.cmd_add_siss.setAttribute('disabled','false');
+ obj.controller.view.cmd_add_scap.setAttribute('disabled','false');
+ obj.controller.view.cmd_transfer_subscription.setAttribute('disabled','false');
+ obj.controller.view.cmd_make_predictions.setAttribute('disabled','false');
+ }
+ if (found_sdist_group) {
+ obj.controller.view.cmd_add_sdist.setAttribute('disabled','false');
+ }
+ if (found_siss_group) {
+ obj.controller.view.cmd_add_siss.setAttribute('disabled','false');
+ }
+ if (found_scap_group) {
+ obj.controller.view.cmd_add_scap.setAttribute('disabled','false');
+ }
+ if (found_sdist) {
+ obj.controller.view.cmd_delete_sdist.setAttribute('disabled','false');
+ obj.controller.view.cmd_transfer_sdists.setAttribute('disabled','false');
+ }
+ if (found_siss) {
+ obj.controller.view.cmd_delete_siss.setAttribute('disabled','false');
+ }
+ if (found_scap) {
+ obj.controller.view.cmd_delete_scap.setAttribute('disabled','false');
+ }
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.actions.error'),E);
+ }
+ },
+
+ 'refresh_list' : function() {
+ try {
+ var obj = this;
+ obj.list.clear();
+ obj.map_tree = {};
+ obj.map_ssub = {};
+ obj.map_sdist = {};
+ obj.map_siss = {};
+ obj.map_scap = {};
+ obj.org_ids = obj.network.simple_request('FM_SSUB_AOU_IDS_RETRIEVE_VIA_RECORD_ID.authoritative',[ obj.docid ]);
+ if (typeof obj.org_ids.ilsevent != 'undefined') throw(obj.org_ids);
+ JSAN.use('util.functional');
+ obj.org_ids = util.functional.map_list( obj.org_ids, function (o) { return Number(o); });
+ /*
+ var org = obj.data.hash.aou[ obj.data.list.au[0].ws_ou() ];
+ obj.show_libs( org );
+ */
+ obj.show_my_libs( document.getElementById('lib_menu').value );
+ } catch(E) {
+ this.error.standard_unexpected_error_alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.refresh_list.error'),E);
+ }
+ },
+};
+
+dump('exiting serial/manage_subs.js\n');
--- /dev/null
+<?xml version="1.0"?>
+<!-- Application: Evergreen Staff Client -->
+<!-- Screen: Manage Subscriptions Overlay -->
+<!--
+vim:noet:sw=4:ts=4:
+-->
+<!DOCTYPE overlay PUBLIC "" ""[
+ <!--#include virtual="/opac/locale/${locale}/lang.dtd"-->
+]>
+
+<?xul-overlay href="/xul/server/serial/ssub_editor.xul"?>
+<?xul-overlay href="/xul/server/serial/sdist_editor.xul"?>
+<?xul-overlay href="/xul/server/serial/siss_editor.xul"?>
+<?xul-overlay href="/xul/server/serial/scap_editor.xul"?>
+<overlay id="serial_manage_subs_overlay"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <tab id="serial_manage_subs_tab" label="Subscriptions" oncommand="manage_subs_init()"/>
+ <tabpanel id="serial_manage_subs" orient="vertical" flex="1">
+ <script>
+ <![CDATA[
+ manage_subs_inited = 0;
+ function manage_subs_init() {
+ if (manage_subs_inited) {
+ return;
+ }
+ try {
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ if (typeof JSAN == 'undefined') {
+ throw( document.getElementById("commonStrings").getString('common.jsan.missing') );
+ }
+ JSAN.errorLevel = "die"; // none, warn, or die
+ JSAN.addRepository('/xul/server/');
+ JSAN.use('util.error'); g.error = new util.error();
+ g.error.sdump('D_TRACE','manage_subs_init() for serial/manage_subs.xul');
+ JSAN.use('serial.manage_subs'); g.manage_subs = new serial.manage_subs();
+
+ g.manage_subs.init( { 'docid' : xul_param('docid') } );
+ manage_subs_inited = 1;
+
+ } catch(E) {
+ var err_msg = document.getElementById("commonStrings").getFormattedString('common.exception', ['serial/manage_subs.xul', E]);
+ try { g.error.sdump('D_ERROR',err_msg); } catch(E) { dump(err_msg); }
+ alert(err_msg);
+ }
+ }
+
+ ]]>
+ </script>
+
+ <popupset>
+ <popup id="serial_manage_subs_popup">
+ <menuitem command="cmd_add_subscriptions" label="Add Subscription"/>
+ <menuitem command="cmd_add_sdist" label="Add Distribution"/>
+ <menuitem command="cmd_add_siss" label="Add Issuance"/>
+ <menuitem command="cmd_add_scap" label="Add Caption/Pattern"/>
+ <menuseparator/>
+ <menuitem command="cmd_make_predictions" label="Make Predictions"/>
+ <menuseparator/>
+ <menuitem command="cmd_delete_ssub" label="Delete Subscription"/>
+ <menuitem command="cmd_delete_sdist" label="Delete Distribution"/>
+ <menuitem command="cmd_delete_siss" label="Delete Issuance"/>
+ <menuitem command="cmd_delete_scap" label="Delete Caption/Pattern"/>
+ </popup>
+ </popupset>
+
+ <hbox flex="1">
+ <vbox flex="1">
+ <hbox id="serial_sub_lib_menu"/>
+ <hbox>
+ <checkbox id="show_ssubs" label="Show Subs." />
+ <checkbox id="show_groups" label="Show Groups" />
+ <button id="serial_sub_add_button" label="&staff.cat.copy_browser.holdings_maintenance.refresh_button.label;" command="cmd_refresh_list" />
+ <spacer flex="1"/>
+ <menubar>
+ <menu label="Actions for Selected Row">
+ <menupopup>
+ <menuitem command="cmd_add_subscriptions" label="Add Subscription"/>
+ <menuitem command="cmd_add_sdist" label="Add Distribution"/>
+ <menuitem command="cmd_add_siss" label="Add Issuance"/>
+ <menuitem command="cmd_add_scap" label="Add Caption/Pattern"/>
+ <menuseparator/>
+ <menuitem command="cmd_make_predictions" label="Make Predictions"/>
+ <menuseparator/>
+ <menuitem command="cmd_delete_ssub" label="Delete Subscription"/>
+ <menuitem command="cmd_delete_sdist" label="Delete Distribution"/>
+ <menuitem command="cmd_delete_siss" label="Delete Issuance"/>
+ <menuitem command="cmd_delete_scap" label="Delete Caption/Pattern"/>
+ </menupopup>
+ </menu>
+ </menubar>
+ </hbox>
+ <tree id="subs_tree" flex="15" enableColumnDrag="true" context="serial_manage_subs_popup"/>
+ </vbox>
+ <splitter state="open" collapse="before" resizebefore="closest" resizeafter="farthest"/>
+ <deck id="serial_manage_subs_editor_deck" flex="20">
+ <description value="Please select an object to edit"/>
+ <vbox id="serial_ssub_editor_panel" />
+ <vbox id="serial_sdist_editor_panel" />
+ <vbox id="serial_siss_editor_panel" />
+ <vbox id="serial_scap_editor_panel" />
+ </deck>
+ </hbox>
+ </tabpanel>
+
+</overlay>
--- /dev/null
+<?xml version="1.0"?>
+<!-- Application: Evergreen Staff Client -->
+<!-- Screen: Serial Notes -->
+<!--
+ vim:noet:sw=4:ts=4
+-->
+
+<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+<!-- STYLESHEETS -->
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="chrome://open_ils_staff_client/skin/global.css" type="text/css"?>
+<?xml-stylesheet href="/xul/server/skin/global.css" type="text/css"?>
+<?xml-stylesheet href="/xul/server/skin/patron_display.css" type="text/css"?>
+
+<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+<!-- LOCALIZATION -->
+<!DOCTYPE window PUBLIC "" ""[
+ <!--#include virtual="/opac/locale/${locale}/lang.dtd"-->
+]>
+
+<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+<!-- OVERLAYS -->
+<?xul-overlay href="/xul/server/OpenILS/util_overlay.xul"?>
+
+<window id="notes_win" width="700" height="550"
+ onload="try{ my_init(); font_helper(); } catch(E) { alert(E); }"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+ <!-- BEHAVIOR -->
+ <script type="text/javascript">var myPackageDir = 'open_ils_staff_client'; var IAMXUL = true; var g = {};</script>
+ <scripts id="openils_util_scripts"/>
+
+ <script type="text/javascript" src="/xul/server/main/JSAN.js"/>
+ <script>
+ <![CDATA[
+
+ function $(id) { return document.getElementById(id); }
+
+ function my_init() {
+ try {
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ if (typeof JSAN == 'undefined') {
+ throw( $("commonStrings").getString('common.jsan.missing') );
+ }
+ JSAN.errorLevel = "die"; // none, warn, or die
+ JSAN.addRepository('/xul/server/');
+
+ JSAN.use('util.error'); g.error = new util.error();
+ JSAN.use('util.network'); g.network = new util.network();
+ JSAN.use('util.date'); JSAN.use('util.money');
+ JSAN.use('OpenILS.data'); g.data = new OpenILS.data(); g.data.init({'via':'stash'});
+
+ g.error.sdump('D_TRACE','my_init() for notes.xul');
+
+ g.object_type = xul_param('object_type',{'modal_xulG':true});
+ g.object_id = xul_param('object_id',{'modal_xulG':true});
+ g.function_type = xul_param('function_type',{'modal_xulG':true});
+ g.constructor = xul_param('constructor',{'modal_xulG':true});
+
+ refresh();
+
+ } catch(E) {
+ var err_msg = $("commonStrings").getFormattedString('common.exception', ['serial/notes.xul', js2JSON(E)]);
+ try { g.error.sdump('D_ERROR',err_msg); } catch(E) { dump(err_msg); }
+ alert(err_msg);
+ }
+ }
+
+ function refresh() {
+ retrieve_notes(); render_notes();
+ }
+
+ function retrieve_notes() {
+ g.notes = g.network.simple_request('FM_'+g.function_type+'_RETRIEVE_ALL',[ { 'authtoken' : ses(), 'object_id' : g.object_id } ]).reverse();
+ }
+
+ function apply(node,field,value) {
+ util.widgets.apply(
+ node,'name',field,
+ function(n) {
+ switch(n.nodeName) {
+ case 'description' : n.appendChild( document.createTextNode( value ) ); break;
+ case 'label' : n.value = value; break;
+ default : n.value = value; break;
+ }
+ }
+ );
+ }
+
+ function render_notes() {
+ JSAN.use('util.widgets'); util.widgets.remove_children('notes_panel');
+ var np = $('notes_panel');
+ var hbox = document.createElement('hbox'); np.appendChild(hbox);
+ var btn = document.createElement('button'); hbox.appendChild(btn);
+ btn.setAttribute('label', $('catStrings').getString('staff.cat.copy_notes.render_notes.label'));
+ btn.setAttribute('accesskey', $('catStrings').getString('staff.cat.copy_notes.render_notes.accesskey'));
+ btn.setAttribute('oncommand','new_note()');
+
+ for (var i = 0; i < g.notes.length; i++) {
+
+ /* template */
+ var node = $('note_template').cloneNode(true); np.appendChild(node); node.hidden = false;
+ apply(node,'create_date',g.notes[i].create_date().toString().substr(0,10));
+ util.widgets.apply(node,'name','create_date',
+ function(n) {
+ n.setAttribute(
+ "tooltiptext",
+ $('catStrings').getString('staff.cat.copy_notes.widgets_apply.note_id') + " "
+ + g.notes[i].id() + " "
+ + $('catStrings').getString('staff.cat.copy_notes.widgets_apply.creator_id') + " "
+ + g.notes[i].creator()
+ );
+ }
+ );
+ apply(node,'title',g.notes[i].title());
+ apply(node,'pub',get_bool( g.notes[i].pub() ) ? $('catStrings').getString('staff.cat.copy_notes.widgets.public') : $('catStrings').getString('staff.cat.copy_notes.widgets.private'));
+ apply(node,'value',g.notes[i].value());
+ apply(node,'id',g.notes[i].id());
+ apply(node,'creator',g.notes[i].creator());
+
+ /* button bar */
+ var hb = document.createElement('hbox'); np.appendChild(hb);
+ var btn1 = document.createElement('button'); hb.appendChild(btn1);
+ btn1.setAttribute('label', $('catStrings').getString('staff.cat.copy_notes.delete_note.label'));
+ btn1.setAttribute('image',"/xul/server/skin/media/images/up_arrow.gif");
+
+ btn1.addEventListener(
+ 'command',
+ function(id){ return function() {
+ var r = g.error.yns_alert(
+ $('catStrings').getFormattedString('staff.cat.copy_notes.delete_note.prompt.msg', [g.notes[id].title(), g.notes[id].create_date().toString().substr(0,10)]),
+ $('catStrings').getString('staff.cat.copy_notes.delete_note.prompt.title'),
+ $('catStrings').getString('staff.cat.copy_notes.delete_note.prompt.yes'),
+ $('catStrings').getString('staff.cat.copy_notes.delete_note.prompt.no'),
+ null,
+ $('commonStrings').getString('common.confirm')
+ );
+ if (r == 0) {
+ g.network.simple_request('FM_'+g.function_type+'_DELETE',[ses(),g.notes[id].id()]);
+ setTimeout(function() {
+ alert($('catStrings').getString('staff.cat.copy_notes.delete_note.success'));
+ refresh(); },0
+ );
+ }
+ } }(i),
+ false
+ );
+ var spacer = document.createElement('spacer'); hb.appendChild(spacer); spacer.flex = 1;
+ var btn2 = document.createElement('button'); hb.appendChild(btn2);
+ btn2.setAttribute('label', $('catStrings').getString('staff.cat.copy_notes.delete_note.close_window'));
+ btn2.setAttribute('oncommand','window.close();');
+ }
+
+ }
+
+ function new_note() {
+ try {
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect UniversalBrowserWrite");
+ var xml = '<groupbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1"> \
+ <caption label="' + $('catStrings').getString('staff.cat.copy_notes.new_note.label') + '"/> \
+ <grid flex="1"><columns><column/><column flex="1"/></columns> \
+ <rows> \
+ <row><label value="' + $('catStrings').getString('staff.cat.copy_notes.new_note.public') + '"/><checkbox id="pub" name="fancy_data" checked="false"/></row> \
+ <row><label value="' + $('catStrings').getString('staff.cat.copy_notes.new_note.title') + '"/><textbox id="title" name="fancy_data" context="clipboard"/></row> \
+ <row><label value="' + $('catStrings').getString('staff.cat.copy_notes.new_note.note') + '"/><textbox multiline="true" id="note" name="fancy_data" context="clipboard"/></row> \
+ <row><spacer/><hbox> \
+ <button label="' + $('catStrings').getString('staff.cat.copy_notes.new_note.cancel.label') + '" name="fancy_cancel" accesskey="' + $('catStrings').getString('staff.cat.copy_notes.new_note.cancel.accesskey') + '"/> \
+ <button label="' + $('catStrings').getString('staff.cat.copy_notes.new_note.add_note.label') + '" accesskey="' + $('catStrings').getString('staff.cat.copy_notes.new_note.add_note.accesskey') + '" name="fancy_submit"/></hbox></row> \
+ </rows></grid></groupbox>';
+ //g.data.init({'via':'stash'});
+ //g.data.temp_note_xml = xml; g.data.stash('temp_note_xml');
+ JSAN.use('util.window'); var win = new util.window();
+ var fancy_prompt_data = win.open(
+ urls.XUL_FANCY_PROMPT,
+ //+ '?xml_in_stash=temp_note_xml'
+ //+ '&focus=' + window.escape('title')
+ //+ '&title=' + window.escape('Add Note'),
+ 'fancy_prompt', 'chrome,resizable,modal,width=700,height=500',
+ { 'xml' : xml, 'focus' : 'title', 'title' : $('catStrings').getString('staff.cat.copy_notes.new_note.add_note.label') }
+ );
+ //g.data.init({'via':'stash'});
+ if (fancy_prompt_data.fancy_status == 'complete') {
+ //alert(js2JSON(g.data.fancy_prompt_data));
+ var note = new g.constructor();
+ note.isnew(1);
+ note.title( fancy_prompt_data.title );
+ note.value( fancy_prompt_data.note );
+ note.pub( get_bool( fancy_prompt_data.pub ) ? get_db_true() : get_db_false() );
+ note[g.object_type]( g.object_id );
+ var r = g.network.simple_request('FM_'+g.function_type+'_CREATE',[ ses(), note ]);
+ if (typeof r.ilsevent != 'undefined') throw(r);
+ setTimeout(function() {
+ alert($('catStrings').getString('staff.cat.copy_notes.new_note.success'));
+ refresh();},0
+ );
+ }
+ } catch(E) {
+ g.error.standard_unexpected_error_alert($('catStrings').getString('staff.cat.copy_notes.new_note.error'),E);
+ }
+ }
+
+ ]]>
+ </script>
+
+ <messagecatalog id="catStrings" src="/xul/server/locale/<!--#echo var='locale'-->/cat.properties" />
+ <messagecatalog id="circStrings" src="/xul/server/locale/<!--#echo var='locale'-->/circ.properties" />
+
+ <stack hidden="true" id="note_template" flex="1">
+ <groupbox flex="1" style="background-color: black;"/>
+ <groupbox flex="1" style="background-color: #FFDE00; -moz-border-radius-topright: 35px;" >
+ <hbox>
+ <description name="title" style="font-weight: bold"/>
+ <spacer flex="1"/>
+ <description name="create_date" style="font-weight: bold"/>
+ <description name="pub" style="font-weight: bold"/>
+ </hbox>
+ <description name="value"/>
+ </groupbox>
+ </stack>
+
+ <vbox flex="1" class="my_overflow" id="notes_panel">
+ </vbox>
+
+
+</window>
+
--- /dev/null
+dump('entering serial/scap_editor.js\n');
+// vim:noet:sw=4:ts=4:
+
+JSAN.use('serial.editor_base');
+
+if (typeof serial == 'undefined') serial = {};
+serial.scap_editor = function (params) {
+ try {
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ JSAN.use('util.error'); this.error = new util.error();
+ JSAN.use('OpenILS.data'); this.data = new OpenILS.data(); this.data.init({'via':'stash'});
+ JSAN.use('util.network'); this.network = new util.network();
+ } catch(E) {
+ dump('serial/scap_editor: ' + E + '\n');
+ }
+
+ /* This keeps track of what fields have been edited for styling purposes */
+ this.changed = {};
+
+ /* This holds the original values for prepopulating the field editors */
+ this.editor_values = {};
+
+};
+
+serial.scap_editor.prototype = {
+ // we could do this with non-standard '__proto__' property instead
+ 'editor_base_init' : serial.editor_base.editor_base_init,
+ 'editor_base_apply' : serial.editor_base.editor_base_apply,
+ 'editor_base_save' : serial.editor_base.editor_base_save,
+
+ 'fm_type' : 'scap',
+ 'fm_type_plural' : 'scaps',
+
+ 'init' : function (params) {
+ var obj = this;
+
+ params.retrieve_function = 'FM_SCAP_BATCH_RETRIEVE.authoritative';
+
+ obj.editor_base_init(params);
+
+ /* Do it */
+ obj.summarize( obj.scaps );
+ obj.render();
+ },
+
+ /******************************************************************************************************/
+ /* Restore backup copies */
+
+ 'reset' : serial.editor_base.editor_base_reset,
+
+ /******************************************************************************************************/
+ /* Apply a value to a specific field on all the copies being edited */
+
+ 'apply' : function(field,value) {
+ var obj = this;
+
+ obj.editor_base_apply(field, value);
+ },
+
+ /******************************************************************************************************/
+
+ 'init_panes' : function () {
+ var obj = this;
+ obj.panes_and_field_names = {
+
+ /* These get shown in the left panel */
+ 'scap_editor_left_pane' :
+ [
+ [
+ 'ID',
+ {
+ render: '"ID : " + fm.id();',
+ //input: 'c = function(v){ obj.apply("distribution",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+
+ }
+ ],
+ [
+ $('catStrings').getString('staff.cat.copy_editor.field.creation_date.label'),
+ {
+ render: 'fm.create_date() == null ? "<Unset>" : util.date.formatted_date( fm.create_date(), "%F");',
+ }
+ ],
+ [
+ 'Type',
+ {
+ render: 'fm.type();',
+ input: 'c = function(v){ obj.apply("type",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( [ ["basic", "basic"], ["index", "index"], ["supplement", "supplement"] ] ); x.setAttribute("value",obj.editor_values.type); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+ value_key: 'type'
+ }
+ ],
+ [
+ 'Active?',
+ {
+ render: 'fm.active() == null ? $("catStrings").getString("staff.cat.copy_editor.field.unset_or_null") : ( get_bool( fm.active() ) ? $("catStrings").getString("staff.cat.copy_editor.field.circulate.yes_or_true") : $("catStrings").getString("staff.cat.copy_editor.field.circulate.no_or_false") )',
+ input: 'c = function(v){ obj.apply("active",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( [ [ $("catStrings").getString("staff.cat.copy_editor.field.circulate.yes_or_true"), get_db_true() ], [ $("catStrings").getString("staff.cat.copy_editor.field.circulate.no_or_false"), get_db_false() ] ] ); x.setAttribute("value",obj.editor_values.active); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+ value_key: 'active',
+ dropdown_key: 'fm.active()'
+ }
+ ],
+ [
+ 'Pattern Code (temporary)',
+ {
+ render: 'fm.pattern_code() == null ? "" : fm.pattern_code();',
+ input: 'c = function(v){ obj.apply("pattern_code",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.setAttribute("value",obj.editor_values.pattern_code); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+ value_key: 'pattern_code'
+ }
+ ]
+ ]
+
+ };
+ },
+
+ /******************************************************************************************************/
+ /* This loops through all our fieldnames and all the copies, tallying up counts for the different values */
+
+ 'summarize' : serial.editor_base.editor_base_summarize,
+
+ /******************************************************************************************************/
+ /* Display the summarized data and inputs for editing */
+
+ 'render' : serial.editor_base.editor_base_render,
+
+ /******************************************************************************************************/
+ /* This actually draws the change button and input widget for a given field */
+ 'render_input' : serial.editor_base.editor_base_render_input,
+
+ /******************************************************************************************************/
+ /* save the caption/patterns */
+
+ 'save' : function() {
+ var obj = this;
+ obj.editor_base_save('open-ils.serial.caption_and_pattern.batch.update');
+ },
+
+ /******************************************************************************************************/
+ 'save_attributes' : serial.editor_base.editor_base_save_attributes
+};
+
+dump('exiting serial/scap_editor.js\n');
--- /dev/null
+<?xml version="1.0"?>
+<!-- Application: Evergreen Staff Client -->
+<!-- Screen: Caption/Pattern Editor Overlay -->
+
+<!-- LOCALIZATION -->
+<!DOCTYPE overlay PUBLIC "" ""[
+ <!--#include virtual="/opac/locale/${locale}/lang.dtd"-->
+]>
+
+<overlay id="serial_scap_editor_panel_overlay"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <vbox flex="1" id="serial_scap_editor_panel" class="my_overflow">
+ <vbox id="brief_display_box"/>
+
+ <hbox flex="1" style="overflow: auto">
+ <vbox flex="1">
+ <label value="Caption and Pattern" style="font-weight: bold; font-size: large"/>
+ <vbox id="scap_editor_left_pane" flex="1"/>
+ </vbox>
+ </hbox>
+
+ <hbox id="scap_editor_nav">
+ <spacer flex="1"/>
+ <button id="scap_save" label="&staff.serial.scap_editor.modify;" hidden="true" accesskey="&staff.serial.scap_editor.modify.accesskey;" oncommand="g.manage_subs.scap_editor.save()" />
+ <!--<button id="cancel" label="&staff.cat.copy_editor.cancel.label;" accesskey="&staff.cat.copy_editor.cancel.accesskey;" oncommand="window.close();"/>-->
+ </hbox>
+
+ <spacer/>
+ </vbox>
+
+</overlay>
+
--- /dev/null
+dump('entering serial/sdist_editor.js\n');
+// vim:noet:sw=4:ts=4:
+
+JSAN.use('serial.editor_base');
+
+if (typeof serial == 'undefined') serial = {};
+serial.sdist_editor = function (params) {
+ try {
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ JSAN.use('util.error'); this.error = new util.error();
+ JSAN.use('OpenILS.data'); this.data = new OpenILS.data(); this.data.init({'via':'stash'});
+ JSAN.use('util.network'); this.network = new util.network();
+ } catch(E) {
+ dump('serial/sdist_editor: ' + E + '\n');
+ }
+
+ /* This keeps track of what fields have been edited for styling purposes */
+ this.changed = {};
+
+ /* This holds the original values for prepopulating the field editors */
+ this.editor_values = {};
+
+ // setup sre arrays
+ this.sre_id_map = {};
+ this.sres_ou_map = {};
+ var parent_g = window.parent.g;
+ if (parent_g.mfhd) {
+ var mfhd_details = parent_g.mfhd.details;
+ for (var i = 0; i < mfhd_details.length; i++) {
+ var mfhd_detail = mfhd_details[i];
+ mfhd_detail.label = mfhd_detail.label + ' (' + (mfhd_detail.entryNum + 1) + ')';
+ var sre_id = mfhd_detail.id;
+ var org_unit_id = mfhd_detail.owning_lib;
+ this.sre_id_map[sre_id] = mfhd_detail;
+ if (!this.sres_ou_map[org_unit_id]) {
+ this.sres_ou_map[org_unit_id] = [];
+ }
+ this.sres_ou_map[org_unit_id].push(mfhd_detail);
+ }
+ }
+};
+
+serial.sdist_editor.prototype = {
+ // we could do this with non-standard '__proto__' property instead
+ 'editor_base_init' : serial.editor_base.editor_base_init,
+ 'editor_base_apply' : serial.editor_base.editor_base_apply,
+ 'editor_base_save' : serial.editor_base.editor_base_save,
+
+ 'fm_type' : 'sdist',
+ 'fm_type_plural' : 'sdists',
+ 'can_have_notes' : true,
+
+ 'init' : function (params) {
+ var obj = this;
+
+ params.retrieve_function = 'FM_SDIST_FLESHED_BATCH_RETRIEVE.authoritative';
+
+ obj.editor_base_init(params);
+
+ obj.multi_org_edit = false;
+ var org_unit = obj.sdists[0].holding_lib();
+ for (var i = 1; i < obj.sdists.length; i++) {
+ if (obj.sdists[i].holding_lib() != org_unit) {
+ obj.multi_org_edit = true;
+ break;
+ }
+ }
+
+ /* Do it */
+ obj.summarize( obj.sdists );
+ obj.render();
+ },
+
+ /******************************************************************************************************/
+ /* Restore backup copies */
+
+ 'reset' : serial.editor_base.editor_base_reset,
+
+ /******************************************************************************************************/
+ /* Apply a value to a specific field on all the copies being edited */
+
+ 'apply' : function(field,value) {
+ var obj = this;
+
+ // null out call number if the holding lib is changed
+ obj.holding_lib_changed = (field == 'holding_lib');
+ var loop_func = function(sdist) {
+ if (obj.holding_lib_changed) {
+ sdist['bind_call_number'](null);
+ obj.changed['Bind Call Number'] = true;
+ sdist['receive_call_number'](null);
+ obj.changed['Receive Call Number'] = true;
+ sdist['bind_unit_template'](null);
+ obj.changed['Bind Unit Template'] = true;
+ sdist['receive_unit_template'](null);
+ obj.changed['Receive Unit Template'] = true;
+ sdist['record_entry'](null);
+ obj.changed['Legacy Record Entry'] = true;
+ }
+ }
+ obj.editor_base_apply(field, value, loop_func);
+ obj.holding_lib_changed = false;
+ },
+
+ /******************************************************************************************************/
+
+ 'render_call_number' : function(cn) {
+ var obj = this;
+ if (cn === null) {
+ return "<Unset>";
+ } else if (typeof cn != 'object') {
+ return obj.acn_label_map[cn];
+ } else {
+ return cn.label()
+ }
+ },
+
+ 'render_unit_template' : function(ut) {
+ var obj = this;
+ if (ut === null) {
+ return "<Unset>";
+ } else if (typeof ut != 'object') {
+ return obj.act_name_map[ut];
+ } else {
+ return ut.name()
+ }
+ },
+
+ 'render_record_entry' : function(sre) {
+ var obj = this;
+ var sre_id;
+ if (sre === null) {
+ return "<Unset>";
+ } else if (typeof sre != 'object') {
+ sre_id = sre;
+ } else {
+ sre_id = sre.id();
+ }
+ return obj.sre_id_map[sre_id].label;
+ },
+
+ 'init_panes' : function () {
+ var obj = this;
+ obj.panes_and_field_names = {
+
+ /* These get shown in the left panel */
+ 'sdist_editor_left_pane' :
+ [
+ [
+ 'ID',
+ {
+ render: '"ID : " + fm.id();',
+ //input: 'c = function(v){ obj.apply("distribution",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+
+ }
+ ],
+ [
+ 'Label',
+ {
+ render: 'fm.label() == null ? "" : fm.label();',
+ input: 'c = function(v){ obj.apply("label",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.setAttribute("value",obj.editor_values.label); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+ value_key: 'label'
+ }
+ ],
+ [
+ 'Unit Label Prefix',
+ {
+ render: 'fm.unit_label_prefix() == null ? "" : fm.unit_label_prefix();',
+ input: 'c = function(v){ obj.apply("unit_label_prefix",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.setAttribute("value",obj.editor_values.unit_label_prefix); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+ value_key: 'unit_label_prefix'
+ }
+ ],
+ [
+ 'Unit Label Suffix',
+ {
+ render: 'fm.unit_label_suffix() == null ? "" : fm.unit_label_suffix();',
+ input: 'c = function(v){ obj.apply("unit_label_suffix",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.setAttribute("value",obj.editor_values.unit_label_suffix); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+ value_key: 'unit_label_suffix'
+ }
+ ],
+ ],
+ /* These get shown in the right panel */
+ 'sdist_editor_right_pane' :
+ [
+ [
+ 'Holding Lib',
+ {
+ render: 'typeof fm.holding_lib() == "object" ? fm.holding_lib().shortname() : obj.data.hash.aou[ fm.holding_lib() ].shortname()',
+ input: 'c = function(v){ if (obj.editor_values.holding_lib != v) obj.apply("holding_lib",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( obj.data.list.aou, function(myobj) { var sname = myobj.shortname(); for (i = sname.length; i < 20; i++) sname += " "; return [ myobj.name() ? sname + " " + myobj.name() : myobj.shortname(), myobj.id(), ( ! get_bool( obj.data.hash.aout[ myobj.ou_type() ].can_have_vols() ) ), ( obj.data.hash.aout[ myobj.ou_type() ].depth() * 2), ]; }), obj.data.list.au[0].ws_ou()); x.setAttribute("value",obj.editor_values.holding_lib); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+ value_key: 'holding_lib',
+ dropdown_key: 'typeof fm.holding_lib() == "object" ? fm.holding_lib().id() : fm.holding_lib()',
+ }
+ ],
+ ],
+ /* These get shown in the right 'library-specific-options' panel */
+ 'sdist_editor_lso_pane' :
+ [
+ [
+ 'Legacy Record Entry',
+ {
+ render: 'obj.render_record_entry(fm.record_entry())',
+ input: 'if(!obj.multi_org_edit) { c = function(v){ obj.apply("record_entry",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( obj.get_sre_details_list(), function(obj) { return [ obj.label, obj.id ]; }).sort()); x.setAttribute("value",obj.editor_values.record_entry); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false); }',
+ value_key: 'record_entry',
+ dropdown_key: 'fm.record_entry() == null ? null : typeof fm.record_entry() == "object" ? fm.record_entry().id() : fm.record_entry()'
+ }
+ ],
+ [
+ 'Receive Call Number',
+ {
+ render: 'obj.render_call_number(fm.receive_call_number())',
+ input: 'if(!obj.multi_org_edit) { c = function(v){ obj.apply("receive_call_number",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( obj.get_acn_list(), function(obj) { return [ obj.label(), obj.id() ]; }).sort()); x.setAttribute("value",obj.editor_values.receive_call_number); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false); }',
+ value_key: 'receive_call_number',
+ dropdown_key: 'fm.receive_call_number() == null ? null : typeof fm.receive_call_number() == "object" ? fm.receive_call_number().id() : fm.receive_call_number()'
+ }
+ ],
+ [
+ 'Bind Call Number',
+ {
+ render: 'obj.render_call_number(fm.bind_call_number())',
+ input: 'if(!obj.multi_org_edit) { c = function(v){ obj.apply("bind_call_number",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( obj.get_acn_list(), function(obj) { return [ obj.label(), obj.id() ]; }).sort()); x.setAttribute("value",obj.editor_values.bind_call_number); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false); }',
+ value_key: 'bind_call_number',
+ dropdown_key: 'fm.bind_call_number() == null ? null : typeof fm.bind_call_number() == "object" ? fm.bind_call_number().id() : fm.bind_call_number()'
+ }
+ ],
+ [
+ 'Receive Unit Template',
+ {
+ render: 'obj.render_unit_template(fm.receive_unit_template())',
+ input: 'if(!obj.multi_org_edit) { c = function(v){ obj.apply("receive_unit_template",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( obj.get_act_list(), function(obj) { return [ obj.name(), obj.id() ]; }).sort()); x.setAttribute("value",obj.editor_values.receive_unit_template); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false); }',
+ value_key: 'receive_unit_template',
+ dropdown_key: 'fm.receive_unit_template() == null ? null : typeof fm.receive_unit_template() == "object" ? fm.receive_unit_template().id() : fm.receive_unit_template()'
+ }
+ ],
+ [
+ 'Bind Unit Template',
+ {
+ render: 'obj.render_unit_template(fm.bind_unit_template())',
+ input: 'if(!obj.multi_org_edit) { c = function(v){ obj.apply("bind_unit_template",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( obj.get_act_list(), function(obj) { return [ obj.name(), obj.id() ]; }).sort()); x.setAttribute("value",obj.editor_values.bind_unit_template); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false); }',
+ value_key: 'bind_unit_template',
+ dropdown_key: 'fm.bind_unit_template() == null ? null : typeof fm.bind_unit_template() == "object" ? fm.bind_unit_template().id() : fm.bind_unit_template()'
+ }
+ ],
+ ],
+
+ };
+ },
+
+ /******************************************************************************************************/
+ /* This loops through all our fieldnames and all the copies, tallying up counts for the different values */
+
+ 'summarize' : serial.editor_base.editor_base_summarize,
+
+ /******************************************************************************************************/
+ /* Display the summarized data and inputs for editing */
+
+ 'render' : serial.editor_base.editor_base_render,
+
+ /******************************************************************************************************/
+ /* This actually draws the change button and input widget for a given field */
+ 'render_input' : serial.editor_base.editor_base_render_input,
+
+ /******************************************************************************************************/
+ /* save the distributions */
+
+ 'save' : function() {
+ var obj = this;
+ obj.editor_base_save('open-ils.serial.distribution.fleshed.batch.update');
+ },
+
+ /******************************************************************************************************/
+ /* spawn notes interface */
+
+ 'notes' : function() {
+ var obj = this;
+ JSAN.use('util.window'); var win = new util.window();
+ win.open(
+ urls.XUL_SERIAL_NOTES,
+ //+ '?copy_id=' + window.escape(obj.sdists[0].id()),
+ 'Distribution Notes','chrome,resizable,modal',
+ { 'object_id' : obj.sdists[0].id(), 'function_type' : 'SDISTN', 'object_type' : 'distribution', 'constructor' : sdistn }
+ );
+ },
+
+ /******************************************************************************************************/
+ 'save_attributes' : serial.editor_base.editor_base_save_attributes,
+
+ /******************************************************************************************************/
+ /* This returns a list of sre details appropriate for the distributions being edited */
+
+ 'get_sre_details_list' : function() {
+ var obj = this;
+ try {
+ /* we only show this list if dealing with one org_unit, default to first sdist*/
+ var lib_id = typeof obj.sdists[0].holding_lib() == 'object' ? obj.sdists[0].holding_lib().id() : obj.sdists[0].holding_lib();
+ var sre_details_list = obj.sres_ou_map[lib_id];
+ if (sre_details_list == null) {
+ return [];
+ } else {
+ return sre_details_list;
+ }
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert('get_sre_details_list',E);
+ return [];
+ }
+ },
+
+ /******************************************************************************************************/
+ /* This returns a list of acn's appropriate for the distributions being edited */
+
+ 'get_acn_list' : function() {
+ var obj = this;
+ try {
+ var lib_id = typeof obj.sdists[0].holding_lib() == 'object' ? obj.sdists[0].holding_lib().id() : obj.sdists[0].holding_lib();
+
+ if (!obj.acn_lists) {
+ obj.acn_lists = {};
+ }
+
+ // return cached version if we have it
+ // TODO: clear cache on holding_lib change? (cannot remember how to reproduce this bug)
+ if (obj.acn_lists[lib_id]) {
+ return obj.acn_lists[lib_id];
+ }
+
+ var acn_list = obj.network.request(
+ 'open-ils.pcrud',
+ 'open-ils.pcrud.search.acn',
+ [ ses(), {"record" : obj.docid, "owning_lib" : lib_id, "deleted" : 'f' }, {"order_by" : {"acn" : "label"} } ]
+ );
+
+ if (!acn_list) {
+ return [];
+ } else if (!acn_list.length) {
+ acn_list = [acn_list];
+ }
+
+ // build label map
+ obj.acn_label_map = {};
+ for (i = 0; i < acn_list.length; i++) {
+ obj.acn_label_map[acn_list[i].id()] = acn_list[i].label();
+ }
+
+ // cache the list
+ obj.acn_lists[lib_id] = acn_list;
+ return acn_list;
+
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert('get_acn_list',E);
+ return [];
+ }
+ },
+
+ /******************************************************************************************************/
+ /* This returns a list of asset copy templates appropriate for the distributions being edited */
+
+ 'get_act_list' : function() {
+ var obj = this;
+ try {
+ /* we only show this list if dealing with one org_unit, default to first sdist*/
+ var lib_id = typeof obj.sdists[0].holding_lib() == 'object' ? obj.sdists[0].holding_lib().id() : obj.sdists[0].holding_lib();
+
+ if (!obj.act_lists) {
+ obj.act_lists = {};
+ }
+
+ // return cached version if we have it
+ if (obj.act_lists[lib_id]) {
+ return obj.act_lists[lib_id];
+ }
+
+ var act_list = obj.network.request(
+ 'open-ils.pcrud',
+ 'open-ils.pcrud.search.act',
+ [ ses(), {"owning_lib" : lib_id }, {"order_by" : {"act" : "name"} } ]
+ );
+
+ if (act_list == null) {
+ return [];
+ } else if (!act_list.length) {
+ act_list = [act_list];
+ }
+
+ // build name map
+ obj.act_name_map = {};
+ for (i = 0; i < act_list.length; i++) {
+ obj.act_name_map[act_list[i].id()] = act_list[i].name();
+ }
+
+ // cache the list
+ obj.act_lists[lib_id] = act_list;
+ return act_list;
+ } catch(E) {
+ obj.error.standard_unexpected_error_alert('get_act_list',E);
+ return [];
+ }
+ }
+
+};
+
+dump('exiting serial/sdist_editor.js\n');
--- /dev/null
+<?xml version="1.0"?>
+<!-- Application: Evergreen Staff Client -->
+<!-- Screen: Distribution Editor Overlay -->
+
+<!-- LOCALIZATION -->
+<!DOCTYPE overlay PUBLIC "" ""[
+ <!--#include virtual="/opac/locale/${locale}/lang.dtd"-->
+]>
+
+<overlay id="serial_sdist_editor_panel_overlay"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <vbox flex="1" id="serial_sdist_editor_panel" class="my_overflow">
+ <vbox id="brief_display_box"/>
+
+ <hbox flex="1" style="overflow: auto">
+ <vbox flex="1">
+ <label value="Distribution" style="font-weight: bold; font-size: large"/>
+ <vbox id="sdist_editor_left_pane" flex="1"/>
+ </vbox>
+ <splitter><grippy /></splitter>
+ <vbox flex="1">
+ <vbox id="sdist_editor_right_pane"/>
+ <groupbox>
+ <caption label="Library Specific Options" />
+ <description>Note: Changing the 'Holding Lib' will unset all of these values</description>
+ <vbox id="sdist_editor_lso_pane" flex="1"/>
+ </groupbox>
+ </vbox>
+ </hbox>
+
+ <hbox id="sdist_editor_nav">
+ <spacer flex="1"/>
+ <button id="sdist_notes" label="&staff.serial.sdist_editor.notes;" accesskey="&staff.serial.sdist_editor.notes.accesskey;" oncommand="g.manage_subs.sdist_editor.notes()" />
+ <button id="sdist_save" label="&staff.serial.sdist_editor.modify;" hidden="true" accesskey="&staff.serial.ssub_editor.modify.accesskey;" oncommand="g.manage_subs.sdist_editor.save()" />
+ <!--<button id="cancel" label="&staff.cat.copy_editor.cancel.label;" accesskey="&staff.cat.copy_editor.cancel.accesskey;" oncommand="window.close();"/>-->
+ </hbox>
+
+ <spacer/>
+ </vbox>
+
+</overlay>
+
--- /dev/null
+<?xml version="1.0"?>
+<!-- Application: Evergreen Staff Client -->
+<!-- Screen: Select AOU Dialog -->
+
+<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+<!-- STYLESHEETS -->
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="chrome://open_ils_staff_client/skin/global.css" type="text/css"?>
+<?xml-stylesheet href="/xul/server/skin/global.css" type="text/css"?>
+<?xml-stylesheet href="/xul/server/skin/cat.css" type="text/css"?>
+
+<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+<!-- LOCALIZATION -->
+<!DOCTYPE window PUBLIC "" ""[
+ <!--#include virtual="/opac/locale/${locale}/lang.dtd"-->
+]>
+
+<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+<!-- OVERLAYS -->
+<?xul-overlay href="/xul/server/OpenILS/util_overlay.xul"?>
+
+<window id="select_aou_win" title="Select Org Unit"
+ onload="try { my_init(); font_helper(); persist_helper(); } catch(E) { alert(E); }" oils_persist="height width"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+ <!-- BEHAVIOR -->
+ <script type="text/javascript">var myPackageDir = 'open_ils_staff_client'; var IAMXUL = true; var g = {};</script>
+ <scripts id="openils_util_scripts"/>
+
+ <script type="text/javascript" src="/xul/server/main/JSAN.js"/>
+ <script>
+ <![CDATA[
+ function $(id) { return document.getElementById(id); }
+ function $c(n) { return document.createElement(n); }
+
+ function my_init() {
+ try {
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ if (typeof JSAN == 'undefined') { throw( $("commonStrings").getString('common.jsan.missing') ); }
+ JSAN.errorLevel = "die"; // none, warn, or die
+ JSAN.addRepository('/xul/server/');
+ JSAN.use('util.error'); g.error = new util.error();
+ g.error.sdump('D_TRACE','my_init() for serial/select_aou.xul');
+
+ JSAN.use('util.file'); JSAN.use('util.widgets');
+
+ var file; var list_data; var ml;
+
+ file = new util.file('offline_ou_list');
+ if (file._file.exists()) {
+ list_data = file.get_object(); file.close();
+ ml = util.widgets.make_menulist( list_data[0], list_data[1] );
+ ml.setAttribute('id','lib_menu');
+ document.getElementById('x_lib_menu').appendChild(ml);
+ ml.addEventListener(
+ 'command',
+ function(ev) {
+ //if (document.getElementById('refresh_button')) document.getElementById('refresh_button').focus();
+ JSAN.use('util.file'); var file = new util.file('mfhd_create_prefs.'+opener.g.data.server_unadorned);
+ util.widgets.save_attributes(file, { 'lib_menu' : [ 'value' ] });
+ },
+ false
+ );
+ } else {
+ throw(document.getElementById('catStrings').getString('staff.cat.copy_browser.missing_library') + '\n'); //TODO: different error?
+ }
+
+ file = new util.file('mfhd_create_prefs.'+opener.g.data.server_unadorned);
+ util.widgets.load_attributes(file);
+ ml.value = ml.getAttribute('value');
+ } catch(E) {
+ //TODO: better error
+ g.error.standard_unexpected_error_alert('', E);
+ }
+ }
+
+ g.select_aou = function() {
+ opener.g.data.create_mfhd_aou = $('lib_menu').value;
+ window.close();
+ }
+
+ ]]>
+ </script>
+
+ <messagecatalog id="catStrings" src="/xul/server/locale/<!--#echo var='locale'-->/cat.properties" />
+
+ <vbox flex="1" style="overflow: auto">
+ <groupbox flex="1">
+<!--TODO: label strings -->
+ <caption label="Select an Org Unit"/>
+ <description id="desc">Please select an Org Unit</description>
+ <hbox id="x_lib_menu"/>
+ <hbox>
+ <button label="Select"
+ accesskey="s" oncommand="g.select_aou()"/>
+ <button label="&staff.cat.record_buckets_quick.cancel.label;"
+ accesskey="&staff.cat.record_buckets_quick.cancel.accesskey;" oncommand="window.close()"/>
+ </hbox>
+ <hbox>
+ </hbox>
+ </groupbox>
+ </vbox>
+
+</window>
+
--- /dev/null
+<?xml version="1.0"?>
+<!-- Application: Evergreen Staff Client -->
+<!-- Screen: Select Serial Unit Dialog -->
+
+<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+<!-- STYLESHEETS -->
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="chrome://open_ils_staff_client/skin/global.css" type="text/css"?>
+<?xml-stylesheet href="/xul/server/skin/global.css" type="text/css"?>
+<?xml-stylesheet href="/xul/server/skin/cat.css" type="text/css"?>
+
+<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+<!-- LOCALIZATION -->
+<!DOCTYPE window PUBLIC "" ""[
+ <!--#include virtual="/opac/locale/${locale}/lang.dtd"-->
+]>
+
+<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+<!-- OVERLAYS -->
+<?xul-overlay href="/xul/server/OpenILS/util_overlay.xul"?>
+
+<window id="select_serial_unit_win" title="Select Serial Unit"
+ onload="try { my_init(); font_helper(); persist_helper(); } catch(E) { alert(E); }" oils_persist="height width"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+ <!-- BEHAVIOR -->
+ <script type="text/javascript">var myPackageDir = 'open_ils_staff_client'; var IAMXUL = true; var g = {};</script>
+ <scripts id="openils_util_scripts"/>
+
+ <script type="text/javascript" src="/xul/server/main/JSAN.js"/>
+ <script>
+ <![CDATA[
+ function $(id) { return document.getElementById(id); }
+
+ function my_init() {
+ try {
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ if (typeof JSAN == 'undefined') { throw( $("commonStrings").getString('common.jsan.missing') ); }
+ JSAN.errorLevel = "die"; // none, warn, or die
+ JSAN.addRepository('/xul/server/');
+ JSAN.use('util.error'); g.error = new util.error();
+ g.error.sdump('D_TRACE','my_init() for serial/select_unit.xul');
+
+ JSAN.use('util.widgets');
+
+ var ml;
+ JSAN.use('util.network'); g.network = new util.network();
+ var robj = g.network.request(
+ 'open-ils.serial',
+ 'open-ils.serial.unit_list.retrieve',
+ opener.g.serial_items_sdist_ids
+ );
+ if (typeof robj.ilsevent != 'undefined') throw(robj);
+ ml = util.widgets.make_menulist(robj);
+ ml.setAttribute('id','unit_menu');
+ document.getElementById('x_unit_menu').appendChild(ml);
+ } catch(E) {
+ //TODO: better error
+ g.error.standard_unexpected_error_alert('', E);
+ }
+ }
+
+ g.select_unit = function() {
+ var selection = JSON2js($('unit_menu').value);
+ selection.label = $('unit_menu').selectedItem.label;
+ opener.g.serial_items_sunit_select = selection;
+ window.close();
+ }
+
+ ]]>
+ </script>
+
+ <messagecatalog id="catStrings" src="/xul/server/locale/<!--#echo var='locale'-->/cat.properties" />
+
+ <vbox flex="1" style="overflow: auto">
+ <groupbox flex="1">
+<!--TODO: label strings -->
+ <caption label="Select a Serial Unit"/>
+ <description id="desc">Please select a Serial Unit</description>
+ <hbox id="x_unit_menu"/>
+ <hbox>
+ <button label="Select"
+ accesskey="s" oncommand="g.select_unit()"/>
+ <button label="&staff.cat.record_buckets_quick.cancel.label;"
+ accesskey="&staff.cat.record_buckets_quick.cancel.accesskey;" oncommand="window.close()"/>
+ </hbox>
+ <hbox>
+ </hbox>
+ </groupbox>
+ </vbox>
+
+</window>
+
--- /dev/null
+<?xml version="1.0"?>
+<!-- Application: Evergreen Staff Client -->
+<!-- Screen: Serial Control Main -->
+<!--
+vim:noet:sw=4:ts=4:
+-->
+
+<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+<!-- STYLESHEETS -->
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="chrome://open_ils_staff_client/skin/global.css" type="text/css"?>
+<?xml-stylesheet href="/xul/server/skin/global.css" type="text/css"?>
+<?xml-stylesheet href="/xul/server/skin/cat.css" type="text/css"?>
+
+<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+<!-- LOCALIZATION -->
+<!DOCTYPE window PUBLIC "" ""[
+<!--#include virtual="/opac/locale/${locale}/lang.dtd"-->
+]>
+
+<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+<!-- OVERLAYS -->
+<?xul-overlay href="/xul/server/OpenILS/util_overlay.xul"?>
+<?xul-overlay href="/xul/server/serial/manage_items.xul"?>
+<?xul-overlay href="/xul/server/serial/manage_subs.xul"?>
+
+<window id="serial_serctrl_main"
+ onload="try { my_init(); font_helper(); } catch(E) { alert(E); }"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+ <!-- BEHAVIOR -->
+ <script type="text/javascript">
+ var myPackageDir = 'open_ils_staff_client'; var IAMXUL = true; var g = {};
+ </script>
+ <scripts id="openils_util_scripts"/>
+
+ <script type="text/javascript" src="/xul/server/main/JSAN.js"/>
+
+ <messagecatalog id="catStrings" src="/xul/server/locale/<!--#echo var='locale'-->/cat.properties" />
+ <messagecatalog id="circStrings" src="/xul/server/locale/<!--#echo var='locale'-->/circ.properties" />
+ <messagecatalog id="patronStrings" src="/xul/server/locale/<!--#echo var='locale'-->/patron.properties"/>
+ <messagecatalog id="serialStrings" src="/xul/server/locale/<!--#echo var='locale'-->/serial.properties"/>
+
+ <commandset id="serial_commands">
+ <command id="cmd_add_item"/>
+ <command id="cmd_add_scap"/>
+ <command id="cmd_add_sdist"/>
+ <command id="cmd_add_siss"/>
+ <command id="cmd_add_subscriptions"/>
+ <command id="cmd_broken" />
+ <command id="cmd_clear" />
+ <command id="cmd_edit_items"/>
+ <command id="cmd_edit_sdists"/>
+ <command id="cmd_edit_subscriptions"/>
+ <command id="cmd_edit_sunit"/>
+ <command id="cmd_delete_items"/>
+ <command id="cmd_delete_scap"/>
+ <command id="cmd_delete_sdist"/>
+ <command id="cmd_delete_siss"/>
+ <command id="cmd_delete_ssub"/>
+ <command id="cmd_make_predictions"/>
+ <command id="cmd_mark_library"/>
+ <command id="cmd_mark_subscription"/>
+ <command id="cmd_predict_items"/>
+ <command id="cmd_print_spine_labels"/>
+ <command id="cmd_receive_items"/>
+ <command id="cmd_refresh_list"/>
+ <command id="cmd_replace_barcode"/>
+ <command id="cmd_set_sunit" />
+ <command id="cmd_set_other_sunit" />
+ <command id="cmd_show_all_libs" />
+ <command id="cmd_show_libs_with_distributions" />
+ <command id="cmd_show_my_libs" />
+ <command id="cmd_transfer_items"/>
+ <command id="cmd_transfer_sdists"/>
+ <command id="cmd_transfer_subscription"/>
+ <command id="save_columns" />
+ <command id="sel_clip" />
+ <command id="sel_mark_items_damaged" />
+ <command id="sel_mark_items_missing" />
+ <command id="sel_mark_sdists_damaged" />
+ <command id="sel_mark_sdists_missing" />
+ </commandset>
+
+ <!--<popupset>
+ <popup id="serctrl_main_actions">
+ <menuitem command="cmd_add_items" label="&staff.cat.copy_browser.actions.cmd_add_items.label;" accesskey="&staff.cat.copy_browser.actions.cmd_add_items.accesskey;"/>
+ <menuitem command="cmd_edit_items" label="Edit Item Attributes" accesskey="&staff.cat.copy_browser.actions.cmd_edit_items.accesskey;"/>
+ <menuitem command="cmd_delete_items" label="Delete Item" accesskey="&staff.cat.copy_browser.actions.cmd_delete_items.accesskey;"/>
+ <menuitem command="sel_clip" label="&staff.cat.copy_browser.actions.sel_clip.label;" accesskey="&staff.cat.copy_browser.actions.sel_clip.accesskey;"/>
+ <menuseparator/>
+ <menuitem command="cmd_edit_volumes" label="&staff.cat.copy_browser.actions.cmd_edit_volumes.label;" accesskey="&staff.cat.copy_browser.actions.cmd_edit_volumes.accesskey;"/>
+ <menuitem command="cmd_mark_volume" label="&staff.cat.copy_browser.actions.cmd_mark_volume.label;" accesskey="&staff.cat.copy_browser.actions.cmd_mark_volume.accesskey;"/>
+ <menuitem command="cmd_transfer_volume" label="&staff.cat.copy_browser.actions.cmd_transfer_volume.label;" accesskey="&staff.cat.copy_browser.actions.cmd_transfer_volume.accesskey;"/>
+ <menuitem command="cmd_delete_volumes" label="&staff.cat.copy_browser.actions.cmd_delete_volumes.label;" accesskey=""/>
+ <menuseparator/>
+ <menuitem command="save_columns" label="&staff.cat.copy_browser.actions.save_columns.label;"/>
+ <menuitem command="cmd_refresh_list" label="&staff.cat.copy_browser.actions.cmd_refresh_list.label;" accesskey="&staff.cat.copy_browser.actions.cmd_refresh_list.accesskey;"/>
+ </popup>
+ </popupset> -->
+
+<!-- <groupbox flex="1" class="my_overflow"> -->
+ <tabbox id="serial_tabbox" flex="1" class="my_overflow">
+ <caption label="Serial Control"/>
+ <tabs>
+ <tab label="Items" />
+ <tab label="Units" />
+ <tab label="Distributions" />
+ <tab id="serial_manage_subs_tab" label="Subscriptions" />
+ <tab label="Claims" />
+ </tabs>
+ <tabpanels flex="1">
+ <tabpanel id="serial_manage_items" />
+ <tabpanel id="serial_manage_units"><description>This tab will contain an alternative unit view/editor.</description></tabpanel>
+ <tabpanel id="serial_manage_distributions"><description>This tab will contain a tree of distributions with editors for templates, summaries, and streams.</description></tabpanel>
+ <tabpanel id="serial_manage_subs" />
+ <tabpanel id="serial_manage_claims"><description>This tab will contain a claims interface.</description></tabpanel>
+ </tabpanels>
+ </tabbox>
+<!-- </groupbox> -->
+
+</window>
+
--- /dev/null
+dump('entering serial/siss_editor.js\n');
+// vim:noet:sw=4:ts=4:
+
+JSAN.use('serial.editor_base');
+
+if (typeof serial == 'undefined') serial = {};
+serial.siss_editor = function (params) {
+ try {
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ JSAN.use('util.error'); this.error = new util.error();
+ JSAN.use('OpenILS.data'); this.data = new OpenILS.data(); this.data.init({'via':'stash'});
+ JSAN.use('util.network'); this.network = new util.network();
+ } catch(E) {
+ dump('serial/siss_editor: ' + E + '\n');
+ }
+
+ /* This keeps track of what fields have been edited for styling purposes */
+ this.changed = {};
+
+ /* This holds the original values for prepopulating the field editors */
+ this.editor_values = {};
+};
+
+serial.siss_editor.prototype = {
+ // we could do this with non-standard '__proto__' property instead
+ 'editor_base_init' : serial.editor_base.editor_base_init,
+ 'editor_base_apply' : serial.editor_base.editor_base_apply,
+ 'editor_base_save' : serial.editor_base.editor_base_save,
+
+ 'fm_type' : 'siss',
+ 'fm_type_plural' : 'sisses',
+ 'can_have_notes' : true,
+
+ 'init' : function (params) {
+ var obj = this;
+
+ params.retrieve_function = 'FM_SISS_FLESHED_BATCH_RETRIEVE.authoritative';
+
+ obj.editor_base_init(params);
+
+ /* Do it */
+ obj.summarize( obj.sisses );
+ obj.render();
+ },
+
+ /******************************************************************************************************/
+ /* Restore backup copies */
+
+ 'reset' : serial.editor_base.editor_base_reset,
+
+ /******************************************************************************************************/
+ /* Apply a value to a specific field on all the copies being edited */
+
+ 'apply' : function(field,value) {
+ var obj = this;
+ if (field == 'date_published') {
+ if (value == '') { value = null; }
+ }
+ obj.editor_base_apply(field, value);
+ },
+
+ /******************************************************************************************************/
+ /* Initialize the panes */
+
+ 'init_panes' : function () {
+ var obj = this;
+ obj.panes_and_field_names = {
+
+ /* These get shown in the left panel */
+ 'siss_editor_left_pane' :
+ [
+ [
+ $('catStrings').getString('staff.cat.copy_editor.field.creation_date.label') + ' ', //adding extra spaces to satisfy summarize uniqueness requirements
+ {
+ render: 'fm.create_date() == null ? "<Unset>" : util.date.formatted_date( fm.create_date(), "%F");',
+ }
+ ],
+ [
+ $('catStrings').getString('staff.cat.copy_editor.field.creator.label') + ' ',
+ {
+ render: 'fm.creator().usrname() == null ? "<Unset>" : fm.creator().usrname();',
+ }
+ ],
+ [
+ $('catStrings').getString('staff.cat.copy_editor.field.last_edit_date.label') + ' ',
+ {
+ render: 'fm.edit_date() == null ? "<Unset>" : util.date.formatted_date( fm.edit_date(), "%F");',
+ }
+ ],
+ [
+ $('catStrings').getString('staff.cat.copy_editor.field.last_editor.label') + ' ',
+ {
+ render: 'fm.editor().usrname() == null ? "<Unset>" : fm.editor().usrname();',
+ }
+ ],
+ ],
+
+ 'siss_editor_middle_pane' :
+ [
+/*rjs7 don't think we need these anymore [
+ 'Holding Type',
+ {
+ render: 'fm.holding_type();',
+ input: 'c = function(v){ obj.apply("holding_type",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( [ ["basic", "basic"], ["index", "index"], ["supplement", "supplement"] ] ); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+ }
+ ],
+ [
+ 'Holding Link ID',
+ {
+ render: 'fm.holding_link_id();',
+ input: 'c = function(v){ obj.apply("holding_link_id",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.setAttribute("value",obj.editor_values.holding_link_id); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+ value_key: 'holding_link_id'
+ }
+ ],*/
+ [
+ 'Holding Code',
+ {
+ render: 'fm.holding_code();',
+ input: 'c = function(v){ obj.apply("holding_code",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.setAttribute("value",obj.editor_values.holding_code); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+ value_key: 'holding_code'
+ }
+ ],
+ [
+ 'Caption/Pattern', //TODO: make this a drop-down selector, perhaps?
+ {
+ render: 'fm.caption_and_pattern();',
+ input: 'c = function(v){ obj.apply("caption_and_pattern",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.setAttribute("value",obj.editor_values.caption_and_pattern); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+ value_key: 'caption_and_pattern'
+ }
+ ],
+ ],
+
+ 'siss_editor_right_pane' :
+ [
+ [
+ 'Date Published',
+ {
+ render: 'fm.date_published() == null ? "" : util.date.formatted_date( fm.date_published(), "%F");',
+ input: 'c = function(v){ obj.apply("date_published",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.setAttribute("value",obj.editor_values.date_published); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+ value_key: 'date_published'
+ }
+ ],
+ [
+ 'Issuance Label',
+ {
+ render: 'fm.label() == null ? "" : fm.label();',
+ input: 'c = function(v){ obj.apply("label",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.setAttribute("value",obj.editor_values.label); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+ value_key: 'label'
+ }
+ ],
+ ],
+
+ };
+ },
+
+ /******************************************************************************************************/
+ /* This loops through all our fieldnames and all the copies, tallying up counts for the different values */
+
+ 'summarize' : serial.editor_base.editor_base_summarize,
+
+ /******************************************************************************************************/
+ /* Display the summarized data and inputs for editing */
+
+ 'render' : serial.editor_base.editor_base_render,
+
+ /******************************************************************************************************/
+ /* This actually draws the change button and input widget for a given field */
+ 'render_input' : serial.editor_base.editor_base_render_input,
+
+ /******************************************************************************************************/
+ /* update the issuances */
+
+ 'save' : function() {
+ var obj = this;
+ obj.editor_base_save('open-ils.serial.issuance.fleshed.batch.update');
+ },
+
+ /******************************************************************************************************/
+ /* spawn issuance notes interface */
+
+ 'notes' : function() {
+ var obj = this;
+ JSAN.use('util.window'); var win = new util.window();
+ win.open(
+ urls.XUL_SERIAL_NOTES,
+ 'Issuance Notes','chrome,resizable,modal',
+ { 'object_id' : obj.sisses[0].id(), 'function_type' : 'SISSN', 'object_type' : 'issuance', 'constructor' : sissn }
+ );
+ },
+
+ /******************************************************************************************************/
+ 'save_attributes' : serial.editor_base.editor_base_save_attributes
+};
+
+dump('exiting serial/siss_editor.js\n');
--- /dev/null
+<?xml version="1.0"?>
+<!-- Application: Evergreen Staff Client -->
+<!-- Screen: Issuance Editor Overlay -->
+
+<!-- LOCALIZATION -->
+<!DOCTYPE overlay PUBLIC "" ""[
+ <!--#include virtual="/opac/locale/${locale}/lang.dtd"-->
+]>
+
+<overlay id="serial_siss_editor_panel_overlay"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <vbox flex="1" id="serial_siss_editor_panel" class="my_overflow">
+ <vbox id="brief_display_box"/>
+
+ <hbox flex="1" style="overflow: auto">
+ <vbox flex="1">
+ <label value="Issuance" style="font-weight: bold; font-size: large"/>
+ <vbox id="siss_editor_left_pane" flex="1"/>
+ </vbox>
+ <splitter><grippy /></splitter>
+ <vbox flex="1">
+ <vbox id="siss_editor_middle_pane"/>
+ </vbox>
+ <splitter><grippy /></splitter>
+ <vbox flex="1">
+ <vbox id="siss_editor_right_pane"/>
+ </vbox>
+ </hbox>
+
+ <hbox id="siss_editor_nav">
+ <spacer flex="1"/>
+ <button id="siss_notes" label="Issuance Notes" accesskey="&staff.cat.copy_editor.copy_notes.accesskey;" oncommand="g.manage_subs.siss_editor.notes()" />
+ <button id="siss_save" label="Modify Issuances" hidden="true" accesskey="&staff.cat.copy_editor.save.accesskey;" oncommand="g.manage_subs.siss_editor.save()" />
+ <!--<button id="cancel" label="&staff.cat.copy_editor.cancel.label;" accesskey="&staff.cat.copy_editor.cancel.accesskey;" oncommand="window.close();"/>-->
+ </hbox>
+
+ <spacer/>
+ </vbox>
+
+</overlay>
+
--- /dev/null
+dump('entering serial/sitem_editor.js\n');
+// vim:noet:sw=4:ts=4:
+
+JSAN.addRepository('/xul/server/');
+JSAN.use('serial.editor_base');
+
+if (typeof serial == 'undefined') serial = {};
+serial.sitem_editor = function (params) {
+ try {
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ JSAN.use('util.error'); this.error = new util.error();
+ JSAN.use('OpenILS.data'); this.data = new OpenILS.data(); this.data.init({'via':'stash'});
+ JSAN.use('util.network'); this.network = new util.network();
+ } catch(E) {
+ dump('serial/sitem_editor: ' + E + '\n');
+ }
+
+ /* This keeps track of what fields have been edited for styling purposes */
+ this.changed = {};
+
+ /* This holds the original values for prepopulating the field editors */
+ this.editor_values = {};
+};
+
+serial.sitem_editor.prototype = {
+ // we could do this with non-standard '__proto__' property instead
+ 'editor_base_init' : serial.editor_base.editor_base_init,
+ 'editor_base_apply' : serial.editor_base.editor_base_apply,
+ 'editor_base_save' : serial.editor_base.editor_base_save,
+
+ 'fm_type' : 'sitem',
+ 'fm_type_plural' : 'sitems',
+ 'can_have_notes' : true,
+
+ 'init' : function (params) {
+ var obj = this;
+
+ params.retrieve_function = 'FM_SITEM_FLESHED_BATCH_RETRIEVE.authoritative';
+
+ obj.editor_base_init(params);
+
+ /* Do it */
+ obj.summarize( obj.sitems );
+ obj.render();
+ },
+
+ /******************************************************************************************************/
+ /* Restore backup copies */
+
+ 'reset' : serial.editor_base.editor_base_reset,
+
+ /******************************************************************************************************/
+ /* Apply a value to a specific field on all the copies being edited */
+
+ 'apply' : function(field,value) {
+ var obj = this;
+ JSAN.use('util.date');
+ if (field == 'date_expected') {
+ if (value == '') {
+ alert("Date Expected cannot be unset.");
+ return false;
+ } else if (!util.date.check('YYYY-MM-DD',value)) {
+ alert("Invalid Date");
+ return false;
+ }
+ } else if (field == 'date_received') { // manually unset not allowed
+ if (value == '') {
+ alert("Date Received cannot be manually unset; use 'Reset to Expected' instead.");
+ return false;
+ } else if (!util.date.check('YYYY-MM-DD',value)) {
+ alert("Invalid Date");
+ return false;
+ }
+ }
+ obj.editor_base_apply(field, value);
+ return true;
+ },
+
+ /******************************************************************************************************/
+
+ 'init_panes' : function () {
+ var obj = this;
+ obj.panes_and_field_names = {
+
+ /* These get shown in the left panel */
+ 'sitem_editor_left_pane' :
+ [
+ [
+ 'ID',
+ {
+ render: '"#" + fm.id();',
+
+ }
+ ],
+ [
+ 'Status',
+ {
+ render: 'fm.status();',
+ value_key: 'label'
+ }
+ ]
+ ],
+ /* These get shown in the middle panel */
+ 'sitem_editor_middle_pane' :
+ [
+ [
+ 'Distribution',
+ {
+ render: 'fm.stream().distribution().label() == null ? "" : fm.stream().distribution().label();',
+
+ }
+ ],
+ [
+ 'Shelving Unit ID',
+ {
+ render: 'fm.unit() == null ? "" : "#" + fm.unit().id();',
+ }
+ ],
+ ],
+
+ /* These get shown in the right panel */
+ 'sitem_editor_right_pane' :
+ [
+ [
+ 'Date Expected',
+ {
+ render: 'fm.date_expected() == null ? "" : util.date.formatted_date( fm.date_expected(), "%F");',
+ input: 'c = function(v){ var applied = obj.apply("date_expected",v); if (typeof post_c == "function") post_c(v, !applied);}; x = document.createElement("textbox"); x.setAttribute("value",obj.editor_values.date_expected); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+ value_key: 'date_expected'
+ }
+ ],
+ [
+ 'Date Received',
+ {
+ render: 'fm.date_received() == null ? "" : util.date.formatted_date( fm.date_received(), "%F");',
+ input: 'if (obj.editor_values.date_received) { c = function(v){ var applied = obj.apply("date_received",v); if (typeof post_c == "function") post_c(v, !applied);}; x = document.createElement("textbox"); x.setAttribute("value",obj.editor_values.date_received); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false); } else { alert("Cannot edit Date Received for unreceived items."); block = false; }',
+ value_key: 'date_received'
+ }
+ ],
+ ],
+
+ };
+ },
+
+ /******************************************************************************************************/
+ /* This loops through all our fieldnames and all the copies, tallying up counts for the different values */
+
+ 'summarize' : serial.editor_base.editor_base_summarize,
+
+ /******************************************************************************************************/
+ /* Display the summarized data and inputs for editing */
+
+ 'render' : serial.editor_base.editor_base_render,
+
+ /******************************************************************************************************/
+ /* This actually draws the change button and input widget for a given field */
+ 'render_input' : serial.editor_base.editor_base_render_input,
+
+ /******************************************************************************************************/
+ /* save the items */
+
+ 'save' : function() {
+ var obj = this;
+ obj.editor_base_save('open-ils.serial.item.fleshed.batch.update');
+ },
+
+ /******************************************************************************************************/
+ /* spawn notes interface */
+
+ 'notes' : function() {
+ var obj = this;
+ JSAN.use('util.window'); var win = new util.window();
+ win.open(
+ urls.XUL_SERIAL_NOTES,
+ //+ '?copy_id=' + window.escape(obj.sitems[0].id()),
+ 'Item Notes','chrome,resizable,modal',
+ { 'object_id' : obj.sitems[0].id(), 'function_type' : 'SIN', 'object_type' : 'item', 'constructor' : sin }
+ );
+ },
+
+ /******************************************************************************************************/
+ 'save_attributes' : serial.editor_base.editor_base_save_attributes
+
+};
+
+dump('exiting serial/sitem.js\n');
--- /dev/null
+<?xml version="1.0"?>
+<!-- Application: Evergreen Staff Client -->
+<!-- Screen: Serial Item Editor -->
+
+<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+<!-- STYLESHEETS -->
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="chrome://open_ils_staff_client/skin/global.css" type="text/css"?>
+<?xml-stylesheet href="/xul/server/skin/global.css" type="text/css"?>
+
+<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+<!-- LOCALIZATION -->
+<!DOCTYPE window PUBLIC "" ""[
+ <!--#include virtual="/opac/locale/${locale}/lang.dtd"-->
+]>
+
+<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+<!-- OVERLAYS -->
+<?xul-overlay href="/xul/server/OpenILS/util_overlay.xul"?>
+
+<window id="serial_item_editor_win"
+ onload="try { my_init(); font_helper(); persist_helper(); } catch(E) { alert(E); }"
+ width="800" height="390" oils_persist="width height"
+ title="Item Editor"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+ <!-- BEHAVIOR -->
+ <script type="text/javascript">
+ var myPackageDir = 'open_ils_staff_client'; var IAMXUL = true; var g = {};
+ </script>
+ <scripts id="openils_util_scripts"/>
+
+ <script type="text/javascript" src="/xul/server/main/JSAN.js"/>
+ <script type="text/javascript" src="sitem_editor.js"/>
+ <script>
+ <![CDATA[
+ function my_init() {
+ try {
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ if (typeof JSAN == 'undefined') {
+ throw( document.getElementById("commonStrings").getString('common.jsan.missing') );
+ }
+ JSAN.errorLevel = "die"; // none, warn, or die
+ JSAN.addRepository('/xul/server/');
+ JSAN.use('util.error'); g.error = new util.error();
+ g.error.sdump('D_TRACE','my_init() for serial/sitem_editor.xul');
+ JSAN.use('serial.sitem_editor'); g.sitem_editor = new serial.sitem_editor();
+
+ g.sitem_editor.init({"do_edit" : true, "handle_update" : true});
+
+ } catch(E) {
+ var err_msg = document.getElementById("commonStrings").getFormattedString('common.exception', ['serial/sitem_editor.xul', E]);
+ try { g.error.sdump('D_ERROR',err_msg); } catch(E) { dump(err_msg); }
+ alert(err_msg);
+ }
+ }
+
+ ]]>
+ </script>
+
+ <messagecatalog id="catStrings" src="/xul/server/locale/<!--#echo var='locale'-->/cat.properties" />
+ <messagecatalog id="serialStrings" src="/xul/server/locale/<!--#echo var='locale'-->/serial.properties" />
+
+ <vbox id="brief_display_box"/>
+
+ <groupbox flex="1" class="my_overflow">
+ <hbox flex="1" style="overflow: auto">
+ <vbox flex="1">
+ <label value="Item" style="font-weight: bold; font-size: large"/>
+ <vbox id="sitem_editor_left_pane" flex="1"/>
+ </vbox>
+ <splitter><grippy /></splitter>
+ <vbox flex="1">
+ <label value=" " style="font-weight: bold; font-size: large"/>
+ <vbox id="sitem_editor_middle_pane" flex="1"/>
+ </vbox>
+ <splitter><grippy /></splitter>
+ <vbox flex="1">
+ <button style="font-weight: bold; font-size: normal" label="Item Dates" accesskey="1" oncommand="document.getElementById('sitem_editor_right_pane').firstChild.firstChild.focus();"/>
+ <vbox id="sitem_editor_right_pane" flex="1"/>
+ </vbox>
+ </hbox>
+
+ <hbox id="nav">
+ <spacer flex="1"/>
+ <button id="sitem_notes" label="&staff.serial.sitem_editor.notes;" accesskey="&staff.serial.sitem_editor.notes.accesskey;" oncommand="g.sitem_editor.notes();"/>
+ <button id="sitem_save" label="&staff.serial.sitem_editor.modify;" hidden="true" accesskey="&staff.serial.sitem_editor.modify.accesskey;" oncommand="g.sitem_editor.save();"/>
+ <button id="sitem_cancel" label="&staff.cat.copy_editor.cancel.label;" accesskey="&staff.cat.copy_editor.cancel.accesskey;" oncommand="window.close();"/>
+ </hbox>
+
+ <spacer/>
+ </groupbox>
+
+</window>
+
--- /dev/null
+dump('entering serial/ssub_editor.js\n');
+// vim:noet:sw=4:ts=4:
+
+JSAN.use('serial.editor_base');
+
+if (typeof serial == 'undefined') serial = {};
+serial.ssub_editor = function (params) {
+ try {
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ JSAN.use('util.error'); this.error = new util.error();
+ } catch(E) {
+ dump('serial/ssub_editor: ' + E + '\n');
+ }
+
+ /* This keeps track of what fields have been edited for styling purposes */
+ this.changed = {};
+
+ /* This holds the original values for prepopulating the field editors */
+ this.editor_values = {};
+
+};
+
+serial.ssub_editor.prototype = {
+ // we could do this with non-standard '__proto__' property instead
+ 'editor_base_init' : serial.editor_base.editor_base_init,
+ 'editor_base_apply' : serial.editor_base.editor_base_apply,
+ 'editor_base_save' : serial.editor_base.editor_base_save,
+
+ 'fm_type' : 'ssub',
+ 'fm_type_plural' : 'ssubs',
+ 'can_have_notes' : true,
+
+ 'init' : function (params) {
+ var obj = this;
+
+ params.retrieve_function = 'FM_SSUB_FLESHED_BATCH_RETRIEVE.authoritative';
+
+ obj.editor_base_init(params);
+
+ /* Do it */
+ obj.summarize( obj.ssubs );
+ obj.render();
+ },
+
+ /******************************************************************************************************/
+ /* Restore backup copies */
+
+ 'reset' : serial.editor_base.editor_base_reset,
+
+ /******************************************************************************************************/
+ /* Apply a value to a specific field on all the copies being edited */
+
+ 'apply' : function(field, value) {
+ var obj = this;
+
+ if (field == 'start_date' || field == 'end_date') {
+ if (value == '') { value = null; }
+ }
+
+ obj.editor_base_apply(field, value);
+ },
+
+
+ /******************************************************************************************************/
+ /* These need data from the middle layer to render */
+
+ /*
+ function init_panes0() {
+ obj.special_exception = {};
+ obj.special_exception[$('catStrings').getString('staff.cat.copy_editor.field.owning_library.label')] = function(label,value) {
+ JSAN.use('util.widgets');
+ if (value>0) { // an existing call number
+ obj.network.simple_request(
+ 'FM_ACN_RETRIEVE.authoritative',
+ [ value ],
+ function(req) {
+ var cn = '??? id = ' + value;
+ try {
+ cn = req.getResultObject();
+ } catch(E) {
+ obj.error.sdump('D_ERROR','callnumber retrieve: ' + E);
+ }
+ util.widgets.set_text(label,obj.data.hash.aou[ cn.owning_lib() ].shortname() + ' : ' + cn.label());
+ }
+ );
+ } else { // a yet to be created call number
+ if (obj.callnumbers) {
+ util.widgets.set_text(label,obj.data.hash.aou[ obj.callnumbers[value].owning_lib ].shortname() + ' : ' + obj.callnumbers[value].label);
+ }
+ }
+ };
+ },
+ */
+
+ /******************************************************************************************************/
+ /* These get show in the left panel */
+
+ 'init_panes' : function () {
+ var obj = this;
+ obj.panes_and_field_names = {
+
+ 'left_pane' :
+ [
+ [
+ 'ID',
+ {
+ render: '"ID : " + fm.id();',
+ //input: 'c = function(v){ obj.apply("distribution",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+
+ }
+ ],
+ [
+ 'Owning Lib',
+ {
+ render: 'typeof fm.owning_lib() == "object" ? fm.owning_lib().shortname() : obj.data.hash.aou[ fm.owning_lib() ].shortname()',
+ input: 'c = function(v){ obj.apply("owning_lib",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( util.functional.map_list( obj.data.list.aou, function(myobj) { var sname = myobj.shortname(); for (i = sname.length; i < 20; i++) sname += " "; return [ myobj.name() ? sname + " " + myobj.name() : myobj.shortname(), myobj.id(), ( ! get_bool( obj.data.hash.aout[ myobj.ou_type() ].can_have_vols() ) ), ( obj.data.hash.aout[ myobj.ou_type() ].depth() * 2), ]; }), obj.data.list.au[0].ws_ou()); x.setAttribute("value",obj.editor_values.owning_lib); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+ value_key: 'owning_lib',
+ dropdown_key: 'fm.owning_lib() == null ? null : typeof fm.owning_lib() == "object" ? fm.owning_lib().id() : fm.owning_lib()',
+ }
+ ],
+ ],
+
+ 'right_pane' :
+ [
+ [
+ 'Start Date',
+ {
+ render: 'fm.start_date() == null ? "" : util.date.formatted_date( fm.start_date(), "%F");',
+ input: 'c = function(v){ obj.apply("start_date",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.setAttribute("value",obj.editor_values.start_date); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+ value_key: 'start_date'
+ }
+ ],
+ [
+ 'End Date',
+ {
+ render: 'fm.end_date() == null ? "" : util.date.formatted_date( fm.end_date(), "%F");',
+ input: 'c = function(v){ obj.apply("end_date",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.setAttribute("value",obj.editor_values.end_date); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+ value_key: 'end_date'
+ }
+ ],
+ [
+ 'Date Offset',
+ {
+ render: 'fm.expected_date_offset() == null ? "" : fm.expected_date_offset();',
+ input: 'c = function(v){ obj.apply("expected_date_offset",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.setAttribute("value",obj.editor_values.expected_date_offset); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+ value_key: 'expected_date_offset'
+ }
+ ],
+ ],
+
+ };
+ },
+
+ /******************************************************************************************************/
+ /* This loops through all our fieldnames and all the copies, tallying up counts for the different values */
+
+ 'summarize' : serial.editor_base.editor_base_summarize,
+
+ /******************************************************************************************************/
+ /* Display the summarized data and inputs for editing */
+
+ 'render' : serial.editor_base.editor_base_render,
+
+ /******************************************************************************************************/
+ /* This actually draws the change button and input widget for a given field */
+ 'render_input' : serial.editor_base.editor_base_render_input,
+
+ /******************************************************************************************************/
+ /* save the subscriptions */
+
+ 'save' : function() {
+ var obj = this;
+ obj.editor_base_save('open-ils.serial.subscription.fleshed.batch.update');
+ },
+
+ /******************************************************************************************************/
+ /* spawn notes interface */
+
+ 'notes' : function() {
+ var obj = this;
+ JSAN.use('util.window'); var win = new util.window();
+ win.open(
+ urls.XUL_SERIAL_NOTES,
+ 'Subscription Notes','chrome,resizable,modal',
+ { 'object_id' : obj.ssubs[0].id(), 'function_type' : 'SSUBN', 'object_type' : 'subscription', 'constructor' : ssubn }
+ );
+ },
+
+ /******************************************************************************************************/
+ 'save_attributes' : serial.editor_base.editor_base_save_attributes
+};
+
+dump('exiting serial/ssub_editor.js\n');
--- /dev/null
+<?xml version="1.0"?>
+<!-- Application: Evergreen Staff Client -->
+<!-- Screen: Subscription Editor Overlay -->
+
+<!-- LOCALIZATION -->
+<!DOCTYPE overlay PUBLIC "" ""[
+ <!--#include virtual="/opac/locale/${locale}/lang.dtd"-->
+]>
+
+<overlay id="serial_ssub_editor_panel_overlay"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <vbox flex="1" id="serial_ssub_editor_panel" class="my_overflow">
+ <vbox id="brief_display_box"/>
+
+ <hbox flex="1" style="overflow: auto">
+ <vbox flex="1">
+ <label value="Subscription" style="font-weight: bold; font-size: large"/>
+ <vbox id="left_pane" flex="1"/>
+ </vbox>
+ <splitter><grippy /></splitter>
+ <vbox flex="1">
+ <label value=" " style="font-weight: bold; font-size: large"/>
+ <vbox id="right_pane" flex="1"/>
+ </vbox>
+ </hbox>
+
+ <hbox id="nav">
+ <spacer flex="1"/>
+ <button id="ssub_notes" label="&staff.serial.ssub_editor.notes;" accesskey="&staff.serial.ssub_editor.notes.accesskey;" oncommand="g.manage_subs.ssub_editor.notes()" />
+ <button id="ssub_save" label="&staff.serial.ssub_editor.modify;" hidden="true" accesskey="&staff.serial.ssub_editor.modify.accesskey;" oncommand="g.manage_subs.ssub_editor.save()" />
+ <!--<button id="cancel" label="&staff.cat.copy_editor.cancel.label;" accesskey="&staff.cat.copy_editor.cancel.accesskey;" oncommand="window.close();"/>-->
+ </hbox>
+
+ <spacer/>
+ </vbox>
+
+</overlay>
+