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,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
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hyrax
|
|
4
|
+
##
|
|
5
|
+
# @api private
|
|
6
|
+
#
|
|
7
|
+
# This is a simple yaml config-driven schema loader
|
|
8
|
+
#
|
|
9
|
+
# @see config/metadata/basic_metadata.yaml for an example configuration
|
|
10
|
+
class SchemaLoader
|
|
11
|
+
class UndefinedSchemaError < ArgumentError; end
|
|
12
|
+
|
|
13
|
+
##
|
|
14
|
+
# @param [Symbol] schema
|
|
15
|
+
#
|
|
16
|
+
# @return [Hash<Symbol, Dry::Types::Type>] a map from attribute names to
|
|
17
|
+
# types
|
|
18
|
+
def attributes_for(schema:, version: 1, contexts: nil)
|
|
19
|
+
definitions(schema, version, contexts).each_with_object({}) do |definition, hash|
|
|
20
|
+
hash[definition.name] = definition.type.meta(definition.config)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
##
|
|
25
|
+
# @param [Symbol] schema
|
|
26
|
+
#
|
|
27
|
+
# @return [Hash{Symbol => Hash{Symbol => Object}}]
|
|
28
|
+
def form_definitions_for(schema:, version: 1, contexts: nil)
|
|
29
|
+
definitions(schema, version, contexts).each_with_object({}) do |definition, hash|
|
|
30
|
+
next if definition.form_options.empty?
|
|
31
|
+
|
|
32
|
+
hash[definition.name] = definition.form_options
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
##
|
|
37
|
+
# @param [Symbol] schema
|
|
38
|
+
#
|
|
39
|
+
# @return [{Symbol => Symbol}] a map from index keys to attribute names
|
|
40
|
+
def index_rules_for(schema:, version: 1, contexts: nil)
|
|
41
|
+
definitions(schema, version, contexts).each_with_object({}) do |definition, hash|
|
|
42
|
+
definition.index_keys.each do |key|
|
|
43
|
+
hash[key] = definition.name
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def current_version
|
|
49
|
+
1
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
##
|
|
53
|
+
# @api private
|
|
54
|
+
class AttributeDefinition
|
|
55
|
+
##
|
|
56
|
+
# @!attr_reader :config
|
|
57
|
+
# @return [Hash<String, Object>]
|
|
58
|
+
# @!attr_reader :name
|
|
59
|
+
# @return [#to_sym]
|
|
60
|
+
attr_reader :config, :name
|
|
61
|
+
|
|
62
|
+
##
|
|
63
|
+
# @param [#to_sym] name
|
|
64
|
+
# @param [Hash<String, Object>] config
|
|
65
|
+
def initialize(name, config)
|
|
66
|
+
@config = config
|
|
67
|
+
@name = (config['name'] || name).to_sym
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
##
|
|
71
|
+
# @return [Hash{Symbol => Object}]
|
|
72
|
+
def form_options
|
|
73
|
+
config.fetch('form', {})&.symbolize_keys || {}
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
##
|
|
77
|
+
# @return [Enumerable<Symbol>]
|
|
78
|
+
def index_keys
|
|
79
|
+
(config.fetch('indexing', nil) || config.fetch('index_keys', []))&.reject { |k| ['facetable', 'stored_searchable', 'admin_only', 'editor_only'].include?(k) }&.map(&:to_sym) || []
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
##
|
|
83
|
+
# @return [Hash{Symbol => Object}]
|
|
84
|
+
def view_options
|
|
85
|
+
# prefer display_label over view:label for labels, make available in the view
|
|
86
|
+
@view_options = config.fetch('view', {})&.with_indifferent_access || {}
|
|
87
|
+
Deprecation.warn('view: label is deprecated, use display_label instead') if @view_options[:label].present?
|
|
88
|
+
@view_options.delete(:label)
|
|
89
|
+
@view_options[:display_label] = display_label
|
|
90
|
+
@view_options[:admin_only] = admin_only?
|
|
91
|
+
@view_options[:editor_only] = editor_only?
|
|
92
|
+
@view_options
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def display_label
|
|
96
|
+
return @display_label if @display_label
|
|
97
|
+
@display_label = config.fetch('display_label', {})&.with_indifferent_access || {}
|
|
98
|
+
@display_label = { default: @display_label } if @display_label.is_a?(String)
|
|
99
|
+
@display_label
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def admin_only?
|
|
103
|
+
@admin_only ||= config.fetch('admin_only', false) || config['indexing']&.include?('admin_only')
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def editor_only?
|
|
107
|
+
@editor_only ||= config.fetch('editor_only', false) || config['indexing']&.include?('editor_only')
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
##
|
|
111
|
+
# @return [Dry::Types::Type]
|
|
112
|
+
def type
|
|
113
|
+
member_type = type_for(config['type'])
|
|
114
|
+
wrapper_type = multiple? ? Valkyrie::Types::Array.constructor(&Coerce) : Identity
|
|
115
|
+
wrapper_type.of(member_type)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Cleans up the input before the type system sees it: drops the
|
|
119
|
+
# "no value provided" placeholder dry-types uses internally, then
|
|
120
|
+
# removes blanks. Wraps a bare Hash in a one-element array; using
|
|
121
|
+
# `Array(hash)` would surprise-flatten it into [[:k, v], ...] pairs.
|
|
122
|
+
# Valkyrie's JSONValueMapper unwraps single-element arrays on read,
|
|
123
|
+
# so the type sees a hash here when there was originally one entry.
|
|
124
|
+
Coerce = lambda do |value|
|
|
125
|
+
return [] if value.equal?(Dry::Types::Undefined)
|
|
126
|
+
wrapped = value.is_a?(::Hash) ? [value] : Array(value)
|
|
127
|
+
wrapped.reject { |v| v.equal?(Dry::Types::Undefined) }.select(&:present?)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Determine whether this attribute allows multiple values.
|
|
131
|
+
def multiple?
|
|
132
|
+
return config['multiple'] if config.key?('multiple')
|
|
133
|
+
return true if config.key?('data_type') && config['data_type'] == 'array'
|
|
134
|
+
return false unless (card = config['cardinality'])
|
|
135
|
+
|
|
136
|
+
max = card['maximum']
|
|
137
|
+
max.nil? || max.to_i > 1
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
##
|
|
141
|
+
# @api private
|
|
142
|
+
#
|
|
143
|
+
# Single-value wrapper that matches the multi-value branch's cleanup:
|
|
144
|
+
# strips the dry-types Undefined placeholder and coerces blank strings to nil.
|
|
145
|
+
# Booleans, numbers, and other types pass through unchanged.
|
|
146
|
+
#
|
|
147
|
+
# @example
|
|
148
|
+
# Identity.of(Valkyrie::Types::String) # => Valkyrie::Types::String with blank-string → nil coercion
|
|
149
|
+
class Identity
|
|
150
|
+
def self.of(type)
|
|
151
|
+
type.constructor do |value|
|
|
152
|
+
next nil if value.equal?(Dry::Types::Undefined)
|
|
153
|
+
value.is_a?(String) ? value.presence : value
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
private
|
|
159
|
+
|
|
160
|
+
##
|
|
161
|
+
# Resolves a `type:` value from a schema YAML to a Dry::Types::Type.
|
|
162
|
+
#
|
|
163
|
+
# Recognized values:
|
|
164
|
+
# - `id`, `uri`, `date_time` — Valkyrie type shortcuts.
|
|
165
|
+
# - `hash` — for attributes whose entries carry multiple sub-fields
|
|
166
|
+
# (e.g. redirects, with path / canonical / sequence). Use this
|
|
167
|
+
# instead of nesting a Valkyrie::Resource. See
|
|
168
|
+
# `documentation/redirects.md` for a worked example.
|
|
169
|
+
# - Any primitive Valkyrie type, looked up under `Valkyrie::Types::*`
|
|
170
|
+
# by classified name (e.g. `string` → `Valkyrie::Types::String`).
|
|
171
|
+
#
|
|
172
|
+
# Raises `ArgumentError` if nothing matches.
|
|
173
|
+
#
|
|
174
|
+
# @param [String]
|
|
175
|
+
# @return [Dry::Types::Type]
|
|
176
|
+
def type_for(type)
|
|
177
|
+
case type
|
|
178
|
+
when 'id'
|
|
179
|
+
Valkyrie::Types::ID
|
|
180
|
+
when 'uri'
|
|
181
|
+
Valkyrie::Types::URI
|
|
182
|
+
when 'date_time'
|
|
183
|
+
Valkyrie::Types::DateTime
|
|
184
|
+
when 'hash'
|
|
185
|
+
Dry::Types['hash']
|
|
186
|
+
else
|
|
187
|
+
"Valkyrie::Types::#{type.classify}".safe_constantize ||
|
|
188
|
+
raise(ArgumentError, "Unrecognized type: #{type}")
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
class UndefinedSchemaError < ArgumentError; end
|
|
194
|
+
|
|
195
|
+
private
|
|
196
|
+
|
|
197
|
+
def definitions(_schema_name, _version, _contexts)
|
|
198
|
+
raise NotImplementedError, 'Implement #definitions in a child class'
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def config_search_paths
|
|
202
|
+
Hyrax.config.schema_loader_config_search_paths
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
end
|
|
@@ -10,7 +10,7 @@ module Hyrax
|
|
|
10
10
|
|
|
11
11
|
def method_missing(method_name, *arguments, &block)
|
|
12
12
|
if scope&.respond_to?(method_name)
|
|
13
|
-
Deprecation.warn(
|
|
13
|
+
Deprecation.warn("Calling `#{method_name}` on scope " \
|
|
14
14
|
'is deprecated and will be removed in Blacklight 8. Call #to_h first if you ' \
|
|
15
15
|
' need to use hash methods (or, preferably, use your own SearchState implementation)')
|
|
16
16
|
scope&.public_send(method_name, *arguments, &block)
|