hyrax 5.2.0 → 5.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (527) hide show
  1. checksums.yaml +4 -4
  2. data/.dassie/.env +5 -1
  3. data/.dassie/Gemfile +4 -2
  4. data/.dassie/app/assets/images/bulkrax/removed.png +0 -0
  5. data/.dassie/app/assets/javascripts/application.js +2 -0
  6. data/.dassie/app/assets/stylesheets/application.css +1 -0
  7. data/.dassie/app/controllers/catalog_controller.rb +1 -0
  8. data/.dassie/app/forms/admin_set_resource_form.rb +6 -0
  9. data/.dassie/app/forms/collection_resource_form.rb +5 -2
  10. data/.dassie/app/forms/generic_work_resource_form.rb +5 -2
  11. data/.dassie/app/forms/monograph_form.rb +5 -3
  12. data/.dassie/app/indexers/admin_set_resource_indexer.rb +5 -0
  13. data/.dassie/app/indexers/collection_resource_indexer.rb +3 -3
  14. data/.dassie/app/indexers/generic_work_resource_indexer.rb +6 -3
  15. data/.dassie/app/indexers/monograph_indexer.rb +6 -2
  16. data/.dassie/app/models/ability.rb +8 -0
  17. data/.dassie/app/models/collection_resource.rb +4 -2
  18. data/.dassie/app/models/concerns/bulkrax/has_local_processing.rb +8 -0
  19. data/.dassie/app/models/generic_work_resource.rb +5 -2
  20. data/.dassie/app/models/monograph.rb +5 -2
  21. data/.dassie/app/views/blacklight_dynamic_sitemap/sitemap/show.xml.builder +22 -0
  22. data/.dassie/bin/importer +142 -0
  23. data/.dassie/bin/web +4 -0
  24. data/.dassie/config/browse_everything_providers.yml +1 -1
  25. data/.dassie/config/bulkrax_api.yml +86 -0
  26. data/.dassie/config/initializers/bulkrax.rb +92 -0
  27. data/.dassie/config/initializers/clamav.rb +2 -0
  28. data/.dassie/config/initializers/hyrax.rb +7 -1
  29. data/.dassie/config/initializers/riiif.rb +4 -80
  30. data/.dassie/config/initializers/wings.rb +1 -1
  31. data/.dassie/config/metadata_profiles/m3_profile.yaml +929 -0
  32. data/.dassie/config/puma.rb +4 -2
  33. data/.dassie/config/routes.rb +7 -0
  34. data/.dassie/config/sidekiq.yml +17 -0
  35. data/.dassie/config/uv/uv.html +63 -81
  36. data/.dassie/db/migrate/20240606205215_create_hyrax_flexible_schemas.rb +9 -0
  37. data/.dassie/db/migrate/20240606205216_add_contexts_to_hyrax_flexible_schemas.rb +5 -0
  38. data/.dassie/db/migrate/20250826142438_create_bulkrax_importers.bulkrax.rb +19 -0
  39. data/.dassie/db/migrate/20250826142439_create_bulkrax_importer_runs.bulkrax.rb +17 -0
  40. data/.dassie/db/migrate/20250826142440_create_bulkrax_entries.bulkrax.rb +17 -0
  41. data/.dassie/db/migrate/20250826142441_add_status_to_entry.bulkrax.rb +10 -0
  42. data/.dassie/db/migrate/20250826142442_add_collections_to_importer_runs.bulkrax.rb +7 -0
  43. data/.dassie/db/migrate/20250826142443_change_collection_ids_on_entries.bulkrax.rb +6 -0
  44. data/.dassie/db/migrate/20250826142444_create_bulkrax_exporters.bulkrax.rb +20 -0
  45. data/.dassie/db/migrate/20250826142445_create_bulkrax_exporter_runs.bulkrax.rb +15 -0
  46. data/.dassie/db/migrate/20250826142446_change_importer_and_exporter_to_polymorphic.bulkrax.rb +19 -0
  47. data/.dassie/db/migrate/20250826142447_add_total_collection_records_to_importer_runs.bulkrax.rb +6 -0
  48. data/.dassie/db/migrate/20250826142448_add_children_to_importer_runs.bulkrax.rb +7 -0
  49. data/.dassie/db/migrate/20250826142449_change_total_records_to_total_work_entries.bulkrax.rb +7 -0
  50. data/.dassie/db/migrate/20250826142450_change_entry_last_error.bulkrax.rb +20 -0
  51. data/.dassie/db/migrate/20250826142451_add_validate_only_to_bulkrax_importers.bulkrax.rb +6 -0
  52. data/.dassie/db/migrate/20250826142452_add_status_to_importers.bulkrax.rb +10 -0
  53. data/.dassie/db/migrate/20250826142453_remove_foreign_key_from_bulkrax_entries.bulkrax.rb +6 -0
  54. data/.dassie/db/migrate/20250826142454_add_status_to_exporters.bulkrax.rb +8 -0
  55. data/.dassie/db/migrate/20250826142455_add_invalid_record_to_importer_run.bulkrax.rb +6 -0
  56. data/.dassie/db/migrate/20250826142456_create_bulkrax_statuses.bulkrax.rb +19 -0
  57. data/.dassie/db/migrate/20250826142457_move_to_statuses.bulkrax.rb +31 -0
  58. data/.dassie/db/migrate/20250826142458_add_date_filter_and_status_to_bulkrax_exporters.bulkrax.rb +8 -0
  59. data/.dassie/db/migrate/20250826142459_add_workflow_status_to_bulkrax_exporter.bulkrax.rb +6 -0
  60. data/.dassie/db/migrate/20250826142460_remove_unused_last_error.bulkrax.rb +8 -0
  61. data/.dassie/db/migrate/20250826142461_increase_text_sizes.bulkrax.rb +13 -0
  62. data/.dassie/db/migrate/20250826142462_change_bulkrax_statuses_error_message_column_type_to_text.bulkrax.rb +6 -0
  63. data/.dassie/db/migrate/20250826142463_rename_children_counters_to_relationships.bulkrax.rb +7 -0
  64. data/.dassie/db/migrate/20250826142464_add_file_set_counters_to_importer_runs.bulkrax.rb +8 -0
  65. data/.dassie/db/migrate/20250826142465_add_import_attempts_to_entries.bulkrax.rb +6 -0
  66. data/.dassie/db/migrate/20250826142466_add_work_counters_to_importer_runs.bulkrax.rb +7 -0
  67. data/.dassie/db/migrate/20250826142467_create_bulkrax_pending_relationships.bulkrax.rb +14 -0
  68. data/.dassie/db/migrate/20250826142468_add_order_to_bulkrax_pending_relationships.bulkrax.rb +6 -0
  69. data/.dassie/db/migrate/20250826142469_add_include_thumbnails_to_bulkrax_exporters.bulkrax.rb +6 -0
  70. data/.dassie/db/migrate/20250826142470_add_generated_metadata_to_bulkrax_exporters.bulkrax.rb +6 -0
  71. data/.dassie/db/migrate/20250826142471_rename_bulkrax_importer_run_to_importer_run.bulkrax.rb +18 -0
  72. data/.dassie/db/migrate/20250826142472_add_indices_to_bulkrax.bulkrax.rb +26 -0
  73. data/.dassie/db/migrate/20250826142473_denormalize_status_message.bulkrax.rb +8 -0
  74. data/.dassie/db/migrate/20250826142474_update_identifier_index.bulkrax.rb +7 -0
  75. data/.dassie/db/migrate/20250826142475_add_index_to_metadata_bulkrax_identifier.bulkrax.rb +19 -0
  76. data/.dassie/db/migrate/20250826142476_add_file_name_to_uploaded_files.bulkrax.rb +6 -0
  77. data/.dassie/db/migrate/20250826142477_add_error_tracking_to_pending_relationships.bulkrax.rb +6 -0
  78. data/.dassie/db/migrate/20250826142478_add_last_imported_at_to_bulkrax_importers.bulkrax.rb +6 -0
  79. data/.dassie/db/migrate/20250826142479_add_next_import_at_to_bulkrax_importers.bulkrax.rb +6 -0
  80. data/.dassie/db/migrate/20250826142480_entry_error_denormalization.bulkrax.rb +8 -0
  81. data/.dassie/db/migrate/20250826142481_faster_first_entry.bulkrax.rb +8 -0
  82. data/.dassie/db/migrate/20260430000001_create_hyrax_redirect_paths.hyrax.rb +13 -0
  83. data/.dassie/db/migrate/20260521003627_add_additional_redirect_info.hyrax.rb +32 -0
  84. data/.dassie/db/schema.rb +154 -1
  85. data/.dassie/package.json +1 -1
  86. data/.dassie/rspec_split_configuration.json +835 -0
  87. data/.dassie/solr/conf/solrconfig.xml +21 -5
  88. data/.github/{ISSUE_TEMPLATE.md → ISSUE_TEMPLATE/issue_template.md} +5 -0
  89. data/.github/workflows/lint-build-test.yml +5 -1
  90. data/.github/workflows/release-charts.yml +48 -0
  91. data/.gitignore +6 -0
  92. data/.koppie/.env +5 -1
  93. data/.koppie/Gemfile +3 -1
  94. data/.koppie/app/assets/images/bulkrax/removed.png +0 -0
  95. data/.koppie/app/assets/javascripts/application.js +2 -0
  96. data/.koppie/app/assets/stylesheets/application.css +1 -0
  97. data/.koppie/app/controllers/catalog_controller.rb +1 -1
  98. data/.koppie/app/forms/collection_resource_form.rb +5 -2
  99. data/.koppie/app/forms/file_set_form.rb +5 -0
  100. data/.koppie/app/forms/generic_work_form.rb +5 -3
  101. data/.koppie/app/forms/monograph_form.rb +5 -3
  102. data/.koppie/app/indexers/collection_resource_indexer.rb +5 -2
  103. data/.koppie/app/indexers/file_set_indexer.rb +7 -0
  104. data/.koppie/app/indexers/generic_work_indexer.rb +6 -3
  105. data/.koppie/app/indexers/monograph_indexer.rb +6 -2
  106. data/.koppie/app/models/ability.rb +8 -0
  107. data/.koppie/app/models/collection_resource.rb +4 -2
  108. data/.koppie/app/models/concerns/bulkrax/has_local_processing.rb +8 -0
  109. data/.koppie/app/models/generic_work.rb +5 -2
  110. data/.koppie/app/models/monograph.rb +5 -2
  111. data/.koppie/app/views/blacklight_dynamic_sitemap/sitemap/show.xml.builder +22 -0
  112. data/.koppie/bin/importer +142 -0
  113. data/.koppie/bin/web +4 -0
  114. data/.koppie/config/browse_everything_providers.yml +2 -0
  115. data/.koppie/config/bulkrax_api.yml +86 -0
  116. data/.koppie/config/initializers/bulkrax.rb +92 -0
  117. data/.koppie/config/initializers/clamav.rb +2 -0
  118. data/.koppie/config/initializers/hyrax.rb +11 -3
  119. data/.koppie/config/initializers/riiif.rb +4 -82
  120. data/.koppie/config/metadata_profiles/m3_profile.yaml +930 -0
  121. data/.koppie/config/routes.rb +7 -0
  122. data/.koppie/config/sidekiq.yml +2 -0
  123. data/.koppie/config/uv/uv.html +63 -81
  124. data/.koppie/db/migrate/20240606205215_create_hyrax_flexible_schemas.rb +9 -0
  125. data/.koppie/db/migrate/20240606205216_add_contexts_to_hyrax_flexible_schemas.rb +5 -0
  126. data/.koppie/db/migrate/20250826142438_create_bulkrax_importers.bulkrax.rb +19 -0
  127. data/.koppie/db/migrate/20250826142439_create_bulkrax_importer_runs.bulkrax.rb +17 -0
  128. data/.koppie/db/migrate/20250826142440_create_bulkrax_entries.bulkrax.rb +17 -0
  129. data/.koppie/db/migrate/20250826142441_add_status_to_entry.bulkrax.rb +10 -0
  130. data/.koppie/db/migrate/20250826142442_add_collections_to_importer_runs.bulkrax.rb +7 -0
  131. data/.koppie/db/migrate/20250826142443_change_collection_ids_on_entries.bulkrax.rb +6 -0
  132. data/.koppie/db/migrate/20250826142444_create_bulkrax_exporters.bulkrax.rb +20 -0
  133. data/.koppie/db/migrate/20250826142445_create_bulkrax_exporter_runs.bulkrax.rb +15 -0
  134. data/.koppie/db/migrate/20250826142446_change_importer_and_exporter_to_polymorphic.bulkrax.rb +19 -0
  135. data/.koppie/db/migrate/20250826142447_add_total_collection_records_to_importer_runs.bulkrax.rb +6 -0
  136. data/.koppie/db/migrate/20250826142448_add_children_to_importer_runs.bulkrax.rb +7 -0
  137. data/.koppie/db/migrate/20250826142449_change_total_records_to_total_work_entries.bulkrax.rb +7 -0
  138. data/.koppie/db/migrate/20250826142450_change_entry_last_error.bulkrax.rb +20 -0
  139. data/.koppie/db/migrate/20250826142451_add_validate_only_to_bulkrax_importers.bulkrax.rb +6 -0
  140. data/.koppie/db/migrate/20250826142452_add_status_to_importers.bulkrax.rb +10 -0
  141. data/.koppie/db/migrate/20250826142453_remove_foreign_key_from_bulkrax_entries.bulkrax.rb +6 -0
  142. data/.koppie/db/migrate/20250826142454_add_status_to_exporters.bulkrax.rb +8 -0
  143. data/.koppie/db/migrate/20250826142455_add_invalid_record_to_importer_run.bulkrax.rb +6 -0
  144. data/.koppie/db/migrate/20250826142456_create_bulkrax_statuses.bulkrax.rb +19 -0
  145. data/.koppie/db/migrate/20250826142457_move_to_statuses.bulkrax.rb +31 -0
  146. data/.koppie/db/migrate/20250826142458_add_date_filter_and_status_to_bulkrax_exporters.bulkrax.rb +8 -0
  147. data/.koppie/db/migrate/20250826142459_add_workflow_status_to_bulkrax_exporter.bulkrax.rb +6 -0
  148. data/.koppie/db/migrate/20250826142460_remove_unused_last_error.bulkrax.rb +8 -0
  149. data/.koppie/db/migrate/20250826142461_increase_text_sizes.bulkrax.rb +13 -0
  150. data/.koppie/db/migrate/20250826142462_change_bulkrax_statuses_error_message_column_type_to_text.bulkrax.rb +6 -0
  151. data/.koppie/db/migrate/20250826142463_rename_children_counters_to_relationships.bulkrax.rb +7 -0
  152. data/.koppie/db/migrate/20250826142464_add_file_set_counters_to_importer_runs.bulkrax.rb +8 -0
  153. data/.koppie/db/migrate/20250826142465_add_import_attempts_to_entries.bulkrax.rb +6 -0
  154. data/.koppie/db/migrate/20250826142466_add_work_counters_to_importer_runs.bulkrax.rb +7 -0
  155. data/.koppie/db/migrate/20250826142467_create_bulkrax_pending_relationships.bulkrax.rb +14 -0
  156. data/.koppie/db/migrate/20250826142468_add_order_to_bulkrax_pending_relationships.bulkrax.rb +6 -0
  157. data/.koppie/db/migrate/20250826142469_add_include_thumbnails_to_bulkrax_exporters.bulkrax.rb +6 -0
  158. data/.koppie/db/migrate/20250826142470_add_generated_metadata_to_bulkrax_exporters.bulkrax.rb +6 -0
  159. data/.koppie/db/migrate/20250826142471_rename_bulkrax_importer_run_to_importer_run.bulkrax.rb +18 -0
  160. data/.koppie/db/migrate/20250826142472_add_indices_to_bulkrax.bulkrax.rb +26 -0
  161. data/.koppie/db/migrate/20250826142473_denormalize_status_message.bulkrax.rb +8 -0
  162. data/.koppie/db/migrate/20250826142474_update_identifier_index.bulkrax.rb +7 -0
  163. data/.koppie/db/migrate/20250826142475_add_index_to_metadata_bulkrax_identifier.bulkrax.rb +19 -0
  164. data/.koppie/db/migrate/20250826142476_add_file_name_to_uploaded_files.bulkrax.rb +6 -0
  165. data/.koppie/db/migrate/20250826142477_add_error_tracking_to_pending_relationships.bulkrax.rb +6 -0
  166. data/.koppie/db/migrate/20250826142478_add_last_imported_at_to_bulkrax_importers.bulkrax.rb +6 -0
  167. data/.koppie/db/migrate/20250826142479_add_next_import_at_to_bulkrax_importers.bulkrax.rb +6 -0
  168. data/.koppie/db/migrate/20250826142480_entry_error_denormalization.bulkrax.rb +8 -0
  169. data/.koppie/db/migrate/20250826142481_faster_first_entry.bulkrax.rb +8 -0
  170. data/.koppie/db/migrate/20260430000001_create_hyrax_redirect_paths.hyrax.rb +13 -0
  171. data/.koppie/db/migrate/20260521003627_add_additional_redirect_info.hyrax.rb +32 -0
  172. data/.koppie/db/schema.rb +154 -1
  173. data/.koppie/package.json +1 -1
  174. data/.koppie/rspec_split_configuration.json +835 -0
  175. data/.koppie/solr/conf/solrconfig.xml +0 -5
  176. data/.koppie/yarn.lock +5587 -752
  177. data/.rubocop.yml +1 -0
  178. data/CONTAINERS.md +2 -0
  179. data/Dockerfile +9 -22
  180. data/Gemfile +0 -1
  181. data/Gemfile.allinson +2 -0
  182. data/README.md +1 -2
  183. data/app/actors/hyrax/actors/file_actor.rb +2 -0
  184. data/app/actors/hyrax/actors/file_set_actor.rb +1 -1
  185. data/app/assets/javascripts/hyrax/app.js.erb +143 -10
  186. data/app/assets/javascripts/hyrax/collection_select.js +68 -0
  187. data/app/assets/javascripts/hyrax/copy_permalink_button.js +28 -0
  188. data/app/assets/javascripts/hyrax/redirects.js +45 -0
  189. data/app/assets/javascripts/hyrax/relationships/control.es6 +21 -1
  190. data/app/assets/javascripts/hyrax/select_work_type.es6 +7 -2
  191. data/app/assets/javascripts/hyrax.js +3 -1
  192. data/app/assets/stylesheets/hyrax/_file-show.scss +1 -0
  193. data/app/assets/stylesheets/hyrax/_viewer.scss +8 -0
  194. data/app/assets/stylesheets/hyrax/dashboard.scss +22 -1
  195. data/app/assets/stylesheets/hyrax/sidebar.scss +98 -3
  196. data/app/authorities/qa/authorities/collections.rb +9 -9
  197. data/app/controllers/concerns/hyrax/analytics_error_handling.rb +97 -0
  198. data/app/controllers/concerns/hyrax/collections_controller_behavior.rb +3 -1
  199. data/app/controllers/concerns/hyrax/ensure_migrated_behavior.rb +50 -0
  200. data/app/controllers/concerns/hyrax/flexible_catalog_behavior.rb +206 -0
  201. data/app/controllers/concerns/hyrax/flexible_schema_behavior.rb +17 -0
  202. data/app/controllers/concerns/hyrax/redirect_to_display_url.rb +54 -0
  203. data/app/controllers/concerns/hyrax/works_controller_behavior.rb +52 -10
  204. data/app/controllers/hyrax/admin/admin_sets_controller.rb +21 -13
  205. data/app/controllers/hyrax/admin/analytics/collection_reports_controller.rb +2 -0
  206. data/app/controllers/hyrax/admin/analytics/work_reports_controller.rb +1 -0
  207. data/app/controllers/hyrax/admin/metadata_profiles_controller.rb +66 -0
  208. data/app/controllers/hyrax/batch_uploads_controller.rb +2 -0
  209. data/app/controllers/hyrax/dashboard/collections_controller.rb +27 -6
  210. data/app/controllers/hyrax/dashboard/nest_collections_controller.rb +2 -1
  211. data/app/controllers/hyrax/dashboard_controller.rb +2 -1
  212. data/app/controllers/hyrax/file_sets_controller.rb +19 -1
  213. data/app/controllers/hyrax/homepage_controller.rb +7 -0
  214. data/app/controllers/hyrax/my/works_controller.rb +2 -21
  215. data/app/controllers/hyrax/permissions_controller.rb +4 -2
  216. data/app/controllers/hyrax/redirects_controller.rb +56 -0
  217. data/app/controllers/hyrax/single_use_links_viewer_controller.rb +2 -1
  218. data/app/controllers/hyrax/transcripts_controller.rb +31 -0
  219. data/app/controllers/hyrax/uploads_controller.rb +18 -9
  220. data/app/forms/concerns/hyrax/based_near_field_behavior.rb +77 -0
  221. data/app/forms/concerns/hyrax/flexible_form_behavior.rb +37 -0
  222. data/app/forms/concerns/hyrax/redirects_field_behavior.rb +95 -0
  223. data/app/forms/concerns/hyrax/transcripts_behavior.rb +40 -0
  224. data/app/forms/hyrax/forms/admin_set_form.rb +1 -1
  225. data/app/forms/hyrax/forms/administrative_set_form.rb +3 -0
  226. data/app/forms/hyrax/forms/batch_edit_form.rb +1 -3
  227. data/app/forms/hyrax/forms/batch_upload_form.rb +14 -0
  228. data/app/forms/hyrax/forms/file_set_edit_form.rb +1 -1
  229. data/app/forms/hyrax/forms/file_set_form.rb +6 -7
  230. data/app/forms/hyrax/forms/pcdm_collection_form.rb +17 -5
  231. data/app/forms/hyrax/forms/pcdm_object_form.rb +11 -3
  232. data/app/forms/hyrax/forms/resource_batch_edit_form.rb +8 -22
  233. data/app/forms/hyrax/forms/resource_form.rb +110 -10
  234. data/app/forms/hyrax/forms.rb +1 -0
  235. data/app/helpers/hyrax/attributes_helper.rb +109 -0
  236. data/app/helpers/hyrax/blacklight_override.rb +26 -0
  237. data/app/helpers/hyrax/collections_helper.rb +2 -0
  238. data/app/helpers/hyrax/file_set_form_helper.rb +24 -0
  239. data/app/helpers/hyrax/hyrax_helper_behavior.rb +51 -2
  240. data/app/helpers/hyrax/iiif_helper.rb +11 -1
  241. data/app/helpers/hyrax/permalink_helper.rb +37 -0
  242. data/app/helpers/hyrax/redirects_tab_helper.rb +29 -0
  243. data/app/helpers/hyrax/work_form_helper.rb +9 -5
  244. data/app/helpers/hyrax/works_helper.rb +14 -0
  245. data/app/indexers/concerns/hyrax/workflow_indexer.rb +30 -0
  246. data/app/indexers/hyrax/file_set_indexer.rb +1 -0
  247. data/app/indexers/hyrax/indexers/administrative_set_indexer.rb +2 -1
  248. data/app/indexers/hyrax/indexers/file_set_indexer.rb +6 -2
  249. data/app/indexers/hyrax/indexers/pcdm_collection_indexer.rb +11 -1
  250. data/app/indexers/hyrax/indexers/pcdm_object_indexer.rb +25 -4
  251. data/app/indexers/hyrax/indexers/redirects_indexer.rb +29 -0
  252. data/app/indexers/hyrax/indexers/resource_indexer.rb +4 -0
  253. data/app/indexers/hyrax/indexers.rb +2 -0
  254. data/app/inputs/controlled_vocabulary_input.rb +7 -1
  255. data/app/jobs/content_deposit_error_event_job.rb +14 -0
  256. data/app/jobs/create_work_job.rb +2 -0
  257. data/app/jobs/migrate_files_to_valkyrie_job.rb +7 -1
  258. data/app/models/batch_upload_item.rb +4 -0
  259. data/app/models/concerns/hyrax/ability/flexible_metadata_ability.rb +10 -0
  260. data/app/models/concerns/hyrax/ability.rb +3 -1
  261. data/app/models/concerns/hyrax/collection_behavior.rb +4 -0
  262. data/app/models/concerns/hyrax/file_set/transcripts.rb +16 -0
  263. data/app/models/concerns/hyrax/file_set_behavior.rb +9 -0
  264. data/app/models/concerns/hyrax/flexibility.rb +107 -0
  265. data/app/models/concerns/hyrax/redirects_normalization.rb +38 -0
  266. data/app/models/concerns/hyrax/solr_document/characterization.rb +1 -1
  267. data/app/models/concerns/hyrax/solr_document/metadata.rb +9 -0
  268. data/app/models/concerns/hyrax/solr_document/ordered_members.rb +4 -0
  269. data/app/models/concerns/hyrax/solr_document_behavior.rb +28 -6
  270. data/app/models/concerns/hyrax/suppressible.rb +1 -1
  271. data/app/models/concerns/hyrax/valkyrie_lazy_migration.rb +1 -1
  272. data/app/models/concerns/hyrax/with_embargoes_and_leases.rb +30 -0
  273. data/app/models/concerns/hyrax/work_behavior.rb +8 -0
  274. data/app/models/hyrax/administrative_set.rb +1 -1
  275. data/app/models/hyrax/change_set.rb +3 -1
  276. data/app/models/hyrax/embargo.rb +3 -1
  277. data/app/models/hyrax/file_set.rb +4 -2
  278. data/app/models/hyrax/flexible_schema.rb +219 -0
  279. data/app/models/hyrax/lease.rb +3 -1
  280. data/app/models/hyrax/pcdm_collection.rb +4 -1
  281. data/app/models/hyrax/redirect.rb +64 -0
  282. data/app/models/hyrax/redirect_path.rb +14 -0
  283. data/app/models/hyrax/resource.rb +22 -25
  284. data/app/models/hyrax/riiif/file.rb +43 -0
  285. data/app/models/hyrax/riiif/file_resolver.rb +65 -0
  286. data/app/models/hyrax/uploaded_file.rb +9 -0
  287. data/app/models/hyrax/virus_scanner.rb +16 -3
  288. data/app/models/hyrax/work.rb +4 -1
  289. data/app/models/job_io_wrapper.rb +12 -3
  290. data/app/models/user_mailbox.rb +3 -1
  291. data/app/presenters/hyrax/admin_set_presenter.rb +11 -0
  292. data/app/presenters/hyrax/annotates_content.rb +35 -0
  293. data/app/presenters/hyrax/collection_presenter.rb +5 -1
  294. data/app/presenters/hyrax/displays_content.rb +133 -0
  295. data/app/presenters/hyrax/displays_image.rb +11 -4
  296. data/app/presenters/hyrax/displays_transcripts.rb +59 -0
  297. data/app/presenters/hyrax/file_set_presenter.rb +8 -18
  298. data/app/presenters/hyrax/google_scholar_presenter.rb +39 -0
  299. data/app/presenters/hyrax/iiif_manifest_presenter.rb +22 -4
  300. data/app/presenters/hyrax/missing_method_behavior.rb +15 -0
  301. data/app/presenters/hyrax/pcdm_member_presenter_factory.rb +2 -4
  302. data/app/presenters/hyrax/work_show_presenter.rb +56 -14
  303. data/app/renderers/hyrax/renderers/attribute_renderer.rb +6 -2
  304. data/app/renderers/hyrax/renderers/license_attribute_renderer.rb +10 -10
  305. data/app/renderers/hyrax/renderers/redirects_label_attribute_renderer.rb +25 -0
  306. data/app/renderers/hyrax/renderers/rights_statement_attribute_renderer.rb +10 -11
  307. data/app/search_builders/hyrax/dashboard/nested_collections_search_builder.rb +1 -5
  308. data/app/search_builders/hyrax/filter_by_type.rb +1 -1
  309. data/app/services/hyrax/action/create_valkyrie_work.rb +3 -2
  310. data/app/services/hyrax/authority_rendering_helper.rb +28 -0
  311. data/app/services/hyrax/authority_service.rb +107 -0
  312. data/app/services/hyrax/callbacks.rb +2 -2
  313. data/app/services/hyrax/collections/nested_collection_query_service.rb +9 -3
  314. data/app/services/hyrax/collections_service.rb +17 -0
  315. data/app/services/hyrax/custom_queries/find_by_property_value.rb +89 -0
  316. data/app/services/hyrax/edit_permissions_service.rb +4 -4
  317. data/app/services/hyrax/file_set_type_service.rb +12 -4
  318. data/app/services/hyrax/flexible_schema_validator_service.rb +153 -0
  319. data/app/services/hyrax/flexible_schema_validators/class_validator.rb +123 -0
  320. data/app/services/hyrax/flexible_schema_validators/core_metadata_validator.rb +211 -0
  321. data/app/services/hyrax/flexible_schema_validators/existing_records_validator.rb +83 -0
  322. data/app/services/hyrax/flexible_schema_validators/redirects_validator.rb +116 -0
  323. data/app/services/hyrax/flexible_schema_validators/schema_validator.rb +34 -0
  324. data/app/services/hyrax/flexible_schema_validators/sort_properties_validator.rb +54 -0
  325. data/app/services/hyrax/license_service.rb +1 -1
  326. data/app/services/hyrax/listeners/metadata_index_listener.rb +11 -0
  327. data/app/services/hyrax/m3_profile_editor.rb +32 -0
  328. data/app/services/hyrax/m3_schema_loader.rb +119 -0
  329. data/app/services/hyrax/manifest_builder_service.rb +18 -24
  330. data/app/services/hyrax/permalink_path.rb +25 -0
  331. data/app/services/hyrax/qa_select_service.rb +9 -5
  332. data/app/services/hyrax/redirect_path_normalizer.rb +58 -0
  333. data/app/services/hyrax/redirects_lookup.rb +59 -0
  334. data/app/services/hyrax/resource_permissions_visibility_propagator.rb +54 -0
  335. data/app/services/hyrax/resource_types_service.rb +3 -20
  336. data/app/services/hyrax/rights_statement_service.rb +1 -1
  337. data/app/services/hyrax/schema_loader.rb +205 -0
  338. data/app/services/hyrax/search_service.rb +1 -1
  339. data/app/services/hyrax/simple_schema_loader.rb +28 -127
  340. data/app/services/hyrax/solr_service.rb +39 -2
  341. data/app/services/hyrax/tolerant_select_service.rb +5 -3
  342. data/app/services/hyrax/valkyrie_upload.rb +2 -2
  343. data/app/services/hyrax/visibility_propagator.rb +4 -1
  344. data/app/services/hyrax/work_uploads_handler.rb +17 -9
  345. data/app/services/hyrax/workflow/workflow_factory.rb +5 -4
  346. data/app/services/migrate_resource_service.rb +7 -1
  347. data/app/uploaders/hyrax/uploaded_file_uploader.rb +2 -2
  348. data/app/utils/hyrax/data_destroyers/collection_branding_destroyer.rb +1 -1
  349. data/app/utils/hyrax/required_data_seeder.rb +1 -0
  350. data/app/utils/hyrax/required_data_seeders/collection_type_seeder.rb +1 -1
  351. data/app/utils/hyrax/required_data_seeders/flexible_profile_seeder.rb +28 -0
  352. data/app/validators/hyrax/controlled_vocabulary_validator.rb +64 -0
  353. data/app/validators/hyrax/redirect_validator.rb +128 -0
  354. data/app/views/catalog/_thumbnail_list_default.html.erb +2 -2
  355. data/app/views/collections/edit_fields/_schema_version.html.erb +1 -0
  356. data/app/views/hyrax/admin/admin_sets/_form_metadata.html.erb +24 -2
  357. data/app/views/hyrax/admin/admin_sets/_show_document_list_row.html.erb +1 -1
  358. data/app/views/hyrax/admin/admin_sets/show.html.erb +1 -1
  359. data/app/views/hyrax/admin/analytics/_analytics_error.html.erb +42 -0
  360. data/app/views/hyrax/admin/analytics/collection_reports/index.html.erb +11 -9
  361. data/app/views/hyrax/admin/analytics/work_reports/index.html.erb +60 -57
  362. data/app/views/hyrax/admin/features/index.html.erb +1 -1
  363. data/app/views/hyrax/admin/metadata_profiles/_import_modal.html.erb +20 -0
  364. data/app/views/hyrax/admin/metadata_profiles/index.html.erb +54 -0
  365. data/app/views/hyrax/base/_attribute_rows.html.erb +4 -21
  366. data/app/views/hyrax/base/_citations.html.erb +1 -0
  367. data/app/views/hyrax/base/_currently_shared.html.erb +2 -1
  368. data/app/views/hyrax/base/_file_manager_thumbnail.html.erb +1 -1
  369. data/app/views/hyrax/base/_form_member_of_collections.html.erb +6 -6
  370. data/app/views/hyrax/base/_form_redirects.html.erb +125 -0
  371. data/app/views/hyrax/base/_form_share.html.erb +7 -2
  372. data/app/views/hyrax/base/_member.html.erb +1 -1
  373. data/app/views/hyrax/base/_social_media.html.erb +1 -1
  374. data/app/views/hyrax/base/iiif_viewers/_universal_viewer.html.erb +1 -1
  375. data/app/views/hyrax/base/show.html.erb +3 -0
  376. data/app/views/hyrax/collections/_default_group.html.erb +3 -0
  377. data/app/views/hyrax/collections/_list_collections.html.erb +3 -0
  378. data/app/views/hyrax/collections/_list_works.html.erb +1 -1
  379. data/app/views/hyrax/collections/_show_document_list_row.html.erb +1 -1
  380. data/app/views/hyrax/collections/show.html.erb +4 -0
  381. data/app/views/hyrax/dashboard/_sidebar.html.erb +4 -2
  382. data/app/views/hyrax/dashboard/collections/_button_for_update_collection.html.erb +2 -1
  383. data/app/views/hyrax/dashboard/collections/_default_group.html.erb +3 -0
  384. data/app/views/hyrax/dashboard/collections/_form.html.erb +17 -0
  385. data/app/views/hyrax/dashboard/collections/_form_for_select_collection.html.erb +7 -10
  386. data/app/views/hyrax/dashboard/collections/_list_collections.html.erb +3 -0
  387. data/app/views/hyrax/dashboard/collections/_list_works.html.erb +1 -1
  388. data/app/views/hyrax/dashboard/collections/_show_document_list_row.html.erb +1 -1
  389. data/app/views/hyrax/dashboard/profiles/_edit_primary.html.erb +1 -8
  390. data/app/views/hyrax/dashboard/profiles/_trophy_edit.html.erb +1 -1
  391. data/app/views/hyrax/dashboard/profiles/show.html.erb +5 -5
  392. data/app/views/hyrax/dashboard/sidebar/_metadata.html.erb +11 -0
  393. data/app/views/hyrax/dashboard/sidebar/_repository_content.html.erb +1 -0
  394. data/app/views/hyrax/dashboard/works/_default_group.html.erb +3 -0
  395. data/app/views/hyrax/dashboard/works/_list_works.html.erb +4 -2
  396. data/app/views/hyrax/file_sets/_form.html.erb +16 -3
  397. data/app/views/hyrax/file_sets/_metadata.html.erb +35 -0
  398. data/app/views/hyrax/file_sets/_valkyrie_form.html.erb +37 -0
  399. data/app/views/hyrax/file_sets/edit.html.erb +14 -8
  400. data/app/views/hyrax/file_sets/media_display/_audio.html.erb +4 -0
  401. data/app/views/hyrax/file_sets/media_display/_image.html.erb +2 -2
  402. data/app/views/hyrax/file_sets/media_display/_video.html.erb +4 -0
  403. data/app/views/hyrax/homepage/_explore_collections.html.erb +1 -1
  404. data/app/views/hyrax/homepage/_featured_fields.html.erb +1 -1
  405. data/app/views/hyrax/homepage/_recent_document.html.erb +1 -1
  406. data/app/views/hyrax/homepage/robots.text.erb +17 -0
  407. data/app/views/hyrax/my/collections/_default_group.html.erb +3 -0
  408. data/app/views/hyrax/my/collections/_list_collections.html.erb +3 -0
  409. data/app/views/hyrax/my/collections/_modal_add_subcollection.html.erb +2 -2
  410. data/app/views/hyrax/my/collections/_modal_add_to_collection.html.erb +2 -2
  411. data/app/views/hyrax/my/works/_default_group.html.erb +3 -0
  412. data/app/views/hyrax/my/works/_list_works.html.erb +5 -2
  413. data/app/views/hyrax/shared/_copy_permalink.html.erb +10 -0
  414. data/app/views/hyrax/users/_user_info.html.erb +1 -6
  415. data/app/views/layouts/_head_tag_content.html.erb +2 -0
  416. data/app/views/layouts/hyrax/dashboard.html.erb +2 -1
  417. data/app/views/records/edit_fields/_contexts.html.erb +1 -0
  418. data/app/views/records/edit_fields/_license.html.erb +17 -5
  419. data/app/views/records/edit_fields/_resource_type.html.erb +16 -2
  420. data/app/views/records/edit_fields/_rights_statement.html.erb +17 -5
  421. data/app/views/records/edit_fields/_schema_version.html.erb +1 -0
  422. data/app/views/records/edit_fields/_transcript_ids.html.erb +18 -0
  423. data/app/views/records/show_fields/_rights.html.erb +1 -1
  424. data/app/views/shared/_citations.html.erb +46 -31
  425. data/app/views/shared/_schema_version.html.erb +38 -0
  426. data/bin/dev-entrypoint.sh +14 -4
  427. data/chart/hyrax/Chart.yaml +4 -4
  428. data/chart/hyrax/templates/ingress.yaml +3 -0
  429. data/chart/hyrax/values.yaml +10 -8
  430. data/config/features.rb +27 -0
  431. data/config/initializers/blacklight_dynamic_sitemap.rb +43 -0
  432. data/config/initializers/deprecation_patch.rb +27 -0
  433. data/config/initializers/hydra_works.rb +3 -0
  434. data/config/initializers/i18n_extensions.rb +197 -0
  435. data/config/initializers/storage_adapter_initializer.rb +15 -9
  436. data/config/locales/hyrax.de.yml +172 -54
  437. data/config/locales/hyrax.en.yml +183 -66
  438. data/config/locales/hyrax.es.yml +174 -49
  439. data/config/locales/hyrax.fr.yml +169 -45
  440. data/config/locales/hyrax.it.yml +172 -48
  441. data/config/locales/hyrax.pt-BR.yml +172 -54
  442. data/config/locales/hyrax.zh.yml +145 -21
  443. data/config/metadata/basic_metadata.yaml +66 -0
  444. data/config/metadata/batch_edit_metadata.yaml +119 -0
  445. data/config/metadata/file_set_metadata.yaml +19 -0
  446. data/config/metadata/redirects.yaml +15 -0
  447. data/config/metadata_profiles/m3_json_schema.json +487 -0
  448. data/config/metadata_profiles/m3_profile.yaml +954 -0
  449. data/config/routes.rb +9 -0
  450. data/docker-compose-allinson.yml +176 -0
  451. data/docker-compose-dassie.yml +14 -6
  452. data/docker-compose-koppie.yml +18 -10
  453. data/docker-compose-sirenia.yml +20 -10
  454. data/documentation/copy_permalink.md +29 -0
  455. data/documentation/developing-your-hyrax-based-app.md +2 -2
  456. data/documentation/file-ingest-characterization.md +763 -0
  457. data/documentation/flexible_metadata.md +113 -0
  458. data/documentation/forms/field_behaviors.md +297 -0
  459. data/documentation/redirects.md +428 -0
  460. data/hyrax.gemspec +7 -2
  461. data/lib/freyja/metadata_adapter.rb +1 -1
  462. data/lib/freyja/persister.rb +25 -1
  463. data/lib/generators/hyrax/collection_resource/collection_resource_generator.rb +2 -2
  464. data/lib/generators/hyrax/collection_resource/templates/collection.rb.erb +5 -1
  465. data/lib/generators/hyrax/collection_resource/templates/collection_form.rb.erb +5 -1
  466. data/lib/generators/hyrax/collection_resource/templates/collection_indexer.rb.erb +6 -1
  467. data/lib/generators/hyrax/iiif_viewer/USAGE +22 -0
  468. data/lib/generators/hyrax/iiif_viewer/iiif_viewer_generator.rb +49 -0
  469. data/lib/generators/hyrax/iiif_viewer/templates/_clover.html.erb +7 -0
  470. data/lib/generators/hyrax/iiif_viewer/templates/clover/clover.css +3328 -0
  471. data/lib/generators/hyrax/iiif_viewer/templates/clover/clover.html +16 -0
  472. data/lib/generators/hyrax/iiif_viewer/templates/clover/clover.js +237 -0
  473. data/lib/generators/hyrax/install_generator.rb +25 -1
  474. data/lib/generators/hyrax/riiif_generator.rb +1 -1
  475. data/lib/generators/hyrax/templates/app/views/blacklight_dynamic_sitemap/sitemap/show.xml.builder +22 -0
  476. data/lib/generators/hyrax/templates/config/clamav.rb +2 -0
  477. data/lib/generators/hyrax/templates/config/initializers/riiif.rb +4 -80
  478. data/lib/generators/hyrax/templates/db/migrate/20240606205215_create_hyrax_flexible_schemas.rb.erb +9 -0
  479. data/lib/generators/hyrax/templates/db/migrate/20240606205216_add_contexts_to_hyrax_flexible_schemas.rb.erb +5 -0
  480. data/lib/generators/hyrax/templates/db/migrate/20260430000001_create_hyrax_redirect_paths.rb.erb +22 -0
  481. data/lib/generators/hyrax/templates/db/migrate/20260521003627_add_additional_redirect_info.rb.erb +39 -0
  482. data/lib/generators/hyrax/templates/package.json +1 -1
  483. data/lib/generators/hyrax/templates/uv.html +60 -82
  484. data/lib/generators/hyrax/work/templates/indexer.rb.erb +1 -1
  485. data/lib/generators/hyrax/work/templates/model.rb.erb +5 -1
  486. data/lib/generators/hyrax/work_resource/templates/form.rb.erb +5 -2
  487. data/lib/generators/hyrax/work_resource/templates/indexer.rb.erb +6 -2
  488. data/lib/generators/hyrax/work_resource/templates/work.rb.erb +5 -2
  489. data/lib/generators/hyrax/work_resource/work_resource_generator.rb +1 -0
  490. data/lib/hyrax/active_fedora_dummy_model.rb +6 -0
  491. data/lib/hyrax/configuration.rb +197 -3
  492. data/lib/hyrax/deprecation.rb +31 -0
  493. data/lib/hyrax/engine.rb +2 -0
  494. data/lib/hyrax/form_fields.rb +17 -5
  495. data/lib/hyrax/indexer.rb +31 -2
  496. data/lib/hyrax/resource_sync/resource_list_writer.rb +3 -0
  497. data/lib/hyrax/schema.rb +15 -4
  498. data/lib/hyrax/specs/shared_specs/factories/administrative_sets.rb +12 -0
  499. data/lib/hyrax/specs/shared_specs/factories/hyrax_embargo.rb +1 -1
  500. data/lib/hyrax/specs/shared_specs/factories/hyrax_file_set.rb +13 -0
  501. data/lib/hyrax/specs/shared_specs/factories/hyrax_lease.rb +5 -1
  502. data/lib/hyrax/specs/shared_specs/factories/hyrax_work.rb +14 -0
  503. data/lib/hyrax/specs/shared_specs/simple_work.rb +41 -0
  504. data/lib/hyrax/specs/shared_specs.rb +1 -0
  505. data/lib/hyrax/transactions/collection_create.rb +2 -1
  506. data/lib/hyrax/transactions/collection_destroy.rb +1 -0
  507. data/lib/hyrax/transactions/collection_update.rb +2 -1
  508. data/lib/hyrax/transactions/container.rb +28 -0
  509. data/lib/hyrax/transactions/steps/apply_permission_template_on_update.rb +65 -0
  510. data/lib/hyrax/transactions/steps/apply_workflow_on_admin_set_change.rb +97 -0
  511. data/lib/hyrax/transactions/steps/ensure_admin_set.rb +1 -1
  512. data/lib/hyrax/transactions/steps/remove_redirect_paths.rb +35 -0
  513. data/lib/hyrax/transactions/steps/save.rb +10 -0
  514. data/lib/hyrax/transactions/steps/set_default_admin_set.rb +1 -1
  515. data/lib/hyrax/transactions/steps/sync_redirect_paths.rb +141 -0
  516. data/lib/hyrax/transactions/work_create.rb +2 -1
  517. data/lib/hyrax/transactions/work_destroy.rb +1 -0
  518. data/lib/hyrax/transactions/work_update.rb +4 -1
  519. data/lib/hyrax/version.rb +1 -1
  520. data/lib/hyrax.rb +61 -0
  521. data/lib/tasks/m3_profile_cleanup.rake +35 -0
  522. data/template.rb +4 -1
  523. metadata +313 -19
  524. data/.dassie/public/robots.txt +0 -1
  525. data/.koppie/public/robots.txt +0 -1
  526. data/app/forms/concerns/hyrax/basic_metadata_form_fields_behavior.rb +0 -39
  527. data/app/views/catalog/_thumbnail_list_collection.html.erb +0 -4
