diff --git a/Gemfile b/Gemfile index e4fffea..90ca431 100644 --- a/Gemfile +++ b/Gemfile @@ -6,7 +6,7 @@ # RAILS # Full-stack web application framework. (http://www.rubyonrails.org) # Full-stack web application framework. (http://rubyonrails.org) -gem 'rails', '~> 4.2.10' +gem 'rails', '~> 4.2.11.1' # Rake is a Make-like program implemented in Ruby (https://github.com/ruby/rake) gem "rake" diff --git a/Gemfile.lock b/Gemfile.lock index ca18930..8b13c2b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -30,7 +30,7 @@ activemodel (= 4.2.11.1) activesupport (= 4.2.11.1) arel (~> 6.0) - activerecord-session_store (1.1.2) + activerecord-session_store (1.1.3) actionpack (>= 4.0) activerecord (>= 4.0) multi_json (~> 1.11, >= 1.11.2) @@ -88,7 +88,7 @@ launchy childprocess (0.9.0) ffi (~> 1.0, >= 1.0.11) - chromedriver-helper (2.1.0) + chromedriver-helper (2.1.1) archive-zip (~> 0.10) nokogiri (~> 1.8) coderay (1.1.2) @@ -101,7 +101,7 @@ daemons (1.3.1) database_cleaner (1.7.0) debug_inspector (0.0.3) - devise (4.6.1) + devise (4.6.2) bcrypt (~> 3.0) orm_adapter (~> 0.1) railties (>= 4.1.0, < 6.0) @@ -112,9 +112,9 @@ devise (>= 4.0.0) diff-lcs (1.3) docile (1.3.1) - dotenv (2.7.1) - dotenv-rails (2.7.1) - dotenv (= 2.7.1) + dotenv (2.7.2) + dotenv-rails (2.7.2) + dotenv (= 2.7.2) railties (>= 3.2, < 6.1) dragonfly (1.2.0) addressable (~> 2.3) @@ -257,7 +257,7 @@ multipart-post (2.0.0) mysql2 (0.4.10) nenv (0.3.0) - nokogiri (1.10.1) + nokogiri (1.10.2) mini_portile2 (~> 2.4.0) notiffany (0.1.1) nenv (~> 0.1) @@ -466,7 +466,8 @@ activesupport (>= 4.2) rack-proxy (>= 0.6.1) railties (>= 4.2) - wicked_pdf (1.1.0) + wicked_pdf (1.2.1) + activesupport wkhtmltopdf-binary (0.12.4) xpath (3.2.0) nokogiri (~> 1.8) @@ -526,7 +527,7 @@ puma pundit rack-mini-profiler - rails (~> 4.2.10) + rails (~> 4.2.11.1) rails_12factor railties rake diff --git a/app/assets/fonts/GillSans-Light.ttf b/app/assets/fonts/GillSans-Light.ttf new file mode 100644 index 0000000..5d5a135 --- /dev/null +++ b/app/assets/fonts/GillSans-Light.ttf Binary files differ diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 5d2acee..3203372 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -8,5 +8,10 @@ @debug "3 #{$navbar-branding-bg}"; @import "utils/*"; +// JQuery-UI CSS for Datepicker +@import "vendor/jquery-ui/datepicker/jquery-ui.min.css"; +@import "vendor/jquery-ui/datepicker/jquery-ui.structure.min.css"; +@import "vendor/jquery-ui/datepicker/jquery-ui.theme.min.css"; + @import "font-awesome-sprockets"; @import "font-awesome"; diff --git a/app/assets/stylesheets/blocks/_datepicker.scss b/app/assets/stylesheets/blocks/_datepicker.scss new file mode 100644 index 0000000..cc17f93 --- /dev/null +++ b/app/assets/stylesheets/blocks/_datepicker.scss @@ -0,0 +1,32 @@ +.ui-datepicker-header { + background: $color-seccondary-background; + color: $color-seccondary-text; + border: none; +} +.ui-datepicker-prev, +.ui-datepicker-next, +.ui-datepicker-prev:hover, .ui-datepicker-prev:focus, +.ui-datepicker-next:hover, .ui-datepicker-next:focus { + background: $color-primary-background; + color: $color-primary-text; + + .ui-icon { + background-attachment: none; + background-clip: none; + background-color: $color-primary-background; + background-image: none; + background-origin: none; + background-position: 1px 1px; + color: $color-primary-text; + } +} + +.ui-datepicker-next:before { + content: '\f0da'; + font-family: FontAwesome; + font-weight: normal; + font-style: normal; + margin: 0px 0px 0px 10px; + text-decoration: none; + width: 15px; +} diff --git a/app/assets/stylesheets/blocks/_question_container.scss b/app/assets/stylesheets/blocks/_question_container.scss new file mode 100644 index 0000000..d70077c --- /dev/null +++ b/app/assets/stylesheets/blocks/_question_container.scss @@ -0,0 +1,10 @@ +.question_container { + + dl.dl-horizontal { + padding-right: 10px; + border-right: 1px solid $color-black; + } + .fa-plus, .fa-minus { + font-size: 1.6rem; + } +} \ No newline at end of file diff --git a/app/assets/stylesheets/blocks/_readonly_textarea.scss b/app/assets/stylesheets/blocks/_readonly_textarea.scss new file mode 100644 index 0000000..ec288cf --- /dev/null +++ b/app/assets/stylesheets/blocks/_readonly_textarea.scss @@ -0,0 +1,19 @@ +/* For display of readonly textarea content without the TinyMCE editor */ +.display-readonly-textarea-content { + // Replicating some TinyMCE styling of textarea + overflow-y: hidden; + padding-left: 1px; + padding-right: 1px; + padding-bottom: 10px; + + // Ensure table borders are not lost + table { + td { + border: 1px solid black; + } + + td, tr { + padding: 10px; + } + } +} diff --git a/app/assets/stylesheets/utils/_break_words.scss b/app/assets/stylesheets/utils/_break_words.scss new file mode 100644 index 0000000..53a6c2d --- /dev/null +++ b/app/assets/stylesheets/utils/_break_words.scss @@ -0,0 +1,4 @@ +.allow-break-words { + overflow-wrap: break-word; + width: 100%; +} diff --git a/app/assets/stylesheets/variables/_bootstrap.scss b/app/assets/stylesheets/variables/_bootstrap.scss index fdfcc7c..edc5852 100644 --- a/app/assets/stylesheets/variables/_bootstrap.scss +++ b/app/assets/stylesheets/variables/_bootstrap.scss @@ -30,11 +30,11 @@ // from colors: -$dropdown-inverse-bg: $color-navbar-background; -$dropdown-inverse-border: $color-dropdown-inverse-border; -$dropdown-inverse-text: $color-dropdown-inverse-text; -$dropdown-inverse-text-hoover: $color-dropdown-inverse-text-hover; -$dropdown-inverse-bg-hoover: $color-navbar-background-active; +$dropdown-inverse-bg: $color-navbar-background !default; +$dropdown-inverse-border: $color-dropdown-inverse-border !default; +$dropdown-inverse-text: $color-dropdown-inverse-text !default; +$dropdown-inverse-text-hoover: $color-dropdown-inverse-text-hover !default; +$dropdown-inverse-bg-hoover: $color-navbar-background-active !default; // Navbar branding colours $navbar-branding-color: $color-navbar-text !default; @@ -55,5 +55,5 @@ $navbar-branding-toggle-border-color: $color-navbar-background-active !default; // org-navbar branding colors -$navbar-org-link-color: $color-org-navbar-links; -$navbar-org-link-hover-color: $color-org-navbar-links-hover; +$navbar-org-link-color: $color-org-navbar-links !default; +$navbar-org-link-hover-color: $color-org-navbar-links-hover !default; diff --git a/app/assets/stylesheets/vendor/jquery-ui/datepicker/jquery-ui.min.css b/app/assets/stylesheets/vendor/jquery-ui/datepicker/jquery-ui.min.css new file mode 100644 index 0000000..a686231 --- /dev/null +++ b/app/assets/stylesheets/vendor/jquery-ui/datepicker/jquery-ui.min.css @@ -0,0 +1,7 @@ +/*! jQuery UI - v1.12.1 - 2019-03-06 +* http://jqueryui.com +* Includes: core.css, datepicker.css, theme.css +* To view and modify this theme, visit http://jqueryui.com/themeroller/?scope=&folderName=custom-theme&bgImgOpacityError=&bgImgOpacityHighlight=&bgImgOpacityActive=&bgImgOpacityHover=&bgImgOpacityDefault=&bgImgOpacityContent=&bgImgOpacityHeader=&cornerRadiusShadow=8px&offsetLeftShadow=0px&offsetTopShadow=0px&thicknessShadow=5px&opacityShadow=30&bgImgOpacityShadow=0&bgTextureShadow=flat&bgColorShadow=%23666666&opacityOverlay=30&bgImgOpacityOverlay=0&bgTextureOverlay=flat&bgColorOverlay=%23aaaaaa&iconColorError=%23cc0000&fcError=%235f3f3f&borderColorError=%23f1a899&bgTextureError=flat&bgColorError=%23fddfdf&iconColorHighlight=%23fff&fcHighlight=%23fff&borderColorHighlight=%23337ab7&bgTextureHighlight=flat&bgColorHighlight=%23337ab7&iconColorActive=%23ffffff&fcActive=%23ffffff&borderColorActive=%23777&bgTextureActive=flat&bgColorActive=%234F5253&iconColorHover=%23555555&fcHover=%232b2b2b&borderColorHover=%23cccccc&bgTextureHover=flat&bgColorHover=%23ededed&iconColorDefault=%23777777&fcDefault=%23454545&borderColorDefault=%23c5c5c5&bgTextureDefault=flat&bgColorDefault=%23f6f6f6&iconColorContent=%234F5253&fcContent=%234F5253&borderColorContent=%23dddddd&bgTextureContent=flat&bgColorContent=%23ffffff&iconColorHeader=%23FFF&fcHeader=%23FFF&borderColorHeader=%234F5253&bgTextureHeader=flat&bgColorHeader=%234F5253&cornerRadius=3px&fwDefault=normal&fsDefault=1em&ffDefault=GillSansLight%2CArial%2Csans-serif +* Copyright jQuery Foundation and other contributors; Licensed MIT */ + +.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important;pointer-events:none}.ui-icon{display:inline-block;vertical-align:middle;margin-top:-.25em;position:relative;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-icon-block{left:50%;margin-left:-8px;display:block}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:45%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-datepicker .ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat;left:.5em;top:.3em}.ui-widget{font-family:GillSansLight,Arial,sans-serif;font-size:1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:GillSansLight,Arial,sans-serif;font-size:1em}.ui-widget.ui-widget-content{border:1px solid #c5c5c5}.ui-widget-content{border:1px solid #ddd;background:#fff;color:#4F5253}.ui-widget-content a{color:#4F5253}.ui-widget-header{border:1px solid #4F5253;background:#4F5253;color:#FFF;font-weight:bold}.ui-widget-header a{color:#FFF}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default,.ui-button,html .ui-button.ui-state-disabled:hover,html .ui-button.ui-state-disabled:active{border:1px solid #c5c5c5;background:#f6f6f6;font-weight:normal;color:#454545}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited,a.ui-button,a:link.ui-button,a:visited.ui-button,.ui-button{color:#454545;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus,.ui-button:hover,.ui-button:focus{border:1px solid #ccc;background:#ededed;font-weight:normal;color:#2b2b2b}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited,a.ui-button:hover,a.ui-button:focus{color:#2b2b2b;text-decoration:none}.ui-visual-focus{box-shadow:0 0 3px 1px rgb(94,158,214)}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active,a.ui-button:active,.ui-button:active,.ui-button.ui-state-active:hover{border:1px solid #777;background:#4F5253;font-weight:normal;color:#fff}.ui-icon-background,.ui-state-active .ui-icon-background{border:#777;background-color:#fff}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#fff;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #337ab7;background:#337ab7;color:#fff}.ui-state-checked{border:1px solid #337ab7;background:#337ab7}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#fff}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #f1a899;background:#fddfdf;color:#5f3f3f}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#5f3f3f}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#5f3f3f}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("images/ui-icons_4F5253_256x240.png")}.ui-widget-header .ui-icon{background-image:url("images/ui-icons_FFF_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon,.ui-button:hover .ui-icon,.ui-button:focus .ui-icon{background-image:url("images/ui-icons_555555_256x240.png")}.ui-state-active .ui-icon,.ui-button:active .ui-icon{background-image:url("images/ui-icons_ffffff_256x240.png")}.ui-state-highlight .ui-icon,.ui-button .ui-state-highlight.ui-icon{background-image:url("images/ui-icons_fff_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("images/ui-icons_cc0000_256x240.png")}.ui-button .ui-icon{background-image:url("images/ui-icons_777777_256x240.png")}.ui-icon-blank{background-position:16px 16px}.ui-icon-caret-1-n{background-position:0 0}.ui-icon-caret-1-ne{background-position:-16px 0}.ui-icon-caret-1-e{background-position:-32px 0}.ui-icon-caret-1-se{background-position:-48px 0}.ui-icon-caret-1-s{background-position:-65px 0}.ui-icon-caret-1-sw{background-position:-80px 0}.ui-icon-caret-1-w{background-position:-96px 0}.ui-icon-caret-1-nw{background-position:-112px 0}.ui-icon-caret-2-n-s{background-position:-128px 0}.ui-icon-caret-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-65px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-65px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:1px -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:3px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:3px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:3px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:3px}.ui-widget-overlay{background:#aaa;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{-webkit-box-shadow:0 0 5px #666;box-shadow:0 0 5px #666} \ No newline at end of file diff --git a/app/assets/stylesheets/vendor/jquery-ui/datepicker/jquery-ui.structure.min.css b/app/assets/stylesheets/vendor/jquery-ui/datepicker/jquery-ui.structure.min.css new file mode 100644 index 0000000..1390420 --- /dev/null +++ b/app/assets/stylesheets/vendor/jquery-ui/datepicker/jquery-ui.structure.min.css @@ -0,0 +1,5 @@ +/*! jQuery UI - v1.12.1 - 2019-03-06 +* http://jqueryui.com +* Copyright jQuery Foundation and other contributors; Licensed MIT */ + +.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important;pointer-events:none}.ui-icon{display:inline-block;vertical-align:middle;margin-top:-.25em;position:relative;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-icon-block{left:50%;margin-left:-8px;display:block}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:45%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-datepicker .ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat;left:.5em;top:.3em} \ No newline at end of file diff --git a/app/assets/stylesheets/vendor/jquery-ui/datepicker/jquery-ui.theme.min.css b/app/assets/stylesheets/vendor/jquery-ui/datepicker/jquery-ui.theme.min.css new file mode 100644 index 0000000..ae47491 --- /dev/null +++ b/app/assets/stylesheets/vendor/jquery-ui/datepicker/jquery-ui.theme.min.css @@ -0,0 +1,5 @@ +/*! jQuery UI - v1.12.1 - 2019-03-06 +* http://jqueryui.com +* Copyright jQuery Foundation and other contributors; Licensed MIT */ + +.ui-widget{font-family:GillSansLight,Arial,sans-serif;font-size:1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:GillSansLight,Arial,sans-serif;font-size:1em}.ui-widget.ui-widget-content{border:1px solid #c5c5c5}.ui-widget-content{border:1px solid #ddd;background:#fff;color:#4F5253}.ui-widget-content a{color:#4F5253}.ui-widget-header{border:1px solid #4F5253;background:#4F5253;color:#FFF;font-weight:bold}.ui-widget-header a{color:#FFF}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default,.ui-button,html .ui-button.ui-state-disabled:hover,html .ui-button.ui-state-disabled:active{border:1px solid #c5c5c5;background:#f6f6f6;font-weight:normal;color:#454545}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited,a.ui-button,a:link.ui-button,a:visited.ui-button,.ui-button{color:#454545;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus,.ui-button:hover,.ui-button:focus{border:1px solid #ccc;background:#ededed;font-weight:normal;color:#2b2b2b}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited,a.ui-button:hover,a.ui-button:focus{color:#2b2b2b;text-decoration:none}.ui-visual-focus{box-shadow:0 0 3px 1px rgb(94,158,214)}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active,a.ui-button:active,.ui-button:active,.ui-button.ui-state-active:hover{border:1px solid #777;background:#4F5253;font-weight:normal;color:#fff}.ui-icon-background,.ui-state-active .ui-icon-background{border:#777;background-color:#fff}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#fff;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #337ab7;background:#337ab7;color:#fff}.ui-state-checked{border:1px solid #337ab7;background:#337ab7}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#fff}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #f1a899;background:#fddfdf;color:#5f3f3f}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#5f3f3f}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#5f3f3f}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("images/ui-icons_4F5253_256x240.png")}.ui-widget-header .ui-icon{background-image:url("images/ui-icons_FFF_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon,.ui-button:hover .ui-icon,.ui-button:focus .ui-icon{background-image:url("images/ui-icons_555555_256x240.png")}.ui-state-active .ui-icon,.ui-button:active .ui-icon{background-image:url("images/ui-icons_ffffff_256x240.png")}.ui-state-highlight .ui-icon,.ui-button .ui-state-highlight.ui-icon{background-image:url("images/ui-icons_fff_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("images/ui-icons_cc0000_256x240.png")}.ui-button .ui-icon{background-image:url("images/ui-icons_777777_256x240.png")}.ui-icon-blank{background-position:16px 16px}.ui-icon-caret-1-n{background-position:0 0}.ui-icon-caret-1-ne{background-position:-16px 0}.ui-icon-caret-1-e{background-position:-32px 0}.ui-icon-caret-1-se{background-position:-48px 0}.ui-icon-caret-1-s{background-position:-65px 0}.ui-icon-caret-1-sw{background-position:-80px 0}.ui-icon-caret-1-w{background-position:-96px 0}.ui-icon-caret-1-nw{background-position:-112px 0}.ui-icon-caret-2-n-s{background-position:-128px 0}.ui-icon-caret-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-65px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-65px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:1px -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:3px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:3px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:3px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:3px}.ui-widget-overlay{background:#aaa;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{-webkit-box-shadow:0 0 5px #666;box-shadow:0 0 5px #666} \ No newline at end of file diff --git a/app/assets/vendor/jquery-ui/datepicker/images/ui-bg_flat_0_aaaaaa_40x100.png b/app/assets/vendor/jquery-ui/datepicker/images/ui-bg_flat_0_aaaaaa_40x100.png new file mode 100644 index 0000000..88f194b --- /dev/null +++ b/app/assets/vendor/jquery-ui/datepicker/images/ui-bg_flat_0_aaaaaa_40x100.png @@ -0,0 +1,972 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + jquery-ui/ui-bg_flat_0_aaaaaa_40x100.png at master · jquery/jquery-ui + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Skip to content +
+ + + + + + + + + + + +
+ +
+ +
+ +
+ + + +
+
+
+ + + + + + + + + + + +
+
+ +
    + + + +
  • +
    + +
    + + + Watch + + +
    + Notifications +
    +
    + + + + + + + +
    +
    +
    + +
    +
  • + +
  • +
    +
    + + +
    +
    + + +
    + +
  • + +
  • +
    + + Fork + +
    + +

    Fork jquery-ui

    +
    +
    + +
    +

    If this dialog fails to load, you can visit the fork page directly.

    +
    +
    +
    +
    + + +
  • +
