From d714c4689e54c6935ccabbbbd33e3f5b825385e1 Mon Sep 17 00:00:00 2001 From: knoxygen Date: Mon, 2 Jan 2017 21:44:01 -0700 Subject: [PATCH] Cleaning up styles, fontawesome, etc. --- Gemfile | 5 +- Gemfile.lock | 13 +- app/assets/javascripts/application.js | 1 + app/assets/stylesheets/application.scss | 2 - app/assets/stylesheets/lims.scss | 7 +- app/assets/stylesheets/lims/layout.scss | 178 ++++------ app/assets/stylesheets/lims/studies.css.scss | 7 +- app/assets/stylesheets/shared/constants.scss | 18 +- app/assets/stylesheets/shared/form.scss | 88 +---- app/assets/stylesheets/shared/layout.scss | 305 ++++++++---------- app/assets/stylesheets/shared/mixins.scss | 183 ----------- app/assets/stylesheets/shared/table.scss | 49 --- app/controllers/application_controller.rb | 17 +- app/controllers/diets_controller.rb | 20 +- app/helpers/application_helper.rb | 68 +++- app/models/user.rb | 33 +- app/views/layouts/lims.html.slim | 6 +- app/views/layouts/lims/_navigation.html.slim | 18 +- .../layouts/lims/_navigation_links.html.slim | 94 +++--- app/views/samples/index.html.erb | 61 ---- app/views/samples/index.html.slim | 74 +++++ app/views/samples/show.html.erb | 138 -------- app/views/samples/show.html.slim | 85 +++++ .../subjects/patient/index.html.erb | 38 --- .../subjects/patient/index.html.slim | 33 ++ .../subjects/patient/show.html.erb | 45 --- .../subjects/patient/show.html.slim | 30 ++ app/views/workflows/experiments/new.html.erb | 96 ------ app/views/workflows/experiments/new.html.slim | 60 ++++ lib/knoxy_form_builder.rb | 17 - 30 files changed, 672 insertions(+), 1117 deletions(-) delete mode 100644 app/assets/stylesheets/shared/table.scss delete mode 100644 app/views/samples/index.html.erb create mode 100644 app/views/samples/index.html.slim delete mode 100644 app/views/samples/show.html.erb create mode 100644 app/views/samples/show.html.slim delete mode 100644 app/views/test_subjects/subjects/patient/index.html.erb create mode 100644 app/views/test_subjects/subjects/patient/index.html.slim delete mode 100644 app/views/test_subjects/subjects/patient/show.html.erb create mode 100644 app/views/test_subjects/subjects/patient/show.html.slim delete mode 100644 app/views/workflows/experiments/new.html.erb create mode 100644 app/views/workflows/experiments/new.html.slim diff --git a/Gemfile b/Gemfile index edd977d..c754d00 100644 --- a/Gemfile +++ b/Gemfile @@ -12,7 +12,6 @@ gem 'jquery-rails' gem 'jquery-ui-rails' gem 'jquery-ui-themes' gem 'jbuilder', '~> 2.0' -gem 'sass-rails', '~> 5.0' gem 'highcharts-rails' gem 'jquery-tablesorter' gem 'yui-rails' @@ -26,9 +25,11 @@ gem 'rabl' gem 'simple_form' gem 'cocoon' gem 'slim-rails' -gem 'bootstrap-sass' +gem 'font-awesome-sass' +gem 'bootstrap' source 'https://rails-assets.org' do + gem 'rails-assets-tether', '>= 1.1.0' gem 'rails-assets-jstree' end diff --git a/Gemfile.lock b/Gemfile.lock index c602ec0..2b56005 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -52,9 +52,9 @@ GEM bcrypt (3.1.11) binding_of_caller (0.7.2) debug_inspector (>= 0.0.1) - bootstrap-sass (3.3.7) - autoprefixer-rails (>= 5.2.1) - sass (>= 3.3.4) + bootstrap (4.0.0.alpha5) + autoprefixer-rails (>= 6.0.3) + sass (>= 3.4.19) builder (3.2.2) byebug (9.0.6) capistrano (3.7.1) @@ -93,6 +93,8 @@ GEM warden (~> 1.2.3) erubis (2.7.0) execjs (2.7.0) + font-awesome-sass (4.7.0) + sass (>= 3.2) globalid (0.3.7) activesupport (>= 4.1.0) highcharts-rails (4.2.5) @@ -170,6 +172,7 @@ GEM rails-assets-jquery (3.1.1) rails-assets-jstree (3.3.3) rails-assets-jquery (>= 1.9.1) + rails-assets-tether (1.4.0) rails-deprecated_sanitizer (1.0.3) activesupport (>= 4.2.0.alpha) rails-dom-testing (1.0.8) @@ -254,7 +257,7 @@ PLATFORMS ruby DEPENDENCIES - bootstrap-sass + bootstrap bundler (>= 1.8.4) byebug capistrano @@ -265,6 +268,7 @@ DEPENDENCIES country-select devise execjs + font-awesome-sass highcharts-rails jbuilder (~> 2.0) jquery-cookie-rails @@ -280,6 +284,7 @@ DEPENDENCIES rabl rails (~> 4.2.0) rails-assets-jstree! + rails-assets-tether (>= 1.1.0)! ransack sass-rails (~> 5.0) shoulda diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 602e4a1..3c12dd9 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -9,6 +9,7 @@ //= require jquery_ujs //= require jquery-ui //= require jstree +//= require tether //= require bootstrap //= require yui-min //= require_tree . diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index ad93789..8e7680a 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -1,13 +1,11 @@ @import 'jquery-ui'; @import 'jquery-ui/cupertino'; @import 'jstree'; -@import 'bootstrap-sprockets'; @import 'bootstrap'; @import 'shared/constants'; @import 'shared/mixins'; @import 'shared/layout'; @import 'shared/flash'; @import 'shared/pagination'; -@import 'shared/table'; @import 'shared/form'; @import 'shared/login'; diff --git a/app/assets/stylesheets/lims.scss b/app/assets/stylesheets/lims.scss index f1dada5..ea8eb83 100644 --- a/app/assets/stylesheets/lims.scss +++ b/app/assets/stylesheets/lims.scss @@ -1,14 +1,15 @@ @import 'jquery-ui'; @import 'jquery-ui/cupertino'; @import 'jstree'; -@import 'bootstrap-sprockets'; -@import 'bootstrap'; +@import 'font-awesome-sprockets'; +@import 'font-awesome'; @import 'shared/constants'; +@import 'bootstrap-flex'; + @import 'shared/mixins'; @import 'shared/layout'; @import 'shared/flash'; @import 'shared/pagination'; -@import 'shared/table'; @import 'shared/form'; @import 'shared/login'; diff --git a/app/assets/stylesheets/lims/layout.scss b/app/assets/stylesheets/lims/layout.scss index 91406d8..1f982e1 100644 --- a/app/assets/stylesheets/lims/layout.scss +++ b/app/assets/stylesheets/lims/layout.scss @@ -3,134 +3,74 @@ main { margin-top: 61px; // accommodate the navbar } -.error_notification { - @extend .alert; - @extend .alert-danger; -} - -body { - @extend .container-fluid; - position: relative; - - & > header { - @extend .navbar; - @extend .navbar-fixed-top; +#main-content { + margin-top: .5rem; + &.with-sidebar { + @extend .col-md-9; + } + &.without-sidebar { + @extend .col-md-12; } } -// Table for displaying object data -table#object-data { - text-align: left; - width: 100%; - margin: 1em auto; - border-collapse: collapse; -} - -table#object-data td, table#object-data th { - border: 1px solid #636363; - padding: 0.4em; -} - -table#object-data th { - background: #3399ff; - color: white; - width: 18%; -} - -table#object-data th.spanheader { - background: #E0EEEE; - width: 100%; - color: gray; -} - -table#object-data td { - background: #F7F7F7; - color: black; -} - -table#object-data img.structure { - border: none; - padding: 0px; - margin: 0px; -} - -table#object-data pre { - margin: 0px; - padding: 0px; - font-size: 14px; - font-family: courier; -} - -table#object-data div.citations { - background: red !important; -} - -table#object-data div.inner { - border: 1px solid silver; - margin: 0.5em 0; - padding: 0.3em; - background: white; -} - -/* Metadata section for entities */ -div.metadata { - background: #FFFFCC; - padding: 0.5em; -} - -/* Box used on show pages to group associated information */ -.box { - padding:6px; - margin-bottom: 10px; - background-color:#f6f6f6; - color:#505050; - line-height:1.5em; - border: 1px solid #e4e4e4; -} - -h3.box-header { - background: #E0E0E0; -} - -/* Pharmacological actions */ -div.action-legend { - float: right; - font-weight: bold; +#sidebar-content { + @extend .col-md-3; + #sidebar { + overflow: hidden; + white-space: nowrap; + background: #FCFFF0; + min-height: 800px; + + h2 { + @extend .rounded; + text-shadow: 0px 0px 0.05px white; + border: 2px solid #CDCDC1; + background: white; + font-weight: normal; + font-size: 15px; + margin: .5rem; + margin-bottom: 1rem; + padding: 0.5em 0.4em; + } + } } -.action-yes { - background-color: #9AFF9A; -} +dl.standard { + @extend .row; + dt { + @extend .col-md-3; + @extend .col-sm-6; + @extend .col-xs-6; + } + dd { + @extend .col-md-9; + @extend .col-sm-7; + @extend .col-xs-6; + } -.action-no { - background-color: #EEB4B4; } -/* Inner tables in show views */ -table#object-data table.inner { - background: #E0DFDB; - width: 100%; - text-align: left; - border-collapse: collapse; - padding: 0; - margin: 0; - border: none; +.error_notification { + @extend .alert; + @extend .alert-danger; } -table#object-data table.inner th { - text-align: left; - border-collapse: collapse; - font-size: smaller; - color: #474747; - background: silver; - border: none; - border-bottom: 1px solid grey; - padding: 0.2em; +table.list { + @extend .table; + @extend .table-striped; + @extend .table-sm; + + tr.table-search { + @extend .table-info; + th { + input, select { + @extend .form-control; + @extend .form-control-sm; + } + } + .table-search-actions.btn-group { + float: right; + } + } } -table#object-data table.inner td { - padding: 0 1em 0 0; - border: none; - border-top: 1px solid grey; - padding: 0.2em; -} diff --git a/app/assets/stylesheets/lims/studies.css.scss b/app/assets/stylesheets/lims/studies.css.scss index e7c027c..4f7f659 100644 --- a/app/assets/stylesheets/lims/studies.css.scss +++ b/app/assets/stylesheets/lims/studies.css.scss @@ -51,7 +51,8 @@ margin: 0.5em 0; } -img.info-logo { +.info-logo { float: left; - margin-right: 1.5em; -} \ No newline at end of file + margin-right: 1rem; + color: $app-dark-grey; +} diff --git a/app/assets/stylesheets/shared/constants.scss b/app/assets/stylesheets/shared/constants.scss index 832dc6c..cfa7e78 100644 --- a/app/assets/stylesheets/shared/constants.scss +++ b/app/assets/stylesheets/shared/constants.scss @@ -4,13 +4,13 @@ $app-dark-grey: #515151; $app-grey: #F9F9F9; $app-green: #12d678; $app-purple: #DD5DEB; - -$app-pink: #FF4390; -$app-light-pink: #FF8EBC; -$app-dark-pink: #B21D5A; -$app-yellow: #FFF05D; $app-light-yellow: #FFF69E; -$app-blue: #22AFCC; -$app-light-blue: #7ACFE0; -$app-very-light-blue: #BDE7F0; -$app-dark-blue: #269AB2; + +// Override bootstrap variables: +$font-size-h1: 1.75rem; +$font-size-h2: 1.5rem; +$font-size-h3: 1.25rem; +$font-size-h4: 1rem; +$font-size-h5: .75rem; +$font-size-h6: .5rem; + diff --git a/app/assets/stylesheets/shared/form.scss b/app/assets/stylesheets/shared/form.scss index 2ac6d84..5b4e889 100644 --- a/app/assets/stylesheets/shared/form.scss +++ b/app/assets/stylesheets/shared/form.scss @@ -11,19 +11,6 @@ div.error-explanation { ul { margin: 0.8em; } } -.textile-holder { - .help-block { - .textile-hint { - float: right; - font-size: 12px; - } - } -} - -.textile-editor { - font-size: smaller; -} - .citable { .citation-text { height: 100px; @@ -37,8 +24,8 @@ form.standard { margin-top: .8em; border-top: 1px solid white; a, input, button { - @include btn; - @include btn-primary; + @extend .btn; + @extend .btn-primary; margin-right: 0.5em; } } @@ -56,8 +43,9 @@ form.standard { display: inline; } fieldset { - @include well; - @include well-sm; + @extend .form-group; + @extend .rounded; + padding: 1rem; background: #E0EBEA; margin-top: 1em; margin-bottom: 1em; @@ -90,7 +78,7 @@ form.standard { .nested-fields { .form-control { - @extend .input-sm; + @extend .form-control-sm; } &.inline { @extend .form-inline; @@ -114,72 +102,30 @@ form.standard { } } &.panelled { - @extend .panel; - @extend .panel-default; + @extend .card; + // @extend .panel-default; .btn-rmv { float: right; } } } .btn-add { - @include btn; - @include btn-xs; - @include btn-default; + @extend .btn; + @extend .btn-sm; + @extend .btn-secondary; margin-top: 1em; } .btn-rmv { - @include btn; - @include btn-xs; - @include btn-default; + @extend .btn; + @extend .btn-sm; + @extend .btn-secondary; color: #9D1309; } .btn-new { - @include btn; - @include btn-xs; - @include btn-primary; + @extend .btn; + @extend .btn-sm; + @extend .btn-primary; margin-top: 1em; margin-left: 2em; float: right; } - -.lims-edit-sidebar { - &.affix { - top: 60px; - } - .lims-sidebar-actions { - .cancel { margin-right: 1em; } - } - .lims-edit-sidenav { - > li { - a { - display: block; - padding: 4px 20px; - font-size: 13px; - font-weight: 500; - color: #767676; - &:hover { color: $app-dark-pink; } - } - &.active { - > a { - border-left: 1px solid $app-dark-pink; - background: #f5f5f5; - font-weight: bold; - color: $app-dark-pink; - } - ul.nav { - display: block; - } - } - ul.nav { - display: none; - } - } - .nav>li>a { - padding-top: 1px; - padding-bottom: 1px; - padding-left: 30px; - font-size: 12px; - font-weight: 400; - } - } -} diff --git a/app/assets/stylesheets/shared/layout.scss b/app/assets/stylesheets/shared/layout.scss index 7eac157..1b9e348 100644 --- a/app/assets/stylesheets/shared/layout.scss +++ b/app/assets/stylesheets/shared/layout.scss @@ -1,175 +1,130 @@ -/* Standard HTML Tag Styles */ -body { - font-size: 15px; - font-family: helvetica, sans-serif; -} - -pre { - background-color: #eee; - padding: 10px; - font-size: 13px; -} - -// see http://paulirish.com/2012/box-sizing-border-box-ftw/ -* { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } - -/***** Links *****/ -a, a:link, a:visited{ color: #2A5685; text-decoration: none; } -a:hover, a:active{ color: #c61a1a; text-decoration: underline;} -a img{ border: 0; } - -/* Flash messages */ -div#flash-messages { - margin: 1em 0.6em; - - p.flash { padding: 0.4em 0.8em; font-weight: bold; border-radius: 10px; } - p.flash-notice { background-color: #a6d785; color: #3f602b; border: 1px solid #3f602b; } - p.flash-warning { background-color: #fbec5d; color: #8b6508; border: 1px solid #8b6508; } - p.flash-error, p.flash-alert { background-color: #fa8072; color: #800000; border: 1px solid #800000; } -} - -/* Layout CSS */ -div#hd { - min-width: 1000px; - div#headerbar { - background: #609db3; height: 125px; - img.left { float: left } - img.right { float: right } - } - div#logged-in { - position: absolute; - top: 5px; - right: 15px; - background: #B9D3EE; - padding: 0.3em 0.4em; - border-radius: 5px; - border: 1px solid #FFEBCD; - font-size: 14px; - font-weight: bold; - a { text-decoration: underline; } - } -} - -div#sidebar-holder { - #sidebar { - overflow: auto; - white-space: nowrap; - min-height: 800px; - background: #FCFFF0; - padding: 0.5em; - border-right: 1px dotted silver; - border-bottom: 1px dotted silver; - h2 { - text-shadow: 0px 0px 0.05px white; - border-radius: 4px; - border: 2px solid #CDCDC1; - background: white; - font-weight: normal; - font-size: 15px; - margin-bottom: 0.8em; - margin-top: 5px; - padding: 0.5em 0.4em; - } - } -} - -div#main-holder { - #main { - padding: 0.65em 0.5em; - } - - .without-sidebar { - margin-left: 0.3em !important; - padding-left: 0 !important; - } - - h1 { - color: #4c545a; - font-size: 20px; - background: #E8E8E8; - margin: 0.2em 0 0.7em 0; - padding: 0.3em 0.5em; - text-align: left; - text-shadow: 0px 0px 0.05px white; - letter-spacing: 1px; - border-radius: 8px; - } - h2 { - font-size: larger; - margin: 1.5em 0 1em 0; - font-weight: bold; - } -} - - -// Icon theme -.icon { - background-position: 0% 40%; - background-repeat: no-repeat; - padding-left: 20px; - padding-top: 2px; - padding-bottom: 3px; -} - -.icon-add { background-image: image_url('icons/add.png'); } -.icon-edit { background-image: image_url('icons/edit.png'); } -.icon-copy { background-image: image_url('icons/copy.png'); } -.icon-del { background-image: image_url('icons/delete.png'); } -.icon-move { background-image: image_url('icons/move.png'); } -.icon-save { background-image: image_url('icons/save.png'); } -.icon-cancel { background-image: image_url('icons/cancel.png'); } -.icon-file { background-image: image_url('icons/file.png'); } -.icon-folder { background-image: image_url('icons/folder.png'); } -.open .icon-folder { background-image: image_url('icons/folder_open.png'); } -.icon-package { background-image: image_url('icons/package.png'); } -.icon-home { background-image: image_url('icons/home.png'); } -.icon-user { background-image: image_url('icons/user.png'); } -.icon-mypage { background-image: image_url('icons/user_page.png'); } -.icon-admin { background-image: image_url('icons/admin.png'); } -.icon-projects { background-image: image_url('icons/projects.png'); } -.icon-help { background-image: image_url('icons/help.png'); } -.icon-attachment { background-image: image_url('icons/attachment.png'); } -.icon-index { background-image: image_url('icons/index.png'); } -.icon-history { background-image: image_url('icons/history.png'); } -.icon-time { background-image: image_url('icons/time.png'); } -.icon-stats { background-image: image_url('icons/stats.png'); } -.icon-warning { background-image: image_url('icons/warning.png'); } -.icon-fav { background-image: image_url('icons/fav.png'); } -.icon-fav-off { background-image: image_url('icons/fav_off.png'); } -.icon-reload { background-image: image_url('icons/reload.png'); } -.icon-lock { background-image: image_url('icons/locked.png'); } -.icon-unlock { background-image: image_url('icons/unlock.png'); } -.icon-checked { background-image: image_url('icons/true.png'); } -.icon-details { background-image: image_url('icons/zoom_in.png'); } -.icon-report { background-image: image_url('icons/report.png'); } -.icon-comment { background-image: image_url('icons/comment.png'); } -.icon-calendar { background-image: image_url('icons/calendar.png'); } -.icon-show { background-image: image_url('icons/show.png'); } - -.box { - padding: 1em; - margin-bottom: 10px; - background-color:#f6f6f6; - color: #505050; - border: 1px solid silver; - border-radius: 0.4em; - font-size: 16px; -} - -h3.box-header { - background: #e0e0e0; -} - - -//Unknown: -div.analysis { - float: left; - margin-right: 6em; -} - -div.subcontainer { - background: #F0F0F0; - display: table; - padding: 1em; - border: 1px solid #A3A3A3; -} +// /* Standard HTML Tag Styles */ +// body { +// font-size: 15px; +// font-family: helvetica, sans-serif; +// } + +// pre { +// background-color: #eee; +// padding: 10px; +// font-size: 13px; +// } + +// // see http://paulirish.com/2012/box-sizing-border-box-ftw/ +// * { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } + +// /***** Links *****/ +// a, a:link, a:visited{ color: #2A5685; text-decoration: none; } +// a:hover, a:active{ color: #c61a1a; text-decoration: underline;} +// a img{ border: 0; } + +// /* Flash messages */ +// div#flash-messages { +// margin: 1em 0.6em; + +// p.flash { padding: 0.4em 0.8em; font-weight: bold; border-radius: 10px; } +// p.flash-notice { background-color: #a6d785; color: #3f602b; border: 1px solid #3f602b; } +// p.flash-warning { background-color: #fbec5d; color: #8b6508; border: 1px solid #8b6508; } +// p.flash-error, p.flash-alert { background-color: #fa8072; color: #800000; border: 1px solid #800000; } +// } + +// /* Layout CSS */ +// div#hd { +// min-width: 1000px; +// div#headerbar { +// background: #609db3; height: 125px; +// img.left { float: left } +// img.right { float: right } +// } +// div#logged-in { +// position: absolute; +// top: 5px; +// right: 15px; +// background: #B9D3EE; +// padding: 0.3em 0.4em; +// border-radius: 5px; +// border: 1px solid #FFEBCD; +// font-size: 14px; +// font-weight: bold; +// a { text-decoration: underline; } +// } +// } + +// div#sidebar-holder { +// #sidebar { +// overflow: auto; +// white-space: nowrap; +// min-height: 800px; +// background: #FCFFF0; +// padding: 0.5em; +// border-right: 1px dotted silver; +// border-bottom: 1px dotted silver; +// h2 { +// text-shadow: 0px 0px 0.05px white; +// border-radius: 4px; +// border: 2px solid #CDCDC1; +// background: white; +// font-weight: normal; +// font-size: 15px; +// margin-bottom: 0.8em; +// margin-top: 5px; +// padding: 0.5em 0.4em; +// } +// } +// } + +// div#main-holder { +// #main { +// padding: 0.65em 0.5em; +// } + +// .without-sidebar { +// margin-left: 0.3em !important; +// padding-left: 0 !important; +// } + +// h1 { +// color: #4c545a; +// font-size: 20px; +// background: #E8E8E8; +// margin: 0.2em 0 0.7em 0; +// padding: 0.3em 0.5em; +// text-align: left; +// text-shadow: 0px 0px 0.05px white; +// letter-spacing: 1px; +// border-radius: 8px; +// } +// h2 { +// font-size: larger; +// margin: 1.5em 0 1em 0; +// font-weight: bold; +// } +// } + +// .box { +// padding: 1em; +// margin-bottom: 10px; +// background-color:#f6f6f6; +// color: #505050; +// border: 1px solid silver; +// border-radius: 0.4em; +// font-size: 16px; +// } + +// h3.box-header { +// background: #e0e0e0; +// } + + +// //Unknown: +// div.analysis { +// float: left; +// margin-right: 6em; +// } + +// div.subcontainer { +// background: #F0F0F0; +// display: table; +// padding: 1em; +// border: 1px solid #A3A3A3; +// } diff --git a/app/assets/stylesheets/shared/mixins.scss b/app/assets/stylesheets/shared/mixins.scss index ab04461..e69de29 100644 --- a/app/assets/stylesheets/shared/mixins.scss +++ b/app/assets/stylesheets/shared/mixins.scss @@ -1,183 +0,0 @@ -@mixin bootstrap-btn($background) { - @if lightness($background) >= lightness(#ccc) { //#ddd is btn - @include button-variant(#333, $background, darken($background, 5%)); - } - @else { - @include button-variant(#fff, $background, darken($background, 5%)); - } -} - -// This is ripped from bootstrap so we can use btn as a mixin to avoid -// @extends which causes rendering speed issues. -@mixin btn() { - display: inline-block; - margin-bottom: 0; // For input.btn - font-weight: $btn-font-weight; - text-align: center; - vertical-align: middle; - touch-action: manipulation; - cursor: pointer; - background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214 - border: 1px solid transparent; - white-space: nowrap; - @include button-size($padding-base-vertical, $padding-base-horizontal, $font-size-base, $line-height-base, $border-radius-base); - @include user-select(none); - - &, - &:active, - &.active { - &:focus, - &.focus { - @include tab-focus; - } - } - - &:hover, - &:focus, - &.focus { - color: $btn-default-color; - text-decoration: none; - } - - &:active, - &.active { - outline: 0; - background-image: none; - @include box-shadow(inset 0 3px 5px rgba(0,0,0,.125)); - } - - &.disabled, - &[disabled], - fieldset[disabled] & { - cursor: $cursor-disabled; - pointer-events: none; // Future-proof disabling of clicks - @include opacity(.65); - @include box-shadow(none); - } -} - -@mixin btn-default() { - @include button-variant($btn-default-color, $btn-default-bg, $btn-default-border); -} -@mixin btn-primary() { - @include button-variant($btn-primary-color, $btn-primary-bg, $btn-primary-border); -} -// Success appears as green -@mixin btn-success() { - @include button-variant($btn-success-color, $btn-success-bg, $btn-success-border); -} -// Info appears as blue-green -@mixin btn-info() { - @include button-variant($btn-info-color, $btn-info-bg, $btn-info-border); -} -// Warning appears as orange -@mixin btn-warning() { - @include button-variant($btn-warning-color, $btn-warning-bg, $btn-warning-border); -} -// Danger and error appear as red -@mixin btn-danger() { - @include button-variant($btn-danger-color, $btn-danger-bg, $btn-danger-border); -} - -@mixin btn-lg() { - // line-height: ensure even-numbered height of button next to large input - @include button-size($padding-large-vertical, $padding-large-horizontal, $font-size-large, $line-height-large, $border-radius-large); -} -@mixin btn-sm() { - // line-height: ensure proper height of button next to small input - @include button-size($padding-small-vertical, $padding-small-horizontal, $font-size-small, $line-height-small, $border-radius-small); -} -@mixin btn-xs() { - @include button-size($padding-xs-vertical, $padding-xs-horizontal, $font-size-small, $line-height-small, $border-radius-small); -} - -// Base class -@mixin well() { - min-height: 20px; - padding: 19px; - margin-bottom: 20px; - background-color: $well-bg; - border: 1px solid $well-border; - border-radius: $border-radius-base; - @include box-shadow(inset 0 1px 1px rgba(0,0,0,.05)); - blockquote { - border-color: #ddd; - border-color: rgba(0,0,0,.15); - } -} - -// Sizes -@mixin well-lg() { - padding: 24px; - border-radius: $border-radius-large; -} -@mixin well-sm() { - padding: 9px; - border-radius: $border-radius-small; -} - -// Alerts -@mixin alert() { - padding: $alert-padding; - margin-bottom: $line-height-computed; - border: 1px solid transparent; - border-radius: $alert-border-radius; - - // Headings for larger alerts - h4 { - margin-top: 0; - // Specified for the h4 to prevent conflicts of changing $headings-color - color: inherit; - } - - // Provide class for links that match alerts - .alert-link { - font-weight: $alert-link-font-weight; - } - - // Improve alignment and spacing of inner content - > p, - > ul { - margin-bottom: 0; - } - - > p + p { - margin-top: 5px; - } -} - -// Dismissible alerts -// -// Expand the right padding and account for the close button's positioning. - -@mixin alert-dismissible() { - padding-right: ($alert-padding + 20); - - // Adjust close link position - .close { - position: relative; - top: -2px; - right: -21px; - color: inherit; - } -} - -// Alternate styles -// -// Generate contextual modifier classes for colorizing the alert. - -@mixin alert-success() { - @include alert-variant($alert-success-bg, $alert-success-border, $alert-success-text); -} - -@mixin alert-info() { - @include alert-variant($alert-info-bg, $alert-info-border, $alert-info-text); -} - -@mixin alert-warning() { - @include alert-variant($alert-warning-bg, $alert-warning-border, $alert-warning-text); -} - -@mixin alert-danger() { - @include alert-variant($alert-danger-bg, $alert-danger-border, $alert-danger-text); -} diff --git a/app/assets/stylesheets/shared/table.scss b/app/assets/stylesheets/shared/table.scss deleted file mode 100644 index cc1ff36..0000000 --- a/app/assets/stylesheets/shared/table.scss +++ /dev/null @@ -1,49 +0,0 @@ -/* Standard table style */ -table.list { - text-align: left; - border-collapse: collapse; - font-size: 14px; - width: 100%; - th, td { - padding: 0.2em 0.4em; - vertical-align: top; - } - td { - border-bottom: 1px solid silver; - } - th { - font-weight: bold; - color: #636363; - border-bottom: 1px solid #666; - } - tr.even { - background: #ECF3FE; - } - tr.odd { - background: white; - } - tr.header { - background: white !important; - } - tr:hover { - background: #FFFCCF - } - tr:first-child { - border-bottom: 1px solid #666; - } - h2.sub { - font-weight: bold; - padding: 0.3em; - margin-top: 2em; - margin-bottom: 1em; - background: #EEE9E9; - } - tr.table-search { - background: #F7F7F7; - vertical-align: middle; - th { - vertical-align: middle; - } - } -} - diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 5b52014..78d42b1 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -27,22 +27,25 @@ def find_for_site(objects, site) end def can_view_all(user) - return (current_user.rank == 'Superuser' || current_user.rank == 'Administrator') + current_user.superuser? || current_user.administrator? end protected def only_user?(redirect_path = root_path) - redirect_to redirect_path unless current_user.rank == 'Superuser' || current_user.rank == 'Administrator' + redirect_to redirect_path unless current_user.superuser? || current_user.administrator? end def administrator?(redirect_path = root_path) - redirect_to redirect_path unless current_user.rank == 'Administrator' + redirect_to redirect_path unless current_user.administrator? end - def find_test_subject(param_name = :test_subject_id) - @test_subject = current_user.rank == 'Superuser' || current_user.rank == 'Administrator' ? - TestSubject.find(params[param_name]) : - TestSubject.find_by!(id: params[param_name], site_id: current_user.site) + def find_test_subject(id_param = :test_subject_id) + @test_subject = + if current_user.superuser? || current_user.administrator? + TestSubject.find(params[id_param]) + else + current_user.site.test_subjects.find(params[id_param]) + end end end diff --git a/app/controllers/diets_controller.rb b/app/controllers/diets_controller.rb index f01f2a3..eb67817 100644 --- a/app/controllers/diets_controller.rb +++ b/app/controllers/diets_controller.rb @@ -6,7 +6,7 @@ def index respond_to do |format| format.html # index.html.erb - format.xml { render :xml => @diets } + format.xml { render xml: @diets } end end @@ -17,7 +17,7 @@ def show respond_to do |format| format.html # show.html.erb - format.xml { render :xml => @diet } + format.xml { render xml: @diet } end end @@ -28,7 +28,7 @@ def new respond_to do |format| format.html # new.html.erb - format.xml { render :xml => @diet } + format.xml { render xml: @diet } end end @@ -44,11 +44,11 @@ def create respond_to do |format| if @diet.save - format.html { redirect_to(@diet), notice: 'Diet was successfully created.' } - format.xml { render :xml => @diet, :status => :created, :location => @diet } + format.html { redirect_to @diet, notice: 'Diet was successfully created.' } + format.xml { render xml: @diet, status: :created, location: @diet } else - format.html { render :action => "new" } - format.xml { render :xml => @diet.errors, :status => :unprocessable_entity } + format.html { render action: "new" } + format.xml { render xml: @diet.errors, status: :unprocessable_entity } end end end @@ -60,11 +60,11 @@ def update respond_to do |format| if @diet.update(diet_params) - format.html { redirect_to(@diet), notice: 'Diet was successfully updated.' } + format.html { redirect_to @diet, notice: 'Diet was successfully updated.' } format.xml { head :ok } else - format.html { render :action => "edit" } - format.xml { render :xml => @diet.errors, :status => :unprocessable_entity } + format.html { render action: "edit" } + format.xml { render xml: @diet.errors, status: :unprocessable_entity } end end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index e4aea8b..56701d1 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -61,20 +61,70 @@ def boolean_to_english(val) end end - def destroy_link(params) - link_to('delete', params, {:confirm => 'Are you sure you want to delete this entry?', :method => :delete, :class => 'icon icon-del', :title => 'Delete Entry'} ) + # Return the "Not Available" tag when the given value is blank. + # Optionally pass in a message to use instead of "Not Available". + # Return the given value if it is not blank. + def nah(value=nil, message="Not Available") + if value.present? + value.respond_to?(:html_safe) ? value.html_safe : value + else + "#{message}".html_safe + end + end + + + def destroy_link(params, title='delete') + link_to "#{icon(:remove)} #{title}".html_safe, params, + data: { confirm: 'Are you sure you want to delete this entry?' }, + method: :delete, class: 'btn btn-outline-danger btn-sm', + title: 'Delete Entry' + end + + def edit_link(params, title='edit') + link_to "#{icon(:edit)} #{title}".html_safe, params, + class: 'btn btn-sm btn-outline-primary', title: 'Edit Entry' + end + + def show_link(params, title='view') + link_to "#{icon(:eye)} #{title}".html_safe, params, + class: 'btn btn-sm btn-outline-primary', title: 'Show Entry' + end + + def new_link(title, params) + title ||= 'new' + link_to "#{icon(:'plus-square')} add #{title}".html_safe, params, class: 'btn btn-sm btn-outline-success' end - def edit_link(params) - link_to('edit', params, :class => 'icon icon-edit', :title => 'Edit Entry' ) + def table_search_actions + content_tag(:div, class: 'table-search-actions btn-group') do + button_tag(icon(:search), type: 'submit', class: 'btn btn-info btn-sm') << + link_to('clear', request.path, class: 'btn btn-secondary btn-sm') + end end - def show_link(params, name='show') - link_to(name, params, :class => 'icon icon-show', :title => 'Show Entry' ) + def table_search_text(form, query, *args) + options = args.extract_options! + if options[:class].present? && options[:class].is_a?(String) + options[:class] = [options[:class]] + end + options[:class] ||= [] + options[:class].concat(["form-control", "input-tbl-search"]) + + form.text_field query, *(args << options) end - def new_link(name, params) - name ||= 'new' - link_to(name, params, :class => 'icon icon-add' ) + def table_search_select(form, field, select_options, options={}, *args) + options[:include_blank] ||= true + html_options = args.extract_options! + if html_options[:class].present? && html_options[:class].is_a?(String) + html_options[:class] = [html_options[:class]] + end + html_options[:class] ||= [] + html_options[:class].concat(["form-control", "input-tbl-search"]) + + form.select field, + select_options, + options, + *(args << html_options) end end diff --git a/app/models/user.rb b/app/models/user.rb index ecbf0b0..63c1979 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,21 +1,30 @@ class User < ActiveRecord::Base - devise :database_authenticatable, :recoverable, :rememberable, :trackable, :validatable, :lockable - - # Setup accessible attributes - # attr_accessible :email, :password, :password_confirmation, :name, :site_id, :rank - # attr_protected :current_password + devise :database_authenticatable, :recoverable, + :rememberable, :trackable, :validatable, :lockable belongs_to :site - has_one :photo_file, :class_name => 'StoredFile::Photo', :as => :attachable - accepts_nested_attributes_for :photo_file, :allow_destroy => true + has_one :photo_file, class_name: 'StoredFile::Photo', as: :attachable + accepts_nested_attributes_for :photo_file, allow_destroy: true + + has_many :tasks, foreign_key: 'assigned_to_id' + has_many :samples, foreign_key: 'collected_by_id' - has_many :tasks, :foreign_key => 'assigned_to_id' - has_many :samples, :foreign_key => 'collected_by_id' + scope :administrators, -> { where(rank: 'Administrator') } + scope :superusers, -> { where(rank: 'Superuser') } + scope :users, -> { where(rank: 'User') } + + def superuser? + rank == 'Superuser' + end - scope :administrators, -> { where(:rank => 'Administrator') } - scope :superusers, -> { where(:rank => 'Superuser') } - scope :users, -> { where(:rank => 'User') } + def administrator? + rank == 'Administrator' + end + + def user? + rank == 'User' + end def to_s self.email diff --git a/app/views/layouts/lims.html.slim b/app/views/layouts/lims.html.slim index 81c038b..2b187ef 100644 --- a/app/views/layouts/lims.html.slim +++ b/app/views/layouts/lims.html.slim @@ -27,13 +27,13 @@ html .row - if content_for?(:sidebar) - #sidebar-holder.col-md-3 + #sidebar-content #sidebar == yield :sidebar - #main.col-md-9 + #main-content.with-sidebar == render '/layouts/lims/messages' == yield - else - #main.col-md-12 + #main-content.without-sidebar == render '/layouts/lims/messages' == yield diff --git a/app/views/layouts/lims/_navigation.html.slim b/app/views/layouts/lims/_navigation.html.slim index 1746e44..ca01a72 100644 --- a/app/views/layouts/lims/_navigation.html.slim +++ b/app/views/layouts/lims/_navigation.html.slim @@ -1,14 +1,4 @@ -nav.navbar.navbar-default.navbar-fixed-top.navbar-inverse - .container-fluid - .navbar-header - button.navbar-toggle type="button" data-toggle="collapse" data-target="#main-nav" - span.sr-only Toggle navigation - span.icon-bar - span.icon-bar - span.icon-bar - = link_to 'Metaboflo', main_app.root_path, class: 'navbar-brand' - - if user_signed_in? - .collapse.navbar-collapse id="main-nav" - ul.nav.navbar-nav - = render 'layouts/lims/navigation_links' - +nav.navbar.navbar-dark.navbar-fixed-top.bg-inverse + a.navbar-brand href=main_app.root_path Metaboflo + ul.nav.navbar-nav + = render 'layouts/lims/navigation_links' diff --git a/app/views/layouts/lims/_navigation_links.html.slim b/app/views/layouts/lims/_navigation_links.html.slim index cc71f77..aca39af 100644 --- a/app/views/layouts/lims/_navigation_links.html.slim +++ b/app/views/layouts/lims/_navigation_links.html.slim @@ -1,47 +1,47 @@ -li.dropdown - a href="#" class="dropdown-toggle" data-toggle="dropdown" - ' #{TestSubject.title.pluralize} - ul.dropdown-menu - li= link_to "All #{TestSubject.title.pluralize}", test_subjects_path - li= link_to 'Diets', diets_path -li.dropdown - a href="#" class="dropdown-toggle" data-toggle="dropdown" Wet Lab - ul.dropdown-menu - li= link_to 'Sample Tracking', samples_path - li= link_to 'Experiments', experiments_path -li= link_to 'Run Experiment', new_workflows_experiment_path -li= link_to 'Create Study', new_workflows_study_path -li.dropdown - a href="#" class="dropdown-toggle" data-toggle="dropdown" Analysis - ul.dropdown-menu - li= link_to 'Studies', studies_path - li= link_to "#{TestSubject.title} Groups", test_subject_groupings_path - li= link_to "Sample Groups", sample_groupings_path - li= link_to "Experiment Groups", experiment_groupings_path -li= link_to 'Metabolites', metabolites_path -li.dropdown - a href="#" class="dropdown-toggle" data-toggle="dropdown" Tools - ul.dropdown-menu - li= link_to 'HMDB', 'http://www.hmdb.ca/', target: '_blank' - li= link_to 'DrugBank', 'http://drugbank.ca', target: '_blank' - li= link_to 'Metabo-Analyst', 'http://www.metaboanalyst.ca', target: '_blank' - li= link_to 'PolySearch', 'http://polysearch.cs.ualberta.ca', target: '_blank' -li.dropdown - a href="#" class="dropdown-toggle" data-toggle="dropdown" Planning - ul.dropdown-menu - li= link_to 'Tasks', tasks_path - li= link_to 'My Tasks', user_tasks_path(current_user) - li= link_to 'Gantt Chart', gantt_tasks_path - li= link_to 'Calendar', calendar_tasks_path -li.dropdown - a href="#" class="dropdown-toggle" data-toggle="dropdown" Admin - ul.dropdown-menu - li= link_to 'Sites', sites_path - li= link_to 'Data file types', data_file_types_path - li= link_to 'Users', users_path - li= link_to 'Clients', clients_path - li= link_to 'Protocols', protocols_path -li.dropdown - a href="#" class="dropdown-toggle" data-toggle="dropdown" #{glyphicon(:user)} - ul.dropdown-menu - li= link_to 'Logout', destroy_user_session_path, method: 'delete' +li.nav-item.dropdown + a.nav-link.dropdown-toggle href="#" data-toggle="dropdown" + ' #{TestSubject.title.pluralize} + div.dropdown-menu + = link_to "All #{TestSubject.title.pluralize}", test_subjects_path, class: 'dropdown-item' + = link_to 'Diets', diets_path, class: 'dropdown-item' +li.nav-item.dropdown + a.nav-link.dropdown-toggle href="#" data-toggle="dropdown" Wet Lab + div.dropdown-menu + = link_to 'Sample Tracking', samples_path, class: 'dropdown-item' + = link_to 'Experiments', experiments_path, class: 'dropdown-item' +li.nav-item= link_to 'Run Experiment', new_workflows_experiment_path, class: 'nav-link' +li.nav-item= link_to 'Create Study', new_workflows_study_path, class: 'nav-link' +li.nav-item.dropdown + a.nav-link.dropdown-toggle href="#" data-toggle="dropdown" Analysis + div.dropdown-menu + = link_to 'Studies', studies_path, class: 'dropdown-item' + = link_to "#{TestSubject.title} Groups", test_subject_groupings_path, class: 'dropdown-item' + = link_to "Sample Groups", sample_groupings_path, class: 'dropdown-item' + = link_to "Experiment Groups", experiment_groupings_path, class: 'dropdown-item' +li.nav-item= link_to 'Metabolites', metabolites_path, class: 'nav-link' +li.nav-item.dropdown + a.nav-link.dropdown-toggle href="#" data-toggle="dropdown" Tools + div.dropdown-menu + = link_to 'HMDB', 'http://www.hmdb.ca/', target: '_blank', class: 'dropdown-item' + = link_to 'DrugBank', 'http://drugbank.ca', target: '_blank', class: 'dropdown-item' + = link_to 'Metabo-Analyst', 'http://www.metaboanalyst.ca', target: '_blank', class: 'dropdown-item' + = link_to 'PolySearch', 'http://polysearch.cs.ualberta.ca', target: '_blank', class: 'dropdown-item' +li.nav-item.dropdown + a.nav-link.dropdown-toggle href="#" data-toggle="dropdown" Planning + div.dropdown-menu + = link_to 'Tasks', tasks_path, class: 'dropdown-item' + = link_to 'My Tasks', user_tasks_path(current_user), class: 'dropdown-item' + = link_to 'Gantt Chart', gantt_tasks_path, class: 'dropdown-item' + = link_to 'Calendar', calendar_tasks_path, class: 'dropdown-item' +li.nav-item.dropdown + a.nav-link.dropdown-toggle href="#" data-toggle="dropdown" Admin + div.dropdown-menu + = link_to 'Sites', sites_path, class: 'dropdown-item' + = link_to 'Data file types', data_file_types_path, class: 'dropdown-item' + = link_to 'Users', users_path, class: 'dropdown-item' + = link_to 'Clients', clients_path, class: 'dropdown-item' + = link_to 'Protocols', protocols_path, class: 'dropdown-item' +li.nav-item.dropdown + a.nav-link.dropdown-toggle href="#" data-toggle="dropdown" Account + div.dropdown-menu + = link_to 'Logout', destroy_user_session_path, method: 'delete', class: 'dropdown-item' diff --git a/app/views/samples/index.html.erb b/app/views/samples/index.html.erb deleted file mode 100644 index a88943e..0000000 --- a/app/views/samples/index.html.erb +++ /dev/null @@ -1,61 +0,0 @@ -

