hyrax 3.3.0 → 3.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (255) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +26 -17
  3. data/.dassie/.env +2 -1
  4. data/.dassie/Gemfile +1 -1
  5. data/.dassie/app/forms/collection_resource_form.rb +8 -0
  6. data/.dassie/app/indexers/collection_resource_indexer.rb +8 -0
  7. data/.dassie/app/models/collection_resource.rb +35 -0
  8. data/.dassie/config/initializers/file_services.rb +4 -0
  9. data/.dassie/config/initializers/hyrax.rb +12 -1
  10. data/.dassie/config/metadata/collection_resource.yaml +23 -0
  11. data/.dassie/db/seeds.rb +74 -17
  12. data/.dassie/spec/forms/collection_resource_form_spec.rb +13 -0
  13. data/.dassie/spec/indexers/collection_resource_indexer_spec.rb +14 -0
  14. data/.dassie/spec/models/collection_resource_spec.rb +13 -0
  15. data/.github/release.yml +26 -0
  16. data/.gitignore +3 -0
  17. data/.regen +1 -1
  18. data/.rubocop.yml +1 -1
  19. data/.rubocop_fixme.yml +22 -3
  20. data/CONTAINERS.md +18 -13
  21. data/Dockerfile +4 -3
  22. data/app/actors/hyrax/actors/file_actor.rb +6 -4
  23. data/app/actors/hyrax/actors/transfer_request_actor.rb +3 -7
  24. data/app/assets/javascripts/hyrax/analytics_events.js +8 -2
  25. data/app/assets/javascripts/hyrax/autocomplete/linked_data.es6 +1 -3
  26. data/app/assets/javascripts/hyrax/collections_v2.es6 +13 -0
  27. data/app/controllers/concerns/hyrax/collections_controller_behavior.rb +1 -3
  28. data/app/controllers/concerns/hyrax/controller.rb +21 -0
  29. data/app/controllers/concerns/hyrax/works_controller_behavior.rb +83 -59
  30. data/app/controllers/hyrax/admin/admin_sets_controller.rb +105 -19
  31. data/app/controllers/hyrax/admin/permission_template_accesses_controller.rb +12 -19
  32. data/app/controllers/hyrax/batch_edits_controller.rb +12 -3
  33. data/app/controllers/hyrax/batch_uploads_controller.rb +4 -0
  34. data/app/controllers/hyrax/citations_controller.rb +1 -1
  35. data/app/controllers/hyrax/dashboard/collections_controller.rb +176 -83
  36. data/app/controllers/hyrax/single_use_links_viewer_controller.rb +1 -1
  37. data/app/forms/hyrax/forms/administrative_set_form.rb +19 -1
  38. data/app/forms/hyrax/forms/batch_edit_form.rb +1 -1
  39. data/app/forms/hyrax/forms/collection_form.rb +1 -1
  40. data/app/forms/hyrax/forms/dashboard/nest_collection_form.rb +21 -6
  41. data/app/forms/hyrax/forms/pcdm_collection_form.rb +30 -2
  42. data/app/forms/hyrax/forms/permission_template_form.rb +17 -9
  43. data/app/forms/hyrax/forms/resource_form.rb +23 -5
  44. data/app/forms/hyrax/forms/widgets/admin_set_visibility.rb +1 -1
  45. data/app/helpers/hyrax/collections_helper.rb +14 -0
  46. data/app/helpers/hyrax/membership_helper.rb +1 -1
  47. data/app/helpers/hyrax/trophy_helper.rb +1 -1
  48. data/app/helpers/hyrax/url_helper.rb +1 -1
  49. data/app/indexers/hyrax/administrative_set_indexer.rb +8 -2
  50. data/app/indexers/hyrax/deep_indexing_service.rb +1 -1
  51. data/app/indexers/hyrax/file_set_indexer.rb +1 -0
  52. data/app/indexers/hyrax/pcdm_collection_indexer.rb +3 -2
  53. data/app/indexers/hyrax/thumbnail_indexer.rb +31 -0
  54. data/app/indexers/hyrax/valkyrie_file_set_indexer.rb +6 -6
  55. data/app/indexers/hyrax/valkyrie_indexer.rb +4 -2
  56. data/app/indexers/hyrax/valkyrie_work_indexer.rb +13 -0
  57. data/app/inputs/controlled_vocabulary_input.rb +2 -0
  58. data/app/jobs/change_depositor_event_job.rb +47 -0
  59. data/app/jobs/characterize_job.rb +43 -3
  60. data/app/jobs/concerns/hyrax/members_permission_job_behavior.rb +1 -1
  61. data/app/jobs/content_depositor_change_event_job.rb +2 -1
  62. data/app/jobs/hyrax/propagate_change_depositor_job.rb +32 -0
  63. data/app/jobs/import_url_job.rb +4 -6
  64. data/app/jobs/inherit_permissions_job.rb +1 -1
  65. data/app/jobs/valkyrie_create_derivatives_job.rb +25 -0
  66. data/app/jobs/valkyrie_ingest_job.rb +41 -35
  67. data/app/models/admin_set.rb +10 -2
  68. data/app/models/collection_branding_info.rb +8 -6
  69. data/app/models/concerns/hyrax/collection_behavior.rb +3 -3
  70. data/app/models/concerns/hyrax/file_set/characterization.rb +7 -1
  71. data/app/models/concerns/hyrax/solr_document/metadata.rb +1 -0
  72. data/app/models/concerns/hyrax/solr_document_behavior.rb +9 -3
  73. data/app/models/concerns/hyrax/user.rb +11 -0
  74. data/app/models/concerns/hyrax/work_behavior.rb +1 -1
  75. data/app/models/featured_work_list.rb +0 -1
  76. data/app/models/hyrax/administrative_set.rb +36 -1
  77. data/app/models/hyrax/collection_type.rb +2 -2
  78. data/app/models/hyrax/file_metadata.rb +37 -3
  79. data/app/models/hyrax/file_set.rb +43 -4
  80. data/app/models/hyrax/group.rb +19 -0
  81. data/app/models/hyrax/pcdm_collection.rb +56 -1
  82. data/app/models/hyrax/permission_template.rb +11 -5
  83. data/app/models/hyrax/work.rb +91 -0
  84. data/app/models/job_io_wrapper.rb +1 -1
  85. data/app/models/proxy_deposit_request.rb +1 -1
  86. data/app/presenters/hyrax/admin_set_presenter.rb +2 -2
  87. data/app/presenters/hyrax/member_presenter_factory.rb +2 -4
  88. data/app/presenters/hyrax/pcdm_member_presenter_factory.rb +2 -2
  89. data/app/presenters/hyrax/work_show_presenter.rb +10 -6
  90. data/app/search_builders/hyrax/dashboard/collections_search_builder.rb +2 -2
  91. data/app/search_builders/hyrax/dashboard/managed_search_filters.rb +44 -4
  92. data/app/search_builders/hyrax/dashboard/nested_collections_search_builder.rb +2 -2
  93. data/app/search_builders/hyrax/my/collections_search_builder.rb +11 -4
  94. data/app/services/hyrax/access_control_list.rb +20 -6
  95. data/app/services/hyrax/adapters/nesting_index_adapter.rb +3 -3
  96. data/app/services/hyrax/admin_set_create_service.rb +21 -37
  97. data/app/services/hyrax/change_content_depositor_service.rb +2 -2
  98. data/app/services/hyrax/change_depositor_service.rb +70 -0
  99. data/app/services/hyrax/characterization/valkyrie_characterization_service.rb +4 -6
  100. data/app/services/hyrax/collections/collection_member_service.rb +3 -5
  101. data/app/services/hyrax/collections/nested_collection_query_service.rb +24 -12
  102. data/app/services/hyrax/custom_queries/navigators/child_file_sets_navigator.rb +45 -0
  103. data/app/services/hyrax/custom_queries/navigators/child_filesets_navigator.rb +7 -2
  104. data/app/services/hyrax/custom_queries/navigators/parent_work_navigator.rb +54 -0
  105. data/app/services/hyrax/default_middleware_stack.rb +3 -0
  106. data/app/services/hyrax/file_set_derivatives_service.rb +21 -2
  107. data/app/services/hyrax/file_set_type_service.rb +2 -5
  108. data/app/services/hyrax/listeners/file_metadata_listener.rb +31 -1
  109. data/app/services/hyrax/listeners/member_cleanup_listener.rb +27 -11
  110. data/app/services/hyrax/listeners/metadata_index_listener.rb +39 -0
  111. data/app/services/hyrax/listeners/proxy_deposit_listener.rb +14 -8
  112. data/app/services/hyrax/location_service.rb +33 -0
  113. data/app/services/hyrax/multiple_membership_checker.rb +46 -1
  114. data/app/services/hyrax/resource_visibility_propagator.rb +1 -1
  115. data/app/services/hyrax/simple_schema_loader.rb +5 -1
  116. data/app/services/hyrax/solr_query_service.rb +12 -7
  117. data/app/services/hyrax/thumbnail_path_service.rb +1 -1
  118. data/app/services/hyrax/valkyrie_persist_derivatives.rb +50 -0
  119. data/app/services/hyrax/valkyrie_upload.rb +94 -0
  120. data/app/services/hyrax/work_uploads_handler.rb +0 -10
  121. data/app/services/hyrax/workflow/workflow_importer.rb +7 -9
  122. data/app/services/hyrax/workflow/workflow_schema.rb +3 -5
  123. data/app/strategies/hyrax/strategies/yaml_strategy.rb +4 -6
  124. data/app/uploaders/hyrax/uploaded_file_uploader.rb +4 -4
  125. data/app/utils/hyrax/data_destroyers/collection_branding_destroyer.rb +29 -0
  126. data/app/utils/hyrax/data_destroyers/collection_types_destroyer.rb +26 -0
  127. data/app/utils/hyrax/data_destroyers/default_admin_set_id_cache_destroyer.rb +26 -0
  128. data/app/utils/hyrax/data_destroyers/featured_works_destroyer.rb +27 -0
  129. data/app/utils/hyrax/data_destroyers/permission_templates_destroyer.rb +30 -0
  130. data/app/utils/hyrax/data_destroyers/repository_metadata_destroyer.rb +42 -0
  131. data/app/utils/hyrax/data_destroyers/stats_destroyer.rb +33 -0
  132. data/app/utils/hyrax/data_maintenance.rb +51 -0
  133. data/app/utils/hyrax/required_data_seeder.rb +21 -0
  134. data/app/utils/hyrax/required_data_seeders/collection_seeder.rb +26 -0
  135. data/app/utils/hyrax/required_data_seeders/collection_type_seeder.rb +36 -0
  136. data/app/utils/hyrax/test_data_seeder.rb +24 -0
  137. data/app/utils/hyrax/test_data_seeders/collection_seeder.rb +91 -0
  138. data/app/utils/hyrax/test_data_seeders/collection_type_seeder.rb +72 -0
  139. data/app/utils/hyrax/test_data_seeders/user_seeder.rb +52 -0
  140. data/app/validators/hyrax/collection_membership_validator.rb +39 -0
  141. data/app/views/catalog/_index_header_list_default.html.erb +8 -1
  142. data/app/views/catalog/_thumbnail_list_default.html.erb +8 -3
  143. data/app/views/collections/edit_fields/_based_near.html.erb +7 -7
  144. data/app/views/hyrax/admin/admin_sets/_form_participant_table.html.erb +2 -2
  145. data/app/views/hyrax/admin/admin_sets/_form_participants.html.erb +2 -2
  146. data/app/views/hyrax/admin/admin_sets/_form_visibility.html.erb +2 -2
  147. data/app/views/hyrax/admin/admin_sets/_form_workflow.erb +1 -1
  148. data/app/views/hyrax/admin/collection_types/index.html.erb +1 -1
  149. data/app/views/hyrax/base/_form.html.erb +1 -1
  150. data/app/views/hyrax/base/_form_child_work_relationships.html.erb +1 -1
  151. data/app/views/hyrax/dashboard/collections/_default_group.html.erb +2 -2
  152. data/app/views/hyrax/dashboard/collections/_form.html.erb +24 -17
  153. data/app/views/hyrax/dashboard/collections/_form_branding.html.erb +1 -0
  154. data/app/views/hyrax/dashboard/collections/_form_discovery.html.erb +6 -3
  155. data/app/views/hyrax/dashboard/collections/_form_share.html.erb +2 -2
  156. data/app/views/hyrax/dashboard/collections/_form_share_table.html.erb +3 -3
  157. data/app/views/hyrax/dashboard/collections/_list_collections.html.erb +2 -2
  158. data/app/views/hyrax/dashboard/sidebar/_activity.html.erb +1 -1
  159. data/app/views/hyrax/dashboard/works/_default_group.html.erb +1 -1
  160. data/app/views/hyrax/dashboard/works/_list_works.html.erb +1 -1
  161. data/app/views/hyrax/file_sets/_actions.html.erb +2 -2
  162. data/app/views/hyrax/my/_facet_pagination.html.erb +12 -9
  163. data/app/views/hyrax/my/_work_action_menu.html.erb +8 -9
  164. data/app/views/hyrax/my/collections/_default_group.html.erb +2 -2
  165. data/app/views/hyrax/my/collections/_list_collections.html.erb +2 -2
  166. data/app/views/hyrax/my/collections/index.html.erb +3 -2
  167. data/app/views/hyrax/my/works/_default_group.html.erb +1 -1
  168. data/app/views/hyrax/my/works/_list_works.html.erb +1 -2
  169. data/app/views/hyrax/my/works/_tabs.html.erb +6 -1
  170. data/app/views/hyrax/my/works/index.html.erb +4 -2
  171. data/chart/hyrax/Chart.yaml +11 -7
  172. data/chart/hyrax/README.md +22 -1
  173. data/chart/hyrax/templates/_helpers.tpl +4 -0
  174. data/chart/hyrax/templates/cron-embargo.yaml +5 -0
  175. data/chart/hyrax/templates/cron-lease.yaml +5 -0
  176. data/chart/hyrax/templates/deployment-worker.yaml +11 -0
  177. data/chart/hyrax/templates/ingress.yaml +7 -6
  178. data/chart/hyrax/values.yaml +152 -0
  179. data/config/features.rb +48 -50
  180. data/config/initializers/listeners.rb +0 -1
  181. data/config/initializers/{valkryrie_storage.rb → storage_adapter_initializer.rb} +5 -0
  182. data/config/locales/hyrax.de.yml +18 -17
  183. data/config/locales/hyrax.en.yml +30 -28
  184. data/config/locales/hyrax.es.yml +10 -9
  185. data/config/locales/hyrax.fr.yml +2 -1
  186. data/config/locales/hyrax.it.yml +3 -2
  187. data/config/locales/hyrax.pt-BR.yml +2 -1
  188. data/config/locales/hyrax.zh.yml +2 -1
  189. data/config/metadata/basic_metadata.yaml +2 -0
  190. data/config/metadata/core_metadata.yaml +1 -1
  191. data/docker-compose.yml +47 -42
  192. data/documentation/developing-your-hyrax-based-app.md +1 -1
  193. data/documentation/legacyREADME.md +1 -1
  194. data/hyrax.gemspec +5 -3
  195. data/lib/generators/hyrax/collection_resource/USAGE +20 -0
  196. data/lib/generators/hyrax/collection_resource/collection_resource_generator.rb +133 -0
  197. data/lib/generators/hyrax/collection_resource/templates/collection.rb.erb +34 -0
  198. data/lib/generators/hyrax/collection_resource/templates/collection_form.rb.erb +7 -0
  199. data/lib/generators/hyrax/collection_resource/templates/collection_form_spec.rb.erb +13 -0
  200. data/lib/generators/hyrax/collection_resource/templates/collection_indexer.rb.erb +7 -0
  201. data/lib/generators/hyrax/collection_resource/templates/collection_indexer_spec.rb.erb +13 -0
  202. data/lib/generators/hyrax/collection_resource/templates/collection_metadata.yaml +22 -0
  203. data/lib/generators/hyrax/collection_resource/templates/collection_spec.rb.erb +12 -0
  204. data/lib/generators/hyrax/install_generator.rb +9 -0
  205. data/lib/hyrax/administrative_set_name.rb +18 -0
  206. data/lib/hyrax/collection_name.rb +2 -0
  207. data/lib/hyrax/configuration.rb +22 -0
  208. data/lib/hyrax/controlled_vocabularies/location.rb +9 -2
  209. data/lib/hyrax/controlled_vocabularies/resource_label_caching.rb +42 -0
  210. data/lib/hyrax/controlled_vocabularies.rb +1 -0
  211. data/lib/hyrax/publisher.rb +49 -0
  212. data/lib/hyrax/schema.rb +16 -13
  213. data/lib/hyrax/specs/capybara.rb +1 -1
  214. data/lib/hyrax/specs/shared_specs/hydra_works.rb +11 -5
  215. data/lib/hyrax/specs/shared_specs/indexers.rb +117 -3
  216. data/lib/hyrax/transactions/admin_set_create.rb +2 -1
  217. data/lib/hyrax/transactions/admin_set_destroy.rb +22 -0
  218. data/lib/hyrax/transactions/admin_set_update.rb +21 -0
  219. data/lib/hyrax/transactions/collection_destroy.rb +22 -0
  220. data/lib/hyrax/transactions/collection_update.rb +5 -2
  221. data/lib/hyrax/transactions/container.rb +97 -23
  222. data/lib/hyrax/transactions/create_work.rb +3 -0
  223. data/lib/hyrax/transactions/destroy_work.rb +3 -0
  224. data/lib/hyrax/transactions/steps/apply_collection_permission_template.rb +2 -0
  225. data/lib/hyrax/transactions/steps/apply_permission_template.rb +2 -0
  226. data/lib/hyrax/transactions/steps/apply_visibility.rb +2 -0
  227. data/lib/hyrax/transactions/steps/change_depositor.rb +46 -0
  228. data/lib/hyrax/transactions/steps/check_for_empty_admin_set.rb +36 -0
  229. data/lib/hyrax/transactions/steps/delete_access_control.rb +32 -0
  230. data/lib/hyrax/transactions/steps/delete_resource.rb +19 -3
  231. data/lib/hyrax/transactions/steps/destroy_work.rb +3 -1
  232. data/lib/hyrax/transactions/steps/ensure_permission_template.rb +2 -0
  233. data/lib/hyrax/transactions/steps/save.rb +24 -6
  234. data/lib/hyrax/transactions/steps/save_access_control.rb +2 -2
  235. data/lib/hyrax/transactions/steps/save_collection_banner.rb +59 -0
  236. data/lib/hyrax/transactions/steps/save_collection_logo.rb +109 -0
  237. data/lib/hyrax/transactions/steps/save_work.rb +3 -0
  238. data/lib/hyrax/transactions/steps/set_user_as_creator.rb +41 -0
  239. data/lib/hyrax/transactions/steps/update_work_members.rb +51 -0
  240. data/lib/hyrax/transactions/update_work.rb +4 -3
  241. data/lib/hyrax/transactions/work_create.rb +1 -1
  242. data/lib/hyrax/transactions/work_destroy.rb +2 -1
  243. data/lib/hyrax/transactions/work_update.rb +19 -0
  244. data/lib/hyrax/version.rb +1 -1
  245. data/lib/wings/active_fedora_converter/file_metadata_node.rb +48 -0
  246. data/lib/wings/active_fedora_converter/instance_builder.rb +68 -0
  247. data/lib/wings/active_fedora_converter.rb +3 -3
  248. data/lib/wings/attribute_transformer.rb +5 -1
  249. data/lib/wings/services/custom_queries/find_file_metadata.rb +19 -8
  250. data/lib/wings/setup.rb +3 -1
  251. data/lib/wings/valkyrie/persister.rb +2 -0
  252. data/lib/wings/valkyrie/query_service.rb +6 -7
  253. data/lib/wings/valkyrie/storage.rb +7 -1
  254. data/template.rb +1 -1
  255. metadata +99 -12
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+ module Hyrax
3
+ module TestDataSeeders
4
+ # This class was created for use in rake tasks and db/seeds.rb. It generates
5
+ # collection that can be used in release testing. This data can also be helpful
6
+ # for local development testing.
7
+ #
8
+ # Adding collections is non-destructive. But it may create an additional
9
+ # collection of the same.
10
+ #
11
+ # @todo Do we want to assume that if a collection of the same name exists, then
12
+ # it is the collection we want for release testing?
13
+ class CollectionSeeder
14
+ class << self
15
+ attr_accessor :logger
16
+
17
+ def generate_seeds(logger: Logger.new(STDOUT), allow_seeding_in_production: false) # rubocop:disable Metrics/AbcSize
18
+ raise("TestDataSeeders are not for use in production!") if Rails.env.production? && !allow_seeding_in_production
19
+ @logger = logger
20
+
21
+ logger.info("Adding collections...")
22
+
23
+ create_collection("Grand Parent Collection", collection_types['Nestable only'])
24
+ create_collection("Parent Collection", collection_types['Nestable only'])
25
+ create_collection("Child Collection", collection_types['Nestable only'])
26
+ create_collection("Branded Collection", collection_types['Brandable only'])
27
+ create_collection("Discoverable Collection", collection_types['Discoverable only'])
28
+ create_collection("Shared", collection_types['Sharable only'])
29
+ create_collection("Share Applies to Works", collection_types['Sharable only (and works)'])
30
+ create_collection("(SM1) Single Membership Collection", collection_types['Single Membership 1'])
31
+ create_collection("(SM1) Another Single Membership Collection", collection_types['Single Membership 1'])
32
+ create_collection("(SM2) Single Membership Collection", collection_types['Single Membership 2'])
33
+ create_collection("(SM2) Another Single Membership Collection", collection_types['Single Membership 2'])
34
+ end
35
+
36
+ ##
37
+ # @api private
38
+ class NullUser
39
+ ##
40
+ # @return [nil]
41
+ def user_key
42
+ nil
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ def create_collection(title, collection_type_gid)
49
+ return unless valid_collection_type?(title, collection_type_gid)
50
+ return if exists?(title, collection_type_gid)
51
+
52
+ collection = Hyrax::PcdmCollection.new(title: title, collection_type_gid: collection_type_gid)
53
+ Hyrax.persister.save(resource: collection)
54
+ Hyrax.publisher.publish('collection.metadata.updated', collection: collection, user: seed_user)
55
+ logger.info(" #{collection.title.first} -- CREATED")
56
+ end
57
+
58
+ def seed_user
59
+ @seed_user ||= NullUser.new
60
+ end
61
+
62
+ def collection_types
63
+ @collection_types ||=
64
+ Hyrax::CollectionType.all
65
+ .each_with_object({}) { |ct, hsh| hsh[ct.title] = ct.to_global_id.to_s }
66
+ end
67
+
68
+ def valid_collection_type?(title, collection_type_gid)
69
+ return true if collection_type_gid.present? && collection_types.value?(collection_type_gid.to_s)
70
+
71
+ msg = " #{title} -- NOT CREATED -- Collection type gid (#{collection_type_gid}) " \
72
+ "is invalid or doesn't exist."
73
+ logger.info(msg)
74
+ false
75
+ end
76
+
77
+ def existing_collections
78
+ @existing_collections ||=
79
+ Hyrax.query_service.find_all_of_model(model: Hyrax::PcdmCollection)
80
+ .each_with_object({}) { |col, hsh| hsh[col.title&.first] = col.collection_type_gid.to_s }
81
+ end
82
+
83
+ def exists?(title, collection_type_gid)
84
+ return false unless existing_collections[title] == collection_type_gid.to_s
85
+ logger.info(" #{title} -- ALREADY EXISTS")
86
+ true
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+ module Hyrax
3
+ module TestDataSeeders
4
+ # This class was created for use in rake tasks and db/seeds.rb. It generates
5
+ # collection types that can be used in release testing. This data can also be
6
+ # helpful for local development testing.
7
+ #
8
+ # Adding collection types is non-destructive. If a collection type with the
9
+ # title already exists, it will not be replaced.
10
+ class CollectionTypeSeeder
11
+ class << self
12
+ attr_accessor :logger
13
+
14
+ def generate_seeds(logger: Logger.new(STDOUT), allow_seeding_in_production: false) # rubocop:disable Metrics/MethodLength
15
+ raise("TestDataSeeders are not for use in production!") if Rails.env.production? && !allow_seeding_in_production
16
+ @logger = logger
17
+
18
+ logger.info("Adding collection types...")
19
+
20
+ create_collection_type(title: "Nestable only", badge_color: "#282D3C", nestable: true,
21
+ description: "Collections of this type can be nested.")
22
+ create_collection_type(title: "Brandable only", badge_color: "#ff6600", brandable: true,
23
+ description: "Collections of this type can have branding images.")
24
+ create_collection_type(title: "Discoverable only", badge_color: "#00A170", discoverable: true,
25
+ description: "Collections of this type can have visibility settings modified.")
26
+ create_collection_type(title: "Sharable only", badge_color: "#ff0066", sharable: true, share_applies_to_new_works: false,
27
+ description: "Collections of this type are sharable. Works " \
28
+ "do NOT inherit sharable settings when they are created.")
29
+ create_collection_type(title: "Sharable only (and works)", badge_color: "#0072B5", sharable: true, share_applies_to_new_works: true,
30
+ description: "Collections of this type are sharable. Works " \
31
+ "inherit sharable settings when they are created.")
32
+ create_collection_type(title: "Single Membership 1", badge_color: "#b34700", allow_multiple_membership: false,
33
+ description: "This Single Membership 1 collection type restricts collection membership. " \
34
+ "Collections of this type do not allow works to live in multiple collections of this type.")
35
+ create_collection_type(title: "Single Membership 2", badge_color: "#926AA6", allow_multiple_membership: false,
36
+ description: "This Single Membership 2 collection type restricts collection membership. " \
37
+ "Collections of this type do not allow works to live in multiple collections of this type.")
38
+ end
39
+
40
+ private
41
+
42
+ def collection_type_titles
43
+ @collection_type_titles ||= Hyrax::CollectionType.all.map(&:title)
44
+ end
45
+
46
+ def create_collection_type(options = {})
47
+ title = options[:title]
48
+ return logger.info(" #{title} -- ALREADY EXISTS") if collection_type_titles.include? title
49
+
50
+ defaults_for_options(options)
51
+ Hyrax::CollectionType.new(options).save
52
+ logger.info(" #{title} -- CREATED")
53
+ end
54
+
55
+ def defaults_for_options(options = {})
56
+ options[:nestable] ||= false
57
+ options[:brandable] ||= false
58
+ options[:discoverable] ||= false
59
+ options[:sharable] ||= false
60
+ options[:share_applies_to_new_works] ||= false
61
+ options[:allow_multiple_membership] ||= true
62
+
63
+ # These should always false unless the collection type is Admin Set.
64
+ # Admin Set collection type is created by required_data_seeders
65
+ options[:require_membership] = false
66
+ options[:assigns_workflow] = false
67
+ options[:assigns_visibility] = false
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+ module Hyrax
3
+ module TestDataSeeders
4
+ # This class was created for use in rake tasks and db/seeds.rb. It generates
5
+ # users that can be used in release testing. This data can also be helpful
6
+ # for local development testing.
7
+ #
8
+ # Adding users is non-destructive. If a user with the email already exists,
9
+ # they will not be replaced.
10
+ class UserSeeder
11
+ class << self
12
+ attr_accessor :logger
13
+
14
+ def generate_seeds(logger: Logger.new(STDOUT), allow_seeding_in_production: false)
15
+ raise("TestDataSeeders are not for use in production!") if Rails.env.production? && !allow_seeding_in_production
16
+ @logger = logger
17
+
18
+ logger.info("Adding users...")
19
+
20
+ add_user('admin@example.com', 'admin_password', admin_role)
21
+ add_user('basic_user@example.com', 'password')
22
+ add_user('another_user@example.com', 'password')
23
+ end
24
+
25
+ private
26
+
27
+ def admin_role
28
+ unless defined? Role
29
+ logger.warn("Cannot create `Role` because the `hyrda-role-management` gem, or " \
30
+ "other gem providing a definition for a Role class, is not installed. " \
31
+ "For development, you can edit `config/role_map.yml` and add the user's " \
32
+ "email under the role you want to assign.")
33
+ return
34
+ end
35
+ @admin_role ||= Role.find_by(name: Hyrax.config.admin_user_group_name)
36
+ end
37
+
38
+ def add_user(email, password, role = nil)
39
+ created = false
40
+ user = ::User.find_or_create_by(email: email) do |f|
41
+ created = true
42
+ f.password = password
43
+ end
44
+ logger.info(" #{email} -- #{created ? 'CREATED' : 'ALREADY EXISTS'}")
45
+ return unless role && !user.roles.include?(role)
46
+ user.roles << role
47
+ user.save
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+ module Hyrax
3
+ ##
4
+ # Validates that the record passes the multiple membership requirements for collections.
5
+ class CollectionMembershipValidator < ActiveModel::Validator
6
+ ##
7
+ # @param multiple_membership_checker
8
+ def initialize(multiple_membership_checker: Hyrax::MultipleMembershipChecker, **options)
9
+ @multiple_membership_checker = multiple_membership_checker
10
+ super(options)
11
+ end
12
+
13
+ def validate(record)
14
+ # collections-in-collections do not have multi-membership restrictions
15
+ return true if record.is_a? Hyrax::Forms::PcdmCollectionForm
16
+ checker = @multiple_membership_checker.new(item: nil)
17
+ ids = collections_ids(record)
18
+
19
+ errors = Array(checker.check(collection_ids: ids))
20
+ record.errors[:member_of_collection_ids].concat(errors)
21
+ end
22
+
23
+ private
24
+
25
+ def collections_ids(record)
26
+ collection_ids = record.member_of_collection_ids.reject(&:blank?)
27
+
28
+ if record.member_of_collections_attributes.present?
29
+ record.member_of_collections_attributes
30
+ .each do |_k, h|
31
+ next if h["_destroy"] == "true"
32
+ collection_ids << Valkyrie::ID.new(h["id"])
33
+ end
34
+ end
35
+
36
+ collection_ids
37
+ end
38
+ end
39
+ end
@@ -1,3 +1,10 @@
1
+ <% model = document.hydra_model %>
1
2
  <div class="search-results-title-row">
