From a380248198faa3224e38e08593c0ef8e21d4d35c Mon Sep 17 00:00:00 2001 From: Dan Braghis <dan.braghis@torchbox.com> Date: Thu, 14 Jun 2018 10:24:44 +0100 Subject: [PATCH] Add view and templates --- .../determinations/determination_detail.html | 25 ++++ .../determinations/determination_form.html | 41 ++++++ .../includes/determination_button.html | 12 ++ .../determinations/templatetags/__init__.py | 0 .../templatetags/determination_tags.py | 21 +++ opentech/apply/determinations/urls.py | 1 + opentech/apply/determinations/views.py | 138 ++++++++++++++++++ .../applicationsubmission_admin_detail.html | 10 ++ .../funds/applicationsubmission_detail.html | 3 + .../apply/funds/templatetags/workflow_tags.py | 5 + 10 files changed, 256 insertions(+) create mode 100644 opentech/apply/determinations/templates/determinations/determination_detail.html create mode 100644 opentech/apply/determinations/templates/determinations/determination_form.html create mode 100644 opentech/apply/determinations/templates/determinations/includes/determination_button.html create mode 100644 opentech/apply/determinations/templatetags/__init__.py create mode 100644 opentech/apply/determinations/templatetags/determination_tags.py create mode 100644 opentech/apply/determinations/views.py diff --git a/opentech/apply/determinations/templates/determinations/determination_detail.html b/opentech/apply/determinations/templates/determinations/determination_detail.html new file mode 100644 index 000000000..02737f68c --- /dev/null +++ b/opentech/apply/determinations/templates/determinations/determination_detail.html @@ -0,0 +1,25 @@ +{% extends "base-apply.html" %} +{% load bleach_tags %} + +{% block content %} +<div class="wrapper wrapper--breakout wrapper--admin"> + <div class="wrapper wrapper--large"> + <h2 class="heading heading--no-margin">Determination</h2> + <h5>For <a href="{% url "funds:submission" determination.submission.id %}">{{ determination.submission.title }}</a></h5> + </div> +</div> + +<div class="grid"> + <div> + <h5>Determination</h5> + <p>{{ determination.determination }}</p> + </div> +</div> + +<div class="rich-text rich-text--answers"> + {% for question, answer in determination_data.items %} + <h5>{{ question }}</h5> + {{ answer|bleach }} + {% endfor %} +</div> +{% endblock %} diff --git a/opentech/apply/determinations/templates/determinations/determination_form.html b/opentech/apply/determinations/templates/determinations/determination_form.html new file mode 100644 index 000000000..172e6fc95 --- /dev/null +++ b/opentech/apply/determinations/templates/determinations/determination_form.html @@ -0,0 +1,41 @@ +{% extends "base-apply.html" %} +{% block title %}Create a determination{% endblock %} +{% block content %} +<div class="wrapper wrapper--breakout wrapper--admin"> + <div class="wrapper wrapper--medium"> + <h2 class="heading heading--no-margin">{{ title|default:"Create Determination" }}</h2> + <h5>For <a href="{% url "funds:submission" submission.id %}">{{ submission.title }}</a></h5> + </div> +</div> + +<div class="wrapper wrapper--medium wrapper--inner-space-medium"> +{% if not has_submitted_determination %} + <form class="form form--with-p-tags" action="" method="post" novalidate> + {{ form.media }} + {% csrf_token %} + {% for field in form %} + {# to be replaced with better logic when we use stream form #} + {% ifchanged field.field.group %} + {% for key, value in form.titles.items %} + {% if key == field.field.group %} + <h2>{{ value }}</h2> + {% endif %} + {% endfor %} + {% endifchanged %} + + {% if field.field %} + {% include "funds/includes/field.html" %} + {% else %} + {{ field }} + {% endif %} + {% endfor %} + <input class="button button--primary" type="submit" value="Send Determination" name="submit" /> + {% if not object.id or object.is_draft %} + <input class="button button--secondary button--white" type="submit" value="Save Draft" name="{{ form.draft_button_name }}" /> + {% endif %} + </form> +{% else %} + <p>You have already added a determination for this submission</p> +{% endif %} +</div> +{% endblock %} diff --git a/opentech/apply/determinations/templates/determinations/includes/determination_button.html b/opentech/apply/determinations/templates/determinations/includes/determination_button.html new file mode 100644 index 000000000..f0bd15129 --- /dev/null +++ b/opentech/apply/determinations/templates/determinations/includes/determination_button.html @@ -0,0 +1,12 @@ +{% load determination_tags workflow_tags %} +{% if request.user.is_apply_staff %} + {% if request.user|has_draft:submission or request.user|can_add_determination:submission %} + <a href="{% url 'apply:determinations:form' submission_pk=submission.id %}" class="button button--primary button--half-width"> + {% if request.user|has_draft:submission %} + Update determination draft + {% elif request.user|can_add_determination:submission %} + Add determination + {% endif %} + </a> + {% endif %} +{% endif %} diff --git a/opentech/apply/determinations/templatetags/__init__.py b/opentech/apply/determinations/templatetags/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/opentech/apply/determinations/templatetags/determination_tags.py b/opentech/apply/determinations/templatetags/determination_tags.py new file mode 100644 index 000000000..f65cd2403 --- /dev/null +++ b/opentech/apply/determinations/templatetags/determination_tags.py @@ -0,0 +1,21 @@ +from django import template +from django.core.exceptions import ObjectDoesNotExist + +register = template.Library() + + +@register.filter +def can_add_determination(user, submission): + try: + has_determination = submission.determination + except ObjectDoesNotExist: + has_determination = False + return submission.has_permission_to_add_determination(user) and not has_determination + + +@register.filter +def has_draft(user, submission): + try: + return submission.has_permission_to_add_determination(user) and submission.determination.is_draft + except ObjectDoesNotExist: + return False diff --git a/opentech/apply/determinations/urls.py b/opentech/apply/determinations/urls.py index 7e11903e5..0cb98c4eb 100644 --- a/opentech/apply/determinations/urls.py +++ b/opentech/apply/determinations/urls.py @@ -6,4 +6,5 @@ app_name = 'determinations' urlpatterns = [ path('determination/', DeterminationCreateOrUpdateView.as_view(), name="form"), + path('determination/<int:pk>', DeterminationDetailView.as_view(), name="determination"), ] diff --git a/opentech/apply/determinations/views.py b/opentech/apply/determinations/views.py new file mode 100644 index 000000000..11e2f4278 --- /dev/null +++ b/opentech/apply/determinations/views.py @@ -0,0 +1,138 @@ +from django.core.exceptions import PermissionDenied, ObjectDoesNotExist +from django.http import HttpResponseRedirect +from django.shortcuts import get_object_or_404 +from django.urls import reverse_lazy +from django.utils.decorators import method_decorator +from django.views.generic import DetailView +from django.views.generic.detail import SingleObjectTemplateResponseMixin +from django.views.generic.edit import ProcessFormView, ModelFormMixin + +from opentech.apply.funds.models import ApplicationSubmission +from opentech.apply.users.decorators import staff_required + +from .forms import ConceptDeterminationForm, ProposalDeterminationForm +from .models import Determination + + +def get_form_for_stage(submission): + forms = [ConceptDeterminationForm, ProposalDeterminationForm] + index = [ + i for i, stage in enumerate(submission.workflow.stages) + if submission.stage.name == stage.name + ][0] + return forms[index] + + +class CreateOrUpdateView(SingleObjectTemplateResponseMixin, ModelFormMixin, ProcessFormView): + + def get(self, request, *args, **kwargs): + try: + self.object = self.get_object() + except self.model.DoesNotExist: + self.object = None + + return super().get(request, *args, **kwargs) + + def post(self, request, *args, **kwargs): + try: + self.object = self.get_object() + except self.model.DoesNotExist: + self.object = None + + return super().post(request, *args, **kwargs) + + +class DeterminationCreateOrUpdateView(CreateOrUpdateView): + model = Determination + template_name = 'determinations/determination_form.html' + + def get_object(self, queryset=None): + return self.model.objects.get(submission=self.submission, author=self.request.user) + + def dispatch(self, request, *args, **kwargs): + self.submission = get_object_or_404(ApplicationSubmission, id=self.kwargs['submission_pk']) + + # TODO add proper permission + # if not self.submission.phase.has_perm(request.user, 'add_determination') or \ + if not self.submission.has_permission_to_add_determination(request.user): + raise PermissionDenied() + + if self.request.POST: + return self.get(request, *args, **kwargs) + + return super().dispatch(request, *args, **kwargs) + + def get_context_data(self, **kwargs): + try: + has_submitted_determination = not self.submission.determination.is_draft + except ObjectDoesNotExist: + has_submitted_determination = False + + return super().get_context_data( + submission=self.submission, + has_submitted_determination=has_submitted_determination, + title="Update Determination draft" if self.object else 'Add Determination', + **kwargs + ) + + def get_form_class(self): + return get_form_for_stage(self.submission) + + def get_form_kwargs(self): + kwargs = super().get_form_kwargs() + kwargs['request'] = self.request + kwargs['submission'] = self.submission + + if self.object: + kwargs['initial'] = self.object.determination_data + kwargs['initial']['determination'] = self.object.determination + + return kwargs + + def get_success_url(self): + return self.submission.get_absolute_url() + + +@method_decorator(staff_required, name='dispatch') +class DeterminationDetailView(DetailView): + model = Determination + + def dispatch(self, request, *args, **kwargs): + determination = self.get_object() + + if request.user != determination.submission.lead and not request.user.is_superuser: + raise PermissionDenied + + if determination.is_draft: + return HttpResponseRedirect(reverse_lazy('apply:determinations:form', args=(determination.submission.id,))) + + return super().dispatch(request, *args, **kwargs) + + def get_context_data(self, **kwargs): + determination = self.get_object().determination + form_used = get_form_for_stage(self.get_object().submission) + determination_data = {} + + for name, field in form_used.base_fields.items(): + try: + # Add titles which exist + title = form_used.titles[field.group] + determination_data.setdefault(title, []) + except AttributeError: + pass + + value = determination[name] + try: + choices = dict(field.choices) + except AttributeError: + pass + else: + # Update the stored value to the display value + value = choices[int(value)] + + determination_data.setdefault(field.label, str(value)) + + return super().get_context_data( + determination_data=determination_data, + **kwargs + ) diff --git a/opentech/apply/funds/templates/funds/applicationsubmission_admin_detail.html b/opentech/apply/funds/templates/funds/applicationsubmission_admin_detail.html index fc0040d53..e9cabb5f6 100644 --- a/opentech/apply/funds/templates/funds/applicationsubmission_admin_detail.html +++ b/opentech/apply/funds/templates/funds/applicationsubmission_admin_detail.html @@ -12,6 +12,16 @@ {% include "funds/includes/update_reviewer_form.html" %} {% endblock %} +{% block determination %} + <div class="sidebar__inner"> + <h5>Determination</h5> + {% if object.determination %} + {{ object.determination.determination }} | {{ object.determination.author }} + {% endif %} + {% include 'determinations/includes/determination_button.html' with submission=object %} + </div> +{% endblock %} + {% block reviews %} <div class="sidebar__inner"> <h5>Reviews & assignees</h5> diff --git a/opentech/apply/funds/templates/funds/applicationsubmission_detail.html b/opentech/apply/funds/templates/funds/applicationsubmission_detail.html index d121c37ba..3038b522e 100644 --- a/opentech/apply/funds/templates/funds/applicationsubmission_detail.html +++ b/opentech/apply/funds/templates/funds/applicationsubmission_detail.html @@ -88,6 +88,9 @@ {% endblock %} {% endif %} + {% block determination %} + {% endblock %} + {% block reviews %} {% endblock %} diff --git a/opentech/apply/funds/templatetags/workflow_tags.py b/opentech/apply/funds/templatetags/workflow_tags.py index b2923a6da..928d47dd1 100644 --- a/opentech/apply/funds/templatetags/workflow_tags.py +++ b/opentech/apply/funds/templatetags/workflow_tags.py @@ -16,3 +16,8 @@ def has_edit_perm(user, submission): @register.filter def has_review_perm(user, submission): return check_permission(user, 'review', submission) + + +@register.filter +def has_determination_perm(user, submission): + return check_permission(user, 'create_determination', submission) -- GitLab