<%= (@parent and @parent.kind_of?(Sample)) ? "Aliquots of Sample #{@parent.id}" : (@parent and @parent.kind_of?(TestSubject)) ? "Samples for #{TestSubject.title.downcase} #{@parent}" : 'Sample Tracking' %>

- -<%= search_form_for @search, url: samples_path, html: { method: :get } do |f| %> - - - - - - - - - - - - - - <% if @parent.blank? %> - - - - - - - - - - - - - <% end -%> - -<% @samples.each do |sample| %> - - - - - - - - - - - - - - -<% end %> -
TypeBarcodeAmount Received<%= TestSubject.title unless @test_subject %><%= 'Aliquoted from' unless @parent %>Collected onCollected byLocationExperimentsActions
<%= sample.sample_type %><%= sample.barcode %><%= sample.original_amount %> <%= sample.original_unit %>
(<%= sample.theoretical_amount %> <%= sample.original_unit %> remaining)
<%= link_to(sample.root.code, sample.root) %><%= link_to(sample.sample.barcode, sample.sample) unless @parent_sample || sample.sample.nil? %><%= sample.collected_on %><%= sample.collected_by.present? ? link_to(sample.collected_by.name, sample.collected_by) : '' %><%= sample.building %> <%= sample.room %> - <% sample.experiments.each do |experiment| -%> - <%= link_to experiment.experiment_type.name, [sample, experiment] %>
- <% end -%> -
<%= show_link sample.sample ? sample_sample_path(sample.sample, sample) : test_subject_sample_path(sample.test_subject, sample) %><%= edit_link sample.sample ? edit_sample_sample_path(sample.sample, sample) : edit_test_subject_sample_path(sample.test_subject, sample) %><%= destroy_link sample.sample ? sample_sample_path(sample.sample, sample) : test_subject_sample_path(sample.test_subject, sample) %>
-<% end -%> - -
- -<% if (@parent and @parent.kind_of?(Sample)) %> - <%= new_link "aliquot of sample #{@parent.id}", new_sample_sample_path(@parent) %> -<% elsif (@parent and @parent.kind_of?(TestSubject)) %> - <%= new_link "sample for #{TestSubject.title.downcase} #{@parent.code}", new_test_subject_sample_path(@parent) %> -<% end %> diff --git a/app/views/samples/index.html.slim b/app/views/samples/index.html.slim new file mode 100644 index 0000000..ba4b4a8 --- /dev/null +++ b/app/views/samples/index.html.slim @@ -0,0 +1,74 @@ +h1 + - if !defined? @parent + ' Sample Tracking + - elsif @parent.kind_of?(Sample) + ' Aliquots of Sample #{@parent.id} + - elsif @parent.kind_of?(TestSubject) + ' Samples for #{TestSubject.title.downcase} #{@parent} + += search_form_for @search, url: samples_path, html: { method: :get } do |f| + table.list + thead + tr + th Type + th Barcode + th Amount Received + th= TestSubject.title unless @test_subject + th= 'Aliquoted from' unless @parent + th Collected on + th Collected by + th Location + th Experiments + th colspan="3" Actions + - if @parent.blank? + tr.table-search + th= f.select :sample_type_cont, Sample.sample_types, include_blank: true + th= f.text_field :barcode_cont + th= f.text_field :original_amount_gteq + th= f.text_field :test_subject_code_cont + th= f.text_field :sample_barcode_cont + th= f.text_field :collected_on_gteq + th= f.select :collected_by_id_eq, User.order(:name).map { |s| [s.name, s.id] }, include_blank: true + th= f.text_field :location_cont + th= f.text_field :experiments_experiment_type_name_cont + th colspan="3" = table_search_actions + tbody + - @samples.each do |sample| + tr + td= sample.sample_type + td= sample.barcode + td + ' #{sample.original_amount} #{sample.original_unit}
+ ' (#{sample.theoretical_amount} #{sample.original_unit} remaining) + td= link_to(sample.root.code, sample.root) + td= link_to(sample.sample.barcode, sample.sample) unless @parent_sample || sample.sample.nil? + td= sample.collected_on + td= sample.collected_by.present? ? link_to(sample.collected_by.name, sample.collected_by) : '' + td #{sample.building} #{sample.room} + td + - sample.experiments.each do |experiment| + = link_to experiment.experiment_type.name, [sample, experiment] + br + td + - if sample.aliquot? + = show_link sample_sample_path(sample.sample, sample) + - else + = show_link test_subject_sample_path(sample.test_subject, sample) + td + - if sample.aliquot? + = edit_link edit_sample_sample_path(sample.sample, sample) + - else + = edit_link edit_test_subject_sample_path(sample.test_subject, sample) + td + - if sample.aliquot? + = destroy_link sample_sample_path(sample.sample, sample) + - else + = destroy_link test_subject_sample_path(sample.test_subject, sample) +br +- if defined? @parent + - if @parent.kind_of?(Sample) + = new_link "aliquot of sample #{@parent.id}", new_sample_sample_path(@parent) + - elsif @parent.kind_of?(TestSubject) + = new_link "sample for #{TestSubject.title.downcase} #{@parent.code}", + new_test_subject_sample_path(@parent) + diff --git a/app/views/samples/show.html.erb b/app/views/samples/show.html.erb deleted file mode 100644 index 4202cf0..0000000 --- a/app/views/samples/show.html.erb +++ /dev/null @@ -1,138 +0,0 @@ -

