mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-09-08 14:15:35 +08:00
Merge pull request #5417 from scinote-eln/features/sa-item-assigning
Features/sa item assigning
This commit is contained in:
commit
5a06f649d6
48 changed files with 743 additions and 52 deletions
|
@ -18,7 +18,8 @@ function initEditMyModuleDescription() {
|
|||
{
|
||||
onSaveCallback: () => {
|
||||
Prism.highlightAllUnder(viewObject.get(0));
|
||||
}
|
||||
},
|
||||
assignableMyModuleId: $('#my_module_description_textarea').data('object-id')
|
||||
}
|
||||
);
|
||||
}).on('click', 'a', function(e) {
|
||||
|
|
|
@ -841,6 +841,9 @@ var MyModuleRepositories = (function() {
|
|||
reloadFullViewTable: () => {
|
||||
if (!FULL_VIEW_TABLE) return;
|
||||
FULL_VIEW_TABLE.ajax.reload(null, false);
|
||||
},
|
||||
reloadRepositoriesList: (repositoryId, expand = false) => {
|
||||
reloadRepositoriesList(repositoryId, expand);
|
||||
}
|
||||
};
|
||||
}());
|
||||
|
|
|
@ -25,7 +25,7 @@ var MyModuleStockConsumption = (function() {
|
|||
$manageModal.find('.modal-content').html(result.html);
|
||||
$manageModal.modal('show');
|
||||
focusStockConsumption();
|
||||
SmartAnnotation.init($(CONSUMPTION_MODAL + ' #comment')[0]);
|
||||
SmartAnnotation.init($(CONSUMPTION_MODAL + ' #comment')[0], false);
|
||||
|
||||
$('#stock_consumption').on('input', function() {
|
||||
let initialValue = new Decimal($(this).data('initial-value') || 0);
|
||||
|
|
|
@ -33,7 +33,7 @@ $.fn.dataTable.render.newRepositoryTextValue = function(formId, columnId, $cell)
|
|||
data-type="RepositoryTextValue">
|
||||
</div>`);
|
||||
|
||||
SmartAnnotation.init($cell.find('input'));
|
||||
SmartAnnotation.init($cell.find('input'), false);
|
||||
};
|
||||
|
||||
$.fn.dataTable.render.newRepositoryListValue = function(formId, columnId, $cell) {
|
||||
|
|
|
@ -266,6 +266,10 @@ var RepositoryDatatable = (function(global) {
|
|||
});
|
||||
}
|
||||
|
||||
function updateSelectedRowsForAssignments() {
|
||||
window.AssignItemsToTaskModalComponent.setShowCallback(() => rowsSelected);
|
||||
}
|
||||
|
||||
function checkAvailableColumns() {
|
||||
$.ajax({
|
||||
url: $(TABLE_ID).data('available-columns'),
|
||||
|
@ -730,6 +734,7 @@ var RepositoryDatatable = (function(global) {
|
|||
})
|
||||
|
||||
initRowSelection();
|
||||
updateSelectedRowsForAssignments();
|
||||
// $(window).resize(() => {
|
||||
// setTimeout(() => {
|
||||
// adjustTableHeader();
|
||||
|
|
|
@ -120,7 +120,7 @@ var RepositoryStockValues = (function() {
|
|||
this.value = formatDecimalValue(this.value, decimals);
|
||||
});
|
||||
|
||||
SmartAnnotation.init($('#repository-stock-value-comment')[0]);
|
||||
SmartAnnotation.init($('#repository-stock-value-comment')[0], false);
|
||||
|
||||
$('#repository-stock-value-comment').on('input', function() {
|
||||
$(this).closest('.sci-input-container').toggleClass(
|
||||
|
|
|
@ -27,7 +27,9 @@
|
|||
formAjaxResultText($form);
|
||||
Results.initCancelFormButton($form, initNewReslutText);
|
||||
Results.toggleResultEditButtons(false);
|
||||
TinyMCE.init('#result_text_attributes_textarea');
|
||||
TinyMCE.init('#result_text_attributes_textarea', {
|
||||
assignableMyModuleId: $('#result_text_attributes_textarea').data('my-module-id')
|
||||
});
|
||||
$('#result_name').focus();
|
||||
},
|
||||
error: function() {
|
||||
|
@ -58,7 +60,9 @@
|
|||
Results.toggleResultEditButtons(true);
|
||||
});
|
||||
Results.toggleResultEditButtons(false);
|
||||
TinyMCE.init('#result_text_attributes_textarea');
|
||||
TinyMCE.init('#result_text_attributes_textarea', {
|
||||
assignableMyModuleId: $('#result_text_attributes_textarea').data('my-module-id')
|
||||
});
|
||||
$('#result_name').focus();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ var inlineEditing = (function() {
|
|||
|
||||
function initSmartAnnotation(container) {
|
||||
if (container.data('smart-annotation')) {
|
||||
SmartAnnotation.init(inputField(container));
|
||||
SmartAnnotation.init(inputField(container), false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* global _ */
|
||||
/* global PerfectScrollbar MyModuleRepositories HelperModule _ */
|
||||
|
||||
var SmartAnnotation = (function() {
|
||||
'use strict';
|
||||
|
@ -11,7 +11,7 @@ var SmartAnnotation = (function() {
|
|||
});
|
||||
}
|
||||
|
||||
function SetAtWho(field, deferred) {
|
||||
function SetAtWho(field, deferred, assignableMyModuleId) {
|
||||
var FilterTypeEnum = Object.freeze({
|
||||
USER: { tag: 'users', dataUrl: $(document.body).attr('data-atwho-users-url') },
|
||||
TASK: { tag: 'sa-tasks', dataUrl: $(document.body).attr('data-atwho-task-url') },
|
||||
|
@ -67,6 +67,7 @@ var SmartAnnotation = (function() {
|
|||
let activeRepository = repositoryTab.find('.btn-primary');
|
||||
if (activeRepository.length) {
|
||||
params.repository_id = activeRepository.data('object-id');
|
||||
params.assignable_my_module_id = assignableMyModuleId;
|
||||
}
|
||||
}
|
||||
$.getJSON(filterType.dataUrl, params, function(data) {
|
||||
|
@ -81,6 +82,10 @@ var SmartAnnotation = (function() {
|
|||
$currentAtWho.find(`.repository-object[data-object-id="${data.repository}"]`)
|
||||
.addClass('btn-primary').removeClass('btn-light');
|
||||
}
|
||||
if ($('.atwho-scroll-container')[0]) {
|
||||
// eslint-disable-next-line no-new
|
||||
new PerfectScrollbar($('.atwho-scroll-container')[0]);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
},
|
||||
|
@ -141,6 +146,24 @@ var SmartAnnotation = (function() {
|
|||
$(this).addClass('btn-primary').removeClass('btn-light');
|
||||
$(field).click().focus();
|
||||
});
|
||||
$currentAtWho.on('click', '.atwho-assign-button', function() {
|
||||
let el = $(this);
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
url: el.data('assign-url'),
|
||||
data: { repository_row_id: el.data('repository-row-id') },
|
||||
dataType: 'json',
|
||||
success: function(data) {
|
||||
if (typeof MyModuleRepositories !== 'undefined') {
|
||||
MyModuleRepositories.reloadRepositoriesList(el.data('repository-id'));
|
||||
}
|
||||
HelperModule.flashAlertMsg(data.flash, 'success');
|
||||
},
|
||||
error: function(response) {
|
||||
HelperModule.flashAlertMsg(response.responseJSON.flash, 'danger');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if ($currentAtWho.find('.tab-pane.active').length === 0) {
|
||||
let filterType = DEFAULT_SEARCH_FILTER.tag;
|
||||
|
@ -223,8 +246,8 @@ var SmartAnnotation = (function() {
|
|||
$('.atwho-header-res').find('.fa-times').click();
|
||||
}
|
||||
|
||||
function initialize(field, deferred) {
|
||||
var atWho = new SetAtWho(field, deferred);
|
||||
function initialize(field, deferred, assignableMyModuleId) {
|
||||
var atWho = new SetAtWho(field, deferred, assignableMyModuleId);
|
||||
atWho.init();
|
||||
}
|
||||
|
||||
|
@ -240,7 +263,7 @@ var SmartAnnotation = (function() {
|
|||
(function() {
|
||||
$(document).on('focus', '[data-atwho-edit]', function() {
|
||||
if (_.isUndefined($(this).data('atwho'))) {
|
||||
SmartAnnotation.init(this);
|
||||
SmartAnnotation.init(this, false);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -147,7 +147,7 @@ var CommentsSidebar = (function() {
|
|||
|
||||
function initInputField() {
|
||||
if ($(SIDEBAR).find('.comment-input-field').length) {
|
||||
SmartAnnotation.init($(SIDEBAR).find('.comment-input-field'));
|
||||
SmartAnnotation.init($(SIDEBAR).find('.comment-input-field'), false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
/* global bwipjs PrintModalComponent RepositoryDatatable */
|
||||
/* global bwipjs PrintModalComponent RepositoryDatatable HelperModule MyModuleRepositories */
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
$(document).on('click', '.record-info-link', function(e) {
|
||||
var that = $(this);
|
||||
let params = {};
|
||||
if ($('.my-modules-protocols-index').length) {
|
||||
params.my_module_id = $('.my-modules-protocols-index').data('task-id');
|
||||
}
|
||||
$.ajax({
|
||||
method: 'GET',
|
||||
url: that.attr('href'),
|
||||
data: params,
|
||||
dataType: 'json'
|
||||
}).done(function(xhr, settings, data) {
|
||||
if ($('#modal-info-repository-row').length) {
|
||||
|
@ -16,6 +21,7 @@
|
|||
$('.modal-backdrop').remove();
|
||||
}
|
||||
$('body').append($.parseHTML(data.responseJSON.html));
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
$('#modal-info-repository-row').modal('show', {
|
||||
backdrop: true,
|
||||
keyboard: false
|
||||
|
@ -73,4 +79,27 @@
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('click', '.assign-inventory-button', function(e) {
|
||||
e.preventDefault();
|
||||
let assignUrl = $(this).data('assignUrl');
|
||||
let repositoryRowId = $(this).data('repositoryRowId');
|
||||
|
||||
$.ajax({
|
||||
url: assignUrl,
|
||||
type: 'POST',
|
||||
data: { repository_row_id: repositoryRowId },
|
||||
dataType: 'json',
|
||||
success: function(data) {
|
||||
HelperModule.flashAlertMsg(data.flash, 'success');
|
||||
$('#modal-info-repository-row').modal('hide');
|
||||
if (typeof MyModuleRepositories !== 'undefined') {
|
||||
MyModuleRepositories.reloadRepositoriesList(repositoryRowId);
|
||||
}
|
||||
},
|
||||
error: function(error) {
|
||||
HelperModule.flashAlertMsg(error.responseJSON.flash, 'danger');
|
||||
}
|
||||
});
|
||||
});
|
||||
}());
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
.assign-items-to-task-modal-container {
|
||||
.modal-header {
|
||||
color: $color-volcano;
|
||||
display: flex;
|
||||
font-size: $font-size-h2;
|
||||
font-weight: bold;
|
||||
padding: 1rem;
|
||||
|
||||
.close {
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
color: $color-volcano;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-size: $font-size-base;
|
||||
row-gap: 1rem;
|
||||
|
||||
.level-selector {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: .25rem;
|
||||
|
||||
}
|
||||
|
||||
label {
|
||||
font-size: $font-size-h6;
|
||||
font-weight: bold;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
padding: 1rem;
|
||||
}
|
||||
}
|
|
@ -3,4 +3,15 @@
|
|||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.modal-footer[data-assign-item-button="true"] {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
gap: .5em;
|
||||
width: 100%;
|
||||
|
||||
.print-label-button {
|
||||
margin-right: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,7 +83,6 @@
|
|||
max-height: 300px;
|
||||
overflow: hidden;
|
||||
overflow-y: scroll;
|
||||
position: absolute;
|
||||
top: 2.5em;
|
||||
width: 100%;
|
||||
z-index: 9999;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// scss-lint:disable SelectorDepth
|
||||
// scss-lint:disable NestingDepth
|
||||
|
||||
.atwho-view {
|
||||
background: $color_white;
|
||||
border-radius: $border-radius-default;
|
||||
|
@ -107,15 +110,49 @@
|
|||
|
||||
.item {
|
||||
cursor: pointer;
|
||||
margin-left: -.5em;
|
||||
line-height: 2.25em;
|
||||
overflow: hidden;
|
||||
padding: .25em .5em;
|
||||
padding: 0 .5em;
|
||||
position: relative;
|
||||
text-overflow: ellipsis;
|
||||
width: calc(100% + 1em);
|
||||
vertical-align: middle;
|
||||
white-space: nowrap;
|
||||
width: 100%;
|
||||
|
||||
.atwho-button-container {
|
||||
background: linear-gradient(90deg,
|
||||
transparent,
|
||||
$color-concrete 15%,
|
||||
$color-concrete 100%);
|
||||
display: inline;
|
||||
opacity: 0;
|
||||
padding-left: 2em;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
|
||||
.atwho-assign-button-form {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.atwho-insert-button,
|
||||
.atwho-assign-button {
|
||||
background: $color-concrete;
|
||||
color: $brand-primary;
|
||||
height: 2.25em;
|
||||
margin-right: .5em;
|
||||
padding: 0 .5em;
|
||||
text-align: center;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
&.cur {
|
||||
background: $color-concrete;
|
||||
color: $brand-primary;
|
||||
|
||||
.atwho-button-container {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.atwho-highlight {
|
||||
|
|
|
@ -40,7 +40,7 @@ class AtWhoController < ApplicationController
|
|||
end
|
||||
if repository && can_read_repository?(repository)
|
||||
items = SmartAnnotation.new(current_user, current_team, @query)
|
||||
.repository_rows(repository)
|
||||
.repository_rows(repository, params[:assignable_my_module_id])
|
||||
repository_id = repository.id
|
||||
else
|
||||
items = []
|
||||
|
@ -51,7 +51,7 @@ class AtWhoController < ApplicationController
|
|||
render json: {
|
||||
res: [
|
||||
render_to_string(partial: 'shared/smart_annotation/repository_items.html.erb',
|
||||
locals: { repository_rows: items })
|
||||
locals: { repository_rows: items, repository: repository })
|
||||
],
|
||||
repository: repository_id,
|
||||
team: current_team.id
|
||||
|
|
|
@ -9,8 +9,9 @@ class ExperimentsController < ApplicationController
|
|||
include Breadcrumbs
|
||||
|
||||
before_action :load_project, only: %i(new create archive_group restore_group)
|
||||
before_action :load_experiment, except: %i(new create archive_group restore_group actions_toolbar)
|
||||
before_action :check_read_permissions, except: %i(edit archive clone move new create archive_group restore_group actions_toolbar)
|
||||
before_action :load_experiment, except: %i(new create archive_group restore_group experiment_filter actions_toolbar)
|
||||
before_action :check_read_permissions, except: %i(edit archive clone move new create
|
||||
archive_group restore_group experiment_filter actions_toolbar)
|
||||
before_action :check_canvas_read_permissions, only: %i(canvas)
|
||||
before_action :check_create_permissions, only: %i(new create)
|
||||
before_action :check_manage_permissions, only: %i(edit batch_clone_my_modules)
|
||||
|
@ -433,6 +434,20 @@ class ExperimentsController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def experiment_filter
|
||||
project = Project.readable_by_user(current_user).find_by(id: params[:project_id])
|
||||
return render_404 if project.blank?
|
||||
|
||||
experiments = project.experiments
|
||||
.readable_by_user(current_user)
|
||||
.search(current_user, false, params[:query], 1, current_team)
|
||||
.pluck(:id, :name)
|
||||
|
||||
return render plain: [].to_json if experiments.blank?
|
||||
|
||||
render json: experiments
|
||||
end
|
||||
|
||||
def actions_dropdown
|
||||
if stale?([@experiment, @experiment.project])
|
||||
render json: {
|
||||
|
|
|
@ -4,11 +4,11 @@ class MyModuleRepositoriesController < ApplicationController
|
|||
include ApplicationHelper
|
||||
|
||||
before_action :load_my_module
|
||||
before_action :load_repository, except: %i(repositories_dropdown_list repositories_list_html)
|
||||
before_action :load_repository, except: %i(repositories_dropdown_list repositories_list_html create)
|
||||
before_action :check_my_module_view_permissions, except: %i(update consume_modal update_consumption)
|
||||
before_action :check_repository_view_permissions, except: %i(repositories_dropdown_list repositories_list_html)
|
||||
before_action :check_repository_view_permissions, except: %i(repositories_dropdown_list repositories_list_html create)
|
||||
before_action :check_repository_row_consumption_permissions, only: %i(consume_modal update_consumption)
|
||||
before_action :check_assign_repository_records_permissions, only: :update
|
||||
before_action :check_assign_repository_records_permissions, only: %i(update create)
|
||||
|
||||
def index_dt
|
||||
@draw = params[:draw].to_i
|
||||
|
@ -41,6 +41,34 @@ class MyModuleRepositoriesController < ApplicationController
|
|||
render rows_view
|
||||
end
|
||||
|
||||
def create
|
||||
repository_row = RepositoryRow.find(params[:repository_row_id])
|
||||
repository = repository_row.repository
|
||||
return render_403 unless can_read_repository?(repository)
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
@my_module.my_module_repository_rows.create!(repository_row: repository_row, assigned_by: current_user)
|
||||
|
||||
Activities::CreateActivityService.call(activity_type: :assign_repository_record,
|
||||
owner: current_user,
|
||||
team: @my_module.experiment.project.team,
|
||||
project: @my_module.experiment.project,
|
||||
subject: @my_module,
|
||||
message_items: { my_module: @my_module.id,
|
||||
repository: repository.id,
|
||||
record_names: repository_row.name })
|
||||
|
||||
render json: {
|
||||
flash: t('my_modules.assigned_items.direct_assign.success')
|
||||
}
|
||||
end
|
||||
rescue StandardError => e
|
||||
Rails.logger.error e.message
|
||||
render json: {
|
||||
flash: t('my_modules.repository.flash.update_error')
|
||||
}, status: :bad_request
|
||||
end
|
||||
|
||||
def update
|
||||
service = RepositoryRows::MyModuleAssignUnassignService.call(my_module: @my_module,
|
||||
repository: @repository,
|
||||
|
|
|
@ -8,14 +8,14 @@ class MyModulesController < ApplicationController
|
|||
include MyModulesHelper
|
||||
include Breadcrumbs
|
||||
|
||||
before_action :load_vars, except: %i(restore_group create new save_table_state actions_toolbar)
|
||||
before_action :load_vars, except: %i(restore_group create new save_table_state my_module_filter actions_toolbar)
|
||||
before_action :load_experiment, only: %i(create new)
|
||||
before_action :check_create_permissions, only: %i(new create)
|
||||
before_action :check_archive_permissions, only: %i(update)
|
||||
before_action :check_manage_permissions, only: %i(
|
||||
description due_date update_description update_protocol_description update_protocol
|
||||
)
|
||||
before_action :check_read_permissions, except: %i(create new update update_description
|
||||
before_action :check_read_permissions, except: %i(create new update update_description my_module_filter
|
||||
update_protocol_description restore_group
|
||||
save_table_state actions_toolbar)
|
||||
before_action :check_update_state_permissions, only: :update_state
|
||||
|
@ -456,6 +456,20 @@ class MyModulesController < ApplicationController
|
|||
render json: { provisioning_status: @my_module.provisioning_status }
|
||||
end
|
||||
|
||||
def my_module_filter
|
||||
experiment = Experiment.readable_by_user(current_user).find_by(id: params[:experiment_id])
|
||||
return render_404 if experiment.blank?
|
||||
|
||||
my_modules = experiment.my_modules
|
||||
.readable_by_user(current_user)
|
||||
.search(current_user, false, params[:query], 1, current_team)
|
||||
.pluck(:id, :name)
|
||||
|
||||
return render plain: [].to_json if my_modules.blank?
|
||||
|
||||
render json: my_modules
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_vars
|
||||
|
|
|
@ -17,7 +17,7 @@ class ProjectsController < ApplicationController
|
|||
sidebar experiments_cards view_type actions_dropdown create_tag)
|
||||
before_action :load_current_folder, only: %i(index cards new show)
|
||||
before_action :check_view_permissions, except: %i(index cards new create edit update archive_group restore_group
|
||||
users_filter actions_dropdown actions_toolbar)
|
||||
users_filter actions_dropdown project_filter actions_toolbar)
|
||||
before_action :check_create_permissions, only: %i(new create)
|
||||
before_action :check_manage_permissions, only: :edit
|
||||
before_action :load_exp_sort_var, only: :show
|
||||
|
@ -104,6 +104,16 @@ class ProjectsController < ApplicationController
|
|||
}
|
||||
end
|
||||
|
||||
def project_filter
|
||||
projects = Project.readable_by_user(current_user)
|
||||
.search(current_user, false, params[:query], 1, current_team)
|
||||
.pluck(:id, :name)
|
||||
|
||||
return render plain: [].to_json if projects.blank?
|
||||
|
||||
render json: projects
|
||||
end
|
||||
|
||||
def new
|
||||
@project = current_team.projects.new(project_folder: current_folder)
|
||||
respond_to do |format|
|
||||
|
|
|
@ -64,9 +64,19 @@ class RepositoryRowsController < ApplicationController
|
|||
|
||||
def show
|
||||
@repository_row = RepositoryRow.find_by(id: params[:id])
|
||||
@my_module = MyModule.find_by(id: params[:my_module_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)
|
||||
return render_403 if @my_module && !can_read_my_module?(@my_module)
|
||||
|
||||
if @my_module
|
||||
@my_module_assign_error = if !can_assign_my_module_repository_rows?(@my_module)
|
||||
I18n.t('repository_row.modal_info.assign_to_task_error.no_access')
|
||||
elsif @repository_row.my_modules.where(id: @my_module.id).any?
|
||||
I18n.t('repository_row.modal_info.assign_to_task_error.already_assigned')
|
||||
end
|
||||
end
|
||||
|
||||
@assigned_modules = @repository_row.my_modules.joins(experiment: :project)
|
||||
@viewable_modules = @assigned_modules.viewable_by_user(current_user, current_user.teams)
|
||||
|
|
2
app/javascript/packs/tiny_mce.js
vendored
2
app/javascript/packs/tiny_mce.js
vendored
|
@ -377,7 +377,7 @@ window.TinyMCE = (() => {
|
|||
editor.selection.select(editor.getBody(), true);
|
||||
editor.selection.collapse(false);
|
||||
|
||||
SmartAnnotation.init($(editor.contentDocument.activeElement));
|
||||
SmartAnnotation.init($(editor.contentDocument.activeElement), false, options.assignableMyModuleId);
|
||||
SmartAnnotation.preventPropagation('.atwho-user-popover');
|
||||
|
||||
if (options.afterInitCallback) { options.afterInitCallback(); }
|
||||
|
|
37
app/javascript/packs/vue/assign_items_to_task_modal.js
Normal file
37
app/javascript/packs/vue/assign_items_to_task_modal.js
Normal file
|
@ -0,0 +1,37 @@
|
|||
import TurbolinksAdapter from 'vue-turbolinks';
|
||||
import Vue from 'vue/dist/vue.esm';
|
||||
import AssignItemsToTaskModalContainer from '../../vue/assign_items_to_tasks_modal/container.vue';
|
||||
|
||||
Vue.use(TurbolinksAdapter);
|
||||
Vue.prototype.i18n = window.I18n;
|
||||
|
||||
function initAssignItemsToTaskModalComponent() {
|
||||
const container = $('.assign-items-to-task-modal-container');
|
||||
if (container.length) {
|
||||
window.AssignItemsToTaskModalComponentContainer = new Vue({
|
||||
el: '.assign-items-to-task-modal-container',
|
||||
name: 'AssignItemsToTaskModalComponent',
|
||||
components: {
|
||||
'assign-items-to-task-modal-container': AssignItemsToTaskModalContainer
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
visibility: false,
|
||||
urls: {
|
||||
assign: container.data('assign-url'),
|
||||
projects: container.data('projects-url'),
|
||||
experiments: container.data('experiments-url'),
|
||||
tasks: container.data('tasks-url')
|
||||
}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
closeModal() {
|
||||
this.visibility = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
initAssignItemsToTaskModalComponent();
|
290
app/javascript/vue/assign_items_to_tasks_modal/container.vue
Normal file
290
app/javascript/vue/assign_items_to_tasks_modal/container.vue
Normal file
|
@ -0,0 +1,290 @@
|
|||
<template>
|
||||
<div
|
||||
ref="modal"
|
||||
class="modal fade"
|
||||
id="assign-items-to-task-modal"
|
||||
tabindex="-1"
|
||||
role="dialog"
|
||||
aria-labelledby="assignItemsToTaskModalLabel"
|
||||
>
|
||||
<div class="modal-dialog modal-sm" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">
|
||||
{{ i18n.t("repositories.modal_assign_items_to_task.title") }}
|
||||
</h4>
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="description">
|
||||
{{
|
||||
i18n.t("repositories.modal_assign_items_to_task.body.description")
|
||||
}}
|
||||
</div>
|
||||
|
||||
<div class="project-selector level-selector">
|
||||
<label>
|
||||
{{
|
||||
i18n.t(
|
||||
"repositories.modal_assign_items_to_task.body.project_select.label"
|
||||
)
|
||||
}}
|
||||
</label>
|
||||
|
||||
<SelectSearch
|
||||
ref="projectsSelector"
|
||||
@change="changeProject"
|
||||
:options="projects"
|
||||
:placeholder="
|
||||
i18n.t(
|
||||
'repositories.modal_assign_items_to_task.body.project_select.placeholder'
|
||||
)
|
||||
"
|
||||
:searchPlaceholder="
|
||||
i18n.t(
|
||||
'repositories.modal_assign_items_to_task.body.project_select.placeholder'
|
||||
)
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="experiment-selector level-selector">
|
||||
<label>
|
||||
{{
|
||||
i18n.t(
|
||||
"repositories.modal_assign_items_to_task.body.experiment_select.label"
|
||||
)
|
||||
}}
|
||||
</label>
|
||||
|
||||
<SelectSearch
|
||||
:disabled="!selectedProject"
|
||||
ref="experimentsSelector"
|
||||
@change="changeExperiment"
|
||||
:options="experiments"
|
||||
:placeholder="experimentsSelectorPlaceholder"
|
||||
:searchPlaceholder="
|
||||
i18n.t(
|
||||
'repositories.modal_assign_items_to_task.body.experiment_select.placeholder'
|
||||
)
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="task-selector level-selector">
|
||||
<label>
|
||||
{{
|
||||
i18n.t(
|
||||
"repositories.modal_assign_items_to_task.body.task_select.label"
|
||||
)
|
||||
}}
|
||||
</label>
|
||||
|
||||
<SelectSearch
|
||||
:disabled="!selectedExperiment"
|
||||
ref="tasksSelector"
|
||||
@change="changeTask"
|
||||
:options="tasks"
|
||||
:placeholder="
|
||||
i18n.t(
|
||||
'repositories.modal_assign_items_to_task.body.task_select.disabled_placeholder'
|
||||
)
|
||||
"
|
||||
:searchPlaceholder="
|
||||
i18n.t(
|
||||
'repositories.modal_assign_items_to_task.body.task_select.placeholder'
|
||||
)
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
data-dismiss="modal"
|
||||
:disabled="!selectedTask"
|
||||
@click="assign"
|
||||
>
|
||||
{{ i18n.t("repositories.modal_assign_items_to_task.assign") }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SelectSearch from "../shared/select_search.vue";
|
||||
|
||||
export default {
|
||||
name: "AssignItemsToTaskModalContainer",
|
||||
props: {
|
||||
visibility: Boolean,
|
||||
urls: Object
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
rowsToAssign: [],
|
||||
projects: [],
|
||||
experiments: [],
|
||||
tasks: [],
|
||||
selectedProject: null,
|
||||
selectedExperiment: null,
|
||||
selectedTask: null,
|
||||
showCallback: null
|
||||
};
|
||||
},
|
||||
components: {
|
||||
SelectSearch
|
||||
},
|
||||
created() {
|
||||
window.AssignItemsToTaskModalComponent = this;
|
||||
},
|
||||
mounted() {
|
||||
$(this.$refs.modal).on("shown.bs.modal", () => {
|
||||
$.get(this.projectURL, data => {
|
||||
if (Array.isArray(data)) {
|
||||
this.projects = data;
|
||||
return false;
|
||||
}
|
||||
this.projects = [];
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
$(this.$refs.modal).on("hidden.bs.modal", () => {
|
||||
this.$emit("close");
|
||||
});
|
||||
},
|
||||
beforeDestroy() {
|
||||
delete window.AssignItemsToTaskModalComponent;
|
||||
},
|
||||
computed: {
|
||||
experimentsSelectorPlaceholder() {
|
||||
if (this.selectedProject) {
|
||||
return this.i18n.t(
|
||||
"repositories.modal_assign_items_to_task.body.experiment_select.placeholder"
|
||||
);
|
||||
}
|
||||
return this.i18n.t(
|
||||
"repositories.modal_assign_items_to_task.body.experiment_select.disabled_placeholder"
|
||||
);
|
||||
},
|
||||
tasksSelectorPlaceholder() {
|
||||
if (this.selectedExperiment) {
|
||||
return this.i18n.t(
|
||||
"repositories.modal_assign_items_to_task.body.task_select.placeholder"
|
||||
);
|
||||
}
|
||||
return this.i18n.t(
|
||||
"repositories.modal_assign_items_to_task.body.task_select.disabled_placeholder"
|
||||
);
|
||||
},
|
||||
projectURL() {
|
||||
return `${this.urls.projects}`;
|
||||
},
|
||||
experimentURL() {
|
||||
return `${this.urls.experiments}?project_id=${this.selectedProject ||
|
||||
""}`;
|
||||
},
|
||||
taskURL() {
|
||||
return `${this.urls.tasks}?experiment_id=${this.selectedExperiment ||
|
||||
""}`;
|
||||
},
|
||||
assignURL() {
|
||||
return this.urls.assign.replace(":module_id", this.selectedTask);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
visibility() {
|
||||
if (this.visibility) {
|
||||
this.showModal();
|
||||
} else {
|
||||
this.hideModal();
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
showModal() {
|
||||
$(this.$refs.modal).modal("show");
|
||||
|
||||
this.rowsToAssign = this.showCallback();
|
||||
},
|
||||
hideModal() {
|
||||
$(this.$refs.modal).modal("hide");
|
||||
},
|
||||
changeProject(value) {
|
||||
this.selectedProject = value;
|
||||
this.resetExperimentSelector();
|
||||
this.resetTaskSelector();
|
||||
|
||||
$.get(this.experimentURL, data => {
|
||||
if (Array.isArray(data)) {
|
||||
this.experiments = data;
|
||||
return false;
|
||||
}
|
||||
this.experiments = [];
|
||||
});
|
||||
},
|
||||
changeExperiment(value) {
|
||||
this.selectedExperiment = value;
|
||||
this.resetTaskSelector();
|
||||
|
||||
$.get(this.taskURL, data => {
|
||||
if (Array.isArray(data)) {
|
||||
this.tasks = data;
|
||||
return false;
|
||||
}
|
||||
this.tasks = [];
|
||||
});
|
||||
},
|
||||
changeTask(value) {
|
||||
this.selectedTask = value;
|
||||
},
|
||||
resetProjectSelector() {
|
||||
this.projects = [];
|
||||
this.selectedProject = null;
|
||||
},
|
||||
resetExperimentSelector() {
|
||||
this.experiments = [];
|
||||
this.selectedExperiment = null;
|
||||
},
|
||||
resetTaskSelector() {
|
||||
this.tasks = [];
|
||||
this.selectedTask = null;
|
||||
},
|
||||
resetSelectors() {
|
||||
this.resetTaskSelector();
|
||||
this.resetExperimentSelector();
|
||||
this.resetProjectSelector();
|
||||
},
|
||||
assign() {
|
||||
if (!this.selectedTask) return;
|
||||
|
||||
$.ajax({
|
||||
url: this.assignURL,
|
||||
type: "PATCH",
|
||||
dataType: "json",
|
||||
data: { rows_to_assign: this.rowsToAssign }
|
||||
}).always(() => {
|
||||
this.resetSelectors();
|
||||
this.deselectRows();
|
||||
});
|
||||
},
|
||||
setShowCallback(callback) {
|
||||
this.showCallback = callback;
|
||||
},
|
||||
deselectRows() {
|
||||
$('.repository-row-selector:checked').trigger('click');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -76,6 +76,7 @@
|
|||
:objectId="parseInt(protocol.id)"
|
||||
:fieldName="'protocol[description]'"
|
||||
:lastUpdated="protocol.attributes.updated_at"
|
||||
:assignableMyModuleId="protocol.attributes.assignable_my_module_id"
|
||||
:characterLimit="1000000"
|
||||
@update="updateDescription"
|
||||
/>
|
||||
|
@ -136,6 +137,7 @@
|
|||
@stepUpdated="refreshProtocolStatus"
|
||||
@step:insert="updateStepsPosition"
|
||||
:reorderStepUrl="steps.length > 1 ? urls.reorder_steps_url : null"
|
||||
:assignableMyModuleId="protocol.attributes.assignable_my_module_id"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -136,6 +136,7 @@
|
|||
:element.sync="elements[index]"
|
||||
:inRepository="inRepository"
|
||||
:reorderElementUrl="elements.length > 1 ? urls.reorder_elements_url : ''"
|
||||
:assignableMyModuleId="assignableMyModuleId"
|
||||
:isNew="element.isNew"
|
||||
@component:delete="deleteElement"
|
||||
@update="updateElement"
|
||||
|
@ -213,6 +214,10 @@
|
|||
},
|
||||
reorderStepUrl: {
|
||||
required: false
|
||||
},
|
||||
assignableMyModuleId: {
|
||||
type: Number,
|
||||
required: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
|
|
|
@ -104,6 +104,10 @@
|
|||
isNew: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
assignableMyModuleId: {
|
||||
type: Number,
|
||||
required: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
|
|
|
@ -83,6 +83,10 @@
|
|||
},
|
||||
isNew: {
|
||||
type: Boolean, default: false
|
||||
},
|
||||
assignableMyModuleId: {
|
||||
type: Number,
|
||||
required: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
:objectId="element.attributes.orderable.id"
|
||||
:fieldName="'step_text[text]'"
|
||||
:lastUpdated="element.attributes.orderable.updated_at"
|
||||
:assignableMyModuleId="assignableMyModuleId"
|
||||
:characterLimit="1000000"
|
||||
@update="update"
|
||||
@editingDisabled="disableEditMode"
|
||||
|
@ -64,6 +65,10 @@
|
|||
isNew: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
assignableMyModuleId: {
|
||||
type: Number,
|
||||
required: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
|
|
|
@ -144,7 +144,7 @@
|
|||
this.$refs.input.select();
|
||||
}
|
||||
if (this.smartAnnotation) {
|
||||
SmartAnnotation.init($(this.$refs.input));
|
||||
SmartAnnotation.init($(this.$refs.input), false);
|
||||
}
|
||||
})
|
||||
this.$emit('editingEnabled');
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
setTimeout(() => {
|
||||
this.isOpen = false;
|
||||
this.$emit('blur');
|
||||
}, 100)
|
||||
}, 200)
|
||||
},
|
||||
toggle() {
|
||||
this.isOpen = !this.isOpen;
|
||||
|
@ -70,10 +70,19 @@
|
|||
this.$emit('change', this.value);
|
||||
},
|
||||
updateOptionPosition() {
|
||||
let rect = this.$refs.container.getBoundingClientRect();
|
||||
let top =rect.top + rect.height;
|
||||
let left = rect.left;
|
||||
const container = this.$refs.container;
|
||||
const rect = container.getBoundingClientRect();
|
||||
let width = rect.width;
|
||||
let top = rect.top + rect.height;
|
||||
let left = rect.left;
|
||||
|
||||
const modal = $(container).parents('.modal-content');
|
||||
|
||||
if (modal.length > 0) {
|
||||
const modalRect = modal.get(0).getBoundingClientRect();
|
||||
top -= modalRect.top;
|
||||
left -= modalRect.left;
|
||||
}
|
||||
|
||||
this.optionPositionStyle = `position: fixed; top: ${top}px; left: ${left}px; width: ${width}px`
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<Select class="sn-select--search" :options="currentOptions" :placeholder="placeholder" @change="change" @blur="blur" @open="open" @close="close">
|
||||
<Select class="sn-select--search" :options="currentOptions" :placeholder="placeholder" v-bind:disabled="disabled" @change="change" @blur="blur" @open="open" @close="close">
|
||||
<input ref="focusElement" v-model="query" type="text" class="sn-select__search-input" :placeholder="searchPlaceholder" />
|
||||
<span class="sn-select__value">{{ valueLabel || (placeholder || i18n.t('general.select')) }}</span>
|
||||
<span class="sn-select__caret caret"></span>
|
||||
|
@ -15,7 +15,8 @@
|
|||
options: { type: Array, default: () => [] },
|
||||
optionsUrl: { type: String },
|
||||
placeholder: { type: String },
|
||||
searchPlaceholder: { type: String }
|
||||
searchPlaceholder: { type: String },
|
||||
disabled: { type: Boolean }
|
||||
},
|
||||
components: { Select },
|
||||
data() {
|
||||
|
@ -41,20 +42,25 @@
|
|||
} else {
|
||||
this.currentOptions = this.options.filter((o) => o[1].toLowerCase().includes(this.query.toLowerCase()));
|
||||
}
|
||||
},
|
||||
options() {
|
||||
this.currentOptions = this.options;
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
valueLabel() {
|
||||
let option = this.options.find((o) => o[0] === this.value);
|
||||
let option = this.currentOptions.find((o) => o[0] === this.value);
|
||||
return option && option[1];
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
blur() {
|
||||
this.isOpen = false;
|
||||
this.$emit('blur');
|
||||
},
|
||||
change(value) {
|
||||
this.value = value;
|
||||
this.isOpen = false;
|
||||
this.$emit('change', this.value);
|
||||
},
|
||||
open() {
|
||||
|
@ -66,7 +72,7 @@
|
|||
this.$emit('close');
|
||||
},
|
||||
fetchOptions() {
|
||||
$.get(`${this.optionsUrl}?query=${this.query}`,
|
||||
$.get(`${this.optionsUrl}?query=${this.query || ''}`,
|
||||
(data) => {
|
||||
this.currentOptions = data;
|
||||
}
|
||||
|
|
|
@ -68,6 +68,7 @@
|
|||
fieldName: String,
|
||||
lastUpdated: Number,
|
||||
inEditMode: Boolean,
|
||||
assignableMyModuleId: Number,
|
||||
characterLimit: {
|
||||
type: Number,
|
||||
default: null
|
||||
|
@ -141,7 +142,8 @@
|
|||
this.initCharacterCount();
|
||||
this.$emit('editingEnabled');
|
||||
},
|
||||
placeholder: this.placeholder
|
||||
placeholder: this.placeholder,
|
||||
assignableMyModuleId: this.assignableMyModuleId
|
||||
}
|
||||
)
|
||||
},
|
||||
|
|
|
@ -10,7 +10,7 @@ class ProtocolSerializer < ActiveModel::Serializer
|
|||
attributes :name, :id, :urls, :description, :description_view, :updated_at, :in_repository,
|
||||
:created_at_formatted, :updated_at_formatted, :added_by, :authors, :keywords, :version,
|
||||
:code, :published, :version_comment, :archived, :linked, :has_draft,
|
||||
:published_on_formatted, :published_by, :created_from_version
|
||||
:published_on_formatted, :published_by, :created_from_version, :assignable_my_module_id
|
||||
|
||||
def updated_at
|
||||
object.updated_at.to_i
|
||||
|
@ -116,6 +116,12 @@ class ProtocolSerializer < ActiveModel::Serializer
|
|||
object.linked?
|
||||
end
|
||||
|
||||
def assignable_my_module_id
|
||||
return if in_repository
|
||||
|
||||
object.my_module&.id
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_from_repo_url
|
||||
|
|
|
@ -35,19 +35,33 @@ class SmartAnnotation
|
|||
.limit(Constants::ATWHO_SEARCH_LIMIT + 1)
|
||||
end
|
||||
|
||||
def repository_rows(repository)
|
||||
def repository_rows(repository, my_module_id)
|
||||
res = RepositoryRow
|
||||
.active
|
||||
.where(repository: repository)
|
||||
.search_by_name_and_id(@current_user, @current_team, @query)
|
||||
.limit(Constants::ATWHO_SEARCH_LIMIT + 1)
|
||||
|
||||
if my_module_id.present?
|
||||
res = res.joins('LEFT OUTER JOIN "my_module_repository_rows" "current_my_module_repository_rows"'\
|
||||
'ON "current_my_module_repository_rows"."repository_row_id" = "repository_rows"."id" '\
|
||||
'AND "current_my_module_repository_rows"."my_module_id" = ' + my_module_id.to_s)
|
||||
.select('repository_rows.*',
|
||||
'CASE WHEN current_my_module_repository_rows.id IS NOT NULL '\
|
||||
'THEN true ELSE false END as row_assigned')
|
||||
end
|
||||
rep_items_list = []
|
||||
|
||||
res.each do |rep_row|
|
||||
rep_item = {}
|
||||
rep_item[:id] = rep_row.id.base62_encode
|
||||
rep_item[:id] = rep_row.id
|
||||
rep_item[:id_encoded] = rep_row.id.base62_encode
|
||||
rep_item[:name] = escape_input(rep_row.name)
|
||||
rep_item[:code] = escape_input(rep_row.code)
|
||||
if my_module_id.present?
|
||||
rep_item[:row_assigned] = rep_row&.row_assigned
|
||||
rep_item[:my_module_id] = my_module_id
|
||||
end
|
||||
rep_items_list << rep_item
|
||||
end
|
||||
rep_items_list
|
||||
|
|
15
app/views/repositories/_assign_items_to_task_modal.html.erb
Normal file
15
app/views/repositories/_assign_items_to_task_modal.html.erb
Normal file
|
@ -0,0 +1,15 @@
|
|||
<div
|
||||
class="assign-items-to-task-modal-container"
|
||||
data-assign-url="<%= my_module_repository_path(":module_id") %>"
|
||||
data-projects-url="<%= project_filter_projects_path %>"
|
||||
data-experiments-url="<%= experiment_filter_experiments_path %>"
|
||||
data-tasks-url="<%= module_filter_my_modules_path %>"
|
||||
>
|
||||
<assign-items-to-task-modal-container
|
||||
:visibility="visibility"
|
||||
:urls="urls"
|
||||
@close="closeModal"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<%= javascript_include_tag 'vue_repository_assign_items_to_task_modal' %>
|
|
@ -111,10 +111,27 @@
|
|||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal"><%= t('general.close')%></button>
|
||||
<button type="button" class="btn btn-primary print-label-button" data-rows="[<%= @repository_row.id %>]"><%= t('repository_row.modal_print_label.print_label') %></button>
|
||||
|
||||
<div class="modal-footer" data-assign-item-button="<%= @my_module.present? %>">
|
||||
<% if @my_module %>
|
||||
<button type="button" class="btn btn-secondary print-label-button" data-rows="[<%= @repository_row.id %>]"><%= t('repository_row.modal_print_label.print_label') %></button>
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal"><%= t('general.close')%></button>
|
||||
<span <% if @my_module_assign_error.present? %>
|
||||
data-toggle="tooltip"
|
||||
data-placement="bottom"
|
||||
title="<%= @my_module_assign_error %>"
|
||||
<% end %>
|
||||
>
|
||||
<button type="button" class="btn btn-primary assign-inventory-button"
|
||||
data-assign-url=<%= my_module_repositories_path(@my_module) %>
|
||||
data-repository-row-id=<%= @repository_row.id %>
|
||||
<%= 'disabled' if @my_module_assign_error.present? %>>
|
||||
<%= t('repository_row.modal_info.assign_to_task') %>
|
||||
</button>
|
||||
</span>
|
||||
<% else %>
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal"><%= t('general.close')%></button>
|
||||
<button type="button" class="btn btn-primary print-label-button" data-rows="[<%= @repository_row.id %>]"><%= t('repository_row.modal_print_label.print_label') %></button>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -84,6 +84,7 @@
|
|||
<%= render partial: 'repository_columns/manage_column_modal', locals: { my_module_page: false } %>
|
||||
<%= render partial: "repository_stock_values/manage_modal" %>
|
||||
<%= render partial: "toolbar_buttons" %>
|
||||
<%= render partial: "assign_items_to_task_modal" %>
|
||||
|
||||
<% if @repository.is_a?(BmtRepository) %>
|
||||
<%= render partial: 'save_bmt_filter_modal' %>
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
autocomplete: 'off',
|
||||
data: { object_type: 'result_text',
|
||||
object_id: @result.result_text.id,
|
||||
my_module_id: @result.my_module_id,
|
||||
last_updated: @result.updated_at.to_i * 1000 }) %>
|
||||
<% end %><br />
|
||||
<div class="align-right edit-result-texts-buttons'">
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
autocomplete: 'off',
|
||||
data: { object_type: 'result_text',
|
||||
object_id: @result.result_text.id,
|
||||
my_module_id: @result.my_module_id,
|
||||
last_updated: @result.updated_at.to_i * 1000 }) %>
|
||||
<% end %><br />
|
||||
<div class="align-right new-result-texts-buttons'">
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
<div class="atwho-button-container">
|
||||
<button type="button" class="btn icon-btn btn-light atwho-insert-button"><%= I18n.t("atwho.buttons.insert") %></button>
|
||||
<% if defined?(row) && !row[:row_assigned] && row[:my_module_id].present? %>
|
||||
<button type="button"
|
||||
class="btn icon-btn btn-light atwho-assign-button"
|
||||
data-assign-url= <%= my_module_repositories_path(row[:my_module_id]) %>
|
||||
data-repository-id=<%= repository[:id] %>
|
||||
data-repository-row-id=<%= row[:id] %>>
|
||||
<%= I18n.t("atwho.buttons.assign") %>
|
||||
</button>
|
||||
<%end%>
|
||||
</div>
|
|
@ -11,6 +11,7 @@
|
|||
<span class='sa-type'><%= experiment.code %></span>
|
||||
<span class="dot">·</span>
|
||||
<span class="item-text"><%= experiment.name %></span>
|
||||
<%= render partial: 'shared/smart_annotation/atwho_control_buttons.html.erb' %>
|
||||
</li>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
<span class='sa-type'><%= task.code %></span>
|
||||
<span class="dot">·</span>
|
||||
<span class="item-text"><%= task.name %></span>
|
||||
<%= render partial: 'shared/smart_annotation/atwho_control_buttons.html.erb' %>
|
||||
</li>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
<span class='sa-type'><%= project.code %></span>
|
||||
<span class="dot">·</span>
|
||||
<span class="item-text"><%= project.name %></span>
|
||||
<%= render partial: 'shared/smart_annotation/atwho_control_buttons.html.erb' %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if limit_reached %>
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
<% limit_reached = repository_rows.length == Constants::ATWHO_SEARCH_LIMIT + 1 %>
|
||||
<div class="atwho-scroll-container">
|
||||
<% repository_rows.take(Constants::ATWHO_SEARCH_LIMIT).each do |row| %>
|
||||
<li class="item" data-name="<%= row[:name] %>" data-id="<%= row[:id] %>" data-type="rep_item">
|
||||
<li class="item" data-name="<%= row[:name] %>" data-id="<%= row[:id_encoded] %>" data-type="rep_item">
|
||||
<span class='sa-type'><%= row[:code] %></span>
|
||||
<span class="dot">·</span>
|
||||
<span class="item-text"><%= row[:name] %></span>
|
||||
<%= render partial: 'shared/smart_annotation/atwho_control_buttons.html.erb', locals: { row: row, repository: repository } %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if limit_reached %>
|
||||
|
|
|
@ -1041,6 +1041,8 @@ en:
|
|||
assigned_items:
|
||||
title: "Assigned items"
|
||||
assign_from: "Assign from"
|
||||
direct_assign:
|
||||
success: "Successfully assigned an item to the task."
|
||||
protocol:
|
||||
title: "Protocol"
|
||||
options_dropdown:
|
||||
|
@ -1974,6 +1976,22 @@ en:
|
|||
columns_delete: "Delete"
|
||||
columns_changed: "Someone removed/added a new column to the inventory in use. To prevent data inconsistency we will reload this page for you."
|
||||
columns_visibility: "Visible columns"
|
||||
modal_assign_items_to_task:
|
||||
title: "Assign to task"
|
||||
body:
|
||||
description: "Type in the fields below to find the right task."
|
||||
project_select:
|
||||
label: "Project"
|
||||
placeholder: "Enter project name"
|
||||
experiment_select:
|
||||
label: "Experiment"
|
||||
placeholder: "Enter Experiment name"
|
||||
disabled_placeholder: "Select Project to enable Experiment"
|
||||
task_select:
|
||||
label: "Task"
|
||||
placeholder: "Enter Task name"
|
||||
disabled_placeholder: "Select Experiment to enable Task"
|
||||
assign: "Assign to this task"
|
||||
modal_delete_record:
|
||||
title: "Delete items"
|
||||
notice: "Are you sure you want to delete the selected item(s)?"
|
||||
|
@ -2209,6 +2227,10 @@ en:
|
|||
no_tasks: "This item in not assigned to any task."
|
||||
amount: "Amount: %{value}"
|
||||
unit: "Unit: %{unit}"
|
||||
assign_to_task: "Assign to this task"
|
||||
assign_to_task_error:
|
||||
no_access: "You can only view this task"
|
||||
already_assigned: "This item is already assigned to this task"
|
||||
modal_print_label:
|
||||
head_title: "Print label - %{repository_row}"
|
||||
head_title_multiple: "Print label - %{repository_rows} rows"
|
||||
|
@ -3198,6 +3220,9 @@ en:
|
|||
repository_rows: "Items with this name/ID were not found"
|
||||
users: "Users with this name were not found"
|
||||
description: "Please make sure there are no typos, or erase letters one by one unless you see some results"
|
||||
buttons:
|
||||
insert: "Insert"
|
||||
assign: "Assign to this task"
|
||||
projects: PROJECTS
|
||||
experiments: EXPERIMENTS
|
||||
tasks: TASKS
|
||||
|
@ -3206,7 +3231,7 @@ en:
|
|||
users:
|
||||
title: "People"
|
||||
header: "Type the name or email of the user you want to mention (they will be notified)"
|
||||
help: "Navigate: ↑ ↓ • Submit: Enter / Tab • Dismiss: Esc"
|
||||
help: "Navigate: ↑ ↓ • Insert: Enter / Tab • Dismiss: Esc"
|
||||
popover_html: "<span class='silver'>Team:</span> %{team} <br> <span class='silver'>Role:</span> %{role} <br> <span class='silver'>Joined:</span> %{time}"
|
||||
res:
|
||||
archived: "(archived)"
|
||||
|
|
|
@ -344,8 +344,8 @@ Rails.application.routes.draw do
|
|||
end
|
||||
resources :experiments, only: %i(new create), defaults: { format: 'json' } do
|
||||
collection do
|
||||
post 'archive_group' # archive group of experements
|
||||
post 'restore_group' # restore group of experementss
|
||||
post 'archive_group' # archive group of experiments
|
||||
post 'restore_group' # restore group of experiments
|
||||
end
|
||||
end
|
||||
member do
|
||||
|
@ -359,6 +359,7 @@ Rails.application.routes.draw do
|
|||
end
|
||||
|
||||
collection do
|
||||
get 'project_filter'
|
||||
get 'cards', to: 'projects#cards'
|
||||
get 'users_filter'
|
||||
post 'archive_group'
|
||||
|
@ -382,6 +383,7 @@ Rails.application.routes.draw do
|
|||
|
||||
resources :experiments, only: %i(show edit update) do
|
||||
collection do
|
||||
get 'experiment_filter'
|
||||
get 'edit', action: :edit
|
||||
get 'clone_modal', action: :clone_modal
|
||||
get 'move_modal', action: :move_modal
|
||||
|
@ -411,7 +413,7 @@ Rails.application.routes.draw do
|
|||
post 'clone' # clone experiment
|
||||
get 'move_modal' # return modal with move options
|
||||
post 'move' # move experiment
|
||||
get 'fetch_workflow_img' # Get udated workflow img
|
||||
get 'fetch_workflow_img' # Get updated workflow img
|
||||
get 'modules/new', to: 'my_modules#new'
|
||||
post 'modules', to: 'my_modules#create'
|
||||
post 'restore_my_modules', to: 'my_modules#restore_group'
|
||||
|
@ -427,6 +429,7 @@ Rails.application.routes.draw do
|
|||
# as well as 'module info' page for single module (HTML)
|
||||
resources :my_modules, path: '/modules', only: [:show, :update] do
|
||||
post 'save_table_state', on: :collection, defaults: { format: 'json' }
|
||||
get 'module_filter', to: 'my_modules#my_module_filter', on: :collection, defaults: { format: 'json' }
|
||||
|
||||
collection do
|
||||
get 'actions_toolbar'
|
||||
|
@ -463,7 +466,7 @@ Rails.application.routes.draw do
|
|||
get :repositories_dropdown_list, controller: :my_module_repositories
|
||||
get :repositories_list_html, controller: :my_module_repositories
|
||||
|
||||
resources :repositories, controller: :my_module_repositories, only: :update do
|
||||
resources :repositories, controller: :my_module_repositories, only: %i(update create) do
|
||||
member do
|
||||
get :full_view_table
|
||||
post :index_dt
|
||||
|
|
|
@ -32,6 +32,7 @@ const entryList = {
|
|||
vue_repository_filter: './app/javascript/packs/vue/repository_filter.js',
|
||||
vue_repository_search: './app/javascript/packs/vue/repository_search.js',
|
||||
vue_repository_print_modal: './app/javascript/packs/vue/repository_print_modal.js',
|
||||
vue_repository_assign_items_to_task_modal: './app/javascript/packs/vue/assign_items_to_task_modal.js',
|
||||
vue_navigation_top_menu: './app/javascript/packs/vue/navigation/top_menu.js',
|
||||
vue_navigation_navigator: './app/javascript/packs/vue/navigation/navigator.js',
|
||||
vue_components_action_toolbar: './app/javascript/packs/vue/action_toolbar.js'
|
||||
|
|
Loading…
Add table
Reference in a new issue