2
- <h3 class="search-result-title"><%= link_to document.title_or_label, document %></h3>
3
+ <% if model == Hyrax::PcdmCollection || model < Hyrax::PcdmCollection %>
4
+ <h3 class="search-result-title"><%= link_to document.title_or_label, [hyrax, document] %></h3>
5
+ <%= Hyrax::CollectionPresenter.new(document, current_ability).collection_type_badge %>
6
+ <% else %>
7
+ <h3 class="search-result-title"><%= link_to document.title_or_label, document %></h3>
8
+ <% end %>
3
9
  </div>
10
+
@@ -1,5 +1,10 @@
1
+ <% model = document.hydra_model %>
1
2
  <div class="col-md-2">
2
- <div class="list-thumbnail">
3
- <%= render_thumbnail_tag document %>
4
- </div>
3
+ <% if model == Hyrax::PcdmCollection || model < Hyrax::PcdmCollection %>
4
+ <%= render_thumbnail_tag document, {}, suppress_link: true %>
5
+ <% else %>
6
+ <div class="list-thumbnail">
7
+ <%= render_thumbnail_tag document %>
8
+ </div>
9
+ <% end %>
5
10
  </div>
@@ -1,8 +1,8 @@
1
1
  <%= f.input key,
2
- as: :multi_value,
3
- input_html: {
4
- class: 'form-control',
5
- data: { 'autocomplete-url' => "/authorities/search/geonames",
6
- 'autocomplete' => key }
7
- },
8
- required: f.object.required?(key) %>
2
+ as: :multi_value,
3
+ input_html: {
4
+ class: 'form-control',
5
+ data: { 'autocomplete-url' => "/authorities/search/geonames",
6
+ 'autocomplete' => key }
7
+ },
8
+ required: f.object.required?(key) %>
@@ -1,6 +1,6 @@
1
1
  <h3><%= t(".#{access}.title") %></h3>