- Showing <%= @sample.aliquot? ? 'aliquot' : 'sample' %> <%= @sample.barcode %> from <%= @sample.aliquot? ? 'sample ' : "#{TestSubject.title.downcase} " %> <%= @sample.parent %> -

- -

- Sample type: - <%= @sample.sample_type %> -

- -

- Barcode: - <%= @sample.barcode %> -

- -

- <%= TestSubject.title %>: - <%= link_to(@sample.root.to_s, test_subject_path(@sample.root)) %> -

- -
- -<%= new_link "Aliquot", new_sample_sample_path(@sample) %> | <%= new_link 'Experiment', new_sample_experiment_path(@sample) %>
- -
- -
- Client-related Information -

- Client: - <%= @sample.client.name unless @sample.client.blank? %> -

- -

- Status: - <%= @sample.status %>   - <% unless @sample.client.nil? %> - <%= link_to (@sample.status == 'Finished' ? 'Notify client' : 'Mark finished'), finish_sample_path(@sample), :method => :post, :confirm => 'A notification will be sent to the client. Proceed?' %> - <% end %> -

- -

- Reports:
- <% @sample.stored_files.each do |stored_file| %> - <%= link_to stored_file.attachment_file_name, stored_file.attachment.url %> - <% end %> -

-
- -
- -
- Volume Information -

