diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..38887bb --- /dev/null +++ b/.gitignore @@ -0,0 +1,30 @@ +# Ignore bundler config +/.bundle + +# Ignore all logfiles, tempfiles, public assets, +/log/*.log +/tmp +public/assets/* + +# Ignore gemfile.lock +Gemfile.lock + +# Ignore db schema.rb +#db/schema.rb + +# Ignore database configuration and token secrets +config/database.yml +config/secrets.yml + +# Ignore some of the initializers +config/initializers/recaptcha.rb +config/initializers/devise.rb +config/initializers/contact_us.rb + +# Ignore enviroments settings +config/environments/development.rb +config/environments/production.rb +config/environments/test.rb + + + diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..c8a57bf --- /dev/null +++ b/Gemfile @@ -0,0 +1,95 @@ +source 'https://rubygems.org' +# +# RAILS +# +gem 'rails', '4.0.0' + +# additional gems for rails 4 +gem 'turbolinks' +gem 'railties', '= 4.0.0' +# add these gems to help with the transition: +gem 'protected_attributes' +gem 'rails-observers' +gem 'actionpack-page_caching' +gem 'actionpack-action_caching' + +gem 'uglifier', '>= 1.3.0' + +# Gems used only for assets and not required in production environments by default. +#group :assets do + # gem 'coffee-rails' +#end +# Use SCSS for stylesheets +gem 'sass-rails' +#gem 'sass' + + +# Use SCSS for stylesheets +gem 'less-rails' +gem 'twitter-bootstrap-rails', '2.2.8' +gem 'therubyracer', '0.11.4', platforms: :ruby + +gem 'libv8' + +# To use debugger +gem 'ledermann-rails-settings' +gem 'jbuilder' +#to notify admin of errors +gem 'exception_notification' + +#to allow cloning of objects +gem 'amoeba' + +group :development do + gem 'web-console', '~>2.0' + gem "better_errors" + gem "binding_of_caller" +end + +# +# USERS +# +# devise for user authentication +gem 'devise' +gem 'devise_invitable' +gem 'omniauth' +gem 'omniauth-shibboleth' +#rolify for roles +gem 'rolify' +# Gems for repository integration +gem 'email_validator' +gem 'validate_url' + +# +# DATABASE/SERVER +# +gem 'mysql2', '~> 0.3.10' +# Use unicorn as the app server +# gem 'unicorn' +#cancan for usergroups +gem 'cancancan' + +# +# VIEWS +# +gem 'jquery-rails' +gem 'tinymce-rails' +gem 'friendly_id', '~> 5.0.1' +gem 'contact_us' +gem 'recaptcha' +gem 'turbolinks' +#implementation of forms +gem 'activeadmin', github: 'activeadmin' + +# +# EXPORTING PLANS +# +gem 'thin' +gem 'wicked_pdf' +gem 'htmltoword' +gem 'feedjira' +# WORD DOC EXPORTING +gem 'caracal' +gem 'caracal-rails' + + diff --git a/README.rdoc b/README.rdoc new file mode 100644 index 0000000..3ca4a88 --- /dev/null +++ b/README.rdoc @@ -0,0 +1,43 @@ += DMPonline v4 + +DMPonline is the DCC's data management planning tool, available at https://dmponline.dcc.ac.uk + +Development of the DMPonline by the Digital Curation Centre has been funded by JISC. JISC inspires UK colleges and universities in the innovative use of digital technologies, helping to maintain the UK's position as a global leader in education. www.jisc.ac.uk + +This is just the application code, the accompanying question data available at https://dmponline.dcc.ac.uk is not included. + +The tool has four main functions +1. To help create and maintain different versions of Data Management Plans; +2. To provide useful guidance on data management issues and how to meet research funders' requirements; +3. To export attractive and useful plans in a variety of formats; +4. To allow collaborative work when creating Data Management Plans. + +== Documentation & Support + +* You can contact us by email, dmponline@dcc.ac.uk, but we can only provide limited support for your installation + +== Bugs & Feature Requests + +* Bug Reports & Feature Requests: https://github.com/DigitalCurationCentre/DMPonline_v4/issues + +== Prerequisites + +DMPonline is a Ruby on Rails application and you will need to have Ruby 2.0.0p247 or greater installed on your server and a MySQL server v5.0 or greater. + +Further details on how to install Ruby on Rails applications are available from the Ruby on Rails site, http://rubyonrails.org + +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/ + + +== Copyright + +Copyright (c) 2013 Digital Curation Centre, University of Edinburgh. + +This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License along with this program. If not, see http://www.gnu.org/licenses. diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..04c8372 --- /dev/null +++ b/Rakefile @@ -0,0 +1,17 @@ +#!/usr/bin/env rake +# Add your own tasks in files placed in lib/tasks ending in .rake, +# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. + +require File.expand_path('../config/application', __FILE__) + +DMPonline4::Application.load_tasks + +RDoc::Task.new :rdoc do |rdoc| + rdoc.main = "README.rdoc" + + rdoc.rdoc_files.include("README.rdoc", "doc/*.rdoc", "app/**/*.rb", "lib/*.rb", "config/**/*.rb") + #change above to fit needs + + rdoc.title = "DMPonline4 Documentation" + rdoc.options << "--all" +end \ No newline at end of file diff --git a/app/admin/dashboard.rb b/app/admin/dashboard.rb new file mode 100644 index 0000000..30e55c2 --- /dev/null +++ b/app/admin/dashboard.rb @@ -0,0 +1,39 @@ +# [+Project:+] DMPonline +# [+Description:+] +# +# [+Copyright:+] Digital Curation Centre + + +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/dmptemplate.rb b/app/admin/dmptemplate.rb new file mode 100644 index 0000000..e3f39b0 --- /dev/null +++ b/app/admin/dmptemplate.rb @@ -0,0 +1,125 @@ +# [+Project:+] DMPonline +# [+Description:+] +# +# [+Created:+] 03/09/2014 +# [+Copyright:+] Digital Curation Centre + +ActiveAdmin.register Dmptemplate 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: 'Settings updated successfully' }) + else + settings.formatting = nil + @template = resource + @settings = settings + render(action: :settings) + end + end + + action_item only: %i( show edit ) do + link_to(I18n.t('helpers.settings.title'), settings_admin_dmptemplate_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_dmptemplate_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 { dmptemplate.phases.count >= 1} do + table_for dmptemplate.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 => Organisation.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/guidance.rb b/app/admin/guidance.rb new file mode 100644 index 0000000..fbcc315 --- /dev/null +++ b/app/admin/guidance.rb @@ -0,0 +1,81 @@ +# [+Project:+] DMPonline +# [+Description:+] +# +# [+Created:+] 03/09/2014 +# [+Copyright:+] Digital Curation Centre + +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 => "Selected themes", + :as => :select, + :include_blank => "All themes", + :multiple => true, + :collection => Theme.order('title').map{|the| [the.title, the.id]}, + :hint => 'Choose all themes that apply.' + 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 new file mode 100644 index 0000000..839be8a --- /dev/null +++ b/app/admin/guidance_group.rb @@ -0,0 +1,80 @@ +# [+Project:+] DMPonline +# [+Description:+] +# +# [+Created:+] 03/09/2014 +# [+Copyright:+] Digital Curation Centre + +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 => Organisation.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 => "Selected templates", + :as => :select, + :include_blank => "All Templates", + :multiple => true, + :collection => Dmptemplate.order('title').map{|the| [the.title, the.id]}, + :hint => 'Choose all templates that apply.' + end + f.actions + end + + controller do + def permitted_params + params.permit! + end + end +end diff --git a/app/admin/option.rb b/app/admin/option.rb new file mode 100644 index 0000000..c7553e8 --- /dev/null +++ b/app/admin/option.rb @@ -0,0 +1,79 @@ +# [+Project:+] DMPonline +# [+Description:+] +# +# [+Created:+] 03/09/2014 +# [+Copyright:+] Digital Curation Centre + +ActiveAdmin.register Option 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/organisation.rb b/app/admin/organisation.rb new file mode 100644 index 0000000..8b4afbc --- /dev/null +++ b/app/admin/organisation.rb @@ -0,0 +1,117 @@ +# [+Project:+] DMPonline +# [+Description:+] +# +# [+Created:+] 03/09/2014 +# [+Copyright:+] Digital Curation Centre + +ActiveAdmin.register Organisation do + permit_params :abbreviation, :banner_file_id, :description, :domain, :logo_file_id, :name, :stylesheet_file_id, :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 + 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 :description do |descr| + if !descr.description.nil? then + descr.description.html_safe + 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 :domain + row :wayfless_entity + # row I18n.t('admin.org_parent'), :parent_id do |org_parent| + # if !org_parent.parent_id.nil? then + # parent_org = Organisation.find(org_parent.parent_id) + # link_to parent_org.name, [:admin, parent_org] + # end + # end + # row :stylesheet_file_id + 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 :description + 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 :domain + f.input :wayfless_entity + # f.input :parent_id, :label => I18n.t('admin.org_parent'), :as => :select, :collection => Organisation.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/organisation_type.rb b/app/admin/organisation_type.rb new file mode 100644 index 0000000..2c9c4de --- /dev/null +++ b/app/admin/organisation_type.rb @@ -0,0 +1,55 @@ +# [+Project:+] DMPonline +# [+Description:+] +# +# [+Created:+] 03/09/2014 +# [+Copyright:+] Digital Curation Centre + +ActiveAdmin.register OrganisationType do + permit_params :organisation_id, :name + + menu :priority => 4, :label => proc{I18n.t('admin.org_type')}, :parent => "Organisations management" + + index do + column I18n.t('admin.title'), :sortable => :name do |ggn| + link_to ggn.name, [:admin, ggn] + end + column I18n.t('admin.desc'), :description do |descr| + if !descr.description.nil? then + descr.description.html_safe + end + end + + actions + end + + + #show organisation type details + show do + attributes_table do + row :name + row :description do |descr| + if !descr.description.nil? then + descr.description.html_safe + end + end + row :created_at + row :updated_at + end + end + + #organisations sidebar + sidebar I18n.t('admin.orgs'), :only => :show, :if => proc { organisation_type.organisations.count >= 1} do + table_for organisation_type.organisations.order("name") do |org_list| + column I18n.t('admin.org_title'), :sortable => :name do |ggn| + link_to ggn.name, [:admin, ggn] + end + end + end + + controller do + def permitted_params + params.permit! + end + end + +end diff --git a/app/admin/phase.rb b/app/admin/phase.rb new file mode 100644 index 0000000..0da6ca1 --- /dev/null +++ b/app/admin/phase.rb @@ -0,0 +1,83 @@ +# [+Project:+] DMPonline +# [+Description:+] +# +# [+Created:+] 03/09/2014 +# [+Copyright:+] Digital Curation Centre + +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/project.rb b/app/admin/project.rb new file mode 100644 index 0000000..b410c71 --- /dev/null +++ b/app/admin/project.rb @@ -0,0 +1,39 @@ +# [+Project:+] DMPonline +# [+Description:+] +# +# [+Created:+] 03/09/2014 +# [+Copyright:+] Digital Curation Centre + +ActiveAdmin.register Project do + permit_params :dmptemplate_id, :title, :organisation_id, :unit_id, :guidance_group_ids, :project_group_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 => :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 I18n.t('admin.template_title'), :sortable => :dmptemplate_id do |dmptemp| + if !dmptemp.dmptemplate.nil? then + link_to dmptemp.dmptemplate.title, [:admin, dmptemp.dmptemplate] + else + '-' + end + end + + actions + end + + + controller do + def permitted_params + params.permit! + end + end +end diff --git a/app/admin/project_group.rb b/app/admin/project_group.rb new file mode 100644 index 0000000..2ec7a0c --- /dev/null +++ b/app/admin/project_group.rb @@ -0,0 +1,9 @@ +# [+Project:+] DMPonline +# [+Description:+] +# +# [+Created:+] 03/09/2014 +# [+Copyright:+] Digital Curation Centre + +ActiveAdmin.register ProjectGroup do + menu false +end diff --git a/app/admin/question.rb b/app/admin/question.rb new file mode 100644 index 0000000..6d70ccd --- /dev/null +++ b/app/admin/question.rb @@ -0,0 +1,131 @@ +# [+Project:+] DMPonline +# [+Description:+] +# +# [+Created:+] 03/09/2014 +# [+Copyright:+] Digital Curation Centre + +ActiveAdmin.register Question do + permit_params :default_value, :dependency_id, :dependency_text, :guidance, :number, :parent_id, :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 :guidance do |qguidance| + # if !qguidance.guidance.nil? then + # qguidance.guidance.html_safe + # end + #end + #row :parent_id do |qparent| + # if !qparent.parent_id.nil? then + # parent_q = Question.where('id = ?', qparent.parent_id) + # link_to parent_q.text, [:admin, parent_q] + # end + #end + #row :dependency_id do |qdepend| + # if !qdepend.dependency_id.nil? then + # qdep = Question.where('id = ?', qparent.dependency_id) + # link_to qdep.text, [:admin, qdep] + # end + #end + #row :dependency_text do |dep_text| + # if !dep_text.dependency_text.nil? then + # dep_text.dependency_text.html_safe + # end + #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 + # f.input :guidance + # f.input :parent_id, :label => "Parent", + # :as => :select, + # :collection => Question.find(:all, :order => 'text ASC').map{|que|[que.text, que.id]} + #f.input :dependency_id, :label => "Dependency question", + # :as => :select, + # :collection => Question.find(:all, :order => 'text ASC').map{|que|[que.text, que.id]} + # f.input :dependency_text + + end + f.inputs "Question Format" do + f.input :question_format_id, :label => "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 => "Selected themes", + :as => :select, + :multiple => true, + :include_blank => "None", + :collection => Theme.order('title').map{|the| [the.title, the.id]} , + :hint => 'Choose all themes that apply.' + + 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 new file mode 100644 index 0000000..14bb8eb --- /dev/null +++ b/app/admin/question_format.rb @@ -0,0 +1,39 @@ +# [+Project:+] DMPonline +# [+Description:+] +# +# [+Created:+] 03/09/2014 +# [+Copyright:+] Digital Curation Centre + +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 new file mode 100644 index 0000000..824eb47 --- /dev/null +++ b/app/admin/role.rb @@ -0,0 +1,62 @@ +# [+Project:+] DMPonline +# [+Description:+] +# +# [+Created:+] 03/09/2014 +# [+Copyright:+] Digital Curation Centre + +ActiveAdmin.register Role do + permit_params :name, :role_in_plans + + 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 :role_in_plans + row :created_at + row :updated_at + end + + table_for( (Role.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 + f.input :role_in_plans + end + + f.actions + end + + controller do + def permitted_params + params.permit! + end + end +end diff --git a/app/admin/section.rb b/app/admin/section.rb new file mode 100644 index 0000000..9252bf8 --- /dev/null +++ b/app/admin/section.rb @@ -0,0 +1,93 @@ +# [+Project:+] DMPonline +# [+Description:+] +# +# [+Created:+] 03/09/2014 +# [+Copyright:+] Digital Curation Centre + +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 => Organisation.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 new file mode 100644 index 0000000..555044b --- /dev/null +++ b/app/admin/suggested_answer.rb @@ -0,0 +1,33 @@ +# [+Project:+] DMPonline +# [+Description:+] +# +# [+Created:+] 03/09/2014 +# [+Copyright:+] Digital Curation Centre + +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 => Organisation.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/theme.rb b/app/admin/theme.rb new file mode 100644 index 0000000..de9b562 --- /dev/null +++ b/app/admin/theme.rb @@ -0,0 +1,77 @@ +# [+Project:+] DMPonline +# [+Description:+] +# +# [+Created:+] 03/09/2014 +# [+Copyright:+] Digital Curation Centre + +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 + 'No template' + end + else + 'No phase' + end + else + 'No version' + end + else + '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/user.rb b/app/admin/user.rb new file mode 100644 index 0000000..8fd09cf --- /dev/null +++ b/app/admin/user.rb @@ -0,0 +1,124 @@ +# [+Project:+] DMPonline +# [+Description:+] +# +# [+Created:+] 03/09/2014 +# [+Copyright:+] Digital Curation Centre + +ActiveAdmin.register User do + permit_params :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 :organisations + filter :other_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 => 'organisations.name' do |org_title| + if !org_title.organisation.nil? then + if org_title.other_organisation.nil? || org_title.other_organisation == "" then + link_to org_title.organisation.name, [:admin, org_title.organisation] + else + I18n.t('helpers.org_type.org_name') + ' - ' + org_title.other_organisation + + end + 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_status'), :user_status_id do |us| + # if !us.user_status.nil? then + # link_to us.user_status.name, [:admin, us.user_status] + # end + # end + # row I18n.t('admin.user_type'), :user_type_id do |ut| + # if !ut.user_type.nil? then + # link_to ut.user_type.name, [:admin, ut.user_type] + # else + # '-' + # end + # end + 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 + + end + end + + + form do |f| + f.inputs "Details" do + f.input :firstname + f.input :surname + f.input :email + f.input :orcid_id + # f.input :shibboleth_id + f.input :organisation_id ,:label => I18n.t('admin.org_title'), + :as => :select, + :collection => Organisation.order('name').map{|orgp|[orgp.name, orgp.id]} + f.input :other_organisation + # f.input :user_status_id, :label => I18n.t('admin.user_status'), + # :as => :select, + # :collection => UserStatus.find(:all, :order => 'name ASC').map{|us|[us.name, us.id]} + # f.input :user_type_id, :label => I18n.t('admin.user_type'), + # :as => :select, + # :collection => UserType.find(:all, :order => 'name ASC').map{|ut|[ut.name, ut.id]} + f.input :role_ids, :label => "User role", + :as => :select, + :multiple => true, + :include_blank => 'None', + :collection => Role.order('name').map{|ro| [ro.name, ro.id]} + + end + + f.actions + end + + + + controller do + def scoped_collection + resource_class.includes(:organisations) # prevents N+1 queries to your database + end + + def permitted_params + params.permit! + end + + end + +end diff --git a/app/admin/user_org_role.rb b/app/admin/user_org_role.rb new file mode 100644 index 0000000..9164eda --- /dev/null +++ b/app/admin/user_org_role.rb @@ -0,0 +1,54 @@ +# [+Project:+] DMPonline +# [+Description:+] +# +# [+Created:+] 03/09/2014 +# [+Copyright:+] Digital Curation Centre + +ActiveAdmin.register UserOrgRole do + permit_params :user_id, :organisation_id, :user_role_type_id + + menu false + #:priority => 5, :label => proc{I18n.t('admin.user_org_role')}, :parent => "User management" + + index do + column I18n.t('admin.user'), :sortable => :user_id do |user_n| + if !user_n.user.nil? then + link_to user_n.user.firstname, [:admin, user_n.user] + end + end + column I18n.t('admin.org'), :sortable => :organisation_id do |org| + if !org.organisation.nil? then + link_to org.organisation.name, [:admin, org.organisation] + end + end + column I18n.t('admin.user_role_type'), :sortable => :user_role_type_id do |role| + if !role.user_role_type.nil? then + link_to role.user_role_type.name, [:admin, role.user_role_type] + end + end + + actions + end + + show do + attributes_table do + row I18n.t('admin.user'), :user_id do |user_n| + link_to user_n.user.firstname, [:admin, user_n.user] + end + row I18n.t('admin.org'), :organisation_id do |org| + link_to org.organisation.name, [:admin, org.organisation] + end + row I18n.t('admin.user_role_type'), :user_role_type_id do |role| + link_to role.user_role_type.name, [:admin, role.user_role_type] + end + row :created_at + row :updated_at + end + end + + controller do + def permitted_params + params.permit! + end + end +end diff --git a/app/admin/user_role_type.rb b/app/admin/user_role_type.rb new file mode 100644 index 0000000..4e02387 --- /dev/null +++ b/app/admin/user_role_type.rb @@ -0,0 +1,30 @@ +# [+Project:+] DMPonline +# [+Description:+] +# +# [+Created:+] 03/09/2014 +# [+Copyright:+] Digital Curation Centre + +ActiveAdmin.register UserRoleType do + permit_params :description, :name + menu false + #:priority => 5, :label => proc{I18n.t('admin.user_role_type')}, :parent => "User management" + + index do + column I18n.t('admin.title'), :sortable => :name do |user_n| + link_to user_n.name, [:admin, user_n] + end + column I18n.t('admin.desc'),:description do |descr| + if !descr.description.nil? then + descr.description.html_safe + end + end + + actions + end + + controller do + def permitted_params + params.permit! + end + end +end diff --git a/app/admin/user_status.rb b/app/admin/user_status.rb new file mode 100644 index 0000000..5cfeb45 --- /dev/null +++ b/app/admin/user_status.rb @@ -0,0 +1,31 @@ +# [+Project:+] DMPonline +# [+Description:+] +# +# [+Created:+] 03/09/2014 +# [+Copyright:+] Digital Curation Centre + +ActiveAdmin.register UserStatus do + permit_params :description, :name + + menu false + #:priority => 5, :label => proc{I18n.t('admin.user_status')}, :parent => "User management" + + index do + column I18n.t('admin.title'), :sortable => :name do |user_n| + link_to user_n.name, [:admin, user_n] + end + column I18n.t('admin.desc'),:description do |descr| + if !descr.description.nil? then + descr.description.html_safe + end + end + + actions + end + + controller do + def permitted_params + params.permit! + end + end +end diff --git a/app/admin/user_type.rb b/app/admin/user_type.rb new file mode 100644 index 0000000..9074f5e --- /dev/null +++ b/app/admin/user_type.rb @@ -0,0 +1,42 @@ +# [+Project:+] DMPonline +# [+Description:+] +# +# [+Created:+] 03/09/2014 +# [+Copyright:+] Digital Curation Centre + +ActiveAdmin.register UserType do + permit_params :description, :name + + menu false + #:priority => 5, :label => proc{I18n.t('admin.user_type')}, :parent => "User management" + + index do + column I18n.t('admin.user_type'), :sortable => :name do |user_n| + link_to user_n.name, [:admin, user_n] + end + + actions + end + + # show Template details + show do + attributes_table do + row :name + 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/version.rb b/app/admin/version.rb new file mode 100644 index 0000000..2b6a1fd --- /dev/null +++ b/app/admin/version.rb @@ -0,0 +1,86 @@ +# [+Project:+] DMPonline +# [+Description:+] +# +# [+Created:+] 03/09/2014 +# [+Copyright:+] Digital Curation Centre + +ActiveAdmin.register Version do + permit_params :description, :number, :published, :title, :phase_id + + menu :priority => 9, :label => proc{I18n.t('admin.version')}, :parent => "Templates management" + + index do + column I18n.t('admin.title'), :sortable => :title do |version_used| + if !version_used.title.nil? then + link_to version_used.title, [:admin, version_used] + end + end + column I18n.t('admin.version_numb'), :number + column :published + column I18n.t('admin.phase'), :sortable => :phase_id do |phase_title| + if !phase_title.phase_id.nil? then + link_to phase_title.phase.title, [:admin, phase_title.phase] + else + '-' + end + end + + actions + end + + #show details of a version + 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.phase'), :sortable => :phase_id do |phase_title| + if !phase_title.phase_id.nil? then + link_to phase_title.phase.title, [:admin, phase_title.phase] + end + end + row :published + row :created_at + row :updated_at + end + + end + + #sections sidebar (:organisation_id, :description, :number, :title, :version_id) + sidebar I18n.t('admin.sections'), :only => :show, :if => proc { version.sections.count >= 1} do + table_for version.sections.order("number") do |temp_phases| + column :number + column :title do |row| + link_to row.title, [:admin, row] + end + column I18n.t('admin.org_title'), :sortable => :organisation_id do |org_title| + link_to org_title.organisation.name, [:admin, org_title.organisation] + end + + end + end + + #form + form do |f| + f.inputs "Details" do + f.input :title + f.input :number + f.input :description + f.input :phase, :label => I18n.t('admin.phase_title'), + :as => :select, + :collection => Phase.order('title').map{|ph|[ph.title, ph.id]} + f.input :published + end + f.actions + end + + controller do + def permitted_params + params.permit! + end + end +end diff --git a/app/assets/fonts/GillSansLight.ttf b/app/assets/fonts/GillSansLight.ttf new file mode 100644 index 0000000..183d035 --- /dev/null +++ b/app/assets/fonts/GillSansLight.ttf Binary files differ diff --git a/app/assets/images/2013_Jisc_Logo_RGB72.png b/app/assets/images/2013_Jisc_Logo_RGB72.png new file mode 100644 index 0000000..a36df5a --- /dev/null +++ b/app/assets/images/2013_Jisc_Logo_RGB72.png Binary files differ diff --git a/app/assets/images/asc.gif b/app/assets/images/asc.gif new file mode 100644 index 0000000..2489768 --- /dev/null +++ b/app/assets/images/asc.gif Binary files differ diff --git a/app/assets/images/background.jpg b/app/assets/images/background.jpg new file mode 100644 index 0000000..b488212 --- /dev/null +++ b/app/assets/images/background.jpg Binary files differ diff --git a/app/assets/images/bg.gif b/app/assets/images/bg.gif new file mode 100644 index 0000000..4f9b5e6 --- /dev/null +++ b/app/assets/images/bg.gif Binary files differ diff --git a/app/assets/images/dcc_logo.png b/app/assets/images/dcc_logo.png new file mode 100644 index 0000000..593a7dd --- /dev/null +++ b/app/assets/images/dcc_logo.png Binary files differ diff --git a/app/assets/images/desc.gif b/app/assets/images/desc.gif new file mode 100644 index 0000000..cd31406 --- /dev/null +++ b/app/assets/images/desc.gif Binary files differ diff --git a/app/assets/images/download.png b/app/assets/images/download.png new file mode 100644 index 0000000..43839bf --- /dev/null +++ b/app/assets/images/download.png Binary files differ diff --git a/app/assets/images/favicon.ico b/app/assets/images/favicon.ico new file mode 100644 index 0000000..4ddb00d --- /dev/null +++ b/app/assets/images/favicon.ico Binary files differ diff --git a/app/assets/images/fullscreen.png b/app/assets/images/fullscreen.png new file mode 100644 index 0000000..6181e71 --- /dev/null +++ b/app/assets/images/fullscreen.png Binary files differ diff --git a/app/assets/images/glyphicons-halflings-white.png b/app/assets/images/glyphicons-halflings-white.png new file mode 100644 index 0000000..3bf6484 --- /dev/null +++ b/app/assets/images/glyphicons-halflings-white.png Binary files differ diff --git a/app/assets/images/glyphicons-halflings.png b/app/assets/images/glyphicons-halflings.png new file mode 100644 index 0000000..a996999 --- /dev/null +++ b/app/assets/images/glyphicons-halflings.png Binary files differ diff --git a/app/assets/images/help_button.png b/app/assets/images/help_button.png new file mode 100644 index 0000000..b75449d --- /dev/null +++ b/app/assets/images/help_button.png Binary files differ diff --git a/app/assets/images/lancaster_logo.png b/app/assets/images/lancaster_logo.png new file mode 100644 index 0000000..5707755 --- /dev/null +++ b/app/assets/images/lancaster_logo.png Binary files differ diff --git a/app/assets/images/logo.jpg b/app/assets/images/logo.jpg new file mode 100644 index 0000000..58be19e --- /dev/null +++ b/app/assets/images/logo.jpg Binary files differ diff --git a/app/assets/images/lse-library_logo.png b/app/assets/images/lse-library_logo.png new file mode 100644 index 0000000..a9c1a9e --- /dev/null +++ b/app/assets/images/lse-library_logo.png Binary files differ diff --git a/app/assets/images/minus_laranja.png b/app/assets/images/minus_laranja.png new file mode 100644 index 0000000..fa46860 --- /dev/null +++ b/app/assets/images/minus_laranja.png Binary files differ diff --git a/app/assets/images/newcastle_logo.png b/app/assets/images/newcastle_logo.png new file mode 100644 index 0000000..56f755d --- /dev/null +++ b/app/assets/images/newcastle_logo.png Binary files differ diff --git a/app/assets/images/plus_laranja.png b/app/assets/images/plus_laranja.png new file mode 100644 index 0000000..742c9b2 --- /dev/null +++ b/app/assets/images/plus_laranja.png Binary files differ diff --git a/app/assets/images/question-mark.png b/app/assets/images/question-mark.png new file mode 100644 index 0000000..34e989c --- /dev/null +++ b/app/assets/images/question-mark.png Binary files differ diff --git a/app/assets/images/rails.png b/app/assets/images/rails.png new file mode 100644 index 0000000..d5edc04 --- /dev/null +++ b/app/assets/images/rails.png Binary files differ diff --git a/app/assets/images/screencast.jpg b/app/assets/images/screencast.jpg new file mode 100644 index 0000000..bdc7f0e --- /dev/null +++ b/app/assets/images/screencast.jpg Binary files differ diff --git a/app/assets/images/select2-spinner.gif b/app/assets/images/select2-spinner.gif new file mode 100644 index 0000000..5b33f7e --- /dev/null +++ b/app/assets/images/select2-spinner.gif Binary files differ diff --git a/app/assets/images/select2.png b/app/assets/images/select2.png new file mode 100644 index 0000000..1d804ff --- /dev/null +++ b/app/assets/images/select2.png Binary files differ diff --git a/app/assets/images/select2x2.png b/app/assets/images/select2x2.png new file mode 100644 index 0000000..4bdd5c9 --- /dev/null +++ b/app/assets/images/select2x2.png Binary files differ diff --git a/app/assets/images/ue_logo.png b/app/assets/images/ue_logo.png new file mode 100644 index 0000000..b0b794b --- /dev/null +++ b/app/assets/images/ue_logo.png Binary files differ diff --git a/app/assets/javascripts/active_admin.js b/app/assets/javascripts/active_admin.js new file mode 100644 index 0000000..3752dce --- /dev/null +++ b/app/assets/javascripts/active_admin.js @@ -0,0 +1 @@ +#= require active_admin/base diff --git a/app/assets/javascripts/admin.js b/app/assets/javascripts/admin.js new file mode 100644 index 0000000..51ff7d2 --- /dev/null +++ b/app/assets/javascripts/admin.js @@ -0,0 +1,474 @@ +//= require tinymce +/* +**Project: DMPonline v4 +**Description: This file include all javascript regarding admin interface +**Copyright: Digital Curation Centre +*/ + + +$( document ).ready(function() { + + if($('.in').length > 0) { + if ($('.in .current_question').length > 0) { + $(document.body).animate({ + 'scrollTop': $('.in .current_question').offset().top + }, 1000); + } + else { + $(document.body).animate({ + 'scrollTop': $('.in').offset().top + }, 1000); + } + } + + //set the tinymce popover help text + $(".template_desc_popover, .phase_desc_popover, .version_desc_popover, .section_desc_popover, .question_format_popover," + + " .default_answer_popover, .suggested_answer_popover, .question_guidance_popover, .question_themes_popover," + + " .question_options_popover, .guidance_group_title_popover, .guidance_group_template_popover," + + " .guidance_group_subset_popover, .guidance_text_popover, .guidance_apply_to_popover, .guidance_by_themes_popover," + + " .guidance_by_question_popover, .guidance_group_select_popover, .org_abbr_popover").on('click', function(e) { + e.preventDefault(); + }).popover(); + + //show or hide divs based on what the user selects from the question format. New question + $('.ques_format').on("change", function(e) { + var s_id = $(this).prev(".section_id").val(); + + var selected_format = $('#new-select-format-'+ s_id).val(); + + //text area + if (selected_format == 1){ + $("#new-options-"+ s_id).hide(); + $("#new-default-text-field-"+ s_id).hide(); + $("#new-default-text-area-"+ s_id).show(); + $("#new-default-value-field-"+ s_id).show(); + } + //text field + else if (selected_format == 2){ + $("#new-options-"+ s_id).hide(); + $("#new-default-text-field-"+ s_id).show(); + $("#new-default-value-field-"+ s_id).show(); + $("#new-default-text-area-"+ s_id).hide(); + } + //checkbox,radio button, dropdown, multi select + else if (selected_format == 3 ||selected_format == 4 || selected_format == 5 || selected_format == 6){ + $("#new-options-"+ s_id).show(); + $("#new-default-text-field-"+ s_id).hide(); + $("#new-default-text-area-"+ s_id).hide(); + $("#new-default-value-field-"+ s_id).hide(); + } + delete selected_format; + }).trigger('change'); + + + //show or hide divs based on what the user selects from the question format + $('.ques_format').on("change", function(e) { + var q_id = $(this).find('.quest_id').val(); + + var selected_format = $('#'+ q_id +'-select-format').val(); + //text area + if (selected_format == 1){ + $("#options-"+ q_id).hide(); + $("#default-text-field-"+ q_id).hide(); + $("#default-text-area-"+ q_id).show(); + $("#default-value-field-"+ q_id).show(); + } + //text field + else if (selected_format == 2){ + $("#options-"+ q_id).hide(); + $("#default-text-field-"+ q_id).show(); + $("#default-value-field-"+ q_id).show(); + $("#default-text-area-"+ q_id).hide(); + } + //checkbox,radio button, dropdown, multi select + else if (selected_format == 3 ||selected_format == 4 || selected_format == 5 || selected_format == 6){ + $("#options-"+ q_id).show(); + $("#default-text-field-"+ q_id).hide(); + $("#default-text-area-"+ q_id).hide(); + $("#default-value-field-"+ q_id).hide(); + } + delete selected_format; + delete q_id; + }).trigger('change'); + + + //Code to show/hide divs on new guidance (by themes or by question) + $('#g_options').on("change", function (){ + var g_t_q = $(this).val(); + + e_g_q_f = $("#edit_guid_ques_flag").val(); + + if (g_t_q == 1){ + $(".guindace_by_question").hide(); + $(".guindance_by_theme").show(); + } + else if (g_t_q == 2){ + $(".guindace_by_question").show(); + $(".guindance_by_theme").hide(); + //check if editing + if( e_g_q_f != 2){ + $('#phases_select').hide(); + $('#versions_select').hide(); + $('#sections_select').hide(); + $('#questions_select').hide(); + + } + } + + }).trigger('change'); + + + //filter from template to question 5 dropdowns + $('#templates_select').change(function() { + $.ajax({ + type: 'GET', + url: "update_phases", + dataType: 'script', + data: { + dmptemplate_id : $('#templates_select').val() + } + }); + $('#phases_select').show(); + $('#versions_select').hide(); + $('#sections_select').hide(); + $('#questions_select').hide(); + + }); + $('#phases_select').change(function() { + $.ajax({ + type: 'GET', + url: "update_versions", + dataType: 'script', + data: { + phase_id : $('#phases_select').val() + } + }); + $('#phases_select').show(); + $('#versions_select').show(); + $('#sections_select').hide(); + $('#questions_select').hide(); + }); + $('#versions_select').change(function() { + $.ajax({ + type: 'GET', + url: "update_sections", + dataType: 'script', + data: { + version_id : $('#versions_select').val() + } + }); + $('#phases_select').show(); + $('#versions_select').show(); + $('#sections_select').show(); + $('#questions_select').hide(); + }); + $('#sections_select').change(function() { + $.ajax({ + type: 'GET', + url: "update_questions", + dataType: 'script', + data: { + section_id : $('#sections_select').val() + } + }); + $('#phases_select').show(); + $('#versions_select').show(); + $('#sections_select').show(); + $('#questions_select').show(); + }); + + + //action for show or hide template editing display + $('#edit_template_button').click(function(){ + $('#edit_template_div').show(); + $('#show_template_div').hide(); + }); + + + //action for show or hide phase display + $('#edit_phase_button').click(function(){ + $('#edit_phase_div').show(); + $('#show_phase_div').hide(); + }); + + //action to hide the alert to edit a version + $("#edit-version-confirmed").click(function (){ + $("#version_edit_alert").modal("hide"); + }); + + //action to clone/add a version + $("#clone-version-confirmed").click(function (){ + $("#new_project").submit(); + }); + + //action for show question editing display + $('.edit_question_button').click(function(e){ + var q_id = $(this).prev(".question_id").val(); + $('#edit_question_div_'+ q_id).show(); + $('#show_question_div_'+ q_id).hide(); + e.preventDefault(); + }); + + + $(".cancel_edit_question").click(function(e){ + var q_id = $(this).prev(".question_id").val(); + $('#edit_question_div_'+ q_id).hide(); + $('#show_question_div_'+ q_id).show(); + e.preventDefault(); + }); + + //action for adding a new question + $('.add_question_button').click(function(e){ + var s_id = $(this).prev(".section_id").val(); + $('#add_question_block_div_'+ s_id).show(); + $('#add_question_button_div_'+ s_id).hide(); + e.preventDefault(); + + }); + + //if question text area is empty send alert + $('.new_question_save_button').click(function(e){ + var s_id = $(this).prev(".section_id").val(); + if ($('#new_question_text_'+ s_id).val() == ''){ + alert('Question text is empty, please enter your question.'); + return false; + } + }); + + //action for cancelling a new question + $('.cancel_add_new_question').click(function(e){ + var s_id_new = $(this).prev(".section_id_new").val(); + $('#add_question_block_div_'+ s_id_new).hide(); + $('#add_question_button_div_'+ s_id_new).show(); + e.preventDefault(); + }); + + //action for adding a new section + $('#add_section_button').click(function(e){ + $('#add_section_block_div').show(); + $('#add_section_button_div').hide(); + e.preventDefault(); + }); + + + //action for cancelling a new section + $('#cancel_add_section').click(function(e){ + $('#add_section_block_div').hide(); + $('#add_section_button_div').show(); + e.preventDefault(); + }); + + //SUGGESTED ANSWERS + //action for adding a new suggested answer + $('.add_suggested_answer_button').click(function(e){ + var q_id = $(this).prev(".question_id").val(); + + $('#add_suggested_answer_block_'+ q_id).show(); + $('#add_suggested_answer_button_'+ q_id).hide(); + e.preventDefault(); + }); + + //cancelling edit of a suggested answer + $(".cancel_edit_suggested_answer").click(function(e){ + var q_id = $(this).prev(".question_id").val(); + $('#edit_suggested_answer_div_'+ q_id).hide(); + $('#show_suggested_answer_div_'+ q_id).show(); + e.preventDefault(); + }); + + //edit a suggested answer + $('.edit_form_for_suggested_answer').click(function(e){ + var q_id = $(this).prev(".question_id").val(); + $('#edit_suggested_answer_div_'+ q_id).show(); + $('#show_suggested_answer_div_'+ q_id).hide(); + e.preventDefault(); + }); + + //GUIDANCE + //action for adding a new guidance next to the question + $('.add_guidance_button').click(function(e){ + var q_id = $(this).prev(".question_id").val(); + $('#add_guidance_block_'+ q_id).show(); + $('#add_guidance_button_'+ q_id).hide(); + e.preventDefault(); + }); + + //cancelling edit of guidance next to the question + $(".cancel_guidance_answer").click(function(e){ + var q_id = $(this).prev(".question_id").val(); + $('#edit_guidance_div_'+ q_id).hide(); + $('#show_guidance_div_'+ q_id).show(); + e.preventDefault(); + }); + + //edit guidance next to the question + $('.edit_form_for_guidance').click(function(e){ + var q_id = $(this).prev(".question_id").val(); + $('#edit_guidance_div_'+ q_id).show(); + $('#show_guidance_div_'+ q_id).hide(); + e.preventDefault(); + }); + + + //Add new guidance Alerts + $("#return_to_new_guidance").click(function(){ + $('#new_guidance_alert_dialog').modal("hide"); + }); + + + $('#new_guidance_submit').click( function(e){ + // $('#new_guidance_alert_dialog').on("hide", function(){ + + var alert_message = []; + //verify if text area is not nil + var editorContent = tinyMCE.get('guidance-text').getContent(); + if (editorContent == ''){ + alert_message.push("add guidance text"); + } + //verify dropdown with questions has a selected option if guidance for a question being used + if ($('#g_options').val() == '2') { + if ($('#questions_select').val() == '' || isNaN($('#questions_select').val())){ + alert_message.push("select a question"); + } + } + + //verify dropdown with questions has a selected option if guidance for a question being used + if ($('#g_options').val() == '1' ){ + if($('#guidance_theme_ids').val() == undefined || $('#guidance_theme_ids').val() == ''){ + alert_message.push("select at least one theme"); + } + } + //verify if guidance group is selected + if ( ($('#guidance_guidance_group_ids').val() == '') || $('#guidance_guidance_group_ids').val() == undefined ) { + alert_message.push("select a guidance group"); + } + if(alert_message.length == 0){ + //clear dropdowns before submission + $('#new_guidance_alert_dialog').modal("hide"); + + if ($('#g_options').val() == '2'){ + $('#guidance_theme_ids').val(null); + } + if($('#g_options').val() == '1'){ + $('#questions_select').val(null); + } + $('#new_guidance_form').submit(); + return false; + + } + else if (alert_message.length != 0){ + var message = ''; + $('#new_guidance_alert_dialog').on("show", function(){ + + $("#missing_fields_new_guidance").empty(); + $.each(alert_message, function(key, value){ + message += "
  • "+value+"
  • "; + }); + $("#missing_fields_new_guidance").append(message); + }); + delete message; + } + delete alert_message; + e.preventDefault(); + }); + + //edit guidance alerts + $("#return_to_edit_guidance").click(function(){ + $('#edit_guidance_alert_dialog').modal("hide"); + }); + + + $('#edit_guidance_submit').click( function(e){ + // $('#new_guidance_alert_dialog').on("hide", function(){ + + var alert_message = []; + //verify if text area is not nil + var editorContent = tinyMCE.get('guidance-text').getContent(); + if (editorContent == ''){ + alert_message.push("add guidance text"); + } + //verify dropdown with questions has a selected option if guidance for a question being used + if ($('#g_options').val() == '2') { + if ($('#questions_select').val() == '' || isNaN($('#questions_select').val())){ + alert_message.push("select a question"); + } + } + //verify dropdown with questions has a selected option if guidance for a question being used + if ($('#g_options').val() == '1' ){ + if($('#guidance_theme_ids').val() == undefined || $('#guidance_theme_ids').val() == ''){ + alert_message.push("select at least one theme"); + } + } + //verify if guidance group is selected + if ( ($('#guidance_guidance_group_ids').val() == '') || $('#guidance_guidance_group_ids').val() == undefined ) { + alert_message.push("select a guidance group"); + } + + if(alert_message.length == 0){ + //clear dropdowns before submission + $('#edit_guidance_alert_dialog').modal("hide"); + + if ($('#g_options').val() == '2'){ $('#guidance_theme_ids').val(null);} + if($('#g_options').val() == '1'){$('#questions_select').val(null);} + $('#edit_guidance_form').submit(); + return false; + } + else if (alert_message.length != 0){ + var message = ''; + $('#edit_guidance_alert_dialog').on("show", function(){ + + $("#missing_fields_edit_guidance").empty(); + $.each(alert_message, function(key, value){ + message += "
  • "+value+"
  • "; + }); + $("#missing_fields_edit_guidance").append(message); + }); + delete message; + } + delete alert_message; + e.preventDefault(); + }); + + + //Validate banner_text area for less than 165 character + $("form#edit_org_details").submit(function(){ + + if (getStats('org_banner_text').chars > 165) { + alert("Please only enter up to 165 characters, you have used "+getStats('org_banner_text').chars+". If you are entering an URL try to use something like http://tinyurl.com/ to make it smaller."); + return false; + } + + }); + + + + + }); + + +//remove option when question format is base on a choice +function remove_object(link){ + $(link).prev("input[type=hidden]").val("1"); + $(link).closest(".options_content").hide(); + +} + + +function add_object(link, association, content) { + var new_id = new Date().getTime(); + var regexp = new RegExp("new_" + association, "g") + + if (association == 'options') { + $(link).parent().children('.options_table').children('.options_tbody').children('.new_option_before').before(content.replace(regexp, new_id)); + } +} + + +// Returns text statistics for the specified editor by id +function getStats(id) { + var body = tinymce.get(id).getBody(), text = tinymce.trim(body.innerText || body.textContent); + + return { + chars: text.length + }; +} \ No newline at end of file diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js new file mode 100644 index 0000000..2dfb897 --- /dev/null +++ b/app/assets/javascripts/application.js @@ -0,0 +1,158 @@ +// This is a manifest file that'll be compiled into application.js, which will include all the files +// listed below. +// +// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, +// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path. +// +// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the +// the compiled file. +// +// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD +// GO AFTER THE REQUIRES BELOW. +// +//= require jquery +//= require jquery_ujs +//= require bootstrap +//= require v1.js +//= require select2.min.js +//= require jquery.placeholder.js +//= require turbolinks + + + +$( document ).ready(function() { + + $(function(){ + $('.dropdown-toggle').dropdown() + }); + + $('.accordion-body').on('show', function() { + var plus = $(this).parent().children(".accordion-heading").children(".accordion-toggle").children(".icon-plus").removeClass("icon-plus").addClass("icon-minus"); + }).on('hide', function(){ + var minus = $(this).parent().children(".accordion-heading").children(".accordion-toggle").children(".icon-minus").removeClass("icon-minus").addClass("icon-plus"); + }); + + //accordion home page + $('.accordion-home').on('show', function() { + var plus = $(this).parent().find(".plus-laranja").removeClass("plus-laranja").addClass("minus-laranja"); + }).on('hide', function(){ + var minus = $(this).parent().find(".minus-laranja").removeClass("minus-laranja").addClass("plus-laranja"); + }); + + //accordion project details page when project has more than 1 plan + $('.accordion-project').on('show', function() { + var plus = $(this).parent().find(".plus-laranja").removeClass("plus-laranja").addClass("minus-laranja"); + }).on('hide', function(){ + var minus = $(this).parent().find(".minus-laranja").removeClass("minus-laranja").addClass("plus-laranja"); + }); + + //$('#3-or-4-splash').modal(); + + $('.typeahead').select2({ + width: "element", + allowClear: true + }); + + $(".help").popover(); + + $('.has-tooltip').tooltip({ + placement: "right", + trigger: "focus" + }); + + $(".show-edit-toggle").click(function () { + $(".edit-project").toggle(); + $(".view-project").toggle(); + }); + + $(".toggle-existing-user-access").change(function(){ + $(this).closest("form").submit(); + }); + + $("#user_email.text_field.reg-input").blur(function () { + if (validateEmail($(this).val())) { + $(this).parent().children("div").hide(); + } + else { + $(this).parent().children("div").show(); + } + }); + + $("#user_password.text_field.reg-input").blur(function () { + if ($(this).val().length >= 8) { + $(this).parent().children("div").hide(); + } + else { + $(this).parent().children("div").show(); + } + }); + + $("#user_password_confirmation.text_field.reg-input").blur(function () { + if ($(this).val() == $("#user_password.text_field.reg-input").val()) { + $(this).parent().children("div").hide(); + } + else { + $(this).parent().children("div").show(); + } + }); + + $('#user_organisation_id').on("change", function(e) { + e.preventDefault(); + var selected_org = $(this).select2("val"); + var other_orgs = $("#other-organisation-name").attr("data-orgs").split(","); + var index = $.inArray(selected_org, other_orgs); + if (index > -1) { + $("#other-organisation-name").show(); + $("#user_other_organisation").focus(); + } + else { + $("#other-organisation-name").hide(); + } + }); + + $("#other-org-link > a").click(function(e){ + e.preventDefault(); + var other_org = $("#other-organisation-name").attr("data-orgs").split(","); + $("#user_organisation_id").select2("val", other_org); + $("#other-org-link").hide(); + $("#user_organisation_id").change(); + }); + + + //alert dialog for unlink Shibbileth account + $("#unlink-institutional-credentials-dialog").on("show", function(){ + $('.select2-choice').hide(); + }); + + $("#unlink-shibboleth-cancelled").click(function (){ + $("#unlink-institutional-credentials-dialog").modal("hide"); + $('.select2-choice').show(); + }); + + $("#unlink-shibboleth-confirmed").click(function (){ + $("#unlink_flag").val('true'); + $("#edit_user").submit(); + + }); + + + /*$('#continue-to-new').click(function(e){ + var destination = $(this).attr("href"); + var n = destination.lastIndexOf('='); + destination = decodeURIComponent(destination.substring(n + 1)); + $.post('splash_logs', {destination: destination} ); + $("#3-or-4-splash").modal('hide'); + return false; + });*/ + +}); + +function validateEmail(sEmail) { + var filter = /^[a-zA-Z0-9]+[a-zA-Z0-9_.-]+[a-zA-Z0-9_-]+@[a-zA-Z0-9]+[a-zA-Z0-9.-]+[a-zA-Z0-9]+.[a-z]{2,4}$/; + if (filter.test(sEmail)) { + return true; + } + else { + return false; + } +} diff --git a/app/assets/javascripts/bootstrap.js b/app/assets/javascripts/bootstrap.js new file mode 100644 index 0000000..643e71c --- /dev/null +++ b/app/assets/javascripts/bootstrap.js @@ -0,0 +1,2280 @@ +/* =================================================== + * bootstrap-transition.js v2.3.2 + * http://twitter.github.com/bootstrap/javascript.html#transitions + * =================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================== */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* CSS TRANSITION SUPPORT (http://www.modernizr.com/) + * ======================================================= */ + + $(function () { + + $.support.transition = (function () { + + var transitionEnd = (function () { + + var el = document.createElement('bootstrap') + , transEndEventNames = { + 'WebkitTransition' : 'webkitTransitionEnd' + , 'MozTransition' : 'transitionend' + , 'OTransition' : 'oTransitionEnd otransitionend' + , 'transition' : 'transitionend' + } + , name + + for (name in transEndEventNames){ + if (el.style[name] !== undefined) { + return transEndEventNames[name] + } + } + + }()) + + return transitionEnd && { + end: transitionEnd + } + + })() + + }) + +}(window.jQuery);/* ========================================================== + * bootstrap-alert.js v2.3.2 + * http://twitter.github.com/bootstrap/javascript.html#alerts + * ========================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================== */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* ALERT CLASS DEFINITION + * ====================== */ + + var dismiss = '[data-dismiss="alert"]' + , Alert = function (el) { + $(el).on('click', dismiss, this.close) + } + + Alert.prototype.close = function (e) { + var $this = $(this) + , selector = $this.attr('data-target') + , $parent + + if (!selector) { + selector = $this.attr('href') + selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 + } + + $parent = $(selector) + + e && e.preventDefault() + + $parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent()) + + $parent.trigger(e = $.Event('close')) + + if (e.isDefaultPrevented()) return + + $parent.removeClass('in') + + function removeElement() { + $parent + .trigger('closed') + .remove() + } + + $.support.transition && $parent.hasClass('fade') ? + $parent.on($.support.transition.end, removeElement) : + removeElement() + } + + + /* ALERT PLUGIN DEFINITION + * ======================= */ + + var old = $.fn.alert + + $.fn.alert = function (option) { + return this.each(function () { + var $this = $(this) + , data = $this.data('alert') + if (!data) $this.data('alert', (data = new Alert(this))) + if (typeof option == 'string') data[option].call($this) + }) + } + + $.fn.alert.Constructor = Alert + + + /* ALERT NO CONFLICT + * ================= */ + + $.fn.alert.noConflict = function () { + $.fn.alert = old + return this + } + + + /* ALERT DATA-API + * ============== */ + + $(document).on('click.alert.data-api', dismiss, Alert.prototype.close) + +}(window.jQuery);/* ============================================================ + * bootstrap-button.js v2.3.2 + * http://twitter.github.com/bootstrap/javascript.html#buttons + * ============================================================ + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================ */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* BUTTON PUBLIC CLASS DEFINITION + * ============================== */ + + var Button = function (element, options) { + this.$element = $(element) + this.options = $.extend({}, $.fn.button.defaults, options) + } + + Button.prototype.setState = function (state) { + var d = 'disabled' + , $el = this.$element + , data = $el.data() + , val = $el.is('input') ? 'val' : 'html' + + state = state + 'Text' + data.resetText || $el.data('resetText', $el[val]()) + + $el[val](data[state] || this.options[state]) + + // push to event loop to allow forms to submit + setTimeout(function () { + state == 'loadingText' ? + $el.addClass(d).attr(d, d) : + $el.removeClass(d).removeAttr(d) + }, 0) + } + + Button.prototype.toggle = function () { + var $parent = this.$element.closest('[data-toggle="buttons-radio"]') + + $parent && $parent + .find('.active') + .removeClass('active') + + this.$element.toggleClass('active') + } + + + /* BUTTON PLUGIN DEFINITION + * ======================== */ + + var old = $.fn.button + + $.fn.button = function (option) { + return this.each(function () { + var $this = $(this) + , data = $this.data('button') + , options = typeof option == 'object' && option + if (!data) $this.data('button', (data = new Button(this, options))) + if (option == 'toggle') data.toggle() + else if (option) data.setState(option) + }) + } + + $.fn.button.defaults = { + loadingText: 'loading...' + } + + $.fn.button.Constructor = Button + + + /* BUTTON NO CONFLICT + * ================== */ + + $.fn.button.noConflict = function () { + $.fn.button = old + return this + } + + + /* BUTTON DATA-API + * =============== */ + + $(document).on('click.button.data-api', '[data-toggle^=button]', function (e) { + var $btn = $(e.target) + if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') + $btn.button('toggle') + }) + +}(window.jQuery);/* ========================================================== + * bootstrap-carousel.js v2.3.2 + * http://twitter.github.com/bootstrap/javascript.html#carousel + * ========================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================== */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* CAROUSEL CLASS DEFINITION + * ========================= */ + + var Carousel = function (element, options) { + this.$element = $(element) + this.$indicators = this.$element.find('.carousel-indicators') + this.options = options + this.options.pause == 'hover' && this.$element + .on('mouseenter', $.proxy(this.pause, this)) + .on('mouseleave', $.proxy(this.cycle, this)) + } + + Carousel.prototype = { + + cycle: function (e) { + if (!e) this.paused = false + if (this.interval) clearInterval(this.interval); + this.options.interval + && !this.paused + && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) + return this + } + + , getActiveIndex: function () { + this.$active = this.$element.find('.item.active') + this.$items = this.$active.parent().children() + return this.$items.index(this.$active) + } + + , to: function (pos) { + var activeIndex = this.getActiveIndex() + , that = this + + if (pos > (this.$items.length - 1) || pos < 0) return + + if (this.sliding) { + return this.$element.one('slid', function () { + that.to(pos) + }) + } + + if (activeIndex == pos) { + return this.pause().cycle() + } + + return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos])) + } + + , pause: function (e) { + if (!e) this.paused = true + if (this.$element.find('.next, .prev').length && $.support.transition.end) { + this.$element.trigger($.support.transition.end) + this.cycle(true) + } + clearInterval(this.interval) + this.interval = null + return this + } + + , next: function () { + if (this.sliding) return + return this.slide('next') + } + + , prev: function () { + if (this.sliding) return + return this.slide('prev') + } + + , slide: function (type, next) { + var $active = this.$element.find('.item.active') + , $next = next || $active[type]() + , isCycling = this.interval + , direction = type == 'next' ? 'left' : 'right' + , fallback = type == 'next' ? 'first' : 'last' + , that = this + , e + + this.sliding = true + + isCycling && this.pause() + + $next = $next.length ? $next : this.$element.find('.item')[fallback]() + + e = $.Event('slide', { + relatedTarget: $next[0] + , direction: direction + }) + + if ($next.hasClass('active')) return + + if (this.$indicators.length) { + this.$indicators.find('.active').removeClass('active') + this.$element.one('slid', function () { + var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()]) + $nextIndicator && $nextIndicator.addClass('active') + }) + } + + if ($.support.transition && this.$element.hasClass('slide')) { + this.$element.trigger(e) + if (e.isDefaultPrevented()) return + $next.addClass(type) + $next[0].offsetWidth // force reflow + $active.addClass(direction) + $next.addClass(direction) + this.$element.one($.support.transition.end, function () { + $next.removeClass([type, direction].join(' ')).addClass('active') + $active.removeClass(['active', direction].join(' ')) + that.sliding = false + setTimeout(function () { that.$element.trigger('slid') }, 0) + }) + } else { + this.$element.trigger(e) + if (e.isDefaultPrevented()) return + $active.removeClass('active') + $next.addClass('active') + this.sliding = false + this.$element.trigger('slid') + } + + isCycling && this.cycle() + + return this + } + + } + + + /* CAROUSEL PLUGIN DEFINITION + * ========================== */ + + var old = $.fn.carousel + + $.fn.carousel = function (option) { + return this.each(function () { + var $this = $(this) + , data = $this.data('carousel') + , options = $.extend({}, $.fn.carousel.defaults, typeof option == 'object' && option) + , action = typeof option == 'string' ? option : options.slide + if (!data) $this.data('carousel', (data = new Carousel(this, options))) + if (typeof option == 'number') data.to(option) + else if (action) data[action]() + else if (options.interval) data.pause().cycle() + }) + } + + $.fn.carousel.defaults = { + interval: 5000 + , pause: 'hover' + } + + $.fn.carousel.Constructor = Carousel + + + /* CAROUSEL NO CONFLICT + * ==================== */ + + $.fn.carousel.noConflict = function () { + $.fn.carousel = old + return this + } + + /* CAROUSEL DATA-API + * ================= */ + + $(document).on('click.carousel.data-api', '[data-slide], [data-slide-to]', function (e) { + var $this = $(this), href + , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 + , options = $.extend({}, $target.data(), $this.data()) + , slideIndex + + $target.carousel(options) + + if (slideIndex = $this.attr('data-slide-to')) { + $target.data('carousel').pause().to(slideIndex).cycle() + } + + e.preventDefault() + }) + +}(window.jQuery);/* ============================================================= + * bootstrap-collapse.js v2.3.2 + * http://twitter.github.com/bootstrap/javascript.html#collapse + * ============================================================= + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================ */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* COLLAPSE PUBLIC CLASS DEFINITION + * ================================ */ + + var Collapse = function (element, options) { + this.$element = $(element) + this.options = $.extend({}, $.fn.collapse.defaults, options) + + if (this.options.parent) { + this.$parent = $(this.options.parent) + } + + this.options.toggle && this.toggle() + } + + Collapse.prototype = { + + constructor: Collapse + + , dimension: function () { + var hasWidth = this.$element.hasClass('width') + return hasWidth ? 'width' : 'height' + } + + , show: function () { + var dimension + , scroll + , actives + , hasData + + if (this.transitioning || this.$element.hasClass('in')) return + + dimension = this.dimension() + scroll = $.camelCase(['scroll', dimension].join('-')) + actives = this.$parent && this.$parent.find('> .accordion-group > .in') + + if (actives && actives.length) { + hasData = actives.data('collapse') + if (hasData && hasData.transitioning) return + actives.collapse('hide') + hasData || actives.data('collapse', null) + } + + this.$element[dimension](0) + this.transition('addClass', $.Event('show'), 'shown') + $.support.transition && this.$element[dimension](this.$element[0][scroll]) + } + + , hide: function () { + var dimension + if (this.transitioning || !this.$element.hasClass('in')) return + dimension = this.dimension() + this.reset(this.$element[dimension]()) + this.transition('removeClass', $.Event('hide'), 'hidden') + this.$element[dimension](0) + } + + , reset: function (size) { + var dimension = this.dimension() + + this.$element + .removeClass('collapse') + [dimension](size || 'auto') + [0].offsetWidth + + this.$element[size !== null ? 'addClass' : 'removeClass']('collapse') + + return this + } + + , transition: function (method, startEvent, completeEvent) { + var that = this + , complete = function () { + if (startEvent.type == 'show') that.reset() + that.transitioning = 0 + that.$element.trigger(completeEvent) + } + + this.$element.trigger(startEvent) + + if (startEvent.isDefaultPrevented()) return + + this.transitioning = 1 + + this.$element[method]('in') + + $.support.transition && this.$element.hasClass('collapse') ? + this.$element.one($.support.transition.end, complete) : + complete() + } + + , toggle: function () { + this[this.$element.hasClass('in') ? 'hide' : 'show']() + } + + } + + + /* COLLAPSE PLUGIN DEFINITION + * ========================== */ + + var old = $.fn.collapse + + $.fn.collapse = function (option) { + return this.each(function () { + var $this = $(this) + , data = $this.data('collapse') + , options = $.extend({}, $.fn.collapse.defaults, $this.data(), typeof option == 'object' && option) + if (!data) $this.data('collapse', (data = new Collapse(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + $.fn.collapse.defaults = { + toggle: true + } + + $.fn.collapse.Constructor = Collapse + + + /* COLLAPSE NO CONFLICT + * ==================== */ + + $.fn.collapse.noConflict = function () { + $.fn.collapse = old + return this + } + + + /* COLLAPSE DATA-API + * ================= */ + + $(document).on('click.collapse.data-api', '[data-toggle=collapse]', function (e) { + var $this = $(this), href + , target = $this.attr('data-target') + || e.preventDefault() + || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 + , option = $(target).data('collapse') ? 'toggle' : $this.data() + $this[$(target).hasClass('in') ? 'addClass' : 'removeClass']('collapsed') + $(target).collapse(option) + }) + +}(window.jQuery);/* ============================================================ + * bootstrap-dropdown.js v2.3.2 + * http://twitter.github.com/bootstrap/javascript.html#dropdowns + * ============================================================ + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================ */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* DROPDOWN CLASS DEFINITION + * ========================= */ + + var toggle = '[data-toggle=dropdown]' + , Dropdown = function (element) { + var $el = $(element).on('click.dropdown.data-api', this.toggle) + $('html').on('click.dropdown.data-api', function () { + $el.parent().removeClass('open') + }) + } + + Dropdown.prototype = { + + constructor: Dropdown + + , toggle: function (e) { + var $this = $(this) + , $parent + , isActive + + if ($this.is('.disabled, :disabled')) return + + $parent = getParent($this) + + isActive = $parent.hasClass('open') + + clearMenus() + + if (!isActive) { + if ('ontouchstart' in document.documentElement) { + // if mobile we we use a backdrop because click events don't delegate + $('