hyrax 5.0.1 → 5.0.3

Sign up to get free protection for your applications and to get access to all the features.
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
+