hyrax 5.2.0 → 5.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.dassie/.env +5 -1
- data/.dassie/Gemfile +4 -2
- 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/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/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 +154 -1
- 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 +5 -1
- 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/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 +2 -0
- data/Dockerfile +9 -22
- data/Gemfile +0 -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/works_controller_behavior.rb +52 -10
- 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 +1 -0
- 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 +19 -1
- 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 +51 -2
- 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/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/content_deposit_error_event_job.rb +14 -0
- data/app/jobs/create_work_job.rb +2 -0
- data/app/jobs/migrate_files_to_valkyrie_job.rb +7 -1
- 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 +3 -1
- 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 -6
- 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_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/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/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/edit_permissions_service.rb +4 -4
- 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 +7 -1
- 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/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/index.html.erb +11 -9
- 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 +1 -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_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/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 +27 -0
- 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/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/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 +14 -6
- 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 +7 -2
- data/lib/freyja/metadata_adapter.rb +1 -1
- data/lib/freyja/persister.rb +25 -1
- 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 +197 -3
- 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/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 +61 -0
- data/lib/tasks/m3_profile_cleanup.rake +35 -0
- data/template.rb +4 -1
- metadata +313 -19
- data/.dassie/public/robots.txt +0 -1
- 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,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Hyrax
|
|
3
|
+
class M3ProfileEditor
|
|
4
|
+
attr_accessor :profile_path
|
|
5
|
+
|
|
6
|
+
def initialize(profile_path)
|
|
7
|
+
@profile_path = profile_path
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def profile_data
|
|
11
|
+
return @profile_data if @profile_data
|
|
12
|
+
# Use the provided path or default to the dassie m3_profile.yaml
|
|
13
|
+
raise "Error: Profile file not found at #{profile_path}" unless File.exist?(profile_path)
|
|
14
|
+
|
|
15
|
+
Rails.logger.debug "Processing M3 profile at: #{profile_path}"
|
|
16
|
+
|
|
17
|
+
# Load the YAML file
|
|
18
|
+
@profile_data = YAML.load_file(profile_path)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def find_i18n(label_value)
|
|
22
|
+
I18n.reverse_lookup(label_value, scope: [:blacklight, :search, :fields, :show]) ||
|
|
23
|
+
I18n.reverse_lookup(label_value, scope: [:blacklight, :search, :fields, :index]) ||
|
|
24
|
+
label_value
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def save
|
|
28
|
+
File.write(@profile_path, profile_data.to_yaml)
|
|
29
|
+
Rails.logger.debug "Updated profile saved to: #{@profile_path}"
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hyrax
|
|
4
|
+
##
|
|
5
|
+
# @api private
|
|
6
|
+
#
|
|
7
|
+
# Read m3 profiles from the database
|
|
8
|
+
#
|
|
9
|
+
# @see config/metadata_profiles/m3_profile.yaml for an example configuration
|
|
10
|
+
class M3SchemaLoader < Hyrax::SchemaLoader
|
|
11
|
+
def view_definitions_for(schema:, version: 1, contexts: nil)
|
|
12
|
+
definitions(schema, version, contexts).each_with_object({}) do |definition, hash|
|
|
13
|
+
view_options = definition.view_options
|
|
14
|
+
# display_label, admin_only, and editor_only keys are always added to
|
|
15
|
+
# the view_options hash. If there are no other view options, skip this
|
|
16
|
+
# field.
|
|
17
|
+
next if view_options.without(:display_label, :admin_only, :editor_only).empty?
|
|
18
|
+
|
|
19
|
+
hash[definition.name] = definition.view_options
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def config_paths(schema_name = 'm3_profile')
|
|
24
|
+
config_search_paths.collect do |root_path|
|
|
25
|
+
path = root_path.to_s + "/config/metadata_profiles/#{schema_name}.yaml"
|
|
26
|
+
path if File.exist?(path)
|
|
27
|
+
end.compact
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def current_version
|
|
31
|
+
Hyrax::FlexibleSchema.current_schema_id
|
|
32
|
+
rescue ActiveRecord::StatementInvalid # allow for moments when the database is not yet initialized
|
|
33
|
+
0
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
##
|
|
39
|
+
# @param [#to_s] schema_name
|
|
40
|
+
# @return [Enumerable<AttributeDefinition]
|
|
41
|
+
def definitions(schema_name, version, contexts = nil)
|
|
42
|
+
schema = Hyrax::FlexibleSchema.find_by(id: version) || Hyrax::FlexibleSchema.create_default_schema
|
|
43
|
+
attributes = schema.attributes_for(schema_name)
|
|
44
|
+
attributes ||= fallback_schema_for(schema_name)
|
|
45
|
+
attributes.map do |name, config|
|
|
46
|
+
# We might be able to consolidate these conditions, but they have been kept separate to make it easier to reason about
|
|
47
|
+
# If there is a context filter on the metadata field and no context is set, skip it
|
|
48
|
+
next if contexts.blank? && config['context'].present?
|
|
49
|
+
|
|
50
|
+
# If there is a context filter on the metadata field and we have set a context, but the context does not match, skip it
|
|
51
|
+
next if contexts.present? && config['context'].present? && !(Array(contexts) & Array(config['context'])).any?
|
|
52
|
+
|
|
53
|
+
# Wew, we are in the clear to use this field
|
|
54
|
+
M3AttributeDefinition.new(name, config)
|
|
55
|
+
end.compact
|
|
56
|
+
rescue ActiveRecord::StatementInvalid
|
|
57
|
+
Rails.logger.error "Skipping definition load for migrations to run"
|
|
58
|
+
[]
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# rubocop:disable Metrics/MethodLength
|
|
62
|
+
def fallback_schema_for(_schema_name)
|
|
63
|
+
{ "title" =>
|
|
64
|
+
{ "cardinality" => { "minimum" => 1 },
|
|
65
|
+
"data_type" => "array",
|
|
66
|
+
"controlled_values" => { "format" => "http://www.w3.org/2001/XMLSchema#string", "sources" => ["null"] },
|
|
67
|
+
"definition" =>
|
|
68
|
+
{ "default" =>
|
|
69
|
+
"Enter a standardized title for display. If only one title is needed, transcribe the title from the source itself." },
|
|
70
|
+
"display_label" => { "default" => "Title" },
|
|
71
|
+
"index_documentation" => "displayable, searchable",
|
|
72
|
+
"indexing" => ["title_sim", "title_tesim"],
|
|
73
|
+
"form" => { "primary" => true, "multiple" => true },
|
|
74
|
+
"mappings" =>
|
|
75
|
+
{ "metatags" => "twitter:title, og:title",
|
|
76
|
+
"mods_oai_pmh" => "mods:titleInfo/mods:title",
|
|
77
|
+
"qualified_dc_pmh" => "dcterms:title",
|
|
78
|
+
"simple_dc_pmh" => "dc:title" },
|
|
79
|
+
"property_uri" => "http://purl.org/dc/terms/title",
|
|
80
|
+
"range" => "http://www.w3.org/2001/XMLSchema#string",
|
|
81
|
+
"requirement" => "required",
|
|
82
|
+
"sample_values" => ["Pencil drawn portrait study of woman"],
|
|
83
|
+
"view" => { "label" => { "en" => "Title", "es" => "Título" }, "html_dl" => true },
|
|
84
|
+
"type" => "string",
|
|
85
|
+
"predicate" => "http://purl.org/dc/terms/title",
|
|
86
|
+
"index_keys" => ["title_sim", "title_tesim"],
|
|
87
|
+
"multiple" => true,
|
|
88
|
+
"context" => nil } }
|
|
89
|
+
end
|
|
90
|
+
# rubocop:enable Metrics/MethodLength
|
|
91
|
+
|
|
92
|
+
##
|
|
93
|
+
# @api private
|
|
94
|
+
#
|
|
95
|
+
# M3-specific AttributeDefinition that properly handles cardinality-based requirements
|
|
96
|
+
class M3AttributeDefinition < Hyrax::SchemaLoader::AttributeDefinition
|
|
97
|
+
##
|
|
98
|
+
# @return [Hash{Symbol => Object}]
|
|
99
|
+
def form_options
|
|
100
|
+
options = super
|
|
101
|
+
|
|
102
|
+
# Check if minimum cardinality makes this field required
|
|
103
|
+
options = options.merge(required: true) if cardinality_required?
|
|
104
|
+
|
|
105
|
+
options
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
private
|
|
109
|
+
|
|
110
|
+
def cardinality_required?
|
|
111
|
+
cardinality = config['cardinality']
|
|
112
|
+
return false unless cardinality.is_a?(Hash)
|
|
113
|
+
|
|
114
|
+
minimum = cardinality['minimum']
|
|
115
|
+
minimum.present? && minimum.to_i >= 1
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
@@ -21,7 +21,7 @@ module Hyrax
|
|
|
21
21
|
# @return [Hash] a Ruby hash representation of a IIIF manifest document
|
|
22
22
|
#
|
|
23
23
|
# @see Hyrax::WorksControllerBehavior
|
|
24
|
-
def self.manifest_for(presenter:, iiif_manifest_factory:
|
|
24
|
+
def self.manifest_for(presenter:, iiif_manifest_factory: Hyrax.config.iiif_manifest_factory)
|
|
25
25
|
new(iiif_manifest_factory: iiif_manifest_factory)
|
|
26
26
|
.manifest_for(presenter: presenter)
|
|
27
27
|
end
|
|
@@ -36,7 +36,7 @@ module Hyrax
|
|
|
36
36
|
#
|
|
37
37
|
# @param iiif_manifest_factory [Class] a class that initializes with presenter
|
|
38
38
|
# object and returns an object that responds to `#to_h`
|
|
39
|
-
def initialize(iiif_manifest_factory:
|
|
39
|
+
def initialize(iiif_manifest_factory: Hyrax.config.iiif_manifest_factory)
|
|
40
40
|
@manifest_factory = iiif_manifest_factory
|
|
41
41
|
end
|
|
42
42
|
|
|
@@ -56,33 +56,27 @@ module Hyrax
|
|
|
56
56
|
# @api private
|
|
57
57
|
# @param presenter [Hyrax::WorkShowPresenter]
|
|
58
58
|
def sanitized_manifest(presenter:)
|
|
59
|
-
# ::IIIFManifest::ManifestBuilder#to_h returns a
|
|
60
|
-
# IIIFManifest::ManifestBuilder::IIIFManifest, not a Hash.
|
|
61
|
-
# to get a Hash, we have to call its #to_json, then parse.
|
|
62
|
-
#
|
|
63
|
-
# wild times. maybe there's a better way to do this with the
|
|
64
|
-
# ManifestFactory interface?
|
|
65
59
|
manifest = manifest_factory.new(presenter).to_h
|
|
66
|
-
hash = JSON.parse(manifest.to_json)
|
|
67
|
-
|
|
68
|
-
hash['label'] = sanitize_value(hash['label']) if hash.key?('label')
|
|
69
|
-
hash['description'] = Array(hash['description'])&.collect { |elem| sanitize_value(elem) } if hash.key?('description')
|
|
70
|
-
|
|
71
|
-
hash['sequences']&.each do |sequence|
|
|
72
|
-
sequence['canvases']&.each do |canvas|
|
|
73
|
-
canvas['label'] = sanitize_value(canvas['label'])
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
hash
|
|
60
|
+
hash = manifest.respond_to?(:inner_hash) ? manifest.inner_hash : JSON.parse(manifest.to_json)
|
|
61
|
+
deep_sanitize(hash)
|
|
78
62
|
end
|
|
79
63
|
|
|
80
64
|
##
|
|
81
65
|
# @api private
|
|
82
|
-
#
|
|
83
|
-
# @
|
|
84
|
-
|
|
85
|
-
|
|
66
|
+
# Recursively sanitizes all strings in a nested data structure
|
|
67
|
+
# @param obj [Object] the object to sanitize (Hash, Array, String, or other)
|
|
68
|
+
# @return [Object] sanitized version maintaining the original structure
|
|
69
|
+
def deep_sanitize(obj)
|
|
70
|
+
case obj
|
|
71
|
+
when Hash
|
|
72
|
+
obj.transform_values { |v| deep_sanitize(v) }
|
|
73
|
+
when Array
|
|
74
|
+
obj.map { |v| deep_sanitize(v) }
|
|
75
|
+
when String
|
|
76
|
+
CGI.unescapeHTML(Loofah.fragment(obj.to_s).scrub!(:prune).to_s)
|
|
77
|
+
else
|
|
78
|
+
obj
|
|
79
|
+
end
|
|
86
80
|
end
|
|
87
81
|
end
|
|
88
82
|
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hyrax
|
|
4
|
+
# Returns the canonical, UUID-based path for a Hyrax resource
|
|
5
|
+
# (e.g. '/concern/generic_works/<uuid>' or '/collections/<uuid>').
|
|
6
|
+
#
|
|
7
|
+
# Collections are routed by the Hyrax engine; works are routed by the
|
|
8
|
+
# host app's curation-concern resources, so the picker consults
|
|
9
|
+
# `resource.collection?` to choose the right route helper.
|
|
10
|
+
module PermalinkPath
|
|
11
|
+
module_function
|
|
12
|
+
|
|
13
|
+
# @param resource [#collection?] a Hyrax::Resource (work or collection)
|
|
14
|
+
# @return [String] the canonical path, e.g. '/concern/generic_works/<uuid>'
|
|
15
|
+
def call(resource)
|
|
16
|
+
helpers = collection_resource?(resource) ? Hyrax::Engine.routes.url_helpers : Rails.application.routes.url_helpers
|
|
17
|
+
helpers.polymorphic_path(resource)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def collection_resource?(resource)
|
|
21
|
+
resource.respond_to?(:collection?) && resource.collection?
|
|
22
|
+
end
|
|
23
|
+
private_class_method :collection_resource?
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -27,19 +27,22 @@ module Hyrax
|
|
|
27
27
|
#
|
|
28
28
|
# @raise [KeyError] when the key has no `active:` status
|
|
29
29
|
def active?(id)
|
|
30
|
-
authority.find(id)
|
|
30
|
+
result = authority.find(id)
|
|
31
|
+
return false if result.empty?
|
|
32
|
+
result&.fetch('active')
|
|
31
33
|
end
|
|
32
34
|
|
|
33
35
|
##
|
|
34
36
|
# @param id [String]
|
|
35
37
|
#
|
|
36
|
-
# @return [String] the label for the authority
|
|
38
|
+
# @return [String] the label for the authority, falling back to the id itself
|
|
39
|
+
# when no matching term exists. Callers may pass a block to override the
|
|
40
|
+
# fallback value.
|
|
37
41
|
#
|
|
38
42
|
# @yield when no 'term' value is present for the id
|
|
39
43
|
# @yieldreturn [String] an alternate label to return
|
|
40
|
-
#
|
|
41
|
-
# @raise [KeyError] when no 'term' value is present for the id
|
|
42
44
|
def label(id, &block)
|
|
45
|
+
block ||= ->(_key) { id }
|
|
43
46
|
authority.find(id).fetch('term', &block)
|
|
44
47
|
end
|
|
45
48
|
|
|
@@ -61,8 +64,9 @@ module Hyrax
|
|
|
61
64
|
# that this service knows about HTML rendering details. Maybe a factory
|
|
62
65
|
# is an appropriate next step?
|
|
63
66
|
def include_current_value(value, _index, render_options, html_options)
|
|
67
|
+
force_select = html_options[:class].is_a?(Array) ? [' force-select'] : ' force-select'
|
|
64
68
|
unless value.blank? || active?(value)
|
|
65
|
-
html_options[:class] +=
|
|
69
|
+
html_options[:class] += force_select
|
|
66
70
|
render_options += [[label(value) { value }, value]]
|
|
67
71
|
end
|
|
68
72
|
[render_options, html_options]
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hyrax
|
|
4
|
+
# Normalizes a user- or system-supplied redirect path into the canonical
|
|
5
|
+
# form stored in `hyrax_redirect_paths` and queried by the resolver.
|
|
6
|
+
# Single source of truth for "what does this path look like on disk?".
|
|
7
|
+
#
|
|
8
|
+
# Normalization rules:
|
|
9
|
+
# 1. If input parses as a URL with scheme/host, keep only the path component
|
|
10
|
+
# (drop scheme, host, port, userinfo, query, fragment).
|
|
11
|
+
# 2. Strip query strings and fragments from path-only inputs.
|
|
12
|
+
# 3. Ensure a leading slash.
|
|
13
|
+
# 4. Strip trailing slashes (but never reduce the path to empty).
|
|
14
|
+
#
|
|
15
|
+
# Idempotent: normalize(normalize(x)) == normalize(x).
|
|
16
|
+
#
|
|
17
|
+
# See documentation/redirects.md.
|
|
18
|
+
module RedirectPathNormalizer
|
|
19
|
+
module_function
|
|
20
|
+
|
|
21
|
+
def call(input)
|
|
22
|
+
return input if input.nil?
|
|
23
|
+
path = input.to_s.strip
|
|
24
|
+
return path if path.empty?
|
|
25
|
+
|
|
26
|
+
path = extract_path(path)
|
|
27
|
+
path = strip_query_and_fragment(path)
|
|
28
|
+
path = ensure_leading_slash(path)
|
|
29
|
+
path = strip_trailing_slashes(path)
|
|
30
|
+
path
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def extract_path(path)
|
|
34
|
+
return path unless path.match?(%r{\A[a-zA-Z][a-zA-Z0-9+.-]*://})
|
|
35
|
+
uri = URI.parse(path)
|
|
36
|
+
uri.path.presence || '/'
|
|
37
|
+
rescue URI::InvalidURIError
|
|
38
|
+
path
|
|
39
|
+
end
|
|
40
|
+
private_class_method :extract_path
|
|
41
|
+
|
|
42
|
+
def strip_query_and_fragment(path)
|
|
43
|
+
path.sub(/[?#].*\z/, '')
|
|
44
|
+
end
|
|
45
|
+
private_class_method :strip_query_and_fragment
|
|
46
|
+
|
|
47
|
+
def ensure_leading_slash(path)
|
|
48
|
+
path.start_with?('/') ? path : "/#{path}"
|
|
49
|
+
end
|
|
50
|
+
private_class_method :ensure_leading_slash
|
|
51
|
+
|
|
52
|
+
def strip_trailing_slashes(path)
|
|
53
|
+
stripped = path.sub(/\/+\z/, '')
|
|
54
|
+
stripped.empty? ? '/' : stripped
|
|
55
|
+
end
|
|
56
|
+
private_class_method :strip_trailing_slashes
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hyrax
|
|
4
|
+
# Single point of truth for read-side queries against the
|
|
5
|
+
# `hyrax_redirect_paths` table. The unique index on `from_path` makes
|
|
6
|
+
# both lookups (`.find_row` and `.taken?`) indexed equality checks on a
|
|
7
|
+
# small derived table — sub-millisecond against any reasonable load.
|
|
8
|
+
#
|
|
9
|
+
# See documentation/redirects.md.
|
|
10
|
+
class RedirectsLookup
|
|
11
|
+
# Returns true if any row exists with the given `from_path`, optionally
|
|
12
|
+
# excluding rows owned by `except_id`. Used by `Hyrax::RedirectValidator`
|
|
13
|
+
# at form-submit time to surface "this alias is already in use" before
|
|
14
|
+
# the DB unique index would reject the insert.
|
|
15
|
+
#
|
|
16
|
+
# @param path [String] the alias to check, normalized or not
|
|
17
|
+
# @param except_id [String, nil] resource_id to exclude from the check
|
|
18
|
+
# @return [Boolean]
|
|
19
|
+
def self.taken?(path, except_id: nil)
|
|
20
|
+
new(path, except_id: except_id).taken?
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Returns the `Hyrax::RedirectPath` row matching the given `from_path`,
|
|
24
|
+
# or nil when no row matches. Used by request-time resolvers
|
|
25
|
+
# (`Hyrax::RedirectsController` and the `Hyrax::RedirectToDisplayUrl`
|
|
26
|
+
# before_action) to decide whether the visited path triggers a
|
|
27
|
+
# redirect or in-process dispatch.
|
|
28
|
+
#
|
|
29
|
+
# @param path [String] the visited path, normalized or not
|
|
30
|
+
# @return [Hyrax::RedirectPath, nil]
|
|
31
|
+
def self.find_row(path)
|
|
32
|
+
normalized = Hyrax::RedirectPathNormalizer.call(path)
|
|
33
|
+
return nil if normalized.blank?
|
|
34
|
+
Hyrax::RedirectPath.find_by(from_path: normalized)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Returns the `from_path` of the row marked as the resource's display
|
|
38
|
+
# URL, or nil when no row is marked.
|
|
39
|
+
#
|
|
40
|
+
# @param resource_id [String]
|
|
41
|
+
# @return [String, nil]
|
|
42
|
+
def self.display_path_for(resource_id)
|
|
43
|
+
return nil if resource_id.blank?
|
|
44
|
+
Hyrax::RedirectPath.where(resource_id: resource_id, is_display_url: true).limit(1).pick(:from_path)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def initialize(path, except_id: nil)
|
|
48
|
+
@path = Hyrax::RedirectPathNormalizer.call(path)
|
|
49
|
+
@except_id = except_id
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def taken?
|
|
53
|
+
return false if @path.blank?
|
|
54
|
+
scope = Hyrax::RedirectPath.where(from_path: @path)
|
|
55
|
+
scope = scope.where.not(resource_id: @except_id) if @except_id.present?
|
|
56
|
+
scope.exists?
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hyrax
|
|
4
|
+
##
|
|
5
|
+
# Propagates visibility from a valkyrie Work to its FileSets
|
|
6
|
+
class ResourcePermissionsVisibilityPropagator
|
|
7
|
+
##
|
|
8
|
+
# @!attribute [rw] source
|
|
9
|
+
# @return [#visibility]
|
|
10
|
+
attr_accessor :source
|
|
11
|
+
|
|
12
|
+
##
|
|
13
|
+
# @!attribute [r] embargo_manager
|
|
14
|
+
# @return [Hyrax::EmbargoManager]
|
|
15
|
+
# @!attribute [r] lease_manager
|
|
16
|
+
# @return [Hyrax::LeaseManager]
|
|
17
|
+
# @!attribute [r] persister
|
|
18
|
+
# @return [#save]
|
|
19
|
+
# @!attribute [r] queries
|
|
20
|
+
# @return [Valkyrie::Persistence::CustomQueryContainer]
|
|
21
|
+
attr_reader :embargo_manager, :lease_manager, :persister, :queries
|
|
22
|
+
|
|
23
|
+
##
|
|
24
|
+
# @param source [#visibility] the object to propagate visibility from
|
|
25
|
+
def initialize(source:,
|
|
26
|
+
embargo_manager: Hyrax::EmbargoManager,
|
|
27
|
+
lease_manager: Hyrax::LeaseManager,
|
|
28
|
+
persister: Hyrax.persister,
|
|
29
|
+
queries: Hyrax.custom_queries)
|
|
30
|
+
@persister = persister
|
|
31
|
+
@queries = queries
|
|
32
|
+
self.source = source
|
|
33
|
+
@embargo_manager = embargo_manager.new(resource: source)
|
|
34
|
+
@lease_manager = lease_manager.new(resource: source)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
##
|
|
38
|
+
# @return [void]
|
|
39
|
+
#
|
|
40
|
+
# @raise [RuntimeError] if visibility propagation fails
|
|
41
|
+
def propagate
|
|
42
|
+
queries.find_child_file_sets(resource: source).each do |file_set|
|
|
43
|
+
file_set.visibility = source.visibility
|
|
44
|
+
embargo_manager.copy_embargo_to(target: file_set)
|
|
45
|
+
lease_manager.copy_lease_to(target: file_set)
|
|
46
|
+
|
|
47
|
+
Hyrax::AccessControlList
|
|
48
|
+
.copy_permissions(source: source, target: file_set)
|
|
49
|
+
file_set.permission_manager.acl.save
|
|
50
|
+
persister.save(resource: file_set)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -1,26 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
module Hyrax
|
|
3
3
|
module ResourceTypesService
|
|
4
|
-
|
|
5
|
-
self.authority = Qa::Authorities::Local.subauthority_for('resource_types')
|
|
4
|
+
extend Hyrax::AuthorityService
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
[element[:label], element[:id]]
|
|
10
|
-
end
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def self.label(id)
|
|
14
|
-
authority.find(id).fetch('term')
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
##
|
|
18
|
-
# @param [String, nil] id identifier of the resource type
|
|
19
|
-
#
|
|
20
|
-
# @return [String] a schema.org type. Gives the default type if `id` is nil.
|
|
21
|
-
def self.microdata_type(id)
|
|
22
|
-
return Hyrax.config.microdata_default_type if id.nil?
|
|
23
|
-
Microdata.fetch("resource_type.#{id}", default: Hyrax.config.microdata_default_type)
|
|
24
|
-
end
|
|
6
|
+
authority_name 'resource_types'
|
|
7
|
+
microdata_namespace 'resource_type.'
|
|
25
8
|
end
|
|
26
9
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
module Hyrax
|
|
3
3
|
# Provide select options for the copyright status (edm:rights) field
|
|
4
|
-
class RightsStatementService <
|
|
4
|
+
class RightsStatementService < TolerantSelectService
|
|
5
5
|
def initialize(_authority_name = nil)
|
|
6
6
|
super('rights_statements')
|
|
7
7
|
end
|