- Original amount: - <%= @sample.original_amount %> <%= @sample.original_unit %> -

- -

- Actual amount: - <%= @sample.actual_amount %> <%= @sample.actual_unit %> -

- -

- Theoretical amount: - <%= @sample.theoretical_amount %> <%= @sample.original_unit %> -

-
- -
- -
- Storage Location -

- Site: - <%=(@sample.site.name) if @sample.site %> -

- -

- Building: - <%= @sample.building %> -

- -

- Room: - <%= @sample.room %> -

- -

- Freezer: - <%= @sample.freezer %> -

- -

- Shelf: - <%= @sample.shelf %> -

- -

- Box: - <%= @sample.box %> -

- -

- Box Position: - <%= @sample.box_position %> -

-
- -
- -
- Collection Details - <% if @sample.aliquot? %> -

- Source sample: - <%= link_to(@sample.sample, sample_path(@sample.sample)) %> -

- <% end %> - -

- Collected on: - <%= @sample.collected_on %> -

- -

- Collected by: - <%= @sample.collected_by %> -

- -

- Description: - <%= @sample.description %> -

-
- -
- -<%= edit_link @sample.aliquot? ? edit_sample_sample_path(@sample.sample, @sample) : edit_test_subject_sample_path(@test_subject, @sample) %> diff --git a/app/views/samples/show.html.slim b/app/views/samples/show.html.slim new file mode 100644 index 0000000..0ccf8e7 --- /dev/null +++ b/app/views/samples/show.html.slim @@ -0,0 +1,85 @@ +h1 Showing #{@sample.aliquot? ? 'aliquot' : 'sample'} #{@sample.barcode} from #{@sample.aliquot? ? 'sample ' : "#{TestSubject.title.downcase} "} #{@sample.parent} + +.card-deck + .card + .card-header Sample Details + .card-block + dl + dt Sample type: + dd = @sample.sample_type + dt Barcode: + dd = @sample.barcode + dt = TestSubject.title + dd = link_to(@sample.root.to_s, test_subject_path(@sample.root)) + .card-footer + .btn-group + = new_link 'aliquot', new_sample_sample_path(@sample) + = new_link 'experiment', new_sample_experiment_path(@sample) + + .card + .card-header Client-related Information + .card-block + dl + dt Client + dd = nah @sample.client&.name + dt Status + dd = nah @sample.status + dt Reports + dd + - if @sample.stored_files.present? + - @sample.stored_files.each do |stored_file| + = link_to stored_file.attachment_file_name, stored_file.attachment.url + - else + = nah nil, 'None' + .card-footer + .btn-group + = link_to finish_sample_path(@sample), method: :post, confirm: 'A notification will be sent to the client. Proceed?', class: 'btn btn-info btn-sm' do + = @sample.status == 'Finished' ? 'Notify client' : 'Mark finished' + +.card-deck + .card + .card-header Volume Information + .card-block + dl + dt Original amount + dd #{@sample.original_amount} #{@sample.original_unit} + dt Actual amount + dd = nah "#{@sample.actual_amount} #{@sample.actual_unit}" + dt Theoretical amount + dd #{@sample.theoretical_amount} #{@sample.original_unit} + .card + .card-header Storage Location + .card-block + dl + dt Site + dd = nah @sample.site&.name + dt Building + dd = nah @sample.building + dt Room + dd = nah @sample.room + dt Freezer + dd = nah @sample.freezer + dt Shelf + dd = nah @sample.shelf + dt Box + dd = nah @sample.box + dt Box Position + dd = nah @sample.box_position + .card + .card-header Collection Details + .card-block + dl + - if @sample.aliquot? + dt Source sample + dd = link_to(@sample.sample, sample_path(@sample.sample)) + dt Collected on + dd = nah @sample.collected_on + dt Collected by + dd = nah @sample.collected_by + dt Description + dd = nah @sample.description + +br + += edit_link @sample.aliquot? ? edit_sample_sample_path(@sample.sample, @sample) : edit_test_subject_sample_path(@test_subject, @sample) + diff --git a/app/views/test_subjects/subjects/patient/index.html.erb b/app/views/test_subjects/subjects/patient/index.html.erb deleted file mode 100644 index acca9dc..0000000 --- a/app/views/test_subjects/subjects/patient/index.html.erb +++ /dev/null @@ -1,38 +0,0 @@ -

