diff --git a/.gitignore.keep b/.gitignore.keep deleted file mode 100644 index ad8de45..0000000 --- a/.gitignore.keep +++ /dev/null @@ -1,41 +0,0 @@ -# Backups files -*~ -*.rbc -*.orig -*.bak -*.bkp - -# Temporary files -*.tmp -/tmp/* -/tmp/storage/* -!/tmp/storage/.gitkeep - -# log files -*.log -/log/ - -# Storage directory -/users/* -!/users/.gitkeep - -# Config -config/config.yml -config/environments/* -!config/environments/*.keep -config/initializers/devise.rb -.env - -# Version -version_[0-9-:.]*.json - -# Database -/db/seeds.rb -config/database.yml - -# Secrets -config/initializers/secret_token.rb -config/secrets.yml - -# Precompiled assets -/public/assets/ diff --git a/README.md b/README.md index d8791a3..6796080 100644 --- a/README.md +++ b/README.md @@ -1,361 +1,364 @@ Genocrunch ========== A web-based platform for mining metagenomic data **Official web server:** ## Rights - **Copyright:** All rights reserved. ECOLE POLYTECHNIQUE FEDERALE DE LAUSANNE, Switzerland, Laboratory of Intestinal Immunology, 2016-2018 - **License:** GNU AGPL 3 (See LICENSE.txt for details) - **Authors:** AR Rapin, FPA David, C Pattaroni, J Rougemont, BJ Marsland and NL Harris ## Resources - **Git clone URL:** - **Documentation:** - **License:** - **Dockerfile:** ## Framework Genocrunch uses the ruby on Rails framework with a PostgreSQL database. ## Supported platforms - **Linux** (tested on Ubuntu 16.04 LTS and CentOS 7) - **macOS** (tested on 10.12 Sierra) -## Supported web browsers +## Browser support -- **Mozilla Firefox** (Mobile versions are not supported) +- **Mozilla Firefox** tested on version 60.0.1 Quantum (Ubuntu 16.04 LTS/Windows 10/macOS 10.13) +- **Microsoft Edge** tested on version 42.17134 (Windows 10) +- **Google Chrome** tested on version 67.0.3396.79 (Ubuntu 16.04 LTS/Windows 10) +- **Opera** tested on version 53.0 (Ubuntu 16.04 LTS/Windows 10) ## Requirements - **Ruby version 2.3.1** - **Rails version 5.0.0** - **Python version >=2.7.0 <3.0.0** - **R** (tested with version 3.4.0) ## Installation (Debian Linux and macOS) ### Ruby, Rails and PostgreSQL **Debian Linux** Uninstall possible pre-installed versions of ruby: ``` $ sudo apt-get purge ruby ``` (Re-)install ruby and Rails using rbenv (see [here](https://www.digitalocean.com/community/tutorials/how-to-install-ruby-on-rails-with-rbenv-on-ubuntu-16-04#prerequisites)). Install PostgreSQL and start PostgreSQL server: ``` $ sudo apt-get install postgresql postgresql-contrib libpq-dev $ sudo service postgresql start ``` **macOS** Install ruby and Rails using homebrew and rbenv (see [here](https://www.gorails.com/setup/osx/10.12-sierra)). Install PostgreSQL and start PostgreSQL server with homebrew: ``` $ brew install postgresql $ brew services start postgresql ``` ### Python **Debian Linux** ``` $ sudo apt-get install build-essential python-dev python-pip $ pip install numpy ``` Check that python version is between 2.7.0 and 3.0.0: ``` $ python -V ``` **macOS** If not done yet, install Homebrew: ``` $ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" ``` Install python 2.7 with Homebrew: ``` $ brew install python ``` Check that python version is between 2.7.0 and 3.0.0: ``` $ python -V ``` ### R **Debian Linux** Add the R repository to /etc/apt/sources.list: ``` #/etc/apt/sources.list ... deb http://cran.rstudio.com/bin/linux/ubuntu xenial/ ... ``` ``` $ sudo apt-get install r-base-core libnlopt-dev libcurl4-openssl-dev libxml2 libxml2-dev ``` Open the R environment and check the R version: ``` $ R > R.version.string ``` **macOS** Update XQuartz and Xcode if needed. Download the R binary from CRAN at . Click on the downloaded .pkg file and follow the instructions. ### R dependencies Install required R packages from CRAN and bioconductor: ``` $ sudo R > install.packages(c("ineq", "rjson", "fpc", "multcomp", "FactoMineR", "colorspace", "vegan", "optparse", "gplots", "fossil", "coin", "SNFtool", "devtools")) > source("https://bioconductor.org/biocLite.R") > biocLite("sva") > library(devtools) > install_github("igraph/rigraph") > q() ``` ### Genocrunch web application Create a new rails project and add the Genocrunch files: ``` $ rails new genocrunch -d postgresql -B $ git clone https://git@c4science.ch/source/genocrunch-2.1.git /tmp/genocrunch $ rsync -r /tmp/genocrunch/ /genocrunch $ sudo rm -r /tmp/genocrunch $ cd genocrunch \ && cp gitignore.keep .gitignore \ && cp config/config.yml.keep config/config.yml \ && cp config/database.yml.keep config/database.yml \ && cp config/initializers/devise.rb.keep config/initializers/devise.rb \ && cp config/environments/development.rb.keep config/environments/development.rb \ && cp db/seeds.rb.keep db/seeds.rb ``` Run the `install.sh` script (this is not essential for the application): ``` $ chmod 755 install.sh $ ./install.sh $ source .bashrc # or .bash_profile for macOS ``` The Genocrunch web app will store data files in `users/`. To store data in another location, use a simlink: ``` $ rmdir users && ln -s /path/to/your/custom/storage/location users ``` ### Ruby libraries (gems) Use the Gemefile to install required gems: ``` $ bundle install ``` ### Set application configuration variables Set the application configuration variables in the `config/config.yml` file to fit the current installation needs. All variables are documented in the development section of the file. ### Set genocrunch emails Set the email details that will be used by Genocrunch to send information such as registration confirmation link or password recovery link to users. The following example would set Genocrunch to use an hypothetical gmail address (`app_email@gmail.com`) in development. ``` #config/initializers/devise.rb Devise.setup do |config| ... config.mailer_sender = "app_email@gmail.com" ... ``` ``` #config/environments/development.rb Rails.application.configure do ... config.action_mailer.default_url_options = { :host => 'localhost:3000' } config.action_mailer.smtp_settings = { :address => "smtp.gmail.com", :port => 587, :domain => "mail.google.com", :user_name => "app_email@gmail.com", :password => "app_email_password", :authentication => :plain, :enable_starttls_auto => true } ... ``` ### Setup the PostgreSQL server Create a new role and a new database (you can create different users and databases for development, test and/or production): ``` $ sudo su postgres # for macOS, replace postgres by _postgres $ psql postgres=# CREATE ROLE myusername WITH LOGIN PASSWORD 'mypassword'; postgres=# CREATE DATABASE my_application_db_name OWNER myusername; postgres=# \q $ exit ``` Set the `config/database.yml` file: In development, test and/or production sections, set the `database`, `username` and `password` to fit the corresponding PostgreSQL database. Also make sure to uncomment `host: localhost`: ``` #config/database.yml ... database: my_application_db_name ... username: myusername ... password: mypassword ... host: localhost ... ``` ### Initialize the database Two default users will be created: guest and admin. The guest user is required to try the application without registering/signing-in. The admin user is optional. Seting the guest and admin passwords and emails can be done prior to seeding the database, by editing the `db/seeds.rb` file: ``` #db/seeds.rb User.create!([{username: 'guest', role: 'guest', email: 'guest@guestmailbox.com', # <- HERE confirmed_at: '2017-01-01 00:00:00.000000', password: 'guest_account_password'}, # <- HERE {username: 'admin', role: 'admin', email: 'admin@adminmailbox.com', # <- HERE confirmed_at: '2017-01-01 00:00:00.000000', password: 'admin_account_password'}]) # <- AND THERE ... ``` Run the following commands to create and seed the database. Caution: This will erase previous database tables. Use it for installation, not update. For updates, use migrations or SQL queries. ``` $ rake db:schema:load $ rake db:seed ``` ### Run the Rails server ``` $ rails server ``` You can now access the application in your browser at on your machine and `your.ip.address:3000` on your network. **By default, the server runs in development mode.** ### Start workers * Prefered way: ``` $ RAILS_ENV=development bin/delayed_job -n 2 start ``` OR ``` $ RAILS_ENV=development bin/delayed_job -n 2 restart ``` * Alternative way (not recommanded): ``` $ rake jobs:work ``` You can now create new jobs (run analysis). Read the documentation () for details. ### Create a new version Versions of installed R packages can be referenced in the version page (). For this, run the `get_version.py` script: ``` $ get_version.py ``` This will create a .json file in the working directory with a name looking like `version_2017-12-18_18:03:08.898906.json`. Sign in as admin and navigate to Infos>Versions Click on the **New Version** button and fill the form. In the JSON field, copy the json string contained in the .json file previously created using the `get_version.py` script. Finally, click on the **Create Version** button. ### Terms of service Terms of service can be edited in `public/app/TERMS_OF_SERVICE.txt`. ## Usage See **Infos>Doc** in the application web page (). ## Cleaning up data storage Old jobs can be deleted using the `rake cleanup` task as following. The maximum age allowed for analyses is defined in the `config/config.yml` file uder the fields `max_sandbox_job_age`, for general analyses and `max_job_age` for analyses created by logged in users. ``` $ rake cleanup ``` This can be added as a periodic cron task to automate the cleanup process. Note that Examples will not be deleted by this process. ## Running on Docker See [here](https://c4science.ch/source/genocrunch_docker). diff --git a/app/assets/javascripts/general.js b/app/assets/javascripts/general.js index d25084e..63d4f77 100644 --- a/app/assets/javascripts/general.js +++ b/app/assets/javascripts/general.js @@ -1,30 +1,35 @@ function backToTop() { + $('body, html').animate({scrollTop: $('body').position().top}, + {duration: 400, + easing: 'swing'}); +/* document.body.scrollIntoView({ behavior: 'smooth' }); document.documentElement.scrollIntoView({ behavior: 'smooth' }); +*/ } function randomKey(n) { var choice = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789', k = [...Array(n)]; for (var i = 0; i < n; i++) { k[i] = choice.charAt(Math.floor(Math.random() * choice.length)); } return k; } function scrollTo(source, target) { $('#'+source).on('click', function(){ $('body, html').animate({scrollTop: $('#'+target).position().top}, {duration: 400, easing: 'swing'}); }); } function stopRefresh(refresh_timer) { clearInterval(localStorage.getItem(refresh_timer)); } function selectBtn(id1, id2) { $(id2).addClass("selected"); $(id1).not(id2).removeClass("selected"); } diff --git a/app/assets/stylesheets/form.css.scss b/app/assets/stylesheets/form.css.scss index 94705d2..12a2f76 100644 --- a/app/assets/stylesheets/form.css.scss +++ b/app/assets/stylesheets/form.css.scss @@ -1,455 +1,455 @@ .important { color:red } div.missing_field input{ border-color:red } div.missing_field span.custom-file-control{ border-color:red } .margin_addon { margin-right:10px } .card-text { margin-bottom:15px; } label { margin-bottom:2px; } .form-bool { margin-left:1.25rem; } .group_field { margin-bottom:5px; } .field_group_content{ padding:5px } .fold_bar { background-color:grey; text-align:right } .fold_bar i { color:white; text-align:right } .form-number-field { max-width:80px; overflow:hidden; text-align:right; } -.form_card { - height:50vh; +.form-card { + height:70vh; overflow-y:auto; } #customFile .custom-file-control:lang(en)::after { content: "Select file..."; } #customFile .custom-file-control:lang(en)::before { content: "Click me"; } /*when a value is selected, this class removes the content */ .custom-file-control.selected:lang(en)::after { content: "" !important; } .custom-file { overflow: hidden; } .custom-file-control { white-space: nowrap; } .form-categ { position:absolute; border: solid 1px #999; border-bottom: solid 4px #999; padding:7px; background-color:#f2f2f2; color:#666; height:90vh; width:93%; overflow:hidden; overflow-y:auto; -webkit-transition:max-height .6s ease, background-color .2s ease, border .2s ease; -moz-transition:max-height .6s ease, background-color .2s ease, border .2s ease; -ms-transition:max-height .6s ease, background-color .2s ease, border .2s ease; transition:max-height .6s ease, background-color .2s ease, border .2s ease; .indent-field { margin-left:10px; } .bordered-top-field { border-top:solid 1px #ccc; padding-top:5px; } .form-tabs-selector { margin-bottom:15px; } &:hover { z-index:100; height:auto; max-height:110%; overflow-y:auto; border: solid 1px #333; background-color: #fff; color:#333; -webkit-box-shadow: -1px 1px 2px 1px #B3B3B3; -moz-box-shadow: -1px 1px 2px 1px #B3B3B3; box-shadow: -1px 1px 2px 1px #B3B3B3; } } .file_download { margin-bottom:32px; display:none; &:hover, &:focus, &:active, &.active { color:#333; } } .help-block { padding-top:8px; max-height:0; height:auto; opacity:0; visibility: hidden; -webkit-transition: max-height 0.4s ease, opacity 0.4s ease, visibility 0.8s; -moz-transition: max-height 0.4s ease, opacity 0.4s ease, visibility 0.8s; -ms-transition: max-height 0.4s ease, opacity 0.4s ease, visibility 0.8s; transition: max-height 0.4s ease, opacity 0.4s ease, visibility 0.8s; .file_example { margin-top:2px; display:block; } } .expandable { display:block; border: 1px solid #333; border-radius:5px; padding: 3px; margin-top:2px; margin-bottom:5px; max-height:100%; height:auto; box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -webkit-transition:max-height 1.5s ease; -moz-transition:max-height 1.5s ease; -ms-transition:max-height 1.5s ease; transition:max-height 1.5s ease; .expandable-image { position:absolute; right:90px; margin-left:2px; background-color:#fff; border: 1px solid #d9d9d9; height:auto; max-height:40px; -webkit-box-shadow: 0; -moz-box-shadow: 0; box-shadow: 0; -webkit-transition:max-height 0.7s ease, transform 0.7s ease, webkit-box-shadow 0.7s ease; -moz-transition:max-height 0.7s ease, transform 0.7s ease, -moz-box-shadow 0.7s ease; -ms-transition:max-height 0.7s ease, transform 0.7s ease, box-shadow 0.7s ease; transition:max-height 0.7s ease, transform 0.7s ease, box-shadow 0.7s ease; &:hover { z-index:200; max-height:120px; transform:translate(0, -40px); -webkit-box-shadow: -1px 1px 2px 1px #B3B3B3; -moz-box-shadow: -1px 1px 2px 1px #B3B3B3; box-shadow: -1px 1px 2px 1px #B3B3B3; } } a { color: #666; &:hover, &:focus, &:active, &.active { color:#333; } } .slide-open, .slide-close { padding:3px; float:right; margin-right:7px; } .slider { cursor: pointer; } .slide { display: block; max-height:0; height:auto; opacity:0; visibility: hidden; margin-top: -15px; width: 98%; padding:7px; -webkit-transition:max-height 0.5s ease, opacity 0.5s ease, visibility 0.9s; -moz-transition:max-height 0.5s ease, opacity 0.5s ease, visibility 0.9s; -ms-transition:max-height 0.5s ease, opacity 0.5s ease, visibility 0.9s; transition:max-height 0.5s ease, opacity 0.5s ease, visibility 0.9s; } } .multiselect-btn-container { height:35px; position:relative; display:block; } .form-text { width:auto; max-width:90%; } .input-group-number { width:auto; max-width:110px; } .form-number { text-align:right; } .input-group-addon { width:auto; max-width:50%; } .text-field { color:#333; overflow: hidden; display: inline-block; padding: 0.4em 0.4em; border:solid #999999 1px; border-radius: 5px; background-color: rgba(255, 255, 255, 1); box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; text-decoration: none; font-weight: normal; font-family: verdana, arial, helvetica, sans-serif; white-space: nowrap; outline: none; } .big-text-field { width: 100%; font-size: 20px; line-height: 22px; } input[type=number] {-moz-appearance: textfield;} ::-webkit-inner-spin-button { -webkit-appearance: none;} .form-text-field { width:80%; } .form-select-field, .select-from-file-row, .select-from-field { width:50%; } .text-field:hover, .text-field:focus, .text-field:active, .text-field.active { -webkit-box-shadow: 0px 0px 1px 1px #999999; -moz-box-shadow: 0px 0px 1px 1px #999999; box-shadow: 0px 0px 1px 1px #999999; } .parameters { width: 400px; border: solid 2px #599bdc; margin:0; padding: 7px; background-color: #fff; -webkit-box-shadow: -1px 3px 3px -1px #888888; -moz-box-shadow: -1px 3px 3px -1px #888888; box-shadow: -1px 3px 3px -1px #888888; h1 { color: #fff; background-color:#599bdc; padding: 1px 1px 1px 15px; font-size: 22px; margin-left: -7px; margin-right: -7px; margin-top: -7px; margin-bottom: 15px; } p { padding: 1px 15px 1px 15px; font-size: 14px; margin: -7px; margin-bottom: 0px; } .select-from-file-category { overflow: hidden; padding:0; border:none; background-color:#fff; width:100%; height:38px; option { line-height: 25px; border:1px solid #666666; border-radius:50%; padding:0px; margin:3px; width:25px; height:25px; text-align:center; display:inline-block; float:right; background-color:#F4F4F4; } option:checked, option:hover { color:#fff; background-color:#599bdc; } } .select-from-file-category:disabled { option { width:auto; border:none; border-radius:0px; color:#8F9499; background-color:#fff; background-image: none; } } .field_categ { padding: 7px; .field { margin:0px; width: 100%; overflow: hidden; display: inline-block; padding: 7px; border:solid #999999 1px; border-radius: 5px; box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; } h1 { padding: 0px 0px 0px 15px; font-size: 18px; margin: -7px; background-color: #808080; color: #fff; -webkit-box-shadow: -1px 1px 2px 1px #B3B3B3; -moz-box-shadow: -1px 1px 2px 1px #B3B3B3; box-shadow: -1px 1px 2px 1px #B3B3B3; } .legend { display:inline-block; max-width:200px; width:auto; vertical-align:top; background-color: #F3F4FF; font-size:12px; line-height: 18px; border-radius:2px; padding:2px; overflow:hidden; .legend-text { display:inline; } } .test-file { display:inline-block; width:250px; line-height: 22px; margin-top:5px; margin-left:2px; .test-select { font-size:14px; float:right; } .test-text { display:inline-block; font-size:14px; float:left; } } .comment { margin-top:10px; } } } diff --git a/app/assets/stylesheets/general.css.scss b/app/assets/stylesheets/general.css.scss index cbc08d0..9f2c101 100644 --- a/app/assets/stylesheets/general.css.scss +++ b/app/assets/stylesheets/general.css.scss @@ -1,338 +1,350 @@ .main-container { height:auto; min-height:100vh; padding-top:1rem; } .doc-table tr td, .doc-table tr th, .version-table tr td { text-align:left } .border-left { border-left:1px solid #ccc; } .border-right { border-right:1px solid #ccc; } .border-top { border-top:1px solid #ccc; } .border-bottom { border-top:1px solid #ccc; } .inline-block { display:inline-block; } .navbar.navbar-top { -moz-box-shadow: 0 2px 2px #808080; -webkit-box-shadow: 0 2px 2px #808080; box-shadow: 0 2px 2px #808080; } .navbar.navbar-bottom { border-top:1px solid #ccc; } .side-index-container { padding:0; z-index:0; } .side-index-container .side-index { height:100vh; overflow:auto; width:100%; } .side-index-container .side-index-list { margin-bottom:50vh; padding-left:5px; padding-right:5px; padding-top:1rem; } .topbar-padding { padding-top:56px; } .topbar-margin { margin-top:56px; } .dropdown-item { cursor:pointer; } .float-right { float:right } .align-center { text-align:center; } .align-justify { text-align:justify; } .align-left { text-align:left; } .align-right { text-align:right; } ul.no-bullets li { list-style-type:none; } .full-width { width:100%; } .full-height { height:100%; } .align-items-center { align-items:center; } .hidden { display:none; } +.row { + + +display: -webkit-box; +display: -webkit-flex; +display: -ms-flexbox; +display: flex; +-webkit-flex-wrap: wrap; +-ms-flex-wrap: wrap; +flex-wrap: wrap; +} + .video-wrapper { position: relative; padding-bottom: 56.25%; /* 16:9 */ padding-top: 25px; height: 0; iframe { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } } #popup_window { position: absolute; z-index:100000; padding:15px; display: none; background: #ccc; border: 1px solid; } #popup_window_close { float:right; font-size:20px; margin-top:-19px; margin-right:-10px; cursor:pointer; } .tip-window-container { position:relative; display:block; width:0; height:0; } .tip-window { position: absolute; display:block; z-index:1; margin: 15px 0 0 0; padding:10px; background: #e6e6e6; border: 1px solid #333; color:#333; width:300px; text-align:left; white-space:normal; } .tip-window:before, .tip-window:after { position:absolute; content:""; width:0; height:0; } .tip-window.right:before, .tip-window.right:after { right:10px; } .tip-window.left:before, .tip-window.left:after { left:10px; } .tip-window:before { top:-15px; border-bottom:15px solid #333; border-left:15px solid transparent; border-right:15px solid transparent; } .tip-window:after { top:-14px; z-index:1; border-bottom:15px solid #e6e6e6; border-left:15px solid transparent; border-right:15px solid transparent; } .tip-window-close { cursor:pointer; } .title_popup {white-space:nowrap;font-weight:bold} .infos { position:static; } .background-col-1 { background-color:#e6e6e6; } .background-col-2 { color:#fff; background-color:#999; } .row-padding-10 { padding-top:10vh; padding-bottom:10vh; } .row-padding-5 { padding-top:5vh; padding-bottom:5vh; } .row-padding-2 { padding-top:2vh; padding-bottom:2vh; } .row-padding-bottom-20 { padding-bottom:20vh; } .v-align-middle { height:100%; transform:translate(0, 35%); } .back-to-top { color:#999; text-decoration: none; &:hover, &:focus, &:active { color:#ccc; text-decoration: none; } } .content { position:static; display: table; margin-right: auto; margin-left: auto; margin-top: 60px; margin-bottom: 60px; .left { float:left; margin-right:20px; } .right { float:right; margin-left:20px; } .align-left { text-align:left; } .align-right { text-align:right; } .centered-div { width: 260px; line-height: 300px; } .centered-span { display: inline-block; vertical-align: middle; line-height: normal; } } a { color: #333; &.white { color: #fff; } &:link, &:visited { text-decoration: none; } &:hover { text-decoration: underline; &.button, &.tab, &.subtab, &.help-button, &.slider, &.slide-open, &.slide-close, &.test-button { text-decoration: none; } &.slide-open, &.slide-close { text-shadow: 1px 0px #333, -1px -0px #333, 0px -1px #333, 0px 1px #333; } } } h1 { font-weight: 500; font-size: 28px; line-height: 34px; } h2 { font-weight: 500; font-size: 24px; line-height: 30px; } h3 { font-weight: 500; font-size: 20px; line-height: 25px; } pre { font-family: verdana, arial, helvetica, sans-serif; background-color: #eee; padding: 10px; font-size: 12px; white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word; } diff --git a/app/assets/stylesheets/home.css.scss b/app/assets/stylesheets/home.css.scss index e6fb2e3..aa894b1 100644 --- a/app/assets/stylesheets/home.css.scss +++ b/app/assets/stylesheets/home.css.scss @@ -1,55 +1,68 @@ .image-container { padding:20px; } +.bs-firefox { + background-image: asset-url("comp_firefox.jpg") +} +.bs-edge { + background-image: asset-url("comp_edge.jpg") +} +.bs-chrome { + background-image: asset-url("comp_chrome.jpg") +} +.bs-opera { + background-image: asset-url("comp_opera.jpg") +} + #home-pages-list>.nav-item { position:relative; } #home-pages-list>.nav-item:before, #home-pages-list>.nav-item:after { position:absolute; display:inline-block; content:''; height:0; width:20%; bottom:0; border-bottom:2px solid transparent; } #home-pages-list>.nav-item:before { left:50%; } #home-pages-list>.nav-item:after { right:50%; } #home-pages-list>.nav-item.selected:before, #home-pages-list>.nav-item.selected:after { width:50%; border-bottom:2px solid #025aa5; } #home-pages-list>.nav-item:hover:before, #home-pages-list>.nav-item:focus:before, #home-pages-list>.nav-item:active:before, #home-pages-list>.nav-item:hover:after, #home-pages-list>.nav-item:focus:after, #home-pages-list>.nav-item:active:after { transition: border-color 0.3s ease; transition: width 0.3s ease; width:50%; border-bottom:2px solid #025aa5; } .index-link-1 { padding:.3em .5em; font-size:1.2em; } .index-link-2 { padding:.3em 1em; } .index-link-3 { padding:.3em 1.2em; } .index-link-4 { padding:.3em 1.8em; font-size:0.9em; font-weight:bold; } diff --git a/app/views/jobs/_form.html.erb b/app/views/jobs/_form.html.erb index 18185a1..55dbadf 100644 --- a/app/views/jobs/_form.html.erb +++ b/app/views/jobs/_form.html.erb @@ -1,80 +1,83 @@ <%= form_for(@job, :url => ((action_name == 'edit') ? job_path(@job.key) : jobs_path), :html => {:multipart => true}) do |f| %> <% ['primary_dataset', 'map', 'secondary_dataset'].each do |k| %> <%= hidden_field_tag "p2[" + k + "]", (params[:p2] && params[:p2][k]) || '' %> <% end %> <%= hidden_field_tag "default_bin_levels", @default['bin_levels'].to_json %> <%= hidden_field_tag "url_read_file_column", read_file_column_jobs_path() %> <%= hidden_field_tag 'tmp_key', @job.key %>
<% @h_form['fields'].each_key do |card_title| %>
-
-