@@ -9,7 +9,9 @@ module Hyrax
9
9
  include Hyrax::VisibilityIndexer
10
10
  include Hyrax::LocationIndexer
11
11
  include Hyrax::ThumbnailIndexer
12
- include Hyrax::Indexer(:core_metadata)
12
+ include Hyrax::Indexer(:core_metadata) if Hyrax.config.collection_include_metadata?
13
+ include Hyrax::Indexers::RedirectsIndexer if Hyrax.config.redirects_enabled?
14
+ check_if_flexible(Hyrax::PcdmCollection)
13
15
 
14
16
  self.thumbnail_path_service = CollectionThumbnailPathService
15
17
 
@@ -20,8 +22,16 @@ module Hyrax
20
22
  index_document[:member_of_collection_ids_ssim] = resource.member_of_collection_ids.map(&:to_s)
21
23
  index_document[:depositor_ssim] = [resource.depositor]
22
24
  index_document[:depositor_tesim] = [resource.depositor]
25
+ index_document['thumbnail_alt_text_tesim'] = thumbnail_alt_text(resource.id.to_s)
23
26
  end
24
27
  end
28
+
29
+ private
30
+
31
+ def thumbnail_alt_text(collection_id)
32
+ branding = CollectionBrandingInfo.where(collection_id: collection_id, role: "thumbnail").first
33
+ branding&.alt_text.presence
34
+ end
25
35
  end
