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
@@ -7,41 +7,13 @@ module Hyrax
7
7
  # This is a simple yaml config-driven schema loader
8
8
  #
9
9
  # @see config/metadata/basic_metadata.yaml for an example configuration
10
- class SimpleSchemaLoader
11
- ##
12
- # @param [Symbol] schema
13
- #
14
- # @return [Hash<Symbol, Dry::Types::Type>] a map from attribute names to
15
- # types
16
- def attributes_for(schema:)
17
- definitions(schema).each_with_object({}) do |definition, hash|
18
- hash[definition.name] = definition.type.meta(definition.config)
19
- end
20
- end
21
-
22
- ##
23
- # @param [Symbol] schema
24
- #
25
- # @return [Hash{Symbol => Hash{Symbol => Object}}]
26
- def form_definitions_for(schema:)
27
- definitions(schema).each_with_object({}) do |definition, hash|
28
- next if definition.form_options.empty?
29
-
30
- hash[definition.name] = definition.form_options
31
- end
32
- end
33
-
34
- ##
35
- # @param [Symbol] schema
36
- #
37
- # @return [{Symbol => Symbol}] a map from index keys to attribute names
38
- def index_rules_for(schema:)
39
- definitions(schema).each_with_object({}) do |definition, hash|
40
- definition.index_keys.each do |key|
41
- hash[key] = definition.name
42
- end
10
+ class SimpleSchemaLoader < Hyrax::SchemaLoader
11
+ def view_definitions_for(schema:, version: 1, contexts: nil) # rubocop:disable Lint/UnusedMethodArgument
12
+ schema.each_with_object({}) do |property, metadata|
13
+ view_options = property.meta['view']
14
+ metadata[property.name.to_s] = view_options.with_indifferent_access unless view_options.nil?
43
15
  end
44
- end
16
+ end # rubocop:enable Lint/UnusedMethodArgument
45
17
 
46
18
  def permissive_schema_for_valkrie_adapter
47
19
  metadata_files.each_with_object({}) do |schema_name, ret_hsh|
@@ -49,95 +21,12 @@ module Hyrax
49
21
  end
50
22
  end
51
23
 
52
- ##
53
- # @api private
54
- class AttributeDefinition
55
- ##
56
- # @!attr_reader :config
57
- # @return [Hash<String, Object>]
58
- # @!attr_reader :name
59
- # @return [#to_sym]
60
- attr_reader :config, :name
61
-
62
- ##
63
- # @param [#to_sym] name
64
- # @param [Hash<String, Object>] config
65
- def initialize(name, config)
66
- @config = config
67
- @name = name.to_sym
68
- end
69
-
70
- ##
71
- # @return [Hash{Symbol => Object}]
72
- def form_options
73
- config.fetch('form', {}).symbolize_keys
74
- end
75
-
76
- ##
77
- # @return [Enumerable<Symbol>]
78
- def index_keys
79
- config.fetch('index_keys', []).map(&:to_sym)
80
- end
81
-
82
- ##
83
- # @return [Dry::Types::Type]
84
- def type
85
- collection_type = if config['multiple']
86
- Valkyrie::Types::Array.constructor { |v| Array(v).select(&:present?) }
87
- else
88
- Identity
89
- end
90
- collection_type.of(type_for(config['type']))
91
- end
92
-
93
- ##
94
- # @api private
95
- #
96
- # This class acts as a Valkyrie/Dry::Types collection with typed members,
97
- # but instead of wrapping the given type with itself as the collection type
98
- # (as in `Valkyrie::Types::Array.of(MyType)`), it returns the given type.
99
- #
100
- # @example
101
- # Identity.of(Valkyrie::Types::String) # => Valkyrie::Types::String
102
- #
103
- class Identity
104
- ##
105
- # @param [Dry::Types::Type]
106
- # @return [Dry::Types::Type] the type passed in
107
- def self.of(type)
108
- type
109
- end
110
- end
111
-
112
- private
113
-
114
- ##
115
- # Maps a configuration string value to a `Valkyrie::Type`.
116
- #
117
- # @param [String]
118
- # @return [Dry::Types::Type]
119
- def type_for(type)
120
- case type
121
- when 'id'
122
- Valkyrie::Types::ID
123
- when 'uri'
124
- Valkyrie::Types::URI
125
- when 'date_time'
126
- Valkyrie::Types::DateTime
127
- else
128
- "Valkyrie::Types::#{type.capitalize}".constantize
129
- end
130
- end
131
- end
132
-
133
- class UndefinedSchemaError < ArgumentError; end
134
-
135
24
  private