<%= card_title %> +
+

<%= card_title %> <% if card_title == 'Inputs' %> <% l = ['', ''] %> <% end %>

-
+
+
+ +
<%= render :partial => 'card_form', :locals => {:list_fields => @h_form['fields'][card_title].reject{|e| e['belongs_to']}} %>

<% end %>
<% type_job = (action_name == 'edit') ? 'Restart' : 'Start' %> <% if !current_user and !session[:agree_with_terms] %> <%= f.submit type_job + " Analysis", data: { confirm: "Before using Genocrunch, you must agree with the following Terms of Service:\n\n"+File.read('public/app/TERMS_OF_SERVICE.txt') }, :class => "btn btn-success btn-lg col-md-12 mt-1" %> <% else %> <%= f.submit type_job + " Analysis", :class => "btn btn-success btn-lg full-width" %> <% end %>
<%= javascript_tag do %> $(document).ready(function() { var l = ['category_column', 'bin_levels', 'basic_model']; for (var i =0; i< l.length; i++){ $("#p_" + l[i]).change(function(){ if ($("#p_" + l[i] + " option").length == 0) $("#p_" + l[i] + "-container").addClass("hidden"); }); } $("#p_category_column").change(function(){ var ori_filename = $("#p2_primary_dataset").val(); var url = (ori_filename != '') ? "<%= read_file_column_jobs_path() + '?file_key=primary_dataset' %>" : null; var val = <%= raw (@default["bin_levels"]) ? @default["bin_levels"].to_json : "[]" %> update_bin_levels($(this).val(), val, url) }); $("select.belongs_to").change(function(){ var d = $(this).parent().parent().parent().parent().parent().parent().children().filter('.card-header').first().children().filter('.form-check').first().children().filter('.form-check-label').first().children().filter('.form-check-input').first(); d.prop("checked", "checked"); }); $(".belongs_to").keyup(function(){ var d = $(this).parent().parent().parent().parent().children().filter('.card-header').first().children().filter('.form-check').first().children().filter('.form-check-label').first().children().filter('.form-check-input').first(); d.prop("checked", "checked"); }); }); <% end %> <% end %> diff --git a/app/views/jobs/_jobs.html.erb b/app/views/jobs/_jobs.html.erb index aefe747..c56154d 100644 --- a/app/views/jobs/_jobs.html.erb +++ b/app/views/jobs/_jobs.html.erb @@ -1,129 +1,129 @@ -
+

