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
@@ -108,12 +108,10 @@ module Hyrax
108
108
 
109
109
  def query_docs(generic_type: nil, ids: object.member_ids)
110
110
  query = "{!terms f=id}#{ids.join(',')}"
111
- query += "{!term f=generic_type_si}#{generic_type}" if generic_type
112
- # works created via ActiveFedora use the _sim field
113
- query += "{!term f=generic_type_sim}#{generic_type}" if generic_type
111
+ query = "(generic_type_si:#{generic_type} OR generic_type_sim:#{generic_type}) AND #{query}" if generic_type
114
112
 
115
113
  Hyrax::SolrService
116
- .post(q: query, rows: 10_000)
114
+ .post(query, rows: 10_000)
117
115
  .fetch('response')
118
116
  .fetch('docs')
119
117
  end
@@ -3,6 +3,7 @@ module Hyrax
3
3
  class WorkShowPresenter
4
4
  include ModelProxy
5
5
  include PresentsAttributes
6
+ include MissingMethodBehavior
6
7
 
7
8
  ##
8
9
  # @!attribute [w] member_presenter_factory
@@ -24,12 +25,45 @@ module Hyrax
24
25
  @solr_document = Hyrax::SolrDocument::OrderedMembers.decorate(solr_document)
25
26
  @current_ability = current_ability
26
27
  @request = request
28
+ define_dynamic_methods if @solr_document.flexible?
27
29
  end
28
30
 
31
+ def define_dynamic_methods # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength
32
+ Hyrax::FlexibleSchema.default_properties.each do |prop|
33
+ method_name = prop.to_s
34
+ property_details = Hyrax::FlexibleSchema.current_version["properties"][method_name]
35
+ next unless property_details
36
+
37
+ index_keys = property_details["indexing"]
38
+ next unless index_keys
39
+
40
+ multi_value = property_details['multiple'] || (property_details['data_type'] == 'array')
41
+
42
+ next if self.class.method_defined?(method_name) && solr_document.respond_to?(method_name)
43
+ # Define the method on the SolrDocument class
44
+ Hyrax::SolrDocument::OrderedMembers.send(:define_method, method_name) do |*_args|
45
+ index_keys.each do |index_key|
46
+ value = self[index_key]
47
+ return (multi_value ? Array.wrap(value) : value) if value.present?
48
+ end
49
+ multi_value ? [] : ""
50
+ end
51
+
52
+ # Define the method on the Presenter class
53
+ self.class.send(:define_method, method_name) do |*args|
54
+ @solr_document.send(method_name, *args)
55
+ end
56
+ end
57
+ end # rubocop:enable Metrics/MethodLength
58
+
29
59
  # We cannot rely on the method missing to catch this delegation. Because
30
60
  # most all objects implicitly implicitly implement #to_s
31
61
  delegate :to_s, to: :solr_document
32
62
 
63
+ def schema_version
64
+ solr_document[:schema_version_ssi]
65
+ end
66
+
33
67
  def page_title
34
68
  "#{human_readable_type} | #{title.first} | ID: #{id} | #{I18n.t('hyrax.product_name')}"
35
69
  end
@@ -50,11 +84,9 @@ module Hyrax
50
84
 
51
85
  # @return [Boolean] render a IIIF viewer
52
86
  def iiif_viewer?
53
- Hyrax.config.iiif_image_server? &&
54
- representative_id.present? &&
87
+ representative_id.present? &&
55
88
  representative_presenter.present? &&
56
- representative_presenter.image? &&
57
- members_include_viewable_image?
89
+ (av_viewable? || image_viewable? || pdf_viewable?)
58
90
  end
59
91
 
60
92
  alias universal_viewer? iiif_viewer?
@@ -74,7 +106,11 @@ module Hyrax
74
106
  # <h3>My IIIF Viewer!</h3>
75
107
  # <a href=<%= main_app.polymorphic_url([main_app, :manifest, presenter], { locale: nil }) %>>Manifest</a>
76
108
  def iiif_viewer
77
- :universal_viewer
109
+ if representative_presenter.present? && av_viewable?
110
+ Hyrax.config.iiif_av_viewer
111
+ else
112
+ :universal_viewer
113
+ end
78
114
  end
79
115
 
80
116
  # @return FileSetPresenter presenter for the representative FileSets
@@ -246,15 +282,6 @@ module Hyrax
246
282
 
247
283
  private
248
284
 