136
25
 
137
26
  ##
138
27
  # @param [#to_s] schema_name
139
28
  # @return [Enumerable<AttributeDefinition]
140
- def definitions(schema_name)
29
+ def definitions(schema_name, _version, _contexts = nil)
141
30
  schema_config(schema_name)['attributes'].map do |name, config|
142
31
  AttributeDefinition.new(name, config)
143
32
  end
@@ -147,6 +36,8 @@ module Hyrax
147
36
  # @param [#to_s] schema_name
148
37
  # @return [Hash]
149
38
  def schema_config(schema_name)
39
+ raise(UndefinedSchemaError, "No schema defined: #{schema_name}") if disabled_schemas.include?(schema_name.to_s)
40
+
150
41
  schema_config_path = config_paths(schema_name).find { |path| File.exist? path }
151
42
  raise(UndefinedSchemaError, "No schema defined: #{schema_name}") unless schema_config_path
152
43
 
@@ -157,14 +48,24 @@ module Hyrax
157
48
  config_search_paths.collect { |root_path| root_path.to_s + "/config/metadata/#{schema_name}.yaml" }
158
49
  end
159
50
 
160
- def config_search_paths
161
- Hyrax.config.simple_schema_loader_config_search_paths
162
- end
163
-
164
51
  def metadata_files
165
52
  file_name_arr = []
166
53
  config_search_paths.each { |root_path| file_name_arr += Dir.entries(root_path.to_s + "/config/metadata/") }
167
- file_name_arr.reject { |fn| !fn.include?('.yaml') }.uniq.map { |y| y.gsub('.yaml', '') }
54
+ file_name_arr
55
+ .reject { |fn| !fn.include?('.yaml') }
56
+ .uniq
57
+ .map { |y| y.gsub('.yaml', '') }
58
+ .reject { |schema_name| disabled_schemas.include?(schema_name) }
59
+ end
60
+
61
+ # Names of schemas in `config/metadata/` that the host app has not
62
+ # opted in to. {#metadata_files} skips them and {#schema_config}
63
+ # raises `UndefinedSchemaError` for them, so they behave as if the
64
+ # YAML did not exist.
65
+ def disabled_schemas
66
+ disabled = []
67
+ disabled << 'redirects' unless Hyrax.config.redirects_enabled?
68
+ disabled
168
69
  end
169
70
 
170
71
  def predicate_pairs(ret_hsh, schema_name)
@@ -179,10 +80,10 @@ module Hyrax
179
80
  end
180
81
 
181
82
  def multiple_predicate_message(name, existing, incoming)
182
- message = "The attribute of #{name} has been assigned a predicate multiple times " \
183
- "within the metadata YAMLs. Please be aware that once the attribute's " \
184
- "predicate value is first assigned, any other value will be ignored. " \
185
- "The existing value is #{existing} preventing the use of #{incoming}"
83
+ message = "The attribute of #{name} has been assigned a predicate multiple times " \
84
+ "within the metadata YAMLs. Please be aware that once the attribute's " \
85
+ "predicate value is first assigned, any other value will be ignored. " \
86
+ "The existing value is #{existing} preventing the use of #{incoming}"
186
87
  Hyrax.logger.warn(message)
187
88
  end
188
89
  end
@@ -6,7 +6,7 @@ module Hyrax
6
6
  #
7
7
  # This class replaces `ActiveFedora::SolrService`, which is deprecated for
8
8
  # internal use.
9
- class SolrService
9
+ class SolrService # rubocop:disable Metrics/ClassLength
10
10
  COMMIT_PARAMS = { softCommit: true }.freeze
11
11
 
12
12
  ##