26
36
  end
27
37
  end
@@ -9,7 +9,8 @@ module Hyrax
9
9
  include Hyrax::VisibilityIndexer
10
10
  include Hyrax::LocationIndexer
11
11
  include Hyrax::ThumbnailIndexer
12
- include Hyrax::Indexer(:core_metadata)
12
+ include Hyrax::WorkflowIndexer
13
+ include Hyrax::Indexers::RedirectsIndexer if Hyrax.config.redirects_enabled?
13
14
 
14
15
  def to_solr # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
15
16
  super.tap do |solr_doc|
@@ -20,13 +21,15 @@ module Hyrax
20
21
  solr_doc['admin_set_sim'] = admin_set_label
21
22
  solr_doc['admin_set_tesim'] = admin_set_label
22
23
  solr_doc["#{Hyrax.config.admin_set_predicate.qname.last}_ssim"] = [resource.admin_set_id.to_s]
23
- solr_doc['member_of_collection_ids_ssim'] = resource.member_of_collection_ids.map(&:to_s)
24
- solr_doc['member_ids_ssim'] = resource.member_ids.map(&:to_s)
24
+ solr_doc['member_of_collection_ids_ssim'] = resource.member_of_collection_ids&.map(&:to_s)
25
+ solr_doc['member_of_collections_ssim'] = collection_titles_for(resource.member_of_collection_ids)
26
+ solr_doc['member_ids_ssim'] = resource.member_ids&.map(&:to_s)
25
27
  solr_doc['depositor_ssim'] = [resource.depositor]
