diff --git a/.gitignore b/.gitignore
index 57b25409..efb3f5c8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -27,3 +27,5 @@ local_dev_env
.idea
public/assets
+
+.byebug_history
diff --git a/.ruby-version b/.ruby-version
new file mode 100644
index 00000000..45674f16
--- /dev/null
+++ b/.ruby-version
@@ -0,0 +1 @@
+2.3.3
\ No newline at end of file
diff --git a/Gemfile b/Gemfile
index 84a76875..3100f220 100644
--- a/Gemfile
+++ b/Gemfile
@@ -115,3 +115,5 @@ gem 'blacklight-ris', :git => 'https://github.com/upenn-libraries/blacklight-ris
gem 'oga'
gem 'httparty'
+
+gem 'honeybadger'
diff --git a/Gemfile.lock b/Gemfile.lock
index af70dab8..0ced0530 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -175,6 +175,7 @@ GEM
globalid (0.3.7)
activesupport (>= 4.1.0)
hashie (3.6.0)
+ honeybadger (4.7.2)
htmlentities (4.3.4)
httparty (0.16.4)
mime-types (~> 3.0)
@@ -390,6 +391,7 @@ DEPENDENCIES
dotenv-rails
font-awesome-rails
globalid (= 0.3.7)
+ honeybadger
httparty
jbuilder (= 2.6.0)
jdbc-sqlite3 (= 3.8.11.2)
diff --git a/README.md b/README.md
index e760d1b3..8ebae366 100644
--- a/README.md
+++ b/README.md
@@ -5,9 +5,10 @@ Installation:
- Checkout this repo.
-- Make sure you have ruby 2.3.1 installed. It's recommended that you
+- Make sure you have ruby 2.3.3 installed. It's recommended that you
use [rbenv](https://github.com/rbenv/rbenv), but it may be
quicker/easier to get running with [rvm](https://rvm.io/).
+ - You may have issues installing Ruby 2.3.3 in recent Linux distributions due to an OpenSSL version incompatibility. See [this guide](https://www.garron.me/en/linux/install-ruby-2-3-3-ubuntu.html) for help.
- Run `bundle install` to install all gem dependencies.
diff --git a/app/assets/images/amanpreet_kaur.jpg b/app/assets/images/amanpreet_kaur.jpg
deleted file mode 100644
index 161f5452..00000000
Binary files a/app/assets/images/amanpreet_kaur.jpg and /dev/null differ
diff --git a/app/assets/images/anne_larrivee.jpg b/app/assets/images/anne_larrivee.jpg
deleted file mode 100644
index 76c16d37..00000000
Binary files a/app/assets/images/anne_larrivee.jpg and /dev/null differ
diff --git a/app/assets/images/arthur_kiron.jpg b/app/assets/images/arthur_kiron.jpg
deleted file mode 100644
index 5735cbfe..00000000
Binary files a/app/assets/images/arthur_kiron.jpg and /dev/null differ
diff --git a/app/assets/images/brian_vivier.jpg b/app/assets/images/brian_vivier.jpg
deleted file mode 100644
index 60ff74dd..00000000
Binary files a/app/assets/images/brian_vivier.jpg and /dev/null differ
diff --git a/app/assets/images/bruce_nielsen.jpg b/app/assets/images/bruce_nielsen.jpg
deleted file mode 100644
index 0fb6397f..00000000
Binary files a/app/assets/images/bruce_nielsen.jpg and /dev/null differ
diff --git a/app/assets/images/carlos_rodriguez.jpg b/app/assets/images/carlos_rodriguez.jpg
deleted file mode 100644
index 732aa8ba..00000000
Binary files a/app/assets/images/carlos_rodriguez.jpg and /dev/null differ
diff --git a/app/assets/images/cathy_ogur.jpg b/app/assets/images/cathy_ogur.jpg
deleted file mode 100644
index b9ef677c..00000000
Binary files a/app/assets/images/cathy_ogur.jpg and /dev/null differ
diff --git a/app/assets/images/charles_cobine.jpg b/app/assets/images/charles_cobine.jpg
deleted file mode 100644
index 2626ac6c..00000000
Binary files a/app/assets/images/charles_cobine.jpg and /dev/null differ
diff --git a/app/assets/images/cynthia_cronin_kardon.jpg b/app/assets/images/cynthia_cronin_kardon.jpg
deleted file mode 100644
index 9c53de6c..00000000
Binary files a/app/assets/images/cynthia_cronin_kardon.jpg and /dev/null differ
diff --git a/app/assets/images/david_azzolina.jpg b/app/assets/images/david_azzolina.jpg
deleted file mode 100644
index 3589074f..00000000
Binary files a/app/assets/images/david_azzolina.jpg and /dev/null differ
diff --git a/app/assets/images/david_mcknight.jpg b/app/assets/images/david_mcknight.jpg
deleted file mode 100644
index 7b67d70b..00000000
Binary files a/app/assets/images/david_mcknight.jpg and /dev/null differ
diff --git a/app/assets/images/deborah_stewart.jpg b/app/assets/images/deborah_stewart.jpg
deleted file mode 100644
index 22bc7e28..00000000
Binary files a/app/assets/images/deborah_stewart.jpg and /dev/null differ
diff --git a/app/assets/images/dee_crandall.jpg b/app/assets/images/dee_crandall.jpg
deleted file mode 100644
index e75671a1..00000000
Binary files a/app/assets/images/dee_crandall.jpg and /dev/null differ
diff --git a/app/assets/images/dot_porter.jpg b/app/assets/images/dot_porter.jpg
deleted file mode 100644
index 4c750a25..00000000
Binary files a/app/assets/images/dot_porter.jpg and /dev/null differ
diff --git a/app/assets/images/douglas_mcgee.jpg b/app/assets/images/douglas_mcgee.jpg
deleted file mode 100644
index 06ff7dc9..00000000
Binary files a/app/assets/images/douglas_mcgee.jpg and /dev/null differ
diff --git a/app/assets/images/feedback.png b/app/assets/images/feedback.png
deleted file mode 100644
index 3c994a15..00000000
Binary files a/app/assets/images/feedback.png and /dev/null differ
diff --git a/app/assets/images/frank_campbell.jpg b/app/assets/images/frank_campbell.jpg
deleted file mode 100644
index f9fa96c8..00000000
Binary files a/app/assets/images/frank_campbell.jpg and /dev/null differ
diff --git a/app/assets/images/girmaye_misgna.jpg b/app/assets/images/girmaye_misgna.jpg
deleted file mode 100644
index 6033de5c..00000000
Binary files a/app/assets/images/girmaye_misgna.jpg and /dev/null differ
diff --git a/app/assets/images/gwen_collaco.jpg b/app/assets/images/gwen_collaco.jpg
deleted file mode 100644
index f7deee45..00000000
Binary files a/app/assets/images/gwen_collaco.jpg and /dev/null differ
diff --git a/app/assets/images/hannah_bennett.jpg b/app/assets/images/hannah_bennett.jpg
deleted file mode 100644
index c8e7df89..00000000
Binary files a/app/assets/images/hannah_bennett.jpg and /dev/null differ
diff --git a/app/assets/images/jef_pierce.jpg b/app/assets/images/jef_pierce.jpg
deleted file mode 100644
index 2382ebbc..00000000
Binary files a/app/assets/images/jef_pierce.jpg and /dev/null differ
diff --git a/app/assets/images/joseph_holub.jpg b/app/assets/images/joseph_holub.jpg
deleted file mode 100644
index b7e35f39..00000000
Binary files a/app/assets/images/joseph_holub.jpg and /dev/null differ
diff --git a/app/assets/images/judith_currano.jpg b/app/assets/images/judith_currano.jpg
deleted file mode 100644
index 4aef33e3..00000000
Binary files a/app/assets/images/judith_currano.jpg and /dev/null differ
diff --git a/app/assets/images/kenny_whitebloom.jpg b/app/assets/images/kenny_whitebloom.jpg
deleted file mode 100644
index 952d36aa..00000000
Binary files a/app/assets/images/kenny_whitebloom.jpg and /dev/null differ
diff --git a/app/assets/images/laurel_graham.jpg b/app/assets/images/laurel_graham.jpg
deleted file mode 100644
index 6ed556d4..00000000
Binary files a/app/assets/images/laurel_graham.jpg and /dev/null differ
diff --git a/app/assets/images/lauren_gala.jpg b/app/assets/images/lauren_gala.jpg
deleted file mode 100644
index d818dba3..00000000
Binary files a/app/assets/images/lauren_gala.jpg and /dev/null differ
diff --git a/app/assets/images/lauris_olson.jpg b/app/assets/images/lauris_olson.jpg
deleted file mode 100644
index 4791cc19..00000000
Binary files a/app/assets/images/lauris_olson.jpg and /dev/null differ
diff --git a/app/assets/images/liza_vick.jpg b/app/assets/images/liza_vick.jpg
deleted file mode 100644
index 7d3f5ab1..00000000
Binary files a/app/assets/images/liza_vick.jpg and /dev/null differ
diff --git a/app/assets/images/lynn_ransom.jpg b/app/assets/images/lynn_ransom.jpg
deleted file mode 100644
index bdac0132..00000000
Binary files a/app/assets/images/lynn_ransom.jpg and /dev/null differ
diff --git a/app/assets/images/lynne_farrington.jpg b/app/assets/images/lynne_farrington.jpg
deleted file mode 100644
index 229d7f3d..00000000
Binary files a/app/assets/images/lynne_farrington.jpg and /dev/null differ
diff --git a/app/assets/images/manuel_de_la_cruz_gutierrez.jpg b/app/assets/images/manuel_de_la_cruz_gutierrez.jpg
deleted file mode 100644
index 03c5b066..00000000
Binary files a/app/assets/images/manuel_de_la_cruz_gutierrez.jpg and /dev/null differ
diff --git a/app/assets/images/marcella_barnhart.jpg b/app/assets/images/marcella_barnhart.jpg
deleted file mode 100644
index d77aeacc..00000000
Binary files a/app/assets/images/marcella_barnhart.jpg and /dev/null differ
diff --git a/app/assets/images/margaret_janz.jpg b/app/assets/images/margaret_janz.jpg
deleted file mode 100644
index a75c5246..00000000
Binary files a/app/assets/images/margaret_janz.jpg and /dev/null differ
diff --git a/app/assets/images/margy_lindem.jpg b/app/assets/images/margy_lindem.jpg
deleted file mode 100644
index cb46bdbd..00000000
Binary files a/app/assets/images/margy_lindem.jpg and /dev/null differ
diff --git a/app/assets/images/maylene_qiu.jpg b/app/assets/images/maylene_qiu.jpg
deleted file mode 100644
index 1621cea7..00000000
Binary files a/app/assets/images/maylene_qiu.jpg and /dev/null differ
diff --git a/app/assets/images/melanie_cedrone.jpg b/app/assets/images/melanie_cedrone.jpg
deleted file mode 100644
index 06602686..00000000
Binary files a/app/assets/images/melanie_cedrone.jpg and /dev/null differ
diff --git a/app/assets/images/mia_wells.jpg b/app/assets/images/mia_wells.jpg
deleted file mode 100644
index c97e581c..00000000
Binary files a/app/assets/images/mia_wells.jpg and /dev/null differ
diff --git a/app/assets/images/mitch_fraas.jpg b/app/assets/images/mitch_fraas.jpg
deleted file mode 100644
index ab265868..00000000
Binary files a/app/assets/images/mitch_fraas.jpg and /dev/null differ
diff --git a/app/assets/images/molly_des_jardin.jpg b/app/assets/images/molly_des_jardin.jpg
deleted file mode 100644
index b389d186..00000000
Binary files a/app/assets/images/molly_des_jardin.jpg and /dev/null differ
diff --git a/app/assets/images/nicholas_herman.jpg b/app/assets/images/nicholas_herman.jpg
deleted file mode 100644
index dddcf123..00000000
Binary files a/app/assets/images/nicholas_herman.jpg and /dev/null differ
diff --git a/app/assets/images/nick_okrent.jpg b/app/assets/images/nick_okrent.jpg
deleted file mode 100644
index 00ec478e..00000000
Binary files a/app/assets/images/nick_okrent.jpg and /dev/null differ
diff --git a/app/assets/images/patricia_guardiola.jpg b/app/assets/images/patricia_guardiola.jpg
deleted file mode 100644
index f6c456b7..00000000
Binary files a/app/assets/images/patricia_guardiola.jpg and /dev/null differ
diff --git a/app/assets/images/patty_lynn.jpg b/app/assets/images/patty_lynn.jpg
deleted file mode 100644
index b6a4b3f1..00000000
Binary files a/app/assets/images/patty_lynn.jpg and /dev/null differ
diff --git a/app/assets/images/rebecca_stuhr.jpg b/app/assets/images/rebecca_stuhr.jpg
deleted file mode 100644
index 43c9fb6a..00000000
Binary files a/app/assets/images/rebecca_stuhr.jpg and /dev/null differ
diff --git a/app/assets/images/richard_james.jpg b/app/assets/images/richard_james.jpg
deleted file mode 100644
index c359008c..00000000
Binary files a/app/assets/images/richard_james.jpg and /dev/null differ
diff --git a/app/assets/images/samantha_kirk.jpg b/app/assets/images/samantha_kirk.jpg
deleted file mode 100644
index 8fa56f83..00000000
Binary files a/app/assets/images/samantha_kirk.jpg and /dev/null differ
diff --git a/app/assets/images/sarah_wipperman.jpg b/app/assets/images/sarah_wipperman.jpg
deleted file mode 100644
index f820593b..00000000
Binary files a/app/assets/images/sarah_wipperman.jpg and /dev/null differ
diff --git a/app/assets/images/sharon_black.jpg b/app/assets/images/sharon_black.jpg
deleted file mode 100644
index 3b8dc2a4..00000000
Binary files a/app/assets/images/sharon_black.jpg and /dev/null differ
diff --git a/app/assets/images/sherry_morgan.jpg b/app/assets/images/sherry_morgan.jpg
deleted file mode 100644
index 404d6a85..00000000
Binary files a/app/assets/images/sherry_morgan.jpg and /dev/null differ
diff --git a/app/assets/images/vickie_karasic.jpg b/app/assets/images/vickie_karasic.jpg
deleted file mode 100644
index 0aa7e3cb..00000000
Binary files a/app/assets/images/vickie_karasic.jpg and /dev/null differ
diff --git a/app/assets/images/william_noel.jpg b/app/assets/images/william_noel.jpg
deleted file mode 100644
index 4487338a..00000000
Binary files a/app/assets/images/william_noel.jpg and /dev/null differ
diff --git a/app/assets/javascripts/availability.js.erb b/app/assets/javascripts/availability.js.erb
index 24aed695..aa858dce 100644
--- a/app/assets/javascripts/availability.js.erb
+++ b/app/assets/javascripts/availability.js.erb
@@ -4,7 +4,17 @@ var validRequestTypes = ["CentralCAT","MAINT-EC","CHI CAT","CatMet","HEB CAT",
"Jap-KorCAT","MUSIC CAT","MidEastCat","SASIA CAT",
"SCPC CAT","SLAV CAT","BindRepair","MAINT-enh",
"MAINT-otf","MAINT-tr"];
-$.fn.dataTable.ext.errMode = 'none';
+$.fn.dataTable.ext.errMode = 'none';
+
+// Hackily parses relevant context out of the DOM for the specified mmsid
+function get_request_context(mmsid) {
+ return {
+ pickupable: null,
+ hathi_etas: (document.getElementById('hathi_etas-'+mmsid) != null),
+ hathi_pd: (document.getElementById('hathi_pd-'+mmsid) != null),
+ monograph: (document.getElementById('monograph-'+mmsid) != null)
+ };
+}
$(document).ready(function() {
@@ -13,7 +23,16 @@ $(document).ready(function() {
BlacklightAlma.call(this);
}
- function constructAeonLink(mmsid, holding) {
+ // Based on hackily-parsed DOM context, determine whether the Pickup@Penn link should be suppressed
+ function disable_pickup_at_penn(ctx) {
+ return ctx.monograph && (ctx.pickupable === false || ctx.hathi_etas /*|| ctx.hathi_pd*/);
+ }
+
+ function constructAeonLink(mmsid, holding, ctx) {
+ if (ctx.hathi_etas && ctx.monograph) {
+ return null;
+ }
+
if(holding['link_to_aeon']) {
return 'Request to view';
}
@@ -24,17 +43,24 @@ $(document).ready(function() {
Franklin.prototype = Object.create(BlacklightAlma.prototype);
Franklin.prototype.formatHolding = function (mms_id, holding) {
+ var ctx = get_request_context(mms_id);
if (holding['inventory_type'] == 'physical') {
var availability = "Unknown";
if (holding['availability'] == 'check_holdings') {
availability = "See options";
} else if (holding['availability'] == 'unavailable') {
- availability = "See request options";
+ // pre-COVID-19 always mapped to "See request options";
+ if (holding['link_to_aeon']) {
+ // Aeon materials show as "unavailable", but not in the sense of being unviewable.
+ availability = (ctx.hathi_etas && ctx.monograph) ? "Restricted (COVID-19)" : "See request options";
+ } else {
+ availability = "Unavailable";
+ }
} else if (holding['availability'] == 'available') {
- availability = "Available";
+ availability = disable_pickup_at_penn(ctx) ? "Restricted (COVID-19)" : "Available";
}
// TODO: pass in format to shelfLocatorLink() somehow
- return [availability, holding['location'], holding['call_number'], $.shelfLocatorLink(mms_id, holding, "TODO"), constructAeonLink(mms_id, holding)]
+ return [availability, holding['location'], holding['call_number'], $.shelfLocatorLink(mms_id, holding, "TODO"), constructAeonLink(mms_id, holding, ctx)]
.filter(function (item) {
return item != null && item.length > 0;
}).join(". ");
@@ -43,7 +69,7 @@ $(document).ready(function() {
if (holding['activation_status'] == 'Available') {
var url = null;
if (holding['portfolio_pid']) {
- url = "https://<%= ENV['ALMA_DELIVERY_DOMAIN'] %>/view/uresolver/<%= ENV['ALMA_INSTITUTION_CODE'] %>/openurl?Force_direct=true&portfolio_pid=" +
+ url = "https://<%= ENV['ALMA_DELIVERY_DOMAIN'] %>/view/uresolver/<%= ENV['ALMA_INSTITUTION_CODE'] %>/openurl?Force_direct=true&test_access=true&&portfolio_pid=" +
holding['portfolio_pid'] + "&rfr_id=info%3Asid%2Fprimo.exlibrisgroup.com&u.ignore_date_coverage=true"
}
@@ -75,7 +101,8 @@ $(document).ready(function() {
};
Franklin.prototype.loadRequestOptionsAjax = function(mmsid) {
- var url = "/alma/single_availability.json?mms_id=" + encodeURIComponent(mmsid);
+ var request_context = get_request_context(mmsid);
+ var url = "/alma/single_availability.json?mms_id=" + encodeURIComponent(mmsid) + "&request_context=" + encodeURIComponent(JSON.stringify(request_context));
$('#requestOptions-' + mmsid).on('error.dt', function(e, settings, techNote, message) {
$(this).dataTable().fnSettings().oLanguage.sEmptyTable = 'An error has occurred.';
@@ -86,7 +113,7 @@ $(document).ready(function() {
$.get(url, function(data) {
globaldata = $.extend({}, globaldata, data["metadata"]);
callback({"data": data["data"]});
- Franklin.prototype.loadRequestOptionListAjax(mmsid);
+ Franklin.prototype.loadRequestOptionListAjax(mmsid, request_context);
});
},
"processing": true,
@@ -113,10 +140,11 @@ $(document).ready(function() {
var requests = globaldata[data[i][7]];
if(validRequestTypes.indexOf(requests[0]) != -1) {
renderdata[mmsid].push(data[i][7]);
- data[i][5][0] = "Request";
+ // TODO: when libraries reopen: remove conditional, Pickup@Penn=>Request
+ data[i][5][0] = disable_pickup_at_penn(request_context) ? "" : "Pickup@Penn";
table.row(i).invalidate().draw();
}
- }
+ }
}
}
@@ -198,18 +226,59 @@ $(document).ready(function() {
});
};
- Franklin.prototype.loadRequestOptionListAjax = function(mmsid) {
+ Franklin.prototype.loadRequestOptionListAjax = function(mmsid, request_context) {
+ request_context.pickupable = globaldata[mmsid]["pickupable"];
$.ajax({
- url: "/alma/request_options.json?mms_id="+mmsid,
+ url: "/alma/request_options.json?mms_id="+mmsid+"&request_context="+encodeURIComponent(JSON.stringify(request_context)),
success: function(data, textStatus, jqXHR) {
var optionList = $('#requestOptionList-' + mmsid);
- if(globaldata[mmsid]["facultyexpress"]) {
- for(i = 0; i < data.length; i++) {
- if(data[i]['option_name'] == 'Interlibrary Loan') {
- data[i]['option_name'] = 'FacultyEXPRESS';
+ var openUrlTemplate = null; // grab openUrl params from here if necessary
+ var registeredFacEx = globaldata[mmsid]['facultyexpress'] ? false : null; // null if not applicable
+ var booksByMailOption = null;
+ for(var i = 0; i < data.length && (openUrlTemplate === null || booksByMailOption === null || registeredFacEx === false); i++) {
+ var requestOption = data[i];
+ switch (requestOption['option_name']) {
+ case 'Interlibrary Loan':
+ openUrlTemplate = requestOption['option_url'];
+ if (registeredFacEx === false) { // careful! must distinguish from "falsey" null
+ requestOption['option_name'] = 'FacultyEXPRESS';
+ registeredFacEx = true;
+ }
break;
- }
+ case 'Request Digital Delivery':
+ if (openUrlTemplate === null) {
+ // provisionally grab openUrl from here, but prefer from ILL if present for consistency
+ openUrlTemplate = requestOption['option_url'];
+ }
+ break;
+ case 'Books By Mail':
+ booksByMailOption = requestOption;
+ break;
+ }
+ }
+ if ((registeredFacEx === false || booksByMailOption != null) && (!request_context.monograph || !request_context.hathi_etas)) {
+ // assume first querystring param is 'requesttype=[...]' -- subsequent options (preceded by '&') should be openUrl params
+ var startOpenUrlParams = openUrlTemplate === null ? -1 : openUrlTemplate.indexOf('&');
+ if (startOpenUrlParams < 0) {
+ appendOpenUrlParams = '';
+ } else {
+ appendOpenUrlParams = openUrlTemplate.slice(startOpenUrlParams);
+ }
+ if (registeredFacEx === false) {
+ data.push({
+ option_name: 'FacultyEXPRESS',
+ option_url: 'https://franklin.library.upenn.edu/forms/ill?requesttype=book' + appendOpenUrlParams,
+ highlightable: true
+ });
+ }
+ if (booksByMailOption != null) {
+ // NOTE: we're conjuring an ILL link that would normally be generated by Alma, but is not now (COVID-19) because
+ // ILL-proper is disabled. Despite appearances, 80% confident that requesttype should always be "book" (e.g., even
+ // for "journals"), because "book" differentiates from things like reprographic requests, _not_ actually based on
+ // bibliographic material type. 'deliverytype=bbm' is handled in the ill form (franklinforms) to prepend "BBM " to
+ // otherwise-normal ILL requests (saving staff manually doing so); such ILL requests are then handled as BBM requests.
+ booksByMailOption['option_url'] = 'https://franklin.library.upenn.edu/forms/ill?requesttype=book&deliverytype=bbm' + appendOpenUrlParams;
}
}
@@ -246,9 +315,8 @@ $(document).ready(function() {
containingdiv.appendTo(optionList);
});
$('#request-options-spinner-' + mmsid).remove();
- console.log(data);
}
- });
+ });
};
Franklin.prototype.loadRequestOptions = function() {
@@ -294,6 +362,7 @@ $(document).ready(function() {
"emptyTable": "No item data available"
},
"drawCallback": function(settings) {
+ var request_context = get_request_context(mmsid);
var table = $('#holdingItems-' + mmsid).DataTable();
var pageSize = table.settings()[0]['_iDisplayLength'];
var tableLen = table.data().length;
@@ -305,10 +374,11 @@ $(document).ready(function() {
var requests = globaldata[data[i][0]];
if(validRequestTypes.indexOf(requests[0]) != -1) {
renderdata[mmsid].push(data[i][0]);
- data[i][5].push("Request");
+ // TODO: when libraries reopen: remove conditional, Pickup@Penn=>Request
+ data[i][5].push(disable_pickup_at_penn(request_context) ? "" : "Pickup@Penn");
table.row(i).invalidate().draw();
}
- }
+ }
}
}
@@ -352,11 +422,13 @@ $(document).ready(function() {
ba.loadRequestOptions();
});
-function loadItems(mms_id, holding_id, location_code) {
+function loadItems(mms_id, holding_id, location_code, pickupable) {
+ var request_context = get_request_context(mms_id);
+ request_context.pickupable = pickupable;
renderdata[mms_id] = [];
var holdingItemsTable = $('#holdingItems-' + mms_id).DataTable();
holdingItemsTable.clear().draw();
- holdingItemsTable.ajax.url('/alma/holding_items.json?mms_id=' + mms_id + "&holding_id=" + holding_id + "¤t_location=" + location_code).load();
+ holdingItemsTable.ajax.url('/alma/holding_items.json?mms_id=' + mms_id + "&holding_id=" + holding_id + "¤t_location=" + location_code + "&request_context=" + encodeURIComponent(JSON.stringify(request_context))).load();
swapDataTables(mms_id);
}
diff --git a/app/assets/javascripts/expert_help.js b/app/assets/javascripts/expert_help.js
new file mode 100644
index 00000000..8de4e28d
--- /dev/null
+++ b/app/assets/javascripts/expert_help.js
@@ -0,0 +1,19 @@
+$(document).ready(function() {
+ var $expert;
+ $expert = $('#ExpertOptions');
+
+ if (window.matchMedia("(min-width: 992px)").matches &&
+ !document.cookie.includes('franklin_hide_expert_help=true')) {
+ $expert.collapse('show');
+ } else {
+ $expert.collapse('hide');
+ }
+
+ $expert.on('hide.bs.collapse', function() {
+ document.cookie = 'franklin_hide_expert_help=true;path=/'
+ });
+
+ $expert.on('show.bs.collapse', function() {
+ document.cookie = 'franklin_hide_expert_help=;path=/;max-age=0'
+ });
+});
diff --git a/app/assets/javascripts/login-ezproxy.js b/app/assets/javascripts/login-ezproxy.js
index 140ac3eb..53a36ca0 100644
--- a/app/assets/javascripts/login-ezproxy.js
+++ b/app/assets/javascripts/login-ezproxy.js
@@ -45,7 +45,7 @@ $(document).ready(function() {
var proxyUrl = PROXY_PREPEND + 'http://127.0.0.1:8082/?redirect=' + encodeURIComponent(currentUrl);
$(div).find(".ezproxy-login-link").attr("href", proxyUrl);
- if (auth !== null && auth !== undefined) {
+ if (auth !== null && auth !== undefined && auth.loggedIn) {
$(div).find(".view-and-filter").find("a").each(function (idx, element) {
// ezproxy handles url param specifically so we don't need to escape it
var viewAndFilterUrl = $(element).attr("href");
diff --git a/app/assets/javascripts/no_db_results.js b/app/assets/javascripts/no_db_results.js
index f2ea9313..e69de29b 100644
--- a/app/assets/javascripts/no_db_results.js
+++ b/app/assets/javascripts/no_db_results.js
@@ -1,5 +0,0 @@
-$(document).ajaxComplete(function() {
- if ($('.gs-no-results-result').length) {
- $('#bento-results-google').addClass('hidden');
- }
-});
\ No newline at end of file
diff --git a/app/assets/javascripts/tabs.js b/app/assets/javascripts/tabs.js
index e934a53f..03888d7d 100644
--- a/app/assets/javascripts/tabs.js
+++ b/app/assets/javascripts/tabs.js
@@ -5,10 +5,6 @@
*/
$(document).ready(function() {
- $("#feedbackout").click(function(){
- $("#feedback").hide();
- });
-
$("a[role='tab']").bind('click', function(event) {
window.history.pushState({},"", $(event.currentTarget).attr("href"));
});
diff --git a/app/assets/javascripts/two_columns.js b/app/assets/javascripts/two_columns.js
deleted file mode 100644
index b7b127e4..00000000
--- a/app/assets/javascripts/two_columns.js
+++ /dev/null
@@ -1,6 +0,0 @@
-$(document).ajaxComplete(function() {
- if($("#bento-results-databases .bento-item").length == 0 && $('.gs-no-results-result').length){
- $('#bento-results-catalog').addClass('fifty-percent')
- $('#bento-results-summon').addClass('fifty-percent')
- }
-});
\ No newline at end of file
diff --git a/app/assets/stylesheets/franklin.css.scss b/app/assets/stylesheets/franklin.css.scss
index 08dc5d3f..5be5d8f6 100644
--- a/app/assets/stylesheets/franklin.css.scss
+++ b/app/assets/stylesheets/franklin.css.scss
@@ -3,19 +3,15 @@
@import 'base/colors.css.scss';
@import 'base/mixins.css.scss';
-@media (min-width: 1200px) {
- .col-md-3 {
- width: 24%;
- }
-}
@media (min-width: 992px) and (max-width: 1199px) {
- .col-md-3 {
- width: 25%;
+ .bento-box.databases-results, .bento-box.colenda-results,
+ .bento-box.google-results {
+ width: auto;
}
- .bento-box {
- width: 32%;
+ .bento-box, .libraries-results {
+ width: 32.5%;
}
}
@@ -380,6 +376,10 @@ bg color to fill document-metadata's bottom margin */
display: none;
}
+.libraries-results {
+ padding: 0px;
+}
+
.view-and-filter {
padding: 6px;
background: #ececec;
@@ -613,7 +613,6 @@ h3.ongray {
margin: 5px;
padding: 0px;
z-index: 10;
- min-height: 250px;
}
.bento-box-highlight {
@@ -710,6 +709,18 @@ h3.ongray {
}
}
+.colenda-thumbnail {
+ text-align: center;
+ img {
+ height: 50px;
+ width: 90%;
+ object-fit: cover;
+ }
+}
+.colenda-help {
+ font-size: 13px;
+}
+
/* hack */
#bento-results-google .source-info {
display: none;
@@ -721,26 +732,71 @@ h3.ongray {
/* end of hack */
+.panel-default > .panel-heading.expert-box {
+ color: white;
+ background-color: #337ab7;
+ border-color: #ddd;
+}
+.expert-box.panel-heading.collapse-toggle .panel-title:after {
+ font-family: 'Glyphicons Halflings';
+ content: "\e114";
+ float: right;
+ color: white;
+ font-size: 1.03em;
+ line-height: normal;
+}
+
+.expert-box.panel-heading.collapse-toggle.collapsed .panel-title:after {
+ font-family: 'Glyphicons Halflings';
+ content: "\e113";
+ float: right;
+ color: white;
+ font-size: 1.03em;
+ line-height: normal;
+}
+
+h3.expert-heading {
+ margin-top: 0;
+ padding: 0;
+}
+
+.expert-chat-link {
+ margin: 0 0 5px;
+ text-align: center;
+}
+
+#libchat_7cde980ad423479da2585a498007774e button.libchat_online {
+ font-size: 12px;
+ padding: 1px 5px 3px;
+ height: 20px;
+}
+
.expert-results {
- display: none; /* TODO: remove when launching this feature */
- padding: 10px;
- hr {
- border-bottom: 1px dashed #d2d2d2;
+ position: fixed;
+ bottom: 0;
+ right: 0;
+ width: 235px;
+ min-height: auto;
+ margin: 0;
+
+ .expert-p {
+ margin-bottom: 0;
}
.expert-profile {
+ padding: 8px;
font-size: 12px;
.upper-content {
}
.lower-content {
clear: both;
- padding-top: 10px;
+ padding-top: 3px;
}
img {
@include rounded-corners;
width: 100px;
height: 100px;
float: left;
- margin-right: 20px;
+ margin-right: 8px;
}
a.link-to-profile {
font-size: 16px;
@@ -761,64 +817,54 @@ h3.ongray {
}
}
+.hr-text {
+ line-height: 1em;
+ position: relative;
+ outline: 0;
+ border: 0;
+ color: black;
+ text-align: center;
+ margin-top: 5px;
+ margin-bottom: 5px;
+ height: 1.5em;
+ opacity: .5;
+ &:before {
+ content: '';
+ background: linear-gradient(to right, transparent, #818078, transparent);
+ position: absolute;
+ left: 0;
+ top: 50%;
+ width: 100%;
+ height: 1px;
+ }
+ &:after {
+ content: attr(data-content);
+ position: relative;
+ display: inline-block;
+ color: black;
+
+ padding: 0 .5em;
+ line-height: 1.5em;
+ background-color: #fcfcfa;
+ }
+}
+
.databases-landing-content .heading {
font-weight: bold;
color: #900;
font-size: 1.17em;
}
-#feedback {
- display: none;
- background-image: asset-url('feedback.png');
- background-repeat: no-repeat;
- width: 77px;
- height: 91px;
- background-size: auto 89px;
- position: absolute;
- top: 16.0rem;
- z-index: 1000;
- right: 2.5rem;
-}
-
.bento_item_body href {
overflow: hidden;
-ms-text-overflow: ellipsis;
text-overflow: ellipsis;
}
-@media (min-width: 768px) {
- #feedback {
- display: block;
- }
-}
-
@media (min-width: 1200px) {
- #feedback {
- top: 11.0rem;
- }
.col-lg-4 {
- width: 32.333333%;
+ width: 32.6%;
}
-
-}
-
-#feedbacklink {
- cursor: pointer;
- display: block;
- height: 7.7rem;
- width: 8.9rem;
- position: absolute;
- top: 0;
-}
-
-#feedbackout {
- cursor: pointer;
- display: block;
- height: 1.6rem;
- width: 1.6rem;
- position: absolute;
- right: 0;
- top: 7.7rem;
}
.visually-hidden {
@@ -880,6 +926,11 @@ h3.ongray {
margin-bottom: 20px;
}
+ .expert-results.bento-box {
+ min-width: auto;
+ margin-bottom: auto;
+ }
+
}
.bento-all {
diff --git a/app/controllers/catalog_controller.rb b/app/controllers/catalog_controller.rb
index 809ea8b9..caf5af74 100644
--- a/app/controllers/catalog_controller.rb
+++ b/app/controllers/catalog_controller.rb
@@ -70,7 +70,7 @@ def expire_session
PAGINATION_THRESHOLD=250
before_action only: :index do
if params[:page] && params[:page].to_i > PAGINATION_THRESHOLD
- flash[:error] = "You have paginated too deep into the result set. Please contact us using the feedback form if you have a need to view results past page #{PAGINATION_THRESHOLD}."
+ flash[:error] = "You have paginated too deep into the result set. Please contact us if you have a need to view results past page #{PAGINATION_THRESHOLD}."
redirect_to root_path
end
end
@@ -78,7 +78,7 @@ def expire_session
FACET_PAGINATION_THRESHOLD=50
before_action only: :facet do
if params['facet.page'] && params['facet.page'].to_i > FACET_PAGINATION_THRESHOLD
- flash[:error] = "You have paginated too deep into facets. Please contact us using the feedback form if you have a need to view facets past page #{FACET_PAGINATION_THRESHOLD}."
+ flash[:error] = "You have paginated too deep into facets. Please contact us if you have a need to view facets past page #{FACET_PAGINATION_THRESHOLD}."
redirect_to root_path
end
end
@@ -105,6 +105,12 @@ def expire_session
config.default_solr_params = {
#cache: 'false',
defType: 'perEndPosition_dense_shingle_graphSpans',
+ combo: '{!filters param=$q param=$fq excludeTags=cluster}',
+ post_1928: 'content_max_dtsort:[1929-01-01T00:00:00Z TO *]',
+ culture_filter: "{!bool should='{!terms f=subject_search v=literature,customs,religion,ethics,society,social,culture,cultural}' should='{!prefix f=subject_search v=art}'}",
+ #combo: '{!bool must=$q filter=\'{!filters param=$fq v=*:*}\'}',
+ #combo: '{!query v=$q}',
+ back: '*:*',
# this list is annoying to maintain, but this avoids hard-coding a field list
# in the search request handler in solrconfig.xml
fl: %w{
@@ -201,6 +207,42 @@ def expire_session
'Include Partner Libraries' != a.params.dig(:f, :cluster, 0)
}
+ # Some filters (e.g., subject_f) are capable of driving meaning correlations;
+ # others are not, and either generate spurious correlations, or at best pointlessly add extra
+ # overhead to Solr request.
+ # Keys below indicate filters that we should not attempt to use for purpose of cacluating
+ # correlations -- either entirely (nil value) or for an array of certain filter values
+ @@CORRELATION_IGNORELIST = {
+ :access_f => nil,
+ :record_source_f => nil,
+ :format_f => ['Database & Article Index']
+ }
+
+ actionable_filters = lambda { |a, b, c|
+ params = a.params
+ return true if params[:q].present?
+ f = params[:f]
+ return false if f.nil?
+ # we return true if there is at least one non-ignorelisted filter
+ return true if f.size > @@CORRELATION_IGNORELIST.size
+ f.symbolize_keys.each do |facet_key, facet_values|
+ return true unless @@CORRELATION_IGNORELIST.include?(facet_key) # no vals are ignored for this key
+ ignorelisted_vals = @@CORRELATION_IGNORELIST[facet_key]
+ next unless ignorelisted_vals # all vals are ignored for this key
+ return true if (facet_values - ignorelisted_vals).present? # there is at least one non-ignored val
+ end
+ return false
+ }
+
+ get_hits = lambda { |v|
+ r1 = v[:r1]
+ r1.nil? ? 0 : (r1[:relatedness].to_f * 100000).to_i
+ }
+
+ post_sort = lambda { |items|
+ items.sort { |a,b| b.hits <=> a.hits }
+ }
+
config.induce_sort = lambda { |blacklight_params|
return 'title_nssort asc' if blacklight_params.dig(:f, :format_f)&.include?('Database & Article Index')
}
@@ -221,6 +263,11 @@ def expire_session
}
}
+ @@SUBJECT_SPECIALISTS = File.open("config/translation_maps/subject_specialists.solr-json", "rb").map do |line|
+ comment_idx = line.index('#')
+ (comment_idx.nil? ? line : line.slice(0, comment_idx)).strip.presence
+ end.compact.join
+
@@DATABASE_CATEGORY_TAXONOMY = [
'{',
'db_category_f:{',
@@ -276,6 +323,9 @@ def expire_session
config.add_facet_field 'db_type_f', label: 'Database Type', limit: -1, collapse: false, :if => database_selected,
:facet_type => :database, solr_params: @@MINCOUNT
+ config.add_facet_field 'subject_specialists', label: 'Subject Area Correlation', collapse: true, :partial => 'blacklight/hierarchy/facet_hierarchy',
+ :json_facet => @@SUBJECT_SPECIALISTS, :top_level_field => 'subject_specialists', :get_hits => get_hits, :post_sort => post_sort,
+ :if => actionable_filters
config.add_facet_field 'azlist', label: 'A-Z List', collapse: false, single: :manual, :facet_type => :header,
options: {:layout => 'horizontal_facet_list'}, solr_params: { 'facet.mincount' => 0 }, :if => database_selected, query: {
'A' => { :label => 'A', :fq => "{!prefix tag=azlist ex=azlist f=title_xfacet v='a'}"},
@@ -307,7 +357,7 @@ def expire_session
'Other' => { :label => 'Other', :fq => "{!tag=azlist ex=azlist}title_xfacet:/[ -`{-~].*/"}
}
config.add_facet_field 'access_f', label: 'Access', collapse: false, solr_params: @@MINCOUNT, :if => local_only, query: {
- 'Online' => { :label => 'Online', :fq => "{!join from=cluster_id to=cluster_id v=access_f:Online}"},
+ 'Online' => { :label => 'Online', :fq => "{!join from=cluster_id to=cluster_id v='access_f:Online OR record_source_id:3'}"},
'At the library' => { :label => 'At the library', :fq => "{!join from=cluster_id to=cluster_id v='{!term f=access_f v=\\'At the library\\'}'}"}
}
config.add_facet_field 'format_f', label: 'Format', limit: 5, collapse: false, solr_params: @@MINCOUNT, :if => local_only, query: {
@@ -338,6 +388,11 @@ def expire_session
config.add_facet_field 'language_f', label: 'Language', limit: 5, collapse: false, solr_params: @@MINCOUNT
config.add_facet_field 'library_f', label: 'Library', limit: 5, collapse: false, :if => local_only, solr_params: @@MINCOUNT
config.add_facet_field 'specific_location_f', label: 'Specific location', limit: 5, :if => local_only, solr_params: @@MINCOUNT
+ config.add_facet_field 'recently_published', label: 'Recently published', collapse: false, solr_params: @@MINCOUNT, :query => {
+ :last_5_years => { label: 'Last 5 years', fq: "pub_max_dtsort:[#{Date.current.year - 4}-01-01T00:00:00Z TO *]" },
+ :last_10_years => { label: 'Last 10 years', fq: "pub_max_dtsort:[#{Date.current.year - 9}-01-01T00:00:00Z TO *]" },
+ :last_15_years => { label: 'Last 15 years', fq: "pub_max_dtsort:[#{Date.current.year - 14}-01-01T00:00:00Z TO *]" },
+ }
config.add_facet_field 'publication_date_f', label: 'Publication date', limit: 5, collapse: false, solr_params: @@MINCOUNT
config.add_facet_field 'classification_f', label: 'Classification', limit: 5, collapse: false, :if => local_only, solr_params: @@MINCOUNT
config.add_facet_field 'genre_f', label: 'Form/Genre', limit: 5, solr_params: @@MINCOUNT
diff --git a/app/controllers/collection_news_controller.rb b/app/controllers/collection_news_controller.rb
index 1e335094..a928c8f6 100644
--- a/app/controllers/collection_news_controller.rb
+++ b/app/controllers/collection_news_controller.rb
@@ -7,7 +7,7 @@ class CollectionNewsController < ApplicationController
include RssProxy
def index
- rss_proxy('https://pennlibnews.wordpress.com/category/collection-news/feed/')
+ rss_proxy('http://www.library.upenn.edu/blogs/libraries-news/category/Collections/rss.xml')
end
end
diff --git a/app/controllers/franklin_alma_controller.rb b/app/controllers/franklin_alma_controller.rb
index a915198b..c056e8b2 100644
--- a/app/controllers/franklin_alma_controller.rb
+++ b/app/controllers/franklin_alma_controller.rb
@@ -1,3 +1,4 @@
+require 'json'
#class FranklinAlmaController < BlacklightAlma::AlmaController
class FranklinAlmaController < ApplicationController
@@ -167,6 +168,7 @@ def single_availability
bib_data = bibapi.get_availability([mmsid])
holding_data = nil
holding_map = {}
+ pickupable = false
inventory_type = ''
@@ -182,7 +184,7 @@ def single_availability
# a 'holding_info' value.
unless has_holding_info
holding_data = api_instance.request(api.almaws_v1_bibs.mms_id_holdings_holding_id_items, :get, :mms_id => mmsid, :holding_id => 'ALL', :expand => 'due_date_policy', :user_id => userid)
-
+
[holding_data['items']['item']].flatten.reject(&:nil?).each do |item|
holding_id = item['holding_data']['holding_id']
item_pid = item['item_data']['pid']
@@ -216,14 +218,17 @@ def single_availability
end
.reject(&:nil?)
else
+ ctx = JSON.parse(params[:request_context])
bib_data['availability'][mmsid]['holdings'].each do |holding|
+ holding_pickupable = holding['availability'] == 'available'
+ pickupable = true if holding_pickupable
links = []
- links << "Request to view in reading room" if holding['link_to_aeon']
+ links << "Request to view in reading room" if holding['link_to_aeon'] unless (ctx['hathi_etas'] && ctx['monograph'])
holding['availability'] = availability_status[holding['availability']] || 'Requestable'
if has_holding_info
inventory_type = 'physical'
- holding['location'] = %Q[#{holding['location']} >
#{holding['call_number']}]
+ holding['location'] = %Q[#{holding['location']} >
#{holding['call_number']}]
holding['availability'] = ""
elsif has_portfolio_info
inventory_type = 'electronic'
@@ -241,8 +246,16 @@ def single_availability
if userid == 'GUEST'
holding['availability'] = 'Log in & request below'
else
- holding['availability'] = 'Not on shelf; request below'
+ if suppress_pickup_at_penn(ctx) && session['user_group'] != 'Faculty Express'
+ # we're temporarily disabling all request options for non facex
+ holding['availability'] = 'Not on shelf'
+ else
+ # for non-request-suppressed items and FacEx users, still present the usual link
+ holding['availability'] = 'Not on shelf; request below'
+ end
end
+ elsif holding['availability'] == 'Available' && suppress_pickup_at_penn(ctx)
+ holding['availability'] = 'Restricted (COVID-19)'
end
end
@@ -265,7 +278,8 @@ def single_availability
end
metadata[mmsid][:inventory_type] = inventory_type
- render :json => {"metadata": metadata, "data": table_data}
+ metadata[mmsid][:pickupable] = pickupable
+ render :json => { "metadata": metadata, "data": table_data }
end
def check_requestable(has_holding_info = false)
@@ -322,18 +336,18 @@ def holding_items
while options[:offset] + options[:limit] < response_data['total_record_count']
options[:offset] += options[:limit]
response_data = api_instance.request(api.almaws_v1_bibs.mms_id_holdings_holding_id_items, :get, params.merge(options))
-
+
table_data += response_data['item'].map { |item|
data = item['item_data']
unless(policies.has_key?(data['policy']['value']) || data['base_status']['desc'] != "Item in place" || userid.nil?)
policies[data['policy']['value']] = nil
pids_to_check << [data['pid'], data['policy']['value']]
end
- [data['policy']['value'], data['pid'], data['description'], due_date_policy || data['due_date_policy'], data['base_status']['desc'], data['barcode'], [], params['mms_id'], params['holding_id']]
+ [data['policy']['value'], data['pid'], data['description'], data['base_status']['desc'], data['barcode'], due_date_policy || data['due_date_policy'], [], params['mms_id'], params['holding_id']]
}
end
- pids_to_check.each{ |pid, policy|
+ pids_to_check.each{ |pid, policy|
options = {:user_id => userid, :item_pid => pid}
response_data = api_instance.request(api.almaws_v1_bibs.mms_id_holdings_holding_id_items_item_pid_request_options, :get, params.merge(options))
not_requestable = true
@@ -345,19 +359,28 @@ def holding_items
end
policies[policy] = "/alma/request/?mms_id=%{mms_id}&holding_id=%{holding_id}&item_pid=%{item_pid}" unless not_requestable
}
-
+ suppress = suppress_pickup_at_penn(JSON.parse(params['request_context']))
table_data.each { |item|
policy = item.shift()
request_url = (policies[policy] || '') % params.merge({:item_pid => item[0]})
- item[5] << "Request" unless (request_url.empty? || item[2] != 'Item in place')
+ # TODO: when libraries reopen: remove conditional, Pickup@Penn=>Request
+ item[5] << (suppress ? "" : "Pickup@Penn") unless (request_url.empty? || item[2] != 'Item in place')
}
render :json => {"data": table_data}
end
+ def suppress_pickup_at_penn(ctx)
+ return false unless ctx['monograph']
+ return true unless ctx['pickupable'] != false
+ return true if ctx['hathi_etas'] #|| ctx['hathi_pd']
+ return false
+ end
+
def request_options
userid = session['id'].presence || nil
usergroup = session['user_group'].presence
+ ctx = JSON.parse(params['request_context'])
api_instance = BlacklightAlma::BibsApi.instance
api = api_instance.ezwadl_api[0]
options = {:user_id => userid, :consider_dlr => true}
@@ -373,13 +396,13 @@ def request_options
case option['type']['value']
when 'HOLD'
{
- :option_name => 'Request',
+ :option_name => 'Pickup@Penn',
#:option_url => option['request_url'],
:option_url => "/alma/request?mms_id=#{params['mms_id']}",
:avail_for_physical => true,
:avail_for_electronic => true,
:highlightable => true
- }
+ } unless suppress_pickup_at_penn(ctx) # TODO: when libraries reopen: remove conditional, Pickup@Penn=>Request
when 'GES'
option_url = option['request_url']
if option_url.index('?')
@@ -421,7 +444,7 @@ def request_options
.uniq # Required due to request options API bug returning duplicate options
.sort { |a,b| cmpRequestOptions(a,b) }
# TODO: Remove when GES is updated in Alma & request option API is fixed (again)
- results.reject! { |option|
+ results.reject! { |option|
['Send Penn Libraries a question','Books By Mail'].member?(option[:option_name]) || (option[:option_name] == 'FacultyEXPRESS' && usergroup != 'Faculty Express')
}
@@ -430,7 +453,7 @@ def request_options
results.each { |option|
case option[:option_name]
when 'Suggest Fix / Enhance Record'
- option[:option_name] = "Report Error"
+ option[:option_name] = "Report Cataloging Error"
end
}
@@ -438,8 +461,9 @@ def request_options
:option_name => "Books By Mail",
:option_url => "https://franklin.library.upenn.edu/redir/booksbymail?bibid=#{params['mms_id']}",
:avail_for_physical => true,
- :avail_for_electronic => false
- }) if ['Athenaeum Member','Faculty','Faculty Express','Grad Student','Library Staff'].member?(session['user_group'])
+ :avail_for_electronic => false,
+ :highlightable => true
+ }) if ['Athenaeum Member','Faculty','Faculty Express','Grad Student','Undergraduate Student','Staff','Associate','Retired Library Staff','Library Staff'].member?(session['user_group']) && !suppress_pickup_at_penn(ctx) # suppress for bbm is same as for Pickup@Penn
render :json => results
end
@@ -452,7 +476,7 @@ def request_title?
response_data = api_instance.request(api.almaws_v1_bibs.mms_id_request_options, :get, params.merge(options))
- return (response_data['request_option'] || []).map { |option|
+ return (response_data['request_option'] || []).map { |option|
option['type']['value']
}.member?('HOLD')
end
@@ -465,7 +489,7 @@ def request_item?
response_data = api_instance.request(api.almaws_v1_bibs.mms_id_holdings_holding_id_items_item_pid_request_options, :get, params.merge(options))
- return (response_data['request_option'] || []).map { |option|
+ return (response_data['request_option'] || []).map { |option|
option['type']['value']
}.member?('HOLD')
end
@@ -478,7 +502,7 @@ def load_request
render 'catalog/bad_request'
return
end
-
+
if params['item_pid'].present?
render 'catalog/bad_request' unless request_item?
else
@@ -503,20 +527,21 @@ def load_request
#.reject { |k,v| exclude_libs.member?(k) }
#)
- libraries = { "Annenberg Library" => "AnnenLib",
- "Athenaeum Library" => "AthLib",
- "Biomedical Library" => "BiomLib",
- "Chemistry Library" => "ChemLib",
- "Dental Medicine Library" => "DentalLib",
- "Fisher Fine Arts Library" => "FisherFAL",
- "Library at the Katz Center" => "KatzLib",
- "Math/Physics/Astronomy Library" => "MPALib",
- "Museum Library" => "MuseumLib",
- "Ormandy Music and Media Center" => "MusicLib",
- "Pennsylvania Hospital Library" => "PAHospLib",
- "Van Pelt Library" => "VanPeltLib",
- "Veterinary Library - New Bolton Center" => "VetNBLib",
- "Veterinary Library - Penn Campus" => "VetPennLib"
+ # Uncomment these as more libraries open up as delivery options
+ libraries = { #"Annenberg Library" => "AnnenLib",
+ #"Athenaeum Library" => "AthLib",
+ #"Biomedical Library" => "BiomLib",
+ #"Chemistry Library" => "ChemLib",
+ #"Dental Medicine Library" => "DentalLib",
+ #"Fisher Fine Arts Library" => "FisherFAL",
+ #"Library at the Katz Center" => "KatzLib",
+ #"Math/Physics/Astronomy Library" => "MPALib",
+ #"Museum Library" => "MuseumLib",
+ #"Ormandy Music and Media Center" => "MusicLib",
+ #"Pennsylvania Hospital Library" => "PAHospLib",
+ "Van Pelt Library" => "VanPeltLib"
+ #"Veterinary Library - New Bolton Center" => "VetNBLib",
+ #"Veterinary Library - Penn Campus" => "VetPennLib"
}
if params['item_pid'].present?
@@ -538,7 +563,7 @@ def create_request
render 'catalog/bad_request'
return
end
-
+
if params['item_pid'].present?
render 'catalog/bad_request' unless request_item?
else
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 4e7a0ebd..fbe072ff 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -9,17 +9,24 @@ def summon_url(query, proxy = false)
end
end
- def databases_results_url(query)
- if !params.dig('f', 'format_f')&.include?('Database & Article Index')
- url = path_for_facet('format_f', 'Database & Article Index')
- end
- return url
+ # Path for a BL catalog index page with Databases facet applied
+ # @return [String]
+ # @param [String] query param
+ def databases_results_path(query)
+ search_catalog_path params: {
+ q: query, utf8: '✓', search_field: 'keyword',
+ 'f[format_f][]': 'Database & Article Index'
+ }
end
def google_site_search_results_url(query)
return "https://www.library.upenn.edu/search/web-pages?q=#{query}"
end
+ def colenda_search_results_url(query)
+ return "https://colenda.library.upenn.edu/catalog?q=#{query}"
+ end
+
def catalog_results_url(query)
return search_catalog_path(q: query, search_field: 'keyword')
end
@@ -62,6 +69,10 @@ def render_tab_link(tab_id, tab_label, anchor, url, data_target)
attrs = {
'href': "http://www.library.upenn.edu/search/web-pages"
}
+ elsif tab_id == 'colenda' && action_name == 'landing'
+ attrs = {
+ 'href': "https://colenda.library.upenn.edu"
+ }
else
attrs = {
'href': anchor,
@@ -98,8 +109,18 @@ def my_library_card_url
"https://#{ ENV['ALMA_DELIVERY_DOMAIN'] }/discovery/account?vid=#{ ENV['ALMA_INSTITUTION_CODE'] }:Services&lang=en§ion=overview"
end
- def profile_url(name)
- "https://www.library.upenn.edu/people/staff/#{name.downcase.gsub(/\ +/, '-')}"
+ def subject_url(subject)
+ "https://www.library.upenn.edu/people/subject-specialists##{subject.dasherize}"
+ end
+
+ def bolded_subject_list(subjects, match)
+ subjects.map do |s|
+ if match.downcase.gsub(/[^a-z]|amp/, '') == s.downcase.gsub(/[^a-z]/, '')
+ content_tag(:strong, s)
+ else
+ s
+ end
+ end
end
def refworks_bookmarks_path(opts = {})
@@ -201,5 +222,4 @@ def prepopulated_search_fields_for_advanced_search(num_fields, is_numeric: true,
def resourcesharing_path
'/forms/resourcesharing'
end
-
end
diff --git a/app/helpers/blacklight_helper.rb b/app/helpers/blacklight_helper.rb
index 781ec4bd..51badd0b 100644
--- a/app/helpers/blacklight_helper.rb
+++ b/app/helpers/blacklight_helper.rb
@@ -10,16 +10,25 @@ def render_search_bar
end
def render_expert_help(specialists)
- specialists.present? && specialists.items.first.hits > 50000 ? (render partial: 'catalog/expert_help', locals: {subject: specialists.items.first.value}) : (render partial: 'catalog/ask')
+ if specialists.present? && specialists.items.first.hits > 50000
+ subject = specialists.items.first.value
+ specialist_data = PennLib::SubjectSpecialists.data
+ end
+ if specialist_data
+ specialist = specialist_data[subject.to_sym].sample
+ render partial: 'catalog/expert_help', locals: { specialist: specialist, subject: subject }
+ else
+ render partial: 'catalog/ask'
+ end
end
# override so that we can insert separators
- def search_fields
+ def search_fields
super.map do |option|
field_def = blacklight_config.search_fields[option[1]]
separator = (field_def && field_def.separator_beneath) ?
- [ '--------', '--------', { disabled: 'true', class: 'hidden-xs' } ] : nil
- [ option, separator].compact
+ [ '--------', '--------', { disabled: 'true', class: 'hidden-xs' } ] : nil
+ [option, separator].compact
end.flatten(1)
end
diff --git a/app/helpers/document_render_helper.rb b/app/helpers/document_render_helper.rb
index 6d68bd4a..639ae6f3 100644
--- a/app/helpers/document_render_helper.rb
+++ b/app/helpers/document_render_helper.rb
@@ -51,31 +51,75 @@ def render_electronic_holdings_links(electronic_holdings_str)
end
end
+ @@HATHI_PD_TEXT = 'HathiTrust Digital Library Connect to full text'
+ @@HATHI_TMP_TEXT = 'HathiTrust Digital Library Login for full text'
+ @@HATHI_REPLACEMENT_TEXT = 'COVID-19 Special Access from HathiTrust'
+ @@HATHI_INFO = ' — Full text access only for students, active faculty, and permanent staff'
+ @@HATHI_LOGIN_PREFIX = 'https://babel.hathitrust.org/Shibboleth.sso/Login?entityID=https://idp.pennkey.upenn.edu/idp/shibboleth&target=https%3A%2F%2Fbabel.hathitrust.org%2Fcgi%2Fping%2Fpong%3Ftarget%3D'
+
+ def detect_monograph(document)
+ return nil unless (alma_mms_id = document[:alma_mms_id]).presence
+ return nil unless ['a','m'].include?(document.to_marc.leader[7])
+ "