<%= (@scope == 'global')? 'All analyses' : 'My analyses' %>

<% if current_user.role == "admin" %> <% end %> <% @jobs.compact.each do |job| %> <% date = job.updated_at.year.to_s[-2..-1].to_s + "-" + job.updated_at.month.to_s.rjust(2, '0') + "-" + job.updated_at.day.to_s.rjust(2, '0') + " " + job.updated_at.hour.to_s.rjust(2, '0') + ":" + job.updated_at.min.to_s.rjust(2, '0') + " " + job.updated_at.zone.to_s %> <% if current_user.role == "admin" %> <% end %> <% end %>
Name DateUser TypeStatus Data Results Size | |
<%= link_to job.key, job_path(job.key) %>
<%= link_to job.name, job_path(job.key) %>
<%= link_to date, job_path(job.key) %> <%= (job.user) ? job.user.username : 'NA' %> <%= (Example.where(:job_key => job.key).all.size > 0) ? 'Example' : 'Std' %> <% if job.status %> <% end %> <%= link_to raw(''), serve_job_path(job.key, :filename => 'input/primary_dataset.txt'), title: "primary dataset" %> | <%= link_to raw(''), serve_job_path(job.key, :filename => 'input/map.txt'), title: "map" %> <% if File.exist? Pathname.new(APP_CONFIG[:data_dir]) + 'users' + job.user_id.to_s + job.key + 'input' + 'secondary_dataset.txt' %> | <%= link_to raw(''), serve_job_path(job.key, :filename => 'input/secondary_dataset.txt'), title: "secondary dataset" %> <% end %> <%= link_to raw(''), job_path(job.key), :title => 'show' %> <% if !['pending', 'running'].include? job.status %> | <%= link_to raw(''), serve_archive_job_path(job.key), :title => 'download archive' %> <% end %> <%= number_to_human_size(job.size.to_i, precision: 2, prefix: :si) %> <%= link_to raw(''), clone_job_path(job.key) %> | <%= link_to raw(''), edit_job_path(job.key) %> | <% destroy_text = (['pending', 'running'].include? job.status) ? 'abort' : 'delete' %> <%= link_to(job_path(job.key), method: :delete, data: { confirm: 'Are you sure you want to ' + destroy_text + ' "' + (job.name || 'NA') + '" ?'}) do %> <% end %>
-
+