2
2
  <p><%= t(".#{access}.help") %></p>
3
- <% if @form.permission_template.access_grants.select(&filter).any? %>
3
+ <% if collection_permission_template_form_for(form: @form).access_grants.select(&filter).any? %>
4
4
  <table class="table table-striped share-status">
5
5
  <thead>
6
6
  <tr>
@@ -10,7 +10,7 @@
10
10
  </tr>
11
11
  </thead>
12
12
  <tbody>
13
- <% @form.permission_template.access_grants.select(&filter).each do |g| %>
13
+ <% collection_permission_template_form_for(form: @form).access_grants.select(&filter).each do |g| %>
14
14
  <tr>
15
15
  <td data-agent="<%= g.agent_id %>"><%= g.label %></td>
16
16
  <td><%= g.agent_type.titleize %></td>
@@ -5,7 +5,7 @@
5
5
  <h3><%= t('.add_participants') %></h3>
6
6
  <% access_options = options_for_select([['Manager', 'manage'], ['Depositor', 'deposit'], ['Viewer', 'view']]) %>
7
7
  <div class="sharing-row-form">
8
- <%= simple_form_for @form.permission_template,
8
+ <%= simple_form_for collection_permission_template_form_for(form: @form),
9
9
  url: [hyrax, :admin, @form, :permission_template],
