diff --git a/.gitignore b/.gitignore index 33c0294..2b59cc6 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,9 @@ # Ignore the test DB db/test.sqlite3 +# Ignore the SimpleCov output +coverage + # Ignore database configuration and token secrets config/database.yml config/secrets.yml diff --git a/.travis.yml b/.travis.yml index 6bbd6e5..bc14e2d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,9 @@ before_script: - cp config/database_example.yml config/database.yml - cp config/secrets_example.yml config/secrets.yml + - cp config/initializers/devise.rb.example config/initializers/devise.rb + - cp config/initializers/recaptcha.rb.example config/initializers/recaptcha.rb + - cp config/initializers/wicked_pdf.rb.example config/initializers/wicked_pdf.rb - bundle exec rake db:migrate RAILS_ENV=test script: diff --git a/Gemfile b/Gemfile index 6c77fdc..5290fa3 100644 --- a/Gemfile +++ b/Gemfile @@ -15,10 +15,11 @@ # ------------------------------------------------ # DATABASE/SERVER +gem 'mysql2', '~> 0.3.18' gem 'pg' +gem 'mysql2', '~> 0.3.18' gem 'flag_shih_tzu' # Allows for bitfields in activereccord - # ------------------------------------------------ # JS <-> RUBY BRIDGE gem 'libv8' @@ -47,6 +48,8 @@ gem 'devise_invitable' gem 'omniauth' gem 'omniauth-shibboleth' +gem 'omniauth-orcid' + #rolify for roles gem 'rolify' # Gems for repository integration @@ -63,7 +66,7 @@ gem 'jquery-rails' gem 'twitter-bootstrap-rails', '2.2.8' gem 'tinymce-rails' # WYSIWYG EDITOR -gem 'contact_us', '>= 1.2.0' # COULD BE EASILY REPLACED WITH OUR OWN CODE +gem 'contact_us', '>= 1.2.0' # COULD BE EASILY REPLACED WITH OUR OWN CODE gem 'recaptcha' gem 'dragonfly' # LOGO UPLOAD @@ -103,7 +106,9 @@ gem 'minitest-rails-capybara' gem 'minitest-reporters' gem 'rack-test' + gem 'webmock' gem 'sqlite3' + gem 'simplecov', require: false end group :development do diff --git a/Gemfile.lock b/Gemfile.lock index 432daf6..8359a7c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -108,6 +108,8 @@ concurrent-ruby (1.0.2) contact_us (1.2.0) rails (>= 4.2.0) + crack (0.4.3) + safe_yaml (~> 1.0.0) daemons (1.2.4) debug_inspector (0.0.2) devise (4.2.0) @@ -119,6 +121,7 @@ devise_invitable (1.7.0) actionmailer (>= 4.0.0) devise (>= 4.0.0) + docile (1.1.5) dragonfly (1.0.12) addressable (~> 2.3) multi_json (~> 1.0) @@ -146,6 +149,7 @@ has_scope (0.6.0) actionpack (>= 3.2, < 5) activesupport (>= 3.2, < 5) + hashdiff (0.3.0) hashie (3.4.6) htmltoword (0.5.1) actionpack @@ -169,6 +173,7 @@ jquery-ui-rails (5.0.5) railties (>= 3.2.16) json (1.8.3) + jwt (1.5.6) kaminari (0.17.0) actionpack (>= 3.0.0) activesupport (>= 3.0.0) @@ -211,13 +216,26 @@ minitest (>= 5.0) ruby-progressbar multi_json (1.12.1) + multi_xml (0.5.5) multipart-post (2.0.0) + mysql2 (0.3.21) nokogiri (1.6.8) mini_portile2 (~> 2.1.0) pkg-config (~> 1.1.7) + oauth2 (1.2.0) + faraday (>= 0.8, < 0.10) + jwt (~> 1.0) + multi_json (~> 1.3) + multi_xml (~> 0.5) + rack (>= 1.2, < 3) omniauth (1.3.1) hashie (>= 1.2, < 4) rack (>= 1.0, < 3) + omniauth-oauth2 (1.4.0) + oauth2 (~> 1.0) + omniauth (~> 1.2) + omniauth-orcid (1.2.1) + omniauth-oauth2 (~> 1.3) omniauth-shibboleth (1.2.1) omniauth (>= 1.0.0) orm_adapter (0.5.0) @@ -274,6 +292,7 @@ rolify (5.1.0) ruby-progressbar (1.8.1) rubyzip (1.2.0) + safe_yaml (1.0.4) sass (3.4.22) sass-rails (5.0.6) railties (>= 4.0.0, < 6) @@ -282,6 +301,11 @@ sprockets-rails (>= 2.0, < 4.0) tilt (>= 1.1, < 3) sax-machine (1.3.2) + simplecov (0.12.0) + docile (~> 1.1.0) + json (>= 1.8, < 3) + simplecov-html (~> 0.10.0) + simplecov-html (0.10.0) sprockets (3.7.0) concurrent-ruby (~> 1.0) rack (> 1, < 3) @@ -321,6 +345,10 @@ binding_of_caller (>= 0.7.2) railties (>= 4.0) sprockets-rails (>= 2.0, < 4.0) + webmock (2.1.0) + addressable (>= 2.3.6) + crack (>= 0.3.2) + hashdiff wicked_pdf (1.1.0) wkhtmltopdf-binary (0.12.3) xpath (2.0.0) @@ -354,7 +382,9 @@ libv8 minitest-rails-capybara minitest-reporters + mysql2 (~> 0.3.18) omniauth + omniauth-orcid omniauth-shibboleth pg protected_attributes @@ -368,6 +398,7 @@ responders (~> 2.0) rolify sass-rails + simplecov sqlite3 swagger-docs therubyracer (>= 0.11.4) @@ -376,6 +407,7 @@ twitter-bootstrap-rails (= 2.2.8) uglifier web-console (~> 2.0) + webmock wicked_pdf wkhtmltopdf-binary yaml_db! diff --git a/README.md b/README.md index 597ae17..88ceaba 100644 --- a/README.md +++ b/README.md @@ -15,87 +15,22 @@ #### Summary -#### Pre-requisites -Roadmap is a Ruby on Rails application and you will need to have: -1. Ruby >= 2.0.0p247 -2. Rails >= 4.0 -3. MySql >= 5.0 +#### Installation and Requirements +See the [Installation Guide](https://github.com/DMPRoadmap/roadmap/wiki/Installation) -Further details on how to install Ruby on Rails applications are available from the Ruby on Rails site: http://rubyonrails.org +#### Migrating data from a running instance of DMPOnline_v4 or DMPTool +Migration instructions will be coming soon -Further details on how to install MySQL and create your first user and database. Be sure to follow the instructions for your particular environment. -* Install: http://dev.mysql.com/downloads/mysql/ -* Create a user: http://dev.mysql.com/doc/refman/5.7/en/create-user.html -* Create the database: http://dev.mysql.com/doc/refman/5.7/en/creating-database.html - -You may also find the following resources handy: - -* The Getting Started Guide: http://guides.rubyonrails.org/getting_started.html -* Ruby on Rails Tutorial Book: http://www.railstutorial.org/ - -#### Installation -* Create your mysql db. Select UTF-8 Unicode (utf8mb4) encoding. -* Fork the repository and then clone it onto your server - -> > git clone https://github.com/[your organization]/roadmap.git - -> > cd roadmap - -* Make copies of the yaml configuration files and update the values for your installation - -> > cp config/database_example.yml config/database.yml -> > cp config/secrets_example.yml config/secrets.yml - -* Create an environment variable for your instance's secret (as defined in config/secrets.yml). You should use the following command to generate secrets for each of your environments, storing the production one in the environment variable: - -> > rake secret - -* Run bundler and perform the DB migrations - -> > gem install bundler (if bundler is not yet installed) - -> > bundle install - -> > rake db:migrate - -> > rake db:seed - -* Setup the devise authentication gem - -> > rails generate devise:install (Is this really necessary?) - -* Start the application - -> > rails server - -* Verify that the site is running properly by going to http://localhost:3000 -* Login as the default administrator: 'super_admin@example.com' - 'password1' #### Troubleshooting -##### Installation - OSX: - -``` -An error occurred while installing libv8 (3.11.8.17), and Bundler cannot continue. - -Make sure that `gem install libv8 -v '3.11.8.17'` succeeds before bundling. -``` - -If you are installing on a system that already has v8 installed then you may need to install the libv8 gem manually using your system's current v8 engine. If you're using homebrew to manage your packages you should run 'brew update' and 'brew upgrade' to make sure you have the latest packages - -> > gem uninstall -a libv8 - -> > gem install libv8 -v '<>' -- --with-system-v8 - -> > bundle install +See the [Troubleshooting Guide](https://github.com/DMPRoadmap/roadmap/wiki/Troubleshooting) #### Support Issues should be reported here on [Github Issues](https://github.com/DMPRoadmap/roadmap/issues) Please be advised though that we can only provide limited support for your local installations. #### Become a contributor -Fork this repository and make your modifications in a new branch. Then create a pull request to our 'development' branch. We will reject any pull request made against the 'master' branch. Once your pull request has been submitted the team will review your request and accept it if appropriate. - -Join the developer email listserv at www.jiscmail.ac.uk/DMPONLINE-DEV +See the [Contributor Guide](https://github.com/DMPRoadmap/roadmap/wiki/Contributing) #### License The DMP Roadmap project uses the MIT License. diff --git a/app/admin/org_token_permission.rb b/app/admin/org_token_permission.rb deleted file mode 100644 index 4075d5cf..0000000 --- a/app/admin/org_token_permission.rb +++ /dev/null @@ -1,31 +0,0 @@ -ActiveAdmin.register OrgTokenPermission do - permit_params :organisation_id, :token_permission_type_id - - menu priority: 40, label: proc{ I18n.t('admin.org_token_permission')}, parent: "Api" - - index do - column I18n.t('admin.org') do |n| - link_to n.organisation, [:admin,n] - end - column I18n.t('admin.token_permission') do |n| - link_to n.token_permission_type, [:admin,n] - end - - actions - end - - show do - attributes_table do - row :organisation_id - row :token_permission_type_id - end - end - - controller do - def permitted_params - params.permit! - end - end - - -end diff --git a/app/controllers/api/v0/guidance_groups_controller.rb b/app/controllers/api/v0/guidance_groups_controller.rb index a22c9b2..d300b39 100644 --- a/app/controllers/api/v0/guidance_groups_controller.rb +++ b/app/controllers/api/v0/guidance_groups_controller.rb @@ -5,7 +5,7 @@ def show # check if the user has permission to use the guidances api - if has_auth(constant("api_endpoint_types.guidances")) + if has_auth(constant("token_permission_types.guidances")) # determine if they have authorization to view this guidance group if GuidanceGroup.can_view?(@user, params[:id]) respond_with get_resource @@ -18,7 +18,7 @@ end def index - if has_auth(constant("api_endpoint_types.guidances")) + if has_auth(constant("token_permission_types.guidances")) @all_viewable_groups = GuidanceGroup.all_viewable(@user) respond_with @all_viewable_groups else diff --git a/app/controllers/api/v0/statistics_controller.rb b/app/controllers/api/v0/statistics_controller.rb index ec21140..f893bc5 100644 --- a/app/controllers/api/v0/statistics_controller.rb +++ b/app/controllers/api/v0/statistics_controller.rb @@ -8,7 +8,7 @@ # @return a count of users who joined DMPonline between the optional specified dates # users are scoped to the organisation of the user initiating the call def users_joined - if has_auth(constant("api_endpoint_types.statistics")) + if has_auth(constant("token_permission_types.statistics")) users = restrict_date_range(@user.organisations.first.users) confirmed_users = [] users.each do |user| @@ -29,7 +29,7 @@ # @return the number of DMPs using the specified template between the optional specified dates # ensures that the template is owned/created by the caller's organisation def using_template - if has_auth(constant("api_endpoint_types.statistics")) + if has_auth(constant("token_permission_types.statistics")) template = Dmptemplate.find(params[:id]) if template.organisation == @user.organisations.first @template_count = restrict_date_range(template.projects).count @@ -48,7 +48,7 @@ # the uses are restricted to DMPs created by users of the same organisation # as the user who ititiated the call def plans_by_template - if has_auth(constant("api_endpoint_types.statistics")) + if has_auth(constant("token_permission_types.statistics")) @org_projects = [] @user.organisations.first.users.each do |user| user.projects.each do |project| @@ -70,7 +70,7 @@ # DMPs must be owned by a user who's organisation is the same as the user # who generates the call def plans - if has_auth(constant("api_endpoint_types.statistics")) + if has_auth(constant("token_permission_types.statistics")) @org_projects = [] @user.organisations.first.users.each do |user| user.projects.each do |project| diff --git a/app/controllers/plans_controller.rb b/app/controllers/plans_controller.rb index 8e8c70d..ba1f3ab 100644 --- a/app/controllers/plans_controller.rb +++ b/app/controllers/plans_controller.rb @@ -158,10 +158,10 @@ @plan = Plan.find(params[:id]) authorize @plan - if user_signed_in? && @plan.readable_by(current_user.id) then + if (user_signed_in? && @plan.readable_by(current_user.id)) then @exported_plan = ExportedPlan.new.tap do |ep| ep.plan = @plan - ep.user = current_user + ep.user = current_user ||= nil #ep.format = request.format.try(:symbol) ep.format = request.format.to_sym plan_settings = @plan.settings(:export) @@ -193,10 +193,12 @@ } end end + elsif !user_signed_in? then respond_to do |format| format.html { redirect_to edit_user_registration_path } end + elsif !@plan.editable_by(current_user.id) then respond_to do |format| format.html { redirect_to projects_url, notice: I18n.t('helpers.settings.plans.errors.no_access_account') } diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index ba7b816..0463483 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -1,62 +1,62 @@ class ProjectsController < ApplicationController - before_filter :get_plan_list_columns, only: %i( index ) + before_filter :get_plan_list_columns, only: %i( index ) after_action :verify_authorized - # GET /projects - # GET /projects.json - def index + # GET /projects + # GET /projects.json + def index authorize Project ## TODO: Is this A magic String? the "Show_shib_link?" as we define it and users dont see cookies - if user_signed_in? then - if (current_user.shibboleth_id.nil? || current_user.shibboleth_id.length == 0) && !cookies[:show_shib_link].nil? && cookies[:show_shib_link] == "show_shib_link" then - flash.notice = "Would you like to #{view_context.link_to I18n.t('helpers.shibboleth_to_link_text'), user_omniauth_shibboleth_path}".html_safe - end + if user_signed_in? then + if (current_user.shibboleth_id.nil? || current_user.shibboleth_id.length == 0) && !cookies[:show_shib_link].nil? && cookies[:show_shib_link] == "show_shib_link" then + flash.notice = "Would you like to #{view_context.link_to I18n.t('helpers.shibboleth_to_link_text'), user_omniauth_shibboleth_path}".html_safe + end - @projects = current_user.projects.filter(params[:filter]) - @has_projects = current_user.projects.any? # unfiltered count + @projects = current_user.projects.filter(params[:filter]) + @has_projects = current_user.projects.any? # unfiltered count - respond_to do |format| - format.html # index.html.erb - end - else - respond_to do |format| - format.html { redirect_to edit_user_registration_path } - end - end - end + respond_to do |format| + format.html # index.html.erb + end + else + respond_to do |format| + format.html { redirect_to edit_user_registration_path } + end + end + end - # GET /projects/1 - # GET /projects/1.json - def show - @project = Project.find(params[:id]) + # GET /projects/1 + # GET /projects/1.json + def show + @project = Project.find(params[:id]) authorize @project - @show_form = false - if params[:show_form] == "yes" then - @show_form = true - end - if user_signed_in? && @project.readable_by(current_user.id) then - respond_to do |format| - format.html # show.html.erb - end - elsif user_signed_in? then - respond_to do |format| - format.html { redirect_to projects_url, notice: I18n.t('helpers.settings.plans.errors.no_access_account') } - end - else - respond_to do |format| - format.html { redirect_to edit_user_registration_path } - end - end - end + @show_form = false + if params[:show_form] == "yes" then + @show_form = true + end + if user_signed_in? && @project.readable_by(current_user.id) then + respond_to do |format| + format.html # show.html.erb + end + elsif user_signed_in? then + respond_to do |format| + format.html { redirect_to projects_url, notice: I18n.t('helpers.settings.plans.errors.no_access_account') } + end + else + respond_to do |format| + format.html { redirect_to edit_user_registration_path } + end + end + end - # GET /projects/new - # GET /projects/new.json - def new - if user_signed_in? then - @project = Project.new + # GET /projects/new + # GET /projects/new.json + def new + if user_signed_in? then + @project = Project.new authorize @project - @project.organisation = current_user.organisation - @funders = orgs_of_type(constant("organisation_types.funder"), true) + @project.organisation = current_user.organisation + @funders = orgs_of_type(constant("organisation_types.funder"), true) @templates = get_available_templates @guidance_groups = get_available_guidance @always_guidance = get_always_available_guidance @@ -72,124 +72,133 @@ end end - # GET /projects/1/edit + # GET /projects/1/edit # Should this be removed? - def edit - @project = Project.find(params[:id]) + def edit + @project = Project.find(params[:id]) authorize @project - if !user_signed_in? then + if !user_signed_in? then respond_to do |format| - format.html { redirect_to edit_user_registration_path } - end - elsif !@project.editable_by(current_user.id) then - respond_to do |format| - format.html { redirect_to projects_url, notice: I18n.t('helpers.settings.plans.errors.no_access_account') } - end - end - end + format.html { redirect_to edit_user_registration_path } + end + elsif !@project.editable_by(current_user.id) then + respond_to do |format| + format.html { redirect_to projects_url, notice: I18n.t('helpers.settings.plans.errors.no_access_account') } + end + end + end - def share - @project = Project.find(params[:id]) + def share + @project = Project.find(params[:id]) authorize @project - if !user_signed_in? then + if !user_signed_in? then respond_to do |format| - format.html { redirect_to edit_user_registration_path } - end - elsif !@project.editable_by(current_user.id) then - respond_to do |format| - format.html { redirect_to projects_url, notice: I18n.t('helpers.settings.plans.errors.no_access_account') } - end - end - end + format.html { redirect_to edit_user_registration_path } + end + elsif !@project.editable_by(current_user.id) then + respond_to do |format| + format.html { redirect_to projects_url, notice: I18n.t('helpers.settings.plans.errors.no_access_account') } + end + end + end - def export - @project = Project.find(params[:id]) + def export + @project = Project.find(params[:id]) authorize @project - if !user_signed_in? then + if !user_signed_in? then respond_to do |format| - format.html { redirect_to edit_user_registration_path } - end - else - respond_to do |format| - format.html { render action: "export" } + format.html { redirect_to edit_user_registration_path } + end + else + respond_to do |format| + format.html { render action: "export" } - end - end - end + end + end + end - # POST /projects - # POST /projects.json - def create - if user_signed_in? then - @project = Project.new(params[:project]) + # POST /projects + # POST /projects.json + def create + if user_signed_in? then + + attrs = project_params + @project = Project.new(attrs) authorize @project - if @project.dmptemplate.nil? && params[:project][:funder_id] != "" then # this shouldn't be necessary - see setter for funder_id in project.rb - funder = Org.find(params[:project][:funder_id]) - if funder.dmptemplates.count == 1 then - @project.dmptemplate = funder.published_templates.first - end - elsif @project.dmptemplate.nil? || params[:default_tag] == 'true' then - if @project.organisation.nil? || params[:default_tag] == 'true' || @project.organisation.published_templates.first.nil? then - @project.dmptemplate = Dmptemplate.find_by_is_default(true) - else - @project.dmptemplate = @project.organisation.published_templates.first - end - end - @project.principal_investigator = current_user.name(false) + + if @project.dmptemplate.nil? && attrs[:funder_id] != "" then # this shouldn't be necessary - see setter for funder_id in project.rb + funder = Organisation.find(attrs[:funder_id]) + if funder.dmptemplates.count == 1 then + @project.dmptemplate = funder.published_templates.first + end + + elsif @project.dmptemplate.nil? || params[:default_tag] == 'true' then + if @project.organisation.nil? || params[:default_tag] == 'true' || @project.organisation.published_templates.first.nil? then + @project.dmptemplate = Dmptemplate.find_by_is_default(true) + else + @project.dmptemplate = @project.organisation.published_templates.first + end + end + @project.principal_investigator = current_user.name(false) - @project.title = I18n.t('helpers.project.my_project_name')+' ('+@project.dmptemplate.title+')' - @project.assign_creator(current_user.id) - respond_to do |format| - if @project.save - format.html { redirect_to({:action => "show", :id => @project.slug, :show_form => "yes"}, {:notice => I18n.t('helpers.project.success')}) } - else - format.html { render action: "new" } - end - end - else - render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) - end - end + @project.title = I18n.t('helpers.project.my_project_name')+' ('+@project.dmptemplate.title+')' + @project.assign_creator(current_user.id) + respond_to do |format| + if @project.save + format.html { redirect_to({:action => "show", :id => @project.slug, :show_form => "yes"}, {:notice => I18n.t('helpers.project.success')}) } + else + format.html { render action: "new" } + end + end + + else + render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) + end + end - # PUT /projects/1 - # PUT /projects/1.json - def update - @project = Project.find(params[:id]) + # PUT /projects/1 + # PUT /projects/1.json + def update + @project = Project.find(params[:id]) authorize @project - if user_signed_in? && @project.editable_by(current_user.id) then - if @project.update_attributes(params[:project]) + + if user_signed_in? && @project.editable_by(current_user.id) then + attrs = project_params + + if @project.update_attributes(attrs) respond_to do |format| - format.html { redirect_to({:action => "show", :id => @project.slug, notice: I18n.t('helpers.project.success_update') }) } + format.html { redirect_to({:action => "show", :id => @project.slug, notice: I18n.t('helpers.project.success_update') }) } end else respond_to do |format| - format.html { render action: "edit" } - end - end - else - render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) - end - end + format.html { render action: "edit" } + end + end + else + render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) + end + end - # DELETE /projects/1 - # DELETE /projects/1.json - def destroy - @project = Project.find(params[:id]) + # DELETE /projects/1 + # DELETE /projects/1.json + def destroy + @project = Project.find(params[:id]) authorize @project - if user_signed_in? && @project.editable_by(current_user.id) then - @project.destroy + if user_signed_in? && @project.editable_by(current_user.id) then + @project.destroy - respond_to do |format| - format.html { redirect_to projects_url } - end - else - render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) - end - end + respond_to do |format| + format.html { redirect_to projects_url } + end + else + render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) + end + end # returns to AJAX call from frontend # difficult to secure as it passes through params, and dosent curate data based # on what the user can "view" or is public + # GET /projects/possible_templates.json def possible_templates if !params[:funder].nil? && params[:funder] != "" && params[:funder] != "undefined" then @@ -224,10 +233,12 @@ end # returns to AJAX call from frontend - # difficult to secure as it passes through params, and dosent curate data based + # difficult to secure as it passes through params, and dosent curate data based # on what the user can "view" or is public + # ----------------------------------------------------------- def possible_guidance authorize @project + if !params[:template].nil? && params[:template] != "" && params[:template] != "undefined" then template = Dmptemplate.find(params[:template]) else @@ -242,64 +253,72 @@ guidance_groups = {} ggs = GuidanceGroup.guidance_groups_excluding(excluded_orgs) - ggs.each do |gg| - guidance_groups[gg.id] = gg.name - end + ggs.each do |gg| + guidance_groups[gg.id] = gg.name + end #subset guidance that belong to the institution - unless institution.nil? then + unless institution.nil? then authorize Project - optional_gg = GuidanceGroup.where("optional_subset = ? AND organisation_id = ?", true, institution.id) - optional_gg.each do|optional| - guidance_groups[optional.id] = optional.name - end + optional_gg = GuidanceGroup.where("optional_subset = ? AND organisation_id = ?", true, institution.id) + optional_gg.each do|optional| + guidance_groups[optional.id] = optional.name + end - institution.children.each do |o| - o.guidance_groups.each do |gg| - include = false - gg.guidances.each do |g| - if g.dmptemplate.nil? || g.dmptemplate_id == template.id then - include = true - break - end - end - if include then - guidance_groups[gg.id] = gg.name - end - end - end - end + institution.children.each do |o| + o.guidance_groups.each do |gg| + include = false + gg.guidances.each do |g| + if g.dmptemplate.nil? || g.dmptemplate_id == template.id then + include = true + break + end + end + if include then + guidance_groups[gg.id] = gg.name + end + end + end + end #If template belongs to a funder and that funder has subset guidance display then. if !template.nil? && template.organisation.organisation_type.name == constant("organisation_types.funder") then optional_gg = GuidanceGroup.where("optional_subset = ? AND organisation_id = ?", true, template.organisation_id) - optional_gg.each do|optional| - guidance_groups[optional.id] = optional.name - end + optional_gg.each do|optional| + guidance_groups[optional.id] = optional.name + end end - respond_to do |format| - format.json { render json: guidance_groups.to_json } - end - end + respond_to do |format| + format.json { render json: guidance_groups.to_json } + end + end - private - def orgs_of_type(org_type_name, published_templates = false) - org_type = OrganisationType.find_by_name(org_type_name) - all_such_orgs = org_type.organisations - if published_templates then - with_published = Array.new - all_such_orgs.each do |o| - if o.published_templates.count > 0 then - with_published << o - end - end - return with_published.sort_by {|o| [o.sort_name, o.name] } - else - return all_such_orgs.sort_by {|o| [o.sort_name, o.name] } - end - end + private + def project_params + params.require(:project).permit(:title, :grant_number, :identifier, :description, + :principal_investigator, :principal_investigator_identifier, + :data_contact, :funder_name, :visibility, + :dmptemplate_id, :organisation_id, :funder_id, :institution_id, + :guidance_group_ids, :project_group_ids) + end + + def orgs_of_type(org_type_name, published_templates = false) + org_type = OrganisationType.find_by_name(org_type_name) + all_such_orgs = org_type.organisations + if published_templates then + with_published = Array.new + all_such_orgs.each do |o| + if o.published_templates.count > 0 then + with_published << o + end + end + return with_published.sort_by {|o| [o.sort_name, o.name] } + else + return all_such_orgs.sort_by {|o| [o.sort_name, o.name] } + end + end # ----------------------------------------------------------- def get_available_templates @@ -315,7 +334,7 @@ # ----------------------------------------------------------- def get_always_available_guidance # Exclude Funders, Institutions, or children of Institutions - excluded_orgs = orgs_of_type(constant("organisation_types.funder")) + + excluded_orgs = orgs_of_type(constant("organisation_types.funder")) + orgs_of_type(constant("organisation_types.institution")) + Org.orgs_with_parent_of_type(constant("organisation_types.institution")) @@ -354,4 +373,42 @@ GuidanceGroup.where(id: guidance_groups) end + + # ----------------------------------------------------------- + def generate_export + @exported_plan = ExportedPlan.new.tap do |ep| + ep.plan = @plan + ep.user = current_user ||= nil + #ep.format = request.format.try(:symbol) + ep.format = request.format.to_sym + plan_settings = @plan.settings(:export) + + Settings::Dmptemplate::DEFAULT_SETTINGS.each do |key, value| + ep.settings(:export).send("#{key}=", plan_settings.send(key)) + end + end + + @exported_plan.save! # FIXME: handle invalid request types without erroring? + file_name = @exported_plan.project_name + + respond_to do |format| + format.html + format.xml + format.json + format.csv { send_data @exported_plan.as_csv, filename: "#{file_name}.csv" } + format.text { send_data @exported_plan.as_txt, filename: "#{file_name}.txt" } + format.docx { headers["Content-Disposition"] = "attachment; filename=\"#{file_name}.docx\""} + format.pdf do + @formatting = @plan.settings(:export).formatting + render pdf: file_name, + margin: @formatting[:margin], + footer: { + center: t('helpers.plan.export.pdf.generated_by'), + font_size: 8, + spacing: (@formatting[:margin][:bottom] / 2) - 4, + right: '[page] of [topage]' + } + end + end + end end diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index 0f74a00..a82b679 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -5,6 +5,31 @@ @languages = Language.all.order("name") @orgs = Org.where(parent_id: nil).order("name") @other_organisations = Org.where(parent_id: nil, is_other: true).pluck(:id) + @identifier_schemes = IdentifierScheme.where(active: true).order(:name) + end + + # GET /resource + def new + oauth = {provider: nil, uid: nil} + IdentifierScheme.all.each do |scheme| + oauth = session["devise.#{scheme.name.downcase}_data"] unless session["devise.#{scheme.name.downcase}_data"].nil? + end + + @user = User.new + + unless oauth.nil? + # The OAuth provider could not be determined or there was no unique UID! + if oauth[:provider].nil? || oauth[:uid].nil? + flash[:notice] = t('identifier_schemes.new_login_failure') + + else + # Connect the new user with the identifier sent back by the OAuth provider + flash[:notice] = t('identifier_schemes.new_login_success') + UserIdentifier.create(identifier_scheme: oauth[:provider].upcase, + identifier: oauth[:uid], + user: @user) + end + end end # POST /resource @@ -43,11 +68,16 @@ def update - if user_signed_in? then + if user_signed_in? then @user = User.find(current_user.id) + @orgs = Org.where(parent_id: nil).order("name") + @other_organisations = Org.where(parent_id: nil, is_other: true).pluck(:id) + @languages = Language.order("name") + @identifier_schemes = IdentifierScheme.where(active: true).order(:name) + do_update else - render(file: File.join(Rails.root, 'public/403.html'), status: 403, layout: false) + render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) end end @@ -95,8 +125,11 @@ end set_flash_message :notice, :updated # Sign in the user bypassing validation in case his password changed - sign_in @user, bypass: true - redirect_to({controller: "registrations", action: "edit"}, {notice: I18n.t('helpers.project.details_update_success')}) + + sign_in @user, bypass_sign_in: true + + redirect_to({:controller => "registrations", :action => "edit"}, {:notice => I18n.t('helpers.project.details_update_success')}) + else render "edit" end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 2bf4305..89a5f44 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -1,8 +1,22 @@ class SessionsController < Devise::SessionsController + # POST /auth/:provider/callback + # --------------------------------------------------------------------- +=begin + def oauth_create + existing_user = User.find_by_email(params[:user][:email]) + + unless params[:omniauth].nil? + existing_user = UserIdentifier.find_by(identifier: params[:omniauth][:auth]) + end + end +=end + # Capture the user's shibboleth id if they're coming in from an IDP + # --------------------------------------------------------------------- def create existing_user = User.find_by(email: params[:user][:email]) + if !existing_user.nil? && !params[:shibboleth_data].nil? then #after authentication verify if session[:shibboleth] exists existing_user.update_attributes(shibboleth_id: session[:shibboleth_data][:uid]) diff --git a/app/controllers/settings/projects_controller.rb b/app/controllers/settings/projects_controller.rb index 6ba2cd3..8b0f800 100644 --- a/app/controllers/settings/projects_controller.rb +++ b/app/controllers/settings/projects_controller.rb @@ -36,7 +36,7 @@ @settings = current_user.settings(:plan_list) # :name column should always be present (displayed as a disabled checkbox) # so it's not necessary to include it in the list here - @all_columns -= [:name] + @all_columns -= ['name'] end def settings_json diff --git a/app/controllers/static_pages_controller.rb b/app/controllers/static_pages_controller.rb index c371a2f..da81ea8 100644 --- a/app/controllers/static_pages_controller.rb +++ b/app/controllers/static_pages_controller.rb @@ -14,5 +14,62 @@ def roadmap end + + # GET /projects/publicly_available + # ----------------------------------------------------------- + def public_plans + @projects = Project.publicly_visible.order(title: :asc) + end + # GET /projects/[:project_slug]/public_export + # ------------------------------------------------------------- + def public_export + @project = Project.find(params[:id]) + + # Force PDF response + request.format = :pdf + + # if the project is designated as public + if @project.visibility == :publicly_visible + @plan = @project.plans.first + + if !@plan.nil? + @exported_plan = ExportedPlan.new.tap do |ep| + ep.plan = @plan + ep.user = current_user ||= nil + #ep.format = request.format.try(:symbol) + ep.format = request.format.to_sym + plan_settings = @plan.settings(:export) + + Settings::Dmptemplate::DEFAULT_SETTINGS.each do |key, value| + ep.settings(:export).send("#{key}=", plan_settings.send(key)) + end + end + + @exported_plan.save! # FIXME: handle invalid request types without erroring? + file_name = @exported_plan.project_name + + respond_to do |format| + format.pdf do + @formatting = @plan.settings(:export).formatting + render pdf: file_name, + margin: @formatting[:margin], + footer: { + center: t('helpers.plan.export.pdf.generated_by'), + font_size: 8, + spacing: (@formatting[:margin][:bottom] / 2) - 4, + right: '[page] of [topage]' + } + end + end + + else + # the project has no plans for some reason + redirect_to public_plans_path, notice: I18n.t('helpers.settings.projects.errors.no_plan') + end + else + # Otherwise redirect to the home page with an unauthorized message + redirect_to public_plans_path, notice: I18n.t('helpers.settings.plans.errors.no_access_account') + end + end end \ No newline at end of file diff --git a/app/controllers/user_identifiers_controller.rb b/app/controllers/user_identifiers_controller.rb new file mode 100644 index 0000000..040a50b --- /dev/null +++ b/app/controllers/user_identifiers_controller.rb @@ -0,0 +1,25 @@ +class UserIdentifiersController < ApplicationController + + # DELETE /users/identifiers + # --------------------------------------------------------------------- + def destroy + if user_signed_in? then + user = User.find(current_user.id) + identifier = UserIdentifier.find(params[:id]) + + # If the requested identifier belongs to the current user remove it + if user.user_identifiers.include?(identifier) + identifier.destroy! + flash[:notice] = t('identifier_schemes.disconnect_success', + scheme: identifier.identifier_scheme.name) + + else + flash[:notice] = t('identifier_schemes.disconnect_failure', + scheme: identifier.identifier_scheme.name) + end + + redirect_to edit_user_registration_path + end + end + +end \ No newline at end of file diff --git a/app/controllers/users/omniauth_callback_controller.rb b/app/controllers/users/omniauth_callback_controller.rb deleted file mode 100644 index ee19c5c..0000000 --- a/app/controllers/users/omniauth_callback_controller.rb +++ /dev/null @@ -1,53 +0,0 @@ -class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController - - def shibboleth - if user_signed_in? && current_user.shibboleth_id.present? && current_user.shibboleth_id.length > 0 then - flash[:warning] = I18n.t('devise.failure.already_authenticated') - redirect_to root_path - else - auth = request.env['omniauth.auth'] || {} - eppn = auth['extra']['raw_info']['eppn'] - uid = nil - if !eppn.blank? then - uid = eppn - elsif !auth['uid'].blank? then - uid = auth['uid'] - elsif !auth['extra']['raw_info']['targeted-id'].blank? then - uid = auth['extra']['raw_info']['targeted-id'] - end - - if !uid.nil? && !uid.blank? then - s_user = User.where(shibboleth_id: uid).first - # Take out previous record if was not confirmed. - if !s_user.nil? && s_user.confirmed_at.nil? then - sign_out s_user - User.delete(s_user.id) - s_user = nil - end - - # Stops Shibboleth ID being blocked if email incorrectly entered. - if !s_user.nil? && s_user.try(:persisted?) then - flash[:notice] = I18n.t('devise.omniauth_callbacks.success', :kind => 'Shibboleth') - sign_in s_user - redirect_to root_path - else - if user_signed_in? then - current_user.update_attribute('shibboleth_id', uid) - user_id = current_user.id - sign_out current_user - session.delete(:shibboleth_data) - s_user = User.find(user_id) - sign_in s_user - redirect_to edit_user_registration_path - else - session[:shibboleth_data] = request.env['omniauth.auth'] - session[:shibboleth_data][:uid] = uid - redirect_to new_user_registration_url(:nosplash => 'true') - end - end - else - redirect_to root_path - end - end - end -end diff --git a/app/controllers/users/omniauth_callbacks_controller.rb b/app/controllers/users/omniauth_callbacks_controller.rb new file mode 100644 index 0000000..9b65b77 --- /dev/null +++ b/app/controllers/users/omniauth_callbacks_controller.rb @@ -0,0 +1,116 @@ +class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController + ## + # Dynamically build a handler for each omniauth provider + # ------------------------------------------------------------- + IdentifierScheme.where(active: true).each do |scheme| + define_method(scheme.name.downcase) do + handle_omniauth(scheme) + end + end + + ## + # Processes callbacks from an omniauth provider and directs the user to + # the appropriate page: + # Not logged in and uid had no match ---> Sign Up page + # Not logged in and uid had a match ---> Sign In and go to Home Page + # Signed in and uid had no match --> Save the uid and go to the Profile Page + # Signed in and uid had a match --> Go to the Home Page + # + # @scheme [IdentifierScheme] The IdentifierScheme for the provider + # ------------------------------------------------------------- + def handle_omniauth(scheme) + user = User.from_omniauth(request.env["omniauth.auth"].nil? ? request.env : request.env["omniauth.auth"]) + + # If the user isn't logged in + if current_user.nil? + # If the uid didn't have a match in the system send them to register + if user.nil? + session["devise.#{scheme.name.downcase}_data"] = request.env["omniauth.auth"] + flash[:notice] = t('identifier_schemes.new_login_success') + redirect_to new_user_registration_url + + # Otherwise sign them in + else + sign_in_and_redirect user, event: :authentication + set_flash_message(:notice, :success, kind: scheme.name) if is_navigational_format? + end + + # The user is already logged in and just registering the uid with us + else + # If the user could not be found by that uid then attach it to their record + if user.nil? + if UserIdentifier.create(identifier_scheme: scheme, + identifier: request.env["omniauth.auth"].uid, + user: current_user) + + flash[:notice] = t('identifier_schemes.connect_success', scheme: scheme.name) + else + flash[:notice] = t('identifier_schemes.connect_failure', scheme: scheme.name) + end + end + + # Redirect to the User Profile page + redirect_to edit_user_registration_path + end + end + + + # TODO: We should consider rolling the below function up into the + # generic handler above + # ------------------------------------------------------------- + def shibboleth + if user_signed_in? && current_user.shibboleth_id.present? && current_user.shibboleth_id.length > 0 then + flash[:warning] = I18n.t('devise.failure.already_authenticated') + redirect_to root_path + else + auth = request.env['omniauth.auth'] || {} + eppn = auth['extra']['raw_info']['eppn'] + uid = nil + if !eppn.blank? then + uid = eppn + elsif !auth['uid'].blank? then + uid = auth['uid'] + elsif !auth['extra']['raw_info']['targeted-id'].blank? then + uid = auth['extra']['raw_info']['targeted-id'] + end + + if !uid.nil? && !uid.blank? then + s_user = User.where(shibboleth_id: uid).first + # Take out previous record if was not confirmed. + if !s_user.nil? && s_user.confirmed_at.nil? then + sign_out s_user + User.delete(s_user.id) + s_user = nil + end + + # Stops Shibboleth ID being blocked if email incorrectly entered. + if !s_user.nil? && s_user.try(:persisted?) then + flash[:notice] = I18n.t('devise.omniauth_callbacks.success', :kind => 'Shibboleth') + sign_in s_user + redirect_to root_path + else + if user_signed_in? then + current_user.update_attribute('shibboleth_id', uid) + user_id = current_user.id + sign_out current_user + session.delete(:shibboleth_data) + s_user = User.find(user_id) + sign_in s_user + redirect_to edit_user_registration_path + else + session[:shibboleth_data] = request.env['omniauth.auth'] + session[:shibboleth_data][:uid] = uid + redirect_to new_user_registration_url(:nosplash => 'true') + end + end + else + redirect_to root_path + end + end + end + + # ------------------------------------------------------------- + def failure + redirect_to root_path + end +end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 56f99a5..73851a3 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,41 +1,26 @@ module ApplicationHelper - def resource_name - :user - end - - def resource - @resource ||= User.new - end - - def devise_mapping - @devise_mapping ||= Devise.mappings[:user] - end - - def javascript(*files) - content_for(:head) { javascript_include_tag(*files) } - end - def link_to_add_object(name, f, association, css_class, i) - new_object = f.object.class.reflect_on_association(association).klass.new - fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder| - j = i + 1 - new_object.number = j - render(association.to_s.singularize + "_fields", :f => builder) - end - link_to_function(name, "add_object(this, \"#{association}\", \"#{escape_javascript(fields)}\")", :class => css_class) + def resource_name + :user + end + + # --------------------------------------------------------------------------- + def resource + @resource ||= User.new + end + + # --------------------------------------------------------------------------- + def devise_mapping + @devise_mapping ||= Devise.mappings[:user] end - def link_to_function(name, *args, &block) - html_options = args.extract_options!.symbolize_keys - - function = block_given? ? update_page(&block) : args[0] || '' - onclick = "#{"#{html_options[:onclick]}; " if html_options[:onclick]}#{function}; return false;" - href = html_options[:href] || '#' - - content_tag(:a, name, html_options.merge(:href => href, :onclick => onclick)) + # --------------------------------------------------------------------------- + def javascript(*files) + content_for(:head) { javascript_include_tag(*files) } end - def hash_to_json_object(obj_name, hash) + # --------------------------------------------------------------------------- + def hash_to_js_json_variable(obj_name, hash) "".html_safe end end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 4679053..84c458d 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -44,10 +44,18 @@ shared_num = project.project_groups.count - 1 text = shared_num > 0 ? (t("helpers.yes_label") + " (with #{shared_num} people) ") : t("helpers.no_label") [ "dmp_td_small", text ] + when 'visibility' + ["dmp_td_small", (project.visibility.nil? ? I18n.t("helpers.project.visibilities.labels.organisationally_visible") : I18n.t("helpers.project.visibilities.labels.#{project.visibility}"))] when 'last_edited' [ "dmp_td_small", l(project.latest_update.to_date, formats: :short) ] when 'description' [ "dmp_td_medium", (project.try(col) || "Unknown") ] + when 'non_link_name' + [ "dmp_td_big", project.title ] + when 'template' + ["dmp_td_big", project.dmptemplate.title] + when 'organisation' + ["dmp_td_medium", (project.organisation.nil? ? project.owner.organisation.name : project.organisation.name)] else [ "dmp_td_small", (project.try(col) || "Unknown") ] end diff --git a/app/models/ability.rb b/app/models/ability.rb index e283051..ba5e6fa 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -6,7 +6,7 @@ # Define abilities for the passed in user here. For example: # user ||= User.new # guest user (not logged in) - if user.has_role? constant("user_role_types.super_admin") + if user.has_role? constant("roles.super_admin") can :manage, :all else can :read, :all diff --git a/app/models/answer.rb b/app/models/answer.rb index 131b67b..f8b0d65 100644 --- a/app/models/answer.rb +++ b/app/models/answer.rb @@ -1,4 +1,5 @@ class Answer < ActiveRecord::Base + ## # Associations belongs_to :question @@ -9,5 +10,23 @@ ## # Possibly needed for active_admin # -relies on protected_attributes gem as syntax depricated in rails 4.2 - attr_accessible :text, :plan_id, :question_id, :user_id, :option_ids , :as => [:default, :admin] + attr_accessible :text, :plan_id, :question_id, :user_id, :question_option_ids, + :question, :user, :plan, :question_options, :as => [:default, :admin] + + ## + # Validations + validates :user, :plan, :question, presence: true + + # Make sure there is only one answer per question! + validates :question, uniqueness: {scope: [:plan], + message: I18n.t('helpers.errors.answer.only_one_per_question')} + + # The answer MUST have a text value if the question is NOT option based or a question_option if + # it is option based. + validates :text, presence: true, if: Proc.new{|a| + (a.question.nil? ? false : !a.question.question_format.option_based?) + } + validates :question_options, presence: true, if: Proc.new{|a| + (a.question.nil? ? false : a.question.question_format.option_based?) + } end diff --git a/app/models/exported_plan.rb b/app/models/exported_plan.rb index 2ea784b..e1b18fb 100644 --- a/app/models/exported_plan.rb +++ b/app/models/exported_plan.rb @@ -1,7 +1,8 @@ class ExportedPlan < ActiveRecord::Base include GlobalHelpers - attr_accessible :plan_id, :user_id, :format, :as => [:default, :admin] +# TODO: REMOVE AND HANDLE ATTRIBUTE SECURITY IN THE CONTROLLER! + attr_accessible :plan_id, :user_id, :format, :user, :plan, :as => [:default, :admin] #associations between tables belongs_to :plan @@ -10,6 +11,7 @@ VALID_FORMATS = ['csv', 'html', 'json', 'pdf', 'text', 'xml', 'docx'] validates :format, inclusion: { in: VALID_FORMATS, message: I18n.t('helpers.plan.export.not_valid_format') } + validates :plan, :format, presence: true # Store settings with the exported plan so it can be recreated later # if necessary (otherwise the settings associated with the plan at a @@ -18,6 +20,9 @@ s.key :export, defaults: Settings::Dmptemplate::DEFAULT_SETTINGS end +# TODO: Consider removing the accessor methods, they add no value. The view/controller could +# just access the value directly from the project/plan: exported_plan.plan.project.title + # Getters to match Settings::Dmptemplate::VALID_ADMIN_FIELDS def project_name name = self.plan.project.title @@ -54,6 +59,16 @@ plan.project.organisation.try(:name) end + def orcid + scheme = IdentifierScheme.find_by(name: 'orcid') + if self.user.nil? + '' + else + orcid = self.user.user_identifiers.where(identifier_scheme: scheme).first + (orcid.nil? ? '' : orcid.identifier) + end + end + # sections taken from fields settings def sections sections = self.plan.sections @@ -92,18 +107,18 @@ def as_txt output = "#{self.plan.project.title}\n\n#{self.plan.version.phase.title}\n" - - -puts "SETTINGS: #{self.plan.inspect}" - - output += "\nDetails:\n#{self.plan.settings[:export][:fields][:admin].collect{|f| f.to_s}.join('\n')}\n" + output += "\nDetails:\n\n" + attrs = self.plan.settings(:export)[:value]['fields'][:admin].collect{|f| f.to_s} + attrs.each do |attr| + output += attr + ": " + self.send(attr) + "\n" + end self.sections.each do |section| output += "\n#{section.title}\n" self.questions_for_section(section).each do |question| qtext = sanitize_text( question.text.gsub(/
  • /, ' * ') ) - output += "\n#{qtext}\n" + output += "\n* #{qtext}" answer = self.plan.answer(question.id, false) if answer.nil? || answer.text.nil? then diff --git a/app/models/file_type.rb b/app/models/file_type.rb deleted file mode 100644 index 7c836dc..0000000 --- a/app/models/file_type.rb +++ /dev/null @@ -1,3 +0,0 @@ -class FileType < ActiveRecord::Base - #attr_accessible :name, :icon_location, :icon_name, :icon_size -end diff --git a/app/models/guidance.rb b/app/models/guidance.rb index b6048f4..c2f93fb 100644 --- a/app/models/guidance.rb +++ b/app/models/guidance.rb @@ -15,8 +15,6 @@ belongs_to :guidance_group belongs_to :question has_and_belongs_to_many :themes, join_table: "themes_in_guidance" - # depricated, but required for migration "single_group_for_guidance" - has_and_belongs_to_many :guidance_groups, join_table: "guidance_in_group" @@ -27,6 +25,9 @@ + validates :text, presence: true + + ## # Determine if a guidance is in a group which belongs to a specified organisation # @@ -125,10 +126,8 @@ funder_groups += funder.guidance_groups end # find all groups owned by any of the user's organisations - organisation_groups = [] - user.organisations.each do |organisation| - organisation_groups += organisation.guidance_groups - end + organisation_groups = user.organisation.guidance_groups + # find all guidances belonging to any of the viewable groups all_viewable_guidances = [] all_viewable_groups = managing_groups + funder_groups + organisation_groups diff --git a/app/models/guidance_group.rb b/app/models/guidance_group.rb index 34524ab..cc4bd8f 100644 --- a/app/models/guidance_group.rb +++ b/app/models/guidance_group.rb @@ -10,7 +10,8 @@ ## # Possibly needed for active_admin # -relies on protected_attributes gem as syntax depricated in rails 4.2 - attr_accessible :organisation_id, :name, :optional_subset, :published, :as => [:default, :admin] + attr_accessible :organisation_id, :name, :optional_subset, :published, + :org, :as => [:default, :admin] attr_accessible :dmptemplate_ids, :as => [:default, :admin] @@ -24,6 +25,7 @@ + validates :name, :org, presence: true ## # Converts a guidance group to a string containing the display name @@ -120,7 +122,7 @@ # pass this organisation guidance groups to the view with respond_with @all_viewable_groups all_viewable_groups = managing_org_groups + funder_groups + organisation_groups - all_viewable_groups = all_viewable_groups.uniq{|x| x.id} + all_viewable_groups = all_viewable_groups.flatten.uniq{|x| x.id} return all_viewable_groups end end diff --git a/app/models/identifier_scheme.rb b/app/models/identifier_scheme.rb new file mode 100644 index 0000000..45b8922 --- /dev/null +++ b/app/models/identifier_scheme.rb @@ -0,0 +1,6 @@ +class IdentifierScheme < ActiveRecord::Base + has_many :user_identifiers + has_many :users, through: :user_identifiers + + validates :name, uniqueness: true, presence: true +end \ No newline at end of file diff --git a/app/models/language.rb b/app/models/language.rb index a2bdaa0..0bb5a35 100644 --- a/app/models/language.rb +++ b/app/models/language.rb @@ -2,7 +2,8 @@ ## # Associations has_many :users - + has_many :orgs + ## # Validations validates :abbreviation, presence: true, uniqueness: true diff --git a/app/models/new_plan.rb b/app/models/new_plan.rb new file mode 100644 index 0000000..1dac7cd --- /dev/null +++ b/app/models/new_plan.rb @@ -0,0 +1,5 @@ +class NewPlan < ActiveRecord::Base + belongs_to :template + has_many :roles + has_many :users, through: :roles +end diff --git a/app/models/note.rb b/app/models/note.rb index cc2f472..fc0b3ba 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -7,5 +7,6 @@ ## # Possibly needed for active_admin # -relies on protected_attributes gem as syntax depricated in rails 4.2 - attr_accessible :question_id, :text, :user_id, :archived, :plan_id, :archived_by, :as => [:default, :admin] + attr_accessible :question_id, :text, :user_id, :archived, :plan_id, :archived_by, + :answer, :user, :as => [:default, :admin] end diff --git a/app/models/org.rb b/app/models/org.rb index b75f6d8..83899ae 100644 --- a/app/models/org.rb +++ b/app/models/org.rb @@ -11,7 +11,8 @@ has_many :templates has_many :users has_many :suggested_answers - has_and_belongs_to_many :token_permission_types, join_table: "org_token_permissions" + + has_and_belongs_to_many :token_permission_types, join_table: "org_token_permissions", unique: true ## # Possibly needed for active_admin @@ -19,7 +20,8 @@ attr_accessible :abbreviation, :banner_text, :logo, :remove_logo, :logo_file_name, :name, :target_url, :organisation_type_id, :wayfless_entity, :parent_id, :sort_name, - :token_permission_type_ids, :language_id, :contact_email + :token_permission_type_ids, :language_id, :contact_email, + :language, :org_type, :region, :token_permission_types ## # Validators diff --git a/app/models/phase.rb b/app/models/phase.rb index e5cb352..fa5109c 100644 --- a/app/models/phase.rb +++ b/app/models/phase.rb @@ -15,7 +15,8 @@ ## # Possibly needed for active_admin # -relies on protected_attributes gem as syntax depricated in rails 4.2 - attr_accessible :description, :number, :title, :template_id, :as => [:default, :admin] + attr_accessible :description, :number, :title, :template_id, + :template, :sections, :modifiable, :as => [:default, :admin] ## # sluggable title @@ -40,54 +41,47 @@ # returns the title of the phase # # @return [String] the title of the phase - def to_s - "#{title}" - end + def to_s + "#{title}" + end ## - # returns the most_recent version of this phase - # - # @return [Version] the most recent version of this phase - def latest_version - return versions.order("number DESC").last - end - - ## - # returns either the latest published version of this phase + # returns either the latest published version of this phase # also serves to verify if this phase has any published versions as returns nil # if there are no published versions # # @return [Version, nil] - def latest_published_version - pub_vers = versions.where('published = ?', true).order('updated_at DESC') + def latest_published_version + pub_vers = versions.where('published = ?', true).order('updated_at DESC') if pub_vers.any?() then return pub_vers.first else return nil end - end + end +# TODO: reevaluate this method. It seems like the 1st query is unecessary ## - # verify if a phase has a published version or a version with one or more sections + # verify if a phase has a published version or a version with one or more sections # # @return [Boolean] - def has_sections - versions = self.versions.where('published = ?', true).order('updated_at DESC') - if versions.any? then - version = versions.first - if !version.sections.empty? then - has_section = true - else - has_section = false - end - else - version = self.versions.order('updated_at DESC').first - if !version.sections.empty? then - has_section = true - else - has_section = false - end - end - return has_section - end + def has_sections + versions = self.versions.where('published = ?', true).order('updated_at DESC') + if versions.any? then + version = versions.first + if !version.sections.empty? then + has_section = true + else + has_section = false + end + else + version = self.versions.order('updated_at DESC').first + if !version.sections.empty? then + has_section = true + else + has_section = false + end + end + return has_section + end end diff --git a/app/models/plan.rb b/app/models/plan.rb index 4a76116..d1729e8 100644 --- a/app/models/plan.rb +++ b/app/models/plan.rb @@ -12,7 +12,14 @@ ## # Possibly needed for active_admin # -relies on protected_attributes gem as syntax depricated in rails 4.2 - attr_accessible :locked, :project_id, :version_id, :version, :plan_sections, :as => [:default, :admin] + attr_accessible :locked, :project_id, :version_id, :version, :plan_sections, + :exported_plans, :project, :title, :template, :grant_number, + :identifier, :principal_investigator, :principal_investigator_identifier, + :description, :data_contact, :funder_name, :visibility, + :as => [:default, :admin] + + # public is a Ruby keyword so using publicly + enum visibility: [:organisationally_visible, :publicly_visible, :is_test, :privately_visible] ## # Constants @@ -29,7 +36,7 @@ end alias_method :super_settings, :settings - + @@ -58,7 +65,8 @@ def settings(key) self_settings = self.super_settings(key) return self_settings if self_settings.value? - self.dmptemplate.settings(key) +# self.dmptemplate.settings(key) + self.template.settings(key) end ## @@ -66,7 +74,8 @@ # # @return [Dmptemplate] the template associated with this plan def dmptemplate - self.project.try(:dmptemplate) || Dmptemplate.new +# self.project.try(:dmptemplate) || Dmptemplate.new + self.try(:template) || Template.new end ## @@ -76,8 +85,10 @@ def title logger.debug "Title in settings: #{self.settings(:export).title}" if self.settings(:export).title == "" - if !self.version.nil? && !self.version.phase.nil? && !self.version.phase.title? then - return self.version.phase.title +# if !self.version.nil? && !self.version.phase.nil? && !self.version.phase.title? then + if !self.template.nil? && !self.template.phases.empty? +# return self.version.phase.title + return self.template.phases.first.title else return I18n.t('tool_title2') end diff --git a/app/models/question.rb b/app/models/question.rb index acfba1a..cd15316 100644 --- a/app/models/question.rb +++ b/app/models/question.rb @@ -20,8 +20,12 @@ ## # Possibly needed for active_admin # -relies on protected_attributes gem as syntax depricated in rails 4.2 - attr_accessible :default_value, :dependency_id, :dependency_text, :guidance,:number, :suggested_answer, :text, :section_id, :question_format_id, :question_options_attributes, :suggested_answers_attributes, :id, :option_comment_display, :theme_ids, :as => [:default, :admin] - + attr_accessible :default_value, :dependency_id, :dependency_text, :guidance,:number, + :suggested_answer, :text, :section_id, :question_format_id, + :question_options_attributes, :suggested_answers_attributes, + :option_comment_display, :theme_ids, :section, :question_format, + :question_options, :suggested_answers, :answers, :themes, + :modifiable, :option_comment_display, :as => [:default, :admin] # EVALUATE CLASS AND INSTANCE METHODS BELOW diff --git a/app/models/question_format.rb b/app/models/question_format.rb index 29ad3b8..7f1a900 100644 --- a/app/models/question_format.rb +++ b/app/models/question_format.rb @@ -3,11 +3,13 @@ ## # Associations has_many :questions - + + validates :title, presence: true, uniqueness: true + ## # Possibly needed for active_admin # -relies on protected_attributes gem as syntax depricated in rails 4.2 - attr_accessible :title, :description, :as => [:default, :admin] + attr_accessible :title, :description, :option_based, :questions, :as => [:default, :admin] # EVALUATE CLASS AND INSTANCE METHODS BELOW diff --git a/app/models/question_option.rb b/app/models/question_option.rb index b16b0d9..6fa289d 100644 --- a/app/models/question_option.rb +++ b/app/models/question_option.rb @@ -7,5 +7,6 @@ ## # Possibly needed for active_admin # -relies on protected_attributes gem as syntax depricated in rails 4.2 - attr_accessible :text, :question_id, :is_default, :number, :as => [:default, :admin] + attr_accessible :text, :question_id, :is_default, :number, :question, + :as => [:default, :admin] end diff --git a/app/models/section.rb b/app/models/section.rb index 48b83ae..ee98e8f 100644 --- a/app/models/section.rb +++ b/app/models/section.rb @@ -10,8 +10,10 @@ accepts_nested_attributes_for :questions, :reject_if => lambda {|a| a[:text].blank? }, :allow_destroy => true # accepts_nested_attributes_for :version - attr_accessible :organisation_id, :description, :number, :title, :published, :questions_attributes, :as => [:default, :admin] - + attr_accessible :organisation_id, :description, :number, :title, :published, + :questions_attributes, :organisation, :phase, :modifiable, + :as => [:default, :admin] + ## # return the title of the section # diff --git a/app/models/settings/plan_list.rb b/app/models/settings/plan_list.rb index 17e93a9..812e2c8 100644 --- a/app/models/settings/plan_list.rb +++ b/app/models/settings/plan_list.rb @@ -5,7 +5,7 @@ # TODO: can these be taken from somewhere else rather than hard-coded here? DEFAULT_COLUMNS = ['name', 'owner', 'shared', 'last_edited'] - ALL_COLUMNS = DEFAULT_COLUMNS + ['template_owner', 'identifier', 'grant_number', + ALL_COLUMNS = DEFAULT_COLUMNS + ['template_owner', 'identifier', 'grant_number', 'visibility', 'principal_investigator', 'data_contact', 'description'] validate do diff --git a/app/models/settings/template.rb b/app/models/settings/template.rb index 7bc1968..2956eac 100644 --- a/app/models/settings/template.rb +++ b/app/models/settings/template.rb @@ -12,7 +12,7 @@ VALID_MARGIN_RANGE = (5..25) VALID_ADMIN_FIELDS = ['project_name', 'project_identifier', 'grant_title', 'principal_investigator', - 'project_data_contact', 'project_description', 'funder', 'institution'] + 'project_data_contact', 'project_description', 'funder', 'institution', 'orcid'] DEFAULT_SETTINGS = { formatting: { diff --git a/app/models/suggested_answer.rb b/app/models/suggested_answer.rb index b4df355..5b94c8d 100644 --- a/app/models/suggested_answer.rb +++ b/app/models/suggested_answer.rb @@ -8,7 +8,8 @@ ## # Possibly needed for active_admin # -relies on protected_attributes gem as syntax depricated in rails 4.2 - attr_accessible :org_id, :question_id, :text, :is_example, :as => [:default, :admin] + attr_accessible :org_id, :question_id, :text, :is_example, + :org, :question, :as => [:default, :admin] # EVALUATE CLASS AND INSTANCE METHODS BELOW diff --git a/app/models/template.rb b/app/models/template.rb index 1ddcb9d..63b48de 100644 --- a/app/models/template.rb +++ b/app/models/template.rb @@ -12,7 +12,9 @@ ## # Possibly needed for active_admin # -relies on protected_attributes gem as syntax depricated in rails 4.2 - attr_accessible :id, :organisation_id, :description, :published, :title, :locale, :is_default, :guidance_group_ids, :as => [:default, :admin] + attr_accessible :id, :org_id, :description, :published, :title, :locale, + :is_default, :guidance_group_ids, :org, :plans, :phases, + :version, :visibility, :published, :as => [:default, :admin] # defines the export setting for a template object has_settings :export, class_name: 'Settings::Template' do |s| diff --git a/app/models/token_permission_type.rb b/app/models/token_permission_type.rb index 0d1f291..a7362d9 100644 --- a/app/models/token_permission_type.rb +++ b/app/models/token_permission_type.rb @@ -2,7 +2,7 @@ ## # Associations #has_and_belongs_to_many :org_token_permissions, join_table: "org_token_permissions" - has_and_belongs_to_many :organisations, join_table: 'org_token_permissions' + has_and_belongs_to_many :organisations, join_table: 'org_token_permissions', unique: true ## # Possibly needed for active_admin diff --git a/app/models/user.rb b/app/models/user.rb index 6932106..1a3df5c 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,5 +1,6 @@ class User < ActiveRecord::Base include GlobalHelpers + ## # Devise # Include default devise modules. Others available are: @@ -30,6 +31,9 @@ self.where(conditions) end end + + has_many :user_identifiers + has_many :identifier_schemes, through: :user_identifiers ## # Possibly needed for active_admin @@ -39,7 +43,7 @@ :firstname, :last_login,:login_count, :orcid_id, :password, :shibboleth_id, :user_status_id, :surname, :user_type_id, :org_id, :skip_invitation, :other_organisation, :accept_terms, :role_ids, :dmponline3, :api_token, - :organisation, :language, :language_id + :organisation, :language, :language_id, :org, :perms, :confirmed_at validates :email, email: true, allow_nil: true, uniqueness: true @@ -77,6 +81,15 @@ end ## + # Returns the user's identifier for the specified scheme name + # + # @param the identifier scheme name (e.g. ORCID) + # @return [UserIdentifier] the user's identifier for that scheme + def identifier_for(scheme) + user_identifiers.where(identifier_scheme: scheme).first + end + + ## # sets a new organisation id for the user # if the user has any perms such as org_admin or admin, those are removed # if the user had an api_token, that is removed @@ -229,4 +242,31 @@ #UserMailer.api_token_granted_notification(self) end end + + ## + # Load the user based on the scheme and id provided by the Omniauth call + # -------------------------------------------------------------- + def self.from_omniauth(auth) + scheme = IdentifierScheme.find_by(name: auth.provider.downcase) + + if scheme.nil? + throw Exception.new('Unknown OAuth provider: ' + auth.provider) + else + joins(:user_identifiers).where('user_identifiers.identifier': auth.uid, + 'user_identifiers.identifier_scheme_id': scheme.id).first + end + end + + # this generates a reset password link for a given user + # which can then be sent to them with the appropriate host + # prepended. + def reset_password_link + raw, enc = Devise.token_generator.generate(self.class, :reset_password_token) + self.reset_password_token = enc + self.reset_password_sent_at = Time.now.utc + save(validate: false) + + edit_user_password_path + '?reset_password_token=' + raw + end + end diff --git a/app/models/user_identifier.rb b/app/models/user_identifier.rb new file mode 100644 index 0000000..6623765 --- /dev/null +++ b/app/models/user_identifier.rb @@ -0,0 +1,9 @@ +class UserIdentifier < ActiveRecord::Base + belongs_to :user + belongs_to :identifier_scheme + + # Should only be able to have one identifier per scheme! + validates_uniqueness_of :identifier_scheme, scope: :user + + validates :identifier, :user, :identifier_scheme, presence: true +end \ No newline at end of file diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb index 60c76fd..9ca5bcc 100644 --- a/app/policies/project_policy.rb +++ b/app/policies/project_policy.rb @@ -39,4 +39,5 @@ def possible_guidance? true end + end \ No newline at end of file diff --git a/app/validators/url_validator.rb b/app/validators/url_validator.rb new file mode 100644 index 0000000..a967c32 --- /dev/null +++ b/app/validators/url_validator.rb @@ -0,0 +1,7 @@ +class UrlValidator < ActiveModel::EachValidator + def validate_each(record, attribute, value) + unless value =~ /https?:\/\/[-a-zA-Z0-9@:%_\+.~#?&\/=]{2,256}\.[a-z]{2,4}\b(\/[-a-zA-Z0-9@:%_\+.~#?&\/=]*)?/ + record.errors[attribute] << (options[:message] || "is not a valid URL") + end + end +end \ No newline at end of file diff --git a/app/views/contact_us/contacts/new.html.erb b/app/views/contact_us/contacts/new.html.erb index 73562ec..57596a5 100644 --- a/app/views/contact_us/contacts/new.html.erb +++ b/app/views/contact_us/contacts/new.html.erb @@ -97,18 +97,26 @@ <% end %> + -
    -
    - <%= raw t("contact_page.address_text_html", - organisation_name: Rails.configuration.branding[:organisation][:name], - organisation_email: Rails.configuration.branding[:organisation][:email], - application_name: Rails.configuration.branding[:application][:name],) %> - -
    - +
    +
    + <%= raw t("contact_page.address_text_html", + organisation_name: Rails.configuration.branding[:organisation][:name], + organisation_email: Rails.configuration.branding[:organisation][:email], + application_name: Rails.configuration.branding[:application][:name], + organisation_telephone: Rails.configuration.branding[:organisation][:telephone], + organisation_address_line1: Rails.configuration.branding[:organisation][:address_line1], + organisation_address_line2: Rails.configuration.branding[:organisation][:address_line2], + organisation_address_line3: Rails.configuration.branding[:organisation][:address_line3], + organisation_address_line4: Rails.configuration.branding[:organisation][:address_line4], + organisation_address_country: Rails.configuration.branding[:organisation][:address_country]) %> + +
    + +
    -
    +
    diff --git a/app/views/devise/registrations/_external_identifier.html.erb b/app/views/devise/registrations/_external_identifier.html.erb new file mode 100644 index 0000000..bbc8d75 --- /dev/null +++ b/app/views/devise/registrations/_external_identifier.html.erb @@ -0,0 +1,27 @@ +
    ); background-size: 16px 16px;"> + + <% if id.nil? || id.identifier == '' %> + + <%= link_to "#{t("identifier_schemes.schemes.#{scheme.name}.connect")}", + Rails.application.routes.url_helpers.send( + "user_#{scheme.name.downcase}_omniauth_authorize_path" + ), + title: t("identifier_schemes.schemes.#{scheme.name}.connect_tooltip") %> + + <% else %> + <% if t("identifier_schemes.schemes.#{scheme.name}.user_landing_page").nil? %> + <%= t("identifier_schemes.schemes.connect_success").gsub(/%\{scheme\}/, scheme.name.capitalize) %> + + <% else %> + <% uri = t("identifier_schemes.schemes.#{scheme.name}.user_landing_page").gsub(/%\{id\}/, id.identifier) %> + <%= link_to uri, uri, target: '_blank', + title: t("identifier_schemes.schemes.#{scheme.name}.connect_tooltip") %> + <% end %> + + <%= link_to image_tag('remove.png', height: '16px', width: '16px'), + destroy_user_identifier_path(id), method: :delete, + title: t("identifier_schemes.schemes.#{scheme.name}.disconnect_tooltip"), + data: {confirm: t("identifier_schemes.schemes.#{scheme.name}.disconnect_confirmation")} %> + <% end %> +
    diff --git a/app/views/devise/registrations/edit.html.erb b/app/views/devise/registrations/edit.html.erb index 9e320e7..ae0c08c 100644 --- a/app/views/devise/registrations/edit.html.erb +++ b/app/views/devise/registrations/edit.html.erb @@ -10,75 +10,81 @@

    <%= raw t("helpers.user_details_paragraph_html") %>

    - - - - - - - - - - - - - - - - - - "> - - - +
    <%= (t("helpers.email") + " *") %><%= f.email_field :email, as: :email %>
    <%= t("helpers.first_name") %><%= f.text_field :firstname, as: :string, - id: "first_time_login_firstname", - autofocus: true, - class: "text_field has-tooltip", - "data-toggle" => "tooltip", - "data-trigger" => "focus" , - "title" => t("helpers.first_name_help_text") %>
    <%= t("helpers.last_name") %><%= f.text_field :surname, - as: :string, id: "first_time_login_surname", - class: "text_field has-tooltip", - "data-toggle" => "tooltip", - "data-trigger" => "focus" , - "title" => t("helpers.surname_help_text") %>
    <%= t("helpers.org_type.organisation") %><%= collection_select(:user, - :org_id, @orgs, - :id, :name, {include_blank: constant("organisation_types.organisation")}, - { class: "typeahead org_sign_up" }) %>
    + + + + + + + + + + + + + + + + + "> + + + - + - - - - - <% unless @user.api_token.blank? %> - - - - - - - - - <% end %> -
    <%= (t("helpers.email") + " *") %><%= f.email_field :email, as: :email %>
    <%= t("helpers.first_name") %><%= f.text_field :firstname, as: :string, + id: "first_time_login_firstname", + autofocus: true, + class: "text_field has-tooltip", + "data-toggle" => "tooltip", + "data-trigger" => "focus" , + "title" => t("helpers.first_name_help_text") %>
    <%= t("helpers.last_name") %><%= f.text_field :surname, + as: :string, id: "first_time_login_surname", + class: "text_field has-tooltip", + "data-toggle" => "tooltip", + "data-trigger" => "focus" , + "title" => t("helpers.surname_help_text") %>
    <%= t("helpers.org_type.organisation") %><%= collection_select(:user, + :org_id, @orgs, + :id, :name, {include_blank: constant("organisation_types.organisation")}, + { class: "typeahead org_sign_up" }) %>
    <%= t('helpers.user_details_language') %> - - + + + -
    <%= t("helpers.orcid_id") %><%= f.text_field :orcid_id , - as: :string, - autocomplete: "off" , - class: "text_field has-tooltip", "data-toggle" => "tooltip", "data-html" => "true", "title" => t("helpers.orcid_html") %>
    <%= t("helpers.api_token") %><%= @user.api_token %>
    <%= t("helpers.api_info") %><%= link_to( t("helpers.api_use"), controller: "token_permission_types", action: "index")%>
    -
    -

    + + <% @identifier_schemes.each do |scheme| %> + + <%= scheme.name %> + + <%= render partial: 'external_identifier', + locals: {scheme: scheme, + id: current_user.identifier_for(scheme)} %> + + + <% end %> + + + <% unless @user.api_token.blank? %> + + <%= t("helpers.api_token") %> + <%= @user.api_token %> + + + <%= t("helpers.api_info") %> + <%= link_to( t("helpers.api_use"), controller: "token_permission_types", action: "index")%> + + <% end %> + +
    +

    <% if Rails.application.config.shibboleth_enabled %> <% if resource.shibboleth_id.nil? || resource.shibboleth_id.length == 0 then %> <%= link_to t("helpers.shibboleth_to_link_text"), user_omniauth_shibboleth_path, class: "a-orange" %> @@ -89,38 +95,38 @@ <% end %> <% end %> -

    -
    -
    -
    -

    - <%= raw t("helpers.edit_password_info")%> -

    - - <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %> -
    <%= t('custom_devise.waiting_for_confirmation') %><%= resource.unconfirmed_email %>
    - <% end %> - - - - - - - - - - - - -
    <%= t("helpers.current_password") %> - <%= f.password_field :current_password, as: :password %> -
    <%= t("helpers.new_password") %><%= f.password_field :password, as: :password, autocomplete: "off" %> -
    <%= t("helpers.password_conf") %><%= f.password_field :password_confirmation, as: :password, autocomplete: "off" %>
    -
    - <%= f.submit t("helpers.submit.save"), class: "btn btn-primary" %> - <%= link_to t("helpers.submit.cancel"), :back, class: "btn btn-primary" %> -
    - <% end %> +

    +
    +
    +
    +

    + <%= raw t("helpers.edit_password_info")%> +

    + + <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %> +
    <%= t('custom_devise.waiting_for_confirmation') %><%= resource.unconfirmed_email %>
    + <% end %> + + + + + + + + + + + + +
    <%= t("helpers.current_password") %> + <%= f.password_field :current_password, as: :password %> +
    <%= t("helpers.new_password") %><%= f.password_field :password, as: :password, autocomplete: "off" %> +
    <%= t("helpers.password_conf") %><%= f.password_field :password_confirmation, as: :password, autocomplete: "off" %>
    +
    + <%= f.submit t("helpers.submit.save"), class: "btn btn-primary" %> + <%= link_to t("helpers.submit.cancel"), :back, class: "btn btn-primary" %> +
    + <% end %>
    diff --git a/app/views/dmptemplates/_add_question.html.erb b/app/views/dmptemplates/_add_question.html.erb new file mode 100644 index 0000000..b9bbfc8 --- /dev/null +++ b/app/views/dmptemplates/_add_question.html.erb @@ -0,0 +1,183 @@ + + +<% @new_question = Question.new %> +<% @new_question.number = section.questions.count + 1 %> + + +<%= form_for @new_question, :url => {:action => "admin_createquestion"}, :html => {:id => "new_question_#{section.id}"} do |f| %> +<%= f.hidden_field :section_id, :value => section.id %> +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    <%= t("org_admin.questions.question_number_label")%><%= f.number_field :number, :in => 1..50, :class => "number_field has-tooltip", "data-toggle" => "tooltip", "title" => t("org_admin.questions.number_help_text") %> + +
    +
    <%= t("org_admin.questions.question_text_label")%><%= f.text_area :text, :rows => "5", :id => "new_question_text_#{section.id}" %> +
    +
    <%= t("org_admin.questions.answer_format_label")%><%= f.hidden_field :section_id, :value => section.id, :class => "section_id" %> +
    +
    + <%= f.select :question_format_id, + #options_from_collection_for_select(QuestionFormat.all.order("title"), :id, :title, QuestionFormat.find_by_title(t("helpers.text_area")).id), + # the above was the line but it doesn't work because in the DB + # the QuestionFormat title is in English (Text area) + # but the above uses the Fr translation and so gets a nil + options_from_collection_for_select(QuestionFormat.all.order("title"), :id, :title, QuestionFormat.find_by_title("Text area").id), + {}, :id => "new-select-format-#{section.id}"%> +
    +
    + <%= link_to( image_tag("help_button.png"), "#", :class => "question_format_popover", :rel => "popover", "data-html" => "true", "data-content" => t("org_admin.questions.question_format_help_text_html"))%> +
    + +
    +
    + + +
    + + +
    + + +
    + +
    +
    +
    +
    <%= t("org_admin.questions.suggested_or_example_answer_label")%>
    + <% suggested_answer = @new_question.suggested_answers.build %> + <%= f.fields_for :suggested_answers, suggested_answer do |s|%> + <%= s.hidden_field :organisation_id, :value => current_user.organisation.id %> +
      +
    • <%= s.select :is_example, {t("org_admin.questions.example_answer_label") => true, t("org_admin.questions.suggested_answer_label") => false} %>
    • +
    • <%= s.text_area :text, :rows => 5 %>
    • +
    + <%end%> +
    +
    + <%= link_to( image_tag("help_button.png"), "#", :class => "suggested_answer_popover", :rel => "popover", "data-html" => "true", "data-content" => t("org_admin.questions.suggested_answer_help_text_html"))%> +
    +
    +
    + +
    <%= t("org_admin.questions.guidance_label")%>
    + <%= text_area_tag("new-question-guidance", "", class: "tinymce") %> +
    +
    + <%= link_to( image_tag("help_button.png"), "#", :class => "question_guidance_popover", :rel => "popover", "data-html" => "true", "data-content" => t("org_admin.questions.question_guidance_help_text_html"))%> +
    +
    +
    +
    <%= t("org_admin.questions.themes_label")%>
    + <%= f.collection_select(:theme_ids, + Theme.all.order("title"), + :id, :title, {:prompt => false, :include_blank => t('helpers.none')}, {:multiple => true})%> +
    +
    + <%= link_to( image_tag("help_button.png"), "#", :class => "question_themes_popover", :rel => "popover", "data-html" => "true", "data-content" => t("org_admin.questions.question_themes_help_text_html"))%> +
    + + +
    +
    + + +
    + <%= hidden_field_tag :section_id, section.id, :class => "section_id" %> + <%= f.submit t("helpers.submit.save"), :class => "btn btn-primary new_question_save_button" %> + <%= hidden_field_tag :section_id, section.id, :class => "section_id_new" %> + <%= link_to t("helpers.submit.cancel"), '#', :class => "btn cancel cancel_add_new_question" %> +
    +
    + +<%end%> + diff --git a/app/views/dmptemplates/_admin_nav_tabs.html.erb b/app/views/dmptemplates/_admin_nav_tabs.html.erb new file mode 100644 index 0000000..e2237ea --- /dev/null +++ b/app/views/dmptemplates/_admin_nav_tabs.html.erb @@ -0,0 +1,34 @@ + + + diff --git a/app/views/layouts/_navigation.html.erb b/app/views/layouts/_navigation.html.erb index 671ab79..8fa890a 100644 --- a/app/views/layouts/_navigation.html.erb +++ b/app/views/layouts/_navigation.html.erb @@ -97,6 +97,16 @@ <% end %> <%= t("helpers.help_label") %>
  • + + + <% if current_path == "/plans/public_plans" then %> +
  • + <% else %> +
  • + <% end %> + <%= t("helpers.public_plans_label") %> +
  • + <% end %> - \ No newline at end of file + diff --git a/app/views/plans/_answer_form.html.erb b/app/views/plans/_answer_form.html.erb index 29be29c..dd256e4 100644 --- a/app/views/plans/_answer_form.html.erb +++ b/app/views/plans/_answer_form.html.erb @@ -47,24 +47,27 @@ <% end %> - <% if q_format.title == t("helpers.checkbox") || q_format.title == t("helpers.multi_select_box") || q_format.title == t("helpers.radio_buttons") || q_format.title == t("helpers.dropdown") then%> + <% if q_format.title == "Check box" || + q_format.title == "Multi select box" || + q_format.title == "Radio buttons" || + q_format.title == "Dropdown" then%> <% options = question.options.order("number") %> - <% if q_format.title == t("helpers.checkbox") then %> + <% if q_format.title == "Check box" then %> <% if readonly then %> <%= f.input :options, :as => :check_boxes, :collection => options, :label => false, input_html => { :disabled => true, :id => "options-#{question.id}" } %> <% else %> <%= f.input :options, :as => :check_boxes, :collection => options, :label => false, :input_html => { :id => "options-#{question.id}" } %> <% end %> - <% elsif q_format.title == t("helpers.multi_select_box") then %> + <% elsif q_format.title == "Multi select box" then %> <% if readonly then %> <%= f.input :options, :as => :select, :collection => options, :label => false, :input_html => { :multiple => true, :disabled => true , :id => "options-#{question.id}" } %> <% else %> <%= f.input :options, :as => :select, :collection => options, :label => false, :input_html => { :multiple => true , :id => "options-#{question.id}" } %> <% end %> - <% elsif q_format.title == t("helpers.radio_buttons") then%> + <% elsif q_format.title == "Radio buttons" then%>
      <% options.each do |op| %>
    1. @@ -85,7 +88,7 @@ <% end %>
    - <% elsif q_format.title == t("helpers.dropdown") then%> + <% elsif q_format.title == "Dropdown" then%> <% if readonly then %> <%= f.input :options, :as => :select, :collection => options, :label => false, :input_html => { :multiple => false, :disabled => true, :id => "options-#{question.id}" } %> <% else %> @@ -99,10 +102,10 @@ <%end%> - <% elsif q_format.title == t("helpers.text_field") then %> + <% elsif q_format.title == "Text field" then %> <%= text_field_tag("answer-text-#{question.id}".to_sym, strip_tags(answer.text), class: "question_text_field") %> - <% elsif q_format.title == t("helpers.text_area") then%> + <% elsif q_format.title == "Text area" then%> <%= text_area_tag("answer-text-#{question.id}".to_sym, answer.text, class: "tinymce") %> <% end %> @@ -113,7 +116,8 @@ <% if readonly then %> <%= f.action :submit, :label => t("helpers.save"), :button_html => { :class => "btn btn-primary"}, :input_html => { :disabled => true } %> <% else %> - <%= f.action :submit, :label => t("helpers.save"), :button_html => { :class => "btn btn-primary"} %> + + <% end %> <% end %> @@ -124,7 +128,10 @@
    >

    <%= question.text %>

    - <% if q_format.title == t("helpers.checkbox") || q_format.title == t("helpers.multi_select_box") || q_format.title == t("helpers.radio_buttons") || q_format.title == t("helpers.dropdown") %> + <% if q_format.title == "Check box" || + q_format.title == "Multi select box" || + q_format.title == "Radio buttons" || + q_format.title == "Dropdown" %>
      <% if answer.options.is_a? Option then %>
    • <%= answer.options.text %>
    • diff --git a/app/views/projects/_dropdowns_new_project.html.erb b/app/views/projects/_dropdowns_new_project.html.erb index 241753b..92b9dd5 100644 --- a/app/views/projects/_dropdowns_new_project.html.erb +++ b/app/views/projects/_dropdowns_new_project.html.erb @@ -68,27 +68,27 @@ # (they are referenced in /app/assets/javascripts/projects.js) # %> - <%= hash_to_json_object('funders', + <%= hash_to_js_json_variable('funders', @funders.collect{ |inst| {'id': inst.id, 'text': inst.name} }) %> - <%= hash_to_json_object('institutions', + <%= hash_to_js_json_variable('institutions', @institutions.collect{ |inst| {'id': inst.id, 'text': inst.name, 'default': (current_user.organisation_id == inst.id)} }) %> - <%= hash_to_json_object('templates', + <%= hash_to_js_json_variable('templates', @templates.collect{ |tmplt| {'organisation': tmplt.organisation_id, 'id': tmplt.id, 'text': tmplt.title} }) %> - <%= hash_to_json_object('guidance_for_template_or_organisation', + <%= hash_to_js_json_variable('guidance_for_template_or_organisation', @guidance_groups.collect{ |grp| {'organisation': grp.organisation_id, 'templates': grp.dmptemplates.collect{ |t| t.id }, @@ -96,7 +96,7 @@ 'text': grp.name} }) %> - <%= hash_to_json_object('guidance_always_available', + <%= hash_to_js_json_variable('guidance_always_available', @always_guidance.collect{ |grp| {'id': grp.id, 'text': grp.name} diff --git a/app/views/projects/_form.html.erb b/app/views/projects/_form.html.erb index 526577f..360d87f 100644 --- a/app/views/projects/_form.html.erb +++ b/app/views/projects/_form.html.erb @@ -18,6 +18,12 @@ <%= f.text_area :note, :class => 'text_area', :rows => 10 %>
    +
    + <%= f.label t('helpers.is_test'), class: 'left-label' %> +
    + <%= f.check_box :is_test, class: 'check_box has-tooltip', 'data-toggle': 'tooltip' title: t('helpers.project.is_test_help_text') %> +
    +
    <%= f.submit t("helpers.submit.save"), :class => 'btn btn-primary' %> <%= link_to t("helpers.links.cancel"), diff --git a/app/views/projects/_project_details.html.erb b/app/views/projects/_project_details.html.erb index dc62033..6826f47 100644 --- a/app/views/projects/_project_details.html.erb +++ b/app/views/projects/_project_details.html.erb @@ -1,277 +1,299 @@
    -
    "> -
    -

    - <%= t('helpers.project.project_details_text_html')%> -

    -
    +
    "> +
    +

    + <%= t('helpers.project.project_details_text_html')%> +

    +
    - -
    - -
    - - - - - - - - - - - - - - - - - - <% if !@project.principal_investigator_identifier.nil? && @project.principal_investigator_identifier != "" then %> - - - - - <%end%> - - - - - - - - -
    <%= t('helpers.project.project_name') %><%= @project.title %>
    <%= t('helpers.project.project_identifier') %> - <% if !@project.identifier.nil? && @project.identifier != "" then %> - <%= @project.identifier %> - <%else%> - - - <%end%> -
    <%= t('helpers.project.grant_title') %> - <% if !@project.grant_number.nil? && @project.grant_number!= "" then %> - <%= @project.grant_number %> - <%else%> - - - <%end%> -
    <%= t('helpers.project.principal_investigator') %><% if !@project.principal_investigator.nil? && @project.principal_investigator != "" then %> - <%= @project.principal_investigator %> - <%else%> - - - <%end%> -
    <%= t('helpers.project.principal_investigator_id') %> - <%= @project.principal_investigator_identifier %> -
    <%= t('helpers.project.project_data_contact') %><% if !@project.data_contact.nil? && @project.data_contact != "" then%> - <%= @project.data_contact %> - <%else%> - - - <%end%> -
    <%= t('helpers.desc') %><% if !@project.description.nil? && @project.description != "" then%> - <%= @project.description %> - <%else%> - - - <%end%> -
    -
    -
    - <% if @project.administerable_by(current_user.id) then %> -
    "> - -
    -

    - <%= raw t('helpers.project.project_details_editing_text_html')%> -

    -
    - -
    - <%= semantic_form_for @project, :url => {:controller => :projects, :action => :update }, :html=>{:method=>:put} do |f| %> - <%= f.inputs do %> -
    + +
    + <% if @project.administerable_by(current_user.id) then %> + <%= t("helpers.project.edit") %> + <% end %> +
    + +
    + + + + + + + + + + + + + + + + + + <% if !@project.principal_investigator_identifier.nil? && @project.principal_investigator_identifier != "" then %> + + + + + <%end%> + + + + + + + + + + + + +
    <%= t('helpers.project.project_name') %><%= @project.title %>
    <%= t('helpers.project.project_identifier') %> + <% if !@project.identifier.nil? && @project.identifier != "" then %> + <%= @project.identifier %> + <%else%> + - + <%end%> +
    <%= t('helpers.project.grant_title') %> + <% if !@project.grant_number.nil? && @project.grant_number!= "" then %> + <%= @project.grant_number %> + <%else%> + - + <%end%> +
    <%= t('helpers.project.principal_investigator') %><% if !@project.principal_investigator.nil? && @project.principal_investigator != "" then %> + <%= @project.principal_investigator %> + <%else%> + - + <%end%> +
    <%= t('helpers.project.principal_investigator_id') %> + <%= @project.principal_investigator_identifier %> +
    <%= t('helpers.project.project_data_contact') %><% if !@project.data_contact.nil? && @project.data_contact != "" then%> + <%= @project.data_contact %> + <%else%> + - + <%end%> +
    <%= t('helpers.desc') %><% if !@project.description.nil? && @project.description != "" then%> + <%= @project.description %> + <%else%> + - + <%end%> +
    <%= t('helpers.project.visibility') %><%= (@project.is_test? ? t("helpers.project.visibilities.help_texts.is_test") : (@project.organisationally_visible? ? t("helpers.project.visibilities.help_texts.organisationally_visible") : (@project.publicly_visible? ? t("helpers.project.visibilities.help_texts.publicly_visible") : (@project.privately_visible? ? t("helpers.project.visibilities.help_texts.privately_visible") : "Defaulting to: #{t("helpers.project.visibilities.help_texts.not_set")}")))) %>
    +
    +
    + <% if @project.administerable_by(current_user.id) then %> +
    "> + +
    +

    + <%= raw t('helpers.project.project_details_editing_text_html')%> +

    +
    + +
    + <%= semantic_form_for @project, :url => {:controller => :projects, :action => :update }, :html=>{:method=>:put} do |f| %> + <%= f.inputs do %> +
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    <%= t('helpers.project.project_name') %> - <%= f.text_field :title, :class => 'text_field has-tooltip', 'data-toggle' => "tooltip", 'title' => t('helpers.project.project_name_help_text') %> -
    <%= t('helpers.project.project_identifier') %> - <%= f.text_field :identifier, :class => 'text_field has-tooltip', 'data-toggle' => "tooltip", 'title' => t('helpers.project.project_identifier_help_text') %> -
    <%= t('helpers.project.grant_title') %> - <%= f.text_field :grant_number, :class => 'text_field has-tooltip', 'data-toggle' => "tooltip", 'title' => t('helpers.project.grant_help_text') %> -
    <%= t('helpers.project.principal_investigator') %> - <%= f.text_field :principal_investigator, :class => 'text_field has-tooltip', 'data-toggle' => "tooltip", 'title' => t('helpers.project.principal_investigator_help_text') %> -
    <%= t('helpers.project.principal_investigator_id') %> - <%= f.text_field :principal_investigator_identifier, :class => 'text_field has-tooltip', 'data-toggle' => "tooltip", 'title' => t('helpers.project.principal_investigator_id_help_text') %> -
    <%= t('helpers.project.project_data_contact') %> - <%= f.text_field :data_contact, :class => 'text_field has-tooltip', 'data-toggle' => "tooltip", 'title' => t('helpers.project.project_data_contact_help_text') %> -
    <%= t('helpers.desc') %> - <%= f.text_area :description, { :rows => 7, :class => 'text_area has-tooltip', 'data-toggle' => "tooltip", 'data-html' => "true", 'title'=> t('helpers.project.project_desc_help_text_html')} %> -
    -
    - <% end %> - - <%= f.actions do %> -
    - <%= f.submit t("helpers.submit.save"), :class => 'btn btn-primary' %> - <%= t("helpers.links.cancel") %> -
    - <%end%> - <%end%> -
    - <% end %> -

    <%= t('helpers.project.project_static_info')%>

    - - - <%if @project.dmptemplate.organisation.organisation_type.name == constant("organisation_types.funder")%> - - - - - <%end%> - <%if !@project.organisation_id.nil? %> - - - - - <%end%> -
    <%= constant("organisation_types.funder") %><%= @project.dmptemplate.organisation.name %>
    <%= constant("organisation_types.institution") %><%= @project.organisation.name %>
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    <%= t('helpers.project.project_name') %> + <%= f.text_field :title, :class => 'text_field has-tooltip', 'data-toggle' => "tooltip", 'title' => t('helpers.project.project_name_help_text') %> +
    <%= t('helpers.project.project_identifier') %> + <%= f.text_field :identifier, :class => 'text_field has-tooltip', 'data-toggle' => "tooltip", 'title' => t('helpers.project.project_identifier_help_text') %> +
    <%= t('helpers.project.grant_title') %> + <%= f.text_field :grant_number, :class => 'text_field has-tooltip', 'data-toggle' => "tooltip", 'title' => t('helpers.project.grant_help_text') %> +
    <%= t('helpers.project.principal_investigator') %> + <%= f.text_field :principal_investigator, :class => 'text_field has-tooltip', 'data-toggle' => "tooltip", 'title' => t('helpers.project.principal_investigator_help_text') %> +
    <%= t('helpers.project.principal_investigator_id') %> + <%= f.text_field :principal_investigator_identifier, :class => 'text_field has-tooltip', 'data-toggle' => "tooltip", 'title' => t('helpers.project.principal_investigator_id_help_text') %> +
    <%= t('helpers.project.project_data_contact') %> + <%= f.text_field :data_contact, :class => 'text_field has-tooltip', 'data-toggle' => "tooltip", 'title' => t('helpers.project.project_data_contact_help_text') %> +
    <%= t('helpers.desc') %> + <%= f.text_area :description, { :rows => 7, :class => 'text_area has-tooltip', 'data-toggle' => "tooltip", 'data-html' => "true", 'title'=> t('helpers.project.project_desc_help_text_html')} %> +
    <%= t('helpers.project.visibility') %> +
    + /><%= t('helpers.project.visibilities.help_texts.publicly_visible') %> +
    +
    + /><%= t('helpers.project.visibilities.help_texts.organisationally_visible') %> +
    +
    + /><%= t('helpers.project.visibilities.help_texts.is_test') %> +
    +
    + /><%= t('helpers.project.visibilities.help_texts.privately_visible') %> +
    +
    +
    + <% end %> + + <%= f.actions do %> +
    + <%= f.submit t("helpers.submit.save"), :class => 'btn btn-primary' %> + <%= t("helpers.links.cancel") %> +
    + <%end%> + <%end%> +
    + <% end %> +

    <%= t('helpers.project.project_static_info')%>

    + + + <%if @project.dmptemplate.organisation.organisation_type.name == constant("organisation_types.funder")%> + + + + + <%end%> + <%if !@project.organisation_id.nil? %> + + + + + <%end%> +
    <%= constant("organisation_types.funder") %><%= @project.dmptemplate.organisation.name %>
    <%= constant("organisation_types.institution") %><%= @project.organisation.name %>
    +>>>>>>> final_schema - - <% if @project.plans.any? %> - <% if @project.plans.count == 1 then %> - <% @project.plans.each do |plan| %> + + <% if @project.plans.any? %> + <% if @project.plans.count == 1 then %> + <% @project.plans.each do |plan| %> -
    - <%= link_to t('helpers.answer_questions'), [:edit, @project, plan], :class => 'btn btn-primary' %> - <%= t('helpers.export') %> -
    - <%= render :partial => "plans/export", locals: {plan: plan} %> -
    -

    <%= raw plan.version.phase.description %>

    - <% if !plan.sections.nil? %> - - - - - - - - - <% plan.sections.each do |section| %> - - - - - <%end%> - -
    <%= t('helpers.sections_label')%><%= t('helpers.questions_label')%>
    -

    <%= section.title %>

    -
    - <% if section.questions.any? %> - <% questions = section.questions.sort_by(&:number) %> -
      - <% questions.each do |ques|%> -
    • - <%= raw ques.text %> -
    • - <%end%> -
    - <%end%> -
    - <%end%> - <%end%> - <%else%> -
    - <%= raw @project.dmptemplate.description %> -
    - <% @project.plans.each do |plan| %> -
    -
    - -
    -
    -
    - <%= link_to t('helpers.answer_questions'), [:edit, @project, plan], :class => 'btn btn-primary' %> - <%= t('helpers.export') %> -
    - <%= render :partial => "plans/export", locals: {plan: plan} %> -
    -

    <%= raw plan.version.phase.description %> -

    +
    + <%= link_to t('helpers.answer_questions'), [:edit, @project, plan], :class => 'btn btn-primary' %> + <%= t('helpers.export') %> +
    + <%= render :partial => "plans/export", locals: {plan: plan} %> +
    +

    <%= raw plan.version.phase.description %>

    + <% if !plan.sections.nil? %> + + + + + + + + + <% plan.sections.each do |section| %> + + + + + <%end%> + +
    <%= t('helpers.sections_label')%><%= t('helpers.questions_label')%>
    +

    <%= section.title %>

    +
    + <% if section.questions.any? %> + <% questions = section.questions.sort_by(&:number) %> +
      + <% questions.each do |ques|%> +
    • + <%= raw ques.text %> +
    • + <%end%> +
    + <%end%> +
    + <%end%> + <%end%> + <%else%> +
    + <%= raw @project.dmptemplate.description %> +
    + <% @project.plans.each do |plan| %> +
    +
    + +
    +
    +
    + <%= link_to t('helpers.answer_questions'), [:edit, @project, plan], :class => 'btn btn-primary' %> + <%= t('helpers.export') %> +
    + <%= render :partial => "plans/export", locals: {plan: plan} %> +
    +

    <%= raw plan.version.phase.description %> +

    - <% if !plan.sections.nil? %> - - - - - - - - - <% plan.sections.each do |section| %> - - - - - <%end%> - -
    <%= t('helpers.sections_label')%><%= t('helpers.questions_label')%>
    -

    <%= section.title %>

    -
    - <% if section.questions.any? %> - <% questions = section.questions.sort_by(&:number) %> -
      - <% questions.each do |ques|%> -
    • - - <%= ques.text %> -
    • - <%end%> -
    - <%end%> -
    - <%end%> -
    -
    -
    -
    - <%end%> - <%end%> - <%end%> + <% if !plan.sections.nil? %> + + + + + + + + + <% plan.sections.each do |section| %> + + + + + <%end%> + +
    <%= t('helpers.sections_label')%><%= t('helpers.questions_label')%>
    +

    <%= section.title %>

    +
    + <% if section.questions.any? %> + <% questions = section.questions.sort_by(&:number) %> +
      + <% questions.each do |ques|%> +
    • + - <%= ques.text %> +
    • + <%end%> +
    + <%end%> +
    + <%end%> +
    +
    +
    +
    + <%end%> + <%end%> + <%end%>
    diff --git a/app/views/projects/_project_nav_tabs.html.erb b/app/views/projects/_project_nav_tabs.html.erb index 9e860f6..07200bd 100644 --- a/app/views/projects/_project_nav_tabs.html.erb +++ b/app/views/projects/_project_nav_tabs.html.erb @@ -9,8 +9,9 @@ <% end %> <%= link_to t("helpers.project.tab_plan"), project_path(project) %> - - <% project.plans.each do |plan| %> + + <% pplans = project.plans.sort { |x,y| x.version.phase.number <=> y.version.phase.number} %> + <% pplans.each do |plan| %> <% if active == plan.id then %>
  • <% else %> @@ -42,4 +43,4 @@ <%= link_to t("helpers.project.tab_export"), ["export",project] %>
  • -
    \ No newline at end of file + diff --git a/app/views/projects/show.html.erb b/app/views/projects/show.html.erb index 9dd737c..8faab88 100644 --- a/app/views/projects/show.html.erb +++ b/app/views/projects/show.html.erb @@ -1,3 +1,5 @@ +<%= javascript_include_tag "projects" %> + <%- model_class = Project -%> diff --git a/app/views/settings/plans/_export_formatting_form.html.erb b/app/views/settings/plans/_export_formatting_form.html.erb index 632a9b1..ffa3cb2 100644 --- a/app/views/settings/plans/_export_formatting_form.html.erb +++ b/app/views/settings/plans/_export_formatting_form.html.erb @@ -10,8 +10,8 @@ <%= form_for(@export_settings, url: settings_plan_path(plan), method: :put, as: :export, remote: true) do |f| %>
    - <%= submit_tag(t("helpers.settings.plans.reset"), class: "btn btn-primary") %> - <%= submit_tag(t("helpers.save"), class: "btn btn-primary", "data-toggle" => "collapse", "data-target" => "#settings-accordion-plan-#{plan.version.phase.id}") %> + <%= submit_tag(t("helpers.settings.plans.reset"), class: "resetbutton btn btn-primary") %> + <%= submit_tag(t("helpers.save"), class: "savebutton btn btn-primary", "data-toggle" => "collapse", "data-target" => "#settings-accordion-plan-#{plan.version.phase.id}") %>
    diff --git a/app/views/shared/_register_form.html.erb b/app/views/shared/_register_form.html.erb index 462083a..cb61bfb 100644 --- a/app/views/shared/_register_form.html.erb +++ b/app/views/shared/_register_form.html.erb @@ -20,6 +20,10 @@ <%= f.text_field :surname, placeholder: t('helpers.last_name'), :as => :string, :class => 'text_field' %> <% end %> + <% if resource.user_identifiers.count > 0 %> + <% scheme = resource.user_identifiers.identifier_scheme.name %> + <%= f.hidden_field "user_identifiers[#{scheme}]", value: resource.user_identifiers.first.identifier%> + <% end %>
  • <%= collection_select(:user, :organisation_id, Org.where("parent_id IS NULL").order("sort_name ASC, name ASC"), :id, :name, {include_blank: constant("organisation_types.organisation")}, { :class => 'typeahead org_sign_up' }) %>
  • diff --git a/app/views/static_pages/about_us.html.erb b/app/views/static_pages/about_us.html.erb index 59890dc..873c031 100644 --- a/app/views/static_pages/about_us.html.erb +++ b/app/views/static_pages/about_us.html.erb @@ -37,7 +37,8 @@ organisation_url: Rails.configuration.branding[:organisation][:url], application_name: Rails.configuration.branding[:application][:name], application_home: Rails.configuration.branding[:application][:home], - application_url: Rails.configuration.branding[:application][:url])%> + application_url: Rails.configuration.branding[:application][:url], + current_locale: I18n.locale)%>
    <%= raw t("about_page.body_text_tab_2_html", diff --git a/app/views/static_pages/public_export.html.erb b/app/views/static_pages/public_export.html.erb new file mode 100644 index 0000000..37f1a18 --- /dev/null +++ b/app/views/static_pages/public_export.html.erb @@ -0,0 +1,41 @@ +<%- model_class = Project -%> + + +<%= render :partial => "/projects/project_title", locals: {project: @project} %> + + +<%= render :partial => "project_nav_tabs", locals: {project: @project, active: "export_page"} %> + + +
    + + <%= raw t('helpers.project.export_text_html')%> + + + <% if @project.plans.any? %> + <% if @project.plans.count == 1 then %> + <% @project.plans.each do |plan| %> + <%= render :partial => "/shared/export_links", locals: {plan: plan} %> + <% end %> + <%else%> + <% @project.plans.each do |plan| %> +
    +
    + +
    +
    + <%= render :partial => "/shared/export_links", locals: {plan: plan} %> +
    +
    +
    +
    + <%end%> + <%end%> + <%end%> + +
    \ No newline at end of file diff --git a/app/views/static_pages/public_export.pdf.erb b/app/views/static_pages/public_export.pdf.erb new file mode 100644 index 0000000..77d68cb --- /dev/null +++ b/app/views/static_pages/public_export.pdf.erb @@ -0,0 +1,72 @@ + + + + + + <% if @plan.project.dmptemplate.phases.count > 1 then %> + <%= "#{@plan.project.title} - #{@plan.title}" %> + <% else %> + <%= @plan.project.title %> + <% end %> + + + + +

    <%= @plan.title %>

    + <% @exported_plan.admin_details.each do |field| + value = @exported_plan.send(field) + if value.present? + %> +

    <%= t("helpers.plan.export.#{field}") -%> <%= value -%>

    + <% end %> + <% end %> + + <% @exported_plan.sections.each do |section| %> +

    <%= section.title %>

    + <% questions = @exported_plan.questions_for_section(section.id) %> + <% questions.each_with_index do |question, idx| %> +
    + <% unless idx == 0 && question.text == section.title %> +

    <%= raw question.text %>

    + <% end %> + <% answer = @plan.answer(question.id, false) %> + <% if answer.nil? then %> +

    <%= t('helpers.plan.export.pdf.question_not_answered') -%>

    + <% else %> + <% q_format = question.question_format%> + + <% if q_format.title == t("helpers.checkbox") || q_format.title == t("helpers.multi_select_box") || + q_format.title == t("helpers.radio_buttons") || q_format.title == t("helpers.dropdown") then%> +
      + <% answer.options.each do |option| %> +
    • <%= option.text %>
    • + <% end %> +
    + + <% if question.option_comment_display == true then%> + <% if !answer.text.nil? then %> + <%= raw answer.text.gsub(/(\s||<\/td>| )*(<\/tr>|)/,"") %> + <%end%> + <%end%> + <%else%> + + <% if !answer.text.nil? then %> + <%= raw answer.text.gsub(/(\s||<\/td>| )*(<\/tr>|)/,"") %> + <%end%> + <% end %> + <% end %> +
    + <% end %> + <% end %> + + \ No newline at end of file diff --git a/app/views/static_pages/public_plans.html.erb b/app/views/static_pages/public_plans.html.erb new file mode 100644 index 0000000..16cdb15 --- /dev/null +++ b/app/views/static_pages/public_plans.html.erb @@ -0,0 +1,41 @@ +<%- model_class = Project -%> +

    + <%= raw t("public_plans_page.title") %> +

    + + +<% if @projects.count > 0 %> +

    + <%= raw t("public_plans_page.body_text_html", {app_name: Rails.configuration.branding[:application][:name]}) %> +

    + + + + + <% ['name', 'template', 'organisation', 'owner'].each do |column| %> + <%= project_list_column_heading(column) %> + <% end %> + + + + + <% @projects.each do |project| %> + + <% ['non_link_name', 'template', 'organisation', 'owner'].each do |column| %> + <%= project_list_column_body(column, project) %> + <% end %> + + + + <% end %> + +
    + <%= link_to t("helpers.project.tab_export"), "#{public_export_path(project)}", :class => "dmp_table_link" %> +
    + + +<% else %> +

    + <%= raw t("public_plans_page.no_plans_body_text_html")%> +

    +<% end %> diff --git a/config/application.rb b/config/application.rb index f13810f..f4e3351 100644 --- a/config/application.rb +++ b/config/application.rb @@ -98,6 +98,5 @@ # Load Branded terminology (e.g. organization name, application name, etc.) config.branding = config_for(:branding).deep_symbolize_keys - end end diff --git a/config/branding.yml b/config/branding.yml index 578347c..5649562 100644 --- a/config/branding.yml +++ b/config/branding.yml @@ -26,4 +26,4 @@ <<: *defaults production: - <<: *defaults \ No newline at end of file + <<: *defaults diff --git a/config/environment.rb b/config/environment.rb index c82b616..3488440 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -5,5 +5,4 @@ Rails.logger = Logger.new(STDOUT) # Initialize the Rails application. -#DMPonline4::Application.initialize! Rails.application.initialize! \ No newline at end of file diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb deleted file mode 100644 index f31db11..0000000 --- a/config/initializers/devise.rb +++ /dev/null @@ -1,272 +0,0 @@ -require "custom_failure" - -# Use this hook to configure devise mailer, warden hooks and so forth. -# Many of these configuration options can be set straight in your model. -Devise.setup do |config| - # The secret key used by Devise. Devise uses this key to generate - # random tokens. Changing this key will render invalid all existing - # confirmation, reset password and unlock tokens in the database. - # Devise will use the `secret_key_base` on Rails 4+ applications as its `secret_key` - # by default. You can change it below and use your own secret key. - # config.secret_key = '65991d837d53ee81812e8c15598e3f691d03d5517d9e0073b6f6eab94df0e8a8c3d6a8bc3c11f1972520187f233bf5e355645a0c7224108ed2a578e45af759cd' - - # ==> Mailer Configuration - # Configure the e-mail address which will be shown in Devise::Mailer, - # note that it will be overwritten if you use your own mailer class - # with default "from" parameter. - config.mailer_sender = 'please-change-me-at-config-initializers-devise@example.com' - - # Configure the class responsible to send e-mails. - # config.mailer = 'Devise::Mailer' - - # ==> ORM configuration - # Load and configure the ORM. Supports :active_record (default) and - # :mongoid (bson_ext recommended) by default. Other ORMs may be - # available as additional gems. - require 'devise/orm/active_record' - - # ==> Configuration for any authentication mechanism - # Configure which keys are used when authenticating a user. The default is - # just :email. You can configure it to use [:username, :subdomain], so for - # authenticating a user, both parameters are required. Remember that those - # parameters are used only when authenticating and not when retrieving from - # session. If you need permissions, you should implement that in a before filter. - # You can also supply a hash where the value is a boolean determining whether - # or not authentication should be aborted when the value is not present. - # config.authentication_keys = [:email] - - # Configure parameters from the request object used for authentication. Each entry - # given should be a request method and it will automatically be passed to the - # find_for_authentication method and considered in your model lookup. For instance, - # if you set :request_keys to [:subdomain], :subdomain will be used on authentication. - # The same considerations mentioned for authentication_keys also apply to request_keys. - # config.request_keys = [] - - # Configure which authentication keys should be case-insensitive. - # These keys will be downcased upon creating or modifying a user and when used - # to authenticate or find a user. Default is :email. - config.case_insensitive_keys = [:email] - - # Configure which authentication keys should have whitespace stripped. - # These keys will have whitespace before and after removed upon creating or - # modifying a user and when used to authenticate or find a user. Default is :email. - config.strip_whitespace_keys = [:email] - - # Tell if authentication through request.params is enabled. True by default. - # It can be set to an array that will enable params authentication only for the - # given strategies, for example, `config.params_authenticatable = [:database]` will - # enable it only for database (email + password) authentication. - # config.params_authenticatable = true - - # Tell if authentication through HTTP Auth is enabled. False by default. - # It can be set to an array that will enable http authentication only for the - # given strategies, for example, `config.http_authenticatable = [:database]` will - # enable it only for database authentication. The supported strategies are: - # :database = Support basic authentication with authentication key + password - # config.http_authenticatable = false - - # If 401 status code should be returned for AJAX requests. True by default. - # config.http_authenticatable_on_xhr = true - - # The realm used in Http Basic Authentication. 'Application' by default. - # config.http_authentication_realm = 'Application' - - # It will change confirmation, password recovery and other workflows - # to behave the same regardless if the e-mail provided was right or wrong. - # Does not affect registerable. - # config.paranoid = true - - # By default Devise will store the user in session. You can skip storage for - # particular strategies by setting this option. - # Notice that if you are skipping storage for all authentication paths, you - # may want to disable generating routes to Devise's sessions controller by - # passing skip: :sessions to `devise_for` in your config/routes.rb - config.skip_session_storage = [:http_auth] - - # By default, Devise cleans up the CSRF token on authentication to - # avoid CSRF token fixation attacks. This means that, when using AJAX - # requests for sign in and sign up, you need to get a new CSRF token - # from the server. You can disable this option at your own risk. - # config.clean_up_csrf_token_on_authentication = true - - # ==> Configuration for :database_authenticatable - # For bcrypt, this is the cost for hashing the password and defaults to 10. If - # using other encryptors, it sets how many times you want the password re-encrypted. - # - # Limiting the stretches to just one in testing will increase the performance of - # your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use - # a value less than 10 in other environments. Note that, for bcrypt (the default - # encryptor), the cost increases exponentially with the number of stretches (e.g. - # a value of 20 is already extremely slow: approx. 60 seconds for 1 calculation). - config.stretches = Rails.env.test? ? 1 : 10 - - # Setup a pepper to generate the encrypted password. - config.pepper = 'fce14df8477896bd9cc8ea3724d97270a5f19cb6544173d17b7e148cf360bf16449d96318275bfb3efde7b3b377db06cede2b64efb0a6d07dd02dd5076f639c9' - - # Send a notification email when the user's password is changed - # config.send_password_change_notification = false - - # ==> Configuration for :confirmable - # A period that the user is allowed to access the website even without - # confirming their account. For instance, if set to 2.days, the user will be - # able to access the website for two days without confirming their account, - # access will be blocked just in the third day. Default is 0.days, meaning - # the user cannot access the website without confirming their account. - # config.allow_unconfirmed_access_for = 2.days - - # A period that the user is allowed to confirm their account before their - # token becomes invalid. For example, if set to 3.days, the user can confirm - # their account within 3 days after the mail was sent, but on the fourth day - # their account can't be confirmed with the token any more. - # Default is nil, meaning there is no restriction on how long a user can take - # before confirming their account. - # config.confirm_within = 3.days - - # If true, requires any email changes to be confirmed (exactly the same way as - # initial account confirmation) to be applied. Requires additional unconfirmed_email - # db field (see migrations). Until confirmed, new email is stored in - # unconfirmed_email column, and copied to email column on successful confirmation. - config.reconfirmable = false - - # Defines which key will be used when confirming an account - # config.confirmation_keys = [:email] - - # ==> Configuration for :rememberable - # The time the user will be remembered without asking for credentials again. - # config.remember_for = 2.weeks - - # Invalidates all the remember me tokens when the user signs out. - config.expire_all_remember_me_on_sign_out = true - - # If true, extends the user's remember period when remembered via cookie. - # config.extend_remember_period = false - - # Options to be passed to the created cookie. For instance, you can set - # secure: true in order to force SSL only cookies. - # config.rememberable_options = {} - - # ==> Configuration for :validatable - # Range for password length. - config.password_length = 8..72 - - # Email regex used to validate email formats. It simply asserts that - # one (and only one) @ exists in the given string. This is mainly - # to give user feedback and not to assert the e-mail validity. - # config.email_regexp = /\A[^@]+@[^@]+\z/ - - # ==> Configuration for :timeoutable - # The time you want to timeout the user session without activity. After this - # time the user will be asked for credentials again. Default is 30 minutes. - config.timeout_in = 1.minutes - - # ==> Configuration for :lockable - # Defines which strategy will be used to lock an account. - # :failed_attempts = Locks an account after a number of failed attempts to sign in. - # :none = No lock strategy. You should handle locking by yourself. - # config.lock_strategy = :failed_attempts - - # Defines which key will be used when locking and unlocking an account - # config.unlock_keys = [:email] - - # Defines which strategy will be used to unlock an account. - # :email = Sends an unlock link to the user email - # :time = Re-enables login after a certain amount of time (see :unlock_in below) - # :both = Enables both strategies - # :none = No unlock strategy. You should handle unlocking by yourself. - # config.unlock_strategy = :both - - # Number of authentication tries before locking an account if lock_strategy - # is failed attempts. - # config.maximum_attempts = 20 - - # Time interval to unlock the account if :time is enabled as unlock_strategy. - # config.unlock_in = 1.hour - - # Warn on the last attempt before the account is locked. - # config.last_attempt_warning = true - - # ==> Configuration for :recoverable - # - # Defines which key will be used when recovering the password for an account - # config.reset_password_keys = [:email] - - # Time interval you can reset your password with a reset password key. - # Don't put a too small interval or your users won't have the time to - # change their passwords. - config.reset_password_within = 6.hours - - # When set to false, does not sign a user in automatically after their password is - # reset. Defaults to true, so a user is signed in automatically after a reset. - # config.sign_in_after_reset_password = true - - # ==> Configuration for :encryptable - # Allow you to use another encryption algorithm besides bcrypt (default). You can use - # :sha1, :sha512 or encryptors from others authentication tools as :clearance_sha1, - # :authlogic_sha512 (then you should set stretches above to 20 for default behavior) - # and :restful_authentication_sha1 (then you should set stretches to 10, and copy - # REST_AUTH_SITE_KEY to pepper). - # - # Require the `devise-encryptable` gem when using anything other than bcrypt - # config.encryptor = :sha512 - - # ==> Scopes configuration - # Turn scoped views on. Before rendering "sessions/new", it will first check for - # "users/sessions/new". It's turned off by default because it's slower if you - # are using only default views. - # config.scoped_views = false - - # Configure the default scope given to Warden. By default it's the first - # devise role declared in your routes (usually :user). - # config.default_scope = :user - - # Set this configuration to false if you want /users/sign_out to sign out - # only the current scope. By default, Devise signs out all scopes. - # config.sign_out_all_scopes = true - - # ==> Navigation configuration - # Lists the formats that should be treated as navigational. Formats like - # :html, should redirect to the sign in page when the user does not have - # access, but formats like :xml or :json, should return 401. - # - # If you have any extra navigational formats, like :iphone or :mobile, you - # should add them to the navigational formats lists. - # - # The "*/*" below is required to match Internet Explorer requests. - # config.navigational_formats = ['*/*', :html] - - # The default HTTP method used to sign out a resource. Default is :delete. - config.sign_out_via = :delete - - # ==> OmniAuth - # Add a new OmniAuth provider. Check the wiki for more information on setting - # up on your models and hooks. - # config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo' - - # ==> Warden configuration - # If you want to use other strategies, that are not supported by Devise, or - # change the failure app, you can configure them inside the config.warden block. - # - # config.warden do |manager| - # manager.intercept_401 = false - # manager.default_strategies(scope: :user).unshift :some_external_strategy - # end - - # ==> Mountable engine configurations - # When using Devise inside an engine, let's call it `MyEngine`, and this engine - # is mountable, there are some extra configurations to be taken into account. - # The following options are available, assuming the engine is mounted as: - # - # mount MyEngine, at: '/my_engine' - # - # The router that invoked `devise_for`, in the example above, would be: - # config.router_name = :my_engine - # - # When using OmniAuth, Devise cannot automatically set OmniAuth path, - # so you need to do it manually. For the users scope, it would be: - # config.omniauth_path_prefix = '/my_engine/users/auth' - - # Configure the system to redirect to the home page after a session timeout - config.warden do |manager| - manager.failure_app = CustomFailure - end -end diff --git a/config/initializers/devise.rb.example b/config/initializers/devise.rb.example index 17b481e..cce856a 100644 --- a/config/initializers/devise.rb.example +++ b/config/initializers/devise.rb.example @@ -247,7 +247,11 @@ # Add a new OmniAuth provider. Check the wiki for more information on setting # up on your models and hooks. # config.omniauth :github, 'APP_ID', 'APP_SECRET', :scope => 'user,public_repo' - + + # Any entries here MUST match a corresponding entry in the identifier_schemes table as + # well as an identifier_schemes.schemes section in each locale file! + config.omniauth :orcid, 'client_id', 'client_secret', {'scope': '/authenticate'} + # ==> Warden configuration # If you want to use other strategies, that are not supported by Devise, or # change the failure app, you can configure them inside the config.warden block. @@ -269,7 +273,7 @@ # # When using omniauth, Devise cannot automatically set Omniauth path, # so you need to do it manually. For the users scope, it would be: - # config.omniauth_path_prefix = "/my_engine/users/auth" + config.omniauth_path_prefix = "/users/auth" config.warden do |manager| manager.failure_app = CustomFailure diff --git a/config/initializers/wicked_pdf.rb.example b/config/initializers/wicked_pdf.rb.example new file mode 100644 index 0000000..1473351 --- /dev/null +++ b/config/initializers/wicked_pdf.rb.example @@ -0,0 +1,7 @@ +module DMPRoadmap + class Application < Rails::Application + WickedPdf.config = { + :exe_path => '/usr/local/bin/wkhtmltopdf' + } + end +end \ No newline at end of file diff --git a/config/initializers/wicked_pdf_example.rb b/config/initializers/wicked_pdf_example.rb deleted file mode 100644 index 103b3e5..0000000 --- a/config/initializers/wicked_pdf_example.rb +++ /dev/null @@ -1,9 +0,0 @@ -module DMPRoadmap - class Application < Rails::Application - - WickedPdf.config = { - :exe_path => '/usr/local/bin/wkhtmltopdf' - } - - end -end \ No newline at end of file diff --git a/config/locales/de.yml b/config/locales/de.yml index 9c10799..fc7de1a 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -289,6 +289,7 @@ news_label: "Aktuelles" help_label: "Hilfe" contact_label: "Kontakt" + public_plans_label: "Öffentliche DMPs" jisc: "Das DCC wird untertützt von" greeting: "Hallo" @@ -338,8 +339,8 @@ error: "Fehler!" comment: "Kommentar" send: "Senden" - yes: "Ja" - no: "Nein" + 'yes': "Ja" + 'no': "Nein" none: "Keines" title: "Titel" note: "Anmerkung" @@ -511,6 +512,21 @@ project_identifier_help_text: "Eine Identifikationskürzel, wie es von Förderern oder Institutionen vergeben wird." project_static_info: "Dieser Plan basiert auf:" projects_title: "Meine Pläne" + + visibility: "Sichtweite" + visibilities: + labels: + privately_visible: "Private" + organisationally_visible: "Organisatorische" + publicly_visible: "Öffentlichkeit" + is_test: "Test/Übung" + help_texts: + privately_visible: "Private (Besitzer, Miteigentümer und Admins) Siehe unsere Nutzungsbedingungen." + organisationally_visible: "Mit anderen innerhalb Ihrer Organisation" + publicly_visible: "Öffentlich im Internet. Ihr DMP erscheint auf der Public DMPs Seite dieser Seite." + is_test: "Test / Praxis (Ihr Plan ist für andere Benutzer nicht sichtbar) Siehe unsere Nutzungsbedingungen." + not_set: "Nicht angegeben (wird standardmäßig für andere in Ihrer Organisation sichtbar sein)" + project_settings_text: "Die hier ausgewählten Einträge werden in der Tabelle unten angezeigt. Sie können die Daten durch jeden ihrer Tabellenköpfe sortieren oder filtern, indem Sie eine Zeichenkette in der Suchbox eingeben." project_text_when_no_project: "

    Willkommen.
    Sie können nun ihren ersten DMP erstellen.
    Wählen Sie 'Plan erstellen' weiter unten aus, um zu beginnen.

    " project_text_when_project: "

    Die folgende Tabelle listet alle von Ihnen erstellten und von anderen mit Ihnen geteilten Pläne.
    Diese können jederzeit bearbeitet, geteilt, exportiert und gelöscht werden.

    " @@ -577,6 +593,10 @@ data_contact: "Plandatenkontakt" description: "Beschreibung" unknown: " - " + visibility: "Sichtweite" + name: 'Name' + template: 'Vorlage' + organisation: 'Organisation' filter: placeholder: "Filter Pläne" submit: "Filter" @@ -597,6 +617,7 @@ project_description: "Beschreibung" funder: "Geldgeber" institution: "Institution" + orcid: "Ihre ORCID" settings: title: "Einstellungen" @@ -608,6 +629,7 @@ no_name: "'Name' muss in der Liste von Spalten enthalten sein." duplicate: "Doppelter Spaltenname. Bitte jede Spalte nur einmal einfügen." unknown: "Unbekannter Spaltenname." + no_plan: "Der Plan ist unvollständig." plans: title: "Dateiname" reset: "Zurücksetzen" @@ -684,6 +706,23 @@ no_auth_for_endpoint: '{"Error":"You do not have authorisation to view this endpoint"}' bad_resource: '{"Error":"You do not have authorisation to view this resource"}' + identifier_schemes: + connect_success: 'Ihr Konto wurde mit %{scheme}' + connect_failure: 'Wir konnten nicht auf Ihr Konto %{scheme} verbinden' + disconnect_success: 'Ihr Konto wurde von %{scheme} getrennt' + disconnect_failure: 'Wir waren nicht in der Lage, Ihr Konto zu trennen von %{scheme}' + new_login_success: 'Sie haben nicht Setup ein Konto bei uns. Bitte füllen Sie das folgende Informationen, um Ihre Registrierung abzuschließen.' + new_login_failure: 'Wir waren nicht in der Lage, Ihr Konto zu überprüfen. Bitte benutzen Sie das folgende Formular ein neues Konto zu erstellen. Sie können danach Ihr neues Konto zu verknüpfen.' + + schemes: + orcid: + logo: 'http://orcid.org/sites/default/files/images/orcid_16x16.png' + user_landing_page: 'https://orcid.org/%{id}' + connect: 'Erstellen oder Verbinden Sie Ihren ORCID ID' + connect_tooltip: 'ORCID bietet eine persistente digitale Kennung, die Sie von anderen Forschern unterscheidet. Erfahren Sie mehr unter orcid.org' + disconnect_confirmation: 'Sind Sie sicher, dass Sie Ihre ORCID ID trennen möchten?' + disconnect_tooltip: 'Trennen Sie Ihr Konto von ORCID. Sie können jederzeit wieder an.' + magic_strings: organisation_types: funder: 'Funder' @@ -694,6 +733,10 @@ template: 'Template' managing_organisation: 'Digital Curation Centre' user_role_types: + admin: 'admin' + org_admin: 'org_admin' + user: 'user' + roles: super_admin: 'admin' organisational_admin: 'org_admin' user: 'user' @@ -705,7 +748,7 @@ use_api: 'use_api' change_org_details: 'change_org_details' grant_api_to_orgs: 'grant_api_to_orgs' - api_endpoint_types: + token_permission_types: guidances: 'guidances' plans: 'plans' templates: 'templates' diff --git a/config/locales/en-UK.yml b/config/locales/en-UK.yml index 0caef61..db83e6d 100644 --- a/config/locales/en-UK.yml +++ b/config/locales/en-UK.yml @@ -338,11 +338,17 @@ about_us_label: "About" roadmap_label: "Future plans" help_label: "Help" + public_plans_label: "Public DMPs" + contact_label: "Contact" + public_plans_label: "Public DMPs" jisc: "The %{organisation_abbreviation} is funded by" format: "format" change_language: "Change language" + 'yes': 'Yes' + 'no': 'No' + sign_in: "Sign in" sign_out: "Sign out" sign_up: "Sign up" @@ -574,6 +580,21 @@ project_identifier_help_text: "A pertinent ID as determined by the funder and/or institution." project_static_info: "This plan is based on:" projects_title: "My plans" + + visibility: "Visibility" + visibilities: + labels: + privately_visible: "Private" + organisationally_visible: "Organisational" + publicly_visible: "Public" + is_test: "Test/Practice" + help_texts: + privately_visible: "Private (owners, co-owners, and administrators only) See our Terms of Use." + organisationally_visible: "Organisational (visibile to others within your organisation)" + publicly_visible: "Public (Your DMP will appear on the Public DMPs page of this site)" + is_test: "Test/Practice (your plan is not visible to other users) See our Terms of Use." + not_set: "Not specified (will be visible to others within your organisation by default)" + project_settings_text: "The items you select here will be displayed in the table below. You can sort the data by each of these headings or filter by entering a text string in the search box." project_text_when_no_project: "

    Welcome.
    You are now ready to create your first DMP.
    Click the 'Create plan' button below to begin.

    " project_text_when_project: "

    The table below lists the plans that you have created, and any that have been shared with you by others.
    These can be edited, shared, exported or deleted at anytime.

    " @@ -626,6 +647,11 @@ data_contact: "Plan data contact" description: "Description" unknown: " - " + visibility: "Visibility" + name: 'Name' + template: 'Template' + organisation: 'Organization' + filter: placeholder: "Filter plans" submit: "Filter" @@ -657,6 +683,7 @@ project_description: "Plan Description" funder: "Funder" institution: "Institution" + orcid: "Your ORCID" not_valid_format: '%{value}% is not a valid format' settings: @@ -668,6 +695,7 @@ no_name: "'name' must be included in column list." duplicate: "Duplicate column name. Please only include each column once." unknown: "Unknown column name." + no_plan: "The plan is incomplete." plans: title: "File Name" reset: "Reset" @@ -739,6 +767,23 @@ no_auth_for_endpoint: '{"Error":"You do not have authorisation to view this endpoint"}' bad_resource: '{"Error":"You do not have authorisation to view this resource"}' + identifier_schemes: + connect_success: 'Your account has bee connected to %{scheme}' + connect_failure: 'We could not connect your account to %{scheme}' + disconnect_success: 'Your account has been disconnected from %{scheme}' + disconnect_failure: 'We were unable to disconnect your account from %{scheme}' + new_login_success: 'It does not look like you have setup an account with us yet. Please fill in the following information to complete your registration.' + new_login_failure: 'We were unable to verify your account. Please use the following form to create a new account. You will be able to link your new account afterward.' + + schemes: + orcid: + logo: 'http://orcid.org/sites/default/files/images/orcid_16x16.png' + user_landing_page: 'https://orcid.org/%{id}' + connect: 'Create or Connect your ORCID ID' + connect_tooltip: 'ORCID provides a persistent digital identifier that distinguishes you from other researchers. Learn more at orcid.org' + disconnect_confirmation: 'Are you sure you want to disconnect your ORCID ID?' + disconnect_tooltip: 'Disconnect your account from ORCID. You can reconnect at any time.' + magic_strings: organisation_types: funder: 'Funder' @@ -749,6 +794,10 @@ template: 'Template' managing_organisation: 'Digital Curation Centre' user_role_types: + admin: 'admin' + org_admin: 'org_admin' + user: 'user' + roles: super_admin: 'admin' organisational_admin: 'org_admin' user: 'user' @@ -760,7 +809,7 @@ use_api: 'use_api' change_org_details: 'change_org_details' grant_api_to_orgs: 'grant_api_to_orgs' - api_endpoint_types: + token_permission_types: guidances: 'guidances' plans: 'plans' templates: 'templates' diff --git a/config/locales/en-US.yml b/config/locales/en-US.yml index 16de5b7..f3f02ba 100644 --- a/config/locales/en-US.yml +++ b/config/locales/en-US.yml @@ -327,9 +327,13 @@ roadmap_label: "Future plans" help_label: "Help" contact_label: "Contact" + public_plans_label: "Public DMPs" jisc: "The %{organisation_abbreviation} is funded by" format: "format" + 'yes': 'Yes' + 'no': 'No' + sign_in: "Sign in" sign_out: "Sign out" sign_up: "Sign up" @@ -560,6 +564,21 @@ project_identifier_help_text: "A pertinent ID as determined by the funder and/or institution." project_static_info: "This plan is based on:" projects_title: "My plans" + + visibility: "Visibility" + visibilities: + labels: + privately_visible: "Private" + organisationally_visible: "Organizational" + publicly_visible: "Public" + is_test: "Test/Practice" + help_texts: + privately_visible: "Private (owners, co-owners, and administrators only) See our Terms of Use." + organisationally_visible: "Organizational (visibile to others within your organization)" + publicly_visible: "Public (Your DMP will appear on the Public DMPs page of this site)" + is_test: "Test/Practice (your plan is not visible to other users) See our Terms of Use." + not_set: "Not specified (will be visible to others within your organization by default)" + project_settings_text: "The items you select here will be displayed in the table below. You can sort the data by each of these headings or filter by entering a text string in the search box." project_text_when_no_project: "

    Welcome.
    You are now ready to create your first DMP.
    Click the 'Create plan' button below to begin.

    " project_text_when_project: "

    The table below lists the plans that you have created, and any that have been shared with you by others.
    These can be edited, shared, exported or deleted at anytime.

    " @@ -612,6 +631,10 @@ data_contact: "Plan data contact" description: "Description" unknown: " - " + visibility: "Visibility" + name: 'Name' + template: 'Template' + organisation: 'Organization' filter: placeholder: "Filter plans" submit: "Filter" @@ -643,6 +666,7 @@ project_description: "Description" funder: "Funder" institution: "Institution" + orcid: "Your ORCID" not_valid_format: '%{value}% is not a valid format' settings: @@ -654,6 +678,7 @@ no_name: "'name' must be included in column list." duplicate: "Duplicate column name. Please only include each column once." unknown: "Unknown column name." + no_plan: "The plan is incomplete." plans: title: "File Name" reset: "Reset" @@ -725,6 +750,23 @@ no_auth_for_endpoint: '{"Error":"You do not have authorisation to view this endpoint"}' bad_resource: '{"Error":"You do not have authorisation to view this resource"}' + identifier_schemes: + connect_success: 'Your account has bee connected to %{scheme}' + connect_failure: 'We could not connect your account to %{scheme}' + disconnect_success: 'Your account has been disconnected from %{scheme}' + disconnect_failure: 'We were unable to disconnect your account from %{scheme}' + new_login_success: 'It does not look like you have setup an account with us yet. Please fill in the following information to complete your registration.' + new_login_failure: 'We were unable to verify your account. Please use the following form to create a new account. You will be able to link your new account afterward.' + + schemes: + orcid: + logo: 'http://orcid.org/sites/default/files/images/orcid_16x16.png' + user_landing_page: 'https://orcid.org/%{id}' + connect: 'Create or Connect your ORCID ID' + connect_tooltip: 'ORCID provides a persistent digital identifier that distinguishes you from other researchers. Learn more at orcid.org' + disconnect_confirmation: 'Are you sure you want to disconnect your ORCID ID?' + disconnect_tooltip: 'Disconnect your account from ORCID. You can reconnect at any time.' + magic_strings: organisation_types: funder: 'Funder' @@ -735,6 +777,10 @@ template: 'Template' managing_organisation: 'Digital Curation Centre' user_role_types: + admin: 'admin' + org_admin: 'org_admin' + user: 'user' + roles: super_admin: 'admin' organisational_admin: 'org_admin' user: 'user' @@ -746,7 +792,7 @@ use_api: 'use_api' change_org_details: 'change_org_details' grant_api_to_orgs: 'grant_api_to_orgs' - api_endpoint_types: + token_permission_types: guidances: 'guidances' plans: 'plans' templates: 'templates' diff --git a/config/locales/es.yml b/config/locales/es.yml index 9c288cd..615b0c5 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -280,6 +280,7 @@ roadmap_label: "Hoja de ruta" help_label: "Ayuda" contact_label: "Contacto" + public_plans_label: "DMP Públicos" jisc: "El DCC está financiado por" sign_in: "Conectar" @@ -322,8 +323,8 @@ error: "¡Error!" comment: "Comentario" send: "Enviar" - yes: "Si" - no: "No" + 'yes': "Si" + 'no': "No" none: "Ninguno/a" false_lowercase: "falso" title: "Título" @@ -453,6 +454,21 @@ project_identifier_help_text: "El ID tal como lo determinó la institución u organismo financiador." project_static_info: "Este plan está basado en:" projects_title: "Mis planes" + + visibility: "Visibilidad" + visibilities: + labels: + privately_visible: "Privado" + organisationally_visible: "Organizativo" + publicly_visible: "Público" + is_test: "Prueba/Práctica" + help_texts: + privately_visible: "Privado (propietarios, copropietarios y administradores solamente) Consulte nuestras Condiciones de uso." + organisationally_visible: "Con otros miembros de su organización" + publicly_visible: "Publicamente en la web. Su DMP aparecerá en la página Public DMPs de este sitio." + is_test: "Prueba / Práctica (su plan no es visible para otros usuarios) Vea nuestras Condiciones de uso." + not_set: "No especificado (será visible para otros dentro de su organización de forma predeterminada)" + project_settings_text: "Los items que seleccione se mostarán en la siguiente tabla. Puede ordenar los datos según sus encabezados o filtrar tecleando textos en la caja de búsqueda." project_text_when_no_project: "

    Bienvenido.
    Ya está listo para crear su primer PGD.
    Haga clic en el botón 'Crear un plan' para comenzar.

    " project_text_when_project: "

    La siguiente tabla lista los planes que usted ha creado, así como los que otros investigadores hayan compartido con usted.
    Se pueden editar, compartir, exportar o borrar en cualquier momento.

    " @@ -504,6 +520,10 @@ principal_investigator: "Principal Investigador / Científico" data_contact: "Datos de contacto del plan" description: "Descripción" + visibility: 'Visibilidad' + name: 'Nombre' + template: 'Plantilla' + organisation: 'Organización' filter: placeholder: "Filtro de planes" submit: "Filtrar" @@ -534,6 +554,7 @@ no_name: "'nombre' tiene que estar en la lista de columnas." duplicate: "Nombre de columna duplicado. Por favor, indique cada columna sólo una vez." unknown: "Nombre de columna desconocido." + no_plan: "El plan es incompleto." plans: title: Título del plan reset: "Reiniciar" @@ -789,3 +810,60 @@

    El uso de la herramienta indica que usted entiende y está de acuerdo con estos términos y condiciones.

    " + + api: + bad_credentials: '{"Error":"Bad credentials"}' + org_dosent_exist: '{"Error":"Organization does not exist"}' + org_not_funder: '{"Error":"Organization specified is not a funder"}' + org_multiple_templates: '{"Error":"Organization has more than one template and template name unspecified or invalid"}' + no_auth_for_endpoint: '{"Error":"You do not have authorisation to view this endpoint"}' + bad_resource: '{"Error":"You do not have authorisation to view this resource"}' + + identifier_schemes: + connect_success: 'Tu cuenta se ha conectado a %{scheme}' + connect_failure: 'No pudimos conectar tu cuenta a %{scheme}' + disconnect_success: 'Su cuenta se ha desconectado de %{scheme}' + disconnect_failure: 'No hemos podido desconectar tu cuenta de %{scheme}' + new_login_success: 'No ha configurado una cuenta. Por favor complete su registro.' + new_login_failure: 'No hemos podido verificar tu cuenta. Utilice el siguiente formulario para crear una cuenta nueva. Podrá vincular su nueva cuenta posteriormente.' + + schemes: + orcid: + logo: 'http://orcid.org/sites/default/files/images/orcid_16x16.png' + user_landing_page: 'https://orcid.org/%{id}' + connect: 'Cree o conecte su ID de ORCID ID' + connect_tooltip: 'ORCID proporciona un identificador digital persistente que lo distingue de otros investigadores. Más información en orcid.org' + disconnect_confirmation: '¿Está seguro de que desea desconectar su ORCID ID?' + disconnect_tooltip: 'Desconecte su cuenta de ORCID. Puede volver a conectarse en cualquier momento.' + + magic_strings: + organisation_types: + funder: 'Financiador' + organisation: 'Organización' + project: 'Proyecto' + institution: 'Institución' + research_institute: 'Instituto de Investigación' + template: 'Modelo' + managing_organisation: 'Centro de Cura Digital' + user_role_types: + admin: 'admin' + org_admin: 'org_admin' + user: 'user' + roles: + super_admin: 'admin' + organisational_admin: 'org_admin' + user: 'user' + add_organisations: 'add_organisations' + change_org_affiliation: 'change_org_affiliation' + grant_permissions: 'grant_permissions' + modify_templates: 'modify_templates' + modify_guidance: 'modify_guidance' + use_api: 'use_api' + change_org_details: 'change_org_details' + grant_api_to_orgs: 'grant_api_to_orgs' + token_permission_types: + guidances: 'guidances' + plans: 'plans' + templates: 'templates' + statistics: 'statistics' + languages: diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 5f4e0eb..2dbc142 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -19,7 +19,7 @@ day_names: [dimanche, lundi, mardi, mercredi, jeudi, vendredi, samedi] abbr_day_names: [DIM, LUN, MAR, MER, JEU, VEN, SAM] - # Don't forget the nil at the beginning; there's no such thing as a 0th month + # Dont forget the nil at the beginning; theres no such thing as a 0th month month_names: [~, janvier, février, mars, avril, mai, juin, juillet, août, septembre, octobre, novembre, décembre] abbr_month_names: [~, JAN, FEV, MAR, AVR, MAI, JUN, JUL, AOU, SEP, OCT, NOV, DEC] # Used in date_select and datetime_select. @@ -42,23 +42,23 @@ dmponline3_text: "Version précédente de DMPonline" dcc_name: "Digital Curation Centre" welcome_title: "Bienvenue !" - welcome_text: "

    DMPonline est un développement du Digital Curation Centre (Centre de curation numérique britannique - DCC) pour vous aider dans la rédaction de plans de gestion de données, ou DMP.

    " - screencast_text: "Vidéo en ligne sur l'utilisation de DMPonline" - screencast_error_text: "La balise

    -

    Use of the tool indicates that you understand and agree to these terms and conditions.

    " \ No newline at end of file +

    Use of the tool indicates that you understand and agree to these terms and conditions.

    " + + public_plans_page: + title: "Public DMPs" + body_text_html: "Public DMPs are plans created using the DMPTool and shared publicly by their owners. They are not vetted for quality, completeness, or adherence to funder guidelines." + no_plans_body_text_html: "There are no public DMPs." \ No newline at end of file diff --git a/config/locales/static_pages/en-US.static.yml.example b/config/locales/static_pages/en-US.static.yml.example index ed79687..3f9f003 100644 --- a/config/locales/static_pages/en-US.static.yml.example +++ b/config/locales/static_pages/en-US.static.yml.example @@ -126,15 +126,15 @@ intro_text_html: "

    %{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 enter your query in the form below or email dmponline@dcc.ac.uk.

    " github_text_html: "

    If you have a feature request or think you have found a bug, please check out the list of issues on GitHub. If your issue isn't listed there, please add it; if it is, please add a comment if you have more information or just to let us know how important it is to you. This will help us to prioritise future developments.

    " address_text_html: " -

    Tel. +44 (0) 131 651 1239

    -

    Email dmponline@dcc.ac.uk

    " +
  • %{organisation_name}
  • +
  • %{organisation_address_line1}
  • +
  • %{organisation_address_line2}
  • +
  • %{organisation_address_line3}
  • +
  • %{organisation_address_line4}
  • +
  • %{organisation_address_country}
  • + +

    CDL Helpline: %{organisation_telephone}

    +

    Email %{organisation_email}

    " roadmap_page: title: "Future plans" @@ -215,3 +215,8 @@

    Use of the tool indicates that you understand and agree to these terms and conditions.

    " + + public_plans_page: + title: "Public DMPs" + body_text_html: "Public DMPs are plans created using the DMPTool and shared publicly by their owners. They are not vetted for quality, completeness, or adherence to funder guidelines." + no_plans_body_text_html: "There are no public DMPs." \ No newline at end of file diff --git a/config/locales/static_pages/fr.static.yml.example b/config/locales/static_pages/fr.static.yml.example index 3bf7021..b48a7c2 100644 --- a/config/locales/static_pages/fr.static.yml.example +++ b/config/locales/static_pages/fr.static.yml.example @@ -114,7 +114,17 @@ title: "Communiquez avec nous" intro_text_html: "

    L'Assistant PGD est rendu disponible par les Bibliothèques de l'Université d'Alberta. Pour en savoir plus sur les services offerts par ces bibliothèques, consulter la page suivante : Research Data Management page. Si vous désirez communiquer avec nous concernant l'Assistant PGD, merci de saisir votre message dans le formulaire Web ci-dessous ou nous écrire à portage@carl-abrc.ca.

    Nous joindre

    " - + address_text_html: " +

    CDL Helpline: %{organisation_telephone}

    +

    Email %{organisation_email}

    " + terms_page: title: "Exploitation sous licence et conditions d'utilisation" body_text_html: " @@ -145,4 +155,9 @@
    -

    En utilisant l'outil, vous comprenez et acceptez ces conditions.

    " \ No newline at end of file +

    En utilisant l'outil, vous comprenez et acceptez ces conditions.

    " + + public_plans_page: + title: "DMP publics" + no_plans_body_text_html: "Aucun DMP n'a été rendu public." + body_text_html: "Les DMP publics sont des plans créés à l'aide de DMPTool et partagés publiquement par leurs propriétaires. Ils ne sont pas vérifiés pour la qualité, l'exhaustivité ou l'adhésion aux lignes directrices des bailleurs de fonds." diff --git a/config/routes.rb b/config/routes.rb index 8e6d1d0..8c35cc8 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,18 +1,28 @@ Rails.application.routes.draw do - devise_for :users, :controllers => {:registrations => "registrations", :confirmations => 'confirmations', :passwords => 'passwords', :sessions => 'sessions', :omniauth_callbacks => 'users/omniauth_callbacks'} do + devise_for :users, controllers: { + registrations: "registrations", + confirmations: 'confirmations', + passwords: 'passwords', + sessions: 'sessions', + omniauth_callbacks: 'users/omniauth_callbacks'} do + get "/users/sign_out", :to => "devise/sessions#destroy" end - + # WAYFless access point - use query param idp get 'auth/shibboleth' => 'users/omniauth_shibboleth_request#redirect', :as => 'user_omniauth_shibboleth' get 'auth/shibboleth/assoc' => 'users/omniauth_shibboleth_request#associate', :as => 'user_shibboleth_assoc' + #post '/auth/:provider/callback' => 'sessions#oauth_create' + # fix for activeadmin signout bug devise_scope :user do get '/users/sign_out' => 'devise/sessions#destroy' end + delete '/users/identifiers/:id', to: 'user_identifiers#destroy', as: 'destroy_user_identifier' + #ActiveAdmin.routes(self) #organisation admin area @@ -36,6 +46,9 @@ get "help" => 'static_pages#help' get "roadmap" => 'static_pages#roadmap' get "terms" => 'static_pages#termsuse' + get "public_plans" => 'static_pages#public_plans' + get "public_export/:id" => 'static_pages#public_export', as: 'public_export' + get "existing_users" => 'existing_users#index' #post 'contact_form' => 'contacts', as: 'localized_contact_creation' diff --git a/db/migrate/20130708092900_devise_create_admin_users.rb b/db/migrate/20130708092900_devise_create_admin_users.rb index ac03c44..b386cea 100644 --- a/db/migrate/20130708092900_devise_create_admin_users.rb +++ b/db/migrate/20130708092900_devise_create_admin_users.rb @@ -44,8 +44,8 @@ t.timestamps end - add_index :admin_users, :email, :unique => true - add_index :admin_users, :reset_password_token, :unique => true + # +add_index+ :admin_users, :email, :unique => true + # add_index :admin_users, :reset_password_token, :unique => true # add_index :admin_users, :confirmation_token, :unique => true # add_index :admin_users, :unlock_token, :unique => true # add_index :admin_users, :authentication_token, :unique => true diff --git a/db/migrate/20131118094629_change_versions_published.rb b/db/migrate/20131118094629_change_versions_published.rb index dc8deb4..6f05c55 100644 --- a/db/migrate/20131118094629_change_versions_published.rb +++ b/db/migrate/20131118094629_change_versions_published.rb @@ -1,5 +1,18 @@ class ChangeVersionsPublished < ActiveRecord::Migration def change - change_column :versions, :published, :boolean + add_column :versions, :published_tmp, :boolean + + # Since we ultimately drop the Version model we must check for it before + # attempting to manipulate data + if table_exists?('versions') + Version.reset_column_information # make the new column available to model methods + Version.all.each do |v| + v.published_tmp = v.published == 't' ? true : false + v.save + end + end + + remove_column :versions, :published + rename_column :versions, :published_tmp, :published end end diff --git a/db/migrate/20150809210811_add_field_to_questions.rb b/db/migrate/20150809210811_add_field_to_questions.rb index a4cc424..95ad8c6 100644 --- a/db/migrate/20150809210811_add_field_to_questions.rb +++ b/db/migrate/20150809210811_add_field_to_questions.rb @@ -1,9 +1,12 @@ class AddFieldToQuestions < ActiveRecord::Migration def change add_column :questions, :option_comment_display, :boolean, :default => true - Question.find_each do |question| - question.option_comment_display = true - question.save! + + if table_exists?('questions') + Question.find_each do |question| + question.option_comment_display = true + question.save! + end end end end diff --git a/db/migrate/20151208142029_add_field_to_guidances.rb b/db/migrate/20151208142029_add_field_to_guidances.rb index e2c792f..a6dbe1c 100644 --- a/db/migrate/20151208142029_add_field_to_guidances.rb +++ b/db/migrate/20151208142029_add_field_to_guidances.rb @@ -1,9 +1,12 @@ class AddFieldToGuidances < ActiveRecord::Migration def change add_column :guidances, :published, :boolean - Guidance.find_each do |guidance| - guidance.published = true - guidance.save! + + if table_exists?('guidances') + Guidance.find_each do |guidance| + guidance.published = true + guidance.save! + end end end end diff --git a/db/migrate/20151208142836_update_field_in_guidance_groups.rb b/db/migrate/20151208142836_update_field_in_guidance_groups.rb index f77f8ed..2062073 100644 --- a/db/migrate/20151208142836_update_field_in_guidance_groups.rb +++ b/db/migrate/20151208142836_update_field_in_guidance_groups.rb @@ -1,8 +1,10 @@ class UpdateFieldInGuidanceGroups < ActiveRecord::Migration def change + if table_exists?('guidance_groups') GuidanceGroup.find_each do |guidance_group| guidance_group.published = true guidance_group.save! end + end end end diff --git a/db/migrate/20161021100420_single_organisation_for_users.rb b/db/migrate/20161021100420_single_organisation_for_users.rb index c7aa3ac..20cceec 100644 --- a/db/migrate/20161021100420_single_organisation_for_users.rb +++ b/db/migrate/20161021100420_single_organisation_for_users.rb @@ -2,16 +2,18 @@ def up unless Rails.env.test? - User.class_eval do - belongs_to :organisation, - :class_name => "Organisation", - :foreign_key => "organisation_id" - end + if table_exists?('users') + User.class_eval do + belongs_to :organisation, + :class_name => "Organisation", + :foreign_key => "organisation_id" + end - User.includes(:user_org_roles, :roles).all.each do | user | - # NOTE: we'll grab the first organisation (if present), so if there are more, these will be lost! - user.organisation_id = user.user_org_roles.first.organisation_id unless user.user_org_roles.empty? - user.save! + User.includes(:user_org_roles, :roles).all.each do | user | + # NOTE: we'll grab the first organisation (if present), so if there are more, these will be lost! + user.organisation_id = user.user_org_roles.first.organisation_id unless user.user_org_roles.empty? + user.save! + end end end diff --git a/db/migrate/20161024163546_create_user_identifier_scheme.rb b/db/migrate/20161024163546_create_user_identifier_scheme.rb new file mode 100644 index 0000000..657d0e5 --- /dev/null +++ b/db/migrate/20161024163546_create_user_identifier_scheme.rb @@ -0,0 +1,10 @@ +class CreateUserIdentifierScheme < ActiveRecord::Migration + def change + create_table :identifier_schemes do |t| + t.string :name + t.string :description + t.boolean :active + t.timestamps + end + end +end \ No newline at end of file diff --git a/db/migrate/20161024163920_create_user_identifiers.rb b/db/migrate/20161024163920_create_user_identifiers.rb new file mode 100644 index 0000000..9a86e89 --- /dev/null +++ b/db/migrate/20161024163920_create_user_identifiers.rb @@ -0,0 +1,11 @@ +class CreateUserIdentifiers < ActiveRecord::Migration + def change + create_table :user_identifiers do |t| + t.string :identifier + t.timestamps + end + + add_reference :user_identifiers, :user, foreign_key: true + add_reference :user_identifiers, :identifier_scheme, foreign_key: true + end +end diff --git a/db/migrate/20161122152339_new_plan_template_structure.rb b/db/migrate/20161122152339_new_plan_template_structure.rb index 5f27f6a..2432dea 100644 --- a/db/migrate/20161122152339_new_plan_template_structure.rb +++ b/db/migrate/20161122152339_new_plan_template_structure.rb @@ -138,138 +138,144 @@ # Then migrate all customised plans # migrate most current template into templates (org facing) proj_number = 0 - # migrating uncustomised plans - Template.transaction do - Project.includes( { dmptemplate: [ { phases: [ { versions: [:sections] } ] } ] }, {plans: [:version ]}, :organisation).find_each(batch_size: 20) do |project| - puts "" - puts "beginning number #{proj_number}" - proj_number +=1 - if project.dmptemplate.nil? # one of the templates dosent exist - next - end - new_plan = initNewPlan(project) # copy data from project to NewPlan object - plans = project.plans # select plans for project - version_ids = [] - versions = [] - plans.each do |plan| # select version ids from plans list - version_ids << plan.version.id - versions << plan.version - end - dmptemplate = project.dmptemplate # select template for project - phases = dmptemplate.phases # select phases for project - temp_match = false # flag for if we found a matching template + + if table_exists?('projects') && table_exists?('templates') && table_exists?('answers') && + table_exists?('comments') && table_exists?('sections') + # migrating uncustomised plans + Template.transaction do + Project.includes( { dmptemplate: [ { phases: [ { versions: [:sections] } ] } ] }, {plans: [:version ]}, :organisation).find_each(batch_size: 20) do |project| + puts "" + puts "beginning number #{proj_number}" + proj_number +=1 + if project.dmptemplate.nil? # one of the templates dosent exist + next + end + new_plan = initNewPlan(project) # copy data from project to NewPlan object + plans = project.plans # select plans for project + version_ids = [] + versions = [] + plans.each do |plan| # select version ids from plans list + version_ids << plan.version.id + versions << plan.version + end + dmptemplate = project.dmptemplate # select template for project + phases = dmptemplate.phases # select phases for project + temp_match = false # flag for if we found a matching template - puts "checking for matching templates for #{dmptemplate.title} customised by #{project.organisation.name}" unless project.organisation.nil? - puts "checking for matching templates for #{dmptemplate.title} uncustomised" unless project.organisation.present? - possible_templates = project.organisation.nil? ? - Template.includes(:new_phases).where(dmptemplate_id: dmptemplate.id, organisation_id: dmptemplate.organisation_id) : - Template.includes(:new_phases).where(dmptemplate_id: dmptemplate.id, organisation_id: project.organisation_id) - possible_templates.find_each do |t| # for templates with same id - # early cut for un-even number of phases - new_phase_versions = t.new_phases.pluck(:vid) - if new_phase_versions.sort == version_ids.sort - temp_match = true # flag that we found match - # we can point the new_plan to this template and init all data - new_plan.template_id = t.id + puts "checking for matching templates for #{dmptemplate.title} customised by #{project.organisation.name}" unless project.organisation.nil? + puts "checking for matching templates for #{dmptemplate.title} uncustomised" unless project.organisation.present? + possible_templates = project.organisation.nil? ? + Template.includes(:new_phases).where(dmptemplate_id: dmptemplate.id, organisation_id: dmptemplate.organisation_id) : + Template.includes(:new_phases).where(dmptemplate_id: dmptemplate.id, organisation_id: project.organisation_id) + possible_templates.find_each do |t| # for templates with same id + # early cut for un-even number of phases + new_phase_versions = t.new_phases.pluck(:vid) + if new_phase_versions.sort == version_ids.sort + temp_match = true # flag that we found match + # we can point the new_plan to this template and init all data + new_plan.template_id = t.id + new_plan.save! + puts "found a match: #{t.title} version #{t.version}" + break + end + end + + + # this section handles for customisations + unless temp_match # no matches found, init template & phase & sections & questions & themes & options + puts "creating new template for #{dmptemplate.title}" unless project.organisation.present? + puts "creating new template for #{dmptemplate.title} customised by #{project.organisation.name}" unless project.organisation.nil? + modifiable = project.organisation.nil? || project.organisation_id == dmptemplate.organisation_id + template = initTemplate(dmptemplate, modifiable, project.organisation_id) # needs to select next version of temp based on old_temp_id + # some differences between a customised and un-customised template + # customised templates need a different organisation_id + template.organisation_id = project.organisation_id unless project.organisation_id.nil? # updated to not overwrite with nil + # customised templates follow different version rules + template.save! + # since template was not a match, need to gen/copy all data below the template level + versions.each do |version| + new_phase = initNewPhase(version.phase, version, template, modifiable) + new_phase.save! + sections = [] + sections += version.sections.where("organisation_id = ? ", dmptemplate.organisation_id).pluck(:id) + unless project.organisation_id.nil? + sections += Section.where(organisation_id: project.organisation_id, version_id: version.id).pluck(:id) + end + Section.includes(questions: [:themes, :options, :suggested_answers]).where(id: sections).each do |section| + new_section = initNewSection(section, new_phase, modifiable) + new_section.save! + section.questions.each do |question| + new_question = initNewQuestion(question, new_section, modifiable) + new_question.save! + question.themes.each do |theme| + new_question.themes << theme + end + question.options.each do |option| + question_option = initQuestionOption(option, new_question) + question_option.save! + end + question.suggested_answers.each do |suggested_answer| + new_suggested_answer = initNewSuggestedAnswers(suggested_answer, new_question) + new_suggested_answer.save! + end + end + end + end + new_plan.template_id = template.id new_plan.save! - puts "found a match: #{t.title} version #{t.version}" - break end - end - - # this section handles for customisations - unless temp_match # no matches found, init template & phase & sections & questions & themes & options - puts "creating new template for #{dmptemplate.title}" unless project.organisation.present? - puts "creating new template for #{dmptemplate.title} customised by #{project.organisation.name}" unless project.organisation.nil? - template = initTemplate(dmptemplate) # needs to select next version of temp based on old_temp_id - # some differences between a customised and un-customised template - # customised templates need a different organisation_id - template.organisation_id = project.organisation_id - # customised templates follow different version rules - template.save! - # since template was not a match, need to gen/copy all data below the template level - versions.each do |version| - new_phase = initNewPhase(version.phase, version, template, true) - new_phase.save! - sections = [] - sections += version.sections.where("organisation_id = ? ", dmptemplate.organisation_id).pluck(:id) - unless project.organisation_id.nil? - sections += Section.where(organisation_id: project.organisation_id, version_id: version.id).pluck(:id) + # up to this point, we have either found a matching template and pointed the + # new_plan obj at it, or we have generated a new: + # template/phases/sections/questions/question_options/question_themes + # now need to init answers, notes, answers_options + #new_plan.template.new_phases.each do |new_phase| + puts "transfering plan data" + project.project_groups.each do |group| + role = initRole(group, new_plan) + role.save! + end + template = Template.includes(new_phases: {new_sections: :new_questions}).find(new_plan.template_id) + template.new_phases.each do |new_phase| + old_plan = project.plans.where(version_id: new_phase.vid).first + puts "old plan id: #{old_plan.id}" + puts "plan ids :#{plans.pluck(:id)}" + if old_plan.id == 46 + puts "IT'S NOT WORKING RITE HERE!!!!!!!!!!!!!!!!!!!!!!! IT'S NOT WORKING RITE HERE!!!!!!!!!!!!!!!!!!!!!!! IT'S NOT WORKING RITE HERE!!!!!!!!!!!!!!!!!!!!!!!" end - Section.includes(questions: [:themes, :options, :suggested_answers]).where(id: sections).each do |section| - new_section = initNewSection(section, new_phase, true) - new_section.save! - section.questions.each do |question| - new_question = initNewQuestion(question, new_section, true) - new_question.save! - question.themes.each do |theme| - new_question.themes << theme + new_phase.new_sections.each do |new_section| + new_section.new_questions.each do |new_question| + # init new answer + old_ans = Answer.where(question_id: new_question.question_id, plan_id: old_plan.id).order("created_at DESC").first + # init comments on answer + new_ans = nil + comments = Comment.where(question_id: new_question.question_id, plan_id: old_plan.id) + # unless there is no old answer, and no comments, create an answer + unless old_ans.nil? && comments.length < 1 + new_ans = initNewAnswer(old_ans, new_plan, new_question) + new_ans.save! end - question.options.each do |option| - question_option = initQuestionOption(option, new_question) - question_option.save! + comments.find_each do |comment| + note = initNote(comment, new_ans) + note.save! end - question.suggested_answers.each do |suggested_answer| - new_suggested_answer = initNewSuggestedAnswers(suggested_answer, new_question) - new_suggested_answer.save! + if new_ans.present? && new_ans.text.present? && new_ans.text.include?("test2") + puts "!!!!!!!!!!!!!!!!DEBUG MODE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + puts "old answer: #{old_ans.text}" + puts "old answer: #{old_ans.id}" + puts "new answer: #{new_ans.text}" + puts "old plans: #{project.plans.pluck(:id)}" + puts "old_plan: #{old_plan.id}" + puts "old project: #{project.id}" + puts "question: #{new_question.question_id}" + puts "old user: #{old_ans.user.email}" end end end end - new_plan.template_id = template.id - new_plan.save! - end - - # up to this point, we have either found a matching template and pointed the - # new_plan obj at it, or we have generated a new: - # template/phases/sections/questions/question_options/question_themes - # now need to init answers, notes, answers_options - #new_plan.template.new_phases.each do |new_phase| - puts "transfering plan data" - project.project_groups.each do |group| - role = initRole(group, new_plan) - role.save! - end - template = Template.includes(new_phases: {new_sections: :new_questions}).find(new_plan.template_id) - template.new_phases.each do |new_phase| - old_plan = project.plans.where(version_id: new_phase.vid).first - puts "old plan id: #{old_plan.id}" - puts "plan ids :#{plans.pluck(:id)}" - if old_plan.id == 46 - puts "IT'S NOT WORKING RITE HERE!!!!!!!!!!!!!!!!!!!!!!! IT'S NOT WORKING RITE HERE!!!!!!!!!!!!!!!!!!!!!!! IT'S NOT WORKING RITE HERE!!!!!!!!!!!!!!!!!!!!!!!" - end - new_phase.new_sections.each do |new_section| - new_section.new_questions.each do |new_question| - # init new answer - old_ans = Answer.where(question_id: new_question.question_id, plan_id: old_plan.id).order("created_at DESC").first - # init comments on answer - new_ans = nil - comments = Comment.where(question_id: new_question.question_id, plan_id: old_plan.id) - # unless there is no old answer, and no comments, create an answer - unless old_ans.nil? && comments.length < 1 - new_ans = initNewAnswer(old_ans, new_plan, new_question) - new_ans.save! - end - comments.find_each do |comment| - note = initNote(comment, new_ans) - note.save! - end - if new_ans.present? && new_ans.text.present? && new_ans.text.include?("test2") - puts "!!!!!!!!!!!!!!!!DEBUG MODE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" - puts "old answer: #{old_ans.text}" - puts "old answer: #{old_ans.id}" - puts "new answer: #{new_ans.text}" - puts "old plans: #{project.plans.pluck(:id)}" - puts "old_plan: #{old_plan.id}" - puts "old project: #{project.id}" - puts "question: #{new_question.question_id}" - puts "old user: #{old_ans.user.email}" - end - end - end end end + end # indexes on join tables at the end @@ -303,23 +309,32 @@ -def initTemplate(dmptemp) - template = Template.new - template.title = dmptemp.title - template.description = dmptemp.description - template.published = dmptemp.published - template.organisation_id = dmptemp.organisation_id - template.locale = dmptemp.locale - template.is_default = dmptemp.is_default - template.created_at = dmptemp.created_at - template.updated_at = dmptemp.updated_at - template.visibility = 0 # dummy value for private - template.customization_of = nil - template.version = Template.where(dmptemplate_id: dmptemp.id).blank? ? - 0 : Template.where(dmptemplate_id: dmptemp.id).pluck(:version).max + 1 - puts "NEW TEMPLATE: \n title: #{template.title} \n version: #{template.version} \n others_present? #{Template.where(dmptemplate_id: dmptemp.id).count}" - template.dmptemplate_id = dmptemp.id - return template +def initTemplate(dmptemp, modifiable, organisation_id) + if table_exists?('templates') + template = Template.new + template.title = dmptemp.title + template.description = dmptemp.description + template.published = dmptemp.published + template.organisation_id = organisation_id.present? ? organisation_id : dmptemp.organisation_id + template.locale = dmptemp.locale + template.is_default = dmptemp.is_default + template.created_at = dmptemp.created_at + template.updated_at = dmptemp.updated_at + template.visibility = 0 # dummy value for private + template.customization_of = modifiable ? nil : dmptemp.id + template.dmptemplate_id = dmptemp.id + # if no templates with the same dmptemplate_id and organisation_id exist + # 0 + # otherwise + # take the maximum version from templates with the same dmptemplate_id and organisation_id and add 1 + template.version = Template.where(dmptemplate_id: dmptemp.id, organisation_id: template.organisation_id).blank? ? + 0 : Template.where(dmptemplate_id: dmptemp.id, organisation_id: template.organisation_id).pluck(:version).max + 1 + puts "NEW TEMPLATE: \n title: #{template.title} \n version: #{template.version} \n others_present? #{Template.where(dmptemplate_id: dmptemp.id).count}" + return template + + else + return nil + end end def initNewPhase(phase, version, temp, modifiable) @@ -354,8 +369,10 @@ new_question.text = question.text new_question.default_value = question.default_value new_question.guidance = question.guidance.nil? ? "" : question.guidance - Guidance.where(question_id: question.id).each do |guidance| - new_question.guidance += guidance.text + if table_exists?('guidances') + Guidance.where(question_id: question.id).each do |guidance| + new_question.guidance += guidance.text + end end new_question.number = question.number new_question.new_section_id = new_section.id @@ -378,35 +395,45 @@ new_answer.created_at = answer.created_at new_answer.updated_at = answer.updated_at # not sure if these get saved properly as new_answer has no id yet - answer.options.each do |option| - new_answer.question_options << QuestionOption.find_by(option_id: option.id) + if table_exists?('question_options') + answer.options.each do |option| + new_answer.question_options << QuestionOption.find_by(option_id: option.id) + end end end return new_answer end def initQuestionOption(option, new_question) - question_option = QuestionOption.new - question_option.new_question_id = new_question.id - question_option.option_id = option.id - question_option.text = option.text - question_option.number = option.number - question_option.is_default = option.is_default - question_option.created_at = option.created_at - question_option.updated_at = option.updated_at - return question_option + if table_exists?('question_options') + question_option = QuestionOption.new + question_option.new_question_id = new_question.id + question_option.option_id = option.id + question_option.text = option.text + question_option.number = option.number + question_option.is_default = option.is_default + question_option.created_at = option.created_at + question_option.updated_at = option.updated_at + return question_option + else + return nil + end end def initNote(comment, new_answer) - note = Note.new - note.user_id = comment.user_id - note.text = comment.text - note.archived = comment.archived - note.archived_by = comment.archived_by - note.new_answer_id = new_answer.id - note.created_at = comment.created_at - note.updated_at = comment.updated_at - return note + if table_exists?('notes') + note = Note.new + note.user_id = comment.user_id + note.text = comment.text + note.archived = comment.archived + note.archived_by = comment.archived_by + note.new_answer_id = new_answer.id + note.created_at = comment.created_at + note.updated_at = comment.updated_at + return note + else + return nil + end end def initNewPlan(project) @@ -438,13 +465,17 @@ end def initRole(project_group, new_plan) - role = Role.new - role.creator = project_group.project_creator - role.administrator = project_group.project_administrator - role.editor = project_group.project_editor - role.created_at = project_group.created_at - role.updated_at = project_group.updated_at - role.user_id = project_group.user_id - role.new_plan_id = new_plan.id - return role -end \ No newline at end of file + if table_exists?('roles') + role = Role.new + role.creator = project_group.project_creator + role.administrator = project_group.project_administrator + role.editor = project_group.project_editor + role.created_at = project_group.created_at + role.updated_at = project_group.updated_at + role.user_id = project_group.user_id + role.new_plan_id = new_plan.id + return role + else + return nil + end +end diff --git a/db/migrate/20161205095624_replacing_organisation_types_with_bitflags.rb b/db/migrate/20161205095624_replacing_organisation_types_with_bitflags.rb index 16be879..0ebed56 100644 --- a/db/migrate/20161205095624_replacing_organisation_types_with_bitflags.rb +++ b/db/migrate/20161205095624_replacing_organisation_types_with_bitflags.rb @@ -12,26 +12,30 @@ # t.boolean :School # t.boolean :Project end - # migrate old org_type data to bitfield - Org.includes(:organisation_type).all.each do |org| - unless org.organisation_type.nil? - case org.organisation_type.name - when "Organisation" - org.organisation = true - when "Funder" - org.funder = true - when "Project" - org.project = true - when "School" - org.school = true - when "Institution" - org.institution = true - when "Research Institute" - org.research_institute = true + + if table_exists?('orgs') + # migrate old org_type data to bitfield + Org.includes(:organisation_type).all.each do |org| + unless org.organisation_type.nil? + case org.organisation_type.name + when "Organisation" + org.organisation = true + when "Funder" + org.funder = true + when "Project" + org.project = true + when "School" + org.school = true + when "Institution" + org.institution = true + when "Research Institute" + org.research_institute = true + end + org.save! end - org.save! end end + # remove organisation_type_id field from orgs remove_column :orgs, :organisation_type_id # remove organisation_type table diff --git a/db/migrate/20161205095625_replacing_plan_roles_with_bitflags.rb b/db/migrate/20161205095625_replacing_plan_roles_with_bitflags.rb index fa9d143..859586c 100644 --- a/db/migrate/20161205095625_replacing_plan_roles_with_bitflags.rb +++ b/db/migrate/20161205095625_replacing_plan_roles_with_bitflags.rb @@ -6,19 +6,23 @@ rename_column :roles, :creator, :create rename_column :roles, :editor, :edit rename_column :roles, :administrator, :admin + # transfer the data from the other fields to the bitfield - Role.find_each do |role| - if role.admin - role.administrator = true + if table_exists?('roles') + Role.find_each do |role| + if role.admin + role.administrator = true + end + if role.edit + role.editor = true + end + if role.create + role.creator = true + end + role.save! end - if role.edit - role.editor = true - end - if role.create - role.creator = true - end - role.save! end + # remove the other columns remove_column :roles, :create remove_column :roles, :edit diff --git a/db/migrate/20161206122926_add_foreign_keys.rb b/db/migrate/20161206122926_add_foreign_keys.rb index 2eba3c6..7574279 100644 --- a/db/migrate/20161206122926_add_foreign_keys.rb +++ b/db/migrate/20161206122926_add_foreign_keys.rb @@ -83,79 +83,91 @@ def scrub_references # answers i = 0 - Answer.includes(:user, :plan, :question).find_each do |ans| - if ans.user.nil? && ans.user_id.present? - ans.user_id = nil - i += 1 + if table_exists?('answers') + Answer.includes(:user, :plan, :question).find_each do |ans| + if ans.user.nil? && ans.user_id.present? + ans.user_id = nil + i += 1 + end + if ans.plan.nil? && ans.plan_id.present? + ans.plan_id = nil + i += 1 + end + if ans.question.nil? && ans.question_id.present? + ans.question_id = nil + i += 1 + end + ans.save! end - if ans.plan.nil? && ans.plan_id.present? - ans.plan_id = nil - i += 1 - end - if ans.question.nil? && ans.question_id.present? - ans.question_id = nil - i += 1 - end - ans.save! end puts "#{i} answers scrubbed" # notes i = 0 - Note.includes(:answer, :user).find_each do |note| - if note.answer.nil? && note.answer_id.present? - note.answer_id = nil - i += 1 + if table_exists?('notes') + Note.includes(:answer, :user).find_each do |note| + if note.answer.nil? && note.answer_id.present? + note.answer_id = nil + i += 1 + end + if note.user.nil? && note.user_id.present? + note.user_id = nil + i += 1 + end + note.save! end - if note.user.nil? && note.user_id.present? - note.user_id = nil - i += 1 - end - note.save! end puts "#{i} notes scrubbed" # templates i = 0 - Template.includes(:org).find_each do |temp| - if temp.org.nil? && temp.org_id.present? - temp.org_id = nil - i += 1 + if table_exists?('templates') + Template.includes(:org).find_each do |temp| + if temp.org.nil? && temp.org_id.present? + temp.org_id = nil + i += 1 + end + temp.save! end - temp.save! end puts "#{i} templates scrubbed" # guidance_groups # i = 0 - # GuidanceGroup.includes(:org).find_each do |gg| - # if gg.org.nil? && gg.org_id.present? - # gg.org_id = nil - # i += 1 + # if table_exists?('guidance_groups') + # GuidanceGroup.includes(:org).find_each do |gg| + # if gg.org.nil? && gg.org_id.present? + # gg.org_id = nil + # i += 1 + # end + # gg.save! # end - # gg.save! # end # puts "#{i} guidance groups scrubbed" # # question_options # i = 0 - # QuestionOption.includes(:question).find_each do |opt| - # if opt.question.nil? && opt.question_id.present? - # opt.question_id = nil - # i += 1 + # if table_exists?('question_options') + # QuestionOption.includes(:question).find_each do |opt| + # if opt.question.nil? && opt.question_id.present? + # opt.question_id = nil + # i += 1 + # end + # opt.save! # end - # opt.save! # end # puts "#{i} question_options scrubbed" # # orgs # i = 0 - # Org.includes( :language).find_each do |org| - # if org.language.nil? && org.language_id.present? - # org.language_id = nil - # i += 1 + # if table_exists?('orgs') + # Org.includes( :language).find_each do |org| + # if org.language.nil? && org.language_id.present? + # org.language_id = nil + # i += 1 + # end + # org.save! # end - # org.save! # end # puts "#{i} orgs scrubbed" @@ -167,15 +179,17 @@ # roles i = 0 - Role.includes(:user, :plan).find_each do |role| - if role.user.nil? && role.user_id.present? - Role.delete_all(user_id: role.user_id) - i += 1 - next - end - if role.plan.nil? && role.plan_id.present? - Role.delete_all(plan_id: role.plan_id) - i += 1 + if table_exists?('roles') + Role.includes(:user, :plan).find_each do |role| + if role.user.nil? && role.user_id.present? + Role.delete_all(user_id: role.user_id) + i += 1 + next + end + if role.plan.nil? && role.plan_id.present? + Role.delete_all(plan_id: role.plan_id) + i += 1 + end end end puts "#{i} roles scrubbed" @@ -186,17 +200,19 @@ # # suggested_answers # i = 0 - # SuggestedAnswer.includes(:org, :question).find_each do |sa| - # if sa.org.nil? && sa.org_id.present? - # sa.org_id = nil - # i += 1 + # if table_exists?('suggested_answers') + # SuggestedAnswer.includes(:org, :question).find_each do |sa| + # if sa.org.nil? && sa.org_id.present? + # sa.org_id = nil + # i += 1 + # end + # if sa.question.nil? + # sa.delete! + # i += 1 + # next + # end + # sa.save! # end - # if sa.question.nil? - # sa.delete! - # i += 1 - # next - # end - # sa.save! # end # puts "#{i} suggested answers scrubbed" @@ -204,23 +220,27 @@ # # users # i = 0 - # User.includes(:org, :language).find_each do |u| - # if u.org.nil? && u.org_id.present? - # u.org_id = nil - # i += 1 + # if table_exists?('users') + # User.includes(:org, :language).find_each do |u| + # if u.org.nil? && u.org_id.present? + # u.org_id = nil + # i += 1 + # end + # if u.language.nil? && u.language_id.present? + # u.language_id = nil + # i += 1 + # end + # u.save! # end - # if u.language.nil? && u.language_id.present? - # u.language_id = nil - # i += 1 - # end - # u.save! # end # puts "#{i} users scrubbed" # users_perms - UsersPerm.includes(:user).all.each do |u| - if u.user.nil? - UsersPerm.delete_all(user_id: u.user_id) + if table_exists?('users_perms') + UsersPerm.includes(:user).all.each do |u| + if u.user.nil? + UsersPerm.delete_all(user_id: u.user_id) + end end end end diff --git a/db/migrate/20161208122123_single_group_for_guidance.rb b/db/migrate/20161208122123_single_group_for_guidance.rb index 4c02f86..562673c 100644 --- a/db/migrate/20161208122123_single_group_for_guidance.rb +++ b/db/migrate/20161208122123_single_group_for_guidance.rb @@ -1,16 +1,18 @@ class SingleGroupForGuidance < ActiveRecord::Migration def change unless Rails.env.test? - Guidance.class_eval do - belongs_to :guidance_group, class_name: "GuidanceGroup", foreign_key: "guidance_group_id" - end + if table_exists?('guidances') + Guidance.class_eval do + belongs_to :guidance_group, class_name: "GuidanceGroup", foreign_key: "guidance_group_id" + end - Guidance.includes( :guidance_groups).all.each do |guidance| - guidance.guidance_group_id = guidance.guidance_groups.first.id unless guidance.guidance_groups.empty? - if guidance.guidance_group_id.nil? - guidance.destroy - else - guidance.save! + Guidance.includes( :guidance_groups).all.each do |guidance| + guidance.guidance_group_id = guidance.guidance_groups.first.id unless guidance.guidance_groups.empty? + if guidance.guidance_group_id.nil? + guidance.destroy + else + guidance.save! + end end end end diff --git a/db/migrate/20170124235829_add_visibility_to_plans.rb b/db/migrate/20170124235829_add_visibility_to_plans.rb new file mode 100644 index 0000000..1ba4f54 --- /dev/null +++ b/db/migrate/20170124235829_add_visibility_to_plans.rb @@ -0,0 +1,5 @@ +class AddVisibilityToPlans < ActiveRecord::Migration + def change + add_column :plans, :visibility, :integer, null: false, default: 0 + end +end diff --git a/db/migrate/20170130173049_add_option_based_to_question_formats.rb b/db/migrate/20170130173049_add_option_based_to_question_formats.rb new file mode 100644 index 0000000..936fa3e --- /dev/null +++ b/db/migrate/20170130173049_add_option_based_to_question_formats.rb @@ -0,0 +1,15 @@ +class AddOptionBasedToQuestionFormats < ActiveRecord::Migration + def change + add_column :question_formats, :option_based, :boolean, default: false + + # Set the new field to true for the question formats that have options + if table_exists?('question_formats') + QuestionFormat.all.each do |qf| + unless ['text area', 'text field', 'date'].include?(qf.title.downcase) + qf.option_based = true + qf.save! + end + end + end + end +end diff --git a/db/migrate/20170130173612_move_orcid_id_from_users_to_user_identifiers.rb b/db/migrate/20170130173612_move_orcid_id_from_users_to_user_identifiers.rb new file mode 100644 index 0000000..c20c37f --- /dev/null +++ b/db/migrate/20170130173612_move_orcid_id_from_users_to_user_identifiers.rb @@ -0,0 +1,20 @@ +class MoveOrcidIdFromUsersToUserIdentifiers < ActiveRecord::Migration + def change + + if table_exists?('users') && table_exists?('identifier_schemes') + scheme = IdentifierScheme.find_by(name: 'orcid') + + unless scheme.nil? + User.all.each do |u| + unless u.orcid_id.nil? + u.user_identifiers << UserIdentifier.new(identifier_scheme: scheme, identifier: u.orcid_id) + u.save! + end + end + + remove_column :users, :orcid_id + end + end + + end +end diff --git a/db/schema.rb b/db/schema.rb index d93bfbc..b749bfe 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,60 +11,61 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20161208122123) do - - # These are extensions that must be enabled in order to support this database - enable_extension "plpgsql" +ActiveRecord::Schema.define(version: 20170130173612) do create_table "answers", force: :cascade do |t| - t.text "text" - t.integer "plan_id" - t.integer "user_id" - t.integer "question_id" + t.text "text", limit: 65535 + t.integer "plan_id", limit: 4 + t.integer "user_id", limit: 4 + t.integer "question_id", limit: 4 t.datetime "created_at" t.datetime "updated_at" end + add_index "answers", ["plan_id"], name: "fk_rails_84a6005a3e", using: :btree + add_index "answers", ["question_id"], name: "fk_rails_3d5ed4418f", using: :btree + add_index "answers", ["user_id"], name: "fk_rails_584be190c2", using: :btree + create_table "answers_question_options", id: false, force: :cascade do |t| - t.integer "answer_id", null: false - t.integer "question_option_id", null: false + t.integer "answer_id", limit: 4, null: false + t.integer "question_option_id", limit: 4, null: false end add_index "answers_question_options", ["answer_id", "question_option_id"], name: "answer_question_option_index", using: :btree add_index "answers_question_options", ["question_option_id", "answer_id"], name: "question_option_answer_index", using: :btree create_table "exported_plans", force: :cascade do |t| - t.integer "plan_id" - t.integer "user_id" - t.string "format" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.integer "plan_id", limit: 4 + t.integer "user_id", limit: 4 + t.string "format", limit: 255 + t.datetime "created_at" + t.datetime "updated_at" end create_table "file_types", force: :cascade do |t| - t.string "name" - t.string "icon_name" - t.integer "icon_size" - t.string "icon_location" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.string "name", limit: 255 + t.string "icon_name", limit: 255 + t.integer "icon_size", limit: 4 + t.string "icon_location", limit: 255 + t.datetime "created_at" + t.datetime "updated_at" end create_table "file_uploads", force: :cascade do |t| - t.string "name" - t.string "title" - t.text "description" - t.integer "size" + t.string "name", limit: 255 + t.string "title", limit: 255 + t.text "description", limit: 65535 + t.integer "size", limit: 4 t.boolean "published" - t.string "location" - t.integer "file_type_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.string "location", limit: 255 + t.integer "file_type_id", limit: 4 + t.datetime "created_at" + t.datetime "updated_at" end create_table "friendly_id_slugs", force: :cascade do |t| - t.string "slug", null: false - t.integer "sluggable_id", null: false + t.string "slug", limit: 255, null: false + t.integer "sluggable_id", limit: 4, null: false t.string "sluggable_type", limit: 40 t.datetime "created_at" end @@ -74,275 +75,333 @@ add_index "friendly_id_slugs", ["sluggable_type"], name: "index_friendly_id_slugs_on_sluggable_type", using: :btree create_table "guidance_groups", force: :cascade do |t| - t.string "name" - t.integer "org_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.string "name", limit: 255 + t.integer "org_id", limit: 4 + t.datetime "created_at" + t.datetime "updated_at" t.boolean "optional_subset" t.boolean "published" end + add_index "guidance_groups", ["org_id"], name: "fk_rails_819c1dbbc7", using: :btree + create_table "guidances", force: :cascade do |t| - t.text "text" - t.integer "guidance_group_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.integer "question_id" + t.text "text", limit: 65535 + t.integer "guidance_group_id", limit: 4 + t.datetime "created_at" + t.datetime "updated_at" + t.integer "question_id", limit: 4 t.boolean "published" end + add_index "guidances", ["guidance_group_id"], name: "fk_rails_20d29da787", using: :btree + + create_table "identifier_schemes", force: :cascade do |t| + t.string "name", limit: 255 + t.string "description", limit: 255 + t.boolean "active" + t.datetime "created_at" + t.datetime "updated_at" + end + create_table "languages", force: :cascade do |t| - t.string "abbreviation" - t.string "description" - t.string "name" + t.string "abbreviation", limit: 255 + t.string "description", limit: 255 + t.string "name", limit: 255 t.boolean "default_language" end create_table "notes", force: :cascade do |t| - t.integer "user_id" - t.text "text" + t.integer "user_id", limit: 4 + t.text "text", limit: 65535 t.boolean "archived" - t.integer "answer_id" - t.integer "archived_by" + t.integer "answer_id", limit: 4 + t.integer "archived_by", limit: 4 t.datetime "created_at" t.datetime "updated_at" end + add_index "notes", ["answer_id"], name: "fk_rails_907f8d48bf", using: :btree + add_index "notes", ["user_id"], name: "fk_rails_7f2323ad43", using: :btree + create_table "org_token_permissions", force: :cascade do |t| - t.integer "org_id" - t.integer "token_permission_type_id" + t.integer "org_id", limit: 4 + t.integer "token_permission_type_id", limit: 4 t.datetime "created_at" t.datetime "updated_at" end + add_index "org_token_permissions", ["org_id"], name: "fk_rails_e1db1b22c5", using: :btree + add_index "org_token_permissions", ["token_permission_type_id"], name: "fk_rails_2aa265f538", using: :btree + create_table "orgs", force: :cascade do |t| - t.string "name" - t.string "abbreviation" - t.string "target_url" - t.string "wayfless_entity" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.integer "parent_id" + t.string "name", limit: 255 + t.string "abbreviation", limit: 255 + t.string "target_url", limit: 255 + t.string "wayfless_entity", limit: 255 + t.datetime "created_at" + t.datetime "updated_at" + t.integer "parent_id", limit: 4 t.boolean "is_other" - t.string "sort_name" - t.text "banner_text" - t.string "logo_file_name" - t.integer "region_id" - t.integer "language_id" - t.string "logo_uid" - t.string "logo_name" - t.string "contact_email" - t.integer "org_type", default: 0, null: false + t.string "sort_name", limit: 255 + t.text "banner_text", limit: 65535 + t.string "logo_file_name", limit: 255 + t.integer "region_id", limit: 4 + t.integer "language_id", limit: 4 + t.string "logo_uid", limit: 255 + t.string "logo_name", limit: 255 + t.string "contact_email", limit: 255 + t.integer "org_type", limit: 4, default: 0, null: false end + add_index "orgs", ["language_id"], name: "fk_rails_5640112cab", using: :btree + add_index "orgs", ["region_id"], name: "fk_rails_5a6adf6bab", using: :btree + create_table "perms", force: :cascade do |t| - t.string "name" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.string "name", limit: 255 + t.datetime "created_at" + t.datetime "updated_at" end add_index "perms", ["name"], name: "index_perms_on_name", using: :btree add_index "perms", ["name"], name: "index_roles_on_name_and_resource_type_and_resource_id", using: :btree create_table "phases", force: :cascade do |t| - t.string "title" - t.text "description" - t.integer "number" - t.integer "template_id" + t.string "title", limit: 255 + t.text "description", limit: 65535 + t.integer "number", limit: 4 + t.integer "template_id", limit: 4 t.datetime "created_at" t.datetime "updated_at" - t.string "slug" + t.string "slug", limit: 255 t.boolean "modifiable" end + add_index "phases", ["template_id"], name: "fk_rails_0f8036cb2e", using: :btree + create_table "plans", force: :cascade do |t| - t.integer "project_id" - t.string "title" - t.integer "template_id" + t.integer "project_id", limit: 4 + t.string "title", limit: 255 + t.integer "template_id", limit: 4 t.datetime "created_at" t.datetime "updated_at" - t.string "slug" - t.string "grant_number" - t.string "identifier" - t.text "description" - t.string "principal_investigator" - t.string "principal_investigator_identifier" - t.string "data_contact" - t.string "funder_name" + t.string "slug", limit: 255 + t.string "grant_number", limit: 255 + t.string "identifier", limit: 255 + t.text "description", limit: 65535 + t.string "principal_investigator", limit: 255 + t.string "principal_investigator_identifier", limit: 255 + t.string "data_contact", limit: 255 + t.string "funder_name", limit: 255 + t.integer "visibility", limit: 4, default: 0, null: false end + add_index "plans", ["template_id"], name: "fk_rails_3424ca281f", using: :btree + create_table "question_formats", force: :cascade do |t| - t.string "title" - t.text "description" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.string "title", limit: 255 + t.text "description", limit: 65535 + t.datetime "created_at" + t.datetime "updated_at" + t.boolean "option_based", default: false end create_table "question_options", force: :cascade do |t| - t.integer "question_id" - t.string "text" - t.integer "number" + t.integer "question_id", limit: 4 + t.string "text", limit: 255 + t.integer "number", limit: 4 t.boolean "is_default" t.datetime "created_at" t.datetime "updated_at" end + add_index "question_options", ["question_id"], name: "fk_rails_b9c5f61cf9", using: :btree + create_table "questions", force: :cascade do |t| - t.text "text" - t.text "default_value" - t.text "guidance" - t.integer "number" - t.integer "section_id" + t.text "text", limit: 65535 + t.text "default_value", limit: 65535 + t.text "guidance", limit: 65535 + t.integer "number", limit: 4 + t.integer "section_id", limit: 4 t.datetime "created_at" t.datetime "updated_at" - t.integer "question_format_id" - t.boolean "option_comment_display", default: true + t.integer "question_format_id", limit: 4 + t.boolean "option_comment_display", default: true t.boolean "modifiable" end + add_index "questions", ["question_format_id"], name: "fk_rails_4fbc38c8c7", using: :btree + add_index "questions", ["section_id"], name: "fk_rails_c50eadc3e3", using: :btree + create_table "questions_themes", id: false, force: :cascade do |t| - t.integer "question_id", null: false - t.integer "theme_id", null: false + t.integer "question_id", limit: 4, null: false + t.integer "theme_id", limit: 4, null: false end add_index "questions_themes", ["question_id", "theme_id"], name: "question_theme_index", using: :btree add_index "questions_themes", ["theme_id", "question_id"], name: "theme_question_index", using: :btree create_table "region_groups", force: :cascade do |t| - t.integer "super_region_id" - t.integer "region_id" + t.integer "super_region_id", limit: 4 + t.integer "region_id", limit: 4 end create_table "regions", force: :cascade do |t| - t.string "abbreviation" - t.string "description" - t.string "name" + t.string "abbreviation", limit: 255 + t.string "description", limit: 255 + t.string "name", limit: 255 end create_table "roles", force: :cascade do |t| - t.integer "user_id" - t.integer "plan_id" + t.integer "user_id", limit: 4 + t.integer "plan_id", limit: 4 t.datetime "created_at" t.datetime "updated_at" - t.integer "access", default: 0, null: false + t.integer "access", limit: 4, default: 0, null: false end + add_index "roles", ["plan_id"], name: "fk_rails_a1ce6c2772", using: :btree + add_index "roles", ["user_id"], name: "fk_rails_ab35d699f0", using: :btree + create_table "sections", force: :cascade do |t| - t.string "title" - t.text "description" - t.integer "number" + t.string "title", limit: 255 + t.text "description", limit: 65535 + t.integer "number", limit: 4 t.datetime "created_at" t.datetime "updated_at" t.boolean "published" - t.integer "phase_id" + t.integer "phase_id", limit: 4 t.boolean "modifiable" end + add_index "sections", ["phase_id"], name: "fk_rails_1853581585", using: :btree + create_table "settings", force: :cascade do |t| - t.string "var", null: false - t.text "value" - t.integer "target_id", null: false - t.string "target_type", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.string "var", limit: 255, null: false + t.text "value", limit: 65535 + t.integer "target_id", limit: 4, null: false + t.string "target_type", limit: 255, null: false + t.datetime "created_at" + t.datetime "updated_at" end add_index "settings", ["target_type", "target_id", "var"], name: "index_settings_on_target_type_and_target_id_and_var", unique: true, using: :btree create_table "splash_logs", force: :cascade do |t| - t.string "destination" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.string "destination", limit: 255 + t.datetime "created_at" + t.datetime "updated_at" end create_table "suggested_answers", force: :cascade do |t| - t.integer "question_id" - t.integer "org_id" - t.text "text" + t.integer "question_id", limit: 4 + t.integer "org_id", limit: 4 + t.text "text", limit: 65535 t.boolean "is_example" t.datetime "created_at" t.datetime "updated_at" end + add_index "suggested_answers", ["org_id"], name: "fk_rails_473de65779", using: :btree + add_index "suggested_answers", ["question_id"], name: "fk_rails_daa60b5b70", using: :btree + create_table "templates", force: :cascade do |t| - t.string "title" - t.text "description" + t.string "title", limit: 255 + t.text "description", limit: 65535 t.boolean "published" - t.integer "org_id" - t.string "locale" + t.integer "org_id", limit: 4 + t.string "locale", limit: 255 t.boolean "is_default" t.datetime "created_at" t.datetime "updated_at" - t.integer "version" - t.integer "visibility" - t.integer "customization_of" - t.integer "dmptemplate_id" + t.integer "version", limit: 4 + t.integer "visibility", limit: 4 + t.integer "customization_of", limit: 4 + t.integer "dmptemplate_id", limit: 4 end + add_index "templates", ["org_id"], name: "fk_rails_481431e1bd", using: :btree + create_table "themes", force: :cascade do |t| - t.string "title" - t.text "description" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "locale" + t.string "title", limit: 255 + t.text "description", limit: 65535 + t.datetime "created_at" + t.datetime "updated_at" + t.string "locale", limit: 255 end create_table "themes_in_guidance", id: false, force: :cascade do |t| - t.integer "theme_id" - t.integer "guidance_id" + t.integer "theme_id", limit: 4 + t.integer "guidance_id", limit: 4 end + add_index "themes_in_guidance", ["guidance_id"], name: "fk_rails_a5ab9402df", using: :btree + add_index "themes_in_guidance", ["theme_id"], name: "fk_rails_7d708f6f1e", using: :btree + create_table "token_permission_types", force: :cascade do |t| - t.string "token_type" - t.text "text_description" + t.string "token_type", limit: 255 + t.text "text_description", limit: 65535 t.datetime "created_at" t.datetime "updated_at" end - create_table "users", force: :cascade do |t| - t.string "firstname" - t.string "surname" - t.string "email", default: "", null: false - t.string "orcid_id" - t.string "shibboleth_id" + create_table "user_identifiers", force: :cascade do |t| + t.string "identifier", limit: 255 t.datetime "created_at" t.datetime "updated_at" - t.string "encrypted_password", default: "" - t.string "reset_password_token" + t.integer "user_id", limit: 4 + t.integer "identifier_scheme_id", limit: 4 + end + + add_index "user_identifiers", ["identifier_scheme_id"], name: "fk_rails_fe95df7db0", using: :btree + add_index "user_identifiers", ["user_id"], name: "fk_rails_65c9a98cdb", using: :btree + + create_table "users", force: :cascade do |t| + t.string "firstname", limit: 255 + t.string "surname", limit: 255 + t.string "email", limit: 255, default: "", null: false + t.string "shibboleth_id", limit: 255 + t.datetime "created_at" + t.datetime "updated_at" + t.string "encrypted_password", limit: 255, default: "" + t.string "reset_password_token", limit: 255 t.datetime "reset_password_sent_at" t.datetime "remember_created_at" - t.integer "sign_in_count", default: 0 + t.integer "sign_in_count", limit: 4, default: 0 t.datetime "current_sign_in_at" t.datetime "last_sign_in_at" - t.string "current_sign_in_ip" - t.string "last_sign_in_ip" - t.string "confirmation_token" + t.string "current_sign_in_ip", limit: 255 + t.string "last_sign_in_ip", limit: 255 + t.string "confirmation_token", limit: 255 t.datetime "confirmed_at" t.datetime "confirmation_sent_at" - t.string "invitation_token" + t.string "invitation_token", limit: 255 t.datetime "invitation_created_at" t.datetime "invitation_sent_at" t.datetime "invitation_accepted_at" - t.string "other_organisation" + t.string "other_organisation", limit: 255 t.boolean "dmponline3" t.boolean "accept_terms" - t.integer "org_id" - t.string "api_token" - t.integer "invited_by_id" - t.string "invited_by_type" - t.integer "language_id" + t.integer "org_id", limit: 4 + t.string "api_token", limit: 255 + t.integer "invited_by_id", limit: 4 + t.string "invited_by_type", limit: 255 + t.integer "language_id", limit: 4 end add_index "users", ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true, using: :btree add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree add_index "users", ["invitation_token"], name: "index_users_on_invitation_token", unique: true, using: :btree + add_index "users", ["language_id"], name: "fk_rails_45f4f12508", using: :btree + add_index "users", ["org_id"], name: "fk_rails_e73753bccb", using: :btree add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree create_table "users_perms", id: false, force: :cascade do |t| - t.integer "user_id" - t.integer "perm_id" + t.integer "user_id", limit: 4 + t.integer "perm_id", limit: 4 end + add_index "users_perms", ["perm_id"], name: "fk_rails_457217c31c", using: :btree add_index "users_perms", ["user_id", "perm_id"], name: "index_users_perms_on_user_id_and_perm_id", using: :btree add_foreign_key "answers", "plans" @@ -373,6 +432,8 @@ add_foreign_key "templates", "orgs" add_foreign_key "themes_in_guidance", "guidances" add_foreign_key "themes_in_guidance", "themes" + add_foreign_key "user_identifiers", "identifier_schemes" + add_foreign_key "user_identifiers", "users" add_foreign_key "users", "languages" add_foreign_key "users", "orgs" add_foreign_key "users_perms", "perms" diff --git a/db/seeds.rb b/db/seeds.rb index 70912b7..2467322 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -2,762 +2,794 @@ # This file should contain all the record creation needed to seed the database with its default values. # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). -# Dmptemplate default formatting settings based on https://je-s.rcuk.ac.uk/Handbook/pages/GuidanceonCompletingaStandardG/CaseforSupportandAttachments/CaseforSupportandAttachments.htm +# Identifier Schemes +# ------------------------------------------------------- +identifier_schemes = [ + {name: 'orcid', description: 'ORCID researcher identifiers', active: true}, + {name: 'shibboleth', description: 'Shibboleth', active: false}, + {name: 'facebook', description: 'Facebook OAuth', active: false} +] +identifier_schemes.map{ |is| IdentifierScheme.create!(is) if IdentifierScheme.find_by(name: is[:name]).nil? } -d1 = DateTime.new(2015, 6, 22) +# Question Formats +# ------------------------------------------------------- +question_formats = [ + {title: "Text area", option_based: false}, + {title: "Text field", option_based: false}, + {title: "Radio buttons", option_based: true}, + {title: "Check box", option_based: true}, + {title: "Dropdown", option_based: true}, + {title: "Multi select box", option_based: true}, + {title: "Date", option_based: false} +] +question_formats.map{ |qf| QuestionFormat.create!(qf) if QuestionFormat.find_by(title: qf[:title]).nil? } -languages = { - 'English(UK)' => { - abbreviation: 'en-UK', - description: 'UK English language used as default', - name: 'English(UK)', - default_language: true - }, - 'FR' => { - abbreviation: 'fr', - description: '', - name: 'fr', +# Languages (check config/locales for any ones not defined here) +# ------------------------------------------------------- +languages = [ + {abbreviation: 'en-UK', + description: 'UK English', + name: 'English (UK)', + default_language: true}, + {abbreviation: 'en-US', + description: 'US English', + name: 'English (US)', + default_language: false}, + {abbreviation: 'fr', + description: 'French', + name: 'French', + default_language: false}, + {abbreviation: 'de', + description: 'German', + name: 'German', + default_language: false}, + {abbreviation: 'es', + description: 'Spanish', + name: 'Spanish', + default_language: false} +] +languages.map{ |l| Language.create!(l) if Language.find_by(abbreviation: l[:abbreviation]).nil? } + +# Scan through the locale files and add an entry if a file is present but +# not defined in this seed file +Dir.entries("#{Rails.root.join("config", "locales").to_s}").each do |f| + if f[-4..-1] == '.yml' + lang = f.gsub('.yml', '') + + if Language.where(abbreviation: lang).empty? + Language.create!({ + abbreviation: lang, + description: lang, + name: lang, default_language: false - }, - 'DE' => { - abbreviation: 'de', - description: '', - name: 'de', - default_language: false - }, - 'ES' => { - abbreviation: 'es', - description: '', - name: 'es', - default_language: false - } -} - -languages.each do |l, details| - if Language.where(name: details[:name]).empty? - language = Language.new - language.abbreviation = details[:abbreviation] - language.description = details[:description] - language.name = details[:name] - language.default_language = details[:default_language] - language.save! - end -end - -regions = { - 'UK' => { - abbreviation: 'uk', - description: 'default region', - name: 'UK', - }, - 'DE' => { - abbreviation: 'de', - description: '', - name: 'DE', - }, - 'Horizon2020' => { - abbreviation: 'horizon', - description: 'European super region', - name: 'Horizon2020', - } -} - -regions.each do |l, details| - if Region.where(name: details[:name]).empty? - region = Region.new - region.abbreviation = details[:abbreviation] - region.description = details[:description] - region.name = details[:name] - region.save! - end -end - -region_groups = { - 'UK' => { - super_region_name: 'Horizon2020', - region_name: 'UK', - }, - 'DE' => { - super_region_name: 'Horizon2020', - region_name: 'DE', - } -} - -region_groups.each do |l, details| - if RegionGroup.find_by(region_id: details[:region_name]).blank? - region_group = RegionGroup.new - region_group.super_region_id = Region.find_by_name(details[:super_region_name]).id - region_group.region_id = Region.find_by_name(details[:region_name]).id - region_group.save! - end -end - -organisation_types = { - 'Organisation' => { - name: "Organisation" - }, - 'Funder' => { - name: "Funder" - }, - 'Project' => { - name: "Project" - }, - 'Institution' => { - name: "Institution" - }, - 'Research Institute' => { - name: "Research Institute" - } - } - - organisation_types.each do |org_type, details| - if OrganisationType.where(name: details[:name]).empty? - organisation_type = OrganisationType.new - organisation_type.name = details[:name] - organisation_type.save! - end - end - - organisations = { - 'Your Organization' => { - name: "My Regional Curation Centre", - abbreviation: "RCC", - sort_name: "MyRegionalCurationCenter", - organisation_type: "Organisation", - description: "An example: Regional Curation Center concerned with research data management (typically the organization hosting this website)", - banner_text: "Example: Your Regional Curation Center", - region: 'UK', - language: 'English(UK)' - }, - 'Global Funding Organization' => { - name: "Global Research Center", - abbreviation: "EGRC", - sort_name: "GlobalResearchCenter", - organisation_type: "Funder", - description: "An example: Research funding agency", - banner_text: "Example: Global Research Center", - region: 'UK', - language: 'English(UK)' - }, - 'Regional Funding Organization' => { - name: "Regional Science Federation", - abbreviation: "RegSciFed", - sort_name: "RegionalScienceFederation", - organisation_type: "Funder", - description: "An example: Regional funding agency for scientific research", - banner_text: "Example: Regional Science Federation", - region: 'UK', - language: 'English(UK)' - }, - 'Example Institution'=> { - name: "Capital City College", - abbreviation: "CapColl", - sort_name: "CapitalCityCollege", - organisation_type: "Institution", - description: "An example: Academic institution", - banner_text: "Example: Capital City College ... go mascots!!", - region: 'UK', - language: 'English(UK)' - } - } - - organisations.each do |org, details| - if Org.where(abbreviation: details[:abbreviation]).empty? - organisation = Org.new - organisation.name = details[:name] - organisation.abbreviation = details[:abbreviation] - organisation.sort_name = details[:sort_name] - organisation.organisation_type = OrganisationType.find_by_name(details[:organisation_type]) - organisation.region_id = Region.find_by_name(details[:region]).id - organisation.language_id = Language.find_by_name(details[:language]).id - organisation.save! - end - end - -roles = { - 'admin' => { - name: "admin" #depricated - }, - 'org_admin' => { - name: "org_admin" #depricated - }, - 'user' => { - name: "user" #depricated - }, - 'add_organisations' => { - name: 'add_organisations' - }, - 'change_org_affiliation' => { - name: 'change_org_affiliation' - }, - 'grant_permissions' => { - name: 'grant_permissions' - }, - 'modify_templates' => { - name: 'modify_templates' - }, - 'modify_guidance' => { - name: 'modify_guidance' - }, - 'use_api' => { - name: 'use_api' - }, - 'change_org_details' => { - name: 'change_org_details' - }, - 'grant_api_to_orgs' => { - name: 'grant_api_to_orgs' - } -} - -roles.each do |role, details| - if Role.where(name: details[:name]).empty? - role = Role.new - role.name = details[:name] - role.save! - end -end - -users = { - 'Super admin' => { - email: "super_admin@example.com", - password: "password123", - firstname: "RCC Super", - surname: "Admin", - password_confirmation: "password123", - organisation: "RCC", - language: 'English(UK)', - roles: ['admin','org_admin','add_organisations','change_org_affiliation','grant_permissions','modify_templates','modify_guidance','use_api','change_org_details','grant_api_to_orgs'], - accept_terms: true, - confirmed_at: Time.zone.now - }, - 'Funder admin' => { - email: "funder_admin@example.com", - password: "password123", - password_confirmation: "password123", - firstname: "Funder", - surname: "Admin", - organisation: "RegSciFed", - language: 'English(UK)', - roles: ['org_admin','grant_permissions','modify_templates','modify_guidance','change_org_details'], - accept_terms: true, - confirmed_at: Time.zone.now - }, - 'Organizational admin' => { - email: "org_admin@example.com", - password: "password123", - password_confirmation: "password123", - firstname: "Organization", - surname: "Admin", - organisation: "CapColl", - language: 'English(UK)', - roles: ['org_admin','grant_permissions','modify_templates','modify_guidance','change_org_details'], - accept_terms: true, - confirmed_at: Time.zone.now - }, - 'Organizational user' => { - email: "org_user@example.com", - password: "password123", - password_confirmation: "password123", - firstname: "Jane", - surname: "Researcher", - organisation: "CapColl", - language: 'English(UK)', - roles: ['user'], - accept_terms: true, - confirmed_at: Time.zone.now - }, - 'Organizational user' => { - email: "org_user@example.com", - password: "password123", - password_confirmation: "password123", - firstname: "Jane", - surname: "Researcher", - organisation: "CapColl", - language: 'English(UK)', - roles: ['user'], - accept_terms: true, - confirmed_at: Time.zone.now - } - } - -users.each do |user, details| - if User.where(email: details[:email]).empty? - usr = User.new - else - usr = User.where(email: details[:email]) - end - usr.email = details[:email] - usr.password = details[:password] - usr.password_confirmation = details[:password_confirmation] - usr.confirmed_at = details[:confirmed_at] - usr.organisation_id = Org.find_by_abbreviation(details[:organisation]).id - usr.language_id = Language.find_by_name(details[:language]).id - details[:roles].each do |role| - usr.roles << Role.find_by_name(role) + }) end - usr.accept_terms = details[:accept_terms] - usr.save! -end - - themes = { - "Theme 1" => { - title: "Theme 1", - locale: "en" - }, - "Theme 2" => { - title: "Theme 2", - locale: "en" - }, - "Theme 3" => { - title: "Theme 3", - locale: "en", - description: "Theme 3 description." - }, - "Theme 4" => { - title: "Theme 4", - locale: "en", - description: "Theme 4 description." - } - } - - themes.each do |t, details| - if Theme.where(title: details[:title]).empty? - theme = Theme.new - theme.title = details[:title] - theme.locale = details[:locale] - theme.description = details[:description] - theme.save! - end - end - - question_formats = { - "Text area" => { - title: "Text area" - }, - "Text field" => { - title: "Text field" - }, - "Radio buttons" => { - title: "Radio buttons" - }, - "Check box" => { - title: "Check box" - }, - "Dropdown" => { - title: "Dropdown" - }, - "Multi select box" => { - title: "Multi select box" - }, - } - - question_formats.each do |qf, details| - if QuestionFormat.where(title: details[:title]).empty? - question_format = QuestionFormat.new - question_format.title = details[:title] - question_format.save! - end - end - - guidance_groups = { - "RCC Guidance" => { - name: "My organization guidance (optional generic guidance you provide for users)", - organisation: "RCC", - optional_subset: true - }, - "Global Research Center Guidance" => { - name: "Global Research Center (Funder specific guidance)", - organisation: "EGRC", - optional_subset: false - }, - "Regional Science Federation Guidance" => { - name: "Regional Science Federation (Funder specific guidance)", - organisation: "RegSciFed", - optional_subset: false - }, - "Institutional Guidance" => { - name: "CapColl - School of Math and Science (optional institutional guidance)", - organisation: "CapColl", - optional_subset: true - } - } - - guidance_groups.each do |gg, details| - if GuidanceGroup.where(name: details[:name]).empty? - guidance_group = GuidanceGroup.new - guidance_group.name = details[:name] - guidance_group.organisation = Org.find_by_abbreviation(details[:organisation]) - guidance_group.optional_subset = details[:optional_subset] - guidance_group.save! - end - end - - guidances = { - "Guidance 1" => { - text: "Guidance text", - guidance_group: "My organization guidance (optional generic guidance you provide for users)", - themes: ["Theme 4"] - }, - "Guidance 2" => { - text: "Guidance text", - guidance_group: "Global Research Center (Funder specific guidance)", - themes: ["Theme 2"] - }, - "Guidance 3" => { - text: "Guidance text", - guidance_group: "Global Research Center (Funder specific guidance)", - themes: ["Theme 3"] - }, - "Guidance 4" => { - text: "Guidance text", - guidance_group: "Regional Science Federation (Funder specific guidance)", - themes: ["Theme 1"] - }, - "Guidance 4" => { - text: "Guidance text", - guidance_group: "CapColl - School of Math and Science (optional institutional guidance)", - themes: ["Theme 1"] - } - } - - guidances.each do |g, details| - if Guidance.where(text: details[:text]).empty? - guidance = Guidance.new - guidance.text = details[:text] - guidance.guidance_groups << GuidanceGroup.find_by_name(details[:guidance_group]) - details[:themes].each do |theme| - guidance.themes << Theme.find_by_title(theme) - end - guidance.save! - end - end - - templates = { - "RCC" => { - title: "Regional Curation Center Template", - description: "The default RCC template", - published: true, - organisation: "RCC", - locale: "en", - is_default: true - }, - "Global Research Center" => { - title: "Global Research Center Award", - description: "Funder template description", - published: true, - organisation: "EGRC", - locale: "en", - is_default: false - }, - "Regional Science Federation" => { - title: "Regional Science Federation Grant - Summary", - description: "Funder template description for phase 1", - published: true, - organisation: "RegSciFed", - locale: "en", - is_default: false - }, - "Regional Science Federation2" => { - title: "Regional Science Federation Grant - Finalized", - description: "Funder template description for phase 2", - published: true, - organisation: "RegSciFed", - locale: "en", - is_default: false - } - } - - templates.each do |t, details| - org = Org.where(abbreviation: details[:organisation]).first - - if Dmptemplate.where(organisation: org).where(title: details[:title]).empty? - template = Dmptemplate.new - template.title = details[:title] - template.description = details[:description] - template.published = details[:published] - template.locale = details[:locale] - template.is_default = details[:is_default] - template.organisation = org - template.save! - end - end - - phases = { - "RCC" => { - title: "Regional CurationCenter Data Management Plan", - number: 1, - template: "Regional Curation Center Template" - }, - "EGRC Template" => { - title: "Global Research Center Annual Award", - number: 1, - template: "Global Research Center Award" - }, - "RegSciFed Template" => { - title: "Regional Science Federation - Preliminary", - number: 1, - template: "Regional Science Federation Grant - Summary" - }, - "RegSciFed Template2" => { - title: "Regional Science Federation - Final", - number: 1, - template: "Regional Science Federation Grant - Finalized" - } - } - - phases.each do |p, details| - if Phase.where(title: details[:title]).empty? - phase = Phase.new - phase.title = details[:title] - phase.number = details[:number] - phase.dmptemplate = Dmptemplate.find_by_title(details[:template]) - phase.save! - end - end - - versions = { - "RCC" => { - title: "Default Template v1", - number: 1, - phase: "Regional CurationCenter Data Management Plan" - }, - "EGRC" => { - title: "Annual Award v1", - number: 1, - phase: "Global Research Center Annual Award" - }, - "RegSciFed_1" => { - title: "Grant Summary v1", - number: 1, - phase: "Regional Science Federation - Preliminary" - }, - "RegSciFed_2" => { - title: "Grant Finalized Award v1", - number: 1, - phase: "Regional Science Federation - Final" - }, - "RegSciFed_2.1" => { - title: "Grant Finalized v2", - number: 1, - phase: "Regional Science Federation - Final" - }, - } - - versions.each do |v, details| - if Version.where(title: details[:title]).empty? - version = Version.new - version.title = details[:title] - version.number = details[:number] - version.phase = Phase.find_by_title(details[:phase]) - version.save! - end - end - - sections = { - "Section 1" => { - title: "Data Collection", - number: 1, - description: "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", - version: "Default Template v1", - organisation: "RCC" - }, - "Section 2" => { - title: "Documentation and Metadata", - number: 2, - description: "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", - version: "Default Template v1", - organisation: "RCC" - }, - "Section A" => { - title: "Data Overview", - number: 1, - version: "Annual Award v1", - organisation: "EGRC" - }, - "Section B" => { - title: "Ethics and Legal Compliance", - number: 2, - version: "Annual Award v1", - organisation: "EGRC" - }, - "Section C" => { - title: "Storage and Backup", - number: 3, - version: "Annual Award v1", - organisation: "EGRC" - }, - "Section D" => { - title: "Preservation, Sustainability and Use", - number: 4, - version: "Annual Award v1", - organisation: "EGRC" - }, - "regSciFed Summary" => { - title: "Data Collection Guidelines", - number: 1, - description: "This is what we plan on collecting and how we're going to store it.", - version: "Grant Summary v1", - organisation: "RegSciFed" - }, - "RegSciFed Final 1" => { - title: "Data Collection and Storage", - number: 1, - version: "Grant Finalized Award v1", - organisation: "RegSciFed" - }, - "RegSciFed Final 1_2" => { - title: "Data Preservation", - number: 2, - version: "Grant Finalized v2", - organisation: "RegSciFed" - }, - "RegSciFed Final 2_2" => { - title: "Ongoing Access", - number: 3, - version: "Grant Finalized v2", - organisation: "RegSciFed" - } - } - - sections.each do |s, details| - if Section.where(title: details[:title]).empty? - section = Section.new - section.title = details[:title] - section.number = details[:number] - section.description = details[:description] - section.version = Version.find_by_title(details[:version]) - section.organisation = Org.find_by_abbreviation(details[:organisation]) - section.save! - end - end - - questions = { - "What data will you collect or create?" => { - text: "What data will you collect or create?", - section: "Data Collection", - number: 1, - guidance: "

    Questions to consider:

    Guidance:

    Give a brief description of the data, including any existing data or third-party sources that will be used, in each case noting its content, type and coverage. Outline and justify your choice of format and consider the implications of data format and data volumes in terms of storage, backup and access.

    ", - themes: ["Theme 2"] - }, - "How will the data be collected or created?" => { - text: "How will the data be collected or created?", - section: "Data Collection", - number: 2, - guidance: "

    Questions to consider:

    Guidance:

    Outline how the data will be collected/created and which community data standards (if any) will be used. Consider how the data will be organised during the project, mentioning for example naming conventions, version control and folder structures. Explain how the consistency and quality of data collection will be controlled and documented. This may include processes such as calibration, repeat samples or measurements, standardised data capture or recording, data entry validation, peer review of data or representation with controlled vocabularies.

    ", - themes: ["Theme 3"] - }, - "What documentation and metadata will accompany the data?" => { - text: "What documentation and metadata will accompany the data?", - section: "Documentation and Metadata", - number: 1, - guidance: "

    Questions to consider:

    Guidance:

    Describe the types of documentation that will accompany the data to help secondary users to understand and reuse it. This should at least include basic details that will help people to find the data, including who created or contributed to the data, its title, date of creation and under what conditions it can be accessed.

    Documentation may also include details on the methodology used, analytical and procedural information, definitions of variables, vocabularies, units of measurement, any assumptions made, and the format and file type of the data. Consider how you will capture this information and where it will be recorded. Wherever possible you should identify and use existing community standards.

    ", - themes: ["Theme 1"] - }, - "Data Overview" => { - text: "Overview of the Data", - section: "Data Overview", - number: 1, - guidance: "

    Things to consider: