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
@@ -26,6 +26,8 @@ module Hyrax
26
26
  end
27
27
  end
28
28
 
29
+ include BasedNearFieldBehavior
30
+ include CompoundFieldBehavior
29
31
  class_attribute :model_class
30
32
 
31
33
  property :human_readable_type, writable: false
@@ -42,25 +44,87 @@ module Hyrax
42
44
  # @see https://github.com/samvera/valkyrie/wiki/Optimistic-Locking
43
45
  property :version, virtual: true, prepopulator: LockKeyPrepopulator
44
46
 
47
+ # Wire validators with `attributes:` through `validation { ... }` rather
48
+ # than the bare `validates_with`. Reform's `validates_with` shim closes
49
+ # over the args array, so the options hash (`{attributes: [:foo]}`) is
50
+ # shared across heritage replays. ActiveModel mutates that hash on each
51
+ # call (`options[:class] = self`, then `options.delete(:attributes)`
52
+ # inside `EachValidator#initialize`). The first replay leaves the hash
53
+ # without `:attributes`; the second replay raises
54
+ # `:attributes cannot be blank` and the subclass crashes at load time.
55
+ # Wrapping in `validation(name: :default, inherit: true) { ... }` rebuilds
56
+ # the literal options hash on every replay so each subclass gets its own
57
+ # clean copy. This pattern applies to *any* `validates_with` that takes
58
+ # an `attributes:` keyword.
59
+
45
60
  ##
46
61
  # @api public
47
62
  #
48
63
  # Forms should be initialized with an explicit +resource:+ parameter to
49
64
  # match indexers.
65
+ # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
50
66
  def initialize(deprecated_resource = nil, resource: nil)
67
+ r = resource || deprecated_resource
68
+ if r.flexible?
69
+ self.class.deserializer_class = nil # need to reload this on first use after schema is loaded
70
+ singleton_class.schema_definitions = self.class.definitions
71
+ contexts = r.respond_to?(:contexts) ? r.contexts : nil
72
+ current_schema_fields = Hyrax::Schema.m3_schema_loader.form_definitions_for(schema: r.class.name, version: Hyrax::FlexibleSchema.current_schema_id, contexts: contexts)
73
+ current_schema_fields.each do |field_name, options|
74
+ singleton_class.property field_name.to_sym, options.merge(display: options.fetch(:display, true), default: [])
75
+ end
76
+ end
77
+
51
78
  if resource.nil?
52
79
  if !deprecated_resource.nil?
53
80
  Deprecation.warn "Initializing Valkyrie forms without an explicit resource parameter is deprecated. Pass the resource with `resource:` instead."
81
+ # Remove form definitions for attributes the model doesn't support,
82
+ # mirroring the cleanup in the resource: keyword path below.
83
+ if deprecated_resource.respond_to?(:flexible?) && deprecated_resource.flexible?
84
+ to_remove = singleton_class.definitions.select { |k, v| !deprecated_resource.respond_to?(k) && v.instance_variable_get("@options")[:display] }
85
+ to_remove.keys.each { |removed_field| singleton_class.definitions.delete(removed_field) }
86
+ end
54
87
  super(deprecated_resource)
55
88
  else
56
89
  super()
57
90
  end
58
91
  else
92
+ # make a new resource with all of the existing attributes
93
+ if resource.flexible?
94
+ hash = resource.attributes.dup
95
+ hash[:schema_version] = Hyrax::FlexibleSchema.current_schema_id
96
+ resource = resource.class.new(hash)
97
+ # find any fields removed by the current schema
98
+ current_field_keys = current_schema_fields.keys.map(&:to_s)
99
+ to_remove = singleton_class.definitions.select { |k, v| !current_field_keys.include?(k.to_s) && v.instance_variable_get("@options")[:display] }
100
+ to_remove.keys.each do |removed_field|
101
+ singleton_class.definitions.delete(removed_field)
102
+ end
103
+ end
104
+
59
105
  super(resource)
60
106
  end
61
107
  end
108
+ # rubocop:enable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
62
109
 
63
110
  class << self
