arclight 0.5.0 → 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (216) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintrc +11 -4
  3. data/.github/workflows/ruby.yml +24 -11
  4. data/.rspec +0 -1
  5. data/.rubocop.yml +286 -2
  6. data/.rubocop_todo.yml +18 -195
  7. data/CONTRIBUTING.md +5 -5
  8. data/Gemfile +12 -12
  9. data/README.md +18 -12
  10. data/app/assets/javascripts/arclight/arclight.js +3 -7
  11. data/app/assets/javascripts/arclight/oembed_viewer.js +64 -39
  12. data/app/assets/javascripts/arclight/truncate_controller.js +27 -0
  13. data/app/assets/stylesheets/arclight/application.scss +1 -5
  14. data/app/assets/stylesheets/arclight/modules/hierarchy_and_online_contents.scss +104 -130
  15. data/app/assets/stylesheets/arclight/modules/icons.scss +14 -3
  16. data/app/assets/stylesheets/arclight/modules/layout.scss +120 -100
  17. data/app/assets/stylesheets/arclight/modules/mastheads.scss +15 -57
  18. data/app/assets/stylesheets/arclight/modules/repositories.scss +2 -2
  19. data/app/assets/stylesheets/arclight/modules/repository_card.scss +4 -48
  20. data/app/assets/stylesheets/arclight/modules/search_results.scss +86 -35
  21. data/app/assets/stylesheets/arclight/modules/show_collection.scss +5 -32
  22. data/app/assets/stylesheets/arclight/modules/truncator.scss +56 -0
  23. data/app/assets/stylesheets/arclight/variables.scss +7 -4
  24. data/app/components/arclight/access_component.html.erb +14 -0
  25. data/app/components/arclight/access_component.rb +25 -0
  26. data/app/components/arclight/bookmark_component.html.erb +25 -0
  27. data/app/components/arclight/bookmark_component.rb +9 -0
  28. data/app/components/arclight/breadcrumb_component.rb +40 -0
  29. data/app/components/arclight/breadcrumbs_hierarchy_component.html.erb +34 -0
  30. data/app/components/arclight/breadcrumbs_hierarchy_component.rb +25 -0
  31. data/app/components/arclight/collection_context_component.html.erb +12 -0
  32. data/app/components/arclight/collection_context_component.rb +27 -0
  33. data/app/components/arclight/collection_info_component.html.erb +28 -0
  34. data/app/components/arclight/collection_info_component.rb +26 -0
  35. data/app/components/arclight/collection_sidebar_component.html.erb +15 -0
  36. data/app/components/arclight/collection_sidebar_component.rb +41 -0
  37. data/app/{views/catalog/_search_results_repository.html.erb → components/arclight/constraints_component.html.erb} +2 -1
  38. data/app/components/arclight/constraints_component.rb +17 -0
  39. data/app/components/arclight/document_collection_context_component.html.erb +29 -0
  40. data/app/components/arclight/document_collection_context_component.rb +28 -0
  41. data/app/components/arclight/document_collection_hierarchy_component.html.erb +46 -0
  42. data/app/components/arclight/document_collection_hierarchy_component.rb +62 -0
  43. data/app/components/arclight/document_component.html.erb +39 -0
  44. data/app/components/arclight/document_component.rb +49 -0
  45. data/app/components/arclight/document_components_hierarchy_component.html.erb +32 -0
  46. data/app/components/arclight/document_components_hierarchy_component.rb +28 -0
  47. data/app/components/arclight/document_download_component.html.erb +24 -0
  48. data/app/components/arclight/document_download_component.rb +71 -0
  49. data/app/components/arclight/embed_component.html.erb +10 -0
  50. data/app/components/arclight/embed_component.rb +43 -0
  51. data/app/components/arclight/group_component.html.erb +30 -0
  52. data/app/components/arclight/group_component.rb +23 -0
  53. data/app/components/arclight/header_component.html.erb +5 -0
  54. data/app/components/arclight/header_component.rb +10 -0
  55. data/app/components/arclight/index_metadata_field_component.html.erb +17 -0
  56. data/app/components/arclight/index_metadata_field_component.rb +20 -0
  57. data/app/components/arclight/masthead_component.html.erb +15 -0
  58. data/app/components/arclight/masthead_component.rb +10 -0
  59. data/app/components/arclight/metadata_section_component.html.erb +13 -0
  60. data/app/components/arclight/metadata_section_component.rb +22 -0
  61. data/app/components/arclight/oembed_viewer_component.html.erb +5 -0
  62. data/app/components/arclight/oembed_viewer_component.rb +16 -0
  63. data/app/components/arclight/online_content_filter_component.html.erb +15 -0
  64. data/app/components/arclight/online_content_filter_component.rb +19 -0
  65. data/app/components/arclight/online_status_indicator_component.rb +19 -0
  66. data/app/components/arclight/repository_breadcrumb_component.html.erb +10 -0
  67. data/app/components/arclight/repository_breadcrumb_component.rb +17 -0
  68. data/app/components/arclight/repository_location_component.html.erb +20 -0
  69. data/app/components/arclight/repository_location_component.rb +10 -0
  70. data/app/components/arclight/search_bar_component.html.erb +25 -0
  71. data/app/components/arclight/search_bar_component.rb +32 -0
  72. data/app/components/arclight/search_result_breadcrumbs_component.html.erb +3 -0
  73. data/app/components/arclight/search_result_breadcrumbs_component.rb +37 -0
  74. data/app/components/arclight/search_result_component.html.erb +20 -0
  75. data/app/components/arclight/search_result_component.rb +24 -0
  76. data/app/components/arclight/search_result_title_component.html.erb +13 -0
  77. data/app/components/arclight/search_result_title_component.rb +15 -0
  78. data/app/components/arclight/sidebar_component.html.erb +9 -0
  79. data/app/components/arclight/sidebar_component.rb +19 -0
  80. data/app/components/arclight/upper_metadata_layout_component.rb +10 -0
  81. data/app/components/blacklight/icons/bookmark_component.rb +12 -0
  82. data/app/components/blacklight/icons/collection_component.rb +14 -0
  83. data/app/components/blacklight/icons/compact_component.rb +12 -0
  84. data/app/components/blacklight/icons/container_component.rb +14 -0
  85. data/app/components/blacklight/icons/ead_component.rb +12 -0
  86. data/app/components/blacklight/icons/file_component.rb +14 -0
  87. data/app/components/blacklight/icons/folder_component.rb +12 -0
  88. data/app/components/blacklight/icons/online_component.rb +15 -0
  89. data/app/components/blacklight/icons/pdf_component.rb +12 -0
  90. data/app/components/blacklight/icons/repository_component.rb +12 -0
  91. data/app/controllers/arclight/repositories_controller.rb +4 -4
  92. data/app/{controllers/concerns → helpers}/arclight/ead_format_helpers.rb +4 -7
  93. data/app/helpers/arclight/field_config_helpers.rb +26 -0
  94. data/app/helpers/arclight_helper.rb +15 -253
  95. data/app/models/arclight/document_downloads.rb +12 -15
  96. data/app/models/arclight/parent.rb +5 -0
  97. data/app/models/arclight/parents.rb +2 -1
  98. data/app/models/arclight/requests/aeon_external_request.rb +1 -1
  99. data/app/models/arclight/requests/aeon_web_ead.rb +8 -3
  100. data/app/models/arclight/requests/google_form.rb +8 -3
  101. data/app/models/concerns/arclight/catalog.rb +25 -15
  102. data/app/models/concerns/arclight/search_behavior.rb +12 -26
  103. data/app/models/concerns/arclight/solr_document.rb +70 -73
  104. data/app/presenters/arclight/show_presenter.rb +34 -7
  105. data/app/views/arclight/_requests.html.erb +2 -2
  106. data/app/views/arclight/repositories/_repository.html.erb +21 -40
  107. data/app/views/arclight/repositories/index.html.erb +3 -1
  108. data/app/views/arclight/repositories/show.html.erb +4 -6
  109. data/app/views/arclight/requests/_aeon_external_request_endpoint.html.erb +4 -5
  110. data/app/views/arclight/requests/_aeon_web_ead.html.erb +2 -3
  111. data/app/views/arclight/requests/_google_form.html.erb +4 -6
  112. data/app/views/catalog/_group.html.erb +1 -18
  113. data/app/views/catalog/_group_toggle.html.erb +1 -1
  114. data/app/views/catalog/_search_results_header.html.erb +3 -0
  115. data/app/views/catalog/hierarchy.html.erb +19 -0
  116. data/app/views/catalog/index.html.erb +16 -7
  117. data/app/views/shared/_breadcrumbs.html.erb +2 -14
  118. data/app/views/shared/_main_menu_links.html.erb +1 -1
  119. data/arclight.gemspec +7 -6
  120. data/config/breadcrumbs.rb +24 -0
  121. data/config/i18n-tasks.yml +9 -8
  122. data/config/importmap.rb +3 -0
  123. data/config/locales/arclight.en.yml +31 -30
  124. data/config/routes.rb +1 -1
  125. data/docker-compose.yml +16 -0
  126. data/lib/arclight/digital_object.rb +2 -1
  127. data/lib/arclight/engine.rb +18 -31
  128. data/lib/arclight/exceptions.rb +1 -0
  129. data/lib/arclight/hash_absolute_xpath.rb +2 -1
  130. data/lib/arclight/normalized_id.rb +2 -0
  131. data/lib/arclight/normalized_title.rb +2 -0
  132. data/lib/arclight/repository.rb +43 -54
  133. data/lib/arclight/routes/hierarchy.rb +19 -0
  134. data/lib/arclight/routes.rb +8 -0
  135. data/lib/arclight/traject/ead2_component_config.rb +292 -0
  136. data/lib/arclight/traject/ead2_config.rb +66 -287
  137. data/lib/arclight/version.rb +1 -1
  138. data/lib/arclight/year_range.rb +4 -3
  139. data/lib/arclight.rb +6 -1
  140. data/lib/generators/arclight/install_generator.rb +59 -21
  141. data/lib/generators/arclight/templates/arclight.scss +4 -3
  142. data/lib/generators/arclight/templates/catalog_controller.rb +150 -169
  143. data/lib/generators/arclight/templates/config/locales/arclight.en.yml +53 -0
  144. data/lib/generators/arclight/templates/config/repositories.yml +20 -27
  145. data/lib/tasks/index.rake +14 -17
  146. data/package.json +11 -13
  147. data/solr/conf/schema.xml +40 -36
  148. data/solr/conf/solrconfig.xml +33 -31
  149. data/tasks/arclight.rake +8 -7
  150. data/template.rb +0 -1
  151. metadata +111 -104
  152. data/.babelrc +0 -3
  153. data/app/assets/javascripts/arclight/collection_navigation.js +0 -100
  154. data/app/assets/javascripts/arclight/collection_scrollspy.js +0 -6
  155. data/app/assets/javascripts/arclight/context_navigation.js +0 -351
  156. data/app/assets/javascripts/arclight/truncator.js.erb +0 -29
  157. data/app/assets/stylesheets/arclight/bootstrap_overrides.scss +0 -26
  158. data/app/assets/stylesheets/arclight/modules/context_navigation.scss +0 -75
  159. data/app/controllers/concerns/arclight/field_config_helpers.rb +0 -102
  160. data/app/factories/blacklight_field_configuration_factory.rb +0 -30
  161. data/app/views/arclight/repositories/_in_person_repository.html.erb +0 -19
  162. data/app/views/arclight/repositories/_repository_contact.html.erb +0 -9
  163. data/app/views/arclight/viewers/_oembed.html.erb +0 -8
  164. data/app/views/catalog/_access_contents.html.erb +0 -15
  165. data/app/views/catalog/_arclight_abstract_or_scope.html.erb +0 -5
  166. data/app/views/catalog/_arclight_bookmark_control.html.erb +0 -38
  167. data/app/views/catalog/_arclight_document_header_icon.html.erb +0 -1
  168. data/app/views/catalog/_arclight_document_index_header.html.erb +0 -13
  169. data/app/views/catalog/_arclight_document_index_header_hierarchy_default.html.erb +0 -0
  170. data/app/views/catalog/_arclight_document_index_header_online_contents_default.html.erb +0 -0
  171. data/app/views/catalog/_arclight_index_compact_default.html.erb +0 -22
  172. data/app/views/catalog/_arclight_index_default.html.erb +0 -45
  173. data/app/views/catalog/_arclight_index_group_document_compact_default.html.erb +0 -19
  174. data/app/views/catalog/_arclight_index_group_document_default.html.erb +0 -18
  175. data/app/views/catalog/_arclight_online_content_indicator.html.erb +0 -3
  176. data/app/views/catalog/_arclight_rangelimit.html.erb +0 -24
  177. data/app/views/catalog/_arclight_viewer_default.html.erb +0 -1
  178. data/app/views/catalog/_collection_contents.html.erb +0 -4
  179. data/app/views/catalog/_collection_context.html.erb +0 -15
  180. data/app/views/catalog/_collection_context_nav.html.erb +0 -12
  181. data/app/views/catalog/_collection_online_contents.html.erb +0 -17
  182. data/app/views/catalog/_component_context.html.erb +0 -5
  183. data/app/views/catalog/_containers.html.erb +0 -3
  184. data/app/views/catalog/_context_card.html.erb +0 -27
  185. data/app/views/catalog/_context_sidebar.html.erb +0 -8
  186. data/app/views/catalog/_custom_metadata.html.erb +0 -16
  187. data/app/views/catalog/_document_downloads.html.erb +0 -14
  188. data/app/views/catalog/_group_header_compact_default.html.erb +0 -15
  189. data/app/views/catalog/_group_header_default.html.erb +0 -20
  190. data/app/views/catalog/_home.html.erb +0 -1
  191. data/app/views/catalog/_index_breadcrumb_default.html.erb +0 -6
  192. data/app/views/catalog/_index_collection_context_default.html.erb +0 -53
  193. data/app/views/catalog/_index_default.html.erb +0 -17
  194. data/app/views/catalog/_index_header.html.erb +0 -7
  195. data/app/views/catalog/_index_header_online_contents_default.html.erb +0 -1
  196. data/app/views/catalog/_index_online_contents_default.html.erb +0 -6
  197. data/app/views/catalog/_online_content_label.html.erb +0 -5
  198. data/app/views/catalog/_search_form.html.erb +0 -38
  199. data/app/views/catalog/_search_results.html.erb +0 -28
  200. data/app/views/catalog/_show_actions_box_default.html.erb +0 -27
  201. data/app/views/catalog/_show_breadcrumbs_default.html.erb +0 -6
  202. data/app/views/catalog/_show_collection.html.erb +0 -66
  203. data/app/views/catalog/_show_default.html.erb +0 -70
  204. data/app/views/catalog/_show_upper_metadata_collection.html.erb +0 -1
  205. data/app/views/catalog/_show_upper_metadata_default.html.erb +0 -14
  206. data/app/views/catalog/_sort_and_per_page.html.erb +0 -8
  207. data/app/views/catalog/_within_collection_dropdown.html.erb +0 -26
  208. data/app/views/layouts/catalog_result.html.erb +0 -7
  209. data/app/views/shared/_context_sidebar.html.erb +0 -8
  210. data/app/views/shared/_header_navbar.html.erb +0 -61
  211. data/app/views/shared/_show_breadcrumbs.html.erb +0 -27
  212. data/lib/arclight/viewer.rb +0 -45
  213. data/lib/arclight/viewers/oembed.rb +0 -57
  214. data/solr/conf/scripts.conf +0 -24
  215. data/vendor/assets/javascripts/responsiveTruncator.js +0 -69
  216. data/vendor/assets/javascripts/stickyfill.js +0 -480
