hyrax 5.0.0 → 5.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (331) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +7 -176
  3. data/.dassie/.env +8 -3
  4. data/.dassie/Gemfile +13 -2
  5. data/.dassie/app/controllers/hyrax/generic_work_resources_controller.rb +17 -0
  6. data/.dassie/app/controllers/hyrax/generic_works_controller.rb +7 -1
  7. data/.dassie/app/forms/generic_work_resource_form.rb +20 -0
  8. data/.dassie/app/indexers/generic_work_resource_indexer.rb +16 -0
  9. data/.dassie/app/models/admin_set_resource.rb +9 -0
  10. data/.dassie/app/models/collection_resource.rb +2 -0
  11. data/.dassie/app/models/file_set.rb +2 -0
  12. data/.dassie/app/models/generic_work_resource.rb +10 -0
  13. data/.dassie/app/views/hyrax/generic_work_resources/_generic_work_resource.html.erb +2 -0
  14. data/.dassie/config/analytics.yml +6 -1
  15. data/.dassie/config/application.rb +24 -0
  16. data/.dassie/config/initializers/hyrax.rb +13 -3
  17. data/.dassie/config/initializers/wings.rb +109 -0
  18. data/.dassie/config/metadata/generic_work_resource.yaml +22 -0
  19. data/.dassie/config/valkyrie_index.yml +4 -10
  20. data/.dassie/db/migrate/20240506070809_valkyrie_id_to_string.rb +5 -0
  21. data/.dassie/db/schema.rb +2 -2
  22. data/.dassie/spec/indexers/generic_work_resource_indexer_spec.rb +13 -0
  23. data/.dassie/spec/models/generic_work_resource_spec.rb +12 -0
  24. data/.dassie/spec/views/generic_work_resources/_generic_work_resource.html.erb_spec.rb +7 -0
  25. data/.dockerignore +6 -4
  26. data/.github/release.yml +3 -0
  27. data/.github/workflows/lint-build-test.yml +130 -0
  28. data/.github/workflows/test-results.yml +40 -0
  29. data/.koppie/.env +7 -5
  30. data/.koppie/Gemfile +12 -1
  31. data/.koppie/config/analytics.yml +6 -1
  32. data/.koppie/config/environments/test.rb +2 -0
  33. data/.koppie/config/initializers/1_valkyrie.rb +6 -2
  34. data/.koppie/config/solr.yml +1 -1
  35. data/.regen +1 -1
  36. data/.rubocop.yml +5 -0
  37. data/Dockerfile +16 -36
  38. data/Gemfile +2 -0
  39. data/app/assets/javascripts/hydra-editor/field_manager.es6 +187 -0
  40. data/app/assets/javascripts/hyrax/analytics_events.js +48 -24
  41. data/app/assets/javascripts/hyrax/autocomplete/linked_data.es6 +3 -0
  42. data/app/assets/javascripts/hyrax/collapse.js +4 -4
  43. data/app/assets/javascripts/hyrax/editor/controlled_vocabulary.es6 +38 -5
  44. data/app/assets/javascripts/hyrax/file_manager/save_manager.es6 +2 -0
  45. data/app/assets/javascripts/hyrax/search.js +2 -3
  46. data/app/assets/javascripts/hyrax/select_work_type.es6 +3 -1
  47. data/app/assets/javascripts/hyrax/uploader.js +20 -18
  48. data/app/assets/javascripts/hyrax.js +1 -0
  49. data/app/assets/stylesheets/_bootstrap-default-overrides.scss +4 -0
  50. data/app/assets/stylesheets/hyrax/_card.scss +4 -0
  51. data/app/assets/stylesheets/hyrax/_catalog.scss +21 -0
  52. data/app/assets/stylesheets/hyrax/_collections.scss +1 -1
  53. data/app/assets/stylesheets/hyrax/_facets.scss +15 -3
  54. data/app/assets/stylesheets/hyrax/_featured.scss +4 -0
  55. data/app/assets/stylesheets/hyrax/_file_upload.scss +6 -0
  56. data/app/assets/stylesheets/hyrax/_form.scss +4 -0
  57. data/app/assets/stylesheets/hyrax/_forms.scss +2 -1
  58. data/app/assets/stylesheets/hyrax/_nestable.scss +9 -8
  59. data/app/assets/stylesheets/hyrax/_select_work_type.scss +12 -0
  60. data/app/assets/stylesheets/hyrax/_styles.scss +4 -0
  61. data/app/assets/stylesheets/hyrax/_work-show.scss +3 -0
  62. data/app/assets/stylesheets/hyrax/controlled_vocabulary.scss +2 -2
  63. data/app/controllers/concerns/hyrax/singular_subresource_controller.rb +7 -2
  64. data/app/controllers/concerns/hyrax/valkyrie_downloads_controller_behavior.rb +11 -2
  65. data/app/controllers/concerns/hyrax/works_controller_behavior.rb +9 -2
  66. data/app/controllers/hyrax/admin/analytics/collection_reports_controller.rb +2 -2
  67. data/app/controllers/hyrax/admin/analytics/work_reports_controller.rb +7 -8
  68. data/app/controllers/hyrax/dashboard/collections_controller.rb +2 -1
  69. data/app/controllers/hyrax/downloads_controller.rb +24 -3
  70. data/app/controllers/hyrax/file_sets_controller.rb +33 -7
  71. data/app/controllers/hyrax/my/works_controller.rb +20 -0
  72. data/app/controllers/hyrax/single_use_links_viewer_controller.rb +9 -2
  73. data/app/controllers/hyrax/stats_controller.rb +1 -1
  74. data/app/controllers/hyrax/uploads_controller.rb +28 -2
  75. data/app/forms/hyrax/forms/admin/appearance.rb +1 -1
  76. data/app/forms/hyrax/forms/admin/collection_type_form.rb +1 -7
  77. data/app/forms/hyrax/forms/pcdm_collection_form.rb +9 -0
  78. data/app/forms/hyrax/forms/work_embargo_form.rb +6 -0
  79. data/app/forms/hyrax/forms/work_lease_form.rb +6 -0
  80. data/app/indexers/concerns/hyrax/location_indexer.rb +2 -2
  81. data/app/indexers/hyrax/indexers/file_set_indexer.rb +4 -0
  82. data/app/indexers/hyrax/indexers/resource_indexer.rb +1 -0
  83. data/app/indexers/hyrax/valkyrie_indexer.rb +3 -5
  84. data/app/jobs/migrate_files_to_valkyrie_job.rb +109 -0
  85. data/app/jobs/migrate_resources_job.rb +34 -0
  86. data/app/jobs/valkyrie_create_derivatives_job.rb +2 -1
  87. data/app/models/admin_set.rb +1 -0
  88. data/app/models/collection.rb +13 -1
  89. data/app/models/concerns/hyrax/ar_resource.rb +104 -0
  90. data/app/models/concerns/hyrax/solr_document/ordered_members.rb +2 -1
  91. data/app/models/concerns/hyrax/solr_document_behavior.rb +13 -2
  92. data/app/models/concerns/hyrax/valkyrie_lazy_migration.rb +82 -0
  93. data/app/models/file_download_stat.rb +1 -1
  94. data/app/models/file_view_stat.rb +1 -1
  95. data/app/models/hyrax/collection_type.rb +12 -4
  96. data/app/models/hyrax/file_metadata.rb +19 -0
  97. data/app/models/hyrax/file_set.rb +25 -0
  98. data/app/models/hyrax/model_registry.rb +3 -4
  99. data/app/models/hyrax/resource.rb +5 -0
  100. data/app/models/hyrax/statistic.rb +12 -37
  101. data/app/presenters/hyrax/file_set_presenter.rb +2 -1
  102. data/app/presenters/hyrax/file_usage.rb +3 -3
  103. data/app/presenters/hyrax/iiif_manifest_presenter.rb +2 -1
  104. data/app/presenters/hyrax/member_presenter_factory.rb +7 -1
  105. data/app/presenters/hyrax/menu_presenter.rb +1 -1
  106. data/app/presenters/hyrax/pcdm_member_presenter_factory.rb +2 -2
  107. data/app/presenters/hyrax/stats_usage_presenter.rb +2 -1
  108. data/app/presenters/hyrax/work_show_presenter.rb +15 -19
  109. data/app/presenters/hyrax/work_usage.rb +5 -2
  110. data/app/search_builders/hyrax/expired_embargo_search_builder.rb +7 -1
  111. data/app/search_builders/hyrax/expired_lease_search_builder.rb +7 -1
  112. data/app/search_builders/hyrax/filter_by_type.rb +1 -3
  113. data/app/search_builders/hyrax/valkyrie_abstract_type_relation.rb +7 -2
  114. data/app/services/hyrax/access_control_list.rb +1 -1
  115. data/app/services/hyrax/admin_set_create_service.rb +16 -5
  116. data/app/services/hyrax/admin_set_service.rb +2 -1
  117. data/app/services/hyrax/analytics/ga4/base.rb +96 -0
  118. data/app/services/hyrax/analytics/ga4/events.rb +25 -0
  119. data/app/services/hyrax/analytics/ga4/events_daily.rb +36 -0
  120. data/app/services/hyrax/analytics/ga4/visits.rb +33 -0
  121. data/app/services/hyrax/analytics/ga4/visits_daily.rb +24 -0
  122. data/app/services/hyrax/analytics/ga4.rb +204 -0
  123. data/app/services/hyrax/analytics/google.rb +16 -2
  124. data/app/services/hyrax/analytics/matomo.rb +16 -3
  125. data/app/services/hyrax/analytics/results.rb +6 -0
  126. data/app/services/hyrax/custom_queries/find_access_control.rb +1 -1
  127. data/app/services/hyrax/custom_queries/find_by_date_range.rb +6 -23
  128. data/app/services/hyrax/custom_queries/find_collections_by_type.rb +2 -2
  129. data/app/services/hyrax/custom_queries/find_count_by.rb +3 -31
  130. data/app/services/hyrax/custom_queries/find_file_metadata.rb +2 -2
  131. data/app/services/hyrax/custom_queries/find_models_by_access.rb +5 -27
  132. data/app/services/hyrax/embargo_manager.rb +2 -1
  133. data/app/services/hyrax/file_set_file_service.rb +10 -1
  134. data/app/services/hyrax/listeners/file_listener.rb +39 -0
  135. data/app/services/hyrax/listeners/file_metadata_listener.rb +0 -30
  136. data/app/services/hyrax/lock_manager.rb +7 -7
  137. data/app/services/hyrax/lockable.rb +4 -3
  138. data/app/services/hyrax/simple_schema_loader.rb +1 -1
  139. data/app/services/hyrax/solr_service.rb +22 -8
  140. data/app/services/hyrax/statistics/query_service.rb +1 -1
  141. data/app/services/hyrax/statistics/works/over_time.rb +1 -1
  142. data/app/services/hyrax/thumbnail_path_service.rb +2 -0
  143. data/app/services/hyrax/user_stat_importer.rb +5 -5
  144. data/app/services/hyrax/valkyrie_upload.rb +14 -9
  145. data/app/services/hyrax/versioning_service.rb +10 -2
  146. data/app/services/hyrax/work_query_service.rb +2 -2
  147. data/app/services/migrate_resource_service.rb +55 -0
  148. data/app/views/_controls.html.erb +5 -5
  149. data/app/views/_masthead.html.erb +1 -1
  150. data/app/views/catalog/_search_form.html.erb +9 -16
  151. data/app/views/catalog/_thumbnail_list_collection.html.erb +1 -1
  152. data/app/views/catalog/_thumbnail_list_default.html.erb +2 -2
  153. data/app/views/hyrax/admin/analytics/collection_reports/index.html.erb +4 -4
  154. data/app/views/hyrax/admin/analytics/work_reports/index.html.erb +1 -1
  155. data/app/views/hyrax/admin/collection_types/_form.html.erb +4 -4
  156. data/app/views/hyrax/admin/collection_types/index.html.erb +1 -1
  157. data/app/views/hyrax/admin/features/index.html.erb +1 -1
  158. data/app/views/hyrax/base/_file_manager_actions.html.erb +1 -1
  159. data/app/views/hyrax/base/_file_manager_member.html.erb +7 -4
  160. data/app/views/hyrax/base/_file_manager_thumbnail.html.erb +1 -1
  161. data/app/views/hyrax/base/_form_files.html.erb +1 -1
  162. data/app/views/hyrax/base/_form_member_of_collections.html.erb +4 -0
  163. data/app/views/hyrax/base/_show_actions.html.erb +7 -8
  164. data/app/views/hyrax/base/_work_button_row.html.erb +1 -1
  165. data/app/views/hyrax/batch_select/_add_button.html.erb +1 -1
  166. data/app/views/hyrax/content_blocks/_form.html.erb +3 -3
  167. data/app/views/hyrax/dashboard/_sidebar.html.erb +1 -1
  168. data/app/views/hyrax/dashboard/_user_activity.html.erb +2 -2
  169. data/app/views/hyrax/dashboard/collections/_form.html.erb +4 -4
  170. data/app/views/hyrax/dashboard/collections/_form_share.html.erb +6 -4
  171. data/app/views/hyrax/dashboard/collections/_list_collections.html.erb +1 -1
  172. data/app/views/hyrax/dashboard/collections/_show_document_list_row.html.erb +1 -1
  173. data/app/views/hyrax/dashboard/show_admin.html.erb +18 -19
  174. data/app/views/hyrax/dashboard/sidebar/_activity.html.erb +1 -1
  175. data/app/views/hyrax/embargoes/_list_expired_active_embargoes.html.erb +7 -7
  176. data/app/views/hyrax/file_sets/_actions.html.erb +9 -1
  177. data/app/views/hyrax/file_sets/_permission_form.html.erb +4 -2
  178. data/app/views/hyrax/file_sets/_show_actions.html.erb +1 -1
  179. data/app/views/hyrax/homepage/_featured.html.erb +1 -1
  180. data/app/views/hyrax/homepage/_recent_document.html.erb +2 -2
  181. data/app/views/hyrax/leases/_list_expired_active_leases.html.erb +6 -6
  182. data/app/views/hyrax/my/collections/_list_collections.html.erb +1 -1
  183. data/app/views/hyrax/my/collections/_tabs.html.erb +1 -1
  184. data/app/views/hyrax/pages/_form.html.erb +8 -8
  185. data/app/views/hyrax/transfers/_received.html.erb +1 -1
  186. data/app/views/hyrax/uploads/_js_templates.html.erb +9 -9
  187. data/app/views/hyrax/uploads/_js_templates_branding.html.erb +3 -3
  188. data/app/views/hyrax/uploads/_js_templates_versioning.html.erb +1 -1
  189. data/app/views/hyrax/uploads/create.json.jbuilder +2 -2
  190. data/app/views/hyrax/users/_activity_log.html.erb +15 -9
  191. data/app/views/hyrax/users/_user_row.html.erb +6 -3
  192. data/app/views/hyrax/users/_vitals.html.erb +3 -2
  193. data/app/views/layouts/_head_tag_content.html.erb +2 -0
  194. data/app/views/shared/_appearance_styles.html.erb +5 -1
  195. data/app/views/shared/_ga4.html.erb +11 -0
  196. data/app/views/shared/_select_work_type_modal.html.erb +10 -1
  197. data/bin/db-migrate-seed.sh +3 -3
  198. data/bin/dev-entrypoint.sh +7 -2
  199. data/bin/{db-wait.sh → service-wait.sh} +1 -1
  200. data/bin/worker-entrypoint.sh +8 -0
  201. data/chart/hyrax/Chart.yaml +1 -1
  202. data/chart/hyrax/templates/deployment-worker.yaml +2 -2
  203. data/chart/hyrax/templates/deployment.yaml +12 -0
  204. data/chart/hyrax/values.yaml +10 -0
  205. data/config/locales/hyrax.en.yml +4 -2
  206. data/config/metadata/basic_metadata.yaml +20 -0
  207. data/config/metadata/hyrax_internal_metadata.yaml +1 -1
  208. data/docker-compose-dassie.yml +167 -0
  209. data/docker-compose-koppie.yml +21 -36
  210. data/docker-compose-sirenia.yml +50 -44
  211. data/docker-compose.yml +2 -183
  212. data/documentation/developing-your-hyrax-based-app.md +4 -4
  213. data/hyrax.gemspec +7 -12
  214. data/lib/freyja/custom_query_container.rb +5 -0
  215. data/lib/freyja/metadata_adapter.rb +32 -0
  216. data/lib/freyja/persister.rb +42 -0
  217. data/lib/freyja/query_service.rb +20 -0
  218. data/lib/freyja/resource_factory.rb +8 -0
  219. data/lib/freyja.rb +14 -0
  220. data/lib/frigg/custom_query_container.rb +5 -0
  221. data/lib/frigg/metadata_adapter.rb +22 -0
  222. data/lib/frigg/persister.rb +33 -0
  223. data/lib/frigg/query_service.rb +15 -0
  224. data/lib/frigg.rb +13 -0
  225. data/lib/generators/hyrax/install_generator.rb +5 -0
  226. data/lib/generators/hyrax/templates/config/analytics.yml +6 -1
  227. data/lib/generators/hyrax/templates/config/initializers/1_valkyrie.rb +6 -2
  228. data/lib/generators/hyrax/templates/config/valkyrie_index.yml +1 -1
  229. data/lib/goddess/custom_query_container.rb +71 -0
  230. data/lib/goddess/metadata.rb +13 -0
  231. data/lib/goddess/query.rb +176 -0
  232. data/lib/hyrax/configuration.rb +83 -0
  233. data/lib/hyrax/engine.rb +2 -0
  234. data/lib/hyrax/form_fields.rb +1 -3
  235. data/lib/hyrax/name.rb +5 -0
  236. data/lib/hyrax/publisher.rb +11 -0
  237. data/lib/hyrax/rubocop/custom_cops.rb +30 -0
  238. data/lib/hyrax/specs/capybara.rb +10 -6
  239. data/{spec → lib/hyrax/specs/shared_specs}/factories/admin_sets.rb +2 -0
  240. data/{spec → lib/hyrax/specs/shared_specs}/factories/hyrax_embargo.rb +4 -0
  241. data/{spec → lib/hyrax/specs/shared_specs}/factories/hyrax_lease.rb +4 -0
  242. data/{spec → lib/hyrax/specs/shared_specs}/factories/hyrax_work.rb +26 -1
  243. data/lib/hyrax/specs/shared_specs/hydra_works.rb +1 -1
  244. data/lib/hyrax/transactions/admin_set_destroy.rb +2 -1
  245. data/lib/hyrax/transactions/collection_destroy.rb +2 -1
  246. data/lib/hyrax/transactions/container.rb +9 -0
  247. data/lib/hyrax/transactions/steps/add_file_sets.rb +2 -1
  248. data/lib/hyrax/transactions/steps/delete_all_file_metadata.rb +4 -5
  249. data/lib/hyrax/transactions/steps/delete_permission_template.rb +30 -0
  250. data/lib/hyrax/transactions/steps/delete_resource.rb +1 -1
  251. data/lib/hyrax/transactions/steps/save_collection_logo.rb +2 -1
  252. data/lib/hyrax/valkyrie_can_can_adapter.rb +8 -1
  253. data/lib/hyrax/version.rb +1 -1
  254. data/lib/wings/active_fedora_converter.rb +13 -5
  255. data/lib/wings/converter_value_mapper.rb +1 -0
  256. data/lib/wings/services/custom_queries/find_collections_by_type.rb +2 -1
  257. data/lib/wings/services/custom_queries/find_file_metadata.rb +2 -2
  258. data/lib/wings/setup.rb +12 -3
  259. data/lib/wings/transformer_value_mapper.rb +5 -1
  260. data/lib/wings/valkyrie/persister.rb +3 -1
  261. data/template.rb +1 -1
  262. metadata +118 -94
  263. data/.koppie/scripts/db-migrate-seed.sh +0 -9
  264. data/.koppie/scripts/entrypoint.sh +0 -10
  265. data/spec/support/book_resource.rb +0 -36
  266. data/spec/support/can_can_overrides.rb +0 -43
  267. data/spec/support/clean_solr.rb +0 -7
  268. data/spec/support/controller_level_helpers.rb +0 -27
  269. data/spec/support/factory_helpers.rb +0 -94
  270. data/spec/support/fakes/fake_actor.rb +0 -22
  271. data/spec/support/fakes/fake_authority.rb +0 -14
  272. data/spec/support/fakes/fake_search_builder_scope.rb +0 -44
  273. data/spec/support/fakes/indexing_adapter.rb +0 -17
  274. data/spec/support/fakes/test_hydra_group_service.rb +0 -55
  275. data/spec/support/features/batch_edit_actions.rb +0 -37
  276. data/spec/support/features/session_helpers.rb +0 -15
  277. data/spec/support/features/workflow.rb +0 -10
  278. data/spec/support/features.rb +0 -11
  279. data/spec/support/form_with_validations.rb +0 -15
  280. data/spec/support/input_support.rb +0 -12
  281. data/spec/support/logging_formatter.rb +0 -67
  282. data/spec/support/matchers/api_responses.rb +0 -27
  283. data/spec/support/matchers/collection_type_property_matchers.rb +0 -30
  284. data/spec/support/matchers/embargo.rb +0 -9
  285. data/spec/support/matchers/lease.rb +0 -9
  286. data/spec/support/matchers/match_valkyrie_ids_with_af_ids.rb +0 -12
  287. data/spec/support/matchers/pcdm_matchers.rb +0 -34
  288. data/spec/support/matchers/permission.rb +0 -31
  289. data/spec/support/matchers/response_matchers.rb +0 -8
  290. data/spec/support/optional_example.rb +0 -17
  291. data/spec/support/rake.rb +0 -42
  292. data/spec/support/selectors.rb +0 -112
  293. data/spec/support/shared_examples_for_collection_presenter.rb +0 -44
  294. data/spec/support/simple_work.rb +0 -28
  295. data/spec/support/spec_statistic.rb +0 -24
  296. data/spec/support/speedup.rb +0 -7
  297. data/spec/support/statistic_helper.rb +0 -10
  298. data/spec/support/valkyrie_indexing.rb +0 -2
  299. data/spec/support/wings_models.rb +0 -9
  300. /data/{spec → lib/hyrax/specs/shared_specs}/factories/access_control.rb +0 -0
  301. /data/{spec → lib/hyrax/specs/shared_specs}/factories/admin_sets_lw.rb +0 -0
  302. /data/{spec → lib/hyrax/specs/shared_specs}/factories/administrative_sets.rb +0 -0
  303. /data/{spec → lib/hyrax/specs/shared_specs}/factories/api_items.rb +0 -0
  304. /data/{spec → lib/hyrax/specs/shared_specs}/factories/collection_branding_infos.rb +0 -0
  305. /data/{spec → lib/hyrax/specs/shared_specs}/factories/collection_type_participants.rb +0 -0
  306. /data/{spec → lib/hyrax/specs/shared_specs}/factories/collection_types.rb +0 -0
  307. /data/{spec → lib/hyrax/specs/shared_specs}/factories/collections.rb +0 -0
  308. /data/{spec → lib/hyrax/specs/shared_specs}/factories/collections_factory.rb +0 -0
  309. /data/{spec → lib/hyrax/specs/shared_specs}/factories/content_blocks.rb +0 -0
  310. /data/{spec → lib/hyrax/specs/shared_specs}/factories/counter_metrics.rb +0 -0
  311. /data/{spec → lib/hyrax/specs/shared_specs}/factories/featured_works.rb +0 -0
  312. /data/{spec → lib/hyrax/specs/shared_specs}/factories/file_sets.rb +0 -0
  313. /data/{spec → lib/hyrax/specs/shared_specs}/factories/generic_works.rb +0 -0
  314. /data/{spec → lib/hyrax/specs/shared_specs}/factories/hyrax_collection.rb +0 -0
  315. /data/{spec → lib/hyrax/specs/shared_specs}/factories/hyrax_default_admin_set.rb +0 -0
  316. /data/{spec → lib/hyrax/specs/shared_specs}/factories/hyrax_file_metadata.rb +0 -0
  317. /data/{spec → lib/hyrax/specs/shared_specs}/factories/hyrax_file_set.rb +0 -0
  318. /data/{spec → lib/hyrax/specs/shared_specs}/factories/hyrax_resource.rb +0 -0
  319. /data/{spec → lib/hyrax/specs/shared_specs}/factories/object_id.rb +0 -0
  320. /data/{spec → lib/hyrax/specs/shared_specs}/factories/operations.rb +0 -0
  321. /data/{spec → lib/hyrax/specs/shared_specs}/factories/permission.rb +0 -0
  322. /data/{spec → lib/hyrax/specs/shared_specs}/factories/permission_template_accesses.rb +0 -0
  323. /data/{spec → lib/hyrax/specs/shared_specs}/factories/permission_templates.rb +0 -0
  324. /data/{spec → lib/hyrax/specs/shared_specs}/factories/proxy_deposit_requests.rb +0 -0
  325. /data/{spec → lib/hyrax/specs/shared_specs}/factories/single_use_links.rb +0 -0
  326. /data/{spec → lib/hyrax/specs/shared_specs}/factories/sipity_entities.rb +0 -0
  327. /data/{spec → lib/hyrax/specs/shared_specs}/factories/uploaded_files.rb +0 -0
  328. /data/{spec → lib/hyrax/specs/shared_specs}/factories/users.rb +0 -0
  329. /data/{spec → lib/hyrax/specs/shared_specs}/factories/workflow_actions.rb +0 -0
  330. /data/{spec → lib/hyrax/specs/shared_specs}/factories/workflow_states.rb +0 -0
  331. /data/{spec → lib/hyrax/specs/shared_specs}/factories/workflows.rb +0 -0
