diff --git a/.gitignore b/.gitignore
index 2b59cc6..d6d744a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,6 +35,7 @@
# Ignore database configuration and token secrets
config/database.yml
config/secrets.yml
+config/branding.yml
# Ignore some of the initializers
config/initializers/recaptcha.rb
@@ -60,3 +61,7 @@
# ignore yard generated documents
/doc/*
!/doc/README_FOR_APP
+
+# ignore auto-generated gettext files when running gettext:find
+config/locale/*/app.edit.po
+config/locale/*/app.po.time_stamp
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
index bc14e2d..453b68d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,10 +5,13 @@
before_script:
- cp config/database_example.yml config/database.yml
- cp config/secrets_example.yml config/secrets.yml
+ - cp config/branding_example.yml config/branding.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
+ - bundle exec rake db:drop RAILS_ENV=test
+ - bundle exec rake db:create RAILS_ENV=test
+ - bundle exec rake db:schema:load RAILS_ENV=test
script:
- bundle exec rake test
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..c1617b1
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,127 @@
+## Introduction
+The goal of the DMPRoadmap project is to provide the community with a reliable and stable platform for managing data management plans. This means that all development efforts should adhere to some basic tenets to ensure that the system remains stable and provides functionality for the community as a whole.
+
+These guidelines are an attempt to ensure that we are able to provide the community with a reliable system, stable APIs, a clear roadmap, and a predictable release schedule.
+
+* If you would like to contribute to the project. Please follow these steps to submit a contribution:
+ * Comment on the Github issue (or create one if one does not exist) and let us know that you're working on it.
+ * Fork the project (if you have not already) or rebase your fork so that it is up to date with the current repository's '_**development**_' branch
+ * Create a new branch in your fork. This will ensure that you are able to work at your own pace and continue to pull in any updates made to this project.
+ * Make your changes in the new branch
+ * When you have finished your work, make sure that your version of the '_**development**_' branch is still up to date with this project. Then merge your new branch into your '_**development**_' branch.
+ * Then create a new Pull Request (PR) to this project's '_**contributions**_' branch in GitHub
+ * The project team will then review your PR and communicate with you to convey any additional changes that would ensure that your work adheres to our guidelines.
+
+Table of contents:
+* [Github Workflow](#github-workflow)
+* [Pull Requests](#pull-requests)
+* [Testing Guidelines](#testing-guidelines)
+* [Coding Style/Guidelines](#coding-style)
+
+## GitHub Workflow
+A contribution consists of any work that is voluntarily submitted to the project. This includes bug fixes, enhancements and documentation that is intended as an improvement to the DMP Roadmap system.
+
+Any individual with a GitHub account may propose a Contribution by submitting a Pull Request (PR) to this project's '_**contributions**_' branch. The project team will evaluate each PR as time permits and communicate with the contributor via comments on the PR. We will not accept a contribution until it adheres to the guidelines outlined in this document. If your contribution fits well with the development roadmap, the team will merge it into the project and schedule it for the next upcoming release.
+
+
+
+## Pull Requests
+Please use these checklists to help you prepare your Pull Request for submission.
+
+ALL Pull Requests MUST be made to the '_**contributions**_' branch!
+
+#### Checklist for changes to a database table and/or its corresponding model
+* Did you include the appropriate database migration? ```> rails g migration AddTwitterIdToUsers```
+* Did you update/add the Unit tests?
+* Did your change require you to transform data? For example moving data from one field to another like moving users.organisation_id to a join table called users_organisations. If so, did you include a rake task to help others migrate their data over to the new model (along with instructions)?
+* Does the schema.rb include the changes?
+* Did you remember to update the seeds.rb file to reflect the change?
+
+#### Checklist for changes to a controller
+* Did you update/add the Functional tests?
+* Did you update/add the Routing tests (if applicable)?
+* Did you update the corresponding view(s)?
+* Did you include any updates/additions to localisation text config/locales/pot file?
+
+#### Checklist for changes to a view
+* Did you include any updates/additions to localisation text config/locales/pot file?
+* Did you update the corresponding controller?
+* Did you manually test the change in multiple browsers?
+* Did your change require modifications to the CSS, JS or image files? If so did you include them in your branded file locations or in the core system files? For example: lib/assets/javascripts is the default javascript directory. app/assets/javascripts are specific to your local installation. (See [Branding](https://github.com/DMPRoadmap/roadmap/wiki/Branding) for more information)
+
+## Testing Guidelines
+First and foremost, all of the existing tests must pass before we accept your contribution. If your work has made a change to an object that results in failed tests then you should update those tests so that they are accurate.
+
+To run the tests:
+```shell
+# Make sure that your test DB has all of the current database migrations:
+> rake db:migrate RAILS_ENV=test
+
+# To run all of the tests:
+> rake test
+# To run all of a specific type of tests:
+> rake test test/unit/
+# To run a specific test:
+> rake test test/unit/users_test.rb
+```
+
+If you are adding a new feature to the system you must build out the appropriate tests before we will accept your contribution. For example, if I add a new field to the User table that stores the user's Twitter id, I should update the test/unit/users_test.rb Unit test. If my contribution included changes to the User Profile page that allowed the user to enter this new Twitter id then I should update the test/functional/registrations_controller_test.rb Functional controller test.
+
+DMP Roadmap uses the Travis CI framework to verify that are tests are passing. When you create your PR you will see a note stating that the tests are pending. Check back after a few minutes to give the Travis system time to run its tests.
+
+**Please Note:** We will not review your PR until the tests are passing and GitHub notes that there are no merge conflicts
+
+The original DMP Roadmap codebase did not include a full suite of tests. The project team has been busy adding them in when we can but we still have a long way to go. The requirements mentioned above are in place for pieces of the system that already have tests. For example, if your work involves an enhancement to an existing controller that has no functional test in the current codebase, we do not expect you to write tests for the entire controller (although we would welcome the help!). In cases like this, we only ask that you write tests for the endpoints that you have updated.
+
+We do not currently have testing for the UI components. We plan to add tests for these in the near future using a headless browser like PhantomJS. We welcome any contributors who are willing to begin work in this area!
+
+#### Unit tests:
+* The model can be Created, Read/Loaded, Updated and Deleted (CRUD)
+* Required fields are required and that the model cannot be saved without those fields
+* Any other validations are working as expected (e.g. email address is in the email format)
+* Associations are functioning properly. Use the helper methods in test/test_helper.rb
+* All other functions that are defined within the model are tested
+* You should update or create the corresponding fixtures for the model you are testing
+
+#### Functional Controller tests:
+* The correct HTTP response was received (200 success, 302 redirect, 401 unauthorized, etc.)
+* The user was redirected to the correct page (if applicable)
+* All of the instance variables set within the controller were properly defined
+* All flash messaging is correct
+
+#### Integration tests:
+* Complex workflows that involve multiple pieces of the system should have an integration test. This can include interaction with gem dependencies or external services. For example email, login/logout, etc.
+
+#### Helper/Service tests:
+* Each method within the helper or service should be tested for both success and failure conditions
+
+#### Routing tests:
+New controller/API endpoints should have tests within the test/routing_test.rb
+
+#### General Notes and Advice:
+* You should use the Rails URL and Path helpers instead of hard-coding them in your tests. (e.g. edit_plans_path(@plan) instead of '/plans/123/edit'
+* You should use the I18n.t method to validate flash messaging rather than hard-coding messages in your tests
+* You should include assertions that test both success and failure conditions
+
+## Coding style
+We realize that every developer has their own style and we encourage a bit of individuality. However, we do impose some of the following rules to contributions to this project.
+
+* We quite like the principle of [DRY (Don't Repeat Yourself)](https://en.wikipedia.org/wiki/Don't_repeat_yourself) so please always look through the existing code to make sure you are not reinventing something that has already been done. Also clever bits of code or reuse of existing ones to avoid copying and pasting is always appreciated.
+* Include database migrations when you are altering the database model. Use the following command to create a new migration and be specific about what it does in the name of the file
+
+ ```shell
+ > rails g migration AddTwitterIdToUsers
+ ```
+* You do not need to comment every line of your code but we do expect to see inline comments explaining the intent of your if blocks and loops.
+* We do not want to see Tab characters. Tabs should be converted to a double space. If you are working on a file that has Tabs already, please convert them for us before making your Pull Request
+* If a line is going to go beyond 100 characters please break it out onto multiple lines. For example:
+
+ ```ruby
+ # This is preferable
+ users = [{email: @user.email, password: 'bAd_pas$word1', remember_me: true},
+ {email: 'unknown@institution.org', password: 'password123', remember_me: true}]
+
+ # to this long line that requires scrolling
+ users = [{email: @user.email, password: 'bAd_pas$word1', remember_me: true}, {email: 'unknown@institution.org', password: 'password123', remember_me: true}]
+ ```
+* Finally, please make sure your code is properly indented as this enhances readability.
diff --git a/Gemfile b/Gemfile
index 2b41610..2d9b5b9 100644
--- a/Gemfile
+++ b/Gemfile
@@ -34,7 +34,7 @@
# ------------------------------------------------
# SUPER ADMIN SECTION
-gem 'activeadmin', github: 'activeadmin'
+gem "administrate", :github => 'thoughtbot/administrate', :branch =>'v0.7.0'
# ------------------------------------------------
# USERS
@@ -59,11 +59,13 @@
gem 'sass-rails'
gem 'less-rails' # WE SHOULD PROBABLY USE SASS OR LESS NOT BOTH
gem 'jquery-rails'
+gem 'font-awesome-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 'recaptcha'
+gem 'recaptcha', '>= 4.0'
gem 'dragonfly' # LOGO UPLOAD
+gem 'formtastic'
# ------------------------------------------------
# EXPORTING
@@ -72,14 +74,14 @@
gem 'wicked_pdf'
gem 'htmltoword'
gem 'feedjira'
-gem 'caracal' # WORD DOC EXPORTING
-gem 'caracal-rails'
gem 'yaml_db', :git => 'https://github.com/vyruss/yaml_db.git'
# ------------------------------------------------
# INTERNATIONALIZATION
gem "i18n-js", ">= 3.0.0.rc11" #damodar added TODO: explain
gem 'gettext_i18n_rails', '~> 1.8'
+gem "gettext_i18n_rails_js", "~> 1.2.0"
+gem 'gettext', '>=3.0.2', :require => false, :group => :development
# ------------------------------------------------
# API
diff --git a/Gemfile.lock b/Gemfile.lock
index d430a3c..53bf3cf 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,21 +1,20 @@
GIT
- remote: git://github.com/activeadmin/activeadmin.git
- revision: f8926831429fe635d26ac8043ea5d676fb6ee637
+ remote: git://github.com/thoughtbot/administrate.git
+ revision: 6bc227907e8567ca9d8c51658abc92fc2b19ca2d
+ branch: v0.7.0
specs:
- activeadmin (1.0.0.pre4)
- arbre (~> 1.0, >= 1.0.2)
- bourbon
- coffee-rails
- formtastic (~> 3.1)
- formtastic_i18n
- inherited_resources (~> 1.6)
- jquery-rails
- jquery-ui-rails
- kaminari (~> 0.15)
- railties (>= 3.2, < 5.1)
- ransack (~> 1.3)
- sass-rails
- sprockets (< 4.1)
+ administrate (0.7.0)
+ actionpack (>= 4.2, < 5.1)
+ actionview (>= 4.2, < 5.1)
+ activerecord (>= 4.2, < 5.1)
+ autoprefixer-rails (~> 6.0)
+ datetime_picker_rails (~> 0.0.7)
+ jquery-rails (>= 4.0)
+ kaminari (>= 1.0)
+ momentjs-rails (~> 2.8)
+ normalize-rails (>= 3.0)
+ sass-rails (~> 5.0)
+ selectize-rails (~> 0.6)
GIT
remote: https://github.com/vyruss/yaml_db.git
@@ -65,9 +64,9 @@
tzinfo (~> 1.1)
addressable (2.4.0)
ansi (1.5.0)
- arbre (1.1.1)
- activesupport (>= 3.0.0)
arel (6.0.3)
+ autoprefixer-rails (6.7.7.2)
+ execjs
bcrypt (3.1.11)
better_errors (2.1.1)
coderay (>= 1.0.0)
@@ -75,9 +74,6 @@
rack (>= 0.9.0)
binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1)
- bourbon (4.2.7)
- sass (~> 3.4)
- thor (~> 0.19)
builder (3.2.2)
byebug (9.0.5)
capybara (2.9.1)
@@ -87,21 +83,7 @@
rack (>= 1.0.0)
rack-test (>= 0.5.4)
xpath (~> 2.0)
- caracal (1.0.8)
- nokogiri (~> 1.6)
- rubyzip (~> 1.1)
- tilt (>= 1.4)
- caracal-rails (1.0.1)
- caracal (~> 1.0)
- rails (>= 3.2)
coderay (1.1.1)
- coffee-rails (4.2.1)
- coffee-script (>= 2.2.0)
- railties (>= 4.0.0, < 5.2.x)
- coffee-script (2.4.1)
- coffee-script-source
- execjs
- coffee-script-source (1.10.0)
commonjs (0.2.7)
concurrent-ruby (1.0.2)
contact_us (1.2.0)
@@ -109,6 +91,8 @@
crack (0.4.3)
safe_yaml (~> 1.0.0)
daemons (1.2.4)
+ datetime_picker_rails (0.0.7)
+ momentjs-rails (>= 2.8.1)
debug_inspector (0.0.2)
devise (4.2.0)
bcrypt (~> 3.0)
@@ -131,22 +115,31 @@
multipart-post (>= 1.2, < 3)
faraday_middleware (0.10.0)
faraday (>= 0.7.4, < 0.10)
+ fast_gettext (1.3.0)
feedjira (2.0.0)
faraday (~> 0.9)
faraday_middleware (~> 0.9)
loofah (~> 2.0)
sax-machine (~> 1.0)
flag_shih_tzu (0.3.15)
+ font-awesome-rails (4.7.0.1)
+ railties (>= 3.2, < 5.1)
formtastic (3.1.4)
actionpack (>= 3.2.13)
- formtastic_i18n (0.6.0)
friendly_id (5.1.0)
activerecord (>= 4.0.0)
+ gettext (3.2.2)
+ locale (>= 2.0.5)
+ text (>= 1.3.0)
+ gettext_i18n_rails (1.8.0)
+ fast_gettext (>= 0.9.0)
+ gettext_i18n_rails_js (1.2.0)
+ gettext (>= 3.0.2)
+ gettext_i18n_rails (>= 0.7.1)
+ po_to_json (>= 1.0.0)
+ rails (>= 3.2.0)
globalid (0.3.7)
activesupport (>= 4.1.0)
- 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)
@@ -156,11 +149,6 @@
i18n (0.7.0)
i18n-js (3.0.0.rc14)
i18n (~> 0.6, >= 0.6.6)
- inherited_resources (1.6.0)
- actionpack (>= 3.2, < 5)
- has_scope (~> 0.6.0.rc)
- railties (>= 3.2, < 5)
- responders
jbuilder (2.6.0)
activesupport (>= 3.0.0, < 5.1)
multi_json (~> 1.2)
@@ -168,13 +156,20 @@
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
- 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)
+ kaminari (1.0.1)
+ activesupport (>= 4.1.0)
+ kaminari-actionview (= 1.0.1)
+ kaminari-activerecord (= 1.0.1)
+ kaminari-core (= 1.0.1)
+ kaminari-actionview (1.0.1)
+ actionview
+ kaminari-core (= 1.0.1)
+ kaminari-activerecord (1.0.1)
+ activerecord
+ kaminari-core (= 1.0.1)
+ kaminari-core (1.0.1)
ledermann-rails-settings (2.4.2)
activerecord (>= 3.1)
less (2.6.0)
@@ -185,6 +180,7 @@
sprockets (> 2, < 4)
tilt
libv8 (3.16.14.15)
+ locale (2.1.2)
loofah (2.0.3)
nokogiri (>= 1.5.9)
mail (2.6.4)
@@ -213,6 +209,8 @@
builder
minitest (>= 5.0)
ruby-progressbar
+ momentjs-rails (2.17.1)
+ railties (>= 3.1)
multi_json (1.12.1)
multi_xml (0.5.5)
multipart-post (2.0.0)
@@ -220,6 +218,7 @@
nokogiri (1.6.8)
mini_portile2 (~> 2.1.0)
pkg-config (~> 1.1.7)
+ normalize-rails (4.1.1)
oauth2 (1.2.0)
faraday (>= 0.8, < 0.10)
jwt (~> 1.0)
@@ -239,8 +238,8 @@
orm_adapter (0.5.0)
pg (0.19.0)
pkg-config (1.1.7)
- polyamorous (1.3.1)
- activerecord (>= 3.0)
+ po_to_json (1.0.1)
+ json (>= 1.6.0)
protected_attributes (1.1.3)
activemodel (>= 4.0.1, < 5.0)
pundit (1.1.0)
@@ -275,13 +274,7 @@
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rake (11.3.0)
- ransack (1.8.2)
- actionpack (>= 3.0)
- activerecord (>= 3.0)
- activesupport (>= 3.0)
- i18n
- polyamorous (~> 1.3)
- recaptcha (3.3.0)
+ recaptcha (4.1.0)
json
redcarpet (3.3.4)
ref (2.0.0)
@@ -299,6 +292,7 @@
sprockets-rails (>= 2.0, < 4.0)
tilt (>= 1.1, < 3)
sax-machine (1.3.2)
+ selectize-rails (0.12.4)
simplecov (0.12.0)
docile (~> 1.1.0)
json (>= 1.8, < 3)
@@ -315,6 +309,7 @@
swagger-docs (0.2.9)
activesupport (>= 3)
rails (>= 3)
+ text (1.3.1)
therubyracer (0.12.2)
libv8 (~> 3.16.14.0)
ref
@@ -357,19 +352,22 @@
ruby
DEPENDENCIES
- activeadmin!
+ administrate!
better_errors
binding_of_caller
byebug
- caracal
- caracal-rails
contact_us (>= 1.2.0)
devise
devise_invitable
dragonfly
feedjira
flag_shih_tzu
+ font-awesome-rails
+ formtastic
friendly_id
+ gettext (>= 3.0.2)
+ gettext_i18n_rails (~> 1.8)
+ gettext_i18n_rails_js (~> 1.2.0)
htmltoword
i18n-js (>= 3.0.0.rc11)
jbuilder
@@ -390,7 +388,7 @@
rack-test
rails (= 4.2.7)
railties
- recaptcha
+ recaptcha (>= 4.0)
redcarpet
responders (~> 2.0)
rolify
@@ -414,4 +412,4 @@
ruby 2.2.2p95
BUNDLED WITH
- 1.13.7
+ 1.14.6
diff --git a/README.md b/README.md
index 88ceaba..0ae2435 100644
--- a/README.md
+++ b/README.md
@@ -10,27 +10,89 @@
4. To allow collaborative work when creating Data Management Plans.
#### Current Release
-v.0.1.0
+Official release coming soon!
[](https://travis-ci.org/DMPRoadmap/roadmap)
#### Summary
-#### Installation and Requirements
-See the [Installation Guide](https://github.com/DMPRoadmap/roadmap/wiki/Installation)
+#### Pre-requisites
+Roadmap is a Ruby on Rails application and you will need to have:
+* Ruby >= 2.2.2
+* Rails >= 4.2
+* MySql >= 5.0 OR PostgreSql
#### 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 database. Select UTF-8 Unicode (utf8) encoding.
+* Clone this repository (or Fork the repository first if you plan on contributing)
+
+> > 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
+
+* Make copies of the example gem initializer files and update the values for your installation
+
+> > 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
+> > cp config/locales/*.static.yml.example config/locales/*.static.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:schema:load
+
+> > rake db:seed (Unless you are migrating data from an old DMPOnline system)
+
+* 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' - 'password123'
#### Troubleshooting
-See the [Troubleshooting Guide](https://github.com/DMPRoadmap/roadmap/wiki/Troubleshooting)
+See the [Troubleshooting Guide](https://github.com/DMPRoadmap/roadmap/wiki/Troubleshooting) on the Wiki
#### 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
-See the [Contributor Guide](https://github.com/DMPRoadmap/roadmap/wiki/Contributing)
+If you would like to contribute to the project. Please follow these steps to submit a contribution:
+* Comment on the Github issue (or create one if one does not exist) and let us know that you're working on it.
+* Fork the project (if you have not already) or rebase your fork so that it is up to date with the current repository's '_**development**_' branch
+* Create a new branch in your fork. This will ensure that you are able to work at your own pace and continue to pull in any updates made to this project.
+* Make your changes in the new branch
+* When you have finished your work, make sure that your version of the '_**development**_' branch is still up to date with this project. Then merge your new branch into your '_**development**_' branch.
+* Then create a new Pull Request (PR) to this project's '_**contributions**_' branch in GitHub
+* The project team will then review your PR and communicate with you to convey any additional changes that would ensure that your work adheres to our guidelines.
+
+See the [Contribution Guide](https://github.com/DMPRoadmap/roadmap/wiki/Contributing) on the Wiki for more details
#### License
The DMP Roadmap project uses the MIT License.
diff --git a/app/admin/dashboard.rb b/app/admin/dashboard.rb
deleted file mode 100644
index 3aa2b89..0000000
--- a/app/admin/dashboard.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# [+Project:+] DMPRoadmap
-# [+Description:+]
-#
-# [+Copyright:+] Digital Curation Centre and University of California Curation Center
-
-
-ActiveAdmin.register_page "Dashboard" do
-
- menu priority: 1, label: proc{ I18n.t("active_admin.dashboard") }
-
- content title: proc{ I18n.t("active_admin.dashboard") } do
- #div class: "blank_slate_container", id: "dashboard_default_message" do
- # span class: "blank_slate" do
- # span I18n.t("active_admin.dashboard_welcome.welcome")
- # small I18n.t("active_admin.dashboard_welcome.call_to_action")
- # end
- #end
-
- # Here is an example of a simple dashboard with columns and panels.
- #
- # columns do
- # column do
- # panel "Recent Posts" do
- # ul do
- # Post.recent(5).map do |post|
- # li link_to(post.title, admin_post_path(post))
- # end
- # end
- # end
- # end
-
- # column do
- # panel "Info" do
- # para "Welcome to ActiveAdmin."
- # end
- # end
- # end
- end # content
-end
\ No newline at end of file
diff --git a/app/admin/guidance.rb b/app/admin/guidance.rb
deleted file mode 100644
index f4400e9..0000000
--- a/app/admin/guidance.rb
+++ /dev/null
@@ -1,81 +0,0 @@
-# [+Project:+] DMPRoadmap
-# [+Description:+]
-#
-# [+Created:+] 03/09/2014
-# [+Copyright:+] Digital Curation Centre and University of California Curation Center
-
-ActiveAdmin.register Guidance do
- permit_params :text, :guidance_group_id, :question_id
-
- menu :priority => 13, :label => proc{ I18n.t('admin.guidance')}, :parent => "Guidance list"
-
- index do
- column (:text) { |guidance| raw(guidance.text) }
- column I18n.t('admin.theme') do |t|
- (t.themes.map{|t_q| link_to t_q.title, [:admin, t_q]}).join(', ').html_safe
- end
-
- column I18n.t('admin.question'), :sortable => :question_id do |que|
- if !que.nil? then
- que.question
- else
- '-'
- end
- end
-
- column I18n.t('admin.guidance_group') do |guidance|
- (guidance.guidance_groups.map{|t_q| link_to t_q.name, [:admin, t_q]}).join(', ').html_safe
- end
- actions
- end
-
- #show details of a question
- show do
- attributes_table do
- row (:text) { |guidance| raw(guidance.text) }
-
- row I18n.t('admin.theme') do
- (guidance.themes.map{|t_q| link_to t_q.title, [:admin, t_q]}).join(', ').html_safe
- end
- row I18n.t('admin.question'), :question_id do |question|
- question.question
- end
- row I18n.t('admin.guidance_group') do |guidance|
- (guidance.guidance_groups.map{|t_q| link_to t_q.name, [:admin, t_q]}).join(', ').html_safe
- end
-
- row :created_at
- row :updated_at
- end
- end
-
- #form
- form do |f|
- f.inputs "Details" do
- f.input :text
- f.input :question_id, :as => :select,
- :collection => Question.order('text').map{|que|[que.text, que.id]}
- f.input :guidance_group_ids, :label => I18n.t('admin.guidance_group'),
- :as => :select,
- :collection => GuidanceGroup.order('name').map{|gui|[gui.name, gui.id]}
-
- end
- f.inputs "Themes" do
- f.input :theme_ids, :label => I18n.t('admin.selected_themes'),
- :as => :select,
- :include_blank => I18n.t('admin.all_themes'),
- :multiple => true,
- :collection => Theme.order('title').map{|the| [the.title, the.id]},
- :hint => I18n.t('admin.choose_themes')
- end
-
- f.actions
- end
-
- controller do
- def permitted_params
- params.permit!
- end
- end
-
-end
diff --git a/app/admin/guidance_group.rb b/app/admin/guidance_group.rb
deleted file mode 100644
index c193af9..0000000
--- a/app/admin/guidance_group.rb
+++ /dev/null
@@ -1,80 +0,0 @@
-# [+Project:+] DMPRoadmap
-# [+Description:+]
-#
-# [+Created:+] 03/09/2014
-# [+Copyright:+] Digital Curation Centre and University of California Curation Center
-
-ActiveAdmin.register GuidanceGroup do
- permit_params :organisation_id, :name, :published, :optional_subset
-
- menu :priority => 2, :label => proc{I18n.t('admin.guidance_group')}, :parent => "Guidance list"
-
- index do
- column I18n.t('admin.name'), :sortable => :name do |ggn|
- link_to ggn.name, [:admin, ggn]
- end
- column I18n.t('admin.org_title'), :sortable => :organisation_id do |org_title|
- link_to org_title.organisation.name, [:admin, org_title.organisation]
- end
- column I18n.t('admin.template') do |t|
- (t.dmptemplates.map{|t_q| link_to t_q.title, [:admin, t_q]}).join(', ').html_safe
- end
-
- actions
- end
-
- #show details of guidance group
- show do
- attributes_table do
- row :name
- row :organisation_id do |org_title|
- link_to org_title.organisation.name, [:admin, org_title.organisation]
- end
- row I18n.t('admin.template') do
- (guidance_group.dmptemplates.map{|t_q| link_to t_q.title, [:admin, t_q]}).join(', ').html_safe
- end
- row :created_at
- row :updated_at
- end
- end
-
- #guidance list
- sidebar I18n.t('admin.guidance'), :only => :show, :if => proc { guidance_group.guidances.count >= 1} do
- table_for guidance_group.guidances.order("text asc") do |guis|
- column :text do |gtext|
- link_to gtext.text.html_safe, [:admin, gtext]
- end
- column I18n.t('admin.theme') do |themelist|
- (themelist.themes.map{|t_q| link_to t_q.title, [:admin, t_q]}).join(', ').html_safe
- end
- end
- end
-
- #form
- form do |f|
- f.inputs "Details" do
- f.input :name
- f.input :organisation_id, :label => I18n.t('admin.org_title'),
- :as => :select,
- :collection => Org.order('name').map{|orgp|[orgp.name, orgp.id]}
- f.input :published
- f.input :optional_subset
- end
-
- f.inputs "Templates" do
- f.input :dmptemplate_ids, :label => I18n.t('admin.selected_templates'),
- :as => :select,
- :include_blank => I18n.t('admin.all_templates'),
- :multiple => true,
- :collection => Dmptemplate.order('title').map{|the| [the.title, the.id]},
- :hint => I18n.t('admin.choose_templates')
- end
- f.actions
- end
-
- controller do
- def permitted_params
- params.permit!
- end
- end
-end
diff --git a/app/admin/language.rb b/app/admin/language.rb
deleted file mode 100644
index 777478c..0000000
--- a/app/admin/language.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# [+Project:+] DMPonline
-# [+Description:+]
-#
-# [+Created:+] 12/08/2016
-# [+Copyright:+] Digital Curation Centre
-
-ActiveAdmin.register Language do
- permit_params :language_id, :name, :abbreviation, :default_language
-
- menu :priority => 10, :label => proc { I18n.t('admin.language') }
-
- index do
- column I18n.t('admin.language_name'), :sortable => :name do |lang|
- link_to lang.name, [:admin, lang]
- end
- column I18n.t('admin.language_abbreviation'), :sortable => :abbreviation do |lang|
- link_to lang.abbreviation, [:admin, lang]
- end
- column I18n.t('admin.language_is_default'), :sortable => :default_language do |lang|
- if lang[:default_language]
- 'Yes'
- else
- 'No'
- end
- end
-
- actions
- end
-
- show do
- attributes_table do
- row :name
- row :abbreviation
- row :default_language
- row :description
- end
- end
-
- controller do
- def permitted_params
- params.permit!
- end
- end
-
-end
\ No newline at end of file
diff --git a/app/admin/option.rb b/app/admin/option.rb
deleted file mode 100644
index cd68f1a..0000000
--- a/app/admin/option.rb
+++ /dev/null
@@ -1,79 +0,0 @@
-# [+Project:+] DMPRoadmap
-# [+Description:+]
-#
-# [+Created:+] 03/09/2014
-# [+Copyright:+] Digital Curation Centre and University of California Curation Center
-
-ActiveAdmin.register QuestionOption do
- permit_params :question_id, :text, :number, :is_default
- menu :priority => 6, :label => proc{I18n.t('admin.multi_options')}, :parent => "Templates management"
-
- index do
- column :text
- column I18n.t('admin.questions'), :sortable => :question_id do |ques|
- if !ques.question_id.nil? then
- link_to ques.question.text, [:admin, ques.question]
- end
- end
- column I18n.t('admin.sections'), :sortable => :question_id do |ques|
- if !ques.question_id.nil? then
- link_to ques.question.section.title, [:admin, ques.question.section]
- end
- end
- column I18n.t('admin.template'), :sortable => :question_id do |ques|
- if !ques.question_id.nil? then
- link_to ques.question.section.version.phase.dmptemplate.title, [:admin, ques.question.section.version.phase.dmptemplate]
- end
- end
-
- actions
- end
-
- #show details of a section
- show do
- attributes_table do
- row :text
- row :number
- row I18n.t('admin.questions'), :question_id do |ques|
- if !ques.question_id.nil? then
- link_to ques.question.text, [:admin, ques.question]
- end
- end
- row I18n.t('admin.sections'), :question_id do |ques|
- if !ques.question_id.nil? then
- link_to ques.question.section.title, [:admin, ques.question.section]
- end
- end
- row I18n.t('admin.template'), :question_id do |ques|
- if !ques.question_id.nil? then
- link_to ques.question.section.version.phase.dmptemplate.title, [:admin, ques.question.section.version.phase.dmptemplate]
- end
- end
- row :is_default
- row :created_at
- row :updated_at
- end
- end
-
-
- #form
- form do |f|
- f.inputs "Details" do
- f.input :text
- f.input :number
- f.input :question,
- :as => :select,
- :collection => Question.order('text').map{ |sec| ["#{truncate(sec.section.version.phase.dmptemplate.title, :lengh => 20)} - #{truncate(sec.section.title, :lengh => 50)} - #{truncate(sec.text, :lengh => 20)}", sec.id] }
- f.input :is_default
- end
-
- f.actions
- end
-
-
- controller do
- def permitted_params
- params.permit!
- end
- end
-end
diff --git a/app/admin/org.rb b/app/admin/org.rb
deleted file mode 100644
index 7d9391b..0000000
--- a/app/admin/org.rb
+++ /dev/null
@@ -1,110 +0,0 @@
-# [+Project:+] DMPRoadmap
-# [+Description:+]
-#
-# [+Created:+] 03/09/2014
-# [+Copyright:+] Digital Curation Centre and University of California Curation Center
-
-ActiveAdmin.register Org do
- permit_params :abbreviation, :banner_file_id, :description, :logo_file_id, :name, :target_url, :organisation_type_id, :wayfless_entity, :parent_id
-
- menu :priority => 14, :label => proc{I18n.t('admin.org')}, :parent => "Organisations management"
-
- index do
- column I18n.t('admin.org_title'), :sortable => :name do |ggn|
- link_to ggn.name, [:admin, ggn]
- end
- column I18n.t('admin.abbrev'), :sortable => :abbreviation do |ggn|
- if !ggn.abbreviation.nil?
- link_to ggn.abbreviation, [:admin, ggn]
- else
- '-'
- end
- end
- column I18n.t('admin.org_type'), :sortable => :organisation_type_id do |org_type|
- if !org_type.organisation_type_id.nil? then
- link_to org_type.organisation_type.name, [:admin, org_type]
- end
- end
-
- actions
- end
-
-
- #show details of an organisation
- show do
- resource.check_api_credentials
- attributes_table do
- row I18n.t('admin.org_title'), :sortable => :name do |gn|
- if !gn.name.nil? then
- link_to gn.name, [:admin, gn]
- end
- end
- row I18n.t('admin.abbrev'), :abbreviation do |ggn|
- if !ggn.abbreviation.nil?
- link_to ggn.abbreviation, [:admin, ggn]
- else
- '-'
- end
- end
- row :sort_name
- row I18n.t('admin.org_type'), :organisation_type_id do |org_type|
- if !org_type.organisation_type_id.nil? then
- link_to org_type.organisation_type.name, [:admin, org_type]
- end
- end
- row :banner_text do |banner|
- if !banner.banner_text.nil? then
- banner.banner_text.html_safe
- end
- end
- # row :target_url
- row :logo_file_name
- row :wayfless_entity
- row I18n.t('admin.token_permission_type') do
- (organisation.token_permission_types.map{|tpt| link_to tpt.token_type, [:admin, tpt]}).join(', ').html_safe
- end
- row :created_at
- row :updated_at
- end
- end
-
- #templates sidebar
- sidebar I18n.t('admin.templates'), :only => :show, :if => proc { organisation.dmptemplates.count >= 1} do
- table_for organisation.dmptemplates.order("title asc") do |temp|
- column :title do |dmptemp|
- link_to dmptemp.title, [:admin, dmptemp]
- end
- column :published
- end
- end
-
- #form
- form do |f|
- f.inputs "Details" do
- f.input :name
- f.input :abbreviation
- f.input :sort_name
- f.input :organisation_type_id, :label => I18n.t('admin.org_type'), :as => :select, :collection => OrganisationType.order('name').map{|orgt|[orgt.name, orgt.id]}
- # f.input :target_url
- f.input :banner_text
- f.input :logo_file_name
- f.input :wayfless_entity
- f.input :token_permission_types, label: I18n.t('admin.token_permission_type'),
- as: :select, multiple: true, include_blank: I18n.t('helpers.none'),
- collection: TokenPermissionType.order(:token_type).map{|token| [token.token_type, token.id]},
- hint: I18n.t('admin.choose_api_permissions')
- # f.input :parent_id, :label => I18n.t('admin.org_parent'), :as => :select, :collection => Org.find(:all, :order => 'name ASC').map{|orgp|[orgp.name, orgp.id]}
- # f.input :stylesheet_file_id
- end
- f.actions
- end
-
-
- controller do
- def permitted_params
- params.permit!
- end
- end
-
-
-end
diff --git a/app/admin/perm.rb b/app/admin/perm.rb
deleted file mode 100644
index 4401e31..0000000
--- a/app/admin/perm.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-# [+Project:+] DMPRoadmap
-# [+Description:+]
-#
-# [+Created:+] 03/09/2014
-# [+Copyright:+] Digital Curation Centre and University of California Curation Center
-
-ActiveAdmin.register Perm do
- permit_params :name
-
- menu :priority => 5, :label => proc{I18n.t('admin.role')}, :parent => "User management"
-
- index do
- column I18n.t('admin.title'), :sortable => :name do |role_name|
- link_to role_name.name, [:admin, role_name]
- end
-
- actions
- end
-
-
- show do
- attributes_table do
- row :name
- row :created_at
- row :updated_at
- end
-
- table_for( (Perm.find(params[:id]).users)) do
- column (:email){|user| link_to user.email, [:admin, user]}
- column (:firstname){|user| user.firstname}
- column (:surname){|user| user.surname}
- column (:last_sign_in_at){|user| user.last_sign_in_at}
- column (I18n.t('admin.org_title')){|user|
- if !user.organisation.nil? then
- if user.other_organisation.nil? || user.other_organisation == "" then
- link_to user.organisation.name, [:admin, user.organisation]
- else
- I18n.t('helpers.org_type.org_name') + ' - ' + user.other_organisation
-
- end
- end
- }
- end
-
- end
-
- form do |f|
- f.inputs "Details" do
- f.input :name
- end
-
- f.actions
- end
-
- controller do
- def permitted_params
- params.permit!
- end
- end
-end
diff --git a/app/admin/phase.rb b/app/admin/phase.rb
deleted file mode 100644
index d7d061e..0000000
--- a/app/admin/phase.rb
+++ /dev/null
@@ -1,83 +0,0 @@
-# [+Project:+] DMPRoadmap
-# [+Description:+]
-#
-# [+Created:+] 03/09/2014
-# [+Copyright:+] Digital Curation Centre and University of California Curation Center
-
-ActiveAdmin.register Phase do
- permit_params :description, :number, :title, :dmptemplate_id
-
- menu :priority => 10, :label => proc{I18n.t('admin.phase')}, :parent => "Templates management"
-
- index do
- column :title, :sortable => :title do |ph|
- if !ph.title.nil? then
- link_to ph.title, [:admin, ph]
- end
- end
- column :number
- column I18n.t('admin.template'), :sortable => :dmptemplate_id do |temp_title|
- if !temp_title.nil? then
- if !temp_title.dmptemplate.nil? then
- link_to temp_title.dmptemplate.title, [:admin, temp_title.dmptemplate]
- else
- "-"
- end
- end
- end
-
- actions
- end
-
- #show details of a phase
- show do
- attributes_table do
- row :title
- row :number
- row :description do |descr|
- if !descr.description.nil? then
- descr.description.html_safe
- end
- end
- row I18n.t('admin.template'), :sortable => :dmptemplate_id do |temp_title|
- link_to temp_title.dmptemplate.title, [:admin, temp_title.dmptemplate]
- end
- row :created_at
- row :updated_at
- end
-
- end
-
- #versions sidebar
- sidebar I18n.t('admin.version'), :only => :show, :if => proc { phase.versions.count >= 1} do
- table_for phase.versions.order("number asc") do |temp_phases|
- column :number
- column :title do |row|
- link_to row.title, [:admin, row]
- end
- column :published
- end
- end
-
-
- #form
- form do |f|
- f.inputs "Details" do
- f.input :title
- f.input :number
- f.input :description
- f.input :dmptemplate_id, :label => I18n.t('admin.template'),
- :as => :select,
- :collection => Dmptemplate.order('title').map{|temp|[temp.title, temp.id]}
-
- end
- f.actions
- end
-
-
- controller do
- def permitted_params
- params.permit!
- end
- end
-end
diff --git a/app/admin/plan.rb b/app/admin/plan.rb
deleted file mode 100644
index 574a7c2..0000000
--- a/app/admin/plan.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# [+Project:+] DMPRoadmap
-# [+Description:+]
-#
-# [+Created:+] 03/09/2014
-# [+Copyright:+] Digital Curation Centre and University of California Curation Center
-
-ActiveAdmin.register Plan do
- permit_params :template_id, :title, :org_id, :unit_id, :guidance_group_ids, :role_ids, :funder_id, :institution_id, :grant_number,:identifier, :description, :principal_investigator, :principal_investigator_identifier, :data_contact
-
- menu :priority => 25, :label => proc{I18n.t('admin.plans')}
-
-
- index do
- column :title
- column I18n.t('admin.org_title'), :sortable => :org_id do |org_title|
- if !org_title.organisation.nil? then
- link_to org_title.organisation.name, [:admin, org_title.organisation]
- else
- '-'
- end
- end
- column I18n.t('admin.template_title'), :sortable => :template_id do |dmptemp|
- if !dmptemp.template.nil? then
- link_to dmptemp.template.title, [:admin, dmptemp.template]
- else
- '-'
- end
- end
-
- actions
- end
-
-
- controller do
- def permitted_params
- params.permit!
- end
- end
-end
diff --git a/app/admin/question.rb b/app/admin/question.rb
deleted file mode 100644
index 45d8e18..0000000
--- a/app/admin/question.rb
+++ /dev/null
@@ -1,101 +0,0 @@
-# [+Project:+] DMPRoadmap
-# [+Description:+]
-#
-# [+Created:+] 03/09/2014
-# [+Copyright:+] Digital Curation Centre and University of California Curation Center
-
-ActiveAdmin.register Question do
- permit_params :default_value, :dependency_id, :dependency_text, :guidance, :number, :suggested_answer, :text, :question_type, :section_id
-
- menu :priority => 7, :label => proc{I18n.t('admin.question')}, :parent => "Templates management"
-
- index do
- column I18n.t('admin.question'), :sortable => :text do |descr|
- if !descr.text.nil? then
- descr.text.html_safe
- end
- end
- column I18n.t('admin.section_title'), :sortable => :section_id do |dmptemplate|
- if !dmptemplate.section_id.nil? then
- link_to dmptemplate.section.title, [:admin, dmptemplate.section]
- end
- end
- column :number, :sortable => :number do |question_n|
- if !question_n.number.nil? then
- question_n.number
- end
- end
- column I18n.t('admin.template_title'), :sortable => true do |dmptemplate|
- if !dmptemplate.section_id.nil? then
- if !dmptemplate.section.version.phase.dmptemplate.nil? then
- link_to dmptemplate.section.version.phase.dmptemplate.title, [:admin, dmptemplate.section.version.phase.dmptemplate]
- else
- "-"
- end
- end
- end
- actions
- end
-
-
- #show details of a question
- show do
- attributes_table do
- row :text do |descr|
- if !descr.text.nil? then
- descr.text.html_safe
- end
- end
- row :section_id do |question|
- link_to question.section.title, [:admin, question.section]
- end
- row :number
- row :default_value
- row I18n.t('admin.question_format') do |format|
- link_to format.question_format.title, [:admin, format.question_format]
- end
- row I18n.t('admin.themes') do
- (question.themes.map{|t_q| link_to t_q.title, [:admin, t_q]}).join(', ').html_safe
- end
- row :created_at
- row :updated_at
-
- end
- end
-
-
- #form
- form do |f|
- f.inputs "Details" do
- f.input :text
- f.input :number
- f.input :section,
- :as => :select,
- :collection => Section.order('title').map{ |sec| ["#{sec.version.phase.dmptemplate.title} - #{sec.title}", sec.id] }
- f.input :default_value
-
- end
- f.inputs "Question Format" do
- f.input :question_format_id, :label => I18n.t('admin.select_question_format'),
- :as => :select,
- :collection => QuestionFormat.order('title').map{|format| [format.title, format.id]}
- end
- f.inputs "Themes" do
- f.input :theme_ids, :label => I18n.t('admin.selected_themes'),
- :as => :select,
- :multiple => true,
- :include_blank => I18n.t('helpers.none'),
- :collection => Theme.order('title').map{|the| [the.title, the.id]} ,
- :hint => I18n.t('admin.choose_themes')
-
- end
- f.actions
- end
-
- controller do
- def permitted_params
- params.permit!
- end
- end
-
-end
diff --git a/app/admin/question_format.rb b/app/admin/question_format.rb
deleted file mode 100644
index a5b9523..0000000
--- a/app/admin/question_format.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# [+Project:+] DMPRoadmap
-# [+Description:+]
-#
-# [+Created:+] 03/09/2014
-# [+Copyright:+] Digital Curation Centre and University of California Curation Center
-
-ActiveAdmin.register QuestionFormat do
- permit_params :description, :title
-
- menu :priority => 5, :label => proc{I18n.t('admin.question_format')}, :parent => "Templates management"
-
- index do
- column I18n.t('admin.question_format'), :sortable => :title do |n|
- link_to n.title, [:admin, n]
- end
-
- actions
- end
-
- # show Template details
- show do
- attributes_table do
- row :title
- row :description do |descr|
- if !descr.description.nil? then
- descr.description.html_safe
- end
- end
- row :created_at
- row :updated_at
- end
- end
-
- controller do
- def permitted_params
- params.permit!
- end
- end
-end
diff --git a/app/admin/role.rb b/app/admin/role.rb
deleted file mode 100644
index 4fcf03b..0000000
--- a/app/admin/role.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# [+Project:+] DMPRoadmap
-# [+Description:+]
-#
-# [+Created:+] 03/09/2014
-# [+Copyright:+] Digital Curation Centre and University of California Curation Center
-
-ActiveAdmin.register Role do
- menu false
-end
diff --git a/app/admin/section.rb b/app/admin/section.rb
deleted file mode 100644
index 4cc6c37..0000000
--- a/app/admin/section.rb
+++ /dev/null
@@ -1,93 +0,0 @@
-# [+Project:+] DMPRoadmap
-# [+Description:+]
-#
-# [+Created:+] 03/09/2014
-# [+Copyright:+] Digital Curation Centre and University of California Curation Center
-
-ActiveAdmin.register Section do
- permit_params :organisation_id, :description, :number, :title, :version_id
-
- menu :priority => 8, :label => proc{I18n.t('admin.section')}, :parent => "Templates management"
-
- filter :title
- filter :organisation
- filter :version
- filter :created_at
- filter :updated_at
-
-
- index do
- column :title , :sortable => :title do |section|
- if !section.title.nil? then
- link_to section.title, [:admin, section]
- end
- end
- column I18n.t('admin.version'), :sortable => :version_id do |version_title|
- if !version_title.version_id.nil? then
- link_to version_title.version.title, [:admin, version_title.version]
- end
- end
- column I18n.t('admin.org_title'), :sortable => :organisation_id do |org_title|
- if !org_title.organisation_id.nil? then
- link_to org_title.organisation.name, [:admin, org_title.organisation]
- end
- end
-
- actions
- end
-
- #show details of a section
- show do
- attributes_table do
- row :title
- row :number
- row :description do |descr|
- if !descr.description.nil? then
- descr.description.html_safe
- end
- end
- row I18n.t('admin.version'), :sortable => :version_id do |version_title|
- if !version_title.version_id.nil? then
- link_to version_title.version.title, [:admin, version_title.version]
- end
- end
- row I18n.t('admin.org_title'), :sortable => :organisation_id do |org_title|
- if !org_title.organisation_id.nil? then
- link_to org_title.organisation.name, [:admin, org_title.organisation]
- end
- end
- row :created_at
- row :updated_at
- end
-
- end
-
-
- #questions sidebar(:default_value, :dependency_id, :dependency_text, :guidance, :number, :parent_id, :suggested_answer, :text, :question_type, :section_id)
- sidebar proc{I18n.t("admin.questions")}, :only => :show, :if => proc { (Question.where("section_id = ?", params[:id])).count >= 1} do
- table_for( Question.where("section_id = ?", params[:id] ).order("number")) do
- column (:number){|question| question.number}
- column (I18n.t("admin.question")){|question| link_to question.text, [:admin, question]}
- end
-
- end
-
- #form
- form do |f|
- f.inputs "Details" do
- f.input :title
- f.input :number
- f.input :version, :collection => Version.all.map{ |ver| [ver.title, ver.id] }
- f.input :organisation, :as => :select, :collection => Org.order('name').map{|orgp|[orgp.name, orgp.id]}
- f.input :description
- end
-
- f.actions
- end
-
- controller do
- def permitted_params
- params.permit!
- end
- end
-end
diff --git a/app/admin/suggested_answer.rb b/app/admin/suggested_answer.rb
deleted file mode 100644
index 9c46eab..0000000
--- a/app/admin/suggested_answer.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# [+Project:+] DMPRoadmap
-# [+Description:+]
-#
-# [+Created:+] 03/09/2014
-# [+Copyright:+] Digital Curation Centre and University of California Curation Center
-
-ActiveAdmin.register SuggestedAnswer do
- permit_params :question_id, :organisation_id
-
- menu :priority => 4, :label => proc{I18n.t('admin.sug_answer')}, :parent => "Templates management"
-
-
- #form
- form do |f|
- f.inputs "Details" do
- f.input :question_id, :label => I18n.t('admin.question'),
- :as => :select,
- :collection => Question.order('text').map{|ques|[ques.text, ques.id]}
- f.input :organisation_id, :label => I18n.t('admin.org_title'),
- :as => :select,
- :collection => Org.order('name').map{|orgp|[orgp.name, orgp.id]}
- f.input :text
- f.input :is_example
- end
- f.actions
- end
-
- controller do
- def permitted_params
- params.permit!
- end
- end
-end
diff --git a/app/admin/template.rb b/app/admin/template.rb
deleted file mode 100644
index 2f2695b..0000000
--- a/app/admin/template.rb
+++ /dev/null
@@ -1,125 +0,0 @@
-# [+Project:+] DMPRoadmap
-# [+Description:+]
-#
-# [+Created:+] 03/09/2014
-# [+Copyright:+] Digital Curation Centre and University of California Curation Center
-
-ActiveAdmin.register Template do
- permit_params :title, :description, :organisation_id, :published, :is_default
-
- menu :priority => 11, :label => proc{ I18n.t('admin.template')}, :parent => "Templates management"
-
- # FIXME: The below member_actions only work on :export settings.
- member_action :settings do
- @template = resource
- @settings = resource.settings(:export)
- end
-
- member_action :update_settings, method: :put do
- new_settings = params[:settings][:export]
-
- settings = resource.settings(:export).tap do |s|
- s.formatting, s.max_pages = if params[:commit] != 'Reset'
- [
- new_settings[:formatting].try(:deep_symbolize_keys),
- new_settings[:max_pages].try(:to_i)
- ]
- else
- [ nil, nil ]
- end
- end
-
- if settings.save
- redirect_to(action: :show, flash: { notice: I18n.t('admin.settings_updated') })
- else
- settings.formatting = nil
- @template = resource
- @settings = settings
- render(action: :settings)
- end
- end
-
- action_item(:edit) do
- link_to(I18n.t('helpers.settings.title'), settings_admin_template_path(resource.id))
- end
-
- index do
- column :title do |dmptemp|
- link_to dmptemp.title, [:admin, dmptemp]
- end
- column :description do |descr|
- if !descr.description.nil? then
- descr.description.html_safe
- end
- end
- column I18n.t('admin.org_title'), :sortable => :organisation_id do |org_title|
- if !org_title.organisation.nil? then
- link_to org_title.organisation.name, [:admin, org_title.organisation]
- else
- '-'
- end
- end
- column :published
- column :is_default
-
- actions defaults: true do |template|
- link_to(I18n.t('helpers.settings.title'), settings_admin_template_path(template.id))
- end
- end
-
-
- # show Template details
- show do
- attributes_table do
- row :title
- row :description do |descr|
- if !descr.description.nil? then
- descr.description.html_safe
- end
- end
- row I18n.t('admin.org_title'), :sortable => :organisation_id do |org_title|
- if !org_title.organisation.nil? then
- link_to org_title.organisation.name, [:admin, org_title.organisation]
- else
- '-'
- end
- end
- row :published
- row :is_default
- row :created_at
- row :updated_at
- end
- end
-
- #phases sidebar
- sidebar I18n.t('admin.phases'), :only => :show, :if => proc { template.phases.count >= 1} do
- table_for template.phases.order("number asc") do |temp_phases|
- column :number
- column :title do |row|
- link_to row.title, [:admin, row]
- end
- end
- end
-
- #form
- form do |f|
- f.inputs "Details" do
- f.input :title
- f.input :description
- f.input :organisation_id, :label => I18n.t('admin.org_title'),
- :as => :select,
- :collection => Org.order('name').map{|orgp|[orgp.name, orgp.id]}
- f.input :published
- f.input :is_default
- end
- f.actions
- end
-
- controller do
- def permitted_params
- params.permit!
- end
- end
-
-end
-
diff --git a/app/admin/theme.rb b/app/admin/theme.rb
deleted file mode 100644
index 913f32e..0000000
--- a/app/admin/theme.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-# [+Project:+] DMPRoadmap
-# [+Description:+]
-#
-# [+Created:+] 03/09/2014
-# [+Copyright:+] Digital Curation Centre and University of California Curation Center
-
-ActiveAdmin.register Theme do
- permit_params :description, :title, :locale
-
- menu :priority => 12, :label => "Themes"
-
- index do
- column :title , :sortable => :title do |theme|
- link_to theme.title, [:admin, theme]
- end
- column :description do |descr|
- if !descr.description.nil? then
- descr.description.html_safe
- end
- end
-
- actions
- end
-
- #show details of a theme
- show do
- attributes_table do
- row :title
- row :description
- row :created_at
- row :updated_at
- end
-
- table_for( (Theme.find(params[:id]).questions).order('number')) do
- column (:number){|question| question.number}
- column (I18n.t("admin.question")){|question| link_to question.text, [:admin, question]}
- column (I18n.t("admin.template")){|question|
- if !question.section.nil? then
- if !question.section.version.nil? then
- if !question.section.version.phase.nil? then
- if !question.section.version.phase.dmptemplate.nil? then
- link_to question.section.version.phase.dmptemplate.title, [:admin, question.section.version.phase.dmptemplate]
- else
- I18n.t('admin.no_template')
- end
- else
- I18n.t('admin.no_phase')
- end
- else
- I18n.t('admin.no_version')
- end
- else
- I18n.t('admin.no_section')
- end
- }
- end
- end
-
-
-
- #form
- form do |f|
- f.inputs "Details" do
- f.input :title
- f.input :description
- end
- f.actions
- end
-
-
- controller do
- def permitted_params
- params.permit!
- end
- end
-
-end
diff --git a/app/admin/token_permission_type.rb b/app/admin/token_permission_type.rb
deleted file mode 100644
index 5c804e8..0000000
--- a/app/admin/token_permission_type.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-ActiveAdmin.register TokenPermissionType do
- permit_params :token_type, :text_description
-
- menu priority: 40, label: proc{ I18n.t('admin.token_permission_type')}, parent: "Api"
-
- # TODO: Find better fix for the undefined method xxx_id_eq
- remove_filter :org_token_permissions
-
- index do
- column I18n.t('admin.token_permission_type'), sortable: :token_type do |n|
- link_to n.token_type, [:admin, n]
- end
- column I18n.t('admin.permission_description') do |n|
- link_to n.text_description, [:admin, n]
- end
-
- actions
- end
-
- show do
- attributes_table do
- row :token_type
- row :text_description
- end
- end
-
- controller do
- def permitted_params
- params.permit!
- end
- end
-
-end
diff --git a/app/admin/user.rb b/app/admin/user.rb
deleted file mode 100644
index 1456f53..0000000
--- a/app/admin/user.rb
+++ /dev/null
@@ -1,99 +0,0 @@
-# [+Project:+] DMPRoadmap
-# [+Description:+]
-#
-# [+Created:+] 03/09/2014
-# [+Copyright:+] Digital Curation Centre and University of California Curation Center
-
-ActiveAdmin.register User do
- permit_params :api_token, :password_confirmation, :encrypted_password, :remember_me, :id, :email, :firstname, :orcid_id, :shibboleth_id, :user_status_id, :surname, :user_type_id, :organisation_id, :skip_invitation, :other_organisation, :accept_terms, :role_ids
-
- menu :priority => 15, :label => proc{ I18n.t('admin.user')}, :parent => "User management"
-
- filter :firstname
- filter :surname
- filter :email
- filter :organisation
- filter :created_at
- filter :updated_at
-
-
-
- index do
-
- column I18n.t('admin.user_name'), :sortable => :email do |user_email|
- link_to user_email.email, [:admin, user_email]
- end
- column I18n.t('admin.firstname'), :sortable => :firstname do |use_first|
- link_to use_first.firstname, [:admin, use_first]
- end
- column I18n.t('admin.surname'), :sortable => :surname do |user|
- link_to user.surname, [:admin, user]
- end
- column I18n.t('admin.last_logged_in'), :last_sign_in_at
-
- column I18n.t('admin.org_title'), :sortable => 'organisation.name' do |org_title|
- if !org_title.organisation.nil? then
- link_to org_title.organisation.name, [:admin, org_title.organisation]
- end
- end
-
- actions
- end
-
- show do
- attributes_table do
- row :firstname
- row :surname
- row :email
- row :orcid_id
- row I18n.t('admin.org_title'), :organisation_id do |org_title|
- if !org_title.organisation_id.nil? then
- link_to org_title.organisation.name, [:admin, org_title.organisation]
- end
- end
- row :other_organisation
- row I18n.t('admin.user_role') do
- (user.roles.map{|ro| link_to ro.name, [:admin, ro]}).join(', ').html_safe
- end
- # row :shibboleth_id
- row :last_sign_in_at
- row :sign_in_count
- row :api_token
-
- end
- end
-
-
- form do |f|
- f.inputs "Details" do
- f.input :firstname
- f.input :surname
- f.input :email
- f.input :orcid_id
- f.input :api_token
- # f.input :shibboleth_id
- f.input :organisation_id, :label => I18n.t('admin.org_title'),
- :as => :select,
- :collection => Org.order('name').map{|orgp|[orgp.name, orgp.id]}
- f.input :other_organisation
- f.input :role_ids, :label => I18n.t('admin.user_role'),
- :as => :select,
- :multiple => true,
- :include_blank => I18n.t('helpers.none'),
- :collection => Role.order('name').map{|ro| [ro.name, ro.id]}
- end
-
- f.actions
- end
-
-
-
- controller do
-
- def permitted_params
- params.permit!
- end
-
- end
-
-end
diff --git a/app/controllers/admin/annotations_controller.rb b/app/controllers/admin/annotations_controller.rb
new file mode 100644
index 0000000..f0881d1
--- /dev/null
+++ b/app/controllers/admin/annotations_controller.rb
@@ -0,0 +1,21 @@
+module Admin
+ class AnnotationsController < Admin::ApplicationController
+ # To customize the behavior of this controller,
+ # you can overwrite any of the RESTful actions. For example:
+ #
+ # def index
+ # super
+ # @resources = Annotation.
+ # page(params[:page]).
+ # per(10)
+ # end
+
+ # Define a custom finder by overriding the `find_resource` method:
+ # def find_resource(param)
+ # Annotation.find_by!(slug: param)
+ # end
+
+ # See https://administrate-prototype.herokuapp.com/customizing_controller_actions
+ # for more information
+ end
+end
diff --git a/app/controllers/admin/answers_controller.rb b/app/controllers/admin/answers_controller.rb
new file mode 100644
index 0000000..8960f9f
--- /dev/null
+++ b/app/controllers/admin/answers_controller.rb
@@ -0,0 +1,21 @@
+module Admin
+ class AnswersController < Admin::ApplicationController
+ # To customize the behavior of this controller,
+ # you can overwrite any of the RESTful actions. For example:
+ #
+ # def index
+ # super
+ # @resources = Answer.
+ # page(params[:page]).
+ # per(10)
+ # end
+
+ # Define a custom finder by overriding the `find_resource` method:
+ # def find_resource(param)
+ # Answer.find_by!(slug: param)
+ # end
+
+ # See https://administrate-prototype.herokuapp.com/customizing_controller_actions
+ # for more information
+ end
+end
diff --git a/app/controllers/admin/application_controller.rb b/app/controllers/admin/application_controller.rb
new file mode 100644
index 0000000..0018efc
--- /dev/null
+++ b/app/controllers/admin/application_controller.rb
@@ -0,0 +1,25 @@
+# All Administrate controllers inherit from this `Admin::ApplicationController`,
+# making it the ideal place to put authentication logic or other
+# before_actions.
+#
+# If you want to add pagination or other controller-level concerns,
+# you're free to overwrite the RESTful controller actions.
+module Admin
+ class ApplicationController < Administrate::ApplicationController
+ before_action :authenticate_admin
+
+ protect_from_forgery with: :exception
+ include Pundit
+ rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
+
+ def authenticate_admin
+ redirect_to root_path unless user_signed_in? && current_user.can_super_admin?
+ end
+
+ # Override this value to specify the number of elements to display at a time
+ # on index pages. Defaults to 20.
+ # def records_per_page
+ # params[:per_page] || 20
+ # end
+ end
+end
diff --git a/app/controllers/admin/exported_plans_controller.rb b/app/controllers/admin/exported_plans_controller.rb
new file mode 100644
index 0000000..e4bde90
--- /dev/null
+++ b/app/controllers/admin/exported_plans_controller.rb
@@ -0,0 +1,21 @@
+module Admin
+ class ExportedPlansController < Admin::ApplicationController
+ # To customize the behavior of this controller,
+ # you can overwrite any of the RESTful actions. For example:
+ #
+ # def index
+ # super
+ # @resources = ExportedPlan.
+ # page(params[:page]).
+ # per(10)
+ # end
+
+ # Define a custom finder by overriding the `find_resource` method:
+ # def find_resource(param)
+ # ExportedPlan.find_by!(slug: param)
+ # end
+
+ # See https://administrate-prototype.herokuapp.com/customizing_controller_actions
+ # for more information
+ end
+end
diff --git a/app/controllers/admin/guidance_groups_controller.rb b/app/controllers/admin/guidance_groups_controller.rb
new file mode 100644
index 0000000..95d3e7c
--- /dev/null
+++ b/app/controllers/admin/guidance_groups_controller.rb
@@ -0,0 +1,21 @@
+module Admin
+ class GuidanceGroupsController < Admin::ApplicationController
+ # To customize the behavior of this controller,
+ # you can overwrite any of the RESTful actions. For example:
+ #
+ # def index
+ # super
+ # @resources = GuidanceGroup.
+ # page(params[:page]).
+ # per(10)
+ # end
+
+ # Define a custom finder by overriding the `find_resource` method:
+ # def find_resource(param)
+ # GuidanceGroup.find_by!(slug: param)
+ # end
+
+ # See https://administrate-prototype.herokuapp.com/customizing_controller_actions
+ # for more information
+ end
+end
diff --git a/app/controllers/admin/guidances_controller.rb b/app/controllers/admin/guidances_controller.rb
new file mode 100644
index 0000000..1f2495f
--- /dev/null
+++ b/app/controllers/admin/guidances_controller.rb
@@ -0,0 +1,21 @@
+module Admin
+ class GuidancesController < Admin::ApplicationController
+ # To customize the behavior of this controller,
+ # you can overwrite any of the RESTful actions. For example:
+ #
+ # def index
+ # super
+ # @resources = Guidance.
+ # page(params[:page]).
+ # per(10)
+ # end
+
+ # Define a custom finder by overriding the `find_resource` method:
+ # def find_resource(param)
+ # Guidance.find_by!(slug: param)
+ # end
+
+ # See https://administrate-prototype.herokuapp.com/customizing_controller_actions
+ # for more information
+ end
+end
diff --git a/app/controllers/admin/identifier_schemes_controller.rb b/app/controllers/admin/identifier_schemes_controller.rb
new file mode 100644
index 0000000..eb50d8a
--- /dev/null
+++ b/app/controllers/admin/identifier_schemes_controller.rb
@@ -0,0 +1,21 @@
+module Admin
+ class IdentifierSchemesController < Admin::ApplicationController
+ # To customize the behavior of this controller,
+ # you can overwrite any of the RESTful actions. For example:
+ #
+ # def index
+ # super
+ # @resources = IdentifierScheme.
+ # page(params[:page]).
+ # per(10)
+ # end
+
+ # Define a custom finder by overriding the `find_resource` method:
+ # def find_resource(param)
+ # IdentifierScheme.find_by!(slug: param)
+ # end
+
+ # See https://administrate-prototype.herokuapp.com/customizing_controller_actions
+ # for more information
+ end
+end
diff --git a/app/controllers/admin/languages_controller.rb b/app/controllers/admin/languages_controller.rb
new file mode 100644
index 0000000..e58baa9
--- /dev/null
+++ b/app/controllers/admin/languages_controller.rb
@@ -0,0 +1,21 @@
+module Admin
+ class LanguagesController < Admin::ApplicationController
+ # To customize the behavior of this controller,
+ # you can overwrite any of the RESTful actions. For example:
+ #
+ # def index
+ # super
+ # @resources = Language.
+ # page(params[:page]).
+ # per(10)
+ # end
+
+ # Define a custom finder by overriding the `find_resource` method:
+ # def find_resource(param)
+ # Language.find_by!(slug: param)
+ # end
+
+ # See https://administrate-prototype.herokuapp.com/customizing_controller_actions
+ # for more information
+ end
+end
diff --git a/app/controllers/admin/notes_controller.rb b/app/controllers/admin/notes_controller.rb
new file mode 100644
index 0000000..db832f4
--- /dev/null
+++ b/app/controllers/admin/notes_controller.rb
@@ -0,0 +1,21 @@
+module Admin
+ class NotesController < Admin::ApplicationController
+ # To customize the behavior of this controller,
+ # you can overwrite any of the RESTful actions. For example:
+ #
+ # def index
+ # super
+ # @resources = Note.
+ # page(params[:page]).
+ # per(10)
+ # end
+
+ # Define a custom finder by overriding the `find_resource` method:
+ # def find_resource(param)
+ # Note.find_by!(slug: param)
+ # end
+
+ # See https://administrate-prototype.herokuapp.com/customizing_controller_actions
+ # for more information
+ end
+end
diff --git a/app/controllers/admin/orgs_controller.rb b/app/controllers/admin/orgs_controller.rb
new file mode 100644
index 0000000..d68f358
--- /dev/null
+++ b/app/controllers/admin/orgs_controller.rb
@@ -0,0 +1,21 @@
+module Admin
+ class OrgsController < Admin::ApplicationController
+ # To customize the behavior of this controller,
+ # you can overwrite any of the RESTful actions. For example:
+ #
+ # def index
+ # super
+ # @resources = Org.
+ # page(params[:page]).
+ # per(10)
+ # end
+
+ # Define a custom finder by overriding the `find_resource` method:
+ # def find_resource(param)
+ # Org.find_by!(slug: param)
+ # end
+
+ # See https://administrate-prototype.herokuapp.com/customizing_controller_actions
+ # for more information
+ end
+end
diff --git a/app/controllers/admin/perms_controller.rb b/app/controllers/admin/perms_controller.rb
new file mode 100644
index 0000000..99e9b95
--- /dev/null
+++ b/app/controllers/admin/perms_controller.rb
@@ -0,0 +1,21 @@
+module Admin
+ class PermsController < Admin::ApplicationController
+ # To customize the behavior of this controller,
+ # you can overwrite any of the RESTful actions. For example:
+ #
+ # def index
+ # super
+ # @resources = Perm.
+ # page(params[:page]).
+ # per(10)
+ # end
+
+ # Define a custom finder by overriding the `find_resource` method:
+ # def find_resource(param)
+ # Perm.find_by!(slug: param)
+ # end
+
+ # See https://administrate-prototype.herokuapp.com/customizing_controller_actions
+ # for more information
+ end
+end
diff --git a/app/controllers/admin/phases_controller.rb b/app/controllers/admin/phases_controller.rb
new file mode 100644
index 0000000..de6e3c3
--- /dev/null
+++ b/app/controllers/admin/phases_controller.rb
@@ -0,0 +1,21 @@
+module Admin
+ class PhasesController < Admin::ApplicationController
+ # To customize the behavior of this controller,
+ # you can overwrite any of the RESTful actions. For example:
+ #
+ # def index
+ # super
+ # @resources = Phase.
+ # page(params[:page]).
+ # per(10)
+ # end
+
+ # Define a custom finder by overriding the `find_resource` method:
+ # def find_resource(param)
+ # Phase.find_by!(slug: param)
+ # end
+
+ # See https://administrate-prototype.herokuapp.com/customizing_controller_actions
+ # for more information
+ end
+end
diff --git a/app/controllers/admin/plan_guidance_groups_controller.rb b/app/controllers/admin/plan_guidance_groups_controller.rb
new file mode 100644
index 0000000..0eeb458
--- /dev/null
+++ b/app/controllers/admin/plan_guidance_groups_controller.rb
@@ -0,0 +1,21 @@
+module Admin
+ class PlanGuidanceGroupsController < Admin::ApplicationController
+ # To customize the behavior of this controller,
+ # simply overwrite any of the RESTful actions. For example:
+ #
+ # def index
+ # super
+ # @resources = PlanGuidanceGroup.
+ # page(params[:page]).
+ # per(10)
+ # end
+
+ # Define a custom finder by overriding the `find_resource` method:
+ # def find_resource(param)
+ # PlanGuidanceGroup.find_by!(slug: param)
+ # end
+
+ # See https://administrate-prototype.herokuapp.com/customizing_controller_actions
+ # for more information
+ end
+end
diff --git a/app/controllers/admin/plans_controller.rb b/app/controllers/admin/plans_controller.rb
new file mode 100644
index 0000000..424389f
--- /dev/null
+++ b/app/controllers/admin/plans_controller.rb
@@ -0,0 +1,21 @@
+module Admin
+ class PlansController < Admin::ApplicationController
+ # To customize the behavior of this controller,
+ # you can overwrite any of the RESTful actions. For example:
+ #
+ # def index
+ # super
+ # @resources = Plan.
+ # page(params[:page]).
+ # per(10)
+ # end
+
+ # Define a custom finder by overriding the `find_resource` method:
+ # def find_resource(param)
+ # Plan.find_by!(slug: param)
+ # end
+
+ # See https://administrate-prototype.herokuapp.com/customizing_controller_actions
+ # for more information
+ end
+end
diff --git a/app/controllers/admin/question_formats_controller.rb b/app/controllers/admin/question_formats_controller.rb
new file mode 100644
index 0000000..1338b69
--- /dev/null
+++ b/app/controllers/admin/question_formats_controller.rb
@@ -0,0 +1,21 @@
+module Admin
+ class QuestionFormatsController < Admin::ApplicationController
+ # To customize the behavior of this controller,
+ # you can overwrite any of the RESTful actions. For example:
+ #
+ # def index
+ # super
+ # @resources = QuestionFormat.
+ # page(params[:page]).
+ # per(10)
+ # end
+
+ # Define a custom finder by overriding the `find_resource` method:
+ # def find_resource(param)
+ # QuestionFormat.find_by!(slug: param)
+ # end
+
+ # See https://administrate-prototype.herokuapp.com/customizing_controller_actions
+ # for more information
+ end
+end
diff --git a/app/controllers/admin/question_options_controller.rb b/app/controllers/admin/question_options_controller.rb
new file mode 100644
index 0000000..103e543
--- /dev/null
+++ b/app/controllers/admin/question_options_controller.rb
@@ -0,0 +1,21 @@
+module Admin
+ class QuestionOptionsController < Admin::ApplicationController
+ # To customize the behavior of this controller,
+ # you can overwrite any of the RESTful actions. For example:
+ #
+ # def index
+ # super
+ # @resources = QuestionOption.
+ # page(params[:page]).
+ # per(10)
+ # end
+
+ # Define a custom finder by overriding the `find_resource` method:
+ # def find_resource(param)
+ # QuestionOption.find_by!(slug: param)
+ # end
+
+ # See https://administrate-prototype.herokuapp.com/customizing_controller_actions
+ # for more information
+ end
+end
diff --git a/app/controllers/admin/questions_controller.rb b/app/controllers/admin/questions_controller.rb
new file mode 100644
index 0000000..be5d2a7
--- /dev/null
+++ b/app/controllers/admin/questions_controller.rb
@@ -0,0 +1,21 @@
+module Admin
+ class QuestionsController < Admin::ApplicationController
+ # To customize the behavior of this controller,
+ # you can overwrite any of the RESTful actions. For example:
+ #
+ # def index
+ # super
+ # @resources = Question.
+ # page(params[:page]).
+ # per(10)
+ # end
+
+ # Define a custom finder by overriding the `find_resource` method:
+ # def find_resource(param)
+ # Question.find_by!(slug: param)
+ # end
+
+ # See https://administrate-prototype.herokuapp.com/customizing_controller_actions
+ # for more information
+ end
+end
diff --git a/app/controllers/admin/regions_controller.rb b/app/controllers/admin/regions_controller.rb
new file mode 100644
index 0000000..6e5627b
--- /dev/null
+++ b/app/controllers/admin/regions_controller.rb
@@ -0,0 +1,21 @@
+module Admin
+ class RegionsController < Admin::ApplicationController
+ # To customize the behavior of this controller,
+ # you can overwrite any of the RESTful actions. For example:
+ #
+ # def index
+ # super
+ # @resources = Region.
+ # page(params[:page]).
+ # per(10)
+ # end
+
+ # Define a custom finder by overriding the `find_resource` method:
+ # def find_resource(param)
+ # Region.find_by!(slug: param)
+ # end
+
+ # See https://administrate-prototype.herokuapp.com/customizing_controller_actions
+ # for more information
+ end
+end
diff --git a/app/controllers/admin/roles_controller.rb b/app/controllers/admin/roles_controller.rb
new file mode 100644
index 0000000..748c165
--- /dev/null
+++ b/app/controllers/admin/roles_controller.rb
@@ -0,0 +1,21 @@
+module Admin
+ class RolesController < Admin::ApplicationController
+ # To customize the behavior of this controller,
+ # you can overwrite any of the RESTful actions. For example:
+ #
+ # def index
+ # super
+ # @resources = Role.
+ # page(params[:page]).
+ # per(10)
+ # end
+
+ # Define a custom finder by overriding the `find_resource` method:
+ # def find_resource(param)
+ # Role.find_by!(slug: param)
+ # end
+
+ # See https://administrate-prototype.herokuapp.com/customizing_controller_actions
+ # for more information
+ end
+end
diff --git a/app/controllers/admin/sections_controller.rb b/app/controllers/admin/sections_controller.rb
new file mode 100644
index 0000000..3b94a0a
--- /dev/null
+++ b/app/controllers/admin/sections_controller.rb
@@ -0,0 +1,21 @@
+module Admin
+ class SectionsController < Admin::ApplicationController
+ # To customize the behavior of this controller,
+ # you can overwrite any of the RESTful actions. For example:
+ #
+ # def index
+ # super
+ # @resources = Section.
+ # page(params[:page]).
+ # per(10)
+ # end
+
+ # Define a custom finder by overriding the `find_resource` method:
+ # def find_resource(param)
+ # Section.find_by!(slug: param)
+ # end
+
+ # See https://administrate-prototype.herokuapp.com/customizing_controller_actions
+ # for more information
+ end
+end
diff --git a/app/controllers/admin/splash_logs_controller.rb b/app/controllers/admin/splash_logs_controller.rb
new file mode 100644
index 0000000..aa3fa22
--- /dev/null
+++ b/app/controllers/admin/splash_logs_controller.rb
@@ -0,0 +1,21 @@
+module Admin
+ class SplashLogsController < Admin::ApplicationController
+ # To customize the behavior of this controller,
+ # you can overwrite any of the RESTful actions. For example:
+ #
+ # def index
+ # super
+ # @resources = SplashLog.
+ # page(params[:page]).
+ # per(10)
+ # end
+
+ # Define a custom finder by overriding the `find_resource` method:
+ # def find_resource(param)
+ # SplashLog.find_by!(slug: param)
+ # end
+
+ # See https://administrate-prototype.herokuapp.com/customizing_controller_actions
+ # for more information
+ end
+end
diff --git a/app/controllers/admin/templates_controller.rb b/app/controllers/admin/templates_controller.rb
new file mode 100644
index 0000000..8ac79e1
--- /dev/null
+++ b/app/controllers/admin/templates_controller.rb
@@ -0,0 +1,21 @@
+module Admin
+ class TemplatesController < Admin::ApplicationController
+ # To customize the behavior of this controller,
+ # you can overwrite any of the RESTful actions. For example:
+ #
+ # def index
+ # super
+ # @resources = Template.
+ # page(params[:page]).
+ # per(10)
+ # end
+
+ # Define a custom finder by overriding the `find_resource` method:
+ # def find_resource(param)
+ # Template.find_by!(slug: param)
+ # end
+
+ # See https://administrate-prototype.herokuapp.com/customizing_controller_actions
+ # for more information
+ end
+end
diff --git a/app/controllers/admin/themes_controller.rb b/app/controllers/admin/themes_controller.rb
new file mode 100644
index 0000000..9617c6c
--- /dev/null
+++ b/app/controllers/admin/themes_controller.rb
@@ -0,0 +1,21 @@
+module Admin
+ class ThemesController < Admin::ApplicationController
+ # To customize the behavior of this controller,
+ # you can overwrite any of the RESTful actions. For example:
+ #
+ # def index
+ # super
+ # @resources = Theme.
+ # page(params[:page]).
+ # per(10)
+ # end
+
+ # Define a custom finder by overriding the `find_resource` method:
+ # def find_resource(param)
+ # Theme.find_by!(slug: param)
+ # end
+
+ # See https://administrate-prototype.herokuapp.com/customizing_controller_actions
+ # for more information
+ end
+end
diff --git a/app/controllers/admin/token_permission_types_controller.rb b/app/controllers/admin/token_permission_types_controller.rb
new file mode 100644
index 0000000..37b3487
--- /dev/null
+++ b/app/controllers/admin/token_permission_types_controller.rb
@@ -0,0 +1,21 @@
+module Admin
+ class TokenPermissionTypesController < Admin::ApplicationController
+ # To customize the behavior of this controller,
+ # you can overwrite any of the RESTful actions. For example:
+ #
+ # def index
+ # super
+ # @resources = TokenPermissionType.
+ # page(params[:page]).
+ # per(10)
+ # end
+
+ # Define a custom finder by overriding the `find_resource` method:
+ # def find_resource(param)
+ # TokenPermissionType.find_by!(slug: param)
+ # end
+
+ # See https://administrate-prototype.herokuapp.com/customizing_controller_actions
+ # for more information
+ end
+end
diff --git a/app/controllers/admin/user_identifiers_controller.rb b/app/controllers/admin/user_identifiers_controller.rb
new file mode 100644
index 0000000..bdf5faa
--- /dev/null
+++ b/app/controllers/admin/user_identifiers_controller.rb
@@ -0,0 +1,21 @@
+module Admin
+ class UserIdentifiersController < Admin::ApplicationController
+ # To customize the behavior of this controller,
+ # you can overwrite any of the RESTful actions. For example:
+ #
+ # def index
+ # super
+ # @resources = UserIdentifier.
+ # page(params[:page]).
+ # per(10)
+ # end
+
+ # Define a custom finder by overriding the `find_resource` method:
+ # def find_resource(param)
+ # UserIdentifier.find_by!(slug: param)
+ # end
+
+ # See https://administrate-prototype.herokuapp.com/customizing_controller_actions
+ # for more information
+ end
+end
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
new file mode 100644
index 0000000..70251c0
--- /dev/null
+++ b/app/controllers/admin/users_controller.rb
@@ -0,0 +1,21 @@
+module Admin
+ class UsersController < Admin::ApplicationController
+ # To customize the behavior of this controller,
+ # you can overwrite any of the RESTful actions. For example:
+ #
+ # def index
+ # super
+ # @resources = User.
+ # page(params[:page]).
+ # per(10)
+ # end
+
+ # Define a custom finder by overriding the `find_resource` method:
+ # def find_resource(param)
+ # User.find_by!(slug: param)
+ # end
+
+ # See https://administrate-prototype.herokuapp.com/customizing_controller_actions
+ # for more information
+ end
+end
diff --git a/app/controllers/annotations_controller.rb b/app/controllers/annotations_controller.rb
new file mode 100644
index 0000000..e83366b
--- /dev/null
+++ b/app/controllers/annotations_controller.rb
@@ -0,0 +1,116 @@
+class AnnotationsController < ApplicationController
+ respond_to :html
+ after_action :verify_authorized
+
+ #create annotations
+ def admin_create
+ # authorize the question (includes to reduce queries)
+ @question = Question.includes(section: { phase: :template}).find(params[:question_id])
+ authorize @question
+ if params[:example_answer_text].present?
+ example_answer = init_annotation(params[:example_answer_text], @question, current_user.org, Annotation.types[:example_answer])
+ end
+ if params[:guidance_text].present?
+ guidance = init_annotation(params[:guidance_text], @question, current_user.org, Annotation.types[:guidance])
+ end
+ # if they dont exist, no requirement for them to be saved
+ ex_save = example_answer.present? ? example_answer.save : true
+ guid_save = guidance.present? ? guidance.save : true
+
+ if ex_save && guid_save
+ redirect_to admin_show_phase_path(id: @question.section.phase_id, section_id: @question.section_id, question_id: @question.id, edit: 'true'), notice: _('Information was successfully created.')
+ else
+ @section = @question.section
+ @phase = @section.phase
+ @open = true
+ @sections = @phase.sections
+ @section_id = @section.id
+ @question_id = @example_answer.question
+ if !ex_save && !guid_save
+ flash[:notice] = failed_create_error(example_answer, _('example answer')) + '\n' +
+ failed_create_error(gudiance, _('guidance'))
+ elsif !guid_save
+ flash[:notice] = failed_create_error(gudiance, _('guidance'))
+ elsif !ex_save
+ flash[:notice] = failed_create_error(example_answer, _('example answer'))
+ end
+ render "phases/admin_show"
+ end
+ end
+
+
+ #update a example answer of a template
+ def admin_update
+ @question = Question.includes(section: { phase: :template}).find(params[:question_id])
+ if params[:guidance_id].present?
+ guidance = Annotation.includes(question: {section: {phase: :template}}).find(params[:guidance_id])
+ authorize guidance
+ end
+ if params[:example_answer_id].present?
+ example_answer = Annotation.includes(question: {section: {phase: :template}}).find(params[:example_answer_id])
+ authorize example_answer
+ end
+ verify_authorized
+ # if guidance present, update
+ if params[:guidance_text].present?
+ if guidance.present?
+ guidance.text = params[:guidance_text]
+ else
+ guidance = init_annotation(params[:guidance_text], @question, current_user.org, Annotation.types[:guidance])
+ end
+ end
+ # if example answer present, update
+ if params[:example_answer_text].present?
+ if example_answer.present?
+ example_answer.text = params[:example_answer_text]
+ else
+ example_answer = init_annotation(params[:example_answer_text], @question, current_user.org, Annotation.types[:example_answer])
+ end
+ end
+ # only required to save if we updated/created one
+ ex_save = example_answer.present? ? example_answer.save : true
+ guid_save = guidance.present? ? guidance.save : true
+
+ @section = @question.section
+ @phase = @section.phase
+ if ex_save && guid_save
+ redirect_to admin_show_phase_path(id: @phase.id, section_id: @section.id, question_id: @question.id, edit: 'true'), notice: _('Information was successfully updated.')
+ else
+ if !ex_save && !guid_save
+ flash[:notice] = failed_create_error(example_answer, _('example answer')) + '\n' +
+ failed_create_error(gudiance, _('guidance'))
+ elsif !guid_save
+ flash[:notice] = failed_create_error(gudiance, _('guidance'))
+ elsif !ex_save
+ flash[:notice] = failed_create_error(example_answer, _('example answer'))
+ end
+ render action: "phases/admin_show"
+ end
+ end
+
+ #delete an annotation
+ def admin_destroy
+ @example_answer = Annotation.includes(question: { section: {phase: :template}}).find(params[:id])
+ authorize @example_answer
+ @question = @example_answer.question
+ @section = @question.section
+ @phase = @section.phase
+ if @example_answer.destroy
+ redirect_to admin_show_phase_path(id: @phase.id, section_id: @section.id, edit: 'true'), notice: _('Information was successfully deleted.')
+ else
+ redirect_to admin_show_phase_path(id: @phase.id, section_id: @section.id, edit: 'true'), notice: flash[:notice] = failed_destroy_error(@example_answer, _('example answer'))
+ end
+ end
+
+ private
+
+ def init_annotation(text, question, org, type)
+ annotation = Annotation.new
+ annotation.org = org
+ annotation.question = question
+ annotation.text = text
+ annotation.type = type
+ return annotation
+ end
+
+end
\ No newline at end of file
diff --git a/app/controllers/answers_controller.rb b/app/controllers/answers_controller.rb
index 8ef2500..7d48ddf 100644
--- a/app/controllers/answers_controller.rb
+++ b/app/controllers/answers_controller.rb
@@ -2,49 +2,54 @@
after_action :verify_authorized
respond_to :html
- ##
- # PUT/PATCH /[:locale]/answer/[:id]
+ # PUT/PATCH /answers/[:id]
def update
- # create a new answer based off the passed params
-
- ans_params = params[:answer]
- plan_id = ans_params[:plan_id]
- user_id = ans_params[:user_id]
- question_id = ans_params[:question_id]
- @answer = Answer.find_by(
- plan_id: plan_id,
- user_id: user_id,
- question_id: question_id)
- if @answer.nil?
- @answer = Answer.new(params[:answer])
+ p_params = permitted_params()
+ @answer = Answer.find_by({plan_id: p_params[:plan_id], question_id: p_params[:question_id], })
+ begin
+ if @answer
+ authorize @answer
+ @answer.update(p_params)
+ if p_params[:question_option_ids].present?
+ @answer.touch() # Saves the record with the updated_at set to the current time. Needed if only answer.question_options is updated
+ end
+ else
+ @answer = Answer.new(p_params)
+ @answer.lock_version = 1
+ authorize @answer
+ @answer.save() # NOTE, there is a chance to create multiple answer associated for a plan/question (IF any concurrent thread) INSERTS an answer after checking the existence of an answer (Line 8)
+ # In order to avoid that edge-case, it is recommended to create answers whenever a new plan is created (e.g. after_create callback)
+ end
+ rescue ActiveRecord::StaleObjectError
+ @stale_answer = @answer
+ @answer = Answer.find_by({plan_id: p_params[:plan_id], question_id: p_params[:question_id]})
end
+
+ @plan = Plan.includes({
+ sections: {
+ questions: [
+ :answers,
+ :question_format
+ ]
+ }
+ }).find(p_params[:plan_id])
+ @question = @answer.question
+ @section = @plan.get_section(@question.section_id)
- authorize @answer
+ respond_to do |format|
+ format.js {}
+ end
+ end # End update
-puts params.inspect
-
- @answer.text = params["answer-text-#{@answer.question_id}".to_sym]
-
- #TODO: check for optimistic locking
-
- # Is this validation necessary?
-# if (@answer.question.question_format.title == I18n.t("helpers.checkbox") ||
-# @answer.question.question_format.title == I18n.t("helpers.multi_select_box") ||
-# @answer.question.question_format.title == I18n.t("helpers.radio_buttons") ||
-# @answer.question.question_format.title == I18n.t("helpers.dropdown")) then
-# if (old_answer.nil? && @answer.option_ids.count > 0) || ((!old_answer.nil?) && (old_answer.option_ids - @answer.option_ids).count != 0 && (@answer.option_ids - old_answer.option_ids).count != 0) then
-# proceed = true
-# end
-# end
-
-# if proceed
- if @answer.save
- redirect_to :back, status: :found, notice: I18n.t('helpers.project.answer_recorded')
- else
- redirect_to :back, notice: I18n.t('helpers.project.answer_error')
- end
-# else
-# redirect_to :back, notice: I18n.t('helpers.project.answer_no_change')
-# end
- end
+ private
+ def permitted_params
+ permitted = params.require(:answer).permit(:id, :text, :plan_id, :user_id, :question_id, :lock_version, :question_option_ids => [])
+ if !params[:answer][:question_option_ids].nil? && !permitted[:question_option_ids].present? #If question_option_ids has been filtered out because it was a scalar value (e.g. radiobutton answer)
+ permitted[:question_option_ids] = [params[:answer][:question_option_ids]] # then convert to an Array
+ end
+ if !permitted[:id].present?
+ permitted.delete(:id)
+ end
+ return permitted
+ end # End permitted_params
end
diff --git a/app/controllers/api/v0/base_controller.rb b/app/controllers/api/v0/base_controller.rb
index 631983e..c8edddd 100644
--- a/app/controllers/api/v0/base_controller.rb
+++ b/app/controllers/api/v0/base_controller.rb
@@ -117,31 +117,9 @@
def render_bad_credentials
self.headers['WWW-Authenticate'] = "Token realm=\"\""
- render json: I18n.t("api.bad_credentials"), status: 401
+ render json: _("Bad Credentials"), status: 401
end
- def has_auth (auth_type)
- #auth = false
- # not sure if initial if is necissary, but it works with it there... refactor later?
- # if !TokenPermission.where(api_token: @token).nil?
- # TokenPermission.where(api_token: @token).find_each do |permission|
- # if permission.token_permission_type.token_type == auth_type
- # auth = true
- # logger.info "we have auth"
- # end
- # end
- # end
-
- #OrgTokenPermission.where(org_id: @user.org_id).find_each do |org_token_permission|
- # logger.debug "#{org_token_permission.token_permission_type.token_type}"
- # if org_token_permission.token_permission_type.token_type == auth_type
- # auth= true
- # end
- #end
- #return auth
- tpt = TokenPermissionType.find_by(token_type: auth)
- org.token_permission_types.include?(tpt)
- end
end
end
diff --git a/app/controllers/api/v0/guidance_groups_controller.rb b/app/controllers/api/v0/guidance_groups_controller.rb
index d300b39..65899b9 100644
--- a/app/controllers/api/v0/guidance_groups_controller.rb
+++ b/app/controllers/api/v0/guidance_groups_controller.rb
@@ -2,29 +2,16 @@
module V0
class GuidanceGroupsController < Api::V0::BaseController
before_action :authenticate
-
- def show
- # check if the user has permission to use the guidances api
- 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
- else
- render json: I18n.t("api.bad_resource"), status: 401
- end
- else
- render json: I18n.t("api.no_auth_for_endpoint"), status: 401
- end
- end
+ #after_action :verify_authorized
def index
- if has_auth(constant("token_permission_types.guidances"))
- @all_viewable_groups = GuidanceGroup.all_viewable(@user)
- respond_with @all_viewable_groups
- else
- #render unauthorised
- render json: I18n.t("api.no_auth_for_endpoint"), status: 401
- end
+ raise Pundit::NotAuthorizedError unless Api::V0::GuidanceGroupPolicy.new(@user, :guidance_group).index?
+ @all_viewable_groups = GuidanceGroup.all_viewable(@user)
+ respond_with @all_viewable_groups
+ end
+
+ def pundit_user
+ return @user
end
diff --git a/app/controllers/api/v0/guidances_controller.rb b/app/controllers/api/v0/guidances_controller.rb
deleted file mode 100644
index 2803ea6..0000000
--- a/app/controllers/api/v0/guidances_controller.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-module Api
- module V0
- class GuidancesController < Api::V0::BaseController
- before_action :authenticate
-
- swagger_controller :guidances, 'Guidances'
-
- swagger_api :show do
- summary 'Returns a single guidance item'
- notes 'Notes...'
- param :path, :id, :integer, :required, "Guidance Id"
- param :header, 'Authentication-Token', :string, :required, 'Authentication-Token'
- response :ok, "success", :Guidance
- response :unauthorized
- response :not_found
- end
-
- # TODO: impliment auth on show/index
- # for both, first validate that the user has the permission to use this api
- # then for show, display iff they have permissions for that resource
- # for index, compile the list of all groups they have permissions to view, then return
-
- def show
- # ensure use has auth for guidances api
- if has_auth("guidance")
- if Guidance.can_view?(@user, params[:id])
- respond_with get_resource
- else
- render json: I18n.t("api.bad_resource"), status: 401
- end
- else
- render I18n.t("api.no_auth_for_endpoint"), status: 401
- end
- end
-
- swagger_api :index do
- summary 'Returns a list of all viewable guidances'
- notes 'Notes...'
- param :header, 'Authentication-Token', :string, :required, 'Authentication-Token'
- response :unauthorized
- end
-
- def index
- if has_auth("guidance")
- @all_viewable_guidances = Guidance.all_viewable(@user)
- respond_with @all_viewable_guidances
- else
- render json I18n.t("api.no_auth_for_endpoint"), status: 401
- end
- end
-
-
- private
- def query_params
- params.permit(:id)
- end
- end
- end
-end
diff --git a/app/controllers/api/v0/plans_controller.rb b/app/controllers/api/v0/plans_controller.rb
index c96d174..23ae557 100644
--- a/app/controllers/api/v0/plans_controller.rb
+++ b/app/controllers/api/v0/plans_controller.rb
@@ -1,104 +1,48 @@
module Api
module V0
- class ProjectsController < Api::V0::BaseController
+ class PlansController < Api::V0::BaseController
before_action :authenticate
- swagger_controller :projects, 'Plans'
-
- swagger_api :create do |api|
- summary 'Returns a single guidance group item'
- notes 'Notes...'
- param :header, 'Authentication-Token', :string, :required, 'Authentication-Token'
- response :unauthorized
- response :not_found
- end
-
##
- # Creates a new project based on the information passed in JSON to the API
+ # Creates a new plan based on the information passed in JSON to the API
def create
- # find the user's api_token permissions
- # then ensure that they have the permission associated with creating plans
- if has_auth(constant("api_endpoint_types.plans"))
- #params[:organization_id] = Org.where(name: params[:template][:organization])
- # find_by returns nil if none found, find_by! raises an ActiveRecord error
- org = Org.find_by name: params[:template][:organisation]
-
- # if organization exists
- if !org.nil?
- # if organization is funder
- if org.funder?
- # if organization has only 1 template
- if org.templates.length == 1
- # set template id
- template = org.templates.first
- # else if params.template.name specified && params.template.name == one of organization's tempates
- elsif !org.templates.find_by title: params[:template][:name].nil?
- # set template id
- template = org.templates.find_by title: params[:template][:name]
- # else error: organization has more than one template and template name unspecified
- else
- render json: I18n.t("api.org_multiple_templates"), status: 400 and return
- end
- # else error: organization specified is not a funder
- else
- render json: I18n.t("api.org_not_funder"), status: 400 and return
- end
- # else error: organization does not exist
- else
- render json: I18n.t("api.org_dosent_exist"), status: 400 and return
- end
+ @template = Template.live(params[:template_id])
+ raise Pundit::NotAuthorizedError unless Api::V0::PlansPolicy.new(@user, @template).create?
- all_groups = []
- # Check to see if the user specified guidances
- if !params[:guidance].nil?
- # for each specified guidance, see if it exists
- params[:guidance][:name].each do |guidance_name|
- group = GuidanceGroup.find_by(name: guidance_name)
- # if it exists, add it to the guidances for the new project
- if !group.nil?
- all_groups = all_groups + [group]
- end
- end
- end
+ plan_user = User.find_by(email: params[:plan][:email])
+ # ensure user exists
+ if plan_user.blank?
+ User.invite!({email: params[:plan][:email]}, ( @user))
+ plan_user = User.find_by(email: params[:plan][:email])
+ plan_user.org = @user.org
+ plan_user.save
+ end
+ # ensure user's organisation is the same as api user's
+ raise Pundit::NotAuthorizedError, _("user must be in your organisation") unless plan_user.org == @user.org
- # cant invite a user without having a current user because of devise :ivitable
- # after we have auth, will be able to assign an :invited_by_id
- user = User.find_by email: params[:project][:email]
- # if user does not exist
- if user.nil?
- # invite user to DMPRoadmap
- User.invite!({email: params[:project][:email]}, ( @user))
- # set project owner to user associated w/email
- user = (User.find_by email: params[:project][:email])
- end
-
- # create new project with specified parameters
- @project = Plan.new
- @project.title = params[:project][:title]
- @project.template = template
- @project.slug = params[:project][:title]
- #@project.organisation = @user.organisations.first
- @project.assign_creator(user.id)
- @project.guidance_groups = all_groups
-
- # if save successful, render success, otherwise show error
- if @project.save
- #render json: @project ,status: :created
- render :show, status: :created
- else
- render json: get_resource.errors, status: :unprocessable_entity
- end
+ # initialize the plan
+ @plan = Plan.new
+ @plan.principal_investigator = plan_user.surname.blank? ? nil : "#{plan_user.firstname} #{plan_user.surname}"
+ @plan.data_contact = plan_user.email
+ # set funder name to template's org, or original template's org
+ if @template.customization_of.nil?
+ @plan.funder_name = @template.org.name
else
-
- render json: I18n.t("api.no_auth_for_endpoint"), status: 400 and return
+ @plan.funder_name = Template.where(dmptemplate_id: @template.customization_of).first.org.name
+ end
+ @plan.template = @template
+ @plan.title = params[:plan][:title]
+ if @plan.save
+ @plan.assign_creator(plan_user)
+ respond_with @plan
+ else
+ # the plan did not save
+ self.headers['WWW-Authenticate'] = "Token realm=\"\""
+ render json: _("Bad Parameters"), status: 400
end
end
- # private
- # def project_params
- # params.require(:template).permit(:organisation, :name)
- # params.require(:project).permit(:title, :email)
- # end
+
end
end
end
diff --git a/app/controllers/api/v0/statistics_controller.rb b/app/controllers/api/v0/statistics_controller.rb
index a09bec3..b3b95a4 100644
--- a/app/controllers/api/v0/statistics_controller.rb
+++ b/app/controllers/api/v0/statistics_controller.rb
@@ -8,19 +8,16 @@
# @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("token_permission_types.statistics"))
- users = restrict_date_range(@user.org.users)
- confirmed_users = []
- users.each do |user|
- unless user.confirmed_at.blank?
- confirmed_users += [user]
- end
+ raise Pundit::NotAuthorizedError unless Api::V0::StatisticsPolicy.new(@user, :statistics).users_joined?
+ users = restrict_date_range(@user.org.users)
+ confirmed_users = []
+ users.each do |user|
+ unless user.confirmed_at.blank?
+ confirmed_users += [user]
end
- @users_count = confirmed_users.count
- respond_with @users_count
- else
- render json: I18n.t("api.no_auth_for_endpoint"), status: 401
end
+ @users_count = confirmed_users.count
+ respond_with @users_count
end
@@ -29,17 +26,26 @@
# @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("token_permission_types.statistics"))
- template = Dmptemplate.find(params[:id])
- if template.org == @user.org
- @template_count = restrict_date_range(template.plans).count
- respond_with @template_count
+ org_templates = @user.org.templates.where(customization_of: nil)
+ raise Pundit::NotAuthorizedError unless Api::V0::StatisticsPolicy.new(@user, org_templates.first).using_template?
+ @templates = {}
+ org_templates.each do |template|
+ if @templates[template.title].blank?
+ @templates[template.title] = {}
+ @templates[template.title][:title] = template.title
+ @templates[template.title][:id] = template.dmptemplate_id
+ if template.plans.present?
+ @templates[template.title][:uses] = restrict_date_range(template.plans).length
+ else
+ @templates[template.title][:uses] = 0
+ end
else
- #no auth to view statistics for this template
+ if template.plans.present?
+ @templates[template.title][:uses] += restrict_date_range(template.plans).length
+ end
end
- else
- render json: I18n.t("api.no_auth_for_endpoint"), status: 401
end
+ respond_with @templates
end
##
@@ -48,20 +54,29 @@
# 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("token_permission_types.statistics"))
- @org_projects = []
- @user.org.users.each do |user|
- user.plans.each do |plan|
- unless @org_projects.include? plan
- @org_projects += [plan]
- end
+ raise Pundit::NotAuthorizedError unless Api::V0::StatisticsPolicy.new(@user, :statistics).plans_by_template?
+ org_projects = []
+ @user.org.users.each do |user|
+ user.plans.each do |plan|
+ unless org_projects.include? plan
+ org_projects += [plan]
end
end
- @org_projects = restrict_date_range(@org_projects)
- respond_with @org_projects
- else
- render json: I18n.t("api.no_auth_for_endpoint"), status: 401
end
+ org_projects = restrict_date_range(org_projects)
+ @templates = {}
+ org_projects.each do |plan|
+ # if hash exists
+ if @templates[plan.template.title].blank?
+ @templates[plan.template.title] = {}
+ @templates[plan.template.title][:title] = plan.template.title
+ @templates[plan.template.title][:id] = plan.template.dmptemplate_id
+ @templates[plan.template.title][:uses] = 1
+ else
+ @templates[plan.template.title][:uses] += 1
+ end
+ end
+ respond_with @templates
end
##
@@ -70,20 +85,17 @@
# 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("token_permission_types.statistics"))
- @org_projects = []
- @user.org.users.each do |user|
- user.plans.each do |plan|
- unless @org_projects.include? plan
- @org_projects += [plan]
- end
+ raise Pundit::NotAuthorizedError unless Api::V0::StatisticsPolicy.new(@user, :statistics).plans?
+ @org_plans = []
+ @user.org.users.each do |user|
+ user.plans.each do |plan|
+ unless @org_plans.include? plan
+ @org_plans += [plan]
end
end
- @org_projects = restrict_date_range(@org_projects)
- respond_with @org_projects
- else
- render json: I18n.t("api.no_auth_for_endpoint"), status: 401
end
+ @org_plans = restrict_date_range(@org_plans)
+ respond_with @org_plans
end
diff --git a/app/controllers/api/v0/templates_controller.rb b/app/controllers/api/v0/templates_controller.rb
index 3ab1207..8560068 100644
--- a/app/controllers/api/v0/templates_controller.rb
+++ b/app/controllers/api/v0/templates_controller.rb
@@ -9,26 +9,39 @@
# @return a list of templates ordered by organisation
def index
# check if the user has permissions to use the templates API
- if has_auth(constant("api_endpoint_types.templates"))
- @org_templates = {}
- published_templates = Template.includes(:org).where(customization_of: nil, published: true).order(:org_id, :version)
- published_templates.all.each do |temp|
- if @org_templates[temp.org].present?
- if @org_templates[temp.org][temp.dmptemplate_id].nil?
- @org_templates[temp.org][temp.dmptemplate_id] = temp
- end
- else
- @org_templates[temp.org] = {}
- @org_templates[temp.org][temp.dmptemplate_id] = temp
- end
- end
- respond_with @org_templates
- else
- #render unauthorised
- render json: I18n.t("api.no_auth_for_endpoint"), status: 401
- end
+ raise Pundit::NotAuthorizedError unless Api::V0::TemplatePolicy.new(@user, :guidance_group).index?
- end
+ @org_templates = {}
+
+ published_templates = Template.includes(:org).valid.where(customization_of: nil, published: true).order(:org_id, :version)
+ customized_templates = Template.includes(:org).valid.where(org_id: @user.org_id, published: true).where.not(customization_of: nil)
+
+ published_templates.each do |temp|
+ if @org_templates[temp.org].present?
+ if @org_templates[temp.org][:own][temp.dmptemplate_id].nil?
+ @org_templates[temp.org][:own][temp.dmptemplate_id] = temp
+ end
+ else
+ @org_templates[temp.org] = {}
+ @org_templates[temp.org][:own] = {}
+ @org_templates[temp.org][:cust] = {}
+ @org_templates[temp.org][:own][temp.dmptemplate_id] = temp
+ end
+ end
+ customized_templates.each do |temp|
+ if @org_templates[temp.org].present?
+ if @org_templates[temp.org][:cust][temp.dmptemplate_id].nil?
+ @org_templates[temp.org][:cust][temp.dmptemplate_id] = temp
+ end
+ else
+ @org_templates[temp.org] = {}
+ @org_templates[temp.org][:own] = {}
+ @org_templates[temp.org][:cust] = {}
+ @org_templates[temp.org][:cust][temp.dmptemplate_id] = temp
+ end
+ end
+ respond_with @org_templates
+ end
end
end
end
\ No newline at end of file
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index a02811c..2d3dcb0 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -8,44 +8,42 @@
include Pundit
helper_method GlobalHelpers.instance_methods
- # Override build_footer method in ActiveAdmin::Views::Pages
- require 'active_admin_views_pages_base.rb'
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
def user_not_authorized
- redirect_to root_url, alert: I18n.t('unauthorized')
+ if user_signed_in?
+ redirect_to plans_url, notice: _('You are not authorized to perform this action.')
+ else
+ redirect_to root_url, alert: _('You need to sign in or sign up before continuing.')
+ end
end
before_filter :set_gettext_locale
after_filter :store_location
+ # Sets FastGettext locale for every request made
def set_gettext_locale
- if params[:locale] and FastGettext.default_available_locales.include?(params[:locale])
- FastGettext.locale = params[:locale]
- elsif user_signed_in? and !current_user[:language_id].nil?
- FastGettext.locale = Language.find_by_id(current_user[:language_id]).abbreviation #Relies on successful db call
- elsif user_signed_in? and current_user.org.present? and !current_user.org[:language_id].nil?
- FastGettext.locale = Language.find_by_id(current_user.org[:language_id]).abbreviation #Relies on successful db call
- else
- FastGettext.locale = FastGettext.default_locale
- end
- puts 'FastGettext.locale = '+FastGettext.locale
+ FastGettext.locale = session[:locale] || FastGettext.default_locale
end
- # Added setting for passing local params across pages
- def default_url_options(options = {})
- { locale: I18n.locale }.merge options
+ # PATCH /locale/:locale REST method
+ def set_locale_session
+ if FastGettext.default_available_locales.include?(params[:locale])
+ session[:locale] = params[:locale]
+ end
+ redirect_to(request.referer || root_path) #redirects the user to URL where she/he was when the request to this resource was made or root if none is encountered
end
def store_location
# store last url - this is needed for post-login redirect to whatever the user last visited.
- if (request.fullpath != "/users/sign_in" && \
- request.fullpath != "/users/sign_up" && \
- request.fullpath != "/users/password" && \
- request.fullpath != "/users/sign_up?nosplash=true" && \
- !request.xhr?) # don't store ajax calls
+ unless ["/users/sign_in",
+ "/users/sign_up",
+ "/users/password",
+ "/users/invitation/accept",
+ ].any? { |ur| request.fullpath.include?(ur) } \
+ or request.xhr? # don't store ajax calls
session[:previous_url] = request.fullpath
end
end
@@ -71,23 +69,16 @@
redirect_to root_path unless user_signed_in? && (current_user.can_add_orgs? || current_user.can_change_org? || current_user.can_super_admin?)
end
- def get_plan_list_columns
- if user_signed_in?
- @selected_columns = current_user.settings(:plan_list).columns
+ def failed_create_error(obj, obj_name)
+ "#{_('Could not create your %{o}.') % {o: obj_name}} #{errors_to_s(obj)}"
+ end
- # handle settings saved and stored using an older version of the settings gem
- if @selected_columns.kind_of? Hash
- unless @selected_columns['elements'].nil?
- @selected_columns = @selected_columns['elements'].collect{|k,v| puts "#{k} - #{v}"; k}
- end
- end
-
- # If the settings are missing or stored in the wrong format for some reason
- # then use the defaults columns
- @selected_columns = Settings::PlanList::DEFAULT_COLUMNS if @selected_columns.empty?
-
- @all_columns = Settings::PlanList::ALL_COLUMNS
- end
+ def failed_update_error(obj, obj_name)
+ "#{_('Could not update your %{o}.') % {o: obj_name}} #{errors_to_s(obj)}"
+ end
+
+ def failed_destroy_error(obj, obj_name)
+ "#{_('Could not delete the %{o}.') % {o: obj_name}} #{errors_to_s(obj)}"
end
private
@@ -101,4 +92,32 @@
def prepend_view_paths
prepend_view_path "app/views/branded"
end
+
+ def errors_to_s(obj)
+ if obj.errors.count > 0
+ msg = " "
+ obj.errors.each do |e,m|
+ if m.include?('empty') || m.include?('blank')
+ msg += "#{_(e)} - #{_(m)} "
+ else
+ msg += "'#{obj[e]}' - #{_(m)} "
+ end
+ end
+ msg
+ end
+ end
+
+ ##
+ # Sign out of Shibboleth SP local session too.
+ # -------------------------------------------------------------
+ def after_sign_out_path_for(resource_or_scope)
+ if Rails.application.config.shibboleth_enabled
+ return Rails.application.config.shibboleth_logout_url + root_url
+ super
+ else
+ super
+ end
+ end
+ # -------------------------------------------------------------
+
end
diff --git a/app/controllers/confirmations_controller.rb b/app/controllers/confirmations_controller.rb
deleted file mode 100644
index 8070b25..0000000
--- a/app/controllers/confirmations_controller.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-class ConfirmationsController < Devise::ConfirmationsController
-
- protected
-
- def after_confirmation_path_for(resource_name, resource)
- root_path
- end
-
-end
\ No newline at end of file
diff --git a/app/controllers/contacts_controller.rb b/app/controllers/contacts_controller.rb
deleted file mode 100644
index 36fa10f..0000000
--- a/app/controllers/contacts_controller.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-class ContactsController < ContactUs::ContactsController
- respond_to :html
-
- ##
- # create
- #
- # POST - Create a Contact Request
- def create
- @contact = ContactUs::Contact.new(params[:contact_us_contact])
- if (!user_signed_in?)
- if verify_recaptcha(message: "You have not added the validation words correctly") && @contact.save
- flash[:notice] = t('contact_us.notices.success')
- redirect_to(root_path)
- else # recaptcha invalid or contact failed to save
- flash[:alert] = t('contact_us.notices.error')
- render_new_page
- end
- else # no user signed in
- if @contact.save
- flash[:notice] = t('contact_us.notices.success')
- redirect_to :controller => 'projects', :action => 'index'
- else # contact failed to save
- flash[:alert] = t('contact_us.notices.error')
- render_new_page
- end
- end
- end
-end
\ No newline at end of file
diff --git a/app/controllers/guidance_groups_controller.rb b/app/controllers/guidance_groups_controller.rb
index 3729dd7..ce09688 100644
--- a/app/controllers/guidance_groups_controller.rb
+++ b/app/controllers/guidance_groups_controller.rb
@@ -9,11 +9,11 @@
end
- # GET add new guidance groups
- def admin_new
+ # GET add new guidance groups
+ def admin_new
@guidance_group = GuidanceGroup.new
authorize @guidance_group
- end
+ end
# POST /guidance_groups
@@ -27,45 +27,48 @@
end
if @guidance_group.save
- redirect_to admin_index_guidance_path, notice: I18n.t('org_admin.guidance_group.created_message')
+ redirect_to admin_index_guidance_path, notice: _('Guidance group was successfully created.')
else
- render action: "new"
+ flash[:notice] = failed_create_error(@guidance_group, _('guidance group'))
+ render 'admin_new'
end
end
# GET /guidance_groups/1/edit
def admin_edit
- @guidance_group = GuidanceGroup.find(params[:id])
- authorize @guidance_group
+ @guidance_group = GuidanceGroup.find(params[:id])
+ authorize @guidance_group
end
# PUT /guidance_groups/1
def admin_update
- @guidance_group = GuidanceGroup.find(params[:id])
+ @guidance_group = GuidanceGroup.find(params[:id])
authorize @guidance_group
@guidance_group.org_id = current_user.org_id
+ @guidance_group.published = true unless params[:save_publish].nil?
if @guidance_group.update_attributes(params[:guidance_group])
- redirect_to admin_index_guidance_path(params[:guidance_group]), notice: I18n.t('org_admin.guidance_group.updated_message')
+ redirect_to admin_index_guidance_path(params[:guidance_group]), notice: _('Guidance group was successfully updated.')
else
- render action: "edit"
+ flash[:notice] = failed_update_error(@guidance_group, _('guidance group'))
+ render 'admin_edit'
end
end
-
+# TODO: This does not have a route in config/routes.rb and is unreachable!
# PUT /guidance_groups/1
def admin_update_publish
- @guidance_group = GuidanceGroup.find(params[:id])
+ @guidance_group = GuidanceGroup.find(params[:id])
authorize @guidance_group
@guidance_group.org.id = current_user.org.id
@guidance_group.published = true
if @guidance_group.update_attributes(params[:guidance_group])
- redirect_to admin_index_guidance_path(params[:guidance_group]), notice: I18n.t('org_admin.guidance_group.updated_message')
+ redirect_to admin_index_guidance_path(params[:guidance_group]), notice: _('Guidance group was successfully updated.')
else
- render action: "edit"
+ redirect_to admin_index_guidance_path(@guidance_group), notice: failed_update_error(@guidance_group, _('guidance group'))
end
end
@@ -73,11 +76,13 @@
# DELETE /guidance_groups/1
# DELETE /guidance_groups/1.json
def admin_destroy
- @guidance_group = GuidanceGroup.find(params[:id])
+ @guidance_group = GuidanceGroup.find(params[:id])
authorize @guidance_group
- @guidance_group.destroy
-
- redirect_to admin_index_guidance_path, notice: I18n.t('org_admin.guidance_group.destroyed_message')
- end
+ if @guidance_group.destroy
+ redirect_to admin_index_guidance_path, notice: _('Guidance group was successfully deleted.')
+ else
+ redirect_to admin_index_guidance_path, notice: failed_destroy_error(@guidance_group, _('guidance group'))
+ end
+ end
end
\ No newline at end of file
diff --git a/app/controllers/guidances_controller.rb b/app/controllers/guidances_controller.rb
index 75c0808..9cfcfc5 100644
--- a/app/controllers/guidances_controller.rb
+++ b/app/controllers/guidances_controller.rb
@@ -13,112 +13,45 @@
##
# GET /guidances/1
def admin_show
- @guidance = Guidance.includes(:guidance_group, :question, :themes).find(params[:id])
+ @guidance = Guidance.eager_load(:guidance_group, :themes).find(params[:id])
authorize @guidance
end
def admin_new
@guidance = Guidance.new
authorize @guidance
-
- #@templates = Template.funders_and_own_templates(current_user.org_id)
- # Replacing weird accessor on Template
- @templates = (Org.funders.collect{|o| o.templates } + current_user.org.templates).flatten
-
- @phases = nil
- @templates.includes(:phases).each do |template|
- if @phases.nil? then
- @phases = template.phases.all.order('number')
- else
- @phases = @phases + template.phases.all.order('number')
- end
- end
- @sections = nil
- @phases.each do |phase|
- if @sections.nil? then
- @sections = phase.sections.all.order('number')
- else
- @sections = @sections + phase.sections.all.order('number')
- end
- end
- @questions = nil
- @sections.each do |section|
- if @questions.nil? then
- @questions = section.questions.all.order('number')
- else
- @questions = @questions + section.questions.all.order('number')
- end
- end
@themes = Theme.all.order('title')
@guidance_groups = GuidanceGroup.where(org_id: current_user.org_id).order('name ASC')
end
- #setup variables for use in the dynamic updating
- def update_phases
- authorize Guidance
- # updates phases, versions, sections and questions based on template selected
- dmptemplate = Template.find(params[:dmptemplate_id])
- # map to title and id for use in our options_for_select
- @phases = dmptemplate.phases.map{|a| [a.title, a.id]}.insert(0, I18n.t('helpers.select_phase'))
- @versions = dmptemplate.versions.map{|s| [s.title, s.id]}.insert(0, I18n.t('helpers.select_version'))
- @sections = dmptemplate.sections.map{|s| [s.title, s.id]}.insert(0, I18n.t('helpers.select_section'))
- @questions = dmptemplate.questions.map{|s| [s.text, s.id]}.insert(0, I18n.t('helpers.select_question'))
- end
-
- def update_versions
- authorize Guidance
- # updates versions, sections and questions based on phase selected
- phase = Phase.find(params[:phase_id])
- # map to name and id for use in our options_for_select
- @versions = phase.versions.map{|s| [s.title, s.id]}.insert(0, I18n.t('helpers.select_version'))
- @sections = phase.sections.map{|s| [s.title, s.id]}.insert(0, I18n.t('helpers.select_section'))
- @questions = phase.questions.map{|s| [s.text, s.id]}.insert(0, I18n.t('helpers.select_question'))
- end
-
- def update_sections
- authorize Guidance
- # updates sections and questions based on version selected
- version = Version.find(params[:version_id])
- # map to name and id for use in our options_for_select
- @sections = version.sections.map{|s| [s.title, s.id]}.insert(0, I18n.t('helpers.select_section'))
- @questions = version.questions.map{|s| [s.text, s.id]}.insert(0, I18n.t('helpers.select_question'))
- end
-
- def update_questions
- authorize Guidance
- # updates songs based on artist selected
- section = Section.find(params[:section_id])
- @questions = section.questions.map{|s| [s.text, s.id]}.insert(0, I18n.t('helpers.select_question'))
- end
-
##
# GET /guidances/1/edit
def admin_edit
- @guidance = Guidance.includes(:themes, :guidance_group).find(params[:id])
+ @guidance = Guidance.eager_load(:themes, :guidance_group).find(params[:id])
authorize @guidance
- @guidance_groups = GuidanceGroup.where(org_id: current_user.org_id).order('name ASC')
@themes = Theme.all.order('title')
+ @guidance_groups = GuidanceGroup.where(org_id: current_user.org_id).order('name ASC')
end
##
# POST /guidances
def admin_create
- @guidance = Guidance.new(params[:guidance])
+ @guidance = Guidance.new(guidance_params)
authorize @guidance
@guidance.text = params["guidance-text"]
- @guidance.question_id = params["question_id"]
- if @guidance.published == true then
- @gg = GuidanceGroup.find(@guidance.guidance_group_ids).first
- if @gg.published == false || @gg.published.nil? then
- @gg.published = true
- @gg.save
- end
+
+ @guidance.themes = []
+ if !guidance_params[:theme_ids].nil?
+ guidance_params[:theme_ids].map{|t| @guidance.themes << Theme.find(t.to_i) unless t.empty? }
end
if @guidance.save
- redirect_to admin_show_guidance_path(@guidance), notice: I18n.t('org_admin.guidance.created_message')
+ redirect_to admin_show_guidance_path(@guidance), notice: _('Guidance was successfully created.')
else
- render action: "new"
+ flash[:notice] = failed_create_error(@guidance, _('guidance'))
+ @themes = Theme.all.order('title')
+ @guidance_groups = GuidanceGroup.where(org_id: current_user.org_id).order('name ASC')
+ render action: "admin_new"
end
end
@@ -128,12 +61,14 @@
@guidance = Guidance.find(params[:id])
authorize @guidance
@guidance.text = params["guidance-text"]
- @guidance.question_id = params["question_id"]
-
- if @guidance.update_attributes(params[:guidance])
- redirect_to admin_show_guidance_path(params[:guidance]), notice: I18n.t('org_admin.guidance.updated_message')
+ if @guidance.update_attributes(guidance_params)
+ redirect_to admin_show_guidance_path(params[:guidance]), notice: _('Guidance was successfully updated.')
else
- render action: "edit"
+ flash[:notice] = failed_update_error(@guidance, _('guidance'))
+ @themes = Theme.all.order('title')
+ @guidance_groups = GuidanceGroup.where(org_id: current_user.org_id).order('name ASC')
+
+ render action: "admin_edit"
end
end
@@ -142,9 +77,17 @@
def admin_destroy
@guidance = Guidance.find(params[:id])
authorize @guidance
- @guidance.destroy
-
- redirect_to admin_index_guidance_path
+ if @guidance.destroy
+ redirect_to admin_index_guidance_path, notice: _('Guidance was successfully deleted.')
+ else
+ redirect_to admin_index_guidance_path, notice: failed_destroy_error(@guidance, _('guidance'))
+ end
end
+
+ private
+ def guidance_params
+ # The form on the page is weird. The text and template/section/question stuff is outside of the normal form params
+ params.require(:guidance).permit(:guidance_group_id, :published, theme_ids: [])
+ end
end
\ No newline at end of file
diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb
index a311c09..7a75e3c 100644
--- a/app/controllers/home_controller.rb
+++ b/app/controllers/home_controller.rb
@@ -11,6 +11,8 @@
def index
if user_signed_in?
name = current_user.name(false)
+# TODO: Investigate if this is even relevant anymore. The name var will never be blank here because the logic in
+# User says to return the email if the firstname and surname are empty regardless of the flag passed in
if name.blank?
redirect_to edit_user_registration_path
else
diff --git a/app/controllers/notes_controller.rb b/app/controllers/notes_controller.rb
index 8a400f6..474281a 100644
--- a/app/controllers/notes_controller.rb
+++ b/app/controllers/notes_controller.rb
@@ -2,18 +2,19 @@
after_action :verify_authorized
respond_to :html
- ##
- # POST /notes
+ require "pp"
+
def create
@note = Note.new
user_id = params[:new_note][:user_id]
@note.user_id = user_id
-
answer_id = params[:new_note][:answer_id]
question_id = params[:new_note][:question_id]
plan_id = params[:new_note][:plan_id]
+
+ # create answer if we dont already have one
if answer_id.present?
- answer = Answer.find(@note.answer_id)
+ answer = Answer.find(answer_id)
else
answer = Answer.new
answer.plan_id = plan_id
@@ -23,49 +24,59 @@
end
@note.answer= answer
- @note.text = params["#{params[:new_note][:answer_id]}new_note_text"]
+ @note.text = params["#{question_id}new_note_text"]
authorize @note
@plan = answer.plan
- @phase = answer.question.section.phase
+ @answer = answer
+ @question = Question.find(question_id)
if @note.save
- session[:question_id_notes] = answer.question_id
- redirect_to edit_plan_phase_path(@plan, @phase), status: :found, notice: I18n.t("helpers.comments.note_created")
+ @status = true
+ @notice = _('Comment was successfully created.')
+ else
+ @status = false
+ @notice = failed_create_error(@note, _('note'))
end
+ notes = answer.notes.all
+ @num_notes = notes.count
end
- ##
- # PUT /notes/1
+
+
def update
@note = Note.find(params[:note][:id])
authorize @note
@note.text = params["#{params[:note][:id]}_note_text"]
- @plan = Plan.find(@note.plan_id)
- @project = Project.find(@plan.project_id)
+ @answer = @note.answer
+ @question = @answer.question
+ @plan = @answer.plan
if @note.update_attributes(params[:note])
- session[:question_id_notes] = @note.question_id
- redirect_to edit_project_plan_path(@project, @plan), status: :found, notice: I18n.t("helpers.comments.note_updated")
+ @notice = _('Comment was successfully saved.')
+ else
+ @notice = failed_update_error(@note, _('note'))
end
end
- ##
- # ARCHIVE /notes/1
+
+
def archive
@note = Note.find(params[:note][:id])
authorize @note
@note.archived = true
@note.archived_by = params[:note][:archived_by]
- @plan = Plan.find(@note.plan_id)
- @project = Project.find(@plan.project_id)
+ @answer = @note.answer
+ @question = @answer.question
+ @plan = @answer.plan
if @note.update_attributes(params[:note])
- session[:question_id_notes] = @note.question_id
- redirect_to edit_project_plan_path(@project, @plan), status: :found, notice: I18n.t("helpers.comments.note_removed")
+ @notice = _('Comment removed.')
+ else
+ @notice = failed_destroy_error(@note, _('note'))
end
end
end
diff --git a/app/controllers/orgs_controller.rb b/app/controllers/orgs_controller.rb
index 905fd06..d0f5a8e 100644
--- a/app/controllers/orgs_controller.rb
+++ b/app/controllers/orgs_controller.rb
@@ -20,24 +20,33 @@
##
# PUT /organisations/1
def admin_update
+ attrs = org_params
@org = Org.find(params[:id])
authorize @org
@org.banner_text = params["org_banner_text"]
- @org.logo = params[:org][:logo] if params[:org][:logo]
- assign_params = params[:org].dup
- assign_params.delete(:logo)
- assign_params.delete(:contact_email) unless params[:org][:contact_email].present?
+ @org.logo = org_params[:logo] if org_params[:logo]
begin
- if @org.update_attributes(assign_params)
- redirect_to admin_show_org_path(params[:id]), notice: I18n.t("admin.org_updated_message")
+ if @org.update_attributes(org_params)
+ redirect_to admin_show_org_path(params[:id]), notice: _('Organisation was successfully updated.')
else
- flash[:notice] = @org.errors.collect{|e| e.message}.join(' ').html_safe
+ # For some reason our custom validator returns as a string and not a hash like normal activerecord
+ # errors. We followed the example provided in the Rails guides when building the validator so
+ # its unclear why its doing this. Placing a check here for the data type. We should reasses though
+ # when doing a broader eval of the look/feel of the site and we come up with a standardized way of
+ # displaying errors
+ flash[:notice] = failed_update_error(@org, _('organisation'))
render action: "admin_edit"
end
rescue Dragonfly::Job::Fetch::NotFound => dflye
- flash[:notice] = I18n.t("admin.org_bad_logo")
+ flash[:notice] = _('There seems to be a problem with your logo. Please upload it again.')
render action: "admin_edit"
end
end
+
+ private
+ def org_params
+ params.require(:org).permit(:name, :abbreviation, :target_url, :is_other, :banner_text, :language_id,
+ :region_id, :logo, :contact_email, :remove_logo)
+ end
end
diff --git a/app/controllers/phases_controller.rb b/app/controllers/phases_controller.rb
index b65f33f..21084a9 100644
--- a/app/controllers/phases_controller.rb
+++ b/app/controllers/phases_controller.rb
@@ -3,44 +3,82 @@
after_action :verify_authorized
- TEXTAREA = QuestionFormat.where(title: "Text area").first.id
- TEXTFIELD = QuestionFormat.where(title: "Text field").first.id
- RADIO = QuestionFormat.where(title: "Radio buttons").first.id
- CHECKBOX = QuestionFormat.where(title: "Check box").first.id
- DROPDOWN = QuestionFormat.where(title: "Dropdown").first.id
- MULTI = QuestionFormat.where(title: "Multi select box").first.id
-
- # GET /plans/PLANID/phases/PHASEID/edit
- def edit
-
- @textarea = TEXTAREA
- @textfield = TEXTFIELD
- @radio = RADIO
- @checkbox = CHECKBOX
- @dropdown = DROPDOWN
- @multi = MULTI
- @plan = Plan.find(params[:plan_id])
+ # GET /plans/:plan_id/phases/:id/edit
+ def edit
+
+ @plan = Plan.eager_load2(params[:plan_id])
+ # authorization done on plan so found in plan_policy
authorize @plan
- @plan_data = @plan.to_hash
-
phase_id = params[:id].to_i
- @phase = Phase.find(phase_id)
- @phase_data = @plan_data["template"]["phases"].select {|p| p["id"] == phase_id}.first
+ @phase = @plan.template.phases.select {|p| p.id == phase_id}.first
+ @readonly = !@plan.editable_by?(current_user.id)
+
+ # Now we need to get all the themed guidance for the plan.
+ # TODO: think this through again, there may be a better way to do this.
+ #
+ # Ultimately we are heading to a map from question id to theme to guidance.
+ #
+ # get the ids of the dynamically selected guidance groups
+ # and keep a map of them so we can extract the names later
+ guidance_groups_ids = @plan.guidance_groups.map{|pgg| pgg.id}
+ guidance_groups = GuidanceGroup.includes({guidances: :themes}).where(published: true, id: guidance_groups_ids)
+
+ # create a map from theme to array of guidances
+ # where guidance is a hash with the text and the org name
+ theme_guidance = {}
+
+ guidance_groups.includes(guidances:[:themes]).each do |guidance_group|
+ guidance_group.guidances.each do |guidance|
+ if guidance.published
+ guidance.themes.each do |theme|
+ title = theme.title
+ if !theme_guidance.has_key?(title)
+ theme_guidance[title] = Array.new
+ end
+ theme_guidance[title] << {
+ text: guidance.text,
+ org: guidance_group.name + ':'
+ }
+ end
+ end
+ end
+ end
+
+ # create hash from question id to theme to guidance array
+ # so when we arerendering a question we can grab the guidance out of this
+ #
+ # question_guidance = {
+ # question.id => {
+ # theme => [ {text: "......", org: "....."} ]
+ # }
+ # }
+ @question_guidance = {}
+ @plan.questions.each do |question|
+ qg = {}
+ question.themes.each do |t|
+ title = t.title
+ qg[title] = theme_guidance[title] if theme_guidance.has_key?(title)
+ end
+ if !@question_guidance.has_key?(question.id)
+ @question_guidance[question.id] = Array.new
+ end
+ @question_guidance[question.id] = qg
+ end
if !user_signed_in? then
respond_to do |format|
- format.html { redirect_to edit_user_registration_path }
- end
- end
+ format.html { redirect_to edit_user_registration_path }
+ end
+ end
- end
-
-
- # GET /plans/PLANID/phases/PHASEID/status.json
+ end
+
+
+ # GET /plans/PLANID/phases/PHASEID/status.json
def status
- @plan = Plan.find(params[:plan_id])
+ @plan = Plan.eager_load(params[:plan_id])
authorize @plan
if user_signed_in? && @plan.readable_by?(current_user.id) then
respond_to do |format|
@@ -52,4 +90,138 @@
end
+
+ #show and edit a phase of the template
+ def admin_show
+ @phase = Phase.eager_load(:sections).find_by('phases.id = ?', params[:id])
+ authorize @phase
+
+ @current = Template.current(@phase.template.dmptemplate_id)
+ @edit = (@phase.template.org == current_user.org) && (@phase.template == @current)
+ #@edit = params[:edit] == "true" ? true : false
+
+ #verify if there are any sections if not create one
+ @sections = @phase.sections
+ if !@sections.any?() || @sections.count == 0
+ @section = @phase.sections.build
+ @section.phase = @phase
+ @section.title = ''
+ @section.number = 1
+ @section.published = true
+ @section.modifiable = true
+ @section.save
+ @new_sec = true
+ end
+ #verify if section_id has been passed, if so then open that section
+ if params.has_key?(:section_id)
+ @open = true
+ @section_id = params[:section_id].to_i
+ end
+ if params.has_key?(:question_id)
+ @question_id = params[:question_id].to_i
+ end
+ if @phase.template.customization_of.present?
+ @original_org = Template.where(dmptemplate_id: @phase.template.customization_of).first.org
+ else
+ @original_org = @phase.template.org
+ end
+ end
+
+
+ #preview a phase
+ def admin_preview
+ @phase = Phase.find(params[:id])
+ authorize @phase
+ @template = @phase.template
+ end
+
+
+ #add a new phase to a passed template
+ def admin_add
+ @template = Template.find(params[:id])
+ @phase = Phase.new
+ @phase.template = @template
+ authorize @phase
+ @phase.number = @template.phases.count + 1
+ end
+
+
+ #create a phase
+ def admin_create
+ @phase = Phase.new(params[:phase])
+ authorize @phase
+
+ @phase.description = params["phase-desc"]
+ @phase.modifiable = true
+ if @phase.save
+ @phase.template.dirty = true
+ @phase.template.save!
+
+ redirect_to admin_show_phase_path(id: @phase.id, edit: 'true'), notice: _('Information was successfully created.')
+ else
+ flash[:notice] = failed_create_error(@phase, _('phase'))
+ @template = @phase.template
+ render "admin_add"
+ end
+ end
+
+
+ #update a phase of a template
+ def admin_update
+ @phase = Phase.find(params[:id])
+ authorize @phase
+ @phase.description = params["phase-desc"]
+ if @phase.update_attributes(params[:phase])
+ @phase.template.dirty = true
+ @phase.template.save!
+
+ redirect_to admin_show_phase_path(@phase), notice: _('Information was successfully updated.')
+ else
+ @sections = @phase.sections
+ @template = @phase.template
+ # These params may not be available in this context so they may need
+ # to be set to true without the check
+ @edit = true
+ @open = !params[:section_id].nil?
+ @section_id = (params[:section_id].nil? ? nil : params[:section_id].to_i)
+ @question_id = (params[:question_id].nil? ? nil : params[:question_id].to_i)
+ flash[:notice] = failed_update_error(@phase, _('phase'))
+ if @phase.template.customization_of.present?
+ @original_org = Template.where(dmptemplate_id: @phase.template.customization_of).first.org
+ else
+ @original_org = @phase.template.org
+ end
+ render 'admin_show'
+ end
+ end
+
+ #delete a phase
+ def admin_destroy
+ @phase = Phase.find(params[:phase_id])
+ authorize @phase
+ @template = @phase.template
+ if @phase.destroy
+ @template.dirty = true
+ @template.save!
+
+ redirect_to admin_template_template_path(@template), notice: _('Information was successfully deleted.')
+ else
+ @sections = @phase.sections
+
+ # These params may not be available in this context so they may need
+ # to be set to true without the check
+ @edit = true
+ @open = !params[:section_id].nil?
+ @section_id = (params[:section_id].nil? ? nil : params[:section_id].to_i)
+ @question_id = (params[:question_id].nil? ? nil : params[:question_id].to_i)
+ flash[:notice] = failed_destroy_error(@phase, _('phase'))
+ if @phase.template.customization_of.present?
+ @original_org = Template.where(dmptemplate_id: @phase.template.customization_of).first.org
+ else
+ @original_org = @phase.template.org
+ end
+ render 'admin_show'
+ end
+ end
+
end
diff --git a/app/controllers/plans_controller.rb b/app/controllers/plans_controller.rb
index edae8f5..f7edc1f 100644
--- a/app/controllers/plans_controller.rb
+++ b/app/controllers/plans_controller.rb
@@ -1,17 +1,8 @@
class PlansController < ApplicationController
require 'pp'
- #Uncomment the line below in order to add authentication to this page - users without permission will not be able to add new plans
- #load_and_authorize_resource
- #
- before_filter :get_plan_list_columns, only: %i( index )
- after_action :verify_authorized
+ helper SettingsTemplateHelper
- TEXTAREA = QuestionFormat.where(title: "Text area").first.id
- TEXTFIELD = QuestionFormat.where(title: "Text field").first.id
- RADIO = QuestionFormat.where(title: "Radio buttons").first.id
- CHECKBOX = QuestionFormat.where(title: "Check box").first.id
- DROPDOWN = QuestionFormat.where(title: "Dropdown").first.id
- MULTI = QuestionFormat.where(title: "Multi select box").first.id
+ after_action :verify_authorized
def index
authorize Plan
@@ -21,88 +12,90 @@
# GET /plans/new
+ # ------------------------------------------------------------------------------------
def new
- if user_signed_in? then
- @plan = Plan.new
- authorize @plan
- @funders = Org.funders.all
+ @plan = Plan.new
+ authorize @plan
- respond_to do |format|
- format.html # new.html.erb
- end
- else
- respond_to do |format|
- format.html { redirect_to edit_user_registration_path }
- end
- end
+ # Get all of the available funders and non-funder orgs
+ @funders = Org.funders.joins(:templates).where(templates: {published: true}).uniq.sort{|x,y| x.name <=> y.name }
+ @orgs = (Org.institutions + Org.managing_orgs).flatten.uniq.sort{|x,y| x.name <=> y.name }
+
+ # Get the current user's org
+ @default_org = current_user.org if @orgs.include?(current_user.org)
+
+ respond_to :html
end
-
+ # POST /plans
+ # -------------------------------------------------------------------
def create
- if user_signed_in? then
- @plan = Plan.new
- authorize @plan
- @plan.save
+ @plan = Plan.new
+ authorize @plan
- funder_id = params[:plan][:funder_id]
- if !funder_id.blank?
- # get all funder @templates
- funder = Org.find(params[:plan][:funder_id])
- @templates = get_most_recent( funder.templates.where("published = ?", true).all )
+ @plan.principal_investigator = current_user.surname.blank? ? nil : "#{current_user.firstname} #{current_user.surname}"
+ @plan.data_contact = current_user.email
+ @plan.funder_name = plan_params[:funder_name]
- orgtemplates = current_user.org.templates.all
- replacements = []
+ # If a template hasn't been identified look for the available templates
+ if plan_params[:template_id].blank?
+ template_options(plan_params[:org_id], plan_params[:funder_id])
- # replace any that are customised by the org
- orgtemplates.each do |orgt|
- base_template = orgt.customization_of
- @templates.delete(base_template)
- replacements << orgt
+ # Return the 'Select a template' section
+ respond_to do |format|
+ format.js {}
+ end
+
+ # Otherwise create the plan
+ else
+ @plan.template = Template.find(plan_params[:template_id])
+
+ if plan_params[:title].blank?
+ @plan.title = current_user.firstname.blank? ? _('My Plan') + '(' + @plan.template.title + ')' :
+ current_user.firstname + "'s" + _(" Plan")
+ else
+ @plan.title = plan_params[:title]
+ end
+
+ if @plan.save
+ @plan.assign_creator(current_user)
+
+ # pre-select org's guidance
+ ggs = GuidanceGroup.where(org_id: plan_params[:org_id],
+ optional_subset: false,
+ published: true)
+ if !ggs.blank? then @plan.guidance_groups << ggs end
+
+ default = Template.find_by(is_default: true)
+
+ msg = "#{_('Plan was successfully created.')} "
+
+ if !default.nil? && default == @plan.template
+ # We used the generic/default template
+ msg += _('This plan is based on the default template.')
+
+ elsif !@plan.template.customization_of.nil?
+ # We used a customized version of the the funder template
+ msg += "#{_('This plan is based on the')} #{plan_params[:funder_name]} #{_('template with customisations by the')} #{plan_params[:org_name]}"
+
+ else
+ # We used the specified org's or funder's template
+ msg += "#{_('This plan is based on the')} #{@plan.template.org.name} template."
end
- @templates + replacements
+
+ flash[:notice] = msg
+
+ respond_to do |format|
+ format.js { render js: "window.location='#{plan_url(@plan)}?editing=true'" }
+ end
else
- # get all org @templates which are not customisations
- @templates = current_user.org.templates.where(customization_of: nil)
-
- # if none of these get the basic dcc template
- if @templates.blank?
- @templates = Template.find_by_is_default(true)
+ # Something went wrong so report the issue to the user
+ flash[:notice] = failed_create_error(@plan, 'Plan')
+ respond_to do |format|
+ format.js {}
end
end
-
- # if we have more than one template then back to the user
- # using the 'create' template
- # to choose otherwise just create the plan
- # and go to the plan/show template
- if @templates.length > 1
- return
- end
-
- @plan.template = @templates[0]
-
- @plan.principal_investigator = current_user.name
-
- @plan.title = I18n.t('helpers.project.my_project_name')+' ('+@plan.template.title+')'
-
- @plan.assign_creator(current_user.id)
-
- @plan.set_possible_guidance_groups
-
- @selected_guidance_groups = @plan.guidance_groups.map{ |pgg| [pgg.name, pgg.id, :checked => false] }
- @selected_guidance_groups.sort!
-
- respond_to do |format|
- if @plan.save
- #format.html { redirect_to({:action => "show", :id => @plan.slug, :show_form => "yes"}, {:notice => I18n.t('helpers.project.success')}) }
- format.html { redirect_to({:action => "show", :id => @plan.id, :editing => true }, {:notice => I18n.t('helpers.project.success')}) }
- else
- @error = "Something went wrong"
- format.html { render action: "new" }
- end
- end
- else
- render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false)
end
end
@@ -110,30 +103,31 @@
# GET /plans/show
def show
- @plan = Plan.find(params[:id])
+ @plan = Plan.eager_load(params[:id])
authorize @plan
+ @editing = (!params[:editing].nil? && @plan.administerable_by?(current_user.id))
- @plan_data = @plan.to_hash
+ # Get all Guidance Groups applicable for the plan and group them by org
+ @all_guidance_groups = @plan.get_guidance_group_options
+ @all_ggs_grouped_by_org = @all_guidance_groups.sort.group_by(&:org)
- @editing = params[:editing] && @plan.administerable_by?(current_user.id)
- @selected_guidance_groups = []
- all_guidance_groups = @plan_data["plan_guidance_groups"]
- @selected_guidance_groups = all_guidance_groups.map{ |pgg| [ pgg["guidance_group"]["name"], pgg["guidance_group"]["id"], :checked => pgg["selected"] ] }
- @selected_guidance_groups.sort!
-
- if user_signed_in? && @plan.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 }
+ # Important ones come first on the page - we grab the user's org's GGs and "Organisation" org type GGs
+ @important_ggs = []
+ @important_ggs << [current_user.org, @all_ggs_grouped_by_org.delete(current_user.org)]
+ @all_ggs_grouped_by_org.each do |org, ggs|
+ if org.organisation?
+ @important_ggs << [org,ggs]
+ @all_ggs_grouped_by_org.delete(org)
end
end
+
+ # Sort the rest by org name for the accordion
+ @all_ggs_grouped_by_org = @all_ggs_grouped_by_org.sort_by {|org,gg| org.name}
+
+ @selected_guidance_groups = @plan.guidance_groups.pluck(:id)
+ @based_on = (@plan.template.customization_of.nil? ? @plan.template : Template.where(dmptemplate: @plan.template.customization_of).first)
+
+ respond_to :html
end
@@ -148,49 +142,29 @@
#
# GET /plans/1/edit
def edit
- @textarea = TEXTAREA
- @textfield = TEXTFIELD
- @radio = RADIO
- @checkbox = CHECKBOX
- @dropdown = DROPDOWN
- @multi = MULTI
-
@plan = Plan.find(params[:id])
-
- @phase = nil
- if params[:phase]
- @phase = Phase.find(params[:phase])
- end
-
authorize @plan
- @readonly = @plan.editable_by?(current_user.id)
- if !user_signed_in? then
- respond_to do |format|
- format.html { redirect_to edit_user_registration_path }
- end
- elsif !@plan.readable_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
+ # If there was no phase specified use the template's 1st phase
+ @phase = (params[:phase].nil? ? @plan.template.phases.first : Phase.find(params[:phase]))
+ @readonly = !@plan.editable_by?(current_user.id)
+ respond_to :html
end
+
# PUT /plans/1
# PUT /plans/1.json
def update
@plan = Plan.find(params[:id])
authorize @plan
- if user_signed_in? && @plan.editable_by?(current_user.id) then
- respond_to do |format|
- if @plan.update_attributes(params[:plan])
- format.html { redirect_to @plan, :editing => false, notice: I18n.t('helpers.project.success_update') }
- format.json { head :no_content }
- else
- format.html { render action: "edit" }
- end
+
+ respond_to do |format|
+ if @plan.update_attributes(params[:plan])
+ format.html { redirect_to @plan, :editing => false, notice: _('Plan was successfully updated.') }
+ format.json { head :no_content }
+ else
+ flash[:notice] = failed_update_error(@plan, _('plan'))
+ format.html { render action: "edit" }
end
- else
- render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false)
end
end
@@ -199,49 +173,46 @@
def update_guidance_choices
@plan = Plan.find(params[:id])
authorize @plan
- if user_signed_in? && @plan.editable_by?(current_user.id) then
- guidance_ids = params[:plan][:plan_guidance_group_ids]
- @plan.plan_guidance_groups.each do |pgg|
- pgg.selected = guidance_ids.include?(pgg.guidance_group_id.to_s)
- pgg.save!
+ guidance_group_ids = params[:guidance_group_ids].blank? ? [] : params[:guidance_group_ids].map(&:to_i)
+ all_guidance_groups = @plan.get_guidance_group_options
+ plan_groups = @plan.guidance_groups
+ guidance_groups = GuidanceGroup.where( id: guidance_group_ids)
+ all_guidance_groups.each do |group|
+ # case where plan group exists but not in selection
+ if plan_groups.include?(group) && ! guidance_groups.include?(group)
+ # remove from plan groups
+ @plan.guidance_groups.delete(group)
end
- @plan.save!
-
- respond_to do |format|
- format.json { head :no_content }
+ # case where plan group dosent exist and in selection
+ if !plan_groups.include?(group) && guidance_groups.include?(group)
+ # add to plan groups
+ @plan.guidance_groups << group
end
- else
- render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false)
end
+ @plan.save
+ flash[:notice] = _('Guidance choices saved.')
+ redirect_to action: "show"
end
def share
@plan = Plan.find(params[:id])
authorize @plan
- @plan_data = @plan.to_hash
- if !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 plans_url, notice: I18n.t('helpers.settings.plans.errors.no_access_account') }
- end
- end
+ #@plan_data = @plan.to_hash
end
def destroy
@plan = Plan.find(params[:id])
authorize @plan
- if user_signed_in? && @plan.editable_by?(current_user.id) then
- @plan.destroy
-
+ if @plan.destroy
respond_to do |format|
- format.html { redirect_to plans_url }
+ format.html { redirect_to plans_url, notice: _('Plan was successfully deleted.') }
end
else
- render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false)
+ respond_to do |format|
+ flash[:notice] = failed_create_error(@plan, _('plan'))
+ format.html { render action: "edit" }
+ end
end
end
@@ -250,164 +221,76 @@
def status
@plan = Plan.find(params[:id])
authorize @plan
- if user_signed_in? && @plan.readable_by(current_user.id) then
- respond_to do |format|
- format.json { render json: @plan.status }
- end
- else
- render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false)
- end
- end
-
- def section_answers
- @plan = Plan.find(params[:id])
- authorize @plan
- if user_signed_in? && @plan.readable_by(current_user.id) then
- respond_to do |format|
- format.json { render json: @plan.section_answers(params[:section_id]) }
- end
- else
- render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false)
- end
- end
-
- def locked
- @plan = Plan.find(params[:id])
- authorize @plan
- if !@plan.nil? && user_signed_in? && @plan.readable_by(current_user.id) then
- respond_to do |format|
- format.json { render json: @plan.locked(params[:section_id],current_user.id) }
- end
- else
- render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false)
- end
- end
-
- def delete_recent_locks
- @plan = Plan.find(params[:id])
- authorize @plan
- if user_signed_in? && @plan.editable_by(current_user.id) then
- respond_to do |format|
- if @plan.delete_recent_locks(current_user.id)
- format.html { render action: "edit" }
- else
- format.html { render action: "edit" }
- end
- end
- else
- render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false)
- end
- end
-
- def unlock_all_sections
- @plan = Plan.find(params[:id])
- authorize @plan
- if user_signed_in? && @plan.editable_by(current_user.id) then
- respond_to do |format|
- if @plan.unlock_all_sections(current_user.id)
- format.html { render action: "edit" }
- else
- format.html { render action: "edit" }
- end
- end
- else
- render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false)
- end
- end
-
- def lock_section
- @plan = Plan.find(params[:id])
- authorize @plan
- if user_signed_in? && @plan.editable_by(current_user.id) then
- respond_to do |format|
- if @plan.lock_section(params[:section_id], current_user.id)
- format.html { render action: "edit" }
- else
- format.html { render action: "edit" }
- format.json { render json: @plan.errors, status: :unprocessable_entity }
- end
- end
- else
- render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false)
- end
- end
-
- def unlock_section
- @plan = Plan.find(params[:id])
- authorize @plan
- if user_signed_in? && @plan.editable_by(current_user.id) then
- respond_to do |format|
- if @plan.unlock_section(params[:section_id], current_user.id)
- format.html { render action: "edit" }
-
- else
- format.html { render action: "edit" }
- end
- end
- else
- render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false)
+ respond_to do |format|
+ format.json { render json: @plan.status }
end
end
def answer
@plan = Plan.find(params[:id])
authorize @plan
- if user_signed_in? && @plan.readable_by(current_user.id) then
+ if !params[:q_id].nil?
respond_to do |format|
format.json { render json: @plan.answer(params[:q_id], false).to_json(:include => :options) }
end
else
- render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false)
+ respond_to do |format|
+ format.json { render json: {} }
+ end
end
end
+ def show_export
+ @plan = Plan.find(params[:id])
+ authorize @plan
+ render 'show_export'
+ end
+
+
+
def export
@plan = Plan.find(params[:id])
authorize @plan
- 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.format = request.format.try(:symbol)
- ep.format = request.format.to_sym
- plan_settings = @plan.settings(:export)
+ # If no format is specified, default to PDF
+ params[:format] = 'pdf' if params[:format].nil?
- Settings::Template::DEFAULT_SETTINGS.each do |key, value|
- ep.settings(:export).send("#{key}=", plan_settings.send(key))
- end
+ @exported_plan = ExportedPlan.new.tap do |ep|
+ ep.plan = @plan
+ ep.phase_id = params[:phase_id]
+ ep.user = current_user
+ ep.format = params[:format].to_sym
+ plan_settings = @plan.settings(:export)
+
+ Settings::Template::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
+ begin
+ @exported_plan.save!
+ file_name = @exported_plan.settings(:export)[:value]['title'].gsub(/ /, "_")
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.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 { render docx: 'export', 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'),
+ center: _('This document was generated by %{application_name}') % {application_name: Rails.configuration.branding[:application][:name]},
font_size: 8,
spacing: (@formatting[:margin][:bottom] / 2) - 4,
right: '[page] of [topage]'
}
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') }
- end
+ rescue ActiveRecord::RecordInvalid => e
+ redirect_to show_export_plan_path(@plan), notice: _('%{format} is not a valid exporting format. Available formats to export are %{available_formats}.') %
+ {format: params[:format], available_formats: ExportedPlan::VALID_FORMATS.to_s}
end
end
@@ -415,13 +298,19 @@
private
+ def plan_params
+ params.require(:plan).permit(:org_id, :org_name, :funder_id, :funder_name, :template_id, :title)
+ end
+ # different versions of the same template have the same dmptemplate_id
+ # but different version numbers so for each set of templates with the
+ # same dmptemplate_id choose the highest version number.
def get_most_recent( templates )
groups = Hash.new
templates.each do |t|
k = t.dmptemplate_id
if !groups.has_key?(k)
- groups[k] =t
+ groups[k] = t
else
other = groups[k]
if other.version < t.version
@@ -443,7 +332,7 @@
ghash = {}
plan["guidance_groups"].map{|g| ghash[g["id"]] = g}
- plan["plan_guidance_groups"].each do |pgg|
+ plan["plans_guidance_groups"].each do |pgg|
pgg["guidance_group"] = ghash[ pgg["guidance_group_id"] ]
end
@@ -476,4 +365,49 @@
plan.delete(src_plan_key)
end
+ # Collect all of the templates available for the org+funder combination
+ # --------------------------------------------------------------------------
+ def template_options(org_id, funder_id)
+ @templates = []
+
+ if !org_id.blank? || !funder_id.blank?
+ if funder_id.blank?
+ # Load the org's template(s)
+ unless org_id.nil?
+ org = Org.find(org_id)
+ @templates = Template.valid.where(published: true, org: org, customization_of: nil).to_a
+ @msg = _("We found multiple DMP templates corresponding to the research organisation.") if @templates.count > 1
+ end
+
+ else
+ funder = Org.find(funder_id)
+ # Load the funder's template(s)
+ @templates = Template.valid.where(published: true, org: funder).to_a
+
+ unless org_id.blank?
+ org = Org.find(org_id)
+
+ # Swap out any organisational cusotmizations of a funder template
+ @templates.each do |tmplt|
+ customization = Template.valid.find_by(published: true, org: org, customization_of: tmplt.dmptemplate_id)
+ unless customization.nil?
+ @templates.delete(tmplt)
+ @templates << customization
+ end
+ end
+ end
+
+ msg = _("We found multiple DMP templates corresponding to the funder.") if @templates.count > 1
+ end
+ end
+
+ # If no templates were available use the generic templates
+ if @templates.empty?
+ @msg = _("Using the generic Data Management Plan")
+ @templates << Template.where(is_default: true, published: true).first
+ end
+
+ @templates = @templates.sort{|x,y| x.title <=> y.title } if @templates.count > 1
+ end
+
end
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
deleted file mode 100644
index 5b98dd2..0000000
--- a/app/controllers/projects_controller.rb
+++ /dev/null
@@ -1,401 +0,0 @@
-class ProjectsController < ApplicationController
- before_filter :get_plan_list_columns, only: %i( index )
- after_action :verify_authorized
-
- # 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
-
- @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
-
- # 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
-
- def new
- if user_signed_in? then
- @plan = Plan.new
- authorize @plan
- @funders = Org.funder.all
-
- respond_to do |format|
- format.html # new.html.erb
- end
- else
- respond_to do |format|
- format.html { redirect_to edit_user_registration_path }
- end
- end
- end
-
-
- # GET /projects/1/edit
- # Should this be removed?
- def edit
- @project = Project.find(params[:id])
- authorize @project
- 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
-
- def share
- @project = Project.find(params[:id])
- authorize @project
- 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
-
- def export
- @project = Project.find(params[:id])
- authorize @project
- 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" }
-
- end
- end
- end
-
- # POST /projects
- def create
- puts params
- return
- if user_signed_in? then
- @plan = Plan.new(params[:plan])
- 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)
-
- @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])
- authorize @project
- if user_signed_in? && @project.editable_by(current_user.id) then
- if @project.update_attributes(params[:project])
- respond_to do |format|
- 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
-
- # 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
-
- 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
- funder = Org.find(params[:funder])
- else
- funder = nil
- end
- if !params[:institution].nil? && params[:institution] != "" && params[:institution] != "undefined" then
- institution = Org.find(params[:institution])
- else
- institution = nil
- end
- templates = {}
- unless funder.nil? then
- funder.published_templates.each do |t|
- templates[t.id] = t.title
- end
- end
- if templates.count == 0 && !institution.nil? then
- institution.published_templates.each do |t|
- templates[t.id] = t.title
- end
- institution.children.each do |o|
- o.published_templates.each do |t|
- templates[t.id] = t.title
- end
- end
- end
- respond_to do |format|
- format.json { render json: templates.to_json }
- 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
- # -----------------------------------------------------------
- def possible_guidance
- authorize @project
-
- if !params[:template].nil? && params[:template] != "" && params[:template] != "undefined" then
- template = Dmptemplate.find(params[:template])
- else
- template = nil
- end
- if !params[:institution].nil? && params[:institution] != "" && params[:institution] != "undefined" then
- institution = Org.find(params[:institution])
- else
- institution = nil
- end
- excluded_orgs = Org.funders + Org.institutions
- guidance_groups = {}
- ggs = GuidanceGroup.guidance_groups_excluding(excluded_orgs)
-
- ggs.each do |gg|
- guidance_groups[gg.id] = gg.name
- end
-
- #subset guidance that belong to the institution
- 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
-
- 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
- end
-
-
- respond_to do |format|
- format.json { render json: guidance_groups.to_json }
- 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
- Template.find_by(published: true)
- end
-
- # -----------------------------------------------------------
- # Some guidance is always available to the user regardless of
- # the template or institution.
- #
- # TODO: Reevaluate this. We should probably only do this for
- # guidance groups who have guidance attached to themes
- # -----------------------------------------------------------
- def get_always_available_guidance
- # Exclude Funders, Institutions, or children of Institutions
- 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"))
-
- GuidanceGroup.guidance_groups_excluding(excluded_orgs)
- end
-
- # -----------------------------------------------------------
- # This is a simplified version of the old possible_guidance method
- # above. It sends all possible guidance to the client instead of
- # forcing the client to make ajax calls to change the available
- # guidance list (that is now handled via JS clientside)
- #
- # TODO: Reevaluate whether or not this logic makes sense once the
- # DB has been cleaned up
- # -----------------------------------------------------------
- def get_available_guidance
- guidance_groups = []
-
- #subset guidance that belong to an institution
- optional_gg = GuidanceGroup.where("optional_subset = ? AND organisation_id IS NOT NULL", true)
- optional_gg.each do|optional|
- guidance_groups << optional.id
-
- optional.organisation.children.each do |o|
- o.guidance_groups.each do |gg|
- guidance_groups << gg.id
- end
- end
- end
-
- # If template belongs to a funder and is an optional_subset
- optional_gg = GuidanceGroup.where("optional_subset = ? AND organisation_id IN (?)", true, orgs_of_type(constant("organisation_types.funder")))
- optional_gg.each do|optional|
- guidance_groups << optional.id
- end
-
- 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/questions_controller.rb b/app/controllers/questions_controller.rb
new file mode 100644
index 0000000..f3250bb
--- /dev/null
+++ b/app/controllers/questions_controller.rb
@@ -0,0 +1,132 @@
+class QuestionsController < ApplicationController
+ respond_to :html
+ after_action :verify_authorized
+
+ #create a question
+ def admin_create
+ begin
+ @question = Question.new(question_params)
+ authorize @question
+ @question.modifiable = true
+ if @question.question_format.textfield?
+ @question.default_value = params["question-default-value-textfield"]
+ elsif @question.question_format.textarea?
+ @question.default_value = params["question-default-value-textarea"]
+ end
+ if @question.save
+ @question.section.phase.template.dirty = true
+ @question.section.phase.template.save!
+ if params[:example_answer].present?
+ example_answer = Annotation.new({question_id: @question.id, org_id: current_user.org_id, text: params[:example_answer], type: Annotation.types[:example_answer]})
+ example_answer.save
+ end
+ if params[:guidance].present?
+ guidance = Annotation.new({question_id: @question.id, org_id: current_user.org_id, text: params[:guidance], type: Annotation.types[:guidance]})
+ guidance.save
+ end
+ redirect_to admin_show_phase_path(id: @question.section.phase_id, section_id: @question.section_id, question_id: @question.id, edit: 'true'), notice: _('Information was successfully created.')
+ else
+ @edit = (@question.section.phase.template.org == current_user.org)
+ @open = true
+ @phase = @question.section.phase
+ @section = @question.section
+ @sections = @phase.sections
+ @section_id = @question.section.id
+ @question_id = @question.id
+
+ flash[:notice] = failed_create_error(@question, _('question'))
+ if @phase.template.customization_of.present?
+ @original_org = Template.where(dmptemplate_id: @phase.template.customization_of).first.org
+ else
+ @original_org = @phase.template.org
+ end
+ render template: 'phases/admin_show'
+ end
+ rescue ActionController::ParameterMissing => e
+ flash[:notice] = e.message
+ end
+ end
+
+ #update a question of a template
+ def admin_update
+ @question = Question.find(params[:id])
+ authorize @question
+ guidance = @question.get_guidance_annotation(current_user.org_id)
+ if params["question-guidance-#{params[:id]}"].present?
+ if guidance.blank?
+ guidance = @question.annotations.build
+ guidance.type = :guidance
+ guidance.org_id = current_user.org_id
+ end
+ guidance.text = params["question-guidance-#{params[:id]}"]
+ guidance.save
+ end
+ example_answer = @question.get_example_answer(current_user.org_id)
+ if params["question"]["annotations_attributes"].present? && params["question"]["annotations_attributes"]["0"]["id"].present?
+ if example_answer.blank?
+ example_answer = @question.annotations.build
+ example_answer.type = :example_answer
+ example_answer.org_id = current_user.org_id
+ end
+ example_answer.text = params["question"]["annotations_attributes"]["0"]["text"]
+ example_answer.save
+ end
+ if @question.question_format.textfield?
+ @question.default_value = params["question-default-value-textfield"]
+ elsif @question.question_format.textarea?
+ @question.default_value = params["question-default-value-textarea"]
+ end
+ @section = @question.section
+ @phase = @section.phase
+ template = @phase.template
+ if @question.update_attributes(params[:question])
+ @phase.template.dirty = true
+ @phase.template.save!
+
+ redirect_to admin_show_phase_path(id: @phase.id, section_id: @section.id, question_id: @question.id, edit: 'true'), notice: _('Information was successfully updated.')
+ else
+ @edit = (@phase.template.org == current_user.org)
+ @open = true
+ @sections = @phase.sections
+ @section_id = @section.id
+ @question_id = @question.id
+
+ flash[:notice] = failed_update_error(@question, _('question'))
+ if @phase.template.customization_of.present?
+ @original_org = Template.where(dmptemplate_id: @phase.template.customization_of).first.org
+ else
+ @original_org = @phase.template.org
+ end
+ render template: 'phases/admin_show'
+ end
+ end
+
+ #delete question
+ def admin_destroy
+ @question = Question.find(params[:question_id])
+ authorize @question
+ @section = @question.section
+ @phase = @section.phase
+ if @question.destroy
+ @phase.template.dirty = true
+ @phase.template.save!
+
+ redirect_to admin_show_phase_path(id: @phase.id, section_id: @section.id, edit: 'true'), notice: _('Information was successfully deleted.')
+ else
+ redirect_to admin_show_phase_path(id: @phase.id, section_id: @section.id, edit: 'true'), notice: failed_destroy_error(@question, 'question')
+ end
+ end
+
+ private
+ # Filters the valid attributes for a question according to each type.
+ # Note, that params[:question] and params[:question][:question_format_id] are required and their absence raises ActionController::ParameterMissing
+ def question_params
+ permitted = params.require(:question).except(:created_at, :updated_at).tap do |question_params|
+ question_params.require(:question_format_id)
+ q_format = QuestionFormat.find(question_params[:question_format_id])
+ if !q_format.option_based?
+ question_params.delete(':question_options_attributes')
+ end
+ end
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb
index a82b679..a628929 100644
--- a/app/controllers/registrations_controller.rb
+++ b/app/controllers/registrations_controller.rb
@@ -6,6 +6,7 @@
@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)
+ @default_org = current_user.org
end
# GET /resource
@@ -34,48 +35,48 @@
# POST /resource
def create
- logger.debug "#{sign_up_params}"
- if sign_up_params[:accept_terms] != "1" then
- redirect_to after_sign_up_error_path_for(resource), alert: I18n.t('helpers.you_must_accept')
- else
- existing_user = User.find_by_email(sign_up_params[:email])
- if !existing_user.nil? then
- if (existing_user.password == "" || existing_user.password.nil?) && existing_user.confirmed_at.nil? then
- @user = existing_user
- do_update(false, true)
- else
- redirect_to after_sign_up_error_path_for(resource), alert: I18n.t('helpers.email_already_registered')
- end
- else
+ #logger.debug "#{sign_up_params}"
+ if sign_up_params[:accept_terms] != "1" then
+ redirect_to after_sign_up_error_path_for(resource), alert: _('You must accept the terms and conditions to register.')
+ else
+ existing_user = User.find_by_email(sign_up_params[:email])
+ if !existing_user.nil? # If email exists
+ if (existing_user.password == "" || existing_user.password.nil?) && existing_user.confirmed_at.nil? # If user has not accepted invitation yet
+ existing_user.destroy # Only solution for now
+ super
+ else
+ redirect_to after_sign_up_error_path_for(resource), alert: _('That email address is already registered.')
+ end
+ else
build_resource(sign_up_params)
- if resource.save
- if resource.active_for_authentication?
- set_flash_message :notice, :signed_up if is_navigational_format?
- sign_up(resource_name, resource)
- respond_with resource, location: after_sign_up_path_for(resource)
- else
- set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_navigational_format?
- #expire_session_data_after_sign_in! <-- DEPRECATED BY DEVISE
- respond_with resource, location: after_inactive_sign_up_path_for(resource)
- end
- else
- clean_up_passwords resource
- redirect_to after_sign_up_error_path_for(resource), alert: I18n.t('helpers.error_registration_check')
- end
- end
+ if resource.save
+ if resource.active_for_authentication?
+ set_flash_message :notice, :signed_up if is_navigational_format?
+ sign_up(resource_name, resource)
+ UserMailer.welcome_notification(current_user).deliver
+ respond_with resource, location: after_sign_up_path_for(resource)
+ else
+ set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_navigational_format?
+ #expire_session_data_after_sign_in! <-- DEPRECATED BY DEVISE
+ respond_with resource, location: after_inactive_sign_up_path_for(resource)
+ end
+ else
+ clean_up_passwords resource
+ redirect_to after_sign_up_error_path_for(resource), alert: _('Error processing registration. Please check that you have entered a valid email address and that your chosen password is at least 8 characters long.')
+ end
+ end
end
end
def update
if user_signed_in? then
- @user = User.find(current_user.id)
@orgs = Org.where(parent_id: nil).order("name")
+ @default_org = current_user.org
@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
+ @languages = Language.sorted_by_abbreviation
+ do_update(require_password=needs_password?(current_user, params))
else
render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false)
end
@@ -91,53 +92,93 @@
end
def do_update(require_password = true, confirm = false)
- if require_password then
- successfully_updated = if needs_password?(@user, params)
- @user.update_with_password(params[:user])
- else
- # remove the virtual current_password attribute update_without_password
- # doesn't know how to ignore it
- params[:user].delete(:current_password)
- @user.update_without_password(params[:user])
+ mandatory_params = true
+ message = _('Save Unsuccessful.') + ' ' # added to by below, overwritten otherwise
+ # ensure that the required fields are present
+ if params[:user][:email].blank?
+ message +=_('Please enter an email address.') + ' '
+ mandatory_params &&= false
+ end
+ if params[:user][:firstname].blank?
+ message +=_('Please enter a First name.') + ' '
+ mandatory_params &&= false
+ end
+ if params[:user][:surname].blank?
+ message +=_('Please enter a Last name.') + ' '
+ mandatory_params &&= false
+ end
+ if params[:user][:org_id].blank?
+ message += _('Please select an organisation, or select Other.')
+ mandatory_params &&= false
+ end
+ if mandatory_params # has the user entered all the details
+ if require_password # user is changing email or password
+ if current_user.email != params[:user][:email] # if user is changing email
+ if params[:user][:current_password].blank? # password needs to be present
+ message = _('Please enter your password to change email address.')
+ successfully_updated = false
+ else
+ successfully_updated = current_user.update_with_password(password_update)
+ end
+ elsif params[:user][:password].present? # if user is changing password
+ successfully_updated = false # shared across first 3 conditions
+ if params[:user][:current_password].blank?
+ message = _('Please enter your current password')
+ elsif params[:user][:password_confirmation].blank?
+ message = _('Please enter a password confirmation')
+ elsif params[:user][:password] != params[:user][:password_confirmation]
+ message = _('Password and comfirmation must match')
+ else
+ successfully_updated = current_user.update_with_password(password_update)
+ end
+ else # potentially unreachable... but I dont like to leave off the else
+ successfully_updated = current_user.update_with_password(password_update)
+ end
+ else # password not required
+ successfully_updated = current_user.update_without_password(update_params)
end
else
- @user.update_attributes(password: params[:user][:password], password_confirmation: params[:user][:password_confirmation])
- successfully_updated = @user.update_without_password(params[:user])
- end
-
- # If the user selected a new language setting, go ahead and reset the locale
- if params[:user][:language_id]
- if @user.language_id != params[:user][:language_id]
- params[:locale] = Language.find(params[:user][:language_id]).abbreviation
- set_locale
- end
+ successfully_updated = false
end
#unlink shibboleth from user's details
if params[:unlink_flag] == 'true' then
- @user.update_attributes(shibboleth_id: "")
+ current_user.update_attributes(shibboleth_id: "")
end
+ #render the correct page
if successfully_updated
- if confirm then
- @user.skip_confirmation!
- @user.save!
- end
- set_flash_message :notice, :updated
- # Sign in the user bypassing validation in case his password changed
+ if confirm
+ current_user.skip_confirmation! # will error out if confirmable is turned off in user model
+ current_user.save!
+ end
+ session[:locale] = current_user.get_locale unless current_user.get_locale.nil?
+ set_gettext_locale #Method defined at controllers/application_controller.rb
+ set_flash_message :notice, _('Details successfully updated.')
+ sign_in current_user, bypass: true # Sign in the user bypassing validation in case his password changed
+ redirect_to edit_user_registration_path, notice: _('Details successfully updated.')
- sign_in @user, bypass_sign_in: true
-
- redirect_to({:controller => "registrations", :action => "edit"}, {:notice => I18n.t('helpers.project.details_update_success')})
-
else
+ flash[:notice] = message.blank? ? failed_update_error(current_user, _('profile')) : message
render "edit"
end
end
def sign_up_params
- params.require(:user).permit(:email, :password, :password_confirmation, :accept_terms,
- :organisation_id, :other_organisation)
+ params.require(:user).permit(:email, :password, :password_confirmation, :firstname, :surname,
+ :accept_terms, :org_id, :other_organisation)
+ end
+
+ def update_params
+ params.require(:user).permit(:firstname, :org_id, :other_organisation,
+ :language_id, :surname)
+ end
+
+ def password_update
+ params.require(:user).permit(:email, :firstname, :current_password,
+ :org_id, :language_id, :password,
+ :password_confirmation, :surname,
+ :other_organisation)
end
end
diff --git a/app/controllers/roles_controller.rb b/app/controllers/roles_controller.rb
index d4e4072..3a50d54 100644
--- a/app/controllers/roles_controller.rb
+++ b/app/controllers/roles_controller.rb
@@ -2,60 +2,91 @@
respond_to :html
after_action :verify_authorized
- def create
- @role = Role.new(params[:role])
+ def create
+ registered = true
+ @role = Role.new(role_params)
authorize @role
- @role.access_level = params[:role][:access_level].to_i
- if params[:role][:email].present?
- message = I18n.t('helpers.project.user_added')
- if @role.save
- if @role.user.nil? then
- if User.find_by_email(params[:role][:email]).nil? then
- User.invite!(email: params[:role][:email])
- message = I18n.t('helpers.project.invitation_success')
- @role.user = User.find_by_email(params[:role][:email])
- @role.save
- else
- @role.user = User.find_by_email(params[:role][:email])
- @role.save
- UserMailer.sharing_notification(@role).deliver
- end
- else
- UserMailer.sharing_notification(@role).deliver
- end
- flash[:notice] = message
- redirect_to controller: 'plans', action: 'share', id: @role.plan.slug
- else
- render action: "new"
- end
- else
- flash[:notice] = I18n.t('helpers.project.enter_email')
- redirect_to controller: 'plans', action: 'share', id: @role.plan.slug
- end
- end
+ access_level = params[:role][:access_level].to_i
+ set_access_level(access_level)
+ if params[:user].present?
+ if @role.plan.owner.present? && @role.plan.owner.email == params[:user]
+ flash[:notice] = _('Cannot share plan with %{email} since that email matches with the owner of the plan.') % {email: params[:user]}
+ else
+ if Role.find_by(plan: @role.plan, user: User.find_by(email: params[:user])) # role already exists
+ flash[:notice] = _('Plan is already shared with %{email}.') % {email: params[:user]}
+ else
+ message = _('Plan shared with %{email}.') % {email: params[:user]}
+ user = User.find_by(email: params[:user])
+ if user.nil?
+ registered = false
+ User.invite!(email: params[:user])
+ message = _('Invitation to %{email} issued successfully.') % {email: params[:user]}
+ user = User.find_by(email: params[:user])
+ end
+ @role.user = user
+ if @role.save
+ if registered then UserMailer.sharing_notification(@role, current_user).deliver_now end
+ flash[:notice] = message
+ else
+ flash[:notice] = failed_create_error(@role, _('role'))
+ end
+ end
+ end
+ else
+ flash[:notice] = _('Please enter an email address')
+ end
+ redirect_to controller: 'plans', action: 'share', id: @role.plan.id
+ end
- def update
- @role = Role.find(params[:id])
+
+ def update
+ @role = Role.find(params[:id])
authorize @role
- @role.access_level = params[:role][:access_level].to_i
- if @role.update_attributes(params[:role])
- flash[:notice] = I18n.t('helpers.project.sharing_updated')
- UserMailer.permissions_change_notification(@role).deliver
- redirect_to controller: 'plans', action: 'share', id: @role.plan.slug
- else
- render action: "edit"
- end
- end
+ access_level = params[:role][:access_level].to_i
+ set_access_level(access_level)
+ if @role.update_attributes(role_params)
+ flash[:notice] = _('Sharing details successfully updated.')
+ UserMailer.permissions_change_notification(@role, current_user).deliver_now
+ redirect_to controller: 'plans', action: 'share', id: @role.plan.id
+ else
+ flash[:notice] = failed_create_error(@role, _('role'))
+ render action: "edit"
+ end
+ end
- def destroy
- @role = Role.find(params[:id])
+ def destroy
+ @role = Role.find(params[:id])
authorize @role
- user = @role.user
- plan = @role.plan
- @role.destroy
+ user = @role.user
+ plan = @role.plan
+ @role.destroy
+ flash[:notice] = _('Access removed')
+ UserMailer.project_access_removed_notification(user, plan, current_user).deliver_now
+ redirect_to controller: 'plans', action: 'share', id: @role.plan.id
+ end
- flash[:notice] = I18n.t('helpers.project.access_removed')
- UserMailer.project_access_removed_notification(user, plan).deliver
- redirect_to controller: 'plans', action: 'share', id: @role.plan.slug
- end
-end
\ No newline at end of file
+ private
+
+ def role_params
+ params.require(:role).permit(:plan_id)
+ end
+
+ def set_access_level(access_level)
+ if access_level >= 1
+ @role.commenter = true
+ else
+ @role.commenter = false
+ end
+ if access_level >= 2
+ @role.editor = true
+ else
+ @role.editor = false
+ end
+ if access_level >= 3
+ @role.administrator = true
+ else
+ @role.administrator = false
+ end
+ end
+
+end
diff --git a/app/controllers/sections_controller.rb b/app/controllers/sections_controller.rb
new file mode 100644
index 0000000..b6ef3d1
--- /dev/null
+++ b/app/controllers/sections_controller.rb
@@ -0,0 +1,91 @@
+class SectionsController < ApplicationController
+ respond_to :html
+ after_action :verify_authorized
+
+ #create a section
+ def admin_create
+ @section = Section.new(params[:section])
+ authorize @section
+ @section.description = params["section-desc"]
+ @section.modifiable = true
+ @phase = @section.phase
+ if @section.save
+ @section.phase.template.dirty = true
+ @section.phase.template.save!
+
+ redirect_to admin_show_phase_path(id: @section.phase_id,
+ :section_id => @section.id, edit: 'true'), notice: _('Information was successfully created.')
+ else
+ @edit = (@phase.template.org == current_user.org)
+ @open = true
+ @sections = @phase.sections
+ @section_id = @section.id
+ @question_id = nil
+ flash[:notice] = failed_create_error(@section, _('section'))
+ if @phase.template.customization_of.present?
+ @original_org = Template.where(dmptemplate_id: @phase.template.customization_of).first.org
+ else
+ @original_org = @phase.template.org
+ end
+ render template: 'phases/admin_show'
+ end
+ end
+
+
+ #update a section of a template
+ def admin_update
+ @section = Section.includes(phase: :template).find(params[:id])
+ authorize @section
+ @section.description = params["section-desc-#{params[:id]}"]
+ @phase = @section.phase
+ if @section.update_attributes(params[:section])
+ @section.phase.template.dirty = true
+ @section.phase.template.save!
+
+ redirect_to admin_show_phase_path(id: @phase.id, section_id: @section.id , edit: 'true'), notice: _('Information was successfully updated.')
+ else
+ @edit = (@phase.template.org == current_user.org)
+ @open = true
+ @sections = @phase.sections
+ @section_id = @section.id
+ @question_id = nil
+ flash[:notice] = failed_update_error(@section, _('section'))
+ if @phase.template.customization_of.present?
+ @original_org = Template.where(dmptemplate_id: @phase.template.customization_of).first.org
+ else
+ @original_org = @phase.template.org
+ end
+ render template: 'phases/admin_show'
+ end
+ end
+
+
+ #delete a section and questions
+ def admin_destroy
+ @section = Section.includes(phase: :template).find(params[:section_id])
+ authorize @section
+ @phase = @section.phase
+
+ if @section.destroy
+ @phase.template.dirty = true
+ @phase.template.save!
+
+ redirect_to admin_show_phase_path(id: @phase.id, edit: 'true' ), notice: _('Information was successfully deleted.')
+ else
+ @edit = (@phase.template.org == current_user.org)
+ @open = true
+ @sections = @phase.sections
+ @section_id = @section.id
+ @question_id = nil
+
+ flash[:notice] = failed_destroy_error(@section, _('section'))
+ if @phase.template.customization_of.present?
+ @original_org = Template.where(dmptemplate_id: @phase.template.customization_of).first.org
+ else
+ @original_org = @phase.template.org
+ end
+ render template: 'phases/admin_show'
+ end
+ end
+
+end
\ No newline at end of file
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index 89a5f44..a4154d9 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -16,13 +16,23 @@
# ---------------------------------------------------------------------
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])
+ if !existing_user.nil?
+
+# TODO: Not sure why we check for shib data in params and then use session value below. We should move this to the
+# new user_identifiers table
+ if !params[:shibboleth_data].nil?
+ #after authentication verify if session[:shibboleth] exists
+ existing_user.update_attributes(shibboleth_id: session[:shibboleth_data][:uid])
+ end
+ session[:locale] = existing_user.get_locale unless existing_user.get_locale.nil?
+ set_gettext_locale #Method defined at controllers/application_controller.rb
end
-
super
end
+ def destroy
+ super
+ session[:locale] = nil
+ set_gettext_locale #Method defined at controllers/application_controller.rb
+ end
end
\ No newline at end of file
diff --git a/app/controllers/settings/plans_controller.rb b/app/controllers/settings/plans_controller.rb
index 9708521..c406401 100644
--- a/app/controllers/settings/plans_controller.rb
+++ b/app/controllers/settings/plans_controller.rb
@@ -1,7 +1,6 @@
module Settings
class PlansController < SettingsController
- before_filter :get_plan_list_columns
before_filter :get_settings
after_action :verify_authorized
@@ -23,6 +22,7 @@
if params[:commit] == 'Reset'
s.formatting = nil
s.fields = nil
+ s.title = nil
else
s.formatting = export_params[:formatting]
s.fields = export_params[:fields]
@@ -31,13 +31,13 @@
end
if settings.save
- respond_to do |format|
- format.html { redirect_to(export_project_path(@plan.project)) }
- end
+ flash[:notice] = _('Export settings updated successfully.')
else
- settings.formatting = nil
- @export_settings = settings
- render(action: :show)
+ flash[:alert] = _('An error has occurred while saving/resetting your export settings.')
+ end
+ respond_to do |format|
+ format.html { redirect_to(show_export_plan_path(@plan.id)) }
+ # format.json { render json: settings_json }
end
end
diff --git a/app/controllers/settings/projects_controller.rb b/app/controllers/settings/projects_controller.rb
deleted file mode 100644
index 8b0f800..0000000
--- a/app/controllers/settings/projects_controller.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-module Settings
- class ProjectsController < SettingsController
-
- before_filter :get_plan_list_columns
- before_filter :get_settings
-
- after_action :verify_authorized
-
- def show
- authorize [:settings, Project]
- respond_to do |format|
- format.html
-
- format.json{ render json: settings_json }
- end
- end
-
- def update
- authorize [:settings, Project]
- columns = (params[:columns] || {})
-
- if @settings.update_attributes(columns: columns)
- respond_to do |format|
- format.html { redirect_to(projects_path) }
-
- format.json{ render json: settings_json }
- end
- else
- render(action: :show) # Expect #show to display errors etc
- end
- end
-
- private
-
- def get_settings
- @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']
- end
-
- def settings_json
- @settings_json ||= { selected_columns: @settings.columns, all_columns: @all_columns }.to_json
- end
- end
-end
diff --git a/app/controllers/static_pages_controller.rb b/app/controllers/static_pages_controller.rb
index cded887..6f38009 100644
--- a/app/controllers/static_pages_controller.rb
+++ b/app/controllers/static_pages_controller.rb
@@ -13,61 +13,61 @@
end
def roadmap
+
end
- # GET /plans/publicly_available
- # -----------------------------------------------------------
def public_plans
- @plans = Plan.where(visibility: :publicly_visible).order(title: :asc)
+ @plans = Plan.publicly_visible
end
# GET /plans/[:plan_slug]/public_export
# -------------------------------------------------------------
def public_export
- @plan = Plan.find(params[:id])
+ redirect_to public_plans_path, notice: _('Exporting public plan is under development. Apologies for any inconvience.')
+ #@plan = Plan.find(params[:id])
# Force PDF response
- request.format = :pdf
+ #request.format = :pdf
# if the project is designated as public
- if @plan.visibility == :publicly_visible
- 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)
+ #if @plan.visibility == :publicly_visible
+ # 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
+ # 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
+ # @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
+ # 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
+ # 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
+ # redirect_to public_plans_path, notice: _('The plan is incomplete.')
+ # 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
+ # redirect_to public_plans_path, notice: _('This account does not have access to that plan.')
+ #end
end
end
\ No newline at end of file
diff --git a/app/controllers/templates_controller.rb b/app/controllers/templates_controller.rb
index 50f3c60..42eb4ee 100644
--- a/app/controllers/templates_controller.rb
+++ b/app/controllers/templates_controller.rb
@@ -6,416 +6,321 @@
respond_to :html
after_action :verify_authorized
- # GET /dmptemplates
+ # GET /org/admin/templates/:id/admin_index
+ # -----------------------------------------------------
def admin_index
authorize Template
- # institutional templates
- all_versions_own_templates = Template.where(org_id: current_user.org_id, customization_of: nil).order(version: :desc)
- current_templates = {}
- # take most recent version of each template
- all_versions_own_templates.each do |temp|
- if current_templates[temp.dmptemplate_id].nil?
- current_templates[temp.dmptemplate_id] = temp
- end
+
+ funder_templates, org_templates = [], []
+
+ # Get all of the unique template family ids (dmptemplate_id) for each funder and the current org
+ funder_ids = Org.funders.includes(:templates).collect{|f| f.templates.where(published: true).valid.collect{|ft| ft.dmptemplate_id } }.flatten.uniq
+ org_ids = current_user.org.templates.where(customization_of: nil).valid.collect{|t| t.dmptemplate_id }.flatten.uniq
+
+ org_ids.each do |id|
+ current = Template.current(id)
+ live = Template.live(id)
+ org_templates << {current: current, live: live}
end
- @templates_own = current_templates.values
- @other_published_version = {}
- current_templates.keys.each do |dmptemplate_id|
- @other_published_version[dmptemplate_id] = Template.where(org_id: current_user.org_id, dmptemplate_id: dmptemplate_id, published: true).present?
+ funder_ids.each do |id|
+ funder_live = Template.live(id)
+ current = Template.org_customizations(id, current_user.org_id)
+ # if we have a current template, check to see if there is a live version
+ live = current.nil? ? nil : Template.live(current.dmptemplate_id)
+ # need a current version, default to funder live if no custs exist
+ current = funder_live unless current.present?
+
+ funder_templates << {current: current, live: live, funder_live: funder_live, stale: funder_live.updated_at > current.created_at}
end
- # funders templates
- funders_templates = {}
- Org.includes(:templates).funder.each do |org|
- org.templates.where(customization_of: nil, published: true).order(version: :desc).each do |temp|
- if funders_templates[temp.dmptemplate_id].nil?
- funders_templates[temp.dmptemplate_id] = temp
- end
- end
- end
-
- @templates_funders = funders_templates.values
- # are any funder templates customized
- @templates_customizations = {}
- Template.where(org_id: current_user.org_id, customization_of: funders_templates.keys).order(version: :desc).each do |temp|
- if @templates_customizations[temp.customization_of].nil?
- @templates_customizations[temp.customization_of] = {}
- @templates_customizations[temp.customization_of][:temp] = temp
- @templates_customizations[temp.customization_of][:published] = temp.published
- else
- @templates_customizations[temp.customization_of][:published] = @templates_customizations[temp.customization_of][:published] || temp.published
- end
- end
+ @funder_templates = funder_templates.sort{|x,y|
+ x[:current].title <=> y[:current].title
+ }
+ @org_templates = org_templates.sort{|x,y|
+ x[:current].title <=> y[:current].title
+ }
end
-
- # GET /dmptemplates/1
- def admin_template
+ # GET /org/admin/templates/:id/admin_customize
+ # -----------------------------------------------------
+ def admin_customize
@template = Template.find(params[:id])
- # check to see if this is a funder template needing customized
- if @template.org_id != current_user.org_id
- # definitely need to deep_copy the given template
- new_customization = Template.deep_copy(@template)
- new_customization.org_id = current_user.org_id
- new_customization.published = false
- new_customization.customization_of = @template.dmptemplate_id
- # need to mark all Phases, questions, sections as not-modifiable
- new_customization.phases.includes(sections: :questions).each do |phase|
- phase.modifiable = false
- phase.save!
- phase.sections.each do |section|
- section.modifiable = false
- section.save!
- section.questions.each do |question|
- question.modifiable = false
- question.save!
- end
+ authorize @template
+
+ customisation = Template.deep_copy(@template)
+ customisation.org = current_user.org
+ customisation.version = 0
+ customisation.customization_of = @template.dmptemplate_id
+ customisation.dmptemplate_id = loop do
+ random = rand 2147483647
+ break random unless Template.exists?(dmptemplate_id: random)
+ end
+ customisation.save
+
+ customisation.phases.includes(:sections, :questions).each do |phase|
+ phase.modifiable = false
+ phase.save!
+ phase.sections.each do |section|
+ section.modifiable = false
+ section.save!
+ section.questions.each do |question|
+ question.modifiable = false
+ question.save!
end
end
- customizations = Template.includes(phases: [sections: [questions: :suggested_answers ]]).where(org_id: current_user.org_id, customization_of: @template.dmptemplate_id).order(version: :desc)
- if customizations.present?
- # existing customization to port over
- max_version = customizations.first
- new_customization.dmptemplate_id = max_version.dmptemplate_id
- new_customization.version = max_version.version + 1
- # here we rip the customizations out of the old template
- # First, we find any customized phases or sections
- max_version.phases.each do |phase|
- # check if the phase was added as a customization
- if phase.modifiable
- # deep copy the phase and add it to the template
- phase_copy = Phase.deep_copy(phase)
- phase_copy.number = new_customization.phases.length + 1
- phase_copy.template_id = new_customization.id
- phase_copy.save!
+ end
+
+ redirect_to admin_template_template_path(customisation)
+ end
+
+ # GET /org/admin/templates/:id/admin_transfer_customization
+ # the funder template's id is passed through here
+ # -----------------------------------------------------
+ def admin_transfer_customization
+ @template = Template.includes(:org).find(params[:id])
+ authorize @template
+ new_customization = Template.deep_copy(@template)
+ new_customization.org_id = current_user.org_id
+ new_customization.published = false
+ new_customization.customization_of = @template.dmptemplate_id
+ new_customization.dirty = true
+ new_customization.phases.includes(sections: :questions).each do |phase|
+ phase.modifiable = false
+ phase.save
+ phase.sections.each do |section|
+ section.modifiable = false
+ section.save
+ section.questions.each do |question|
+ question.modifiable = false
+ question.save
+ end
+ end
+ end
+ customizations = Template.includes(:org, phases:[sections: [questions: :annotations]]).where(org_id: current_user.org_id, customization_of: @template.dmptemplate_id).order(version: :desc)
+ # existing version to port over
+ max_version = customizations.first
+ new_customization.dmptemplate_id = max_version.dmptemplate_id
+ new_customization.version = max_version.version + 1
+ # here we rip the customizations out of the old template
+ # First, we find any customzed phases or sections
+ max_version.phases.each do |phase|
+ # check if the phase was added as a customization
+ if phase.modifiable
+ # deep copy the phase and add it to the template
+ phase_copy = Phase.deep_copy(phase)
+ phase_copy.number = new_customization.phases.length + 1
+ phase_copy.template_id = new_customization.id
+ phase_copy.save!
+ else
+ # iterate over the sections to see if any of them are customizations
+ phase.sections.each do |section|
+ if section.modifiable
+ # this is a custom section
+ section_copy = Section.deep_copy(section)
+ customization_phase = new_customization.phases.includes(:sections).where(number: phase.number).first
+ section_copy.phase_id = customization_phase.id
+ # custom sections get added to the end
+ section_copy.number = customization_phase.sections.length + 1
+ # section from phase with corresponding number in the main_template
+ section_copy.save!
else
- # iterate over the sections to see if any of them are customizations
- phase.sections.each do |section|
- if section.modifiable
- # this is a custom section
- section_copy = Section.deep_copy(section)
- customization_phase = new_customization.phases.includes(:sections).where(number: phase.number).first
- section_copy.phase_id = customization_phase.id
- # custom sections get added to the end
- section_copy.number = customization_phase.sections.length + 1
- # section from phase with corresponding number in the main_template
- section_copy.save!
- else
- # not a customized section, iterate over questions
- customization_phase = new_customization.phases.includes(sections: [questions: :suggested_answers]).where(number: phase.number).first
- customization_section = customization_phase.sections.where(number: section.number).first
- section.questions.each do |question|
- # find corresponding question in new template
- customization_question = customization_section.questions.where(number: question.number).first
- # apply suggested_answers
- question.suggested_answers.each do |suggested_answer|
- suggested_answer_copy = SuggestedAnswer.deep_copy(suggested_answer)
- suggested_answer_copy.org_id = current_user.org_id
- suggested_answer_copy.question_id = customization_question.id
- suggested_answer_copy.save!
- end
- # guidance attached to a question is also a form of customization
- # It will soon become an annotation of the question, and be combined with
- # suggested answers
- customization_question.guidance = customization_question.guidance + question.guidance
- customization_question.save!
- end
+ # not a customized section, iterate over questions
+ customization_phase = new_customization.phases.includes(sections: [questions: :annotations]).where(number: phase.number).first
+ customization_section = customization_phase.sections.where(number: section.number).first
+ section.questions.each do |question|
+ # find corresponding question in new template
+ customization_question = customization_section.questions.where(number: question.number).first
+ # apply annotations
+ question.annotations.where(org_id: current_user.org_id).each do |annotation|
+ annotation_copy = Annotation.deep_copy(annotation)
+ annotation_copy.question_id = customization_question.id
+ annotation_copy.save!
end
end
end
end
- else
- # first time customization
- new_customization.version = 0
- new_customization.dmptemplate_id = loop do
- random = rand 2147483647 # max int field in psql
- break random unless Template.exists?(dmptemplate_id: random)
- end
end
- new_customization.save!
- @template = new_customization
end
- # needed for some post-migration edge cases
- # some customized templates which were edited
- if @template.published
+ new_customization.save
+ redirect_to admin_template_template_path(new_customization)
+ end
+
+ # PUT /org/admin/templates/:id/admin_publish
+ # -----------------------------------------------------
+ def admin_publish
+ @template = Template.find(params[:id])
+ authorize @template
+
+ current = Template.current(@template.dmptemplate_id)
+
+ # Only allow the current version to be updated
+ if current != @template
+ redirect_to admin_template_template_path(@template), notice: _('You can not publish a historical version of this template.')
+
+ else
+ # Unpublish the older published version if there is one
+ live = Template.live(@template.dmptemplate_id)
+ if !live.nil? and self != live
+ live.published = false
+ live.save!
+ end
+ # Set the dirty flag to false
+ @template.dirty = false
+ @template.published = true
+ @template.save
+
+ flash[:notice] = _('Your template has been published and is now available to users.')
+
+ redirect_to admin_index_template_path(current_user.org)
+ end
+ end
+
+ # PUT /org/admin/templates/:id/admin_unpublish
+ # -----------------------------------------------------
+ def admin_unpublish
+ template = Template.find(params[:id])
+ authorize template
+
+ # Unpublish the live version
+ @template = Template.live(template.dmptemplate_id)
+
+ if @template.nil?
+ flash[:notice] = _('That template is not currently published.')
+ else
+ @template.published = false
+ @template.save
+ flash[:notice] = _('Your template is no longer published. Users will not be able to create new DMPs for this template until you re-publish it')
+ end
+
+ redirect_to admin_index_template_path(current_user.org)
+ end
+
+ # GET /org/admin/templates/:id/admin_template
+ # -----------------------------------------------------
+ def admin_template
+ @template = Template.includes(:org, phases: [sections: [questions: [:question_options, :question_format, :annotations]]]).find(params[:id])
+ authorize @template
+
+ @current = Template.current(@template.dmptemplate_id)
+
+ if @template == @current
+ # If the template is published
+ if @template.published?
+ # We need to create a new, editable version
+ new_version = Template.deep_copy(@template)
+ new_version.version = (@template.version + 1)
+ new_version.published = false
+ new_version.save
+ @template = new_version
+# @current = Template.current(@template.dmptemplate_id)
+ end
+ else
+ flash[:notice] = _('You are viewing a historical version of this template. You will not be able to make changes.')
+ end
+
+ # If the template is published
+ if @template.published?
+ # We need to create a new, editable version
new_version = Template.deep_copy(@template)
- new_version.version = @template.version + 1
+ new_version.version = (@template.version + 1)
new_version.published = false
- new_version.save!
+ new_version.save
@template = new_version
end
- authorize @template
+
+ # once the correct template has been generated, we convert it to hash
+ @hash = @template.to_hash
end
- # PUT /dmptemplates/1
+ # PUT /org/admin/templates/:id/admin_update
+ # -----------------------------------------------------
def admin_update
@template = Template.find(params[:id])
authorize @template
- if @template.published?
- # published templates cannot be edited
- redirect_to admin_template_template_path(@template), notice: I18n.t('org_admin.templates.read_only') and return
- end
- @template.description = params["template-desc"]
- if @template.update_attributes(params[:template])
- if @template.published
- # create a new template version if this template became published
- new_version = Template.deep_copy(@template)
- new_version.version = @template.version + 1
- new_version.published = false
- new_version.save!
- end
- redirect_to admin_index_template_path(), notice: I18n.t('org_admin.templates.updated_message')
+
+ current = Template.current(@template.dmptemplate_id)
+
+ # Only allow the current version to be updated
+ if current != @template
+ redirect_to admin_template_template_path(@template), notice: _('You can not edit a historical version of this template.')
+
else
- render action: "edit"
+ if @template.description != params["template-desc"] ||
+ @template.title != params[:template][:title]
+ @template.dirty = true
+ end
+
+ @template.description = params["template-desc"]
+ if @template.update_attributes(params[:template])
+ flash[:notice] = _('Information was successfully updated.')
+
+ else
+ flash[:notice] = failed_update_error(@template, _('template'))
+ end
+
+ @hash = @template.to_hash
+ render 'admin_template'
end
end
- # GET /dmptemplates/new
+ # GET /org/admin/templates/:id/admin_new
+ # -----------------------------------------------------
def admin_new
authorize Template
end
- # POST /dmptemplates
- # creates a new template with version 0 and new dmptemplate_id
+ # POST /org/admin/templates/:id/admin_create
+ # -----------------------------------------------------
def admin_create
+ # creates a new template with version 0 and new dmptemplate_id
@template = Template.new(params[:template])
- @template.org_id = current_user.org_id
- @template.description = params['template-desc']
- @template.published = false
- @template.version = 0
- # Generate a unique identifier for the dmptemplate_id
- @template.dmptemplate_id = loop do
- random = rand 2147483647
- break random unless Template.exists?(dmptemplate_id: random)
- end
authorize @template
+ @template.org_id = current_user.org.id
+ @template.description = params['template-desc']
+
if @template.save
- redirect_to admin_template_template_path(@template), notice: I18n.t('org_admin.templates.created_message')
+ redirect_to admin_template_template_path(@template), notice: _('Information was successfully created.')
else
+ @hash = @template.to_hash
+ flash[:notice] = failed_create_error(@template, _('template'))
render action: "admin_new"
end
end
- # DELETE /dmptemplates/1
+ # DELETE /org/admin/templates/:id/admin_destroy
+ # -----------------------------------------------------
def admin_destroy
@template = Template.find(params[:id])
authorize @template
- @template.destroy
- redirect_to admin_index_template_path
+
+ current = Template.current(@template.dmptemplate_id)
+
+ # Only allow the current version to be destroyed
+ if current == @template
+ if @template.destroy
+ redirect_to admin_index_template_path
+ else
+ @hash = @template.to_hash
+ flash[:notice] = failed_destroy_error(@template, _('template'))
+ render admin_template_template_path(@template)
+ end
+ else
+ flash[:notice] = _('You cannot delete historical versions of this template.')
+ redirect_to admin_index_template_path
+ end
end
- # GET /templates/1
+ # GET /org/admin/templates/:id/admin_template_history
+ # -----------------------------------------------------
def admin_template_history
@template = Template.find(params[:id])
authorize @template
@templates = Template.where(dmptemplate_id: @template.dmptemplate_id).order(:version)
+ @current = Template.current(@template.dmptemplate_id)
end
-
-
- # PHASES
-
- #show and edit a phase of the template
- def admin_phase
- @phase = Phase.find(params[:id])
- authorize @phase.template
- @edit = params[:edit] == "true" ? true : false
- #verify if there are any sections if not create one
- @sections = @phase.sections
- if !@sections.any?() || @sections.count == 0
- @section = @phase.sections.build
- @section.phase = @phase
- @section.title = ''
- @section.number = 1
- @section.published = true
- @section.modifiable = true
- @section.save
- @new_sec = true
- end
- #verify if section_id has been passed, if so then open that section
- if params.has_key?(:section_id)
- @open = true
- @section_id = params[:section_id].to_i
- end
- if params.has_key?(:question_id)
- @question_id = params[:question_id].to_i
- end
- end
-
-
- #preview a phase
- def admin_previewphase
- @phase = Phase.find(params[:id])
- authorize @phase.template
- @template = @phase.template
- end
-
-
- #add a new phase to a template
- def admin_addphase
- @template = Template.find(params[:id])
- @phase = Phase.new
- authorize @template
- @phase.number = @template.phases.count + 1
- end
-
-
- #create a phase
- def admin_createphase
- @phase = Phase.new(params[:phase])
- authorize @phase.template
- @phase.description = params["phase-desc"]
- @phase.modifiable = true
- if @phase.save
- redirect_to admin_phase_template_path(id: @phase.id, edit: 'true'), notice: I18n.t('org_admin.templates.created_message')
- else
- render action: "admin_phase"
- end
- end
-
-
- #update a phase of a template
- def admin_updatephase
- @phase = Phase.find(params[:id])
- authorize @phase.template
- @phase.description = params["phase-desc"]
- if @phase.update_attributes(params[:phase])
- redirect_to admin_phase_template_path(@phase), notice: I18n.t('org_admin.templates.updated_message')
- else
- render action: "admin_phase"
- end
- end
-
- #delete a phase
- def admin_destroyphase
- @phase = Phase.find(params[:phase_id])
- authorize @phase.template
- @template = @phase.template
- @phase.destroy
- redirect_to admin_template_template_path(@template), notice: I18n.t('org_admin.templates.destroyed_message')
- end
-
-# SECTIONS
- #create a section
- def admin_createsection
- @section = Section.new(params[:section])
- authorize @section.phase.template
- @section.description = params["section-desc"]
- @section.modifiable = true
- if @section.save
- redirect_to admin_phase_template_path(id: @section.phase_id,
- :section_id => @section.id, edit: 'true'), notice: I18n.t('org_admin.templates.created_message')
- else
- render action: "admin_phase"
- end
- end
-
-
- #update a section of a template
- def admin_updatesection
- @section = Section.find(params[:id])
- authorize @section.phase.template
- @section.description = params["section-desc-#{params[:id]}"]
- @phase = @section.phase
- if @section.update_attributes(params[:section])
- redirect_to admin_phase_template_path(id: @phase.id, section_id: @section.id , edit: 'true'), notice: I18n.t('org_admin.templates.updated_message')
- else
- render action: "admin_phase"
- end
- end
-
-
- #delete a section and questions
- def admin_destroysection
- @section = Section.find(params[:section_id])
- authorize @section.phase.template
- @phase = @section.phase
- @section.destroy
- redirect_to admin_phase_template_path(id: @phase.id, edit: 'true' ), notice: I18n.t('org_admin.templates.destroyed_message')
- end
-
-
-# QUESTIONS
-
- #create a question
- def admin_createquestion
- @question = Question.new(params[:question])
- authorize @question.section.phase.template
- @question.guidance = params["new-question-guidance"]
- @question.default_value = params["new-question-default-value"]
- if @question.save!
- redirect_to admin_phase_template_path(id: @question.section.phase_id, section_id: @question.section_id, question_id: @question.id, edit: 'true'), notice: I18n.t('org_admin.templates.created_message')
- else
- render action: "admin_phase"
- end
- end
-
- #update a question of a template
- def admin_updatequestion
- @question = Question.find(params[:id])
- authorize @question.section.phase.template
- @question.guidance = params["question-guidance-#{params[:id]}"]
- @question.default_value = params["question-default-value-#{params[:id]}"]
- @section = @question.section
- @phase = @section.phase
- if @question.update_attributes(params[:question])
- redirect_to admin_phase_template_path(id: @phase.id, section_id: @section.id, question_id: @question.id, edit: 'true'), notice: I18n.t('org_admin.templates.updated_message')
- else
- render action: "admin_phase"
- end
- end
-
- #delete question
- def admin_destroyquestion
- @question = Question.find(params[:question_id])
- authorize @question.section.phase.template
- @section = @question.section
- @phase = @section.phase
- @question.destroy
- redirect_to admin_phase_template_path(id: @phase.id, section_id: @section.id, edit: 'true'), notice: I18n.t('org_admin.templates.destroyed_message')
- end
-
-
- #SUGGESTED ANSWERS
- #create suggested answers
- def admin_createsuggestedanswer
- @suggested_answer = SuggestedAnswer.new(params[:suggested_answer])
- authorize @suggested_answer.question.section.phase.template
- if @suggested_answer.save
- redirect_to admin_phase_template_path(id: @suggested_answer.question.section.phase_id, section_id: @suggested_answer.question.section_id, question_id: @suggested_answer.question.id, edit: 'true'), notice: I18n.t('org_admin.templates.created_message')
- else
- render action: "admin_phase"
- end
- end
-
-
- #update a suggested answer of a template
- def admin_updatesuggestedanswer
- @suggested_answer = SuggestedAnswer.find(params[:id])
- authorize @suggested_answer.question.section.phase.template
- @question = @suggested_answer.question
- @section = @question.section
- @phase = @section.phase
- if @suggested_answer.update_attributes(params[:suggested_answer])
- redirect_to admin_phase_template_path(id: @phase.id, section_id: @section.id, question_id: @question.id, edit: 'true'), notice: I18n.t('org_admin.templates.updated_message')
- else
- render action: "admin_phase"
- end
- end
-
- #delete a suggested answer
- def admin_destroysuggestedanswer
- @suggested_answer = SuggestedAnswer.find(params[:suggested_answer])
- authorize @suggested_answer.question.section.phase.template
- @question = @suggested_answer.question
- @section = @question.section
- @phase = @section.phase
- @suggested_answer.destroy
- redirect_to admin_phase_template_path(id: @phase.id, section_id: @section.id, edit: 'true'), notice: I18n.t('org_admin.templates.destroyed_message')
- end
-
-end
\ No newline at end of file
+end
diff --git a/app/controllers/user_identifiers_controller.rb b/app/controllers/user_identifiers_controller.rb
index 040a50b..6b78c8e 100644
--- a/app/controllers/user_identifiers_controller.rb
+++ b/app/controllers/user_identifiers_controller.rb
@@ -1,25 +1,23 @@
class UserIdentifiersController < ApplicationController
+ respond_to :html
+ after_action :verify_authorized
# 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
+ authorize UserIdentifier
+ 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] = _('Successfully unlinked your account from %{is}.') % {is: identifier.identifier_scheme.description}
+ else
+ flash[:notice] = _('Unable to unlink your account from %{is}.') % {is: identifier.identifier_scheme.description}
end
+
+ redirect_to edit_user_registration_path
end
-end
\ No newline at end of file
+end
diff --git a/app/controllers/users/omniauth_callbacks_controller.rb b/app/controllers/users/omniauth_callbacks_controller.rb
index 593e146..d50e397 100644
--- a/app/controllers/users/omniauth_callbacks_controller.rb
+++ b/app/controllers/users/omniauth_callbacks_controller.rb
@@ -31,8 +31,14 @@
# Otherwise sign them in
else
- sign_in_and_redirect user, event: :authentication
- set_flash_message(:notice, :success, kind: scheme.name) if is_navigational_format?
+ # Until ORCID becomes supported as a login method
+ if scheme.name == 'shibboleth'
+ set_flash_message(:notice, :success, kind: scheme.description) if is_navigational_format?
+ sign_in_and_redirect user, event: :authentication
+ else
+ flash[:notice] = t('identifier_schemes.new_login_success')
+ redirect_to new_user_registration_url
+ end
end
# The user is already logged in and just registering the uid with us
@@ -43,9 +49,9 @@
identifier: request.env["omniauth.auth"].uid,
user: current_user)
- flash[:notice] = t('identifier_schemes.connect_success', scheme: scheme.name)
+ flash[:notice] = _('Your account has been successfully linked to %{scheme}.') % { scheme: scheme.description }
else
- flash[:notice] = t('identifier_schemes.connect_failure', scheme: scheme.name)
+ flash[:notice] = _('Unable to link your account to %{scheme}.') % { scheme: scheme.description }
end
end
@@ -53,63 +59,9 @@
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
diff --git a/app/controllers/users/omniauth_shibboleth_request_controller.rb b/app/controllers/users/omniauth_shibboleth_request_controller.rb
deleted file mode 100644
index 3190c2f..0000000
--- a/app/controllers/users/omniauth_shibboleth_request_controller.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-class Users::OmniauthShibbolethRequestController < ApplicationController
- before_filter :authenticate_user!, only: :associate
-
- def redirect
- if !current_user.nil? && !current_user.org.nil?
- idp = params[:idp] || current_user.org.wayfless_entity
- else
- idp = params[:idp]
- end
- query_params = {target: user_omniauth_callback_path(:shibboleth)}
- unless idp.blank?
- query_params[:entityID] = idp
- end
- redirect_to "#{Rails.application.config.shibboleth_login}?#{query_params.to_query}", status: 302
- end
-
- def associate
- # This action is protected - can only be reached if user is already logged in.
- # See before_filter
- redirect_to user_omniauth_callback_path(:shibboleth)
- end
-end
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 6ca0cd7..b26a62e 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -18,12 +18,13 @@
@user = User.includes(:perms).find(params[:id])
authorize @user
user_perms = current_user.perms
- @perms = user_perms & Perm.where(name: [constant("user_role_types.change_org_details"),constant("user_role_types.use_api"), constant("user_role_types.modify_guidance"), constant("user_role_types.modify_templates"), constant("user_role_types.grant_permissions")])
+ @perms = user_perms & [Perm.grant_permissions, Perm.modify_templates, Perm.modify_guidance, Perm.use_api, Perm.change_org_details]
end
##
# POST - updates the permissions for a user
# redirects to the admin_index action
+ # should add validation that the perms given are current perms of the current_user
def admin_update_permissions
@user = User.includes(:perms).find(params[:id])
authorize @user
@@ -33,21 +34,25 @@
if @user.perms.include? perm
if ! perms.include? perm
@user.perms.delete(perm)
- if perm.name == constant("user_role_types.use_api")
+ if perm.id == Perm.use_api.id
@user.remove_token!
end
end
else
if perms.include? perm
@user.perms << perm
- if perm.name == constant("user_role_types.use_api")
+ if perm.id == Perm.use_api.id
@user.keep_or_generate_token!
end
end
end
end
- @user.save!
- redirect_to({controller: 'users', action: 'admin_index'}, {notice: I18n.t('helpers.success')})
+
+ if @user.save!
+ redirect_to({controller: 'users', action: 'admin_index'}, {notice: _('Information was successfully updated.')}) # helpers.success key does not exist, replaced with a generic string
+ else
+ flash[:notice] = failed_update_error(@user, _('user'))
+ end
end
end
diff --git a/app/dashboards/annotation_dashboard.rb b/app/dashboards/annotation_dashboard.rb
new file mode 100644
index 0000000..e26b609
--- /dev/null
+++ b/app/dashboards/annotation_dashboard.rb
@@ -0,0 +1,60 @@
+require "administrate/base_dashboard"
+
+class AnnotationDashboard < Administrate::BaseDashboard
+ # ATTRIBUTE_TYPES
+ # a hash that describes the type of each of the model's fields.
+ #
+ # Each different type represents an Administrate::Field object,
+ # which determines how the attribute is displayed
+ # on pages throughout the dashboard.
+ ATTRIBUTE_TYPES = {
+ org: Field::BelongsTo,
+ question: Field::BelongsTo,
+ id: Field::Number,
+ text: Field::Text,
+ type: Field::String.with_options(searchable: false),
+ created_at: Field::DateTime,
+ updated_at: Field::DateTime,
+ }.freeze
+
+ # COLLECTION_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's index page.
+ #
+ # By default, it's limited to four items to reduce clutter on index pages.
+ # Feel free to add, remove, or rearrange items.
+ COLLECTION_ATTRIBUTES = [
+ :org,
+ :question,
+ :id,
+ :text,
+ ].freeze
+
+ # SHOW_PAGE_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's show page.
+ SHOW_PAGE_ATTRIBUTES = [
+ :org,
+ :question,
+ :id,
+ :text,
+ :type,
+ :created_at,
+ :updated_at,
+ ].freeze
+
+ # FORM_ATTRIBUTES
+ # an array of attributes that will be displayed
+ # on the model's form (`new` and `edit`) pages.
+ FORM_ATTRIBUTES = [
+ :org,
+ :question,
+ :text,
+ :type,
+ ].freeze
+
+ # Overwrite this method to customize how annotations are displayed
+ # across all pages of the admin dashboard.
+ #
+ # def display_resource(annotation)
+ # "Annotation ##{annotation.id}"
+ # end
+end
diff --git a/app/dashboards/answer_dashboard.rb b/app/dashboards/answer_dashboard.rb
new file mode 100644
index 0000000..ad7df7f
--- /dev/null
+++ b/app/dashboards/answer_dashboard.rb
@@ -0,0 +1,69 @@
+require "administrate/base_dashboard"
+
+class AnswerDashboard < Administrate::BaseDashboard
+ # ATTRIBUTE_TYPES
+ # a hash that describes the type of each of the model's fields.
+ #
+ # Each different type represents an Administrate::Field object,
+ # which determines how the attribute is displayed
+ # on pages throughout the dashboard.
+ ATTRIBUTE_TYPES = {
+ question: Field::BelongsTo,
+ user: Field::BelongsTo,
+ plan: Field::BelongsTo,
+ notes: Field::HasMany,
+ question_options: Field::HasMany,
+ id: Field::Number,
+ text: Field::Text,
+ created_at: Field::DateTime,
+ updated_at: Field::DateTime,
+ lock_version: Field::Number,
+ }.freeze
+
+ # COLLECTION_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's index page.
+ #
+ # By default, it's limited to four items to reduce clutter on index pages.
+ # Feel free to add, remove, or rearrange items.
+ COLLECTION_ATTRIBUTES = [
+ :question,
+ :user,
+ :plan,
+ :notes,
+ ].freeze
+
+ # SHOW_PAGE_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's show page.
+ SHOW_PAGE_ATTRIBUTES = [
+ :question,
+ :user,
+ :plan,
+ :notes,
+ :question_options,
+ :id,
+ :text,
+ :created_at,
+ :updated_at,
+ :lock_version,
+ ].freeze
+
+ # FORM_ATTRIBUTES
+ # an array of attributes that will be displayed
+ # on the model's form (`new` and `edit`) pages.
+ FORM_ATTRIBUTES = [
+ :question,
+ :user,
+ :plan,
+ :notes,
+ :question_options,
+ :text,
+ :lock_version,
+ ].freeze
+
+ # Overwrite this method to customize how answers are displayed
+ # across all pages of the admin dashboard.
+ #
+ # def display_resource(answer)
+ # "Answer ##{answer.id}"
+ # end
+end
diff --git a/app/dashboards/exported_plan_dashboard.rb b/app/dashboards/exported_plan_dashboard.rb
new file mode 100644
index 0000000..ec618cf
--- /dev/null
+++ b/app/dashboards/exported_plan_dashboard.rb
@@ -0,0 +1,63 @@
+require "administrate/base_dashboard"
+
+class ExportedPlanDashboard < Administrate::BaseDashboard
+ # ATTRIBUTE_TYPES
+ # a hash that describes the type of each of the model's fields.
+ #
+ # Each different type represents an Administrate::Field object,
+ # which determines how the attribute is displayed
+ # on pages throughout the dashboard.
+ ATTRIBUTE_TYPES = {
+ plan: Field::BelongsTo,
+ user: Field::BelongsTo,
+ setting_objects: Field::HasMany.with_options(class_name: "Settings::Template"),
+ id: Field::Number,
+ format: Field::String,
+ created_at: Field::DateTime,
+ updated_at: Field::DateTime,
+ phase_id: Field::Number,
+ }.freeze
+
+ # COLLECTION_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's index page.
+ #
+ # By default, it's limited to four items to reduce clutter on index pages.
+ # Feel free to add, remove, or rearrange items.
+ COLLECTION_ATTRIBUTES = [
+ :plan,
+ :user,
+ :setting_objects,
+ :id,
+ ].freeze
+
+ # SHOW_PAGE_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's show page.
+ SHOW_PAGE_ATTRIBUTES = [
+ :plan,
+ :user,
+ :setting_objects,
+ :id,
+ :format,
+ :created_at,
+ :updated_at,
+ :phase_id,
+ ].freeze
+
+ # FORM_ATTRIBUTES
+ # an array of attributes that will be displayed
+ # on the model's form (`new` and `edit`) pages.
+ FORM_ATTRIBUTES = [
+ :plan,
+ :user,
+ :setting_objects,
+ :format,
+ :phase_id,
+ ].freeze
+
+ # Overwrite this method to customize how exported plans are displayed
+ # across all pages of the admin dashboard.
+ #
+ # def display_resource(exported_plan)
+ # "ExportedPlan ##{exported_plan.id}"
+ # end
+end
diff --git a/app/dashboards/guidance_dashboard.rb b/app/dashboards/guidance_dashboard.rb
new file mode 100644
index 0000000..c76c41b
--- /dev/null
+++ b/app/dashboards/guidance_dashboard.rb
@@ -0,0 +1,63 @@
+require "administrate/base_dashboard"
+
+class GuidanceDashboard < Administrate::BaseDashboard
+ # ATTRIBUTE_TYPES
+ # a hash that describes the type of each of the model's fields.
+ #
+ # Each different type represents an Administrate::Field object,
+ # which determines how the attribute is displayed
+ # on pages throughout the dashboard.
+ ATTRIBUTE_TYPES = {
+ guidance_group: Field::BelongsTo,
+ themes: Field::HasMany,
+ id: Field::Number,
+ text: Field::Text,
+ created_at: Field::DateTime,
+ updated_at: Field::DateTime,
+ question_id: Field::Number,
+ published: Field::Boolean,
+ }.freeze
+
+ # COLLECTION_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's index page.
+ #
+ # By default, it's limited to four items to reduce clutter on index pages.
+ # Feel free to add, remove, or rearrange items.
+ COLLECTION_ATTRIBUTES = [
+ :guidance_group,
+ :themes,
+ :id,
+ :text,
+ ].freeze
+
+ # SHOW_PAGE_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's show page.
+ SHOW_PAGE_ATTRIBUTES = [
+ :guidance_group,
+ :themes,
+ :id,
+ :text,
+ :created_at,
+ :updated_at,
+ :question_id,
+ :published,
+ ].freeze
+
+ # FORM_ATTRIBUTES
+ # an array of attributes that will be displayed
+ # on the model's form (`new` and `edit`) pages.
+ FORM_ATTRIBUTES = [
+ :guidance_group,
+ :themes,
+ :text,
+ :question_id,
+ :published,
+ ].freeze
+
+ # Overwrite this method to customize how guidances are displayed
+ # across all pages of the admin dashboard.
+ #
+ # def display_resource(guidance)
+ # "Guidance ##{guidance.id}"
+ # end
+end
diff --git a/app/dashboards/guidance_group_dashboard.rb b/app/dashboards/guidance_group_dashboard.rb
new file mode 100644
index 0000000..76e2f09
--- /dev/null
+++ b/app/dashboards/guidance_group_dashboard.rb
@@ -0,0 +1,70 @@
+require "administrate/base_dashboard"
+
+class GuidanceGroupDashboard < Administrate::BaseDashboard
+ # ATTRIBUTE_TYPES
+ # a hash that describes the type of each of the model's fields.
+ #
+ # Each different type represents an Administrate::Field object,
+ # which determines how the attribute is displayed
+ # on pages throughout the dashboard.
+ ATTRIBUTE_TYPES = {
+ org: Field::BelongsTo,
+ guidances: Field::HasMany,
+ plans: Field::HasMany,
+ id: Field::Number,
+ name: Field::String,
+ created_at: Field::DateTime,
+ updated_at: Field::DateTime,
+ optional_subset: Field::Boolean,
+ published: Field::Boolean,
+ }.freeze
+
+ # COLLECTION_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's index page.
+ #
+ # By default, it's limited to four items to reduce clutter on index pages.
+ # Feel free to add, remove, or rearrange items.
+ COLLECTION_ATTRIBUTES = [
+ :name,
+ :org,
+ :guidances,
+# :plans,
+ :id,
+ ].freeze
+
+ # SHOW_PAGE_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's show page.
+ SHOW_PAGE_ATTRIBUTES = [
+ :org,
+ :guidances,
+# :plans,
+ :id,
+ :name,
+ :created_at,
+ :updated_at,
+ :optional_subset,
+ :published,
+ ].freeze
+
+ # FORM_ATTRIBUTES
+ # an array of attributes that will be displayed
+ # on the model's form (`new` and `edit`) pages.
+ FORM_ATTRIBUTES = [
+ :org,
+ :guidances,
+# :plans,
+ :name,
+ :optional_subset,
+ :published,
+ ].freeze
+
+ # Overwrite this method to customize how guidance groups are displayed
+ # across all pages of the admin dashboard.
+ #
+ # def display_resource(guidance_group)
+ # "GuidanceGroup ##{guidance_group.id}"
+ # end
+ def display_resource(guidance_group)
+ guidance_group.name
+ end
+end
diff --git a/app/dashboards/identifier_scheme_dashboard.rb b/app/dashboards/identifier_scheme_dashboard.rb
new file mode 100644
index 0000000..7dc1dca
--- /dev/null
+++ b/app/dashboards/identifier_scheme_dashboard.rb
@@ -0,0 +1,68 @@
+require "administrate/base_dashboard"
+
+class IdentifierSchemeDashboard < Administrate::BaseDashboard
+ # ATTRIBUTE_TYPES
+ # a hash that describes the type of each of the model's fields.
+ #
+ # Each different type represents an Administrate::Field object,
+ # which determines how the attribute is displayed
+ # on pages throughout the dashboard.
+ ATTRIBUTE_TYPES = {
+ user_identifiers: Field::HasMany,
+ users: Field::HasMany,
+ id: Field::Number,
+ name: Field::String,
+ description: Field::String,
+ active: Field::Boolean,
+ created_at: Field::DateTime,
+ updated_at: Field::DateTime,
+ }.freeze
+
+ # COLLECTION_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's index page.
+ #
+ # By default, it's limited to four items to reduce clutter on index pages.
+ # Feel free to add, remove, or rearrange items.
+ COLLECTION_ATTRIBUTES = [
+ :name,
+ :description,
+ :user_identifiers,
+ :users,
+ ].freeze
+
+ # SHOW_PAGE_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's show page.
+ SHOW_PAGE_ATTRIBUTES = [
+ :user_identifiers,
+ :users,
+ :id,
+ :name,
+ :description,
+ :active,
+ :created_at,
+ :updated_at,
+ ].freeze
+
+ # FORM_ATTRIBUTES
+ # an array of attributes that will be displayed
+ # on the model's form (`new` and `edit`) pages.
+ FORM_ATTRIBUTES = [
+ :user_identifiers,
+ :users,
+ :name,
+ :description,
+ :active,
+ ].freeze
+
+ # Overwrite this method to customize how identifier schemes are displayed
+ # across all pages of the admin dashboard.
+ #
+ # def display_resource(identifier_scheme)
+ # "IdentifierScheme ##{identifier_scheme.id}"
+ # end
+
+ def display_resource(identifier_scheme)
+ identifier_scheme.description
+ end
+
+end
diff --git a/app/dashboards/language_dashboard.rb b/app/dashboards/language_dashboard.rb
new file mode 100644
index 0000000..c888a7d
--- /dev/null
+++ b/app/dashboards/language_dashboard.rb
@@ -0,0 +1,68 @@
+require "administrate/base_dashboard"
+
+class LanguageDashboard < Administrate::BaseDashboard
+ # ATTRIBUTE_TYPES
+ # a hash that describes the type of each of the model's fields.
+ #
+ # Each different type represents an Administrate::Field object,
+ # which determines how the attribute is displayed
+ # on pages throughout the dashboard.
+ ATTRIBUTE_TYPES = {
+ users: Field::HasMany,
+ orgs: Field::HasMany,
+ id: Field::Number,
+ abbreviation: Field::String,
+ description: Field::String,
+ name: Field::String,
+ default_language: Field::Boolean,
+ }.freeze
+
+ # COLLECTION_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's index page.
+ #
+ # By default, it's limited to four items to reduce clutter on index pages.
+ # Feel free to add, remove, or rearrange items.
+ COLLECTION_ATTRIBUTES = [
+ :abbreviation,
+ :name,
+ :users,
+ :orgs,
+ :default_language,
+ ].freeze
+
+ # SHOW_PAGE_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's show page.
+ SHOW_PAGE_ATTRIBUTES = [
+ :users,
+ :orgs,
+ :id,
+ :abbreviation,
+ :description,
+ :name,
+ :default_language,
+ ].freeze
+
+ # FORM_ATTRIBUTES
+ # an array of attributes that will be displayed
+ # on the model's form (`new` and `edit`) pages.
+ FORM_ATTRIBUTES = [
+ # :users,
+ # :orgs,
+ :abbreviation,
+ :description,
+ :name,
+ :default_language,
+ ].freeze
+
+ # Overwrite this method to customize how languages are displayed
+ # across all pages of the admin dashboard.
+ #
+ # def display_resource(language)
+ # "Language ##{language.id}"
+ # end
+
+ def display_resource(language)
+ language.abbreviation
+ end
+
+end
diff --git a/app/dashboards/note_dashboard.rb b/app/dashboards/note_dashboard.rb
new file mode 100644
index 0000000..5912418
--- /dev/null
+++ b/app/dashboards/note_dashboard.rb
@@ -0,0 +1,63 @@
+require "administrate/base_dashboard"
+
+class NoteDashboard < Administrate::BaseDashboard
+ # ATTRIBUTE_TYPES
+ # a hash that describes the type of each of the model's fields.
+ #
+ # Each different type represents an Administrate::Field object,
+ # which determines how the attribute is displayed
+ # on pages throughout the dashboard.
+ ATTRIBUTE_TYPES = {
+ answer: Field::BelongsTo,
+ user: Field::BelongsTo,
+ id: Field::Number,
+ text: Field::Text,
+ archived: Field::Boolean,
+ archived_by: Field::Number,
+ created_at: Field::DateTime,
+ updated_at: Field::DateTime,
+ }.freeze
+
+ # COLLECTION_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's index page.
+ #
+ # By default, it's limited to four items to reduce clutter on index pages.
+ # Feel free to add, remove, or rearrange items.
+ COLLECTION_ATTRIBUTES = [
+ :answer,
+ :user,
+ :id,
+ :text,
+ ].freeze
+
+ # SHOW_PAGE_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's show page.
+ SHOW_PAGE_ATTRIBUTES = [
+ :answer,
+ :user,
+ :id,
+ :text,
+ :archived,
+ :archived_by,
+ :created_at,
+ :updated_at,
+ ].freeze
+
+ # FORM_ATTRIBUTES
+ # an array of attributes that will be displayed
+ # on the model's form (`new` and `edit`) pages.
+ FORM_ATTRIBUTES = [
+ :answer,
+ :user,
+ :text,
+ :archived,
+ :archived_by,
+ ].freeze
+
+ # Overwrite this method to customize how notes are displayed
+ # across all pages of the admin dashboard.
+ #
+ # def display_resource(note)
+ # "Note ##{note.id}"
+ # end
+end
diff --git a/app/dashboards/org_dashboard.rb b/app/dashboards/org_dashboard.rb
new file mode 100644
index 0000000..72f8962
--- /dev/null
+++ b/app/dashboards/org_dashboard.rb
@@ -0,0 +1,115 @@
+require "administrate/base_dashboard"
+
+class OrgDashboard < Administrate::BaseDashboard
+ # ATTRIBUTE_TYPES
+ # a hash that describes the type of each of the model's fields.
+ #
+ # Each different type represents an Administrate::Field object,
+ # which determines how the attribute is displayed
+ # on pages throughout the dashboard.
+ ATTRIBUTE_TYPES = {
+ language: Field::BelongsTo,
+ guidance_groups: Field::HasMany,
+ templates: Field::HasMany,
+ users: Field::HasMany,
+ annotations: Field::HasMany,
+ token_permission_types: Field::HasMany,
+ id: Field::Number,
+ name: Field::String,
+ abbreviation: Field::String,
+ target_url: Field::String,
+ wayfless_entity: Field::String,
+ created_at: Field::DateTime,
+ updated_at: Field::DateTime,
+ parent_id: Field::Number,
+ is_other: Field::Boolean,
+ sort_name: Field::String,
+ banner_text: Field::Text,
+ logo_file_name: Field::String,
+ region_id: Field::Number,
+ logo_uid: Field::String,
+ logo_name: Field::String,
+ contact_email: Field::String,
+ org_type: Field::Number,
+ }.freeze
+
+ # COLLECTION_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's index page.
+ #
+ # By default, it's limited to four items to reduce clutter on index pages.
+ # Feel free to add, remove, or rearrange items.
+ COLLECTION_ATTRIBUTES = [
+ :name,
+ :abbreviation,
+ :language,
+ :guidance_groups,
+# :templates,
+ :contact_email,
+ :org_type,
+ ].freeze
+
+ # SHOW_PAGE_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's show page.
+ SHOW_PAGE_ATTRIBUTES = [
+ :name,
+ :abbreviation,
+ :language,
+ :guidance_groups,
+# :templates,
+ :contact_email,
+ :org_type,
+ :users,
+ :annotations,
+ :token_permission_types,
+ :id,
+ :target_url,
+ :wayfless_entity,
+ :created_at,
+ :updated_at,
+ :parent_id,
+ :is_other,
+ :sort_name,
+ :banner_text,
+ :logo_file_name,
+ :region_id,
+ :logo_uid,
+ :logo_name,
+ ].freeze
+
+ # FORM_ATTRIBUTES
+ # an array of attributes that will be displayed
+ # on the model's form (`new` and `edit`) pages.
+ FORM_ATTRIBUTES = [
+ :language,
+ :guidance_groups,
+# :templates,
+# :users,
+# :annotations,
+ :token_permission_types,
+ :name,
+ :abbreviation,
+ :target_url,
+ :wayfless_entity,
+ :parent_id,
+ :is_other,
+ :sort_name,
+ :banner_text,
+ :logo_file_name,
+ :region_id,
+ :logo_uid,
+ :logo_name,
+ :contact_email,
+ :org_type,
+ ].freeze
+
+ # Overwrite this method to customize how orgs are displayed
+ # across all pages of the admin dashboard.
+ #
+ # def display_resource(org)
+ # "Org ##{org.id}"
+ # end
+
+ def display_resource(org)
+ org.name
+ end
+end
diff --git a/app/dashboards/perm_dashboard.rb b/app/dashboards/perm_dashboard.rb
new file mode 100644
index 0000000..dc9e20b
--- /dev/null
+++ b/app/dashboards/perm_dashboard.rb
@@ -0,0 +1,59 @@
+require "administrate/base_dashboard"
+
+class PermDashboard < Administrate::BaseDashboard
+ # ATTRIBUTE_TYPES
+ # a hash that describes the type of each of the model's fields.
+ #
+ # Each different type represents an Administrate::Field object,
+ # which determines how the attribute is displayed
+ # on pages throughout the dashboard.
+ ATTRIBUTE_TYPES = {
+ users: Field::HasMany,
+ id: Field::Number,
+ name: Field::String,
+ created_at: Field::DateTime,
+ updated_at: Field::DateTime,
+ }.freeze
+
+ # COLLECTION_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's index page.
+ #
+ # By default, it's limited to four items to reduce clutter on index pages.
+ # Feel free to add, remove, or rearrange items.
+ COLLECTION_ATTRIBUTES = [
+ :id,
+ :name,
+ :users,
+ :created_at,
+ ].freeze
+
+ # SHOW_PAGE_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's show page.
+ SHOW_PAGE_ATTRIBUTES = [
+ :id,
+ :name,
+ :users,
+ :created_at,
+ :updated_at,
+ ].freeze
+
+ # FORM_ATTRIBUTES
+ # an array of attributes that will be displayed
+ # on the model's form (`new` and `edit`) pages.
+ FORM_ATTRIBUTES = [
+# :users,
+ :name,
+ ].freeze
+
+ # Overwrite this method to customize how perms are displayed
+ # across all pages of the admin dashboard.
+ #
+ # def display_resource(perm)
+ # "Perm ##{perm.id}"
+ # end
+
+ def display_resource(perm)
+ perm.name
+ end
+
+end
diff --git a/app/dashboards/phase_dashboard.rb b/app/dashboards/phase_dashboard.rb
new file mode 100644
index 0000000..966961b
--- /dev/null
+++ b/app/dashboards/phase_dashboard.rb
@@ -0,0 +1,72 @@
+require "administrate/base_dashboard"
+
+class PhaseDashboard < Administrate::BaseDashboard
+ # ATTRIBUTE_TYPES
+ # a hash that describes the type of each of the model's fields.
+ #
+ # Each different type represents an Administrate::Field object,
+ # which determines how the attribute is displayed
+ # on pages throughout the dashboard.
+ ATTRIBUTE_TYPES = {
+ template: Field::BelongsTo,
+ sections: Field::HasMany,
+ questions: Field::HasMany,
+ id: Field::Number,
+ title: Field::String,
+ description: Field::Text,
+ number: Field::Number,
+ created_at: Field::DateTime,
+ updated_at: Field::DateTime,
+ slug: Field::String,
+ modifiable: Field::Boolean,
+ }.freeze
+
+ # COLLECTION_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's index page.
+ #
+ # By default, it's limited to four items to reduce clutter on index pages.
+ # Feel free to add, remove, or rearrange items.
+ COLLECTION_ATTRIBUTES = [
+ :template,
+ :sections,
+ :questions,
+ :id,
+ ].freeze
+
+ # SHOW_PAGE_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's show page.
+ SHOW_PAGE_ATTRIBUTES = [
+ :template,
+ :sections,
+ :questions,
+ :id,
+ :title,
+ :description,
+ :number,
+ :created_at,
+ :updated_at,
+ :slug,
+ :modifiable,
+ ].freeze
+
+ # FORM_ATTRIBUTES
+ # an array of attributes that will be displayed
+ # on the model's form (`new` and `edit`) pages.
+ FORM_ATTRIBUTES = [
+ :template,
+ :sections,
+ :questions,
+ :title,
+ :description,
+ :number,
+ :slug,
+ :modifiable,
+ ].freeze
+
+ # Overwrite this method to customize how phases are displayed
+ # across all pages of the admin dashboard.
+ #
+ # def display_resource(phase)
+ # "Phase ##{phase.id}"
+ # end
+end
diff --git a/app/dashboards/plan_dashboard.rb b/app/dashboards/plan_dashboard.rb
new file mode 100644
index 0000000..e22c30f
--- /dev/null
+++ b/app/dashboards/plan_dashboard.rb
@@ -0,0 +1,114 @@
+require "administrate/base_dashboard"
+
+class PlanDashboard < Administrate::BaseDashboard
+ # ATTRIBUTE_TYPES
+ # a hash that describes the type of each of the model's fields.
+ #
+ # Each different type represents an Administrate::Field object,
+ # which determines how the attribute is displayed
+ # on pages throughout the dashboard.
+ ATTRIBUTE_TYPES = {
+ template: Field::BelongsTo,
+ phases: Field::HasMany,
+ sections: Field::HasMany,
+ questions: Field::HasMany,
+ themes: Field::HasMany,
+ answers: Field::HasMany,
+ notes: Field::HasMany,
+ roles: Field::HasMany,
+ users: Field::HasMany,
+ guidance_groups: Field::HasMany,
+ exported_plans: Field::HasMany,
+ setting_objects: Field::HasMany.with_options(class_name: "Settings::Template"),
+ id: Field::Number,
+ title: Field::String,
+ created_at: Field::DateTime,
+ updated_at: Field::DateTime,
+ slug: Field::String,
+ grant_number: Field::String,
+ identifier: Field::String,
+ description: Field::Text,
+ principal_investigator: Field::String,
+ principal_investigator_identifier: Field::String,
+ data_contact: Field::String,
+ funder_name: Field::String,
+ visibility: Field::String.with_options(searchable: false),
+ }.freeze
+
+ # COLLECTION_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's index page.
+ #
+ # By default, it's limited to four items to reduce clutter on index pages.
+ # Feel free to add, remove, or rearrange items.
+ COLLECTION_ATTRIBUTES = [
+ :template,
+ :phases,
+ :sections,
+ :questions,
+ ].freeze
+
+ # SHOW_PAGE_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's show page.
+ SHOW_PAGE_ATTRIBUTES = [
+ :template,
+ :phases,
+ :sections,
+ :questions,
+ :themes,
+ :answers,
+ :notes,
+ :roles,
+ :users,
+ :guidance_groups,
+ :exported_plans,
+ :setting_objects,
+ :id,
+ :title,
+ :created_at,
+ :updated_at,
+ :slug,
+ :grant_number,
+ :identifier,
+ :description,
+ :principal_investigator,
+ :principal_investigator_identifier,
+ :data_contact,
+ :funder_name,
+ :visibility,
+ ].freeze
+
+ # FORM_ATTRIBUTES
+ # an array of attributes that will be displayed
+ # on the model's form (`new` and `edit`) pages.
+ FORM_ATTRIBUTES = [
+ :template,
+ :phases,
+ :sections,
+ :questions,
+ :themes,
+ :answers,
+ :notes,
+ :roles,
+ :users,
+ :guidance_groups,
+ :exported_plans,
+ :setting_objects,
+ :title,
+ :slug,
+ :grant_number,
+ :identifier,
+ :description,
+ :principal_investigator,
+ :principal_investigator_identifier,
+ :data_contact,
+ :funder_name,
+ :visibility,
+ ].freeze
+
+ # Overwrite this method to customize how plans are displayed
+ # across all pages of the admin dashboard.
+ #
+ # def display_resource(plan)
+ # "Plan ##{plan.id}"
+ # end
+end
diff --git a/app/dashboards/plan_guidance_group_dashboard.rb b/app/dashboards/plan_guidance_group_dashboard.rb
new file mode 100644
index 0000000..5e659c0
--- /dev/null
+++ b/app/dashboards/plan_guidance_group_dashboard.rb
@@ -0,0 +1,57 @@
+require "administrate/base_dashboard"
+
+class PlanGuidanceGroupDashboard < Administrate::BaseDashboard
+ # ATTRIBUTE_TYPES
+ # a hash that describes the type of each of the model's fields.
+ #
+ # Each different type represents an Administrate::Field object,
+ # which determines how the attribute is displayed
+ # on pages throughout the dashboard.
+ ATTRIBUTE_TYPES = {
+ plan: Field::BelongsTo,
+ guidance_group: Field::BelongsTo,
+ id: Field::Number,
+ created_at: Field::DateTime,
+ updated_at: Field::DateTime,
+ selected: Field::Boolean,
+ }.freeze
+
+ # COLLECTION_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's index page.
+ #
+ # By default, it's limited to four items to reduce clutter on index pages.
+ # Feel free to add, remove, or rearrange items.
+ COLLECTION_ATTRIBUTES = [
+ :plan,
+ :guidance_group,
+ :id,
+ :created_at,
+ ].freeze
+
+ # SHOW_PAGE_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's show page.
+ SHOW_PAGE_ATTRIBUTES = [
+ :plan,
+ :guidance_group,
+ :id,
+ :created_at,
+ :updated_at,
+ :selected,
+ ].freeze
+
+ # FORM_ATTRIBUTES
+ # an array of attributes that will be displayed
+ # on the model's form (`new` and `edit`) pages.
+ FORM_ATTRIBUTES = [
+ :plan,
+ :guidance_group,
+ :selected,
+ ].freeze
+
+ # Overwrite this method to customize how plan guidance groups are displayed
+ # across all pages of the admin dashboard.
+ #
+ # def display_resource(plans_guidance_group)
+ # "PlanGuidanceGroup ##{plans_guidance_group.id}"
+ # end
+end
diff --git a/app/dashboards/question_dashboard.rb b/app/dashboards/question_dashboard.rb
new file mode 100644
index 0000000..cda2c4c
--- /dev/null
+++ b/app/dashboards/question_dashboard.rb
@@ -0,0 +1,81 @@
+require "administrate/base_dashboard"
+
+class QuestionDashboard < Administrate::BaseDashboard
+ # ATTRIBUTE_TYPES
+ # a hash that describes the type of each of the model's fields.
+ #
+ # Each different type represents an Administrate::Field object,
+ # which determines how the attribute is displayed
+ # on pages throughout the dashboard.
+ ATTRIBUTE_TYPES = {
+ answers: Field::HasMany,
+ question_options: Field::HasMany,
+ annotations: Field::HasMany,
+ themes: Field::HasMany,
+ section: Field::BelongsTo,
+ question_format: Field::BelongsTo,
+ id: Field::Number,
+ text: Field::Text,
+ default_value: Field::Text,
+ number: Field::Number,
+ created_at: Field::DateTime,
+ updated_at: Field::DateTime,
+ option_comment_display: Field::Boolean,
+ modifiable: Field::Boolean,
+ }.freeze
+
+ # COLLECTION_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's index page.
+ #
+ # By default, it's limited to four items to reduce clutter on index pages.
+ # Feel free to add, remove, or rearrange items.
+ COLLECTION_ATTRIBUTES = [
+ :answers,
+ :question_options,
+ :annotations,
+ :themes,
+ ].freeze
+
+ # SHOW_PAGE_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's show page.
+ SHOW_PAGE_ATTRIBUTES = [
+ :answers,
+ :question_options,
+ :annotations,
+ :themes,
+ :section,
+ :question_format,
+ :id,
+ :text,
+ :default_value,
+ :number,
+ :created_at,
+ :updated_at,
+ :option_comment_display,
+ :modifiable,
+ ].freeze
+
+ # FORM_ATTRIBUTES
+ # an array of attributes that will be displayed
+ # on the model's form (`new` and `edit`) pages.
+ FORM_ATTRIBUTES = [
+ :answers,
+ :question_options,
+ :annotations,
+ :themes,
+ :section,
+ :question_format,
+ :text,
+ :default_value,
+ :number,
+ :option_comment_display,
+ :modifiable,
+ ].freeze
+
+ # Overwrite this method to customize how questions are displayed
+ # across all pages of the admin dashboard.
+ #
+ # def display_resource(question)
+ # "Question ##{question.id}"
+ # end
+end
diff --git a/app/dashboards/question_format_dashboard.rb b/app/dashboards/question_format_dashboard.rb
new file mode 100644
index 0000000..76bbff3
--- /dev/null
+++ b/app/dashboards/question_format_dashboard.rb
@@ -0,0 +1,63 @@
+require "administrate/base_dashboard"
+
+class QuestionFormatDashboard < Administrate::BaseDashboard
+ # ATTRIBUTE_TYPES
+ # a hash that describes the type of each of the model's fields.
+ #
+ # Each different type represents an Administrate::Field object,
+ # which determines how the attribute is displayed
+ # on pages throughout the dashboard.
+ ATTRIBUTE_TYPES = {
+ questions: Field::HasMany,
+ id: Field::Number,
+ title: Field::String,
+ description: Field::Text,
+ created_at: Field::DateTime,
+ updated_at: Field::DateTime,
+ option_based: Field::Boolean,
+ formattype: Field::String.with_options(searchable: false),
+ }.freeze
+
+ # COLLECTION_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's index page.
+ #
+ # By default, it's limited to four items to reduce clutter on index pages.
+ # Feel free to add, remove, or rearrange items.
+ COLLECTION_ATTRIBUTES = [
+ :questions,
+ :id,
+ :title,
+ :description,
+ ].freeze
+
+ # SHOW_PAGE_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's show page.
+ SHOW_PAGE_ATTRIBUTES = [
+ :questions,
+ :id,
+ :title,
+ :description,
+ :created_at,
+ :updated_at,
+ :option_based,
+ :formattype,
+ ].freeze
+
+ # FORM_ATTRIBUTES
+ # an array of attributes that will be displayed
+ # on the model's form (`new` and `edit`) pages.
+ FORM_ATTRIBUTES = [
+ :questions,
+ :title,
+ :description,
+ :option_based,
+ :formattype,
+ ].freeze
+
+ # Overwrite this method to customize how question formats are displayed
+ # across all pages of the admin dashboard.
+ #
+ # def display_resource(question_format)
+ # "QuestionFormat ##{question_format.id}"
+ # end
+end
diff --git a/app/dashboards/question_option_dashboard.rb b/app/dashboards/question_option_dashboard.rb
new file mode 100644
index 0000000..967a91d
--- /dev/null
+++ b/app/dashboards/question_option_dashboard.rb
@@ -0,0 +1,63 @@
+require "administrate/base_dashboard"
+
+class QuestionOptionDashboard < Administrate::BaseDashboard
+ # ATTRIBUTE_TYPES
+ # a hash that describes the type of each of the model's fields.
+ #
+ # Each different type represents an Administrate::Field object,
+ # which determines how the attribute is displayed
+ # on pages throughout the dashboard.
+ ATTRIBUTE_TYPES = {
+ question: Field::BelongsTo,
+ answers: Field::HasMany,
+ id: Field::Number,
+ text: Field::String,
+ number: Field::Number,
+ is_default: Field::Boolean,
+ created_at: Field::DateTime,
+ updated_at: Field::DateTime,
+ }.freeze
+
+ # COLLECTION_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's index page.
+ #
+ # By default, it's limited to four items to reduce clutter on index pages.
+ # Feel free to add, remove, or rearrange items.
+ COLLECTION_ATTRIBUTES = [
+ :question,
+ :answers,
+ :id,
+ :text,
+ ].freeze
+
+ # SHOW_PAGE_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's show page.
+ SHOW_PAGE_ATTRIBUTES = [
+ :question,
+ :answers,
+ :id,
+ :text,
+ :number,
+ :is_default,
+ :created_at,
+ :updated_at,
+ ].freeze
+
+ # FORM_ATTRIBUTES
+ # an array of attributes that will be displayed
+ # on the model's form (`new` and `edit`) pages.
+ FORM_ATTRIBUTES = [
+ :question,
+ :answers,
+ :text,
+ :number,
+ :is_default,
+ ].freeze
+
+ # Overwrite this method to customize how question options are displayed
+ # across all pages of the admin dashboard.
+ #
+ # def display_resource(question_option)
+ # "QuestionOption ##{question_option.id}"
+ # end
+end
diff --git a/app/dashboards/region_dashboard.rb b/app/dashboards/region_dashboard.rb
new file mode 100644
index 0000000..851ad0e
--- /dev/null
+++ b/app/dashboards/region_dashboard.rb
@@ -0,0 +1,62 @@
+require "administrate/base_dashboard"
+
+class RegionDashboard < Administrate::BaseDashboard
+ # ATTRIBUTE_TYPES
+ # a hash that describes the type of each of the model's fields.
+ #
+ # Each different type represents an Administrate::Field object,
+ # which determines how the attribute is displayed
+ # on pages throughout the dashboard.
+ ATTRIBUTE_TYPES = {
+ sub_regions: Field::HasMany.with_options(class_name: "Region"),
+ super_region: Field::BelongsTo.with_options(class_name: "Region"),
+ id: Field::Number,
+ abbreviation: Field::String,
+ description: Field::String,
+ name: Field::String,
+ super_region_id: Field::Number,
+ }.freeze
+
+ # COLLECTION_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's index page.
+ #
+ # By default, it's limited to four items to reduce clutter on index pages.
+ # Feel free to add, remove, or rearrange items.
+ COLLECTION_ATTRIBUTES = [
+ :sub_regions,
+ :super_region,
+ :id,
+ :abbreviation,
+ ].freeze
+
+ # SHOW_PAGE_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's show page.
+ SHOW_PAGE_ATTRIBUTES = [
+ :sub_regions,
+ :super_region,
+ :id,
+ :abbreviation,
+ :description,
+ :name,
+ :super_region_id,
+ ].freeze
+
+ # FORM_ATTRIBUTES
+ # an array of attributes that will be displayed
+ # on the model's form (`new` and `edit`) pages.
+ FORM_ATTRIBUTES = [
+ :sub_regions,
+ :super_region,
+ :abbreviation,
+ :description,
+ :name,
+ :super_region_id,
+ ].freeze
+
+ # Overwrite this method to customize how regions are displayed
+ # across all pages of the admin dashboard.
+ #
+ # def display_resource(region)
+ # "Region ##{region.id}"
+ # end
+end
diff --git a/app/dashboards/role_dashboard.rb b/app/dashboards/role_dashboard.rb
new file mode 100644
index 0000000..0d8b9ea
--- /dev/null
+++ b/app/dashboards/role_dashboard.rb
@@ -0,0 +1,57 @@
+require "administrate/base_dashboard"
+
+class RoleDashboard < Administrate::BaseDashboard
+ # ATTRIBUTE_TYPES
+ # a hash that describes the type of each of the model's fields.
+ #
+ # Each different type represents an Administrate::Field object,
+ # which determines how the attribute is displayed
+ # on pages throughout the dashboard.
+ ATTRIBUTE_TYPES = {
+ user: Field::BelongsTo,
+ plan: Field::BelongsTo,
+ id: Field::Number,
+ created_at: Field::DateTime,
+ updated_at: Field::DateTime,
+ access: Field::Number,
+ }.freeze
+
+ # COLLECTION_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's index page.
+ #
+ # By default, it's limited to four items to reduce clutter on index pages.
+ # Feel free to add, remove, or rearrange items.
+ COLLECTION_ATTRIBUTES = [
+ :user,
+ :plan,
+ :id,
+ :created_at,
+ ].freeze
+
+ # SHOW_PAGE_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's show page.
+ SHOW_PAGE_ATTRIBUTES = [
+ :user,
+ :plan,
+ :id,
+ :created_at,
+ :updated_at,
+ :access,
+ ].freeze
+
+ # FORM_ATTRIBUTES
+ # an array of attributes that will be displayed
+ # on the model's form (`new` and `edit`) pages.
+ FORM_ATTRIBUTES = [
+ :user,
+ :plan,
+ :access,
+ ].freeze
+
+ # Overwrite this method to customize how roles are displayed
+ # across all pages of the admin dashboard.
+ #
+ # def display_resource(role)
+ # "Role ##{role.id}"
+ # end
+end
diff --git a/app/dashboards/section_dashboard.rb b/app/dashboards/section_dashboard.rb
new file mode 100644
index 0000000..2dfb78b
--- /dev/null
+++ b/app/dashboards/section_dashboard.rb
@@ -0,0 +1,72 @@
+require "administrate/base_dashboard"
+
+class SectionDashboard < Administrate::BaseDashboard
+ # ATTRIBUTE_TYPES
+ # a hash that describes the type of each of the model's fields.
+ #
+ # Each different type represents an Administrate::Field object,
+ # which determines how the attribute is displayed
+ # on pages throughout the dashboard.
+ ATTRIBUTE_TYPES = {
+ phase: Field::BelongsTo,
+ organisation: Field::BelongsTo,
+ questions: Field::HasMany,
+ id: Field::Number,
+ title: Field::String,
+ description: Field::Text,
+ number: Field::Number,
+ created_at: Field::DateTime,
+ updated_at: Field::DateTime,
+ published: Field::Boolean,
+ modifiable: Field::Boolean,
+ }.freeze
+
+ # COLLECTION_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's index page.
+ #
+ # By default, it's limited to four items to reduce clutter on index pages.
+ # Feel free to add, remove, or rearrange items.
+ COLLECTION_ATTRIBUTES = [
+ :phase,
+ :organisation,
+ :questions,
+ :id,
+ ].freeze
+
+ # SHOW_PAGE_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's show page.
+ SHOW_PAGE_ATTRIBUTES = [
+ :phase,
+ :organisation,
+ :questions,
+ :id,
+ :title,
+ :description,
+ :number,
+ :created_at,
+ :updated_at,
+ :published,
+ :modifiable,
+ ].freeze
+
+ # FORM_ATTRIBUTES
+ # an array of attributes that will be displayed
+ # on the model's form (`new` and `edit`) pages.
+ FORM_ATTRIBUTES = [
+ :phase,
+ :organisation,
+ :questions,
+ :title,
+ :description,
+ :number,
+ :published,
+ :modifiable,
+ ].freeze
+
+ # Overwrite this method to customize how sections are displayed
+ # across all pages of the admin dashboard.
+ #
+ # def display_resource(section)
+ # "Section ##{section.id}"
+ # end
+end
diff --git a/app/dashboards/splash_log_dashboard.rb b/app/dashboards/splash_log_dashboard.rb
new file mode 100644
index 0000000..ed549aa
--- /dev/null
+++ b/app/dashboards/splash_log_dashboard.rb
@@ -0,0 +1,51 @@
+require "administrate/base_dashboard"
+
+class SplashLogDashboard < Administrate::BaseDashboard
+ # ATTRIBUTE_TYPES
+ # a hash that describes the type of each of the model's fields.
+ #
+ # Each different type represents an Administrate::Field object,
+ # which determines how the attribute is displayed
+ # on pages throughout the dashboard.
+ ATTRIBUTE_TYPES = {
+ id: Field::Number,
+ destination: Field::String,
+ created_at: Field::DateTime,
+ updated_at: Field::DateTime,
+ }.freeze
+
+ # COLLECTION_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's index page.
+ #
+ # By default, it's limited to four items to reduce clutter on index pages.
+ # Feel free to add, remove, or rearrange items.
+ COLLECTION_ATTRIBUTES = [
+ :id,
+ :destination,
+ :created_at,
+ :updated_at,
+ ].freeze
+
+ # SHOW_PAGE_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's show page.
+ SHOW_PAGE_ATTRIBUTES = [
+ :id,
+ :destination,
+ :created_at,
+ :updated_at,
+ ].freeze
+
+ # FORM_ATTRIBUTES
+ # an array of attributes that will be displayed
+ # on the model's form (`new` and `edit`) pages.
+ FORM_ATTRIBUTES = [
+ :destination,
+ ].freeze
+
+ # Overwrite this method to customize how splash logs are displayed
+ # across all pages of the admin dashboard.
+ #
+ # def display_resource(splash_log)
+ # "SplashLog ##{splash_log.id}"
+ # end
+end
diff --git a/app/dashboards/template_dashboard.rb b/app/dashboards/template_dashboard.rb
new file mode 100644
index 0000000..7a5a313
--- /dev/null
+++ b/app/dashboards/template_dashboard.rb
@@ -0,0 +1,107 @@
+require "administrate/base_dashboard"
+
+class TemplateDashboard < Administrate::BaseDashboard
+ # ATTRIBUTE_TYPES
+ # a hash that describes the type of each of the model's fields.
+ #
+ # Each different type represents an Administrate::Field object,
+ # which determines how the attribute is displayed
+ # on pages throughout the dashboard.
+ ATTRIBUTE_TYPES = {
+ org: Field::BelongsTo,
+ plans: Field::HasMany,
+ phases: Field::HasMany,
+ sections: Field::HasMany,
+ questions: Field::HasMany,
+ customizations: Field::HasMany.with_options(class_name: "Template"),
+ dmptemplate: Field::BelongsTo.with_options(class_name: "Template"),
+ setting_objects: Field::HasMany.with_options(class_name: "Settings::Template"),
+ id: Field::Number,
+ title: Field::String,
+ description: Field::Text,
+ published: Field::Boolean,
+ locale: Field::String,
+ is_default: Field::Boolean,
+ created_at: Field::DateTime,
+ updated_at: Field::DateTime,
+ version: Field::Number,
+ visibility: Field::Number,
+ customization_of: Field::Number,
+ dmptemplate_id: Field::Number,
+ migrated: Field::Boolean,
+ dirty: Field::Boolean,
+ }.freeze
+
+ # COLLECTION_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's index page.
+ #
+ # By default, it's limited to four items to reduce clutter on index pages.
+ # Feel free to add, remove, or rearrange items.
+ COLLECTION_ATTRIBUTES = [
+ :title,
+ :description,
+ :org,
+ :plans,
+ :phases,
+ :sections,
+ ].freeze
+
+ # SHOW_PAGE_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's show page.
+ SHOW_PAGE_ATTRIBUTES = [
+ :org,
+ :plans,
+ :phases,
+ :sections,
+ :questions,
+ :customizations,
+ :dmptemplate,
+ :setting_objects,
+ :id,
+ :title,
+ :description,
+ :published,
+ :locale,
+ :is_default,
+ :created_at,
+ :updated_at,
+ :version,
+ :visibility,
+ :customization_of,
+ :dmptemplate_id,
+ :migrated,
+ :dirty,
+ ].freeze
+
+ # FORM_ATTRIBUTES
+ # an array of attributes that will be displayed
+ # on the model's form (`new` and `edit`) pages.
+ FORM_ATTRIBUTES = [
+ :org,
+ :plans,
+ :phases,
+ :sections,
+ :questions,
+ :customizations,
+ :dmptemplate,
+ :setting_objects,
+ :title,
+ :description,
+ :published,
+ :locale,
+ :is_default,
+ :version,
+ :visibility,
+ :customization_of,
+ :dmptemplate_id,
+ :migrated,
+ :dirty,
+ ].freeze
+
+ # Overwrite this method to customize how templates are displayed
+ # across all pages of the admin dashboard.
+ #
+ # def display_resource(template)
+ # "Template ##{template.id}"
+ # end
+end
diff --git a/app/dashboards/theme_dashboard.rb b/app/dashboards/theme_dashboard.rb
new file mode 100644
index 0000000..2be7c8d
--- /dev/null
+++ b/app/dashboards/theme_dashboard.rb
@@ -0,0 +1,66 @@
+require "administrate/base_dashboard"
+
+class ThemeDashboard < Administrate::BaseDashboard
+ # ATTRIBUTE_TYPES
+ # a hash that describes the type of each of the model's fields.
+ #
+ # Each different type represents an Administrate::Field object,
+ # which determines how the attribute is displayed
+ # on pages throughout the dashboard.
+ ATTRIBUTE_TYPES = {
+ questions: Field::HasMany,
+ guidances: Field::HasMany,
+ id: Field::Number,
+ title: Field::String,
+ description: Field::Text,
+ created_at: Field::DateTime,
+ updated_at: Field::DateTime,
+ locale: Field::String,
+ }.freeze
+
+ # COLLECTION_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's index page.
+ #
+ # By default, it's limited to four items to reduce clutter on index pages.
+ # Feel free to add, remove, or rearrange items.
+ COLLECTION_ATTRIBUTES = [
+ :questions,
+ :guidances,
+ :id,
+ :title,
+ ].freeze
+
+ # SHOW_PAGE_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's show page.
+ SHOW_PAGE_ATTRIBUTES = [
+ :questions,
+ :guidances,
+ :id,
+ :title,
+ :description,
+ :created_at,
+ :updated_at,
+ :locale,
+ ].freeze
+
+ # FORM_ATTRIBUTES
+ # an array of attributes that will be displayed
+ # on the model's form (`new` and `edit`) pages.
+ FORM_ATTRIBUTES = [
+ :questions,
+ :guidances,
+ :title,
+ :description,
+ :locale,
+ ].freeze
+
+ # Overwrite this method to customize how themes are displayed
+ # across all pages of the admin dashboard.
+ #
+ # def display_resource(theme)
+ # "Theme ##{theme.id}"
+ # end
+ def display_resource(theme)
+ "Theme: #{theme.title} (##{theme.id})"
+ end
+end
diff --git a/app/dashboards/token_permission_type_dashboard.rb b/app/dashboards/token_permission_type_dashboard.rb
new file mode 100644
index 0000000..93deb0f
--- /dev/null
+++ b/app/dashboards/token_permission_type_dashboard.rb
@@ -0,0 +1,61 @@
+require "administrate/base_dashboard"
+
+class TokenPermissionTypeDashboard < Administrate::BaseDashboard
+ # ATTRIBUTE_TYPES
+ # a hash that describes the type of each of the model's fields.
+ #
+ # Each different type represents an Administrate::Field object,
+ # which determines how the attribute is displayed
+ # on pages throughout the dashboard.
+ ATTRIBUTE_TYPES = {
+ orgs: Field::HasMany,
+ id: Field::Number,
+ token_type: Field::String,
+ text_description: Field::Text,
+ created_at: Field::DateTime,
+ updated_at: Field::DateTime,
+ }.freeze
+
+ # COLLECTION_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's index page.
+ #
+ # By default, it's limited to four items to reduce clutter on index pages.
+ # Feel free to add, remove, or rearrange items.
+ COLLECTION_ATTRIBUTES = [
+ :orgs,
+ :id,
+ :token_type,
+ :text_description,
+ ].freeze
+
+ # SHOW_PAGE_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's show page.
+ SHOW_PAGE_ATTRIBUTES = [
+ :orgs,
+ :id,
+ :token_type,
+ :text_description,
+ :created_at,
+ :updated_at,
+ ].freeze
+
+ # FORM_ATTRIBUTES
+ # an array of attributes that will be displayed
+ # on the model's form (`new` and `edit`) pages.
+ FORM_ATTRIBUTES = [
+ :orgs,
+ :token_type,
+ :text_description,
+ ].freeze
+
+ # Overwrite this method to customize how token permission types are displayed
+ # across all pages of the admin dashboard.
+ #
+ # def display_resource(token_permission_type)
+ # "TokenPermissionType ##{token_permission_type.id}"
+ # end
+ def display_resource(token_permission_type)
+ "#{token_permission_type.token_type}: #{token_permission_type.text_description}"
+ end
+
+end
diff --git a/app/dashboards/user_dashboard.rb b/app/dashboards/user_dashboard.rb
new file mode 100644
index 0000000..4ba23ad
--- /dev/null
+++ b/app/dashboards/user_dashboard.rb
@@ -0,0 +1,160 @@
+require "administrate/base_dashboard"
+
+class UserDashboard < Administrate::BaseDashboard
+ # ATTRIBUTE_TYPES
+ # a hash that describes the type of each of the model's fields.
+ #
+ # Each different type represents an Administrate::Field object,
+ # which determines how the attribute is displayed
+ # on pages throughout the dashboard.
+ ATTRIBUTE_TYPES = {
+ invited_by: Field::Polymorphic,
+ perms: Field::HasMany,
+ language: Field::BelongsTo,
+ org: Field::BelongsTo,
+ answers: Field::HasMany,
+ notes: Field::HasMany,
+ exported_plans: Field::HasMany,
+ roles: Field::HasMany,
+ plans: Field::HasMany,
+ user_identifiers: Field::HasMany,
+ identifier_schemes: Field::HasMany,
+ setting_objects: Field::HasMany.with_options(class_name: "Settings::PlanList"),
+ id: Field::Number,
+ firstname: Field::String,
+ surname: Field::String,
+ email: Field::String,
+ orcid_id: Field::String,
+ shibboleth_id: Field::String,
+ created_at: Field::DateTime,
+ updated_at: Field::DateTime,
+ encrypted_password: Field::String,
+ reset_password_token: Field::String,
+ reset_password_sent_at: Field::DateTime,
+ remember_created_at: Field::DateTime,
+ sign_in_count: Field::Number,
+ current_sign_in_at: Field::DateTime,
+ last_sign_in_at: Field::DateTime,
+ current_sign_in_ip: Field::String,
+ last_sign_in_ip: Field::String,
+ confirmation_token: Field::String,
+ confirmed_at: Field::DateTime,
+ confirmation_sent_at: Field::DateTime,
+ invitation_token: Field::String,
+ invitation_created_at: Field::DateTime,
+ invitation_sent_at: Field::DateTime,
+ invitation_accepted_at: Field::DateTime,
+ other_organisation: Field::String,
+ accept_terms: Field::Boolean,
+ api_token: Field::String,
+ }.freeze
+
+ # COLLECTION_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's index page.
+ #
+ # By default, it's limited to four items to reduce clutter on index pages.
+ # Feel free to add, remove, or rearrange items.
+ COLLECTION_ATTRIBUTES = [
+ :firstname,
+ :surname,
+ :email,
+ :org,
+ :perms,
+ :confirmed_at,
+ ].freeze
+
+ # SHOW_PAGE_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's show page.
+ SHOW_PAGE_ATTRIBUTES = [
+ :firstname,
+ :surname,
+ :email,
+ :org,
+ :perms,
+ :confirmed_at,
+ :id,
+ :invited_by,
+ :language,
+ :answers,
+ :notes,
+ :exported_plans,
+ :roles,
+ :plans,
+ :user_identifiers,
+ :identifier_schemes,
+ :orcid_id,
+ :shibboleth_id,
+ :created_at,
+ :updated_at,
+ :encrypted_password,
+ :reset_password_token,
+ :reset_password_sent_at,
+ :remember_created_at,
+ :sign_in_count,
+ :current_sign_in_at,
+ :last_sign_in_at,
+ :current_sign_in_ip,
+ :last_sign_in_ip,
+ :confirmation_token,
+ :confirmation_sent_at,
+ :invitation_token,
+ :invitation_created_at,
+ :invitation_sent_at,
+ :invitation_accepted_at,
+ :other_organisation,
+ :accept_terms,
+ :api_token,
+ ].freeze
+
+ # FORM_ATTRIBUTES
+ # an array of attributes that will be displayed
+ # on the model's form (`new` and `edit`) pages.
+ FORM_ATTRIBUTES = [
+# :invited_by,
+ :perms,
+ :language,
+ :org,
+# :answers,
+# :notes,
+# :exported_plans,
+# :roles,
+# :plans,
+ :user_identifiers,
+ :identifier_schemes,
+ :firstname,
+ :surname,
+ :email,
+ :orcid_id,
+ :shibboleth_id,
+# :encrypted_password,
+# :reset_password_token,
+# :reset_password_sent_at,
+# :remember_created_at,
+# :sign_in_count,
+# :current_sign_in_at,
+# :last_sign_in_at,
+# :current_sign_in_ip,
+# :last_sign_in_ip,
+# :confirmation_token,
+# :confirmed_at,
+# :confirmation_sent_at,
+# :invitation_token,
+# :invitation_created_at,
+# :invitation_sent_at,
+# :invitation_accepted_at,
+# :other_organisation,
+ :accept_terms,
+# :api_token,
+ ].freeze
+
+ # Overwrite this method to customize how users are displayed
+ # across all pages of the admin dashboard.
+ #
+ # def display_resource(user)
+ # "User ##{user.id}"
+ # end
+
+ def display_resource(user)
+ "#{user.firstname} #{user.surname} (##{user.id})"
+ end
+end
diff --git a/app/dashboards/user_identifier_dashboard.rb b/app/dashboards/user_identifier_dashboard.rb
new file mode 100644
index 0000000..fc6d73e
--- /dev/null
+++ b/app/dashboards/user_identifier_dashboard.rb
@@ -0,0 +1,62 @@
+require "administrate/base_dashboard"
+
+class UserIdentifierDashboard < Administrate::BaseDashboard
+ # ATTRIBUTE_TYPES
+ # a hash that describes the type of each of the model's fields.
+ #
+ # Each different type represents an Administrate::Field object,
+ # which determines how the attribute is displayed
+ # on pages throughout the dashboard.
+ ATTRIBUTE_TYPES = {
+ user: Field::BelongsTo,
+ identifier_scheme: Field::BelongsTo,
+ id: Field::Number,
+ identifier: Field::String,
+ created_at: Field::DateTime,
+ updated_at: Field::DateTime,
+ }.freeze
+
+ # COLLECTION_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's index page.
+ #
+ # By default, it's limited to four items to reduce clutter on index pages.
+ # Feel free to add, remove, or rearrange items.
+ COLLECTION_ATTRIBUTES = [
+ :user,
+ :identifier_scheme,
+ :id,
+ :identifier,
+ ].freeze
+
+ # SHOW_PAGE_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's show page.
+ SHOW_PAGE_ATTRIBUTES = [
+ :user,
+ :identifier_scheme,
+ :id,
+ :identifier,
+ :created_at,
+ :updated_at,
+ ].freeze
+
+ # FORM_ATTRIBUTES
+ # an array of attributes that will be displayed
+ # on the model's form (`new` and `edit`) pages.
+ FORM_ATTRIBUTES = [
+ :user,
+ :identifier_scheme,
+ :identifier,
+ ].freeze
+
+ # Overwrite this method to customize how user identifiers are displayed
+ # across all pages of the admin dashboard.
+ #
+ # def display_resource(user_identifier)
+ # "UserIdentifier ##{user_identifier.id}"
+ # end
+
+ def display_resource(user_identifier)
+ user_identifier.identifier
+ end
+
+end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 0d8de1a..8c37586 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -29,4 +29,5 @@
def isActivePage(path)
return request.fullpath() == path
end
+
end
diff --git a/app/helpers/plans_helper.rb b/app/helpers/plans_helper.rb
index 8cdd5d9..cf5a0c6 100644
--- a/app/helpers/plans_helper.rb
+++ b/app/helpers/plans_helper.rb
@@ -4,18 +4,18 @@
# --------------------------------------------------------
def plan_list_column_heading(column)
if column.kind_of?(Array)
- heading = (column.first.kind_of?(String) ? column.first : t("helpers.project.columns.unknown"))
+ heading = (column.first.kind_of?(String) ? column.first : _(' - '))
elsif column.kind_of?(String)
heading = column
else
- heading = t("helpers.project.columns.unknown")
+ heading = _(' - ')
end
klass = (['name', 'description'].include?(heading) ? :dmp_th_big : :dmp_th_small)
- content_tag(:th, t("helpers.project.columns.#{heading}"), class: klass)
+ content_tag(:th, t("helpers.project.columns.#{heading}"), class: klass) # parametrised YAML keys are no longer possible with gettext, TODO
end
# Populate a variable column for the project list
@@ -26,15 +26,13 @@
klass, content = case col
when 'name'
- [ "dmp_td_big", link_to(plan.title, plan_path(I18n.locale, plan), class: "dmp_table_link") ]
-
+ [ "dmp_td_big", link_to(plan.title, plan_path(plan), class: "dmp_table_link") ]
when 'owner'
user = plan.owner
-
text = if user.nil?
- t("helpers.project.columns.unknown")
+ _(' - ')
elsif user == current_user
- t("helpers.me")
+ _('Me')
else
user.name
end
@@ -42,24 +40,32 @@
[ "tmp_td_small", text ]
when 'shared'
shared_num = plan.users.count - 1
- text = shared_num > 0 ? (t("helpers.yes_label") + " (with #{shared_num} people) ") : t("helpers.no_label")
+ text = shared_num > 0 ? (_('Yes') + " (with #{shared_num} people) ") : _('No') # Hardcoded strings are not internationalised
[ "dmp_td_small", text ]
when 'visibility'
- ["dmp_td_small", (plan.visibility.nil? ? I18n.t("helpers.project.visibilities.labels.organisationally_visible") : I18n.t("helpers.project.visibilities.labels.#{plan.visibility}"))]
+ text = if plan.visibility == 'organisationally_visible'
+ _('Organisational')
+ elsif plan.visibility == 'publicly_visible'
+ _('Public')
+ elsif plan.visibility == 'is_test'
+ _('Test/Practice')
+ elsif plan.visibility == 'privately_visible'
+ _('Private')
+ end
+ ["dmp_td_small", text ]
when 'last_edited'
[ "dmp_td_small", l(plan.latest_update.to_date, formats: :short) ]
when 'description'
- [ "dmp_td_medium", (plan.try(col) || t("helpers.settings.unknown")) ]
+ [ "dmp_td_medium", (plan.try(col) || _(' - ')) ]
when 'non_link_name'
[ "dmp_td_big", plan.title ]
when 'template'
["dmp_td_big", plan.template.title]
when 'organisation'
- ["dmp_td_medium", (plan.owner.org.nil? ? t("helpers.settings.unknown") : plan.owner.org.name) ]
+ ["dmp_td_medium", plan.template.org.name] # This will trigger 2 queries for each function call, i.e. one for templates and another for orgs tables
else
- [ "dmp_td_small", (plan.try(col) || t("helpers.settings.unknown")) ]
+ [ "dmp_td_small", (plan.try(col) || _(' - ')) ]
end
-
content_tag(:td, content, class: klass)
end
diff --git a/app/helpers/settings_template_helper.rb b/app/helpers/settings_template_helper.rb
new file mode 100644
index 0000000..255c95e
--- /dev/null
+++ b/app/helpers/settings_template_helper.rb
@@ -0,0 +1,27 @@
+module SettingsTemplateHelper
+ # Retrieves an msgstr for a given admin_field
+ def admin_field_t(admin_field)
+ if Settings::Template::VALID_ADMIN_FIELDS.include?(admin_field)
+ if admin_field == 'project_name'
+ return _('Plan Name')
+ elsif admin_field == 'project_identifier'
+ return _('Plan ID')
+ elsif admin_field == 'grant_title'
+ return _('Grant number')
+ elsif admin_field == 'principal_investigator'
+ return _('Principal Investigator / Researcher')
+ elsif admin_field == 'project_data_contact'
+ return _('Plan Data Contact')
+ elsif admin_field == 'project_description'
+ return _('Plan Description')
+ elsif admin_field == 'funder'
+ return _('Funder')
+ elsif admin_field == 'institution'
+ return _('Institution')
+ elsif admin_field == 'orcid'
+ return _('Your ORCID')
+ end
+ end
+ return _('Unknown column name.')
+ end
+end
\ No newline at end of file
diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb
index e11166a..f679ba2 100644
--- a/app/mailers/user_mailer.rb
+++ b/app/mailers/user_mailer.rb
@@ -1,24 +1,47 @@
class UserMailer < ActionMailer::Base
- default from: I18n.t('helpers.main_email.from')
+ default from: Rails.configuration.branding[:organisation][:email]
- def sharing_notification(project_group)
- @project_group = project_group
- mail(to: @project_group.user.email, subject: I18n.t('helpers.main_email.access_given'))
+ def welcome_notification(user)
+ @user = user
+ FastGettext.with_locale FastGettext.default_locale do
+ mail(to: @user.email,
+ subject: "#{_('Welcome to')} #{Rails.configuration.branding[:application][:name]}")
+ end
+ end
+
+ def sharing_notification(role, user)
+ @role = role
+ @user = user
+ FastGettext.with_locale FastGettext.default_locale do
+ mail(to: @role.user.email,
+ subject: "#{_('A Data Management Plan in ')} #{Rails.configuration.branding[:application][:name]} #{_(' has been shared with you')}")
+ end
end
- def permissions_change_notification(project_group)
- @project_group = project_group
- mail(to: @project_group.user.email, subject: I18n.t('helpers.main_email.permission_changed'))
+ def permissions_change_notification(role, current_user)
+ @role = role
+ @current_user = current_user
+ FastGettext.with_locale FastGettext.default_locale do
+ mail(to: @role.user.email,
+ subject: "#{_('Changed permissions on a DMP in')} #{Rails.configuration.branding[:application][:name]}")
+ end
end
- def project_access_removed_notification(user, project)
+ def project_access_removed_notification(user, plan, current_user)
@user = user
- @project = project
- mail(to: @user.email, subject: I18n.t('helpers.main_email.access_removed'))
+ @plan = plan
+ @current_user = current_user
+ FastGettext.with_locale FastGettext.default_locale do
+ mail(to: @user.email,
+ subject: "#{_('Permissions removed on a DMP in')} #{Rails.configuration.branding[:application][:name]}")
+ end
end
def api_token_granted_notification(user)
@user = user
- mail(to: @user.email, subject: I18n.t('helper.api_mail_subject'))
+ FastGettext.with_locale FastGettext.default_locale do
+ mail(to: @user.email,
+ subject: "#{_('API rights in')} #{Rails.configuration.branding[:application][:name]}")
+ end
end
-end
\ No newline at end of file
+end
diff --git a/app/models/annotation.rb b/app/models/annotation.rb
new file mode 100644
index 0000000..8ea44dd
--- /dev/null
+++ b/app/models/annotation.rb
@@ -0,0 +1,40 @@
+class Annotation < ActiveRecord::Base
+ enum type: [ :example_answer, :guidance]
+ ##
+ # Associations
+ belongs_to :org
+ belongs_to :question
+
+ ##
+ # I liked type as the name for the enum so overriding inheritance column
+ self.inheritance_column = nil
+
+ ##
+ # Possibly needed for active_admin
+ # -relies on protected_attributes gem as syntax depricated in rails 4.2
+ attr_accessible :org_id, :question_id, :text, :type,
+ :org, :question, :as => [:default, :admin]
+
+
+ validates :question, :org, presence: {message: _("can't be blank")}
+
+ ##
+ # returns the text from the annotation
+ #
+ # @return [String] the text from the annotation
+ def to_s
+ "#{text}"
+ end
+
+
+ ##
+ # deep copy the given annotation and all it's associations
+ #
+ # @params [Annotation] annotation to be deep copied
+ # @return [Annotation] the saved, copied annotation
+ def self.deep_copy(annotation)
+ annotation_copy = annotation.dup
+ annotation_copy.save!
+ return annotation_copy
+ end
+end
\ No newline at end of file
diff --git a/app/models/answer.rb b/app/models/answer.rb
index 35e0c2d..d46ad59 100644
--- a/app/models/answer.rb
+++ b/app/models/answer.rb
@@ -13,8 +13,8 @@
##
# 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, :question_option_ids,
- :question, :user, :plan, :question_options, :notes, :note_ids,
+ attr_accessible :text, :plan_id, :lock_version, :question_id, :user_id, :question_option_ids,
+ :question, :user, :plan, :question_options, :notes, :note_ids, :id,
:as => [:default, :admin]
##
@@ -36,4 +36,24 @@
#
# # Make sure the plan and question are associated with the same template!
# validates :plan, :question, answer_for_correct_template: true
+
+ # This method helps to decide if an answer option (:radiobuttons, :checkbox, etc ) in form views should be checked or not
+ # Returns true if the given option_id is present in question_options, otherwise returns false
+ def has_question_option(option_id)
+ self.question_option_ids.include?(option_id)
+ end
+
+ # Returns true if the answer is valid and false otherwise. If the answer's question is option_based, it is checked if exist
+ # any question_option selected. For non option_based (e.g. textarea or textfield), it is checked the presence of text
+ def is_valid?
+ if self.question.present?
+ if self.question.question_format.option_based?
+ return !self.question_options.empty?
+ else # (e.g. textarea or textfield question formats)
+ return self.text.present?
+ end
+ else
+ return false
+ end
+ end
end
diff --git a/app/models/exported_plan.rb b/app/models/exported_plan.rb
index 4045298..0bd9ef1 100644
--- a/app/models/exported_plan.rb
+++ b/app/models/exported_plan.rb
@@ -1,5 +1,6 @@
class ExportedPlan < ActiveRecord::Base
include GlobalHelpers
+ include SettingsTemplateHelper
# TODO: REMOVE AND HANDLE ATTRIBUTE SECURITY IN THE CONTROLLER!
attr_accessible :plan_id, :user_id, :format, :user, :plan, :as => [:default, :admin]
@@ -8,10 +9,15 @@
belongs_to :plan
belongs_to :user
- VALID_FORMATS = ['csv', 'html', 'json', 'pdf', 'text', 'xml', 'docx']
+ VALID_FORMATS = ['csv', 'html', 'pdf', 'text', 'docx']
- validates :format, inclusion: { in: VALID_FORMATS, message: I18n.t('helpers.plan.export.not_valid_format') }
- validates :plan, :format, presence: true
+ validates :format, inclusion: {
+ in: VALID_FORMATS,
+ message: -> (object, data) do
+ _('%{value} is not a valid format') % { :value => data[:value] }
+ end
+ }
+ validates :plan, :format, presence: {message: _("can't be blank")}
# Store settings with the exported plan so it can be recreated later
# if necessary (otherwise the settings associated with the plan at a
@@ -50,6 +56,10 @@
self.plan.description
end
+ def owner
+ self.plan.roles.to_a.select{ |role| role.creator? }.first.user
+ end
+
def funder
org = self.plan.template.try(:org)
org.name if org.present? && org.funder?
@@ -69,91 +79,109 @@
end
end
-# TODO: This looks like it will always return an empty array as questions is undefined
- # sections taken from fields settings
def sections
- # TODO: How do we know which phase to use here!?
- sections = self.template.phases.first.sections
-
- return [] if questions.empty?
-
- section_ids = questions.pluck(:section_id).uniq
- sections = sections.select {|section| section_ids.member?(section.id) }
-
- sections.sort_by(&:number)
+ self.phase_id ||= self.plan.template.phases.first.id
+ Section.where({phase_id: phase_id}).order(:number)
end
def questions_for_section(section_id)
- questions.where(section_id: section_id)
+ Question.where(id: questions).where(section_id: section_id).order(:number)
end
def admin_details
@admin_details ||= self.settings(:export).fields[:admin]
end
+ # Retrieves the title field
+ def title
+ self.settings(:export).title
+ end
+
# Export formats
def as_csv
CSV.generate do |csv|
- csv << ["Section","Question","Answer","Selected option(s)","Answered by","Answered at"]
+ csv << [_('Section'),_('Question'),_('Answer'),_('Selected option(s)'),_('Answered by'),_('Answered at')]
self.sections.each do |section|
- self.questions_for_section(section).each do |question|
- answer = self.plan.answer(question.id)
- options_string = answer.options.collect {|o| o.text}.join('; ')
-
- csv << [section.title, sanitize_text(question.text), sanitize_text(answer.text), options_string, answer.try(:user).try(:name), answer.created_at]
+ questions = self.questions_for_section(section)
+ if questions.present?
+ questions.each do |question|
+ answer = self.plan.answer(question.id)
+ q_format = question.question_format
+ if q_format.option_based?
+ options_string = answer.question_options.collect {|o| o.text}.join('; ')
+ else
+ options_string = ''
+ end
+ csv << [
+ section.title,
+ sanitize_text(question.text),
+ question.option_comment_display ? sanitize_text(answer.text) : '',
+ options_string,
+ user.name,
+ answer.updated_at
+ ]
+ end
end
end
end
end
def as_txt
- output = "#{self.plan.project.title}\n\n#{self.plan.version.phase.title}\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"
+ output = "#{self.plan.title}\n\n#{self.plan.template.title}\n"
+ output += "\n"+_('Details')+"\n\n"
+
+ self.admin_details.each do |at|
+ value = self.send(at)
+ if value.present?
+ output += admin_field_t(at.to_s) + ": " + value + "\n"
+ else
+ output += admin_field_t(at.to_s) + ": " + _('-') + "\n"
+ end
end
self.sections.each do |section|
- output += "\n#{section.title}\n"
+ questions = self.questions_for_section(section)
+ if questions.present?
+ output += "\n#{section.title}\n"
+ questions.each do |question|
+ qtext = sanitize_text( question.text.gsub(/
/, ' * ') )
- output += "\n* #{qtext}"
- answer = self.plan.answer(question.id, false)
-
- if answer.nil? || answer.text.nil? then
- output += I18n.t('helpers.plan.export.pdf.question_not_answered')+ "\n"
- else
- output += answer.options.collect {|o| o.text}.join("\n")
- if question.option_comment_display == true then
- output += "\n#{sanitize_text(answer.text)}\n"
+ if answer.nil?
+ output += _('Question not answered.')+ "\n"
else
- output += "\n"
+ q_format = question.question_format
+ if q_format.option_based?
+ output += answer.question_options.collect {|o| o.text}.join("\n")
+ if question.option_comment_display
+ output += "\n#{sanitize_text(answer.text)}\n"
+ end
+ else
+ output += "\n#{sanitize_text(answer.text)}\n"
+ end
end
end
end
end
-
output
end
private
-
+ # Returns an Array of question_ids for the exported settings stored for a plan
def questions
- @questions ||= begin
- question_settings = self.settings(:export).fields[:questions]
-
- return [] if question_settings.is_a?(Array) && question_settings.empty?
-
- questions = if question_settings.present? && question_settings != :all
- Question.where(id: question_settings)
+ question_settings = self.settings(:export).fields[:questions]
+ @questions ||= if question_settings.present?
+ if question_settings == :all
+ Question.where(section_id: self.plan.sections.collect { |s| s.id }).pluck(:id)
+ elsif question_settings.is_a?(Array)
+ question_settings
else
- Question.where(section_id: self.plan.sections.collect {|s| s.id })
+ []
end
-
- questions.order(:number)
+ else
+ []
end
end
diff --git a/app/models/guidance.rb b/app/models/guidance.rb
index 3b15e2a..8ba321b 100644
--- a/app/models/guidance.rb
+++ b/app/models/guidance.rb
@@ -3,7 +3,7 @@
# This class keeps the information organisations enter to support users when answering questions.
# It always belongs to a guidance group class and it can be linked directly to a question or through one or more themes
# [+Created:+] 07/07/2014
-# [+Copyright:+] Digital Curation Centre and University of California Curation Center
+# [+Copyright:+] Digital Curation Centre and California Digital Library
@@ -13,12 +13,9 @@
##
# Associations
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"
-
-
+ #has_and_belongs_to_many :guidance_groups, join_table: "guidance_in_group"
# EVALUATE CLASS AND INSTANCE METHODS BELOW
@@ -28,7 +25,7 @@
- validates :text, presence: true
+ validates :text, presence: {message: _("can't be blank")}
##
@@ -91,7 +88,7 @@
unless guidance.nil?
unless guidance.guidance_group.nil?
- # guidances are viewable if they are owned by any of the user's organisations
+ # guidances are viewable if they are owned by the user's org
if guidance.guidance_group.org == user.org
viewable = true
end
@@ -99,14 +96,14 @@
if Org.managing_orgs.include?(guidance.guidance_group.org)
viewable = true
end
-
+
# guidance groups are viewable if they are owned by a funder
if Org.funders.include?(guidance.guidance_group.org)
viewable = true
end
end
end
-
+
return viewable
end
@@ -120,24 +117,17 @@
# @param user [User] a user object
# @return [Array] a list of all "viewable" guidances to a user
def self.all_viewable(user)
- managing_groups = Org.managing_orgs.collect{|o| o.guidance_groups}
+ managing_groups = Org.includes(guidance_groups: :guidances).managing_orgs.collect{|o| o.guidance_groups}
# find all groups owned by a Funder organisation
- funder_groups = []
- funders = Org.funders
- funders.each do |funder|
- funder_groups += funder.guidance_groups
- end
+ funder_groups = Org.includes(guidance_groups: :guidances).funders.collect{|org| org.guidance_groups}
# find all groups owned by any of the user's organisations
organisation_groups = user.org.guidance_groups
-
+
# find all guidances belonging to any of the viewable groups
- all_viewable_guidances = []
- all_viewable_groups = managing_groups + funder_groups + organisation_groups
- all_viewable_groups.flatten.each do |group|
- all_viewable_guidances += group.guidances
- end
+ all_viewable_groups = (managing_groups + funder_groups + organisation_groups).flatten
+ all_viewable_guidances = all_viewable_groups.collect{|group| group.guidances}
# pass the list of viewable guidances to the view
- return all_viewable_guidances
+ return all_viewable_guidances.flatten
end
end
diff --git a/app/models/guidance_group.rb b/app/models/guidance_group.rb
index 71535c3..ee3e685 100644
--- a/app/models/guidance_group.rb
+++ b/app/models/guidance_group.rb
@@ -3,9 +3,11 @@
##
# Associations
belongs_to :org
- has_many :guidances
+ has_many :guidances, dependent: :destroy
+ has_and_belongs_to_many :plans, join_table: :plans_guidance_groups
# depricated but needed for migration "single_group_for_guidance"
# has_and_belongs_to_many :guidances, join_table: "guidance_in_group"
+
##
# Possibly needed for active_admin
@@ -13,7 +15,7 @@
attr_accessible :org_id, :name, :optional_subset, :published, :org, :guidances,
:as => [:default, :admin]
- validates :name, :org, presence: true
+ validates :name, :org, presence: {message: _("can't be blank")}
# EVALUATE CLASS AND INSTANCE METHODS BELOW
@@ -70,22 +72,20 @@
# @param id [Integer] the integer id for a guidance group
# @param user [User] a user object
# @return [Boolean] true if the specified user can view the specified guidance group, false otherwise
- def self.can_view?(user, id)
- guidance_group = GuidanceGroup.find_by(id: id)
+ def self.can_view?(user, guidance_group)
viewable = false
-
# groups are viewable if they are owned by any of the user's organisations
if guidance_group.org == user.org
viewable = true
end
# groups are viewable if they are owned by the managing curation center
- Org.where( name: GlobalHelpers.constant("organisation_types.managing_organisation")).find_each do |managing_group|
+ Org.managing_orgs.each do |managing_group|
if guidance_group.org.id == managing_group.id
viewable = true
end
end
# groups are viewable if they are owned by a funder
- if guidance_group.org.org_type == 2
+ if guidance_group.org.funder?
viewable = true
end
@@ -103,22 +103,16 @@
# @return [Array] a list of all "viewable" guidance groups to a user
def self.all_viewable(user)
# first find all groups owned by the Managing Curation Center
- managing_org_groups = []
- Org.where(name: GlobalHelpers.constant("organisation_types.managing_organisation")).find_each do |managing_org|
- managing_org_groups = managing_org_groups + managing_org.guidance_groups
- end
+ managing_org_groups = Org.includes(guidance_groups: [guidances: :themes]).managing_orgs.collect{|org| org.guidance_groups}
# find all groups owned by a Funder organisation
- funder_groups = []
- funders = Org.where(org_type: 2)
- funders.each do |funder|
- funder_groups = funder_groups + funder.guidance_groups
- end
+ funder_groups = Org.includes(:guidance_groups).funders.collect{|org| org.guidance_groups}
+
organisation_groups = [user.org.guidance_groups]
# 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.flatten.uniq{|x| x.id}
+ all_viewable_groups = all_viewable_groups.flatten.uniq
return all_viewable_groups
end
end
diff --git a/app/models/identifier_scheme.rb b/app/models/identifier_scheme.rb
index 45b8922..d07aafc 100644
--- a/app/models/identifier_scheme.rb
+++ b/app/models/identifier_scheme.rb
@@ -2,5 +2,5 @@
has_many :user_identifiers
has_many :users, through: :user_identifiers
- validates :name, uniqueness: true, presence: true
+ validates :name, uniqueness: {message: _("must be unique")}, presence: {message: _("can't be blank")}
end
\ No newline at end of file
diff --git a/app/models/language.rb b/app/models/language.rb
index 0bb5a35..2d02783 100644
--- a/app/models/language.rb
+++ b/app/models/language.rb
@@ -6,5 +6,9 @@
##
# Validations
- validates :abbreviation, presence: true, uniqueness: true
+ # Cannot do FastGettext translations here because we constantize LANGUAGES in initializers/constants.rb
+ validates :abbreviation, presence: {message: "can't be blank"}, uniqueness: {message: "must be unique"}
+
+ scope :sorted_by_abbreviation, -> { all.order(:abbreviation) }
+ scope :default, -> { where(default_language: true).first }
end
\ No newline at end of file
diff --git a/app/models/note.rb b/app/models/note.rb
index 74b3078..4341c2a 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -10,5 +10,5 @@
attr_accessible :text, :user_id, :answer_id, :archived, :archived_by,
:answer, :user, :as => [:default, :admin]
- validates :text, :answer, :user, presence: true
+ validates :text, :answer, :user, presence: {message: _("can't be blank")}
end
diff --git a/app/models/org.rb b/app/models/org.rb
index 15dcd92..9abbe2e 100644
--- a/app/models/org.rb
+++ b/app/models/org.rb
@@ -4,13 +4,18 @@
extend Dragonfly::Model::Validations
##
+ # Sort order: Name ASC
+ default_scope { order(name: :asc) }
+
+
+ ##
# Associations
- belongs_to :organisation_type # depricated, but cannot be removed until migration run
+# belongs_to :organisation_type # depricated, but cannot be removed until migration run
belongs_to :language
has_many :guidance_groups
has_many :templates
has_many :users
- has_many :suggested_answers
+ has_many :annotations
has_and_belongs_to_many :token_permission_types, join_table: "org_token_permissions", unique: true
@@ -21,19 +26,20 @@
:logo_file_name, :name, :target_url,
:organisation_type_id, :wayfless_entity, :parent_id, :sort_name,
:token_permission_type_ids, :language_id, :contact_email,
- :language, :org_type, :region, :token_permission_types
+ :language, :org_type, :region, :token_permission_types,
+ :guidance_group_ids, :is_other, :region_id, :logo_uid, :logo_name
##
# Validators
validates :contact_email, email: true, allow_nil: true
- validates :name, presence: true, uniqueness: true
+ validates :name, presence: {message: _("can't be blank")}, uniqueness: {message: _("must be unique")}
# allow validations for logo upload
dragonfly_accessor :logo do
after_assign :resize_image
end
- validates_property :height, of: :logo, in: (0..100)
- validates_property :format, of: :logo, in: ['jpeg', 'png', 'gif','jpg','bmp']
- validates_size_of :logo, maximum: 500.kilobytes
+ validates_property :height, of: :logo, in: (0..100), message: _("height must be less than 100px")
+ validates_property :format, of: :logo, in: ['jpeg', 'png', 'gif','jpg','bmp'], message: _("must be one of the following formats: jpeg, jpg, png, gif, bmp")
+ validates_size_of :logo, maximum: 500.kilobytes, message: _("can't be larger than 500KB")
##
# Define Bit Field values
@@ -47,15 +53,24 @@
column: 'org_type'
# Predefined queries for retrieving the managain organisation and funders
- scope :managing_orgs, -> { where(name: GlobalHelpers.constant("organisation_types.managing_organisation")) }
+ scope :managing_orgs, -> { where(abbreviation: Rails.configuration.branding[:organisation][:abbreviation]) }
scope :funders, -> { where(org_type: 2) }
- scope :institutions, -> { where(org_type: 3) }
+ scope :institutions, -> { where(org_type: 1) }
# EVALUATE CLASS AND INSTANCE METHODS BELOW
#
# What do they do? do they do it efficiently, and do we need them?
+ # Determines the locale set for the organisation
+ # @return String or nil
+ def get_locale
+ if !self.language.nil?
+ return self.language.abbreviation
+ else
+ return nil
+ end
+ end
# TODO: Should these be hardcoded? Also, an Org can currently be multiple org_types at one time.
# For example you can do: funder = true; project = true; school = true
diff --git a/app/models/perm.rb b/app/models/perm.rb
index 114c0f0..58aad3e 100644
--- a/app/models/perm.rb
+++ b/app/models/perm.rb
@@ -6,7 +6,27 @@
##
# Possibly needed for active_admin
# -relies on protected_attributes gem as syntax depricated in rails 4.2
- attr_accessible :name, :as => [:default, :admin]
+ #attr_accessible :name, :as => [:default, :admin]
+
+ validates :name, presence: {message: _("can't be blank")}, uniqueness: {message: _("must be unique")}
+
+ ##
+ # Constant perms
+ #ADD_ORGS = Perm.where(name: 'add_organisations').first.freeze
+ #CHANGE_AFFILIATION = Perm.where(name: 'change_org_affiliation').first.freeze
+ #GRANT_PERMISSIONS = Perm.where(name: 'grant_permissions').first.freeze
+ #MODIFY_TEMPLATES = Perm.where(name: 'modify_templates').first.freeze
+ #MODIFY_GUIDANCE = Perm.where(name: 'modify_guidance').first.freeze
+ #USE_API = Perm.where(name: 'use_api').first.freeze
+ #CHANGE_ORG_DETAILS = Perm.where(name: 'change_org_details').first.freeze
+ #GRANT_API = Perm.where(name: 'grant_api_to_orgs').first.freeze
- validates :name, presence: true, uniqueness: true
+ scope :add_orgs, -> {Perm.find_by(name: 'add_organisations')}
+ scope :change_affiliation, -> {Perm.find_by(name: 'change_org_affiliation')}
+ scope :grant_permissions, -> {Perm.find_by(name: 'grant_permissions')}
+ scope :modify_templates, -> {Perm.find_by(name: 'modify_templates')}
+ scope :modify_guidance, -> {Perm.find_by(name: 'modify_guidance')}
+ scope :use_api, -> {Perm.find_by(name: 'use_api')}
+ scope :change_org_details, -> {Perm.find_by(name: 'change_org_details')}
+ scope :grant_api, -> {Perm.find_by(name: 'grant_api_to_orgs')}
end
diff --git a/app/models/phase.rb b/app/models/phase.rb
index 88429fd..5c2323f 100644
--- a/app/models/phase.rb
+++ b/app/models/phase.rb
@@ -4,12 +4,17 @@
# [+Created:+] 03/09/2014
# [+Copyright:+] Digital Curation Centre and University of California Curation Center
class Phase < ActiveRecord::Base
-# extend FriendlyId
+ ##
+ # Sort order: Number ASC
+ default_scope { order(number: :asc) }
+
+
+# extend FriendlyId
##
# Associations
belongs_to :template
- has_many :sections, dependent: :destroy
+ has_many :sections, -> { order(:number => :asc) }, dependent: :destroy
has_many :questions, :through => :sections, dependent: :destroy
##
@@ -23,13 +28,9 @@
#friendly_id :title, use: [:slugged, :history, :finders]
- validates :title, :number, :template, presence: true
+ validates :title, :number, :template, presence: {message: _("can't be blank")}
-
-
-
-
-
+
# EVALUATE CLASS AND INSTANCE METHODS BELOW
#
# What do they do? do they do it efficiently, and do we need them?
@@ -104,4 +105,5 @@
end
return phase_copy
end
+
end
diff --git a/app/models/plan.rb b/app/models/plan.rb
index a32b171..8688f34 100644
--- a/app/models/plan.rb
+++ b/app/models/plan.rb
@@ -1,4 +1,7 @@
class Plan < ActiveRecord::Base
+
+ before_validation :set_creation_defaults
+
##
# Associations
belongs_to :template
@@ -10,13 +13,14 @@
has_many :notes, through: :answers
has_many :roles, dependent: :destroy
has_many :users, through: :roles
- has_many :plan_guidance_groups, dependent: :destroy
- has_many :guidance_groups, through: :plan_guidance_groups
+ has_and_belongs_to_many :guidance_groups, join_table: :plans_guidance_groups
accepts_nested_attributes_for :template
has_many :exported_plans
has_many :roles
+
+
# COMMENTED OUT THE DIRECT CONNECTION HERE TO Users to prevent assignment of users without an access_level specified (currently defaults to creator)
# has_many :users, through: :roles
@@ -46,6 +50,10 @@
FONT_HEIGHT_CONVERSION_FACTOR = 0.35278 #convert font point size to mm
FONT_WIDTH_HEIGHT_RATIO = 0.4 #Assume glyph width averages 2/5 the height
+ # Scope queries
+ # Note that in ActiveRecord::Enum the mappings are exposed through a class method with the pluralized attribute name (e.g visibilities rather than visibility)
+ scope :publicly_visible, -> { where(:visibility => visibilities[:publicly_visible]).order(:title => :asc) }
+
##
# Settings for the template
has_settings :export, class_name: 'Settings::Template' do |s|
@@ -79,6 +87,17 @@
+ def base_template
+ base = nil
+ t = self.template
+ if t.customization_of.present?
+ base = Template.where("dmptemplate_id = ? and created_at < ?", t.customization_of, self.created_at).order(version: :desc).first
+ end
+ return base
+ end
+
+
+
##
# returns the most recent answer to the given question id
# optionally can create an answer if none exists
@@ -120,7 +139,8 @@
section.questions.each do |question|
question.themes.each do |theme|
theme.guidances.each do |guidance|
- ggroups << guidance.guidance_group
+ ggroups << guidance.guidance_group if guidance.guidance_group.published
+ # only show published guidance groups
end
end
end
@@ -130,10 +150,34 @@
self.guidance_groups = ggroups.uniq
end
-
-
-
##
+ # returns all of the possible guidance groups for the plan (all options to
+ # be selected by the user to display)
+ #
+ # @return Array
+ def get_guidance_group_options
+ # find all the themes in this plan
+ # and get the guidance groups they belong to
+ ggroups = []
+ Template.includes(phases: [sections: [questions: [themes: [guidances: [guidance_group: :org]]]]]).find(self.template_id).phases.each do |phase|
+ phase.sections.each do |section|
+ section.questions.each do |question|
+ question.themes.each do |theme|
+ theme.guidances.each do |guidance|
+ ggroups << guidance.guidance_group if guidance.guidance_group.published
+ # only show published guidance groups
+ end
+ end
+ end
+ end
+ end
+ return ggroups.uniq
+ end
+
+
+
+
+ ##
# returns the guidances associated with the project's organisation, for a specified question
#
# @param question [Question] the question to find guidance for
@@ -168,8 +212,7 @@
end
# Get guidance by theme from any guidance groups currently selected
- self.plan_guidance_groups.where(selected: true).each do |pgg|
- group = pgg.guidance_group
+ self.guidance_groups.each do |group|
group.guidances.each do |guidance|
common_themes = guidance.themes.all & question.themes.all
if common_themes.length > 0
@@ -181,6 +224,9 @@
return guidances
end
+
+
+
##
# adds the given guidance to a hash indexed by a passed guidance group and theme
#
@@ -217,6 +263,7 @@
# @param user_id [Integer] the id for a user
# @return [Boolean] true if user can edit the plan
def editable_by?(user_id)
+ user_id = user_id.id if user_id.is_a?(User)
role = roles.where(user_id: user_id).first
return role.present? && role.editor?
end
@@ -229,6 +276,7 @@
# @param user_id [Integer] the id for a user
# @return [Boolean] true if the user can read the plan
def readable_by?(user_id)
+ user_id = user_id.id if user_id.is_a?(User)
role = roles.where(user_id: user_id).first
return role.present?
end
@@ -239,6 +287,7 @@
# @param user_id [Integer] the id for the user
# @return [Boolean] true if the user can administer the plan
def administerable_by?(user_id)
+ user_id = user_id.id if user_id.is_a?(User)
role = roles.where(user_id: user_id).first
return role.present? && role.administrator?
end
@@ -247,65 +296,140 @@
##
# defines and returns the status of the plan
# status consists of a hash of the num_questions, num_answers, sections, questions, and spaced used.
- # For each section, it contains theid's of each of the questions
+ # For each section, it contains the id's of each of the questions
# for each question, it contains the answer_id, answer_created_by, answer_text, answer_options_id, aand answered_by
#
# @return [Status]
- def status
- status = {
- "num_questions" => 0,
- "num_answers" => 0,
- "sections" => {},
- "questions" => {},
- "space_used" => 0 # percentage of available space in pdf used
- }
- space_used = height_of_text(self.title, 2, 2)
+ def status
+ status = {
+ "num_questions" => 0,
+ "num_answers" => 0,
+ "sections" => {},
+ "questions" => {},
+ "space_used" => 0 # percentage of available space in pdf used
+ }
- sections.each do |s|
- space_used += height_of_text(s.title, 1, 1)
- section_questions = 0
- section_answers = 0
- status["sections"][s.id] = {}
- status["sections"][s.id]["questions"] = Array.new
- s.questions.each do |q|
- status["num_questions"] += 1
- section_questions += 1
- status["sections"][s.id]["questions"] << q.id
- status["questions"][q.id] = {}
- answer = answer(q.id, false)
+ space_used = height_of_text(self.title, 2, 2)
- space_used += height_of_text(q.text) unless q.text == s.title
- space_used += height_of_text(answer.try(:text) || I18n.t('helpers.plan.export.pdf.question_not_answered'))
+ section_ids = sections.map {|s| s.id}
- if ! answer.nil? then
- status["questions"][q.id] = {
- "answer_id" => answer.id,
- "answer_created_at" => answer.created_at.to_i,
- "answer_text" => answer.text,
- "answer_option_ids" => answer.question_options.pluck(:id),
- "answered_by" => answer.user.name
- }
- q_format = q.question_format
- status["num_answers"] += 1 if (q_format.title == I18n.t("helpers.checkbox") || q_format.title == I18n.t("helpers.multi_select_box") ||
- q_format.title == I18n.t("helpers.radio_buttons") || q_format.title == I18n.t("helpers.dropdown")) || answer.text.present?
- section_answers += 1
- #TODO: include selected options in space estimate
- else
- status["questions"][q.id] = {
- "answer_id" => nil,
- "answer_created_at" => nil,
- "answer_text" => nil,
- "answer_option_ids" => nil,
- "answered_by" => nil
- }
- end
- status["sections"][s.id]["num_questions"] = section_questions
- status["sections"][s.id]["num_answers"] = section_answers
+ # we retrieve this is 2 joins:
+ # 1. sections and questions
+ # 2. questions and answers
+ # why? because Rails 4 doesn't have any sensible left outer join.
+ # when we change to RAILS 5 it is meant to have so this can be fixed then
+
+ records = Section.joins(questions: :question_format)
+ .select('sections.id as sectionid,
+ sections.title as stitle,
+ questions.id as questionid,
+ questions.text as questiontext,
+ question_formats.title as qformat')
+ .where("sections.id in (?) ", section_ids)
+ .to_a
+
+ # extract question ids to get answers
+ question_ids = records.map {|r| r.questionid}.uniq
+ status["num_questions"] = question_ids.count
+
+ arecords = Question.joins(answers: :user)
+ .select('questions.id as questionid,
+ answers.id as answerid,
+ answers.plan_id as plan_id,
+ answers.text as answertext,
+ answers.updated_at as updated,
+ users.email as username')
+ .where("questions.id in (?) and answers.plan_id = ?",question_ids, self.id)
+ .to_a
+
+ # we want answerids to extract options later
+ answer_ids = arecords.map {|r| r.answerid}.uniq
+ status["num_answers"] = answer_ids.count
+
+ # create map from questionid to answer structure
+ qa_map = {}
+ arecords.each do |rec|
+ qa_map[rec.questionid] = {
+ plan: rec.plan_id,
+ id: rec.answerid,
+ text: rec.answertext,
+ updated: rec.updated,
+ user: rec.username
+ }
+ end
+
+
+ # build main status structure
+ records.each do |rec|
+ sid = rec.sectionid
+ stitle = rec.stitle
+ qid = rec.questionid
+ qtext = rec.questiontext
+ format = rec.qformat
+
+ answer = nil
+ if qa_map.has_key?(qid)
+ answer = qa_map[qid]
end
+
+ aid = answer.nil? ? nil : answer[:id]
+ atext = answer.nil? ? nil : answer[:text]
+ updated = answer.nil? ? nil : answer[:updated]
+ uname = answer.nil? ? nil : answer[:user]
+
+ space_used += height_of_text(stitle, 1, 1)
+
+ shash = status["sections"]
+ if !shash.has_key?(sid)
+ shash[sid] = {}
+ shash[sid]["num_questions"] = 0
+ shash[sid]["num_answers"] = 0
+ shash[sid]["questions"] = Array.new
+ end
+
+ shash[sid]["questions"] << qid
+ shash[sid]["num_questions"] += 1
+
+ space_used += height_of_text(qtext) unless qtext == stitle
+ if atext.present?
+ space_used += height_of_text(atext)
+ else
+ space_used += height_of_text(_('Question not answered.'))
+ end
+
+ if answer.present? then
+ shash[sid]["num_answers"] += 1
+ end
+
+ status["questions"][qid] = {
+ "format" => format,
+ "answer_id" => aid,
+ "answer_updated_at" => updated.to_i,
+ "answer_text" => atext,
+ "answered_by" => uname
+ }
+
+ end
+
+ records = Answer.joins(:question_options).select('answers.id as answerid, question_options.id as optid').where(id: answer_ids).to_a
+ opt_hash = {}
+ records.each do |rec|
+ aid = rec.answerid
+ optid = rec.optid
+ if !opt_hash.has_key?(aid)
+ opt_hash[aid] = Array.new
+ end
+ opt_hash[aid] << optid
+ end
+
+ status["questions"].each_key do |questionid|
+ answerid = status["questions"][questionid]["answer_id"]
+ status["questions"][questionid]["answer_option_ids"] = opt_hash[answerid]
end
status['space_used'] = estimate_space_used(space_used)
+
return status
end
@@ -509,6 +633,7 @@
#
# @param user_id [Integer] the user to be given priveleges' id
def assign_creator(user_id)
+ user_id = user_id.id if user_id.is_a?(User)
add_user(user_id, true, true, true)
end
@@ -587,6 +712,7 @@
end
end
end
+=end
##
# returns the funder id for the plan
@@ -598,7 +724,6 @@
end
return self.template.org
end
-=end
##
# returns the funder organisation for the project or nil if none is specified
@@ -826,171 +951,61 @@
end
=end
+ # Returns the number of answered questions from the entire plan
+ def num_answered_questions
+ n = 0
+ self.sections.each do |s|
+ n+= s.num_answered_questions(self.id)
+ end
+ return n
+ end
+ # Returns a section given its id or nil if does not exist for the current plan
+ def get_section(section_id)
+ self.sections.find { |s| s.id == section_id }
+ end
- ##
+ # Returns the number of questions for a plan. Note, this method becomes useful
+ # for when sections and their questions are eager loaded so that avoids SQL queries.
+ def num_questions
+ n = 0
+ self.sections.each do |s|
+ n+= s.questions.size()
+ end
+ return n
+ end
+ # the following two methods are for eager loading. One gets used for the plan/show
+ # page and the oter for the plan/edit. The difference is just that one pulls in more than
+ # the other.
+ # TODO: revisit this and work out for sure that maintaining the difference is worthwhile.
+ # it may not be. Also make sure nether is doing more thanit needs to.
#
- # The following method is to help optimise data access.
- # Even using includes or joins the data access gets performed lazily
- # and the caching appears to be forgotten at times over view/partial boundaries
- # To get round it we can pull everything out into a hash and use that
- # which guarantees no further DB accesses.
- #
- # The serializable_hash method only pulls in one level but this includes
- # attributes which are "through" other attributes. So we do a basic
- # conversion to hash and then a "fixup" which knits the pieces together into
- # the structure which we really want.
- #
- def to_hash
- plan_data = self.serializable_hash(
- include: [ :template, :phases, :sections,
- :answers, :notes, :roles, :users, :questions,
- :plan_guidance_groups, :guidance_groups]
- )
+ def self.eager_load(id)
+ Plan.includes(
+ [{template: [
+ {phases: {sections: {questions: :answers}}},
+ {customizations: :org}
+ ]},
+ {plans_guidance_groups: {guidance_group: :guidances}}
+ ]).find(id)
+ end
- question_hash = {}
-
- plan_data["questions"].each do |q|
- question_hash[q["id"]] = q
- end
-
- question_ids = question_hash.keys
-
- suggested_answers = SuggestedAnswer.where(question_id: question_ids).where.not(text: '')
- suggested_answers.each do |sa|
- question_hash[sa.question_id]["suggested_answer"] = sa.serializable_hash
- end
-
- qf_hash = {}
- QuestionFormat.all.each do |qf|
- qf_hash[qf.id] = qf.serializable_hash
- end
- question_hash.values.each do |q|
- q["question_format"] = qf_hash[q["question_format_id"]]
- end
-
- gg_ids = plan_data["plan_guidance_groups"].select{|pgg| pgg["selected"]}.map{|pgg| pgg["guidance_group_id"]}
- gg_hash = {}
-
- theme_guidance = {}
-
- ggs = GuidanceGroup.find(gg_ids).each do |gg|
- gg_hash[gg.id] = gg.serializable_hash
- end
-
- guidances = Guidance.joins(:themes).select('guidances.guidance_group_id, guidances.text, themes.title').where(guidance_group: gg_ids).to_a
- guidances.each do |g|
- title = g.title
- if !theme_guidance.has_key?(title)
- theme_guidance[title] = Array.new
- end
- theme_guidance[title] << {
- "text" => g.text,
- "org" => gg_hash[g.guidance_group_id]["name"]
- }
- end
-
- plan_data["questions"].each do |q|
- qg = {}
- if q.has_key?("themes")
- q["themes"].each do |t|
- title = t["title"]
- qg[title] = theme_guidance[title] if theme_guidance.has_key?(title)
- end
- q["theme_guidance"] = qg
- end
- end
-
- fixup_hash(plan_data)
-
- return plan_data
+ def self.eager_load2(id)
+ Plan.includes(
+ [{template: [
+ {phases: {sections: {questions: [{answers: :notes}, :annotations, :question_format, :themes]}}},
+ {customizations: :org},
+ :org
+ ]},
+ {plans_guidance_groups: {guidance_group: {guidances: :themes}}},
+ {questions: :themes}
+ ]).find(id)
end
private
- # reconnect the various parts of the hash so that:
- # plan = {
- # template:
- # phases:
- # sections:
- # questions:
- # answers
- # }
- #
- # becomes a nested structure like so
- #
- # plan = { template: {
- # phases: [ {
- # sections: [ {
- # questions: [ {
- # answers: [...]
- #
- def fixup_hash(plan)
- # sort out guidance first so we can add it to the questions
- # before rolling up
- ghash = {}
- plan["guidance_groups"].map{|g| ghash[g["id"]] = g}
- plan["plan_guidance_groups"].each do |pgg|
- pgg["guidance_group"] = ghash[ pgg["guidance_group_id"] ]
- end
-
- rollup(plan, "notes", "answer_id", "answers")
- rollup(plan, "answers", "question_id", "questions")
- rollup(plan, "questions", "section_id", "sections", true)
- rollup(plan, "sections", "phase_id", "phases", true)
-
- plan["template"]["phases"] = plan.delete("phases")
- plan["template"]["phases"].sort! { |x,y| x["number"].to_i <=> y["number"].to_i }
-
- plan["template"]["org"] = Org.find(plan["template"]["org_id"]).serializable_hash()
-
- # when editing phases we want the number of questions answered
- # so calculate that now
- plan["template"]["phases"].each do |phase|
- phase["sections"].each do |section|
- nanswers = 0
- section["questions"].each do |question|
- if question.has_key?("answers") && question["answers"].first["text"].present?
- nanswers += 1
- end
- end
- section["nanswers"] = nanswers
- end
- end
-
- end
-
-
- # find all object under src_plan_key
- # merge them into the items under obj_plan_key using
- # super_id = id
- # so we have answers which each have a question_id
- # rollup(plan, "answers", "quesiton_id", "questions")
- # will put the answers into the right questions.
- # sort determines whether the items being rolled up should be sorted by number field
- def rollup(plan, src_plan_key, super_id, obj_plan_key, sort = false)
- id_to_obj = Hash.new()
- plan[src_plan_key].each do |o|
- id = o[super_id]
- if !id_to_obj.has_key?(id)
- id_to_obj[id] = Array.new
- end
- id_to_obj[id] << o
- end
-
- plan[obj_plan_key].each do |o|
- id = o["id"]
- if id_to_obj.has_key?(id)
- if sort
- id_to_obj[ id ].sort! { |x,y| x["number"].to_i <=> y["number"].to_i }
- end
- o[src_plan_key] = id_to_obj[ id ]
- end
- end
- plan.delete(src_plan_key)
- end
##
# adds a user to the project
@@ -1014,9 +1029,25 @@
role.user_id = user_id
role.plan_id = id
- role.creator= is_creator
- role.editor= is_editor
- role.administrator= is_administrator
+ # if you get assigned a role you can comment
+ role.commenter= true
+
+ # the rest of the roles are inclusing so creator => administrator => editor
+ if is_creator
+ role.creator = true
+ role.administrator = true
+ role.editor = true
+ end
+
+ if is_administrator
+ role.administrator = true
+ role.editor = true
+ end
+
+ if is_editor
+ role.editor = true
+ end
+
role.save
# This is necessary because we're creating the associated record but not assigning it
@@ -1099,4 +1130,14 @@
(num_lines * font_height) + vertical_margin + leading
end
+ # Initialize the title and dirty flags for new templates
+ # --------------------------------------------------------
+ def set_creation_defaults
+ # Only run this before_validation because rails fires this before save/create
+ if self.id.nil?
+ self.title = "My plan (#{self.template.title})" if self.title.nil? && !self.template.nil?
+ self.visibility = 3
+ end
+ end
+
end
diff --git a/app/models/plan_guidance_group.rb b/app/models/plan_guidance_group.rb
deleted file mode 100644
index 7b76499..0000000
--- a/app/models/plan_guidance_group.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# Used to link plans to guidance groups
-# the links are created at plan creation stage
-# and link to all possible GGs
-# then the selected field keeps track of which ones the user has turned on /off
-#
-class PlanGuidanceGroup < ActiveRecord::Base
- belongs_to :plan
- belongs_to :guidance_group
-
- attr_accessible :selected
-end
diff --git a/app/models/question.rb b/app/models/question.rb
index 61eddd1..0a3e947 100644
--- a/app/models/question.rb
+++ b/app/models/question.rb
@@ -1,10 +1,14 @@
class Question < ActiveRecord::Base
##
+ # Sort order: Number ASC
+ default_scope { order(number: :asc) }
+
+ ##
# Associations
has_many :answers, :dependent => :destroy
- has_many :question_options, :dependent => :destroy
- has_many :suggested_answers, :dependent => :destroy
+ has_many :question_options, :dependent => :destroy, :inverse_of => :question # inverse_of needed for nester forms
+ has_many :annotations, :dependent => :destroy
has_and_belongs_to_many :themes, join_table: "questions_themes"
belongs_to :section
belongs_to :question_format
@@ -14,21 +18,20 @@
# TODO: evaluate if we need this
accepts_nested_attributes_for :answers, :reject_if => lambda {|a| a[:text].blank? }, :allow_destroy => true
accepts_nested_attributes_for :question_options, :reject_if => lambda {|a| a[:text].blank? }, :allow_destroy => true
- accepts_nested_attributes_for :suggested_answers, :allow_destroy => true
+ accepts_nested_attributes_for :annotations, :allow_destroy => true
accepts_nested_attributes_for :themes
##
# 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,
+ :annotation, :text, :section_id, :question_format_id,
+ :question_options_attributes, :annotations_attributes,
:option_comment_display, :theme_ids, :section, :question_format,
- :question_options, :suggested_answers, :answers, :themes,
+ :question_options, :annotations, :answers, :themes,
:modifiable, :option_comment_display, :as => [:default, :admin]
- validates :text, :section, :number, presence: true
-
+ validates :text, :section, :number, presence: {message: _("can't be blank")}
# EVALUATE CLASS AND INSTANCE METHODS BELOW
#
@@ -44,6 +47,16 @@
"#{text}"
end
+
+ def option_based?
+ format = self.question_format
+ return format.option_based
+ end
+
+ def plan_answers(plan_id)
+ return self.answers.to_a.select{|ans| ans.plan_id == plan_id}
+ end
+
##
# deep copy the given question and all it's associations
#
@@ -57,10 +70,10 @@
question_option_copy.question_id = question_copy.id
question_option_copy.save!
end
- question.suggested_answers.each do |suggested_answer|
- suggested_answer_copy = SuggestedAnswer.deep_copy(suggested_answer)
- suggested_answer_copy.question_id = question_copy.id
- suggested_answer_copy.save!
+ question.annotations.each do |annotation|
+ annotation_copy = Annotation.deep_copy(annotation)
+ annotation_copy.question_id = question_copy.id
+ annotation_copy.save!
end
question.themes.each do |theme|
question_copy.themes << theme
@@ -82,7 +95,7 @@
group.guidances.each do |g|
g.themes.each do |theme|
if theme_ids.include? theme.id
- guidances["#{group.name} " + I18n.t('admin.guidance_lowercase_on') + " #{theme.title}"] = g
+ guidances["#{group.name} " + _('guidance on') + " #{theme.title}"] = g
end
end
end
@@ -93,13 +106,24 @@
end
##
- # get suggested answer belonging to the currents user for this question
+ # get example answer belonging to the currents user for this question
#
# @param org_id [Integer] the id for the organisation
- # @return [String] the suggested_answer for this question for the specified organisation
- def get_suggested_answer(org_id)
- suggested_answer = suggested_answers.find_by(org_id: org_id)
- return suggested_answer
+ # @return [String] the example answer for this question for the specified org
+ def get_example_answer(org_id)
+ example_answer = self.annotations.where(org_id: org_id).where(type: Annotation.types[:example_answer]).order(:created_at)
+ return example_answer.first
end
+ ##
+ # get guidance belonging to the current user's org for this question(need org
+ # to distinguish customizations)
+ #
+ # @param org_id [Integer] the id for the organisation
+ # @return [String] the annotation guidance for this question for the specified org
+ def get_guidance_annotation(org_id)
+ guidance = self.annotations.where(org_id: org_id).where(type: Annotation.types[:guidance])
+ return guidance.first
+ end
+
end
diff --git a/app/models/question_format.rb b/app/models/question_format.rb
index 7f1a900..b7d6afc 100644
--- a/app/models/question_format.rb
+++ b/app/models/question_format.rb
@@ -3,14 +3,23 @@
##
# Associations
has_many :questions
+
+ enum formattype: [ :textarea, :textfield, :radiobuttons, :checkbox, :dropdown, :multiselectbox, :date ]
+ attr_accessible :formattype
- validates :title, presence: true, uniqueness: true
+ validates :title, presence: {message: _("can't be blank")}, uniqueness: {message: _("must be unique")}
##
# Possibly needed for active_admin
# -relies on protected_attributes gem as syntax depricated in rails 4.2
attr_accessible :title, :description, :option_based, :questions, :as => [:default, :admin]
+ # Retrieves the id for a given formattype passed
+ scope :id_for, -> (formattype) { where(formattype: formattype).pluck(:id).first }
+
+ ##
+ # Define Bit Field Values so we can test a format without doing string comps
+ # Column type
# EVALUATE CLASS AND INSTANCE METHODS BELOW
#
@@ -25,4 +34,4 @@
"#{title}"
end
-end
\ No newline at end of file
+end
diff --git a/app/models/question_option.rb b/app/models/question_option.rb
index 11552b0..b0fec82 100644
--- a/app/models/question_option.rb
+++ b/app/models/question_option.rb
@@ -10,8 +10,9 @@
attr_accessible :text, :question_id, :is_default, :number, :question,
:as => [:default, :admin]
- validates :text, :question, :number, presence: true
+ validates :text, :question, :number, presence: {message: _("can't be blank")}
+ scope :by_number, -> { order(:number) }
##
# deep copy the given question_option and all it's associations
#
diff --git a/app/models/region.rb b/app/models/region.rb
index 2c57e79..a7e366a 100644
--- a/app/models/region.rb
+++ b/app/models/region.rb
@@ -3,6 +3,6 @@
belongs_to :super_region, class_name: 'Region'
- validates :name, presence: true, uniqueness: true
- validates :abbreviation, uniqueness: true, allow_nil: true
+ validates :name, presence: {message: _("can't be blank")}, uniqueness: {message: _("must be unique")}
+ validates :abbreviation, uniqueness: {message: _("must be unique")}, allow_nil: true
end
\ No newline at end of file
diff --git a/app/models/role.rb b/app/models/role.rb
index cf49c87..a51177d 100644
--- a/app/models/role.rb
+++ b/app/models/role.rb
@@ -1,64 +1,59 @@
class Role < ActiveRecord::Base
include FlagShihTzu
- before_validation :check_access_level
-
##
- # Associations
+ # Associationsrequire "role"
+
belongs_to :user
belongs_to :plan
##
# Define Bit Field Values
# Column access
- has_flags 1 => :creator,
- 2 => :administrator,
- 3 => :editor,
+ has_flags 1 => :creator, # 1
+ 2 => :administrator, # 2
+ 3 => :editor, # 4
+ 4 => :commenter, # 8
column: 'access'
- validates :user, :plan, :access, presence: true
- validates :access, numericality: {greater_than: 0}
+ validates :user, :plan, :access, presence: {message: _("can't be blank")}
+ validates :access, numericality: {greater_than: 0, message: _("can't be less than zero")}
##
# return the access level for the current project group
# 3 if the user is an administrator
# 2 if the user is an editor
# 1 if the user can only read
+ # used to facilliatte formtastic
#
# @return [Integer]
def access_level
- if self.administrator? then
+ if self.administrator?
return 3
- elsif self.editor? then
+ elsif self.editor?
return 2
- else
+ elsif self.commenter?
return 1
end
end
- ##
- # define a new access level for the current project group
- # if >=3, the user is a project administrator
- # if >=2, the user is an editor
- #
- # @param new_access_level [Integer] the access level to give the user
- def access_level=(new_access_level)
- new_access_level = new_access_level.to_i
- if new_access_level >= 3 then
- self.administrator = true
- else
- self.administrator = false
- end
- if new_access_level >= 2 then
- self.editor = true
- else
- self.editor = false
- end
- self.creator = true unless self.administrator? || self.editor?
- end
-
- # Ensures that the access attribute is set (will default to creator - see logic in access_level=)
- def check_access_level
- self.access_level = self.access_level
- end
end
+
+# -----------------------------------------------------
+# Bitwise key
+# -----------------------------------------------------
+# 01 - creator
+# 02 - administrator
+# 03 - creator + administrator
+# 04 - editor
+# 05 - creator + editor
+# 06 - administraor + editor
+# 07 - creator + editor + administrator
+# 08 - commenter
+# 09 - creator + commenter
+# 10 - administrator + commenter
+# 11 - creator + administrator + commenter
+# 12 - editor + commenter
+# 13 - creator + editor + commenter
+# 14 - administrator + editor + commenter
+# 15 - creator + administrator + editor + commenter
\ No newline at end of file
diff --git a/app/models/section.rb b/app/models/section.rb
index 87e98b6..4d4562b 100644
--- a/app/models/section.rb
+++ b/app/models/section.rb
@@ -1,5 +1,4 @@
class Section < ActiveRecord::Base
-
##
# Associations
belongs_to :phase
@@ -14,7 +13,7 @@
:questions_attributes, :organisation, :phase, :modifiable,
:as => [:default, :admin]
- validates :phase, :title, :number, presence: true
+ validates :phase, :title, :number, presence: {message: _("can't be blank")}
##
# return the title of the section
@@ -24,6 +23,15 @@
"#{title}"
end
+ # Returns the number of answered questions for a given plan id
+ def num_answered_questions(plan_id)
+ n = 0
+ self.questions.each do |question|
+ n += question.plan_answers(plan_id).select{|answer| answer.is_valid?}.count
+ end
+ return n
+ end
+
##
# deep copy of the given section and all it's associations
#
@@ -39,5 +47,4 @@
end
return section_copy
end
-
end
diff --git a/app/models/settings/plan_list.rb b/app/models/settings/plan_list.rb
deleted file mode 100644
index 26f6ed5..0000000
--- a/app/models/settings/plan_list.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-module Settings
- class PlanList < RailsSettings::SettingObject
-
- #attr_accessible :var, :target, :target_type, :target_id
-
- # 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', 'visibility',
- 'principal_investigator', 'data_contact', 'description']
-
- validate do
- cols = value["columns"]
-
- if cols.present? # columns can be empty, in which case they revert to defaults
- errors.add(:columns, I18n.t("helpers.settings.projects.errors.no_name")) unless cols.member?("name")
- errors.add(:columns, I18n.t("helpers.settings.projects.errors.duplicate")) unless cols.keys.uniq == cols.keys
- errors.add(:columns, I18n.t("helpers.settings.projects.errors.unknown")) unless (cols.keys.uniq & ALL_COLUMNS) == cols.keys.uniq
- end
- end
- end
-end
diff --git a/app/models/settings/template.rb b/app/models/settings/template.rb
index 2956eac..59ac3de 100644
--- a/app/models/settings/template.rb
+++ b/app/models/settings/template.rb
@@ -59,13 +59,27 @@
end
errs.map do |key|
- errors.add(:formatting, I18n.t("helpers.settings.plans.errors.#{key}"))
+ if key == :missing_key
+ errors.add(:formatting, _('A required setting has not been provided'))
+ elsif key == :invalid_margin
+ errors.add(:formatting, _('Margin value is invalid'))
+ elsif key == :negative_margin
+ errors.add(:formatting, _('Margin cannot be negative'))
+ elsif key == :unknown_margin
+ errors.add(:formatting, _("Unknown margin. Can only be 'top', 'bottom', 'left' or 'right'"))
+ elsif key == :invalid_font_size
+ errors.add(:formatting, _('Invalid font size'))
+ elsif key == :invalid_font_face
+ errors.add(:formatting, _('Invalid font face'))
+ elsif key == :unknown_key
+ errors.add(:formatting, _('Unknown formatting setting'))
+ end
end
end
if max_pages.present? && (!max_pages.is_a?(Integer) || max_pages <= 0)
- errors.add(:max_pages, I18n.t('helpers.settings.plans.errors.invalid_max_pages'))
+ errors.add(:max_pages, _('Invalid maximum pages'))
end
end
diff --git a/app/models/suggested_answer.rb b/app/models/suggested_answer.rb
deleted file mode 100644
index 91ce3aa..0000000
--- a/app/models/suggested_answer.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-class SuggestedAnswer < ActiveRecord::Base
-
- ##
- # Associations
- belongs_to :org
- belongs_to :question
-
- ##
- # 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,
- :org, :question, :as => [:default, :admin]
-
-
- validates :question, :org, presence: true
-
- # EVALUATE CLASS AND INSTANCE METHODS BELOW
- #
- # What do they do? do they do it efficiently, and do we need them?
-
-
-
- ##
- # returns the text from the suggested_answer
- #
- # @return [String] the text from the suggested_answer
- def to_s
- "#{text}"
- end
-
-
- ##
- # deep copy the given question_option and all it's associations
- #
- # @params [QuestionOption] question_option to be deep copied
- # @return [QuestionOption] the saved, copied question_option
- def self.deep_copy(suggested_answer)
- suggested_answer_copy = suggested_answer.dup
- suggested_answer_copy.save!
- return suggested_answer_copy
- end
-end
\ No newline at end of file
diff --git a/app/models/template.rb b/app/models/template.rb
index 9c59637..b72d216 100644
--- a/app/models/template.rb
+++ b/app/models/template.rb
@@ -1,6 +1,8 @@
class Template < ActiveRecord::Base
include GlobalHelpers
+ before_validation :set_creation_defaults
+ scope :valid, -> {where(migrated: false)}
##
# Associations
belongs_to :org
@@ -15,21 +17,43 @@
##
# Possibly needed for active_admin
# -relies on protected_attributes gem as syntax depricated in rails 4.2
- attr_accessible :id, :org_id, :description, :published, :title, :locale,
- :is_default, :guidance_group_ids, :org, :plans, :phases,
- :version, :visibility, :published, :as => [:default, :admin]
+ attr_accessible :id, :org_id, :description, :published, :title, :locale, :customization_of,
+ :is_default, :guidance_group_ids, :org, :plans, :phases, :dmptemplate_id,
+ :migrated, :version, :visibility, :published, :as => [:default, :admin]
# defines the export setting for a template object
has_settings :export, class_name: 'Settings::Template' do |s|
s.key :export, defaults: Settings::Template::DEFAULT_SETTINGS
end
- validates :org, :title, :version, presence: true
+ validates :org, :title, :version, presence: {message: _("can't be blank")}
- # EVALUATE CLASS AND INSTANCE METHODS BELOW
+ # Retrieves the list of all dmptemplate_ids (template versioning families) for the specified Org
+ def self.dmptemplate_ids
+ Template.all.valid.distinct.pluck(:dmptemplate_id)
+ end
+
+ # Retrieves the most recent version of the template for the specified Org and dmptemplate_id
+ def self.current(dmptemplate_id)
+ Template.where(dmptemplate_id: dmptemplate_id).order(version: :desc).valid.first
+ end
+
+ # Retrieves the current published version of the template for the specified Org and dmptemplate_id
+ def self.live(dmptemplate_id)
+ Template.where(dmptemplate_id: dmptemplate_id, published: true).valid.first
+ end
+
+ ##
+ # Retrieves the most current customization of the template for the
+ # specified org and dmptemplate_id
+ # returns nil if no customizations found
#
- # What do they do? do they do it efficiently, and do we need them?
-
+ # @params [integer] dmptemplate_id of the original template
+ # @params [integer] org_id for the customizing organisation
+ # @return [nil, Template] the customized template or nil
+ def self.org_customizations(dmptemplate_id, org_id)
+ Template.where(customization_of: dmptemplate_id, org_id: org_id).order(version: :desc).valid.first
+ end
##
# deep copy the given template and all of it's associations
@@ -47,96 +71,54 @@
return template_copy
end
- ##
- # takes a type or organisation and returns all published templates from
- # organisations of that type
- #
- # @param ot [String] name of an organisation type e.g. founder
- # @return [Array] list of published dmptemplates
-=begin
- def self.templates_org_type(ot)
- # DISCUSS - This function other than the check for the template being published
- # is a superclass for the below funders_templates
- new_org_obejcts = OrganisationType.find_by( name: ot ).organisations
- org_templates = Array.new
- new_org_obejcts.each do |neworg|
- org_templates += neworg.dmptemplates.where("published = ?", true)
+ # EVALUATE CLASS AND INSTANCE METHODS BELOW
+ #
+ # What do they do? do they do it efficiently, and do we need them?
+
+
+ ##
+ # convert the given template to a hash and return with all it's associations
+ # to use, please pre-fetch org, phases, section, questions, annotations,
+ # question_options, question_formats,
+ # TODO: Themes & guidance?
+ #
+ # @return [hash] hash of template, phases, sections, questions, question_options, annotations
+ def to_hash
+ hash = {}
+ hash[:template] = {}
+ hash[:template][:data] = self
+ hash[:template][:org] = self.org
+ phases = {}
+ hash[:template][:phases] = phases
+ self.phases.each do |phase|
+ phases[phase.number] = {}
+ phases[phase.number][:data] = phase
+ phases[phase.number][:sections] = {}
+ phase.sections.each do |section|
+ phases[phase.number][:sections][section.number] = {}
+ phases[phase.number][:sections][section.number][:data] = section
+ phases[phase.number][:sections][section.number][:questions] = {}
+ section.questions.each do |question|
+ phases[phase.number][:sections][section.number][:questions][question.number] = {}
+ phases[phase.number][:sections][section.number][:questions][question.number][:data] = question
+ phases[phase.number][:sections][section.number][:questions][question.number][:annotations] = {}
+ question.annotations.each do |annotation|
+ phases[phase.number][:sections][section.number][:questions][question.number][:annotations][annotation.id] = {}
+ phases[phase.number][:sections][section.number][:questions][question.number][:annotations][annotation.id][:data] = annotation
+ end
+ phases[phase.number][:sections][section.number][:questions][question.number][:question_options] = {}
+ question.question_options.each do |question_option|
+ phases[phase.number][:sections][section.number][:questions][question.number][:question_options][:data] = question_option
+ phases[phase.number][:sections][section.number][:questions][question.number][:question_format] = question.question_format
+ end
+ end
+ end
end
-
- return org_templates
+ return hash
end
- ##
- # returns all templates from all organisations of the Organisation_Type funder
- #
- # @return [Array] all templates from funder organisations
- def self.funders_templates
- funder_orgs = Org.includes(:templates).funder
- org_templates = Array.new
-
- funder_orgs.each do |neworg|
- org_templates += neworg.templates
- end
-
- return org_templates
- end
-
- ##
- # returns all institutional templates bellowing to the given organisation
- #
- # @param org_id [integer] the integer id for an organisation
- # @return [Array] all templates from a user's organisation
- def self.own_institutional_templates(org_id)
- # DISCUSS - Why is this done by scanning organisation_id's from the templates
- # yet all other calls are done by finding an organisation, and using the
- # has_many relationship to find the dmptemplates?
- # - A possible answer is that there may be deleted organisations which we are
- # serching for templates for.
- # - A standardised behavior on querries, wether through active reccord or the
- # where, should maybe be thought of/decided upon
- new_templates = self.where("org_id = ?", org_id)
- return new_templates
- end
-
- ##
- # returns an array with all funders and of the given organisations's
- # institutional templates
- #
- # @param org_id [integer] the integer id for an organisation
- # @return [Array] all templates from the template's organisation
- # or from a funder organisation
- def self.funders_and_own_templates(org_id)
- funders_templates = self.funders_templates
-
- #verify if org type is not a funder
- current_org = Org.find(org_id)
- if !current_org.funder? then
- own_institutional_templates = self.own_institutional_templates(org_id)
- else
- own_institutional_templates = []
- end
-
- templates_list = Array.new
- templates_list += own_institutional_templates
- templates_list += funders_templates
- templates_list = templates_list.sort_by { |f| f['title'].downcase }
-
- return templates_list
- end
-
- ##
- # Returns the string name of the organisation type of the organisation who
- # owns this dmptemplate
- #
- # @return [string] the string name of an organisation type
- def org_type
- org_type = org.organisation_type
- return org_type
- end
-=end
-
-# TODO: Why are we passing in an org and template here?
+# TODO: Why are we passing in an org and template here?
##
# Verify if a template has customisation by given organisation
#
@@ -149,33 +131,29 @@
modifiable = modifiable && phase.modifiable
end
return !modifiable
- # if temp.org_id != org_id then
- # temp.phases.each do |phase|
- # phase.versions.each do |version|
- # version.sections.each do |section|
- # return true if section.organisation_id == org_id
- # end
- # end
- # return false
- # end
- # else
- # return false
- # end
end
-=begin
- ##
- # verify if there are any publish version for the template
- #
- # @return [Boolean] true if there is a published version for the template
- def has_published_versions?
- phases.each do |phase|
- return true if !phase.latest_published_version.nil?
+ # --------------------------------------------------------
+ private
+ # Initialize the published and dirty flags for new templates
+ def set_creation_defaults
+ # Only run this before_validation because rails fires this before save/create
+ if self.id.nil?
+ self.published = false
+ self.migrated = false
+ self.dirty = false
+ self.visibility = 1
+ self.is_default = false
+ self.version = 0 if self.version.nil?
+
+ # Generate a unique identifier for the dmptemplate_id if necessary
+ if self.dmptemplate_id.nil?
+ self.dmptemplate_id = loop do
+ random = rand 2147483647
+ break random unless Template.exists?(dmptemplate_id: random)
+ end
+ end
end
- return false
end
-=end
-
- # OLD CODE STARTS HERE
end
diff --git a/app/models/theme.rb b/app/models/theme.rb
index 315dfe8..bd787f6 100644
--- a/app/models/theme.rb
+++ b/app/models/theme.rb
@@ -13,7 +13,7 @@
attr_accessible :description, :title, :locale , :as => [:default, :admin]
- validates :title, presence: true
+ validates :title, presence: {message: _("can't be blank")}
# EVALUATE CLASS AND INSTANCE METHODS BELOW
#
diff --git a/app/models/token_permission_type.rb b/app/models/token_permission_type.rb
index 71f8186..5770e6c 100644
--- a/app/models/token_permission_type.rb
+++ b/app/models/token_permission_type.rb
@@ -12,13 +12,14 @@
##
# Validators
- validates :token_type, presence: true, uniqueness: true
+ validates :token_type, presence: {message: _("can't be blank")}, uniqueness: {message: _("must be unique")}
-
- # EVALUATE CLASS AND INSTANCE METHODS BELOW
- #
- # What do they do? do they do it efficiently, and do we need them?
-
+ ##
+ # Constant Token Permission Types
+ GUIDANCES = TokenPermissionType.where(token_type: 'guidances').first.freeze
+ PLANS = TokenPermissionType.where(token_type: 'plans').first.freeze
+ TEMPLATES = TokenPermissionType.where(token_type: 'templates').first.freeze
+ STATISTICS = TokenPermissionType.where(token_type: 'statistics').first.freeze
##
diff --git a/app/models/user.rb b/app/models/user.rb
index 4cf42a2..f900030 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -7,7 +7,7 @@
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :invitable, :database_authenticatable, :registerable, :recoverable,
- :rememberable, :trackable, :validatable, :confirmable, :omniauthable,
+ :rememberable, :trackable, :validatable, :omniauthable,
:omniauth_providers => [:shibboleth, :orcid]
##
@@ -40,25 +40,20 @@
##
# Possibly needed for active_admin
# -relies on protected_attributes gem as syntax depricated in rails 4.2
- accepts_nested_attributes_for :roles
- attr_accessible :password_confirmation, :encrypted_password, :remember_me,
- :id, :email, :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, :org, :perms,
- :confirmed_at, :org_id
+ #accepts_nested_attributes_for :roles
+ #attr_accessible :password_confirmation, :encrypted_password, :remember_me,
+ # :id, :email, :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, :org, :perms,
+ # :confirmed_at, :org_id
- validates :email, email: true, allow_nil: true, uniqueness: true
+ validates :email, email: true, allow_nil: true, uniqueness: {message: _("must be unique")}
##
- # Settings
- # FIXME: The duplication in the block is to set defaults. It might be better if
- # they could be set in Settings::PlanList itself, if possible.
- has_settings :plan_list, class_name: 'Settings::PlanList' do |s|
- s.key :plan_list, defaults: { columns: Settings::PlanList::DEFAULT_COLUMNS }
- end
-
+ # Scopes
+ default_scope { includes(:org, :perms) }
@@ -66,8 +61,17 @@
#
# What do they do? do they do it efficiently, and do we need them?
-
-
+ # Determines the locale set for the user or the organisation he/she belongs
+ # @return String or nil
+ def get_locale
+ if !self.language.nil?
+ return self.language.abbreviation
+ elsif !self.org.nil?
+ return self.org.get_locale
+ else
+ return nil
+ end
+ end
##
@@ -103,14 +107,13 @@
#
# @param new_organisation_id [Integer] the id for an organisation
# @return [String] the empty string as a causality of setting api_token
-=begin
- def organisation_id=(new_organisation_id)
- unless self.can_change_org? || new_organisation_id.nil? || self.organisation.nil?
+ def org_id=(new_org_id)
+ unless self.can_change_org? || new_org_id.nil? || self.org.nil? || (new_org_id.to_s == self.org.id.to_s)
# rip all permissions from the user
self.perms.delete_all
end
# set the user's new organisation
- super(new_organisation_id)
+ super(new_org_id)
self.save!
# rip api permissions from the user
self.remove_token!
@@ -120,10 +123,9 @@
# sets a new organisation for the user
#
# @param new_organisation [Organisation] the new organisation for the user
- def organisation=(new_organisation)
- organisation_id = new_organisation.id unless new_organisation.nil?
+ def organisation=(new_org)
+ org_id = new_org.id unless new_org.nil?
end
-=end
##
# checks if the user is a super admin
@@ -151,7 +153,7 @@
#
# @return [Boolean] true if the user can add new organisations
def can_add_orgs?
- perms.include? Perm.find_by(name: constant("roles.add_organisations"))
+ perms.include? Perm.add_orgs
end
##
@@ -159,7 +161,7 @@
#
# @return [Boolean] true if the user can change their organisation affiliations
def can_change_org?
- perms.include? Perm.find_by(name: constant("roles.change_org_affiliation"))
+ perms.include? Perm.change_affiliation
end
##
@@ -167,7 +169,7 @@
#
# @return [Boolean] true if the user can grant their permissions to others
def can_grant_permissions?
- perms.include? Perm.find_by(name: constant("roles.grant_permissions"))
+ perms.include? Perm.grant_permissions
end
##
@@ -175,7 +177,7 @@
#
# @return [Boolean] true if the user can modify organisation templates
def can_modify_templates?
- perms.include? Perm.find_by(name: constant("roles.modify_templates"))
+ self.perms.include? Perm.modify_templates
end
##
@@ -183,7 +185,7 @@
#
# @return [Boolean] true if the user can modify organistion guidance
def can_modify_guidance?
- perms.include? Perm.find_by(name: constant("roles.modify_guidance"))
+ perms.include? Perm.modify_guidance
end
##
@@ -191,7 +193,7 @@
#
# @return [Boolean] true if the user can use the api
def can_use_api?
- perms.include? Perm.find_by(name: constant("roles.use_api"))
+ perms.include? Perm.use_api
end
##
@@ -199,7 +201,7 @@
#
# @return [Boolean] true if the user can modify the org's details
def can_modify_org_details?
- perms.include? Perm.find_by(name: constant("roles.change_org_details"))
+ perms.include? Perm.change_org_details
end
@@ -208,7 +210,7 @@
#
# @return [Boolean] true if the user can grant api permissions to organisations
def can_grant_api_to_orgs?
- perms.include? Perm.find_by(name: constant('roles.grant_api_to_orgs'))
+ perms.include? Perm.grant_api
end
##
@@ -261,6 +263,14 @@
end
end
+ ##
+ # Override devise_invitable email title
+ # --------------------------------------------------------------
+ def deliver_invitation(options = {})
+ super(options.merge(subject: _('A Data Management Plan in %{application_name} has been shared with you') % {application_name: Rails.configuration.branding[:application][:name]}))
+ end
+
+
# TODO: Remove this, its never called.
# this generates a reset password link for a given user
# which can then be sent to them with the appropriate host
diff --git a/app/models/user_identifier.rb b/app/models/user_identifier.rb
index 6623765..840e394 100644
--- a/app/models/user_identifier.rb
+++ b/app/models/user_identifier.rb
@@ -5,5 +5,5 @@
# Should only be able to have one identifier per scheme!
validates_uniqueness_of :identifier_scheme, scope: :user
- validates :identifier, :user, :identifier_scheme, presence: true
+ validates :identifier, :user, :identifier_scheme, presence: {message: _("can't be blank")}
end
\ No newline at end of file
diff --git a/app/policies/annotation_policy.rb b/app/policies/annotation_policy.rb
new file mode 100644
index 0000000..a426546
--- /dev/null
+++ b/app/policies/annotation_policy.rb
@@ -0,0 +1,29 @@
+class AnnotationPolicy < ApplicationPolicy
+ attr_reader :user, :annotation
+
+ def initialize(user, annotation)
+ raise Pundit::NotAuthorizedError, "must be logged in" unless user
+ @user = user
+ @annotation = annotation
+ end
+
+ ##
+ # Users can modify annotations if:
+ # - They can modify templates
+ # - The template which they are modifying belongs to their orggi
+ ##
+
+ def admin_create?
+ # here we pass through a question instead of an annotation object
+ user.can_modify_templates? && (annotation.section.phase.template.org_id == user.org_id)
+ end
+
+ def admin_update?
+ user.can_modify_templates? && (annotation.question.section.phase.template.org_id == user.org_id) && annotation.org_id == user.org_id
+ end
+
+ def admin_destroy?
+ user.can_modify_templates? && (annotation.question.section.phase.template.org_id == user.org_id)
+ end
+
+end
\ No newline at end of file
diff --git a/app/policies/answer_policy.rb b/app/policies/answer_policy.rb
index 805efac..1e9502c 100644
--- a/app/policies/answer_policy.rb
+++ b/app/policies/answer_policy.rb
@@ -8,9 +8,10 @@
@answer = answer
end
- def create?
- # is the plan editable by the user, and is the user_id that of the user
- @answer.plan.editable_by(@user.id) && (@answer.user_id == @user.id)
+ def update?
+ # TODO: Remove the owner check after the Roles have been updated
+ # is the plan editable by the user or the user is the owner of the plan
+ @answer.plan.editable_by?(@user.id) || @user == @answer.plan.owner
end
end
\ No newline at end of file
diff --git a/app/policies/api/v0/guidance_group_policy.rb b/app/policies/api/v0/guidance_group_policy.rb
new file mode 100644
index 0000000..1ea52f4
--- /dev/null
+++ b/app/policies/api/v0/guidance_group_policy.rb
@@ -0,0 +1,29 @@
+module Api
+ module V0
+ class GuidanceGroupPolicy < ApplicationPolicy
+ attr_reader :user, :guidance_group
+
+ def initialize(user, guidance_group)
+ raise Pundit::NotAuthorizedError, _("must be logged in") unless user
+ unless user.org.token_permission_types.include? TokenPermissionType::GUIDANCES
+ raise Pundit::NotAuthorizedError, _("must have access to guidances api")
+ end
+ @user = user
+ @guidance_group = guidance_group
+ end
+
+ ##
+ # is the plan editable by the user
+ def show?
+ GuidanceGroup.can_view?(@user, @guidance_group)
+ end
+
+ ##
+ # always allowed as index chooses which guidances to display
+ def index?
+ true
+ end
+
+ end
+ end
+end
\ No newline at end of file
diff --git a/app/policies/api/v0/guidance_policy.rb b/app/policies/api/v0/guidance_policy.rb
new file mode 100644
index 0000000..fd17c4e
--- /dev/null
+++ b/app/policies/api/v0/guidance_policy.rb
@@ -0,0 +1,29 @@
+module Api
+ module V0
+ class GuidancePolicy < ApplicationPolicy
+ attr_reader :user
+ attr_reader :guidance
+
+ def initialize(user, guidance)
+ raise Pundit::NotAuthorizedError, _("must be logged in") unless user
+ unless user.org.token_permission_types.include? TokenPermissionType::GUIDANCES
+ raise Pundit::NotAuthorizedError, _("must have access to guidances api")
+ end
+ @user = user
+ @guidance = guidance
+ end
+
+ ##
+ # is the plan editable by the user
+ def show?
+ Guidance.can_view(@user, @guidance.id)
+ end
+
+ ##
+ # always allowed as index chooses which guidances to display
+ def index?
+ true
+ end
+ end
+ end
+end
\ No newline at end of file
diff --git a/app/policies/api/v0/plans_policy.rb b/app/policies/api/v0/plans_policy.rb
new file mode 100644
index 0000000..6d0ab77
--- /dev/null
+++ b/app/policies/api/v0/plans_policy.rb
@@ -0,0 +1,23 @@
+module Api
+ module V0
+ class PlansPolicy < ApplicationPolicy
+ attr_reader :user
+ attr_reader :template
+
+ def initialize(user, template)
+ raise Pundit::NotAuthorizedError, _("must be logged in") unless user
+ unless user.org.token_permission_types.include? TokenPermissionType::PLANS
+ raise Pundit::NotAuthorizedError, _("must have access to plans api")
+ end
+ @user = user
+ @template = template
+ end
+
+ ##
+ # users can create a plan if their template exists
+ def create?
+ @template.present?
+ end
+ end
+ end
+end
\ No newline at end of file
diff --git a/app/policies/api/v0/statistics_policy.rb b/app/policies/api/v0/statistics_policy.rb
new file mode 100644
index 0000000..155a3da
--- /dev/null
+++ b/app/policies/api/v0/statistics_policy.rb
@@ -0,0 +1,41 @@
+module Api
+ module V0
+ class StatisticsPolicy < ApplicationPolicy
+ attr_reader :user
+
+ def initialize(user, statistic)
+ raise Pundit::NotAuthorizedError, _("must be logged in") unless user
+ unless user.org.token_permission_types.include? TokenPermissionType::STATISTICS
+ raise Pundit::NotAuthorizedError, _("must have access to guidances api")
+ end
+ @user = user
+ @statistic = statistic
+ end
+
+ ##
+ # always allowed to see how many users joined your org within a date range
+ def users_joined?
+ true
+ end
+
+ ##
+ # need to check if your org owns this template
+ def using_template?
+ @statistic.org_id == @user.org_id
+ end
+
+ ##
+ # always allowed to get plans by template
+ def plans_by_template?
+ true
+ end
+
+ ##
+ # always allowed to get plans
+ def plans?
+ true
+ end
+
+ end
+ end
+end
\ No newline at end of file
diff --git a/app/policies/api/v0/template_policy.rb b/app/policies/api/v0/template_policy.rb
new file mode 100644
index 0000000..7ec770b
--- /dev/null
+++ b/app/policies/api/v0/template_policy.rb
@@ -0,0 +1,23 @@
+module Api
+ module V0
+ class TemplatePolicy < ApplicationPolicy
+ attr_reader :user, :template
+
+ def initialize(user, template)
+ raise Pundit::NotAuthorizedError, _("must be logged in") unless user
+ unless user.org.token_permission_types.include? TokenPermissionType::TEMPLATES
+ raise Pundit::NotAuthorizedError, _("must have access to guidances api")
+ end
+ @user = user
+ @template = template
+ end
+
+ ##
+ # always allowed as index chooses which guidances to display
+ def index?
+ true
+ end
+
+ end
+ end
+end
\ No newline at end of file
diff --git a/app/policies/note_policy.rb b/app/policies/note_policy.rb
index 8ffe95a..88a9e11 100644
--- a/app/policies/note_policy.rb
+++ b/app/policies/note_policy.rb
@@ -13,11 +13,11 @@
end
def update?
- Plan.find(@note.plan_id).readable_by?(@user.id)
+ Plan.find(@note.answer.plan_id).readable_by?(@user.id)
end
def archive?
- Plan.find(@note.plan_id).readable_by?(@user.id)
+ Plan.find(@note.answer.plan_id).readable_by?(@user.id)
end
end
diff --git a/app/policies/phase_policy.rb b/app/policies/phase_policy.rb
new file mode 100644
index 0000000..caa0e3c
--- /dev/null
+++ b/app/policies/phase_policy.rb
@@ -0,0 +1,40 @@
+class PhasePolicy < ApplicationPolicy
+ attr_reader :user, :phase
+
+ def initialize(user, phase)
+ raise Pundit::NotAuthorizedError, "must be logged in" unless user
+ @user = user
+ @phase = phase
+ end
+
+ ##
+ # Org-admin side
+ # Users can modify phases if:
+ # - They can modify templates
+ # - The template which they are modifying belongs to their org
+
+ def admin_show?
+ user.can_modify_templates? && (phase.template.org_id == user.org_id)
+ end
+
+ def admin_preview?
+ user.can_modify_templates? && (phase.template.org_id == user.org_id)
+ end
+
+ def admin_update?
+ user.can_modify_templates? && (phase.template.org_id == user.org_id)
+ end
+
+ def admin_add?
+ user.can_modify_templates? && (phase.template.org_id == user.org_id)
+ end
+
+ def admin_create?
+ user.can_modify_templates? && (phase.template.org_id == user.org_id)
+ end
+
+ def admin_destroy?
+ user.can_modify_templates? && (phase.template.org_id == user.org_id)
+ end
+
+end
\ No newline at end of file
diff --git a/app/policies/plan_policy.rb b/app/policies/plan_policy.rb
index cb43258..aa99a2b 100644
--- a/app/policies/plan_policy.rb
+++ b/app/policies/plan_policy.rb
@@ -7,13 +7,13 @@
@user = user
@plan = plan
end
-
+
def show?
@plan.readable_by?(@user.id)
end
def edit?
- @plan.editable_by?(@user.id)
+ @plan.readable_by?(@user.id)
end
def update_guidance_choices?
@@ -28,14 +28,28 @@
@plan.readable_by?(@user.id)
end
+ def show_export?
+ @plan.readable_by?(@user.id)
+ end
+
def update?
@plan.editable_by?(@user.id)
end
+ def destroy?
+ @plan.editable_by?(@user.id)
+ end
+
def status?
@plan.readable_by?(@user.id)
end
+
+ def possible_templates?
+ @plan.id.nil?
+ end
+# TODO: These routes are no lonmger used
+=begin
def section_answers?
@plan.readable_by?(@user.id)
end
@@ -59,6 +73,7 @@
def unlock_section?
@plan.editable_by?(@user.id)
end
+=end
def answer?
@plan.readable_by?(@user.id)
diff --git a/app/policies/question_policy.rb b/app/policies/question_policy.rb
new file mode 100644
index 0000000..5ea487c
--- /dev/null
+++ b/app/policies/question_policy.rb
@@ -0,0 +1,28 @@
+class QuestionPolicy < ApplicationPolicy
+ attr_reader :user, :question
+
+ def initialize(user, question)
+ raise Pundit::NotAuthorizedError, "must be logged in" unless user
+ @user = user
+ @question = question
+ end
+
+ ##
+ # Users can modify questions if:
+ # - They can modify templates
+ # - The template which they are modifying belongs to their org
+ ##
+
+ def admin_create?
+ user.can_modify_templates? && (question.section.phase.template.org_id == user.org_id)
+ end
+
+ def admin_update?
+ user.can_modify_templates? && (question.section.phase.template.org_id == user.org_id)
+ end
+
+ def admin_destroy?
+ user.can_modify_templates? && (question.section.phase.template.org_id == user.org_id)
+ end
+
+end
\ No newline at end of file
diff --git a/app/policies/role_policy.rb b/app/policies/role_policy.rb
index 7aebf02..cf2b691 100644
--- a/app/policies/role_policy.rb
+++ b/app/policies/role_policy.rb
@@ -9,14 +9,14 @@
end
def create?
- @role.plan.administerable_by(@user.id)
+ @role.plan.administerable_by?(@user.id)
end
def update?
- @role.plan.administerable_by(@user.id)
+ @role.plan.administerable_by?(@user.id)
end
def destroy?
- @role.plan.administerable_by(@user.id)
+ @role.plan.administerable_by?(@user.id)
end
end
\ No newline at end of file
diff --git a/app/policies/section_policy.rb b/app/policies/section_policy.rb
new file mode 100644
index 0000000..6effdbe
--- /dev/null
+++ b/app/policies/section_policy.rb
@@ -0,0 +1,28 @@
+class SectionPolicy < ApplicationPolicy
+ attr_reader :user, :section
+
+ def initialize(user, section)
+ raise Pundit::NotAuthorizedError, "must be logged in" unless user
+ @user = user
+ @section = section
+ end
+
+ ##
+ # Users can modify sections if:
+ # - They can modify templates
+ # - The template which they are modifying belongs to their org
+ ##
+
+ def admin_create?
+ user.can_modify_templates? && (section.phase.template.org_id == user.org_id)
+ end
+
+ def admin_update?
+ user.can_modify_templates? && (section.phase.template.org_id == user.org_id)
+ end
+
+ def admin_destroy?
+ user.can_modify_templates? && (section.phase.template.org_id == user.org_id)
+ end
+
+end
\ No newline at end of file
diff --git a/app/policies/template_policy.rb b/app/policies/template_policy.rb
index 1fd64f5..754e622 100644
--- a/app/policies/template_policy.rb
+++ b/app/policies/template_policy.rb
@@ -7,6 +7,12 @@
@template = template
end
+ ##
+ # Users can modify templates if:
+ # - They can modify templates
+ # - The template which they are modifying belongs to their org
+ ##
+
def admin_index?
user.can_modify_templates?
end
@@ -14,6 +20,18 @@
def admin_template?
user.can_modify_templates? && (template.org_id == user.org_id)
end
+
+ def admin_customize?
+ user.can_modify_templates?
+ end
+
+ def admin_publish?
+ user.can_modify_templates? && (template.org_id == user.org_id)
+ end
+
+ def admin_unpublish?
+ user.can_modify_templates? && (template.org_id == user.org_id)
+ end
def admin_update?
user.can_modify_templates? && (template.org_id == user.org_id)
@@ -24,7 +42,7 @@
end
def admin_create?
- user.can_modify_templates? && (template.org_id == user.org_id)
+ user.can_modify_templates? && (template.org_id.nil? || (template.org_id == user.org_id))
end
def admin_destroy?
@@ -35,89 +53,10 @@
user.can_modify_templates? && (template.org_id == user.org_id)
end
- def admin_phase?
- user.can_modify_templates? && (template.org_id == user.org_id)
+ def admin_transfer_customization?
+ user.can_modify_templates?
end
- def admin_previewphase?
- user.can_modify_templates? && (template.org_id == user.org_id)
- end
-
- def admin_addphase?
- user.can_modify_templates? && (template.org_id == user.org_id)
- end
-
- def admin_createphase?
- user.can_modify_templates? && (template.org_id == user.org_id)
- end
-
- def admin_updatephase?
- user.can_modify_templates? && (template.org_id == user.org_id)
- end
-
- def admin_destroyphase?
- user.can_modify_templates? && (template.org_id == user.org_id)
- end
-
- def admin_updateversion?
- user.can_modify_templates? && (template.org_id == user.org_id)
- end
-
- def admin_cloneversion?
- user.can_modify_templates? && (template.org_id == user.org_id)
- end
-
- def admin_destroyversion?
- user.can_modify_templates? && (template.org_id == user.org_id)
- end
-
- def admin_createsection?
- user.can_modify_templates? && (template.org_id == user.org_id)
- end
-
- def admin_updatesection?
- user.can_modify_templates? && (template.org_id == user.org_id)
- end
-
- def admin_destroysection?
- user.can_modify_templates? && (template.org_id == user.org_id)
- end
-
- def admin_createquestion?
- user.can_modify_templates? && (template.org_id == user.org_id)
- end
-
- def admin_updatequestion?
- user.can_modify_templates? && (template.org_id == user.org_id)
- end
-
- def admin_destroyquestion?
- user.can_modify_templates? && (template.org_id == user.org_id)
- end
-
- def admin_createsuggestedanswer?
- user.can_modify_templates? && (template.org_id == user.org_id)
- end
-
- def admin_updatesuggestedanswer?
- user.can_modify_templates? && (template.org_id == user.org_id)
- end
-
- def admin_destroysuggestedanswer?
- user.can_modify_templates? && (template.org_id == user.org_id)
- end
-
- def admin_createguidance?
- user.can_modify_templates? && (template.org_id == user.org_id)
- end
-
- def admin_updateguidance?
- user.can_modify_templates? && (template.org_id == user.org_id)
- end
-
- def admin_destroyguidance?
- user.can_modify_templates? && (template.org_id == user.org_id)
- end
class Scope < Scope
def resolve
diff --git a/app/policies/user_identifier_policy.rb b/app/policies/user_identifier_policy.rb
new file mode 100644
index 0000000..e57f1c9
--- /dev/null
+++ b/app/policies/user_identifier_policy.rb
@@ -0,0 +1,20 @@
+class UserIdentifierPolicy < ApplicationPolicy
+ attr_reader :user_identifier
+
+ def initialize(user, users)
+ raise Pundit::NotAuthorizedError, "must be logged in" unless user
+ @user = user
+ @users = users
+ end
+
+ def destroy?
+ !user.nil?
+ end
+
+ class Scope < Scope
+ def resolve
+ scope.where(user_id: user.id)
+ end
+ end
+
+end
\ No newline at end of file
diff --git a/app/views/admin/dmptemplates/settings.html.erb b/app/views/admin/dmptemplates/settings.html.erb
deleted file mode 100644
index c955083..0000000
--- a/app/views/admin/dmptemplates/settings.html.erb
+++ /dev/null
@@ -1,38 +0,0 @@
-<% @settings.errors.full_messages.each do |error| %>
-
<%= error %>
-<% end %>
-
-<%= form_for(@settings, url: update_settings_admin_dmptemplate_path(@template), method: :put, as: 'settings[export][formatting]', html: { class: 'formtastic' }) do |f| %>
-
-
-
-
-
-<% end %>
diff --git a/app/views/administrate/application/_admin_header.html.erb b/app/views/administrate/application/_admin_header.html.erb
new file mode 100644
index 0000000..115db95
--- /dev/null
+++ b/app/views/administrate/application/_admin_header.html.erb
@@ -0,0 +1,4 @@
+
diff --git a/app/views/administrate/application/_navigation.html.erb b/app/views/administrate/application/_navigation.html.erb
new file mode 100644
index 0000000..a5cfa7a
--- /dev/null
+++ b/app/views/administrate/application/_navigation.html.erb
@@ -0,0 +1,26 @@
+<%# Hack for customisation %>
+
+<%#
+# Navigation
+
+This partial is used to display the navigation in Administrate.
+By default, the navigation contains navigation links
+for all resources in the admin dashboard,
+as defined by the routes in the `admin/` namespace
+%>
+
+
diff --git a/app/views/administrate/application/_search.html.erb b/app/views/administrate/application/_search.html.erb
new file mode 100644
index 0000000..7145011
--- /dev/null
+++ b/app/views/administrate/application/_search.html.erb
@@ -0,0 +1,21 @@
+
diff --git a/app/views/annotations/_add_annotation.html.erb b/app/views/annotations/_add_annotation.html.erb
new file mode 100644
index 0000000..8add942
--- /dev/null
+++ b/app/views/annotations/_add_annotation.html.erb
@@ -0,0 +1,32 @@
+
+
<%= _('Add Annotations') %>
+<%= form_tag admin_create_annotation_path , class: 'add_annotation_form' do %>
+
<%= _('since %{name} saved the answer below while you were editing. Please, combine your changes and then save the answer again.') % { name: user.name} %>
+
diff --git a/app/views/answers/_new_edit.html.erb b/app/views/answers/_new_edit.html.erb
new file mode 100644
index 0000000..2434033
--- /dev/null
+++ b/app/views/answers/_new_edit.html.erb
@@ -0,0 +1,101 @@
+
+<% q_format = question.question_format %>
+<%= semantic_form_for answer, :url => {controller: :answers, action: :update }, html: {method: "put", class: "roadmap-form", 'data-autosave': question.id }, remote: true do |f| %>
+
+ <% end %>
\ No newline at end of file
diff --git a/app/views/answers/_status.html.erb b/app/views/answers/_status.html.erb
new file mode 100644
index 0000000..ddf8dcf
--- /dev/null
+++ b/app/views/answers/_status.html.erb
@@ -0,0 +1,9 @@
+
+ <%= _('Saving...')%>
+ <%= _('Unsaved changes') %>
+
+ <% if answer.updated_at.blank? %>
+ <%= _('Not answered yet') %>
+ <% else %>
+ <%= _('Answered')%> <%= answer.updated_at.iso8601 %><%= _(' by')%> <%= answer.user.name %>
+ <% end %>
\ No newline at end of file
diff --git a/app/views/answers/update.js.erb b/app/views/answers/update.js.erb
new file mode 100644
index 0000000..2290a67
--- /dev/null
+++ b/app/views/answers/update.js.erb
@@ -0,0 +1,26 @@
+// partial /answers/locking
+<% if @stale_answer %>
+ $("#answer-locking-<%= @question.id%>")
+ .html("<%= escape_javascript(render partial: '/answers/locking', locals: { question: @question, answer: @stale_answer, user: @answer.user }) %>");
+<% else %>
+ $("#answer-locking-<%= @question.id%>").html("");
+<% end %>
+
+// partial /answer/new_edit
+if(tinymce)
+ tinymce.remove("#answer-text-<%= @question.id %>");
+$("#answer-form-<%= @question.id%>")
+ .html("<%= escape_javascript(render partial: '/answers/new_edit', locals: { question: @question, answer: @answer, readonly: false }) %>");
+
+// partial /answer/status
+$("#answer-status-<%= @question.id %>")
+ .html("<%= escape_javascript(render partial: '/answers/status', locals: { answer: @answer}) %>");
+if($.fn.init_answer_status)
+ $.fn.init_answer_status();
+
+// partial /plans/progress
+$(".progress").html("<%= escape_javascript(render :partial => '/plans/progress', locals: { plan: @plan }) %>");
+
+// partial /sections/progress
+$("#section-progress-<%= @section.id %>")
+ .html("<%= escape_javascript(render partial: '/sections/progress', locals: { section: @section, plan: @plan }) %>");
\ No newline at end of file
diff --git a/app/views/api/v0/guidance_groups/index.json.jbuilder b/app/views/api/v0/guidance_groups/index.json.jbuilder
index 908b19d..7a5fd3d 100644
--- a/app/views/api/v0/guidance_groups/index.json.jbuilder
+++ b/app/views/api/v0/guidance_groups/index.json.jbuilder
@@ -5,17 +5,13 @@
json.name guidance_group.name
json.id guidance_group.id
- # for each template associated with the guidance group, list the template name
- @templates = guidance_group.dmptemplates
- # if the template is empty, instead use all avalable templates
- if @templates.empty?
- @templates = Dmptemplate.all
- end
- json.templates @templates do |template|
- json.title template.title
- json.id template.id
- end
-
json.optional guidance_group.optional_subset
json.updated guidance_group.updated_at
-end
+ json.guidances guidance_group.guidances.each do |guidance|
+ json.text guidance.text
+ json.updated guidance.updated_at
+ json.themes guidance.themes.each do |theme|
+ json.title theme.title
+ end
+ end
+end
\ No newline at end of file
diff --git a/app/views/api/v0/guidance_groups/show.json.jbuilder b/app/views/api/v0/guidance_groups/show.json.jbuilder
deleted file mode 100644
index 1a412db..0000000
--- a/app/views/api/v0/guidance_groups/show.json.jbuilder
+++ /dev/null
@@ -1,25 +0,0 @@
-# builds a json response to api query for a list of guidance groups
-json.prettify!
-
-json.guidance_group do
- json.name @guidance_group.name
- json.id @guidance_group.id
-
- # for each template associated with the guidance group, list the template name
- @templates = @guidance_group.dmptemplates
- # if the template is empty, instead use all avalable templates
- if @templates.empty?
- @templates = Dmptemplate.all
- end
- json.templates @templates do |template|
- json.title template.title
- json.id template.id
- end
-
- json.guidances @guidance_group.guidances do |guidance|
- json.text guidance.text
- json.id guidance.id
- end
- json.optional @guidance_group.optional_subset
- json.updated @guidance_group.updated_at
-end
diff --git a/app/views/api/v0/guidances/index.json.jbuilder b/app/views/api/v0/guidances/index.json.jbuilder
deleted file mode 100644
index 82edd20..0000000
--- a/app/views/api/v0/guidances/index.json.jbuilder
+++ /dev/null
@@ -1,29 +0,0 @@
-# builds a json response to api querry for all guidances
-
-json.prettify!
-
-json.guidance @all_viewable_guidances do |guidance|
- json.id guidance.id
- json.text guidance.text
- json.updated_at guidance.updated_at
-
- # each guidance may be associated with many guidance groups
- @guidance_groups = guidance.guidance_groups
- json.guidance_groups @guidance_groups do |guidance_group|
- json.name guidance_group.name
- json.id guidance_group.id
-
- # for each template associated with the guidance group, list the template name
- @templates = guidance_group.dmptemplates
- # if the template is empty, instead use all avalable templates
- if @templates.empty?
- @templates = Dmptemplate.all
- end
- json.templates @templates do |template|
- json.title template.title
- end
- json.optional guidance_group.optional_subset
- json.updated guidance_group.updated_at
- end
-
-end
diff --git a/app/views/api/v0/guidances/show.json.jbuilder b/app/views/api/v0/guidances/show.json.jbuilder
deleted file mode 100644
index be04df7..0000000
--- a/app/views/api/v0/guidances/show.json.jbuilder
+++ /dev/null
@@ -1,30 +0,0 @@
-# builds a json response to api querry for a specific guidance
-
-json.prettify!
-
-json.guidance do
- json.id @guidance.id
- json.text @guidance.text
- json.updated_at @guidance.updated_at
-
- # each guidance may be associated with many guidance groups
- @guidance_groups = @guidance.guidance_groups
- unless @guidance_groups.empty?
- json.guidance_groups @guidance_groups do |guidance_group|
- json.name guidance_group.name
- json.id guidance_group.id
-
- # for each template associated with the guidance group, list the template name
- @templates = guidance_group.dmptemplates
- # if the template is empty, instead use all avalable templates
- if @templates.empty?
- @templates = Dmptemplate.all
- end
- json.templates @templates do |template|
- json.title template.title
- end
- json.optional guidance_group.optional_subset
- json.updated guidance_group.updated_at
- end
- end
-end
\ No newline at end of file
diff --git a/app/views/api/v0/plans/create.json.jbuilder b/app/views/api/v0/plans/create.json.jbuilder
index ebb8c58..0c3b359 100644
--- a/app/views/api/v0/plans/create.json.jbuilder
+++ b/app/views/api/v0/plans/create.json.jbuilder
@@ -2,14 +2,11 @@
json.prettify!
-json.project do
- json.title @project.title
+json.plan do
+ json.title @plan.title
+ json.template @plan.template.title
# TODO add after decision on user creation/identification
- #json.created_by @project.owner.email
- json.id @project.id
- json.created_at @project.created_at
-end
-
-# json.location do
-# json.link (url_for action: 'show', controller: 'project')
-# end
+ json.created_by @plan.owner.email
+ json.id @plan.id
+ json.created_at @plan.created_at
+end
\ No newline at end of file
diff --git a/app/views/api/v0/statistics/plans.json.jbuilder b/app/views/api/v0/statistics/plans.json.jbuilder
index fe85ca8..fdefac1 100644
--- a/app/views/api/v0/statistics/plans.json.jbuilder
+++ b/app/views/api/v0/statistics/plans.json.jbuilder
@@ -1,18 +1,15 @@
json.prettify!
-json.plans @org_projects.each do |plan|
+json.plans @org_plans.each do |plan|
json.id plan.id
json.grant_number plan.grant_number
- json.org_id plan.creator.org.id
+ json.title plan.title
json.template do
json.title plan.template.title
- json.id plan.template.id
- end
- json.project do
- json.title plan.title
+ json.id plan.template.dmptemplate_id
end
json.funder do
- json.name (plan.template.org.funder? ? plan.org.name : '')
+ json.name (plan.template.org.funder? ? plan.template.org.name : '')
end
json.principal_investigator do
json.name plan.principal_investigator
diff --git a/app/views/api/v0/statistics/plans_by_template.json.jbuilder b/app/views/api/v0/statistics/plans_by_template.json.jbuilder
index d8d5485..9a7efd8 100644
--- a/app/views/api/v0/statistics/plans_by_template.json.jbuilder
+++ b/app/views/api/v0/statistics/plans_by_template.json.jbuilder
@@ -1,20 +1,7 @@
json.prettify!
-templates = {}
-@org_projects.each do |plan|
- # if hash exists
- if templates[plan.template.title].blank?
- templates[plan.template.title] = {}
- templates[plan.template.title][:title] = plan.template.title
- templates[plan.template.title][:id] = plan.template.id
- templates[plan.template.title][:uses] = 1
- else
- templates[plan.template.title][:uses] += 1
- end
-end
-json.templates templates.each do |template, info|
+json.templates @templates.each do |template, info|
json.template_name info[:title]
json.template_id info[:id]
json.template_uses info[:uses]
-end
-
+end
\ No newline at end of file
diff --git a/app/views/api/v0/statistics/using_template.json.jbuilder b/app/views/api/v0/statistics/using_template.json.jbuilder
index 04a77b6..9a7efd8 100644
--- a/app/views/api/v0/statistics/using_template.json.jbuilder
+++ b/app/views/api/v0/statistics/using_template.json.jbuilder
@@ -1,3 +1,7 @@
json.prettify!
-json.plans_using_template @template_count
\ No newline at end of file
+json.templates @templates.each do |template, info|
+ json.template_name info[:title]
+ json.template_id info[:id]
+ json.template_uses info[:uses]
+end
\ No newline at end of file
diff --git a/app/views/api/v0/templates/index.json.jbuilder b/app/views/api/v0/templates/index.json.jbuilder
index 643d87d..5f9b5ff 100644
--- a/app/views/api/v0/templates/index.json.jbuilder
+++ b/app/views/api/v0/templates/index.json.jbuilder
@@ -2,11 +2,18 @@
json.prettify!
json.templates @org_templates.each do |org, templates|
- json.organisation_name org.name
- json.organisation_id org.id
- json.organisation_templates templates.each do |_, template|
- json.title template.title
- json.id template.id
- json.description template.description
- end
+ json.organisation_name org.name
+ json.organisation_id org.id
+ json.is_funder org.funder?
+ json.organisation_templates templates[:own].each do |_, template|
+ json.title template.title
+ json.id template.dmptemplate_id
+ json.description template.description
+ end
+ json.customized_templates templates[:cust].each do |_,template|
+ json.title template.title
+ json.id template.dmptemplate_id
+ json.customization_of template.customization_of
+ json.description template.description
+ 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 57596a5..c4d2f30 100644
--- a/app/views/contact_us/contacts/new.html.erb
+++ b/app/views/contact_us/contacts/new.html.erb
@@ -1,122 +1,111 @@
-
+<% javascript "contacts/new_contact.js" %>
+
- <%= raw t("contact_page.intro_text_html",
- organisation_name: Rails.configuration.branding[:organisation][:name],
- organisation_email: Rails.configuration.branding[:organisation][:email],
- organisation_url: Rails.configuration.branding[:organisation][:url],
- application_name: Rails.configuration.branding[:application][:name],
- application_url: Rails.configuration.branding[:application][:url],
- application_issue_list_url: Rails.configuration.branding[:application][:issue_list_url]) %>
- <%= raw t("contact_page.github_text_html") %>
+ <%= raw _('%{application_name} is provided by the %{organisation_name}. You can find out more about us on our website. If you would like to contact us about %{application_name}, please fill out the form below.') % {organisation_name: Rails.configuration.branding[:organisation][:name],
+ organisation_url: Rails.configuration.branding[:organisation][:url],
+ application_name: Rails.configuration.branding[:application][:name]} %>
<%= link_to _("Click here to confirm your account"), confirmation_url(@resource, :confirmation_token => @token) %> (<%= _("or copy") %> <%= confirmation_url(@resource, :confirmation_token => @token) %> <%= _("into your browser") %>).
+<% end %>
\ No newline at end of file
diff --git a/app/views/devise/mailer/invitation_instructions.html.erb b/app/views/devise/mailer/invitation_instructions.html.erb
index 7beb75d..c7235c1 100644
--- a/app/views/devise/mailer/invitation_instructions.html.erb
+++ b/app/views/devise/mailer/invitation_instructions.html.erb
@@ -1,7 +1,8 @@
-
+<% FastGettext.with_locale FastGettext.default_locale do %>
+
<%= _("Hello") %> <%= @resource.email %>,
+
<%= _("A colleague has invited you to contribute to their Data Management Plan at ") %> <%= link_to Rails.configuration.branding[:application][:name], root_url %>.
+
<%= link_to _("Click here to accept the invitation"), accept_invitation_url(@resource, :invitation_token => @token) %> (<%= _("or copy") %> <%= accept_invitation_url(@resource, :invitation_token => @token) %> <%= _("into your browser") %>).
+
<%= _("If you don't want to accept the invitation, please ignore this email.") %> <%= _("Your account won't be created until you access the link above and set your password.") %>
+
<%=_('All the best,')%> <%= _('The ')%><%= Rails.configuration.branding[:application][:name] %><%=_(' team')%>.
-
-<%= t('custom_devise.ignore_wont_be_created') %>
\ No newline at end of file
+<% end %>
diff --git a/app/views/devise/mailer/reset_password_instructions.html.erb b/app/views/devise/mailer/reset_password_instructions.html.erb
index b4c0ac6..55858c9 100644
--- a/app/views/devise/mailer/reset_password_instructions.html.erb
+++ b/app/views/devise/mailer/reset_password_instructions.html.erb
@@ -1,7 +1,13 @@
-
<%= _("Someone has requested a link to change your ") %><%= Rails.configuration.branding[:application][:name] %><%= _(" password. You can do this through the link below.") %>
-
<%= link_to 'Change my password', edit_password_url(@resource, :reset_password_token => @token) %>
+
<%= link_to _('Change my password'), edit_password_url(@resource, :reset_password_token => @token) %>
+<% end %>
\ No newline at end of file
diff --git a/app/views/devise/mailer/unlock_instructions.html.erb b/app/views/devise/mailer/unlock_instructions.html.erb
index 0346189..3787b7a 100644
--- a/app/views/devise/mailer/unlock_instructions.html.erb
+++ b/app/views/devise/mailer/unlock_instructions.html.erb
@@ -1,7 +1,9 @@
-
<%= _("Your") %> <%= link_to Rails.configuration.branding[:application][:name], root_url %> <%= _("account has been locked due to an excessive number of unsuccessful sign in attempts.") %>
-
<%= t('custom_devise.click_to_unlock') %>
+
<%= _("Click the link below to unlock your account") %>:
<%= link_to _("Unlock my account"), unlock_url(@resource, :unlock_token => @token) %>
+<% end %>
\ No newline at end of file
diff --git a/app/views/devise/registrations/_external_identifier.html.erb b/app/views/devise/registrations/_external_identifier.html.erb
index bbc8d75..226b270 100644
--- a/app/views/devise/registrations/_external_identifier.html.erb
+++ b/app/views/devise/registrations/_external_identifier.html.erb
@@ -1,27 +1,21 @@
-
); 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") %>
-
+ <%= link_to "#{_("Link account with #{scheme.description} ID")}",
+ Rails.application.routes.url_helpers.send(
+ "user_#{scheme.name.downcase}_omniauth_authorize_path"
+ ),
+ title: t("identifier_schemes.schemes.#{scheme.name}.connect_tooltip", default: "")
+ %>
<% 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") %>
+ <% if scheme.user_landing_url.nil? %>
+ <%= _("Your account has been linked to #{scheme.description}.") %>
+ <% else %>
+ <%= link_to "#{_("Your account has been linked to #{scheme.description}.")}", "#{scheme.user_landing_url}/#{id.identifier}", target: '_blank',
+ title: t("identifier_schemes.schemes.#{scheme.name}.connect_tooltip", default: "") %>
<% end %>
-
- <%= link_to image_tag('remove.png', height: '16px', width: '16px'),
+ <%= link_to ''.html_safe,
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")} %>
+ title: _("Unlink your account from #{scheme.description}. You can link again at any time."),
+ data: {confirm: _("Are you sure you want to unlink #{scheme.description} ID?")} %>
<% end %>
- <%= raw t('helpers.sign_up_shibboleth_alert_text_html')%>
+ <%= (_("%{application_name} doesn't recognise your institutional credentials - either you haven't created an account with us or you haven't linked these details to your existing account. * If you do not have an account with %{application_name}, please complete the form below. * If you have an account with %{application_name}, please Sign in so we can link your account to your institutional credentials. Once you have created and/or linked your account, you'll be able to sign in with your institutional credentials directly.") % { :application_name => Rails.configuration.branding[:application][:name] }).html_safe %>
- <%= link_to(image_tag('help_button.png'), '#', class: 'guidance_group_title_popover', rel: "popover", 'data-html' => "true", 'data-content' => t('org_admin.guidance_group.title_help_text_html')) %>
+ <%= link_to(image_tag('help_button.png'), '#', "data-toggle": "popover", rel: "popover", 'data-html' => "true", 'data-content' => _('Add an appropriate name for your guidance group. This name will be used to tell the end user where the guidance has come from. It will be appended to text identifying the theme e.g. "[guidance group name]: guidance on data sharing" so we suggest you just use the institution or department name.')) %>
-
- <% if @guidance_group.published == true then %>
-
+ <%= link_to(image_tag('help_button.png'), '#', "data-toggle": "popover", rel: "popover", 'data-html' => "true", 'data-content' => _("If the guidance is only meant for a subset of users e.g. those in a specific college or institute, check this box. Users will be able to select to display this subset guidance when answering questions in the 'create plan' wizard.")) %>
- <%= link_to( image_tag("help_button.png"), "#", class: 'guidance_group_title_popover', rel: "popover", 'data-html' => "true", 'data-content' => t("org_admin.guidance_group.title_help_text_html"))%>
+ <%= link_to( image_tag("help_button.png"), "#", "data-toggle": "popover", rel: "popover", 'data-html' => "true", 'data-content' => _('Add an appropriate name for your guidance group. This name will be used to tell the end user where the guidance has come from. It will be appended to text identifying the theme e.g. "[guidance group name]: guidance on data sharing" so we suggest you just use the institution or department name.'))%>
- <%= link_to( image_tag('help_button.png'), '#', class: 'guidance_group_subset_popover', rel: "popover", 'data-html' => "true", 'data-content' => t('org_admin.guidance_group.subset_option_help_text'))%>
+ <%= link_to( image_tag('help_button.png'), '#', "data-toggle": "popover", rel: "popover", 'data-html' => "true", 'data-content' => _("If the guidance is only meant for a subset of users e.g. those in a specific college or institute, check this box. Users will be able to select to display this subset guidance when answering questions in the 'create plan' wizard."))%>
+ <%= link_to( image_tag("help_button.png"), "#", "data-toggle": "popover", rel: "popover", "data-html" => "true", "data-content" => _('Enter your guidance here. You can include links where needed.'))%>
+
- <%= t("org_admin.guidance_group.guidance_group_list") %>
+ <%= _('Guidance group list') %>
- <%= raw t("org_admin.guidance_group.guidance_group_text_html")%>
+ <%= raw _("
First create a guidance group. This could be institution wide or a subset e.g. a particular College / School, Institute or department. When you create guidance you'll be asked to assign it to a guidance group.
- <%= raw t("org_admin.guidance.guidance_text_html")%>
+ <%= raw _('
You can write pieces of guidance to be displayed by theme (e.g. generic guidance on storage and backup that should present across the board). Writing generic guidance by theme saves you time and effort as your advice will be automatically displayed across all templates rather than having to write guidance to accompany each.
If you do have a need to provide guidance for specific funders that would not be useful to a wider audience (e.g. if you have specific instructions for applicants to BBSRC for example), you can do so by adding guidance to a specific question when you edit your template.
-<% end %>
\ No newline at end of file
+<% end %>
diff --git a/app/views/layouts/_navigation.html.erb b/app/views/layouts/_navigation.html.erb
index 5400e0d..57bfe0b 100644
--- a/app/views/layouts/_navigation.html.erb
+++ b/app/views/layouts/_navigation.html.erb
@@ -1,4 +1,3 @@
-
<%= f.text_field :contact_email, as: :string, class: 'text_field has-tooltip', data_toggle: "tooltip", title: _('The email address of an administrator at your organisation. Your users will use this address if they have questions.') %>
-
-<%end%>
diff --git a/app/views/phases/_answer_form.html.erb b/app/views/phases/_answer_form.html.erb
index 74ae43a..c95732b 100644
--- a/app/views/phases/_answer_form.html.erb
+++ b/app/views/phases/_answer_form.html.erb
@@ -2,221 +2,121 @@
**Project: DMPRoadmap
**Description: This block sets up the type of question, its guidance.
**Arguments transferred: an instance of "question"
- **Copyright: Digital Curation Centre and University of California Curation Center
+ **Copyright: Digital Curation Centre and California Digital Library
-->
Here you set the title that users will see. If you intend to have multiple phases for you DMP, this should be clear in the title and description.
")%>
+
+
+
+
+
+
+
<%= _('Title') %>
+
<%= f.text_field :title,
+ as: :string,
+ class: 'text_field has-tooltip', 'data-toggle' => "tooltip", 'title' => _('Enter a title for the phase e.g. intial DMP, full DMP... This is what users will see in the tabs when completing a plan. If you only have one phase, call it something generic e.g. Glasgow DMP') %>
+
+
+
<%= _('Order of display') %>
+
<%= f.number_field :number, in: 0..5, class: "number_field has-tooltip", 'data-toggle' => "tooltip", 'title' => _('This allows you to order the phases of your template.') %>
+ <%= link_to( image_tag('help_button.png'), '#', "data-toggle": "popover", rel: "popover", 'data-html' => "true", 'data-content' => _("Enter a basic description. This will be presented to users on the 'Admin Plan' tab, above the summary of the sections and questions which they will be asked to answer."))%>
+
+ <%= raw _('When you create a new phase for your template, a version will automatically be created. Once you complete the form below you will be provided with options to create sections and questions.')%>
+
+
+ <%= f.hidden_field :template_id, value: @template.id%>
+
+
+
<%= _('Title') %>
+
<%= f.text_field :title,
+ as: :string,
+ class: "text_field has-tooltip", "data-toggle" => "tooltip", "title" => _('Enter a title for the phase e.g. intial DMP, full DMP... This is what users will see in the tabs when completing a plan. If you only have one phase, call it something generic e.g. Glasgow DMP') %>
+
+
+
<%= _('Order of display') %>
+
<%= f.number_field :number, in: 1..5, class: "number_field has-tooltip", "data-toggle" => "tooltip", title: _('This allows you to order the phases of your template.') %>
+ <%= link_to( image_tag("help_button.png"), "#", "data-toggle": "popover", rel: "popover", "data-html" => "true", "data-content" => _("Enter a basic description. This will be presented to users on the 'Admin Plan' tab, above the summary of the sections and questions which they will be asked to answer."))%>
+
-
-
diff --git a/app/views/plans/create.js.erb b/app/views/plans/create.js.erb
new file mode 100644
index 0000000..11be185
--- /dev/null
+++ b/app/views/plans/create.js.erb
@@ -0,0 +1,16 @@
+$("#available-templates").fadeOut();
+
+<% if @templates.nil? %>
+ $(".main_page_content").prepend('
<%= raw notice %>
');
+
+<% elsif @templates.count > 1 %>
+ // Clear the existing contents of the modal and then display template combobox
+ $("#available-templates").html("<%= escape_javascript(render partial: 'available_templates') %>").fadeIn();
+
+<% else %>
+ // Only one template so fill in the id
+ $("#plan_template_id").val("<%= @templates.first.id %>");
+<% end %>
+
+// Force the submit button toggle
+$("#plan_template_id").change();
\ No newline at end of file
diff --git a/app/views/plans/edit.html.erb b/app/views/plans/edit.html.erb
index bd3de93..96cfa9c 100644
--- a/app/views/plans/edit.html.erb
+++ b/app/views/plans/edit.html.erb
@@ -8,16 +8,17 @@
<%= render :partial => "plan_title", locals: {plan: @plan} %>
+
<%=@readonly%>
<% status = @plan.status %>
<%space_used = status["space_used"].to_i
- space_title = t("helpers.plan.export.space_used", space_used: space_used, num_pages: @plan.template.settings(:export).max_pages)
+ space_title = _('approx. %{space_used}%% of available space used (max %{num_pages} pages)') % { space_used: space_used, num_pages: @plan.template.settings(:export).max_pages }
answered = %(#{status["num_answers"]}/#{status["num_questions"]})%>
-<%= render :partial => "export", locals: {plan: @plan} %>
+<%= render :partial => "export", locals: {plan: @plan, phase: @phase} %>
<% session.delete(:question_id_comments)%>
diff --git a/app/views/plans/export.docx.caracal b/app/views/plans/export.docx.caracal
deleted file mode 100644
index e6b4fbb..0000000
--- a/app/views/plans/export.docx.caracal
+++ /dev/null
@@ -1,251 +0,0 @@
-#-----------------------------------------------------
-# page settings
-#-----------------------------------------------------
-
-docx.page_numbers true do
- align :center
-end
-
-docx.font do
- name 'Arial'
-end
-
-docx.p do
- size 32
-end
-
-
-#---------------------------------------------
-# Structure for docx format
-#---------------------------------------------
-
-docx.h1 @exported_plan.plan.project.title.upcase, font: 'Arial', color: '000000'
-docx.h2 @exported_plan.plan.title.upcase, font: 'Arial', color: '000000'
-
-#---- PLAN ADMIN DETAILS -----
-if @exported_plan.admin_details.present?
- docx.p
- docx.h3 'Admin Details'.upcase , italic: false, font: 'Arial', color: '000000'
- @exported_plan.admin_details.each do |field|
- value = @exported_plan.send(field)
- label = "helpers.plan.export.#{field}"
- if value.present?
- docx.p do
- text I18n.t(label), bold: true, color: '000000'
- text ': ', bold: true, color: '000000'
- text value
- end
- end
- end
-end
-
-
-#---- PLAN SECTIONS, QUESTIONS AND ANSWERS -----
-@exported_plan.sections.each do |section|
- docx.p
- docx.h3 section.title.upcase, italic: false, font: 'Arial', color: '000000'
-
- @exported_plan.questions_for_section(section.id).each do |question|
- docx.p strip_tags(question.text.gsub(/
/, ' * ')), bold: true
-
- answer = @exported_plan.plan.answer(question.id, false)
- if answer.nil?
- docx.p 'Question not answered', italic: true
- else
- q_format = question.question_format
- if q_format.title == I18n.t("helpers.checkbox") || q_format.title == I18n.t("helpers.multi_select_box") ||
- q_format.title == I18n.t("helpers.radio_buttons") || q_format.title == I18n.t("helpers.dropdown") then
- answer.options.each do |option|
- docx.ul do
- if !option.text.nil?
- li option.text
- end
- end
- end
- end
-
- if !answer.text.nil? && question.option_comment_display == true then
- search_answer = Nokogiri::HTML::DocumentFragment.parse "
"
- search_answer.at(".//div").inner_html = answer.text
-
- if search_answer.css('table').present? then
- table_content = search_answer.css('table').css('tbody')
-
- if table_content.size > 0 then
- table_array = Array.new
-
- table_content.css('tr').each do |tr|
- row_th_array = Array.new
- row_td_array = Array.new
-
- if tr.search('th') then
- tr.search('th').each do |cell|
- row_th_array << cell.text.to_s
- end
- end
-
- if tr.search('td') then
- tr.search('td').each do |td_cell|
- if !td_cell.text.to_s.blank? then
- new_val = Nokogiri::HTML::DocumentFragment.parse "
"
- new_val.at(".//p").inner_html = td_cell
- td_tags = new_val.at_css('td').children.map {|x| x.name.strip}
- td_text = new_val.at_css('td').children.map {|x| x.text.strip}
-
- start_c = 0
- end_c = td_tags.size
-
- c1 = Caracal::Core::Models::TableCellModel.new do
- while start_c < end_c do
- p do
- #-- TEXT
- if td_tags[start_c] == 'text' then
- text td_text[start_c]
- else
- #-- LINK
- if td_tags[start_c] == 'a' then
- l_address = ""
- l_text = td_text[start_c]
- #-- GET HREF
- td_cell.search('a').each do |link|
- if link.content == td_text[start_c] then
- l_address = link["href"]
- end
- end
- link td_text[start_c], l_address
- #-- BOLD TEXT
- else
- if td_tags[start_c] == 'strong' && td_text[start_c] != "" then
- text td_text[start_c], bold: true
- text ' '
- #-- ITALIC TEXT
- else
- if td_tags[start_c] == 'em' && td_text[start_c] != "" then
- text td_text[start_c], italic: true
- text ' '
- end
- end
- end
- end
- end
- start_c += 1
- end
- end
- row_td_array << c1
- else
- row_td_array << td_cell.text.to_s
- end
- end
- end
-
- #--- check if all cells are empty
- if row_td_array.size > 0 then
- if row_td_array.all?(&:blank?) then
- row_td_array = []
- end
- end
-
- if !row_th_array.empty? then
- table_array << row_th_array
- end
- if !row_td_array.empty? then
- table_array << row_td_array
- end
-
- end
-
- #--- build the table layout
- docx.table table_array, border_size: 4 do
- cell_style rows[0], bold: true, background: 'fbb400'
- cell_style cells, size: 18, margins: { top: 100, bottom: 0, left: 100, right: 100 }
- end
-
- end
-
- else
- higher_level = search_answer.search('div.container').children.map {|x| x.name.strip}
- all_text = search_answer.search('div.container').children.map {|x| x.inner_html.strip}
- high_count = 0
- high_end_count = higher_level.size
-
- while high_count < high_end_count do
-
- if higher_level[high_count] == 'p' then
- inner_txt_with_tags = Nokogiri::HTML::DocumentFragment.parse "
"
- inner_txt_with_tags.at(".//p").inner_html = all_text[high_count]
- tags_type = inner_txt_with_tags.at_css('p').children.map {|x| x.name.strip}
- inner_txt = inner_txt_with_tags.at_css('p').children.map {|x| x.text.strip}
-
- start_count = 0
- end_counter = tags_type.size
-
- docx.p do
- while start_count < end_counter do
- text_val = inner_txt[start_count].to_s
- #-- TEXT
- if tags_type[start_count] == 'text' && text_val != "" then
- text text_val
- text ' '
- #-- LINK
- else
- if tags_type[start_count] == 'a' && text_val != "" then
- l_text = text_val
- l_address = ""
- # all links
- search_answer.search('a').each do |link|
- if link.content == text_val then
- l_address = link["href"]
- end
- end
- link text_val, l_address
- #-- BOLD TEXT
- else
- if tags_type[start_count] == 'strong' && text_val != "" then
- text text_val, bold: true
- text ' '
- #-- ITALIC TEXT
- else
- if tags_type[start_count] == 'em' && text_val != "" then
- text text_val, italic: true
- text ' '
- end
- end
- end
- end
- start_count +=1
- end
- end
- #-- END OF P
- else
- if higher_level[high_count] == 'ul' then
- ul_text = search_answer.search('ul').children.map {|x| x.text.strip}
- docx.ul do
- ul_text.each do |txt|
- if !txt.blank?
- li txt
- end
- end
- end
- else
- if higher_level[high_count] == 'ol' then
- ol_text = search_answer.search('ol').children.map {|x| x.text.strip}
- docx.ol do
- ol_text.each do |txt|
- if !txt.blank?
- li txt
- end
- end
- end
- end
- end
- end
-
- high_count += 1
- end
- end
- end
- end
- #-- add a new line
- docx.p
- end
-end
diff --git a/app/views/plans/export.docx.erb b/app/views/plans/export.docx.erb
new file mode 100644
index 0000000..05f5a3c
--- /dev/null
+++ b/app/views/plans/export.docx.erb
@@ -0,0 +1,46 @@
+