Merge branch 'develop' into features/task-flows

This commit is contained in:
Urban Rotnik 2020-08-25 15:30:22 +02:00
commit 5923a4c014
40 changed files with 255 additions and 135 deletions

View file

@ -1 +1 @@
1.19.4
1.19.6

View file

@ -154,6 +154,7 @@ var MyModuleRepositories = (function() {
pageLength: 25,
sScrollX: '100%',
sScrollXInner: '100%',
stateDuration: 0,
destroy: true,
ajax: {
url: $(tableContainer).data('source'),

View file

@ -405,7 +405,6 @@
var $checkboxes = $(checkboxUl).find(".nested_fields");
$checkboxes.each(function (itemPos) {
var $this = $(this);
var $formGroup = $this.find(".form-group");
var $label = $formGroup.find(".control-label");
var $textInput = $formGroup.find(".checklist-item-text");
@ -583,6 +582,11 @@
}, 1000);
animateSpinner(null, true);
$(".nested_step_checklists ul").each(function () {
reorderCheckboxData(this);
});
DragNDropSteps.appendFilesToForm(ev).then(formData => {
formData.append('step[description]', $tinyMCEInput);
$.ajax({
@ -591,11 +595,6 @@
data: formData,
contentType: false,
processData: false,
beforeSend: function() {
$(".nested_step_checklists ul").each(function () {
reorderCheckboxData(this);
});
},
success: function(data) {
$($form.closest('.well')).after(data.html);
var $new_step = $($form.closest('.well')).next();

View file

@ -398,6 +398,7 @@ var RepositoryDatatable = (function(global) {
sScrollX: '100%',
sScrollXInner: '100%',
order: $(TABLE_ID).data('default-order'),
stateDuration: 0,
colReorder: {
fixedColumnsLeft: 2,
realtime: false

View file

@ -11,8 +11,6 @@
display: flex;
.add-result-dropdown {
margin-right: auto;
li {
cursor: pointer;
padding: .5em 1em;
@ -31,6 +29,10 @@
}
}
.collapse-expand-result {
margin-left: auto;
}
.sort-result-dropdown {
margin-left: .5em;

View file

@ -3,23 +3,26 @@
module Api
module V1
class ProtocolsController < BaseController
before_action :load_team
before_action :load_project
before_action :load_experiment
before_action :load_task
include Api::V1::ExtraParams
before_action :load_team, :load_project, :load_experiment, :load_task
before_action only: :show do
load_protocol(:id)
end
def index
protocols = @task.protocols
.page(params.dig(:page, :number))
.per(params.dig(:page, :size))
render jsonapi: protocols,
each_serializer: ProtocolSerializer
each_serializer: ProtocolSerializer, rte_rendering: render_rte?, team: @team
end
private
def load_protocol
@protocol = @task.protocols.find(params.require(:id))
def show
render jsonapi: @protocol, serializer: ProtocolSerializer,
include: include_params,
rte_rendering: render_rte?,
team: @team
end
end
end

View file

@ -16,13 +16,15 @@ module Api
render jsonapi: steps, each_serializer: StepSerializer,
include: include_params,
rte_rendering: render_rte?
rte_rendering: render_rte?,
team: @team
end
def show
render jsonapi: @step, serializer: StepSerializer,
include: include_params,
rte_rendering: render_rte?
rte_rendering: render_rte?,
team: @team
end
def create
@ -59,7 +61,7 @@ module Api
end
def permitted_includes
%w(tables assets checklists checklists.checklist_items comments)
%w(tables assets checklists checklists.checklist_items comments user)
end
def load_step_for_managing

View file

@ -19,11 +19,11 @@ module Api
.page(params.dig(:page, :number))
.per(params.dig(:page, :size))
render jsonapi: tasks, each_serializer: TaskSerializer, rte_rendering: render_rte?
render jsonapi: tasks, each_serializer: TaskSerializer, rte_rendering: render_rte?, team: @team
end
def show
render jsonapi: @task, serializer: TaskSerializer, rte_rendering: render_rte?
render jsonapi: @task, serializer: TaskSerializer, rte_rendering: render_rte?, team: @team
end
def create

View file

@ -33,10 +33,7 @@ class CanvasController < ApplicationController
to_archive = []
if update_params[:remove].present?
to_archive = update_params[:remove].split(',')
if to_archive.all? do |id|
is_int?(id) &&
can_manage_module?(MyModule.find_by_id(id))
end
if to_archive.all? { |id| can_archive_module?(MyModule.find_by(id: id)) }
to_archive.collect!(&:to_i)
else
return render_403
@ -117,16 +114,14 @@ class CanvasController < ApplicationController
# Okay, JSON parsed!
unless to_move.is_a?(Hash) &&
to_move.keys.all? do |id|
id.is_a?(String) &&
(!is_int?(id) || can_manage_module?(MyModule.find_by_id(id)))
!is_int?(id) || can_move_module?(MyModule.find_by(id: id))
end &&
to_move.values.all? do |exp_id|
exp_id.is_a?(String) &&
can_manage_experiment?(Experiment.find_by_id(exp_id))
can_manage_experiment?(Experiment.find_by(id: exp_id))
end
return render_403
end
rescue
rescue StandardError
return render_403
end
end

View file

@ -6,9 +6,9 @@ module Dashboard
include MyModulesHelper
def show
date = DateTime.parse(params[:date])
start_date = date.at_beginning_of_month.utc - 7.days
end_date = date.at_end_of_month.utc + 14.days
date = params[:date].in_time_zone(current_user.time_zone)
start_date = date.at_beginning_of_month.utc - 8.days
end_date = date.at_end_of_month.utc + 15.days
due_dates = current_user.my_modules.active.uncomplete
.joins(experiment: :project)
.where(experiments: { archived: false })
@ -16,16 +16,18 @@ module Dashboard
.where('my_modules.due_date > ? AND my_modules.due_date < ?', start_date, end_date)
.joins(:protocols).where(protocols: { team_id: current_team.id })
.pluck(:due_date)
render json: { events: due_dates.map { |i| { date: i } } }
render json: { events: due_dates.map { |i| { date: i.to_date } } }
end
def day
date = DateTime.parse(params[:date]).utc
date = params[:date].in_time_zone(current_user.time_zone)
start_date = date.utc
end_date = date.end_of_day.utc
my_modules = current_user.my_modules.active.uncomplete
.joins(experiment: :project)
.where(experiments: { archived: false })
.where(projects: { archived: false })
.where('DATE(my_modules.due_date) = DATE(?)', date)
.where('my_modules.due_date > ? AND my_modules.due_date < ?', start_date, end_date)
.where(projects: { team_id: current_team.id })
render json: {
html: render_to_string(partial: 'shared/my_modules_list_partial.html.erb', locals: {

View file

@ -4,8 +4,7 @@ class MyModuleRepositoriesController < ApplicationController
include ApplicationHelper
before_action :load_my_module
before_action :load_repository, except: %i(repositories_dropdown_list repositories_list_html export_repository)
before_action :load_repository_or_snapshot, only: :export_repository
before_action :load_repository, except: %i(repositories_dropdown_list repositories_list_html)
before_action :check_my_module_view_permissions
before_action :check_repository_view_permissions, except: %i(repositories_dropdown_list repositories_list_html)
before_action :check_assign_repository_records_permissions, only: :update
@ -120,6 +119,18 @@ class MyModuleRepositoriesController < ApplicationController
def export_repository
if params[:header_ids]
RepositoryZipExport.generate_zip(params, @repository, current_user)
Activities::CreateActivityService.call(
activity_type: :export_inventory_items_assigned_to_task,
owner: current_user,
subject: @repository,
team: current_team,
message_items: {
my_module: @my_module.id,
repository: @repository.id
}
)
render json: { message: t('zip_export.export_request_success') }, status: :ok
else
render json: { message: t('zip_export.export_error') }, status: :unprocessable_entity
@ -138,12 +149,6 @@ class MyModuleRepositoriesController < ApplicationController
render_404 unless @repository
end
def load_repository_or_snapshot
@repository = Repository.accessible_by_teams(current_team).find_by(id: params[:id])
@repository ||= RepositorySnapshot.find_by(id: params[:id])
render_404 unless @repository
end
def check_my_module_view_permissions
render_403 unless can_read_experiment?(@my_module.experiment)
end

View file

@ -101,6 +101,28 @@ class MyModuleRepositorySnapshotsController < ApplicationController
render json: {}
end
def export_repository_snapshot
if params[:header_ids]
RepositoryZipExport.generate_zip(params, @repository_snapshot, current_user)
Activities::CreateActivityService.call(
activity_type: :export_inventory_snapshot_items_assigned_to_task,
owner: current_user,
subject: @repository_snapshot,
team: current_team,
message_items: {
my_module: @my_module.id,
repository_snapshot: @repository_snapshot.id,
created_at: @repository_snapshot.created_at
}
)
render json: { message: t('zip_export.export_request_success') }, status: :ok
else
render json: { message: t('zip_export.export_error') }, status: :unprocessable_entity
end
end
private
def load_my_module

View file

@ -9,7 +9,7 @@ class MyModulesController < ApplicationController
before_action :load_vars
before_action :load_projects_tree, only: %i(protocols results activities archive)
before_action :check_manage_permissions_archive, only: %i(update)
before_action :check_archive_and_restore_permissions, only: %i(update)
before_action :check_manage_permissions, only: %i(description due_date update_description update_protocol_description)
before_action :check_view_permissions, except: %i(update update_description update_protocol_description
toggle_task_state)
@ -297,11 +297,11 @@ class MyModulesController < ApplicationController
render_403 && return unless can_manage_module?(@my_module)
end
def check_manage_permissions_archive
def check_archive_and_restore_permissions
render_403 && return unless if my_module_params[:archived] == 'false'
can_restore_module?(@my_module)
else
can_manage_module?(@my_module)
can_archive_module?(@my_module)
end
end

View file

@ -4,9 +4,9 @@ class RepositoryRowsController < ApplicationController
include ApplicationHelper
include MyModulesHelper
before_action :load_repository
before_action :load_repository_row, only: %i(update show assigned_task_list)
before_action :check_read_permissions, except: %i(create update delete_records copy_records)
before_action :load_repository, except: :show
before_action :load_repository_row, only: %i(update assigned_task_list)
before_action :check_read_permissions, except: %i(show create update delete_records copy_records)
before_action :check_snapshotting_status, only: %i(create update delete_records copy_records)
before_action :check_create_permissions, only: :create
before_action :check_delete_permissions, only: %i(delete_records archive_records restore_records)
@ -51,6 +51,11 @@ class RepositoryRowsController < ApplicationController
end
def show
@repository_row = RepositoryRow.find_by(id: params[:id])
return render_404 unless @repository_row
return render_404 unless @repository_row.repository_id == params[:repository_id].to_i
return render_403 unless can_read_repository?(@repository_row.repository)
@assigned_modules = @repository_row.my_modules.joins(experiment: :project)
@viewable_modules = @assigned_modules.viewable_by_user(current_user, current_user.teams)
@private_modules = @assigned_modules - @viewable_modules

View file

@ -263,7 +263,9 @@ class SearchController < ApplicationController
def search_repository
@repository = Repository.find_by_id(params[:repository])
render_403 unless can_read_repository?(@repository)
unless current_user.teams.include?(@repository.team) || @repository.private_shared_with?(current_user.teams)
render_403
end
@repository_results = []
if @repository_search_count_total > 0
@repository_results =

View file

@ -13,8 +13,6 @@ class StepsController < ApplicationController
before_action :check_manage_permissions, only: %i(new create edit update destroy move_up move_down)
before_action :check_complete_and_checkbox_permissions, only: %i(toggle_step_state checklistitem_state)
before_action :update_checklist_item_positions, only: %i(create update)
def new
@step = Step.new
@ -165,6 +163,9 @@ class StepsController < ApplicationController
table.last_modified_by = current_user unless table.new_record?
table.team = current_team
end
update_checklist_items_without_callback(step_params_all)
if @step.save
TinyMceAsset.update_images(@step, params[:tiny_mce_images], current_user)
@ -423,18 +424,6 @@ class StepsController < ApplicationController
private
def update_checklist_item_positions
if params["step"].present? && params["step"]["checklists_attributes"].present?
params["step"]["checklists_attributes"].values.each do |cla|
if cla["checklist_items_attributes"].present?
cla["checklist_items_attributes"].each do |idx, item|
item["position"] = idx
end
end
end
end
end
# This function is used for partial update of step references and
# it's useful when you want to execute destroy action on attribute
# collection separately from normal update action, for example if
@ -534,6 +523,22 @@ class StepsController < ApplicationController
end
end
def update_checklist_items_without_callback(params)
params.dig('checklists_attributes')&.values&.each do |cl|
ck = @step.checklists.find_by(id: cl[:id])
next if ck.nil? # ck is new checklist, skip update positions
cl['checklist_items_attributes']&.each do |item|
# Here item is somehow array of index and parameters [0, paramteters<Object>], should be fixed on FE also
item_record = ck.checklist_items.find_by(id: item[1][:id])
next unless item_record
item_record.update_attribute('position', item[1][:position])
end
end
end
def check_view_permissions
render_403 unless can_read_protocol_in_module?(@protocol) || can_read_protocol_in_repository?(@protocol)
end

View file

@ -15,15 +15,32 @@ class Users::PasswordsController < Devise::PasswordsController
# end
# PUT /resource/password
# def update
# super
# end
def update
self.resource = resource_class.reset_password_by_token(resource_params)
yield resource if block_given?
# protected
if resource.errors.empty?
resource.unlock_access! if unlockable?(resource)
if !resource.two_factor_auth_enabled?
flash_message = resource.active_for_authentication? ? :updated : :updated_not_active
set_flash_message!(:notice, flash_message)
resource.after_database_authentication
sign_in(resource_name, resource)
else
set_flash_message!(:notice, :updated_not_active)
end
respond_with resource, location: after_resetting_password_path_for(resource)
else
set_minimum_password_length
respond_with resource
end
end
# def after_resetting_password_path_for(resource)
# super(resource)
# end
protected
def after_resetting_password_path_for(resource)
resource.two_factor_auth_enabled? ? new_session_path(resource_name) : after_sign_in_path_for(resource)
end
# The path used after sending reset password instructions
# def after_sending_reset_password_instructions_path_for(resource_name)

View file

@ -12,7 +12,7 @@ module GlobalActivitiesHelper
if value.is_a? String
value
elsif value['type'] == 'Time' # use saved date for printing
l(Time.at(value['value']), format: :full_date)
l(Time.at(value['value']), format: :full)
else
no_links ? generate_name(value) : generate_link(value, activity)
end

View file

@ -138,13 +138,11 @@ class Experiment < ApplicationRecord
archive_modules(to_archive, current_user) if to_archive.any?
# Update only existing tasks positions to release positions for new tasks
existing_positions = positions
.slice(*positions.keys.map { |k| k unless k.to_s.start_with?('n') }.compact)
existing_positions = positions.slice(*positions.keys.map { |k| k unless k.to_s.start_with?('n') }.compact)
update_module_positions(existing_positions) if existing_positions.any?
# Move only existing tasks to release positions for new tasks
existing_to_move = to_move
.slice(*to_move.keys.map { |k| k unless k.to_s.start_with?('n') }.compact)
existing_to_move = to_move.slice(*to_move.keys.map { |k| k unless k.to_s.start_with?('n') }.compact)
move_modules(existing_to_move, current_user) if existing_to_move.any?
# add new modules

View file

@ -5,7 +5,6 @@ Canaid::Permissions.register_for(MyModule) do
manage_users_in_module
assign_repository_rows_to_module
assign_sample_to_module
change_my_module_flow_status
create_comments_in_module
create_my_module_repository_snapshot
manage_my_module_repository_snapshots)
@ -17,12 +16,17 @@ Canaid::Permissions.register_for(MyModule) do
end
end
# module: update, archive, move
# module: update
# result: create, update
can :manage_module do |user, my_module|
can_manage_experiment?(user, my_module.experiment)
end
# module: archive
can :archive_module do |user, my_module|
can_manage_experiment?(user, my_module.experiment)
end
# NOTE: Must not be dependent on canaid parmision for which we check if it's
# active
# module: restore
@ -31,6 +35,11 @@ Canaid::Permissions.register_for(MyModule) do
my_module.archived?
end
# module: move
can :move_module do |user, my_module|
can_manage_experiment?(user, my_module.experiment)
end
# module: assign/reassign/unassign users
can :manage_users_in_module do |user, my_module|
user.is_owner_of_project?(my_module.experiment.project)

View file

@ -3,6 +3,10 @@
module Api
module V1
class ProtocolSerializer < ActiveModel::Serializer
include ApplicationHelper
include ActionView::Helpers::TextHelper
include InputSanitizeHelper
type :protocols
attributes :id, :name, :authors, :description, :protocol_type
has_many :protocol_keywords,
@ -12,6 +16,17 @@ module Api
unless: -> { object.protocol_keywords.empty? }
has_many :steps, serializer: StepSerializer, if: -> { object.steps.any? }
belongs_to :parent, serializer: ProtocolSerializer, if: -> { object.parent.present? }
def description
if instance_options[:rte_rendering]
custom_auto_link(object.tinymce_render(:description),
simple_format: false,
tags: %w(img),
team: instance_options[:team])
else
object.description
end
end
end
end
end

View file

@ -8,8 +8,9 @@ module Api
include InputSanitizeHelper
type :steps
attributes :id, :name, :description, :position, :completed
attributes :id, :name, :description, :created_at, :position, :completed
attribute :completed_on, if: -> { object.completed? }
belongs_to :user, serializer: UserSerializer
belongs_to :protocol, serializer: ProtocolSerializer
has_many :assets, serializer: AssetSerializer
has_many :checklists, serializer: ChecklistSerializer
@ -18,7 +19,10 @@ module Api
def description
if instance_options[:rte_rendering]
custom_auto_link(object.tinymce_render(:description), simple_format: false, tags: %w(img))
custom_auto_link(object.tinymce_render(:description),
simple_format: false,
tags: %w(img),
team: instance_options[:team])
else
object.description
end

View file

@ -3,6 +3,10 @@
module Api
module V1
class TaskSerializer < ActiveModel::Serializer
include ApplicationHelper
include ActionView::Helpers::TextHelper
include InputSanitizeHelper
type :tasks
attributes :id, :name, :started_on, :due_date, :description, :state, :archived
has_many :output_tasks, key: :outputs,
@ -22,7 +26,10 @@ module Api
def description
if instance_options[:rte_rendering]
custom_auto_link(object.tinymce_render(:description), simple_format: false, tags: %w(img))
custom_auto_link(object.tinymce_render(:description),
simple_format: false,
tags: %w(img),
team: instance_options[:team])
else
object.description
end

View file

@ -68,7 +68,7 @@ class ActivitiesService
end
def self.my_module_activities(my_module)
subjects_with_children = load_subjects_children(my_module: [my_module.id])
subjects_with_children = load_subjects_children('MyModule': [my_module.id])
query = Activity.where(project: my_module.experiment.project)
query.where(
subjects_with_children.map { '(subject_type = ? AND subject_id IN(?))' }.join(' OR '),

View file

@ -19,12 +19,17 @@ module Reports::Docx::PrivateMethods
tiny_mce_table(elem[:data])
elsif elem[:type] == 'newline'
style = elem[:style] || {}
@docx.p elem[:value] do
align style[:align]
color style[:color]
bold style[:bold]
italic style[:italic]
style style[:style] if style[:style]
# print heading if its heading
# Mixing heading with other style setting causes problems for Word
if %w(h1 h2 h3 h4 h5).include?(style[:style])
@docx.public_send(style[:style], elem[:value])
else
@docx.p elem[:value] do
align style[:align]
color style[:color]
bold style[:bold]
italic style[:italic]
end
end
elsif elem[:type] == 'image'
Reports::Docx.render_img_element(@docx, elem)
@ -287,7 +292,7 @@ module Reports::Docx::PrivateMethods
Reports::Docx.render_p_element(c, cell_content,
scinote_url: scinote_url, link_style: link_style, skip_br: true)
elsif cell_content[:type] == 'table'
c.table formated_cell_content[:data]
c.table formated_cell_content[:data], border_size: Constants::REPORT_DOCX_TABLE_BORDER_SIZE
elsif cell_content[:type] == 'image'
Reports::Docx.render_img_element(c, cell_content, table: { columns: row.children.length / 3 })
end
@ -301,7 +306,7 @@ module Reports::Docx::PrivateMethods
if options[:nested_table]
docx_table
else
@docx.table docx_table
@docx.table docx_table, border_size: Constants::REPORT_DOCX_TABLE_BORDER_SIZE
end
end

View file

@ -44,18 +44,18 @@ class RepositoryTableStateColumnUpdateService
end
end
if state.dig('order', 0, 0) == old_column_index
if state.dig('order', 0, 0).to_i == old_column_index
# Fallback to default order if user had table ordered by
# the deleted column
state['order'] = Constants::REPOSITORY_TABLE_DEFAULT_STATE['order']
elsif state.dig('order', 0, 0) > old_column_index
elsif state.dig('order', 0, 0).to_i > old_column_index
state['order'][0][0] -= 1
end
state['length'] = (state['length'] - 1)
state['time'] = (Time.now.to_f * 1_000).to_i
table_state.save
rescue NoMethodError => e
rescue StandardError => e
Rails.logger.error e.message
RepositoryTableStateService.new(user, repository).create_default_state
end

View file

@ -7,11 +7,12 @@ module RepositoryZipExport
# Fetch rows in the same order as in the currently viewed datatable
if params[:my_module_id]
rows = if repository.is_a?(RepositorySnapshot)
repository.repository_rows
else
repository.repository_rows.joins(:my_module_repository_rows)
.where(my_module_repository_rows: { my_module_id: params[:my_module_id] })
end
repository.repository_rows
else
repository.repository_rows
.joins(:my_module_repository_rows)
.where(my_module_repository_rows: { my_module_id: params[:my_module_id] })
end
else
ordered_row_ids = params[:row_ids]
id_row_map = RepositoryRow.where(id: ordered_row_ids,

View file

@ -7,7 +7,6 @@
data-module-conns="<%= construct_module_connections(my_module) %>">
<% module_group = my_module.my_module_group %>
<% can_manage_module_group = module_group && (module_group.new_record? || module_group.my_modules.all? { |my_module| can_manage_module?(my_module) }) %>
<div class="panel-heading">
@ -21,35 +20,35 @@
<li class="dropdown-header"><%= t('projects.index.options_header') %></li>
<% if can_manage_module?(my_module) %>
<li>
<a class="edit-module" href="" data-module-id="<%= my_module.id %>"><%=t "experiments.canvas.edit.edit_module" %></a>
<a class="edit-module" href="" data-module-id="<%= my_module.id %>"><%= t('experiments.canvas.edit.edit_module') %></a>
</li>
<% end %>
<% if can_manage_experiment?(my_module.experiment) %>
<li>
<a class ="clone-module" href="" data-module-id="<%= my_module.id %>"><%=t "experiments.canvas.edit.clone_module" %></a>
<a class ="clone-module" href="" data-module-id="<%= my_module.id %>"><%= t('experiments.canvas.edit.clone_module') %></a>
</li>
<li <%= 'style=display:none;' if my_module.my_module_group.blank? %>>
<a class ="clone-module-group" href="" data-module-id="<%= my_module.id %>"><%=t "experiments.canvas.edit.clone_module_group" %></a>
<a class ="clone-module-group" href="" data-module-id="<%= my_module.id %>"><%= t('experiments.canvas.edit.clone_module_group') %></a>
</li>
<% end %>
<% if can_manage_module?(my_module) %>
<% if can_move_module?(my_module) %>
<li>
<a class="move-module" href="" data-module-id="<%= my_module.id %>"><%=t "experiments.canvas.edit.move_module" %></a>
<a class="move-module" href="" data-module-id="<%= my_module.id %>"><%= t('experiments.canvas.edit.move_module') %></a>
</li>
<% end %>
<% if can_manage_module_group %>
<% if module_group.my_modules.all? { |my_module| can_move_module?(my_module) } %>
<li>
<a class="move-module-group" href="" data-module-id="<%= my_module.id %>"><%=t "experiments.canvas.edit.move_module_group" %></a>
<a class="move-module-group" href="" data-module-id="<%= my_module.id %>"><%= t('experiments.canvas.edit.move_module_group') %></a>
</li>
<% end %>
<% if can_manage_module?(my_module) %>
<% if can_archive_module?(my_module) %>
<li>
<a class="delete-module" href="" data-module-id="<%= my_module.id %>"><%=t "experiments.canvas.edit.delete_module" %></a>
<a class="delete-module" href="" data-module-id="<%= my_module.id %>"><%= t('experiments.canvas.edit.delete_module') %></a>
</li>
<% end %>
<% if can_manage_module_group %>
<% if module_group.my_modules.all? { |my_module| can_archive_module?(my_module) } %>
<li data-hook="archive-module-group">
<a class ="delete-module-group" href="" data-module-id="<%= my_module.id %>"><%=t "experiments.canvas.edit.delete_module_group" %></a>
<a class ="delete-module-group" href="" data-module-id="<%= my_module.id %>"><%= t('experiments.canvas.edit.delete_module_group') %></a>
</li>
<% end %>
</ul>
@ -59,7 +58,7 @@
<% if can_manage_experiment?(my_module.experiment) %>
<div class="panel-body ep">
<%=t "experiments.canvas.edit.drag_connections" %>
<%= t('experiments.canvas.edit.drag_connections') %>
</div>
<% end %>

View file

@ -25,7 +25,7 @@
<%= t('my_modules.repository.snapshots.full_view.versions_sidebar_button') %>
</button>
<button id="exportAssignedItems" type="button" class="btn btn-secondary">
<span class="fas fa-download"></span>
<span class="fas fa-upload"></span>
<%= t('my_modules.repository.snapshots.full_view.export_button') %>
</button>
</div>

View file

@ -8,7 +8,7 @@
data-default-order="<%= default_snapshot_table_order_as_js_array %>"
data-default-table-columns="<%= default_snapshot_table_columns %>"
data-load-state-url="<%= repository_load_table_state_path(@repository_snapshot) %>"
data-export-url="<%= export_repository_my_module_repository_path(@my_module ,@repository_snapshot) %>"
data-export-url="<%= export_repository_snapshot_my_module_repository_snapshot_path(@my_module, @repository_snapshot) %>"
data-versions-sidebar-url="<%= full_view_sidebar_my_module_repository_snapshots_path(@my_module, @repository_snapshot.parent_id) %>"
>
<thead>

View file

@ -30,7 +30,7 @@
</ul>
</div>
<% end %>
<div class="sci-btn-group">
<div class="sci-btn-group collapse-expand-result">
<button class="btn btn-light" id="results-collapse-btn">
<span class="fas fa-caret-up"></span>
<span class="hidden-xs-custom"><%= t'my_modules.results.collapse_label' %></span>

View file

@ -57,8 +57,11 @@
(function () {
var formErrors = {};
<% resource.errors.each do |err, m| %>
formErrors["<%= err %>"] =["<%= m %>"];
<% resource.errors.as_json.each do |err, messages| %>
formErrors["<%= err %>"]=[]
<% messages.each do |message| %>
formErrors["<%= err %>"].push('<%= message %>');
<% end %>
<% end %>
$("form").renderFormErrors("user", formErrors, false);
@ -71,8 +74,11 @@
(function () {
var formErrors = {};
<% @team.errors.each do |err, m| %>
formErrors["<%= err %>"] =["<%= m %>"];
<% @team.errors.as_json.each do |err, messages| %>
formErrors["<%= err %>"]=[]
<% messages.each do |message| %>
formErrors["<%= err %>"].push('<%= message %>');
<% end %>
<% end %>
$("form").renderFormErrors("team", formErrors, false);

View file

@ -65,9 +65,11 @@
<script>
(function () {
var formErrors = {};
<% resource.errors.each do |err, m| %>
formErrors["<%= err %>"] =["<%= m %>"];
<% resource.errors.as_json.each do |err, messages| %>
formErrors["<%= err %>"]=[]
<% messages.each do |message| %>
formErrors["<%= err %>"].push('<%= message %>');
<% end %>
<% end %>
$("form").renderFormErrors("user", formErrors, false);
@ -80,8 +82,11 @@
(function () {
var formErrors = {};
<% @team.errors.each do |err, m| %>
formErrors["<%= err %>"] =["<%= m %>"];
<% @team.errors.as_json.each do |err, messages| %>
formErrors["<%= err %>"]=[]
<% messages.each do |message| %>
formErrors["<%= err %>"].push('<%= message %>');
<% end %>
<% end %>
$("form").renderFormErrors('team', formErrors, false);

View file

@ -17,7 +17,7 @@
<%= link_to t("devise.links.not_receive_confirmation"), new_confirmation_path(resource_name) %><br />
<% end -%>
<%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %>
<%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' && flash[:alert] == t('devise.failure.locked') %>
<%= link_to t("devise.links.not_receive_unlock"), new_unlock_path(resource_name) %><br />
<% end -%>

View file

@ -243,7 +243,9 @@ Devise.setup do |config|
# When set to false, does not sign a user in automatically after their password is
# reset. Defaults to true, so a user is signed in automatically after a reset.
config.sign_in_after_reset_password = false
#
# This setting has no effect, controller has been overriden at controllers/users/passwords_controller.rb
# config.sign_in_after_reset_password = false
# ==> Configuration for :encryptable
# Allow you to use another encryption algorithm besides bcrypt (default). You can use

View file

@ -143,9 +143,8 @@ class Extends
step: nil
}
ACTIVITY_MESSAGE_ITEMS_TYPES =
ACTIVITY_SUBJECT_TYPES + %w(User Tag RepositoryColumn RepositoryRow Step Asset TinyMceAsset Repository)
.freeze
ACTIVITY_MESSAGE_ITEMS_TYPES = ACTIVITY_SUBJECT_TYPES + %w(User Tag RepositoryColumn RepositoryRow Step
Asset TinyMceAsset Repository RepositorySnapshot).freeze
ACTIVITY_TYPES = {
create_project: 0,
@ -287,7 +286,9 @@ class Extends
archive_inventory_item: 142,
restore_inventory_item: 143,
archive_inventory: 144,
restore_inventory: 145
restore_inventory: 145,
export_inventory_items_assigned_to_task: 146,
export_inventory_snapshot_items_assigned_to_task: 147
}
ACTIVITY_GROUPS = {

View file

@ -825,7 +825,7 @@ en:
no_assigned_items: 'No items assigned'
no_snapshots_label: 'You have not created any snapshots yet. To do so click the button bellow.'
versions_sidebar_button: 'View versions'
export_button: "Export .csv"
export_button: "Export items"
create_button: 'Create snapshot'
set_default_button: 'Set as default view'
created_by: 'by %{full_name}'

View file

@ -173,6 +173,8 @@ en:
delete_chemical_structure_on_protocol_html: "%{user} deleted chemical structure %{asset_name} on protocol %{protocol}."
delete_chemical_structure_on_task_html: "%{user} deleted chemical structure %{asset_name} on task %{my_module}."
protocol_description_in_task_edited_html: "%{user} edited protocol description on task %{my_module}."
export_inventory_items_assigned_to_task_html: "%{user} exported inventory item(s) assigned to task %{my_module} from inventory %{repository}: Live version."
export_inventory_snapshot_items_assigned_to_task_html: "%{user} exported inventory item(s) assigned to task %{my_module} from inventory %{repository_snapshot}: Snapshot of %{created_at}."
activity_name:
create_project: "Project created"
@ -311,6 +313,8 @@ en:
delete_chemical_structure_on_protocol: "Chemical structure on protocol deleted"
delete_chemical_structure_on_task: "Chemical structure on task deleted"
protocol_description_in_task_edited: "Protocol description in task edited"
export_inventory_items_assigned_to_task: "Task-assigned inventory items exported (live version)"
export_inventory_snapshot_items_assigned_to_task: "Task-assigned inventory items exported (snapshot)"
activity_group:
projects: "Projects"

View file

@ -14,7 +14,8 @@ Rails.application.routes.draw do
sessions: 'users/sessions',
invitations: 'users/invitations',
confirmations: 'users/confirmations',
omniauth_callbacks: 'users/omniauth_callbacks' }
omniauth_callbacks: 'users/omniauth_callbacks',
passwords: 'users/passwords' }
root 'dashboards#show'
@ -365,6 +366,7 @@ Rails.application.routes.draw do
member do
get :full_view_table
post :index_dt
post :export_repository_snapshot
get :status
end
@ -684,7 +686,7 @@ Rails.application.routes.draw do
resources :task_tags, only: %i(index show),
path: 'tags',
as: :tags
resources :protocols, only: %i(index) do
resources :protocols, only: %i(index show) do
resources :steps do
resources :assets, only: %i(index show create), path: 'attachments'
resources :checklists, path: 'checklists' do

View file

@ -20,6 +20,7 @@ Scenario: Unsuccessful add Text result
Given I am on Task results page
And I click "Add new result" button
And I click on "Text" within dropdown menu
And WAIT
And I click "Add" button
Then I should see "can't be blank"
And I click "Cancel" button