@@ -8,11 +8,14 @@ module Hyrax
8
8
  # and prepares it for visualization in /app/views/stats/work.html.erb
9
9
  class WorkUsage < StatsUsagePresenter
10
10
  def initialize(id)
11
- self.model = Hyrax::WorkRelation.new.find(id)
11
+ self.model = Hyrax.query_service.find_by(id: id)
12
12
  end
13
13
 
14
14
  alias work model
15
- delegate :to_s, to: :model
15
+
16
+ def to_s
17
+ model.title.first
18
+ end
16
19
 
17
20
  def total_pageviews
18
21
  pageviews.reduce(0) { |total, result| total + result[1].to_i }
@@ -6,7 +6,13 @@ module Hyrax
6
6
 
7
7
  def only_expired_embargoes(solr_params)
8
8
  solr_params[:fq] ||= []
9
- solr_params[:fq] = 'embargo_release_date_dtsi:[* TO NOW]'
9
+ solr_params[:fq] = "embargo_release_date_dtsi:[* TO #{now}]"
10
+ end
11
+
12
+ private
13
+
14
+ def now
15
+ Hyrax::TimeService.time_in_utc.utc.xmlschema
10
16
  end
11
17
  end
12
18
  end
@@ -6,7 +6,13 @@ module Hyrax
6
6
 
