diff --git a/Gemfile b/Gemfile index f3084d8..1a3b3fb 100644 --- a/Gemfile +++ b/Gemfile @@ -134,9 +134,6 @@ # Minimal embedded v8 for Ruby (https://github.com/discourse/mini_racer) gem 'mini_racer' -# Nested forms for datasets implementation (https://github.com/nathanvda/cocoon) -gem 'cocoon' - # ------------------------------------------------ # EXPORTING # Provides binaries for WKHTMLTOPDF project in an easily accessible package. diff --git a/Gemfile.lock b/Gemfile.lock index df3d530..09d17aa 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -91,7 +91,6 @@ chromedriver-helper (2.1.0) archive-zip (~> 0.10) nokogiri (~> 1.8) - cocoon (1.2.12) coderay (1.1.2) concurrent-ruby (1.1.3) contact_us (1.2.0) @@ -494,7 +493,6 @@ capybara capybara-screenshot chromedriver-helper (>= 1.2.0) - cocoon contact_us database_cleaner devise diff --git a/app/assets/stylesheets/dmpopidor.scss b/app/assets/stylesheets/dmpopidor.scss index 249feba..ffbedca 100644 --- a/app/assets/stylesheets/dmpopidor.scss +++ b/app/assets/stylesheets/dmpopidor.scss @@ -682,10 +682,8 @@ .datasets-description { width: 50vw; - border: 0.5px groove #ddd; padding: 0 5px; margin-top: 5px; - box-shadow: 0px 0px 0px 0px #000; .dataset-element { display: flex; diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index e859d56..03a057a 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -111,12 +111,12 @@ } end - def success_message(obj, action = "saved") - _("Successfully %{action} the %{object}.") % { - object: obj_name_for_display(obj), - action: action || "save", - } - end + # def success_message(obj, action = "saved") + # _("Successfully %{action} the %{object}.") % { + # object: obj_name_for_display(obj), + # action: action || "save", + # } + # end def errors_for_display(obj) if obj.present? && obj.errors.any? @@ -125,21 +125,21 @@ end end - def obj_name_for_display(obj) - display_name = { - ExportedPlan: _("plan"), - GuidanceGroup: _("guidance group"), - Note: _("comment"), - Org: _("organisation"), - Perm: _("permission"), - Pref: _("preferences"), - User: obj == current_user ? _("profile") : _("user") - } - if obj.respond_to?(:customization_of) && obj.send(:customization_of).present? - display_name[:Template] = "customization" - end - display_name[obj.class.name.to_sym] || obj.class.name.downcase || "record" - end + # def obj_name_for_display(obj) + # display_name = { + # ExportedPlan: _("plan"), + # GuidanceGroup: _("guidance group"), + # Note: _("comment"), + # Org: _("organisation"), + # Perm: _("permission"), + # Pref: _("preferences"), + # User: obj == current_user ? _("profile") : _("user") + # } + # if obj.respond_to?(:customization_of) && obj.send(:customization_of).present? + # display_name[:Template] = "customization" + # end + # display_name[obj.class.name.to_sym] || obj.class.name.downcase || "record" + # end # Override rails default render action to look for a branded version of a # template instead of using the default one. If no override exists, the diff --git a/app/controllers/datasets_controller.rb b/app/controllers/datasets_controller.rb new file mode 100644 index 0000000..9d6bcd4 --- /dev/null +++ b/app/controllers/datasets_controller.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +class DatasetsController < ApplicationController + + after_action :verify_authorized + + # GET /plans/:plan_id/datasets + def index + begin + @plan = Plan.find(params[:plan_id]) + @datasets = @plan.datasets + + authorize @plan + render('plans/datasets', locals: { plan: @plan, datasets: @datasets }) + rescue ActiveRecord::RecordNotFound + flash[:alert] = _("There is no plan associated with id %{id}") % { + id: params[:id] + } + redirect_to(:controller => 'plans', :action => 'index') + end + end + + def destroy + @plan = Plan.find(params[:plan_id]) + @dataset = Dataset.find(params[:id]) + authorize @plan + if @dataset.destroy + flash[:notice] = success_message(@plan, _("deleted")) + redirect_to(:action => 'index') + else + flash[:alert] = failure_message(@plan, _("delete")) + redirect_to(:action => 'index') + end + end + + + +end diff --git a/app/javascript/packs/application.js b/app/javascript/packs/application.js index 12f89ea..6624b5b 100644 --- a/app/javascript/packs/application.js +++ b/app/javascript/packs/application.js @@ -1,7 +1,6 @@ // Rails setup import 'jquery-ujs'; import 'jquery-accessible-autocomplete-list-aria/jquery-accessible-autocomplete-list-aria'; -import 'cocoon-js'; // Generic JS that is applicable across multiple pages import '../utils/array'; @@ -34,6 +33,7 @@ import '../views/orgs/admin_edit'; import '../views/orgs/shibboleth_ds'; import '../views/plans/download'; +import '../views/plans/datasets'; import '../views/plans/edit_details'; import '../views/plans/index'; import '../views/plans/new'; diff --git a/app/javascript/views/plans/datasets.js b/app/javascript/views/plans/datasets.js new file mode 100644 index 0000000..5a9ffab --- /dev/null +++ b/app/javascript/views/plans/datasets.js @@ -0,0 +1,36 @@ + +$(() => { + $('#datasets').sortable({ + handle: '.dataset-actions .handle', + stop: () => { + $('#datasets .dataset-element').each(function callback(index) { + $(this).find('.dataset-order').val(index + 1); + }); + }, + }); + + $('#add-dataset').click(() => { + const lastDataset = $('#datasets .dataset-element').last(); + const lastDatasetOrder = parseInt(lastDataset.find('.dataset-order').val(), 10); + const duplicated = lastDataset.clone(false, false); + const duplicatedId = `plan_datasets_attributes_${new Date().getTime()}`; + const duplicatedName = `plan[datasets_attributes][${new Date().getTime()}]`; + + // Dataset name + duplicated.find('.dataset-name input').attr('id', `${duplicatedId}_name`); + duplicated.find('.dataset-name input').attr('name', `${duplicatedName}[name]`); + duplicated.find('.dataset-name label').attr('for', `${duplicatedId}_name`); + duplicated.find('.dataset-name input').val(null); + // Dataset description + duplicated.find('.dataset-description input').attr('id', `${duplicatedId}_description`); + duplicated.find('.dataset-description input').attr('name', `${duplicatedName}[description]`); + duplicated.find('.dataset-description label').attr('for', `${duplicatedId}_description`); + duplicated.find('.dataset-description input').val(null); + // Dataset order + duplicated.find('.dataset-order').attr('id', `${duplicatedId}_order`); + duplicated.find('.dataset-order').attr('name', `${duplicatedName}[order]`); + duplicated.find('.dataset-order').val(lastDatasetOrder + 1); + + duplicated.appendTo('#datasets'); + }); +}); diff --git a/app/javascript/views/plans/edit_details.js b/app/javascript/views/plans/edit_details.js index 55d1eca..0000d75 100644 --- a/app/javascript/views/plans/edit_details.js +++ b/app/javascript/views/plans/edit_details.js @@ -76,13 +76,4 @@ }); toggleCheckboxes($('#priority-guidance-orgs input[type="checkbox"]:checked').map((i, el) => $(el).val()).get()); - - $('#datasets').sortable({ - handle: '.dataset-actions .handle', - stop: () => { - $('#datasets .dataset-element').each(function callback(index) { - $(this).find('.dataset-order').val(index + 1); - }); - }, - }); }); diff --git a/app/policies/plan_policy.rb b/app/policies/plan_policy.rb index 09dee32..5eeb0d5 100644 --- a/app/policies/plan_policy.rb +++ b/app/policies/plan_policy.rb @@ -1,6 +1,7 @@ class PlanPolicy < ApplicationPolicy attr_reader :user attr_reader :plan + include Dmpopidor::Policies::Plan def initialize(user, plan) raise Pundit::NotAuthorizedError, _("must be logged in") unless user diff --git a/app/views/branded/plans/_dataset_fields.html.erb b/app/views/branded/plans/_dataset_fields.html.erb index 6fb2588..b14d633 100644 --- a/app/views/branded/plans/_dataset_fields.html.erb +++ b/app/views/branded/plans/_dataset_fields.html.erb @@ -1,4 +1,5 @@ -
+<%# locals: { plan, dataset } %> +
<%= f.label :name, _('Name'), class: 'control-label' %> <%= f.text_field :name, class: 'form-control', "aria-required": true %> @@ -10,10 +11,12 @@ <%= f.hidden_field :order, class: 'dataset-order' %>
- <%= link_to_remove_association f do %> - + title="<%= d_('dmpopidor', 'Move dataset') %>"> + <%= link_to plan_dataset_url(plan, dataset), + data: {:confirm => d_('dmpopidor', 'Deleting this dataset will remove the associated answers. Do you confirm ?')}, + :method => :delete do %> + <% end %>