111
+ def inherited(subclass)
112
+ # Field Behaviors must be prepended onto every subclass so their
113
+ # `deserialize!` overrides land above Reform's base method on the
114
+ # ancestor chain. Each behavior gates itself internally and is a
115
+ # no-op when its feature is off or its property isn't on the
116
+ # subclass's model.
117
+ subclass.prepend(BasedNearFieldBehavior)
118
+ subclass.prepend(RedirectsFieldBehavior)
119
+ super
120
+ end
121
+
122
+ def check_if_flexible(model)
123
+ return unless model.flexible?
124
+ include FlexibleFormBehavior
125
+ include Hyrax::FormFields(model.to_s, definition_loader: Hyrax::Schema.m3_schema_loader)
126
+ end
127
+
64
128
  ##
65
129
  # @api public
66
130
  #
@@ -69,11 +133,12 @@ module Hyrax
69
133
  # @example
70
134
  # monograph = Monograph.new
71
135
  # change_set = Hyrax::Forms::ResourceForm.for(resource: monograph)
72
- def for(deprecated_resource = nil, resource: nil)
136
+ def for(deprecated_resource = nil, resource: nil, admin_set_id: nil)
73
137
  if resource.nil? && !deprecated_resource.nil?
74
138
  Deprecation.warn "Initializing Valkyrie forms without an explicit resource parameter is deprecated. Pass the resource with `resource:` instead."
75
- return self.for(resource: deprecated_resource)
139
+ return self.for(resource: deprecated_resource, admin_set_id: admin_set_id)
76
140
  end
141
+ apply_admin_set_contexts(resource: resource, admin_set_id: admin_set_id)
77
142
  klass = "#{resource.class.name}Form".safe_constantize
78
143
  klass ||= Hyrax::Forms::ResourceForm(resource.class)
79
144
  begin
@@ -84,10 +149,23 @@ module Hyrax
84
149
  end
85
150
  end
86
151
 
152
+ private
153
+
154
+ def apply_admin_set_contexts(resource:, admin_set_id:)
155
+ return if admin_set_id.blank?
156
+ return unless resource.respond_to?(:flexible?) && resource.flexible?
157
+ admin_set = Hyrax.query_service.find_by(id: admin_set_id)
158
+ return unless admin_set&.respond_to?(:contexts)
159
+ contexts = Array(admin_set.contexts)
160
+ resource.contexts = contexts if contexts.present?
161
+ rescue Valkyrie::Persistence::ObjectNotFoundError
162
+ nil
163
+ end
164
+
87
165
  ##
88
166
  # @return [Array<Symbol>] list of required field names as symbols
89
167
  def required_fields
90
- definitions
168
+ schema_definitions
91
169
  .select { |_, definition| definition[:required] }
92
170
  .keys.map(&:to_sym)
93
171
  end
@@ -98,14 +176,27 @@ module Hyrax
98
176
  # @return [Array<Symbol>] list of required field names as symbols
99
177
  def required_fields=(fields)
100
178
  fields = fields.map(&:to_s)
101
- raise(KeyError) unless fields.all? { |f| definitions.key?(f) }
179
+ raise(KeyError) unless fields.all? { |f| schema_definitions.key?(f) }
102
180
 
103
- fields.each { |field| definitions[field].merge!(required: true) }
181
+ fields.each { |field| schema_definitions[field].merge!(required: true) }
104
182
 
105
183
  required_fields
106
184
  end
107
- end
108
185
 
186
+ def schema_definitions
187
+ @definitions
188
+ end
189
+
190
+ def schema_definitions=(values)
191
+ @definitions = values
192
+ end
193
+
194
+ def expose_class
195
+ @expose_class = Class.new(Disposable::Expose).from(schema_definitions.values)
196
+ end
197
+
198
+ public :expose_class, :required_fields, :required_fields=, :schema_definitions, :schema_definitions=
199
+ end
109
200
  ##
110
201
  # @param [#to_s] attr
111
202
  # @param [Object] value
