arclight 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.eslintrc +12 -0
- data/.gitignore +5 -0
- data/.rubocop.yml +66 -0
- data/.solr_wrapper +5 -0
- data/.travis.yml +30 -2
- data/CONTRIBUTING.md +43 -0
- data/Gemfile +36 -0
- data/LICENSE.txt +1 -0
- data/README.md +85 -12
- data/Rakefile +14 -3
- data/app/assets/images/blacklight/compact.svg +25 -0
- data/app/assets/images/blacklight/logo.png +0 -0
- data/app/assets/javascripts/arclight/arclight.js +9 -0
- data/app/assets/javascripts/arclight/collection_context.js +18 -0
- data/app/assets/javascripts/arclight/collection_navigation.js +114 -0
- data/app/assets/javascripts/arclight/collection_scrollspy.js +6 -0
- data/app/assets/javascripts/arclight/component_ancestors.js +56 -0
- data/app/assets/javascripts/arclight/oembed_viewer.js +39 -0
- data/app/assets/javascripts/arclight/truncator.js.erb +23 -0
- data/app/assets/stylesheets/arclight/application.scss +13 -0
- data/app/assets/stylesheets/arclight/bootstrap_overrides.scss +3 -0
- data/app/assets/stylesheets/arclight/modules/collection_search.scss +3 -0
- data/app/assets/stylesheets/arclight/modules/hierarchy_and_online_contents.scss +174 -0
- data/app/assets/stylesheets/arclight/modules/highlights.scss +10 -0
- data/app/assets/stylesheets/arclight/modules/layout.scss +33 -0
- data/app/assets/stylesheets/arclight/modules/mastheads.scss +60 -0
- data/app/assets/stylesheets/arclight/modules/repositories.scss +29 -0
- data/app/assets/stylesheets/arclight/modules/repository_card.scss +54 -0
- data/app/assets/stylesheets/arclight/modules/search_results.scss +75 -0
- data/app/assets/stylesheets/arclight/modules/show_collection.scss +78 -0
- data/app/assets/stylesheets/arclight/modules/sidebar.scss +16 -0
- data/app/assets/stylesheets/arclight/variables.scss +2 -0
- data/app/controllers/arclight/repositories_controller.rb +40 -0
- data/app/controllers/concerns/arclight/field_config_helpers.rb +86 -0
- data/app/factories/blacklight_field_configuration_factory.rb +29 -0
- data/app/helpers/arclight_helper.rb +173 -0
- data/app/models/arclight/parent.rb +24 -0
- data/app/models/arclight/parents.rb +34 -0
- data/app/models/arclight/requests/google_form.rb +44 -0
- data/app/models/concerns/arclight/catalog.rb +22 -0
- data/app/models/concerns/arclight/search_behavior.rb +46 -0
- data/app/models/concerns/arclight/solr_document.rb +131 -0
- data/app/presenters/arclight/index_presenter.rb +10 -0
- data/app/presenters/arclight/show_presenter.rb +27 -0
- data/app/views/arclight/.keep +0 -0
- data/app/views/arclight/repositories/_in_person_repository.html.erb +19 -0
- data/app/views/arclight/repositories/_repository.html.erb +62 -0
- data/app/views/arclight/repositories/index.html.erb +4 -0
- data/app/views/arclight/repositories/show.html.erb +38 -0
- data/app/views/arclight/requests/_google_form.html.erb +11 -0
- data/app/views/arclight/viewers/_oembed.html.erb +7 -0
- data/app/views/catalog/_arclight_document_index_header.html.erb +13 -0
- data/app/views/catalog/_arclight_document_index_header_hierarchy_default.html.erb +0 -0
- data/app/views/catalog/_arclight_document_index_header_online_contents_default.html.erb +0 -0
- data/app/views/catalog/_arclight_document_show_header.html.erb +15 -0
- data/app/views/catalog/_arclight_document_show_header_collection.html.erb +12 -0
- data/app/views/catalog/_arclight_index_compact_default.html.erb +15 -0
- data/app/views/catalog/_arclight_online_content_indicator.html.erb +5 -0
- data/app/views/catalog/_arclight_rangelimit.html.erb +24 -0
- data/app/views/catalog/_arclight_viewer_default.html.erb +1 -0
- data/app/views/catalog/_collection_contents.html.erb +12 -0
- data/app/views/catalog/_collection_count.html.erb +7 -0
- data/app/views/catalog/_collection_downloads.html.erb +17 -0
- data/app/views/catalog/_collection_online_contents.html.erb +17 -0
- data/app/views/catalog/_collection_overview.html.erb +7 -0
- data/app/views/catalog/_component_overview.html.erb +46 -0
- data/app/views/catalog/_context_card.html.erb +27 -0
- data/app/views/catalog/_context_sidebar.html.erb +8 -0
- data/app/views/catalog/_custom_metadata.html.erb +16 -0
- data/app/views/catalog/_home.html.erb +1 -0
- data/app/views/catalog/_index_breadcrumb_default.html.erb +3 -0
- data/app/views/catalog/_index_default.html.erb +17 -0
- data/app/views/catalog/_index_header.html.erb +7 -0
- data/app/views/catalog/_index_header_hierarchy_default.html.erb +42 -0
- data/app/views/catalog/_index_header_online_contents_default.html.erb +1 -0
- data/app/views/catalog/_index_hierarchy_default.html.erb +28 -0
- data/app/views/catalog/_index_online_contents_default.html.erb +6 -0
- data/app/views/catalog/_results_histogram.html.erb +10 -0
- data/app/views/catalog/_search_results.html.erb +31 -0
- data/app/views/catalog/_search_results_repository.html.erb +6 -0
- data/app/views/catalog/_search_within_form.html.erb +16 -0
- data/app/views/catalog/_show_breadcrumbs_default.html.erb +7 -0
- data/app/views/catalog/_show_collection.html.erb +40 -0
- data/app/views/catalog/_show_component_sidebar.html.erb +12 -0
- data/app/views/catalog/_show_default.html.erb +32 -0
- data/app/views/catalog/_show_header.html.erb +5 -0
- data/app/views/catalog/_show_sidebar.html.erb +30 -0
- data/app/views/catalog/index.html.erb +8 -0
- data/app/views/layouts/catalog_result.html.erb +7 -0
- data/app/views/shared/_breadcrumbs.html.erb +15 -0
- data/app/views/shared/_context_sidebar.html.erb +8 -0
- data/app/views/shared/_header_navbar.html.erb +54 -0
- data/app/views/shared/_main_menu_links.html.erb +6 -0
- data/arclight.gemspec +17 -4
- data/bin/rails +13 -0
- data/config/locales/arclight.en.yml +65 -0
- data/config/routes.rb +6 -0
- data/lib/arclight.rb +5 -0
- data/lib/arclight/custom_component.rb +98 -0
- data/lib/arclight/custom_document.rb +93 -0
- data/lib/arclight/digital_object.rb +26 -0
- data/lib/arclight/engine.rb +55 -0
- data/lib/arclight/exceptions.rb +18 -0
- data/lib/arclight/indexer.rb +9 -0
- data/lib/arclight/normalized_date.rb +45 -0
- data/lib/arclight/normalized_id.rb +25 -0
- data/lib/arclight/normalized_title.rb +30 -0
- data/lib/arclight/repository.rb +91 -0
- data/lib/arclight/shared_indexing_behavior.rb +97 -0
- data/lib/arclight/shared_terminology_behavior.rb +65 -0
- data/lib/arclight/solr_ead_indexer_ext.rb +159 -0
- data/lib/arclight/version.rb +3 -1
- data/lib/arclight/viewer.rb +45 -0
- data/lib/arclight/viewers/oembed.rb +56 -0
- data/lib/arclight/year_range.rb +102 -0
- data/lib/generators/arclight/install_generator.rb +63 -0
- data/lib/generators/arclight/templates/arclight.js +2 -0
- data/lib/generators/arclight/templates/arclight.scss +3 -0
- data/lib/generators/arclight/templates/catalog_controller.rb +347 -0
- data/lib/generators/arclight/templates/config/downloads.yml +13 -0
- data/lib/generators/arclight/templates/config/repositories.yml +42 -0
- data/lib/generators/arclight/update_generator.rb +22 -0
- data/lib/tasks/index.rake +87 -0
- data/package.json +24 -0
- data/solr/conf/_rest_managed.json +3 -0
- data/solr/conf/admin-extra.html +31 -0
- data/solr/conf/elevate.xml +36 -0
- data/solr/conf/mapping-ISOLatin1Accent.txt +246 -0
- data/solr/conf/protwords.txt +21 -0
- data/solr/conf/schema.xml +631 -0
- data/solr/conf/scripts.conf +24 -0
- data/solr/conf/solrconfig.xml +393 -0
- data/solr/conf/spellings.txt +2 -0
- data/solr/conf/stopwords.txt +58 -0
- data/solr/conf/stopwords_en.txt +58 -0
- data/solr/conf/synonyms.txt +31 -0
- data/solr/conf/xslt/example.xsl +132 -0
- data/solr/conf/xslt/example_atom.xsl +67 -0
- data/solr/conf/xslt/example_rss.xsl +66 -0
- data/solr/conf/xslt/luke.xsl +337 -0
- data/tasks/arclight.rake +68 -0
- data/template.rb +15 -0
- data/vendor/assets/javascripts/responsiveTruncator.js +69 -0
- data/vendor/assets/javascripts/stickyfill.js +480 -0
- metadata +301 -6
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Arclight
|
4
|
+
##
|
5
|
+
# A utility class to normalize dates, typically by joining inclusive and bulk dates
|
6
|
+
# e.g., "1990-2000, bulk 1990-1999"
|
7
|
+
# @see http://www2.archivists.org/standards/DACS/part_I/chapter_2/4_date
|
8
|
+
class NormalizedDate
|
9
|
+
# @param [String | Array<String>] `inclusive` from the `unitdate`
|
10
|
+
# @param [String] `bulk` from the `unitdate`
|
11
|
+
# @param [String] `other` from the `unitdate` when type is not specified
|
12
|
+
def initialize(inclusive, bulk = nil, other = nil)
|
13
|
+
if inclusive.is_a? Array # of YYYY-YYYY for ranges
|
14
|
+
@inclusive = YearRange.new(inclusive.include?('/') ? inclusive : inclusive.map { |v| v.tr('-', '/') }).to_s
|
15
|
+
elsif inclusive.present?
|
16
|
+
@inclusive = inclusive.strip
|
17
|
+
end
|
18
|
+
@bulk = bulk.strip if bulk.present?
|
19
|
+
@other = other.strip if other.present?
|
20
|
+
end
|
21
|
+
|
22
|
+
# @return [String] the normalized title/date
|
23
|
+
def to_s
|
24
|
+
normalize
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
attr_reader :inclusive, :bulk, :other
|
30
|
+
|
31
|
+
# @see http://www2.archivists.org/standards/DACS/part_I/chapter_2/4_date for rules
|
32
|
+
def normalize
|
33
|
+
if inclusive.present?
|
34
|
+
result = inclusive.to_s
|
35
|
+
result << ", bulk #{bulk}" if bulk.present?
|
36
|
+
elsif other.present?
|
37
|
+
result = other.to_s
|
38
|
+
else
|
39
|
+
result = nil
|
40
|
+
end
|
41
|
+
return if result.blank?
|
42
|
+
result.strip
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Arclight
|
4
|
+
##
|
5
|
+
# A simple utility class to normalize identifiers
|
6
|
+
# to be used around the application for linking
|
7
|
+
class NormalizedId
|
8
|
+
def initialize(id)
|
9
|
+
@id = id
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_s
|
13
|
+
normalize
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
attr_reader :id
|
19
|
+
|
20
|
+
def normalize
|
21
|
+
raise Arclight::Exceptions::IDNotFound if id.blank?
|
22
|
+
id.strip.tr('.', '-')
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Arclight
|
4
|
+
##
|
5
|
+
# A utility class to normalize titles, typically by joining
|
6
|
+
# the title and date, e.g., "My Title, 1990-2000"
|
7
|
+
class NormalizedTitle
|
8
|
+
# @param [String] `title` from the `unittitle`
|
9
|
+
# @param [String] `date` from the `unitdate`
|
10
|
+
def initialize(title, date = nil)
|
11
|
+
@title = title.gsub(/\s*,\s*$/, '').strip if title.present?
|
12
|
+
@date = date.strip if date.present?
|
13
|
+
end
|
14
|
+
|
15
|
+
# @return [String] the normalized title/date
|
16
|
+
def to_s
|
17
|
+
normalize
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
attr_reader :title, :date, :default
|
23
|
+
|
24
|
+
def normalize
|
25
|
+
result = [title, date].compact.join(', ')
|
26
|
+
raise Arclight::Exceptions::TitleNotFound if result.blank?
|
27
|
+
result
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Arclight
|
4
|
+
#
|
5
|
+
# Static information about a given repository identified by a unique `slug`
|
6
|
+
#
|
7
|
+
class Repository
|
8
|
+
include ActiveModel::Conversion # for to_partial_path
|
9
|
+
|
10
|
+
FIELDS = %i[name
|
11
|
+
description
|
12
|
+
visit_note
|
13
|
+
building
|
14
|
+
address1
|
15
|
+
address2
|
16
|
+
city
|
17
|
+
state
|
18
|
+
zip
|
19
|
+
country
|
20
|
+
phone
|
21
|
+
contact_info
|
22
|
+
thumbnail_url
|
23
|
+
google_request_url
|
24
|
+
google_request_mappings
|
25
|
+
collection_count].freeze
|
26
|
+
|
27
|
+
attr_accessor :slug, *FIELDS
|
28
|
+
|
29
|
+
# @param [String] `slug` the unique identifier for the repository
|
30
|
+
# @param [Hash] `data`
|
31
|
+
def initialize(slug, data = {})
|
32
|
+
@slug = slug
|
33
|
+
FIELDS.each do |field|
|
34
|
+
value = data[field.to_s]
|
35
|
+
send("#{field}=", value) if value.present?
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# @return [String] handles the formatting of "city, state zip, country"
|
40
|
+
def city_state_zip_country
|
41
|
+
state_zip = state
|
42
|
+
state_zip += " #{zip}" if zip
|
43
|
+
[city, state_zip, country].compact.join(', ')
|
44
|
+
end
|
45
|
+
|
46
|
+
# Load repository information from a YAML file
|
47
|
+
#
|
48
|
+
# @param [String] `filename`
|
49
|
+
# @return [Hash<Slug,Repository>]
|
50
|
+
def self.from_yaml(file)
|
51
|
+
repos = {}
|
52
|
+
data = YAML.safe_load(File.read(file))
|
53
|
+
data.keys.each do |slug|
|
54
|
+
repos[slug] = new(slug, data[slug])
|
55
|
+
end
|
56
|
+
repos
|
57
|
+
end
|
58
|
+
|
59
|
+
# Mimics ActiveRecord's `all` behavior
|
60
|
+
#
|
61
|
+
# @return [Array<Repository>]
|
62
|
+
def self.all
|
63
|
+
from_yaml(ENV['REPOSITORY_FILE'] || 'config/repositories.yml').values
|
64
|
+
end
|
65
|
+
|
66
|
+
# Mimics ActiveRecord dynamic `find_by` behavior for the slug or name
|
67
|
+
#
|
68
|
+
# @param [String] `slug` or `name`
|
69
|
+
# @return [Repository]
|
70
|
+
def self.find_by(slug: nil, name: nil)
|
71
|
+
if slug
|
72
|
+
all.find { |repo| repo.slug == slug }
|
73
|
+
elsif name
|
74
|
+
all.find { |repo| repo.name == name }
|
75
|
+
else
|
76
|
+
raise ArgumentError, 'Requires either slug or name parameters to find_by'
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Mimics ActiveRecord dynamic `find_by!` behavior for the slug or name
|
81
|
+
#
|
82
|
+
# @param [String] `slug` or `name` -- same as `find_by`
|
83
|
+
# @return [Repository]
|
84
|
+
# @raise [ActiveRecord::RecordNotFound] if cannot find repository
|
85
|
+
def self.find_by!(*args)
|
86
|
+
repository = find_by(*args)
|
87
|
+
raise ActiveRecord::RecordNotFound if repository.blank?
|
88
|
+
repository
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Arclight
|
4
|
+
##
|
5
|
+
# A mixin intended to share indexing behavior between
|
6
|
+
# the CustomDocument and CustomComponent classes
|
7
|
+
module SharedIndexingBehavior
|
8
|
+
# @see http://eadiva.com/2/unitdate/
|
9
|
+
# @return [YearRange] all of the years between the given years
|
10
|
+
def unitdate_for_range
|
11
|
+
range = YearRange.new
|
12
|
+
return range if normal_unit_dates.blank?
|
13
|
+
range << range.parse_ranges(normal_unit_dates)
|
14
|
+
range
|
15
|
+
end
|
16
|
+
|
17
|
+
def subjects_array(elements, parent:)
|
18
|
+
xpath_elements = elements.map { |el| "local-name()='#{el}'" }.join(' or ')
|
19
|
+
subjects = search("//#{parent}/controlaccess/*[#{xpath_elements}]").to_a
|
20
|
+
clean_facets_array(subjects.flatten.map(&:text))
|
21
|
+
end
|
22
|
+
|
23
|
+
def names_array(elements, parent:)
|
24
|
+
xpath_elements = elements.map { |el| "local-name()='#{el}'" }.join(' or ')
|
25
|
+
names = search("//#{parent}/controlaccess/*[#{xpath_elements}]").to_a
|
26
|
+
clean_facets_array(names.flatten.map(&:text))
|
27
|
+
end
|
28
|
+
|
29
|
+
# Return a cleaned array of facets without marc subfields
|
30
|
+
#
|
31
|
+
# E.g. clean_facets_array(
|
32
|
+
# ['FacetValue1 |z FacetValue2','FacetValue3']
|
33
|
+
# ) => ['FacetValue1 -- FacetValue2', 'FacetValue3']
|
34
|
+
def clean_facets_array(facets_array)
|
35
|
+
Array(facets_array).map { |text| fix_subfield_demarcators(text) }.compact.uniq
|
36
|
+
end
|
37
|
+
|
38
|
+
# Replace MARC style subfield demarcators
|
39
|
+
#
|
40
|
+
# Usage: fix_subfield_demarcators("Subject 1 |z Sub-Subject 2") => "Subject 1 -- Sub-Subject 2"
|
41
|
+
def fix_subfield_demarcators(value)
|
42
|
+
value.gsub(/\|\w{1}/, '--')
|
43
|
+
end
|
44
|
+
|
45
|
+
# Wrap OM's find_by_xpath for convenience
|
46
|
+
def search(path)
|
47
|
+
find_by_xpath(path) # rubocop:disable DynamicFindBy
|
48
|
+
end
|
49
|
+
|
50
|
+
# If a repository slug is provided via an environment variable `REPOSITORY_ID`,
|
51
|
+
# then use that to lookup the name rather than the parsed out name from the EAD
|
52
|
+
# @param [String] `repository` the default repository name
|
53
|
+
def repository_as_configured(repository)
|
54
|
+
slug = ENV['REPOSITORY_ID']
|
55
|
+
if slug.present?
|
56
|
+
begin
|
57
|
+
Arclight::Repository.find_by(slug: slug).name
|
58
|
+
rescue => e
|
59
|
+
raise "The repository slug '#{slug}' was given but it is not found in the Repository configuration data: #{e}"
|
60
|
+
end
|
61
|
+
else
|
62
|
+
repository
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def add_digital_content(prefix:, solr_doc:)
|
67
|
+
dao = ng_xml.xpath("#{prefix}/dao").to_a
|
68
|
+
return if dao.blank?
|
69
|
+
field_name = Solrizer.solr_name('digital_objects', :displayable)
|
70
|
+
solr_doc[field_name] = digital_objects(dao)
|
71
|
+
end
|
72
|
+
|
73
|
+
def digital_objects(objects)
|
74
|
+
objects.map do |dao|
|
75
|
+
label = dao.attributes['title'].try(:value) || dao.xpath('daodesc/p').try(:text)
|
76
|
+
href = (dao.attributes['href'] || dao.attributes['xlink:href']).try(:value)
|
77
|
+
Arclight::DigitalObject.new(label: label, href: href).to_json
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def add_date_ranges(solr_doc)
|
82
|
+
Solrizer.insert_field(solr_doc, 'date_range', unitdate_for_range.years, :facetable)
|
83
|
+
end
|
84
|
+
|
85
|
+
def add_normalized_title(solr_doc)
|
86
|
+
dates = Arclight::NormalizedDate.new(unitdate_inclusive.first, unitdate_bulk.first, unitdate_other.first).to_s
|
87
|
+
title = Arclight::NormalizedTitle.new(solr_doc['title_ssm'].try(:first), dates).to_s
|
88
|
+
solr_doc['normalized_title_ssm'] = [title]
|
89
|
+
solr_doc['normalized_date_ssm'] = [dates]
|
90
|
+
title
|
91
|
+
end
|
92
|
+
|
93
|
+
def online_content?
|
94
|
+
search('//dao[@href]').present?
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Arclight
|
4
|
+
##
|
5
|
+
# An extendable mixin intended to share terminology behavior between
|
6
|
+
# the CustomDocument and CustomComponent classes
|
7
|
+
module SharedTerminologyBehavior
|
8
|
+
def add_unitid(t, prefix)
|
9
|
+
t.unitid(path: prefix + 'did/unitid', index_as: %i[displayable searchable])
|
10
|
+
end
|
11
|
+
|
12
|
+
def add_extent(t, prefix)
|
13
|
+
t.extent(path: prefix + 'did/physdesc/extent', index_as: %i[displayable searchable])
|
14
|
+
end
|
15
|
+
|
16
|
+
# date indexing
|
17
|
+
def add_dates(t, prefix)
|
18
|
+
t.normal_unit_dates(path: prefix + 'did/unitdate/@normal')
|
19
|
+
t.unitdate_bulk(path: prefix + 'did/unitdate[@type=\'bulk\']', index_as: %i[displayable])
|
20
|
+
t.unitdate_inclusive(path: prefix + 'did/unitdate[@type=\'inclusive\']', index_as: %i[displayable])
|
21
|
+
t.unitdate_other(path: prefix + 'did/unitdate[not(@type)]', index_as: %i[displayable])
|
22
|
+
t.unitdate(path: prefix + 'did/unitdate', index_as: %i[displayable])
|
23
|
+
end
|
24
|
+
|
25
|
+
def add_searchable_notes(t, prefix) # rubocop: disable Metrics/MethodLength
|
26
|
+
# various searchable notes
|
27
|
+
%i[
|
28
|
+
accessrestrict
|
29
|
+
accruals
|
30
|
+
acqinfo
|
31
|
+
altformavail
|
32
|
+
appraisal
|
33
|
+
arrangement
|
34
|
+
bibliography
|
35
|
+
bioghist
|
36
|
+
custodhist
|
37
|
+
fileplan
|
38
|
+
note
|
39
|
+
odd
|
40
|
+
originalsloc
|
41
|
+
otherfindaid
|
42
|
+
phystech
|
43
|
+
prefercite
|
44
|
+
processinfo
|
45
|
+
relatedmaterial
|
46
|
+
scopecontent
|
47
|
+
separatedmaterial
|
48
|
+
userestrict
|
49
|
+
].each do |k|
|
50
|
+
# many of the notes support various markup so we want everything but the heading
|
51
|
+
t.send(k, path: "#{prefix}#{k}/*[local-name()!=\"head\"]", index_as: %i[displayable searchable])
|
52
|
+
end
|
53
|
+
|
54
|
+
# various searchable notes in the did
|
55
|
+
%i[
|
56
|
+
abstract
|
57
|
+
materialspec
|
58
|
+
physloc
|
59
|
+
].each do |k|
|
60
|
+
t.send(k, path: "#{prefix}did/#{k}", index_as: %i[displayable searchable])
|
61
|
+
end
|
62
|
+
t.did_note(path: "#{prefix}did/note", index_as: %i[displayable searchable]) # conflicts with top-level note
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Arclight
|
4
|
+
##
|
5
|
+
# An module to extend SolrEad::Indexer behaviors to allow us to add
|
6
|
+
# or override behaviors that require knowledge of the entire XML document.
|
7
|
+
module SolrEadIndexerExt
|
8
|
+
def additional_component_fields(node, addl_fields = {})
|
9
|
+
solr_doc = super
|
10
|
+
|
11
|
+
add_count_of_child_compontents(node, solr_doc)
|
12
|
+
add_ancestral_titles(node, solr_doc)
|
13
|
+
add_ancestral_ids(node, solr_doc)
|
14
|
+
|
15
|
+
add_collection_creator_to_component(node, solr_doc)
|
16
|
+
|
17
|
+
add_self_or_parents_restrictions(node, solr_doc)
|
18
|
+
|
19
|
+
add_self_or_parents_terms(node, solr_doc)
|
20
|
+
|
21
|
+
solr_doc
|
22
|
+
end
|
23
|
+
|
24
|
+
def delete_all
|
25
|
+
solr.delete_by_query('*:*')
|
26
|
+
solr.commit
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
# Note that we need to redo what solr_ead does for ids due to our normalization process
|
32
|
+
def add_ancestral_ids(node, solr_doc)
|
33
|
+
@parent_id_name ||= Solrizer.solr_name('parent', :stored_sortable)
|
34
|
+
@parent_ids_field_name ||= Solrizer.solr_name('parent', :displayable)
|
35
|
+
@parent_ids_search_field_name ||= Solrizer.solr_name('parent', :searchable)
|
36
|
+
|
37
|
+
ids = ancestral_ids(node)
|
38
|
+
solr_doc[@parent_ids_field_name] = ids
|
39
|
+
solr_doc[@parent_ids_search_field_name] = ids
|
40
|
+
solr_doc[@parent_id_name] = ids.last
|
41
|
+
end
|
42
|
+
|
43
|
+
# Note that we need to redo what solr_ead does for titles due to our normalization process
|
44
|
+
def add_ancestral_titles(node, solr_doc)
|
45
|
+
@parent_titles_field_name ||= Solrizer.solr_name('parent_unittitles', :displayable)
|
46
|
+
@parent_titles_search_field_name ||= Solrizer.solr_name('parent_unittitles', :searchable)
|
47
|
+
@collection_facet_name ||= Solrizer.solr_name('collection', :facetable)
|
48
|
+
@collection_name ||= Solrizer.solr_name('collection', :displayable)
|
49
|
+
|
50
|
+
titles = ancestral_titles(node)
|
51
|
+
solr_doc[@parent_titles_field_name] = titles
|
52
|
+
solr_doc[@parent_titles_search_field_name] = titles
|
53
|
+
solr_doc[@collection_name] = [titles.first] # collection is always on top
|
54
|
+
solr_doc[@collection_facet_name] = [titles.first]
|
55
|
+
end
|
56
|
+
|
57
|
+
def add_count_of_child_compontents(node, solr_doc)
|
58
|
+
@child_component_count_name ||= Solrizer.solr_name('child_component_count', type: :integer)
|
59
|
+
|
60
|
+
solr_doc[@child_component_count_name] = node.xpath('count(c)').to_i
|
61
|
+
end
|
62
|
+
|
63
|
+
def ancestral_ids(node)
|
64
|
+
ancestral_visit(node, :normalized_component_id, :normalized_collection_id)
|
65
|
+
end
|
66
|
+
|
67
|
+
def ancestral_titles(node)
|
68
|
+
ancestral_visit(node, :normalized_component_title, :normalized_collection_title)
|
69
|
+
end
|
70
|
+
|
71
|
+
# visit each component's parent and finish with a visit on the collection
|
72
|
+
def ancestral_visit(node, component_fn, collection_fn, results = [])
|
73
|
+
while node.parent && node.parent.name == 'c'
|
74
|
+
parent = node.parent
|
75
|
+
results << send(component_fn, parent)
|
76
|
+
node = parent
|
77
|
+
end
|
78
|
+
results << send(collection_fn, node)
|
79
|
+
results.reverse
|
80
|
+
end
|
81
|
+
|
82
|
+
def normalized_component_title(node)
|
83
|
+
data = extract_title_and_dates(node)
|
84
|
+
normalize_title(data)
|
85
|
+
end
|
86
|
+
|
87
|
+
def normalized_collection_title(node)
|
88
|
+
data = extract_title_and_dates(node, '//archdesc/')
|
89
|
+
normalize_title(data)
|
90
|
+
end
|
91
|
+
|
92
|
+
def normalize_title(data)
|
93
|
+
Arclight::NormalizedTitle.new(
|
94
|
+
data[:title],
|
95
|
+
Arclight::NormalizedDate.new(
|
96
|
+
data[:unitdate_inclusive],
|
97
|
+
data[:unitdate_bulk],
|
98
|
+
data[:unitdate_other]
|
99
|
+
).to_s
|
100
|
+
).to_s
|
101
|
+
end
|
102
|
+
|
103
|
+
# TODO: these xpaths should be DRY'd up -- they're in both terminologies
|
104
|
+
def extract_title_and_dates(node, prefix = nil)
|
105
|
+
data = {
|
106
|
+
title: node.at_xpath("#{prefix}did/unittitle"),
|
107
|
+
unitdate_inclusive: node.at_xpath("#{prefix}did/unitdate[@type=\"inclusive\"]"),
|
108
|
+
unitdate_bulk: node.at_xpath("#{prefix}did/unitdate[@type=\"bulk\"]"),
|
109
|
+
unitdate_other: node.at_xpath("#{prefix}did/unitdate[not(@type)]")
|
110
|
+
}
|
111
|
+
data.each do |k, v|
|
112
|
+
data[k] = v.text if v
|
113
|
+
end
|
114
|
+
data
|
115
|
+
end
|
116
|
+
|
117
|
+
def normalized_component_id(node)
|
118
|
+
Arclight::NormalizedId.new(node['id'].to_s).to_s
|
119
|
+
end
|
120
|
+
|
121
|
+
def normalized_collection_id(node)
|
122
|
+
Arclight::NormalizedId.new(node.document.at_xpath('//eadid').text).to_s
|
123
|
+
end
|
124
|
+
|
125
|
+
# This mimics similar behavior in Arclight::CustomDocument
|
126
|
+
def add_collection_creator_to_component(node, solr_doc)
|
127
|
+
field_name = Solrizer.solr_name('collection_creator', :displayable)
|
128
|
+
repository = solr_doc[Solrizer.solr_name('repository', :displayable)]
|
129
|
+
creators = node.xpath('//archdesc/did/origination[@label="creator"]/*/text()').map(&:text)
|
130
|
+
solr_doc[field_name] = creators - [repository]
|
131
|
+
end
|
132
|
+
|
133
|
+
def parent_check_list(node, root_path, element_path, results = [])
|
134
|
+
orginal_node = node
|
135
|
+
results = node.xpath("#{root_path}/#{element_path}").map(&:text)
|
136
|
+
# if current restriction return, else go up to parent and check
|
137
|
+
while node.parent.name == 'c' && results.blank?
|
138
|
+
parent = node.parent
|
139
|
+
results = parent.xpath("#{root_path}/#{element_path}").map(&:text)
|
140
|
+
node = parent
|
141
|
+
end
|
142
|
+
# If no parental results, check the collection
|
143
|
+
results = orginal_node.xpath("//archdesc/#{element_path}").map(&:text) if results.blank?
|
144
|
+
results.flatten # can't use with flatten! because that returns nil
|
145
|
+
end
|
146
|
+
|
147
|
+
def add_self_or_parents_restrictions(node, solr_doc)
|
148
|
+
field_name = Solrizer.solr_name('parent_access_restrict', :displayable)
|
149
|
+
solr_doc[field_name] = parent_check_list(node, './', 'accessrestrict/p/text()')
|
150
|
+
solr_doc[field_name]
|
151
|
+
end
|
152
|
+
|
153
|
+
def add_self_or_parents_terms(node, solr_doc)
|
154
|
+
field_name = Solrizer.solr_name('parent_access_terms', :displayable)
|
155
|
+
solr_doc[field_name] = parent_check_list(node, './', 'userestrict/p/text()')
|
156
|
+
solr_doc[field_name]
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|