arclight 0.0.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.all-contributorsrc +450 -0
- data/.codeclimate.yml +5 -0
- data/.eslintrc +22 -0
- data/.github/workflows/ruby.yml +44 -0
- data/.gitignore +7 -0
- data/.rspec +0 -1
- data/.rubocop.yml +362 -0
- data/.rubocop_todo.yml +122 -0
- data/.solr_wrapper +5 -0
- data/CONTRIBUTING.md +43 -0
- data/CONTRIBUTORS.md +79 -0
- data/Gemfile +41 -0
- data/LICENSE.txt +1 -0
- data/README.md +100 -12
- data/Rakefile +13 -3
- data/app/assets/images/arclight/logo.png +0 -0
- data/app/assets/images/blacklight/bookmark.svg +1 -0
- data/app/assets/images/blacklight/collection.svg +5 -0
- data/app/assets/images/blacklight/compact.svg +1 -0
- data/app/assets/images/blacklight/container.svg +5 -0
- data/app/assets/images/blacklight/ead.svg +1 -0
- data/app/assets/images/blacklight/file.svg +5 -0
- data/app/assets/images/blacklight/folder.svg +1 -0
- data/app/assets/images/blacklight/list.svg +1 -0
- data/app/assets/images/blacklight/minus.svg +1 -0
- data/app/assets/images/blacklight/online.svg +5 -0
- data/app/assets/images/blacklight/pdf.svg +1 -0
- data/app/assets/images/blacklight/plus.svg +1 -0
- data/app/assets/images/blacklight/repository.svg +1 -0
- data/app/assets/javascripts/arclight/arclight.js +4 -0
- data/app/assets/javascripts/arclight/oembed_controller.js +58 -0
- data/app/assets/javascripts/arclight/truncate_controller.js +27 -0
- data/app/assets/stylesheets/arclight/application.scss +14 -0
- data/app/assets/stylesheets/arclight/build.scss +4 -0
- data/app/assets/stylesheets/arclight/modules/collection_search.scss +3 -0
- data/app/assets/stylesheets/arclight/modules/hierarchy_and_online_contents.scss +155 -0
- data/app/assets/stylesheets/arclight/modules/highlights.scss +11 -0
- data/app/assets/stylesheets/arclight/modules/icons.scss +20 -0
- data/app/assets/stylesheets/arclight/modules/layout.scss +220 -0
- data/app/assets/stylesheets/arclight/modules/mastheads.scss +57 -0
- data/app/assets/stylesheets/arclight/modules/repositories.scss +25 -0
- data/app/assets/stylesheets/arclight/modules/repository_card.scss +9 -0
- data/app/assets/stylesheets/arclight/modules/search_form.scss +9 -0
- data/app/assets/stylesheets/arclight/modules/search_results.scss +250 -0
- data/app/assets/stylesheets/arclight/modules/show_collection.scss +38 -0
- data/app/assets/stylesheets/arclight/modules/truncator.scss +58 -0
- data/app/assets/stylesheets/arclight/responsive.scss +13 -0
- data/app/assets/stylesheets/arclight/variables.scss +25 -0
- data/app/components/arclight/access_component.html.erb +14 -0
- data/app/components/arclight/access_component.rb +25 -0
- data/app/components/arclight/bookmark_component.html.erb +25 -0
- data/app/components/arclight/bookmark_component.rb +9 -0
- data/app/components/arclight/breadcrumb_component.rb +40 -0
- data/app/components/arclight/breadcrumbs_hierarchy_component.html.erb +34 -0
- data/app/components/arclight/breadcrumbs_hierarchy_component.rb +25 -0
- data/app/components/arclight/collection_context_component.html.erb +12 -0
- data/app/components/arclight/collection_context_component.rb +27 -0
- data/app/components/arclight/collection_info_component.html.erb +28 -0
- data/app/components/arclight/collection_info_component.rb +26 -0
- data/app/components/arclight/collection_sidebar_component.html.erb +15 -0
- data/app/components/arclight/collection_sidebar_component.rb +39 -0
- data/app/components/arclight/constraints_component.html.erb +7 -0
- data/app/components/arclight/constraints_component.rb +17 -0
- data/app/components/arclight/document_collection_context_component.html.erb +29 -0
- data/app/components/arclight/document_collection_context_component.rb +28 -0
- data/app/components/arclight/document_collection_hierarchy_component.html.erb +50 -0
- data/app/components/arclight/document_collection_hierarchy_component.rb +62 -0
- data/app/components/arclight/document_component.html.erb +39 -0
- data/app/components/arclight/document_component.rb +49 -0
- data/app/components/arclight/document_components_hierarchy_component.html.erb +32 -0
- data/app/components/arclight/document_components_hierarchy_component.rb +28 -0
- data/app/components/arclight/document_download_component.html.erb +24 -0
- data/app/components/arclight/document_download_component.rb +71 -0
- data/app/components/arclight/embed_component.html.erb +10 -0
- data/app/components/arclight/embed_component.rb +43 -0
- data/app/components/arclight/group_component.html.erb +34 -0
- data/app/components/arclight/group_component.rb +23 -0
- data/app/components/arclight/header_component.html.erb +5 -0
- data/app/components/arclight/header_component.rb +10 -0
- data/app/components/arclight/index_metadata_field_component.html.erb +16 -0
- data/app/components/arclight/index_metadata_field_component.rb +20 -0
- data/app/components/arclight/masthead_component.html.erb +15 -0
- data/app/components/arclight/masthead_component.rb +10 -0
- data/app/components/arclight/metadata_section_component.html.erb +13 -0
- data/app/components/arclight/metadata_section_component.rb +22 -0
- data/app/components/arclight/oembed_viewer_component.html.erb +5 -0
- data/app/components/arclight/oembed_viewer_component.rb +16 -0
- data/app/components/arclight/online_content_filter_component.html.erb +15 -0
- data/app/components/arclight/online_content_filter_component.rb +19 -0
- data/app/components/arclight/online_status_indicator_component.rb +19 -0
- data/app/components/arclight/repository_breadcrumb_component.html.erb +10 -0
- data/app/components/arclight/repository_breadcrumb_component.rb +17 -0
- data/app/components/arclight/repository_location_component.html.erb +20 -0
- data/app/components/arclight/repository_location_component.rb +10 -0
- data/app/components/arclight/search_bar_component.html.erb +27 -0
- data/app/components/arclight/search_bar_component.rb +32 -0
- data/app/components/arclight/search_result_breadcrumbs_component.html.erb +6 -0
- data/app/components/arclight/search_result_breadcrumbs_component.rb +37 -0
- data/app/components/arclight/search_result_component.html.erb +20 -0
- data/app/components/arclight/search_result_component.rb +18 -0
- data/app/components/arclight/search_result_title_component.html.erb +15 -0
- data/app/components/arclight/search_result_title_component.rb +15 -0
- data/app/components/arclight/sidebar_component.html.erb +9 -0
- data/app/components/arclight/sidebar_component.rb +19 -0
- data/app/components/arclight/upper_metadata_layout_component.rb +10 -0
- data/app/components/blacklight/icons/bookmark_component.rb +12 -0
- data/app/components/blacklight/icons/collection_component.rb +14 -0
- data/app/components/blacklight/icons/compact_component.rb +12 -0
- data/app/components/blacklight/icons/container_component.rb +14 -0
- data/app/components/blacklight/icons/ead_component.rb +12 -0
- data/app/components/blacklight/icons/file_component.rb +14 -0
- data/app/components/blacklight/icons/folder_component.rb +12 -0
- data/app/components/blacklight/icons/online_component.rb +15 -0
- data/app/components/blacklight/icons/pdf_component.rb +12 -0
- data/app/components/blacklight/icons/repository_component.rb +12 -0
- data/app/controllers/arclight/repositories_controller.rb +40 -0
- data/app/helpers/arclight/ead_format_helpers.rb +309 -0
- data/app/helpers/arclight/field_config_helpers.rb +26 -0
- data/app/helpers/arclight_helper.rb +108 -0
- data/app/models/arclight/document_downloads.rb +122 -0
- data/app/models/arclight/parent.rb +24 -0
- data/app/models/arclight/parents.rb +39 -0
- data/app/models/arclight/requests/aeon_external_request.rb +42 -0
- data/app/models/arclight/requests/aeon_web_ead.rb +52 -0
- data/app/models/arclight/requests/google_form.rb +49 -0
- data/app/models/concerns/arclight/catalog.rb +44 -0
- data/app/models/concerns/arclight/search_behavior.rb +47 -0
- data/app/models/concerns/arclight/solr_document.rb +159 -0
- data/app/presenters/arclight/index_presenter.rb +10 -0
- data/app/presenters/arclight/show_presenter.rb +54 -0
- data/app/views/arclight/.keep +0 -0
- data/app/views/arclight/_requests.html.erb +7 -0
- data/app/views/arclight/repositories/_repository.html.erb +43 -0
- data/app/views/arclight/repositories/index.html.erb +9 -0
- data/app/views/arclight/repositories/show.html.erb +37 -0
- data/app/views/arclight/requests/_aeon_external_request_endpoint.html.erb +8 -0
- data/app/views/arclight/requests/_aeon_web_ead.html.erb +6 -0
- data/app/views/arclight/requests/_google_form.html.erb +10 -0
- data/app/views/catalog/_document_list.html.erb +8 -0
- data/app/views/catalog/_group.html.erb +4 -0
- data/app/views/catalog/_group_toggle.html.erb +10 -0
- data/app/views/catalog/_search_results_header.html.erb +3 -0
- data/app/views/catalog/hierarchy.html.erb +19 -0
- data/app/views/catalog/index.html.erb +17 -0
- data/app/views/shared/_breadcrumbs.html.erb +3 -0
- data/app/views/shared/_main_menu_links.html.erb +6 -0
- data/arclight.gemspec +29 -11
- data/bin/rails +13 -0
- data/config/breadcrumbs.rb +24 -0
- data/config/i18n-tasks.yml +134 -0
- data/config/importmap.rb +3 -0
- data/config/locales/arclight.en.yml +100 -0
- data/config/repositories.yml +0 -0
- data/config/routes.rb +6 -0
- data/docker-compose.yml +16 -0
- data/lib/arclight/digital_object.rb +27 -0
- data/lib/arclight/engine.rb +47 -0
- data/lib/arclight/exceptions.rb +19 -0
- data/lib/arclight/hash_absolute_xpath.rb +62 -0
- data/lib/arclight/level_label.rb +46 -0
- data/lib/arclight/missing_id_strategy.rb +21 -0
- data/lib/arclight/normalized_date.rb +49 -0
- data/lib/arclight/normalized_id.rb +30 -0
- data/lib/arclight/normalized_title.rb +33 -0
- data/lib/arclight/repository.rb +116 -0
- data/lib/arclight/routes/hierarchy.rb +19 -0
- data/lib/arclight/routes.rb +8 -0
- data/lib/arclight/traject/ead2_component_config.rb +334 -0
- data/lib/arclight/traject/ead2_config.rb +315 -0
- data/lib/arclight/traject/nokogiri_namespaceless_reader.rb +22 -0
- data/lib/arclight/version.rb +3 -1
- data/lib/arclight/year_range.rb +111 -0
- data/lib/arclight.rb +11 -1
- data/lib/generators/arclight/install_generator.rb +126 -0
- data/lib/generators/arclight/templates/arclight.scss +5 -0
- data/lib/generators/arclight/templates/catalog_controller.rb +422 -0
- data/lib/generators/arclight/templates/config/downloads.yml +25 -0
- data/lib/generators/arclight/templates/config/locales/arclight.en.yml +61 -0
- data/lib/generators/arclight/templates/config/repositories.yml +53 -0
- data/lib/generators/arclight/update_generator.rb +22 -0
- data/lib/tasks/index.rake +84 -0
- data/package.json +30 -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 +400 -0
- data/solr/conf/solrconfig.xml +328 -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 +72 -0
- data/template.rb +10 -0
- metadata +432 -20
- data/.travis.yml +0 -5
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
##
|
|
4
|
+
# Generic Helpers used in Arclight
|
|
5
|
+
module ArclightHelper
|
|
6
|
+
include Arclight::EadFormatHelpers
|
|
7
|
+
include Arclight::FieldConfigHelpers
|
|
8
|
+
include Blacklight::DocumentHelperBehavior
|
|
9
|
+
include Blacklight::LayoutHelperBehavior
|
|
10
|
+
|
|
11
|
+
def repository_collections_path(repository)
|
|
12
|
+
search_action_url(
|
|
13
|
+
f: {
|
|
14
|
+
repository: [repository.name],
|
|
15
|
+
level: ['Collection']
|
|
16
|
+
}
|
|
17
|
+
)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Returns the i18n-ed string to be used as the h1 in search results
|
|
21
|
+
def search_results_header_text
|
|
22
|
+
if (repo = repository_faceted_on).present?
|
|
23
|
+
t('arclight.search.repository_header', repository: repo.name)
|
|
24
|
+
elsif collection_active?
|
|
25
|
+
t('arclight.search.collections_header')
|
|
26
|
+
else
|
|
27
|
+
t('blacklight.search.header')
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
##
|
|
32
|
+
# Classes used for customized show page in arclight
|
|
33
|
+
def show_content_classes
|
|
34
|
+
'col-12 col-lg-8 show-document order-2'
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def show_sidebar_classes
|
|
38
|
+
'col-lg-4 order-1 collection-sidebar'
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def collection_active?
|
|
42
|
+
search_state.filter('level').values == ['Collection']
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def collection_active_class
|
|
46
|
+
'active' if collection_active?
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def grouped?
|
|
50
|
+
respond_to?(:search_state) && search_state&.params_for_search&.dig('group') == 'true'
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def search_with_group
|
|
54
|
+
search_state.params_for_search.merge('group' => 'true').except('page')
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def search_without_group
|
|
58
|
+
search_state.params_for_search.except('group', 'page')
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def on_repositories_index?
|
|
62
|
+
controller_name == 'repositories' && action_name == 'index'
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# the Repositories menu item is only active on the Repositories index page
|
|
66
|
+
def repositories_active_class
|
|
67
|
+
'active' if on_repositories_index?
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# If we have a facet on the repository, then return the Repository object for it
|
|
71
|
+
#
|
|
72
|
+
# @return [Repository]
|
|
73
|
+
def repository_faceted_on
|
|
74
|
+
repos = search_state.filter('repository').values
|
|
75
|
+
return unless repos.one?
|
|
76
|
+
|
|
77
|
+
Arclight::Repository.find_by(name: repos.first)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# determine which icon to show in search results header
|
|
81
|
+
# these icon names will need to be updated when the icons are determined
|
|
82
|
+
def document_or_parent_icon(document)
|
|
83
|
+
case document.level&.downcase
|
|
84
|
+
when 'collection'
|
|
85
|
+
'collection'
|
|
86
|
+
when 'file'
|
|
87
|
+
'file'
|
|
88
|
+
when 'series', 'subseries'
|
|
89
|
+
'folder'
|
|
90
|
+
else
|
|
91
|
+
'container'
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
##
|
|
96
|
+
# Override of BL core https://github.com/projectblacklight/blacklight/blob/v8.1.0/app/helpers/blacklight/document_helper_behavior.rb#L55
|
|
97
|
+
# Remove document_type check. It isn't a method on arclight documents
|
|
98
|
+
# Check if the document is in the user's bookmarks
|
|
99
|
+
# @param [Blacklight::Document] document
|
|
100
|
+
# @return [Boolean]
|
|
101
|
+
def bookmarked?(document)
|
|
102
|
+
current_bookmarks.any? { |x| x.document_id == document.id }
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def current_context_document
|
|
106
|
+
@document
|
|
107
|
+
end
|
|
108
|
+
end
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Arclight
|
|
4
|
+
##
|
|
5
|
+
# Model the Download links that can be configured (via YAML) for a collection
|
|
6
|
+
# or container
|
|
7
|
+
class DocumentDownloads
|
|
8
|
+
attr_reader :document
|
|
9
|
+
|
|
10
|
+
def initialize(document, id = nil)
|
|
11
|
+
@document = document
|
|
12
|
+
@id = id
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Accessor for the ID
|
|
16
|
+
# @return [String]
|
|
17
|
+
def id
|
|
18
|
+
@id || document.unitid
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Factory method for the File objects
|
|
22
|
+
# @return [Array<Arclight::DocumentDownloads::File>]
|
|
23
|
+
def files
|
|
24
|
+
data = self.class.config[id] || self.class.config['default']
|
|
25
|
+
disabled = data.delete('disabled')
|
|
26
|
+
return [] if disabled
|
|
27
|
+
|
|
28
|
+
@files ||= data.map do |file_type, file_data|
|
|
29
|
+
self.class.file_class.new(type: file_type, data: file_data, document: document)
|
|
30
|
+
end.compact
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
class << self
|
|
34
|
+
def config
|
|
35
|
+
@config ||= begin
|
|
36
|
+
YAML.safe_load(::File.read(config_filename))
|
|
37
|
+
rescue Errno::ENOENT
|
|
38
|
+
{}
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def config_filename
|
|
43
|
+
Rails.root.join('config/downloads.yml')
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Accessor for the File Class
|
|
47
|
+
# @return [Class]
|
|
48
|
+
def file_class
|
|
49
|
+
Arclight::DocumentDownloads::File
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
##
|
|
54
|
+
# Model a single file configured in downloads.yml
|
|
55
|
+
class File
|
|
56
|
+
attr_reader :type, :document
|
|
57
|
+
|
|
58
|
+
def initialize(type:, data:, document:)
|
|
59
|
+
@type = type
|
|
60
|
+
@data = data
|
|
61
|
+
@document = document
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def href
|
|
65
|
+
return data['href'] if data['href']
|
|
66
|
+
|
|
67
|
+
format_template
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def size
|
|
71
|
+
return data['size'] if data['size']
|
|
72
|
+
|
|
73
|
+
document.public_send(data['size_accessor'].to_sym) if data['size_accessor']
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
private
|
|
77
|
+
|
|
78
|
+
attr_reader :data
|
|
79
|
+
|
|
80
|
+
def format_template
|
|
81
|
+
return unless template
|
|
82
|
+
|
|
83
|
+
template % template_interpolations
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def template
|
|
87
|
+
data['template']
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def template_interpolations
|
|
91
|
+
escaped_document_interpolations.merge(custom_interpolations).symbolize_keys
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def custom_interpolations
|
|
95
|
+
{ 'repository_id' => document.repository_config&.slug }
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def template_variables
|
|
99
|
+
template.scan(Regexp.union(/%{(\w+)}/, /%<(\w+)>/)).flatten.compact.uniq
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def escaped_document_interpolations
|
|
103
|
+
non_custom_template_variables.index_with do |method_name|
|
|
104
|
+
escape_non_url_doc_value(document.public_send(method_name))
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def escape_non_url_doc_value(value)
|
|
109
|
+
value = Array.wrap(value).first || '' # Handle single values/arrays and nil
|
|
110
|
+
return value if value.start_with?(/https?:/)
|
|
111
|
+
|
|
112
|
+
CGI.escape(value)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def non_custom_template_variables
|
|
116
|
+
template_variables.reject do |v|
|
|
117
|
+
custom_interpolations.keys.include?(v)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Arclight
|
|
4
|
+
##
|
|
5
|
+
# Logic containing information about Solr_Ead "Parent"
|
|
6
|
+
# https://github.com/awead/solr_ead/blob/8cf7ffaa66e0e4c9c0b12f5646d6c2e20984cd99/lib/solr_ead/behaviors.rb#L54-L57
|
|
7
|
+
class Parent
|
|
8
|
+
attr_reader :id, :label, :eadid, :level
|
|
9
|
+
|
|
10
|
+
alias global_id id
|
|
11
|
+
Arclight.deprecation.deprecate_methods(self, global_id: 'Call `id` instead')
|
|
12
|
+
|
|
13
|
+
def initialize(id:, label:, eadid:, level:)
|
|
14
|
+
@id = id
|
|
15
|
+
@label = label
|
|
16
|
+
@eadid = eadid
|
|
17
|
+
@level = level
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def collection?
|
|
21
|
+
level == 'collection'
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Arclight
|
|
4
|
+
##
|
|
5
|
+
# Object for parsing and formalizing Solr_Ead "Parents"
|
|
6
|
+
# https://github.com/awead/solr_ead/blob/8cf7ffaa66e0e4c9c0b12f5646d6c2e20984cd99/lib/solr_ead/behaviors.rb#L54-L57
|
|
7
|
+
class Parents
|
|
8
|
+
attr_reader :ids, :legacy_ids, :labels, :levels
|
|
9
|
+
|
|
10
|
+
def initialize(ids:, legacy_ids:, labels:, eadid:, levels:)
|
|
11
|
+
@ids = ids
|
|
12
|
+
@legacy_ids = legacy_ids
|
|
13
|
+
@labels = labels
|
|
14
|
+
@eadid = eadid
|
|
15
|
+
@levels = levels
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def eadid
|
|
19
|
+
Arclight::NormalizedId.new(@eadid).to_s
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
##
|
|
23
|
+
# @return [Array[Arclight::Parent]]
|
|
24
|
+
def as_parents
|
|
25
|
+
(ids.presence || legacy_ids).map.with_index { |id, idx| Arclight::Parent.new(id: id, label: labels[idx], eadid: eadid, level: levels[idx]) }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
##
|
|
29
|
+
# @param [SolrDocument] document
|
|
30
|
+
def self.from_solr_document(document)
|
|
31
|
+
ids = document.parent_ids
|
|
32
|
+
legacy_ids = document.legacy_parent_ids.map { |legacy_id| document.collection_id == legacy_id ? legacy_id : "#{document.collection_id}#{legacy_id}" }
|
|
33
|
+
labels = document.parent_labels
|
|
34
|
+
eadid = document.eadid
|
|
35
|
+
levels = document.parent_levels
|
|
36
|
+
new(ids: ids, legacy_ids: legacy_ids, labels: labels, eadid: eadid, levels: levels)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Arclight
|
|
4
|
+
module Requests
|
|
5
|
+
##
|
|
6
|
+
# This class should be used to turn configuration into a URL and
|
|
7
|
+
# POST form specifically aimed at Aeon's external request
|
|
8
|
+
# endpoint (https://support.atlas-sys.com/hc/en-us/articles/360011820054-External-Request-Endpoint)
|
|
9
|
+
class AeonExternalRequest
|
|
10
|
+
def initialize(document, presenter)
|
|
11
|
+
@document = document
|
|
12
|
+
@presenter = presenter
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def config
|
|
16
|
+
@config ||= @document.repository_config.request_config_for_type('aeon_external_request_endpoint')
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def url
|
|
20
|
+
"#{config['request_url']}?#{url_params}"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def form_mapping
|
|
24
|
+
static_mappings.merge(dynamic_mappings)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def static_mappings
|
|
28
|
+
config['request_mappings']['static']
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def dynamic_mappings
|
|
32
|
+
config['request_mappings']['accessor'].transform_values do |v|
|
|
33
|
+
@document.public_send(v.to_sym)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def url_params
|
|
38
|
+
config['request_mappings']['url_params'].to_query
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Arclight
|
|
4
|
+
module Requests
|
|
5
|
+
##
|
|
6
|
+
# This object relies on the ability to respond to attributes passed in as
|
|
7
|
+
# query parameters from the form mapping configuration
|
|
8
|
+
class AeonWebEad
|
|
9
|
+
attr_reader :document, :ead_url
|
|
10
|
+
|
|
11
|
+
##
|
|
12
|
+
# @param [SolrDocument] document
|
|
13
|
+
# @param [String] ead_url
|
|
14
|
+
def initialize(document, ead_url)
|
|
15
|
+
@document = document
|
|
16
|
+
@ead_url = ead_url
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
##
|
|
20
|
+
# Url target for Aeon request params
|
|
21
|
+
def request_url
|
|
22
|
+
request_config['request_url']
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
##
|
|
26
|
+
# Constructed request URL
|
|
27
|
+
def url
|
|
28
|
+
"#{request_url}?#{form_mapping.to_query}"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
##
|
|
32
|
+
# Converts mappings as a query url param into a Hash used for sending
|
|
33
|
+
# messages
|
|
34
|
+
# If a defined method is provided as a value, that method will be invoked
|
|
35
|
+
# "collection_name=entry.123" => { "collection_name" => "entry.123" }
|
|
36
|
+
# @return [Hash]
|
|
37
|
+
def form_mapping
|
|
38
|
+
form_hash = Rack::Utils.parse_nested_query(
|
|
39
|
+
request_config['request_mappings']
|
|
40
|
+
)
|
|
41
|
+
form_hash.each do |key, value|
|
|
42
|
+
respond_to?(value) && form_hash[key] = send(value)
|
|
43
|
+
end
|
|
44
|
+
form_hash
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def request_config
|
|
48
|
+
document.repository_config.request_config_for_type('aeon_web_ead')
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Arclight
|
|
4
|
+
module Requests
|
|
5
|
+
##
|
|
6
|
+
# This object relies on the ability to respond to attributes passed in as
|
|
7
|
+
# query parameters from the form mapping configuratino
|
|
8
|
+
class GoogleForm
|
|
9
|
+
attr_reader :document, :presenter, :document_url
|
|
10
|
+
|
|
11
|
+
delegate :collection_name, :collection_creator, :eadid, :containers, to: :document
|
|
12
|
+
|
|
13
|
+
##
|
|
14
|
+
# @param [SolrDocument] document
|
|
15
|
+
# @param [Arclight::ShowPresenter] presenter
|
|
16
|
+
# @param [String] document_url
|
|
17
|
+
def initialize(document, presenter, document_url)
|
|
18
|
+
@document = document
|
|
19
|
+
@presenter = presenter
|
|
20
|
+
@document_url = document_url
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
##
|
|
24
|
+
# Url of form to fill
|
|
25
|
+
def url
|
|
26
|
+
request_config['request_url']
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
##
|
|
30
|
+
# Converts mappings as a query url param into a Hash used for sending
|
|
31
|
+
# messages and providing pre-filled form fields
|
|
32
|
+
# "collection_name=entry.123" => { "collection_name" => "entry.123" }
|
|
33
|
+
# @return [Hash]
|
|
34
|
+
def form_mapping
|
|
35
|
+
Rack::Utils.parse_nested_query(
|
|
36
|
+
request_config['request_mappings']
|
|
37
|
+
)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def title
|
|
41
|
+
presenter.heading
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def request_config
|
|
45
|
+
document.repository_config&.request_config_for_type('google_form')
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Arclight
|
|
4
|
+
##
|
|
5
|
+
# Arclight specific methods for the Catalog
|
|
6
|
+
module Catalog
|
|
7
|
+
extend ActiveSupport::Concern
|
|
8
|
+
|
|
9
|
+
included do
|
|
10
|
+
before_action only: :index do
|
|
11
|
+
if (params.dig(:f, :collection) || []).any?(&:blank?)
|
|
12
|
+
params[:f][:collection].compact_blank!
|
|
13
|
+
params[:f].delete(:collection) if params[:f][:collection].blank?
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
before_action only: :hierarchy do
|
|
18
|
+
blacklight_config.search_state_fields += %i[id limit offset]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
Blacklight::Configuration.define_field_access :summary_field, Blacklight::Configuration::ShowField
|
|
22
|
+
Blacklight::Configuration.define_field_access :background_field, Blacklight::Configuration::ShowField
|
|
23
|
+
Blacklight::Configuration.define_field_access :related_field, Blacklight::Configuration::ShowField
|
|
24
|
+
Blacklight::Configuration.define_field_access :indexed_terms_field, Blacklight::Configuration::ShowField
|
|
25
|
+
Blacklight::Configuration.define_field_access :in_person_field, Blacklight::Configuration::ShowField
|
|
26
|
+
Blacklight::Configuration.define_field_access :cite_field, Blacklight::Configuration::ShowField
|
|
27
|
+
Blacklight::Configuration.define_field_access :contact_field, Blacklight::Configuration::ShowField
|
|
28
|
+
Blacklight::Configuration.define_field_access :component_field, Blacklight::Configuration::ShowField
|
|
29
|
+
Blacklight::Configuration.define_field_access :component_indexed_terms_field, Blacklight::Configuration::ShowField
|
|
30
|
+
Blacklight::Configuration.define_field_access :terms_field, Blacklight::Configuration::ShowField
|
|
31
|
+
Blacklight::Configuration.define_field_access :component_terms_field, Blacklight::Configuration::ShowField
|
|
32
|
+
Blacklight::Configuration.define_field_access :group_header_field, Blacklight::Configuration::IndexField
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def hierarchy
|
|
36
|
+
@response = search_service.search_results
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Overrides blacklight search state so we can exclude some parameters from being passed into the SearchState
|
|
40
|
+
def search_state
|
|
41
|
+
@search_state ||= search_state_class.new(params.except('hierarchy', 'nest_path'), blacklight_config, self)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Arclight
|
|
4
|
+
##
|
|
5
|
+
# Customized Search Behavior for Arclight
|
|
6
|
+
module SearchBehavior
|
|
7
|
+
extend ActiveSupport::Concern
|
|
8
|
+
|
|
9
|
+
included do
|
|
10
|
+
self.default_processor_chain += %i[
|
|
11
|
+
add_highlighting
|
|
12
|
+
add_grouping
|
|
13
|
+
add_hierarchy_behavior
|
|
14
|
+
]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
|
18
|
+
def add_hierarchy_behavior(solr_parameters)
|
|
19
|
+
return unless search_state.controller&.action_name == 'hierarchy'
|
|
20
|
+
|
|
21
|
+
solr_parameters[:fq] ||= []
|
|
22
|
+
solr_parameters[:fq] << "_nest_parent_:#{blacklight_params[:id]}"
|
|
23
|
+
solr_parameters[:rows] = blacklight_params[:per_page]&.to_i || blacklight_params[:limit]&.to_i || 999_999_999
|
|
24
|
+
solr_parameters[:start] = blacklight_params[:offset] if blacklight_params[:offset]
|
|
25
|
+
solr_parameters[:sort] = 'sort_isi asc'
|
|
26
|
+
solr_parameters[:facet] = false
|
|
27
|
+
end
|
|
28
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
|
29
|
+
|
|
30
|
+
##
|
|
31
|
+
# Add highlighting
|
|
32
|
+
def add_highlighting(solr_params)
|
|
33
|
+
solr_params['hl'] = true
|
|
34
|
+
solr_params['hl.fl'] = CatalogController.blacklight_config.highlight_field
|
|
35
|
+
solr_params['hl.snippets'] = 3
|
|
36
|
+
solr_params
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
##
|
|
40
|
+
# Adds grouping parameters for Solr if enabled
|
|
41
|
+
def add_grouping(solr_params)
|
|
42
|
+
solr_params.merge!(Arclight::Engine.config.catalog_controller_group_query_params) if blacklight_params[:group] == 'true'
|
|
43
|
+
|
|
44
|
+
solr_params
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Arclight
|
|
4
|
+
##
|
|
5
|
+
# Extends Blacklight::Solr::Document to provide Arclight specific behavior
|
|
6
|
+
module SolrDocument
|
|
7
|
+
extend ActiveSupport::Concern
|
|
8
|
+
|
|
9
|
+
included do
|
|
10
|
+
attribute :collection_id, :string, '_root_'
|
|
11
|
+
attribute :parent_ids, :array, 'parent_ids_ssim'
|
|
12
|
+
attribute :legacy_parent_ids, :array, 'parent_ssim'
|
|
13
|
+
Arclight.deprecation.deprecate_methods(self, legacy_parent_ids: 'Use `parent_ids` instead')
|
|
14
|
+
attribute :parent_labels, :array, 'parent_unittitles_ssm'
|
|
15
|
+
attribute :parent_levels, :array, 'parent_levels_ssm'
|
|
16
|
+
attribute :unitid, :string, 'unitid_ssm'
|
|
17
|
+
attribute :extent, :array, 'extent_ssm'
|
|
18
|
+
attribute :abstract, :string, 'abstract_html_tesm'
|
|
19
|
+
attribute :scope, :string, 'scopecontent_html_tesm'
|
|
20
|
+
attribute :creator, :string, 'creator_ssm'
|
|
21
|
+
attribute :level, :string, 'level_ssm'
|
|
22
|
+
attribute :terms, :string, 'userestrict_html_tesm'
|
|
23
|
+
# Restrictions for component sidebar
|
|
24
|
+
attribute :parent_restrictions, :string, 'parent_access_restrict_tesm'
|
|
25
|
+
# Terms for component sidebar
|
|
26
|
+
attribute :parent_terms, :string, 'parent_access_terms_tesm'
|
|
27
|
+
attribute :reference, :string, 'ref_ssm'
|
|
28
|
+
attribute :normalized_title, :string, 'normalized_title_ssm'
|
|
29
|
+
attribute :normalized_date, :string, 'normalized_date_ssm'
|
|
30
|
+
attribute :total_component_count, :string, 'total_component_count_is'
|
|
31
|
+
attribute :online_item_count, :string, 'online_item_count_is'
|
|
32
|
+
attribute :last_indexed, :date, 'timestamp'
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def repository_config
|
|
36
|
+
return unless repository
|
|
37
|
+
|
|
38
|
+
@repository_config ||= Arclight::Repository.find_by(name: repository)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def parents
|
|
42
|
+
@parents ||= Arclight::Parents.from_solr_document(self).as_parents
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Get this document's EAD ID, or fall back to the collection (especially
|
|
46
|
+
# for components that may not have their own.
|
|
47
|
+
def eadid
|
|
48
|
+
first('ead_ssi')&.strip || collection&.first('ead_ssi')&.strip
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def normalized_eadid
|
|
52
|
+
Arclight::NormalizedId.new(eadid).to_s
|
|
53
|
+
end
|
|
54
|
+
Arclight.deprecation.deprecate_methods(self, normalized_eadid: 'Use `collection_id` instead')
|
|
55
|
+
|
|
56
|
+
def repository
|
|
57
|
+
first('repository_ssm') || collection&.first('repository_ssm')
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def repository_and_unitid
|
|
61
|
+
[repository, unitid].compact.join(': ')
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# @return [SolrDocument] a SolrDocument representing the EAD collection
|
|
65
|
+
# that this document belongs to
|
|
66
|
+
def collection
|
|
67
|
+
return self if collection?
|
|
68
|
+
|
|
69
|
+
@collection ||= self.class.new(self['collection']&.dig('docs', 0), @response)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def collection_name
|
|
73
|
+
collection&.normalized_title
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def collection_unitid
|
|
77
|
+
collection&.unitid
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def abstract_or_scope
|
|
81
|
+
abstract || scope
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def collection_creator
|
|
85
|
+
collection&.creator
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def online_content?
|
|
89
|
+
first('has_online_content_ssim') == 'true'
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def number_of_children
|
|
93
|
+
first('child_component_count_isi') || 0
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def children?
|
|
97
|
+
number_of_children.positive?
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def component_level
|
|
101
|
+
first('component_level_isim')
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def collection?
|
|
105
|
+
level&.parameterize == 'collection'
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def digital_objects
|
|
109
|
+
digital_objects_field = fetch('digital_objects_ssm', []).reject(&:empty?)
|
|
110
|
+
return [] if digital_objects_field.blank?
|
|
111
|
+
|
|
112
|
+
digital_objects_field.map do |object|
|
|
113
|
+
Arclight::DigitalObject.from_json(object)
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def containers
|
|
118
|
+
# NOTE: Keep uppercase characters if present, but upcase the first if not already
|
|
119
|
+
containers_field = fetch('containers_ssim', []).reject(&:empty?)
|
|
120
|
+
return [] if containers_field.blank?
|
|
121
|
+
|
|
122
|
+
containers_field.map do |container|
|
|
123
|
+
container.dup.sub!(/\A./, &:upcase)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# @return [Array<String>] with embedded highlights using <em>...</em>
|
|
128
|
+
def highlights
|
|
129
|
+
highlight_field(CatalogController.blacklight_config.highlight_field)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Factory method for constructing the Object modeling downloads
|
|
133
|
+
# @return [DocumentDownloads]
|
|
134
|
+
def downloads
|
|
135
|
+
@downloads ||= DocumentDownloads.new(self)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def ead_file
|
|
139
|
+
@ead_file ||= begin
|
|
140
|
+
files = Arclight::DocumentDownloads.new(self, collection_unitid).files
|
|
141
|
+
files.find do |file|
|
|
142
|
+
file.type == 'ead'
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def nest_path
|
|
148
|
+
self['_nest_path_']
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def root
|
|
152
|
+
self['_root_'] || self['id']
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def requestable?
|
|
156
|
+
repository_config&.request_types&.any?
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end
|