10
10
  html: { id: 'group-participants-form', class: 'form-inline' } do |f| %>
11
11
 
@@ -33,7 +33,7 @@
33
33
  </div>
34
34
 
35
35
  <div class="sharing-row-form">
36
- <%= simple_form_for @form.permission_template,
36
+ <%= simple_form_for collection_permission_template_form_for(form: @form),
37
37
  url: [hyrax, :admin, @form, :permission_template],
38
38
  html: { id: 'user-participants-form', class: 'form-inline add-users' } do |f| %>
39
39
 
@@ -1,6 +1,6 @@
1
1
  <div id="visibility" class="tab-pane">
2
2
  <div class="panel panel-default labels">
3
- <%= simple_form_for @form.permission_template,
3
+ <%= simple_form_for collection_permission_template_form_for(form: @form),
4
4
  url: [hyrax, :admin, @form, :permission_template],
5
5
  html: { class: 'nav-safety' } do |f| %>
6
6
  <div class="panel-body">
@@ -62,4 +62,4 @@
62
62
  </div>
63
63
  <% end %>
64
64
  </div>
65
- </div>
65
+ </div>
@@ -1,6 +1,6 @@
1
1
  <div id="workflow" class="tab-pane">
2
2
  <div class="panel panel-default labels">
3
- <%= simple_form_for @form.permission_template,
3
+ <%= simple_form_for collection_permission_template_form_for(form: @form),
4
4
  url: [hyrax, :admin, @form, :permission_template],