@@ -39,7 +39,7 @@ module Hyrax
39
39
 
40
40
  def instance
41
41
  # Deprecation warning for calling from outside of the Hyrax::SolrService class
42
- Deprecation.warn(self, rsolr_call_warning) unless caller[1].include?("#{self.class.name.underscore}.rb")
42
+ Deprecation.warn(rsolr_call_warning) unless caller[1].include?("#{self.class.name.underscore}.rb")
43
43
 
44
44
  @old_service.instance
45
45
  end
@@ -125,6 +125,43 @@ module Hyrax
125
125
  end
126
126
  end
127
127
 
128
+ # Pages through a caller-supplied Solr search, returning matching
129
+ # documents as a single Array. The block is yielded once with (0, 0) as
130
+ # a count probe, then once per page with (rows, start) where rows is
131
+ # bounded by Hyrax.config.solr_rows_per_request. Results are truncated
132
+ # to Hyrax.config.solr_max_results; when numFound exceeds the cap, a
133
+ # warning is logged and only the first solr_max_results docs are
134
+ # returned. The block must return a response object responding to
135
+ # +response['numFound']+ and +documents+.
136
+ #
137
+ # @return [Array] matching documents, truncated at solr_max_results
138
+ def self.fetch_all
139
+ rows_per_request = Hyrax.config.solr_rows_per_request
140
+ target = fetch_all_target(yield(0, 0))
141
+ return [] if target.zero?
142
+
143
+ documents = []
144
+ (0...target).step(rows_per_request) do |start|
145
+ rows = [rows_per_request, target - start].min
146
+ documents.concat(yield(rows, start).documents)
147
+ end
148
+ documents
149
+ end
150
+
151
+ # @api private
152
+ # Returns the number of documents to fetch, capped at
153
+ # Hyrax.config.solr_max_results. Logs a warning when truncating.
154
+ def self.fetch_all_target(count_response)
155
+ total = count_response.response['numFound'].to_i
156
+ max = Hyrax.config.solr_max_results
157
+ return total if total <= max
158
+
159
+ Hyrax.logger.warn("Hyrax::SolrService.fetch_all truncated: numFound=#{total} exceeds " \
160
+ "Hyrax.config.solr_max_results=#{max}. Returning the first #{max} documents.")
161
+ max
162
+ end
163
+ private_class_method :fetch_all_target
164
+
128
165
  # Wraps rsolr :delete_by_query
129
166
  def delete_by_query(query, **args)
130
167
  connection.delete_by_query(query, params: args)
@@ -6,10 +6,12 @@ module Hyrax
6
6
  class TolerantSelectService < QaSelectService
7
7
  ##
8
8
  # @return [Boolean] indicates whether the term is active;
9
- # false if the term is inactive or does not exist; defaults to true when
10
- # no key is given
9
+ # false if the term is inactive or is not present in the authority;
10
+ # defaults to true when the term is present but no `active:` key is given.
11
11
  def active?(id)
12
- authority.find(id)&.fetch('active', true)
12
+ result = authority.find(id)
13
+ return false if result.blank?
14
+ result.fetch('active', true)
13
15
  end
14
16
 
15
17
  ##
@@ -38,7 +38,7 @@ class Hyrax::ValkyrieUpload
38
38
  @file_set_file_service = file_set_file_service
39
39
  end
40
40
 
41
- def upload(filename:, file_set:, io:, use: Hyrax::FileMetadata::Use::ORIGINAL_FILE, user: nil, mime_type: nil, skip_derivatives: false) # rubocop:disable Metrics/AbcSize
41
+ def upload(filename:, file_set:, io:, use: Hyrax::FileMetadata::Use::ORIGINAL_FILE, user: nil, mime_type: nil, skip_derivatives: false) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
42
42
  return version_upload(file_set: file_set, io: io, user: user) if use == Hyrax::FileMetadata::Use::ORIGINAL_FILE && file_set.original_file_id && storage_adapter.supports?(:versions)
43
43
  streamfile = storage_adapter.upload(file: io, original_filename: filename, resource: file_set)
44
44
  file_metadata = Hyrax::FileMetadata(streamfile)
