diff --git a/app/controllers/super_admin/themes_controller.rb b/app/controllers/super_admin/themes_controller.rb
index f1fbc6c..0dee094 100644
--- a/app/controllers/super_admin/themes_controller.rb
+++ b/app/controllers/super_admin/themes_controller.rb
@@ -52,6 +52,18 @@
redirect_to(action: :index)
end
+ def destroy
+ authorize(Theme)
+ begin
+ Theme.find(params[:id]).destroy!
+ flash[:notice] = _('Theme destroyed successfully')
+ rescue ActiveRecord::RecordNotFound
+ flash[:alert] = _('There is no theme associated with id %{id}') % { :id => params[:id] }
+ rescue ActiveRecord::RecordNotDestroyed # Unlikely to happen since we don't have callback associated to destroy! but put for safety
+ flash[:alert] = _('The theme with id %{id} could not be destroyed') % { :id => params[:id] }
+ end
+ redirect_to(action: :index)
+ end
# Private instance methods
private
diff --git a/app/policies/theme_policy.rb b/app/policies/theme_policy.rb
index d7b7895..3767696 100644
--- a/app/policies/theme_policy.rb
+++ b/app/policies/theme_policy.rb
@@ -18,4 +18,7 @@
def update?
@user.can_super_admin?
end
+ def destroy?
+ @user.can_super_admin?
+ end
end
diff --git a/app/views/paginable/plans/_privately_visible.html.erb b/app/views/paginable/plans/_privately_visible.html.erb
index 1deafb2..326118a 100644
--- a/app/views/paginable/plans/_privately_visible.html.erb
+++ b/app/views/paginable/plans/_privately_visible.html.erb
@@ -33,8 +33,9 @@
<%= display_role(plan.roles.find_by(user: current_user)) %>
<% if plan.administerable_by?(current_user.id) then %>
- <%= form_for plan, url: set_test_plan_path(plan), html: {method: :post, id: 'update-test-plan'} do |f| %>
+ <%= form_for plan, url: set_test_plan_path(plan), html: { method: :post, class: 'set_test_plan', remote: true } do |f| %>
<%= check_box_tag(:is_test, "1", (plan.visibility === 'is_test')) %>
+ <%= f.submit(_('Update'), style: 'display:none') %>
<% end %>
<% else %>
<%= plan.visibility === 'is_test' ? _('Yes') : _('No') %>
@@ -68,8 +69,7 @@
<%= link_to _('Download'), download_plan_path(plan) %>
- <%= link_to _('Make a copy'), duplicate_plan_path(plan),
- method: :post, remote: true %>
+ <%= link_to(_('Make a copy'), duplicate_plan_path(plan), data: { method: :post }) %>
<% else %>
<%= link_to _('View'), plan_path(plan) %>
@@ -78,7 +78,7 @@
<% role = plan.roles.where(user_id: current_user.id).first %>
<% conf = (role.creator? && plan.publicly_visible?) ? _("Are you sure you wish to remove this public plan? This will remove it from the Public DMPs page but any collaborators will still be able to access it.") : _("Are you sure you wish to remove this plan? Any collaborators will still be able to access it.") %>
<%= link_to _('Remove'), deactivate_role_path(role),
- method: :put, data: {confirm: conf} %>
+ method: :put, data: { confirm: conf } %>
diff --git a/app/views/plans/_share_form.html.erb b/app/views/plans/_share_form.html.erb
index 8d5f202..0cff2c1 100644
--- a/app/views/plans/_share_form.html.erb
+++ b/app/views/plans/_share_form.html.erb
@@ -1,7 +1,7 @@
<%= _('Set plan visibility') %>
<%= _('Public or organisational visibility is intended for finished plans. You must answer at least one question to enable these options.') %>
<% allow_visibility = @plan.visibility_allowed? %>
-<%= form_for(@plan, url: visibility_plan_path, method: :post, html: { id: 'set_visibility'}) do |f| %>
+<%= form_for(@plan, url: visibility_plan_path, method: :post, html: { id: 'set_visibility', remote: true }) do |f| %>
>
+
+ <%= f.submit(_('Update'), style: 'display:none') %>
+
<% end %>
diff --git a/app/views/super_admin/themes/new_edit.html.erb b/app/views/super_admin/themes/new_edit.html.erb
index 16a3b35..ca5c4a2 100644
--- a/app/views/super_admin/themes/new_edit.html.erb
+++ b/app/views/super_admin/themes/new_edit.html.erb
@@ -16,6 +16,13 @@
<%= f.button(_('Save'), class: "btn btn-default", type: "submit") %>
+ <%= link_to(
+ _('Delete'),
+ super_admin_theme_path(theme),
+ class: 'btn btn-default',
+ rel: 'nofollow',
+ 'data-method': 'delete',
+ 'data-confirm': _("Are you sure you want to delete the theme \"%{title}\"?") %{ :title => theme.title }) if options[:method] == :PUT %>
<%= link_to(_('Cancel'), super_admin_themes_path, class: 'btn btn-default', role: 'button') %>
<% end %>
\ No newline at end of file
diff --git a/config/routes.rb b/config/routes.rb
index c66fa7d..310794e 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -287,6 +287,6 @@
end
namespace :super_admin do
- resources :themes, only: [:index, :new, :create, :edit, :update]
+ resources :themes, only: [:index, :new, :create, :edit, :update, :destroy]
end
end
diff --git a/lib/assets/javascripts/application.js b/lib/assets/javascripts/application.js
index 415992b..5730159 100644
--- a/lib/assets/javascripts/application.js
+++ b/lib/assets/javascripts/application.js
@@ -1,7 +1,6 @@
// Generic JS that is applicable across multiple pages
import './utils/paginable';
import './utils/panelHeading';
-import './utils/linkHelper';
import './utils/links';
import './utils/tabHelper';
import './utils/tableHelper';
@@ -44,5 +43,5 @@
import './views/shared/create_account_form';
import './views/shared/my_org';
import './views/shared/sign_in_form';
-import './views/themes/new_edit';
+import './views/super_admin/themes/new_edit';
import './views/users/notification_preferences';
diff --git a/lib/assets/javascripts/utils/linkHelper.js b/lib/assets/javascripts/utils/linkHelper.js
deleted file mode 100644
index 43236ce..0000000
--- a/lib/assets/javascripts/utils/linkHelper.js
+++ /dev/null
@@ -1,25 +0,0 @@
-import { isString } from './isType';
-
-$(() => {
- const restfulLinks = $('a[data-method]');
-
- restfulLinks.map((idx, el) => {
- const method = $(el).attr('data-method');
- const target = $(el).attr('href');
- const token = $('meta[name="csrf-token"]').attr('content');
-
- if (isString(method) && isString(target)) {
- const html = ``;
- $(el).append(html);
-
- $(el).click((e) => {
- e.preventDefault();
- $(e.currentTarget).find('form').submit();
- });
- }
- return true;
- });
-});
diff --git a/lib/assets/javascripts/views/plans/index.js b/lib/assets/javascripts/views/plans/index.js
index 1429bba..8e9bf88 100644
--- a/lib/assets/javascripts/views/plans/index.js
+++ b/lib/assets/javascripts/views/plans/index.js
@@ -7,37 +7,30 @@
} from '../../constants';
$(() => {
- const checkboxHandler = (el) => {
- const form = $(el).closest('form');
+ $('.set_test_plan input[type="checkbox"]').on('click, change', (e) => {
+ const form = $(e.target).closest('form');
+ form.submit();
+ });
+ $('.set_test_plan').on('ajax:success', (e, data) => {
+ const form = $(e.target);
+ if (data.code === 1 && data.msg && data.msg !== '') {
+ notifier.renderNotice(data.msg);
+ } else {
+ notifier.renderAlert(data.msg);
+ }
- $.ajax({
- method: $(form).attr('method'),
- url: $(form).attr('action'),
- data: $(form).serializeArray(),
- }).done((data) => {
- if (data.code === 1 && data.msg && data.msg !== '') {
- notifier.renderNotice(data.msg);
- } else {
- notifier.renderAlert(data.msg);
- }
-
- if ($(el).is(':checked')) {
- $(form).parent().siblings('.plan-visibility').html(PLAN_VISIBILITY_WHEN_TEST)
- .attr('title', '');
- } else {
- $(form).parent().siblings('.plan-visibility').html(PLAN_VISIBILITY_WHEN_NOT_TEST)
- .attr('title', PLAN_VISIBILITY_WHEN_NOT_TEST_TOOLTIP);
- }
- }, () => {
- // TODO adequate error handling for network error
- });
- };
-
- $("#my-plans input[type='checkbox']").on('click, change', (e) => {
- checkboxHandler(e.currentTarget);
+ if (form.find('input[type="checkbox"]').is(':checked')) {
+ form.parent().siblings('.plan-visibility').html(PLAN_VISIBILITY_WHEN_TEST)
+ .attr('title', '');
+ } else {
+ form.parent().siblings('.plan-visibility').html(PLAN_VISIBILITY_WHEN_NOT_TEST)
+ .attr('title', PLAN_VISIBILITY_WHEN_NOT_TEST_TOOLTIP);
+ }
+ });
+ $('.set_test_plan').on('ajax:error', () => {
+ // TODO adequate error handling for network error
});
});
-
// Attach the tablesorter and filter to all tables with those selectors
$(() => {
collateTable({ selector: 'table.tablesorter' });
diff --git a/lib/assets/javascripts/views/plans/share.js b/lib/assets/javascripts/views/plans/share.js
index b061775..fcc018c 100644
--- a/lib/assets/javascripts/views/plans/share.js
+++ b/lib/assets/javascripts/views/plans/share.js
@@ -6,27 +6,19 @@
// Invite Collaborators form on the Share page
ariatiseForm({ selector: '#new_role' });
- const request = (el) => {
- const form = $(el).closest('form');
- return $.ajax({
- method: $(form).attr('method'),
- url: $(form).attr('action'),
- data: $(form).serializeArray(),
- dataType: 'json',
- });
- };
-
$('#set_visibility [name="plan[visibility]"]').click((e) => {
- request(e.target).then((data) => {
- if (isObject(data) && isString(data.msg)) {
- notifier.renderNotice(data.msg);
- }
- }, (jqXHR, textStatus) => {
- if (isObject(jqXHR.responseJSON)) {
- notifier.renderAlert(jqXHR.responseJSON.msg);
- } else {
- notifier.renderAlert(textStatus);
- }
- });
+ $(e.target).closest('form').submit();
+ });
+ $('#set_visibility').on('ajax:success', (e, data) => {
+ if (isObject(data) && isString(data.msg)) {
+ notifier.renderNotice(data.msg);
+ }
+ });
+ $('#set_visibility').on('ajax:error', (e, xhr) => {
+ if (isObject(xhr.responseJSON)) {
+ notifier.renderAlert(xhr.responseJSON.msg);
+ } else {
+ notifier.renderAlert(`${xhr.statusCode} - ${xhr.statusText}`);
+ }
});
});
diff --git a/lib/assets/javascripts/views/super_admin/themes/new_edit.js b/lib/assets/javascripts/views/super_admin/themes/new_edit.js
new file mode 100644
index 0000000..d5cd530
--- /dev/null
+++ b/lib/assets/javascripts/views/super_admin/themes/new_edit.js
@@ -0,0 +1,7 @@
+import ariatiseForm from '../../../utils/ariatiseForm';
+import { Tinymce } from '../../../utils/tinymce';
+
+$(() => {
+ ariatiseForm({ selector: 'form.theme' });
+ Tinymce.init({ selector: '#theme_description' });
+});
diff --git a/lib/assets/javascripts/views/themes/new_edit.js b/lib/assets/javascripts/views/themes/new_edit.js
deleted file mode 100644
index 0ee3315..0000000
--- a/lib/assets/javascripts/views/themes/new_edit.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import ariatiseForm from '../../utils/ariatiseForm';
-import { Tinymce } from '../../utils/tinymce';
-
-$(() => {
- ariatiseForm({ selector: 'form.theme' });
- Tinymce.init({ selector: '#theme_description' });
-});
diff --git a/test/functional/super_admin/themes_controller.test.rb b/test/functional/super_admin/themes_controller.test.rb
index 815fdb4..b31559e 100644
--- a/test/functional/super_admin/themes_controller.test.rb
+++ b/test/functional/super_admin/themes_controller.test.rb
@@ -98,4 +98,20 @@
assert_response :redirect
assert_equal(_('Theme updated successfully'), flash[:notice])
end
+ test 'destroy action responds redirect when user is not super_admin' do
+ delete(super_admin_theme_path({ id: Theme.first.id }))
+ assert_response :redirect
+ end
+ test 'destroy action responds redirect when theme id does not exist' do
+ sign_in @user
+ delete(super_admin_theme_path({ id: 'foo' }))
+ assert_response :redirect
+ assert_equal(_('There is no theme associated with id %{id}') % { :id => 'foo' }, flash[:alert])
+ end
+ test 'destroy action responds redirect with flash notice' do
+ sign_in @user
+ delete(super_admin_theme_path({ id: Theme.first.id }))
+ assert_response :redirect
+ assert_equal(_('Theme destroyed successfully'), flash[:notice])
+ end
end
\ No newline at end of file