hyrax 5.0.1 → 5.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (247) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +7 -176
  3. data/.dassie/.env +8 -3
  4. data/.dassie/Gemfile +13 -2
  5. data/.dassie/app/controllers/hyrax/generic_work_resources_controller.rb +17 -0
  6. data/.dassie/app/controllers/hyrax/generic_works_controller.rb +7 -1
  7. data/.dassie/app/forms/generic_work_resource_form.rb +20 -0
  8. data/.dassie/app/indexers/generic_work_resource_indexer.rb +16 -0
  9. data/.dassie/app/models/admin_set_resource.rb +9 -0
  10. data/.dassie/app/models/collection_resource.rb +2 -0
  11. data/.dassie/app/models/file_set.rb +2 -0
  12. data/.dassie/app/models/generic_work_resource.rb +10 -0
  13. data/.dassie/app/views/hyrax/generic_work_resources/_generic_work_resource.html.erb +2 -0
  14. data/.dassie/config/analytics.yml +6 -1
  15. data/.dassie/config/application.rb +24 -0
  16. data/.dassie/config/initializers/hyrax.rb +13 -3
  17. data/.dassie/config/initializers/wings.rb +109 -0
  18. data/.dassie/config/metadata/generic_work_resource.yaml +22 -0
  19. data/.dassie/config/valkyrie_index.yml +4 -10
  20. data/.dassie/db/migrate/20240506070809_valkyrie_id_to_string.rb +5 -0
  21. data/.dassie/db/schema.rb +2 -2
  22. data/.dassie/spec/indexers/generic_work_resource_indexer_spec.rb +13 -0
  23. data/.dassie/spec/models/generic_work_resource_spec.rb +12 -0
  24. data/.dassie/spec/views/generic_work_resources/_generic_work_resource.html.erb_spec.rb +7 -0
  25. data/.dockerignore +6 -4
  26. data/.github/release.yml +3 -0
  27. data/.github/workflows/lint-build-test.yml +130 -0
  28. data/.github/workflows/test-results.yml +40 -0
  29. data/.koppie/.env +7 -5
  30. data/.koppie/Gemfile +12 -1
  31. data/.koppie/config/analytics.yml +6 -1
  32. data/.koppie/config/environments/test.rb +2 -0
  33. data/.koppie/config/initializers/1_valkyrie.rb +6 -2
  34. data/.koppie/config/solr.yml +1 -1
  35. data/.regen +1 -1
  36. data/.rubocop.yml +5 -0
  37. data/Dockerfile +16 -36
  38. data/Gemfile +2 -0
  39. data/app/assets/javascripts/hydra-editor/field_manager.es6 +187 -0
  40. data/app/assets/javascripts/hyrax/analytics_events.js +48 -24
  41. data/app/assets/javascripts/hyrax/collapse.js +4 -4
  42. data/app/assets/javascripts/hyrax/file_manager/save_manager.es6 +2 -0
  43. data/app/assets/javascripts/hyrax/search.js +2 -3
  44. data/app/assets/javascripts/hyrax/select_work_type.es6 +3 -1
  45. data/app/assets/javascripts/hyrax/uploader.js +20 -18
  46. data/app/assets/javascripts/hyrax.js +1 -0
  47. data/app/assets/stylesheets/_bootstrap-default-overrides.scss +4 -0
  48. data/app/assets/stylesheets/hyrax/_card.scss +4 -0
  49. data/app/assets/stylesheets/hyrax/_catalog.scss +21 -0
  50. data/app/assets/stylesheets/hyrax/_collections.scss +1 -1
  51. data/app/assets/stylesheets/hyrax/_facets.scss +15 -3
  52. data/app/assets/stylesheets/hyrax/_featured.scss +4 -0
  53. data/app/assets/stylesheets/hyrax/_form.scss +4 -0
  54. data/app/assets/stylesheets/hyrax/_forms.scss +2 -1
  55. data/app/assets/stylesheets/hyrax/_nestable.scss +9 -8
  56. data/app/assets/stylesheets/hyrax/_select_work_type.scss +12 -0
  57. data/app/assets/stylesheets/hyrax/_styles.scss +4 -0
  58. data/app/assets/stylesheets/hyrax/_work-show.scss +3 -0
  59. data/app/controllers/concerns/hyrax/singular_subresource_controller.rb +7 -2
  60. data/app/controllers/concerns/hyrax/valkyrie_downloads_controller_behavior.rb +11 -2
  61. data/app/controllers/concerns/hyrax/works_controller_behavior.rb +9 -2
  62. data/app/controllers/hyrax/admin/analytics/collection_reports_controller.rb +2 -2
  63. data/app/controllers/hyrax/admin/analytics/work_reports_controller.rb +7 -8
  64. data/app/controllers/hyrax/dashboard/collections_controller.rb +2 -1
  65. data/app/controllers/hyrax/downloads_controller.rb +24 -3
  66. data/app/controllers/hyrax/file_sets_controller.rb +32 -6
  67. data/app/controllers/hyrax/my/works_controller.rb +20 -0
  68. data/app/controllers/hyrax/stats_controller.rb +1 -1
  69. data/app/controllers/hyrax/uploads_controller.rb +28 -2
  70. data/app/forms/hyrax/forms/admin/appearance.rb +1 -1
  71. data/app/forms/hyrax/forms/admin/collection_type_form.rb +1 -7
  72. data/app/forms/hyrax/forms/pcdm_collection_form.rb +9 -0
  73. data/app/forms/hyrax/forms/work_embargo_form.rb +6 -0
  74. data/app/forms/hyrax/forms/work_lease_form.rb +6 -0
  75. data/app/indexers/concerns/hyrax/location_indexer.rb +2 -2
  76. data/app/indexers/hyrax/indexers/file_set_indexer.rb +4 -0
  77. data/app/indexers/hyrax/indexers/resource_indexer.rb +1 -0
  78. data/app/indexers/hyrax/valkyrie_indexer.rb +3 -5
  79. data/app/jobs/migrate_files_to_valkyrie_job.rb +109 -0
  80. data/app/jobs/migrate_resources_job.rb +34 -0
  81. data/app/jobs/valkyrie_create_derivatives_job.rb +2 -1
  82. data/app/models/admin_set.rb +1 -0
  83. data/app/models/concerns/hyrax/ar_resource.rb +104 -0
  84. data/app/models/concerns/hyrax/solr_document/ordered_members.rb +2 -1
  85. data/app/models/concerns/hyrax/solr_document_behavior.rb +13 -2
  86. data/app/models/concerns/hyrax/valkyrie_lazy_migration.rb +82 -0
  87. data/app/models/file_download_stat.rb +1 -1
  88. data/app/models/file_view_stat.rb +1 -1
  89. data/app/models/hyrax/collection_type.rb +12 -4
  90. data/app/models/hyrax/file_metadata.rb +19 -0
  91. data/app/models/hyrax/file_set.rb +25 -0
  92. data/app/models/hyrax/model_registry.rb +2 -3
  93. data/app/models/hyrax/resource.rb +5 -0
  94. data/app/models/hyrax/statistic.rb +12 -37
  95. data/app/presenters/hyrax/file_set_presenter.rb +2 -1
  96. data/app/presenters/hyrax/file_usage.rb +3 -3
  97. data/app/presenters/hyrax/iiif_manifest_presenter.rb +2 -1
  98. data/app/presenters/hyrax/member_presenter_factory.rb +7 -1
  99. data/app/presenters/hyrax/menu_presenter.rb +1 -1
  100. data/app/presenters/hyrax/stats_usage_presenter.rb +2 -1
  101. data/app/presenters/hyrax/work_show_presenter.rb +13 -17
  102. data/app/presenters/hyrax/work_usage.rb +5 -2
  103. data/app/search_builders/hyrax/expired_embargo_search_builder.rb +7 -1
  104. data/app/search_builders/hyrax/expired_lease_search_builder.rb +7 -1
  105. data/app/search_builders/hyrax/filter_by_type.rb +1 -3
  106. data/app/search_builders/hyrax/valkyrie_abstract_type_relation.rb +7 -2
  107. data/app/services/hyrax/access_control_list.rb +1 -1
  108. data/app/services/hyrax/admin_set_create_service.rb +16 -5
  109. data/app/services/hyrax/admin_set_service.rb +2 -1
  110. data/app/services/hyrax/analytics/ga4/base.rb +96 -0
  111. data/app/services/hyrax/analytics/ga4/events.rb +25 -0
  112. data/app/services/hyrax/analytics/ga4/events_daily.rb +36 -0
  113. data/app/services/hyrax/analytics/ga4/visits.rb +33 -0
  114. data/app/services/hyrax/analytics/ga4/visits_daily.rb +24 -0
  115. data/app/services/hyrax/analytics/ga4.rb +204 -0
  116. data/app/services/hyrax/analytics/google.rb +16 -2
  117. data/app/services/hyrax/analytics/matomo.rb +16 -3
  118. data/app/services/hyrax/analytics/results.rb +6 -0
  119. data/app/services/hyrax/custom_queries/find_access_control.rb +1 -1
  120. data/app/services/hyrax/custom_queries/find_by_date_range.rb +6 -23
  121. data/app/services/hyrax/custom_queries/find_collections_by_type.rb +2 -2
  122. data/app/services/hyrax/custom_queries/find_count_by.rb +3 -31
  123. data/app/services/hyrax/custom_queries/find_file_metadata.rb +2 -2
  124. data/app/services/hyrax/custom_queries/find_models_by_access.rb +5 -27
  125. data/app/services/hyrax/embargo_manager.rb +2 -1
  126. data/app/services/hyrax/listeners/file_listener.rb +2 -2
  127. data/app/services/hyrax/lock_manager.rb +6 -6
  128. data/app/services/hyrax/lockable.rb +4 -3
  129. data/app/services/hyrax/simple_schema_loader.rb +1 -1
  130. data/app/services/hyrax/solr_service.rb +22 -8
  131. data/app/services/hyrax/statistics/query_service.rb +1 -1
  132. data/app/services/hyrax/statistics/works/over_time.rb +1 -1
  133. data/app/services/hyrax/thumbnail_path_service.rb +2 -0
  134. data/app/services/hyrax/user_stat_importer.rb +5 -5
  135. data/app/services/hyrax/valkyrie_upload.rb +9 -7
  136. data/app/services/hyrax/versioning_service.rb +10 -2
  137. data/app/services/hyrax/work_query_service.rb +2 -2
  138. data/app/services/migrate_resource_service.rb +55 -0
  139. data/app/views/_controls.html.erb +5 -5
  140. data/app/views/_masthead.html.erb +1 -1
  141. data/app/views/catalog/_search_form.html.erb +9 -16
  142. data/app/views/catalog/_thumbnail_list_collection.html.erb +1 -1
  143. data/app/views/catalog/_thumbnail_list_default.html.erb +2 -2
  144. data/app/views/hyrax/admin/analytics/collection_reports/index.html.erb +4 -4
  145. data/app/views/hyrax/admin/analytics/work_reports/index.html.erb +1 -1
  146. data/app/views/hyrax/admin/collection_types/_form.html.erb +4 -4
  147. data/app/views/hyrax/admin/collection_types/index.html.erb +1 -1
  148. data/app/views/hyrax/admin/features/index.html.erb +1 -1
  149. data/app/views/hyrax/base/_file_manager_actions.html.erb +1 -1
  150. data/app/views/hyrax/base/_file_manager_member.html.erb +7 -4
  151. data/app/views/hyrax/base/_file_manager_thumbnail.html.erb +1 -1
  152. data/app/views/hyrax/base/_form_files.html.erb +1 -1
  153. data/app/views/hyrax/base/_form_member_of_collections.html.erb +4 -0
  154. data/app/views/hyrax/base/_show_actions.html.erb +7 -8
  155. data/app/views/hyrax/base/_work_button_row.html.erb +1 -1
  156. data/app/views/hyrax/batch_select/_add_button.html.erb +1 -1
  157. data/app/views/hyrax/content_blocks/_form.html.erb +3 -3
  158. data/app/views/hyrax/dashboard/_sidebar.html.erb +1 -1
  159. data/app/views/hyrax/dashboard/_user_activity.html.erb +2 -2
  160. data/app/views/hyrax/dashboard/collections/_form.html.erb +4 -4
  161. data/app/views/hyrax/dashboard/collections/_form_share.html.erb +6 -4
  162. data/app/views/hyrax/dashboard/collections/_list_collections.html.erb +1 -1
  163. data/app/views/hyrax/dashboard/collections/_show_document_list_row.html.erb +1 -1
  164. data/app/views/hyrax/dashboard/show_admin.html.erb +18 -19
  165. data/app/views/hyrax/dashboard/sidebar/_activity.html.erb +1 -1
  166. data/app/views/hyrax/embargoes/_list_expired_active_embargoes.html.erb +7 -7
  167. data/app/views/hyrax/file_sets/_actions.html.erb +9 -1
  168. data/app/views/hyrax/file_sets/_permission_form.html.erb +4 -2
  169. data/app/views/hyrax/file_sets/_show_actions.html.erb +1 -1
  170. data/app/views/hyrax/homepage/_featured.html.erb +1 -1
  171. data/app/views/hyrax/homepage/_recent_document.html.erb +2 -2
  172. data/app/views/hyrax/leases/_list_expired_active_leases.html.erb +6 -6
  173. data/app/views/hyrax/my/collections/_list_collections.html.erb +1 -1
  174. data/app/views/hyrax/my/collections/_tabs.html.erb +1 -1
  175. data/app/views/hyrax/pages/_form.html.erb +8 -8
  176. data/app/views/hyrax/transfers/_received.html.erb +1 -1
  177. data/app/views/hyrax/uploads/create.json.jbuilder +2 -2
  178. data/app/views/hyrax/users/_activity_log.html.erb +15 -9
  179. data/app/views/hyrax/users/_user_row.html.erb +6 -3
  180. data/app/views/hyrax/users/_vitals.html.erb +3 -2
  181. data/app/views/layouts/_head_tag_content.html.erb +2 -0
  182. data/app/views/shared/_appearance_styles.html.erb +5 -1
  183. data/app/views/shared/_ga4.html.erb +11 -0
  184. data/app/views/shared/_select_work_type_modal.html.erb +10 -1
  185. data/bin/db-migrate-seed.sh +3 -3
  186. data/bin/dev-entrypoint.sh +7 -2
  187. data/bin/{db-wait.sh → service-wait.sh} +1 -1
  188. data/bin/worker-entrypoint.sh +8 -0
  189. data/chart/hyrax/templates/deployment-worker.yaml +2 -2
  190. data/config/locales/hyrax.en.yml +4 -2
  191. data/config/metadata/basic_metadata.yaml +20 -0
  192. data/config/metadata/hyrax_internal_metadata.yaml +1 -1
  193. data/docker-compose-dassie.yml +167 -0
  194. data/docker-compose-koppie.yml +21 -36
  195. data/docker-compose-sirenia.yml +50 -44
  196. data/docker-compose.yml +2 -183
  197. data/documentation/developing-your-hyrax-based-app.md +2 -2
  198. data/hyrax.gemspec +5 -4
  199. data/lib/freyja/custom_query_container.rb +5 -0
  200. data/lib/freyja/metadata_adapter.rb +32 -0
  201. data/lib/freyja/persister.rb +42 -0
  202. data/lib/freyja/query_service.rb +20 -0
  203. data/lib/freyja/resource_factory.rb +8 -0
  204. data/lib/freyja.rb +14 -0
  205. data/lib/frigg/custom_query_container.rb +5 -0
  206. data/lib/frigg/metadata_adapter.rb +22 -0
  207. data/lib/frigg/persister.rb +33 -0
  208. data/lib/frigg/query_service.rb +15 -0
  209. data/lib/frigg.rb +13 -0
  210. data/lib/generators/hyrax/install_generator.rb +5 -0
  211. data/lib/generators/hyrax/templates/config/analytics.yml +6 -1
  212. data/lib/generators/hyrax/templates/config/initializers/1_valkyrie.rb +6 -2
  213. data/lib/generators/hyrax/templates/config/valkyrie_index.yml +1 -1
  214. data/lib/goddess/custom_query_container.rb +71 -0
  215. data/lib/goddess/metadata.rb +13 -0
  216. data/lib/goddess/query.rb +176 -0
  217. data/lib/hyrax/configuration.rb +83 -0
  218. data/lib/hyrax/engine.rb +2 -0
  219. data/lib/hyrax/form_fields.rb +1 -3
  220. data/lib/hyrax/name.rb +5 -0
  221. data/lib/hyrax/rubocop/custom_cops.rb +30 -0
  222. data/lib/hyrax/specs/capybara.rb +10 -6
  223. data/lib/hyrax/specs/shared_specs/factories/admin_sets.rb +2 -0
  224. data/lib/hyrax/specs/shared_specs/factories/hyrax_embargo.rb +4 -0
  225. data/lib/hyrax/specs/shared_specs/factories/hyrax_lease.rb +4 -0
  226. data/lib/hyrax/specs/shared_specs/factories/hyrax_work.rb +16 -2
  227. data/lib/hyrax/specs/shared_specs/hydra_works.rb +1 -1
  228. data/lib/hyrax/transactions/admin_set_destroy.rb +2 -1
  229. data/lib/hyrax/transactions/collection_destroy.rb +2 -1
  230. data/lib/hyrax/transactions/container.rb +9 -0
  231. data/lib/hyrax/transactions/steps/add_file_sets.rb +2 -1
  232. data/lib/hyrax/transactions/steps/delete_permission_template.rb +30 -0
  233. data/lib/hyrax/transactions/steps/delete_resource.rb +1 -1
  234. data/lib/hyrax/transactions/steps/save_collection_logo.rb +2 -1
  235. data/lib/hyrax/valkyrie_can_can_adapter.rb +8 -1
  236. data/lib/hyrax/version.rb +1 -1
  237. data/lib/wings/active_fedora_converter.rb +13 -5
  238. data/lib/wings/converter_value_mapper.rb +1 -0
  239. data/lib/wings/services/custom_queries/find_collections_by_type.rb +2 -1
  240. data/lib/wings/services/custom_queries/find_file_metadata.rb +2 -2
  241. data/lib/wings/setup.rb +12 -3
  242. data/lib/wings/transformer_value_mapper.rb +5 -1
  243. data/lib/wings/valkyrie/persister.rb +3 -1
  244. data/template.rb +1 -1
  245. metadata +77 -19
  246. data/.koppie/scripts/db-migrate-seed.sh +0 -9
  247. data/.koppie/scripts/entrypoint.sh +0 -10
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Generated via
4
+ # `rails generate hyrax:work_resource GenericWorkResource`
5
+ RSpec.describe 'generic_work_resources/generic_work_resource.html.erb', type: :view do # rubocop:disable RSpec/EmptyExampleGroup
6
+ # add generic_work_resource view specs
7
+ end
data/.dockerignore CHANGED
@@ -14,9 +14,11 @@ artifacts/*
14
14
  coverage/*
15
15
  chart/*
16
16
 
17
- Gemfile.lock
18
- .dassie/Gemfile.lock
19
- .koppie/Gemfile.lock
17
+ Gemfile*lock
18
+ */Gemfile*lock
20
19
 