@@ -50,7 +50,7 @@ class Hyrax::ValkyrieUpload
50
50
 
51
51
  if use == Hyrax::FileMetadata::Use::ORIGINAL_FILE
52
52
  # Set file set label.
53
- reset_title = file_set.title.first == file_set.label
53
+ reset_title = (file_set.title.first == file_set.label || (file_set.title.blank? && file_set.label.blank?))
54
54
  # set title to label if that's how it was before this characterization
55
55
  file_set.title = file_metadata.original_filename if reset_title
56
56
  # always set the label to the original_name
@@ -13,7 +13,10 @@ module Hyrax
13
13
  when ActiveFedora::Base # ActiveFedora
14
14
  FileSetVisibilityPropagator.new(source: source)
15
15
  when Hyrax::Resource # Valkyrie
16
- ResourceVisibilityPropagator.new(source: source)
16
+ # Due to performance issues for a Hyrax::Resource in Fedora 6,
17
+ # use a job that copies both permissions and visibility instead
18
+ # of reloading and iterating again.
19
+ ResourcePermissionsVisibilityPropagator.new(source: source)
17
20
  else
18
21
  NullVisibilityPropagator.new(source: source)
19
22
  end
@@ -68,7 +68,9 @@ module Hyrax
68
68
  # (for job retries). this is for legacy/AttachFilesToWorkJob
69
69
  # compatibility, but could stand for a robust reimplementation.
70
70
  #
71
- # @param [Enumberable<Hyrax::UploadedFile>] files files to add
71
+ # @param [Enumerable<Hyrax::UploadedFile>] files files to add
72
+ #
73
+ # @param [Enumerable<Hash>] file_set_params additional parameters for each file_set
72
74
  #
73
75
  # @return [WorkFileSetManager] self
74
76
  # @raise [ArgumentError] if any of the uploaded files are not an
@@ -76,21 +78,24 @@ module Hyrax
76
78
  def add(files:, file_set_params: [])
77
79
  validate_files(files) &&
78
80
  @files = Array.wrap(files).reject { |f| f.file_set_uri.present? }
79
- @file_set_params = file_set_params
81
+ @file_set_params = file_set_params || []
80
82
  self
81
83
  end
82
84
 
83
85
  ##
84
86
  # @api public
85
87
  #
86
- # Create filesets for each added file
88
+ # Create filesets for each added file, and add some additional metadata passed in file_set_params
89
+ # Additional metadata will only be set if it is not overriden by the `file_set_args` hash, and if it is a valid part of the schema
87
90
  #
88
91
  # @return [Boolean] true if all requested files were attached
89
92
  def attach
90
93
  return true if Array.wrap(files).empty? # short circuit to avoid aquiring a lock we won't use
91
94
 
92
95
  acquire_lock_for(work.id) do
93
- event_payloads = files.each_with_object([]) { |file, arry| arry << make_file_set_and_ingest(file) }
96
+ event_payloads = files.each_with_object([]).with_index do |(file, arry), index|
97
+ arry << make_file_set_and_ingest(file, @file_set_params[index] || {})
98
+ end
94
99
  @persister.save(resource: work)
95
100
  Hyrax.publisher.publish('object.metadata.updated', object: work, user: files.first.user)
96
101
  event_payloads.each do |payload|
@@ -104,8 +109,8 @@ module Hyrax
104
109
 
105
110
  ##
106
111
  # @api private
107
- def make_file_set_and_ingest(file)
108
- file_set = @persister.save(resource: Hyrax::FileSet.new(file_set_args(file)))
112
+ def make_file_set_and_ingest(file, file_set_params = {})
113
+ file_set = @persister.save(resource: Hyrax.config.valkyrie_file_set_class.new(file_set_args(file, file_set_params)))
109
114
  Hyrax.publisher.publish('object.deposited', object: file_set, user: file.user)
110
115
  file.add_file_set!(file_set)
111
116
 
@@ -133,14 +138,17 @@ module Hyrax
133
138
  ##
134
139
  # @api private
135
140
  #
141
+ # @note the second hash overrides values in the first hash
142
+ #
143
+ #
136
144
  # @return [Hash{Symbol => Object}]