7
7
  def only_expired_leases(solr_params)
8
8
  solr_params[:fq] ||= []
9
- solr_params[:fq] = 'lease_expiration_date_dtsi:[* TO NOW]'
9
+ solr_params[:fq] = "lease_expiration_date_dtsi:[* TO #{now}]"
10
+ end
11
+
12
+ private
13
+
14
+ def now
15
+ Hyrax::TimeService.time_in_utc.utc.xmlschema
10
16
  end
11
17
  end
12
18
  end
@@ -30,9 +30,7 @@ module Hyrax
30
30
  end
31
31
 
32
32
  def models_to_solr_clause
33
- models.map do |model|
34
- model.respond_to?(:to_rdf_representation) ? model.to_rdf_representation : model.name
35
- end.join(',')
33
+ Hyrax::ModelRegistry.rdf_representations_from(models).join(',')
36
34
  end
37
35
 
38
36
  def generic_type_field
@@ -19,8 +19,13 @@ module Hyrax
19
19
  Hyrax.query_service.custom_queries.find_count_by(models: allowable_types)
20
20
  end
21
21
 
22
- def where(hash)
23
- Hyrax.query_service.find_references_by(resource: hash.values.first, property: hash.keys.first)
22
+ def where(hash_or_string)
23
+ case hash_or_string
24
+ when String
25
+ Hyrax::SolrService.query(hash_or_string)
26
+ else
27
+ Hyrax.query_service.find_references_by(resource: hash_or_string.values.first, property: hash_or_string.keys.first)
28
+ end
24
29
  end
