hyrax 5.1.0 → 5.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (561) hide show
  1. checksums.yaml +4 -4
  2. data/.dassie/.env +5 -1
  3. data/.dassie/Gemfile +5 -3
  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/application.rb +1 -1
  25. data/.dassie/config/browse_everything_providers.yml +1 -1
  26. data/.dassie/config/bulkrax_api.yml +86 -0
  27. data/.dassie/config/initializers/bulkrax.rb +92 -0
  28. data/.dassie/config/initializers/clamav.rb +2 -0
  29. data/.dassie/config/initializers/devise.rb +1 -0
  30. data/.dassie/config/initializers/hyrax.rb +7 -1
  31. data/.dassie/config/initializers/riiif.rb +4 -80
  32. data/.dassie/config/initializers/wings.rb +1 -1
  33. data/.dassie/config/metadata_profiles/m3_profile.yaml +929 -0
  34. data/.dassie/config/puma.rb +4 -2
  35. data/.dassie/config/routes.rb +7 -0
  36. data/.dassie/config/sidekiq.yml +17 -0
  37. data/.dassie/config/uv/uv.html +63 -81
  38. data/.dassie/db/migrate/20240606205215_create_hyrax_flexible_schemas.rb +9 -0
  39. data/.dassie/db/migrate/20240606205216_add_contexts_to_hyrax_flexible_schemas.rb +5 -0
  40. data/.dassie/db/migrate/20250826142438_create_bulkrax_importers.bulkrax.rb +19 -0
  41. data/.dassie/db/migrate/20250826142439_create_bulkrax_importer_runs.bulkrax.rb +17 -0
  42. data/.dassie/db/migrate/20250826142440_create_bulkrax_entries.bulkrax.rb +17 -0
  43. data/.dassie/db/migrate/20250826142441_add_status_to_entry.bulkrax.rb +10 -0
  44. data/.dassie/db/migrate/20250826142442_add_collections_to_importer_runs.bulkrax.rb +7 -0
  45. data/.dassie/db/migrate/20250826142443_change_collection_ids_on_entries.bulkrax.rb +6 -0
  46. data/.dassie/db/migrate/20250826142444_create_bulkrax_exporters.bulkrax.rb +20 -0
  47. data/.dassie/db/migrate/20250826142445_create_bulkrax_exporter_runs.bulkrax.rb +15 -0
  48. data/.dassie/db/migrate/20250826142446_change_importer_and_exporter_to_polymorphic.bulkrax.rb +19 -0
  49. data/.dassie/db/migrate/20250826142447_add_total_collection_records_to_importer_runs.bulkrax.rb +6 -0
  50. data/.dassie/db/migrate/20250826142448_add_children_to_importer_runs.bulkrax.rb +7 -0
  51. data/.dassie/db/migrate/20250826142449_change_total_records_to_total_work_entries.bulkrax.rb +7 -0
  52. data/.dassie/db/migrate/20250826142450_change_entry_last_error.bulkrax.rb +20 -0
  53. data/.dassie/db/migrate/20250826142451_add_validate_only_to_bulkrax_importers.bulkrax.rb +6 -0
  54. data/.dassie/db/migrate/20250826142452_add_status_to_importers.bulkrax.rb +10 -0
  55. data/.dassie/db/migrate/20250826142453_remove_foreign_key_from_bulkrax_entries.bulkrax.rb +6 -0
  56. data/.dassie/db/migrate/20250826142454_add_status_to_exporters.bulkrax.rb +8 -0
  57. data/.dassie/db/migrate/20250826142455_add_invalid_record_to_importer_run.bulkrax.rb +6 -0
  58. data/.dassie/db/migrate/20250826142456_create_bulkrax_statuses.bulkrax.rb +19 -0
  59. data/.dassie/db/migrate/20250826142457_move_to_statuses.bulkrax.rb +31 -0
  60. data/.dassie/db/migrate/20250826142458_add_date_filter_and_status_to_bulkrax_exporters.bulkrax.rb +8 -0
  61. data/.dassie/db/migrate/20250826142459_add_workflow_status_to_bulkrax_exporter.bulkrax.rb +6 -0
  62. data/.dassie/db/migrate/20250826142460_remove_unused_last_error.bulkrax.rb +8 -0
  63. data/.dassie/db/migrate/20250826142461_increase_text_sizes.bulkrax.rb +13 -0
  64. data/.dassie/db/migrate/20250826142462_change_bulkrax_statuses_error_message_column_type_to_text.bulkrax.rb +6 -0
  65. data/.dassie/db/migrate/20250826142463_rename_children_counters_to_relationships.bulkrax.rb +7 -0
  66. data/.dassie/db/migrate/20250826142464_add_file_set_counters_to_importer_runs.bulkrax.rb +8 -0
  67. data/.dassie/db/migrate/20250826142465_add_import_attempts_to_entries.bulkrax.rb +6 -0
  68. data/.dassie/db/migrate/20250826142466_add_work_counters_to_importer_runs.bulkrax.rb +7 -0
  69. data/.dassie/db/migrate/20250826142467_create_bulkrax_pending_relationships.bulkrax.rb +14 -0
  70. data/.dassie/db/migrate/20250826142468_add_order_to_bulkrax_pending_relationships.bulkrax.rb +6 -0
  71. data/.dassie/db/migrate/20250826142469_add_include_thumbnails_to_bulkrax_exporters.bulkrax.rb +6 -0
  72. data/.dassie/db/migrate/20250826142470_add_generated_metadata_to_bulkrax_exporters.bulkrax.rb +6 -0
  73. data/.dassie/db/migrate/20250826142471_rename_bulkrax_importer_run_to_importer_run.bulkrax.rb +18 -0
  74. data/.dassie/db/migrate/20250826142472_add_indices_to_bulkrax.bulkrax.rb +26 -0
  75. data/.dassie/db/migrate/20250826142473_denormalize_status_message.bulkrax.rb +8 -0
  76. data/.dassie/db/migrate/20250826142474_update_identifier_index.bulkrax.rb +7 -0
  77. data/.dassie/db/migrate/20250826142475_add_index_to_metadata_bulkrax_identifier.bulkrax.rb +19 -0
  78. data/.dassie/db/migrate/20250826142476_add_file_name_to_uploaded_files.bulkrax.rb +6 -0
  79. data/.dassie/db/migrate/20250826142477_add_error_tracking_to_pending_relationships.bulkrax.rb +6 -0
  80. data/.dassie/db/migrate/20250826142478_add_last_imported_at_to_bulkrax_importers.bulkrax.rb +6 -0
  81. data/.dassie/db/migrate/20250826142479_add_next_import_at_to_bulkrax_importers.bulkrax.rb +6 -0
  82. data/.dassie/db/migrate/20250826142480_entry_error_denormalization.bulkrax.rb +8 -0
  83. data/.dassie/db/migrate/20250826142481_faster_first_entry.bulkrax.rb +8 -0
  84. data/.dassie/db/migrate/20260430000001_create_hyrax_redirect_paths.hyrax.rb +13 -0
  85. data/.dassie/db/migrate/20260521003627_add_additional_redirect_info.hyrax.rb +32 -0
  86. data/.dassie/db/schema.rb +263 -109
  87. data/.dassie/package.json +1 -1
  88. data/.dassie/rspec_split_configuration.json +835 -0
  89. data/.dassie/solr/conf/solrconfig.xml +21 -5
  90. data/.github/{ISSUE_TEMPLATE.md → ISSUE_TEMPLATE/issue_template.md} +5 -0
  91. data/.github/workflows/lint-build-test.yml +6 -2
  92. data/.github/workflows/release-charts.yml +48 -0
  93. data/.gitignore +6 -0
  94. data/.koppie/.env +5 -1
  95. data/.koppie/Gemfile +3 -1
  96. data/.koppie/app/assets/images/bulkrax/removed.png +0 -0
  97. data/.koppie/app/assets/javascripts/application.js +2 -0
  98. data/.koppie/app/assets/stylesheets/application.css +1 -0
  99. data/.koppie/app/controllers/catalog_controller.rb +1 -1
  100. data/.koppie/app/forms/collection_resource_form.rb +5 -2
  101. data/.koppie/app/forms/file_set_form.rb +5 -0
  102. data/.koppie/app/forms/generic_work_form.rb +5 -3
  103. data/.koppie/app/forms/monograph_form.rb +5 -3
  104. data/.koppie/app/indexers/collection_resource_indexer.rb +5 -2
  105. data/.koppie/app/indexers/file_set_indexer.rb +7 -0
  106. data/.koppie/app/indexers/generic_work_indexer.rb +6 -3
  107. data/.koppie/app/indexers/monograph_indexer.rb +6 -2
  108. data/.koppie/app/models/ability.rb +8 -0
  109. data/.koppie/app/models/collection_resource.rb +4 -2
  110. data/.koppie/app/models/concerns/bulkrax/has_local_processing.rb +8 -0
  111. data/.koppie/app/models/generic_work.rb +5 -2
  112. data/.koppie/app/models/monograph.rb +5 -2
  113. data/.koppie/app/views/blacklight_dynamic_sitemap/sitemap/show.xml.builder +22 -0
  114. data/.koppie/bin/importer +142 -0
  115. data/.koppie/bin/web +4 -0
  116. data/.koppie/config/browse_everything_providers.yml +2 -0
  117. data/.koppie/config/bulkrax_api.yml +86 -0
  118. data/.koppie/config/initializers/bulkrax.rb +92 -0
  119. data/.koppie/config/initializers/clamav.rb +2 -0
  120. data/.koppie/config/initializers/devise.rb +1 -1
  121. data/.koppie/config/initializers/hyrax.rb +11 -3
  122. data/.koppie/config/initializers/riiif.rb +4 -82
  123. data/.koppie/config/metadata_profiles/m3_profile.yaml +930 -0
  124. data/.koppie/config/routes.rb +7 -0
  125. data/.koppie/config/sidekiq.yml +2 -0
  126. data/.koppie/config/uv/uv.html +63 -81
  127. data/.koppie/db/migrate/20240606205215_create_hyrax_flexible_schemas.rb +9 -0
  128. data/.koppie/db/migrate/20240606205216_add_contexts_to_hyrax_flexible_schemas.rb +5 -0
  129. data/.koppie/db/migrate/20250826142438_create_bulkrax_importers.bulkrax.rb +19 -0
  130. data/.koppie/db/migrate/20250826142439_create_bulkrax_importer_runs.bulkrax.rb +17 -0
  131. data/.koppie/db/migrate/20250826142440_create_bulkrax_entries.bulkrax.rb +17 -0
  132. data/.koppie/db/migrate/20250826142441_add_status_to_entry.bulkrax.rb +10 -0
  133. data/.koppie/db/migrate/20250826142442_add_collections_to_importer_runs.bulkrax.rb +7 -0
  134. data/.koppie/db/migrate/20250826142443_change_collection_ids_on_entries.bulkrax.rb +6 -0
  135. data/.koppie/db/migrate/20250826142444_create_bulkrax_exporters.bulkrax.rb +20 -0
  136. data/.koppie/db/migrate/20250826142445_create_bulkrax_exporter_runs.bulkrax.rb +15 -0
  137. data/.koppie/db/migrate/20250826142446_change_importer_and_exporter_to_polymorphic.bulkrax.rb +19 -0
  138. data/.koppie/db/migrate/20250826142447_add_total_collection_records_to_importer_runs.bulkrax.rb +6 -0
  139. data/.koppie/db/migrate/20250826142448_add_children_to_importer_runs.bulkrax.rb +7 -0
  140. data/.koppie/db/migrate/20250826142449_change_total_records_to_total_work_entries.bulkrax.rb +7 -0
  141. data/.koppie/db/migrate/20250826142450_change_entry_last_error.bulkrax.rb +20 -0
  142. data/.koppie/db/migrate/20250826142451_add_validate_only_to_bulkrax_importers.bulkrax.rb +6 -0
  143. data/.koppie/db/migrate/20250826142452_add_status_to_importers.bulkrax.rb +10 -0
  144. data/.koppie/db/migrate/20250826142453_remove_foreign_key_from_bulkrax_entries.bulkrax.rb +6 -0
  145. data/.koppie/db/migrate/20250826142454_add_status_to_exporters.bulkrax.rb +8 -0
  146. data/.koppie/db/migrate/20250826142455_add_invalid_record_to_importer_run.bulkrax.rb +6 -0
  147. data/.koppie/db/migrate/20250826142456_create_bulkrax_statuses.bulkrax.rb +19 -0
  148. data/.koppie/db/migrate/20250826142457_move_to_statuses.bulkrax.rb +31 -0
  149. data/.koppie/db/migrate/20250826142458_add_date_filter_and_status_to_bulkrax_exporters.bulkrax.rb +8 -0
  150. data/.koppie/db/migrate/20250826142459_add_workflow_status_to_bulkrax_exporter.bulkrax.rb +6 -0
  151. data/.koppie/db/migrate/20250826142460_remove_unused_last_error.bulkrax.rb +8 -0
  152. data/.koppie/db/migrate/20250826142461_increase_text_sizes.bulkrax.rb +13 -0
  153. data/.koppie/db/migrate/20250826142462_change_bulkrax_statuses_error_message_column_type_to_text.bulkrax.rb +6 -0
  154. data/.koppie/db/migrate/20250826142463_rename_children_counters_to_relationships.bulkrax.rb +7 -0
  155. data/.koppie/db/migrate/20250826142464_add_file_set_counters_to_importer_runs.bulkrax.rb +8 -0
  156. data/.koppie/db/migrate/20250826142465_add_import_attempts_to_entries.bulkrax.rb +6 -0
  157. data/.koppie/db/migrate/20250826142466_add_work_counters_to_importer_runs.bulkrax.rb +7 -0
  158. data/.koppie/db/migrate/20250826142467_create_bulkrax_pending_relationships.bulkrax.rb +14 -0
  159. data/.koppie/db/migrate/20250826142468_add_order_to_bulkrax_pending_relationships.bulkrax.rb +6 -0
  160. data/.koppie/db/migrate/20250826142469_add_include_thumbnails_to_bulkrax_exporters.bulkrax.rb +6 -0
  161. data/.koppie/db/migrate/20250826142470_add_generated_metadata_to_bulkrax_exporters.bulkrax.rb +6 -0
  162. data/.koppie/db/migrate/20250826142471_rename_bulkrax_importer_run_to_importer_run.bulkrax.rb +18 -0
  163. data/.koppie/db/migrate/20250826142472_add_indices_to_bulkrax.bulkrax.rb +26 -0
  164. data/.koppie/db/migrate/20250826142473_denormalize_status_message.bulkrax.rb +8 -0
  165. data/.koppie/db/migrate/20250826142474_update_identifier_index.bulkrax.rb +7 -0
  166. data/.koppie/db/migrate/20250826142475_add_index_to_metadata_bulkrax_identifier.bulkrax.rb +19 -0
  167. data/.koppie/db/migrate/20250826142476_add_file_name_to_uploaded_files.bulkrax.rb +6 -0
  168. data/.koppie/db/migrate/20250826142477_add_error_tracking_to_pending_relationships.bulkrax.rb +6 -0
  169. data/.koppie/db/migrate/20250826142478_add_last_imported_at_to_bulkrax_importers.bulkrax.rb +6 -0
  170. data/.koppie/db/migrate/20250826142479_add_next_import_at_to_bulkrax_importers.bulkrax.rb +6 -0
  171. data/.koppie/db/migrate/20250826142480_entry_error_denormalization.bulkrax.rb +8 -0
  172. data/.koppie/db/migrate/20250826142481_faster_first_entry.bulkrax.rb +8 -0
  173. data/.koppie/db/migrate/20260430000001_create_hyrax_redirect_paths.hyrax.rb +13 -0
  174. data/.koppie/db/migrate/20260521003627_add_additional_redirect_info.hyrax.rb +32 -0
  175. data/.koppie/db/schema.rb +154 -1
  176. data/.koppie/package.json +1 -1
  177. data/.koppie/rspec_split_configuration.json +835 -0
  178. data/.koppie/solr/conf/solrconfig.xml +0 -5
  179. data/.koppie/yarn.lock +5587 -752
  180. data/.rubocop.yml +1 -0
  181. data/CONTAINERS.md +12 -10
  182. data/Dockerfile +9 -22
  183. data/Gemfile +1 -1
  184. data/Gemfile.allinson +2 -0
  185. data/README.md +1 -2
  186. data/app/actors/hyrax/actors/file_actor.rb +2 -0
  187. data/app/actors/hyrax/actors/file_set_actor.rb +1 -1
  188. data/app/assets/javascripts/hyrax/app.js.erb +143 -10
  189. data/app/assets/javascripts/hyrax/collection_select.js +68 -0
  190. data/app/assets/javascripts/hyrax/copy_permalink_button.js +28 -0
  191. data/app/assets/javascripts/hyrax/redirects.js +45 -0
  192. data/app/assets/javascripts/hyrax/relationships/control.es6 +21 -1
  193. data/app/assets/javascripts/hyrax/select_work_type.es6 +7 -2
  194. data/app/assets/javascripts/hyrax.js +3 -1
  195. data/app/assets/stylesheets/hyrax/_file-show.scss +1 -0
  196. data/app/assets/stylesheets/hyrax/_viewer.scss +8 -0
  197. data/app/assets/stylesheets/hyrax/dashboard.scss +22 -1
  198. data/app/assets/stylesheets/hyrax/sidebar.scss +98 -3
  199. data/app/authorities/qa/authorities/collections.rb +9 -9
  200. data/app/controllers/concerns/hyrax/analytics_error_handling.rb +97 -0
  201. data/app/controllers/concerns/hyrax/collections_controller_behavior.rb +3 -1
  202. data/app/controllers/concerns/hyrax/ensure_migrated_behavior.rb +50 -0
  203. data/app/controllers/concerns/hyrax/flexible_catalog_behavior.rb +206 -0
  204. data/app/controllers/concerns/hyrax/flexible_schema_behavior.rb +17 -0
  205. data/app/controllers/concerns/hyrax/redirect_to_display_url.rb +54 -0
  206. data/app/controllers/concerns/hyrax/valkyrie_downloads_controller_behavior.rb +1 -0
  207. data/app/controllers/concerns/hyrax/works_controller_behavior.rb +54 -11
  208. data/app/controllers/hyrax/admin/admin_sets_controller.rb +21 -13
  209. data/app/controllers/hyrax/admin/analytics/collection_reports_controller.rb +2 -0
  210. data/app/controllers/hyrax/admin/analytics/work_reports_controller.rb +5 -4
  211. data/app/controllers/hyrax/admin/metadata_profiles_controller.rb +66 -0
  212. data/app/controllers/hyrax/batch_uploads_controller.rb +2 -0
  213. data/app/controllers/hyrax/dashboard/collections_controller.rb +27 -6
  214. data/app/controllers/hyrax/dashboard/nest_collections_controller.rb +2 -1
  215. data/app/controllers/hyrax/dashboard_controller.rb +2 -1
  216. data/app/controllers/hyrax/file_sets_controller.rb +20 -2
  217. data/app/controllers/hyrax/homepage_controller.rb +7 -0
  218. data/app/controllers/hyrax/my/works_controller.rb +2 -21
  219. data/app/controllers/hyrax/permissions_controller.rb +4 -2
  220. data/app/controllers/hyrax/redirects_controller.rb +56 -0
  221. data/app/controllers/hyrax/single_use_links_viewer_controller.rb +2 -1
  222. data/app/controllers/hyrax/transcripts_controller.rb +31 -0
  223. data/app/controllers/hyrax/uploads_controller.rb +18 -9
  224. data/app/forms/concerns/hyrax/based_near_field_behavior.rb +77 -0
  225. data/app/forms/concerns/hyrax/flexible_form_behavior.rb +37 -0
  226. data/app/forms/concerns/hyrax/redirects_field_behavior.rb +95 -0
  227. data/app/forms/concerns/hyrax/transcripts_behavior.rb +40 -0
  228. data/app/forms/hyrax/forms/admin_set_form.rb +1 -1
  229. data/app/forms/hyrax/forms/administrative_set_form.rb +3 -0
  230. data/app/forms/hyrax/forms/batch_edit_form.rb +1 -3
  231. data/app/forms/hyrax/forms/batch_upload_form.rb +14 -0
  232. data/app/forms/hyrax/forms/file_set_edit_form.rb +1 -1
  233. data/app/forms/hyrax/forms/file_set_form.rb +6 -7
  234. data/app/forms/hyrax/forms/pcdm_collection_form.rb +17 -5
  235. data/app/forms/hyrax/forms/pcdm_object_form.rb +11 -3
  236. data/app/forms/hyrax/forms/resource_batch_edit_form.rb +8 -22
  237. data/app/forms/hyrax/forms/resource_form.rb +110 -10
  238. data/app/forms/hyrax/forms.rb +1 -0
  239. data/app/helpers/hyrax/attributes_helper.rb +109 -0
  240. data/app/helpers/hyrax/blacklight_override.rb +26 -0
  241. data/app/helpers/hyrax/collections_helper.rb +2 -0
  242. data/app/helpers/hyrax/file_set_form_helper.rb +24 -0
  243. data/app/helpers/hyrax/hyrax_helper_behavior.rb +53 -4
  244. data/app/helpers/hyrax/iiif_helper.rb +11 -1
  245. data/app/helpers/hyrax/permalink_helper.rb +37 -0
  246. data/app/helpers/hyrax/redirects_tab_helper.rb +29 -0
  247. data/app/helpers/hyrax/trophy_helper.rb +1 -1
  248. data/app/helpers/hyrax/work_form_helper.rb +9 -5
  249. data/app/helpers/hyrax/works_helper.rb +14 -0
  250. data/app/indexers/concerns/hyrax/workflow_indexer.rb +30 -0
  251. data/app/indexers/hyrax/file_set_indexer.rb +1 -0
  252. data/app/indexers/hyrax/indexers/administrative_set_indexer.rb +2 -1
  253. data/app/indexers/hyrax/indexers/file_set_indexer.rb +6 -2
  254. data/app/indexers/hyrax/indexers/pcdm_collection_indexer.rb +11 -1
  255. data/app/indexers/hyrax/indexers/pcdm_object_indexer.rb +25 -4
  256. data/app/indexers/hyrax/indexers/redirects_indexer.rb +29 -0
  257. data/app/indexers/hyrax/indexers/resource_indexer.rb +4 -0
  258. data/app/indexers/hyrax/indexers.rb +2 -0
  259. data/app/inputs/controlled_vocabulary_input.rb +7 -1
  260. data/app/jobs/concerns/hyrax/queued_job_behavior.rb +22 -0
  261. data/app/jobs/content_deposit_error_event_job.rb +14 -0
  262. data/app/jobs/create_work_job.rb +2 -0
  263. data/app/jobs/hyrax/propagate_change_depositor_job.rb +1 -1
  264. data/app/jobs/hyrax/queued_delete_job.rb +11 -0
  265. data/app/jobs/hyrax/queued_indexing_job.rb +11 -0
  266. data/app/jobs/migrate_files_to_valkyrie_job.rb +39 -21
  267. data/app/jobs/migrate_sipity_entity_job.rb +21 -0
  268. data/app/models/batch_upload_item.rb +4 -0
  269. data/app/models/concerns/hyrax/ability/flexible_metadata_ability.rb +10 -0
  270. data/app/models/concerns/hyrax/ability.rb +7 -3
  271. data/app/models/concerns/hyrax/collection_behavior.rb +4 -0
  272. data/app/models/concerns/hyrax/file_set/transcripts.rb +16 -0
  273. data/app/models/concerns/hyrax/file_set_behavior.rb +9 -0
  274. data/app/models/concerns/hyrax/flexibility.rb +107 -0
  275. data/app/models/concerns/hyrax/redirects_normalization.rb +38 -0
  276. data/app/models/concerns/hyrax/solr_document/characterization.rb +1 -1
  277. data/app/models/concerns/hyrax/solr_document/metadata.rb +9 -0
  278. data/app/models/concerns/hyrax/solr_document/ordered_members.rb +4 -0
  279. data/app/models/concerns/hyrax/solr_document_behavior.rb +28 -3
  280. data/app/models/concerns/hyrax/suppressible.rb +1 -1
  281. data/app/models/concerns/hyrax/valkyrie_lazy_migration.rb +1 -1
  282. data/app/models/concerns/hyrax/with_embargoes_and_leases.rb +30 -0
  283. data/app/models/concerns/hyrax/work_behavior.rb +8 -0
  284. data/app/models/hyrax/administrative_set.rb +1 -1
  285. data/app/models/hyrax/change_set.rb +3 -1
  286. data/app/models/hyrax/embargo.rb +3 -1
  287. data/app/models/hyrax/file_metadata.rb +22 -7
  288. data/app/models/hyrax/file_set.rb +4 -2
  289. data/app/models/hyrax/flexible_schema.rb +219 -0
  290. data/app/models/hyrax/lease.rb +3 -1
  291. data/app/models/hyrax/pcdm_collection.rb +4 -1
  292. data/app/models/hyrax/redirect.rb +64 -0
  293. data/app/models/hyrax/redirect_path.rb +14 -0
  294. data/app/models/hyrax/resource.rb +22 -25
  295. data/app/models/hyrax/riiif/file.rb +43 -0
  296. data/app/models/hyrax/riiif/file_resolver.rb +65 -0
  297. data/app/models/hyrax/uploaded_file.rb +9 -0
  298. data/app/models/hyrax/virus_scanner.rb +16 -3
  299. data/app/models/hyrax/work.rb +4 -1
  300. data/app/models/job_io_wrapper.rb +12 -3
  301. data/app/models/user_mailbox.rb +3 -1
  302. data/app/presenters/hyrax/admin_set_presenter.rb +11 -0
  303. data/app/presenters/hyrax/annotates_content.rb +35 -0
  304. data/app/presenters/hyrax/collection_presenter.rb +5 -1
  305. data/app/presenters/hyrax/displays_content.rb +133 -0
  306. data/app/presenters/hyrax/displays_image.rb +11 -4
  307. data/app/presenters/hyrax/displays_transcripts.rb +59 -0
  308. data/app/presenters/hyrax/file_set_presenter.rb +8 -18
  309. data/app/presenters/hyrax/google_scholar_presenter.rb +39 -0
  310. data/app/presenters/hyrax/iiif_manifest_presenter.rb +22 -4
  311. data/app/presenters/hyrax/missing_method_behavior.rb +15 -0
  312. data/app/presenters/hyrax/pcdm_member_presenter_factory.rb +2 -4
  313. data/app/presenters/hyrax/work_show_presenter.rb +56 -14
  314. data/app/renderers/hyrax/renderers/attribute_renderer.rb +6 -2
  315. data/app/renderers/hyrax/renderers/license_attribute_renderer.rb +10 -10
  316. data/app/renderers/hyrax/renderers/redirects_label_attribute_renderer.rb +25 -0
  317. data/app/renderers/hyrax/renderers/rights_statement_attribute_renderer.rb +10 -11
  318. data/app/search_builders/hyrax/dashboard/nested_collections_search_builder.rb +1 -5
  319. data/app/search_builders/hyrax/filter_by_type.rb +1 -1
  320. data/app/services/hyrax/action/create_valkyrie_work.rb +3 -2
  321. data/app/services/hyrax/analytics/ga4/base.rb +1 -1
  322. data/app/services/hyrax/analytics/ga4.rb +5 -1
  323. data/app/services/hyrax/authority_rendering_helper.rb +28 -0
  324. data/app/services/hyrax/authority_service.rb +107 -0
  325. data/app/services/hyrax/callbacks.rb +2 -2
  326. data/app/services/hyrax/change_depositor_service.rb +1 -1
  327. data/app/services/hyrax/characterization/valkyrie_characterization_service.rb +21 -13
  328. data/app/services/hyrax/collections/nested_collection_query_service.rb +9 -3
  329. data/app/services/hyrax/collections_service.rb +17 -0
  330. data/app/services/hyrax/custom_queries/find_by_property_value.rb +89 -0
  331. data/app/services/hyrax/custom_queries/find_ids_by_model.rb +31 -6
  332. data/app/services/hyrax/edit_permissions_service.rb +11 -10
  333. data/app/services/hyrax/file_set_type_service.rb +12 -4
  334. data/app/services/hyrax/flexible_schema_validator_service.rb +153 -0
  335. data/app/services/hyrax/flexible_schema_validators/class_validator.rb +123 -0
  336. data/app/services/hyrax/flexible_schema_validators/core_metadata_validator.rb +211 -0
  337. data/app/services/hyrax/flexible_schema_validators/existing_records_validator.rb +83 -0
  338. data/app/services/hyrax/flexible_schema_validators/redirects_validator.rb +116 -0
  339. data/app/services/hyrax/flexible_schema_validators/schema_validator.rb +34 -0
  340. data/app/services/hyrax/flexible_schema_validators/sort_properties_validator.rb +54 -0
  341. data/app/services/hyrax/license_service.rb +1 -1
  342. data/app/services/hyrax/listeners/metadata_index_listener.rb +11 -0
  343. data/app/services/hyrax/m3_profile_editor.rb +32 -0
  344. data/app/services/hyrax/m3_schema_loader.rb +119 -0
  345. data/app/services/hyrax/manifest_builder_service.rb +18 -24
  346. data/app/services/hyrax/permalink_path.rb +25 -0
  347. data/app/services/hyrax/qa_select_service.rb +9 -5
  348. data/app/services/hyrax/redirect_path_normalizer.rb +58 -0
  349. data/app/services/hyrax/redirects_lookup.rb +59 -0
  350. data/app/services/hyrax/resource_permissions_visibility_propagator.rb +54 -0
  351. data/app/services/hyrax/resource_types_service.rb +3 -20
  352. data/app/services/hyrax/rights_statement_service.rb +1 -1
  353. data/app/services/hyrax/schema_loader.rb +205 -0
  354. data/app/services/hyrax/search_service.rb +1 -1
  355. data/app/services/hyrax/simple_schema_loader.rb +28 -127
  356. data/app/services/hyrax/solr_service.rb +39 -2
  357. data/app/services/hyrax/tolerant_select_service.rb +5 -3
  358. data/app/services/hyrax/valkyrie_upload.rb +2 -2
  359. data/app/services/hyrax/visibility_propagator.rb +4 -1
  360. data/app/services/hyrax/work_uploads_handler.rb +17 -9
  361. data/app/services/hyrax/workflow/workflow_factory.rb +5 -4
  362. data/app/services/migrate_resource_service.rb +8 -2
  363. data/app/uploaders/hyrax/uploaded_file_uploader.rb +2 -2
  364. data/app/utils/hyrax/data_destroyers/collection_branding_destroyer.rb +1 -1
  365. data/app/utils/hyrax/required_data_seeder.rb +1 -0
  366. data/app/utils/hyrax/required_data_seeders/collection_type_seeder.rb +1 -1
  367. data/app/utils/hyrax/required_data_seeders/flexible_profile_seeder.rb +28 -0
  368. data/app/validators/hyrax/controlled_vocabulary_validator.rb +64 -0
  369. data/app/validators/hyrax/redirect_validator.rb +128 -0
  370. data/app/views/_user_util_links.html.erb +2 -1
  371. data/app/views/catalog/_thumbnail_list_default.html.erb +2 -2
  372. data/app/views/collections/edit_fields/_schema_version.html.erb +1 -0
  373. data/app/views/hyrax/admin/admin_sets/_form_metadata.html.erb +24 -2
  374. data/app/views/hyrax/admin/admin_sets/_show_document_list_row.html.erb +1 -1
  375. data/app/views/hyrax/admin/admin_sets/show.html.erb +1 -1
  376. data/app/views/hyrax/admin/analytics/_analytics_error.html.erb +42 -0
  377. data/app/views/hyrax/admin/analytics/collection_reports/_top_collections.html.erb +3 -7
  378. data/app/views/hyrax/admin/analytics/collection_reports/index.html.erb +11 -9
  379. data/app/views/hyrax/admin/analytics/work_reports/_top_file_set_downloads.html.erb +3 -6
  380. data/app/views/hyrax/admin/analytics/work_reports/_top_works.html.erb +2 -3
  381. data/app/views/hyrax/admin/analytics/work_reports/_work_files.html.erb +1 -6
  382. data/app/views/hyrax/admin/analytics/work_reports/index.html.erb +60 -57
  383. data/app/views/hyrax/admin/features/index.html.erb +1 -1
  384. data/app/views/hyrax/admin/metadata_profiles/_import_modal.html.erb +20 -0
  385. data/app/views/hyrax/admin/metadata_profiles/index.html.erb +54 -0
  386. data/app/views/hyrax/base/_attribute_rows.html.erb +4 -21
  387. data/app/views/hyrax/base/_citations.html.erb +1 -0
  388. data/app/views/hyrax/base/_currently_shared.html.erb +2 -1
  389. data/app/views/hyrax/base/_file_manager_thumbnail.html.erb +1 -1
  390. data/app/views/hyrax/base/_form_member_of_collections.html.erb +6 -6
  391. data/app/views/hyrax/base/_form_redirects.html.erb +125 -0
  392. data/app/views/hyrax/base/_form_share.html.erb +7 -2
  393. data/app/views/hyrax/base/_member.html.erb +1 -1
  394. data/app/views/hyrax/base/_social_media.html.erb +3 -1
  395. data/app/views/hyrax/base/iiif_viewers/_universal_viewer.html.erb +1 -1
  396. data/app/views/hyrax/base/show.html.erb +3 -0
  397. data/app/views/hyrax/collections/_default_group.html.erb +3 -0
  398. data/app/views/hyrax/collections/_list_collections.html.erb +3 -0
  399. data/app/views/hyrax/collections/_list_works.html.erb +1 -1
  400. data/app/views/hyrax/collections/_show_document_list_row.html.erb +1 -1
  401. data/app/views/hyrax/collections/show.html.erb +4 -0
  402. data/app/views/hyrax/dashboard/_sidebar.html.erb +4 -2
  403. data/app/views/hyrax/dashboard/collections/_button_for_update_collection.html.erb +2 -1
  404. data/app/views/hyrax/dashboard/collections/_default_group.html.erb +3 -0
  405. data/app/views/hyrax/dashboard/collections/_form.html.erb +17 -0
  406. data/app/views/hyrax/dashboard/collections/_form_for_select_collection.html.erb +7 -10
  407. data/app/views/hyrax/dashboard/collections/_list_collections.html.erb +3 -0
  408. data/app/views/hyrax/dashboard/collections/_list_works.html.erb +1 -1
  409. data/app/views/hyrax/dashboard/collections/_show_document_list_menu.html.erb +13 -12
  410. data/app/views/hyrax/dashboard/collections/_show_document_list_row.html.erb +1 -1
  411. data/app/views/hyrax/dashboard/profiles/_edit_primary.html.erb +1 -8
  412. data/app/views/hyrax/dashboard/profiles/_trophy_edit.html.erb +1 -1
  413. data/app/views/hyrax/dashboard/profiles/show.html.erb +5 -5
  414. data/app/views/hyrax/dashboard/sidebar/_metadata.html.erb +11 -0
  415. data/app/views/hyrax/dashboard/sidebar/_repository_content.html.erb +1 -0
  416. data/app/views/hyrax/dashboard/works/_default_group.html.erb +3 -0
  417. data/app/views/hyrax/dashboard/works/_list_works.html.erb +4 -2
  418. data/app/views/hyrax/file_sets/_form.html.erb +16 -3
  419. data/app/views/hyrax/file_sets/_metadata.html.erb +35 -0
  420. data/app/views/hyrax/file_sets/_valkyrie_form.html.erb +37 -0
  421. data/app/views/hyrax/file_sets/edit.html.erb +14 -8
  422. data/app/views/hyrax/file_sets/media_display/_audio.html.erb +4 -0
  423. data/app/views/hyrax/file_sets/media_display/_image.html.erb +2 -2
  424. data/app/views/hyrax/file_sets/media_display/_video.html.erb +4 -0
  425. data/app/views/hyrax/homepage/_explore_collections.html.erb +1 -1
  426. data/app/views/hyrax/homepage/_featured_fields.html.erb +1 -1
  427. data/app/views/hyrax/homepage/_recent_document.html.erb +1 -1
  428. data/app/views/hyrax/homepage/robots.text.erb +17 -0
  429. data/app/views/hyrax/my/_admin_set_action_menu.html.erb +31 -27
  430. data/app/views/hyrax/my/_collection_action_menu.html.erb +40 -35
  431. data/app/views/hyrax/my/_work_action_menu.html.erb +23 -22
  432. data/app/views/hyrax/my/collections/_default_group.html.erb +3 -0
  433. data/app/views/hyrax/my/collections/_list_collections.html.erb +3 -0
  434. data/app/views/hyrax/my/collections/_modal_add_subcollection.html.erb +2 -2
  435. data/app/views/hyrax/my/collections/_modal_add_to_collection.html.erb +2 -2
  436. data/app/views/hyrax/my/works/_default_group.html.erb +3 -0
  437. data/app/views/hyrax/my/works/_list_works.html.erb +5 -2
  438. data/app/views/hyrax/shared/_copy_permalink.html.erb +10 -0
  439. data/app/views/hyrax/users/_user_info.html.erb +1 -6
  440. data/app/views/layouts/_head_tag_content.html.erb +2 -0
  441. data/app/views/layouts/hyrax/dashboard.html.erb +2 -1
  442. data/app/views/records/edit_fields/_contexts.html.erb +1 -0
  443. data/app/views/records/edit_fields/_license.html.erb +17 -5
  444. data/app/views/records/edit_fields/_resource_type.html.erb +16 -2
  445. data/app/views/records/edit_fields/_rights_statement.html.erb +17 -5
  446. data/app/views/records/edit_fields/_schema_version.html.erb +1 -0
  447. data/app/views/records/edit_fields/_transcript_ids.html.erb +18 -0
  448. data/app/views/records/show_fields/_rights.html.erb +1 -1
  449. data/app/views/shared/_citations.html.erb +46 -31
  450. data/app/views/shared/_schema_version.html.erb +38 -0
  451. data/bin/dev-entrypoint.sh +14 -4
  452. data/chart/hyrax/Chart.yaml +4 -4
  453. data/chart/hyrax/templates/ingress.yaml +3 -0
  454. data/chart/hyrax/values.yaml +10 -8
  455. data/config/features.rb +77 -40
  456. data/config/initializers/blacklight_dynamic_sitemap.rb +43 -0
  457. data/config/initializers/deprecation_patch.rb +27 -0
  458. data/config/initializers/hydra_works.rb +3 -0
  459. data/config/initializers/i18n_extensions.rb +197 -0
  460. data/config/initializers/indexing_adapter_initializer.rb +4 -0
  461. data/config/initializers/new_framework_defaults_7_2.rb +6 -4
  462. data/config/initializers/reform_rails_6_1_monkey_patch.rb +29 -0
  463. data/config/initializers/storage_adapter_initializer.rb +15 -9
  464. data/config/locales/hyrax.de.yml +172 -54
  465. data/config/locales/hyrax.en.yml +183 -66
  466. data/config/locales/hyrax.es.yml +174 -49
  467. data/config/locales/hyrax.fr.yml +169 -45
  468. data/config/locales/hyrax.it.yml +172 -48
  469. data/config/locales/hyrax.pt-BR.yml +172 -54
  470. data/config/locales/hyrax.zh.yml +145 -21
  471. data/config/metadata/basic_metadata.yaml +66 -0
  472. data/config/metadata/batch_edit_metadata.yaml +119 -0
  473. data/config/metadata/core_metadata.yaml +1 -0
  474. data/config/metadata/file_set_metadata.yaml +19 -0
  475. data/config/metadata/redirects.yaml +15 -0
  476. data/config/metadata_profiles/m3_json_schema.json +487 -0
  477. data/config/metadata_profiles/m3_profile.yaml +954 -0
  478. data/config/routes.rb +9 -0
  479. data/docker-compose-allinson.yml +176 -0
  480. data/docker-compose-dassie.yml +18 -10
  481. data/docker-compose-koppie.yml +18 -10
  482. data/docker-compose-sirenia.yml +20 -10
  483. data/documentation/copy_permalink.md +29 -0
  484. data/documentation/developing-your-hyrax-based-app.md +2 -2
  485. data/documentation/file-ingest-characterization.md +763 -0
  486. data/documentation/flexible_metadata.md +113 -0
  487. data/documentation/forms/field_behaviors.md +297 -0
  488. data/documentation/redirects.md +428 -0
  489. data/hyrax.gemspec +9 -4
  490. data/lib/freyja/metadata_adapter.rb +1 -1
  491. data/lib/freyja/persister.rb +36 -5
  492. data/lib/generators/hyrax/collection_resource/collection_resource_generator.rb +2 -2
  493. data/lib/generators/hyrax/collection_resource/templates/collection.rb.erb +5 -1
  494. data/lib/generators/hyrax/collection_resource/templates/collection_form.rb.erb +5 -1
  495. data/lib/generators/hyrax/collection_resource/templates/collection_indexer.rb.erb +6 -1
  496. data/lib/generators/hyrax/iiif_viewer/USAGE +22 -0
  497. data/lib/generators/hyrax/iiif_viewer/iiif_viewer_generator.rb +49 -0
  498. data/lib/generators/hyrax/iiif_viewer/templates/_clover.html.erb +7 -0
  499. data/lib/generators/hyrax/iiif_viewer/templates/clover/clover.css +3328 -0
  500. data/lib/generators/hyrax/iiif_viewer/templates/clover/clover.html +16 -0
  501. data/lib/generators/hyrax/iiif_viewer/templates/clover/clover.js +237 -0
  502. data/lib/generators/hyrax/install_generator.rb +25 -1
  503. data/lib/generators/hyrax/riiif_generator.rb +1 -1
  504. data/lib/generators/hyrax/templates/app/views/blacklight_dynamic_sitemap/sitemap/show.xml.builder +22 -0
  505. data/lib/generators/hyrax/templates/config/clamav.rb +2 -0
  506. data/lib/generators/hyrax/templates/config/initializers/riiif.rb +4 -80
  507. data/lib/generators/hyrax/templates/db/migrate/20240606205215_create_hyrax_flexible_schemas.rb.erb +9 -0
  508. data/lib/generators/hyrax/templates/db/migrate/20240606205216_add_contexts_to_hyrax_flexible_schemas.rb.erb +5 -0
  509. data/lib/generators/hyrax/templates/db/migrate/20260430000001_create_hyrax_redirect_paths.rb.erb +22 -0
  510. data/lib/generators/hyrax/templates/db/migrate/20260521003627_add_additional_redirect_info.rb.erb +39 -0
  511. data/lib/generators/hyrax/templates/package.json +1 -1
  512. data/lib/generators/hyrax/templates/uv.html +60 -82
  513. data/lib/generators/hyrax/work/templates/indexer.rb.erb +1 -1
  514. data/lib/generators/hyrax/work/templates/model.rb.erb +5 -1
  515. data/lib/generators/hyrax/work_resource/templates/form.rb.erb +5 -2
  516. data/lib/generators/hyrax/work_resource/templates/indexer.rb.erb +6 -2
  517. data/lib/generators/hyrax/work_resource/templates/work.rb.erb +5 -2
  518. data/lib/generators/hyrax/work_resource/work_resource_generator.rb +1 -0
  519. data/lib/hyrax/active_fedora_dummy_model.rb +6 -0
  520. data/lib/hyrax/configuration.rb +219 -10
  521. data/lib/hyrax/controlled_vocabulary/importer/language.rb +5 -1
  522. data/lib/hyrax/deprecation.rb +31 -0
  523. data/lib/hyrax/engine.rb +2 -0
  524. data/lib/hyrax/form_fields.rb +17 -5
  525. data/lib/hyrax/indexer.rb +31 -2
  526. data/lib/hyrax/resource_sync/resource_list_writer.rb +3 -0
  527. data/lib/hyrax/schema.rb +15 -4
  528. data/lib/hyrax/specs/shared_specs/factories/administrative_sets.rb +12 -0
  529. data/lib/hyrax/specs/shared_specs/factories/hyrax_embargo.rb +1 -1
  530. data/lib/hyrax/specs/shared_specs/factories/hyrax_file_set.rb +13 -0
  531. data/lib/hyrax/specs/shared_specs/factories/hyrax_lease.rb +5 -1
  532. data/lib/hyrax/specs/shared_specs/factories/hyrax_work.rb +14 -0
  533. data/lib/hyrax/specs/shared_specs/simple_work.rb +41 -0
  534. data/lib/hyrax/specs/shared_specs.rb +1 -0
  535. data/lib/hyrax/transactions/collection_create.rb +2 -1
  536. data/lib/hyrax/transactions/collection_destroy.rb +1 -0
  537. data/lib/hyrax/transactions/collection_update.rb +2 -1
  538. data/lib/hyrax/transactions/container.rb +28 -0
  539. data/lib/hyrax/transactions/steps/add_file_sets.rb +2 -1
  540. data/lib/hyrax/transactions/steps/apply_permission_template_on_update.rb +65 -0
  541. data/lib/hyrax/transactions/steps/apply_workflow_on_admin_set_change.rb +97 -0
  542. data/lib/hyrax/transactions/steps/ensure_admin_set.rb +1 -1
  543. data/lib/hyrax/transactions/steps/remove_redirect_paths.rb +35 -0
  544. data/lib/hyrax/transactions/steps/save.rb +10 -0
  545. data/lib/hyrax/transactions/steps/set_default_admin_set.rb +1 -1
  546. data/lib/hyrax/transactions/steps/sync_redirect_paths.rb +141 -0
  547. data/lib/hyrax/transactions/work_create.rb +2 -1
  548. data/lib/hyrax/transactions/work_destroy.rb +1 -0
  549. data/lib/hyrax/transactions/work_update.rb +4 -1
  550. data/lib/hyrax/version.rb +1 -1
  551. data/lib/hyrax.rb +62 -0
  552. data/lib/tasks/m3_profile_cleanup.rake +35 -0
  553. data/lib/valkyrie/indexing/redis_queue/indexing_adapter.rb +144 -0
  554. data/lib/wings/valkyrie/query_service.rb +3 -4
  555. data/template.rb +4 -1
  556. metadata +327 -25
  557. data/.dassie/public/robots.txt +0 -1
  558. data/.github/workflows/main.yml +0 -17
  559. data/.koppie/public/robots.txt +0 -1
  560. data/app/forms/concerns/hyrax/basic_metadata_form_fields_behavior.rb +0 -39
  561. data/app/views/catalog/_thumbnail_list_collection.html.erb +0 -4