21
- node_modules/*
20
+
21
+ node_modules
22
+ */node_modules
22
23
  yarn.lock
24
+ */yarn.lock
data/.github/release.yml CHANGED
@@ -24,6 +24,9 @@ changelog:
24
24
  - title: Tests and CI Process
25
25
  labels:
26
26
  - notes-tests
27
+ - title: Accessibility Standards
28
+ labels:
29
+ - notes-accessibility
27
30
  - title: Other
28
31
  labels:
29
32
  - "*"
@@ -0,0 +1,130 @@
1
+ name: 'Lint Build Test'
2
+ run-name: Lint Build Test of ${{ github.ref_name }} by @${{ github.actor }}
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ pull_request:
8
+ branches:
9
+ - main
10
+ workflow_dispatch:
11
+ inputs:
12
+ debug_enabled:
13
+ type: boolean
14
+ description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)'
15
+ required: false
16
+ default: false
17
+
18
+ env:
19
+ REGISTRY: ghcr.io
20
+ DOCKER_BUILDKIT: 1
21
+ COMPOSE_DOCKER_CLI_BUILD: 1
22
+
23
+ jobs:
24
+ lint:
25
+ runs-on: ubuntu-latest
26
+ steps:
27
+ - uses: actions/checkout@v4
28
+ - uses: ruby/setup-ruby@v1
29
+ with:
30
+ ruby-version: '3.2'
31
+ bundler-cache: true
32
+ cache-version: 1
33
+ - name: Rubocop
34
+ run: bundle install && bundle exec rubocop --parallel --format progress --format junit --out rubocop.xml --display-only-failed
35
+ - name: Archive rubocop reports
36
+ uses: actions/upload-artifact@v4
37
+ if: always()
38
+ with:
39
+ name: rubocop-reports
40
+ path: 'rubocop*.xml'
41
+
42
+ build:
43
+ needs: lint
44
+ runs-on: ubuntu-latest
45
+ strategy:
46
+ fail-fast: false
47
+ steps:
48
+ - name: Checkout
49
+ uses: actions/checkout@v4
50
+ - name: Set up Docker Buildx
51
+ uses: docker/setup-buildx-action@v3
52
+ - name: Build and export
53
+ uses: docker/build-push-action@v6
54
+ with:
55
+ cache-from: type=gha
56
+ cache-to: type=gha, mode=max
57
+ context: .
58
+ target: hyrax-engine-dev
59
+ tags: samvera/hyrax-dev:latest,samvera/hyrax-dev:${{ github.sha }}
60
+ outputs: type=docker,dest=/tmp/hyrax-dev-${{ github.sha }}.tar
61
+ - name: Upload built image artifact
62
+ uses: actions/upload-artifact@v4
63
+ with:
64
+ name: hyrax-dev
65
+ path: /tmp/hyrax-dev-${{ github.sha }}.tar
66
+
67
+ test:
68
+ needs: build
69
+ runs-on: ubuntu-latest
70
+ strategy:
71
+ fail-fast: false
72
+ matrix:
73
+ ci_test_app: [dassie,koppie,sirenia]
74
+ ci_node_total: [4]
75
+ ci_node_index: [0,1,2,3]
76
+ steps:
77
+ - name: Checkout
78
+ uses: actions/checkout@v4
79
+ - name: Setup tmate debug session
80
+ uses: mxschmitt/action-tmate@v3
81
+ if: ${{ github.event_name == 'workflow_dispatch' && inputs.debug_enabled }}
82
+ with:
83
+ limit-access-to-actor: true
84
+ detached: true
85
+ - name: Download built image artifact
86
+ uses: actions/download-artifact@v4
87
+ with:
88
+ name: hyrax-dev
89
+ path: /tmp
90
+ - name: Start containers
91
+ run: |
92
+ docker load --input /tmp/hyrax-dev-${{ github.sha }}.tar
93
+ docker image ls -a
94
+ docker compose -f docker-compose-${{ matrix.ci_test_app }}.yml up -d --quiet-pull --pull missing --no-build
95
+ - name: RSpec
96
+ env:
97
+ CI_NODE_TOTAL: ${{ matrix.ci_node_total }}
98
+ CI_NODE_INDEX: ${{ matrix.ci_node_index }}
99
+ run: >-
100
+ docker compose -f docker-compose-${{ matrix.ci_test_app }}.yml exec -T -w /app/samvera/hyrax-engine web sh -c
101
+ "bundle install && yarn install && rspec_booster --job ${{ matrix.ci_node_index }}/${{ matrix.ci_node_total }}"
102
+ - name: Capture Container Logs
103
+ if: always()
104
+ uses: jwalton/gh-docker-logs@v2
105
+ with:
106
+ images: 'selenium/standalone-chromium,postgres,fcrepo/fcrepo,solr,bitnami/redis,ghcr.io/samvera/fitsservlet,ghcr.io/samvera/fcrepo4'
107
+ - name: Move Test Files
108
+ if: always()
109
+ env:
110
+ CI_TEST_APP: ${{ matrix.ci_test_app }}
111
+ CI_NODE_TOTAL: ${{ matrix.ci_node_total }}
112
+ CI_NODE_INDEX: ${{ matrix.ci_node_index }}
113
+ run: >-
114
+ mv rspec.xml rspec-${CI_TEST_APP}-${CI_NODE_INDEX}.xml
115
+ - name: Archive spec reports
116
+ uses: actions/upload-artifact@v4
117
+ if: always()
118
+ with:
119
+ name: spec-reports-${{ matrix.ci_test_app }}-${{ matrix.ci_node_index }}
120
+ path: '**/rspec*.xml'
121
+
122
+ event_file:
123
+ name: "Event File"
124
+ runs-on: ubuntu-latest
125
+ steps:
126
+ - name: Upload
127
+ uses: actions/upload-artifact@v4
128
+ with:
129
+ name: Event File
130
+ path: ${{ github.event_path }}
@@ -0,0 +1,40 @@
1
+ name: Test Results
2
+ run-name: Test Results of ${{ github.ref_name }} by @${{ github.actor }}
3
+ on:
4
+ workflow_run:
5
+ workflows: ["Lint Build Test"]
6
+ types:
7
+ - completed
8
+ permissions: {}
9
+
10
+ jobs:
11
+ test-results:
12
+ name: Test Results Check
13
+ runs-on: ubuntu-latest
14
+ if: github.event.workflow_run.conclusion != 'skipped'
15
+
16
+ permissions:
17
+ checks: write
18
+ # needed unless run with comment_mode: off
19
+ pull-requests: write
20
+ # required by download step to access artifacts API
21
+ actions: read
22
+
23
+ steps:
24
+ - name: Download and Extract Artifacts
25
+ uses: dawidd6/action-download-artifact@e7466d1a7587ed14867642c2ca74b5bcc1e19a2d
26
+ with:
27
+ run_id: ${{ github.event.workflow_run.id }}
28
+ path: artifacts
29
+ name: ".*(report|Event).*"
30
+ name_is_regexp: true
31
+
32
+ - name: Publish Test Results
33
+ uses: EnricoMi/publish-unit-test-result-action@v2
34
+ with:
35
+ commit: ${{ github.event.workflow_run.head_sha }}
36
+ event_file: artifacts/Event File/event.json
37
+ event_name: ${{ github.event.workflow_run.event }}
38
+ files: "artifacts/**/*.xml"
39
+ action_fail_on_inconclusive: true
40
+ fail_on: "test failures"
data/.koppie/.env CHANGED
@@ -2,7 +2,7 @@ APP_NAME=koppie
2
2
  BUNDLE_GEMFILE=Gemfile.koppie
