arclight 0.2.0 → 0.3.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 (153) hide show
  1. checksums.yaml +4 -4
  2. data/.all-contributorsrc +450 -0
  3. data/.babelrc +3 -0
  4. data/.codeclimate.yml +5 -0
  5. data/.eslintrc +3 -0
  6. data/.rubocop.yml +19 -0
  7. data/.rubocop_todo.yml +15 -135
  8. data/.travis.yml +2 -2
  9. data/CONTRIBUTORS.md +79 -0
  10. data/README.md +21 -24
  11. data/Rakefile +0 -1
  12. data/app/assets/images/blacklight/bookmark.svg +1 -0
  13. data/app/assets/images/blacklight/collection.svg +5 -0
  14. data/app/assets/images/blacklight/compact.svg +1 -25
  15. data/app/assets/images/blacklight/container.svg +5 -0
  16. data/app/assets/images/blacklight/ead.svg +1 -0
  17. data/app/assets/images/blacklight/file.svg +5 -0
  18. data/app/assets/images/blacklight/folder.svg +1 -0
  19. data/app/assets/images/blacklight/list.svg +1 -0
  20. data/app/assets/images/blacklight/minus.svg +1 -0
  21. data/app/assets/images/blacklight/online.svg +5 -0
  22. data/app/assets/images/blacklight/pdf.svg +1 -0
  23. data/app/assets/images/blacklight/plus.svg +1 -0
  24. data/app/assets/images/blacklight/repository.svg +1 -0
  25. data/app/assets/javascripts/arclight/arclight.js +1 -3
  26. data/app/assets/javascripts/arclight/collection_navigation.js +36 -53
  27. data/app/assets/javascripts/arclight/collection_scrollspy.js +1 -1
  28. data/app/assets/javascripts/arclight/context_navigation.js +374 -0
  29. data/app/assets/javascripts/arclight/truncator.js.erb +8 -2
  30. data/app/assets/stylesheets/arclight/application.scss +3 -1
  31. data/app/assets/stylesheets/arclight/bootstrap_overrides.scss +23 -0
  32. data/app/assets/stylesheets/arclight/modules/context_navigation.scss +75 -0
  33. data/app/assets/stylesheets/arclight/modules/hierarchy_and_online_contents.scss +28 -35
  34. data/app/assets/stylesheets/arclight/modules/highlights.scss +2 -1
  35. data/app/assets/stylesheets/arclight/modules/layout.scss +128 -14
  36. data/app/assets/stylesheets/arclight/modules/mastheads.scss +27 -5
  37. data/app/assets/stylesheets/arclight/modules/repositories.scss +1 -5
  38. data/app/assets/stylesheets/arclight/modules/repository_card.scss +6 -7
  39. data/app/assets/stylesheets/arclight/modules/search_results.scss +145 -24
  40. data/app/assets/stylesheets/arclight/modules/show_collection.scss +38 -59
  41. data/app/assets/stylesheets/arclight/responsive.scss +13 -0
  42. data/app/assets/stylesheets/arclight/variables.scss +21 -1
  43. data/app/controllers/concerns/arclight/ead_format_helpers.rb +225 -0
  44. data/app/controllers/concerns/arclight/field_config_helpers.rb +23 -7
  45. data/app/factories/blacklight_field_configuration_factory.rb +1 -0
  46. data/app/helpers/arclight_helper.rb +197 -35
  47. data/app/models/arclight/document_downloads.rb +125 -0
  48. data/app/models/arclight/parent.rb +4 -2
  49. data/app/models/arclight/parents.rb +6 -4
  50. data/app/models/arclight/requests/aeon_external_request.rb +42 -0
  51. data/app/models/arclight/requests/aeon_web_ead.rb +47 -0
  52. data/app/models/arclight/requests/google_form.rb +2 -2
  53. data/app/models/concerns/arclight/catalog.rb +14 -2
  54. data/app/models/concerns/arclight/search_behavior.rb +27 -12
  55. data/app/models/concerns/arclight/solr_document.rb +29 -7
  56. data/app/views/arclight/_requests.html.erb +7 -0
  57. data/app/views/arclight/repositories/_in_person_repository.html.erb +1 -1
  58. data/app/views/arclight/repositories/_repository.html.erb +2 -2
  59. data/app/views/arclight/repositories/_repository_contact.html.erb +9 -0
  60. data/app/views/arclight/repositories/index.html.erb +3 -0
  61. data/app/views/arclight/repositories/show.html.erb +5 -4
  62. data/app/views/arclight/requests/_aeon_external_request_endpoint.html.erb +9 -0
  63. data/app/views/arclight/requests/_aeon_web_ead.html.erb +7 -0
  64. data/app/views/arclight/requests/_google_form.html.erb +2 -1
  65. data/app/views/arclight/viewers/_oembed.html.erb +2 -1
  66. data/app/views/catalog/_access_contents.html.erb +15 -0
  67. data/app/views/catalog/_arclight_abstract_or_scope.html.erb +5 -0
  68. data/app/views/catalog/_arclight_bookmark_control.html.erb +38 -0
  69. data/app/views/catalog/_arclight_document_header_icon.html.erb +1 -0
  70. data/app/views/catalog/_arclight_index_compact_default.html.erb +18 -11
  71. data/app/views/catalog/_arclight_index_default.html.erb +45 -0
  72. data/app/views/catalog/_arclight_index_group_document_compact_default.html.erb +19 -0
  73. data/app/views/catalog/_arclight_index_group_document_default.html.erb +18 -0
  74. data/app/views/catalog/_arclight_online_content_indicator.html.erb +1 -3
  75. data/app/views/catalog/_collection_contents.html.erb +2 -10
  76. data/app/views/catalog/_collection_context.html.erb +15 -0
  77. data/app/views/catalog/_collection_context_nav.html.erb +12 -0
  78. data/app/views/catalog/_collection_online_contents.html.erb +3 -3
  79. data/app/views/catalog/_component_context.html.erb +5 -0
  80. data/app/views/catalog/_containers.html.erb +3 -0
  81. data/app/views/catalog/_context_sidebar.html.erb +2 -2
  82. data/app/views/catalog/_document_downloads.html.erb +14 -0
  83. data/app/views/catalog/_group.html.erb +21 -0
  84. data/app/views/catalog/_group_header_compact_default.html.erb +15 -0
  85. data/app/views/catalog/_group_header_default.html.erb +20 -0
  86. data/app/views/catalog/_group_toggle.html.erb +10 -0
  87. data/app/views/catalog/_home.html.erb +1 -1
  88. data/app/views/catalog/_index_breadcrumb_default.html.erb +5 -2
  89. data/app/views/catalog/_index_collection_context_default.html.erb +53 -0
  90. data/app/views/catalog/_index_header.html.erb +3 -3
  91. data/app/views/catalog/_index_online_contents_default.html.erb +1 -1
  92. data/app/views/catalog/_online_content_label.html.erb +5 -0
  93. data/app/views/catalog/_search_form.html.erb +34 -0
  94. data/app/views/catalog/_search_results.html.erb +1 -4
  95. data/app/views/catalog/_show_actions_box_default.html.erb +27 -0
  96. data/app/views/catalog/_show_breadcrumbs_default.html.erb +5 -20
  97. data/app/views/catalog/_show_collection.html.erb +42 -24
  98. data/app/views/catalog/_show_default.html.erb +63 -35
  99. data/app/views/catalog/_show_upper_metadata_default.html.erb +1 -1
  100. data/app/views/catalog/_sort_and_per_page.html.erb +8 -0
  101. data/app/views/catalog/_within_collection_dropdown.html.erb +26 -0
  102. data/app/views/shared/_breadcrumbs.html.erb +4 -4
  103. data/app/views/shared/_context_sidebar.html.erb +2 -2
  104. data/app/views/shared/_header_navbar.html.erb +13 -17
  105. data/app/views/shared/_show_breadcrumbs.html.erb +27 -0
  106. data/arclight.gemspec +5 -6
  107. data/config/i18n-tasks.yml +2 -1
  108. data/config/locales/arclight.en.yml +54 -21
  109. data/config/repositories.yml +0 -0
  110. data/lib/arclight/engine.rb +22 -12
  111. data/lib/arclight/hash_absolute_xpath.rb +11 -7
  112. data/lib/arclight/level_label.rb +46 -0
  113. data/lib/arclight/normalized_date.rb +2 -2
  114. data/lib/arclight/normalized_id.rb +1 -0
  115. data/lib/arclight/normalized_title.rb +1 -0
  116. data/lib/arclight/repository.rb +58 -5
  117. data/lib/arclight/traject/ead2_config.rb +178 -159
  118. data/lib/arclight/traject/nokogiri_namespaceless_reader.rb +22 -0
  119. data/lib/arclight/version.rb +1 -1
  120. data/lib/arclight/viewers/oembed.rb +1 -0
  121. data/lib/arclight/year_range.rb +9 -1
  122. data/lib/generators/arclight/install_generator.rb +5 -1
  123. data/lib/generators/arclight/templates/catalog_controller.rb +128 -100
  124. data/lib/generators/arclight/templates/config/downloads.yml +12 -0
  125. data/lib/generators/arclight/templates/config/repositories.yml +20 -2
  126. data/lib/generators/arclight/update_generator.rb +1 -1
  127. data/lib/tasks/index.rake +18 -20
  128. data/package.json +8 -1
  129. data/solr/conf/schema.xml +51 -292
  130. data/solr/conf/solrconfig.xml +40 -125
  131. data/tasks/arclight.rake +1 -0
  132. data/vendor/assets/javascripts/responsiveTruncator.js +2 -2
  133. metadata +71 -44
  134. data/app/assets/javascripts/arclight/collection_context.js +0 -18
  135. data/app/assets/javascripts/arclight/component_ancestors.js +0 -56
  136. data/app/assets/javascripts/arclight/search_results.js +0 -15
  137. data/app/assets/stylesheets/arclight/modules/sidebar.scss +0 -21
  138. data/app/views/catalog/_collection_count.html.erb +0 -7
  139. data/app/views/catalog/_collection_downloads.html.erb +0 -15
  140. data/app/views/catalog/_collection_overview.html.erb +0 -7
  141. data/app/views/catalog/_component_contents.html.erb +0 -16
  142. data/app/views/catalog/_component_overview.html.erb +0 -40
  143. data/app/views/catalog/_index_header_hierarchy_default.html.erb +0 -42
  144. data/app/views/catalog/_index_hierarchy_default.html.erb +0 -28
  145. data/app/views/catalog/_results_histogram.html.erb +0 -15
  146. data/app/views/catalog/_show_component_sidebar.html.erb +0 -12
  147. data/app/views/catalog/_show_sidebar.html.erb +0 -22
  148. data/lib/arclight/custom_component.rb +0 -99
  149. data/lib/arclight/custom_document.rb +0 -93
  150. data/lib/arclight/indexer.rb +0 -9
  151. data/lib/arclight/shared_indexing_behavior.rb +0 -97
  152. data/lib/arclight/shared_terminology_behavior.rb +0 -65
  153. data/lib/arclight/solr_ead_indexer_ext.rb +0 -155
