diff --git a/isatemplates/templates/isatemplates/list.html b/isatemplates/templates/isatemplates/list.html index 8edd192b..0613b3bf 100644 --- a/isatemplates/templates/isatemplates/list.html +++ b/isatemplates/templates/isatemplates/list.html @@ -115,7 +115,8 @@

Export Template - {# TODO #} + Delete Template diff --git a/isatemplates/templates/isatemplates/template_confirm_delete.html b/isatemplates/templates/isatemplates/template_confirm_delete.html new file mode 100644 index 00000000..844114f7 --- /dev/null +++ b/isatemplates/templates/isatemplates/template_confirm_delete.html @@ -0,0 +1,30 @@ +{% extends 'projectroles/base.html' %} + +{% block title %}Confirm ISA-Tab Template Deletion{% endblock %} + +{% block projectroles %} + +
+

Confirm ISA-Tab Template Deletion

+
+ +
+ +
+ {% csrf_token %} +
+ + Cancel + + +
+
+
+ +{% endblock projectroles %} diff --git a/isatemplates/tests/test_permissions.py b/isatemplates/tests/test_permissions.py index e9e7b17f..eed861fc 100644 --- a/isatemplates/tests/test_permissions.py +++ b/isatemplates/tests/test_permissions.py @@ -44,3 +44,15 @@ def test_get_update(self): bad_users = [self.anonymous, self.regular_user] self.assert_response(url, good_users, 200) self.assert_response(url, bad_users, 302) + + def test_get_delete(self): + """Test ISATemplateDeleteView GET""" + template = self.make_isa_template(TEMPLATE_NAME, TEMPLATE_DESC, {}) + url = reverse( + 'isatemplates:delete', + kwargs={'cookiecutterisatemplate': template.sodar_uuid}, + ) + good_users = [self.superuser] + bad_users = [self.anonymous, self.regular_user] + self.assert_response(url, good_users, 200) + self.assert_response(url, bad_users, 302) diff --git a/isatemplates/tests/test_views.py b/isatemplates/tests/test_views.py index 3b4760f5..36a7b807 100644 --- a/isatemplates/tests/test_views.py +++ b/isatemplates/tests/test_views.py @@ -478,6 +478,7 @@ def test_post(self): self.assertEqual(self.template.description, TEMPLATE_DESC) self.assertEqual(self.template.name, TEMPLATE_NAME) self.assertEqual(self.template.json_data, {}) + self.assertEqual(self.template.active, True) for f in self._get_files(): self.assertEqual(f.content, '') self.assertEqual( @@ -488,6 +489,7 @@ def test_post(self): 'file_upload': self.get_zip(TEMPLATE_PATH, ARCHIVE_NAME), 'description': TEMPLATE_DESC_UPDATE, 'name': TEMPLATE_NAME_UPDATE, + 'active': False, } with self.login(self.user): response = self.client.post(self.url, data) @@ -498,6 +500,7 @@ def test_post(self): self.template.refresh_from_db() self.assertEqual(self.template.description, TEMPLATE_DESC_UPDATE) self.assertEqual(self.template.name, TEMPLATE_NAME_UPDATE) + self.assertEqual(self.template.active, False) with open(TEMPLATE_JSON_PATH, 'rb') as f: json_data = json.load(f) self.assertEqual(self.template.json_data, json_data) @@ -647,3 +650,49 @@ def test_post_cubi_template_exists(self): self.assertEqual(CookiecutterISAFile.objects.count(), 3) for f in self._get_files(): self.assertEqual(f.content, '') + + +class TestISATemplateDeleteView(ISATemplateViewTestBase): + """Tests for ISATemplateDeleteView""" + + def _get_files(self): + return CookiecutterISAFile.objects.filter(template=self.template) + + def setUp(self): + super().setUp() + # Set up template with empty files + self.template = self.make_isa_template( + name=TEMPLATE_NAME, + description=TEMPLATE_DESC, + json_data={}, + user=self.user, + ) + for fn in ISA_FILE_NAMES: + self.make_isa_file(template=self.template, file_name=fn, content='') + self.url = reverse( + 'isatemplates:delete', + kwargs={'cookiecutterisatemplate': self.template.sodar_uuid}, + ) + + def test_get(self): + """Test ISATemplateUpdateView GET""" + with self.login(self.user): + response = self.client.get(self.url) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.context['object'], self.template) + + def test_post(self): + """Test POST""" + self.assertEqual( + ProjectEvent.objects.filter(event_name='template_delete').count(), 0 + ) + self.assertEqual(CookiecutterISATemplate.objects.count(), 1) + self.assertEqual(CookiecutterISAFile.objects.count(), 3) + with self.login(self.user): + response = self.client.post(self.url) + self.assertEqual(response.status_code, 302) + self.assertEqual(CookiecutterISATemplate.objects.count(), 0) + self.assertEqual(CookiecutterISAFile.objects.count(), 0) + self.assertEqual( + ProjectEvent.objects.filter(event_name='template_delete').count(), 1 + ) diff --git a/isatemplates/urls.py b/isatemplates/urls.py index 889fe573..88efae77 100644 --- a/isatemplates/urls.py +++ b/isatemplates/urls.py @@ -22,4 +22,9 @@ view=views.ISATemplateUpdateView.as_view(), name='update', ), + path( + route='delete/', + view=views.ISATemplateDeleteView.as_view(), + name='delete', + ), ] diff --git a/isatemplates/views.py b/isatemplates/views.py index 7e7ee533..5f97082b 100644 --- a/isatemplates/views.py +++ b/isatemplates/views.py @@ -6,7 +6,12 @@ from django.contrib import messages from django.shortcuts import redirect from django.urls import reverse -from django.views.generic import CreateView, UpdateView, TemplateView +from django.views.generic import ( + CreateView, + UpdateView, + DeleteView, + TemplateView, +) # Projectroles dependency from projectroles.plugins import get_backend_api @@ -72,7 +77,7 @@ def handle_modify(self, obj, action): self.request, 'ISA-Tab template "{}" {}d.'.format(obj.description, action), ) - return redirect(reverse('isatemplates:list')) + return reverse('isatemplates:list') class ISATemplateCreateView( @@ -89,7 +94,7 @@ class ISATemplateCreateView( def form_valid(self, form): obj = form.save() - return self.handle_modify(obj, 'create') + return redirect(self.handle_modify(obj, 'create')) class ISATemplateUpdateView( @@ -109,4 +114,21 @@ class ISATemplateUpdateView( def form_valid(self, form): obj = form.save() - return self.handle_modify(obj, 'update') + return redirect(self.handle_modify(obj, 'update')) + + +class ISATemplateDeleteView( + LoggedInPermissionMixin, + ISATemplateModifyMixin, + DeleteView, +): + """CookiecutterISATemplate update view""" + + model = CookiecutterISATemplate + permission_required = 'isatemplates.delete_template' + slug_url_kwarg = 'cookiecutterisatemplate' + slug_field = 'sodar_uuid' + template_name = 'isatemplates/template_confirm_delete.html' + + def get_success_url(self): + return self.handle_modify(self.object, 'delete')