geoblacklight 4.1.1 → 4.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +4 -12
  3. data/.gitignore +9 -0
  4. data/Gemfile +14 -0
  5. data/Procfile.dev +3 -0
  6. data/README.md +5 -30
  7. data/app/assets/images/blacklight/geoblacklight-icons.json +1857 -966
  8. data/app/assets/javascripts/geoblacklight/modules/util.js +8 -3
  9. data/app/assets/javascripts/geoblacklight/templates/index_map_info.hbs +22 -1
  10. data/app/assets/javascripts/geoblacklight/viewers/cog.js +5 -0
  11. data/app/assets/javascripts/geoblacklight/viewers/pmtiles.js +5 -0
  12. data/app/controllers/download_controller.rb +1 -21
  13. data/app/frontend/clover/clover_initializer.js +29 -0
  14. data/app/frontend/entrypoints/application.js +28 -0
  15. data/app/frontend/entrypoints/clover.js +5 -0
  16. data/app/frontend/entrypoints/ol.js +5 -0
  17. data/app/frontend/openlayers/basemaps.js +47 -0
  18. data/app/frontend/openlayers/ol_initializer.js +105 -0
  19. data/app/frontend/stylesheets/openlayers.css +1 -0
  20. data/app/helpers/geoblacklight_helper.rb +54 -0
  21. data/app/views/catalog/_citation.html.erb +1 -1
  22. data/app/views/catalog/_show_default_viewer_container.html.erb +1 -2
  23. data/app/views/catalog/_web_services_default.html.erb +6 -1
  24. data/app/views/catalog/_web_services_wfs.html.erb +6 -1
  25. data/app/views/catalog/_web_services_wms.html.erb +6 -1
  26. data/app/views/catalog/web_services.html.erb +16 -0
  27. data/bin/vite +29 -0
  28. data/config/locales/geoblacklight.en.yml +12 -2
  29. data/config/vite.json +14 -0
  30. data/geoblacklight.gemspec +8 -6
  31. data/lib/generators/geoblacklight/install_generator.rb +30 -4
  32. data/lib/generators/geoblacklight/templates/base.html.erb +52 -0
  33. data/lib/generators/geoblacklight/templates/catalog_controller.rb +0 -2
  34. data/lib/generators/geoblacklight/templates/clover.js +5 -0
  35. data/lib/generators/geoblacklight/templates/ol.js +5 -0
  36. data/lib/generators/geoblacklight/templates/package.json +7 -0
  37. data/lib/generators/geoblacklight/templates/settings.yml +4 -0
  38. data/lib/generators/geoblacklight/templates/vite.config.ts +19 -0
  39. data/lib/generators/geoblacklight/templates/vite.json +16 -0
  40. data/lib/generators/geoblacklight/templates/vite.rb +4 -0
  41. data/lib/geoblacklight/constants.rb +3 -1
  42. data/lib/geoblacklight/faraday_middleware/follow_redirects.rb +1 -1
  43. data/lib/geoblacklight/item_viewer.rb +13 -1
  44. data/lib/geoblacklight/metadata_transformer/base.rb +1 -1
  45. data/lib/geoblacklight/version.rb +1 -1
  46. data/package.json +8 -12
  47. data/spec/features/download_layer_spec.rb +1 -2
  48. data/spec/features/full_screen_controll_spec.rb +8 -1
  49. data/spec/features/home_page_spec.rb +3 -0
  50. data/spec/features/search_results_map_spec.rb +1 -0
  51. data/spec/features/web_services_modal_spec.rb +30 -0
  52. data/spec/fixtures/index_maps/index-map-point.geojson +949 -0
  53. data/spec/fixtures/index_maps/index-map-polygon-no-downloadurl.geojson +970 -0
  54. data/spec/fixtures/index_maps/index-map-polygon.geojson +970 -0
  55. data/spec/fixtures/index_maps/index-map-stanford.geojson +390 -0
  56. data/spec/fixtures/index_maps/index-map-v1-complex.geojson +12249 -0
  57. data/spec/fixtures/solr_documents/README.md +1 -0
  58. data/spec/fixtures/solr_documents/b1g_iiif_manifest.json +64 -0
  59. data/spec/fixtures/solr_documents/index-map-polygon-no-downloadurl.json +1 -1
  60. data/spec/fixtures/solr_documents/index-map-polygon.json +1 -1
  61. data/spec/fixtures/solr_documents/index-map-stanford.json +1 -1
  62. data/spec/fixtures/solr_documents/index-map-v1-complex.json +56 -0
  63. data/spec/fixtures/solr_documents/index_map_point.json +1 -1
  64. data/spec/fixtures/solr_documents/public_cog_princeton.json +57 -0
  65. data/spec/fixtures/solr_documents/public_pmtiles_princeton.json +41 -0
  66. data/spec/helpers/geoblacklight_helper_spec.rb +42 -0
  67. data/spec/spec_helper.rb +1 -1
  68. data/spec/test_app_templates/Gemfile.extra +0 -1
  69. data/spec/test_app_templates/lib/generators/test_app_generator.rb +16 -17
  70. data/vite.config.ts +8 -0
  71. metadata +79 -28
  72. data/spec/test_app_templates/solr_documents +0 -1
  73. /data/spec/{test_app_templates → fixtures}/metadata/fgdc.html +0 -0
  74. /data/spec/{test_app_templates → fixtures}/metadata/fgdc.xml +0 -0
  75. /data/spec/{test_app_templates → fixtures}/metadata/iso.html +0 -0
  76. /data/spec/{test_app_templates → fixtures}/metadata/iso.xml +0 -0
