Refactor experiment workflow image generation [SCI-5063]

This commit is contained in:
Oleksii Kriuchykhin 2020-10-16 14:21:25 +02:00
parent 235f87e0d9
commit 13fcfedf41
16 changed files with 70 additions and 129 deletions

View file

@ -1,67 +1,24 @@
(function(){
var count = 0;
function init(){
$("[data-id]").each(function(){
var that = $(this);
initProjectExperiment(that);
});
}
function initProjectExperiment(element){
var container = element.find(".workflowimg-container");
var url = container.data("check-img");
var timestamp = container.data("timestamp");
var img_url = container.data('updated-img');
animateSpinner(container, true, { color: '#555', top: '60%', zIndex: '100' });
checkUpdatedImg(img_url, url, timestamp, container);
}
// checks if the experiment image is updated
function checkUpdatedImg(img_url, url, timestamp, container){
if (count < 30 && timestamp){
$.ajax({
url: url,
type: "GET",
data: { "timestamp": timestamp },
dataType: "json",
success: function (data) {
getNewWorkforwImg(container, img_url);
container.show();
animateSpinner(container, false);
},
error: function (ev) {
if (ev.status == 404) {
setTimeout(function () {
checkUpdatedImg(img_url, url, timestamp, container)
}, 5000);
} else {
animateSpinner(container, false);
(function() {
function init() {
$('.workflowimg-container').each(function() {
let container = $(this);
if (container.data('workflowimg-present') === false) {
let imgUrl = container.data('workflowimg-url');
container.find('.workflowimg-spinner').removeClass('hidden');
$.ajax({
url: imgUrl,
type: 'GET',
dataType: 'json',
success: function(data) {
container.html(data.workflowimg);
},
error: function() {
container.find('.workflowimg-spinner').addClass('hidden');
}
count++;
}
});
} else {
animateSpinner(container, false);
}
}
// fetch the new experiment image
function getNewWorkforwImg(el, url){
$.ajax({
url: url,
type: "GET",
dataType: "json",
success: function (data) {
el.children('img').remove();
el.append(data.workflowimg);
},
error: function (ev) {
// TODO
});
}
});
}
init();
})();
}());

View file

@ -1,6 +1,6 @@
// scss-lint:disable SelectorDepth
// scss-lint:disable NestingDepth
@import 'constants';
@import "constants";
@import "mixins";
// Some color definitions
@ -559,9 +559,16 @@ li.module-hover {
.no-workflowimg {
color: $color-alto;
display: block;
font-size: 22px;
text-align: center;
text-decoration: none;
}
.no-tasks {
color: $color-alto;
display: block;
font-size: 1.5em;
font-weight: bold;
margin: 15px 0;
margin: 1em 0;
max-height: 200px;
padding-bottom: 70px;
padding-top: 50px;
@ -575,6 +582,11 @@ li.module-hover {
height: 100%;
justify-content: center;
.workflowimg-spinner {
color: $color-alto;
top: 50%;
}
img {
max-height: 190px;
max-width: 100%;

View file

@ -171,9 +171,6 @@ class CanvasController < ApplicationController
next if my_module.blank?
end
# Create workflow image
@experiment.generate_workflow_img
flash[:success] = t('experiments.canvas.update.success_flash')
redirect_to canvas_experiment_path(@experiment)
end

View file

@ -213,28 +213,19 @@ class ExperimentsController < ApplicationController
def module_archive
end
def updated_img
if @experiment.workflowimg.attached? && !@experiment.workflowimg_exists?
@experiment.workflowimg.purge
@experiment.generate_workflow_img
end
respond_to do |format|
format.json do
if @experiment.workflowimg.attached?
render json: {}, status: 200
else
render json: {}, status: 404
end
def fetch_workflow_img
unless @experiment.workflowimg_exists?
Experiment.no_touching do
Experiments::GenerateWorkflowImageService.call(experiment: @experiment)
end
end
end
def fetch_workflow_img
respond_to do |format|
format.json do
render json: {
workflowimg: render_to_string(
partial: 'projects/show/workflow_img.html.erb'
partial: 'projects/show/workflow_img.html.erb',
locals: { experiment: @experiment }
)
}
end

View file

@ -212,13 +212,8 @@ class Experiment < ApplicationRecord
true
end
def generate_workflow_img
workflowimg.purge if workflowimg.attached?
Experiments::GenerateWorkflowImageService.delay.call(experiment_id: id)
end
def workflowimg_exists?
workflowimg.service.exist?(workflowimg.blob.key)
workflowimg.attached? && workflowimg.service.exist?(workflowimg.blob.key)
end
# Get projects where user is either owner or user in the same team
@ -345,9 +340,6 @@ class Experiment < ApplicationRecord
experiment_new: experiment.id
})
end
# Generate workflow image for the experiment in which we moved the task
generate_workflow_img_for_moved_modules(to_move)
end
# Move module groups; this method accepts a map where keys
@ -406,17 +398,6 @@ class Experiment < ApplicationRecord
group.save!
end
end
# Generate workflow image for the experiment in which we moved the workflow
generate_workflow_img_for_moved_modules(to_move)
end
# Generates workflow img when the workflow or module is moved
# to other experiment
def generate_workflow_img_for_moved_modules(to_move)
Experiment.where(id: to_move.values.uniq).each do |exp|
exp.generate_workflow_img
end
end
# Update connections for all modules in this project.
@ -485,7 +466,7 @@ class Experiment < ApplicationRecord
def update_module_positions(positions)
modules = my_modules.where(id: positions.keys)
modules.each do |m|
m.update_columns(x: positions[m.id.to_s][:x], y: positions[m.id.to_s][:y])
m.update(x: positions[m.id.to_s][:x], y: positions[m.id.to_s][:y])
end
my_modules.reload
end
@ -498,7 +479,7 @@ class Experiment < ApplicationRecord
y_diff = my_modules.pluck(:y).min
my_modules.each do |m|
m.update_columns(x: m.x - x_diff, y: m.y - y_diff)
m.update(x: m.x - x_diff, y: m.y - y_diff)
end
end

View file

@ -10,8 +10,9 @@ class MyModule < ApplicationRecord
before_create :create_blank_protocol
before_create :assign_default_status_flow
around_save :exec_status_consequences, if: :my_module_status_id_changed?
after_save -> { experiment.workflowimg.purge },
if: -> { (saved_changes.keys & %w(x y experiment_id my_module_group_id input_id output_id archived)).any? }
auto_strip_attributes :name, :description, nullify: false, if: proc { |mm| mm.name_changed? || mm.description_changed? }
validates :name,
@ -168,7 +169,6 @@ class MyModule < ApplicationRecord
raise ActiveRecord::Rollback
end
end
experiment.generate_workflow_img
restored
end

View file

@ -37,7 +37,6 @@ class CreateMyModuleService
@my_module.assign_user(@user)
@params[:experiment].generate_workflow_img
new_my_module = @my_module
end
new_my_module

View file

@ -43,7 +43,6 @@ module Experiments
@errors.merge!(@c_exp.errors.to_hash) unless @c_exp.valid?
@c_exp = nil unless succeed?
@c_exp.generate_workflow_img if succeed?
track_activity if succeed?
self

View file

@ -7,8 +7,8 @@ module Experiments
attr_reader :errors
def initialize(experiment_id:)
@exp = Experiment.find experiment_id
def initialize(experiment:)
@exp = experiment
@graph = GraphViz.new(:G, type: :digraph, use: :neato)
@graph[:size] = '4,4'
@ -75,10 +75,14 @@ module Experiments
def save_file
file = Tempfile.open(%w(wimg .png), Rails.root.join('tmp'))
@graph.output(png: file.path)
@exp.workflowimg.attach(io: file, filename: File.basename(file.path))
file.close
file.unlink
begin
@graph.output(png: file.path)
file.rewind
@exp.workflowimg.attach(io: file, filename: File.basename(file.path))
ensure
file.close
file.unlink
end
end
end
end

View file

@ -616,7 +616,6 @@ class TeamImporter
my_module_group.save!
@my_module_group_mappings[orig_module_group_id] = my_module_group.id
end
experiment.generate_workflow_img
create_my_modules(experiment_json['my_modules'], experiment, user_id)
experiment
end

View file

@ -1297,9 +1297,6 @@ module FirstTimeDataGenerator
created_at: generate_random_time(my_modules[7].created_at, 3.days),
file_name: 'result-ddCq.JPG'
)
# create thumbnail
experiment.generate_workflow_img
end
# Used for delayed jobs

View file

@ -55,18 +55,24 @@
<div class="panel-body">
<% if experiment.active_modules.length > 0 %>
<%= link_to canvas_experiment_path(experiment) do %>
<div class="workflowimg-container"
data-check-img="<%= updated_img_experiment_url(experiment) %>"
data-updated-img="<%= fetch_workflow_img_experiment_url(experiment) %>"
data-timestamp="<%= experiment.updated_at %>" >
</div>
<%= link_to canvas_experiment_path(experiment), class: 'no-workflowimg' do %>
<% if experiment.workflowimg.attached? %>
<div class="workflowimg-container" data-workflowimg-present="true">
<%= render partial: 'projects/show/workflow_img.html.erb', locals: { experiment: experiment } %>
</div>
<% else %>
<div class="workflowimg-container"
data-workflowimg-present="false"
data-workflowimg-url="<%= fetch_workflow_img_experiment_url(experiment) %>" >
<i class="fas fa-spinner fa-spin fa-3x workflowimg-spinner hidden" aria-hidden="true"></i>
</div>
<% end %>
<% end %>
<% else %>
<% if can_manage_experiment?(experiment) %>
<%= link_to( t('experiments.edit.add_task'),
canvas_experiment_path(experiment, editMode: true),
class: 'no-workflowimg') %>
class: 'no-tasks') %>
<% else %>
<div class="no-workflowimg">
<p><%= t('experiments.edit.no_workflowimg') %></p>

View file

@ -1 +1 @@
<%= image_tag url_for(@experiment.workflowimg), class: 'img-responsive center-block' %>
<%= image_tag url_for(experiment.workflowimg), class: 'img-responsive center-block' %>

View file

@ -315,7 +315,6 @@ Rails.application.routes.draw do
post 'clone' # clone experiment
get 'move_modal' # return modal with move options
post 'move' # move experiment
get 'updated_img' # Checks if the workflow image is updated
get 'fetch_workflow_img' # Get udated workflow img
end
end

View file

@ -4,7 +4,7 @@ require 'rails_helper'
describe Experiments::GenerateWorkflowImageService do
let(:experiment) { create :experiment, :with_tasks }
let(:params) { { experiment_id: experiment.id } }
let(:params) { { experiment: experiment } }
context 'when succeed' do
it 'succeed? returns true' do

View file

@ -33,7 +33,7 @@ describe TeamImporter do
@exp = @team_importer.import_experiment_template_from_dir(TEMPLATE_DIR,
PROJECT_ID,
USER_ID)
Experiments::GenerateWorkflowImageService.call(experiment_id: @exp.id)
Experiments::GenerateWorkflowImageService.call(experiment: @exp)
@exp.reload
end