Remove tutorial [SCI-1860]

This commit is contained in:
Oleksii Kriuchykhin 2018-01-09 15:57:06 +01:00
parent dc22e05b02
commit a105e61d48
54 changed files with 42 additions and 892 deletions

View file

@ -36,7 +36,6 @@ gem 'jquery-ui-rails'
gem 'jquery-scrollto-rails',
git: 'https://github.com/biosistemika/jquery-scrollto-rails'
gem 'hammerjs-rails'
gem 'introjs-rails' # Create quick tutorials
gem 'js_cookie_rails' # Simple JS API for cookies
gem 'spinjs-rails'
gem 'autosize-rails' # jQuery autosize plugin

View file

@ -231,9 +231,6 @@ GEM
concurrent-ruby (~> 1.0)
i18n-js (3.0.3)
i18n (~> 0.6, >= 0.6.6)
introjs-rails (1.0.0)
sass-rails (>= 3.2)
thor (~> 0.14)
jbuilder (2.7.0)
activesupport (>= 4.2.0)
multi_json (>= 1.2)
@ -558,7 +555,6 @@ DEPENDENCIES
font-awesome-rails (~> 4.7.0.2)
hammerjs-rails
i18n-js (~> 3.0)
introjs-rails
jbuilder
jquery-rails
jquery-scrollto-rails!

View file

@ -7,7 +7,6 @@ SECRET_KEY_BASE=$(shell openssl rand -hex 64)
PAPERCLIP_HASH_SECRET=$(shell openssl rand -base64 128 | tr -d '\n')
DATABASE_URL=postgresql://postgres@db/scinote_production
PAPERCLIP_STORAGE=filesystem
ENABLE_TUTORIAL=true
ENABLE_RECAPTCHA=false
ENABLE_USER_CONFIRMATION=false
ENABLE_USER_REGISTRATION=true
@ -83,7 +82,7 @@ integration-tests:
@$(MAKE) rails cmd="bundle exec cucumber"
tests-ci:
@docker-compose run -e ENABLE_EMAIL_CONFIRMATIONS=false -e MAILER_PORT=$MAILER_PORT -e SMTP_DOMAIN=$SMTP_DOMAIN -e SMTP_USERNAME=$SMTP_USERNAME -e SMTP_PASSWORD=$SMTP_PASSWORD -e SMTP_ADDRESS=$SMTP_ADDRESS -e PAPERCLIP_HASH_SECRET=PAPERCLIP_HASH_SECRET -e MAIL_SERVER_URL=localhost -e PAPERCLIP_STORAGE=filesystem -e ENABLE_TUTORIAL=false -e ENABLE_RECAPTCHA=false -e ENABLE_USER_CONFIRMATION=false -e ENABLE_USER_REGISTRATION=true --rm web bash -c "bundle install && rake db:create db:migrate && rake db:migrate RAILS_ENV=test && yarn install && bundle exec rspec && bundle exec cucumber"
@docker-compose run -e ENABLE_EMAIL_CONFIRMATIONS=false -e MAILER_PORT=$MAILER_PORT -e SMTP_DOMAIN=$SMTP_DOMAIN -e SMTP_USERNAME=$SMTP_USERNAME -e SMTP_PASSWORD=$SMTP_PASSWORD -e SMTP_ADDRESS=$SMTP_ADDRESS -e PAPERCLIP_HASH_SECRET=PAPERCLIP_HASH_SECRET -e MAIL_SERVER_URL=localhost -e PAPERCLIP_STORAGE=filesystem -e ENABLE_RECAPTCHA=false -e ENABLE_USER_CONFIRMATION=false -e ENABLE_USER_REGISTRATION=true --rm web bash -c "bundle install && rake db:create db:migrate && rake db:migrate RAILS_ENV=test && yarn install && bundle exec rspec && bundle exec cucumber"
console:
@$(MAKE) rails cmd="rails console"

View file

Before

Width:  |  Height:  |  Size: 531 KiB

After

Width:  |  Height:  |  Size: 531 KiB

View file

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 41 KiB

View file

Before

Width:  |  Height:  |  Size: 530 KiB

After

Width:  |  Height:  |  Size: 530 KiB

View file

Before

Width:  |  Height:  |  Size: 474 KiB

After

Width:  |  Height:  |  Size: 474 KiB

View file

Before

Width:  |  Height:  |  Size: 183 KiB

After

Width:  |  Height:  |  Size: 183 KiB

View file

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB

View file

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

View file

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB

View file

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 73 KiB

View file

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 80 KiB

View file

@ -1,4 +1,4 @@
# Content for tables used in tutorial (demo project).
# Content for tables used in demo project.
module1:
experimental_design: '{"data":[["","","",null,null],["","","",null,null],["group/time","1 dpi","6 dpi","",""],["PVYNTN","1","1","",""],["mock","1","1","",""],[null,null,null,null,null]]}'

View file

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View file

@ -15,7 +15,6 @@
//= require jquery.caret.min
//= require jquery.atwho.min
//= require hammer
//= require introjs
//= require js.cookie
//= require spin
//= require jquery.spin

View file