26
28
  solr_doc['depositor_tesim'] = [resource.depositor]
27
29
  solr_doc['hasRelatedMediaFragment_ssim'] = [resource.representative_id.to_s]
28
30
  solr_doc['hasRelatedImage_ssim'] = [resource.thumbnail_id.to_s]
29
- solr_doc['hasFormat_ssim'] = resource.rendering_ids.map(&:to_s) if resource.rendering_ids.present?
31
+ solr_doc['thumbnail_alt_text_tesim'] = thumbnail_alt_text(resource.thumbnail_id)
32
+ solr_doc['hasFormat_ssim'] = resource.rendering_ids&.map(&:to_s) if resource.rendering_ids.present?
30
33
  index_embargo(solr_doc)
31
34
  index_lease(solr_doc)
32
35
  end
@@ -34,6 +37,14 @@ module Hyrax
34
37
 
35
38
  private
36
39
 
40
+ def thumbnail_alt_text(thumbnail_id)
41
+ return if thumbnail_id.blank?
42
+ file_set = Hyrax.query_service.find_by(id: thumbnail_id)
43
+ Array(file_set.try(:alt_text)).first.presence
44
+ rescue Valkyrie::Persistence::ObjectNotFoundError, Hyrax::ObjectNotFoundError
45
+ nil
46
+ end
47
+
37
48
  def suppressed?(resource)
