geoblacklight 5.1.0 → 5.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +15 -0
  3. data/.github/workflows/ruby.yml +13 -8
  4. data/app/assets/stylesheets/geoblacklight/modules/item.scss +20 -3
  5. data/app/components/geoblacklight/accordion_component.html.erb +16 -0
  6. data/app/components/geoblacklight/accordion_component.rb +11 -0
  7. data/app/components/geoblacklight/attribute_table_component.html.erb +15 -17
  8. data/app/components/geoblacklight/index_map_inspect_component.html.erb +4 -3
  9. data/app/controllers/relation_controller.rb +1 -1
  10. data/app/javascript/geoblacklight/controllers/downloads_controller.js +2 -2
  11. data/app/javascript/geoblacklight/controllers/leaflet_viewer_controller.js +17 -3
  12. data/app/javascript/geoblacklight/leaflet/controls/sidebar.js +47 -0
  13. data/config/importmap.rb +4 -10
  14. data/config/locales/geoblacklight.en.yml +1 -0
  15. data/lib/generators/geoblacklight/assets/importmap_generator.rb +11 -20
  16. data/lib/generators/geoblacklight/assets/vite_generator.rb +15 -18
  17. data/lib/generators/geoblacklight/assets_generator.rb +17 -2
  18. data/lib/generators/geoblacklight/templates/assets/application.scss +1 -1
  19. data/lib/generators/geoblacklight/templates/settings.yml +2 -1
  20. data/lib/geoblacklight/download/geojson_download.rb +1 -1
  21. data/lib/geoblacklight/engine.rb +1 -1
  22. data/lib/geoblacklight/version.rb +1 -1
  23. data/lib/tasks/geoblacklight.rake +15 -23
  24. data/package.json +7 -10
  25. data/schema/geoblacklight-schema-aardvark.json +2 -2
  26. data/solr/conf/solrconfig.xml +1 -1
  27. data/spec/features/full_screen_control_spec.rb +4 -6
  28. data/spec/features/saved_searches_spec.rb +1 -8
  29. data/spec/lib/geoblacklight/download/geojson_download_spec.rb +1 -0
  30. data/template.rb +7 -20
  31. data/vite.config.ts +0 -3
  32. metadata +7 -12
  33. data/.github/workflows/build-demo-app.yml +0 -156
  34. data/.github/workflows/prune-containers.yml +0 -19
  35. data/lib/generators/geoblacklight/templates/demo-app/Dockerfile +0 -31
  36. data/lib/generators/geoblacklight/templates/demo-app/compose.yml +0 -26
  37. data/lib/generators/geoblacklight/templates/demo-app/start-server.sh +0 -21
  38. data/test/leaflet/layers.test.js +0 -17
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c3a533a2028cc4a5d4edc6aba0c532812d5266ce7e94fc290208f0ea26216056
4
- data.tar.gz: 4644a2f7c1cae18643207a99c2d7cdbde53a1b27c521a6a94a1e1ff6a7c37e15
3
+ metadata.gz: 2f9e80f30735f8fa8f8e4c03e0a855b4e709acbf1eb860cad0a14e66dba72064
4
+ data.tar.gz: 824c5c71fb501807335ab0862522d5a14fec06f31b1f21b09d732338f27e5b89
5
5
  SHA512:
6
- metadata.gz: 404ed2e84916e9505a22e08979e569b301fb1dbf620d72d1c015e0f49f106183bbc2757d649a7ab3392fe9bec8cdefbe735d0a3ec9ea8b96909b4e5b10267bd2
7
- data.tar.gz: 82e33f34850832707b5259c9f356ca5858446474b44672357f05495b517c4bbdd539ff330c557ac143422baf0c7377c4e0ca6dc758be73cce8a7d4b939c2be72
6
+ metadata.gz: acbee7539ae6c048356e42467b99f4e94c948cc9d5a35ddeeccc721028965808267d33d3d3ce91fc05afdd5992fbee5edeeda1760aa6257dea6420bc83e194ce
7
+ data.tar.gz: 8395fe82750ac0bfe3dc3de410a7039d0eff671ffee63690f1a0858b88687dc163ed92a711a46a94caf956eb3cdd5b04f7c96cb5a7cf2aedbaec9d74a2136412
@@ -0,0 +1,15 @@
1
+ # To get started with Dependabot version updates, you'll need to specify which
2
+ # package ecosystems to update and where the package manifests are located.
3
+ # Please see the documentation for all configuration options:
4
+ # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
5
+
6
+ version: 2
7
+ updates:
8
+ - package-ecosystem: "github-actions"
9
+ directory: "/"
10
+ schedule:
11
+ interval: "weekly"
12
+ - package-ecosystem: "npm"
13
+ directory: "/"
14
+ schedule:
15
+ interval: "weekly"
@@ -10,7 +10,7 @@ jobs:
10
10
  linter:
11
11
  runs-on: ubuntu-latest
12
12
  steps:
13
- - uses: actions/checkout@v4
13
+ - uses: actions/checkout@v6
14
14
  - name: Set up Ruby
15
15
  uses: ruby/setup-ruby@v1
16
16
  with:
@@ -23,7 +23,7 @@ jobs:
23
23
  aardvark-fixture-linter:
24
24
  runs-on: ubuntu-latest
25
25
  steps:
26
- - uses: actions/checkout@v4
26
+ - uses: actions/checkout@v6
27
27
  - name: Set up Ruby
28
28
  uses: ruby/setup-ruby@v1
29
29
  with:
@@ -38,13 +38,18 @@ jobs:
38
38
  strategy:
39
39
  matrix:
40
40
  ruby_version: ["3.2", "3.3", "3.4"]
41
- rails_version: ["7.1.5.1", "7.2.2.1", "8.0.1"]
42
- asset_pipeline: ["vite"]
43
- additional_engine_cart_rails_options: ["--js rollup"]
41
+ rails_version: ["7.2.3", "8.1.1"]
42
+ asset_pipeline: ["importmap"]
43
+ additional_engine_cart_rails_options: ["--js importmap"]
44
+ include:
45
+ - ruby_version: "3.4"
46
+ rails_version: "8.1.1"
47
+ asset_pipeline: "vite"
48
+ additional_engine_cart_rails_options: "--js rollup"
44
49
 
45
50
  name: test ruby ${{ matrix.ruby_version }} / rails ${{ matrix.rails_version }} / ${{ matrix.asset_pipeline }}
46
51
  steps:
47
- - uses: actions/checkout@v4
52
+ - uses: actions/checkout@v6
48
53
  - name: Set up Ruby
49
54
  uses: ruby/setup-ruby@v1
50
55
  with:
@@ -67,8 +72,8 @@ jobs:
67
72
  ENGINE_CART_RAILS_OPTIONS: "--skip-docker --skip-action-cable --skip-rubocop --skip-brakeman --skip-kamal --skip-solid -a propshaft --css bootstrap ${{ matrix.additional_engine_cart_rails_options }}"