137
- def file_set_args(file)
145
+ def file_set_args(file, file_set_params = {})
138
146
  { depositor: file.user.user_key,
139
- creator: file.user.user_key,
147
+ creator: Array.wrap(file.user.user_key),
140
148
  date_uploaded: file.created_at,
141
149
  date_modified: Hyrax::TimeService.time_in_utc,
142
150
  label: file.uploader.filename,
143
- title: file.uploader.filename }
151
+ title: Array.wrap(file.uploader.filename) }.merge(file_set_params)
144
152
  end
145
153
 
146
154
  ##
@@ -50,9 +50,10 @@ module Hyrax
50
50
  private
51
51
 
52
52
  def create_workflow_entity!
53
- Sipity::Entity.create!(proxy_for_global_id: Hyrax::GlobalID(work).to_s,
54
- workflow: workflow_for(work),
55
- workflow_state: nil)
53
+ entity = Sipity::Entity.find_by(proxy_for_global_id: Hyrax::GlobalID(work).to_s)
54
+ entity || Sipity::Entity.create!(proxy_for_global_id: Hyrax::GlobalID(work).to_s,
55
+ workflow: workflow_for(work),
56
+ workflow_state: nil)
56
57
  end
57
58
 
58
59
  def assign_specific_roles_to(entity:)
@@ -63,7 +64,7 @@ module Hyrax
63
64
  end
64
65
 
65
66
  def run_workflow_action!(action:)
66
- subject = WorkflowActionInfo.new(work, user)
67
+ subject = Hyrax::WorkflowActionInfo.new(work, user)
67
68
  Workflow::WorkflowActionService.run(subject: subject,
68
69
  action: action)
69
70
  end
@@ -8,7 +8,7 @@ class MigrateResourceService
8
8
  end
9
9
 
10
10
  def model
11
- @model || Wings::ModelRegistry.lookup(resource.class).to_s
11
+ @model ||= Wings::ModelRegistry.lookup(resource.class).to_s
12
12
  end
13
13
 
14
14
  def call
@@ -25,7 +25,13 @@ class MigrateResourceService
25
25
  end
26
26
 
27
27
  def resource_form
28
- @resource_form ||= Hyrax::Forms::ResourceForm.for(resource: resource)
28
+ # needs to validate the form to prevent potential frozen errors in custom transaction steps
29
+ @resource_form ||= begin
30
+ form_params = resource.attributes.to_h.with_indifferent_access
31
+ form = Hyrax::Forms::ResourceForm.for(resource: resource)
32
+ form.validate(form_params)
33
+ form
34
+ end
29
35
  end
30
36
 
31
37
  def model_events(model)
@@ -4,11 +4,11 @@ module Hyrax
4
4
  # Override the directory where uploaded files will be stored.
5
5
  # This is a sensible default for uploaders that are meant to be mounted:
6
6
  def store_dir
7
- (configured_upload_path / model.class.to_s.underscore / mounted_as.to_s / model.id.to_s).to_s
7
+ (configured_upload_path / model.class.name.underscore / mounted_as.to_s / model.id.to_s).to_s
8
8
  end
9
9
 
10
10
  def cache_dir
11
- (configured_cache_path / model.class.to_s.underscore / mounted_as.to_s / model.id.to_s).to_s
11
+ (configured_cache_path / model.class.name.underscore / mounted_as.to_s / model.id.to_s).to_s
12
12
  end
13
13
 
14
14
  private
@@ -20,7 +20,7 @@ module Hyrax
20
20
 
21
21
  logger.info("Destroying collection branding...")
22
22
 
23
- Hyrax::CollectionBrandingInfo.destroy_all
23
+ CollectionBrandingInfo.destroy_all
24
24
  logger.info(" collection branding -- DESTROYED")
25
25
  end
26
26
  end
@@ -14,6 +14,7 @@ module Hyrax
14
14
  end
15
15
 
16
16
  def generate_seed_data
