mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2024-09-20 06:35:56 +08:00
Merge branch 'develop' into features/step-editing-improvements
This commit is contained in:
commit
9abbe22c26
|
@ -1,4 +1,4 @@
|
|||
FROM ruby:2.7.5-bullseye
|
||||
FROM ruby:2.7.6-bullseye
|
||||
MAINTAINER BioSistemika <info@biosistemika.com>
|
||||
|
||||
ARG WKHTMLTOPDF_PACKAGE_URL=https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.buster_amd64.deb
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
FROM ruby:2.7.5-bullseye
|
||||
FROM ruby:2.7.6-bullseye
|
||||
MAINTAINER BioSistemika <info@biosistemika.com>
|
||||
|
||||
ARG WKHTMLTOPDF_PACKAGE_URL=https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.buster_amd64.deb
|
||||
|
|
6
Gemfile
6
Gemfile
|
@ -2,7 +2,7 @@
|
|||
|
||||
source 'http://rubygems.org'
|
||||
|
||||
ruby '2.7.5'
|
||||
ruby '2.7.6'
|
||||
|
||||
gem 'bootsnap', require: false
|
||||
gem 'bootstrap-sass', '~> 3.4.1'
|
||||
|
@ -12,7 +12,7 @@ gem 'devise_invitable'
|
|||
gem 'figaro'
|
||||
gem 'pg', '~> 1.1'
|
||||
gem 'pg_search' # PostgreSQL full text search
|
||||
gem 'rails', '~> 6.1.4'
|
||||
gem 'rails', '~> 6.1.5'
|
||||
gem 'psych', '< 4.0'
|
||||
gem 'view_component', require: 'view_component/engine'
|
||||
gem 'recaptcha', require: 'recaptcha/rails'
|
||||
|
@ -73,7 +73,7 @@ gem 'i18n-js', '~> 3.6' # Localization in javascript files
|
|||
gem 'jbuilder' # JSON structures via a Builder-style DSL
|
||||
gem 'logging', '~> 2.0.0'
|
||||
gem 'nested_form_fields'
|
||||
gem 'nokogiri', '~> 1.13.4' # HTML/XML parser
|
||||
gem 'nokogiri', '~> 1.13.6' # HTML/XML parser
|
||||
gem 'rails_autolink', '~> 1.1', '>= 1.1.6'
|
||||
gem 'rgl' # Graph framework for project diagram calculations
|
||||
gem 'roo', '~> 2.8.2' # Spreadsheet parser
|
||||
|
|
124
Gemfile.lock
124
Gemfile.lock
|
@ -42,40 +42,40 @@ GIT
|
|||
GEM
|
||||
remote: http://rubygems.org/
|
||||
specs:
|
||||
actioncable (6.1.4.7)
|
||||
actionpack (= 6.1.4.7)
|
||||
activesupport (= 6.1.4.7)
|
||||
actioncable (6.1.5.1)
|
||||
actionpack (= 6.1.5.1)
|
||||
activesupport (= 6.1.5.1)
|
||||
nio4r (~> 2.0)
|
||||
websocket-driver (>= 0.6.1)
|
||||
actionmailbox (6.1.4.7)
|
||||
actionpack (= 6.1.4.7)
|
||||
activejob (= 6.1.4.7)
|
||||
activerecord (= 6.1.4.7)
|
||||
activestorage (= 6.1.4.7)
|
||||
activesupport (= 6.1.4.7)
|
||||
actionmailbox (6.1.5.1)
|
||||
actionpack (= 6.1.5.1)
|
||||
activejob (= 6.1.5.1)
|
||||
activerecord (= 6.1.5.1)
|
||||
activestorage (= 6.1.5.1)
|
||||
activesupport (= 6.1.5.1)
|
||||
mail (>= 2.7.1)
|
||||
actionmailer (6.1.4.7)
|
||||
actionpack (= 6.1.4.7)
|
||||
actionview (= 6.1.4.7)
|
||||
activejob (= 6.1.4.7)
|
||||
activesupport (= 6.1.4.7)
|
||||
actionmailer (6.1.5.1)
|
||||
actionpack (= 6.1.5.1)
|
||||
actionview (= 6.1.5.1)
|
||||
activejob (= 6.1.5.1)
|
||||
activesupport (= 6.1.5.1)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
rails-dom-testing (~> 2.0)
|
||||
actionpack (6.1.4.7)
|
||||
actionview (= 6.1.4.7)
|
||||
activesupport (= 6.1.4.7)
|
||||
actionpack (6.1.5.1)
|
||||
actionview (= 6.1.5.1)
|
||||
activesupport (= 6.1.5.1)
|
||||
rack (~> 2.0, >= 2.0.9)
|
||||
rack-test (>= 0.6.3)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
||||
actiontext (6.1.4.7)
|
||||
actionpack (= 6.1.4.7)
|
||||
activerecord (= 6.1.4.7)
|
||||
activestorage (= 6.1.4.7)
|
||||
activesupport (= 6.1.4.7)
|
||||
actiontext (6.1.5.1)
|
||||
actionpack (= 6.1.5.1)
|
||||
activerecord (= 6.1.5.1)
|
||||
activestorage (= 6.1.5.1)
|
||||
activesupport (= 6.1.5.1)
|
||||
nokogiri (>= 1.8.5)
|
||||
actionview (6.1.4.7)
|
||||
activesupport (= 6.1.4.7)
|
||||
actionview (6.1.5.1)
|
||||
activesupport (= 6.1.5.1)
|
||||
builder (~> 3.1)
|
||||
erubi (~> 1.4)
|
||||
rails-dom-testing (~> 2.0)
|
||||
|
@ -85,24 +85,24 @@ GEM
|
|||
activemodel (>= 4.1, < 6.2)
|
||||
case_transform (>= 0.2)
|
||||
jsonapi-renderer (>= 0.1.1.beta1, < 0.3)
|
||||
activejob (6.1.4.7)
|
||||
activesupport (= 6.1.4.7)
|
||||
activejob (6.1.5.1)
|
||||
activesupport (= 6.1.5.1)
|
||||
globalid (>= 0.3.6)
|
||||
activemodel (6.1.4.7)
|
||||
activesupport (= 6.1.4.7)
|
||||
activerecord (6.1.4.7)
|
||||
activemodel (= 6.1.4.7)
|
||||
activesupport (= 6.1.4.7)
|
||||
activemodel (6.1.5.1)
|
||||
activesupport (= 6.1.5.1)
|
||||
activerecord (6.1.5.1)
|
||||
activemodel (= 6.1.5.1)
|
||||
activesupport (= 6.1.5.1)
|
||||
activerecord-import (1.0.7)
|
||||
activerecord (>= 3.2)
|
||||
activestorage (6.1.4.7)
|
||||
actionpack (= 6.1.4.7)
|
||||
activejob (= 6.1.4.7)
|
||||
activerecord (= 6.1.4.7)
|
||||
activesupport (= 6.1.4.7)
|
||||
marcel (~> 1.0.0)
|
||||
activestorage (6.1.5.1)
|
||||
actionpack (= 6.1.5.1)
|
||||
activejob (= 6.1.5.1)
|
||||
activerecord (= 6.1.5.1)
|
||||
activesupport (= 6.1.5.1)
|
||||
marcel (~> 1.0)
|
||||
mini_mime (>= 1.1.0)
|
||||
activesupport (6.1.4.7)
|
||||
activesupport (6.1.5.1)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 1.6, < 2)
|
||||
minitest (>= 5.1)
|
||||
|
@ -210,7 +210,7 @@ GEM
|
|||
coffee-script-source
|
||||
execjs
|
||||
coffee-script-source (1.12.2)
|
||||
concurrent-ruby (1.1.9)
|
||||
concurrent-ruby (1.1.10)
|
||||
crack (0.4.5)
|
||||
rexml
|
||||
crass (1.0.6)
|
||||
|
@ -354,7 +354,7 @@ GEM
|
|||
logging (2.0.0)
|
||||
little-plugger (~> 1.1)
|
||||
multi_json (~> 1.10)
|
||||
loofah (2.14.0)
|
||||
loofah (2.16.0)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.5.9)
|
||||
mail (2.7.1)
|
||||
|
@ -381,7 +381,7 @@ GEM
|
|||
rails (>= 3.2.0)
|
||||
newrelic_rpm (6.15.0)
|
||||
nio4r (2.5.8)
|
||||
nokogiri (1.13.4)
|
||||
nokogiri (1.13.6)
|
||||
mini_portile2 (~> 2.8.0)
|
||||
racc (~> 1.4)
|
||||
nokogumbo (2.0.4)
|
||||
|
@ -441,7 +441,7 @@ GEM
|
|||
nio4r (~> 2.0)
|
||||
raabro (1.4.0)
|
||||
racc (1.6.0)
|
||||
rack (2.2.3)
|
||||
rack (2.2.3.1)
|
||||
rack-attack (6.4.0)
|
||||
rack (>= 1.0, < 3)
|
||||
rack-cors (1.1.1)
|
||||
|
@ -450,20 +450,20 @@ GEM
|
|||
rack
|
||||
rack-test (1.1.0)
|
||||
rack (>= 1.0, < 3)
|
||||
rails (6.1.4.7)
|
||||
actioncable (= 6.1.4.7)
|
||||
actionmailbox (= 6.1.4.7)
|
||||
actionmailer (= 6.1.4.7)
|
||||
actionpack (= 6.1.4.7)
|
||||
actiontext (= 6.1.4.7)
|
||||
actionview (= 6.1.4.7)
|
||||
activejob (= 6.1.4.7)
|
||||
activemodel (= 6.1.4.7)
|
||||
activerecord (= 6.1.4.7)
|
||||
activestorage (= 6.1.4.7)
|
||||
activesupport (= 6.1.4.7)
|
||||
rails (6.1.5.1)
|
||||
actioncable (= 6.1.5.1)
|
||||
actionmailbox (= 6.1.5.1)
|
||||
actionmailer (= 6.1.5.1)
|
||||
actionpack (= 6.1.5.1)
|
||||
actiontext (= 6.1.5.1)
|
||||
actionview (= 6.1.5.1)
|
||||
activejob (= 6.1.5.1)
|
||||
activemodel (= 6.1.5.1)
|
||||
activerecord (= 6.1.5.1)
|
||||
activestorage (= 6.1.5.1)
|
||||
activesupport (= 6.1.5.1)
|
||||
bundler (>= 1.15.0)
|
||||
railties (= 6.1.4.7)
|
||||
railties (= 6.1.5.1)
|
||||
sprockets-rails (>= 2.0.0)
|
||||
rails-controller-testing (1.0.5)
|
||||
actionpack (>= 5.0.1.rc1)
|
||||
|
@ -481,11 +481,11 @@ GEM
|
|||
rails (> 3.1)
|
||||
rails_serve_static_assets (0.0.5)
|
||||
rails_stdout_logging (0.0.5)
|
||||
railties (6.1.4.7)
|
||||
actionpack (= 6.1.4.7)
|
||||
activesupport (= 6.1.4.7)
|
||||
railties (6.1.5.1)
|
||||
actionpack (= 6.1.5.1)
|
||||
activesupport (= 6.1.5.1)
|
||||
method_source
|
||||
rake (>= 0.13)
|
||||
rake (>= 12.2)
|
||||
thor (~> 1.0)
|
||||
rainbow (3.0.0)
|
||||
rake (13.0.6)
|
||||
|
@ -688,7 +688,7 @@ DEPENDENCIES
|
|||
momentjs-rails (~> 2.17.1)
|
||||
nested_form_fields
|
||||
newrelic_rpm
|
||||
nokogiri (~> 1.13.4)
|
||||
nokogiri (~> 1.13.6)
|
||||
omniauth
|
||||
omniauth-azure-activedirectory
|
||||
omniauth-linkedin-oauth2
|
||||
|
@ -704,7 +704,7 @@ DEPENDENCIES
|
|||
puma
|
||||
rack-attack
|
||||
rack-cors
|
||||
rails (~> 6.1.4)
|
||||
rails (~> 6.1.5)
|
||||
rails-controller-testing
|
||||
rails_12factor
|
||||
rails_autolink (~> 1.1, >= 1.1.6)
|
||||
|
@ -744,7 +744,7 @@ DEPENDENCIES
|
|||
yomu!
|
||||
|
||||
RUBY VERSION
|
||||
ruby 2.7.5p203
|
||||
ruby 2.7.6p219
|
||||
|
||||
BUNDLED WITH
|
||||
2.1.4
|
||||
|
|
|
@ -283,7 +283,7 @@
|
|||
function initTagsSelector() {
|
||||
var myModuleTagsSelector = '#module-tags-selector';
|
||||
|
||||
dropdownSelector.init(myModuleTagsSelector, {
|
||||
dropdownSelector.init($(myModuleTagsSelector), {
|
||||
closeOnSelect: true,
|
||||
tagClass: 'my-module-white-tags',
|
||||
tagStyle: (data) => {
|
||||
|
|
|
@ -54,14 +54,16 @@ var MyModuleRepositories = (function() {
|
|||
return columns;
|
||||
}
|
||||
|
||||
function reloadRepositoriesList(repositoryId) {
|
||||
function reloadRepositoriesList(repositoryId, expand = false) {
|
||||
var repositoriesContainer = $('#assigned-items-container');
|
||||
$.get(repositoriesContainer.data('repositories-list-url'), function(result) {
|
||||
repositoriesContainer.html(result.html);
|
||||
$('.assigned-items-title').attr('data-assigned-items-count', result.assigned_rows_count);
|
||||
// expand recently updated repository
|
||||
$('#assigned-items-container').collapse('show');
|
||||
$('#assigned-repository-items-container-' + repositoryId).collapse('show');
|
||||
if (expand) {
|
||||
$('#assigned-items-container').collapse('show');
|
||||
$('#assigned-repository-items-container-' + repositoryId).collapse('show');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -566,6 +568,7 @@ var MyModuleRepositories = (function() {
|
|||
versionsList.find('.list-group-item').attr('data-selected', false);
|
||||
versionsList.find('.list-group-item.active').attr('data-selected', true);
|
||||
$('#setDefaultVersionButton').parent().addClass('hidden');
|
||||
reloadRepositoriesList(FULL_VIEW_MODAL.find('.table').data('id'));
|
||||
animateSpinner(null, false);
|
||||
}
|
||||
});
|
||||
|
@ -595,6 +598,7 @@ var MyModuleRepositories = (function() {
|
|||
|
||||
renderFullViewRepositoryName(repositoryNameObject.text());
|
||||
FULL_VIEW_MODAL.modal('show');
|
||||
initCloseFullViewModal();
|
||||
$.getJSON($(this).data('table-url'), (data) => {
|
||||
FULL_VIEW_MODAL.find('.table-container').html(data.html);
|
||||
renderFullViewTable(FULL_VIEW_MODAL.find('.table'), { assigned: true, skipCheckbox: true });
|
||||
|
@ -682,6 +686,7 @@ var MyModuleRepositories = (function() {
|
|||
var assignUrlModal = $(this).data('assign-url-modal');
|
||||
var updateUrlModal = $(this).data('update-url-modal');
|
||||
FULL_VIEW_MODAL.modal('show');
|
||||
initCloseFullViewModal();
|
||||
$.get($(this).data('table-url'), (data) => {
|
||||
FULL_VIEW_MODAL.find('.table-container').html(data.html);
|
||||
FULL_VIEW_MODAL.data('assign-url-modal', assignUrlModal);
|
||||
|
@ -776,7 +781,7 @@ var MyModuleRepositories = (function() {
|
|||
$(FULL_VIEW_TABLE.table().container()).find('.dataTable')
|
||||
.attr('data-assigned-items-count', data.rows_count);
|
||||
FULL_VIEW_TABLE.ajax.reload(null, false);
|
||||
reloadRepositoriesList(data.repository_id);
|
||||
reloadRepositoriesList(data.repository_id, true);
|
||||
updateFullViewRowsCount(data.rows_count);
|
||||
renderFullViewAssignButtons();
|
||||
},
|
||||
|
@ -809,6 +814,14 @@ var MyModuleRepositories = (function() {
|
|||
});
|
||||
}
|
||||
|
||||
function initCloseFullViewModal() {
|
||||
$(FULL_VIEW_MODAL).on('keyup', function(e) {
|
||||
if (e.key === 'Escape') {
|
||||
FULL_VIEW_MODAL.modal('hide');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
init: () => {
|
||||
initSimpleTable();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* global SmartAnnotation I18n MyModuleRepositories GLOBAL_CONSTANTS formatDecimalValue */
|
||||
/* global SmartAnnotation I18n MyModuleRepositories GLOBAL_CONSTANTS formatDecimalValue Decimal */
|
||||
var MyModuleStockConsumption = (function() {
|
||||
const CONSUMPTION_MODAL = '#consumeRepositoryStockValueModal';
|
||||
const WARNING_MODAL = '#consumeRepositoryStockValueModalWarning';
|
||||
|
@ -28,16 +28,29 @@ var MyModuleStockConsumption = (function() {
|
|||
SmartAnnotation.init($(CONSUMPTION_MODAL + ' #comment')[0]);
|
||||
|
||||
$('#stock_consumption').on('input', function() {
|
||||
let initialValue = parseFloat($(this).data('initial-value'));
|
||||
let initialStock = parseFloat($(this).data('initial-stock'));
|
||||
let initialValue = new Decimal($(this).data('initial-value') || 0);
|
||||
let initialStock = new Decimal($(this).data('initial-stock'));
|
||||
let decimals = $(this).data('decimals');
|
||||
this.value = formatDecimalValue(String(this.value), decimals);
|
||||
let finalValue = initialValue - ($(this).val() || 0) + initialStock;
|
||||
let finalValue = initialValue.minus(new Decimal($(this).val() || 0)).plus(initialStock);
|
||||
$('.stock-final-container .value')
|
||||
.text(formatDecimalValue(String(finalValue), $('#stock_consumption').data('decimals')));
|
||||
$('.stock-final-container').toggleClass('error', finalValue <= 0);
|
||||
$(this).closest('.sci-input-container').toggleClass('error', this.value === '');
|
||||
$('.update-consumption-button').attr('disabled', $(this).val() === '');
|
||||
$('.stock-final-container').toggleClass('negative', finalValue <= 0);
|
||||
$(this).closest('.sci-input-container').toggleClass('error', !($(this).val().length && this.value >= 0));
|
||||
if ($(this).val().length === 0) {
|
||||
$(this).closest('.sci-input-container')
|
||||
.attr(
|
||||
'data-error-text',
|
||||
I18n.t('repository_stock_values.manage_modal.amount_error')
|
||||
);
|
||||
} else if (this.value <= 0) {
|
||||
$(this).closest('.sci-input-container')
|
||||
.attr(
|
||||
'data-error-text',
|
||||
I18n.t('repository_stock_values.manage_modal.negative_error')
|
||||
);
|
||||
}
|
||||
$('.update-consumption-button').attr('disabled', !($(this).val().length && this.value >= 0));
|
||||
});
|
||||
|
||||
$(CONSUMPTION_MODAL + ' form').on('ajax:success', function() {
|
||||
|
@ -85,7 +98,7 @@ var MyModuleStockConsumption = (function() {
|
|||
} else if (e.key === 'Enter') {
|
||||
$('.update-consumption-button').trigger('click', [true]);
|
||||
}
|
||||
})
|
||||
});
|
||||
$(WARNING_MODAL).on('click', '.cancel-consumption', function(e) {
|
||||
$(WARNING_MODAL).modal('hide');
|
||||
$(CONSUMPTION_MODAL).modal('show');
|
||||
|
|
|
@ -209,27 +209,19 @@ function initializeEdit() {
|
|||
|
||||
if (canEditModules) {
|
||||
initEditModules();
|
||||
$(".edit-module").on("click touchstart", editModuleHandler);
|
||||
$("#canvas-container").on("click touchstart", ".edit-module", editModuleHandler);
|
||||
}
|
||||
|
||||
if (canCloneModules) {
|
||||
bindCloneModuleAction(
|
||||
$(".module-options a.clone-module"),
|
||||
".diagram .module",
|
||||
GRID_DIST_EDIT_X,
|
||||
GRID_DIST_EDIT_Y);
|
||||
bindCloneModuleGroupAction(
|
||||
$(".module-options a.clone-module-group"),
|
||||
".diagram .module",
|
||||
GRID_DIST_EDIT_X,
|
||||
GRID_DIST_EDIT_Y);
|
||||
bindCloneModuleAction(".diagram .module", GRID_DIST_EDIT_X, GRID_DIST_EDIT_Y);
|
||||
bindCloneModuleGroupAction(".diagram .module", GRID_DIST_EDIT_X, GRID_DIST_EDIT_Y);
|
||||
}
|
||||
if (canMoveModules) {
|
||||
initMoveModules();
|
||||
$(".move-module").on("click touchstart", moveModuleHandler);
|
||||
$("#canvas-container").on("click touchstart", ".move-module", moveModuleHandler);
|
||||
|
||||
initMoveModuleGroups();
|
||||
$(".move-module-group").on("click touchstart", moveModuleGroupHandler);
|
||||
$("#canvas-container").on("click touchstart", ".move-module-group", moveModuleGroupHandler);
|
||||
}
|
||||
if (canDeleteModules) {
|
||||
bindDeleteModuleAction();
|
||||
|
@ -250,6 +242,17 @@ function initializeEdit() {
|
|||
{ color: 'white', shadow: true }
|
||||
);
|
||||
});
|
||||
|
||||
$('.module-options-dropdown')
|
||||
.on('show.bs.dropdown', function() {
|
||||
let dropdownContainer = $(this);
|
||||
$.getJSON(dropdownContainer.data('dropdown-menu-path'), function(result) {
|
||||
dropdownContainer.find('.dropdown-menu').html(result.html);
|
||||
});
|
||||
})
|
||||
.on('show.bs.dropdown', function() {
|
||||
$(this).find('.dropdown-menu').html('');
|
||||
});
|
||||
}
|
||||
|
||||
function destroyEdit() {
|
||||
|
@ -1174,9 +1177,6 @@ function updateModuleHtml(module, id, name, gridDistX, gridDistY) {
|
|||
.addClass("edit-module")
|
||||
.html($("#edit-link-placeholder").text().trim())
|
||||
.appendTo(editModuleItem);
|
||||
|
||||
// Add click handler for the edit module
|
||||
$(editModuleLink).on("click touchstart", editModuleHandler);
|
||||
}
|
||||
|
||||
// Add clone links if neccesary
|
||||
|
@ -1192,9 +1192,6 @@ function updateModuleHtml(module, id, name, gridDistX, gridDistY) {
|
|||
.html($("#clone-link-placeholder").text().trim())
|
||||
.appendTo(cloneModuleItem);
|
||||
|
||||
// Add clone click handler for the new module
|
||||
bindCloneModuleAction($(cloneModuleLink), ".diagram .module", gridDistX, gridDistY);
|
||||
|
||||
var cloneModuleGroupItem = document.createElement("li");
|
||||
$(cloneModuleGroupItem).appendTo(dropdownMenu);
|
||||
$(cloneModuleGroupItem).hide();
|
||||
|
@ -1207,9 +1204,6 @@ function updateModuleHtml(module, id, name, gridDistX, gridDistY) {
|
|||
.html($("#clone-group-link-placeholder").text().trim())
|
||||
.appendTo(cloneModuleGroupItem);
|
||||
|
||||
// Add clone click handler for the new module
|
||||
bindCloneModuleGroupAction($(cloneModuleGroupLink), ".diagram .module", gridDistX, gridDistY);
|
||||
|
||||
bindEditModeDropdownHandlers(module);
|
||||
}
|
||||
|
||||
|
@ -1226,9 +1220,6 @@ function updateModuleHtml(module, id, name, gridDistX, gridDistY) {
|
|||
.html($("#move-link-placeholder").text().trim())
|
||||
.appendTo(moveModuleItem);
|
||||
|
||||
// Add clone click handler for the new module
|
||||
$(moveModuleLink).on("click touchstart", moveModuleHandler);
|
||||
|
||||
// Add buttons for module groups
|
||||
var moveModuleGroupItem = document.createElement("li");
|
||||
$(moveModuleGroupItem).appendTo(dropdownMenu);
|
||||
|
@ -1241,8 +1232,6 @@ function updateModuleHtml(module, id, name, gridDistX, gridDistY) {
|
|||
.addClass("move-module-group")
|
||||
.html($("#move-group-link-placeholder").text().trim())
|
||||
.appendTo(moveModuleGroupItem);
|
||||
|
||||
$(moveModuleGroupLink).on("click touchstart", moveModuleGroupHandler);
|
||||
}
|
||||
|
||||
// Add delete links if neccesary
|
||||
|
@ -1258,9 +1247,6 @@ function updateModuleHtml(module, id, name, gridDistX, gridDistY) {
|
|||
.html($("#delete-link-placeholder").text().trim())
|
||||
.appendTo(deleteModuleItem);
|
||||
|
||||
// Add delete click handler for the new module
|
||||
$(deleteModuleLink).on("click touchstart", deleteModuleHandler);
|
||||
|
||||
var deleteModuleGroupItem = document.createElement("li");
|
||||
$(deleteModuleGroupItem).appendTo(dropdownMenu);
|
||||
$(deleteModuleGroupItem).hide();
|
||||
|
@ -1272,9 +1258,6 @@ function updateModuleHtml(module, id, name, gridDistX, gridDistY) {
|
|||
.addClass("delete-module-group")
|
||||
.html($("#delete-group-link-placeholder").text().trim())
|
||||
.appendTo(deleteModuleGroupItem);
|
||||
|
||||
// Add delete click handler for the new module
|
||||
$(deleteModuleGroupLink).on("click touchstart", deleteModuleGroupHandler);
|
||||
}
|
||||
|
||||
// Set it up for jsPlumb, depending on permissions
|
||||
|
@ -1482,8 +1465,9 @@ function initEditModules() {
|
|||
var moduleId = modal.attr("data-module-id");
|
||||
var moduleEl = $("#" + moduleId);
|
||||
// Update the module's name in GUI
|
||||
moduleEl.attr("data-module-name", newName);
|
||||
moduleEl.find(".panel-heading .panel-title").html(newName);
|
||||
moduleEl.attr('data-module-name', newName);
|
||||
moduleEl.find('.panel-heading .panel-title').attr('title', newName);
|
||||
moduleEl.find('.panel-heading .panel-title').html(newName);
|
||||
|
||||
// Add this information to form
|
||||
var formAddInput = $('#update-canvas form input#add');
|
||||
|
@ -1769,7 +1753,7 @@ moveModuleGroupHandler = function(ev) {
|
|||
*/
|
||||
function bindDeleteModuleAction() {
|
||||
// First, bind the delete module handler onto all "delete module" links
|
||||
$(".module-options a.delete-module").on("click touchstart", deleteModuleHandler);
|
||||
$("#canvas-container").on("click touchstart", ".delete-module", deleteModuleHandler);
|
||||
|
||||
// Then, bind on modal events
|
||||
var modal = $("#modal-delete-module");
|
||||
|
@ -1961,7 +1945,7 @@ deleteModuleHandler =function() {
|
|||
function bindDeleteModuleGroupAction() {
|
||||
// First, bind the delete module group handler onto all
|
||||
// "delete module group" links
|
||||
$(".module-options a.delete-module-group").on("click touchstart", deleteModuleGroupHandler);
|
||||
$("#canvas-container").on("click touchstart", ".delete-module-group", deleteModuleGroupHandler);
|
||||
|
||||
// Then, bind on modal events
|
||||
var modal = $("#modal-delete-module-group");
|
||||
|
@ -2031,8 +2015,8 @@ deleteModuleGroupHandler = function() {
|
|||
* @param gridDistX - The grid distance in X direction.
|
||||
* @param gridDistY - The grid distance in Y direction.
|
||||
*/
|
||||
function bindCloneModuleAction(element, modulesSel, gridDistX, gridDistY) {
|
||||
element.on("click touchstart", function(event) {
|
||||
function bindCloneModuleAction(modulesSel, gridDistX, gridDistY) {
|
||||
$("#canvas-container").on("click touchstart", ".clone-module", function(event) {
|
||||
cloneModuleHandler($(this).data("module-id"), modulesSel, gridDistX, gridDistY);
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
@ -2133,8 +2117,8 @@ function cloneModule(originalModule, gridDistX, gridDistY, left, top) {
|
|||
* @param gridDistX - The grid distance in X direction.
|
||||
* @param gridDistY - The grid distance in Y direction.
|
||||
*/
|
||||
function bindCloneModuleGroupAction(element, modulesSel, gridDistX, gridDistY) {
|
||||
element.on("click touchstart", function(event) {
|
||||
function bindCloneModuleGroupAction(modulesSel, gridDistX, gridDistY) {
|
||||
$("#canvas-container").on("click touchstart", ".clone-module-group", function(event) {
|
||||
cloneModuleGroupHandler($(this).data("module-id"), modulesSel, gridDistX, gridDistY);
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
|
|
@ -209,7 +209,7 @@ $.fn.dataTable.render.RepositoryStockValue = function(data) {
|
|||
</a>`;
|
||||
}
|
||||
return `<span class="stock-value-view-render
|
||||
${data.stock_managable !== undefined ? `stock-${data.stock_status}` : ''}">
|
||||
${data.displayWarnings ? `stock-${data.stock_status}` : ''}">
|
||||
${data.value.stock_formatted}
|
||||
</span>`;
|
||||
}
|
||||
|
@ -231,18 +231,18 @@ $.fn.dataTable.render.defaultRepositoryStockValue = function() {
|
|||
|
||||
$.fn.dataTable.render.RepositoryStockConsumptionValue = function(data = {}) {
|
||||
// covers case of snapshots
|
||||
if (!data.stock_present && data.value && data.value.consumed_stock_formatted) {
|
||||
if (!data.stock_present && data.value && data.value.consumed_stock !== null) {
|
||||
return `<span class="empty-consumed-stock-render">${data.value.consumed_stock_formatted}</span>`;
|
||||
}
|
||||
if (!data.stock_present) {
|
||||
return '<span class="empty-consumed-stock-render"> - </span>';
|
||||
}
|
||||
if (!data.consumptionManagable) {
|
||||
if (!data.consumptionManagable && data.value && !data.value.consumed_stock) {
|
||||
return `<span class="consumption-locked">
|
||||
${I18n.t('libraries.manange_modal_column.stock_type.stock_consumption_locked')}
|
||||
</span>`;
|
||||
}
|
||||
if (!data.consumptionPermitted) {
|
||||
if (!data.consumptionPermitted || !data.consumptionManagable) {
|
||||
return `<span class="empty-consumed-stock-render">${data.value.consumed_stock_formatted}</span>`;
|
||||
}
|
||||
if (!data.value.consumed_stock) {
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
/*
|
||||
globals HelperModule animateSpinner SmartAnnotation AssetColumnHelper GLOBAL_CONSTANTS
|
||||
globals HelperModule animateSpinner SmartAnnotation AssetColumnHelper GLOBAL_CONSTANTS I18n
|
||||
*/
|
||||
/* eslint-disable no-unused-vars */
|
||||
/* eslint-disable no-alert no-unused-vars */
|
||||
/* eslint-disable no-alert */
|
||||
|
||||
var RepositoryDatatableRowEditor = (function() {
|
||||
const NAME_COLUMN_ID = 'row-name';
|
||||
|
@ -49,7 +50,10 @@ var RepositoryDatatableRowEditor = (function() {
|
|||
$form.submit();
|
||||
return false;
|
||||
}).catch((reason) => {
|
||||
alert(reason);
|
||||
if (reason.includes('Status: 403')) {
|
||||
HelperModule.flashAlertMsg(I18n.t('activerecord.errors.storage.limit_reached'), 'danger');
|
||||
} else alert(reason);
|
||||
animateSpinner($table, false);
|
||||
return false;
|
||||
});
|
||||
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
/* global dropdownSelector GLOBAL_CONSTANTS I18n SmartAnnotation formatDecimalValue */
|
||||
/* global dropdownSelector GLOBAL_CONSTANTS I18n SmartAnnotation formatDecimalValue Decimal */
|
||||
|
||||
var RepositoryStockValues = (function() {
|
||||
const UNIT_SELECTOR = '#repository-stock-value-units';
|
||||
|
||||
function updateChangeAmount($element) {
|
||||
var currentAmount = parseFloat($element.data('currentAmount'));
|
||||
var inputAmount = parseFloat($element.val());
|
||||
var newAmount;
|
||||
|
||||
if (!$element.val()) {
|
||||
$('.stock-final-container .value').text('-');
|
||||
return;
|
||||
}
|
||||
if (!(inputAmount >= 0)) return;
|
||||
if (!($element.val() >= 0)) return;
|
||||
|
||||
let currentAmount = new Decimal($element.data('currentAmount') || 0);
|
||||
let inputAmount = new Decimal($element.val());
|
||||
let newAmount;
|
||||
|
||||
switch ($element.data('operator')) {
|
||||
case 'set':
|
||||
newAmount = inputAmount;
|
||||
break;
|
||||
case 'add':
|
||||
newAmount = currentAmount + inputAmount;
|
||||
newAmount = currentAmount.plus(inputAmount);
|
||||
break;
|
||||
case 'remove':
|
||||
newAmount = currentAmount - inputAmount;
|
||||
newAmount = currentAmount.minus(inputAmount);
|
||||
break;
|
||||
default:
|
||||
newAmount = currentAmount;
|
||||
|
@ -41,6 +41,9 @@ var RepositoryStockValues = (function() {
|
|||
let amountChanged = false;
|
||||
|
||||
$('.repository-show').on('click', '.manage-repository-stock-value-link', function() {
|
||||
let colIndex = this.parentNode.cellIndex;
|
||||
let rowIndex = this.parentNode.parentNode.rowIndex;
|
||||
|
||||
$.ajax({
|
||||
url: $(this).closest('tr').data('manage-stock-url'),
|
||||
type: 'GET',
|
||||
|
@ -73,10 +76,15 @@ var RepositoryStockValues = (function() {
|
|||
.dropdown-selector-container .search-field
|
||||
`).attr('tabindex', 2);
|
||||
|
||||
$manageModal.find('form').on('ajax:success', function() {
|
||||
var dataTable = $('.dataTable').DataTable();
|
||||
$manageModal.find('form').on('ajax:success', function(_, data) {
|
||||
$manageModal.modal('hide');
|
||||
dataTable.ajax.reload(null, false);
|
||||
let $cell = $('.dataTable').find(
|
||||
`tr:nth-child(${rowIndex}) td:nth-child(${colIndex + 1})`
|
||||
);
|
||||
$cell.parent().data('manage-stock-url', data.manageStockUrl);
|
||||
$cell.html(
|
||||
$.fn.dataTable.render.RepositoryStockValue(data)
|
||||
);
|
||||
});
|
||||
|
||||
$('.stock-operator-option').click(function() {
|
||||
|
@ -114,7 +122,7 @@ var RepositoryStockValues = (function() {
|
|||
|
||||
SmartAnnotation.init($('#repository-stock-value-comment')[0]);
|
||||
|
||||
$('#repository-stock-value-comment').on('keyup change', function() {
|
||||
$('#repository-stock-value-comment').on('input', function() {
|
||||
$(this).closest('.sci-input-container').toggleClass(
|
||||
'error',
|
||||
this.value.length > GLOBAL_CONSTANTS.NAME_MAX_LENGTH
|
||||
|
@ -128,7 +136,6 @@ var RepositoryStockValues = (function() {
|
|||
$('#reminder-selector-checkbox').on('change', function() {
|
||||
let valueContainer = $('.repository-stock-reminder-value');
|
||||
valueContainer.toggleClass('hidden', !this.checked);
|
||||
valueContainer.find('input').attr('required', this.checked);
|
||||
if (!this.checked) {
|
||||
$(this).data('reminder-value', valueContainer.find('input').val());
|
||||
valueContainer.find('input').val(null);
|
||||
|
@ -157,14 +164,50 @@ var RepositoryStockValues = (function() {
|
|||
} else {
|
||||
dropdownSelector.hideError(UNIT_SELECTOR);
|
||||
}
|
||||
|
||||
if ($('#stock-input-amount').val().length) {
|
||||
$('#stock-input-amount').parent().removeClass('error');
|
||||
let stockInput = $('#stock-input-amount');
|
||||
if (stockInput.val().length && stockInput.val() >= 0) {
|
||||
stockInput.parent().removeClass('error');
|
||||
} else {
|
||||
$('#stock-input-amount').parent().addClass('error');
|
||||
stockInput.parent().addClass('error');
|
||||
if (stockInput.val().length === 0) {
|
||||
stockInput.parent()
|
||||
.attr(
|
||||
'data-error-text',
|
||||
I18n.t('repository_stock_values.manage_modal.amount_error')
|
||||
);
|
||||
} else {
|
||||
stockInput.parent()
|
||||
.attr(
|
||||
'data-error-text',
|
||||
I18n.t('repository_stock_values.manage_modal.negative_error')
|
||||
);
|
||||
}
|
||||
status = false;
|
||||
}
|
||||
|
||||
let reminderInput = $('.repository-stock-reminder-value input');
|
||||
if ($('#reminder-selector-checkbox')[0].checked) {
|
||||
if (reminderInput.val().length && reminderInput.val() >= 0) {
|
||||
reminderInput.parent().removeClass('error');
|
||||
} else {
|
||||
reminderInput.parent().addClass('error');
|
||||
if (reminderInput.val().length === 0) {
|
||||
reminderInput.parent()
|
||||
.attr(
|
||||
'data-error-text',
|
||||
I18n.t('repository_stock_values.manage_modal.amount_error')
|
||||
);
|
||||
} else {
|
||||
reminderInput.parent()
|
||||
.attr(
|
||||
'data-error-text',
|
||||
I18n.t('repository_stock_values.manage_modal.negative_error')
|
||||
);
|
||||
}
|
||||
status = false;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
});
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* global dropdownSelector */
|
||||
/* global GLOBAL_CONSTANTS dropdownSelector */
|
||||
/* eslint-disable no-unused-vars */
|
||||
var RepositoryDateColumnType = (function() {
|
||||
const columnContainer = '.date-column-type';
|
||||
|
@ -12,18 +12,22 @@ var RepositoryDateColumnType = (function() {
|
|||
});
|
||||
}
|
||||
|
||||
function setReminderDelta() {
|
||||
let reminderValueInput = $(columnContainer).find('.reminder-value');
|
||||
reminderValueInput.val(reminderValueInput.val().replace(/[^0-9]/, ''));
|
||||
let value = reminderValueInput.val();
|
||||
|
||||
if (!isNaN(parseInt(value, 10))) {
|
||||
$(columnContainer).find('.reminder-delta').val(
|
||||
value * $(columnContainer).find('.reminder-unit').val()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function initReminders() {
|
||||
let $modal = $('#manage-repository-column');
|
||||
$modal.on('input', `${columnContainer} .reminder-value, ${columnContainer} .reminder-unit`, function() {
|
||||
let reminderValueInput = $(columnContainer).find('.reminder-value');
|
||||
reminderValueInput.val(reminderValueInput.val().replace(/[^0-9]/, ''));
|
||||
let value = reminderValueInput.val();
|
||||
|
||||
if (!isNaN(parseInt(value, 10))) {
|
||||
$(columnContainer).find('.reminder-delta').val(
|
||||
value * $(columnContainer).find('.reminder-unit').val()
|
||||
);
|
||||
}
|
||||
setReminderDelta();
|
||||
});
|
||||
|
||||
$modal.on('change', `${columnContainer} #date-reminder, ${columnContainer} #date-range`, function() {
|
||||
|
@ -32,10 +36,21 @@ var RepositoryDateColumnType = (function() {
|
|||
rangeCheckbox.attr('disabled', reminderCheckbox.is(':checked'));
|
||||
reminderCheckbox.attr('disabled', rangeCheckbox.is(':checked'));
|
||||
$(columnContainer).find('.reminder-group').toggleClass('hidden', !reminderCheckbox.is(':checked'));
|
||||
if (reminderCheckbox.is(':checked')) setReminderDelta();
|
||||
});
|
||||
|
||||
$modal.on('columnModal::partialLoadedForRepositoryDateValue', function() {
|
||||
initReminderUnitDropdown();
|
||||
$('#date-reminder-message').on('input', function() {
|
||||
$(this).closest('.sci-input-container').toggleClass(
|
||||
'error',
|
||||
this.value.length > GLOBAL_CONSTANTS.NAME_MAX_LENGTH
|
||||
);
|
||||
$('#update-repo-column-submit').toggleClass(
|
||||
'disabled',
|
||||
this.value.length > GLOBAL_CONSTANTS.NAME_MAX_LENGTH
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* global dropdownSelector */
|
||||
/* global GLOBAL_CONSTANTS dropdownSelector */
|
||||
/* eslint-disable no-unused-vars */
|
||||
var RepositoryDateTimeColumnType = (function() {
|
||||
const columnContainer = '.datetime-column-type';
|
||||
|
@ -12,18 +12,22 @@ var RepositoryDateTimeColumnType = (function() {
|
|||
});
|
||||
}
|
||||
|
||||
function setReminderDelta() {
|
||||
let reminderValueInput = $(columnContainer).find('.reminder-value');
|
||||
reminderValueInput.val(reminderValueInput.val().replace(/[^0-9]/, ''));
|
||||
let value = reminderValueInput.val();
|
||||
|
||||
if (!isNaN(parseInt(value, 10))) {
|
||||
$(columnContainer).find('.reminder-delta').val(
|
||||
value * $(columnContainer).find('.reminder-unit').val()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function initReminders() {
|
||||
let $modal = $('#manage-repository-column');
|
||||
$modal.on('input', `${columnContainer} .reminder-value, ${columnContainer} .reminder-unit`, function() {
|
||||
let reminderValueInput = $(columnContainer).find('.reminder-value');
|
||||
reminderValueInput.val(reminderValueInput.val().replace(/[^0-9]/, ''));
|
||||
let value = reminderValueInput.val();
|
||||
|
||||
if (!isNaN(parseInt(value, 10))) {
|
||||
$(columnContainer).find('.reminder-delta').val(
|
||||
value * $(columnContainer).find('.reminder-unit').val()
|
||||
);
|
||||
}
|
||||
setReminderDelta();
|
||||
});
|
||||
|
||||
$modal.on('change', `${columnContainer} #datetime-reminder, ${columnContainer} #datetime-range`, function() {
|
||||
|
@ -32,10 +36,21 @@ var RepositoryDateTimeColumnType = (function() {
|
|||
rangeCheckbox.attr('disabled', reminderCheckbox.is(':checked'));
|
||||
reminderCheckbox.attr('disabled', rangeCheckbox.is(':checked'));
|
||||
$(columnContainer).find('.reminder-group').toggleClass('hidden', !reminderCheckbox.is(':checked'));
|
||||
if (reminderCheckbox.is(':checked')) setReminderDelta();
|
||||
});
|
||||
|
||||
$modal.on('columnModal::partialLoadedForRepositoryDateTimeValue', function() {
|
||||
initReminderUnitDropdown();
|
||||
$('#datetime-reminder-message').on('input', function() {
|
||||
$(this).closest('.sci-input-container').toggleClass(
|
||||
'error',
|
||||
this.value.length > GLOBAL_CONSTANTS.NAME_MAX_LENGTH
|
||||
);
|
||||
$('#update-repo-column-submit').toggleClass(
|
||||
'disabled',
|
||||
this.value.length > GLOBAL_CONSTANTS.NAME_MAX_LENGTH
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ var InfiniteScroll = (function() {
|
|||
$container.data('next-page', result.next_page);
|
||||
} else {
|
||||
$container.addClass('last-page');
|
||||
if ($container.data('config').endOfListTemplate) {
|
||||
if ($container.data('config').endOfListTemplate && page > 2) {
|
||||
$($($container.data('config').endOfListTemplate).html()).appendTo($container);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,10 +65,20 @@ function prepareRepositoryHeaderForExport(th) {
|
|||
|
||||
function initReminderDropdown(table) {
|
||||
$(table).on('keyup', '.row-reminders-dropdown', function(e) {
|
||||
if (e.key === 'Escape') {
|
||||
if (e.key === 'Escape' && $('.row-reminders-dropdown').hasClass('open')) {
|
||||
$(this).children('.dropdown-menu').dropdown('toggle');
|
||||
// Preventing closing modal on full view mode for assigning repository items
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
});
|
||||
|
||||
$(table).on('keyup', '.row-reminders-footer', function(e) {
|
||||
if (e.key === ' ') {
|
||||
$(this).click();
|
||||
}
|
||||
});
|
||||
|
||||
$(table).on('show.bs.dropdown', '.row-reminders-dropdown', function() {
|
||||
let row = $(this).closest('tr');
|
||||
let screenHeight = screen.height;
|
||||
|
|
17
app/assets/javascripts/sitewide/show_password.js
Normal file
17
app/assets/javascripts/sitewide/show_password.js
Normal file
|
@ -0,0 +1,17 @@
|
|||
$(document).on('turbolinks:load', function() {
|
||||
$.each($('input[type="password"]'), function(i, e) {
|
||||
$('<i class="fas fa-eye show-password" style="cursor: pointer; z-index: 10"></i>').insertAfter(e);
|
||||
$(e).parent().addClass('right-icon');
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on('click', '.show-password', function() {
|
||||
let $icon = $(this);
|
||||
if ($icon.hasClass('fa-eye')) {
|
||||
$icon.removeClass('fa-eye').addClass('fa-eye-slash');
|
||||
$icon.parent().find('input[type=password]').attr('type', 'text');
|
||||
} else {
|
||||
$icon.removeClass('fa-eye-slash').addClass('fa-eye');
|
||||
$icon.parent().find('input[type=text]').attr('type', 'password');
|
||||
}
|
||||
});
|
|
@ -44,6 +44,7 @@
|
|||
labelHTML: true,
|
||||
tagClass: 'users-dropdown-list',
|
||||
inputTagMode: true,
|
||||
selectKeys: [13, 32, 44, 188],
|
||||
customDropdownIcon: () => { return '<i class="fas fa-search right-icon"></i>'; },
|
||||
onChange: () => {
|
||||
let values = dropdownSelector.getValues(emailsInput);
|
||||
|
@ -57,6 +58,14 @@
|
|||
}
|
||||
});
|
||||
|
||||
modal.find('.search-field').focusout(function() {
|
||||
if ($(this).val()) {
|
||||
$(this).trigger(
|
||||
$.Event('keypress', { keyCode: 13 })
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
dropdownSelector.init('#role', {
|
||||
noEmptyOption: true,
|
||||
singleSelect: true,
|
||||
|
|
|
@ -45,14 +45,13 @@
|
|||
|
||||
.assigned-repository-title {
|
||||
@include my-module-repository-title;
|
||||
padding-right: 2.2em;
|
||||
|
||||
&::after {
|
||||
color: $color-alto;
|
||||
content: '[' attr(data-rows-count) ']';
|
||||
display: inline-block;
|
||||
padding-left: 1px;
|
||||
padding-right: .7em;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
@ -214,6 +213,11 @@
|
|||
color: $color-volcano;
|
||||
}
|
||||
|
||||
.empty-stock-render,
|
||||
.consumption-locked {
|
||||
color: $color-silver-chalice;
|
||||
}
|
||||
|
||||
.row-stock,
|
||||
.row-consumption {
|
||||
min-width: 140px;
|
||||
|
|
|
@ -27,6 +27,14 @@ $color-module-hover: $brand-primary;
|
|||
|
||||
.actions-button {
|
||||
margin-right: 15px;
|
||||
|
||||
.fas {
|
||||
margin-right: .4em;
|
||||
}
|
||||
|
||||
a {
|
||||
padding: .5em 1em;
|
||||
}
|
||||
}
|
||||
|
||||
.toolbarButtons {
|
||||
|
|
|
@ -120,7 +120,7 @@
|
|||
padding: 1em;
|
||||
|
||||
.apply-button {
|
||||
margin-left: auto !important;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.filters-columns-list {
|
||||
|
@ -232,6 +232,49 @@
|
|||
}
|
||||
}
|
||||
|
||||
@media (max-width: 992px) {
|
||||
.filters-container {
|
||||
width: 200px;
|
||||
|
||||
.filter-container {
|
||||
.filter-attributes {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
|
||||
.operator-selector {
|
||||
.dropdown-selector-container {
|
||||
width: 125px;
|
||||
}
|
||||
}
|
||||
|
||||
.date-time-picker {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.between-delimiter {
|
||||
height: 10px;
|
||||
margin: 5px auto;
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
|
||||
.apply-button {
|
||||
margin-left: 0;
|
||||
margin-top: .5em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.task-option {
|
||||
background-image: image-url("icon_small/task-black.svg");
|
||||
background-position: left center;
|
||||
|
|
|
@ -75,12 +75,13 @@
|
|||
@media (max-width: 1299px) {
|
||||
.repository-toolbar {
|
||||
|
||||
.btn {
|
||||
.btn:not(.prevent-shrink) {
|
||||
padding: 7px;
|
||||
width: 36px;
|
||||
}
|
||||
.button-text {
|
||||
display: none;
|
||||
|
||||
.button-text {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.auto-shrink-button {
|
||||
|
|
|
@ -53,6 +53,13 @@ module Api
|
|||
)
|
||||
end
|
||||
|
||||
rescue_from URI::InvalidURIError do
|
||||
render_error(
|
||||
I18n.t('api.service.errors.url.not_valid'),
|
||||
I18n.t('api.service.errors.url.not_valid'), :bad_request
|
||||
)
|
||||
end
|
||||
|
||||
rescue_from JWT::DecodeError,
|
||||
JWT::InvalidPayload,
|
||||
JWT::VerificationError,
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Api
|
||||
module Service
|
||||
class ProjectsJsonExportController < BaseController
|
||||
require 'uri'
|
||||
|
||||
def projects_json_export
|
||||
projects_json_export_params = projects_json_export_data_params
|
||||
valid_url?(projects_json_export_params[:callback_url])
|
||||
ProjectsJsonExportJob.perform_later(projects_json_export_params[:task_ids],
|
||||
projects_json_export_params[:callback_url],
|
||||
current_user)
|
||||
render json: { status: :ok }, status: :accepted
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def projects_json_export_data_params
|
||||
raise ActionController::ParameterMissing, I18n.t('api.service.errors.missing_task_ids') unless
|
||||
params.require(:data).require(:task_ids)
|
||||
raise ActionController::ParameterMissing, I18n.t('api.service.errors.callback_missing') unless
|
||||
params.require(:data).require(:callback_url)
|
||||
|
||||
params.require(:data).permit(:callback_url, task_ids: [])
|
||||
end
|
||||
|
||||
def valid_url?(url)
|
||||
uri = URI.parse(url)
|
||||
raise URI::InvalidURIError if uri.host.blank?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,13 +1,15 @@
|
|||
class CanvasController < ApplicationController
|
||||
before_action :load_vars
|
||||
|
||||
before_action :check_view_canvas, only: [:edit, :full_zoom, :medium_zoom, :small_zoom]
|
||||
before_action :check_edit_canvas, only: [:edit, :update]
|
||||
before_action :check_view_canvas, except: %i(edit update)
|
||||
before_action :check_edit_canvas, only: %i(edit update)
|
||||
|
||||
def edit
|
||||
render partial: 'canvas/edit',
|
||||
locals: { experiment: @experiment, my_modules: @my_modules },
|
||||
:content_type => 'text/html'
|
||||
locals: {
|
||||
experiment: @experiment,
|
||||
my_modules: @my_modules
|
||||
}, content_type: 'text/html'
|
||||
end
|
||||
|
||||
def full_zoom
|
||||
|
@ -201,11 +203,12 @@ class CanvasController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
@my_modules = @experiment.my_modules.active
|
||||
@my_modules = @experiment.my_modules.active.preload(outputs: :to, user_assignments: %i(user user_role))
|
||||
end
|
||||
|
||||
def check_edit_canvas
|
||||
render_403 and return unless can_manage_experiment?(@experiment)
|
||||
@experiment_managable = can_manage_experiment?(@experiment)
|
||||
return render_403 unless @experiment_managable
|
||||
end
|
||||
|
||||
def check_view_canvas
|
||||
|
|
|
@ -67,8 +67,13 @@ class ExperimentsController < ApplicationController
|
|||
def canvas
|
||||
redirect_to module_archive_experiment_path(@experiment) if @experiment.archived_branch?
|
||||
@project = @experiment.project
|
||||
@active_modules = @experiment.my_modules.active.order(:name).includes(:tags, :inputs, :outputs)
|
||||
current_team_switch(@project.team)
|
||||
@active_modules = @experiment.my_modules.active.order(:name)
|
||||
.left_outer_joins(:designated_users, :task_comments)
|
||||
.preload(:tags, outputs: :to)
|
||||
.preload(:my_module_status, :my_module_group, user_assignments: %i(user user_role))
|
||||
.select('COUNT(DISTINCT users.id) as designated_users_count')
|
||||
.select('COUNT(DISTINCT comments.id) as task_comments_count')
|
||||
.select('my_modules.*').group(:id)
|
||||
end
|
||||
|
||||
def edit
|
||||
|
@ -254,6 +259,12 @@ class ExperimentsController < ApplicationController
|
|||
def module_archive
|
||||
@my_modules = @experiment.archived_branch? ? @experiment.my_modules : @experiment.my_modules.archived
|
||||
@my_modules = @my_modules.with_granted_permissions(current_user, MyModulePermissions::READ_ARCHIVED)
|
||||
.left_outer_joins(:designated_users, :task_comments)
|
||||
.preload(:tags, outputs: :to)
|
||||
.preload(:my_module_status, :my_module_group, user_assignments: %i(user user_role))
|
||||
.select('COUNT(DISTINCT users.id) as designated_users_count')
|
||||
.select('COUNT(DISTINCT comments.id) as task_comments_count')
|
||||
.select('my_modules.*').group(:id)
|
||||
end
|
||||
|
||||
def fetch_workflow_img
|
||||
|
@ -290,7 +301,7 @@ class ExperimentsController < ApplicationController
|
|||
private
|
||||
|
||||
def load_experiment
|
||||
@experiment = Experiment.find_by(id: params[:id])
|
||||
@experiment = Experiment.preload(user_assignments: %i(user user_role)).find_by(id: params[:id])
|
||||
render_404 unless @experiment
|
||||
end
|
||||
|
||||
|
|
|
@ -167,6 +167,7 @@ class MyModuleRepositoriesController < ApplicationController
|
|||
module_repository_row.consume_stock(current_user, params[:stock_consumption], params[:comment])
|
||||
|
||||
log_activity(module_repository_row, current_stock, params[:comment])
|
||||
protocol_consumption_notification(params[:comment], module_repository_row)
|
||||
end
|
||||
|
||||
render json: {}, status: :ok
|
||||
|
@ -229,6 +230,21 @@ class MyModuleRepositoriesController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def protocol_consumption_notification(comment, module_repository_row)
|
||||
smart_annotation_notification(
|
||||
old_text: nil,
|
||||
new_text: comment,
|
||||
title: t('notifications.my_module_consumption_comment_annotation_title',
|
||||
repository_item: module_repository_row.repository_row.name,
|
||||
repository: @repository.name,
|
||||
user: current_user.full_name),
|
||||
message: t('notifications.my_module_consumption_comment_annotation_message_html',
|
||||
project: link_to(@my_module.experiment.project.name, project_url(@my_module.experiment.project)),
|
||||
experiment: link_to(@my_module.experiment.name, canvas_experiment_url(@my_module.experiment)),
|
||||
my_module: link_to(@my_module.name, protocols_my_module_url(@my_module)))
|
||||
)
|
||||
end
|
||||
|
||||
def log_activity(module_repository_row, stock_consumption_was, comment)
|
||||
Activities::CreateActivityService
|
||||
.call(activity_type: :task_inventory_item_stock_consumed,
|
||||
|
|
|
@ -58,6 +58,15 @@ class MyModulesController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def canvas_dropdown_menu
|
||||
@experiment_managable = can_manage_experiment?(@experiment)
|
||||
@group_my_modules = @my_module.my_module_group&.my_modules&.preload(user_assignments: %i(user user_role))
|
||||
render json: {
|
||||
html: render_to_string({ partial: 'canvas/edit/my_module_dropdown_menu',
|
||||
locals: { my_module: @my_module } })
|
||||
}
|
||||
end
|
||||
|
||||
def activities
|
||||
params[:subjects] = {
|
||||
MyModule: [@my_module.id]
|
||||
|
@ -340,7 +349,7 @@ class MyModulesController < ApplicationController
|
|||
private
|
||||
|
||||
def load_vars
|
||||
@my_module = MyModule.find_by_id(params[:id])
|
||||
@my_module = MyModule.preload(user_assignments: %i(user user_role)).find_by(id: params[:id])
|
||||
if @my_module
|
||||
@experiment = @my_module.experiment
|
||||
@project = @my_module.experiment.project if @experiment
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class RepositoryStockValuesController < ApplicationController
|
||||
include RepositoryDatatableHelper # for use of display_cell_value method on stock update
|
||||
|
||||
before_action :load_vars
|
||||
before_action :check_manage_permissions
|
||||
|
||||
|
@ -45,7 +47,11 @@ class RepositoryStockValuesController < ApplicationController
|
|||
)
|
||||
end
|
||||
|
||||
render json: @repository_stock_value
|
||||
render json: {
|
||||
stock_managable: true,
|
||||
stock_status: @repository_stock_value.status,
|
||||
manageStockUrl: edit_repository_stock_repository_repository_row_url(@repository, @repository_row)
|
||||
}.merge(display_cell_value(@repository_stock_value.repository_cell, current_team, @repository))
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -58,6 +58,7 @@ class ResultAssetsController < ApplicationController
|
|||
if update_params.dig(:asset_attributes, :signed_blob_id)
|
||||
@result.asset.last_modified_by = current_user
|
||||
@result.asset.update(file: update_params[:asset_attributes][:signed_blob_id])
|
||||
@result.asset.file_pdf_preview.purge if @result.asset.file_pdf_preview.attached?
|
||||
update_params.delete(:asset_attributes)
|
||||
end
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ class TagsController < ApplicationController
|
|||
before_action :load_vars, only: [:create, :update, :destroy]
|
||||
before_action :load_vars_nested, only: [:update, :destroy]
|
||||
before_action :check_manage_permissions, only: %i(create update destroy)
|
||||
before_action :check_manage_my_module_permissions, only: %i(create)
|
||||
|
||||
def create
|
||||
@tag = Tag.new(tag_params)
|
||||
|
@ -154,16 +153,12 @@ class TagsController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def check_manage_my_module_permissions
|
||||
def check_manage_permissions
|
||||
my_module = MyModule.find_by id: params[:my_module_id]
|
||||
|
||||
render_403 if my_module && !can_manage_my_module_tags?(my_module)
|
||||
end
|
||||
|
||||
def check_manage_permissions
|
||||
render_403 unless can_manage_project_tags?(@project)
|
||||
end
|
||||
|
||||
def tag_params
|
||||
params.require(:tag).permit(:name, :color, :project_id)
|
||||
end
|
||||
|
|
|
@ -59,15 +59,19 @@ module RepositoryDatatableHelper
|
|||
# always add stock cell, even if empty
|
||||
row['stock'] = stock_present ? display_cell_value(record.repository_stock_cell, team, repository) : {}
|
||||
row['stock'][:stock_managable] = stock_managable
|
||||
|
||||
if !options[:include_stock_consumption] || stock_consumption_permitted?(repository, options[:my_module])
|
||||
row['stock'][:stock_status] = record.repository_stock_cell&.value&.status
|
||||
end
|
||||
row['stock']['displayWarnings'] = display_stock_warnings?(repository)
|
||||
row['stock'][:stock_status] = record.repository_stock_cell&.value&.status
|
||||
|
||||
row['stock']['value_type'] = 'RepositoryStockValue'
|
||||
|
||||
if options[:include_stock_consumption] && record.repository.has_stock_management? && options[:my_module]
|
||||
consumption_managable = stock_consumption_managable?(record, repository, options[:my_module])
|
||||
consumed_stock_formatted =
|
||||
number_with_precision(
|
||||
record.consumed_stock,
|
||||
precision: (record.repository.repository_stock_column.metadata['decimals'].to_i || 0),
|
||||
strip_insignificant_zeros: true
|
||||
)
|
||||
row['consumedStock'] = {
|
||||
stock_present: stock_present,
|
||||
consumptionPermitted: stock_consumption_permitted?(repository, options[:my_module]),
|
||||
|
@ -80,7 +84,7 @@ module RepositoryDatatableHelper
|
|||
value: {
|
||||
consumed_stock: record.consumed_stock,
|
||||
consumed_stock_formatted:
|
||||
"#{record.consumed_stock || 0} #{record.repository_stock_value&.repository_stock_unit_item&.data}"
|
||||
"#{consumed_stock_formatted || 0} #{record.repository_stock_value&.repository_stock_unit_item&.data}"
|
||||
}
|
||||
}
|
||||
end
|
||||
|
@ -115,10 +119,8 @@ module RepositoryDatatableHelper
|
|||
consumption_managable = stock_consumption_managable?(record, repository, my_module)
|
||||
|
||||
row['stock'] = stock_present ? display_cell_value(record.repository_stock_cell, record.repository.team, repository) : {}
|
||||
|
||||
if !options[:include_stock_consumption] || stock_consumption_permitted?(repository, my_module)
|
||||
row['stock'][:stock_status] = record.repository_stock_cell&.value&.status
|
||||
end
|
||||
row['stock']['displayWarnings'] = display_stock_warnings?(repository)
|
||||
row['stock'][:stock_status] = record.repository_stock_cell&.value&.status
|
||||
|
||||
row['stock'][:stock_managable] = stock_managable
|
||||
if record.repository.is_a?(RepositorySnapshot)
|
||||
|
@ -136,10 +138,16 @@ module RepositoryDatatableHelper
|
|||
my_module, record.repository, row_id: record.id
|
||||
)
|
||||
end
|
||||
consumed_stock_formatted =
|
||||
number_with_precision(
|
||||
record.consumed_stock,
|
||||
precision: (record.repository.repository_stock_column.metadata['decimals'].to_i || 0),
|
||||
strip_insignificant_zeros: true
|
||||
)
|
||||
row['consumedStock'][:value] = {
|
||||
consumed_stock: record.consumed_stock,
|
||||
consumed_stock_formatted:
|
||||
"#{record.consumed_stock || 0} #{record.repository_stock_value&.repository_stock_unit_item&.data}"
|
||||
"#{consumed_stock_formatted || 0} #{record.repository_stock_value&.repository_stock_unit_item&.data}"
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -170,10 +178,14 @@ module RepositoryDatatableHelper
|
|||
end
|
||||
|
||||
if options[:include_stock_consumption] && repository_snapshot.has_stock_management?
|
||||
stock_present = record.repository_stock_cell.present?
|
||||
row['stock'] = stock_present ? display_cell_value(record.repository_stock_cell, team, repository_snapshot) : {}
|
||||
row['stock'] = if record.repository_stock_cell.present?
|
||||
display_cell_value(record.repository_stock_cell, team, repository_snapshot)
|
||||
else
|
||||
{ value_type: 'RepositoryStockValue' }
|
||||
end
|
||||
|
||||
row['consumedStock'] =
|
||||
if stock_present
|
||||
if record.repository_stock_consumption_cell.present?
|
||||
display_cell_value(record.repository_stock_consumption_cell, team, repository_snapshot)
|
||||
else
|
||||
{}
|
||||
|
@ -262,6 +274,9 @@ module RepositoryDatatableHelper
|
|||
# don't load reminders for archived repositories
|
||||
return [] if repository_rows.blank? || repository.archived?
|
||||
|
||||
# don't load reminders for snapshots
|
||||
return [] if repository.is_a?(RepositorySnapshot)
|
||||
|
||||
repository_rows.active.with_active_reminders(current_user).to_a.pluck(:id).uniq
|
||||
end
|
||||
|
||||
|
@ -277,4 +292,8 @@ module RepositoryDatatableHelper
|
|||
|
||||
true
|
||||
end
|
||||
|
||||
def display_stock_warnings?(repository)
|
||||
!repository.is_a?(RepositorySnapshot)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
window.bwipjs = require('bwip-js');
|
||||
window.Decimal = require('decimal.js');
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-light clear-filters-btn" @click="clearFilters()">
|
||||
<button class="btn btn-light clear-filters-btn prevent-shrink" @click="clearFilters()">
|
||||
<i class="fas fa-times-circle"></i>
|
||||
{{ i18n.t('repositories.show.filters.clear') }}
|
||||
</button>
|
||||
|
@ -36,7 +36,7 @@
|
|||
</div>
|
||||
<div class="footer">
|
||||
<div id="filtersColumnsDropdown" class="dropup filters-columns-dropdown" @click="toggleColumnsFilters">
|
||||
<button class="btn btn-secondary add-filter" >
|
||||
<button class="btn btn-secondary add-filter prevent-shrink" >
|
||||
<i class="fas fa-plus"></i>
|
||||
{{ i18n.t('repositories.show.filters.add_filter') }}
|
||||
</button>
|
||||
|
@ -50,7 +50,7 @@
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
<button @click="$emit('filters:apply')" class="btn btn-primary apply-button">
|
||||
<button @click="$emit('filters:apply')" class="btn btn-primary apply-button prevent-shrink">
|
||||
{{ i18n.t('repositories.show.filters.apply') }}
|
||||
</button>
|
||||
</div>
|
||||
|
|
11
app/jobs/projects_json_export_job.rb
Normal file
11
app/jobs/projects_json_export_job.rb
Normal file
|
@ -0,0 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ProjectsJsonExportJob < ApplicationJob
|
||||
def perform(task_ids, callback, user)
|
||||
projects_json_export_service = ProjectsJsonExportService.new(task_ids,
|
||||
callback,
|
||||
user)
|
||||
projects_json_export_service.generate_data
|
||||
projects_json_export_service.post_request
|
||||
end
|
||||
end
|
|
@ -15,7 +15,8 @@ module ReminderRepositoryCellJoinable
|
|||
).joins( # stock reminders
|
||||
'LEFT OUTER JOIN "repository_stock_values" ON "repository_stock_values"."id" = "repository_cells"."value_id" AND '\
|
||||
'"repository_cells"."value_type" = \'RepositoryStockValue\' AND '\
|
||||
'repository_stock_values.amount <= repository_stock_values.low_stock_threshold'
|
||||
'(repository_stock_values.amount <= repository_stock_values.low_stock_threshold OR '\
|
||||
' repository_stock_values.amount <= 0)'
|
||||
).joins(
|
||||
'LEFT OUTER JOIN "hidden_repository_cell_reminders" ON '\
|
||||
'"repository_cells"."id" = "hidden_repository_cell_reminders"."repository_cell_id" AND '\
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
class MyModule < ApplicationRecord
|
||||
SEARCHABLE_ATTRIBUTES = ['my_modules.name', 'my_modules.description']
|
||||
|
||||
include ActionView::Helpers::NumberHelper
|
||||
include ArchivableModel
|
||||
include SearchableModel
|
||||
include SearchableByNameModel
|
||||
|
@ -310,8 +311,7 @@ class MyModule < ApplicationRecord
|
|||
rows = rows.left_joins(my_module_repository_rows: :repository_stock_unit_item)
|
||||
.select(
|
||||
'repository_rows.*',
|
||||
'my_module_repository_rows.stock_consumption',
|
||||
'repository_stock_unit_items.data AS stock_unit'
|
||||
'my_module_repository_rows.stock_consumption'
|
||||
)
|
||||
end
|
||||
rows.find_each do |row|
|
||||
|
@ -325,7 +325,18 @@ class MyModule < ApplicationRecord
|
|||
consumed_stock = row.repository_stock_consumption_cell&.value&.formatted
|
||||
row_json << (consumed_stock || 0)
|
||||
else
|
||||
row_json << "#{row['stock_consumption'] || 0} #{row['stock_unit']}"
|
||||
consumed_stock_formatted =
|
||||
if row.repository_stock_cell.present?
|
||||
consumed_stock = number_with_precision(
|
||||
row.stock_consumption || 0,
|
||||
precision: (row.repository.repository_stock_column.metadata['decimals'].to_i || 0),
|
||||
strip_insignificant_zeros: true
|
||||
)
|
||||
"#{consumed_stock} #{row.repository_stock_value&.repository_stock_unit_item&.data}"
|
||||
else
|
||||
'-'
|
||||
end
|
||||
row_json << consumed_stock_formatted
|
||||
end
|
||||
end
|
||||
data << row_json
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
class MyModuleRepositoryRow < ApplicationRecord
|
||||
include ActionView::Helpers::NumberHelper
|
||||
|
||||
attr_accessor :last_modified_by
|
||||
attr_accessor :comment
|
||||
attribute :last_modified_by, :integer
|
||||
attribute :comment, :text
|
||||
|
||||
belongs_to :assigned_by,
|
||||
foreign_key: 'assigned_by_id',
|
||||
|
|
|
@ -65,6 +65,8 @@ class RepositoryAssetValue < ApplicationRecord
|
|||
asset.file.attach(io: StringIO.new(Base64.decode64(new_data[:file_data])), filename: new_data[:file_name])
|
||||
end
|
||||
|
||||
asset.file_pdf_preview.purge if asset.file_pdf_preview.attached?
|
||||
|
||||
asset.last_modified_by = user
|
||||
self.last_modified_by = user
|
||||
asset.save! && save!
|
||||
|
|
|
@ -87,7 +87,11 @@ class RepositoryColumn < ApplicationRecord
|
|||
end
|
||||
|
||||
def importable?
|
||||
Extends::REPOSITORY_IMPORTABLE_TYPES.include?(data_type.to_sym)
|
||||
if data_type == 'RepositoryStockValue'
|
||||
RepositoryBase.stock_management_enabled?
|
||||
else
|
||||
Extends::REPOSITORY_IMPORTABLE_TYPES.include?(data_type.to_sym)
|
||||
end
|
||||
end
|
||||
|
||||
def deep_dup
|
||||
|
|
|
@ -14,8 +14,12 @@ class RepositoryStockValue < ApplicationRecord
|
|||
accepts_nested_attributes_for :repository_cell
|
||||
|
||||
validates :repository_cell, presence: true
|
||||
validates :low_stock_threshold, numericality: { greater_than_or_equal_to: 0 }, allow_nil: true
|
||||
|
||||
before_save :update_consumption_stock_units, if: :repository_stock_unit_item_id_changed?
|
||||
after_create do
|
||||
next if is_a?(RepositoryStockConsumptionValue)
|
||||
|
||||
repository_ledger_records.create!(user: created_by,
|
||||
amount: amount,
|
||||
balance: amount,
|
||||
|
@ -182,4 +186,12 @@ class RepositoryStockValue < ApplicationRecord
|
|||
end
|
||||
|
||||
alias export_formatted formatted
|
||||
|
||||
private
|
||||
|
||||
def update_consumption_stock_units
|
||||
repository_cell.repository_row
|
||||
.my_module_repository_rows
|
||||
.update_all(repository_stock_unit_item_id: repository_stock_unit_item_id)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
class Settings < ApplicationRecord
|
||||
def self.instance
|
||||
@instance ||= first
|
||||
@instance ||= new
|
||||
first || new
|
||||
end
|
||||
end
|
||||
|
|
|
@ -27,7 +27,7 @@ Canaid::Permissions.register_for(Asset) do
|
|||
if object.repository_column.repository.is_a?(RepositorySnapshot)
|
||||
false
|
||||
else
|
||||
can_manage_repository?(user, object.repository_column.repository)
|
||||
can_manage_repository_assets?(user, object.repository_column.repository)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -19,7 +19,7 @@ Canaid::Permissions.register_for(Experiment) do
|
|||
# assign/reassign/unassign tags
|
||||
can :manage_experiment do |user, experiment|
|
||||
experiment.permission_granted?(user, ExperimentPermissions::MANAGE) &&
|
||||
experiment.my_modules.all? do |my_module|
|
||||
experiment.my_modules.preload(my_module_status: :my_module_status_implications).all? do |my_module|
|
||||
if my_module.my_module_status
|
||||
my_module.my_module_status.my_module_status_implications.all? { |implication| implication.call(my_module) }
|
||||
else
|
||||
|
@ -72,7 +72,7 @@ Canaid::Permissions.register_for(Experiment) do
|
|||
end
|
||||
|
||||
can :clone_experiment do |user, experiment|
|
||||
experiment.permission_granted?(user, ExperimentPermissions::MANAGE)
|
||||
experiment.permission_granted?(user, ExperimentPermissions::READ)
|
||||
end
|
||||
|
||||
can :move_experiment do |user, experiment|
|
||||
|
|
|
@ -69,6 +69,10 @@ Canaid::Permissions.register_for(Repository) do
|
|||
end
|
||||
end
|
||||
|
||||
can :manage_repository_assets do |user, repository|
|
||||
can_create_repository_rows?(user, repository)
|
||||
end
|
||||
|
||||
# repository: update/delete records
|
||||
can :manage_repository_rows do |user, repository|
|
||||
can_create_repository_rows?(user, repository)
|
||||
|
|
|
@ -7,10 +7,6 @@ Canaid::Permissions.register_for(RepositoryColumn) do
|
|||
managable = repository_column.repository.repository_snapshots.provisioning.none? &&
|
||||
can_create_repository_columns?(user, repository_column.repository)
|
||||
|
||||
if repository_column.data_type == 'RepositoryStockValue'
|
||||
managable = can_manage_repository_stock?(user, repository_column.repository) && managable
|
||||
end
|
||||
|
||||
managable
|
||||
end
|
||||
end
|
||||
|
|
183
app/services/projects_json_export_service.rb
Normal file
183
app/services/projects_json_export_service.rb
Normal file
|
@ -0,0 +1,183 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ProjectsJsonExportService
|
||||
include Canaid::Helpers::PermissionsHelper
|
||||
require 'net/http'
|
||||
|
||||
def initialize(task_ids, callback, user)
|
||||
@user = user
|
||||
@task_ids = task_ids
|
||||
@experiment_ids = MyModule.where(id: @task_ids).pluck(:experiment_id).uniq
|
||||
@project_ids = Experiment.where(id: @experiment_ids).pluck(:project_id).uniq
|
||||
@callback = callback
|
||||
@storage_location = ENV['ACTIVESTORAGE_SERVICE'] || 'local'
|
||||
@request_json = {}
|
||||
end
|
||||
|
||||
def generate_data
|
||||
project_json = []
|
||||
projects = Project.where(id: @project_ids)
|
||||
projects.find_each do |prj|
|
||||
next unless can_read_project?(@user, prj)
|
||||
|
||||
project = prj.as_json(only: %i(id name))
|
||||
experiments = []
|
||||
prj.experiments.find_each do |exp|
|
||||
if @experiment_ids.map(&:to_i).include?(exp.id.to_i)
|
||||
next unless can_read_experiment?(@user, exp)
|
||||
|
||||
experiment = exp.as_json(only: %i(id name description))
|
||||
tasks = []
|
||||
exp.my_modules.where(archived: false).find_each do |tsk|
|
||||
if @task_ids.map(&:to_i).include?(tsk.id.to_i)
|
||||
next unless can_read_my_module?(@user, tsk)
|
||||
|
||||
tasks << task_json(tsk)
|
||||
end
|
||||
end
|
||||
experiment['tasks'] = tasks if tasks.any?
|
||||
experiments << experiment
|
||||
end
|
||||
project['experiments'] = experiments if experiments.any?
|
||||
end
|
||||
project_json << project
|
||||
end
|
||||
|
||||
@request_json['projects'] = project_json
|
||||
end
|
||||
|
||||
def post_request
|
||||
url = URI.parse(@callback)
|
||||
req = Net::HTTP::Post.new(url.request_uri, 'Content-Type': 'application/json;charset=utf-8')
|
||||
Rails.logger.info(@request_json.to_json)
|
||||
req.body = @request_json.to_json
|
||||
http = Net::HTTP.new(url.host, url.port)
|
||||
http.use_ssl = (url.scheme == 'https')
|
||||
http.request(req)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def protocol_json(protocol)
|
||||
protocol_json = protocol.as_json(only: %i(id description))
|
||||
t_m_files = protocol.tiny_mce_assets.map { |asset| tiny_mce_file_json(asset) }
|
||||
protocol_json['tiny_mce_files'] = t_m_files if t_m_files.any?
|
||||
protocol_json
|
||||
end
|
||||
|
||||
def step_json(step)
|
||||
step_json = step.as_json(only: %i(id position name description completed))
|
||||
checklists = []
|
||||
step.checklists.find_each do |cl|
|
||||
checklist = cl.as_json(only: %i(id name))
|
||||
items = []
|
||||
cl.checklist_items.find_each do |cli|
|
||||
item = cli.as_json(only: %i(id position text checked))
|
||||
items << item
|
||||
end
|
||||
checklist['items'] = items if items.any?
|
||||
checklists << checklist
|
||||
end
|
||||
step_json['checklists'] = checklists if checklists.any?
|
||||
files = []
|
||||
step.assets.find_each do |asset|
|
||||
files << asset_file_json(asset)
|
||||
end
|
||||
step_json['files'] = files if files.any?
|
||||
t_m_files = []
|
||||
step.tiny_mce_assets.find_each do |asset|
|
||||
t_m_files << tiny_mce_file_json(asset)
|
||||
end
|
||||
step_json['tiny_mce_files'] = t_m_files if t_m_files.any?
|
||||
tables = []
|
||||
step.tables.find_each do |tbl|
|
||||
table = tbl.as_json(only: %i(id name))
|
||||
table['contents'] = JSON.parse(tbl.contents)['data']
|
||||
tables << table
|
||||
end
|
||||
step_json['tables'] = tables if tables.any?
|
||||
step_json
|
||||
end
|
||||
|
||||
def task_json(task)
|
||||
task_json = task.as_json(only: %i(id name description))
|
||||
t_m_files = task.tiny_mce_assets.map { |asset| tiny_mce_file_json(asset) }
|
||||
task_json['tiny_mce_files'] = t_m_files if t_m_files.any?
|
||||
steps = []
|
||||
task_json['protocols'] = []
|
||||
task.protocols.find_each do |protocol|
|
||||
task_json['protocols'] << protocol_json(protocol)
|
||||
protocol.steps.order(:position).find_each { |stp| steps << step_json(stp) }
|
||||
end
|
||||
task_json['steps'] = steps if steps.any?
|
||||
results = []
|
||||
Rails.logger.info(task.results.to_yaml.to_s)
|
||||
task.results
|
||||
.where(archived: false)
|
||||
.order(created_at: :desc)
|
||||
.find_each { |res| results << result_json(res) }
|
||||
task_json['results'] = results if results.any?
|
||||
task_json
|
||||
end
|
||||
|
||||
def result_json(result)
|
||||
result_json = result.as_json(only: %i(id name))
|
||||
if result.result_text
|
||||
result_json['type'] = 'text'
|
||||
result_json['text'] = result.result_text.text
|
||||
t_m_files = []
|
||||
result.result_text.tiny_mce_assets.find_each do |asset|
|
||||
t_m_files << tiny_mce_file_json(asset)
|
||||
end
|
||||
result_json['tiny_mce_files'] = t_m_files if t_m_files.any?
|
||||
elsif result.asset
|
||||
result_json['type'] = 'file'
|
||||
result_json['bucket'] = ENV['S3_BUCKET']
|
||||
result_json['key'] = ActiveStorage::Blob.service.path_for(result.asset.file.key)
|
||||
result_json['url'] = asset_url(result.asset)
|
||||
elsif result.table
|
||||
result_json['type'] = 'table'
|
||||
result_json['contents'] = JSON.parse(result.table.contents)['data']
|
||||
end
|
||||
result_json
|
||||
end
|
||||
|
||||
def asset_file_json(asset)
|
||||
if ENV['ACTIVESTORAGE_SERVICE'] && ENV['S3_BUCKET']
|
||||
{
|
||||
'storage' => ENV['ACTIVESTORAGE_SERVICE'],
|
||||
'id' => asset.id,
|
||||
'bucket' => ENV['S3_BUCKET'],
|
||||
'key' => ActiveStorage::Blob.service.path_for(asset.file.key),
|
||||
'url' => asset_url(asset)
|
||||
}
|
||||
else
|
||||
{
|
||||
'storage' => 'local',
|
||||
'id' => asset.id,
|
||||
'url' => asset_url(asset)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def tiny_mce_file_json(asset)
|
||||
if ENV['ACTIVESTORAGE_SERVICE'] && ENV['S3_BUCKET']
|
||||
{
|
||||
'storage' => @storage_location,
|
||||
'id' => asset.id,
|
||||
'bucket' => ENV['S3_BUCKET'],
|
||||
'key' => ActiveStorage::Blob.service.path_for(asset.image.key)
|
||||
}
|
||||
else
|
||||
{
|
||||
'storage' => @storage_location,
|
||||
'id' => asset.id,
|
||||
'url' => Rails.application.routes.url_helpers.url_for(asset.image)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def asset_url(asset)
|
||||
ENV['MAIL_SERVER_URL'] + Rails.application.routes.url_helpers.asset_file_url_path(asset)
|
||||
end
|
||||
end
|
|
@ -83,10 +83,7 @@ module ReportActions
|
|||
|
||||
my_module_element = save_element!({ 'my_module_id' => my_module.id }, :my_module, experiment_element)
|
||||
|
||||
@repositories.each do |repository|
|
||||
repository = assigned_repository_or_snapshot(my_module, repository)
|
||||
next unless repository
|
||||
|
||||
my_module.live_and_snapshot_repositories_list.each do |repository|
|
||||
save_element!(
|
||||
{ 'my_module_id' => my_module.id, 'repository_id' => repository.id },
|
||||
:my_module_repository,
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
module Reports::Docx::RepositoryHelper
|
||||
include InputSanitizeHelper
|
||||
include ActionView::Helpers::NumberHelper
|
||||
|
||||
def prepare_row_columns(repository_data, my_module, repository)
|
||||
result = [repository_data[:headers]]
|
||||
|
@ -20,7 +21,11 @@ module Reports::Docx::RepositoryHelper
|
|||
consumed_stock = record.repository_stock_consumption_cell&.value&.formatted || 0
|
||||
cell_values[cell.repository_column_id] = consumed_stock
|
||||
else
|
||||
consumption = record.my_module_repository_rows.find_by(my_module: my_module)&.stock_consumption || 0
|
||||
consumption = number_with_precision(
|
||||
record.my_module_repository_rows.find_by(my_module: my_module)&.stock_consumption || 0,
|
||||
precision: (record.repository.repository_stock_column.metadata['decimals'].to_i || 0),
|
||||
strip_insignificant_zeros: true
|
||||
)
|
||||
unit = cell.value.repository_stock_unit_item&.data
|
||||
cell_values[cell.repository_column_id] = "#{consumption} #{unit}"
|
||||
end
|
||||
|
@ -28,6 +33,9 @@ module Reports::Docx::RepositoryHelper
|
|||
cell_values[cell.repository_column_id] = cell.value.formatted
|
||||
end
|
||||
end
|
||||
if repository.repository_stock_column.present? && record.repository_stock_cell.blank?
|
||||
cell_values[repository.repository_stock_column.id] = '-'
|
||||
end
|
||||
|
||||
repository_data[:custom_columns].each do |column_id|
|
||||
value = cell_values[column_id]
|
||||
|
|
|
@ -71,10 +71,16 @@ module Repositories
|
|||
my_module_repository_row =
|
||||
repository_row.my_module_repository_rows.find { |mrr| mrr.my_module_id == @repository_snapshot.my_module_id }
|
||||
|
||||
stock_unit_item =
|
||||
@repository_snapshot.repository_stock_consumption_column
|
||||
.repository_stock_unit_items
|
||||
.find { |item| item.data == my_module_repository_row.repository_stock_unit_item&.data }
|
||||
stock_unit_item_data =
|
||||
if my_module_repository_row.repository_stock_unit_item.present?
|
||||
my_module_repository_row.repository_stock_unit_item.data
|
||||
else
|
||||
repository_row.repository_stock_cell&.repository_stock_value&.repository_stock_unit_item&.data
|
||||
end
|
||||
|
||||
stock_unit_item = @repository_snapshot.repository_stock_consumption_column
|
||||
.repository_stock_unit_items
|
||||
.find { |item| item.data == stock_unit_item_data }
|
||||
RepositoryStockConsumptionValue.create!(
|
||||
repository_cell_attributes: {
|
||||
repository_column: @repository_snapshot.repository_stock_consumption_column,
|
||||
|
|
|
@ -52,7 +52,7 @@ module SmartAnnotations
|
|||
def generate_rep_snippet(name, object)
|
||||
if object&.repository
|
||||
repository_name = fetch_repository_name(object)
|
||||
"<a href='#{ROUTES.repository_path(object)}' " \
|
||||
"<a href='#{ROUTES.repository_path(object.repository)}' " \
|
||||
"><span class='sa-type'>#{trim_repository_name(repository_name)}</span>" \
|
||||
"#{object.name} #{object.archived? ? I18n.t('atwho.res.archived') : ''}</a>"
|
||||
else
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
<div id="update-canvas"
|
||||
data-can-create-modules="<%= can_manage_experiment?(@experiment) ? "yes" : "no" %>"
|
||||
data-can-edit-modules="<%= can_manage_experiment?(@experiment) ? "yes" : "no" %>"
|
||||
data-can-clone-modules="<%= can_manage_experiment?(@experiment) ? "yes" : "no" %>"
|
||||
data-can-move-modules="<%= can_manage_experiment?(@experiment) ? "yes" : "no" %>"
|
||||
data-can-delete-modules="<%= can_manage_experiment?(@experiment) ? "yes" : "no" %>"
|
||||
data-can-reposition-modules="<%= can_manage_experiment?(@experiment) ? "yes" : "no" %>"
|
||||
data-can-edit-connections="<%= can_manage_experiment?(@experiment) ? "yes" : "no" %>"
|
||||
data-can-create-modules="<%= @experiment_managable ? "yes" : "no" %>"
|
||||
data-can-edit-modules="<%= @experiment_managable ? "yes" : "no" %>"
|
||||
data-can-clone-modules="<%= @experiment_managable ? "yes" : "no" %>"
|
||||
data-can-move-modules="<%= @experiment_managable ? "yes" : "no" %>"
|
||||
data-can-delete-modules="<%= @experiment_managable ? "yes" : "no" %>"
|
||||
data-can-reposition-modules="<%= @experiment_managable ? "yes" : "no" %>"
|
||||
data-can-edit-connections="<%= @experiment_managable ? "yes" : "no" %>"
|
||||
data-unsaved-work-text="<%=t "experiments.canvas.edit.unsaved_work" %>"
|
||||
>
|
||||
<%= bootstrap_form_tag url: canvas_experiment_url, method: "post", html: {class: "canvas-header"} do |f| %>
|
||||
<% if can_manage_experiment?(@experiment) %>
|
||||
<% if @experiment_managable %>
|
||||
<%=link_to "", type: "button", class: "btn btn-primary", id: "canvas-new-module" do %>
|
||||
<span class="hbtn-default">
|
||||
<span class="fas fa-credit-card"></span>
|
||||
|
@ -71,7 +71,7 @@
|
|||
</span>
|
||||
</div>
|
||||
<div id="diagram-container">
|
||||
<% if can_manage_experiment?(@experiment) %>
|
||||
<% if @experiment_managable %>
|
||||
<div id="diagram" class="diagram">
|
||||
<% my_modules.each do |my_module| %>
|
||||
<% if can_read_my_module?(my_module) %>
|
||||
|
@ -85,7 +85,7 @@
|
|||
</div>
|
||||
|
||||
<%-# Since we need to preload modals, we just check permission for experiment, instead of permissions for every module and module group -%>
|
||||
<% if can_manage_experiment?(@experiment) %>
|
||||
<% if @experiment_managable %>
|
||||
<%= render partial: "canvas/edit/modal/new_module", locals: {experiment: @experiment} %>
|
||||
<%= render partial: "canvas/edit/modal/edit_module", locals: {experiment: @experiment } %>
|
||||
<%= render partial: "canvas/edit/modal/move_module", locals: {experiment: @experiment } %>
|
||||
|
|
|
@ -7,12 +7,12 @@
|
|||
<span class="fas fa-tag"></span>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if tags2.count == 0 %>
|
||||
<% if tags2.length.zero? %>
|
||||
<div class="add-tag last"><span class="fas fa-tag"></span></div>
|
||||
<% end %>
|
||||
<% if my_module.tags.count > 0 %>
|
||||
<% if my_module.tags.size.positive? %>
|
||||
<span class="badge badge-indicator">
|
||||
<%= my_module.tags.count %>
|
||||
<%= my_module.tags.size %>
|
||||
</span>
|
||||
<% else %>
|
||||
<span class="badge badge-indicator <%= "invisible" unless can_manage_my_module?(my_module) %>">
|
||||
|
|
|
@ -6,68 +6,23 @@
|
|||
data-module-y="<%= my_module.y %>"
|
||||
data-module-conns="<%= construct_module_connections(my_module) %>">
|
||||
|
||||
<% module_group = my_module.my_module_group %>
|
||||
|
||||
<div class="panel-heading">
|
||||
|
||||
<h3 class="panel-title"><%= my_module.name %></h3>
|
||||
<h3 class="panel-title", title="<%= my_module.name %>"><%= my_module.name %></h3>
|
||||
|
||||
<div class="dropdown pull-right module-options">
|
||||
<div class="dropdown module-options-dropdown pull-right module-options" data-dropdown-menu-path="<%= canvas_dropdown_menu_my_module_path(my_module) %>">
|
||||
<a class="dropdown-toggle" id="<%= my_module.id %>_options" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
|
||||
<span class="fas fa-caret-down" aria-hidden="true"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu custom-dropdown-menu no-scale" aria-labelledby="<%= my_module.id %>_options">
|
||||
<% if can_manage_my_module?(my_module) %>
|
||||
<li>
|
||||
<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>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if can_move_my_module?(my_module) %>
|
||||
<li>
|
||||
<a class="move-module" href="" data-module-id="<%= my_module.id %>"><%= t('experiments.canvas.edit.move_module') %></a>
|
||||
</li>
|
||||
<% end %>
|
||||
<li>
|
||||
<%= link_to t('experiments.canvas.edit.task_access'),
|
||||
can_manage_my_module_users?(my_module) ? edit_access_permissions_project_experiment_my_module_path(my_module.experiment.project, my_module.experiment, my_module) : access_permissions_project_experiment_my_module_path(my_module.experiment.project, my_module.experiment, my_module),
|
||||
data: { action: 'remote-modal'} %>
|
||||
</li>
|
||||
<% if can_archive_my_module?(my_module) %>
|
||||
<li>
|
||||
<a class="delete-module" href="" data-module-id="<%= my_module.id %>"><%= t('experiments.canvas.edit.delete_module') %></a>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if can_manage_experiment?(my_module.experiment) %>
|
||||
<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>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if module_group&.my_modules&.all? { |my_module| can_move_my_module?(my_module) } %>
|
||||
<li>
|
||||
<a class="move-module-group" href="" data-module-id="<%= my_module.id %>"><%= t('experiments.canvas.edit.move_module_group') %></a>
|
||||
</li>
|
||||
<% end %>
|
||||
|
||||
<% if module_group&.my_modules&.all? { |my_module| can_archive_my_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>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<% if can_manage_experiment?(my_module.experiment) %>
|
||||
<div class="panel-body ep">
|
||||
<%= t('experiments.canvas.edit.drag_connections') %>
|
||||
</div>
|
||||
<% end %>
|
||||
<div class="panel-body ep">
|
||||
<%= t('experiments.canvas.edit.drag_connections') %>
|
||||
</div>
|
||||
|
||||
<div class="overlay"></div>
|
||||
|
||||
|
|
41
app/views/canvas/edit/_my_module_dropdown_menu.html.erb
Normal file
41
app/views/canvas/edit/_my_module_dropdown_menu.html.erb
Normal file
|
@ -0,0 +1,41 @@
|
|||
<% if can_manage_my_module?(my_module) %>
|
||||
<li>
|
||||
<a class="edit-module" href="" data-module-id="<%= my_module.id %>"><%= t('experiments.canvas.edit.edit_module') %></a>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if @experiment_managable %>
|
||||
<li>
|
||||
<a class="clone-module" href="" data-module-id="<%= my_module.id %>"><%= t('experiments.canvas.edit.clone_module') %></a>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if can_move_my_module?(my_module) %>
|
||||
<li>
|
||||
<a class="move-module" href="" data-module-id="<%= my_module.id %>"><%= t('experiments.canvas.edit.move_module') %></a>
|
||||
</li>
|
||||
<% end %>
|
||||
<li>
|
||||
<%= link_to t('experiments.canvas.edit.task_access'),
|
||||
can_manage_my_module_users?(my_module) ? edit_access_permissions_project_experiment_my_module_path(my_module.experiment.project, my_module.experiment, my_module) : access_permissions_project_experiment_my_module_path(my_module.experiment.project, my_module.experiment, my_module),
|
||||
data: { action: 'remote-modal'} %>
|
||||
</li>
|
||||
<% if can_archive_my_module?(my_module) %>
|
||||
<li>
|
||||
<a class="delete-module" href="" data-module-id="<%= my_module.id %>"><%= t('experiments.canvas.edit.delete_module') %></a>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if @experiment_managable %>
|
||||
<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>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if @group_my_modules&.all? { |my_module| can_move_my_module?(my_module) } %>
|
||||
<li>
|
||||
<a class="move-module-group" href="" data-module-id="<%= my_module.id %>"><%= t('experiments.canvas.edit.move_module_group') %></a>
|
||||
</li>
|
||||
<% end %>
|
||||
|
||||
<% if @group_my_modules&.all? { |my_module| can_archive_my_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>
|
||||
</li>
|
||||
<% end %>
|
|
@ -41,7 +41,7 @@
|
|||
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">
|
||||
<%= link_to_if can_read_experiment?(my_module.experiment), my_module.name, protocols_my_module_path(my_module), class: 'my-module-title' %>
|
||||
<%= link_to my_module.name, protocols_my_module_path(my_module), title: my_module.name, class: 'my-module-title' %>
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
|
@ -82,41 +82,37 @@
|
|||
|
||||
<div class="panel-footer panel-footer-scinote buttons-container">
|
||||
<ul class="nav nav-tabs nav-tabs-less" role="tablist">
|
||||
<% if can_read_experiment?(my_module.experiment) %>
|
||||
<li role="presentation">
|
||||
<a class="btn btn-link task-card-view-users" href="<%= index_old_my_module_user_my_modules_url(my_module_id: my_module.id, format: :json) %>" aria-controls="<%= my_module.id %>_users" role="tab" data-remote="true">
|
||||
<span class="fas fa-users" aria-hidden="true"></span>
|
||||
<span class="badge badge-indicator users-badge-indicator <%= 'hidden' unless my_module.designated_users.count.positive? %>"
|
||||
data-linked-id="<%= my_module.id %>">
|
||||
<%= my_module.designated_users.count %>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li role="presentation">
|
||||
<a class="btn btn-link task-card-view-activities" href="<%= activities_my_module_url(id: my_module.id) %>" aria-controls="<%= my_module.id %>_activities" role="tab">
|
||||
<span class="fas fa-list" aria-hidden="true"></span>
|
||||
</a>
|
||||
</li>
|
||||
<li role="presentation">
|
||||
<a class="btn btn-link task-card-view-comments" href="<%= my_module_my_module_comments_url(my_module_id: my_module.id, format: :json) %>" aria-controls="<%= my_module.id %>_comments" role="tab" data-remote="true">
|
||||
<span class="fas fa-comment" aria-hidden="true"></span>
|
||||
<span id="comment-counter-<%= my_module.id %>" class="badge badge-indicator comments-badge-indicator <%= 'hidden' unless my_module.task_comments.count.positive? %>"
|
||||
data-linked-id="<%= my_module.id %>">
|
||||
<%= my_module.task_comments.count %>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<% end %>
|
||||
<li role="presentation">
|
||||
<a class="btn btn-link task-card-view-users" href="<%= index_old_my_module_user_my_modules_url(my_module_id: my_module.id, format: :json) %>" aria-controls="<%= my_module.id %>_users" role="tab" data-remote="true">
|
||||
<span class="fas fa-users" aria-hidden="true"></span>
|
||||
<span class="badge badge-indicator users-badge-indicator <%= 'hidden' unless my_module.designated_users_count.positive? %>"
|
||||
data-linked-id="<%= my_module.id %>">
|
||||
<%= my_module.designated_users_count %>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li role="presentation">
|
||||
<a class="btn btn-link task-card-view-activities" href="<%= activities_my_module_url(id: my_module.id) %>" aria-controls="<%= my_module.id %>_activities" role="tab">
|
||||
<span class="fas fa-list" aria-hidden="true"></span>
|
||||
</a>
|
||||
</li>
|
||||
<li role="presentation">
|
||||
<a class="btn btn-link task-card-view-comments" href="<%= my_module_my_module_comments_url(my_module_id: my_module.id, format: :json) %>" aria-controls="<%= my_module.id %>_comments" role="tab" data-remote="true">
|
||||
<span class="fas fa-comment" aria-hidden="true"></span>
|
||||
<span id="comment-counter-<%= my_module.id %>" class="badge badge-indicator comments-badge-indicator <%= 'hidden' unless my_module.task_comments_count.positive? %>"
|
||||
data-linked-id="<%= my_module.id %>">
|
||||
<%= my_module.task_comments_count %>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- Tab panes -->
|
||||
<div class="tab-content">
|
||||
<% if can_read_experiment?(my_module.experiment) %>
|
||||
<div role="tabpanel" class="tab-pane" id="<%= my_module.id %>_info" data-contents="info"></div>
|
||||
<div role="tabpanel" class="tab-pane" id="<%= my_module.id %>_users" data-contents="users"></div>
|
||||
<div role="tabpanel" class="tab-pane" id="<%= my_module.id %>_activities" data-contents="activities"></div>
|
||||
<div role="tabpanel" class="tab-pane" id="<%= my_module.id %>_comments" data-contents="comments"></div>
|
||||
<% end %>
|
||||
<div role="tabpanel" class="tab-pane" id="<%= my_module.id %>_info" data-contents="info"></div>
|
||||
<div role="tabpanel" class="tab-pane" id="<%= my_module.id %>_users" data-contents="users"></div>
|
||||
<div role="tabpanel" class="tab-pane" id="<%= my_module.id %>_activities" data-contents="activities"></div>
|
||||
<div role="tabpanel" class="tab-pane" id="<%= my_module.id %>_comments" data-contents="comments"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">
|
||||
<%= link_to_if can_read_experiment?(my_module.experiment), my_module.name, protocols_my_module_path(my_module) %>
|
||||
<%= link_to_if can_read_experiment?(my_module.experiment), my_module.name, protocols_my_module_path(my_module), title: my_module.name %>
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -10,6 +10,6 @@
|
|||
data-module-y="<%= my_module.y %>"
|
||||
data-module-conns="<%= construct_module_connections(my_module) %>">
|
||||
<span>
|
||||
<%= link_to_if can_read_experiment?(my_module.experiment), my_module.name[0], protocols_my_module_path(my_module) %>
|
||||
<%= link_to_if can_read_experiment?(my_module.experiment), my_module.name[0], protocols_my_module_path(my_module), title: my_module.name %>
|
||||
</span>
|
||||
</div>
|
||||
|
|
|
@ -3,48 +3,64 @@
|
|||
data-id="<%= experiment.id %>">
|
||||
|
||||
<% if can_manage_experiment?(experiment) %>
|
||||
<li><%= link_to t('experiments.edit.label_title'),
|
||||
edit_experiment_url(experiment),
|
||||
remote: true,
|
||||
type: 'button',
|
||||
data: { id: experiment.id },
|
||||
class: 'edit-experiment' %></li>
|
||||
<li>
|
||||
<%= link_to edit_experiment_url(experiment),
|
||||
remote: true,
|
||||
type: 'button',
|
||||
data: { id: experiment.id },
|
||||
class: 'edit-experiment' do %>
|
||||
<i class="fas fa-pen"></i>
|
||||
<span><%= t('experiments.edit.label_title') %></span>
|
||||
<% end %>
|
||||
</li>
|
||||
<% end %>
|
||||
<li data-hook="experiment-actions-second-child"></li>
|
||||
<% if can_clone_experiment?(experiment) %>
|
||||
<li><%= link_to t('experiments.clone.label_title'),
|
||||
clone_modal_experiment_url(experiment),
|
||||
remote: true, type: 'button',
|
||||
class: 'clone-experiment' %>
|
||||
<li>
|
||||
<%= link_to clone_modal_experiment_url(experiment),
|
||||
remote: true, type: 'button',
|
||||
class: 'clone-experiment' do %>
|
||||
<i class="fas fa-copy"></i>
|
||||
<span><%= t('experiments.clone.label_title') %></span>
|
||||
<% end %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if can_move_experiment?(experiment) %>
|
||||
<li><%= link_to t('experiments.move.label_title'),
|
||||
move_modal_experiment_url(experiment),
|
||||
remote: true, type: 'button',
|
||||
class: 'move-experiment'%>
|
||||
<li>
|
||||
<%= link_to move_modal_experiment_url(experiment),
|
||||
remote: true, type: 'button',
|
||||
class: 'move-experiment' do %>
|
||||
<i class="fas fa-arrow-right"></i>
|
||||
<span><%= t('experiments.move.label_title') %></span>
|
||||
<% end %>
|
||||
</li>
|
||||
<% end %>
|
||||
<!-- Set or view user experiment assignments -->
|
||||
<% if can_manage_experiment_users?(experiment) %>
|
||||
<li>
|
||||
<%= link_to edit_access_permissions_project_experiment_path(project, experiment), data: { action: 'remote-modal'} do %>
|
||||
<i class="fas fa-door-open"></i>
|
||||
<span><%= t('experiments.index.experiment_access') %></span>
|
||||
<% end %>
|
||||
</li>
|
||||
<% else %>
|
||||
<li>
|
||||
<%= link_to access_permissions_project_experiment_path(project, experiment), data: { action: 'remote-modal'} do %>
|
||||
<i class="fas fa-door-open"></i>
|
||||
<span><%= t('experiments.index.experiment_access') %></span>
|
||||
<% end %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if can_archive_experiment?(experiment) %>
|
||||
<li><%= link_to t('experiments.archive.label_title'),
|
||||
archive_experiment_url(experiment),
|
||||
<li>
|
||||
<%= link_to archive_experiment_url(experiment),
|
||||
type: 'button',
|
||||
method: :post,
|
||||
data: { confirm: t('experiments.canvas.archive_confirm') } %></li>
|
||||
data: { confirm: t('experiments.canvas.archive_confirm') } do %>
|
||||
<i class="fas fa-archive"></i>
|
||||
<span><%= t('experiments.archive.label_title') %></span>
|
||||
<% end %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if can_restore_experiment?(experiment) %>
|
||||
<% experiment_form = nil %>
|
||||
|
@ -52,6 +68,12 @@
|
|||
<% experiment_form = f %>
|
||||
<%= f.hidden_field :archived, value: false %>
|
||||
<% end %>
|
||||
<li><a href="#" class="form-submit-link" data-turbolinks="false" data-submit-form="<%= experiment_form.options[:html][:id] %>"><%= t "projects.experiment_archive.restore_option" %></a></li>
|
||||
<li><a href="#" class="form-submit-link" data-turbolinks="false" data-submit-form="<%= experiment_form.options[:html][:id] %>">
|
||||
<i class="fas fa-undo"></i><%= t "projects.experiment_archive.restore_option" %></a></li>
|
||||
<% end %>
|
||||
<li class="form-dropdown-item">
|
||||
<div class="form-dropdown-item-info">
|
||||
<small><%= t('experiments.experiment_id') %>: <strong><%= experiment.code %></strong></small>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
<span class="fas fa-pencil-alt"></span>
|
||||
<span class="hidden-xs"><%=t 'experiments.canvas.canvas_edit' %></span>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% if can_manage_experiment?(@experiment) || can_clone_experiment?(@experiment) %>
|
||||
<!-- experiment actions -->
|
||||
<span class="dropdown actions-button">
|
||||
<button class="btn btn-secondary dropdown-toggle" type="button" id="exActionsMenu" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
|
||||
|
|
|
@ -67,18 +67,16 @@
|
|||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if can_manage_project_tags?(@my_module.experiment.project) && can_manage_my_module_tags?(@my_module) %>
|
||||
<div class="pull-right create-new-tag-btn">
|
||||
<%= bootstrap_form_for [@my_module.experiment.project, @new_tag], remote: true, format: :json, html: { class: 'add-tag-form' } do |f| %>
|
||||
<%= hidden_field_tag :my_module_id, @my_module.id %>
|
||||
<%= f.hidden_field :project_id, :value => @my_module.experiment.project.id %>
|
||||
<%= f.hidden_field :name, :value => t("tags.create.new_name") %>
|
||||
<%= f.hidden_field :color, :value => Constants::TAG_COLORS[0] %>
|
||||
<%= f.button class: "btn btn-primary" do %>
|
||||
<span class="fas fa-plus"></span>
|
||||
<span class="hidden-xs"><%=t "experiments.canvas.modal_manage_tags.create_new" %></span>
|
||||
<% end %>
|
||||
<div class="pull-right create-new-tag-btn">
|
||||
<%= bootstrap_form_for [@my_module.experiment.project, @new_tag], remote: true, format: :json, html: { class: 'add-tag-form' } do |f| %>
|
||||
<%= hidden_field_tag :my_module_id, @my_module.id %>
|
||||
<%= f.hidden_field :project_id, :value => @my_module.experiment.project.id %>
|
||||
<%= f.hidden_field :name, :value => t("tags.create.new_name") %>
|
||||
<%= f.hidden_field :color, :value => Constants::TAG_COLORS[0] %>
|
||||
<%= f.button class: "btn btn-primary" do %>
|
||||
<span class="fas fa-plus"></span>
|
||||
<span class="hidden-xs"><%=t "experiments.canvas.modal_manage_tags.create_new" %></span>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
<div class="row mt-3">
|
||||
<div class="col-sm-12">
|
||||
<div class="stock-update-view">
|
||||
<div class="stock-initial-container">
|
||||
<div class="stock-initial-container <%= 'negative' if @stock_value.amount < 0 %>">
|
||||
<span class="subtitle"><%= t('repository_stock_values.manage_modal.current_stock') %></span>
|
||||
<span class="value"><%= @stock_value.formatted_value %></span>
|
||||
<span class="units"><%= @stock_value.repository_stock_unit_item&.data %></span>
|
||||
|
@ -42,7 +42,7 @@
|
|||
<div class="stock-arrow">
|
||||
<i class="fas fa-arrow-right"></i>
|
||||
</div>
|
||||
<div class="stock-final-container">
|
||||
<div class="stock-final-container ">
|
||||
<span class="subtitle"><%= t('repository_stock_values.manage_modal.new_stock') %></span>
|
||||
<span class="value">-</span>
|
||||
<span class="units"><%= @stock_value.repository_stock_unit_item&.data %></span>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<div class="modal" id="myModuleRepositoryFullViewModal" tabindex="-1" role="dialog">
|
||||
<div class="modal" id="myModuleRepositoryFullViewModal" data-keyboard="false" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
|
|
|
@ -53,11 +53,11 @@
|
|||
</span>
|
||||
|
||||
<span id="saveCancel" data-toggle="buttons" style="display:none">
|
||||
<button type="button" class="btn btn-success" id="saveRecord" data-view-mode="active">
|
||||
<button type="button" class="btn btn-success prevent-shrink" id="saveRecord" data-view-mode="active">
|
||||
<span class="fas fa-save"></span>
|
||||
<%= t("repositories.save_record") %>
|
||||
</button>
|
||||
<button type="button" class="btn btn-light" id="cancelSave" data-view-mode="active">
|
||||
<button type="button" class="btn btn-light prevent-shrink" id="cancelSave" data-view-mode="active">
|
||||
<span class="fas fa-times-circle"></span>
|
||||
<%= t("repositories.cancel_save") %>
|
||||
</button>
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<div class="repository-cog dropdown hidden" id="saveRepositoryFilters">
|
||||
<button type="button"
|
||||
class="btn btn-default"
|
||||
class="btn btn-light auto-shrink-button"
|
||||
data-toggle="dropdown"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="true">
|
||||
<span class="fas fa-save"></span>
|
||||
<span class="hidden-xs"><%= t("repositories.show.filters.save_filters") %></span>
|
||||
<span class="caret"></span>
|
||||
<span class="hidden-xs button-text"><%= t("repositories.show.filters.save_filters") %></span>
|
||||
<span class="caret button-text"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li id="newFilterLink">
|
||||
|
|
|
@ -82,7 +82,7 @@
|
|||
<option data-create-url="<%= repository_repository_columns_stock_columns_path(@repository) %>"
|
||||
data-edit-url="<%= repository_repository_columns_stock_column_path(@repository, @repository_column) unless @repository_column.new_record? %>"
|
||||
value="RepositoryStockValue"
|
||||
<% if @repository.repository_columns.where(data_type: 'RepositoryStockValue').any? %>
|
||||
<% if @repository.repository_stock_column.present? %>
|
||||
data-params="<%= {
|
||||
optionClass: 'disabled-option',
|
||||
text_description: 'Only one per inventory allowed'
|
||||
|
@ -91,6 +91,12 @@
|
|||
<%= 'selected' if @repository_column.repository_stock_value? %> >
|
||||
<%= t('libraries.manange_modal_column.select.repository_stock_value') %>
|
||||
</option>
|
||||
<% elsif @repository_column.repository_stock_value? && @repository_column.persisted? %>
|
||||
<option value="RepositoryTextValue" class="disabled-option"
|
||||
data-params="<%= { optionClass: 'disabled-option' }.to_json %>"
|
||||
selected>
|
||||
<%= t('libraries.manange_modal_column.select.repository_stock_value') %>
|
||||
</option>
|
||||
<% end %>
|
||||
<option data-delimiter=true></option>
|
||||
|
||||
|
|
|
@ -54,10 +54,9 @@
|
|||
<%= t('libraries.manange_modal_column.datetime_type.reminder_message') %>
|
||||
</label>
|
||||
<div class="col-sm-9">
|
||||
<div class="sci-input-container">
|
||||
<input type="text" class="sci-input-field reminder-message"
|
||||
<div class="sci-input-container" data-error-text="<%= t('libraries.manange_modal_column.datetime_type.reminder_message_limit') %>">
|
||||
<input id="date-reminder-message" type="text" class="sci-input-field reminder-message"
|
||||
placeholder="<%= t('libraries.manange_modal_column.datetime_type.enter_reminder_message')%>"
|
||||
maxlength="<%= Constants::NAME_MAX_LENGTH %>"
|
||||
value="<%= column&.metadata['reminder_message'] %>">
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -54,10 +54,9 @@
|
|||
<%= t('libraries.manange_modal_column.datetime_type.reminder_message') %>
|
||||
</label>
|
||||
<div class="col-sm-9">
|
||||
<div class="sci-input-container">
|
||||
<input type="text" class="sci-input-field reminder-message"
|
||||
<div class="sci-input-container" data-error-text="<%= t('libraries.manange_modal_column.datetime_type.reminder_message_limit') %>">
|
||||
<input id="datetime-reminder-message" type="text" class="sci-input-field reminder-message"
|
||||
placeholder="<%= t('libraries.manange_modal_column.datetime_type.enter_reminder_message')%>"
|
||||
maxlength="<%= Constants::NAME_MAX_LENGTH %>"
|
||||
value="<%= column&.metadata['reminder_message'] %>">
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -64,13 +64,12 @@
|
|||
<% if can_read_experiment?(@my_module.experiment) %>
|
||||
<li id="steps-nav-tab" class="<%= "active" if is_module_protocols? %>">
|
||||
<a href="<%= protocols_my_module_url(@my_module) %>" title="<%=t "nav2.modules.steps" %>">
|
||||
<span class="hidden-xs"><%=t "nav2.modules.steps" %></span>
|
||||
<span class="hidden-xs hidden-lg fas fa-arrow-circle-right"></span>
|
||||
<%=t "nav2.modules.steps" %>
|
||||
</a>
|
||||
</li>
|
||||
<li id="results-nav-tab" class="<%= "active" if is_module_results? %>">
|
||||
<a href="<%= results_my_module_url(@my_module) %>" title="<%=t "nav2.modules.results" %>">
|
||||
<span class="hidden-xs"><%=t "nav2.modules.results" %></span>
|
||||
<%=t "nav2.modules.results" %>
|
||||
<% if @my_module.results.size.positive? %>
|
||||
<sup class="navigation-results-counter"><%= @my_module.results.size %></sup>
|
||||
<% end %>
|
||||
|
@ -79,8 +78,7 @@
|
|||
</li>
|
||||
<li id="activities-nav-tab" class="<%= "active" if is_module_activities? %>">
|
||||
<a href="<%= activities_my_module_url(@my_module) %>" title="<%=t "nav2.modules.activities" %>">
|
||||
<span class="hidden-xs"><%=t "nav2.modules.activities" %></span>
|
||||
<span class="hidden-xs hidden-lg fas fa-list"></span>
|
||||
<%=t "nav2.modules.activities" %>
|
||||
</a>
|
||||
</li>
|
||||
<% end %>
|
||||
|
@ -89,8 +87,7 @@
|
|||
<% if can_read_experiment?(@my_module.experiment) && !@my_module.archived_branch? %>
|
||||
<li id="archive-nav-tab" class="<%= "active" if is_module_archive? %>">
|
||||
<a href="<%= archive_my_module_url(@my_module) %>" title="<%= t'nav2.modules.archive' %>">
|
||||
<span class="hidden-xs"><%=t "nav2.modules.archive" %></span>
|
||||
<span class="hidden-xs hidden-lg fas fa-briefcase"></span>
|
||||
<%=t "nav2.modules.archive" %>
|
||||
</a>
|
||||
</li>
|
||||
<% end %>
|
||||
|
|
|
@ -180,6 +180,8 @@ en:
|
|||
creates_cycle: "mustn't create cycle"
|
||||
errors:
|
||||
general: "Something went wrong."
|
||||
storage:
|
||||
limit_reached: "Storage limit has been reached."
|
||||
helpers:
|
||||
label:
|
||||
team:
|
||||
|
@ -1069,7 +1071,7 @@ en:
|
|||
open_mobile_app: "Open mobile app"
|
||||
status_error:
|
||||
general: "Status transition failed"
|
||||
repository_snapshot: "Snapshot failed in %{repository}"
|
||||
repository_snapshot: "Snapshot failed in %{repository} inventory"
|
||||
experiments:
|
||||
id: "ID"
|
||||
experiment_id: "Experiment ID"
|
||||
|
@ -1096,7 +1098,7 @@ en:
|
|||
more: "more"
|
||||
index:
|
||||
edit_option: "Edit details"
|
||||
clone_option: "Duplicate (as template)"
|
||||
clone_option: "Duplicate as template"
|
||||
move_option: "Move"
|
||||
archive_option: "Archive"
|
||||
archive_confirm: "Are you sure you want to archive this project?"
|
||||
|
@ -1138,11 +1140,11 @@ en:
|
|||
success_flash: "<strong>%{number}</strong> experiment(s) successfully restored."
|
||||
error_flash: "Failed to restore experiment(s)."
|
||||
clone:
|
||||
modal_title: 'Copy experiment %{experiment} as template'
|
||||
label_title: 'Copy as template'
|
||||
modal_submit: 'Copy'
|
||||
success_flash: 'Successfully copied experiment %{experiment} as template.'
|
||||
error_flash: 'Could not copy the experiment as template.'
|
||||
modal_title: 'Duplicate experiment %{experiment} as template'
|
||||
label_title: 'Duplicate as template'
|
||||
modal_submit: 'Duplicate'
|
||||
success_flash: 'Successfully duplicated experiment %{experiment} as template.'
|
||||
error_flash: 'Could not duplicate the experiment as template.'
|
||||
current_project: '(current project)'
|
||||
move:
|
||||
modal_title: 'Move experiment %{experiment}'
|
||||
|
@ -1731,6 +1733,7 @@ en:
|
|||
amount_placeholder: "Enter amount"
|
||||
amount_placeholder_new: "100, 2000, ..."
|
||||
amount_error: "Enter an amount"
|
||||
negative_error: "Negative values are not allowed."
|
||||
unit: "Unit"
|
||||
unit_prompt: "Select unit"
|
||||
unit_error: "Select a unit"
|
||||
|
@ -1813,6 +1816,7 @@ en:
|
|||
reminder_message: 'Message (optional)'
|
||||
enter_reminder_message: 'Enter a reminder message'
|
||||
range_label: 'Range'
|
||||
reminder_message_limit: "Maximum number of characters reached (255)"
|
||||
stock_type:
|
||||
multiple_options: 'selected'
|
||||
all_options: 'All options'
|
||||
|
@ -1904,7 +1908,7 @@ en:
|
|||
stock_low_html: "Only <strong>%{stock_formated}</strong> left."
|
||||
stock_empty: "There is no stock left."
|
||||
date_reminder: "Date reminder."
|
||||
date_expiration_html: "This item is expiring in <strong>%{date_expiration}</strong>"
|
||||
date_expiration_html: "This item is expiring in <strong>%{date_expiration}</strong>."
|
||||
item_expired: "This item has expired."
|
||||
day: "day"
|
||||
label_printers:
|
||||
|
@ -2093,8 +2097,8 @@ en:
|
|||
teams: "Teams"
|
||||
webhooks: "Webhooks"
|
||||
account_nav:
|
||||
profile: "Profile"
|
||||
preferences: "Preferences"
|
||||
profile: "My profile"
|
||||
preferences: "My preferences"
|
||||
addons: "Add-ons"
|
||||
connected_accounts: "Connected Accounts"
|
||||
account:
|
||||
|
@ -2706,6 +2710,8 @@ en:
|
|||
my_module_comment_annotation_message_html: "Project: %{project} | Experiment: %{experiment} | Task: %{my_module}"
|
||||
my_module_protocol_annotation_title: "%{user} mentioned you in a protocol description on task %{my_module}."
|
||||
my_module_protocol_annotation_message_html: "Project: %{project} | Experiment: %{experiment} | Task: %{my_module}"
|
||||
my_module_consumption_comment_annotation_title: "%{user} mentioned you in a comment on item consumption of item %{repository_item} from inventory %{repository}"
|
||||
my_module_consumption_comment_annotation_message_html: "Project: %{project} | Experiment: %{experiment} | Task: %{my_module}"
|
||||
step_comment_annotation_title: "%{user} mentioned you in a comment on step %{step}."
|
||||
step_description_title: "%{user} mentioned you in a description on step %{step}."
|
||||
checklist_title: "%{user} mentioned you in a checklist on step %{step}."
|
||||
|
@ -3063,6 +3069,12 @@ en:
|
|||
detail: "Text contains reference to nonexisting TinyMCE image"
|
||||
result_wrong_tinymce:
|
||||
detail: "Image reference not found in the text"
|
||||
service:
|
||||
errors:
|
||||
missing_task_ids: "Missing task_ids"
|
||||
callback_missing: "Missing callback"
|
||||
url:
|
||||
not_valid: "Not valid URL"
|
||||
|
||||
|
||||
Add: "Add"
|
||||
|
|
|
@ -205,10 +205,10 @@ en:
|
|||
register_molecule_on_step_html: "%{user} registered molecule %{asset_name} on protocol's step %{step_position} %{step} on task %{my_module}."
|
||||
register_molecule_on_result_html: "%{user} registered molecule %{asset_name} on result %{result}."
|
||||
register_molecule_on_step_in_repository_html: "%{user} registered molecule %{asset_name} on protocol %{protocol}'s step %{step_position} %{step}."
|
||||
inventory_item_stock_set_html: "%{user} set total stock for %{repository_row} to %{new_amount} %{unit} in %{repository} \n%{comment}"
|
||||
inventory_item_stock_add_html: "%{user} added %{change_amount} %{unit} of stock to a total of %{new_amount} %{unit} for %{repository_row} in %{repository} \n%{comment}"
|
||||
inventory_item_stock_remove_html: "%{user} removed %{change_amount} %{unit} of stock to a total of %{new_amount} %{unit} for %{repository_row} in %{repository} \n%{comment}"
|
||||
task_inventory_item_stock_consumed_html: "%{user} changed consumption of %{repository_row} from %{stock_consumption_was} %{unit} to %{stock_consumption} %{unit} in %{my_module} \n%{comment}"
|
||||
inventory_item_stock_set_html: "%{user} set total stock for inventory item %{repository_row} to %{new_amount} %{unit} in inventory %{repository} \n%{comment}"
|
||||
inventory_item_stock_add_html: "%{user} added %{change_amount} %{unit} of stock to a total %{new_amount} %{unit} for inventory item %{repository_row} in inventory %{repository} \n%{comment}"
|
||||
inventory_item_stock_remove_html: "%{user} removed %{change_amount} %{unit} of stock to a total %{new_amount} %{unit} for inventory item %{repository_row} in inventory %{repository} \n%{comment}"
|
||||
task_inventory_item_stock_consumed_html: "%{user} changed consumption of inventory item %{repository_row} from %{stock_consumption_was} %{unit} to %{stock_consumption} %{unit} on task %{my_module} \n%{comment}"
|
||||
task_steps_rearranged_html: "%{user} rearranged protocol's steps on task %{my_module}"
|
||||
task_step_content_rearranged_html: "%{user} rearranged content of protocol's step %{step_position} <strong>%{step}</strong> on task %{my_module}"
|
||||
task_step_file_added_html: "%{user} added file <strong>%{file}</strong> to protocol's step %{step_position} <strong>%{step}</strong> on task %{my_module}"
|
||||
|
|
|
@ -419,6 +419,7 @@ Rails.application.routes.draw do
|
|||
# AJAX popup accessed from full-zoom canvas for single module,
|
||||
# as well as full activities view (HTML) for single module
|
||||
get 'description'
|
||||
get 'canvas_dropdown_menu'
|
||||
get 'activities'
|
||||
post 'activities'
|
||||
get 'activities_tab' # Activities in tab view for single module
|
||||
|
@ -713,6 +714,7 @@ Rails.application.routes.draw do
|
|||
get 'health', to: 'api#health'
|
||||
get 'status', to: 'api#status'
|
||||
namespace :service do
|
||||
post 'projects_json_export', to: 'projects_json_export#projects_json_export'
|
||||
resources :teams, except: %i(index new create show edit update destroy) do
|
||||
post 'clone_experiment' => 'experiments#clone'
|
||||
end
|
||||
|
|
|
@ -24,10 +24,15 @@ class CreateLabelTemplates < ActiveRecord::Migration[6.1]
|
|||
content:
|
||||
<<~HEREDOC
|
||||
^XA
|
||||
^MTT
|
||||
^MUD,300,300
|
||||
^PR2
|
||||
^MD30
|
||||
^LH20,20
|
||||
^PW310
|
||||
^CF0,23
|
||||
^FO0,0^FD{{item_id}}^FS
|
||||
^FO0,7^BQN,2,4^FDMA\{{item_id}}^FS
|
||||
^FO0,20^BQN,2,4^FDMA,{{item_id}}^FS
|
||||
^FO95,30^FB180,4,0,L^FD{{item_name}}^FS^FS
|
||||
^XZ
|
||||
HEREDOC
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
"compression-webpack-plugin": "^1.1.11",
|
||||
"croppie": "^2.6.4",
|
||||
"css-loader": "2.1.1",
|
||||
"decimal.js": "^10.3.1",
|
||||
"extract-text-webpack-plugin": "^3.0.2",
|
||||
"fabric": "1.6.7",
|
||||
"file-loader": "^4.0.0",
|
||||
|
|
11
yarn.lock
11
yarn.lock
|
@ -3262,6 +3262,11 @@ decamelize@^1.1.1, decamelize@^1.1.2, decamelize@^1.2.0:
|
|||
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
|
||||
integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
|
||||
|
||||
decimal.js@^10.3.1:
|
||||
version "10.3.1"
|
||||
resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.3.1.tgz#d8c3a444a9c6774ba60ca6ad7261c3a94fd5e783"
|
||||
integrity sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==
|
||||
|
||||
decode-uri-component@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
|
||||
|
@ -4055,9 +4060,9 @@ events@^3.2.0:
|
|||
integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
|
||||
|
||||
eventsource@^1.0.7:
|
||||
version "1.0.7"
|
||||
resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-1.0.7.tgz#8fbc72c93fcd34088090bc0a4e64f4b5cee6d8d0"
|
||||
integrity sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-1.1.1.tgz#4544a35a57d7120fba4fa4c86cb4023b2c09df2f"
|
||||
integrity sha512-qV5ZC0h7jYIAOhArFJgSfdyz6rALJyb270714o7ZtNnw2WSJ+eexhKtE0O8LYPRsHZHf2osHKZBxGPvm3kPkCA==
|
||||
dependencies:
|
||||
original "^1.0.0"
|
||||
|
||||
|
|
Loading…
Reference in a new issue