38
49
  Hyrax::ResourceStatus.new(resource: resource).inactive?
39
50
  end
@@ -44,6 +55,16 @@ module Hyrax
44
55
  admin_set.title
45
56
  end
46
57
 
58
+ def collection_titles_for(collection_ids)
59
+ return [] if collection_ids.blank?
60
+ collection_ids.map do |id|
61
+ collection = Hyrax.query_service.find_by(id: id)
62
+ collection.title&.first
63
+ rescue Valkyrie::Persistence::ObjectNotFoundError
64
+ nil
65
+ end.compact
66
+ end
67
+
47
68
  def index_embargo(doc)
48
69
  if resource.embargo&.active?
49
70
  doc['embargo_release_date_dtsi'] = resource.embargo.embargo_release_date&.to_datetime
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hyrax
4
+ module Indexers
5
+ ##
6
+ # Indexer mixin that emits the `redirects_path_tesim` Solr field for
7
+ # resources that carry a `redirects` attribute. The field is consumed
8
+ # by the show-page renderer via `SolrDocument#redirects_path`.
9
+ #
10
+ # @example
11
+ # class WorkIndexer < Hyrax::Indexers::PcdmObjectIndexer
12
+ # include Hyrax::Indexers::RedirectsIndexer
13
+ # end
14
+ module RedirectsIndexer
15
+ def to_solr(*args)
16
+ super.tap do |document|
17
+ next document unless Hyrax.config.redirects_active?
18
+ next document unless resource.respond_to?(:redirects)
19
+ # Valkyrie's JSONValueMapper symbolizes hash keys on read; accept either.
20
+ # Paths are normalized at write time by Hyrax::RedirectsNormalization.
21
+ paths = Array(resource.redirects)
22
+ .map { |entry| entry['path'] || entry[:path] }
23
+ .reject(&:blank?)
24
+ document['redirects_path_tesim'] = paths
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -60,6 +60,10 @@ module Hyrax
60
60
  end