@@ -0,0 +1,13 @@
1
+ .my-w-25 {
2
+ width: 25% !important;
3
+ }
4
+
5
+ .my-w-75 {
6
+ width: 75% !important;
7
+ }
8
+
9
+ .w-md-100 {
10
+ @media (max-width: 767px) {
11
+ width: 100% !important;
12
+ }
13
+ }
@@ -1,2 +1,22 @@
1
+ // Colors
2
+ $background-highlight: #ffffaa;
3
+ $default-border-color: $border-color;
4
+
5
+ // Spacing
1
6
  $result-item-body-padding: 12px;
2
- $result-item-border-styling: 1px solid #ccc;
7
+
8
+ // Mixins
9
+ $default-border-styling: 1px solid $default-border-color;
10
+
11
+ @mixin extent-badge {
12
+ background-color: $gray-200;
13
+ border: $default-border-styling;
14
+ border-radius: $border-radius-lg;
15
+ color: $dark;
16
+ font-size: $font-size-sm;
17
+ line-height: 1.2;
18
+ margin: 0;
19
+ padding: ($spacer * .25) ($spacer * .5);
20
+ text-align: left;
21
+ white-space: normal;
22
+ }
@@ -0,0 +1,225 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arclight
4
+ ##
5
+ # A module to add EAD to HTML transformation rules for Arclight
6
+ module EadFormatHelpers # rubocop:disable Metrics/ModuleLength
7
+ extend ActiveSupport::Concern
8
+ include ActionView::Helpers::OutputSafetyHelper
9
+
10
+ def render_html_tags(args)
11
+ values = args[:value] || []
12
+ values.map! do |value|
13
+ transform_ead_to_html(value)
14
+ end
15
+ values.map! { |value| wrap_in_paragraph(value) } if values.count > 1
16
+ safe_join(values.map(&:html_safe))
17
+ end
18
+
19
+ private
20
+
21
+ def transform_ead_to_html(value)
22
+ Loofah.xml_fragment(condense_whitespace(value))
23
+ .scrub!(ead_to_html_scrubber)
24
+ .scrub!(:strip).to_html
25
+ end
26
+
27
+ def ead_to_html_scrubber
28
+ Loofah::Scrubber.new do |node|
29
+ format_render_attributes(node) if node.attr('render').present?
30
+ format_lists(node) if %w[list chronlist].include? node.name
31
+ node
32
+ end
33
+ end
34
+
35
+ def condense_whitespace(str)
36
+ str.squish.strip.gsub(/>[\n\s]+</, '><')
37
+ end
38
+
39
+ def wrap_in_paragraph(value)
40
+ if value.start_with?('<')
41
+ value
42
+ else
43
+ content_tag(:p, value)
44
+ end
45
+ end
46
+
47
+ def format_render_attributes(node) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity
48
+ case node.attr('render')
49
+ when 'altrender'
50
+ node.name = 'span'
51
+ node['class'] = node['altrender']
52
+ when 'bold'
53
+ node.name = 'strong'
54
+ when 'bolddoublequote'
55
+ node.name = 'strong'
56
+ node.prepend_child '"'
57
+ node.add_child '"'
58
+ when 'bolditalic'
59
+ node.name = 'strong'
60
+ node.wrap('<em/>')
61
+ when 'boldsinglequote'
62
+ node.name = 'strong'
63
+ node.prepend_child '\''
64
+ node.add_child '\''
65
+ when 'boldsmcaps'
66
+ node.name = 'strong'
67
+ node.wrap('<small/>')
68
+ node['class'] = 'text-uppercase'
69
+ when 'boldunderline'
70
+ node.name = 'strong'
71
+ node['class'] = 'text-underline'
72
+ when 'doublequote'
73
+ node.name = 'span'
74
+ node.prepend_child '"'
75
+ node.add_child '"'
76
+ when 'italic'
77
+ node.name = 'em'
78
+ when 'nonproport'
79
+ node.name = 'em'
80
+ when 'singlequote'
81
+ node.name = 'span'
82
+ node.prepend_child '\''
83
+ node.add_child '\''
84
+ when 'smcaps'
85
+ node.name = 'small'
86
+ node['class'] = 'text-uppercase'
87
+ when 'sub'
88
+ node.name = 'sub'
89
+ when 'super'
90
+ node.name = 'sup'
91
+ when 'underline'
92
+ node.name = 'span'
93
+ node['class'] = 'text-underline'
94
+ end
95
+ end
96
+
97
+ def format_lists(node)
98
+ format_simple_lists(node) if node.name == 'list' && node['type'] != 'deflist'
99
+ format_deflists(node) if node.name == 'list' && node['type'] == 'deflist'
100
+ format_chronlists(node) if node.name == 'chronlist'
101
+ end
102
+
103
+ def format_simple_lists(node)
104
+ node.name = 'ul' if (%w[simple marked].include? node['type']) || node['type'].blank?
105
+ node.name = 'ol' if node['type'] == 'ordered'
106
+ node.remove_attribute('type')
107
+ head_node = node.at_css('head')
108
+ format_list_head(head_node) if head_node.present?
109
+ items = node.css('item')
110
+ items.each { |item_node| item_node.name = 'li' }
111
+ end
112
+
113
+ def format_list_head(node)
114
+ node['class'] = 'list-head'
115
+ node.name = 'div'
116
+ node.parent.previous = node # move it from within the list to above it
117
+ end
118
+
119
+ def format_deflists(node)
120
+ listhead_node = node.at_css('listhead')
121
+ labels = node.css('label')
122
+ items = node.css('item')
123
+ defitems = node.css('defitem')
124
+ node.remove_attribute('type')
125
+
126
+ if listhead_node.present?
127
+ format_deflist_as_table(node, labels, items, defitems)
128
+ else
129
+ format_deflist_as_dl(node, labels, items, defitems)
130
+ end
131
+ end
132
+
133
+ def format_deflist_as_table(node, labels, items, defitems)
134
+ node.name = 'table'
135
+ node['class'] = 'table deflist'
136
+ listhead_node = node.at_css('listhead')
137
+ format_deflist_table_head(listhead_node)
138
+ node.at_css('thead').next = '<tbody/>'
139
+ labels.each { |label_node| label_node.name = 'td' }
140
+ items.each { |item_node| item_node.name = 'td' }
141
+ defitems.each do |defitem_node|
142
+ defitem_node.name = 'tr'
143
+ defitem_node.parent = node.at_css('tbody')
144
+ end
145
+ end
146
+
147
+ def format_deflist_table_head(listhead_node)
148
+ listhead_node.at_css('head01').name = 'th'
149
+ listhead_node.at_css('head02').name = 'th'
150
+ listhead_node.name = 'tr'
151
+ listhead_node.wrap('<thead/>')
152
+ end
153
+
154
+ def format_deflist_as_dl(node, labels, items, defitems)
155
+ node.name = 'dl'
156
+ node['class'] = 'deflist'
157
+ labels.each { |label_node| label_node.name = 'dt' }
158
+ items.each { |item_node| item_node.name = 'dd' }
159
+ defitems.each { |defitem_node| defitem_node.swap(defitem_node.children) } # unwrap
160
+ end
161
+
162
+ def format_chronlists(node)
163
+ node.name = 'table'
164
+ node['class'] = 'table chronlist'
165
+ eventgrps = node.css('eventgrp')
166
+ single_events = node.css('chronitem > event')
167
+ multi_events = node.css('eventgrp > event')
168
+ format_chronlist_header(node)
169
+ node.at_css('thead').next = '<tbody/>'
170
+ format_chronlist_caption(node)
171
+ format_chronlist_chronitems(node)
172
+ format_chronlist_dates(node)
173
+ format_chronlist_events(eventgrps, single_events, multi_events)
174
+ end
175
+
176
+ def format_chronlist_header(node)
177
+ node.add_child('<thead><tr><th>Date</th><th>Event</th></tr></thead>')
178
+ table_head = node.at_css('thead')
179
+ node.children.first.add_previous_sibling(table_head)
180
+ listhead_node = node.at_css('listhead')
181
+ return unless listhead_node.present?
182
+
183
+ node.at_css('thead tr th:nth-of-type(1)').content = node.at_css('listhead/head01').content
184
+ node.at_css('thead tr th:nth-of-type(2)').content = node.at_css('listhead/head02').content
185
+ listhead_node.remove
186
+ end
187
+
188
+ def format_chronlist_caption(node)
189
+ head_node = node.at_css('head')
190
+ return unless head_node.present?
191
+
192
+ head_node.name = 'caption'
193
+ head_node['class'] = 'chronlist-head'
194
+ node.children.first.add_previous_sibling(head_node) # make the caption first
195
+ end
196
+
197
+ def format_chronlist_chronitems(node)
198
+ chronitems = node.css('chronitem')
199
+ chronitems.each do |chronitem_node|
200
+ chronitem_node.name = 'tr'
201
+ chronitem_node.parent = node.at_css('tbody')
202
+ end
203
+ end
204
+
205
+ def format_chronlist_dates(node)
206
+ dates = node.css('date')
207
+ dates.each do |date_node|
208
+ date_node.name = 'td'
209
+ date_node['class'] = 'chronlist-item-date'
210
+ end
211
+ end
212
+
213
+ def format_chronlist_events(eventgrps, single_events, multi_events)
214
+ eventgrps.each do |eventgrp_node|
215
+ eventgrp_node.name = 'td'
216
+ eventgrp_node['class'] = 'chronlist-item-event'
217
+ end
218
+ single_events.each do |event_node|
219
+ event_node.name = 'td'
220
+ event_node['class'] = 'chronlist-item-event'
221
+ end
222
+ multi_events.each { |event_node| event_node.name = 'div' }
223
+ end
224
+ end
225
+ end
@@ -7,18 +7,22 @@ module Arclight
7
7
  extend ActiveSupport::Concern