@@ -127,9 +218,12 @@ module Hyrax
127
218
  # @return [Array<Symbol>] terms for display 'above-the-fold', or in the most
128
219
  # prominent form real estate
129
220
  def primary_terms
130
- _form_field_definitions
131
- .select { |_, definition| definition[:primary] }
132
- .keys.map(&:to_sym)
221
+ terms = _form_field_definitions
222
+ .select { |_, definition| definition[:primary] }
223
+ .keys.map(&:to_sym)
224
+
225
+ terms = [:schema_version, :contexts] + terms if model.flexible?
226
+ terms
133
227
  end
134
228
 
135
229
  ##
@@ -146,10 +240,16 @@ module Hyrax
146
240
  secondary_terms.any?
147
241
  end
148
242
 
243
+ delegate :flexible?, to: :model
244
+
149
245
  private
150
246
 
151
247
  def _form_field_definitions
152
- self.class.definitions
248
+ if model.flexible?
249
+ singleton_class.schema_definitions
250
+ else
251
+ self.class.definitions
252
+ end
153
253
  end
154
254
  end
155
255
  end
@@ -13,6 +13,7 @@ module Hyrax
13
13
  def self.PcdmObjectForm(work_class) # rubocop:disable Naming/MethodName
14
14
  Class.new(Hyrax::Forms::PcdmObjectForm) do
15
15
  self.model_class = work_class
16
+ include Hyrax::FormFields(:core_metadata) if work_class.ancestors.detect { |k| k.inspect == "Hyrax::Schema(core_metadata)" }
16
17
 
17
18
  ##
18
19
  # @return [String]
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hyrax
4
+ module AttributesHelper
5
+ def view_options_for(presenter)
6
+ model_name = presenter.model.model_name.klass.to_s
7
+ if presenter.respond_to?(:flexible?) && presenter.flexible?
8
+ Hyrax::Schema.m3_schema_loader.view_definitions_for(schema: model_name, version: presenter.solr_document.schema_version, contexts: presenter.solr_document.contexts)
9
+ else
10
+ view_options_without_flexibility(presenter, model_name)
11
+ end
12
+ end
13
+
14
+ def view_options_without_flexibility(presenter, model_name)
15
+ model = presenter.model
16
+ schema = schema(model)
17
+
18
+ # no schema found for given model - try a few more fallbacks
19
+
20
+ # if wings is enabled we may be able to use the model registry to find the new model
21
+ if schema.nil? && !Hyrax.config.disable_wings
22
+ new_model = Wings::ModelRegistry.reverse_lookup(model)
23
+ schema = schema(new_model) if new_model
24
+ end
25
+ # Check if the model has a resource version
26
+ if schema.nil?
27
+ new_model = "#{model_name}Resource".safe_constantize
28
+ schema = schema(new_model) if new_model
29
+ end
30
+ # If we still don't have a schema, assume we have a pre-valkyrie model
31
+ if schema.nil?
32
+ if model.respond_to?(:local_attributes)
33
+ return model.local_attributes
34
+ else
35
+ return []
36
+ end
37
+ end
38
+
39
+ Hyrax::Schema.simple_schema_loader.view_definitions_for(schema:)
40
+ end
41
+
42
+ # @param [String] model's class name
43
+ # @return [Hash] the schema for the model or nil if not found
44
+ def schema(model)
45
+ return nil unless model.present?
46
+
47
+ # If this is an ActiveFedoraDummyModel, get the schema from the actual model class
48
+ if model.is_a?(Hyrax::ActiveFedoraDummyModel)
49
+ actual_model = model.instance_variable_get(:@model)
50
+ return schema(actual_model) if actual_model
51
+ end
52
+
53
+ # using respond_to? check because try? does not succeed with Dry::Types object that is returned by schema method
54
+ return nil unless model.respond_to?(:schema)
55
+ model.schema
56
+ end
57
+
58
+ # @param [String] field name
59
+ # @param [Hash<Hash>] a nested hash of view options...
60
+ # {:render_term=>:based_near_label, :label=>{"en"=>"Title", "es"=>"Título"}, :html_dl=>true}
61
+ # @return [String] the field name to be used for rendering
62
+ def conform_field(field_name, options_hash)
63
+ options_hash&.with_indifferent_access&.fetch('render_term', nil) || field_name
64
+ end
65
+
66
+ # @param [String] field name
67
+ # @param [Hash<Hash>] a nested hash of view options...
68
+ # {:label=>{"en"=>"Title", "es"=>"Título"}, :html_dl=>true}
69
+ # @return [Hash] the transformed options for the field
70
+ def conform_options(field_name, view_options)
71
+ hash_of_locales = view_options.delete(:display_label) || {}
72
+
73
+ if hash_of_locales.present?
74
+ view_options[:label] = hash_of_locales[locale] || hash_of_locales[:default]
75
+ else
76
+ view_options[:label] = (view_options[:render_term] || field_name).to_s
77
+ end
78
+ field = view_options[:label]
79
+ translate = I18n.t(field, default: field) if field.match(/\./)
80
+ if translate && translate != field
81
+ view_options[:label] = translate
82
+ else
83
+ view_options[:label] = field_label(
84
+ :"blacklight.search.fields.index.#{field}",
85
+ :"blacklight.search.fields.show.#{field}",
86
+ :"blacklight.search.fields.#{field}",
87
+ field.to_s.humanize
88
+ )
89
+ end
90
+ view_options[:base_url] = request.base_url if respond_to?(:request) && request.respond_to?(:base_url)
91
+ view_options
92
+ end
93
+
94
+ # Returns true when the field should render on the work show page.
95
+ # Honors these view options:
96
+ # * `show_page: false` — suppresses the field on the show page for everyone.
97
+ # * `admin_only: true` — only visible to admins.
98
+ # * `editor_only: true` — only visible to users the presenter reports as editors.
99
+ # Setting both `admin_only` and `editor_only` is effectively equivalent to
100
+ # `admin_only` alone: admins are editors of every record, so they pass both
101
+ # guards, but a plain editor of the record still fails the admin guard.
102
+ def field_visible?(view_options, presenter)
103
+ return false if view_options[:show_page] == false
104
+ return false if view_options[:admin_only] && !current_user&.admin?
105
+ return false if view_options[:editor_only] && !presenter.try(:editor?)
106
+ true
107
+ end
108
+ end
109
+ end
@@ -5,5 +5,31 @@ module Hyrax
5
5
  def application_name