249
- def method_missing(method_name, *args, &block)
250
- return solr_document.public_send(method_name, *args, &block) if solr_document.respond_to?(method_name)
251
- super
252
- end
253
-
254
- def respond_to_missing?(method_name, include_private = false)
255
- solr_document.respond_to?(method_name, include_private) || super
256
- end
257
-
258
285
  # list of item ids to display is based on ordered_ids
259
286
  def authorized_item_ids(filter_unreadable: Flipflop.hide_private_items?)
260
287
  @member_item_list_ids ||=
@@ -320,5 +347,20 @@ module Hyrax
320
347
  def members_include_viewable_image?
321
348
  file_set_presenters.any? { |presenter| presenter.image? && current_ability.can?(:read, presenter.id) }
322
349
  end
350
+
351
+ def av_viewable?
352
+ return false unless Flipflop.iiif_av?
353
+ representative_presenter.video? || representative_presenter.audio?
354
+ end
355
+
356
+ def image_viewable?
357
+ return false unless Hyrax.config.iiif_image_server?
358
+ representative_presenter.image? && members_include_viewable_image?
359
+ end
360
+
361
+ def pdf_viewable?
362
+ return false unless Flipflop.iiif_pdf?
363
+ representative_presenter.pdf?
364
+ end
323
365
  end
324
366
  end
@@ -27,7 +27,7 @@ module Hyrax
27
27
 
28
28
  # Draw the table row for the attribute
29
29
  def render
30
- return '' if values.blank? && !options[:include_empty]
30
+ return '' if blank_values? && !options[:include_empty]
31
31
 