61
61
 
62
62
  class << self
63
+ def check_if_flexible(model)
64
+ include Hyrax::Indexer(model.to_s, index_loader: Hyrax::Schema.m3_schema_loader) if model.flexible?
65
+ end
66
+
63
67
  ##
64
68
  # @api public
65
69
  # @param resource [Valkyrie::Resource] an instance of a
@@ -11,6 +11,8 @@ module Hyrax
11
11
  def self.PcdmObjectIndexer(work_class) # rubocop:disable Naming/MethodName
12
12
  Class.new(Hyrax::Indexers::PcdmObjectIndexer) do
13
13
  @model_class = work_class
14
+ include Hyrax::Indexer(:core_metadata) if work_class.ancestors.detect { |k| k.inspect == "Hyrax::Schema(core_metadata)" }
15
+ check_if_flexible(work_class)
14
16
 
15
17
  class << self
16
18
  attr_reader :model_class
@@ -44,7 +44,13 @@ class ControlledVocabularyInput < MultiValueInput
44
44
  def hidden_id_field(value, index)
45
45
  name = name_for(attribute_name, index, 'id')
46
46
  id = id_for(attribute_name, index, 'id')
47
- hidden_value = value.try(:node?) ? '' : value.rdf_subject
47
+ hidden_value = if value.try(:node?) || value.is_a?(ActionController::Parameters)
48
+ ''
49
+ elsif value.respond_to?(:rdf_subject)
50
+ value.rdf_subject
51
+ else
52
+ value.to_s
53
+ end
48
54
  @builder.hidden_field(attribute_name, name: name, id: id, value: hidden_value, data: { id: 'remote' })
49
55
  end
50
56
 
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+ # Log a concern deposit to activity streams
3
+ class ContentDepositErrorEventJob < ContentEventJob
4
+ attr_accessor :reason
5
+
6
+ def perform(repo_object, depositor, reason: '')
7
+ self.reason = reason
8
+ super(repo_object, depositor)
9
+ end
10
+
11
+ def action
12
+ "User #{link_to_profile depositor} deposit of #{link_to repo_object.title.first, polymorphic_path(repo_object)} has failed for #{reason}"
13
+ end
14
+ end
@@ -2,6 +2,7 @@
2
2
  # This is a job spawned by the BatchCreateJob
3
3
  class CreateWorkJob < Hyrax::ApplicationJob
4
4
  queue_as Hyrax.config.ingest_queue_name
5
+ discard_on StandardError
5
6
 
6
7
  before_enqueue do |job|
7
8
  operation = job.arguments.last
@@ -28,6 +29,7 @@ class CreateWorkJob < Hyrax::ApplicationJob
28
29
 
29
30
  return operation.success! if status
30
31
  operation.fail!(errors.full_messages.join(' '))
32
+ raise StandardError, operation.message
31
33
  end
32
34
 
33
35
  private
@@ -59,8 +59,14 @@ class MigrateFilesToValkyrieJob < Hyrax::ApplicationJob
59
59
  begin
60
60
  # If it doesn't start with fedora, we've likely already migrated it.
