geoblacklight 6.0.0.pre.alpha.7 → 6.0.0.pre.beta.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 (231) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +14 -3
  3. data/README.md +2 -2
  4. data/Rakefile +1 -17
  5. data/app/assets/images/geoblacklight/logo-dark.svg +31 -0
  6. data/app/assets/images/geoblacklight/logo.svg +10 -10
  7. data/app/assets/stylesheets/geoblacklight/global.css +44 -7
  8. data/app/assets/stylesheets/geoblacklight/index_maps.css +0 -7
  9. data/app/assets/stylesheets/geoblacklight/record.css +33 -9
  10. data/app/assets/stylesheets/geoblacklight/search.css +66 -17
  11. data/app/assets/stylesheets/geoblacklight/viewers.css +18 -111
  12. data/app/assets/stylesheets/geoblacklight.css +0 -5
  13. data/app/components/blacklight/icons/georeferenced_component.rb +23 -0
  14. data/app/components/geoblacklight/document/download_link_component.html.erb +1 -1
  15. data/app/components/geoblacklight/document/preview_component.html.erb +0 -2
  16. data/app/components/geoblacklight/document_component.html.erb +0 -4
  17. data/app/components/geoblacklight/facets/bbox_field_component.html.erb +2 -1
  18. data/app/components/geoblacklight/georeferenced_header_badge_component.rb +16 -0
  19. data/app/components/geoblacklight/header_badge_component.html.erb +4 -2
  20. data/app/components/geoblacklight/header_badge_component.rb +1 -1
  21. data/app/components/geoblacklight/header_badges_component.html.erb +5 -0
  22. data/app/components/geoblacklight/header_badges_component.rb +34 -0
  23. data/app/components/geoblacklight/iiif_drag_drop_component.html.erb +1 -1
  24. data/app/components/geoblacklight/item_map_viewer_component.html.erb +0 -58
  25. data/app/components/geoblacklight/item_map_viewer_component.rb +19 -70
  26. data/app/components/geoblacklight/locator_map_component.rb +31 -0
  27. data/app/components/geoblacklight/login_link_component.html.erb +1 -1
  28. data/app/components/geoblacklight/login_link_component.rb +17 -1
  29. data/app/components/geoblacklight/metadata_description_markdown_component.rb +3 -9
  30. data/app/components/geoblacklight/overview_map_component.html.erb +2 -0
  31. data/app/components/geoblacklight/overview_map_component.rb +86 -0
  32. data/app/components/geoblacklight/relations/relation_component.html.erb +12 -0
  33. data/app/components/geoblacklight/relations/relation_component.rb +30 -0
  34. data/app/components/geoblacklight/relations/relations_component.html.erb +15 -0
  35. data/app/components/geoblacklight/relations/relations_component.rb +59 -0
  36. data/app/components/geoblacklight/resource_header_badge_component.rb +1 -1
  37. data/app/components/geoblacklight/search_result_component.html.erb +14 -33
  38. data/app/components/geoblacklight/search_result_component.rb +2 -14
  39. data/app/components/geoblacklight/static_map_component.rb +3 -14
  40. data/app/components/geoblacklight/truncatable_metadata_field_layout_component.html.erb +7 -0
  41. data/app/components/geoblacklight/truncatable_metadata_field_layout_component.rb +45 -0
  42. data/app/controllers/{relation_controller.rb → relations_controller.rb} +4 -2
  43. data/app/controllers/viewer_record_controller.rb +28 -0
  44. data/app/helpers/geoblacklight_helper.rb +57 -6
  45. data/app/javascript/geoblacklight/controllers/overview_map_controller.js +143 -0
  46. data/app/javascript/geoblacklight/core.js +8 -10
  47. data/app/javascript/geoblacklight/index.js +9 -12
  48. data/app/javascript/geoblacklight/initializers/field_truncation.js +62 -0
  49. data/app/javascript/geoblacklight/initializers/metadata_download.js +3 -8
  50. data/app/javascript/geoblacklight/initializers/truncation.js +7 -3
  51. data/app/javascript/geoblacklight/initializers/viewer_requests.js +61 -0
  52. data/app/javascript/geoblacklight/initializers/viewer_theme.js +28 -0
  53. data/app/models/concerns/geoblacklight/solr_document/thumbnail.rb +38 -0
  54. data/app/models/concerns/geoblacklight/solr_document.rb +2 -0
  55. data/app/models/concerns/geoblacklight/suppressed_records_search_behavior.rb +1 -1
  56. data/app/views/catalog/_document_split.html.erb +10 -10
  57. data/app/views/catalog/_home_text.html.erb +1 -1
  58. data/app/views/catalog/metadata.html.erb +1 -1
  59. data/app/views/{relation → relations}/index.html.erb +1 -1
  60. data/app/views/relations/index.json.jbuilder +9 -0
  61. data/config/importmap.rb +8 -8
  62. data/config/locales/geoblacklight.en.yml +48 -99
  63. data/geoblacklight.gemspec +3 -3
  64. data/lib/generators/geoblacklight/assets_generator.rb +2 -2
  65. data/lib/generators/geoblacklight/install_generator.rb +3 -6
  66. data/lib/generators/geoblacklight/templates/assets/customizations.css +5 -1
  67. data/lib/generators/geoblacklight/templates/catalog_controller.rb +17 -27
  68. data/lib/generators/geoblacklight/templates/settings.yml +15 -95
  69. data/lib/geoblacklight/configuration/display_note_shown_config.rb +3 -0
  70. data/lib/geoblacklight/configuration/relationship_config.rb +7 -1
  71. data/lib/geoblacklight/configuration/relationships_config.rb +15 -15
  72. data/lib/geoblacklight/configuration/settings_attributes.rb +85 -0
  73. data/lib/geoblacklight/configuration/settings_builder.rb +3 -14
  74. data/lib/geoblacklight/configuration.rb +23 -62
  75. data/lib/geoblacklight/exceptions.rb +4 -0
  76. data/lib/geoblacklight/reference.rb +0 -2
  77. data/lib/geoblacklight/references.rb +17 -5
  78. data/lib/geoblacklight/relations/ancestors.rb +12 -0
  79. data/lib/geoblacklight/relations/descendants.rb +11 -0
  80. data/lib/geoblacklight/relations/query.rb +39 -0
  81. data/lib/geoblacklight/{relation → relations}/relation_response.rb +5 -4
  82. data/lib/geoblacklight/routes/exportable.rb +2 -1
  83. data/lib/geoblacklight/version.rb +1 -1
  84. data/lib/geoblacklight/viewer_record.rb +39 -0
  85. data/lib/geoblacklight.rb +1 -1
  86. data/lib/tasks/geoblacklight.rake +1 -17
  87. data/lib/tasks/solr.rb +37 -0
  88. data/schema/readme.md +1 -1
  89. data/script/wait-for-solr +36 -0
  90. data/solr/conf/solrconfig.xml +10 -16
  91. data/spec/components/geoblacklight/document/sidebar_component_spec.rb +3 -3
  92. data/spec/components/geoblacklight/document_component_spec.rb +8 -34
  93. data/spec/components/geoblacklight/{header_icons_component_spec.rb → header_badges_component_spec.rb} +20 -2
  94. data/spec/components/geoblacklight/item_map_viewer_component_spec.rb +65 -15
  95. data/spec/components/geoblacklight/locator_map_component_spec.rb +54 -0
  96. data/spec/components/geoblacklight/login_link_component_spec.rb +20 -12
  97. data/spec/components/geoblacklight/metadata_description_markdown_component_spec.rb +1 -6
  98. data/spec/components/geoblacklight/overview_map_component_spec.rb +136 -0
  99. data/spec/components/geoblacklight/relations/relation_component_spec.rb +98 -0
  100. data/spec/components/geoblacklight/relations/relations_component_spec.rb +146 -0
  101. data/spec/components/geoblacklight/search_result_component_spec.rb +66 -39
  102. data/spec/components/geoblacklight/static_map_component_spec.rb +8 -2
  103. data/spec/components/geoblacklight/truncatable_metadata_field_layout_component_spec.rb +83 -0
  104. data/spec/controllers/catalog_controller_spec.rb +22 -7
  105. data/spec/controllers/{relation_controller_spec.rb → relations_controller_spec.rb} +1 -1
  106. data/spec/factories/user.rb +6 -1
  107. data/spec/features/axe_spec.rb +5 -3
  108. data/spec/features/home_page_spec.rb +8 -7
  109. data/spec/features/index_view_spec.rb +6 -20
  110. data/spec/features/layer_preview_spec.rb +4 -11
  111. data/spec/features/locator_map_spec.rb +31 -0
  112. data/spec/features/relations_spec.rb +22 -11
  113. data/spec/features/restricted_viewer_spec.rb +14 -0
  114. data/spec/features/search_results_map_spec.rb +89 -13
  115. data/spec/features/search_spec.rb +6 -2
  116. data/spec/features/sign_in_spec.rb +26 -0
  117. data/spec/features/tilejson_spec.rb +1 -3
  118. data/spec/features/tms_spec.rb +2 -2
  119. data/spec/features/truncated_metadata_spec.rb +77 -0
  120. data/spec/features/viewer_requests_spec.rb +40 -0
  121. data/spec/features/viewer_theme_spec.rb +51 -0
  122. data/spec/features/wmts_spec.rb +6 -6
  123. data/spec/features/xyz_spec.rb +3 -3
  124. data/spec/fixtures/solr_documents/README.md +18 -14
  125. data/spec/fixtures/solr_documents/actual-polygon1.json +22 -18
  126. data/spec/fixtures/solr_documents/b1g_wabash_child_15.json +14 -15
  127. data/spec/fixtures/solr_documents/b1g_wabash_child_16.json +14 -15
  128. data/spec/fixtures/solr_documents/b1g_wabash_child_17.json +14 -15
  129. data/spec/fixtures/solr_documents/b1g_wabash_child_18.json +14 -15
  130. data/spec/fixtures/solr_documents/b1g_wabash_parent.json +14 -15
  131. data/spec/fixtures/solr_documents/esri-dynamic-layer-single-layer.json +2 -2
  132. data/spec/fixtures/solr_documents/esri-feature-layer.json +1 -1
  133. data/spec/fixtures/solr_documents/esri-image-map-layer.json +20 -20
  134. data/spec/fixtures/solr_documents/esri-wms-layer.json +22 -24
  135. data/spec/fixtures/solr_documents/index_map_point.json +3 -3
  136. data/spec/fixtures/solr_documents/public_polygon.json +28 -0
  137. data/spec/helpers/geoblacklight_helper_spec.rb +103 -25
  138. data/spec/lib/geoblacklight/bounding_box_spec.rb +16 -0
  139. data/spec/lib/geoblacklight/configuration/relationships_config_spec.rb +121 -0
  140. data/spec/lib/geoblacklight/configuration/settings_attributes_spec.rb +113 -0
  141. data/spec/lib/geoblacklight/configuration/settings_builder_spec.rb +33 -4
  142. data/spec/lib/geoblacklight/references_spec.rb +35 -0
  143. data/spec/lib/geoblacklight/{relation → relations}/ancestors_spec.rb +17 -6
  144. data/spec/lib/geoblacklight/{relation → relations}/descendants_spec.rb +14 -7
  145. data/spec/lib/geoblacklight/{relation → relations}/relation_response_spec.rb +31 -17
  146. data/spec/lib/geoblacklight/viewer_record_spec.rb +69 -0
  147. data/spec/models/concerns/geoblacklight/solr_document/thumbnail_spec.rb +149 -0
  148. data/spec/models/concerns/geoblacklight/solr_document_spec.rb +1 -1
  149. data/spec/requests/bookmarks_spec.rb +2 -1
  150. data/spec/requests/catalog_show_spec.rb +24 -2
  151. data/spec/requests/index_view_spec.rb +50 -2
  152. data/spec/requests/missing_metadata_spec.rb +1 -1
  153. data/spec/requests/relations_spec.rb +9 -2
  154. data/spec/requests/search_results_spec.rb +6 -6
  155. data/spec/requests/viewer_record_spec.rb +37 -0
  156. data/spec/requests/viewer_requests_spec.rb +52 -0
  157. data/spec/solr_config_spec.rb +41 -0
  158. data/spec/solr_fixtures_spec.rb +23 -0
  159. data/spec/spec_helper.rb +13 -3
  160. data/spec/support/authentication.rb +37 -0
  161. data/spec/support/features/map_helpers.rb +68 -0
  162. data/spec/support/features/session_helpers.rb +18 -13
  163. data/spec/support/features/viewer_helpers.rb +20 -0
  164. data/spec/support/features.rb +4 -0
  165. data/spec/test_app_templates/lib/generators/test_app_generator.rb +1 -1
  166. data/template.rb +1 -1
  167. metadata +72 -84
  168. data/app/components/geoblacklight/accordion_component.html.erb +0 -16
  169. data/app/components/geoblacklight/accordion_component.rb +0 -15
  170. data/app/components/geoblacklight/attribute_table_component.html.erb +0 -15
  171. data/app/components/geoblacklight/attribute_table_component.rb +0 -17
  172. data/app/components/geoblacklight/header_icons_component.html.erb +0 -3
  173. data/app/components/geoblacklight/header_icons_component.rb +0 -27
  174. data/app/components/geoblacklight/index_map_inspect_component.html.erb +0 -12
  175. data/app/components/geoblacklight/index_map_inspect_component.rb +0 -15
  176. data/app/components/geoblacklight/index_map_legend_component.html.erb +0 -14
  177. data/app/components/geoblacklight/index_map_legend_component.rb +0 -24
  178. data/app/components/geoblacklight/location_leaflet_map_component.rb +0 -68
  179. data/app/components/geoblacklight/relations_component.html.erb +0 -23
  180. data/app/components/geoblacklight/relations_component.rb +0 -25
  181. data/app/components/geoblacklight/viewer_help_text_component.html.erb +0 -1
  182. data/app/components/geoblacklight/viewer_help_text_component.rb +0 -46
  183. data/app/controllers/wms_controller.rb +0 -17
  184. data/app/javascript/geoblacklight/controllers/leaflet_viewer_controller.js +0 -240
  185. data/app/javascript/geoblacklight/controllers/openlayers_viewer_controller.js +0 -74
  186. data/app/javascript/geoblacklight/controllers/search_results_controller.js +0 -50
  187. data/app/javascript/geoblacklight/initializers/popovers.js +0 -11
  188. data/app/javascript/geoblacklight/initializers/tooltips.js +0 -51
  189. data/app/javascript/geoblacklight/leaflet/basemaps.js +0 -73
  190. data/app/javascript/geoblacklight/leaflet/constants.js +0 -18
  191. data/app/javascript/geoblacklight/leaflet/controls/geosearch.js +0 -168
  192. data/app/javascript/geoblacklight/leaflet/controls/layer_opacity.js +0 -121
  193. data/app/javascript/geoblacklight/leaflet/controls/sidebar.js +0 -49
  194. data/app/javascript/geoblacklight/leaflet/controls/sleep.js +0 -101
  195. data/app/javascript/geoblacklight/leaflet/inspection.js +0 -210
  196. data/app/javascript/geoblacklight/leaflet/layer_index_map.js +0 -128
  197. data/app/javascript/geoblacklight/leaflet/layer_wmts.js +0 -57
  198. data/app/javascript/geoblacklight/leaflet/layers.js +0 -146
  199. data/app/javascript/geoblacklight/leaflet/utils.js +0 -83
  200. data/app/javascript/geoblacklight/openlayers/basemaps.js +0 -55
  201. data/app/javascript/geoblacklight/openlayers/inspection.js +0 -42
  202. data/app/javascript/geoblacklight/openlayers/layers.js +0 -44
  203. data/app/views/relation/index.json.jbuilder +0 -8
  204. data/lib/geoblacklight/configuration/layer_config.rb +0 -28
  205. data/lib/geoblacklight/configuration/leaflet_config.rb +0 -73
  206. data/lib/geoblacklight/configuration/leaflet_layers_config.rb +0 -33
  207. data/lib/geoblacklight/configuration/leaflet_sleep_config.rb +0 -20
  208. data/lib/geoblacklight/relation/ancestors.rb +0 -31
  209. data/lib/geoblacklight/relation/descendants.rb +0 -31
  210. data/lib/geoblacklight/routes/wms.rb +0 -15
  211. data/lib/geoblacklight/wms_layer/feature_info_response.rb +0 -37
  212. data/lib/geoblacklight/wms_layer.rb +0 -34
  213. data/spec/components/geoblacklight/attribute_table_component_spec.rb +0 -36
  214. data/spec/components/geoblacklight/index_map_legend_component_spec.rb +0 -29
  215. data/spec/components/geoblacklight/viewer_help_text_component_spec.rb +0 -27
  216. data/spec/controllers/wms_controller_spec.rb +0 -34
  217. data/spec/features/configurable_basemap_spec.rb +0 -40
  218. data/spec/features/full_screen_control_spec.rb +0 -15
  219. data/spec/features/layer_inspection_spec.rb +0 -12
  220. data/spec/features/layer_opacity_spec.rb +0 -16
  221. data/spec/fixtures/solr_documents/harvard_raster.json +0 -39
  222. data/spec/fixtures/solr_documents/public_polygon_mit.json +0 -23
  223. data/spec/fixtures/solr_documents/uva_slug_colon.json +0 -29
  224. data/spec/javascripts/geoblacklight_spec.js +0 -11
  225. data/spec/lib/geoblacklight/configuration/layer_config_spec.rb +0 -71
  226. data/spec/lib/geoblacklight/configuration/leaflet_config_spec.rb +0 -129
  227. data/spec/lib/geoblacklight/configuration/leaflet_layers_config_spec.rb +0 -63
  228. data/spec/lib/geoblacklight/configuration_spec.rb +0 -48
  229. data/spec/lib/geoblacklight/wms_layer/feature_info_response_spec.rb +0 -54
  230. data/spec/lib/geoblacklight/wms_layer_spec.rb +0 -115
  231. /data/app/components/geoblacklight/{location_leaflet_map_component.html.erb → locator_map_component.html.erb} +0 -0
