arclight 0.2.0 → 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 (246) hide show
  1. checksums.yaml +4 -4
  2. data/.all-contributorsrc +450 -0
  3. data/.codeclimate.yml +5 -0
  4. data/.eslintrc +14 -4
  5. data/.github/workflows/ruby.yml +51 -0
  6. data/.gitignore +1 -0
  7. data/.rspec +0 -1
  8. data/.rubocop.yml +504 -8
  9. data/.rubocop_todo.yml +62 -199
  10. data/.solr_wrapper +2 -1
  11. data/CONTRIBUTING.md +5 -5
  12. data/CONTRIBUTORS.md +79 -0
  13. data/Gemfile +15 -10
  14. data/README.md +36 -34
  15. data/Rakefile +0 -1
  16. data/app/assets/images/blacklight/bookmark.svg +1 -0
  17. data/app/assets/images/blacklight/collection.svg +5 -0
  18. data/app/assets/images/blacklight/compact.svg +1 -25
  19. data/app/assets/images/blacklight/container.svg +5 -0
  20. data/app/assets/images/blacklight/ead.svg +1 -0
  21. data/app/assets/images/blacklight/file.svg +5 -0
  22. data/app/assets/images/blacklight/folder.svg +1 -0
  23. data/app/assets/images/blacklight/list.svg +1 -0
  24. data/app/assets/images/blacklight/minus.svg +1 -0
  25. data/app/assets/images/blacklight/online.svg +5 -0
  26. data/app/assets/images/blacklight/pdf.svg +1 -0
  27. data/app/assets/images/blacklight/plus.svg +1 -0
  28. data/app/assets/images/blacklight/repository.svg +1 -0
  29. data/app/assets/javascripts/arclight/arclight.js +4 -10
  30. data/app/assets/javascripts/arclight/oembed_controller.js +58 -0
  31. data/app/assets/javascripts/arclight/truncate_controller.js +27 -0
  32. data/app/assets/stylesheets/arclight/application.scss +4 -4
  33. data/app/assets/stylesheets/arclight/build.scss +4 -0
  34. data/app/assets/stylesheets/arclight/modules/hierarchy_and_online_contents.scss +117 -146
  35. data/app/assets/stylesheets/arclight/modules/highlights.scss +2 -1
  36. data/app/assets/stylesheets/arclight/modules/icons.scss +20 -0
  37. data/app/assets/stylesheets/arclight/modules/layout.scss +183 -40
  38. data/app/assets/stylesheets/arclight/modules/mastheads.scss +24 -75
  39. data/app/assets/stylesheets/arclight/modules/repositories.scss +3 -7
  40. data/app/assets/stylesheets/arclight/modules/repository_card.scss +5 -50
  41. data/app/assets/stylesheets/arclight/modules/search_form.scss +9 -0
  42. data/app/assets/stylesheets/arclight/modules/search_results.scss +197 -26
  43. data/app/assets/stylesheets/arclight/modules/show_collection.scss +21 -69
  44. data/app/assets/stylesheets/arclight/modules/truncator.scss +58 -0
  45. data/app/assets/stylesheets/arclight/responsive.scss +13 -0
  46. data/app/assets/stylesheets/arclight/variables.scss +25 -2
  47. data/app/components/arclight/access_component.html.erb +14 -0
  48. data/app/components/arclight/access_component.rb +25 -0
  49. data/app/components/arclight/bookmark_component.html.erb +25 -0
  50. data/app/components/arclight/bookmark_component.rb +9 -0
  51. data/app/components/arclight/breadcrumb_component.rb +50 -0
  52. data/app/components/arclight/breadcrumbs_hierarchy_component.html.erb +34 -0
  53. data/app/components/arclight/breadcrumbs_hierarchy_component.rb +25 -0
  54. data/app/components/arclight/collection_context_component.html.erb +12 -0
  55. data/app/components/arclight/collection_context_component.rb +27 -0
  56. data/app/components/arclight/collection_info_component.html.erb +28 -0
  57. data/app/components/arclight/collection_info_component.rb +26 -0
  58. data/app/components/arclight/collection_sidebar_component.html.erb +15 -0
  59. data/app/components/arclight/collection_sidebar_component.rb +39 -0
  60. data/app/{views/catalog/_search_results_repository.html.erb → components/arclight/constraints_component.html.erb} +2 -1
  61. data/app/components/arclight/constraints_component.rb +17 -0
  62. data/app/components/arclight/document_collection_context_component.html.erb +29 -0
  63. data/app/components/arclight/document_collection_context_component.rb +28 -0
  64. data/app/components/arclight/document_collection_hierarchy_component.html.erb +50 -0
  65. data/app/components/arclight/document_collection_hierarchy_component.rb +62 -0
  66. data/app/components/arclight/document_component.html.erb +39 -0
  67. data/app/components/arclight/document_component.rb +49 -0
  68. data/app/components/arclight/document_components_hierarchy_component.html.erb +20 -0
  69. data/app/components/arclight/document_components_hierarchy_component.rb +34 -0
  70. data/app/components/arclight/document_download_component.html.erb +24 -0
  71. data/app/components/arclight/document_download_component.rb +71 -0
  72. data/app/components/arclight/embed_component.html.erb +10 -0
  73. data/app/components/arclight/embed_component.rb +43 -0
  74. data/app/components/arclight/expand_hierarchy_button_component.html.erb +5 -0
  75. data/app/components/arclight/expand_hierarchy_button_component.rb +16 -0
  76. data/app/components/arclight/group_component.html.erb +34 -0
  77. data/app/components/arclight/group_component.rb +23 -0
  78. data/app/components/arclight/header_component.html.erb +5 -0
  79. data/app/components/arclight/header_component.rb +10 -0
  80. data/app/components/arclight/index_metadata_field_component.html.erb +16 -0
  81. data/app/components/arclight/index_metadata_field_component.rb +20 -0
  82. data/app/components/arclight/masthead_component.html.erb +17 -0
  83. data/app/components/arclight/masthead_component.rb +10 -0
  84. data/app/components/arclight/metadata_section_component.html.erb +13 -0
  85. data/app/components/arclight/metadata_section_component.rb +22 -0
  86. data/app/components/arclight/oembed_viewer_component.html.erb +5 -0
  87. data/app/components/arclight/oembed_viewer_component.rb +16 -0
  88. data/app/components/arclight/online_content_filter_component.html.erb +15 -0
  89. data/app/components/arclight/online_content_filter_component.rb +17 -0
  90. data/app/components/arclight/online_status_indicator_component.rb +19 -0
  91. data/app/components/arclight/repository_breadcrumb_component.html.erb +10 -0
  92. data/app/components/arclight/repository_breadcrumb_component.rb +17 -0
  93. data/app/components/arclight/repository_location_component.html.erb +20 -0
  94. data/app/components/arclight/repository_location_component.rb +10 -0
  95. data/app/components/arclight/search_bar_component.html.erb +27 -0
  96. data/app/components/arclight/search_bar_component.rb +32 -0
  97. data/app/components/arclight/search_result_breadcrumbs_component.html.erb +6 -0
  98. data/app/components/arclight/search_result_breadcrumbs_component.rb +37 -0
  99. data/app/components/arclight/search_result_component.html.erb +20 -0
  100. data/app/components/arclight/search_result_component.rb +18 -0
  101. data/app/components/arclight/search_result_title_component.html.erb +15 -0
  102. data/app/components/arclight/search_result_title_component.rb +15 -0
  103. data/app/components/arclight/sidebar_component.html.erb +9 -0
  104. data/app/components/arclight/sidebar_component.rb +19 -0
  105. data/app/components/arclight/upper_metadata_layout_component.rb +10 -0
  106. data/app/components/blacklight/icons/bookmark_component.rb +12 -0
  107. data/app/components/blacklight/icons/collection_component.rb +14 -0
  108. data/app/components/blacklight/icons/compact_component.rb +12 -0
  109. data/app/components/blacklight/icons/container_component.rb +14 -0
  110. data/app/components/blacklight/icons/ead_component.rb +12 -0
  111. data/app/components/blacklight/icons/file_component.rb +14 -0
  112. data/app/components/blacklight/icons/folder_component.rb +12 -0
  113. data/app/components/blacklight/icons/online_component.rb +15 -0
  114. data/app/components/blacklight/icons/pdf_component.rb +12 -0
  115. data/app/components/blacklight/icons/repository_component.rb +12 -0
  116. data/app/controllers/arclight/repositories_controller.rb +4 -4
  117. data/app/helpers/arclight/ead_format_helpers.rb +309 -0
  118. data/app/helpers/arclight/field_config_helpers.rb +26 -0
  119. data/app/helpers/arclight_helper.rb +55 -120
  120. data/app/models/arclight/document_downloads.rb +122 -0
  121. data/app/models/arclight/parent.rb +9 -9
  122. data/app/models/arclight/parents.rb +9 -4
  123. data/app/models/arclight/requests/aeon_external_request.rb +42 -0
  124. data/app/models/arclight/requests/aeon_web_ead.rb +52 -0
  125. data/app/models/arclight/requests/google_form.rb +8 -3
  126. data/app/models/concerns/arclight/catalog.rb +33 -11
  127. data/app/models/concerns/arclight/search_behavior.rb +22 -21
  128. data/app/models/concerns/arclight/solr_document.rb +88 -59
  129. data/app/presenters/arclight/show_presenter.rb +34 -7
  130. data/app/views/arclight/_requests.html.erb +7 -0
  131. data/app/views/arclight/repositories/_repository.html.erb +22 -41
  132. data/app/views/arclight/repositories/index.html.erb +5 -0
  133. data/app/views/arclight/repositories/show.html.erb +7 -8
  134. data/app/views/arclight/requests/_aeon_external_request_endpoint.html.erb +8 -0
  135. data/app/views/arclight/requests/_aeon_web_ead.html.erb +6 -0
  136. data/app/views/arclight/requests/_google_form.html.erb +4 -5
  137. data/app/views/catalog/_document_list.html.erb +8 -0
  138. data/app/views/catalog/_group.html.erb +4 -0
  139. data/app/views/catalog/_group_toggle.html.erb +10 -0
  140. data/app/views/catalog/_search_results_header.html.erb +3 -0
  141. data/app/views/catalog/hierarchy.html.erb +19 -0
  142. data/app/views/catalog/index.html.erb +16 -7
  143. data/app/views/shared/_breadcrumbs.html.erb +3 -15
  144. data/app/views/shared/_main_menu_links.html.erb +1 -1
  145. data/arclight.gemspec +18 -17
  146. data/config/breadcrumbs.rb +24 -0
  147. data/config/i18n-tasks.yml +11 -9
  148. data/config/importmap.rb +3 -0
  149. data/config/locales/arclight.en.yml +68 -34
  150. data/config/routes.rb +1 -1
  151. data/docker-compose.yml +16 -0
  152. data/lib/arclight/digital_object.rb +2 -1
  153. data/lib/arclight/engine.rb +22 -31
  154. data/lib/arclight/exceptions.rb +1 -0
  155. data/lib/arclight/hash_absolute_xpath.rb +13 -8
  156. data/lib/arclight/level_label.rb +46 -0
  157. data/lib/arclight/normalized_date.rb +5 -10
  158. data/lib/arclight/normalized_id.rb +7 -2
  159. data/lib/arclight/normalized_title.rb +3 -0
  160. data/lib/arclight/repository.rb +70 -28
  161. data/lib/arclight/routes/hierarchy.rb +19 -0
  162. data/lib/arclight/routes.rb +8 -0
  163. data/lib/arclight/traject/ead2_component_config.rb +335 -0
  164. data/lib/arclight/traject/ead2_config.rb +172 -331
  165. data/lib/arclight/traject/nokogiri_namespaceless_reader.rb +22 -0
  166. data/lib/arclight/version.rb +1 -1
  167. data/lib/arclight/year_range.rb +13 -4
  168. data/lib/arclight.rb +6 -1
  169. data/lib/generators/arclight/install_generator.rb +100 -10
  170. data/lib/generators/arclight/templates/arclight.scss +6 -3
  171. data/lib/generators/arclight/templates/catalog_controller.rb +237 -179
  172. data/lib/generators/arclight/templates/config/downloads.yml +12 -0
  173. data/lib/generators/arclight/templates/config/locales/arclight.en.yml +61 -0
  174. data/lib/generators/arclight/templates/config/repositories.yml +42 -31
  175. data/lib/generators/arclight/update_generator.rb +1 -1
  176. data/lib/tasks/index.rake +25 -30
  177. data/package.json +15 -9
  178. data/solr/conf/schema.xml +97 -328
  179. data/solr/conf/solrconfig.xml +99 -164
  180. data/tasks/arclight.rake +18 -9
  181. data/template.rb +6 -7
  182. metadata +188 -129
  183. data/.travis.yml +0 -28
  184. data/app/assets/javascripts/arclight/collection_context.js +0 -18
  185. data/app/assets/javascripts/arclight/collection_navigation.js +0 -117
  186. data/app/assets/javascripts/arclight/collection_scrollspy.js +0 -6
  187. data/app/assets/javascripts/arclight/component_ancestors.js +0 -56
  188. data/app/assets/javascripts/arclight/oembed_viewer.js +0 -46
  189. data/app/assets/javascripts/arclight/search_results.js +0 -15
  190. data/app/assets/javascripts/arclight/truncator.js.erb +0 -23
  191. data/app/assets/stylesheets/arclight/bootstrap_overrides.scss +0 -3
  192. data/app/assets/stylesheets/arclight/modules/sidebar.scss +0 -21
  193. data/app/controllers/concerns/arclight/field_config_helpers.rb +0 -86
  194. data/app/factories/blacklight_field_configuration_factory.rb +0 -29
  195. data/app/views/arclight/repositories/_in_person_repository.html.erb +0 -19
  196. data/app/views/arclight/viewers/_oembed.html.erb +0 -7
  197. data/app/views/catalog/_arclight_document_index_header.html.erb +0 -13
  198. data/app/views/catalog/_arclight_document_index_header_online_contents_default.html.erb +0 -0
  199. data/app/views/catalog/_arclight_index_compact_default.html.erb +0 -15
  200. data/app/views/catalog/_arclight_online_content_indicator.html.erb +0 -5
  201. data/app/views/catalog/_arclight_rangelimit.html.erb +0 -24
  202. data/app/views/catalog/_arclight_viewer_default.html.erb +0 -1
  203. data/app/views/catalog/_collection_contents.html.erb +0 -12
  204. data/app/views/catalog/_collection_count.html.erb +0 -7
  205. data/app/views/catalog/_collection_downloads.html.erb +0 -15
  206. data/app/views/catalog/_collection_online_contents.html.erb +0 -17
  207. data/app/views/catalog/_collection_overview.html.erb +0 -7
  208. data/app/views/catalog/_component_contents.html.erb +0 -16
  209. data/app/views/catalog/_component_overview.html.erb +0 -40
  210. data/app/views/catalog/_context_card.html.erb +0 -27
  211. data/app/views/catalog/_context_sidebar.html.erb +0 -8
  212. data/app/views/catalog/_custom_metadata.html.erb +0 -16
  213. data/app/views/catalog/_home.html.erb +0 -1
  214. data/app/views/catalog/_index_breadcrumb_default.html.erb +0 -3
  215. data/app/views/catalog/_index_default.html.erb +0 -17
  216. data/app/views/catalog/_index_header.html.erb +0 -7
  217. data/app/views/catalog/_index_header_hierarchy_default.html.erb +0 -42
  218. data/app/views/catalog/_index_header_online_contents_default.html.erb +0 -1
  219. data/app/views/catalog/_index_hierarchy_default.html.erb +0 -28
  220. data/app/views/catalog/_index_online_contents_default.html.erb +0 -6
  221. data/app/views/catalog/_results_histogram.html.erb +0 -15
  222. data/app/views/catalog/_search_results.html.erb +0 -31
  223. data/app/views/catalog/_show_breadcrumbs_default.html.erb +0 -21
  224. data/app/views/catalog/_show_collection.html.erb +0 -48
  225. data/app/views/catalog/_show_component_sidebar.html.erb +0 -12
  226. data/app/views/catalog/_show_default.html.erb +0 -42
  227. data/app/views/catalog/_show_sidebar.html.erb +0 -22
  228. data/app/views/catalog/_show_upper_metadata_collection.html.erb +0 -1
  229. data/app/views/catalog/_show_upper_metadata_default.html.erb +0 -14
  230. data/app/views/layouts/catalog_result.html.erb +0 -7
  231. data/app/views/shared/_context_sidebar.html.erb +0 -8
  232. data/app/views/shared/_header_navbar.html.erb +0 -65
  233. data/lib/arclight/custom_component.rb +0 -99
  234. data/lib/arclight/custom_document.rb +0 -93
  235. data/lib/arclight/indexer.rb +0 -9
  236. data/lib/arclight/shared_indexing_behavior.rb +0 -97
  237. data/lib/arclight/shared_terminology_behavior.rb +0 -65
  238. data/lib/arclight/solr_ead_indexer_ext.rb +0 -155
  239. data/lib/arclight/viewer.rb +0 -45
  240. data/lib/arclight/viewers/oembed.rb +0 -56
  241. data/lib/generators/arclight/templates/arclight.js +0 -2
  242. data/solr/conf/scripts.conf +0 -24
  243. data/vendor/assets/javascripts/responsiveTruncator.js +0 -69
  244. data/vendor/assets/javascripts/stickyfill.js +0 -480
  245. /data/app/assets/images/{blacklight → arclight}/logo.png +0 -0
  246. /data/{app/views/catalog/_arclight_document_index_header_hierarchy_default.html.erb → config/repositories.yml} +0 -0
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arclight
4
+ # Render access information for a document
5
+ class AccessComponent < ViewComponent::Base
6
+ def initialize(presenter:)
7
+ super()
8
+ @show_config = presenter.configuration.show
9
+ @presenter = presenter
10
+ end
11
+
12
+ attr_reader :presenter, :show_config
13
+
14
+ delegate :collection?, to: :presenter
15
+
16
+ # @return Array<Symbol> a list of metadata section names
17
+ def section_names
18
+ return Array(collection_access_items) if collection?
19
+
20
+ Array(component_access_items)
21
+ end
22
+
23
+ delegate :collection_access_items, :component_access_items, to: :show_config
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ <% if current_or_guest_user %>
2
+ <%= form_tag(bookmark_path,
3
+ authenticity_token: false,
4
+ method: bookmarked? ? :delete : :put,
5
+ class: "bookmark-toggle ms-2",
6
+ data: {
7
+ 'doc-id' => document.id,
8
+ present: "#{blacklight_icon(:bookmark).html_safe}<span class=\"sr-only visually-hidden\">#{t('blacklight.search.bookmarks.present')}</span>",
9
+ absent: "#{blacklight_icon(:bookmark).html_safe}<span class=\"sr-only visually-hidden\">#{t('blacklight.search.bookmarks.absent')}</span>",
10
+ inprogress: t('blacklight.search.bookmarks.inprogress')
11
+ }) do %>
12
+ <div class="checkbox toggle-bookmark">
13
+ <label class="toggle-bookmark" data-checkboxsubmit-target="label">
14
+ <input type="checkbox" class="toggle-bookmark" data-checkboxsubmit-target="checkbox" <%= 'checked="checked"' if bookmarked? %>>
15
+ <span data-checkboxsubmit-target="span"><%= bookmarked? ? "#{blacklight_icon(:bookmark).html_safe}<span class=\"sr-only visually-hidden\">#{t('blacklight.search.bookmarks.present')}</span>".html_safe : "#{blacklight_icon(:bookmark).html_safe}<span class=\"sr-only visually-hidden\">#{t('blacklight.search.bookmarks.absent')}</span>".html_safe %></span>
16
+ </label>
17
+ </div>
18
+
19
+ <%= submit_tag(t(bookmarked? ? 'remove.button' : 'add.button', scope: 'blacklight.bookmarks'),
20
+ id: "bookmark_toggle_#{document.id.to_s.parameterize}",
21
+ class: "bookmark-#{bookmarked? ? 'remove' : 'add'} btn btn-outline-secondary") %>
22
+ <% end %>
23
+ <% else %>
24
+ &nbsp;
25
+ <% end %>
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arclight
4
+ # A component to render a bookmark button for a document
5
+ class BookmarkComponent < Blacklight::Document::BookmarkComponent
6
+ delegate :current_or_guest_user, :blacklight_icon, to: :helpers
7
+ attr_accessor :document
8
+ end
9
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arclight
4
+ # Display the document hierarchy as "breadcrumbs"
5
+ class BreadcrumbComponent < ViewComponent::Base
6
+ # @param [Integer] count if provided the number of bookmarks is limited to this number
7
+ def initialize(document:, count: nil, offset: 0)
8
+ @document = document
9
+ @count = count
10
+ @offset = offset
11
+ super()
12
+ end
13
+
14
+ def call
15
+ return unless breadcrumb_links.any?
16
+
17
+ tag.ol class: 'breadcrumb' do
18
+ safe_join(breadcrumb_links)
19
+ end
20
+ end
21
+
22
+ def components
23
+ return to_enum(:components) unless block_given?
24
+
25
+ yield build_repository_link
26
+
27
+ @document.parents.each do |parent|
28
+ yield tag.li(class: 'breadcrumb-item') { link_to(parent.label, solr_document_path(parent.id)) }
29
+ end
30
+ end
31
+
32
+ def build_repository_link
33
+ render Arclight::RepositoryBreadcrumbComponent.new(document: @document)
34
+ end
35
+
36
+ private
37
+
38
+ def breadcrumb_links
39
+ @breadcrumb_links ||= limit_breadcrumb_links(components.drop(@offset))
40
+ end
41
+
42
+ def limit_breadcrumb_links(links)
43
+ return links unless @count && links.length > @count
44
+
45
+ limited_links = links.first(@count)
46
+ limited_links << tag.li('&hellip;'.html_safe, class: 'breadcrumb-item')
47
+ limited_links
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,34 @@
1
+ <ol class="breadcrumb">
2
+ <li class="breadcrumb-home-link">
3
+ <%= link_to t('arclight.routes.home'), root_path %>
4
+ </li>
5
+ <li class="breadcrumb-item breadcrumb-item-1">
6
+ <span aria-hidden="true"><%= blacklight_icon :repository, classes: 'al-repository-content-icon' %></span>
7
+ <span class="breadcrumb-text"><%= repository %></span>
8
+ <ol class="breadcrumb">
9
+ <% if collection %>
10
+ <li class="breadcrumb-item breadcrumb-item-2">
11
+ <span aria-hidden="true"><%= blacklight_icon :collection, classes: 'al-collection-content-icon' %></span>
12
+ <span class="breadcrumb-text"><%= link_to collection.label, solr_document_path(collection.id) %></span>
13
+
14
+ <ol class="breadcrumb">
15
+ <% parents_under_collection.each do |parent| %>
16
+ <li class="breadcrumb-item breadcrumb-item-3">
17
+ <span class="breadcrumb-text"><%= link_to parent.label, solr_document_path(parent.id) %></span>
18
+ </li>
19
+ <% end %>
20
+
21
+ <li class="breadcrumb-item breadcrumb-item-4">
22
+ <span class="breadcrumb-text"><%= @presenter.heading %></span>
23
+ </li>
24
+ </ol>
25
+ </li>
26
+ <% else # this is a collection %>
27
+ <li class="breadcrumb-item breadcrumb-item-4">
28
+ <span aria-hidden="true"><%= blacklight_icon :collection, classes: 'al-collection-content-icon' %></span>
29
+ <span class="breadcrumb-text"><%= @presenter.heading %></span>
30
+ </li>
31
+ <% end %>
32
+ </ol>
33
+ </li>
34
+ </ol>
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arclight
4
+ # Render the hierarchy for a document
5
+ class BreadcrumbsHierarchyComponent < ViewComponent::Base
6
+ delegate :document, to: :@presenter
7
+ delegate :blacklight_icon, to: :helpers
8
+
9
+ def initialize(presenter:)
10
+ super()
11
+
12
+ @presenter = presenter
13
+ collections, @parents_under_collection = document.parents.partition(&:collection?)
14
+ @collection = collections.first
15
+ end
16
+
17
+ attr_reader :collection, :parents_under_collection
18
+
19
+ def repository
20
+ return tag.span(t('arclight.show_breadcrumb_label')) if document.repository_config.blank?
21
+
22
+ link_to(document.repository_config.name, helpers.arclight_engine.repository_path(document.repository_config.slug))
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,12 @@
1
+ <div class='al-show-actions-box mb-3'>
2
+ <div class="al-actions-box-container">
3
+ <button type="button" class="btn-close d-lg-none float-end mt-1 me-1" data-bs-dismiss="offcanvas" data-bs-target="#sidebar" aria-label="Close"></button>
4
+ <h2>Collection</h2>
5
+ <h3><%= title %></h3>
6
+
7
+ <div class="al-collection-context-actions d-flex flex-wrap gap-1">
8
+ <%= document_download %>
9
+ <%= collection_info %>
10
+ </div>
11
+ </div>
12
+ </div>
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arclight
4
+ # Render various actions for a collection (e.g. requesting, download links, etc)
5
+ class CollectionContextComponent < ViewComponent::Base
6
+ def initialize(presenter:, download_component:)
7
+ super()
8
+
9
+ @collection = presenter.document.collection
10
+ @download_component = download_component
11
+ end
12
+
13
+ attr_reader :collection
14
+
15
+ def title
16
+ collection.normalized_title
17
+ end
18
+
19
+ def document_download
20
+ render @download_component.new(downloads: collection.downloads) || Arclight::DocumentDownloadComponent.new(downloads: collection.downloads)
21
+ end
22
+
23
+ def collection_info
24
+ render Arclight::CollectionInfoComponent.new(collection: collection)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,28 @@
1
+ <div class='al-show-actions-box-info'>
2
+
3
+ <div class="dropdown">
4
+ <button class="dropdown-toggle btn btn-secondary btn-sm" type="button" data-bs-toggle="dropdown" aria-expanded="false">
5
+ <%= info_icon %> <%= t('.more_info') %>
6
+ </button>
7
+ <div class="dropdown-menu shadow-lg p-2" style="min-width: 300px;" >
8
+ <table style="width: 100%">
9
+ <tr>
10
+ <th scope="row"><%= t('.collection_id') %></th>
11
+ <td><%= collection_unitid %></td>
12
+ </tr>
13
+ <tr>
14
+ <th scope="row"><%= t('.total_components') %></th>
15
+ <td><%= total_component_count %></td>
16
+ </tr>
17
+ <tr>
18
+ <th scope="row"><%= t('.online_items') %></th>
19
+ <td><%= tag.span blacklight_icon(:online), class: 'al-online-content-icon' %><%= online_item_count %></td>
20
+ </tr>
21
+ <tr>
22
+ <th scope="row"><%= t('.last_indexed') %></th>
23
+ <td><%= last_indexed.strftime('%F') %></td>
24
+ </tr>
25
+ </table>
26
+ </div>
27
+ </div>
28
+ </div>
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arclight
4
+ # Render information about the collection
5
+ class CollectionInfoComponent < ViewComponent::Base
6
+ def initialize(collection:)
7
+ super()
8
+
9
+ @collection = collection
10
+ end
11
+
12
+ attr_reader :collection
13
+
14
+ delegate :total_component_count, :online_item_count, :last_indexed, :collection_unitid, to: :collection
15
+ delegate :blacklight_icon, to: :helpers
16
+
17
+ def info_icon
18
+ icon = <<~SVG
19
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-info-circle-fill" viewBox="0 0 16 16">
20
+ <path d="M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16zm.93-9.412-1 4.705c-.07.34.029.533.304.533.194 0 .487-.07.686-.246l-.088.416c-.287.346-.92.598-1.465.598-.703 0-1.002-.422-.808-1.319l.738-3.468c.064-.293.006-.399-.287-.47l-.451-.081.082-.381 2.29-.287zM8 5.5a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/>
21
+ </svg>
22
+ SVG
23
+ icon.html_safe # rubocop:disable Rails/OutputSafety
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,15 @@
1
+ <nav class="al-sidebar-navigation-context sidebar-section" aria-labelledby="collection-nav">
2
+ <h2 id="collection-nav"><%= t('arclight.views.show.context_nav.title') %></h2>
3
+ <ul class='nav flex-column'>
4
+ <% partials.each do |section| %>
5
+ <% next unless has_section?(section) %>
6
+ <li class='nav-item'>
7
+ <%= link_to section_label(section),
8
+ document_section_path(section),
9
+ class: 'nav-link pl-0 ps-0 py-1',
10
+ data: { turbolinks: 'false' }
11
+ %>
12
+ </li>
13
+ <% end %>
14
+ </ul>
15
+ </nav>
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arclight
4
+ # Draw the links to the collection info in the sidebar
5
+ class CollectionSidebarComponent < ViewComponent::Base
6
+ def initialize(document:, partials:, collection_presenter:)
7
+ super()
8
+
9
+ @document = document
10
+ @partials = Array(partials)
11
+ @collection_presenter = collection_presenter
12
+ end
13
+
14
+ attr_reader :document, :partials, :collection_presenter
15
+
16
+ def has_section?(section)
17
+ # Access field data comes from repositories.yml not from solr, so handle it in a different way.
18
+ return true if section == :access_field
19
+
20
+ collection_presenter.with_field_group(section).fields_to_render.any?
21
+ end
22
+
23
+ def document_section_path(section)
24
+ [document_path, section_anchor(section)].join
25
+ end
26
+
27
+ def section_label(section)
28
+ t("arclight.views.show.sections.#{section}")
29
+ end
30
+
31
+ def document_path
32
+ @document_path ||= solr_document_path(document.root)
33
+ end
34
+
35
+ def section_anchor(section)
36
+ "##{t("arclight.views.show.sections.#{section}").parameterize}"
37
+ end
38
+ end
39
+ end
@@ -1,6 +1,7 @@
1
- <% repository = repository_faceted_on %>
2
1
  <% if repository %>