8
8
  include ActionView::Helpers::OutputSafetyHelper
9
9
  include ActionView::Helpers::TagHelper
10
+ include Arclight::EadFormatHelpers
10
11
 
11
12
  included do
12
13
  if respond_to?(:helper_method)
13
14
  helper_method :repository_config_present
14
15
  helper_method :request_config_present
15
- helper_method :context_sidebar_repository
16
+ helper_method :context_access_tab_repository
17
+ helper_method :access_repository_contact
16
18
  helper_method :before_you_visit_note_present
17
- helper_method :context_sidebar_visit_note
19
+ helper_method :context_access_tab_visit_note
20
+ helper_method :highlight_terms
18
21
  helper_method :context_sidebar_containers_request
19
22
  helper_method :item_requestable?
20
23
  helper_method :paragraph_separator
21
24
  helper_method :link_to_name_facet
25
+ helper_method :render_html_tags
22
26
  end
23
27
  end
24
28
 
@@ -28,16 +32,15 @@ module Arclight
28
32
 
29
33
  def item_requestable?(_, options)
30
34
  document = options[:document]
31
- request_config_present('', document) && document.containers.present?
35
+ request_config_present('', document)
32
36
  end
33
37
 
34
38
  def request_config_present(var, document)
35
39
  repository_config_present(var, document) &&
