arclight 0.0.1 → 1.6.2

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 (204) 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 +51 -0
  6. data/.gitignore +7 -0
  7. data/.rspec +0 -1
  8. data/.rubocop.yml +521 -0
  9. data/.rubocop_todo.yml +122 -0
  10. data/.solr_wrapper +6 -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 +42 -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 +50 -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 +20 -0
  72. data/app/components/arclight/document_components_hierarchy_component.rb +34 -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/expand_hierarchy_button_component.html.erb +5 -0
  78. data/app/components/arclight/expand_hierarchy_button_component.rb +16 -0
  79. data/app/components/arclight/group_component.html.erb +34 -0
  80. data/app/components/arclight/group_component.rb +23 -0
  81. data/app/components/arclight/header_component.html.erb +5 -0
  82. data/app/components/arclight/header_component.rb +10 -0
  83. data/app/components/arclight/index_metadata_field_component.html.erb +16 -0
  84. data/app/components/arclight/index_metadata_field_component.rb +20 -0
  85. data/app/components/arclight/masthead_component.html.erb +17 -0
  86. data/app/components/arclight/masthead_component.rb +10 -0
  87. data/app/components/arclight/metadata_section_component.html.erb +13 -0
  88. data/app/components/arclight/metadata_section_component.rb +22 -0
  89. data/app/components/arclight/oembed_viewer_component.html.erb +5 -0
  90. data/app/components/arclight/oembed_viewer_component.rb +16 -0
  91. data/app/components/arclight/online_content_filter_component.html.erb +15 -0
  92. data/app/components/arclight/online_content_filter_component.rb +17 -0
  93. data/app/components/arclight/online_status_indicator_component.rb +19 -0
  94. data/app/components/arclight/repository_breadcrumb_component.html.erb +10 -0
  95. data/app/components/arclight/repository_breadcrumb_component.rb +17 -0
  96. data/app/components/arclight/repository_location_component.html.erb +20 -0
  97. data/app/components/arclight/repository_location_component.rb +10 -0
  98. data/app/components/arclight/search_bar_component.html.erb +27 -0
  99. data/app/components/arclight/search_bar_component.rb +32 -0
  100. data/app/components/arclight/search_result_breadcrumbs_component.html.erb +6 -0
  101. data/app/components/arclight/search_result_breadcrumbs_component.rb +37 -0
  102. data/app/components/arclight/search_result_component.html.erb +20 -0
  103. data/app/components/arclight/search_result_component.rb +18 -0
  104. data/app/components/arclight/search_result_title_component.html.erb +15 -0
  105. data/app/components/arclight/search_result_title_component.rb +15 -0
  106. data/app/components/arclight/sidebar_component.html.erb +9 -0
  107. data/app/components/arclight/sidebar_component.rb +19 -0
  108. data/app/components/arclight/upper_metadata_layout_component.rb +10 -0
  109. data/app/components/blacklight/icons/bookmark_component.rb +12 -0
  110. data/app/components/blacklight/icons/collection_component.rb +14 -0
  111. data/app/components/blacklight/icons/compact_component.rb +12 -0
  112. data/app/components/blacklight/icons/container_component.rb +14 -0
  113. data/app/components/blacklight/icons/ead_component.rb +12 -0
  114. data/app/components/blacklight/icons/file_component.rb +14 -0
  115. data/app/components/blacklight/icons/folder_component.rb +12 -0
  116. data/app/components/blacklight/icons/online_component.rb +15 -0
  117. data/app/components/blacklight/icons/pdf_component.rb +12 -0
  118. data/app/components/blacklight/icons/repository_component.rb +12 -0
  119. data/app/controllers/arclight/repositories_controller.rb +40 -0
  120. data/app/helpers/arclight/ead_format_helpers.rb +309 -0
  121. data/app/helpers/arclight/field_config_helpers.rb +26 -0
  122. data/app/helpers/arclight_helper.rb +108 -0
  123. data/app/models/arclight/document_downloads.rb +122 -0
  124. data/app/models/arclight/parent.rb +24 -0
  125. data/app/models/arclight/parents.rb +39 -0
  126. data/app/models/arclight/requests/aeon_external_request.rb +42 -0
  127. data/app/models/arclight/requests/aeon_web_ead.rb +52 -0
  128. data/app/models/arclight/requests/google_form.rb +49 -0
  129. data/app/models/concerns/arclight/catalog.rb +44 -0
  130. data/app/models/concerns/arclight/search_behavior.rb +47 -0
  131. data/app/models/concerns/arclight/solr_document.rb +160 -0
  132. data/app/presenters/arclight/index_presenter.rb +10 -0
  133. data/app/presenters/arclight/show_presenter.rb +54 -0
  134. data/app/views/arclight/.keep +0 -0
  135. data/app/views/arclight/_requests.html.erb +7 -0
  136. data/app/views/arclight/repositories/_repository.html.erb +43 -0
  137. data/app/views/arclight/repositories/index.html.erb +9 -0
  138. data/app/views/arclight/repositories/show.html.erb +37 -0
  139. data/app/views/arclight/requests/_aeon_external_request_endpoint.html.erb +8 -0
  140. data/app/views/arclight/requests/_aeon_web_ead.html.erb +6 -0
  141. data/app/views/arclight/requests/_google_form.html.erb +10 -0
  142. data/app/views/catalog/_document_list.html.erb +8 -0
  143. data/app/views/catalog/_group.html.erb +4 -0
  144. data/app/views/catalog/_group_toggle.html.erb +10 -0
  145. data/app/views/catalog/_search_results_header.html.erb +3 -0
  146. data/app/views/catalog/hierarchy.html.erb +19 -0
  147. data/app/views/catalog/index.html.erb +17 -0
  148. data/app/views/shared/_breadcrumbs.html.erb +3 -0
  149. data/app/views/shared/_main_menu_links.html.erb +6 -0
  150. data/arclight.gemspec +29 -11
  151. data/bin/rails +13 -0
  152. data/config/breadcrumbs.rb +24 -0
  153. data/config/i18n-tasks.yml +134 -0
  154. data/config/importmap.rb +3 -0
  155. data/config/locales/arclight.en.yml +100 -0
  156. data/config/repositories.yml +0 -0
  157. data/config/routes.rb +6 -0
  158. data/docker-compose.yml +16 -0
  159. data/lib/arclight/digital_object.rb +27 -0
  160. data/lib/arclight/engine.rb +47 -0
  161. data/lib/arclight/exceptions.rb +19 -0
  162. data/lib/arclight/hash_absolute_xpath.rb +62 -0
  163. data/lib/arclight/level_label.rb +46 -0
  164. data/lib/arclight/missing_id_strategy.rb +21 -0
  165. data/lib/arclight/normalized_date.rb +49 -0
  166. data/lib/arclight/normalized_id.rb +30 -0
  167. data/lib/arclight/normalized_title.rb +33 -0
  168. data/lib/arclight/repository.rb +116 -0
  169. data/lib/arclight/routes/hierarchy.rb +19 -0
  170. data/lib/arclight/routes.rb +8 -0
  171. data/lib/arclight/traject/ead2_component_config.rb +335 -0
  172. data/lib/arclight/traject/ead2_config.rb +316 -0
  173. data/lib/arclight/traject/nokogiri_namespaceless_reader.rb +22 -0
  174. data/lib/arclight/version.rb +3 -1
  175. data/lib/arclight/year_range.rb +111 -0
  176. data/lib/arclight.rb +11 -1
  177. data/lib/generators/arclight/install_generator.rb +163 -0
  178. data/lib/generators/arclight/templates/arclight.scss +6 -0
  179. data/lib/generators/arclight/templates/catalog_controller.rb +423 -0
  180. data/lib/generators/arclight/templates/config/downloads.yml +25 -0
  181. data/lib/generators/arclight/templates/config/locales/arclight.en.yml +61 -0
  182. data/lib/generators/arclight/templates/config/repositories.yml +53 -0
  183. data/lib/generators/arclight/update_generator.rb +22 -0
  184. data/lib/tasks/index.rake +84 -0
  185. data/package.json +30 -0
  186. data/solr/conf/_rest_managed.json +3 -0
  187. data/solr/conf/admin-extra.html +31 -0
  188. data/solr/conf/elevate.xml +36 -0
  189. data/solr/conf/mapping-ISOLatin1Accent.txt +246 -0
  190. data/solr/conf/protwords.txt +21 -0
  191. data/solr/conf/schema.xml +400 -0
  192. data/solr/conf/solrconfig.xml +328 -0
  193. data/solr/conf/spellings.txt +2 -0
  194. data/solr/conf/stopwords.txt +58 -0
  195. data/solr/conf/stopwords_en.txt +58 -0
  196. data/solr/conf/synonyms.txt +31 -0
  197. data/solr/conf/xslt/example.xsl +132 -0
  198. data/solr/conf/xslt/example_atom.xsl +67 -0
  199. data/solr/conf/xslt/example_rss.xsl +66 -0
  200. data/solr/conf/xslt/luke.xsl +337 -0
  201. data/tasks/arclight.rake +79 -0
  202. data/template.rb +10 -0
  203. metadata +440 -20
  204. data/.travis.yml +0 -5