+ +

+ + /jquery-ui + +

+ +
+ + + + +
+
+
+ + + + + + + + Permalink + + + + + +
+ +
+ + Branch: + master + + + + + + + +
+ +
+ + Find file + + + Copy path + +
+ +
+ + + +
+ + +
+ +
+ + + 2 contributors + + +
+ +

Users who have contributed to this file

+
+ + + +
+
+ + @TravisCarden + + @PeterDaveHello + + +
+
+ + + + + +
+ +
+ +
+ 86 Bytes +
+ +
+ + + + +
+ +
+ +
+
+
+ + + +
+
+ ui-bg_flat_0_aaaaaa_40x100.png +
+
+ +
+ + + +
+ + +
+ + +
+
+ + + +
+ +
+ +
+
+ + +
+ + + + + + +
+ + + You can’t perform that action at this time. +
+ + + + + + + + + +
+ + You signed in with another tab or window. Reload to refresh your session. + You signed out in another tab or window. Reload to refresh your session. +
+ + + + +
+ + + + diff --git a/app/assets/vendor/jquery-ui/datepicker/images/ui-icons_444444_256x240.png b/app/assets/vendor/jquery-ui/datepicker/images/ui-icons_444444_256x240.png new file mode 100644 index 0000000..9221438 --- /dev/null +++ b/app/assets/vendor/jquery-ui/datepicker/images/ui-icons_444444_256x240.png Binary files differ diff --git a/app/assets/vendor/jquery-ui/datepicker/images/ui-icons_555555_256x240.png b/app/assets/vendor/jquery-ui/datepicker/images/ui-icons_555555_256x240.png new file mode 100644 index 0000000..c974ed9 --- /dev/null +++ b/app/assets/vendor/jquery-ui/datepicker/images/ui-icons_555555_256x240.png @@ -0,0 +1,993 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + jquery-ui/ui-icons_555555_256x240.png at master · jquery/jquery-ui + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Skip to content +
+ + + + + + + + + + + +
+ +
+ +
+ +
+ + + +
+
+
+ + + + + + + + + + + +
+
+ +
    + + + +
  • +
    + +
    + + + Watch + + +
    + Notifications +
    +
    + + + + + + + +
    +
    +
    + +
    +
  • + +
  • +
    +
    + + +
    +
    + + +
    + +
  • + +
  • +
    + + Fork + +
    + +

    Fork jquery-ui

    +
    +
    + +
    +

    If this dialog fails to load, you can visit the fork page directly.

    +
    +
    +
    +
    + + +
  • +
