sufia 7.0.0.beta4 → 7.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (164) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +0 -1
  3. data/.rubocop_todo.yml +1 -2
  4. data/.travis.yml +1 -0
  5. data/Gemfile +18 -9
  6. data/README.md +23 -3
  7. data/app/assets/javascripts/sufia.js +4 -1
  8. data/app/assets/javascripts/sufia/app.js +15 -3
  9. data/app/assets/javascripts/sufia/autocomplete.es6 +51 -0
  10. data/app/assets/javascripts/sufia/autocomplete/language.es6 +25 -0
  11. data/app/assets/javascripts/sufia/autocomplete/location.es6 +24 -0
  12. data/app/assets/javascripts/sufia/autocomplete/subject.es6 +26 -0
  13. data/app/assets/javascripts/sufia/batch_edit.js +8 -5
  14. data/app/assets/javascripts/sufia/permissions/control.es6 +7 -3
  15. data/app/assets/javascripts/sufia/save_work/required_fields.es6 +10 -4
  16. data/app/assets/javascripts/sufia/save_work/save_work_control.es6 +14 -4
  17. data/app/assets/stylesheets/sufia/_fixedsticky.scss +23 -21
  18. data/app/assets/stylesheets/sufia/_form-progress.scss +16 -7
  19. data/app/assets/stylesheets/sufia/_header.scss +2 -1
  20. data/app/assets/stylesheets/sufia/_settings.scss +4 -0
  21. data/app/controllers/api/items_controller.rb +2 -2
  22. data/app/controllers/api/zotero_controller.rb +1 -1
  23. data/app/controllers/citations_controller.rb +0 -2
  24. data/app/controllers/concerns/sufia/batch_edits_controller_behavior.rb +7 -7
  25. data/app/controllers/concerns/sufia/batch_uploads_controller_behavior.rb +9 -3
  26. data/app/controllers/concerns/sufia/singular_subresource_controller.rb +6 -1
  27. data/app/controllers/concerns/sufia/transfers_controller_behavior.rb +1 -1
  28. data/app/controllers/concerns/sufia/users_controller_behavior.rb +3 -3
  29. data/app/controllers/concerns/sufia/works_controller_behavior.rb +11 -4
  30. data/app/controllers/my/highlights_controller.rb +1 -1
  31. data/app/forms/sufia/forms/batch_edit_form.rb +10 -6
  32. data/app/forms/sufia/forms/batch_upload_form.rb +2 -2
  33. data/app/forms/sufia/forms/collection_form.rb +4 -0
  34. data/app/forms/sufia/forms/work_form.rb +4 -0
  35. data/app/helpers/sufia/blacklight_override.rb +0 -20
  36. data/app/helpers/sufia/collections_helper.rb +12 -0
  37. data/app/helpers/sufia/sufia_helper_behavior.rb +84 -56
  38. data/app/jobs/batch_create_job.rb +18 -2
  39. data/app/jobs/content_depositor_change_event_job.rb +13 -6
  40. data/app/jobs/create_work_job.rb +6 -2
  41. data/app/models/batch_upload_item.rb +15 -0
  42. data/app/models/concerns/sufia/ability.rb +7 -4
  43. data/app/models/concerns/sufia/user.rb +0 -11
  44. data/app/models/concerns/sufia/work_behavior.rb +1 -0
  45. data/app/models/concerns/sufia/works/featured.rb +23 -0
  46. data/app/models/file_download_stat.rb +9 -12
  47. data/app/models/file_view_stat.rb +5 -15
  48. data/app/models/proxy_deposit_request.rb +11 -7
  49. data/app/models/sufia/statistic.rb +65 -0
  50. data/app/models/work_view_stat.rb +5 -16
  51. data/app/presenters/file_usage.rb +3 -4
  52. data/app/presenters/sufia/file_set_presenter.rb +1 -3
  53. data/app/presenters/sufia/trophy_presenter.rb +28 -0
  54. data/app/presenters/sufia/user_profile_presenter.rb +1 -1
  55. data/app/presenters/work_usage.rb +5 -4
  56. data/app/search_builders/deposit_search_builder.rb +4 -3
  57. data/app/search_builders/parent_collection_search_builder.rb +1 -1
  58. data/app/services/sufia/collection_member_service.rb +1 -1
  59. data/app/services/sufia/user_stat_importer.rb +11 -6
  60. data/app/views/_controls.html.erb +11 -9
  61. data/app/views/batch_edits/edit.html.erb +8 -2
  62. data/app/views/catalog/_index_list_default.html.erb +2 -1
  63. data/app/views/curation_concerns/base/_form_metadata.html.erb +1 -1
  64. data/app/views/curation_concerns/base/_form_progress.html.erb +1 -1
  65. data/app/views/curation_concerns/base/_form_relationships.html.erb +1 -1
  66. data/app/views/curation_concerns/base/_guts4form.html.erb +6 -2
  67. data/app/views/curation_concerns/base/_items.html.erb +1 -1
  68. data/app/views/curation_concerns/base/edit.html.erb +1 -1
  69. data/app/views/curation_concerns/base/new.html.erb +1 -1
  70. data/app/views/curation_concerns/file_sets/_permission.html.erb +5 -1
  71. data/app/views/curation_concerns/file_sets/media_display/_default.html.erb +1 -1
  72. data/app/views/curation_concerns/file_sets/show.html.erb +1 -1
  73. data/app/views/dashboard/_index_partials/_heading_actions.html.erb +1 -1
  74. data/app/views/{error → errors}/404.html.erb +0 -0
  75. data/app/views/records/edit_fields/_based_near.html.erb +8 -0
  76. data/app/views/records/edit_fields/_language.html.erb +8 -0
  77. data/app/views/records/edit_fields/_subject.html.erb +8 -0
  78. data/app/views/stats/work.html.erb +1 -1
  79. data/app/views/sufia/batch_uploads/_form.html.erb +1 -1
  80. data/app/views/sufia/homepage/_home_header.html.erb +1 -1
  81. data/app/views/sufia/homepage/_sortable_featured.html.erb +1 -1
  82. data/app/views/transfers/new.html.erb +3 -1
  83. data/app/views/users/_contributions.html.erb +1 -1
  84. data/config/locales/sufia.en.yml +3 -2
  85. data/config/routes.rb +0 -7
  86. data/lib/generators/sufia/install_generator.rb +0 -24
  87. data/lib/generators/sufia/templates/catalog_controller.rb +4 -3
  88. data/lib/generators/sufia/templates/config/sufia.rb +4 -2
  89. data/lib/generators/sufia/upgrade700_generator.rb +7 -9
  90. data/lib/generators/sufia/work_generator.rb +56 -0
  91. data/lib/sufia.rb +4 -1
  92. data/lib/sufia/arkivo/actor.rb +1 -1
  93. data/lib/sufia/configuration.rb +15 -3
  94. data/lib/sufia/engine.rb +1 -10
  95. data/lib/sufia/version.rb +1 -1
  96. data/spec/controllers/api/items_controller_spec.rb +20 -7
  97. data/spec/controllers/sufia/batch_uploads_controller_spec.rb +4 -3
  98. data/spec/controllers/transfers_controller_spec.rb +3 -11
  99. data/spec/controllers/users_controller_spec.rb +2 -1
  100. data/spec/features/batch_edit_spec.rb +17 -2
  101. data/spec/forms/sufia/forms/batch_edit_form_spec.rb +2 -0
  102. data/spec/forms/sufia/forms/batch_upload_form_spec.rb +1 -1
  103. data/spec/helpers/blacklight_helper_spec.rb +36 -26
  104. data/spec/helpers/{generic_work_helper_spec.rb → sufia/collections_helper_spec.rb} +1 -1
  105. data/spec/helpers/sufia_helper_spec.rb +70 -32
  106. data/spec/javascripts/autocomplete_spec.js.coffee +7 -7
  107. data/spec/javascripts/save_work_spec.js +20 -20
  108. data/spec/lib/sufia/configuration_spec.rb +30 -0
  109. data/spec/lib/sufia/user_stat_importer_spec.rb +21 -36
  110. data/spec/models/file_download_stat_spec.rb +8 -8
  111. data/spec/models/file_view_stat_spec.rb +8 -8
  112. data/spec/models/generic_work_spec.rb +24 -0
  113. data/spec/models/proxy_deposit_request_spec.rb +2 -4
  114. data/spec/models/sufia/ability_spec.rb +7 -13
  115. data/spec/models/user_spec.rb +0 -14
  116. data/spec/models/work_view_stat_spec.rb +22 -8
  117. data/spec/presenters/sufia/file_usage_spec.rb +0 -4
  118. data/spec/presenters/sufia/trophy_presenter_spec.rb +46 -0
  119. data/spec/presenters/sufia/user_profile_presenter_spec.rb +4 -1
  120. data/spec/presenters/sufia/work_usage_spec.rb +8 -17
  121. data/spec/routing/route_spec.rb +0 -6
  122. data/spec/spec_helper.rb +8 -2
  123. data/spec/test_app_templates/lib/generators/test_app_generator.rb +4 -0
  124. data/spec/views/batch_edits/edit.html.erb_spec.rb +8 -2
  125. data/spec/views/catalog/_index_list_default.html.erb_spec.rb +8 -6
  126. data/spec/views/curation_concerns/base/_form.html.erb_spec.rb +3 -0
  127. data/spec/views/curation_concerns/file_sets/_permission.html.erb_spec.rb +16 -0
  128. data/spec/views/curation_concerns/file_sets/show.html.erb_spec.rb +0 -2
  129. data/spec/views/records/edit_fields/_based_near.html.erb_spec.rb +20 -0
  130. data/spec/views/records/edit_fields/_language.html.erb_spec.rb +20 -0
  131. data/spec/views/records/edit_fields/_subject.html.erb_spec.rb +20 -0
  132. data/spec/views/{homepage → sufia/homepage}/_announcement.html.erb_spec.rb +0 -0
  133. data/spec/views/{homepage → sufia/homepage}/_featured_works.html.erb_spec.rb +0 -0
  134. data/spec/views/{homepage → sufia/homepage}/_home_header.html.erb_spec.rb +0 -0
  135. data/spec/views/sufia/homepage/_sortable_featured.html.erb_spec.rb +21 -0
  136. data/spec/views/users/edit.html.erb_spec.rb +5 -5
  137. data/spec/views/users/show.html.erb_spec.rb +5 -3
  138. data/sufia.gemspec +4 -3
  139. data/tasks/noid.rake +2 -2
  140. data/tasks/sufia-dev.rake +1 -1
  141. metadata +73 -68
  142. data/app/assets/javascripts/sufia/edit_metadata.js +0 -87
  143. data/app/controllers/authorities_controller.rb +0 -19
  144. data/app/helpers/generic_work_helper.rb +0 -10
  145. data/app/helpers/sufia_url_helper.rb +0 -14
  146. data/app/models/concerns/sufia/file_stat_utils.rb +0 -33
  147. data/app/models/concerns/sufia/work_stat_utils.rb +0 -33
  148. data/app/models/geo_names_resource.rb +0 -18
  149. data/app/models/local_authority.rb +0 -101
  150. data/app/models/local_authority_entry.rb +0 -3
  151. data/app/models/subject_local_authority_entry.rb +0 -2
  152. data/app/views/curation_concerns/generic_works/_generic_work.html.erb +0 -3
  153. data/app/views/error/401.html.erb +0 -18
  154. data/app/views/error/500.html.erb +0 -9
  155. data/app/views/error/single_use_error.html.erb +0 -19
  156. data/lib/generators/sufia/geonames_username_config_generator.rb +0 -20
  157. data/spec/controllers/authorities_controller_spec.rb +0 -18
  158. data/spec/fixtures/cities15000.tsv +0 -149
  159. data/spec/fixtures/genreForms.nt +0 -471
  160. data/spec/fixtures/lexvo.rdf +0 -3108
  161. data/spec/helpers/sufia_url_helper_spec.rb +0 -18
  162. data/spec/models/geo_names_resource_spec.rb +0 -30
  163. data/spec/models/local_authority_spec.rb +0 -108
  164. data/vendor/assets/javascripts/almond.js +0 -430