@ -17,7 +17,6 @@ function init() {
initImport();
Comments.bindNewElement();
Comments.initialize();
initTutorial();
setupAssetsLoading();
}
@ -113,31 +112,6 @@ function bindEditDueDateAjax() {
});
}
/**
* Initializes tutorial
*/
function initTutorial() {
var stepNum = parseInt(Cookies.get('current_tutorial_step'), 10);
if (stepNum >= 12 && stepNum <= 14) {
var resultsTab = $('#results-nav-tab');
var nextPage = resultsTab.find('a').attr('href');
var steps = [{
intro: I18n.t('tutorial.module_protocols_html'),
}, {
element: $('#protocol-copy-to-repository')[0],
intro: I18n.t('tutorial.module_protocols_save_html'),
position: 'right'
}, {
element: resultsTab[0],
intro: I18n.t('tutorial.module_protocols_click_results_html'),
position: 'right'
}];
initPageTutorialSteps(12, 14, nextPage, function() {}, function() {},
steps);
}
}
function initCopyToRepository() {
var link = $("[data-action='copy-to-repository']");
var modal = $("#copy-to-repository-modal");

View file

@ -15,7 +15,6 @@
function init() {
initHandsOnTables($(document));
_expandAllResults();
_initTutorial();
applyCollapseLinkCallBack();
Comments.bindNewElement();
@ -130,28 +129,6 @@
}
}
/**
* 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();

View file

@ -116,9 +116,6 @@ var ignoreUnsavedWorkAlert;
// Global variable for hammer js
var hammertime;
// Cookie data for tutorial
var tutorialData;
/*
* As a guideline, all module elements should contain
* the following attributes:
@ -146,7 +143,6 @@ function init() {
bindWindowResizeEvent();
initializeGraph(".diagram .module-large");
initializeFullZoom();
initTutorial();
}
jsPlumb.ready(function () {
@ -2999,117 +2995,6 @@ function initJsPlumb(containerSel, containerChildSel, modulesSel, params) {
}
})();
/**
* Initializes tutorial
*/
function initTutorial() {
var tutorialData = Cookies.get('tutorial_data');
if (tutorialData) {
tutorialData = JSON.parse(tutorialData);
var stepNum = parseInt(Cookies.get('current_tutorial_step'), 10);
if (stepNum >= 6 && stepNum <= 7) {
var nextPage = window.location.pathname;
var steps = [{
element: $('#canvas-container')[0],
intro: I18n.t('tutorial.canvas_overview_html'),
position: 'left'
}, {
element: $('#edit-canvas-button')[0],
intro: I18n.t('tutorial.canvas_click_edit_workflow_html'),
position: 'left'
}];
initPageTutorialSteps(6, 7, nextPage, tutorialBeforeCb, tutorialAfterCb,
steps);
} else if (stepNum >= 8 && stepNum <= 9) {
// Go into edit canvas mode
$('.introjs-overlay').remove();
$('.introjs-helperLayer').remove();
$('.introjs-tooltipReferenceLayer').remove();
$('#edit-canvas-button').click();
setTimeout(function() {
var nextPage = window.location.pathname;
var steps = [{
intro: I18n.t('tutorial.edit_workflow_html'),
element: $('#canvas-new-module')[0],
position: 'right'
}, {
intro: I18n.t('tutorial.edit_workflow_click_save_html'),
element: $('#canvas-save')[0],
position: 'right'
}];
initPageTutorialSteps(8, 9, nextPage, tutorialBeforeCb, function() {
// Go out of edit canvas mode
$('.cancel-edit-canvas').click();
tutorialAfterCb();
}, steps);
}, 1000);
} else if (stepNum >= 10 && stepNum <= 11) {
var qpcrModuleLeaf =
$("li.leaf[data-module-id='" + tutorialData[0].qpcr_module + "']");
var nextPage = qpcrModuleLeaf.find('a.module-link').attr('href');
var steps = [{
element: $('#slide-panel .tree')[0],
intro: I18n.t('tutorial.sidebar_html'),
position: 'right'
}, {
element: qpcrModuleLeaf[0],
intro: I18n.t('tutorial.sidebar_click_module_html'),
position: 'right'
}];
initPageTutorialSteps(10, 11, nextPage, tutorialBeforeCb,
tutorialAfterCb, steps);
}
}
}
/**
* Callback to be executed before tutorial starts
*/
function tutorialBeforeCb() {
$('#slide-panel')
.css({'pointer-events': 'none'});
$('#canvas-new-module')
.css({'pointer-events': 'none'});
$.each($('.panel-default'), function(i, el) {
$(el)
.find('.tab-pane')
.css({'pointer-events': 'none'});
$(el)
.find('.edit-tags-link')
.css({'pointer-events': 'none'});
$(el)
.find('.panel-heading')
.css({'pointer-events': 'none'});
});
}
/**
* Callback to be executed after tutorial exits
*/
function tutorialAfterCb() {
$('#slide-panel')
.css({'pointer-events': 'auto'});
$('#canvas-new-module')
.css({'pointer-events': 'auto'});
$.each($('.panel-default'), function(i, el) {
$(el)
.find('.tab-pane')
.css({'pointer-events': 'auto'});
$(el)
.find('.edit-tags-link')
.css({'pointer-events': 'auto'});
$(el)
.find('.panel-heading')
.css({'pointer-events': 'auto'});
});
}
/** prevent reload page */
var preventCanvasReloadOnSave = (function() {
'use strict';

View file

@ -102,8 +102,6 @@
.on('ajax:error', function() {
// TODO
});
initTutorial();
}
/**
@ -335,131 +333,5 @@
initUserRoleForms();
}
/**
* Initializes tutorial
*/
function initTutorial() {
var tutorialData = Cookies.get('tutorial_data');
if (tutorialData) {
tutorialData = JSON.parse(tutorialData);
var stepNum = parseInt(Cookies.get('current_tutorial_step'), 10);
if (isNaN(stepNum)) {
// Cookies data initialization
stepNum = 1;
Cookies.set('current_tutorial_step', stepNum);
tutorialData[0].backPagesPaths = [];
Cookies.set('tutorial_data', tutorialData);
}
var demoProjectId = tutorialData[0].project;
var demoProject = $('#' + demoProjectId);
if (stepNum >= 1 && stepNum <= 3) {
var thirdStepPos = (demoProject.offset().top > window.innerHeight / 2) ?
'top' : 'bottom';
var nextPage = $('#' + demoProjectId + '-project-canvas-link')
.attr('href');
var steps = [{
element: $('#projects-toolbar')[0],
intro: I18n.t('tutorial.tutorial_welcome_title_html'),
position: 'bottom'
}, {
element: $('#new-project-btn')[0],
intro: I18n.t('tutorial.create_project_html'),
position: 'left'
}, {
element: demoProject[0],
intro: I18n.t('tutorial.project_options_html'),
position: thirdStepPos
}];
initPageTutorialSteps(1, 3, nextPage, tutorialBeforeCb,
tutorialAfterCb, steps);
} else if (stepNum === 22) {
var protocolLink = $('#protocol-link');
var nextPage = protocolLink.attr('href');
var steps = [{
element: protocolLink[0],
intro: I18n.t('tutorial.protocols_link_html'),
position: 'left'
}];
initPageTutorialSteps(22, 22, nextPage, function() {}, function() {},
steps);
} else if (stepNum >= 25 && stepNum <= 26) {
var firstStepPos = 'right';
if (demoProject.offset().left > window.innerWidth / 2 ||
window.innerWidth < demoProject.width() + 100) {
if (demoProject.offset().top > 500 && demoProject.offset().top >
window.innerHeight / 2) {
firstStepPos = 'top';
} else {
firstStepPos = 'bottom';
}
}
var nextPage = $('#new-report-btn').attr('href');
var steps = [{
element: demoProject[0],
intro: I18n.t('tutorial.archive_project_html'),
position: firstStepPos
}, {
element: $('.avatar')[0],
intro: I18n.t('tutorial.goodbye_message'),
position: 'left'
}];
initPageTutorialSteps(25, 26, nextPage, function() {}, function() {},
steps);
}
}
}
/**
* Callback to be executed before tutorial starts
*/
function tutorialBeforeCb() {
$.each($('.panel'), function(i, el){
$(el)
.find('.panel-title')
.css({ 'pointer-events': 'none' });
$(el)
.find('.tab-content')
.css({ 'pointer-events': 'none' });
$(el)
.find('.form-submit-link')
.css({
'pointer-events': 'none',
'color': '<%= Constants::COLOR_ALTO %>'});
$(el)
.find("[data-action='edit']")
.css({
'pointer-events': 'none',
'color': '<%= Constants::COLOR_ALTO %>'});
});
}
/**
* Callback to be executed after tutorial exits
*/
function tutorialAfterCb() {
$.each($('.panel'), function(i, el){
$(el)
.find('.tab-content')
.css({ 'pointer-events': 'auto' });
$(el)
.find('.panel-title')
.css({ 'pointer-events': 'auto' });
$(el)
.find('.form-submit-link')
.css({
'pointer-events': 'auto',
'color': '<%= Constants::COLOR_NERO %>'});
$(el)
.find("[data-action='edit']")
.css({
'pointer-events': 'auto',
'color': '<%= Constants::COLOR_NERO %>'});
});
}
init();
}());