25
30
 
26
31
  def ==(other)
@@ -136,7 +136,7 @@ module Hyrax
136
136
  #
137
137
  # @return [Boolean]
138
138
  def pending_changes?
139
- change_set.changed?
139
+ !change_set.resource.persisted? || change_set.changed?
140
140
  end
141
141
 
142
142
  ##
@@ -10,7 +10,7 @@ module Hyrax
10
10
  # @see Hyrax::PermissionTemplate
11
11
  # @see Sipity::Workflow
12
12
  class AdminSetCreateService # rubocop:disable Metrics/ClassLength
13
- DEFAULT_ID = 'admin_set/default'
13
+ DEFAULT_ID = 'admin_set_default'
14
14
  DEFAULT_TITLE = ['Default Admin Set'].freeze
15
15
 
16
16
  class_attribute :permissions_create_service, :default_admin_set_persister
@@ -124,11 +124,22 @@ module Hyrax
124
124
  # do not support hardcoded IDs (e.g. postgres)
125
125
  # @return [Hyrax::AdministrativeSet] the default admin set; nil if not found
126
126
  def find_unsaved_default_admin_set
127
- admin_set = Hyrax.query_service.find_by(id: DEFAULT_ID)
128
- default_admin_set_persister.update(default_admin_set_id: DEFAULT_ID) if save_default?
127
+ admin_set = begin
128
+ # to support repositories still using the deprecated 'admin_set/default' as DEFAULT_ID
129
+ Hyrax.query_service.find_by(id: 'admin_set/default')
130
+ rescue Ldp::BadRequest, Valkyrie::Persistence::ObjectNotFoundError
131
+ # Fedora 6.5+ does not support slashes in IDs, hence the need to rescue Ldp::BadRequest
132
+ # if an admin set with deprecated ID 'admin_set/default' does not exist, check again for admin set with DEFAULT_ID
133
+ begin
134
+ Hyrax.query_service.find_by(id: DEFAULT_ID)
135
+ rescue Valkyrie::Persistence::ObjectNotFoundError
136
+ nil
137
+ end
138
+ end
139
+
140
+ default_admin_set_persister.update(default_admin_set_id: admin_set.id.to_s) if admin_set.present? && save_default?
141
+
129
142
  admin_set