diff --git a/app/views/branded/plans/_datasets_form.html.erb b/app/views/branded/plans/_datasets_form.html.erb index 2a7b44c..0564faf 100644 --- a/app/views/branded/plans/_datasets_form.html.erb +++ b/app/views/branded/plans/_datasets_form.html.erb @@ -1,11 +1,17 @@ -
+<%# locals: { plan, datasets } %> +
<%= d_('dmpopidor', 'Datasets') %> -
- <%= f.fields_for :datasets do |d| %> - <%= render 'dataset_fields', f: d %> - <% end %> - + + <%= f.button(_('Submit'), class: "btn btn-default", type: "submit") %> + <% end %>
\ No newline at end of file diff --git a/app/views/branded/plans/_edit_details.html.erb b/app/views/branded/plans/_edit_details.html.erb index 84d8adf..7b563f7 100644 --- a/app/views/branded/plans/_edit_details.html.erb +++ b/app/views/branded/plans/_edit_details.html.erb @@ -148,8 +148,6 @@
- <%# Datasets category %> - <%= render 'datasets_form', f: f if Dataset.table_exists? %> <%= f.button(_('Submit'), class: "btn btn-default", type: "submit") %>
diff --git a/app/views/branded/plans/_navigation.html.erb b/app/views/branded/plans/_navigation.html.erb new file mode 100644 index 0000000..021a7db --- /dev/null +++ b/app/views/branded/plans/_navigation.html.erb @@ -0,0 +1,38 @@ +<% phases = Phase.titles(plan.template.id) %> + +
+
+
+
+ <%= yield %> +
+
+
+
\ No newline at end of file diff --git a/app/views/branded/plans/datasets.html.erb b/app/views/branded/plans/datasets.html.erb new file mode 100644 index 0000000..62a9ed9 --- /dev/null +++ b/app/views/branded/plans/datasets.html.erb @@ -0,0 +1,14 @@ +<%# locals: { plan, datasets } %> +
<%= _('Beta') %>
+<% title "#{plan.title}" %> +
+
+