@@ -8,8 +8,11 @@ module Hyrax
8
8
  include Hyrax::PermissionIndexer
9
9
  include Hyrax::VisibilityIndexer
10
10
  include Hyrax::ThumbnailIndexer
11
- include Hyrax::Indexer(:core_metadata)
12
- include Hyrax::Indexer(:file_set_metadata)
11
+ if Hyrax.config.file_set_include_metadata
12
+ include Hyrax::Indexer(:core_metadata)
13
+ include Hyrax::Indexer(:file_set_metadata)
14
+ end
15
+ check_if_flexible(Hyrax::FileSet)
13
16
 
14
17
  def to_solr # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
15
18
  super.tap do |solr_doc| # rubocop:disable Metrics/BlockLength
@@ -21,6 +24,7 @@ module Hyrax
21
24
  solr_doc['extracted_text_id_ssi'] = resource.extracted_text_id.to_s
22
25
  solr_doc['hasRelatedMediaFragment_ssim'] = resource.representative_id.to_s
23
26
  solr_doc['hasRelatedImage_ssim'] = resource.thumbnail_id.to_s
27
+ solr_doc['transcript_ids_ssim'] = resource.transcript_ids&.map(&:to_s) if resource.respond_to?(:transcript_ids)
24
28
 
25
29
  index_lease(solr_doc)