36
- document.repository_config.google_request_url.present? &&
37
- document.repository_config.google_request_mappings.present?
40
+ document.repository_config.request_config_present?
38
41
  end
39
42
 
40
- def context_sidebar_repository(args)
43
+ def context_access_tab_repository(args)
41
44
  document = args[:document]
42
45
  ApplicationController.renderer.render(
43
46
  'arclight/repositories/_in_person_repository',
@@ -46,15 +49,28 @@ module Arclight
46
49
  )
47
50
  end
48
51
 
52
+ def access_repository_contact(args)
53
+ document = args[:document]
54
+ ApplicationController.renderer.render(
55
+ 'arclight/repositories/_repository_contact',
56
+ layout: false,
57
+ locals: { repository: document.repository_config }
58
+ )
59
+ end
60
+
49
61
  def before_you_visit_note_present(_, document)
50
62
  document.repository_config && document.repository_config.visit_note.present?
51
63
  end
52
64
 
53
- def context_sidebar_visit_note(args)
65
+ def context_access_tab_visit_note(args)
54
66
  document = args[:document]
55
67
  document.repository_config.visit_note
56
68
  end
57
69
 
70
+ def highlight_terms(args)
71
+ safe_join(args[:value].map { |value| content_tag(:span, value, class: 'bg-info') })
72
+ end
73
+
58
74
  def context_sidebar_containers_request(args)