130
- rescue Valkyrie::Persistence::ObjectNotFoundError
131
- # a default admin set hasn't been created yet
132
143
  end
133
144
 
134
145
  # @return [String | nil] the default admin set id; returns nil if not set
@@ -51,9 +51,10 @@ module Hyrax
51
51
  # @return [Hash] admin set id keys and file count values
52
52
  def count_files(admin_sets)
53
53
  file_counts = Hash.new(0)
54
+ file_set_models = Hyrax::ModelRegistry.file_set_rdf_representations
54
55
  admin_sets.each do |admin_set|
55
56
  query = "{!join from=member_ids_ssim to=id}isPartOf_ssim:#{admin_set.id}"
56
- file_results = Hyrax::SolrService.get(fq: [query, "{!terms f=has_model_ssim}FileSet,Hyrax::FileSet"], rows: 0)
57
+ file_results = Hyrax::SolrService.get(fq: [query, "{!terms f=has_model_ssim}#{file_set_models.join(',')}"], rows: 0)
57
58
  file_counts[admin_set.id] = file_results['response']['numFound']
58
59
  end
59
60
  file_counts
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+ module Hyrax
3
+ module Analytics
4
+ module Ga4
5
+ class Base
6
+ attr_reader :start_date, :end_date, :dimensions, :metrics
7
+
8
+ def initialize(start_date:,
9
+ end_date:,
10
+ dimensions: [],
11
+ metrics: [])
12
+ @start_date = start_date.to_date
13
+ @end_date = end_date.to_date
14
+ @dimensions = dimensions
15
+ @metrics = metrics
16
+ end
17
+
18
+ def filters
19
+ @filters ||= {}
20
+ end
21
+
22
+ def filters=(value)
23
+ value
24
+ end
25
+
26
+ def add_filter(dimension:, values:)
27
+ # reset any cached results
28
+ @results = nil
29
+ filters[dimension] ||= []
30
+ filters[dimension] += values
31
+ end
32
+
33
+ def results
34
+ @results ||= Hyrax::Analytics.client.run_report(report).rows
35
+ end
36
+
37
+ def report
38
+ ::Google::Analytics::Data::V1beta::RunReportRequest.new(
39
+ property: Hyrax::Analytics.property,
40
+ metrics: metrics,
41
+ date_ranges: [{ start_date: start_date.iso8601, end_date: end_date.iso8601 }],
42
+ dimensions: dimensions,
43
+ dimension_filter: dimension_filter
44
+ )
45
+ end
46
+
47
+ def dimension_filter
48
+ return nil if filters.blank?
49
+ {
50
+ and_group: {
51
+ expressions: dimension_expressions
52
+ }
53
+ }
54
+ end
55
+
56
+ def dimension_expressions
57
+ filters.map do |dimension, values|
58
+ {
59
+ filter: {
60
+ field_name: dimension,
61
+ in_list_filter: { values: values.uniq }
62
+ }
63
+ }
64
+ end
65
+ end
66
+
67
+ def results_array(target_type = nil)
68
+ r = {}
69
+ # prefill dates so that all dates at least have 0
70
+ (start_date..end_date).each do |date|
71
+ r[date] = 0
72
+ end
73
+ results.each do |result|
74
+ date = unwrap_dimension(metric: result, dimension: 0)
75
+ type = unwrap_dimension(metric: result, dimension: 1)
76
+ next if date.nil? || type.nil?
77
+ next if target_type && type != target_type
78
+ date = date.to_date
79
+ r[date] += unwrap_metric(result)
80
+ end
81
+ Hyrax::Analytics::Results.new(r.to_a)
82
+ end
83
+
84
+ protected
85
+
86
+ def unwrap_dimension(metric:, dimension: 0)
87
+ metric.dimension_values[dimension]&.value
88
+ end
89
+
90
+ def unwrap_metric(metric)
91
+ metric.metric_values.first.value.to_i
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+ module Hyrax
3
+ module Analytics
4
+ module Ga4
5
+ class Events < Hyrax::Analytics::Ga4::Base
6
+ def initialize(start_date:,
7
+ end_date:,
8
+ dimensions: [{ name: 'eventName' }, { name: 'contentType' }, { name: 'contentId' }],
9
+ metrics: [{ name: 'eventCount' }])
10
+ super
11
+ end
12
+
13
+ def self.list(start_date, end_date, action)
14
+ events = Events.new(start_date: start_date, end_date: end_date)
15
+ events.add_filter(dimension: 'eventName', values: [action])
16
+ events.top_result_array
17
+ end
18
+
19
+ def top_result_array
20
+ results.map { |r| [unwrap_dimension(metric: r, dimension: 2), unwrap_metric(r)] }.sort_by { |r| r[1] }
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+ module Hyrax
3
+ module Analytics
4
+ module Ga4
5
+ class EventsDaily < Hyrax::Analytics::Ga4::Base
6
+ def initialize(start_date:,
7
+ end_date:,
8
+ dimensions: [{ name: 'date' }, { name: 'eventName' }, { name: 'contentType' }, { name: 'contentId' }],
9
+ metrics: [{ name: 'eventCount' }])
10
+ super
11
+ end
12
+
13
+ # returns a daily number of events for a specific action
14
+ def self.summary(start_date, end_date, action)
15
+ events_daily = EventsDaily.new(
16
+ start_date: start_date,
17
+ end_date: end_date
18
+ )
19
+ events_daily.add_filter(dimension: 'eventName', values: [action])
20
+ events_daily.results_array
21
+ end
22
+
23
+ # returns a daily number of events for a specific action
24
+ def self.by_id(start_date, end_date, id, action)
25
+ events_daily = EventsDaily.new(
26
+ start_date: start_date,
27
+ end_date: end_date
28
+ )
29
+ events_daily.add_filter(dimension: 'contentId', values: [id])
30
+ events_daily.add_filter(dimension: 'eventName', values: [action])
31
+ events_daily.results_array
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+ module Hyrax
3
+ module Analytics
4
+ module Ga4
5
+ class Visits < Hyrax::Analytics::Ga4::Base
6
+ def initialize(start_date:, end_date:, dimensions: [{ name: 'newVsReturning' }], metrics: [{ name: 'sessions' }])
7
+ super
8
+ end
9
+
10
+ def new_visits
11
+ unwrap_metric(results.detect { |r| unwrap_dimension(metric: r) == 'new' })
12
+ end
13
+
14
+ def return_visits
15
+ unwrap_metric(results.detect { |r| unwrap_dimension(metric: r) == 'returning' })
16
+ end
17
+
18
+ def unknown_visits
19
+ empty_metrics = results.detect { |r| unwrap_dimension(metric: r) == '' }
20
+ not_set_metrics = results.detect { |r| unwrap_dimension(metric: r) == '(not set)' }
21
+ unknown = 0
22
+ unknown += unwrap_metric(empty_metrics) if empty_metrics.present?
23
+ unknown += unwrap_metric(not_set_metrics) if not_set_metrics.present?
24
+ unknown
25
+ end
26
+
27
+ def total_visits
28
+ new_visits + return_visits + unknown_visits
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+ module Hyrax
3
+ module Analytics
4
+ module Ga4
5
+ class VisitsDaily < Hyrax::Analytics::Ga4::Base
6
+ def initialize(start_date:, end_date:, dimensions: [{ name: 'date' }, { name: 'newVsReturning' }], metrics: [{ name: 'sessions' }])
7
+ super
8
+ end
9
+
10
+ def new_visits
11
+ results_array('new')
12
+ end
13
+
14
+ def return_visits
15
+ results_array('returning')
16
+ end
17
+
18
+ def total_visits
19
+ results_array
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,204 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'oauth2'
4
+
5
+ begin
6
+ require "google/analytics/data/v1beta"
7
+ rescue LoadError
8
+ $stderr.puts "Unable to load 'google/analytics/data/v1beta'; this is okay unless you are trying to do analytics reporting."
9
+ end
10
+
11
+ module Hyrax
12
+ module Analytics
13
+ # rubocop:disable Metrics/ModuleLength
14
+ module Ga4
15
+ extend ActiveSupport::Concern
16
+ # rubocop:disable Metrics/BlockLength
17
+ class_methods do
18
+ # Loads configuration options from config/analytics.yml. You only need PRIVATE_KEY_PATH or
19
+ # PRIVATE_KEY_VALUE. VALUE takes precedence.
20
+ # Expected structure:
21
+ # `analytics:`
22
+ # ` ga4:`
23
+ # analytics_id: <%= ENV['GOOGLE_ANALYTICS_ID'] %>
24
+ # property_id: <%= ENV['GOOGLE_ANALYTICS_PROPERTY_ID'] %>
25
+ # account_json: <%= ENV['GOOGLE_ACCOUNT_JSON'] %>
26
+ # account_json_path: <%= ENV['GOOGLE_ACCOUNT_JSON_PATH'] %>
27
+ # @return [Config]
28
+ def config
29
+ @config ||= Config.load_from_yaml
30
+ end
31
+
32
+ class Config
33
+ def self.load_from_yaml
34
+ filename = Rails.root.join('config', 'analytics.yml')
35
+ yaml = YAML.safe_load(ERB.new(File.read(filename)).result)
36
+ unless yaml
37
+ Hyrax.logger.error("Unable to fetch any keys from #{filename}.")
38
+ return new({})
39
+ end
40
+ config = yaml.fetch('analytics')&.fetch('ga4', nil)
41
+ unless config
42
+ Deprecation.warn("Deprecated analytics configuration format found. Please update config/analytics.yml.")
43
+ config = yaml.fetch('analytics')
44
+ # this has to exist here with a placeholder so it can be set in the Hyrax initializer
45
+ # it is only for backward compatibility
46
+ config['analytics_id'] = '-'
47
+ end
48
+ new config
49
+ end
50
+
51
+ KEYS = %w[analytics_id property_id account_json account_json_path].freeze
52
+ REQUIRED_KEYS = %w[analytics_id property_id].freeze
53
+
54
+ def initialize(config)
55
+ @config = config
56
+ end
57
+
58
+ # @return [Boolean] are all the required values present?
59
+ def valid?
60
+ return false unless @config['account_json'].present? || @config['account_json_path'].present?
61
+
62
+ REQUIRED_KEYS.all? { |required| @config[required].present? }
63
+ end
64
+
65
+ def base64?(value)
66
+ value.is_a?(String) && Base64.strict_encode64(Base64.decode64(value)) == value
67
+ end
68
+
69
+ def account_json_string
70
+ return @account_json_string if @account_json_string
71
+ @account_json_string = if @config['account_json']
72
+ base64?(@config['account_json']) ? Base64.decode64(@config['account_json']) : @config['account_json']
73
+ else
74
+ File.read(@config['account_json_path'])
75
+ end
76
+ end
77
+
78
+ def account_info
79
+ @account_info ||= JSON.parse(account_json_string)
80
+ end
81
+
82
+ KEYS.each do |key|
83
+ # rubocop:disable Style/EvalWithLocation
84
+ class_eval %{ def #{key}; @config.fetch('#{key}'); end }
85
+ class_eval %{ def #{key}=(value); @config['#{key}'] = value; end }
86
+ # rubocop:enable Style/EvalWithLocation
87
+ end
88
+ end
89
+
90
+ def client
91
+ @client ||= ::Google::Analytics::Data::V1beta::AnalyticsData::Client.new do |conf|
92
+ conf.credentials = config.account_info
93
+ end
94
+ end
95
+
96
+ def property
97
+ "properties/#{config.property_id}"
98
+ end
99
+
100
+ # rubocop:disable Metrics/MethodLength
101
+ def to_date_range(period)
102
+ case period
103
+ when "day"
104
+ start_date = Time.zone.today
105
+ end_date = Time.zone.today
106
+ when "week"
107
+ start_date = Time.zone.today - 7.days
108
+ end_date = Time.zone.today
109
+ when "month"
110
+ start_date = Time.zone.today - 1.month
111
+ end_date = Time.zone.today
112
+ when "year"
113
+ start_date = Time.zone.today - 1.year
114
+ end_date = Time.zone.today
115
+ end
116
+
117
+ [start_date, end_date]
118
+ end
119
+ # rubocop:enable Metrics/MethodLength
120
+
121
+ def keyword_conversion(date)
122
+ case date
123
+ when "last12"
124
+ start_date = Time.zone.today - 11.months
125
+ end_date = Time.zone.today
126
+
127
+ [start_date, end_date]
128
+ else
129
+ date.split(",")
130
+ end
131
+ end
132
+
133
+ def date_period(period, date)
134
+ if period == "range"
135
+ date.split(",")
136
+ else
137
+ to_date_range(period)
138
+ end
139
+ end
140
+
141
+ # Configure analytics_start_date in ENV file
142
+ def default_date_range
143
+ "#{Hyrax.config.analytics_start_date},#{Time.zone.today + 1.day}"
144
+ end
145
+
146
+ # The number of events by day for an action
147
+ def daily_events(action, date = default_date_range)
148
+ date = date.split(",")
149
+ EventsDaily.summary(date[0], date[1], action)
150
+ end
151
+
152
+ # The number of events by day for an action and ID
153
+ def daily_events_for_id(id, action, date = default_date_range)
154
+ date = date.split(",")
155
+ EventsDaily.by_id(date[0], date[1], id, action)
156
+ end
157
+
158
+ # A list of events sorted by highest event count
159
+ def top_events(action, date = default_date_range)
160
+ date = date.split(",")
161
+ Events.list(date[0], date[1], action)
162
+ end
163
+
164
+ def unique_visitors(date = default_date_range); end
165
+
166
+ def unique_visitors_for_id(id, date = default_date_range); end
167
+
168
+ def new_visitors(period = 'month', date = default_date_range)
169
+ start_date, end_date = date_period(period, date)
170
+ Visits.new(start_date: start_date, end_date: end_date).new_visits
171
+ end
172
+
173
+ def new_visits_by_day(date = default_date_range, period = 'range')
174
+ start_date, end_date = date_period(period, date)
175
+ VisitsDaily.new(start_date: start_date, end_date: end_date).new_visits
176
+ end
177
+
178
+ def returning_visitors(period = 'month', date = default_date_range)
179
+ start_date, end_date = date_period(period, date)
180
+ Visits.new(start_date: start_date, end_date: end_date).return_visits
181
+ end
182
+
183
+ def returning_visits_by_day(date = default_date_range, period = 'range')
184
+ start_date, end_date = date_period(period, date)
185
+ VisitsDaily.new(start_date: start_date, end_date: end_date).return_visits
186
+ end
187
+
188
+ def total_visitors(period = 'month', date = default_date_range)
189
+ start_date, end_date = date_period(period, date)
190
+ Visits.new(start_date: start_date, end_date: end_date).total_visits
191
+ end
192
+
193
+ def page_statistics(start_date, object)
194
+ visits = VisitsDaily.new(start_date: start_date, end_date: Date.yesterday)
195
+ visits.add_filter(dimension: 'contentId', values: [object.id.to_s])
196
+ visits.total_visits
197
+ end
198
+ end
199
+ # rubocop:enable Metrics/BlockLength
200
+ end
201
+ # rubocop:enable Metrics/ModuleLength
202
+ end
203
+ end
204
+ # rubocop:enable Metrics/ModuleLength
@@ -55,7 +55,6 @@ module Hyrax
55
55
  # @return [Boolean] are all the required values present?
56
56
  def valid?
57
57
  return false unless @config['privkey_value'].present? || @config['privkey_path'].present?
58
-
59
58
  REQUIRED_KEYS.all? { |required| @config[required].present? }
60
59
  end
61
60
 
@@ -203,10 +202,25 @@ module Hyrax
203
202
  date = date_period(period, date)
204
203
  Visits.total_visits(profile, date[0], date[1])
205
204
  end
205
+
206
+ # Hyrax::Download is sent to Hyrax::Analytics.profile as #hyrax__download
207
+ # see Legato::ProfileMethods.method_name_from_klass
208
+ def page_statistics(start_date, object)
209
+ path = Rails.application.routes.url_helpers.polymorphic_path(object)
210
+ profile = Hyrax::Analytics.profile
211
+ unless profile
212
+ Hyrax.logger.error("Google Analytics profile has not been established. Unable to fetch statistics.")
213
+ return []
214
+ end
215
+ profile.hyrax__pageview(sort: 'date',
216
+ start_date: start_date,
217
+ end_date: Date.yesterday,
218
+ limit: 10_000)
219
+ .for_path(path)
220
+ end
206
221
  end
207
222
  # rubocop:enable Metrics/BlockLength
208
223
  end
209
224
  # rubocop:enable Metrics/ModuleLength
210
225
  end
211
226
  end
212
- # rubocop:enable Metrics/ModuleLength
@@ -154,24 +154,37 @@ module Hyrax
154
154
  response["nb_visits_returning"].to_i + response["nb_visits_new"].to_i
155
155
  end
156
156
 
157
+ # TODO: implement
158
+ def page_statistics(_start_date, _object)
159
+ []
160
+ end
161
+
157
162
  def results_array(response, metric)
158
163
  results = []
159
164
  response.each do |result|
160
165
  if result[1].empty?
161
166
  results.push([result[0].to_date, 0])
162
167
  elsif result[1].is_a?(Array)
163
- results.push([result[0].to_date, result[1].first[metric]])
168
+ results.push([result[0].to_date, result[1].first[metric].to_i])
164
169
  else
165
- results.push([result[0].to_date, result[1][metric].presence || 0])
170
+ results.push([result[0].to_date, result[1][metric].presence.to_i])
166
171
  end
167
172
  end
168
173
  Hyrax::Analytics::Results.new(results)
169
174
  end
170
175
 
176
+ # If Matomo detects an error it will return a reponse with the key {"result":"error"}
177
+ # instead of returning an error status code. This method checks for that key.
178
+ def contains_matomo_error?(response)
179
+ response.is_a?(Hash) && response["result"] == "error"
180
+ end
181
+
171
182
  def get(params)
172
183
  response = Faraday.get(config.base_url, params)
173
184
  return [] if response.status != 200
174
- JSON.parse(response.body)
185
+ api_response = JSON.parse(response.body)
186
+ return [] if contains_matomo_error?(api_response)
187
+ api_response
175
188
  end
176
189
 
177
190
  def api_params(method, period, date, additional_params = {})
@@ -74,6 +74,12 @@ module Hyrax
74
74
  fields = [:date, :pageviews]
75
75
  results.map { |row| fields.zip(row).to_h }
76
76
  end
77
+
78
+ def each
79
+ results.each do |result|
80
+ yield({ date: result[0], pageviews: result[1] })
81
+ end
82
+ end
77
83
  end
78
84
  end
79
85
  end
@@ -20,7 +20,7 @@ module Hyrax
20
20
  .find_inverse_references_by(resource: resource, property: :access_to)
21
21
  .find { |r| r.is_a?(Hyrax::AccessControl) } ||
22
22
  raise(Valkyrie::Persistence::ObjectNotFoundError)
23
- rescue ArgumentError # some adapters raise ArgumentError for missing resources
23
+ rescue ArgumentError, Ldp::Gone, Ldp::NotFound # some adapters raise ArgumentError for missing resources
24
24
  raise(Valkyrie::Persistence::ObjectNotFoundError)
25
25
  end
26
26
  end