3
3
  BUNDLE_PATH=/app/bundle
4
4
  CH12N_TOOL=fits_servlet
5
- CHROME_HEADLESS_MODE=false
5
+ CHROME_HEADLESS_MODE=true
6
6
  DATABASE_CLEANER_ALLOW_REMOTE_DATABASE_URL=true
7
7
  DATABASE_TEST_URL=postgresql://hyrax_user:hyrax_password@postgres/hyrax_test?pool=5
8
8
  DATABASE_URL=postgresql://hyrax_user:hyrax_password@postgres/hyrax?pool=5
@@ -20,7 +20,7 @@ HYRAX_UPLOAD_PATH=/app/samvera/hyrax-webapp/uploads/
20
20
  HYRAX_VALKYRIE=true
21
21
  IN_DOCKER=true
22
22
  KARMA_BROWSER=remote-chromium
23
- KARMA_HOSTNAME=app
23
+ KARMA_HOSTNAME=web
24
24
  MEMCACHED_HOST=memcached
25
25
  METADATA_DATABASE_NAME=koppie_metadata_development
26
26
  POSTGRES_DB=koppie
@@ -29,8 +29,8 @@ POSTGRES_PASSWORD=hyrax_password
29
29
  POSTGRES_USER=hyrax_user
30
30
  RACK_ENV=development
