Skip to content

Commit 43d1aba

Browse files
committed
Support moving user versions.
closes #4614
1 parent 0e4674e commit 43d1aba

9 files changed

Lines changed: 165 additions & 6 deletions

File tree

app/components/show/controls_component.html.erb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,6 @@
4444
<%= create_embargo %>
4545
<%= create_text_extraction %>
4646
<%= withdraw_or_restore %>
47+
<%= move_user_version %>
4748
<% end %>
4849
</div>

app/components/show/controls_component.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,16 @@ def withdraw_or_restore
172172
end
173173
end
174174

175+
def move_user_version
176+
return unless item? && user_versions_presenter.move_version_targets.present?
177+
178+
render ActionButton.new(
179+
url: item_user_version_edit_move_path(doc, user_version_view),
180+
label: 'Move',
181+
open_modal: true
182+
)
183+
end
184+
175185
def upload_mods
176186
link_to 'Upload MODS', apo_bulk_jobs_path(doc), class: 'btn btn-primary'
177187
end

app/controllers/user_versions_controller.rb

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,29 @@ def show
1313
end
1414

1515
def withdraw
16-
update_user_version(withdrawn: true)
16+
update_withdrawn(withdrawn: true)
1717
redirect_to item_user_version_path(druid_param, user_version_param),
1818
notice: 'Withdrawn. Purl will no longer display this version.'
1919
end
2020

2121
def restore
22-
update_user_version(withdrawn: false)
22+
update_withdrawn(withdrawn: false)
2323
redirect_to item_user_version_path(druid_param, user_version_param),
2424
notice: 'Restored. Purl will display this version.'
2525
end
2626

27+
def edit_move
28+
@druid = druid_param
29+
@user_versions_presenter = UserVersionsPresenter.new(user_version_view: user_version_param, user_version_inventory: client.inventory)
30+
end
31+
32+
def move
33+
client.update(user_version: Dor::Services::Client::UserVersion::Version.new(userVersion: user_version_param, version: params[:version]))
34+
35+
redirect_to item_user_version_path(druid_param, user_version_param),
36+
notice: 'Moved user version.'
37+
end
38+
2739
private
2840

2941
def druid_param
@@ -38,8 +50,11 @@ def find_user_version_cocina
3850
@cocina = Repository.find_user_version(druid_param, user_version_param)
3951
end
4052

41-
def update_user_version(withdrawn:)
42-
client = Dor::Services::Client.object(druid_param).user_version
53+
def update_withdrawn(withdrawn:)
4354
client.update(user_version: Dor::Services::Client::UserVersion::Version.new(withdrawn:, userVersion: user_version_param))
4455
end
56+
57+
def client
58+
Dor::Services::Client.object(druid_param).user_version
59+
end
4560
end

app/presenters/user_versions_presenter.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,18 @@ def version_view
4343
user_version_data_for(user_version_view)&.version&.to_i
4444
end
4545

46+
# @return [Array<Integer>] the versions that this user version can be moved to
47+
def move_version_targets
48+
return [] unless user_version_data
49+
return [] if user_version_data.restorable? # Can't move it if withdrawn.
50+
51+
next_user_version = user_version_view + 1
52+
version_for_next_user_version = user_version_data_for(next_user_version)&.version&.to_i
53+
return [] unless version_for_next_user_version
54+
55+
(version_view + 1..version_for_next_user_version - 1).to_a
56+
end
57+
4658
attr_reader :user_version_view, :user_version_inventory
4759

