Skip to content

Commit

Permalink
Merge pull request #4427 from pulibrary/i4012_add_citation_scsb
Browse files Browse the repository at this point in the history
Add citations for SCSB items
  • Loading branch information
sandbergja authored Oct 10, 2024
2 parents e3143b9 + df3938c commit 849803f
Show file tree
Hide file tree
Showing 20 changed files with 715 additions and 15 deletions.
1 change: 1 addition & 0 deletions .reek.yml
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,7 @@ detectors:
- Requests::RequestMailer#service_error_email
- Bookmark#self.destroy_without_solr_documents
- Bookmark#self.update_to_alma_ids
- Blacklight::Document::CiteProc#properties
- Blacklight::Document::DublinCore#export_as_oai_dc_xml
- Blacklight::Document::DublinCore#export_as_rdf_dc
- Blacklight::Document::Email#add_holdings_text
Expand Down
3 changes: 3 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ gem 'bootstrap', '~> 4.6'
# In the Capistrano documentation, it has these limited to the development group, and `require: false``
gem 'capistrano', '~> 3.4'
gem 'capistrano-passenger'
# support for non-marc citations (e.g. SCSB records)
gem 'citeproc-ruby'
gem 'csl-styles'
# Authentication and authorization
gem 'devise'
gem 'devise-guests'
Expand Down
16 changes: 16 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,12 @@ GEM
regexp_parser (>= 1.5, < 3.0)
xpath (~> 3.2)
chronic (0.10.2)
citeproc (1.0.10)
namae (~> 1.0)
citeproc-ruby (2.1.0)
citeproc (~> 1.0, >= 1.0.9)
csl (~> 2.0)
observer (< 1.0)
coderay (1.1.3)
coercible (1.0.0)
descendants_tracker (~> 0.0.1)
Expand All @@ -193,6 +199,11 @@ GEM
bigdecimal
rexml
crass (1.0.6)
csl (2.0.0)
namae (~> 1.0)
rexml
csl-styles (2.0.1)
csl (~> 2.0)
csv (3.3.0)
datadog (2.3.0)
debase-ruby_core_source (= 3.3.1)
Expand Down Expand Up @@ -389,6 +400,8 @@ GEM
msgpack (1.7.3)
multi_xml (0.6.0)
mutex_m (0.2.0)
namae (1.2.0)
racc (~> 1.7)
net-http (0.4.1)
uri
net-imap (0.4.15)
Expand All @@ -414,6 +427,7 @@ GEM
racc (~> 1.4)
nokogiri (1.16.7-x86_64-linux)
racc (~> 1.4)
observer (0.1.2)
omniauth (2.1.2)
hashie (>= 3.4.6)
rack (>= 2.2.3)
Expand Down Expand Up @@ -743,7 +757,9 @@ DEPENDENCIES
capistrano-passenger
capistrano-rails
capybara
citeproc-ruby
coveralls_reborn
csl-styles
datadog
devise
devise-guests
Expand Down
11 changes: 11 additions & 0 deletions app/components/orangelight/document/citation_component.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<div>
<h1 class="modal-title"><%= title %></h1>

<% @formats.each do |i18n_key, citation_method| %>
<h2><%= t(i18n_key) %></h2>
<%= @document.send(citation_method).html_safe %>
<% unless @formats.keys.last === i18n_key %>
<br/><br/>
<% end %>
<% end %>
</div>
13 changes: 13 additions & 0 deletions app/components/orangelight/document/citation_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

class Orangelight::Document::CitationComponent < Blacklight::Document::CitationComponent
DEFAULT_FORMATS = {
'blacklight.citation.mla': :export_as_mla,
'blacklight.citation.apa': :export_as_apa,
'blacklight.citation.chicago': :export_as_chicago
}.freeze

def initialize(document:, formats: DEFAULT_FORMATS)
super
end
end
21 changes: 21 additions & 0 deletions app/models/concerns/blacklight/document/apa.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: true