26
30
  index_embargo(solr_doc)
@@ -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,22 @@
1
+ # frozen_string_literal: true
2
+ module Hyrax
3
+ # Grants the user's edit access on the provided FileSet
4
+ module QueuedJobBehavior
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ queue_as Hyrax.config.ingest_queue_name
9
+ cattr_accessor :requeue_frequency
10
+ end
11
+
12
+ private
13
+
14
+ def redis_queue
15
+ Valkyrie::IndexingAdapter.find(:redis_queue)
16
+ end
17
+
18
+ def requeue(**args)
19
+ self.class.set(wait_until: (self.class.requeue_frequency || 5.minutes).from_now).perform_later(**args)
20
+ end
21
+ end
22
+ end
@@ -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
@@ -26,7 +26,7 @@ module Hyrax
26
26
  def apply_depositor_metadata(resource, depositor)
27
27
  depositor_id = depositor.respond_to?(:user_key) ? depositor.user_key : depositor
28
28
  resource.depositor = depositor_id if resource.respond_to? :depositor=
29
- Hyrax::AccessControlList.new(resource: resource).grant(:edit).to(::User.find_by_user_key(depositor_id)).save
29
+ resource.permission_manager.acl.grant(:edit).to(::User.find_by_user_key(depositor_id)).save
30
30
  end
