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.
Files changed (202) hide show
  1. checksums.yaml +5 -5
  2. data/.all-contributorsrc +450 -0
  3. data/.codeclimate.yml +5 -0
  4. data/.eslintrc +22 -0
  5. data/.github/workflows/ruby.yml +44 -0
  6. data/.gitignore +7 -0
  7. data/.rspec +0 -1
  8. data/.rubocop.yml +362 -0
  9. data/.rubocop_todo.yml +122 -0
  10. data/.solr_wrapper +5 -0
  11. data/CONTRIBUTING.md +43 -0
  12. data/CONTRIBUTORS.md +79 -0
  13. data/Gemfile +41 -0
  14. data/LICENSE.txt +1 -0
  15. data/README.md +100 -12
  16. data/Rakefile +13 -3
  17. data/app/assets/images/arclight/logo.png +0 -0
  18. data/app/assets/images/blacklight/bookmark.svg +1 -0
  19. data/app/assets/images/blacklight/collection.svg +5 -0
  20. data/app/assets/images/blacklight/compact.svg +1 -0
  21. data/app/assets/images/blacklight/container.svg +5 -0
  22. data/app/assets/images/blacklight/ead.svg +1 -0
  23. data/app/assets/images/blacklight/file.svg +5 -0
  24. data/app/assets/images/blacklight/folder.svg +1 -0
  25. data/app/assets/images/blacklight/list.svg +1 -0
  26. data/app/assets/images/blacklight/minus.svg +1 -0
  27. data/app/assets/images/blacklight/online.svg +5 -0
  28. data/app/assets/images/blacklight/pdf.svg +1 -0
  29. data/app/assets/images/blacklight/plus.svg +1 -0
  30. data/app/assets/images/blacklight/repository.svg +1 -0
  31. data/app/assets/javascripts/arclight/arclight.js +4 -0
  32. data/app/assets/javascripts/arclight/oembed_controller.js +58 -0
  33. data/app/assets/javascripts/arclight/truncate_controller.js +27 -0
  34. data/app/assets/stylesheets/arclight/application.scss +14 -0
  35. data/app/assets/stylesheets/arclight/build.scss +4 -0
  36. data/app/assets/stylesheets/arclight/modules/collection_search.scss +3 -0
  37. data/app/assets/stylesheets/arclight/modules/hierarchy_and_online_contents.scss +155 -0
  38. data/app/assets/stylesheets/arclight/modules/highlights.scss +11 -0
  39. data/app/assets/stylesheets/arclight/modules/icons.scss +20 -0
  40. data/app/assets/stylesheets/arclight/modules/layout.scss +220 -0
  41. data/app/assets/stylesheets/arclight/modules/mastheads.scss +57 -0
  42. data/app/assets/stylesheets/arclight/modules/repositories.scss +25 -0
  43. data/app/assets/stylesheets/arclight/modules/repository_card.scss +9 -0
  44. data/app/assets/stylesheets/arclight/modules/search_form.scss +9 -0
  45. data/app/assets/stylesheets/arclight/modules/search_results.scss +250 -0
  46. data/app/assets/stylesheets/arclight/modules/show_collection.scss +38 -0
  47. data/app/assets/stylesheets/arclight/modules/truncator.scss +58 -0
  48. data/app/assets/stylesheets/arclight/responsive.scss +13 -0
  49. data/app/assets/stylesheets/arclight/variables.scss +25 -0
  50. data/app/components/arclight/access_component.html.erb +14 -0
  51. data/app/components/arclight/access_component.rb +25 -0
  52. data/app/components/arclight/bookmark_component.html.erb +25 -0
  53. data/app/components/arclight/bookmark_component.rb +9 -0
  54. data/app/components/arclight/breadcrumb_component.rb +40 -0
  55. data/app/components/arclight/breadcrumbs_hierarchy_component.html.erb +34 -0
  56. data/app/components/arclight/breadcrumbs_hierarchy_component.rb +25 -0
  57. data/app/components/arclight/collection_context_component.html.erb +12 -0
  58. data/app/components/arclight/collection_context_component.rb +27 -0
  59. data/app/components/arclight/collection_info_component.html.erb +28 -0
  60. data/app/components/arclight/collection_info_component.rb +26 -0
  61. data/app/components/arclight/collection_sidebar_component.html.erb +15 -0
  62. data/app/components/arclight/collection_sidebar_component.rb +39 -0
  63. data/app/components/arclight/constraints_component.html.erb +7 -0
  64. data/app/components/arclight/constraints_component.rb +17 -0
  65. data/app/components/arclight/document_collection_context_component.html.erb +29 -0
  66. data/app/components/arclight/document_collection_context_component.rb +28 -0
  67. data/app/components/arclight/document_collection_hierarchy_component.html.erb +50 -0
  68. data/app/components/arclight/document_collection_hierarchy_component.rb +62 -0
  69. data/app/components/arclight/document_component.html.erb +39 -0
  70. data/app/components/arclight/document_component.rb +49 -0
  71. data/app/components/arclight/document_components_hierarchy_component.html.erb +32 -0
  72. data/app/components/arclight/document_components_hierarchy_component.rb +28 -0
  73. data/app/components/arclight/document_download_component.html.erb +24 -0
  74. data/app/components/arclight/document_download_component.rb +71 -0
  75. data/app/components/arclight/embed_component.html.erb +10 -0
  76. data/app/components/arclight/embed_component.rb +43 -0
  77. data/app/components/arclight/group_component.html.erb +34 -0
  78. data/app/components/arclight/group_component.rb +23 -0
  79. data/app/components/arclight/header_component.html.erb +5 -0
  80. data/app/components/arclight/header_component.rb +10 -0
  81. data/app/components/arclight/index_metadata_field_component.html.erb +16 -0
  82. data/app/components/arclight/index_metadata_field_component.rb +20 -0
  83. data/app/components/arclight/masthead_component.html.erb +15 -0
  84. data/app/components/arclight/masthead_component.rb +10 -0
  85. data/app/components/arclight/metadata_section_component.html.erb +13 -0
  86. data/app/components/arclight/metadata_section_component.rb +22 -0
  87. data/app/components/arclight/oembed_viewer_component.html.erb +5 -0
  88. data/app/components/arclight/oembed_viewer_component.rb +16 -0
  89. data/app/components/arclight/online_content_filter_component.html.erb +15 -0
  90. data/app/components/arclight/online_content_filter_component.rb +19 -0
  91. data/app/components/arclight/online_status_indicator_component.rb +19 -0
  92. data/app/components/arclight/repository_breadcrumb_component.html.erb +10 -0
  93. data/app/components/arclight/repository_breadcrumb_component.rb +17 -0
  94. data/app/components/arclight/repository_location_component.html.erb +20 -0
  95. data/app/components/arclight/repository_location_component.rb +10 -0
  96. data/app/components/arclight/search_bar_component.html.erb +27 -0
  97. data/app/components/arclight/search_bar_component.rb +32 -0
  98. data/app/components/arclight/search_result_breadcrumbs_component.html.erb +6 -0
  99. data/app/components/arclight/search_result_breadcrumbs_component.rb +37 -0
  100. data/app/components/arclight/search_result_component.html.erb +20 -0
  101. data/app/components/arclight/search_result_component.rb +18 -0
  102. data/app/components/arclight/search_result_title_component.html.erb +15 -0
  103. data/app/components/arclight/search_result_title_component.rb +15 -0
  104. data/app/components/arclight/sidebar_component.html.erb +9 -0
  105. data/app/components/arclight/sidebar_component.rb +19 -0
  106. data/app/components/arclight/upper_metadata_layout_component.rb +10 -0
  107. data/app/components/blacklight/icons/bookmark_component.rb +12 -0
  108. data/app/components/blacklight/icons/collection_component.rb +14 -0
  109. data/app/components/blacklight/icons/compact_component.rb +12 -0
  110. data/app/components/blacklight/icons/container_component.rb +14 -0
  111. data/app/components/blacklight/icons/ead_component.rb +12 -0
  112. data/app/components/blacklight/icons/file_component.rb +14 -0
  113. data/app/components/blacklight/icons/folder_component.rb +12 -0
  114. data/app/components/blacklight/icons/online_component.rb +15 -0
  115. data/app/components/blacklight/icons/pdf_component.rb +12 -0
  116. data/app/components/blacklight/icons/repository_component.rb +12 -0
  117. data/app/controllers/arclight/repositories_controller.rb +40 -0
  118. data/app/helpers/arclight/ead_format_helpers.rb +309 -0
  119. data/app/helpers/arclight/field_config_helpers.rb +26 -0
  120. data/app/helpers/arclight_helper.rb +108 -0
  121. data/app/models/arclight/document_downloads.rb +122 -0
  122. data/app/models/arclight/parent.rb +24 -0
  123. data/app/models/arclight/parents.rb +39 -0
  124. data/app/models/arclight/requests/aeon_external_request.rb +42 -0
  125. data/app/models/arclight/requests/aeon_web_ead.rb +52 -0
  126. data/app/models/arclight/requests/google_form.rb +49 -0
  127. data/app/models/concerns/arclight/catalog.rb +44 -0
  128. data/app/models/concerns/arclight/search_behavior.rb +47 -0
  129. data/app/models/concerns/arclight/solr_document.rb +159 -0
  130. data/app/presenters/arclight/index_presenter.rb +10 -0
  131. data/app/presenters/arclight/show_presenter.rb +54 -0
  132. data/app/views/arclight/.keep +0 -0
  133. data/app/views/arclight/_requests.html.erb +7 -0
  134. data/app/views/arclight/repositories/_repository.html.erb +43 -0
  135. data/app/views/arclight/repositories/index.html.erb +9 -0
  136. data/app/views/arclight/repositories/show.html.erb +37 -0
  137. data/app/views/arclight/requests/_aeon_external_request_endpoint.html.erb +8 -0
  138. data/app/views/arclight/requests/_aeon_web_ead.html.erb +6 -0
  139. data/app/views/arclight/requests/_google_form.html.erb +10 -0
  140. data/app/views/catalog/_document_list.html.erb +8 -0
  141. data/app/views/catalog/_group.html.erb +4 -0
  142. data/app/views/catalog/_group_toggle.html.erb +10 -0
  143. data/app/views/catalog/_search_results_header.html.erb +3 -0
  144. data/app/views/catalog/hierarchy.html.erb +19 -0
  145. data/app/views/catalog/index.html.erb +17 -0
  146. data/app/views/shared/_breadcrumbs.html.erb +3 -0
  147. data/app/views/shared/_main_menu_links.html.erb +6 -0
  148. data/arclight.gemspec +29 -11
  149. data/bin/rails +13 -0
  150. data/config/breadcrumbs.rb +24 -0
  151. data/config/i18n-tasks.yml +134 -0
  152. data/config/importmap.rb +3 -0
  153. data/config/locales/arclight.en.yml +100 -0
  154. data/config/repositories.yml +0 -0
  155. data/config/routes.rb +6 -0
  156. data/docker-compose.yml +16 -0
  157. data/lib/arclight/digital_object.rb +27 -0
  158. data/lib/arclight/engine.rb +47 -0
  159. data/lib/arclight/exceptions.rb +19 -0
  160. data/lib/arclight/hash_absolute_xpath.rb +62 -0
  161. data/lib/arclight/level_label.rb +46 -0
  162. data/lib/arclight/missing_id_strategy.rb +21 -0
  163. data/lib/arclight/normalized_date.rb +49 -0
  164. data/lib/arclight/normalized_id.rb +30 -0
  165. data/lib/arclight/normalized_title.rb +33 -0
  166. data/lib/arclight/repository.rb +116 -0
  167. data/lib/arclight/routes/hierarchy.rb +19 -0
  168. data/lib/arclight/routes.rb +8 -0
  169. data/lib/arclight/traject/ead2_component_config.rb +334 -0
  170. data/lib/arclight/traject/ead2_config.rb +315 -0
  171. data/lib/arclight/traject/nokogiri_namespaceless_reader.rb +22 -0
  172. data/lib/arclight/version.rb +3 -1
  173. data/lib/arclight/year_range.rb +111 -0
  174. data/lib/arclight.rb +11 -1
  175. data/lib/generators/arclight/install_generator.rb +126 -0
  176. data/lib/generators/arclight/templates/arclight.scss +5 -0
  177. data/lib/generators/arclight/templates/catalog_controller.rb +422 -0
  178. data/lib/generators/arclight/templates/config/downloads.yml +25 -0
  179. data/lib/generators/arclight/templates/config/locales/arclight.en.yml +61 -0
  180. data/lib/generators/arclight/templates/config/repositories.yml +53 -0
  181. data/lib/generators/arclight/update_generator.rb +22 -0
  182. data/lib/tasks/index.rake +84 -0
  183. data/package.json +30 -0
  184. data/solr/conf/_rest_managed.json +3 -0
  185. data/solr/conf/admin-extra.html +31 -0
  186. data/solr/conf/elevate.xml +36 -0
  187. data/solr/conf/mapping-ISOLatin1Accent.txt +246 -0
  188. data/solr/conf/protwords.txt +21 -0
  189. data/solr/conf/schema.xml +400 -0
  190. data/solr/conf/solrconfig.xml +328 -0
  191. data/solr/conf/spellings.txt +2 -0
  192. data/solr/conf/stopwords.txt +58 -0
  193. data/solr/conf/stopwords_en.txt +58 -0
  194. data/solr/conf/synonyms.txt +31 -0
  195. data/solr/conf/xslt/example.xsl +132 -0
  196. data/solr/conf/xslt/example_atom.xsl +67 -0
  197. data/solr/conf/xslt/example_rss.xsl +66 -0
  198. data/solr/conf/xslt/luke.xsl +337 -0
  199. data/tasks/arclight.rake +72 -0
  200. data/template.rb +10 -0
  201. metadata +432 -20
  202. 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
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arclight
4
+ # Custom presentation methods for index partials
5
+ class IndexPresenter < Blacklight::IndexPresenter
6
+ def label(*)
7
+ document.normalized_title
8
+ end
9
+ end
10
+ end