+ +

+ + /jquery-ui + +

+ +
+ + + + +
+
+
+ + + + + + + + Permalink + + + + + +
+ +
+ + Branch: + master + + + + + + + +
+ +
+ + Find file + + + Copy path + +
+ +
+ + + +
+ + +
+ +
+ + + 5 contributors + + +
+ +

Users who have contributed to this file

+
+ + + +
+
+ + @scottgonzalez + + @peritpatrio + + @jaspermdegroot + + @joliss + + @PeterDaveHello + + +
+
+ + + + + +
+ +
+ +
+ 3.2 KB +
+ +
+ + + + +
+ +
+ +
+
+
+ + + +
+
+ ui-icons_555555_256x240.png +
+
+ +
+ + + +
+ + +
+ + +
+
+ + + +
+ +
+ +
+
+ + +
+ + + + + + +
+ + + You can’t perform that action at this time. +
+ + + + + + + + + +
+ + You signed in with another tab or window. Reload to refresh your session. + You signed out in another tab or window. Reload to refresh your session. +
+ + + + +
+ + + + diff --git a/app/assets/vendor/jquery-ui/datepicker/images/ui-icons_777620_256x240.png b/app/assets/vendor/jquery-ui/datepicker/images/ui-icons_777620_256x240.png new file mode 100644 index 0000000..1ba9301 --- /dev/null +++ b/app/assets/vendor/jquery-ui/datepicker/images/ui-icons_777620_256x240.png @@ -0,0 +1,993 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + jquery-ui/ui-icons_777620_256x240.png at master · jquery/jquery-ui + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Skip to content +
+ + + + + + + + + + + +
+ +
+ +
+ +
+ + + +
+
+
+ + + + + + + + + + + +
+
+ +
    + + + +
  • +
    + +
    + + + Watch + + +
    + Notifications +
    +
    + + + + + + + +
    +
    +
    + +
    +
  • + +
  • +
    +
    + + +
    +
    + + +
    + +
  • + +
  • +
    + + Fork + +
    + +

    Fork jquery-ui

    +
    +
    + +
    +

    If this dialog fails to load, you can visit the fork page directly.

    +
    +
    +
    +
    + + +
  • +
+ +

+ + /jquery-ui + +

+ +
+ + + + +
+
+
+ + + + + + + + Permalink + + + + + +
+ +
+ + Branch: + master + + + + + + + +
+ +
+ + Find file + + + Copy path + +
+ +
+ + + +
+ + +
+ +
+ + + 5 contributors + + +
+ +

Users who have contributed to this file

+
+ + + +
+
+ + @scottgonzalez + + @peritpatrio + + @jaspermdegroot + + @joliss + + @PeterDaveHello + + +
+
+ + + + + +
+ +
+ +
+ 3.19 KB +
+ +
+ + + + +
+ +
+ +
+
+
+ + + +
+
+ ui-icons_777620_256x240.png +
+
+ +
+ + + +
+ + +
+ + +
+
+ + + +
+ +
+ +
+
+ + +
+ + + + + + +
+ + + You can’t perform that action at this time. +
+ + + + + + + + + +
+ + You signed in with another tab or window. Reload to refresh your session. + You signed out in another tab or window. Reload to refresh your session. +
+ + + + +
+ + + + diff --git a/app/assets/vendor/jquery-ui/datepicker/images/ui-icons_777777_256x240.png b/app/assets/vendor/jquery-ui/datepicker/images/ui-icons_777777_256x240.png new file mode 100644 index 0000000..8d34c9a --- /dev/null +++ b/app/assets/vendor/jquery-ui/datepicker/images/ui-icons_777777_256x240.png @@ -0,0 +1,993 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + jquery-ui/ui-icons_777777_256x240.png at master · jquery/jquery-ui + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Skip to content +
+ + + + + + + + + + + +
+ +
+ +
+ +
+ + + +
+
+
+ + + + + + + + + + + +
+
+ +
    + + + +
  • +
    + +
    + + + Watch + + +
    + Notifications +
    +
    + + + + + + + +
    +
    +
    + +
    +
  • + +
  • +
    +
    + + +
    +
    + + +
    + +
  • + +
  • +
    + + Fork + +
    + +

    Fork jquery-ui

    +
    +
    + +
    +

    If this dialog fails to load, you can visit the fork page directly.

    +
    +
    +
    +
    + + +
  • +
+ +

+ + /jquery-ui + +

+ +
+ + + + +
+
+
+ + + + + + + + Permalink + + + + + +
+ +
+ + Branch: + master + + + + + + + +
+ +
+ + Find file + + + Copy path + +
+ +
+ + + +
+ + +
+ +
+ + + 5 contributors + + +
+ +

Users who have contributed to this file

+
+ + + +
+
+ + @scottgonzalez + + @peritpatrio + + @jaspermdegroot + + @joliss + + @PeterDaveHello + + +
+
+ + + + + +
+ +
+ +
+ 3.19 KB +
+ +
+ + + + +
+ +
+ +
+
+
+ + + +
+
+ ui-icons_777777_256x240.png +
+
+ +
+ + + +
+ + +
+ + +
+
+ + + +
+ +
+ +
+
+ + +
+ + + + + + +
+ + + You can’t perform that action at this time. +
+ + + + + + + + + +
+ + You signed in with another tab or window. Reload to refresh your session. + You signed out in another tab or window. Reload to refresh your session. +
+ + + + +
+ + + + diff --git a/app/assets/vendor/jquery-ui/datepicker/images/ui-icons_FFF_256x240.png b/app/assets/vendor/jquery-ui/datepicker/images/ui-icons_FFF_256x240.png new file mode 100644 index 0000000..60f8fb2 --- /dev/null +++ b/app/assets/vendor/jquery-ui/datepicker/images/ui-icons_FFF_256x240.png @@ -0,0 +1,993 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + jquery-ui/ui-icons_ffffff_256x240.png at master · jquery/jquery-ui + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Skip to content +
+ + + + + + + + + + + +
+ +
+ +
+ +
+ + + +
+
+
+ + + + + + + + + + + +
+
+ +
    + + + +
  • +
    + +
    + + + Watch + + +
    + Notifications +
    +
    + + + + + + + +
    +
    +
    + +
    +
  • + +
  • +
    +
    + + +
    +
    + + +
    + +
  • + +
  • +
    + + Fork + +
    + +

    Fork jquery-ui

    +
    +
    + +
    +

    If this dialog fails to load, you can visit the fork page directly.

    +
    +
    +
    +
    + + +
  • +