6
6
  t('hyrax.product_name', default: super)
7
7
  end
8
+
9
+ # rubocop:disable Metrics/MethodLength
10
+ def index_field_label(document, field)
11
+ field_config = index_fields(document)[field]
12
+ return resolve_label(field_config) if field_config&.custom_label || field_config&.label&.respond_to?(:call)
13
+
14
+ translate = I18n.t(field_config.label, default: field_config.label) if field_config&.label&.match(/\./)
15
+ if translate && translate != field_config.label
16
+ field_label(translate, field_config.label, field.to_s.humanize)
17
+ else
18
+ field_label(
19
+ :"blacklight.search.fields.index.#{field}",
20
+ :"blacklight.search.fields.show.#{field}",
21
+ :"blacklight.search.fields.#{field}",
22
+ (field_config.label if field_config),
23
+ field.to_s.humanize
24
+ )
25
+ end
26
+ end
27
+ # rubocop:enable Metrics/MethodLength
28
+
29
+ private
30
+
31
+ def resolve_label(field_config)
32
+ field_config.label.respond_to?(:call) ? field_config.label.call : field_config.label
33
+ end
8
34
  end
9
35
  end
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
  module Hyrax
3
3
  module CollectionsHelper # rubocop:disable Metrics/ModuleLength
4
+ include Hyrax::RedirectsTabHelper
5
+
4
6
  ##
5
7
  # @since 3.1.0
