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
@@ -1,128 +0,0 @@
1
- const indexMapInfoTemplate = (data, labels) => `
2
- <div class="index-map-info">
3
- ${
4
- data.title
5
- ? `
6
- <div class="col-sm-12">
7
- <h3>${data.title}</h3>
8
- </div>`
9
- : ""
10
- }
11
- <div class="col-sm-12">
12
- ${
13
- data.thumbnailUrl
14
- ? `
15
- ${
16
- data.websiteUrl
17
- ? `
18
- <a href="${data.websiteUrl}">
19
- <img src="${data.thumbnailUrl}" class="img-responsive">
20
- </a>`
21
- : `
22
- <img src="${data.thumbnailUrl}">`
23
- }`
24
- : ""
25
- }
26
- <dl class="row dl-invert document-metadata">
27
- ${
28
- data.websiteUrl
29
- ? `
30
- <dt class="col-sm-3">${labels.websiteLabel}</dt>
31
- <dd class="col-sm-9"><a href="${data.websiteUrl}">${data.websiteUrl}</a></dd>`
32
- : ""
33
- }
34
- ${
35
- data.downloadUrl
36
- ? `
37
- <dt class="col-sm-3">${labels.downloadLabel}</dt>
38
- <dd class="col-sm-9"><a href="${data.downloadUrl}">${data.downloadUrl}</a></dd>`
39
- : ""
40
- }
41
- ${
42
- data.recordIdentifier
43
- ? `
44
- <dt class="col-sm-3">${labels.recordIdentifierLabel}</dt>
45
- <dd class="col-sm-9">${data.recordIdentifier}</dd>`
46
- : ""
47
- }
48
- ${
49
- data.label
50
- ? `
51
- <dt class="col-sm-3">${labels.labelLabel}</dt>
52
- <dd class="col-sm-9">${data.label}</dd>`
53
- : ""
54
- }
55
- ${
56
- data.note
57
- ? `
58
- <dt class="col-sm-3">${labels.noteLabel}</dt>
59
- <dd class="col-sm-9">${data.note}</dd>`
60
- : ""
61
- }
62
- </dl>
63
- </div>
64
- </div>`
65
-
66
- const indexMapDownloadTemplate = (data, labels) =>
67
- data.downloadUrl
68
- ? `
69
- <li class="list-group-item download js-index-map-feature">
70
- <h3 class="card-subtitle">${labels.selectedFeature}</h3>
71
- <ul class="list-group list-group-flush list-group-nested">
72
- <li class="list-group-item download">
73
- <div class="download-link-container">
74
- <a class="btn btn-default download download-original" href="${data.downloadUrl}">
75
- ${data.label ? data.label : labels.downloadText}
76
- </a>
77
- </div>
78
- </li>
79
- </ul>
80
- </li>
81
- `
82
- : ""
83
-
84
- const indexMapTemplate = (data) => {
85
- return new Promise((resolve) => {
86
- if (data.iiifUrl && !data.thumbnailUrl) {
87
- fetch(data.iiifUrl)
88
- .then((response) => response.json())
89
- .then((manifestResponse) => {
90
- if (manifestResponse.thumbnail["@id"] !== null) {
91
- data.thumbnailUrl = manifestResponse.thumbnail["@id"]
92
- }
93
- resolve(data) // Resolve the modified data
94
- })
95
- .catch(() => resolve(data)) // In case of error, resolve with original data
96
- } else {
97
- resolve(data) // Immediately resolve if no iiifUrl
98
- }
99
- })
100
- }
101
-
102
- export const availabilityStyle = (availability, leafletOptions) => {
103
- var style =
104
- availability || typeof availability === "undefined"
105
- ? leafletOptions.layers.index.DEFAULT
106
- : leafletOptions.layers.index.UNAVAILABLE
107
- style["fillOpacity"] = leafletOptions.opacity || 0.65
108
- style["opacity"] = leafletOptions.opacity || 0.65
109
- return style
110
- }
111
-
112
- export const updateInformation = (properties) => {
113
- const informationContainer = document.querySelector(".viewer-information")
114
- const labels = informationContainer.dataset
115
-
116
- indexMapTemplate(properties).then((updatedProperties) => {
117
- const indexMapHtml = indexMapInfoTemplate(updatedProperties, labels)
118
- informationContainer.innerHTML = indexMapHtml
119
-
120
- const indexMapDownloadHtml = indexMapDownloadTemplate(updatedProperties, labels)
121
- const downloadElement = document.querySelector(".js-download-list")
122
-
123
- if (Boolean(downloadElement)) {
124
- downloadElement.innerHTML += indexMapDownloadHtml // Appends new download template
125
- downloadElement.querySelectorAll(".js-index-map-feature").forEach((elem) => elem.remove())
126
- }
127
- })
128
- }
@@ -1,57 +0,0 @@
1
- import { latLng, latLngBounds } from "leaflet"
2
-
3
- export const parseWmtsCapabilities = (wmtsCapabilities, layerId) => {
4
- const parser = new DOMParser(),
5
- doc = parser.parseFromString(wmtsCapabilities, "application/xml"),
6
- layers = doc.getElementsByTagName("Layer"),
7
- selectedLayer = findLayer(layers, layerId),
8
- resourceElement = selectedLayer.getElementsByTagName("ResourceURL")[0]
9
-
10
- // Generate URL with Leaflet.TileLayer URL template formatting
11
- const tileURL = resourceElement
12
- .getAttribute("template")
13
- .replace("{Style}", getStyle(selectedLayer))
14
- .replace("{TileMatrixSet}", getTileMatrixSet(selectedLayer))
15
- .replace("TileMatrix", "z")
16
- .replace("TileCol", "x")
17
- .replace("TileRow", "y")
18
-
19
- return { url: tileURL, bounds: getBounds(selectedLayer) }
20
- }
21
-
22
- const findLayer = (layers, layerId) => {
23
- if (layers.length === 1) {
24
- return layers[0]
25
- } else {
26
- for (let i = 0; i < layers.length; i++) {
27
- const ids = layers[i].getElementsByTagName("ows:Identifier")
28
- for (let x = 0; x < ids.length; x++) {
29
- if (ids[x].textContent === layerId) {
30
- return layers[i]
31
- }
32
- }
33
- }
34
- }
35
- }
36
-
37
- const getStyle = (layer) => {
38
- const styleElement = layer.getElementsByTagName("Style")[0]
39
- return styleElement ? styleElement.getElementsByTagName("ows:Identifier")[0].textContent : undefined
40
- }
41
-
42
- const getTileMatrixSet = (layer) => {
43
- const tileMatrixElement = layer.getElementsByTagName("TileMatrixSet")[0]
44
- return tileMatrixElement ? tileMatrixElement.textContent : undefined
45
- }
46
-
47
- const getBounds = (layer) => {
48
- const lcElement = layer.getElementsByTagName("ows:LowerCorner")[0],
49
- ucElement = layer.getElementsByTagName("ows:UpperCorner")[0]
50
- if (lcElement && ucElement) {
51
- const lc = lcElement.textContent.split(" "),
52
- uc = ucElement.textContent.split(" "),
53
- corner1 = latLng(lc[1], lc[0]),
54
- corner2 = latLng(uc[1], uc[0])
55
- return latLngBounds(corner1, corner2)
56
- }
57
- }
@@ -1,146 +0,0 @@
1
- /** This file contains methods for creating the various types of leaflet and esri-leaflet layers required in leaflet_viewer_controller.
2
- * If complex logic is needed for a certain layer type, it is broken out into its own file,
3
- * such as layer_wmts.js for WMTS layers and layer_index_map.js for index map layers, at the same directory level as this file.
4
- */
5
- import { tileLayer, geoJson, circleMarker } from "leaflet"
6
- import { dynamicMapLayer, featureLayer, tiledMapLayer } from "esri-leaflet"
7
- import { parseWmtsCapabilities } from "geoblacklight/leaflet/layer_wmts"
8
- import { availabilityStyle, updateInformation } from "geoblacklight/leaflet/layer_index_map"
9
- import { getTileJsonBounds } from "geoblacklight/leaflet/utils"
10
-
11
- // Create a leaflet tile layer for WMS
12
- export const wmsLayer = (url, { layerId, opacity, detectRetina }) => {
13
- return tileLayer.wms(url, {
14
- layers: layerId,
15
- format: "image/png",
16
- transparent: true,
17
- tiled: true,
18
- CRS: "EPSG:3857",
19
- opacity,
20
- detectRetina,
21
- })
22
- }
23
-
24
- // Fetch a WMTSCapabilities document and create a leaflet tileLayer using it
25
- export const wmtsLayer = async (url, { opacity, detectRetina, layerId }) => {
26
- const response = await fetch(url)
27
- if (!response.ok) throw new Error("Unable to fetch WMTSCapabilities document", url)
28
-
29
- const wmtsCapabilities = await response.text()
30
- if (!wmtsCapabilities) throw new Error("Unable to parse WMTSCapabilities document", url)
31
-
32
- const tileInfo = parseWmtsCapabilities(wmtsCapabilities, layerId)
33
- const options = tileInfo.bounds ? { bounds: tileInfo.bounds } : {}
34
- return tileLayer(tileInfo.url, {
35
- opacity,
36
- detectRetina,
37
- ...options,
38
- })
39
- }
40
-
41
- // Create an ESRI-leaflet dynamic map layer
42
- export const esriDynamicMapLayer = (url, { opacity, detectRetina }) => {
43
- // Remove any trailing slash and get the last segment from the URL
44
- url = url.replace(/\/$/, "")
45
- const pathArray = url.split("/")
46
- const lastSegment = pathArray[pathArray.length - 1]
47
-
48
- // If the last segment is an integer it's the layer ID
49
- let layerId
50
- if (Number(lastSegment) === parseInt(lastSegment, 10)) {
51
- layerId = lastSegment
52
- url = url.slice(0, -(lastSegment.length + 1))
53
- }
54
-
55
- const options = layerId ? { layers: [layerId] } : {}
56
- return dynamicMapLayer({
57
- url,
58
- opacity,
59
- detectRetina,
60
- ...options,
61
- })
62
- }
63
-
64
- // Create an ESRI-leaflet feature layer
65
- export const esriFeatureLayer = (url, { opacity, detectRetina }) => {
66
- return featureLayer({
67
- url,
68
- opacity,
69
- detectRetina,
70
- })
71
- }
72
-
73
- // Create an ESRI tiled map layer
74
- export const esriTiledMapLayer = async (url, options) => {
75
- const response = await fetch(url)
76
-
77
- if (!response.ok) throw new Error("Unable to fetch EsriTiledMapLayer document", url)
78
-
79
- let layerInfo
80
- try {
81
- layerInfo = await response.json()
82
- } catch (error) {
83
- throw new Error("Unable to parse TiledMapLayer document", response)
84
- }
85
-
86
- // For an example of tiledMapLayer data see nyu-test-soil-survey-map
87
- // We aren't sure what the json structure looks like
88
- // This is not rendering anything (and wasn't before we made changes) and the keys are not even present
89
- // Check out this json: https://dnrmaps.wi.gov/arcgis2/rest/services/TS_AGOL_STAGING_SERVICES/EN_AGOL_STAGING_SurfaceWater_WTM/MapServer/2?f=pjson -- wrong protocol, now a feature map??
90
- if (layerInfo.singleFusedMapCache === true && layerInfo.spatialReference.wkid === 102100) {
91
- return tiledMapLayer({ url, ...options })
92
- }
93
- }
94
-
95
- // Create a leaflet tile layer
96
- export const tileJsonLayer = async (url, options) => {
97
- const response = await fetch(url)
98
-
99
- if (!response.ok) {
100
- throw new Error("Unable to fetch TiledJson document", url)
101
- }
102
-
103
- const layerInfo = await response.json()
104
-
105
- const bounds = getTileJsonBounds(layerInfo)
106
- if (bounds) options.bounds = bounds
107
- const tileUrl = layerInfo.tiles[0]
108
- return tileLayer(tileUrl, options)
109
- }
110
-
111
- // Fetch an indexMapLayer document and create a leaflet geoJSON layer
112
- export const indexMapLayer = async (url, leafletOptions) => {
113
- let prevLayer = null
114
-
115
- const response = await fetch(url)
116
-
117
- if (!response.ok) {
118
- throw new Error("Unable to fetch indexMapLayer document", url)
119
- }
120
-
121
- const data = await response.json()
122
-
123
- // name the const geoJSONLayer; we access it self-referentially within the method
124
- const geoJSONLayer = geoJson(data, {
125
- style: (feature) => availabilityStyle(feature.properties.available, leafletOptions),
126
- onEachFeature: (feature, layer) => {
127
- if (feature.properties.label !== null) {
128
- layer.bindTooltip(feature.properties.label)
129
- }
130
- if (feature.properties.available !== null) {
131
- layer.on("click", (e) => {
132
- layer.setStyle(leafletOptions.layers.index.SELECTED)
133
- if (prevLayer !== null) {
134
- leafletOptions.opacity = layer.options.fillOpacity
135
- geoJSONLayer.resetStyle(prevLayer)
136
- }
137
- prevLayer = layer
138
- updateInformation(feature.properties)
139
- })
140
- }
141
- },
142
- pointToLayer: (feature, latlng) => circleMarker(latlng),
143
- })
144
-
145
- return geoJSONLayer
146
- }
@@ -1,83 +0,0 @@
1
- import { latLngBounds, Util, geoJSON, latLng } from "leaflet"
2
-
3
- export const bboxToBounds = (bbox) => {
4
- bbox = bbox.split(" ")
5
- if (bbox.length === 4) {
6
- return latLngBounds([
7
- [parseFloat(bbox[1]), parseFloat(bbox[0])],
8
- [parseFloat(bbox[3]), parseFloat(bbox[2])],
9
- ])
10
- } else {
11
- throw new Error("Invalid bounding box string")
12
- }
13
- }
14
-
15
- export const boundsToBbox = (bounds) => {
16
- let sw = bounds.getSouthWest(),
17
- ne = bounds.getNorthEast()
18
-
19
- if (ne.lng - sw.lng >= 360) {
20
- sw.lng = -180
21
- ne.lng = 180
22
- }
23
- sw = sw.wrap()
24
- ne = ne.wrap()
25
- return [Util.formatNum(sw.lng, 6), Util.formatNum(sw.lat, 6), Util.formatNum(ne.lng, 6), Util.formatNum(ne.lat, 6)]
26
- }
27
-
28
- export const geoJSONToBounds = (geojson) => {
29
- const layer = geoJSON(geojson)
30
- return layer.getBounds()
31
- }
32
-
33
- export const debounce = (fn, delay) => {
34
- let timeout = null
35
- return function (...args) {
36
- clearTimeout(timeout)
37
- timeout = setTimeout(() => {
38
- fn.apply(this, args)
39
- }, delay)
40
- }
41
- }
42
-
43
- export const getTileJsonBounds = (doc) => {
44
- const bounds = doc.bounds
45
- if (bounds) {
46
- const corner1 = latLng(bounds[1], bounds[0]),
47
- corner2 = latLng(bounds[3], bounds[2])
48
- return latLngBounds(corner1, corner2)
49
- }
50
- }
51
-
52
- export const getInspectingText = () =>
53
- document.getElementById("attribute-table")?.dataset.inspectingText || "Inspecting"
54
-
55
- export const getNotFoundText = () =>
56
- document.getElementById("attribute-table")?.dataset.notFoundText || "Could not find that feature"
57
-
58
- export const appendLoadingMessage = () => {
59
- const spinner = `<tbody class="attribute-table-body"><tr><td colspan="2">
60
- <span id="attribute-table">
61
- <div class="spinner-border" role="status"><span class="visually-hidden">${getInspectingText()}</span></div>
62
- </span>
63
- </td></tr></tbody>`
64
-
65
- document.querySelector(".attribute-table-body").innerHTML = spinner
66
- }
67
-
68
- export const appendErrorMessage = () => {
69
- document.querySelector(".attribute-table-body").innerHTML = `<tbody class="attribute-table-body">
70
- <tr><td colspan="2">${getNotFoundText()}</td></tr></tbody>`
71
- }
72
-
73
- // Looks for strings that could be URLs and wraps them in <a> tags
74
- export const linkify = (str) => {
75
- if (!str) return ""
76
- const urlRegEx =
77
- /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[\-;:&=\+\$,\w]+@)?[A-Za-z0-9\.\-]+|(?:www\.|[\-;:&=\+\$,\w]+@)[A-Za-z0-9\.\-]+)((?:\/[\+~%\/\.\w\-]*)?\??(?:[\-\+=&;%@\.\w]*)#?(?:[\.\!\/\\\w]*))?)/g
78
- return str.toString().replace(urlRegEx, "<a href='$1'>$1</a>")
79
- }
80
-
81
- export const getLayerOpacity = (layer) => {
82
- return layer.options.fillOpacity ? layer.options.fillOpacity : layer.options.opacity
83
- }
@@ -1,55 +0,0 @@
1
- export default {
2
- dark_matter: {
3
- url: "https://{a-d}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png",
4
- attributions:
5
- '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, &copy; <a href="http://carto.com/attributionss">Carto</a>',
6
- maxZoom: 18,
7
- },
8
- positron: {
9
- url: "https://{a-d}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png",
10
- attributions:
11
- '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, &copy; <a href="http://carto.com/attributionss">Carto</a>',
12
- maxZoom: 18,
13
- },
14
- positron_lite: {
15
- url: "https://{a-d}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}.png",
16
- attributions:
17
- '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, &copy; <a href="http://carto.com/attributionss">Carto</a>',
18
- maxZoom: 18,
19
- },
20
- world_antique: {
21
- url: "https://cartocdn_{a-d}.global.ssl.fastly.net/base-antique/{z}/{x}/{y}.png",
22
- attributions:
23
- '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, &copy; <a href="http://carto.com/attributionss">Carto</a>',
24
- maxZoom: 18,
25
- },
26
- world_eco: {
27
- url: "https://cartocdn_{a-d}.global.ssl.fastly.net/base-eco/{z}/{x}/{y}.png",
28
- attributions:
29
- '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, &copy; <a href="http://carto.com/attributionss">Carto</a>',
30
- maxZoom: 18,
31
- },
32
- flat_blue: {
33
- url: "https://cartocdn_{a-d}.global.ssl.fastly.net/base-flatblue/{z}/{x}/{y}.png",
34
- attributions:
35
- '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, &copy; <a href="http://carto.com/attributionss">Carto</a>',
36
- maxZoom: 18,
37
- },
38
- midnight_commander: {
39
- url: "https://cartocdn_{a-d}.global.ssl.fastly.net/base-midnight/{z}/{x}/{y}.png",
40
- attributions:
41
- '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, &copy; <a href="http://carto.com/attributionss">Carto</a>',
42
- maxZoom: 18,
43
- },
44
- openstreetmap_hot: {
45
- url: "https://{a-c}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png",
46
- attributions:
47
- '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>, Tiles courtesy of <a href="http://hot.openstreetmap.org/" target="_blank">Humanitarian OpenStreetMap Team</a>',
48
- maxZoom: 19,
49
- },
50
- openstreetmap_standard: {
51
- url: "https://tile.openstreetmap.org/{z}/{x}/{y}.png",
52
- attributions: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
53
- maxZoom: 19,
54
- },
55
- }
@@ -1,42 +0,0 @@
1
- import { getInspectingText, getNotFoundText, linkify } from "geoblacklight/leaflet/utils"
2
-
3
- export const pmTilesInspection = (map) => {
4
- // add crosshair class for map items
5
- map.on("pointermove", function (e) {
6
- var pixel = map.getEventPixel(e.originalEvent)
7
- var hit = map.hasFeatureAtPixel(pixel)
8
- map.getViewport().style.cursor = hit ? "crosshair" : ""
9
- })
10
-
11
- map.on("click", (event) => {
12
- const spinner = document.createElement("tbody")
13
- spinner.className = "attribute-table-body"
14
- spinner.innerHTML = `<tr><td colspan="2"><div class="spinner-border" role="status"><span class="visually-hidden">${getInspectingText()}</span></div></td></tr>`
15
- document.querySelector(".attribute-table-body").replaceWith(spinner)
16
-
17
- const features = map.getFeaturesAtPixel(event.pixel)
18
- if (features.length == 0) {
19
- document.querySelector(".attribute-table-body").innerHTML = `<tr><td colspan="2">${getNotFoundText()}</td></tr>`
20
- return
21
- }
22
-
23
- const properties = features[0].getProperties()
24
- populateAttributeTable(properties)
25
- })
26
- }
27
-
28
- const populateAttributeTable = (properties) => {
29
- let html = '<tbody class="attribute-table-body">'
30
-
31
- // Step through properties and append to table
32
- Object.keys(properties).forEach((property) => {
33
- html += `<tr><td>${property}</td>
34
- <td>${linkify(properties[property])}</td></tr>`
35
- })
36
- html += "</tbody>"
37
-
38
- const tableBody = document.querySelector(".attribute-table-body")
39
- if (tableBody) {
40
- tableBody.outerHTML = html // Replace existing table body with new content
41
- }
42
- }
@@ -1,44 +0,0 @@
1
- import VectorTile from "ol/layer/VectorTile"
2
- import { Style, Stroke, Fill, Circle } from "ol/style"
3
- import { PMTilesVectorSource } from "ol-pmtiles"
4
- import { useGeographic } from "ol/proj"
5
- import GeoTIFF from "ol/source/GeoTIFF"
6
- import WebGLTileLayer from "ol/layer/WebGLTile"
7
-
8
- // Create a new PMTiles layer
9
- export const pmTilesLayer = (url) => {
10
- useGeographic()
11
- return new VectorTile({
12
- declutter: true,
13
- source: new PMTilesVectorSource({ url }),
14
- style: new Style({
15
- stroke: new Stroke({
16
- color: "#7070B3",
17
- width: 1,
18
- }),
19
- fill: new Fill({
20
- color: "#FFFFFF",
21
- }),
22
- image: new Circle({
23
- radius: 7,
24
- fill: new Fill({
25
- color: "#7070B3",
26
- }),
27
- stroke: new Stroke({
28
- color: "#FFFFFF",
29
- width: 2,
30
- }),
31
- }),
32
- }),
33
- })
34
- }
35
-
36
- // Create a new cloud-optimized GeoTIFF (COG) layer
37
- export const cogLayer = (url) => {
38
- return new WebGLTileLayer({
39
- source: new GeoTIFF({
40
- sources: [{ url }],
41
- convertToRGB: true,
42
- }),
43
- })
44
- }
@@ -1,8 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- json.current_doc @relations.search_id
4
- json.relations do
5
- Geoblacklight.configuration.relationships_shown.each do |key, _value|
6
- json.set! key.downcase.to_s, @relations.public_send(key) unless @relations.public_send(key)["numFound"].to_i.zero?
7
- end
8
- end
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Geoblacklight
4
- class Configuration
5
- # Configuration for Leaflet map layer styles.
6
- class LayerConfig
7
- include ActiveModel::Model
8
- include ActiveModel::Attributes
9
-
10
- attribute :color, :string
11
- attribute :weight, :integer, default: 1
12
- attribute :radius, :integer, default: 4
13
- attribute :sr_color_name, :string
14
-
15
- # Supports Hash-like access for backward compatibility
16
- # @param [Symbol, String] key
17
- def [](key)
18
- respond_to?(key) ? send(key) : nil
19
- end
20
-
21
- # Returns the attributes as a symbolized hash
22
- # @return [Hash]
23
- def to_h
24
- attributes.symbolize_keys
25
- end
26
- end
27
- end
28
- end
@@ -1,73 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Geoblacklight
4
- class Configuration
5
- class LeafletConfig
6
- include ActiveModel::Model
7
- include ActiveModel::Attributes
8
-
9
- attr_accessor :bounds_overlay, :controls
10
-
11
- attr_reader :sleep, :layers
12
-
13
- # set to false to display attribute table as a separate panel below the map
14
- attribute :sidebar, :boolean, default: true
15
- attribute :selected_color, :string, default: "#2C7FB8"
16
-
17
- DEFAULT_SLEEP_CONFIG = {
18
- sleep: true, # set to false to disable
19
- margin_distance: 100, # set to zero / false if you want to disable this check
20
- sleeptime: 750,
21
- waketime: 750,
22
- hovertowake: false,
23
- background: "rgba(214, 214, 214, .7)"
24
- }.freeze
25
-
26
- # Built lazily (rather than as a frozen constant) so the sr_color_name
27
- # values pick up the current I18n locale each time a config is built.
28
- def self.default_layers_config
29
- {
30
- index: {
31
- DEFAULT: LayerConfig.new(
32
- color: "#7FCDBB",
33
- sr_color_name: I18n.t("geoblacklight.map.legend.colors.default")
34
- ),
35
- UNAVAILABLE: LayerConfig.new(
36
- color: "#EDF8B1",
37
- sr_color_name: I18n.t("geoblacklight.map.legend.colors.unavailable")
38
- ),
39
- SELECTED: LayerConfig.new(
40
- color: "#2C7FB8",
41
- sr_color_name: I18n.t("geoblacklight.map.legend.colors.selected")
42
- )
43
- }
44
- }
45
- end
46
-
47
- def initialize
48
- super
49
- @sleep = LeafletSleepConfig.new(DEFAULT_SLEEP_CONFIG)
50
- @layers = LeafletLayersConfig.new(self.class.default_layers_config)
51
- end
52
-
53
- def sleep=(attributes)
54
- @sleep = LeafletSleepConfig.new(attributes)
55
- end
56
-
57
- def layers=(attributes)
58
- @layers = LeafletLayersConfig.new(attributes)
59
- end
60
-
61
- def to_h
62
- {
63
- bounds_overlay: bounds_overlay,
64
- selected_color: selected_color,
65
- sleep: sleep.to_h,
66
- sidebar: sidebar,
67
- layers: layers.to_h,
68
- controls: controls
69
- }.compact
70
- end
71
- end
72
- end
73
- end