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.
- checksums.yaml +4 -4
- data/.dassie/.env +5 -1
- data/.dassie/Gemfile +5 -3
- data/.dassie/app/assets/images/bulkrax/removed.png +0 -0
- data/.dassie/app/assets/javascripts/application.js +2 -0
- data/.dassie/app/assets/stylesheets/application.css +1 -0
- data/.dassie/app/controllers/catalog_controller.rb +1 -0
- data/.dassie/app/forms/admin_set_resource_form.rb +6 -0
- data/.dassie/app/forms/collection_resource_form.rb +5 -2
- data/.dassie/app/forms/generic_work_resource_form.rb +5 -2
- data/.dassie/app/forms/monograph_form.rb +5 -3
- data/.dassie/app/indexers/admin_set_resource_indexer.rb +5 -0
- data/.dassie/app/indexers/collection_resource_indexer.rb +3 -3
- data/.dassie/app/indexers/generic_work_resource_indexer.rb +6 -3
- data/.dassie/app/indexers/monograph_indexer.rb +6 -2
- data/.dassie/app/models/ability.rb +8 -0
- data/.dassie/app/models/collection_resource.rb +4 -2
- data/.dassie/app/models/concerns/bulkrax/has_local_processing.rb +8 -0
- data/.dassie/app/models/generic_work_resource.rb +5 -2
- data/.dassie/app/models/monograph.rb +5 -2
- data/.dassie/app/views/blacklight_dynamic_sitemap/sitemap/show.xml.builder +22 -0
- data/.dassie/bin/importer +142 -0
- data/.dassie/bin/web +4 -0
- data/.dassie/config/application.rb +1 -1
- data/.dassie/config/browse_everything_providers.yml +1 -1
- data/.dassie/config/bulkrax_api.yml +86 -0
- data/.dassie/config/initializers/bulkrax.rb +92 -0
- data/.dassie/config/initializers/clamav.rb +2 -0
- data/.dassie/config/initializers/devise.rb +1 -0
- data/.dassie/config/initializers/hyrax.rb +7 -1
- data/.dassie/config/initializers/riiif.rb +4 -80
- data/.dassie/config/initializers/wings.rb +1 -1
- data/.dassie/config/metadata_profiles/m3_profile.yaml +929 -0
- data/.dassie/config/puma.rb +4 -2
- data/.dassie/config/routes.rb +7 -0
- data/.dassie/config/sidekiq.yml +17 -0
- data/.dassie/config/uv/uv.html +63 -81
- data/.dassie/db/migrate/20240606205215_create_hyrax_flexible_schemas.rb +9 -0
- data/.dassie/db/migrate/20240606205216_add_contexts_to_hyrax_flexible_schemas.rb +5 -0
- data/.dassie/db/migrate/20250826142438_create_bulkrax_importers.bulkrax.rb +19 -0
- data/.dassie/db/migrate/20250826142439_create_bulkrax_importer_runs.bulkrax.rb +17 -0
- data/.dassie/db/migrate/20250826142440_create_bulkrax_entries.bulkrax.rb +17 -0
- data/.dassie/db/migrate/20250826142441_add_status_to_entry.bulkrax.rb +10 -0
- data/.dassie/db/migrate/20250826142442_add_collections_to_importer_runs.bulkrax.rb +7 -0
- data/.dassie/db/migrate/20250826142443_change_collection_ids_on_entries.bulkrax.rb +6 -0
- data/.dassie/db/migrate/20250826142444_create_bulkrax_exporters.bulkrax.rb +20 -0
- data/.dassie/db/migrate/20250826142445_create_bulkrax_exporter_runs.bulkrax.rb +15 -0
- data/.dassie/db/migrate/20250826142446_change_importer_and_exporter_to_polymorphic.bulkrax.rb +19 -0
- data/.dassie/db/migrate/20250826142447_add_total_collection_records_to_importer_runs.bulkrax.rb +6 -0
- data/.dassie/db/migrate/20250826142448_add_children_to_importer_runs.bulkrax.rb +7 -0
- data/.dassie/db/migrate/20250826142449_change_total_records_to_total_work_entries.bulkrax.rb +7 -0
- data/.dassie/db/migrate/20250826142450_change_entry_last_error.bulkrax.rb +20 -0
- data/.dassie/db/migrate/20250826142451_add_validate_only_to_bulkrax_importers.bulkrax.rb +6 -0
- data/.dassie/db/migrate/20250826142452_add_status_to_importers.bulkrax.rb +10 -0
- data/.dassie/db/migrate/20250826142453_remove_foreign_key_from_bulkrax_entries.bulkrax.rb +6 -0
- data/.dassie/db/migrate/20250826142454_add_status_to_exporters.bulkrax.rb +8 -0
- data/.dassie/db/migrate/20250826142455_add_invalid_record_to_importer_run.bulkrax.rb +6 -0
- data/.dassie/db/migrate/20250826142456_create_bulkrax_statuses.bulkrax.rb +19 -0
- data/.dassie/db/migrate/20250826142457_move_to_statuses.bulkrax.rb +31 -0
- data/.dassie/db/migrate/20250826142458_add_date_filter_and_status_to_bulkrax_exporters.bulkrax.rb +8 -0
- data/.dassie/db/migrate/20250826142459_add_workflow_status_to_bulkrax_exporter.bulkrax.rb +6 -0
- data/.dassie/db/migrate/20250826142460_remove_unused_last_error.bulkrax.rb +8 -0
- data/.dassie/db/migrate/20250826142461_increase_text_sizes.bulkrax.rb +13 -0
- data/.dassie/db/migrate/20250826142462_change_bulkrax_statuses_error_message_column_type_to_text.bulkrax.rb +6 -0
- data/.dassie/db/migrate/20250826142463_rename_children_counters_to_relationships.bulkrax.rb +7 -0
- data/.dassie/db/migrate/20250826142464_add_file_set_counters_to_importer_runs.bulkrax.rb +8 -0
- data/.dassie/db/migrate/20250826142465_add_import_attempts_to_entries.bulkrax.rb +6 -0
- data/.dassie/db/migrate/20250826142466_add_work_counters_to_importer_runs.bulkrax.rb +7 -0
- data/.dassie/db/migrate/20250826142467_create_bulkrax_pending_relationships.bulkrax.rb +14 -0
- data/.dassie/db/migrate/20250826142468_add_order_to_bulkrax_pending_relationships.bulkrax.rb +6 -0
- data/.dassie/db/migrate/20250826142469_add_include_thumbnails_to_bulkrax_exporters.bulkrax.rb +6 -0
- data/.dassie/db/migrate/20250826142470_add_generated_metadata_to_bulkrax_exporters.bulkrax.rb +6 -0
- data/.dassie/db/migrate/20250826142471_rename_bulkrax_importer_run_to_importer_run.bulkrax.rb +18 -0
- data/.dassie/db/migrate/20250826142472_add_indices_to_bulkrax.bulkrax.rb +26 -0
- data/.dassie/db/migrate/20250826142473_denormalize_status_message.bulkrax.rb +8 -0
- data/.dassie/db/migrate/20250826142474_update_identifier_index.bulkrax.rb +7 -0
- data/.dassie/db/migrate/20250826142475_add_index_to_metadata_bulkrax_identifier.bulkrax.rb +19 -0
- data/.dassie/db/migrate/20250826142476_add_file_name_to_uploaded_files.bulkrax.rb +6 -0
- data/.dassie/db/migrate/20250826142477_add_error_tracking_to_pending_relationships.bulkrax.rb +6 -0
- data/.dassie/db/migrate/20250826142478_add_last_imported_at_to_bulkrax_importers.bulkrax.rb +6 -0
- data/.dassie/db/migrate/20250826142479_add_next_import_at_to_bulkrax_importers.bulkrax.rb +6 -0
- data/.dassie/db/migrate/20250826142480_entry_error_denormalization.bulkrax.rb +8 -0
- data/.dassie/db/migrate/20250826142481_faster_first_entry.bulkrax.rb +8 -0
- data/.dassie/db/migrate/20260430000001_create_hyrax_redirect_paths.hyrax.rb +13 -0
- data/.dassie/db/migrate/20260521003627_add_additional_redirect_info.hyrax.rb +32 -0
- data/.dassie/db/schema.rb +263 -109
- data/.dassie/package.json +1 -1
- data/.dassie/rspec_split_configuration.json +835 -0
- data/.dassie/solr/conf/solrconfig.xml +21 -5
- data/.github/{ISSUE_TEMPLATE.md → ISSUE_TEMPLATE/issue_template.md} +5 -0
- data/.github/workflows/lint-build-test.yml +6 -2
- data/.github/workflows/release-charts.yml +48 -0
- data/.gitignore +6 -0
- data/.koppie/.env +5 -1
- data/.koppie/Gemfile +3 -1
- data/.koppie/app/assets/images/bulkrax/removed.png +0 -0
- data/.koppie/app/assets/javascripts/application.js +2 -0
- data/.koppie/app/assets/stylesheets/application.css +1 -0
- data/.koppie/app/controllers/catalog_controller.rb +1 -1
- data/.koppie/app/forms/collection_resource_form.rb +5 -2
- data/.koppie/app/forms/file_set_form.rb +5 -0
- data/.koppie/app/forms/generic_work_form.rb +5 -3
- data/.koppie/app/forms/monograph_form.rb +5 -3
- data/.koppie/app/indexers/collection_resource_indexer.rb +5 -2
- data/.koppie/app/indexers/file_set_indexer.rb +7 -0
- data/.koppie/app/indexers/generic_work_indexer.rb +6 -3
- data/.koppie/app/indexers/monograph_indexer.rb +6 -2
- data/.koppie/app/models/ability.rb +8 -0
- data/.koppie/app/models/collection_resource.rb +4 -2
- data/.koppie/app/models/concerns/bulkrax/has_local_processing.rb +8 -0
- data/.koppie/app/models/generic_work.rb +5 -2
- data/.koppie/app/models/monograph.rb +5 -2
- data/.koppie/app/views/blacklight_dynamic_sitemap/sitemap/show.xml.builder +22 -0
- data/.koppie/bin/importer +142 -0
- data/.koppie/bin/web +4 -0
- data/.koppie/config/browse_everything_providers.yml +2 -0
- data/.koppie/config/bulkrax_api.yml +86 -0
- data/.koppie/config/initializers/bulkrax.rb +92 -0
- data/.koppie/config/initializers/clamav.rb +2 -0
- data/.koppie/config/initializers/devise.rb +1 -1
- data/.koppie/config/initializers/hyrax.rb +11 -3
- data/.koppie/config/initializers/riiif.rb +4 -82
- data/.koppie/config/metadata_profiles/m3_profile.yaml +930 -0
- data/.koppie/config/routes.rb +7 -0
- data/.koppie/config/sidekiq.yml +2 -0
- data/.koppie/config/uv/uv.html +63 -81
- data/.koppie/db/migrate/20240606205215_create_hyrax_flexible_schemas.rb +9 -0
- data/.koppie/db/migrate/20240606205216_add_contexts_to_hyrax_flexible_schemas.rb +5 -0
- data/.koppie/db/migrate/20250826142438_create_bulkrax_importers.bulkrax.rb +19 -0
- data/.koppie/db/migrate/20250826142439_create_bulkrax_importer_runs.bulkrax.rb +17 -0
- data/.koppie/db/migrate/20250826142440_create_bulkrax_entries.bulkrax.rb +17 -0
- data/.koppie/db/migrate/20250826142441_add_status_to_entry.bulkrax.rb +10 -0
- data/.koppie/db/migrate/20250826142442_add_collections_to_importer_runs.bulkrax.rb +7 -0
- data/.koppie/db/migrate/20250826142443_change_collection_ids_on_entries.bulkrax.rb +6 -0
- data/.koppie/db/migrate/20250826142444_create_bulkrax_exporters.bulkrax.rb +20 -0
- data/.koppie/db/migrate/20250826142445_create_bulkrax_exporter_runs.bulkrax.rb +15 -0
- data/.koppie/db/migrate/20250826142446_change_importer_and_exporter_to_polymorphic.bulkrax.rb +19 -0
- data/.koppie/db/migrate/20250826142447_add_total_collection_records_to_importer_runs.bulkrax.rb +6 -0
- data/.koppie/db/migrate/20250826142448_add_children_to_importer_runs.bulkrax.rb +7 -0
- data/.koppie/db/migrate/20250826142449_change_total_records_to_total_work_entries.bulkrax.rb +7 -0
- data/.koppie/db/migrate/20250826142450_change_entry_last_error.bulkrax.rb +20 -0
- data/.koppie/db/migrate/20250826142451_add_validate_only_to_bulkrax_importers.bulkrax.rb +6 -0
- data/.koppie/db/migrate/20250826142452_add_status_to_importers.bulkrax.rb +10 -0
- data/.koppie/db/migrate/20250826142453_remove_foreign_key_from_bulkrax_entries.bulkrax.rb +6 -0
- data/.koppie/db/migrate/20250826142454_add_status_to_exporters.bulkrax.rb +8 -0
- data/.koppie/db/migrate/20250826142455_add_invalid_record_to_importer_run.bulkrax.rb +6 -0
- data/.koppie/db/migrate/20250826142456_create_bulkrax_statuses.bulkrax.rb +19 -0
- data/.koppie/db/migrate/20250826142457_move_to_statuses.bulkrax.rb +31 -0
- data/.koppie/db/migrate/20250826142458_add_date_filter_and_status_to_bulkrax_exporters.bulkrax.rb +8 -0
- data/.koppie/db/migrate/20250826142459_add_workflow_status_to_bulkrax_exporter.bulkrax.rb +6 -0
- data/.koppie/db/migrate/20250826142460_remove_unused_last_error.bulkrax.rb +8 -0
- data/.koppie/db/migrate/20250826142461_increase_text_sizes.bulkrax.rb +13 -0
- data/.koppie/db/migrate/20250826142462_change_bulkrax_statuses_error_message_column_type_to_text.bulkrax.rb +6 -0
- data/.koppie/db/migrate/20250826142463_rename_children_counters_to_relationships.bulkrax.rb +7 -0
- data/.koppie/db/migrate/20250826142464_add_file_set_counters_to_importer_runs.bulkrax.rb +8 -0
- data/.koppie/db/migrate/20250826142465_add_import_attempts_to_entries.bulkrax.rb +6 -0
- data/.koppie/db/migrate/20250826142466_add_work_counters_to_importer_runs.bulkrax.rb +7 -0
- data/.koppie/db/migrate/20250826142467_create_bulkrax_pending_relationships.bulkrax.rb +14 -0
- data/.koppie/db/migrate/20250826142468_add_order_to_bulkrax_pending_relationships.bulkrax.rb +6 -0
- data/.koppie/db/migrate/20250826142469_add_include_thumbnails_to_bulkrax_exporters.bulkrax.rb +6 -0
- data/.koppie/db/migrate/20250826142470_add_generated_metadata_to_bulkrax_exporters.bulkrax.rb +6 -0
- data/.koppie/db/migrate/20250826142471_rename_bulkrax_importer_run_to_importer_run.bulkrax.rb +18 -0
- data/.koppie/db/migrate/20250826142472_add_indices_to_bulkrax.bulkrax.rb +26 -0
- data/.koppie/db/migrate/20250826142473_denormalize_status_message.bulkrax.rb +8 -0
- data/.koppie/db/migrate/20250826142474_update_identifier_index.bulkrax.rb +7 -0
- data/.koppie/db/migrate/20250826142475_add_index_to_metadata_bulkrax_identifier.bulkrax.rb +19 -0
- data/.koppie/db/migrate/20250826142476_add_file_name_to_uploaded_files.bulkrax.rb +6 -0
- data/.koppie/db/migrate/20250826142477_add_error_tracking_to_pending_relationships.bulkrax.rb +6 -0
- data/.koppie/db/migrate/20250826142478_add_last_imported_at_to_bulkrax_importers.bulkrax.rb +6 -0
- data/.koppie/db/migrate/20250826142479_add_next_import_at_to_bulkrax_importers.bulkrax.rb +6 -0
- data/.koppie/db/migrate/20250826142480_entry_error_denormalization.bulkrax.rb +8 -0
- data/.koppie/db/migrate/20250826142481_faster_first_entry.bulkrax.rb +8 -0
- data/.koppie/db/migrate/20260430000001_create_hyrax_redirect_paths.hyrax.rb +13 -0
- data/.koppie/db/migrate/20260521003627_add_additional_redirect_info.hyrax.rb +32 -0
- data/.koppie/db/schema.rb +154 -1
- data/.koppie/package.json +1 -1
- data/.koppie/rspec_split_configuration.json +835 -0
- data/.koppie/solr/conf/solrconfig.xml +0 -5
- data/.koppie/yarn.lock +5587 -752
- data/.rubocop.yml +1 -0
- data/CONTAINERS.md +12 -10
- data/Dockerfile +9 -22
- data/Gemfile +1 -1
- data/Gemfile.allinson +2 -0
- data/README.md +1 -2
- data/app/actors/hyrax/actors/file_actor.rb +2 -0
- data/app/actors/hyrax/actors/file_set_actor.rb +1 -1
- data/app/assets/javascripts/hyrax/app.js.erb +143 -10
- data/app/assets/javascripts/hyrax/collection_select.js +68 -0
- data/app/assets/javascripts/hyrax/copy_permalink_button.js +28 -0
- data/app/assets/javascripts/hyrax/redirects.js +45 -0
- data/app/assets/javascripts/hyrax/relationships/control.es6 +21 -1
- data/app/assets/javascripts/hyrax/select_work_type.es6 +7 -2
- data/app/assets/javascripts/hyrax.js +3 -1
- data/app/assets/stylesheets/hyrax/_file-show.scss +1 -0
- data/app/assets/stylesheets/hyrax/_viewer.scss +8 -0
- data/app/assets/stylesheets/hyrax/dashboard.scss +22 -1
- data/app/assets/stylesheets/hyrax/sidebar.scss +98 -3
- data/app/authorities/qa/authorities/collections.rb +9 -9
- data/app/controllers/concerns/hyrax/analytics_error_handling.rb +97 -0
- data/app/controllers/concerns/hyrax/collections_controller_behavior.rb +3 -1
- data/app/controllers/concerns/hyrax/ensure_migrated_behavior.rb +50 -0
- data/app/controllers/concerns/hyrax/flexible_catalog_behavior.rb +206 -0
- data/app/controllers/concerns/hyrax/flexible_schema_behavior.rb +17 -0
- data/app/controllers/concerns/hyrax/redirect_to_display_url.rb +54 -0
- data/app/controllers/concerns/hyrax/valkyrie_downloads_controller_behavior.rb +1 -0
- data/app/controllers/concerns/hyrax/works_controller_behavior.rb +54 -11
- data/app/controllers/hyrax/admin/admin_sets_controller.rb +21 -13
- data/app/controllers/hyrax/admin/analytics/collection_reports_controller.rb +2 -0
- data/app/controllers/hyrax/admin/analytics/work_reports_controller.rb +5 -4
- data/app/controllers/hyrax/admin/metadata_profiles_controller.rb +66 -0
- data/app/controllers/hyrax/batch_uploads_controller.rb +2 -0
- data/app/controllers/hyrax/dashboard/collections_controller.rb +27 -6
- data/app/controllers/hyrax/dashboard/nest_collections_controller.rb +2 -1
- data/app/controllers/hyrax/dashboard_controller.rb +2 -1
- data/app/controllers/hyrax/file_sets_controller.rb +20 -2
- data/app/controllers/hyrax/homepage_controller.rb +7 -0
- data/app/controllers/hyrax/my/works_controller.rb +2 -21
- data/app/controllers/hyrax/permissions_controller.rb +4 -2
- data/app/controllers/hyrax/redirects_controller.rb +56 -0
- data/app/controllers/hyrax/single_use_links_viewer_controller.rb +2 -1
- data/app/controllers/hyrax/transcripts_controller.rb +31 -0
- data/app/controllers/hyrax/uploads_controller.rb +18 -9
- data/app/forms/concerns/hyrax/based_near_field_behavior.rb +77 -0
- data/app/forms/concerns/hyrax/flexible_form_behavior.rb +37 -0
- data/app/forms/concerns/hyrax/redirects_field_behavior.rb +95 -0
- data/app/forms/concerns/hyrax/transcripts_behavior.rb +40 -0
- data/app/forms/hyrax/forms/admin_set_form.rb +1 -1
- data/app/forms/hyrax/forms/administrative_set_form.rb +3 -0
- data/app/forms/hyrax/forms/batch_edit_form.rb +1 -3
- data/app/forms/hyrax/forms/batch_upload_form.rb +14 -0
- data/app/forms/hyrax/forms/file_set_edit_form.rb +1 -1
- data/app/forms/hyrax/forms/file_set_form.rb +6 -7
- data/app/forms/hyrax/forms/pcdm_collection_form.rb +17 -5
- data/app/forms/hyrax/forms/pcdm_object_form.rb +11 -3
- data/app/forms/hyrax/forms/resource_batch_edit_form.rb +8 -22
- data/app/forms/hyrax/forms/resource_form.rb +110 -10
- data/app/forms/hyrax/forms.rb +1 -0
- data/app/helpers/hyrax/attributes_helper.rb +109 -0
- data/app/helpers/hyrax/blacklight_override.rb +26 -0
- data/app/helpers/hyrax/collections_helper.rb +2 -0
- data/app/helpers/hyrax/file_set_form_helper.rb +24 -0
- data/app/helpers/hyrax/hyrax_helper_behavior.rb +53 -4
- data/app/helpers/hyrax/iiif_helper.rb +11 -1
- data/app/helpers/hyrax/permalink_helper.rb +37 -0
- data/app/helpers/hyrax/redirects_tab_helper.rb +29 -0
- data/app/helpers/hyrax/trophy_helper.rb +1 -1
- data/app/helpers/hyrax/work_form_helper.rb +9 -5
- data/app/helpers/hyrax/works_helper.rb +14 -0
- data/app/indexers/concerns/hyrax/workflow_indexer.rb +30 -0
- data/app/indexers/hyrax/file_set_indexer.rb +1 -0
- data/app/indexers/hyrax/indexers/administrative_set_indexer.rb +2 -1
- data/app/indexers/hyrax/indexers/file_set_indexer.rb +6 -2
- data/app/indexers/hyrax/indexers/pcdm_collection_indexer.rb +11 -1
- data/app/indexers/hyrax/indexers/pcdm_object_indexer.rb +25 -4
- data/app/indexers/hyrax/indexers/redirects_indexer.rb +29 -0
- data/app/indexers/hyrax/indexers/resource_indexer.rb +4 -0
- data/app/indexers/hyrax/indexers.rb +2 -0
- data/app/inputs/controlled_vocabulary_input.rb +7 -1
- data/app/jobs/concerns/hyrax/queued_job_behavior.rb +22 -0
- data/app/jobs/content_deposit_error_event_job.rb +14 -0
- data/app/jobs/create_work_job.rb +2 -0
- data/app/jobs/hyrax/propagate_change_depositor_job.rb +1 -1
- data/app/jobs/hyrax/queued_delete_job.rb +11 -0
- data/app/jobs/hyrax/queued_indexing_job.rb +11 -0
- data/app/jobs/migrate_files_to_valkyrie_job.rb +39 -21
- data/app/jobs/migrate_sipity_entity_job.rb +21 -0
- data/app/models/batch_upload_item.rb +4 -0
- data/app/models/concerns/hyrax/ability/flexible_metadata_ability.rb +10 -0
- data/app/models/concerns/hyrax/ability.rb +7 -3
- data/app/models/concerns/hyrax/collection_behavior.rb +4 -0
- data/app/models/concerns/hyrax/file_set/transcripts.rb +16 -0
- data/app/models/concerns/hyrax/file_set_behavior.rb +9 -0
- data/app/models/concerns/hyrax/flexibility.rb +107 -0
- data/app/models/concerns/hyrax/redirects_normalization.rb +38 -0
- data/app/models/concerns/hyrax/solr_document/characterization.rb +1 -1
- data/app/models/concerns/hyrax/solr_document/metadata.rb +9 -0
- data/app/models/concerns/hyrax/solr_document/ordered_members.rb +4 -0
- data/app/models/concerns/hyrax/solr_document_behavior.rb +28 -3
- data/app/models/concerns/hyrax/suppressible.rb +1 -1
- data/app/models/concerns/hyrax/valkyrie_lazy_migration.rb +1 -1
- data/app/models/concerns/hyrax/with_embargoes_and_leases.rb +30 -0
- data/app/models/concerns/hyrax/work_behavior.rb +8 -0
- data/app/models/hyrax/administrative_set.rb +1 -1
- data/app/models/hyrax/change_set.rb +3 -1
- data/app/models/hyrax/embargo.rb +3 -1
- data/app/models/hyrax/file_metadata.rb +22 -7
- data/app/models/hyrax/file_set.rb +4 -2
- data/app/models/hyrax/flexible_schema.rb +219 -0
- data/app/models/hyrax/lease.rb +3 -1
- data/app/models/hyrax/pcdm_collection.rb +4 -1
- data/app/models/hyrax/redirect.rb +64 -0
- data/app/models/hyrax/redirect_path.rb +14 -0
- data/app/models/hyrax/resource.rb +22 -25
- data/app/models/hyrax/riiif/file.rb +43 -0
- data/app/models/hyrax/riiif/file_resolver.rb +65 -0
- data/app/models/hyrax/uploaded_file.rb +9 -0
- data/app/models/hyrax/virus_scanner.rb +16 -3
- data/app/models/hyrax/work.rb +4 -1
- data/app/models/job_io_wrapper.rb +12 -3
- data/app/models/user_mailbox.rb +3 -1
- data/app/presenters/hyrax/admin_set_presenter.rb +11 -0
- data/app/presenters/hyrax/annotates_content.rb +35 -0
- data/app/presenters/hyrax/collection_presenter.rb +5 -1
- data/app/presenters/hyrax/displays_content.rb +133 -0
- data/app/presenters/hyrax/displays_image.rb +11 -4
- data/app/presenters/hyrax/displays_transcripts.rb +59 -0
- data/app/presenters/hyrax/file_set_presenter.rb +8 -18
- data/app/presenters/hyrax/google_scholar_presenter.rb +39 -0
- data/app/presenters/hyrax/iiif_manifest_presenter.rb +22 -4
- data/app/presenters/hyrax/missing_method_behavior.rb +15 -0
- data/app/presenters/hyrax/pcdm_member_presenter_factory.rb +2 -4
- data/app/presenters/hyrax/work_show_presenter.rb +56 -14
- data/app/renderers/hyrax/renderers/attribute_renderer.rb +6 -2
- data/app/renderers/hyrax/renderers/license_attribute_renderer.rb +10 -10
- data/app/renderers/hyrax/renderers/redirects_label_attribute_renderer.rb +25 -0
- data/app/renderers/hyrax/renderers/rights_statement_attribute_renderer.rb +10 -11
- data/app/search_builders/hyrax/dashboard/nested_collections_search_builder.rb +1 -5
- data/app/search_builders/hyrax/filter_by_type.rb +1 -1
- data/app/services/hyrax/action/create_valkyrie_work.rb +3 -2
- data/app/services/hyrax/analytics/ga4/base.rb +1 -1
- data/app/services/hyrax/analytics/ga4.rb +5 -1
- data/app/services/hyrax/authority_rendering_helper.rb +28 -0
- data/app/services/hyrax/authority_service.rb +107 -0
- data/app/services/hyrax/callbacks.rb +2 -2
- data/app/services/hyrax/change_depositor_service.rb +1 -1
- data/app/services/hyrax/characterization/valkyrie_characterization_service.rb +21 -13
- data/app/services/hyrax/collections/nested_collection_query_service.rb +9 -3
- data/app/services/hyrax/collections_service.rb +17 -0
- data/app/services/hyrax/custom_queries/find_by_property_value.rb +89 -0
- data/app/services/hyrax/custom_queries/find_ids_by_model.rb +31 -6
- data/app/services/hyrax/edit_permissions_service.rb +11 -10
- data/app/services/hyrax/file_set_type_service.rb +12 -4
- data/app/services/hyrax/flexible_schema_validator_service.rb +153 -0
- data/app/services/hyrax/flexible_schema_validators/class_validator.rb +123 -0
- data/app/services/hyrax/flexible_schema_validators/core_metadata_validator.rb +211 -0
- data/app/services/hyrax/flexible_schema_validators/existing_records_validator.rb +83 -0
- data/app/services/hyrax/flexible_schema_validators/redirects_validator.rb +116 -0
- data/app/services/hyrax/flexible_schema_validators/schema_validator.rb +34 -0
- data/app/services/hyrax/flexible_schema_validators/sort_properties_validator.rb +54 -0
- data/app/services/hyrax/license_service.rb +1 -1
- data/app/services/hyrax/listeners/metadata_index_listener.rb +11 -0
- data/app/services/hyrax/m3_profile_editor.rb +32 -0
- data/app/services/hyrax/m3_schema_loader.rb +119 -0
- data/app/services/hyrax/manifest_builder_service.rb +18 -24
- data/app/services/hyrax/permalink_path.rb +25 -0
- data/app/services/hyrax/qa_select_service.rb +9 -5
- data/app/services/hyrax/redirect_path_normalizer.rb +58 -0
- data/app/services/hyrax/redirects_lookup.rb +59 -0
- data/app/services/hyrax/resource_permissions_visibility_propagator.rb +54 -0
- data/app/services/hyrax/resource_types_service.rb +3 -20
- data/app/services/hyrax/rights_statement_service.rb +1 -1
- data/app/services/hyrax/schema_loader.rb +205 -0
- data/app/services/hyrax/search_service.rb +1 -1
- data/app/services/hyrax/simple_schema_loader.rb +28 -127
- data/app/services/hyrax/solr_service.rb +39 -2
- data/app/services/hyrax/tolerant_select_service.rb +5 -3
- data/app/services/hyrax/valkyrie_upload.rb +2 -2
- data/app/services/hyrax/visibility_propagator.rb +4 -1
- data/app/services/hyrax/work_uploads_handler.rb +17 -9
- data/app/services/hyrax/workflow/workflow_factory.rb +5 -4
- data/app/services/migrate_resource_service.rb +8 -2
- data/app/uploaders/hyrax/uploaded_file_uploader.rb +2 -2
- data/app/utils/hyrax/data_destroyers/collection_branding_destroyer.rb +1 -1
- data/app/utils/hyrax/required_data_seeder.rb +1 -0
- data/app/utils/hyrax/required_data_seeders/collection_type_seeder.rb +1 -1
- data/app/utils/hyrax/required_data_seeders/flexible_profile_seeder.rb +28 -0
- data/app/validators/hyrax/controlled_vocabulary_validator.rb +64 -0
- data/app/validators/hyrax/redirect_validator.rb +128 -0
- data/app/views/_user_util_links.html.erb +2 -1
- data/app/views/catalog/_thumbnail_list_default.html.erb +2 -2
- data/app/views/collections/edit_fields/_schema_version.html.erb +1 -0
- data/app/views/hyrax/admin/admin_sets/_form_metadata.html.erb +24 -2
- data/app/views/hyrax/admin/admin_sets/_show_document_list_row.html.erb +1 -1
- data/app/views/hyrax/admin/admin_sets/show.html.erb +1 -1
- data/app/views/hyrax/admin/analytics/_analytics_error.html.erb +42 -0
- data/app/views/hyrax/admin/analytics/collection_reports/_top_collections.html.erb +3 -7
- data/app/views/hyrax/admin/analytics/collection_reports/index.html.erb +11 -9
- data/app/views/hyrax/admin/analytics/work_reports/_top_file_set_downloads.html.erb +3 -6
- data/app/views/hyrax/admin/analytics/work_reports/_top_works.html.erb +2 -3
- data/app/views/hyrax/admin/analytics/work_reports/_work_files.html.erb +1 -6
- data/app/views/hyrax/admin/analytics/work_reports/index.html.erb +60 -57
- data/app/views/hyrax/admin/features/index.html.erb +1 -1
- data/app/views/hyrax/admin/metadata_profiles/_import_modal.html.erb +20 -0
- data/app/views/hyrax/admin/metadata_profiles/index.html.erb +54 -0
- data/app/views/hyrax/base/_attribute_rows.html.erb +4 -21
- data/app/views/hyrax/base/_citations.html.erb +1 -0
- data/app/views/hyrax/base/_currently_shared.html.erb +2 -1
- data/app/views/hyrax/base/_file_manager_thumbnail.html.erb +1 -1
- data/app/views/hyrax/base/_form_member_of_collections.html.erb +6 -6
- data/app/views/hyrax/base/_form_redirects.html.erb +125 -0
- data/app/views/hyrax/base/_form_share.html.erb +7 -2
- data/app/views/hyrax/base/_member.html.erb +1 -1
- data/app/views/hyrax/base/_social_media.html.erb +3 -1
- data/app/views/hyrax/base/iiif_viewers/_universal_viewer.html.erb +1 -1
- data/app/views/hyrax/base/show.html.erb +3 -0
- data/app/views/hyrax/collections/_default_group.html.erb +3 -0
- data/app/views/hyrax/collections/_list_collections.html.erb +3 -0
- data/app/views/hyrax/collections/_list_works.html.erb +1 -1
- data/app/views/hyrax/collections/_show_document_list_row.html.erb +1 -1
- data/app/views/hyrax/collections/show.html.erb +4 -0
- data/app/views/hyrax/dashboard/_sidebar.html.erb +4 -2
- data/app/views/hyrax/dashboard/collections/_button_for_update_collection.html.erb +2 -1
- data/app/views/hyrax/dashboard/collections/_default_group.html.erb +3 -0
- data/app/views/hyrax/dashboard/collections/_form.html.erb +17 -0
- data/app/views/hyrax/dashboard/collections/_form_for_select_collection.html.erb +7 -10
- data/app/views/hyrax/dashboard/collections/_list_collections.html.erb +3 -0
- data/app/views/hyrax/dashboard/collections/_list_works.html.erb +1 -1
- data/app/views/hyrax/dashboard/collections/_show_document_list_menu.html.erb +13 -12
- data/app/views/hyrax/dashboard/collections/_show_document_list_row.html.erb +1 -1
- data/app/views/hyrax/dashboard/profiles/_edit_primary.html.erb +1 -8
- data/app/views/hyrax/dashboard/profiles/_trophy_edit.html.erb +1 -1
- data/app/views/hyrax/dashboard/profiles/show.html.erb +5 -5
- data/app/views/hyrax/dashboard/sidebar/_metadata.html.erb +11 -0
- data/app/views/hyrax/dashboard/sidebar/_repository_content.html.erb +1 -0
- data/app/views/hyrax/dashboard/works/_default_group.html.erb +3 -0
- data/app/views/hyrax/dashboard/works/_list_works.html.erb +4 -2
- data/app/views/hyrax/file_sets/_form.html.erb +16 -3
- data/app/views/hyrax/file_sets/_metadata.html.erb +35 -0
- data/app/views/hyrax/file_sets/_valkyrie_form.html.erb +37 -0
- data/app/views/hyrax/file_sets/edit.html.erb +14 -8
- data/app/views/hyrax/file_sets/media_display/_audio.html.erb +4 -0
- data/app/views/hyrax/file_sets/media_display/_image.html.erb +2 -2
- data/app/views/hyrax/file_sets/media_display/_video.html.erb +4 -0
- data/app/views/hyrax/homepage/_explore_collections.html.erb +1 -1
- data/app/views/hyrax/homepage/_featured_fields.html.erb +1 -1
- data/app/views/hyrax/homepage/_recent_document.html.erb +1 -1
- data/app/views/hyrax/homepage/robots.text.erb +17 -0
- data/app/views/hyrax/my/_admin_set_action_menu.html.erb +31 -27
- data/app/views/hyrax/my/_collection_action_menu.html.erb +40 -35
- data/app/views/hyrax/my/_work_action_menu.html.erb +23 -22
- data/app/views/hyrax/my/collections/_default_group.html.erb +3 -0
- data/app/views/hyrax/my/collections/_list_collections.html.erb +3 -0
- data/app/views/hyrax/my/collections/_modal_add_subcollection.html.erb +2 -2
- data/app/views/hyrax/my/collections/_modal_add_to_collection.html.erb +2 -2
- data/app/views/hyrax/my/works/_default_group.html.erb +3 -0
- data/app/views/hyrax/my/works/_list_works.html.erb +5 -2
- data/app/views/hyrax/shared/_copy_permalink.html.erb +10 -0
- data/app/views/hyrax/users/_user_info.html.erb +1 -6
- data/app/views/layouts/_head_tag_content.html.erb +2 -0
- data/app/views/layouts/hyrax/dashboard.html.erb +2 -1
- data/app/views/records/edit_fields/_contexts.html.erb +1 -0
- data/app/views/records/edit_fields/_license.html.erb +17 -5
- data/app/views/records/edit_fields/_resource_type.html.erb +16 -2
- data/app/views/records/edit_fields/_rights_statement.html.erb +17 -5
- data/app/views/records/edit_fields/_schema_version.html.erb +1 -0
- data/app/views/records/edit_fields/_transcript_ids.html.erb +18 -0
- data/app/views/records/show_fields/_rights.html.erb +1 -1
- data/app/views/shared/_citations.html.erb +46 -31
- data/app/views/shared/_schema_version.html.erb +38 -0
- data/bin/dev-entrypoint.sh +14 -4
- data/chart/hyrax/Chart.yaml +4 -4
- data/chart/hyrax/templates/ingress.yaml +3 -0
- data/chart/hyrax/values.yaml +10 -8
- data/config/features.rb +77 -40
- data/config/initializers/blacklight_dynamic_sitemap.rb +43 -0
- data/config/initializers/deprecation_patch.rb +27 -0
- data/config/initializers/hydra_works.rb +3 -0
- data/config/initializers/i18n_extensions.rb +197 -0
- data/config/initializers/indexing_adapter_initializer.rb +4 -0
- data/config/initializers/new_framework_defaults_7_2.rb +6 -4
- data/config/initializers/reform_rails_6_1_monkey_patch.rb +29 -0
- data/config/initializers/storage_adapter_initializer.rb +15 -9
- data/config/locales/hyrax.de.yml +172 -54
- data/config/locales/hyrax.en.yml +183 -66
- data/config/locales/hyrax.es.yml +174 -49
- data/config/locales/hyrax.fr.yml +169 -45
- data/config/locales/hyrax.it.yml +172 -48
- data/config/locales/hyrax.pt-BR.yml +172 -54
- data/config/locales/hyrax.zh.yml +145 -21
- data/config/metadata/basic_metadata.yaml +66 -0
- data/config/metadata/batch_edit_metadata.yaml +119 -0
- data/config/metadata/core_metadata.yaml +1 -0
- data/config/metadata/file_set_metadata.yaml +19 -0
- data/config/metadata/redirects.yaml +15 -0
- data/config/metadata_profiles/m3_json_schema.json +487 -0
- data/config/metadata_profiles/m3_profile.yaml +954 -0
- data/config/routes.rb +9 -0
- data/docker-compose-allinson.yml +176 -0
- data/docker-compose-dassie.yml +18 -10
- data/docker-compose-koppie.yml +18 -10
- data/docker-compose-sirenia.yml +20 -10
- data/documentation/copy_permalink.md +29 -0
- data/documentation/developing-your-hyrax-based-app.md +2 -2
- data/documentation/file-ingest-characterization.md +763 -0
- data/documentation/flexible_metadata.md +113 -0
- data/documentation/forms/field_behaviors.md +297 -0
- data/documentation/redirects.md +428 -0
- data/hyrax.gemspec +9 -4
- data/lib/freyja/metadata_adapter.rb +1 -1
- data/lib/freyja/persister.rb +36 -5
- data/lib/generators/hyrax/collection_resource/collection_resource_generator.rb +2 -2
- data/lib/generators/hyrax/collection_resource/templates/collection.rb.erb +5 -1
- data/lib/generators/hyrax/collection_resource/templates/collection_form.rb.erb +5 -1
- data/lib/generators/hyrax/collection_resource/templates/collection_indexer.rb.erb +6 -1
- data/lib/generators/hyrax/iiif_viewer/USAGE +22 -0
- data/lib/generators/hyrax/iiif_viewer/iiif_viewer_generator.rb +49 -0
- data/lib/generators/hyrax/iiif_viewer/templates/_clover.html.erb +7 -0
- data/lib/generators/hyrax/iiif_viewer/templates/clover/clover.css +3328 -0
- data/lib/generators/hyrax/iiif_viewer/templates/clover/clover.html +16 -0
- data/lib/generators/hyrax/iiif_viewer/templates/clover/clover.js +237 -0
- data/lib/generators/hyrax/install_generator.rb +25 -1
- data/lib/generators/hyrax/riiif_generator.rb +1 -1
- data/lib/generators/hyrax/templates/app/views/blacklight_dynamic_sitemap/sitemap/show.xml.builder +22 -0
- data/lib/generators/hyrax/templates/config/clamav.rb +2 -0
- data/lib/generators/hyrax/templates/config/initializers/riiif.rb +4 -80
- data/lib/generators/hyrax/templates/db/migrate/20240606205215_create_hyrax_flexible_schemas.rb.erb +9 -0
- data/lib/generators/hyrax/templates/db/migrate/20240606205216_add_contexts_to_hyrax_flexible_schemas.rb.erb +5 -0
- data/lib/generators/hyrax/templates/db/migrate/20260430000001_create_hyrax_redirect_paths.rb.erb +22 -0
- data/lib/generators/hyrax/templates/db/migrate/20260521003627_add_additional_redirect_info.rb.erb +39 -0
- data/lib/generators/hyrax/templates/package.json +1 -1
- data/lib/generators/hyrax/templates/uv.html +60 -82
- data/lib/generators/hyrax/work/templates/indexer.rb.erb +1 -1
- data/lib/generators/hyrax/work/templates/model.rb.erb +5 -1
- data/lib/generators/hyrax/work_resource/templates/form.rb.erb +5 -2
- data/lib/generators/hyrax/work_resource/templates/indexer.rb.erb +6 -2
- data/lib/generators/hyrax/work_resource/templates/work.rb.erb +5 -2
- data/lib/generators/hyrax/work_resource/work_resource_generator.rb +1 -0
- data/lib/hyrax/active_fedora_dummy_model.rb +6 -0
- data/lib/hyrax/configuration.rb +219 -10
- data/lib/hyrax/controlled_vocabulary/importer/language.rb +5 -1
- data/lib/hyrax/deprecation.rb +31 -0
- data/lib/hyrax/engine.rb +2 -0
- data/lib/hyrax/form_fields.rb +17 -5
- data/lib/hyrax/indexer.rb +31 -2
- data/lib/hyrax/resource_sync/resource_list_writer.rb +3 -0
- data/lib/hyrax/schema.rb +15 -4
- data/lib/hyrax/specs/shared_specs/factories/administrative_sets.rb +12 -0
- data/lib/hyrax/specs/shared_specs/factories/hyrax_embargo.rb +1 -1
- data/lib/hyrax/specs/shared_specs/factories/hyrax_file_set.rb +13 -0
- data/lib/hyrax/specs/shared_specs/factories/hyrax_lease.rb +5 -1
- data/lib/hyrax/specs/shared_specs/factories/hyrax_work.rb +14 -0
- data/lib/hyrax/specs/shared_specs/simple_work.rb +41 -0
- data/lib/hyrax/specs/shared_specs.rb +1 -0
- data/lib/hyrax/transactions/collection_create.rb +2 -1
- data/lib/hyrax/transactions/collection_destroy.rb +1 -0
- data/lib/hyrax/transactions/collection_update.rb +2 -1
- data/lib/hyrax/transactions/container.rb +28 -0
- data/lib/hyrax/transactions/steps/add_file_sets.rb +2 -1
- data/lib/hyrax/transactions/steps/apply_permission_template_on_update.rb +65 -0
- data/lib/hyrax/transactions/steps/apply_workflow_on_admin_set_change.rb +97 -0
- data/lib/hyrax/transactions/steps/ensure_admin_set.rb +1 -1
- data/lib/hyrax/transactions/steps/remove_redirect_paths.rb +35 -0
- data/lib/hyrax/transactions/steps/save.rb +10 -0
- data/lib/hyrax/transactions/steps/set_default_admin_set.rb +1 -1
- data/lib/hyrax/transactions/steps/sync_redirect_paths.rb +141 -0
- data/lib/hyrax/transactions/work_create.rb +2 -1
- data/lib/hyrax/transactions/work_destroy.rb +1 -0
- data/lib/hyrax/transactions/work_update.rb +4 -1
- data/lib/hyrax/version.rb +1 -1
- data/lib/hyrax.rb +62 -0
- data/lib/tasks/m3_profile_cleanup.rake +35 -0
- data/lib/valkyrie/indexing/redis_queue/indexing_adapter.rb +144 -0
- data/lib/wings/valkyrie/query_service.rb +3 -4
- data/template.rb +4 -1
- metadata +327 -25
- data/.dassie/public/robots.txt +0 -1
- data/.github/workflows/main.yml +0 -17
- data/.koppie/public/robots.txt +0 -1
- data/app/forms/concerns/hyrax/basic_metadata_form_fields_behavior.rb +0 -39
- data/app/views/catalog/_thumbnail_list_collection.html.erb +0 -4
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hyrax
|
|
4
|
+
module CustomQueries
|
|
5
|
+
##
|
|
6
|
+
# Finds resources for arbitrary properties using the Solr index.
|
|
7
|
+
# @see https://github.com/samvera/valkyrie/wiki/Queries#custom-queries
|
|
8
|
+
class FindByPropertyValue
|
|
9
|
+
def self.queries
|
|
10
|
+
[:find_ids_by_property_pairs,
|
|
11
|
+
:find_many_by_property_pairs,
|
|
12
|
+
:find_many_by_property_value,
|
|
13
|
+
:find_by_property_value]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def initialize(query_service:, query_rows: 1_000)
|
|
17
|
+
@query_service = query_service
|
|
18
|
+
@query_rows = query_rows
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
##
|
|
22
|
+
# Returns ids for resources matching all specified property/value pairs.
|
|
23
|
+
# @param pairs [Hash<String, String>] properties and values to match
|
|
24
|
+
# @param field_suffix Hash,Symbol which solr field suffix to use; Use a hash to set per field pair
|
|
25
|
+
# @param options Hash options to pass to solr
|
|
26
|
+
#
|
|
27
|
+
# @return [Array<String>] found ids, if any
|
|
28
|
+
def find_ids_by_property_pairs(pairs:, field_suffix: :ssim, **options)
|
|
29
|
+
options = { rows: @query_rows }.merge(options)
|
|
30
|
+
query = pairs.map do |k, v|
|
|
31
|
+
suffix = if field_suffix.is_a? Hash
|
|
32
|
+
field_suffix[k] || :ssim
|
|
33
|
+
else
|
|
34
|
+
field_suffix
|
|
35
|
+
end
|
|
36
|
+
"+#{k}_#{suffix}:\"#{RSolr.solr_escape(v)}\""
|
|
37
|
+
end
|
|
38
|
+
response = Hyrax::SolrService.query_result(query.join(' '), fl: 'id', **options)
|
|
39
|
+
response['response']['docs'].map { |doc| doc['id'] }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
##
|
|
43
|
+
# Returns resources matching all specified property/value pairs.
|
|
44
|
+
# @param pairs [Hash<String, String>] properties and values to match
|
|
45
|
+
# @param field_suffix Hash,Symbol which solr field suffix to use; Use a hash to set per field pair
|
|
46
|
+
# @param options Hash options to pass to solr
|
|
47
|
+
#
|
|
48
|
+
# @return [Array<Valkyrie::Resource>] found resources, if any
|
|
49
|
+
def find_many_by_property_pairs(pairs:, field_suffix: :ssim, **options)
|
|
50
|
+
found_ids = find_ids_by_property_pairs(pairs: pairs, field_suffix: field_suffix, **options)
|
|
51
|
+
@query_service.find_many_by_ids(ids: found_ids).to_a # Wings emits an Enumerator
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
##
|
|
55
|
+
# Returns resources matching the specified property and value.
|
|
56
|
+
# @param property [#to_s] the name of the property we're attempting to query.
|
|
57
|
+
# @param value [#to_s] the property value we're trying to match.
|
|
58
|
+
# @param field_suffix Symbol which solr field suffix to use
|
|
59
|
+
# @param search_field String alt way to set property and suffix for compatibility
|
|
60
|
+
# @param options Hash options to pass to solr
|
|
61
|
+
#
|
|
62
|
+
# @return [Array<Valkyrie::Resource>] found resources, if any
|
|
63
|
+
def find_many_by_property_value(property:, value:, field_suffix: :ssim, search_field: nil, **options)
|
|
64
|
+
if search_field
|
|
65
|
+
search_field_array = search_field.split('_')
|
|
66
|
+
field_suffix = search_field_array.last
|
|
67
|
+
property = search_field_array[0...-1].join('_')
|
|
68
|
+
end
|
|
69
|
+
find_many_by_property_pairs(pairs: { property => value }, field_suffix: field_suffix, **options)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
##
|
|
73
|
+
# Returns one resource matching the specified property and value.
|
|
74
|
+
# @param property [#to_s] the name of the property we're attempting to query.
|
|
75
|
+
# @param value [#to_s] the property value we're trying to match.
|
|
76
|
+
# @param field_suffix Symbol which solr field suffix to use
|
|
77
|
+
# @param search_field String alt way to set property and suffix for compatibility
|
|
78
|
+
# @param options Hash options to pass to solr
|
|
79
|
+
#
|
|
80
|
+
# @return [NilClass] when no record was found
|
|
81
|
+
# @return [Valkyrie::Resource] when a resource was found
|
|
82
|
+
def find_by_property_value(property:, value:, field_suffix: :ssim, search_field: nil, **options)
|
|
83
|
+
options[:rows] = 1
|
|
84
|
+
find_many_by_property_value(property: property, value: value,
|
|
85
|
+
field_suffix: field_suffix, search_field: search_field, **options).first
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -8,8 +8,9 @@ module Hyrax
|
|
|
8
8
|
[:find_ids_by_model]
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
def initialize(query_service:)
|
|
11
|
+
def initialize(query_service:, query_rows: 1_000)
|
|
12
12
|
@query_service = query_service
|
|
13
|
+
@query_rows = query_rows
|
|
13
14
|
end
|
|
14
15
|
|
|
15
16
|
attr_reader :query_service
|
|
@@ -23,14 +24,38 @@ module Hyrax
|
|
|
23
24
|
#
|
|
24
25
|
# @param model [Class]
|
|
25
26
|
# @param ids [Enumerable<#to_s>, Symbol]
|
|
27
|
+
# @param use_solr [Boolean]
|
|
26
28
|
#
|
|
27
29
|
# @return [Enumerable<Valkyrie::ID>]
|
|
28
|
-
def find_ids_by_model(model:, ids: :all)
|
|
29
|
-
|
|
30
|
+
def find_ids_by_model(model:, ids: :all, use_solr: true)
|
|
31
|
+
if use_solr
|
|
32
|
+
query_solr(model, ids)
|
|
33
|
+
else
|
|
34
|
+
return query_service.find_all_of_model(model: model).map(&:id) if ids == :all
|
|
35
|
+
query_service.find_many_by_ids(ids: ids).select do |resource|
|
|
36
|
+
resource.is_a?(model)
|
|
37
|
+
end.map(&:id)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def query_solr(model, ids)
|
|
44
|
+
return enum_for(:query_solr, model, ids) unless block_given?
|
|
45
|
+
model_name = Hyrax::ModelRegistry.rdf_representations_from(Array(model)).first
|
|
46
|
+
|
|
47
|
+
solr_query = "_query_:\"{!raw f=has_model_ssim}#{model_name}\""
|
|
48
|
+
solr_response = Hyrax::SolrService.get(solr_query, fl: 'id', rows: @query_rows)['response']
|
|
49
|
+
|
|
50
|
+
loop do
|
|
51
|
+
response_docs = solr_response['docs']
|
|
52
|
+
response_docs.select! { |doc| ids.include?(doc['id']) } unless ids == :all
|
|
53
|
+
|
|
54
|
+
response_docs.each { |doc| yield doc['id'] }
|
|
30
55
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
end
|
|
56
|
+
break if (solr_response['start'] + solr_response['docs'].count) >= solr_response['numFound']
|
|
57
|
+
solr_response = Hyrax::SolrService.get(solr_query, fl: 'id', rows: @query_rows, start: solr_response['start'] + @query_rows)['response']
|
|
58
|
+
end
|
|
34
59
|
end
|
|
35
60
|
end
|
|
36
61
|
end
|
|
@@ -33,23 +33,24 @@ module Hyrax
|
|
|
33
33
|
# * use work the file_set is in
|
|
34
34
|
# No other object types are supported by this view.
|
|
35
35
|
def self.build_service_object_from(form:, ability:)
|
|
36
|
-
|
|
36
|
+
obj = form.object
|
|
37
|
+
if obj.respond_to?(:model) && obj.model.work?
|
|
37
38
|
# The provided form object is a work form.
|
|
38
|
-
new(object:
|
|
39
|
-
elsif
|
|
39
|
+
new(object: obj, ability: ability)
|
|
40
|
+
elsif obj.respond_to?(:model) && obj.model.file_set?
|
|
40
41
|
# The provided form object is a FileSet form. For Valkyrie forms
|
|
41
42
|
# (+Hyrax::Forms::FileSetForm+), +:in_works_ids+ is prepopulated onto
|
|
42
43
|
# the form object itself. For +Hyrax::Forms::FileSetEditForm+, the
|
|
43
44
|
# +:in_works+ method is present on the wrapped +:model+.
|
|
44
|
-
if
|
|
45
|
-
|
|
46
|
-
new(object: Hyrax.query_service.find_by(id: object_id), ability: ability)
|
|
45
|
+
if obj.model.respond_to?(:in_works)
|
|
46
|
+
new(object: obj.model.in_works.first, ability: ability)
|
|
47
47
|
else
|
|
48
|
-
|
|
48
|
+
object_id = obj.in_works_ids.first
|
|
49
|
+
new(object: Hyrax.query_service.find_by(id: object_id), ability: ability)
|
|
49
50
|
end
|
|
50
|
-
elsif
|
|
51
|
+
elsif obj.file_set?
|
|
51
52
|
# The provided form object is a FileSet.
|
|
52
|
-
new(object:
|
|
53
|
+
new(object: obj.in_works.first, ability: ability)
|
|
53
54
|
end
|
|
54
55
|
end
|
|
55
56
|
|
|
@@ -170,7 +171,7 @@ module Hyrax
|
|
|
170
171
|
unauthorized_managers = []
|
|
171
172
|
unauthorized_collection_managers = []
|
|
172
173
|
object_unauthorized_collection_ids.each do |id|
|
|
173
|
-
Hyrax::PermissionTemplate.find_by(source_id: id)
|
|
174
|
+
Hyrax::PermissionTemplate.find_by(source_id: id)&.access_grants&.each do |grant|
|
|
174
175
|
if grant.access == "manage"
|
|
175
176
|
unauthorized_managers << grant.agent_id
|
|
176
177
|
unauthorized_collection_managers += Array.wrap({ name: grant.agent_id }.merge(id: id))
|
|
@@ -8,9 +8,6 @@ module Hyrax
|
|
|
8
8
|
# @note this service is for `Hyrax::FileSet` Valkyrie Resources. for
|
|
9
9
|
# ActiveFedora file sets see Hydra::Works::MimeTypes
|
|
10
10
|
class FileSetTypeService
|
|
11
|
-
DEFAULT_AUDIO_TYPES = ['audio/mp3', 'audio/mpeg', 'audio/wav',
|
|
12
|
-
'audio/x-wave', 'audio/x-wav', 'audio/ogg'].freeze
|
|
13
|
-
|
|
14
11
|
##
|
|
15
12
|
# @!attribute [r] file_set
|
|
16
13
|
# @return [Hyrax::FileSet]
|
|
@@ -42,11 +39,22 @@ module Hyrax
|
|
|
42
39
|
audio_types.include?(mime_type)
|
|
43
40
|
end
|
|
44
41
|
|
|
42
|
+
##
|
|
43
|
+
# @return [Boolean]
|
|
44
|
+
def video?
|
|
45
|
+
video_types.include?(mime_type)
|
|
46
|
+
end
|
|
47
|
+
|
|
45
48
|
private
|
|
46
49
|
|
|
47
50
|
def audio_types
|
|
48
51
|
return ::FileSet.audio_mime_types if defined?(::FileSet) && ::FileSet.respond_to?(:audio_mime_types)
|
|
49
|
-
|
|
52
|
+
Hyrax.config.mime_types_map.fetch(:audio_mime_types)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def video_types
|
|
56
|
+
return ::FileSet.video_mime_types if defined?(::FileSet) && ::FileSet.respond_to?(:video_mime_types)
|
|
57
|
+
Hyrax.config.mime_types_map.fetch(:video_mime_types)
|
|
50
58
|
end
|
|
51
59
|
end
|
|
52
60
|
end
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hyrax
|
|
4
|
+
class FlexibleSchemaValidatorService
|
|
5
|
+
DEFAULT_SCHEMA = Hyrax::Engine.root.join('config', 'metadata_profiles', 'm3_json_schema.json')
|
|
6
|
+
REQUIRED_CLASSES = [
|
|
7
|
+
Hyrax.config.admin_set_model,
|
|
8
|
+
Hyrax.config.collection_model,
|
|
9
|
+
Hyrax.config.file_set_model
|
|
10
|
+
].map { |str| str.gsub(/^::/, '') }
|
|
11
|
+
|
|
12
|
+
attr_reader :profile, :schema, :schemer, :errors, :warnings
|
|
13
|
+
|
|
14
|
+
# Initializes a new FlexibleSchemaValidatorService.
|
|
15
|
+
#
|
|
16
|
+
# @param profile [Hash] the flexible metadata profile to validate
|
|
17
|
+
# @param schema [Pathname, String] the JSON schema to validate against.
|
|
18
|
+
# Defaults to {DEFAULT_SCHEMA}.
|
|
19
|
+
# @return [void]
|
|
20
|
+
def initialize(profile:, schema: default_schema)
|
|
21
|
+
@profile = profile
|
|
22
|
+
@schema = schema
|
|
23
|
+
@schemer = JSONSchemer.schema(schema)
|
|
24
|
+
@errors = []
|
|
25
|
+
@warnings = []
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Execute all validation routines and populate {#errors} with any
|
|
29
|
+
# issues discovered.
|
|
30
|
+
#
|
|
31
|
+
# @return [void]
|
|
32
|
+
def validate!
|
|
33
|
+
validate_required_classes
|
|
34
|
+
validate_class_availability
|
|
35
|
+
validate_available_on_classes_defined
|
|
36
|
+
validate_existing_records_classes_defined
|
|
37
|
+
validate_schema
|
|
38
|
+
validate_label_prop
|
|
39
|
+
validate_core_metadata
|
|
40
|
+
validate_sort_properties
|
|
41
|
+
validate_redirects
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# The default JSON schema used when no custom schema is provided.
|
|
45
|
+
#
|
|
46
|
+
# @return [Pathname]
|
|
47
|
+
def default_schema
|
|
48
|
+
DEFAULT_SCHEMA
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Classes that MUST be present in every flexible metadata profile.
|
|
52
|
+
#
|
|
53
|
+
# @return [Array<String>]
|
|
54
|
+
def required_classes
|
|
55
|
+
REQUIRED_CLASSES
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
private
|
|
59
|
+
|
|
60
|
+
# Validates core metadata requirements using the CoreMetadataValidator.
|
|
61
|
+
#
|
|
62
|
+
# This delegates to CoreMetadataValidator to check that essential metadata
|
|
63
|
+
# properties are properly configured across all classes in the profile.
|
|
64
|
+
#
|
|
65
|
+
# @return [void]
|
|
66
|
+
def validate_core_metadata
|
|
67
|
+
FlexibleSchemaValidators::CoreMetadataValidator.new(profile: profile, errors: @errors).validate!
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Runs JSON schema validation and translates resulting errors into
|
|
71
|
+
# user-friendly messages appended to {#errors}.
|
|
72
|
+
#
|
|
73
|
+
# @return [void]
|
|
74
|
+
def validate_schema
|
|
75
|
+
FlexibleSchemaValidators::SchemaValidator.new(schemer, profile, @errors).validate!
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Ensures that all required classes are defined in the profile.
|
|
79
|
+
#
|
|
80
|
+
# @return [void]
|
|
81
|
+
def validate_required_classes
|
|
82
|
+
missing_classes = clean_class_names(required_classes) - clean_class_names(profile['classes'].keys)
|
|
83
|
+
return if missing_classes.empty?
|
|
84
|
+
|
|
85
|
+
@errors << "Missing required classes: #{missing_classes.join(', ')}."
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def clean_class_names(names)
|
|
89
|
+
names.map { |name| name.to_s.strip.gsub(/^::/, '') }
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Checks that any class referenced in the profile is a registered
|
|
93
|
+
# Hyrax curation concern type.
|
|
94
|
+
#
|
|
95
|
+
# @return [void]
|
|
96
|
+
def validate_class_availability
|
|
97
|
+
FlexibleSchemaValidators::ClassValidator.new(profile, required_classes, @errors).validate_availability!
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Validates that every class referenced under `available_on.class` is also
|
|
101
|
+
# defined in the profile's top-level `classes` section.
|
|
102
|
+
#
|
|
103
|
+
# @return [void]
|
|
104
|
+
def validate_available_on_classes_defined
|
|
105
|
+
FlexibleSchemaValidators::ClassValidator.new(profile, required_classes, @errors).validate_references!
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Delegates to {ExistingRecordsValidator} to ensure that no classes with
|
|
109
|
+
# existing repository records have been removed from the profile.
|
|
110
|
+
#
|
|
111
|
+
# @return [void]
|
|
112
|
+
def validate_existing_records_classes_defined
|
|
113
|
+
FlexibleSchemaValidators::ExistingRecordsValidator.new(profile, required_classes, @errors).validate!
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Validates that any properties needed to support sorting catalog search results.
|
|
117
|
+
#
|
|
118
|
+
# @return [void]
|
|
119
|
+
def validate_sort_properties
|
|
120
|
+
FlexibleSchemaValidators::SortPropertiesValidator.new(profile, @warnings).validate!
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Validates that the `redirects` property is declared on every work and
|
|
124
|
+
# collection class when both `Hyrax.config.redirects_enabled?` and
|
|
125
|
+
# `Flipflop.redirects?` are true. When either gate is closed, this
|
|
126
|
+
# validator is a no-op.
|
|
127
|
+
#
|
|
128
|
+
# @return [void]
|
|
129
|
+
def validate_redirects
|
|
130
|
+
FlexibleSchemaValidators::RedirectsValidator.new(
|
|
131
|
+
profile: profile, errors: @errors, warnings: @warnings
|
|
132
|
+
).validate!
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# Validates that a `label` property exists and that it is available on
|
|
136
|
+
# `Hyrax.config.file_set_model`.
|
|
137
|
+
#
|
|
138
|
+
# @return [void]
|
|
139
|
+
def validate_label_prop
|
|
140
|
+
label_prop = profile.dig('properties', 'label')
|
|
141
|
+
unless label_prop
|
|
142
|
+
@errors << "A `label` property is required."
|
|
143
|
+
return
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
available_on_classes = label_prop.dig('available_on', 'class')
|
|
147
|
+
file_set_model_name = Hyrax.config.file_set_model.gsub(/^::/, '')
|
|
148
|
+
return if available_on_classes&.include?(file_set_model_name)
|
|
149
|
+
|
|
150
|
+
@errors << "Label must be available on #{file_set_model_name}."
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hyrax
|
|
4
|
+
module FlexibleSchemaValidators
|
|
5
|
+
# Handles class-related validations for flexible metadata profiles
|
|
6
|
+
class ClassValidator
|
|
7
|
+
# @param profile [Hash] M3 profile data
|
|
8
|
+
# @param required_classes [Array<String>] Foundational classes that must be present
|
|
9
|
+
# @param errors [Array<String>] Array to append validation errors to
|
|
10
|
+
def initialize(profile, required_classes, errors)
|
|
11
|
+
@profile = profile
|
|
12
|
+
@required_classes = required_classes
|
|
13
|
+
@errors = errors
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Validates that referenced classes are registered Hyrax curation concern
|
|
17
|
+
# types and that Valkyrie models use the correct `...Resource` naming
|
|
18
|
+
# convention when applicable.
|
|
19
|
+
#
|
|
20
|
+
# @return [void]
|
|
21
|
+
def validate_availability!
|
|
22
|
+
classes_to_validate = all_profile_classes - @required_classes
|
|
23
|
+
invalid_classes = []
|
|
24
|
+
mismatched_valkyrie_classes = []
|
|
25
|
+
|
|
26
|
+
classes_to_validate.each do |klass|
|
|
27
|
+
validate_class(klass, invalid_classes, mismatched_valkyrie_classes)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
report_mismatched_classes(mismatched_valkyrie_classes)
|
|
31
|
+
report_invalid_classes(invalid_classes)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Validates that all classes referenced within property `available_on`
|
|
35
|
+
# definitions are themselves defined in the top-level `classes` section of
|
|
36
|
+
# the profile.
|
|
37
|
+
#
|
|
38
|
+
# @return [void]
|
|
39
|
+
def validate_references!
|
|
40
|
+
properties = @profile['properties'] || {}
|
|
41
|
+
|
|
42
|
+
referenced_classes = properties.values.flat_map do |prop|
|
|
43
|
+
prop.dig('available_on', 'class')
|
|
44
|
+
end.compact.uniq
|
|
45
|
+
|
|
46
|
+
undefined_classes = referenced_classes - @profile['classes'].keys
|
|
47
|
+
|
|
48
|
+
return if undefined_classes.empty?
|
|
49
|
+
|
|
50
|
+
@errors << "Classes referenced in `available_on` but not defined in `classes`: #{undefined_classes.join(', ')}."
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
# Gathers all unique class names from both the top-level `classes`
|
|
56
|
+
# definition and all `available_on` property references.
|
|
57
|
+
#
|
|
58
|
+
# @return [Array<String>]
|
|
59
|
+
def all_profile_classes
|
|
60
|
+
profile_classes = @profile.fetch('classes', {}).keys
|
|
61
|
+
properties = @profile['properties'] || {}
|
|
62
|
+
available_on_classes = properties.values.flat_map do |prop|
|
|
63
|
+
prop.dig('available_on', 'class')
|
|
64
|
+
end.compact
|
|
65
|
+
|
|
66
|
+
clean_class_names(profile_classes + available_on_classes).uniq
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def clean_class_names(names)
|
|
70
|
+
names.map { |name| name.to_s.strip.gsub(/^::/, '') }
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Validates a single class, checking for registration as a curation concern
|
|
74
|
+
# and for Valkyrie naming mismatches using the Valkyrie resolver.
|
|
75
|
+
#
|
|
76
|
+
# @param klass [String] the class name to validate
|
|
77
|
+
# @param invalid_classes [Array<String>] an array to append invalid class errors to
|
|
78
|
+
# @param mismatched_valkyrie_classes [Array<Hash>] an array to append Valkyrie mismatch errors to
|
|
79
|
+
# @return [void]
|
|
80
|
+
def validate_class(klass, invalid_classes, mismatched_valkyrie_classes)
|
|
81
|
+
base_class_name = klass.gsub(/(?<=.)Resource$/, '')
|
|
82
|
+
unless Hyrax.config.registered_curation_concern_types.include?(base_class_name)
|
|
83
|
+
invalid_classes << klass
|
|
84
|
+
return
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
begin
|
|
88
|
+
expected_valkyrie_class = Valkyrie.config.resource_class_resolver.call(base_class_name)
|
|
89
|
+
expected_class_name = expected_valkyrie_class.to_s
|
|
90
|
+
|
|
91
|
+
mismatched_valkyrie_classes << { non_resource: klass, resource: expected_class_name } if klass != expected_class_name
|
|
92
|
+
rescue NameError
|
|
93
|
+
# This occurs if a registered concern doesn't have a loadable backing class,
|
|
94
|
+
# which is an invalid state.
|
|
95
|
+
invalid_classes << klass
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Appends a formatted error message for any Valkyrie naming mismatches.
|
|
100
|
+
#
|
|
101
|
+
# @param mismatched_classes [Array<Hash>]
|
|
102
|
+
# @return [void]
|
|
103
|
+
def report_mismatched_classes(mismatched_classes)
|
|
104
|
+
return if mismatched_classes.empty?
|
|
105
|
+
|
|
106
|
+
message = mismatched_classes.map do |mismatch|
|
|
107
|
+
"'#{mismatch[:non_resource]}' should be '#{mismatch[:resource]}'"
|
|
108
|
+
end.join(', ')
|
|
109
|
+
@errors << "Mismatched Valkyrie classes found: #{message}."
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Appends a formatted error message for any invalid classes.
|
|
113
|
+
#
|
|
114
|
+
# @param invalid_classes [Array<String>]
|
|
115
|
+
# @return [void]
|
|
116
|
+
def report_invalid_classes(invalid_classes)
|
|
117
|
+
return if invalid_classes.empty?
|
|
118
|
+
|
|
119
|
+
@errors << "Invalid classes: #{invalid_classes.join(', ')}."
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|