6
8
  # @return [Array<SolrDocument>]
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hyrax
4
+ module FileSetFormHelper
5
+ def render_transcript_ids_field?(file_set)
6
+ return unless file_set.persisted?
7
+ return if @parent.nil?
8
+ case file_set
9
+ when ActiveFedora::Base
10
+ file_set.video? || file_set.audio?
11
+ when Valkyrie::Resource
12
+ service = Hyrax::FileSetTypeService.new(file_set: file_set)
13
+ service.video? || service.audio?
14
+ end
15
+ end
16
+
17
+ def transcript_ids_select_options
18
+ options = Forms::FileSetForm.available_transcripts(parent: @parent, current_ability: current_ability)
19
+ options.each_with_object({}) do |doc, hash|
20
+ hash[doc.title_or_label] = doc.id.to_s
21
+ end
22
+ end
23
+ end
24
+ end
@@ -19,6 +19,34 @@ module Hyrax
19
19
  include Hyrax::WorkFormHelper
20
20
  include Hyrax::WorkflowsHelper
21
21
  include Hyrax::FacetsHelper
22
+ include Hyrax::AttributesHelper
23
+ include Hyrax::PermalinkHelper
24
+ include Hyrax::WorksHelper
25
+ include Hyrax::FileSetFormHelper
26
+
27
+ ##
28
+ # @return [Array<String>] the list of admin sets available for creating works for this user
29
+ def available_admin_sets_for_creating_works(ability:)
30
+ return [] unless Flipflop.assign_admin_set?
31
+ return [] unless ability
32
+
33
+ source_ids = Hyrax::Collections::PermissionsService.source_ids_for_deposit(ability:, source_type: 'admin_set')
34
+
35
+ admin_sets_list = Hyrax.query_service.find_many_by_ids(ids: source_ids).map do |source|
36
+ [source.title.first, source.id]
37
+ end
38
+
39
+ # Sorts the default admin set to be first, then the rest by title.
40
+ admin_sets_list.sort do |a, b|
41
+ if Hyrax::AdminSetCreateService.default_admin_set?(id: a[1])
42
+ -1
43
+ elsif Hyrax::AdminSetCreateService.default_admin_set?(id: b[1])
44
+ 1
45
+ else
46
+ a[0] <=> b[0]
47
+ end
48
+ end
49
+ end
22
50
 
23
51
  ##
24
52
  # @return [Array<String>] the list of all user groups
@@ -233,7 +261,10 @@ module Hyrax
233
261
  # @return [ActiveSupport::SafeBuffer] license links, html_safe
234
262
  def license_links(options)
235
263
  service = Hyrax.config.license_service_class.new
236
- to_sentence(options[:value].map { |right| link_to service.label(right), right })
264
+ to_sentence(options[:value].map do |right|
265
+ label = service.label(right) { right }
266
+ Hyrax::AuthorityRenderingHelper.linkable_uri?(right) ? link_to(label, right) : ERB::Util.h(label)
267
+ end)
237
268
  end
238
269
 
239
270
  # A Blacklight index field helper_method
@@ -241,7 +272,10 @@ module Hyrax
241
272
  # @return [ActiveSupport::SafeBuffer] rights statement links, html_safe
242
273
  def rights_statement_links(options)
243
274
  service = Hyrax.config.rights_statement_service_class.new
244
- to_sentence(options[:value].map { |right| link_to service.label(right), right })
275
+ to_sentence(options[:value].map do |right|
276
+ label = service.label(right) { right }
277
+ Hyrax::AuthorityRenderingHelper.linkable_uri?(right) ? link_to(label, right) : ERB::Util.h(label)
278
+ end)
245
279
  end
246
280
 
247
281
  # A Blacklight facet field helper_method
@@ -288,6 +322,21 @@ module Hyrax
288
322
  tag.span("", class: [Hyrax::ModelIcon.css_class_for(::Collection), "collection-icon-search"])
289
323
  end
290
324
 