31
31
  RAILS_ENV=development
32
- RAILS_ROOT=.koppie
33
- RAILS_LOG_TO_STDOUT=true
32
+ RAILS_ROOT=/app/samvera/hyrax-webapp
33
+ RAILS_LOG_TO_STDOUT=false
34
34
  RAILS_QUEUE=sidekiq
35
35
  REDIS_HOST=redis
36
36
  REDIS_PASSWORD=sidekickin
@@ -43,6 +43,8 @@ SOLR_CORES=koppie
43
43
  SOLR_HOST=solr
44
44
  SOLR_PORT=8983
45
45
  SOLR_URL=http://solr:8983/solr/koppie
46
- SOLR_TEST_URL=http://solr:8983/solr/hydra-test
46
+ SOLR_TEST_URL=http://solr:8983/solr/koppie-test
47
+ TB_RSPEC_OPTIONS="--format RspecJunitFormatter --out rspec.xml"
48
+ TB_RSPEC_FORMATTER=progress
47
49
  VALKYRIE_METADATA_ADAPTER=pg_metadata
48
50
  VALKYRIE_STORAGE_ADAPTER=versioned_disk_storage
data/.koppie/Gemfile CHANGED
@@ -14,12 +14,23 @@ gem 'coffee-rails', '~> 4.2'
14
14
  gem 'dalli'