68
73
  SOLR_URL: http://solr:SolrRocks@localhost:8983/solr/blacklight-core
69
74
  - name: Upload coverage artifacts
70
- uses: actions/upload-artifact@v4
71
- if: always()
75
+ uses: actions/upload-artifact@v6
76
+ if: matrix.asset_pipeline == 'vite'
72
77
  with:
73
78
  name: "coverage-${{ matrix.ruby_version }}-${{ matrix.rails_version }}"
74
79
  path: coverage/
@@ -49,13 +49,30 @@
49
49
  -webkit-line-clamp: 8;
50
50
  }
51
51
 
52
- #table-container{
53
- overflow:scroll;
54
- max-height: 450px;
52
+ #table-container {
55
53
  margin-bottom: 1rem;
56
54
 
57
55
  table {
58
56
  margin-bottom: 0px;
59
57
  }
60
58
  }
59
+
60
+ .attribute-data {
61
+ --bs-accordion-active-bg: none;
62
+ }
63
+
64
+ .sidebar-container {
65
+ width: 25vw;
66
+ overflow: scroll;
67
+ overscroll-behavior: contain;
68
+
69
+ img {
70
+ width: 100%;
71
+ }
72
+
73
+ @media screen and (max-width: breakpoint-max(sm)) {
74
+ width: calc(100vw - 100px);
75
+ max-height: 20vh!important;
76
+ }
77
+ }
61
78
  }
@@ -0,0 +1,16 @@
1
+ <div data-sidebar="<%= Settings.LEAFLET.SIDEBAR %>">
2
+ <div class="accordion attribute-data<% if Settings.LEAFLET.SIDEBAR %> sidebar-container<% end %>">
3
+ <div class="accordion-item">
4
+ <h2 class="accordion-header" id="accordionHeading">
5
+ <button class="accordion-button p-2 border-none bg-none" type="button" data-bs-toggle="collapse" data-bs-target="#<%= @id %>" aria-expanded="true" aria-controls="<%= @id %>">
6
+ <%= @title %>
7
+ </button>
8
+ </h2>
9
+ <div id="<%= @id %>" class="accordion-collapse collapse show" aria-labelledby="accordionHeading" data-bs-parent="#accordionHeading">
10
+ <div class="accordion-body p-0">
11
+ <%= content %>
12
+ </div>
13
+ </div>
14
+ </div>
15
+ </div>
16
+ </div>
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Geoblacklight
4
+ class AccordionComponent < ViewComponent::Base
5
+ def initialize(id:, title:)
6
+ @id = id
7
+ @title = title
8
+ super()
9
+ end
10
+ end
11
+ end
@@ -1,17 +1,15 @@
1
- <div class='row'>
2
- <div id='table-container' class='col-md-12'>
3
- <table id="attribute-table" class="table table-hover table-condensed table-striped table-bordered col-md-12">
4
- <thead>
5
- <tr>
6
- <th><%= t('geoblacklight.show.attribute') %></th>
7
- <th><%= t('geoblacklight.show.value') %></th>
8
- </tr>
9
- </thead>
10
- <tbody class='attribute-table-body'>
11
- <tr>
12
- <td class='default-text' colspan='2'><em><%= t('geoblacklight.show.click_map') %></em></td>
13
- </tr>
14
- </tbody>
15
- </table>
16
- </div>
17
- </div>
1
+ <%= render Geoblacklight::AccordionComponent.new(id: 'attribute-table', title: t('geoblacklight.show.table_name')) do %>
2
+ <table id="attribute-table" class="table table-hover table-condensed table-striped mb-0 collapse show">
3
+ <thead>
4
+ <tr>
5
+ <th><%= t('geoblacklight.show.attribute') %></th>
6
+ <th><%= t('geoblacklight.show.value') %></th>
7
+ </tr>
8
+ </thead>
9
+ <tbody class='attribute-table-body'>
10
+ <tr>
11
+ <td class='default-text' colspan='2'><em><%= t('geoblacklight.show.click_map') %></em></td>
12
+ </tr>
13
+ </tbody>
14
+ </table>
15
+ <% end %>
@@ -1,4 +1,5 @@
1
- <div class='row'>
2
- <div class='viewer-information col-sm-12'>
1
+ <%= render Geoblacklight::AccordionComponent.new(id: 'index-map-attributes', title: t('geoblacklight.show.table_name')) do %>
2
+ <div class='viewer-information px-3'>
3
+ <em><%= t('geoblacklight.show.click_map') %></em>
3
4
  </div>
4
- </div>
5
+ <% end %>
@@ -2,7 +2,7 @@
2
2
 
3
3
  class RelationController < ApplicationController
4
4
  include Blacklight::Configurable
5
- # include Blacklight::SearchHelper
5
+
6
6
  copy_blacklight_config_from(CatalogController)
7
7
 
8
8
  def index