5
5
  html: { id: 'form_workflows', class: 'nav-safety' } do |f| %>
6
6
  <% if f.object.available_workflows.any? %>
@@ -41,7 +41,7 @@
41
41
  <button class="btn btn-danger btn-sm delete-collection-type"
42
42
  data-collection-type="<%= collection_type.to_json %>"
43
43
  data-collection-type-index="<%= hyrax.dashboard_collections_path({ 'f[collection_type_gid_ssim][]' => collection_type.to_global_id.to_s, 'f[has_model_ssim][]' => 'Collection' }) %>"
44
- data-has-collections="<%= collection_type.collections? %>">
44
+ data-has-collections="<%= collection_type.collections.any? %>">
45
45
  <%= t('helpers.action.delete') %>
46
46
  </button>
47
47
  <% end %>
@@ -14,7 +14,7 @@
14
14
  <%= render 'form_visibility_error', f: f %>
15
15
  </div>
16
16
  <% end %>
17
- <% if Flipflop.batch_upload? && f.object.new_record? %>
17
+ <% if Flipflop.batch_upload? && !f.object.persisted? %>
18
18
  <% provide :metadata_tab do %>
19
19
  <p class="switch-upload-type"><%= t('.batch_upload_hint') %> <%= link_to t('.batch_link'), hyrax.new_batch_upload_path(payload_concern: @form.model.class) %></p>