4860
private
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<%= render EditModalComponent.new do |component| %>
2+
<% component.with_header { 'Move user version' } %>
3+
<% component.with_body do %>
4+
<%= form_with(url: item_user_version_move_path(@druid, @user_versions_presenter.user_version_view)) do |f| %>
5+
<% move_version_targets = @user_versions_presenter.move_version_targets %>
6+
<% if move_version_targets.one? %>
7+
<div>Move user version <%= @user_versions_presenter.user_version_view %> to version <%= move_version_targets.first %>.</div>
8+
<%= f.hidden_field('version', value: move_version_targets.first) %>
9+
<% else %>
10+
<%= f.label :version, "Move user version #{@user_versions_presenter.user_version_view} to version:", class: 'form-label' %>
11+
<%= f.select :version, move_version_targets, {}, { class: 'form-select', style: 'width: 100px;' } %>
12+
<% end %>
13+
<div class='my-3'>
14+
<button type='submit' class='btn btn-primary'>Submit</button>
15+
</div>
16+
<% end %>
17+
<% end %>
18+
<% end %>

config/routes.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,8 @@
236236
resources :user_versions, only: %i[] do
237237
post 'withdraw'
238238
post 'restore'
239+
get 'move', to: 'user_versions#edit_move', as: 'edit_move'
240+
post 'move'
239241
get 'descriptive', to: 'descriptives#show'
240242
get 'structure', to: 'structures#show'
241243
resources 'files', only: %i[index], constraints: { item_id: /.*/ } do

spec/components/show/controls_component_spec.rb

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,20 @@
2424
version_or_user_version_view?: version.present? || user_version.present?,
2525
user_versions_presenter:)
2626
end
27-
let(:user_versions_presenter) { instance_double(UserVersionsPresenter, user_version_withdrawable?: user_version_withdrawable, user_version_restorable?: user_version_restorable) }
27+
let(:user_versions_presenter) do
28+
instance_double(UserVersionsPresenter,
29+
user_version_withdrawable?: user_version_withdrawable,
30+
user_version_restorable?: user_version_restorable,
31+
move_version_targets:)
32+
end
2833
let(:cocina) { instance_double(Cocina::Models::DRO, dro?: dro, type: 'https://cocina.sul.stanford.edu/models/book') }
2934
let(:open) { false }
3035
let(:open_and_not_assembling) { false }
3136
let(:user_version) { nil }
3237
let(:version) { nil }
3338
let(:user_version_withdrawable) { false }
3439
let(:user_version_restorable) { false }
40+
let(:move_version_targets) { [] }
3541

3642
before do
3743
rendered
@@ -164,6 +170,15 @@
164170
expect(page).to have_link 'Restore', href: '/items/druid:kv840xx0000/user_versions/2/restore'
165171
end
166172
end
173+
174+
context 'when the user version can be moved' do
175+
let(:user_version) { 2 }
176+
let(:move_version_targets) { [3, 4] }
177+
178+
it 'the move button is displayed' do
179+
expect(page).to have_link 'Move', href: '/items/druid:kv840xx0000/user_versions/2/move'
180+
end
181+
end
167182
end
168183

169184
context 'when the object is an AdminPolicy the user can manage' do

spec/features/user_version_view_spec.rb

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
let(:solr_conn) { blacklight_config.repository_class.new(blacklight_config).connection }
88
let(:druid) { 'druid:hj185xx2222' }
99
let(:version_client) { instance_double(Dor::Services::Client::ObjectVersion, current: 1, inventory: [version1]) }
10-
let(:user_version_client) { instance_double(Dor::Services::Client::UserVersion, inventory: [user_version1], find: cocina_object, solr: solr_doc, update: true) }
10+
let(:user_version_client) { instance_double(Dor::Services::Client::UserVersion, inventory:, find: cocina_object, solr: solr_doc, update: true) }
11+
let(:inventory) { [user_version1] }
1112
let(:release_tags_client) { instance_double(Dor::Services::Client::ReleaseTags, list: release_tags_list) }
1213
let(:version1) { Dor::Services::Client::ObjectVersion::Version.new }
1314
let(:user_version1) { Dor::Services::Client::UserVersion::Version.new(version: 4, userVersion: 2, withdrawable:, restorable:) }
@@ -237,6 +238,48 @@
237238
end
238239
end
239240