View file

@ -6,8 +6,6 @@
var that = $(this);
initProjectExperiment(that);
});
initTutorial();
}
function initProjectExperiment(element){
@ -64,58 +62,5 @@
});
}
/**
* Initializes tutorial
*/
function initTutorial() {
var stepNum = parseInt(Cookies.get('current_tutorial_step'), 10);
if (stepNum >= 4 && stepNum <= 5) {
var nextPage = $('[data-canvas-link]').data('canvasLink');
var steps = [{
element: $('#new-experiment')[0],
intro: I18n.t('tutorial.tutorial_welcome_title_html'),
position: 'left'
}, {
element: $('.experiment-panel')[0],
intro: I18n.t('tutorial.edit_experiment_html'),
position: 'right'
}];
initPageTutorialSteps(4, 5, nextPage, tutorialBeforeCb, tutorialAfterCb,
steps);
}
}
/**
* Callback to be executed before tutorial starts
*/
function tutorialBeforeCb() {
$.each( $(".panel-title"), function(){
$(this).css({ "pointer-events": "none" });
});
$.each( $(".workflowimg-container"), function(){
$(this).css({ "pointer-events": "none" });
});
$.each( $(".dropdown-experiment-actions").find("li"),
function(){
$(this).css({ "pointer-events": "none" });
});
}
/**
* Callback to be executed after tutorial exits
*/
function tutorialAfterCb() {
$.each( $(".panel-title"), function(){
$(this).css({ "pointer-events": "auto" });
});
$.each( $(".workflowimg-container"), function(){
$(this).css({ "pointer-events": "auto" });
});
$.each( $(".dropdown-experiment-actions").find("li"),
function(){
$(this).css({ "pointer-events": "auto" });
});
}
init();
})();

View file

@ -19,7 +19,6 @@ function init() {
initCreateNewModal();
initModals();
initImport();
initTutorial();
}
// Initialize protocols DataTable
@ -770,25 +769,4 @@ function initImport() {
});
}
/**
* Initializes tutorial
*/
function initTutorial() {
var stepNum = parseInt(Cookies.get('current_tutorial_step'), 10);
if (stepNum >= 23 && stepNum <= 24) {
var nextPage = $('.navbar-brand').attr('href');
var steps = [{
element: $('.nav-settings')[0],
intro: I18n.t('tutorial.protocols_index_html'),
position: 'bottom'
}, {
element: $('#import-export-protocols')[0],
intro: I18n.t('tutorial.protocols_import_export_html'),
position: 'bottom'
}];
initPageTutorialSteps(23, 24, nextPage, function() {}, function() {},
steps);
}
}
init();

View file

@ -38,7 +38,6 @@
updateButtons();
initEditReport();
initDeleteReports();
initTutorial();
}
/**
@ -163,24 +162,5 @@
});
}
/**
* Initializes tutorial
*/
function initTutorial() {
var stepNum = parseInt(Cookies.get('current_tutorial_step'), 10);
if (stepNum === 19) {
var newReportBtn = $('#new-report-btn');
var nextPage = newReportBtn.attr('href');
var steps = [{
element: newReportBtn[0],
intro: I18n.t('tutorial.reports_index_click_new_report_html'),
position: 'right'
}];
initPageTutorialSteps(19, 19, nextPage, function() {}, function() {},
steps);
}
}
$(document).ready(init);
}());

View file