@@ -12,6 +12,7 @@
12
12
  </button>
13
13
  </h3>
14
14
  <div id="<%= html_id %>" role="region" aria-labelledby="<%= header_html_id %>" class="panel-collapse facet-content collapse show">
15
- <%= render Geoblacklight::LocationLeafletMapComponent.new(geosearch: { dynamic: true }) %>
15
+ <%# No map_geometry: this map is pointed at the results, or at the area they are filtered to %>
16
+ <%= render Geoblacklight::OverviewMapComponent.new(geosearch: true, map_geometry: nil) %>
16
17
  </div>
17
18
  </div>
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Geoblacklight
4
+ # Badge that indicates the data is georeferenced
5
+ class GeoreferencedHeaderBadgeComponent < HeaderBadgeComponent
6
+ # Don't render for empty or false values
7
+ def render?
8
+ @document.georeferenced?
9
+ end
10
+
11
+ # Without this, the badge would show "true" for the label
12
+ def label
13
+ t("geoblacklight.badges.georeferenced")
14
+ end
15
+ end
16
+ end
@@ -1,2 +1,4 @@
1
- <span class="badge text-bg-secondary text-uppercase fw-semibold d-inline-flex align-items-center gap-1 me-1">
2
- <%= label %><%= icon(field) %></span>
1
+ <span class="badge icon-badge">
2
+ <%= tag.span label, class: 'label' %>
3
+ <%= icon %>
4
+ </span>
@@ -14,7 +14,7 @@ module Geoblacklight
14
14
  @document[field]