32
32
  markup = %(<tr><th>#{label}</th>\n<td><ul class='tabular'>)
33
33
 
@@ -47,7 +47,7 @@ module Hyrax
47
47
 
48
48
  # Draw the dl row for the attribute
49
49
  def render_dl_row
50
- return '' if values.blank? && !options[:include_empty]
50
+ return '' if blank_values? && !options[:include_empty]
51
51
 
52
52
  markup = %(<dt>#{label}</dt>\n<dd><ul class='tabular'>)
53
53
 
@@ -107,6 +107,10 @@ module Hyrax
107
107
  def work_type_label_key
108
108
  options[:work_type] ? options[:work_type].underscore : nil
109
109
  end
110
+
111
+ def blank_values?
112
+ Array(values).all?(&:blank?)
113
+ end
110
114
  end
111
115
  end
112
116
  end
@@ -7,18 +7,18 @@ module Hyrax
7
7
  private
8
8
 
9
9
  ##
10
- # Special treatment for license/rights. A URL from the Hyrax gem's config/hyrax.rb is stored in the descMetadata of the
11
- # curation_concern. If that URL is valid in form, then it is used as a link. If it is not valid, it is used as plain text.
10
+ # Special treatment for license/rights. A URL from the Hyrax gem's
11
+ # `config/hyrax.rb` is stored in the descMetadata of the
12
+ # curation_concern. If the stored value is an absolute http/https URI,
13
+ # render it as a link with the authority's label; otherwise render the
14
+ # value as plain text to avoid emitting unsafe href values (e.g.
15
+ # `javascript:`) or broken links for free-text values.
12
16
  def attribute_value_to_html(value)
13
- begin
14
- parsed_uri = URI.parse(value)
15
- rescue URI::InvalidURIError
16
- nil
17
- end
18
- if parsed_uri.nil?
19
- ERB::Util.h(value)
17
+ if Hyrax::AuthorityRenderingHelper.linkable_uri?(value)
18
+ label = Hyrax.config.license_service_class.new.label(value) { value }
19
+ %(<a href="#{ERB::Util.h(value)}" target="_blank" rel="noopener noreferrer">#{ERB::Util.h(label)}</a>)
20
20
  else
21
- %(<a href=#{ERB::Util.h(value)} target="_blank">#{Hyrax.config.license_service_class.new.label(value)}</a>)
21
+ ERB::Util.h(value)
22
22
  end
23
23
  end
24
24
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hyrax
4
+ module Renderers
5
+ # Renders each redirect path as a clickable link. The link text is the full
6
+ # absolute URL (host + path); the href is the path alone, which the browser
7
+ # resolves against the current document's host. Used on show pages via the
8
+ # `redirects` schema's `render_as: redirects_label` view option.
9
+ class RedirectsLabelAttributeRenderer < AttributeRenderer
10
+ private
11
+
12
+ def li_value(value)
13
+ path = value.to_s
14
+ return ERB::Util.h(path) if path.blank?
15
+
16
+ display = base_url.present? ? "#{base_url}#{path}" : path
17
+ link_to(ERB::Util.h(display), path)
18
+ end
19
+
20
+ def base_url
21
+ options[:base_url].to_s.sub(%r{/+\z}, '')
22
+ end
23
+ end
24
+ end
25
+ end
@@ -7,19 +7,18 @@ module Hyrax
7
7
  private
8
8
 
9
9
  ##
10
- # Special treatment for license/rights. A URL from the Hyrax gem's config/hyrax.rb is stored in the descMetadata of the
11
- # curation_concern. If that URL is valid in form, then it is used as a link. If it is not valid, it is used as plain text.
10
+ # Special treatment for license/rights. A URL from the Hyrax gem's
11
+ # `config/hyrax.rb` is stored in the descMetadata of the
12
+ # curation_concern. If the stored value is an absolute http/https URI,
13
+ # render it as a link with the authority's label; otherwise render the
14
+ # value as plain text to avoid emitting unsafe href values (e.g.
15
+ # `javascript:`) or broken links for free-text values.
12
16
  def attribute_value_to_html(value)
13
- begin
14
- parsed_uri = URI.parse(value)
15
- rescue URI::InvalidURIError
16
- nil
17
- end
18
- if parsed_uri.nil?
19
- ERB::Util.h(value)
20
- else
17
+ if Hyrax::AuthorityRenderingHelper.linkable_uri?(value)
21
18
  label = Hyrax.config.rights_statement_service_class.new.label(value) { value }
22
- %(<a href=#{ERB::Util.h(value)} target="_blank">#{label}</a>)
19
+ %(<a href="#{ERB::Util.h(value)}" target="_blank" rel="noopener noreferrer">#{ERB::Util.h(label)}</a>)
20
+ else
21
+ ERB::Util.h(value)
23
22
  end
24
23
  end
25
24
  end
@@ -16,11 +16,7 @@ module Hyrax
16
16
 
17
17
  # Override for Hydra::AccessControlsEnforcement
18
18
  attr_reader :discovery_permissions
19
- self.default_processor_chain += [:with_pagination, :show_only_other_collections_of_the_same_collection_type]
20
-
21
- def with_pagination(solr_parameters)
22
- solr_parameters[:rows] = 1000
23
- end
19
+ self.default_processor_chain += [:show_only_other_collections_of_the_same_collection_type]
24
20
 
25
21
  # Solr can do graph traversal without the need of special indexing with the Graph query parser so
26
22
  # use this to compute both the parents and children of the current collection then exclude them
@@ -41,7 +41,7 @@ module Hyrax
41
41
  # types from appearing in search results
42
42
  # @return [Array<Class>] the list of work types to include in searches
43
43
  def work_types
44
- Hyrax::ModelRegistry.work_classes
44
+ Hyrax::ModelRegistry.work_classes - Hyrax::ModelRegistry.file_set_classes
45
45
  end
46
46
 
47
47
  def work_classes
@@ -35,6 +35,7 @@ module Hyrax
35
35
  @params = params
36
36
  @work_attributes_key = work_attributes_key
37
37
  @work_attributes = @params.fetch(work_attributes_key, {})
38
+ @file_set_params = work_attributes[:file_set]&.map { |fs| fs.permit! } || []
38
39
  end
39
40
 
40
41
  attr_reader :form, :transactions, :user, :parent_id, :work_attributes, :uploaded_files, :params, :work_attributes_key
@@ -42,7 +43,7 @@ module Hyrax
42
43
  ##
43
44
  # @api public
44
45
  # @return [TrueClass] when the object is valid.
45
- # @return [FalseClass] when the object is valid.
46
+ # @return [FalseClass] when the object is not valid.
46
47
  def validate
47
48
  form.validate(work_attributes)
48
49
  end
@@ -63,7 +64,7 @@ module Hyrax
63
64
  def step_args
64
65
  {
65
66
  'work_resource.add_to_parent' => { parent_id: params[:parent_id], user: user },
66
- 'work_resource.add_file_sets' => { uploaded_files: uploaded_files, file_set_params: work_attributes[:file_set] },
67
+ 'work_resource.add_file_sets' => { uploaded_files: uploaded_files, file_set_params: @file_set_params },
67
68
  'change_set.set_user_as_depositor' => { user: user },
68
69
  'work_resource.change_depositor' => { user: ::User.find_by_user_key(form.on_behalf_of) },
69
70
  'work_resource.save_acl' => { permissions_params: form.input_params["permissions"] }
@@ -88,7 +88,7 @@ module Hyrax
88
88
  end
89
89
 
90
90
  def unwrap_metric(metric)
91
- metric.metric_values.first.value.to_i
91
+ metric&.metric_values&.first&.value.to_i
92
92
  end
93
93
  end
94
94
  end
@@ -76,7 +76,11 @@ module Hyrax
76
76
  end
77
77
 
78
78
  def account_info
79
- @account_info ||= JSON.parse(account_json_string)
79
+ @account_info ||= if account_json_string.is_a? Hash
80
+ account_json_string
81
+ else
82
+ JSON.parse(account_json_string)
83
+ end
80
84
  end
81
85
 
82
86
  KEYS.each do |key|
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+ module Hyrax
3
+ # Shared rendering helpers for authority-backed values that may have been
4
+ # stored as either a real URI or as free text (the M3 metadata profile, plus
5
+ # bulk importers such as Bulkrax and Willow Sword, can both produce
6
+ # free-text values that the UI's authority dropdown did not constrain).
7
+ module AuthorityRenderingHelper
8
+ # Schemes considered safe to emit in an `<a href>`. Anything else (notably
9
+ # `javascript:`, `data:`, custom schemes, or non-absolute strings like
10
+ # `"moomin"`) is rendered as plain text so it cannot be activated as a
11
+ # link.
12
+ LINKABLE_URI_SCHEMES = %w[http https].freeze
13
+
14
+ module_function
15
+
16
+ # @param value [String, nil]
17
+ # @return [Boolean] true when the value parses as an absolute URI with an
18
+ # allowed scheme, suitable to use as an anchor's href.
19
+ def linkable_uri?(value)
20
+ return false if value.blank?
21
+
22
+ parsed = URI.parse(value)
23
+ parsed.absolute? && LINKABLE_URI_SCHEMES.include?(parsed.scheme&.downcase)
24
+ rescue URI::InvalidURIError
25
+ false
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+ module Hyrax
3
+ # Shared behavior for authority-backed services. Module-level services
4
+ # (such as {Hyrax::ResourceTypesService}) `extend` this module to gain a
5
+ # tolerant `label` / `active?` / `include_current_value` API plus the
6
+ # declarative macros described below.
7
+ #
8
+ # The tolerant methods are intentionally forgiving of off-authority values:
9
+ # `label` falls back to the id itself, `active?` returns false for ids that
10
+ # aren't present in the authority at all, and `include_current_value`
11
+ # preserves such values in edit forms so they are not silently dropped on
12
+ # save.
13
+ #
14
+ # ## Declarative macros
15
+ #
16
+ # Hosts use the {#authority_name} and {#microdata_namespace} macros to
17
+ # declare the wrapped subauthority and the i18n namespace used for
18
+ # schema.org type lookup. These macros generate the rest of the host's
19
+ # API for free:
20
+ #
21
+ # module Hyrax
22
+ # module DisciplineService
23
+ # extend Hyrax::AuthorityService
24
+ #
25
+ # authority_name 'discipline'
26
+ # microdata_namespace 'type.'
27
+ # end
28
+ # end
29
+ #
30
+ # `authority_name` provides `authority`, `authority=`, `select_options`,
31
+ # and `select_all_options` (the latter is an alias of the former — both
32
+ # names are in use in the wild). `microdata_namespace` provides
33
+ # `microdata_type`.
34
+ #
35
+ # @note This module is intended for use via `extend` on a host module. The
36
+ # macros define singleton methods on the host and are not available via
37
+ # `include`. Hosts that need instance-level tolerant lookup should
38
+ # subclass {Hyrax::QaSelectService} instead.
39
+ module AuthorityService
40
+ # Declares which Qa::Authorities::Local subauthority this host wraps,
41
+ # generating `authority`, `authority=`, `select_options`, and
42
+ # `select_all_options` accessors on the host.
43
+ #
44
+ # @param subauthority_name [String] the YAML subauthority name (e.g.
45
+ # `'discipline'`)
46
+ def authority_name(subauthority_name)
47
+ define_singleton_method(:authority) do
48
+ @authority ||= Qa::Authorities::Local.subauthority_for(subauthority_name)
49
+ end
50
+
51
+ define_singleton_method(:authority=) do |value|
52
+ @authority = value
53
+ end
54
+
55
+ define_singleton_method(:select_all_options) do
56
+ authority.all.map { |element| [element[:label], element[:id]] }
57
+ end
58
+ singleton_class.alias_method(:select_options, :select_all_options)
59
+ end
60
+
61
+ # Declares the Microdata i18n namespace this host uses for schema.org
62
+ # type lookup, generating a `microdata_type(id)` method on the host.
63
+ #
64
+ # @param namespace [String] the Microdata key prefix (e.g. `'type.'`,
65
+ # `'resource_type.'`, `'accessibility_feature_type.'`)
66
+ def microdata_namespace(namespace)
67
+ define_singleton_method(:microdata_type) do |id|
68
+ return Hyrax.config.microdata_default_type if id.nil?
69
+ Microdata.fetch("#{namespace}#{id}", default: Hyrax.config.microdata_default_type)
70
+ end
71
+ end
72
+
73
+ # @param id [String]
74
+ # @return [String] the label for the authority entry, falling back to the
75
+ # id itself when no matching term is found.
76
+ #
77
+ # @yield when no 'term' value is present for the id
78
+ # @yieldreturn [String] an alternate label to return
79
+ def label(id, &block)
80
+ block ||= ->(_key) { id }
81
+ authority.find(id).fetch('term', &block)
82
+ end
83
+
84
+ # @return [Boolean] whether the id is an active entry. Returns false for
85
+ # ids that aren't present in the authority at all, so a caller can treat
86
+ # unknown ids as inactive (and preserve them in edit forms via
87
+ # {#include_current_value}).
88
+ def active?(id)
89
+ result = authority.find(id)
90
+ return false if result.blank?
91
+ result.fetch('active', true)
92
+ end
93
+
94
+ # Preserves an off-authority value as a forced-select option in a Simple
95
+ # Form input so it is not silently dropped on save. Intended for use as a
96
+ # Simple Form `item_helper:` callback or to augment a `collection:` array
97
+ # in a partial.
98
+ def include_current_value(value, _index, render_options, html_options)
99
+ force_select = html_options[:class].is_a?(Array) ? [' force-select'] : ' force-select'
100
+ unless value.blank? || active?(value)
101
+ html_options[:class] += force_select
102
+ render_options += [[label(value), value]]
103
+ end
104
+ [render_options, html_options]
105
+ end
106
+ end
107
+ end
@@ -48,7 +48,7 @@ module Hyrax
48
48
 
49
49
  # Defines a callback for a given hook.
50
50
  def set(hook, warn: true, &block)
51
- Deprecation.warn(self, warning_for_set) if warn
51
+ Deprecation.warn(warning_for_set) if warn
52
52
  raise NoBlockGiven, "a block is required when setting a callback" unless block_given?
53
53
  @callbacks[hook] = proc(&block)
54
54
  end
@@ -60,7 +60,7 @@ module Hyrax
60
60
 
61
61
  # Runs the callback defined for a given hook, with the arguments provided
62
62
  def run(hook, *args, warn: true, **opts)
63
- Deprecation.warn(self, warning_for_run) if warn
63
+ Deprecation.warn(warning_for_run) if warn
64
64
  raise NotEnabled unless enabled?(hook)
65
65
  return nil unless set?(hook)
66
66
  @callbacks[hook].call(*args, **opts)
@@ -63,7 +63,7 @@ module Hyrax
63
63
  def self.apply_depositor_metadata(resource, depositor)
64
64
  depositor_id = depositor.respond_to?(:user_key) ? depositor.user_key : depositor
65
65
  resource.depositor = depositor_id if resource.respond_to? :depositor=
66
- Hyrax::AccessControlList.new(resource: resource).grant(:edit).to(::User.find_by_user_key(depositor_id)).save
66
+ resource.permission_manager.acl.grant(:edit).to(::User.find_by_user_key(depositor_id)).save
67
67
  end
68
68
  private_class_method :apply_depositor_metadata
69
69
  end
@@ -107,13 +107,19 @@ class Hyrax::Characterization::ValkyrieCharacterizationService
107
107
  end
108
108
 
109
109
  # Assign values of the instance properties from the metadata mapping :prop => val
110
+ # @todo push exceptional per-property behavior into the mapping somehow?
110
111
  # @return [Hash]
111
112
  def apply_metadata(terms)
112
- terms.each_pair do |term, value|
113
- property = property_for(term)
114
- next if property.nil?
115
-
116
- Array(value).each { |v| append_property_value(property, v) }
113
+ values_by_property(terms).each do |property, values|
114
+ value = if property == :mime_type
115
+ values.last
116
+ elsif [:height, :width].include?(property)
117
+ # keep only the max height or width
118
+ values.map(&:to_i).max.to_s
119
+ else
120
+ values
121
+ end
122
+ metadata.public_send("#{property}=", value)
117
123
  end
118
124
  end
119
125
 
@@ -127,13 +133,15 @@ class Hyrax::Characterization::ValkyrieCharacterizationService
127
133
  end
128
134
  end
129
135
 
130
- ##
131
- # @todo push exceptional per-property behavior into the mapping somehow?
132
- def append_property_value(property, value)
133
- # We don't want multiple mime_types; this overwrites each time to accept last value
134
- value = Array(metadata.public_send(property)) + [value] unless property == :mime_type
135
- # We don't want multiple heights / widths, pick the max
136
- value = value.map(&:to_i).max.to_s if property == :height || property == :width
137
- metadata.public_send("#{property}=", value)
136
+ # Map each term to the corresponding property
137
+ # (multiple terms can map to the same property),
138
+ # and gather all values for each property
139
+ # @return [Hash]
140
+ def values_by_property(terms)
141
+ terms.each_with_object({}) do |(term, value), property_values|
142
+ next unless (property = property_for(term))
143
+
144
+ (property_values[property] ||= []).concat(Array(value))
145
+ end
138
146
  end
139
147
  end
@@ -16,7 +16,7 @@ module Hyrax
16
16
  def self.available_child_collections(parent:, scope:, limit_to_id: nil)
17
17
  return [] unless nestable?(collection: parent)
18
18
  return [] unless scope.can?(:deposit, parent)
19
- query_solr(collection: parent, access: :read, scope: scope, limit_to_id: limit_to_id, nest_direction: :as_child).documents
19
+ query_solr(collection: parent, access: :read, scope: scope, limit_to_id: limit_to_id, nest_direction: :as_child)
20
20
  end
21
21
 
22
22
  ##
@@ -34,7 +34,7 @@ module Hyrax
34
34
  def self.available_parent_collections(child:, scope:, limit_to_id: nil)
35
35
  return [] unless nestable?(collection: child)
36
36
  return [] unless scope.can?(:read, child)
37
- query_solr(collection: child, access: :deposit, scope: scope, limit_to_id: limit_to_id, nest_direction: :as_parent).documents
37
+ query_solr(collection: child, access: :deposit, scope: scope, limit_to_id: limit_to_id, nest_direction: :as_parent)
38
38
  end
39
39
 
40
40
  ##
@@ -65,6 +65,7 @@ module Hyrax
65
65
  # id is in the response. Useful for validation.
66
66
  # @param nest_direction [Symbol] :as_child or :as_parent
67
67
  def self.query_solr(collection:, access:, scope:, limit_to_id:, nest_direction:)
68
+ scope.blacklight_config.http_method = :post
68
69
  query_builder = Hyrax::Dashboard::NestedCollectionsSearchBuilder.new(
69
70
  access: access,
70
71
  collection: collection,
@@ -73,7 +74,12 @@ module Hyrax
73
74
  )
74
75
 
75
76
  query_builder.where(id: limit_to_id.to_s) if limit_to_id
76
- scope.blacklight_config.repository.search(query_builder.query)
77
+
78
+ Hyrax::SolrService.fetch_all do |rows, start|
79
+ scope.blacklight_config.repository.search(
80
+ query_builder.query.merge(rows: rows, start: start, fl: 'id,title_tesim,has_model_ssim')
81
+ )
82
+ end
77
83
  end
78
84
  private_class_method :query_solr
79
85
 
@@ -25,5 +25,22 @@ module Hyrax
25
25
 
26
26
  response.documents
27
27
  end
28
+
29
+ # Like {#search_results}, but pages through every matching collection
30
+ # (up to Hyrax.config.solr_max_results). Use this only for surfaces that
31
+ # need the full set, e.g. the "Add to Collection" dropdown where a user
32
+ # must see every collection they can deposit into.
33
+ #
34
+ # @param [Symbol] access :read or :edit
35
+ # @return [Array<SolrDocument>]
36
+ def all_search_results(access = nil)
37
+ builder = search_builder.with(user_params)
38
+ builder.with_access(access) if access
39
+ yield builder if block_given?
40
+
41
+ Hyrax::SolrService.fetch_all do |rows, start|
42
+ blacklight_config.repository.search(builder.query.merge(rows: rows, start: start))
43
+ end
44
+ end
28
45
  end
29
46
  end