data/arclight.gemspec CHANGED
@@ -1,28 +1,46 @@
1
- # coding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
- lib = File.expand_path('../lib', __FILE__)
3
+ lib = File.expand_path('lib', __dir__)
4
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
  require 'arclight/version'
6
6
 
7
7
  Gem::Specification.new do |spec|
8
8
  spec.name = 'arclight'
9
9
  spec.version = Arclight::VERSION
10
- spec.authors = ['Jack Reed']
11
- spec.email = ['phillipjreed@gmail.com']
10
+ spec.authors = ['Darren Hardy', 'Jessie Keck', 'Gordon Leacock', 'Jack Reed']
11
+ spec.email = ['drh@stanford.edu', 'jessie.keck@gmail.com', 'gordonl@umich.edu', 'phillipjreed@gmail.com']
12
12
 
13
- spec.summary = ''
13
+ spec.summary = 'A Blacklight-based environment to support discovery and delivery for archives and special collections'
14
14
  spec.description = ''
15
- spec.homepage = 'https://github.com/sul-dlss/arclight'
16
- spec.license = 'Apache-2.0'
15
+ spec.homepage = 'https://library.stanford.edu/projects/arclight'
16
+ spec.metadata = { 'source_code_uri' => 'https://github.com/projectblacklight/arclight' }
17
+ spec.license = 'Apache-2.0'
17
18
 