20
20
  <% end %>
@@ -18,7 +18,7 @@ HTML Properties:
18
18
  data: {
19
19
  autocomplete: 'work',
20
20
  'autocomplete-url' => Rails.application.routes.url_helpers.qa_path + '/search/find_works',
21
- 'exclude-work': f.object.model.id # exclude this item from the result set.
21
+ 'exclude-work': f.object.model.id.to_s # exclude this item from the result set.
22
22
  } %>
23
23
  <a href="#" onclick="return false;" class="btn btn-primary" data-behavior="add-relationship"><%= t('.add') %></a>
24
24
  </div>
@@ -16,9 +16,9 @@
16
16
  <th><%= t("hyrax.dashboard.my.heading.access") %></th>
17
17
  <% end %>
18
18
  <th><%= t("hyrax.dashboard.my.heading.type") %></th>
19
- <th><%= t("hyrax.dashboard.my.heading.collection.visibility") %></th>
20
- <th><%= t("hyrax.dashboard.my.heading.items") %></th>
21
19
  <th><%= t("hyrax.dashboard.my.heading.last_modified") %></th>
20
+ <th><%= t("hyrax.dashboard.my.heading.items") %></th>
21
+ <th><%= t("hyrax.dashboard.my.heading.collection.visibility") %></th>
22
22
  <th><%= t("hyrax.dashboard.my.heading.action") %></th>