241+
context 'when moving a version and only one target' do
242+
let(:inventory) do
243+
[
244+
Dor::Services::Client::UserVersion::Version.new(version: 1, userVersion: 1, withdrawable: true, restorable: false),
245+
Dor::Services::Client::UserVersion::Version.new(version: 3, userVersion: 2, withdrawable: true, restorable: false)
246+
]
247+
end
248+
249+
it 'moves' do
250+
visit item_user_version_path(item_id: druid, user_version_id: 1)
251+
click_link('Move')
252+
expect(page).to have_content('Move user version')
253+
expect(page).to have_content('Move user version 1 to version 2.')
254+
click_button('Submit')
255+
expect(page).to have_content('Moved user version.')
256+
257+
expect(user_version_client).to have_received(:update)
258+
.with(user_version: Dor::Services::Client::UserVersion::Version.new(userVersion: '1', version: '2'))
259+
end
260+
end
261+
262+
context 'when moving a version and multiple targets' do
263+
let(:inventory) do
264+
[
265+
Dor::Services::Client::UserVersion::Version.new(version: 1, userVersion: 1, withdrawable: true, restorable: false),
266+
Dor::Services::Client::UserVersion::Version.new(version: 4, userVersion: 2, withdrawable: true, restorable: false)
267+
]
268+
end
269+
270+
it 'moves' do
271+
visit item_user_version_path(item_id: druid, user_version_id: 1)
272+
click_link('Move')
273+
expect(page).to have_content('Move user version')
274+
select('3', from: 'Move user version 1 to version:')
275+
click_button('Submit')
276+
expect(page).to have_content('Moved user version.')
277+
278+
expect(user_version_client).to have_received(:update)
279+
.with(user_version: Dor::Services::Client::UserVersion::Version.new(userVersion: '1', version: '3'))
280+
end
281+
end
282+
240283
context 'when viewing an unknown version' do
241284
before do
242285
allow(user_version_client).to receive(:find).and_raise(Dor::Services::Client::NotFoundResponse)

spec/presenters/user_versions_presenter_spec.rb

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,47 @@
9090

9191
it { is_expected.to eq 2 }
9292
end
93+
94+
describe '#move_version_targets' do
95+
subject { presenter.move_version_targets }
96+
97+
context 'when no versions are movable' do
98+
it { is_expected.to eq [] }
99+
end
100+
101+
context 'when versions are movable' do
102+
let(:user_version_inventory) do
103+
[
104+
Dor::Services::Client::UserVersion::Version.new(userVersion: '1', version: '3', withdrawable: true, restorable: false),
105+
Dor::Services::Client::UserVersion::Version.new(userVersion: '2', version: '6', withdrawable: true, restorable: false)
106+
]
107+
end
108+
109+
it { is_expected.to eq [4, 5] }
110+
end
111+
112+
context 'when the user version is withdrawn' do
113+
let(:user_version_inventory) do
114+
[
115+
Dor::Services::Client::UserVersion::Version.new(userVersion: '1', version: '3', withdrawable: false, restorable: true),
116+
Dor::Services::Client::UserVersion::Version.new(userVersion: '2', version: '6', withdrawable: true, restorable: false)
117+
]
118+
end
119+
120+
it { is_expected.to eq [] }
121+
end
122+
123+
context 'when the user version is the last user version' do
124+
let(:user_version_inventory) do
125+
[
126+
Dor::Services::Client::UserVersion::Version.new(userVersion: '1', version: '3', withdrawable: false, restorable: true),
127+
Dor::Services::Client::UserVersion::Version.new(userVersion: '2', version: '6', withdrawable: true, restorable: false)
128+
]
129+
end
130+
131+
let(:user_version) { '2' }
132+
133+
it { is_expected.to eq [] }
134+
end
135+
end
93136
end

0 commit comments

Comments
 (0)