18
- spec.files = `git ls-files -z`.split("\x0").reject do |f|
19
+ spec.required_ruby_version = '>= 3.0.0'
20
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
19
21
  f.match(%r{^(test|spec|features)/})
20
22
  end
21
23
  spec.bindir = 'exe'
22
24
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
25
  spec.require_paths = ['lib']
24
26
 
25
- spec.add_development_dependency 'bundler', '~> 1.14'
26
- spec.add_development_dependency 'rake', '~> 10.0'
27
- spec.add_development_dependency 'rspec', '~> 3.0'
27
+ spec.add_dependency 'blacklight', '>= 8.0.0', '< 9'
28
+ spec.add_dependency 'gretel'
29
+ spec.add_dependency 'rails', '>= 7.1', '< 9'
30
+ spec.add_dependency 'traject', '~> 3.0'
31
+ spec.add_dependency 'traject_plus', '~> 2.0'
32
+
33
+ spec.add_development_dependency 'bundler'
34
+ spec.add_development_dependency 'capybara'
35
+ spec.add_development_dependency 'engine_cart'
36
+ spec.add_development_dependency 'i18n-tasks'
37
+ spec.add_development_dependency 'rake', '>= 12.0'
38
+ spec.add_development_dependency 'rspec-rails'
39
+ spec.add_development_dependency 'rubocop', '~> 1.8'
40
+ spec.add_development_dependency 'rubocop-rails', '~> 2.8'
41
+ spec.add_development_dependency 'rubocop-rake'
42
+ spec.add_development_dependency 'rubocop-rspec', '~> 2.3'
43
+ spec.add_development_dependency 'selenium-webdriver'
44
+ spec.add_development_dependency 'simplecov'
45
+ spec.add_development_dependency 'solr_wrapper'
28
46
  end
