mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-02-28 09:43:01 +08:00
Merge branch 'master' of https://github.com/biosistemika/scinote-web into zd_SCI_1336
This commit is contained in:
commit
bad52ceff1
67 changed files with 1283 additions and 487 deletions
GemfileGemfile.lockMakefile
app
assets
javascripts
my_modules
protocols
reports
repositories
results
samples
sitewide
stylesheets
controllers
my_modules_controller.rbrepositories_controller.rbrepository_columns_controller.rbrepository_rows_controller.rbresult_assets_controller.rbsteps_controller.rbteams_controller.rb
datatables
helpers
models
views
my_modules
protocols
reports/elements
_my_module_activity_element.html.erb_my_module_element.html.erb_my_module_repository_element.html.erb_my_module_result_asset_element.html.erb_my_module_result_table_element.html.erb_my_module_result_text_element.html.erb_my_module_samples_element.html.erb_my_module_step_element.html.erb_project_header_element.html.erb_result_comments_element.html.erb_step_asset_element.html.erb_step_checklist_element.html.erb_step_comments_element.html.erb_step_table_element.html.erb
repositories
result_assets
samples
shared
steps
config
2
Gemfile
2
Gemfile
|
@ -55,7 +55,7 @@ gem 'faker' # Generate fake data
|
|||
gem 'auto_strip_attributes', '~> 2.1' # Removes unnecessary whitespaces from ActiveRecord or ActiveModel attributes
|
||||
gem 'deface', '~> 1.0'
|
||||
gem 'nokogiri' # HTML/XML parser
|
||||
gem 'sneaky-save', git: 'git://github.com/einzige/sneaky-save.git'
|
||||
gem 'sneaky-save', git: 'https://github.com/einzige/sneaky-save'
|
||||
gem 'rails_autolink', '~> 1.1', '>= 1.1.6'
|
||||
gem 'delayed_paperclip'
|
||||
gem 'rubyzip'
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
GIT
|
||||
remote: git://github.com/einzige/sneaky-save.git
|
||||
revision: 03866e838f62a4b13e15784974fcc13e14cd9502
|
||||
remote: https://github.com/einzige/sneaky-save
|
||||
revision: e7c77674abe74d598dfd58db7c680dd85936f207
|
||||
specs:
|
||||
sneaky-save (0.1.1)
|
||||
sneaky-save (0.1.2)
|
||||
activerecord (>= 3.2.0)
|
||||
|
||||
GEM
|
||||
|
|
2
Makefile
2
Makefile
|
@ -1,5 +1,5 @@
|
|||
APP_HOME="/usr/src/app"
|
||||
DB_IP=$(shell docker inspect web_db_1 | grep -m 1 "\"IPAddress\": " | awk '{ match($$0, /"IPAddress": "([0-9\.]*)",/, a); print a[1] }')
|
||||
DB_IP=$(shell docker inspect scinote_db_development | grep "\"IPAddress\": " | awk '{ match($$0, /"IPAddress": "([0-9\.]*)",/, a); print a[1] }')
|
||||
|
||||
define PRODUCTION_CONFIG_BODY
|
||||
SECRET_KEY_BASE=$(shell openssl rand -hex 64)
|
||||
|
|
|
@ -157,23 +157,6 @@
|
|||
$form.clearFormErrors();
|
||||
|
||||
switch(resultTypeEnum) {
|
||||
case ResultTypeEnum.FILE:
|
||||
var $nameInput = $form.find('#result_name');
|
||||
var nameValid = textValidator(ev, $nameInput, 0,
|
||||
<%= Constants::NAME_MAX_LENGTH %>);
|
||||
var $fileInput = $form.find('#result_asset_attributes_file');
|
||||
var filesValid = true;
|
||||
if ($fileInput.val()) {
|
||||
filesValid = filesValidator(ev, $fileInput, FileTypeEnum.FILE,
|
||||
editMode);
|
||||
}
|
||||
|
||||
if(nameValid && filesValid) {
|
||||
// Local file uploading
|
||||
animateSpinner();
|
||||
|
||||
}
|
||||
break;
|
||||
case ResultTypeEnum.TABLE:
|
||||
var $nameInput = $form.find('#result_name');
|
||||
var nameValid = textValidator(ev, $nameInput, 0,
|
||||
|
|
|
@ -214,23 +214,6 @@
|
|||
$(e.target).find("input[type='file']").val("");
|
||||
}
|
||||
});
|
||||
|
||||
// Add hidden fields for tables
|
||||
$form.submit(function(){
|
||||
$(this).find("[data-role='editable-table']").each(function() {
|
||||
var hot = $(this).find(".hot").handsontable('getInstance');
|
||||
var contents = $(this).find('.hot-contents');
|
||||
var data = JSON.stringify({data: hot.getData()});
|
||||
contents.attr("value", data);
|
||||
});
|
||||
|
||||
setTimeout(function() {
|
||||
initStepsComments();
|
||||
animateSpinner(null, false);
|
||||
SmartAnnotation.preventPropagation('.atwho-user-popover');
|
||||
}, 1000);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
// Init ajax success/error for edit form
|
||||
|
@ -279,49 +262,6 @@
|
|||
});
|
||||
}
|
||||
|
||||
function formNewAjax($form) {
|
||||
$form
|
||||
.on("ajax:beforeSend", function () {
|
||||
$(".nested_step_checklists ul").each(function () {
|
||||
reorderCheckboxData(this);
|
||||
});
|
||||
})
|
||||
.on("ajax:success", function(e, data) {
|
||||
$(this).after(data.html);
|
||||
var $new_step = $(this).next();
|
||||
$(this).remove();
|
||||
|
||||
initCallBacks();
|
||||
initHandsOnTable($new_step);
|
||||
expandStep($new_step);
|
||||
toggleButtons(true);
|
||||
SmartAnnotation.preventPropagation('.atwho-user-popover');
|
||||
|
||||
//Rerender tables
|
||||
$new_step.find("div.step-result-hot-table").each(function() {
|
||||
$(this).handsontable("render");
|
||||
});
|
||||
animateSpinner(null, false);
|
||||
setupAssetsLoading();
|
||||
})
|
||||
.on("ajax:error", function(e, xhr, status, error) {
|
||||
$(this).after(xhr.responseJSON.html);
|
||||
var $form = $(this).next();
|
||||
$(this).remove();
|
||||
|
||||
$errInput = $form.find(".form-group.has-error").first().find("input");
|
||||
renderFormError(e, $errInput);
|
||||
|
||||
formCallback($form);
|
||||
formNewAjax($form);
|
||||
applyCancelOnNew();
|
||||
animateSpinner(null, false);
|
||||
|
||||
TinyMCE.destroyAll();
|
||||
SmartAnnotation.preventPropagation('.atwho-user-popover');
|
||||
});
|
||||
}
|
||||
|
||||
function toggleButtons(show) {
|
||||
if (show) {
|
||||
$("[data-action='new-step']").show();
|
||||
|
@ -562,7 +502,6 @@
|
|||
scrollTop: $(document).height() - $(window).height()
|
||||
});
|
||||
formCallback($form);
|
||||
formNewAjax($form);
|
||||
applyCancelOnNew();
|
||||
toggleButtons(false);
|
||||
initializeCheckboxSorting();
|
||||
|
@ -588,13 +527,13 @@
|
|||
// experience is improved
|
||||
global.processStep = function processStep(ev, editMode) {
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
ev.stopImmediatePropagation();
|
||||
|
||||
var $form = $(ev.target.form);
|
||||
$form.clearFormErrors();
|
||||
$form.removeBlankFileForms();
|
||||
|
||||
var $fileInputs = $form.find("input[type=file]");
|
||||
var filesValid = filesValidator(ev, $fileInputs, FileTypeEnum.FILE);
|
||||
var $checklists = $form.find(".nested_step_checklists");
|
||||
var checklistsValid = checklistsValidator(ev, $checklists, editMode);
|
||||
var $nameInput = $form.find("#step_name");
|
||||
|
@ -604,8 +543,73 @@
|
|||
var descriptionValid = textValidator(ev, $descrTextarea, 0,
|
||||
<%= Constants::TEXT_MAX_LENGTH %>);
|
||||
|
||||
if (filesValid && checklistsValid && nameValid && descriptionValid) {
|
||||
// Local file uploading
|
||||
if (DragNDropSteps.filesStatus() &&
|
||||
checklistsValid &&
|
||||
nameValid &&
|
||||
descriptionValid) {
|
||||
|
||||
$form.find("[data-role='editable-table']").each(function() {
|
||||
var hot = $(this).find(".hot").handsontable('getInstance');
|
||||
var contents = $(this).find('.hot-contents');
|
||||
var data = JSON.stringify({data: hot.getData()});
|
||||
contents.attr("value", data);
|
||||
});
|
||||
|
||||
setTimeout(function() {
|
||||
initStepsComments();
|
||||
SmartAnnotation.preventPropagation('.atwho-user-popover');
|
||||
}, 1000);
|
||||
|
||||
animateSpinner(null, true);
|
||||
var data = DragNDropSteps.appendFilesToForm(ev);
|
||||
data.append('step[description]', TinyMCE.getContent());
|
||||
$.ajax({
|
||||
url: $form.attr('action'),
|
||||
method: 'POST',
|
||||
data: data,
|
||||
contentType: false,
|
||||
processData: false,
|
||||
beforeSend: function() {
|
||||
$(".nested_step_checklists ul").each(function () {
|
||||
reorderCheckboxData(this);
|
||||
});
|
||||
},
|
||||
success: function(data) {
|
||||
$($form.closest('.well')).after(data.html);
|
||||
var $new_step = $($form.closest('.well')).next();
|
||||
$($form.closest('.well')).remove();
|
||||
|
||||
initCallBacks();
|
||||
initHandsOnTable($new_step);
|
||||
expandStep($new_step);
|
||||
toggleButtons(true);
|
||||
SmartAnnotation.preventPropagation('.atwho-user-popover');
|
||||
|
||||
//Rerender tables
|
||||
$new_step.find("div.step-result-hot-table").each(function() {
|
||||
$(this).handsontable("render");
|
||||
});
|
||||
animateSpinner(null, false);
|
||||
setupAssetsLoading();
|
||||
},
|
||||
error: function(e) {
|
||||
$form.after(xhr.responseJSON.html);
|
||||
var $new_form = $form.next();
|
||||
$form.remove();
|
||||
|
||||
$errInput = $new_form.find(".form-group.has-error")
|
||||
.first()
|
||||
.find("input");
|
||||
renderFormError(e, $errInput);
|
||||
|
||||
formCallback($form);
|
||||
applyCancelOnNew();
|
||||
animateSpinner(null, false);
|
||||
|
||||
TinyMCE.destroyAll();
|
||||
SmartAnnotation.preventPropagation('.atwho-user-popover');
|
||||
}
|
||||
});
|
||||
newStepHandler();
|
||||
}
|
||||
}
|
||||
|
@ -635,8 +639,9 @@
|
|||
function renderTable(table) {
|
||||
$(table).handsontable("render");
|
||||
// Yet another dirty hack to solve HandsOnTable problems
|
||||
if (parseInt($(table).css("height"), 10) < parseInt($(table).css("max-height"), 10) - 30) {
|
||||
$(table).find(".ht_master .wtHolder").css("height", "100%");
|
||||
if (parseInt($(table).css('height'), 10) < parseInt($(table).css('max-height'), 10) - 30) {
|
||||
$(table).find('.ht_master .wtHolder').css({ 'height': '100%',
|
||||
'width': '100%' });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -672,4 +677,5 @@
|
|||
});
|
||||
})
|
||||
|
||||
global.initHandsOnTable = initHandsOnTable;
|
||||
})(window);
|
||||
|
|
|
@ -564,7 +564,7 @@ function initSidebarElement(reportEl) {
|
|||
var type = reportEl.data("type");
|
||||
var name = reportEl.data("name");
|
||||
var scrollId = reportEl.data("scroll-id");
|
||||
var iconClass = "glyphicon " + reportEl.data("icon-class");
|
||||
var iconClass = reportEl.data("icon-class");
|
||||
|
||||
// Generate list element
|
||||
var newLi = $(document.createElement("li"));
|
||||
|
|
7
app/assets/javascripts/repositories/edit.js
Normal file
7
app/assets/javascripts/repositories/edit.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
(function() {
|
||||
'use strict';
|
||||
|
||||
$('.delete-repo-option').initializeModal('#delete-repo-modal');
|
||||
$('.rename-repo-option').initializeModal('#rename-repo-modal');
|
||||
$('.copy-repo-option').initializeModal('#copy-repo-modal');
|
||||
})();
|
|
@ -1,49 +1,35 @@
|
|||
//= require repositories/import/records_importer.js
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
function showNewRepository() {
|
||||
$('#create-repo-modal').on('ajax:success', function(data) {
|
||||
var location = data.url;
|
||||
window.location.replace(location);
|
||||
function initImportRecordsModal() {
|
||||
$('#importRecordsButton').off().on('click', function() {
|
||||
$('#modal-import-records').modal('show');
|
||||
_initParseRecordsModal();
|
||||
});
|
||||
}
|
||||
|
||||
function initCreateRepository() {
|
||||
$('.create-repository').off().on('click', function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
e.stopImmediatePropagation();
|
||||
$.ajax({
|
||||
url: $(this).attr('href'),
|
||||
type: 'GET',
|
||||
dataType: 'json',
|
||||
success: function(data) {
|
||||
$(data.html).appendTo('body').promise().done(function() {
|
||||
$('#create-repo-modal').modal('show');
|
||||
});
|
||||
},
|
||||
error: function() {
|
||||
location.reload();
|
||||
}
|
||||
})
|
||||
function _initParseRecordsModal() {
|
||||
$('#form-records-file').on('ajax:success', function(ev, data) {
|
||||
$('#modal-import-records').modal('hide');
|
||||
$(data.html).appendTo('body').promise().done(function() {
|
||||
$('#parse-records_modal').modal('show');
|
||||
repositoryRecordsImporter();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function loadRepositoryTab() {
|
||||
var param, pane;
|
||||
var param;
|
||||
$('#repository-tabs a').on("click", function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
e.stopImmediatePropagation();
|
||||
pane = $(this);
|
||||
var pane = $(this);
|
||||
$.ajax({
|
||||
url: pane.attr('data-url'),
|
||||
type: 'GET',
|
||||
dataType: 'json',
|
||||
success: function(data) {
|
||||
var tabBody = $(pane.context.hash).find('.tab-content-body');
|
||||
url: $(this).attr("data-url"),
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
var tabBody = $(pane.context.hash).find(".tab-content-body");
|
||||
tabBody.html(data.html);
|
||||
pane.tab('show').promise().done(function() {
|
||||
initImportRecordsModal();
|
||||
|
@ -58,7 +44,7 @@
|
|||
// on page load
|
||||
if( param = getParam('repository') ){
|
||||
// load selected tab
|
||||
$('a[href="#custom_repo_' + param + '"]').click();
|
||||
$('a[href="#custom_repo_'+param+'"]').click();
|
||||
}
|
||||
else {
|
||||
// load first tab content
|
||||
|
@ -66,37 +52,15 @@
|
|||
}
|
||||
|
||||
// clean tab content
|
||||
$('a[data-toggle="tab"]').on('hide.bs.tab', function(e) {
|
||||
$('a[data-toggle="tab"]').on('hide.bs.tab', function (e) {
|
||||
$(".tab-content-body").html("");
|
||||
})
|
||||
}
|
||||
|
||||
function initImportRecordsModal() {
|
||||
$('#importRecordsButton').off().on('click', function() {
|
||||
$('#modal-import-records').modal('show');
|
||||
initParseRecordsModal();
|
||||
});
|
||||
}
|
||||
|
||||
function initParseRecordsModal() {
|
||||
$('#form-records-file').on('ajax:success', function(ev, data) {
|
||||
$('#modal-import-records').modal('hide');
|
||||
$(data.html).appendTo('body').promise().done(function() {
|
||||
$('#parse-records_modal').modal('show');
|
||||
repositoryRecordsImporter();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
$('.delete-repo-option').initializeModal('#delete-repo-modal');
|
||||
$('.rename-repo-option').initializeModal('#rename-repo-modal');
|
||||
$('.copy-repo-option').initializeModal('#copy-repo-modal');
|
||||
// $('.create-repository').initializeModal('#create-repo-modal');
|
||||
$('.create-repository').initializeModal('#create-repo-modal');
|
||||
|
||||
$(document).ready(function() {
|
||||
loadRepositoryTab();
|
||||
// showParsedRecords();
|
||||
initCreateRepository();
|
||||
initImportRecordsModal();
|
||||
});
|
||||
|
||||
})();
|
||||
|
|
|
@ -92,7 +92,6 @@ function dataTableInit() {
|
|||
columns: (function() {
|
||||
var numOfColumns = $('#repository-table').data('num-columns');
|
||||
var columns = [];
|
||||
|
||||
for (var i = 0; i < numOfColumns; i++) {
|
||||
var visible = (i <= 4);
|
||||
var searchable = (i > 0 && i <= 4);
|
||||
|
@ -119,6 +118,7 @@ function dataTableInit() {
|
|||
rowsSelected.length +
|
||||
' entries selected)');
|
||||
initRowSelection();
|
||||
initHeaderTooltip();
|
||||
},
|
||||
preDrawCallback: function() {
|
||||
animateSpinner(this);
|
||||
|
@ -154,16 +154,13 @@ function dataTableInit() {
|
|||
type: 'POST'
|
||||
});
|
||||
loadFirstTime = false;
|
||||
initHeaderTooltip();
|
||||
},
|
||||
fnInitComplete: function(oSettings) {
|
||||
// Reload correct column order and visibility (if you refresh page)
|
||||
// First two columns are fixed
|
||||
table.column(0).visible(true);
|
||||
if ($('#assigned').text().length === 0) {
|
||||
table.column(1).visible(false);
|
||||
} else {
|
||||
table.column(1).visible(true);
|
||||
}
|
||||
table.column(1).visible(true);
|
||||
for (var i = 2; i < table.columns()[0].length; i++) {
|
||||
var visibility = false;
|
||||
if (myData.columns[i]) {
|
||||
|
@ -197,6 +194,10 @@ function dataTableInit() {
|
|||
$(this).parent().find('.repository-row-selector').trigger('click');
|
||||
});
|
||||
|
||||
table.on('column-reorder', function() {
|
||||
initRowSelection();
|
||||
});
|
||||
|
||||
$('#assignRepositories, #unassignRepositories').click(function() {
|
||||
animateLoading();
|
||||
});
|
||||
|
@ -214,6 +215,59 @@ setTimeout(function() {
|
|||
// Enables noSearchHidden plugin
|
||||
$.fn.dataTable.defaults.noSearchHidden = true;
|
||||
|
||||
$('form#form-export').submit(function() {
|
||||
var form = this;
|
||||
|
||||
if (currentMode === 'viewMode') {
|
||||
// Remove all hidden fields
|
||||
$(form).find('input[name=row_ids\\[\\]]').remove();
|
||||
$(form).find('input[name=header_ids\\[\\]]').remove();
|
||||
|
||||
// Append visible column information
|
||||
$('.active table#repository-table thead tr th').each(function() {
|
||||
var th = $(this);
|
||||
var val;
|
||||
switch ($(th).attr('id')) {
|
||||
case 'checkbox':
|
||||
val = -1;
|
||||
break;
|
||||
case 'assigned':
|
||||
val = -2;
|
||||
break;
|
||||
case 'row-name':
|
||||
val = -3;
|
||||
break;
|
||||
case 'added-by':
|
||||
val = -4;
|
||||
break;
|
||||
case 'added-on':
|
||||
val = -5;
|
||||
break;
|
||||
default:
|
||||
val = th.attr('id');
|
||||
}
|
||||
|
||||
if (val) {
|
||||
appendInput(form, val, 'header_ids[]');
|
||||
}
|
||||
});
|
||||
|
||||
// Append records
|
||||
$.each(rowsSelected, function(index, rowId) {
|
||||
appendInput(form, rowId, 'row_ids[]');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function appendInput(form, val, name) {
|
||||
$(form).append(
|
||||
$('<input>')
|
||||
.attr('type', 'hidden')
|
||||
.attr('name', name)
|
||||
.val(val)
|
||||
);
|
||||
}
|
||||
|
||||
function initRowSelection() {
|
||||
// Handle clicks on checkbox
|
||||
$('.dt-body-center .repository-row-selector').change(function(e) {
|
||||
|
@ -303,6 +357,13 @@ function initHeaderTooltip() {
|
|||
offsetLeft -= 150;
|
||||
}
|
||||
var offsetTop = $tooltip.offset().top;
|
||||
var width = 200;
|
||||
|
||||
// set tooltip params in the table body
|
||||
if ( $(this).parents('#repository-table').length ) {
|
||||
offsetLeft = $('#repository-table').offset().left + 100;
|
||||
width = $('#repository-table').width() - 200;
|
||||
}
|
||||
$('body').append($tooltip);
|
||||
$tooltip.css('background-color', '#d2d2d2');
|
||||
$tooltip.css('border-radius', '6px');
|
||||
|
@ -314,8 +375,9 @@ function initHeaderTooltip() {
|
|||
$tooltip.css('text-align', 'center');
|
||||
$tooltip.css('top', offsetTop + 'px');
|
||||
$tooltip.css('visibility', 'visible');
|
||||
$tooltip.css('width', '200px');
|
||||
$tooltip.css('width', width + 'px');
|
||||
$tooltip.css('word-wrap', 'break-word');
|
||||
$tooltip.css('z-index', '4');
|
||||
$(this).data('dropdown-tooltip', $tooltip);
|
||||
}, function() {
|
||||
$(this).append($(this).data('dropdown-tooltip'));
|
||||
|
@ -399,10 +461,12 @@ function onClickAssignRecords() {
|
|||
success: function(data) {
|
||||
HelperModule.flashAlertMsg(data.flash, 'success');
|
||||
onClickCancel();
|
||||
clearRowSelection();
|
||||
},
|
||||
error: function(data) {
|
||||
HelperModule.flashAlertMsg(data.responseJSON.flash, 'danger');
|
||||
onClickCancel();
|
||||
clearRowSelection();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -417,10 +481,12 @@ function onClickUnassignRecords() {
|
|||
success: function(data) {
|
||||
HelperModule.flashAlertMsg(data.flash, 'success');
|
||||
onClickCancel();
|
||||
clearRowSelection();
|
||||
},
|
||||
error: function(data) {
|
||||
HelperModule.flashAlertMsg(data.responseJSON.flash, 'danger');
|
||||
onClickCancel();
|
||||
clearRowSelection();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -433,7 +499,8 @@ function onClickDeleteRecord() {
|
|||
dataType: 'json',
|
||||
data: {selected_rows: rowsSelected},
|
||||
success: function(data) {
|
||||
HelperModule.flashAlertMsg(data.flash, 'success');
|
||||
HelperModule.flashAlertMsg(data.flash, data.color);
|
||||
rowsSelected = [];
|
||||
onClickCancel();
|
||||
},
|
||||
error: function(e) {
|
||||
|
@ -615,7 +682,7 @@ function onClickSave() {
|
|||
if (input) {
|
||||
input.closest('.form-group').addClass('has-error');
|
||||
input.parent().append("<span class='help-block'>" +
|
||||
val.value[0] + '<br /></span>');
|
||||
val.data[0] + '<br /></span>');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -637,29 +704,38 @@ function updateButtons() {
|
|||
$('th').removeClass('disable-click');
|
||||
$('.repository-row-selector').removeClass('disabled');
|
||||
$('.repository-row-selector').prop('disabled', false);
|
||||
if (rowsSelected.length === 1) {
|
||||
$('#editRepositoryRecord').prop('disabled', false);
|
||||
$('#editRepositoryRecord').removeClass('disabled');
|
||||
$('#deleteRepositoryRecordsButton').prop('disabled', false);
|
||||
$('#deleteRepositoryRecordsButton').removeClass('disabled');
|
||||
$('#assignRepositoryRecords').removeClass('disabled');
|
||||
$('#assignRepositoryRecords').prop('disabled', false);
|
||||
$('#unassignRepositoryRecords').removeClass('disabled');
|
||||
$('#unassignRepositoryRecords').prop('disabled', false);
|
||||
} else if (rowsSelected.length === 0) {
|
||||
if (rowsSelected.length === 0) {
|
||||
$('#editRepositoryRecord').prop('disabled', true);
|
||||
$('#editRepositoryRecord').addClass('disabled');
|
||||
$('#deleteRepositoryRecordsButton').prop('disabled', true);
|
||||
$('#deleteRepositoryRecordsButton').addClass('disabled');
|
||||
$('#exportRepositoriesButton').addClass('disabled');
|
||||
$('#exportRepositoriesButton').prop('disabled', true);
|
||||
$('#exportRepositoriesButton').off('click');
|
||||
$('#export-repositories').off('click');
|
||||
$('#assignRepositoryRecords').addClass('disabled');
|
||||
$('#assignRepositoryRecords').prop('disabled', true);
|
||||
$('#unassignRepositoryRecords').addClass('disabled');
|
||||
$('#unassignRepositoryRecords').prop('disabled', true);
|
||||
} else {
|
||||
$('#editRepositoryRecord').prop('disabled', true);
|
||||
$('#editRepositoryRecord').addClass('disabled');
|
||||
if (rowsSelected.length === 1) {
|
||||
$('#editRepositoryRecord').prop('disabled', false);
|
||||
$('#editRepositoryRecord').removeClass('disabled');
|
||||
} else {
|
||||
$('#editRepositoryRecord').prop('disabled', true);
|
||||
$('#editRepositoryRecord').addClass('disabled');
|
||||
}
|
||||
$('#deleteRepositoryRecordsButton').prop('disabled', false);
|
||||
$('#deleteRepositoryRecordsButton').removeClass('disabled');
|
||||
$('#exportRepositoriesButton').removeClass('disabled');
|
||||
$('#exportRepositoriesButton').prop('disabled', false);
|
||||
$('#exportRepositoriesButton').on('click', function() {
|
||||
$('#exportRepositoryModal').modal('show');
|
||||
});
|
||||
$('#export-repositories').on('click', function() {
|
||||
animateSpinner(null, true);
|
||||
$('#form-export').submit();
|
||||
});
|
||||
$('#assignRepositoryRecords').removeClass('disabled');
|
||||
$('#assignRepositoryRecords').prop('disabled', false);
|
||||
$('#unassignRepositoryRecords').removeClass('disabled');
|
||||
|
@ -674,6 +750,9 @@ function updateButtons() {
|
|||
$('#addNewColumn').prop('disabled', true);
|
||||
$('#deleteRepositoryRecordsButton').addClass('disabled');
|
||||
$('#deleteRepositoryRecordsButton').prop('disabled', true);
|
||||
$('#exportRepositoriesButton').addClass('disabled');
|
||||
$('#exportRepositoriesButton').off('click');
|
||||
$('#export-repositories').off('click');
|
||||
$('#assignRepositoryRecords').addClass('disabled');
|
||||
$('#assignRepositoryRecords').prop('disabled', true);
|
||||
$('#unassignRepositoryRecords').addClass('disabled');
|
||||
|
@ -697,6 +776,13 @@ function clearAllErrors() {
|
|||
$('#alert-container').find('div').remove();
|
||||
}
|
||||
|
||||
function clearRowSelection() {
|
||||
$('.dt-body-center .repository-row-selector').prop('checked', false);
|
||||
$('.dt-body-center .repository-row-selector').closest('tr')
|
||||
.removeClass('selected');
|
||||
rowsSelected = [];
|
||||
}
|
||||
|
||||
// Restore previous table
|
||||
function onClickCancel() {
|
||||
if ($('#assigned').text().length === 0) {
|
||||
|
@ -759,6 +845,7 @@ function changeToEditMode() {
|
|||
currentMode = 'editMode';
|
||||
// Table specific stuff
|
||||
table.button(0).enable(false);
|
||||
initHeaderTooltip();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -971,6 +1058,7 @@ function changeToEditMode() {
|
|||
if (!_.isEmpty(searchText)) {
|
||||
table.search(searchText).draw();
|
||||
}
|
||||
initRowSelection();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1257,7 +1345,7 @@ function changeToEditMode() {
|
|||
var maxLength = $('#repository-table').data('max-dropdown-length');
|
||||
if ($.trim(name).length > maxLength) {
|
||||
return '<div class="modal-tooltip">' +
|
||||
maxLength +
|
||||
truncateLongString(name, maxLength) +
|
||||
'<span class="modal-tooltiptext">' + name + '</span></div>';
|
||||
}
|
||||
return name;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
(function(global) {
|
||||
'use strict';
|
||||
|
||||
var ResutlAssets = (function() {
|
||||
global.ResutlAssets = (function() {
|
||||
// New result asset behaviour
|
||||
function initNewResultAsset() {
|
||||
$('#new-result-asset').on('click', function(event) {
|
||||
|
@ -23,7 +23,7 @@
|
|||
_formAjaxResultAsset($form);
|
||||
Results.initCancelFormButton($form, initNewResultAsset);
|
||||
Results.toggleResultEditButtons(false);
|
||||
$('#result_name').focus();
|
||||
dragNdropAssetsInit('results');
|
||||
},
|
||||
error: function(xhr, status, e) {
|
||||
$(this).renderFormErrors('result', xhr.responseJSON, true, e);
|
||||
|
|
|
@ -33,9 +33,12 @@ var loadFirstTime = true;
|
|||
var table;
|
||||
var originalHeader;
|
||||
|
||||
var view_assigned;
|
||||
|
||||
function dataTableInit() {
|
||||
// Make a copy of original samples table header
|
||||
originalHeader = $('#samples thead').children().clone();
|
||||
view_assigned = 'assigned';
|
||||
table = $('#samples').DataTable({
|
||||
order: [[2, 'desc']],
|
||||
dom: "R<'row'<'col-sm-9-custom toolbar'l><'col-sm-3-custom'f>>tpi",
|
||||
|
@ -53,6 +56,9 @@ function dataTableInit() {
|
|||
destroy: true,
|
||||
ajax: {
|
||||
url: $('#samples').data('source'),
|
||||
data: function ( d ) {
|
||||
d.assigned = view_assigned;
|
||||
},
|
||||
global: false,
|
||||
type: 'POST'
|
||||
},
|
||||
|
@ -661,7 +667,14 @@ function updateButtons() {
|
|||
$("#deleteSamplesButton").removeClass("disabled");
|
||||
$("#exportSamplesButton").removeClass("disabled");
|
||||
$("#exportSamplesButton").prop("disabled",false);
|
||||
$("#exportSamplesButton").on("click", function() { $('#form-export').submit(); });
|
||||
$("#exportSamplesButton").on("click", function() {
|
||||
$('#modal-export-samples-success')
|
||||
.modal('show')
|
||||
.on('hidden.bs.modal', function() {
|
||||
animateSpinner(null, true);
|
||||
$('#form-export').submit();
|
||||
});
|
||||
});
|
||||
$("#assignSamples").removeClass("disabled");
|
||||
$("#assignSamples").prop("disabled", false);
|
||||
$("#unassignSamples").removeClass("disabled");
|
||||
|
@ -687,7 +700,14 @@ function updateButtons() {
|
|||
$("#deleteSamplesButton").removeClass("disabled");
|
||||
$("#exportSamplesButton").removeClass("disabled");
|
||||
$("#exportSamplesButton").prop("disabled",false);
|
||||
$("#exportSamplesButton").on("click", function() { $('#form-export').submit(); });
|
||||
$("#exportSamplesButton").on("click", function() {
|
||||
$('#modal-export-samples-success')
|
||||
.modal('show')
|
||||
.on('hidden.bs.modal', function() {
|
||||
animateSpinner(null, true);
|
||||
$('#form-export').submit();
|
||||
});
|
||||
});
|
||||
$("#assignSamples").removeClass("disabled");
|
||||
$("#assignSamples").prop("disabled", false);
|
||||
$("#unassignSamples").removeClass("disabled");
|
||||
|
@ -819,6 +839,15 @@ function onClickAddSample() {
|
|||
});
|
||||
}
|
||||
|
||||
$('#assignedSamples').on('click', function () {
|
||||
view_assigned = 'assigned';
|
||||
table.draw();
|
||||
});
|
||||
$('#allSamples').on('click', function () {
|
||||
view_assigned = 'all';
|
||||
table.draw();
|
||||
});
|
||||
|
||||
// Handle enter key
|
||||
$(document).off('keypress').keypress(function(event) {
|
||||
var keycode = (event.keyCode ? event.keyCode : event.which);
|
||||
|
|
|
@ -17,6 +17,12 @@ $("form#form-samples-file")
|
|||
$(this).find(".form-group").append("<span class='help-block'>" + data.responseJSON.message + "</span>");
|
||||
});
|
||||
|
||||
$('.sample-assign-group > .btn').click(function() {
|
||||
$('.btn-group > .btn').removeClass('active btn-primary');
|
||||
$('.btn-group > .btn').addClass('btn-default');
|
||||
$(this).addClass('active btn-primary');
|
||||
});
|
||||
|
||||
// Fetch samples data and updates the select options fields for
|
||||
// sample group and sample type column
|
||||
function updateSamplesTypesandGroups() {
|
||||
|
|
346
app/assets/javascripts/sitewide/drag_n_drop.js.erb
Normal file
346
app/assets/javascripts/sitewide/drag_n_drop.js.erb
Normal file
|
@ -0,0 +1,346 @@
|
|||
(function(global) {
|
||||
'use strict';
|
||||
|
||||
// Module to handle file uploading in Steps
|
||||
global.DragNDropSteps = (function() {
|
||||
var droppedFiles = [];
|
||||
var filesValid = true;
|
||||
var totalSize = 0;
|
||||
|
||||
function init(files) {
|
||||
for(var i = 0; i < files.length; i++) {
|
||||
droppedFiles.push(files[i]);
|
||||
}
|
||||
listItems();
|
||||
}
|
||||
|
||||
// return the status of files if they are ready to submit
|
||||
function filesStatus() {
|
||||
return filesValid;
|
||||
}
|
||||
|
||||
// loops through a list of files and display each file in a separate panel
|
||||
function listItems() {
|
||||
droppedFiles = droppedFiles.filter(Boolean);
|
||||
$('.panel-step-attachment-new').remove();
|
||||
_dragNdropAssetsOff();
|
||||
for(var i = 0; i < droppedFiles.length; i++) {
|
||||
$('#new-step-assets')
|
||||
.append(_uploadedAseetPreview(droppedFiles[i], i))
|
||||
.promise()
|
||||
.done(function() {
|
||||
_removeItemHandler(i);
|
||||
});
|
||||
}
|
||||
_validateTotalSize();
|
||||
dragNdropAssetsInit('steps');
|
||||
}
|
||||
|
||||
// append the files to the form before submit
|
||||
function appendFilesToForm(ev) {
|
||||
var regex = /step\[assets_attributes\]\[[0-9]*\]\[id\]/;
|
||||
var prevEls = $('input').filter(function() {
|
||||
return this.name.match(regex);
|
||||
});
|
||||
droppedFiles = droppedFiles.filter(Boolean);
|
||||
var fd = new FormData($(ev.target).closest('form').get(0));
|
||||
for(var i = 0; i < droppedFiles.length; i++) {
|
||||
var index = i + prevEls.length;
|
||||
var name = 'step[assets_attributes][' + index + '][file]';
|
||||
fd.append(name, droppedFiles[i]);
|
||||
}
|
||||
droppedFiles = [];
|
||||
filesValid = true;
|
||||
totalSize = 0;
|
||||
_dragNdropAssetsOff();
|
||||
return fd;
|
||||
}
|
||||
|
||||
function _validateFilesSize(file) {
|
||||
var maxSize = file.size/1048576;
|
||||
if(maxSize > <%= Constants::FILE_MAX_SIZE_MB %> && filesValid) {
|
||||
return "<p><%= I18n.t 'general.file.size_exceeded', file_size: Constants::FILE_MAX_SIZE_MB %></p>";
|
||||
}
|
||||
totalSize += parseInt(maxSize);
|
||||
return '';
|
||||
}
|
||||
|
||||
function _validateTotalSize() {
|
||||
if(totalSize > <%= Constants::FILE_MAX_SIZE_MB %>) {
|
||||
filesValid = false;
|
||||
$.each($('.panel-step-attachment-new'), function() {
|
||||
$(this)
|
||||
.find('.panel-body')
|
||||
.append("<p class='dnd-error'><%= I18n.t('general.file.total_size', size: Constants::FILE_MAX_SIZE_MB) %></p>");
|
||||
});
|
||||
} else {
|
||||
$('.dnd-error').remove();
|
||||
filesValid = true;
|
||||
}
|
||||
}
|
||||
|
||||
function _uploadedAseetPreview(asset, i) {
|
||||
var html = '<div class="panel panel-default panel-step-attachment-new">';
|
||||
html += '<div class="panel-heading">';
|
||||
html += '<span class="glyphicon glyphicon-file"></span>';
|
||||
html += '<%= I18n.t 'assets.drag_n_drop.file_label' %>';
|
||||
html += '<div class="pull-right">';
|
||||
html += '<a data-item-id="' + i + '" href="#">';
|
||||
html += '<span class="glyphicon glyphicon-remove"></span></a></div></div>';
|
||||
html += '<div class="panel-body">';
|
||||
html += '<label class="control-label">';
|
||||
html += '<%= I18n.t 'assets.drag_n_drop.file_label' %>:</label> ';
|
||||
html += truncateLongString(asset.name,
|
||||
<%= Constants::FILENAME_TRUNCATION_LENGTH %>);
|
||||
html += _validateFilesSize(asset);
|
||||
html += '</div></div>';
|
||||
return html;
|
||||
}
|
||||
|
||||
function _removeItemHandler(id) {
|
||||
$('[data-item-id="' + id +'"]').off('click').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
e.stopImmediatePropagation();
|
||||
e.stopPropagation();
|
||||
var $el = $(this);
|
||||
var index = $el.data('item-id');
|
||||
totalSize -= parseInt(droppedFiles[index]/1048576);
|
||||
droppedFiles[index] = null;
|
||||
$el.closest('.panel-step-attachment-new').remove();
|
||||
_validateTotalSize();
|
||||
});
|
||||
}
|
||||
|
||||
function _dragNdropAssetsOff() {
|
||||
$('body').off('drag dragstart dragend dragover dragenter dragleave drop');
|
||||
$('.is-dragover').hide();
|
||||
}
|
||||
|
||||
return Object.freeze({
|
||||
init: init,
|
||||
appendFilesToForm: appendFilesToForm,
|
||||
listItems: listItems,
|
||||
filesStatus: filesStatus
|
||||
});
|
||||
})();
|
||||
|
||||
// Module to handle file uploading in Results
|
||||
global.DragNDropResults = (function() {
|
||||
var droppedFiles = [];
|
||||
var isValid = true;
|
||||
var totalSize = 0;
|
||||
|
||||
function init(files) {
|
||||
var filesPresent = droppedFiles.length;
|
||||
for(var i = 0; i < files.length; i++) {
|
||||
droppedFiles.push(files[i]);
|
||||
}
|
||||
listItems(filesPresent);
|
||||
}
|
||||
|
||||
// return the status of files if they are ready to submit
|
||||
function filesStatus() {
|
||||
return isValid;
|
||||
}
|
||||
|
||||
// loops through a list of files and display each file in a separate panel
|
||||
function listItems(index) {
|
||||
_dragNdropAssetsOff();
|
||||
for(var i = index; i < droppedFiles.length; i++) {
|
||||
$('#new-result-assets-select')
|
||||
.after(_uploadedAseetPreview(droppedFiles[i], i))
|
||||
.promise()
|
||||
.done(function() {
|
||||
_removeItemHandler(i);
|
||||
});
|
||||
}
|
||||
_validateTotalSize();
|
||||
dragNdropAssetsInit('results');
|
||||
}
|
||||
|
||||
// appent the files to the form before submit
|
||||
function _appendFilesToForm() {
|
||||
var regex = /result\[assets_attributes\]\[[0-9]*\]\[id\]/;
|
||||
var prevEls = $('input').filter(function() {
|
||||
return this.name.match(regex);
|
||||
});
|
||||
|
||||
var fd = new FormData();
|
||||
var result_names = [];
|
||||
$.each($('input[rel="results[name]"]'), function() {
|
||||
result_names.push($(this).val());
|
||||
});
|
||||
result_names.reverse();
|
||||
for(var i = 0; i < droppedFiles.length; i++) {
|
||||
var index = i + prevEls.length;
|
||||
var file_name = 'results_files[' + index + ']';
|
||||
fd.append(file_name, droppedFiles[i]);
|
||||
fd.append('results_names[' + i + ']', result_names[i]);
|
||||
}
|
||||
destroyAll();
|
||||
return fd;
|
||||
}
|
||||
|
||||
function _filerAndCheckFiles() {
|
||||
droppedFiles = droppedFiles.filter(Boolean);
|
||||
return (droppedFiles.length > 0);
|
||||
}
|
||||
|
||||
function _validateFilesSize(file) {
|
||||
var maxSize = file.size/1048576;
|
||||
if(maxSize > <%= Constants::FILE_MAX_SIZE_MB %> && isValid) {
|
||||
return "<p><%= I18n.t 'general.file.size_exceeded', file_size: Constants::FILE_MAX_SIZE_MB %></p>";
|
||||
}
|
||||
totalSize += parseInt(maxSize);
|
||||
return '';
|
||||
}
|
||||
|
||||
function _validateTotalSize() {
|
||||
if(totalSize > <%= Constants::FILE_MAX_SIZE_MB %>) {
|
||||
isValid = false;
|
||||
$.each($('.panel-result-attachment-new'), function() {
|
||||
$(this)
|
||||
.find('.panel-body')
|
||||
.append("<p class='dnd-error'><%= I18n.t('general.file.total_size', size: Constants::FILE_MAX_SIZE_MB) %></p>");
|
||||
});
|
||||
} else {
|
||||
$('.dnd-error').remove();
|
||||
isValid = true;
|
||||
}
|
||||
}
|
||||
|
||||
function validateTextSize(input) {
|
||||
if(input.value.length > <%= Constants::NAME_MAX_LENGTH %>) {
|
||||
$(input).parent().find('.dnd-error').remove();
|
||||
$(input).after("<p class='dnd-error'><%= I18n.t('general.text.length_too_long', max_length: Constants::NAME_MAX_LENGTH) %></p>");
|
||||
isValid = false;
|
||||
} else {
|
||||
$(input).parent().find('.dnd-error').remove();
|
||||
isValid = true;
|
||||
}
|
||||
}
|
||||
|
||||
function _uploadedAseetPreview(asset, i) {
|
||||
var html = '<div class="panel panel-default panel-result-attachment-new">';
|
||||
html += '<div class="panel-heading">';
|
||||
html += '<span class="glyphicon glyphicon-file"></span>';
|
||||
html += '<%= I18n.t 'assets.drag_n_drop.file_label' %>';
|
||||
html += '<div class="pull-right">';
|
||||
html += '<a data-item-id="' + i + '" href="#">';
|
||||
html += '<span class="glyphicon glyphicon-remove"></span></a></div></div>';
|
||||
html += '<div class="panel-body"><div class="form-group">';
|
||||
html += '<label class="control-label">Name</label>';
|
||||
html += '<input type="text" class="form-control" ';
|
||||
html += 'onChange="DragNDropResults.validateTextSize(this)"';
|
||||
html += ' rel="results[name]" name="results[name][' + i + ']">';
|
||||
html += '</div><div class="form-group"><label class="control-label">';
|
||||
html += '<%= I18n.t 'assets.drag_n_drop.file_label' %>:</label> ';
|
||||
html += truncateLongString(asset.name,
|
||||
<%= Constants::FILENAME_TRUNCATION_LENGTH %>);
|
||||
html += _validateFilesSize(asset);
|
||||
html += '</div></div>';
|
||||
return html;
|
||||
}
|
||||
|
||||
function _removeItemHandler(id) {
|
||||
$('[data-item-id="' + id +'"]').off('click').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
e.stopImmediatePropagation();
|
||||
e.stopPropagation();
|
||||
var $el = $(this);
|
||||
var index = $el.data('item-id');
|
||||
totalSize -= parseInt(droppedFiles[index]/1048576);
|
||||
droppedFiles[index] = null;
|
||||
$el.closest('.panel-result-attachment-new').remove();
|
||||
_validateTotalSize();
|
||||
});
|
||||
}
|
||||
|
||||
function processResult(button) {
|
||||
if(isValid && _filerAndCheckFiles()) {
|
||||
animateSpinner();
|
||||
$.ajax({
|
||||
url: $(button).attr('data-href'),
|
||||
method: 'POST',
|
||||
data: _appendFilesToForm(),
|
||||
contentType: false,
|
||||
processData: false,
|
||||
success: function(data) {
|
||||
animateSpinner(null, false);
|
||||
$('#new-result-assets-select').parent().remove();
|
||||
$(data.html).prependTo('#results').promise().done(function() {
|
||||
$.each($('[data-container="new-reports"]').find('.result'),
|
||||
function() {
|
||||
initFormSubmitLinks($(this));
|
||||
ResutlAssets.applyEditResultAssetCallback();
|
||||
Results.applyCollapseLinkCallBack();
|
||||
Results.toggleResultEditButtons(true);
|
||||
initPreviewModal();
|
||||
Comments.initialize();
|
||||
ResutlAssets.initNewResultAsset();
|
||||
Results.expandResult($(this));
|
||||
});
|
||||
|
||||
});
|
||||
$('#results-toolbar').show();
|
||||
},
|
||||
error: function() {
|
||||
animateSpinner();
|
||||
location.reload();
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function destroyAll() {
|
||||
_dragNdropAssetsOff();
|
||||
droppedFiles = [];
|
||||
isValid = true;
|
||||
totalSize = 0;
|
||||
}
|
||||
|
||||
function _dragNdropAssetsOff() {
|
||||
$('body').off('drag dragstart dragend dragover dragenter dragleave drop');
|
||||
$('.is-dragover').hide();
|
||||
}
|
||||
|
||||
return Object.freeze({
|
||||
init: init,
|
||||
listItems: listItems,
|
||||
destroyAll: destroyAll,
|
||||
filesStatus: filesStatus,
|
||||
validateTextSize: validateTextSize,
|
||||
processResult: processResult
|
||||
});
|
||||
})();
|
||||
|
||||
global.dragNdropAssetsInit = function(location) {
|
||||
var in_window = true;
|
||||
|
||||
$('body').on('drag dragstart dragend dragover dragenter dragleave drop',
|
||||
function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}).on('dragover', function() {
|
||||
in_window = true;
|
||||
$('.is-dragover').show();
|
||||
}).on('dragleave', function() {
|
||||
in_window = false;
|
||||
setTimeout(function() {
|
||||
if(!in_window) {
|
||||
$('.is-dragover').hide();
|
||||
}
|
||||
}, 5000);
|
||||
|
||||
}).on('drop', function(e) {
|
||||
$('.is-dragover').hide();
|
||||
var files = e.originalEvent.dataTransfer.files;
|
||||
if(location === 'steps') {
|
||||
DragNDropSteps.init(files);
|
||||
} else {
|
||||
DragNDropResults.init(files);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
})(window);
|
|
@ -44,6 +44,9 @@ $color-milano-red: #a70b05;
|
|||
// Colors for specific intents
|
||||
$color-visited-link: #23527c;
|
||||
|
||||
// Overlay shade for drag'n dropdown
|
||||
$color-drag-overlay: rgba(0, 0, 0, .4);
|
||||
|
||||
//==============================================================================
|
||||
// Other
|
||||
//==============================================================================
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
height: auto;
|
||||
max-height: 400px;
|
||||
overflow-x: hidden;
|
||||
text-transform: initial;
|
||||
}
|
||||
|
||||
.repository-table {
|
||||
|
@ -12,3 +13,9 @@
|
|||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.repository-cog {
|
||||
display: inline-block;
|
||||
float: right;
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
|
|
@ -1265,6 +1265,45 @@ ul.content-module-activities {
|
|||
}
|
||||
}
|
||||
|
||||
.new-asset-box {
|
||||
border: 1px solid $color-silver;
|
||||
border-radius: 2px;
|
||||
font-size: 2rem;
|
||||
margin-bottom: 20px;
|
||||
margin-top: 20px;
|
||||
padding-bottom: 30px;
|
||||
padding-top: 30px;
|
||||
}
|
||||
|
||||
.dnd-error {
|
||||
color: $color-milano-red;
|
||||
}
|
||||
|
||||
.is-dragover {
|
||||
background: $color-drag-overlay;
|
||||
bottom: 0;
|
||||
display: none;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
min-height: 100%;
|
||||
pointer-events: none;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
z-index: 999999;
|
||||
|
||||
span {
|
||||
color: $color-white;
|
||||
display: block;
|
||||
font-size: 4em;
|
||||
font-weight: bold;
|
||||
padding-top: 25%;
|
||||
pointer-events: none;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.step,
|
||||
.result {
|
||||
.panel {
|
||||
|
@ -1537,6 +1576,11 @@ table.dataTable {
|
|||
visibility: visible;
|
||||
}
|
||||
|
||||
// don't display tooltip, it's handeled with js
|
||||
.repository-table .modal-tooltip:hover .modal-tooltiptext {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
// Comments
|
||||
|
||||
.comment-more {
|
||||
|
|
|
@ -27,6 +27,10 @@ class MyModulesController < ApplicationController
|
|||
before_action :check_assign_samples_permissions, only: :assign_samples
|
||||
before_action :check_unassign_samples_permissions, only: :unassign_samples
|
||||
before_action :check_complete_my_module_perimission, only: :complete_my_module
|
||||
before_action :check_assign_repository_records_permissions,
|
||||
only: :assign_repository_records
|
||||
before_action :check_unassign_repository_records_permissions,
|
||||
only: :unassign_repository_records
|
||||
|
||||
layout 'fluid'.freeze
|
||||
|
||||
|
@ -386,8 +390,6 @@ class MyModulesController < ApplicationController
|
|||
|
||||
# Submit actions
|
||||
def assign_repository_records
|
||||
render_403 && return unless can_assign_repository_records(@my_module,
|
||||
@repository)
|
||||
if params[:selected_rows].present? && params[:repository_id].present?
|
||||
records_names = []
|
||||
|
||||
|
@ -415,7 +417,7 @@ class MyModulesController < ApplicationController
|
|||
'activities.assign_repository_records',
|
||||
user: current_user.full_name,
|
||||
task: @my_module.name,
|
||||
repository: @repository,
|
||||
repository: @repository.name,
|
||||
records: records_names.join(', ')
|
||||
)
|
||||
)
|
||||
|
@ -437,8 +439,6 @@ class MyModulesController < ApplicationController
|
|||
end
|
||||
|
||||
def unassign_repository_records
|
||||
render_403 && return unless can_unassign_repository_records(@my_module,
|
||||
@repository)
|
||||
if params[:selected_rows].present? && params[:repository_id].present?
|
||||
records = []
|
||||
|
||||
|
@ -462,7 +462,7 @@ class MyModulesController < ApplicationController
|
|||
'activities.unassign_repository_records',
|
||||
user: current_user.full_name,
|
||||
task: @my_module.name,
|
||||
repository: @repository,
|
||||
repository: @repository.name,
|
||||
records: records.map(&:name).join(', ')
|
||||
)
|
||||
)
|
||||
|
@ -641,12 +641,20 @@ class MyModulesController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def check_assign_repository_records_permissions
|
||||
render_403 unless can_assign_repository_records(@my_module, @repository)
|
||||
end
|
||||
|
||||
def check_unassign_repository_records_permissions
|
||||
render_403 unless can_unassign_repository_records(@my_module, @repository)
|
||||
end
|
||||
|
||||
def check_complete_my_module_perimission
|
||||
render_403 unless can_complete_module(@my_module)
|
||||
end
|
||||
|
||||
def my_module_params
|
||||
params.require(:my_module).permit(:name, :description, :due_date,
|
||||
:archived)
|
||||
:archived)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,21 +1,23 @@
|
|||
class RepositoriesController < ApplicationController
|
||||
before_action :load_vars,
|
||||
except: %i(repository_table_index parse_sheet import_records)
|
||||
except: %i(index create create_modal parse_sheet import_records)
|
||||
before_action :load_parent_vars, except:
|
||||
%i(repository_table_index export_repository parse_sheet import_records)
|
||||
before_action :check_team, only: %i(parse_sheet import_records)
|
||||
before_action :check_view_all_permissions, only: :index
|
||||
before_action :check_edit_and_destroy_permissions,
|
||||
only: %i(destroy destroy_modal rename_modal update)
|
||||
before_action :check_copy_permissions,
|
||||
only: %i(copy_modal copy)
|
||||
before_action :check_create_permissions,
|
||||
only: %i(create_new_modal create)
|
||||
before_action :check_view_permissions, only: :export_repository
|
||||
before_action :check_edit_and_destroy_permissions, only:
|
||||
%i(destroy destroy_modal rename_modal update)
|
||||
before_action :check_copy_permissions, only:
|
||||
%i(copy_modal copy)
|
||||
before_action :check_create_permissions, only:
|
||||
%i(create_new_modal create)
|
||||
|
||||
def index
|
||||
render('repositories/index')
|
||||
end
|
||||
|
||||
def show_tab
|
||||
@repository = Repository.find_by_id(params[:repository_id])
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
render json: {
|
||||
|
@ -64,7 +66,6 @@ class RepositoriesController < ApplicationController
|
|||
end
|
||||
|
||||
def destroy_modal
|
||||
@repository = Repository.find(params[:repository_id])
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
render json: {
|
||||
|
@ -77,7 +78,6 @@ class RepositoriesController < ApplicationController
|
|||
end
|
||||
|
||||
def destroy
|
||||
@repository = Repository.find(params[:id])
|
||||
flash[:success] = t('repositories.index.delete_flash',
|
||||
name: @repository.name)
|
||||
@repository.destroy
|
||||
|
@ -85,7 +85,6 @@ class RepositoriesController < ApplicationController
|
|||
end
|
||||
|
||||
def rename_modal
|
||||
@repository = Repository.find(params[:repository_id])
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
render json: {
|
||||
|
@ -98,7 +97,6 @@ class RepositoriesController < ApplicationController
|
|||
end
|
||||
|
||||
def update
|
||||
@repository = Repository.find(params[:id])
|
||||
old_name = @repository.name
|
||||
@repository.update_attributes(repository_params)
|
||||
|
||||
|
@ -118,7 +116,6 @@ class RepositoriesController < ApplicationController
|
|||
end
|
||||
|
||||
def copy_modal
|
||||
@repository = Repository.find(params[:repository_id])
|
||||
@tmp_repository = Repository.new(
|
||||
team: @team,
|
||||
created_by: current_user,
|
||||
|
@ -136,7 +133,6 @@ class RepositoriesController < ApplicationController
|
|||
end
|
||||
|
||||
def copy
|
||||
@repository = Repository.find(params[:repository_id])
|
||||
@tmp_repository = Repository.new(
|
||||
team: @team,
|
||||
created_by: current_user
|
||||
|
@ -171,7 +167,6 @@ class RepositoriesController < ApplicationController
|
|||
|
||||
# AJAX actions
|
||||
def repository_table_index
|
||||
@repository = Repository.find_by_id(params[:repository_id])
|
||||
if @repository.nil? || !can_view_repository(@repository)
|
||||
render_403
|
||||
else
|
||||
|
@ -247,6 +242,15 @@ class RepositoriesController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def export_repository
|
||||
if params[:row_ids] && params[:header_ids]
|
||||
generate_zip
|
||||
else
|
||||
flash[:alert] = t('zip_export.export_error')
|
||||
end
|
||||
redirect_to :back
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def repostiory_import_actions
|
||||
|
@ -260,6 +264,12 @@ class RepositoriesController < ApplicationController
|
|||
end
|
||||
|
||||
def load_vars
|
||||
repository_id = params[:id] || params[:repository_id]
|
||||
@repository = Repository.find_by_id(repository_id)
|
||||
render_404 unless @repository
|
||||
end
|
||||
|
||||
def load_parent_vars
|
||||
@team = Team.find_by_id(params[:team_id])
|
||||
render_404 unless @team
|
||||
@repositories = @team.repositories.order(created_at: :asc)
|
||||
|
@ -273,6 +283,10 @@ class RepositoriesController < ApplicationController
|
|||
render_403 unless can_view_team_repositories(@team)
|
||||
end
|
||||
|
||||
def check_view_permissions
|
||||
render_403 unless can_view_repository(@repository)
|
||||
end
|
||||
|
||||
def check_create_permissions
|
||||
render_403 unless can_create_repository(@team)
|
||||
end
|
||||
|
@ -299,4 +313,66 @@ class RepositoriesController < ApplicationController
|
|||
status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
def generate_zip
|
||||
# Fetch rows in the same order as in the currently viewed datatable
|
||||
ordered_row_ids = params[:row_ids]
|
||||
id_row_map = RepositoryRow.where(id: ordered_row_ids,
|
||||
repository: @repository)
|
||||
.index_by(&:id)
|
||||
ordered_rows = ordered_row_ids.collect { |id| id_row_map[id.to_i] }
|
||||
|
||||
zip = ZipExport.create(user: current_user)
|
||||
zip.generate_exportable_zip(
|
||||
current_user,
|
||||
to_csv(ordered_rows, params[:header_ids]),
|
||||
:repositories
|
||||
)
|
||||
end
|
||||
|
||||
def to_csv(rows, column_ids)
|
||||
require 'csv'
|
||||
|
||||
# Parse column names
|
||||
csv_header = []
|
||||
column_ids.each do |c_id|
|
||||
csv_header << case c_id.to_i
|
||||
when -1, -2
|
||||
next
|
||||
when -3
|
||||
I18n.t('repositories.table.row_name')
|
||||
when -4
|
||||
I18n.t('repositories.table.added_by')
|
||||
when -5
|
||||
I18n.t('repositories.table.added_on')
|
||||
else
|
||||
column = RepositoryColumn.find_by_id(c_id)
|
||||
column ? column.name : nil
|
||||
end
|
||||
end
|
||||
|
||||
CSV.generate do |csv|
|
||||
csv << csv_header
|
||||
rows.each do |row|
|
||||
csv_row = []
|
||||
column_ids.each do |c_id|
|
||||
csv_row << case c_id.to_i
|
||||
when -1, -2
|
||||
next
|
||||
when -3
|
||||
row.name
|
||||
when -4
|
||||
row.created_by.full_name
|
||||
when -5
|
||||
I18n.l(row.created_at, format: :full)
|
||||
else
|
||||
cell = row.repository_cells
|
||||
.find_by(repository_column_id: c_id)
|
||||
cell ? cell.value.data : nil
|
||||
end
|
||||
end
|
||||
csv << csv_row
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -113,11 +113,11 @@ class RepositoryColumnsController < ApplicationController
|
|||
end
|
||||
|
||||
def check_update_permissions
|
||||
render_403 unless can_edit_columns_in_repository(@repository)
|
||||
render_403 unless can_edit_column_in_repository(@repository_column)
|
||||
end
|
||||
|
||||
def check_destroy_permissions
|
||||
render_403 unless can_delete_columns_in_repository(@repository)
|
||||
render_403 unless can_delete_column_in_repository(@repository_column)
|
||||
end
|
||||
|
||||
def repository_column_params
|
||||
|
|
|
@ -21,7 +21,6 @@ class RepositoryRowsController < ApplicationController
|
|||
record.name = record_params[:name] unless record_params[:name].blank?
|
||||
unless record.save
|
||||
errors[:default_fields] = record.errors.messages
|
||||
raise ActiveRecord::RecordInvalid
|
||||
end
|
||||
if params[:repository_cells]
|
||||
params[:repository_cells].each do |key, value|
|
||||
|
@ -37,29 +36,31 @@ class RepositoryRowsController < ApplicationController
|
|||
repository_column: column
|
||||
}
|
||||
)
|
||||
unless cell_value.save
|
||||
if cell_value.save
|
||||
record_annotation_notification(record, cell_value.repository_cell)
|
||||
else
|
||||
errors[:repository_cells] << {
|
||||
"#{cell.repository_column.id}": cell_value.errors.messages
|
||||
"#{column.id}": cell_value.errors.messages
|
||||
}
|
||||
raise ActiveRecord::RecordInvalid
|
||||
end
|
||||
record_annotation_notification(record, cell_value.repository_cell)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
render json: { id: record.id,
|
||||
flash: t('repositories.create.success_flash',
|
||||
record: escape_input(record.name),
|
||||
repository: escape_input(@repository.name)) },
|
||||
status: :ok
|
||||
if errors[:default_fields].empty? && errors[:repository_cells].empty?
|
||||
render json: { id: record.id,
|
||||
flash: t('repositories.create.success_flash',
|
||||
record: escape_input(record.name),
|
||||
repository: escape_input(@repository.name)) },
|
||||
status: :ok
|
||||
else
|
||||
render json: errors,
|
||||
status: :bad_request
|
||||
end
|
||||
end
|
||||
end
|
||||
rescue
|
||||
respond_to do |format|
|
||||
format.json { render json: errors, status: :bad_request }
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
|
@ -94,7 +95,6 @@ class RepositoryRowsController < ApplicationController
|
|||
@record.name = record_params[:name].blank? ? nil : record_params[:name]
|
||||
unless @record.save
|
||||
errors[:default_fields] = @record.errors.messages
|
||||
raise ActiveRecord::RecordInvalid
|
||||
end
|
||||
if params[:repository_cells]
|
||||
params[:repository_cells].each do |key, value|
|
||||
|
@ -104,13 +104,14 @@ class RepositoryRowsController < ApplicationController
|
|||
if existing
|
||||
# Cell exists and new value present, so update value
|
||||
existing.value.data = value
|
||||
unless existing.value.save
|
||||
if existing.value.save
|
||||
record_annotation_notification(@record, existing)
|
||||
else
|
||||
errors[:repository_cells] << {
|
||||
"#{cell.repository_column_id}": existing.value.errors.messages
|
||||
"#{existing.repository_column_id}":
|
||||
existing.value.errors.messages
|
||||
}
|
||||
raise ActiveRecord::RecordInvalid
|
||||
end
|
||||
record_annotation_notification(@record, existing)
|
||||
else
|
||||
# Looks like it is a new cell, so we need to create new value, cell
|
||||
# will be created automatically
|
||||
|
@ -126,13 +127,13 @@ class RepositoryRowsController < ApplicationController
|
|||
repository_column: column
|
||||
}
|
||||
)
|
||||
unless value.save
|
||||
if value.save
|
||||
record_annotation_notification(@record, value.repository_cell)
|
||||
else
|
||||
errors[:repository_cells] << {
|
||||
"#{cell.repository_column_id}": value.errors.messages
|
||||
"#{column.id}": value.errors.messages
|
||||
}
|
||||
raise ActiveRecord::RecordInvalid
|
||||
end
|
||||
record_annotation_notification(@record, value.repository_cell)
|
||||
end
|
||||
end
|
||||
# Clean up empty cells, not present in updated record
|
||||
|
@ -145,24 +146,26 @@ class RepositoryRowsController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
# Row sucessfully updated, so sending response to client
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
render json: {
|
||||
id: @record.id,
|
||||
flash: t(
|
||||
'repositories.update.success_flash',
|
||||
record: escape_input(@record.name),
|
||||
repository: escape_input(@repository.name)
|
||||
)
|
||||
},
|
||||
status: :ok
|
||||
if errors[:default_fields].empty? && errors[:repository_cells].empty?
|
||||
# Row sucessfully updated, so sending response to client
|
||||
render json: {
|
||||
id: @record.id,
|
||||
flash: t(
|
||||
'repositories.update.success_flash',
|
||||
record: escape_input(@record.name),
|
||||
repository: escape_input(@repository.name)
|
||||
)
|
||||
},
|
||||
status: :ok
|
||||
else
|
||||
# Errors
|
||||
render json: errors,
|
||||
status: :bad_request
|
||||
end
|
||||
end
|
||||
end
|
||||
rescue
|
||||
respond_to do |format|
|
||||
format.json { render json: errors, status: :bad_request }
|
||||
end
|
||||
end
|
||||
|
||||
def delete_records
|
||||
|
@ -175,7 +178,8 @@ class RepositoryRowsController < ApplicationController
|
|||
end
|
||||
end
|
||||
if deleted_count.zero?
|
||||
flash = t('repositories.destroy.no_deleted_records_flash')
|
||||
flash = t('repositories.destroy.no_deleted_records_flash',
|
||||
other_records_number: params[:selected_rows].count)
|
||||
elsif deleted_count != params[:selected_rows].count
|
||||
not_deleted_count = params[:selected_rows].count - deleted_count
|
||||
flash = t('repositories.destroy.contains_other_records_flash',
|
||||
|
@ -186,7 +190,8 @@ class RepositoryRowsController < ApplicationController
|
|||
records_number: deleted_count)
|
||||
end
|
||||
respond_to do |format|
|
||||
format.json { render json: { flash: flash }, status: :ok }
|
||||
color = deleted_count.zero? ? 'info' : 'success'
|
||||
format.json { render json: { flash: flash, color: color }, status: :ok }
|
||||
end
|
||||
else
|
||||
respond_to do |format|
|
||||
|
@ -219,7 +224,7 @@ class RepositoryRowsController < ApplicationController
|
|||
end
|
||||
|
||||
def check_edit_permissions
|
||||
render_403 unless can_edit_repository_records(@repository)
|
||||
render_403 unless can_edit_repository_record(@record)
|
||||
end
|
||||
|
||||
def check_destroy_permissions
|
||||
|
|
|
@ -26,53 +26,27 @@ class ResultAssetsController < ApplicationController
|
|||
end
|
||||
|
||||
def create
|
||||
@asset = Asset.new(result_params[:asset_attributes])
|
||||
@asset.created_by = current_user
|
||||
@asset.last_modified_by = current_user
|
||||
@asset.team = current_team
|
||||
@result = Result.new(
|
||||
user: current_user,
|
||||
my_module: @my_module,
|
||||
name: result_params[:name],
|
||||
asset: @asset
|
||||
)
|
||||
@result.last_modified_by = current_user
|
||||
|
||||
obj = create_multiple_results
|
||||
respond_to do |format|
|
||||
if (@result.save and @asset.save) then
|
||||
# Post process file here
|
||||
@asset.post_process_file(@my_module.experiment.project.team)
|
||||
|
||||
# Generate activity
|
||||
Activity.create(
|
||||
type_of: :add_result,
|
||||
user: current_user,
|
||||
project: @my_module.experiment.project,
|
||||
experiment: @my_module.experiment,
|
||||
my_module: @my_module,
|
||||
message: t(
|
||||
"activities.add_asset_result",
|
||||
user: current_user.full_name,
|
||||
result: @result.name,
|
||||
)
|
||||
)
|
||||
|
||||
if obj.fetch(:status)
|
||||
format.html do
|
||||
flash[:success] = t(
|
||||
"result_assets.create.success_flash",
|
||||
module: @my_module.name)
|
||||
flash[:success] = t('result_assets.create.success_flash',
|
||||
module: @my_module.name)
|
||||
redirect_to results_my_module_path(@my_module)
|
||||
end
|
||||
format.json do
|
||||
render json: {
|
||||
status: 'ok',
|
||||
html: render_to_string(
|
||||
partial: 'my_modules/result.html.erb', locals: { result: @result }
|
||||
partial: 'my_modules/results.html.erb',
|
||||
locals: { results: obj.fetch(:results) }
|
||||
)
|
||||
}, status: :ok
|
||||
end
|
||||
else
|
||||
format.json { render json: @result.errors, status: :bad_request }
|
||||
flash[:error] = t('result_assets.error_flash')
|
||||
format.json do
|
||||
render json: {}, status: :bad_request
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -249,4 +223,40 @@ class ResultAssetsController < ApplicationController
|
|||
]
|
||||
)
|
||||
end
|
||||
|
||||
def create_multiple_results
|
||||
success = true
|
||||
results = []
|
||||
params[:results_files].each_with_index do |file, index|
|
||||
asset = Asset.new(file: file.second,
|
||||
created_by: current_user,
|
||||
last_modified_by: current_user,
|
||||
team: current_team)
|
||||
result = Result.new(user: current_user,
|
||||
my_module: @my_module,
|
||||
name: params[:results_names][index.to_s],
|
||||
asset: asset,
|
||||
last_modified_by: current_user)
|
||||
if result.save && asset.save
|
||||
results << result
|
||||
# Post process file here
|
||||
asset.post_process_file(@my_module.experiment.project.team)
|
||||
|
||||
# Generate activity
|
||||
Activity.create(
|
||||
type_of: :add_result,
|
||||
user: current_user,
|
||||
project: @my_module.experiment.project,
|
||||
experiment: @my_module.experiment,
|
||||
my_module: @my_module,
|
||||
message: t('activities.add_asset_result',
|
||||
user: current_user.full_name,
|
||||
result: result.name)
|
||||
)
|
||||
else
|
||||
success = false
|
||||
end
|
||||
end
|
||||
{ status: success, results: results }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -44,7 +44,6 @@ class StepsController < ApplicationController
|
|||
table.created_by = current_user
|
||||
table.team = current_team
|
||||
end
|
||||
|
||||
# Update default checked state
|
||||
@step.checklists.each do |checklist|
|
||||
checklist.checklist_items.each do |checklist_item|
|
||||
|
|
|
@ -262,26 +262,20 @@ class TeamsController < ApplicationController
|
|||
end
|
||||
|
||||
def export_samples
|
||||
require "csv"
|
||||
|
||||
respond_to do |format|
|
||||
if params[:sample_ids].present? and params[:header_ids].present?
|
||||
samples = []
|
||||
|
||||
params[:sample_ids].each do |id|
|
||||
sample = Sample.find_by_id(id)
|
||||
|
||||
if sample
|
||||
samples << sample
|
||||
end
|
||||
end
|
||||
format.csv { send_data @team.to_csv(samples, params[:header_ids]) }
|
||||
else
|
||||
format.csv { render nothing: true }
|
||||
end
|
||||
if params[:sample_ids] && params[:header_ids]
|
||||
generate_samples_zip
|
||||
else
|
||||
flash[:alert] = t('zip_export.export_error')
|
||||
end
|
||||
redirect_to :back
|
||||
end
|
||||
|
||||
def routing_error(error = 'Routing error', status = :not_found, exception=nil)
|
||||
redirect_to root_path
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_vars
|
||||
@team = Team.find_by_id(params[:id])
|
||||
|
||||
|
@ -302,8 +296,12 @@ class TeamsController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def routing_error(error = 'Routing error', status = :not_found, exception=nil)
|
||||
redirect_to root_path
|
||||
def generate_samples_zip
|
||||
zip = ZipExport.create(user: current_user)
|
||||
zip.generate_exportable_zip(
|
||||
current_user,
|
||||
@team.to_csv(Sample.where(id: params[:sample_ids]), params[:header_ids]),
|
||||
:samples
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -102,7 +102,7 @@ class RepositoryDatatable < AjaxDatatablesRails::Base
|
|||
records.map do |record|
|
||||
row = {
|
||||
'DT_RowId': record.id,
|
||||
'1': @my_module ? assigned_row(record) : '',
|
||||
'1': assigned_row(record),
|
||||
'2': escape_input(record.name),
|
||||
'3': I18n.l(record.created_at, format: :full),
|
||||
'4': escape_input(record.created_by.full_name),
|
||||
|
@ -118,9 +118,12 @@ class RepositoryDatatable < AjaxDatatablesRails::Base
|
|||
# Add custom columns
|
||||
record.repository_cells.each do |cell|
|
||||
row[@columns_mappings[cell.repository_column.id]] =
|
||||
custom_auto_link(cell.value.data,
|
||||
simple_format: true,
|
||||
team: @team)
|
||||
custom_auto_link(
|
||||
display_tooltip(cell.value.data,
|
||||
Constants::NAME_MAX_LENGTH),
|
||||
simple_format: true,
|
||||
team: @team
|
||||
)
|
||||
end
|
||||
row
|
||||
end
|
||||
|
@ -138,18 +141,14 @@ class RepositoryDatatable < AjaxDatatablesRails::Base
|
|||
# after that "data" function will return json
|
||||
def get_raw_records
|
||||
repository_rows = RepositoryRow
|
||||
.includes(
|
||||
.preload(
|
||||
:repository_columns,
|
||||
:created_by
|
||||
# repository_cells: :value
|
||||
).references(
|
||||
:repository_columns,
|
||||
:created_by
|
||||
:created_by,
|
||||
repository_cells: :value
|
||||
)
|
||||
.joins(:created_by)
|
||||
.where(repository: @repository)
|
||||
|
||||
@assigned_rows = @my_module.repository_rows if @my_module
|
||||
|
||||
# Make mappings of custom columns, so we have same id for every column
|
||||
i = 5
|
||||
@columns_mappings = {}
|
||||
|
@ -157,6 +156,24 @@ class RepositoryDatatable < AjaxDatatablesRails::Base
|
|||
@columns_mappings[column.id] = i.to_s
|
||||
i += 1
|
||||
end
|
||||
|
||||
if @my_module
|
||||
@assigned_rows = @my_module.repository_rows
|
||||
.preload(
|
||||
:repository_columns,
|
||||
:created_by,
|
||||
repository_cells: :value
|
||||
)
|
||||
.joins(:created_by)
|
||||
.where(repository: @repository)
|
||||
return @assigned_rows if params[:assigned] == 'assigned'
|
||||
else
|
||||
@assigned_rows = repository_rows.joins(
|
||||
'INNER JOIN my_module_repository_rows ON
|
||||
(repository_rows.id = my_module_repository_rows.repository_row_id)'
|
||||
)
|
||||
end
|
||||
|
||||
repository_rows
|
||||
end
|
||||
|
||||
|
@ -166,32 +183,73 @@ class RepositoryDatatable < AjaxDatatablesRails::Base
|
|||
# number of samples/all samples it's dependant upon sort_record query
|
||||
def fetch_records
|
||||
records = get_raw_records
|
||||
records = @assigned_rows if @my_module && params[:assigned] == 'assigned'
|
||||
records = filter_records(records) if params[:search].present?
|
||||
records = sort_records(records) if params[:order].present?
|
||||
records = paginate_records(records) unless params[:length].present? &&
|
||||
params[:length] == '-1'
|
||||
escape_special_chars
|
||||
records = filter_records(records) if params[:search].present? &&
|
||||
!sorting_by_custom_column
|
||||
records = paginate_records(records) if !(params[:length].present? &&
|
||||
params[:length] == '-1') &&
|
||||
!sorting_by_custom_column
|
||||
records
|
||||
end
|
||||
|
||||
# Overriden to make it work for custom columns, because they are polymorphic
|
||||
# NOTE: Function assumes the provided records/rows are only from the current
|
||||
# repository!
|
||||
def filter_records(repo_rows)
|
||||
return repo_rows unless params[:search].present? &&
|
||||
params[:search][:value].present?
|
||||
search_val = params[:search][:value]
|
||||
|
||||
filtered_rows = repo_rows.find_by_sql(
|
||||
"SELECT DISTINCT repository_rows.*
|
||||
FROM repository_rows
|
||||
INNER JOIN (
|
||||
SELECT users.*
|
||||
FROM users
|
||||
) AS users
|
||||
ON users.id = repository_rows.created_by_id
|
||||
LEFT OUTER JOIN (
|
||||
SELECT repository_cells.repository_row_id,
|
||||
repository_text_values.data AS text_value,
|
||||
to_char(repository_date_values.data, 'DD.MM.YYYY HH24:MI')
|
||||
AS date_value
|
||||
FROM repository_cells
|
||||
INNER JOIN repository_text_values
|
||||
ON repository_text_values.id = repository_cells.value_id
|
||||
FULL OUTER JOIN repository_date_values
|
||||
ON repository_date_values.id = repository_cells.value_id
|
||||
) AS values
|
||||
ON values.repository_row_id = repository_rows.id
|
||||
WHERE repository_rows.repository_id = #{@repository.id}
|
||||
AND (repository_rows.name ILIKE '%#{search_val}%'
|
||||
OR to_char(repository_rows.created_at, 'DD.MM.YYYY HH24:MI')
|
||||
ILIKE '%#{search_val}%'
|
||||
OR users.full_name ILIKE '%#{search_val}%'
|
||||
OR text_value ILIKE '%#{search_val}%'
|
||||
OR date_value ILIKE '%#{search_val}%')"
|
||||
)
|
||||
repo_rows.where(id: filtered_rows)
|
||||
end
|
||||
|
||||
# Override default sort method if needed
|
||||
def sort_records(records)
|
||||
if params[:order].present? && params[:order].length == 1
|
||||
if sort_column(params[:order].values[0]) == ASSIGNED_SORT_COL
|
||||
# If "assigned" column is sorted
|
||||
direction = sort_null_direction(params[:order].values[0])
|
||||
if @my_module
|
||||
# Depending on the sort, order nulls first or
|
||||
# nulls last on repository_cells association
|
||||
direction = sort_null_direction(params[:order].values[0])
|
||||
records.joins(
|
||||
"LEFT OUTER JOIN my_module_repository_rows ON
|
||||
(repository_rows.id = my_module_repository_rows.repository_row_id
|
||||
AND (my_module_repository_rows.my_module_id = #{@my_module.id} OR
|
||||
my_module_repository_rows.id IS NULL))"
|
||||
).order("my_module_repository_rows.id NULLS #{direction}")
|
||||
else
|
||||
records.joins(
|
||||
'LEFT OUTER JOIN my_module_repository_rows ON
|
||||
(repository_rows.id = my_module_repository_rows.repository_row_id)'
|
||||
).order("my_module_repository_rows.id NULLS #{direction}")
|
||||
end
|
||||
elsif sorting_by_custom_column
|
||||
# Check if have to filter records first
|
||||
|
@ -237,18 +295,14 @@ class RepositoryDatatable < AjaxDatatablesRails::Base
|
|||
# as sq ORDER BY CASE WHEN sq.custom_field_id = #{column_id} THEN 1 ELSE 2 END #{dir}, sq.value #{dir}
|
||||
# LIMIT #{per_page} OFFSET #{offset}")
|
||||
|
||||
RepositoryRow.find_by_sql(
|
||||
"SELECT repository_rows.*, values.value AS value
|
||||
FROM repository_rows
|
||||
LEFT OUTER JOIN (SELECT repository_cells.*,
|
||||
records.joins(
|
||||
"LEFT OUTER JOIN (SELECT repository_cells.repository_row_id,
|
||||
repository_text_values.data AS value FROM repository_cells
|
||||
INNER JOIN repository_text_values
|
||||
ON repository_text_values.id = repository_cells.value_id
|
||||
WHERE repository_cells.repository_column_id = #{column_id}) AS values
|
||||
ON values.repository_row_id = repository_rows.id
|
||||
WHERE repository_rows.repository_id = #{@repository.id}
|
||||
ORDER BY value #{dir} LIMIT #{per_page} OFFSET #{offset}"
|
||||
)
|
||||
ON values.repository_row_id = repository_rows.id"
|
||||
).order("values.value #{dir}")
|
||||
else
|
||||
super(records)
|
||||
end
|
||||
|
|
|
@ -21,6 +21,7 @@ class SampleDatatable < AjaxDatatablesRails::Base
|
|||
'regex' => false,
|
||||
'caseInsensitive' => true },
|
||||
'columns' => [],
|
||||
'assigned' => 'all',
|
||||
'ColReorder' => [*0..6]
|
||||
}
|
||||
7.times do
|
||||
|
@ -178,10 +179,14 @@ class SampleDatatable < AjaxDatatablesRails::Base
|
|||
@assigned_samples = @my_module.samples
|
||||
|
||||
samples = samples.joins("LEFT OUTER JOIN sample_my_modules ON
|
||||
(samples.id = sample_my_modules.sample_id AND
|
||||
(sample_my_modules.my_module_id = #{@my_module.id.to_s} OR
|
||||
sample_my_modules.id IS NULL))")
|
||||
.references(:sample_my_modules)
|
||||
(samples.id = sample_my_modules.sample_id AND
|
||||
(sample_my_modules.my_module_id =
|
||||
#{@my_module.id} OR
|
||||
sample_my_modules.id IS NULL))")
|
||||
.references(:sample_my_modules)
|
||||
if params[:assigned] == 'assigned'
|
||||
samples = samples.where('"sample_my_modules"."id" > 0')
|
||||
end
|
||||
elsif @project
|
||||
@assigned_samples = @project.assigned_samples
|
||||
ids = @project.my_modules_ids
|
||||
|
@ -198,6 +203,16 @@ class SampleDatatable < AjaxDatatablesRails::Base
|
|||
sample_my_modules.id IS NULL))")
|
||||
.references(:sample_my_modules)
|
||||
end
|
||||
if params[:assigned] == 'assigned'
|
||||
samples = samples.joins('LEFT OUTER JOIN "my_modules" ON
|
||||
"my_modules"."id" =
|
||||
"sample_my_modules"."my_module_id"')
|
||||
.joins('LEFT OUTER JOIN "experiments" ON
|
||||
"experiments"."id" =
|
||||
"my_modules"."experiment_id"')
|
||||
.where('"experiments"."project_id" = ?', @project.id)
|
||||
.where('"my_modules"."nr_of_assigned_samples" > 0')
|
||||
end
|
||||
elsif @experiment
|
||||
@assigned_samples = @experiment.assigned_samples
|
||||
ids = @experiment.my_modules.select(:id)
|
||||
|
@ -207,6 +222,14 @@ class SampleDatatable < AjaxDatatablesRails::Base
|
|||
(sample_my_modules.my_module_id IN (#{ids.to_sql}) OR
|
||||
sample_my_modules.id IS NULL))")
|
||||
.references(:sample_my_modules)
|
||||
if params[:assigned] == 'assigned'
|
||||
samples = samples.joins('LEFT OUTER JOIN "my_modules" ON
|
||||
"my_modules"."id" =
|
||||
"sample_my_modules"."my_module_id"')
|
||||
.where('"my_modules"."experiment_id" = ?',
|
||||
@experiment.id)
|
||||
.where('"my_modules"."nr_of_assigned_samples" > 0')
|
||||
end
|
||||
end
|
||||
|
||||
# Make mappings of custom fields, so we have same id for every column
|
||||
|
@ -297,9 +320,9 @@ class SampleDatatable < AjaxDatatablesRails::Base
|
|||
.distinct
|
||||
|
||||
# check the input param and merge the two arrays of ids
|
||||
if params[:order].values[0]["dir"] == "asc"
|
||||
if params[:order].values[0]['dir'] == 'asc'
|
||||
ids = assigned + unassigned
|
||||
elsif params[:order].values[0]["dir"] == "desc"
|
||||
elsif params[:order].values[0]['dir'] == 'desc'
|
||||
ids = unassigned + assigned
|
||||
end
|
||||
ids = ids.collect { |s| s.id }
|
||||
|
|
|
@ -1,13 +1,20 @@
|
|||
module ActivityHelper
|
||||
def activity_truncate(message, len = Constants::NAME_TRUNCATION_LENGTH)
|
||||
activity_title = message.match(/<strong>(.*?)<\/strong>/)[1]
|
||||
if activity_title.length > Constants::NAME_TRUNCATION_LENGTH
|
||||
title = "<div class='modal-tooltip'>#{truncate(activity_title, length: len)}
|
||||
<span class='modal-tooltiptext'>#{activity_title}</span></div>"
|
||||
else
|
||||
title = truncate(activity_title, length: len)
|
||||
activity_titles = message.scan(/<strong>(.*?)<\/strong>/)
|
||||
activity_titles.each do |activity_title|
|
||||
activity_title = activity_title[0]
|
||||
if activity_title.length > Constants::NAME_TRUNCATION_LENGTH
|
||||
title = "<div class='modal-tooltip'>
|
||||
#{truncate(activity_title, length: len)}
|
||||
<span class='modal-tooltiptext'>
|
||||
#{activity_title}
|
||||
</span>
|
||||
</div>"
|
||||
else
|
||||
title = truncate(activity_title, length: len)
|
||||
end
|
||||
message = message.gsub(/#{Regexp.escape(activity_title)}/, title)
|
||||
end
|
||||
message = message.gsub(/#{activity_title}/, title )
|
||||
sanitize_input(message) if message
|
||||
end
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ module ApplicationHelper
|
|||
end
|
||||
|
||||
def display_tooltip(message, len = Constants::NAME_TRUNCATION_LENGTH)
|
||||
if message.strip.length > Constants::NAME_TRUNCATION_LENGTH
|
||||
if message.strip.length > len
|
||||
sanitize_input("<div class='modal-tooltip'> \
|
||||
#{truncate(message.strip, length: len)} \
|
||||
<span class='modal-tooltiptext'> \
|
||||
|
@ -233,11 +233,29 @@ module ApplicationHelper
|
|||
raw(user_description) + raw('" >') + user_name + raw('</a>')
|
||||
end
|
||||
|
||||
# Dirty, dirty hack for displaying images in reports
|
||||
def user_avatar_absolute_url(user, style)
|
||||
unless user.avatar(style) == '/images/icon_small/missing.png'
|
||||
return user.avatar(style)
|
||||
prefix = ''
|
||||
if ENV['PAPERCLIP_STORAGE'].present? &&
|
||||
ENV['MAIL_SERVER_URL'].present? &&
|
||||
ENV['PAPERCLIP_STORAGE'] != 'filesystem'
|
||||
prefix = ENV['MAIL_SERVER_URL']
|
||||
end
|
||||
URI.join(Rails.application.routes.url_helpers.root_url,
|
||||
"/images/#{style}/missing.png").to_s
|
||||
# for development
|
||||
prefix = 'localhost:3000' if ENV['MAIL_SERVER_URL'] == 'localhost'
|
||||
if !prefix.empty? &&
|
||||
!prefix.include?('http://') &&
|
||||
!prefix.include?('https://')
|
||||
prefix = if respond_to?(:request) && request.ssl?
|
||||
"https://#{prefix}"
|
||||
else
|
||||
"http://#{prefix}"
|
||||
end
|
||||
end
|
||||
|
||||
unless user.avatar(style) == '/images/icon_small/missing.png'
|
||||
return user.avatar(style, timeout: Constants::URL_LONG_EXPIRE_TIME)
|
||||
end
|
||||
url_for(prefix + "/images/#{style}/missing.png")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1058,12 +1058,8 @@ module PermissionHelper
|
|||
team.repositories.count < Constants::REPOSITORIES_LIMIT
|
||||
end
|
||||
|
||||
def can_view_repositories(team)
|
||||
is_normal_user_or_admin_of_team(team)
|
||||
end
|
||||
|
||||
def can_view_repository(repository)
|
||||
is_normal_user_or_admin_of_team(repository.team)
|
||||
is_member_of_team(repository.team)
|
||||
end
|
||||
|
||||
def can_edit_and_destroy_repository(repository)
|
||||
|
@ -1078,12 +1074,12 @@ module PermissionHelper
|
|||
is_normal_user_or_admin_of_team(repository.team)
|
||||
end
|
||||
|
||||
def can_delete_columns_in_repository(repository)
|
||||
is_normal_user_or_admin_of_team(repository.team)
|
||||
def can_delete_column_in_repository(column)
|
||||
is_normal_user_or_admin_of_team(column.repository.team)
|
||||
end
|
||||
|
||||
def can_edit_columns_in_repository(repository)
|
||||
is_normal_user_or_admin_of_team(repository.team)
|
||||
def can_edit_column_in_repository(column)
|
||||
is_normal_user_or_admin_of_team(column.repository.team)
|
||||
end
|
||||
|
||||
def can_create_repository_records(repository)
|
||||
|
@ -1094,8 +1090,8 @@ module PermissionHelper
|
|||
is_normal_user_or_admin_of_team(repository.team)
|
||||
end
|
||||
|
||||
def can_edit_repository_records(repository)
|
||||
is_normal_user_or_admin_of_team(repository.team)
|
||||
def can_edit_repository_record(record)
|
||||
is_normal_user_or_admin_of_team(record.repository.team)
|
||||
end
|
||||
|
||||
def can_delete_repository_records(repository)
|
||||
|
@ -1109,12 +1105,12 @@ module PermissionHelper
|
|||
end
|
||||
|
||||
def can_assign_repository_records(my_module, repository)
|
||||
can_edit_repository_records(repository) &&
|
||||
can_delete_repository_records(repository) &&
|
||||
is_technician_or_higher_of_project(my_module.experiment.project)
|
||||
end
|
||||
|
||||
def can_unassign_repository_records(my_module, repository)
|
||||
can_edit_repository_records(repository) &&
|
||||
can_delete_repository_records(repository) &&
|
||||
is_technician_or_higher_of_project(my_module.experiment.project)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -31,17 +31,21 @@ module SidebarHelper
|
|||
end
|
||||
|
||||
def module_action_to_link_to(my_module)
|
||||
case action_name
|
||||
when 'results'
|
||||
return results_my_module_url(my_module)
|
||||
when 'activities'
|
||||
return activities_my_module_url(my_module)
|
||||
when 'samples'
|
||||
return samples_my_module_url(my_module)
|
||||
when 'archive', 'module_archive', 'experiment_archive'
|
||||
return archive_my_module_url(my_module)
|
||||
if action_name == 'results'
|
||||
results_my_module_url(my_module)
|
||||
elsif action_name == 'activities'
|
||||
activities_my_module_url(my_module)
|
||||
elsif action_name == 'samples'
|
||||
samples_my_module_url(my_module)
|
||||
elsif action_name.in?(%w(archive module_archive experiment_archive))
|
||||
archive_my_module_url(my_module)
|
||||
elsif action_name == 'repository' && @repository
|
||||
repository_my_module_url(
|
||||
id: my_module.id,
|
||||
repository_id: @repository.id
|
||||
)
|
||||
else
|
||||
return protocols_my_module_url(my_module)
|
||||
protocols_my_module_url(my_module)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -18,6 +18,7 @@ module TinyMceHelper
|
|||
end
|
||||
|
||||
def generate_image_tag_from_token(text)
|
||||
return unless text
|
||||
regex = /\[~tiny_mce_id:([0-9a-zA-Z]+)\]/
|
||||
text.gsub(regex) do |el|
|
||||
match = el.match(regex)
|
||||
|
|
|
@ -84,8 +84,6 @@ class ReportElement < ActiveRecord::Base
|
|||
|
||||
if parent_model == 'experiment'
|
||||
destroy unless send(parent_model).project == report.project
|
||||
elsif parent_model == 'step'
|
||||
destroy unless send(parent_model).completed
|
||||
else
|
||||
destroy unless (send(parent_model).active? rescue send(parent_model))
|
||||
end
|
||||
|
|
|
@ -14,39 +14,41 @@ class RepositoryTableState < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def self.update_state(custom_column, column_index, user)
|
||||
table_state = RepositoryTableState.where(
|
||||
user: user,
|
||||
# table state of every user having access to this repository needs udpating
|
||||
table_states = RepositoryTableState.where(
|
||||
repository: custom_column.repository
|
||||
)
|
||||
return if table_state.empty?
|
||||
repository_state = table_state.first['state']
|
||||
if column_index
|
||||
# delete column
|
||||
repository_state['columns'].delete(column_index)
|
||||
repository_state['columns'].keys.each do |index|
|
||||
if index.to_i > column_index.to_i
|
||||
repository_state['columns'][(index.to_i - 1).to_s] =
|
||||
repository_state['columns'].delete(index)
|
||||
else
|
||||
index
|
||||
table_states.each do |table_state|
|
||||
repository_state = table_state['state']
|
||||
if column_index
|
||||
# delete column
|
||||
repository_state['columns'].delete(column_index)
|
||||
repository_state['columns'].keys.each do |index|
|
||||
if index.to_i > column_index.to_i
|
||||
repository_state['columns'][(index.to_i - 1).to_s] =
|
||||
repository_state['columns'].delete(index)
|
||||
else
|
||||
index
|
||||
end
|
||||
end
|
||||
end
|
||||
repository_state['ColReorder'].delete(column_index)
|
||||
repository_state['ColReorder'].map! do |index|
|
||||
if index.to_i > column_index.to_i
|
||||
(index.to_i - 1).to_s
|
||||
else
|
||||
index
|
||||
|
||||
repository_state['ColReorder'].delete(column_index)
|
||||
repository_state['ColReorder'].map! do |index|
|
||||
if index.to_i > column_index.to_i
|
||||
(index.to_i - 1).to_s
|
||||
else
|
||||
index
|
||||
end
|
||||
end
|
||||
else
|
||||
# add column
|
||||
index = repository_state['columns'].count
|
||||
repository_state['columns'][index] = RepositoryDatatable::
|
||||
REPOSITORY_TABLE_DEFAULT_STATE['columns'].first
|
||||
repository_state['ColReorder'].insert(2, index)
|
||||
end
|
||||
else
|
||||
# add column
|
||||
index = repository_state['columns'].count
|
||||
repository_state['columns'][index] = RepositoryDatatable::
|
||||
REPOSITORY_TABLE_DEFAULT_STATE['columns'].first
|
||||
repository_state['ColReorder'].insert(2, index)
|
||||
table_state.update(state: repository_state)
|
||||
end
|
||||
table_state.first.update(state: repository_state)
|
||||
end
|
||||
|
||||
def self.create_state(user, repository)
|
||||
|
|
|
@ -101,4 +101,14 @@ class ZipExport < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
def generate_samples_zip(tmp_dir, data, _options = {})
|
||||
file = FileUtils.touch("#{tmp_dir}/export.csv").first
|
||||
File.open(file, 'wb') { |f| f.write(data) }
|
||||
end
|
||||
|
||||
def generate_repositories_zip(tmp_dir, data, _options = {})
|
||||
file = FileUtils.touch("#{tmp_dir}/export.csv").first
|
||||
File.open(file, 'wb') { |f| f.write(data) }
|
||||
end
|
||||
end
|
||||
|
|
5
app/views/my_modules/_results.html.erb
Normal file
5
app/views/my_modules/_results.html.erb
Normal file
|
@ -0,0 +1,5 @@
|
|||
<div data-container="new-reports">
|
||||
<% results.reverse_each do |result| %>
|
||||
<%= render partial: 'my_modules/result.html.erb', locals: { result: result } %>
|
||||
<% end %>
|
||||
</div>
|
|
@ -1,4 +1,6 @@
|
|||
<% provide(:head_title, t("my_modules.protocols.head_title", project: h(@project.name), module: h(@my_module.name)).html_safe) %>
|
||||
|
||||
<%= render partial: 'shared/drag_n_drop_overlay' %>
|
||||
<%= render partial: "shared/sidebar" %>
|
||||
<%= render partial: "shared/secondary_navigation" %>
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<% provide(:head_title, t("my_modules.results.head_title", project: h(@project.name), module: h(@my_module.name)).html_safe) %>
|
||||
<%= render partial: "shared/sidebar" %>
|
||||
<%= render partial: "shared/secondary_navigation" %>
|
||||
<%= render partial: 'shared/drag_n_drop_overlay' %>
|
||||
|
||||
<div id="results-toolbar">
|
||||
<div class="pull-right">
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<% provide(:head_title, t("protocols.edit.head_title")) %>
|
||||
|
||||
<%= render partial: 'shared/drag_n_drop_overlay' %>
|
||||
<%= render partial: "protocols/breadcrumbs.html.erb",
|
||||
locals: { teams: @teams,
|
||||
current_team: @protocol.team,
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<div class="report-element-header">
|
||||
<div class="row">
|
||||
<div class="pull-left activity-icon">
|
||||
<span class="glyphicon glyphicon glyphicon-equalizer"></span>
|
||||
<span class="glyphicon glyphicon-equalizer"></span>
|
||||
</div>
|
||||
<div class="pull-left activity-name">
|
||||
<%=t "projects.reports.elements.module_activity.name", my_module: my_module.name %>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<% if my_module.blank? and @my_module.present? then my_module = @my_module end %>
|
||||
<% timestamp = my_module.created_at %>
|
||||
<% name = my_module.name %>
|
||||
<div class="report-element report-module-element" data-ts="<%= timestamp.to_i %>" data-type="my_module" data-id='{ "my_module_id": <%= my_module.id %> }' data-scroll-id="<%= my_module.id %>" data-modal-title="<%=t "projects.reports.elements.modals.module_contents.head_title", module: my_module.name %>" data-name="<%= name %>" data-icon-class="glyphicon-credit-card">
|
||||
<div class="report-element report-module-element" data-ts="<%= timestamp.to_i %>" data-type="my_module" data-id='{ "my_module_id": <%= my_module.id %> }' data-scroll-id="<%= my_module.id %>" data-modal-title="<%=t "projects.reports.elements.modals.module_contents.head_title", module: my_module.name %>" data-name="<%= name %>" data-icon-class="glyphicon glyphicon-credit-card">
|
||||
<div class="report-element-header">
|
||||
<div class="row">
|
||||
<div class="pull-left user-time">
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
<% if order.blank? and @order.present? then order = @order end %>
|
||||
<% timestamp = Time.current + 1.year - 1.days %>
|
||||
<% rows_json = my_module.repository_json_hot(repository.id, order) %>
|
||||
<div class="report-element report-module-repository-element" data-sort-hot="1" data-ts="<%= timestamp.to_i %>" data-type="my_module_repository" data-id='{ "my_module_id": <%= my_module.id %>, "repository_id": <%= repository.id %> }' data-scroll-id="<%= "#{my_module.id}_#{repository.id}" %>" data-order="<%= order == :asc ? "asc" : "desc" %>" data-name="<%= repository.name %>" data-icon-class="glyphicon-oil">
|
||||
<div class="report-element report-module-repository-element" data-sort-hot="1" data-ts="<%= timestamp.to_i %>" data-type="my_module_repository" data-id='{ "my_module_id": <%= my_module.id %>, "repository_id": <%= repository.id %> }' data-scroll-id="<%= "#{my_module.id}_#{repository.id}" %>" data-order="<%= order == :asc ? "asc" : "desc" %>" data-name="<%= repository.name %>" data-icon-class="fa fa-cubes">
|
||||
<div class="report-element-header">
|
||||
<div class="row">
|
||||
<div class="pull-left repository-icon">
|
||||
<span class="glyphicon glyphicon-oil"></span>
|
||||
<span class="fa fa-cubes"></span>
|
||||
</div>
|
||||
<div class="pull-left repository-name">
|
||||
<%=t "projects.reports.elements.module_repository.name", repository: repository.name, my_module: my_module.name %>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<% comments = result.result_comments %>
|
||||
<% timestamp = asset.created_at %>
|
||||
<% name = result.name %>
|
||||
<% icon_class = is_image ? "glyphicon-picture" : "glyphicon-file" %>
|
||||
<% icon_class = 'glyphicon ' + (is_image ? 'glyphicon-picture' : 'glyphicon-file') %>
|
||||
<div class="report-element report-result-element report-result-asset-element" data-ts="<%= timestamp.to_i %>" data-type="result_asset" data-id='{ "result_id": <%= result.id %> }' data-scroll-id="<%= result.id %>" data-modal-title="<%=t "projects.reports.elements.modals.result_contents.head_title", result: result.name %>" data-name="<%= name %>" data-icon-class="<%= icon_class %>">
|
||||
<div class="report-element-header">
|
||||
<div class="row">
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<% comments = result.result_comments %>
|
||||
<% timestamp = table.created_at %>
|
||||
<% name = result.name %>
|
||||
<div class="report-element report-result-element report-result-table-element" data-ts="<%= timestamp.to_i %>" data-type="result_table" data-id='{ "result_id": <%= result.id %> }' data-scroll-id="<%= result.id %>" data-modal-title="<%=t "projects.reports.elements.modals.result_contents.head_title", result: result.name %>" data-name="<%= name %>" data-icon-class="glyphicon-th">
|
||||
<div class="report-element report-result-element report-result-table-element" data-ts="<%= timestamp.to_i %>" data-type="result_table" data-id='{ "result_id": <%= result.id %> }' data-scroll-id="<%= result.id %>" data-modal-title="<%=t "projects.reports.elements.modals.result_contents.head_title", result: result.name %>" data-name="<%= name %>" data-icon-class="glyphicon glyphicon-th">
|
||||
<div class="report-element-header">
|
||||
<div class="row">
|
||||
<div class="pull-left result-name-container">
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<% comments = result.result_comments %>
|
||||
<% timestamp = result.created_at %>
|
||||
<% name = result.name %>
|
||||
<div class="report-element report-result-element report-result-text-element" data-ts="<%= timestamp.to_i %>" data-type="result_text" data-id='{ "result_id": <%= result.id %> }' data-scroll-id="<%= result.id %>" data-modal-title="<%=t "projects.reports.elements.modals.result_contents.head_title", result: result.name %>" data-name="<%= name %>" data-icon-class="glyphicon-asterisk">
|
||||
<div class="report-element report-result-element report-result-text-element" data-ts="<%= timestamp.to_i %>" data-type="result_text" data-id='{ "result_id": <%= result.id %> }' data-scroll-id="<%= result.id %>" data-modal-title="<%=t "projects.reports.elements.modals.result_contents.head_title", result: result.name %>" data-name="<%= name %>" data-icon-class="glyphicon glyphicon-asterisk">
|
||||
<div class="report-element-header">
|
||||
<div class="row">
|
||||
<div class="pull-left result-icon">
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<% if order.blank? and @order.present? then order = @order end %>
|
||||
<% timestamp = Time.current + 1.year - 1.days %>
|
||||
<% samples_json = my_module.samples_json_hot(order) %>
|
||||
<div class="report-element report-module-samples-element" data-sort-hot="3" data-ts="<%= timestamp.to_i %>" data-type="my_module_samples" data-id='{ "my_module_id": <%= my_module.id %> }' data-scroll-id="<%= my_module.id %>" data-order="<%= order == :asc ? "asc" : "desc" %>" data-name="<%=t "projects.reports.elements.module_samples.sidebar_name" %>" data-icon-class="glyphicon-tint">
|
||||
<div class="report-element report-module-samples-element" data-sort-hot="3" data-ts="<%= timestamp.to_i %>" data-type="my_module_samples" data-id='{ "my_module_id": <%= my_module.id %> }' data-scroll-id="<%= my_module.id %>" data-order="<%= order == :asc ? "asc" : "desc" %>" data-name="<%=t "projects.reports.elements.module_samples.sidebar_name" %>" data-icon-class="glyphicon glyphicon-tint">
|
||||
<div class="report-element-header">
|
||||
<div class="row">
|
||||
<div class="pull-left samples-icon">
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<% assets = step.assets %>
|
||||
<% checklists = step.checklists %>
|
||||
<% comments = step.step_comments %>
|
||||
<div class="report-element report-step-element" data-ts="<%= timestamp.to_i %>" data-type="step" data-id='{ "step_id": <%= step.id %> }' data-scroll-id="<%= step.id %>" data-modal-title="<%=t "projects.reports.elements.modals.step_contents.head_title", step: step.name %>" data-name="<%=t "projects.reports.elements.step.sidebar_name", pos: (step.position + 1), name: step.name %>" data-icon-class="glyphicon-circle-arrow-right">
|
||||
<div class="report-element report-step-element" data-ts="<%= timestamp.to_i %>" data-type="step" data-id='{ "step_id": <%= step.id %> }' data-scroll-id="<%= step.id %>" data-modal-title="<%=t "projects.reports.elements.modals.step_contents.head_title", step: step.name %>" data-name="<%=t "projects.reports.elements.step.sidebar_name", pos: (step.position + 1), name: step.name %>" data-icon-class="glyphicon glyphicon-circle-arrow-right">
|
||||
<div class="report-element-header">
|
||||
<div class="row">
|
||||
<div class="pull-left user-time">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<% if project.blank? and @project.present? then project = @project end %>
|
||||
<% name = t("projects.reports.elements.project_header.title", project: project.name) %>
|
||||
<div class="report-element report-project-header-element" data-ts="ignore" data-type="project_header" data-id='{ "project_id": <%= project.id %> }' data-scroll-id="<%= project.id %>" data-name="<%= name %>" data-icon-class="glyphicon-header">
|
||||
<div class="report-element report-project-header-element" data-ts="ignore" data-type="project_header" data-id='{ "project_id": <%= project.id %> }' data-scroll-id="<%= project.id %>" data-name="<%= name %>" data-icon-class="glyphicon glyphicon-header">
|
||||
<div class="report-element-header">
|
||||
<div class="row">
|
||||
<div class="pull-left user-time">
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<% if order.blank? and @order.present? then order = @order end %>
|
||||
<% comments = result.result_comments.order(created_at: order) %>
|
||||
<% timestamp = Time.current + 1.year %>
|
||||
<div class="report-element report-comments-element report-result-comments-element" data-ts="<%= timestamp.to_i %>" data-order="<%= order == :asc ? "asc" : "desc" %>" data-type="result_comments" data-id='{ "result_id": <%= result.id %> }' data-scroll-id="<%= result.id %>" data-name="<%=t "projects.reports.elements.result_comments.sidebar_name" %>" data-icon-class="glyphicon-comment">
|
||||
<div class="report-element report-comments-element report-result-comments-element" data-ts="<%= timestamp.to_i %>" data-order="<%= order == :asc ? "asc" : "desc" %>" data-type="result_comments" data-id='{ "result_id": <%= result.id %> }' data-scroll-id="<%= result.id %>" data-name="<%=t "projects.reports.elements.result_comments.sidebar_name" %>" data-icon-class="glyphicon glyphicon-comment">
|
||||
<div class="report-element-header">
|
||||
<div class="row">
|
||||
<div class="pull-left comments-icon">
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<% if asset.blank? and @asset.present? then asset = @asset end %>
|
||||
<% is_image = asset.is_image? %>
|
||||
<% timestamp = asset.created_at %>
|
||||
<% icon_class = is_image ? 'glyphicon-picture' : 'glyphicon-file' %>
|
||||
<% icon_class = 'glyphicon ' + (is_image ? 'glyphicon-picture' : 'glyphicon-file') %>
|
||||
<div class="report-element report-step-attachment-element report-step-asset-element" data-ts="<%= timestamp.to_i %>" data-type="step_asset" data-id='{ "asset_id": <%= asset.id %> }' data-scroll-id="<%= asset.id %>" data-name="<%=t "projects.reports.elements.step_asset.sidebar_name", file: asset.file_file_name %>" data-icon-class="<%= icon_class %>">
|
||||
<div class="report-element-header">
|
||||
<div class="row">
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<% if checklist.blank? and @checklist.present? then checklist = @checklist end %>
|
||||
<% items = checklist.checklist_items %>
|
||||
<% timestamp = checklist.created_at %>
|
||||
<div class="report-element report-step-attachment-element report-step-checklist-element" data-ts="<%= timestamp.to_i %>" data-type="step_checklist" data-id='{ "checklist_id": <%= checklist.id %> }' data-scroll-id="<%= checklist.id %>" data-name="<%= checklist.name %>" data-icon-class="glyphicon-list">
|
||||
<div class="report-element report-step-attachment-element report-step-checklist-element" data-ts="<%= timestamp.to_i %>" data-type="step_checklist" data-id='{ "checklist_id": <%= checklist.id %> }' data-scroll-id="<%= checklist.id %>" data-name="<%= checklist.name %>" data-icon-class="glyphicon glyphicon-list">
|
||||
<div class="report-element-header">
|
||||
<div class="row">
|
||||
<div class="pull-left attachment-icon">
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<% if order.blank? and @order.present? then order = @order end %>
|
||||
<% comments = step.step_comments.order(created_at: order) %>
|
||||
<% timestamp = Time.current + 1.year %>
|
||||
<div class="report-element report-comments-element report-step-comments-element" data-ts="<%= timestamp.to_i %>" data-order="asc" data-type="step_comments" data-id='{ "step_id": <%= step.id %> }' data-scroll-id="<%= step.id %>" data-name="<%=t "projects.reports.elements.step_comments.sidebar_name" %>" data-icon-class="glyphicon-comment">
|
||||
<div class="report-element report-comments-element report-step-comments-element" data-ts="<%= timestamp.to_i %>" data-order="asc" data-type="step_comments" data-id='{ "step_id": <%= step.id %> }' data-scroll-id="<%= step.id %>" data-name="<%=t "projects.reports.elements.step_comments.sidebar_name" %>" data-icon-class="glyphicon glyphicon-comment">
|
||||
<div class="report-element-header">
|
||||
<div class="row">
|
||||
<div class="pull-left comments-icon">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<% if table.blank? and @table.present? then table = @table end %>
|
||||
<% timestamp = table.created_at %>
|
||||
<div class="report-element report-step-attachment-element report-step-table-element" data-ts="<%= timestamp.to_i %>" data-type="step_table" data-id='{ "table_id": <%= table.id %> }' data-scroll-id="<%= table.id %>" data-name="<%= table.name %>" data-icon-class="glyphicon-th">
|
||||
<div class="report-element report-step-attachment-element report-step-table-element" data-ts="<%= timestamp.to_i %>" data-type="step_table" data-id='{ "table_id": <%= table.id %> }' data-scroll-id="<%= table.id %>" data-name="<%= table.name %>" data-icon-class="glyphicon glyphicon-th">
|
||||
<div class="report-element-header">
|
||||
<div class="row">
|
||||
<div class="pull-left attachment-icon">
|
||||
|
|
24
app/views/repositories/_export_repository_modal.html.erb
Normal file
24
app/views/repositories/_export_repository_modal.html.erb
Normal file
|
@ -0,0 +1,24 @@
|
|||
<div class="modal fade"
|
||||
id="exportRepositoryModal"
|
||||
tabindex="-1"
|
||||
role="dialog"
|
||||
aria-labelledby="modal-export-repository-label">
|
||||
<%= bootstrap_form_tag(url: export_repository_team_path(repository),
|
||||
html: { id: 'form-export' }) do |f| %>
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title"><%=t 'zip_export.modal_label' %></h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<%=t('zip_export.repository_html', repository: repository.name) %>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type='button' class='btn btn-primary' data-dismiss='modal' id='export-repositories'> <%=t 'my_modules.repository.export' %> </button>
|
||||
<button type='button' class='btn btn-default' data-dismiss='modal' id='close-modal-export-repositories'><%= t('general.close')%></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
|
@ -1,5 +1,7 @@
|
|||
<%= render partial: "repositories/delete_record_modal.html.erb" %>
|
||||
<%= render partial: "repositories/delete_column_modal.html.erb" %>
|
||||
<%= render partial: 'repositories/export_repository_modal.html.erb',
|
||||
locals: { repository: repository } %>
|
||||
|
||||
<div id="alert-container"></div>
|
||||
|
||||
|
@ -18,6 +20,59 @@
|
|||
</button>
|
||||
<% end %>
|
||||
|
||||
<% if can_view_repository(repository) %>
|
||||
<a href="#" class="btn btn-default" id="exportRepositoriesButton">
|
||||
<span class="glyphicon glyphicon-cloud-download"></span>
|
||||
<span class="hidden-xs"><%= t("my_modules.repository.export") %></span>
|
||||
</a>
|
||||
<% end %>
|
||||
|
||||
<div class="repository-cog">
|
||||
<div class="dropdown">
|
||||
<div class="btn btn-default"
|
||||
type="button"
|
||||
data-toggle="dropdown"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="true"
|
||||
<%= "disabled='disabled'" if !can_edit_and_destroy_repository repository and !can_copy_repository repository %>>
|
||||
<span class="glyphicon glyphicon-cog"></span>
|
||||
<span class="caret"></span>
|
||||
</div>
|
||||
<% if can_edit_and_destroy_repository repository or can_copy_repository repository %>
|
||||
<ul class="dropdown-menu pull-right">
|
||||
<li class="dropdown-header">
|
||||
<%= t("repositories.index.options_dropdown.header") %>
|
||||
</li>
|
||||
<% if can_edit_and_destroy_repository repository %>
|
||||
<li>
|
||||
<%= link_to t('repositories.index.options_dropdown.rename'),
|
||||
team_repository_rename_modal_path(repository_id: repository),
|
||||
class: "rename-repo-option",
|
||||
remote: true %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if can_copy_repository(repository) %>
|
||||
<li>
|
||||
<%= link_to t('repositories.index.options_dropdown.copy'),
|
||||
team_repository_copy_modal_path(repository_id: repository),
|
||||
class: "copy-repo-option",
|
||||
remote: true %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if can_edit_and_destroy_repository repository %>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li>
|
||||
<%= link_to t('repositories.index.modal_delete.delete'),
|
||||
team_repository_destroy_modal_path(repository_id: repository),
|
||||
class: "delete-repo-option",
|
||||
remote: true %>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="datatables-buttons" style="display: inline;">
|
||||
<div id="repository-columns-dropdown" class="dropdown">
|
||||
<button class="btn btn-default dropdown-toggle" type="button" data-toggle="dropdown">
|
||||
|
@ -81,3 +136,4 @@
|
|||
%>
|
||||
<%= render partial: 'repositories/import_repository_records.html.erb',
|
||||
locals: { repository: repository } %>
|
||||
<%= javascript_include_tag 'repositories/edit', 'data-turbolinks-track' => true %>
|
||||
|
|
|
@ -15,18 +15,14 @@
|
|||
<thead>
|
||||
<tr>
|
||||
<th id="checkbox"><input name="select_all" value="1" type="checkbox"></th>
|
||||
<% if @my_module %>
|
||||
<th id="assigned"><%= t("repositories.table.assigned") %></th>
|
||||
<% else %>
|
||||
<th id="assigned"></th>
|
||||
<% end %>
|
||||
<th id="assigned"><%= t("repositories.table.assigned") %></th>
|
||||
<th id="row-name"><%= t("repositories.table.row_name") %></th>
|
||||
<th id="added-on"><%= t("repositories.table.added_on") %></th>
|
||||
<th id="added-by"><%= t("repositories.table.added_by") %></th>
|
||||
<% repository.repository_columns.each do |column| %>
|
||||
<th class="repository-column" id="<%= column.id %>"
|
||||
<%= 'data-editable' if can_edit_columns_in_repository(repository) %>
|
||||
<%= 'data-deletable' if can_delete_columns_in_repository(repository) %>
|
||||
<%= 'data-editable' if can_edit_column_in_repository(column) %>
|
||||
<%= 'data-deletable' if can_delete_column_in_repository(column) %>
|
||||
<%= "data-edit-url='#{edit_repository_repository_column_path(repository, column)}'" %>
|
||||
<%= "data-update-url='#{repository_repository_column_path(repository, column)}'" %>
|
||||
<%= "data-destroy-html-url='#{repository_columns_destroy_html_path(repository, column)}'" %>
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
<% if can_create_repository(current_team) %>
|
||||
href="<%= create_modal_team_repositories_path %>"
|
||||
class='create-repository'
|
||||
data-remote='true'
|
||||
<% end %>>
|
||||
<span class="glyphicon glyphicon-plus"></span>
|
||||
<span class="hidden-xs"> <%= t('repositories.index.add_new_repository_tab') %></span>
|
||||
|
@ -37,50 +38,9 @@
|
|||
<% @repositories.each do |repo| %>
|
||||
<div class="tab-pane tab-pane-settings" id="custom_repo_<%= repo.id %>">
|
||||
<!-- Tab Content -->
|
||||
<div id="repository-toolbar">
|
||||
<div class="dropdown text-right">
|
||||
<div class="btn btn-default btn-xs"
|
||||
type="button"
|
||||
data-toggle="dropdown"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="true"
|
||||
<%= "disabled='disabled'" if !can_edit_and_destroy_repository repo %>>
|
||||
<span class="glyphicon glyphicon-cog"></span>
|
||||
<span class="caret"></span>
|
||||
</div>
|
||||
<ul class="dropdown-menu pull-right">
|
||||
<li class="dropdown-header">
|
||||
<%= t("repositories.index.options_dropdown.header") %>
|
||||
</li>
|
||||
<% if can_edit_and_destroy_repository repo %>
|
||||
<li>
|
||||
<%= link_to t('repositories.index.options_dropdown.rename'),
|
||||
team_repository_rename_modal_path(repository_id: repo),
|
||||
class: "rename-repo-option",
|
||||
remote: true %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if can_copy_repository(repo) %>
|
||||
<li>
|
||||
<%= link_to t('repositories.index.options_dropdown.copy'),
|
||||
team_repository_copy_modal_path(repository_id: repo),
|
||||
class: "copy-repo-option",
|
||||
remote: true %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if can_edit_and_destroy_repository repo %>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li>
|
||||
<%= link_to t('repositories.index.modal_delete.delete'),
|
||||
team_repository_destroy_modal_path(repository_id: repo),
|
||||
class: "delete-repo-option",
|
||||
remote: true %>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="container-fluid">
|
||||
<div class="tab-content-body"></div>
|
||||
</div>
|
||||
<div class="tab-content-body"></div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
|
@ -1,14 +1,22 @@
|
|||
<div class="well">
|
||||
<%= bootstrap_form_for(@result, url: my_module_result_assets_path(format: :json), remote: true, multipart: true, data: { type: :json }) do |f| %>
|
||||
<%= f.text_field :name, style: "margin-top: 10px;" %><br />
|
||||
<%= f.fields_for :asset do |ff| %>
|
||||
<%= ff.file_field :file %>
|
||||
<% end %>
|
||||
<%= f.submit t("result_assets.new.create"),
|
||||
class: 'btn btn-primary save-result',
|
||||
onclick: "Results.processResult(event, Results.ResultTypeEnum.FILE, false);" %>
|
||||
<button type="button" class="btn btn-default cancel-new">
|
||||
<div id="new-result-assets-select"
|
||||
class="text-center new-asset-box">
|
||||
<%=t 'assets.drag_n_drop.label_html' %> <label><span class="btn btn-primary"><%=t 'assets.drag_n_drop.browse_label' %></span>
|
||||
<input type="file"
|
||||
onchange="DragNDropResults.init(this.files, 'select')"
|
||||
id="drag-n-drop-assets"
|
||||
style="display: none" multiple>
|
||||
</label>
|
||||
</div>
|
||||
<br />
|
||||
<button type="button"
|
||||
class="btn btn-primary save-result"
|
||||
data-href="<%= my_module_result_assets_path(format: :json) %>"
|
||||
onClick="DragNDropResults.processResult(this)"><%=t 'result_assets.new.create' %></button>
|
||||
<button type="button"
|
||||
class="btn btn-default cancel-new"
|
||||
onClick="DragNDropResults.destroyAll()">
|
||||
<%= t("general.cancel")%>
|
||||
</button>
|
||||
<% end %>
|
||||
<%# end %>
|
||||
</div>
|
||||
|
|
20
app/views/samples/_export_samples_modal.html.erb
Normal file
20
app/views/samples/_export_samples_modal.html.erb
Normal file
|
@ -0,0 +1,20 @@
|
|||
<div class="modal fade"
|
||||
id="modal-export-samples-success"
|
||||
tabindex="-1"
|
||||
role="dialog"
|
||||
aria-labelledby="modal-export-samples-successs-label">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title"><%=t 'zip_export.modal_label' %></h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<%=t('zip_export.modal_html', email: current_user.email) %>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal"><%= t('general.cancel')%></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -40,7 +40,7 @@
|
|||
<br>
|
||||
<span>
|
||||
<%= t "samples.modal_info.custom_field", cf: sample_custom_field.custom_field.name %>
|
||||
<%= sample_custom_field.value %>
|
||||
<%= custom_auto_link(sample_custom_field.value, simple_format: false, team: @team) %>
|
||||
</span>
|
||||
<% end %>
|
||||
</p>
|
||||
|
|
3
app/views/shared/_drag_n_drop_overlay.html.erb
Normal file
3
app/views/shared/_drag_n_drop_overlay.html.erb
Normal file
|
@ -0,0 +1,3 @@
|
|||
<div class="is-dragover">
|
||||
<span><%=t 'assets.drag_n_drop.drop_label' %></span>
|
||||
</div>
|
|
@ -46,7 +46,7 @@
|
|||
</li>
|
||||
<li>
|
||||
<a id="repositories-link" href="<%= team_repositories_path(current_team) %>">
|
||||
<span class="glyphicon glyphicon-oil"></span>
|
||||
<i class="fa fa-cubes" aria-hidden="true"></i>
|
||||
<span class="visible-xs-inline visible-sm-inline"><%= t('nav.label.repositories') %></span>
|
||||
</a>
|
||||
</li>
|
||||
|
@ -59,7 +59,7 @@
|
|||
</li>
|
||||
<li class="disabled">
|
||||
<a id="repositories-link" href="#">
|
||||
<span class="glyphicon glyphicon-oil"></span>
|
||||
<span class="fa fa-cubes"></span>
|
||||
<span class="visible-xs-inline visible-sm-inline"><%= t('nav.label.repositories') %></span>
|
||||
</a>
|
||||
</li>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<%= render partial: "samples/import_samples_modal" %>
|
||||
<%= render partial: "samples/delete_samples_modal" %>
|
||||
<%= render partial: "samples/delete_custom_field_modal" %>
|
||||
<%= render partial: 'samples/export_samples_modal' %>
|
||||
|
||||
<!-- Modal for parsing sample sheets should be empty at first -->
|
||||
<div class="modal fade" id="modal-parse-samples" tabindex="-1" role="dialog" aria-labelledby=="modal-parse-samples-label"></div>
|
||||
|
@ -8,8 +9,8 @@
|
|||
<div id="alert-container"></div>
|
||||
|
||||
<% if can_view_samples(@team) %>
|
||||
<%= bootstrap_form_tag(url: export_samples_team_path(@team, format: :csv),
|
||||
html: { id: 'form-export', class: 'hidden' }) do |f| %>
|
||||
<%= bootstrap_form_tag(url: export_samples_team_path(@team),
|
||||
html: { id: 'form-export', class: 'hidden' }) do |f| %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
|
@ -36,6 +37,11 @@
|
|||
<span class="glyphicon glyphicon-cloud-download"></span>
|
||||
<span class="hidden-xs"><%= t("samples.export") %></span>
|
||||
</a>
|
||||
|
||||
<div id="show-assigned-buttons" class="btn-group sample-assign-group" data-toggle="buttons">
|
||||
<button type="button" class="active btn btn-primary" id="assignedSamples"><%= t("samples.view_assigned_samples") %></button>
|
||||
<button type="button" class="btn btn-default" id="allSamples"><%= t("samples.view_all_samples") %></button>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div id="datatables-buttons" style="display: inline;">
|
||||
|
|
|
@ -188,7 +188,7 @@
|
|||
</a>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if can_view_repositories(@my_module.experiment.project.team) &&
|
||||
<% if can_view_team_repositories(@my_module.experiment.project.team) &&
|
||||
@my_module.experiment.project.team.repositories.exists? %>
|
||||
<li id="repositories-nav-tab" class="<%= "active" if module_repository_page? %>">
|
||||
<a href="#" id="repositoriesDropdownMenuLink" title="<%=t "nav2.modules.repositories" %>" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
|
@ -197,10 +197,10 @@
|
|||
<span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu repositories-dropdown-menu" aria-labelledby="repositoriesDropdownMenuLink">
|
||||
<% @my_module.experiment.project.team.repositories.each do |repository| %>
|
||||
<% @my_module.experiment.project.team.repositories.order(created_at: :asc).each do |repository| %>
|
||||
<li>
|
||||
<a class="dropdown-item" href="<%= repository_my_module_url(repository_id: repository) %>" title="<%= repository.name %>">
|
||||
<%= repository.name %>
|
||||
<%= truncate(repository.name) %>
|
||||
</a>
|
||||
</li>
|
||||
<% unless @my_module.experiment.project.team.repositories.last == repository %>
|
||||
|
|
|
@ -10,7 +10,9 @@
|
|||
<%= t("protocols.steps.new.tab_checklists") %>
|
||||
</a>
|
||||
</li>
|
||||
<li role="presentation" id="new-step-assets-tab">
|
||||
<li role="presentation"
|
||||
id="new-step-assets-tab"
|
||||
onClick="dragNdropAssetsInit('steps')">
|
||||
<a href="#new-step-assets" data-toggle="tab">
|
||||
<span class="glyphicon glyphicon-file"></span>
|
||||
<%= t("protocols.steps.new.tab_assets") %>
|
||||
|
@ -40,13 +42,17 @@
|
|||
<% end %>
|
||||
</div>
|
||||
<div class="tab-pane" role="tabpanel" id="new-step-assets">
|
||||
<div class="text-center new-asset-box">
|
||||
<%=t 'assets.drag_n_drop.label_html' %> <label><span class="btn btn-primary"><%=t 'assets.drag_n_drop.browse_label' %></span>
|
||||
<input type="file"
|
||||
onchange="DragNDropSteps.init(this.files)"
|
||||
id="drag-n-drop-assets"
|
||||
style="display: none" multiple>
|
||||
</label>
|
||||
</div>
|
||||
<%= f.nested_fields_for :assets do |ff| %>
|
||||
<%= render "form_assets.html.erb", ff: ff, step: step %>
|
||||
<% end %>
|
||||
<%= f.add_nested_fields_link :assets do %>
|
||||
<span class="glyphicon glyphicon-plus"></span>
|
||||
<%= t("protocols.steps.new.add_asset") %>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="tab-pane" role="tabpanel" id="new-step-tables">
|
||||
<%= f.nested_fields_for :tables do |ff| %>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div class="well">
|
||||
<%= bootstrap_form_for(@step, url: protocol_steps_path(@protocol, format: :json), remote: true, authenticity_token: true, multipart: true, data: { role: "new-step-form", type: :json }) do |f| %>
|
||||
<%= bootstrap_form_for(@step, url: protocol_steps_path(@protocol, format: :json), authenticity_token: true, multipart: true, data: { role: "new-step-form", type: :json }) do |f| %>
|
||||
<h4><%= t("protocols.steps.new.add_step_title") %></h4>
|
||||
<hr>
|
||||
<%= render partial: "empty_step.html.erb", locals: {step: @step, f: f} %>
|
||||
|
|
|
@ -73,6 +73,7 @@ Rails.application.config.assets.precompile += %w(samples/sample_types_groups.js)
|
|||
Rails.application.config.assets.precompile += %w(highlightjs-github-theme.css)
|
||||
Rails.application.config.assets.precompile += %w(search.js)
|
||||
Rails.application.config.assets.precompile += %w(repositories/index.js)
|
||||
Rails.application.config.assets.precompile += %w(repositories/edit.js)
|
||||
Rails.application.config.assets.precompile +=
|
||||
%w(repositories/repository_datatable.js)
|
||||
|
||||
|
|
|
@ -612,6 +612,7 @@ en:
|
|||
more_activities: "Load older activities"
|
||||
repository:
|
||||
head_title: "%{project} | %{module} | Custom repository %{repository}"
|
||||
export: 'Export'
|
||||
|
||||
experiments:
|
||||
new:
|
||||
|
@ -820,6 +821,7 @@ en:
|
|||
success_flash: "File result successfully deleted."
|
||||
wopi_open_file: "Open in %{app}"
|
||||
wopi_edit_file: "Edit in %{app}"
|
||||
error_flash: 'Something went wrong! Please try again later.'
|
||||
|
||||
result_tables:
|
||||
new:
|
||||
|
@ -843,7 +845,7 @@ en:
|
|||
index:
|
||||
head_title: "Repositories"
|
||||
title: "Repositories"
|
||||
add_new_repository_tab: "Create new repository"
|
||||
add_new_repository_tab: "Add repository"
|
||||
delete_flash: "\"%{name}\" repository was successfully deleted!"
|
||||
rename_flash: "\"%{old_name}\" repository was successfully renamed to \"%{new_name}\"!"
|
||||
copy_flash: "\"%{new}\" repository was successfully copied from \"%{old}\"!"
|
||||
|
@ -886,7 +888,7 @@ en:
|
|||
row_name: "Name"
|
||||
added_on: "Added on"
|
||||
added_by: "Added by"
|
||||
add_new_record: "Add record"
|
||||
add_new_record: "Add new item"
|
||||
import_records:
|
||||
import: 'Import'
|
||||
success_flash: "%{number_of_rows} new record(s) successfully imported."
|
||||
|
@ -947,7 +949,7 @@ en:
|
|||
no_records_assigned_flash: "No records were assigned to task"
|
||||
no_records_unassigned_flash: "No records were unassigned from task"
|
||||
default_column: 'Name'
|
||||
|
||||
|
||||
samples:
|
||||
columns: "Columns"
|
||||
columns_visibility: "Toggle visibility"
|
||||
|
@ -969,6 +971,8 @@ en:
|
|||
add_new_sample_type: "Add sample type"
|
||||
add_new_sample_group: "Add sample group"
|
||||
add_new_column: "Add column"
|
||||
view_all_samples: "View all samples"
|
||||
view_assigned_samples: "View assigned samples"
|
||||
modal_info:
|
||||
added_on: "Added on"
|
||||
added_by: "Added by"
|
||||
|
@ -1135,8 +1139,8 @@ en:
|
|||
uncomplete_module: "<i>%{user}</i> uncompleted task <strong>%{module}</strong>."
|
||||
assign_sample: "<i>%{user}</i> assigned sample(s) <strong>%{samples}</strong> to task(s) <strong>%{tasks}</strong>"
|
||||
unassign_sample: "<i>%{user}</i> unassigned sample(s) <strong>%{samples}</strong> from task(s) <strong>%{tasks}</strong>"
|
||||
assign_repository_records: "<i>%{user}</i> assigned <strong>%{repository}</strong> repository records(s) <strong>%{records}</strong> to task <strong>%{task}</strong>"
|
||||
unassign_repository_records: "<i>%{user}</i> unassigned <strong>%{repository}</strong> repository records(s) <strong>%{records}</strong> from task <strong>%{task}</strong>"
|
||||
assign_repository_records: "<i>%{user}</i> assigned record(s) <strong>%{records}</strong> from <strong>%{repository}</strong> repository to task <strong>%{task}</strong>"
|
||||
unassign_repository_records: "<i>%{user}</i> unassigned record(s) <strong>%{records}</strong> from <strong>%{repository}</strong> repository from task <strong>%{task}</strong>"
|
||||
create_step: "<i>%{user}</i> created Step %{step} <strong>%{step_name}</strong>."
|
||||
destroy_step: "<i>%{user}</i> deleted Step %{step} <strong>%{step_name}</strong>."
|
||||
add_comment_to_step: "<i>%{user}</i> commented on Step %{step} <strong>%{step_name}</strong>."
|
||||
|
@ -1684,7 +1688,11 @@ en:
|
|||
head_title:
|
||||
edit: "sciNote | %{file_name} | Edit"
|
||||
view: "sciNote | %{file_name} | View"
|
||||
|
||||
drag_n_drop:
|
||||
label_html: 'Drag & drop files here or '
|
||||
browse_label: 'Browse to add'
|
||||
drop_label: 'Drop to add to Step'
|
||||
file_label: 'File'
|
||||
atwho:
|
||||
no_results: "No results found"
|
||||
users:
|
||||
|
@ -1702,9 +1710,15 @@ en:
|
|||
deleted: "(deleted)"
|
||||
|
||||
zip_export:
|
||||
modal_label: 'Export repository'
|
||||
notification_title: 'Your package is ready to be exported!'
|
||||
expired_title: 'The required file was expired!'
|
||||
expired_description: 'The downloadable file expires in 7 days after its creation.'
|
||||
modal_label: 'Export request received'
|
||||
modal_html: "<p>Your export request is being processed.</p><p>When completed we will <strong>send an email to %{email}</strong> inbox with a link to your exported samples. Note that the link will expire in 7 days.</p>"
|
||||
repository_html: '<p>You are about to export selected items in repository %{repository}</p> <br> Repository will be exported in a .csv file format. You will receive <strong>email with a link</strong> where you can download it.'
|
||||
export_error: "Error when creating zip export."
|
||||
|
||||
# This section contains general words that can be used in any parts of
|
||||
# application.
|
||||
tiny_mce:
|
||||
|
|
|
@ -155,6 +155,7 @@ Rails.application.routes.draw do
|
|||
post 'parse_sheet'
|
||||
post 'import_samples'
|
||||
post 'export_samples'
|
||||
post 'export_repository', to: 'repositories#export_repository'
|
||||
# Used for atwho (smart annotations)
|
||||
get 'atwho_users', to: 'at_who#users'
|
||||
get 'atwho_samples', to: 'at_who#samples'
|
||||
|
|
Loading…
Reference in a new issue