From: Jason Stephenson Date: Fri, 2 Sep 2022 15:31:57 +0000 (-0400) Subject: CMARS Custom Patches for MOBIUS X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=33d2330463b7290fc696e8a78697174c363f2447;p=working%2FEvergreen.git CMARS Custom Patches for MOBIUS Using override directories as requested. No "configuration" files included. Signed-off-by: Jason Stephenson --- diff --git a/Open-ILS/src/eg2/src/app/share/catalog/search-context.ts b/Open-ILS/src/eg2/src/app/share/catalog/search-context.ts index 7ee7ab1271..53d6763199 100644 --- a/Open-ILS/src/eg2/src/app/share/catalog/search-context.ts +++ b/Open-ILS/src/eg2/src/app/share/catalog/search-context.ts @@ -417,7 +417,7 @@ export class CatalogSearchContext { */ reset(): void { this.pager.offset = 0; - this.sort = ''; + this.sort = 'poprel'; this.showBasket = false; this.result = new CatalogSearchResults(); this.resultIds = []; diff --git a/Open-ILS/src/eg2/src/app/staff/catalog/search-form.component.html b/Open-ILS/src/eg2/src/app/staff/catalog/search-form.component.html index c63c5e8e63..3a4b44ca75 100644 --- a/Open-ILS/src/eg2/src/app/staff/catalog/search-form.component.html +++ b/Open-ILS/src/eg2/src/app/staff/catalog/search-form.component.html @@ -53,7 +53,9 @@ + + + + + - + {{hold.title}} diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/AppUtils.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/AppUtils.pm index 120b568b9c..fdc9763796 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/AppUtils.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/AppUtils.pm @@ -2437,6 +2437,79 @@ sub verify_migrated_user_password { $e, $user_id, md5_hex($salt . $md5_pass), $pw_type); } +# Calculate a barcode check digit using the Luhn algorithm: +# https://en.wikipedia.org/wiki/Luhn_algorithm +# Takes a string of digits and returns the checkdigit. +# -1 is returned if the string contains any characters other than digits. +sub calculate_luhn_checkdigit { + my ($class, $input) = @_; + return -1 unless ($input =~ /^\d+$/); + my @bc = reverse(split(//, $input)); + my $mult = 2; + my $sum = 0; + for (my $i = 0; $i < @bc; $i++) { + my $v = $bc[$i] * $mult; + $v -= 9 if ($v > 9); + $sum += $v; + $mult = ($mult == 2) ? 1 : 2; + } + return ($sum % 10) ? 10 - ($sum % 10) : 0; +} + +# Generate a barcode using a combination of: +# $prefix : A prefix sequence for the barcode. +# $length : The total lenght for the generated barcode, including +# length of the prefix and checkdigit (if any). +# $checkdigit: A boolean, whether or not to calculate a check digit. +# $sequence: A database sequence to use as a source of the main digit +# sequence for the barcode. +# $e : An optional CStoreEditor to use for queries. If not provided, +# a new one will be created and used. +# +# Returns the new barcode or undef on failure. +sub generate_barcode { + my ($class, $prefix, $length, $checkdigit, $sequence, $e) = @_; + $e = OpenILS::Utils::CStoreEditor->new() unless($e); + # Don't do checkdigit if prefix is not all numbers. + if ($prefix !~ /^\d+$/) { + $checkdigit = 0; + } + $length = $length - length($prefix); + $length -= 1 if ($checkdigit); + if ($length > 0) { + my $barcode; + do { + my $r = $e->json_query( + {from => [ + 'actor.generate_barcode', + $prefix, + $length, + $sequence + ]}); + if ($r && $r->[0] && $r->[0]->{'actor.generate_barcode'}) { + $barcode = $r->[0]->{'actor.generate_barcode'}; + if ($checkdigit) { + $barcode .= $class->calculate_luhn_checkdigit($barcode); + } + # Check for duplication. + my $x = $e->json_query( + { + select => ['id'], + from => 'ac', + where => { + barcode => $barcode + } + } + ); + undef($barcode) if ($x && $x->[0]); + } else { + return undef; + } + } until ($barcode); + return $barcode; + } + return undef; +} # generate a MARC XML document from a MARC XML string sub marc_xml_to_doc { diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Publisher/action.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Publisher/action.pm index 2b6a6b4a22..e8b8efb1c7 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Publisher/action.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Publisher/action.pm @@ -577,11 +577,34 @@ sub nearest_hold { ON ( au.id = ausp.usr AND ( ausp.stop_date IS NULL OR ausp.stop_date > NOW() ) ) LEFT JOIN config.standing_penalty csp ON ( csp.id = ausp.standing_penalty AND csp.block_list LIKE '%CAPTURE%' ) + LEFT JOIN LATERAL ( + SELECT OILS_JSON_TO_TEXT(value) AS age + FROM actor.org_unit_ancestor_setting('circ.pickup_hold_stalling.soft', h.pickup_lib) + ) AS pickup_stall ON TRUE $addl_join WHERE hm.target_copy = ? - /* not protected, or protection is expired or we're in range */ + + /* not protected, or protection is expired or we're in range */ AND (cahp.id IS NULL OR (AGE(NOW(),acp.active_date) >= cahp.age OR cahp.prox >= hm.proximity)) - AND (AGE(NOW(),h.request_time) >= CAST(? AS INTERVAL) OR hm.proximity = 0 OR p.prox = 0) + + /* the complicated hold stalling logic */ + AND CASE WHEN pickup_stall.age IS NOT NULL AND h.request_time + pickup_stall.age::INTERVAL > NOW() + THEN -- pickup lib oriented stalling is configured for this hold's pickup lib, and it's "too young" + CASE WHEN p.prox = 0 + THEN TRUE -- Cheap test: allow it when scanning at pickup lib + ELSE action.hold_copy_calculated_proximity( -- have to call this because we don't know if pprox will be included + h.id, + acp.id, + p.from_org -- equals scan lib, see first JOIN above + ) <= 0 -- else more expensive test for scan-lib calc prox + END + ELSE ( h.request_time + CAST(? AS INTERVAL) < NOW() + OR hm.proximity <= 0 + OR p.prox = 0 + ) -- not "too young" OR copy-owner/pickup prox OR scan-lib/pickup prox + END + + /* simple, quick tests */ AND h.capture_time IS NULL AND h.cancel_time IS NULL AND (h.expire_time IS NULL OR h.expire_time > NOW()) diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Utils/HoldTargeter.pm b/Open-ILS/src/perlmods/lib/OpenILS/Utils/HoldTargeter.pm index 56e9c841a8..31b8852cb0 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Utils/HoldTargeter.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Utils/HoldTargeter.pm @@ -298,6 +298,34 @@ sub hold { return $self->{hold}; } +sub inside_hard_stall_interval { + my ($self) = @_; + if (defined $self->{inside_hard_stall_interval}) { + $self->log_hold('already looked up hard stalling state: '.$self->{inside_hard_stall_interval}); + return $self->{inside_hard_stall_interval}; + } + + my $hard_stall_interval = + $self->parent->get_ou_setting( + $self->hold->pickup_lib, 'circ.pickup_hold_stalling.hard', $self->editor) || '0 seconds'; + + $self->log_hold('hard stalling interval '.$hard_stall_interval); + + my $hold_request_time = $dt_parser->parse_datetime(clean_ISO8601($self->hold->request_time)); + my $hard_stall_time = $hold_request_time->clone->add( + seconds => OpenILS::Utils::DateTime->interval_to_seconds($hard_stall_interval) + ); + + if (DateTime->compare($hard_stall_time, DateTime->now(time_zone => 'local')) > 0) { + $self->{inside_hard_stall_interval} = 1 + } else { + $self->{inside_hard_stall_interval} = 0 + } + + $self->log_hold('hard stalling state: '.$self->{inside_hard_stall_interval}); + return $self->{inside_hard_stall_interval}; +} + # Debug message sub message { my ($self, $message) = @_; @@ -355,6 +383,12 @@ sub recall_copies { return $self->{recall_copies}; } +sub in_use_copies { + my ($self, $in_use_copies) = @_; + $self->{in_use_copies} = $in_use_copies if $in_use_copies; + return $self->{in_use_copies}; +} + # Maps copy ID's to their hold proximity sub copy_prox_map { my ($self, $copy_prox_map) = @_; @@ -720,6 +754,7 @@ sub compile_weighted_proximity_map { my %prox_map; for my $copy_hash (@{$self->copies}) { my $prox = $copy_prox_map{$copy_hash->{id}}; + $copy_hash->{proximity} = $prox; $prox_map{$prox} ||= []; my $weight = $self->parent->get_ou_setting( @@ -730,6 +765,20 @@ sub compile_weighted_proximity_map { push(@{$prox_map{$prox}}, $copy_hash) foreach (1 .. $weight); } + # We need to grab the proximity for copies targeted by other holds + # that belong to this pickup lib for hard-stalling tests later. We'll + # just grab them all in case it's useful later. + for my $copy_hash (@{$self->in_use_copies}) { + my $prox = $copy_prox_map{$copy_hash->{id}}; + $copy_hash->{proximity} = $prox; + } + + # We also need the proximity for the previous target. + if ($self->{valid_previous_copy}) { + my $prox = $copy_prox_map{$self->{valid_previous_copy}->{id}}; + $self->{valid_previous_copy}->{proximity} = $prox; + } + return $self->{weighted_prox_map} = \%prox_map; } @@ -806,6 +855,10 @@ sub filter_copies_by_status { sub filter_copies_in_use { my $self = shift; + # Copies that are targeted, but could contribute to pickup lib + # hard (foreign) stalling. These are Available-status copies. + $self->in_use_copies([grep {$_->{current_copy}} @{$self->copies}]); + # A copy with a 'current_copy' value means it's in use by another hold. $self->copies([ grep {!$_->{current_copy}} @{$self->copies} @@ -920,7 +973,7 @@ sub attempt_force_recall_target { sub attempt_to_find_copy { my $self = shift; - return undef unless @{$self->copies}; + $self->log_hold("attempting to find a copy normally"); my $max_loops = $self->parent->get_ou_setting( $self->hold->pickup_lib, @@ -1102,13 +1155,40 @@ sub find_nearest_copy { my $hold = $self->hold; my %seen; + # See if there are in-use (targeted) copies "here". + my $have_local_copies = 0; + if ($self->inside_hard_stall_interval) { # But only if we're inside the hard age. + if (grep { $_->{proximity} <= 0 } @{$self->in_use_copies}) { + $have_local_copies = 1; + } + $self->log_hold("inside hard stall interval and does ". + ($have_local_copies ? "" : "not "). "have in-use local copies"); + } + # Pick a copy at random from each tier of the proximity map, # starting at the lowest proximity and working up, until a # copy is found that is suitable for targeting. + my $no_copies = 1; for my $prox (sort {$a <=> $b} keys %prox_map) { my @copies = @{$prox_map{$prox}}; next unless @copies; + $no_copies = 0; + $have_local_copies = 1 if ($prox <= 0); + + $self->log_hold("inside hard stall interval and does ". + ($have_local_copies ? "" : "not "). "have testable local copies") + if ($self->inside_hard_stall_interval && $prox > 0); + + if ($have_local_copies and $self->inside_hard_stall_interval) { + # Unset valid_previous_copy if it's not local and we have local copies now + $self->{valid_previous_copy} = undef if ( + $self->{valid_previous_copy} + and $self->{valid_previous_copy}->{proximity} > 0 + ); + last if ($prox > 0); # No point in looking further "out". + } + my $rand = int(rand(scalar(@copies))); while (my ($c) = splice(@copies, $rand, 1)) { @@ -1122,6 +1202,14 @@ sub find_nearest_copy { } } + if ($no_copies and $have_local_copies and $self->inside_hard_stall_interval) { + # Unset valid_previous_copy if it's not local and we have local copies now + $self->{valid_previous_copy} = undef if ( + $self->{valid_previous_copy} + and $self->{valid_previous_copy}->{proximity} > 0 + ); + } + return undef; } diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Utils/RemoteAccount.pm b/Open-ILS/src/perlmods/lib/OpenILS/Utils/RemoteAccount.pm index b4a8f1ecf1..bf11a1aa3c 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Utils/RemoteAccount.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Utils/RemoteAccount.pm @@ -542,7 +542,7 @@ sub _slash_path { sub _ftp { my $self = shift; - my %options = (); + my %options = (Timeout => 15); $self->{ftp} and return $self->{ftp}; # caching foreach (qw/debug port/) { $options{ucfirst($_)} = $self->{$_} if $self->{$_}; diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm index 5763cb8e03..011132272c 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm @@ -29,6 +29,7 @@ use OpenILS::WWW::EGCatLoader::Course; use OpenILS::WWW::EGCatLoader::Container; use OpenILS::WWW::EGCatLoader::SMS; use OpenILS::WWW::EGCatLoader::Register; +use OpenILS::WWW::EGCatLoader::Ecard; my $U = 'OpenILS::Application::AppUtils'; @@ -182,6 +183,10 @@ sub load { $self->load_simple("myopac") if $path =~ m:opac/myopac:; # A default page for myopac parts + return $self->load_ecard_form($path) if $path =~ m|opac/ecard/form|; + return $self->load_ecard_submit if $path =~ m|opac/ecard/submit|; + return $self->load_ecard_verify if $path =~ m|opac/ecard/verify|; + if($path =~ m|opac/login|) { return $self->load_login unless $self->editor->requestor; # already logged in? diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Register.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Register.pm index 4949d10073..7732c1ade3 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Register.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Register.pm @@ -38,6 +38,14 @@ sub load_patron_reg { my $val = $cgi->param($_); $self->inspect_register_value($_, $val); s/^stgu\.//g; + # Upcase certain fields per CW MARS + my @upcase_fields = ('first_given_name', 'second_given_name', 'family_name', + 'pref_first_given_name', 'pref_second_given_name', + 'pref_family_name'); + my $f = $_; + if (grep {$f eq $_} @upcase_fields) { + $val = uc($val); + } $user->$_($val); } @@ -56,7 +64,7 @@ sub load_patron_reg { my $val = $cgi->param($_); $self->inspect_register_value($_, $val); s/^stgma\.//g; - $addr->$_($val); + $addr->$_(uc($val)); # Uppercase per CW MARS $has_addr = 1; } diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/SuperCat.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/SuperCat.pm index 2728f36460..c002e61f2d 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/SuperCat.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/SuperCat.pm @@ -2184,7 +2184,7 @@ sub sru_search { } } - $quote_it = 0 if ( $base eq 'all' ); + $quote_it = 0 if ( $base eq 'all' || ( $base eq '=' && grep {$qualifier eq $_} qw(eg.keyword eg.title eg.author) ) ); $term = maybeQuote($term) if $quote_it; } else { diff --git a/Open-ILS/src/reporter/clark-kent.pl b/Open-ILS/src/reporter/clark-kent.pl index 9db6778f42..f4ec1c5799 100755 --- a/Open-ILS/src/reporter/clark-kent.pl +++ b/Open-ILS/src/reporter/clark-kent.pl @@ -28,6 +28,12 @@ use Email::Send; use open ':utf8'; +# Put this at the top because it was not found when at the bottom. +sub die_error { + my $msg = shift; + $logger->error('Reporter died with error: ' . $msg); + die $msg; +} my ($config, $sleep_interval, $lockfile, $daemon) = ('SYSCONFDIR/opensrf_core.xml', 10, '/tmp/reporter-LOCK'); @@ -128,7 +134,7 @@ my ($dbh,$running,$sth,@reports,$run, $current_time); if ($daemon) { daemonize("Clark Kent, waiting for trouble"); - open(F, ">$lockfile") or die "Cannot write lockfile '$lockfile'"; + open(F, ">$lockfile") or die_error "Cannot write lockfile '$lockfile'"; print F $$; close F; } @@ -143,7 +149,7 @@ $dbh = DBI->connect( { AutoCommit => 1, pg_expand_array => 0, pg_enable_utf8 => 1, - RaiseError => 1 + HandleError => \&die_error } ); @@ -333,7 +339,7 @@ for my $r ( @reports ) { $r->{chart_line}, )) { # Ignore duplicate key errors on reporter.schedule (err 7 is a fatal query error). Just look for the constraint name in the message to avoid l10n issues. - warn($state_dbh->errstr()) unless $state_dbh->err() == 7 && $state_dbh->errstr() =~ m/rpt_sched_recurrence_once_idx/; + $logger->warn($state_dbh->errstr()) unless $state_dbh->err() == 7 && $state_dbh->errstr() =~ m/rpt_sched_recurrence_once_idx/; } $state_dbh->{PrintError} = $prevP; } @@ -701,7 +707,7 @@ sub draw_pie { print IMG $pic->gd->$format; } otherwise { my $e = shift; - warn "Couldn't draw $file.pie.$vcol.$sub_graph.$format : $e"; + $logger->warn("Couldn't draw $file.pie.$vcol.$sub_graph.$format : $e"); $forgetit = 1; }; @@ -824,7 +830,7 @@ sub draw_bars { print IMG $pic->gd->$format; } otherwise { my $e = shift; - warn "Couldn't draw $file.bar.$format : $e"; + $logger->warn("Couldn't draw $file.bar.$format : $e"); }; close IMG; @@ -930,7 +936,7 @@ sub draw_lines { print IMG $pic->gd->$format; } otherwise { my $e = shift; - warn "Couldn't draw $file.line.$format : $e"; + $logger->warn("Couldn't draw $file.line.$format : $e"); }; close IMG; diff --git a/Open-ILS/src/support-scripts/marc_export.in b/Open-ILS/src/support-scripts/marc_export.in index 843ddff1ca..9e57c0b7a1 100755 --- a/Open-ILS/src/support-scripts/marc_export.in +++ b/Open-ILS/src/support-scripts/marc_export.in @@ -99,7 +99,8 @@ sub new { 'since=s', 'store=s', 'uris', - 'debug'); + 'debug', + 'pipe'); if ($opts{help}) { print <<"HELP"; @@ -129,6 +130,8 @@ Usage: $0 [options] --store Use the given storage backend to connect to the database. Choices are (reporter, cstore, storage) [reporter] --since Export records modified since a certain date and time. + --pipe Force record ids to be read from list on standard input, + despite other options to the contrary Additional options for type = 'BIBLIO': --items or -i Include items (holdings) in the output @@ -181,6 +184,10 @@ HELP die('Incompatible arguments: you cannot combine a request for all ' . 'records with a request for records added or changed since a certain date'); } + if ($opts{all} && $opts{pipe}) { + die('Incompatible arguments: you cannot combine a request for all ' . + 'records with the option to read record ids via standard input'); + } $opts{type} = lc($opts{type}); if (none {$_ eq $opts{type}} (TYPES)) { die "Please select a supported type. ". @@ -219,12 +226,11 @@ HELP join('|',(STORES)). "]\n"; } else { my $app; - if ($opts{store} eq 'reporter') { - $app = 'open-ils.reporter-store'; - } else { - $app = 'open-ils.' . $opts{store}; - } - if ($app eq 'open-ils.storage') { + $app = 'open-ils.' . $opts{store}; + if ($app eq 'open-ils.reporter') { + $self->{dbsettings} = $sclient->config_value( + reporter => setup => 'database'); + } elsif ($app eq 'open-ils.storage') { $self->{dbsettings} = $sclient->config_value( apps => $app => app_settings => databases => 'database'); } else { @@ -253,10 +259,13 @@ sub need_ids { my $self = shift; my $rv = 1; - $rv = 0 if ($self->{options}->{all}); $rv = 0 if ($self->{options}->{since}); $rv = 0 if ($self->{options}->{library}); $rv = 0 if ($self->{options}->{descendants}); + # --pipe trumps the above. + $rv = 1 if ($self->{options}->{pipe}); + # --all trumps --pipe, but we should throw an error before we get here. + $rv = 0 if ($self->{options}->{all}); return $rv; } diff --git a/Open-ILS/src/support-scripts/marc_stream_importer.pl.in b/Open-ILS/src/support-scripts/marc_stream_importer.pl.in index 4f2a1df80e..5a42f489e7 100755 --- a/Open-ILS/src/support-scripts/marc_stream_importer.pl.in +++ b/Open-ILS/src/support-scripts/marc_stream_importer.pl.in @@ -75,10 +75,12 @@ my $bib_import_no_match; my $bib_auto_overlay_exact; my $bib_auto_overlay_1match; my $bib_auto_overlay_best_match; +my $bib_match_quality_ratio; my $auth_import_no_match; my $auth_auto_overlay_exact; my $auth_auto_overlay_1match; my $auth_auto_overlay_best_match; +my $auth_match_quality_ratio; # deprecated options; these map to their bib_* equivalents my $import_no_match; @@ -118,10 +120,12 @@ GetOptions( 'bib-auto-overlay-exact' => \$bib_auto_overlay_exact, 'bib-auto-overlay-1match' => \$bib_auto_overlay_1match, 'bib-auto-overlay-best-match' => \$bib_auto_overlay_best_match, + 'bib-match-quality-ratio=f' => \$bib_match_quality_ratio, 'auth-import-no-match' => \$auth_import_no_match, 'auth-auto-overlay-exact' => \$auth_auto_overlay_exact, 'auth-auto-overlay-1match' => \$auth_auto_overlay_1match, 'auth-auto-overlay-best-match' => \$auth_auto_overlay_best_match, + 'auth-match-quality-ratio=f' => \$auth_match_quality_ratio, 'help' => \$help, 'net-server-config=s' => \$net_server_conf, 'port=i' => \$port @@ -189,10 +193,12 @@ sub usage { --bib-auto-overlay-exact --bib-auto-overlay-1match --bib-auto-overlay-best-match + --bib-match-quality-ratio --auth-import-no-match --auth-auto-overlay-exact --auth-auto-overlay-1match --auth-auto-overlay-best-match + --auth-match-quality-ratio Bib and auth import options which map directly to Vandelay import options. @@ -289,11 +295,13 @@ sub compile_vandelay_ops { $vl_ops->{auto_overlay_exact} = $auth_auto_overlay_exact; $vl_ops->{auto_overlay_1match} = $auth_auto_overlay_1match; $vl_ops->{auto_overlay_best_match} = $auth_auto_overlay_best_match; + $vl_ops->{match_quality_ratio} = $auth_match_quality_ratio; } else { $vl_ops->{import_no_match} = $bib_import_no_match; $vl_ops->{auto_overlay_exact} = $bib_auto_overlay_exact; $vl_ops->{auto_overlay_1match} = $bib_auto_overlay_1match; $vl_ops->{auto_overlay_best_match} = $bib_auto_overlay_best_match; + $vl_ops->{match_quality_ratio} = $bib_match_quality_ratio; } # Default to exact match only if not other strategy is selected. @@ -443,7 +451,8 @@ sub process_request { set_tempdir(); # copy data to a temporary file so vandelay can scoop it up - my ($handle, $tempfile) = tempfile("$0_XXXX", DIR => $tempdir) + my $base = fileparse($0, qw(.pl)); + my ($handle, $tempfile) = tempfile("${base}_XXXX", DIR => $tempdir) or die "Cannot create tempfile in $tempdir : $!"; print $handle $data or die "Error writing to tempfile $tempfile : $!\n"; diff --git a/Open-ILS/src/templates-bootstrap_cons/opac/css/style.css.tt2 b/Open-ILS/src/templates-bootstrap_cons/opac/css/style.css.tt2 new file mode 100644 index 0000000000..97abe4e9db --- /dev/null +++ b/Open-ILS/src/templates-bootstrap_cons/opac/css/style.css.tt2 @@ -0,0 +1,4048 @@ +[%- + PROCESS "opac/parts/css/colors.tt2"; + PROCESS "opac/parts/css/fonts.tt2"; + rtl = ctx.get_i18n_l(ctx.eg_locale).rtl; +%] + +.adv_filters{ + + -moz-column-count: 4; + -moz-column-gap: 20px; + -webkit-column-count: 4; + -webkit-column-gap: 20px; + column-count: 4; + column-gap: 20px; + list-style: none; +} + +.top-divide{ + border-top: 1px solid rgba(0,0,0,.1); +} + +/* +Mini Table Styling +*/ +@media +only screen and (max-width: 650px) { + .miniTable{ + width: 100% !important; + } + + /* Force table to not be like tables anymore */ + .miniTable table, .miniTable thead, .miniTable tbody, .miniTable th, .miniTable td, .miniTable tr + { + display: block; + } + + .miniTable th{ + display:none; + } + + /* Hide table headers (but not display: none;, for accessibility) */ + .miniTable thead tr{ + position: absolute; + top: -9999px; + left: -9999px; + } + + .miniTable tr + { + border: 1px solid #ccc; + margin: 10px 0px; + } + + + .miniTable td + { + border: none; + border-bottom: 1px solid #eee; + position: relative; + padding-left: 50%; + min-height:45px; + text-align: right; + } + + .miniTable td:before + { + left: 6px; + width: 45%; + padding-right: 10px; + white-space: nowrap; + position: absolute; + } + .copyTable tr:nth-of-type(1):before { content: "Copy #1"; display: block; text-align:center; } + .copyTable tr:nth-of-type(2):before { content: "Copy #2"; display: block; text-align:center;} + .copyTable tr:nth-of-type(3):before { content: "Copy #3"; display: block; text-align:center;} + .copyTable tr:nth-of-type(4):before { content: "Copy #4"; display: block; text-align:center;} + .copyTable tr:nth-of-type(5):before { content: "Copy #5"; display: block; text-align:center;} + .copyTable tr:nth-of-type(6):before { content: "Copy #6"; display: block; text-align:center;} + .copyTable tr:nth-of-type(7):before { content: "Copy #7"; display: block; text-align:center;} + .copyTable tr:nth-of-type(8):before { content: "Copy #8"; display: block; text-align:center;} + .copyTable tr:nth-of-type(9):before { content: "Copy #9"; display: block; text-align:center;} + .copyTable tr:nth-of-type(10):before { content: "Copy #10"; display: block; text-align:center;} + + .copyTable td:nth-of-type(1):before { content: "Library"; display: flex; } + .copyTable td:nth-of-type(2):before { content: "Call Number"; display: flex; } + .copyTable td:nth-of-type(3):before { content: "Barcode"; display: flex;} + .copyTable td:nth-of-type(4):before { content: "Shelving Location"; display: flex;} + .copyTable td:nth-of-type(5):before { content: "Status"; display: flex;} + .copyTable td:nth-of-type(6):before { content: "Due Date"; display: flex;} + .copyTable td:nth-of-type(7):before { content: "[% l('Distance') %]"; display: flex;} + + .holdingsTable tr:nth-of-type(1):before { content: "Copy #1"; display: block; text-align:center; } + .holdingsTable tr:nth-of-type(2):before { content: "Copy #2"; display: block; text-align:center;} + .holdingsTable tr:nth-of-type(3):before { content: "Copy #3"; display: block; text-align:center;} + .holdingsTable tr:nth-of-type(4):before { content: "Copy #4"; display: block; text-align:center;} + .holdingsTable tr:nth-of-type(5):before { content: "Copy #5"; display: block; text-align:center;} + .holdingsTable tr:nth-of-type(6):before { content: "Copy #6"; display: block; text-align:center;} + .holdingsTable tr:nth-of-type(7):before { content: "Copy #7"; display: block; text-align:center;} + .holdingsTable tr:nth-of-type(8):before { content: "Copy #8"; display: block; text-align:center;} + .holdingsTable tr:nth-of-type(9):before { content: "Copy #9"; display: block; text-align:center;} + .holdingsTable tr:nth-of-type(10):before { content: "Copy #10"; display: block; text-align:center;} + + + .holdingsTable td:nth-of-type(1):before { content: "Library"; display: flex; } + .holdingsTable td:nth-of-type(2):before { content: "Shelving location"; display: flex; } + .holdingsTable td:nth-of-type(3):before { content: "Call number"; display: flex;} + .holdingsTable td:nth-of-type(4):before { content: "Status"; display: flex;} + + .chargesTable td:nth-of-type(1):before { content: "Select"; display: flex; } + .chargesTable td:nth-of-type(2):before { content: "Owed"; display: flex; } + .chargesTable td:nth-of-type(3):before { content: "Billing Type"; display: flex;} + .chargesTable td:nth-of-type(4):before { content: "Note"; display: flex;} + .chargesTable td:nth-of-type(5):before { content: "Date"; display: flex;} + + .chargesMainTable td:nth-of-type(1):before { content: "Select"; display: flex; } + .chargesMainTable td:nth-of-type(2):before { content: "Owed"; display: flex; } + .chargesMainTable td:nth-of-type(3):before { content: "Billing Type"; display: flex;} + .chargesMainTable td:nth-of-type(4):before { content: "Title"; display: flex;} + .chargesMainTable td:nth-of-type(5):before { content: "Checkout"; display: flex;} + .chargesMainTable td:nth-of-type(6):before { content: "Due"; display: flex;} + .chargesMainTable td:nth-of-type(7):before { content: "Returned/Renewed"; display: flex;} + + .activeHoldstable td:nth-of-type(1):before { content: "Select"; display: flex; } + .activeHoldstable td:nth-of-type(2):before { content: "Title"; display: flex; } + .activeHoldstable td:nth-of-type(3):before { content: "Author"; display: flex;} + .activeHoldstable td:nth-of-type(4):before { content: "Format"; display: flex;} + .activeHoldstable td:nth-of-type(5):before { content: "Pickup Location"; display: flex;} + .activeHoldstable td:nth-of-type(6):before { content: "Cancel If Not Filled By"; display: flex;} + .activeHoldstable td:nth-of-type(7):before { content: "Status"; display: flex;} + .activeHoldstable td:nth-of-type(8):before { content: "Notes"; display: flex;} + + .holdHistoryTable td:nth-of-type(1):before { content: "Title"; display: flex; } + .holdHistoryTable td:nth-of-type(2):before { content: "Author"; display: flex; } + .holdHistoryTable td:nth-of-type(3):before { content: "Format"; display: flex; } + .holdHistoryTable td:nth-of-type(4):before { content: "Pickup Location"; display: flex; } + .holdHistoryTable td:nth-of-type(5):before { content: "Status"; display: flex; } + + .curbsideApptTable td:nth-of-type(1):before { content: "Pickup Location"; display: flex; } + .curbsideApptTable td:nth-of-type(2):before { content: "Date"; display: flex; } + .curbsideApptTable td:nth-of-type(3):before { content: "Time"; display: flex;} + .curbsideApptTable td:nth-of-type(4):before { content: "Arrival Notes"; display: flex;} + .curbsideApptTable td:nth-of-type(5):before { content: "Action"; display: flex;} + + .paymentTable td:nth-of-type(1):before { content: "Payment Date"; display: flex; } + .paymentTable td:nth-of-type(2):before { content: "Payment For"; display: flex; } + .paymentTable td:nth-of-type(3):before { content: "Amount"; display: flex; } + .paymentTable td:nth-of-type(4):before { content: "Receipt"; display: flex; } + + .messagesTable td:nth-of-type(1):before { content: "Select"; display: flex; } + .messagesTable td:nth-of-type(2):before { content: "Date"; display: flex; } + .messagesTable td:nth-of-type(3):before { content: "Library"; display: flex; } + .messagesTable td:nth-of-type(4):before { content: "Subject"; display: flex; } + .messagesTable td:nth-of-type(5):before { content: ""; display: flex; } + + .circTable td:nth-of-type(1):before { content: "Select"; display: flex; } + .circTable td:nth-of-type(2):before { content: "Title"; display: flex; } + .circTable td:nth-of-type(3):before { content: "Author"; display: flex; } + .circTable td:nth-of-type(4):before { content: "Renewals Left"; display: flex; } + .circTable td:nth-of-type(5):before { content: "Due Date"; display: flex; } + .circTable td:nth-of-type(6):before { content: "Barcode"; display: flex; } + .circTable td:nth-of-type(7):before { content: "Call Number"; display: flex; } + + .circHistTable td:nth-of-type(1):before { content: "Select"; display: flex; } + .circHistTable td:nth-of-type(2):before { content: "Title"; display: flex; } + .circHistTable td:nth-of-type(3):before { content: "Author"; display: flex; } + .circHistTable td:nth-of-type(4):before { content: "Checkout Date"; display: flex; } + .circHistTable td:nth-of-type(5):before { content: "Due Date"; display: flex; } + .circHistTable td:nth-of-type(6):before { content: "Date Returned"; display: flex; } + .circHistTable td:nth-of-type(7):before { content: "Barcode"; display: flex; } + .circHistTable td:nth-of-type(8):before { content: "Call Number"; display: flex; } + + .bookbagTable td:nth-of-type(1):before { content: ""; display: flex; } + .bookbagTable td:nth-of-type(2):before { content: "Title"; display: flex; } + .bookbagTable td:nth-of-type(3):before { content: "Author(s)"; display: flex; } + .bookbagTable td:nth-of-type(4):before { content: "Local Call number"; display: flex; } + .bookbagTable td:nth-of-type(5):before { content: "Publication Date"; display: flex; } + .bookbagTable td:nth-of-type(6):before { content: "Format"; display: flex; } + .bookbagTable td:nth-of-type(7):before { content: "Notes"; display: flex; } + + .eholdsTable td:nth-of-type(1):before { content: "Title"; display: flex; } + .eholdsTable td:nth-of-type(2):before { content: "Author"; display: flex; } + .eholdsTable td:nth-of-type(3):before { content: "Expire Date"; display: flex; } + .eholdsTable td:nth-of-type(4):before { content: "Status"; display: flex; } + .eholdsTable td:nth-of-type(5):before { content: "Actions"; display: flex; } + + .eholdsreadyTable td:nth-of-type(1):before { content: "Title"; display: flex; } + .eholdsreadyTable td:nth-of-type(2):before { content: "Author"; display: flex; } + .eholdsreadyTable td:nth-of-type(3):before { content: "Expire Date"; display: flex; } + .eholdsreadyTable td:nth-of-type(4):before { content: "Actions"; display: flex; } + + .echeckoutTable td:nth-of-type(1):before { content: "Title"; display: flex; } + .echeckoutTable td:nth-of-type(2):before { content: "Author"; display: flex; } + .echeckoutTable td:nth-of-type(3):before { content: "Due Date"; display: flex; } + .echeckoutTable td:nth-of-type(4):before { content: "Actions"; display: flex; } + + .ecircsTable td:nth-of-type(1):before { content: "Title"; display: flex; } + .ecircsTable td:nth-of-type(2):before { content: "Author"; display: flex; } + .ecircsTable td:nth-of-type(3):before { content: "Due Date"; display: flex; } + .ecircsTable td:nth-of-type(4):before { content: "Actions"; display: flex; } + + .bucketTable td:nth-of-type(2):before { content: "Title"; display: flex; text-align:left; } + .bucketTable td:nth-of-type(3):before { content: "Author"; display: flex; text-align:left; } + .bucketTable td:nth-of-type(4):before { content: "Call Number"; display: flex; text-align:left; } + + /*Media Style Additions*/ + .fullRow{ + padding: 5px !important; + text-align: center !important; + width: 100%; + } + + .paginateText{ + display:none; + } +}/*Micro Tables End*/ + +.sumNum { + font-weight:700; +} + +.coverImage{position: relative;} +.carousel .glide__arrow{background: unset;} + +/* +Novelist Styling +*/ + +.NovGroupHeader{ + font-size: 16pt !important; + text-align: center; + font-weight: 600 !important; +} + +.NovSectionHeader{ + font-size: 16pt !important; + font-weight: 600 !important; +} + +.NovSelectImageHeadingToggle{ + font-size: 20px; + +} + +/*Novelist Styling End*/ + +/* Buttons */ + +.btn-confirm { + color: [% css_colors.button_confirm_text %]; + background-color: [% css_colors.button_confirm %]; + border-color: [% css_colors.button_confirm_border %]; +} + +.btn-confirm:hover { + color: [% css_colors.button_confirm_text %]; + background-color: [% css_colors.button_confirm_hover %]; + border-color: [% css_colors.button_confirm_border_hover %]; +} + +.btn-deny { + color: [% css_colors.button_deny_text %]; + background-color: [% css_colors.button_deny %]; + border-color: [% css_colors.button_deny_border_hover %]; +} + +.btn-deny:hover { + color: [% css_colors.button_deny_text %]; + background-color: [% css_colors.button_deny_hover %]; + border-color: [% css_colors.button_deny_border_hover %]; +} + +.btn-remove { + color: [% css_colors.button_remove_text %]; + background-color: [% css_colors.button_remove %]; + border-color: [% css_colors.button_remove_border %]; +} + +.btn-remove:hover { + color: [% css_colors.button_remove_text %]; + background-color: [% css_colors.button_remove_hover %]; + border-color: [% css_colors.button_remove_border_hover %]; +} + +.btn-opac{ + color: [% css_colors.opac_button_text %] !important; + background-color: [% css_colors.opac_button %]; + border-color: [% css_colors.opac_button_border %]; +} + +.btn-opac:hover{ + color: [% css_colors.opac_button_text %]; + background-color: [% css_colors.opac_button_hover %] !important; + border-color: [% css_colors.opac_button_border_hover %]; +} + +.btn-action{ + color: [% css_colors.action_button_text %] !important; + background-color: [% css_colors.action_button %]; + border-color: [% css_colors.action_button_border %]; +} + +.btn-action:hover{ + color: [% css_colors.action_button_text %]; + background-color: [% css_colors.action_button_hover %] !important; + border-color: [% css_colors.action_button_border_hover %]; +} +.btn-action > a{ + color: [% css_colors.action_button_text_anchors %]; +} + + +.dash-link{ + color: #fff; +} + +.dash-clear{ + color: [% css_colors.zero_count %] !important; +} + +.dash-unclear{ + color: [% css_colors.non_zero_count %] !important; +} + +.remove_filter{ + padding: .25rem .25rem !important; + font-size: .875rem; + line-height: 0.5; + border-radius: 1rem !important; +} + + +.cn_browse_item .card{ + padding: 15px; +} +#facets .card-header,#facets .card-header a { + background-color: [% css_colors.facets_back %]; + color: [% css_colors.text_invert %] +} + +.facet_template:hover{ + background-color:#e8e8e8; +} + +.danger, .validate{ + color: [% css_colors.text_alert %] !important; +} + +.danger{ + font-weight: 600; + font-style: italic; +} + +.success{ + color: green !important; +} +.dropdown-menu{ + border: 1px solid black; + box-shadow: 2px 2px #00000054; +} +.dropdown-item.active, .dropdown-item:active{ + color : #000 !important; +} +.browse-result-list{ + list-style:none; +} +.not_active_pill{ + border: 2px solid #007bff; + padding: 6px; + margin: 0 10px; +} + +.mini-control{ + max-width: 100px !important; +} + +.card-body:empty{ + display:none; +} +.min{ + min-height:500px; +} +.container{ + +} +html{ + height:100%; + min-height: 100vh; +} +body { + min-height: 100vh; + margin:0; + font-family: [% css_fonts.font_main %] !important; + font-size: [% css_fonts.size_base %]; + /* background-color: [% css_colors.primary %]; */ + [% IF rtl == 't' -%] + direction: rtl; + [%- END %] +} + +button, input { + font-family: [% css_fonts.font_main %] !important; + font-size: [% css_fonts.size_base %]; +} + +img { + border: none; +} + +#topnav_logo { + margin-left: 2em; + margin-bottom: 2em; +} + +#homesearch_main_logo { + padding-top: 60px; + margin: auto; + width: 50%; +} + +a { + color: [% css_colors.link %]; +} + +#search-wrapper h1, +#search-wrapper h2 { + text-align: center; +} + +#search-wrapper input[type=text] { + height: calc(1.8125rem + 2px); + margin:0; + padding:0; +} + +#search-wrapper select, .results_header_lbl select { + border:1px solid [% css_colors.border_standard %]; + height: calc(1.8125rem + 2px); + margin:0; + padding:0; + width: 12em; +} + +.search-check { + text-align: center; +} + +.searchbar { + font-weight: bold; + padding-top: 10px; + [% IF rtl == 't' -%] + margin-right: 1em; + [%- ELSE %] + margin-left: 1em; + [%- END %] +} + +.refine_search { + padding-bottom: 7px; + margin-left: 1em; +} + +/* +#search-wrapper select { + border:0px solid [% css_colors.border_dark %]; + filter:alpha(opacity=0); + -khtml-opacity:0; + opacity:0; + padding:0; + margin:0; + height:18px; +} +*/ + +#actions .btn-action { + text-align: left; +} + +#adv_numeric_block{ + max-width: 600px; +} + + +h2.graphic880 { + font-size: [% css_fonts.size_bigger %]; + font-weight:normal; +} + +.hide_me, .hidden { + display: none; + visibility: hidden; +} + +div.select-box-wrapper { + position:absolute; + padding-top:2px; + overflow:hidden; + [% IF rtl == 't' -%] + padding-right: 3px; + text-align:right; + [%- ELSE %] + padding-left:3px; + text-align:left; + [%- END %] +} + +#dash_wrapper { + [% IF rtl == 't' -%] + margin-right: 0.5em; + [%- ELSE %] + margin-left: 0.5em; + [%- END %] +} + +#dash_wrapper div { + background-color: [% css_colors.primary %]; + border-radius: 5px; + padding: 0em 1em; +} + +.dash_divider { + margin: 0 20px; + color: #fff; + display:inline-block; +} + + + +#dash_user { + font-weight: bold; +} + +#logout_link { + [% IF rtl == 't' -%] + right: 1px; + [%- ELSE %] + left: 1px; + [%- END %] +} + + +/* +#dash_fines { color: [% css_colors.text_badnews %]; } +the color contrast between "text_badnews" and "primary" +is too low for WCAG compliance. Use "text_attention" +for now until a better color is picked - if needed. +*/ + +#dash_wrapper #dash_user_message_button_container { + display: inline; + padding: 0; +} +#dash_wrapper #unread_message_count_floater { + position: absolute; + background-color: [% css_colors.text_alert %]; + padding-left: 0.2em; + padding-right: 0.2em; + display: inline-block; + font-size: 95%; + border-radius: 0; + z-index: 2; + margin-top: 0.2em; + [% IF rtl == 't' -%] + margin-right: -1.5em; + [%- ELSE %] + margin-left: -1.5em; + [%- END %] +} + +#header-wrap { + /* border-bottom: 5px solid [% css_colors.nav_separation %]; */ + background-color: [% css_colors.header_primary_fade %]; + background-image: -moz-linear-gradient([% css_colors.header_primary %], [% css_colors.header_primary_fade %]); + background-image: -o-linear-gradient([% css_colors.header_primary %], [% css_colors.header_primary_fade %]); + background-image: -webkit-linear-gradient([% css_colors.header_primary %], [% css_colors.header_primary_fade %]); + background-image: linear-gradient([% css_colors.header_primary %], [% css_colors.header_primary_fade %]); +} +#header { + color: [% css_colors.background %]; + margin-left: 1em; + margin-right: 1em; + font-size: [% css_fonts.size_small %]; +} + +#header a { + color: [% css_colors.background %]; +} + +#header a:hover { + color: [% css_colors.text_invert %]; + text-decoration: none; +} + +#header-links { + color: [% css_colors.text_invert %]; + font-size: [% css_fonts.size_small %]; + font-weight: bold; + position: relative; + top:4px; + +} + +#header-links a { + color: [% css_colors.text_invert %]; + display: block; + text-decoration: none; + [% IF rtl == 't' -%] + float: right; + margin-left: 22px; + [%- ELSE %] + float:left; + margin-right:22px; + [%- END %] +} + +#header-links a:hover { + color: [% css_colors.text_invert %]; + text-shadow: 0 0 0.2em [% css_colors.primary %], 0 0 0.2em [% css_colors.primary %]; + text-decoration: none; +} + +#header #header-links2 { + position:relative; + top:-8px; + color: [% css_colors.text_invert %]; + padding-bottom: 15px; +} + +#header #header-links2 a { + color: [% css_colors.text_invert %]; +} + +#header #header-links2 a:hover { + text-decoration: underline; +} + +#your-acct-login { + padding-top:2em; +} + +#gold-links { + [% IF rtl == 't' -%] + margin-right: 1em; + padding-right: 0px; + [%- ELSE %] + margin-left: 1em; + padding-left:0px; + [%- END %] +} + +#gold-links-home { + margin:auto; + [% IF rtl == 't' -%] + padding-right: 0px; + [%- ELSE %] + padding-left:0px; + [%- END %] +} + +#gold-links-holder { + height: 24px; + background-color: [% css_colors.background_invert %]; +} + +#util-bar { + [% IF rtl == 't' -%] + margin-right: 1em; + padding-right: 0px; + [%- ELSE %] + margin-left: 1em; + padding-left:0px; + [%- END %] + height:0px; +} + +.search_box_wrapper { + padding-left: 1rem; +} + +#search-wrapper { + /*border-bottom: 1px solid [% css_colors.border_standard %];*/ + padding-bottom: 5px; + background-color: [% css_colors.background %]; +} + +#search-wrapper #breadcrumb { + margin-top:0px; + font-size: [% css_fonts.size_smaller %]; + [% IF rtl == 't' -%] + float: right; + [%- ELSE %] + float:left; + [%- END %] +} + +#search-wrapper #search-within { + margin-top:10px; + position:relative; + [% IF rtl == 't' -%] + float: left; + right: -173px; + [%- ELSE %] + float:right; + left:-173px; + [%- END %] +} + +#search-wrapper #breadcrumb a { + color: [% css_colors.text %]; +} + +#search-wrapper #search_frm label { + font-size: [% css_fonts.size_smaller %]; +} + +#search-wrapper #search-box { + [% IF rtl == 't' -%] + margin-right: 1em; + padding-right: 0px; + [%- ELSE %] + margin-left: 1em; + padding-left: 0px; + [%- END %] + padding-top: 10px; + padding-bottom: 10px; +} + +#adv_search_tabs, #acct_tabs, #acct_fines_tabs, #acct_checked_tabs, #acct_holds_tabs, #acct_prefs_tabs { + [% IF rtl == 't' -%] + margin-right:2px; + [%- ELSE %] + margin-left: 2px; + [%- END %] + overflow: auto; +} + +#adv_search_tabs a, #acct_tabs a, #acct_fines_tabs a, #acct_checked_tabs a, #acct_holds_tabs a, #acct_prefs_tabs a { + [% IF rtl == 't' -%] + float: right; + margin: 10px 0px 0px 7px; + border-radius: 10px 10px 0px 0px; + [%- ELSE %] + float: left; + margin: 10px 7px 0px 0px; + border-radius: 10px 10px 0px 0px; + [%- END %] + text-align: center; + vertical-align: middle; + display: block; + padding: 10px 0px 10px 0px; + font-weight: bold; + color: [% css_colors.text_invert %]; + background-color: [% css_colors.control %]; + font-weight: bold; + text-decoration: none; +} + +#adv_search_tabs a, #acct_tabs a, #acct_fines_tabs a { + padding: 1em 1em 0.5em; +} + +#adv_search_tabs a:hover, #acct_tabs a:hover, #acct_fines_tabs a:hover, #acct_checked_tabs a:hover, #acct_holds_tabs a:hover, #acct_prefs_tabs a:hover { + background-color: [% css_colors.primary %]; + color: [% css_colors.text_invert %]; + text-decoration: none; +} + +#adv_search_filters { + position: relative; +} +#adv_search_rows { + border-bottom: none; +} +.adv_filter_block { + [% IF rtl == 't' -%] + float: right; + [%- ELSE %] + float: left; + [%- END %] + padding: 15px; + clear: both; +} +.adv_filter_block_item { + [% IF rtl == 't' -%] + float: right; + [%- ELSE %] + float: left; + [%- END %] + padding: 5px; +} + +.adv_special_block { + + padding: 5px; + margin-top: 5px; +} + + +.checkbox_col { + width: 1%; + [% IF rtl == 't' -%] + padding-right: 10px !important; + [%- ELSE %] + padding-left: 10px !important; + [%- END %] +} + +#adv_search.on, #num_search.on, #expert_search.on { + color: [% css_colors.accent_darker %]; + background-color: [% css_colors.background %]; + text-decoration: none; +} + +#adv_search_tabs a.acct-tab-on, #acct_tabs a.acct-tab-on, #acct_fines_tabs a.acct-tab-on { + color: [% css_colors.accent_darker %]; + background-color: [% css_colors.background %]; + text-decoration: none; +} + +.acct-tab-off { + background-color: [% css_colors.control %]; +} + +#acct_checked_tabs a, #acct_holds_tabs a, #acct_prefs_tabs a { + margin-top: 0px; + font-size: [% css_fonts.size_smaller %]; + color: [% css_colors.accent_darker %]; + padding: 10px 10px 10px 10px; +} + +#acct_checked_tabs div.selected a, #acct_holds_tabs div.selected a, #acct_prefs_tabs div.selected a { + background-color: [% css_colors.accent_lightest %]; + color: [% css_colors.accent_darker %]; +} + +#acct_checked_tabs, #acct_holds_tabs, #acct_prefs_tabs { + padding-bottom: 12px; + color: [% css_colors.accent_medium %]; +} + +#acct_select, #acct_prefs_select { + display: none; +} + +#mobile_acct_search_links { + background-color: [% css_colors.primary_fade %]; +} + +.rdetail_header { + [% IF rtl == 't' -%] + padding: 5px 0px 6px 7px; + margin-right: 1em; + [%- ELSE %] + padding: 5px 7px 6px 0px; + margin-left: 1em; + [%- END %] + border-bottom: 1px dotted [% css_colors.accent_light %]; +} + +.rdetail_results a { + color:[% css_colors.primary_fade %]; + font-weight:bold; + font-size: [% css_fonts.size_bigger %]; +} + +.rdetail_result_count { + color: [% css_colors.text %]; + font-weight: normal; + display: inline-block; + [% IF rtl == 't' -%] + padding-right: 1em; + [%- ELSE %] + padding-left: 1em; + [%- END %] +} + +.rdetail_result_nav { + font-weight:normal; + display: inline-block; + [% IF rtl == 't' -%] + padding-right: 1em; + [%- ELSE %] + padding-left: 1em; + [%- END %] +} + +#rdetail_details_table { + margin-top: 15px; +} + +#rdetail_image { border: none; } +#rdetail_image_cell { + padding-top: 3px; + [% IF rtl == 't' -%] + padding-left: 10px; + [%- ELSE %] + padding-right: 10px; + [%- END %] +} + +h2.rdetail_uris { + margin-top: 1em; +} +div.rdetail_uris { + padding: 0.5em 1em 0.5em 1em; + background-color: [% css_colors.accent_lighter2 %]; +} +div.rdetail_uris ul li { + position: relative; + [% IF rtl == 't' -%] + right: 1em; + [%- ELSE %] + left: 1em; + [%- END %] +} + +div.rdetail_show_copies { + margin-top: 1em; +} + +div#rdetail_actions_div { + background-color: [% css_colors.background %]; + [% IF rtl == 't' -%] + float: left; + [%- ELSE %] + float: right; + [%- END %] +} + +span#rdetail_copy_counts { + display: inline-block; + vertical-align: top; + [% IF rtl == 't' -%] + border-left: thin; + margin-left: 1em; + padding-left: 1em; + [%- ELSE %] + border-right: thin; + margin-right: 1em; + padding-right: 1em; + [%- END %] +} + +span#rdetail_hold_counts { + display: inline-block; + vertical-align: top; +} +span#rdetail_hold_counts p { + [% IF rtl == 't' -%] + padding-right: 2em; + [%- ELSE %] + padding-left: 2em; + [%- END %] +} + +#rdetail_image_div { + [% IF rtl == 't' -%] + float: right; + margin-left: 1em; + [%- ELSE %] + float: left; + margin-right: 1em; + [%- END %] +} + +.rdetail_aux_utils { + padding-bottom: 6px; + [% IF rtl == 't' -%] + border-right: 1px dotted [% css_colors.accent_light %]; + padding-right:17px; + padding-left:70px; + [%- ELSE %] + border-left:1px dotted [% css_colors.accent_light %]; + padding-left: 17px; + padding-right: 70px; + [%- END %] +} + +div.place_hold { + border-bottom: 1px dotted [% css_colors.accent_light %]; + padding-top: 10px; +} + +div.toggle_list { padding-top: 6px; } + +div.share_record { + padding-top: 6px; + border-top: 1px dotted [% css_colors.accent_light %]; +} + +div.format_icon { + [% IF rtl == 't' -%] + float: left; + margin-left: 17px; + [%- ELSE %] + float: right; + margin-right: 17px; + [%- END %] +} + +#metarecord_population { + overflow: hidden; + width: 40%; + padding-bottom: 10px; +} + +.metarecord_population_span_link { + line-height: 20px; +} + +.metarecord_population_format { + border-right: thin; + display: inline-block; + margin-right: 1em; + padding-right: 1em; + vertical-align: top; +} + +.metarecord_population_item_lang { + display: inline-block; + vertical-align: top; +} + +.metarecord_population_all { + padding-top:10px; +} + +.results_aux_utils { + display: table-cell; +} + +.result_util { + border-bottom: 1px dotted [% css_colors.accent_light %]; + padding-top: 6px; + [% IF rtl == 't' -%] + padding-right: 1em; + [%- ELSE %] + padding-left: 1em; + [%- END %] +} + +.results_reviews { + top: -5px; +} + +#rdetail_copies { + padding-top: 1.5em; +} + +#rdetails_status td { + [% IF rtl == 't' -%] + padding: 7px 13px 3px 0px; + [%- ELSE %] + padding: 7px 0px 3px 13px; + [%- END %] +} + +#rdetails_status td[headers=copy_header_library], +#rdetails_status td[headers=copy_header_shelfloc] { + white-space: normal; +} + +#rdetails_status thead th { + [% IF rtl == 't' -%] + padding: 13px 13px 13px 0px; + text-align: right; + [%- ELSE %] + padding: 13px 0px 13px 13px; + text-align: left; + [%- END %] + background-color: [% css_colors.accent_lighter2 %]; + font-size: [% css_fonts.size_smaller %]; + font-weight: bold; +} + +#rdetails_status tbody td { + [% IF rtl == 't' -%] + padding-right: 13px; + text-align: right; + [%- ELSE %] + padding-left: 13px; + text-align: left; + [%- END %] +} +#rdetails_status tbody td.copy_note { + color: [% css_colors.primary %]; + text-wrap:normal; + white-space:pre-wrap !important; + word-wrap:normal; +} + +#rdetails_status tbody td.copy_tag { + border-color: [% css_colors.primary %]; + border-style: dashed; + border-width: 2px; +} +#rdetails_status tbody .copy_tag_value { + font-weight: bolder; +} + +.rdetail_extras { + background-color: [% css_colors.primary_fade %]; + border: 1px solid [% css_colors.primary %]; + padding-top:1px; + clear:both; +} + +#rdetail_extras_div { + margin: 1em 0; +} + +.rdetail_extras_hr { + [% IF rtl == 't' -%] + margin-right: 1px; + margin-left: 1px; + [%- ELSE %] + margin-left: 1px; + margin-right: 1px; + [%- END %] + height: 1px; + background-color: [% css_colors.accent_light %]; +} + +.rdetail_extras_link { + padding: 6px 12px; + font-size: [% css_fonts.size_smaller %]; + font-weight: bold; +} + +.rdetail_extras_lbl { + color: [% css_colors.text_invert %]; + text-decoration: none; +} + +#rdetail_extras_expand, #rdetail_extras_collapse, #rdetail_locs_collapse { + [% IF rtl == 't' -%] + margin-right: 13px; + [%- ELSE %] + margin-left: 13px; + [%- END %] +} + +#rdetail_locs_expand, #rdetail_locs_collapse { + [% IF rtl == 't' -%] + margin-right: 13px; + [%- ELSE %] + margin-left:13px; + [%- END %] + padding-bottom:3px; + margin-top:15px; +} + +#rdetail_anotes_div .biography { + margin:0; +} + +span.copy_note_label { + font-weight: bold; +} + +span.copy_tag_type_label { + font-weight: bold; +} + +#gbp_extra, #gbp_arrow_down_link { + display: none; +} + +.almost-content-wrapper { + background-color: [% css_colors.background %]; +} + +#cartDropdown .dropdown-menu { + +} + +#content-wrapper { + background-color: [% css_colors.background %]; + height: auto; + display: grid; +} + +.content-wrapper-record-page { top: -15px; position: relative; } + +#main-content-home { + [% IF rtl == 't' -%] + padding-right: 17px; + margin-right: 1em; + [%- ELSE %] + padding-left: 17px; + margin-left: 1em; + [%- END %] +} +#main-content { + [% IF rtl == 't' -%] + padding-right: 0px; + [%- ELSE %] + padding-left: 0px; + [%- END %] + margin: 0 1em; + clear: both; +} + +#main-content-after-bar { + [% IF rtl == 't' -%] + margin-right: 1em; + padding-right: 4px; + [%- ELSE %] + margin-left: 1em; + padding-left: 4px; + [%- END %] +} + +#results_header_inner { + padding-bottom: 1rem; +} + +#results-side-bar { + [% IF rtl == 't' -%] + float: right; + margin-left: 5px; + [%- ELSE %] + float: left; + margin-right: 5px; + [%- END %] + width: 174px; + background-color: [% css_colors.background %]; +} + +#main-content .login_boxes { + border: 1px solid [% css_colors.accent_lighter %]; + background-color: [% css_colors.accent_lightest %]; + background-image: -moz-linear-gradient(bottom, [% css_colors.accent_ultralight %] 15%, [% css_colors.accent_lightest %] 55%, [% css_colors.accent_ultralight %] 85%); + background-image: -ms-linear-gradient(bottom, [% css_colors.accent_ultralight %] 15%, [% css_colors.accent_lightest %] 55%, [% css_colors.accent_ultralight %] 85%); + background-image: -o-linear-gradient(bottom, [% css_colors.accent_ultralight %] 15%, [% css_colors.accent_lightest %] 55%, [% css_colors.accent_ultralight %] 85%); + background-image: -webkit-linear-gradient(bottom, [% css_colors.accent_ultralight %] 15%, [% css_colors.accent_lightest %] 55%, [% css_colors.accent_ultralight %] 85%); + background-image: linear-gradient(to bottom, [% css_colors.accent_ultralight %] 15%, [% css_colors.accent_lightest %] 55%, [% css_colors.accent_ultralight %] 85%); + color: [% css_colors.accent_darker %]; +} + +#main-content .login_boxes h1 { + font-weight: normal; + font-size: [% css_fonts.size_biggest %]; + margin:0; +} + +#main-content .left_brain { + [% IF rtl == 't' -%] + padding-right: 28px; + [% ELSE -%] + padding-left:28px; + [% END -%] + padding-top:25px; +} + +#main-content .left_brain input[type=text], #main-content .left_brain input[type=password] { + width:167px; + margin:0; + padding:0; + background-color: [% css_colors.background %]; + font-size: [% css_fonts.size_bigger %]; + color: [% css_colors.text %]; +} + +#main-content .left_brain .input_bg { + [% IF rtl == 't' -%] + padding: 10px 13px 0px 10px; + [% ELSE -%] + padding:10px 10px 0px 13px; + [% END -%] + width:167px; + height:29px; +} + +.login-help-box { + [% IF rtl == 't' -%] + float: right; + margin-right: 2em; + [% ELSE -%] + float: left; + margin-left: 2em; + [% END -%] + width: 200px; + text-align: center; +} + +.login-help-button { + font-size: [% css_fonts.size_biggest %]; + padding: 1.5em; +} + +#login-failed-message { + font-size: [% css_fonts.size_bigger %]; + font-weight: bold; + color: [% css_colors.text_alert %]; + padding-top: 1em; +} + +#holds_temp_parent td { + border-bottom:1px solid [% css_colors.border_standard %]; +} + +#holds_temp_parent input, #holds_temp_parent select { + margin:0; +} + + +#holds_temp_parent tr td div.format_icon { + margin-top: 6px; + margin-bottom: 6px; + float: none; +} + +#results_header_bar { + background-color: [% css_colors.accent_medium %]; + border-top:1px solid [% css_colors.accent_mediumdark %]; + border-bottom:1px solid [% css_colors.accent_mediumdark %]; +} + +.results_header_lbl { + [% IF rtl == 't' -%] + float: right; + [% ELSE -%] + float: left; + [% END -%] + font-weight: bold; + color: [% css_colors.text %]; + /* this border is not visible, but it keeps these labels the same size + as the buttons */ + border: 1px solid [% css_colors.accent_medium %]; + background-color: [% css_colors.accent_medium %]; + margin: 0.5em 0.3em; + padding: 0.3em; +} +/* we need a negative margin on the select to allow the containing