59
75
  document = args[:document]
60
76
  presenter = Arclight::ShowPresenter.new(document, view_context)
@@ -16,6 +16,7 @@ class BlacklightFieldConfigurationFactory
16
16
 
17
17
  def field_config
18
18
  return null_field unless config.respond_to?(:"#{field_group}s")
19
+
19
20
  config.send(:"#{field_group}s").fetch(field) { null_field }
20
21
  end
21
22
 
@@ -3,12 +3,87 @@
3
3
  ##
4
4
  # Generic Helpers used in Arclight
5
5
  module ArclightHelper
6
+ def aria_hidden_breadcrumb_separator
7
+ safe_join(
8
+ [
9
+ '<span aria-hidden="true">'.html_safe,
10
+ t('arclight.breadcrumb_separator'),
11
+ '</span>'.html_safe
12
+ ]
13
+ )
14
+ end
15
+
6
16
  ##
7
17
  # @param [SolrDocument]
8
18
  def parents_to_links(document)
9
- safe_join(Arclight::Parents.from_solr_document(document).as_parents.map do |parent|
19
+ breadcrumb_links = []
20
+
21
+ breadcrumb_links << build_repository_link(document)
22
+
23
+ breadcrumb_links << document_parents(document).map do |parent|
24
+ link_to parent.label, solr_document_path(parent.global_id)
25
+ end
26
+
27
+ safe_join(breadcrumb_links, aria_hidden_breadcrumb_separator)
28
+ end
29
+
30
+ ##
31
+ # For a non-grouped compact view, display the breadcrumbs with the following
32
+ # algorithm:
33
+ # - Display only the first two parts of the item breadcrumb: the repository
34
+ # and the collection.
35
+ # - After the collection and the breadcrumb divider icon, show an ellipses as
36
+ # shown in the mockup above. The repository and the collection parts are
37
+ # linked as usual; the ellipses is not linked.
38
+ def regular_compact_breadcrumbs(document)
39
+ breadcrumb_links = [build_repository_link(document)]
40
+
41
+ parents = document_parents(document)
42
+ breadcrumb_links << parents[0, 1].map do |parent|
43
+ link_to parent.label, solr_document_path(parent.global_id)
44
+ end
45
+
46
+ breadcrumb_links << '&hellip;'.html_safe if parents.length > 1
47
+
48
+ safe_join(
49
+ breadcrumb_links,
50
+ aria_hidden_breadcrumb_separator
51
+ )
52
+ end
53
+
54
+ ##
55
+ # @param [SolrDocument]
56
+ def component_parents_to_links(document)
57
+ parents = document_parents(document)
58
+ return unless parents.length > 1
59
+
60
+ safe_join(parents.slice(1, 999).map do |parent|
10
61
  link_to parent.label, solr_document_path(parent.global_id)
11
- end, t('arclight.breadcrumb_separator'))
62
+ end, aria_hidden_breadcrumb_separator)
63
+ end
64
+
65
+ ##
66
+ # @param [SolrDocument]
67
+ def component_top_level_parent_to_links(document)
68
+ parents = document_parents(document)
69
+ return unless parents.length > 1
70
+
71
+ parent_link = link_to(parents[1].label, solr_document_path(parents[1].global_id))
72
+ return parent_link if parents.length == 2
73
+
74
+ safe_join(
75
+ [
76
+ parent_link,
77
+ aria_hidden_breadcrumb_separator,
78
+ '&hellip;'.html_safe
79
+ ]
80
+ )
81
+ end
82
+
83
+ ##
84
+ # @param [SolrDocument]
85
+ def document_parents(document)
86
+ Arclight::Parents.from_solr_document(document).as_parents
12
87
  end