61
61
  next unless /^fedora:/.match?(file.file_identifier.to_s)
62
+
62
63
  resource.file_ids.delete(file.id)
63
64
 
65
+ # We've observed cases where the extracted text (which doesn't get created in Valkyrie)
66
+ # does not have a filename and it overrides the original file. The extracted text should
67
+ # be in the derivatives, not with the file set.
68
+ next if file.original_filename.blank?
69
+
64
70
  Tempfile.create do |tempfile|
65
71
  tempfile.binmode
66
72
  tempfile.write(URI.open(file.file_identifier.to_s.gsub("fedora:", "http:")).read)
@@ -68,7 +74,7 @@ class MigrateFilesToValkyrieJob < Hyrax::ApplicationJob
68
74
 
69
75
  # valkyrie_file = Hyrax.storage_adapter.upload(resource: resource, file: tempfile, original_filename: file.original_filename)
70
76
  valkyrie_file = Hyrax::ValkyrieUpload.file(
71
- filename: resource.label,
77
+ filename: file.original_filename,
72
78
  file_set: resource,
73
79
  io: tempfile,
74
80
  use: file.pcdm_use.select {|use| Hyrax::FileMetadata::Use.use_list.include?(use)},
@@ -18,4 +18,8 @@ class BatchUploadItem < ActiveFedora::Base
18
18
  def create_or_update
19
19
  raise "This is a read only record"
20
20
  end
21
+
22
+ def flexible?
23
+ false
24
+ end
21
25
  end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+ module Hyrax
3
+ module Ability
4
+ module FlexibleMetadataAbility
5
+ def flexible_metadata_abilities
6
+ can :manage, Hyrax::FlexibleSchema if admin? && Hyrax.config.flexible?
7
+ end
8
+ end
9
+ end
10
+ end
@@ -55,6 +55,7 @@ module Hyrax
55
55
  include Hyrax::Ability::PermissionTemplateAbility
56
56
  include Hyrax::Ability::ResourceAbility
57
57
  include Hyrax::Ability::SolrDocumentAbility
58
+ include Hyrax::Ability::FlexibleMetadataAbility
58
59
 
59
60
  class_attribute :admin_group_name, :registered_group_name, :public_group_name
60
61
  self.admin_group_name = Hyrax.config.admin_user_group_name
@@ -79,7 +80,8 @@ module Hyrax
79
80
  :permission_template_abilities,
80
81
  :resource_abilities,
81
82
  :solr_document_abilities,
82
- :trophy_abilities]
83
+ :trophy_abilities,
84
+ :flexible_metadata_abilities]
83
85
  end
84
86
 
85
87
  # Samvera doesn't use download user/groups, so make it an alias to read
@@ -68,6 +68,10 @@ module Hyrax
68
68
  title.present? ? title.join(' | ') : 'No Title'
69
69
  end
70
70
 
71
+ def flexible?
72
+ false
73
+ end
74
+
71
75
  module ClassMethods
72
76
  # This governs which partial to draw when you render this type of object
73
77
  def _to_partial_path # :nodoc:
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+ module Hyrax
3
+ class FileSet
4
+ module Transcripts
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ if Hyrax.config.file_set_include_metadata?
9
+ property :transcript_ids, predicate: ::RDF::URI.new('http://vocabulary.samvera.org/ns#transcriptIds'), multiple: true do |index|
10
+ index.as :stored_sortable
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -14,6 +14,7 @@ module Hyrax
14
14
  include Hyrax::FileSet::Indexing
15
15
  include Hyrax::FileSet::BelongsToWorks
16
16
  include Hyrax::FileSet::Querying
17
+ include Hyrax::FileSet::Transcripts
17
18
  include HumanReadableType
18
19
  include CoreMetadata
19
20
  include Hyrax::BasicMetadata
@@ -38,5 +39,13 @@ module Hyrax
38
39
  Deprecation.warn "Method #to_presenter will be removed in Hyrax 5.0. Use Hyrax::FileSetsController#presenter.solr_document or `@presenter.solr_document` from a view instead."
39
40
  Blacklight::SearchService.new(config: CatalogController.blacklight_config).fetch(id).last
40
41
  end
42
+
43
+ def self.flexible?
44
+ false
45
+ end
46
+
47
+ def flexible?
48
+ false
49
+ end
41
50
  end
42
51
  end
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hyrax
4
+ module Flexibility
5
+ extend ActiveSupport::Concern
6
+ included do
7
+ attribute :schema_version, Valkyrie::Types::String
8
+ attribute :contexts, Valkyrie::Types::Set.of(Valkyrie::Types::String)
9
+ end
10
+
11
+ class_methods do
12
+ def try(term)
13
+ # This logic is necessary to handle method :try on a class
14
+ # otherwise load(attributes) tries to use the term as a schema to load and errors
15
+ return nil unless self.respond_to?(term)
16
+ self.send(term)
17
+ end
18
+
19
+ def flexible?
20
+ true
21
+ end
22
+
23
+ ## Override dry-struct 1.6.0 to enable redefining schemas on the fly
24
+ def attributes(new_schema)
25
+ keys = new_schema.keys.map { |k| k.to_s.chomp("?").to_sym }
26
+ schema_location = singleton_class? ? self.superclass : self
27
+ schema schema_location.schema.schema(new_schema)
28
+
29
+ define_accessors(keys)
30
+
31
+ @attribute_names = nil
32
+
33
+ direct_descendants = descendants&.select { |d| d.superclass == self }
34
+ direct_descendants&.each do |d|
35
+ inherited_attrs = new_schema.reject { |k, _| d.has_attribute?(k.to_s.chomp("?").to_sym) }
36
+ d.attributes(inherited_attrs)
37
+ end
38
+
39
+ new_schema.each_key do |key|
40
+ key = key.to_s.chomp('?')
41
+ next if instance_methods.include?("#{key}=".to_sym)
42
+
43
+ class_eval(<<-RUBY)
44
+ def #{key}=(value)
45
+ set_value("#{key}".to_sym, value)
46
+ end
47
+ RUBY
48
+ end
49
+
50
+ self
51
+ end
52
+
53
+ ## Override dry-struct 1.6.0 to filter attributes after schema reload happens
54
+ def new(attributes = default_attributes, safe = false, &block) # rubocop:disable Style/OptionalBooleanParameter
55
+ if attributes.is_a?(Struct)
56
+ if equal?(attributes.class)
57
+ attributes
58
+ else
59
+ # This implicit coercion is arguable but makes sense overall
60
+ # in cases there you pass child struct to the base struct constructor
61
+ # User.new(super_user)
62
+ #
63
+ # We may deprecate this behavior in future forcing people to be explicit
64
+ new(attributes.to_h, safe, &block)
65
+ end
66
+ else
67
+ load(attributes, safe)
68
+ end
69
+ rescue Dry::Types::CoercionError => e
70
+ raise RuntimeError, "[#{self}.new] #{e.class}: #{e.message}", e.backtrace
71
+ end
72
+
73
+ ## Read the schema from the database and load the correct schemas for the instance in to the class
74
+ def load(attributes, safe = false)
75
+ attributes[:schema_version] ||= Hyrax::FlexibleSchema.order('id DESC').pick(:id)
76
+ struct = allocate
77
+ schema_version = attributes[:schema_version]
78
+ contexts = attributes[:contexts] || []
79
+ struct.singleton_class.attributes(Hyrax::Schema(self, schema_loader: Hyrax::Schema.m3_schema_loader, schema_version:, contexts:).attributes)
80
+ clean_attributes = safe ? struct.singleton_class.schema.call_safe(attributes) { |output = attributes| return yield output } : struct.singleton_class.schema.call_unsafe(attributes)
81
+ struct.__send__(:initialize, clean_attributes)
82
+ struct
83
+ end
84
+ end
85
+
86
+ def contexts=(value)
87
+ val = Array.wrap(value).map { |v| v.split }.flatten
88
+ @attributes[:contexts] = val
89
+ end
90
+
91
+ # Override set_value from valkyrie 3.1.1 to enable dynamic schema loading
92
+ def set_value(key, value)
93
+ @attributes[key.to_sym] = self.singleton_class.schema.key(key.to_sym).type.call(value)
94
+ end
95
+
96
+ def flexible?
97
+ self.class.flexible?
98
+ end
99
+
100
+ # Override inspect from dry-struct 1.6.0 to enable dynamic schema loading
101
+ def inspect
102
+ klass = self.singleton_class
103
+ attrs = klass.attribute_names.map { |key| " #{key}=#{@attributes[key].inspect}" }.join
104
+ "#<#{klass.name || klass.inspect}#{attrs}>"
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hyrax
4
+ # Normalizes redirect path entries on assignment so every write path —
5
+ # form submissions, console writes, importers, change-set saves —
6
+ # produces canonical data. Read-side consumers can trust the persisted
7
+ # shape and skip their own normalization.
8
+ #
9
+ # Included next to Hyrax::Schema(:redirects) on Hyrax::Work and
10
+ # Hyrax::PcdmCollection. The override sits on Valkyrie's set_value
11
+ # primitive so it fires under both flex modes (the simple schema's
12
+ # generated setter and the m3 singleton-class setter both route through
13
+ # set_value).
14
+ #
15
+ # See documentation/redirects.md.
16
+ module RedirectsNormalization
17
+ extend ActiveSupport::Concern
18
+
19
+ def set_value(key, value)
20
+ value = normalize_redirects(value) if key.to_sym == :redirects
21
+ super
22
+ end
23
+
24
+ private
25
+
26
+ def normalize_redirects(value)
27
+ Array(value).map { |entry| normalize_entry(entry) }
28
+ end
29
+
30
+ def normalize_entry(entry)
31
+ return entry unless entry.is_a?(Hash)
32
+ normalized = entry.dup
33
+ path_key = normalized.key?(:path) ? :path : 'path'
34
+ normalized[path_key] = Hyrax::RedirectPathNormalizer.call(normalized[path_key])
35
+ normalized
36
+ end
37
+ end
38
+ end
@@ -133,7 +133,7 @@ module Hyrax
133
133
  end
