diff --git a/opentech/apply/activity/messaging.py b/opentech/apply/activity/messaging.py index 20e1b053a5069767c6f2a95e245574270e0697e9..bb946cacdedfccf1d6c920283be521a0ed84f005 100644 --- a/opentech/apply/activity/messaging.py +++ b/opentech/apply/activity/messaging.py @@ -51,6 +51,7 @@ neat_related = { MESSAGES.COMMENT: 'comment', MESSAGES.SCREENING: 'old_status', MESSAGES.REVIEW_OPINION: 'opinion', + MESSAGES.DELETE_REVIEW: 'review', } @@ -361,6 +362,7 @@ class SlackAdapter(AdapterBase): MESSAGES.REVIEW_OPINION: '{user} {opinion.opinion_display}s with {opinion.review.author}''s review of {submission}', MESSAGES.BATCH_READY_FOR_REVIEW: 'batch_notify_reviewers', MESSAGES.DELETE_SUBMISSION: '{user} has deleted {submission.title}', + MESSAGES.DELETE_REVIEW: '{user} has deleted {review.author} review for <{link}|{submission.title}>.', } def __init__(self): diff --git a/opentech/apply/activity/migrations/0021_add_review_delete_event.py b/opentech/apply/activity/migrations/0021_add_review_delete_event.py new file mode 100644 index 0000000000000000000000000000000000000000..d549e1cd660fd78dda514f9bef037ad5fd335f7d --- /dev/null +++ b/opentech/apply/activity/migrations/0021_add_review_delete_event.py @@ -0,0 +1,18 @@ +# Generated by Django 2.0.10 on 2019-04-18 12:00 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('activity', '0020_add_delete_event'), + ] + + operations = [ + migrations.AlterField( + model_name='event', + name='type', + field=models.CharField(choices=[('UPDATE_LEAD', 'Update Lead'), ('EDIT', 'Edit'), ('APPLICANT_EDIT', 'Applicant Edit'), ('NEW_SUBMISSION', 'New Submission'), ('SCREENING', 'Screening'), ('TRANSITION', 'Transition'), ('BATCH_TRANSITION', 'Batch Transition'), ('DETERMINATION_OUTCOME', 'Determination Outcome'), ('BATCH_DETERMINATION_OUTCOME', 'Batch Determination Outcome'), ('INVITED_TO_PROPOSAL', 'Invited To Proposal'), ('REVIEWERS_UPDATED', 'Reviewers Updated'), ('BATCH_REVIEWERS_UPDATED', 'Batch Reviewers Updated'), ('PARTNERS_UPDATED', 'Partners Updated'), ('READY_FOR_REVIEW', 'Ready For Review'), ('BATCH_READY_FOR_REVIEW', 'Batch Ready For Review'), ('NEW_REVIEW', 'New Review'), ('COMMENT', 'Comment'), ('PROPOSAL_SUBMITTED', 'Proposal Submitted'), ('OPENED_SEALED', 'Opened Sealed Submission'), ('REVIEW_OPINION', 'Review Opinion'), ('DELETE_SUBMISSION', 'Delete Submission'), ('DELETE_REVIEW', 'Delete Review')], max_length=50), + ), + ] diff --git a/opentech/apply/activity/options.py b/opentech/apply/activity/options.py index e1fddf8358183f31e0e2c60b50038e63973a972e..f99b2608911b4375365e7ccf12628cc5133ae058 100644 --- a/opentech/apply/activity/options.py +++ b/opentech/apply/activity/options.py @@ -23,6 +23,7 @@ class MESSAGES(Enum): OPENED_SEALED = 'Opened Sealed Submission' REVIEW_OPINION = 'Review Opinion' DELETE_SUBMISSION = 'Delete Submission' + DELETE_REVIEW = 'Delete Review' @classmethod def choices(cls): diff --git a/opentech/apply/funds/templates/funds/applicationsubmission_detail.html b/opentech/apply/funds/templates/funds/applicationsubmission_detail.html index f6ea15359f228af01789a6e3e8d778bd9a2a87e3..1fe5bdc008db857104a3c0c8cdc03c555533db57 100644 --- a/opentech/apply/funds/templates/funds/applicationsubmission_detail.html +++ b/opentech/apply/funds/templates/funds/applicationsubmission_detail.html @@ -68,9 +68,9 @@ <span>Submitted: <strong>{{ object.submit_time.date }} by {{ object.user.get_full_name }}</strong></span> <span>Last edited: <strong>{{ object.live_revision.timestamp.date }} by {{ object.live_revision.author }}</strong></span> {% if perms.funds.delete_applicationsubmission %} - <a class="link link--edit-submission is-active" href="{% url 'funds:submissions:delete' object.id %}"> + <a class="link link--delete-submission is-active" href="{% url 'funds:submissions:delete' object.id %}"> Delete - <svg class="icon icon--pen"><use xlink:href="#pen"></use></svg> + <svg class="icon icon--delete"><use xlink:href="#delete"></use></svg> </a> {% endif %} {% if request.user|has_edit_perm:object %} diff --git a/opentech/apply/review/templates/review/review_confirm_delete.html b/opentech/apply/review/templates/review/review_confirm_delete.html new file mode 100644 index 0000000000000000000000000000000000000000..227b09d5003419c1738196001878c40369a9b680 --- /dev/null +++ b/opentech/apply/review/templates/review/review_confirm_delete.html @@ -0,0 +1,21 @@ +{% extends "base-apply.html" %} + +{% block title %}Deleting: {{object.title }}{% endblock %} + +{% block content %} +<div class="admin-bar"> + <div class="admin-bar__inner"> + <h2 class="heading heading--no-margin">Deleting: {{ object.title }}</h2> + </div> +</div> + +<div class="wrapper wrapper--light-grey-bg wrapper--form wrapper--sidebar"> + <div class="wrapper--sidebar--inner"> + <form class="form" action="" method="post"> + {% csrf_token %} + <p><strong>Are you sure you want to delete "{{ object }}"?</strong></p> + <input class="button button--warning button--submit button--top-space" type="submit"value="Confirm" /> + </form> + </div> +</div> +{% endblock %} diff --git a/opentech/apply/review/templates/review/review_detail.html b/opentech/apply/review/templates/review/review_detail.html index fc0265dca511f9f59802668bf29c737144ca6b53..75f0743e02d2b794424ebb9a385e86ac8fb072c9 100644 --- a/opentech/apply/review/templates/review/review_detail.html +++ b/opentech/apply/review/templates/review/review_detail.html @@ -1,6 +1,6 @@ {% extends "base-apply.html" %} {% load bleach_tags submission_tags %} - +{% block title %}Review for {{ review.submission.title }}{% endblock %} {% block content %} <div class="admin-bar"> <div class="admin-bar__inner"> @@ -32,6 +32,14 @@ </p> </div> {% endif %} + {% if perms.funds.delete_review %} + <div> + <a class="link link--delete-review is-active" href="{% url 'apply:submissions:reviews:delete' submission_pk=object.submission.id pk=object.id %}"> + Delete + <svg class="icon icon--delete"><use xlink:href="#delete"></use></svg> + </a> + </div> + {% endif %} </div> <div class="rich-text rich-text--answers"> diff --git a/opentech/apply/review/urls.py b/opentech/apply/review/urls.py index 6f509a0e021c3a430a842891e22efec07f608ba8..2d632fb1cddd25f1ee42b697acba11c72ffe2d67 100644 --- a/opentech/apply/review/urls.py +++ b/opentech/apply/review/urls.py @@ -1,11 +1,12 @@ from django.urls import path -from .views import ReviewDetailView, ReviewListView, ReviewCreateOrUpdateView +from .views import ReviewDetailView, ReviewListView, ReviewCreateOrUpdateView, ReviewDeleteView app_name = 'reviews' urlpatterns = [ path('reviews/', ReviewListView.as_view(), name='list'), path('reviews/<int:pk>/', ReviewDetailView.as_view(), name="review"), + path('reviews/<int:pk>/delete/', ReviewDeleteView.as_view(), name="delete"), path('review/', ReviewCreateOrUpdateView.as_view(), name='form'), ] diff --git a/opentech/apply/review/views.py b/opentech/apply/review/views.py index 611de4fb3398ba59b499b54e073316a0b65cca47..cd77213788a966fe866e4b38d95dda5e47d90941 100644 --- a/opentech/apply/review/views.py +++ b/opentech/apply/review/views.py @@ -1,13 +1,13 @@ from collections import defaultdict -from django.contrib.auth.decorators import login_required +from django.contrib.auth.decorators import login_required, permission_required from django.core.exceptions import PermissionDenied from django.http import HttpResponseRedirect from django.shortcuts import get_object_or_404 from django.template.loader import get_template from django.urls import reverse_lazy from django.utils.decorators import method_decorator -from django.views.generic import CreateView, ListView, DetailView +from django.views.generic import CreateView, ListView, DetailView, DeleteView from wagtail.core.blocks import RichTextBlock @@ -280,3 +280,24 @@ class ReviewListView(ListView): review_data=review_data, **kwargs ) + + +@method_decorator(permission_required('review.delete_review', raise_exception=True), name='dispatch') +class ReviewDeleteView(DeleteView): + model = Review + + def delete(self, request, *args, **kwargs): + review = self.get_object() + messenger( + MESSAGES.DELETE_REVIEW, + user=request.user, + request=request, + submission=review.submission, + related=review, + ) + response = super().delete(request, *args, **kwargs) + return response + + def get_success_url(self): + review = self.get_object() + return reverse_lazy('funds:submissions:detail', args=(review.submission.id,)) diff --git a/opentech/apply/review/wagtail_hooks.py b/opentech/apply/review/wagtail_hooks.py new file mode 100644 index 0000000000000000000000000000000000000000..71f122fb74e779aa73c878ed427d79d88480aa36 --- /dev/null +++ b/opentech/apply/review/wagtail_hooks.py @@ -0,0 +1,11 @@ +from django.contrib.auth.models import Permission + +from wagtail.core import hooks + + +@hooks.register('register_permissions') +def register_permissions(): + return Permission.objects.filter( + content_type__app_label='review', + codename__in=['add_review', 'change_review', 'delete_review'] + ) diff --git a/opentech/static_src/src/sass/apply/components/_icon.scss b/opentech/static_src/src/sass/apply/components/_icon.scss index 1802fbc085051be8f50306c5f00afd84b053b46d..0293ae0ad2ca6457ee1950e7eaa446c053347e1d 100644 --- a/opentech/static_src/src/sass/apply/components/_icon.scss +++ b/opentech/static_src/src/sass/apply/components/_icon.scss @@ -104,4 +104,11 @@ margin-left: 7px; stroke: $color--mid-grey; } + + &--delete { + width: 12px; + margin-left: 7px; + fill: $color--tomato; + } + } diff --git a/opentech/static_src/src/sass/apply/components/_link.scss b/opentech/static_src/src/sass/apply/components/_link.scss index ad8fbec69a79fe53c36ea9cf1eb8c98bd73ea2a7..19617f0e7c9a5d8d9ee2e57615ecb20f75b567e9 100644 --- a/opentech/static_src/src/sass/apply/components/_link.scss +++ b/opentech/static_src/src/sass/apply/components/_link.scss @@ -183,7 +183,8 @@ } } - &--edit-submission { + &--edit-submission, + &--delete-submission { display: flex; align-items: center; font-weight: $weight--bold; diff --git a/opentech/templates/includes/sprites.html b/opentech/templates/includes/sprites.html index bc2e557b45e1756eb06551ce86540379b4e181d5..4e829a8d8675e7b814a5405eef5a66b80e8d343d 100644 --- a/opentech/templates/includes/sprites.html +++ b/opentech/templates/includes/sprites.html @@ -316,4 +316,10 @@ <path d="M14 4l2.29 2.29-2.88 2.88 1.42 1.42 2.88-2.88L20 10V4zm-4 0H4v6l2.29-2.29 4.71 4.7V20h2v-8.41l-5.29-5.3z" /> </symbol> + + <symbol id="delete" viewbox="0 0 11 11"> + <g fill-rule="evenodd"> + <path d="M3 4h5v7H3zM2 2h7v1H2zM5 1h1v1H5z"/> + </g> + </symbol> </svg>