15
15
  gem 'devise'
16
16
  gem 'devise-guests', '~> 0.8'
17
+
18
+ # Required because grpc and google-protobuf gem's binaries are not compatible with Alpine Linux.
19
+ # To install the package in Alpine: `apk add ruby-grpc`
20
+ # The pinned versions should match the version provided by the Alpine packages.
21
+ if RUBY_PLATFORM =~ /musl/
22
+ path '/usr/lib/ruby/gems/3.2.0' do
23
+ gem 'google-protobuf', '~> 3.24.4', force_ruby_platform: true
24
+ gem 'grpc', '~> 1.59.3', force_ruby_platform: true
25
+ end
26
+ end
27
+
17
28
  gemspec name: 'hyrax', path: ENV.fetch('HYRAX_ENGINE_PATH', '..')
18
29
  gem 'jbuilder', '~> 2.5'
19
30
  gem 'jquery-rails'
20
31
  gem 'pg', '~> 1.3'
21
32
  gem 'puma'
22
- gem 'rails', '~> 6.1'
33
+ gem 'rails', '~> 6.1', '>= 6.1.7.10'
23
34
  gem 'riiif', '~> 2.1'
24
35
  gem 'rsolr', '>= 1.0', '< 3'
25
36
  gem 'sass-rails', '~> 6.0'
