Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Async Samples Cloning #904

Merged
merged 7 commits into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ AllCops:
- "**/bin/**/**"
- "**/db/schema.rb"
- "**/db/jobs_schema.rb"
TargetRubyVersion: "3.2"
TargetRubyVersion: "3.3"
NewCops: enable

# https://rubocop.readthedocs.io/en/latest/cops_metrics/#metricsblocklength
Expand Down
16 changes: 8 additions & 8 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ GEM
actionview (>= 5.0.0)
activesupport (>= 5.0.0)
jmespath (1.6.2)
json (2.7.2)
json (2.9.1)
json_schemer (2.3.0)
bigdecimal
hana (~> 1.3)
Expand Down Expand Up @@ -416,7 +416,7 @@ GEM
parallel (1.26.3)
paranoia (3.0.0)
activerecord (>= 6, < 8.1)
parser (3.3.5.0)
parser (3.3.7.0)
ast (~> 2.4.1)
racc
pg (1.5.7)
Expand Down Expand Up @@ -490,7 +490,7 @@ GEM
rdoc (6.10.0)
psych (>= 4.0.0)
redcarpet (3.6.0)
regexp_parser (2.9.2)
regexp_parser (2.10.0)
reline (0.6.0)
io-console (~> 0.5)
representable (3.2.0)
Expand All @@ -510,17 +510,17 @@ GEM
roo (>= 2.0.0, < 3)
spreadsheet (> 0.9.0)
rouge (4.3.0)
rubocop (1.67.0)
rubocop (1.70.0)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10)
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 2.4, < 3.0)
rubocop-ast (>= 1.32.2, < 2.0)
regexp_parser (>= 2.9.3, < 3.0)
rubocop-ast (>= 1.36.2, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.32.3)
unicode-display_width (>= 2.4.0, < 4.0)
rubocop-ast (1.37.0)
parser (>= 3.3.1.0)
rubocop-graphql (1.5.4)
rubocop (>= 1.50, < 2)
Expand Down
31 changes: 9 additions & 22 deletions app/controllers/projects/samples/clones_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,19 @@ class ClonesController < Projects::ApplicationController
respond_to :turbo_stream
before_action :projects

def new
@broadcast_target = "samples_clone_#{SecureRandom.uuid}"
end

def create
@broadcast_target = params[:broadcast_target]
new_project_id = clone_params[:new_project_id]
sample_ids = clone_params[:sample_ids]

@cloned_sample_ids = ::Samples::CloneService.new(@project, current_user).execute(new_project_id, sample_ids)

if @project.errors.empty?
render status: :ok, locals: { type: :success, message: t('.success') }
elsif @project.errors.include?(:sample)
render_sample_errors
else
errors = @project.errors.full_messages_for(:base)
render status: :unprocessable_entity,
locals: { type: :alert, message: t('.no_samples_cloned_error'), errors: }
end
::Samples::CloneJob.set(wait_until: 1.second.from_now).perform_later(@project, current_user, new_project_id,
sample_ids, @broadcast_target)

render status: :ok
end

private
Expand All @@ -30,17 +28,6 @@ def clone_params
params.require(:clone).permit(:new_project_id, sample_ids: [])
end

def render_sample_errors
errors = @project.errors.messages_for(:sample)
if @cloned_sample_ids.count.positive?
render status: :partial_content,
locals: { type: :alert, message: t('projects.samples.clones.create.error'), errors: }
else
render status: :unprocessable_entity,
locals: { type: :alert, message: t('projects.samples.clones.create.error'), errors: }
end
end

def projects
@projects = authorized_scope(Project, type: :relation,
as: :manageable).where.not(namespace_id: @project.namespace_id)
Expand Down
43 changes: 43 additions & 0 deletions app/jobs/samples/clone_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# frozen_string_literal: true

module Samples
# Job used to clone samples
class CloneJob < ApplicationJob
queue_as :default

def perform(project, current_user, new_project_id, sample_ids, broadcast_target) # rubocop:disable Metrics/MethodLength
@cloned_sample_ids = ::Samples::CloneService.new(project, current_user).execute(new_project_id, sample_ids)