@@ -48,8 +48,8 @@ export default class extends Controller {
48
48
  renderMessage(message) {
49
49
  Object.entries(message).forEach(([idx, msg]) => {
50
50
  const flash = document.createElement("div");
51
- flash.className = `alert alert-${msg[0]}`;
52
- flash.innerHTML = `<button type="button" class="close" data-bs-dismiss="alert" aria-hidden="true">&times;</button>${msg[1]}`;
51
+ flash.className = `alert alert-${msg[0]} alert-dismissible fade show`;
52
+ flash.innerHTML = `${msg[1]}<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>`;
53
53
  document.querySelector("div.flash_messages").appendChild(flash);
54
54
  });
55
55
  }
@@ -1,5 +1,5 @@
1
1
  import { Icon, Control } from "leaflet";
2
- import "leaflet-fullscreen";
2
+ import { FullScreen } from "leaflet.fullscreen";
3
3
  import { layerGroup, polygon, map, tileLayer } from "leaflet";
4
4
  import { imageMapLayer } from "esri-leaflet";
5
5
  import { Controller } from "@hotwired/stimulus";
@@ -23,6 +23,7 @@ import {
23
23
  } from "geoblacklight/leaflet/layers";
24
24
  import { geoJSONToBounds } from "geoblacklight/leaflet/utils";
25
25
  import { DEFAULT_BOUNDS, DEFAULT_OPACITY, DEFAULT_GEOM_OVERLAY_OPTIONS } from "geoblacklight/leaflet/constants";
26
+ import sidebarControl from "geoblacklight/leaflet/controls/sidebar";
26
27
 
27
28
  export default class LeafletViewerController extends Controller {
28
29
  static values = {
@@ -146,7 +147,7 @@ export default class LeafletViewerController extends Controller {
146
147
  if (controlName == "Opacity")
147
148
  return new LayerOpacityControl(this.previewOverlay);
148
149
  if (controlName == "Fullscreen")
149
- return new Control.Fullscreen({ position: "topright", ...controlOptions });
150
+ return new FullScreen({ position: "bottomleft", ...controlOptions });
150
151
  if (controlName == "Geosearch")
151
152
  return new GeoSearchControl({ baseUrl: this.catalogBaseUrlValue, ...controlOptions });
152
153
  console.error(`Unsupported control name: "${controlName}"`);
@@ -179,10 +180,23 @@ export default class LeafletViewerController extends Controller {
179
180
  if (this.boundsOverlay) this.overlay.removeLayer(this.boundsOverlay);
180
181
  }
181
182
 
183
+ setUpSidebar() {
184
+ const sidebar = document.querySelector('[data-sidebar]')
185
+ if (!sidebar || sidebar.dataset.sidebar != 'true') return;
186
+ const control = new sidebarControl({
187
+ position: 'topright',
188
+ sidebar
189
+ });
190
+ this.map.addControl(control);
191
+ }
192
+
182
193
  addInspection() {
194
+ const inspectionProtocols = ['Wms', 'FeatureLayer', 'DynamicMapLayer', 'IndexMap']
195
+ if (!inspectionProtocols.includes(this.protocolValue)) return;
196
+ this.setUpSidebar();
183
197
  if (this.protocolValue == "Wms") return wmsInspection(this.map, this.urlValue, this.layerIdValue, this.previewOverlay);
184
198
  if (this.protocolValue == "FeatureLayer") return featureLayerInspection(this.map, this.previewOverlay);
185
- if (this.protocolValue == "DynamicMapLayer") return dynamicMapLayerInspection(this.map, this.previewOverlay, this.layerIdValue)
199
+ if (this.protocolValue == "DynamicMapLayer") return dynamicMapLayerInspection(this.map, this.previewOverlay, this.layerIdValue);
186
200
  // TODO: TiledMapLayer is converted but seems busted -- see layers.js. Don't know what to test it with, need a fixture.
187
201
  // if (this.protocolValue == "TiledMapLayer") return tiledMapLayerInspection(this.map, this.previewOverlay);
188
202
  }
@@ -0,0 +1,47 @@
1
+ import { Control } from "leaflet";
2
+
3
+ export default class sidebarControl extends Control {
4
+ constructor(options) {
5
+ const _options = { ...options };
6
+ super(_options);
7
+ }
8
+
9
+ onAdd(map) {
10
+ var div = L.DomUtil.create('div', 'leaflet-sidebar');
11
+ div.setAttribute("tabindex", "0");
12
+ const sidebarContainer = this.options.sidebar;
13
+
14
+ // Disable zoom when the mouse enters the sidebar
15
+ div.addEventListener('mouseenter', function() {
16
+ map.scrollWheelZoom.disable();
17
+ });
18
+
19
+ div.addEventListener('touchstart', function() {
20
+ map.touchZoom.disable();
21
+ map.dragging.disable();
22
+ });
23
+
24
+ // without this the map will try to find data about whatever is behind the sidebar
25
+ div.addEventListener('click', function(event) {
26
+ event.stopPropagation();
27
+ });
28
+
29
+ // Enable zoom when the mouse leaves the sidebar
30
+ div.addEventListener('touchend', function() {
31
+ map.touchZoom.enable();
32
+ map.dragging.enable();
33
+ });
34
+
35
+ // Enable zoom when the mouse leaes the sidebar
36
+ div.addEventListener('mouseleave', function() {
37
+ map.scrollWheelZoom.enable();
38
+ });
39
+
40
+ if (!sidebarContainer) { return };
41
+ // Make sure table height is same as map (with a little padding)
42
+ sidebarContainer.children[0].style.maxHeight = `${map._container.offsetHeight - 30}px`;
43
+ div.innerHTML = sidebarContainer.innerHTML;
44
+ sidebarContainer.remove();
45
+ return div;
46
+ }
47
+ }
data/config/importmap.rb CHANGED
@@ -3,18 +3,12 @@
3
3
  # OpenLayers viewer
4
4
  pin "ol", to: "https://esm.sh/ol@8.1.0"
5
5
  pin "ol/", to: "https://esm.sh/ol@8.1.0/"
6
- pin "ol-pmtiles", to: "https://cdn.skypack.dev/ol-pmtiles@0.3.0"
6
+ pin "ol-pmtiles", to: "https://cdn.jsdelivr.net/npm/ol-pmtiles@0.3.0/+esm"
7
7
 
8
8
  # Leaflet viewer
9
- pin "leaflet", to: "https://cdn.skypack.dev/leaflet@1.9.4"
10
- pin "esri-leaflet", to: "https://cdn.skypack.dev/esri-leaflet@3.0.12"
11
- pin "leaflet-fullscreen", to: "https://cdn.skypack.dev/leaflet-fullscreen@1.0.2"
12
-
13
- # Clover viewer
14
- pin "react", to: "https://esm.sh/react@18.3.1"
15
- pin "react-dom/client", to: "https://esm.sh/react-dom@18.3.1/client"
16
- pin "@samvera/clover-iiif/viewer", to: "https://esm.sh/@samvera/clover-iiif@2.10.0/dist/viewer"
17
- pin "@samvera/clover-iiif/image", to: "https://esm.sh/@samvera/clover-iiif@2.10.0/dist/image"
9
+ pin "leaflet", to: "https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet-src.esm.js"
10
+ pin "esri-leaflet", to: "https://cdn.jsdelivr.net/npm/esri-leaflet@3.0.19/+esm"
11
+ pin "leaflet.fullscreen", to: "https://cdn.jsdelivr.net/npm/leaflet.fullscreen@5.3.0/+esm"
18
12
 
19
13
  # Geoblacklight
20
14
  pin_all_from Geoblacklight::Engine.root.join("app", "javascript", "geoblacklight"), under: "geoblacklight"
@@ -93,6 +93,7 @@ en:
93
93
  attribute: 'Attribute'
94
94
  value: 'Value'
95
95
  click_map: 'Click on map to inspect values'
96
+ table_name: 'Map data'
96
97
  help_text:
97
98
  viewer_protocol:
98
99
  cog:
@@ -21,17 +21,19 @@ module Geoblacklight
21
21
  delivered via CDN.
22
22
  DESCRIPTION
23
23
 
24
- # If this is a local dev/test build, symlink the frontend package so we
25
- # can reference its stylesheets in development
26
- def link_frontend
27
- run "yarn link @geoblacklight/frontend" if options[:test]
24
+ # Switch Blacklight's bootstrap and popper imports to ESM versions so we
25
+ # can import individual modules
26
+ def use_bootstrap_esm
27
+ gsub_file "config/importmap.rb", %r{dist/js/bootstrap.js}, "dist/js/bootstrap.esm.js"
28
+ gsub_file "config/importmap.rb", %r{dist/umd/popper.min.js}, "dist/esm/popper.js"
28
29
  end
29
30
 
30
- # Add the customization overrides and insert before bootstrap import
31
+ # Add the SCSS customization overrides and insert before bootstrap import
31
32
  def add_customizations
32
33
  copy_file "assets/_customizations.scss", "app/assets/stylesheets/_customizations.scss"
33
34
  gsub_file "app/assets/stylesheets/_customizations.scss", "@geoblacklight/frontend/app/assets/", ""
34
- insert_into_file "app/assets/stylesheets/application.bootstrap.scss", "@import 'customizations';\n", before: "@import 'bootstrap/scss/bootstrap';"
35
+ insert_into_file "app/assets/stylesheets/application.bootstrap.scss", "@import 'customizations';\n",
36
+ before: "@import 'bootstrap/scss/bootstrap';"
35
37
  end
36
38
 
37
39
  # Add CDN imports for CSS files used by Geoblacklight (leaflet, openlayers)
@@ -39,9 +41,9 @@ module Geoblacklight
39
41
  insert_into_file "app/assets/stylesheets/application.bootstrap.scss", before: "@import 'customizations';\n" do
40
42
  <<~SCSS
41
43
  /* GeoBlacklight dependencies CSS */
42
- @import url("https://cdn.skypack.dev/leaflet@1.9.4/dist/leaflet.css");
43
- @import url("https://cdn.jsdelivr.net/npm/leaflet-fullscreen@1.0.2/dist/leaflet.fullscreen.css");
44
- @import url("https://cdn.skypack.dev/ol@8.1.0/ol.css");
44
+ @import url("https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.css");
45
+ @import url("https://cdn.jsdelivr.net/npm/leaflet.fullscreen@5.3.0/dist/Control.FullScreen.css");
46
+ @import url("https://cdn.jsdelivr.net/npm/ol@8.1.0/ol.css");
45
47
 
46
48
  SCSS
47
49
  end
@@ -62,17 +64,6 @@ module Geoblacklight
62
64
  append_to_file "app/javascript/application.js", "import Geoblacklight from \"geoblacklight\";"
63
65
  end
64
66
 
65
- # Add pins for application dependencies to the importmap
66
- def update_importmap
67
- gsub_file "config/importmap.rb", "bootstrap.min.js", "https://cdn.skypack.dev/bootstrap@5.3.3"
68
- append_to_file "config/importmap.rb" do
69
- <<~CONTENT
70
- pin "@github/auto-complete-element", to: "https://cdn.skypack.dev/@github/auto-complete-element"
71
- pin "@popperjs/core", to: "https://ga.jspm.io/npm:@popperjs/core@2.11.8/dist/umd/popper.min.js"
72
- CONTENT
73
- end
74
- end
75
-
76
67
  # Run the build so styles are available for the first load of the app
77
68
  def build_styles
78
69
  run "yarn build:css"
@@ -16,8 +16,8 @@ module Geoblacklight
16
16
  SCSS entrypoint file, which will be bundled by Vite.
17
17
 
18
18
  Geoblacklight's frontend assets are installed from the npm package. In
19
- local development they automatically reference the versions from the
20
- outer directory (the Geoblacklight repository) via a yarn symlink.
19
+ CI they automatically reference the versions from the outer directory
20
+ (the Geoblacklight repository) via a yarn symlink.
21
21
  DESCRIPTION
22
22
 
23
23
  # Install Vite
@@ -26,6 +26,13 @@ module Geoblacklight
26
26
  run "bundle install"
27
27
  end
28
28
 
29
+ # Symlink geoblacklight's frontend assets in CI
30
+ def link_geoblacklight_package
31
+ if options[:test]
32
+ run "yarn link @geoblacklight/frontend"
33
+ end
34
+ end
35
+
29
36
  # Add our version of the Blacklight base layout with Vite helper tags
30
37
  def geoblacklight_base_layout
31
38
  copy_file "base.html.erb", "app/views/layouts/blacklight/base.html.erb"
@@ -42,23 +49,13 @@ module Geoblacklight
42
49
  run "bundle exec vite install"
43
50
  end
44
51
 
45
- # Pick a version of the frontend asset package and install it.
46
- def add_frontend
47
- # If a branch was specified (e.g. you are running a template.rb build
48
- # against a test branch), use the latest version available on npm
49
- if ENV["BRANCH"]
50
- run "yarn add @geoblacklight/frontend@latest"
51
-
52
- # Otherwise, pick the version from npm that matches our Geoblacklight
53
- # gem version
54
- else
55
- run "yarn add @geoblacklight/frontend@#{Geoblacklight::VERSION}"
52
+ # The vite-plugin-ruby package has a breaking change in 5.1.2,
53
+ # so we need to resolve to a specific version to avoid issues.
54
+ # Remove after https://github.com/ElMassimo/vite_ruby/issues/586 is fixed.
55
+ def pin_vite_plugin_ruby
56
+ inject_into_file "package.json", before: " \"dependencies\": {" do
57
+ " \"resolutions\": { \"vite-plugin-ruby\": \"5.1.1\" },\n"
56
58
  end
57
-
58
- # If in local development or CI, also create a link. This will make it so
59
- # changes made in the outer directory are picked up automatically.
60
- # `yarn link` has to have already been run in the outer directory first.
61
- run "yarn link @geoblacklight/frontend" if options[:test]
62
59
  end
63
60
 
64
61
  # The vite_rails gem doesn't currently install the vite-plugin-rails
@@ -4,15 +4,30 @@ module Geoblacklight
4
4
  # Run general asset setup and then delegate to the appropriate generator
5
5
  # Based on Blacklight::AssetsGenerator
6
6
  class AssetsGenerator < Rails::Generators::Base
7
- class_option :"asset-pipeline", type: :string, default: ENV.fetch("ASSET_PIPELINE", "vite"), desc: "Choose the asset pipeline to use (vite or importmap)"
7
+ class_option :"asset-pipeline", type: :string, default: ENV.fetch("ASSET_PIPELINE", "importmap"), desc: "Choose the asset pipeline to use (vite or importmap)"
8
8
  class_option :test, type: :boolean, default: ENV.fetch("CI", false), aliases: "-t", desc: "Indicates that app will be installed in a test environment"
9
9
 
10
+ # Pick a version of the frontend asset package and install it.
11
+ #
12
+ # If a branch was specified (e.g. you are running a template.rb build
13
+ # against a test branch), use the latest version available on npm.
14
+ #
15
+ # Otherwise, pick the version from npm that matches our Geoblacklight
16
+ # gem version.
17
+ def add_frontend
18
+ if ENV["BRANCH"]
19
+ run "yarn add @geoblacklight/frontend@latest"
20
+ else
21
+ run "yarn add @geoblacklight/frontend@#{Geoblacklight::VERSION}"
22
+ end
23
+ end
24
+
10
25
  def run_asset_pipeline_specific_generator
11
26
  generated_options = "--test=true" if options[:test]
12
27
  generator = if options[:"asset-pipeline"]
13
28
  "geoblacklight:assets:#{options[:"asset-pipeline"]}"
14
29
  else
15
- "geoblacklight:assets:vite"
30
+ "geoblacklight:assets:importmap"
16
31
  end
17
32
 
18
33
  generate generator, generated_options
@@ -2,7 +2,7 @@
2
2
 
3
3
  // Leaflet, OpenLayers, GeoBlacklight (includes Blacklight and Bootstrap)
4
4
  @import "leaflet/dist/leaflet.css";
5
- @import "leaflet-fullscreen/dist/leaflet.fullscreen.css";
5
+ @import "leaflet.fullscreen/dist/Control.FullScreen.css";
6
6
  @import "ol/ol.css";
7
7
  @import "~/stylesheets/geoblacklight.scss";
8
8
 
@@ -1,5 +1,5 @@
1
1
  # ArcGIS Online Base URL
2
- ARCGIS_BASE_URL: 'https://www.arcgis.com/home/webmap/viewer.html'
2
+ ARCGIS_BASE_URL: 'https://www.arcgis.com/apps/mapviewer/index.html'
3
3
 
4
4
  # Download path can be configured using this setting
5
5
  #DOWNLOAD_PATH: "./tmp/cache/downloads"
@@ -247,6 +247,7 @@ LEAFLET:
247
247
  HOVERTOWAKE: false
248
248
  MESSAGE: 'Click to Wake'
249
249
  BACKGROUND: 'rgba(214, 214, 214, .7)'
250
+ SIDEBAR: false # set to true to display attribute table as sidebar on map
250
251
  LAYERS:
251
252
  DETECT_RETINA: true
252
253
  INDEX:
@@ -14,7 +14,7 @@ module Geoblacklight
14
14
  request_params = GEOJSON_DOWNLOAD_PARAMS.merge(typeName: document.wxs_identifier)
15
15
  super(document, {
16
16
  type: "geojson",
17
- extension: "json",
17
+ extension: "geojson",
18
18
  request_params: request_params,
19
19
  content_type: "application/json",
20
20
  service_type: "wfs"
@@ -32,7 +32,7 @@ module Geoblacklight
32
32
  next unless app.config.respond_to?(:importmap) # skip for Vite
33
33
 
34
34
  app.config.importmap.paths << Engine.root.join("config/importmap.rb")
35
- app.config.importmap.cache_sweepers << Engine.root.join("app/assets/javascripts")
35
+ app.config.importmap.cache_sweepers << Engine.root.join("app/javascript")
36
36
  end
37
37
  end
38
38
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Geoblacklight
4
- VERSION = "5.1.0"
4
+ VERSION = "5.3.0"
5
5
  end
@@ -13,6 +13,7 @@ end
13
13
  def with_solr(&block)
14
14
  puts "Starting Solr"
15
15
  system_with_error_handling "docker compose up -d solr"
16
+ sleep 5 # give solr a few seconds to load the core config and be ready
16
17
  yield
17
18
  ensure
18
19
  puts "Stopping Solr"
@@ -23,7 +24,7 @@ namespace :geoblacklight do
23
24
  desc "Run Solr and GeoBlacklight for interactive development"
24
25
  task :server, [:rails_server_args] do |_t, args|
25
26
  with_solr do
26
- Rake::Task["geoblacklight:internal:seed"].invoke
27
+ Rake::Task["geoblacklight:index:seed"].invoke
27
28
 
28
29
  puts "Starting GeoBlacklight (Rails server)"
29
30
  puts " "
@@ -35,26 +36,15 @@ namespace :geoblacklight do
35
36
  end
36
37
  end
37
38
 
38
- # Local fixtures: bundle exec rake "geoblacklight:index:seed"
39
- # Remote fixtures: bundle exec rake "geoblacklight:index:seed[:remote]"
39
+ # Get fixture items bundled with the gem and index them into Solr
40
40
  namespace :index do
41
41
  desc "Index GBL test fixture metadata into Solr"
42
- task :seed, [:remote] => :environment do |t, args|
43
- docs = []
42
+ task seed: :environment do
43
+ puts "Indexing test fixtures"
44
44
 
45
- if args.remote
46
- puts "Indexing - Remote test fixtures"
47
- JSON.parse(
48
- URI.parse("https://api.github.com/repos/geoblacklight/geoblacklight/contents/spec/fixtures/solr_documents").open.read
49
- ).each do |fixture|
50
- if fixture["name"].include?(".json")
51
- docs << JSON.parse(URI.parse(fixture["download_url"]).open.read)
52
- end
53
- end
54
- else
55
- puts "Indexing - Local test fixtures"
56
- docs = Dir["spec/fixtures/solr_documents/*.json"].map { |f| JSON.parse File.read(f) }.flatten
57
- end
45
+ gem_path = Gem::Specification.find_by_name("geoblacklight").gem_dir
46
+ fixtures_path = File.join(gem_path, "spec", "fixtures", "solr_documents", "*.json")
47
+ docs = Dir[fixtures_path].flat_map { |f| JSON.parse(File.read(f)) }
58
48
 
59
49
  Blacklight.default_index.connection.add docs
60
50
  Blacklight.default_index.connection.commit
@@ -71,19 +61,21 @@ namespace :geoblacklight do
71
61
  FileUtils.mkdir_p(Rails.root.join("tmp", "cache", "downloads"), verbose: true)
72
62
  end
73
63
  desc "Precaches a download"
74
- task :precache, [:doc_id, :download_type, :timeout] => [:environment] do |_t, args|
64
+ task :precache, %i[doc_id download_type timeout] => [:environment] do |_t, args|
75
65
  unless args[:doc_id] && args[:download_type] && args[:timeout]
76
- fail "Please supply required arguments [document_id, download_type and timeout]"
66
+ raise "Please supply required arguments [document_id, download_type and timeout]"
77
67
  end
68
+
78
69
  document = Geoblacklight::SolrDocument.find(args[:doc_id])
79
- fail Blacklight::Exceptions::RecordNotFound if document[:id] != args[:doc_id]
70
+ raise Blacklight::Exceptions::RecordNotFound if document[:id] != args[:doc_id]
71
+
80
72
  download = "Geoblacklight::#{args[:download_type].capitalize}Download"
81
73
  .constantize.new(document, timeout: args[:timeout].to_i)
82
74
  download.get
83
75
  Rails.logger.info "Successfully downloaded #{download.file_name}"
84
76
  Rails.logger.info Geoblacklight::ShapefileDownload.file_path.to_s
85
- rescue Geoblacklight::Exceptions::ExternalDownloadFailed => error
86
- Rails.logger.error error.message + " " + error.url
77
+ rescue Geoblacklight::Exceptions::ExternalDownloadFailed => e
78
+ Rails.logger.error e.message + " " + e.url
87
79
  rescue NameError
88
80
  Rails.logger.error "Could not find that download type \"#{args[:download_type]}\""
89
81
  end
data/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@geoblacklight/frontend",
3
3
  "type": "module",
4
- "version": "5.1.0",
4
+ "version": "5.3.0",
5
5
  "license": "Apache-2.0",
6
6
  "publishConfig": {
7
7
  "access": "public"
@@ -9,8 +9,7 @@
9
9
  "scripts": {
10
10
  "dev": "vite",
11
11
  "build": "vite build",
12
- "watch": "vite build --watch",
13
- "test": "vitest"
12
+ "watch": "vite build --watch"
14
13
  },
15
14
  "files": [
16
15
  "app/assets",
@@ -26,15 +25,13 @@
26
25
  "bootstrap": "^5.3.3",
27
26
  "esri-leaflet": "^3.0.12",
28
27
  "leaflet": "^1.9.4",
29
- "leaflet-iiif": "^3.0.0",
30
- "leaflet-fullscreen": "^1.0.2",
31
- "ol": "8.1.0",
32
- "ol-pmtiles": "^0.3.0"
28
+ "leaflet.fullscreen": "^5.3.0",
29
+ "ol": "10.7.0",
30
+ "ol-pmtiles": "^2.0.2"
33
31
  },
34
32
  "devDependencies": {
35
- "jsdom": "^24.1.0",
33
+ "jsdom": "^27.3.0",
36
34
  "rollup-plugin-includepaths": "^0.2.4",
37
- "vite": "^5.0.0",
38
- "vitest": "^2.0.3"
35
+ "vite": "^7.2.2"
39
36
  }
40
37
  }
@@ -190,8 +190,8 @@
190
190
  "type": "string",
191
191
  "const": "Aardvark"
192
192
  },
193
- "gbl_suppressed_b": { "type": "boolean" },
194
- "gbl_georeferenced_b": { "type": "boolean" }
193
+ "gbl_suppressed_b": { "type": ["string", "boolean"] },
194
+ "gbl_georeferenced_b": { "type": ["string", "boolean"] }
195
195
  },
196
196
  "required": ["id", "dct_title_s", "gbl_resourceClass_sm", "dct_accessRights_s", "gbl_mdVersion_s"]
197
197
  }
@@ -94,7 +94,7 @@
94
94
  </query>
95
95
 
96
96
  <requestDispatcher handleSelect="false">
97
- <requestParsers enableRemoteStreaming="true" multipartUploadLimitInKB="2048000" formdataUploadLimitInKB="2048"/>
97
+ <requestParsers multipartUploadLimitInKB="2048000" formdataUploadLimitInKB="2048"/>
98
98
  <httpCaching never304="true"/>
99
99
  </requestDispatcher>
100
100
 
@@ -5,20 +5,18 @@ require "spec_helper"
5
5
  feature "Leaflet fullscreen control", js: true do
6
6
  scenario "WMS layer should have full screen control" do
7
7
  visit solr_document_path("stanford-cz128vq0535")
8
- expect(page).to have_css(".leaflet-control-fullscreen-button", visible: :all)
8
+ expect(page).to have_css(".leaflet-control-zoom-fullscreen", visible: :all)
9
9
  end
10
10
  end
11
11
 
12
- feature "Clover IIIF fullscreen control", js: true do
12
+ feature "IIIF fullscreen control", js: true do
13
13
  scenario "IIIF layer should have full screen control" do
14
- skip "Clover is disabled" # see https://github.com/geoblacklight/geoblacklight/issues/1675
15
14
  visit solr_document_path("princeton-sx61dn82p")
16
- expect(page).to have_button("Toggle full page")
15
+ expect(page).to have_button("Full screen", visible: :all)
17
16
  end
18
17
 
19
18
  scenario "IIIF image should have full screen control" do
20
- skip "Clover is disabled" # see https://github.com/geoblacklight/geoblacklight/issues/1675
21
19
  visit solr_document_path("princeton-02870w62c")
22
- expect(page).to have_css("[data-button='full-page']")
20
+ expect(page).to have_css("img[alt='Toggle full page']", visible: :all)
23
21
  end
24
22
  end
@@ -4,14 +4,7 @@ require "spec_helper"
4
4
 
5
5
  feature "saved searches" do
6
6
  scenario "list spatial search", js: true do
7
- visit root_path
8
- within "#leaflet-viewer" do
9
- find(".search-control a").click
10
- expect(page.current_url).to match(/bbox=/)
11
- end
12
- if Rails.version == "6.1.7.6"
13
- visit root_path({bbox: "-180 -89.338214 180 88.918831"})
14
- end
7
+ visit root_path({bbox: "-180 -89.338214 180 88.918831"})
15
8
  visit blacklight.search_history_path
16
9
  expect(page).to have_css "td.query a", text: /#{I18n.t("geoblacklight.bbox_label")}/
17
10
  end
@@ -11,6 +11,7 @@ describe Geoblacklight::GeojsonDownload do
11
11
  options = download.instance_variable_get(:@options)
12
12
  expect(options[:content_type]).to eq "application/json"
13
13
  expect(options[:request_params][:typeName]).to eq "stanford-test"
14
+ expect(options[:extension]).to eq "geojson"
14
15
  end
15
16
  it "merges custom options" do
16
17
  download = described_class.new(document, timeout: 33)
data/template.rb CHANGED
@@ -1,29 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- gem "blacklight", "~> 8.0"
4
-
5
- # Ensure the app generates with Propshaft; sprockets is no longer supported
6
- # https://github.com/geoblacklight/geoblacklight/issues/1265
7
- ENV["ENGINE_CART_RAILS_OPTIONS"] = ENV["ENGINE_CART_RAILS_OPTIONS"].to_s + " -a propshaft --css bootstrap"
8
-
9
- # Use importmaps for JS if requested, otherwise default to vite
10
- ENV["ENGINE_CART_RAILS_OPTIONS"] += if ENV["ASSET_PIPELINE"] == "importmap"
11
- " --js importmap"
12
- else
13
- " --js rollup"
14
- end
15
-
16
- # Install latest version of geoblacklight gem if running
17
- # generator with a development branch.
3
+ # Set BRANCH=<branch_name> to install from a specific branch
18
4
  if ENV["BRANCH"]
19
5
  gem "geoblacklight", github: "geoblacklight/geoblacklight", branch: ENV["BRANCH"]
20
6
  else
21
- gem "geoblacklight", "~> 5.0"
7
+ gem "geoblacklight"
22
8
  end
23
9
 
24
10
  run "bundle install"
25
11
 
26
- generate "blacklight:install", "--devise", "--skip-solr"
27
- generate "geoblacklight:install", "-f"
28
-
29
- rake "db:migrate"
12
+ after_bundle do
13
+ generate "blacklight:install", ENV.fetch("BLACKLIGHT_INSTALL_OPTIONS", "--devise --skip-solr")
14
+ generate "geoblacklight:install"
15
+ rails_command "db:migrate"
16
+ end
data/vite.config.ts CHANGED
@@ -28,8 +28,5 @@ export default defineConfig(() => {
28
28
  ],
29
29
  },
30
30
  },
31
- test: {
32
- environment: "jsdom",
33
- },
34
31
  };
35
32
  });