+ +

+ + /jquery-ui + +

+ +
+ + + + +
+
+
+ + + + + + + + Permalink + + + + + +
+ +
+ + Branch: + master + + + + + + + +
+ +
+ + Find file + + + Copy path + +
+ +
+ + + +
+ + +
+ +
+ + + 5 contributors + + +
+ +

Users who have contributed to this file

+
+ + + +
+
+ + @scottgonzalez + + @peritpatrio + + @jaspermdegroot + + @joliss + + @PeterDaveHello + + +
+
+ + + + + +
+ +
+ +
+ 3.19 KB +
+ +
+ + + + +
+ +
+ +
+
+
+ + + +
+
+ ui-icons_ffffff_256x240.png +
+
+ +
+ + + +
+ + +
+ + +
+
+ + + +
+ +
+ +
+
+ + +
+ + + + + + +
+ + + You can’t perform that action at this time. +
+ + + + + + + + + +
+ + You signed in with another tab or window. Reload to refresh your session. + You signed out in another tab or window. Reload to refresh your session. +
+ + + + +
+ + + + diff --git a/app/assets/vendor/jquery-ui/datepicker/images/ui-icons_cc0000_256x240.png b/app/assets/vendor/jquery-ui/datepicker/images/ui-icons_cc0000_256x240.png new file mode 100644 index 0000000..4afd18e --- /dev/null +++ b/app/assets/vendor/jquery-ui/datepicker/images/ui-icons_cc0000_256x240.png @@ -0,0 +1,993 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + jquery-ui/ui-icons_cc0000_256x240.png at master · jquery/jquery-ui + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Skip to content +
+ + + + + + + + + + + +
+ +
+ +
+ +
+ + + +
+
+
+ + + + + + + + + + + +
+
+ +
    + + + +
  • +
    + +
    + + + Watch + + +
    + Notifications +
    +
    + + + + + + + +
    +
    +
    + +
    +
  • + +
  • +
    +
    + + +
    +
    + + +
    + +
  • + +
  • +
    + + Fork + +
    + +

    Fork jquery-ui

    +
    +
    + +
    +

    If this dialog fails to load, you can visit the fork page directly.

    +
    +
    +
    +
    + + +
  • +
+ +

+ + /jquery-ui + +

+ +
+ + + + +
+
+
+ + + + + + + + Permalink + + + + + +
+ +
+ + Branch: + master + + + + + + + +
+ +
+ + Find file + + + Copy path + +
+ +
+ + + +
+ + +
+ +
+ + + 5 contributors + + +
+ +

Users who have contributed to this file