13
88
 
14
89
  def repository_collections_path(repository)
@@ -20,6 +95,17 @@ module ArclightHelper
20
95
  )
21
96
  end
22
97
 
98
+ # Returns the i18n-ed string to be used as the h1 in search results
99
+ def search_results_header_text
100
+ if (repo = repository_faceted_on).present?
101
+ t('arclight.search.repository_header', repository: repo.name)
102
+ elsif collection_active?
103
+ t('arclight.search.collections_header')
104
+ else
105
+ t('blacklight.search.header')
106
+ end
107
+ end
108
+
23
109
  ##
24
110
  # Classes used for customized show page in arclight
25
111
  def custom_show_content_classes
@@ -42,15 +128,20 @@ module ArclightHelper
42
128
  @response.response['numFound']
43
129
  end
44
130
 
45
- ##
46
- # Looks for `document.unitid` in the downloads configuration
47
- # @param [SolrDocument] `document`
48
- # @param [Hash] `config` metadata for downloadable files
49
- # @return [Hash] with `:href` and `:size` keys
50
- def collection_downloads(document, config = load_download_config)
51
- config = config[document.unitid] if config.present?
52
- return {} if config.blank?
53
- parse_collection_downloads(config)
131
+ def grouped?
132
+ try(:search_state) && search_state.params_for_search.try(:[], 'group') == 'true'
133
+ end
134
+
135
+ def search_with_group
136
+ search_state.params_for_search.merge('group' => 'true').except('page')
137
+ end
138
+
139
+ def search_without_group
140
+ search_state.params_for_search.except('group', 'page')
141
+ end
142
+
143
+ def search_within_collection(collection_name, search)
144
+ search.merge(f: { collection_sim: [collection_name] })
54
145
  end