metadata CHANGED
@@ -1,17 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: geoblacklight
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.1.0
4
+ version: 5.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Graves
8
8
  - Darren Hardy
9
9
  - Eliot Jordan
10
10
  - Jack Reed
11
- autorequire:
12
11
  bindir: bin
13
12
  cert_chain: []
14
- date: 2025-08-11 00:00:00.000000000 Z
13
+ date: 2026-05-28 00:00:00.000000000 Z
15
14
  dependencies:
16
15
  - !ruby/object:Gem::Dependency
17
16
  name: rails
@@ -370,8 +369,7 @@ extensions: []
370
369
  extra_rdoc_files: []
371
370
  files:
372
371
  - ".github/ISSUE_TEMPLATE.md"
373
- - ".github/workflows/build-demo-app.yml"
374
- - ".github/workflows/prune-containers.yml"
372
+ - ".github/dependabot.yml"
375
373
  - ".github/workflows/ruby.yml"
376
374
  - ".gitignore"
377
375
  - ".standard.yml"
@@ -485,6 +483,8 @@ files:
485
483
  - app/components/blacklight/icons/uva_component.rb
486
484
  - app/components/blacklight/icons/web_services_component.rb
487
485
  - app/components/blacklight/icons/websites_component.rb
486
+ - app/components/geoblacklight/accordion_component.html.erb
487
+ - app/components/geoblacklight/accordion_component.rb
488
488
  - app/components/geoblacklight/arcgis_component.html.erb