15
15
  end
16
16
 
17
- def icon(field)
17
+ def icon
18
18
  helpers.geoblacklight_icon(label)
19
19
  end
20
20
  end
@@ -0,0 +1,5 @@
1
+ <div class="badges">
2
+ <% @fields.each do |field| %>
3
+ <%= render_badge(field) %>
4
+ <% end %>
5
+ </div>
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Geoblacklight
4
+ class HeaderBadgesComponent < ViewComponent::Base
5
+ attr_reader :document
6
+
7
+ DEFAULT_FIELDS = [
8
+ Geoblacklight.configuration.fields.access_rights,
9
+ Geoblacklight.configuration.fields.resource_class,
10
+ Geoblacklight.configuration.fields.georeferenced
11
+ ].freeze
12
+
13
+ def initialize(document:, fields: DEFAULT_FIELDS)
14
+ @document = document
15
+ @fields = fields
16
+ super()
17
+ end
18
+
19
+ def render_badge(field)
20
+ render badge_class(field).new(document: @document, field:)
21
+ end
22
+
23
+ def badge_class(field)
24
+ case field
25
+ when Geoblacklight.configuration.fields.resource_class
26
+ Geoblacklight::ResourceHeaderBadgeComponent
27
+ when Geoblacklight.configuration.fields.georeferenced
28
+ Geoblacklight::GeoreferencedHeaderBadgeComponent
29
+ else
30
+ Geoblacklight::HeaderBadgeComponent
31
+ end
32
+ end
33
+ end
34
+ end
@@ -1,3 +1,3 @@
1
1
  <%= link_to @href_link, data: {manifest: @manifest}, class: 'float-end' do %>