# Creates an html APA citation for non-Marc records
module Blacklight::Document::Apa
def self.extended(document)
Blacklight::Document::Apa.register_export_formats(document)
end

def self.register_export_formats(document)
document.will_export_as(:apa, 'text/html')
end

def export_as_apa
return export_as_apa_citation_txt if alma?

cp = CiteProc::Processor.new style: 'apa', format: 'html'
item = CiteProc::Item.new(properties)
cp.import(item)
cp.render(:bibliography, id:).first
end
end
21 changes: 21 additions & 0 deletions app/models/concerns/blacklight/document/chicago.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: true

# Creates an html Chicago citation for non-Marc records
module Blacklight::Document::Chicago
def self.extended(document)
Blacklight::Document::Chicago.register_export_formats(document)
end

def self.register_export_formats(document)
document.will_export_as(:chicago, 'text/html')
end

def export_as_chicago
return export_as_chicago_citation_txt if alma?

cp = CiteProc::Processor.new style: 'chicago-author-date', format: 'html'
item = CiteProc::Item.new(properties)
cp.import(item)
cp.render(:bibliography, id:).first
end
end
62 changes: 62 additions & 0 deletions app/models/concerns/blacklight/document/cite_proc.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# frozen_string_literal: true

## Adds the methods needed for CiteProc citations,
# Including MLA, APA, and Chicago
module Blacklight::Document::CiteProc
private

def properties
props = {}
props[:id] = id
props[:edition] = cite_proc_edition if cite_proc_edition
props[:type] = cite_proc_type if cite_proc_type
props[:author] = cite_proc_author if cite_proc_author
props[:title] = cite_proc_title if cite_proc_title
props[:publisher] = cite_proc_publisher if cite_proc_publisher
props[:'publisher-place'] = cite_proc_publisher_place if cite_proc_publisher_place
props[:issued] = cite_proc_issued if cite_proc_issued
props
end

def cite_proc_type
self[:format]&.first&.downcase
end

def cite_proc_author
@cite_proc_author ||= begin
family, given = citation_fields_from_solr[:author_citation_display]&.first&.split(', ')
CiteProc::Name.new(family:, given:) if family || given
end
end

def cite_proc_edition
@cite_proc_edition ||= begin
str = citation_fields_from_solr[:edition_display]&.first
str&.dup&.sub!(/[[:punct:]]?$/, '')
end
end

def cite_proc_title
@cite_proc_title ||= citation_fields_from_solr[:title_citation_display]&.first
end

def cite_proc_publisher
@cite_proc_publisher ||= citation_fields_from_solr[:pub_citation_display]&.first&.split(': ').try(:[], 1)
end

def cite_proc_publisher_place
@cite_proc_publisher_place ||= citation_fields_from_solr[:pub_citation_display]&.first&.split(': ').try(:[], 0)
end

def cite_proc_issued
@cite_proc_issued ||= citation_fields_from_solr[:pub_date_start_sort]
end

def citation_fields_from_solr
@citation_fields_from_solr ||= begin
params = { q: "id:#{RSolr.solr_escape(id)}", fl: "author_citation_display, title_citation_display, pub_citation_display, number_of_pages_citation_display, pub_date_start_sort, edition_display" }
solr_response = Blacklight.default_index.connection.get('select', params:)
solr_response["response"]["docs"].first.with_indifferent_access
end
end
end
21 changes: 21 additions & 0 deletions app/models/concerns/blacklight/document/mla.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: true

# Creates an html MLA citation for non-Marc records
module Blacklight::Document::Mla
def self.extended(document)
Blacklight::Document::Mla.register_export_formats(document)
end

def self.register_export_formats(document)
document.will_export_as(:mla, 'text/html')
end

def export_as_mla
return export_as_mla_citation_txt if alma?

cp = CiteProc::Processor.new style: 'modern-language-association', format: 'html'
item = CiteProc::Item.new(properties)
cp.import(item)
cp.render(:bibliography, id:).first
end
end
13 changes: 13 additions & 0 deletions app/models/solr_document.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,19 @@ class SolrDocument
## Adds JSON-LD
use_extension(Blacklight::Document::JsonLd)