+
+ + + +
+
+ + @scottgonzalez + + @peritpatrio + + @jaspermdegroot + + @joliss + + @PeterDaveHello + + +
+
+ + + + + +
+ +
+ +
+ 3.19 KB +
+ +
+ + + + +
+ +
+ +
+
+
+ + + +
+
+ ui-icons_cc0000_256x240.png +
+
+ +
+ + + +
+ + +
+ + +
+
+ + + +
+ +
+ +
+
+ + +
+ + + + + + +
+ + + You can’t perform that action at this time. +
+ + + + + + + + + +
+ + You signed in with another tab or window. Reload to refresh your session. + You signed out in another tab or window. Reload to refresh your session. +
+ + + + +
+ + + + diff --git a/app/controllers/answers_controller.rb b/app/controllers/answers_controller.rb index e7afbfb..75aca78 100644 --- a/app/controllers/answers_controller.rb +++ b/app/controllers/answers_controller.rb @@ -144,6 +144,10 @@ if !permitted[:id].present? permitted.delete(:id) end + # If no question options has been chosen. + if params[:answer][:question_option_ids].nil? + permitted[:question_option_ids] = [] + end permitted end diff --git a/app/controllers/api/v0/statistics_controller.rb b/app/controllers/api/v0/statistics_controller.rb index 5d387fb..c06ef51 100644 --- a/app/controllers/api/v0/statistics_controller.rb +++ b/app/controllers/api/v0/statistics_controller.rb @@ -28,6 +28,9 @@ r[k] = scoped.where(created_at: dates_to_range(v)).count end + # Reverse hash r, so dates in ascending order + r = Hash[r.to_a.reverse] + respond_to do |format| format.json { render(json: r.to_json) } format.csv { @@ -66,6 +69,9 @@ r[k] = scoped.where(created_at: dates_to_range(v)).count end + # Reverse hash r, so dates in ascending order + r = Hash[r.to_a.reverse] + respond_to do |format| format.json { render(json: r.to_json) } format.csv { @@ -104,6 +110,9 @@ r[k] = scoped.where(created_at: dates_to_range(v)).count end + # Reverse hash r, so dates in ascending order + r = Hash[r.to_a.reverse] + respond_to do |format| format.json { render(json: r.to_json) } format.csv { diff --git a/app/controllers/notes_controller.rb b/app/controllers/notes_controller.rb index 0ac5285..ba2fc07 100644 --- a/app/controllers/notes_controller.rb +++ b/app/controllers/notes_controller.rb @@ -43,7 +43,7 @@ plan = answer.plan owner = plan.owner deliver_if(recipients: owner, key: "users.new_comment") do |r| - UserMailer.new_comment(current_user, plan).deliver_now() + UserMailer.new_comment(current_user, plan, answer).deliver_now() end @notice = success_message(@note, _("created")) render(json: { diff --git a/app/controllers/org_admin/plans_controller.rb b/app/controllers/org_admin/plans_controller.rb index 1112fe0..7788ad1 100644 --- a/app/controllers/org_admin/plans_controller.rb +++ b/app/controllers/org_admin/plans_controller.rb @@ -12,7 +12,7 @@ feedback_ids = Role.where(user_id: current_user.id).reviewer.pluck(:plan_id).uniq @feedback_plans = Plan.where(id: feedback_ids) - @plans = current_user.org.plans + @plans = current_user.org.plans.page(1) end # GET org_admin/plans/:id/feedback_complete diff --git a/app/controllers/org_admin/templates_controller.rb b/app/controllers/org_admin/templates_controller.rb index ea57ead..cee3329 100644 --- a/app/controllers/org_admin/templates_controller.rb +++ b/app/controllers/org_admin/templates_controller.rb @@ -20,7 +20,7 @@ @orgs = Org.all @title = _("All Templates") - @templates = templates.includes(:org) + @templates = templates.includes(:org).page(1) @query_params = { sort_field: "templates.title", sort_direction: "asc" } @all_count = templates.length @published_count = published.present? ? published : 0 @@ -47,7 +47,7 @@ else _("Own Templates") end - @templates = templates + @templates = templates.page(1) @query_params = { sort_field: "templates.title", sort_direction: "asc" } @all_count = templates.length @published_count = published.present? ? published : 0 diff --git a/app/controllers/paginable/guidance_groups_controller.rb b/app/controllers/paginable/guidance_groups_controller.rb index 4605ffe..4cd3893 100644 --- a/app/controllers/paginable/guidance_groups_controller.rb +++ b/app/controllers/paginable/guidance_groups_controller.rb @@ -7,8 +7,11 @@ # /paginable/guidance_groups/index/:page def index authorize(Guidance) - paginable_renderise(partial: "index", - scope: GuidanceGroup.by_org(current_user.org)) + paginable_renderise( + partial: "index", + scope: GuidanceGroup.by_org(current_user.org), + query_params: { sort_field: "guidance_groups.name", sort_direction: :asc } + ) end end diff --git a/app/controllers/paginable/guidances_controller.rb b/app/controllers/paginable/guidances_controller.rb index 4ad8492..efec2eb 100644 --- a/app/controllers/paginable/guidances_controller.rb +++ b/app/controllers/paginable/guidances_controller.rb @@ -7,9 +7,12 @@ # /paginable/guidances/index/:page def index authorize(Guidance) - paginable_renderise(partial: "index", + paginable_renderise( + partial: "index", scope: Guidance.by_org(current_user.org) - .includes(:guidance_group, :themes)) + .includes(:guidance_group, :themes), + query_params: { sort_field: "guidances.text", sort_direction: :asc } + ) end end diff --git a/app/controllers/paginable/orgs_controller.rb b/app/controllers/paginable/orgs_controller.rb index 17c8e26..b561930 100644 --- a/app/controllers/paginable/orgs_controller.rb +++ b/app/controllers/paginable/orgs_controller.rb @@ -9,7 +9,7 @@ authorize(Org) paginable_renderise( partial: "index", - scope: Org.includes(:templates, :users), + scope: Org.with_template_and_user_counts, query_params: { sort_field: "orgs.name", sort_direction: :asc }) end diff --git a/app/controllers/paginable/plans_controller.rb b/app/controllers/paginable/plans_controller.rb index 515a5fe..721d25c 100644 --- a/app/controllers/paginable/plans_controller.rb +++ b/app/controllers/paginable/plans_controller.rb @@ -11,7 +11,8 @@ end paginable_renderise( partial: "privately_visible", - scope: Plan.active(current_user) + scope: Plan.active(current_user), + query_params: { sort_field: 'plans.updated_at', sort_direction: :desc } ) end @@ -22,7 +23,8 @@ end paginable_renderise( partial: "organisationally_or_publicly_visible", - scope: Plan.organisationally_or_publicly_visible(current_user) + scope: Plan.organisationally_or_publicly_visible(current_user), + query_params: { sort_field: 'plans.updated_at', sort_direction: :desc } ) end @@ -30,7 +32,8 @@ def publicly_visible paginable_renderise( partial: "publicly_visible", - scope: Plan.publicly_visible + scope: Plan.publicly_visible.includes(:template), + query_params: { sort_field: 'plans.updated_at', sort_direction: :desc } ) end @@ -41,7 +44,8 @@ end paginable_renderise( partial: "org_admin", - scope: current_user.org.plans + scope: current_user.org.plans, + query_params: { sort_field: 'plans.updated_at', sort_direction: :desc } ) end diff --git a/app/controllers/paginable/templates_controller.rb b/app/controllers/paginable/templates_controller.rb index 086b41a..988432a 100644 --- a/app/controllers/paginable/templates_controller.rb +++ b/app/controllers/paginable/templates_controller.rb @@ -2,6 +2,7 @@ class Paginable::TemplatesController < ApplicationController + include CustomizableTemplateLinkHelper include Paginable # TODO: Clean up this code for Rubocop @@ -23,6 +24,7 @@ paginable_renderise( partial: "index", scope: templates.includes(:org), + query_params: { sort_field: 'templates.title', sort_direction: :asc }, locals: { action: "index" } ) end @@ -44,6 +46,7 @@ paginable_renderise( partial: "organisational", scope: templates, + query_params: { sort_field: 'templates.title', sort_direction: :asc }, locals: { action: "organisational" } ) end @@ -67,6 +70,7 @@ paginable_renderise( partial: "customisable", scope: templates.joins(:org).includes(:org), + query_params: { sort_field: 'templates.title', sort_direction: :asc }, locals: { action: "customisable", customizations: customizations } ) end @@ -84,7 +88,8 @@ scope: Template.joins(:org) .includes(:org) .where(id: templates.uniq.flatten) - .published + .published, + query_params: { sort_field: 'templates.title', sort_direction: :asc } ) end @@ -98,6 +103,7 @@ paginable_renderise( partial: "history", scope: @templates, + query_params: { sort_field: 'templates.title', sort_direction: :asc }, locals: { current: @templates.maximum(:version) } ) end diff --git a/app/controllers/paginable/users_controller.rb b/app/controllers/paginable/users_controller.rb index 02f2835..5e8b678 100644 --- a/app/controllers/paginable/users_controller.rb +++ b/app/controllers/paginable/users_controller.rb @@ -15,6 +15,7 @@ paginable_renderise( partial: "index", scope: scope, + query_params: { sort_field: 'users.surname', sort_direction: :asc }, view_all: !current_user.can_super_admin? ) end diff --git a/app/controllers/plan_exports_controller.rb b/app/controllers/plan_exports_controller.rb index 6018de0..4dd2a62 100644 --- a/app/controllers/plan_exports_controller.rb +++ b/app/controllers/plan_exports_controller.rb @@ -66,8 +66,10 @@ end def show_docx + # Using and optional locals_assign export_format render docx: "#{file_name}.docx", - content: render_to_string(partial: "shared/export/plan") + content: render_to_string(partial: "shared/export/plan", + locals: { export_format: "docx" }) end def show_pdf @@ -80,7 +82,8 @@ }, font_size: 8, spacing: (Integer(@formatting[:margin][:bottom]) / 2) - 4, - right: "[page] of [topage]" + right: "[page] of [topage]", + encoding: "utf8" } end diff --git a/app/controllers/public_pages_controller.rb b/app/controllers/public_pages_controller.rb index 17ab192..b4b96a1 100644 --- a/app/controllers/public_pages_controller.rb +++ b/app/controllers/public_pages_controller.rb @@ -59,7 +59,8 @@ }, font_size: 8, spacing: (@formatting[:margin][:bottom] / 2) - 4, - right: "[page] of [topage]" + right: "[page] of [topage]", + encoding: "utf8" } # rubocop:enable LineLength end @@ -74,7 +75,7 @@ # GET /plans_index # ------------------------------------------------------------------------------------ def plan_index - @plans = Plan.publicly_visible.page(1) + @plans = Plan.publicly_visible.includes(:template).page(1) render "plan_index", locals: { query_params: { sort_field: "plans.updated_at", diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index 81f6c69..3defde5 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -189,6 +189,9 @@ successfully_updated = false else successfully_updated = current_user.update_with_password(password_update) + if !successfully_updated + message = _("Save unsuccessful. That email address is already registered. You must enter a unique email address.") + end end else # This case is never reached since this method when called with diff --git a/app/controllers/super_admin/orgs_controller.rb b/app/controllers/super_admin/orgs_controller.rb index c6fcd5b..5bff645 100644 --- a/app/controllers/super_admin/orgs_controller.rb +++ b/app/controllers/super_admin/orgs_controller.rb @@ -8,7 +8,9 @@ def index authorize Org - render "index", locals: { orgs: Org.includes(:templates, :users) } + render "index", locals: { + orgs: Org.with_template_and_user_counts.page(1) + } end def new diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 08299de..6cde1b8 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -17,12 +17,12 @@ respond_to do |format| format.html do if current_user.can_super_admin? - @users = User.page(1) + @users = User.includes(:roles).page(1) else - @users = current_user.org.users.page(1) + @users = current_user.org.users.includes(:roles).page(1) end end - + format.csv do send_data User.to_csv(current_user.org.users.order(:surname)), filename: "users-accounts-#{Date.today}.csv" diff --git a/app/helpers/customizable_template_link_helper.rb b/app/helpers/customizable_template_link_helper.rb new file mode 100644 index 0000000..aad7542 --- /dev/null +++ b/app/helpers/customizable_template_link_helper.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +module CustomizableTemplateLinkHelper + + # Link to the appropriate customizable template. + # Default link name set if name not set which can be overwritten. + def link_to_customizable_template(name = nil, customization, template) + if customization.present? + if customization.created_at < template.created_at + name = name.blank? ? _("Transfer customisation") : name + link_to name, + org_admin_template_customization_transfers_path(customization.id), + data: { method: "post" } + else + name = name.blank? ? _("Edit customisation") : name + link_to name, org_admin_template_path(id: customization.id) + end + else + name = name.blank? ? _("Customise") : name + link_to name, + org_admin_template_customizations_path(template.id), + "data-method": "post" + end + end + +end diff --git a/app/helpers/exports_helper.rb b/app/helpers/exports_helper.rb index d60364b..5b9c416 100644 --- a/app/helpers/exports_helper.rb +++ b/app/helpers/exports_helper.rb @@ -3,18 +3,18 @@ module ExportsHelper PAGE_MARGINS = { - top: '5', + top: "5", bottom: "10", left: "12", right: "12", } def font_face - @formatting[:font_face].presence || 'Arial, Helvetica, Sans-Serif' + @formatting[:font_face].presence || "Arial, Helvetica, Sans-Serif" end def font_size - @formatting[:font_size].presence || '12' + @formatting[:font_size].presence || "12" end def margin_top @@ -36,7 +36,7 @@ def plan_attribution(attribution) attribution = Array(attribution) prefix = attribution.many? ? _("Creators:") : _("Creator:") - "#{prefix} #{attribution.join(', ')}" + "#{prefix} #{attribution.join(', ')}" end private @@ -49,4 +49,5 @@ @formatting.dig(:margin, side).presence || PAGE_MARGINS[side] end end -end \ No newline at end of file + +end diff --git a/app/helpers/feedbacks_helper.rb b/app/helpers/feedbacks_helper.rb index 15fca1b..713b192 100644 --- a/app/helpers/feedbacks_helper.rb +++ b/app/helpers/feedbacks_helper.rb @@ -1,18 +1,24 @@ +# frozen_string_literal: true + module FeedbacksHelper + def feedback_confirmation_default_subject - _('%{application_name}: Your plan has been submitted for feedback') + _("%{application_name}: Your plan has been submitted for feedback") end def feedback_confirmation_default_message - _('

Hello %{user_name}.

'\ - '

Your plan "%{plan_name}" has been submitted for feedback from an administrator at your organisation. '\ - 'If you have questions pertaining to this action, please contact us at %{organisation_email}.

') + _("

Hello %{user_name}.

"\ + "

Your plan \"%{plan_name}\" has been submitted for feedback from an + administrator at your organisation. "\ + "If you have questions pertaining to this action, please contact us + at %{organisation_email}.

") end def feedback_constant_to_text(text, user, plan, org) - _("#{text}") % {application_name: Rails.configuration.branding[:application][:name], - user_name: user.name, + _("#{text}") % { application_name: Rails.configuration.branding[:application][:name], + user_name: user.name(false), plan_name: plan.title, - organisation_email: org.contact_email} + organisation_email: org.contact_email } end + end diff --git a/app/helpers/orgs_helper.rb b/app/helpers/orgs_helper.rb index 91b503d..c90d10a 100644 --- a/app/helpers/orgs_helper.rb +++ b/app/helpers/orgs_helper.rb @@ -2,18 +2,18 @@ module OrgsHelper - DEFAULT_EMAIL = '%{organisation_email}' + EMAIL_PLACEHOLDER = "[Organisation Contact Email Placeholder]" - # Tooltip string for Org feedback form. + # Sample message for Org feedback form. # # org - The current Org we're updating feedback form for. # # Returns String - def tooltip_for_org_feedback_form(org) - email = org.contact_email.presence || DEFAULT_EMAIL - _("SAMPLE MESSAGE: A data librarian from %{org_name} will respond to your request within 48 + def sample_message_for_org_feedback_form(org) + email = org.contact_email || EMAIL_PLACEHOLDER + _("