2
- <%= helpers.geoblacklight_icon('iiif-drag-drop', classes: 'svg_tooltip iiif-icon') %>
2
+ <%= helpers.geoblacklight_icon('iiif-drag-drop', classes: 'iiif-icon') %>
3
3
  <% end %>
@@ -1,59 +1 @@
1
1
  <%= display_tag %>
2
- <% content_for :head do %>
3
- <!-- Include Mirador 3 for IIIF content -->
4
- <script src="https://unpkg.com/mirador@^3/dist/mirador.min.js"></script>
5
- <!-- Include OpenSeadragon for IIIF Image content -->
6
- <script src="https://cdnjs.cloudflare.com/ajax/libs/openseadragon/2.4.2/openseadragon.min.js"></script>
7
- <% end %>
8
- <% if iiif_manifest? %>
9
- <!-- Initialize Mirador viewer -->
10
- <script>
11
- window.miradorTarget = document.getElementById("mirador");
12
- if (window.miradorTarget) {
13
- Mirador.viewer({
14
- id: "mirador",
15
- windows: [
16
- {
17
- id: "main",
18
- loadedManifest: window.miradorTarget.dataset.manifestUrl,
19
- },
20
- ],
21
- window: {
22
- allowClose: false,
23
- allowFullscreen: true,
24
- allowMaximize: false,
25
- authNewWindowCenter: "screen",
26
- hideWindowTitle: true,
27
- sidebarPanel: "attribution",
28
- views: [
29
- { key: "single", behaviors: [null, "individuals"] },
30
- { key: "book", behaviors: [null, "paged"] },
31
- { key: "scroll", behaviors: ["continuous"] },
32
- { key: "gallery" },
33
- ],
34
- },
35
- workspace: {
36
- showZoomControls: true,
37
- type: "single",
38
- },
39
- workspaceControlPanel: {
40
- enabled: false,
41
- },
42
- });
43
- }
44
- </script>
45
- <% elsif iiif_image? %>
46
- <!-- Initialize OpenSeadragon viewer -->
47
- <script>
48
- window.osdTarget = document.getElementById("openseadragon");
49
- if (window.osdTarget) {
50
- OpenSeadragon({
51
- id: "openseadragon",
52
- tileSources: [window.osdTarget.dataset.imageUrl],
53
- prefixUrl: "https://cdnjs.cloudflare.com/ajax/libs/openseadragon/2.4.2/images/",
54
- preserveViewport: true,
55
- visibilityRatio: 1,
56
- });
57
- }
58
- </script>
59
- <% end %>
@@ -7,16 +7,10 @@ module Geoblacklight
7
7
  @document = document
