diff --git a/Capfile b/Capfile new file mode 100644 index 0000000000..af3b01630b --- /dev/null +++ b/Capfile @@ -0,0 +1,20 @@ +# Load DSL and set up stages +require "capistrano/setup" + +# Include default deployment tasks +require "capistrano/deploy" + +# Load the SCM plugin appropriate to your project: +require "capistrano/scm/git" +install_plugin Capistrano::SCM::Git + +require 'capistrano/bundler' + +# TODO: Uncomment this for deployments to dmp-dev or roadmap-stg and permenantly once we have +# merged the latest changes into dmptool stage and prod +require "capistrano/rails/assets" + +require 'capistrano/rails/migrations' + +# Load custom tasks from `lib/capistrano/tasks` if you have any defined +Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r } diff --git a/Gemfile b/Gemfile index c38f3a255c..2042606f8d 100644 --- a/Gemfile +++ b/Gemfile @@ -53,7 +53,9 @@ group :puma do end # Bit fields for ActiveRecord (https://github.com/pboling/flag_shih_tzu) -gem 'flag_shih_tzu' # Allows for bitfields in activereccord +gem 'flag_shih_tzu', '~> 0.3.23' # Allows for bitfields in activereccord +# Pinned here because we're using a private method in Role.rb +# if this gets updated, check this method still exists # ------------------------------------------------ # JSON DSL - USED BY API @@ -110,8 +112,16 @@ gem 'recaptcha' # Ideal gem for handling attachments in Rails, Sinatra and Rack applications. (http://github.com/markevans/dragonfly) gem 'dragonfly' -group :aws, optional: true do - +# ------------------------------------------------ +# Start DMPTool customization +# For some reason capistrano's `set :bundle_with` is not working +# so we remove the optional flag to ensure this gem gets installed +# ------------------------------------------------ +#group :aws, optional: true do +group :aws do +# ------------------------------------------------ +# End DMPTool customization +# ------------------------------------------------ gem 'dragonfly-s3_data_store' end @@ -143,17 +153,28 @@ gem 'mini_racer' # ------------------------------------------------ # EXPORTING # Provides binaries for WKHTMLTOPDF project in an easily accessible package. -gem 'wkhtmltopdf-binary' +# ------------------------------------------------ +# Start DMPTool customization +# 0.12.5 does not work on our new linux2 instances. Pegging at 0.12.4 for now +# ------------------------------------------------ +#gem 'wkhtmltopdf-binary' +gem 'wkhtmltopdf-binary', '0.12.4' +# ------------------------------------------------ +# End DMPTool customization +# ------------------------------------------------ # PDF generator (from HTML) gem for Ruby on Rails (https://github.com/mileszs/wicked_pdf) gem 'wicked_pdf', '~> 1.1.0' # This simple gem allows you to create MS Word docx documents from simple html documents. This makes it easy to create dynamic reports and forms that can be downloaded by your users as simple MS Word docx files. (http://github.com/karnov/htmltoword) -gem 'htmltoword' +gem 'htmltoword', '1.1.0' # A feed fetching and parsing library (http://feedjira.com) gem 'feedjira' +# Filename sanitization for Ruby. This is useful when you generate filenames for downloads from user input +gem 'zaru' + # ------------------------------------------------ # INTERNATIONALIZATION # Simple FastGettext Rails integration. (http://github.com/grosser/gettext_i18n_rails) @@ -206,6 +227,9 @@ group :development, :test do # Guard gem for RSpec (https://github.com/guard/guard-rspec) gem "guard-rspec" + gem "capistrano" + + gem "capistrano-rails" end group :test do @@ -236,11 +260,7 @@ group :test do # Automatically create snapshots when Cucumber steps fail with Capybara and Rails (http://github.com/mattheworiordan/capybara-screenshot) gem "capybara-screenshot" - # The next generation developer focused tool for automated testing of webapps (https://github.com/SeleniumHQ/selenium) - gem "selenium-webdriver", "~> 3.14" - - # Easy installation and use of chromedriver. (https://github.com/flavorjones/chromedriver-helper) - gem "chromedriver-helper", ">= 1.2.0" + gem 'webdrivers', '~> 3.0' gem "rspec-collection_matchers" diff --git a/Gemfile.lock b/Gemfile.lock index 74545293dc..7898555ec3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -43,17 +43,17 @@ GEM tzinfo (~> 1.1) addressable (2.7.0) public_suffix (>= 2.0.2, < 5.0) - annotate (2.7.5) + airbrussh (1.4.0) + sshkit (>= 1.6.1, != 1.7.0) + annotate (3.0.3) activerecord (>= 3.2, < 7.0) - rake (>= 10.4, < 13.0) + rake (>= 10.4, < 14.0) annotate_gem (0.0.14) bundler (>= 1.1) api-pagination (4.8.2) - archive-zip (0.12.0) - io-like (~> 0.3.0) arel (6.0.4) ast (2.4.0) - autoprefixer-rails (9.6.1.1) + autoprefixer-rails (9.7.3) execjs bcrypt (3.1.13) better_errors (2.5.1) @@ -65,7 +65,7 @@ GEM bootstrap-sass (3.4.1) autoprefixer-rails (>= 5.2.1) sassc (>= 2.0.0) - brakeman (4.6.1) + brakeman (4.7.2) builder (3.2.3) bullet (6.0.2) activesupport (>= 3.0.0) @@ -76,6 +76,16 @@ GEM bundler (>= 1.2.0, < 3) thor (~> 0.18) byebug (11.0.1) + capistrano (3.11.2) + airbrussh (>= 1.0.0) + i18n + rake (>= 10.0.0) + sshkit (>= 1.9.0) + capistrano-bundler (1.6.0) + capistrano (~> 3.1) + capistrano-rails (1.4.0) + capistrano (~> 3.1) + capistrano-bundler (~> 1.1) capybara (3.29.0) addressable mini_mime (>= 0.1.3) @@ -84,21 +94,17 @@ GEM rack-test (>= 0.6.3) regexp_parser (~> 1.5) xpath (~> 3.2) - capybara-screenshot (1.0.23) + capybara-screenshot (1.0.24) capybara (>= 1.0, < 4) launchy - childprocess (2.0.0) - rake (< 13.0) - chromedriver-helper (2.1.1) - archive-zip (~> 0.10) - nokogiri (~> 1.8) + childprocess (3.0.0) coderay (1.1.2) concurrent-ruby (1.1.5) contact_us (1.2.0) rails (>= 4.2.0) crack (0.4.3) safe_yaml (~> 1.0.0) - crass (1.0.4) + crass (1.0.5) daemons (1.3.1) database_cleaner (1.7.0) debug_inspector (0.0.3) @@ -127,22 +133,22 @@ GEM erubi (1.9.0) erubis (2.7.0) eventmachine (1.2.7) - excon (0.67.0) + excon (0.70.0) execjs (2.7.0) - factory_bot (5.1.0) + factory_bot (5.1.1) activesupport (>= 4.2.0) - factory_bot_rails (5.1.0) + factory_bot_rails (5.1.1) factory_bot (~> 5.1.0) railties (>= 4.2.0) faker (2.2.1) i18n (>= 0.8) - faraday (0.15.4) + faraday (0.17.1) multipart-post (>= 1.2, < 3) fast_gettext (2.0.1) - feedjira (3.0.0) - loofah (>= 2.2.1) + feedjira (3.1.0) + loofah (>= 2.3.1) sax-machine (>= 1.0) - ffi (1.11.1) + ffi (1.11.3) flag_shih_tzu (0.3.23) fog-aws (3.5.2) fog-core (~> 2.1) @@ -163,7 +169,7 @@ GEM font-awesome-sass (4.2.2) sass (~> 3.2) formatador (0.2.5) - fuubar (2.4.1) + fuubar (2.5.0) rspec-core (~> 3.0) ruby-progressbar (~> 1.4) gettext (3.2.9) @@ -178,7 +184,7 @@ GEM rails (>= 3.2.0) globalid (0.4.2) activesupport (>= 4.2.0) - guard (2.15.1) + guard (2.16.1) formatador (>= 0.2.4) listen (>= 2.7, < 4.0) lumberjack (>= 1.0.12, < 2.0) @@ -194,16 +200,15 @@ GEM rspec (>= 2.99.0, < 4.0) hashdiff (1.0.0) hashie (3.6.0) - highline (2.0.2) + highline (2.0.3) htmltoword (1.1.0) actionpack nokogiri rubyzip (>= 1.0) i18n (0.9.5) concurrent-ruby (~> 1.0) - io-like (0.3.0) ipaddress (0.8.3) - jaro_winkler (1.5.3) + jaro_winkler (1.5.4) jbuilder (2.6.4) activesupport (>= 3.0.0) multi_json (>= 1.2) @@ -226,42 +231,42 @@ GEM ledermann-rails-settings (2.5.0) activerecord (>= 4.2) libv8 (7.3.492.27.1) - listen (3.1.5) - rb-fsevent (~> 0.9, >= 0.9.4) - rb-inotify (~> 0.9, >= 0.9.7) - ruby_dep (~> 1.2) + listen (3.2.1) + rb-fsevent (~> 0.10, >= 0.10.3) + rb-inotify (~> 0.9, >= 0.9.10) locale (2.1.2) - loofah (2.2.3) + loofah (2.4.0) crass (~> 1.0.2) nokogiri (>= 1.5.9) lumberjack (1.0.13) mail (2.7.1) mini_mime (>= 0.1.1) - metaclass (0.0.4) method_source (0.9.2) mime-types (3.3) mime-types-data (~> 3.2015) - mime-types-data (3.2019.0904) + mime-types-data (3.2019.1009) mini_mime (1.0.2) mini_portile2 (2.4.0) - mini_racer (0.2.6) + mini_racer (0.2.8) libv8 (>= 6.9.411) - minitest (5.12.0) - mocha (1.9.0) - metaclass (~> 0.0.1) - multi_json (1.13.1) + minitest (5.13.0) + mocha (1.10.1) + multi_json (1.14.1) multi_xml (0.6.0) multipart-post (2.1.1) mysql2 (0.4.10) nenv (0.3.0) + net-scp (2.0.0) + net-ssh (>= 2.6.5, < 6.0.0) + net-ssh (5.2.0) nio4r (2.5.2) - nokogiri (1.10.4) + nokogiri (1.10.7) mini_portile2 (~> 2.4.0) notiffany (0.1.3) nenv (~> 0.1) shellany (~> 0.0) - oauth2 (1.4.1) - faraday (>= 0.8, < 0.16.0) + oauth2 (1.4.2) + faraday (>= 0.8, < 2.0) jwt (>= 1.0, < 3.0) multi_json (~> 1.3) multi_xml (~> 0.5) @@ -282,25 +287,25 @@ GEM omniauth (>= 1.0.0) options (2.3.2) orm_adapter (0.5.0) - parallel (1.17.0) - parser (2.6.4.1) + parallel (1.19.1) + parser (2.6.5.0) ast (~> 2.4.0) pg (0.19.0) po_to_json (1.0.1) json (>= 1.6.0) - progress_bar (1.3.0) + progress_bar (1.3.1) highline (>= 1.6, < 3) options (~> 2.3.0) pry (0.12.2) coderay (~> 1.1.0) method_source (~> 0.9.0) public_suffix (4.0.1) - puma (4.2.0) + puma (4.3.1) nio4r (~> 2.0) pundit (2.1.0) activesupport (>= 3.0.0) rack (1.6.11) - rack-mini-profiler (1.0.2) + rack-mini-profiler (1.1.3) rack (>= 1.2.0) rack-proxy (0.6.5) rack @@ -323,8 +328,8 @@ GEM activesupport (>= 4.2.0, < 5.0) nokogiri (~> 1.6) rails-deprecated_sanitizer (>= 1.0.1) - rails-html-sanitizer (1.2.0) - loofah (~> 2.2, >= 2.2.2) + rails-html-sanitizer (1.3.0) + loofah (~> 2.3) rails_12factor (0.0.3) rails_serve_static_assets rails_stdout_logging @@ -336,65 +341,64 @@ GEM rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) rainbow (3.0.0) - rake (12.3.3) + rake (13.0.1) rb-fsevent (0.10.3) rb-inotify (0.10.0) ffi (~> 1.0) - recaptcha (5.1.0) + recaptcha (5.2.1) json regexp_parser (1.6.0) responders (2.4.1) actionpack (>= 4.2.0, < 6.0) railties (>= 4.2.0, < 6.0) rollbar (2.22.1) - rspec (3.8.0) - rspec-core (~> 3.8.0) - rspec-expectations (~> 3.8.0) - rspec-mocks (~> 3.8.0) + rspec (3.9.0) + rspec-core (~> 3.9.0) + rspec-expectations (~> 3.9.0) + rspec-mocks (~> 3.9.0) rspec-collection_matchers (1.2.0) rspec-expectations (>= 2.99.0.beta1) - rspec-core (3.8.2) - rspec-support (~> 3.8.0) - rspec-expectations (3.8.4) + rspec-core (3.9.0) + rspec-support (~> 3.9.0) + rspec-expectations (3.9.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.8.0) - rspec-mocks (3.8.1) + rspec-support (~> 3.9.0) + rspec-mocks (3.9.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.8.0) - rspec-rails (3.8.2) + rspec-support (~> 3.9.0) + rspec-rails (3.9.0) actionpack (>= 3.0) activesupport (>= 3.0) railties (>= 3.0) - rspec-core (~> 3.8.0) - rspec-expectations (~> 3.8.0) - rspec-mocks (~> 3.8.0) - rspec-support (~> 3.8.0) - rspec-support (3.8.2) - rubocop (0.74.0) + rspec-core (~> 3.9.0) + rspec-expectations (~> 3.9.0) + rspec-mocks (~> 3.9.0) + rspec-support (~> 3.9.0) + rspec-support (3.9.0) + rubocop (0.77.0) jaro_winkler (~> 1.5.1) parallel (~> 1.10) parser (>= 2.6) rainbow (>= 2.2.2, < 4.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 1.4.0, < 1.7) - rubocop-dmp_roadmap (1.1.0) + rubocop-dmp_roadmap (1.1.2) rubocop (>= 0.58.2) rubocop-rails_config (>= 0.2.2) rubocop-rspec (>= 1.27.0) - rubocop-performance (1.4.1) + rubocop-performance (1.5.1) rubocop (>= 0.71.0) - rubocop-rails (2.3.2) + rubocop-rails (2.4.0) rack (>= 1.1) rubocop (>= 0.72.0) - rubocop-rails_config (0.7.2) + rubocop-rails_config (0.9.0) railties (>= 3.0) - rubocop (~> 0.74) + rubocop (~> 0.77) rubocop-performance (~> 1.3) rubocop-rails (~> 2.0) - rubocop-rspec (1.35.0) - rubocop (>= 0.60.0) + rubocop-rspec (1.37.0) + rubocop (>= 0.68.1) ruby-progressbar (1.10.1) - ruby_dep (1.5.0) ruby_dig (0.0.2) rubyzip (1.3.0) safe_yaml (1.0.5) @@ -414,9 +418,9 @@ GEM sprockets-rails tilt sax-machine (1.3.2) - selenium-webdriver (3.142.4) - childprocess (>= 0.5, < 3.0) - rubyzip (~> 1.2, >= 1.2.2) + selenium-webdriver (3.142.6) + childprocess (>= 0.5, < 4.0) + rubyzip (>= 1.2.2) shellany (0.0.1) shoulda (3.6.0) shoulda-context (~> 1.0, >= 1.0.1) @@ -439,6 +443,9 @@ GEM actionpack (>= 4.0) activesupport (>= 4.0) sprockets (>= 3.0.0) + sshkit (1.20.0) + net-scp (>= 1.1.2) + net-ssh (>= 2.8.0) text (1.3.1) thin (1.7.2) daemons (~> 1.0, >= 1.0.9) @@ -451,14 +458,18 @@ GEM tzinfo (1.2.5) thread_safe (~> 0.1) unicode-display_width (1.6.0) - uniform_notifier (1.12.1) + uniform_notifier (1.13.0) warden (1.2.7) rack (>= 1.0) web-console (3.3.0) activemodel (>= 4.2) debug_inspector railties (>= 4.2) - webmock (3.7.5) + webdrivers (3.9.4) + nokogiri (~> 1.6) + rubyzip (~> 1.0) + selenium-webdriver (~> 3.0) + webmock (3.7.6) addressable (>= 2.3.6) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) @@ -474,6 +485,7 @@ GEM yard-tomdoc (0.7.1) tomparse (>= 0.4.0) yard + zaru (0.3.0) PLATFORMS ruby @@ -491,9 +503,10 @@ DEPENDENCIES bullet bundle-audit byebug + capistrano + capistrano-rails capybara capybara-screenshot - chromedriver-helper (>= 1.2.0) contact_us database_cleaner devise (>= 4.7.1) @@ -504,7 +517,7 @@ DEPENDENCIES factory_bot_rails faker feedjira - flag_shih_tzu + flag_shih_tzu (~> 0.3.23) font-awesome-sass (~> 4.2.0) fuubar gettext @@ -512,7 +525,7 @@ DEPENDENCIES gettext_i18n_rails_js guard guard-rspec - htmltoword + htmltoword (= 1.1.0) jbuilder (~> 2.6.0) kaminari ledermann-rails-settings @@ -541,7 +554,6 @@ DEPENDENCIES ruby_dig sass-rails sassc-rails - selenium-webdriver (~> 3.14) shoulda simplecov spring @@ -549,15 +561,17 @@ DEPENDENCIES text thin web-console + webdrivers (~> 3.0) webmock webpacker (~> 3.5) wicked_pdf (~> 1.1.0) - wkhtmltopdf-binary + wkhtmltopdf-binary (= 0.12.4) yard yard-tomdoc + zaru RUBY VERSION ruby 2.4.0p0 BUNDLED WITH - 1.17.1 + 1.17.2 diff --git a/app/assets/stylesheets/blocks/_accessibility.scss b/app/assets/stylesheets/blocks/_accessibility.scss index 3dde3a0a80..67caed1e1b 100644 --- a/app/assets/stylesheets/blocks/_accessibility.scss +++ b/app/assets/stylesheets/blocks/_accessibility.scss @@ -1,3 +1,8 @@ +/* Setting font-family for improving screen legibility */ +body, .tooltip, .popover { + font-family: $font-family; +} + /* Text meant only for screen readers. */ .screen-reader-text { border: 0; @@ -28,3 +33,36 @@ div.skip a:focus { height:auto; overflow:visible !important; } + +/** Focus outline required for accessibility */ +a, input, select, .form-control { + &:focus, + &:hover, + &:active { + outline-style: solid !important; + outline-color: $color-focus-outline !important; + outline-width: 2px !important; + } +} + + /** button outline-width increased for better visibility of outline */ + button { + + &:focus, + &:hover, + &:active { + outline-style: solid !important; + outline-color: $color-focus-outline !important; + outline-width: 3px !important; + } + } + + td { + &:focus-within, + &:focus, + &:hover { + outline-style: solid !important; + outline-color: $color-focus-outline !important; + outline-width: 2px !important; + } + } diff --git a/app/assets/stylesheets/blocks/_new_window_popup.scss b/app/assets/stylesheets/blocks/_new_window_popup.scss new file mode 100644 index 0000000000..a499e26a67 --- /dev/null +++ b/app/assets/stylesheets/blocks/_new_window_popup.scss @@ -0,0 +1,35 @@ +a.has-new-window-popup-info, +button.has-new-window-popup-info { + + position:relative; + z-index:24; + + & > span.new-window-popup-info { + position: absolute; + left: -9000px; + width: 0; + overflow: hidden; + } + + &:hover, + &:focus, + &:active { + + z-index:25; + + & > span.new-window-popup-info { + display:block; + position:absolute; + top:2em; + left:-1em; + width:12em; + border-radius: 5px; + border:1px solid #0cf; + background-color:#cff; + color:#000; + text-align: center; + } + + } + +} diff --git a/app/assets/stylesheets/blocks/_tinymce_content.scss b/app/assets/stylesheets/blocks/_tinymce_content.scss new file mode 100644 index 0000000000..895c5a0eec --- /dev/null +++ b/app/assets/stylesheets/blocks/_tinymce_content.scss @@ -0,0 +1,8 @@ +@import "../variables/tinymce"; + +.mce-content-body { + + a { + color: $color-link-text; + } +} \ No newline at end of file diff --git a/app/assets/stylesheets/dmptool/blocks/_new_window_popup.scss b/app/assets/stylesheets/dmptool/blocks/_new_window_popup.scss new file mode 100644 index 0000000000..4adcdf8ea7 --- /dev/null +++ b/app/assets/stylesheets/dmptool/blocks/_new_window_popup.scss @@ -0,0 +1,23 @@ +a.has-new-window-popup-info, +button.has-new-window-popup-info { + + & > span.new-window-popup-info { + left: auto; + right: 10px; + } + + &:hover, + &:focus, + &:active { + + & > span.new-window-popup-info { + border:1px solid $color-dark-blue; + background-color: $color-light-blue; + color: $color-dark-blue; + left: auto; + right: 10px; + } + + } + +} \ No newline at end of file diff --git a/app/assets/stylesheets/variables/_colours.scss b/app/assets/stylesheets/variables/_colours.scss index 1c2842d441..6f173d8882 100644 --- a/app/assets/stylesheets/variables/_colours.scss +++ b/app/assets/stylesheets/variables/_colours.scss @@ -12,6 +12,7 @@ $color-grey-darker: #333; $color-grey-light: #777; $color-grey-lighter: #999; $color-blue: #337ab7; +$color-blue-alice-darkest: #107896; $color-muted: #CCC; $color-dark-blue: #0E5682; @@ -74,3 +75,6 @@ $color-shadow-dark: $color-black; // FontAwesome Colors $color-fa: $color-grey; + +// Focus colors +$color-focus-outline: $color-blue-alice-darkest; \ No newline at end of file diff --git a/app/assets/stylesheets/variables/_tinymce.scss b/app/assets/stylesheets/variables/_tinymce.scss index d6fd4d7abf..a7c70a7715 100644 --- a/app/assets/stylesheets/variables/_tinymce.scss +++ b/app/assets/stylesheets/variables/_tinymce.scss @@ -1,2 +1,3 @@ // Import the desired TinyMCE skin name //@import "lightgray/skin.min"; +@import "./colours"; \ No newline at end of file diff --git a/app/assets/stylesheets/variables/_typography.scss b/app/assets/stylesheets/variables/_typography.scss index 48a14fa833..7cc3a8faf2 100644 --- a/app/assets/stylesheets/variables/_typography.scss +++ b/app/assets/stylesheets/variables/_typography.scss @@ -3,3 +3,6 @@ src: font-url('GillSansLight.ttf') format('truetype'); font-weight: normal; } + +// Chosen for Accessibility +$font-family: Verdana, Trebuchet, "Helvetica Neue", Helvetica, Arial, sans-serif; diff --git a/app/assets/xslt/htmltoword/functions.xslt b/app/assets/xslt/htmltoword/functions.xslt new file mode 100644 index 0000000000..4624cd0e1c --- /dev/null +++ b/app/assets/xslt/htmltoword/functions.xslt @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + rId + diff --git a/app/assets/xslt/htmltoword/numbering.xslt b/app/assets/xslt/htmltoword/numbering.xslt new file mode 100644 index 0000000000..71cf55bc48 --- /dev/null +++ b/app/assets/xslt/htmltoword/numbering.xslt @@ -0,0 +1,198 @@ + + + + + + + + + + + + + + + + lowerLetter + upperLetter + lowerRoman + upperRoman + none + decimal + bullet,● + bullet,o + bullet,■ + none + + + + + decimal + bullet,● + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/controllers/api/v0/plans_controller.rb b/app/controllers/api/v0/plans_controller.rb index 3863292234..783002dfb3 100644 --- a/app/controllers/api/v0/plans_controller.rb +++ b/app/controllers/api/v0/plans_controller.rb @@ -61,10 +61,46 @@ def index if params[:per_page].present? && params[:per_page].to_i > Rails.configuration.branding[:application][:api_max_page_size] params[:per_page] = Rails.configuration.branding[:application][:api_max_page_size] end - @plans = paginate @user.org.plans.includes( [ {answers: :question_options} , - template: [ { phases: { sections: { questions: :question_format } } }, :org] + @plans = @user.org.plans.includes( [ {roles: :user}, {answers: :question_options} , + template: [ { phases: { sections: { questions: [:question_format, :themes ] } } }, :org] ]) + + # Filter on list of users + user_ids = extract_param_list(params, "user") + @plans = @plans.where(roles: {user_id: user_ids, access: Role.bit_values(:editor)}) if user_ids.present? + # filter on dates + if params["created_after"].present? || params["created_before"].present? + @plans = @plans.where(created_at: dates_to_range(params,"created_after","created_before")) + end + if params["updated_after"].present? || params["updated_before"].present? + @plans = @plans.where(updated_at: dates_to_range(params,"updated_after","updated_before")) + end + # filter on funder (dmptemplate_id) + template_ids = extract_param_list(params, "template") + @plans = @plans.where(templates: {family_id: template_ids}) if template_ids.present? + # filter on id(s) + plan_ids = extract_param_list(params, "plan") + @plans = @plans.where(id: plan_ids ) if plan_ids.present? + # apply pagination after filtering + @plans = paginate @plans respond_with @plans end + private + + def extract_param_list(params, attribute) + list = params.fetch(attribute+"[]", []) + val = params.fetch(attribute, []) + list << val if val.present? + list + end + + # takes in the params hash and converts to a date-range + def dates_to_range(hash,start,stop) + today = Date.today + start_date = Date.parse(hash.fetch(start, today.prev_month.to_date.to_s)) + end_date = Date.parse(hash.fetch(stop, today.to_date.to_s)) + 1.day + start_date..end_date + end + end diff --git a/app/controllers/api/v0/templates_controller.rb b/app/controllers/api/v0/templates_controller.rb index e38bbe9b2f..d210159253 100644 --- a/app/controllers/api/v0/templates_controller.rb +++ b/app/controllers/api/v0/templates_controller.rb @@ -25,7 +25,7 @@ def index .where(org_id: @user.org_id, published: true) .where.not(customization_of: nil) - Template.published.order(:org_id, :version).each do |temp| + published_templates.order(:org_id, :version).each do |temp| if @org_templates[temp.org].present? if @org_templates[temp.org][:own][temp.family_id].nil? @org_templates[temp.org][:own][temp.family_id] = temp @@ -37,7 +37,7 @@ def index @org_templates[temp.org][:own][temp.family_id] = temp end end - Template.published_customization(@user.org_id).each do |temp| + customized_templates.each do |temp| if @org_templates[temp.org].present? if @org_templates[temp.org][:cust][temp.family_id].nil? @org_templates[temp.org][:cust][temp.family_id] = temp diff --git a/app/controllers/feedback_requests_controller.rb b/app/controllers/feedback_requests_controller.rb index 241c6ad38e..af26af1cea 100644 --- a/app/controllers/feedback_requests_controller.rb +++ b/app/controllers/feedback_requests_controller.rb @@ -14,12 +14,12 @@ def create authorize @plan, :request_feedback? begin if @plan.request_feedback(current_user) - redirect_to share_plan_path(@plan), notice: _(request_feedback_flash_notice) + redirect_to request_feedback_plan_path(@plan), notice: _(request_feedback_flash_notice) else - redirect_to share_plan_path(@plan), alert: ALERT + redirect_to request_feedback_plan_path(@plan), alert: ALERT end rescue Exception - redirect_to share_plan_path(@plan), alert: ERROR + redirect_to request_feedback_plan_path(@plan), alert: ERROR end end diff --git a/app/controllers/org_admin/templates_controller.rb b/app/controllers/org_admin/templates_controller.rb index 4c69d0be6c..fc9fd960d4 100644 --- a/app/controllers/org_admin/templates_controller.rb +++ b/app/controllers/org_admin/templates_controller.rb @@ -174,7 +174,11 @@ def update template = Template.find(params[:id]) authorize template begin - template.assign_attributes(template_params) + args = template_params + # Swap in the appropriate visibility enum value for the checkbox value + args[:visibility] = args.fetch(:visibility, '0') == '1' ? 'organisationally_visible' : 'publicly_visible' + + template.assign_attributes(args) if params["template-links"].present? template.links = ActiveSupport::JSON.decode(params["template-links"]) end @@ -282,6 +286,60 @@ def unpublish redirect_to request.referrer.present? ? request.referrer : org_admin_templates_path end + # GET template_export/:id + # ----------------------------------------------------- + def template_export + @template = Template.find(params[:id]) + + authorize @template + # now with prefetching (if guidance is added, prefetch annottaions/guidance) + @template = Template.includes( + :org, + phases: { + sections: { + questions: [ + :question_options, + :question_format, + :annotations + ] + } + } + ).find(@template.id) + + @formatting = Settings::Template::DEFAULT_SETTINGS[:formatting] + + begin + file_name = @template.title.gsub(/[^a-zA-Z\d\s]/, "").gsub(/ /, "_") + '_v' + @template.version.to_s + respond_to do |format| + format.docx do + render docx: "template_exports/template_export", filename: "#{file_name}.docx" + end + + format.pdf do + # rubocop:disable LineLength + render pdf: file_name, + template: "template_exports/template_export", + margin: @formatting[:margin], + footer: { + center: _("Template created using the %{application_name} service. Last modified %{date}") % { + application_name: Rails.configuration.branding[:application][:name], + date: l(@template.updated_at.to_date, formats: :short) + }, + font_size: 8, + spacing: (@formatting[:margin][:bottom] / 2) - 4, + right: "[page] of [topage]", + encoding: "utf8" + } + # rubocop:enable LineLength + end + end + rescue ActiveRecord::RecordInvalid => e + # What scenario is this triggered in? it's common to our export pages + redirect_to public_templates_path, + alert: _("Unable to download the DMP Template at this time.") + end + end + private def template_params diff --git a/app/controllers/org_admin/users_controller.rb b/app/controllers/org_admin/users_controller.rb new file mode 100644 index 0000000000..e2c730ce6f --- /dev/null +++ b/app/controllers/org_admin/users_controller.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +module OrgAdmin + + class UsersController < ApplicationController + + after_action :verify_authorized + + def edit + @user = User.find(params[:id]) + authorize @user + @departments = @user.org.departments.order(:name) + @plans = Plan.active(@user).page(1) + render "org_admin/users/edit", + locals: { user: @user, + departments: @departments, + plans: @plans, + languages: @languages, + orgs: @orgs, + identifier_schemes: @identifier_schemes, + default_org: @user.org } + end + + def update + @user = User.find(params[:id]) + authorize @user + @departments = @user.org.departments.order(:name) + @plans = Plan.active(@user).page(1) + # Replace the 'your' word from the canned responses so that it does + # not read 'Successfully updated your profile for John Doe' + topic = _("profile for %{username}") % { username: @user.name(false) } + if @user.update_attributes(user_params) + flash.now[:notice] = success_message(@user, _("updated")) + else + flash.now[:alert] = failure_message(@user, _("update")) + end + render :edit + end + + def user_plans + @user = User.find(params[:id]) + authorize @user + @plans = Plan.active(@user).page(1) + render "org_admin/users/plans" + end + + + private + def user_params + params.require(:user).permit(:department_id) + end + + end + +end diff --git a/app/controllers/orgs_controller.rb b/app/controllers/orgs_controller.rb index 2e753e1087..e8693bf2f0 100644 --- a/app/controllers/orgs_controller.rb +++ b/app/controllers/orgs_controller.rb @@ -33,25 +33,22 @@ def admin_update # Only allow super admins to change the org types and shib info if current_user.can_super_admin? # Handle Shibboleth identifiers if that is enabled - if Rails.application.config.shibboleth_use_filtered_discovery_service && - params[:shib_id].present? + if Rails.application.config.shibboleth_use_filtered_discovery_service shib = IdentifierScheme.find_by(name: "shibboleth") shib_settings = @org.org_identifiers.select do |ids| ids.identifier_scheme == shib end.first - if !params[:shib_id].blank? + if params[:shib_id].blank? && shib_settings.present? + # The user cleared the shib values so delete the object + shib_settings.destroy + else unless shib_settings.present? shib_settings = OrgIdentifier.new(org: @org, identifier_scheme: shib) - shib_settings.identifier = params[:shib_id] - shib_settings.attrs = { domain: params[:shib_domain] } - shib_settings.save - end - else - if shib_settings.present? - # The user cleared the shib values so delete the object - shib_settings.destroy end + shib_settings.identifier = params[:shib_id] + shib_settings.attrs = { domain: params[:shib_domain] } + shib_settings.save end end end diff --git a/app/controllers/paginable/plans_controller.rb b/app/controllers/paginable/plans_controller.rb index 6e06b9bffc..b82e459c7a 100644 --- a/app/controllers/paginable/plans_controller.rb +++ b/app/controllers/paginable/plans_controller.rb @@ -32,7 +32,6 @@ def organisationally_or_publicly_visible def publicly_visible paginable_renderise( partial: "publicly_visible", - scope: Plan.publicly_visible.includes(:template) scope: Plan.publicly_visible.includes(:template), query_params: { sort_field: 'plans.updated_at', sort_direction: :desc } ) @@ -50,4 +49,18 @@ def org_admin ) end + # GET /paginable/plans/org_admin/:page + def org_admin_other_user + @user = User.find(params[:id]) + authorize @user + unless current_user.present? && current_user.can_org_admin? && @user.present? + raise Pundit::NotAuthorizedError + end + paginable_renderise( + partial: "org_admin_other_user", + scope: Plan.organisationally_or_publicly_visible(@user), + query_params: { sort_field: 'plans.updated_at', sort_direction: :desc } + ) + end + end diff --git a/app/controllers/plan_exports_controller.rb b/app/controllers/plan_exports_controller.rb index fc8d3e8b30..42c583934b 100644 --- a/app/controllers/plan_exports_controller.rb +++ b/app/controllers/plan_exports_controller.rb @@ -88,7 +88,15 @@ def show_pdf end def file_name - @plan.title.gsub(/ /, "_") + # Sanitize bad characters and replace spaces with underscores + ret = @plan.title + Zaru.sanitize! ret + ret = ret.strip.gsub(/\s+/, "_") + # limit the filename length to 100 chars. Windows systems have a MAX_PATH allowance + # of 255 characters, so this should provide enough of the title to allow the user + # to understand which DMP it is and still allow for the file to be saved to a deeply + # nested directory + ret[0, 100] end def publicly_authorized? diff --git a/app/controllers/plans_controller.rb b/app/controllers/plans_controller.rb index 17ab569c18..2a3fccff17 100644 --- a/app/controllers/plans_controller.rb +++ b/app/controllers/plans_controller.rb @@ -17,6 +17,10 @@ def index @organisationally_or_publicly_visible = Plan.organisationally_or_publicly_visible(current_user).page(1) end + + if params[:plan].present? + @template = Template.find(params[:plan][:template_id]) + end end # GET /plans/new @@ -264,6 +268,16 @@ def share end end + def request_feedback + @plan = Plan.find(params[:id]) + if @plan.present? + authorize @plan + @plan_roles = @plan.roles + else + redirect_to(plans_path) + end + end + def destroy @plan = Plan.find(params[:id]) authorize @plan diff --git a/app/controllers/public_pages_controller.rb b/app/controllers/public_pages_controller.rb index 25fb04f05d..7d69fed5ab 100644 --- a/app/controllers/public_pages_controller.rb +++ b/app/controllers/public_pages_controller.rb @@ -2,8 +2,6 @@ class PublicPagesController < ApplicationController - after_action :verify_authorized, except: [:template_index, :plan_index] - include Dmptool::Controller::PublicPages # GET template_index @@ -44,15 +42,16 @@ def template_export @formatting = Settings::Template::DEFAULT_SETTINGS[:formatting] begin - file_name = @template.title.gsub(/[^a-zA-Z\d\s]/, "").gsub(/ /, "_") + file_name = @template.title.gsub(/[^a-zA-Z\d\s]/, "").gsub(/ /, "_") + '_v' + @template.version.to_s respond_to do |format| format.docx do - render docx: "template_export", filename: "#{file_name}.docx" + render docx: "template_exports/template_export", filename: "#{file_name}.docx" end format.pdf do # rubocop:disable LineLength render pdf: file_name, + template: "template_exports/template_export", margin: @formatting[:margin], footer: { center: _("Template created using the %{application_name} service. Last modified %{date}") % { diff --git a/app/controllers/roles_controller.rb b/app/controllers/roles_controller.rb index bafc2d7f3f..46dd1eebb1 100644 --- a/app/controllers/roles_controller.rb +++ b/app/controllers/roles_controller.rb @@ -77,7 +77,7 @@ def update # rubocop:disable LineLength render json: { code: 1, - msg: _("Successfully changed the permissions for #{@role.user.email}. They have been notified via email.") + msg: _("Successfully changed the permissions for %{email}. They have been notified via email.") % { email: @role.user.email } } # rubocop:enable LineLength else diff --git a/app/controllers/static_pages_controller.rb b/app/controllers/static_pages_controller.rb index 698b8fecbe..f68cc42998 100644 --- a/app/controllers/static_pages_controller.rb +++ b/app/controllers/static_pages_controller.rb @@ -6,7 +6,7 @@ class StaticPagesController < ApplicationController def about_us dcc_news_feed_url = "http://www.dcc.ac.uk/news/dmponline-0/feed" - @dcc_news_feed = Feedjira::Feed.fetch_and_parse dcc_news_feed_url + #@dcc_news_feed = Feedjira::Feed.fetch_and_parse dcc_news_feed_url respond_to do |format| format.rss { redirect_to dcc_news_feed_url } format.html diff --git a/app/controllers/super_admin/users_controller.rb b/app/controllers/super_admin/users_controller.rb index ab5d69cc48..a4d2a14ba0 100644 --- a/app/controllers/super_admin/users_controller.rb +++ b/app/controllers/super_admin/users_controller.rb @@ -9,8 +9,12 @@ class UsersController < ApplicationController def edit @user = User.find(params[:id]) authorize @user + @departments = @user.org.departments.order(:name) + @plans = Plan.active(@user).page(1) render "super_admin/users/edit", locals: { user: @user, + departments: @departments, + plans: @plans, languages: @languages, orgs: @orgs, identifier_schemes: @identifier_schemes, @@ -20,6 +24,8 @@ def edit def update @user = User.find(params[:id]) authorize @user + @departments = @user.org.departments.order(:name) + @plans = Plan.active(@user).page(1) # Replace the 'your' word from the canned responses so that it does # not read 'Successfully updated your profile for John Doe' topic = _("profile for %{username}") % { username: @user.name(false) } @@ -31,10 +37,63 @@ def update render :edit end + def merge + @user = User.find(params[:id]) + authorize @user + remove = User.find(params[:merge_id]) + + topic = _("profile for %{remove} into %{keep}" % { + remove: remove.name(false), keep: @user.name(false)}) + if @user.merge(remove) + flash.now[:notice] = success_message(@user, _("merged")) + else + flash.now[:alert] = failure_message(@user, _("merge")) + end + # After merge attempt get departments and plans + @departments = @user.org.departments.order(:name) + @plans = Plan.active(@user).page(1) + render :edit + end + + def search + @user = User.find(params[:id]) + @users = User.where('email LIKE ?', "%#{params[:email]}%") + authorize @users + @departments = @user.org.departments.order(:name) + @plans = Plan.active(@user).page(1) + # WHAT TO RETURN!?!?! + if @users.present? # found a user, or Users, submit for merge + render json: { + form: render_to_string(partial: 'super_admin/users/confirm_merge.html.erb'), + } + else # NO USER, re-render w/error? + flash.now[:alert] = "Unable to find user" + render :edit # re-do as responding w/ json + end + end + + def archive + @user = User.find(params[:id]) + authorize @user + @departments = @user.org.departments.order(:name) + @plans = Plan.active(@user).page(1) + if @user.archive + flash.now[:notice] = success_message(@user, _("archived")) + else + flash.now[:alert] = failure_message(@user, _("archive")) + end + render :edit + end + private def user_params - params.require(:user).permit(:email, :firstname, :surname, :org_id, - :language_id, :other_organisation) + params.require(:user).permit(:email, + :firstname, + :surname, + :org_id, + :department_id, + :language_id, + :other_organisation) end end diff --git a/app/helpers/template_helper.rb b/app/helpers/template_helper.rb index 3905e98735..2a8392eddc 100644 --- a/app/helpers/template_helper.rb +++ b/app/helpers/template_helper.rb @@ -33,4 +33,22 @@ def links_to_a_elements(links, separator = ", ") a.join(separator) end + # Generate a direct plan creation link based on provided template + # @param template [Template] template used for plan creation + # @param hidden [Boolean] should the link be hidden? + # @param text [String] text for the link + # @param id [String] id for the link element + def direct_link(template, hidden = false, text = nil, id = nil) + params = { org_id: template.org.id, funder_id: '-1', template_id: template.id } + cls = text.nil? ? 'direct-link' : 'direct-link btn btn-default' + style = hidden ? 'display: none' : '' + + link_to(plans_url(plan: params), method: :post, title: _('Create plan'), class: cls, id: id, style: style) do + if text.nil? + ''.html_safe + else + text.html_safe + end + end + end end diff --git a/app/javascript/dmptool/views/home/index.js b/app/javascript/dmptool/views/home/index.js index 4eaa4ee445..4d39a0594d 100644 --- a/app/javascript/dmptool/views/home/index.js +++ b/app/javascript/dmptool/views/home/index.js @@ -1,4 +1,7 @@ /* eslint-env browser */ // This allows us to reference 'window' below + +import getConstant from '../../../constants'; + $(() => { // Rotate through the news items every 8 seconds const articles = $('#home-news-array').val(); @@ -6,9 +9,9 @@ $(() => { const news = JSON.parse(`${articles.replace(/\\"/g, '"').replace(/\\'/g, '\'')}`); const updateNews = (item) => { const text = $('#home-news-link'); - const sr = ' (new window)'; + const span = `${getConstant('OPENS_IN_A_NEW_WINDOW_TEXT')}`; text.hide(); - text.html(`${news[item].title}${sr}`); + text.html(`${news[item].title} ${span}`); text.fadeIn(100); }; const startNewsTimer = (item) => { diff --git a/app/javascript/packs/application.js b/app/javascript/packs/application.js index 96e90920e1..988858c4a6 100644 --- a/app/javascript/packs/application.js +++ b/app/javascript/packs/application.js @@ -8,6 +8,7 @@ import '../utils/externalLink'; import '../utils/paginable'; import '../utils/panelHeading'; import '../utils/links'; +import '../utils/outOfFocus'; import '../utils/tabHelper'; import '../utils/tooltipHelper'; import '../utils/popoverHelper'; @@ -62,6 +63,7 @@ import '../views/usage/index'; import '../views/users/notification_preferences'; import '../views/users/admin_grant_permissions'; import '../views/super_admin/notifications/edit'; +import '../views/public_templates/show'; // ---------------------------------------- // START DMPTool customization diff --git a/app/javascript/utils/externalLink.js b/app/javascript/utils/externalLink.js index 9eb13059fa..128df44ef8 100644 --- a/app/javascript/utils/externalLink.js +++ b/app/javascript/utils/externalLink.js @@ -17,6 +17,30 @@ $(() => { && !(exceptions.ids.indexOf(link.attr('id')) >= 0) ) { link.attr('target', '_blank'); + link.addClass('has-new-window-popup-info'); + // Add span as child of link. + link.append($(`${getConstant('OPENS_IN_A_NEW_WINDOW_TEXT')}`)); + } + }); + + $('a[href^="http"]').each((index, value) => { + const link = $(value); + const protocol = new RegExp('^https?'); + const regex = new RegExp(`^https?://${getConstant('HOST')}`); + const exceptions = { + ids: ['connect-orcid-button', 'view-all-templates'], + }; + // Internal links are typically just the path, but also check for other domains + if ( + !link.attr('target') + && protocol.test(link.attr('href')) + && !regex.test(link.attr('href')) + && !(exceptions.ids.indexOf(link.attr('id')) >= 0) + ) { + link.attr('target', '_blank'); + link.addClass('has-new-window-popup-info'); + // Add span as child of link. + link.append($(`${getConstant('OPENS_IN_A_NEW_WINDOW_TEXT')}`)); } }); }); diff --git a/app/javascript/utils/outOfFocus.js b/app/javascript/utils/outOfFocus.js new file mode 100644 index 0000000000..2d873e6a02 --- /dev/null +++ b/app/javascript/utils/outOfFocus.js @@ -0,0 +1,22 @@ +$(() => { + // This bit of code currently only closes dropdown + // menus in a table when the focus is no longer in the containing cell. + + // List of focusable Elements on page + const focusables = $('td, .dropdown, .dropdown-toggle, a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, [tabindex], [contenteditable]'); + + focusables.each((i, el) => { + const focusable = $(el); // JQuery object + // On entrying a new focusable element we respond to event + focusable.focusin(() => { + $('td').children('.dropdown.open').each((j, elj) => { + const td = $(elj).parent(); // DOM Element + const dropdownBtn = $(elj).find('.dropdown-toggle'); // JQuery object + // Close dropdown menu if the focus is not the table cell containing the dropdown + if (!($.contains(td.get(0), focusable.get(0)) || focusable.is(td))) { + dropdownBtn.dropdown('toggle'); + } + }); + }); + }); +}); diff --git a/app/javascript/utils/tinymce.js b/app/javascript/utils/tinymce.js index c064a52474..2e5a8e14c4 100644 --- a/app/javascript/utils/tinymce.js +++ b/app/javascript/utils/tinymce.js @@ -42,6 +42,7 @@ export const defaultOptions = { // editorManager.baseURL is not resolved properly for IE since document.currentScript // is not supported, see issue https://github.com/tinymce/tinymce/issues/358 skin_url: '/tinymce/skins/lightgray', + content_css: ['/assets/blocks/_tinymce_content.css'], }; /* This function is invoked anytime a new editor is initialised (e.g. Tinymce.init()) diff --git a/app/javascript/views/plans/index.js b/app/javascript/views/plans/index.js index b030b67f4e..b3cd74c1eb 100644 --- a/app/javascript/views/plans/index.js +++ b/app/javascript/views/plans/index.js @@ -26,4 +26,6 @@ $(() => { $(paginableSelector).on('ajax:error', '.set_test_plan', () => { // TODO adequate error handling for network error }); + + $('#create-modal').modal('show'); }); diff --git a/app/javascript/views/public_templates/show.js b/app/javascript/views/public_templates/show.js new file mode 100644 index 0000000000..16bf07f7dc --- /dev/null +++ b/app/javascript/views/public_templates/show.js @@ -0,0 +1,15 @@ +$(() => { + $('.copy-link').click((e) => { + const link = $(e.currentTarget).siblings('.direct-link'); + + $('#link-modal').on('show.bs.modal', () => { + $('#link').val(link.attr('href')); + }); + }); + + $('#copy-link-btn').click(() => { + $('#link').select(); + // eslint-disable-next-line + document.execCommand('copy'); + }); +}); diff --git a/app/javascript/views/super_admin/users/edit.js b/app/javascript/views/super_admin/users/edit.js index 0b3d18b054..b8ab0ebbe8 100644 --- a/app/javascript/views/super_admin/users/edit.js +++ b/app/javascript/views/super_admin/users/edit.js @@ -4,10 +4,29 @@ $(() => { const options = { selector: '#super_admin_user_edit' }; initOrgSelection(options); + const updateMergeConfirmation = (userSelect) => { + // update the confirmation dialogue with the selected user's email address + const editingUserEmail = $('#superadmin_user_email').val(); + const chosenUserEmail = userSelect.find('option:selected').text(); + const submitButton = userSelect.closest('form').find(':submit'); + submitButton.attr('data-confirm', + `Confirm Account Merge: The account for ${editingUserEmail} will be merged with ${chosenUserEmail}. + All plans and account information for ${chosenUserEmail} will now be accessible via ${editingUserEmail}. + The account for ${chosenUserEmail} will then be destroyed.`); + }; + $('#super_admin_user_edit').on('submit', (e) => { // Additional validation to force the user to choose an org or type something for other if (!validateOrgSelection(options)) { e.preventDefault(); } }); + + $('#merge_form').on('ajax:success', (e, data) => { + // replace the search form with the merge form + $('#merge_form_container').html(data.form); + const userSelect = $('#merge_id'); + userSelect.on('change', () => updateMergeConfirmation(userSelect)); + userSelect.change(); + }); }); diff --git a/app/models/answer.rb b/app/models/answer.rb index dbda9d08c0..c6417be54e 100644 --- a/app/models/answer.rb +++ b/app/models/answer.rb @@ -93,7 +93,7 @@ def has_question_option(option_id) # presence of text # # Returns Boolean - def is_valid? + def answered? if question.present? if question.question_format.option_based? return question_options.any? diff --git a/app/models/phase.rb b/app/models/phase.rb index 84c216c7cc..a6c9709313 100644 --- a/app/models/phase.rb +++ b/app/models/phase.rb @@ -52,6 +52,12 @@ class Phase < ActiveRecord::Base has_many :sections, dependent: :destroy + has_many :questions, through: :sections + + has_many :answers, through: :questions + + has_many :annotations, through: :questions + has_many :template_sections, -> { not_modifiable }, class_name: "Section" diff --git a/app/models/plan.rb b/app/models/plan.rb index 867d900fe1..afafe82536 100644 --- a/app/models/plan.rb +++ b/app/models/plan.rb @@ -165,8 +165,11 @@ class Plan < ActiveRecord::Base scope :search, lambda { |term| search_pattern = "%#{term}%" joins(:template) - .where("lower(plans.title) LIKE lower(?) OR lower(templates.title) LIKE lower(?)", - search_pattern, search_pattern) + .where("lower(plans.title) LIKE lower(:search_pattern) + OR lower(templates.title) LIKE lower(:search_pattern) + OR lower(plans.principal_investigator) LIKE lower(:search_pattern) + OR lower(plans.principal_investigator_identifier) LIKE lower(:search_pattern)", + search_pattern: search_pattern) } # Retrieves plan, template, org, phases, sections and questions @@ -486,11 +489,13 @@ def authors # The number of answered questions from the entire plan # # Returns Integer - def num_answered_questions - Answer.where(id: answers.map(&:id)) - .includes(:question_options, question: :question_format) - .to_a - .sum { |answer| answer.is_valid? ? 1 : 0 } + def num_answered_questions(phase = nil) + return answers.select { |answer| answer.answered? }.length unless phase.present? + + answered = answers.select do |answer| + answer.answered? && phase.questions.include?(answer.question) + end + answered.length end # The number of questions for a plan. @@ -526,7 +531,7 @@ def no_questions_matches_no_answers? question: :question_format) .where(id: answer_ids) num_answers = pre_fetched_answers.reduce(0) do |m, a| - m += 1 if a.is_valid? + m += 1 if a.answered? m end num_questions == num_answers diff --git a/app/models/role.rb b/app/models/role.rb index d3ede86ff5..1588897a05 100644 --- a/app/models/role.rb +++ b/app/models/role.rb @@ -82,6 +82,23 @@ class Role < ActiveRecord::Base where(access: access_values) } + + # ================= + # = Class Methods = + # ================= + + ## + # Get the integer values that correspond to a given access flag + # Convert into a condition, take the numerical half, remove formatting + # split on commas, and then convert each to an integer + # + # access - The symbol corresponding to the user's access, i.e. :editor + # + # Returns [Integer] + def self.bit_values(access) + Role.send(:chained_flags_values, 'access', access) + end + # =========================== # = Public instance methods = # =========================== diff --git a/app/models/section.rb b/app/models/section.rb index afa0599031..c7e52e687e 100644 --- a/app/models/section.rb +++ b/app/models/section.rb @@ -103,10 +103,11 @@ def to_s # Returns the number of answered questions for a given plan def num_answered_questions(plan) return 0 if plan.nil? - plan.answers.includes({ question: :question_format }, :question_options) - .where(question_id: question_ids) - .to_a - .count(&:is_valid?) + + answered = plan.answers.select do |answer| + answer.answered? && questions.include?(answer.question) + end + answered.length end def deep_copy(**options) diff --git a/app/models/user.rb b/app/models/user.rb index 199339a849..12febe6e2e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -56,6 +56,7 @@ class User < ActiveRecord::Base include ConditionalUserMailer include ValidationMessages include ValidationValues + extend UniqueRandom include Dmptool::Model::User @@ -330,11 +331,8 @@ def remove_token! # Returns Boolean def keep_or_generate_token! if api_token.nil? || api_token.empty? - self.api_token = loop do - random_token = SecureRandom.urlsafe_base64(nil, false) - break random_token unless User.exists?(api_token: random_token) - end - update_column(:api_token, api_token) unless new_record? + new_token = User.unique_random(field_name: 'api_token') + update_column(:api_token, new_token) unless new_record? end end @@ -395,6 +393,43 @@ def acknowledge(notification) notifications << notification if notification.dismissable? end + # remove personal data from the user account and save + # leave account in-place, with org for statistics (until we refactor those) + # + # Returns boolean + def archive + self.firstname = 'Deleted' + self.surname = 'User' + self.email = User.unique_random(field_name: 'email', + prefix: 'user_', + suffix: Rails.configuration.branding[:application].fetch(:archived_accounts_email_suffix, '@example.org'), + length: 5) + self.recovery_email = nil + self.api_token = nil + self.encrypted_password = nil + self.last_sign_in_ip = nil + self.current_sign_in_ip = nil + self.active = false + return self.save + end + + def merge(to_be_merged) + # merge logic + # => answers -> map id + to_be_merged.answers.update_all(user_id: self.id) + # => notes -> map id + to_be_merged.notes.update_all(user_id: self.id) + # => plans -> map on id roles + to_be_merged.roles.update_all(user_id: self.id) + # => prefs -> Keep's from self + # => auths -> map onto keep id only if keep does not have the identifier + to_be_merged.user_identifiers. + where.not(identifier_scheme_id: self.identifier_scheme_ids) + .update_all(user_id: self.id) + # => ignore any perms the deleted user has + to_be_merged.destroy + end + private # ============================ diff --git a/app/policies/template_policy.rb b/app/policies/template_policy.rb index de4b0bcdff..b70e201675 100644 --- a/app/policies/template_policy.rb +++ b/app/policies/template_policy.rb @@ -1,12 +1,12 @@ class TemplatePolicy < ApplicationPolicy attr_reader :user, :template - + def initialize(user, template = Template.new) raise Pundit::NotAuthorizedError, _("must be logged in") unless user.is_a?(User) @user = user @template = template end - + def index? user.can_super_admin? end @@ -14,11 +14,11 @@ def index? def organisational? user.can_modify_templates? end - + def customisable? user.can_modify_templates? end - + def new? user.can_super_admin? || user.can_modify_templates? end @@ -30,7 +30,7 @@ def create? def show? user.can_super_admin? || (user.can_modify_templates? && template.org_id == user.org_id) end - + def edit? user.can_super_admin? || (user.can_modify_templates? && template.org_id == user.org_id) end @@ -42,7 +42,7 @@ def update? def destroy? user.can_super_admin? || (user.can_modify_templates? && (template.org_id == user.org_id)) end - + def history? user.can_super_admin? || (user.can_modify_templates? && template.org_id == user.org_id) end @@ -55,6 +55,10 @@ def transfer_customization? user.can_super_admin? || user.can_modify_templates? end + def template_export? + user.can_super_admin? || (user.can_modify_templates? && (template.org_id == user.org_id)) + end + # AJAX Calls def copy? user.can_super_admin? || (user.can_modify_templates? && (template.org_id == user.org_id)) @@ -82,4 +86,4 @@ def template_options? end -end \ No newline at end of file +end diff --git a/app/policies/user_policy.rb b/app/policies/user_policy.rb index 4a3bc31491..5293585b4a 100644 --- a/app/policies/user_policy.rb +++ b/app/policies/user_policy.rb @@ -34,11 +34,15 @@ def activate? end def edit? - signed_in_user.can_super_admin? + signed_in_user.can_super_admin? || signed_in_user.can_org_admin? end def update? - signed_in_user.can_super_admin? + signed_in_user.can_super_admin? || signed_in_user.can_org_admin? + end + + def user_plans? + signed_in_user.can_super_admin? || signed_in_user.can_org_admin? end def update_email_preferences? @@ -49,6 +53,18 @@ def acknowledge_notification? true end + def merge? + signed_in_user.can_super_admin? + end + + def archive? + signed_in_user.can_super_admin? + end + + def search? + signed_in_user.can_super_admin? + end + class Scope < Scope def resolve scope.where(org_id: user.org_id) diff --git a/app/views/answers/_status.html.erb b/app/views/answers/_status.html.erb index bddd28fb96..f842fb09bf 100644 --- a/app/views/answers/_status.html.erb +++ b/app/views/answers/_status.html.erb @@ -2,7 +2,7 @@ -<% if answer.is_valid? %> +<% if answer.answered? %> <%= _('Answered')%> <%= _(' by %{user_name}') %{ :user_name => answer.user.name } if answer.user.present? %> diff --git a/app/views/api/v0/plans/index.json.jbuilder b/app/views/api/v0/plans/index.json.jbuilder index 7934bfc837..1ca4cd4de1 100644 --- a/app/views/api/v0/plans/index.json.jbuilder +++ b/app/views/api/v0/plans/index.json.jbuilder @@ -6,6 +6,8 @@ json.array! @plans.each do |plan| json.id plan.id json.title plan.title json.grant_number plan.grant_number + json.last_updated plan.updated_at + json.creation_date plan.created_at json.template do json.title plan.template.title json.id plan.template.family_id @@ -25,7 +27,6 @@ json.array! @plans.each do |plan| end json.users plan.roles.each do |role| json.email role.user.email - end json.description plan.description json.plan_content plan.template.phases.each do |phase| @@ -40,6 +41,9 @@ json.array! @plans.each do |plan| json.number question.number json.format question.question_format.title json.option_based question.question_format.option_based + json.themes question.themes.each do |theme| + json.theme theme.title + end answer = plan.answers.select{ |a| a.question_id = question.id }.first if answer.present? json.answered true diff --git a/app/views/api/v0/statistics/plans.json.jbuilder b/app/views/api/v0/statistics/plans.json.jbuilder index 06cff393c4..fbab651afe 100644 --- a/app/views/api/v0/statistics/plans.json.jbuilder +++ b/app/views/api/v0/statistics/plans.json.jbuilder @@ -4,19 +4,32 @@ json.plans @org_plans.each do |plan| json.id plan.id json.grant_number plan.grant_number json.title plan.title + json.template do json.title plan.template.title json.id plan.template.family_id end + json.funder do json.name (plan.template.org.funder? ? plan.template.org.name : '') end + json.principal_investigator do json.name plan.principal_investigator end + json.data_contact do json.info plan.data_contact end + json.description plan.description -end \ No newline at end of file + json.date_created plan.created_at + json.date_last_updated plan.updated_at + + json.completion do + json.total_questions plan.questions.count + json.answered_questions plan.answers.count + end + +end diff --git a/app/views/branded/contact_us/contacts/new.html.erb b/app/views/branded/contact_us/contacts/new.html.erb index f4169d2e98..e53adf0387 100644 --- a/app/views/branded/contact_us/contacts/new.html.erb +++ b/app/views/branded/contact_us/contacts/new.html.erb @@ -10,7 +10,7 @@