55
146
 
56
147
  def on_repositories_show?
@@ -76,41 +167,49 @@ module ArclightHelper
76
167
  #
77
168
  # @return [Repository]
78
169
  def repository_faceted_on
79
- return unless try(:search_state)
80
- repos = facets_from_request.find { |f| f.name == 'repository_sim' }.try(:items)
81
- faceted = repos && repos.length == 1 && repos.first.value
82
- Arclight::Repository.find_by(name: repos.first.value) if faceted
170
+ return unless try(:search_state) && facet_field_in_params?('repository_sim')
171
+
172
+ repos = Array(facet_params('repository_sim'))
173
+ faceted = repos && repos.length == 1 && repos.first
174
+ Arclight::Repository.find_by(name: repos.first) if faceted
83
175
  end
84
176
 
85
177
  def hierarchy_component_context?
86
178
  params[:hierarchy_context] == 'component'
87
179
  end
88
180
 
89
- # @return [Hash] loaded from config/downloads.yml, or `{}` if missing file
90
- def load_download_config(filename = Rails.root.join('config', 'downloads.yml'))
91
- YAML.safe_load(File.read(filename))
92
- rescue Errno::ENOENT
93
- {}
181
+ def online_contents_context?
182
+ params[:view] == 'online_contents'
94
183
  end