Summary

<%= @jobs.select{ |i| i.status == "completed" }.length %> completed ()
<%= @jobs.select{ |i| i.status == "pending" }.length %> pending ()
<%= @jobs.select{ |i| i.status == "running" }.length %> running ()
<%= @jobs.select{ |i| i.status == "failed" }.length %> failed ()
Total: <%= @jobs.length %>
<% if @scope != 'global' %>
Storage quota <%= (number_to_human_size(@current_user.total_jobs_size.to_i, precision: 2, prefix: :si) +" / "+ ((@current_user.storage_quota.to_i > 0) ? number_to_human_size(@current_user.storage_quota.to_i, precision: 2, prefix: :si) : 'unlimited')) %>
<% else %>
Storage: <%= number_to_human_size(@jobs.sum(&:size).to_i, precision: 2, prefix: :si) %>
<% end %>
<%= javascript_tag do %> $(document).ready(function(){ var storage_quota = <%= @current_user.storage_quota.to_i %>; if (storage_quota > 0) { var total_jobs_size = <%= @current_user.total_jobs_size.to_i %>, percent_storage_limit = Math.min(100, (100*total_jobs_size/storage_quota)), storage_limit_col = (percent_storage_limit < 90) ? "#0275d8" : ((percent_storage_limit < 95) ? "orange" : "red"); $("#storage-limit-bar>.progress-bar").css({"width":percent_storage_limit+"%", "border-top-color":storage_limit_col}) } var table = $('#jobTable').DataTable({ "sDom": 'lfrtip', "aLengthMenu": [[10, 25, 50, 100, -1], [10, 25, 50, 100, "All"]], "iDisplayLength" : 25, "order": [[ 2, 'desc' ], [ 1, 'asc' ]] }); }); <% end %> diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 77581b5..3d5ac7c 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -1,163 +1,160 @@ <%= Rails.application.class.parent_name %> <%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %> <%= javascript_include_tag "application", "data-turbolinks-track" => true %> <%= csrf_meta_tags %>
<%= yield %>
diff --git a/app/views/users/sessions/_infos.html.erb b/app/views/users/sessions/_infos.html.erb index 2a62c14..ec895e2 100644 --- a/app/views/users/sessions/_infos.html.erb +++ b/app/views/users/sessions/_infos.html.erb @@ -1,22 +1,50 @@
<%# PIPELINE %>