31
31
  end
32
32
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+ module Hyrax
3
+ class QueuedDeleteJob < ApplicationJob
4
+ include QueuedJobBehavior
5
+
6
+ def perform(size: 200)
7
+ redis_queue.delete_queue(size: size)
8
+ requeue(size: size)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+ module Hyrax
3
+ class QueuedIndexingJob < ApplicationJob
4
+ include QueuedJobBehavior
5
+
6
+ def perform(size: 200)
7
+ redis_queue.index_queue(size: size)
8
+ requeue(size: size)
9
+ end
10
+ end
11
+ end
@@ -2,6 +2,11 @@
2
2
  # Responsible for conditionally enqueuing the file and thumbnail migration
3
3
  # logic of an ActiveFedora object.
4
4
  class MigrateFilesToValkyrieJob < Hyrax::ApplicationJob
5
+ # Define a logger for this job
6
+ def logger
7
+ FileUtils.mkdir_p(Hyrax.config.working_path)
8
+ @logger ||= Logger.new(Hyrax.config.working_path.join('migrate_files_to_valkyrie_job.log'))
9
+ end
5
10
  ##
6
11
  #
7
12
  # @param resource [Hyrax::FileSet]
@@ -33,6 +38,7 @@ class MigrateFilesToValkyrieJob < Hyrax::ApplicationJob
33
38
  # @todo should we trigger a job if the member is a child work?
