arclight 0.0.1 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (202) hide show
  1. checksums.yaml +5 -5
  2. data/.all-contributorsrc +450 -0
  3. data/.codeclimate.yml +5 -0
  4. data/.eslintrc +22 -0
  5. data/.github/workflows/ruby.yml +44 -0
  6. data/.gitignore +7 -0
  7. data/.rspec +0 -1
  8. data/.rubocop.yml +362 -0
  9. data/.rubocop_todo.yml +122 -0
  10. data/.solr_wrapper +5 -0
  11. data/CONTRIBUTING.md +43 -0
  12. data/CONTRIBUTORS.md +79 -0
  13. data/Gemfile +41 -0
  14. data/LICENSE.txt +1 -0
  15. data/README.md +100 -12
  16. data/Rakefile +13 -3
  17. data/app/assets/images/arclight/logo.png +0 -0
  18. data/app/assets/images/blacklight/bookmark.svg +1 -0
  19. data/app/assets/images/blacklight/collection.svg +5 -0
  20. data/app/assets/images/blacklight/compact.svg +1 -0
  21. data/app/assets/images/blacklight/container.svg +5 -0
  22. data/app/assets/images/blacklight/ead.svg +1 -0
  23. data/app/assets/images/blacklight/file.svg +5 -0
  24. data/app/assets/images/blacklight/folder.svg +1 -0
  25. data/app/assets/images/blacklight/list.svg +1 -0
  26. data/app/assets/images/blacklight/minus.svg +1 -0
  27. data/app/assets/images/blacklight/online.svg +5 -0
  28. data/app/assets/images/blacklight/pdf.svg +1 -0
  29. data/app/assets/images/blacklight/plus.svg +1 -0
  30. data/app/assets/images/blacklight/repository.svg +1 -0
  31. data/app/assets/javascripts/arclight/arclight.js +4 -0
  32. data/app/assets/javascripts/arclight/oembed_controller.js +58 -0
  33. data/app/assets/javascripts/arclight/truncate_controller.js +27 -0
  34. data/app/assets/stylesheets/arclight/application.scss +14 -0
  35. data/app/assets/stylesheets/arclight/build.scss +4 -0
  36. data/app/assets/stylesheets/arclight/modules/collection_search.scss +3 -0
  37. data/app/assets/stylesheets/arclight/modules/hierarchy_and_online_contents.scss +155 -0
  38. data/app/assets/stylesheets/arclight/modules/highlights.scss +11 -0
  39. data/app/assets/stylesheets/arclight/modules/icons.scss +20 -0
  40. data/app/assets/stylesheets/arclight/modules/layout.scss +220 -0
  41. data/app/assets/stylesheets/arclight/modules/mastheads.scss +57 -0
  42. data/app/assets/stylesheets/arclight/modules/repositories.scss +25 -0
  43. data/app/assets/stylesheets/arclight/modules/repository_card.scss +9 -0
  44. data/app/assets/stylesheets/arclight/modules/search_form.scss +9 -0
  45. data/app/assets/stylesheets/arclight/modules/search_results.scss +250 -0
  46. data/app/assets/stylesheets/arclight/modules/show_collection.scss +38 -0
  47. data/app/assets/stylesheets/arclight/modules/truncator.scss +58 -0
  48. data/app/assets/stylesheets/arclight/responsive.scss +13 -0
  49. data/app/assets/stylesheets/arclight/variables.scss +25 -0
  50. data/app/components/arclight/access_component.html.erb +14 -0
  51. data/app/components/arclight/access_component.rb +25 -0
  52. data/app/components/arclight/bookmark_component.html.erb +25 -0
  53. data/app/components/arclight/bookmark_component.rb +9 -0
  54. data/app/components/arclight/breadcrumb_component.rb +40 -0
  55. data/app/components/arclight/breadcrumbs_hierarchy_component.html.erb +34 -0
  56. data/app/components/arclight/breadcrumbs_hierarchy_component.rb +25 -0
  57. data/app/components/arclight/collection_context_component.html.erb +12 -0
  58. data/app/components/arclight/collection_context_component.rb +27 -0
  59. data/app/components/arclight/collection_info_component.html.erb +28 -0
  60. data/app/components/arclight/collection_info_component.rb +26 -0
  61. data/app/components/arclight/collection_sidebar_component.html.erb +15 -0
  62. data/app/components/arclight/collection_sidebar_component.rb +39 -0
  63. data/app/components/arclight/constraints_component.html.erb +7 -0
  64. data/app/components/arclight/constraints_component.rb +17 -0
  65. data/app/components/arclight/document_collection_context_component.html.erb +29 -0
  66. data/app/components/arclight/document_collection_context_component.rb +28 -0
  67. data/app/components/arclight/document_collection_hierarchy_component.html.erb +50 -0
  68. data/app/components/arclight/document_collection_hierarchy_component.rb +62 -0
  69. data/app/components/arclight/document_component.html.erb +39 -0
  70. data/app/components/arclight/document_component.rb +49 -0
  71. data/app/components/arclight/document_components_hierarchy_component.html.erb +32 -0
  72. data/app/components/arclight/document_components_hierarchy_component.rb +28 -0
  73. data/app/components/arclight/document_download_component.html.erb +24 -0
  74. data/app/components/arclight/document_download_component.rb +71 -0
  75. data/app/components/arclight/embed_component.html.erb +10 -0
  76. data/app/components/arclight/embed_component.rb +43 -0
  77. data/app/components/arclight/group_component.html.erb +34 -0
  78. data/app/components/arclight/group_component.rb +23 -0
  79. data/app/components/arclight/header_component.html.erb +5 -0
  80. data/app/components/arclight/header_component.rb +10 -0
  81. data/app/components/arclight/index_metadata_field_component.html.erb +16 -0
  82. data/app/components/arclight/index_metadata_field_component.rb +20 -0
  83. data/app/components/arclight/masthead_component.html.erb +15 -0
  84. data/app/components/arclight/masthead_component.rb +10 -0
  85. data/app/components/arclight/metadata_section_component.html.erb +13 -0
  86. data/app/components/arclight/metadata_section_component.rb +22 -0
  87. data/app/components/arclight/oembed_viewer_component.html.erb +5 -0
  88. data/app/components/arclight/oembed_viewer_component.rb +16 -0
  89. data/app/components/arclight/online_content_filter_component.html.erb +15 -0
  90. data/app/components/arclight/online_content_filter_component.rb +19 -0
  91. data/app/components/arclight/online_status_indicator_component.rb +19 -0
  92. data/app/components/arclight/repository_breadcrumb_component.html.erb +10 -0
  93. data/app/components/arclight/repository_breadcrumb_component.rb +17 -0
  94. data/app/components/arclight/repository_location_component.html.erb +20 -0
  95. data/app/components/arclight/repository_location_component.rb +10 -0
  96. data/app/components/arclight/search_bar_component.html.erb +27 -0
  97. data/app/components/arclight/search_bar_component.rb +32 -0
  98. data/app/components/arclight/search_result_breadcrumbs_component.html.erb +6 -0
  99. data/app/components/arclight/search_result_breadcrumbs_component.rb +37 -0
  100. data/app/components/arclight/search_result_component.html.erb +20 -0
  101. data/app/components/arclight/search_result_component.rb +18 -0
  102. data/app/components/arclight/search_result_title_component.html.erb +15 -0
  103. data/app/components/arclight/search_result_title_component.rb +15 -0
  104. data/app/components/arclight/sidebar_component.html.erb +9 -0
  105. data/app/components/arclight/sidebar_component.rb +19 -0
  106. data/app/components/arclight/upper_metadata_layout_component.rb +10 -0
  107. data/app/components/blacklight/icons/bookmark_component.rb +12 -0
  108. data/app/components/blacklight/icons/collection_component.rb +14 -0
  109. data/app/components/blacklight/icons/compact_component.rb +12 -0
  110. data/app/components/blacklight/icons/container_component.rb +14 -0
  111. data/app/components/blacklight/icons/ead_component.rb +12 -0
  112. data/app/components/blacklight/icons/file_component.rb +14 -0
  113. data/app/components/blacklight/icons/folder_component.rb +12 -0
  114. data/app/components/blacklight/icons/online_component.rb +15 -0
  115. data/app/components/blacklight/icons/pdf_component.rb +12 -0
  116. data/app/components/blacklight/icons/repository_component.rb +12 -0
  117. data/app/controllers/arclight/repositories_controller.rb +40 -0
  118. data/app/helpers/arclight/ead_format_helpers.rb +309 -0
  119. data/app/helpers/arclight/field_config_helpers.rb +26 -0
  120. data/app/helpers/arclight_helper.rb +108 -0
  121. data/app/models/arclight/document_downloads.rb +122 -0
  122. data/app/models/arclight/parent.rb +24 -0
  123. data/app/models/arclight/parents.rb +39 -0
  124. data/app/models/arclight/requests/aeon_external_request.rb +42 -0
  125. data/app/models/arclight/requests/aeon_web_ead.rb +52 -0
  126. data/app/models/arclight/requests/google_form.rb +49 -0
  127. data/app/models/concerns/arclight/catalog.rb +44 -0
  128. data/app/models/concerns/arclight/search_behavior.rb +47 -0
  129. data/app/models/concerns/arclight/solr_document.rb +159 -0
  130. data/app/presenters/arclight/index_presenter.rb +10 -0
  131. data/app/presenters/arclight/show_presenter.rb +54 -0
  132. data/app/views/arclight/.keep +0 -0
  133. data/app/views/arclight/_requests.html.erb +7 -0
  134. data/app/views/arclight/repositories/_repository.html.erb +43 -0
  135. data/app/views/arclight/repositories/index.html.erb +9 -0
  136. data/app/views/arclight/repositories/show.html.erb +37 -0
  137. data/app/views/arclight/requests/_aeon_external_request_endpoint.html.erb +8 -0
  138. data/app/views/arclight/requests/_aeon_web_ead.html.erb +6 -0
  139. data/app/views/arclight/requests/_google_form.html.erb +10 -0
  140. data/app/views/catalog/_document_list.html.erb +8 -0
  141. data/app/views/catalog/_group.html.erb +4 -0
  142. data/app/views/catalog/_group_toggle.html.erb +10 -0
  143. data/app/views/catalog/_search_results_header.html.erb +3 -0
  144. data/app/views/catalog/hierarchy.html.erb +19 -0
  145. data/app/views/catalog/index.html.erb +17 -0
  146. data/app/views/shared/_breadcrumbs.html.erb +3 -0
  147. data/app/views/shared/_main_menu_links.html.erb +6 -0
  148. data/arclight.gemspec +29 -11
  149. data/bin/rails +13 -0
  150. data/config/breadcrumbs.rb +24 -0
  151. data/config/i18n-tasks.yml +134 -0
  152. data/config/importmap.rb +3 -0
  153. data/config/locales/arclight.en.yml +100 -0
  154. data/config/repositories.yml +0 -0
  155. data/config/routes.rb +6 -0
  156. data/docker-compose.yml +16 -0
  157. data/lib/arclight/digital_object.rb +27 -0
  158. data/lib/arclight/engine.rb +47 -0
  159. data/lib/arclight/exceptions.rb +19 -0
  160. data/lib/arclight/hash_absolute_xpath.rb +62 -0
  161. data/lib/arclight/level_label.rb +46 -0
  162. data/lib/arclight/missing_id_strategy.rb +21 -0
  163. data/lib/arclight/normalized_date.rb +49 -0
  164. data/lib/arclight/normalized_id.rb +30 -0
  165. data/lib/arclight/normalized_title.rb +33 -0
  166. data/lib/arclight/repository.rb +116 -0
  167. data/lib/arclight/routes/hierarchy.rb +19 -0
  168. data/lib/arclight/routes.rb +8 -0
  169. data/lib/arclight/traject/ead2_component_config.rb +334 -0
  170. data/lib/arclight/traject/ead2_config.rb +315 -0
  171. data/lib/arclight/traject/nokogiri_namespaceless_reader.rb +22 -0
  172. data/lib/arclight/version.rb +3 -1
  173. data/lib/arclight/year_range.rb +111 -0
  174. data/lib/arclight.rb +11 -1
  175. data/lib/generators/arclight/install_generator.rb +126 -0
  176. data/lib/generators/arclight/templates/arclight.scss +5 -0
  177. data/lib/generators/arclight/templates/catalog_controller.rb +422 -0
  178. data/lib/generators/arclight/templates/config/downloads.yml +25 -0
  179. data/lib/generators/arclight/templates/config/locales/arclight.en.yml +61 -0
  180. data/lib/generators/arclight/templates/config/repositories.yml +53 -0
  181. data/lib/generators/arclight/update_generator.rb +22 -0
  182. data/lib/tasks/index.rake +84 -0
  183. data/package.json +30 -0
  184. data/solr/conf/_rest_managed.json +3 -0
  185. data/solr/conf/admin-extra.html +31 -0
  186. data/solr/conf/elevate.xml +36 -0
  187. data/solr/conf/mapping-ISOLatin1Accent.txt +246 -0
  188. data/solr/conf/protwords.txt +21 -0
  189. data/solr/conf/schema.xml +400 -0
  190. data/solr/conf/solrconfig.xml +328 -0
  191. data/solr/conf/spellings.txt +2 -0
  192. data/solr/conf/stopwords.txt +58 -0
  193. data/solr/conf/stopwords_en.txt +58 -0
  194. data/solr/conf/synonyms.txt +31 -0
  195. data/solr/conf/xslt/example.xsl +132 -0
  196. data/solr/conf/xslt/example_atom.xsl +67 -0
  197. data/solr/conf/xslt/example_rss.xsl +66 -0
  198. data/solr/conf/xslt/luke.xsl +337 -0
  199. data/tasks/arclight.rake +72 -0
  200. data/template.rb +10 -0
  201. metadata +432 -20
  202. data/.travis.yml +0 -5
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arclight
4
+ # Display a document's constituent components with appropriate lazy-loading
5
+ # to keep the page load time reasonable.
6
+ class DocumentComponentsHierarchyComponent < ViewComponent::Base
7
+ # rubocop:disable Metrics/ParameterLists
8
+ def initialize(document: nil, target_index: -1, minimum_pagination_size: 20, left_outer_window: 3, maximum_left_gap: 10, window: 10)
9
+ super
10
+
11
+ @document = document
12
+ @target_index = target_index&.to_i || -1
13
+ @minimum_pagination_size = minimum_pagination_size
14
+ @left_outer_window = left_outer_window
15
+ @maximum_left_gap = maximum_left_gap
16
+ @window = window
17
+ end
18
+ # rubocop:enable Metrics/ParameterLists
19
+
20
+ def paginate?
21
+ @document.number_of_children > @minimum_pagination_size
22
+ end
23
+
24
+ def hierarchy_path(**kwargs)
25
+ helpers.hierarchy_solr_document_path(id: @document.id, hierarchy: true, nest_path: params[:nest_path], **kwargs)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,24 @@
1
+ <div class="al-show-actions-box-downloads-container">
2
+ <% case files.size %>
3
+ <% when 2 %>
4
+ <div class="dropdown">
5
+ <button class="btn btn-secondary btn-sm dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
6
+ <%= t("arclight.views.show.download.default") %>
7
+ </button>
8
+ <ul class="dropdown-menu">
9
+ <% files.each do |file| %>
10
+ <li><%= link_to(file.href, class: "dropdown-item", **@link_options) do %>
11
+ <%= icon_for(file.type) %> <%= dropdown_label(file) %>
12
+ <% end %>
13
+ </li>
14
+ <% end %>
15
+ </ul>
16
+ </div>
17
+ <% when 1 %>
18
+ <% files.each do |file| %>
19
+ <%= link_to(file.href, class: "btn btn-secondary btn-sm", **@link_options) do %>
20
+ <%= download_icon %> <%= label(file) %>
21
+ <% end %>
22
+ <% end %>
23
+ <% end %>
24
+ </div>
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arclight
4
+ # ViewComponent for rendering a single document download link
5
+ class DocumentDownloadComponent < ViewComponent::Base
6
+ def initialize(downloads:, **kwargs)
7
+ super
8
+
9
+ @downloads = downloads
10
+ @link_options = kwargs
11
+ end
12
+
13
+ attr_reader :downloads
14
+
15
+ delegate :files, to: :downloads
16
+
17
+ def render?
18
+ files.present?
19
+ end
20
+
21
+ # i18n-tasks-use t('arclight.views.show.download.multiple.pdf')
22
+ # i18n-tasks-use t('arclight.views.show.download.multiple.ead')
23
+ def dropdown_label(file)
24
+ t(file.type, scope: 'arclight.views.show.download.multiple')
25
+ end
26
+
27
+ # i18n-tasks-use t('arclight.views.show.download.single.pdf')
28
+ # i18n-tasks-use t('arclight.views.show.download.single.ead')
29
+ def label(file)
30
+ t(file.type, scope: 'arclight.views.show.download.single')
31
+ end
32
+
33
+ # From https://icons.getbootstrap.com/icons/download/
34
+ def download_icon
35
+ icon = <<~HTML
36
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-download" viewBox="0 0 16 16">
37
+ <path d="M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5z"/>
38
+ <path d="M7.646 11.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 10.293V1.5a.5.5 0 0 0-1 0v8.793L5.354 8.146a.5.5 0 1 0-.708.708l3 3z"/>
39
+ </svg>
40
+ HTML
41
+ icon.html_safe # rubocop:disable Rails/OutputSafety
42
+ end
43
+
44
+ # This is an extension point where one could configure a different icon per file type
45
+ def icon_for(type)
46
+ public_send("#{type}_icon")
47
+ end
48
+
49
+ # From https://icons.getbootstrap.com/icons/file-earmark-pdf/
50
+ def pdf_icon
51
+ icon = <<~HTML
52
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-earmark-pdf" viewBox="0 0 16 16">
53
+ <path d="M14 14V4.5L9.5 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2zM9.5 3A1.5 1.5 0 0 0 11 4.5h2V14a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h5.5v2z"/>
54
+ <path d="M4.603 14.087a.81.81 0 0 1-.438-.42c-.195-.388-.13-.776.08-1.102.198-.307.526-.568.897-.787a7.68 7.68 0 0 1 1.482-.645 19.697 19.697 0 0 0 1.062-2.227 7.269 7.269 0 0 1-.43-1.295c-.086-.4-.119-.796-.046-1.136.075-.354.274-.672.65-.823.192-.077.4-.12.602-.077a.7.7 0 0 1 .477.365c.088.164.12.356.127.538.007.188-.012.396-.047.614-.084.51-.27 1.134-.52 1.794a10.954 10.954 0 0 0 .98 1.686 5.753 5.753 0 0 1 1.334.05c.364.066.734.195.96.465.12.144.193.32.2.518.007.192-.047.382-.138.563a1.04 1.04 0 0 1-.354.416.856.856 0 0 1-.51.138c-.331-.014-.654-.196-.933-.417a5.712 5.712 0 0 1-.911-.95 11.651 11.651 0 0 0-1.997.406 11.307 11.307 0 0 1-1.02 1.51c-.292.35-.609.656-.927.787a.793.793 0 0 1-.58.029zm1.379-1.901c-.166.076-.32.156-.459.238-.328.194-.541.383-.647.547-.094.145-.096.25-.04.361.01.022.02.036.026.044a.266.266 0 0 0 .035-.012c.137-.056.355-.235.635-.572a8.18 8.18 0 0 0 .45-.606zm1.64-1.33a12.71 12.71 0 0 1 1.01-.193 11.744 11.744 0 0 1-.51-.858 20.801 20.801 0 0 1-.5 1.05zm2.446.45c.15.163.296.3.435.41.24.19.407.253.498.256a.107.107 0 0 0 .07-.015.307.307 0 0 0 .094-.125.436.436 0 0 0 .059-.2.095.095 0 0 0-.026-.063c-.052-.062-.2-.152-.518-.209a3.876 3.876 0 0 0-.612-.053zM8.078 7.8a6.7 6.7 0 0 0 .2-.828c.031-.188.043-.343.038-.465a.613.613 0 0 0-.032-.198.517.517 0 0 0-.145.04c-.087.035-.158.106-.196.283-.04.192-.03.469.046.822.024.111.054.227.09.346z"/>
55
+ </svg>
56
+ HTML
57
+ icon.html_safe # rubocop:disable Rails/OutputSafety
58
+ end
59
+
60
+ # From https://icons.getbootstrap.com/icons/file-earmark-code/
61
+ def ead_icon
62
+ icon = <<~HTML
63
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-earmark-code" viewBox="0 0 16 16">
64
+ <path d="M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5L14 4.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5h-2z"/>
65
+ <path d="M8.646 6.646a.5.5 0 0 1 .708 0l2 2a.5.5 0 0 1 0 .708l-2 2a.5.5 0 0 1-.708-.708L10.293 9 8.646 7.354a.5.5 0 0 1 0-.708zm-1.292 0a.5.5 0 0 0-.708 0l-2 2a.5.5 0 0 0 0 .708l2 2a.5.5 0 0 0 .708-.708L5.707 9l1.647-1.646a.5.5 0 0 0 0-.708z"/>
66
+ </svg>
67
+ HTML
68
+ icon.html_safe # rubocop:disable Rails/OutputSafety
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,10 @@
1
+ <div id="embed" class="mb-2">
2
+ <h2 class="al-show-sub-heading"><%= t('arclight.views.show.embedded_content') %></h2>
3
+ <%= render Arclight::OembedViewerComponent.with_collection(embeddable_resources, document: @document) %>
4
+
5
+ <% linked_resources.each do |resource| %>
6
+ <div class="al-digital-object">
7
+ <%= link_to(resource.label, resource.href) %>
8
+ </div>
9
+ <% end %>
10
+ </div>
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arclight
4
+ # Render digital object links for a document
5
+ class EmbedComponent < ViewComponent::Base
6
+ def initialize(document:, presenter:, **kwargs)
7
+ super
8
+
9
+ @document = document
10
+ @presenter = presenter
11
+ end
12
+
13
+ def render?
14
+ resources.any?
15
+ end
16
+
17
+ def embeddable_resources
18
+ resources.first(1).select { |object| embeddable?(object) }
19
+ end
20
+
21
+ def linked_resources
22
+ resources - embeddable_resources
23
+ end
24
+
25
+ def resources
26
+ @resources ||= @document.digital_objects || []
27
+ end
28
+
29
+ def depth
30
+ @document.parents.length || 0
31
+ end
32
+
33
+ def embeddable?(object)
34
+ exclude_patterns.none? do |pattern|
35
+ object.href =~ pattern
36
+ end
37
+ end
38
+
39
+ def exclude_patterns
40
+ Arclight::Engine.config.oembed_resource_exclude_patterns
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,34 @@
1
+ <div class='al-grouped-title-bar'>
2
+ <div class='row'>
3
+ <div class='col-md-12'>
4
+ <% if document.repository_config.present? %>
5
+ <div class='al-grouped-repository breadcrumb-links'>
6
+ <%= link_to(document.repository_config.name, helpers.arclight_engine.repository_path(document.repository_config.slug)) %>
7
+ </div>
8
+ <% end %>
9
+ <h3><%= helpers.link_to_document document %></h3>
10
+ <% document.extent.each do |extent| %>
11
+ <%= tag.span extent, class: 'al-document-extent badge' unless compact? %>
12
+ <% end %>
13
+ <dl>
14
+ <%= render Arclight::IndexMetadataFieldComponent.with_collection(presenter.field_presenters.select { |field| !compact? || field.field_config.compact }) %>
15
+ </dl>
16
+ </div>
17
+ </div>
18
+ </div>
19
+
20
+ <div class="grouped-documents">
21
+ <div class="al-grouped-more">
22
+ <% if @group.total > 3 %>
23
+ <%= t('arclight.views.index.top_group_results', count: 3) %>
24
+ <%= link_to(
25
+ t('arclight.views.index.all_group_results', count: @group.total),
26
+ search_within_collection_url)
27
+ %>
28
+ <% else %>
29
+ <%= t('arclight.views.index.group_results_count', count: @group.total) %>
30
+ <% end %>
31
+ </div>
32
+
33
+ <%= helpers.render_document_index @group.docs %>
34
+ </div>
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arclight
4
+ # Render a collection document for a
5
+ # grouped search result view
6
+ class GroupComponent < Blacklight::Document::GroupComponent
7
+ def compact?
8
+ helpers.document_index_view_type.to_s == 'compact'
9
+ end
10
+
11
+ def document
12
+ @document ||= @group.docs.first.collection
13
+ end
14
+
15
+ def presenter
16
+ @presenter ||= Arclight::ShowPresenter.new(document, helpers).with_field_group('group_header_field')
17
+ end
18
+
19
+ def search_within_collection_url
20
+ search_catalog_path(helpers.search_without_group.deep_merge(f: { collection: [document.collection_name] }))
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,5 @@
1
+ <header>
2
+ <%= top_bar %>
3
+ <%= masthead %>
4
+ <%= search_bar %>
5
+ </header>
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arclight
4
+ # Provides a header with a masthead
5
+ class HeaderComponent < Blacklight::HeaderComponent
6
+ def masthead
7
+ render Arclight::MastheadComponent.new
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,16 @@
1
+ <div class="row">
2
+ <%= tag.dt @field.label, class: 'visually-hidden' %>
3
+ <% if truncate? %>
4
+ <%= tag.dd(class: @classes + ['truncator'], data: { controller: 'arclight-truncate' }) do %>
5
+ <%= tag.div @field.render, class: 'content', data: { arclight_truncate_target: 'content' } %>
6
+ <%= button_tag(type: :button, class: 'btn btn-sm btn-link px-0',
7
+ data: { action: 'click->arclight-truncate#trigger' }) do %>
8
+ <%= tag.span t('arclight.truncation.view_more'), class: 'view-more' %>
9
+ <%= tag.span t('arclight.truncation.view_less'), class: 'view-less' %>
10
+ <%= tag.span(class: 'icon') %>
11
+ <% end %>
12
+ <% end %>
13
+ <% else %>
14
+ <%= tag.dd @field.render, class: @classes %>
15
+ <% end %>
16
+ </div>
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arclight
4
+ # Render a simple metadata field (e.g. without labels) in a .row div
5
+ class IndexMetadataFieldComponent < Blacklight::MetadataFieldComponent
6
+ def initialize(field:, classes: ['col'], **kwargs)
7
+ super(field: field, **kwargs)
8
+
9
+ @classes = classes + ["al-document-#{@field.key.dasherize}"]
10
+ end
11
+
12
+ def render?
13
+ helpers.document_index_view_type != :compact || @field.field_config.compact
14
+ end
15
+
16
+ def truncate?
17
+ !!@field.field_config.truncate
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,15 @@
1
+ <div class='al-masthead bg-light'>
2
+ <div class="container">
3
+ <div class="row align-items-center">
4
+ <div class="col-md-8" >
5
+ <span class="h1"><%= heading %></span>
6
+ </div>
7
+
8
+ <nav class="col-md-4 nav-links d-flex justify-content-end" aria-label="browse">
9
+ <ul class="navbar-nav">
10
+ <%= render 'shared/main_menu_links' %>
11
+ </ul>
12
+ </nav>
13
+ </div>
14
+ </div>
15
+ </div>
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arclight
4
+ # Render the masthead
5
+ class MastheadComponent < Blacklight::Component
6
+ def heading
7
+ t('arclight.masthead_heading_html')
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,13 @@
1
+ <%= tag.div id: t("arclight.views.show.sections.#{@section}").parameterize do %>
2
+ <% if @heading %>
3
+ <h3 class='al-show-sub-heading'>
4
+ <%= t("arclight.views.show.sections.#{@section}", level: @presenter.document.level) %>
5
+ </h3>
6
+ <% end %>
7
+
8
+ <%= tag.dl class: @classes do %>
9
+ <% @presenter.field_presenters.each do |field_presenter| %>
10
+ <%= render (field_presenter.component || Blacklight::MetadataFieldComponent).new(field: field_presenter, show: true, **@metadata_attr) %>
11
+ <% end %>
12
+ <% end %>
13
+ <% end %>
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arclight
4
+ # Render a simple metadata field (e.g. without labels) in a .row div
5
+ class MetadataSectionComponent < ViewComponent::Base
6
+ with_collection_parameter :section
7
+
8
+ def initialize(section:, presenter:, metadata_attr: {}, classes: %w[row dl-invert], heading: false)
9
+ super
10
+
11
+ @classes = classes
12
+ @section = section
13
+ @presenter = presenter.with_field_group(section)
14
+ @heading = heading
15
+ @metadata_attr = metadata_attr
16
+ end
17
+
18
+ def render?
19
+ @presenter.fields_to_render.any?
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,5 @@
1
+ <%= tag.div(class: 'al-oembed-viewer', data: { controller: 'arclight-oembed', arclight_oembed_url_value: @resource.href }) do %>
2
+ <div class="al-digital-object">
3
+ <%= link_to(@resource.label, @resource.href) %>
4
+ </div>
5
+ <% end %>
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arclight
4
+ # Render an oembed viewer for a document
5
+ class OembedViewerComponent < ViewComponent::Base
6
+ with_collection_parameter :resource
7
+
8
+ def initialize(resource:, document:, depth: 0)
9
+ super
10
+
11
+ @resource = resource
12
+ @document = document
13
+ @depth = depth
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,15 @@
1
+ <div class="card online-contents">
2
+ <div class="card-body d-flex align-items-center">
3
+ <div class="d-flex">
4
+ <span class="al-online-content-icon mr-2 me-2" aria-hidden="true"><%= helpers.blacklight_icon :online %></span>
5
+ <h2 class="d-none d-lg-inline">
6
+ <span class="visually-hidden">Filter</span>
7
+ <%= t('arclight.views.show.online_content.title') %>
8
+ </h2>
9
+ </div>
10
+ <div class="ml-3 ms-3 ml-xl-5 ms-xl-5">
11
+ <div><%= t('arclight.views.show.online_content.description') %></div>
12
+ <%= link_to t('arclight.views.show.online_content.link_text'), helpers.search_action_path(f: { collection: [collection_name], access: ['online'] }) %>
13
+ </div>
14
+ </div>
15
+ </div>
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arclight
4
+ # Render the box that displays a link to filter only for online content
5
+ class OnlineContentFilterComponent < Blacklight::Component
6
+ def initialize(document:)
7
+ @document = document
8
+ super
9
+ end
10
+
11
+ def render?
12
+ @document.collection? && @document.online_content?
13
+ end
14
+
15
+ def collection_name
16
+ @document.collection_name
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arclight
4
+ # Render an online status indicator for a document
5
+ class OnlineStatusIndicatorComponent < Blacklight::Component
6
+ def initialize(document:, **)
7
+ @document = document
8
+ super
9
+ end
10
+
11
+ def render?
12
+ @document.online_content?
13
+ end
14
+
15
+ def call
16
+ tag.span helpers.blacklight_icon(:online), class: 'al-online-content-icon'
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,10 @@
1
+ <li class='breadcrumb-item'>
2
+ <span class="ml-3 ms-3" aria-hidden="true">
3
+ <%= blacklight_icon(:repository, classes: 'al-repository-content-icon') %>
4
+ </span>
5
+ <% if repository_path %>
6
+ <%= link_to(@document.repository, helpers.arclight_engine.repository_path(repository_path)) %>
7
+ <% else %>
8
+ <%= @document.repository %>
9
+ <% end %>
10
+ </li>
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arclight
4
+ # Draws the repository breadcrumb item for a search result
5
+ class RepositoryBreadcrumbComponent < ViewComponent::Base
6
+ def initialize(document:)
7
+ super
8
+ @document = document
9
+ end
10
+
11
+ delegate :blacklight_icon, to: :helpers
12
+
13
+ def repository_path
14
+ @document.repository_config&.slug
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,20 @@
1
+ <%= render(@layout.new(field: @field)) do |component| %>
2
+ <% component.with_label do %>
3
+ <%= label %>
4
+ <% end %>
5
+ <% component.with_value do %>
6
+ <div class='al-in-person-repository-name'>
7
+ <% if repository.thumbnail_url %>
8
+ <%= image_tag repository.thumbnail_url, alt: '', class: 'img-fluid float-left' %>
9
+ <% end %>
10
+ <div>
11
+ <%= link_to(repository.name, helpers.arclight_engine.repository_path(repository.slug)) %>
12
+ </div>
13
+ </div>
14
+ <div class='al-in-person-repository-location'>
15
+ <address>
16
+ <%= repository.location %>
17
+ </address>
18
+ </div>
19
+ <% end %>
20
+ <% end %>
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arclight
4
+ # Render the repository location card as a metadata field
5
+ class RepositoryLocationComponent < Blacklight::MetadataFieldComponent
6
+ def repository
7
+ @field.values.first
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,27 @@
1
+ <%= render(Blacklight::SearchBarComponent.new(
2
+ **@kwargs,
3
+ params: @params.merge(f: (@params[:f] || {}).except(:collection)),
4
+ q: @q,
5
+ search_field: @search_field)) do |c| %>
6
+
7
+ <% c.with_before_input_group do %>
8
+ <div class="input-group within-collection-dropdown">
9
+ <label class="input-group-text" for="within_collection">
10
+ <%= t('arclight.within_collection_dropdown.label_html') %>
11
+ </label>
12
+ <%= select_tag ('f[collection][]' if collection_name.present?), within_collection_options, id: 'within_collection', class: 'form-select search-field rounded-end' %>
13
+ </div>
14
+ <% end %>
15
+
16
+ <% c.with_prepend do %>
17
+ <%= prepend %>
18
+ <% end %>
19
+
20
+ <% c.with_append do %>
21
+ <%= append %>
22
+ <% end if append? %>
23
+
24
+ <% c.with_search_button do %>
25
+ <%= search_button %>
26
+ <% end if respond_to?(:search_button?) && search_button? # only BL8 has this option %>
27
+ <% end %>
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arclight
4
+ # Override Blacklight's SearchBarComponent to add a dropdown for choosing
5
+ # the context of the search (within "this collection" or "all collections").
6
+ # If a collection has not been chosen, it displays a dropdown with only "all collections"
7
+ # as the only selectable option.
8
+ class SearchBarComponent < Blacklight::SearchBarComponent
9
+ def initialize(**kwargs)
10
+ super
11
+
12
+ @kwargs = kwargs
13
+ end
14
+
15
+ def within_collection_options
16
+ value = collection_name || 'none-selected'
17
+ options_for_select(
18
+ [
19
+ [t('arclight.within_collection_dropdown.all_collections'), ''],
20
+ [t('arclight.within_collection_dropdown.this_collection'), value]
21
+ ],
22
+ selected: collection_name,
23
+ disabled: 'none-selected'
24
+ )
25
+ end
26
+
27
+ def collection_name
28
+ @collection_name ||= Array(@params.dig(:f, :collection)).reject(&:empty?).first ||
29
+ helpers.current_context_document&.collection_name
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,6 @@
1
+ <dt class="visually-hidden">Collection Context</dt>
2
+ <dd>
3
+ <div class='breadcrumb-links'>
4
+ <%= rendered_breadcrumbs %>
5
+ </div>
6
+ </dd>
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arclight
4
+ # Render the breadcrumbs for a search result document
5
+ class SearchResultBreadcrumbsComponent < Blacklight::MetadataFieldComponent
6
+ delegate :document, to: :@field
7
+
8
+ def initialize(field:, **kwargs)
9
+ @field = field
10
+ super
11
+ end
12
+
13
+ def breadcrumbs
14
+ offset = grouped? ? 2 : 0
15
+
16
+ Arclight::BreadcrumbComponent.new(document: document, count: breadcrumb_count, offset: offset)
17
+ end
18
+
19
+ def rendered_breadcrumbs
20
+ @rendered_breadcrumbs ||= capture { render breadcrumbs }
21
+ end
22
+
23
+ def render?
24
+ rendered_breadcrumbs.present?
25
+ end
26
+
27
+ def breadcrumb_count
28
+ @field.field_config.compact&.dig(:count) if compact?
29
+ end
30
+
31
+ delegate :grouped?, to: :helpers
32
+
33
+ def compact?
34
+ helpers.document_index_view_type == :compact
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,20 @@
1
+ <%= content_tag @component,
2
+ id: @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.flatten.join(' ') do %>
10
+ <div class="px-2 document-type-icon">
11
+ <%= icon %>
12
+ </div>
13
+ <div class="container">
14
+ <%= render Arclight::SearchResultTitleComponent.new(document: document, compact: compact?) %>
15
+
16
+ <div class="row">
17
+ <%= metadata %>
18
+ </div>
19
+ </div>
20
+ <% end %>
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arclight
4
+ # Render a document for a search result; this works with
5
+ # both the compact and list views for grouped or ungrouped
6
+ # results.
7
+ class SearchResultComponent < Blacklight::DocumentComponent
8
+ attr_reader :document
9
+
10
+ def compact?
11
+ presenter.view_config.key.to_s == 'compact'
12
+ end
13
+
14
+ def icon
15
+ helpers.blacklight_icon helpers.document_or_parent_icon(@document)
16
+ end
17
+ end
18
+ end