Genocrunch is a web-based data analysis platform dedicated to metagenomics and metataxonomics. It is tailored to process counts datasets derived from high-throughput nucleic acids sequencing of microbial communities <%= image_tag('genocrunch_pipeline-1.png', height:'14px') %>, such as gene counts or counts of operational taxonomic units (OTUs) <%= image_tag('genocrunch_pipeline-2.png', height:'14px') %>. In addition to such primary dataset, it also allows the integration of a secondary dataset (e.g. metabolites levels) <%= image_tag('genocrunch_pipeline-3.png', height:'14px') %>.

Genocrunch provides tools covering data pre-processing and transformation, diversity analysis, multivariate statistics, dimensionality reduction, differential analysis, clustering as well as similarity network analysis and associative analysis. The results of clustering are automatically inferred as additional models into other analyses <%= image_tag('genocrunch_pipeline-4.png', height:'14px') %>.

Interactive visualization is offered for all figures.

<%= image_tag('genocrunch_pipeline.png', width:'100%', alt: 'Genocrunch pipeline') %>
+ +
diff --git a/app/views/users/sessions/new.html.erb b/app/views/users/sessions/new.html.erb index 98fff41..31c5240 100644 --- a/app/views/users/sessions/new.html.erb +++ b/app/views/users/sessions/new.html.erb @@ -1,93 +1,99 @@
<%# WELCOME TEXT %>

