hyrax 2.1.0.rc2 → 2.1.0.rc3

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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/app/assets/stylesheets/hyrax/_work-show.scss +11 -2
  4. data/app/controllers/hyrax/admin/admin_sets_controller.rb +22 -1
  5. data/app/jobs/import_url_job.rb +50 -18
  6. data/app/models/concerns/hyrax/ability/admin_set_ability.rb +1 -1
  7. data/app/presenters/hyrax/file_set_presenter.rb +4 -0
  8. data/app/presenters/hyrax/work_show_presenter.rb +2 -2
  9. data/app/services/hyrax/collections/permissions_create_service.rb +23 -0
  10. data/app/services/hyrax/collections/permissions_service.rb +17 -11
  11. data/app/views/hyrax/base/_items.html.erb +3 -1
  12. data/app/views/hyrax/collections/_show_document_list_row.html.erb +0 -19
  13. data/app/views/hyrax/file_sets/_actions.html.erb +38 -36
  14. data/app/views/hyrax/file_sets/media_display/_image.html.erb +1 -1
  15. data/config/features.rb +2 -2
  16. data/config/locales/hyrax.de.yml +13 -1
  17. data/config/locales/hyrax.en.yml +12 -0
  18. data/config/locales/hyrax.es.yml +12 -0
  19. data/config/locales/hyrax.fr.yml +12 -0
  20. data/config/locales/hyrax.it.yml +12 -0
  21. data/config/locales/hyrax.pt-BR.yml +12 -0
  22. data/config/locales/hyrax.zh.yml +12 -0
  23. data/lib/hyrax/version.rb +1 -1
  24. data/spec/abilities/admin_set_ability_spec.rb +5 -0
  25. data/spec/controllers/hyrax/admin/admin_sets_controller_spec.rb +71 -2
  26. data/spec/jobs/import_url_job_spec.rb +53 -0
  27. data/spec/models/flipflop_spec.rb +2 -2
  28. data/spec/presenters/hyrax/file_set_presenter_spec.rb +24 -0
  29. data/spec/presenters/hyrax/work_show_presenter_spec.rb +10 -0
  30. data/spec/services/hyrax/collections/permissions_create_service_spec.rb +23 -0
  31. data/spec/services/hyrax/collections/permissions_service_spec.rb +92 -8
  32. data/spec/views/hyrax/base/_items.html.erb_spec.rb +23 -45
  33. data/spec/views/hyrax/base/_member.html.erb_spec.rb +1 -1
  34. data/spec/views/hyrax/collections/_show_document_list_row.html.erb_spec.rb +1 -0
  35. data/spec/views/hyrax/dashboard/collections/_show_document_list_row.html.erb_spec.rb +1 -0
  36. data/spec/views/hyrax/file_sets/_actions.html.erb_spec.rb +30 -9
  37. data/template.rb +1 -1
  38. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2f567b87262e35a9cb150d7155519d89714b19b0
4
- data.tar.gz: 1ba5abb5d18be1edaacdb1bceb77030e1dfa1c66
3
+ metadata.gz: 025cc22285626454040035c0cf14f5d89d818fa8
4
+ data.tar.gz: 5669ec53c680bfe657ba9f1064102b43c5cd6efd
5
5
  SHA512:
