Merge branch 'ux-release-1'
10
.travis.yml
|
@ -1,8 +1,16 @@
|
|||
env:
|
||||
- DOCKER_COMPOSE_VERSION=1.13.0
|
||||
|
||||
sudo: required
|
||||
language: ruby
|
||||
install: true
|
||||
services:
|
||||
- docker
|
||||
before_script:
|
||||
before_install:
|
||||
- sudo rm /usr/local/bin/docker-compose
|
||||
- curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` > docker-compose
|
||||
- chmod +x docker-compose
|
||||
- sudo mv docker-compose /usr/local/bin
|
||||
- make docker
|
||||
script:
|
||||
- make tests-ci
|
||||
|
|
8
Gemfile
|
@ -9,11 +9,10 @@ gem 'pg', '~> 0.18'
|
|||
gem 'devise', '~> 4.3.0'
|
||||
gem 'devise_invitable'
|
||||
gem 'simple_token_authentication', '~> 1.15.1' # Token authentication for Devise
|
||||
gem 'bootstrap-sass', '~> 3.3.5'
|
||||
gem 'bootstrap-sass', '~> 3.3.7'
|
||||
gem 'sass-rails', '~> 5.0.6'
|
||||
gem 'bootstrap_form'
|
||||
gem 'yomu'
|
||||
gem 'font-awesome-rails', '~> 4.7.0.2'
|
||||
gem 'recaptcha', require: 'recaptcha/rails'
|
||||
gem 'sanitize', '~> 4.4'
|
||||
gem 'omniauth'
|
||||
|
@ -27,7 +26,7 @@ gem 'momentjs-rails', '~> 2.17.1'
|
|||
# JS datetime picker
|
||||
gem 'bootstrap3-datetimepicker-rails', '~> 4.15.35'
|
||||
# Select elements for Bootstrap
|
||||
gem 'bootstrap-select-rails', '~> 1.6.3'
|
||||
gem 'bootstrap-select-rails', '~> 1.12.4'
|
||||
gem 'uglifier', '>= 1.3.0'
|
||||
# jQuery & plugins
|
||||
gem 'jquery-turbolinks'
|
||||
|
@ -36,7 +35,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
|
||||
|
@ -79,6 +77,8 @@ gem 'devise-async',
|
|||
git: 'https://github.com/mhfs/devise-async.git',
|
||||
branch: 'devise-4.x'
|
||||
|
||||
gem 'discard', '~> 1.0'
|
||||
|
||||
gem 'ruby-graphviz', '~> 1.2' # Graphviz for rails
|
||||
gem 'tinymce-rails', '~> 4.6.4' # Rich text editor
|
||||
|
||||
|
|
31
Gemfile.lock
|
@ -1,10 +1,11 @@
|
|||
GIT
|
||||
remote: https://github.com/biosistemika/canaid
|
||||
revision: f2000c19b75e66ea929a44cb0575262b7f5fc13e
|
||||
revision: 943ae9b9801819fd2513f6ab9e1143ad8de523ce
|
||||
branch: master
|
||||
specs:
|
||||
canaid (1.0.1)
|
||||
canaid (1.0.2)
|
||||
devise (>= 3.4.1)
|
||||
docile (>= 1.1.0)
|
||||
rails (>= 4)
|
||||
|
||||
GIT
|
||||
|
@ -82,7 +83,7 @@ GEM
|
|||
activemodel (= 5.1.1)
|
||||
activesupport (= 5.1.1)
|
||||
arel (~> 8.0)
|
||||
activerecord-import (0.22.0)
|
||||
activerecord-import (0.23.0)
|
||||
activerecord (>= 3.2)
|
||||
activesupport (5.1.1)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
|
@ -127,7 +128,7 @@ GEM
|
|||
bootstrap-sass (3.3.7)
|
||||
autoprefixer-rails (>= 5.2.1)
|
||||
sass (>= 3.3.4)
|
||||
bootstrap-select-rails (1.6.3)
|
||||
bootstrap-select-rails (1.12.4)
|
||||
bootstrap3-datetimepicker-rails (4.15.35)
|
||||
momentjs-rails (>= 2.8.1)
|
||||
bootstrap_form (2.7.0)
|
||||
|
@ -136,7 +137,7 @@ GEM
|
|||
activesupport (>= 3.0.0)
|
||||
uniform_notifier (~> 1.11.0)
|
||||
byebug (9.1.0)
|
||||
capybara (2.17.0)
|
||||
capybara (2.18.0)
|
||||
addressable
|
||||
mini_mime (>= 0.1.3)
|
||||
nokogiri (>= 1.3.3)
|
||||
|
@ -203,6 +204,8 @@ GEM
|
|||
actionmailer (>= 4.1.0)
|
||||
devise (>= 4.0.0)
|
||||
diff-lcs (1.3)
|
||||
discard (1.0.0)
|
||||
activerecord (>= 4.2, < 6)
|
||||
docile (1.1.5)
|
||||
erubi (1.7.0)
|
||||
execjs (2.7.0)
|
||||
|
@ -218,8 +221,6 @@ GEM
|
|||
ffi (1.9.18)
|
||||
figaro (1.1.1)
|
||||
thor (~> 0.14)
|
||||
font-awesome-rails (4.7.0.3)
|
||||
railties (>= 3.2, < 5.2)
|
||||
gherkin (5.0.0)
|
||||
globalid (0.4.1)
|
||||
activesupport (>= 4.2.0)
|
||||
|
@ -229,9 +230,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)
|
||||
|
@ -297,7 +295,7 @@ GEM
|
|||
rails (>= 3.2.0)
|
||||
newrelic_rpm (4.7.1.340)
|
||||
nio4r (2.2.0)
|
||||
nokogiri (1.8.1)
|
||||
nokogiri (1.8.2)
|
||||
mini_portile2 (~> 2.3.0)
|
||||
nokogumbo (1.4.13)
|
||||
nokogiri
|
||||
|
@ -343,9 +341,9 @@ GEM
|
|||
pry (~> 0.10)
|
||||
pry-rails (0.3.6)
|
||||
pry (>= 0.10.4)
|
||||
public_suffix (3.0.1)
|
||||
public_suffix (3.0.2)
|
||||
puma (3.11.2)
|
||||
rack (2.0.3)
|
||||
rack (2.0.4)
|
||||
rack-test (0.6.3)
|
||||
rack (>= 1.0)
|
||||
rails (5.1.1)
|
||||
|
@ -532,8 +530,8 @@ DEPENDENCIES
|
|||
bcrypt (~> 3.1.10)
|
||||
better_errors
|
||||
binding_of_caller
|
||||
bootstrap-sass (~> 3.3.5)
|
||||
bootstrap-select-rails (~> 1.6.3)
|
||||
bootstrap-sass (~> 3.3.7)
|
||||
bootstrap-select-rails (~> 1.12.4)
|
||||
bootstrap3-datetimepicker-rails (~> 4.15.35)
|
||||
bootstrap_form
|
||||
bullet
|
||||
|
@ -551,13 +549,12 @@ DEPENDENCIES
|
|||
devise-async!
|
||||
devise_invitable
|
||||
devise_security_extension!
|
||||
discard (~> 1.0)
|
||||
factory_bot_rails
|
||||
faker
|
||||
figaro
|
||||
font-awesome-rails (~> 4.7.0.2)
|
||||
hammerjs-rails
|
||||
i18n-js (~> 3.0)
|
||||
introjs-rails
|
||||
jbuilder
|
||||
jquery-rails
|
||||
jquery-scrollto-rails!
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
Copyright (c) 2016 BioSistemika USA, LLC <info@biosistemika.com>
|
||||
|
||||
sciNote is licensed under the following license:
|
||||
SciNote is licensed under the following license:
|
||||
|
||||
Mozilla Public License Version 2.0
|
||||
==================================
|
||||
|
|
6
Makefile
|
@ -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,10 @@ 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 --rm web bash -c "bundle install && npm install"
|
||||
@docker-compose up -d webpack
|
||||
@docker-compose ps
|
||||
@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 "rake db:create db:migrate && rake db:migrate RAILS_ENV=test && npm install && bundle exec rspec && bundle exec cucumber"
|
||||
|
||||
console:
|
||||
@$(MAKE) rails cmd="rails console"
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
# sciNote
|
||||
# SciNote
|
||||
|
||||
![sciNote logo](http://scinote.net/wp-content/uploads/2015/10/logo_sciNote_final.png)
|
||||
![SciNote logo](http://scinote.net/wp-content/uploads/2015/10/logo_sciNote_final.png)
|
||||
|
||||
## About
|
||||
|
||||
[sciNote is an open source electronic lab notebook](https://scinote.net) ([ELN](https://en.wikipedia.org/wiki/Electronic_lab_notebook)) that helps you manage your laboratory work and stores all your experimental data in one place. sciNote is specifically designed for life science students, researchers, lab technicians and group leaders.
|
||||
[SciNote is an open source electronic lab notebook](https://scinote.net) ([ELN](https://en.wikipedia.org/wiki/Electronic_lab_notebook)) that helps you manage your laboratory work and stores all your experimental data in one place. SciNote is specifically designed for life science students, researchers, lab technicians and group leaders.
|
||||
|
||||
## Build & run
|
||||
|
||||
|
@ -20,6 +20,6 @@ See [Wiki/Contributing & Collaboration](https://github.com/biosistemika/scinote-
|
|||
|
||||
## License
|
||||
|
||||
sciNote is developed and maintained by BioSistemika USA, LLC, under [Mozilla Public License Version 2.0](LICENSE.txt).
|
||||
SciNote is developed and maintained by BioSistemika USA, LLC, under [Mozilla Public License Version 2.0](LICENSE.txt).
|
||||
|
||||
See [LICENSE-3RD-PARTY.txt](LICENSE-3RD-PARTY.txt) for licenses of included third-party libraries.
|
||||
|
|
Before Width: | Height: | Size: 531 KiB After Width: | Height: | Size: 531 KiB |
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 41 KiB |
Before Width: | Height: | Size: 530 KiB After Width: | Height: | Size: 530 KiB |
Before Width: | Height: | Size: 474 KiB After Width: | Height: | Size: 474 KiB |
Before Width: | Height: | Size: 183 KiB After Width: | Height: | Size: 183 KiB |
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 73 KiB |
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 80 KiB |
|
@ -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]]}'
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 991 B |
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 3.5 KiB |
19
app/assets/javascripts/activities/index.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
'use strict';
|
||||
|
||||
(function() {
|
||||
function initActivitiesButton() {
|
||||
$(document).ready(function() {
|
||||
$(document).find('.btn-more-activities')
|
||||
.on('ajax:success', function(e, data) {
|
||||
$(data.html).insertAfter($('#list-activities li').last());
|
||||
if(data.more_url) {
|
||||
$(this).attr('href', data.more_url);
|
||||
} else {
|
||||
$(this).remove();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
initActivitiesButton();
|
||||
|
||||
})();
|
|
@ -11,10 +11,10 @@
|
|||
//= require jquery-ui/widgets/draggable
|
||||
//= require jquery-ui/widgets/droppable
|
||||
//= require jquery.ui.touch-punch.min
|
||||
//= require jquery-ui/effects/effect-slide
|
||||
//= require jquery.caret.min
|
||||
//= require jquery.atwho.min
|
||||
//= require hammer
|
||||
//= require introjs
|
||||
//= require js.cookie
|
||||
//= require spin
|
||||
//= require jquery.spin
|
||||
|
@ -30,11 +30,11 @@
|
|||
//= require tinymce-jquery
|
||||
//= require jsPlumb-2.0.4-min
|
||||
//= require jsnetworkx
|
||||
//= require bootstrap-select
|
||||
//= require_directory ./sitewide
|
||||
//= require jquery.dataTables.yadcf
|
||||
//= require datatables
|
||||
//= require dataTables.noSearchHidden
|
||||
//= require bootstrap-select
|
||||
//= require ajax-bootstrap-select.min
|
||||
//= require underscore
|
||||
//= require i18n.js
|
||||
//= require i18n/translations
|
||||
|
@ -197,17 +197,20 @@ var HelperModule = (function(){
|
|||
window.setTimeout(function () {
|
||||
flash.fadeTo(500, 0).slideUp(500, function () {
|
||||
$(this).remove();
|
||||
if($('.alert').length <= 0) {
|
||||
$('#content-wrapper').removeClass('alert-shown');
|
||||
}
|
||||
});
|
||||
}, 5000);
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
|
||||
helpers.dismissAlert = function() {
|
||||
$('#alert-flash').on('click', function() {
|
||||
$('#alert-flash').alert('close');
|
||||
})
|
||||
}
|
||||
|
||||
helpers.flashAlertMsg = function(message, type) {
|
||||
var alertType;
|
||||
var glyphSign;
|
||||
var alertType, glyphSign;
|
||||
|
||||
$('#notifications').html('');
|
||||
if (type === 'success') {
|
||||
alertType = ' alert-success ';
|
||||
|
@ -222,34 +225,38 @@ var HelperModule = (function(){
|
|||
alertType = ' alert-warning ';
|
||||
glyphSign = ' glyphicon-exclamation-sign ';
|
||||
}
|
||||
var htmlSnippet = '<div class="alert alert' + alertType +
|
||||
var htmlSnippet = '<div id="alert-flash" class="alert alert' + alertType +
|
||||
'alert-dismissable alert-floating">' +
|
||||
'<div class="container">' +
|
||||
'<button type="button" class="close" ' +
|
||||
'data-dismiss="alert" aria-label="Close">' +
|
||||
'<div>' +
|
||||
'<button type="button" class="close" ' +
|
||||
'data-dismiss="alert" aria-label="Close">' +
|
||||
'<span aria-hidden="true">×</span></button>' +
|
||||
'<span class="glyphicon' + glyphSign + '"></span>' +
|
||||
'<span class="glyphicon' + glyphSign + '"></span> ' +
|
||||
'<span>' + message + '</span>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
$('#notifications').html(htmlSnippet);
|
||||
$('#content-wrapper').addClass('alert-shown');
|
||||
helpers.hideFlashMsg();
|
||||
helpers.dismissAlert();
|
||||
}
|
||||
|
||||
$( document ).ready(function() {
|
||||
helpers.treeLinkTruncation();
|
||||
helpers.hideFlashMsg();
|
||||
helpers.dismissAlert();
|
||||
});
|
||||
|
||||
return helpers;
|
||||
})();
|
||||
|
||||
// initialize code markup in rich text fields
|
||||
(function() {
|
||||
$(document).ready(function() {
|
||||
// initialize code markup in rich text fields
|
||||
$('[class^=language]').each(function(i, block) {
|
||||
hljs.highlightBlock(block);
|
||||
});
|
||||
|
||||
// fix dropdown-menu style throughout the app
|
||||
$('.dropdown-header').parent('ul').addClass('custom-dropdown-menu');
|
||||
});
|
||||
})();
|
||||
|
|
|
@ -25,29 +25,22 @@ function setupAssetsLoading() {
|
|||
$el.next().hide();
|
||||
$el.html("");
|
||||
|
||||
if (data.type === "image") {
|
||||
if (data.type === 'image') {
|
||||
$el.html(
|
||||
"<a class='image-preview-link' id='modal_link" +
|
||||
"<a class='file-preview-link' id='modal_link" +
|
||||
data['asset-id'] + "' data-status='asset-present' " +
|
||||
"href='" + data['download-url'] + "'>" +
|
||||
"<img src='" + data['image-tag-url'] + "' data-preview-url='" +
|
||||
data['preview-url'] + "'><p>" +
|
||||
"href='" + data['download-url'] + "' data-preview-url='" +
|
||||
data['preview-url'] + "'>" +
|
||||
"<img src='" + data['image-tag-url'] + "'><p>" +
|
||||
data.filename + '</p></a>'
|
||||
);
|
||||
} else if (data.type === 'wopi') {
|
||||
if (data['wopi-edit']) {
|
||||
wopiBtns = data['wopi-file-name'] +
|
||||
data['wopi-view'] +
|
||||
data['wopi-edit'];
|
||||
} else {
|
||||
wopiBtns = data['wopi-file-name'] +
|
||||
data['wopi-view'];
|
||||
}
|
||||
$el.html(wopiBtns);
|
||||
} else {
|
||||
$el.html(
|
||||
"<a href='" + data['download-url'] + "'><p>" +
|
||||
data.filename + "</p></a>"
|
||||
"<a class='file-preview-link' id='modal_link" +
|
||||
data['asset-id'] + "' data-status='asset-present' " +
|
||||
"href='" + data['download-url'] + "' data-preview-url='" +
|
||||
data['preview-url'] + "'><p>" +
|
||||
data.filename + '</p></a>'
|
||||
);
|
||||
}
|
||||
animateSpinner(null, false);
|
||||
|
|
|
@ -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");
|
||||
|
@ -320,6 +294,9 @@ function initLoadFromRepositoryTable(content) {
|
|||
{ data: "5" },
|
||||
{ data: "6" }
|
||||
],
|
||||
oLanguage: {
|
||||
sSearch: I18n.t('general.filter')
|
||||
},
|
||||
rowCallback: function(row, data, dataIndex) {
|
||||
// Get row ID
|
||||
var rowId = data["DT_RowId"];
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -94,67 +94,9 @@
|
|||
});
|
||||
}
|
||||
|
||||
function focusSearchInput() {
|
||||
var searchIco = $('#search-ico');
|
||||
searchIco
|
||||
.on('shown.bs.dropdown', function() {
|
||||
searchIco
|
||||
.find('input.form-control')
|
||||
.focus();
|
||||
});
|
||||
}
|
||||
|
||||
function initActivitiesButton() {
|
||||
$(document.body).ready(function() {
|
||||
// Activity feed modal in main navigation menu
|
||||
var activityModal = $('#activity-modal');
|
||||
var activityModalBody = activityModal.find('.modal-body');
|
||||
var initMoreBtn = function() {
|
||||
activityModalBody.find('.btn-more-activities')
|
||||
.on('ajax:success', function(e, data) {
|
||||
$(data.html).insertBefore($(this).parents('li'));
|
||||
if(data.more_url) {
|
||||
$(this).attr('href', data.more_url);
|
||||
} else {
|
||||
$(this).remove();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
notificationAlertClose();
|
||||
|
||||
$('#main-menu .btn-activity')
|
||||
.on('ajax:before', function() {
|
||||
activityModal.modal('show');
|
||||
})
|
||||
.on('ajax:success', function(e, data) {
|
||||
activityModalBody.html(data.html);
|
||||
initMoreBtn();
|
||||
});
|
||||
|
||||
activityModal.on('hidden.bs.modal', function() {
|
||||
activityModalBody.html('');
|
||||
});
|
||||
});
|
||||
|
||||
$(document).ajaxComplete(function() {
|
||||
notificationAlertClose();
|
||||
});
|
||||
|
||||
function notificationAlertClose() {
|
||||
$('#notifications .alert').on('closed.bs.alert', function() {
|
||||
$('#content-wrapper')
|
||||
.addClass('alert-hidden')
|
||||
.removeClass('alert-shown');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// init
|
||||
loadDropdownNotifications();
|
||||
loadUnseenNotificationsNumber();
|
||||
toggleNotificationBellPosition();
|
||||
focusSearchInput();
|
||||
initGlobalSwitchForm();
|
||||
initActivitiesButton();
|
||||
})();
|
||||
|
|
|
@ -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 () {
|
||||
|
@ -174,7 +170,7 @@ function initializeEdit() {
|
|||
|
||||
// Hide sidebar & also its toggle button
|
||||
$("#wrapper").addClass("hidden2");
|
||||
$("#wrapper").find(".sidebar-header-toggle").hide();
|
||||
$("#toggle-sidebar-btn").addClass("hidden2");
|
||||
$(".navbar-secondary").addClass("navbar-without-sidebar");
|
||||
|
||||
// Also, hide zoom levels button group
|
||||
|
@ -331,7 +327,6 @@ function destroyFullZoom() {
|
|||
$(".module-large .buttons-container [role=tab]").off("ajax:before ajax:success ajax:error");
|
||||
$("div.module-large").off("mouseenter mouseleave");
|
||||
$("div.module-large a.due-date-link").off("ajax:success ajax:error");
|
||||
$("#manage-module-description-modal [data-action='submit']").off("click");
|
||||
$("#manage-module-due-date-modal [data-action='submit']").off("click");
|
||||
$("div.module-large a.edit-tags-link").off("ajax:before ajax:success");
|
||||
$("li[data-module-group]").off("mouseenter mouseleave");
|
||||
|
@ -597,46 +592,6 @@ function bindWindowResizeEvent() {
|
|||
function bindFullZoomAjaxTabs() {
|
||||
var manageUsersModal = null;
|
||||
var manageUsersModalBody = null;
|
||||
var editDescriptionModal = null;
|
||||
var editDescriptionModalBody = null;
|
||||
|
||||
// Initialize edit description modal window
|
||||
function initEditDescription($el) {
|
||||
$el.find(".description-link")
|
||||
.on("ajax:success", function(ev, data, status) {
|
||||
var descriptionLink = $(this);
|
||||
var descriptionTab = descriptionLink.closest(".tab-pane");
|
||||
|
||||
// Set modal body & title
|
||||
editDescriptionModalBody.html(data.html);
|
||||
editDescriptionModal
|
||||
.find("#manage-module-description-modal-label")
|
||||
.text(data.title);
|
||||
|
||||
editDescriptionModalBody.find("form")
|
||||
.on("ajax:success", function(ev2, data2, status2) {
|
||||
// Update module's description in the tab
|
||||
descriptionTab.find(".description-label")
|
||||
.html(data2.description_label);
|
||||
|
||||
// Close modal
|
||||
editDescriptionModal.modal("hide");
|
||||
})
|
||||
.on("ajax:error", function(ev2, data2, status2) {
|
||||
// Display errors if needed
|
||||
$(this).renderFormErrors("my_module", data2.responseJSON);
|
||||
});
|
||||
|
||||
// Disable canvas dragging events
|
||||
toggleCanvasEvents(false);
|
||||
|
||||
// Show modal
|
||||
editDescriptionModal.modal("show");
|
||||
})
|
||||
.on("ajax:error", function(ev, data, status) {
|
||||
// TODO
|
||||
});
|
||||
}
|
||||
|
||||
// Initialize users editing modal remote loading.
|
||||
function initUsersEditLink($el) {
|
||||
|
@ -680,8 +635,6 @@ function bindFullZoomAjaxTabs() {
|
|||
|
||||
manageUsersModal = $("#manage-module-users-modal");
|
||||
manageUsersModalBody = manageUsersModal.find(".modal-body");
|
||||
editDescriptionModal = $("#manage-module-description-modal");
|
||||
editDescriptionModalBody = editDescriptionModal.find(".modal-body");
|
||||
|
||||
// Reload users tab HTML element when modal is closed
|
||||
manageUsersModal.on("hide.bs.modal", function () {
|
||||
|
@ -709,21 +662,6 @@ function bindFullZoomAjaxTabs() {
|
|||
manageUsersModalBody.html("");
|
||||
});
|
||||
|
||||
// When clicking on description modal "Update" button,
|
||||
// submit its inner-lying form
|
||||
editDescriptionModal.find("[data-action='submit']").click(function() {
|
||||
editDescriptionModalBody.find("form").submit();
|
||||
});
|
||||
|
||||
// Remove description modal content when window is closed
|
||||
editDescriptionModal.on("hidden.bs.modal", function() {
|
||||
$(this).find("form").off("ajax:success ajax:error");
|
||||
editDescriptionModalBody.html("");
|
||||
|
||||
// Re-activate canvas dragging events
|
||||
toggleCanvasEvents(true);
|
||||
});
|
||||
|
||||
// initialize my_module tab remote loading
|
||||
var elements = $(".module-large .buttons-container [role=tab]");
|
||||
elements.on("ajax:before", function (e) {
|
||||
|
@ -1189,6 +1127,7 @@ function updateModuleHtml(module, id, name, gridDistX, gridDistY) {
|
|||
var dropdownMenu = document.createElement("ul");
|
||||
$(dropdownMenu)
|
||||
.addClass("dropdown-menu")
|
||||
.addClass("custom-dropdown-menu")
|
||||
.addClass("no-scale")
|
||||
.attr("aria-labelledby", id + "_options")
|
||||
.appendTo(dropdown);
|
||||
|
@ -1667,7 +1606,7 @@ function initMoveModules() {
|
|||
})
|
||||
.on("shown.bs.modal", function(event) {
|
||||
// Focus the text element
|
||||
$(this).find(".selectpicker").focus();
|
||||
$(this).find(".selectpicker").selectpicker().focus();
|
||||
})
|
||||
.on("hide.bs.modal", function (event) {
|
||||
// When hiding modal, re-enable events
|
||||
|
@ -1766,7 +1705,7 @@ function initMoveModuleGroups() {
|
|||
})
|
||||
.on("shown.bs.modal", function(event) {
|
||||
// Focus the text element
|
||||
$(this).find(".selectpicker").focus();
|
||||
$(this).find(".selectpicker").selectpicker().focus();
|
||||
})
|
||||
.on("hide.bs.modal", function (event) {
|
||||
// When hiding modal, re-enable events
|
||||
|
@ -2999,117 +2938,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';
|
||||
|
|
|
@ -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();
|
||||
}());
|
||||
|
|
|
@ -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();
|
||||
})();
|
||||
|
|
|
@ -19,7 +19,6 @@ function init() {
|
|||
initCreateNewModal();
|
||||
initModals();
|
||||
initImport();
|
||||
initTutorial();
|
||||
}
|
||||
|
||||
// Initialize protocols DataTable
|
||||
|
@ -66,6 +65,9 @@ function initProtocolsTable() {
|
|||
{ data: "5" },
|
||||
{ data: "6" }
|
||||
],
|
||||
oLanguage: {
|
||||
sSearch: I18n.t('general.filter')
|
||||
},
|
||||
rowCallback: function(row, data, dataIndex) {
|
||||
// Get row ID
|
||||
var rowId = data["DT_RowId"];
|
||||
|
@ -770,25 +772,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();
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
var task_button = $("[data-action='complete-task']");
|
||||
task_button.attr('data-action', 'uncomplete-task');
|
||||
task_button.find('.btn')
|
||||
.removeClass('btn-primary').addClass('btn-greyed');
|
||||
.removeClass('btn-toggle').addClass('btn-default');
|
||||
$('.task-due-date').html(data.module_header_due_date_label);
|
||||
$('.task-state-label').html(data.module_state_label);
|
||||
task_button
|
||||
|
@ -80,7 +80,8 @@
|
|||
|
||||
button = step.find("[data-action='complete-step']");
|
||||
button.attr("data-action", "uncomplete-step");
|
||||
button.find(".btn").removeClass("btn-primary").addClass("btn-default");
|
||||
button.find(".btn").removeClass("btn-toggle").addClass("btn-default");
|
||||
button.find("button").html('<span class="glyphicon glyphicon-remove"></span> ' + data.new_title);
|
||||
|
||||
if (data.task_ready_to_complete) {
|
||||
$('#completed-task-modal').modal('show');
|
||||
|
@ -92,10 +93,9 @@
|
|||
|
||||
button = step.find("[data-action='uncomplete-step']");
|
||||
button.attr("data-action", "complete-step");
|
||||
button.find(".btn").removeClass("btn-default").addClass("btn-primary");
|
||||
button.find(".btn").removeClass("btn-default").addClass("btn-toggle");
|
||||
button.find("button").html('<span class="glyphicon glyphicon-ok"></span> ' + data.new_title);
|
||||
}
|
||||
|
||||
button.find("button").html(data.new_title);
|
||||
},
|
||||
error: function (data) {
|
||||
console.log ("error");
|
||||
|
@ -462,7 +462,7 @@
|
|||
function enableCheckboxSorting(el) {
|
||||
Sortable.create(el, {
|
||||
draggable: 'fieldset',
|
||||
handle: '.glyphicon-chevron-right',
|
||||
handle: '.fa-circle',
|
||||
onUpdate: function () {
|
||||
reorderCheckboxData(el);
|
||||
}
|
||||
|
@ -595,6 +595,7 @@
|
|||
animateSpinner(null, false);
|
||||
setupAssetsLoading();
|
||||
DragNDropSteps.clearFiles();
|
||||
initPreviewModal();
|
||||
},
|
||||
error: function(xhr) {
|
||||
if (xhr.responseJSON['assets.file']) {
|
||||
|
|
|
@ -1,186 +0,0 @@
|
|||
(function () {
|
||||
|
||||
var newReportModal = null;
|
||||
var newReportModalBody = null;
|
||||
var newReportCreateButton = null;
|
||||
|
||||
var deleteReportsModal = null;
|
||||
var deleteReportsInput = null;
|
||||
|
||||
var newReportButton = null;
|
||||
var editReportButton = null;
|
||||
var deleteReportsButton = null;
|
||||
var checkAll = null;
|
||||
var allChecks = null;
|
||||
var allRows = null;
|
||||
|
||||
var checkedReports = [];
|
||||
|
||||
/**
|
||||
* Initializes page
|
||||
*/
|
||||
function init() {
|
||||
// Initialize selectors
|
||||
newReportModal = $('#new-report-modal');
|
||||
newReportModalBody = newReportModal.find('.modal-body');
|
||||
newReportCreateButton = $('#create-new-report-btn');
|
||||
deleteReportsModal = $('#delete-reports-modal');
|
||||
deleteReportsInput = $('#report-ids');
|
||||
newReportButton = $('#new-report-btn');
|
||||
editReportButton = $('#edit-report-btn');
|
||||
deleteReportsButton = $('#delete-reports-btn');
|
||||
checkAll = $('.check-all-reports');
|
||||
allChecks = $('.check-report');
|
||||
allRows = $('.report-row');
|
||||
|
||||
initNewReportModal();
|
||||
initCheckboxesAndEditing();
|
||||
updateButtons();
|
||||
initEditReport();
|
||||
initDeleteReports();
|
||||
initTutorial();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the new report modal.
|
||||
*/
|
||||
function initNewReportModal() {
|
||||
// TEMPORARY DISABLED
|
||||
/**
|
||||
// Remove modal content when modal window is closed.
|
||||
newReportModal.on("hidden.bs.modal", function () {
|
||||
newReportModalBody.html("");
|
||||
});
|
||||
|
||||
// Populate modal content when AJAX call is complete
|
||||
newReportButton
|
||||
.on("ajax:before", function () {
|
||||
newReportModal.modal('show');
|
||||
})
|
||||
.on("ajax:success", function (e, data) {
|
||||
newReportModalBody.html(data.html);
|
||||
});
|
||||
|
||||
// Before redirecting, pass parameters
|
||||
newReportCreateButton.click(function(event){
|
||||
var url = $(this).closest("form").attr("action");
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
// Copy the GET params
|
||||
var val = newReportModalBody.find(".btn-primary.active > input[type='radio']").attr("value");
|
||||
url += "/" + val;
|
||||
|
||||
$(location).attr("href", url);
|
||||
return false;
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize interaction between checkboxes, editing and deleting.
|
||||
*/
|
||||
function initCheckboxesAndEditing() {
|
||||
checkAll.click(function() {
|
||||
allChecks.prop("checked", this.checked);
|
||||
checkedReports = [];
|
||||
if (this.checked) {
|
||||
_.each(allRows, function(row) {
|
||||
checkedReports.push($(row).data("id"));
|
||||
});
|
||||
}
|
||||
|
||||
updateButtons();
|
||||
});
|
||||
allChecks.click(function() {
|
||||
checkAll.prop("checked", false);
|
||||
var id = $(this).closest(".report-row").data("id");
|
||||
if (this.checked) {
|
||||
if (_.indexOf(checkedReports, id) === -1) {
|
||||
checkedReports.push(id);
|
||||
}
|
||||
} else {
|
||||
var idx = _.indexOf(checkedReports, id);
|
||||
if (idx !== -1) {
|
||||
checkedReports.splice(idx, 1);
|
||||
}
|
||||
}
|
||||
|
||||
updateButtons();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update edit & delete buttons depending on checking of reports.
|
||||
*/
|
||||
function updateButtons() {
|
||||
if (checkedReports.length === 0) {
|
||||
editReportButton.addClass("disabled");
|
||||
deleteReportsButton.addClass("disabled");
|
||||
} else if (checkedReports.length === 1) {
|
||||
editReportButton.removeClass("disabled");
|
||||
deleteReportsButton.removeClass("disabled");
|
||||
} else {
|
||||
editReportButton.addClass("disabled");
|
||||
deleteReportsButton.removeClass("disabled");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the edit report functionality.
|
||||
*/
|
||||
function initEditReport() {
|
||||
editReportButton.click(function(e) {
|
||||
animateLoading();
|
||||
if (checkedReports.length === 1) {
|
||||
var id = checkedReports[0];
|
||||
var row = $(".report-row[data-id='" + id + "']");
|
||||
var url = row.data("edit-link");
|
||||
|
||||
$(location).attr("href", url);
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the deleting of reports.
|
||||
*/
|
||||
function initDeleteReports() {
|
||||
deleteReportsButton.click(function(e) {
|
||||
if (checkedReports.length > 0) {
|
||||
// Copy the checked IDs into the hidden input
|
||||
deleteReportsInput.attr("value", "[" + checkedReports + "]");
|
||||
|
||||
// Show modal
|
||||
deleteReportsModal.modal("show");
|
||||
}
|
||||
});
|
||||
|
||||
$("#confirm-delete-reports-btn").click(function(e) {
|
||||
animateLoading();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}());
|
|
@ -5,7 +5,6 @@ $.fn.findWithSelf = function(selector) {
|
|||
};
|
||||
|
||||
var REPORT_CONTENT = "#report-content";
|
||||
var SIDEBAR_PARENT_TREE = "#report-sidebar-tree";
|
||||
var ADD_CONTENTS_FORM_ID = "#add-contents-form";
|
||||
var SAVE_REPORT_FORM_ID = "#save-report-form";
|
||||
|
||||
|
@ -31,13 +30,14 @@ var ignoreUnsavedWorkAlert;
|
|||
initializeSaveToPdf();
|
||||
initializeSaveReport();
|
||||
initializeAddContentsModal();
|
||||
initializeSidebarNavigation();
|
||||
initializeUnsavedWorkDialog();
|
||||
initTutorial();
|
||||
|
||||
$('.report-nav-link').each(function() {
|
||||
truncateLongString($(this), <%= Constants::NAME_TRUNCATION_LENGTH %>);
|
||||
});
|
||||
|
||||
// Automatically display the "Add content" modal
|
||||
$('.new-element.initial').click();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -239,9 +239,6 @@ function initializeNewElement(newEl) {
|
|||
} else if (data.status == 200) {
|
||||
// Add elements
|
||||
addElements(el, data.responseJSON.elements);
|
||||
|
||||
// Update sidebar
|
||||
initializeSidebarNavigation();
|
||||
}
|
||||
})
|
||||
.on("ajax:error", function(e, xhr, settings, error) {
|
||||
|
@ -487,140 +484,6 @@ function initializeUnsavedWorkDialog() {
|
|||
$(document).on('page:before-change', beforeUnload);
|
||||
}
|
||||
|
||||
/**
|
||||
* SIDEBAR CODE
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get the sidebar <li> element for the specified report element.
|
||||
* @param reportEl - The .report-element in the report.
|
||||
* @return The corresponding sidebar <li>.
|
||||
*/
|
||||
function getSidebarEl(reportEl) {
|
||||
var type = reportEl.data("type");
|
||||
var scrollId = reportEl.data("scroll-id");
|
||||
return $(SIDEBAR_PARENT_TREE).find(
|
||||
"li" +
|
||||
"[data-type='" + type + "']" +
|
||||
"[data-scroll-id='" + scrollId + "']"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the report <div.report-element> element for the specified
|
||||
* sidebar element.
|
||||
* @param sidebarEl - The <li> sidebar element.
|
||||
* @return The corresponding report element.
|
||||
*/
|
||||
function getReportEl(sidebarEl) {
|
||||
var type = sidebarEl.data("type");
|
||||
var scrollId = sidebarEl.data("scroll-id");
|
||||
return $(REPORT_CONTENT).find(
|
||||
"div.report-element" +
|
||||
"[data-type='" + type + "']" +
|
||||
"[data-scroll-id='" + scrollId + "']"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the sidebar navigation pane.
|
||||
*/
|
||||
function initializeSidebarNavigation() {
|
||||
var reportContent = $(REPORT_CONTENT);
|
||||
var treeParent = $(SIDEBAR_PARENT_TREE);
|
||||
|
||||
// Remove existing contents (also remove click listeners)
|
||||
treeParent.find(".report-nav-link").off("click");
|
||||
treeParent.children().remove();
|
||||
|
||||
// Re-populate the sidebar
|
||||
_.each(reportContent.children(".report-element"), function(child) {
|
||||
var li = initSidebarElement($(child));
|
||||
li.appendTo(treeParent);
|
||||
});
|
||||
|
||||
// Add click listener on all links
|
||||
treeParent.find(".report-nav-link").click(function(e) {
|
||||
var el = $(this).closest("li");
|
||||
scrollToElement(el);
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
});
|
||||
|
||||
// Call to sidebar function to re-initialize tree functionality
|
||||
setupSidebarTree();
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive call to initialize sidebar elements.
|
||||
* @param reportEl - The report element for which to
|
||||
* generate the sidebar.
|
||||
* @return A <li> jQuery element containing sidebar entry.
|
||||
*/
|
||||
function initSidebarElement(reportEl) {
|
||||
var elChildrenContainer = reportEl.children(".report-element-children");
|
||||
var type = reportEl.data("type");
|
||||
var name = reportEl.data("name");
|
||||
var scrollId = reportEl.data("scroll-id");
|
||||
var iconClass = reportEl.data("icon-class");
|
||||
|
||||
// Generate list element
|
||||
var newLi = $(document.createElement("li"));
|
||||
newLi
|
||||
.attr("data-type", type)
|
||||
.attr("data-scroll-id", scrollId);
|
||||
|
||||
var newSpan = $(document.createElement("span"));
|
||||
newSpan.appendTo(newLi);
|
||||
var newI = $(document.createElement("i"));
|
||||
newI.appendTo(newSpan);
|
||||
var newHref = $(document.createElement("a"));
|
||||
newHref
|
||||
.attr("href", "")
|
||||
.addClass("report-nav-link")
|
||||
.text(name)
|
||||
.appendTo(newSpan);
|
||||
var newIcon = $(document.createElement("span"));
|
||||
newIcon.addClass(iconClass).prependTo(newHref);
|
||||
|
||||
if (elChildrenContainer.length && elChildrenContainer.length > 0) {
|
||||
var elChildren = elChildrenContainer.children(".report-element");
|
||||
if (elChildren.length && elChildren.length > 0) {
|
||||
var newUl = $(document.createElement("ul"));
|
||||
newUl.appendTo(newLi);
|
||||
|
||||
_.each(elChildren, function(child) {
|
||||
var li = initSidebarElement($(child));
|
||||
li.appendTo(newUl);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return newLi;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scroll to the specified element in the report.
|
||||
* @param sidebarEl - The sidebar element.
|
||||
*/
|
||||
function scrollToElement(sidebarEl) {
|
||||
var el = getReportEl(sidebarEl);
|
||||
|
||||
if (el.length && el.length == 1) {
|
||||
var content = $("body");
|
||||
content.scrollTo(
|
||||
el,
|
||||
{
|
||||
axis: 'y',
|
||||
duration: 500,
|
||||
offset: -150
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* INDIVIDUAL ELEMENTS SORTING/MODIFYING FUNCTIONS
|
||||
*/
|
||||
|
@ -684,8 +547,6 @@ function sortWholeReport(asc) {
|
|||
sortElementChildren($(el), asc, true);
|
||||
});
|
||||
|
||||
// Reinitialize sidebar
|
||||
initializeSidebarNavigation();
|
||||
animateLoading(false);
|
||||
}
|
||||
|
||||
|
@ -735,22 +596,6 @@ function sortElementChildren(el, asc, recursive) {
|
|||
sortElementChildren($(child), asc, true);
|
||||
}
|
||||
});
|
||||
|
||||
// Update sidebar
|
||||
var prevEl = null;
|
||||
_.each(children, function(child) {
|
||||
var sidebarEl = getSidebarEl($(child));
|
||||
if (sidebarEl.length && sidebarEl.length == 1) {
|
||||
var sidebarParent = sidebarEl.closest("ul");
|
||||
sidebarEl.detach();
|
||||
if (prevEl === null) {
|
||||
sidebarParent.prepend(sidebarEl);
|
||||
} else {
|
||||
prevEl.after(sidebarEl);
|
||||
}
|
||||
prevEl = sidebarEl;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -845,38 +690,24 @@ function moveElement(el, up) {
|
|||
return;
|
||||
}
|
||||
|
||||
var sidebarEl;
|
||||
if (up) {
|
||||
var prevEl = prevNewEl.prev();
|
||||
if (!prevEl.length || !prevEl.hasClass("report-element")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Move sidebar element up
|
||||
sidebarEl = getSidebarEl(el);
|
||||
var sidebarPrev = sidebarEl.prev();
|
||||
sidebarEl.detach();
|
||||
sidebarPrev.before(sidebarEl);
|
||||
|
||||
el.detach();
|
||||
nextNewEl.detach();
|
||||
prevEl.before(el);
|
||||
prevEl.before(nextNewEl);
|
||||
updateElementControls(prevEl);
|
||||
|
||||
|
||||
} else {
|
||||
var nextEl = nextNewEl.next();
|
||||
if (!nextEl.length || !nextEl.hasClass("report-element")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Move sidebar element up
|
||||
sidebarEl = getSidebarEl(el);
|
||||
var sidebarNext = sidebarEl.next();
|
||||
sidebarEl.detach();
|
||||
sidebarNext.after(sidebarEl);
|
||||
|
||||
prevNewEl.detach();
|
||||
el.detach();
|
||||
nextEl.after(el);
|
||||
|
@ -906,10 +737,6 @@ function removeElement(el) {
|
|||
|
||||
// TODO Remove event listeners
|
||||
|
||||
// Remove sidebar entry
|
||||
var sidebarEl = getSidebarEl(el);
|
||||
sidebarEl.remove();
|
||||
|
||||
prevNewEl.remove();
|
||||
el.remove();
|
||||
|
||||
|
@ -934,10 +761,6 @@ function removeResultCommentsElement(el) {
|
|||
|
||||
// TODO Remove event listeners
|
||||
|
||||
// Remove sidebar entry
|
||||
var sidebarEl = getSidebarEl(el);
|
||||
sidebarEl.remove();
|
||||
|
||||
// Remove element, show the new element container
|
||||
el.remove();
|
||||
parent.children(".new-element").removeClass("hidden");
|
||||
|
@ -1126,52 +949,6 @@ function constructElementContentsJson(el) {
|
|||
return jsonEl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds listeners to sidebar
|
||||
* that truncate long strings
|
||||
*/
|
||||
function initializeReportSidebartruncation() {
|
||||
var target = document.getElementById("report-sidebar-tree");
|
||||
var observer = new MutationObserver(
|
||||
function() {
|
||||
$.each($("a.report-nav-link"),
|
||||
function(){
|
||||
truncateLongString($(this),
|
||||
<%= Constants::NAME_TRUNCATION_LENGTH %>);
|
||||
});
|
||||
}
|
||||
);
|
||||
var config = { childList: true };
|
||||
|
||||
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) {
|
||||
|
|
202
app/assets/javascripts/reports/reports_datatable.js.erb
Normal file
|
@ -0,0 +1,202 @@
|
|||
(function(global) {
|
||||
'use strict';
|
||||
|
||||
var DATATABLE;
|
||||
var CHECKED_REPORTS = [];
|
||||
|
||||
function tableDrowCallback() {
|
||||
checkboxToggleCallback();
|
||||
initToggleAllCheckboxes();
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
function initSelectPicker() {
|
||||
$('.selectpicker').selectpicker({liveSearch: true})
|
||||
.ajaxSelectPicker({
|
||||
ajax: {
|
||||
url: '<%= Rails.application.routes.url_helpers.reports_visible_projects_path %>',
|
||||
type: 'POST',
|
||||
dataType: 'json',
|
||||
data: function () {
|
||||
return { q: '{{{q}}}' };
|
||||
}
|
||||
},
|
||||
locale: {
|
||||
emptyTitle: 'Nothing selected'
|
||||
},
|
||||
preprocessData: appendSearchResults,
|
||||
emptyRequest: true,
|
||||
clearOnEmpty: false,
|
||||
preserveSelected: false
|
||||
}).on('change.bs.select', function(el) {
|
||||
$('#new-report-reports-btn').attr('data-new-report-path', el.target.value);
|
||||
}).on('loaded.bs.select', function(el) {
|
||||
$('#new-report-reports-btn').attr('data-new-report-path', el.target.value);
|
||||
});
|
||||
}
|
||||
|
||||
function appendSearchResults(data) {
|
||||
var items = [];
|
||||
if(data.hasOwnProperty('projects')){
|
||||
$.each(data.projects, function(index, el) {
|
||||
items.push(
|
||||
{
|
||||
'value': el.path,
|
||||
'text': el.name,
|
||||
'disabled': false
|
||||
}
|
||||
)
|
||||
});
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
function initRedirectToNewReportPage() {
|
||||
$('#new-report-reports-btn').on('click', function() {
|
||||
animateSpinner();
|
||||
var url = $(this).attr('data-new-report-path');
|
||||
$(location).attr('href', url);
|
||||
});
|
||||
}
|
||||
|
||||
function initToggleAllCheckboxes() {
|
||||
$('input[name="select_all"]').change(function() {
|
||||
if($(this).is(':checked')) {
|
||||
$("[data-action='toggle']").prop('checked', true);
|
||||
addAllItems();
|
||||
} else {
|
||||
$("[data-action='toggle']").prop('checked', false);
|
||||
removeAllItems();
|
||||
}
|
||||
updateButtons();
|
||||
});
|
||||
}
|
||||
|
||||
function addAllItems() {
|
||||
$.each($("[data-action='toggle']"), function(i, el) {
|
||||
CHECKED_REPORTS.push($(el).attr('data-report-id'));
|
||||
})
|
||||
}
|
||||
|
||||
function removeAllItems() {
|
||||
CHECKED_REPORTS = [];
|
||||
}
|
||||
|
||||
function renderCheckboxHTML(data) {
|
||||
var html;
|
||||
html = "<input data-action='toggle' data-report-id='";
|
||||
html += data + "' type='checkbox'>";
|
||||
return html;
|
||||
}
|
||||
|
||||
function appendEditPathToRow(row, data) {
|
||||
$(row).addClass('report-row')
|
||||
.attr('data-edit-path', data['edit'])
|
||||
.attr('data-id', data['0']);
|
||||
}
|
||||
|
||||
function checkboxToggleCallback() {
|
||||
$("[data-action='toggle']").change(function() {
|
||||
var id = $(this).attr('data-report-id');
|
||||
if($(this).is(':checked')) {
|
||||
CHECKED_REPORTS.push(id);
|
||||
} else {
|
||||
var index = CHECKED_REPORTS.indexOf(id);
|
||||
if(index != -1) {
|
||||
CHECKED_REPORTS.splice(index, 1);
|
||||
}
|
||||
}
|
||||
updateButtons();
|
||||
});
|
||||
}
|
||||
|
||||
function updateButtons() {
|
||||
var editReportButton = $('#edit-report-btn');
|
||||
var deleteReportsButton = $('#delete-reports-btn');
|
||||
if (CHECKED_REPORTS.length === 0) {
|
||||
editReportButton.addClass("disabled");
|
||||
deleteReportsButton.addClass("disabled");
|
||||
} else if (CHECKED_REPORTS.length === 1) {
|
||||
editReportButton.removeClass("disabled");
|
||||
deleteReportsButton.removeClass("disabled");
|
||||
} else {
|
||||
editReportButton.addClass("disabled");
|
||||
deleteReportsButton.removeClass("disabled");
|
||||
}
|
||||
}
|
||||
|
||||
// INIT
|
||||
|
||||
function initDatatable() {
|
||||
var $table = $('#reports-table')
|
||||
DATATABLE = $table.dataTable({
|
||||
'order': [[2, 'desc']],
|
||||
'processing': true,
|
||||
'serverSide': true,
|
||||
'ajax': $table.data('source'),
|
||||
'pagingType': 'simple_numbers',
|
||||
'colReorder': {
|
||||
'fixedColumnsLeft': 1000000 // Disable reordering
|
||||
},
|
||||
'columnDefs': [{
|
||||
'targets': 0,
|
||||
'searchable': false,
|
||||
'orderable': false,
|
||||
'className': 'dt-body-center',
|
||||
'sWidth': '1%',
|
||||
'render': renderCheckboxHTML
|
||||
}],
|
||||
'oLanguage': {
|
||||
'sSearch': I18n.t('general.filter')
|
||||
},
|
||||
'fnDrawCallback': tableDrowCallback,
|
||||
'createdRow': appendEditPathToRow
|
||||
});
|
||||
}
|
||||
|
||||
function initEditReport() {
|
||||
$('#edit-report-btn').click(function(e) {
|
||||
e.preventDefault();
|
||||
animateSpinner();
|
||||
if (CHECKED_REPORTS.length === 1) {
|
||||
var id = CHECKED_REPORTS[0];
|
||||
var row = $(".report-row[data-id='" + id + "']");
|
||||
var url = row.attr('data-edit-path');
|
||||
$(location).attr('href', url);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function initDeleteReports() {
|
||||
$('#delete-reports-btn').click(function(e) {
|
||||
if (CHECKED_REPORTS.length > 0) {
|
||||
$('#report-ids').attr("value", "[" + CHECKED_REPORTS + "]");
|
||||
$('#delete-reports-modal').modal("show");
|
||||
}
|
||||
});
|
||||
|
||||
$("#confirm-delete-reports-btn").click(function(e) {
|
||||
animateLoading();
|
||||
});
|
||||
}
|
||||
|
||||
function initNewReportModal() {
|
||||
$('#new-report-btn').on('click', function() {
|
||||
$('#new-report-modal').modal('show').promise().done(function() {
|
||||
initSelectPicker();
|
||||
initRedirectToNewReportPage();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function init() {
|
||||
$(document).ready(function() {
|
||||
initDatatable();
|
||||
initEditReport();
|
||||
initDeleteReports();
|
||||
initNewReportModal();
|
||||
});
|
||||
}
|
||||
|
||||
init();
|
||||
})(window);
|
282
app/assets/javascripts/reports/save_pdf_to_inventory.js.erb
Normal file
|
@ -0,0 +1,282 @@
|
|||
(function() {
|
||||
'use strict';
|
||||
|
||||
var INVENTORY_PICKER, COLUMN_PICKER, ITEM_PICKER;
|
||||
var SELECTED_IDS = {
|
||||
repository_id: null,
|
||||
respository_column_id: null,
|
||||
repository_item_id: null,
|
||||
};
|
||||
|
||||
function clearErrors() {
|
||||
var $columnsAlertSection = $('#save-PDF-to-inventory-column-warnings');
|
||||
var $itemsAlertSection = $('#save-PDF-to-inventory-warnings');
|
||||
$itemsAlertSection.empty();
|
||||
$columnsAlertSection.empty();
|
||||
}
|
||||
|
||||
function toggleHasFileErrorMessage(value) {
|
||||
var element = $('#selectInventoryItem [value="' + value + '"]');
|
||||
var $alertSection = $('#save-PDF-to-inventory-warnings');
|
||||
$alertSection.empty();
|
||||
if(element.data('hasfile')) {
|
||||
$alertSection.append(
|
||||
'<div class="alert alert-danger">' +
|
||||
'<%=I18n.t("projects.reports.new.save_PDF_to_inventory_modal.asset_present_warning_html") %>' +
|
||||
'</div>'
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function appendSearchResults(data) {
|
||||
var items = [];
|
||||
if(data.hasOwnProperty('results')){
|
||||
$.each(data.results, function(index, el) {
|
||||
items.push(
|
||||
{
|
||||
value: el.id,
|
||||
text: el.name,
|
||||
disabled: false
|
||||
}
|
||||
)
|
||||
});
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
function appendSearchResultsForItems(data) {
|
||||
var items = [];
|
||||
if(data.hasOwnProperty('results')){
|
||||
$('#selectInventoryItem').parent().find('button').removeAttr('disabled');
|
||||
$.each(data.results, function(index, el) {
|
||||
items.push(
|
||||
{
|
||||
value: el.id,
|
||||
text: el.name,
|
||||
disabled: false,
|
||||
data: {
|
||||
hasFile: el.hasOwnProperty('has_file_attached') ?
|
||||
el.has_file_attached :
|
||||
null
|
||||
}
|
||||
}
|
||||
)
|
||||
});
|
||||
} else {
|
||||
$('#selectInventoryItem').parent().find('button').attr('disabled', true);
|
||||
clearErrors();
|
||||
$('#save-PDF-to-inventory-warnings').append(
|
||||
'<strong class="danger">' + data.no_items + '</strong>'
|
||||
)
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
function appendSearchResultsForColumns(data) {
|
||||
var items = [];
|
||||
if(data.hasOwnProperty('results')){
|
||||
$('#selectInventoryColumn').parent().find('button').removeAttr('disabled');
|
||||
$.each(data.results, function(index, el) {
|
||||
items.push(
|
||||
{
|
||||
value: el.id,
|
||||
text: el.name,
|
||||
disabled: false
|
||||
}
|
||||
)
|
||||
});
|
||||
} else {
|
||||
$('#selectInventoryColumn').parent().find('button').attr('disabled', true);
|
||||
clearErrors();
|
||||
$('#save-PDF-to-inventory-column-warnings').append(
|
||||
'<div class="save-PDF-to-inventory-alerts"><strong class="danger">' +
|
||||
data.no_items + '</strong></div>'
|
||||
)
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
function submitButtonEnableToggle(status) {
|
||||
var button = $('#savePDFtoInventorySubmit');
|
||||
if(status) {
|
||||
button.removeAttr('disabled');
|
||||
} else {
|
||||
button.attr('disabled', true);
|
||||
}
|
||||
}
|
||||
|
||||
function deselect(element) {
|
||||
if(element) {
|
||||
element.selectpicker('val', null)
|
||||
element.selectpicker('render');
|
||||
element.attr('disabled', true);
|
||||
}
|
||||
}
|
||||
|
||||
// triggers first request and cleans the dropdown selectpicker
|
||||
function clearDropdownResultsCallback(element) {
|
||||
element.parent().find('button').on('click', function(el) {
|
||||
$(this).parent().find('input').trigger('keyup');
|
||||
});
|
||||
}
|
||||
|
||||
function initInventoryItemSelectPicker() {
|
||||
ITEM_PICKER =
|
||||
$('#selectInventoryItem')
|
||||
.removeAttr('disabled')
|
||||
.selectpicker({liveSearch: true})
|
||||
.ajaxSelectPicker({
|
||||
ajax: {
|
||||
url: '<%= Rails.application.routes.url_helpers.available_rows_path %>',
|
||||
type: 'POST',
|
||||
dataType: 'json',
|
||||
data: function () {
|
||||
return {
|
||||
q: '{{{q}}}',
|
||||
repository_id: SELECTED_IDS.repository_id,
|
||||
repository_column_id: SELECTED_IDS.respository_column_id
|
||||
};
|
||||
}
|
||||
},
|
||||
locale: {
|
||||
emptyTitle: '<%= I18n.t('projects.reports.new.save_PDF_to_inventory_modal.nothing_selected') %>'
|
||||
},
|
||||
preprocessData: appendSearchResultsForItems,
|
||||
emptyRequest: true,
|
||||
clearOnEmpty: true,
|
||||
cache: false,
|
||||
preserveSelected: false
|
||||
}).on('change.bs.select', function(el) {
|
||||
var value = el.target.value;
|
||||
toggleHasFileErrorMessage(value);
|
||||
submitButtonEnableToggle(true);
|
||||
SELECTED_IDS.repository_item_id = value;
|
||||
});
|
||||
clearDropdownResultsCallback(ITEM_PICKER);
|
||||
}
|
||||
|
||||
function initInventoryColumnSelectPicker() {
|
||||
COLUMN_PICKER =
|
||||
$('#selectInventoryColumn')
|
||||
.removeAttr('disabled')
|
||||
.selectpicker({liveSearch: true})
|
||||
.ajaxSelectPicker({
|
||||
ajax: {
|
||||
url: '<%= Rails.application.routes.url_helpers.available_asset_type_columns_path %>',
|
||||
type: 'POST',
|
||||
dataType: 'json',
|
||||
data: function () {
|
||||
return {
|
||||
q: '{{{q}}}',
|
||||
repository_id: SELECTED_IDS.repository_id
|
||||
};
|
||||
}
|
||||
},
|
||||
locale: {
|
||||
emptyTitle: '<%= I18n.t('projects.reports.new.save_PDF_to_inventory_modal.nothing_selected') %>'
|
||||
},
|
||||
preprocessData: appendSearchResultsForColumns,
|
||||
emptyRequest: true,
|
||||
clearOnEmpty: true,
|
||||
cache: false,
|
||||
preserveSelected: false
|
||||
}).on('change.bs.select', function(el) {
|
||||
SELECTED_IDS.respository_column_id = el.target.value;
|
||||
deselect(ITEM_PICKER);
|
||||
submitButtonEnableToggle(false);
|
||||
initInventoryItemSelectPicker();
|
||||
// refresh the dropdown state
|
||||
$('#selectInventoryItem').parent().find('input').trigger('keyup');
|
||||
clearErrors();
|
||||
});
|
||||
clearDropdownResultsCallback(COLUMN_PICKER);
|
||||
}
|
||||
|
||||
function initInventoriesSelectPicker() {
|
||||
INVENTORY_PICKER =
|
||||
$('#selectInventory')
|
||||
.selectpicker({liveSearch: true})
|
||||
.ajaxSelectPicker({
|
||||
ajax: {
|
||||
url: '<%= Rails.application.routes.url_helpers.reports_available_repositories_path %>',
|
||||
type: 'POST',
|
||||
dataType: 'json',
|
||||
data: function () {
|
||||
return { q: '{{{q}}}' };
|
||||
}
|
||||
},
|
||||
locale: {
|
||||
emptyTitle: '<%= I18n.t('projects.reports.new.save_PDF_to_inventory_modal.nothing_selected') %>'
|
||||
},
|
||||
preprocessData: appendSearchResults,
|
||||
emptyRequest: true,
|
||||
clearOnEmpty: false,
|
||||
cache: false,
|
||||
preserveSelected: false
|
||||
}).on('change.bs.select', function(el) {
|
||||
SELECTED_IDS.repository_id = el.target.value;
|
||||
deselect(COLUMN_PICKER);
|
||||
deselect(ITEM_PICKER);
|
||||
submitButtonEnableToggle(false);
|
||||
initInventoryColumnSelectPicker();
|
||||
clearErrors();
|
||||
// refresh the dropdown state
|
||||
$('#selectInventoryColumn').parent().find('input').trigger('keyup');
|
||||
});
|
||||
clearDropdownResultsCallback(INVENTORY_PICKER);
|
||||
}
|
||||
|
||||
function initializeSubmitAction() {
|
||||
$('#savePDFtoInventorySubmit').off().on('click', function() {
|
||||
animateSpinner();
|
||||
$.ajax({
|
||||
url: '<%= Rails.application.routes.url_helpers.reports_save_pdf_to_inventory_item_path %>',
|
||||
data: Object.assign(SELECTED_IDS, { html: $(REPORT_CONTENT).html() }, {}),
|
||||
type: 'POST',
|
||||
success: function(data) {
|
||||
animateSpinner(null, false);
|
||||
HelperModule.flashAlertMsg(data.message, 'success');
|
||||
$('#savePDFtoInventory').modal('hide');
|
||||
},
|
||||
error: function(xhr) {
|
||||
animateSpinner(null, false);
|
||||
HelperModule.flashAlertMsg(xhr.responseJSON.message, 'danger');
|
||||
$('#savePDFtoInventory').modal('hide');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* INITIALIZERS
|
||||
*/
|
||||
|
||||
function initializeSavePDFtoInventoryModal() {
|
||||
$('#savePDFtoInventory').off().on('shown.bs.modal', function() {
|
||||
initInventoriesSelectPicker();
|
||||
initializeSubmitAction();
|
||||
clearErrors();
|
||||
// refresh the dropdown state
|
||||
$('#selectInventory').parent().find('input').trigger('keyup');
|
||||
}).on('hidden.bs.modal', function() {
|
||||
// clear ids
|
||||
SELECTED_IDS = {
|
||||
repository_id: null,
|
||||
respository_column_id: null,
|
||||
repository_item_id: null,
|
||||
}
|
||||
// clear select picker objects
|
||||
|
||||
if(COLUMN_PICKER) {
|
||||
deselect(COLUMN_PICKER);
|
||||
}
|
||||
|
||||
if(ITEM_PICKER) {
|
||||
deselect(ITEM_PICKER);
|
||||
}
|
||||
submitButtonEnableToggle(false);
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(initializeSavePDFtoInventoryModal);
|
||||
})();
|
|
@ -66,7 +66,7 @@
|
|||
type: "GET",
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
var tabBody = $(pane.context.hash).find(".tab-content-body");
|
||||
var tabBody = $(pane.context.hash).find(".tab-content-body");
|
||||
tabBody.html(data.html);
|
||||
pane.tab('show').promise().done(function(el) {
|
||||
initImportRecordsModal();
|
||||
|
@ -96,9 +96,8 @@
|
|||
})
|
||||
}
|
||||
|
||||
$('.create-repository').initializeModal('#create-repo-modal');
|
||||
|
||||
$(document).ready(function() {
|
||||
$('#create-new-repository').initializeModal('#create-repo-modal');
|
||||
loadRepositoryTab();
|
||||
initImportRecordsModal();
|
||||
});
|
||||
|
|
38
app/assets/javascripts/repositories/show.js
Normal file
|
@ -0,0 +1,38 @@
|
|||
(function() {
|
||||
'use strict';
|
||||
|
||||
function initImportRecordsModal() {
|
||||
$('#importRecordsButton').off().on('click', function() {
|
||||
$('#modal-import-records').modal('show');
|
||||
_initParseRecordsModal();
|
||||
});
|
||||
}
|
||||
|
||||
function _initParseRecordsModal() {
|
||||
$('#form-records-file').on('ajax:success', function(ev, data) {
|
||||
$('#modal-import-records').modal('hide');
|
||||
$(data.html).appendTo('body').promise().done(function() {
|
||||
$('#parse-records-modal')
|
||||
.modal('show')
|
||||
.on('hidden.bs.modal', function() {
|
||||
animateSpinner();
|
||||
location.reload();
|
||||
});
|
||||
repositoryRecordsImporter();
|
||||
});
|
||||
}).on('ajax:error', function(ev, data) {
|
||||
$(this).find('.form-group').addClass('has-error');
|
||||
$(this).find('.form-group').find('.help-block').remove();
|
||||
$(this).find('.form-group').append("<span class='help-block'>" +
|
||||
data.responseJSON.message + '</span>');
|
||||
});
|
||||
}
|
||||
|
||||
function initialzerRepositoryTable() {
|
||||
initImportRecordsModal();
|
||||
RepositoryDatatable.destroy();
|
||||
RepositoryDatatable.init('#' + $('.repository-table table').attr('id'));
|
||||
}
|
||||
|
||||
$(document).ready(initialzerRepositoryTable);
|
||||
})()
|
230
app/assets/javascripts/repository_columns/index.js.erb
Normal file
|
@ -0,0 +1,230 @@
|
|||
(function() {
|
||||
'use strict';
|
||||
|
||||
// @TODO refactor that eventually
|
||||
function initEditCoumnModal() {
|
||||
var modalID = '#manageRepositoryColumn';
|
||||
var colRadID = '#repository_column_data_type_repositorylistvalue';
|
||||
var tagsInputID = '[data-role="tagsinput"]';
|
||||
var formID = '[data-role="manage-repository-column-form"]';
|
||||
|
||||
$('[data-action="edit"]').off('click').on('click', function() {
|
||||
var editUrl = $(this).closest('li').attr('data-edit-url');
|
||||
$.get(editUrl, function(data) {
|
||||
$(data.html).appendTo('body').promise().done(function() {
|
||||
$(modalID).modal('show').promise().done(function() {
|
||||
|
||||
$(modalID).on('hidden.bs.modal', function () {
|
||||
// remove edit modal window
|
||||
$(modalID).remove();
|
||||
$('.modal-backdrop').remove();
|
||||
});
|
||||
|
||||
_initTagInput();
|
||||
setTimeout(function() {
|
||||
$('#repository_column_name').focus();
|
||||
}, 500)
|
||||
|
||||
if($(modalID).attr('data-edit-type') === 'RepositoryListValue') {
|
||||
var values = JSON.parse($(tagsInputID).attr('data-value'));
|
||||
$(colRadID).click().promise().done(function() {
|
||||
$.each(values, function(index, element) {
|
||||
$(tagsInputID).tagsinput('add', element);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$('[data-action="save"]').on('click', function() {
|
||||
if($(colRadID).is(':checked')) {
|
||||
$('#list_items').val($(tagsInputID).val());
|
||||
}
|
||||
|
||||
_processResponse($(formID), 'update', modalID);
|
||||
});
|
||||
});
|
||||
});
|
||||
}).fail(function(error) {
|
||||
HelperModule.flashAlertMsg(
|
||||
"<%= I18n.t("libraries.repository_columns.no_permissions") %>",
|
||||
'danger');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function initDeleteColumnModal() {
|
||||
$('[data-action="destroy"]').off('click').on('click', function() {
|
||||
var element = $(this);
|
||||
var modal_html = $("#deleteRepositoryColumn");
|
||||
$.get(element.closest('li').attr('data-destroy-url'), function(data) {
|
||||
modal_html.find('.modal-body').html(data.html)
|
||||
.promise()
|
||||
.done(function() {
|
||||
modal_html.modal('show');
|
||||
_initSubmitAction(modal_html, $(modal_html.find('form')));
|
||||
});
|
||||
}).fail(function(error) {
|
||||
HelperModule.flashAlertMsg(
|
||||
"<%= I18n.t("libraries.repository_columns.no_permissions") %>",
|
||||
'danger');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// @TODO refactor that eventually
|
||||
function initNewColumnModal() {
|
||||
var modalID = '#manageRepositoryColumn';
|
||||
$('[data-action="new-column-modal"]').off('click').on('click', function() {
|
||||
var modalUrl = $(this).attr('data-modal-url');
|
||||
$.get(modalUrl, function(data) {
|
||||
$(data.html).appendTo('body').promise().done(function() {
|
||||
$(modalID).modal('show').promise().done(function() {
|
||||
|
||||
$(modalID).on('hidden.bs.modal', function () {
|
||||
// remove create new modal window
|
||||
$(modalID).remove();
|
||||
$('.modal-backdrop').remove();
|
||||
});
|
||||
|
||||
_initTagInput();
|
||||
setTimeout(function() {
|
||||
$('#repository_column_name').focus();
|
||||
}, 500);
|
||||
|
||||
$('[data-action="save"]').on('click', function() {
|
||||
var colRad = '#repository_column_data_type_repositorylistvalue';
|
||||
if($(colRad).is(':checked')) {
|
||||
$('#list_items')
|
||||
.val($('[data-role="tagsinput"]').val());
|
||||
}
|
||||
var form = $('[data-role="manage-repository-column-form"]');
|
||||
_processResponse(form, 'create', modalID);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/* *********************************
|
||||
Helper methods
|
||||
********************************* */
|
||||
|
||||
function _insertNewListItem(column) {
|
||||
// remove element if already persent
|
||||
$('[data-id="' + column.id + '"]').remove();
|
||||
var html = '<li class="list-group-item" data-id="' + column.id + '" ';
|
||||
html += 'data-destroy-url="' + column.destroy_html_url + '"';
|
||||
html += 'data-edit-url="' + column.edit_url + '">';
|
||||
html += '<span class="pull-left">' + column.name + '</span>';
|
||||
html += '<span class="controlls pull-right">';
|
||||
html += '<button class="btn btn-default" data-action="edit">';
|
||||
html += '<span class="fas fa-pencil-alt"></span> ';
|
||||
html += '<%= I18n.t "libraries.repository_columns.index.edit_column" %></button> ';
|
||||
html += '<button class="btn btn-default" data-action="destroy">';
|
||||
html += '<span class="glyphicon glyphicon-trash"></span> ';
|
||||
html += '<%= I18n.t "libraries.repository_columns.index.delete_column" %>';
|
||||
html += '</button></span></li>';
|
||||
$(html).insertBefore('.repository-columns-body ul li:first')
|
||||
.promise()
|
||||
.done(function() {
|
||||
initDeleteColumnModal();
|
||||
initEditCoumnModal();
|
||||
// remove create new modal window
|
||||
$('#manageRepositoryColumn').remove();
|
||||
$('.modal-backdrop').remove();
|
||||
});
|
||||
// remove 'no column' list item
|
||||
$('[data-attr="no-columns"]').remove();
|
||||
}
|
||||
|
||||
function _replaceListItem(column) {
|
||||
$('.list-group-item[data-id="' + column.id + '"]')
|
||||
.find('span.pull-left').text(column.name);
|
||||
}
|
||||
|
||||
function _initTagInput() {
|
||||
$('[name="repository_column[data_type]"]')
|
||||
.on('click', function() {
|
||||
var listValueId = 'repository_column_data_type_repositorylistvalue';
|
||||
if($(this).attr('id') === listValueId) {
|
||||
$('[data-role="tagsinput"]').tagsinput({
|
||||
maxChars: <%= Constants::NAME_MAX_LENGTH %>,
|
||||
trimValue: true
|
||||
});
|
||||
$('.bootstrap-tagsinput').show();
|
||||
$('[data-role="tagsimput-label"]').show();
|
||||
} else {
|
||||
$('.bootstrap-tagsinput').hide();
|
||||
$('[data-role="tagsimput-label"]').hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function _removeElementFromDom(column) {
|
||||
$('.list-group-item[data-id="' + column.id + '"]').remove();
|
||||
if($('.list-group-item').length === 0) {
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
|
||||
function _initSubmitAction(modal, form) {
|
||||
modal.find('[data-action="delete"]').on('click', function() {
|
||||
form.submit();
|
||||
modal.modal('hide')
|
||||
animateSpinner();
|
||||
_processResponse(form, 'destroy');
|
||||
});
|
||||
}
|
||||
|
||||
function _processResponse(form, action, modalID) {
|
||||
form.on('ajax:success', function(e, data) {
|
||||
switch(action) {
|
||||
case 'destroy':
|
||||
_removeElementFromDom(data);
|
||||
break;
|
||||
case 'create':
|
||||
_insertNewListItem(data);
|
||||
break;
|
||||
case 'update':
|
||||
_replaceListItem(data);
|
||||
break;
|
||||
default:
|
||||
location.reload();
|
||||
}
|
||||
HelperModule.flashAlertMsg(data.message, 'success');
|
||||
animateSpinner(null, false);
|
||||
if (modalID) {
|
||||
$(modalID).modal('hide');
|
||||
}
|
||||
}).on('ajax:error', function(e, xhr) {
|
||||
animateSpinner(null, false);
|
||||
if (modalID) {
|
||||
if(xhr.responseJSON.message.hasOwnProperty('repository_list_items')) {
|
||||
var message = xhr.responseJSON.message['repository_list_items'];
|
||||
$('.dnd-error').remove();
|
||||
$('#manageRepositoryColumn ').find('.bootstrap-tagsinput').after(
|
||||
"<i class='dnd-error'>" + message + "</i>"
|
||||
);
|
||||
} else {
|
||||
var field = { "name": xhr.responseJSON.message }
|
||||
$(form).renderFormErrors('repository_column', field, true, e);
|
||||
}
|
||||
} else {
|
||||
HelperModule.flashAlertMsg(xhr.responseJSON.message, 'danger');
|
||||
}
|
||||
});
|
||||
if (modalID) {
|
||||
form.submit();
|
||||
}
|
||||
}
|
||||
|
||||
/* *********************************
|
||||
Initializers
|
||||
********************************* */
|
||||
|
||||
$(document).ready(function() {
|
||||
initEditCoumnModal();
|
||||
initDeleteColumnModal();
|
||||
initNewColumnModal();
|
||||
});
|
||||
})();
|
|
@ -271,10 +271,6 @@ setTimeout(function () {
|
|||
table.columns.adjust();
|
||||
}, 10);
|
||||
|
||||
|
||||
// Enables noSearchHidden plugin
|
||||
$.fn.dataTable.defaults.noSearchHidden = true;
|
||||
|
||||
// Updates "Select all" control in a data table
|
||||
function updateDataTableSelectAllCtrl(table) {
|
||||
var $table = table.table().node();
|
||||
|
@ -1081,7 +1077,7 @@ function changeToEditMode() {
|
|||
var editable = $(el).is('[data-editable]');
|
||||
var deletable = $(el).is('[data-deletable]');
|
||||
|
||||
var visClass = (visible) ? 'glyphicon-eye-open' : 'glyphicon-eye-close';
|
||||
var visClass = (visible) ? 'fas fa-eye' : 'glyphicon-eye-close';
|
||||
var visLi = (visible) ? '' : 'col-invisible';
|
||||
var editClass = (editable) ? '' : 'disabled';
|
||||
var delClass = (deletable) ? '' : 'disabled';
|
||||
|
@ -1109,7 +1105,7 @@ function changeToEditMode() {
|
|||
'<span class="ok glyphicon glyphicon-ok" style="display: none;" title="<%= I18n.t("general.save") %>"></span>' +
|
||||
'<span class="cancel glyphicon glyphicon-remove" style="display: none;" title="<%= I18n.t("general.cancel") %>"></span>' +
|
||||
'<span class="vis glyphicon ' + visClass + '" title="<%= I18n.t("samples.columns_visibility") %>"></span> ' +
|
||||
'<span class="edit glyphicon glyphicon-pencil ' + editClass + '" title="<%= I18n.t("general.edit") %>"></span>' +
|
||||
'<span class="edit fas fa-pencil-alt ' + editClass + '" title="<%= I18n.t("general.edit") %>"></span>' +
|
||||
'<span class="del glyphicon glyphicon-trash ' + delClass + '" title="<%= I18n.t("samples.columns_delete") %>"></span>' +
|
||||
'</span><br></span></li>';
|
||||
dropdownList.append(html);
|
||||
|
@ -1145,12 +1141,12 @@ function changeToEditMode() {
|
|||
|
||||
if (column.visible()) {
|
||||
self.addClass('glyphicon-eye-close');
|
||||
self.removeClass('glyphicon-eye-open');
|
||||
self.removeClass('fas fa-eye');
|
||||
li.addClass('col-invisible');
|
||||
column.visible(false);
|
||||
table.setColumnSearchable(column.index(), false);
|
||||
} else {
|
||||
self.addClass('glyphicon-eye-open');
|
||||
self.addClass('fas fa-eye');
|
||||
self.removeClass('glyphicon-eye-close');
|
||||
li.removeClass('col-invisible');
|
||||
column.visible(true);
|
||||
|
|
|
@ -87,25 +87,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();
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
*/
|
||||
|
||||
var STORAGE_TREE_KEY = "scinote-sidebar-tree-collapsed-ids";
|
||||
var STORAGE_TOGGLE_KEY = "scinote-sidebar-toggled";
|
||||
|
||||
/**
|
||||
* Get all collapsed sidebar elements.
|
||||
|
@ -84,33 +83,6 @@ function recalculateElementsPositions(ids, item, elements) {
|
|||
sessionStorage.setItem(STORAGE_TREE_KEY, JSON.stringify(ids));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get the session stored toggled boolean or null value if
|
||||
* sidebar toggle state was not changed by user. It allow for
|
||||
* automatic toggling for small devices.
|
||||
*
|
||||
* @return True if sidebar is toggled; false otherwise.
|
||||
*/
|
||||
function sessionIsSidebarToggled() {
|
||||
var val = sessionStorage.getItem(STORAGE_TOGGLE_KEY);
|
||||
|
||||
if (val === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return val === "toggled";
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the sidebar toggled boolean to session storage.
|
||||
*/
|
||||
function sessionToggleSidebar() {
|
||||
if (sessionIsSidebarToggled()) {
|
||||
sessionStorage.setItem(STORAGE_TOGGLE_KEY, "not_toggled");
|
||||
} else {
|
||||
sessionStorage.setItem(STORAGE_TOGGLE_KEY, "toggled");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the sidebar collapsing & expanding functionality.
|
||||
|
@ -128,7 +100,7 @@ function setupSidebarTree() {
|
|||
}
|
||||
el
|
||||
.find(" > span i")
|
||||
.attr("title", "Expand this branch")
|
||||
.attr("title", I18n.t('sidebar.branch_expand'))
|
||||
.removeClass("expanded");
|
||||
} else {
|
||||
if (animate) {
|
||||
|
@ -138,7 +110,7 @@ function setupSidebarTree() {
|
|||
}
|
||||
el
|
||||
.find(" > span i")
|
||||
.attr("title", "Collapse this branch")
|
||||
.attr("title", I18n.t('sidebar.branch_collapse'))
|
||||
.addClass("expanded");
|
||||
}
|
||||
}
|
||||
|
@ -147,9 +119,10 @@ function setupSidebarTree() {
|
|||
$(".tree li:has(ul)")
|
||||
.addClass("parent_li")
|
||||
.find(" > span i")
|
||||
.attr("title", "Collapse this branch");
|
||||
.attr("title", I18n.t('sidebar.branch_collapse'));
|
||||
$(".tree li.parent_li ")
|
||||
.find("> span i")
|
||||
.removeClass("no-arrow")
|
||||
.addClass("glyphicon glyphicon-triangle-right expanded");
|
||||
|
||||
// Add IDs to all parent <lis>
|
||||
|
@ -169,7 +142,7 @@ function setupSidebarTree() {
|
|||
// Get the session-stored elements
|
||||
var collapsedIds = sessionGetCollapsedSidebarElements();
|
||||
|
||||
// Get the current project stered elements
|
||||
// Get the current project stored elements
|
||||
var currentProjectIds = _.findWhere(collapsedIds, { prid: project });
|
||||
if ( currentProjectIds ){
|
||||
currentProjectIds.ids = _.filter(currentProjectIds.ids,
|
||||
|
@ -241,62 +214,33 @@ function setupSidebarTree() {
|
|||
e.stopPropagation();
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the show/hide toggling of sidebar.
|
||||
*/
|
||||
function initializeSidebarToggle() {
|
||||
var wrapper = $("#wrapper");
|
||||
var toggled = sessionIsSidebarToggled();
|
||||
// Add bold style to all levels of selected element
|
||||
$(".tree li.active ")
|
||||
.parents('.parent_li[data-parent="candidate"]')
|
||||
.find("> span a")
|
||||
.css("font-weight", "bold");
|
||||
|
||||
if (toggled || toggled === null && $(window).width() <
|
||||
<%= Constants::SCREEN_WIDTH_LARGE %>) {
|
||||
wrapper.addClass("no-animation");
|
||||
wrapper.addClass("toggled");
|
||||
// Cause reflow of the wrapper element
|
||||
wrapper[0].offsetHeight;
|
||||
wrapper.removeClass("no-animation");
|
||||
$(".navbar-secondary").addClass("navbar-without-sidebar");
|
||||
}
|
||||
|
||||
$("#toggle-sidebar-link").on("click", function() {
|
||||
$("#wrapper").toggleClass("toggled");
|
||||
sessionToggleSidebar();
|
||||
$(".navbar-secondary").toggleClass("navbar-without-sidebar", sessionIsSidebarToggled());
|
||||
return false;
|
||||
});
|
||||
// Add custom borders to tree links
|
||||
$(".tree li span.tree-link ").after("<div class='border-custom'></div>");
|
||||
}
|
||||
|
||||
// Resize the sidebar to accomodate to the page size
|
||||
function resizeSidebarContents() {
|
||||
var wrapper = $("#wrapper");
|
||||
var tree = $("#sidebar-wrapper .tree");
|
||||
var toggled = sessionIsSidebarToggled();
|
||||
var navbar = $(".navbar-secondary");
|
||||
|
||||
// Set vertical scrollbar on navigation tree
|
||||
if (tree.length && tree.length == 1) {
|
||||
tree.css(
|
||||
"height",
|
||||
($(window).height() - tree.position().top - 50) + "px"
|
||||
);
|
||||
}
|
||||
// Automatic toggling of sidebar for smaller devices
|
||||
if (toggled === null) {
|
||||
if ($(window).width() < <%= Constants::SCREEN_WIDTH_LARGE %>) {
|
||||
wrapper.addClass("toggled");
|
||||
navbar.addClass("navbar-without-sidebar");
|
||||
} else {
|
||||
wrapper.removeClass("toggled");
|
||||
navbar.removeClass("navbar-without-sidebar");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(function () {
|
||||
// Initialize click listeners
|
||||
setupSidebarTree();
|
||||
initializeSidebarToggle();
|
||||
|
||||
// Actually display wrapper, which is, up to now,
|
||||
// hidden
|
||||
|
|
51
app/assets/javascripts/sidebar_toggle.js.erb
Normal file
|
@ -0,0 +1,51 @@
|
|||
(function(global) {
|
||||
'use strict';
|
||||
global.SideBarToggle = (function() {
|
||||
|
||||
function show() {
|
||||
$('#wrapper').removeClass('hidden2');
|
||||
$('#sidebar-wrapper').show(
|
||||
'slide', { direction: 'right', easing: 'linear' }, 400
|
||||
);
|
||||
$('#wrapper').css('paddingLeft', '280px');
|
||||
$('.navbar-secondary').css(
|
||||
{ 'margin-left': '-280px', 'padding-left': '294px' }
|
||||
);
|
||||
$('#toggle-sidebar-btn').attr('data-shown', '');
|
||||
}
|
||||
|
||||
function hide() {
|
||||
$('#wrapper').addClass('hidden2');
|
||||
$('#sidebar-wrapper').hide(
|
||||
'slide', { direction: 'left', easing: 'linear'}, 400
|
||||
);
|
||||
$('#wrapper').css('paddingLeft', '0');
|
||||
$('.navbar-secondary').css({
|
||||
'margin-left': '0',
|
||||
'padding-left': '14px'
|
||||
});
|
||||
$('#toggle-sidebar-btn').removeAttr('data-shown');
|
||||
}
|
||||
|
||||
function toggle() {
|
||||
var btn = $('#toggle-sidebar-btn');
|
||||
if (btn.is('[data-shown]')) {
|
||||
hide();
|
||||
} else {
|
||||
show();
|
||||
}
|
||||
}
|
||||
|
||||
function isShown() {
|
||||
var btn = $('#toggle-sidebar-btn');
|
||||
return btn.is('[data-shown]');
|
||||
}
|
||||
|
||||
return Object.freeze({
|
||||
show: show,
|
||||
hide: hide,
|
||||
toggle: toggle,
|
||||
isShown: isShown
|
||||
})
|
||||
})();
|
||||
})(window);
|
|
@ -39,16 +39,18 @@ var SmartAnnotation = (function() {
|
|||
dataUrl: $(document.body).attr('data-atwho-project-url')},
|
||||
EXPERIMENT: {tag: "exp",
|
||||
dataUrl: $(document.body).attr('data-atwho-experiment-url')},
|
||||
SAMPLE: {tag: "sam",
|
||||
dataUrl: $(document.body).attr('data-atwho-sample-url')},
|
||||
REPOSITORY: {tag: "rep",
|
||||
dataUrl: $(document.body).attr('data-atwho-rep-items-url')},
|
||||
MENU: {tag: "menu",
|
||||
dataUrl: $(document.body).attr('data-atwho-menu-items')}
|
||||
});
|
||||
var prevAt,
|
||||
// Default selected filter when using '#'
|
||||
DEFAULT_SEARCH_FILTER = FilterTypeEnum.SAMPLE,
|
||||
DEFAULT_SEARCH_FILTER = FilterTypeEnum.REPOSITORY,
|
||||
atWhoUpdating = false;
|
||||
|
||||
var defaultRepId;
|
||||
|
||||
// helper methods for AtWho callback
|
||||
function _templateEval(_tpl, map) {
|
||||
var res;
|
||||
|
@ -109,7 +111,7 @@ var SmartAnnotation = (function() {
|
|||
}
|
||||
|
||||
// Initialize or update dropdown header buttons
|
||||
function updateHeaderButtons(query, filterTypeTag) {
|
||||
function updateHeaderButtons(query, filterType) {
|
||||
var $currentAtWho = $('.atwho-view[style]');
|
||||
initDismissButton($currentAtWho);
|
||||
|
||||
|
@ -117,15 +119,25 @@ var SmartAnnotation = (function() {
|
|||
$currentAtWho.find('[data-filter]')
|
||||
.removeClass('btn-primary')
|
||||
.addClass('btn-default');
|
||||
$currentAtWho.find('[data-filter="' + filterTypeTag + '"]')
|
||||
.removeClass('btn-default')
|
||||
.addClass('btn-primary');
|
||||
if(filterType.tag === 'rep') {
|
||||
$currentAtWho.find('[data-rep-id="' + filterType.repository_id + '"]')
|
||||
.removeClass('btn-default')
|
||||
.addClass('btn-primary');
|
||||
} else {
|
||||
$currentAtWho.find('[data-filter="' + filterType.tag + '"]')
|
||||
.removeClass('btn-default')
|
||||
.addClass('btn-primary');
|
||||
}
|
||||
|
||||
// Update the selected filter button when clicking on one of them
|
||||
$currentAtWho.find('[data-filter]').off()
|
||||
.on('click', function(e) {
|
||||
if($(this).hasClass('btn-primary')) {
|
||||
return;
|
||||
}
|
||||
var $selectedBtn = $(this);
|
||||
var $prevBtn = $selectedBtn.closest('.title').children('.btn-primary');
|
||||
var $prevBtn = $selectedBtn.closest('.atwho-header-res')
|
||||
.children('.btn-primary');
|
||||
$selectedBtn.removeClass('btn-default').addClass('btn-primary');
|
||||
$prevBtn.removeClass('btn-primary').addClass('btn-default');
|
||||
|
||||
|
@ -136,16 +148,31 @@ var SmartAnnotation = (function() {
|
|||
|
||||
// Generates suggestion dropdown filter
|
||||
function generateFilterMenu(active, res_data) {
|
||||
var rep_buttons = '';
|
||||
$.ajax({
|
||||
async: false,
|
||||
dataType: 'json',
|
||||
url: $(document.body).attr('data-atwho-repositories-url'),
|
||||
success: function(data) {
|
||||
$.each(data['repositories'], function(id, name) {
|
||||
if(defaultRepId === undefined){
|
||||
defaultRepId = id;
|
||||
}
|
||||
rep_buttons += '<button data-filter="rep" data-rep-id="' + id +
|
||||
'" class="btn btn-xs btn-primary">' + name + '</button>';
|
||||
});
|
||||
}
|
||||
});
|
||||
var header = '<div class="atwho-header-res">' +
|
||||
'<div class="title">' +
|
||||
'<button data-filter="prj" class="btn btn-xs ' +
|
||||
(active === 'prj' ? 'btn-primary' : 'btn-default') + '">project#</button>' +
|
||||
'<button data-filter="exp" class="btn btn-xs ' +
|
||||
(active === 'exp' ? 'btn-primary' : 'btn-default') + '">experiment#</button>' +
|
||||
'<button data-filter="tsk" class="btn btn-xs ' +
|
||||
(active === 'tsk' ? 'btn-primary' : 'btn-default') + '">task#</button>' +
|
||||
'<button data-filter="sam" class="btn btn-xs ' +
|
||||
(active === 'sam' ? 'btn-primary' : 'btn-default') + '">sample#</button>' +
|
||||
'<button data-filter="prj" class="btn btn-xs btn-primary' +
|
||||
'">Projects</button>' +
|
||||
'<button data-filter="exp" class="btn btn-xs btn-primary' +
|
||||
'">Experiments</button>' +
|
||||
'<button data-filter="tsk" class="btn btn-xs btn-primary' +
|
||||
'">Tasks</button>' +
|
||||
rep_buttons +
|
||||
'<div class="dismiss">' +
|
||||
'<span class="glyphicon glyphicon-remove"></span>' +
|
||||
'</div>' +
|
||||
'<div class="help">' +
|
||||
'<div>' +
|
||||
|
@ -159,9 +186,6 @@ var SmartAnnotation = (function() {
|
|||
'<strong><%= I18n.t("atwho.users.dismiss_1") %></strong> ' +
|
||||
'<%= I18n.t("atwho.users.dismiss_2") %>' +
|
||||
'</div>' +
|
||||
'<div class="dismiss">' +
|
||||
'<span class="glyphicon glyphicon-remove"></span>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
|
||||
|
@ -193,8 +217,9 @@ var SmartAnnotation = (function() {
|
|||
case 'exp':
|
||||
res += '<span data-type class="res-type">' + map.type + '</span>';
|
||||
break;
|
||||
case 'sam':
|
||||
res += '<span class="glyphicon glyphicon-tint"></span>';
|
||||
case 'rep_item':
|
||||
res += '<span data-type class="res-type">' +
|
||||
map.repository_tag + '</span>';
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -287,9 +312,21 @@ var SmartAnnotation = (function() {
|
|||
$currentAtWho.removeAttr("style");
|
||||
}
|
||||
|
||||
var params = { query: query };
|
||||
|
||||
if(filterType.tag === 'rep') {
|
||||
params.repository_id = $currentAtWho
|
||||
.find('.btn-primary')
|
||||
.data('rep-id');
|
||||
if(params.repository_id === undefined) {
|
||||
params.repository_id = defaultRepId;
|
||||
}
|
||||
filterType.repository_id = params.repository_id;
|
||||
}
|
||||
|
||||
$.getJSON(
|
||||
filterType.dataUrl,
|
||||
{query: query},
|
||||
params,
|
||||
function(data) {
|
||||
// Updates dropdown
|
||||
if (data.res.length < 1) {
|
||||
|
@ -298,7 +335,7 @@ var SmartAnnotation = (function() {
|
|||
callback(data.res);
|
||||
}
|
||||
|
||||
updateHeaderButtons(query, filterType.tag);
|
||||
updateHeaderButtons(query, filterType);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -389,7 +426,7 @@ var SmartAnnotation = (function() {
|
|||
},
|
||||
headerTpl:
|
||||
'<div class="atwho-header-res">' +
|
||||
'<div class="title title-user"><%= I18n.t("atwho.users.title") %></div>' +
|
||||
'<div class="title-user"><%= I18n.t("atwho.users.title") %></div>' +
|
||||
'<div class="help">' +
|
||||
'<div>' +
|
||||
'<strong><%= I18n.t("atwho.users.navigate_1") %></strong> ' +
|
||||
|
@ -403,21 +440,21 @@ var SmartAnnotation = (function() {
|
|||
'<strong><%= I18n.t("atwho.users.dismiss_1") %></strong> ' +
|
||||
'<%= I18n.t("atwho.users.dismiss_2") %>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'<div class="dismiss">' +
|
||||
'<span class="glyphicon glyphicon-remove"></span>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>',
|
||||
limit: <%= Constants::ATWHO_SEARCH_LIMIT %>,
|
||||
startsWithSpace: true,
|
||||
acceptSpaceBar: true,
|
||||
displayTimeout: 120000
|
||||
})
|
||||
.atwho(atWhoSettings('#', DEFAULT_SEARCH_FILTER));
|
||||
.atwho(atWhoSettings('#', DEFAULT_SEARCH_FILTER))
|
||||
// .atwho(atWhoSettings('task#', FilterTypeEnum.TASK)) Waiting for better times
|
||||
// .atwho(atWhoSettings('project#', FilterTypeEnum.PROJECT))
|
||||
// .atwho(atWhoSettings('experiment#', FilterTypeEnum.EXPERIMENT))
|
||||
// .atwho(atWhoSettings('sample#', FilterTypeEnum.SAMPLE));
|
||||
// .atwho(atWhoSettings('sample#', FilterTypeEnum.REPOSITORY));
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
@ -137,8 +137,8 @@
|
|||
html += 'placeholder="<%= I18n.t('assets.from_clipboard.file_name_placeholder') %>" aria-describedby="image-name">';
|
||||
html += '<span class="input-group-addon" id="image-name"></span></div>';
|
||||
html += '</div><div class="modal-footer">';
|
||||
html += '<button type="button" class="btn btn-primary" data-action="addImageFormClipboard"><%= I18n.t('assets.from_clipboard.add_image') %></button>';
|
||||
html += '<button type="button" class="btn btn-default" data-dismiss="modal"><%= I18n.t('general.cancel') %></button>'
|
||||
html += '<button type="button" class="btn btn-default" data-dismiss="modal"><%= I18n.t('general.cancel') %></button>';
|
||||
html += '<button type="button" class="btn btn-success" data-action="addImageFormClipboard"><%= I18n.t('assets.from_clipboard.add_image') %></button>';
|
||||
html += '</div></div></div></div><!-- /.modal -->';
|
||||
return $(html).appendTo($('body')).promise().done(function() {
|
||||
// display modal
|
||||
|
|
106
app/assets/javascripts/sitewide/file_preview.js.erb
Normal file
|
@ -0,0 +1,106 @@
|
|||
(function(global) {
|
||||
'use strict';
|
||||
|
||||
global.initPreviewModal = function initPreviewModal() {
|
||||
var name;
|
||||
var url;
|
||||
var downloadUrl;
|
||||
$('.file-preview-link').off('click');
|
||||
$('.file-preview-link').click(function(e) {
|
||||
e.preventDefault();
|
||||
name = $(this).find('p').text();
|
||||
url = $(this).data('preview-url');
|
||||
downloadUrl = $(this).attr('href');
|
||||
openPreviewModal(name, url, downloadUrl);
|
||||
});
|
||||
}
|
||||
|
||||
function openPreviewModal(name, url, downloadUrl) {
|
||||
var modal = $('#filePreviewModal');
|
||||
$.ajax({
|
||||
url: url,
|
||||
type: 'GET',
|
||||
dataType: 'json',
|
||||
success: function(data) {
|
||||
modal.find('.file-preview-container').empty();
|
||||
modal.find('.file-wopi-controls').empty();
|
||||
if (data.hasOwnProperty('wopi-controls')) {
|
||||
modal.find('.file-wopi-controls').html(data['wopi-controls']);
|
||||
}
|
||||
var link = modal.find('.file-download-link');
|
||||
link.attr('href', downloadUrl);
|
||||
link.attr('data-no-turbolink', true);
|
||||
link.attr('data-status', 'asset-present');
|
||||
if (data['type'] === 'image') {
|
||||
if(data['processing']) {
|
||||
animateSpinner('.file-preview-container', true);
|
||||
} else {
|
||||
animateSpinner('.file-preview-container', false);
|
||||
modal.find('.file-preview-container')
|
||||
.append($('<img>')
|
||||
.attr('src', data['large-preview-url'])
|
||||
.attr('alt', name)
|
||||
.click(function(ev) {
|
||||
ev.stopPropagation();
|
||||
})
|
||||
);
|
||||
}
|
||||
} else {
|
||||
modal.find('.file-preview-container').html(data['preview-icon']);
|
||||
}
|
||||
if(data['processing']) {
|
||||
checkFileReady(url, modal);
|
||||
}
|
||||
modal.find('.file-name').text(name);
|
||||
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
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function checkFileReady(url, modal) {
|
||||
$.get(url, function(data) {
|
||||
if(data['processing']) {
|
||||
$('.file-download-link')
|
||||
.addClass('disabled-with-click-events')
|
||||
.attr('title',
|
||||
'<%= I18n.t('general.file.processing')%>')
|
||||
.click(function(ev) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
});
|
||||
setTimeout(function() {
|
||||
checkFileReady(url, modal);
|
||||
}, 10000);
|
||||
} else {
|
||||
if(data['type'] === 'image') {
|
||||
modal.find('.file-preview-container').empty();
|
||||
modal.find('.file-preview-container')
|
||||
.append($('<img>')
|
||||
.attr('src', data['large-preview-url'])
|
||||
.attr('alt', data['filename'])
|
||||
.click(function(ev) {
|
||||
ev.stopPropagation();
|
||||
})
|
||||
);
|
||||
modal.find('.file-name').text(data['filename']);
|
||||
modal.find('.modal-body').click(function() {
|
||||
modal.modal('hide');
|
||||
});
|
||||
modal.modal();
|
||||
$('.modal-backdrop').last().css('z-index', modal.css('z-index') - 1);
|
||||
}
|
||||
$('.file-download-link')
|
||||
.removeClass('disabled-with-click-events')
|
||||
.removeAttr('title')
|
||||
.off();
|
||||
}
|
||||
})
|
||||
}
|
||||
})(window);
|
|
@ -1,48 +0,0 @@
|
|||
(function(global) {
|
||||
'use strict';
|
||||
|
||||
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);
|
44
app/assets/javascripts/sitewide/repository_row_info_modal.js
Normal file
|
@ -0,0 +1,44 @@
|
|||
(function() {
|
||||
'use strict';
|
||||
|
||||
$(document).on('click', '.record-info-link', function(e) {
|
||||
var that = $(this);
|
||||
$.ajax({
|
||||
method: 'GET',
|
||||
url: that.attr('href'),
|
||||
dataType: 'json'
|
||||
}).done(function(xhr, settings, data) {
|
||||
$('body').append($.parseHTML(data.responseJSON.html));
|
||||
$('#modal-info-repository-row').modal('show', {
|
||||
backdrop: true,
|
||||
keyboard: false
|
||||
}).on('hidden.bs.modal', function() {
|
||||
$(this).find('.modal-body #repository_row-info-table').DataTable().destroy();
|
||||
$(this).remove();
|
||||
});
|
||||
initPreviewModal();
|
||||
$('#repository_row-info-table').DataTable({
|
||||
dom: 'RBltpi',
|
||||
stateSave: false,
|
||||
buttons: [],
|
||||
processing: true,
|
||||
colReorder: {
|
||||
fixedColumnsLeft: 1000000 // Disable reordering
|
||||
},
|
||||
columnDefs: [{
|
||||
targets: 0,
|
||||
searchable: false,
|
||||
orderable: false
|
||||
}],
|
||||
fnDrawCallback: function(settings, json) {
|
||||
animateSpinner(this, false);
|
||||
},
|
||||
preDrawCallback: function(settings) {
|
||||
animateSpinner(this);
|
||||
}
|
||||
});
|
||||
});
|
||||
e.preventDefault();
|
||||
return false;
|
||||
});
|
||||
})();
|
|
@ -36,7 +36,6 @@ $(document).ready(function () {
|
|||
$("#hide-alert").click(function(ev) {
|
||||
$(this).closest("div.alert").addClass("alert-hidden");
|
||||
$("#content-wrapper").addClass("alert-hidden");
|
||||
$("#content-wrapper").removeClass("alert-shown");
|
||||
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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",
|
||||
|
@ -101,10 +75,10 @@
|
|||
for (var i = 0; i < notification_settings.length; i++ ) {
|
||||
var setting = $('[name="' + notification_settings[i] + '"]');
|
||||
var dependant = $('[name="' + notification_settings[i] + '_email"]');
|
||||
dependant.checkboxpicker({ onActiveCls: 'btn-primary' });
|
||||
dependant.checkboxpicker({ onActiveCls: 'btn-toggle', offActiveCls: 'btn-toggle' });
|
||||
setting
|
||||
.checkboxpicker({
|
||||
onActiveCls: 'btn-primary'
|
||||
onActiveCls: 'btn-toggle', offActiveCls: 'btn-toggle'
|
||||
}).change(function() {
|
||||
if ( $(this).prop('checked') ) {
|
||||
enableDependant($('[name="' + $(this).attr('name') + '_email"]'));
|
||||
|
@ -126,7 +100,7 @@
|
|||
function setEmailSwitch(setting) {
|
||||
setting
|
||||
.checkboxpicker({
|
||||
onActiveCls: 'btn-primary'
|
||||
onActiveCls: 'btn-toggle', offActiveCls: 'btn-toggle'
|
||||
});
|
||||
if ( setting.attr('value') === 'true' ) {
|
||||
setting.prop('checked', true);
|
||||
|
@ -149,7 +123,7 @@
|
|||
var system_message_notification = $('[name="system_message_notification"]');
|
||||
system_message_notification
|
||||
.checkboxpicker({
|
||||
onActiveCls: 'btn-primary'
|
||||
onActiveCls: 'btn-toggle', offActiveCls: 'btn-toggle'
|
||||
});
|
||||
system_message_notification.prop('checked', true);
|
||||
system_message_notification.prop('disabled', true);
|
||||
|
@ -158,7 +132,7 @@
|
|||
var system_message_notification_mail = $('[name="system_message_notification_email"]');
|
||||
system_message_notification_mail
|
||||
.checkboxpicker({
|
||||
onActiveCls: 'btn-primary'
|
||||
onActiveCls: 'btn-toggle', offActiveCls: 'btn-toggle'
|
||||
});
|
||||
system_message_notification_mail.prop(
|
||||
'checked',
|
||||
|
|
18
app/assets/javascripts/users/settings/list_toggle.js.erb
Normal file
|
@ -0,0 +1,18 @@
|
|||
(function() {
|
||||
'use strict';
|
||||
|
||||
$(".tree li.parent_li ").find("> span i").on("click", function (e) {
|
||||
e.stopPropagation();
|
||||
var el = $(this).closest("li.parent_li");
|
||||
|
||||
if (el.find(" > ul.accountNavigation").is(":visible")) {
|
||||
el.find(" > span > i.triangleDown").hide();
|
||||
el.find(" > span > i.triangleRight").show();
|
||||
el.find(" > ul.accountNavigation").hide();
|
||||
} else {
|
||||
el.find(" > span > i.triangleDown").show();
|
||||
el.find(" > span > i.triangleRight").hide();
|
||||
el.find(" > ul.accountNavigation").show();
|
||||
}
|
||||
});
|
||||
})();
|
|
@ -120,7 +120,10 @@ function initUsersTable() {
|
|||
{ data: "3" },
|
||||
{ data: "4" },
|
||||
{ data: "5" }
|
||||
]
|
||||
],
|
||||
oLanguage: {
|
||||
sSearch: I18n.t('general.filter')
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -6,9 +6,10 @@
|
|||
*= require rails_bootstrap_forms
|
||||
*= require bootstrap-select
|
||||
*= require constants
|
||||
*= require introjs
|
||||
*= stub reports_pdf
|
||||
*/
|
||||
|
||||
@import "constants";
|
||||
@import "bootstrap-sprockets";
|
||||
@import "bootstrap";
|
||||
@import "bootstrap-datetimepicker";
|
||||
|
@ -16,6 +17,6 @@
|
|||
@import "bootstrap-tagsinput";
|
||||
@import "bootstrap-tagsinput-typeahead";
|
||||
@import "handsontable.full.min";
|
||||
@import "ajax-bootstrap-select.min";
|
||||
@import "extend/bootstrap";
|
||||
@import "font-awesome";
|
||||
@import "themes/scinote";
|
||||
|
|
|
@ -1,51 +1,35 @@
|
|||
@import url(https://fonts.googleapis.com/css?family=Open+Sans:400,600,700,400italic&subset=latin,latin-ext);
|
||||
|
||||
//==============================================================================
|
||||
// Colors
|
||||
//==============================================================================
|
||||
|
||||
// Theme colors
|
||||
$color-theme-primary: #37a0d9;
|
||||
$color-theme-secondary: #8fd13f;
|
||||
$color-theme-dark: #6d6e71;
|
||||
|
||||
// Grayscale colors
|
||||
$color-white: #fff;
|
||||
$color-alabaster: #fcfcfc;
|
||||
$color-snow: #f9f9f9;
|
||||
$color-wild-sand: #f5f5f5;
|
||||
$color-concrete: #f2f2f2;
|
||||
$color-gallery: #eee;
|
||||
$color-gainsboro: #e3e3e3;
|
||||
$color-alto: #d2d2d2;
|
||||
$color-silver: #c5c5c5;
|
||||
$color-dark-gray: #adadad;
|
||||
$color-silver-chalice: #a0a0a0;
|
||||
$color-gray: #909088;
|
||||
$color-dove-gray: #666;
|
||||
$color-emperor: #555;
|
||||
$color-mine-shaft: #333;
|
||||
$color-nero: #262626;
|
||||
$color-black: #000;
|
||||
$color-cloud: rgba(0, 0, 0, .1);
|
||||
$color-gray-light-yadcf: #ccc;
|
||||
$color-gray-dark-yadcf: #a9a9a9;
|
||||
|
||||
// Miscelaneous colors
|
||||
$color-mystic: #eaeff2;
|
||||
$color-candlelight: #ffda23;
|
||||
$color-orange: #ff900b;
|
||||
$color-saturated-green: #008600;
|
||||
$color-blue-yadcf: #337ab7;
|
||||
// Theme colors
|
||||
$brand-default: $color-white;
|
||||
$brand-primary: #37a0d9;
|
||||
$brand-success: #2dbe61;
|
||||
$brand-info: #5bc0de;
|
||||
$brand-warning: #f0ad4e;
|
||||
$brand-danger: #e54e42;
|
||||
$brand-other: #8fd13f;
|
||||
$brand-extra: #34495e;
|
||||
$brand-primary-light: #dcedf6;
|
||||
$brand-success-light: #e2eed8;
|
||||
$brand-warning-light: #fcf7e4;
|
||||
$brand-danger-light: #efdfdf;
|
||||
|
||||
// Red colors
|
||||
$color-mojo: #cf4b48;
|
||||
$color-apple-blossom: #a94442;
|
||||
$color-milano-red: #a70b05;
|
||||
|
||||
// Colors for specific intents
|
||||
$color-visited-link: #23527c;
|
||||
|
||||
// Overlay shade for drag'n dropdown
|
||||
$color-drag-overlay: rgba(0, 0, 0, .4);
|
||||
|
||||
//==============================================================================
|
||||
// Other
|
||||
|
@ -53,3 +37,460 @@ $color-drag-overlay: rgba(0, 0, 0, .4);
|
|||
|
||||
// Some big value which is still supported by all browsers
|
||||
$infinity: 9999999;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// Bootstrap
|
||||
//==============================================================================
|
||||
|
||||
// Grayscale Colors in bootstrap
|
||||
$gray-darker: $color-black;
|
||||
$gray-dark: $color-emperor;
|
||||
$gray: $color-emperor;
|
||||
$gray-light: $color-dove-gray;
|
||||
$gray-lighter: $color-concrete;
|
||||
|
||||
// Scaffolding
|
||||
$body-bg: $color-concrete;
|
||||
$text-color: $color-emperor;
|
||||
$link-color: $brand-primary;
|
||||
$link-hover-color: darken($link-color, 15%);
|
||||
$link-hover-decoration: underline;
|
||||
|
||||
// Typography
|
||||
$font-family-lato: lato, "Open Sans", Arial, Helvetica, sans-serif;
|
||||
$font-family-sans-serif: "Open Sans", Arial, Helvetica, sans-serif;
|
||||
$font-family-serif: Georgia, "Times New Roman", Times, serif;
|
||||
$font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace;
|
||||
$font-family-base: $font-family-lato;
|
||||
$font-size-base: 14px;
|
||||
$font-size-large: ceil(($font-size-base * 1.1)); //16px
|
||||
$font-size-small: ceil(($font-size-base * .9)); //13px
|
||||
$font-size-h1: floor(($font-size-base * 2.6)); //36px
|
||||
$font-size-h2: floor(($font-size-base * 2.15)); //30px
|
||||
$font-size-h3: ceil(($font-size-base * 1.7)); //24px
|
||||
$font-size-h4: ceil(($font-size-base * 1.25)); //18px
|
||||
$font-size-h5: $font-size-base; //14px
|
||||
$font-size-h6: ceil(($font-size-base * .85)); //12px
|
||||
$line-height-base: 1.428571429;
|
||||
$line-height-computed: floor(($font-size-base * $line-height-base));
|
||||
$headings-font-family: inherit;
|
||||
$headings-font-weight: 500;
|
||||
$headings-line-height: 1.1;
|
||||
$headings-color: inherit;
|
||||
|
||||
// // Iconography
|
||||
// $icon-font-path: "../fonts/";
|
||||
// $icon-font-name: "glyphicons-halflings-regular";
|
||||
// $icon-font-svg-id: "glyphicons_halflingsregular";
|
||||
|
||||
// Components
|
||||
$padding-base-vertical: 6px;
|
||||
$padding-base-horizontal: 12px;
|
||||
$padding-large-vertical: 10px;
|
||||
$padding-large-horizontal: 16px;
|
||||
$padding-small-vertical: 5px;
|
||||
$padding-small-horizontal: 10px;
|
||||
$padding-xs-vertical: 1px;
|
||||
$padding-xs-horizontal: 5px;
|
||||
$line-height-large: 1.3333333;
|
||||
$line-height-small: 1.5;
|
||||
$border-radius-base: 4px;
|
||||
$border-radius-large: 6px;
|
||||
$border-radius-small: 3px;
|
||||
$component-active-color: $color-white;
|
||||
$component-active-bg: $brand-primary;
|
||||
$caret-width-base: 4px;
|
||||
$caret-width-large: 5px;
|
||||
|
||||
// // Tables
|
||||
// $table-cell-padding: 8px;
|
||||
// $table-condensed-cell-padding: 5px;
|
||||
// $table-bg: transparent;
|
||||
// $table-bg-accent: #f9f9f9;
|
||||
// $table-bg-hover: #f5f5f5;
|
||||
// $table-bg-active: $table-bg-hover;
|
||||
// $table-border-color: #ddd;
|
||||
|
||||
// Buttons
|
||||
$btn-font-weight: normal;
|
||||
$btn-default-color: $gray-dark;
|
||||
$btn-default-bg: $brand-default;
|
||||
$btn-default-border: $color-silver;
|
||||
$btn-primary-color: $color-white;
|
||||
$btn-primary-bg: $brand-success;
|
||||
$btn-primary-border: darken($btn-primary-bg, 5%);
|
||||
$btn-success-color: $color-white;
|
||||
$btn-success-bg: $brand-success;
|
||||
$btn-success-border: darken($btn-success-bg, 5%);
|
||||
$btn-info-color: $color-white;
|
||||
$btn-info-bg: $brand-info;
|
||||
$btn-info-border: darken($btn-info-bg, 5%);
|
||||
$btn-warning-color: $color-white;
|
||||
$btn-warning-bg: $brand-warning;
|
||||
$btn-warning-border: darken($btn-warning-bg, 5%);
|
||||
$btn-danger-color: $color-white;
|
||||
$btn-danger-bg: $brand-danger;
|
||||
$btn-danger-border: darken($btn-danger-bg, 5%);
|
||||
$btn-toggle-color: $color-white;
|
||||
$btn-toggle-bg: $brand-primary;
|
||||
$btn-toggle-border: darken($btn-toggle-bg, 5%);
|
||||
$btn-link-disabled-color: $gray-light;
|
||||
$btn-border-radius-base: $border-radius-base;
|
||||
$btn-border-radius-large: $border-radius-large;
|
||||
$btn-border-radius-small: $border-radius-small;
|
||||
|
||||
// // Forms
|
||||
// $input-bg: #fff;
|
||||
// $input-bg-disabled: $gray-lighter;
|
||||
// $input-color: $gray;
|
||||
// $input-border: #ccc;
|
||||
// $input-border-radius: $border-radius-base;
|
||||
// $input-border-radius-large: $border-radius-large;
|
||||
// $input-border-radius-small: $border-radius-small;
|
||||
// $input-border-focus: #66afe9;
|
||||
// $input-color-placeholder: #999;
|
||||
// $input-height-base: ($line-height-computed + ($padding-base-vertical * 2) + 2);
|
||||
// $input-height-large: (ceil($font-size-large * $line-height-large) + ($padding-large-vertical * 2) + 2);
|
||||
// $input-height-small: (floor($font-size-small * $line-height-small) + ($padding-small-vertical * 2) + 2);
|
||||
// $form-group-margin-bottom: 15px;
|
||||
// $legend-color: $gray-dark;
|
||||
// $legend-border-color: #e5e5e5;
|
||||
// $input-group-addon-bg: $gray-lighter;
|
||||
// $input-group-addon-border-color: $input-border;
|
||||
// $cursor-disabled: not-allowed;
|
||||
//
|
||||
// // Dropdowns
|
||||
// $dropdown-bg: #fff;
|
||||
// $dropdown-border: rgba(0,0,0,.15);
|
||||
// $dropdown-fallback-border: #ccc;
|
||||
// $dropdown-divider-bg: #e5e5e5;
|
||||
// $dropdown-link-color: $gray-dark;
|
||||
// $dropdown-link-hover-color: darken($gray-dark, 5%);
|
||||
// $dropdown-link-hover-bg: #f5f5f5;
|
||||
// $dropdown-link-active-color: $component-active-color;
|
||||
// $dropdown-link-active-bg: $component-active-bg;
|
||||
// $dropdown-link-disabled-color: $gray-light;
|
||||
// $dropdown-header-color: $gray-light;
|
||||
// $dropdown-caret-color: #000;
|
||||
//
|
||||
// // Media queries breakpoints
|
||||
// $screen-xs: 480px;
|
||||
// $screen-xs-min: $screen-xs;
|
||||
// $screen-phone: $screen-xs-min;
|
||||
// $screen-sm: 768px;
|
||||
// $screen-sm-min: $screen-sm;
|
||||
// $screen-tablet: $screen-sm-min;
|
||||
// $screen-md: 992px;
|
||||
// $screen-md-min: $screen-md;
|
||||
// $screen-desktop: $screen-md-min;
|
||||
// $screen-lg: 1200px;
|
||||
// $screen-lg-min: $screen-lg;
|
||||
// $screen-lg-desktop: $screen-lg-min;
|
||||
// $screen-xs-max: ($screen-sm-min - 1);
|
||||
// $screen-sm-max: ($screen-md-min - 1);
|
||||
// $screen-md-max: ($screen-lg-min - 1);
|
||||
//
|
||||
// // Grid system
|
||||
// $grid-columns: 12;
|
||||
// $grid-gutter-width: 30px;
|
||||
// $grid-float-breakpoint: $screen-sm-min;
|
||||
// $grid-float-breakpoint-max: ($grid-float-breakpoint - 1);
|
||||
|
||||
// Container sizes
|
||||
$container-tablet: auto;
|
||||
$container-sm: auto;
|
||||
$container-desktop: auto;
|
||||
$container-md: auto;
|
||||
$container-large-desktop: auto;
|
||||
$container-lg: auto;
|
||||
|
||||
// // Navbar
|
||||
// $navbar-height: 50px;
|
||||
// $navbar-margin-bottom: $line-height-computed;
|
||||
// $navbar-border-radius: $border-radius-base;
|
||||
// $navbar-padding-horizontal: floor(($grid-gutter-width / 2));
|
||||
// $navbar-padding-vertical: (($navbar-height - $line-height-computed) / 2);
|
||||
// $navbar-collapse-max-height: 340px;
|
||||
// $navbar-default-color: #777;
|
||||
// $navbar-default-bg: #f8f8f8;
|
||||
// $navbar-default-border: darken($navbar-default-bg, 6.5%);
|
||||
// $navbar-default-link-color: #777;
|
||||
// $navbar-default-link-hover-color: #333;
|
||||
// $navbar-default-link-hover-bg: transparent;
|
||||
// $navbar-default-link-active-color: #555;
|
||||
// $navbar-default-link-active-bg: darken($navbar-default-bg, 6.5%);
|
||||
// $navbar-default-link-disabled-color: #ccc;
|
||||
// $navbar-default-link-disabled-bg: transparent;
|
||||
// $navbar-default-brand-color: $navbar-default-link-color;
|
||||
// $navbar-default-brand-hover-color: darken($navbar-default-brand-color, 10%);
|
||||
// $navbar-default-brand-hover-bg: transparent;
|
||||
// $navbar-default-toggle-hover-bg: #ddd;
|
||||
// $navbar-default-toggle-icon-bar-bg: #888;
|
||||
// $navbar-default-toggle-border-color: #ddd;
|
||||
//
|
||||
// // Inverted navbar
|
||||
// $navbar-inverse-color: lighten($gray-light, 15%);
|
||||
// $navbar-inverse-bg: #222;
|
||||
// $navbar-inverse-border: darken($navbar-inverse-bg, 10%);
|
||||
// $navbar-inverse-link-color: lighten($gray-light, 15%);
|
||||
// $navbar-inverse-link-hover-color: #fff;
|
||||
// $navbar-inverse-link-hover-bg: transparent;
|
||||
// $navbar-inverse-link-active-color: $navbar-inverse-link-hover-color;
|
||||
// $navbar-inverse-link-active-bg: darken($navbar-inverse-bg, 10%);
|
||||
// $navbar-inverse-link-disabled-color: #444;
|
||||
// $navbar-inverse-link-disabled-bg: transparent;
|
||||
// $navbar-inverse-brand-color: $navbar-inverse-link-color;
|
||||
// $navbar-inverse-brand-hover-color: #fff;
|
||||
// $navbar-inverse-brand-hover-bg: transparent;
|
||||
// $navbar-inverse-toggle-hover-bg: #333;
|
||||
// $navbar-inverse-toggle-icon-bar-bg: #fff;
|
||||
// $navbar-inverse-toggle-border-color: #333;
|
||||
//
|
||||
// // Navs
|
||||
// $nav-link-padding: 10px 15px;
|
||||
// $nav-link-hover-bg: $gray-lighter;
|
||||
// $nav-disabled-link-color: $gray-light;
|
||||
// $nav-disabled-link-hover-color: $gray-light;
|
||||
//
|
||||
// // Tabs
|
||||
// $nav-tabs-border-color: #ddd;
|
||||
// $nav-tabs-link-hover-border-color: $gray-lighter;
|
||||
// $nav-tabs-active-link-hover-bg: $body-bg;
|
||||
// $nav-tabs-active-link-hover-color: $gray;
|
||||
// $nav-tabs-active-link-hover-border-color: #ddd;
|
||||
// $nav-tabs-justified-link-border-color: #ddd;
|
||||
// $nav-tabs-justified-active-link-border-color: $body-bg;
|
||||
//
|
||||
// // Pills
|
||||
// $nav-pills-border-radius: $border-radius-base;
|
||||
// $nav-pills-active-link-hover-bg: $component-active-bg;
|
||||
// $nav-pills-active-link-hover-color: $component-active-color;
|
||||
//
|
||||
// // Pagination
|
||||
// $pagination-color: $link-color;
|
||||
// $pagination-bg: #fff;
|
||||
// $pagination-border: #ddd;
|
||||
// $pagination-hover-color: $link-hover-color;
|
||||
// $pagination-hover-bg: $gray-lighter;
|
||||
// $pagination-hover-border: #ddd;
|
||||
// $pagination-active-color: #fff;
|
||||
// $pagination-active-bg: $brand-primary;
|
||||
// $pagination-active-border: $brand-primary;
|
||||
// $pagination-disabled-color: $gray-light;
|
||||
// $pagination-disabled-bg: #fff;
|
||||
// $pagination-disabled-border: #ddd;
|
||||
//
|
||||
// // Pager
|
||||
// $pager-bg: $pagination-bg;
|
||||
// $pager-border: $pagination-border;
|
||||
// $pager-border-radius: 15px;
|
||||
// $pager-hover-bg: $pagination-hover-bg;
|
||||
// $pager-active-bg: $pagination-active-bg;
|
||||
// $pager-active-color: $pagination-active-color;
|
||||
// $pager-disabled-color: $pagination-disabled-color;
|
||||
//
|
||||
// // Jumbotron
|
||||
// $jumbotron-padding: 30px;
|
||||
// $jumbotron-color: inherit;
|
||||
// $jumbotron-bg: $gray-lighter;
|
||||
// $jumbotron-heading-color: inherit;
|
||||
// $jumbotron-font-size: ceil(($font-size-base * 1.5));
|
||||
// $jumbotron-heading-font-size: ceil(($font-size-base * 4.5));
|
||||
|
||||
// Form states and alerts
|
||||
$state-success-text: #3c763d;
|
||||
$state-success-bg: #d5f2df;
|
||||
$state-success-border: adjust-hue(darken($state-success-bg, 5%), -10);
|
||||
$state-info-text: #31708f;
|
||||
$state-info-bg: #d7ecf7;
|
||||
$state-info-border: adjust-hue(darken($state-info-bg, 7%), -10);
|
||||
$state-warning-text: #8a6d3b;
|
||||
$state-warning-bg: #fcf8e3;
|
||||
$state-warning-border: adjust-hue(darken($state-warning-bg, 5%), -10);
|
||||
$state-danger-text: #a94442;
|
||||
$state-danger-bg: #fadcd9;
|
||||
$state-danger-border: adjust-hue(darken($state-danger-bg, 5%), -10);
|
||||
|
||||
// // Tooltips
|
||||
// $tooltip-max-width: 200px;
|
||||
// $tooltip-color: #fff;
|
||||
// $tooltip-bg: #000;
|
||||
// $tooltip-opacity: .9;
|
||||
// $tooltip-arrow-width: 5px;
|
||||
// $tooltip-arrow-color: $tooltip-bg;
|
||||
//
|
||||
// // Popovers
|
||||
// $popover-bg: #fff;
|
||||
// $popover-max-width: 276px;
|
||||
// $popover-border-color: rgba(0,0,0,.2);
|
||||
// $popover-fallback-border-color: #ccc;
|
||||
// $popover-title-bg: darken($popover-bg, 3%);
|
||||
// $popover-arrow-width: 10px;
|
||||
// $popover-arrow-color: $popover-bg;
|
||||
// $popover-arrow-outer-width: ($popover-arrow-width + 1);
|
||||
// $popover-arrow-outer-color: fadein($popover-border-color, 5%);
|
||||
// $popover-arrow-outer-fallback-color: darken($popover-fallback-border-color, 20%);
|
||||
//
|
||||
// // Labels
|
||||
// $label-default-bg: $gray-light;
|
||||
// $label-primary-bg: $brand-primary;
|
||||
// $label-success-bg: $brand-success;
|
||||
// $label-info-bg: $brand-info;
|
||||
// $label-warning-bg: $brand-warning;
|
||||
// $label-danger-bg: $brand-danger;
|
||||
// $label-color: #fff;
|
||||
// $label-link-hover-color: #fff;
|
||||
//
|
||||
// // Modals
|
||||
// $modal-inner-padding: 15px;
|
||||
// $modal-title-padding: 15px;
|
||||
// $modal-title-line-height: $line-height-base;
|
||||
// $modal-content-bg: #fff;
|
||||
// $modal-content-border-color: rgba(0,0,0,.2);
|
||||
// $modal-content-fallback-border-color: #999;
|
||||
// $modal-backdrop-bg: #000;
|
||||
// $modal-backdrop-opacity: .5;
|
||||
// $modal-header-border-color: #e5e5e5;
|
||||
// $modal-footer-border-color: $modal-header-border-color;
|
||||
// $modal-lg: 900px;
|
||||
// $modal-md: 600px;
|
||||
// $modal-sm: 300px;
|
||||
//
|
||||
// // Alerts
|
||||
// $alert-padding: 15px;
|
||||
// $alert-border-radius: $border-radius-base;
|
||||
// $alert-link-font-weight: bold;
|
||||
// $alert-success-bg: $state-success-bg;
|
||||
// $alert-success-text: $state-success-text;
|
||||
// $alert-success-border: $state-success-border;
|
||||
// $alert-info-bg: $state-info-bg;
|
||||
// $alert-info-text: $state-info-text;
|
||||
// $alert-info-border: $state-info-border;
|
||||
// $alert-warning-bg: $state-warning-bg;
|
||||
// $alert-warning-text: $state-warning-text;
|
||||
// $alert-warning-border: $state-warning-border;
|
||||
// $alert-danger-bg: $state-danger-bg;
|
||||
// $alert-danger-text: $state-danger-text;
|
||||
// $alert-danger-border: $state-danger-border;
|
||||
//
|
||||
// // Progress bars
|
||||
// $progress-bg: #f5f5f5;
|
||||
// $progress-bar-color: #fff;
|
||||
// $progress-border-radius: $border-radius-base;
|
||||
// $progress-bar-bg: $brand-primary;
|
||||
// $progress-bar-success-bg: $brand-success;
|
||||
// $progress-bar-warning-bg: $brand-warning;
|
||||
// $progress-bar-danger-bg: $brand-danger;
|
||||
// $progress-bar-info-bg: $brand-info;
|
||||
//
|
||||
// // List group
|
||||
// $list-group-bg: #fff;
|
||||
// $list-group-border: #ddd;
|
||||
// $list-group-border-radius: $border-radius-base;
|
||||
// $list-group-hover-bg: #f5f5f5;
|
||||
// $list-group-active-color: $component-active-color;
|
||||
// $list-group-active-bg: $component-active-bg;
|
||||
// $list-group-active-border: $list-group-active-bg;
|
||||
// $list-group-active-text-color: lighten($list-group-active-bg, 40%);
|
||||
// $list-group-disabled-color: $gray-light;
|
||||
// $list-group-disabled-bg: $gray-lighter;
|
||||
// $list-group-disabled-text-color: $list-group-disabled-color;
|
||||
// $list-group-link-color: #555;
|
||||
// $list-group-link-hover-color: $list-group-link-color;
|
||||
// $list-group-link-heading-color: #333;
|
||||
//
|
||||
// // Panels
|
||||
// $panel-bg: #fff;
|
||||
// $panel-body-padding: 15px;
|
||||
// $panel-heading-padding: 10px 15px;
|
||||
// $panel-footer-padding: $panel-heading-padding;
|
||||
// $panel-border-radius: $border-radius-base;
|
||||
// $panel-inner-border: #ddd;
|
||||
// $panel-footer-bg: #f5f5f5;
|
||||
// $panel-default-text: $gray-dark;
|
||||
// $panel-default-border: #ddd;
|
||||
// $panel-default-heading-bg: #f5f5f5;
|
||||
// $panel-primary-text: #fff;
|
||||
// $panel-primary-border: $brand-primary;
|
||||
// $panel-primary-heading-bg: $brand-primary;
|
||||
// $panel-success-text: $state-success-text;
|
||||
// $panel-success-border: $state-success-border;
|
||||
// $panel-success-heading-bg: $state-success-bg;
|
||||
// $panel-info-text: $state-info-text;
|
||||
// $panel-info-border: $state-info-border;
|
||||
// $panel-info-heading-bg: $state-info-bg;
|
||||
// $panel-warning-text: $state-warning-text;
|
||||
// $panel-warning-border: $state-warning-border;
|
||||
// $panel-warning-heading-bg: $state-warning-bg;
|
||||
// $panel-danger-text: $state-danger-text;
|
||||
// $panel-danger-border: $state-danger-border;
|
||||
// $panel-danger-heading-bg: $state-danger-bg;
|
||||
//
|
||||
// // Thumbnails
|
||||
// $thumbnail-padding: 4px;
|
||||
// $thumbnail-bg: $body-bg;
|
||||
// $thumbnail-border: #ddd;
|
||||
// $thumbnail-border-radius: $border-radius-base;
|
||||
// $thumbnail-caption-color: $text-color;
|
||||
// $thumbnail-caption-padding: 9px;
|
||||
//
|
||||
// // Wells
|
||||
// $well-bg: #f5f5f5;
|
||||
// $well-border: darken($well-bg, 7%);
|
||||
//
|
||||
// // Badges
|
||||
// $badge-color: #fff;
|
||||
// $badge-link-hover-color: #fff;
|
||||
// $badge-bg: $gray-light;
|
||||
// $badge-active-color: $link-color;
|
||||
// $badge-active-bg: #fff;
|
||||
// $badge-font-weight: bold;
|
||||
// $badge-line-height: 1;
|
||||
// $badge-border-radius: 10px;
|
||||
//
|
||||
// // Breadcrumbs
|
||||
// $breadcrumb-padding-vertical: 8px;
|
||||
// $breadcrumb-padding-horizontal: 15px;
|
||||
// $breadcrumb-bg: #f5f5f5;
|
||||
// $breadcrumb-color: #ccc;
|
||||
// $breadcrumb-active-color: $gray-light;
|
||||
// $breadcrumb-separator: "/";
|
||||
//
|
||||
// // Carousel
|
||||
// $carousel-text-shadow: 0 1px 2px rgba(0,0,0,.6);
|
||||
// $carousel-control-color: #fff;
|
||||
// $carousel-control-width: 15%;
|
||||
// $carousel-control-opacity: .5;
|
||||
// $carousel-control-font-size: 20px;
|
||||
// $carousel-indicator-active-bg: #fff;
|
||||
// $carousel-indicator-border-color: #fff;
|
||||
// $carousel-caption-color: #fff;
|
||||
//
|
||||
// // Close
|
||||
// $close-font-weight: bold;
|
||||
// $close-color: #000;
|
||||
// $close-text-shadow: 0 1px 0 #fff;
|
||||
//
|
||||
// // Code
|
||||
// $code-color: #c7254e;
|
||||
// $code-bg: #f9f2f4;
|
||||
// $kbd-color: #fff;
|
||||
// $kbd-bg: #333;
|
||||
// $pre-bg: #f5f5f5;
|
||||
// $pre-color: $gray-dark;
|
||||
// $pre-border-color: #ccc;
|
||||
// $pre-scrollable-max-height: 340px;
|
||||
//
|
||||
// // Type
|
||||
// $component-offset-horizontal: 180px;
|
||||
// $text-muted: $gray-light;
|
||||
// $abbr-border-color: $gray-light;
|
||||
// $headings-small-color: $gray-light;
|
||||
// $blockquote-small-color: $gray-light;
|
||||
// $blockquote-font-size: ($font-size-base * 1.25);
|
||||
// $blockquote-border-color: $gray-lighter;
|
||||
// $page-header-border-color: $gray-lighter;
|
||||
// $dl-horizontal-offset: $component-offset-horizontal;
|
||||
// $dl-horizontal-breakpoint: $grid-float-breakpoint;
|
||||
// $hr-border: $gray-lighter;
|
||||
|
|
4
app/assets/stylesheets/extend/bootstrap.scss
vendored
|
@ -14,7 +14,7 @@
|
|||
|
||||
// Active tab with error should retain error color if clicked on again
|
||||
.nav-tabs > li.active.has-error > a {
|
||||
color: $color-apple-blossom;
|
||||
color: $brand-danger;
|
||||
}
|
||||
|
||||
@media (max-width: 886px) {
|
||||
|
@ -58,7 +58,7 @@
|
|||
float: none;
|
||||
}
|
||||
|
||||
@media (max-width: 1000px) {
|
||||
@media (max-width: 1188px) {
|
||||
.navbar-header {
|
||||
float: none;
|
||||
}
|
||||
|
|
|
@ -8,15 +8,15 @@
|
|||
.task-due-date,
|
||||
.task-state-label {
|
||||
.alert-green {
|
||||
color: $color-saturated-green;
|
||||
color: $brand-success;
|
||||
}
|
||||
|
||||
.alert-yellow {
|
||||
color: $color-candlelight;
|
||||
color: $brand-warning;
|
||||
}
|
||||
|
||||
.alert-red {
|
||||
color: $color-milano-red;
|
||||
color: $brand-danger;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
padding-top: 10px;
|
||||
|
||||
&:hover {
|
||||
background-color: $color-mystic;
|
||||
background-color: $color-gainsboro;
|
||||
}
|
||||
|
||||
&.no-notifications {
|
||||
|
@ -40,7 +40,7 @@
|
|||
}
|
||||
|
||||
.unseen {
|
||||
border-left: 4px solid $color-theme-primary;
|
||||
border-left: 4px solid $brand-primary;
|
||||
}
|
||||
|
||||
.text-center {
|
||||
|
@ -49,54 +49,39 @@
|
|||
}
|
||||
|
||||
.assignment {
|
||||
background-color: $color-theme-primary;
|
||||
background-color: $brand-primary;
|
||||
border-radius: 50%;
|
||||
color: $color-wild-sand;
|
||||
color: $color-concrete;
|
||||
display: inline-block;
|
||||
font-size: 13px;
|
||||
font-size: $font-size-small;
|
||||
height: 30px;
|
||||
padding-top: 5px;
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
.system-message {
|
||||
background-color: $color-theme-secondary;
|
||||
background-color: $brand-success;
|
||||
border-radius: 50%;
|
||||
color: $color-wild-sand;
|
||||
color: $color-concrete;
|
||||
display: inline-block;
|
||||
font-size: 13px;
|
||||
font-size: $font-size-small;
|
||||
height: 30px;
|
||||
padding-top: 5px;
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
.deliver {
|
||||
background-color: $color-orange;
|
||||
background-color: $brand-warning;
|
||||
border-radius: 50%;
|
||||
color: $color-wild-sand;
|
||||
color: $color-concrete;
|
||||
display: inline-block;
|
||||
font-size: 13px;
|
||||
font-size: $font-size-small;
|
||||
height: 30px;
|
||||
padding-top: 5px;
|
||||
width: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.notifications-footer {
|
||||
|
||||
background-color: $color-mystic;
|
||||
|
||||
.btn-more-notifications {
|
||||
border-bottom: 1px solid $color-alto;
|
||||
border-left: 1px solid $color-alto;
|
||||
border-right: 1px solid $color-alto;
|
||||
margin: 0;
|
||||
padding: 8px;
|
||||
text-align: center;
|
||||
|
||||
&:hover {
|
||||
background-color: $color-mystic;
|
||||
}
|
||||
}
|
||||
.btn-more-notifications {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
|
|
@ -22,71 +22,26 @@ $toggle-btn-size: 50px;
|
|||
transition: all 0.5s ease;
|
||||
|
||||
#sidebar-wrapper {
|
||||
background-color: $color-alto;
|
||||
z-index: 1000;
|
||||
position: fixed;
|
||||
width: $wrapper-width;
|
||||
left: $wrapper-width;
|
||||
background-color: $color-white;
|
||||
box-shadow: 1px 3px 6px $color-alto;
|
||||
height: 100%;
|
||||
margin-left: -$wrapper-width;
|
||||
-webkit-transition: all 0.5s ease;
|
||||
position: fixed;
|
||||
-moz-transition: all 0.5s ease;
|
||||
-o-transition: all 0.5s ease;
|
||||
-webkit-transition: all 0.5s ease;
|
||||
transition: all 0.5s ease;
|
||||
width: $wrapper-width;
|
||||
z-index: 999;
|
||||
|
||||
#slide-panel {
|
||||
height: 100%;
|
||||
|
||||
.sidebar-header {
|
||||
height: $toggle-btn-size;
|
||||
background: $color-theme-primary;
|
||||
border-bottom: 2px solid darken($color-theme-primary, 10%);
|
||||
|
||||
.sidebar-header-title {
|
||||
width: inherit;
|
||||
color: $color-white;
|
||||
display: inline-block;
|
||||
margin-left: 15px;
|
||||
margin-top: 6px;
|
||||
text-transform: uppercase;
|
||||
max-width: ($wrapper-width - $toggle-btn-size);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
opacity: 1;
|
||||
|
||||
// Animations
|
||||
@include transition(opacity 0.5s ease);
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-header-toggle {
|
||||
height: $toggle-btn-size;
|
||||
width: $toggle-btn-size;
|
||||
margin-left: ($wrapper-width - $toggle-btn-size);
|
||||
margin-top: -$toggle-btn-size;
|
||||
font-size: 20pt;
|
||||
background: $color-theme-primary;
|
||||
border-left: 2px solid darken($color-theme-primary, 10%);
|
||||
border-bottom: 2px solid darken($color-theme-primary, 10%);
|
||||
|
||||
// Animations
|
||||
@include transition(margin-left 0.5s ease);
|
||||
|
||||
span {
|
||||
margin: 10px;
|
||||
color: $color-white;
|
||||
|
||||
// Animations
|
||||
@include rotate-animation(0.5s, 180deg);
|
||||
@include transition(color 0.5s ease);
|
||||
}
|
||||
}
|
||||
|
||||
.tree {
|
||||
overflow-y: auto;
|
||||
margin-bottom: 0;
|
||||
padding-top: 15px;
|
||||
opacity: 1;
|
||||
overflow-y: auto;
|
||||
padding: 20px 0;
|
||||
|
||||
// Animations
|
||||
@include transition(opacity 0.5s ease);
|
||||
|
@ -99,32 +54,10 @@ $toggle-btn-size: 50px;
|
|||
padding-left: 0;
|
||||
|
||||
#sidebar-wrapper {
|
||||
margin-left: 0;
|
||||
width: 0;
|
||||
|
||||
#slide-panel {
|
||||
.sidebar-header .sidebar-header-title {
|
||||
width: 0;
|
||||
opacity: 0;
|
||||
|
||||
@include transition(width 0.5s ease);
|
||||
@include transition(opacity 0.5s ease);
|
||||
}
|
||||
|
||||
.sidebar-header-toggle {
|
||||
margin-left: 0;
|
||||
background: none;
|
||||
border: none;
|
||||
|
||||
@include transition(margin-left 0.5s ease);
|
||||
|
||||
span {
|
||||
color: darken($color-theme-primary, 10%);
|
||||
|
||||
@include rotate-animation(0.5s, 0deg);
|
||||
@include transition(color 0.5s ease);
|
||||
}
|
||||
}
|
||||
|
||||
.tree {
|
||||
opacity: 0;
|
||||
|
||||
|
|
|
@ -1,65 +1,105 @@
|
|||
@import 'constants';
|
||||
@import "constants";
|
||||
@import "mixins";
|
||||
|
||||
.tree {
|
||||
height: 100%;
|
||||
padding-bottom: 30px;
|
||||
}
|
||||
.tree > ul {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.tree ul {
|
||||
padding-left: 0;
|
||||
}
|
||||
.tree li {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 5px 5px 5px 15px;
|
||||
position: relative;
|
||||
|
||||
&.active > span {
|
||||
ul {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
> ul {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.no-indent {
|
||||
background-color: $color-white;
|
||||
border: 1px solid $color-white;
|
||||
border-radius: 4px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
&.active:not span.tree-link:hover {
|
||||
text-decoration: underline;
|
||||
.first-indent {
|
||||
background-color: $color-concrete;
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
&.leaf {
|
||||
padding-left: 10px;
|
||||
.tree-link::before {
|
||||
content: "\25B8";
|
||||
.second-indent {
|
||||
background-color: $color-concrete;
|
||||
padding-left: 60px;
|
||||
}
|
||||
|
||||
li {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
position: relative;
|
||||
|
||||
span {
|
||||
display: block;
|
||||
padding: 15px;
|
||||
|
||||
&.my-module-group-element {
|
||||
border: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
&.glyphicon-map-marker {
|
||||
border: 0;
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.active > span {
|
||||
background-color: $brand-primary;
|
||||
color: $color-white;
|
||||
font-weight: bold;
|
||||
|
||||
&.first-indent > span,
|
||||
&.no-indent > span {
|
||||
border: 0;
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
i.no-arrow {
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
i.glyphicon {
|
||||
cursor: pointer;
|
||||
font-size: 9pt;
|
||||
|
||||
&.expanded {
|
||||
@include rotate(90deg);
|
||||
}
|
||||
}
|
||||
|
||||
// Links are recolored
|
||||
a {
|
||||
color: $color-emperor;
|
||||
|
||||
&:hover {
|
||||
color: $brand-primary;
|
||||
}
|
||||
}
|
||||
|
||||
.border-custom {
|
||||
box-shadow: 0 -.25px 0 .25px $color-alto;
|
||||
margin: 0 15px;
|
||||
}
|
||||
}
|
||||
|
||||
& i.glyphicon {
|
||||
font-size: 9pt;
|
||||
#settings {
|
||||
.glyphicon-triangle-right {
|
||||
margin-left: -15px;
|
||||
}
|
||||
|
||||
&.expanded {
|
||||
@include rotate(45deg);
|
||||
.no-indent {
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
.first-indent {
|
||||
padding-left: 45px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Links are recolored */
|
||||
a {
|
||||
color: $color-emperor;
|
||||
|
||||
&:hover {
|
||||
color: $color-theme-primary;
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
display:inline-block;
|
||||
padding:3px 8px;
|
||||
}
|
||||
}
|
||||
.tree li.parent_li>span {
|
||||
display: block;
|
||||
}
|
||||
.tree li:last-child::before {
|
||||
height:30px;
|
||||
}
|
||||
|
|
|
@ -2,8 +2,18 @@
|
|||
@import "mixins";
|
||||
|
||||
// Some color definitions
|
||||
$color-group-hover: $color-theme-primary;
|
||||
$color-module-hover: $color-theme-secondary;
|
||||
$color-group-hover: $color-alabaster;
|
||||
$color-module-hover: $brand-primary;
|
||||
|
||||
#new-project-modal,
|
||||
#edit-project-modal,
|
||||
#copy-to-repository-modal {
|
||||
.btn-group label.btn-toggle:not(.active) {
|
||||
background-color: $color-white;
|
||||
border-color: $color-silver;
|
||||
color: $color-emperor;
|
||||
}
|
||||
}
|
||||
|
||||
/* Canvas index page */
|
||||
|
||||
|
@ -32,8 +42,6 @@ $color-module-hover: $color-theme-secondary;
|
|||
}
|
||||
|
||||
#canvas-new-module {
|
||||
margin-left: 10px;
|
||||
|
||||
.hbtn-default {
|
||||
opacity: 1;
|
||||
width: 0;
|
||||
|
@ -61,14 +69,13 @@ $color-module-hover: $color-theme-secondary;
|
|||
}
|
||||
|
||||
#diagram-container {
|
||||
/* for IE10+ touch devices */
|
||||
touch-action: none;
|
||||
|
||||
height: 650px;
|
||||
background: $color-dove-gray;
|
||||
@include box-shadow(0px 0px 2px 1px $color-dove-gray);
|
||||
overflow: hidden;
|
||||
@include box-shadow(0 0 2px 1px $color-silver);
|
||||
background: $color-silver;
|
||||
cursor: move;
|
||||
height: 650px;
|
||||
overflow: hidden;
|
||||
// for IE10+ touch devices
|
||||
touch-action: none;
|
||||
}
|
||||
|
||||
.diagram {
|
||||
|
@ -112,7 +119,7 @@ $color-module-hover: $color-theme-secondary;
|
|||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: $color-theme-primary;
|
||||
color: $brand-primary;
|
||||
padding: 2px 9px 4px 9px;
|
||||
}
|
||||
}
|
||||
|
@ -122,7 +129,7 @@ $color-module-hover: $color-theme-secondary;
|
|||
border: 2px solid green;
|
||||
}
|
||||
.jsplumb-drag .title {
|
||||
background-color: $color-theme-primary !important;
|
||||
background-color: $brand-primary !important;
|
||||
color: $color-white !important;
|
||||
}
|
||||
path, ._jsPlumb_endpoint {
|
||||
|
@ -132,7 +139,7 @@ path, ._jsPlumb_endpoint {
|
|||
fill: $color-white;
|
||||
}
|
||||
.ep-hover svg * {
|
||||
fill: $color-theme-primary;
|
||||
fill: $brand-primary;
|
||||
}
|
||||
|
||||
/* EDIT MODE MODULE */
|
||||
|
@ -140,16 +147,16 @@ path, ._jsPlumb_endpoint {
|
|||
opacity: 0.7;
|
||||
}
|
||||
.module.dragged > .panel-heading {
|
||||
background-color: $color-theme-primary;
|
||||
background-color: $brand-primary;
|
||||
color: $color-white;
|
||||
}
|
||||
.module.collided {
|
||||
.overlay {
|
||||
display: block;
|
||||
z-index: 21;
|
||||
background-color: $color-milano-red;
|
||||
border: 1px solid $color-milano-red;
|
||||
@include box-shadow(0 0 0 1pt $color-milano-red);
|
||||
background-color: $brand-danger;
|
||||
border: 1px solid $brand-danger;
|
||||
@include box-shadow(0 0 0 1pt $brand-danger);
|
||||
border-radius: 4px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
|
@ -223,28 +230,28 @@ path, ._jsPlumb_endpoint {
|
|||
}
|
||||
|
||||
&.alert-green .panel-body {
|
||||
color: $color-saturated-green;
|
||||
color: $brand-success;
|
||||
font-weight: bold;
|
||||
|
||||
.due-date-link {
|
||||
color: $color-saturated-green;
|
||||
color: $brand-success;
|
||||
}
|
||||
}
|
||||
|
||||
&.alert-yellow .panel-body {
|
||||
color: $color-candlelight;
|
||||
color: $brand-warning;
|
||||
font-weight: bold;
|
||||
|
||||
.due-date-link {
|
||||
color: $color-candlelight;
|
||||
color: $brand-warning;
|
||||
}
|
||||
}
|
||||
&.alert-red .panel-body {
|
||||
color: $color-milano-red;
|
||||
color: $brand-danger;
|
||||
font-weight: bold;
|
||||
|
||||
.due-date-link {
|
||||
color: $color-milano-red;
|
||||
color: $brand-danger;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -265,18 +272,18 @@ path, ._jsPlumb_endpoint {
|
|||
}
|
||||
|
||||
&.alert-green {
|
||||
border-color: $color-saturated-green;
|
||||
border-color: $brand-success;
|
||||
border-radius: 8px;
|
||||
border-width: 4px;
|
||||
}
|
||||
|
||||
&.alert-yellow {
|
||||
border-color: $color-candlelight;
|
||||
border-color: $brand-warning;
|
||||
border-width: 4px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
&.alert-red {
|
||||
border-color: $color-milano-red;
|
||||
border-color: $brand-danger;
|
||||
border-width: 4px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
@ -326,13 +333,13 @@ path, ._jsPlumb_endpoint {
|
|||
|
||||
span {
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
font-size: $font-size-large;
|
||||
text-transform: uppercase;
|
||||
display: block;
|
||||
margin-top: 20%;
|
||||
|
||||
a {
|
||||
color: $color-mine-shaft;
|
||||
color: $color-emperor;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -344,14 +351,14 @@ path, ._jsPlumb_endpoint {
|
|||
}
|
||||
|
||||
&.alert-green {
|
||||
border-color: $color-saturated-green;
|
||||
border-color: $brand-success;
|
||||
}
|
||||
|
||||
&.alert-yellow {
|
||||
border-color: $color-candlelight;
|
||||
border-color: $brand-warning;
|
||||
}
|
||||
&.alert-red {
|
||||
border-color: $color-milano-red;
|
||||
border-color: $brand-danger;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -362,7 +369,7 @@ li.group-hover {
|
|||
}
|
||||
li.module-hover {
|
||||
a {
|
||||
color: $color-theme-primary;
|
||||
color: $brand-primary;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
@ -400,7 +407,7 @@ li.module-hover {
|
|||
margin-top: 5px;
|
||||
font-family: 'Glyphicons Halflings';
|
||||
color: $color-white;
|
||||
font-size: 12pt;
|
||||
font-size: $font-size-large;
|
||||
|
||||
&:before {
|
||||
content: "\e221";
|
||||
|
@ -410,9 +417,9 @@ li.module-hover {
|
|||
}
|
||||
}
|
||||
|
||||
.glyphicon {
|
||||
.glyphicon, .fas {
|
||||
color: $color-white;
|
||||
font-size: 12pt;
|
||||
font-size: $font-size-h6;
|
||||
}
|
||||
|
||||
a.btn-link {
|
||||
|
@ -430,6 +437,7 @@ li.module-hover {
|
|||
|
||||
.create-new-tag-btn {
|
||||
margin-right: 15px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -463,7 +471,7 @@ li.module-hover {
|
|||
.experiment-no-description {
|
||||
color: $color-alto;
|
||||
display: block;
|
||||
font-size: 18px;
|
||||
font-size: $font-size-h4;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
|
||||
|
@ -508,7 +516,7 @@ li.module-hover {
|
|||
}
|
||||
|
||||
.big-plus {
|
||||
color: $color-mystic;
|
||||
color: $color-gainsboro;
|
||||
display: block;
|
||||
font-size: 250px;
|
||||
margin: 20px 0;
|
||||
|
|
62
app/assets/stylesheets/protocol_management.scss
Normal file
|
@ -0,0 +1,62 @@
|
|||
@import 'constants';
|
||||
|
||||
.btn-open-file {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
& > input[type=file] {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
min-width: 100%;
|
||||
min-height: 100%;
|
||||
font-size: 100px;
|
||||
text-align: right;
|
||||
filter: alpha(opacity=0);
|
||||
opacity: 0;
|
||||
outline: none;
|
||||
background: white;
|
||||
cursor: inherit;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
#protocols-index,
|
||||
#load-from-repository-modal {
|
||||
padding: 0;
|
||||
|
||||
.nav-tabs > li {
|
||||
text-transform: uppercase;
|
||||
|
||||
a {
|
||||
color: $color-silver-chalice;
|
||||
padding: 15px 20px;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
border-color: $color-white;
|
||||
}
|
||||
}
|
||||
|
||||
.nav > li > a:hover,
|
||||
.nav > li > a:focus {
|
||||
background-color: $color-white;
|
||||
color: $color-emperor;
|
||||
}
|
||||
|
||||
.nav-tabs > li.active > a,
|
||||
.nav-tabs > li.active > a:hover,
|
||||
.nav-tabs > li.active > a:focus {
|
||||
background-color: $color-white;
|
||||
border: 0;
|
||||
box-shadow: 0 4px 0 $brand-primary;
|
||||
color: $color-emperor;
|
||||
font-weight: bold;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.tab-pane-settings {
|
||||
border: 0;
|
||||
padding: 25px 20px;
|
||||
}
|
||||
}
|
|
@ -8,27 +8,30 @@
|
|||
|
||||
/* New page navbar */
|
||||
.navbar-report {
|
||||
border-left: none;
|
||||
border-top: none;
|
||||
border-right: none;
|
||||
border-bottom: 4px solid $color-silver;
|
||||
background: $color-concrete !important;
|
||||
margin-bottom: 0;
|
||||
background: $color-white;
|
||||
border-bottom: 1px solid $color-gainsboro;
|
||||
border-left: 0;
|
||||
border-right: 0;
|
||||
border-top: 15px solid $color-concrete;
|
||||
margin-bottom: 15px;
|
||||
min-width: 320px;
|
||||
padding: 0 15px;
|
||||
padding: 25px 20px;
|
||||
position: sticky;
|
||||
top: 50px;
|
||||
z-index: 500;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
|
||||
div.row {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
#report-menu {
|
||||
|
||||
form {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
& > div.row {
|
||||
|
@ -54,43 +57,6 @@ label {
|
|||
}
|
||||
}
|
||||
|
||||
/* New page sidebar */
|
||||
.report-sidebar-wrapper {
|
||||
background-color: $color-white !important;
|
||||
}
|
||||
|
||||
// Some additional styling on the treeview
|
||||
.report-tree {
|
||||
li {
|
||||
padding: 0 0 0 15px;
|
||||
|
||||
a.report-nav-link:visited {
|
||||
text-decoration: none;
|
||||
}
|
||||
a.report-nav-link:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
[data-type='step']:not(.parent_li) {
|
||||
padding-left: 27px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.report-sidebar-panel-description {
|
||||
margin: 10px 10px 0 10px;
|
||||
}
|
||||
|
||||
.report-item-elements {
|
||||
margin-top: 10px !important;
|
||||
margin-left: 15px !important;
|
||||
|
||||
li {
|
||||
margin: 5px 5px 5px 15px;
|
||||
}
|
||||
|
||||
ul {
|
||||
padding-left: 15px !important;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Global fix for handsontable
|
||||
|
@ -108,26 +74,34 @@ label {
|
|||
|
||||
|
||||
/* New page content */
|
||||
#report-new {
|
||||
margin-top: -15px;
|
||||
}
|
||||
|
||||
.report-body {
|
||||
background: $color-dove-gray;
|
||||
background: $color-silver;
|
||||
}
|
||||
|
||||
.report-container {
|
||||
background: $color-silver;
|
||||
box-shadow: 0 0 2px 1px $color-silver;
|
||||
overflow-x: auto;
|
||||
overflow-y: auto;
|
||||
padding-top: 30px;
|
||||
padding-bottom: 30px;
|
||||
padding: 30px;
|
||||
padding-left: 0;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
#report-content {
|
||||
color: $color-black;
|
||||
@include box-shadow(0 0 58px -10px $color-black);
|
||||
background: $color-white;
|
||||
@include box-shadow(0px 0px 58px -10px $color-black);
|
||||
max-width: 800px;
|
||||
min-width: 230px;
|
||||
min-height: 1200px;
|
||||
color: $color-black;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-top: -15px;
|
||||
max-width: 800px;
|
||||
min-height: 1200px;
|
||||
min-width: 230px;
|
||||
padding: 45px;
|
||||
}
|
||||
|
||||
|
@ -148,7 +122,7 @@ label {
|
|||
opacity: 0.7;
|
||||
padding: 15px;
|
||||
border-radius: 5px;
|
||||
border: 4px $color-theme-primary solid;
|
||||
border: 4px $brand-primary solid;
|
||||
|
||||
.plus-icon {
|
||||
bottom: 16px !important;
|
||||
|
@ -166,7 +140,7 @@ label {
|
|||
.filler {
|
||||
display: block;
|
||||
height: 4px;
|
||||
background-color: $color-theme-primary;
|
||||
background-color: $brand-primary;
|
||||
border-radius: 1px;
|
||||
margin-top: 8px;
|
||||
margin-bottom: 8px;
|
||||
|
@ -183,7 +157,7 @@ label {
|
|||
}
|
||||
|
||||
.plus-icon {
|
||||
color: $color-theme-primary;
|
||||
color: $brand-primary;
|
||||
display: block;
|
||||
text-align: center;
|
||||
width: 40px;
|
||||
|
@ -201,7 +175,7 @@ label {
|
|||
opacity: 1.0;
|
||||
|
||||
.filler {
|
||||
background-color: $color-theme-primary;
|
||||
background-color: $brand-primary;
|
||||
|
||||
.plus-icon span {
|
||||
font-weight: bold;
|
||||
|
@ -223,7 +197,7 @@ label {
|
|||
}
|
||||
.controls {
|
||||
margin-right: 15px;
|
||||
font-size: 12pt;
|
||||
font-size: $font-size-h6;
|
||||
opacity: 0.05;
|
||||
}
|
||||
}
|
||||
|
@ -240,8 +214,8 @@ label {
|
|||
}
|
||||
|
||||
&:hover {
|
||||
background-color: $color-mystic;
|
||||
@include box-shadow(0 0 2px 15px $color-mystic);
|
||||
background-color: $color-gainsboro;
|
||||
@include box-shadow(0 0 2px 15px $color-gainsboro);
|
||||
|
||||
& > .report-element-header {
|
||||
|
||||
|
@ -266,7 +240,7 @@ label {
|
|||
}
|
||||
|
||||
&:hover > .report-element-body .project-name {
|
||||
color: $color-theme-primary;
|
||||
color: $brand-primary;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -297,7 +271,7 @@ label {
|
|||
}
|
||||
|
||||
&:hover > .report-element-body .module-name {
|
||||
color: $color-theme-primary;
|
||||
color: $brand-primary;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -329,7 +303,7 @@ label {
|
|||
}
|
||||
|
||||
&:hover > .report-element-header {
|
||||
color: $color-theme-primary;
|
||||
color: $brand-primary;
|
||||
}
|
||||
|
||||
.report-element-body {
|
||||
|
@ -368,7 +342,7 @@ label {
|
|||
/** Step element style */
|
||||
.report-step-element {
|
||||
&:hover > .report-element-body .step-name {
|
||||
color: $color-theme-primary;
|
||||
color: $brand-primary;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -388,7 +362,7 @@ label {
|
|||
|
||||
&:hover > .report-element-header {
|
||||
.attachment-icon {
|
||||
color: $color-theme-primary;
|
||||
color: $brand-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -403,7 +377,7 @@ label {
|
|||
|
||||
&:hover > .report-element-header {
|
||||
.table-name {
|
||||
color: $color-theme-primary;
|
||||
color: $brand-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -417,7 +391,7 @@ label {
|
|||
}
|
||||
|
||||
&:hover > .report-element-header .file-name {
|
||||
color: $color-theme-primary;
|
||||
color: $brand-primary;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -438,7 +412,7 @@ label {
|
|||
}
|
||||
|
||||
&:hover > .report-element-header .checklist-name {
|
||||
color: $color-theme-primary;
|
||||
color: $brand-primary;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -475,7 +449,7 @@ label {
|
|||
|
||||
&:hover > .report-element-header {
|
||||
.comments-icon,.comments-name {
|
||||
color: $color-theme-primary;
|
||||
color: $brand-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -504,7 +478,7 @@ label {
|
|||
|
||||
&:hover > .report-element-header {
|
||||
.samples-icon,.samples-name {
|
||||
color: $color-theme-primary;
|
||||
color: $brand-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -524,7 +498,7 @@ label {
|
|||
&:hover > .report-element-header {
|
||||
.repository-icon,
|
||||
.repository-name {
|
||||
color: $color-theme-primary;
|
||||
color: $brand-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -559,7 +533,17 @@ label {
|
|||
|
||||
&:hover > .report-element-header {
|
||||
.activity-icon,.activity-name {
|
||||
color: $color-theme-primary;
|
||||
color: $brand-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#save-PDF-to-inventory-warnings {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.save-PDF-to-inventory-alerts {
|
||||
.danger {
|
||||
color: $brand-danger;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
@import "constants";
|
||||
|
||||
.repositories-dropdown-menu {
|
||||
height: auto;
|
||||
max-height: 400px;
|
||||
|
@ -24,3 +26,8 @@
|
|||
float: right;
|
||||
text-align: inherit;
|
||||
}
|
||||
|
||||
.breadcrumb.breadcrumb-repository {
|
||||
background-color: $color-concrete;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
}
|
||||
|
||||
.glyphicon-ok {
|
||||
color: $color-theme-secondary;
|
||||
color: $brand-default;
|
||||
}
|
||||
|
||||
.glyphicon {
|
||||
|
|
|
@ -9,5 +9,5 @@
|
|||
padding-top: 20px;
|
||||
}
|
||||
.search-asset-text-data{
|
||||
font-size: 14px;
|
||||
font-size: $font-size-base;
|
||||
}
|
||||
|
|
|
@ -11,8 +11,7 @@
|
|||
margin-bottom: 10px;
|
||||
|
||||
& > div > span.pull-left {
|
||||
margin-top: 8px;
|
||||
font-size: 1.2em;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
364
app/assets/stylesheets/themes/main_navigation.scss
Normal file
|
@ -0,0 +1,364 @@
|
|||
@import 'constants';
|
||||
@import "mixins";
|
||||
|
||||
#main-nav {
|
||||
box-shadow: 0 3px 6px $color-alto;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
#notifications-dropdown {
|
||||
.fa-bell {
|
||||
font-size: $font-size-large;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
#count-notifications {
|
||||
background-color: $brand-primary;
|
||||
border-radius: 5px;
|
||||
color: $color-concrete;
|
||||
display: none;
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
margin-left: 12px;
|
||||
padding: 1px 6px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.navbar {
|
||||
border-radius: 0;
|
||||
padding-right: 15px;
|
||||
}
|
||||
|
||||
.navbar-default {
|
||||
background-color: $color-white;
|
||||
border-color: $color-alto;
|
||||
}
|
||||
|
||||
.navbar-default .navbar-brand {
|
||||
& > img {
|
||||
margin-top: -7px;
|
||||
max-width: 55px;
|
||||
max-height: 38px;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-notifications {
|
||||
max-height: 500px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
padding-bottom: 0;
|
||||
padding-top: 0;
|
||||
width: 450px;
|
||||
word-wrap: break-word;
|
||||
|
||||
.notifications-no-recent {
|
||||
padding-bottom: 10px;
|
||||
padding-left: 10px;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.notification {
|
||||
border-bottom: 1px solid $color-alto;
|
||||
padding-bottom: 10px;
|
||||
padding-top: 10px;
|
||||
|
||||
&:hover {
|
||||
background-color: $color-concrete;
|
||||
}
|
||||
}
|
||||
|
||||
.unseen {
|
||||
border-left: 4px solid $brand-primary;
|
||||
}
|
||||
|
||||
.text-center {
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
top: 0px;
|
||||
margin-top: 5px;
|
||||
height: 45px;
|
||||
width: 45px;
|
||||
}
|
||||
|
||||
.assignment {
|
||||
background-color: $brand-primary;
|
||||
border-radius: 50%;
|
||||
color: $color-concrete;
|
||||
display: block;
|
||||
font-size: $font-size-h3;
|
||||
height: 45px;
|
||||
padding-top: 5px;
|
||||
width: 45px;
|
||||
}
|
||||
|
||||
.deliver {
|
||||
background-color: $brand-warning;
|
||||
border-radius: 50%;
|
||||
color: $color-concrete;
|
||||
display: block;
|
||||
font-size: $font-size-h3;
|
||||
height: 45px;
|
||||
padding-top: 5px;
|
||||
width: 45px;
|
||||
}
|
||||
|
||||
.system-message {
|
||||
background-color: $brand-success;
|
||||
border-radius: 50%;
|
||||
color: $color-concrete;
|
||||
display: block;
|
||||
font-size: $font-size-h3;
|
||||
height: 45px;
|
||||
padding-top: 8px;
|
||||
width: 45px;
|
||||
}
|
||||
|
||||
.notifications-dropdown-footer {
|
||||
background-color: $color-gainsboro;
|
||||
padding: 8px;
|
||||
text-align: center;
|
||||
|
||||
a:hover {
|
||||
background-color: $color-gainsboro;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.notification {
|
||||
padding-right: 8px;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
#search-menu {
|
||||
padding-right: 0;
|
||||
|
||||
.nav {
|
||||
position: relative;
|
||||
z-index: 1000;
|
||||
}
|
||||
}
|
||||
|
||||
#search-content {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
#search-container {
|
||||
padding-left: 45px;
|
||||
}
|
||||
|
||||
/** Search */
|
||||
.nav-search {
|
||||
li.disabled {
|
||||
opacity: .8;
|
||||
|
||||
.badge {
|
||||
background-color: $color-emperor;
|
||||
opacity: .8;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.repositories-team {
|
||||
padding: 10px 15px;
|
||||
|
||||
&.active {
|
||||
color: $brand-primary;
|
||||
}
|
||||
}
|
||||
|
||||
.repository-search {
|
||||
padding-left: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.notification-settings-container {
|
||||
margin-bottom: 50px;
|
||||
margin-top: 50px;
|
||||
|
||||
h4 {
|
||||
font-weight: 600;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.col-sm-4 {
|
||||
padding-left: 5rem;
|
||||
padding-top: .5rem;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.col-sm-2 {
|
||||
padding-left: 3rem;
|
||||
padding-top: .7rem;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.col-sm-4 {
|
||||
margin-bottom: 1rem;
|
||||
padding-left: 1.8rem;
|
||||
}
|
||||
|
||||
.col-sm-2 {
|
||||
padding-left: 1.8rem;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-group {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.assignment {
|
||||
background-color: $brand-primary;
|
||||
border-radius: 50%;
|
||||
color: $color-concrete;
|
||||
display: block !important;
|
||||
font-size: $font-size-base;
|
||||
height: 30px;
|
||||
margin-right: 15px;
|
||||
padding: 7px;
|
||||
padding-bottom: 5px;
|
||||
padding-top: 5px;
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
.system-message {
|
||||
background-color: $brand-success;
|
||||
border-radius: 50%;
|
||||
color: $color-concrete;
|
||||
display: block !important;
|
||||
font-size: $font-size-base;
|
||||
height: 30px;
|
||||
margin-right: 15px;
|
||||
padding: 8px;
|
||||
padding-bottom: 5px;
|
||||
padding-top: 5px;
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
.img-circle {
|
||||
margin-right: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
// Global team switch
|
||||
#team-switch {
|
||||
word-wrap: break-word;
|
||||
|
||||
.team-name {
|
||||
margin-left: 17px;
|
||||
}
|
||||
|
||||
.glyphicon-ok-sign {
|
||||
color: $brand-primary;
|
||||
margin-left: -2px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.team-name-item {
|
||||
border-bottom: 1px solid $color-gainsboro;
|
||||
padding-bottom: 8px;
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
li:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.btn-default:not(.dropdown-toggle) {
|
||||
margin-left: 15px;
|
||||
text-align: right;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.btn-group {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
border-radius: 0;
|
||||
margin-top: 0;
|
||||
padding-top: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
i {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
li {
|
||||
display: block;
|
||||
text-align: left;
|
||||
word-wrap: break-word;
|
||||
|
||||
&:hover {
|
||||
background-color: $color-concrete;
|
||||
}
|
||||
|
||||
a {
|
||||
color: $color-emperor;
|
||||
display: block;
|
||||
line-height: 1.6em;
|
||||
padding: 3px 20px;
|
||||
text-align: left;
|
||||
text-decoration: none;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#nav-team-switch {
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
.custom-nav-dropdown {
|
||||
border: 1px solid $color-alto;
|
||||
padding: 10px 0 10px 30px;
|
||||
}
|
||||
|
||||
// Alert
|
||||
.alert {
|
||||
border-radius: 0;
|
||||
margin-bottom: 0;
|
||||
opacity: .86;
|
||||
width: 100%;
|
||||
|
||||
&.alert-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
a#hide-alert {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
&.alert-floating {
|
||||
position: fixed;
|
||||
top: 50px;
|
||||
z-index: 1000;
|
||||
}
|
||||
}
|
||||
|
||||
#content-wrapper {
|
||||
margin-top: 50px;
|
||||
margin-left: 83px;
|
||||
}
|
||||
|
||||
#search-bar {
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
#search-bar {
|
||||
padding: 10px 30px;
|
||||
}
|
||||
}
|
||||
|
||||
// reset margins on small screens
|
||||
@media (max-width: 1188px) {
|
||||
|
||||
#nav-team-switch {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
92
app/assets/stylesheets/themes/menu_bar.scss
Normal file
|
@ -0,0 +1,92 @@
|
|||
@import "constants";
|
||||
@import "mixins";
|
||||
|
||||
.menu-bar {
|
||||
background-color: $color-white;
|
||||
box-shadow: 1px 3px 6px 0 $color-alto;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
overflow-x: hidden;
|
||||
position: fixed;
|
||||
width: 83px;
|
||||
z-index: 1001;
|
||||
padding-bottom: 50px;
|
||||
|
||||
.scroll-wrapper {
|
||||
height: 100%;
|
||||
padding-top: 16px;
|
||||
width: 83px;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
ul.nav > li {
|
||||
|
||||
& > a {
|
||||
color: $color-silver-chalice;
|
||||
display: grid;
|
||||
font-size: $font-size-h6;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
word-break: normal;
|
||||
|
||||
& > span {
|
||||
padding-top: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
@include box-shadow(-4px 0 0 $brand-primary);
|
||||
background-color: $color-gainsboro;
|
||||
margin-left: 4px;
|
||||
|
||||
& > a {
|
||||
color: $color-emperor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ul.nav-bottom {
|
||||
bottom: 0;
|
||||
padding-bottom: 16px;
|
||||
position: fixed;
|
||||
width: inherit;
|
||||
}
|
||||
|
||||
.dropup {
|
||||
.dropdown-menu {
|
||||
bottom: 0;
|
||||
left: 99%;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&.open > a {
|
||||
color: $color-emperor;
|
||||
}
|
||||
}
|
||||
|
||||
#toggle-sidebar-btn > span {
|
||||
@include rotate-animation(.5s, 0deg);
|
||||
}
|
||||
|
||||
#toggle-sidebar-btn[data-shown] > span {
|
||||
@include rotate-animation(.5s, 180deg);
|
||||
}
|
||||
|
||||
#toggle-sidebar-btn:hover {
|
||||
background-color: $color-concrete;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#toggle-sidebar-btn.hidden2 {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
@media(max-height:510px) {
|
||||
.menu-bar .nav-bottom {
|
||||
position: relative;
|
||||
width: auto;
|
||||
}
|
||||
}
|
45
app/assets/stylesheets/themes/repositories.scss
Normal file
|
@ -0,0 +1,45 @@
|
|||
@import "constants";
|
||||
|
||||
.repository-columns-body {
|
||||
margin-top: 50px;
|
||||
|
||||
.list-group-item {
|
||||
padding: 28px;
|
||||
|
||||
.controlls {
|
||||
margin-top: -18px;
|
||||
}
|
||||
|
||||
span {
|
||||
margin-top: -10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#repository-columns-dropdown {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.new-repository-button {
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.custom-alert-info {
|
||||
background-color: $state-info-bg;
|
||||
border: 1px solid $state-info-border;
|
||||
color: $state-info-text;
|
||||
margin: 10px 0;
|
||||
opacity: .86;
|
||||
padding: 15px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.repository-input-file-field {
|
||||
display: inline-flex;
|
||||
|
||||
a {
|
||||
color: $brand-danger;
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
|
@ -2,15 +2,17 @@ class ActivitiesController < ApplicationController
|
|||
include ActivityHelper
|
||||
|
||||
def index
|
||||
@vars = local_vars
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
render json: {
|
||||
more_url: local_vars.fetch(:more_activities_url),
|
||||
html: render_to_string(
|
||||
partial: 'index.html.erb', locals: local_vars
|
||||
partial: 'list.html.erb', locals: @vars
|
||||
)
|
||||
}
|
||||
end
|
||||
format.html
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -7,7 +7,6 @@ class AssetsController < ApplicationController
|
|||
include ActionView::Context
|
||||
include InputSanitizeHelper
|
||||
include FileIconsHelper
|
||||
include WopiHelper
|
||||
|
||||
before_action :load_vars
|
||||
before_action :check_read_permission, except: :file_present
|
||||
|
@ -31,32 +30,62 @@ class AssetsController < ApplicationController
|
|||
render json: {
|
||||
'asset-id' => @asset.id,
|
||||
'image-tag-url' => @asset.url(:medium),
|
||||
'preview-url' => large_image_url_asset_path(@asset),
|
||||
'preview-url' => asset_file_preview_path(@asset),
|
||||
'filename' => truncate(@asset.file_file_name,
|
||||
length:
|
||||
Constants::FILENAME_TRUNCATION_LENGTH),
|
||||
'download-url' => download_asset_path(@asset),
|
||||
'type' => asset_data_type(@asset),
|
||||
'wopi-file-name' => wopi_asset_file_name(@asset, true),
|
||||
'wopi-edit' => (wopi_asset_edit_button(@asset) if wopi_file?(@asset)),
|
||||
'wopi-view' => (wopi_asset_view_button(@asset) if wopi_file?(@asset))
|
||||
'type' => asset_data_type(@asset)
|
||||
}, status: 200
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def large_image_url
|
||||
def file_preview
|
||||
response_json = {
|
||||
'type' => (@asset.is_image? ? 'image' : 'file'),
|
||||
|
||||
'filename' => truncate(@asset.file_file_name,
|
||||
length:
|
||||
Constants::FILENAME_TRUNCATION_LENGTH),
|
||||
'download-url' => download_asset_path(@asset)
|
||||
}
|
||||
|
||||
if @asset.is_image?
|
||||
response_json.merge!(
|
||||
'processing' => @asset.file.processing?,
|
||||
'large-preview-url' => @asset.url(:large),
|
||||
'processing-url' => image_tag('medium/processing.gif')
|
||||
)
|
||||
else
|
||||
response_json.merge!(
|
||||
'processing' => @asset.file.processing?,
|
||||
'preview-icon' => render_to_string(
|
||||
partial: 'shared/file_preview_icon.html.erb',
|
||||
locals: { asset: @asset }
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
if wopi_file?(@asset)
|
||||
can_edit =
|
||||
if @assoc.class == Step
|
||||
can_manage_protocol_in_module?(@protocol) ||
|
||||
can_manage_protocol_in_repository?(@protocol)
|
||||
elsif @assoc.class == Result
|
||||
can_manage_module?(@my_module)
|
||||
elsif @assoc.class == RepositoryCell
|
||||
can_manage_repository_rows?(@repository.team)
|
||||
end
|
||||
response_json['wopi-controls'] = render_to_string(
|
||||
partial: 'shared/file_wopi_controlls.html.erb',
|
||||
locals: { asset: @asset, can_edit: can_edit }
|
||||
)
|
||||
end
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
render json: {
|
||||
'large-preview-url' => @asset.url(:large),
|
||||
'filename' => truncate(@asset.file_file_name,
|
||||
length:
|
||||
Constants::FILENAME_TRUNCATION_LENGTH),
|
||||
'download-url' => download_asset_path(@asset),
|
||||
'type' => (@asset.is_image? ? 'image' : 'file')
|
||||
}
|
||||
render json: response_json
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -103,13 +132,17 @@ class AssetsController < ApplicationController
|
|||
|
||||
step_assoc = @asset.step
|
||||
result_assoc = @asset.result
|
||||
repository_cell_assoc = @asset.repository_cell
|
||||
@assoc = step_assoc unless step_assoc.nil?
|
||||
@assoc = result_assoc unless result_assoc.nil?
|
||||
@assoc = repository_cell_assoc unless repository_cell_assoc.nil?
|
||||
|
||||
if @assoc.class == Step
|
||||
@protocol = @asset.step.protocol
|
||||
else
|
||||
elsif @assoc.class == Result
|
||||
@my_module = @assoc.my_module
|
||||
elsif @assoc.class == RepositoryCell
|
||||
@repository = @assoc.repository_column.repository
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -119,6 +152,8 @@ class AssetsController < ApplicationController
|
|||
can_read_protocol_in_repository?(@protocol)
|
||||
elsif @assoc.class == Result
|
||||
render_403 and return unless can_read_experiment?(@my_module.experiment)
|
||||
elsif @assoc.class == RepositoryCell
|
||||
render_403 and return unless can_read_team?(@repository.team)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -128,6 +163,8 @@ class AssetsController < ApplicationController
|
|||
can_manage_protocol_in_repository?(@protocol)
|
||||
elsif @assoc.class == Result
|
||||
render_403 and return unless can_manage_module?(@my_module)
|
||||
elsif @assoc.class == RepositoryCell
|
||||
render_403 and return unless can_manage_repository_rows?(@repository.team)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -29,12 +29,29 @@ class AtWhoController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def samples
|
||||
def rep_items
|
||||
res = SmartAnnotation.new(current_user, current_team, @query)
|
||||
repository = Repository.find_by_id(params[:repository_id])
|
||||
render_403 && return unless repository && can_read_team?(repository.team)
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
render json: {
|
||||
res: res.samples,
|
||||
res: res.repository_rows(repository),
|
||||
status: :ok
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def repositories
|
||||
repositories =
|
||||
@team.repositories.limit(Rails.configuration.x.repositories_limit)
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
render json: {
|
||||
repositories: repositories.map do |r|
|
||||
[r.id, r.name.truncate(Constants::ATWHO_REP_NAME_LIMIT)]
|
||||
end.to_h,
|
||||
status: :ok
|
||||
}
|
||||
end
|
||||
|
|
|
@ -7,19 +7,19 @@ class ExperimentsController < ApplicationController
|
|||
include Rails.application.routes.url_helpers
|
||||
|
||||
before_action :set_experiment,
|
||||
except: [:new, :create]
|
||||
except: %i(new create)
|
||||
before_action :set_project,
|
||||
only: [:new, :create, :samples_index, :samples, :module_archive,
|
||||
:clone_modal, :move_modal, :delete_samples]
|
||||
only: %i(new create samples_index samples module_archive
|
||||
clone_modal move_modal delete_samples)
|
||||
before_action :load_projects_by_teams, only: %i(canvas samples module_archive)
|
||||
before_action :check_view_permissions,
|
||||
only: [:canvas, :module_archive]
|
||||
only: %i(canvas module_archive)
|
||||
before_action :check_manage_permissions, only: :edit
|
||||
before_action :check_archive_permissions, only: :archive
|
||||
before_action :check_clone_permissions, only: %i(clone_modal clone)
|
||||
before_action :check_move_permissions, only: %i(move_modal move)
|
||||
|
||||
# except parameter could be used but it is not working.
|
||||
layout :choose_layout
|
||||
layout 'fluid'.freeze
|
||||
|
||||
# Action defined in SampleActions
|
||||
DELETE_SAMPLES = 'Delete'.freeze
|
||||
|
@ -348,6 +348,11 @@ class ExperimentsController < ApplicationController
|
|||
params.require(:experiment).permit(:name, :description, :archived)
|
||||
end
|
||||
|
||||
def load_projects_by_teams
|
||||
@projects_by_teams = current_user.projects_by_teams(current_team.id,
|
||||
nil, false)
|
||||
end
|
||||
|
||||
def check_view_permissions
|
||||
render_403 unless can_read_experiment?(@experiment)
|
||||
end
|
||||
|
@ -368,10 +373,6 @@ class ExperimentsController < ApplicationController
|
|||
render_403 unless can_move_experiment?(@experiment)
|
||||
end
|
||||
|
||||
def choose_layout
|
||||
action_name.in?(%w(index archive)) ? 'main' : 'fluid'
|
||||
end
|
||||
|
||||
def experiment_annotation_notification(old_text = nil)
|
||||
smart_annotation_notification(
|
||||
old_text: old_text,
|
||||
|
|
|
@ -6,20 +6,36 @@ class MyModulesController < ApplicationController
|
|||
include ActionView::Helpers::UrlHelper
|
||||
include ApplicationHelper
|
||||
|
||||
before_action :load_vars
|
||||
before_action :load_vars_nested, only: %I[new create]
|
||||
before_action :load_repository, only: %I[assign_repository_records
|
||||
unassign_repository_records]
|
||||
before_action :check_manage_permissions, only:
|
||||
%i(destroy description due_date)
|
||||
before_action :load_vars,
|
||||
only: %i(show update destroy description due_date protocols
|
||||
results samples activities activities_tab
|
||||
assign_samples unassign_samples delete_samples
|
||||
toggle_task_state samples_index archive
|
||||
complete_my_module repository repository_index
|
||||
assign_repository_records unassign_repository_records
|
||||
unassign_repository_records_modal
|
||||
assign_repository_records_modal)
|
||||
before_action :load_vars_nested, only: %i(new create)
|
||||
before_action :load_repository, only: %i(assign_repository_records
|
||||
unassign_repository_records
|
||||
unassign_repository_records_modal
|
||||
assign_repository_records_modal
|
||||
repository_index)
|
||||
before_action :load_projects_by_teams, only: %i(protocols results activities
|
||||
samples repository archive)
|
||||
before_action :check_manage_permissions_archive, only: %i(update destroy)
|
||||
before_action :check_manage_permissions, only: %i(description due_date)
|
||||
before_action :check_view_permissions, only:
|
||||
%i(show activities activities_tab protocols results samples samples_index
|
||||
archive)
|
||||
before_action :check_complete_module_permission, only: :complete_my_module
|
||||
before_action :check_assign_repository_records_permissions, only:
|
||||
%i(assign_repository_records unassign_repository_records)
|
||||
before_action :check_assign_samples_permissions, only: %i(assign_samples
|
||||
unassign_samples)
|
||||
before_action :check_assign_repository_records_permissions,
|
||||
only: %i(unassign_repository_records_modal
|
||||
assign_repository_records_modal
|
||||
assign_repository_records
|
||||
unassign_repository_records
|
||||
assign_samples
|
||||
unassign_samples)
|
||||
|
||||
layout 'fluid'.freeze
|
||||
|
||||
|
@ -62,7 +78,7 @@ class MyModulesController < ApplicationController
|
|||
@last_activity_id = params[:from].to_i || 0
|
||||
@per_page = 10
|
||||
|
||||
@activities = @my_module.last_activities(@last_activity_id, @per_page +1 )
|
||||
@activities = @my_module.last_activities(@last_activity_id, @per_page + 1)
|
||||
@more_activities_url = ""
|
||||
|
||||
@overflown = @activities.length > @per_page
|
||||
|
@ -128,12 +144,6 @@ class MyModulesController < ApplicationController
|
|||
end
|
||||
|
||||
def update
|
||||
render_403 && return unless if my_module_params[:archived] == 'false'
|
||||
can_restore_module?(@my_module)
|
||||
else
|
||||
can_manage_module?(@my_module)
|
||||
end
|
||||
|
||||
@my_module.assign_attributes(my_module_params)
|
||||
@my_module.last_modified_by = current_user
|
||||
description_changed = @my_module.description_changed?
|
||||
|
@ -364,38 +374,51 @@ class MyModulesController < ApplicationController
|
|||
|
||||
# AJAX actions
|
||||
def repository_index
|
||||
@repository = Repository.find_by_id(params[:repository_id])
|
||||
if @repository.nil? || !can_read_team?(@repository.team)
|
||||
render_403
|
||||
else
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.json do
|
||||
render json: ::RepositoryDatatable.new(view_context,
|
||||
@repository,
|
||||
@my_module,
|
||||
current_user)
|
||||
end
|
||||
end
|
||||
end
|
||||
@draw = params[:draw].to_i
|
||||
per_page = params[:length] == '-1' ? 100 : params[:length].to_i
|
||||
page = (params[:start].to_i / per_page) + 1
|
||||
records = RepositoryDatatableService.new(@repository,
|
||||
params,
|
||||
current_user,
|
||||
@my_module)
|
||||
@assigned_rows = records.assigned_rows
|
||||
@repository_row_count = records.repository_rows.count
|
||||
@columns_mappings = records.mappings
|
||||
@repository_rows = records.repository_rows.page(page).per(per_page)
|
||||
render 'repository_rows/index.json'
|
||||
end
|
||||
|
||||
# Submit actions
|
||||
def assign_repository_records
|
||||
if params[:selected_rows].present? && params[:repository_id].present?
|
||||
records_names = []
|
||||
downstream = ActiveModel::Type::Boolean.new.cast(params[:downstream])
|
||||
|
||||
params[:selected_rows].each do |id|
|
||||
record = RepositoryRow.find_by_id(id)
|
||||
next if !record || @my_module.repository_rows.include?(record)
|
||||
record.last_modified_by = current_user
|
||||
record.save
|
||||
records_names << record.name
|
||||
MyModuleRepositoryRow.create!(
|
||||
my_module: @my_module,
|
||||
repository_row: record,
|
||||
assigned_by: current_user
|
||||
)
|
||||
RepositoryRow
|
||||
.where(id: params[:selected_rows],
|
||||
repository_id: params[:repository_id])
|
||||
.find_each do |record|
|
||||
unless @my_module.repository_rows.include?(record)
|
||||
record.last_modified_by = current_user
|
||||
record.save
|
||||
|
||||
MyModuleRepositoryRow.create!(
|
||||
my_module: @my_module,
|
||||
repository_row: record,
|
||||
assigned_by: current_user
|
||||
)
|
||||
records_names << record.name
|
||||
end
|
||||
|
||||
next unless downstream
|
||||
@my_module.downstream_modules.each do |my_module|
|
||||
next if my_module.repository_rows.include?(record)
|
||||
MyModuleRepositoryRow.create!(
|
||||
my_module: my_module,
|
||||
repository_row: record,
|
||||
assigned_by: current_user
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
if records_names.any?
|
||||
|
@ -432,17 +455,29 @@ class MyModulesController < ApplicationController
|
|||
|
||||
def unassign_repository_records
|
||||
if params[:selected_rows].present? && params[:repository_id].present?
|
||||
records = []
|
||||
downstream = ActiveModel::Type::Boolean.new.cast(params[:downstream])
|
||||
|
||||
params[:selected_rows].each do |id|
|
||||
record = RepositoryRow.find_by_id(id)
|
||||
next unless record && @my_module.repository_rows.include?(record)
|
||||
record.last_modified_by = current_user
|
||||
record.save
|
||||
records << record
|
||||
end
|
||||
records = RepositoryRow.assigned_on_my_module(params[:selected_rows],
|
||||
@my_module)
|
||||
|
||||
@my_module.repository_rows.destroy(records & @my_module.repository_rows)
|
||||
|
||||
if downstream
|
||||
@my_module.downstream_modules.each do |my_module|
|
||||
assigned_records = RepositoryRow.assigned_on_my_module(
|
||||
params[:selected_rows],
|
||||
my_module
|
||||
)
|
||||
my_module.repository_rows.destroy(
|
||||
assigned_records & my_module.repository_rows
|
||||
)
|
||||
assigned_records.update_all(last_modified_by_id: current_user.id)
|
||||
end
|
||||
end
|
||||
|
||||
# update last last_modified_by
|
||||
records.update_all(last_modified_by_id: current_user.id)
|
||||
|
||||
if records.any?
|
||||
Activity.create(
|
||||
type_of: :unassign_repository_record,
|
||||
|
@ -475,6 +510,28 @@ class MyModulesController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def unassign_repository_records_modal
|
||||
selected_rows = params[:selected_rows]
|
||||
modal = render_to_string(
|
||||
partial: 'my_modules/modals/unassign_repository_records_modal.html.erb',
|
||||
locals: { my_module: @my_module,
|
||||
repository: @repository,
|
||||
selected_rows: selected_rows }
|
||||
)
|
||||
render json: { html: modal }, status: :ok
|
||||
end
|
||||
|
||||
def assign_repository_records_modal
|
||||
selected_rows = params[:selected_rows]
|
||||
modal = render_to_string(
|
||||
partial: 'my_modules/modals/assign_repository_records_modal.html.erb',
|
||||
locals: { my_module: @my_module,
|
||||
repository: @repository,
|
||||
selected_rows: selected_rows }
|
||||
)
|
||||
render json: { html: modal }, status: :ok
|
||||
end
|
||||
|
||||
# Complete/uncomplete task
|
||||
def toggle_task_state
|
||||
respond_to do |format|
|
||||
|
@ -596,11 +653,25 @@ class MyModulesController < ApplicationController
|
|||
|
||||
def load_repository
|
||||
@repository = Repository.find_by_id(params[:repository_id])
|
||||
render_404 unless @repository && can_read_team?(@repository.team)
|
||||
render_404 unless @repository
|
||||
render_403 unless can_read_team?(@repository.team)
|
||||
end
|
||||
|
||||
def load_projects_by_teams
|
||||
@projects_by_teams = current_user.projects_by_teams(current_team.id,
|
||||
nil, false)
|
||||
end
|
||||
|
||||
def check_manage_permissions
|
||||
render_403 unless can_manage_module?(@my_module)
|
||||
render_403 && return unless can_manage_module?(@my_module)
|
||||
end
|
||||
|
||||
def check_manage_permissions_archive
|
||||
render_403 && return unless if my_module_params[:archived] == 'false'
|
||||
can_restore_module?(@my_module)
|
||||
else
|
||||
can_manage_module?(@my_module)
|
||||
end
|
||||
end
|
||||
|
||||
def check_view_permissions
|
||||
|
|
|
@ -4,20 +4,22 @@ class ProjectsController < ApplicationController
|
|||
include TeamsHelper
|
||||
include InputSanitizeHelper
|
||||
|
||||
before_action :load_vars, only: [:show, :edit, :update,
|
||||
:notifications, :reports,
|
||||
:samples, :experiment_archive,
|
||||
:delete_samples, :samples_index]
|
||||
before_action :generate_intro_demo, only: :index
|
||||
before_action :load_vars, only: %i(show edit update
|
||||
notifications reports
|
||||
samples experiment_archive
|
||||
delete_samples samples_index)
|
||||
before_action :load_projects_by_teams, only: %i(index show samples archive
|
||||
experiment_archive)
|
||||
before_action :load_archive_vars, only: :archive
|
||||
before_action :check_view_permissions, only: %i(show reports notifications
|
||||
samples experiment_archive
|
||||
samples_index)
|
||||
before_action :check_create_permissions, only: [ :new, :create ]
|
||||
before_action :check_create_permissions, only: %i(new create)
|
||||
before_action :check_manage_permissions, only: :edit
|
||||
|
||||
@filter_by_archived = false
|
||||
|
||||
# except parameter could be used but it is not working.
|
||||
layout :choose_layout
|
||||
layout 'fluid'
|
||||
|
||||
# Action defined in SampleActions
|
||||
DELETE_SAMPLES = 'Delete'.freeze
|
||||
|
@ -27,18 +29,6 @@ class ProjectsController < ApplicationController
|
|||
current_team_switch(Team.find_by_id(params[:team]))
|
||||
end
|
||||
|
||||
if current_user.teams.any?
|
||||
@current_team_id = current_team.id if current_team
|
||||
|
||||
@current_team_id ||= current_user.teams.first.id
|
||||
@current_sort = params[:sort].to_s
|
||||
@projects_by_teams = current_user.projects_by_teams(@current_team_id,
|
||||
@current_sort,
|
||||
@filter_by_archived)
|
||||
else
|
||||
@projects_by_teams = []
|
||||
end
|
||||
|
||||
@teams = current_user.teams
|
||||
|
||||
# New project for create new project modal
|
||||
|
@ -46,7 +36,6 @@ class ProjectsController < ApplicationController
|
|||
end
|
||||
|
||||
def archive
|
||||
@filter_by_archived = true
|
||||
index
|
||||
end
|
||||
|
||||
|
@ -306,6 +295,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, team) if team && team.projects.blank?
|
||||
end
|
||||
|
||||
def project_params
|
||||
params.require(:project).permit(:name, :team_id, :visibility, :archived)
|
||||
end
|
||||
|
@ -318,6 +313,29 @@ class ProjectsController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def load_projects_by_teams
|
||||
if current_user.teams.any?
|
||||
@current_team_id = current_team.id if current_team
|
||||
|
||||
@current_team_id ||= current_user.teams.first.id
|
||||
@current_sort = params[:sort].to_s
|
||||
@projects_by_teams = current_user.projects_by_teams(@current_team_id,
|
||||
@current_sort,
|
||||
false)
|
||||
else
|
||||
@projects_by_teams = []
|
||||
end
|
||||
end
|
||||
|
||||
def load_archive_vars
|
||||
if current_user.teams.any?
|
||||
@archived_projects_by_teams =
|
||||
current_user.projects_by_teams(@current_team_id, @current_sort, true)
|
||||
else
|
||||
@projects_by_teams = []
|
||||
end
|
||||
end
|
||||
|
||||
def check_view_permissions
|
||||
render_403 unless can_read_project?(@project)
|
||||
end
|
||||
|
@ -329,8 +347,4 @@ class ProjectsController < ApplicationController
|
|||
def check_manage_permissions
|
||||
render_403 unless can_manage_project?(@project)
|
||||
end
|
||||
|
||||
def choose_layout
|
||||
action_name.in?(['index', 'archive']) ? 'main' : 'fluid'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,37 +5,11 @@ class ReportsController < ApplicationController
|
|||
# used via target='_blank')
|
||||
protect_from_forgery with: :exception, except: :generate
|
||||
|
||||
before_action :load_vars, only: [
|
||||
:edit,
|
||||
:update
|
||||
]
|
||||
before_action :load_vars_nested, only: [
|
||||
:index,
|
||||
:new,
|
||||
:create,
|
||||
:edit,
|
||||
:update,
|
||||
:generate,
|
||||
:destroy,
|
||||
:save_modal,
|
||||
:project_contents_modal,
|
||||
:experiment_contents_modal,
|
||||
:module_contents_modal,
|
||||
:step_contents_modal,
|
||||
:result_contents_modal,
|
||||
:project_contents,
|
||||
:module_contents,
|
||||
:step_contents,
|
||||
:result_contents
|
||||
]
|
||||
|
||||
before_action :check_view_permissions, only: :index
|
||||
before_action :check_manage_permissions, only: %i(
|
||||
BEFORE_ACTION_METHODS = %i(
|
||||
new
|
||||
create
|
||||
edit
|
||||
update
|
||||
destroy
|
||||
generate
|
||||
save_modal
|
||||
project_contents_modal
|
||||
|
@ -47,12 +21,29 @@ class ReportsController < ApplicationController
|
|||
module_contents
|
||||
step_contents
|
||||
result_contents
|
||||
)
|
||||
).freeze
|
||||
|
||||
layout 'fluid'
|
||||
before_action :load_vars, only: %i(edit update)
|
||||
before_action :load_vars_nested, only: BEFORE_ACTION_METHODS
|
||||
before_action :load_visible_projects, only: %i(index visible_projects)
|
||||
before_action :load_available_repositories,
|
||||
only: %i(new edit available_repositories)
|
||||
|
||||
before_action :check_manage_permissions, only: BEFORE_ACTION_METHODS
|
||||
|
||||
# Index showing all reports of a single project
|
||||
def index
|
||||
def index; end
|
||||
|
||||
def datatable
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
render json: ::ReportDatatable.new(
|
||||
view_context,
|
||||
current_user,
|
||||
current_team.datatables_reports.visible_by(current_user, current_team)
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Report grouped by modules
|
||||
|
@ -72,6 +63,7 @@ class ReportsController < ApplicationController
|
|||
@report = Report.new(report_params)
|
||||
@report.project = @project
|
||||
@report.user = current_user
|
||||
@report.team = current_team
|
||||
@report.last_modified_by = current_user
|
||||
|
||||
if continue && @report.save_with_contents(report_contents)
|
||||
|
@ -88,7 +80,7 @@ class ReportsController < ApplicationController
|
|||
)
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
render json: { url: project_reports_path(@project) }, status: :ok
|
||||
render json: { url: reports_path }, status: :ok
|
||||
end
|
||||
end
|
||||
else
|
||||
|
@ -133,7 +125,7 @@ class ReportsController < ApplicationController
|
|||
)
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
render json: { url: project_reports_path(@project) }, status: :ok
|
||||
render json: { url: reports_path }, status: :ok
|
||||
end
|
||||
end
|
||||
else
|
||||
|
@ -155,7 +147,7 @@ class ReportsController < ApplicationController
|
|||
|
||||
report_ids.each do |report_id|
|
||||
report = Report.find_by_id(report_id)
|
||||
next unless report.present?
|
||||
next unless report.present? && can_manage_reports?(current_team)
|
||||
# record an activity
|
||||
Activity.create(
|
||||
type_of: :delete_report,
|
||||
|
@ -170,24 +162,46 @@ class ReportsController < ApplicationController
|
|||
report.destroy
|
||||
end
|
||||
|
||||
redirect_to project_reports_path(@project)
|
||||
redirect_to reports_path
|
||||
end
|
||||
|
||||
# Generation action
|
||||
# Currently, only .PDF is supported
|
||||
def generate
|
||||
content = params[:html]
|
||||
content = I18n.t('projects.reports.new.no_content_for_PDF_html') if content.blank?
|
||||
respond_to do |format|
|
||||
format.pdf do
|
||||
@html = params[:html]
|
||||
@html = '<h1>No content</h1>' if @html.blank?
|
||||
render pdf: 'report',
|
||||
header: { right: '[page] of [topage]' },
|
||||
template: 'reports/report.pdf.erb',
|
||||
disable_javascript: true
|
||||
render pdf: 'report', header: { right: '[page] of [topage]' },
|
||||
locals: { content: content },
|
||||
template: 'reports/report.pdf.erb',
|
||||
disable_javascript: true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def save_pdf_to_inventory_item
|
||||
save_pdf_to_inventory_item = ReportActions::SavePdfToInventoryItem.new(
|
||||
current_user, current_team, save_PDF_params
|
||||
)
|
||||
if save_pdf_to_inventory_item.save
|
||||
render json: {
|
||||
message: I18n.t(
|
||||
'projects.reports.new.save_PDF_to_inventory_modal.success_flash'
|
||||
)
|
||||
}, status: :ok
|
||||
else
|
||||
render json: { message: save_pdf_to_inventory_item.error_messages },
|
||||
status: :unprocessable_entity
|
||||
end
|
||||
rescue ReportActions::RepositoryPermissionError => error
|
||||
render json: { message: error },
|
||||
status: :forbidden
|
||||
rescue Exception => error
|
||||
render json: { message: error.message },
|
||||
status: :internal_server_error
|
||||
end
|
||||
|
||||
# Modal for saving the existsing/new report
|
||||
def save_modal
|
||||
# Assume user is updating existing report
|
||||
|
@ -434,8 +448,20 @@ class ReportsController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def visible_projects
|
||||
render json: { projects: @visible_projects }, status: :ok
|
||||
end
|
||||
|
||||
def available_repositories
|
||||
render json: { results: @available_repositories }, status: :ok
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
include StringUtility
|
||||
VisibleProject = Struct.new(:path, :name)
|
||||
AvailableRepository = Struct.new(:id, :name)
|
||||
|
||||
def load_vars
|
||||
@report = Report.find_by_id(params[:id])
|
||||
render_404 unless @report
|
||||
|
@ -446,16 +472,45 @@ class ReportsController < ApplicationController
|
|||
render_404 unless @project
|
||||
end
|
||||
|
||||
def check_view_permissions
|
||||
render_403 unless can_read_project?(@project)
|
||||
def check_manage_permissions
|
||||
render_403 unless can_manage_reports?(@project.team)
|
||||
end
|
||||
|
||||
def check_manage_permissions
|
||||
render_403 unless can_manage_reports?(@project)
|
||||
def load_visible_projects
|
||||
render_404 unless current_team
|
||||
projects = current_team.projects.visible_from_user_by_name(
|
||||
current_user, current_team, search_params[:q]
|
||||
).limit(Constants::SEARCH_LIMIT).select(:id, :name)
|
||||
@visible_projects = projects.collect do |project|
|
||||
VisibleProject.new(new_project_reports_path(project),
|
||||
ellipsize(project.name, 50, 40))
|
||||
end
|
||||
end
|
||||
|
||||
def load_available_repositories
|
||||
repositories = current_team.repositories
|
||||
.name_like(search_params[:q])
|
||||
.limit(Constants::SEARCH_LIMIT)
|
||||
.select(:id, :name)
|
||||
@available_repositories = repositories.collect do |repository|
|
||||
AvailableRepository.new(repository.id,
|
||||
ellipsize(repository.name, 75, 50))
|
||||
end
|
||||
end
|
||||
|
||||
def report_params
|
||||
params.require(:report)
|
||||
.permit(:name, :description, :grouped_by, :report_contents)
|
||||
end
|
||||
|
||||
def search_params
|
||||
params.permit(:q)
|
||||
end
|
||||
|
||||
def save_PDF_params
|
||||
params.permit(:repository_id,
|
||||
:respository_column_id,
|
||||
:repository_item_id,
|
||||
:html)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,27 +5,22 @@ class RepositoriesController < ApplicationController
|
|||
%i(repository_table_index export_repository parse_sheet import_records)
|
||||
before_action :check_team, only: %i(parse_sheet import_records)
|
||||
before_action :check_view_all_permissions, only: :index
|
||||
before_action :check_view_permissions, only: :export_repository
|
||||
before_action :check_view_permissions, only: %i(export_repository show)
|
||||
before_action :check_manage_permissions, only:
|
||||
%i(destroy destroy_modal rename_modal update)
|
||||
before_action :check_create_permissions, only:
|
||||
%i(create_new_modal create copy_modal copy)
|
||||
%i(create_modal create copy_modal copy)
|
||||
|
||||
layout 'fluid'
|
||||
|
||||
def index
|
||||
render('repositories/index')
|
||||
unless @repositories.length.zero? && current_team
|
||||
redirect_to repository_path(@repositories.first) and return
|
||||
end
|
||||
render 'repositories/index'
|
||||
end
|
||||
|
||||
def show_tab
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
render json: {
|
||||
html: render_to_string(
|
||||
partial: 'repositories/repository.html.erb',
|
||||
locals: { repository: @repository }
|
||||
)
|
||||
}
|
||||
end
|
||||
end
|
||||
def show
|
||||
end
|
||||
|
||||
def create_modal
|
||||
|
@ -53,7 +48,7 @@ class RepositoriesController < ApplicationController
|
|||
if @repository.save
|
||||
flash[:success] = t('repositories.index.modal_create.success_flash',
|
||||
name: @repository.name)
|
||||
render json: { url: team_repositories_path(repository: @repository) },
|
||||
render json: { url: repository_path(@repository) },
|
||||
status: :ok
|
||||
else
|
||||
render json: @repository.errors,
|
||||
|
@ -78,7 +73,8 @@ class RepositoriesController < ApplicationController
|
|||
def destroy
|
||||
flash[:success] = t('repositories.index.delete_flash',
|
||||
name: @repository.name)
|
||||
@repository.destroy
|
||||
@repository.discard
|
||||
ClearDiscardedRepositoriesJob.perform_later
|
||||
redirect_to team_repositories_path
|
||||
end
|
||||
|
||||
|
@ -261,7 +257,7 @@ class RepositoriesController < ApplicationController
|
|||
|
||||
def export_repository
|
||||
if params[:row_ids] && params[:header_ids]
|
||||
generate_zip
|
||||
RepositoryZipExport.generate_zip(params, @repository, current_user)
|
||||
else
|
||||
flash[:alert] = t('zip_export.export_error')
|
||||
end
|
||||
|
@ -287,7 +283,7 @@ class RepositoriesController < ApplicationController
|
|||
end
|
||||
|
||||
def load_parent_vars
|
||||
@team = Team.find_by_id(params[:team_id])
|
||||
@team = current_team
|
||||
render_404 unless @team
|
||||
@repositories = @team.repositories.order(created_at: :asc)
|
||||
end
|
||||
|
@ -305,8 +301,10 @@ class RepositoriesController < ApplicationController
|
|||
end
|
||||
|
||||
def check_create_permissions
|
||||
render_403 unless can_create_repositories?(@team) ||
|
||||
@team.repositories.count < Constants::REPOSITORIES_LIMIT
|
||||
unless can_create_repositories?(@team) ||
|
||||
@team.repositories.count < Rails.configuration.x.repositories_limit
|
||||
render_403
|
||||
end
|
||||
end
|
||||
|
||||
def check_manage_permissions
|
||||
|
@ -333,66 +331,4 @@ class RepositoriesController < ApplicationController
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
def generate_zip
|
||||
# Fetch rows in the same order as in the currently viewed datatable
|
||||
ordered_row_ids = params[:row_ids]
|
||||
id_row_map = RepositoryRow.where(id: ordered_row_ids,
|
||||
repository: @repository)
|
||||
.index_by(&:id)
|
||||
ordered_rows = ordered_row_ids.collect { |id| id_row_map[id.to_i] }
|
||||
|
||||
zip = ZipExport.create(user: current_user)
|
||||
zip.generate_exportable_zip(
|
||||
current_user,
|
||||
to_csv(ordered_rows, params[:header_ids]),
|
||||
:repositories
|
||||
)
|
||||
end
|
||||
|
||||
def to_csv(rows, column_ids)
|
||||
require 'csv'
|
||||
|
||||
# Parse column names
|
||||
csv_header = []
|
||||
column_ids.each do |c_id|
|
||||
csv_header << case c_id.to_i
|
||||
when -1, -2
|
||||
next
|
||||
when -3
|
||||
I18n.t('repositories.table.row_name')
|
||||
when -4
|
||||
I18n.t('repositories.table.added_by')
|
||||
when -5
|
||||
I18n.t('repositories.table.added_on')
|
||||
else
|
||||
column = RepositoryColumn.find_by_id(c_id)
|
||||
column ? column.name : nil
|
||||
end
|
||||
end
|
||||
|
||||
CSV.generate do |csv|
|
||||
csv << csv_header
|
||||
rows.each do |row|
|
||||
csv_row = []
|
||||
column_ids.each do |c_id|
|
||||
csv_row << case c_id.to_i
|
||||
when -1, -2
|
||||
next
|
||||
when -3
|
||||
row.name
|
||||
when -4
|
||||
row.created_by.full_name
|
||||
when -5
|
||||
I18n.l(row.created_at, format: :full)
|
||||
else
|
||||
cell = row.repository_cells
|
||||
.find_by(repository_column_id: c_id)
|
||||
cell ? cell.value.data : nil
|
||||
end
|
||||
end
|
||||
csv << csv_row
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,39 +1,67 @@
|
|||
class RepositoryColumnsController < ApplicationController
|
||||
include InputSanitizeHelper
|
||||
|
||||
before_action :load_vars, except: :create
|
||||
before_action :load_vars_nested, only: :create
|
||||
ACTIONS = %i(create index create_html available_asset_type_columns).freeze
|
||||
before_action :load_vars,
|
||||
except: ACTIONS
|
||||
before_action :load_vars_nested,
|
||||
only: ACTIONS
|
||||
before_action :check_create_permissions, only: :create
|
||||
before_action :check_manage_permissions, except: :create
|
||||
before_action :check_manage_permissions,
|
||||
except: ACTIONS
|
||||
before_action :load_repository_columns, only: :index
|
||||
before_action :load_asset_type_columns, only: :available_asset_type_columns
|
||||
|
||||
def index; end
|
||||
|
||||
def create_html
|
||||
@repository_column = RepositoryColumn.new
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
render json: {
|
||||
html: render_to_string(
|
||||
partial: 'repository_columns/manage_column_modal.html.erb'
|
||||
)
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
@repository_column = RepositoryColumn.new(repository_column_params)
|
||||
@repository_column.repository = @repository
|
||||
@repository_column.created_by = current_user
|
||||
@repository_column.data_type = :RepositoryTextValue
|
||||
|
||||
respond_to do |format|
|
||||
if @repository_column.save
|
||||
format.json do
|
||||
render json: {
|
||||
id: @repository_column.id,
|
||||
name: escape_input(@repository_column.name),
|
||||
edit_url:
|
||||
edit_repository_repository_column_path(@repository,
|
||||
@repository_column),
|
||||
update_url:
|
||||
repository_repository_column_path(@repository,
|
||||
@repository_column),
|
||||
destroy_html_url:
|
||||
repository_columns_destroy_html_path(
|
||||
@repository, @repository_column
|
||||
)
|
||||
},
|
||||
status: :ok
|
||||
end
|
||||
else
|
||||
format.json do
|
||||
render json: @repository_column.errors.to_json,
|
||||
format.json do
|
||||
if @repository_column.save
|
||||
if generate_repository_list_items(params[:list_items])
|
||||
render json: {
|
||||
id: @repository_column.id,
|
||||
name: escape_input(@repository_column.name),
|
||||
message: t('libraries.repository_columns.create.success_flash',
|
||||
name: @repository_column.name),
|
||||
edit_url:
|
||||
edit_repository_repository_column_path(@repository,
|
||||
@repository_column),
|
||||
update_url:
|
||||
repository_repository_column_path(@repository,
|
||||
@repository_column),
|
||||
destroy_html_url:
|
||||
repository_columns_destroy_html_path(@repository,
|
||||
@repository_column)
|
||||
},
|
||||
status: :ok
|
||||
else
|
||||
render json: {
|
||||
message: {
|
||||
repository_list_items:
|
||||
t('libraries.repository_columns.repository_list_items_limit',
|
||||
limit: Constants::REPOSITORY_LIST_ITEMS_PER_COLUMN)
|
||||
}
|
||||
}, status: :unprocessable_entity
|
||||
end
|
||||
else
|
||||
render json: { message: @repository_column.errors.full_messages },
|
||||
status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
@ -43,7 +71,11 @@ class RepositoryColumnsController < ApplicationController
|
|||
def edit
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
render json: { status: :ok }
|
||||
render json: {
|
||||
html: render_to_string(
|
||||
partial: 'repository_columns/manage_column_modal.html.erb'
|
||||
)
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -53,9 +85,24 @@ class RepositoryColumnsController < ApplicationController
|
|||
format.json do
|
||||
@repository_column.update_attributes(repository_column_params)
|
||||
if @repository_column.save
|
||||
render json: { status: :ok }
|
||||
if update_repository_list_items(params[:list_items])
|
||||
render json: {
|
||||
id: @repository_column.id,
|
||||
name: escape_input(@repository_column.name),
|
||||
message: t('libraries.repository_columns.update.success_flash',
|
||||
name: @repository_column.name)
|
||||
}, status: :ok
|
||||
else
|
||||
render json: {
|
||||
message: {
|
||||
repository_list_items:
|
||||
t('libraries.repository_columns.repository_list_items_limit',
|
||||
limit: Constants::REPOSITORY_LIST_ITEMS_PER_COLUMN)
|
||||
}
|
||||
}, status: :unprocessable_entity
|
||||
end
|
||||
else
|
||||
render json: @repository_column.errors.to_json,
|
||||
render json: { message: @repository_column.errors.full_messages },
|
||||
status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
@ -67,8 +114,7 @@ class RepositoryColumnsController < ApplicationController
|
|||
format.json do
|
||||
render json: {
|
||||
html: render_to_string(
|
||||
partial: 'repositories/delete_column_modal_body.html.erb',
|
||||
locals: { column_index: params[:column_index] }
|
||||
partial: 'repository_columns/delete_column_modal_body.html.erb'
|
||||
)
|
||||
}
|
||||
end
|
||||
|
@ -76,25 +122,44 @@ class RepositoryColumnsController < ApplicationController
|
|||
end
|
||||
|
||||
def destroy
|
||||
@del_repository_column = @repository_column.dup
|
||||
column_id = @repository_column.id
|
||||
column_name = @repository_column.name
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
if @repository_column.destroy
|
||||
RepositoryTableState.update_state(
|
||||
@del_repository_column,
|
||||
params[:repository_column][:column_index],
|
||||
current_user
|
||||
)
|
||||
render json: { status: :ok }
|
||||
render json: {
|
||||
message: t('libraries.repository_columns.destroy.success_flash',
|
||||
name: column_name),
|
||||
id: column_id,
|
||||
status: :ok
|
||||
}
|
||||
else
|
||||
render json: { status: :unprocessable_entity }
|
||||
render json: {
|
||||
message: t('libraries.repository_columns.destroy.error_flash'),
|
||||
status: :unprocessable_entity
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def available_asset_type_columns
|
||||
if @asset_columns.empty?
|
||||
render json: {
|
||||
no_items: t(
|
||||
'projects.reports.new.save_PDF_to_inventory_modal.no_columns'
|
||||
)
|
||||
}, status: :ok
|
||||
else
|
||||
render json: { results: @asset_columns }, status: :ok
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
include StringUtility
|
||||
AvailableRepositoryColumn = Struct.new(:id, :name)
|
||||
|
||||
def load_vars
|
||||
@repository = Repository.find_by_id(params[:repository_id])
|
||||
render_404 unless @repository
|
||||
|
@ -107,6 +172,16 @@ class RepositoryColumnsController < ApplicationController
|
|||
render_404 unless @repository
|
||||
end
|
||||
|
||||
def load_repository_columns
|
||||
@repository_columns = @repository.repository_columns
|
||||
.order(created_at: :desc)
|
||||
end
|
||||
|
||||
def load_asset_type_columns
|
||||
render_403 unless can_read_team?(@repository.team)
|
||||
@asset_columns = load_asset_columns(search_params[:q])
|
||||
end
|
||||
|
||||
def check_create_permissions
|
||||
render_403 unless can_create_repository_columns?(@repository.team)
|
||||
end
|
||||
|
@ -116,6 +191,80 @@ class RepositoryColumnsController < ApplicationController
|
|||
end
|
||||
|
||||
def repository_column_params
|
||||
params.require(:repository_column).permit(:name)
|
||||
params.require(:repository_column).permit(:name, :data_type)
|
||||
end
|
||||
|
||||
def search_params
|
||||
params.permit(:q, :repository_id)
|
||||
end
|
||||
|
||||
def load_asset_columns(query)
|
||||
@repository.repository_columns
|
||||
.asset_type.name_like(query)
|
||||
.limit(Constants::SEARCH_LIMIT)
|
||||
.select(:id, :name)
|
||||
.collect do |column|
|
||||
AvailableRepositoryColumn.new(
|
||||
column.id,
|
||||
ellipsize(column.name, 75, 50)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def generate_repository_list_items(item_names)
|
||||
return true unless @repository_column.data_type == 'RepositoryListValue'
|
||||
column_items = @repository_column.repository_list_items.size
|
||||
success = true
|
||||
item_names.split(',').uniq.each do |name|
|
||||
if column_items >= Constants::REPOSITORY_LIST_ITEMS_PER_COLUMN
|
||||
success = false
|
||||
next
|
||||
end
|
||||
RepositoryListItem.create(
|
||||
repository: @repository,
|
||||
repository_column: @repository_column,
|
||||
data: name,
|
||||
created_by: current_user,
|
||||
last_modified_by: current_user
|
||||
)
|
||||
column_items += 1
|
||||
end
|
||||
success
|
||||
end
|
||||
|
||||
def update_repository_list_items(item_names)
|
||||
return true unless @repository_column.data_type == 'RepositoryListValue'
|
||||
column_items = @repository_column.repository_list_items.size
|
||||
items_list = item_names.split(',').uniq
|
||||
existing = @repository_column.repository_list_items.pluck(:data)
|
||||
existing.each do |name|
|
||||
next if items_list.include? name
|
||||
list_item_id = @repository_column.repository_list_items
|
||||
.find_by_data(name)
|
||||
.destroy
|
||||
.id
|
||||
RepositoryCell.where(
|
||||
'value_type = ? AND value_id = ?',
|
||||
'RepositoryListValue',
|
||||
list_item_id
|
||||
).destroy_all
|
||||
end
|
||||
success = true
|
||||
items_list.each do |name|
|
||||
next if @repository_column.repository_list_items.find_by_data(name)
|
||||
if column_items >= Constants::REPOSITORY_LIST_ITEMS_PER_COLUMN
|
||||
success = false
|
||||
next
|
||||
end
|
||||
RepositoryListItem.create(
|
||||
repository: @repository,
|
||||
repository_column: @repository_column,
|
||||
data: name,
|
||||
created_by: current_user,
|
||||
last_modified_by: current_user
|
||||
)
|
||||
column_items += 1
|
||||
end
|
||||
success
|
||||
end
|
||||
end
|
||||
|
|
28
app/controllers/repository_list_items_controller.rb
Normal file
|
@ -0,0 +1,28 @@
|
|||
class RepositoryListItemsController < ApplicationController
|
||||
before_action :load_vars, only: :search
|
||||
|
||||
def search
|
||||
column_list_items = @repository_column.repository_list_items
|
||||
.where('data ILIKE ?',
|
||||
"%#{search_params[:q]}%")
|
||||
.limit(Constants::SEARCH_LIMIT)
|
||||
.select(:id, :data)
|
||||
|
||||
render json: { list_items: column_list_items }, status: :ok
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def search_params
|
||||
params.permit(:q, :column_id)
|
||||
end
|
||||
|
||||
def load_vars
|
||||
@repository_column = RepositoryColumn.find_by_id(search_params[:column_id])
|
||||
repository = @repository_column.repository if @repository_column
|
||||
unless @repository_column&.data_type == 'RepositoryListValue'
|
||||
render_404 and return
|
||||
end
|
||||
render_403 unless can_manage_repository_rows?(repository.team)
|
||||
end
|
||||
end
|
|
@ -3,10 +3,30 @@ class RepositoryRowsController < ApplicationController
|
|||
include ActionView::Helpers::TextHelper
|
||||
include ApplicationHelper
|
||||
|
||||
before_action :load_info_modal_vars, only: :show
|
||||
before_action :load_vars, only: %i(edit update)
|
||||
before_action :load_repository, only: %i(create delete_records)
|
||||
before_action :load_repository,
|
||||
only: %i(create
|
||||
delete_records
|
||||
index
|
||||
copy_records
|
||||
available_rows)
|
||||
before_action :check_create_permissions, only: :create
|
||||
before_action :check_manage_permissions, only: %i(edit update delete_records)
|
||||
before_action :check_manage_permissions,
|
||||
only: %i(edit update delete_records copy_records)
|
||||
|
||||
def index
|
||||
@draw = params[:draw].to_i
|
||||
per_page = params[:length] == '-1' ? 100 : params[:length].to_i
|
||||
page = (params[:start].to_i / per_page) + 1
|
||||
records = RepositoryDatatableService.new(@repository,
|
||||
params,
|
||||
current_user)
|
||||
@assigned_rows = records.assigned_rows
|
||||
@repository_row_count = records.repository_rows.count
|
||||
@columns_mappings = records.mappings
|
||||
@repository_rows = records.repository_rows.page(page).per(per_page)
|
||||
end
|
||||
|
||||
def create
|
||||
record = RepositoryRow.new(repository: @repository,
|
||||
|
@ -16,29 +36,11 @@ class RepositoryRowsController < ApplicationController
|
|||
repository_cells: [] }
|
||||
|
||||
record.transaction do
|
||||
record.name = record_params[:name] unless record_params[:name].blank?
|
||||
record.name = record_params[:repository_row_name] unless record_params[:repository_row_name].blank?
|
||||
errors[:default_fields] = record.errors.messages unless record.save
|
||||
if cell_params
|
||||
cell_params.each do |key, value|
|
||||
column = @repository.repository_columns.detect do |c|
|
||||
c.id == key.to_i
|
||||
end
|
||||
cell_value = RepositoryTextValue.new(
|
||||
data: value,
|
||||
created_by: current_user,
|
||||
last_modified_by: current_user,
|
||||
repository_cell_attributes: {
|
||||
repository_row: record,
|
||||
repository_column: column
|
||||
}
|
||||
)
|
||||
if cell_value.save
|
||||
record_annotation_notification(record, cell_value.repository_cell)
|
||||
else
|
||||
errors[:repository_cells] << {
|
||||
"#{column.id}": cell_value.errors.messages
|
||||
}
|
||||
end
|
||||
next if create_cell_value(record, key, value, errors).nil?
|
||||
end
|
||||
end
|
||||
raise ActiveRecord::Rollback if errors[:repository_cells].any?
|
||||
|
@ -60,19 +62,40 @@ class RepositoryRowsController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def show
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
render json: {
|
||||
html: render_to_string(
|
||||
partial: 'repositories/repository_row_info_modal.html.erb'
|
||||
)
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
json = {
|
||||
repository_row: {
|
||||
name: escape_input(@record.name),
|
||||
repository_cells: {}
|
||||
repository_cells: {},
|
||||
repository_column_items: fetch_columns_list_items
|
||||
}
|
||||
}
|
||||
|
||||
# Add custom cells ids as key (easier lookup on js side)
|
||||
@record.repository_cells.each do |cell|
|
||||
if cell.value_type == 'RepositoryAssetValue'
|
||||
cell_value = cell.value.asset if cell.value_type == 'RepositoryAssetValue'
|
||||
else
|
||||
cell_value = escape_input(cell.value.data)
|
||||
end
|
||||
|
||||
json[:repository_row][:repository_cells][cell.repository_column_id] = {
|
||||
repository_cell_id: cell.id,
|
||||
value: escape_input(cell.value.data)
|
||||
value: cell_value,
|
||||
type: cell.value_type,
|
||||
list_items: fetch_list_items(cell)
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -89,7 +112,7 @@ class RepositoryRowsController < ApplicationController
|
|||
}
|
||||
|
||||
@record.transaction do
|
||||
@record.name = record_params[:name].blank? ? nil : record_params[:name]
|
||||
@record.name = record_params[:repository_row_name].blank? ? nil : record_params[:repository_row_name]
|
||||
errors[:default_fields] = @record.errors.messages unless @record.save
|
||||
if cell_params
|
||||
cell_params.each do |key, value|
|
||||
|
@ -98,42 +121,48 @@ class RepositoryRowsController < ApplicationController
|
|||
end
|
||||
if existing
|
||||
# Cell exists and new value present, so update value
|
||||
existing.value.data = value
|
||||
if existing.value.save
|
||||
record_annotation_notification(@record, existing)
|
||||
if existing.value_type == 'RepositoryListValue'
|
||||
item = RepositoryListItem.where(
|
||||
repository_column: existing.repository_column
|
||||
).find(value) unless value == '-1'
|
||||
if item
|
||||
existing.value.update_attribute(
|
||||
:repository_list_item_id, item.id
|
||||
)
|
||||
else
|
||||
existing.delete
|
||||
end
|
||||
elsif existing.value_type == 'RepositoryAssetValue'
|
||||
next if value.blank?
|
||||
if existing.value.asset.update(file: value)
|
||||
existing.value.asset.created_by = current_user
|
||||
existing.value.asset.last_modified_by = current_user
|
||||
existing.value.asset.post_process_file(current_team)
|
||||
else
|
||||
errors[:repository_cells] << {
|
||||
"#{existing.repository_column_id}": { data: existing.value.asset.errors.messages[:file].first }
|
||||
}
|
||||
end
|
||||
else
|
||||
errors[:repository_cells] << {
|
||||
"#{existing.repository_column_id}":
|
||||
existing.value.errors.messages
|
||||
}
|
||||
existing.value.data = value
|
||||
if existing.value.save
|
||||
record_annotation_notification(@record, existing)
|
||||
else
|
||||
errors[:repository_cells] << {
|
||||
"#{existing.repository_column_id}":
|
||||
existing.value.errors.messages
|
||||
}
|
||||
end
|
||||
end
|
||||
else
|
||||
# Looks like it is a new cell, so we need to create new value, cell
|
||||
# will be created automatically
|
||||
column = @repository.repository_columns.detect do |c|
|
||||
c.id == key.to_i
|
||||
end
|
||||
cell_value = RepositoryTextValue.new(
|
||||
data: value,
|
||||
created_by: current_user,
|
||||
last_modified_by: current_user,
|
||||
repository_cell_attributes: {
|
||||
repository_row: @record,
|
||||
repository_column: column
|
||||
}
|
||||
)
|
||||
if cell_value.save
|
||||
record_annotation_notification(@record,
|
||||
cell_value.repository_cell)
|
||||
else
|
||||
errors[:repository_cells] << {
|
||||
"#{column.id}": cell_value.errors.messages
|
||||
}
|
||||
end
|
||||
next if create_cell_value(@record, key, value, errors).nil?
|
||||
end
|
||||
end
|
||||
# Clean up empty cells, not present in updated record
|
||||
@record.repository_cells.each do |cell|
|
||||
next if cell.value_type == 'RepositoryListValue'
|
||||
cell.value.destroy unless cell_params
|
||||
.key?(cell.repository_column_id.to_s)
|
||||
end
|
||||
|
@ -165,6 +194,72 @@ class RepositoryRowsController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def create_cell_value(record, key, value, errors)
|
||||
column = @repository.repository_columns.detect do |c|
|
||||
c.id == key.to_i
|
||||
end
|
||||
save_successful = false
|
||||
if column.data_type == 'RepositoryListValue'
|
||||
return if value == '-1'
|
||||
# check if item exists else revert the transaction
|
||||
list_item = RepositoryListItem.where(repository_column: column)
|
||||
.find(value)
|
||||
cell_value = RepositoryListValue.new(
|
||||
repository_list_item_id: list_item.id,
|
||||
created_by: current_user,
|
||||
last_modified_by: current_user,
|
||||
repository_cell_attributes: {
|
||||
repository_row: record,
|
||||
repository_column: column
|
||||
}
|
||||
)
|
||||
save_successful = list_item && cell_value.save
|
||||
elsif column.data_type == 'RepositoryAssetValue'
|
||||
return if value.blank?
|
||||
asset = Asset.new(file: value,
|
||||
created_by: current_user,
|
||||
last_modified_by: current_user,
|
||||
team: current_team)
|
||||
if asset.save
|
||||
asset.post_process_file(current_team)
|
||||
else
|
||||
errors[:repository_cells] << {
|
||||
"#{column.id}": { data: asset.errors.messages[:file].first }
|
||||
}
|
||||
end
|
||||
cell_value = RepositoryAssetValue.new(
|
||||
asset: asset,
|
||||
created_by: current_user,
|
||||
last_modified_by: current_user,
|
||||
repository_cell_attributes: {
|
||||
repository_row: record,
|
||||
repository_column: column
|
||||
}
|
||||
)
|
||||
save_successful = cell_value.save
|
||||
else
|
||||
cell_value = RepositoryTextValue.new(
|
||||
data: value,
|
||||
created_by: current_user,
|
||||
last_modified_by: current_user,
|
||||
repository_cell_attributes: {
|
||||
repository_row: record,
|
||||
repository_column: column
|
||||
}
|
||||
)
|
||||
if (save_successful = cell_value.save)
|
||||
record_annotation_notification(record,
|
||||
cell_value.repository_cell)
|
||||
end
|
||||
end
|
||||
|
||||
unless save_successful
|
||||
errors[:repository_cells] << {
|
||||
"#{column.id}": cell_value.errors.messages
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def delete_records
|
||||
deleted_count = 0
|
||||
if selected_params
|
||||
|
@ -201,8 +296,47 @@ class RepositoryRowsController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def copy_records
|
||||
duplicate_service = RepositoryActions::DuplicateRows.new(
|
||||
current_user, @repository, params[:selected_rows]
|
||||
)
|
||||
duplicate_service.call
|
||||
render json: {
|
||||
flash: t('repositories.copy_records_report',
|
||||
number: duplicate_service.number_of_duplicated_items)
|
||||
}, status: :ok
|
||||
end
|
||||
|
||||
def available_rows
|
||||
if @repository.repository_rows.empty?
|
||||
no_items_string =
|
||||
"#{t('projects.reports.new.save_PDF_to_inventory_modal.no_items')} " \
|
||||
"#{link_to(t('projects.reports.new.save_PDF_to_inventory_modal.here'),
|
||||
repository_path(@repository),
|
||||
data: { 'no-turbolink' => true })}"
|
||||
render json: { no_items: no_items_string },
|
||||
status: :ok
|
||||
else
|
||||
render json: { results: load_available_rows(search_params[:q]) },
|
||||
status: :ok
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
include StringUtility
|
||||
AvailableRepositoryRow = Struct.new(:id, :name, :has_file_attached)
|
||||
|
||||
def load_info_modal_vars
|
||||
@repository_row = RepositoryRow.eager_load(:created_by, repository: [:team])
|
||||
.find_by_id(params[:id])
|
||||
@assigned_modules = MyModuleRepositoryRow.eager_load(
|
||||
my_module: [{ experiment: :project }]
|
||||
).where(repository_row: @repository_row)
|
||||
render_404 and return unless @repository_row
|
||||
render_403 unless can_read_team?(@repository_row.repository.team)
|
||||
end
|
||||
|
||||
def load_vars
|
||||
@repository = Repository.eager_load(:repository_columns)
|
||||
.find_by_id(params[:repository_id])
|
||||
|
@ -214,6 +348,7 @@ class RepositoryRowsController < ApplicationController
|
|||
def load_repository
|
||||
@repository = Repository.find_by_id(params[:repository_id])
|
||||
render_404 unless @repository
|
||||
render_403 unless can_read_team?(@repository.team)
|
||||
end
|
||||
|
||||
def check_create_permissions
|
||||
|
@ -225,7 +360,7 @@ class RepositoryRowsController < ApplicationController
|
|||
end
|
||||
|
||||
def record_params
|
||||
params.require(:repository_row).permit(:name).to_h
|
||||
params.permit(:repository_row_name).to_h
|
||||
end
|
||||
|
||||
def cell_params
|
||||
|
@ -236,6 +371,27 @@ class RepositoryRowsController < ApplicationController
|
|||
params.permit(selected_rows: []).to_h[:selected_rows]
|
||||
end
|
||||
|
||||
def load_available_rows(query)
|
||||
@repository.repository_rows
|
||||
.includes(:repository_cells)
|
||||
.name_like(search_params[:q])
|
||||
.limit(Constants::SEARCH_LIMIT)
|
||||
.select(:id, :name)
|
||||
.collect do |row|
|
||||
with_asset_cell = row.repository_cells.where(
|
||||
'repository_cells.repository_column_id = ?',
|
||||
search_params[:repository_column_id]
|
||||
)
|
||||
AvailableRepositoryRow.new(row.id,
|
||||
ellipsize(row.name, 75, 50),
|
||||
with_asset_cell.present?)
|
||||
end
|
||||
end
|
||||
|
||||
def search_params
|
||||
params.permit(:q, :repository_id, :repository_column_id)
|
||||
end
|
||||
|
||||
def record_annotation_notification(record, cell, old_text = nil)
|
||||
table_url = params.fetch(:request_url) { :request_url_must_be_present }
|
||||
smart_annotation_notification(
|
||||
|
@ -251,4 +407,28 @@ class RepositoryRowsController < ApplicationController
|
|||
column: link_to(cell.repository_column.name, table_url))
|
||||
)
|
||||
end
|
||||
|
||||
def fetch_list_items(cell)
|
||||
return [] if cell.value_type != 'RepositoryListValue'
|
||||
RepositoryListItem.where(repository: @repository)
|
||||
.where(repository_column: cell.repository_column)
|
||||
.limit(Constants::SEARCH_LIMIT)
|
||||
.pluck(:id, :data)
|
||||
end
|
||||
|
||||
def fetch_columns_list_items
|
||||
collection = []
|
||||
@repository.repository_columns
|
||||
.list_type
|
||||
.preload(:repository_list_items)
|
||||
.each do |column|
|
||||
collection << {
|
||||
column_id: column.id,
|
||||
list_items: column.repository_list_items
|
||||
.limit(Constants::SEARCH_LIMIT)
|
||||
.pluck(:id, :data)
|
||||
}
|
||||
end
|
||||
collection
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,6 +4,8 @@ class SearchController < ApplicationController
|
|||
def index
|
||||
redirect_to new_search_path unless @search_query
|
||||
|
||||
@search_id = params[:search_id] ? params[:search_id] : generate_search_id
|
||||
|
||||
count_search_results
|
||||
|
||||
search_projects if @search_category == :projects
|
||||
|
@ -15,7 +17,6 @@ class SearchController < ApplicationController
|
|||
search_protocols if @search_category == :protocols
|
||||
search_steps if @search_category == :steps
|
||||
search_checklists if @search_category == :checklists
|
||||
search_samples if @search_category == :samples
|
||||
if @search_category == :repositories && params[:repository]
|
||||
search_repository
|
||||
end
|
||||
|
@ -86,6 +87,10 @@ class SearchController < ApplicationController
|
|||
|
||||
protected
|
||||
|
||||
def generate_search_id
|
||||
SecureRandom.urlsafe_base64(32)
|
||||
end
|
||||
|
||||
def search_by_name(model)
|
||||
model.search(current_user,
|
||||
true,
|
||||
|
@ -109,53 +114,70 @@ class SearchController < ApplicationController
|
|||
end
|
||||
|
||||
def count_by_repository
|
||||
count_total = 0
|
||||
search_results = Repository.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)
|
||||
@repository_search_count = {}
|
||||
current_user.teams.includes(:repositories).each do |team|
|
||||
team_results = {}
|
||||
team_results[:count] = 0
|
||||
team_results[:repositories] = {}
|
||||
team.repositories.each do |repository|
|
||||
repository_results = {}
|
||||
repository_results[:id] = repository.id
|
||||
repository_results[:count] = 0
|
||||
search_results.each do |result|
|
||||
if repository.id == result.id
|
||||
count_total += result.counter
|
||||
repository_results[:count] += result.counter
|
||||
@repository_search_count =
|
||||
Rails.cache.fetch("#{@search_id}/repository_search_count",
|
||||
expires_in: 5.minutes) do
|
||||
search_count = {}
|
||||
search_results = Repository.search(current_user,
|
||||
@search_query,
|
||||
Constants::SEARCH_NO_LIMIT,
|
||||
nil,
|
||||
match_case: @search_case,
|
||||
whole_word: @search_whole_word,
|
||||
whole_phrase: @search_whole_phrase)
|
||||
|
||||
current_user.teams.includes(:repositories).each do |team|
|
||||
team_results = {}
|
||||
team_results[:count] = 0
|
||||
team_results[:repositories] = {}
|
||||
team.repositories.each do |repository|
|
||||
repository_results = {}
|
||||
repository_results[:id] = repository.id
|
||||
repository_results[:count] = 0
|
||||
search_results.each do |result|
|
||||
if repository.id == result.id
|
||||
repository_results[:count] += result.counter
|
||||
end
|
||||
end
|
||||
team_results[:repositories][repository.name] = repository_results
|
||||
team_results[:count] += repository_results[:count]
|
||||
end
|
||||
search_count[team.name] = team_results
|
||||
end
|
||||
team_results[:repositories][repository.name] = repository_results
|
||||
team_results[:count] += repository_results[:count]
|
||||
search_count
|
||||
end
|
||||
@repository_search_count[team.name] = team_results
|
||||
|
||||
count_total = 0
|
||||
@repository_search_count.each_value do |team_results|
|
||||
count_total += team_results[:count]
|
||||
end
|
||||
count_total
|
||||
end
|
||||
|
||||
def current_repository_search_count
|
||||
@repository_search_count.each_value do |counter|
|
||||
res = counter[:repositories].values.detect do |rep|
|
||||
rep[:id] == @repository.id
|
||||
end
|
||||
return res[:count] if res && res[:count]
|
||||
end
|
||||
end
|
||||
|
||||
def count_search_results
|
||||
@project_search_count = count_by_name Project
|
||||
@experiment_search_count = count_by_name Experiment
|
||||
@module_search_count = count_by_name MyModule
|
||||
@result_search_count = count_by_name Result
|
||||
@tag_search_count = count_by_name Tag
|
||||
@report_search_count = count_by_name Report
|
||||
@protocol_search_count = count_by_name Protocol
|
||||
@step_search_count = count_by_name Step
|
||||
@checklist_search_count = count_by_name Checklist
|
||||
@sample_search_count = count_by_name Sample
|
||||
@project_search_count = fetch_cached_count Project
|
||||
@experiment_search_count = fetch_cached_count Experiment
|
||||
@module_search_count = fetch_cached_count MyModule
|
||||
@result_search_count = fetch_cached_count Result
|
||||
@tag_search_count = fetch_cached_count Tag
|
||||
@report_search_count = fetch_cached_count Report
|
||||
@protocol_search_count = fetch_cached_count Protocol
|
||||
@step_search_count = fetch_cached_count Step
|
||||
@checklist_search_count = fetch_cached_count Checklist
|
||||
@sample_search_count = fetch_cached_count Sample
|
||||
@repository_search_count_total = count_by_repository
|
||||
@asset_search_count = count_by_name Asset
|
||||
@table_search_count = count_by_name Table
|
||||
@comment_search_count = count_by_name Comment
|
||||
@asset_search_count = fetch_cached_count Asset
|
||||
@table_search_count = fetch_cached_count Table
|
||||
@comment_search_count = fetch_cached_count Comment
|
||||
|
||||
@search_results_count = @project_search_count
|
||||
@search_results_count += @experiment_search_count
|
||||
|
@ -173,6 +195,15 @@ class SearchController < ApplicationController
|
|||
@search_results_count += @comment_search_count
|
||||
end
|
||||
|
||||
def fetch_cached_count(type)
|
||||
exp = 5.minutes
|
||||
Rails.cache.fetch(
|
||||
"#{@search_id}/#{type.name.underscore}_search_count", expires_in: exp
|
||||
) do
|
||||
count_by_name type
|
||||
end
|
||||
end
|
||||
|
||||
def search_projects
|
||||
@project_results = []
|
||||
@project_results = search_by_name(Project) if @project_search_count > 0
|
||||
|
@ -231,24 +262,19 @@ class SearchController < ApplicationController
|
|||
@search_count = @checklist_search_count
|
||||
end
|
||||
|
||||
def search_samples
|
||||
@sample_results = []
|
||||
@sample_results = search_by_name(Sample) if @sample_search_count > 0
|
||||
@search_count = @sample_search_count
|
||||
end
|
||||
|
||||
def search_repository
|
||||
@repository = Repository.find_by_id(params[:repository])
|
||||
render_403 unless can_read_team?(@repository.team)
|
||||
@repository_results = []
|
||||
if @repository_search_count_total > 0
|
||||
@repository_results =
|
||||
RepositoryRow.search(@repository, @search_query, @search_page,
|
||||
match_case: @search_case,
|
||||
whole_word: @search_whole_word,
|
||||
whole_phrase: @search_whole_phrase)
|
||||
Repository.search(current_user, @search_query, @search_page,
|
||||
@repository,
|
||||
match_case: @search_case,
|
||||
whole_word: @search_whole_word,
|
||||
whole_phrase: @search_whole_phrase)
|
||||
end
|
||||
@search_count = @repository_search_count_total
|
||||
@search_count = current_repository_search_count
|
||||
end
|
||||
|
||||
def search_assets
|
||||
|
|
|
@ -2,15 +2,8 @@ class UserRepositoriesController < ApplicationController
|
|||
before_action :load_vars
|
||||
|
||||
def save_table_state
|
||||
table_state = RepositoryTableState.where(user: current_user,
|
||||
repository: @repository).first
|
||||
if table_state
|
||||
table_state.update(state: params[:state])
|
||||
else
|
||||
RepositoryTableState.create(user: current_user,
|
||||
repository: @repository,
|
||||
state: params[:state])
|
||||
end
|
||||
service = RepositoryTableStateService.new(current_user, @repository)
|
||||
service.update_state(params[:state])
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
render json: {
|
||||
|
@ -21,13 +14,13 @@ class UserRepositoriesController < ApplicationController
|
|||
end
|
||||
|
||||
def load_table_state
|
||||
table_state = RepositoryTableState.load_state(current_user,
|
||||
@repository).first
|
||||
service = RepositoryTableStateService.new(current_user, @repository)
|
||||
state = service.load_state.state
|
||||
respond_to do |format|
|
||||
if table_state
|
||||
if state
|
||||
format.json do
|
||||
render json: {
|
||||
state: table_state
|
||||
state: state
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,6 +4,7 @@ class Users::RegistrationsController < Devise::RegistrationsController
|
|||
only: %i(new create new_with_provider create_with_provider)
|
||||
before_action :sign_up_with_provider_enabled?,
|
||||
only: %i(new_with_provider create_with_provider)
|
||||
layout :layout
|
||||
|
||||
def avatar
|
||||
user = User.find_by_id(params[:id]) || current_user
|
||||
|
@ -291,6 +292,10 @@ class Users::RegistrationsController < Devise::RegistrationsController
|
|||
|
||||
private
|
||||
|
||||
def layout
|
||||
'fluid' if action_name == 'edit'
|
||||
end
|
||||
|
||||
def check_captcha
|
||||
if Rails.configuration.x.enable_recaptcha
|
||||
unless verify_recaptcha
|
||||
|
|
|
@ -2,6 +2,7 @@ module Users
|
|||
module Settings
|
||||
module Account
|
||||
class AddonsController < ApplicationController
|
||||
layout 'fluid'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,10 +5,9 @@ module Users
|
|||
before_action :load_user, only: [
|
||||
:index,
|
||||
:update,
|
||||
:tutorial,
|
||||
:reset_tutorial,
|
||||
:notifications_settings
|
||||
]
|
||||
layout 'fluid'
|
||||
|
||||
def index
|
||||
end
|
||||
|
@ -31,51 +30,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
|
||||
|
|
|
@ -22,6 +22,8 @@ module Users
|
|||
before_action :check_create_team_permission,
|
||||
only: %i(new create)
|
||||
|
||||
layout 'fluid'
|
||||
|
||||
def index
|
||||
@user_teams =
|
||||
@user
|
||||
|
|