<%= plan.title %>

+
+
+ +
+
+ <%= render partial: 'plans/datasets_form', layout: 'plans/navigation', locals: local_assigns %> +
+
\ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index b172d9e..f523250 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -116,6 +116,7 @@ post 'set_test', constraints: {format: [:json]} get 'overview' end + resources :datasets, only: [:index, :destroy], controller: 'datasets' end resources :usage, only: [:index] diff --git a/lib/dmpopidor/controllers/application.rb b/lib/dmpopidor/controllers/application.rb index 129581f..ab52b54 100644 --- a/lib/dmpopidor/controllers/application.rb +++ b/lib/dmpopidor/controllers/application.rb @@ -5,6 +5,32 @@ def set_nav_static_pages @nav_static_pages = StaticPage.navigable end + # Added Dataset Support + def obj_name_for_display(obj) + display_name = { + Dataset: d_('dmpopidor', "dataset"), + ExportedPlan: _("plan"), + GuidanceGroup: _("guidance group"), + Note: _("comment"), + Org: _("organisation"), + Perm: _("permission"), + Pref: _("preferences"), + User: obj == current_user ? _("profile") : _("user") + } + if obj.respond_to?(:customization_of) && obj.send(:customization_of).present? + display_name[:Template] = "customization" + end + display_name[obj.class.name.to_sym] || obj.class.name.downcase || "record" + end + + + + def success_message(obj, action = "saved") + d_('dmpopidor', "Successfully %{action} the %{object}.") % { + object: obj_name_for_display(obj), + action: action || "save", + } + end end end end \ No newline at end of file diff --git a/lib/dmpopidor/controllers/plans.rb b/lib/dmpopidor/controllers/plans.rb index 3bc0124..586e335 100644 --- a/lib/dmpopidor/controllers/plans.rb +++ b/lib/dmpopidor/controllers/plans.rb @@ -126,6 +126,8 @@ end + # PUT /plans/1 + # PUT /plans/1.json # CHANGES : # Added Dataset Support def update @@ -147,7 +149,7 @@ @plan.datasets.toggle_default format.html do - redirect_to overview_plan_path(@plan), + redirect_to datasets_plan_path(@plan), notice: success_message(@plan, _("saved")) end format.json do @@ -237,6 +239,7 @@ @export_settings = @plan.settings(:export) render "download" end + end end end \ No newline at end of file diff --git a/lib/dmpopidor/policies/plan.rb b/lib/dmpopidor/policies/plan.rb new file mode 100644 index 0000000..8757818 --- /dev/null +++ b/lib/dmpopidor/policies/plan.rb @@ -0,0 +1,9 @@ +module Dmpopidor + module Policies + module Plan + def datasets? + @plan.readable_by?(@user.id) + end + end + end +end \ No newline at end of file diff --git a/package.json b/package.json index df60581..15b90f6 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,6 @@ "bootstrap": "^4.1.3", "bootstrap-sass": "^3.3.7", "chart.js": "^2.7.2", - "cocoon-js": "0.0.5", "eslint": "^5.8.0", "eslint-config-airbnb-base": "^13.1.0", "eslint-loader": "^2.1.1", diff --git a/yarn.lock b/yarn.lock index 6b214cc..99f0148 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2015,6 +2015,13 @@ dependencies: q "^1.1.2" +cocoon-js@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/cocoon-js/-/cocoon-js-0.0.5.tgz#2d269db2e3375014dbc43e4dda3bdd8d161b238b" + integrity sha512-1h51/2LDnZdyQehtIIA4eqCMSef4yFvUwXQF1XWRp12KSVLCXrvuGOsnoEm7OXviM7wgEiTf1nAkjbyws9i1EQ== + dependencies: + jquery "^3.2.1" + code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" @@ -4792,6 +4799,11 @@ resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.3.1.tgz#958ce29e81c9790f31be7792df5d4d95fc57fbca" integrity sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg== +jquery@^3.2.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.4.1.tgz#714f1f8d9dde4bdfa55764ba37ef214630d80ef2" + integrity sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw== + js-base64@^2.1.8, js-base64@^2.1.9: version "2.4.9" resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.9.tgz#748911fb04f48a60c4771b375cac45a80df11c03" @@ -4820,6 +4832,14 @@ argparse "^1.0.7" esprima "^4.0.0" +js-yaml@^3.13.1: + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + js-yaml@~3.7.0: version "3.7.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80"