<%= title 'Patients' %>

- -<%= search_form_for @search, url: test_subjects_path, html: { method: :get } do |f| %> - - - - - - - - - - - - - - - - - - - <% @test_subjects.each do |patient| %> - - - - - - - - - - - <% end %> -
CodeSite# of samplesPractitionerNotesActions
<%= link_to(patient.code, patient) %><%= patient.site.name %><%= patient.samples.length %> (<%= link_to 'display', test_subject_samples_path(patient) %>)<%= patient.practitioner %><%= truncate(patient.notes) %><%= show_link patient %><%= edit_link edit_test_subject_path(patient) %><%= destroy_link patient %>
-<% end %> - -
-<%= new_link 'patient', new_test_subject_path %> diff --git a/app/views/test_subjects/subjects/patient/index.html.slim b/app/views/test_subjects/subjects/patient/index.html.slim new file mode 100644 index 0000000..7de4f39 --- /dev/null +++ b/app/views/test_subjects/subjects/patient/index.html.slim @@ -0,0 +1,33 @@ +h1= title 'Patients' += search_form_for @search, url: test_subjects_path, html: { method: :get } do |f| + table.list + thead + tr.header + th Code + th Site + th # of samples + th Practitioner + th Notes + th colspan="3" + tr.table-search + th= f.text_field :code_cont, size: 12 + th= f.select :site_id_eq, Site.order(:name).map { |s| [s.name, s.id] }, include_blank: true + th + th= f.text_field :practitioner_cont, size: 15 + th= f.text_field :notes_cont + th colspan="3" + = table_search_actions + tbody + - @test_subjects.each do |patient| + tr + td= link_to(patient.code, patient) + td= patient.site.name + td #{patient.samples.length} (#{link_to 'display', test_subject_samples_path(patient)}) + td= patient.practitioner + td= truncate(patient.notes) + td= show_link patient + td= edit_link edit_test_subject_path(patient) + td= destroy_link patient + += new_link 'patient', new_test_subject_path + diff --git a/app/views/test_subjects/subjects/patient/show.html.erb b/app/views/test_subjects/subjects/patient/show.html.erb deleted file mode 100644 index 15e2cc8..0000000 --- a/app/views/test_subjects/subjects/patient/show.html.erb +++ /dev/null @@ -1,45 +0,0 @@ -

