diff --git a/.github/actions/build-container/action.yml b/.github/actions/build-container/action.yml index 441577959..ba23907af 100644 --- a/.github/actions/build-container/action.yml +++ b/.github/actions/build-container/action.yml @@ -39,7 +39,7 @@ runs: echo "tag=$clean_tag" >> "$GITHUB_OUTPUT" - name: Build and push ${{ inputs.image_name }} container - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v7 with: build-args: | build_date="${{ steps.build_date.outputs.date }}" diff --git a/.github/workflows/build-containers.yml b/.github/workflows/build-containers.yml index 2b6ddad0c..2d38e2cc3 100644 --- a/.github/workflows/build-containers.yml +++ b/.github/workflows/build-containers.yml @@ -31,10 +31,10 @@ jobs: environment: ${{ fromJson(inputs.environments) }} service: ${{ fromJson(inputs.services) }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v4 + uses: aws-actions/configure-aws-credentials@v6 with: role-to-assume: ${{ secrets.aws_role_to_assume }} aws-region: ${{ vars.AWS_REGION }} @@ -44,7 +44,7 @@ jobs: uses: aws-actions/amazon-ecr-login@v2 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v4 - name: Get service config id: service diff --git a/.github/workflows/lint-and-test.yml b/.github/workflows/lint-and-test.yml index 4ee18cca9..a11eee65d 100644 --- a/.github/workflows/lint-and-test.yml +++ b/.github/workflows/lint-and-test.yml @@ -10,7 +10,7 @@ jobs: BUNDLE_PATH: vendor/bundle BUNDLE_WITH: test steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - uses: ruby/setup-ruby@v1 with: bundler-cache: true @@ -19,13 +19,16 @@ jobs: run: bundle exec rubocop --format github test: - name: Test + name: "Test (Valkyrie enabled: ${{ matrix.hyrax_valkyrie_enabled }})" runs-on: ubuntu-latest container: - image: ruby:2.7.8-slim-bullseye + image: ruby:3.2.9-slim-bookworm volumes: - solr:/tmp/solr needs: lint + strategy: + matrix: + hyrax_valkyrie_enabled: [false] services: database: image: postgres:13-alpine @@ -51,17 +54,21 @@ jobs: ports: - 6379:6379 solr: - image: solr:8.11.4 + image: solr:9.10.1 ports: - 8983:8983 volumes: - - solr:/var/solr/data + - solr:/var/solr + env: + SOLR_OPTS: "-Dsolr.config.lib.enabled=true -Dsolr.modules=analysis-extras" + SOLR_HOST: solr env: BUNDLE_PATH: vendor/bundle BUNDLE_WITH: test CAS_BASE_URL: '' CI: 1 FEDORA_TEST_URL: http://fedora:8080/rest + HYRAX_VALKYRIE: ${{ matrix.hyrax_valkyrie_enabled }} IIIF_BASE_URL: http://localhost/iiif/2 NOKOGIRI_USE_SYSTEM_LIBRARIES: true PSQL_PASSWORD: spot_test_pw @@ -70,17 +77,17 @@ jobs: PSQL_HOST: database RAILS_ENV: test SOLR_TEST_URL: http://solr:8983/solr/spot-test - SOLR_VERSION: "8.11.4" + SOLR_VERSION: "9.10.1" URL_HOST: http://localhost:3000 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: Copy Solr config to mount run: | - mkdir -p /tmp/solr/spot-test/data - cp -r docker/solr/config/* /tmp/solr/spot-test - touch /tmp/solr/spot-test/core.properties - chown -R 8983:8983 /tmp/solr/spot-test + mkdir -p /tmp/solr/data/spot-test/data + cp -r docker/solr/config /tmp/solr/data/spot-test/conf + touch /tmp/solr/data/spot-test/core.properties + chown -R 8983:8983 /tmp/solr/data/spot-test - name: Restart Solr service uses: docker://docker with: @@ -88,13 +95,11 @@ jobs: - name: Install system dependencies from Dockerfile run: | - apt-get update -y && apt-get install -y --no-install-recommends ca-certificates curl gnupg && \ - mkdir -p /etc/apt/keyrings && \ - curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \ - echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list && \ - apt-get update -y && apt-get install -y \ - build-essential coreutils curl git libxml2 libxml2-dev libxslt-dev \ - netcat-openbsd nodejs openssl postgresql-13 ruby-dev tzdata zip \ + apt-get update -y && apt-get install -y curl && \ + curl -fsSL https://deb.nodesource.com/setup_22.x | bash - && \ + apt-get update -y --fix-missing && apt-get install -y --no-install-recommends \ + awscli build-essential coreutils cron git libpq-dev libxml2 libxml2-dev \ + libxslt-dev netcat-openbsd nodejs openssl postgresql ruby-dev tzdata zip \ libasound2 libdbus-glib-1-dev libgtk-3-0 libpq-dev unzip libx11-xcb1 - name: Setup Firefox diff --git a/.ruby-version b/.ruby-version index 6a81b4c83..e650c01d9 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.7.8 +3.2.9 diff --git a/Dockerfile b/Dockerfile index 1d78fa408..1e77d05d0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,15 +3,13 @@ # !! This is a builder image. Not for general use !! # Use this as the base image for the Rails / Sidekiq services. ## -FROM ruby:2.7.8-slim-bullseye AS spot-base +FROM ruby:3.2.9-slim-bookworm AS spot-base RUN apt-get clean && \ - apt-get update && \ - apt-get install -y --no-install-recommends ca-certificates curl gnupg && \ - mkdir -p /etc/apt/keyrings && \ - curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \ - echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list && \ - apt-get update -y && apt-get install -y --no-install-recommends \ + apt-get update -y && \ + apt-get install -y curl && \ + curl -fsSL https://deb.nodesource.com/setup_22.x | bash - && \ + apt-get update -y --fix-missing && apt-get install -y --no-install-recommends \ awscli \ build-essential \ coreutils \ @@ -24,7 +22,7 @@ RUN apt-get clean && \ netcat-openbsd \ nodejs \ openssl \ - postgresql-13 \ + postgresql \ ruby-dev \ tzdata \ zip @@ -38,10 +36,9 @@ ENV HYRAX_CACHE_PATH=/spot/tmp/cache \ RUN corepack enable -COPY Gemfile.lock /spot/ +COPY Gemfile Gemfile.lock /spot/ RUN gem install bundler:$(tail -n 1 Gemfile.lock | sed -e 's/\s*//') -COPY Gemfile /spot/ RUN bundle config unset with && \ bundle config unset without && \ bundle config set without "development:test" && \ @@ -137,14 +134,14 @@ ENV MALLOC_ARENA_MAX=2 # We don't need the entrypoint script to generate an SSL cert ENV SKIP_SSL_CERT=true -RUN apt-get update && apt-get install -y --no-install-recommends \ - bash \ +RUN apt-get update -y && \ + apt-get install -y \ ffmpeg \ ghostscript \ imagemagick \ libreoffice \ mediainfo \ - openjdk-11-jre \ + openjdk-17-jre \ perl \ python3 \ unzip diff --git a/Gemfile b/Gemfile index db585bb3a..622f8ce4c 100644 --- a/Gemfile +++ b/Gemfile @@ -9,16 +9,16 @@ end # # the base rails stack (installed with 'rails new spot') # -gem 'rails', '~> 5.2.7' +gem 'rails', '~> 6.1' # use Puma as the app server gem 'puma', '~> 6.4.0' # Use SCSS for stylesheets -gem 'sass-rails', '~> 5.1.0' +gem 'sass-rails', '~> 6.0' -# Use Uglifier as compressor for JavaScript assets -gem 'uglifier', '~> 4.2.0' +# Use Terser as compressor for JavaScript assets +gem 'terser', '~> 1.2.7' # Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks gem 'turbolinks', '~> 5.2.1' @@ -29,7 +29,7 @@ gem 'jbuilder', '~> 2.11.5' # # the hyrax/spot stack # -gem 'hyrax', '~> 3.6.0' +gem 'hyrax', '~> 5.2.0' # modularize our javascripts gem 'almond-rails', '~> 0.3.0' @@ -44,16 +44,18 @@ gem 'aws-sdk-s3', '~> 1.142.0' gem 'bagit', '~> 0.6.0' # blacklight plugins for enhanced searching -gem 'blacklight_advanced_search', '~> 6.4.1' -gem 'blacklight_oai_provider', '~> 6.0.0' -gem 'blacklight_range_limit', '~> 6.3.3' +gem 'blacklight_advanced_search', '~> 7.0.0' +gem 'blacklight_oai_provider', '~> 7.0.2' +gem 'blacklight_range_limit', '~> 8.5.0' # start up the server faster gem 'bootsnap', '~> 1.17', require: false +gem 'bootstrap', '~> 4.0' + # Bulkrax for batch ingesting objects -gem 'browse-everything', '~> 1.1.2' -gem 'bulkrax', '~> 9.0.2' +gem 'browse-everything', '~> 1.6.0' +gem 'bulkrax', '~> 9.3.3' # This needs to be here if we want to compile our own JS # (there's like a single coffee-script file still remaining in hyrax) @@ -73,7 +75,7 @@ gem 'edtf-humanize', '~> 2.1.0' # a bunch of samvera gems rely on Faraday already, but we'll # require it as we're explicitly using it. -gem 'faraday', '~> 0.17.6' +gem 'faraday', '~> 2.0' # video file resource for getting information on video derivatives gem 'ffprober' @@ -99,7 +101,8 @@ gem 'kaminari', '~> 1.2.2' # mini_magick is a dependency of hydra-derivatives, but since we're # calling it explicitly, we should require it. -gem 'mini_magick', '~> 4.11' +# gem 'mini_magick', '~> 4.11' +gem 'posix-spawn' # manually add this gem to enable questioning_authority to parse linked-data results gem 'linkeddata', '~> 3.1.6' @@ -116,7 +119,7 @@ gem 'pg', '~> 1.5.4' # this is bundled somewhere within the hyrax stack, but since we're # calling it within our code we shouldn't expect it to always be there -gem 'rdf-vocab', '~> 3.2.7' +gem 'rdf-vocab', '~> 3.3.3' # solr client for interacting with rails (installed w/ hyrax) gem 'rsolr', '~> 2.5.0' @@ -129,7 +132,10 @@ gem 'sidekiq', '~> 5.2.9' gem 'sidekiq-cron', '~> 1.9.1' # using Slack for some of our messaging -gem 'slack-ruby-client', '~> 0.14.6' +gem 'slack-ruby-client' + +# used in the Hyrax 4 upgrade but not a dependency?? +gem 'twitter-typeahead-rails', '~> 0.11.1' # now that we're writing es6 javascript of our own (+ not just using the hyrax js) # we need to compile it in sprockets. @@ -148,12 +154,18 @@ gem 'redlock', '>= 0.1.2', '< 2.0' # that throws off how forms are built in Hyrax. gem 'simple_form', '< 5.2' +# sprockets support gets cagey after 1.0 +gem 'openseadragon', '~> 0.9.0' + +# need to be 1.20.1 or higher to avoid an incompatibility with json gem +gem 'multi_json', '~> 1.20.1' + # development dependencies (not as necessary to lock down versions here) group :development do # Seed data # gem 'ldr-development-seeds', github: 'LafayetteCollegeLibraries/ldr-development-seeds', branch: 'main' - gem 'listen', '>= 3.0.5', '< 3.8' + gem 'listen', '~> 3.9.0' # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring gem 'spring', '~> 2.1.1' gem 'spring-watcher-listen', '~> 2.0.0' @@ -177,7 +189,7 @@ group :development, :test do gem 'selenium-webdriver' gem 'shoulda-matchers', '~> 4' gem 'simplecov', '~> 0.22.0', require: false - gem 'simplecov-cobertura', '~> 2.1', require: false + gem 'simplecov-cobertura', '~> 3', require: false gem 'stub_env', '~> 1.0.4' gem 'webmock', '~> 3.8' end diff --git a/Gemfile.lock b/Gemfile.lock index f10d88aa4..7a5a540fe 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,37 +1,53 @@ GEM remote: https://rubygems.org/ specs: - actioncable (5.2.8.1) - actionpack (= 5.2.8.1) + actioncable (6.1.7.10) + actionpack (= 6.1.7.10) + activesupport (= 6.1.7.10) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailer (5.2.8.1) - actionpack (= 5.2.8.1) - actionview (= 5.2.8.1) - activejob (= 5.2.8.1) + actionmailbox (6.1.7.10) + actionpack (= 6.1.7.10) + activejob (= 6.1.7.10) + activerecord (= 6.1.7.10) + activestorage (= 6.1.7.10) + activesupport (= 6.1.7.10) + mail (>= 2.7.1) + actionmailer (6.1.7.10) + actionpack (= 6.1.7.10) + actionview (= 6.1.7.10) + activejob (= 6.1.7.10) + activesupport (= 6.1.7.10) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (5.2.8.1) - actionview (= 5.2.8.1) - activesupport (= 5.2.8.1) - rack (~> 2.0, >= 2.0.8) + actionpack (6.1.7.10) + actionview (= 6.1.7.10) + activesupport (= 6.1.7.10) + rack (~> 2.0, >= 2.0.9) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (5.2.8.1) - activesupport (= 5.2.8.1) + rails-html-sanitizer (~> 1.0, >= 1.2.0) + actiontext (6.1.7.10) + actionpack (= 6.1.7.10) + activerecord (= 6.1.7.10) + activestorage (= 6.1.7.10) + activesupport (= 6.1.7.10) + nokogiri (>= 1.8.5) + actionview (6.1.7.10) + activesupport (= 6.1.7.10) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.0.3) - active-fedora (13.3.0) + rails-html-sanitizer (~> 1.1, >= 1.2.0) + active-fedora (15.0.1) active-triples (>= 0.11.0, < 2.0.0) - activemodel (>= 5.1) - activesupport (>= 5.1) + activemodel (>= 6.1) + activesupport (>= 6.1) deprecation - faraday (~> 0.12) + faraday (>= 1.0) faraday-encoding (>= 0.0.5) ldp (>= 0.7.0, < 2) + mutex_m rsolr (>= 1.1.2, < 3) ruby-progressbar (~> 1.0) active-triples (1.2.0) @@ -39,35 +55,38 @@ GEM activesupport (>= 3.0.0) rdf (>= 2.0.2, < 4.0) rdf-vocab (>= 2.0, < 4.0) - active_encode (0.8.2) + active_encode (1.3.0) + addressable (~> 2.8) rails - sprockets (< 4) - activejob (5.2.8.1) - activesupport (= 5.2.8.1) + activejob (6.1.7.10) + activesupport (= 6.1.7.10) globalid (>= 0.3.6) - activemodel (5.2.8.1) - activesupport (= 5.2.8.1) - activemodel-serializers-xml (1.0.2) - activemodel (> 5.x) - activesupport (> 5.x) + activemodel (6.1.7.10) + activesupport (= 6.1.7.10) + activemodel-serializers-xml (1.0.3) + activemodel (>= 5.0.0.a) + activesupport (>= 5.0.0.a) builder (~> 3.1) - activerecord (5.2.8.1) - activemodel (= 5.2.8.1) - activesupport (= 5.2.8.1) - arel (>= 9.0) + activerecord (6.1.7.10) + activemodel (= 6.1.7.10) + activesupport (= 6.1.7.10) activerecord-import (2.2.0) activerecord (>= 4.2) - activestorage (5.2.8.1) - actionpack (= 5.2.8.1) - activerecord (= 5.2.8.1) - marcel (~> 1.0.0) - activesupport (5.2.8.1) + activestorage (6.1.7.10) + actionpack (= 6.1.7.10) + activejob (= 6.1.7.10) + activerecord (= 6.1.7.10) + activesupport (= 6.1.7.10) + marcel (~> 1.0) + mini_mime (>= 1.1.0) + activesupport (6.1.7.10) concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 0.7, < 2) - minitest (~> 5.1) - tzinfo (~> 1.1) - addressable (2.8.5) - public_suffix (>= 2.0.2, < 6.0) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + zeitwerk (~> 2.3) + addressable (2.8.8) + public_suffix (>= 2.0.2, < 8.0) almond-rails (0.3.0) rails (>= 4.2) anystyle (1.4.2) @@ -76,27 +95,29 @@ GEM namae (~> 1.0) wapiti (~> 2.1) anystyle-data (1.3.0) - arel (9.0.0) - ast (2.4.2) - autoprefixer-rails (10.4.13.0) + ast (2.4.3) + autoprefixer-rails (10.4.21.0) execjs (~> 2) - awesome_nested_set (3.5.0) - activerecord (>= 4.0.0, < 7.1) - aws-eventstream (1.3.0) - aws-partitions (1.887.0) - aws-sdk-core (3.191.0) + awesome_nested_set (3.8.0) + activerecord (>= 4.0.0, < 8.1) + aws-eventstream (1.4.0) + aws-partitions (1.1172.0) + aws-sdk-core (3.233.0) aws-eventstream (~> 1, >= 1.3.0) - aws-partitions (~> 1, >= 1.651.0) - aws-sigv4 (~> 1.8) + aws-partitions (~> 1, >= 1.992.0) + aws-sigv4 (~> 1.9) + base64 + bigdecimal jmespath (~> 1, >= 1.6.1) - aws-sdk-kms (1.77.0) - aws-sdk-core (~> 3, >= 3.191.0) - aws-sigv4 (~> 1.1) + logger + aws-sdk-kms (1.113.0) + aws-sdk-core (~> 3, >= 3.231.0) + aws-sigv4 (~> 1.5) aws-sdk-s3 (1.142.0) aws-sdk-core (~> 3, >= 3.189.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.8) - aws-sigv4 (1.8.0) + aws-sigv4 (1.12.1) aws-eventstream (~> 1, >= 1.0.2) babel-source (5.8.35) babel-transpiler (0.7.0) @@ -108,67 +129,70 @@ GEM base64 (0.3.0) bcp47 (0.3.3) i18n - bcrypt (3.1.19) - bibtex-ruby (6.0.0) + bcp47_spec (0.2.1) + bcrypt (3.1.20) + bibtex-ruby (6.2.0) latex-decode (~> 0.0) + logger (~> 1.7) + racc (~> 1.7) + bigdecimal (3.3.1) bixby (5.0.2) rubocop (= 1.28.2) rubocop-ast rubocop-performance rubocop-rails rubocop-rspec - blacklight (6.25.0) - bootstrap-sass (~> 3.2) + blacklight (7.41.0) deprecation globalid + hashdiff + i18n (>= 1.7.0) jbuilder (~> 2.7) kaminari (>= 0.15) - nokogiri (~> 1.6) - rails (>= 4.2, < 6) - rsolr (>= 1.0.6, < 3) - twitter-typeahead-rails (= 0.11.1.pre.corejavascript) - blacklight-access_controls (0.6.2) - blacklight (~> 6.0) - cancancan (~> 1.8) + ostruct (>= 0.3.2) + rails (>= 6.1, < 8.1) + view_component (>= 2.74, < 4) + zeitwerk + blacklight-access_controls (6.1.0) + blacklight (> 6.0, < 9) + cancancan (>= 1.8) deprecation (~> 1.0) - blacklight-gallery (0.12.0) - blacklight (~> 6.3) - bootstrap-sass (~> 3.0) - openseadragon (>= 0.2.0) - rails - blacklight_advanced_search (6.4.1) - blacklight (~> 6.0, >= 6.0.1) + blacklight-gallery (4.6.4) + blacklight (>= 7.17, < 9) + rails (>= 6.1, < 9) + blacklight_advanced_search (7.0.0) + blacklight (~> 7.0) parslet - blacklight_oai_provider (6.0.0) - blacklight (~> 6.0) - oai (~> 0.4) - rails (>= 4.2, < 6) - blacklight_range_limit (6.3.3) - blacklight (>= 6.0.2) - jquery-rails - rails (>= 3.0) - bootsnap (1.17.0) + blacklight_oai_provider (7.0.2) + blacklight (~> 7.0) + oai (~> 1.2) + rexml + blacklight_range_limit (8.5.0) + blacklight (>= 7.25.2, < 9) + deprecation + view_component (>= 2.54, < 4) + bootsnap (1.18.6) msgpack (~> 1.2) - bootstrap-sass (3.4.1) - autoprefixer-rails (>= 5.2.1) - sassc (>= 2.0.0) + bootstrap (4.6.2) + autoprefixer-rails (>= 9.1.0) + popper_js (>= 1.16.1, < 2) + sassc-rails (>= 2.0.0) bootstrap_form (5.1.0) actionpack (>= 5.2) activemodel (>= 5.2) breadcrumbs_on_rails (3.0.1) - browse-everything (1.1.2) + browse-everything (1.6.0) addressable (~> 2.5) aws-sdk-s3 - dropbox_api (>= 0.1.10) - google-api-client (~> 0.23) - google_drive (>= 2.1, < 4) - googleauth (>= 0.6.6, < 1.0) - rails (>= 4.2, < 7.0) + dropbox_api (>= 0.1.20) + faraday (~> 2.0) + google-apis-drive_v3 + googleauth (>= 0.6.6, < 2.0) + rails (>= 4.2, < 8.1) ruby-box signet (~> 0.8) - typhoeus - builder (3.2.4) - bulkrax (9.0.2) + builder (3.3.0) + bulkrax (9.3.3) bagit (~> 0.6.0) coderay denormalize_fields @@ -180,12 +204,12 @@ GEM marcel oai (>= 0.4, < 2.x) rack (>= 2.0.6) - rails (>= 5.1.6) + rails (>= 5.1.6, < 8.0.0) rdf (>= 2.0.2, < 4.0) rubyzip simple_form byebug (11.1.3) - cancancan (1.17.0) + cancancan (3.6.1) capybara (3.39.2) addressable matrix @@ -198,11 +222,13 @@ GEM capybara-screenshot (1.0.26) capybara (>= 1.0, < 4) launchy - carrierwave (1.3.3) + carrierwave (1.3.4) activemodel (>= 4.0.0) activesupport (>= 4.0.0) mime-types (>= 1.16) ssrf_filter (~> 1.0, < 1.1.0) + childprocess (5.1.0) + logger (~> 1.5) clipboard-rails (1.7.1) coderay (1.1.3) coffee-rails (5.0.0) @@ -212,52 +238,47 @@ GEM coffee-script-source execjs coffee-script-source (1.12.2) - concurrent-ruby (1.2.3) - connection_pool (2.4.1) - crack (0.4.5) + concurrent-ruby (1.3.4) + connection_pool (2.5.4) + crack (1.0.0) + bigdecimal rexml crass (1.0.6) csv (3.3.5) database_cleaner (2.0.2) database_cleaner-active_record (>= 2, < 3) - database_cleaner-active_record (2.1.0) + database_cleaner-active_record (2.2.2) activerecord (>= 5.a) - database_cleaner-core (~> 2.0.0) + database_cleaner-core (~> 2.0) database_cleaner-core (2.0.1) - date (3.3.4) + date (3.5.1) declarative (0.0.20) - declarative-builder (0.1.0) - declarative-option (< 0.2.0) - declarative-option (0.1.0) denormalize_fields (1.3.0) activerecord (>= 4.1.14, < 8.0.0) deprecation (1.1.0) activesupport - devise (4.9.2) + devise (4.9.4) bcrypt (~> 3.0) orm_adapter (~> 0.1) railties (>= 4.1.0) responders warden (~> 1.2.3) - devise-guests (0.8.1) + devise-guests (0.8.3) devise devise_cas_authenticatable (2.0.2) devise (>= 4.0.0) rack-cas - diff-lcs (1.5.0) - disposable (0.4.7) + diff-lcs (1.6.2) + disposable (0.6.3) declarative (>= 0.0.9, < 1.0.0) - declarative-builder (< 0.2.0) - declarative-option (< 0.2.0) - representable (>= 2.4.0, <= 3.1.0) - uber (< 0.2.0) + representable (>= 3.1.1, < 4) docile (1.4.1) docopt (0.5.0) dotenv (2.7.6) dotenv-rails (2.7.6) dotenv (= 2.7.6) railties (>= 3.2) - draper (4.0.2) + draper (4.0.4) actionpack (>= 5.0) activemodel (>= 5.0) activemodel-serializers-xml (>= 1.0) @@ -267,67 +288,60 @@ GEM dropbox_api (0.1.21) faraday (< 3.0) oauth2 (~> 1.1) - dry-configurable (0.16.1) - dry-core (~> 0.6) + dry-configurable (1.3.0) + dry-core (~> 1.1) zeitwerk (~> 2.6) dry-container (0.11.0) concurrent-ruby (~> 1.0) - dry-core (0.9.1) + dry-core (1.1.0) concurrent-ruby (~> 1.0) + logger zeitwerk (~> 2.6) - dry-equalizer (0.3.0) - dry-events (0.2.0) + dry-events (1.1.0) concurrent-ruby (~> 1.0) - dry-core (~> 0.4) - dry-equalizer (~> 0.2) - dry-inflector (0.3.0) - dry-initializer (3.1.1) - dry-logic (1.3.0) + dry-core (~> 1.1) + dry-inflector (1.2.0) + dry-initializer (3.2.0) + dry-logic (1.6.0) + bigdecimal concurrent-ruby (~> 1.0) - dry-core (~> 0.9, >= 0.9) + dry-core (~> 1.1) zeitwerk (~> 2.6) - dry-matcher (0.9.0) - dry-core (~> 0.4, >= 0.4.8) - dry-monads (1.4.0) + dry-monads (1.9.0) concurrent-ruby (~> 1.0) - dry-core (~> 0.7) - dry-schema (1.11.3) + dry-core (~> 1.1) + zeitwerk (~> 2.6) + dry-schema (1.14.1) concurrent-ruby (~> 1.0) - dry-configurable (~> 0.16, >= 0.16) - dry-core (~> 0.9, >= 0.9) - dry-initializer (~> 3.0) - dry-logic (~> 1.3) - dry-types (~> 1.6) + dry-configurable (~> 1.0, >= 1.0.1) + dry-core (~> 1.1) + dry-initializer (~> 3.2) + dry-logic (~> 1.5) + dry-types (~> 1.8) zeitwerk (~> 2.6) - dry-struct (1.5.2) - dry-core (~> 0.9, >= 0.9) - dry-types (~> 1.6) + dry-struct (1.8.0) + dry-core (~> 1.1) + dry-types (~> 1.8, >= 1.8.2) ice_nine (~> 0.11) zeitwerk (~> 2.6) - dry-transaction (0.13.3) - dry-container (>= 0.2.8) - dry-events (>= 0.1.0) - dry-matcher (>= 0.7.0) - dry-monads (>= 0.4.0) - dry-types (1.6.1) + dry-types (1.8.3) + bigdecimal (~> 3.0) concurrent-ruby (~> 1.0) - dry-container (~> 0.3) - dry-core (~> 0.9, >= 0.9) - dry-inflector (~> 0.1, >= 0.1.2) - dry-logic (~> 1.3, >= 1.3) + dry-core (~> 1.0) + dry-inflector (~> 1.0) + dry-logic (~> 1.4) zeitwerk (~> 2.6) - dry-validation (1.9.0) + dry-validation (1.11.1) concurrent-ruby (~> 1.0) - dry-container (~> 0.7, >= 0.7.1) - dry-core (~> 0.9, >= 0.9) - dry-initializer (~> 3.0) - dry-schema (~> 1.11, >= 1.11.0) + dry-core (~> 1.1) + dry-initializer (~> 3.2) + dry-schema (~> 1.14) zeitwerk (~> 2.6) - ebnf (2.3.5) + ebnf (2.4.0) htmlentities (~> 4.3) - rdf (~> 3.2) + rdf (~> 3.3) scanf (~> 1.0) - sxp (~> 1.2) + sxp (~> 1.3) unicode-types (~> 1.8) edtf (3.1.1) activesupport (>= 3.0, < 8.0) @@ -337,125 +351,154 @@ GEM roman (~> 0.2.0) equivalent-xml (0.6.0) nokogiri (>= 1.4.3) - erubi (1.12.0) - et-orbi (1.2.7) + erubi (1.13.1) + et-orbi (1.4.0) tzinfo - ethon (0.16.0) - ffi (>= 1.15.0) - execjs (2.8.1) + execjs (2.10.0) factory_bot (6.4.5) activesupport (>= 5.0.0) factory_bot_rails (6.4.3) factory_bot (~> 6.4) railties (>= 5.0.0) - faraday (0.17.6) - multipart-post (>= 1.2, < 3) - faraday-encoding (0.0.5) + faraday (2.14.0) + faraday-net_http (>= 2.0, < 3.5) + json + logger + faraday-encoding (0.0.6) faraday - faraday_middleware (0.14.0) - faraday (>= 0.7.4, < 1.0) - ffi (1.15.5) + faraday-follow_redirects (0.4.0) + faraday (>= 1, < 3) + faraday-mashify (1.0.0) + faraday (~> 2.0) + hashie + faraday-multipart (1.1.1) + multipart-post (~> 2.0) + faraday-net_http (3.4.2) + net-http (~> 0.5) + faraday-retry (2.3.2) + faraday (~> 2.0) + ffi (1.17.2) ffprober (1.0) sorbet-runtime - flipflop (2.7.1) + flipflop (2.8.0) activesupport (>= 4.0) terminal-table (>= 1.8) flot-rails (0.0.7) jquery-rails - font-awesome-rails (4.7.0.8) - railties (>= 3.2, < 8.0) - fugit (1.8.1) - et-orbi (~> 1, >= 1.2.7) + font-awesome-rails (4.7.0.9) + railties (>= 3.2, < 9.0) + fugit (1.12.1) + et-orbi (~> 1.4) raabro (~> 1.4) - gems (1.2.0) - geocoder (1.8.5) + gapic-common (1.2.0) + faraday (>= 1.9, < 3.a) + faraday-retry (>= 1.0, < 3.a) + google-cloud-env (~> 2.2) + google-logging-utils (~> 0.1) + google-protobuf (~> 4.26) + googleapis-common-protos (~> 1.6) + googleapis-common-protos-types (~> 1.15) + googleauth (~> 1.12) + grpc (~> 1.66) + geocoder (1.8.6) base64 (>= 0.1.0) csv (>= 3.0.0) - gli (2.21.0) - globalid (1.1.0) - activesupport (>= 5.0) - google-api-client (0.53.0) - google-apis-core (~> 0.1) - google-apis-generator (~> 0.1) - google-apis-core (0.11.0) - addressable (~> 2.5, >= 2.5.1) - googleauth (>= 0.16.2, < 2.a) - httpclient (>= 2.8.1, < 3.a) - mini_mime (~> 1.0) + gli (2.22.2) + ostruct + globalid (1.3.0) + activesupport (>= 6.1) + google-analytics-data (0.7.2) + google-analytics-data-v1beta (>= 0.11, < 2.a) + google-cloud-core (~> 1.6) + google-analytics-data-v1beta (0.19.0) + gapic-common (~> 1.2) + google-cloud-errors (~> 1.0) + google-apis-core (1.0.2) + addressable (~> 2.8, >= 2.8.7) + faraday (~> 2.13) + faraday-follow_redirects (~> 0.3) + googleauth (~> 1.14) + mini_mime (~> 1.1) representable (~> 3.0) - retriable (>= 2.0, < 4.a) - rexml - webrick - google-apis-discovery_v1 (0.14.0) - google-apis-core (>= 0.11.0, < 2.a) - google-apis-drive_v3 (0.42.0) - google-apis-core (>= 0.11.0, < 2.a) - google-apis-generator (0.12.0) - activesupport (>= 5.0) - gems (~> 1.2) - google-apis-core (>= 0.11.0, < 2.a) - google-apis-discovery_v1 (~> 0.5) - thor (>= 0.20, < 2.a) - google-apis-sheets_v4 (0.24.0) - google-apis-core (>= 0.11.0, < 2.a) - google_drive (3.0.7) - google-apis-drive_v3 (>= 0.5.0, < 1.0.0) - google-apis-sheets_v4 (>= 0.4.0, < 1.0.0) - googleauth (>= 0.5.0, < 1.0.0) - nokogiri (>= 1.5.3, < 2.0.0) - googleauth (0.17.1) - faraday (>= 0.17.3, < 2.0) - jwt (>= 1.4, < 3.0) - memoist (~> 0.16) + retriable (~> 3.1) + google-apis-drive_v3 (0.75.0) + google-apis-core (>= 0.15.0, < 2.a) + google-cloud-core (1.8.0) + google-cloud-env (>= 1.0, < 3.a) + google-cloud-errors (~> 1.0) + google-cloud-env (2.3.1) + base64 (~> 0.2) + faraday (>= 1.0, < 3.a) + google-cloud-errors (1.5.0) + google-logging-utils (0.2.0) + google-protobuf (4.33.0) + bigdecimal + rake (>= 13) + googleapis-common-protos (1.9.0) + google-protobuf (~> 4.26) + googleapis-common-protos-types (~> 1.21) + grpc (~> 1.41) + googleapis-common-protos-types (1.22.0) + google-protobuf (~> 4.26) + googleauth (1.15.1) + faraday (>= 1.0, < 3.a) + google-cloud-env (~> 2.2) + google-logging-utils (~> 0.1) + jwt (>= 1.4, < 4.0) multi_json (~> 1.11) os (>= 0.9, < 2.0) - signet (~> 0.15) + signet (>= 0.16, < 2.a) + grpc (1.75.0) + google-protobuf (>= 3.25, < 5.0) + googleapis-common-protos-types (~> 1.0) haml (6.3.0) temple (>= 0.8.2) thor tilt - hashdiff (1.0.1) + hashdiff (1.2.1) hashie (5.0.0) hiredis (0.6.3) honeybadger (4.12.2) - htmlentities (4.3.4) - http_logger (0.7.0) - httpclient (2.8.3) - hydra-access-controls (11.0.7) + htmlentities (4.4.2) + http_logger (1.0.1) + hydra-access-controls (13.1.0) active-fedora (>= 10.0.0) - activesupport (>= 4, < 6) - blacklight (>= 5.16) - blacklight-access_controls (~> 0.6.0) - cancancan (~> 1.8) + activesupport (>= 6.1, < 8.1) + blacklight-access_controls (~> 6.0) + cancancan (>= 1.8, < 4) deprecation (~> 1.0) - hydra-core (11.0.7) - hydra-access-controls (= 11.0.7) - railties (>= 4.0.0, < 6) - hydra-derivatives (3.7.0) - active-fedora (>= 11.5.6, != 13.2.1, != 13.2.0, != 13.1.3, != 13.1.2, != 13.1.1, != 13.1.0, != 13.0.0, != 12.2.1, != 12.2.0, != 12.1.1, != 12.1.0, != 12.0.3, != 12.0.2, != 12.0.1, != 12.0.0) - active_encode (~> 0.1) - activesupport (>= 4.0, < 7) + hydra-core (13.1.0) + hydra-access-controls (= 13.1.0) + railties (>= 6.1, < 8.1) + hydra-derivatives (4.1.0) + active-fedora (>= 14.0) + active-triples (>= 1.2) + active_encode (~> 1.2) + activesupport (>= 4.0, < 9.0) addressable (~> 2.5) deprecation mime-types (> 2.0, < 4.0) mini_magick (>= 3.2, < 5) - hydra-editor (5.0.5) + ruby-vips + hydra-editor (7.0.0) active-fedora (>= 9.0.0) - activerecord (~> 5.0) + activerecord (>= 5.2, < 8.0) almond-rails (~> 0.1) - cancancan (~> 1.8) - rails (>= 5, < 6) - simple_form (>= 4.1.0, < 6.0) - sprockets (~> 3.7) + cancancan + concurrent-ruby (= 1.3.4) + psych (~> 3.3, < 4) + rails (>= 5.2, < 8.0) + simple_form (>= 4.1.0, < 5.2) + sprockets (>= 3.7) sprockets-es6 - hydra-file_characterization (1.1.2) + hydra-file_characterization (1.2.0) activesupport (>= 3.0.0) - hydra-head (11.0.7) - hydra-access-controls (= 11.0.7) - hydra-core (= 11.0.7) - rails (>= 5.2, < 6.1) - hydra-pcdm (1.3.0) - active-fedora (>= 10, < 15) + hydra-head (13.1.0) + hydra-access-controls (= 13.1.0) + hydra-core (= 13.1.0) + rails (>= 6.1, < 8.1) + hydra-pcdm (1.4.0) + active-fedora (>= 10) mime-types (>= 1) rdf-vocab hydra-role-management (1.1.0) @@ -465,54 +508,51 @@ GEM cancancan json (>= 1.8) psych (~> 3.0) - hydra-works (2.1.0) - activesupport (>= 5.2, < 7.1) - hydra-derivatives (~> 3.6) + hydra-works (2.2.0) + activesupport (>= 5.2, < 8.0) + hydra-derivatives (>= 3.6) hydra-file_characterization (~> 1.0) hydra-pcdm (>= 0.9) - hyrax (3.6.0) - active-fedora (~> 13.1, >= 13.1.2) + hyrax (5.2.0) + active-fedora (~> 15.0) almond-rails (~> 0.1) awesome_nested_set (~> 3.1) - blacklight (~> 6.14) - blacklight-gallery (~> 0.7) + blacklight (~> 7.29) + blacklight-gallery (~> 4.6.4) breadcrumbs_on_rails (~> 3.0) browse-everything (>= 0.16, < 2.0) carrierwave (~> 1.0) clipboard-rails (~> 1.5) + concurrent-ruby (= 1.3.4) + connection_pool (~> 2.4) draper (~> 4.0) - dry-equalizer (~> 0.2) - dry-events (~> 0.2.0) - dry-monads (< 1.5) - dry-struct (~> 1.0) - dry-transaction (~> 0.11) - dry-validation (~> 1.3) + dry-container (~> 0.11) + dry-events (~> 1.0, >= 1.0.1) + dry-logic (~> 1.5) + dry-monads (~> 1.6) + dry-validation (~> 1.10) flipflop (~> 2.3) flot-rails (~> 0.0.6) font-awesome-rails (~> 4.2) - hydra-derivatives (~> 3.3) - hydra-editor (~> 5.0, >= 5.0.4) - hydra-file_characterization (~> 1.1.2) - hydra-head (~> 11.0, >= 11.0.1) + google-analytics-data (~> 0.6) + hydra-derivatives (~> 4.0) + hydra-editor (~> 7.0) + hydra-file_characterization (~> 1.1) + hydra-head (~> 13.0) hydra-works (>= 0.16) iiif_manifest (>= 0.3, < 2.0) - jquery-datatables-rails (~> 3.4) - jquery-ui-rails (~> 6.0) - json-ld (< 3.2) json-schema - kaminari_route_prefix (~> 0.1.1) legato (~> 0.3) linkeddata + listen (~> 3.9) mailboxer (~> 0.12) nest (~> 3.1) - noid-rails (~> 3.0.0) + noid-rails (~> 3.0) oauth oauth2 (~> 1.2) - posix-spawn - power_converter (~> 0.1, >= 0.1.2) - psych (~> 3.3) + openseadragon (~> 0.9) qa (~> 5.5, >= 5.5.1) - rails (~> 5.0) + rails (> 6.1, < 8.0) rails_autolink (~> 1.1) rdf-rdfxml rdf-vocab (~> 3.0) @@ -522,51 +562,50 @@ GEM reform (~> 2.3) reform-rails (~> 0.2.0) retriable (>= 2.9, < 4.0) - samvera-nesting_indexer (~> 2.0) - sass-rails (~> 5.0) + sass-rails (~> 6.0) select2-rails (~> 3.5) signet + sprockets (= 3.7.2) tinymce-rails (~> 5.10) - valkyrie (~> 2, >= 2.1.1) + valkyrie (~> 3.5) + view_component (~> 2.74.1) hyrax-spec (0.3.2) rspec (~> 3.6) - i18n (1.14.4) + i18n (1.14.8) concurrent-ruby (~> 1.0) ice_nine (0.11.2) - iiif_manifest (1.3.1) + iiif_manifest (1.6.0) activesupport (>= 4) - iso-639 (0.3.6) + io-console (0.8.2) + iso-639 (0.3.8) + csv iso8601 (0.9.1) jbuilder (2.11.5) actionview (>= 5.0.0) activesupport (>= 5.0.0) jmespath (1.6.2) - jquery-datatables-rails (3.4.0) - actionpack (>= 3.1) - jquery-rails - railties (>= 3.1) - sass-rails - jquery-rails (4.6.0) + jquery-rails (4.6.1) rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) - jquery-ui-rails (6.0.1) - railties (>= 3.2.16) - json (2.6.3) - json-canonicalization (0.4.0) - json-ld (3.1.10) + json (2.18.0) + json-canonicalization (1.0.0) + json-ld (3.3.2) htmlentities (~> 4.3) - json-canonicalization (~> 0.2) + json-canonicalization (~> 1.0) link_header (~> 0.0, >= 0.0.8) - multi_json (~> 1.14) - rack (~> 2.0) - rdf (~> 3.1) - json-ld-preloaded (3.1.6) - json-ld (~> 3.1) - rdf (~> 3.1) - json-schema (4.0.0) - addressable (>= 2.8) - jwt (2.7.1) + multi_json (~> 1.15) + rack (>= 2.2, < 4) + rdf (~> 3.3) + rexml (~> 3.2) + json-ld-preloaded (3.2.2) + json-ld (~> 3.2) + rdf (~> 3.2) + json-schema (6.0.0) + addressable (~> 2.8) + bigdecimal (~> 3.1) + jwt (2.10.2) + base64 kaminari (1.2.2) activesupport (>= 4.1.0) kaminari-actionview (= 1.2.2) @@ -579,25 +618,26 @@ GEM activerecord kaminari-core (= 1.2.2) kaminari-core (1.2.2) - kaminari_route_prefix (0.1.1) - kaminari (~> 1.0) language_list (1.2.1) latex-decode (0.4.0) - launchy (2.5.2) + launchy (3.1.1) addressable (~> 2.8) - ld-patch (3.2.0) - ebnf (~> 2.2) + childprocess (~> 5.0) + logger (~> 1.6) + ld-patch (3.2.2) + ebnf (~> 2.3) rdf (~> 3.2) rdf-xsd (~> 3.2) sparql (~> 3.2) sxp (~> 1.2) - ldp (1.0.3) + ldp (1.2.0) deprecation - faraday + faraday (>= 1) http_logger - json-ld - rdf (>= 1.1) + json-ld (~> 3.2) + rdf (~> 3.2) rdf-isomorphic + rdf-ldp rdf-turtle rdf-vocab (>= 0.8) slop @@ -608,7 +648,7 @@ GEM rdf-vocab (~> 3.0) legato (0.7.0) multi_json - libxml-ruby (5.0.3) + libxml-ruby (5.0.5) link_header (0.0.8) linkeddata (3.1.6) equivalent-xml (~> 0.6) @@ -637,19 +677,20 @@ GEM shex (~> 0.6, >= 0.6.4) sparql (~> 3.1, >= 3.1.8) sparql-client (~> 3.1, >= 3.1.2) - listen (3.7.1) + listen (3.9.0) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) - logger (1.5.3) + logger (1.7.0) lograge (0.14.0) actionpack (>= 4) activesupport (>= 4) railties (>= 4) request_store (~> 1.0) - loofah (2.22.0) + loofah (2.25.0) crass (~> 1.0.2) nokogiri (>= 1.12.0) - mail (2.8.1) + mail (2.9.0) + logger mini_mime (>= 0.1.1) net-imap net-pop @@ -657,78 +698,87 @@ GEM mailboxer (0.15.1) carrierwave (>= 0.5.8) rails (>= 5.0.0) - marcel (1.0.4) - matrix (0.4.2) - memoist (0.16.2) - method_source (1.0.0) - mime-types (3.4.1) - mime-types-data (~> 3.2015) - mime-types-data (3.2023.0218.1) - mini_magick (4.12.0) + marcel (1.1.0) + matrix (0.4.3) + method_source (1.1.0) + mime-types (3.7.0) + logger + mime-types-data (~> 3.2025, >= 3.2025.0507) + mime-types-data (3.2026.0113) + mini_magick (4.13.2) mini_mime (1.1.5) - mini_portile2 (2.8.5) - minitest (5.22.3) - msgpack (1.7.1) - multi_json (1.15.0) - multi_xml (0.6.0) - multipart-post (2.4.0) - namae (1.1.1) + mini_portile2 (2.8.9) + minitest (6.0.1) + prism (~> 1.5) + msgpack (1.8.0) + multi_json (1.20.1) + multi_xml (0.7.2) + bigdecimal (~> 3.1) + multipart-post (2.4.1) + mutex_m (0.3.0) + namae (1.2.0) + racc (~> 1.7) nest (3.2.0) redic - net-http-persistent (4.0.2) - connection_pool (~> 2.2) - net-imap (0.4.10) + net-http (0.9.1) + uri (>= 0.11.1) + net-http-persistent (4.0.6) + connection_pool (~> 2.2, >= 2.2.4) + net-imap (0.6.2) date net-protocol net-pop (0.1.2) net-protocol net-protocol (0.2.2) timeout - net-smtp (0.4.0.1) + net-smtp (0.5.1) net-protocol - nio4r (2.7.0) + nio4r (2.7.5) noid (0.9.0) - noid-rails (3.0.3) - actionpack (>= 5.0.0, < 7) + noid-rails (3.3.0) + actionpack (>= 5.0.0, < 9) noid (~> 0.9) - nokogiri (1.15.6) + nokogiri (1.19.0) mini_portile2 (~> 2.8.2) racc (~> 1.4) non-digest-assets (2.2.0) activesupport (>= 5.2, < 7.1) sprockets (>= 2.0, < 5.0) - oai (0.4.0) + oai (1.3.0) builder (>= 3.1.0) - faraday - faraday_middleware - oauth (1.1.0) - oauth-tty (~> 1.0, >= 1.0.1) + faraday (< 3) + faraday-follow_redirects (>= 0.3.0, < 2) + rexml + oauth (1.1.2) + oauth-tty (~> 1.0, >= 1.0.6) snaky_hash (~> 2.0) - version_gem (~> 1.1) - oauth-tty (1.0.5) - version_gem (~> 1.1, >= 1.1.1) + version_gem (~> 1.1, >= 1.1.9) + oauth-tty (1.0.6) + version_gem (~> 1.1, >= 1.1.9) oauth2 (1.4.11) faraday (>= 0.17.3, < 3.0) jwt (>= 1.0, < 3.0) multi_json (~> 1.3) multi_xml (~> 0.5) rack (>= 1.2, < 4) - okcomputer (1.18.5) - openseadragon (0.6.0) - rails (> 3.2.0) + okcomputer (1.18.6) + openseadragon (0.9.0) + rails (> 6.1.0) orm_adapter (0.5.0) os (1.1.4) - parallel (1.23.0) - parser (3.2.2.3) + ostruct (0.6.3) + parallel (1.27.0) + parser (3.3.9.0) ast (~> 2.4.1) racc parslet (2.0.0) - pg (1.5.4) + pg (1.5.9) + popper_js (1.16.1) posix-spawn (0.3.15) - power_converter (0.1.2) + prism (1.5.2) psych (3.3.4) - public_suffix (5.0.3) - puma (6.4.2) + public_suffix (7.0.2) + puma (6.4.3) nio4r (~> 2.0) qa (5.15.0) activerecord-import @@ -740,63 +790,74 @@ GEM rails (>= 5.0, < 8.1) rdf raabro (1.4.0) - racc (1.7.3) - rack (2.2.8.1) + racc (1.8.1) + rack (2.2.21) rack-cas (0.16.1) addressable (~> 2.3) nokogiri (~> 1.5) rack (>= 1.3) - rack-protection (3.0.6) - rack - rack-test (2.1.0) + rack-protection (3.2.0) + base64 (>= 0.1.0) + rack (~> 2.2, >= 2.2.4) + rack-test (2.2.0) rack (>= 1.3) - rails (5.2.8.1) - actioncable (= 5.2.8.1) - actionmailer (= 5.2.8.1) - actionpack (= 5.2.8.1) - actionview (= 5.2.8.1) - activejob (= 5.2.8.1) - activemodel (= 5.2.8.1) - activerecord (= 5.2.8.1) - activestorage (= 5.2.8.1) - activesupport (= 5.2.8.1) - bundler (>= 1.3.0) - railties (= 5.2.8.1) + rails (6.1.7.10) + actioncable (= 6.1.7.10) + actionmailbox (= 6.1.7.10) + actionmailer (= 6.1.7.10) + actionpack (= 6.1.7.10) + actiontext (= 6.1.7.10) + actionview (= 6.1.7.10) + activejob (= 6.1.7.10) + activemodel (= 6.1.7.10) + activerecord (= 6.1.7.10) + activestorage (= 6.1.7.10) + activesupport (= 6.1.7.10) + bundler (>= 1.15.0) + railties (= 6.1.7.10) sprockets-rails (>= 2.0.0) rails-controller-testing (1.0.5) actionpack (>= 5.0.1.rc1) actionview (>= 5.0.1.rc1) activesupport (>= 5.0.1.rc1) - rails-dom-testing (2.2.0) + rails-dom-testing (2.3.0) activesupport (>= 5.0.0) minitest nokogiri (>= 1.6) - rails-html-sanitizer (1.6.0) + rails-html-sanitizer (1.6.2) loofah (~> 2.21) - nokogiri (~> 1.14) + nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0) rails_autolink (1.1.8) actionview (> 3.1) activesupport (> 3.1) railties (> 3.1) - railties (5.2.8.1) - actionpack (= 5.2.8.1) - activesupport (= 5.2.8.1) + railties (6.1.7.10) + actionpack (= 6.1.7.10) + activesupport (= 6.1.7.10) method_source - rake (>= 0.8.7) - thor (>= 0.19.0, < 2.0) + rake (>= 12.2) + thor (~> 1.0) rainbow (3.1.1) - rake (13.1.0) + rake (13.3.1) rb-fsevent (0.11.2) - rb-inotify (0.10.1) + rb-inotify (0.11.1) ffi (~> 1.0) - rdf (3.2.11) + rdf (3.3.4) + bcp47_spec (~> 0.2) + bigdecimal (~> 3.1, >= 3.1.5) link_header (~> 0.0, >= 0.0.8) + logger (~> 1.5) + ostruct (~> 0.6) + readline (~> 0.0) rdf-aggregate-repo (3.2.1) rdf (~> 3.2) - rdf-isomorphic (3.2.1) - rdf (~> 3.2) + rdf-isomorphic (3.3.0) + rdf (~> 3.3) rdf-json (3.2.0) rdf (~> 3.2) + rdf-ldp (0.1.0) + deprecation + rdf rdf-microdata (3.2.1) htmlentities (~> 4.3) nokogiri (~> 1.13) @@ -812,7 +873,7 @@ GEM rdf (~> 3.2) rdf-ordered-repo (3.2.1) rdf (~> 3.2, >= 3.2.1) - rdf-rdfa (3.2.2) + rdf-rdfa (3.2.3) haml (>= 5.2, < 7) htmlentities (~> 4.3) rdf (~> 3.2) @@ -827,28 +888,30 @@ GEM rdf-reasoner (0.8.0) rdf (~> 3.2) rdf-xsd (~> 3.2) - rdf-tabular (3.1.1) - addressable (~> 2.3) + rdf-tabular (3.2.1) + addressable (~> 2.8) bcp47 (~> 0.3, >= 0.3.3) - json-ld (~> 3.1) - rdf (~> 3.1) - rdf-vocab (~> 3.1) - rdf-xsd (~> 3.1) - rdf-trig (3.2.0) - ebnf (~> 2.2) - rdf (~> 3.2) - rdf-turtle (~> 3.2) + json-ld (~> 3.2) + rdf (~> 3.2, >= 3.2.7) + rdf-vocab (~> 3.2) + rdf-xsd (~> 3.2) + rdf-trig (3.3.0) + ebnf (~> 2.4) + rdf (~> 3.3) + rdf-turtle (~> 3.3) rdf-trix (3.2.0) rdf (~> 3.2) rdf-xsd (~> 3.2) - rdf-turtle (3.2.1) - ebnf (~> 2.3) - rdf (~> 3.2) - rdf-vocab (3.2.7) - rdf (~> 3.2, >= 3.2.4) + rdf-turtle (3.3.0) + ebnf (~> 2.4) + rdf (~> 3.3) + rdf-vocab (3.3.3) + rdf (~> 3.3) rdf-xsd (3.2.1) rdf (~> 3.2) rexml (~> 3.2) + readline (0.0.4) + reline redic (1.5.3) hiredis redis (4.5.1) @@ -856,44 +919,46 @@ GEM redis (>= 4) redlock (1.3.2) redis (>= 3.0.0, < 6.0) - reform (2.5.0) - disposable (>= 0.4.2, < 0.5.0) - representable (>= 2.4.0, < 3.1.0) + reform (2.6.2) + disposable (>= 0.5.0, < 1.0.0) + representable (>= 3.1.1, < 4) uber (< 0.2.0) - reform-rails (0.2.5) + reform-rails (0.2.6) activemodel (>= 5.0) reform (>= 2.3.1, < 3.0.0) - regexp_parser (2.8.1) - representable (3.0.4) + regexp_parser (2.11.3) + reline (0.6.3) + io-console (~> 0.5) + representable (3.2.0) declarative (< 0.1.0) - declarative-option (< 0.2.0) + trailblazer-option (>= 0.1.1, < 0.2.0) uber (< 0.2.0) - request_store (1.5.1) + request_store (1.7.0) rack (>= 1.4) - responders (3.1.0) + responders (3.1.1) actionpack (>= 5.2) railties (>= 5.2) retriable (3.1.2) - rexml (3.2.6) + rexml (3.4.4) roman (0.2.0) rsolr (2.5.0) builder (>= 2.1.2) faraday (>= 0.9, < 3, != 2.0.0) - rspec (3.12.0) - rspec-core (~> 3.12.0) - rspec-expectations (~> 3.12.0) - rspec-mocks (~> 3.12.0) - rspec-core (3.12.2) - rspec-support (~> 3.12.0) - rspec-expectations (3.12.3) + rspec (3.13.1) + rspec-core (~> 3.13.0) + rspec-expectations (~> 3.13.0) + rspec-mocks (~> 3.13.0) + rspec-core (3.13.6) + rspec-support (~> 3.13.0) + rspec-expectations (3.13.5) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.12.0) - rspec-its (1.3.0) + rspec-support (~> 3.13.0) + rspec-its (1.3.1) rspec-core (>= 3.0.0) rspec-expectations (>= 3.0.0) - rspec-mocks (3.12.6) + rspec-mocks (3.13.6) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.12.0) + rspec-support (~> 3.13.0) rspec-rails (5.1.2) actionpack (>= 5.2) activesupport (>= 5.2) @@ -902,7 +967,7 @@ GEM rspec-expectations (~> 3.10) rspec-mocks (~> 3.10) rspec-support (~> 3.10) - rspec-support (3.12.1) + rspec-support (3.13.6) rspec_junit_formatter (0.4.1) rspec-core (>= 2, < 4, != 2.12.0) rubocop (1.28.2) @@ -914,9 +979,10 @@ GEM rubocop-ast (>= 1.17.0, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 1.4.0, < 3.0) - rubocop-ast (1.29.0) - parser (>= 3.2.1.0) - rubocop-performance (1.18.0) + rubocop-ast (1.47.1) + parser (>= 3.3.7.2) + prism (~> 1.4) + rubocop-performance (1.19.1) rubocop (>= 1.7.0, < 2.0) rubocop-ast (>= 0.4.0) rubocop-rails (2.15.2) @@ -931,43 +997,41 @@ GEM multipart-post oauth2 ruby-progressbar (1.13.0) + ruby-vips (2.3.0) + ffi (~> 1.12) + logger ruby2_keywords (0.0.5) rubyzip (2.3.2) - samvera-nesting_indexer (2.0.0) - dry-equalizer - sass (3.7.4) - sass-listen (~> 4.0.0) - sass-listen (4.0.0) - rb-fsevent (~> 0.9, >= 0.9.4) - rb-inotify (~> 0.9, >= 0.9.7) - sass-rails (5.1.0) - railties (>= 5.2.0) - sass (~> 3.1) - sprockets (>= 2.8, < 4.0) - sprockets-rails (>= 2.0, < 4.0) - tilt (>= 1.1, < 3) + sass-rails (6.0.0) + sassc-rails (~> 2.1, >= 2.1.1) sassc (2.4.0) ffi (~> 1.9) + sassc-rails (2.1.2) + railties (>= 4.0.0) + sassc (>= 2.0) + sprockets (> 3.0) + sprockets-rails + tilt scanf (1.0.0) select2-rails (3.5.11) selenium-webdriver (4.9.0) rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2, < 3.0) websocket (~> 1.0) - shacl (0.1.1) - json-ld (~> 3.1, >= 3.1.7) - rdf (~> 3.1, >= 3.1.8) - sparql (~> 3.1) - sxp (~> 1.1) - shex (0.6.4) - ebnf (~> 2.1, >= 2.2) + shacl (0.3.0) + json-ld (~> 3.2) + rdf (~> 3.2, >= 3.2.8) + sparql (~> 3.2, >= 3.2.4) + sxp (~> 1.2) + shex (0.7.1) + ebnf (~> 2.2) htmlentities (~> 4.3) - json-ld (~> 3.1) - json-ld-preloaded (~> 3.1) - rdf (~> 3.1) - rdf-xsd (~> 3.1) - sparql (~> 3.1) - sxp (~> 1.1) + json-ld (~> 3.2) + json-ld-preloaded (~> 3.2) + rdf (~> 3.2) + rdf-xsd (~> 3.2) + sparql (~> 3.2) + sxp (~> 1.2) shoulda-matchers (4.5.1) activesupport (>= 4.2.0) sidekiq (5.2.10) @@ -978,10 +1042,10 @@ GEM sidekiq-cron (1.9.1) fugit (~> 1.8) sidekiq (>= 4.2.1) - signet (0.17.0) + signet (0.21.0) addressable (~> 2.8) faraday (>= 0.17.5, < 3.a) - jwt (>= 1.5, < 3.0) + jwt (>= 1.5, < 4.0) multi_json (~> 1.10) simple_form (5.1.0) actionpack (>= 5.2) @@ -990,35 +1054,35 @@ GEM docile (~> 1.1) simplecov-html (~> 0.11) simplecov_json_formatter (~> 0.1) - simplecov-cobertura (2.1.0) + simplecov-cobertura (3.1.0) rexml simplecov (~> 0.19) - simplecov-html (0.12.3) + simplecov-html (0.13.2) simplecov_json_formatter (0.1.4) - slack-ruby-client (0.14.6) - activesupport - faraday (>= 0.9) - faraday_middleware + slack-ruby-client (3.0.0) + faraday (>= 2.0.1) + faraday-mashify + faraday-multipart gli hashie - websocket-driver + logger slop (4.10.1) - snaky_hash (2.0.1) - hashie - version_gem (~> 1.1, >= 1.1.1) - sorbet-runtime (0.5.11463) - sparql (3.2.5) - builder (~> 3.2) - ebnf (~> 2.2, >= 2.3.1) + snaky_hash (2.0.3) + hashie (>= 0.1.0, < 6) + version_gem (>= 1.1.8, < 3) + sorbet-runtime (0.5.12443) + sparql (3.2.6) + builder (~> 3.2, >= 3.2.4) + ebnf (~> 2.3, >= 2.3.5) logger (~> 1.5) - rdf (~> 3.2, >= 3.2.8) - rdf-aggregate-repo (~> 3.2) + rdf (~> 3.2, >= 3.2.11) + rdf-aggregate-repo (~> 3.2, >= 3.2.1) rdf-xsd (~> 3.2) - sparql-client (~> 3.2, >= 3.2.1) - sxp (~> 1.2, >= 1.2.2) - sparql-client (3.2.1) - net-http-persistent (~> 4.0, >= 4.0.1) - rdf (~> 3.2, >= 3.2.6) + sparql-client (~> 3.2, >= 3.2.2) + sxp (~> 1.2, >= 1.2.4) + sparql-client (3.2.2) + net-http-persistent (~> 4.0, >= 4.0.2) + rdf (~> 3.2, >= 3.2.11) spring (2.1.1) spring-watcher-listen (2.0.1) listen (>= 2.7, < 4.0) @@ -1030,50 +1094,48 @@ GEM babel-source (>= 5.8.11) babel-transpiler sprockets (>= 3.0.0) - sprockets-rails (3.4.2) - actionpack (>= 5.2) - activesupport (>= 5.2) + sprockets-rails (3.5.2) + actionpack (>= 6.1) + activesupport (>= 6.1) sprockets (>= 3.0.0) ssrf_filter (1.0.8) stub_env (1.0.4) rspec (>= 2.0, < 4.0) - sxp (1.2.4) + sxp (1.3.0) matrix (~> 0.4) - rdf (~> 3.2) - temple (0.10.3) - terminal-table (3.0.2) - unicode-display_width (>= 1.1.1, < 3) - thor (1.3.1) - thread_safe (0.3.6) - tilt (2.3.0) - timeout (0.4.1) - tinymce-rails (5.10.7.1) + rdf (~> 3.3) + temple (0.10.4) + terminal-table (4.0.0) + unicode-display_width (>= 1.1.1, < 4) + terser (1.2.7) + execjs (>= 0.3.0, < 3) + thor (1.5.0) + tilt (2.6.1) + timeout (0.6.0) + tinymce-rails (5.10.9) railties (>= 3.1.1) + trailblazer-option (0.1.2) turbolinks (5.2.1) turbolinks-source (~> 5.2) turbolinks-source (5.2.0) - twitter-typeahead-rails (0.11.1.pre.corejavascript) + twitter-typeahead-rails (0.11.1) actionpack (>= 3.1) jquery-rails railties (>= 3.1) - typhoeus (1.4.0) - ethon (>= 0.9.0) - tzinfo (1.2.11) - thread_safe (~> 0.1) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) uber (0.1.0) - uglifier (4.2.0) - execjs (>= 0.3.0, < 3) - unicode-display_width (2.4.2) - unicode-types (1.8.0) + unicode-display_width (2.6.0) + unicode-types (1.11.0) + uri (1.1.1) validatable (1.6.7) - valkyrie (2.2.0) + valkyrie (3.5.0) activemodel activesupport - disposable (~> 0.4.5) - draper dry-struct dry-types (~> 1.0) - faraday (< 1.0) + faraday (>= 0.9, < 3, != 2.0.0) + faraday-multipart json json-ld railties @@ -1081,24 +1143,28 @@ GEM rdf-vocab reform (~> 2.2) reform-rails - version_gem (1.1.3) + version_gem (1.1.9) + view_component (2.74.1) + activesupport (>= 5.0.0, < 8.0) + concurrent-ruby (~> 1.0) + method_source (~> 1.0) wapiti (2.1.0) builder (~> 3.2) rexml (~> 3.0) warden (1.2.9) rack (>= 2.0.9) - webmock (3.19.1) + webmock (3.25.1) addressable (>= 2.8.0) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) - webrick (1.8.1) - websocket (1.2.10) - websocket-driver (0.7.6) + websocket (1.2.11) + websocket-driver (0.8.0) + base64 websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.6.13) + zeitwerk (2.7.4) PLATFORMS ruby @@ -1109,12 +1175,13 @@ DEPENDENCIES aws-sdk-s3 (~> 1.142.0) bagit (~> 0.6.0) bixby (~> 5.0.1) - blacklight_advanced_search (~> 6.4.1) - blacklight_oai_provider (~> 6.0.0) - blacklight_range_limit (~> 6.3.3) + blacklight_advanced_search (~> 7.0.0) + blacklight_oai_provider (~> 7.0.2) + blacklight_range_limit (~> 8.5.0) bootsnap (~> 1.17) - browse-everything (~> 1.1.2) - bulkrax (~> 9.0.2) + bootstrap (~> 4.0) + browse-everything (~> 1.6.0) + bulkrax (~> 9.3.3) byebug (~> 11.1.3) capybara (~> 3.38) capybara-screenshot (~> 1.0.26) @@ -1128,27 +1195,29 @@ DEPENDENCIES edtf-humanize (~> 2.1.0) equivalent-xml (~> 0.6.0) factory_bot_rails (~> 6) - faraday (~> 0.17.6) + faraday (~> 2.0) ffprober honeybadger (~> 4.12.1) hydra-role-management (~> 1.1.0) - hyrax (~> 3.6.0) + hyrax (~> 5.2.0) hyrax-spec (~> 0.3.2) iso-639 (~> 0.3.6) jbuilder (~> 2.11.5) jquery-rails (~> 4.6.0) kaminari (~> 1.2.2) linkeddata (~> 3.1.6) - listen (>= 3.0.5, < 3.8) + listen (~> 3.9.0) lograge - mini_magick (~> 4.11) + multi_json (~> 1.20.1) non-digest-assets (~> 2.2.0) okcomputer (~> 1.18.5) + openseadragon (~> 0.9.0) pg (~> 1.5.4) + posix-spawn puma (~> 6.4.0) - rails (~> 5.2.7) + rails (~> 6.1) rails-controller-testing (~> 1.0.5) - rdf-vocab (~> 3.2.7) + rdf-vocab (~> 3.3.3) redlock (>= 0.1.2, < 2.0) rsolr (~> 2.5.0) rspec (~> 3.10) @@ -1156,21 +1225,22 @@ DEPENDENCIES rspec-rails (~> 5.1) rspec_junit_formatter (~> 0.4.1) rubyzip (~> 2.3.2) - sass-rails (~> 5.1.0) + sass-rails (~> 6.0) selenium-webdriver shoulda-matchers (~> 4) sidekiq (~> 5.2.9) sidekiq-cron (~> 1.9.1) simple_form (< 5.2) simplecov (~> 0.22.0) - simplecov-cobertura (~> 2.1) - slack-ruby-client (~> 0.14.6) + simplecov-cobertura (~> 3) + slack-ruby-client spring (~> 2.1.1) spring-watcher-listen (~> 2.0.0) sprockets-es6 (~> 0.9.2) stub_env (~> 1.0.4) + terser (~> 1.2.7) turbolinks (~> 5.2.1) - uglifier (~> 4.2.0) + twitter-typeahead-rails (~> 0.11.1) webmock (~> 3.8) BUNDLED WITH diff --git a/app/actors/spot/actors/collections_membership_actor.rb b/app/actors/spot/actors/collections_membership_actor.rb index 22f414f76..da6102090 100644 --- a/app/actors/spot/actors/collections_membership_actor.rb +++ b/app/actors/spot/actors/collections_membership_actor.rb @@ -26,8 +26,6 @@ def add(env, id) col = collection_stack.shift next if collection_ids.include?(col.id) - col.reindex_extent = Hyrax::Adapters::NestingIndexAdapter::LIMITED_REINDEX - collection_ids << col.id env.curation_concern.member_of_collections << col collection_stack += col.member_of_collections diff --git a/app/assets/config/manifest.js b/app/assets/config/manifest.js index b16e53d6d..75466dd08 100644 --- a/app/assets/config/manifest.js +++ b/app/assets/config/manifest.js @@ -1,3 +1,5 @@ //= link_tree ../images //= link_directory ../javascripts .js //= link_directory ../stylesheets .css + +//= link blacklight_gallery/manifest.js \ No newline at end of file diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 7e6b2f8dc..15718ad85 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -13,26 +13,34 @@ //= require turbolinks // Required by Blacklight -//= require jquery +//= require jquery3 +//= require rails-ujs + +//= require popper +//= require twitter/typeahead +//= require bootstrap + +//= require jquery.dataTables +//= require dataTables.bootstrap4 +//= require blacklight/blacklight //= require blacklight_advanced_search //= require blacklight_range_limit -//= require jquery_ujs -//= require dataTables/jquery.dataTables -//= require dataTables/bootstrap/3/jquery.dataTables.bootstrap -//= require blacklight/blacklight -// local require that in turn calls a require -//= require blacklight_gallery +//= require blacklight_gallery/default +//= require blacklight_gallery/osd_viewer + +// require openseadragon +//= require openseadragon/openseadragon +//= require openseadragon/rails -//= require openseadragon //= require hyrax //= require almond // Bulkrax //= require bulkrax/application -//= require browse_everything //= require spot/editor/multi_auth_controlled_vocabulary +//= require spot/hyrax_overrides //= require language-tagged-autocomplete-setup //= require multi-auth-input //= require workflow-action-form-validation diff --git a/app/assets/javascripts/blacklight_gallery.js b/app/assets/javascripts/blacklight_gallery.js deleted file mode 100644 index 992a7d4df..000000000 --- a/app/assets/javascripts/blacklight_gallery.js +++ /dev/null @@ -1 +0,0 @@ -//= require blacklight_gallery/default \ No newline at end of file diff --git a/app/assets/javascripts/openseadragon.js b/app/assets/javascripts/openseadragon.js deleted file mode 100644 index 2ab91a9f1..000000000 --- a/app/assets/javascripts/openseadragon.js +++ /dev/null @@ -1,2 +0,0 @@ -//= require openseadragon/openseadragon -//= require openseadragon/rails \ No newline at end of file diff --git a/app/assets/javascripts/spot/hyrax_overrides.js b/app/assets/javascripts/spot/hyrax_overrides.js new file mode 100644 index 000000000..2b1d42a3d --- /dev/null +++ b/app/assets/javascripts/spot/hyrax_overrides.js @@ -0,0 +1,13 @@ +// This file is for overriding defaul hyrax js behavior. + +$(document).ready(() => { + if ($('#permissions_error_text').text() === '') { + $('#permissions_error').attr('hidden', ''); + } + + $('#file-upload-cancel-btn').attr('hidden', ''); + + $('#fileupload').on('fileuploadstop', () => { + $('#file-upload-cancel-btn').attr('hidden', ''); + }) +}); \ No newline at end of file diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 5e6f25936..e35bc7138 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -15,8 +15,8 @@ // //= require hyrax //= require openseadragon -//= require dataTables/bootstrap/3/jquery.dataTables.bootstrap -//= require 'bulkrax/application' +//= require dataTables.bootstrap4 +//= require bulkrax/application // //= require spot //= require_self @@ -27,29 +27,13 @@ background: #fff image-url("spinner-24.gif") right center no-repeat; } -.work-show dd { - margin-left: 0; -} - -.work-representative-media { - margin-bottom: 1rem; - margin-top: 1rem; -} - -.attribute-identifier-with-label { - margin-bottom: 0.5rem; - margin-top: 0.5rem; -} - -// undoing `max-width: 40em` that hydra-editor sets; -// scss-lint:disable SelectorFormat -.multi_value .listing, -.controlled_vocabulary .listing { - max-width: 100%; -} -// scss-lint:enable SelectorFormat - .full-text-excerpt { font-size: 1.4rem; font-style: italic; } + +// fix for the dashboard Admin Sets subheading, which is just kinda smushed in there +.main-content #admin_sets .card-subtitle { + margin-top: 0.5rem; + margin-bottom: 0.5rem; +} diff --git a/app/assets/stylesheets/hyrax.scss b/app/assets/stylesheets/hyrax.scss index 2baaa74e2..bfec41942 100644 --- a/app/assets/stylesheets/hyrax.scss +++ b/app/assets/stylesheets/hyrax.scss @@ -1,14 +1,13 @@ // our own overrides are called _before_ we import hyrax/bootstrap @import "spot/variables"; -@import "bootstrap-compass"; -@import "bootstrap-sprockets"; +// @import "bootstrap-compass"; @import "bootstrap-default-overrides"; @import 'bootstrap'; @import 'blacklight/blacklight'; @import "font-awesome"; -@import "blacklight_gallery/gallery"; @import "blacklight_gallery/masonry"; @import "blacklight_gallery/slideshow"; @import "blacklight_gallery/osd_viewer"; +@import "hyrax/blacklight_gallery"; @import 'hyrax/hyrax'; diff --git a/app/assets/stylesheets/spot.scss b/app/assets/stylesheets/spot.scss index 7d6e538b3..64508a35c 100644 --- a/app/assets/stylesheets/spot.scss +++ b/app/assets/stylesheets/spot.scss @@ -1,140 +1,6 @@ @import "spot/variables"; -@import "spot/navbar"; +@import "spot/global"; @import "spot/homepage"; -@import "spot/multi-auth-controlled-vocab"; -@import "spot/audio"; - -.rights-statement-icon { - max-width: 120px; -} - -.panel-heading-slim { - padding: 4px 15px; - padding-left: 8px; // TODO: this is a magic number; what's the value in bootstrap? - - h5, - h6 { - margin-bottom: 0; - margin-top: 0; - } -} - -.splash-image { - margin: 0.5em auto; -} - -[role="main"] { - margin-top: 1rem; - padding-bottom: 10rem; -} - -.dashboard > [role="main"] { - margin-top: 0; -} - -.thumbnail.file-set { - margin: auto; - max-width: 250px; -} - -.ldr-logo img { - height: 50px; -} - -// bootstrap is very specific in targeting table cells, -// so we also need to be that specific to override -.metadata-table > tbody > tr { - > td, - > th { - vertical-align: middle; - } -} - -// collection overrides -.hyc-banner { - min-height: 200px; - - .hyc-title { - background-color: $red-light; - border-bottom-left-radius: inherit; - border-top-right-radius: inherit; - bottom: 0; - position: absolute; - } -} - -.collection-list-item { - .thumbnail img { - height: 200px; - } -} - -// give some breathing room to collection items w/ thumbnails in search results -.search-result-wrapper { - padding-bottom: 1rem; -} - -.site-footer { - background-color: $tan-light; - height: 20rem; -} - -// duplicating styles from #facet-panel-collapse -// otherwise the panel will not display -#admin-facet-panel-collapse { - display: block !important; - height: auto !important; - overflow: visible !important; - padding-bottom: 0; -} - -select[multiple] { - min-height: 15rem; -} - -// styling the iiif viewer iframe to fill the space -.viewer-wrapper iframe { - height: 100%; - width: 100%; -} - -.collection-list-item { - .collection-logo-container { - background-position: center center; - background-repeat: no-repeat; - background-size: contain; - height: 300px; - margin: 1em; - } - - .thumbnail .caption { - min-height: 2em; - } - - .collection-counts-wrapper { - margin: 1em auto; - } - - .collection-counts-item { - background-color: #f5f5f5; - color: #666; - display: inline-block; - font-size: 13px; - font-weight: bold; - margin-left: 10px; - padding: 8px; - text-align: center; - width: 100%; - - &:first-child { - margin-left: 0; - } - - span { - display: block; - font-size: 18px; - font-weight: normal; - line-height: 1; - } - } -} +@import "spot/works"; +@import "spot/collections"; +@import "spot/forms"; \ No newline at end of file diff --git a/app/assets/stylesheets/spot/_audio.scss b/app/assets/stylesheets/spot/_audio.scss deleted file mode 100644 index c2b8c4a0e..000000000 --- a/app/assets/stylesheets/spot/_audio.scss +++ /dev/null @@ -1,24 +0,0 @@ -.play-list { - .play-list-row { - .track-title { - .playlist-track { - &:hover { - text-decoration: underline; - } - color: #000; - text-decoration: none; - } - } - .track-title { - .playlist-track { - text-decoration: none; - &:hover { - text-decoration: underline; - } - } - } - .track-title.active-track { - font-weight: bold; - } - } -} \ No newline at end of file diff --git a/app/assets/stylesheets/spot/_collections.scss b/app/assets/stylesheets/spot/_collections.scss new file mode 100644 index 000000000..4219bc373 --- /dev/null +++ b/app/assets/stylesheets/spot/_collections.scss @@ -0,0 +1,82 @@ +/// +// Collection overrides +/// +.hyc-banner { + min-height: 200px; + + .hyc-title { + background-color: $red-light; + border-bottom-left-radius: inherit; + border-top-right-radius: inherit; + bottom: 0; + position: absolute; + } +} + +.collection-list-item .thumbnail img { + height: 200px; +} + +// give some breathing room to collection items w/ thumbnails in search results +.search-result-wrapper { + padding-bottom: 1rem; +} + +// duplicating styles from #facet-panel-collapse +// otherwise the panel will not display +#admin-facet-panel-collapse { + display: block !important; + height: auto !important; + overflow: visible !important; + padding-bottom: 0; +} + +#accordion .card { + margin-bottom: .5rem; +} + +.collection-list-item { + .collection-logo-container { + background-position: center center; + background-repeat: no-repeat; + background-size: contain; + height: 300px; + margin: 1em; + } + + .card .card-body { + text-align: center; + + .card-title { + min-height: 2em; + font-size: 24px; + } + } + + .collection-counts-wrapper { + margin: 1em auto; + } + + .collection-counts-item { + background-color: #f5f5f5; + color: #666; + display: inline-block; + font-size: 13px; + font-weight: bold; + margin-left: 10px; + padding: 8px; + text-align: center; + width: 100%; + + &:first-child { + margin-left: 0; + } + + span { + display: block; + font-size: 18px; + font-weight: normal; + line-height: 1; + } + } +} diff --git a/app/assets/stylesheets/spot/_forms.scss b/app/assets/stylesheets/spot/_forms.scss new file mode 100644 index 000000000..68452fcdf --- /dev/null +++ b/app/assets/stylesheets/spot/_forms.scss @@ -0,0 +1,94 @@ +/// +// Form-related stylings +/// +select[multiple] { + min-height: 15rem; +} + +// these are adjustments we need to make to the multi-authority controlled vocabulary +// inputs so that they resemble their '.multi_value' or '.controlled_vocabulary' siblings. +.multi_auth_controlled_vocabulary { + .listing { + margin-bottom: 0; + margin-left: 0; + max-width: 100%; + padding-left: 0; + } + + .btn { + &.add { + padding-left: 0; + } + + &.remove { + color: #d33a35; + } + + &.add, + &.remove { + text-decoration: underline; + } + } + + .add .glyphicon-plus, + .remove .glyphicon-remove { + margin-right: 0.3rem; + } +} + +// undoing `max-width: 40em` that hydra-editor sets; +// scss-lint:disable SelectorFormat +.multi_value .listing, +.controlled_vocabulary .listing { + max-width: 100%; +} +// scss-lint:enable SelectorFormat + +.multi_value .listing li:first-of-type { + width: 84%; +} + +.multi_value{ + &.language_tagged .listing li:first-of-type { + width: 100%; + } +} + +.control-label { + .required-tag { + vertical-align: baseline; + } +} + +.language_tagged li.field-wrapper .row { + width: 84%; +} + +.language_tagged .row .col-sm-2 { + padding-left: 0px; +} + +.language_tagged li.field-wrapper .row .col-sm-2 { + padding-left: 0px; + padding-right: 0px; +} + +.table caption { + caption-side: top; +} + +.controlled_vocabulary .listing li .remove { + display: inline-block; +} + +.controlled_vocabulary .listing li:first-of-type .remove { + display: none; +} + +.multi_auth_controlled_vocabulary .listing li:first-of-type .remove { + display: none; +} + +.controlled_vocabulary .listing li:first-of-type { + width: 84%; +} \ No newline at end of file diff --git a/app/assets/stylesheets/spot/_global.scss b/app/assets/stylesheets/spot/_global.scss new file mode 100644 index 000000000..9b15a29db --- /dev/null +++ b/app/assets/stylesheets/spot/_global.scss @@ -0,0 +1,73 @@ +/// +// global site overrides +/// + +// flip Bootstrap's defaults back to not underlining links unless hovered. +a { + text-decoration: none; + + &:hover { text-decoration: underline; } +} + +// padding-bottom gives us plenty of spacing to prevent the +// footer from displaying on top of any page content. +#content-wrapper { + margin-top: 2rem; + padding-bottom: 10rem !important; +} + +// adjust content-wrapper margin specifically for the dashboard views +body.dashboard { + #content-wrapper { + margin-top: -4px; + } +} + +/// +// masthead / navbar stylings +/// + +#masthead { // scss-lint:disable IdSelector + background-color: $red-light; + border-bottom: 0; + padding: 0.06rem 0.25rem; + + @media(min-width: 768px) { + #search-field-header { // scss-lint:disable IdSelector + width: 50rem; + } + } +} + +#user_utility_links a.nav-link { + color: $white; +} + +.ldr-logo { + margin-left: 0.5rem; + + img { + height: 50px; + } +} + +/// +// Footer bits and bobs +/// +.site-footer { + background-color: $tan-light; + font-size: 0.85rem; + min-height: 180px; +} + + +/// +// Bootstrap overrides (should these be in a separate file?) +/// +a.badge { + text-decoration: none; +} + +.facets .card { + margin-bottom: 5px; +} \ No newline at end of file diff --git a/app/assets/stylesheets/spot/_homepage.scss b/app/assets/stylesheets/spot/_homepage.scss index 3e7d25779..b13937810 100644 --- a/app/assets/stylesheets/spot/_homepage.scss +++ b/app/assets/stylesheets/spot/_homepage.scss @@ -1,10 +1,15 @@ +/// +// Styles related to the homepage pieces +/// + $featured-info-bg-color: rgba(0, 0, 0, 0.7); $featured-info-text-color: $white; .welcome-splash { background-position: top center; background-size: cover; - min-height: 50rem; + min-height: 32rem; + padding-bottom: 4rem; position: relative; } @@ -12,8 +17,8 @@ $featured-info-text-color: $white; background-color: $featured-info-bg-color; bottom: 0; color: $featured-info-text-color; - margin: 4rem; - padding: 2rem; + margin: 3rem; + padding: 1rem; position: absolute; right: 0; @@ -22,9 +27,13 @@ $featured-info-text-color: $white; } } +.splash-image { + margin: 0.5em auto; +} + .featured-collection { background-size: cover; - min-height: 26rem; + min-height: 18rem; margin: 1rem 0; padding-top: 7rem; position: relative; @@ -34,7 +43,7 @@ $featured-info-text-color: $white; bottom: 0; color: $featured-info-text-color; display: block; - font-size: 1.75rem; + font-size: 1.25rem; left: 0; margin-top: 0; padding: 1rem; @@ -43,7 +52,7 @@ $featured-info-text-color: $white; } .collection-title { - font-size: 3rem; + font-size: 2rem; font-weight: normal; margin: 0.5rem 0; } @@ -66,7 +75,7 @@ $featured-info-text-color: $white; background-color: $featured-info-bg-color; bottom: 0; color: $featured-info-text-color; - font-size: 1.5rem; + font-size: 1rem; height: 33%; overflow: hidden; padding: 0.5rem; diff --git a/app/assets/stylesheets/spot/_multi-auth-controlled-vocab.scss b/app/assets/stylesheets/spot/_multi-auth-controlled-vocab.scss deleted file mode 100644 index 759026c8a..000000000 --- a/app/assets/stylesheets/spot/_multi-auth-controlled-vocab.scss +++ /dev/null @@ -1,30 +0,0 @@ -// these are adjustments we need to make to the multi-authority controlled vocabulary -// inputs so that they resemble their '.multi_value' or '.controlled_vocabulary' siblings. -.multi_auth_controlled_vocabulary { - .listing { - margin-bottom: 0; - margin-left: 0; - max-width: 100%; - padding-left: 0; - } - - .btn { - &.add { - padding-left: 0; - } - - &.remove { - color: #d33a35; - } - - &.add, - &.remove { - text-decoration: underline; - } - } - - .add .glyphicon-plus, - .remove .glyphicon-remove { - margin-right: 0.3rem; - } -} diff --git a/app/assets/stylesheets/spot/_navbar.scss b/app/assets/stylesheets/spot/_navbar.scss deleted file mode 100644 index 843bc9999..000000000 --- a/app/assets/stylesheets/spot/_navbar.scss +++ /dev/null @@ -1,12 +0,0 @@ -// styles applied to the navbar + masthead - -#masthead { // scss-lint:disable IdSelector - background-color: $red-light; - border-bottom: 0; - - @media(min-width: 768px) { - #search-field-header { // scss-lint:disable IdSelector - width: 50rem; - } - } -} diff --git a/app/assets/stylesheets/spot/_variables.scss b/app/assets/stylesheets/spot/_variables.scss index 8f202a4a1..9efaa8f4a 100644 --- a/app/assets/stylesheets/spot/_variables.scss +++ b/app/assets/stylesheets/spot/_variables.scss @@ -13,5 +13,7 @@ $black: #1e1e1e; // bootstrap overrides //// +$font-size-base: .9rem; + // navbar / masthead -$navbar-inverse-link-color: $white; +$navbar-inverse-link-color: #666; diff --git a/app/assets/stylesheets/spot/_works.scss b/app/assets/stylesheets/spot/_works.scss new file mode 100644 index 000000000..2af6ae27c --- /dev/null +++ b/app/assets/stylesheets/spot/_works.scss @@ -0,0 +1,105 @@ +/// +// Work-Show views +// - global metadata for work views +// - iiif viewer +// - a/v playlists + +// +.tab-content .form-group label { + font-weight: bolder; +} + +.panel-heading-slim { + padding: 4px 15px; + padding-left: 8px; // TODO: this is a magic number; what's the value in bootstrap? + + h5, + h6 { + margin-bottom: 0; + margin-top: 0; + } +} + +.rights-statement-icon { + max-width: 120px; +} + +.thumbnail.file-set { + margin: auto; + max-width: 250px; +} + +.thumbnail.file-set.image { + width: 100%; + height: auto; +} + +.thumbnail.collection-thumb img { + max-width: 100%; + height: auto; + object-fit: contain +} + +// bootstrap is very specific in targeting table cells, +// so we also need to be that specific to override +.metadata-table > tbody > tr { + > td, + > th { + vertical-align: middle; + } +} + +.work-show dd { + margin-left: 0; +} + +.work-representative-media { + margin-bottom: 1rem; + margin-top: 1rem; +} + +.attribute-identifier-with-label { + margin-bottom: 0.5rem; + margin-top: 0.5rem; +} + +// styling badges to default to the right on activity-log +.activity-log { + float: right; +} + +/// +// styling the iiif viewer iframe to fill the space +/// +.viewer-wrapper iframe { + height: 100%; + width: 100%; +} + +/// +// a/v playlists +/// +.play-list { + .play-list-row { + .track-title { + .playlist-track { + &:hover { + text-decoration: underline; + } + color: #000; + text-decoration: none; + } + } + .track-title { + .playlist-track { + text-decoration: none; + &:hover { + text-decoration: underline; + } + } + } + .track-title.active-track { + font-weight: bold; + } + } +} \ No newline at end of file diff --git a/app/components/spot/visibility_facet_item_component.rb b/app/components/spot/visibility_facet_item_component.rb new file mode 100644 index 000000000..7b404fd56 --- /dev/null +++ b/app/components/spot/visibility_facet_item_component.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true +module Spot + # Custom ItemComponent for Visibility facets. We want to display the PermissionBadge + # for each possibility as opposed to the plain-text value. This was previously accomplished + # using a helper method, but wrapping a span badge inside a hyperlink in Bootstrap 4 + # cuts off the text with a negative indentation. So instead we'll render an unwrapped link. + # + # @see app/presenters/spot/permission_badge.rb + class VisibilityFacetItemComponent < Blacklight::FacetItemComponent + def render_facet_value + link_to_unless(@suppress_link, + permission_badge.visibility_label, + href, + class: "facet-select badge #{permission_badge.badge_class} px-2 py-1", + rel: 'nofollow') + render_facet_count + end + + private + + def permission_badge + Spot::PermissionBadge.new(label) + end + end +end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index fa502e1f0..4ff144044 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -13,16 +13,13 @@ class ApplicationController < ActionController::Base before_action :store_user_location!, if: :storable_location? - # from Blacklight: 'Discarding flash messages on XHR requests is deprecated.' - skip_after_action :discard_flash_if_xhr - protect_from_forgery with: :exception - # @return [Hash] - # @todo remove this when supporting multiple locales - def default_url_options - super.reject { |k, _v| k == :locale } - end + # # @return [Hash] + # # @todo remove this when supporting multiple locales + # def default_url_options + # super.reject { |k, _v| k == :locale } + # end # Borrowed from pul's figgy app. Restricts our guests to a single entry # in the database, preventing hundreds of fake user accounts from being diff --git a/app/controllers/catalog_controller.rb b/app/controllers/catalog_controller.rb index e2ea41762..de44e965b 100644 --- a/app/controllers/catalog_controller.rb +++ b/app/controllers/catalog_controller.rb @@ -11,9 +11,12 @@ class CatalogController < ApplicationController include Hydra::Controller::ControllerBehavior # This filter applies the hydra access controls + # @todo is this doing anything? we're not using Blacklight/CatalogController for :show views... before_action :enforce_show_permissions, only: :show configure_blacklight do |config| + config.http_method = :post + # default advanced config values config.advanced_search ||= Blacklight::OpenStructWithHashAccess.new # config.advanced_search[:qt] ||= 'advanced' @@ -49,31 +52,21 @@ class CatalogController < ApplicationController config.index.display_type_field = 'has_model_ssim' config.index.thumbnail_field = 'thumbnail_path_ss' - # solr fields that will be treated as facets by the blacklight application - # The ordering of the field names is the order of the display + # Field configuration for Facets. # - # @note: when defining a field (facet, index, show, search), define the - # +:label+ option as a Symbol that refers to the field _without_ - # the "solr jargon" (ex. "_tesim", "_ssim", etc) suffix. it _needs_ - # to be a Symbol in order for +I18n.translate+ to use it as - # a fall-back when the lookup with the "solr jargon" ultimately fails. - # this will save us from having to provide multiple locale definitions - # for each attribute. # - # @example - # config.add_index_field('keyword_ssim', label: :'blacklight.search.fields.keyword') - - config.add_facet_field 'member_of_collections_ssim', label: :'blacklight.search.fields.member_of_collection' - config.add_facet_field 'resource_type_sim', label: :'blacklight.search.fields.resource_type' - config.add_facet_field 'creator_sim', label: :'blacklight.search.fields.creator' - config.add_facet_field 'publisher_sim', label: :'blacklight.search.fields.publisher' - config.add_facet_field 'division_sim', label: :'blacklight.search.fields.division' - config.add_facet_field 'academic_department_sim', label: :'blacklight.search.fields.academic_department' - config.add_facet_field 'advisor_label_ssim', label: :'blacklight.search.fields.advisor_label' - config.add_facet_field 'subject_label_sim', label: :'blacklight.search.fields.subject' - config.add_facet_field 'keyword_sim', label: :'blacklight.search.fields.keyword' - config.add_facet_field 'language_label_ssim', label: :'blacklight.search.fields.language' - config.add_facet_field 'location_label_sim', label: :'blacklight.search.fields.location' + # + config.add_facet_field 'member_of_collection_ids_ssim', helper_method: :collection_title_by_id + config.add_facet_field 'resource_type_sim' + config.add_facet_field 'creator_sim' + config.add_facet_field 'publisher_sim' + config.add_facet_field 'division_sim' + config.add_facet_field 'academic_department_sim' + config.add_facet_field 'advisor_label_ssim' + config.add_facet_field 'subject_label_sim' + config.add_facet_field 'keyword_sim' + config.add_facet_field 'language_label_ssim' + config.add_facet_field 'location_label_sim' config.add_facet_field 'years_encompassed_iim', include_in_advanced_search: false, label: :'blacklight.search.fields.years_encompassed', @@ -86,11 +79,16 @@ class CatalogController < ApplicationController # config.add_facet_field 'visibility_ssi', label: :'blacklight.search.fields.visibility', - helper_method: :render_catalog_visibility_facet, - admin: true - config.add_facet_field 'depositor_ssim', label: :'blacklight.search.fields.depositor', admin: true - config.add_facet_field 'proxy_depositor_ssim', label: :'blacklight.search.fields.proxy_depositor', admin: true - config.add_facet_field 'admin_set_sim', label: :'blacklight.search.fields.admin_set', admin: true + item_component: Spot::VisibilityFacetItemComponent, + group: :admin + config.add_facet_field 'depositor_ssim', label: :'blacklight.search.fields.depositor', group: :admin + config.add_facet_field 'proxy_depositor_ssim', label: :'blacklight.search.fields.proxy_depositor', group: :admin + config.add_facet_field 'admin_set_sim', label: :'blacklight.search.fields.admin_set', group: :admin + + # + # By configuring these fields with `if: false`, we're hiding facets from the sidebar + # but allowing them to be used within Works show pages (ex. "Research Assistance" and "Organization" fields) + # # The generic_type isn't displayed on the facet list # It's used to give a label to the filter that comes from the user profile @@ -103,8 +101,10 @@ class CatalogController < ApplicationController config.add_facet_field 'research_assistance_ssim', label: :'blacklight.search.fields.research_assistance', if: false config.add_facet_field 'organization_sim', label: :'blacklight.search.fields.organization', if: false + # # Blacklight will default a facet's limit to the +blacklight_config.default_facet_limit+ value # only if the field config +:limit+ entry is true. This does that. + # config.facet_fields.each { |(_key, val)| val[:limit] = true } # Have BL send all facet field names to Solr, which has been the default diff --git a/app/controllers/concerns/spot/additional_formats_for_controller.rb b/app/controllers/concerns/spot/additional_formats_for_controller.rb index 25f3ccfea..ca2ef684e 100644 --- a/app/controllers/concerns/spot/additional_formats_for_controller.rb +++ b/app/controllers/concerns/spot/additional_formats_for_controller.rb @@ -22,7 +22,7 @@ def csv_filename # @return [String] def work_as_csv - Spot::WorkCSVService.new(presenter.solr_document).csv + Spot::WorkCsvService.new(presenter.solr_document).csv end end end diff --git a/app/controllers/concerns/spot/hyrax_dashboard_controller_decorator.rb b/app/controllers/concerns/spot/hyrax_dashboard_controller_decorator.rb new file mode 100644 index 000000000..882b9bc7e --- /dev/null +++ b/app/controllers/concerns/spot/hyrax_dashboard_controller_decorator.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true +module Spot + # Changing the Hyrax behavior slightly to only display a dashboard + # if a user has been assigned to the 'depositor' role. + # + # @see config/initializers/spot_overrides.rb + # @see https://github.com/samvera/hyrax/blob/hyrax-v5.2.0/app/controllers/hyrax/dashboard_controller.rb + module HyraxDashboardControllerDecorator + extend ActiveSupport::Concern + + prepended do + class_attribute :create_work_presenter_class, default: Hyrax::SelectTypeListPresenter + + sidebar_partials[:activity] << 'hyrax/dashboard/sidebar/fixity_checks' + end + + def show + if can? :read, :admin_dashboard + @presenter = Hyrax::Admin::DashboardPresenter.new + @admin_set_rows = Hyrax::AdminSetService.new(self).search_results_with_work_count(:read) + render 'show_admin' + + # @see {Ability#depositor_abilities} + elsif can? :read, :dashboard + @presenter = Hyrax::Dashboard::UserPresenter.new(current_user, view_context, params[:since]) + @create_work_presenter = create_work_presenter_class.new(current_user) + render 'show_user' + else + redirect_to root_path + end + end + end +end diff --git a/app/controllers/concerns/spot/works_controller_behavior.rb b/app/controllers/concerns/spot/works_controller_behavior.rb index 1b8571f24..f12e097a5 100644 --- a/app/controllers/concerns/spot/works_controller_behavior.rb +++ b/app/controllers/concerns/spot/works_controller_behavior.rb @@ -26,7 +26,7 @@ module WorksControllerBehavior # # @return [Spot::IiifManifestPresenter] def iiif_manifest_presenter - ::Spot::IiifManifestPresenter.new(curation_concern_from_search_results).tap do |p| + ::Spot::IiifManifestPresenter.new(search_result_document(id: params[:id], defType: 'lucene')).tap do |p| p.hostname = request.hostname p.ability = current_ability end diff --git a/app/controllers/handle_controller.rb b/app/controllers/handle_controller.rb index e43aca06a..b42390ce0 100644 --- a/app/controllers/handle_controller.rb +++ b/app/controllers/handle_controller.rb @@ -9,12 +9,11 @@ class HandleController < ApplicationController # Displays a 404 (via raised +Blacklight::Exceptions::RecordNotFound+ # that is handled with +Hydra::Catalog+) if no item is found. def show - query = query_for_identifier(Spot::Identifier.new('hdl', params[:id])) - result, _documents = repository.search(query) - - raise Blacklight::Exceptions::RecordNotFound if result.response['numFound'].zero? - document = result.response['docs'].first + query_opts = query_for_identifier(Spot::Identifier.new('hdl', params[:id])) + service = Hyrax::SolrQueryService.new(query: [query_opts.delete(:q)]) + document = service.get(**query_opts)['response']['docs'].first + raise Blacklight::Exceptions::RecordNotFound if document.nil? redirect_to redirect_params_for(solr_document: document) end @@ -32,7 +31,6 @@ def identifier_solr_field # @param id [Spot::Identifier, #to_s] the identifier (with prefix) # @return [Hash String>] def query_for_identifier(id) - { q: "{!terms f=#{identifier_solr_field}}#{id}", - defType: 'lucene' } + { q: "{!terms f=identifier_ssim}#{id}", defType: 'lucene' } end end diff --git a/app/controllers/hyrax/dashboard_controller.rb b/app/controllers/hyrax/dashboard_controller.rb deleted file mode 100644 index 46ea0d914..000000000 --- a/app/controllers/hyrax/dashboard_controller.rb +++ /dev/null @@ -1,51 +0,0 @@ -# frozen_string_literal: true -module Hyrax - # Changing the Hyrax behavior slightly to _not_ display a dashboard - # if a user has not been assigned to the 'depositor' role. - # - # NOTE: when migrating to Hyrax@3, be sure to uncomment the definition - # of the +:sidebar_partials+ class attribute below! - class DashboardController < ApplicationController - include Blacklight::Base - include Hyrax::Breadcrumbs - with_themed_layout 'dashboard' - before_action :authenticate_user! - before_action :build_breadcrumbs, only: [:show] - before_action :set_date_range - - class_attribute :create_work_presenter_class - self.create_work_presenter_class = Hyrax::SelectTypeListPresenter - - ## - # @!attribute [rw] sidebar_partials - # @return [Hash] - # - # @example Add a custom partial to the tasks sidebar block - # Hyrax::DashboardController.sidebar_partials[:tasks] << "hyrax/dashboard/sidebar/custom_task" - class_attribute :sidebar_partials - self.sidebar_partials = { activity: [], configuration: [], repository_content: [], tasks: [] } - - def show - if can? :read, :admin_dashboard - @presenter = Hyrax::Admin::DashboardPresenter.new - @admin_set_rows = Hyrax::AdminSetService.new(self).search_results_with_work_count(:read) - render 'show_admin' - - # @see {Ability#depositor_abilities} - elsif can? :read, :dashboard - @presenter = Dashboard::UserPresenter.new(current_user, view_context, params[:since]) - @create_work_presenter = create_work_presenter_class.new(current_user) - render 'show_user' - else - redirect_to root_path - end - end - - private - - def set_date_range - @start_date = params[:start_date] || Time.zone.today - 1.month - @end_date = params[:end_date] || Time.zone.today + 1.day - end - end -end diff --git a/app/controllers/spot/redirect_controller.rb b/app/controllers/spot/redirect_controller.rb index 08c293ed9..d70c17005 100644 --- a/app/controllers/spot/redirect_controller.rb +++ b/app/controllers/spot/redirect_controller.rb @@ -1,6 +1,4 @@ # frozen_string_literal: true -require 'uri' - module Spot # Controller responsible for redirecting requests from legacy services # (in particular, our Islandora instance) to their migrated counterparts. @@ -28,9 +26,8 @@ def show private def document_params - # The only fields we'll need to generate a URL (or url_helper params) is are id and has_model_ssim. - result, _documents = repository.search(q: "{!terms f=identifier_ssim}url:#{http_uri}", fl: ['id', 'has_model_ssim'], defType: 'lucene') - document = result.response['docs']&.first + service = Hyrax::SolrQueryService.new(query: ["{!terms f=identifier_ssim}url:#{http_uri}"]) + document = service.query_result(fl: ['id', 'has_model_ssim'], defType: 'lucene')['response']['docs'].first raise Blacklight::Exceptions::RecordNotFound if document.nil? redirect_params_for(solr_document: document) diff --git a/app/factories/concerns/spot/bulkrax_object_factory_find_patch.rb b/app/factories/concerns/spot/bulkrax_object_factory_find_patch.rb new file mode 100644 index 000000000..e80f08a61 --- /dev/null +++ b/app/factories/concerns/spot/bulkrax_object_factory_find_patch.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true +module Spot + # We made this patch because there are two places that the original ‘find’ + # method in Bulkrax was failing to perform. First, Bulkrax will display a link + # to an imported work's record but the ObjectFactory appears to be searching + # for a work's 'source_identifier' as the object's ID. The second is that the ‘find’ + # Method is what is used to match and object with a collection at ingest, also + # using 'source_identifier' as the object's ID. We believe that both of these + # problems arise from our setup being on Hyrax 3.6.0 and unvalkyrized, and + # that we can retire this patch once larger upgrades are made. This patch adds + # a new method, ‘find_by_source_identifier’, which is added to the front of the + # queue of methods to try in ‘find’. Notably, ‘find_by_source_identifier’ does not + # succeed when called during ingest to make the link, but for some reason truly + # unknown to us, if this method is called before ‘search_by_identifier’, that + # method then succeeds where it would typically fail. The order of those methods + # being switched does not produce the same result, both methods fail in that case. + # However, once the CreateRelationshipsJob stage is reached, + # ‘find_by_source_identifier’ always succeeds where ‘search_by_identifier’ always + # fails. Truly incomprehensible. Nonetheless, this order seems to fulfill all desired + # functions. + # + # @see config/initializers/spot_overrides.rb + module BulkraxObjectFactoryFindPatch + extend ActiveSupport::Concern + + # We have to overwrite this behavior to add 'find_by_source_identifier' + # to the queue of methods to try. + # + # @see https://github.com/samvera/bulkrax/blob/v9.1.0/app/factories/bulkrax/object_factory_interface.rb#L317-L325 + def find + find_by_source_identifier || find_by_id || search_by_identifier || nil + end + + def find_by_source_identifier + return unless attributes.key?('source_identifier') && attributes['source_identifier'].present? + identifier = Array.wrap(attributes['source_identifier']).first + id_doc = Hyrax::SolrService.get("source_identifier_ssim:#{identifier}", fl: ['id', 'source_identifier_ssim'], defType: 'lucene') + id_doc = id_doc.try(:[], 'response').try(:[], 'docs')&.first + return nil if id_doc.nil? || id_doc.try(:[], 'id').nil? + + ActiveFedora::Base.find(id_doc['id']) + end + + # We have to implement these for testing purposes. + # :nocov: + def find_by_id + super + end + + def search_by_identifier + super + end + # :nocov: + end +end diff --git a/app/forms/hyrax/student_work_form.rb b/app/forms/hyrax/student_work_form.rb index 8a0cdff57..92b2976aa 100644 --- a/app/forms/hyrax/student_work_form.rb +++ b/app/forms/hyrax/student_work_form.rb @@ -96,7 +96,10 @@ def model_attributes(_form_params) def admin_set_id Spot::StudentWorkAdminSetCreateService.find_or_create_student_work_admin_set_id rescue Ldp::Gone, Hyrax::ObjectNotFoundError - AdminSet.find_or_create_default_admin_set_id + # :nocov: + # test directly interfacing with this case mysteriously does not convey coverage + Hyrax::AdminSetCreateService.find_or_create_default_admin_set.id + # :nocov: end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index d6e957ac4..2b13fd332 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,4 +1,6 @@ # frozen_string_literal: true +require 'hyrax/version' + module ApplicationHelper delegate :advanced_search_path, to: :blacklight_advanced_search_engine @@ -14,6 +16,10 @@ def extracted_text_highlight_values_for(document) document.highlight_field('extracted_text_tsimv').reject(&:blank?) end + def hyrax_footer_text + "Powered by Hyrax (v#{Hyrax::VERSION})" + end + # rubocop:disable Style/ClassVars # @return [String, nil] def site_last_updated @@ -23,9 +29,9 @@ def site_last_updated # @api private def generate_site_last_updated - return if ENV['SPOT_BUILD_DATE'].blank? - Date.parse(ENV['SPOT_BUILD_DATE']).strftime('%B %d, %Y') - rescue + return '(in development)' if Rails.env.development? || ENV['SPOT_BUILD_DATE'].blank? + Date.parse(ENV['SPOT_BUILD_DATE'].to_s).strftime('%B %d, %Y') + rescue Date::Error ENV['SPOT_BUILD_DATE'] end end diff --git a/app/helpers/audio_visual_helper.rb b/app/helpers/audio_visual_helper.rb index 2c7fb9cb6..acb673b91 100644 --- a/app/helpers/audio_visual_helper.rb +++ b/app/helpers/audio_visual_helper.rb @@ -56,6 +56,6 @@ def get_derivative_res(derivative) # @return the network path to the thumbnail # @param [FileSet] file_set of the video def transcript_path(file_set) - Hyrax::Engine.routes.url_helpers.download_path(file_set.id, file: 'transcript') + Hyrax::Engine.routes.url_helpers.download_path(id: file_set.id, file: 'transcript') end end diff --git a/app/helpers/hyrax_helper.rb b/app/helpers/hyrax_helper.rb index c5c6c14a6..784887b00 100644 --- a/app/helpers/hyrax_helper.rb +++ b/app/helpers/hyrax_helper.rb @@ -4,6 +4,15 @@ module HyraxHelper include Hyrax::BlacklightOverride include Hyrax::HyraxHelperBehavior + # We currently don't offer translations beyond those offered in Hyrax, so we'll default + # to English for now. This will hide a translation dropdown in the site's header. + # + # @see https://github.com/samvera/hyrax/blob/hyrax-v4.0.0/app/views/_user_util_links.html.erb + # @see https://github.com/samvera/hyrax/blob/hyrax-v4.0.0/app/helpers/hyrax/hyrax_helper_behavior.rb#L31-L43 + def available_translations + { 'en' => 'English' } + end + # @see https://github.com/samvera/hyrax/blob/v2.9.6/app/helpers/hyrax/title_helper.rb#L18-L22 def default_page_title i18n_key = "spot.#{controller_name.underscore}" diff --git a/app/helpers/spot/catalog_helper.rb b/app/helpers/spot/catalog_helper.rb index 4ce97de76..2008fcb91 100644 --- a/app/helpers/spot/catalog_helper.rb +++ b/app/helpers/spot/catalog_helper.rb @@ -53,5 +53,12 @@ def i18n_key_for_document(document) 'default_html' # not expecting to get here, but we should have a generic message just in case end end + + def page_title_for_search_results + key = params[:page].present? ? 'spot.catalog.page_title_with_pagination' : 'spot.catalog.page_title' + I18n.t(key, query: params[:q] || '""', + page: params[:page]&.to_i, + name: application_name).html_safe + end end end diff --git a/app/helpers/spot/facet_helper.rb b/app/helpers/spot/facet_helper.rb deleted file mode 100644 index 9d0743013..000000000 --- a/app/helpers/spot/facet_helper.rb +++ /dev/null @@ -1,60 +0,0 @@ -# frozen_string_literal: true -# -# Helpers to split out facets useful to admins from the regular ("general") ones -module Spot - module FacetHelper - # render only the admin facet partials - # - # @return [String] - def render_admin_facet_partials - render_facet_partials(admin_facet_names) - end - - # Wraps our visibility facets in the Hyrax::PermissionBadge HTML - # - # @return [String] - def render_catalog_visibility_facet(visibility) - Hyrax::PermissionBadge.new(visibility).render - end - - # render partials for the majority of our partials - # - # @return [String] - def render_general_facet_partials - render_facet_partials(general_facet_names) - end - - # Returns only the facets where the option +:admin+ is truthy - # - # @return [Array] - def admin_facet_names - @admin_facet_names ||= - blacklight_config.facet_fields.select { |_facet, opts| opts[:admin] }.values.map(&:field) - end - - # Facet names whose configuration does not include a truthy +:admin+ value. - # - # @return [Array] - def general_facet_names - facet_field_names - admin_facet_names - end - - # @return [true, false] - def any_facets? - general_facets? || admin_facets? - end - - # @return [true, false] - def general_facets? - has_facet_values?(general_facet_names) - end - - # @return [true, false] - def admin_facets? - return false unless current_user&.admin? - return false if admin_facet_names.empty? - - facets_from_request(admin_facet_names).any? { |facet| should_render_facet?(facet) } - end - end -end diff --git a/app/inputs/language_tagged_multi_input_group_input.rb b/app/inputs/language_tagged_multi_input_group_input.rb index 15e583cbe..078022cde 100644 --- a/app/inputs/language_tagged_multi_input_group_input.rb +++ b/app/inputs/language_tagged_multi_input_group_input.rb @@ -22,6 +22,16 @@ def input_type 'multi_value language_tagged' end + protected + + def inner_wrapper + <<-HTML +
  • + #{yield} +
  • + HTML + end + private # Explicitly state that this is a multi-value property, rather than diff --git a/app/jobs/spot/repository_fixity_check_job.rb b/app/jobs/spot/repository_fixity_check_job.rb index 7d94d349f..726553e4c 100644 --- a/app/jobs/spot/repository_fixity_check_job.rb +++ b/app/jobs/spot/repository_fixity_check_job.rb @@ -19,14 +19,13 @@ class RepositoryFixityCheckJob < ApplicationJob # @param [true, false] :force Ignore the 'max days between check' parameter def perform(force: false) + @count = 0 opts = { async_jobs: false } opts[:max_days_between_fixity_checks] = -1 if force - @count = 0 - ::FileSet.find_each do |file_set| @count += 1 - Hyrax::FileSetFixityCheckService.new(file_set, opts).fixity_check + Hyrax::FileSetFixityCheckService.new(file_set, **opts).fixity_check end end diff --git a/app/models/ability.rb b/app/models/ability.rb index f28f9d9b2..cf01b3b07 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -27,10 +27,18 @@ def self.preload_roles! # @return [void] def custom_permissions; end + # Added by Bulkrax generator + # + # @return [true, false] + # @see https://github.com/samvera/bulkrax/blob/v9.1.0/lib/generators/bulkrax/install_generator.rb#L58-L76 def can_import_works? current_user.admin? || current_user.depositor? end + # Added by Bulkrax generator + # + # @return [true, false] + # @see https://github.com/samvera/bulkrax/blob/v9.1.0/lib/generators/bulkrax/install_generator.rb#L58-L76 def can_export_works? current_user.admin? || current_user.depositor? end diff --git a/app/models/audio_visual_resource.rb b/app/models/audio_visual_resource.rb new file mode 100644 index 000000000..3cf3507f3 --- /dev/null +++ b/app/models/audio_visual_resource.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true +class AudioVisualResource < ::Hyrax::Work + include Hyrax::Schema(:base_metadata, schema_loader: Spot::SimpleSchemaLoader.new) + include Hyrax::Schema(:audio_visual_metadata, schema_loader: Spot::SimpleSchemaLoader.new) + + attribute :stored_derivatives, Valkyrie::Types::String +end diff --git a/app/models/concerns/hyrax/file_set/derivatives.rb b/app/models/concerns/hyrax/file_set/derivatives.rb new file mode 100644 index 000000000..ab275d2c3 --- /dev/null +++ b/app/models/concerns/hyrax/file_set/derivatives.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true +module Hyrax + class FileSet + module Derivatives + extend ActiveSupport::Concern + + included do + # Custom override of the corresponding Hyrax file to revert Hydra::Derivatives.output_file_service + # to Hyrax::PersistDerivatives from Hyrax::ValkyriePersistDerivatives. The latter causes issues in + # the current repository. This change should be able to be undone once we're Valkyrized. + # + # See @https://github.com/samvera/hyrax/blob/main/app/models/concerns/hyrax/file_set/derivatives.rb + Hydra::Derivatives.source_file_service = Hyrax::LocalFileService + Hydra::Derivatives.output_file_service = Hyrax::PersistDerivatives + Hydra::Derivatives::FullTextExtract.output_file_service = Hyrax::PersistDirectlyContainedOutputFileService + before_destroy :cleanup_derivatives + # This completely overrides the version in Hydra::Works so that we + # read and write to a local file. It's important that characterization runs + # before derivatives so that we have a credible mime_type field to work with. + delegate :cleanup_derivatives, :create_derivatives, to: :file_set_derivatives_service + end + + private + + def file_set_derivatives_service + Hyrax::DerivativeService.for(self) + end + end + end +end diff --git a/app/models/concerns/spot/nested_collection_behavior.rb b/app/models/concerns/spot/nested_collection_behavior.rb index 631ddb6ba..437695860 100644 --- a/app/models/concerns/spot/nested_collection_behavior.rb +++ b/app/models/concerns/spot/nested_collection_behavior.rb @@ -58,7 +58,6 @@ def gather_collections_to_add [].tap do |collections| until collections_to_check.size.zero? col = collections_to_check.shift - col.reindex_extent = Hyrax::Adapters::NestingIndexAdapter::LIMITED_REINDEX collections << col unless collections.include?(col) collections_to_check += col.member_of_collections diff --git a/app/models/concerns/spot/solr_document_attributes.rb b/app/models/concerns/spot/solr_document_attributes.rb index 84d37f80f..9f462933d 100644 --- a/app/models/concerns/spot/solr_document_attributes.rb +++ b/app/models/concerns/spot/solr_document_attributes.rb @@ -3,10 +3,6 @@ module Spot # Various model attributes for the single SolrDocument model. Since that model wraps # every kind of Solr document, we need to ensure that _all_ of the models attributes # are available. - # - # - # - # @todo Remove {.attribute} definition when Hyrax upgrades to Blacklight >=7 module SolrDocumentAttributes extend ActiveSupport::Concern @@ -107,13 +103,5 @@ module SolrDocumentAttributes attribute :citation_firstpage, ::Blacklight::Types::String, 'citation_firstpage_ss' attribute :citation_lastpage, ::Blacklight::Types::String, 'citation_lastpage_ss' end - - module ClassMethods - def attribute(name, type, field) - define_method name do - type.coerce(self[field]) - end - end - end end end diff --git a/app/models/image_resource.rb b/app/models/image_resource.rb new file mode 100644 index 000000000..9de64fee0 --- /dev/null +++ b/app/models/image_resource.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true +class ImageResource < ::Hyrax::Work + include Hyrax::Schema(:base_metadata, schema_loader: Spot::SimpleSchemaLoader.new) + include Hyrax::Schema(:image_metadata, schema_loader: Spot::SimpleSchemaLoader.new) +end diff --git a/app/models/publication_resource.rb b/app/models/publication_resource.rb new file mode 100644 index 000000000..5900482b7 --- /dev/null +++ b/app/models/publication_resource.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true +class PublicationResource < ::Hyrax::Work + include Hyrax::Schema(:base_metadata, schema_loader: Spot::SimpleSchemaLoader.new) + include Hyrax::Schema(:institutional_metadata, schema_loader: Spot::SimpleSchemaLoader.new) + include Hyrax::Schema(:publication_metadata, schema_loader: Spot::SimpleSchemaLoader.new) +end diff --git a/app/models/solr_document.rb b/app/models/solr_document.rb index ad4845652..6dc7f5af6 100644 --- a/app/models/solr_document.rb +++ b/app/models/solr_document.rb @@ -1,6 +1,4 @@ # frozen_string_literal: true -# -# Generated from +rails generate hyrax:install+ class SolrDocument include Blacklight::Solr::Document include BlacklightOaiProvider::SolrDocument diff --git a/app/models/spot/oai_collection_solr_set.rb b/app/models/spot/oai_collection_solr_set.rb index bf04ed476..56588a824 100644 --- a/app/models/spot/oai_collection_solr_set.rb +++ b/app/models/spot/oai_collection_solr_set.rb @@ -1,6 +1,4 @@ # frozen_string_literal: true -require 'cgi' - module Spot # Subclass of +BlacklightOaiProvider::SolrSet+ that translates # spaces to underscores, making the following assumptions: diff --git a/app/models/student_work_resource.rb b/app/models/student_work_resource.rb new file mode 100644 index 000000000..316197ce9 --- /dev/null +++ b/app/models/student_work_resource.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true +class StudentWorkResource < ::Hyrax::Work + include Hyrax::Schema(:base_metadata, schema_loader: Spot::SimpleSchemaLoader.new) + include Hyrax::Schema(:institutional_metadata, schema_loader: Spot::SimpleSchemaLoader.new) + include Hyrax::Schema(:student_work_metadata, schema_loader: Spot::SimpleSchemaLoader.new) +end diff --git a/app/presenters/spot/base_presenter.rb b/app/presenters/spot/base_presenter.rb index 0a0190b01..6ba902397 100644 --- a/app/presenters/spot/base_presenter.rb +++ b/app/presenters/spot/base_presenter.rb @@ -86,6 +86,13 @@ def page_title "#{title.first} // #{I18n.t('hyrax.product_name')}" end + # Replacing Hyrax::PermissionBadge with our own subclass that can handle :metadata visibility + # + # @return [Spot::PermissionBadge] + def permission_badge_class + Spot::PermissionBadge + end + # @return [Array>] def rights_statement_merged solr_document.rights_statement.zip(solr_document.rights_statement_label) diff --git a/app/presenters/spot/permission_badge.rb b/app/presenters/spot/permission_badge.rb new file mode 100644 index 000000000..6ddad0e73 --- /dev/null +++ b/app/presenters/spot/permission_badge.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true +module Spot + class PermissionBadge < Hyrax::PermissionBadge + VISIBILITY_LABEL_CLASS = { + authenticated: "badge-info", + embargo: "badge-warning", + lease: "badge-warning", + metadata: "badge-info", + open: "badge-success", + restricted: "badge-danger" + }.freeze + + def badge_class + dom_label_class + end + + def visibility_label + text + end + end +end diff --git a/app/renderers/spot/renderers/attribute_renderer.rb b/app/renderers/spot/renderers/attribute_renderer.rb index 2adb3d8a2..43adf8019 100644 --- a/app/renderers/spot/renderers/attribute_renderer.rb +++ b/app/renderers/spot/renderers/attribute_renderer.rb @@ -47,11 +47,11 @@ def render markup = [] vals = Array(values) - attributes = microdata_object_attributes(field).merge(class: "attribute attribute-#{field}") + attributes = microdata_object_attributes(field).merge(class: "p-2 attribute attribute-#{field}") vals.each_with_index do |value, index| markup << '' - markup << %(#{label}) if index.zero? + markup << %(#{label}) if index.zero? markup << %(#{attribute_value_to_html(value)}) markup << '' end diff --git a/app/search_builders/spot/catalog_search_builder.rb b/app/search_builders/spot/catalog_search_builder.rb index b6f5b53d5..400134116 100644 --- a/app/search_builders/spot/catalog_search_builder.rb +++ b/app/search_builders/spot/catalog_search_builder.rb @@ -5,7 +5,7 @@ module Spot # the Hyrax join query for extracted text, and conditionally (for now) # display highlight matches (where present). class CatalogSearchBuilder < ::Hyrax::CatalogSearchBuilder - include BlacklightAdvancedSearch::AdvancedSearchBuilder + # include BlacklightAdvancedSearch::AdvancedSearchBuilder include BlacklightRangeLimit::RangeLimitBuilder self.default_processor_chain -= [:show_works_or_works_that_contain_files] diff --git a/app/services/concerns/spot/bulkrax_s3_files_matcher.rb b/app/services/concerns/spot/bulkrax_s3_files_matcher.rb new file mode 100644 index 000000000..1e3361335 --- /dev/null +++ b/app/services/concerns/spot/bulkrax_s3_files_matcher.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true +module Spot + # Patch to add an s3 file matcher to remotely fetch files from s3 without a Browse Everything UI. + # This is based on the remote files matcher in the application matcher but assumes a file path + # (on s3) is provided rather than a url. The url is fetched in the same manner as AV s3 urls. + # + # @see spec/matchers/bulkrax/application_matcher_spec.rb (for related specs) + # @see config/initializers/spot_overrides.rb (for inclusion) + # @see https://github.com/samvera/bulkrax/blob/5e85a0760e9cc317ae11dbecd35c508d6882a5b6/app/matchers/bulkrax/application_matcher.rb#L58C5-L63C8 + module BulkraxS3FilesMatcher + extend ActiveSupport::Concern + + def parse_remote_files(src) + return if src.blank? + src.strip! + + client = Aws::S3::Client.new + begin + client.head_object(key: src, bucket: ENV['AWS_BULKRAX_IMPORTS_BUCKET']) + rescue Aws::S3::Errors::NotFound + Rails.logger.warn('S3: Key not found.') + return "S3: Key not found." + end + obj = Aws::S3::Object.new(bucket_name: ENV['AWS_BULKRAX_IMPORTS_BUCKET'], key: src, client: client) + url = obj.presigned_url(:get, expires_in: 3600) + + name = src.split('/')[-1] + { url: url, file_name: name } + end + end +end diff --git a/app/services/concerns/spot/retrieves_s3_urls.rb b/app/services/concerns/spot/retrieves_s3_urls.rb index a2c857532..a979b9f2c 100644 --- a/app/services/concerns/spot/retrieves_s3_urls.rb +++ b/app/services/concerns/spot/retrieves_s3_urls.rb @@ -22,6 +22,16 @@ def can_retrieve?(uri, headers = {}) uri_parsed = ::Addressable::URI.parse(uri) case uri_parsed.scheme + when "http" + if Rails.env.development? + client = Aws::S3::Client.new + kv = uri_parsed.path[1..-1].split('/', 2) + resp = client.head_object(bucket: kv[0], key: kv[1]) + return true unless resp.nil? + false + else + super(uri, headers) + end when "s3" client = Aws::S3::Client.new resp = client.head_object(bucket: uri_parsed.host, key: uri_parsed.path[1..-1]) diff --git a/app/services/rdf_literal_serializer.rb b/app/services/rdf_literal_serializer.rb index 093d2640e..4ddcc6370 100644 --- a/app/services/rdf_literal_serializer.rb +++ b/app/services/rdf_literal_serializer.rb @@ -1,6 +1,4 @@ # frozen_string_literal: true -require 'rdf/ntriples' - class RdfLiteralSerializer # @return [String] def serialize(literal) diff --git a/app/services/spot/characterization_service.rb b/app/services/spot/characterization_service.rb index 53de286d6..74e5e9c64 100644 --- a/app/services/spot/characterization_service.rb +++ b/app/services/spot/characterization_service.rb @@ -12,7 +12,7 @@ def self.run(characterization_proxy, filepath, opts = {}) tool = ENV['FITS_SERVLET_URL'].present? ? :fits_servlet : :fits opts = { ch12n_tool: tool }.merge(opts) - super(characterization_proxy, filepath, opts) + super(characterization_proxy, filepath, **opts) end end end diff --git a/app/services/spot/derivatives/audio_derivative_service.rb b/app/services/spot/derivatives/audio_derivative_service.rb index 6901c6c31..ffdbafa8d 100644 --- a/app/services/spot/derivatives/audio_derivative_service.rb +++ b/app/services/spot/derivatives/audio_derivative_service.rb @@ -1,9 +1,4 @@ # frozen_string_literal: true -require 'aws-sdk-s3' -require 'digest/md5' -require 'fileutils' -require 'ffprober' - module Spot module Derivatives # Checks the 'premade_derivatives' property on the associated work. If the property is empty, diff --git a/app/services/spot/derivatives/audio_visual_base_derivative_service.rb b/app/services/spot/derivatives/audio_visual_base_derivative_service.rb index aafa15c66..7dfc290b7 100644 --- a/app/services/spot/derivatives/audio_visual_base_derivative_service.rb +++ b/app/services/spot/derivatives/audio_visual_base_derivative_service.rb @@ -1,9 +1,4 @@ # frozen_string_literal: true -require 'aws-sdk-s3' -require 'digest/md5' -require 'fileutils' -require 'ffprober' - module Spot module Derivatives # Base file that audio and video derivative services inherit from. Contains functionality common to both. diff --git a/app/services/spot/derivatives/iiif_access_copy_service.rb b/app/services/spot/derivatives/iiif_access_copy_service.rb index 704b01329..0484ac792 100644 --- a/app/services/spot/derivatives/iiif_access_copy_service.rb +++ b/app/services/spot/derivatives/iiif_access_copy_service.rb @@ -1,8 +1,4 @@ # frozen_string_literal: true -require 'aws-sdk-s3' -require 'digest/md5' -require 'fileutils' - module Spot module Derivatives # Creates pyramidal TIFF copies of Images for serving via IIIF. Pyramidal TIFFs contain diff --git a/app/services/spot/derivatives/video_derivative_service.rb b/app/services/spot/derivatives/video_derivative_service.rb index 7fb752836..5a2d799c0 100644 --- a/app/services/spot/derivatives/video_derivative_service.rb +++ b/app/services/spot/derivatives/video_derivative_service.rb @@ -1,9 +1,4 @@ # frozen_string_literal: true -require 'aws-sdk-s3' -require 'digest/md5' -require 'fileutils' -require 'ffprober' - module Spot module Derivatives # Checks the 'premade_derivatives' property on the associated work. If the property is empty, diff --git a/app/services/spot/embargo_lease_service.rb b/app/services/spot/embargo_lease_service.rb index 061262742..45f1cb27a 100644 --- a/app/services/spot/embargo_lease_service.rb +++ b/app/services/spot/embargo_lease_service.rb @@ -3,15 +3,15 @@ module Spot # A service for dealing with embargoes and leases. Right now, we're just # using this to clear out expired items. # - # @example Clear out all expired values at once - # Spot::EmbargoLeaseService.clear_all_expired + # @example Clear out all expired values at once and regenerate thumbnails + # Spot::EmbargoLeaseService.clear_all_expired(regenerate_thumbnails: true) # - # @example Clear out expired embargoes (and update +date_available+ values) + # @example Clear out expired embargoes # Spot::EmbargoLeaseService.clear_expired_embargoes # # @example Clear out expired leases # Spot::EmbargoLeaseService.clear_expired_leases - # + class EmbargoLeaseService class << self # Convenience method to clear both embargoes and leases @@ -28,18 +28,7 @@ def clear_all_expired(regenerate_thumbnails: false) # @return [void] def clear_expired_embargoes(regenerate_thumbnails: false) ::Hyrax::EmbargoService.assets_with_expired_embargoes.each do |presenter| - item = ActiveFedora::Base.find(presenter.id) - - next if item.under_embargo? - - ::Hyrax::Actors::EmbargoActor.new(item).destroy - - next if item.is_a? FileSet - - item.copy_visibility_to_files - item.save! - - RegenerateThumbnailJob.perform_later(item) if regenerate_thumbnails == true + release_and_save_for_id(presenter.id, type: :embargo, regenerate_thumbnails: regenerate_thumbnails) end end @@ -48,17 +37,65 @@ def clear_expired_embargoes(regenerate_thumbnails: false) # @return [void] def clear_expired_leases(regenerate_thumbnails: false) ::Hyrax::LeaseService.assets_with_expired_leases.each do |presenter| - item = ActiveFedora::Base.find(presenter.id) + release_and_save_for_id(presenter.id, type: :lease, regenerate_thumbnails: regenerate_thumbnails) + end + end + + private - next if item.active_lease? + # Embargos and Leases behave very similarly and are managed through similar interfaces + # in Hyrax, so we'll do the bulk of that work here. + # + # @param [String] id + # @option [:embargo, :lease] :type + # @option [true/false] :regenerate_thumbnails + # @return [void] + def release_and_save_for_id(id, type:, regenerate_thumbnails: false) + resource = release_and_save_acl_for(type: type, resource: Hyrax.query_service.find_by_alternate_identifier(alternate_identifier: id)) + return if resource.nil? + + copy_visibility_to_members!(resource: resource) + + RegenerateThumbnailJob.perform_later(resource) if regenerate_thumbnails == true + end - ::Hyrax::Actors::LeaseActor.new(item).destroy + # calling #release! on the managers will raise a +NotReleaseableError+ if + # the embargo/lease isn't ready to be deactivated. Since the resource's + # visibility hasn't changed, we won't bother to resave the object or enqueue + # a thumbnail regeneration job. + # + # @todo how can we test the `nil` return value for coverage? + def release_and_save_acl_for(type:, resource:) + manager_class = manager_class_for(type) + return if manager_class.nil? + + manager_class.new(resource: resource).release! + resource.permission_manager.acl.save + resource + rescue Hyrax::EmbargoManager::NotReleasableError, Hyrax::LeaseManager::NotReleasableError + # :nocov: + # This is covered via other tests + nil + # :nocov: + end - item.copy_visibility_to_files unless item.is_a? FileSet + def manager_class_for(type) + case type + when :embargo + Hyrax::EmbargoManager + when :lease + Hyrax::LeaseManager + end + end - RegenerateThumbnailJob.perform_later(item) if regenerate_thumbnails == true + # :nocov: + # return to this post valkyrization + def copy_visibility_to_members!(resource:) + Hyrax.query_service.find_members(resource: resource).each do |member| + Hyrax::AccessControlList.copy_permissions(source: resource, target: member) end end + # :nocov: end end end diff --git a/app/services/spot/exporters/work_metadata_exporter.rb b/app/services/spot/exporters/work_metadata_exporter.rb index 196bfc427..6c5c24124 100644 --- a/app/services/spot/exporters/work_metadata_exporter.rb +++ b/app/services/spot/exporters/work_metadata_exporter.rb @@ -55,12 +55,12 @@ def export_for_format(format) # @return [String] def generate_csv_content - Spot::WorkCSVService.new(solr_document).csv + Spot::WorkCsvService.new(solr_document).csv end # @return [RDF::Graph] def graph - @graph ||= Hyrax::GraphExporter.new(solr_document, request).fetch + @graph ||= Hyrax::GraphExporter.new(solr_document, hostname: request.host).fetch end end end diff --git a/app/services/spot/exporters/zipped_work_exporter.rb b/app/services/spot/exporters/zipped_work_exporter.rb index 2b38caa5f..873bcc215 100644 --- a/app/services/spot/exporters/zipped_work_exporter.rb +++ b/app/services/spot/exporters/zipped_work_exporter.rb @@ -1,7 +1,4 @@ # frozen_string_literal: true -require 'tmpdir' -require 'fileutils' - module Spot module Exporters class ZippedWorkExporter diff --git a/app/services/spot/iiif_service.rb b/app/services/spot/iiif_service.rb index 46fac8ee3..c0488e906 100644 --- a/app/services/spot/iiif_service.rb +++ b/app/services/spot/iiif_service.rb @@ -1,7 +1,4 @@ # frozen_string_literal: true -require 'cgi' -require 'uri' - module Spot # Service for generating IIIF urls (via file_ids) for an external Cantaloupe image server. # Really, this could be used for _any_ external image server, save for the #download_url diff --git a/app/services/spot/iso6391.rb b/app/services/spot/iso_6391.rb similarity index 100% rename from app/services/spot/iso6391.rb rename to app/services/spot/iso_6391.rb diff --git a/app/services/spot/rdf_authority_parser.rb b/app/services/spot/rdf_authority_parser.rb index 46e9c5791..b476e11ad 100644 --- a/app/services/spot/rdf_authority_parser.rb +++ b/app/services/spot/rdf_authority_parser.rb @@ -9,14 +9,14 @@ # # @example # -# class FrenchRDFAuthorityParser < Spot::RDFAuthorityParser +# class FrenchRdfAuthorityParser < Spot::RdfAuthorityParser # self.preferred_language = :fr # end # -# FrenchRDFAuthorityParser.load_rdf('languages_fr', ['http://id.loc.gov/vocabulary/iso639-1.nt']) +# FrenchRdfAuthorityParser.load_rdf('languages_fr', ['http://id.loc.gov/vocabulary/iso639-1.nt']) # module Spot - class RDFAuthorityParser < ::Qa::Services::RDFAuthorityParser + class RdfAuthorityParser < ::Qa::Services::RDFAuthorityParser class_attribute :preferred_language self.preferred_language = :en diff --git a/app/services/spot/simple_schema_loader.rb b/app/services/spot/simple_schema_loader.rb new file mode 100644 index 000000000..889a8c782 --- /dev/null +++ b/app/services/spot/simple_schema_loader.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true +module Spot + # Using our own SchemaLoader for the time being to bypass an issue with the Hyrax loader + # where 'type: uri' and 'multiple: true' fields were passing the Dry::Struct interface default + # value of +Dry::Types::Unknown+ through, as it responds true to #present?, which was resulting + # in new resources having default URI values of 'Unknown' + # + # @example + # # config/metadata/cool_metadata.yml + # attributes: + # subject: + # type: uri + # multiple: true + # + # # app/models/cool_resource.rb + # class CoolResource < Hyrax::Resource + # include Hyrax::Schema(:cool_metadata) + # end + # + # CoolResource.new.subject + # => [#] + # + # # app/models/better_resource.rb + # class BetterResource < Hyrax::Resource + # include Hyrax::Schema(:cool_metadata, schema_loader: Spot::SimpleSchemaLoader.new) + # end + # + # BetterResource.new.subject + # => [] + # + class SimpleSchemaLoader < Hyrax::SimpleSchemaLoader + class AttributeDefinition < Hyrax::SimpleSchemaLoader::AttributeDefinition + def type + collection_type = if config['multiple'] + Valkyrie::Types::Array.constructor { |v| Array(v).select { |x| x.present? && x != Dry::Types::Undefined } } + else + Identity + end + collection_type.of(type_for(config['type'])) + end + end + + private + + # Map the definitions to use our overloaded AttributeDefinition class. + # + # @param [#to_s] schema_name + # @return [Enumerable 1 + record.errors.add(:date_issued, :invalid, message: 'Date Issued may not be blank') if record.date_issued.empty? + record.errors.add(:date_issued, :invalid, message: 'Date Issued may only contain one value') if record.date_issued.size > 1 record.date_issued.each do |date| - record.errors[:date_issued] << 'Date Issued must be in YYYY-MM-DD, YYYY-MM, or YYYY format' unless + record.errors.add(:date_issued, :invalid, message: 'Date Issued must be in YYYY-MM-DD, YYYY-MM, or YYYY format') unless date.match?(/\A\d{4}(-\d{2}){0,2}\z/) end end diff --git a/app/validators/spot/only_urls_validator.rb b/app/validators/spot/only_urls_validator.rb index d4ee56447..94b46d536 100644 --- a/app/validators/spot/only_urls_validator.rb +++ b/app/validators/spot/only_urls_validator.rb @@ -1,8 +1,4 @@ # frozen_string_literal: true -# -# -require 'uri' - module Spot class OnlyUrlsValidator < ActiveModel::Validator # @param record [ActiveModel::Base] @@ -15,7 +11,7 @@ def validate(record) next if values.empty? values.each do |val| - record.errors[field] << "#{val} is not a valid URL" unless val.match?(uri_regex) + record.errors.add(field, :invalid, message: "#{val} is not a valid URL") unless val.match?(uri_regex) end end end diff --git a/app/validators/spot/required_local_authority_validator.rb b/app/validators/spot/required_local_authority_validator.rb index 0296f7898..1448b7eab 100644 --- a/app/validators/spot/required_local_authority_validator.rb +++ b/app/validators/spot/required_local_authority_validator.rb @@ -16,13 +16,12 @@ def validate(record) authority_name = options[:authority] field = options[:field] authority = authority_for(authority_name) - values = record.send(field) - values = Array.wrap(values) unless values.respond_to?(:each) + values = Array.wrap(values) unless values.class < Enumerable values.each do |v| value = v.is_a?(ActiveTriples::Resource) ? v.id : v.to_s - record.errors[field] << %("#{value}" is not a valid #{field.to_s.titleize}.) if authority.find(value).empty? + record.errors.add(field, :invalid, message: %("#{value}" is not a valid #{field.to_s.titleize}.)) if authority.find(value).empty? end end diff --git a/app/validators/spot/slug_validator.rb b/app/validators/spot/slug_validator.rb index aef053501..2d9da5633 100644 --- a/app/validators/spot/slug_validator.rb +++ b/app/validators/spot/slug_validator.rb @@ -13,8 +13,8 @@ def validate(record) slugs = record.send(field).select { |id| id.start_with? 'slug:' } next if slugs.empty? - record.errors[field] << single_slug_message unless slugs.size == 1 - record.errors[field] << slug_regex_message unless slug_valid?(slugs.first) + record.errors.add(field, :invalid, message: single_slug_message) unless slugs.size == 1 + record.errors.add(field, :invalid, message: slug_regex_message) unless slug_valid?(slugs.first) end end diff --git a/app/values/blacklight/types.rb b/app/values/blacklight/types.rb deleted file mode 100644 index b0751d1fb..000000000 --- a/app/values/blacklight/types.rb +++ /dev/null @@ -1,34 +0,0 @@ -# frozen_string_literal: true -# -# This is copied whole-hog from Blacklight@master and gives us types to use -# for -# @todo remove this file when Hyrax upgrades to Blacklight 7. -module Blacklight - # These are data types that blacklight can use to coerce values from the index - module Types - class Array - def self.coerce(input) - ::Array.wrap(input) - end - end - - class String - def self.coerce(input) - ::Array.wrap(input).first - end - end - - class Date - def self.coerce(input) - field = String.coerce(input) - return if field.blank? - - begin - ::Date.parse(field) - rescue ArgumentError - Rails.logger.info "Unable to parse date: #{field.first.inspect}" - end - end - end - end -end diff --git a/app/views/_controls.html.erb b/app/views/_controls.html.erb index a3695e84b..84f08da0d 100644 --- a/app/views/_controls.html.erb +++ b/app/views/_controls.html.erb @@ -1,20 +1,13 @@ - + \ No newline at end of file diff --git a/app/views/_masthead.html.erb b/app/views/_masthead.html.erb index 83c8a9494..c800d77dc 100644 --- a/app/views/_masthead.html.erb +++ b/app/views/_masthead.html.erb @@ -1,20 +1,12 @@ -
    -
    \ No newline at end of file diff --git a/app/views/_user_util_links.html.erb b/app/views/_user_util_links.html.erb index c2da425d3..7dd86dca5 100644 --- a/app/views/_user_util_links.html.erb +++ b/app/views/_user_util_links.html.erb @@ -1,4 +1,4 @@ -