Analyse your data online

We offer a user-friendly data analysis platform for metagenomics and metataxonomics

<%# SIGNIN %> <%# GO DOWN %>
<%# SESSION INTRO %> <%= render :partial => "infos" %>
<%= javascript_tag do %> +scrollTo('move-down','session-intro') + +/* $('#move-down').on('click', function(){ - document.getElementById('session-intro').scrollIntoView({ behavior: 'smooth' }); + document.getElementById('session-intro').scrollIntoView({ + behavior: 'smooth', + block: 'start' + }); }); - +*/ var notice = '<%= notice %>', is_firefox = typeof InstallTrigger !== 'undefined'; -/* $(document).ready(function() { +/* if (!is_firefox) { $('#firefox_msg').show(); }; +*/ if (notice != '') { alert(notice) }; }); -*/ <% end %> diff --git a/gitignore.keep b/gitignore.keep old mode 100755 new mode 100644 index c0c6440..ad8de45 --- a/gitignore.keep +++ b/gitignore.keep @@ -1,38 +1,41 @@ # Backups files *~ *.rbc *.orig *.bak *.bkp # Temporary files *.tmp /tmp/* /tmp/storage/* !/tmp/storage/.gitkeep # log files *.log /log/ # Storage directory /users/* !/users/.gitkeep # Config config/config.yml config/environments/* !config/environments/*.keep config/initializers/devise.rb .env +# Version +version_[0-9-:.]*.json + # Database /db/seeds.rb config/database.yml # Secrets config/initializers/secret_token.rb config/secrets.yml # Precompiled assets /public/assets/