17
+ Hyrax::RequiredDataSeeders::FlexibleProfileSeeder.generate_seeds(logger: logger) if Hyrax.config.flexible?
17
18
  Hyrax::RequiredDataSeeders::CollectionTypeSeeder.generate_seeds(logger: logger)
18
19
  Hyrax::RequiredDataSeeders::CollectionSeeder.generate_seeds(logger: logger)
19
20
  end
@@ -20,7 +20,7 @@ module Hyrax
20
20
  logger.info(" #{as_ct.title} -- FOUND OR CREATED")
21
21
 
22
22
  user_ct = Hyrax::CollectionType.find_or_create_default_collection_type
23
- set_badge_color(user_ct, '#0099cc')
23
+ set_badge_color(user_ct, '#007EA8')
24
24
  logger.info(" #{user_ct.title} -- FOUND OR CREATED")
25
25
  end
26
26
 
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hyrax
4
+ module RequiredDataSeeders
5
+ # This class was created for use in rake tasks and db/seeds.rb. It generates
6
+ # collections that are required for all Hyrax applications.
7
+ #
8
+ # Seeders of required data are non-destructive. If the data already exists,
9
+ # it will not be replaced.
10
+ class FlexibleProfileSeeder
11
+ class << self
12
+ attr_accessor :logger
13
+
14
+ def generate_seeds(logger: Logger.new(STDOUT))
15
+ @logger = logger
16
+
17
+ logger.info("Adding required collections...")
18
+
19
+ flexible_schema = Hyrax::FlexibleSchema.first_or_create do |f|
20
+ f.profile = YAML.safe_load_file(Rails.root.join('config', 'metadata_profiles', 'm3_profile.yaml'))
21
+ end
22
+
23
+ logger.info " #{flexible_schema.title} -- FOUND OR CREATED"
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+ module Hyrax
3
+ ##
4
+ # Validates that controlled vocabulary properties contain only active
5
+ # terms from their corresponding local QA authority.
6
+ #
7
+ # Properties are matched to authorities dynamically via
8
+ # +Qa::Authorities::Local.subauthorities+, using the singularized
9
+ # authority name to match property names on the change set.
10
+ #
11
+ # Only covers local authorities (file-based and table-based).
12
+ # Remote authorities (e.g. Geonames) are out of scope.
13
+ class ControlledVocabularyValidator < ActiveModel::Validator
14
+ def validate(record)
15
+ return unless Flipflop.validate_local_controlled_vocabulary?
16
+
17
+ active_terms_by_property(record).each do |property, terms|
18
+ values = Array.wrap(record.public_send(property)).reject(&:blank?)
19
+ next if values.empty?
20
+
21
+ invalid = values.reject { |v| terms.include?(v) }
22
+ invalid.each do |v|
23
+ record.errors.add(property, "#{property.to_s.humanize} contains unrecognized value: #{v}")
24
+ end
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ ##
31
+ # @example
32
+ # # { "license" => ["http://creativecommons.org/licenses/by/4.0/", ...],
33
+ # # "resource_type" => ["Article", "Book", ...] }
34
+ #
35
+ # @return [Hash{String => Array<String>}]
36
+ def active_terms_by_property(record)
37
+ authorities = Qa::Authorities::Local.subauthorities
38
+
39
+ # { "license" => "licenses", "resource_type" => "resource_types", ... }
40
+ property_to_authority = {}.tap do |hash|
41
+ authorities.each { |name| hash[name.singularize] = name }
42
+ end
43
+
44
+ properties = record.fields.keys.map(&:to_s)
45
+
46
+ {}.tap do |result|
47
+ (properties & property_to_authority.keys).each do |property|
48
+ authority = Qa::Authorities::Local.subauthority_for(property_to_authority[property])
49
+ terms = authority.all
50
+ next if terms.empty?
51
+
52
+ result[property] = terms.filter_map { |term| term[:id] if active?(term) }
53
+ end
54
+ end
55
+ end
56
+
57
+ ##
58
+ # Terms without an +active+ field (e.g. resource_types) are
59
+ # treated as active, matching QA's +FileBasedAuthority#all+ behavior.
60
+ def active?(term)
61
+ term.fetch(:active, true) != false
62
+ end
63
+ end
64
+ end