Merge pull request #647 from biosistemika/master

Bring latest master changes into custom-repositories
This commit is contained in:
Luka Murn 2017-05-30 14:18:14 +02:00 committed by GitHub
commit fcc3995049
42 changed files with 1814 additions and 1475 deletions

View file

@ -1,199 +1,238 @@
//= require assets
//= require comments
/**
* Initializes page
*/
function init() {
initHandsOnTables($(document));
expandAllResults();
initTutorial();
applyCollapseLinkCallBack();
(function(global) {
'use strict';
Comments.bindNewElement();
Comments.initialize();
global.Results = (function() {
var ResultTypeEnum = Object.freeze({
FILE: 0,
TABLE: 1,
TEXT: 2,
COMMENT: 3
});
Comments.initCommentOptions("ul.content-comments");
Comments.initEditComments("#results");
Comments.initDeleteComments("#results");
function init() {
initHandsOnTables($(document));
_expandAllResults();
_initTutorial();
applyCollapseLinkCallBack();
$(function () {
$("#results-collapse-btn").click(function () {
$('.result .panel-collapse').collapse('hide');
$(document).find("span.collapse-result-icon").each(function() {
$(this).addClass("glyphicon-collapse-down");
$(this).removeClass("glyphicon-collapse-up");
Comments.bindNewElement();
Comments.initialize();
Comments.initCommentOptions('ul.content-comments');
Comments.initEditComments('#results');
Comments.initDeleteComments('#results');
$(function () {
$('#results-collapse-btn').click(function () {
$('.result .panel-collapse').collapse('hide');
$(document).find('span.collapse-result-icon').each(function() {
$(this).addClass('glyphicon-collapse-down');
$(this).removeClass('glyphicon-collapse-up');
});
});
$('#results-expand-btn').click(_expandAllResults);
});
});
$("#results-expand-btn").click(expandAllResults);
});
// This checks if the ctarget param exist in the rendered url and opens the
// comment tab
if( getParam('ctarget') ){
var target = "#"+ getParam('ctarget');
$(target).find('a.comment-tab-link').click();
}
}
function initHandsOnTables(root) {
root.find("div.hot-table").each(function() {
var $container = $(this).find(".step-result-hot-table");
var contents = $(this).find('.hot-contents');
$container.handsontable({
width: '100%',
startRows: 5,
startCols: 5,
rowHeaders: true,
colHeaders: true,
fillHandle: false,
formulas: true,
cells: function (row, col, prop) {
var cellProperties = {};
if (col >= 0)
cellProperties.readOnly = true;
else
cellProperties.readOnly = false;
return cellProperties;
// This checks if the ctarget param exist in the rendered url and opens the
// comment tab
if( getParam('ctarget') ){
var target = '#'+ getParam('ctarget');
$(target).find('a.comment-tab-link').click();
}
});
var hot = $container.handsontable('getInstance');
var data = JSON.parse(contents.attr("value"));
hot.loadData(data.data);
}
});
}
function initHandsOnTables(root) {
root.find('div.hot-table').each(function() {
var $container = $(this).find('.step-result-hot-table');
var contents = $(this).find('.hot-contents');
function applyCollapseLinkCallBack() {
$(".result-panel-collapse-link")
.on("ajax:success", function() {
var collapseIcon = $(this).find(".collapse-result-icon");
var collapsed = $(this).hasClass("collapsed");
// Toggle collapse button
collapseIcon.toggleClass("glyphicon-collapse-up", !collapsed);
collapseIcon.toggleClass("glyphicon-collapse-down", collapsed);
});
}
$container.handsontable({
width: '100%',
startRows: 5,
startCols: 5,
rowHeaders: true,
colHeaders: true,
fillHandle: false,
formulas: true,
cells: function (row, col, prop) {
var cellProperties = {};
// Toggle editing buttons
function toggleResultEditButtons(show) {
if (show) {
$("#results-toolbar").show();
$(".edit-result-button").show();
} else {
$(".edit-result-button").hide();
$("#results-toolbar").hide();
}
}
if (col >= 0)
cellProperties.readOnly = true;
else
cellProperties.readOnly = false;
// Expand all results
function expandAllResults() {
$('.result .panel-collapse').collapse('show');
$(document).find("span.collapse-result-icon").each(function() {
$(this).addClass("glyphicon-collapse-up");
$(this).removeClass("glyphicon-collapse-down");
});
$(document).find("div.step-result-hot-table").each(function() {
renderTable(this);
});
}
return cellProperties;
}
});
var hot = $container.handsontable('getInstance');
var data = JSON.parse(contents.attr('value'));
hot.loadData(data.data);
});
}
function expandResult(result) {
$('.panel-collapse', result).collapse('show');
$(result).find("span.collapse-result-icon").each(function() {
$(this).addClass("glyphicon-collapse-up");
$(this).removeClass("glyphicon-collapse-down");
});
renderTable($(result).find("div.step-result-hot-table"));
animateSpinner(null, false);
setupAssetsLoading();
}
function applyCollapseLinkCallBack() {
$('.result-panel-collapse-link')
.on('ajax:success', function() {
var collapseIcon = $(this).find('.collapse-result-icon');
var collapsed = $(this).hasClass('collapsed');
// Toggle collapse button
collapseIcon.toggleClass('glyphicon-collapse-up', !collapsed);
collapseIcon.toggleClass('glyphicon-collapse-down', collapsed);
});
}
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%',
'width': '100%' });
}
}
/**
* Initializes tutorial
*/
function initTutorial() {
var stepNum = parseInt(Cookies.get('current_tutorial_step'), 10);
if (stepNum >= 15 && stepNum <= 16) {
var samplesTab = $('#module-samples-nav-tab');
var nextPage = samplesTab.find('a').attr('href');
var steps = [{
element: $('#results-toolbar')[0],
intro: I18n.t('tutorial.module_results_html')
}, {
element: samplesTab[0],
intro: I18n.t('tutorial.module_results_click_samples_html'),
position: 'left'
}];
initPageTutorialSteps(15, 16, nextPage, function() {}, function() {},
steps);
}
}
var ResultTypeEnum = Object.freeze({
FILE: 0,
TABLE: 1,
TEXT: 2,
COMMENT: 3
});
function processResult(ev, resultTypeEnum, editMode) {
var $form = $(ev.target.form);
$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);
// Toggle editing buttons
function toggleResultEditButtons(show) {
if(show) {
$('#results-toolbar').show();
$('.edit-result-button').show();
} else {
$('.edit-result-button').hide();
$('#results-toolbar').hide();
}
}
if(nameValid && filesValid) {
// Local file uploading
// Expand all results
function _expandAllResults() {
$('.result .panel-collapse').collapse('show');
$(document).find('span.collapse-result-icon').each(function() {
$(this).addClass('glyphicon-collapse-up');
$(this).removeClass('glyphicon-collapse-down');
});
$(document).find('div.step-result-hot-table').each(function() {
_renderTable(this);
});
}
function expandResult(result) {
$('.panel-collapse', result).collapse('show');
$(result).find('span.collapse-result-icon').each(function() {
$(this).addClass('glyphicon-collapse-up');
$(this).removeClass('glyphicon-collapse-down');
});
_renderTable($(result).find('div.step-result-hot-table'));
animateSpinner(null, false);
setupAssetsLoading();
}
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%',
'width': '100%' });
}
}
/**
* Initializes tutorial
*/
function _initTutorial() {
var stepNum = parseInt(Cookies.get('current_tutorial_step'), 10);
if (stepNum >= 15 && stepNum <= 16) {
var samplesTab = $('#module-samples-nav-tab');
var nextPage = samplesTab.find('a').attr('href');
var steps = [{
element: $('#results-toolbar')[0],
intro: I18n.t('tutorial.module_results_html')
}, {
element: samplesTab[0],
intro: I18n.t('tutorial.module_results_click_samples_html'),
position: 'left'
}];
initPageTutorialSteps(15, 16, nextPage, function() {}, function() {},
steps);
}
}
function processResult(ev, resultTypeEnum, editMode) {
var $form = $(ev.target.form);
$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,
<%= Constants::NAME_MAX_LENGTH %>);
break;
case ResultTypeEnum.TEXT:
var $nameInput = $form.find('#result_name');
var nameValid = textValidator(ev, $nameInput, 0,
<%= Constants::NAME_MAX_LENGTH %>);
var $textInput = TinyMCE.getContent();
textValidator(ev, $textInput, 1, <%= Constants::TEXT_MAX_LENGTH %>, false, true);
break;
case ResultTypeEnum.COMMENT:
var $commentInput = $form.find('#comment_message');
var commentValid = textValidator(ev, $commentInput, 1,
<%= Constants::TEXT_MAX_LENGTH %>);
break;
}
}
// init cancel button
function initCancelFormButton(form, callback) {
$(form).find('.cancel-new').click(function(event) {
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
$(form).remove();
toggleResultEditButtons(true);
callback();
});
}
function archive(e, element) {
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
var el = $(element);
if(confirm(el.data('confirm-text'))) {
animateSpinner();
$('#' + el.data('form-id')).submit();
}
break;
case ResultTypeEnum.TABLE:
var $nameInput = $form.find("#result_name");
var nameValid = textValidator(ev, $nameInput, 0,
<%= Constants::NAME_MAX_LENGTH %>);
break;
case ResultTypeEnum.TEXT:
var $nameInput = $form.find("#result_name");
var nameValid = textValidator(ev, $nameInput, 0,
<%= Constants::NAME_MAX_LENGTH %>);
var $textInput = TinyMCE.getContent();
textValidator(ev, $textInput, 1, <%= Constants::TEXT_MAX_LENGTH %>, false, true);
break;
case ResultTypeEnum.COMMENT:
var $commentInput = $form.find("#comment_message");
var commentValid = textValidator(ev, $commentInput, 1,
<%= Constants::TEXT_MAX_LENGTH %>);
break;
}
}
}
$(document).ready(function(){
init();
});
var publicAPI = Object.freeze({
init: init,
initHandsOnTables: initHandsOnTables,
applyCollapseLinkCallBack: applyCollapseLinkCallBack,
toggleResultEditButtons: toggleResultEditButtons,
expandResult: expandResult,
processResult: processResult,
ResultTypeEnum: ResultTypeEnum,
initCancelFormButton: initCancelFormButton,
archive: archive
});
return publicAPI;
})();
$(document).ready(function(){
Results.init();
});
})(window);

File diff suppressed because it is too large Load diff

View file