325
+ # Returns alt text for a thumbnail image.
326
+ # When the document has a custom thumbnail (thumbnail_alt_text indexed), delegates to
327
+ # alt_text_for_view to get the specific alt text. Otherwise returns a generic fallback
328
+ # (hyrax.sr.thumbnail) indicating a default representative image is shown.
329
+ # Apps can override this method to inject content-block lookups or other custom logic.
330
+ #
331
+ # @param document [SolrDocument]
332
+ # @param block_name [String] unused here; provided for API compatibility with overrides
333
+ # @return [String]
334
+ def thumbnail_alt_text_for(document, block_name: nil) # rubocop:disable Lint/UnusedMethodArgument
335
+ return document.alt_text_for_view if document.respond_to?(:thumbnail_alt_text) && document.thumbnail_alt_text.present?
336
+
337
+ t('hyrax.sr.thumbnail')
338
+ end
339
+
291
340
  def collection_title_by_id(id)
292
341
  solr_docs = controller.blacklight_config.repository.find(id).docs
293
342
  return nil if solr_docs.empty?
@@ -10,8 +10,18 @@ module Hyrax
10
10
  'hyrax/base/iiif_viewers/' + work_presenter.iiif_viewer.to_s
11
11
  end
12
12
 
13
+ # For backwards compatibility
13
14
  def universal_viewer_base_url
14
- "#{request&.base_url}/uv/uv.html"
15
+ iiif_viewer_base_url(:universal_viewer)
16
+ end
17
+
18
+ def iiif_viewer_base_url(viewer)
19
+ case viewer
20
+ when :universal_viewer
21
+ "#{request&.base_url}/uv/uv.html"
22
+ else
23
+ "#{request&.base_url}/#{viewer}/#{viewer}.html"
24
+ end
15
25
  end
16
26
 
17
27
  def universal_viewer_config_url
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hyrax
4
+ # Helpers for the "Copy permalink" button on work and collection show pages.
5
+ # See documentation/copy_permalink.md.
6
+ module PermalinkHelper
7
+ # The UUID-based URL for the record represented by `presenter`, so
8
+ # it is stable across alias changes and is safe to share or cite.
9
+ def permalink_for(presenter)
10
+ strip_query_string(request.base_url + Hyrax::PermalinkPath.call(presenter))
11
+ end
12
+
13
+ # The URL used in the show page's `<link rel="canonical">` tag.
14
+ def canonical_url_for(presenter)
15
+ display_path = Hyrax.config.redirects_active? && Hyrax::RedirectsLookup.display_path_for(presenter.id.to_s)
16
+ return permalink_for(presenter) if display_path.blank?
17
+ strip_query_string(request.base_url + display_path)
18
+ end
19
+
20
+ def copy_permalink_enabled?
21
+ Flipflop.enabled?(:copy_permalink_button)
22
+ end
23
+
24
+ private
25
+
26
+ # Removes the `?…` query string from a URL so the permalink is a clean
27
+ # canonical reference. Rails URL helpers append `?locale=...` (and any
28
+ # other registered `default_url_options`) by default; for a stable
29
+ # citable URL we want the bare host + path.
30
+ def strip_query_string(url)
31
+ parsed = URI.parse(url)
32
+ parsed.query = nil
33
+ parsed.fragment = nil
34
+ parsed.to_s
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hyrax
4
+ ##
5
+ # Decides whether the Aliases tab should appear on a work or
6
+ # collection edit form. Included into `WorkFormHelper` and
7
+ # `CollectionsHelper` so both forms share one rule.
8
+ #
9
+ # The tab appears only when the redirects feature is fully active
10
+ # (`Hyrax.config.redirects_active?`), the form is a ResourceForm
11
+ # (the only form pipeline with the redirects populator, validator,
12
+ # and prepopulator wired in), AND the form's underlying resource
13
+ # carries the `redirects` attribute. The structural check guards
14
+ # against adopter work or collection classes that don't include
15
+ # the redirects schema; without it the tab would render and crash
16
+ # on `f.object.redirects`.
17
+ module RedirectsTabHelper
18
+ def redirects_tab?(form)
19
+ return false unless Hyrax.config.redirects_active?
20
+ return false unless redirects_supported_form?(form)
21
+ target = form.respond_to?(:model) ? form.model : form
22
+ target.respond_to?(:redirects)
23
+ end
24
+
25
+ def redirects_supported_form?(form)
26
+ form.is_a?(Hyrax::Forms::ResourceForm)
27
+ end
28
+ end
29
+ end
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
  module Hyrax