@ -33,7 +33,6 @@ var ignoreUnsavedWorkAlert;
initializeAddContentsModal();
initializeSidebarNavigation();
initializeUnsavedWorkDialog();
initTutorial();
$('.report-nav-link').each(function() {
truncateLongString($(this), <%= Constants::NAME_TRUNCATION_LENGTH %>);
@ -1146,32 +1145,6 @@ function initializeReportSidebartruncation() {
observer.observe(target, config);
}
/**
* Initializes tutorial
*/
function initTutorial() {
var stepNum = parseInt(Cookies.get('current_tutorial_step'), 10);
if (stepNum >= 20 && stepNum <= 21) {
ignoreUnsavedWorkAlert = true;
var nextPage = $('.navbar-brand').attr('href');
var steps = [{
element: $('.new-element')[0],
intro: I18n.t('tutorial.new_report_html'),
position: 'left'
}, {
element: $('#team-link')[0],
intro: I18n.t('tutorial.new_report_click_team_html',
{ private_team: $('#team-link span').last().text() }),
position: 'left'
}];
initPageTutorialSteps(20, 21, nextPage, function() {}, function() {
ignoreUnsavedWorkAlert = false;
},
steps);
}
}
$(document).ready(function() {
// Check if we are actually at new report page
if ($(REPORT_CONTENT).length) {

View file

@ -58,25 +58,3 @@ function updateSamplesTypesandGroups() {
}
});
}
/**
* Initializes tutorial
*/
function initTutorial() {
var stepNum = parseInt(Cookies.get('current_tutorial_step'), 10);
if (stepNum >= 17 && stepNum <= 18) {
var nextPage = $('#reports-nav-tab a').attr('href');
var steps = [{
element: $('#importSamplesButton')[0],
intro: I18n.t('tutorial.samples_html'),
position: 'right'
}, {
element: $('#secondary-menu')[0],
intro: I18n.t('tutorial.breadcrumbs_html')
}];
initPageTutorialSteps(17, 18, nextPage, function() {}, function() {},
steps);
}
}
initTutorial();

View file

@ -26,165 +26,6 @@ $.fn.onAjaxComplete = function (cb) {
});
}
// Number of all tutorial steps
var TUTORIAL_STEPS_CNT = 26;
/**
* Initializes tutorial steps for the current page.
* NOTE: You can specify steps manually in JS with steps parameter (preferred
* way), or hardcode them in HTML
* NOTE: If some steps edit page, then this function needs to be called several
* times for the same page, but for different steps. The same goes if the page
* has discontinuous tutorial steps. In such cases, use steps branching, e.g.:
* @example
* var tutorialData = Cookies.get('tutorial_data');
* if (tutorialData) {
* tutorialData = JSON.parse(tutorialData);
* var stepNum = parseInt(Cookies.get('current_tutorial_step'), 10);
*
* if (stepNum >= 6 && stepNum <= 7) {
* ...
* } else if ...
* NOTE: If an element the popup is pointing at is of lesser horizontal length
* than the popup itself, then it will not be positioned correctly if it's
* position is top or bottom, so set/change the step's position to either left
* or right (and don't use any custom styling!), e.g.:
* @example
* var steps = [
* {
* ...
* position: 'right'
* },
* {
* ...
* ];
* NOTE: If only one page step is needed, then make pageFirstStepN ==
* pageLastStepN (both represent the one and only step number)
*
* @param {number} pageFirstStepN Page's first step number
* @param {number} pageLastStepN Page's last step number
* @param {string} nextPagePath Next page absolute path
* @param {function} beforeCb Callback called before the tutorial starts. Mainly
* used for setting 'pointer-events: none' on the elements the page's steps
* highlight.
* @param {function} endCb Callback called after the tutorial ends. Mainly used
* for setting 'pointer-events: auto' on the elements the page's steps
* highlight.
* @param {object} steps JSON containing intro.js steps.
*/
function initPageTutorialSteps(pageFirstStepN, pageLastStepN, nextPagePath,
beforeCb, endCb, steps) {
var tutorialData = Cookies.get('tutorial_data');
if (tutorialData) {
tutorialData = JSON.parse(tutorialData);
var stepNum = parseInt(Cookies.get('current_tutorial_step'), 10);
if (isNaN(stepNum)) {
// Cookies data initialization
stepNum = 1;
Cookies.set('current_tutorial_step', stepNum);
tutorialData[0].backPagesPaths = [];
Cookies.set('tutorial_data', tutorialData);
}
var thisPagePath = window.location.pathname;
beforeCb();
// Initialize tutorial for the current pages' steps
var doneLabel;
if (pageLastStepN == TUTORIAL_STEPS_CNT) {
doneLabel = I18n.t('tutorial.finish_tutorial');
} else {
doneLabel = I18n.t('tutorial.skip_tutorial');
// Add extra fake step, so that next button on last step of current page
// gets focused. Also, if current page has only one step, this adds back
// and next buttons to the popup.
steps.push({});
}
introJs()
.setOptions({
overlayOpacity: '0.2',
prevLabel: I18n.t('tutorial.back'),
nextLabel: I18n.t('tutorial.next'),
skipLabel: I18n.t('tutorial.skip_tutorial'),
doneLabel: doneLabel,
showBullets: false,
showStepNumbers: false,
exitOnOverlayClick: false,
exitOnEsc: false,
disableInteraction: true,
keyboardNavigation: false,
tooltipClass: 'custom next-page-link',
steps: steps
})
.goToStep(stepNum - (pageFirstStepN - 1))
.onexit(function() {
Cookies.remove('tutorial_data');
Cookies.remove('current_tutorial_step');
location.reload();
})
.oncomplete(function() {
Cookies.remove('tutorial_data');
Cookies.remove('current_tutorial_step');
location.reload();
})
.start();
// Page navigation when coming to this page from previous or from next page
$(function() {
if (stepNum === pageFirstStepN && stepNum > 1) {
$('.introjs-prevbutton').removeClass('introjs-disabled');
} else if (stepNum === pageLastStepN && stepNum < TUTORIAL_STEPS_CNT) {
$('.introjs-nextbutton').removeClass('introjs-disabled');
}
});
// Page navigation when already on this page
$('.introjs-skipbutton').click(function() {
Cookies.remove('current_tutorial_step');
Cookies.remove('tutorial_data');
endCb();
});
$('.introjs-prevbutton').click(function() {
if (stepNum > 1) {
Cookies.set('current_tutorial_step', --stepNum);
if (stepNum === pageFirstStepN && stepNum > 1) {
$('.introjs-prevbutton').removeClass('introjs-disabled');
} else if (stepNum < pageFirstStepN) {
// Go to previous page;
var prevPagePath = tutorialData[0].backPagesPaths.pop();
Cookies.set('tutorial_data', tutorialData);
$('.introjs-prevbutton').attr('href', prevPagePath);
introJs().exit();
endCb();
}
}
});
$('.introjs-nextbutton').click(function() {
if (stepNum < TUTORIAL_STEPS_CNT) {
Cookies.set('current_tutorial_step', ++stepNum);
if (stepNum === pageLastStepN && stepNum < TUTORIAL_STEPS_CNT) {
$('.introjs-nextbutton').removeClass('introjs-disabled');
} else if (stepNum > pageLastStepN) {
// Go to next page
tutorialData[0].backPagesPaths.push(thisPagePath);
Cookies.set('tutorial_data', tutorialData);
$('.introjs-nextbutton').attr('href', nextPagePath);
introJs().exit();
endCb();
}
}
});
}
}
/**
* Checkbox on/off logic. For each checkbox hierarchy add 'checkbox-tree' class
* to a parent 'div' surrounding the checkbox hierarchy, represented with 'ul',

View file

@ -64,35 +64,9 @@
$(this).renderFormErrors("user", data.responseJSON);
});
var repeatTutorialModal = $("#repeat-tutorial-modal");
var repeatTutorialModalBody = repeatTutorialModal.find(".modal-body");
initRepeatTutorialModal();
notificationsSettings();
initNotificationSettingsForm();
$("#reset-tutorial-btn")
.on("ajax:before", function () {
repeatTutorialModal.modal('show');
})
.on("ajax:success", function (e, data) {
initRepeatTutorialModalBody(data);
});
function initRepeatTutorialModal() {
// Remove modal content when modal window is closed.
repeatTutorialModal.on("hidden.bs.modal", function () {
repeatTutorialModalBody.html("");
});
}
// Initialize ajax listeners and elements style on modal body. This
// function must be called when modal body is changed.
function initRepeatTutorialModalBody(data) {
repeatTutorialModalBody.html(data.html);
repeatTutorialModalBody.find(".selectpicker").selectpicker();
}
// Setup notification checkbox buttons
function notificationsSettings() {
var notification_settings = [ "recent_notification",

View file

@ -6,7 +6,6 @@
*= require rails_bootstrap_forms
*= require bootstrap-select
*= require constants
*= require introjs
*= stub reports_pdf
*/
@import "bootstrap-sprockets";