@@ -5,7 +5,6 @@ require 'traject'
5
5
  require 'traject/nokogiri_reader'
6
6
  require 'traject_plus'
7
7
  require 'traject_plus/macros'
8
- require 'arclight/exceptions'
9
8
  require 'arclight/level_label'
10
9
  require 'arclight/normalized_date'
11
10
  require 'arclight/normalized_title'
@@ -14,7 +13,6 @@ require 'active_support/core_ext/array/wrap'
14
13
  require 'arclight/digital_object'
15
14
  require 'arclight/year_range'
16
15
  require 'arclight/repository'
17
- require 'arclight/missing_id_strategy'
18
16
  require 'arclight/traject/nokogiri_namespaceless_reader'
19
17
 
20
18
  # rubocop:disable Style/MixinUsage
@@ -55,8 +53,9 @@ DID_SEARCHABLE_NOTES_FIELDS = %w[
55
53
  settings do
56
54
  provide 'reader_class_name', 'Arclight::Traject::NokogiriNamespacelessReader'
57
55
  provide 'solr_writer.commit_on_close', 'true'
58
- provide 'repository', ENV['REPOSITORY_ID']
56
+ provide 'repository', ENV.fetch('REPOSITORY_ID', nil)
59
57
  provide 'logger', Logger.new($stderr)
58
+ provide 'component_traject_config', File.join(__dir__, 'ead2_component_config.rb')
60
59
  end
61
60
 
62
61
  each_record do |_record, context|
@@ -69,12 +68,14 @@ end
69
68
 
70
69
  # ==================
71
70
  # Top level document
71
+ #
72
+ # NOTE: All fields should be stored in Solr
72
73
  # ==================
73
74
 
74
75
  to_field 'id', extract_xpath('/ead/eadheader/eadid'), strip, gsub('.', '-')
75
- to_field 'title_filing_si', extract_xpath('/ead/eadheader/filedesc/titlestmt/titleproper[@type="filing"]')
76
+ to_field 'title_filing_ssi', extract_xpath('/ead/eadheader/filedesc/titlestmt/titleproper[@type="filing"]')
76
77
  to_field 'title_ssm', extract_xpath('/ead/archdesc/did/unittitle')
77
- to_field 'title_teim', extract_xpath('/ead/archdesc/did/unittitle')
78
+ to_field 'title_tesim', extract_xpath('/ead/archdesc/did/unittitle')
78
79
  to_field 'ead_ssi', extract_xpath('/ead/eadheader/eadid')
79
80
 
80
81
  to_field 'unitdate_ssm', extract_xpath('/ead/archdesc/did/unitdate')
@@ -88,7 +89,7 @@ to_field 'level_ssm' do |_record, accumulator|
88
89
  end
89
90
 
90
91
  # Keep the original top-level archdesc/@level for Level facet in addition to 'Collection'
91
- to_field 'level_sim' do |record, accumulator|
92
+ to_field 'level_ssim' do |record, accumulator|
92
93
  level = record.at_xpath('/ead/archdesc').attribute('level')&.value
93
94
  other_level = record.at_xpath('/ead/archdesc').attribute('otherlevel')&.value
94
95
 
@@ -97,8 +98,7 @@ to_field 'level_sim' do |record, accumulator|
97
98
  end
98
99
 
99
100
  to_field 'unitid_ssm', extract_xpath('/ead/archdesc/did/unitid')
100
- to_field 'unitid_teim', extract_xpath('/ead/archdesc/did/unitid')
101
- to_field 'collection_unitid_ssm', extract_xpath('/ead/archdesc/did/unitid')
101
+ to_field 'unitid_tesim', extract_xpath('/ead/archdesc/did/unitid')
102
102
 
103
103
  to_field 'normalized_title_ssm' do |_record, accumulator, context|
104
104
  dates = Arclight::NormalizedDate.new(
@@ -118,16 +118,11 @@ to_field 'normalized_date_ssm' do |_record, accumulator, context|
118
118
  ).to_s
119
119
  end
120
120
 
121
- to_field 'collection_ssm' do |_record, accumulator, context|
122
- accumulator.concat context.output_hash.fetch('normalized_title_ssm', [])
123
- end
124
- to_field 'collection_sim' do |_record, accumulator, context|
125
- accumulator.concat context.output_hash.fetch('normalized_title_ssm', [])
126
- end
127
- to_field 'collection_ssi' do |_record, accumulator, context|
121
+ to_field 'collection_title_tesim' do |_record, accumulator, context|
128
122
  accumulator.concat context.output_hash.fetch('normalized_title_ssm', [])
129
123
  end
130
- to_field 'collection_title_tesim' do |_record, accumulator, context|
124
+
125
+ to_field 'collection_ssim' do |_record, accumulator, context|
131
126
  accumulator.concat context.output_hash.fetch('normalized_title_ssm', [])
132
127
  end
133
128
 
@@ -135,39 +130,30 @@ to_field 'repository_ssm' do |_record, accumulator, context|
135
130
  accumulator << context.clipboard[:repository]
136
131
  end
137
132
 
138
- to_field 'repository_sim' do |_record, accumulator, context|
133
+ to_field 'repository_ssim' do |_record, accumulator, context|
139
134
  accumulator << context.clipboard[:repository]
140
135
  end
141
136
 
142
137
  to_field 'geogname_ssm', extract_xpath('/ead/archdesc/controlaccess/geogname')
143
- to_field 'geogname_sim', extract_xpath('/ead/archdesc/controlaccess/geogname')
138
+ to_field 'geogname_ssim', extract_xpath('/ead/archdesc/controlaccess/geogname')
144
139
 
145
140
  to_field 'creator_ssm', extract_xpath('/ead/archdesc/did/origination')
146
- to_field 'creator_sim', extract_xpath('/ead/archdesc/did/origination')
147
141
  to_field 'creator_ssim', extract_xpath('/ead/archdesc/did/origination')
148
142
  to_field 'creator_sort' do |record, accumulator|
149
143
  accumulator << record.xpath('/ead/archdesc/did/origination').map { |c| c.text.strip }.join(', ')
150
144
  end
151
145
 
152
- to_field 'creator_persname_ssm', extract_xpath('/ead/archdesc/did/origination/persname')
153
146
  to_field 'creator_persname_ssim', extract_xpath('/ead/archdesc/did/origination/persname')
154
- to_field 'creator_corpname_ssm', extract_xpath('/ead/archdesc/did/origination/corpname')
155
- to_field 'creator_corpname_sim', extract_xpath('/ead/archdesc/did/origination/corpname')
156
147
  to_field 'creator_corpname_ssim', extract_xpath('/ead/archdesc/did/origination/corpname')
157
- to_field 'creator_famname_ssm', extract_xpath('/ead/archdesc/did/origination/famname')
158
148
  to_field 'creator_famname_ssim', extract_xpath('/ead/archdesc/did/origination/famname')
159
149
 
160
- to_field 'persname_sim', extract_xpath('//persname')
161
-
162
150
  to_field 'creators_ssim' do |_record, accumulator, context|
163
- accumulator.concat context.output_hash['creator_persname_ssm'] if context.output_hash['creator_persname_ssm']
164
- accumulator.concat context.output_hash['creator_corpname_ssm'] if context.output_hash['creator_corpname_ssm']
165
- accumulator.concat context.output_hash['creator_famname_ssm'] if context.output_hash['creator_famname_ssm']
151
+ accumulator.concat context.output_hash['creator_persname_ssim'] if context.output_hash['creator_persname_ssim']
152
+ accumulator.concat context.output_hash['creator_corpname_ssim'] if context.output_hash['creator_corpname_ssim']
153
+ accumulator.concat context.output_hash['creator_famname_ssim'] if context.output_hash['creator_famname_ssim']
166
154
  end
167
155
 
168
- to_field 'places_sim', extract_xpath('/ead/archdesc/controlaccess/geogname')
169
156
  to_field 'places_ssim', extract_xpath('/ead/archdesc/controlaccess/geogname')
170
- to_field 'places_ssm', extract_xpath('/ead/archdesc/controlaccess/geogname')
171
157
 
172
158
  to_field 'access_terms_ssm', extract_xpath('/ead/archdesc/userestrict/*[local-name()!="head"]')
173
159
 
@@ -200,11 +186,10 @@ to_field 'digital_objects_ssm', extract_xpath('/ead/archdesc/did/dao|/ead/archde
200
186
  end
201
187
 
202
188
  to_field 'extent_ssm', extract_xpath('/ead/archdesc/did/physdesc/extent')
203
- to_field 'extent_teim', extract_xpath('/ead/archdesc/did/physdesc/extent')
204
- to_field 'genreform_sim', extract_xpath('/ead/archdesc/controlaccess/genreform')
205
- to_field 'genreform_ssm', extract_xpath('/ead/archdesc/controlaccess/genreform')
189
+ to_field 'extent_tesim', extract_xpath('/ead/archdesc/did/physdesc/extent')
190
+ to_field 'genreform_ssim', extract_xpath('/ead/archdesc/controlaccess/genreform')
206
191
 
207
- to_field 'date_range_sim', extract_xpath('/ead/archdesc/did/unitdate/@normal', to_text: false) do |_record, accumulator|
192
+ to_field 'date_range_ssim', extract_xpath('/ead/archdesc/did/unitdate/@normal', to_text: false) do |_record, accumulator|
208
193
  range = Arclight::YearRange.new
209
194
  next range.years if accumulator.blank?
210
195
 
@@ -214,282 +199,76 @@ to_field 'date_range_sim', extract_xpath('/ead/archdesc/did/unitdate/@normal', t
214
199
  end
215
200
 
216
201
  SEARCHABLE_NOTES_FIELDS.map do |selector|
217
- to_field "#{selector}_ssm", extract_xpath("/ead/archdesc/#{selector}/*[local-name()!='head']", to_text: false)
202
+ to_field "#{selector}_html_tesm", extract_xpath("/ead/archdesc/#{selector}/*[local-name()!='head']", to_text: false) do |_record, accumulator|
203
+ accumulator.map!(&:to_html)
204
+ end
218
205
  to_field "#{selector}_heading_ssm", extract_xpath("/ead/archdesc/#{selector}/head") unless selector == 'prefercite'
219
- to_field "#{selector}_teim", extract_xpath("/ead/archdesc/#{selector}/*[local-name()!='head']")
206
+ to_field "#{selector}_tesim", extract_xpath("/ead/archdesc/#{selector}/*[local-name()!='head']")
220
207
  end
221
208
 
222
209
  DID_SEARCHABLE_NOTES_FIELDS.map do |selector|
223
- to_field "#{selector}_ssm", extract_xpath("/ead/archdesc/did/#{selector}", to_text: false)
210
+ to_field "#{selector}_html_tesm", extract_xpath("/ead/archdesc/did/#{selector}", to_text: false)
224
211
  end
225
212
 
226
213
  NAME_ELEMENTS.map do |selector|
227
214
  to_field 'names_coll_ssim', extract_xpath("/ead/archdesc/controlaccess/#{selector}")
228
- to_field 'names_ssim', extract_xpath("//#{selector}")
229
- to_field "#{selector}_ssm", extract_xpath("//#{selector}")
215
+ to_field 'names_ssim', extract_xpath("//#{selector}"), unique
216
+ to_field "#{selector}_ssim", extract_xpath("//#{selector}"), unique
230
217
  end
231
218
 
232
- to_field 'corpname_sim', extract_xpath('//corpname')
233
-
234
- to_field 'language_sim', extract_xpath('/ead/archdesc/did/langmaterial')
235
- to_field 'language_ssm', extract_xpath('/ead/archdesc/did/langmaterial')
219
+ to_field 'language_ssim', extract_xpath('/ead/archdesc/did/langmaterial')
236
220
 
237
221
  to_field 'descrules_ssm', extract_xpath('/ead/eadheader/profiledesc/descrules')
238
222
 
239
- # =============================
240
- # Each component child document
241
- # <c> <c01> <c12>
242
- # =============================
243
-
244
- compose 'components', ->(record, accumulator, _context) { accumulator.concat record.xpath('//*[is_component(.)]', NokogiriXpathExtensions.new) } do
245
- to_field 'ref_ssi' do |record, accumulator, context|
246
- accumulator << if record.attribute('id').blank?
247
- strategy = Arclight::MissingIdStrategy.selected
248
- hexdigest = strategy.new(record).to_hexdigest
249
- parent_id = context.clipboard[:parent].output_hash['id'].first
250
- logger.warn('MISSING ID WARNING') do
251
- [
252
- "A component in #{parent_id} did not have an ID so one was minted using the #{strategy} strategy.",
253
- "The ID of this document will be #{parent_id}#{hexdigest}."
254
- ].join(' ')
255
- end
256
- record['id'] = hexdigest
257
- hexdigest
258
- else
259
- record.attribute('id')&.value&.strip&.gsub('.', '-')
260
- end
261
- end
262
- to_field 'ref_ssm' do |_record, accumulator, context|
263
- accumulator.concat context.output_hash['ref_ssi']
264
- end
265
-
266
- to_field 'id' do |_record, accumulator, context|
267
- accumulator << [
268
- context.clipboard[:parent].output_hash['id'],
269
- context.output_hash['ref_ssi']
270
- ].join('')
271
- end
272
-
273
- to_field 'ead_ssi' do |_record, accumulator, context|
274
- accumulator << context.clipboard[:parent].output_hash['ead_ssi'].first
275
- end
276
-
277
- to_field 'title_filing_si', extract_xpath('./did/unittitle'), first_only
278
- to_field 'title_ssm', extract_xpath('./did/unittitle')
279
- to_field 'title_teim', extract_xpath('./did/unittitle')
280
-
281
- to_field 'unitdate_bulk_ssim', extract_xpath('./did/unitdate[@type="bulk"]')
282
- to_field 'unitdate_inclusive_ssm', extract_xpath('./did/unitdate[@type="inclusive"]')
283
- to_field 'unitdate_other_ssim', extract_xpath('./did/unitdate[not(@type)]')
284
-
285
- to_field 'normalized_title_ssm' do |_record, accumulator, context|
286
- dates = Arclight::NormalizedDate.new(
287
- context.output_hash['unitdate_inclusive_ssm'],
288
- context.output_hash['unitdate_bulk_ssim'],
289
- context.output_hash['unitdate_other_ssim']
290
- ).to_s
291
- title = context.output_hash['title_ssm']&.first
292
- accumulator << Arclight::NormalizedTitle.new(title, dates).to_s
293
- end
294
-
295
- to_field 'normalized_date_ssm' do |_record, accumulator, context|
296
- accumulator << Arclight::NormalizedDate.new(
297
- context.output_hash['unitdate_inclusive_ssm'],
298
- context.output_hash['unitdate_bulk_ssim'],
299
- context.output_hash['unitdate_other_ssim']
300
- ).to_s
301
- end
302
-
303
- to_field 'component_level_isim' do |record, accumulator|
304
- accumulator << 1 + NokogiriXpathExtensions.new.is_component(record.ancestors).count
305
- end
306
-
307
- to_field 'parent_ssim' do |record, accumulator, context|
308
- accumulator << context.clipboard[:parent].output_hash['id'].first
309
- accumulator.concat NokogiriXpathExtensions.new.is_component(record.ancestors).reverse.map { |n| n.attribute('id')&.value }
310
- end
311
-
312
- to_field 'parent_ssi' do |_record, accumulator, context|
313
- accumulator << context.output_hash['parent_ssim'].last
314
- end
315
-
316
- to_field 'parent_unittitles_ssm' do |_rec, accumulator, context|
317
- # top level document
318
- accumulator.concat context.clipboard[:parent].output_hash['normalized_title_ssm']
319
- parent_ssim = context.output_hash['parent_ssim']
320
- components = context.clipboard[:parent].output_hash['components']
321
-
322
- # other components
323
- if parent_ssim && components
324
- ancestors = parent_ssim.drop(1).map { |x| [x] }
325
- accumulator.concat components.select { |c| ancestors.include? c['ref_ssi'] }.flat_map { |c| c['normalized_title_ssm'] }
326
- end
327
- end
328
-
329
- to_field 'parent_unittitles_teim' do |_record, accumulator, context|
330
- accumulator.concat context.output_hash['parent_unittitles_ssm']
331
- end
332
-
333
- to_field 'parent_levels_ssm' do |_record, accumulator, context|
334
- ## Top level document
335
- accumulator.concat context.clipboard[:parent].output_hash['level_ssm']
336
- ## Other components
337
- context.output_hash['parent_ssim']&.drop(1)&.each do |id|
338
- accumulator.concat Array
339
- .wrap(context.clipboard[:parent].output_hash['components'])
340
- .select { |c| c['ref_ssi'] == [id] }.map { |c| c['level_ssm'] }.flatten
341
- end
342
- end
343
-
344
- to_field 'unitid_ssm', extract_xpath('./did/unitid')
345
- to_field 'collection_unitid_ssm' do |_record, accumulator, context|
346
- accumulator.concat Array.wrap(context.clipboard[:parent].output_hash['unitid_ssm'])
347
- end
348
- to_field 'repository_ssm' do |_record, accumulator, context|
349
- accumulator << context.clipboard[:parent].clipboard[:repository]
350
- end
351
- to_field 'repository_sim' do |_record, accumulator, context|
352
- accumulator << context.clipboard[:parent].clipboard[:repository]
353
- end
354
- to_field 'collection_ssm' do |_record, accumulator, context|
355
- accumulator.concat context.clipboard[:parent].output_hash['normalized_title_ssm']
356
- end
357
- to_field 'collection_sim' do |_record, accumulator, context|
358
- accumulator.concat context.clipboard[:parent].output_hash['normalized_title_ssm']
359
- end
360
- to_field 'collection_ssi' do |_record, accumulator, context|
361
- accumulator.concat context.clipboard[:parent].output_hash['normalized_title_ssm']
362
- end
363
-
364
- to_field 'extent_ssm', extract_xpath('./did/physdesc/extent')
365
- to_field 'extent_teim', extract_xpath('./did/physdesc/extent')
366
-
367
- to_field 'creator_ssm', extract_xpath('./did/origination')
368
- to_field 'creator_ssim', extract_xpath('./did/origination')
369
- to_field 'creators_ssim', extract_xpath('./did/origination')
370
- to_field 'creator_sort' do |record, accumulator|
371
- accumulator << record.xpath('./did/origination').map(&:text).join(', ')
372
- end
373
- to_field 'collection_creator_ssm' do |_record, accumulator, context|
374
- accumulator.concat Array.wrap(context.clipboard[:parent].output_hash['creator_ssm'])
375
- end
376
- to_field 'has_online_content_ssim', extract_xpath('.//dao') do |_record, accumulator|
377
- accumulator.replace([accumulator.any?])
378
- end
379
- to_field 'child_component_count_isim' do |record, accumulator|
380
- accumulator << NokogiriXpathExtensions.new.is_component(record.children).count
381
- end
382
-
383
- to_field 'ref_ssm' do |record, accumulator|
384
- accumulator << record.attribute('id')
385
- end
386
-
387
- to_field 'level_ssm' do |record, accumulator|
388
- level = record.attribute('level')&.value
389
- other_level = record.attribute('otherlevel')&.value
390
- accumulator << Arclight::LevelLabel.new(level, other_level).to_s
391
- end
223
+ # count all descendant components from the top-level
224
+ to_field 'total_component_count_is', first_only do |record, accumulator|
225
+ accumulator << record.xpath('//c|//c01|//c02|//c03|//c04|//c05|//c06|//c07|//c08|//c09|//c10|//c11|//c12').count
226
+ end
392
227
 
393
- to_field 'level_sim' do |_record, accumulator, context|
394
- next unless context.output_hash['level_ssm']
228
+ # count all digital objects from the top-level
229
+ to_field 'online_item_count_is', first_only do |record, accumulator|
230
+ accumulator << record.xpath('//dao').count
231
+ end
395
232
 
396
- accumulator.concat context.output_hash['level_ssm']&.map(&:capitalize)
397
- end
233
+ to_field 'component_level_isim' do |_record, accumulator, _context|
234
+ accumulator << 0
235
+ end
398
236
 
399
- to_field 'sort_ii' do |_record, accumulator, context|
400
- accumulator.replace([context.position])
401
- end
237
+ to_field 'sort_isi' do |_record, accumulator, _context|
238
+ accumulator << 0
239
+ end
402
240
 
403
- # Get the <accessrestrict> from the closest ancestor that has one (includes top-level)
404
- to_field 'parent_access_restrict_ssm' do |record, accumulator|
405
- accumulator.concat Array
406
- .wrap(record.xpath('(./ancestor::*/accessrestrict)[last()]/*[local-name()!="head"]')
407
- .map(&:text))
408
- end
241
+ # =============================
242
+ # Each component child document
243
+ # <c> <c01> <c12>
244
+ # =============================
409
245
 
410
- # Get the <userestrict> from self OR the closest ancestor that has one (includes top-level)
411
- to_field 'parent_access_terms_ssm' do |record, accumulator|
412
- accumulator.concat Array
413
- .wrap(record.xpath('(./ancestor-or-self::*/userestrict)[last()]/*[local-name()!="head"]')
414
- .map(&:text))
415
- end
246
+ to_field 'components' do |record, accumulator, context|
247
+ child_components = record.xpath("/ead/archdesc/dsc/c|#{('/ead/archdesc/dsc/c01'..'/ead/archdesc/dsc/c12').to_a.join('|')}")
248
+ next unless child_components.any?
416
249
 
417
- to_field 'digital_objects_ssm', extract_xpath('./dao|./did/dao', to_text: false) do |_record, accumulator|
418
- accumulator.map! do |dao|
419
- label = dao.attributes['title']&.value ||
420
- dao.xpath('daodesc/p')&.text
421
- href = (dao.attributes['href'] || dao.attributes['xlink:href'])&.value
422
- Arclight::DigitalObject.new(label: label, href: href).to_json
250
+ counter = Class.new do
251
+ def increment
252
+ @counter ||= 0
253
+ @counter += 1
423
254
  end
424
- end
425
-
426
- to_field 'date_range_sim', extract_xpath('./did/unitdate/@normal', to_text: false) do |_record, accumulator|
427
- range = Arclight::YearRange.new
428
- next range.years if accumulator.blank?
429
-
430
- ranges = accumulator.map(&:to_s)
431
- range << range.parse_ranges(ranges)
432
- accumulator.replace range.years
433
- end
434
-
435
- NAME_ELEMENTS.map do |selector|
436
- to_field 'names_ssim', extract_xpath("./controlaccess/#{selector}")
437
- to_field "#{selector}_ssm", extract_xpath(".//#{selector}")
438
- end
439
-
440
- to_field 'geogname_sim', extract_xpath('./controlaccess/geogname')
441
- to_field 'geogname_ssm', extract_xpath('./controlaccess/geogname')
442
- to_field 'places_ssim', extract_xpath('./controlaccess/geogname')
443
-
444
- to_field 'access_subjects_ssim', extract_xpath('./controlaccess', to_text: false) do |_record, accumulator|
445
- accumulator.map! do |element|
446
- %w[subject function occupation genreform].map do |selector|
447
- element.xpath(".//#{selector}").map(&:text)
448
- end
449
- end.flatten!
450
- end
451
-
452
- to_field 'access_subjects_ssm' do |_record, accumulator, context|
453
- accumulator.concat(context.output_hash.fetch('access_subjects_ssim', []))
454
- end
455
-
456
- to_field 'acqinfo_ssim', extract_xpath('/ead/archdesc/acqinfo/*[local-name()!="head"]')
457
- to_field 'acqinfo_ssim', extract_xpath('/ead/archdesc/descgrp/acqinfo/*[local-name()!="head"]')
458
- to_field 'acqinfo_ssim', extract_xpath('./acqinfo/*[local-name()!="head"]')
459
- to_field 'acqinfo_ssim', extract_xpath('./descgrp/acqinfo/*[local-name()!="head"]')
460
-
461
- to_field 'language_ssm', extract_xpath('./did/langmaterial')
462
- to_field 'containers_ssim' do |record, accumulator|
463
- record.xpath('./did/container').each do |node|
464
- accumulator << [node.attribute('type'), node.text].join(' ').strip
255
+ end.new
256
+
257
+ component_indexer = Traject::Indexer::NokogiriIndexer.new.tap do |i|
258
+ i.settings do
259
+ provide :parent, context
260
+ provide :root, context
261
+ provide :counter, counter
262
+ provide :depth, 1
263
+ provide :logger, context.settings[:logger]
264
+ provide :component_traject_config, context.settings[:component_traject_config]
465
265
  end
466
- end
467
266
 
468
- SEARCHABLE_NOTES_FIELDS.map do |selector|
469
- to_field "#{selector}_ssm", extract_xpath("./#{selector}/*[local-name()!='head']", to_text: false)
470
- to_field "#{selector}_heading_ssm", extract_xpath("./#{selector}/head")
471
- to_field "#{selector}_teim", extract_xpath("./#{selector}/*[local-name()!='head']")
472
- end
473
- DID_SEARCHABLE_NOTES_FIELDS.map do |selector|
474
- to_field "#{selector}_ssm", extract_xpath("./did/#{selector}", to_text: false)
267
+ i.load_config_file(context.settings[:component_traject_config])
475
268
  end
476
- to_field 'did_note_ssm', extract_xpath('./did/note')
477
- end
478
269
 
479
- each_record do |_record, context|
480
- context.output_hash['components'] &&= context.output_hash['components'].select { |c| c.keys.any? }
481
- end
482
-
483
- ##
484
- # Used for evaluating xpath components to find
485
- class NokogiriXpathExtensions
486
- # rubocop:disable Naming/PredicateName, Style/FormatString
487
- def is_component(node_set)
488
- node_set.find_all do |node|
489
- component_elements = (1..12).map { |i| "c#{'%02d' % i}" }
490
- component_elements.push 'c'
491
- component_elements.include? node.name
492
- end
270
+ child_components.each do |child_component|
271
+ output = component_indexer.map_record(child_component)
272
+ accumulator << output if output.keys.any?
493
273
  end
494
- # rubocop:enable Naming/PredicateName, Style/FormatString
495
274
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Arclight
4
- VERSION = '0.5.0'
4
+ VERSION = '1.0.0.beta1'
5
5
  end
@@ -18,7 +18,6 @@ module Arclight
18
18
  def initialize(dates = nil)
19
19
  @years = []
20
20
  self << parse_ranges(dates) if dates.present?
21
- self
22
21
  end
23
22
 
24
23
  # @return [String] a concise, human-readable version of the year range, including gaps
@@ -77,13 +76,14 @@ module Arclight
77
76
  # Deals with making a human-readable range for years with 1 or more gaps.
78
77
  # It involves detection of streaks between the gaps.
79
78
  # @return [String] 1999-2000, 2002 for 1999, 2000, 2002
80
- def to_s_with_gaps # rubocop: disable Metrics/AbcSize, Metrics/MethodLength
79
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
80
+ def to_s_with_gaps
81
81
  raise ArgumentError if years.blank? || years.length < 2
82
82
 
83
83
  results = []
84
84
  streak = [years[0]]
85
85
  i = streak.first
86
- years[1..-1].each do |j|
86
+ years[1..].each do |j|
87
87
  i += 1
88
88
  if i == j
89
89
  streak << j
@@ -100,6 +100,7 @@ module Arclight
100
100
  results << to_s_for_streak(streak)
101
101
  results.join(', ')
102
102
  end
103
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
103
104
 
104
105
  def to_s_for_streak(streak)
105
106
  return streak.min.to_s if streak.min == streak.max
data/lib/arclight.rb CHANGED
@@ -5,6 +5,11 @@ require 'arclight/engine'
5
5
  require 'arclight/repository'
6
6
  require 'arclight/year_range'
7
7
 
8
+ # :nodoc:
8
9
  module Arclight
9
- # Your code goes here...
10
+ autoload :Routes, 'arclight/routes'
11
+
12
+ def self.deprecation
13
+ @deprecation ||= ActiveSupport::Deprecation.new('2.0', 'Arclight')
14
+ end
10
15
  end
@@ -33,32 +33,17 @@ module Arclight
33
33
  end
34
34
  end
35
35
 
36
- def install_blacklight_range_limit
37
- generate 'blacklight_range_limit:install'
38
- end
39
-
40
36
  def add_custom_routes
41
37
  inject_into_file 'config/routes.rb', after: "mount Blacklight::Engine => '/'" do
42
- "\n mount Arclight::Engine => '/'\n"
38
+ "\n mount Arclight::Engine => '/'\n"
43
39
  end
40
+
41
+ gsub_file 'config/routes.rb', 'root to: "catalog#index"', 'root to: "arclight/repositories#index"'
44
42
  end
45
43
 
46
44
  def copy_styles
47
45
  copy_file 'arclight.scss', 'app/assets/stylesheets/arclight.scss'
48
- end
49
-
50
- def inject_js
51
- inject_into_file 'app/assets/javascripts/application.js', after: '//= require blacklight/blacklight' do
52
- "\n// Required by Arclight" \
53
- "\n//= require arclight/arclight" \
54
- "\n//= require stickyfill"
55
- end
56
- end
57
-
58
- def install_webpacker
59
- return unless Rails.version.to_i == 6
60
-
61
- rake 'webpacker:install'
46
+ remove_file 'app/assets/stylesheets/blacklight.scss' # Avoid two copies of bootstrap
62
47
  end
63
48
 
64
49
  def add_arclight_search_behavior
@@ -79,12 +64,65 @@ module Arclight
79
64
  copy_file 'config/downloads.yml' unless File.exist?('config/downloads.yml')
80
65
  end
81
66
 
67
+ def add_i18n_config
68
+ copy_file 'config/locales/arclight.en.yml'
69
+ end
70
+
82
71
  def modify_blacklight_yml
83
72
  gsub_file 'config/locales/blacklight.en.yml', "application_name: 'Blacklight'", "application_name: 'Arclight'"
84
73
  end
85
74
 
86
- def run_yarn
87
- run 'yarn add @babel/core @babel/plugin-external-helpers @babel/plugin-transform-modules-umd @babel/preset-env'
75
+ def assets
76
+ if using_importmap?
77
+ pin_javascript_dependencies
78
+ import_arclight_javascript
79
+ else
80
+ install_javascript_dependencies
81
+ end
82
+ end
83
+
84
+ def inject_arclight_routes
85
+ inject_into_file 'config/routes.rb',
86
+ " concern :hierarchy, Arclight::Routes::Hierarchy.new\n",
87
+ after: /concern :exportable.*\n/
88
+ inject_into_file 'config/routes.rb',
89
+ " concerns :hierarchy\n",
90
+ after: /resources :solr_documents.*\n/
91
+ end
92
+
93
+ private
94
+
95
+ def root
96
+ @root ||= Pathname(destination_root)
97
+ end
98
+
99
+ def using_importmap?
100
+ @using_importmap ||= root.join('config/importmap.rb').exist?
101
+ end
102
+
103
+ # This is the last step because any failure here wouldn't prevent the other steps from running
104
+ def install_javascript_dependencies
105
+ inject_into_file 'app/assets/javascripts/application.js', after: '//= require blacklight/blacklight' do
106
+ "\n// Required by Arclight" \
107
+ "\n//= require arclight/arclight"
108
+ end
109
+ end
110
+
111
+ def pin_javascript_dependencies
112
+ say 'Arclight Importmap asset generation'
113
+
114
+ append_to_file 'config/importmap.rb', <<~RUBY
115
+ pin "arclight", to: "arclight/arclight.js"
116
+ # TODO: We may be able to move these to a single importmap for arclight.
117
+ pin "arclight/oembed_viewer", to: "arclight/oembed_viewer.js"
118
+ pin "arclight/truncate_controller", to: "arclight/truncate_controller.js"
119
+ RUBY
120
+ end
121
+
122
+ def import_arclight_javascript
123
+ inject_into_file 'app/javascript/application.js', after: 'import "blacklight"' do
124
+ "\nimport \"arclight\""
125
+ end
88
126
  end
89
127
  end
90
128
  end
@@ -1,3 +1,4 @@
1
- /*
2
- *= require arclight/application
3
- */
1
+ $breadcrumb-divider: quote("»");
2
+ @import 'bootstrap';
3
+ @import 'blacklight/blacklight';
4
+ @import 'arclight/application';