23
23
  </tr>
24
24
  </thead>
@@ -23,7 +23,7 @@
23
23
  <% end %>
24
24
  </ul>
25
25
 
26
- <%= simple_form_for @form, url: [hyrax, :dashboard, @form], html: { class: 'editor nav-safety' } do |f| %>
26
+ <%= simple_form_for @form, url: [hyrax, :dashboard, @form], html: { class: 'editor nav-safety', data: { behavior: 'collection-form', 'param-key' => @form.model_name.param_key } } do |f| %>
27
27
  <div class="tab-content">
28
28
  <div id="description" class="tab-pane active">
29
29
  <div class="panel panel-default labels">
@@ -35,7 +35,7 @@
35
35
  <% end %>
36
36
 
37
37
  <% # TODO: Remove check for PcdmCollection when Issue #5286 is resolved. %>
38
- <% if f.object.persisted? && Hyrax.config.collection_class != Hyrax::PcdmCollection %>
38
+ <% if f.object.persisted? && !(Hyrax.config.collection_class < Valkyrie::Resource) %>
39
39
  <%# we're loading these values dynamically to speed page load %>
40
40
  <%= f.input :thumbnail_id,
41
41
  input_html: { data: { text: thumbnail_label_for(object: f.object) } } %>
@@ -72,29 +72,35 @@
72
72
  </div> <!-- end description -->
73
73
 
74
74
  <% if @form.persisted? %>
75
- <div id="branding" class="tab-pane">
76
- <div class="panel panel-default labels">
77
- <div class="panel-body">
78
- <%= render 'form_branding', f: f %>
75
+ <% if collection_brandable?(collection: @collection) %>
76
+ <div id="branding" class="tab-pane">
77
+ <div class="panel panel-default labels">
78
+ <div class="panel-body">
79
+ <%= render 'form_branding', f: f %>
80
+ </div>
79
81
  </div>
80
82
  </div>
81
- </div>
83
+ <% end %>
82
84
 
83
- <div id="discovery" class="tab-pane">
84
- <div class="panel panel-default labels">
85
- <div class="panel-body">
86
- <%= render 'form_discovery', f: f %>
85
+ <% if collection_discoverable?(collection: @collection) %>
86
+ <div id="discovery" class="tab-pane">
87
+ <div class="panel panel-default labels">
88
+ <div class="panel-body">
89
+ <%= render 'form_discovery', f: f %>
90
+ </div>
87
91
  </div>
88
92
  </div>
89
- </div>
93
+ <% end %>
90
94
 
91
- <div id="sharing" class="tab-pane">
92
- <div class="panel panel-default labels" id="collection_permissions" data-param-key="<%= f.object.model_name.param_key %>">
93
- <div class="panel-body">
94
- <%= render 'form_share', f: f %>
95
+ <% if collection_sharable?(collection: @collection) %>
96
+ <div id="sharing" class="tab-pane">
97
+ <div class="panel panel-default labels" id="collection_permissions" data-param-key="<%= f.object.model_name.param_key %>">
98
+ <div class="panel-body">
99
+ <%= render 'form_share', f: f %>
100
+ </div>
95
101
  </div>
96
102
  </div>
97
- </div>
103
+ <% end %>
98
104
  <% end %>
99
105
 
100
106
  <div class="panel-footer">
@@ -110,3 +116,4 @@
110
116
  <% end # simple_form_for %>
111
117
 
112
118
  </div> <!-- end collection-controls -->
119
+
@@ -34,6 +34,7 @@
34
34
  <div class="row branding-banner-list">
35
35
  <div class="col-xs-12">
36
36
  <div class="container">
37
+ <%# Where the request to display the branding comes from. %>
37
38
  <% if f.object.banner_info[:file] %>
38
39
  <div id="banner">
39
40
  <div class="row branding-banner-row">
@@ -5,13 +5,16 @@
5
5
 
6
6
  <div class="form-group">
7
7
  <label class="radio">
8
- <input type="radio" id="visibility_open" name="<%= f.object_name %>[visibility]" value="<%= Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC %>" <% if @collection.open_access? %> checked="true"<% end %> /><strong><%= t('hyrax.visibility.open.text') %></strong> - <%= t('hyrax.visibility.open.note_html') %>
8
+ <%= f.radio_button :visibility, Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC %>
9
+ <strong><%= t('hyrax.visibility.open.text') %></strong> - <%= t('hyrax.visibility.open.note_html') %>
9
10
  </label>
10
11
  <label class="radio">
11
- <input type="radio" id="visibility_registered" name="<%= f.object_name %>[visibility]" value="<%= Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_AUTHENTICATED %>" <% if @collection.authenticated_only_access? %> checked="true"<% end %> /><strong><%= t('hyrax.visibility.authenticated.text', institution: institution_name) %></strong> - <%= t('hyrax.visibility.authenticated.note_html', institution: institution_name) %>
12
+ <%= f.radio_button :visibility, Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_AUTHENTICATED %>
13
+ <strong><%= t('hyrax.visibility.authenticated.text', institution: institution_name) %></strong> - <%= t('hyrax.visibility.authenticated.note_html', institution: institution_name) %>
12
14
  </label>