34
39
  paths = Hyrax::DerivativePath.derivatives_for_reference(resource)
35
40
  paths.each do |path|
41
+ next unless File.size?(path) # skip blank files
36
42
  container = container_for(path)
37
43
  mime_type = Marcel::MimeType.for(extension: File.extname(path))
38
44
  directives = { url: path, container: container, mime_type: mime_type }
@@ -50,27 +56,39 @@ class MigrateFilesToValkyrieJob < Hyrax::ApplicationJob
50
56
 
51
57
  files = Hyrax.custom_queries.find_many_file_metadata_by_ids(ids: resource.file_ids)
52
58
  files.each do |file|
53
- # If it doesn't start with fedora, we've likely already migrated it.
54
- next unless /^fedora:/.match?(file.file_identifier.to_s)
55
- resource.file_ids.delete(file.id)
59
+ begin
60
+ # If it doesn't start with fedora, we've likely already migrated it.
61
+ next unless /^fedora:/.match?(file.file_identifier.to_s)
62
+
63
+ resource.file_ids.delete(file.id)
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?
56
69
 
57
- Tempfile.create do |tempfile|
58
- tempfile.binmode
59
- tempfile.write(URI.open(file.file_identifier.to_s.gsub("fedora:", "http:")).read)
60
- tempfile.rewind
70
+ Tempfile.create do |tempfile|
71
+ tempfile.binmode
72
+ tempfile.write(URI.open(file.file_identifier.to_s.gsub("fedora:", "http:")).read)
73
+ tempfile.rewind
61
74
 