489
489
  - app/components/geoblacklight/arcgis_component.rb
490
490
  - app/components/geoblacklight/attribute_table_component.html.erb
@@ -559,6 +559,7 @@ files:
559
559
  - app/javascript/geoblacklight/leaflet/constants.js
560
560
  - app/javascript/geoblacklight/leaflet/controls/geosearch.js
561
561
  - app/javascript/geoblacklight/leaflet/controls/layer_opacity.js
562
+ - app/javascript/geoblacklight/leaflet/controls/sidebar.js
562
563
  - app/javascript/geoblacklight/leaflet/controls/sleep.js
563
564
  - app/javascript/geoblacklight/leaflet/inspection.js
564
565
  - app/javascript/geoblacklight/leaflet/layer_index_map.js
@@ -607,9 +608,6 @@ files:
607
608
  - lib/generators/geoblacklight/templates/assets/geoblacklight.scss
608
609
  - lib/generators/geoblacklight/templates/base.html.erb
609
610
  - lib/generators/geoblacklight/templates/catalog_controller.rb
610
- - lib/generators/geoblacklight/templates/demo-app/Dockerfile
611
- - lib/generators/geoblacklight/templates/demo-app/compose.yml
612
- - lib/generators/geoblacklight/templates/demo-app/start-server.sh
613
611
  - lib/generators/geoblacklight/templates/settings.yml