<%= title "Showing patient #{@test_subject}" %>

- -

- Code: - <%= @test_subject.code %> -

- -

- Site: - <%= @test_subject.site.name %> -

- -

- Birthdate: - <%= @test_subject.birthdate %> -

- -

- Blood type: - <%= @test_subject.blood_type %> -

- -

- Gender: - <%= @test_subject.gender %> -

- -

- Race: - <%= @test_subject.race %> -

- -

- Practitioner: - <%= @test_subject.practitioner %> -

- -

- Notes: - <%= @test_subject.notes %> -

- -
- -<%= edit_link edit_test_subject_path(@test_subject) %> diff --git a/app/views/test_subjects/subjects/patient/show.html.slim b/app/views/test_subjects/subjects/patient/show.html.slim new file mode 100644 index 0000000..e784313 --- /dev/null +++ b/app/views/test_subjects/subjects/patient/show.html.slim @@ -0,0 +1,30 @@ +.card + h3.card-header = title "Showing #{TestSubject.title} #{@test_subject}" + .card-block + p + b Code: + = @test_subject.code + p + b Site: + = @test_subject.site.name + p + b Birthdate: + = @test_subject.birthdate + p + b Blood type: + = @test_subject.blood_type + p + b Gender: + = @test_subject.gender + p + b Race: + = @test_subject.race + p + b Practitioner: + = @test_subject.practitioner + p + b Notes: + = @test_subject.notes + br/ + = edit_link edit_test_subject_path(@test_subject) + diff --git a/app/views/workflows/experiments/new.html.erb b/app/views/workflows/experiments/new.html.erb deleted file mode 100644 index ff424e6..0000000 --- a/app/views/workflows/experiments/new.html.erb +++ /dev/null @@ -1,96 +0,0 @@ -