A data librarian from %{org_name} will respond to your request within 48 hours. If you have questions pertaining to this action please contact us - at %{organisation_email}.") % { + at %{organisation_email}.

") % { organisation_email: email, org_name: org.name } @@ -22,7 +22,7 @@ # The preferred logo url for the current configuration. If DRAGONFLY_AWS is true, return # the remote_url, otherwise return the url def logo_url_for_org(org) - if ENV['DRAGONFLY_AWS'] == "true" + if ENV["DRAGONFLY_AWS"] == "true" org.logo.remote_url else org.logo.url diff --git a/app/javascript/utils/datePicker.js b/app/javascript/utils/datePicker.js new file mode 100644 index 0000000..ba746bc --- /dev/null +++ b/app/javascript/utils/datePicker.js @@ -0,0 +1,16 @@ +import 'jquery-ui/ui/widgets/datepicker'; + +/* + * Date picker polyfill: + * Wire up the JQuery UI DatePicker if the browser does not support the HTML5 date + */ +export default () => { + if ($('[type="date"]').prop('type') !== 'date') { + $('[type="date"]').datepicker({ + dateFormat: 'yy-mm-dd', + constrainInput: true, + navigationAsDateFormat: true, + goToCurrent: true, + }); + } +}; diff --git a/app/javascript/utils/panelHeading.js b/app/javascript/utils/panelHeading.js index 670c048..534cad0 100644 --- a/app/javascript/utils/panelHeading.js +++ b/app/javascript/utils/panelHeading.js @@ -1,5 +1,5 @@ $(() => { - $('.heading-button').on('click', (e) => { + $('body').on('click', '.heading-button', (e) => { $(e.currentTarget) .find('i.fa-plus, i.fa-minus') .toggleClass('fa-plus') diff --git a/app/javascript/views/answers/edit.js b/app/javascript/views/answers/edit.js index a2df62d..cc1ddbd 100644 --- a/app/javascript/views/answers/edit.js +++ b/app/javascript/views/answers/edit.js @@ -5,6 +5,7 @@ } from '../../utils/isType'; import { Tinymce } from '../../utils/tinymce'; import debounce from '../../utils/debounce'; +import datePicker from '../../utils/datePicker'; import TimeagoFactory from '../../utils/timeagoFactory'; $(() => { @@ -176,4 +177,6 @@ editor.setMode('readonly'); }); } + + datePicker(); }); diff --git a/app/javascript/views/usage/index.js b/app/javascript/views/usage/index.js index edf7949..0873b2b 100644 --- a/app/javascript/views/usage/index.js +++ b/app/javascript/views/usage/index.js @@ -25,6 +25,27 @@ return rangeDates; }; + + // Register a plugin for displaying a message for no data + Chart.plugins.register({ + afterDraw: (chart) => { + if (chart.data.datasets.length === 0) { + const { ctx, width, height } = { + ctx: chart.chart.ctx, + width: chart.chart.width, + height: chart.chart.height, + }; + chart.clear(); + ctx.save(); + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + ctx.font = '25px bold'; + ctx.fillText('No data to display for selected time period', width / 2, height / 2); + ctx.restore(); + } + }, + }); + const createChart = ({ selector, data, appendTolabel = '' } = {}) => { new Chart($(selector), { // eslint-disable-line no-new type: 'bar', @@ -161,15 +182,21 @@ }; const yAxisLabel = date => moment(date).format('MMM-YY'); - const drawHorizontalBar = (canvasSelector, data) => { + const drawHorizontalBar = (canvasSelector, data, aspectRatio = 1) => { const chart = new Chart(canvasSelector, { // eslint-disable-line no-new type: 'horizontalBar', data, options: { + responsive: true, + maintainAspectRatio: true, + aspectRatio, scales: { xAxes: [{ - ticks: { beginAtZero: true }, - precision: 1, + ticks: { beginAtZero: true, stepSize: 10 }, + stacked: true, + }], + yAxes: [{ + stacked: true, }], }, }, @@ -179,7 +206,6 @@ const buildData = (data) => { const labels = data.map(current => yAxisLabel(current.date)); - const datasetsMap = data.reduce((acc, statCreatedPlan) => { statCreatedPlan.by_template.forEach((template) => { if (!acc[template.name]) { @@ -189,13 +215,32 @@ }); return acc; }, {}); - - const datasets = Object.keys(datasetsMap).map(key => datasetsMap[key]); - + // const datasets = Object.keys(datasetsMap).map(key => datasetsMap[key]); + const compare = (a, b) => { + const aIndex = labels.indexOf(a.y); + const bIndex = labels.indexOf(b.y); + if (aIndex > bIndex) return 1; + if (aIndex < bIndex) return -1; + return 0; + }; + const datasets = Object.keys(datasetsMap).map((key) => { + const datasetByKey = datasetsMap[key]; + const availableMonths = datasetByKey.data.reduce((acc, value) => { + // month has y as key + acc.push(value.y); + return acc; + }, []); + // Find missing months in data + const missingMonths = labels.filter(month => !availableMonths.includes(month)); + // Add data for missing months with x value set to 0 + missingMonths.forEach(month => datasetByKey.data.push({ x: 0, y: month })); + datasetByKey.data = datasetByKey.data.sort(compare); + return datasetByKey; + }); return { labels, datasets }; }; - const fetch = (lastDayOfMonth) => { + const fetch = (lastDayOfMonth, aspectRatio = 1) => { const baseUrl = $('select[name="monthly_plans_by_template"]').attr('data-url'); $.ajax({ url: `${baseUrl}?start_date=${lastDayOfMonth}`, @@ -205,14 +250,60 @@ if (drawnChart) { drawnChart.destroy(); } - drawnChart = drawHorizontalBar($(canvasSelector), chartData); + drawnChart = drawHorizontalBar($(canvasSelector), chartData, aspectRatio); }); }; + // Set Aspect Rate (width of X-axis/height of Y-axis) based on + // choice of selectedLastDayOfMonth in Time picker string value. Note aspect + const getAspectRatio = (selectedLastDayOfMonth) => { + let aspectRatio; + try { + const now = new Date(); + const dateOfSelectedMonth = new Date(selectedLastDayOfMonth); + const diff = new Date(now.getTime() - dateOfSelectedMonth.getTime()); + const diffInMonths = diff.getUTCMonth(); + + switch (diffInMonths) { + case 0: + case 1: + aspectRatio = 5; + break; + case 2: + case 3: + aspectRatio = 3.5; + break; + case 4: + case 5: + case 6: + aspectRatio = 2.5; + break; + case 7: + case 8: + case 9: + case 10: + aspectRatio = 2; + break; + case 11: + case 12: + aspectRatio = 1.5; + break; + default: + aspectRatio = 0.9; + } + } catch (e) { + aspectRatio = 0.9; + } + + return aspectRatio; + }; + const handler = () => { const selectedMonth = jQuerySelectorSelect.val(); + if (selectedMonth) { - fetch(selectedMonth); + const aspectRatio = getAspectRatio(selectedMonth); + fetch(selectedMonth, aspectRatio); } }; diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb index 525773b..0e73fe9 100644 --- a/app/mailers/user_mailer.rb +++ b/app/mailers/user_mailer.rb @@ -72,6 +72,7 @@ if recipient.active? FastGettext.with_locale FastGettext.default_locale do mail(to: recipient.email, + from: requestor.org.contact_email, subject: _("%{application_name}: Expert feedback has been provided for %{plan_title}") % {application_name: Rails.configuration.branding[:application][:name], plan_title: @plan.title}) end end @@ -110,12 +111,14 @@ # commenter - User who wrote the comment # plan - Plan for which the comment is associated to - def new_comment(commenter, plan) + # answer - Answer commented on + def new_comment(commenter, plan, answer) if commenter.is_a?(User) && plan.is_a?(Plan) owner = plan.owner if owner.present? && owner.active? @commenter = commenter @plan = plan + @answer = answer FastGettext.with_locale FastGettext.default_locale do mail(to: plan.owner.email, subject: _('%{tool_name}: A new comment was added to %{plan_title}') %{ :tool_name => Rails.configuration.branding[:application][:name], :plan_title => plan.title }) diff --git a/app/models/concerns/exportable_plan.rb b/app/models/concerns/exportable_plan.rb index 7a36da2..546ee0e 100644 --- a/app/models/concerns/exportable_plan.rb +++ b/app/models/concerns/exportable_plan.rb @@ -149,10 +149,12 @@ if answer.present? || (answer.blank? && unanswered) answer_text = answer.present? ? answer.text : (unanswered ? _("Not Answered") : "") - if answer.present? && answer.question_options.any? - answer_text = answer.question_options.pluck(:text).join(", ") + if answer.present? && answer.is_valid? && answer.question_options.any? + answer_text = answer.question_options.pluck(:text).join(", ") + + " " + answer_text end end + single_line_answer_for_csv = sanitize_text(answer_text).gsub(/\r|\n/, " ") flds = (hash[:phases].many? ? [phase[:title]] : []) if headings if question[:text].is_a? String @@ -163,10 +165,9 @@ question[:text][0]) end flds << [ section[:title], sanitize_text(question_text), - sanitize_text(answer_text) - ] + single_line_answer_for_csv ] else - flds << [ sanitize_text(answer_text) ] + flds << [ single_line_answer_for_csv ] end csv << flds.flatten end diff --git a/app/models/guidance.rb b/app/models/guidance.rb index f0ae5da..37c294a 100644 --- a/app/models/guidance.rb +++ b/app/models/guidance.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Guidance provides information from organisations to Users, helping them when # answering questions. (e.g. "Here's how to think about your data # protection responsibilities...") @@ -24,12 +26,15 @@ # [+Project:+] DMPRoadmap # [+Description:+] -# This class keeps the information organisations enter to support users when answering questions. -# It always belongs to a guidance group class and it can be linked directly to a question or through one or more themes +# This class keeps the information organisations enter to support users +# when answering questions. +# It always belongs to a guidance group class and it can be linked directly +# to a question or through one or more themes # [+Created:+] 07/07/2014 # [+Copyright:+] Digital Curation Centre and California Digital Library class Guidance < ActiveRecord::Base + include GlobalHelpers include ValidationMessages include ValidationValues @@ -52,7 +57,7 @@ validates :guidance_group, presence: { message: PRESENCE_MESSAGE } validates :published, inclusion: { message: INCLUSION_MESSAGE, - in: BOOLEAN_VALUES} + in: BOOLEAN_VALUES } validates :themes, presence: { message: PRESENCE_MESSAGE }, if: :published? @@ -64,7 +69,8 @@ scope :search, -> (term) { search_pattern = "%#{term}%" joins(:guidance_group) - .where("guidances.text LIKE ? OR guidance_groups.name LIKE ?", + .where("lower(guidances.text) LIKE lower(?) OR " + + "lower(guidance_groups.name) LIKE lower(?)", search_pattern, search_pattern) } @@ -120,10 +126,10 @@ # Returns Array def self.all_viewable(user) managing_groups = Org.includes(guidance_groups: :guidances) - .managing_orgs.collect{|o| o.guidance_groups} + .managing_orgs.collect { |o| o.guidance_groups } # find all groups owned by a Funder organisation funder_groups = Org.includes(guidance_groups: :guidances) - .funder.collect{|org| org.guidance_groups} + .funder.collect { |org| org.guidance_groups } # find all groups owned by any of the user's organisations organisation_groups = user.org.guidance_groups @@ -152,4 +158,5 @@ end return false end + end diff --git a/app/models/guidance_group.rb b/app/models/guidance_group.rb index 3a63430..bf079e4 100644 --- a/app/models/guidance_group.rb +++ b/app/models/guidance_group.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Set of Guidances that pertain to a certain category of Users (e.g. Maths # department, vs Biology department) # @@ -23,6 +25,7 @@ # class GuidanceGroup < ActiveRecord::Base + include GlobalHelpers include ValidationValues include ValidationMessages @@ -62,7 +65,7 @@ scope :search, lambda { |term| search_pattern = "%#{term}%" - where("name LIKE ?", search_pattern) + where("lower(name) LIKE lower(?)", search_pattern) } scope :published, -> { where(published: true) } @@ -125,4 +128,5 @@ all_viewable_groups = all_viewable_groups.flatten.uniq all_viewable_groups end + end diff --git a/app/models/org.rb b/app/models/org.rb index d54b1df..ade85ba 100644 --- a/app/models/org.rb +++ b/app/models/org.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # == Schema Information # # Table name: orgs @@ -29,6 +31,7 @@ # class Org < ActiveRecord::Base + include ValidationMessages include ValidationValues include FeedbacksHelper @@ -39,8 +42,10 @@ LOGO_FORMATS = %w[jpeg png gif jpg bmp].freeze - # Stores links as an JSON object: { org: [{"link":"www.example.com","text":"foo"}, ...] } - # The links are validated against custom validator allocated at validators/template_links_validator.rb + # Stores links as an JSON object: + # { org: [{"link":"www.example.com","text":"foo"}, ...] } + # The links are validated against custom validator allocated at + # validators/template_links_validator.rb serialize :links, JSON @@ -60,7 +65,9 @@ has_many :annotations - has_and_belongs_to_many :token_permission_types, join_table: "org_token_permissions", unique: true + has_and_belongs_to_many :token_permission_types, + join_table: "org_token_permissions", + unique: true has_many :org_identifiers @@ -81,10 +88,12 @@ validates :language, presence: { message: PRESENCE_MESSAGE } - validates :contact_name, presence: { message: PRESENCE_MESSAGE, if: :feedback_enabled } + validates :contact_name, presence: { message: PRESENCE_MESSAGE, + if: :feedback_enabled } validates :contact_email, email: { allow_nil: true }, - presence: { message: PRESENCE_MESSAGE, if: :feedback_enabled } + presence: { message: PRESENCE_MESSAGE, + if: :feedback_enabled } validates :org_type, presence: { message: PRESENCE_MESSAGE } @@ -98,9 +107,12 @@ if: :feedback_enabled } validates_property :format, of: :logo, in: LOGO_FORMATS, - message: _("must be one of the following formats: jpeg, jpg, png, gif, bmp") + message: _("must be one of the following formats: " + + "jpeg, jpg, png, gif, bmp") - validates_size_of :logo, maximum: 500.kilobytes, message: _("can't be larger than 500KB") + validates_size_of :logo, + maximum: 500.kilobytes, + message: _("can't be larger than 500KB") # allow validations for logo upload dragonfly_accessor :logo do @@ -116,7 +128,7 @@ 4 => :research_institute, 5 => :project, 6 => :school, - column: 'org_type' + column: "org_type" # Predefined queries for retrieving the managain organisation and funders scope :managing_orgs, -> do @@ -125,7 +137,19 @@ scope :search, -> (term) { search_pattern = "%#{term}%" - where("orgs.name LIKE ? OR orgs.contact_email LIKE ?", search_pattern, search_pattern) + where("lower(orgs.name) LIKE lower(?) OR " + + "lower(orgs.contact_email) LIKE lower(?)", + search_pattern, search_pattern) + } + + # Scope used in several controllers + scope :with_template_and_user_counts, -> { + joins("LEFT OUTER JOIN templates ON orgs.id = templates.org_id") + .joins("LEFT OUTER JOIN users ON orgs.id = users.org_id") + .group("orgs.id") + .select("orgs.*, + count(distinct templates.family_id) as template_count, + count(users.id) as user_count") } before_validation :set_default_feedback_email_subject @@ -164,7 +188,7 @@ ret << "Research Institute" if self.research_institute? ret << "Project" if self.project? ret << "School" if self.school? - return (ret.length > 0 ? ret.join(', ') : "None") + return (ret.length > 0 ? ret.join(", ") : "None") end def funder_only? @@ -201,7 +225,7 @@ def org_admins User.joins(:perms).where("users.org_id = ? AND perms.name IN (?)", self.id, - ['grant_permissions', 'modify_templates', 'modify_guidance', 'change_org_details']) + ["grant_permissions", "modify_templates", "modify_guidance", "change_org_details"]) end def plans @@ -213,7 +237,8 @@ end def grant_api!(token_permission_type) - self.token_permission_types << token_permission_type unless self.token_permission_types.include? token_permission_type + self.token_permission_types << token_permission_type unless + self.token_permission_types.include? token_permission_type end private @@ -224,7 +249,7 @@ def resize_image unless logo.nil? if logo.height != 100 - self.logo = logo.thumb('x100') # resize height and maintain aspect ratio + self.logo = logo.thumb("x100") # resize height and maintain aspect ratio end end end @@ -241,7 +266,7 @@ # Attempt to locate the file by name. If it exists update the uid logo = Dir.glob("#{data_store_path}/**/*#{self.logo_name}") if !logo.empty? - self.logo_uid = logo.first.gsub(data_store_path, '') + self.logo_uid = logo.first.gsub(data_store_path, "") else # Otherwise the logo is missing so clear it to prevent save failures self.logo = nil @@ -258,11 +283,12 @@ # creates a dfefault Guidance Group on create on the Org def create_guidance_group - GuidanceGroup.create!({ - name: abbreviation? ? self.abbreviation : self.name , + GuidanceGroup.create!( + name: abbreviation? ? self.abbreviation : self.name, org: self, optional_subset: false, published: false, - }) + ) end + end diff --git a/app/models/plan.rb b/app/models/plan.rb index bce3571..269b365 100644 --- a/app/models/plan.rb +++ b/app/models/plan.rb @@ -166,7 +166,7 @@ scope :search, lambda { |term| search_pattern = "%#{term}%" joins(:template) - .where("plans.title LIKE ? OR templates.title LIKE ?", + .where("lower(plans.title) LIKE lower(?) OR lower(templates.title) LIKE lower(?)", search_pattern, search_pattern) } @@ -317,9 +317,13 @@ if save! # Send an email confirmation to the owners and co-owners - deliver_if(recipients: owner_and_coowners, key: "users.feedback_provided") do |r| - UserMailer.feedback_complete(r, self, org_admin).deliver_now - end + deliver_if(recipients: owner_and_coowners, + key: "users.feedback_provided") do |r| + UserMailer.feedback_complete( + r, + self, + org_admin).deliver_now + end true else false @@ -505,7 +509,7 @@ # # Returns Boolean def visibility_allowed? - !is_test? && phases.select{ |phase| phase.visibility_allowed?(self) }.any? + !is_test? && phases.select { |phase| phase.visibility_allowed?(self) }.any? end # Determines whether or not a question (given its id) exists for the self plan diff --git a/app/models/stat_created_plan.rb b/app/models/stat_created_plan.rb index 0f0bd35..4e53896 100644 --- a/app/models/stat_created_plan.rb +++ b/app/models/stat_created_plan.rb @@ -50,7 +50,7 @@ end.call(created_plans) data = created_plans.map do |created_plan| - tuple = { date: created_plan.date } + tuple = { Date: created_plan.date.strftime("%b %Y") } template_names.reduce(tuple) do |acc, name| acc[name] = 0 acc @@ -58,11 +58,10 @@ created_plan.details&.fetch("by_template", [])&.each do |name_count| tuple[name_count.fetch("name")] = name_count.fetch("count") end - tuple[:count] = created_plan.count + tuple[:Count] = created_plan.count tuple end - - Csvable.from_array_of_hashes(data) + Csvable.from_array_of_hashes(data, false) end end diff --git a/app/models/stat_created_plan/create_or_update.rb b/app/models/stat_created_plan/create_or_update.rb index cfc5d32..8802105 100644 --- a/app/models/stat_created_plan/create_or_update.rb +++ b/app/models/stat_created_plan/create_or_update.rb @@ -52,10 +52,16 @@ .administrator .merge(users(org)) .merge(plans(start_date: start_date, end_date: end_date)) - .select(:plan_id) - .distinct - template_counts = Plan.where(id: roleable_plan_ids).group(:template_id).count - template_names = Template.where(id: template_counts.keys).pluck(:id, :title) + .pluck(:plan_id) + .uniq + + template_counts = Plan.joins(:template).where(id: roleable_plan_ids) + .group("templates.family_id").count + most_recent_versions = Template.where(family_id: template_counts.keys) + .group(:family_id).maximum("version") + most_recent_versions = most_recent_versions.map { |k, v| "#{k}=#{v}" } + template_names = Template.where("CONCAT(family_id, '=', version) IN (?)", + most_recent_versions).pluck(:family_id, :title) template_names.map do |t| { name: t[1], count: template_counts[t[0]] } end diff --git a/app/models/template.rb b/app/models/template.rb index 4553d90..71b3902 100644 --- a/app/models/template.rb +++ b/app/models/template.rb @@ -189,8 +189,10 @@ # Retrieves unarchived templates whose title or org.name includes the term # passed scope :search, lambda { |term| - unarchived.joins(:org).where("templates.title LIKE :term OR orgs.name LIKE :term", - term: "%#{term}%") + unarchived.joins(:org) + .where("lower(templates.title) LIKE lower(:term) OR " + + "lower(orgs.name) LIKE lower(:term)", + term: "%#{term}%") } diff --git a/app/models/theme.rb b/app/models/theme.rb index 4e66430..297a660 100644 --- a/app/models/theme.rb +++ b/app/models/theme.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # == Schema Information # # Table name: themes @@ -11,6 +13,7 @@ # class Theme < ActiveRecord::Base + include ValidationMessages # ================ @@ -32,7 +35,8 @@ scope :search, -> (term) { search_pattern = "%#{term}%" - where("title LIKE ? OR description LIKE ?", search_pattern, search_pattern) + where("lower(title) LIKE lower(?) OR description LIKE lower(?)", + search_pattern, search_pattern) } # =========================== @@ -43,6 +47,7 @@ # # Returns String def to_s - title + title end + end diff --git a/app/models/user.rb b/app/models/user.rb index 8e5963e..870e05a 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # == Schema Information # # Table name: users @@ -46,6 +48,7 @@ # class User < ActiveRecord::Base + include ConditionalUserMailer include ValidationMessages include ValidationValues @@ -57,7 +60,7 @@ # :lockable, :timeoutable and :omniauthable devise :invitable, :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :omniauthable, - :omniauth_providers => [:shibboleth, :orcid] + omniauth_providers: [:shibboleth, :orcid] ## @@ -93,7 +96,7 @@ has_many :identifier_schemes, through: :user_identifiers has_and_belongs_to_many :notifications, dependent: :destroy, - join_table: 'notification_acknowledgements' + join_table: "notification_acknowledgements" # =============== @@ -116,8 +119,14 @@ # Retrieves all of the org_admins for the specified org scope :org_admins, -> (org_id) { - joins(:perms).where("users.org_id = ? AND perms.name IN (?) AND users.active = ?", org_id, - ['grant_permissions', 'modify_templates', 'modify_guidance', 'change_org_details'], true) + joins(:perms).where("users.org_id = ? AND perms.name IN (?) AND " + + "users.active = ?", + org_id, + ["grant_permissions", + "modify_templates", + "modify_guidance", + "change_org_details"], + true) } scope :search, -> (term) { @@ -126,9 +135,12 @@ # or concat functions do not exist for sqlite, we have to come up with this # conditional if ActiveRecord::Base.connection.adapter_name == "Mysql2" - where("concat_ws(' ', firstname, surname) LIKE ? OR email LIKE ?", search_pattern, search_pattern) + where("lower(concat_ws(' ', firstname, surname)) LIKE lower(?) OR " + + "lower(email) LIKE lower(?)", + search_pattern, search_pattern) else - where("firstname || ' ' || surname LIKE ? OR email LIKE ?", search_pattern, search_pattern) + where("lower(firstname || ' ' || surname) LIKE lower(?) OR " + + "email LIKE lower(?)", search_pattern, search_pattern) end } @@ -332,7 +344,10 @@ # Override devise_invitable email title def deliver_invitation(options = {}) - super(options.merge(subject: _('A Data Management Plan in %{application_name} has been shared with you') % {application_name: Rails.configuration.branding[:application][:name]})) + super(options.merge(subject: _("A Data Management Plan in " + + "%{application_name} has been shared with you") % + { application_name: Rails.configuration.branding[:application][:name] }) + ) end # Case insensitive search over User model @@ -373,4 +388,5 @@ def clear_other_organisation self.other_organisation = nil end + end diff --git a/app/views/answers/_new_edit.html.erb b/app/views/answers/_new_edit.html.erb index ad6a1e4..67db511 100644 --- a/app/views/answers/_new_edit.html.erb +++ b/app/views/answers/_new_edit.html.erb @@ -6,7 +6,9 @@ <% q_format = question.question_format %> <% if q_format.rda_metadata? %>

- <%= sanitize question.text %> +

+ <%= sanitize question.text %> +

<% answer_hash = answer.answer_hash %>
@@ -55,11 +57,13 @@ <% end %>
> <% if question.option_based? || question.question_format.rda_metadata? %> - <%= render(partial: 'questions/new_edit_question_option_based', locals: { f: f, question: question, answer: answer }) %> + <%= render(partial: 'questions/new_edit_question_option_based', locals: { f: f, question: question, answer: answer, readonly: readonly }) %> <% elsif question.question_format.textfield?%> <%= render(partial: 'questions/new_edit_question_textfield', locals: { f: f, question: question, answer: answer }) %> <% elsif question.question_format.textarea? %> - <%= render(partial: 'questions/new_edit_question_textarea', locals: { f: f, question: question, answer: answer, locking: locking, readonly: readonly}) %> + <%= render(partial: 'questions/new_edit_question_textarea', locals: { f: f, question: question, answer: answer, locking: locking, readonly: readonly }) %> + <% elsif question.question_format.date? %> + <%= render(partial: 'questions/new_edit_question_datefield', locals: { f: f, question: question, answer: answer, locking: locking, readonly: readonly }) %> <% end %> <%= f.button(_('Save'), class: "btn btn-default", type: "submit") %>
@@ -72,7 +76,7 @@ <%="#{annotation.org.abbreviation} "%> <%=_('example answer')%>
- <%= sanitize annotation.text %> +
<%= sanitize annotation.text %>
<% end %> diff --git a/app/views/guidance_groups/_index_by_theme.html.erb b/app/views/guidance_groups/_index_by_theme.html.erb index 707dc11..db1da61 100644 --- a/app/views/guidance_groups/_index_by_theme.html.erb +++ b/app/views/guidance_groups/_index_by_theme.html.erb @@ -1,15 +1,18 @@ <%# locals{ guidance_groups_by_theme } %> <% parent_id = guidance_groups_by_theme.object_id %>
-
- -
<% guidance_groups_by_theme.each_pair do |guidance_group, theme_hash| %> <% guidances_output = [] %> + <%# Do not show expand/collapse all links if there is only one item in theme_hash %> + <% if theme_hash.length > 1 %> +
+ +
+ <% end %> <% theme_hash.each_pair do |theme, guidances| %> <% question_guidance_id = "#{question.object_id}-#{guidances.object_id}" %> <%# if guidances with this theme have not been output %> @@ -42,7 +45,9 @@ <% end %>

<% unless guidances_output.include?(guidance.id) %> - <%= sanitize(guidance.text) %> +

+ <%= sanitize(guidance.text) %> +
<% guidances_output << guidance.id %> <% multiple = true %> <% end %> diff --git a/app/views/guidances/_guidance_display.html.erb b/app/views/guidances/_guidance_display.html.erb index 3454f45..6208b8a 100644 --- a/app/views/guidances/_guidance_display.html.erb +++ b/app/views/guidances/_guidance_display.html.erb @@ -13,7 +13,9 @@
- <%= sanitize question.guidance_annotation(current_user.org).text %> +
+ <%= sanitize question.guidance_annotation(current_user.org).text %> +
@@ -29,7 +31,11 @@
-
<%= sanitize guidance.text %>
+
+
+ <%= sanitize guidance.text %> +
+
<% end %> diff --git a/app/views/notes/_list.html.erb b/app/views/notes/_list.html.erb index 2c55831..dd43a76 100644 --- a/app/views/notes/_list.html.erb +++ b/app/views/notes/_list.html.erb @@ -5,7 +5,7 @@