data/bin/rails ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails gems
3
+ # installed from the root of your application.
4
+
5
+ ENGINE_ROOT = File.expand_path('../..', __FILE__)
6
+ ENGINE_PATH = File.expand_path('../../lib/arclight/engine', __FILE__)
7
+
8
+ # Set up gems listed in the Gemfile.
9
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
10
+ require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
11
+
12
+ require 'rails/all'
13
+ require 'rails/engine/commands'
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Root crumb
4
+ crumb :root do
5
+ link t('arclight.routes.home'), root_path
6
+ end
7
+
8
+ crumb :repositories do
9
+ link t('arclight.routes.repositories'), arclight_engine.repositories_path
10
+ end
11
+
12
+ crumb :repository do |repository|
13
+ link repository.name, arclight_engine.repository_path(repository.slug)
14
+
15
+ parent :repositories
16
+ end
17
+
18
+ crumb :search_results do |search_state|
19
+ if search_state.filter('level').values == ['Collection']
20
+ link t('arclight.routes.collections')
21
+ else
22
+ link t('arclight.routes.search_results')
23
+ end
24
+ end
@@ -0,0 +1,134 @@
1
+ # i18n-tasks finds and manages missing and unused translations: https://github.com/glebm/i18n-tasks
2
+
3
+ # The "main" locale.
4
+ base_locale: en
5
+ ## All available locales are inferred from the data by default. Alternatively, specify them explicitly:
6
+ # locales: [es, fr]
7
+ ## Reporting locale, default: en. Available: en, ru.
8
+ # internal_locale: en
9
+
10
+ # Read and write translations.
11
+ data:
12
+ ## Translations are read from the file system. Supported format: YAML, JSON.
13
+ ## Provide a custom adapter:
14
+ # adapter: I18n::Tasks::Data::FileSystem
15
+
16
+ # Locale files or `File.find` patterns where translations are read from:
17
+ read:
18
+ ## Default:
19
+ # - config/locales/%{locale}.yml
20
+ ## More files:
21
+ - config/locales/**/*.%{locale}.yml
22
+
23
+ # Locale files to write new keys to, based on a list of key pattern => file rules. Matched from top to bottom:
24
+ # `i18n-tasks normalize -p` will force move the keys according to these rules
25
+ write:
26
+ ## For example, write devise and simple form keys to their respective files:
27
+ # - ['{devise, simple_form}.*', 'config/locales/\1.%{locale}.yml']
28
+ ## Catch-all default:
29
+ # - config/locales/%{locale}.yml
30
+
31
+ # External locale data (e.g. gems).
32
+ # This data is not considered unused and is never written to.
33
+ external:
34
+ ## Example (replace %#= with %=):
35
+ # - "<%#= %x[bundle show vagrant].chomp %>/templates/locales/%{locale}.yml"
36
+
37
+ ## Specify the router (see Readme for details). Valid values: conservative_router, pattern_router, or a custom class.
38
+ # router: conservative_router
39
+
40
+ yaml:
41
+ write:
42
+ # do not wrap lines at 80 characters
43
+ line_width: -1
44
+
45
+ ## Pretty-print JSON:
46
+ # json:
47
+ # write:
48
+ # indent: ' '
49
+ # space: ' '
50
+ # object_nl: "\n"
51
+ # array_nl: "\n"
52
+
53
+ # Find translate calls
54
+ search:
55
+ ## Paths or `File.find` patterns to search in:
56
+ paths:
57
+ - app/
58
+ - config/breadcrumbs.rb
59
+
60
+ ## Root directories for relative keys resolution.
61
+ relative_roots:
62
+ - app/components
63
+ - app/controllers
64
+ - app/helpers
65
+ - app/presenters
66
+ - app/views
67
+
68
+ ## Files or `File.fnmatch` patterns to exclude from search. Some files are always excluded regardless of this setting:
69
+ ## %w(*.jpg *.png *.gif *.svg *.ico *.eot *.otf *.ttf *.woff *.woff2 *.pdf *.css *.sass *.scss *.less *.yml *.json)
70
+ exclude:
71
+ - app/assets/images
72
+ - app/assets/fonts
73
+ - app/assets/videos
74
+
75
+ ## Alternatively, the only files or `File.fnmatch patterns` to search in `paths`:
76
+ ## If specified, this settings takes priority over `exclude`, but `exclude` still applies.
77
+ # only: ["*.rb", "*.html.slim"]
78
+
79
+ ## If `strict` is `false`, guess usages such as t("categories.#{category}.title"). The default is `true`.
80
+ # strict: true
81
+
82
+ ## Multiple scanners can be used. Their results are merged.
83
+ ## The options specified above are passed down to each scanner. Per-scanner options can be specified as well.
84
+ ## See this example of a custom scanner: https://github.com/glebm/i18n-tasks/wiki/A-custom-scanner-example
85
+
86
+ ## Translation Services
87
+ # translation:
88
+ # # Google Translate
89
+ # # Get an API key and set billing info at https://code.google.com/apis/console to use Google Translate
90
+ # google_translate_api_key: "AbC-dEf5"
91
+ # # DeepL Pro Translate
92
+ # # Get an API key and subscription at https://www.deepl.com/pro to use DeepL Pro
93
+ # deepl_api_key: "48E92789-57A3-466A-9959-1A1A1A1A1A1A"
94
+
95
+ ## Do not consider these keys missing:
96
+ ignore_missing:
97
+ - '{blacklight}.*'
98
+
99
+ ## Consider these keys used:
100
+ ignore_unused:
101
+ - '{blacklight}.*'
102
+ # - 'activerecord.attributes.*'
103
+ # - '{devise,kaminari,will_paginate}.*'
104
+ # - 'simple_form.{yes,no}'
105
+ # - 'simple_form.{placeholders,hints,labels}.*'
106
+ # - 'simple_form.{error_notification,required}.:'
107
+
108
+ ## Exclude these keys from the `i18n-tasks eq-base' report:
109
+ # ignore_eq_base:
110
+ # all:
111
+ # - common.ok
112
+ # fr,es:
113
+ # - common.brand
114
+
115
+ ## Exclude these keys from the `i18n-tasks check-consistent-interpolations` report:
116
+ # ignore_inconsistent_interpolations:
117
+ # - 'activerecord.attributes.*'
118
+
119
+ ## Ignore these keys completely:
120
+ # ignore:
121
+ # - kaminari.*
122
+
123
+ ## Sometimes, it isn't possible for i18n-tasks to match the key correctly,
124
+ ## e.g. in case of a relative key defined in a helper method.
125
+ ## In these cases you can use the built-in PatternMapper to map patterns to keys, e.g.:
126
+ #
127
+ # <%# I18n::Tasks.add_scanner 'I18n::Tasks::Scanners::PatternMapper',
128
+ # only: %w(*.html.haml *.html.slim),
129
+ # patterns: [['= title\b', '.page_title']] %>
130
+ #
131
+ # The PatternMapper can also match key literals via a special %{key} interpolation, e.g.:
132
+ #
133
+ # <%# I18n::Tasks.add_scanner 'I18n::Tasks::Scanners::PatternMapper',
134
+ # patterns: [['\bSpree\.t[( ]\s*%{key}', 'spree.%{key}']] %>
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ pin_all_from File.expand_path('../app/assets/javascript', __dir__)
@@ -0,0 +1,100 @@
1
+ ---
2
+ en:
3
+ arclight:
4
+ breadcrumbs:
5
+ aria_label: breadcrumb
6
+ collection_info_component:
7
+ collection_id: Collection ID
8
+ last_indexed: Last indexed
9
+ more_info: More info
10
+ online_items: Items available online
11
+ total_components: Total components
12
+ hierarchy:
13
+ view_all: View
14
+ masthead_heading_html: Archival Collections at Institution
15
+ repositories: Repositories
16
+ request:
17
+ container: Request
18
+ routes:
19
+ collections: Collections
20
+ home: Home
21
+ repositories: Repositories
22
+ search_results: Search results
23
+ search:
24
+ collections_header: Collections
25
+ repository_header: 'Collections : [%{repository}]'
26
+ show_breadcrumb_label: Repository
27
+ truncation:
28
+ view_less: view less
29
+ view_more: view more
30
+ views:
31
+ index:
32
+ all_group_results: view all %{count}
33
+ all_results: All results
34
+ group_by_collection: Grouped by collection
35
+ group_results: Group results
36
+ group_results_count:
37
+ one: 1 result
38
+ other: "%{count} results"
39
+ zero: 0 results
40
+ number_of_components:
41
+ one: component
42
+ other: components
43
+ top_group_results:
44
+ one: Top %{count} result
45
+ other: Top %{count} results
46
+ repositories:
47
+ number_of_collections:
48
+ one: 1 collection
49
+ other: "%{count} collections"
50
+ zero: No collections
51
+ show: "%{name} - Arclight"
52
+ title: Repositories - Arclight
53
+ view_all_collections: View all of our collections
54
+ view_more: View more
55
+ show:
56
+ collection_id: 'Collection ID: %{id}'
57
+ contents: Contents
58
+ context: Collection context
59
+ context_nav:
60
+ title: Collection overview
61
+ download:
62
+ default: Download
63
+ multiple:
64
+ ead: EAD
65
+ pdf: Finding aid
66
+ single:
67
+ ead: Download EAD
68
+ pdf: Download finding aid
69
+ embedded_content: Online content
70
+ expand: Expand
71
+ has_content: Collection contents
72
+ online_content:
73
+ description: Some materials from this collection are available online.
74
+ link_text: Show only online content
75
+ title: Online content
76
+ our_collections: Our Collections
77
+ sections:
78
+ access_field: Access and use
79
+ background_field: Background
80
+ collection_context_field: Collection context
81
+ component_field: About this %{level}
82
+ component_indexed_terms_field: Indexed terms
83
+ indexed_terms_field: Indexed terms
84
+ related_field: Related
85
+ scope_and_arrangement_field: Scope and arrangement
86
+ summary_field: Summary
87
+ toggle_sidebar: Navigate the collection
88
+ within_collection_dropdown:
89
+ all_collections: all collections
90
+ label_html: Search<span class="sr-only visually-hidden"> within</span>
91
+ this_collection: this collection
92
+ blacklight:
93
+ entry_name:
94
+ grouped:
95
+ _root_: collections
96
+ search:
97
+ pagination_info:
98
+ pages:
99
+ one: "<strong>%{start_num}</strong> - <strong>%{end_num}</strong> of <strong>%{total_num} %{entry_name}</strong>"
100
+ other: "<strong>%{start_num}</strong> - <strong>%{end_num}</strong> of <strong>%{total_num} %{entry_name}</strong>"
File without changes
data/config/routes.rb ADDED
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ Arclight::Engine.routes.draw do
4
+ get 'collections' => 'catalog#index', defaults: { f: { level: ['Collection'] } }, as: :collections
5
+ resources :repositories, only: %i[index show], controller: 'arclight/repositories'
6
+ end
@@ -0,0 +1,16 @@
1
+ version: "3.7"
2
+
3
+ services:
4
+ solr:
5
+ image: solr:latest
6
+ volumes:
7
+ - $PWD/solr/conf:/opt/solr/conf
8
+ ports:
9
+ - 8983:8983
10
+ entrypoint:
11
+ - docker-entrypoint.sh
12
+ - solr-precreate
13
+ - blacklight-core
14
+ - /opt/solr/conf
15
+ - "-Xms256m"
16
+ - "-Xmx512m"
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arclight
4
+ ##
5
+ # Plain ruby class to model serializing/deserializing digital object data
6
+ class DigitalObject
7
+ attr_reader :label, :href
8
+
9
+ def initialize(label:, href:)
10
+ @label = label.presence || href
11
+ @href = href
12
+ end
13
+
14
+ def to_json(*)
15
+ { label: label, href: href }.to_json
16
+ end
17
+
18
+ def self.from_json(json)
19
+ object_data = JSON.parse(json)
20
+ new(label: object_data['label'], href: object_data['href'])
21
+ end
22
+
23
+ def ==(other)
24
+ href == other.href && label == other.label
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'blacklight'
4
+ require 'traject'
5
+ require 'active_model'
6
+ require 'arclight/exceptions'
7
+ require 'arclight/normalized_date'
8
+ require 'arclight/normalized_id'
9
+ require 'arclight/normalized_title'
10
+ require 'arclight/digital_object'
11
+ require 'gretel'
12
+
13
+ module Arclight
14
+ ##
15
+ # This is the defining class for the Arclight Rails Engine
16
+ class Engine < ::Rails::Engine
17
+ config.oembed_resource_exclude_patterns = [/\.pdf$/, /\.ppt$/]
18
+
19
+ Arclight::Engine.config.catalog_controller_group_query_params = {
20
+ group: true,
21
+ 'group.field': '_root_',
22
+ 'group.ngroups': true,
23
+ 'group.limit': 3,
24
+ fl: '*,collection:[subquery]',
25
+ 'collection.q': '{!terms f=id v=$row._root_}',
26
+ 'collection.defType': 'lucene',
27
+ 'collection.fl': '*',
28
+ 'collection.rows': 1
29
+ }
30
+
31
+ initializer 'arclight.helpers' do
32
+ config.after_initialize do
33
+ ActiveSupport.on_load(:action_view) { include ArclightHelper }
34
+ end
35
+ end
36
+
37
+ initializer 'arclight.assets', before: 'assets' do |app|
38
+ app.config.assets.precompile << 'arclight/arclight.js'
39
+ app.config.assets.precompile << 'arclight/oembed_controller.js'
40
+ app.config.assets.precompile << 'arclight/truncate_controller.js'
41
+ end
42
+
43
+ initializer 'arclight.importmap', before: 'importmap' do |app|
44
+ app.config.importmap.paths << Engine.root.join('config/importmap.rb') if app.config.respond_to?(:importmap)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arclight
4
+ module Exceptions
5
+ # Id's must be present on all documents and components
6
+ class IDNotFound < StandardError
7
+ def message
8
+ 'id must be present for all documents and components'
9
+ end
10
+ end
11
+
12
+ # Unittitle or unitdate must be present on all documents and components
13
+ class TitleNotFound < StandardError
14
+ def message
15
+ '<unittitle/> or <unitdate/> must be present for all documents and components'
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'digest'
4
+
5
+ module Arclight
6
+ ##
7
+ # Take a Nokogiri node and get its absolute path (inserting our own indexes for component levels)
8
+ # and hash that outout. This is intended as a potential strategy for handling missing IDs in EADs.
9
+ class HashAbsoluteXpath
10
+ class << self
11
+ attr_writer :hash_algorithm
12
+
13
+ def hash_algorithm
14
+ return Digest::SHA1 unless defined? @hash_algorithm
15
+
16
+ @hash_algorithm
17
+ end
18
+ end
19
+
20
+ COMPONENT_NODE_NAME_REGEX = /^c\d{,2}$/
21
+ attr_reader :node
22
+
23
+ def initialize(node)
24
+ @node = node
25
+ end
26
+
27
+ def to_hexdigest
28
+ self.class.hash_algorithm.hexdigest(absolute_xpath).prepend('al_')
29
+ end
30
+
31
+ def absolute_xpath
32
+ ancestor_tree = node.ancestors.map do |ancestor|
33
+ ancestor_name_and_index(ancestor)
34
+ end
35
+
36
+ "#{[ancestor_tree.reverse, node.name].flatten.join('/')}#{current_index}"
37
+ end
38
+
39
+ private
40
+
41
+ def current_index
42
+ siblings.index(node)
43
+ end
44
+
45
+ def component_siblings_for_node(xml_node)
46
+ xml_node.parent.children.select { |n| n.name =~ COMPONENT_NODE_NAME_REGEX }
47
+ end
48
+
49
+ def siblings
50
+ @siblings ||= component_siblings_for_node(node)
51
+ end
52
+
53
+ def ancestor_name_and_index(ancestor)
54
+ if ancestor.name =~ COMPONENT_NODE_NAME_REGEX
55
+ index = component_siblings_for_node(ancestor).index(ancestor)
56
+ "#{ancestor.name}#{index}"
57
+ else
58
+ ancestor.name
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arclight
4
+ ##
5
+ # A utility class to return a human-readable label for an EAD @level code.
6
+ # Can use the value from @otherlevel if provided.
7
+ # Examples from @level: recordgrp = "Record Group"
8
+ # collection = "Collection"
9
+ # subseries = "Subseries"
10
+ # otherlevel = (text provided in @otherlevel)
11
+ class LevelLabel
12
+ # @param [String] `level` from the collection or component @level
13
+ # @param [String] `other_level` from the collection or component @otherlevel
14
+ def initialize(level, other_level = nil)
15
+ @level = level
16
+ @other_level = other_level if other_level.present?
17
+ end
18
+
19
+ # @return [String] the human-readable label
20
+ def to_s
21
+ human_readable_level
22
+ end
23
+
24
+ private
25
+
26
+ attr_reader :level, :other_level
27
+
28
+ CUSTOM_LEVEL_LABELS = {
29
+ recordgrp: 'Record Group',
30
+ subgrp: 'Subgroup'
31
+ }.freeze
32
+
33
+ def human_readable_level
34
+ if level == 'otherlevel'
35
+ alternative_level
36
+ elsif level.present?
37
+ CUSTOM_LEVEL_LABELS.fetch(level.to_sym, level.capitalize).to_s
38
+ end
39
+ end
40
+
41
+ def alternative_level
42
+ alternative_level = other_level if other_level
43
+ alternative_level.present? ? alternative_level.capitalize : 'Other'
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'arclight/hash_absolute_xpath'
4
+
5
+ module Arclight
6
+ ##
7
+ # A class to configure a selected MissingIdStrategy.
8
+ # Defaults to Arclight::HashAbsoluteXpath
9
+ # This can be updated in an initializer to be any other class
10
+ class MissingIdStrategy
11
+ class << self
12
+ attr_writer :selected
13
+
14
+ def selected
15
+ return Arclight::HashAbsoluteXpath unless defined? @selected
16
+
17
+ @selected
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arclight
4
+ ##
5
+ # A utility class to normalize dates, typically by joining inclusive and bulk dates
6
+ # e.g., "1990-2000, bulk 1990-1999"
7
+ # @see http://www2.archivists.org/standards/DACS/part_I/chapter_2/4_date
8
+ class NormalizedDate
9
+ # @param [String | Array<String>] `inclusive` from the `unitdate`
10
+ # @param [Array<String>] `bulk` from the `unitdate`
11
+ # @param [Array<String>] `other` from the `unitdate` when type is not specified
12
+ def initialize(inclusive, bulk = [], other = [])
13
+ @inclusive = (inclusive || []).map do |inclusive_text|
14
+ if inclusive_text.is_a? Array # of YYYY-YYYY for ranges
15
+ # NOTE: This code is not routable AFAICT in actual indexing.
16
+ # We pass arrays of strings (or xml nodes) here, and never a multidimensional array
17
+ year_range(inclusive_text)
18
+ elsif inclusive_text.present?
19
+ inclusive_text.strip
20
+ end
21
+ end&.join(', ')
22
+
23
+ @bulk = Array.wrap(bulk).compact.map(&:strip).join(', ')
24
+ @other = Array.wrap(other).compact.map(&:strip).join(', ')
25
+ end
26
+
27
+ # @return [String] the normalized title/date
28
+ def to_s
29
+ normalize
30
+ end
31
+
32
+ private
33
+
34
+ attr_reader :inclusive, :bulk, :other
35
+
36
+ def year_range(date_array)
37
+ YearRange.new(date_array.include?('/') ? date_array : date_array.map { |v| v.tr('-', '/') }).to_s
38
+ end
39
+
40
+ # @see http://www2.archivists.org/standards/DACS/part_I/chapter_2/4_date for rules
41
+ def normalize
42
+ result = []
43
+ result << inclusive if inclusive.present?
44
+ result << other if other.present?
45
+ result << "bulk #{bulk}" if bulk.present?
46
+ result.compact.map(&:strip).join(', ').presence
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'arclight/exceptions'
4
+
5
+ module Arclight
6
+ ##
7
+ # A simple utility class to normalize identifiers
8
+ class NormalizedId
9
+ # Accepts unused kwargs from the ead2_config.rb id to_field directive
10
+ # (:title and :repository) so that applications can provide a custom
11
+ # id_normalizer class to traject to form the collection id from these attributes.
12
+ def initialize(id, **_kwargs)
13
+ @id = id
14
+ end
15
+
16
+ def to_s
17
+ normalize
18
+ end
19
+
20
+ private
21
+
22
+ attr_reader :id
23
+
24
+ def normalize
25
+ raise Arclight::Exceptions::IDNotFound if id.blank?
26
+
27
+ id.strip.tr('.', '-')
28
+ end
29
+ end
30
+ end