134
134
 
135
135
  def original_checksum
136
- self["original_checksum_tesim"]
136
+ self["original_checksum_tesim"] || self["checksum_tesim"]
137
137
  end
138
138
 
139
139
  def alpha_channels
@@ -40,11 +40,20 @@ module Hyrax
40
40
  end
41
41
  end
42
42
 
43
+ def alt_text_for_view
44
+ return alt_text.first.presence || title.first if file_set?
45
+
46
+ thumbnail_alt_text.first || "#{title.first} #{I18n.t('hyrax.homepage.admin_sets.thumbnail')}"
47
+ end
48
+
43
49
  included do
44
50
  attribute :alternative_title, Solr::Array, "alternative_title_tesim"
51
+ attribute :alt_text, Solr::Array, "alt_text_tesim"
52
+ attribute :thumbnail_alt_text, Solr::Array, "thumbnail_alt_text_tesim"
45
53
  attribute :identifier, Solr::Array, "identifier_tesim"
46
54
  attribute :based_near, Solr::Array, "based_near_tesim"
47
55
  attribute :based_near_label, Solr::Array, "based_near_label_tesim"
56
+ attribute :redirects_path, Solr::Array, "redirects_path_tesim"
48
57
  attribute :related_url, Solr::Array, "related_url_tesim"
49
58
  attribute :resource_type, Solr::Array, "resource_type_tesim"
50
59
  attribute :edit_groups, Solr::Array, ::Ability.edit_group_field
@@ -30,6 +30,10 @@ module Hyrax
30
30
  @ordered_member_ids ||= valkyrie? ? member_ids : query_for_ordered_ids
31
31
  end
32
32
 
33
+ def flexible?
34
+ respond_to?(:schema_version) && schema_version.present?
35
+ end
36
+
33
37
  private
34
38
 
35
39
  def query_for_ordered_ids(limit: 10_000,
@@ -12,6 +12,8 @@ module Hyrax
12
12
  # end
13
13
  #
14
14
  # @see https://github.com/projectblacklight/blacklight/wiki/Understanding-Rails-and-Blacklight#models
15
+
16
+ # rubocop:disable Metrics/ModuleLength
15
17
  module SolrDocumentBehavior
16
18
  ModelWrapper = ActiveFedoraDummyModel # alias for backward compatibility
17
19
 
@@ -82,12 +84,15 @@ module Hyrax
82
84
 
83
85
  # Method to return the model
84
86
  def hydra_model(classifier: nil)
85
- # finds the model from the solr document
86
- model = first('has_model_ssim')&.safe_constantize
87
- # this returns nil if it isn't a valid model
88
- resource_model = (first('has_model_ssim')&.+ 'Resource')&.safe_constantize if Hyrax.config.valkyrie_transition?
89
- # if valkyrie_transition is enabled, we generally want to use the resource model if it exists
90
- resource_model || model || model_classifier(classifier).classifier(self).best_model
87
+ valkyrie_model = Valkyrie.config.resource_class_resolver.call(hydra_model_name) if Hyrax.config.valkyrie_transition?
88
+
89
+ valkyrie_model ||
90
+ hydra_model_name&.safe_constantize ||
91
+ model_classifier(classifier).classifier(self).best_model
92
+ end
93
+
94
+ def hydra_model_name
95
+ @has_model ||= first('has_model_ssim')
91
96
  end
92
97
 
93
98
  def depositor(default = '')
@@ -149,10 +154,27 @@ module Hyrax
149
154
  JSON.parse(self['extensions_and_mime_types_ssm'].first).map(&:with_indifferent_access) if self['extensions_and_mime_types_ssm']
150
155
  end
151
156
 
157
+ def schema_version
158
+ self['schema_version_ssi']
159
+ end
160
+
161
+ def contexts
162
+ self['contexts_ssim']
163
+ end
164
+
165
+ def flexible?
166
+ schema_version.present?
167
+ end
168
+
169
+ def transcript_ids
170
+ self['transcript_ids_ssim']
171
+ end
172
+
152
173
  private
153
174
 
154
175
  def model_classifier(classifier)
155
176
  classifier || ActiveFedora.model_mapper
156
177
  end
157
178
  end
179
+ # rubocop:enable Metrics/ModuleLength
158
180
  end
@@ -6,7 +6,7 @@ module Hyrax
6
6
 
7
7
  included do
8
8
  # This holds the workflow state
9
- property :state, predicate: Vocab::FedoraResourceStatus.objState, multiple: false
9
+ property :state, predicate: Vocab::FedoraResourceStatus.objState, multiple: false if respond_to?(:property)
10
10
  end
11
11
 
12
12
  ##
@@ -50,7 +50,7 @@ module Hyrax
50
50
  # Hyrax::ValkyrieLazyMigration.migrating(self, from: MyWork)
51
51
  # end
52
52
  def self.migrating(klass, from:, name_class: Hyrax::ValkyrieLazyMigration::ResourceName)
53
- Wings::ModelRegistry.register(klass, from)
53
+ Wings::ModelRegistry.register(klass, from) if defined?(Wings::ModelRegistry)
54
54
  from.singleton_class.define_method(:migrating_from) { from }
55
55
  from.singleton_class.define_method(:migrating_to) { klass }
56
56
  klass.singleton_class.define_method(:migrating_from) { from }
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+ module Hyrax
3
+ module WithEmbargoesAndLeases
4
+ extend ActiveSupport::Concern
5
+
6
+ def embargo=(value)
7
+ raise TypeError "can't convert #{value.class} into Hyrax::Embargo" unless value.is_a? Hyrax::Embargo
8
+
9
+ @embargo = value
10
+ self.embargo_id = @embargo.id
11
+ end
12
+
13
+ def embargo
14
+ return @embargo if @embargo
15
+ @embargo = Hyrax.query_service.find_by(id: embargo_id) if embargo_id.present?
16
+ end
17
+
18
+ def lease=(value)
19
+ raise TypeError "can't convert #{value.class} into Hyrax::Lease" unless value.is_a? Hyrax::Lease
20
+
21
+ @lease = value
22
+ self.lease_id = @lease.id
23
+ end
24
+
25
+ def lease
26
+ return @lease if @lease
27
+ @lease = Hyrax.query_service.find_by(id: lease_id) if lease_id.present?
28
+ end
29
+ end
30
+ end
@@ -34,6 +34,10 @@ module Hyrax
34
34
  self.class.to_rdf_representation
35
35
  end
36
36
 
37
+ def flexible?
38
+ false
39
+ end
40
+
37
41
  module ClassMethods
38
42
  # This governs which partial to draw when you render this type of object
39
43
  def _to_partial_path # :nodoc:
@@ -43,6 +47,10 @@ module Hyrax
43
47
  "hyrax/#{collection}/#{element}"
44
48
  end
45
49
  end
50
+
51
+ def flexible?
52
+ false
53
+ end
46
54
  end
47
55
  end
48
56
  end
@@ -25,7 +25,7 @@ module Hyrax
25
25
  # @see Valkyrie query adapter's #find_inverse_references_by
26
26
  #
27
27
  class AdministrativeSet < Hyrax::Resource
28
- include Hyrax::Schema(:core_metadata)
28
+ include Hyrax::Schema(:core_metadata) if Hyrax.config.admin_set_include_metadata?
29
29
 
30
30
  attribute :alternative_title, Valkyrie::Types::Set.of(Valkyrie::Types::String)
31
31
  attribute :creator, Valkyrie::Types::Set.of(Valkyrie::Types::String)
@@ -13,7 +13,7 @@ module Hyrax
13
13
  # @example
14
14
  # Hyrax::ChangeSet(Monograph)
15
15
  def self.ChangeSet(resource_class)
16
- klass = (resource_class.to_s + "ChangeSet").safe_constantize || Hyrax::ChangeSet
16
+ klass = (resource_class.name + "ChangeSet").safe_constantize || Hyrax::ChangeSet
17
17
  Class.new(klass) do
18
18
  (resource_class.fields - resource_class.reserved_attributes).each do |field|
19
19
  property field, default: nil
@@ -29,6 +29,8 @@ module Hyrax
29
29
  end
30
30
 
31
31
  class ChangeSet < Valkyrie::ChangeSet
32
+ validates_with Hyrax::ControlledVocabularyValidator
33
+
32
34
  ##
33
35
  # @api public
34
36
  #