View file

@ -1120,40 +1120,6 @@ table.dataTable {
transform: translate3d(0%, 0, 0);
}
/* Custom settings for intro-js */
.introjs-tooltip {
opacity: 1 !important;
}
.custom .introjs-button {
font-weight: bold;
text-transform: uppercase;
}
.custom .introjs-disabled {
display: none;
}
.custom .introjs-skipbutton {
border-radius: 0;
color: $color-theme-primary;
background-color: $color-white;
background-image: none;
border: none;
}
.disabled-next .introjs-nextbutton {
display: none;
}
.introjs-tooltipReferenceLayer {
z-index: $infinity !important;
&.max {
z-index: calc($infinity + 1) !important;
}
}
.modal-tooltip {
border-bottom: 1px dotted $color-alto;
cursor: help;

View file

@ -7,7 +7,6 @@ class ApplicationController < ActionController::Base
protect_from_forgery with: :exception, prepend: true
before_action :authenticate_user!
helper_method :current_team
before_action :generate_intro_tutorial, if: :is_current_page_root?
before_action :update_current_team, if: :user_signed_in?
around_action :set_time_zone, if: :current_user
layout 'main'
@ -66,19 +65,6 @@ class ApplicationController < ActionController::Base
private
def generate_intro_tutorial
if Rails.configuration.x.enable_tutorial &&
current_user.no_tutorial_done? &&
current_user.teams.where(created_by: current_user).count > 0 then
demo_cookie = seed_demo_data current_user
cookies[:tutorial_data] = {
value: demo_cookie,
expires: 1.week.from_now
}
current_user.update(tutorial_status: 1)
end
end
def update_current_team
if current_user.current_team_id.blank? &&
current_user.teams.count > 0

View file

@ -4,6 +4,7 @@ class ProjectsController < ApplicationController
include TeamsHelper
include InputSanitizeHelper
before_action :generate_intro_demo, only: :index
before_action :load_vars, only: [:show, :edit, :update,
:notifications, :reports,
:samples, :experiment_archive,
@ -306,6 +307,12 @@ class ProjectsController < ApplicationController
private
def generate_intro_demo
return unless current_user.sign_in_count == 1
team = current_user.teams.where(created_by: current_user).first
seed_demo_data(current_user) if team && team.projects.blank?
end
def project_params
params.require(:project).permit(:name, :team_id, :visibility, :archived)
end

View file

@ -5,8 +5,6 @@ module Users
before_action :load_user, only: [
:index,
:update,
:tutorial,
:reset_tutorial,
:notifications_settings
]
@ -31,51 +29,6 @@ module Users
end
end
def tutorial
@teams =
@user
.user_teams
.includes(team: :users)
.where(role: 1..2)
.order(created_at: :asc)
.map(&:team)
@member_of = @teams.count
respond_to do |format|
format.json do
render json: {
status: :ok,
html: render_to_string(
partial: 'users/settings/account/preferences/' \
'repeat_tutorial_modal_body.html.erb'
)
}
end
end
end
def reset_tutorial
if @user.update(tutorial_status: 0) && params[:team][:id].present?
@user.update(current_team_id: params[:team][:id])
cookies.delete :tutorial_data
cookies.delete :current_tutorial_step
cookies[:repeat_tutorial_team_id] = {
value: params[:team][:id],
expires: 1.day.from_now
}
flash[:notice] = t(
'users.settings.account.preferences.tutorial.tutorial_reset_flash'
)
redirect_to root_path
else
flash[:alert] = t(
'users.settings.account.preferences.tutorial.tutorial_reset_error'
)
redirect_back(fallback_location: root_path)
end
end
def notifications_settings
@user.assignments_notification =
params[:assignments_notification] ? true : false

View file

@ -16,11 +16,6 @@ class User < ApplicationRecord
},
default_url: Constants::DEFAULT_AVATAR_URL
enum tutorial_status: {
no_tutorial_done: 0,
intro_tutorial_done: 1
}
auto_strip_attributes :full_name, :initials, nullify: false
validates :full_name,
presence: true,

View file

@ -1,9 +1,9 @@
module DelayedUploaderTutorial
# Get asset from tutorial_files folder
module DelayedUploaderDemo
# Get asset from demo_files folder
def self.get_asset(user, team, file_name)
Asset.new(
file: File.open(
"#{Rails.root}/app/assets/tutorial_files/#{file_name}", 'r'
"#{Rails.root}/app/assets/demo_files/#{file_name}", 'r'
),
created_by: user,
team: team,
@ -12,7 +12,7 @@ module DelayedUploaderTutorial
end
# Generates results asset for given module, file_name assumes file is located
# in tutorial_files.
# in demo_files.
def self.generate_result_asset(
my_module:,
current_user:,
@ -53,7 +53,7 @@ module DelayedUploaderTutorial
# Adds asset to existing step
def self.add_step_asset(step:, current_user:, current_team:, file_name:)
temp_asset =
DelayedUploaderTutorial.get_asset(current_user, current_team, file_name)
DelayedUploaderDemo.get_asset(current_user, current_team, file_name)
step.assets << temp_asset
temp_asset.post_process_file(step.my_module.experiment.project.team)
end

View file

@ -1,24 +1,11 @@
module FirstTimeDataGenerator
# Create data for tutorial for new users
# Create data for demo for new users
def seed_demo_data(user)
@user = user
# First team that this user created
# should contain the "intro" project
if cookies[:repeat_tutorial_org_id] || cookies[:repeat_tutorial_team_id]
team = Team.find_by_id(cookies[:repeat_tutorial_org_id])
team ||= Team.find_by_id(cookies[:repeat_tutorial_team_id])
%w(repeat_tutorial_team_id repeat_tutorial_org_id)
.each do |repeat_tutorial|
cookies.delete repeat_tutorial.to_sym if cookies[repeat_tutorial.to_sym]
end
else
team = user
.teams
.where(created_by: user)
.order(created_at: :asc)
.first
end
team = user.teams.where(created_by: user).order(created_at: :asc).first
# If private private team does not exist,
# there was something wrong with user creation.
@ -499,7 +486,7 @@ module FirstTimeDataGenerator
# Load table contents yaml file
tab_content = YAML.load_file(
"#{Rails.root}/app/assets/tutorial_files/tables_content.yaml"
"#{Rails.root}/app/assets/demo_files/tables_content.yaml"
)
# Create module content
@ -516,7 +503,7 @@ module FirstTimeDataGenerator
module_step_descriptions)
# Results
DelayedUploaderTutorial.delay(queue: :tutorial).generate_result_asset(
DelayedUploaderDemo.delay(queue: :demo).generate_result_asset(
my_module: my_modules[0],
current_user: user,
current_team: team,
@ -563,7 +550,7 @@ module FirstTimeDataGenerator
module_step_descriptions)
# Add file to existig step
DelayedUploaderTutorial.delay(queue: :tutorial).add_step_asset(
DelayedUploaderDemo.delay(queue: :demo).add_step_asset(
step: my_modules[1].protocol.steps.where('position = 0').take,
current_user: user,
current_team: team,
@ -571,7 +558,7 @@ module FirstTimeDataGenerator
)
# Results
DelayedUploaderTutorial.delay(queue: :tutorial).generate_result_asset(
DelayedUploaderDemo.delay(queue: :demo).generate_result_asset(
my_module: my_modules[1],
current_user: user,
current_team: team,
@ -580,7 +567,7 @@ module FirstTimeDataGenerator
file_name: 'DSCN0660.JPG'
)
DelayedUploaderTutorial.delay(queue: :tutorial).generate_result_asset(
DelayedUploaderDemo.delay(queue: :demo).generate_result_asset(
my_module: my_modules[1],
current_user: user,
current_team: team,
@ -589,7 +576,7 @@ module FirstTimeDataGenerator
file_name: 'DSCN0354.JPG'
)
DelayedUploaderTutorial.delay(queue: :tutorial).generate_result_asset(
DelayedUploaderDemo.delay(queue: :demo).generate_result_asset(
my_module: my_modules[1],
current_user: user,
current_team: team,
@ -642,7 +629,7 @@ module FirstTimeDataGenerator
generate_module_steps(my_modules[2], module_step_names, module_step_descriptions)
# Add file to existig step
DelayedUploaderTutorial.delay(queue: :tutorial).add_step_asset(
DelayedUploaderDemo.delay(queue: :demo).add_step_asset(
step: my_modules[2].protocol.steps.where('position = 1').take,
current_user: user,
current_team: team,
@ -685,7 +672,7 @@ module FirstTimeDataGenerator
).sneaky_save
# Second result
DelayedUploaderTutorial.delay(queue: :tutorial).generate_result_asset(
DelayedUploaderDemo.delay(queue: :demo).generate_result_asset(
my_module: my_modules[2],
current_user: user,
current_team: team,
@ -704,7 +691,7 @@ module FirstTimeDataGenerator
generate_module_steps(my_modules[3], module_step_names, module_step_descriptions)
# Add file to existig step
DelayedUploaderTutorial.delay(queue: :tutorial).add_step_asset(
DelayedUploaderDemo.delay(queue: :demo).add_step_asset(
step: my_modules[3].protocol.steps.where('position = 0').take,
current_user: user,
current_team: team,
@ -712,7 +699,7 @@ module FirstTimeDataGenerator
)
# Results
DelayedUploaderTutorial.delay(queue: :tutorial).generate_result_asset(
DelayedUploaderDemo.delay(queue: :demo).generate_result_asset(
my_module: my_modules[3],
current_user: user,
current_team: team,
@ -778,28 +765,28 @@ module FirstTimeDataGenerator
module_step_descriptions)
# Add file to existig steps
DelayedUploaderTutorial.delay(queue: :tutorial).add_step_asset(
DelayedUploaderDemo.delay(queue: :demo).add_step_asset(
step: my_modules[5].protocol.steps.where('position = 0').take,
current_user: user,
current_team: team,
file_name: 'sample_preparation.JPG'
)
DelayedUploaderTutorial.delay(queue: :tutorial).add_step_asset(
DelayedUploaderDemo.delay(queue: :demo).add_step_asset(
step: my_modules[5].protocol.steps.where('position = 1').take,
current_user: user,
current_team: team,
file_name: 'reaction_setup.JPG'
)
DelayedUploaderTutorial.delay(queue: :tutorial).add_step_asset(
DelayedUploaderDemo.delay(queue: :demo).add_step_asset(
step: my_modules[5].protocol.steps.where('position = 2').take,
current_user: user,
current_team: team,
file_name: 'cycling_conditions.JPG'
)
DelayedUploaderTutorial.delay(queue: :tutorial).add_step_asset(
DelayedUploaderDemo.delay(queue: :demo).add_step_asset(
step: my_modules[5].protocol.steps.where('position = 3').take,
current_user: user,
current_team: team,
@ -842,7 +829,7 @@ module FirstTimeDataGenerator
).sneaky_save
# Results
DelayedUploaderTutorial.delay(queue: :tutorial).generate_result_asset(
DelayedUploaderDemo.delay(queue: :demo).generate_result_asset(
my_module: my_modules[5],
current_user: user,
current_team: team,
@ -851,7 +838,7 @@ module FirstTimeDataGenerator
file_name: 'Mixes_Templats.xls'
)
DelayedUploaderTutorial.delay(queue: :tutorial).generate_result_asset(
DelayedUploaderDemo.delay(queue: :demo).generate_result_asset(
my_module: my_modules[5],
current_user: user,
current_team: team,
@ -860,7 +847,7 @@ module FirstTimeDataGenerator
file_name: 'BootCamp-Experiment-results-20122.sds'
)
DelayedUploaderTutorial.delay(queue: :tutorial).generate_result_asset(
DelayedUploaderDemo.delay(queue: :demo).generate_result_asset(
my_module: my_modules[5],
current_user: user,
current_team: team,
@ -907,7 +894,7 @@ module FirstTimeDataGenerator
module_step_descriptions)
# Add file to existig step
DelayedUploaderTutorial.delay(queue: :tutorial).add_step_asset(
DelayedUploaderDemo.delay(queue: :demo).add_step_asset(
step: my_modules[7].protocol.steps.where('position = 0').take,
current_user: user,
current_team: team,
@ -915,7 +902,7 @@ module FirstTimeDataGenerator
)
# Add result
DelayedUploaderTutorial.delay(queue: :tutorial).generate_result_asset(
DelayedUploaderDemo.delay(queue: :demo).generate_result_asset(
my_module: my_modules[7],
current_user: user,
current_team: team,
@ -924,7 +911,7 @@ module FirstTimeDataGenerator
file_name: 'ddCq-quantification_diagnostics-results.xls'
)
DelayedUploaderTutorial.delay(queue: :tutorial).generate_result_asset(
DelayedUploaderDemo.delay(queue: :demo).generate_result_asset(
my_module: my_modules[7],
current_user: user,
current_team: team,
@ -933,7 +920,7 @@ module FirstTimeDataGenerator
file_name: 'dilution_curve-efficiency.JPG'
)
DelayedUploaderTutorial.delay(queue: :tutorial).generate_result_asset(
DelayedUploaderDemo.delay(queue: :demo).generate_result_asset(
my_module: my_modules[7],
current_user: user,
current_team: team,
@ -973,12 +960,6 @@ module FirstTimeDataGenerator
# create thumbnail
experiment.delay.generate_workflow_img
# Lastly, create cookie with according ids
# so tutorial steps can be properly positioned
JSON.generate([team: team.id,
project: project.id,
qpcr_module: my_modules[5].id])
end
# WARNING: This only works on PostgreSQL

View file

@ -18,10 +18,6 @@
<%= render partial: "protocols/steps.html.erb" %>
</div>
<!-- Tutorial data -->
<div class="hidden" data-role="tutorial-data" data-module-id="<%= @my_module.id %>">
</div>
<!-- URL for status bar refreshing -->
<div class="hidden" data-role="protocol-status-bar-url" data-url="<%= protocol_status_bar_protocol_path(@protocol) %>"></div>

View file

@ -1,21 +0,0 @@
<% if @member_of == 0 %>
<div class="row">
<span class="col-xs-12"><em><%=t 'users.settings.account.preferences.tutorial.no_teams' %></em></span>
</div>
<% else %>
<div class="row">
<span class="col-xs-12"><%=t 'users.settings.account.preferences.tutorial.select_team_instruction' %></span>
</div>
<hr>
<div class="row">
<%= bootstrap_form_tag url: reset_tutorial_path, method: :post do |f| %>
<div class="col-xs-12 col-sm-4">
<%= collection_select(:team, :id, @teams, :id, :name, {}, { class: 'selectpicker' }) %>
</div>
<div class="visible-xs">&nbsp;</div>
<div class="col-xs-4 col-sm-2">
<%= f.button t('users.settings.account.preferences.tutorial.repeat_tutorial'), class: "btn btn-primary" %>
</div>
<% end %>
</div>
<% end %>

View file

@ -51,15 +51,6 @@
</div>
</div>
<% end %>
<% if Rails.configuration.x.enable_tutorial %>
<hr>
<strong><%= t('tutorial.title') %></strong> <br>
<%= link_to t('users.settings.account.preferences.tutorial.repeat_tutorial'),
tutorial_path(format: :json),
remote: true,
class: 'btn btn-primary',
id: 'reset-tutorial-btn' %>
<% end %>
<hr>
<div class="notification-settings-container">
<h4><%= t('notifications.title') %></h4>
@ -150,22 +141,4 @@
<div class="tab-pane tab-pane-settings" role="tabpanel"></div>
</div>
<!-- Repeat tutorial modal -->
<div class="modal" id="repeat-tutorial-modal" tabindex="-1" role="dialog" aria-labelledby="repeat-tutorial-modal-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">&times;</span></button>
<h4 class="modal-title" ><%= t("users.settings.account.preferences.tutorial.modal_title") %></h4>
</div>
<div class="modal-body"></div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal"><%= t("general.cancel")%></button>
</div>
</div>
</div>
</div>
<%= javascript_include_tag "users/settings/account/preferences/index" %>

View file

@ -87,10 +87,6 @@ Rails.application.configure do
# Enable/disable Deface
config.deface.enabled = ENV['DEFACE_ENABLED'] != 'false'
# Enable first-time tutorial for users signing in the sciNote for
# the first time.
config.x.enable_tutorial = ENV['ENABLE_TUTORIAL'] == 'true'
# Enable reCAPTCHA
config.x.enable_recaptcha = ENV['ENABLE_RECAPTCHA'] == 'true'

View file

@ -101,10 +101,6 @@ Rails.application.configure do
# Enable/disable Deface
config.deface.enabled = ENV['DEFACE_ENABLED'] != 'false'
# Enable first-time tutorial for users signing in the sciNote for
# the first time.
config.x.enable_tutorial = ENV['ENABLE_TUTORIAL'] != 'false'
# Enable reCAPTCHA
config.x.enable_recaptcha = ENV['ENABLE_RECAPTCHA'] == 'true'

View file

@ -84,10 +84,6 @@ Rails.application.configure do
# Enable/disable Deface
config.deface.enabled = ENV['DEFACE_ENABLED'] != 'false'
# Enable first-time tutorial for users signing in the sciNote for
# the first time.
config.x.enable_tutorial = false
# Enable reCAPTCHA
config.x.enable_recaptcha = false

View file

@ -1322,14 +1322,6 @@ en:
time_zone_sublabel: "Time zone setting affects all time & date fields throughout application."
time_zone_title: "Time zone"
update_flash: "Preferences successfully updated."
tutorial:
modal_title: "Repeat tutorial"
no_teams: "Seems like you are not a member of any team. Tutorials can be run only by team members."
repeat_tutorial: "Repeat tutorial"
select_team_instruction: "Select the team where you wish to create the demo project."
select_team: "Select team"
tutorial_reset_flash: "Tutorial can now be repeated."
tutorial_reset_error: "Tutorial could not be repeated."
addons:
head_title: "Settings | Add-ons"
title: "Add-ons"
@ -1722,39 +1714,6 @@ en:
time: "%H:%M"
short: "%H"
tutorial:
title: "Tutorial"
back: "Back"
next: "Next"
skip_tutorial: "Skip tutorial"
finish_tutorial: "Start using sciNote"
tutorial_welcome_title_html: "Welcome to <em>sciNote</em>, your electronic lab notebook. <em>sciNote</em> organizes your work in Projects. Click <strong>Team icon</strong> <span class='fa fa-users'></span> to choose Projects from which Team you want to view on your Dashboard. You can also reorder them by clicking the <strong>Sort by</strong> button. <strong>(Step 1/26)</strong>"
create_project_html: "Click here to create a Project and it will appear under the Team you've chosen. Choose public <span class='glyphicon glyphicon-eye-open'></span> if you want everyone from the Team to view the Project or choose private <span class='glyphicon glyphicon-eye-close'></span> so only the people who you invite to the Project can see it. <strong>(Step 2/26)</strong>"
project_options_html: "In the bottom row of the Project card you can check the latest activity <span class='glyphicon glyphicon-equalizer'></span>, invite collaborators <span class='glyphicon glyphicon-user'></span>, see the notifications <span class='glyphicon glyphicon-bell'></span> and write comments <span class='glyphicon glyphicon-comment'></span>. You can also edit the Project's name and visibility or archive it. You can recall the Project from the Archive <span class='glyphicon glyphicon-briefcase'></span> in the top right side of the Dashboard at any time. <strong>(Step 3/26)</strong>"
create_experiment_html: "Inside of a Project you can create Experiments. To create one click on this button and edit Experiments name and description. <strong>(Step 4/26)</strong>"
edit_experiment_html: "By clicking on the down arrow <span class='caret'></span> of an Experiment card you can choose between different actions. You can <strong>Edit details</strong> to the Experiment, such as experiment name and description, <strong>Copy</strong> it as template inside of a Project, where copied Experiment is identical to the original one, <strong>Move</strong> it from one Project to another or <strong>Archive</strong> it in the Archive <span class='glyphicon glyphicon-briefcase'></span>. <strong>(Step 5/26)</strong>"
canvas_overview_html: "A Task is a basic unit of your Experiment. Within a Task, you can add Protocols, Results or Samples. You can connect Tasks into Workflows to assure traceability of your work. You can grab a Task or entire Workflow and move it in all directions on the canvas. <strong>(Step 6/26)</strong>"
canvas_click_edit_workflow_html: " Click <strong>Edit experiment</strong> to add new Tasks or to modify an existing Experiment. <strong>(Step 7/26)</strong>"
edit_workflow_html: "To add a new Task to the Experiment, click on <strong>New task</strong> and drag it onto canvas. <strong>(Step 8/26)</strong>"
edit_workflow_click_save_html: "Click <strong>Save experiment</strong> to save changes youve made to the Experiment. <strong>(Step 9/26)</strong>"
sidebar_html: "Navigation bar helps you to navigate through Experiments. It also helps you to find a specific Task on the canvas by clicking the navigate icon <span class='glyphicon glyphicon-map-marker'></span>. <strong>(Step 10/26)</strong>"
sidebar_click_module_html: "Click on the Task name <strong>qPCR</strong> to see its contents. <strong>(Step 11/26)</strong>"
module_protocols_html: "Inside of a Task you can create Protocol steps and upload existing protocol files. After you have finished a certain step, click the <strong>Complete step</strong> button. Exact time and the person who completed the step are recorded and can be seen in the <strong>Activity</strong> tab in the top right side of the Dashboard. <strong>(Step 12/26)</strong>"
module_protocols_save_html: "You can save the protocol to Protocol repository. Everyone within the same Team will be able to use it. <strong>(Step 13/26)</strong>"
module_protocols_click_results_html: "Click on the <strong>Results</strong> tab to upload experiment results. <strong>(Step 14/26)</strong>"
module_results_html: "You can upload any type of a file, insert table or write comments. <strong>(Step 15/26)</strong>"
module_results_click_samples_html: "Click on the <strong>Samples</strong> tab to import, export or assign samples to the Task. <strong>(Step 16/26)</strong>"
samples_html: "You can easily import sample tables from Excel or tab-delimited files. If you assign samples to a certain Task, these samples will be automatically assigned downstream the Workflow. <strong>(Step 17/26)</strong>"
breadcrumbs_html: "You can always use these <strong>Breadcrumbs</strong> to navigate all the way back to the Dashboard. Click on the <strong>Reports</strong> tab to generate a report of your work. <strong>(Step 18/26)</strong>"
reports_index_click_new_report_html: "Click the <strong>New report</strong> button to create a new report. <strong>(Step 19/26)</strong>"
new_report_html: "To add report elements to the report, click on the <strong>—+—</strong> sign on the sheet. Select the report contents in the tabs and click <strong>Add to report</strong>. You can save the report as a PDF on your computer or save it within sciNote for later viewing and modification. <strong>(Step 20/26)</strong>"
new_report_click_team_html: "Click on <strong>%{private_team}</strong> in breadcrumbs to return to the Dashboard. <strong>(Step 21/26)</strong>"
protocols_link_html: "Click on <span class='glyphicon glyphicon-list-alt'></span> to go to the Protocols repository page. <strong>(Step 22/26)</strong>"
protocols_index_html: "View your Public and Private Protocols, which you can Edit, Create new ones or Copy them. Protocols can be archived and restored from the Archive. <strong>(Step 23/26)</strong>"
protocols_import_export_html: "You can also Import or Export protocols to your hard drive. Return to the Dashboard. <strong>(Step 24/26)</strong>"
archive_project_html: "Archive Demo project - qPCR by clicking on the down arrow <span class='glyphicon glyphicon-triangle-bottom'></span>. You can always access the Archive by clicking the <span class='glyphicon glyphicon-briefcase'></span> icon on the top right side of the Dashboard and restore any item you have archived. <strong>(Step 25/26)</strong>"
goodbye_message: "To repeat the tutorial, go to your <strong>Settings</strong> and open <strong>Preferences</strong> tab. Click on the <strong>Repeat tutorial</strong> button and go through the tutorial as many times as needed. <strong>(Step 26/26)</strong>"
notifications:
title: "Notifications"
email_settings: "E-mail notifications"

View file

@ -56,12 +56,6 @@ Rails.application.routes.draw do
put 'users/settings/account/preferences',
to: 'users/settings/account/preferences#update',
as: 'update_preferences'
get 'users/settings/account/preferences/tutorial',
to: 'users/settings/account/preferences#tutorial',
as: 'tutorial'
post 'users/settings/account/preferences/reset_tutorial/',
to: 'users/settings/account/preferences#reset_tutorial',
as: 'reset_tutorial'
post 'users/settings/account/preferences/notifications_settings',
to: 'users/settings/account/preferences#notifications_settings',
as: 'notifications_settings',

View file

@ -0,0 +1,5 @@
class RemoveTutorialStatusFromUser < ActiveRecord::Migration[5.1]
def change
remove_column :users, :tutorial_status, :integer, default: 0, null: false
end
end

View file

@ -36,7 +36,6 @@ describe User, type: :model do
it { should have_db_column :invited_by_id }
it { should have_db_column :invited_by_type }
it { should have_db_column :invitations_count }
it { should have_db_column :tutorial_status }
it { should have_db_column :settings }
it { should have_db_column :current_team_id }
it { should have_db_column :authentication_token }