<%= title 'New Experiment' %>

- -

- <%= image_tag 'info.png', class: 'info-logo' %> - The experiment workflow allows you to enter all the information for an experiment. You can attach raw data files or concentration data, assign this experiment to a particular individual, and enter the protocol used to perform the analysis. -

- -<%= knoxy_form_for [ :workflows, setup_workflow_experiment(@experiment) ], html: { multipart: true } do |f| %> - <% flash.now[:error] = "#{pluralize(@experiment.errors.count, "error")} prohibited this experiment from being saved" if @experiment.errors.any? %> - -
- Sample Details - - <% if @experiment.sample.present? %> - <% @sample = @experiment.sample %> - <%= render partial: '/workflows/samples/sample' %> - <%= f.hidden_field :sample_id %> - <% else %> - -
- <%= f.inner_field :test_subject, label: "#{TestSubject.title} Code", id: 'dfdf' do %> - <%= text_field_tag :test_subject_code, nil, - class: 'test-subject-autocomplete', :'data-source' => workflows_patients_path(format: :json), - :'data-update' => 'test-subject-id', placeholder: 'Start typing a patient code', - id: 'test-subject-autocomplete-code' %> - <%= hidden_field_tag :test_subject_id, nil, id: 'test-subject-id', :'data-sample-update' => 'sample-id' %> - - <%= link_to 'Add New Patient', new_workflows_patient_path, id: 'open-patient-dialog' %> - - <% end -%> -
- - -
- <% end %> -
- -
- Experiment Description - <%= f.input :name, style: "width: 250px", required: true %> - <%= error_message(Experiment.human_attribute_name(:name), f.object.errors[:name]) %> - - <%= f.input :protocol_id, collection: Protocol.all, include_blank: true %> - <%= error_message(Experiment.human_attribute_name(:protocol_id), f.object.errors[:protocol_id]) %> - - <%= f.input :experiment_type_id, collection: ExperimentType.all, include_blank: true %> - <%= error_message(Experiment.human_attribute_name(:experiment_type_id), f.object.errors[:experiment_type_id]) %> - - <%= f.input :description %> - <%= error_message(Experiment.human_attribute_name(:description), f.object.errors[:description]) %> - - <%= f.input :comments %> - <%= error_message(Experiment.human_attribute_name(:comments), f.object.errors[:comments]) %> -
- -
- Analysis - <%= f.inner_field_group :assigned_to_id do %> - <%= f.input :assigned_to_id, collection: User.order(:name), include_blank: true %> - on - <%= f.input :perform_on, class: 'datepicker' %> - <% end -%> - <%= f.inner_field_group :performed_by_id do %> - <%= f.input :performed_by_id, collection: User.order(:name), include_blank: true %> - on - <%= f.input :performed_on, class: 'datepicker' %> - <% end -%> -
- -
- Data files - - <%= f.full_field_group :data_files do %> - <%= f.fields_for :data_files do |data_files_form| %> - <%= render 'data_file', f: data_files_form %> - <% end %> -
<%= add_child_link f, :data_files, partial: 'data_file', name: 'Add Data File' %>
- <% end -%> -
- -
- <%= f.submit %> -
-<% end %> diff --git a/app/views/workflows/experiments/new.html.slim b/app/views/workflows/experiments/new.html.slim new file mode 100644 index 0000000..375eacf --- /dev/null +++ b/app/views/workflows/experiments/new.html.slim @@ -0,0 +1,60 @@ +h1 New Experiment +p.info #{icon('info-circle', class: 'fa-2x info-logo')} The experiment workflow allows you to enter all the information for an experiment. You can attach raw data files or concentration data, assign this experiment to a particular individual, and enter the protocol used to perform the analysis. + += knoxy_form_for [:workflows, setup_workflow_experiment(@experiment)] do |f| + - flash.now[:error] = "#{pluralize(@experiment.errors.count, "error")} prohibited this experiment from being saved" if @experiment.errors.any? + fieldset + legend Sample Details + - if @experiment.sample.present? + - @sample = @experiment.sample + = render partial: '/workflows/samples/sample' + = f.hidden_field :sample_id + - else + #patient-selector + = f.inner_field :test_subject, label: "#{TestSubject.title} Code", id: 'dfdf' do + = text_field_tag :test_subject_code, nil, class: 'test-subject-autocomplete', + placeholder: 'Start typing a patient code', id: 'test-subject-autocomplete-code', + data: { source: workflows_patients_path(format: :json), update: 'test-subject-id' } + = hidden_field_tag :test_subject_id, nil, id: 'test-subject-id', + data: { 'sample-update' => 'sample-id' } + span.actions + = link_to 'Add New Patient', new_workflows_patient_path, id: 'open-patient-dialog' + #sample-selector style="display:none" + = f.inner_field :sample do + = f.input :sample_id, collection: options_for_workflow_sample(@experiment.test_subject_code), + include_blank: true, id: 'sample-id' + span.actions + = link_to 'Add New Sample', new_workflows_sample_path, id: 'open-sample-dialog' + = f.input :amount_used + = f.input :amount_used_unit, collection: volume_unit_options + = error_message(Experiment.human_attribute_name(:amount_used_unit), f.object.errors[:amount_used_unit]) + #sample-added-show + fieldset + legend Experiment Description + = f.input :name, style: "width: 250px", required: true + = error_message(Experiment.human_attribute_name(:name), f.object.errors[:name]) + = f.input :protocol_id, collection: Protocol.all, include_blank: true + = error_message(Experiment.human_attribute_name(:protocol_id), f.object.errors[:protocol_id]) + = f.input :experiment_type_id, collection: ExperimentType.all, include_blank: true + = error_message(Experiment.human_attribute_name(:experiment_type_id), f.object.errors[:experiment_type_id]) + = f.input :description + = error_message(Experiment.human_attribute_name(:description), f.object.errors[:description]) + = f.input :comments + = error_message(Experiment.human_attribute_name(:comments), f.object.errors[:comments]) + fieldset + legend Analysis + = f.inner_field_group :assigned_to_id do + = f.association :assigned_to, include_blank: true + = f.input :perform_on, class: 'datepicker' + = f.inner_field_group :performed_by_id do + = f.association :performed_by, include_blank: true + = f.input :performed_on, class: 'datepicker' + fieldset#data_files.fields-for + legend Data files + = f.full_field_group :data_files do + = f.fields_for :data_files do |data_files_form| + = render 'data_file', f: data_files_form + div= add_child_link f, :data_files, partial: 'data_file', name: 'Add Data File' + .field-no-label.actions + = f.submit + diff --git a/lib/knoxy_form_builder.rb b/lib/knoxy_form_builder.rb index 9c41484..ecfcc6f 100644 --- a/lib/knoxy_form_builder.rb +++ b/lib/knoxy_form_builder.rb @@ -75,22 +75,5 @@ def group_item(field, options = {}) end full_field.html_safe end - - def textile_editor(field, options = {}) - options[:input_html] ||= {} - if options[:input_html][:class].present? - options[:input_html][:class] << ' textile-editor' - else - options[:input_html][:class] = 'textile-editor' - end - options[:placeholder] ||= 'Insert text in Textile format' - options[:hint] = - @template.link_to('Textile Reference', - 'http://redcloth.org/hobix.com/textile/quick.html', - target: '_blank', class: 'textile-hint') << - options[:hint].to_s.html_safe - @template.content_tag(:div, self.input(field, options), - class: 'textile-holder') - end end