8
8
  end
9
9
 
10
- # If the conditions for this being IIIF content are met, dislay the IIIF viewer
11
- # If it is oembed content, display the oembed viewer
12
- # Otherwise display the base viewer which will take into account if it is open layers
13
- # or generic content.
10
+ # Use the appropriate viewer based on the protocol of the document
14
11
  def display_tag
15
- return iiif_manifest_tag if iiif_manifest?
16
- return iiif_image_tag if iiif_image?
17
- return oembed_tag if protocol == "Oembed"
18
-
19
- base_tag
12
+ return oembed_tag if @document.viewer_protocol == "oembed"
13
+ ogm_viewer_tag
20
14
  end
21
15
 
22
16
  def render?
@@ -25,45 +19,6 @@ module Geoblacklight
25
19
 
26
20
  private
27
21
 
28
- def protocol
29
- @document.viewer_protocol&.camelize
30
- end
31
-
32
- def openlayers?
33
- %w[Cog Pmtiles].include?(protocol)
34
- end
35
-
36
- def iiif_image?
37
- protocol == "Iiif"
38
- end
39
-
40
- def iiif_manifest?
41
- protocol == "IiifManifest"
42
- end
43
-
44
- # Use mirador as the IIIF manifest viewer due to bug in Clover; see:
45
- # https://github.com/samvera-labs/clover-iiif/issues/294
46
- def iiif_manifest_tag
47
- tag.div(nil,
48
- id: "mirador",
49
- class: "viewer mirador-viewer",
50
- data: {
51
- manifest_url: @document.viewer_endpoint
52
- })
53
- end
54
-
55
- # Use openseadragon for IIIF image content due to bug in Clover; see:
56
- # https://github.com/samvera-labs/clover-iiif/issues/294
57
- def iiif_image_tag
58
- tag.div(nil,
59
- id: "openseadragon",
60
- class: "viewer openseadragon-viewer",
61
- data: {
62
- image_url: @document.viewer_endpoint
63
- })
64
- end
65
-
66
- # Generate the viewer HTML for oEmbed content
67
22
  def oembed_tag
68
23
  tag.div(nil,
69
24
  id: "oembed-viewer",
@@ -74,30 +29,24 @@ module Geoblacklight
74
29
  })
75
30
  end
76
31
 
77
- # The leaflet and openlayers viewers share a lot of the same data attributes
78
- # so we can use a base tag for both of them and just vary a few names
79
- def base_tag
80
- viewer_name = openlayers? ? "openlayers-viewer" : "leaflet-viewer"
81
- tag.div(nil,
82
- id: viewer_name,
83
- class: "viewer #{viewer_name}",
84
- data: {
85
- "controller" => viewer_name,
86
- "#{viewer_name}-available-value" => helpers.document_available?(@document),
87
- "#{viewer_name}-basemap-value" => Geoblacklight.configuration.basemap_provider,
88
- "#{viewer_name}-dark-basemap-value" => Geoblacklight.configuration.dark_basemap_provider,
89
- "#{viewer_name}-protocol-value" => protocol,
90
- "#{viewer_name}-url-value" => @document.viewer_endpoint,
91
- "#{viewer_name}-map-geom-value" => @document.geometry.geojson,
92
- "#{viewer_name}-layer-id-value" => @document.wxs_identifier,
93
- "#{viewer_name}-options-value" => leaflet_options.to_h,
94
- "#{viewer_name}-page-value" => params[:action]&.upcase,
95
- "#{viewer_name}-draw-initial-bounds-value" => true
96
- }.compact)
32
+ def ogm_viewer_tag
33
+ tag.ogm_viewer(nil,
34
+ :class => "viewer ogm-viewer",
35
+ "hide-title" => true,
36
+ "theme" => helpers.geoblacklight_viewer_theme,
37
+ "light-basemap" => Geoblacklight.configuration.light_basemap_url,
38
+ "dark-basemap" => Geoblacklight.configuration.dark_basemap_url,
39
+ "record-url" => helpers.viewer_solr_document_path(@document),
40
+ :data => {restricted_origins: restricted_origins})
97
41
  end