@@ -1,26 +1,28 @@
1
- .fixedsticky {
2
- position: -webkit-sticky;
3
- position: -moz-sticky;
4
- position: -ms-sticky;
5
- position: -o-sticky;
6
- position: sticky;
7
- }
1
+ @media (min-width: $screen-sm-min) {
2
+ .fixedsticky {
3
+ position: -webkit-sticky;
4
+ position: -moz-sticky;
5
+ position: -ms-sticky;
6
+ position: -o-sticky;
7
+ position: sticky;
8
+ }
8
9
 
9
- /* When position: sticky is supported but native behavior is ignored */
10
- .fixedsticky-withoutfixedfixed .fixedsticky-off,
11
- .fixed-supported .fixedsticky-off {
12
- position: static;
13
- }
10
+ /* When position: sticky is supported but native behavior is ignored */
11
+ .fixedsticky-withoutfixedfixed .fixedsticky-off,
12
+ .fixed-supported .fixedsticky-off {
13
+ position: static;
14
+ }
14
15
 
15
- .fixedsticky-withoutfixedfixed .fixedsticky-on,
16
- .fixed-supported .fixedsticky-on {
17
- position: fixed;
18
- }
16
+ .fixedsticky-withoutfixedfixed .fixedsticky-on,
17
+ .fixed-supported .fixedsticky-on {
18
+ position: fixed;
19
+ }
19
20
 
20
- .fixedsticky-dummy {
21
- display: none;
22
- }
21
+ .fixedsticky-dummy {
22
+ display: none;
23
+ }
23
24
 
24
- .fixedsticky-on + .fixedsticky-dummy {
25
- display: block;
25
+ .fixedsticky-on + .fixedsticky-dummy {
26
+ display: block;
27
+ }
26
28
  }
@@ -1,12 +1,21 @@
1
- .fixedsticky {
2
- top: 0; /* Required to get consistent results in Safari and Chrome */
1
+ @media (min-width: $screen-xs-min) {
2
+ .fixedsticky {
3
+ margin-top: 1em;
4
+ }
3
5
  }
4
6
 
5
- .fixedsticky-withoutfixedfixed .fixedsticky-on,
6
- .fixed-supported .fixedsticky-on {
7
- left: $save-viz-widget-left;
8
- /* Required so that the widget doesn't pop back to top when public desc long */
9
- bottom: $save-viz-widget-bottom;
7
+ @media (min-width: $screen-sm-min) {
8
+ .fixedsticky {
9
+ margin-top: 0;
10
+ top: 0; /* Required to get consistent results in Safari and Chrome */
11
+ }
12
+
13
+ .fixedsticky-withoutfixedfixed .fixedsticky-on,
14
+ .fixed-supported .fixedsticky-on {
15
+ left: $save-viz-widget-left;
16
+ /* Required so that the widget doesn't pop back to top when public desc long */
17
+ bottom: $save-viz-widget-bottom;
18
+ }
10
19
  }
11
20
 
12
21
  aside.form-progress {
@@ -1,5 +1,6 @@
1
1
  #search-form-header {
2
- margin-top: 6px;
2
+ margin-top: $search-bar-margin-top;
3
+ margin-right: $search-bar-margin-right;
3
4
  }
4
5
 
5
6
  #masthead {
@@ -6,6 +6,10 @@
6
6
  $classic-white: #FFF !default;
7
7
  $vermilion: #F30 !default;
8
8
 
9
+ // Nav and Search Bar
10
+ $search-bar-margin-top: 0.50em;
11
+ $search-bar-margin-right: 0.95em;
12
+
9
13
  // Dashboard
10
14
  $dashboard-border-color: $gray-lighter !default;
11
15
 
@@ -1,7 +1,7 @@
1
1
  module API
2
2
  # Adds an endpoint that consumes and RESTfully emits JSON from Arkivo
3
3
  # representing new and updated Zotero-managed publications. An item in the
4
- # Zotero parlance is mapped to a GenericWork in Sufia.
4
+ # Zotero parlance is mapped to a work in Sufia.
5
5
  class ItemsController < ApplicationController
6
6
  skip_before_action :verify_authenticity_token
7
7
  before_action :validate_item, only: [:create, :update]
@@ -31,7 +31,7 @@ module API
31
31
  private
32
32
 
33
33
  def my_load_and_authorize_resource
34
- @work = GenericWork.find(params[:id])
34
+ @work = CurationConcerns::WorkRelation.new.find(params[:id])
35
35
 
36
36
  unless user.can? :edit, @work
37
37
  return render plain: "#{user} lacks access to #{@work}", status: :unauthorized
@@ -34,7 +34,7 @@ module API
34
34
  private
35
35
 
36
36
  def authorize_user!
37
- authorize! :create, ::GenericWork
37
+ authorize! :create, Sufia.primary_work_type
38
38
  rescue CanCan::AccessDenied
39
39
  return redirect_to root_url, alert: 'You are not authorized to perform this operation'
40
40
  end
@@ -6,13 +6,11 @@ class CitationsController < ApplicationController
6
6
  before_action :build_breadcrumbs, only: [:work, :file]
7
7
 
8
8
  def work
9
- @curation_concern_type = GenericWork
10
9
  @presenter_class = Sufia::WorkShowPresenter
11
10
  show
12
11
  end
13
12
 
14
13
  def file
15
- @curation_concern_type = FileSet
16
14
  @presenter_class = Sufia::FileSetPresenter
17
15
  show
18
16
  end
@@ -10,9 +10,9 @@ module Sufia
10
10
 
11
11
  def edit
12
12
  super
13
- generic_work = ::GenericWork.new
14
- generic_work.depositor = current_user.user_key
15
- @form = form_class.new(generic_work, current_user, batch)
13
+ work = form_class.model_class.new
14
+ work.depositor = current_user.user_key
15
+ @form = form_class.new(work, current_user, batch)
16
16
  end
17
17
 
18
18
  def after_update
@@ -27,7 +27,7 @@ module Sufia
27
27
  end
28
28
 
29
29
  def update_document(obj)
30
- obj.attributes = generic_work_params
30
+ obj.attributes = work_params
31
31
  obj.date_modified = Time.current.ctime
32
32
  obj.visibility = params[:visibility]
33
33
  end
@@ -65,9 +65,9 @@ module Sufia
65
65
  form_class.terms
66
66
  end
67
67
 
68
- def generic_work_params
69
- generic_work_params = params[:generic_work] || ActionController::Parameters.new
70
- form_class.model_attributes(generic_work_params)
68
+ def work_params
69
+ work_params = params[form_class.model_name.param_key] || ActionController::Parameters.new
70
+ form_class.model_attributes(work_params)
71
71
  end
72
72
 
73
73
  def redirect_to_return_controller
@@ -6,22 +6,28 @@ module Sufia
6
6
 
7
7
  included do
8
8
  layout "sufia-one-column"
9
- self.curation_concern_type = GenericWork
9
+ self.curation_concern_type = form_class.model_class
10
10
  end
11
11
 
12
12
  def create
13
13
  authenticate_user!
14
14
  create_update_job
15
- flash[:notice] = t('sufia.generic_works.new.after_create_html', application_name: view_context.application_name)
15
+ flash[:notice] = t('sufia.works.new.after_create_html', application_name: view_context.application_name)
16
16
  redirect_after_update
17
17
  end
18
18
 
19
+ module ClassMethods
20
+ def form_class
21
+ ::Sufia::Forms::BatchUploadForm
22
+ end
23
+ end
24
+
19
25
  protected
20
26
 
21
27
  # Gives the class of the form.
22
28
  # This overrides CurationConcerns
23
29
  def form_class
24
- ::Sufia::Forms::BatchUploadForm
30
+ self.class.form_class
25
31
  end
26
32
 
27
33
  def redirect_after_update
@@ -2,8 +2,9 @@ module Sufia::SingularSubresourceController
2
2
  extend ActiveSupport::Concern
3
3
 
4
4
  included do
5
+ before_action :find_work, only: :work
6
+ load_and_authorize_resource :work, only: :work
5
7
  load_and_authorize_resource :file, class: 'FileSet', only: :file, id_param: :id
6
- load_and_authorize_resource :work, class: 'GenericWork', only: :work, id_param: :id
7
8
  end
8
9
 
9
10
  # Overriding the default behavior from Hydra::Core::ControllerBehavior
@@ -15,4 +16,8 @@ module Sufia::SingularSubresourceController
15
16
  redirect_to new_user_session_path, alert: exception.message
16
17
  end
17
18
  end
19
+
20
+ def find_work
21
+ @work = CurationConcerns::WorkRelation.new.find(params[:id])
22
+ end
18
23
  end
@@ -20,7 +20,7 @@ module Sufia
20
20
  end
21
21
 
22
22
  def new
23
- @generic_work = ::GenericWork.load_instance_from_solr(@id)
23
+ @work = CurationConcerns::WorkRelation.new.find(params[:id])
24
24
  end
25
25
 
26
26
  def create
@@ -5,9 +5,9 @@ module Sufia::UsersControllerBehavior
5
5
  include Blacklight::SearchContext
6
6
  layout "sufia-one-column"
7
7
  prepend_before_action :find_user, except: [:index, :search, :notifications_number]
8
- before_action :authenticate_user!, only: [:edit, :update, :follow, :unfollow, :toggle_trophy]
8
+ before_action :authenticate_user!, only: [:edit, :update, :follow, :unfollow]
9
9
  before_action :user_not_current_user, only: [:follow, :unfollow]
10
- authorize_resource only: [:edit, :update, :toggle_trophy]
10
+ authorize_resource only: [:edit, :update]
11
11
  # Catch permission errors
12
12
  rescue_from CanCan::AccessDenied, with: :deny_access
13
13
  end
@@ -33,7 +33,7 @@ module Sufia::UsersControllerBehavior
33
33
 
34
34
  # Display form for users to edit their profile information
35
35
  def edit
36
- @trophies = @user.trophy_works
36
+ @trophies = Sufia::TrophyPresenter.find_by_user(@user)
37
37
  end
38
38
 
39
39
  # Process changes from profile form
@@ -6,12 +6,19 @@ module Sufia
6
6
  include CurationConcerns::CurationConcernController
7
7
 
8
8
  included do
9
- before_action :build_breadcrumbs, only: [:edit, :show]
10
- self.curation_concern_type = GenericWork
11
9
  self.show_presenter = Sufia::WorkShowPresenter
12
10
  layout "sufia-one-column"
13
11
  end
14
12
 
13
+ module ClassMethods
14
+ # We don't want the breadcrumb action to occur until after the concern has
15
+ # been loaded and authorized
16
+ def curation_concern_type=(curation_concern_type)
17
+ super
18
+ before_action :build_breadcrumbs, only: [:edit, :show]
19
+ end
20
+ end
21
+
15
22
  def new
16
23
  curation_concern.depositor = current_user.user_key
17
24
  super
@@ -46,7 +53,7 @@ module Sufia
46
53
  def after_create_response
47
54
  respond_to do |wants|
48
55
  wants.html do
49
- flash[:notice] = t('sufia.generic_works.new.after_create_html', application_name: view_context.application_name)
56
+ flash[:notice] = t('sufia.works.new.after_create_html', application_name: view_context.application_name)
50
57
  redirect_to [main_app, curation_concern]
51
58
  end
52
59
  wants.json { render :show, status: :created, location: polymorphic_path([main_app, curation_concern]) }
@@ -65,7 +72,7 @@ module Sufia
65
72
  def add_breadcrumb_for_action
66
73
  case action_name
67
74
  when 'edit'.freeze
68
- add_breadcrumb I18n.t("sufia.work.browse_view"), main_app.curation_concerns_generic_work_path(params["id"])
75
+ add_breadcrumb I18n.t("sufia.work.browse_view"), main_app.polymorphic_path(curation_concern)
69
76
  when 'show'.freeze
70
77
  add_breadcrumb presenter.to_s, main_app.polymorphic_path(presenter)
71
78
  end
@@ -16,7 +16,7 @@ module My
16
16
  end
17
17
 
18
18
  def query_solr
19
- return empty_search_result if @user.trophy_works.count == 0
19
+ return empty_search_result if Sufia::TrophyPresenter.find_by_user(@user).count == 0
20
20
  super
21
21
  end
22
22
 
@@ -2,14 +2,17 @@ module Sufia
2
2
  module Forms
3
3
  class BatchEditForm < Sufia::Forms::WorkForm
4
4
  self.terms = [:creator, :contributor, :description,
5
- :keyword, :rights, :publisher, :date_created,
5
+ :keyword, :resource_type, :rights, :publisher, :date_created,
6
6
  :subject, :language, :identifier, :based_near,
7
7
  :related_url]
8
8
  self.required_fields = []
9
- self.model_class = ::GenericWork
9
+ self.model_class = Sufia.primary_work_type
10
10
 
11
11
  attr_accessor :names
12
12
 
13
+ # @param [ActiveFedora::Base] model the model backing the form
14
+ # @param [Ability] current_ability the user authorization model
15
+ # @param [Array<String>] batch a list of document ids in the batch
13
16
  def initialize(model, current_ability, batch)
14
17
  super(model, current_ability)
15
18
  @names = []
@@ -19,18 +22,19 @@ module Sufia
19
22
  private
20
23
 
21
24
  # override this method if you need to initialize more complex RDF assertions (b-nodes)
25
+ # @param [Array<String>] batch a list of document ids in the batch
22
26
  def initialize_combined_fields(batch)
23
27
  combined_attributes = {}
24
28
  permissions = []
25
29
  # For each of the files in the batch, set the attributes to be the concatination of all the attributes
26
30
  batch.each do |doc_id|
27
- gw = ::GenericWork.load_instance_from_solr(doc_id)
31
+ work = model_class.load_instance_from_solr(doc_id)
28
32
  terms.each do |key|
29
33
  combined_attributes[key] ||= []
30
- combined_attributes[key] = (combined_attributes[key] + gw[key]).uniq
34
+ combined_attributes[key] = (combined_attributes[key] + work[key]).uniq
31
35
  end
32
- names << gw.to_s
33
- permissions = (permissions + gw.permissions).uniq
36
+ names << work.to_s
37
+ permissions = (permissions + work.permissions).uniq
34
38
  end
35
39
 
36
40
  terms.each do |key|
@@ -1,13 +1,13 @@
1
1
  module Sufia
2
2
  module Forms
3
3
  class BatchUploadForm < Sufia::Forms::WorkForm
4
- self.model_class = ::GenericWork
4
+ self.model_class = BatchUploadItem
5
5
  include HydraEditor::Form::Permissions
6
6
 
7
7
  self.terms -= [:title, :resource_type]
8
8
 
9
9
  # The WorkForm delegates `#depositor` to `:model`, but `:model` in the
10
- # BatchUpload context is a blank GenericWork with a `nil` depositor
10
+ # BatchUpload context is a blank work with a `nil` depositor
11
11
  # value. This causes the "Sharing With" widget to display the Depositor as
12
12
  # "()". We should be able to reliably pull back the depositor of the new
13
13
  # batch of works by asking the form's Ability what its `current_user` is.
@@ -2,6 +2,10 @@ module Sufia::Forms
2
2
  class CollectionForm < CurationConcerns::Forms::CollectionEditForm
3
3
  delegate :id, to: :model
4
4
 
5
+ # TODO: remove this when https://github.com/projecthydra/hydra-editor/pull/115
6
+ # is merged and hydra-editor 3.0.0 is released
7
+ delegate :model_name, to: :model
8
+
5
9
  def primary_terms
6
10
  [:title]
7
11
  end
@@ -3,6 +3,10 @@ module Sufia::Forms
3
3
  delegate :depositor, :on_behalf_of, :permissions, to: :model
4
4
  include HydraEditor::Form::Permissions
5
5
 
6
+ # TODO: remove this when https://github.com/projecthydra/hydra-editor/pull/115
7
+ # is merged and hydra-editor 3.0.0 is released
8
+ delegate :model_name, to: :model
9
+
6
10
  attr_reader :agreement_accepted
7
11
 
8
12
  self.terms += [:collection_ids]
@@ -1,25 +1,5 @@
1
1
  module Sufia
2
2
  module BlacklightOverride
3
- # TODO: we can remove this override when we can depend on https://github.com/projecthydra-labs/curation_concerns/pull/711
4
- def render_constraints_query(localized_params = params)
5
- # So simple don't need a view template, we can just do it here.
6
- return "".html_safe if localized_params[:q].blank?
7
-
8
- render_constraint_element(constraint_query_label(localized_params),
9
- localized_params[:q],
10
- classes: ["query"],
11
- remove: remove_constraint_url(localized_params))
12
- end
13
-
14
- # TODO: we can remove this override when we can depend on https://github.com/projecthydra-labs/curation_concerns/pull/711
15
- def remove_constraint_url(localized_params)
16
- scope = localized_params.delete(:route_set) || self
17
- options = localized_params.merge(q: nil, action: 'index')
18
- .except(*fields_to_exclude_from_constraint_element)
19
- options.permit!
20
- scope.url_for(options)
21
- end
22
-
23
3
  # This overrides curation_concerns so we aren't removing any fields.
24
4
  # @return [Array<Symbol>] a list of fields to remove on the render_constraint_element
25
5
  # You can override this if you have different fields to remove
@@ -0,0 +1,12 @@
1
+ module Sufia
2
+ module CollectionsHelper
3
+ def render_collection_links(solr_doc)
4
+ collection_list = Sufia::CollectionMemberService.run(solr_doc)
5
+ return if collection_list.empty?
6
+ links = collection_list.map do |collection|
7
+ link_to collection.title_or_label, collection_path(collection.id)
8
+ end
9
+ content_tag :span, safe_join([t('sufia.collection.is_part_of'), ': '] + links)
10
+ end
11
+ end
12
+ end
@@ -1,6 +1,7 @@
1
1
  module Sufia
2
2
  module SufiaHelperBehavior
3
3
  include Sufia::CitationsBehavior
4
+ include ERB::Util # provides html_escape
4
5
 
5
6
  def application_name
6
7
  t('sufia.product_name', default: super)
@@ -28,39 +29,34 @@ module Sufia
28
29
  end
29
30
 
30
31
  # Only Chrome supports this
32
+ # @return [Boolean]
33
+ # @todo Replace uses with more granular client-side detection (as jQuery-fileuploader already does)
31
34
  def browser_supports_directory_upload?
32
35
  user_agent.include? 'Chrome'
33
36
  end
34
37
 
35
- # @param [Hash] options a list of options that blacklight passes from helper_method
36
- # invocation.
37
- def human_readable_date(options)
38
- Date.parse(options[:value]).to_formatted_s(:standard)
39
- end
40
-
41
38
  def error_messages_for(object)
42
- if object.try(:errors) && object.errors.full_messages.any?
43
- content_tag(:div, class: 'alert alert-block alert-error validation-errors') do
44
- content_tag(:h4, I18n.t('sufia.errors.header', model: object.class.model_name.human.downcase), class: 'alert-heading') +
45
- content_tag(:ul) do
46
- object.errors.full_messages.map do |message|
47
- content_tag(:li, message)
48
- end.join('').html_safe
49
- end
50
- end
51
- else
52
- '' # return empty string
39
+ return '' unless object.try(:errors) && object.errors.full_messages.any?
40
+ content_tag(:div, class: 'alert alert-block alert-error validation-errors') do
41
+ content_tag(:h4, I18n.t('sufia.errors.header', model: object.class.model_name.human.downcase), class: 'alert-heading') +
42
+ content_tag(:ul) do
43
+ object.errors.full_messages.map do |message|
44
+ content_tag(:li, message)
45
+ end.join('').html_safe
46
+ end
53
47
  end
54
48
  end
55
49
 
50
+ # @param [ProxyDepositRequest] req
56
51
  def show_transfer_request_title(req)
57
52
  if req.deleted_work? || req.canceled?
58
53
  req.to_s
59
54
  else
60
- link_to(req.to_s, curation_concerns_generic_work_path(req.work_id))
55
+ link_to(req.to_s, req.work)
61
56
  end
62
57
  end
63
58
 
59
+ # @return [Boolean]
64
60
  def has_collection_search_parameters?
65
61
  !params[:cq].blank?
66
62
  end
@@ -69,21 +65,31 @@ module Sufia
69
65
  ActiveFedora::Base.where(DepositSearchBuilder.depositor_field => user.user_key).count
70
66
  end
71
67
 
72
- def link_to_facet(field, field_string)
73
- path = search_action_path(search_state.add_facet_params_and_redirect(field_string, field))
74
- link_to(field, path)
68
+ # @param item [Object]
69
+ # @param field [String]
70
+ # @return [ActiveSupport::SafeBuffer] the html_safe link
71
+ def link_to_facet(item, field)
72
+ path = search_action_path(search_state.add_facet_params_and_redirect(field, item))
73
+ link_to(item, path)
75
74
  end
76
75
 
77
- # @param values [Array] The values to display
78
- # @param solr_field [String] The name of the solr field to link to without its suffix (:facetable)
79
- # @param empty_message [String] ('No value entered') The message to display if no values are passed in.
80
- # @param separator [String] (', ') The value to join with.
81
- def link_to_facet_list(values, solr_field, empty_message = "No value entered", separator = ", ")
76
+ # @param values [Array{String}] strings to display
77
+ # @param solr_field [String] name of the solr field to link to, without its suffix (:facetable)
78
+ # @param empty_message [String] message to display if no values are passed in
79
+ # @param separator [String] value to join with
80
+ # @return [ActiveSupport::SafeBuffer] the html_safe link
81
+ def link_to_facet_list(values, solr_field, empty_message = "No value entered".html_safe, separator = ", ")
82
82
  return empty_message if values.blank?
83
83
  facet_field = Solrizer.solr_name(solr_field, :facetable)
84
84
  safe_join(values.map { |item| link_to_facet(item, facet_field) }, separator)
85
85
  end
86
86
 
87
+ # @param name [String] field name
88
+ # @param value [String] field value
89
+ # @param label [String] defaults to value
90
+ # @param facet_hash [Hash] first argument to Blacklight::SearchState.new
91
+ # @return [ActiveSupport::SafeBuffer] the html_safe link
92
+ # @see Blacklight::SearchState#initialize
87
93
  def link_to_field(name, value, label = nil, facet_hash = {})
88
94
  label ||= value
89
95
  params = { search_field: 'advanced', name => "\"#{value}\"" }
@@ -91,30 +97,57 @@ module Sufia
91
97
  link_to(label, main_app.search_catalog_path(state))
92
98
  end
93
99
 
94
- def index_field_link(options = {})
95
- field_name = options[:config][:field_name]
96
- values = options[:value]
97
- safe_join(values.map { |item| link_to_index_field(item, field_name) }, ", ")
98
- end
100
+ ## GROUP: helper_methods
99
101
 
100
- def link_to_index_field(name, value)
101
- params = { search_field: 'advanced', name => "\"#{value}\"" }
102
- state = search_state.params_for_search(params)
103
- link_to(name, main_app.search_catalog_path(state))
102
+ # A Blacklight helper_method
103
+ # @param [Hash] options from blacklight invocation of helper_method
104
+ # @see #index_field_link params
105
+ # @return [Date]
106
+ def human_readable_date(options)
107
+ Date.parse(options[:value]).to_formatted_s(:standard)
104
108
  end
105
109
 
106
- # @param [String,Hash] text either the string to escape or a hash containing the
107
- # string to escape under the :value key.
108
- def iconify_auto_link(text, showLink = true)
109
- text = presenter(text[:document]).render_values(text[:value], text[:config]) if text.is_a? Hash
110
+ # A Blacklight helper_method
111
+ # @param options [Hash{Symbol=>Object}] Blacklight sends :document, :field, :config, :value and whatever else was in options
112
+ # @option options [Array{String}] :value
113
+ # @option options [Hash] :config including {:field_name => "my_name"}
114
+ # @option options [Hash] :document
115
+ # @option options [Array{String}] :value the strings you might otherwise have passed to this method singly
116
+ # @return [ActiveSupport::SafeBuffer] the html_safe link
117
+ def index_field_link(options)
118
+ raise ArgumentError unless options[:config] && options[:config][:field_name]
119
+ name = options[:config][:field_name]
120
+ values = options[:value]
121
+ safe_join(values.map { |item| link_to_field(name, item, item) }, ", ".html_safe)
122
+ end
123
+
124
+ # Uses Rails auto_link to add links to fields
125
+ #
126
+ # @param field [String,Hash] string to format and escape, or a hash as per helper_method
127
+ # @option field [SolrDocument] :document
128
+ # @option field [String] :field name of the solr field
129
+ # @option field [Blacklight::Configuration::IndexField, Blacklight::Configuration::ShowField] :config
130
+ # @option field [Array] :value array of values for the field
131
+ # @param show_link [Boolean]
132
+ # @return [ActiveSupport::SafeBuffer]
133
+ # @todo stop being a helper_method, start being part of the Blacklight render stack?
134
+ def iconify_auto_link(field, show_link = true)
135
+ if field.is_a? Hash
136
+ options = field[:config].separator_options || {}
137
+ text = field[:value].to_sentence(options)
138
+ else
139
+ text = field
140
+ end
110
141
  # this block is only executed when a link is inserted;
111
142
  # if we pass text containing no links, it just returns text.
112
143
  auto_link(html_escape(text)) do |value|
113
- "<span class='glyphicon glyphicon-new-window'></span>#{('&nbsp;' + value) if showLink}"
144
+ "<span class='glyphicon glyphicon-new-window'></span>#{('&nbsp;' + value) if show_link}"
114
145
  end
115
146
  end
116
147
 
117
- # @param [String,User,Hash] args if a hash, the user_key must be under :value
148
+ # *Sometimes* a Blacklight helper_method
149
+ # @param [String,User,Hash{Symbol=>Array}] args if a hash, the user_key must be under :value
150
+ # @return [ActiveSupport::SafeBuffer] the html_safe link
118
151
  def link_to_profile(args)
119
152
  user_or_key = args.is_a?(Hash) ? args[:value].first : args
120
153
  user = case user_or_key
@@ -124,19 +157,14 @@ module Sufia
124
157
  ::User.find_by_user_key(user_or_key)
125
158
  end
126
159
  return user_or_key if user.nil?
127
-
128
- text = if user.respond_to? :name
129
- user.name
130
- else
131
- user_or_key
132
- end
133
-
160
+ text = user.respond_to?(:name) ? user.name : user_or_key
134
161
  link_to text, Sufia::Engine.routes.url_helpers.profile_path(user)
135
162
  end
136
163
 
137
- # @param [Hash] options hash from blacklight passes from helper_method
138
- # invocation. Maps rights URIs to links with labels.
139
- def rights_statement_links(options = {})
164
+ # A Blacklight helper_method
165
+ # @param [Hash] options from blacklight helper_method invocation. Maps rights URIs to links with labels.
166
+ # @return [ActiveSupport::SafeBuffer] rights statement links, html_safe
167
+ def rights_statement_links(options)
140
168
  options[:value].map { |right| link_to RightsService.label(right), right }.to_sentence.html_safe
141
169
  end
142
170
 
@@ -146,15 +174,13 @@ module Sufia
146
174
  end
147
175
 
148
176
  # Only display the current search parameters if the user is not in the dashboard.
149
- # If they are in the dashboard, then the search defaults to the user's works and not
150
- # all of Sufia.
177
+ # Otherwise, search defaults to the user's works and not all of Sufia.
151
178
  def current_search_parameters
152
179
  return if on_the_dashboard?
153
180
  params[:q]
154
181
  end
155
182
 
156
- # Depending on which page we're landed on, we'll need to set the appropriate action url for
157
- # our search form.
183
+ # @return [String] the appropriate action url for our search form (depending on our current page)
158
184
  def search_form_action
159
185
  if on_the_dashboard?
160
186
  search_action_for_dashboard
@@ -174,7 +200,6 @@ module Sufia
174
200
  def user_display_name_and_key(user_key)
175
201
  user = ::User.find_by_user_key(user_key)
176
202
  return user_key if user.nil?
177
-
178
203
  user.respond_to?(:name) ? "#{user.name} (#{user_key})" : user_key
179
204
  end
180
205
 
@@ -213,6 +238,9 @@ module Sufia
213
238
  end
214
239
  end
215
240
 
241
+ # @param [ActionController::Parameters] params first argument for Blacklight::SearchState.new
242
+ # @param [Hash] facet
243
+ # @note Ignores all but the first facet. Probably a bug.
216
244
  def search_state_with_facets(params, facet = {})
217
245
  state = Blacklight::SearchState.new(params, CatalogController.blacklight_config)
218
246
  return state.params if facet.none?