62
- # valkyrie_file = Hyrax.storage_adapter.upload(resource: resource, file: tempfile, original_filename: file.original_filename)
63
- valkyrie_file = Hyrax::ValkyrieUpload.file(
64
- filename: resource.label,
65
- file_set: resource,
66
- io: tempfile,
67
- use: file.pcdm_use.select {|use| Hyrax::FileMetadata::Use.use_list.include?(use)},
68
- user: User.find_or_initialize_by(User.user_key_field => resource.depositor),
69
- mime_type: file.mime_type,
70
- skip_derivatives: true
71
- )
72
- valkyrie_file = copy_attributes(valkyrie_file:, original_file: file)
73
- Hyrax.persister.save(resource: valkyrie_file)
75
+ # valkyrie_file = Hyrax.storage_adapter.upload(resource: resource, file: tempfile, original_filename: file.original_filename)
76
+ valkyrie_file = Hyrax::ValkyrieUpload.file(
77
+ filename: file.original_filename,
78
+ file_set: resource,
79
+ io: tempfile,
80
+ use: file.pcdm_use.select {|use| Hyrax::FileMetadata::Use.use_list.include?(use)},
81
+ user: User.find_or_initialize_by(User.user_key_field => resource.depositor),
82
+ mime_type: file.mime_type,
83
+ skip_derivatives: true
84
+ )
85
+ valkyrie_file = copy_attributes(valkyrie_file:, original_file: file)
86
+ Hyrax.persister.save(resource: valkyrie_file)
87
+ end
88
+ rescue StandardError => e
89
+ # Log errors specific to file migration
90
+ logger.error("Error migrating file #{file.id} for resource #{resource.id}: #{e.message}")
91
+ logger.error(e.backtrace.join("\n"))
74
92
  end