614
612
  - lib/generators/geoblacklight/templates/vite.config.ts
615
613
  - lib/generators/geoblacklight/templates/vite.json
@@ -932,13 +930,11 @@ files:
932
930
  - spec/tasks/geoblacklight_spec.rb
933
931
  - spec/test_app_templates/lib/generators/test_app_generator.rb
934
932
  - template.rb
935
- - test/leaflet/layers.test.js
936
933
  - vite.config.ts
937
934
  homepage: http://github.com/geoblacklight/geoblacklight
938
935
  licenses:
939
936
  - Apache 2.0
940
937
  metadata: {}
941
- post_install_message:
942
938
  rdoc_options: []
943
939
  require_paths:
944
940
  - lib
@@ -953,8 +949,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
953
949
  - !ruby/object:Gem::Version
954
950
  version: 2.5.2
955
951
  requirements: []
956
- rubygems_version: 3.5.16
957
- signing_key:
952
+ rubygems_version: 3.6.2
958
953
  specification_version: 4
959
954
  summary: A discovery platform for geospatial holdings
960
955
  test_files: []
@@ -1,156 +0,0 @@
1
- name: Build demo app
2
-
3
- on:
4
- pull_request:
5
- push:
6
- branches:
7
- - main
8
- schedule:
9
- - cron: "0 1 * * SUN" # every sunday at 1AM
10
- workflow_dispatch:
11
-
12
- env:
13
- REGISTRY: ghcr.io
14
- IMAGE_NAME: ${{ github.repository }}
15
- BRANCH: ${{ github.head_ref || github.ref_name }}
16
-
17
- jobs:
18
- build-app:
19
- runs-on: ubuntu-latest
20
- outputs:
21
- artifact-url: ${{ steps.artifact-upload-step.outputs.artifact-url }}
22
- steps:
23
- - uses: actions/checkout@v4
24
- - name: Set up Ruby
25
- uses: ruby/setup-ruby@v1
26
- with:
27
- ruby-version: 3.3.4
28
-
29
- - name: Install dependencies
30
- run: bundle install
31
- env:
32
- RAILS_VERSION: "7.2.2.1"
33
-
34
- - name: Build frontend package
35
- run: |
36
- yarn install
37
- yarn build
38
- yarn link
39
-
40
- - name: Build
41
- run: BRANCH=${{ env.BRANCH }} rails new build -m template.rb -a propshaft --css bootstrap --js rollup
42
-
43
- - name: Cleanup
44
- run: rm -rf build/node_modules build/Gemfile.lock build/yarn.lock build/tmp
45
-
46
- - name: Copy Dockerfile
47
- run: cp lib/generators/geoblacklight/templates/demo-app/Dockerfile build/.
48
-
49
- - name: Copy demo-app compose.yml
50
- run: cp -f lib/generators/geoblacklight/templates/demo-app/compose.yml build/.
51
-
52
- - name: Copy start-server script
53
- run: cp lib/generators/geoblacklight/templates/demo-app/start-server.sh build/.
54
-
55
- - name: Copy fixture solr documents
56
- run: mkdir -p build/spec/fixtures && cp -R spec/fixtures/solr_documents build/spec/fixtures/.
57
-
58
- - name: Replace main image tag with pr tag
59
- if: github.ref_name != 'main'
60
- run: sed -i 's/main/pr-${{ github.event.number }}/g' build/compose.yml
61
-
62
- - name: Upload app build
63
- uses: actions/upload-artifact@v4
64
- id: artifact-upload-step
65
- with:
66
- name: build-${{ env.BRANCH }}
67
- path: build/
68
-
69
- build-docker:
70
- runs-on: ubuntu-latest
71
- needs:
72
- - build-app
73
- steps:
74
- - name: Download app build
75
- uses: actions/download-artifact@v4
76
- with:
77
- name: build-${{ env.BRANCH }}
78
-
79
- - name: Set up QEMU
80
- uses: docker/setup-qemu-action@v3
81
-
82
- - name: Set up Docker Buildx
83
- uses: docker/setup-buildx-action@v3
84
-
85
- - name: Log in to the Container registry
86
- uses: docker/login-action@v3
87
- with:
88
- registry: ${{ env.REGISTRY }}
89
- username: ${{ github.actor }}
90
- password: ${{ secrets.GITHUB_TOKEN }}
91
-
92
- - name: Extract metadata (tags, labels) for Docker
93
- id: meta
94
- uses: docker/metadata-action@v5
95
- with:
96
- images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
97
- tags: |
98
- type=ref,event=branch
99
- type=ref,event=pr
100
- type=sha
101
- env:
102
- DOCKER_METADATA_PR_HEAD_SHA: true
103
-
104
- # Rebuild base context when triggered by schedule or workflow_dispatch
105
- - name: Build and push base Docker image
106
- uses: docker/build-push-action@v6
107
- if: github.event_name == 'workflow_dispatch' || github.event_name == 'schedule'
108
- with:
109
- context: "${{ github.workspace }}"
110
- file: "${{ github.workspace }}/Dockerfile"
111
- push: true
112
- platforms: linux/amd64,linux/arm64
113
- cache-from: type=gha
114
- cache-to: type=gha,mode=max
115
- tags: ghcr.io/geoblacklight/geoblacklight:base
116
- target: "base"
117
-
118
- # Build only the app context. Build times are faster because most
119
- # gems and node packages are already installed in the base context.
120
- - name: Build and push branch Docker image
121
- uses: docker/build-push-action@v6
122
- with:
123
- context: "${{ github.workspace }}"
124
- file: "${{ github.workspace }}/Dockerfile"
125
- push: true
126
- platforms: linux/amd64,linux/arm64
127
- cache-from: type=gha
128
- cache-to: type=gha,mode=max
129
- tags: ${{ steps.meta.outputs.tags }}
130
- labels: ${{ steps.meta.outputs.labels }}
131
- target: "app"
132
-
133
- notify:
134
- runs-on: ubuntu-latest
135
- if: github.ref_name != 'main'
136
- needs:
137
- - build-app
138
- - build-docker
139
- permissions:
140
- contents: read
141
- packages: write
142
- pull-requests: write
143
- steps:
144
- - name: Add artifact link to PR comments
145
- uses: mshick/add-pr-comment@v2
146
- with:
147
- message: |
148
- Demo app download link: ${{ needs.build-app.outputs.artifact-url }}
149
-
150
- 1. Download demo app and unzip file
151
- 2. Change into app directory
152
- - run `docker compose pull`
153
- - run `docker compose up`
154
- 3. Open in browser
155
- - App: http://127.0.0.1:3001
156
- - Solr: http://127.0.0.1:8984
@@ -1,19 +0,0 @@
1
- name: Prune containers
2
-
3
- on:
4
- workflow_dispatch:
5
- schedule:
6
- - cron: "0 0 * * SUN" # every sunday at midnight
7
-
8
- jobs:
9
- clean:
10
- runs-on: ubuntu-latest
11
- name: Delete old images
12
- steps:
13
- - uses: snok/container-retention-policy@v3.0.0
14
- with:
15
- account: geoblacklight
16
- image-names: geoblacklight
17
- token: ${{ secrets.GITHUB_TOKEN }}
18
- image-tags: "!main !base"
19
- cut-off: 2w
@@ -1,31 +0,0 @@
1
- # syntax = docker/dockerfile:1
2
-
3
- # Make sure RUBY_VERSION matches the Ruby version in .ruby-version and Gemfile
4
- ARG RUBY_VERSION=3.3.4
5
- FROM registry.docker.com/library/ruby:$RUBY_VERSION-slim AS base
6
-
7
- RUN apt-get update -qq && \
8
- apt-get install --no-install-recommends -y build-essential git pkg-config nodejs npm curl libsqlite3-0
9
-
10
- RUN npm install --global yarn
11
-
12
- ENV RAILS_ENV="development" \
13
- BUNDLE_PATH="/usr/local/bundle"
14
-
15
- # Rails app lives here
16
- WORKDIR /rails
17
-
18
- # Install gems and javascript packages
19
- COPY Gemfile .
20
- RUN bundle install
21
- COPY package.json .
22
- RUN yarn install
23
-
24
- FROM ghcr.io/geoblacklight/geoblacklight:base AS app
25
-
26
- # Add application code
27
- COPY . .
28
-
29
- # Run the server script by default, this can be overwritten at runtime
30
- EXPOSE 3000
31
- CMD ["sh", "start-server"]
@@ -1,26 +0,0 @@
1
- services:
2
- app:
3
- image: ghcr.io/geoblacklight/geoblacklight:main
4
- ports:
5
- - "3001:3001"
6
- links:
7
- - "solr:solr"
8
- environment:
9
- SOLR_URL: "http://solr:8983/solr/blacklight-core"
10
- RAILS_DEVELOPMENT_HOSTS: ".githubpreview.dev,.preview.app.github.dev,.app.github.dev,.csb.app"
11
- depends_on:
12
- - solr
13
- command: sh start-server.sh
14
- solr:
15
- image: solr:9.6.1
16
- volumes:
17
- - $PWD/solr/conf:/opt/solr/conf
18
- ports:
19
- - 8984:8983
20
- entrypoint:
21
- - docker-entrypoint.sh
22
- - solr-precreate
23
- - blacklight-core
24
- - /opt/solr/conf
25
- - "-Xms256m"
26
- - "-Xmx512m"
@@ -1,21 +0,0 @@
1
- #!/bin/sh
2
-
3
- bundle install
4
- yarn install
5
-
6
- # Build and Install local copy of @geoblackligt/frontend
7
- # These steps are included in the docker image instead if the image build script
8
- # to reduce the size of the layers that docker compose has to pull with each new version.
9
- gempath=$(bundle exec gem which geoblacklight | sed 's/\/lib\/geoblacklight.rb//')
10
- if [ ! -d "$gempath/dist/" ]; then
11
- cd $gempath
12
- yarn install
13
- yarn vite build
14
- cd -
15
- fi
16
- yarn add file:$gempath
17
-
18
- # Start the server
19
- bundle exec rake db:prepare
20
- bundle exec rake geoblacklight:index:seed
21
- bundle exec rails server -b 0.0.0.0 -p 3001
@@ -1,17 +0,0 @@
1
- import { wmsLayer, wmtsLayer } from "../../app/javascript/leaflet/layers";
2
- import { describe, expect, it } from "vitest";
3
-
4
- describe("leaflet/layers", () => {
5
- describe("wmsLayer", () => {
6
- it("returns a WMS tile layer", () => {
7
- const url = "http://example.com/wms";
8
- const layerId = "layerId";
9
- const opacity = 0.5;
10
- const detectRetina = true;
11
- const layer = wmsLayer(url, { layerId, opacity, detectRetina });
12
- expect(layer.options.layers).toEqual(layerId);
13
- expect(layer.options.opacity).toEqual(opacity);
14
- expect(layer.options.detectRetina).toEqual(detectRetina);
15
- });
16
- });
17
- });