98
42
 
99
- def leaflet_options
100
- Geoblacklight.configuration.leaflet_options
43
+ # URLs where the viewer will send credentials (cookies) to, in order to try
44
+ # to preview restricted data
45
+ def restricted_origins
46
+ origins = Geoblacklight.configuration.restricted_origins
47
+ return if origins.blank? || !@document.restricted? || !helpers.document_available?(@document)
48
+
49
+ origins.to_json
101
50
  end
102
51
  end
103
52
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Geoblacklight
4
+ # A map of where one record is, beside its metadata. There is nothing to search and nothing it
5
+ # reports back; the record's own extent is all it draws, from the same endpoint <ogm-viewer>
6
+ # already reads its metadata from.
7
+ class LocatorMapComponent < ViewComponent::Base
8
+ def initialize(document:, id: "locator-map")
9
+ @document = document
10
+ @id = id
11
+ super()
12
+ end
13
+
14
+ def viewer_tag
15
+ tag.ogm_locator(nil, **attributes)
16
+ end
17
+
18
+ private
19
+
20
+ def attributes
21
+ {
22
+ :id => @id,
23
+ :class => "viewer locator-map",
24
+ "theme" => helpers.geoblacklight_viewer_theme,
25
+ "light-basemap" => Geoblacklight.configuration.light_basemap_url,
26
+ "dark-basemap" => Geoblacklight.configuration.dark_basemap_url,
27
+ "record-url" => helpers.viewer_solr_document_path(@document)
28
+ }
29
+ end
30
+ end
31
+ end
@@ -1,3 +1,3 @@
1
1
  <%= link_to t('geoblacklight.tools.login_to_view'),
2
- new_user_session_path(referrer: request.original_url),
2
+ helpers.blacklight_login_path,
3
3
  class: ['btn', 'login-btn', 'd-block'] %>
@@ -10,8 +10,24 @@ module Geoblacklight
10
10
  super()
11
11
  end
12
12
 
13
+ def before_render
14
+ store_return_location if render?
15
+ end
16
+
13
17
  def render?
14
- document.restricted? && document.same_institution? && !helpers.user_signed_in?
18
+ document.restricted? &&
19
+ document.same_institution? &&
20
+ helpers.blacklight_login_path.present? &&
21
+ !helpers.current_user_signed_in?
22
+ end
23
+
24
+ private
25
+
26
+ # Bring the user back to this record once they've signed in, for either
27
+ # Devise or Rails auth.
28
+ def store_return_location
29
+ controller.store_location_for(:user, request.original_url) if controller.respond_to?(:store_location_for)
30
+ controller.send(:store_location_for_rails_authentication)
15
31
  end
16
32
  end
17
33
  end
@@ -2,19 +2,13 @@
2
2
 
3
3
  module Geoblacklight
4
4
  class MetadataDescriptionMarkdownComponent < Blacklight::MetadataFieldComponent
5
- # Transform markdown into HTML
6
- # @param [String] value markdown to transform
7
- # @return [ActiveSupport::SafeBuffer] rendered HTML
8
- def markdown_to_html(value)
9
- Commonmarker.to_html(value).html_safe
10
- end
11
-
12
5
  def render_field_values
13
6
  [tag.div(class: "truncate-abstract", data: {
14
7
  read_more_text: t("geoblacklight.truncate.read_more"),
15
- close_text: t("geoblacklight.truncate.close")
8
+ close_text: t("geoblacklight.truncate.close"),
9
+ max_lines: 12
16
10
  }) do
17
- safe_join(Array(@field.values).flatten.map { |value| markdown_to_html(value) })
11
+ safe_join(Array(@field.values).flatten.map { |value| helpers.markdown_to_html(value) })
18
12
  end]
19
13
  end
20
14
  end