@@ -1,10 +1,15 @@
1
1
  analytics:
2
+ ga4:
3
+ analytics_id: <%= ENV['GOOGLE_ANALYTICS_ID'] %>
4
+ property_id: <%= ENV['GOOGLE_ANALYTICS_PROPERTY_ID'] %>
5
+ account_json: <%= ENV['GOOGLE_ACCOUNT_JSON'] %>
6
+ account_json_path: <%= ENV['GOOGLE_ACCOUNT_JSON_PATH'] %>
2
7
  google:
3
8
  analytics_id: <%= ENV['GOOGLE_ANALYTICS_ID'] %>
4
9
  app_name: <%= ENV['GOOGLE_OAUTH_APP_NAME'] %>
5
10
  app_version: <%= ENV['GOOGLE_OAUTH_APP_VERSION'] %>
6
- privkey_value: <%= ENV['GOOGLE_OAUTH_PRIVATE_KEY_VALUE'] %>
7
11
  privkey_path: <%= ENV['GOOGLE_OAUTH_PRIVATE_KEY_PATH'] %>
12
+ privkey_value: <%= ENV['GOOGLE_OAUTH_PRIVATE_KEY_VALUE'] %>
8
13
  privkey_secret: <%= ENV['GOOGLE_OAUTH_PRIVATE_KEY_SECRET'] %>
9
14
  client_email: <%= ENV['GOOGLE_OAUTH_CLIENT_EMAIL'] %>
10
15
  matomo:
@@ -44,4 +44,6 @@ Rails.application.configure do
44
44
 
45
45
  # Raises error for missing translations
46
46
  # config.action_view.raise_on_missing_translations = true
47
+
48
+ config.log_level = :warn
47
49
  end
@@ -34,7 +34,9 @@ Valkyrie::MetadataAdapter.register(
34
34
  ENV.fetch('FCREPO_URL') { "http://localhost:8080/fcrepo/rest" })),
35
35
  base_path: Rails.env,
36
36
  schema: Valkyrie::Persistence::Fedora::PermissiveSchema.new(Hyrax::SimpleSchemaLoader.new.permissive_schema_for_valkrie_adapter),
37
- fedora_version: 6
37
+ fedora_version: 6.5,
38
+ fedora_pairtree_count: 4,
39
+ fedora_pairtree_length: 2
38
40
  ), :fedora_metadata
39
41
  )
40
42
 
@@ -64,7 +66,9 @@ Valkyrie::StorageAdapter.register(
64
66
  connection: ::Ldp::Client.new(Hyrax.config.fedora_connection_builder.call(
65
67
  ENV.fetch('FCREPO_URL') { "http://localhost:8080/fcrepo/rest" })),
66
68
  base_path: Rails.env,
67
- fedora_version: 6
69
+ fedora_version: 6.5,
70
+ fedora_pairtree_count: 4,
71
+ fedora_pairtree_length: 2
68
72
  ), :fedora_storage
69
73
  )
70
74
 
@@ -2,6 +2,6 @@
2
2
  development:
3
3
  url: <%= ENV['SOLR_URL'] || "http://127.0.0.1:8983/solr/nurax-pg-solr-dev" %>
4
4
  test: &test
5
- url: <%= ENV['TEST_SOLR_URL'] ||ENV['SOLR_URL'] || "http://127.0.0.1:#{ENV.fetch('SOLR_TEST_PORT', 8985)}/solr/nurax-pg-test" %>
5
+ url: <%= ENV['SOLR_TEST_URL'] ||ENV['SOLR_URL'] || "http://127.0.0.1:#{ENV.fetch('SOLR_TEST_PORT', 8985)}/solr/nurax-pg-test" %>
6
6
  production:
7
7
  url: <%= ENV['SOLR_URL'] || "http://127.0.0.1:8983/solr/nurax-pg" %>
data/.regen CHANGED
@@ -1,2 +1,2 @@
1
1
  # When updating CI regen seed, set to current date.
2
- 2023-08-09T14:34:59
2
+ 2024-09-09T14:34:59
data/.rubocop.yml CHANGED
@@ -1,3 +1,5 @@
1
+ require: ./lib/hyrax/rubocop/custom_cops.rb
2
+
1
3
  inherit_from:
2
4
  - .rubocop_fixme.yml
3
5
 
@@ -125,3 +127,6 @@ RSpec/NestedGroups:
125
127
 
126
128
  RSpec/LeadingSubject:
127
129
  Enabled: false
130
+
131
+ Hyrax/ArResource:
132
+ Enabled: true
data/Dockerfile CHANGED
@@ -1,7 +1,7 @@
1
1
  ARG ALPINE_VERSION=3.19
2
- ARG RUBY_VERSION=3.2.3
2
+ ARG RUBY_VERSION=3.2.6
3
3
 
4
- FROM ruby:$RUBY_VERSION-alpine$ALPINE_VERSION as hyrax-base
4
+ FROM ruby:$RUBY_VERSION-alpine$ALPINE_VERSION AS hyrax-base
5
5
 
6
6
  ARG DATABASE_APK_PACKAGE="postgresql-dev"
7
7
  ARG EXTRA_APK_PACKAGES="git"
@@ -21,6 +21,7 @@ RUN apk --no-cache upgrade && \
21
21
  imagemagick-tiff \
22
22
  imagemagick-webp \
23
23
  jemalloc \