3
3
  module WorkFormHelper
4
+ include Hyrax::RedirectsTabHelper
5
+
4
6
  ##
5
7
  # @todo this implementation hits database backends (solr) and is invoked
6
8
  # from views. refactor to avoid
@@ -30,11 +32,13 @@ module Hyrax
30
32
  # @param form [Hyrax::Forms::WorkForm, Hyrax::Forms::ResourceForm]
31
33
  # @return [Array<String>] the list of names of tabs to be rendered in the form
32
34
  def form_tabs_for(form:)
33
- if form.instance_of? Hyrax::Forms::BatchUploadForm
34
- %w[files metadata relationships]
35
- else
36
- %w[metadata files relationships]
37
- end
35
+ tabs = if form.instance_of? Hyrax::Forms::BatchUploadForm
36
+ %w[files metadata relationships]
37
+ else
38
+ %w[metadata files relationships]
39
+ end
40
+ tabs << 'redirects' if redirects_tab?(form)
41
+ tabs
38
42
  end
39
43
 
40
44
  ##
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hyrax
4
+ module WorksHelper
5
+ def available_collections(work:)
6
+ return [] if @current_ability.blank?
7
+
8
+ all_collections = Hyrax::CollectionsService.new(self).all_search_results(:deposit)
9
+ return all_collections if work.blank?
10
+
11
+ all_collections.reject { |col| work.member_of_collection_ids.include?(col.id) }
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hyrax
4
+ module WorkflowIndexer
5
+ # Write the workflow roles and state into the solr_document
6
+ # @param [Hash] solr_document the solr document to add the fields to
7
+ def to_solr
8
+ super.tap do |solr_doc|
9
+ index_workflow_fields(solr_doc)
10
+ end
11
+ end
12
+
13
+ # Write the workflow roles and state so one can see where the document moves to next
14
+ # @param [Hash] solr_document the solr document to add the field to
15
+ def index_workflow_fields(solr_document)
16
+ entity = Sipity::Entity(resource)
17
+ solr_document['actionable_workflow_roles_ssim'] = workflow_roles(entity).map { |role| "#{entity.workflow.permission_template.source_id}-#{entity.workflow.name}-#{role}" }
18
+ solr_document['workflow_state_name_ssim'] = entity.workflow_state.name if entity.workflow_state
19
+ rescue Sipity::ConversionError
20
+ nil
21
+ end
22
+
23
+ # Get the workflow roles for the entity
24
+ # @param [Sipity::Entity] entity the entity to get the workflow roles for
25
+ # @return [Array<String>] the workflow roles for the entity
26
+ def workflow_roles(entity)
27
+ Hyrax::Workflow::PermissionQuery.scope_roles_associated_with_the_given_entity(entity: entity)
28
+ end
29
+ end
30
+ end
@@ -9,6 +9,7 @@ module Hyrax
9
9
  super.tap do |solr_doc|
10
10
  solr_doc['hasRelatedMediaFragment_ssim'] = object.representative_id
11
11
  solr_doc['hasRelatedImage_ssim'] = object.thumbnail_id
12
+ solr_doc['transcript_ids_ssim'] = object.transcript_ids
12
13
  # Label is the actual file name. It's not editable by the user.
13
14
  solr_doc['label_tesim'] = object.label
14
15
  solr_doc['label_ssi'] = object.label
@@ -7,7 +7,8 @@ module Hyrax
7
7
  class AdministrativeSetIndexer < Hyrax::Indexers::ResourceIndexer
8
8
  include Hyrax::PermissionIndexer
9
9
  include Hyrax::VisibilityIndexer
10
- include Hyrax::Indexer(:core_metadata)
10
+ include Hyrax::Indexer(:core_metadata) if Hyrax.config.admin_set_include_metadata
11
+ check_if_flexible(Hyrax::AdministrativeSet)
11
12
 
12
13
  def to_solr # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
13
14
  super.tap do |solr_doc|
@@ -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)