6
- metadata.gz: b72273e1c7ecb34223b97e5839232fcdcb5f26d036903bdb2e50f2ec45d437a52edcf88012fc88f2d6c0c14a4a7ac9bd46965b3cdeada506d6e553352f38418f
7
- data.tar.gz: 389b8b29eee7704e80cf71cdceb6ed8f8e96c0bde66a312bb06f31a73cf3996f0e4afbeba6ae132b7f04132a15b036b6ba06e14385ec7c51ff90c8fab65572dd
6
+ metadata.gz: a301edaa82e5823d68d31c7e4dd547848fbac537ae1e30ff6db7de2fc45897d7a2b3171560a1a8f62f242e921d259f5e0ab1a682ff4e7393ba9f446c17745b6e
7
+ data.tar.gz: b034075731f730600bb4415a273e9ae2ed641615052275a91e6d15e52a77af64c15d55687a6922cab802e6cf64118fc365b0e00ab245aafbe0c5014611b2fc0c
data/README.md CHANGED
@@ -63,7 +63,7 @@ The Samvera community is here to help. Please see our [support guide](./.github/
63
63
  # Getting started
64
64
 
65
65
  This document contains instructions specific to setting up an app with __Hyrax
66
- v2.1.0.rc2__. If you are looking for instructions on installing a different
66
+ v2.1.0.rc3__. If you are looking for instructions on installing a different
67
67
  version, be sure to select the appropriate branch or tag from the drop-down
68
68
  menu above.
69
69
 
@@ -162,7 +162,7 @@ NOTE: The steps need to be done in order to create a new Hyrax based app.
162
162
  Generate a new Rails application using the template.
163
163
 
164
164
  ```
165
- rails _5.1.6_ new my_app -m https://raw.githubusercontent.com/samvera/hyrax/v2.1.0.rc2/template.rb
165
+ rails _5.1.6_ new my_app -m https://raw.githubusercontent.com/samvera/hyrax/v2.1.0.rc3/template.rb
166
166
  ```
167
167
 
168
168
  Generating a new Rails application using Hyrax's template above takes cares of a number of steps for you, including:
@@ -4,7 +4,8 @@
4
4
  }
5
5
  }
6
6
 