if project.errors.empty?
Turbo::StreamsChannel.broadcast_replace_to broadcast_target,
target: 'clone_samples_dialog_content',
partial: 'projects/samples/shared/success',
locals: {
type: :success,
message: I18n.t('projects.samples.clones.create.success')
}
elsif project.errors.include?(:sample)
errors = project.errors.messages_for(:sample)
Turbo::StreamsChannel.broadcast_replace_to broadcast_target,
target: 'clone_samples_dialog_content',
partial: 'projects/samples/shared/errors',
locals: {
type: :alert,
message: I18n.t('projects.samples.clones.create.error'),
errors: errors
}
else
errors = project.errors.full_messages_for(:base)
Turbo::StreamsChannel.broadcast_replace_to broadcast_target,
target: 'clone_samples_dialog_content',
partial: 'projects/samples/shared/errors',
locals: {
type: :alert,
message:
I18n.t('projects.samples.clones.create.no_samples_cloned_error'),
errors: errors
}
end
end
end
end
14 changes: 5 additions & 9 deletions app/views/projects/samples/clones/_dialog.html.erb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<%= viral_dialog(open: open, size: :large) do |dialog| %>
<%= dialog.with_header(title: t(".title")) %>
<%= dialog.with_section do %>
<%= turbo_stream_from @broadcast_target %>
<%= turbo_frame_tag "clone_samples_dialog_content" do %>
<div
data-controller="infinite-scroll viral--select2"
Expand Down Expand Up @@ -45,14 +46,14 @@

<%= form_for(:clone, url: namespace_project_samples_clone_path, method: :post,
data: {
controller: "spinner form--hidden-inputs",
controller: "form--hidden-inputs",
"form--hidden-inputs-selection-outlet": '#samples-table',
"form--hidden-inputs-field-name-value": "clone[sample_ids][]",
action:"turbo:submit-start->spinner#submitStart turbo:submit-end->spinner#submitEnd"
}
) do |form| %>
<div class="grid gap-4">
<div class="form-field">
<input type="hidden" name="broadcast_target" value="<%= @broadcast_target %>"/>
<%= form.label :new_project_id, t(".new_project_id") %>
<% if @projects.empty? %>
<input
Expand All @@ -62,8 +63,8 @@
class="
border-slate-300 text-slate-800 sm:text-sm rounded-md block w-full p-2.5
dark:bg-slate-800 dark:border-slate-600 dark:text-slate-50
"
>
"
>
<% else %>
<%= viral_select2(form:, name: :new_project_id, placeholder: t(".select_project")) do |select| %>
<% @projects.each do |project| %>
Expand Down Expand Up @@ -93,11 +94,6 @@
<% end %>
</div>
</div>

<%= render partial: "shared/loading/spinner",
locals: {
spinner_message: t(".spinner_message"),
} %>
<% end %>
<% end %>
<% end %>
29 changes: 14 additions & 15 deletions app/views/projects/samples/clones/create.turbo_stream.erb
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
<% if @project.errors.empty? %>
<%= turbo_stream.append "flashes" do %>
<%= viral_flash(type:, data: message) %>
<% end %>
<%= turbo_stream.update "samples_dialog", partial: "dialog", locals: { open: false } %>
<% else %>
<%= turbo_stream.replace "clone_samples_dialog_content",
partial: "projects/samples/shared/errors",
locals: {
type: type,
message: message,
errors: errors,
} %>
<%= turbo_stream.append "clone_samples_dialog_content" do %>
<div
role="status"
id="spinner"
class="
backdrop-blur-sm absolute h-full w-full -translate-x-1/2 -translate-y-1/2
top-2/4 left-1/2 grid place-items-center
"
>
<div class="grid place-items-center">
<%= viral_icon(name: :loading, classes: "animate-spin text-primary-500") %>
<span class="text-black dark:text-white"><%= t("projects.samples.clones.dialog.spinner_message") %>.</span>
</div>
</div>
<% end %>