@@ -0,0 +1,2 @@
1
+ <%= viewer_tag %>
2
+ <%= bounds_tag %>
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rgeo"
4
+ require "rgeo-geojson"
5
+
6
+ module Geoblacklight
7
+ # Renders a map that can show more than one record at a time, and number them
8
+ # in the order they were provided. Use for homepage, search, bookmarks, etc.
9
+ class OverviewMapComponent < ViewComponent::Base
10
+ def initialize(
11
+ map_geometry: config.homepage_map_geom,
12
+ geosearch: false,
13
+ id: "overview-map"
14
+ )
15
+ @map_geometry = map_geometry if map_geometry != "null"
16
+ @geosearch = geosearch
17
+ @id = id
18
+ super()
19
+ end
20
+
21
+ def viewer_tag
22
+ tag.ogm_overview(nil, **attributes)
23
+ end
24
+
25
+ # Hidden element containing the search bounds for the Stimulus controller
26
+ # to parse when this component is reconnected via Turbo
27
+ def bounds_tag
28
+ tag.span hidden: true, id: "#{@id}-bounds", data: {bounds: search_bounds}
29
+ end
30
+
31
+ def config
32
+ Geoblacklight.configuration
33
+ end
34
+
35
+ private
36
+
37
+ def attributes
38
+ {
39
+ :id => @id,
40
+ :class => "viewer overview-map",
41
+ "theme" => helpers.geoblacklight_viewer_theme,
42
+ "light-basemap" => Geoblacklight.configuration.light_basemap_url,
43
+ "dark-basemap" => Geoblacklight.configuration.dark_basemap_url,
44
+ "search-bounds" => search_bounds,
45
+ "view-bounds" => view_bounds,
46
+ "geosearch" => @geosearch || nil,
47
+ "search-help-text" => (t("geoblacklight.map.geosearch.search_help") if @geosearch),
48
+ "data-turbo-permanent" => true,
49
+ :data => data_attributes
50
+ }
51
+ end
52
+
53
+ def data_attributes
54
+ {
55
+ :controller => "overview-map",
56
+ :action => "boundsChange->overview-map#search highlightChange->overview-map#highlight",
57
+ "overview-map-catalog-url-value" => (helpers.search_action_path if @geosearch)
58
+ }.compact
59
+ end
60
+
61
+ # The bounding box a search is currently filtered to, as W,S,E,N degrees.
62
+ # When this is active, the camera frames it with some padding around the edges.
63
+ def search_bounds
64
+ params[:bbox] if params[:bbox].present?
65
+ end
66
+
67
+ # Where the camera should frame initially. Used for making e.g. the homepage
68
+ # map point somewhere other than null island on initial load.
69
+ def view_bounds
70
+ envelope(@map_geometry) if @map_geometry.present?
71
+ end
72
+
73
+ # Convert geometry provided by homepage_map_geom into a bounding box that
74
+ # we can pass to MapLibre's camera to frame.
75
+ def envelope(geometry)
76
+ shape = RGeo::GeoJSON.decode(geometry)
77
+ raise "not a geometry" unless shape
78
+
79
+ box = RGeo::Cartesian::BoundingBox.create_from_geometry(shape)
80
+ [box.min_x, box.min_y, box.max_x, box.max_y].join(" ")
81
+ rescue
82
+ Geoblacklight.logger.warn "Unreadable homepage_map_geom: #{geometry}"
83
+ nil
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,12 @@
1
+ <li class="list-group-item">
2
+ <%= link_to document.title, solr_document_path(document) %>
3
+ <%= render Geoblacklight::HeaderBadgesComponent.new(document: document) %>
4
+ <% if document.description.present? %>
5
+ <div class="truncate-abstract description" data-read-more-text="<%= t("geoblacklight.truncate.read_more") %>" data-close-text="<%= t("geoblacklight.truncate.close") %>" data-max-lines=5>
6
+ <%= description %>
7
+ </div>
8
+ <% end %>
9
+ <% if render_sibling_link? %>
10
+ <%= link_to t("geoblacklight.relations.browse.#{browse_label_key}", count: sibling_count), sibling_search_path, class: "browse-all" %>
11
+ <% end %>
12
+ </li>
@@ -0,0 +1,30 @@
1
+ module Geoblacklight
2
+ module Relations
3
+ # Display a single record related to this one
4
+ class RelationComponent < ViewComponent::Base
5
+ attr_reader :document, :sibling_count, :browse_label_key
6
+
7
+ def initialize(document:, field: nil, sibling_count: nil, browse_label_key: nil)
8
+ @document = document
9
+ @field = field
10
+ @sibling_count = sibling_count
11
+ @browse_label_key = browse_label_key
12
+ super()
13
+ end
14
+
15
+ def description
16
+ safe_join(Array(document.description).map { |value| helpers.markdown_to_html(value) })
17
+ end
18
+
19
+ # sibling_count includes the current document itself, so there's only something
20
+ # worth browsing to when it's more than just that one document.
21
+ def render_sibling_link?
22
+ sibling_count.to_i > 1
23
+ end
24
+
25
+ def sibling_search_path
26
+ helpers.search_catalog_path(f: {@field => [document.id]})
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,15 @@
1
+ <div class="card relations">
2
+ <div class="card-header">
3
+ <h2 class="mb-0 h6"><%= t(rel_type_info.label, count: result_count) %></h2>
4
+ </div>
5
+ <ul class="list-group list-group-flush relation-list">
6
+ <% related_docs[0..2].each do |document| %>
7
+ <%= render Geoblacklight::Relations::RelationComponent.new(document: document, field: configuration.field, sibling_count: sibling_count(document), browse_label_key: browse_label_key) %>
8
+ <% end %>
9
+ </ul>
10
+ <% if result_count > 3 && configuration.query_type == "descendants" %>
11
+ <div class="card-footer">
12
+ <%= link_to t("geoblacklight.relations.browse.#{browse_label_key}", count: result_count), browse_all_path %>
13
+ </div>
14
+ <% end %>
15
+ </div>
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Geoblacklight
4
+ module Relations
5
+ # Display links to records related to this one
6
+ class RelationsComponent < ViewComponent::Base
7
+ attr_reader :relationship_type, :rel_type_info
8
+
9
+ def initialize(relations:, relationship_type:, rel_type_info:)
10
+ @relations = relations
11
+ @relationship_type = relationship_type
12
+ @rel_type_info = rel_type_info
13
+ super()
14
+ end
15
+
16
+ def render?
17
+ result_count.positive?
18
+ end
19
+
20
+ def result_count
21
+ response["numFound"].to_i
22
+ end
23
+
24
+ def related_docs
25
+ @related_docs ||= Array(response["docs"]).map { |hash| ::SolrDocument.new(hash) }
26
+ end
27
+
28
+ def browse_all_path
29
+ helpers.search_catalog_path({f: {configuration.field => [@relations.link_id]}})
30
+ end
31
+
32
+ # @param [SolrDocument] document an ancestor of the current document
33
+ # @return [Integer, nil] how many documents in total - including the current one,
34
+ # which is always among them, since that's how this ancestor was found in the
35
+ # first place - share this ancestor.
36
+ def sibling_count(document)
37
+ return unless configuration.query_type == "ancestors"
38
+
39
+ Geoblacklight::Relations::Descendants.new(RSolr.solr_escape(document.id), configuration.field, @relations.repository).results["numFound"].to_i
40
+ end
41
+
42
+ # @return [String] locale key under geoblacklight.relations.browse, e.g. "part_of"
43
+ # for both the "part_of_ancestors" and "part_of_descendants" relationship_type
44
+ def browse_label_key
45
+ relationship_type.to_s.sub(/_(ancestors|descendants)\z/, "")
46
+ end
47
+
48
+ private
49
+
50
+ def configuration
51
+ Geoblacklight.configuration.relationships_shown.public_send(relationship_type)
52
+ end
53
+
54
+ def response
55
+ @response ||= @relations.public_send(relationship_type) || {}
56
+ end
57
+ end
58
+ end
59
+ end
@@ -8,7 +8,7 @@ module Geoblacklight
8
8
  dataset_type