95
184
 
96
- # @return [Hash] the downloads for the given configuration using Hash symbols
97
- # @example `{ pdf: { href: 'http://...', size: '123 KB' } }`
98
- def parse_collection_downloads(config, results = {})
99
- %w[pdf ead].each do |type|
100
- next if config[type].blank?
101
- results[type.to_sym] = {
102
- href: config[type]['href'],
103
- size: display_size(config[type]['size'])
104
- }
185
+ # determine which icon to show in search results header
186
+ # these icon names will need to be updated when the icons are determined
187
+ def document_or_parent_icon(document)
188
+ case document.level&.downcase
189
+ when 'collection'
190
+ 'collection'
191
+ when 'file'
192
+ 'file'
193
+ when 'series', 'subseries'
194
+ 'folder'
195
+ else
196
+ 'container'
105
197
  end
106
- results
107
198
  end
108
199
 
109
- # Show a human readable size, or if it's already a string, show that
110
- # @return [String] human readable siz
111
- def display_size(size)
112
- size = number_to_human_size(size.to_i + 1) if size.is_a?(Numeric) || size =~ /^[0-9]+$/ # assumes bytes
113
- size.to_s
200
+ def render_grouped_documents(documents)
201
+ safe_join(
202
+ documents.each_with_index.map do |document, i|
203
+ render_document_partial(document, :arclight_index_group_document, document_counter: i)
204
+ end
205
+ )
206
+ end
207
+
208
+ def ead_files(document)
209
+ files = Arclight::DocumentDownloads.new(document, document.collection_unitid).files
210
+ files.find do |file|
211
+ file.type == 'ead'
212
+ end
114
213
  end
115
214
 
116
215
  ##
@@ -170,4 +269,67 @@ module ArclightHelper
170
269
  def generic_render_document_field_label(config_field, document, field: field_name)
171
270
  send(:"render_document_#{config_field}_label", document, field: field)
172
271
  end
272
+
273
+ def show_expanded?(document)
274
+ !original_document?(document) && within_original_tree?(document)
275
+ end
276
+
277
+ def within_original_tree?(document)
278
+ Array.wrap(params['original_parents']).map do |parent|
279
+ Arclight::Parent.new(id: parent, eadid: document.parent_ids.first, level: nil, label: nil).global_id
280
+ end.include?(document.id)
281
+ end
282
+
283
+ def original_document?(document)
284
+ document.id == params['original_document']
285
+ end
286
+
287
+ def generic_context_navigation(document, original_parents: document.parent_ids, component_level: 1)
288
+ content_tag(
289
+ :div,
290
+ '',
291
+ class: 'context-navigator',
292
+ data: {
293
+ collapse: I18n.t('arclight.views.show.collapse'),
294
+ expand: I18n.t('arclight.views.show.expand'),
295
+ arclight: {
296
+ level: component_level,
297
+ path: search_catalog_path(hierarchy_context: 'component'),
298
+ name: document.collection_name,
299
+ originalDocument: document.id,
300
+ originalParents: original_parents,
301
+ eadid: document.eadid
302
+ }
303
+ }
304
+ )
305
+ end
306
+
307
+ ##
308
+ # Determine if the user is currently under a collection context
309
+ # This is any record view (because it is either the collection or a component w/i a collection)
310
+ # or in a result view where a collection facet has been selected
311
+ def within_collection_context?
312
+ return true if record_view?
313
+
314
+ results_view? && params.dig(:f, 'collection_sim')
315
+ end
316
+
317
+ def results_view?
318
+ controller_name == 'catalog' && action_name == 'index'
319
+ end
320
+
321
+ def record_view?
322
+ controller_name == 'catalog' && action_name == 'show'
323
+ end
324
+
325
+ private
326
+
327
+ def build_repository_link(document)
328
+ repository_path = document.repository_config&.slug
329
+ if repository_path.present?
330
+ link_to(document.repository, arclight_engine.repository_path(repository_path))
331
+ else
332
+ content_tag(:span, document.repository)
333
+ end
334
+ end
173
335
  end