@ -221,12 +221,15 @@ function initializeNewElement(newEl) {
id: parentElementId
},
success: function(data, status, jqxhr) {
// Open modal, set its title
// Open modal, set its title, and display module contents
addContentsModal.find(".modal-title").text(modalTitle);
// Display module contents
addContentsModalBody.html(data.html);
// Add logic for checkbox hierarchies
var dependencies = { '_module_steps': $('#_step_all'),
'_module_results': $('#_result_comments')}
addContentsModalBody.checkboxTreeLogic(dependencies, true);
// Bind to the ajax events of the modal form in its body
$(ADD_CONTENTS_FORM_ID)
.on("ajax:beforeSend", function(){

View file

@ -1,79 +1,97 @@
// New result asset behaviour
$("#new-result-asset").on("ajax:success", function(e, data) {
var $form = $(data.html);
$("#results").prepend($form);
(function(global) {
'use strict';
formAjaxResultAsset($form);
var ResutlAssets = (function() {
// New result asset behaviour
function initNewResultAsset() {
$('#new-result-asset').on('click', function(event) {
event.preventDefault();
event.stopImmediatePropagation();
event.stopPropagation();
var $btn = $(this);
$btn.off();
animateSpinner(null, true);
// Cancel button
$form.find(".cancel-new").click(function () {
$form.remove();
toggleResultEditButtons(true);
});
// get new result form
$.ajax({
url: $btn.data('href'),
method: 'GET',
success: function(data) {
var $form = $(data.html);
animateSpinner(null, false);
$('#results').prepend($form);
_formAjaxResultAsset($form);
Results.initCancelFormButton($form, initNewResultAsset);
Results.toggleResultEditButtons(false);
$('#result_name').focus();
},
error: function(xhr, status, e) {
$(this).renderFormErrors('result', xhr.responseJSON, true, e);
animateSpinner(null, false);
initNewResultAsset();
}
});
});
}
toggleResultEditButtons(false);
function applyEditResultAssetCallback() {
$('.edit-result-asset').on('ajax:success', function(e, data) {
var $result = $(this).closest('.result');
var $form = $(data.html);
var $prevResult = $result;
$result.after($form);
$result.remove();
$("#result_name").focus();
}).on('ajax:error', function(e, xhr) {
$(this).renderFormErrors('result', xhr.responseJSON, true, e);
animateSpinner(null, false);
});
_formAjaxResultAsset($form);
$("#new-result-asset").on("ajax:error", function(e, xhr, status, error) {
animateSpinner(null, false);
});
// Cancel button
$form.find('.cancel-edit').click(function () {
$form.after($prevResult);
$form.remove();
applyEditResultAssetCallback();
Results.toggleResultEditButtons(true);
initPreviewModal();
});
// Edit result asset button behaviour
function applyEditResultAssetCallback() {
$(".edit-result-asset").on("ajax:success", function(e, data) {
var $result = $(this).closest(".result");
var $form = $(data.html);
var $prevResult = $result;
$result.after($form);
$result.remove();
Results.toggleResultEditButtons(false);
formAjaxResultAsset($form);
$('#result_name').focus();
}).on('ajax:error', function(e, xhr, status, error) {
animateSpinner(null, false);
});
}
// Cancel button
$form.find(".cancel-edit").click(function () {
$form.after($prevResult);
$form.remove();
applyEditResultAssetCallback();
toggleResultEditButtons(true);
initPreviewModal();
function _formAjaxResultAsset($form) {
$form.on('ajax:success', function(e, data) {
$form.after(data.html);
var $newResult = $form.next();
initFormSubmitLinks($newResult);
$(this).remove();
applyEditResultAssetCallback();
Results.applyCollapseLinkCallBack();
Results.toggleResultEditButtons(true);
Results.expandResult($newResult);
initPreviewModal();
Comments.initialize();
initNewResultAsset();
}).on('ajax:error', function(e, xhr) {
$form.renderFormErrors('result', xhr.responseJSON, true, e);
animateSpinner(null, false);
});
}
var publicAPI = Object.freeze({
initNewResultAsset: initNewResultAsset,
applyEditResultAssetCallback: applyEditResultAssetCallback
});
toggleResultEditButtons(false);
return publicAPI;
})();
$("#result_name").focus();
$(document).ready(function() {
ResutlAssets.initNewResultAsset();
ResutlAssets.applyEditResultAssetCallback();
global.initPreviewModal();
});
$(".edit-result-asset").on("ajax:error", function(e, xhr, status, error) {
animateSpinner(null, false);
});
}
// Apply ajax callback to form
function formAjaxResultAsset($form) {
$form
.on("ajax:success", function(e, data) {
$form.after(data.html);
var $newResult = $form.next();
initFormSubmitLinks($newResult);
$(this).remove();
applyEditResultAssetCallback();
applyCollapseLinkCallBack();
toggleResultEditButtons(true);
expandResult($newResult);
initPreviewModal();
Comments.initialize();
})
.on('ajax:error', function(e, xhr) {
$form.renderFormErrors('result', xhr.responseJSON, true, e);
animateSpinner(null, false);
});
}
applyEditResultAssetCallback();
initPreviewModal();
})(window);

View file

@ -1,111 +1,135 @@
// Init handsontable which can be edited
function initEditableHandsOnTable(root) {
root.find(".editable-table").each(function() {
var $container = $(this).find(".hot");
var data = null;
var contents = $(this).find('.hot-contents');
if (contents.attr("value")) {
data = JSON.parse(contents.attr("value")).data;
}
(function() {
'use strict';
$container.handsontable({
data: data,
startRows: <%= Constants::HANDSONTABLE_INIT_ROWS_CNT %>,
startCols: <%= Constants::HANDSONTABLE_INIT_COLS_CNT %>,
minRows: 1,
minCols: 1,
rowHeaders: true,
colHeaders: true,
contextMenu: true,
formulas: true,
preventOverflow: 'horizontal'
});
});
}
var ResultTables = (function() {
// Init handsontable which can be edited
function _initEditableHandsOnTable(root) {
root.find('.editable-table').each(function() {
var $container = $(this).find('.hot');
var data = null;
var contents = $(this).find('.hot-contents');
if (contents.attr('value')) {
data = JSON.parse(contents.attr('value')).data;
}
function onSubmitExtractTable($form) {
$form.submit(function(){
var hot = $(".hot").handsontable('getInstance');
var contents = $('.hot-contents');
var data = JSON.stringify({data: hot.getData()});
contents.attr("value", data);
return true;
});
}
$container.handsontable({
data: data,
startRows: <%= Constants::HANDSONTABLE_INIT_ROWS_CNT %>,
startCols: <%= Constants::HANDSONTABLE_INIT_COLS_CNT %>,
minRows: 1,
minCols: 1,
rowHeaders: true,
colHeaders: true,
contextMenu: true,
formulas: true,
preventOverflow: 'horizontal'
});
});
}
// Edit result table button behaviour
function applyEditResultTableCallback() {
$(".edit-result-table").on("ajax:success", function(e, data) {
var $result = $(this).closest(".result");
var $form = $(data.html);
var $prevResult = $result;
$result.after($form);
$result.remove();
function _onSubmitExtractTable($form) {
$form.submit(function(){
var hot = $('.hot').handsontable('getInstance');
var contents = $('.hot-contents');
var data = JSON.stringify({data: hot.getData()});
contents.attr('value', data);
return true;
});
}
formAjaxResultTable($form);
initEditableHandsOnTable($form);
onSubmitExtractTable($form);
// Apply ajax callback to form
function _formAjaxResultTable($form) {
$form.on('ajax:success', function(e, data) {
var $result;
$form.after(data.html);
$result = $(this).next();
initFormSubmitLinks($result);
$(this).remove();
// Cancel button
$form.find(".cancel-edit").click(function () {
$form.after($prevResult);
$form.remove();
applyEditResultTableCallback();
toggleResultEditButtons(true);
applyEditResultTableCallback();
Results.applyCollapseLinkCallBack();
Results.initHandsOnTables($result);
Results.toggleResultEditButtons(true);
Results.expandResult($result);
Comments.initialize();
initNewResultTable();
});
$form.on('ajax:error', function(e, xhr, status, error) {
var data = xhr.responseJSON;
$form.renderFormErrors('result', data);
});
}
// Edit result table button behaviour
function applyEditResultTableCallback() {
$('.edit-result-table').on('ajax:success', function(e, data) {
var $result = $(this).closest('.result');
var $form = $(data.html);
var $prevResult = $result;
$result.after($form);
$result.remove();
_formAjaxResultTable($form);
_initEditableHandsOnTable($form);
_onSubmitExtractTable($form);
// Cancel button
$form.find('.cancel-edit').click(function () {
$form.after($prevResult);
$form.remove();
applyEditResultTableCallback();
Results.toggleResultEditButtons(true);
});
Results.toggleResultEditButtons(false);
$('#result_name').focus();
});
}
// New result text behaviour
function initNewResultTable() {
$('#new-result-table').on('click', function(event) {
event.preventDefault();
event.stopImmediatePropagation();
event.stopPropagation();
var $btn = $(this);
$btn.off();
animateSpinner(null, true);
// get new result form
$.ajax({
url: $btn.data('href'),
method: 'GET',
success: function(data) {
var $form = $(data.html);
animateSpinner(null, false);
$('#results').prepend($form);
_formAjaxResultTable($form);
_initEditableHandsOnTable($form);
_onSubmitExtractTable($form);
Results.initCancelFormButton($form, initNewResultTable);
Results.toggleResultEditButtons(false);
$('#result_name').focus();
},
error: function() {
animateSpinner(null, false);
initNewResultTable();
}
});
});
}
var publicAPI = Object.freeze({
initNewResultTable: initNewResultTable,
applyEditResultTableCallback: applyEditResultTableCallback
});
return publicAPI;
})();
$(document).ready(function() {
ResultTables.initNewResultTable();
ResultTables.applyEditResultTableCallback();
});
toggleResultEditButtons(false);
$("#result_name").focus();
});
$(".edit-result-table").on("ajax:error", function(e, xhr, status, error) {
//TODO: Add error handling
});
}
// New result text behaviour
$("#new-result-table").on("ajax:success", function(e, data) {
var $form = $(data.html);
$("#results").prepend($form);
formAjaxResultTable($form);
initEditableHandsOnTable($form);
onSubmitExtractTable($form);
// Cancel button
$form.find(".cancel-new").click(function () {
$form.remove();
toggleResultEditButtons(true);
});
toggleResultEditButtons(false);
$("#result_name").focus();
});
$("#new-result-table").on("ajax:error", function(e, xhr, status, error) {
//TODO: Add error handling
});
// Apply ajax callback to form
function formAjaxResultTable($form) {
$form.on("ajax:success", function(e, data) {
$form.after(data.html);
$result = $(this).next();
initFormSubmitLinks($result);
$(this).remove();
applyEditResultTableCallback();
applyCollapseLinkCallBack();
initHandsOnTables($result);
toggleResultEditButtons(true);
expandResult($result);
Comments.initialize();
});
$form.on("ajax:error", function(e, xhr, status, error) {
var data = xhr.responseJSON;
$form.renderFormErrors("result", data);
});
}
applyEditResultTableCallback();
})();

View file

@ -1,81 +1,106 @@
// New result text behaviour
$("#new-result-text").on("ajax:success", function(e, data) {
var $form = $(data.html);
$("#results").prepend($form);
(function() {
'use strict';
formAjaxResultText($form);
var ResultText = (function() {
// New result text behaviour
function initNewReslutText() {
$('#new-result-text').on('click', function(event) {
event.preventDefault();
event.stopImmediatePropagation();
event.stopPropagation();
var $btn = $(this);
$btn.off();
animateSpinner(null, true);
// Cancel button
$form.find(".cancel-new").click(function () {
$form.remove();
toggleResultEditButtons(true);
});
toggleResultEditButtons(false);
TinyMCE.refresh();
$("#result_name").focus();
});
// get new result form
$.ajax({
url: $btn.data('href'),
method: 'GET',
success: function(data) {
var $form = $(data.html);
animateSpinner(null, false);
$('#results').prepend($form);
_formAjaxResultText($form);
Results.initCancelFormButton($form, initNewReslutText);
Results.toggleResultEditButtons(false);
TinyMCE.refresh();
TinyMCE.highlight();
$('#result_name').focus();
},
error: function() {
animateSpinner(null, false);
initNewReslutText();
}
})
});
}
$("#new-result-text").on("ajax:error", function(e, xhr, status, error) {
//TODO: Add error handling
});
// Edit result text button behaviour
function applyEditResultTextCallback() {
$(".edit-result-text").on("ajax:success", function(e, data) {
var $result = $(this).closest(".result");
// Edit result text button behaviour
function applyEditResultTextCallback() {
$('.edit-result-text').on('ajax:success', function(e, data) {
var $result = $(this).closest('.result');
var $form = $(data.html);
var $prevResult = $result;
$result.after($form);
$result.remove();
formAjaxResultText($form);
_formAjaxResultText($form);
// Cancel button
$form.find(".cancel-edit").click(function () {
$form.after($prevResult);
$form.remove();
applyEditResultTextCallback();
toggleResultEditButtons(true);
$form.find('.cancel-edit').click(function() {
$form.after($prevResult);
$form.remove();
applyEditResultTextCallback();
Results.toggleResultEditButtons(true);
});
toggleResultEditButtons(false);
Results.toggleResultEditButtons(false);
TinyMCE.refresh();
$("#result_name").focus();
});
$('#result_name').focus();
});
}
$(".edit-result-text").on("ajax:error", function(e, xhr, status, error) {
//TODO: Add error handling
});
}
// Apply ajax callback to form
function formAjaxResultText($form) {
$form.on("ajax:success", function(e, data) {
// Apply ajax callback to form
function _formAjaxResultText($form) {
$form.on('ajax:success', function(e, data) {
$form.after(data.html);
var newResult = $form.next();
initFormSubmitLinks(newResult);
$(this).remove();
applyEditResultTextCallback();
applyCollapseLinkCallBack();
toggleResultEditButtons(true);
expandResult(newResult);
Results.applyCollapseLinkCallBack();
Results.toggleResultEditButtons(true);
Results.expandResult(newResult);
TinyMCE.destroyAll();
Comments.initialize();
});
$form.on("ajax:error", function(e, xhr, status, error) {
initNewReslutText();
});
$form.on('ajax:error', function(e, xhr, status, error) {
var data = xhr.responseJSON;
$form.renderFormErrors("result", data);
$form.renderFormErrors('result', data);
TinyMCE.highlight();
if (data["result_text.text"]) {
var $el = $form.find("textarea[name=result\\[result_text_attributes\\]\\[text\\]]");
if (data['result_text.text']) {
var $el = $form.find(
'textarea[name=result\\[result_text_attributes\\]\\[text\\]]'
);
$el.closest(".form-group").addClass("has-error");
$el.parent().append("<span class='help-block'>" + data["result_text.text"] + "</span>");
$el.closest('.form-group').addClass('has-error');
$el.parent().append('<span class=\'help-block\'>' +
data['result_text.text'] + '</span>');
}
});
}
});
}
$(document).ready(function() {
TinyMCE.highlight();
});
applyEditResultTextCallback();
var publicAPI = Object.freeze({
initNewReslutText: initNewReslutText,
applyEditResultTextCallback: applyEditResultTextCallback
});
return publicAPI;
})();
$(document).ready(function() {
ResultText.initNewReslutText();
ResultText.applyEditResultTextCallback();
});
})();

View file

@ -1,41 +1,50 @@
var previousIndex;
var disabledOptions;
$("select").focus(function() {
var loadingSamples = false;
$('select').focus(function() {
previousIndex = $(this)[0].selectedIndex;
}).change(function () {
}).change(function() {
var currSelect = $(this);
var currIndex = $(currSelect)[0].selectedIndex;
$("select").each(function() {
$('select').each(function() {
if (currSelect !== $(this) && currIndex > 0) {
$(this).children().eq(currIndex).attr("disabled", "disabled");
$(this).children().eq(currIndex).attr('disabled', 'disabled');
}
$(this).children().eq(previousIndex).removeAttr("disabled");
$(this).children().eq(previousIndex).removeAttr('disabled');
});
previousIndex = currIndex;
});
// Create import samples ajax
$("form#form-import")
$('form#form-import')
.submit(function(e) {
// Check if we already uploading samples
if (loadingSamples) {
return false;
}
disabledOptions = $("option[disabled='disabled']");
disabledOptions.removeAttr("disabled");
disabledOptions.removeAttr('disabled');
loadingSamples = true;
animateSpinner();
})
.on("ajax:success", function(ev, data, status) {
.on('ajax:success', function(ev, data, status) {
// Simply reload page to show flash and updated samples list
loadingSamples = false;
location.reload();
})
.on("ajax:error", function(ev, data, status) {
.on('ajax:error', function(ev, data, status) {
loadingSamples = false;
if (_.isUndefined(data.responseJSON.html)) {
// Simply reload page to show flash
location.reload();
location.reload();
} else {
// Re-disable options
disabledOptions.attr("disabled", "disabled");
disabledOptions.attr('disabled', 'disabled');
// Populate the errors container
$("#import-errors-container").html(data.responseJSON.html);
$('#import-errors-container').html(data.responseJSON.html);
}
});

View file

@ -1,43 +1,48 @@
function initPreviewModal() {
$('.image-preview-link').off();
$('.image-preview-link').click(function(e) {
e.preventDefault();
var name = $(this).find('p').text();
var url = $(this).find('img').data('preview-url');
var downloadUrl = $(this).attr('href');
var description = $(this).data('description');
openPreviewModal(name, url, downloadUrl, description);
});
}
(function(global) {
'use strict';
function openPreviewModal(name, url, downloadUrl, description) {
var modal = $('#imagePreviewModal');
$.ajax({
url: url,
type: 'GET',
dataType: 'json',
success: function(data) {
modal.find('.modal-body img').remove();
modal.find('.image-name').text(name);
var link = modal.find('.image-download-link');
link.attr('href', downloadUrl);
link.attr('data-no-turbolink', true);
link.attr('data-status', 'asset-present');
modal.find('.modal-body').append($('<img>')
.attr('src', data['large-preview-url'])
.attr('alt', name)
.click(function(ev) {
ev.stopPropagation();
}));
modal.find('.modal-footer .image-description').text(description);
modal.find('.modal-body').click(function() {
modal.modal('hide');
});
modal.modal();
$('.modal-backdrop').last().css('z-index', modal.css('z-index') - 1);
},
error: function(ev) {
// TODO
}
});
}
global.initPreviewModal = function initPreviewModal() {
var name, url, downloadUrl, description;
$('.image-preview-link').off();
$('.image-preview-link').click(function(e) {
e.preventDefault();
name = $(this).find('p').text();
url = $(this).find('img').data('preview-url');
downloadUrl = $(this).attr('href');
description = $(this).data('description');
openPreviewModal(name, url, downloadUrl, description);
});
}
function openPreviewModal(name, url, downloadUrl, description) {
var modal = $('#imagePreviewModal');
$.ajax({
url: url,
type: 'GET',
dataType: 'json',
success: function(data) {
modal.find('.modal-body img').remove();
modal.find('.image-name').text(name);
var link = modal.find('.image-download-link');
link.attr('href', downloadUrl);
link.attr('data-no-turbolink', true);
link.attr('data-status', 'asset-present');
modal.find('.modal-body').append($('<img>')
.attr('src', data['large-preview-url'])
.attr('alt', name)
.click(function(ev) {
ev.stopPropagation();
}));
modal.find('.modal-footer .image-description').text(description);
modal.find('.modal-body').click(function() {
modal.modal('hide');
});
modal.modal();
$('.modal-backdrop').last().css('z-index', modal.css('z-index') - 1);
},
error: function(ev) {
// TODO
}
});
}
})(window);

View file

@ -184,3 +184,58 @@ function initPageTutorialSteps(pageFirstStepN, pageLastStepN, nextPagePath,
});
}
}
/**
* Checkbox on/off logic. For each checkbox hierarchy add 'checkbox-tree' class
* to a parent 'div' surrounding the checkbox hierarchy, represented with 'ul',
* and apply this function to some ancestor tag.
* @param {object} dependencies Hash of checkbox IDs (as keys), on whose
* children and itself the corresponding checkbox object (as value) and its'
* children depend on, BUT are in a seperate 'tree branch'
* @param {boolean} checkAll Whether to check all the checkboxes by default,
* otherwise leave them as is (the parameter can be left out)
*/
$.fn.checkboxTreeLogic = function(dependencies, checkAll) {
var $checkboxTree = $(this).find('.checkbox-tree').addBack('.checkbox-tree');
var $checkboxTreeCheckboxes = $checkboxTree.find('input:checkbox');
if (checkAll) {
$checkboxTreeCheckboxes.prop('checked', true);
}
$checkboxTreeCheckboxes.change(function() {
// Update descendent checkboxes
var $checkbox = $(this);
var checkboxChecked = $checkbox.prop('checked');
var $childCheckboxes = $checkbox.closest('li').find('ul input:checkbox');
$childCheckboxes.each(function() {
$(this).prop('checked', checkboxChecked);
});
// Update ancestor checkboxes
// Loop until topmost checkbox is reached or until there's no parent
// checkbox
while ($checkbox.length) {
var $checkboxesContainer = $checkbox.closest('ul');
var $parentCheckbox = $checkboxesContainer.siblings()
.find('input:checkbox');
var $checkboxes = $checkboxesContainer.find('input:checkbox');
var $checkedCheckboxes = $checkboxes.filter(':checked');
$parentCheckbox.prop('checked',
$checkboxes.length === $checkedCheckboxes.length);
$checkbox = $parentCheckbox;
}
// Disable/enable dependent checkboxes
$.each(dependencies, function(responsibleParentID, $dependentParent) {
var $responsibleParent = $checkboxTree.find('#' + responsibleParentID);
if ($responsibleParent.length) {
var enable = $responsibleParent.closest('li')
.find('input:checkbox:checked').length
$dependentParent.closest('li').find('input:checkbox')
.prop('disabled', !enable);
}
});
}).trigger('change');
};

View file

@ -44,6 +44,16 @@
display: inline-block;
}
// Modal for adding content
label {
&[for="_experiment_all"],
&[for="_module_all"],
&[for="_step_all"],
&[for="_result_all"] {
font-weight: bold;
}
}
/* New page sidebar */
.report-sidebar-wrapper {
background-color: $color-white !important;
@ -127,16 +137,6 @@
}
}
ul {
&.project-contents-list {
padding-left: 15px !important;
}
&.experiment-contents-list {
padding-left: 30px !important;
}
}
/** "New element" floating element */
.new-element {
display: block;

View file

@ -747,6 +747,13 @@ a[data-toggle="tooltip"] {
}
}
// Checkbox tree
.checkbox-tree ul {
list-style: none;
margin: 0;
padding-left: 15px;
}
/** Add users modal */
.btn-group-existing-users {
width: 100%;

View file

@ -73,10 +73,10 @@ class CanvasController < ApplicationController
poss = update_params[:positions].split(";")
center = ""
(poss.collect { |pos| pos.split(",") }).each_with_index do |pos, index|
unless (pos.length == 3 and
pos[0].is_a? String and
is_int? pos[1] and
is_int? pos[2])
unless pos.length == 3 &&
pos[0].is_a?(String) &&
float?(pos[1]) &&
float?(pos[2])
error = true
break
end
@ -318,4 +318,9 @@ class CanvasController < ApplicationController
/\A[-+]?\d+\z/ === val
end
def float?(val)
true if Float(val)
rescue ArgumentError
false
end
end

View file

@ -70,21 +70,25 @@ module ReportActions
def generate_module_contents_json(my_module)
res = []
ReportExtends::MODULE_CONTENTS.each do |contents|
protocol = contents.element == :step ? my_module.protocol.present? : true
next unless in_params?("module_#{contents.element}".to_sym) && protocol
present = false
contents.values.each do |element|
present = in_params?("module_#{element}".to_sym) ||
in_params?(element.to_sym)
break if present
end
next unless present
if contents.children
contents.collection(my_module).each do |report_el|
contents.collection(my_module, params).each do |report_el|
res << generate_new_el(false)
el = generate_el(
"reports/elements/my_module_#{contents
.element
.to_s
.singularize}_element.html.erb",
"reports/elements/my_module_#{contents.element.to_s.singularize}"\
"_element.html.erb",
contents.parse_locals([report_el])
)
if contents.locals.first == :step
if :step.in? contents.locals
el[:children] = generate_step_contents_json(report_el)
elsif contents.locals.first == :result
elsif :result.in? contents.locals
el[:children] = generate_result_contents_json(report_el)
end
res << el

View file

@ -412,6 +412,7 @@ class ReportsController < ApplicationController
def result_contents
result = Result.find_by_id(params[:id])
respond_to do |format|
if result.blank?
format.json { render json: {}, status: :not_found }

View file

@ -3,6 +3,7 @@ class ResultTextsController < ApplicationController
include ActionView::Helpers::UrlHelper
include ApplicationHelper
include TinyMceHelper
include InputSanitizeHelper
include Rails.application.routes.url_helpers
before_action :load_vars, only: [:edit, :update, :download]

View file

@ -96,7 +96,14 @@ class SearchController < ApplicationController
end
def count_by_name(model)
search_by_name(model).limit(nil).offset(nil).size
model.search(current_user,
true,
@search_query,
Constants::SEARCH_NO_LIMIT,
nil,
match_case: @search_case,
whole_word: @search_whole_word,
whole_phrase: @search_whole_phrase).size
end
def count_search_results

View file

@ -1,6 +1,7 @@
module ApplicationHelper
include ActionView::Helpers::AssetTagHelper
include ActionView::Helpers::UrlHelper
include InputSanitizeHelper
def module_page?
controller_name == 'my_modules'
@ -187,6 +188,7 @@ module ApplicationHelper
new_text = text.gsub(sa_user) do |el|
match = el.match(sa_user)
user = User.find_by_id(match[2].base62_decode)
next unless user
team ||= current_team
popover_for_user_name(user, team)
end
@ -195,13 +197,8 @@ module ApplicationHelper
# Generate smart annotation link for one user object
def popover_for_user_name(user, team = nil)
if user &&
team &&
UserTeam.user_in_team(user, team).any?
user_t = user.user_teams
.where('user_teams.team_id = ?', team)
.first
end
user_still_in_team = user.teams.include?(team)
user_description = %(<div class='col-xs-4'>
<img src='#{user_avatar_absolute_url(user, :thumb)}'
alt='thumb'></div><div class='col-xs-8'>
@ -210,9 +207,12 @@ module ApplicationHelper
<span class='glyphicon glyphicon-remove' aria-hidden='true'></span>
</div></div><div class='row'><div class='col-xs-12'>
<p class='silver'>#{user.email}</p>)
if team.present?
if user_still_in_team
user_t = user.user_teams
.where('user_teams.team_id = ?', team)
.first
user_description += %(<p>
#{I18n.t('atwho.popover_html',
#{I18n.t('atwho.users.popover_html',
role: user_t.role.capitalize,
team: user_t.team.name,
time: user_t.created_at.strftime('%B %Y'))}
@ -221,13 +221,16 @@ module ApplicationHelper
user_description += %(<p></p></div></div></div>)
end
user_name = user.full_name
user_name << ' ' + I18n.t('atwho.res.removed') if !user_still_in_team
raw("<img src='#{user_avatar_absolute_url(user, :icon_small)}'" \
"alt='avatar' class='atwho-user-img-popover'>") +
raw('<a onClick="$(this).popover(\'show\')" ' \
'class="atwho-user-popover" data-container="body" ' \
'data-html="true" tabindex="0" data-trigger="focus" ' \
'data-placement="top" data-toggle="popover" data-content="') +
raw(user_description) + raw('" >') + user.full_name + raw('</a>')
"alt='avatar' class='atwho-user-img-popover'>") +
raw('<a onClick="$(this).popover(\'show\')" ' \
'class="atwho-user-popover" data-container="body" ' \
'data-html="true" tabindex="0" data-trigger="focus" ' \
'data-placement="top" data-toggle="popover" data-content="') +
raw(user_description) + raw('" >') + user_name + raw('</a>')
end
def user_avatar_absolute_url(user, style)

View file

@ -137,7 +137,8 @@ module FirstTimeDataGenerator
user: user.full_name,
project: project.name
),
created_at: project.created_at
created_at: project.created_at,
updated_at: project.created_at
).sneaky_save
# Add a comment
@ -210,7 +211,8 @@ module FirstTimeDataGenerator
user: user.full_name,
module: my_module.name
),
created_at: my_module.created_at
created_at: my_module.created_at,
updated_at: my_module.created_at
).sneaky_save
UserMyModule.create(
@ -230,7 +232,8 @@ module FirstTimeDataGenerator
module: my_module.name,
assigned_by_user: user.full_name
),
created_at: generate_random_time(my_module.created_at, 2.minutes)
created_at: generate_random_time(my_module.created_at, 2.minutes),
updated_at: generate_random_time(my_module.created_at, 2.minutes)
).sneaky_save
end
@ -262,7 +265,8 @@ module FirstTimeDataGenerator
user: user.full_name,
module: archived_module.name
),
created_at: archived_module.created_at
created_at: archived_module.created_at,
updated_at: archived_module.created_at
).sneaky_save
# Activity for archiving archived module
@ -276,7 +280,8 @@ module FirstTimeDataGenerator
user: user.full_name,
module: archived_module.name
),
created_at: archived_module.archived_on
created_at: archived_module.archived_on,
updated_at: archived_module.archived_on
).sneaky_save
# Assign new user to archived module
@ -297,7 +302,8 @@ module FirstTimeDataGenerator
module: archived_module.name,
assigned_by_user: user.full_name
),
created_at: generate_random_time(archived_module.created_at, 2.minutes)
created_at: generate_random_time(archived_module.created_at, 2.minutes),
updated_at: generate_random_time(archived_module.created_at, 2.minutes)
).sneaky_save
# Assign 4 samples to modules
@ -526,6 +532,7 @@ module FirstTimeDataGenerator
my_module: my_modules[1],
user: user,
created_at: temp_result.created_at,
updated_at: temp_result.created_at,
message: I18n.t(
'activities.add_text_result',
user: user.full_name,
@ -578,6 +585,7 @@ module FirstTimeDataGenerator
my_module: my_modules[2],
user: user,
created_at: temp_result.created_at,
updated_at: temp_result.created_at,
message: I18n.t(
'activities.add_text_result',
user: user.full_name,
@ -734,6 +742,7 @@ module FirstTimeDataGenerator
my_module: my_modules[5],
user: user,
created_at: temp_result.created_at,
updated_at: temp_result.created_at,
message: I18n.t(
'activities.add_table_result',
user: user.full_name,
@ -863,6 +872,7 @@ module FirstTimeDataGenerator
my_module: my_modules[7],
user: user,
created_at: temp_result.created_at,
updated_at: temp_result.created_at,
message: I18n.t(
'activities.add_text_result',
user: user.full_name,
@ -922,6 +932,7 @@ module FirstTimeDataGenerator
my_module: my_module,
user: step.user,
created_at: created_at,
updated_at: created_at,
message: I18n.t(
'activities.create_step',
user: step.user.full_name,
@ -936,6 +947,7 @@ module FirstTimeDataGenerator
my_module: my_module,
user: step.user,
created_at: completed_on,
updated_at: completed_on,
message: I18n.t(
'activities.complete_step',
user: step.user.full_name,
@ -980,6 +992,7 @@ module FirstTimeDataGenerator
user: user,
project: project,
created_at: created_at,
updated_at: created_at,
message: t('activities.add_comment_to_project',
user: user.full_name,
project: project.name)
@ -1000,6 +1013,7 @@ module FirstTimeDataGenerator
project: my_module.experiment.project,
my_module: my_module,
created_at: created_at,
updated_at: created_at,
message: t('activities.add_comment_to_module',
user: user.full_name,
module: my_module.name)
@ -1020,6 +1034,7 @@ module FirstTimeDataGenerator
project: result.my_module.experiment.project,
my_module: result.my_module,
created_at: created_at,
updated_at: created_at,
message: t('activities.add_comment_to_result',
user: user.full_name,
result: result.name)
@ -1040,6 +1055,7 @@ module FirstTimeDataGenerator
project: step.protocol.my_module.experiment.project,
my_module: step.protocol.my_module,
created_at: created_at,
updated_at: created_at,
message: t('activities.add_comment_to_step',
user: user.full_name,
step: step.position + 1,

View file

@ -19,7 +19,12 @@
</a>
<% end %>
<% if can_archive_result(result) && !result.archived && result_unlocked?(result) %>
<a href="#" class="btn btn-link form-submit-link" data-submit-form="result-archive-form-<%= result.id %>" data-confirm-form="<%= t('my_modules.results.archive_confirm') %>" title="<%= t'my_modules.results.options.archive_title' %>">
<a href="#"
class="btn btn-link form-submit-link"
data-form-id="result-archive-form-<%= result.id %>"
data-confirm-text="<%= t('my_modules.results.archive_confirm') %>"
title="<%= t'my_modules.results.options.archive_title' %>"
onclick="Results.archive(event, this);">
<span class="glyphicon glyphicon-briefcase"></span>
</a>
<%= form_for :result, url: result_path_of_type(result), method: :patch, html: {id: 'result-archive-form-' + result.id.to_s } do |f| %>

View file

@ -18,19 +18,28 @@
<span class="hidden-xs"><%= t'my_modules.results.add_label' %></span>
<% end %>
<% if can_create_result_text_in_module(@my_module) %>
<a class="btn btn-primary" id="new-result-text" href="<%= new_my_module_result_text_path(my_module_id: @my_module.id) %>" data-remote="true">
<a class="btn btn-primary"
id="new-result-text"
data-href="<%= new_my_module_result_text_path(my_module_id: @my_module.id) %>"
href="#">
<span class="glyphicon glyphicon-font"></span>
<span class="hidden-xs"><%= t("my_modules.results.new_text_result") %></span>
</a>
<% end %>
<% if can_create_result_table_in_module(@my_module) %>
<a class="btn btn-primary" id="new-result-table" href="<%= new_my_module_result_table_path(my_module_id: @my_module.id) %>" data-remote="true">
<a class="btn btn-primary"
id="new-result-table"
data-href="<%= new_my_module_result_table_path(my_module_id: @my_module.id) %>"
href="#">
<span class="glyphicon glyphicon-list-alt"></span>
<span class="hidden-xs"><%= t("my_modules.results.new_table_result") %></span>
</a>
<% end %>
<% if can_create_result_asset_in_module(@my_module) %>
<a class="btn btn-primary" id="new-result-asset" href="<%= new_my_module_result_asset_path(my_module_id: @my_module.id) %>" data-remote="true">
<a class="btn btn-primary"
id="new-result-asset"
data-href="<%= new_my_module_result_asset_path(my_module_id: @my_module.id) %>"
href="#">
<span class="glyphicon glyphicon-picture"></span>
<span class="hidden-xs"><%= t("my_modules.results.new_asset_result") %></span>
</a>

View file

@ -1,7 +1,10 @@
<div class="row">
<div class="pull-right" style="margin: 20px 15px 0 0;">
<% if can_create_step_in_protocol(@protocol) %>
<a class="btn btn-primary" data-action="new-step" href="<%= new_protocol_step_path(protocol_id: @protocol.id, format: :json) %>" data-remote="true">
<a href="#"
class="btn btn-primary"
data-action="new-step"
data-href="<%= new_protocol_step_path(protocol_id: @protocol.id, format: :json) %>">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
<span class="hidden-xs"><%=t "protocols.steps.new_step" %></span>
</a>

View file

@ -1,5 +1,7 @@
<% if step.blank? and @step.present? then step = @step end %>
<% timestamp = step.completed_on %>
<% step_type_str = step.completed ? 'completed' : 'uncompleted' %>
<% user = step.completed || !step.changed? ? step.user : step.last_modified_by %>
<% timestamp = step.completed ? step.completed_on : step.updated_at %>
<% tables = step.tables %>
<% assets = step.assets %>
<% checklists = step.checklists %>
@ -8,7 +10,7 @@
<div class="report-element-header">
<div class="row">
<div class="pull-left user-time">
<%=t "projects.reports.elements.step.user_time", user: step.user.full_name , timestamp: l(timestamp, format: :full) %>
<%=t "projects.reports.elements.step.#{step_type_str}.user_time", user: user.full_name , timestamp: l(timestamp, format: :full) %>
</div>
<div class="pull-right controls">
<%= render partial: "reports/elements/element_controls.html.erb", locals: { show_sort: true } %>

View file

@ -3,80 +3,34 @@
<div>
<!-- Nav tabs -->
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active"><a href="#experiment-tab" aria-controls="experiment-tab" role="tab" data-toggle="tab"><%= t("projects.reports.elements.modals.experiment_contents.experiment_tab") %></a></li>
<li role="presentation"><a href="#module-tab" aria-controls="module-tab" role="tab" data-toggle="tab"><%= t("projects.reports.elements.modals.experiment_contents.module_tab") %></a></li>
<li role="presentation"><a href="#module-steps-tab" aria-controls="module-steps-tab" role="tab" data-toggle="tab"><%= t("projects.reports.elements.modals.experiment_contents.steps_tab") %></a></li>
<li role="presentation"><a href="#step-results-tab" aria-controls="step-results-tab" role="tab" data-toggle="tab"><%= t("projects.reports.elements.modals.experiment_contents.results_tab") %></a></li>
<li role="presentation" class="active">
<a href="#tasks-tab" aria-controls="tasks-tab" role="tab" data-toggle="tab">
<span class="glyphicon glyphicon-credit-card visible-xs"></span>
<span class="hidden-xs"><%= t("projects.reports.elements.modals.project_contents.tasks_tab") %></span>
</a>
</li>
<li role="presentation">
<a href="#content-tab" aria-controls="content-tab" role="tab" data-toggle="tab">
<span class="glyphicon glyphicon-link visible-xs"></span>
<span class="hidden-xs"><%= t("projects.reports.elements.modals.project_contents.content_tab") %></span>
</a>
</li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="experiment-tab">
<div role="tabpanel" class="tab-pane active" id="tasks-tab">
<h5 class="visible-xs"><%= t("projects.reports.elements.modals.project_contents.tasks_tab") %></h5>
<%= render partial: "reports/new/modal/experiment_contents_inner.html.erb", locals: { form: f, experiment: experiment } %>
</div>
<div role="tabpanel" class="tab-pane" id="module-tab">
<div role="tabpanel" class="tab-pane" id="content-tab">
<h5 class="visible-xs"><%= t("projects.reports.elements.modals.project_contents.content_tab") %></h5>
<%= render partial: "reports/new/modal/module_contents_inner.html.erb", locals: { form: f } %>
</div>
<div role="tabpanel" class="tab-pane" id="module-steps-tab">
<hr>
<%= render partial: "reports/new/modal/step_contents_inner.html.erb", locals: { form: f } %>
</div>
<div role="tabpanel" class="tab-pane" id="step-results-tab">
<hr>
<%= render partial: "reports/new/modal/result_contents_inner.html.erb", locals: { form: f } %>
</div>
</div>
</div>
<% end %>
<script type="javascript">
$(function() {
var form = $("#add-contents-form");
var experimentTab = form.find("#experiment-tab");
var moduleTab = form.find("#module-tab");
var stepsTab = form.find("#module-steps-tab");
var experimentCheckAlls = experimentTab.find(".experiment-all-cb");
var experimentAll = experimentTab.find("input:checkbox");
experimentCheckAlls.click(function() {
var nextUl = $(this).closest("div.checkbox").next();
if (nextUl.length && nextUl.is("ul.experiment-contents-list")) {
nextUl.find("input:checkbox").prop("checked", this.checked);
}
});
experimentAll.click(function() {
var parentLists = $(this).parents("ul.experiment-contents-list");
if (parentLists.length) {
var prevEl = parentLists.prev();
if (prevEl.length && prevEl.is("div.checkbox")) {
prevEl.find("input:checkbox").prop("checked", false);
}
}
});
var moduleCheckAll = moduleTab.find(".module-check-all");
var moduleOthers = moduleTab.find("input:checkbox:not(.module-check-all)");
var moduleResultsAll = moduleTab.find(".results-all");
var moduleResults = moduleTab.find(".result-cb");
moduleCheckAll.click(function() {
moduleOthers.prop("checked", this.checked);
});
moduleOthers.click(function() {
moduleCheckAll.prop("checked", false);
});
moduleResultsAll.click(function() {
moduleResults.prop("checked", this.checked);
});
moduleResults.click(function() {
moduleResultsAll.prop("checked", false);
});
var stepsCheckAll = stepsTab.find(".step-check-all");
var stepsOthers = stepsTab.find("input:checkbox:not(.step-check-all)");
stepsCheckAll.click(function() {
stepsOthers.prop("checked", this.checked);
});
stepsOthers.click(function() {
stepsCheckAll.prop("checked", false);
});
});
</script>

View file

@ -4,30 +4,37 @@
</em>
</div>
<% if experiment.my_modules.count > 0 %>
<%= form.check_box :experiment, label: experiment.name, class: "experiment-all-cb" %>
<ul class="no-style experiment-contents-list">
<% experiment.my_module_groups.each do |my_module_group| %>
<% if my_module_group.my_modules.present? then %>
<% my_module_group.ordered_modules.each do |my_module| %>
<li>
<%= form.check_box "modules[#{my_module.id}]", label: my_module.name %>
</li>
<% if experiment.my_modules.exists? %>
<div class="checkbox-tree">
<ul>
<li>
<%= form.check_box :experiment_all, label: experiment.name %>
<ul>
<% experiment.my_module_groups.each do |my_module_group| %>
<% if my_module_group.my_modules.exists? then %>
<% my_module_group.ordered_modules.each do |my_module| %>
<li>
<%= form.check_box "modules[#{my_module.id}]", label: my_module.name %>
</li>
<% end %>
<% end %>
<% end %>
<% end %>
<% end %>
<!-- Tasks without groups -->
<% modules_without_group = experiment.modules_without_group %>
<% if modules_without_group.present? and modules_without_group.count > 0 %>
<% modules_without_group.each do |my_module| %>
<li>
<%= form.check_box "modules[#{my_module.id}]", label: my_module.name %>
</li>
<% end %>
<% end %>
<!-- Tasks without groups -->
<% modules_without_group = experiment.modules_without_group %>
<% if modules_without_group.exists? %>
<% modules_without_group.each do |my_module| %>
<li>
<%= form.check_box "modules[#{my_module.id}]", label: my_module.name %>
</li>
<% end %>
<% end %>
</ul>
</ul>
</li>
</ul>
</div>
<% else %>
<div>
<em>

View file

@ -3,56 +3,24 @@
<div>
<!-- Nav tabs -->
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active"><a href="#module-tab" aria-controls="module-tab" role="tab" data-toggle="tab"><%= t("projects.reports.elements.modals.module_contents.module_tab") %></a></li>
<li role="presentation"><a href="#module-steps-tab" aria-controls="module-steps-tab" role="tab" data-toggle="tab"><%= t("projects.reports.elements.modals.module_contents.steps_tab") %></a></li>
<li role="presentation"><a href="#step-results-tab" aria-controls="step-results-tab" role="tab" data-toggle="tab"><%= t("projects.reports.elements.modals.module_contents.results_tab") %></a></li>
<li role="presentation" class="active">
<a href="#content-tab" aria-controls="content-tab" role="tab" data-toggle="tab">
<span class="glyphicon glyphicon-link visible-xs"></span>
<span class="hidden-xs"><%= t("projects.reports.elements.modals.project_contents.content_tab") %></span>
</a>
</li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="module-tab">
<%= render partial: "reports/new/modal/module_contents_inner.html.erb", locals: { form: f, my_module: my_module } %>
</div>
<div role="tabpanel" class="tab-pane" id="module-steps-tab">
<div role="tabpanel" class="tab-pane active" id="content-tab">
<h5 class="visible-xs"><%= t("projects.reports.elements.modals.project_contents.content_tab") %></h5>
<%= render partial: "reports/new/modal/module_contents_inner.html.erb", locals: { form: f } %>
<hr>
<%= render partial: "reports/new/modal/step_contents_inner.html.erb", locals: { form: f } %>
</div>
<div role="tabpanel" class="tab-pane" id="step-results-tab">
<hr>
<%= render partial: "reports/new/modal/result_contents_inner.html.erb", locals: { form: f } %>
</div>
</div>
</div>
<% end %>
<script type="javascript">
$(function() {
var form = $("#add-contents-form");
var moduleTab = form.find("#module-tab");
var stepsTab = form.find("#module-steps-tab");
var moduleCheckAll = moduleTab.find(".module-check-all");
var moduleOthers = moduleTab.find("input:checkbox:not(.module-check-all)");
var moduleResultsAll = moduleTab.find(".results-all");
var moduleResults = moduleTab.find(".result-cb");
moduleCheckAll.click(function() {
moduleOthers.prop("checked", this.checked);
});
moduleOthers.click(function() {
moduleCheckAll.prop("checked", false);
});
moduleResultsAll.click(function() {
moduleResults.prop("checked", this.checked);
});
moduleResults.click(function() {
moduleResultsAll.prop("checked", false);
});
var stepsCheckAll = stepsTab.find(".step-check-all");
var stepsOthers = stepsTab.find("input:checkbox:not(.step-check-all)");
stepsCheckAll.click(function() {
stepsOthers.prop("checked", this.checked);
});
stepsOthers.click(function() {
stepsCheckAll.prop("checked", false);
});
});
</script>

View file

@ -6,47 +6,71 @@
</em>
</div>
<%= form.check_box :module_all, label: t("general.check_all"), class: "module-check-all" %>
<div class="checkbox-tree">
<ul>
<li>
<%= form.check_box :module_all, label: t("projects.reports.elements.modals.module_contents_inner.check_all") %>
<ul>
<%= form.label t("projects.reports.elements.modals.module_contents_inner.header") %>
<% if my_module_undefined or my_module.protocol.steps.exists? %>
<li>
<%= form.check_box :module_steps, label: t("projects.reports.elements.modals.module_contents_inner.steps") %>
<ul>
<li>
<%= form.check_box :module_completed_steps, label: t("projects.reports.elements.modals.module_contents_inner.completed_steps") %>
</li>
<li>
<%= form.check_box :module_uncompleted_steps, label: t("projects.reports.elements.modals.module_contents_inner.uncompleted_steps") %>
</li>
</ul>
</li>
<% else %>
<div>
<em>
<%= t("projects.reports.elements.modals.module_contents_inner.no_steps") %>
</em>
</div>
<% end %>
<% if my_module_undefined or my_module.protocol.steps.count > 0 %>
<%= form.check_box :module_steps, label: t("projects.reports.elements.modals.module_contents_inner.steps") %>
<% else %>
<div>
<em>
<%= t("projects.reports.elements.modals.module_contents_inner.no_steps") %>
</em>
</div>
<% end %>
<% if my_module_undefined or (my_module.results.select { |r| r.active? }).exists? %>
<li>
<%= form.check_box :module_results, label: t("projects.reports.elements.modals.module_contents_inner.results") %>
<ul>
<% if my_module_undefined or (my_module.results.select { |r| r.active? }).count > 0 %>
<%= form.check_box :module_results, label: t("projects.reports.elements.modals.module_contents_inner.results"), class: "results-all" %>
<ul class="no-style" style="padding-left: 15px;">
<% if my_module_undefined or (my_module.results.select { |r| r.is_asset && r.active? }).count > 0 %>
<li>
<%= form.check_box :module_result_assets, label: t("projects.reports.elements.modals.module_contents_inner.result_assets"), class: "result-cb" %>
</li>
<% end %>
<% if my_module_undefined or (my_module.results.select { |r| r.is_table && r.active? }).count > 0 %>
<li>
<%= form.check_box :module_result_tables, label: t("projects.reports.elements.modals.module_contents_inner.result_tables"), class: "result-cb" %>
</li>
<% end %>
<% if my_module_undefined or (my_module.results.select { |r| r.is_text && r.active? }).count > 0 %>
<li>
<%= form.check_box :module_result_texts, label: t("projects.reports.elements.modals.module_contents_inner.result_texts"), class: "result-cb" %>
</li>
<% end %>
<% if my_module_undefined or (my_module.results.select { |r| r.is_asset && r.active? }).exists? %>
<li>
<%= form.check_box :module_result_assets, label: t("projects.reports.elements.modals.module_contents_inner.result_assets") %>
</li>
<% end %>
<% if my_module_undefined or (my_module.results.select { |r| r.is_table && r.active? }).exists? %>
<li>
<%= form.check_box :module_result_tables, label: t("projects.reports.elements.modals.module_contents_inner.result_tables") %>
</li>
<% end %>
<% if my_module_undefined or (my_module.results.select { |r| r.is_text && r.active? }).exists? %>
<li>
<%= form.check_box :module_result_texts, label: t("projects.reports.elements.modals.module_contents_inner.result_texts") %>
</li>
<% end %>
</ul>
</li>
<% else %>
<div>
<em>
<%= t("projects.reports.elements.modals.module_contents_inner.no_results") %>
</em>
</div>
<% end %>
<li>
<%= form.check_box :module_activity, label: t("projects.reports.elements.modals.module_contents_inner.activity") %>
</li>
<li>
<%= form.check_box :module_samples, label: t("projects.reports.elements.modals.module_contents_inner.samples") %>
</li>
</ul>
</li>
</ul>
<% else %>
<div>
<em>
<%= t("projects.reports.elements.modals.module_contents_inner.no_results") %>
</em>
</div>
<% end %>
<%= form.check_box :module_activity, label: t("projects.reports.elements.modals.module_contents_inner.activity") %>
<%= form.check_box :module_samples, label: t("projects.reports.elements.modals.module_contents_inner.samples") %>
</div>

View file

@ -4,28 +4,16 @@
<!-- Nav tabs -->
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active">
<a href="#project-tab" aria-controls="project-tab" role="tab" data-toggle="tab">
<a href="#tasks-tab" aria-controls="tasks-tab" role="tab" data-toggle="tab">
<span class="glyphicon glyphicon-credit-card visible-xs"></span>
<span class="hidden-xs"><%= t("projects.reports.elements.modals.project_contents.project_tab") %></span>
<span class="hidden-xs"><%= t("projects.reports.elements.modals.project_contents.tasks_tab") %></span>
</a>
</li>
<% if project.project_my_modules.is_archived(false).count > 0 %>
<% if project.project_my_modules.is_archived(false).exists? %>
<li role="presentation">
<a href="#project-modules-tab" aria-controls="project-modules-tab" role="tab" data-toggle="tab">
<a href="#content-tab" aria-controls="content-tab" role="tab" data-toggle="tab">
<span class="glyphicon glyphicon-link visible-xs"></span>
<span class="hidden-xs"><%= t("projects.reports.elements.modals.project_contents.modules_tab") %></span>
</a>
</li>
<li role="presentation">
<a href="#module-steps-tab" aria-controls="module-steps-tab" role="tab" data-toggle="tab">
<span class="glyphicon glyphicon-random visible-xs"></span>
<span class="hidden-xs"><%= t("projects.reports.elements.modals.project_contents.steps_tab") %></span>
</a>
</li>
<li role="presentation">
<a href="#step-results-tab" aria-controls="step-results-tab" role="tab" data-toggle="tab">
<span class="glyphicon glyphicon-th visible-xs"></span>
<span class="hidden-xs"><%= t("projects.reports.elements.modals.project_contents.results_tab") %></span>
<span class="hidden-xs"><%= t("projects.reports.elements.modals.project_contents.content_tab") %></span>
</a>
</li>
<% end %>
@ -33,79 +21,18 @@
<!-- Tab panes -->
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="project-tab">
<h5 class="visible-xs"><%= t("projects.reports.elements.modals.project_contents.project_tab") %></h5>
<div role="tabpanel" class="tab-pane active" id="tasks-tab">
<h5 class="visible-xs"><%= t("projects.reports.elements.modals.project_contents.tasks_tab") %></h5>
<%= render partial: "reports/new/modal/project_contents_inner.html.erb", locals: { form: f, project: project } %>
</div>
<% if project.project_my_modules.is_archived(false).count > 0 %>
<div role="tabpanel" class="tab-pane" id="project-modules-tab">
<h5 class="visible-xs"><%= t("projects.reports.elements.modals.project_contents.modules_tab") %></h5>
<%= render partial: "reports/new/modal/module_contents_inner.html.erb", locals: { form: f } %>
</div>
<div role="tabpanel" class="tab-pane" id="module-steps-tab">
<h5 class="visible-xs"><%= t("projects.reports.elements.modals.project_contents.steps_tab") %></h5>
<%= render partial: "reports/new/modal/step_contents_inner.html.erb", locals: { form: f } %>
</div>
<div role="tabpanel" class="tab-pane" id="step-results-tab">
<h5 class="visible-xs"><%= t("projects.reports.elements.modals.project_contents.results_tab") %></h5>
<%= render partial: "reports/new/modal/result_contents_inner.html.erb", locals: { form: f } %>
</div>
<% end %>
<div role="tabpanel" class="tab-pane" id="content-tab">
<h5 class="visible-xs"><%= t("projects.reports.elements.modals.project_contents.content_tab") %></h5>
<%= render partial: "reports/new/modal/module_contents_inner.html.erb", locals: { form: f } %>
<hr>
<%= render partial: "reports/new/modal/step_contents_inner.html.erb", locals: { form: f } %>
<hr>
<%= render partial: "reports/new/modal/result_contents_inner.html.erb", locals: { form: f } %>
</div>
</div>
</div>
<% end %>
<script type="javascript">
$(function() {
var form = $("#add-contents-form");
var projectTab = form.find("#project-tab");
var modulesTab = form.find("#project-modules-tab");
var stepsTab = form.find("#module-steps-tab");
var projectCheckAlls = projectTab.find(".project-all-cb");
var projectAll = projectTab.find("input:checkbox");
projectCheckAlls.click(function() {
var nextUl = $(this).closest("div.checkbox").next();
if (nextUl.length && nextUl.is("ul.project-contents-list, \
ul.experiment-contents-list")) {
nextUl.find("input:checkbox").prop("checked", this.checked);
}
});
projectAll.click(function() {
var parentLists = $(this).parents("ul.project-contents-list, \
ul.experiment-contents-list");
if (parentLists.length) {
var prevEl = parentLists.prev();
if (prevEl.length && prevEl.is("div.checkbox")) {
prevEl.find("input:checkbox").prop("checked", false);
}
}
});
var modulesCheckAll = modulesTab.find(".module-check-all");
var modulesOthers = modulesTab.find("input:checkbox:not(.module-check-all)");
var modulesResultsAll = modulesTab.find(".results-all");
var modulesResults = modulesTab.find(".result-cb");
modulesCheckAll.click(function() {
modulesOthers.prop("checked", this.checked);
});
modulesOthers.click(function() {
modulesCheckAll.prop("checked", false);
});
modulesResultsAll.click(function() {
modulesResults.prop("checked", this.checked);
});
modulesResults.click(function() {
modulesResultsAll.prop("checked", false);
});
var stepsCheckAll = stepsTab.find(".step-check-all");
var stepsOthers = stepsTab.find("input:checkbox:not(.step-check-all)");
stepsCheckAll.click(function() {
stepsOthers.prop("checked", this.checked);
});
stepsOthers.click(function() {
stepsCheckAll.prop("checked", false);
});
});
</script>

View file

@ -1,41 +1,49 @@
<div>
<em>
<%= t("projects.reports.elements.modals.project_contents_inner.instructions") %>
</em>
</div>
<% if project.project_my_modules.is_archived(false).count > 0 %>
<%= form.check_box :project, label: project.name, class: "project-all-cb" %>
<ul class="no-style project-contents-list">
<% project.experiments.is_archived(false).each do |experiment| %>
<% next unless experiment.my_modules.is_archived(false).count > 0 %>
<% if project.project_my_modules.is_archived(false).exists? %>
<div class="checkbox-tree">
<ul>
<li>
<%= form.check_box "experiment_#{experiment.id}", label: experiment.name, class: "project-all-cb" %>
<ul class="no-style experiment-contents-list">
<% experiment.my_module_groups.each do |my_module_group| %>
<% if my_module_group.my_modules.is_archived(false).present? then %>
<% my_module_group.ordered_modules.is_archived(false).each do |my_module| %>
<li>
<%= form.check_box "modules[#{my_module.id}]", label: my_module.name %>
</li>
<%= form.check_box :project, label: project.name %>
<ul>
<% project.experiments.is_archived(false).each do |experiment| %>
<% next unless experiment.my_modules.is_archived(false).exists? %>
<li>
<%= form.check_box "experiment_#{experiment.id}", label: experiment.name %>
<ul>
<% experiment.my_module_groups.each do |my_module_group| %>
<% next unless my_module_group.my_modules.is_archived(false).exists? %>
<% my_module_group.ordered_modules.is_archived(false).each do |my_module| %>
<li>
<%= form.check_box "modules[#{my_module.id}]", label: my_module.name %>
</li>
<% end %>
<% end %>
<% end %>
<!-- Tasks without groups -->
<% modules_without_group = experiment.modules_without_group %>
<% if modules_without_group.exists? %>
<% modules_without_group.each do |my_module| %>
<li>
<%= form.check_box "modules[#{my_module.id}]", label: my_module.name %>
</li>
<% end %>
<% end %>
</ul>
</li>
<% end %>
<!-- Tasks without groups -->
<% modules_without_group = experiment.modules_without_group %>
<% if modules_without_group.present? and modules_without_group.count > 0 %>
<% modules_without_group.each do |my_module| %>
<li>
<%= form.check_box "modules[#{my_module.id}]", label: my_module.name %>
</li>
<% end %>
<% end %>
</ul>
</li>
<% end %>
</ul>
</ul>
</div>
<% else %>
<div>
<em>

View file

@ -4,4 +4,15 @@
</em>
</div>
<%= form.check_box :result_comments, label: t("projects.reports.elements.modals.result_contents_inner.comments") %>
<div class="checkbox-tree">
<ul>
<li>
<%= form.label :result_all, t("projects.reports.elements.modals.result_contents_inner.check_all"), class: "checkbox" %>
<ul>
<li>
<%= form.check_box :result_comments, label: t("projects.reports.elements.modals.result_contents_inner.comments") %>
</li>
</ul>
</li>
</ul>
</div>

View file

@ -1,19 +1,4 @@
<%= bootstrap_form_tag remote: true, url: step_contents_project_reports_path(project, format: :json), method: :post, html: { id: "add-contents-form" } do |f| %>
<%= hidden_field_tag :id, step.id %>
<%= render partial: "reports/new/modal/step_contents_inner.html.erb", locals: { form: f, step: step } %>
<% end %>
<script type="javascript">
$(function() {
var form = $("#add-contents-form");
var checkAll = form.find(".step-check-all");
var others = form.find("input:checkbox:not(.step-check-all)");
checkAll.click(function() {
others.prop("checked", this.checked);
});
others.click(function() {
checkAll.prop("checked", false);
});
});
</script>

View file

@ -6,33 +6,53 @@
</em>
</div>
<%= form.check_box :step_all, label: t("general.check_all"), class: "step-check-all" %>
<%= form.label t("projects.reports.elements.modals.step_contents_inner.header") %>
<% if step_undefined or step.checklists.count > 0 %>
<%= form.check_box :step_checklists, label: t("projects.reports.elements.modals.step_contents_inner.checklists") %>
<% else %>
<div>
<em>
<%= t("projects.reports.elements.modals.step_contents_inner.no_checklists") %>
</em>
</div>
<% end %>
<% if step_undefined or step.assets.count > 0 %>
<%= form.check_box :step_assets, label: t("projects.reports.elements.modals.step_contents_inner.assets") %>
<% else %>
<div>
<em>
<%= t("projects.reports.elements.modals.step_contents_inner.no_assets") %>
</em>
</div>
<% end %>
<% if step_undefined or step.tables.count > 0 %>
<%= form.check_box :step_tables, label: t("projects.reports.elements.modals.step_contents_inner.tables") %>
<% else %>
<div>
<em>
<%= t("projects.reports.elements.modals.step_contents_inner.no_tables") %>
</em>
</div>
<% end %>
<%= form.check_box :step_comments, label: t("projects.reports.elements.modals.step_contents_inner.comments") %>
<div class="checkbox-tree">
<ul>
<li>
<%= form.check_box :step_all, label: t("projects.reports.elements.modals.step_contents_inner.check_all") %>
<ul>
<% if step_undefined or step.checklists.exists? %>
<li>
<%= form.check_box :step_checklists, label: t("projects.reports.elements.modals.step_contents_inner.checklists") %>
</li>
<% else %>
<div>
<em>
<%= t("projects.reports.elements.modals.step_contents_inner.no_checklists") %>
</em>
</div>
<% end %>
<% if step_undefined or step.assets.exists? %>
<li>
<%= form.check_box :step_assets, label: t("projects.reports.elements.modals.step_contents_inner.assets") %>
</li>
<% else %>
<div>
<em>
<%= t("projects.reports.elements.modals.step_contents_inner.no_assets") %>
</em>
</div>
<% end %>
<% if step_undefined or step.tables.exists? %>
<li>
<%= form.check_box :step_tables, label: t("projects.reports.elements.modals.step_contents_inner.tables") %>
</li>
<% else %>
<div>
<em>
<%= t("projects.reports.elements.modals.step_contents_inner.no_tables") %>
</em>
</div>
<% end %>
<li>
<%= form.check_box :step_comments, label: t("projects.reports.elements.modals.step_contents_inner.comments") %>
</li>
</ul>
</li>
</ul>
</div>

View file

@ -10,7 +10,9 @@
<%= ff.file_field :file %>
<% end %>
<hr>
<%= f.submit t("result_assets.edit.update"), class: 'btn btn-primary save-result', onclick: "processResult(event, ResultTypeEnum.FILE, true);" %>
<%= f.submit t("result_assets.edit.update"),
class: 'btn btn-primary save-result',
onclick: "Results.processResult(event, Results.ResultTypeEnum.FILE, true);" %>
<button type="button" class="btn btn-default cancel-edit">
<%= t("general.cancel")%>
</button>

View file

@ -4,7 +4,9 @@
<%= 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: "processResult(event, ResultTypeEnum.FILE, false);" %>
<%= 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">
<%= t("general.cancel")%>
</button>

View file

@ -26,7 +26,8 @@
single_line: true,
hide_label: true,
placeholder: t("general.comment_placeholder"),
append: f.submit("+", onclick: "processResult(event, ResultTypeEnum.COMMENT, false);"),
append: f.submit("+",
onclick: "Results.processResult(event, Results.ResultTypeEnum.COMMENT, false);"),
help: '.',
data: { 'atwho-edit' => '' } %>
<% end %>

View file

@ -9,7 +9,9 @@
<% end %>
</div>
<hr>
<%= f.submit t("result_tables.edit.update"), class: 'btn btn-primary save-result', onclick: "processResult(event, ResultTypeEnum.TABLE, true);" %>
<%= f.submit t("result_tables.edit.update"),
class: 'btn btn-primary save-result',
onclick: "Results.processResult(event, Results.ResultTypeEnum.TABLE, true);" %>
<button type="button" class="btn btn-default cancel-edit">
<%= t("general.cancel")%>
</button>

View file

@ -8,7 +8,9 @@
</div>
<% end %>
</div>
<%= f.submit t("result_tables.new.create"), class: 'btn btn-primary save-result', onclick: "processResult(event, ResultTypeEnum.TABLE, false);" %>
<%= f.submit t("result_tables.new.create"),
class: 'btn btn-primary save-result',
onclick: "Results.processResult(event, Results.ResultTypeEnum.TABLE, false);" %>
<button type="button" class="btn btn-default cancel-new">
<%= t("general.cancel")%>
</button>

View file

@ -9,7 +9,9 @@
object_id: @result.result_text.id }) %>
</div>
<% end %><br />
<%= f.submit t("result_texts.edit.update"), class: 'btn btn-primary save-result', onclick: "processResult(event, ResultTypeEnum.TEXT, true);" %>
<%= f.submit t("result_texts.edit.update"),
class: 'btn btn-primary save-result',
onclick: "Results.processResult(event, Results.ResultTypeEnum.TEXT, true);" %>
<button type="button" class="btn btn-default cancel-edit">
<%= t("general.cancel")%>
</button>

View file

@ -7,7 +7,9 @@
object_id: @result.result_text.id }) %>
</div>
<% end %><br />
<%= f.submit t("result_texts.new.create"), class: 'btn btn-primary save-result', onclick: "processResult(event, ResultTypeEnum.TEXT, false);" %>
<%= f.submit t("result_texts.new.create"),
class: 'btn btn-primary save-result',
onclick: "Results.processResult(event, Results.ResultTypeEnum.TEXT, false);" %>
<button type="button" class="btn btn-default cancel-new">
<%= t("general.cancel")%>
</button>

View file

@ -194,7 +194,7 @@ class Constants
#=============================================================================
# Application version
APP_VERSION = '1.10.0'.freeze
APP_VERSION = '1.11.0'.freeze
TEXT_EXTRACT_FILE_TYPES = [
'application/pdf',

View file

@ -11,25 +11,27 @@ module ReportExtends
# ModuleElement struct creates an argument objects which is needed in
# generate_module_contents_json method. It takes 3 parameters a Proc and
# additional options wich can be extended.
# :values => name of the hook/identifier for specific module element state
# :element => name of module element in plural
# :children => bolean if element has children elements in report
# :locals => an array of names of local variables which are passed in the view
# :coll => a prock which the my_module is passed and have to return a
# collection of element
# :singular => true by defaut change the enum type to singular
# needed when querying partials by name
# :coll => a procedure which the my_module is passed and have to return a
# collection of elements
# :singular => true by defaut; change the enum type to singular - needed when
# querying partials by name
ModuleElement = Struct.new(:element,
ModuleElement = Struct.new(:values,
:element,
:children,
:locals,
:coll,
:singular) do
def initialize(element, children, locals, coll = nil, singular = true)
super(element, children, locals, coll, singular)
def initialize(values, element, children, locals, coll = nil, singular = true)
super(values, element, children, locals, coll, singular)
end
def collection(my_module)
coll.call(my_module) if coll
def collection(my_module, params2)
coll.call(my_module, params2) if coll
end
def parse_locals(values)
@ -48,34 +50,43 @@ module ReportExtends
# Module contents element
MODULE_CONTENTS = [
ModuleElement.new(:steps,
ModuleElement.new(%i(completed_steps uncompleted_steps),
:steps,
true,
[:step],
proc do |my_module|
my_module.protocol.completed_steps.order(:position)
proc do |my_module, params2|
steps = []
steps << true if params2["module_completed_steps"] == '1'
steps << false if params2["module_uncompleted_steps"] == '1'
my_module.protocol.steps.where(completed: steps).order(:position)
end),
ModuleElement.new(:result_assets,
ModuleElement.new([:result_assets],
:result_assets,
true,
[:result],
proc do |my_module|
my_module.results.select { |r| r.is_asset && r.active? }
end),
ModuleElement.new(:result_tables,
ModuleElement.new([:result_tables],
:result_tables,
true,
[:result],
proc do |my_module|
my_module.results.select { |r| r.is_table && r.active? }
end),
ModuleElement.new(:result_texts,
ModuleElement.new([:result_texts],
:result_texts,
true,
[:result],
proc do |my_module|
my_module.results.select { |r| r.is_text && r.active? }
end),
ModuleElement.new(:activity,
ModuleElement.new([:activity],
:activity,
false,
[:my_module, :order]),
ModuleElement.new(:samples,
ModuleElement.new([:samples],
:samples,
false,
[:my_module, :order])
]

View file

@ -104,7 +104,7 @@ en:
search:
whole_word: "Match any whole word"
whole_phrase: "Match whole phrase"
match_case: "Match case"
match_case: "Match case sensitive"
index:
head_title: "Search"
page_title: "Search"
@ -291,10 +291,8 @@ en:
modals:
project_contents:
head_title: "Add contents to report"
project_tab: "Choose tasks"
modules_tab: "Tasks content"
steps_tab: "Protocols content"
results_tab: "Results content"
tasks_tab: "Choose tasks"
content_tab: "Choose content"
project_contents_inner:
instructions: "Select projects/experiment/tasks to include in the report"
no_modules: "The project contains no tasks"
@ -306,9 +304,11 @@ en:
results_tab: "Results content"
module_contents_inner:
instructions: "Choose what information from task/s to include in the report"
header: "Report elements"
steps: "Completed protocol steps"
no_steps: "Task contains no protocols"
check_all: "All tasks content"
steps: "Steps"
completed_steps: "Completed"
uncompleted_steps: "Uncompleted"
no_steps: "Task has no steps"
results: "Results"
result_assets: "Files"
result_tables: "Tables"
@ -331,7 +331,7 @@ en:
results_tab: "Results content"
step_contents_inner:
instructions: "Choose what information from task protocol step/s to include in the report"
header: "Report elements"
check_all: "All protocols steps content"
tables: "Tables"
no_tables: "Step contains no tables"
assets: "Files"
@ -343,6 +343,7 @@ en:
head_title: "Add contents to result %{result}"
result_contents_inner:
instructions: "Include result/s comments in the report?"
check_all: "All results content"
comments: "Comments"
add: "Add to report"
save_report:
@ -391,9 +392,12 @@ en:
user_time: "Created by %{user} on %{timestamp}."
step:
sidebar_name: "Step %{pos}: %{name}"
user_time: "Completed by %{user} on %{timestamp}."
step_pos: "Step %{pos}:"
no_description: "No description"
completed:
user_time: "Completed by %{user} on %{timestamp}."
uncompleted:
user_time: "Created by %{user} on %{timestamp}."
step_table:
table_name: "[ %{name} ]"
user_time: "Table created on %{timestamp}."
@ -558,7 +562,7 @@ en:
load_from_repository_modal:
title: "Load protocol from repository"
text: "Choose the protocol to be loaded to the task."
text2: "This will overwrite the current protocol!"
text2: "This action will overwrite the current protocol in the task and unlink it from repository. The current protocol will remain unchanged in repository."
tab_public: "Public protocols"
tab_private: "Private protocols"
thead_name: "Name"
@ -569,7 +573,7 @@ en:
thead_published_on: "Published at"
thead_created_at: "Created at"
thead_updated_at: "Last modified at"
confirm_message: "Are you sure you wish to load protocol from repository? This action will overwrite the current protocol."
confirm_message: "Are you sure you wish to load protocol from repository? This action will overwrite the current protocol in the task and unlink it from repository. The current protocol will remain unchanged in repository."
import_to_linked_task_rep: "Are you sure you wish to load protocol from repository? This action will overwrite the current protocol in the task and unlink it from repository. The current protocol will remain unchanged in repository."
load: "Load"
copy_to_repository_modal:
@ -1587,10 +1591,11 @@ en:
confirm_2: "to confirm"
dismiss_1: "esc"
dismiss_2: "to dismiss"
popover_html: "<span class='silver'>Team:</span>&nbsp;%{team} <br> <span class='silver'>Role:</span>&nbsp;%{role} <br> <span class='silver'>Joined:</span>&nbsp;%{time}"
res:
archived: "(archived)"
removed: "(removed)"
deleted: "(deleted)"
popover_html: "<span class='silver'>Team:</span>&nbsp;%{team} <br> <span class='silver'>Role:</span>&nbsp;%{role} <br> <span class='silver'>Joined:</span>&nbsp;%{time}"
zip_export:
notification_title: 'Your package is ready to be exported!'
@ -1612,7 +1617,6 @@ en:
save: "Save"
close: "Close"
create: 'Create'
check_all: "Check all"
no_comments: "No comments!"
more_comments: "More comments"
comment_placeholder: "Your Message"

View file

@ -70,6 +70,67 @@ ActiveRecord::Schema.define(version: 20170515073041) do
add_index "assets", ["last_modified_by_id"], name: "index_assets_on_last_modified_by_id", using: :btree
add_index "assets", ["team_id"], name: "index_assets_on_team_id", using: :btree
create_table "billing_accounts", force: :cascade do |t|
t.string "braintree_customer_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "billing_accounts", ["braintree_customer_id"], name: "index_billing_accounts_on_braintree_customer_id", using: :btree
create_table "billing_addons", force: :cascade do |t|
t.string "braintree_addon_id"
t.integer "type_of"
t.string "name", null: false
t.string "description"
t.integer "amount_cents", default: 0, null: false
t.string "amount_currency", default: "USD", null: false
t.integer "additional_storage", limit: 8, default: 0
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "billing_addons", ["braintree_addon_id"], name: "index_billing_addons_on_braintree_addon_id", using: :btree
add_index "billing_addons", ["name"], name: "index_billing_addons_on_name", using: :btree
add_index "billing_addons", ["type_of"], name: "index_billing_addons_on_type_of", using: :btree
create_table "billing_plans", force: :cascade do |t|
t.string "braintree_plan_id", null: false
t.string "name", null: false
t.string "description"
t.integer "price_cents", default: 0, null: false
t.string "price_currency", default: "USD", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "main", default: false, null: false
t.integer "max_storage", limit: 8, default: 0
t.integer "position", default: 0, null: false
t.boolean "free", default: false, null: false
end
add_index "billing_plans", ["braintree_plan_id"], name: "index_billing_plans_on_braintree_plan_id", using: :btree
create_table "billing_subscription_addons", force: :cascade do |t|
t.integer "billing_subscription_id", null: false
t.integer "billing_addon_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "billing_subscription_addons", ["billing_addon_id"], name: "index_billing_subscription_addons_on_billing_addon_id", using: :btree
add_index "billing_subscription_addons", ["billing_subscription_id"], name: "index_billing_subscription_addons_on_billing_subscription_id", using: :btree
create_table "billing_subscriptions", force: :cascade do |t|
t.string "braintree_subscription_id"
t.integer "billing_account_id", null: false
t.integer "billing_plan_id", null: false
t.boolean "active", default: false, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "billing_subscriptions", ["braintree_subscription_id"], name: "index_billing_subscriptions_on_braintree_subscription_id", using: :btree
create_table "checklist_items", force: :cascade do |t|
t.string "text", null: false
t.boolean "checked", default: false, null: false
@ -175,6 +236,16 @@ ActiveRecord::Schema.define(version: 20170515073041) do
add_index "experiments", ["project_id"], name: "index_experiments_on_project_id", using: :btree
add_index "experiments", ["restored_by_id"], name: "index_experiments_on_restored_by_id", using: :btree
create_table "logs", force: :cascade do |t|
t.integer "action_type", null: false
t.string "user_name"
t.jsonb "details", default: {}, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "logs", ["created_at", "action_type"], name: "index_logs_on_created_at_and_action_type", using: :btree
create_table "my_module_groups", force: :cascade do |t|
t.string "name", null: false
t.datetime "created_at", null: false
@ -197,26 +268,28 @@ ActiveRecord::Schema.define(version: 20170515073041) do
add_index "my_module_tags", ["tag_id"], name: "index_my_module_tags_on_tag_id", using: :btree
create_table "my_modules", force: :cascade do |t|
t.string "name", null: false
t.string "name", null: false
t.datetime "due_date"
t.string "description"
t.integer "x", default: 0, null: false
t.integer "y", default: 0, null: false
t.integer "x", default: 0, null: false
t.integer "y", default: 0, null: false
t.integer "my_module_group_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "archived", default: false, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "archived", default: false, null: false
t.datetime "archived_on"
t.integer "created_by_id"
t.integer "last_modified_by_id"
t.integer "archived_by_id"
t.integer "restored_by_id"
t.datetime "restored_on"
t.integer "nr_of_assigned_samples", default: 0
t.integer "workflow_order", default: -1, null: false
t.integer "experiment_id", default: 0, null: false
t.integer "state", limit: 2, default: 0
t.integer "nr_of_assigned_samples", default: 0
t.integer "workflow_order", default: -1, null: false
t.integer "experiment_id", default: 0, null: false
t.integer "state", limit: 2, default: 0
t.datetime "completed_on"
t.integer "electronic_signature_status", default: 1
t.datetime "electronic_signature_status_locked_at"
end
add_index "my_modules", ["archived_by_id"], name: "index_my_modules_on_archived_by_id", using: :btree
@ -468,6 +541,37 @@ ActiveRecord::Schema.define(version: 20170515073041) do
add_index "samples_tables", ["team_id"], name: "index_samples_tables_on_team_id", using: :btree
add_index "samples_tables", ["user_id"], name: "index_samples_tables_on_user_id", using: :btree
create_table "scinote_core_gamification_scores", force: :cascade do |t|
t.integer "leaf_tokens", limit: 8
t.integer "step", default: 0, null: false
t.integer "user_id"
t.boolean "tutorial", default: false
t.boolean "project", default: false
t.boolean "experiment", default: false
t.boolean "task", default: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "scinote_core_gamification_scores", ["user_id"], name: "index_scinote_core_gamification_scores_on_user_id", using: :btree
create_table "scinote_enterprise_electronic_signatures", force: :cascade do |t|
t.integer "user_id"
t.string "user_full_name", null: false
t.string "user_role", null: false
t.string "user_email", null: false
t.text "comment"
t.integer "action"
t.integer "type_of_signature"
t.integer "reference_object_id"
t.integer "reference_object_name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "scinote_enterprise_electronic_signatures", ["created_at"], name: "index_scinote_enterprise_electronic_signatures_on_created_at", using: :btree
add_index "scinote_enterprise_electronic_signatures", ["user_id"], name: "index_scinote_enterprise_electronic_signatures_on_user_id", using: :btree
create_table "settings", force: :cascade do |t|
t.text "type", null: false
t.jsonb "values", default: {}, null: false
@ -547,8 +651,11 @@ ActiveRecord::Schema.define(version: 20170515073041) do
t.integer "last_modified_by_id"
t.string "description"
t.integer "space_taken", limit: 8, default: 1048576, null: false
t.integer "billing_account_id"
t.integer "agile_crm_deal_id", limit: 8
end
add_index "teams", ["billing_account_id"], name: "index_teams_on_billing_account_id", using: :btree
add_index "teams", ["created_by_id"], name: "index_teams_on_created_by_id", using: :btree
add_index "teams", ["last_modified_by_id"], name: "index_teams_on_last_modified_by_id", using: :btree
add_index "teams", ["name"], name: "index_teams_on_name", using: :btree
@ -669,6 +776,8 @@ ActiveRecord::Schema.define(version: 20170515073041) do
t.string "invited_by_type"
t.integer "invitations_count", default: 0
t.integer "tutorial_status", default: 0, null: false
t.datetime "last_seen_at"
t.integer "agile_crm_contact_id", limit: 8
t.boolean "assignments_notification", default: true
t.boolean "recent_notification", default: true
t.boolean "assignments_notification_email", default: false
@ -676,6 +785,8 @@ ActiveRecord::Schema.define(version: 20170515073041) do
t.integer "current_team_id"
t.boolean "system_message_notification_email", default: false
t.string "authentication_token", limit: 30
t.integer "organization_role", limit: 2, default: 0
t.datetime "password_changed_at"
end
add_index "users", ["authentication_token"], name: "index_users_on_authentication_token", unique: true, using: :btree
@ -684,8 +795,22 @@ ActiveRecord::Schema.define(version: 20170515073041) do
add_index "users", ["invitation_token"], name: "index_users_on_invitation_token", unique: true, using: :btree
add_index "users", ["invitations_count"], name: "index_users_on_invitations_count", using: :btree
add_index "users", ["invited_by_id"], name: "index_users_on_invited_by_id", using: :btree
add_index "users", ["password_changed_at"], name: "index_users_on_password_changed_at", using: :btree
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
create_table "versions", force: :cascade do |t|
t.string "item_type", null: false
t.integer "item_id", null: false
t.string "event", null: false
t.string "whodunnit"
t.text "object"
t.text "object_changes"
t.integer "team_id"
t.datetime "created_at"
end
add_index "versions", ["item_type", "item_id", "team_id"], name: "index_versions_on_item_type_and_item_id_and_team_id", using: :btree
create_table "wopi_actions", force: :cascade do |t|
t.string "action", null: false
t.string "extension", null: false
@ -728,6 +853,10 @@ ActiveRecord::Schema.define(version: 20170515073041) do
add_foreign_key "asset_text_data", "assets"
add_foreign_key "assets", "users", column: "created_by_id"
add_foreign_key "assets", "users", column: "last_modified_by_id"
add_foreign_key "billing_subscription_addons", "billing_addons"
add_foreign_key "billing_subscription_addons", "billing_subscriptions"
add_foreign_key "billing_subscriptions", "billing_accounts"
add_foreign_key "billing_subscriptions", "billing_plans"
add_foreign_key "checklist_items", "checklists"
add_foreign_key "checklist_items", "users", column: "created_by_id"
add_foreign_key "checklist_items", "users", column: "last_modified_by_id"
@ -807,6 +936,7 @@ ActiveRecord::Schema.define(version: 20170515073041) do
add_foreign_key "samples", "teams"
add_foreign_key "samples", "users"
add_foreign_key "samples", "users", column: "last_modified_by_id"
add_foreign_key "scinote_core_gamification_scores", "users"
add_foreign_key "step_assets", "assets"
add_foreign_key "step_assets", "steps"
add_foreign_key "step_tables", "steps"
@ -819,6 +949,7 @@ ActiveRecord::Schema.define(version: 20170515073041) do
add_foreign_key "tags", "projects"
add_foreign_key "tags", "users", column: "created_by_id"
add_foreign_key "tags", "users", column: "last_modified_by_id"
add_foreign_key "teams", "billing_accounts"
add_foreign_key "teams", "users", column: "created_by_id"
add_foreign_key "teams", "users", column: "last_modified_by_id"
add_foreign_key "tokens", "users"