24
+ ruby-grpc \
24
25
  tzdata \
25
26
  nodejs \
26
27
  yarn \
@@ -29,7 +30,7 @@ RUN apk --no-cache upgrade && \
29
30
  $EXTRA_APK_PACKAGES
30
31
 
31
32
  RUN setfacl -d -m o::rwx /usr/local/bundle && \
32
- gem update --system $RUBYGEMS_VERSION
33
+ gem update --silent --system $RUBYGEMS_VERSION
33
34
 
34
35
  RUN addgroup -S --gid 101 app && \
35
36
  adduser -S -G app -u 1001 -s /bin/sh -h /app app
@@ -48,7 +49,7 @@ ENTRYPOINT ["hyrax-entrypoint.sh"]
48
49
  CMD ["bundle", "exec", "puma", "-v", "-b", "tcp://0.0.0.0:3000"]
49
50
 
50
51
 
51
- FROM hyrax-base as hyrax
52
+ FROM hyrax-base AS hyrax
52
53
 
53
54
  ARG APP_PATH=.
54
55
  ARG BUNDLE_WITHOUT="development test"
@@ -58,7 +59,7 @@ ONBUILD RUN bundle install --jobs "$(nproc)"
58
59
  ONBUILD RUN RAILS_ENV=production SECRET_KEY_BASE=`bin/rake secret` DB_ADAPTER=nulldb DATABASE_URL='postgresql://fake' bundle exec rake assets:precompile
59
60
 
60
61
 
61
- FROM hyrax-base as hyrax-worker-base
62
+ FROM hyrax-base AS hyrax-worker-base
62
63
 
63
64
  USER root
64
65
  RUN apk --no-cache add bash \
@@ -77,10 +78,10 @@ RUN mkdir -p /app/fits && \
77
78
  sed -i 's/\(<tool.*TikaTool.*>\)/<!--\1-->/' /app/fits/xml/fits.xml
78
79
  ENV PATH="${PATH}:/app/fits"
79
80
 
80
- CMD bundle exec sidekiq
81
+ CMD ["bundle", "exec", "sidekiq"]
81
82
 
82
83
 
83
- FROM hyrax-worker-base as hyrax-worker
84
+ FROM hyrax-worker-base AS hyrax-worker
84
85
 
85
86
  ARG APP_PATH=.
86
87
  ARG BUNDLE_WITHOUT="development test"
@@ -90,40 +91,19 @@ ONBUILD RUN bundle install --jobs "$(nproc)"
90
91
  ONBUILD RUN RAILS_ENV=production SECRET_KEY_BASE=`bin/rake secret` DB_ADAPTER=nulldb DATABASE_URL='postgresql://fake' bundle exec rake assets:precompile
91
92
 
92
93
 
93
- FROM hyrax-base as hyrax-engine-dev
94
+ FROM hyrax-worker-base AS hyrax-engine-dev
94
95
 
95
- USER root
96
- RUN apk --no-cache add bash \
97
- ffmpeg \
98
- mediainfo \
99
- perl
100
96
  USER app
101
-
102
- ARG APP_PATH=.dassie
103
97
  ARG BUNDLE_WITHOUT=
98
+ ENV HYRAX_ENGINE_PATH=/app/samvera/hyrax-engine
104
99
 
105
- ENV HYRAX_ENGINE_PATH /app/samvera/hyrax-engine
106
-
107
- COPY --chown=1001:101 $APP_PATH /app/samvera/hyrax-webapp
100
+ COPY --chown=1001:101 .dassie /app/samvera/hyrax-webapp
108
101
  COPY --chown=1001:101 . /app/samvera/hyrax-engine
109
102
 
110
103
  RUN bundle -v && \
111
- bundle install --jobs "$(nproc)" && \
112
- cd $HYRAX_ENGINE_PATH && \
113
- bundle install --jobs "$(nproc)" && \
114
- yarn
115
-
116
- RUN RAILS_ENV=production SECRET_KEY_BASE='fakesecret1234' DB_ADAPTER=nulldb DATABASE_URL='postgresql://fake' bundle exec rake assets:precompile
117
-
118
-
119
- FROM hyrax-worker-base as hyrax-engine-dev-worker
120
-
121
- ARG APP_PATH=.dassie
122
- ARG BUNDLE_WITHOUT=
123
-
124
- ENV HYRAX_ENGINE_PATH /app/samvera/hyrax-engine
125
-
126
- COPY --chown=1001:101 $APP_PATH /app/samvera/hyrax-webapp
127
- COPY --chown=1001:101 . /app/samvera/hyrax-engine
104
+ BUNDLE_GEMFILE=Gemfile.dassie bundle install --jobs "$(nproc)" && yarn && \
105
+ cd $HYRAX_ENGINE_PATH && bundle install --jobs "$(nproc)" && yarn && \
106
+ yarn cache clean
128
107
 
129
- RUN bundle install --jobs "$(nproc)"
108
+ ENTRYPOINT ["dev-entrypoint.sh"]
109
+ CMD ["bundle", "exec", "puma", "-v", "-b", "tcp://0.0.0.0:3000"]
data/Gemfile CHANGED
@@ -17,6 +17,8 @@ group :development, :test do
17
17
  gem 'okcomputer'
18
18
  gem 'pry' unless ENV['CI']
19
19
  gem 'pry-byebug' unless ENV['CI']
20
+ gem 'rspec'
20
21
  gem 'ruby-prof', require: false
22
+ gem 'semaphore_test_boosters'
21
23
  gem "simplecov", require: false
22
24
  end