7
- .no-preview, .social-media {
7
+ .no-preview,
8
+ .social-media {
8
9
  padding: $panel-body-padding;
9
10
  }
10
11
 
@@ -17,7 +18,8 @@ header > h1 .label {
17
18
  padding: $panel-body-padding;
18
19
  }
19
20
 
20
- .relationships, .attributes {
21
+ .relationships,
22
+ .attributes {
21
23
  tbody th {
22
24
  width: 20%;
23
25
  }
@@ -52,6 +54,13 @@ ul.tabular {
52
54
  .work-type {
53
55
  margin-bottom: 18px;
54
56
  margin-top: -8px;
57
+
58
+ .panel-body {
59
+ .work_description,
60
+ li.attribute {
61
+ word-break: break-word;
62
+ }
63
+ }
55
64
  }
56
65
 
57
66
  .panel-workflow {
@@ -2,8 +2,13 @@ module Hyrax
2
2
  class Admin::AdminSetsController < ApplicationController
3
3
  include Hyrax::CollectionsControllerBehavior
4
4
 
5
- before_action :ensure_manager!
5
+ before_action :authenticate_user!
6
+ before_action :ensure_manager!, except: [:show]
6
7
  load_and_authorize_resource
8
+ before_action :ensure_viewer!, only: [:show]
9
+
10
+ # Catch permission errors
11
+ rescue_from Hydra::AccessDenied, CanCan::AccessDenied, with: :deny_adminset_access
7
12
 
8
13
  with_themed_layout 'dashboard'
9
14
  self.presenter_class = Hyrax::AdminSetPresenter
@@ -19,6 +24,15 @@ module Hyrax
19
24
  class_attribute :admin_set_create_service
20
25
  self.admin_set_create_service = AdminSetCreateService
21
26
 
27
+ def deny_adminset_access(exception)
28
+ if current_user && current_user.persisted?
29
+ redirect_to root_url, alert: exception.message
30
+ else
31
+ session['user_return_to'] = request.url
32
+ redirect_to main_app.new_user_session_url, alert: exception.message
33
+ end
34
+ end
35
+
22
36
  def show
23
37
  add_breadcrumb I18n.t('hyrax.controls.home'), hyrax.root_path
24
38
  add_breadcrumb t(:'hyrax.dashboard.title'), hyrax.dashboard_path
@@ -92,11 +106,18 @@ module Hyrax
92
106
  end
93
107
 
94
108
  def ensure_manager!
109
+ # TODO: Review for possible removal. Doesn't appear to apply anymore.
95
110
  # Even though the user can view this admin set, they may not be able to view
96
111
  # it on the admin page.
97
112
  authorize! :manage_any, AdminSet
98
113
  end
99
114
 
115
+ def ensure_viewer!
116
+ # Even though the user can view this admin set, they may not be able to view
117
+ # it on the admin page if access is granted as a public or registered user only.
118
+ authorize! :view_admin_show, @admin_set
119
+ end
120
+
100
121
  def create_admin_set
101
122
  admin_set_create_service.call(admin_set: @admin_set, creating_user: current_user)
102
123
  end
@@ -8,22 +8,27 @@ require 'browse_everything/retriever'
8
8
  # and CreateWithRemoteFilesActor when files are located in some other service.
9
9
  class ImportUrlJob < Hyrax::ApplicationJob
10
10
  queue_as Hyrax.config.ingest_queue_name
11
+ attr_reader :file_set, :operation
11
12
 
12
13
  before_enqueue do |job|
14
+ operation = job.arguments[1]
13
15
  operation.pending_job(job)
14
16
  end
15
17
 
16
- # Retrieves the operation for the job
17
- def operation
18
- arguments.reduce(:merge).fetch(:operation)
19
- end
20
-
21
18
  # @param [FileSet] file_set
22
19
  # @param [Hyrax::BatchCreateOperation] operation
23
20
  def perform(file_set, operation, headers = {})
24
21
  operation.performing!
25
22
  user = User.find_by_user_key(file_set.depositor)
26
23
  uri = URI(file_set.import_url)
24
+ @file_set = file_set
25
+ @operation = operation
26
+
27
+ unless HTTParty.head(file_set.import_url).success?
28
+ send_error('Expired URL')
29
+ return false
30
+ end
31
+
27
32
  # @todo Use Hydra::Works::AddExternalFileToFileSet instead of manually
28
33
  # copying the file here. This will be gnarly.
29
34
  copy_remote_file(uri, headers) do |f|
@@ -33,13 +38,7 @@ class ImportUrlJob < Hyrax::ApplicationJob
33
38
  # FileSetActor operates synchronously so that this tempfile is available.
34
39
  # If asynchronous, the job might be invoked on a machine that did not have this temp file on its file system!
35
40
  # NOTE: The return status may be successful even if the content never attaches.
36
- if Hyrax::Actors::FileSetActor.new(file_set, user).create_content(f, from_url: true)
37
- operation.success!
38
- else
39
- # send message to user on download failure
40
- Hyrax.config.callback.run(:after_import_url_failure, file_set, user)
41
- operation.fail!(file_set.errors.full_messages.join(' '))
42
- end
41
+ log_import_status(uri, f, user)
43
42
  end
44
43
  end
45
44
 
@@ -57,14 +56,47 @@ class ImportUrlJob < Hyrax::ApplicationJob
57
56
  Rails.logger.debug("ImportUrlJob: Copying <#{uri}> to #{dir}")
58
57
 
59
58
  File.open(File.join(dir, filename), 'wb') do |f|
60
- retriever = BrowseEverything::Retriever.new
61
- uri_spec = { 'url' => uri }.merge(headers)
62
- retriever.retrieve(uri_spec) do |chunk|
63
- f.write(chunk)
59
+ begin
60
+ write_file(uri, f, headers)
61
+ yield f
62
+ rescue StandardError => e
63
+ send_error(e.message)
64
64
  end
65
- f.rewind
66
- yield f
67
65
  end
68
66
  Rails.logger.debug("ImportUrlJob: Closing #{File.join(dir, filename)}")
69
67
  end
68
+
69
+ # Send message to user on download failure
70
+ # @param filename [String] the filename of the file to download
71
+ # @param error_message [String] the download error message
72
+ def send_error(error_message)
73
+ user = User.find_by_user_key(file_set.depositor)
74
+ @file_set.errors.add('Error:', error_message)
75
+ Hyrax.config.callback.run(:after_import_url_failure, @file_set, user)
76
+ @operation.fail!(@file_set.errors.full_messages.join(' '))
77
+ end
78
+
79
+ # Write file to the stream
80
+ # @param uri [URI] the uri of the file to download
81
+ # @param f [IO] the stream to write to
82
+ def write_file(uri, f, headers)
83
+ retriever = BrowseEverything::Retriever.new
84
+ uri_spec = { 'url' => uri }.merge(headers)
85
+ retriever.retrieve(uri_spec) do |chunk|
86
+ f.write(chunk)
87
+ end
88
+ f.rewind
89
+ end
90
+
91
+ # Set the import operation status
92
+ # @param uri [URI] the uri of the file to download
93
+ # @param f [IO] the stream to write to
94
+ # @param user [User]
95
+ def log_import_status(uri, f, user)
96
+ if Hyrax::Actors::FileSetActor.new(@file_set, user).create_content(f, from_url: true)
97
+ operation.success!
98
+ else
99
+ send_error(uri.path, nil)
100
+ end
101
+ end
70
102
  end
@@ -9,7 +9,7 @@ module Hyrax
9
9
  can :view_admin_show_any, AdminSet
10
10
  else
11
11
  can :manage_any, AdminSet if Hyrax::Collections::PermissionsService.can_manage_any_admin_set?(ability: self)
12
- can :create_any, AdminSet if Hyrax::CollectionTypes::PermissionsService.can_create_admin_set_collection_type?(ability: self)
12
+ can [:create_any, :create], AdminSet if Hyrax::CollectionTypes::PermissionsService.can_create_admin_set_collection_type?(ability: self)
13
13
  can :view_admin_show_any, AdminSet if Hyrax::Collections::PermissionsService.can_view_admin_show_for_any_admin_set?(ability: self)
14
14
 
15
15
  can [:edit, :update, :destroy], AdminSet do |admin_set| # for test by solr_doc, see solr_document_ability.rb
@@ -90,6 +90,10 @@ module Hyrax
90
90
  presenter_args: current_ability).first
91
91
  end
92
92
 
93
+ def user_can_perform_any_action?
94
+ current_ability.can?(:edit, id) || current_ability.can?(:destroy, id) || current_ability.can?(:download, id)
95
+ end
96
+
93
97
  private
94
98
 
95
99
  def link_presenter_class
@@ -155,8 +155,8 @@ module Hyrax
155
155
 
156
156
  delegate :member_presenters, :file_set_presenters, :work_presenters, to: :member_presenter_factory
157
157
 
158
- def exclude_unauthorized_file_sets
159
- member_presenters.delete_if { |m| m.is_a?(Hyrax::FileSetPresenter) && !current_ability.can?(:read, m.id) }
158
+ def exclude_unauthorized_members
159
+ member_presenters.delete_if { |m| !current_ability.can?(:read, m.id) }
160
160
  end
161
161
 
162
162
  def manifest_url
@@ -17,6 +17,29 @@ module Hyrax
17
17
  collection.reset_access_controls!
18
18
  end
19
19
 
20
+ # @api public
21
+ #
22
+ # Add access grants to a collection
23
+ #
24
+ # @param collection_id [String] id of a collection
25
+ # @param grants [Array<Hash>] array of grants to add to the collection
26
+ # @example grants
27
+ # [ { agent_type: Hyrax::PermissionTemplateAccess::GROUP,
28
+ # agent_id: 'my_group_name',
29
+ # access: Hyrax::PermissionTemplateAccess::DEPOSIT } ]
30
+ # @see Hyrax::PermissionTemplateAccess for valid values for agent_type and access
31
+ def self.add_access(collection_id:, grants:)
32
+ collection = Collection.find(collection_id)
33
+ template = Hyrax::PermissionTemplate.find_by!(source_id: collection_id)
34
+ grants.each do |grant|
35
+ Hyrax::PermissionTemplateAccess.find_or_create_by(permission_template_id: template.id,
36
+ agent_type: grant[:agent_type],
37
+ agent_id: grant[:agent_id],
38
+ access: grant[:access])
39
+ end
40
+ collection.reset_access_controls!
41
+ end
42
+
20
43
  # @api private
21
44
  #
22
45
  # Gather the default permissions needed for a new collection
@@ -170,9 +170,11 @@ module Hyrax
170
170
  # @return [Boolean] true if the user has permission to view the admin show page for the collection
171
171
  # @note Several checks get the user's groups from the user's ability. The same values can be retrieved directly from a passed in ability.
172
172
  def self.can_view_admin_show_for_collection?(collection_id:, ability:)
173
- deposit_access_to_collection?(collection_id: collection_id, ability: ability) ||
174
- manage_access_to_collection?(collection_id: collection_id, ability: ability) ||
175
- view_access_to_collection?(collection_id: collection_id, ability: ability)
173
+ exclude_groups = [::Ability.registered_group_name,
174
+ ::Ability.public_group_name]
175
+ manage_access_to_collection?(collection_id: collection_id, ability: ability) ||
176
+ deposit_access_to_collection?(collection_id: collection_id, ability: ability, exclude_groups: exclude_groups) ||
177
+ view_access_to_collection?(collection_id: collection_id, ability: ability, exclude_groups: exclude_groups)
176
178
  end
177
179
 
178
180
  # @api private
@@ -181,10 +183,11 @@ module Hyrax
181
183
  #
182
184
  # @param collection_id [String] id of the collection we are checking permissions on
183
185
  # @param ability [Ability] the ability coming from cancan ability check
186
+ # @param exclude_groups [Array<String>] name of groups to exclude from the results
184
187
  # @return [Boolean] true if the user has :deposit access to the collection
185
188
  # @note Several checks get the user's groups from the user's ability. The same values can be retrieved directly from a passed in ability.
186
- def self.deposit_access_to_collection?(collection_id:, ability: nil)
187
- access_to_collection?(collection_id: collection_id, access: 'deposit', ability: ability)
189
+ def self.deposit_access_to_collection?(collection_id:, ability: nil, exclude_groups: [])
190
+ access_to_collection?(collection_id: collection_id, access: 'deposit', ability: ability, exclude_groups: exclude_groups)
188
191
  end
189
192
  private_class_method :deposit_access_to_collection?
190
193
 
@@ -194,10 +197,11 @@ module Hyrax
194
197
  #
195
198
  # @param collection_id [String] id of the collection we are checking permissions on
196
199
  # @param ability [Ability] the ability coming from cancan ability check
200
+ # @param exclude_groups [Array<String>] name of groups to exclude from the results
197
201
  # @return [Boolean] true if the user has :manage access to the collection
198
202
  # @note Several checks get the user's groups from the user's ability. The same values can be retrieved directly from a passed in ability.
199
- def self.manage_access_to_collection?(collection_id:, ability:)
200
- access_to_collection?(collection_id: collection_id, access: 'manage', ability: ability)
203
+ def self.manage_access_to_collection?(collection_id:, ability:, exclude_groups: [])
204
+ access_to_collection?(collection_id: collection_id, access: 'manage', ability: ability, exclude_groups: exclude_groups)
201
205
  end
202
206
  private_class_method :manage_access_to_collection?
203
207
 
@@ -207,10 +211,11 @@ module Hyrax
207
211
  #
208
212
  # @param collection_id [String] id of the collection we are checking permissions on
209
213
  # @param ability [Ability] the ability coming from cancan ability check
214
+ # @param exclude_groups [Array<String>] name of groups to exclude from the results
210
215
  # @return [Boolean] true if the user has permission to view the collection
211
216
  # @note Several checks get the user's groups from the user's ability. The same values can be retrieved directly from a passed in ability.
212
- def self.view_access_to_collection?(collection_id:, ability:)
213
- access_to_collection?(collection_id: collection_id, access: 'view', ability: ability)
217
+ def self.view_access_to_collection?(collection_id:, ability:, exclude_groups: [])
218
+ access_to_collection?(collection_id: collection_id, access: 'view', ability: ability, exclude_groups: exclude_groups)
214
219
  end
215
220
  private_class_method :view_access_to_collection?
216
221
 
@@ -221,13 +226,14 @@ module Hyrax
221
226
  # @param collection_id [String] id of the collection we are checking permissions on
222
227
  # @param access [Symbol] the access level to check
223
228
  # @param ability [Ability] the ability coming from cancan ability check
229
+ # @param exclude_groups [Array<String>] name of groups to exclude from the results
224
230
  # @return [Boolean] true if the user has permission to view the collection
225
231
  # @note Several checks get the user's groups from the user's ability. The same values can be retrieved directly from a passed in ability.
226
- def self.access_to_collection?(collection_id:, access:, ability:)
232
+ def self.access_to_collection?(collection_id:, access:, ability:, exclude_groups: [])
227
233
  return false unless collection_id
228
234
  template = Hyrax::PermissionTemplate.find_by!(source_id: collection_id)
229
235
  return true if ([ability.current_user.user_key] & template.agent_ids_for(agent_type: 'user', access: access)).present?
230
- return true if (ability.user_groups & template.agent_ids_for(agent_type: 'group', access: access)).present?
236
+ return true if (ability.user_groups & (template.agent_ids_for(agent_type: 'group', access: access) - exclude_groups)).present?
231
237
  false
232
238
  end
233
239
  private_class_method :access_to_collection?
@@ -1,5 +1,5 @@
1
1
  <h2><%= t('.header') %></h2>
2
- <% members = Flipflop.hide_private_files? ? presenter.exclude_unauthorized_file_sets : presenter.member_presenters %>
2
+ <% members = Flipflop.hide_private_items? ? presenter.exclude_unauthorized_members : presenter.member_presenters %>
3
3
  <% if members.present? %>
4
4
  <table class="table table-striped related-files">
5
5
  <thead>
@@ -17,4 +17,6 @@
17
17
  </table>
18
18
  <% elsif can? :edit, presenter.id %>
19
19
  <div class="alert alert-warning" role="alert"><%= t('.empty', type: presenter.human_readable_type) %></div>
20
+ <% else %>
21
+ <div class="alert alert-warning" role="alert"><%= t('.unauthorized', type: presenter.human_readable_type) %></div>
20
22
  <% end %>
@@ -13,7 +13,6 @@
13
13
  <div class="media-body">
14
14
  <p class="media-heading">
15
15
  <strong><%= link_to document.title_or_label, [main_app, document], id: "src_copy_link#{id}", class: "#{'document-title' if document.title_or_label == document.label}" %></strong>
16
- <a href="#" class="small" title="Click for more details"><i id="expand_<%= id %>" class="glyphicon glyphicon-chevron-right"></i></a>
17
16
  </p>
18
17
  <%= render_collection_links(document) %>
19
18
  </div>
@@ -24,21 +23,3 @@
24
23
  <%= render_visibility_link(document) %>
25
24
  </td>
26
25
  </tr>
27
- <tr id="detail_<%= id %>"> <!-- document detail"> -->
28
- <td colspan="6">
29
- <dl class="expanded-details row">
30
- <dt class="col-xs-3 col-lg-2">Creator:</dt>
31
- <dd class="col-xs-9 col-lg-4"><%= document.creator.to_a.to_sentence %></dd>
32
- <dt class="col-xs-3 col-lg-2">Depositor:</dt>
33
- <dd class="col-xs-9 col-lg-4"><%= link_to_profile document.depositor %></dd>
34
- <dt class="col-xs-3 col-lg-2">Edit Access:</dt>
35
- <dd class="col-xs-9 col-lg-10">
36
- <% if document.edit_groups.present? %>
37
- Groups: <%= document.edit_groups.join(', ') %>
38
- <br />
39
- <% end %>
40
- Users: <%= document.edit_people.join(', ') %>
41
- </dd>
42
- </dl>
43
- </td>
44
- </tr>
@@ -1,42 +1,44 @@
1
- <div class="btn-group">
1
+ <% if file_set.user_can_perform_any_action? %>
2
+ <div class="btn-group">
2
3
 
3
- <button class="btn btn-default dropdown-toggle" data-toggle="dropdown" type="button" id="dropdownMenu_<%= file_set.id %>" aria-haspopup="true">
4
- <span class="sr-only">Press to </span>
5
- Select an action
6
- <span class="caret" aria-hidden="true"></span>
7
- </button>
4
+ <button class="btn btn-default dropdown-toggle" data-toggle="dropdown" type="button" id="dropdownMenu_<%= file_set.id %>" aria-haspopup="true">
5
+ <span class="sr-only">Press to </span>
6
+ <%= t('.header') %>
7
+ <span class="caret" aria-hidden="true"></span>
8
+ </button>
8
9
 
9
- <ul role="menu" class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdownMenu_<%= file_set.id %>">
10
- <% if can?(:edit, file_set.id) %>
11
- <li role="menuitem" tabindex="-1">
12
- <%= link_to 'Edit', edit_polymorphic_path([main_app, file_set]),
13
- { title: "Edit #{file_set}" } %>
14
- </li>
10
+ <ul role="menu" class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdownMenu_<%= file_set.id %>">
11
+ <% if can?(:edit, file_set.id) %>
12
+ <li role="menuitem" tabindex="-1">
13
+ <%= link_to t('.edit'), edit_polymorphic_path([main_app, file_set]),
14
+ { title: t('.edit_title', file_set: file_set) } %>
15
+ </li>
15
16
 
16
- <li role="menuitem" tabindex="-1">
17
- <%= link_to 'Versions', edit_polymorphic_path([main_app, file_set], anchor: 'versioning_display'),
18
- { title: "Display previous versions" } %>
19
- </li>
20
- <% end %>
17
+ <li role="menuitem" tabindex="-1">
18
+ <%= link_to t('.versions'), edit_polymorphic_path([main_app, file_set], anchor: 'versioning_display'),
19
+ { title: t('.versions_title') } %>
20
+ </li>
21
+ <% end %>
21
22
 
22
- <% if can?(:destroy, file_set.id) %>
23
- <li role="menuitem" tabindex="-1">
24
- <%= link_to 'Delete', polymorphic_path([main_app, file_set]),
25
- method: :delete, title: "Delete #{file_set}",
26
- data: {confirm: "Deleting #{file_set} from #{application_name} is permanent. Click OK to delete this from #{application_name}, or Cancel to cancel this operation"} %>
27
- </li>
28
- <% end %>
23
+ <% if can?(:destroy, file_set.id) %>
24
+ <li role="menuitem" tabindex="-1">
25
+ <%= link_to t('.delete'), polymorphic_path([main_app, file_set]),
26
+ method: :delete, title: t('.delete_title', file_set: file_set),
27
+ data: { confirm: t('.delete_confirm', file_set: file_set, application_name: application_name) } %>
28
+ </li>
29
+ <% end %>
29
30
 
30
- <% if can?(:download, file_set.id) %>
31
- <li role="menuitem" tabindex="-1">
32
- <%= link_to 'Download',
33
- hyrax.download_path(file_set),
34
- title: "Download #{file_set.to_s.inspect}",
35
- target: "_blank",
36
- id: "file_download",
37
- data: { label: file_set.id } %>
38
- </li>
39
- <% end %>
31
+ <% if can?(:download, file_set.id) %>
32
+ <li role="menuitem" tabindex="-1">
33
+ <%= link_to t('.download'),
34
+ hyrax.download_path(file_set),
35
+ title: t('.download_title', file_set: file_set),
36
+ target: "_blank",
37
+ id: "file_download",
38
+ data: { label: file_set.id } %>
39
+ </li>
40
+ <% end %>
40
41
 
41
- </ul>
42
- </div>
42
+ </ul>
43
+ </div>
44
+ <% end %>