13
15
  <label class="radio">
14
- <input type="radio" id="visibility_restricted" name="<%= f.object_name %>[visibility]" value="<%= Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE %>" <% if @collection.private_access? %> checked="true"<% end %> /><strong><%= t('hyrax.visibility.restricted.text') %></strong>- <%= t('hyrax.visibility.restricted.note_html') %>
16
+ <%= f.radio_button :visibility, Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE %>
17
+ <strong><%= t('hyrax.visibility.restricted.text') %></strong>- <%= t('hyrax.visibility.restricted.note_html') %>
15
18
  </label>
16
19
  </div>
17
20
 
@@ -8,7 +8,7 @@
8
8
 
9
9
  <!-- Add group form -->
10
10
  <div class="form-add-sharing-wrapper" data-id="<%= @form.id %>">
11
- <%= simple_form_for @form.permission_template,
11
+ <%= simple_form_for collection_permission_template_form_for(form: @form),
12
12
  url: [hyrax, :dashboard, @form, :permission_template],
13
13
  html: { id: 'group-participants-form' } do |f| %>
14
14
 
@@ -40,7 +40,7 @@
40
40
 
41
41
  <!-- Add user form -->
42
42
  <div class="form-add-sharing-wrapper" data-id="<%= @form.id %>">
43
- <%= simple_form_for @form.permission_template,
43
+ <%= simple_form_for collection_permission_template_form_for(form: @form),
44
44
  url: [hyrax, :dashboard, @form, :permission_template],
45
45
  html: { id: 'user-participants-form' } do |f| %>
46
46
 
@@ -1,7 +1,7 @@
1
1
  <h3><%= t(".#{access}.title") %></h3>
2
2
  <p><%= t(".#{access}.help") %></p>
3
- <p><%= t(".#{access}.help_with_works", type_title: @collection.collection_type.title) if @collection.share_applies_to_new_works? && access != 'depositors' %></p>
4
- <% if @form.permission_template.access_grants.select(&filter).any? %>
3
+ <p><%= t(".#{access}.help_with_works", type_title: @collection_type.title) if @collection_type.share_applies_to_new_works? && access != 'depositors' %></p>
4
+ <% if collection_permission_template_form_for(form: @form).access_grants.select(&filter).any? %>
5
5
  <table class="table table-striped share-status">
6
6
  <thead>
7
7
  <tr>
@@ -11,7 +11,7 @@
11
11
  </tr>
12
12
  </thead>
13
13
  <tbody>
14
- <% @form.permission_template.access_grants.select(&filter).each do |g| %>
14
+ <% collection_permission_template_form_for(form: @form).access_grants.select(&filter).each do |g| %>
15
15
  <tr>
16
16
  <td data-agent="<%= g.agent_id %>"><%= g.label %></td>
17
17
  <td><%= g.agent_type.titleize %></td>
@@ -61,9 +61,9 @@
61
61
  <td class="collection_type">
62
62
  <%= collection_presenter.collection_type_badge %>
63
63
  </td>
64
- <td><%= collection_presenter.permission_badge %> </td>
64
+ <td class="date"><%= collection_presenter.modified_date %></td>
65
65
  <td><%= collection_presenter.total_viewable_items %></td>
66
- <td class="date"><%= collection_presenter.modified_date.try(:to_formatted_s, :standard) %> </td>
66
+ <td><%= collection_presenter.permission_badge %> </td>
67
67
  <td>
68
68
  <% if collection_presenter.solr_document.admin_set? %>
69
69
  <%= render '/hyrax/my/admin_set_action_menu', admin_set_presenter: collection_presenter %>
@@ -32,7 +32,7 @@
32
32
  <% end %>
33
33
  <% end %>
34
34
 
35
- <% if current_ability.can_create_any_work? %>
35
+ <% if current_ability.can_create_any_work? && Hyrax.config.analytics? %>
36
36
  <li>
37
37
  <%= menu.collapsable_section t('hyrax.admin.sidebar.analytics'),
38
38
  icon_class: "fa fa-pie-chart",
@@ -5,7 +5,7 @@
5
5
  <tr>
6
6
  <th class="check-all"><label for="check_all" class="sr-only"><%= t("hyrax.dashboard.my.sr.check_all_label") %></label><%= render_check_all %></th>
7
7
  <th><%= t("hyrax.dashboard.my.heading.title") %></th>
8
- <th class="date text-center"><%= t("hyrax.dashboard.my.heading.date_uploaded") %></th>
8
+ <th class="date text-center"><%= t("hyrax.dashboard.my.heading.date_modified") %></th>
9
9
  <th class="text-center"><%= t("blacklight.search.fields.facet.suppressed_bsi") %></th>
10
10
  <th class="text-center"><%= t("hyrax.dashboard.my.heading.work.visibility") %></th>
11
11
  <th class="text-center"><%= t("hyrax.dashboard.my.heading.action") %></th>
@@ -27,7 +27,7 @@
27
27
  </div>
28
28
  </td>
29
29
 
30
- <td class='text-center'><%= document.date_uploaded %></td>
30
+ <td class="date text-center"><%= document.date_modified %></td>
31
31
  <td class='workflow-state text-center'><%= presenter.workflow.state_label %></td>
32
32
  <td class='text-center'><%= render_visibility_link document %></td>
33
33
 
@@ -1,4 +1,4 @@
1
- <% if (can?(:download, file_set.id) || can?(:destroy, file_set.id) || can?(:edit, file_set.id)) && !workflow_restriction?(file_set.parent) %>
1
+ <% if (can?(:download, file_set.id) || can?(:destroy, file_set.id) || can?(:edit, file_set.id)) && !workflow_restriction?(@parent) %>
2
2
  <% if can?(:download, file_set.id) && !(can?(:edit, file_set.id) || can?(:destroy, file_set.id)) %>
3
3
  <%= link_to t('.download'),
4
4
  hyrax.download_path(file_set),
@@ -51,4 +51,4 @@
51
51
  </ul>
52
52
  </div>
53
53
  <% end %>
54
- <% end %>
54
+ <% end %>