## Adds the methods needed for CiteProc citations,
# Including MLA, APA, and Chicago
use_extension(Blacklight::Document::CiteProc)

## Adds MLA html
use_extension(Blacklight::Document::Mla)

# Adds APA html
use_extension(Blacklight::Document::Apa)

# Adds Chicago html
use_extension(Blacklight::Document::Chicago)

def identifier_data
values = identifiers.each_with_object({}) do |identifier, hsh|
hsh[identifier.data_key.to_sym] ||= []
Expand Down
4 changes: 4 additions & 0 deletions app/views/catalog/_citation.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<%= render Blacklight::System::ModalComponent.new do |component| %>
<% component.with_title { t('blacklight.tools.citation') } %>
<%= render Orangelight::Document::CitationComponent.with_collection(@documents) if @documents.present? %>
<% end %>
2 changes: 1 addition & 1 deletion app/views/catalog/_previous_next_doc.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
</div>
<div class="search-widgets col pr-4">
<ul class="navbar navbar-nav pull-right">
<% if @document.alma_record? %>
<% if @document.alma_record? || @document.scsb_record? %>
<li>
<%= render_cite_link(citation_solr_document_path(id: @document)) %>
</li>
Expand Down
18 changes: 18 additions & 0 deletions spec/components/orangelight/document/citation_component_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

require "rails_helper"

RSpec.describe Orangelight::Document::CitationComponent, type: :component, citation: true do
let(:document) { SolrDocument.new(properties) }
let(:properties) do
{
id: 'SCSB-2635660',
author_citation_display: ["Saer, Juan José"]
}
end
let(:component) { described_class.new(document:) }

it 'can be rendered' do
expect(render_inline(component).to_s).to include('Saer')
end
end
46 changes: 33 additions & 13 deletions spec/features/citation_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,43 @@

require 'rails_helper'

describe 'citation' do
describe 'citation', citation: true do
before do
allow_any_instance_of(CatalogController).to receive(:agent_is_crawler?).and_return(false)
end
it 'will render successfully even if there is not a subfield a' do
stub_request(:get, "#{Requests.config['bibdata_base']}/bibliographic/9979948663506421")
.with(
headers: {
'Accept' => '*/*',
'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
'User-Agent' => 'Faraday v0.17.4'
}
context 'with an alma marcxml record' do
let(:bibid) { '9979948663506421' }
let(:marc_xml) { File.read(File.join(File.dirname(__FILE__), '..', 'fixtures', 'bibdata', "#{bibid}.xml")) }

before do
stub_request(:get, "#{Requests.config['bibdata_base']}/bibliographic/#{bibid}").to_return(
status: 200,
body: marc_xml
)
.to_return(status: 200, body: "", headers: {})
end
it 'will render successfully even if there is not a subfield a' do
visit '/catalog/9979948663506421/citation'
expect(current_url).to include '/catalog/9979948663506421/citation'
expect(page.status_code).to eq 200
end

it 'renders the citation' do
visit '/catalog/9979948663506421/citation'
expect(page.body).to include('Henderson, W. J, et al.')
end
end

context 'with a scsb record' do
let(:bibid) { 'SCSB-2635660' }
before do
stub_request(:get, "#{Requests.config['bibdata_base']}/bibliographic/#{bibid}")
.to_return(status: 404)
end

visit '/catalog/9979948663506421/citation'
expect(current_url).to include '/catalog/9979948663506421/citation'
expect(page.status_code).to eq 200
it 'renders the citation' do
visit "/catalog/#{bibid}/citation"
expect(current_url).to include("/catalog/#{bibid}/citation")
expect(page.body).to include('Juan José. <i>El Entenado</i>. 1A edición, Destino, 1988.')
end
end
end
Loading

0 comments on commit 849803f

Please sign in to comment.