3
2
  <div class="al-repository-card">
4
3
  <%= render repository %>
5
4
  </div>
6
5
  <% end %>
6
+
7
+ <%= render Blacklight::ConstraintsComponent.new(**@kwargs) %>
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arclight
4
+ # Extend the upstream constraints with breadcrumbs and
5
+ # repository context information
6
+ class ConstraintsComponent < Blacklight::ConstraintsComponent
7
+ def initialize(**kwargs)
8
+ super
9
+
10
+ @kwargs = kwargs
11
+ end
12
+
13
+ def repository
14
+ @repository ||= helpers.repository_faceted_on
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,29 @@
1
+ <%= tag.tr(
2
+ id: @document.id,
3
+ data: {
4
+ 'document-id': @document.id.to_s.parameterize,
5
+ 'document-counter': @counter,
6
+ },
7
+ itemscope: true,
8
+ itemtype: @document.itemtype,
9
+ class: classes.join(' ')) do %>
10
+ <td data-document-id="<%= document.id %>">
11
+ <div class="index_title document-title-heading" data-turbo="false">
12
+ <%= helpers.link_to_document document, counter: @counter %>
13
+ <% if document.children? %>
14
+ <span class="badge badge-pill bg-secondary badge-secondary al-number-of-children-badge"><%= document.number_of_children %><span class="sr-only visually-hidden"><%= t(:'arclight.views.index.number_of_components', count: document.number_of_children) %></span></span>
15
+ <% end %>
16
+ </div>
17
+ </td>
18
+
19
+ <%= tag.td class: 'text-muted' do %>
20
+ <%= document.containers.join(', ') %>
21
+ <% end %>
22
+
23
+ <%= tag.td class: 'text-end' do %>
24
+ <%= helpers.render_index_doc_actions document, wrapping_class: 'd-inline-flex justify-content-end' %>
25
+ <% end %>
26
+ </div>
27
+
28
+ <%= render Arclight::IndexMetadataFieldComponent.with_collection(@presenter&.field_presenters.select { |field| field.field_config.collection_context }, classes: ['col pl-0 my-0']) %>
29
+ <% end %>
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arclight
4
+ # Display a single document in the collection
5
+ class DocumentCollectionContextComponent < Arclight::SearchResultComponent
6
+ # @param [SolrDocument] document
7
+ def initialize(document: nil, blacklight_config: nil, **kwargs)
8
+ super(document: document, **kwargs)
9
+ @blacklight_config = blacklight_config
10
+ end
11
+
12
+ attr_reader :blacklight_config
13
+
14
+ def classes
15
+ (super - ['row'] + ['al-collection-context']).flatten
16
+ end
17
+
18
+ private
19
+
20
+ def online_status
21
+ render online_status_component.new(document: @document)
22
+ end
23
+
24
+ def online_status_component
25
+ blacklight_config.show.online_status_component || Arclight::OnlineStatusIndicatorComponent
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,50 @@
1
+ <%= content_tag :li,
2
+ id: "#{@document.id}-hierarchy-item",
3
+ data: {
4
+ 'document-id': @document.id.to_s.parameterize,
5
+ 'document-counter': @counter,
6
+ },
7
+ itemscope: true,
8
+ itemtype: @document.itemtype,
9
+ class: (classes.flatten + ['al-collection-context', ('al-hierarchy-highlight' if current_target?)].compact).join(' ') do %>
10
+ <div class="documentHeader" data-document-id="<%= document.id %>">
11
+ <% if document.children? %>
12
+ <%= link_to('',
13
+ "#collapsible-hierarchy-#{document.id}",
14
+ class: "al-toggle-view-children#{ ' collapsed' unless show_expanded?}",
15
+ aria: {
16
+ label: t('arclight.hierarchy.view_all'),
17
+ expanded: show_expanded?
18
+ },
19
+ data: {
20
+ bs_toggle: 'collapse',
21
+ toggle: 'collapse'
22
+ }
23
+ )
24
+ %>
25
+ <% end %>
26
+ <div class="index_title document-title-heading" data-turbo="false">
27
+ <% if current_target? %>
28
+ <%= document.normalized_title %>
29
+ <% else %>
30
+ <%= helpers.link_to_document document, counter: @counter %>
31
+ <% end %>
32
+ <% if document.children? %>
33
+ <span class="badge badge-pill bg-secondary badge-secondary al-number-of-children-badge"><%= document.number_of_children %><span class="sr-only visually-hidden"><%= t(:'arclight.views.index.number_of_components', count: document.number_of_children) %></span></span>
34
+ <% end %>
35
+ <%= online_status %>
36
+ </div>
37
+ <%= content_tag('div', class: 'al-document-container text-muted') do %>
38
+ <%= document.containers.join(', ') %>
39
+ <% end if document.containers.present? %>
40
+ </div>
41
+
42
+ <%= render Arclight::IndexMetadataFieldComponent.with_collection(@presenter&.field_presenters.select { |field| field.field_config.collection_context }, classes: ['col pl-0 my-0']) %>
43
+ <% if document.number_of_children > 0 %>
44
+ <%= content_tag(:div, id: "collapsible-hierarchy-#{document.id}",
45
+ class: "collapse al-collection-context-collapsible al-hierarchy-level-#{document.component_level} #{'show' if show_expanded?}"
46
+ ) do %>
47
+ <%= render Arclight::DocumentComponentsHierarchyComponent.new(document: @document, target_index: target_index) %>
48
+ <% end %>
49
+ <% end %>
50
+ <% end %>
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arclight
4
+ # Display a single document in the collection hierarchy
5
+ class DocumentCollectionHierarchyComponent < Arclight::SearchResultComponent
6
+ # @param [Blacklight::DocumentPresenter] document
7
+ # @param [String] nest_path determines which element to highlight
8
+ def initialize(document: nil, nest_path: nil, blacklight_config: nil, **kwargs)
9
+ super(document: document, **kwargs)
10
+ @nest_path = nest_path
11
+ @blacklight_config = blacklight_config
12
+ end
13
+
14
+ attr_reader :blacklight_config
15
+
16
+ def classes
17
+ super - ['row']
18
+ end
19
+
20
+ # we want to eager-load this document's children if we're in the
21
+ # target document's component hierarchy
22
+ def show_expanded?
23
+ within_original_tree?
24
+ end
25
+
26
+ # Solr nest paths are constructed using the path name and an index, e.g.
27
+ # `/components#5/components#3`.
28
+ #
29
+ # @return [String] the targeted index for this level of the hierarchy
30
+ def target_index
31
+ return -1 unless within_original_tree?
32
+
33
+ remaining_path = nest_path.sub("#{@document.nest_path}/", '')
34
+ current_component, _rest = remaining_path.split('/', 2)
35
+ _name, index = current_component.split('#', 2)
36
+
37
+ index&.to_i
38
+ end
39
+
40
+ private
41
+
42
+ # We're in the targeted document's original tree if the target nest path
43
+ # includes this document's path.
44
+ def within_original_tree?
45
+ nest_path&.start_with? "#{@document.nest_path}/"
46
+ end
47
+
48
+ def current_target?
49
+ nest_path == @document.nest_path
50
+ end
51
+
52
+ def online_status
53
+ render online_status_component.new(document: @document)
54
+ end
55
+
56
+ def online_status_component
57
+ blacklight_config.show.online_status_component || Arclight::OnlineStatusIndicatorComponent
58
+ end
59
+
60
+ attr_reader :nest_path
61
+ end
62
+ end
@@ -0,0 +1,39 @@
1
+ <div class='d-md-flex justify-content-between al-show'>
2
+ <div class='al-show-breadcrumb'>
3
+ <nav aria-label="breadcrumb">
4
+ <%= render breadcrumb_component.new(presenter: presenter) %>
5
+ </nav>
6
+ </div>
7
+ </div>
8
+
9
+ <div class="title-container">
10
+ <%= content_tag :h1 do %>
11
+ <%= document.normalized_title %>
12
+ <% end %>
13
+ <%= render 'arclight/requests', document: document %>
14
+ <%= render Arclight::BookmarkComponent.new document: document, action: bookmark_config %>
15
+ <%= toggle_sidebar %>
16
+ <%= online_filter %>
17
+ </div>
18
+
19
+ <%= render Arclight::MetadataSectionComponent.with_collection(component_metadata_partials,
20
+ metadata_attr: { layout: Arclight::UpperMetadataLayoutComponent },
21
+ presenter: presenter) unless document.collection? %>
22
+
23
+ <%= embed %>
24
+
25
+ <% if document.collection? %>
26
+ <div id="metadata">
27
+ <h2 class="sr-only visually-hidden"><%= t 'arclight.views.show.context' %></h2>
28
+ <%= render Arclight::MetadataSectionComponent.with_collection(metadata_partials,
29
+ metadata_attr: { layout: Arclight::UpperMetadataLayoutComponent },
30
+ presenter: presenter, heading: true) %>
31
+ </div>
32
+ <% elsif document.children? %>
33
+ <div id="contents">
34
+ <h2 class="al-show-sub-heading"><%= t 'arclight.views.show.contents' %></h2>
35
+ <%= helpers.turbo_frame_tag "al-hierarchy-#{document.id}-document", loading: 'lazy', src: helpers.hierarchy_solr_document_path(id: document.id, paginate: true, key: '-document', per_page: 50) %>
36
+ </div>
37
+ <% end %>
38
+
39
+ <%= access %>
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arclight
4
+ # Render a single document
5
+ class DocumentComponent < Blacklight::DocumentComponent
6
+ attr_reader :document
7
+
8
+ def online_content?
9
+ document.online_content? && (document.collection? || document.children?)
10
+ end
11
+
12
+ def blacklight_config
13
+ presenter.configuration
14
+ end
15
+
16
+ # @return [Blacklight::Configuration::ToolConfig] the configuration for the bookmark
17
+ def bookmark_config
18
+ blacklight_config.index.document_actions.arclight_bookmark_control
19
+ end
20
+
21
+ def breadcrumb_component
22
+ blacklight_config.show.breadcrumb_component || Arclight::BreadcrumbsHierarchyComponent
23
+ end
24
+
25
+ def metadata_partials
26
+ blacklight_config.show.metadata_partials || []
27
+ end
28
+
29
+ def component_metadata_partials
30
+ blacklight_config.show.component_metadata_partials || []
31
+ end
32
+
33
+ def online_filter
34
+ render Arclight::OnlineContentFilterComponent.new(document: document)
35
+ end
36
+
37
+ def access
38
+ render (blacklight_config.show.access_component || Arclight::AccessComponent).new(presenter: presenter)
39
+ end
40
+
41
+ def toggle_sidebar
42
+ button_tag(t('arclight.views.show.toggle_sidebar'),
43
+ type: :button,
44
+ class: 'btn btn-sm btn-secondary d-lg-none sidebar-toggle',
45
+ data: { bs_toggle: 'offcanvas', bs_target: '#sidebar' },
46
+ aria: { controls: 'sidebar' })
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,20 @@
1
+ <% if paginate? && @target_index >= 0 && @target_index >= @maximum_left_gap %>
2
+ <%# render the hierarchy as: outer (left) window ... window ... because our current document hierarchy is so far down the list it'd be buried %>
3
+ <%= helpers.turbo_frame_tag "al-hierarchy-#{@document.id}-left", loading: 'lazy', src: hierarchy_path(limit: @left_outer_window, key: '-left') %>
4
+ <%= tag.turbo_frame id: "al-hierarchy-#{@document.id}-gap" do %>
5
+ <%= render expand_hierarchy_component.new(path: hierarchy_path(offset: @left_outer_window, limit: @target_index - @left_outer_window - (@window / 2), key: '-gap')) %>
6
+ <% end %>
7
+ <%= helpers.turbo_frame_tag "al-hierarchy-#{@document.id}-window", src: hierarchy_path(offset: @target_index - (@window / 2), limit: @window, key: '-window') %>
8
+ <%= tag.turbo_frame id: "al-hierarchy-#{@document.id}-right" do %>
9
+ <%= render expand_hierarchy_component.new(path: hierarchy_path(offset: @target_index + (@window / 2), key: '-right')) %>
10
+ <% end %>
11
+ <% elsif paginate? %>
12
+ <%# render the first N documents, and let the user expand the remaining if desired %>
13
+ <%= helpers.turbo_frame_tag "al-hierarchy-#{@document.id}-sidebar", loading: ('lazy' unless @target_index >= 0), src: hierarchy_path(limit: @maximum_left_gap, key: '-sidebar') %>
14
+ <%= tag.turbo_frame id: "al-hierarchy-#{@document.id}-right" do %>
15
+ <%= render expand_hierarchy_component.new(path: hierarchy_path(offset: @maximum_left_gap, key: '-right')) %>
16
+ <% end %>
17
+ <% else %>
18
+ <%# there aren't enough to bother paginating, so load them all at once %>
19
+ <%= helpers.turbo_frame_tag "al-hierarchy-#{@document.id}-sidebar", loading: ('lazy' unless @target_index >= 0), src: hierarchy_path(key: '-sidebar') %>
20
+ <% end %>