@@ -26,9 +26,14 @@ GeoBlacklight.Util = {
26
26
  });
27
27
  if (data.iiifUrl && !data.thumbnailUrl) {
28
28
  var manifest = $.getJSON(data.iiifUrl, function(manifestResponse) {
29
- if (manifestResponse.thumbnail['@id'] !== null) {
30
- data.thumbnailUrl = manifestResponse.thumbnail['@id'];
31
- thumbDeferred.resolve();
29
+ try {
30
+ if (manifestResponse.thumbnail['@id'] !== null) {
31
+ data.thumbnailUrl = manifestResponse.thumbnail['@id'];
32
+ thumbDeferred.resolve();
33
+ }
34
+ }
35
+ catch(err) {
36
+ cb(HandlebarsTemplates["index_map_info"](data));
32
37
  }
33
38
  });
34
39
  } else {
@@ -8,12 +8,21 @@
8
8
  {{#if thumbnailUrl}}
9
9
  {{#if websiteUrl}}
10
10
  <a href="{{websiteUrl}}">
11
- <img src="{{thumbnailUrl}}" class="img-responsive">
11
+ <img src="{{thumbnailUrl}}" class="img-fluid">
12
12
  </a>
13
13
  {{else}}
14
14
  <img src="{{thumbnailUrl}}">
15
15
  {{/if}}
16
16
  {{/if}}
17
+ {{#if thumbUrl}}
18
+ {{#if websiteUrl}}
19
+ <a href="{{websiteUrl}}">
20
+ <img src="{{thumbUrl}}" class="img-fluid">
21
+ </a>
22
+ {{else}}
23
+ <img src="{{thumbUrl}}">
24
+ {{/if}}
25
+ {{/if}}
17
26
  <dl class="row dl-invert document-metadata">
18
27
  {{#if websiteUrl}}
19
28
  <dt class="col-sm-3">Website:</dt>
@@ -23,10 +32,22 @@
23
32
  <dt class="col-sm-3">Download:</dt>
24
33
  <dd class="col-sm-9"><a href="{{downloadUrl}}">{{downloadUrl}}</a></dd>
25
34
  {{/if}}
35
+ {{#if download}}
36
+ <dt class="col-sm-3">Download:</dt>
37
+ <dd class="col-sm-9"><a href="{{download}}">{{download}}</a></dd>
38
+ {{/if}}
39
+ {{#if iiifUrl}}
40
+ <dt class="col-sm-3">iiif URL:</dt>
41
+ <dd class="col-sm-9"><a href="{{iiifUrl}}">{{iiifUrl}}</a></dd>
42
+ {{/if}}
26
43
  {{#if recordIdentifier}}
27
44
  <dt class="col-sm-3">Record Identifier:</dt>
28
45
  <dd class="col-sm-9">{{recordIdentifier}}</dd>
29
46
  {{/if}}
47
+ {{#if recId}}
48
+ <dt class="col-sm-3">Record Identifier:</dt>
49
+ <dd class="col-sm-9">{{recId}}</dd>
50
+ {{/if}}
30
51
  {{#if label}}
31
52
  <dt class="col-sm-3">Label:</dt>
32
53
  <dd class="col-sm-9">{{label}}</dd>
@@ -0,0 +1,5 @@
1
+ //= require geoblacklight/viewers/viewer
2
+
3
+ GeoBlacklight.Viewer.Cog = GeoBlacklight.Viewer.extend({
4
+ load: function() {}
5
+ });
@@ -0,0 +1,5 @@
1
+ //= require geoblacklight/viewers/viewer
2
+
3
+ GeoBlacklight.Viewer.Pmtiles = GeoBlacklight.Viewer.extend({
4
+ load: function() {}
5
+ });
@@ -7,7 +7,7 @@ class DownloadController < ApplicationController
7
7
  rescue_from Geoblacklight::Exceptions::ExternalDownloadFailed do |exception|
8
8
  Geoblacklight.logger.error exception.message + " " + exception.url
9
9
  flash[:danger] = view_context
10
- .tag.span(flash_error_message(exception),
10
+ .tag.span(t("geoblacklight.download.error"),
11
11
  data: {
12
12
  download: "error",
13
13
  download_id: params[:id],
@@ -55,26 +55,6 @@ class DownloadController < ApplicationController
55
55
  end
56
56
  end
57
57
 
58
- protected
59
-
60
- ##
61
- # Creates an error flash message with failed download url
62
- # @param [Geoblacklight::Exceptions::ExternalDownloadFailed] Download failed
63
- # exception
64
- # @return [String] error message to display in flash
65
- def flash_error_message(exception)
66
- if exception.url.present?
67
- t("geoblacklight.download.error_with_url",
68
- link: view_context
69
- .link_to(exception.url,
70
- exception.url,
71
- target: "blank"))
72
- .html_safe
73
- else
74
- t("geoblacklight.download.error")
75
- end
76
- end
77
-
78
58
  private
79
59
 
80
60
  def download_file_path_and_name
@@ -0,0 +1,29 @@
1
+ import { createElement } from 'react'
2
+ import { createRoot } from 'react-dom/client'
3
+ import Viewer from '@samvera/clover-iiif/viewer'
4
+
5
+ export default class CloverInitializer {
6
+ constructor () {
7
+ this.element = document.getElementById('clover-viewer')
8
+ if (this.element) {
9
+ this.iiif_content = this.element.attributes['iiif_content'].value
10
+ }
11
+ }
12
+
13
+ run () {
14
+ if (!this.iiif_content) return false
15
+ const root = createRoot(document.getElementById('clover-viewer'))
16
+ root.render(createElement(Viewer, { id: this.iiif_content, options: this.config }))
17
+ }
18
+
19
+ get config () {
20
+ return {
21
+ showTitle: false,
22
+ showIIIFBadge: false,
23
+ informationPanel: {
24
+ renderToggle: false,
25
+ renderAbout: false
26
+ }
27
+ }
28
+ }
29
+ }
@@ -0,0 +1,28 @@
1
+ // To see this message, add the following to the `<head>` section in your
2
+ // views/layouts/application.html.erb
3
+ //
4
+ // <%= vite_client_tag %>
5
+ // <%= vite_javascript_tag 'application' %>
6
+ console.log('Vite ⚡️ Rails - Engine')
7
+
8
+ // If using a TypeScript entrypoint file:
9
+ // <%= vite_typescript_tag 'application' %>
10
+ //
11
+ // If you want to use .jsx or .tsx, add the extension:
12
+ // <%= vite_javascript_tag 'application.jsx' %>
13
+
14
+ console.log('Visit the guide for more information: ', 'https://vite-ruby.netlify.app/guide/rails')
15
+
16
+ // Example: Load Rails libraries in Vite.
17
+ //
18
+ // import * as Turbo from '@hotwired/turbo'
19
+ // Turbo.start()
20
+ //
21
+ // import ActiveStorage from '@rails/activestorage'
22
+ // ActiveStorage.start()
23
+ //
24
+ // // Import all channels.
25
+ // const channels = import.meta.globEager('./**/*_channel.js')
26
+
27
+ // Example: Import a stylesheet in app/frontend/index.css
28
+ // import '~/index.css'
@@ -0,0 +1,5 @@
1
+ import CloverInitializer from '@/clover/clover_initializer'
2
+
3
+ document.addEventListener('DOMContentLoaded', () => {
4
+ new CloverInitializer().run()
5
+ })
@@ -0,0 +1,5 @@
1
+ import OlInitializer from '@/openlayers/ol_initializer'
2
+
3
+ document.addEventListener('DOMContentLoaded', () => {
4
+ new OlInitializer().run()
5
+ })
@@ -0,0 +1,47 @@
1
+ export const openLayersBasemaps = {
2
+ darkMatter: {
3
+ url:'https://{a-d}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png',
4
+ attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, &copy; <a href="http://carto.com/attributions">Carto</a>',
5
+ maxZoom: 18
6
+ },
7
+ positron: {
8
+ url: 'https://{a-d}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png',
9
+ attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, &copy; <a href="http://carto.com/attributions">Carto</a>',
10
+ maxZoom: 18
11
+ },
12
+ positronLite: {
13
+ url: 'https://{a-d}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}.png',
14
+ attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, &copy; <a href="http://carto.com/attributions">Carto</a>',
15
+ maxZoom: 18
16
+ },
17
+ worldAntique: {
18
+ url: 'https://cartocdn_{a-d}.global.ssl.fastly.net/base-antique/{z}/{x}/{y}.png',
19
+ attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, &copy; <a href="http://carto.com/attributions">Carto</a>',
20
+ maxZoom: 18
21
+ },
22
+ worldEco: {
23
+ url: 'https://cartocdn_{a-d}.global.ssl.fastly.net/base-eco/{z}/{x}/{y}.png',
24
+ attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, &copy; <a href="http://carto.com/attributions">Carto</a>',
25
+ maxZoom: 18
26
+ },
27
+ flatBlue: {
28
+ url: 'https://cartocdn_{a-d}.global.ssl.fastly.net/base-flatblue/{z}/{x}/{y}.png',
29
+ attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, &copy; <a href="http://carto.com/attributions">Carto</a>',
30
+ maxZoom: 18
31
+ },
32
+ midnightCommander: {
33
+ url: 'https://cartocdn_{a-d}.global.ssl.fastly.net/base-midnight/{z}/{x}/{y}.png',
34
+ attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, &copy; <a href="http://carto.com/attributions">Carto</a>',
35
+ maxZoom: 18
36
+ },
37
+ openstreetmapHot: {
38
+ url: 'https://{a-c}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png',
39
+ attribution: '&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>',
40
+ maxZoom: 19
41
+ },
42
+ openstreetmapStandard: {
43
+ url: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
44
+ attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
45
+ maxZoom: 19
46
+ }
47
+ }
@@ -0,0 +1,105 @@
1
+ import '../stylesheets/openlayers.css'
2
+ import { Map, View } from 'ol'
3
+ import TileLayer from 'ol/layer/Tile'
4
+ import VectorTile from 'ol/layer/VectorTile'
5
+ import XYZ from 'ol/source/XYZ'
6
+ import GeoJSON from 'ol/format/GeoJSON'
7
+ import { useGeographic } from 'ol/proj'
8
+ import {
9
+ Style, Stroke, Fill, Circle
10
+ } from 'ol/style'
11
+ import GeoTIFF from 'ol/source/GeoTIFF'
12
+ import WebGLTileLayer from 'ol/layer/WebGLTile'
13
+ import { FullScreen, defaults as defaultControls } from 'ol/control'
14
+ import { PMTilesVectorSource } from 'ol-pmtiles'
15
+ import { openLayersBasemaps } from './basemaps'
16
+
17
+ export default class OlInitializer {
18
+ constructor () {
19
+ this.element = document.getElementById('ol-map')
20
+ if (this.element) {
21
+ this.data = this.element.dataset
22
+ this.extent = new GeoJSON().readFeatures(this.data.mapGeom)[0].getGeometry().getExtent()
23
+ }
24
+ }
25
+
26
+ run () {
27
+ if (!this.element) return false
28
+ if (this.data.protocol === 'Pmtiles') {
29
+ this.initializePmtiles()
30
+ } else if (this.data.protocol === 'Cog') {
31
+ this.initializeCog()
32
+ }
33
+ }
34
+
35
+ baseLayer () {
36
+ const basemap = openLayersBasemaps[this.data.basemap]
37
+ const layer = new TileLayer({
38
+ source: new XYZ({
39
+ attributions: basemap["attribution"],
40
+ url: basemap["url"],
41
+ maxZoom: basemap["maxZoom"]
42
+ })
43
+ })
44
+ return layer
45
+ }
46
+
47
+ initializePmtiles () {
48
+ const vectorLayer = new VectorTile({
49
+ declutter: true,
50
+ source: new PMTilesVectorSource({
51
+ url: this.data.url
52
+ }),
53
+ style: new Style({
54
+ stroke: new Stroke({
55
+ color: '#7070B3',
56
+ width: 1
57
+ }),
58
+ fill: new Fill({
59
+ color: '#FFFFFF'
60
+ }),
61
+ image: new Circle({
62
+ radius: 7,
63
+ fill: new Fill({
64
+ color: '#7070B3'
65
+ }),
66
+ stroke: new Stroke({
67
+ color: '#FFFFFF',
68
+ width: 2
69
+ })
70
+ })
71
+ })
72
+ })
73
+
74
+ useGeographic()
75
+ const map = new Map({
76
+ controls: defaultControls().extend([new FullScreen()]),
77
+ layers: [this.baseLayer(), vectorLayer],
78
+ target: 'ol-map'
79
+ })
80
+ map.getView().fit(this.extent, map.getSize())
81
+ }
82
+
83
+ initializeCog () {
84
+ const source = new GeoTIFF({
85
+ sources: [{ url: this.data.url }]
86
+ })
87
+
88
+ source.getView().then((view) => {
89
+ const map = new Map({
90
+ controls: defaultControls().extend([new FullScreen()]),
91
+ target: 'ol-map',
92
+ layers: [
93
+ this.baseLayer(),
94
+ new WebGLTileLayer({
95
+ source
96
+ })
97
+ ],
98
+ view: new View({
99
+ center: view.center
100
+ })
101
+ })
102
+ map.getView().fit(view.extent, map.getSize())
103
+ })
104
+ }
105
+ }
@@ -0,0 +1 @@
1
+ @import "../../../node_modules/ol/ol.css";
@@ -245,4 +245,58 @@ module GeoblacklightHelper
245
245
  "index"
246
246
  end
247
247
  end
248
+
249
+ def viewer_container
250
+ if openlayers_container?
251
+ ol_viewer
252
+ elsif iiif_manifest_container?
253
+ iiif_manifest_viewer
254
+ else
255
+ leaflet_viewer
256
+ end
257
+ end
258
+
259
+ def openlayers_container?
260
+ return false unless @document
261
+ @document.item_viewer.pmtiles || @document.item_viewer.cog
262
+ end
263
+
264
+ def leaflet_viewer
265
+ tag.div(nil,
266
+ id: "map",
267
+ data: {
268
+ :map => "item", :protocol => @document.viewer_protocol.camelize,
269
+ :url => @document.viewer_endpoint,
270
+ "layer-id" => @document.wxs_identifier,
271
+ "map-geom" => @document.geometry.geojson,
272
+ "catalog-path" => search_catalog_path,
273
+ :available => document_available?,
274
+ :basemap => geoblacklight_basemap,
275
+ :leaflet_options => leaflet_options
276
+ })
277
+ end
278
+
279
+ def ol_viewer
280
+ tag.div(nil,
281
+ id: "ol-map",
282
+ data: {
283
+ :map => "item", :protocol => @document.viewer_protocol.camelize,
284
+ :url => @document.viewer_endpoint,
285
+ "layer-id" => @document.wxs_identifier,
286
+ "map-geom" => @document.geometry.geojson,
287
+ "catalog-path" => search_catalog_path,
288
+ :available => document_available?,
289
+ :basemap => geoblacklight_basemap,
290
+ :leaflet_options => leaflet_options
291
+ })
292
+ end
293
+
294
+ def iiif_manifest_container?
295
+ return false unless @document
296
+ @document&.item_viewer&.viewer_preference&.key?(:iiif_manifest)
297
+ end
298
+
299
+ def iiif_manifest_viewer
300
+ tag.div(nil, id: "clover-viewer", iiif_content: @document.viewer_endpoint)
301
+ end
248
302
  end
@@ -7,7 +7,7 @@
7
7
  </div>
8
8
  <div class="modal-body" data-clipboard-target="source">
9
9
  <div class="alert alert-info d-none" role="alert">
10
- Citation copied to clipboard
10
+ <%= t('geoblacklight.clipboard.citation') %>
11
11
  <button type="button" class="close" data-dismiss="alert" aria-label="Close">
12
12
  <span aria-hidden="true">&times;</span>
13
13
  </button>
@@ -23,7 +23,6 @@
23
23
  </div>
24
24
  <% end %>
25
25
 
26
- <%= content_tag :div, id: 'map', aria: { label: t('geoblacklight.map.label') }, data: { map: 'item', protocol: document.viewer_protocol.camelize, url: document.viewer_endpoint, 'layer-id' => document.wxs_identifier, 'map-geom' => document.geometry.geojson, 'catalog-path'=> search_catalog_path, available: document_available?, inspect: show_attribute_table?, basemap: geoblacklight_basemap, leaflet_options: leaflet_options } do %>
27
- <% end %>
26
+ <%= viewer_container %>
28
27
  </div>
29
28
  </div>
@@ -4,5 +4,10 @@
4
4
  <label for='<%= reference.type%>_webservice'>
5
5
  <%= "#{formatted_name_reference(reference.type)}" %>
6
6
  </label>
7
- <input type='text' id='<%= reference.type%>_webservice' value='<%= reference.endpoint %>' readonly='readonly' class='form-control'>
7
+ <div class='input-group'>
8
+ <input type='text' id='<%= reference.type%>_webservice' value='<%= reference.endpoint %>' readonly='readonly' class='form-control'>
9
+ <div class="input-group-append">
10
+ <button button type="button" class="btn btn-primary" data-action="copyToClipboard" data-clipboard-value='<%= reference.endpoint %>'><%= t('blacklight.modal.copy') %></button>
11
+ </div>
12
+ </div>
8
13
  </div>
@@ -4,5 +4,10 @@
4
4
 
5
5
  <div class="form-group form-inline">
6
6
  <label for="wfs_abv_webservice" class="mr-2"><%= t('geoblacklight.references.wfs_abv')%> <code><%= t('geoblacklight.references.wfs_label')%></code></label>
7
- <input id="wfs_abv_webservice" type='text' value='<%= document.wxs_identifier %>' readonly='readonly' class="form-control">
7
+ <div class='input-group'>
8
+ <input id="wfs_abv_webservice" type='text' value='<%= document.wxs_identifier %>' readonly='readonly' class="form-control">
9
+ <div class="input-group-append">
10
+ <button button type="button" class="btn btn-primary" data-action="copyToClipboard" data-clipboard-value='<%= document.wxs_identifier %>'><%= t('blacklight.modal.copy') %></button>
11
+ </div>
12
+ </div>
8
13
  </div>
@@ -4,5 +4,10 @@
4
4
 
5
5
  <div class="form-group form-inline">
6
6
  <label for="wms_abv_webservice" class="mr-2"><%= t('geoblacklight.references.wms_abv')%> <code><%= t('geoblacklight.references.wms_label')%></code></label>
7
- <input id="wms_abv_webservice" type='text' value='<%= document.wxs_identifier %>' readonly='readonly' class="form-control">
7
+ <div class='input-group'>
8
+ <input id="wms_abv_webservice" type='text' value='<%= document.wxs_identifier %>' readonly='readonly' class="form-control" data-action="copyToClipboard" data-clipboard-value='<%= document.wxs_identifier %>'>
9
+ <div class="input-group-append">
10
+ <button button type="button" class="btn btn-primary" data-action="copyToClipboard" data-clipboard-value='<%= document.wxs_identifier %>'><%= t('blacklight.modal.copy') %></button>
11
+ </div>
12
+ </div>
8
13
  </div>
@@ -5,8 +5,24 @@
5
5
  </button>
6
6
  </div>
7
7
  <div class="modal-body web-services-modal-body">
8
+ <div class="alert alert-info d-none" role="alert">
9
+ <%= t('geoblacklight.clipboard.web_service') %>
10
+ <button type="button" class="close" data-dismiss="alert" aria-label="Close">
11
+ <span aria-hidden="true">&times;</span>
12
+ </button>
13
+ </div>
8
14
  <%= render partial: 'web_services' %>
9
15
  </div>
10
16
  <div class="modal-footer">
11
17
  <button type="button" class="btn btn-default hide-without-js" data-dismiss="modal"><%= t('geoblacklight.references.services_close')%></button>
12
18
  </div>
19
+
20
+ <script>
21
+ $('[data-action="copyToClipboard"]').on('click', function() {
22
+ let text = $(this).data('clipboard-value');
23
+ navigator.clipboard.writeText(text)
24
+ .then(() => {
25
+ $('.alert').removeClass('d-none');
26
+ })
27
+ });
28
+ </script>
data/bin/vite ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'vite' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("vite_ruby", "vite")
@@ -4,6 +4,9 @@ en:
4
4
  location: 'Location'
5
5
  citation:
6
6
  retrieved_from: 'Retrieved from %{document_url}'
7
+ clipboard:
8
+ citation: Citation copied to clipboard
9
+ web_service: Web service copied to clipboard
7
10
  download:
8
11
  download: 'Download'
9
12
  download_link: 'Original %{download_format}'
@@ -14,8 +17,7 @@ en:
14
17
  hgl_close: 'Close'
15
18
  hgl_instructions: 'Please enter your email address. You will receive a link to download the layer when it is ready.' ## new variable
16
19
  hgl_email: 'Email'
17
- error: 'Sorry, the requested file could not be downloaded'
18
- error_with_url: 'Sorry, the requested file could not be downloaded. Try downloading it directly from: %{link}'
20
+ error: 'Sorry, the requested file could not be downloaded.'
19
21
  export_formats: 'Export Formats'
20
22
  export_link: 'Export %{download_format}'
21
23
  export_shapefile_link: 'Shapefile'
@@ -70,6 +72,8 @@ en:
70
72
  tilejson: 'TileJSON Document'
71
73
  xyz: 'XYZ Tiles'
72
74
  wmts: 'Web Map Tile Service'
75
+ pmtiles: 'PMTiles Layer'
76
+ cog: 'COG Layer'
73
77
  relations:
74
78
  member_of_ancestors: 'Belongs to collection...'
75
79
  member_of_descendants: 'Collection records...'
@@ -98,6 +102,9 @@ en:
98
102
  click_map: 'Click on map to inspect values'
99
103
  help_text:
100
104
  viewer_protocol:
105
+ cog:
106
+ title: COG Layer
107
+ content: A Cloud Optimized GeoTIFF
101
108
  dynamic_map_layer:
102
109
  title: ArcGIS Dynamic Map Layer
103
110
  content: An ArcGIS Dynamic Map Layer represents vector data (points, lines, and polygons). Map image layers are dynamically rendered image tiles.
@@ -119,6 +126,9 @@ en:
119
126
  oembed:
120
127
  title: Embedded Content
121
128
  content: This content is embedded through a third-party viewer.
129
+ pmtiles:
130
+ title: PMTiles Layer
131
+ content: A PMTiles layer is a single-file archive format for tiled data.
122
132
  tiled_map_layer:
123
133
  title: ArcGIS Tiled Map Layer
124
134
  content: An ArcGIS Tiled Map Layer Service displays set of web-accessible tiles that reside on a server.
data/config/vite.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "all": {
3
+ "sourceCodeDir": "app/frontend",
4
+ "publicOutputDir": "geoblacklight-vite",
5
+ "watchAdditionalPaths": []
6
+ },
7
+ "development": {
8
+ "autoBuild": true,
9
+ "port": 3037
10
+ },
11
+ "test": {
12
+ "autoBuild": true
13
+ }
14
+ }
@@ -17,16 +17,18 @@ Gem::Specification.new do |spec|
17
17
  spec.require_paths = ["lib"]
18
18
  spec.required_rubygems_version = ">= 2.5.2"
19
19
 
20
- spec.add_dependency "rails", ">= 6.1", "< 7.1"
21
- spec.add_dependency "blacklight", ">= 7.0", "<= 7.33"
20
+ spec.add_dependency "rails", ">= 6.1", "< 7.2"
21
+ spec.add_dependency "blacklight", "~> 7.0"
22
22
  spec.add_dependency "config"
23
- spec.add_dependency "faraday", ">= 1.0"
23
+ spec.add_dependency "faraday", "~> 2.0"
24
24
  spec.add_dependency "coderay"
25
25
  spec.add_dependency "deprecation"
26
- spec.add_dependency "geo_combine", "~> 0.8"
26
+ spec.add_dependency "geo_combine", "~> 0.9"
27
27
  spec.add_dependency "mime-types"
28
28
  spec.add_dependency "handlebars_assets"
29
29
  spec.add_dependency "rgeo-geojson"
30
+ spec.add_dependency "sprockets-rails", "~> 3.0"
31
+ spec.add_dependency "vite_rails", "~> 3.0"
30
32
 
31
33
  spec.add_development_dependency "solr_wrapper"
32
34
  spec.add_development_dependency "rails-controller-testing"
@@ -35,8 +37,8 @@ Gem::Specification.new do |spec|
35
37
  spec.add_development_dependency "capybara", ">= 2.5.0"
36
38
  spec.add_development_dependency "webdrivers"
37
39
  spec.add_development_dependency "factory_bot_rails"
38
- spec.add_development_dependency "database_cleaner", "~> 1.3"
39
- spec.add_development_dependency "simplecov", "~> 0.17.1"
40
+ spec.add_development_dependency "database_cleaner", "~> 2.0"
41
+ spec.add_development_dependency "simplecov", "~> 0.22"
40
42
  spec.add_development_dependency "foreman"
41
43
  spec.add_development_dependency "standardrb", "1.0.1"
42
44
  spec.add_development_dependency "webmock", "~> 3.14"