75
93
  end
76
94
  # reindex the file set after migrating files to include characterization info
@@ -93,9 +111,9 @@ class MigrateFilesToValkyrieJob < Hyrax::ApplicationJob
93
111
  #
94
112
  # @param filename [String] the name of the derivative file: i.e. 'x-thumbnail.jpg'
95
113
  # @return [String]
96
- def container_for(filename)
114
+ def container_for(path)
97
115
  # we want the portion between the '-' and the '.'
98
- file_blob = File.basename(filename, '.*').split('-').last
116
+ file_blob = File.basename(path, '.*').split('-').last
99
117
 
100
118
  case file_blob
101
119
  when 'thumbnail'
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ # migrates a resource's sipity entity so it can be found
4
+ class MigrateSipityEntityJob < ApplicationJob
5
+ # input [String] id of a migrated resource
6
+ def perform(id:)
7
+ resource = Hyrax.query_service.find_by(id: id)
8
+ new_gid = Hyrax::GlobalID(resource).to_s
9
+ return if Sipity::Entity.find_by(proxy_for_global_id: new_gid)
10
+
11
+ work = resource.internal_resource.constantize.find(id)
12
+ original_gid = Hyrax::GlobalID(work).to_s
13
+ return if new_gid == original_gid
14
+ original_entity = Sipity::Entity.find_by(proxy_for_global_id: original_gid)
15
+ return if original_entity.nil?
16
+ original_entity.update(proxy_for_global_id: new_gid)
17
+ rescue ActiveFedora::ObjectNotFoundError
18
+ # this happens when the resource was never in Fedora so there is nothing to migrate.
19
+ # We don't want to retry the job so we don't raise an error.
20
+ end
21
+ end
@@ -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
@@ -404,8 +406,10 @@ module Hyrax
404
406
  .select(:source_id)
405
407
  .distinct
406
408
  .pluck(:source_id)
407
-
408
- Hyrax.custom_queries.find_ids_by_model(model: Hyrax::AdministrativeSet, ids: ids).any?
409
+ return false if ids.empty?
410
+ Hyrax::SolrQueryService.new.with_ids(ids: ids).query_result(rows: 1000)['response']['docs'].any? do |doc|
411
+ (Hyrax::ModelRegistry.admin_set_rdf_representations & doc['has_model_ssim']).present?
412
+ end
409
413
  end
410
414
 
411
415
  def registered_user?
@@ -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