@@ -0,0 +1,187 @@
1
+ export class FieldManager {
2
+ constructor(element, options) {
3
+ this.element = $(element);
4
+
5
+ this.options = options;
6
+
7
+ this.options.label = this.getFieldLabel(this.element, options)
8
+
9
+ this.addSelector = '.add'
10
+ this.removeSelector = '.remove'
11
+
12
+ this.adder = this.createAddHtml(this.options)
13
+ this.remover = this.createRemoveHtml(this.options)
14
+
15
+ this.controls = $(options.controlsHtml);
16
+
17
+ this.inputTypeClass = options.inputTypeClass;
18
+ this.fieldWrapperClass = options.fieldWrapperClass;
19
+ this.warningClass = options.warningClass;
20
+ this.listClass = options.listClass;
21
+
22
+ this.init();
23
+ }
24
+
25
+ // call _addInitialID
26
+ init() {
27
+ this._addInitialClasses();
28
+ this._addInitialID();
29
+ this._addAriaLiveRegions();
30
+ this._appendControls();
31
+ this._attachEvents();
32
+ this._addCallbacks();
33
+ }
34
+
35
+ _addInitialClasses() {
36
+ this.element.addClass("managed");
37
+ $(this.fieldWrapperClass, this.element).addClass("input-group input-append");
38
+ }
39
+
40
+ // ensure ID is assigned
41
+ _addInitialID() {
42
+ let id = this.element.find('.multi_value.form-control').attr('id') + '_' + 'label';
43
+ if (id != "undefined_label"){
44
+ this.element.find('label').attr('id', id);
45
+ }
46
+ }
47
+
48
+ _addAriaLiveRegions() {
49
+ $(this.element).find('.listing').attr('aria-live', 'polite')
50
+ }
51
+
52
+ // Add the "Add another" and "Remove" controls to the DOM
53
+ _appendControls() {
54
+ // We want to make these DOM additions idempotently, so exit if it's
55
+ // already set up.
56
+ if (!this._hasRemoveControl()) {
57
+ this._createRemoveWrapper()
58
+ this._createRemoveControl()
59
+ }
60
+
61
+ if (!this._hasAddControl()) {
62
+ this._createAddControl()
63
+ }
64
+ }
65
+
66
+ _createRemoveWrapper() {
67
+ $(this.fieldWrapperClass, this.element).append(this.controls);
68
+ }
69
+
70
+ _createRemoveControl() {
71
+ $(this.fieldWrapperClass + ' .field-controls', this.element).append(this.remover)
72
+ }
73
+
74
+ _createAddControl() {
75
+ this.element.find(this.listClass).after(this.adder)
76
+ }
77
+
78
+ _hasRemoveControl() {
79
+ return this.element.find(this.removeSelector).length > 0
80
+ }
81
+
82
+ _hasAddControl() {
83
+ return this.element.find(this.addSelector).length > 0
84
+ }
85
+
86
+ _attachEvents() {
87
+ this.element.on('click', this.removeSelector, (e) => this.removeFromList(e))
88
+ this.element.on('click', this.addSelector, (e) => this.addToList(e))
89
+ }
90
+
91
+ _addCallbacks() {
92
+ this.element.bind('managed_field:add', this.options.add);
93
+ this.element.bind('managed_field:remove', this.options.remove);
94
+ }
95
+
96
+ _manageFocus() {
97
+ $(this.element).find(this.listClass).children('li').last().find('.form-control').focus();
98
+ }
99
+
100
+ addToList( event ) {
101
+ event.preventDefault();
102
+ let $listing = $(event.target).closest(this.inputTypeClass).find(this.listClass)
103
+ let $activeField = $listing.children('li').last()
104
+
105
+ if (this.inputIsEmpty($activeField)) {
106
+ this.displayEmptyWarning();
107
+ } else {
108
+ this.clearEmptyWarning();
109
+ $listing.append(this._newField($activeField));
110
+ }
111
+
112
+ this._manageFocus()
113
+ }
114
+
115
+ inputIsEmpty($activeField) {
116
+ return $activeField.children('input.multi-text-field').val() === '';
117
+ }
118
+
119
+ _newField ($activeField) {
120
+ var $newField = this.createNewField($activeField);
121
+ return $newField;
122
+ }
123
+
124
+ createNewField($activeField) {
125
+ let $newField = $activeField.clone();
126
+ let $newChildren = this.createNewChildren($newField);
127
+ this.element.trigger("managed_field:add", $newChildren);
128
+ return $newField;
129
+ }
130
+
131
+ clearEmptyWarning() {
132
+ let $listing = $(this.listClass, this.element)
133
+ $listing.children(this.warningClass).remove();
134
+ }
135
+
136
+ displayEmptyWarning() {
137
+ let $listing = $(this.listClass, this.element)
138
+ var $warningMessage = $("<div class=\'message has-warning\'>cannot add another with empty field</div>");
139
+ $listing.children(this.warningClass).remove();
140
+ $listing.append($warningMessage);
141
+ }
142
+
143
+ removeFromList( event ) {
144
+ event.preventDefault();
145
+ var $field = $(event.target).parents(this.fieldWrapperClass).remove();
146
+ this.element.trigger("managed_field:remove", $field);
147
+
148
+ this._manageFocus();
149
+ }
150
+
151
+ destroy() {
152
+ $(this.fieldWrapperClass, this.element).removeClass("input-append");
153
+ this.element.removeClass("managed");
154
+ }
155
+
156
+ getFieldLabel($element, options) {
157
+ var label = '';
158
+ var $label = $element.find("label").first();
159
+ if ($label.length && options.labelControls) {
160
+ var label = $label.data('label') || $.trim($label.contents().filter(function() { return this.nodeType === 3; }).text());
161
+ label = ' ' + label;
162
+ }
163
+
164
+ return label;
165
+ }
166
+
167
+ createAddHtml(options) {
168
+ var $addHtml = $(options.addHtml);
169
+ $addHtml.find('.controls-add-text').html(options.addText + options.label);
170
+ return $addHtml;
171
+ }
172
+
173
+ createRemoveHtml(options) {
174
+ var $removeHtml = $(options.removeHtml);
175
+ $removeHtml.find('.controls-remove-text').html(options.removeText);
176
+ $removeHtml.find('.controls-field-name-text').html(options.label);
177
+ return $removeHtml;
178
+ }
179
+
180
+ createNewChildren(clone) {
181
+ let $newChildren = $(clone).children(this.inputTypeClass);
182
+ $newChildren.val('').removeAttr('required');
183
+ $newChildren.first().focus();
184
+ return $newChildren.first();
185
+ }
186
+ }
187
+