9
9
  end
10
10
 
11
- def icon(field)
11
+ def icon
12
12
  return resource_type_icon unless resource_type_icon_missing?
13
13
  default_resource_icon
14
14
  end
@@ -1,47 +1,28 @@
1
1
  <%# This template copies from Blacklight's components/document_component.html.erb
2
2
  # for the wrapping `content_tag @component` structure
3
- # and adds custom layout within for the document header, status-icons and more-info areas %>
3
+ # and adds custom layout within for the document header, badges and description area %>
4
4
 
5
5
  <%= content_tag @component,
6
6
  id: @id,
7
7
  data: {
8
8
  'document-id': @document.id.to_s.parameterize,
9
- 'document-counter': @counter,
10
- 'search-results-target': 'result',
11
- 'action': 'mouseenter->search-results#previewResultOnMap mouseleave->search-results#clearPreview'
9
+ 'map-id': @document.id.to_s,
10
+ 'document-counter': @counter
12
11
  },
13
12
  itemscope: true,
14
13
  itemtype: @document.itemtype,
15
14
  class: classes do %>
16
-
17
- <%= content_tag :div, class: 'document-main-section' do %>
18
- <%= content_tag :header, class: 'documentHeader index-split', data: { layer_id: @document.id, geom: @document.geometry.geojson } do %>
19
- <div class="document-counter">
20
- <%= t('blacklight.search.documents.counter', :counter => @counter) if @counter %>
15
+ <%= header %>
16
+ <%= thumbnail %>
17
+ <div class="document-main-section">
18
+ <%= title %>
19
+ <div class="metadata">
20
+ <%= render Geoblacklight::HeaderBadgesComponent.new(document: @document) %>
21
+ <% if document.description.present? %>
22
+ <div class="truncate-abstract description" data-read-more-text="<%= t("geoblacklight.truncate.read_more") %>" data-close-text="<%= t("geoblacklight.truncate.close") %>" data-max-lines=4 itemprop="description">
23
+ <%= description %>
24
+ </div>
25
+ <% end %>
21
26
  </div>
22
-
23
- <h3 class="index_title">
24
- <%= helpers.link_to_document(@document, counter: @counter, itemprop: "name") %>
25
- </h3>
26
-
27
- <button
28
- class="btn dropdown-toggle collapsed"
29
- data-bs-toggle="collapse"
30
- data-bs-target="#doc-<%= @document.id %>-fields-collapse"
31
- aria-label="<%= t('geoblacklight.metadata.toggle_summary') %>"
32
- aria-expanded="false"
33
- aria-controls="doc-<%= @document.id %>-fields-collapse">
34
- </button>
35
- <% end %>
36
- <div class="status-icons mx-4 mt-2">
37
- <%= render Geoblacklight::HeaderIconsComponent.new(document: @document) %>
38
27
  </div>
39
- <% end %>
40
28
  <% end %>
41
- <div class="more-info-area border-bottom">
42
- <div id="doc-<%= @document.id %>-fields-collapse" class="collapse">
43
- <small itemprop="description">
44
- <%= index_fields_display %>
45
- </small>
46
- </div>
47
- </div>
@@ -9,20 +9,8 @@ module Geoblacklight
9
9
  # Otherwise view_component will not provide the count value when calling the component.
10
10
  #
11
11
  class SearchResultComponent < Blacklight::DocumentComponent
12
- # Presents configured index fields in search results. Passes values through
13
- # configured helper_method. Multivalued fields separated by presenter
14
- # field_value_separator (default: comma). Fields separated by period.
15
- # @return [String]
16
- def index_fields_display
17
- fields_values = []
18
- @presenter.configuration.index_fields.each_value do |field_config|
19
- val = @presenter.field_value(field_config).to_sentence
20
- if val.present?
21
- val += "." unless val.end_with?(".")
22
- fields_values << val
23
- end
24
- end
25
- safe_join(fields_values, " ")
12
+ def description
13
+ safe_join(Array(document.description).map { |value| helpers.markdown_to_html(value) })
26
14
  end
27
15
  end
28
16
  end