<turbo-stream action="refresh"></turbo-stream>
9 changes: 9 additions & 0 deletions app/views/projects/samples/shared/_success.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<div>
<%= viral_alert(type:, message:, classes: "mb-4 h-30 overflow-y-auto") %>

<div>
<%= viral_button(state: :primary, data: { action: 'click->viral--dialog#close' }) do %>
<%= t(".ok_button") %>
<% end %>
</div>
</div>
Empty file modified bin/rubocop
100644 → 100755
Empty file.
2 changes: 2 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1408,6 +1408,8 @@ en:
ok_button: OK
metadata_toggle:
label: Metadata
success:
ok_button: OK
show:
add_metadata: Add Metadata
concatenate_button: Concatenate Files
Expand Down
2 changes: 2 additions & 0 deletions config/locales/fr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1408,6 +1408,8 @@ fr:
ok_button: OK
metadata_toggle:
label: Metadata
success:
ok_button: OK
show:
add_metadata: Add Metadata
concatenate_button: Concatenate Files
Expand Down
87 changes: 9 additions & 78 deletions test/controllers/projects/samples/clones_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,85 +14,16 @@ class ClonesControllerTest < ActionDispatch::IntegrationTest
@sample2 = samples(:sample2)
end

test 'should not clone samples with empty params' do
post namespace_project_samples_clone_path(@namespace, @project, format: :turbo_stream),
params: {
clone: {
new_project_id: nil,
sample_ids: nil
test 'should enqueue a Samples::CloneJob' do
assert_enqueued_jobs 1, only: ::Samples::CloneJob do
post namespace_project_samples_clone_path(@namespace, @project, format: :turbo_stream),
params: {
clone: {
new_project_id: @new_project.id,
sample_ids: [@sample1.id, @sample2.id]
}
}
}
assert_response :unprocessable_entity
end

test 'should not clone samples with no sample ids' do
post namespace_project_samples_clone_path(@namespace, @project, format: :turbo_stream),
params: {
clone: {
new_project_id: @new_project.id,
sample_ids: []
}
}, as: :json
assert_response :unprocessable_entity
end

test 'should not clone samples with into same project' do
post namespace_project_samples_clone_path(@namespace, @project, format: :turbo_stream),
params: {
clone: {
new_project_id: @project.id,
sample_ids: [@sample1.id, @sample2.id]
}
}
assert_response :unprocessable_entity
end

test 'should not clone one sample with same sample name' do
new_project = projects(:project34)
post namespace_project_samples_clone_path(@namespace, @project, format: :turbo_stream),
params: {
clone: {
new_project_id: new_project.id,
sample_ids: [@sample2.id]
}
}
assert_response :unprocessable_entity
end

test 'should clone good sample & not clone sample with same sample name' do
new_project = projects(:project34)
post namespace_project_samples_clone_path(@namespace, @project, format: :turbo_stream),
params: {
clone: {
new_project_id: new_project.id,
sample_ids: [@sample1.id, @sample2.id]
}
}
assert_response :partial_content
end

test 'should clone samples with permission' do
post namespace_project_samples_clone_path(@namespace, @project, format: :turbo_stream),
params: {
clone: {
new_project_id: @new_project.id,
sample_ids: [@sample1.id, @sample2.id]
}
}

assert_response :success
end

test 'should not clone samples without permission' do
new_project = projects(:project33)
post namespace_project_samples_clone_path(@namespace, @project, format: :turbo_stream),
params: {
clone: {
new_project_id: new_project.id,
sample_ids: [@sample1.id, @sample2.id]
}
}
assert_response :unauthorized
end
end
end
end
Expand Down
4 changes: 3 additions & 1 deletion test/system/dashboard/projects_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,9 @@ def teardown
end
find('input#select2-input').click
find("button[data-viral--select2-primary-param='#{@project2.full_path}']").click
click_on I18n.t('projects.samples.clones.dialog.submit_button')
perform_enqueued_jobs do
click_on I18n.t('projects.samples.clones.dialog.submit_button')
end
end
assert_text I18n.t('projects.samples.clones.create.success')

Expand Down
Loading
Loading