<%= sanitize _('You can find out more about us on our website (new window). %{application_name} is provided by the %{organisation_name}.
If you would like to contact us about %{application_name}, please fill out the form below.') % {organisation_name: Rails.configuration.branding[:organisation][:name], organisation_url: Rails.configuration.branding[:organisation][:url], - application_name: Rails.configuration.branding[:application][:name]}, + application_name: Rails.configuration.branding[:application][:name], open_in_new_window_text: _('Opens in new window') }, tags: %w( a br span em ) %> %>

diff --git a/app/views/branded/devise/registrations/_personal_details.html.erb b/app/views/branded/devise/registrations/_personal_details.html.erb index 981f9949d0..021f50cbd2 100644 --- a/app/views/branded/devise/registrations/_personal_details.html.erb +++ b/app/views/branded/devise/registrations/_personal_details.html.erb @@ -52,17 +52,17 @@ allow_other_orgs: true } %> <% end %> - - <% departments = current_user.org.departments.order(:name) %> - <% if departments.count > 0 %> -
- <% dept_id = current_user.department.nil? ? -1 : current_user.department.id %> - <%= f.label(:department_id, _('Department or school'), class: 'control-label') %> - <%= select_tag("user[department_id]", options_from_collection_for_select(departments, "id", "name", dept_id), include_blank: true, disabled: departments.count === 0, class: "form-control") %> -
- <% end %> + <% departments = current_user.org.departments.order(:name) %> + <% if departments.count > 0 %> +
+ <% dept_id = current_user.department.nil? ? -1 : current_user.department.id %> + <%= f.label(:department_id, _('Department or school'), class: 'control-label') %> + <%= select_tag("user[department_id]", options_from_collection_for_select(departments, "id", "name", dept_id), include_blank: true, disabled: departments.count === 0, class: "form-control") %> +
+ <% end %> + <% if Language.many? %>
<% lang_id = current_user.language.nil? ? Language.id_for(FastGettext.default_locale) : current_user.language.id %> diff --git a/app/views/branded/home/index.html.erb b/app/views/branded/home/index.html.erb index 546741184f..579165a640 100644 --- a/app/views/branded/home/index.html.erb +++ b/app/views/branded/home/index.html.erb @@ -83,12 +83,10 @@
diff --git a/app/views/branded/layouts/_analytics.html.erb b/app/views/branded/layouts/_analytics.html.erb index 7d47fabbaf..e7fed22703 100644 --- a/app/views/branded/layouts/_analytics.html.erb +++ b/app/views/branded/layouts/_analytics.html.erb @@ -1,21 +1,9 @@ <% if Rails.configuration.branding[:keys].present? %> + + <% if Rails.env.stage? %> <% end %> - - <% # this only works without TurboLinks, if we need to add TurboLinks back - # to the application then we need to work around, http://railsapps.github.io/rails-google-analytics.html %> - <% if Rails.env.production? %> - - <% end %> <% end %> diff --git a/app/views/branded/layouts/_constants.html.erb b/app/views/branded/layouts/_constants.html.erb index bd5cfec426..862c3a6765 100644 --- a/app/views/branded/layouts/_constants.html.erb +++ b/app/views/branded/layouts/_constants.html.erb @@ -24,6 +24,8 @@ constants_json = { NO_TEMPLATE_FOUND_ERROR: _('Unable to find a suitable template for the research organisation and funder you selected.'), NEW_PLAN_DISABLED_TOOLTIP: _('Please select a research organisation and funder to continue.'), + OPENS_IN_A_NEW_WINDOW_TEXT: _('Opens in a new window'), + AJAX_LOADING: _('Loading ...'), AJAX_UNABLE_TO_LOAD_TEMPLATE_SECTION: _('Unable to load the section\'s content at this time.'), AJAX_UNABLE_TO_LOAD_TEMPLATE_SECTION_QUESTION: _('Unable to load the question\'s content at this time.') diff --git a/app/views/branded/layouts/_footer.html.erb b/app/views/branded/layouts/_footer.html.erb index b8753ba3f5..fae87839da 100644 --- a/app/views/branded/layouts/_footer.html.erb +++ b/app/views/branded/layouts/_footer.html.erb @@ -13,8 +13,8 @@
  • <%= _('About') %>
  • <%= _('Terms of use') %>
  • <%= _('Privacy statement') %>
  • -
  • <%= _('Accessibility') %> <%= _('new window') %>  
  • -
  • <%= _('Github') %> <%= _('new window') %>  
  • +
  • <%= _('Accessibility') %>
  • +
  • <%= _('Github') %>
  • <%= _('Contact us') %>
  • @@ -26,10 +26,10 @@
    @@ -42,7 +42,7 @@

    <%= sanitize _('DMPTool is a service of the %{uc3} of the %{cdl}') % { - uc3: "University of California Curation Center (new window)", + uc3: "University of California Curation Center (new window)", cdl: "California Digital Library (new window)" } %>
    diff --git a/app/views/branded/layouts/application.html.erb b/app/views/branded/layouts/application.html.erb index 4ecdf4c23c..a7f139557c 100644 --- a/app/views/branded/layouts/application.html.erb +++ b/app/views/branded/layouts/application.html.erb @@ -3,6 +3,17 @@ + + <% gkey = Rails.configuration.branding[:keys][:google_analytics_key] %> + + + <%= content_for?(:title) ? yield(:title) : _('%{application_name}') % { :application_name => Rails.configuration.branding[:application][:name] } %> <%= favicon_link_tag 'apple-touch-icon.png', rel: 'apple-touch-icon', type: 'image/png' %> diff --git a/app/views/branded/paginable/templates/_publicly_visible.html.erb b/app/views/branded/paginable/templates/_publicly_visible.html.erb index 5fa3891b1b..cab1d4cc77 100644 --- a/app/views/branded/paginable/templates/_publicly_visible.html.erb +++ b/app/views/branded/paginable/templates/_publicly_visible.html.erb @@ -3,19 +3,19 @@ - + - - - + + + - + + @@ -55,3 +59,5 @@
    <%= _('Template') %> <%= paginable_sort_link('templates.title') %> <%= _('Download') %> <%= _('Funder') %> <%= paginable_sort_link('orgs.name') %> <%= _('Last Updated') %> <%= paginable_sort_link('templates.updated_at') %> <%= _('Funder Links') %><%= _('Create a new plan') %> <%= _('Sample Plans') %>
    <%= _('(if available)') %> <%= sample_plans_tooltip %> @@ -47,6 +47,10 @@
    <%= sanitize links_to_a_elements(template.links['funder'], '
    ') %>
    + <%= direct_link(template) %> + + <%= sanitize links_to_a_elements(template.links['sample_plan'], '
    ') %>
    + +<%= render 'shared/copy_link_modal' %> diff --git a/app/views/branded/plans/_edit_details.html.erb b/app/views/branded/plans/_edit_details.html.erb new file mode 100644 index 0000000000..4619188e14 --- /dev/null +++ b/app/views/branded/plans/_edit_details.html.erb @@ -0,0 +1,224 @@ +<% project_title_tooltip = _('If applying for funding, state the name exactly as in the grant proposal.') %> +<% project_abstract_tooltip = _("Briefly summarise your research project to help others understand the purposes for which the data are being collected or created.") %> +<% id_tooltip = _('A pertinent ID as determined by the funder and/or organisation.') %> + +

    +
    + <%= form_for plan, html: {method: :put, class: 'form-horizontal edit_plan' } do |f| %> +
    +
    + <%= f.label(:title, _('Project title'), class: 'control-label') %> +
    +
    + <%= project_title_tooltip %> + <%= f.text_field(:title, class: "form-control", "aria-required": true, + 'data-toggle': 'tooltip', spellcheck: true, + title: project_title_tooltip) %> +
    + <%= f.hidden_field :visibility %> + <%= f.label(:is_test, class: 'control-label') do %> + <%= check_box_tag(:is_test, 1, @plan.is_test?, "aria-label": "is_test") %> + <%= _('mock project for testing, practice, or educational purposes') %> + <% end %> +
    +
    +
    +
    +
    + <%= f.label(:funder_name, _('Funder'), class: 'control-label') %> +
    +
    + <%= f.text_field( + :funder_name, + class: "form-control", + spellcheck: true, + "aria-required": false) %> +
    +
    +
    +
    + <%= label_tag(:plan_grant_number_name, _('Grant number'), class: 'control-label') %> +
    + +
    + <%= text_field_tag(:plan_grant_number_name, '', + class: "grant-id-typeahead form-control", + autocomplete: "off", + aria: { required: false }) %> + <%= f.hidden_field(:grant_number) %> + Grant number: <%= @plan.grant_number %> +
    +
    +
    +
    + <%= f.label(:description, _('Project abstract'), class: 'control-label') %> +
    +
    + <%= project_abstract_tooltip %> + <%= f.text_area( + :description, rows: 6, + class: 'form-control tinymce', + "aria-required": false) %> +
    +
    +
    +
    + <%= f.label(:identifier, _('ID'), class: 'control-label') %> +
    +
    + <%= id_tooltip %> + <%= f.text_field(:identifier, class: "form-control", "aria-required": false, + 'data-toggle': "tooltip", spellcheck: true, + title: id_tooltip) %> +
    +
    +
    + <%= _("Principal Investigator") %> +
    +
    + <%= f.label(:principal_investigator, _('Name'), class: 'control-label') %> +
    +
    + <%= f.text_field( + :principal_investigator, + class: "form-control", + "aria-required": false) %> +
    +
    + + + + <%#= f.label(:principal_investigator_identifier, _('ORCID iD'), class: 'control-label') %> + + + <%#= f.text_field( + :principal_investigator_identifier, + class: "form-control", + "aria-required": false) %> + + +
    +
    + <%= f.label(:principal_investigator_email, _('Email'), class: 'control-label') %> +
    +
    + <%= f.email_field( + :principal_investigator_email, + class: "form-control", + "aria-required": false) %> +
    +
    +
    +
    + <%= f.label(:principal_investigator_phone, _('Phone'), class: 'control-label') %> +
    +
    + <%= f.phone_field( + :principal_investigator_phone, + class: "form-control", + "aria-required": false) %> +
    +
    +
    +
    + <%= _('Data contact person') %> +
    + <% checked = ((@plan.data_contact.present? || @plan.data_contact_phone.present? || @plan.data_contact_email.present?) ? 1 : 0) %> + <%= label_tag(:show_data_contact, class: 'control-label') do %> + <%= check_box_tag(:show_data_contact, checked, checked == 0) %> + <%= _('Same as Principal Investigator') %> + <% end %> +
    +
    +
    + <%= f.label(:data_contact, _('Name'), class: 'control-label') %> +
    +
    + <%= f.text_field( + :data_contact, + class: "form-control", + "aria-required": false) %> +
    +
    +
    +
    + <%= f.label(:data_contact_email, _('Email'), class: 'control-label') %> +
    +
    + <%= f.email_field( + :data_contact_email, + class: "form-control", + "aria-required": false) %> +
    +
    +
    +
    + <%= f.label(:data_contact_phone, _('Phone'), class: 'control-label') %> +
    +
    + <%= f.phone_field( + :data_contact_phone, + class: "form-control", + "aria-required": false) %> +
    +
    +
    + <%= f.button(_('Save'), class: "btn btn-default", type: "submit") %> +
    +
    +

    <%= _('Select Guidance') %>

    + + <% if @all_guidance_groups.length > 0 %> +

    <%= _('To help you write your plan, %{application_name} can show you guidance from a variety of organisations.') % + {application_name: Rails.configuration.branding[:application][:name]} %> +

    +
    +

    <%= _('Select up to 6 organisations to see their guidance.') %>

    +
      + <%= render partial: "guidance_choices", + locals: {choices: @important_ggs, form: f, + current_selections: @selected_guidance_groups} %> +
    +
    + + <% if @all_guidance_groups.length > @important_ggs.length %> +

    <%= _('Find guidance from additional organisations below') %>

    + <%= link_to _('See the full list'), '#', 'data-toggle' => 'modal', 'data-target' => '#modal-full-guidances', class: 'modal-guidances-window' %> + <% end %> +
    + <%= f.button(_('Save'), class: "btn btn-default", type: "submit") %> + + <% else %> +

    <%= _("There is no additional guidance for this template.") %>

    + <% end %> +
    + + <% if @all_guidance_groups.length > @important_ggs.length %> + + <% end %> + + <% end %> +
    diff --git a/app/views/branded/plans/index.html.erb b/app/views/branded/plans/index.html.erb new file mode 100644 index 0000000000..102595b4ca --- /dev/null +++ b/app/views/branded/plans/index.html.erb @@ -0,0 +1,51 @@ +<% title _('My Dashboard') %> +
    +
    +

    <%= _('My Dashboard') %>

    + + +

    + <% if @plans.count > 0 %> + <%= _('The table below lists the plans that you have created, and that have been shared with you by others. You can edit, share, download, make a copy, or remove these plans at any time.')%> + <% else %> + <%= _("Welcome") %>
    + <%= _("You are now ready to create your first DMP.") %>
    + <%= _("Click the 'Create plan' button below to begin.")%> + <% end %> +

    +
    +
    +
    +
    + <%= paginable_renderise( + partial: '/paginable/plans/privately_visible', + controller: 'paginable/plans', + action: 'privately_visible', + scope: @plans, + query_params: { sort_field: 'plans.updated_at', sort_direction: 'desc' }) %> +
    +
    + +<%# DMPTool Customization - we already have this link in the nav bar! %> + + + <%#= link_to _('Create plan'), new_plan_path, class: "btn btn-primary" %> + + + +
    +
    + <% if @organisationally_or_publicly_visible.any? && !current_user.org.is_other? %> +

    <%= _('%{org_title} Plans') % { :org_title => current_user.org.name } %>

    +

    <%= _('The table below lists the plans that users at your organisation have created and shared within your organisation. This allows you to download a PDF and view their plans as samples or to discover new research data.') %>

    + <%= paginable_renderise( + partial: '/paginable/plans/organisationally_or_publicly_visible', + controller: 'paginable/plans', + action: 'organisationally_or_publicly_visible', + scope: @organisationally_or_publicly_visible, + query_params: { sort_field: 'plans.title', sort_direction: :asc }) %> + <% end %> +
    +
    + +<%= render 'shared/create_plan_modal' unless @template.nil? %> diff --git a/app/views/branded/static_pages/general_guidance.html.erb b/app/views/branded/static_pages/general_guidance.html.erb index add951ad74..069ed5bb94 100644 --- a/app/views/branded/static_pages/general_guidance.html.erb +++ b/app/views/branded/static_pages/general_guidance.html.erb @@ -197,7 +197,7 @@

    <%= _('Here are some identifier schemes:') %>

    <%= sanitize _('To ethically share confidential data, you may be able to:

    ') % { icpsr_user_url: 'https://www.icpsr.umich.edu/files/DSDR/04701-User_agreement.pdf', icpsr_restricted_url: 'https://www.icpsr.umich.edu/icpsrweb/content/ICPSR/access/restricted/index.html' } %>

    diff --git a/app/views/branded/static_pages/termsuse.html.erb b/app/views/branded/static_pages/termsuse.html.erb index 1f824ed7c8..0d61d07318 100644 --- a/app/views/branded/static_pages/termsuse.html.erb +++ b/app/views/branded/static_pages/termsuse.html.erb @@ -18,7 +18,7 @@

    <%= _('Privacy policy') %>

    -

    <%= sanitize _('The information you enter into this system can be seen by you, people you have chosen to share access with, and—solely for the purposes of maintaining the service—system administrators at the CDL. We compile anonymized, automated, and aggregated information from plans, but we will not directly access, make use of, or share your content with anyone beyond CDL and your home institution without your permission. Authorized users at your home institution may access your plans for specific purposes—for example, to track compliance with funder/institutional requirements, to calculate storage requirements, or to assess demand for data management services across disciplines. For a detailed description of what information (other than the plans) we collect from visitors to this website and how it is used and managed, please see the CDL Privacy Policy and Baseline Supporting Practices listed at %{policies_url}') % {policies_url: 'http://www.cdlib.org/about/policies.html' } %>

    +

    <%= sanitize _('The information you enter into this system can be seen by you, people you have chosen to share access with, and—solely for the purposes of maintaining the service—system administrators at the CDL. We compile anonymized, automated, and aggregated information from plans, but we will not directly access, make use of, or share your content with anyone beyond CDL and your home institution without your permission. Authorized users at your home institution may access your plans for specific purposes—for example, to track compliance with funder/institutional requirements, to calculate storage requirements, or to assess demand for data management services across disciplines. For a detailed description of what information (other than the plans) we collect from visitors to this website and how it is used and managed, please see the CDL Privacy Policy and Baseline Supporting Practices listed at %{policies_url}') % {policies_url: 'https://cdlib.org/about/policies-and-guidelines/privacy-policy/' } %>


    <%= _('Freedom of Information') %>

    diff --git a/app/views/branded/super_admin/users/edit.html.erb b/app/views/branded/super_admin/users/edit.html.erb index 46fd4ef03d..c76afdb2d9 100644 --- a/app/views/branded/super_admin/users/edit.html.erb +++ b/app/views/branded/super_admin/users/edit.html.erb @@ -31,7 +31,7 @@ f: f, default_org: @user.org.is_other? ? nil : @user.org, orgs: Org.participating, - allow_other_orgs: true + allow_other_orgs: true, required: true } %> @@ -59,7 +59,7 @@
    <%= f.button(_('Save'), class: 'btn btn-default', type: "submit", id: "personal_details_registration_form_submit") %> - <%= link_to _('Archive'), super_admin_user_path(id: @user.id), 'data-method': 'delete', rel: 'nofollow', + <%= link_to _('Archive'), archive_super_admin_user_path(id: @user.id), 'data-method': 'put', rel: 'nofollow', 'data-confirm': _("You are about to archive %{user_name}. This will remove their personal information, but retain their plans, answers, and comments. They will be unable to sign-in. Are you sure?") % {user_name: @user.name}, class: 'btn btn-default', role: 'button' %>
    @@ -105,5 +105,4 @@ scope: @plans, query_params: { sort_field: 'plans.updated_at', sort_direction: 'desc' }) %> - diff --git a/app/views/contact_us/contacts/_new_left.html.erb b/app/views/contact_us/contacts/_new_left.html.erb index 1d8f9995dd..4a9d464cc7 100644 --- a/app/views/contact_us/contacts/_new_left.html.erb +++ b/app/views/contact_us/contacts/_new_left.html.erb @@ -22,6 +22,7 @@ <%= f.label(:subject, _('Subject')) %> <%= f.text_field(:subject, class: "form-control", + spellcheck: "true", "aria-required": true) %> <% end %> diff --git a/app/views/contact_us/contacts/new.html.erb b/app/views/contact_us/contacts/new.html.erb index da11501ef5..6a35ac704c 100644 --- a/app/views/contact_us/contacts/new.html.erb +++ b/app/views/contact_us/contacts/new.html.erb @@ -3,9 +3,12 @@

    <%= _("Contact Us") %>

    - <%= sanitize _('%{application_name} is provided by the %{organisation_name}.
    You can find out more about us on our website (new window). If you would like to contact us about %{application_name}, please fill out the form below.') % {organisation_name: Rails.configuration.branding[:organisation][:name], + <%= sanitize _('%{application_name} is provided by the %{organisation_name}.
    You can find out more about us on our website (new window)%{open_in_new_window_text}. If you would like to contact us about %{application_name}, please fill out the form below.') % { + organisation_name: Rails.configuration.branding[:organisation][:name], organisation_url: Rails.configuration.branding[:organisation][:url], - application_name: Rails.configuration.branding[:application][:name]} %> + application_name: Rails.configuration.branding[:application][:name], + open_in_new_window_text: _('Opens in new window') }, + tags: %w( a br span em ) %>

    diff --git a/app/views/guidance_groups/_guidance_group_form.html.erb b/app/views/guidance_groups/_guidance_group_form.html.erb index 4ae1345c0f..b3d63857fa 100644 --- a/app/views/guidance_groups/_guidance_group_form.html.erb +++ b/app/views/guidance_groups/_guidance_group_form.html.erb @@ -1,6 +1,8 @@
    <%= f.label _('Name'), for: :name, class: "control-label" %> - <%= f.text_field :name, as: :string, class: "form-control", 'data-toggle': 'tooltip', title: _('Add an appropriate name for your guidance group. This name will be used to tell the end user where the guidance has come from. It will be appended to text identifying the theme e.g. "[guidance group name]: guidance on data sharing" so we suggest you just use the organisation or department name.'), 'aria-required': true %> + <%= f.text_field :name, as: :string, class: "form-control", 'data-toggle': 'tooltip', + title: _('Add an appropriate name for your guidance group. This name will be used to tell the end user where the guidance has come from. It will be appended to text identifying the theme e.g. "[guidance group name]: guidance on data sharing" so we suggest you just use the organisation or department name.'), + spellcheck: true, 'aria-required': true %>
    diff --git a/app/views/guidance_groups/admin_edit.html.erb b/app/views/guidance_groups/admin_edit.html.erb index 180c1eb200..453e9262d8 100644 --- a/app/views/guidance_groups/admin_edit.html.erb +++ b/app/views/guidance_groups/admin_edit.html.erb @@ -12,7 +12,7 @@
    <%= f.label _('Name'), for: :name, class: "control-label" %> - <%= f.text_field :name, as: :string, class: "form-control", 'aria-required': true, 'data-toggle': 'tooltip', title: _('Add an appropriate name for your guidance group. This name will tell the end user where the guidance has come from. We suggest you use the organisation or department name e.g. "OU" or "Maths & Stats"') %> + <%= f.text_field :name, as: :string, class: "form-control", spellcheck: true, 'aria-required': true, 'data-toggle': 'tooltip', title: _('Add an appropriate name for your guidance group. This name will tell the end user where the guidance has come from. We suggest you use the organisation or department name e.g. "OU" or "Maths & Stats"') %>
    diff --git a/app/views/guidance_groups/admin_new.html.erb b/app/views/guidance_groups/admin_new.html.erb index 095cc41f8f..f59b63d155 100644 --- a/app/views/guidance_groups/admin_new.html.erb +++ b/app/views/guidance_groups/admin_new.html.erb @@ -11,7 +11,7 @@ <%= form_for :guidance_group, url: {action: "admin_create"}, html: {id: 'admin_create_guidance_group_form'} do |f| %>
    <%= f.label _('Name'), for: :name, class: "control-label" %> - <%= f.text_field :name, as: :string, class: "form-control", 'aria-required': true, 'data-toggle': 'tooltip', title: _('Add an appropriate name for your guidance group. This name will tell the end user where the guidance has come from. We suggest you use the organisation or department name e.g. "OU" or "Maths & Stats"') %> + <%= f.text_field :name, as: :string, class: "form-control", spellcheck: true, 'aria-required': true, 'data-toggle': 'tooltip', title: _('Add an appropriate name for your guidance group. This name will tell the end user where the guidance has come from. We suggest you use the organisation or department name e.g. "OU" or "Maths & Stats"') %>
    diff --git a/app/views/guidances/new_edit.html.erb b/app/views/guidances/new_edit.html.erb index b4b1e1af7c..9fc401b5d8 100644 --- a/app/views/guidances/new_edit.html.erb +++ b/app/views/guidances/new_edit.html.erb @@ -7,6 +7,7 @@ else method = "POST" end %> +<% guidance_text_tooltip = _('Enter your guidance here. You can include links where needed.') %> <% title _('Guidance') %> <%# locals: { guidance, themes, guidance_groups, options } %> @@ -19,7 +20,8 @@ end
    <%= form_for(@guidance, url: url, html: { method: method , id: 'new_edit_guidance'}) do |f| %> -
    +
    + <%= guidance_text_tooltip %> <%= f.label :text, class: 'control-label' %> <%= text_area_tag("guidance-text", @guidance.text, class: "form-control", 'aria-required': true, rows: 10) %>
    diff --git a/app/views/layouts/_branding.html.erb b/app/views/layouts/_branding.html.erb index 7f81665292..f951d534c7 100644 --- a/app/views/layouts/_branding.html.erb +++ b/app/views/layouts/_branding.html.erb @@ -10,11 +10,10 @@ <% if user_signed_in? && !current_user.org.nil? %> <% if current_user.org.logo.present? %> - <%= link_to(image_tag(logo_url_for_org(current_user.org), + <%= image_tag(logo_url_for_org(current_user.org), alt: current_user.org.name, class: "org-logo", - title: current_user.org.name), - current_user.org.target_url) %> + title: current_user.org.name) %> <% else %> <% end %> @@ -31,10 +30,11 @@ <% if i.odd? %>
    diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index fe06cd747d..469bd62b49 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -100,7 +100,8 @@ AJAX_LOADING: _('Loading ...'), AJAX_UNABLE_TO_LOAD_TEMPLATE_SECTION: _('Unable to load the section\'s content at this time.'), - AJAX_UNABLE_TO_LOAD_TEMPLATE_SECTION_QUESTION: _('Unable to load the question\'s content at this time.') + AJAX_UNABLE_TO_LOAD_TEMPLATE_SECTION_QUESTION: _('Unable to load the question\'s content at this time.'), + OPENS_IN_A_NEW_WINDOW_TEXT: _('Opens in a new window'), }.to_json %> diff --git a/app/views/org_admin/annotations/_form.html.erb b/app/views/org_admin/annotations/_form.html.erb index da2089fbe0..f6929ca165 100644 --- a/app/views/org_admin/annotations/_form.html.erb +++ b/app/views/org_admin/annotations/_form.html.erb @@ -1,7 +1,9 @@
    ">
    - <%= f.label(:type, f.object.type.humanize, class: "control-label") %> + <% lbl = f.object.type.humanize.downcase == 'example answer' ? _('Example answer') : _('Guidance') %> + <%= f.label(:type, lbl, class: "control-label") %>
    + <%= tooltip_for_annotation_text(f.object) %> <%= f.text_area(:text, class: 'question', id: "question_annotations_attributes_#{unique_dom_id(f.object)}_text") %>
    diff --git a/app/views/org_admin/departments/edit.html.erb b/app/views/org_admin/departments/edit.html.erb index e62cd5b82b..06aafff09f 100644 --- a/app/views/org_admin/departments/edit.html.erb +++ b/app/views/org_admin/departments/edit.html.erb @@ -12,7 +12,7 @@ <%= f.hidden_field :org_id, value: @org_id %>
    <%= f.label _('Name'), for: :name, class: "control-label" %> - <%= f.text_field :name, as: :string, class: "form-control", 'aria-required': true, 'data-toggle': 'tooltip', title: _('Add the name of a school/department.') %> + <%= f.text_field :name, as: :string, class: "form-control", spellcheck: true, 'aria-required': true, 'data-toggle': 'tooltip', title: _('Add the name of a school/department.') %>
    <%= f.label _('Abbreviated name or code'), for: :code, class: "control-label" %> diff --git a/app/views/org_admin/departments/new.html.erb b/app/views/org_admin/departments/new.html.erb index 3e2d3c06f1..0911ab5db1 100644 --- a/app/views/org_admin/departments/new.html.erb +++ b/app/views/org_admin/departments/new.html.erb @@ -12,7 +12,7 @@ <%= f.hidden_field :org_id, value: @org_id %>
    <%= f.label _('Name'), for: :name, class: "control-label" %> - <%= f.text_field :name, as: :string, class: "form-control", 'aria-required': true, 'data-toggle': 'tooltip', title: _('Add the name of a school/department.') %> + <%= f.text_field :name, as: :string, class: "form-control", spellcheck: true, 'aria-required': true, 'data-toggle': 'tooltip', title: _('Add the name of a school/department.') %>
    <%= f.label _('Abbreviated name or code'), for: :code, class: "control-label" %> diff --git a/app/views/org_admin/phases/_form.html.erb b/app/views/org_admin/phases/_form.html.erb index 131f7d2941..ab23b2da64 100644 --- a/app/views/org_admin/phases/_form.html.erb +++ b/app/views/org_admin/phases/_form.html.erb @@ -1,7 +1,10 @@ +<% title_tooltip = _('Enter a title for the phase e.g. initial DMP, full DMP... This is what users will see in the tabs when completing a plan. If you only have one phase, call it something generic e.g. Glasgow DMP') %> + <%= f.hidden_field :template_id, value: template.id%>
    <%= f.label(:title, _('Title') ,class: "control-label") %> - <%= f.text_field(:title, class: "form-control", 'aria-required': true, 'data-toggle': 'tooltip', title: _('Enter a title for the phase e.g. intial DMP, full DMP... This is what users will see in the tabs when completing a plan. If you only have one phase, call it something generic e.g. Glasgow DMP')) %> + <%= title_tooltip %> + <%= f.text_field(:title, class: "form-control", spellcheck: true, 'aria-required': true, 'data-toggle': 'tooltip', title: title_tooltip ) %>
    @@ -18,6 +21,6 @@ <%= f.text_area(:description, class: "phase") %>
    -
    +
    <%= f.button(_('Save'), class: 'btn btn-default', type: "submit") %>
    \ No newline at end of file diff --git a/app/views/org_admin/plans/index.html.erb b/app/views/org_admin/plans/index.html.erb index 297139dd2c..32c8838c32 100644 --- a/app/views/org_admin/plans/index.html.erb +++ b/app/views/org_admin/plans/index.html.erb @@ -37,7 +37,12 @@
    <% end %> <% if @plans.length > 0 %> - <%= link_to sanitize(_('Download plans (new window)')), org_admin_download_plans_path(format: :csv), target: '_blank', class: 'btn btn-default pull-right' %> + <%= link_to sanitize(_('Download plans (new window)%{open_in_new_window_text}') % + { open_in_new_window_text: _('Opens in new window') }, + tags: %w{ span em }), + org_admin_download_plans_path(format: :csv), + target: '_blank', + class: 'btn btn-default pull-right has-new-window-popup-info' %> <%= paginable_renderise( partial: '/paginable/plans/org_admin', controller: 'paginable/plans', diff --git a/app/views/org_admin/question_options/_option_fields.html.erb b/app/views/org_admin/question_options/_option_fields.html.erb index ab836c5bbf..4e78540ecb 100644 --- a/app/views/org_admin/question_options/_option_fields.html.erb +++ b/app/views/org_admin/question_options/_option_fields.html.erb @@ -25,9 +25,9 @@
    <% if i == 1 %> - <%= op.text_field :text, as: :string, class: 'form-control', 'aria-required': true %> + <%= op.text_field :text, as: :string, class: 'form-control', spellcheck: true, 'aria-required': true %> <% else %> - <%= op.text_field :text, as: :string, class: 'form-control' %> + <%= op.text_field :text, as: :string, class: 'form-control', spellcheck: true %> <% end %>
    diff --git a/app/views/org_admin/questions/_form.html.erb b/app/views/org_admin/questions/_form.html.erb index 3e7f181318..bbe8f5910a 100644 --- a/app/views/org_admin/questions/_form.html.erb +++ b/app/views/org_admin/questions/_form.html.erb @@ -1,3 +1,5 @@ +<% question_default_value_tooltip = _('Anything you enter here will display in the answer box. If you want an answer in a certain format (e.g. tables), you can enter that style here.') %> +

    <%= question.id.present? ? _('Question %{number}:') % { number: question.number } : _('New question:') %>

    @@ -56,9 +58,10 @@
    <%= f.label(:default_value, _('Default answer'), class: "control-label") %> -
    +
    + <%= question_default_value_tooltip %> - <%= f.text_field(:default_value, class: 'form-control') %> + <%= f.text_field(:default_value, class: 'form-control', spellcheck: true) %> <%= text_area_tag('question[default_value]', question.default_value, id: "#{question.id.present? ? question.id : 'new'}_question_default_value_area", class: "form-control question") %> diff --git a/app/views/org_admin/sections/_form.html.erb b/app/views/org_admin/sections/_form.html.erb index 951b2eee77..85587c806f 100644 --- a/app/views/org_admin/sections/_form.html.erb +++ b/app/views/org_admin/sections/_form.html.erb @@ -1,10 +1,13 @@ +<% description_tooltip = _("Enter a basic description. This could be a summary of what is covered in the section or instructions on how to answer. This text will be displayed in the coloured banner once a section is opened to edit.") %> + <%= form_for(section, url: url, namespace: section.id.present? ? section.id : 'new_section', html: { method: method }) do |f| %>
    <%= f.label(:title, _('Title') ,class: "control-label") %> - <%= f.text_field(:title, { class: "form-control", placeholder: _('Enter a title for the section'), 'data-toggle': 'tooltip', title: _('Enter a title for the section'), 'aria-required': true} ) %> + <%= f.text_field(:title, { class: "form-control", placeholder: _('Enter a title for the section'), 'data-toggle': 'tooltip', title: _('Enter a title for the section'), spellcheck: true, 'aria-required': true} ) %>
    -
    "> +
    + <%= description_tooltip %> <%= f.label(:description, _('Description'), class: "control-label") %> <%= f.text_area(:description, class: "section") %>
    diff --git a/app/views/org_admin/templates/_form.html.erb b/app/views/org_admin/templates/_form.html.erb index 146b11dca3..d2e67950e6 100644 --- a/app/views/org_admin/templates/_form.html.erb +++ b/app/views/org_admin/templates/_form.html.erb @@ -1,9 +1,12 @@ +<% description_tooltip = _('Enter a description that helps you to differentiate between templates e.g. if you have ones for different audiences') %> +
    <%= f.label(:title, _('Title'), class: "control-label") %> - <%= f.text_field(:title, class: "form-control", "aria-required": true) %> + <%= f.text_field(:title, class: "form-control", spellcheck: true, "aria-required": true) %>
    -
    +
    + <%= description_tooltip %> <%= f.label(:description, _('Description'), class: "control-label") %> <%= f.text_area(:description, class: "template") %>
    @@ -17,8 +20,7 @@ placement: 'right' }%>
    <%= f.label(:visibility) do %> - <%= check_box_tag('template_visibility', '0', - (f.object.visibility == 'organisationally_visible')) %> + <%= f.check_box(:visibility, checked: f.object.visibility == 'organisationally_visible') %> <%= _('for internal %{org_name} use only') % { org_name: f.object.org.name } %> <% end %> diff --git a/app/views/org_admin/users/edit.html.erb b/app/views/org_admin/users/edit.html.erb new file mode 100644 index 0000000000..3bb0ec3ca2 --- /dev/null +++ b/app/views/org_admin/users/edit.html.erb @@ -0,0 +1,76 @@ +
    +
    +

    + <%= _('Editing profile for %{username}') % { username: @user.name(false) } %> + <%= link_to(_('View all users'), admin_index_users_path, class: 'btn btn-default pull-right', role: 'button') %> +

    +
    +
    + +
    +
    + <%= form_for(@user, namespace: :orgadmin, as: :user, url: org_admin_user_path(@user), html: {method: :put, id: 'org_admin_user_edit' }) do |f| %> +
    + <%= f.label(:email, _('Email'), class: 'control-label') %> + <%= f.email_field(:email, class: "form-control", "disabled": true) %> +
    + +
    + <%= f.label(:firstname, _('First name'), class: 'control-label') %> + <%= f.text_field(:firstname, class: "form-control", "disabled": true) %> +
    + +
    + <%= f.label(:surname, _('Last name'), class: 'control-label') %> + <%= f.text_field(:surname, class: "form-control", "disabled": true) %> +
    + + <% if @departments.any? %> +
    + <% dept_id = @user.department.nil? ? -1 : @user.department.id %> + <%= f.label(:department_id, _('Department or school'), class: 'control-label') %> + <%= select_tag(:department_id, + options_from_collection_for_select(@departments, "id", "name", dept_id), + include_blank: true, + class: "form-control", + name: 'user[department_id]') %> +
    + <% end %> + + <% if Language.many? %> +
    + <% lang_id = @user.language.nil? ? Language.id_for(FastGettext.default_locale) : @user.language.id %> + <%= f.label(:language_id, _('Language'), class: 'control-label') %> + <%= select_tag(:org_admin_user_language_id, + options_from_collection_for_select(Language.sorted_by_abbreviation, "id", "name", lang_id), + disabled: true, + class: "form-control", name: 'org_admin_user[language_id]') %> +
    + <% end %> + +
    + + <% if @departments.any? %> + <%= f.button(_('Save'), class: 'btn btn-default', type: "submit", id: "personal_details_registration_form_submit") %> + <% end %> +
    + <% end %> +
    +
    + +
    +
    +

    <%= _('Plans') % { username: @user.name(false) } %>

    + +
    +
    +
    +
    + <%= paginable_renderise( + partial: '/paginable/plans/org_admin_other_user', + controller: 'paginable/plans', + action: 'org_admin_other_user', + scope: @plans, + query_params: { sort_field: 'plans.updated_at', sort_direction: 'desc' }) %> +
    +
    diff --git a/app/views/org_admin/users/plans.html.erb b/app/views/org_admin/users/plans.html.erb new file mode 100644 index 0000000000..f8b1ba0cad --- /dev/null +++ b/app/views/org_admin/users/plans.html.erb @@ -0,0 +1,16 @@ +
    +
    +

    <%= _('Plans of %{username}') % { username: @user.name(false) } %>

    + +
    +
    +
    +
    + <%= paginable_renderise( + partial: '/paginable/plans/org_admin_other_user', + controller: 'paginable/plans', + action: 'org_admin_other_user', + scope: @plans, + query_params: { sort_field: 'plans.updated_at', sort_direction: 'desc' }) %> +
    +
    diff --git a/app/views/orgs/_departments.html.erb b/app/views/orgs/_departments.html.erb index 6357d01abd..5a4f020bfb 100644 --- a/app/views/orgs/_departments.html.erb +++ b/app/views/orgs/_departments.html.erb @@ -13,4 +13,3 @@ <%= _('Create school/department') %>
    -
    \ No newline at end of file diff --git a/app/views/orgs/_profile_form.html.erb b/app/views/orgs/_profile_form.html.erb index 6e8c33f8f0..439911bb51 100644 --- a/app/views/orgs/_profile_form.html.erb +++ b/app/views/orgs/_profile_form.html.erb @@ -1,3 +1,8 @@ +<% + shared_links_tooltip = _('Links will be displayed next to your organisation\'s logo') + org_config_info_tooltip = _('This information can only be changed by a system administrator. Contact the Help Desk if you have questions or to request changes.') +%> + <%= form_for(org, url: url, html: { multipart: true, method: method, id: "edit_org_profile_form" } ) do |f| %>
    @@ -36,17 +41,18 @@
    + <%= shared_links_tooltip %> <%= render(partial: '/shared/links', locals: { context: 'org', title: _('Organisation URLs'), links: (org.links.present? ? org.links['org'] : []), - max_number_links: MAX_NUMBER_LINKS_ORG, - tooltip: _('Links will be displayed next to your organisation\'s logo') }) %> + max_number_links: MAX_NUMBER_LINKS_FUNDER, + tooltip: shared_links_tooltip }) %> <%= hidden_field_tag('org_links', value: org.links) %>
    - +

    <%= _("Administrator contact") %>

    @@ -63,8 +69,8 @@
    -
    -

    <%= _('Organisational Configuration Information') %>

    +
    +

    <%= _('Organisational Configuration Information') %><%= org_config_info_tooltip %>

    <% if current_user.can_super_admin? %> <% if Rails.application.config.shibboleth_use_filtered_discovery_service %> <% shibboleth = org.org_identifiers.select{ |ids| ids.identifier_scheme == IdentifierScheme.find_by(name: 'shibboleth')} %> @@ -75,7 +81,7 @@
    <%= f.label :shib_id, _('Shibboleth Entity Id'), class: "control-label" %> - <%= text_field_tag :shib_id, shib_id, class: "form-control", placeholder: _('Example: urn:mace:incommon:my-org.org') %> + <%= text_field_tag :shib_id, shib_id, class: "form-control", placeholder: _('Example: https://idp.my-org.org/... or urn:mace:...') %>
    diff --git a/app/views/paginable/plans/_org_admin_other_user.html.erb b/app/views/paginable/plans/_org_admin_other_user.html.erb new file mode 100644 index 0000000000..1ea1cd663b --- /dev/null +++ b/app/views/paginable/plans/_org_admin_other_user.html.erb @@ -0,0 +1,34 @@ +
    + + + + + + + + + + + + + <% scope.each do |plan| %> + + + + + + + + + <% end %> + +
    <%= _('Project Title') %> <%= paginable_sort_link('plans.title') %><%= _('Template') %> <%= paginable_sort_link('templates.title') %><%= _('Organisation') %><%= _('Owner') %><%= _('Updated') %> <%= paginable_sort_link('plans.updated_at') %><%= _('Visibility') %>
    + <% if plan.readable_by?(current_user.id) %> + <%= link_to "#{plan.title.length > 60 ? "#{plan.title[0..59]} ..." : plan.title}", plan_path(plan) %> + <% else %> + <%= plan.title.truncate(60) %> + <% end %> + <%= plan.template.title %><%= plan.owner.org.name %><%= plan.owner.name(false) %><%= l(plan.updated_at.to_date, formats: :short) %> + <%= plan.visibility === 'is_test' ? _('Test') : sanitize(display_visibility(plan.visibility)) %> +
    +
    diff --git a/app/views/paginable/plans/_organisationally_or_publicly_visible.html.erb b/app/views/paginable/plans/_organisationally_or_publicly_visible.html.erb index 845b7a1297..76b29e81e8 100644 --- a/app/views/paginable/plans/_organisationally_or_publicly_visible.html.erb +++ b/app/views/paginable/plans/_organisationally_or_publicly_visible.html.erb @@ -32,9 +32,11 @@ <%= l(plan.updated_at.to_date, formats: :short) %> <%= link_to plan_export_path(plan, format: :pdf), + class: 'has-new-window-popup-info', target: '_blank' do %> <%= _('(new window)') %> + <%= _('Opens in new window') %> <% end %> diff --git a/app/views/paginable/plans/_privately_visible.html.erb b/app/views/paginable/plans/_privately_visible.html.erb index 3c12466446..04947a053a 100644 --- a/app/views/paginable/plans/_privately_visible.html.erb +++ b/app/views/paginable/plans/_privately_visible.html.erb @@ -7,6 +7,8 @@ <%= _('Edited') %> <%= paginable_sort_link('plans.updated_at') %> <%= _('Role') %> <%= _('Test') %> + <%= _('Visibility') %> + <%= _('Shared') %> <%= _('Actions') %> diff --git a/app/views/paginable/plans/_publicly_visible.html.erb b/app/views/paginable/plans/_publicly_visible.html.erb index 59b30d54ec..52cd1f838e 100644 --- a/app/views/paginable/plans/_publicly_visible.html.erb +++ b/app/views/paginable/plans/_publicly_visible.html.erb @@ -18,9 +18,10 @@ <%= (plan.owner.nil? ? _('Unknown') : plan.owner.name(false)) %> <%= link_to plan_export_path(plan, format: :pdf), - class: "dmp_table_link", target: '_blank' do %> + class: "dmp_table_link has-new-window-popup-info", target: '_blank' do %> <%= _('(new window)') %> + <%= _('Opens in new window') %> <% end %> diff --git a/app/views/paginable/templates/_customisable.html.erb b/app/views/paginable/templates/_customisable.html.erb index 7e93f320ec..293c3386c2 100644 --- a/app/views/paginable/templates/_customisable.html.erb +++ b/app/views/paginable/templates/_customisable.html.erb @@ -7,7 +7,7 @@ <%= _('Funder') %> <%= paginable_sort_link('orgs.name') %> <%= _('Status') %> <%= _('Edited Date') %> <%= paginable_sort_link('templates.updated_at') %> -   +   @@ -77,4 +77,4 @@ <% end %> -
    \ No newline at end of file +
    diff --git a/app/views/paginable/templates/_history.html.erb b/app/views/paginable/templates/_history.html.erb index 0869325420..97ee1d22f3 100644 --- a/app/views/paginable/templates/_history.html.erb +++ b/app/views/paginable/templates/_history.html.erb @@ -3,6 +3,7 @@ <%= _('Title') %> <%= paginable_sort_link('templates.title') %> + <%= _('Download') %> <%= _('Version') %> <%= paginable_sort_link('templates.version') %> <%= _('Published') %> <%= paginable_sort_link('templates.published') %> <%= _('Last updated') %> <%= paginable_sort_link('templates.updated_at') %> @@ -18,6 +19,22 @@     <%=_('Draft')%> <% end %> + + <%= link_to template_export_org_admin_template_url(template, format: :docx), + target: '_blank', + class: 'has-new-window-popup-info' do %> + + <%= _('(new window)') %> + <%= _('Opens in new window') %> + <% end %> + <%= link_to template_export_org_admin_template_url(template, format: :pdf), + target: '_blank', + class: 'has-new-window-popup-info' do %> + + <%= _('(new window)') %> + <%= _('Opens in new window') %> + <% end %> + <%= template.version %> @@ -46,4 +63,4 @@ <% end %> -
    \ No newline at end of file +
    diff --git a/app/views/paginable/templates/_organisational.html.erb b/app/views/paginable/templates/_organisational.html.erb index 46fa9982bb..0fdba4df2a 100644 --- a/app/views/paginable/templates/_organisational.html.erb +++ b/app/views/paginable/templates/_organisational.html.erb @@ -1,4 +1,6 @@ <% # locals: templates %> +<% export_as_pdf = _('Download') %> +
    @@ -12,7 +14,7 @@ <% if action_name != 'index' %> - + <% end %> @@ -74,6 +76,19 @@ 'data-confirm': _('Are you sure you want to remove "%{template_title}"? Any published versions will become unavailable to users.') % { template_title: template.title} %> <% end %> +
  • <%= link_to template_export_org_admin_template_url(template, format: :pdf), + title: export_as_pdf, + target: '_blank', + class: 'has-new-window-popup-info' do %> + <%= export_as_pdf %> + <%= _('(new window)') %> + <%= _('Opens in new window') %> + <% end %> +
  • +
  • + <%= direct_link(template, true) %> + <%= _('Copy link') %> +
  • @@ -82,4 +97,6 @@ <% end %>
    <%= _('Status') %> <%= _('Edited Date') %> <%= paginable_sort_link('templates.updated_at') %>  
    -
    \ No newline at end of file +
    + +<%= render 'shared/copy_link_modal' %> diff --git a/app/views/paginable/templates/_publicly_visible.html.erb b/app/views/paginable/templates/_publicly_visible.html.erb index ec3e45a8c5..17e89c6fea 100644 --- a/app/views/paginable/templates/_publicly_visible.html.erb +++ b/app/views/paginable/templates/_publicly_visible.html.erb @@ -1,3 +1,4 @@ +<% sample_plans_tooltip = _('Sample plans are provided by a funder, an organisation or a trusted party.') %>
    @@ -7,7 +8,11 @@ - + + @@ -15,13 +20,19 @@ @@ -29,6 +40,10 @@ + @@ -37,3 +52,5 @@
    <%= _('Organisation Name') %> <%= paginable_sort_link('orgs.name') %> <%= _('Last Updated') %> <%= paginable_sort_link('templates.updated_at') %> <%= _('Funder Links') %><%= _('Sample Plans') %>
    <%= _('(if available)') %>
    <%= _('Create a new plan') %> + <%= _('Sample Plans') %>
    <%= _('(if available)') %> + <%= sample_plans_tooltip %> +
    <%= template.title %> - <%= link_to template_export_path(template.family_id, format: :docx), target: '_blank' do %> + <%= link_to template_export_path(template.family_id, format: :docx), + target: '_blank', + class: 'has-new-window-popup-info' do %> <%= _('(new window)') %> + <%= _('Opens in new window') %> <% end %> - <%= link_to template_export_path(template.family_id, format: :pdf), target: '_blank' do %> + <%= link_to template_export_path(template.family_id, format: :pdf), + target: '_blank', + class: 'has-new-window-popup-info' do %> <%= _('(new window)') %> + <%= _('Opens in new window') %> <% end %> <%= template.org.name %> <%= sanitize links_to_a_elements(template.links['funder'], '
    ') %>
    + <%= direct_link(template) %> + + <%= sanitize links_to_a_elements(template.links['sample_plan'], '
    ') %>
    + +<%= render 'shared/copy_link_modal' %> diff --git a/app/views/paginable/users/_index.html.erb b/app/views/paginable/users/_index.html.erb index eb1eabe7c2..024f6ab407 100644 --- a/app/views/paginable/users/_index.html.erb +++ b/app/views/paginable/users/_index.html.erb @@ -1,4 +1,5 @@ <% is_super_admin = current_user.can_super_admin? %> +<% is_org_admin = current_user.can_org_admin? %>
    @@ -23,7 +24,13 @@ <% if !user.name.nil? %> - <%= is_super_admin ? link_to(user.name(false), edit_super_admin_user_path(user)) : user.name(false) %> + <% if is_super_admin %> + <%= link_to(user.name(false), edit_super_admin_user_path(user)) %> + <% elsif is_org_admin %> + <%= link_to(user.name(false), edit_org_admin_user_path(user)) %> + <% else %> + <%= user.name(false) %> + <% end %> <% else %> <%= is_super_admin ? link_to(_('Edit Profile'), edit_user_registration_path(user)) : '' %> <% end %> @@ -43,9 +50,15 @@ <% end %> - <% unless user.roles.nil? %> - <%= user.roles.length %> + <% roles = user.roles.select(&:active) %> + <% if roles.any? %> + <% roles_length = roles.length %> + <% if is_super_admin || is_org_admin %> + <%= link_to(roles_length, user_plans_org_admin_user_path(user)) %> + <% else %> + <%= roles_length %> <% end %> + <% end %> <%# The content of this column get updated through AJAX whenever the permission for an user are updated %> diff --git a/app/views/phases/_guidances_notes.html.erb b/app/views/phases/_guidances_notes.html.erb index 9f7fba2895..8c6937e929 100644 --- a/app/views/phases/_guidances_notes.html.erb +++ b/app/views/phases/_guidances_notes.html.erb @@ -34,6 +34,7 @@ aria-controls="<%= "#guidance_per_question_#{question.id}_#{i}" %>" role="tab" data-toggle="tab" + tabindex="0" class="view-plan-guidance"> <%= tab[:name] %> diff --git a/app/views/plans/_download_form.html.erb b/app/views/plans/_download_form.html.erb index 7a4377ea62..336de7d2a4 100644 --- a/app/views/plans/_download_form.html.erb +++ b/app/views/plans/_download_form.html.erb @@ -113,5 +113,8 @@
    - <%= button_tag(sanitize(_('Download Plan (new window)')), class: "btn btn-primary", type: "submit") %> + <%= button_tag(sanitize(_("Download Plan (new window)%{open_in_new_window_text}") % { open_in_new_window_text: _('Opens in new window') }, + tags: %w{ span em }), + class: "btn btn-primary has-new-window-popup-info", + type: "submit") %> <% end %> diff --git a/app/views/plans/_edit_details.html.erb b/app/views/plans/_edit_details.html.erb index 0475ecc706..375e84c0ee 100644 --- a/app/views/plans/_edit_details.html.erb +++ b/app/views/plans/_edit_details.html.erb @@ -1,3 +1,7 @@ +<% project_title_tooltip = _('If applying for funding, state the name exactly as in the grant proposal.') %> +<% project_abstract_tooltip = _("Briefly summarise your research project to help others understand the purposes for which the data are being collected or created.") %> +<% id_tooltip = _('A pertinent ID as determined by the funder and/or organisation.') %> +
    <%= form_for plan, html: {method: :put, class: 'form-horizontal edit_plan' } do |f| %> @@ -6,8 +10,10 @@ <%= f.label(:title, _('Project title'), class: 'control-label') %>
    - <%= f.text_field(:title, class: "form-control", "aria-required": true, 'data-toggle': 'tooltip', - title: _('If applying for funding, state the name exactly as in the grant proposal.')) %> + <%= project_title_tooltip %> + <%= f.text_field(:title, class: "form-control", "aria-required": true, + 'data-toggle': 'tooltip', spellcheck: true, + title: project_title_tooltip) %>
    <%= f.hidden_field :visibility %> <%= f.label(:is_test, class: 'control-label') do %> @@ -25,6 +31,7 @@ <%= f.text_field( :funder_name, class: "form-control", + spellcheck: true, "aria-required": false) %>
    @@ -46,7 +53,8 @@
    <%= f.label(:description, _('Project abstract'), class: 'control-label') %>
    -
    "> +
    + <%= project_abstract_tooltip %> <%= f.text_area( :description, rows: 6, class: 'form-control tinymce', @@ -58,8 +66,10 @@ <%= f.label(:identifier, _('ID'), class: 'control-label') %>
    - <%= f.text_field(:identifier, class: "form-control", "aria-required": false, 'data-toggle': "tooltip", - title: _('A pertinent ID as determined by the funder and/or organisation.')) %> + <%= id_tooltip %> + <%= f.text_field(:identifier, class: "form-control", "aria-required": false, + 'data-toggle': "tooltip", spellcheck: true, + title: id_tooltip) %>
    diff --git a/app/views/plans/_navigation.html.erb b/app/views/plans/_navigation.html.erb index 7fac168e65..0bdb7bf1b1 100644 --- a/app/views/plans/_navigation.html.erb +++ b/app/views/plans/_navigation.html.erb @@ -18,6 +18,11 @@ <%= _('Share') %> <% end %> + <% if (plan.administerable_by?(current_user) || (current_user.can_org_admin? && current_user.org.plans.include?(plan))) && plan.owner_and_coowners.include?(current_user) && plan.owner.org.feedback_enabled? %> + + <% end %> <% if plan.readable_by?(current_user.id) %>
    -
    \ No newline at end of file +
    diff --git a/app/views/plans/_overview_details.html.erb b/app/views/plans/_overview_details.html.erb index 804e47175b..0cbe818689 100644 --- a/app/views/plans/_overview_details.html.erb +++ b/app/views/plans/_overview_details.html.erb @@ -16,7 +16,7 @@

    <%= _('Template version %{template_version}, published on %{published_date}') \ %{ :template_version => plan.template.version, \ - :published_date => l(plan.updated_at.to_date, format: :readable) } %> + :published_date => l(plan.template.updated_at.to_date, format: :readable) } %>

    diff --git a/app/views/plans/_progress.html.erb b/app/views/plans/_progress.html.erb index 1ad22186ff..650bd05dc3 100644 --- a/app/views/plans/_progress.html.erb +++ b/app/views/plans/_progress.html.erb @@ -1,6 +1,6 @@ <%# locals: { plan, current_phase } %> <% - nanswers = current_phase.num_answered_questions(plan) + nanswers = plan.num_answered_questions(current_phase) nquestions = current_phase.num_questions() value=(nanswers.to_f/nquestions*100).round(2) %> diff --git a/app/views/plans/_request_feedback_form.html.erb b/app/views/plans/_request_feedback_form.html.erb new file mode 100644 index 0000000000..fdaf700544 --- /dev/null +++ b/app/views/plans/_request_feedback_form.html.erb @@ -0,0 +1,21 @@ +<% administerable = @plan.administerable_by?(current_user) %> + +<% if administerable %> +
    + <% if plan.owner_and_coowners.include?(current_user) && plan.owner.org.feedback_enabled? %> +

    <%= _('Request expert feedback') %>

    +

    <%= _("Click below to give data management staff at #{plan.owner.org.name}, the Plan Owner's org, access to read and comment on your plan.") %>

    +
    + <%= sanitize plan.owner.org.feedback_email_msg.to_s % { user_name: current_user.name(false), plan_name: plan.title } %> +
    +

    <%= _('You can continue to edit and download the plan in the interim.') %>

    +
    + <%= link_to _('Request feedback'), + feedback_requests_path(plan_id: @plan.id), + data: { method: 'post' }, + class: "btn btn-default#{' disabled' if @plan.feedback_requested?}" %> + <%= _("Feedback has been requested.") if @plan.feedback_requested? %> +
    + <% end %> +
    +<% end %> diff --git a/app/views/plans/_share_form.html.erb b/app/views/plans/_share_form.html.erb index 28d2317297..b0e509d565 100644 --- a/app/views/plans/_share_form.html.erb +++ b/app/views/plans/_share_form.html.erb @@ -2,6 +2,8 @@ <% editor = Role.new(editor: true, commenter: true) %> <% commenter = Role.new(commenter: true) %> <% administerable = @plan.administerable_by?(current_user) %> +<% email_tooltip = _("Enter the email address of your collaborator: If they are already using #{Rails.configuration.branding[:application][:name]}, they will see this plan on their dashboard, and recieve an email. If they are not currently using #{Rails.configuration.branding[:application][:name]}, they will recieve an email inviting them to the tool so they can collaborate on your plan.") %> +<% permissions_tooltip = _('Co-owner: Has admin-rights to the plan (can invite other users, view the plan, answer questions, or comment). Editor: Has edit-rights to the plan (can view the plan, answer questions, or comment). Read Only: Has read-rights to the plan (can view the plan or comment)') %>

    <%= _('Set plan visibility') %>

    <%= _('Public or organisational visibility is intended for finished plans. You must answer at least %{percentage}%% of the questions to enable these options. Note: test plans are set to private visibility by default.') % { :percentage => Rails.application.config.default_plan_percentage_answered } %>

    @@ -92,36 +94,38 @@ <%= f.hidden_field :plan_id %> <%= f.fields_for :user do |user| %> <%= user.label :email, _('Email'), class: 'control-label'%> + <%= email_tooltip %> <%= user.email_field :email, for: :user, name: "user", class: "form-control", "aria-required": true, 'data-toggle': 'tooltip', 'data-html': true, - title: _("Enter the email address of your collaborator:
    • If they are already using #{Rails.configuration.branding[:application][:name]}, they will see this plan on their dashboard, and recieve an email.
    • If they are not currently using #{Rails.configuration.branding[:application][:name]}, they will recieve an email inviting them to the tool so they can collaborate on your plan.
    ") %> + title: email_tooltip %> <% end %>
    + <%= permissions_tooltip %> <%= field_set_tag nil, class: 'col-xs-2', 'data-toggle': 'tooltip', 'data-html': true, - title: _('Co-owner: Has admin-rights to the plan (can invite other users, view the plan, answer questions, or comment)
    Editor: Has edit-rights to the plan (can view the plan, answer questions, or comment)
    Read Only: Has read-rights to the plan(can view the plan or comment)'), + title: permissions_tooltip, 'data-placement':'right' do %> <%= content_tag :legend , _('Permissions') %>
    - <%= f.label :access do %> - <%= f.radio_button :access, administrator.access, "aria-required": true %> + <%= f.label :administrator_access do %> + <%= f.radio_button :access, administrator.access, id: "role_administrator_access", "aria-required": true %> <%= _('Co-owner') %> <% end %>
    - <%= f.label :access do %> - <%= f.radio_button :access, editor.access %> + <%= f.label :editor_access do %> + <%= f.radio_button :access, editor.access , id: "role_editor_access" %> <%= _('Editor') %> <% end %>
    - <%= f.label :access do %> - <%= f.radio_button :access, commenter.access %> + <%= f.label :commenter_access do %> + <%= f.radio_button :access, commenter.access, id: "role_commenter_access" %> <%= _('Read only') %> <% end %>
    @@ -134,21 +138,4 @@ <% end %> -
    - <% if plan.owner_and_coowners.include?(current_user) && plan.owner.org.feedback_enabled? %> -

    <%= _('Request expert feedback') %>

    -

    <%= _("Click below to give data management staff at #{plan.owner.org.name}, the Plan Owner's org, access to read and comment on your plan.") %>

    -
    - <%= sanitize plan.owner.org.feedback_email_msg.to_s % { user_name: current_user.name(false), plan_name: plan.title } %> -
    -

    <%= _('You can continue to edit and download the plan in the interim.') %>

    -
    - <%= link_to _('Request feedback'), - feedback_requests_path(plan_id: @plan.id), - data: { method: 'post' }, - class: "btn btn-default#{' disabled' if @plan.feedback_requested?}" %> - <%= _("Feedback has been requested.") if @plan.feedback_requested? %> -
    - <% end %> -
    <% end %> diff --git a/app/views/plans/index.html.erb b/app/views/plans/index.html.erb index 57cc963751..e7bc65ef69 100644 --- a/app/views/plans/index.html.erb +++ b/app/views/plans/index.html.erb @@ -46,3 +46,5 @@ <% end %>
    + +<%= render 'shared/create_plan_modal' unless @template.nil? %> diff --git a/app/views/plans/new.html.erb b/app/views/plans/new.html.erb index 8d9b5439e2..0a408cd140 100644 --- a/app/views/plans/new.html.erb +++ b/app/views/plans/new.html.erb @@ -1,4 +1,11 @@ <% title _('Create a new plan') %> +<% required_project_title_tooltip = _('This field is required.') %> +<% project_title_tooltip = _('If applying for funding, state the project title exactly as in the proposal.') %> +<% required_research_org_tooltip = _('You must select a research organisation from the list or click the checkbox.') %> +<% research_org_tooltip = _('Please select a valid research organisation from the list.') %> +<% required_primary_funding_tooltip = _('You must select a funder from the list or click the checkbox.') %> +<% primary_funding_tooltip = _('Please select a valid funding organisation from the list.') %> +

    <%= _('Create a new plan') %>

    @@ -13,13 +20,15 @@
    <%= form_for Plan.new, url: plans_path do |f| %> -

    * <%= _('What research project are you planning?') %>

    +

    *<%= required_project_title_tooltip %> <%= _('What research project are you planning?') %>

    + <%= project_title_tooltip %> <%= f.text_field(:title, class: 'form-control', 'aria-describedby': 'project-title', 'aria-required': 'true', 'aria-label': 'project-title', 'data-toggle': 'tooltip', 'data-placement': 'bottom', - title: _('If applying for funding, state the project title exactly as in the proposal.')) %> + spellcheck: true, + title: project_title_tooltip ) %>
     
    @@ -34,11 +43,12 @@

    - * + *<%= required_research_org_tooltip %> <%= _('Select the primary research organisation') %>

    + <%= research_org_tooltip %> <%= render partial: "shared/accessible_combobox", locals: {name: 'plan[org_name]', id: 'plan_org_name', @@ -47,7 +57,7 @@ attribute: 'name', required: true, error: _('You must select a research organisation from the list.'), - tooltip: _('Please select a valid research organisation from the list.'), + tooltip: research_org_tooltip, placement: 'bottom'} %>
    - <%= _('or') %> -
    @@ -63,9 +73,10 @@
    -

    * <%= _('Select the primary funding organisation') %>

    +

    * <%= required_primary_funding_tooltip %> <%= _('Select the primary funding organisation') %>

    + <%= primary_funding_tooltip %> <%= render partial: "shared/accessible_combobox", locals: {name: 'plan[funder_name]', id: 'plan_funder_name', @@ -74,7 +85,7 @@ attribute: 'name', required: true, error: _('You must select a funding organisation from the list.'), - tooltip: _('Please select a valid funding organisation from the list.'), + tooltip: primary_funding_tooltip, placement: 'bottom'} %>
    - <%= _('or') %> -
    diff --git a/app/views/plans/request_feedback.html.erb b/app/views/plans/request_feedback.html.erb new file mode 100644 index 0000000000..0878409a09 --- /dev/null +++ b/app/views/plans/request_feedback.html.erb @@ -0,0 +1,13 @@ +<% title "#{@plan.title} - Request feedback" %> +
    +
    + +

    <%= @plan.title %>

    +
    +
    + +
    +
    + <%= render partial: 'request_feedback_form', layout: 'navigation', locals: { plan: @plan } %> +
    +
    diff --git a/app/views/questions/_new_edit_question_textfield.html.erb b/app/views/questions/_new_edit_question_textfield.html.erb index 8bdb54ccf9..171432fa90 100644 --- a/app/views/questions/_new_edit_question_textfield.html.erb +++ b/app/views/questions/_new_edit_question_textfield.html.erb @@ -1,5 +1,5 @@ <%# locals: { f, question, answer } %>
    <%= f.label(:text, sanitize(question.text), class: 'control-label') %> - <%= text_field_tag('answer[text]', strip_tags(answer.text || question.default_value), class: 'form-control') %> + <%= text_field_tag('answer[text]', strip_tags(answer.text || question.default_value), class: 'form-control', spellcheck: true) %>
    \ No newline at end of file diff --git a/app/views/shared/_accessible_combobox.html.erb b/app/views/shared/_accessible_combobox.html.erb index fda93b7ca5..3e50b812c4 100644 --- a/app/views/shared/_accessible_combobox.html.erb +++ b/app/views/shared/_accessible_combobox.html.erb @@ -8,6 +8,7 @@ <% models.map{|m| json["#{m[attribute]}"] = m.id} %> <% name = name.gsub(name.match(/^.*\[/)[0].split('_')[0] + '_', '') %> + <%= title %> + +
    diff --git a/app/views/shared/_create_plan_modal.html.erb b/app/views/shared/_create_plan_modal.html.erb new file mode 100644 index 0000000000..6523ae48c0 --- /dev/null +++ b/app/views/shared/_create_plan_modal.html.erb @@ -0,0 +1,15 @@ + diff --git a/app/views/shared/_links.html.erb b/app/views/shared/_links.html.erb index 9452e75e25..26287e054b 100644 --- a/app/views/shared/_links.html.erb +++ b/app/views/shared/_links.html.erb @@ -10,6 +10,7 @@   + <%= tooltip %>
    diff --git a/app/views/shared/_popover.html.erb b/app/views/shared/_popover.html.erb index ab1ac6ed38..a891415722 100644 --- a/app/views/shared/_popover.html.erb +++ b/app/views/shared/_popover.html.erb @@ -1,7 +1,8 @@ <%# available locals: message, placement %> <% if message.present? %> - + <%= message %>> <% end %> \ No newline at end of file diff --git a/app/views/shared/_search.html.erb b/app/views/shared/_search.html.erb index 56d5b95733..19f9a8250b 100644 --- a/app/views/shared/_search.html.erb +++ b/app/views/shared/_search.html.erb @@ -5,7 +5,8 @@ - <%= text_field_tag(:search, search_term, class: 'form-control', 'aria-labelledby': 'search', 'aria-describedby': 'search-addon', 'aria-required': true) %> + <%= text_field_tag(:search, search_term, class: 'form-control', 'aria-labelledby': 'search', + spellcheck: true, 'aria-describedby': 'search-addon', 'aria-required': true) %>
    <%= submit_tag(_('Search'), class: 'btn btn-default', style: 'margin-top: 8px;') %> diff --git a/app/views/shared/_table_filter.html.erb b/app/views/shared/_table_filter.html.erb index 19cf031f1f..f18b5011b6 100644 --- a/app/views/shared/_table_filter.html.erb +++ b/app/views/shared/_table_filter.html.erb @@ -1,3 +1,5 @@ +<% remove_filter_tooltip = _('Remove the filter') %> +
      @@ -8,9 +10,10 @@ class="clear_filter" href="#" data-toggle="tooltip" - title="<%= _('Remove the filter') -%>" - aria-label="<%= _('Remove the filter') %>"> + title="<%= remove_filter_tooltip %>" + aria-label="<%= remove_filter_tooltip %>"> + <%= remove_filter_tooltip %>
    diff --git a/app/views/shared/export/_plan_txt.erb b/app/views/shared/export/_plan_txt.erb index daa000ea1c..0462c8d69a 100644 --- a/app/views/shared/export/_plan_txt.erb +++ b/app/views/shared/export/_plan_txt.erb @@ -42,7 +42,7 @@ <% end %> <% end %> <% answer = @plan.answer(question[:id], false) %> - <% blank = not(answer.present? && answer.is_valid?) %> + <% blank = not(answer.present? && answer.answered?) %> <% if blank && @show_unanswered %> <%= " #{_("Question not answered.")}\n\n" %> <% elsif !blank %> diff --git a/app/views/static_pages/about_us.html.erb b/app/views/static_pages/about_us.html.erb index 11308889b9..d87645bc3f 100644 --- a/app/views/static_pages/about_us.html.erb +++ b/app/views/static_pages/about_us.html.erb @@ -18,8 +18,15 @@

    <%= _("The new platform will be separate from the services each of our teams runs on top of it. Our shared goal: provide a combined DMPRoadmap platform as a core infrastructure for DMPs. Future enhancements will focus on making DMPs machine actionable so please continue sharing your use cases.") %>

    -

    <%= _("We invite you to peruse the DMPRoadmap GitHub wiki to learn how to ")%><%= link_to( sanitize(_("get involved (new window)")), "https://github.com/DMPRoadmap/roadmap/wiki/get-involved", target: '_blank', id: "get involved" ) %><%= _(" in the project. You can also report bugs and request new features via ") %> - <%= _('GitHub Issues') %>

    +

    <%= _("We invite you to peruse the DMPRoadmap GitHub wiki to learn how to ")%><%= link_to( + sanitize(_("get involved (new window)%{open_in_new_window_text}") % { open_in_new_window_text: _('Opens in new window') }, + tags: %w( span em )), + "https://github.com/DMPRoadmap/roadmap/wiki/get-involved", + class: "has-new-window-popup-info", + target: '_blank', + id: "get involved" ) %> + <%= _(" in the project. You can also report bugs and request new features via ") %> + <%= _('GitHub Issues') %><%= _('Opens in new window') %>

    <%= _('Getting Started') %>

    diff --git a/app/views/static_pages/termsuse.html.erb b/app/views/static_pages/termsuse.html.erb index ba04ef5097..2fcbcfb03d 100644 --- a/app/views/static_pages/termsuse.html.erb +++ b/app/views/static_pages/termsuse.html.erb @@ -15,7 +15,7 @@

    <%= _("DMPRoadmap ('the tool', 'the system') is a tool developed by the DCC and CDL as a shared resource for the research community. It is hosted at CDL by the University of California Curation Center.") %>

    - <%= sanitize _("

    Your personal details and consent notice

    + <%= sanitize(_("

    Your personal details and consent notice

    In order to help identify and administer your account with DMPRoadmap, we need to store your name and email address. We may also use it to contact you to obtain feedback on your use of the tool, or to inform you of the latest developments or releases. The information may be transferred between the DCC and CDL but only for the following legitimate DCC and CDL purposes: marketing, improving our services and informing you of relevant content and events. We will not sell, rent, or trade any personal information you provide to us. @@ -35,7 +35,7 @@

    Cookies

    -

    Please note that DMPRoadmap uses Cookies. Further information about Cookies and how we use them is available on the main DCC website (new window).

    +

    Please note that DMPRoadmap uses Cookies. Further information about Cookies and how we use them is available on the main DCC website (new window)%{open_in_new_window_text}.

    Third party APIs

    @@ -43,7 +43,8 @@

    Revisions

    -

    This statement was last revised on October 5, 2017 and may be revised at any time. Use of the tool indicates that you understand and agree to these terms and conditions.

    " ) %> +

    This statement was last revised on October 5, 2017 and may be revised at any time. Use of the tool indicates that you understand and agree to these terms and conditions.

    " ) % { open_in_new_window_text: _('Opens in new window') }, + tags: %w( a h3 p span em )) %>
    \ No newline at end of file diff --git a/app/views/super_admin/notifications/_form.html.erb b/app/views/super_admin/notifications/_form.html.erb index c6ff825c3e..74c539670d 100644 --- a/app/views/super_admin/notifications/_form.html.erb +++ b/app/views/super_admin/notifications/_form.html.erb @@ -7,6 +7,7 @@ <%= f.text_field :title, class: 'form-control', value: @notification.title, + spellcheck: true, "aria-required": true %>
    diff --git a/app/views/super_admin/themes/_form.html.erb b/app/views/super_admin/themes/_form.html.erb index 6bb7e306ee..393bd8729e 100644 --- a/app/views/super_admin/themes/_form.html.erb +++ b/app/views/super_admin/themes/_form.html.erb @@ -3,7 +3,7 @@ <%= form_for @theme, url: url, html: { class: 'theme' } do |f| %>
    <%= f.label(:title, _('Title'), class: 'control-label') %> - <%= f.text_field(:title, class: "form-control", "aria-required": true) %> + <%= f.text_field(:title, class: "form-control", spellcheck: true, "aria-required": true) %>
    <%= f.label(:description, _('Guidance')) %> diff --git a/app/views/super_admin/users/_confirm_merge.html.erb b/app/views/super_admin/users/_confirm_merge.html.erb new file mode 100644 index 0000000000..2144a5b365 --- /dev/null +++ b/app/views/super_admin/users/_confirm_merge.html.erb @@ -0,0 +1,16 @@ +

    + <%= sanitize _("
    The selected user's content will be merged into the account for %{user_email}.
    The selected account will then be removed") % {user_email: @user.email} %> +

    + +<%= form_tag(merge_super_admin_user_path(@user), method: 'put', class: 'form-inline merge_form') do %> +
    +
    + + + + <%= select_tag(:merge_id, options_from_collection_for_select(@users, "id", "email"), class: "form-control") %> +
    +
    + <%= submit_tag( _("Merge"), class: 'btn btn-default', style: 'margin-top: 8px;', data: { confirm: "placeholder" }) %> + <%= link_to(_("Cancel"), edit_super_admin_user_path(@user), class: 'btn btn-default') %> +<% end %> diff --git a/app/views/super_admin/users/edit.html.erb b/app/views/super_admin/users/edit.html.erb index be65963e9f..db0db2c093 100644 --- a/app/views/super_admin/users/edit.html.erb +++ b/app/views/super_admin/users/edit.html.erb @@ -9,24 +9,24 @@
    -
    +
    <%= form_for(@user, namespace: :superadmin, as: :user, url: super_admin_user_path(@user), html: {method: :put, id: 'super_admin_user_edit' }) do |f| %> -
    +
    <%= f.label(:email, _('Email'), class: 'control-label') %> <%= f.email_field(:email, class: "form-control", "aria-required": true) %>
    -
    +
    <%= f.label(:firstname, _('First name'), class: 'control-label') %> <%= f.text_field(:firstname, class: "form-control", "aria-required": true) %>
    -
    +
    <%= f.label(:surname, _('Last name'), class: 'control-label') %> <%= f.text_field(:surname, class: "form-control", "aria-required": true) %>
    -
    +
    <%= render partial: "shared/my_org", locals: { f: f, default_org: @user.org, @@ -35,8 +35,20 @@ required: true } %>
    + <% if @departments.any? %> +
    + <% dept_id = @user.department.nil? ? -1 : @user.department.id %> + <%= f.label(:department_id, _('Department or school'), class: 'control-label') %> + <%= select_tag(:department_id, + options_from_collection_for_select(@departments, "id", "name", dept_id), + include_blank: true, + class: "form-control", + name: 'user[department_id]') %> +
    + <% end %> + <% if Language.many? %> -
    +
    <% lang_id = @user.language.nil? ? Language.id_for(FastGettext.default_locale) : @user.language.id %> <%= f.label(:language_id, _('Language'), class: 'control-label') %> <%= select_tag(:super_admin_user_language_id, @@ -45,9 +57,54 @@
    <% end %> -
    +
    <%= f.button(_('Save'), class: 'btn btn-default', type: "submit", id: "personal_details_registration_form_submit") %> + + <%= link_to _('Archive'), archive_super_admin_user_path(id: @user.id), + data: { method: :put, confirm: _("You are about to archive %{user_name}. This will remove their personal information, but retain their plans, answers, and comments. They will be unable to sign-in. Are you sure?") % {user_name: @user.name } }, + class: 'btn btn-default', role: 'button' %>
    <% end %>
    +
    +
    +

    + <%= _('Merge Accounts') %> +

    +
    +

    + <%= sanitize _("First, search for a user by email, then select them from the list.") %> +

    + <%= form_tag(search_super_admin_user_path(@user), method: 'get', remote: true, class: 'form-inline', id: 'merge_form') do %> +
    +
    + + + + <%= text_field_tag(:email, nil, class: "form-control", placeholder: _("Email")) %> +
    +
    + <%= submit_tag( _("Search"), class: 'btn btn-default', style: 'margin-top: 8px;') %> + <% end %> +
    +
    +
    +
    + +
    +
    +

    <%= _('Plans') % { username: @user.name(false) } %>

    + +
    +
    +
    +
    + <%= paginable_renderise( + partial: '/paginable/plans/org_admin_other_user', + controller: 'paginable/plans', + action: 'org_admin_other_user', + scope: @plans, + query_params: { sort_field: 'plans.updated_at', sort_direction: 'desc' }) %> +
    +
    diff --git a/app/views/public_pages/template_export.docx.erb b/app/views/template_exports/template_export.docx.erb similarity index 100% rename from app/views/public_pages/template_export.docx.erb rename to app/views/template_exports/template_export.docx.erb diff --git a/app/views/public_pages/template_export.pdf.erb b/app/views/template_exports/template_export.pdf.erb similarity index 100% rename from app/views/public_pages/template_export.pdf.erb rename to app/views/template_exports/template_export.pdf.erb diff --git a/app/views/usage/index.html.erb b/app/views/usage/index.html.erb index 42f31a904a..b590553566 100644 --- a/app/views/usage/index.html.erb +++ b/app/views/usage/index.html.erb @@ -169,10 +169,11 @@
  • +
  • diff --git a/config/branding.yml.sample b/config/branding.yml.sample index 87f158bf2d..2eae0c9ba7 100644 --- a/config/branding.yml.sample +++ b/config/branding.yml.sample @@ -2,7 +2,7 @@ defaults: &defaults legal_entity: 'the University of Edinburgh, University of Glasgow and the University of California' # Warning: The abbreviation here should match the org.abbreviation value registered in your database! - organisation: + organisation: &organization_defaults name: 'Curation Center' abbreviation: 'CC' # This value is used to identify the default guidance that get auto-selected when a new plan is created url: 'https://github.com/DMPRoadmap/roadmap/wiki' @@ -32,7 +32,7 @@ defaults: &defaults # Comment this line out if you want to use DMPRoadmap's built-in contact form. contact_us_url: 'https://somewhere.com/contact-us' - application: + application: &application_defaults name: 'DMPRoadmap' url: 'https://github.com/DMPRoadmap/roadmap' version: '0.1.0' @@ -41,6 +41,7 @@ defaults: &defaults user_group_subscription_url: 'http://listserv.ucop.edu/cgi-bin/wa.exe?SUBED1=ROADMAP-L&A=1' api_documentation_url: 'https://github.com/DMPRoadmap/roadmap/wiki/API-Documentation' api_max_page_size: 100 + archived_accounts_email_suffix: '@removed_accounts-example.org' preferences: email: diff --git a/config/deploy.rb b/config/deploy.rb new file mode 100644 index 0000000000..a1eb043143 --- /dev/null +++ b/config/deploy.rb @@ -0,0 +1,104 @@ +# config valid only for current version of Capistrano +lock "3.11.2" + +# Default branch is :master +ask :branch, `git rev-parse --abbrev-ref HEAD`.chomp unless ENV['BRANCH'] +set :branch, ENV['BRANCH'] if ENV['BRANCH'] + +set :default_env, { path: "/dmp/local/bin:$PATH" } + +# Include optional Gem groups +# TODO: For some reason this does not work +#set :bundle_with, %w{ aws mysql }.join(' ') + +# Default environments to skip +set :bundle_without, %w{ puma pgsql thin rollbar test }.join(' ') + +# Define the location of the private configuration repo +set :config_repo, 'git@github.com:cdlib/dmptool_config.git' + +# Default value for :linked_files is [] +append :linked_files, 'config/branding.yml', + 'config/database.yml', + 'config/secrets.yml', + 'config/initializers/contact_us.rb', + 'config/initializers/devise.rb', + 'config/initializers/dragonfly.rb', + 'config/initializers/recaptcha.rb', + 'config/initializers/wicked_pdf.rb' + +# Default value for linked_dirs is [] +append :linked_dirs, 'log', + 'tmp/pids', + 'tmp/cache', + 'tmp/sockets', + 'config/environments', + 'public' + +# Default value for keep_releases is 5 +set :keep_releases, 5 + +namespace :deploy do + before :deploy, 'config:install_shared_dir' + after :deploy, 'cleanup:copy_tinymce_skins' + after :deploy, 'cleanup:copy_logo' + after :deploy, 'cleanup:copy_favicon' + after :deploy, 'cleanup:remove_example_configs' + after :deploy, 'cleanup:restart_passenger' +end + +namespace :config do + desc 'Setup up the config repo as the shared directory' + task :install_shared_dir do + on roles(:app), wait: 1 do + execute "if [ ! -d '#{deploy_path}/shared/' ]; then cd #{deploy_path}/ && git clone #{fetch :config_repo} shared; fi" + execute "cd #{deploy_path}/shared/ && git checkout #{fetch :config_branch} && git pull origin #{fetch :config_branch}" + end + end +end + +namespace :cleanup do + desc "Remove all of the example config files" + task :remove_example_configs do + on roles(:app), wait: 1 do + execute "rm -f #{release_path}/config/*.yml.sample" + execute "rm -f #{release_path}/config/initializers/*.rb.example" + end + end + + desc "Move Tinymce skins into public dir" + task :copy_tinymce_skins do + on roles(:app), wait: 1 do + execute "if [ ! -d '#{release_path}/public/tinymce/' ]; then cd #{release_path}/ && mkdir public/tinymce && cp -r node_modules/tinymce/skins public/tinymce; fi" + end + end + + desc "Move DMPTool logo into public dir for Shib" + task :copy_logo do + on roles(:app), wait: 1 do + execute "if [ ! -d '#{release_path}/public/images/' ]; then cd #{release_path}/ && mkdir public/images; fi" + execute "cd #{release_path}/ && cp app/assets/images/DMPTool_logo_blue_shades_v1b3b.svg public/images" + end + end + + desc "Move favicon-32x32 into public dir" + task :copy_favicon do + on roles(:app), wait: 1 do + execute "if [ ! -d '#{release_path}/public/images/' ]; then cd #{release_path}/ && mkdir public/images; fi" + execute "cd #{release_path}/ && cp app/assets/images/favicon-32x32.png public/assets" + execute "cd #{release_path}/ && cp app/assets/images/apple-touch-icon.png public/assets" + end + end + + desc 'Restart Phusion Passenger' + task :restart_passenger do + on roles(:app), wait: 5 do + execute "cd /apps/dmp/init.d && ./passenger restart" + end + end + + after :restart_passenger, :clear_cache do + on roles(:web), in: :groups, limit: 3, wait: 10 do + end + end +end \ No newline at end of file diff --git a/config/deploy/uc3-dmpx2-prd-2a.rb b/config/deploy/uc3-dmpx2-prd-2a.rb new file mode 100644 index 0000000000..aa5086f0a0 --- /dev/null +++ b/config/deploy/uc3-dmpx2-prd-2a.rb @@ -0,0 +1,13 @@ +set :application, 'DMPTool' +set :repo_url, 'https://github.com/CDLUC3/dmptool.git' + +set :server_host, ENV["SERVER_HOST"] || 'uc3-dmpx2-prd-2a.cdlib.org' +server fetch(:server_host), user: 'dmp', roles: %w{web app db} + +set :deploy_to, '/dmp/apps/dmp' +set :share_to, 'dmp/apps/dmp/shared' + +# Define the location of the private configuration repo +set :config_branch, 'uc3-dmpx2-prd' + +set :rails_env, 'production' diff --git a/config/deploy/uc3-dmpx2-prd-2c.rb b/config/deploy/uc3-dmpx2-prd-2c.rb new file mode 100644 index 0000000000..31ac1a6032 --- /dev/null +++ b/config/deploy/uc3-dmpx2-prd-2c.rb @@ -0,0 +1,13 @@ +set :application, 'DMPTool' +set :repo_url, 'https://github.com/CDLUC3/dmptool.git' + +set :server_host, ENV["SERVER_HOST"] || 'uc3-dmpx2-prd-2c.cdlib.org' +server fetch(:server_host), user: 'dmp', roles: %w{web app db} + +set :deploy_to, '/dmp/apps/dmp' +set :share_to, 'dmp/apps/dmp/shared' + +# Define the location of the private configuration repo +set :config_branch, 'uc3-dmpx2-prd' + +set :rails_env, 'production' diff --git a/config/deploy/uc3-dmpx2-stg-2a.rb b/config/deploy/uc3-dmpx2-stg-2a.rb new file mode 100644 index 0000000000..cc2478fe1d --- /dev/null +++ b/config/deploy/uc3-dmpx2-stg-2a.rb @@ -0,0 +1,13 @@ +set :application, 'DMPTool' +set :repo_url, 'https://github.com/CDLUC3/dmptool.git' + +set :server_host, ENV["SERVER_HOST"] || 'uc3-dmpx2-stg-2a.cdlib.org' +server fetch(:server_host), user: 'dmp', roles: %w{web app db} + +set :deploy_to, '/dmp/apps/dmp' +set :share_to, 'dmp/apps/dmp/shared' + +# Define the location of the private configuration repo +set :config_branch, 'uc3-dmpx2-stg' + +set :rails_env, 'stage' diff --git a/config/deploy/uc3-dmpx2-stg-2c.rb b/config/deploy/uc3-dmpx2-stg-2c.rb new file mode 100644 index 0000000000..c82e209307 --- /dev/null +++ b/config/deploy/uc3-dmpx2-stg-2c.rb @@ -0,0 +1,13 @@ +set :application, 'DMPTool' +set :repo_url, 'https://github.com/CDLUC3/dmptool.git' + +set :server_host, ENV["SERVER_HOST"] || 'uc3-dmpx2-stg-2c.cdlib.org' +server fetch(:server_host), user: 'dmp', roles: %w{web app db} + +set :deploy_to, '/dmp/apps/dmp' +set :share_to, 'dmp/apps/dmp/shared' + +# Define the location of the private configuration repo +set :config_branch, 'uc3-dmpx2-stg' + +set :rails_env, 'stage' diff --git a/config/deploy/uc3-roadmap-stg.rb b/config/deploy/uc3-roadmap-stg.rb new file mode 100644 index 0000000000..7cf2ce5e61 --- /dev/null +++ b/config/deploy/uc3-roadmap-stg.rb @@ -0,0 +1,24 @@ +set :application, 'DMPRoadmap' +set :repo_url, 'https://github.com/DMPRoadmap/roadmap.git' + +set :server_host, ENV["SERVER_HOST"] || 'uc3-roadmap-stg.cdlib.org' +server fetch(:server_host), user: 'dmp', roles: %w{web app db} + +set :deploy_to, '/dmp/apps/roadmap' +set :share_to, 'dmp/apps/roadmap/shared' + +# Define the location of the private configuration repo +set :config_branch, 'uc3-roadmap-stg' + +set :rails_env, 'production' + +namespace :cleanup do + desc "Move DMPTool logo into public dir for Shib" + task :copy_logo do + on roles(:app), wait: 1 do + # Forcing the skip of this step since the DMPTool does not exist in Roadmap and + # we don't need a Shib logo for it + # execute "if [ ! -d '#{release_path}/public/images/' ]; then cd #{release_path}/ && mkdir public/images && cp app/assets/DMPTool_logo_blue_shades_v1b3b.svg public/images; fi" + end + end +end diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index 46578a5572..d314009498 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -1,6 +1,9 @@ Rails.application.config.assets.paths << Rails.root.join('node_modules') -Rails.application.config.assets.precompile += %w[ tinymce/lightgray/skin.min.css ] +Rails.application.config.assets.precompile += %w[ + tinymce/lightgray/skin.min.css, + blocks/_tinymce_content.scss + ] if Rails.env.staging? or Rails.env.production? diff --git a/config/initializers/cookies_serializer.rb b/config/initializers/cookies_serializer.rb index 7f44467d09..1ea6ed8d86 100644 --- a/config/initializers/cookies_serializer.rb +++ b/config/initializers/cookies_serializer.rb @@ -1,6 +1,3 @@ # Be sure to restart your server when you modify this file. -# Rails.application.config.action_dispatch.cookies_serializer = :hybrid -Rails.application.config.session_store :cookie_store, key: '_dmptool' - -Rails.application.config.action_dispatch.cookies_serializer = :json \ No newline at end of file +Rails.application.config.action_dispatch.cookies_serializer = :json diff --git a/config/initializers/htmlto_word_xslt_helper.rb b/config/initializers/htmlto_word_xslt_helper.rb new file mode 100644 index 0000000000..91714541d8 --- /dev/null +++ b/config/initializers/htmlto_word_xslt_helper.rb @@ -0,0 +1,18 @@ +# This helper method xslt_path prepends the htmltoword method, +# to allow us to overide the numbering.xslt styleheet with one +# with fix in https://github.com/karnov/htmltoword/issues/73 +# We applied this gem gem htmltoword-1.1.0. + +module Htmltoword + module XSLTHelper + + def xslt_path(template_name) + if template_name == 'numbering' + File.join(Rails.root.join('app', 'assets', 'xslt', 'htmltoword'), "#{template_name}.xslt") + else + File.join(Htmltoword.config.default_xslt_path, "#{template_name}.xslt") + end + end + + end +end diff --git a/config/locale/app.pot b/config/locale/app.pot index bbafeee3a2..0e695a292c 100644 --- a/config/locale/app.pot +++ b/config/locale/app.pot @@ -167,6 +167,7 @@ msgstr "" msgid "A Data Management Plan in %{application_name} has been shared with you" msgstr "" +#, fuzzy msgid "A Data Management Plan in %{tool_name} has been shared \"\ " " \"with you" @@ -1813,7 +1814,11 @@ msgstr "" msgid "Successfully %{action} the %{object}." msgstr "" -msgid "Successfully changed the permissions for #{@role.user.email}. They have been notified via email." +#msgid "Successfully %{action} your %{object}." +#msgstr "" + +#, fuzzy +msgid "Successfully changed the permissions for %{email}. They have been notified via email." msgstr "" msgid "Successfully signed in" @@ -2448,6 +2453,7 @@ msgstr "" msgid "Your account has been successfully linked to your institutional credentials. You will now be able to sign in with them." msgstr "" +#, fuzzy msgid "Your colleague %{inviter_name} has invited you to contribute to " " their Data Management Plan in %{tool_name}" diff --git a/config/locale/de/app.po b/config/locale/de/app.po index 6f69418c30..fa767b1885 100644 --- a/config/locale/de/app.po +++ b/config/locale/de/app.po @@ -221,7 +221,8 @@ msgid "A Data Management Plan in %{application_name} has been shared with you" msgstr "DMPonline" #, fuzzy -msgid "A Data Management Plan in %{tool_name} has been shared \"\ " +msgid "A Data Management Plan in %{tool_name} has been shared \"\ +" " \"with you" msgstr "" @@ -2287,7 +2288,7 @@ msgstr "" #msgstr "" #, fuzzy -msgid "Successfully changed the permissions for #{@role.user.email}. They have been notified via email." +msgid "Successfully changed the permissions for %{email}. They have been notified via email." msgstr "" #msgid "Successfully deleted your theme" @@ -3105,7 +3106,8 @@ msgid "Your account has been successfully linked to your institutional credentia msgstr "Your " #, fuzzy -msgid "Your colleague %{inviter_name} has invited you to contribute to " +msgid "Your colleague %{inviter_name} has invited you to contribute to +" " their Data Management Plan in %{tool_name}" msgstr "" diff --git a/config/locale/en_GB/app.po b/config/locale/en_GB/app.po index b667cbab84..020d02bbf2 100644 --- a/config/locale/en_GB/app.po +++ b/config/locale/en_GB/app.po @@ -193,7 +193,8 @@ msgid "A Data Management Plan in %{application_name} has been shared with you" msgstr "" #, fuzzy -msgid "A Data Management Plan in %{tool_name} has been shared \"\ " +msgid "A Data Management Plan in %{tool_name} has been shared \"\ +" " \"with you" msgstr "" @@ -1989,7 +1990,7 @@ msgstr "" #msgstr "" #, fuzzy -msgid "Successfully changed the permissions for #{@role.user.email}. They have been notified via email." +msgid "Successfully changed the permissions for %{email}. They have been notified via email." msgstr "" #msgid "Successfully deleted your theme" @@ -2682,7 +2683,8 @@ msgid "Your account has been successfully linked to your institutional credentia msgstr "" #, fuzzy -msgid "Your colleague %{inviter_name} has invited you to contribute to " +msgid "Your colleague %{inviter_name} has invited you to contribute to +" " their Data Management Plan in %{tool_name}" msgstr "" diff --git a/config/locale/en_US/app.po b/config/locale/en_US/app.po index 2cef7319d6..b25f15e48b 100644 --- a/config/locale/en_US/app.po +++ b/config/locale/en_US/app.po @@ -2611,8 +2611,7 @@ msgstr "" msgid "Successfully %{action} your %{object}." msgstr "" -#, fuzzy -msgid "Successfully changed the permissions for #{@role.user.email}. They have been notified via email." +msgid "Successfully changed the permissions for %{email}. They have been notified via email." msgstr "" msgid "Successfully deleted your theme" diff --git a/config/locale/es/app.po b/config/locale/es/app.po index fe84fce270..82b5cc5fda 100644 --- a/config/locale/es/app.po +++ b/config/locale/es/app.po @@ -221,7 +221,8 @@ msgid "A Data Management Plan in %{application_name} has been shared with you" msgstr "DMPonline" #, fuzzy -msgid "A Data Management Plan in %{tool_name} has been shared \"\ " +msgid "A Data Management Plan in %{tool_name} has been shared \"\ +" " \"with you" msgstr "" @@ -2281,7 +2282,7 @@ msgstr "" #msgstr "" #, fuzzy -msgid "Successfully changed the permissions for #{@role.user.email}. They have been notified via email." +msgid "Successfully changed the permissions for %{email}. They have been notified via email." msgstr "" #msgid "Successfully deleted your theme" @@ -3091,7 +3092,8 @@ msgid "Your account has been successfully linked to your institutional credentia msgstr "" #, fuzzy -msgid "Your colleague %{inviter_name} has invited you to contribute to " +msgid "Your colleague %{inviter_name} has invited you to contribute to +" " their Data Management Plan in %{tool_name}" msgstr "" diff --git a/config/locale/fr_FR/app.po b/config/locale/fr_FR/app.po index 0baea5f693..ab1aaef891 100644 --- a/config/locale/fr_FR/app.po +++ b/config/locale/fr_FR/app.po @@ -191,7 +191,8 @@ msgid "A Data Management Plan in %{application_name} has been shared with you" msgstr "Un plan de gestion de données a été partagé avec vous sur %{application_name}" #, fuzzy -msgid "A Data Management Plan in %{tool_name} has been shared \"\ " +msgid "A Data Management Plan in %{tool_name} has been shared \"\ +" " \"with you" msgstr "" @@ -1987,7 +1988,7 @@ msgstr "" #msgstr "%{object} %{action} avec succès." #, fuzzy -msgid "Successfully changed the permissions for #{@role.user.email}. They have been notified via email." +msgid "Successfully changed the permissions for %{email}. They have been notified via email." msgstr "" #msgid "Successfully deleted your theme" @@ -2680,7 +2681,8 @@ msgid "Your account has been successfully linked to your institutional credentia msgstr "Votre compte a été lié avec succès à vos identifiants institutionnels. Vous pouvez à présent vous connecter avec ceux-ci." #, fuzzy -msgid "Your colleague %{inviter_name} has invited you to contribute to " +msgid "Your colleague %{inviter_name} has invited you to contribute to +" " their Data Management Plan in %{tool_name}" msgstr "" diff --git a/config/locale/pt_BR/app.po b/config/locale/pt_BR/app.po index fe6445d47d..cf8f794411 100644 --- a/config/locale/pt_BR/app.po +++ b/config/locale/pt_BR/app.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: app 1.0.0\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2018-06-20 16:23:24-0700\n" -"Last-Translator: Benilton de Sá Carvalho benilton@unicamp.br\n" +"PO-Revision-Date: 2019-10-23 11:10:54-0700\n" +"Last-Translator: Hugo Ebert Carl hugoec@al.insper.edu.br\n" "Language-Team: Portugues do Brasil\n" "Language: pt_BR\n" "MIME-Version: 1.0\n" @@ -42,11 +42,14 @@ msgstr " foi removido por " msgid "#{text}" msgstr "#{text}" +msgid "%{affiliation}" +msgstr "%{affiliation}" + msgid "%{application_name}" msgstr "%{application_name}" -msgid "%{application_name} is provided by the %{organisation_name}. You can find out more about us on our website.
    If you would like to contact us about %{application_name}, please fill out the form below." -msgstr "%{application_name} é fornecido pelo %{organisation_name}. Pode saber mais sobre nós no nosso website.
    Se pretender contactar-nos acerca de %{application_name}, Por favor, preencha o formulário abaixo" +msgid "%{application_name} is provided by the %{organisation_name}.
    You can find out more about us on our website (new window). If you would like to contact us about %{application_name}, please fill out the form below." +msgstr "%{application_name} é fornecido(a) por %{organisation_name}.
    Você pode descobrir mais sobre nós no nosso website (new window). Caso você queira nos contatar %{application_name}, porfavor preencha o formulário abaixo." msgid "%{application_name}: %{user_name} requested feedback on a plan" msgstr "%{application_name}: %{user_name} solicitado feedback sobre um plano." @@ -57,6 +60,9 @@ msgstr "%{application_name}: Feedback especializado fornecido para %{plan_title} msgid "%{application_name}: Your plan has been submitted for feedback" msgstr "%{application_name}: Seu plano foi submetido para feedback." +msgid "%{authors}" +msgstr "%{authors}" + msgid "%{click_here} to accept the invitation, (or copy %{link} into your browser). If you don't want to accept the invitation, please ignore this email." msgstr "%{click_here} para aceitar o convite, (ou copie %{link} em seu navegador). Se não quiser aceitar o convite, por favor, ignore esta mensagem." @@ -66,6 +72,18 @@ msgstr "%{commenter_name} fez comentários sobre o plano %{plan_title}. Para ver msgid "%{commenter} has finished providing feedback on the plan \"%{plan_title}\". To view the comments, please visit the My Dashboard page in %{tool_name} and open your plan." msgstr "%{commenter} concluiu o feedback sobre o plano \"%{plan_title}\". Para ver seus comentários, por favor, visite a página Meu Painel de Controle em %{tool_name} e abra seu plano." +msgid "%{date}" +msgstr "%{date}" + +msgid "%{description}" +msgstr "%{description}" + +msgid "%{funder}" +msgstr "%{funder}" + +msgid "%{grant_number}" +msgstr "%{grant_number}" + msgid "%{org_name} Plans" msgstr "%{org_name} Planos" @@ -90,6 +108,9 @@ msgstr "%{plan_owner} foi avisado de que você terminou de dar feedback" msgid "%{requestor} has requested feedback on a plan \"%{plan_name}.\" To add comments, please visit the 'Plans' page under the Admin menu in %{application_name} and open the plan." msgstr "%{requestor} solicitou feedback sobre um plano \"%{plan_name}.\" Para adicionar comentários, visite a página 'Planos' no menu Admin em %{application_name} e abra o plano." +msgid "%{template}" +msgstr "%{template}" + msgid "%{tool_name} will help you to develop your Data Management Plan. If you have any queries or feedback as you use the tool, please contact us at %{helpdesk_email} or visit %{contact_us}" msgstr "%{tool_name} vai ajudá-lo a desenvolver seu Plano de Gestão de Dados. Se você tiver dúvidas ou quiser enviar-nos algum feedback enquanto estiver usando a ferramenta, por favor, entre em contato conosco em %{helpdesk_email} ou visite %{contact_us}" @@ -99,6 +120,12 @@ msgstr "%{tool_name}: Um novo comentário foi adicionado a %{plan_title}" msgid "%{username}'s profile" msgstr "%{username}'s perfil" +msgid "'Download' allows you to download your plan in various formats. This may be useful if you need to submit your plan as part of a grant application." +msgstr "'Download' permite que você baixe seu plano em vários formatos. Isso pode ser útil se você precisar enviar seu plano como parte de um pedido de subsídio." + +msgid "'Plan Overview' tells you what template and guidance your plan is based on and gives you an overview to the questions that you will be asked." +msgstr "'Visão Geral do Plano' informa em que modelo e orientação seu plano se baseia e fornece uma visão geral das perguntas que serão feitas." + msgid "%{value} is not a valid format" msgstr "%{value} não é um formato válido" @@ -306,8 +333,12 @@ msgstr "Um Plano de Gestão de Dados criado usando %{application_name}" msgid "A Data Management Plan in %{application_name} has been shared with you" msgstr "Um Plano de Gestão de Dados em %{application_name} foi compartilhado com você" -msgid "A Data Management Plan in %{tool_name} has been shared with you" -msgstr "Um Plano de Gestão de Dados em %{tool_name} foi compartilhado com você" +msgid "A Data Management Plan in %{tool_name} has been shared \"\ +" +" \"with you" +msgstr "O Plano de Gerenciamento de Dados %{tool_name} foi compartilhado \"\ +" +" \"com você" msgid "A colleague has invited you to contribute to their Data Management Plan in %{tool_name}" msgstr "Um colega convidou você para contribuir com seu Plano de Gestão de Dados em %{tool_name}" @@ -561,6 +592,9 @@ msgstr "Embora os elementos principais sejam suficientes no caso mais simples - msgid "An error has occurred while saving/resetting your export settings." msgstr "Ocorreu um erro ao salvar/redefinir seus parâmetros de exportação." +msgid "An error occurred when requesting feedback for this plan." +msgstr "Um erro ocorreu ao solicitar avaliação sobre este plano" + msgid "Annotations" msgstr "Anotações" @@ -663,12 +697,14 @@ msgstr "Comece a digitar para ver uma lista filtrada" msgid "Below are some general aspects of your data that you should document, regardless of your discipline. At minimum, store this documentation in a \"readme.txt\" file, or the equivalent, with the data itself." msgstr "Abaixo estão alguns aspectos gerais de seus dados que você deve documentar, independentemente da sua disciplina. No mínimo, armazene esta documentação em um arquivo \"readme.txt\", ou o equivalente, com os dados em si." -msgid "Below is a list of users registered for your organisation. You can sort the data by each field." -msgstr "Veja abaixo a lista de usuários registrados para sua organização. Você pode ordenar os dados segundo os diversos campos." - msgid "Beyond any externally imposed requirments, think about the long-term usefulness of the data. If the data is from an experiment that you anticipate will be repeatable more quickly, inexpensively, and accurately as technology progresses, you may want to store it for a relatively brief period. If the data consists of observations made outside the laborartory that can never be repeated, you may wish to store it indefinitely." msgstr "Além de quaisquer requisitos impostos externamente, pense na utilidade a longo prazo dos dados. Se os dados forem provenientes de um experimento que você prevê que será reproduzível com mais rapidez, baixo custo e precisão conforme a tecnologia avança, você pode armazená-lo por um período relativamente breve. Se os dados consistirem em observações feitas fora do laboratório que nunca poderão ser repetidas, você poderá armazená-las indefinidamente." +msgid "Below is a list of users registered for your organisation. You can" +" sort the data by each field." +msgstr "Abaixo está a lista de usuários registrados para sua organização. Você pode" +" organizar os dados por cada campo." + msgid "Body" msgstr "Corpo" @@ -900,6 +936,9 @@ msgstr "Os nomes dos criadores em scripts não romanos devem ser transliterados msgid "Creator:" msgstr "Criador:" +msgid "Creators:" +msgstr "Ciadores:" + msgid "Creators: " msgstr "Criadores:" @@ -909,9 +948,6 @@ msgstr "Privilégios atuais" msgid "Current password" msgstr "Senha atual" -msgid "Customise" -msgstr "Customizar" - msgid "Customizable Templates" msgstr "Modelos customizáveis" @@ -924,6 +960,30 @@ msgstr "As customizações não são publicadas" msgid "Customize phase" msgstr "Customizar Fase" +msgid "Customisable Templates" +msgstr "Modelos customizáveis" + +msgid "Customisations are published" +msgstr "Customizações estão publicadas" + +msgid "Customisations are unpublished" +msgstr "Customizações estão despublicadas" + +msgid "Customise" +msgstr "Customizar" + +msgid "Customise phase" +msgstr "Fase de customização" + +msgid "Customising for your Organisation" +msgstr "Customizing para sua organização" + +msgid "Customizable Templates" +msgstr "Modelos customizáveis" + +msgid "DMP Background" +msgstr "fundo do PGD" + msgid "DMP Templates" msgstr "Modelos de PGD" @@ -963,6 +1023,9 @@ msgstr "Os participantes da DMPTool são instituições, organizações sem fins msgid "DOCX" msgstr "DOCX" +msgid "DOCX (new window)" +msgstr "DOCX (nova janela)" + msgid "Data Contact Person" msgstr "Pessoa a contatar sobre os dados" @@ -1044,18 +1107,34 @@ msgstr "Não esqueça de salvar suas mudanças após fazer suas seleções." msgid "Download" msgstr "Baixar" + msgid "Download Plan" msgstr "Baixar plano" +msgid "Download Plan (new window)" +msgstr "Baixar Plano (nova janela)" + +msgid "Download global usage" +msgstr "Baixar uso global" + msgid "Download plans" msgstr "Baixar planos" +msgid "Download plans (new window)" +msgstr "Baixar planos (nova janela)" + msgid "Download settings" msgstr "Baixar parâmetros" +msgid "Download users" +msgstr "Baixar usuários" + msgid "Draft" msgstr "Rascunho" +msgid "Drag arrows to rearrange sections." +msgstr "Arrastar setas para rearranjar seções" + msgid "Edit" msgstr "Editar" @@ -1143,6 +1222,9 @@ msgstr "Insira instruções específicas para acompanhar esta pergunta. Se você msgid "Enter your guidance here. You can include links where needed." msgstr "Insira suas instruções aqui. Você pode incluir links onde necessário." +msgid "Error parsing links for a %{template}" +msgstr "Erro analisando links para um %{template}" + msgid "Error parsing links for a #{template_type(template)}" msgstr "Erro ao analisar links para um #{template_type(template)}" @@ -1155,8 +1237,8 @@ msgstr "Erro levantado ao salvar a visibilidade para o plano com id %{plan_id}" msgid "Error:" msgstr "Erro" -msgid "Example Answer" -msgstr "Exemplo de Resposta" +msgid "Example answer" +msgstr "Exemplo de resposta" msgid "Example citations" msgstr "Citações de exemplo" @@ -1566,8 +1648,8 @@ msgstr "Tamanho de fonte inválido" msgid "Invalid maximum pages" msgstr "Máximo de páginas inválido" -msgid "Invitation to %{email} issued successfully. \n" -msgstr "Convite para %{email} emitido com sucesso. \n" +msgid "Invitation to %{email} issued successfully." +msgstr "Convite para %{email} enviado com sucesso." msgid "Invite collaborators" msgstr "Convidar colaboradores" @@ -1728,6 +1810,9 @@ msgstr "Nome" msgid "Need to get others on your campus interested in the DMPTool? Use our Talking Points to guide your discussions. In general, a talking points document is designed to help you stay on track during meetings with those outside of your department. It ensures that your major points are at hand and helps you make progress towards the goals of the meeting." msgstr "Precisa fazer outras pessoas no seu campus interessar-se pelo DMPTool? Use nossos Pontos para Discussão na condução de seus encontros. De maneira geral, um documento com pontos de discussão é estruturado para ajudar você a manter sua linha de argumentação em encontros com pessoas de fora de seu departamento. Ele assegura que os pontos mais importantes estejam ao seu alcance e ajuda você a progredir em direção aos objetivos do encontro. " +msgid "New Notification" +msgstr "Nova notificação" + msgid "New Question" msgstr "Novo Pergunta" @@ -1752,6 +1837,9 @@ msgstr "Novos planos" msgid "New question:" msgstr "Novo perguntas" +msgid "New theme" +msgstr "Novo tema" + msgid "New users" msgstr "Novos usuários" @@ -1977,6 +2065,9 @@ msgstr "Nome do proprietário" msgid "PDF" msgstr "PDF" +msgid "PDF (new window)" +msgstr "PDF (nova janela)" + msgid "PDF formatting" msgstr "Formatação de PDF" @@ -2055,19 +2146,19 @@ msgstr "Planos" msgid "Please check the box to continue." msgstr "Por favor, selecione a caixa para continuar." -msgid "Please choose an organisation" -msgstr "Por favor, escolha uma organização." - msgid "Please choose one of the options." msgstr "Por favor, escolha uma das opções." +msgid "Please choose an organisation" +msgstr "Por favor, escolha uma organização." + msgid "Please do not reply to this email." msgstr "Por favor, não responda esta mensagem." -msgid "Please enter a First name." -msgstr "Por favor, insira o Primeiro Nome." +msgid "Please enter a First name. " +msgstr "Por favor, insira o Primeiro nome" -msgid "Please enter a Last name." +msgid "Please enter a Last name. " msgstr "Por favor, insira o Sobrenome" msgid "Please enter a password confirmation" @@ -2082,7 +2173,7 @@ msgstr "Por favor, insira um valor válido." msgid "Please enter an email address" msgstr "Por favor, insira um endereço de email." -msgid "Please enter an email address." +msgid "Please enter an email address. " msgstr "Por favor, insira um endereço de email." msgid "Please enter the name of your organisation" @@ -2358,6 +2449,9 @@ msgstr "Guia de Início Rápido" msgid "Quick start guide" msgstr "Guia de início rápido" +msgid "Re-order sections" +msgstr "Reordenar seções" + msgid "Read only" msgstr "Somente leitura" @@ -2391,6 +2485,9 @@ msgstr "Remover este link" msgid "Request Expert Feedback - Automated Email:" msgstr "Solicitar feedback de especialista - Email automático" +msgid "Request Expert Feedback - Message Displayed on Share Plan Tab:" +msgstr "Solicitar feedback de especialista - Mensagem Disponível na Aba de Compartilhar Plano" + msgid "Request Feedback" msgstr "Solicitar feedback" @@ -2424,6 +2521,13 @@ msgstr "Papel" msgid "Run your own filter" msgstr "Use seu próprio filtro" +msgid "SAMPLE MESSAGE: 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}." +msgstr "AMOSTRA DE MENSAGEM: Um(a) bibliotecário(o) de dados do(a) %{org_name} vai responder sua requesição em até 48" +" horas. Caso você tenha perguntas pendentes sobre este assunto porfavor nos contate" +" em %{organisation_email}." + msgid "Same as Principal Investigator" msgstr "O mesmo que Investigador Principal" @@ -2439,7 +2543,7 @@ msgstr "As amostras de planos são fornecidas por um órgão financiador, uma or msgid "Save" msgstr "Salvar" -msgid "Save Unsuccessful." +msgid "Save Unsuccessful. " msgstr "Não foi possível salvar." msgid "Saving..." @@ -2473,7 +2577,7 @@ msgid "See the full list" msgstr "Veja a lista completa" msgid "See the full list of participating institutions" -msgstr "Veja a lista completa de instituições participantes" +msgstr "Veja a lista completa das instituições participantes" msgid "See the full list of participating institutions." msgstr "Veja a lista completa de instituições participantes." @@ -2481,6 +2585,9 @@ msgstr "Veja a lista completa de instituições participantes." msgid "Select 'Transfer customisation' in the Actions menu to review your customisation(s) and make any necessary changes. When you are done, you must return to the Actions menu and publish your customisation(s)." msgstr "Selecione 'Transferir customização' no menu Ações para rever sua (s) customização(ões) e fazer as alterações necessárias. Quando estiver pronto, você deve retornar ao menu Ações e publicar suas Customização(oes)." +msgid "Select Guidance" +msgstr "Selecione a orientação" + msgid "Select all" msgstr "Selecionar tudo" @@ -2490,12 +2597,12 @@ msgstr "Selecione uma organização da lista ou deixe em branco se sua organiza msgid "Select an organisation from the list." msgstr "Selecione uma organização da lista." +msgid "Select one or more themes that are relevant to this guidance. This will display your generic organisation-level guidance, or any Schools/Departments for which you create guidance groups, across all templates that have questions with the corresponding theme tags." +msgstr "Selecione um tema relevante para esta instruções. Isso exibirá sua instruções genérica em nível de organização ou quaisquer Escolas/Departamentos para os quais você criar grupos de instruções em todos os modelos que tiverem perguntas com as tags de tema correspondentes." + msgid "Select one or more themes that are relevant to this question. This will allow similarly themed organisation-level guidance to appear alongside your question." msgstr "Selecione um ou mais temas relevantes para esta pergunta. Isso permitirá que sejam exibidas, junto com sua pergunta, instruções com temas similares no âmbito de sua organização." -msgid "Select one theme that is relevant to this guidance. This will display your generic organisation-level guidance, or any Schools/Departments for which you create guidance groups, across all templates that have questions with the corresponding theme tags." -msgstr "Selecione um tema relevante para esta instruções. Isso exibirá sua instruções genérica em nível de organização ou quaisquer Escolas/Departamentos para os quais você criar grupos de instruções em todos os modelos que tiverem perguntas com as tags de tema correspondentes." - msgid "Select phase to download" msgstr "Selecione a fase a ser baixada" @@ -2592,6 +2699,9 @@ msgstr "Ir para o conteúdo principal" msgid "Someone has requested a link to change your %{tool_name} password. You can do this through the link below." msgstr "Alguém solicitou um link para mudar sua senha em %{tool_name} password. Você pode fazer isso usando o link abaixo." +msgid "Sort by %{sort_field}" +msgstr "Ordenar por %{sort_field}" + msgid "Start" msgstr "Compartilhar" @@ -2613,8 +2723,8 @@ msgstr "Successo ao %{action} conta do %{username}" msgid "Successfully %{action} your %{object}." msgstr "Sucesso ao %{action} seu %{object}." -msgid "Successfully changed the permissions for #{@role.user.email}. They have been notified via email." -msgstr "Alterou com sucesso as permissões para #{@role.user.email}. Eles foram notificados por email." +msgid "Successfully changed the permissions for %{email}. They have been notified via email." +msgstr "Alterou com sucesso as permissões para %{email}. Eles foram notificados por email." msgid "Successfully deleted your theme" msgstr "Seu tema foi apagado com sucesso" @@ -2622,6 +2732,9 @@ msgstr "Seu tema foi apagado com sucesso" msgid "Successfully destroyed your notification" msgstr "Destruiu com sucesso sua notificação" +msgid "Successfully %{action} the %{object}." +msgstr "Sucesso ao %{action} o %{object}." + msgid "Successfully signed in" msgstr "Entrada bem sucedida" @@ -2748,6 +2861,19 @@ msgstr "A aba \"Compartilhar\" é outro lugar onde você pode definir a visibili msgid "The answer to this question affects how you organize the data as well as the level of versioning you will need to undertake. Keeping track of rapidly changing datasets can be a challenge so it is imperative that you begin with a plan to carry you through the entire data management process." msgstr "A resposta a esta questão afeta como você organiza os dados, bem como o nível de versionamento que você precisará realizar. Manter o controle de conjuntos de dados que mudam rapidamente pode ser um desafio, por isso é imperativo começar com um plano para levá-lo a todo o processo de gerenciamento de dados." +msgid "The above plan creator(s) have agreed that others may use as" +" much of the text of this plan as they would like in their own plans," +" and customise it as necessary. You do not need to credit the creator(s)" +" as the source of the language used, but using any of the plan's text" +" does not imply that the creator(s) endorse, or have any relationship to," +" your project or proposal" +msgstr "Os criadores do plano acima concordaram que outros podem usar o" +" quanto quiser do texto deste plano em seus próprios planos," +" e customizar caso necessário. Você não precisa fornecer crédito aos criadores" +" quanto a linguagem fonte utilizada, mas quando utilizada qualquer porção do texto contido no plano" +" não implica que os criadores endossem, ou tenham alguma relação" +" com a proposta do seu projeto" + msgid "The current #{scheme.description} iD has been already linked to a user with email #{identifier.user.email}" msgstr "A iD do #{scheme.description} atual já foi vinculada a um usuário com email #{identifier.user.email}" @@ -2814,6 +2940,9 @@ msgstr "Tema criado com sucesso" msgid "Theme updated successfully" msgstr "Tema atualizado com sucesso" +msgid "The ‘Share’ tab is also where you can set your plan visibility." +msgstr "A guia ‘Compartilhar’ também é onde você pode definir a visibilidade do seu plano." + msgid "Themes" msgstr "Temas" @@ -2859,8 +2988,8 @@ msgstr "Não há dúvidas com o id %{question_id} associado ao id do plano %{pla msgid "There is no theme associated with id %{id}" msgstr "Não há nenhum tema associado com a id %{id}" -msgid "There may also be an option to request feedback on your plan (on the “Share” tab). This is available when research support staff at your institution have enabled the service. Click to “Request feedback” and your local administrators will be alerted to your request. Their comments will be visible in the “Comments” field adjacent to each question. You will receive an email notification when an administrator provides feedback." -msgstr "Também pode haver uma opção para solicitar feedback sobre o seu plano (na guia “Compartilhar”). Isso está disponível quando a equipe de suporte de pesquisa da sua instituição habilitou o serviço. Clique em “Solicitar comentários” e seus administradores locais serão alertados sobre sua solicitação. Seus comentários serão visíveis no campo “Comentários” ao lado de cada pergunta. Você receberá uma notificação por email quando um administrador fornecer feedback." +msgid "There may also be an option to request feedback on your plan. This is available when research support staff at your organisation have enabled this service. Click to ‘Request feedback’ and your local administrators will be alerted to your request. Their comments will be visible in the ‘Comments’ field adjacent to each question. You will be notified by email when an administrator provides feedback." +msgstr "Também pode haver uma opção para solicitar feedback sobre seu plano. Isso está disponível quando a equipe de suporte de pesquisa da sua organização habilitou esse serviço. Clique para ‘Solicitar comentários’ e seus administradores locais serão alertados sobre sua solicitação. Seus comentários ficarão visíveis no campo ‘Comentários’ ao lado de cada pergunta. Você será notificado por e-mail quando um administrador fornecer feedback." msgid "There seems to be a problem with your logo. Please upload it again." msgstr "Parece haver um problema com seu logo. Por favor, suba-o novamente." @@ -2985,6 +3114,9 @@ msgstr "URL" msgid "Unable to %{action} %{username}" msgstr "Incapaz de %{action} %{username}" +msgid "Unable to %{action} the %{object}.%{errors}" +msgstr "Incapaz de %{action} o %{object}.%{errors}" + msgid "Unable to change the plan's status since it is needed at least %{percentage} percentage responded" msgstr "Não conseguimos mudar o status do plano. É preciso pelo menos %{percentage} de respostas." @@ -2994,11 +3126,11 @@ msgstr "Não conseguimos mudar o status de teste do plano" msgid "Unable to change your organisation affiliation at this time." msgstr "Não conseguimos mudar sua afiliação organizacional neste momento." -msgid "Unable to create a new section because the phase you specified does not exist." -msgstr "Não criar uma nova seção porque a fase que você especificou não existe." +msgid "Unable to create a new section. The phase you specified does not exist." +msgstr "Não conseguimos criar uma nova seção. A fase especificada não existe." msgid "Unable to create a new version of this template." -msgstr "Não criar uma nova versão deste modelo." +msgstr "Não conseguimos criar uma nova versão deste modelo." msgid "Unable to create your account at this time." msgstr "Não criar sua conta no momento." @@ -3006,6 +3138,9 @@ msgstr "Não criar sua conta no momento." msgid "Unable to create your account." msgstr "Não criar sua conta" +msgid "Unable to create your account.#{errors_for_display(resource)}" +msgstr "Não conseguimos criar sua conta.#{errors_for_display(resource)}" + msgid "Unable to customize that template." msgstr "Não customização esse modelo." @@ -3156,6 +3291,9 @@ msgstr "Ver tudo" msgid "View all guidance" msgstr "Ver toda a instrução" +msgid "View all notifications" +msgstr "Ver todas Notificações" + msgid "View all organisations" msgstr "Ver todas as organizações" @@ -3165,6 +3303,9 @@ msgstr "Ver todos os resultados da busca" msgid "View all templates" msgstr "Ver todos os modelos" +msgid "View all themes" +msgstr "Ver todos os temas" + msgid "View all users" msgstr "Ver todos os usuários" @@ -3423,6 +3564,12 @@ msgstr "Você pode modificar suas preferências de notificação na página com msgid "You may or may not have the rights to do so, depending upon whether that data were accessed under a license with terms of use." msgstr "Você pode ou não ter os direitos para fazê-lo, dependendo se esses dados foram acessados ​​sob uma licença com os termos de uso." +msgid "You may change your notification preferences on your profile page. " +msgstr "Você pode modificar suas preferências de notificação na sua página de perfil. " + +msgid "You may place them before or after the main template sections." +msgstr "Você pode colocá-las antes ou depois da seção de modelos principais." + msgid "You must accept the terms and conditions to register." msgstr "Você deve aceitar os termos e condições para registrar-se." @@ -3435,6 +3582,9 @@ msgstr "Você deve inserir uma URL válida (e.g. https://organizacao.org)." msgid "You must enter a valid email address." msgstr "Você deve inserir um email válido." +msgid "You must provide a valid email address and select a permission level." +msgstr "Você deve fornecer um email valido e selecionar um nível de permissão." + msgid "You must select a funder from the list or click the checkbox." msgstr "Você deve selecionar um financiador na lista ou clicar na caixa de seleção." @@ -3495,6 +3645,13 @@ msgstr "Para entrar no sistema, sua conta foi vinculada a suas credenciais insti msgid "Your account is linked to your institutional credentials for login. Please contact the helpdesk to change your organisation." msgstr "Para entrar no sistema, sua conta foi vinculada a suas credenciais institucionais. Por favor, entre em contato com o helpdesk para alterar sua organização." +msgid "Your colleague %{inviter_name} has invited you to contribute to +" +" their Data Management Plan in %{tool_name}" +msgstr "Seu colega %{inviter_name} convidou você para contribuir em +" +" seu Plano de Gestão de Dados %{tool_name}" + msgid "Your email address is also your login id and therefore an important part of your account information. For your safety we require you to confirm your password to make this change." msgstr "Seu email é também sua id para entrar no sistema. É portanto uma parte importante das informações de sua conta. Para sua segurança, solicitamos que confirme sua senha para realizar essa mudança." @@ -3598,7 +3755,13 @@ msgid "completed_plans" msgstr "completed_plans" msgid "copied" -msgstr "copieado" +msgstr "copiado" + +msgid "copy" +msgstr "copiar" + +msgid "create" +msgstr "criar" msgid "created" msgstr "criado" @@ -3618,6 +3781,9 @@ msgstr "desativar" msgid "deactivated" msgstr "desativado" +msgid "delete" +msgstr "apagar" + msgid "deleted" msgstr "apagado" @@ -3642,6 +3808,9 @@ msgstr "generate_version! requer um modelo publicado" msgid "guidance" msgstr "instruções" +msgid "get involved (new window)" +msgstr "se envolver (nova janela)" + msgid "guidance group" msgstr "grupo de instruções" @@ -3651,6 +3820,9 @@ msgstr "instruções sobre" msgid "into your browser" msgstr "em seu navegador" +msgid "isn't a valid value" +msgstr "Não é um valor válido" + msgid "locals should be a Hash object" msgstr "locals deve ser um objeto Hash" @@ -3660,6 +3832,9 @@ msgstr "logo" msgid "mock project for testing, practice, or educational purposes" msgstr "projeto simulado para testes, prática ou propósitos educacionais" +msgid "must be after %{date}" +msgstr "necessita ser depois de %{date}" + msgid "must be logged in" msgstr "deve estar logado" @@ -3699,6 +3874,9 @@ msgstr "organizacional" msgid "password" msgstr "senha" +msgid "page for guidance." +msgstr "página para orientação." + msgid "path_params should be a Hash object" msgstr "path_params deve ser um objeto hash" @@ -3708,6 +3886,9 @@ msgstr "permissões" msgid "phase" msgstr "fase" +msgid "permission" +msgstr "permissão" + msgid "plan" msgstr "plano" @@ -3726,12 +3907,18 @@ msgstr "privado" msgid "profile" msgstr "perfil" +msgid "profile for %{username}" +msgstr "perfil de %{username}" + msgid "project details coversheet" msgstr "capa com detalhes do projeto" msgid "public" msgstr "público" +msgid "publish" +msgstr "publicar" + msgid "query_params should be a Hash object" msgstr "query_params deve ser um objeto hash" @@ -3753,6 +3940,9 @@ msgstr "ler o plano e dar feedback." msgid "read-only" msgstr "somente leitura" +msgid "remove" +msgstr "remover" + msgid "removed" msgstr "removido" @@ -3762,6 +3952,9 @@ msgstr "revisor" msgid "role" msgstr "papel" +msgid "save" +msgstr "salvar" + msgid "saved" msgstr "salvo" @@ -3798,11 +3991,20 @@ msgstr "plano de teste" msgid "unanswered questions" msgstr "questões não respondida" +msgid "upgrade_customization! cannot be carried out since there is no published template of its current funder" +msgstr "upgrade_customization! não pode ser realizado, uma vez que não existe um modelo publicado do seu financiador atual" + +msgid "unpublish" +msgstr "despublicar" + +msgid "update" +msgstr "atualizar" + msgid "updated" msgstr "Atualizado" -msgid "upgrade_customization! cannot be carried out since there is no published template of its current funder" -msgstr "upgrade_customization! não pode ser realizado, uma vez que não existe um modelo publicado do seu financiador atual" +msgid "upgrade cannot be carried out since there is no published template of its current funder" +msgstr "atualização não pode ser realizada porque não existe um modelo publicado do seu financiador atual" msgid "upgrade_customization! requires a customised template" msgstr "upgrade_customization! requer um modelo customizado" diff --git a/config/routes.rb b/config/routes.rb index ee594dba41..c2bc1e5a86 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -135,6 +135,7 @@ member do get 'answer' get 'share' + get 'request_feedback' get 'download' post 'duplicate' post 'visibility', constraints: {format: [:json]} @@ -188,6 +189,7 @@ get 'organisationally_or_publicly_visible/:page', action: :organisationally_or_publicly_visible, on: :collection, as: :organisationally_or_publicly_visible get 'publicly_visible/:page', action: :publicly_visible, on: :collection, as: :publicly_visible get 'org_admin/:page', action: :org_admin, on: :collection, as: :org_admin + get 'org_admin_other_user/:page', action: :org_admin_other_user, on: :collection, as: :org_admin_other_user end # Paginable actions for users resources :users, only: [] do @@ -227,12 +229,18 @@ # ORG ADMIN specific pages namespace :org_admin do + resources :users, only: [:edit, :update], controller: "users" do + member do + get 'user_plans' + end + end resources :plans, only: [:index] do member do get 'feedback_complete' end end + resources :templates do resources :customizations, only: [:create], controller: "template_customizations" @@ -246,6 +254,7 @@ member do get 'history' + get 'template_export', action: :template_export patch 'publish', action: :publish, constraints: {format: [:json]} patch 'unpublish', action: :unpublish, constraints: {format: [:json]} end @@ -279,7 +288,13 @@ namespace :super_admin do resources :orgs, only: [:index, :new, :create, :destroy] resources :themes, only: [:index, :new, :create, :edit, :update, :destroy] - resources :users, only: [:edit, :update] + resources :users, only: [:edit, :update] do + member do + put :merge + put :archive + get :search + end + end resources :notifications, except: [:show] end diff --git a/lib/tasks/upgrade.rake b/lib/tasks/upgrade.rake index 788d1b26d7..c0644d9df9 100644 --- a/lib/tasks/upgrade.rake +++ b/lib/tasks/upgrade.rake @@ -130,11 +130,16 @@ namespace :upgrade do Rake::Task['upgrade:add_missing_token_permission_types'].execute orgs = Org.where(is_other: false).select(:id) orgs.each do |org| - org.grant_api!(TokenPermissionType.where(token_type: 'statistics')) + unless org.token_permission_types.include?(TokenPermissionType::STATISTICS) + org.grant_api!(TokenPermissionType.where(token_type: 'statistics')) + end + unless org.token_permission_types.include?(TokenPermissionType::PLANS) + org.grant_api!(TokenPermissionType.where(token_type: 'plans')) + end end users = User.joins(:perms).where(org_id: orgs).where(api_token: [nil, '']) users.each do |user| - if user.can_org_admin? + if user.can_org_admin? && user.api_token.blank? # Generate the tokens directly instead of via the User.keep_or_generate_token! method so that we do not spam users!! user.api_token = loop do random_token = SecureRandom.urlsafe_base64(nil, false) diff --git a/lib/unique_random.rb b/lib/unique_random.rb new file mode 100644 index 0000000000..9ea470fa9e --- /dev/null +++ b/lib/unique_random.rb @@ -0,0 +1,11 @@ +module UniqueRandom + + def unique_random(field_name:, prefix: '', suffix:'', length: nil) + return loop do + rand = SecureRandom.urlsafe_base64(length, false) + constructed = "#{prefix}#{rand}#{suffix}" + break constructed unless self.exists?(field_name.to_sym => constructed) + end + end + +end diff --git a/spec/factories/departments.rb b/spec/factories/departments.rb index b480804d40..75600e1571 100644 --- a/spec/factories/departments.rb +++ b/spec/factories/departments.rb @@ -20,6 +20,6 @@ factory :department do name { Faker::Commerce.department } code { SecureRandom.hex(5) } - org_id { Faker::Number.number(5) } + org_id { Faker::Number.number(digits: 5) } end end diff --git a/spec/factories/question_formats.rb b/spec/factories/question_formats.rb index d7e00d0ceb..6b01a8444a 100644 --- a/spec/factories/question_formats.rb +++ b/spec/factories/question_formats.rb @@ -13,7 +13,7 @@ FactoryBot.define do factory :question_format do - title { Faker::Lorem.words(3).join } + title { Faker::Lorem.words(number: 3).join } description { "http://test.host" } formattype { QuestionFormat::FORMAT_TYPES.sample } diff --git a/spec/factories/stat_created_plan.rb b/spec/factories/stat_created_plan.rb index f0ad5b9688..df01c31b24 100644 --- a/spec/factories/stat_created_plan.rb +++ b/spec/factories/stat_created_plan.rb @@ -2,6 +2,6 @@ factory :stat_created_plan do date { Date.today } org { create(:org) } - count { Faker::Number.number(10) } + count { Faker::Number.number(digits: 10) } end end diff --git a/spec/factories/stat_joined_user.rb b/spec/factories/stat_joined_user.rb index 32205ce16e..f53cb948d5 100644 --- a/spec/factories/stat_joined_user.rb +++ b/spec/factories/stat_joined_user.rb @@ -2,6 +2,6 @@ factory :stat_joined_user do date { Date.today } org { create(:org) } - count { Faker::Number.number(10) } + count { Faker::Number.number(digits: 10) } end end diff --git a/spec/features/feedback_requests_spec.rb b/spec/features/feedback_requests_spec.rb index b08a2596de..69b0ed7f1c 100644 --- a/spec/features/feedback_requests_spec.rb +++ b/spec/features/feedback_requests_spec.rb @@ -25,8 +25,16 @@ # Actions click_link plan.title expect(current_path).to eql(plan_path(plan)) - click_link "Share" - click_link "Request feedback" + + # Click "Request feedback" tab + within("ul.nav.nav-tabs") do + click_link "Request feedback" + end + + # Click "Request feedback" button within panel + within("div.panel") do + click_link "Request feedback" + end # Expectations expect(plan.reload).to be_feedback_requested diff --git a/spec/features/plans_spec.rb b/spec/features/plans_spec.rb index 4f5625fe22..eaf307472d 100644 --- a/spec/features/plans_spec.rb +++ b/spec/features/plans_spec.rb @@ -30,32 +30,21 @@ scenario "User creates a new Plan", :js do # Action - # ------------------------------------------------------------- - # start DMPTool customization - # The DMPTool menu item and button have the same label! - # ------------------------------------------------------------- - #click_link "Create plan" - find("a.btn[href=\"#{new_plan_path}\"]").click - # ------------------------------------------------------------- - # end DMPTool customization - # ------------------------------------------------------------- - + click_link "Create plan" fill_in :plan_title, with: "My test plan" fill_in :plan_org_name, with: @research_org.name - # ------------------------------------------------------------- - # start DMPTool customization - # ------------------------------------------------------------- + # -------------------------------------------------------- + # Start DMPTool Customization + # -------------------------------------------------------- #find('#suggestion-2-0').click #fill_in :plan_funder_name, with: @funding_org.name #find('#suggestion-3-0').click find('#suggestion-1-0').click fill_in :plan_funder_name, with: @funding_org.name - find('#suggestion-2-0').click - # ------------------------------------------------------------- - # end DMPTool customization - # ------------------------------------------------------------- - + # -------------------------------------------------------- + # End DMPTool Customization + # -------------------------------------------------------- click_button "Create plan" # Expectations @@ -72,65 +61,20 @@ within "#edit_plan_#{@plan.id}" do fill_in "Grant number", with: "Innodia" fill_in "Project abstract", with: "Plan abstract..." - - # ------------------------------------------------------------- - # start DMPTool customization - # DMPTool does not expose an identifier - # ------------------------------------------------------------- - #fill_in "ID", with: "ABCDEF" - # ------------------------------------------------------------- - # end DMPTool customization - # ------------------------------------------------------------- - - fill_in "ORCID iD", with: "My ORCID" - - # ------------------------------------------------------------- - # start DMPTool customization - # DMPTool does not expose a phone number and relabelled button - # ------------------------------------------------------------- - #fill_in "Phone", with: "07787 000 0000" - #click_button "Save" - click_button "Submit" - # ------------------------------------------------------------- - # end DMPTool customization - # ------------------------------------------------------------- - - # Reload the plan to get the latest from memory - @plan.reload - -# DMPTool issue -# For some reason these assertions sometimes happen before the UI has -# had a chance to clik the Submit button - - expect(current_path).to eql(overview_plan_path(@plan)) - expect(@plan.title).to eql("My test plan") - expect(@plan.funder_name).to eql(@funding_org.name) - expect(@plan.grant_number).to eql("1234") - expect(@plan.description).to eql("Plan abstract...") - - # ------------------------------------------------------------- - # start DMPTool customization - # DMPTool does not expose an identifier - # ------------------------------------------------------------- - #expect(@plan.identifier).to eql("ABCDEF") - # ------------------------------------------------------------- - # end DMPTool customization - # ------------------------------------------------------------- - - name = [@user.firstname, @user.surname].join(" ") - expect(@plan.principal_investigator).to eql(name) - expect(@plan.principal_investigator_identifier).to eql("My ORCID") - expect(@plan.principal_investigator_email).to eql(@user.email) - - # ------------------------------------------------------------- - # start DMPTool customization - # DMPTool does not expose a phone number and relabelled button - # ------------------------------------------------------------- - #expect(@plan.principal_investigator_phone).to eql("07787 000 0000") - # ------------------------------------------------------------- - # end DMPTool customization - # ------------------------------------------------------------- - + fill_in "ID", with: "ABCDEF" + # -------------------------------------------------------- + # Start DMPTool Customization + # ORCID sent us a complaint about allowing people to manually + # enter in an ORCID id. We will have to revise this workflow + # so that it complies with their standards. E.g. send out an + # email to the PI that asks them to assert the connection + # -------------------------------------------------------- + #fill_in "ORCID iD", with: "My ORCID" + # -------------------------------------------------------- + # End DMPTool Customization + # -------------------------------------------------------- + fill_in "Phone", with: "07787 000 0000" + click_button "Save" end # Reload the plan to get the latest from memory @@ -144,7 +88,17 @@ expect(@plan.identifier).to eql("ABCDEF") name = [@user.firstname, @user.surname].join(" ") expect(@plan.principal_investigator).to eql(name) - expect(@plan.principal_investigator_identifier).to eql("My ORCID") + # -------------------------------------------------------- + # Start DMPTool Customization + # ORCID sent us a complaint about allowing people to manually + # enter in an ORCID id. We will have to revise this workflow + # so that it complies with their standards. E.g. send out an + # email to the PI that asks them to assert the connection + # -------------------------------------------------------- + #expect(@plan.principal_investigator_identifier).to eql("My ORCID") + # -------------------------------------------------------- + # End DMPTool Customization + # -------------------------------------------------------- expect(@plan.principal_investigator_email).to eql(@user.email) expect(@plan.principal_investigator_phone).to eql("07787 000 0000") end diff --git a/spec/mixins/versionable_model_spec.rb b/spec/mixins/versionable_model.rb similarity index 99% rename from spec/mixins/versionable_model_spec.rb rename to spec/mixins/versionable_model.rb index 2135a43379..6912171ce8 100644 --- a/spec/mixins/versionable_model_spec.rb +++ b/spec/mixins/versionable_model.rb @@ -4,7 +4,6 @@ shared_examples_for "VersionableModel" do - context "attributes" do it { is_expected.to have_readonly_attribute(:versionable_id) } diff --git a/spec/models/answer_spec.rb b/spec/models/answer_spec.rb index 67ff2028d0..a532ab4bc8 100644 --- a/spec/models/answer_spec.rb +++ b/spec/models/answer_spec.rb @@ -73,11 +73,11 @@ end - describe "#is_valid?" do + describe "#answered?" do let!(:answer) { create(:answer) } - subject { answer.is_valid? } + subject { answer.answered? } context "question present, question format is option and options empty" do diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 928172c87d..4529958ca9 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -506,9 +506,9 @@ context "when user is not a new record and api_token is an empty string" do - let!(:user) { create(:user, api_token: nil) } + let!(:user) { create(:user, api_token: "") } - it { expect { subject }.not_to change { user.api_token } } + it { expect { subject }.to change { user.api_token }.to(nil) } end @@ -535,7 +535,7 @@ context "when user is not a new record and api_token is nil" do - let!(:user) { create(:user, api_token: "") } + let!(:user) { create(:user, api_token: nil) } it { expect { subject }.to change { user.api_token } } @@ -545,7 +545,7 @@ let!(:user) { build(:user, api_token: "") } - it { expect { subject }.not_to change { user.new_record? } } + it { expect { subject }.not_to change { user.api_token } } end end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 421c141a69..6e8b528371 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -7,6 +7,9 @@ require 'rspec/rails' require 'capybara-screenshot/rspec' +# Clear all of the screenshots from old tests +Dir[Rails.root.join('tmp/capybara/*')].each { |f| File.delete(f) } + # Add additional requires below this line. Rails is not loaded until this point! # Requires supporting ruby files with custom matchers and macros, etc, in # spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are diff --git a/spec/support/capybara.rb b/spec/support/capybara.rb index 9c5e0702ca..5fb9609abb 100644 --- a/spec/support/capybara.rb +++ b/spec/support/capybara.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +require 'webdrivers/chromedriver' require_relative "helpers/capybara_helper" require_relative "helpers/sessions_helper" require_relative "helpers/tiny_mce_helper" @@ -10,6 +11,9 @@ Capybara.default_driver = :rack_test +# Cache for one hour +Webdrivers.cache_time = 3600 + # This is a customisation of the default :selenium_chrome_headless config in: # https://github.com/teamcapybara/capybara/blob/master/lib/capybara.rb # diff --git a/spec/support/helpers/tiny_mce_helper.rb b/spec/support/helpers/tiny_mce_helper.rb index 5dc48e3ac0..4edaf36d70 100644 --- a/spec/support/helpers/tiny_mce_helper.rb +++ b/spec/support/helpers/tiny_mce_helper.rb @@ -19,8 +19,8 @@ def tinymce_fill_in(id, with: '') # increase the wait time for XHR loaded tinyMCE elements # we should investigate why its taking longer to load # ------------------------------------------------ - #until x == 50 || page.evaluate_script("tinyMCE.get('#{id}') !== null") - until x == 100 || page.evaluate_script("tinyMCE.get('#{id}') !== null") + until x == 50 || page.evaluate_script("tinyMCE.get('#{id}') !== null") + #until x == 100 || page.evaluate_script("tinyMCE.get('#{id}') !== null") # ------------------------------------------------ # end DMPTool customization # ------------------------------------------------