From 0ce76cf6d97117d8a17f6a8ea2749ce3c0a15185 Mon Sep 17 00:00:00 2001 From: Todd Dembrey <todd.dembrey@torchbox.com> Date: Mon, 5 Mar 2018 09:54:39 +0000 Subject: [PATCH] Create the lead update form --- opentech/apply/activity/views.py | 10 +++++- opentech/apply/funds/forms.py | 11 ++++++ .../0026_add_leads_to_submission_and_lab.py | 30 ++++++++++++++++ opentech/apply/funds/models.py | 15 +++++++- .../funds/applicationsubmission_detail.html | 3 +- .../funds/includes/update_lead_form.html | 5 +++ opentech/apply/funds/views.py | 35 ++++++++++++------- 7 files changed, 94 insertions(+), 15 deletions(-) create mode 100644 opentech/apply/funds/migrations/0026_add_leads_to_submission_and_lab.py create mode 100644 opentech/apply/funds/templates/funds/includes/update_lead_form.html diff --git a/opentech/apply/activity/views.py b/opentech/apply/activity/views.py index 716bcce1b..bfffd64aa 100644 --- a/opentech/apply/activity/views.py +++ b/opentech/apply/activity/views.py @@ -19,7 +19,6 @@ class ActivityContextMixin: extra = { 'actions': Activity.actions.filter(submission=self.object), 'comments': Activity.comments.filter(submission=self.object), - CommentFormView.context_name: CommentFormView.form_class(), } return super().get_context_data(**extra, **kwargs) @@ -37,6 +36,10 @@ class DelegatedViewMixin(View): kwargs.update(**{self.context_name: form}) return super().get_context_data(**kwargs) + @classmethod + def contribute_form(cls, submission): + return cls.context_name, cls.form_class(instance=submission) + class CommentFormView(DelegatedViewMixin, CreateView): form_class = CommentForm @@ -50,3 +53,8 @@ class CommentFormView(DelegatedViewMixin, CreateView): def get_success_url(self): return self.object.submission.get_absolute_url() + + @classmethod + def contribute_form(cls, submission): + # We dont want to pass the submission as the instance + return super().contribute_form(None) diff --git a/opentech/apply/funds/forms.py b/opentech/apply/funds/forms.py index ce71b0b2a..e74a7449e 100644 --- a/opentech/apply/funds/forms.py +++ b/opentech/apply/funds/forms.py @@ -21,3 +21,14 @@ class ProgressSubmissionForm(forms.ModelForm): new_phase = self.instance.workflow.process(self.instance.phase, self.cleaned_data['action']) self.instance.status = str(new_phase) return super().save(*args, **kwargs) + + +class UpdateSubmissionLeadForm(forms.ModelForm): + class Meta: + model = ApplicationSubmission + fields = ('lead',) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + qs = self.fields['lead'].queryset + self.fields['lead'].queryset = qs.exclude(id=self.instance.lead.id) diff --git a/opentech/apply/funds/migrations/0026_add_leads_to_submission_and_lab.py b/opentech/apply/funds/migrations/0026_add_leads_to_submission_and_lab.py new file mode 100644 index 000000000..8d68ac617 --- /dev/null +++ b/opentech/apply/funds/migrations/0026_add_leads_to_submission_and_lab.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.8 on 2018-03-02 17:08 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('funds', '0025_update_with_file_blocks'), + ] + + operations = [ + migrations.AddField( + model_name='applicationsubmission', + name='lead', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='submission_lead', to=settings.AUTH_USER_MODEL), + preserve_default=False, + ), + migrations.AddField( + model_name='labtype', + name='lead', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='lab_lead', to=settings.AUTH_USER_MODEL), + preserve_default=False, + ), + ] diff --git a/opentech/apply/funds/models.py b/opentech/apply/funds/models.py index a9fa5053b..c36510831 100644 --- a/opentech/apply/funds/models.py +++ b/opentech/apply/funds/models.py @@ -382,11 +382,17 @@ class LabType(EmailForm, WorkflowStreamForm, SubmittableStreamForm): # type: ig class Meta: verbose_name = _("Lab") + lead = models.ForeignKey(settings.AUTH_USER_MODEL, limit_choices_to={'groups__name': STAFF_GROUP_NAME}, related_name='lab_lead') + parent_page_types = ['apply_home.ApplyHomePage'] subpage_types = [] # type: ignore + content_panels = WorkflowStreamForm.content_panels + [ + FieldPanel('lead') + ] + edit_handler = TabbedInterface([ - ObjectList(WorkflowStreamForm.content_panels, heading='Content'), + ObjectList(content_panels, heading='Content'), EmailForm.email_tab, ObjectList(WorkflowStreamForm.promote_panels, heading='Promote'), ]) @@ -434,6 +440,7 @@ class ApplicationSubmission(WorkflowHelpers, AbstractFormSubmission): form_fields = StreamField(CustomFormFieldsBlock()) page = models.ForeignKey('wagtailcore.Page', on_delete=models.PROTECT) round = models.ForeignKey('wagtailcore.Page', on_delete=models.PROTECT, related_name='submissions', null=True) + lead = models.ForeignKey(settings.AUTH_USER_MODEL, limit_choices_to={'groups__name': STAFF_GROUP_NAME}, related_name='submission_lead') user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True) search_data = models.TextField() @@ -515,6 +522,12 @@ class ApplicationSubmission(WorkflowHelpers, AbstractFormSubmission): self.workflow_name = self.page.workflow_name self.status = str(self.workflow.first()) + try: + self.lead = self.round.specific.lead + except AttributeError: + # Its a lab + self.lead = self.page.specific.lead + # add a denormed version of the answer for searching self.search_data = ' '.join(self.prepare_search_values()) diff --git a/opentech/apply/funds/templates/funds/applicationsubmission_detail.html b/opentech/apply/funds/templates/funds/applicationsubmission_detail.html index 865bebbd1..d6a2e2805 100644 --- a/opentech/apply/funds/templates/funds/applicationsubmission_detail.html +++ b/opentech/apply/funds/templates/funds/applicationsubmission_detail.html @@ -9,7 +9,7 @@ <span>{{ object.stage }}</span> <span>{{ object.page }}</span> <span>{{ object.round }}</span> - <span>Lead: {{ object.round.specific.lead }}</span> + <span>Lead: {{ object.lead }}</span> </h5> {% include "funds/includes/status_bar.html" with workflow=object.workflow status=object.phase %} </div> @@ -51,6 +51,7 @@ <aside class="sidebar"> {% include "funds/includes/progress_form.html" %} + {% include "funds/includes/update_lead_form.html" %} {% if other_submissions %} <div class="sidebar__inner"> <h6 class="heading heading--light-grey heading--small heading--uppercase">Past Submissions</h6> diff --git a/opentech/apply/funds/templates/funds/includes/update_lead_form.html b/opentech/apply/funds/templates/funds/includes/update_lead_form.html new file mode 100644 index 000000000..b6ad97907 --- /dev/null +++ b/opentech/apply/funds/templates/funds/includes/update_lead_form.html @@ -0,0 +1,5 @@ +<form method="post" id="update-lead-form"> + {% csrf_token %} + {{ lead_form }} + <input id="update-form-submit" name="form-submitted" type="submit" form="update-lead-form" value="Update"> +</form> diff --git a/opentech/apply/funds/views.py b/opentech/apply/funds/views.py index fa5103e36..31b4536c2 100644 --- a/opentech/apply/funds/views.py +++ b/opentech/apply/funds/views.py @@ -13,7 +13,7 @@ from opentech.apply.activity.views import ( ) from opentech.apply.activity.models import Activity -from .forms import ProgressSubmissionForm +from .forms import ProgressSubmissionForm, UpdateSubmissionLeadForm from .models import ApplicationSubmission from .tables import SubmissionsTable, SubmissionFilter, SubmissionFilterAndSearch from .workflow import SingleStage, DoubleStage @@ -49,15 +49,6 @@ class SubmissionSearchView(SingleTableMixin, FilterView): ) -class ProgressContextMixin(View): - def get_context_data(self, **kwargs): - extra = { - ProgressSubmissionView.context_name: ProgressSubmissionView.form_class(instance=self.object), - } - - return super().get_context_data(**extra, **kwargs) - - class ProgressSubmissionView(DelegatedViewMixin, UpdateView): model = ApplicationSubmission form_class = ProgressSubmissionForm @@ -75,17 +66,37 @@ class ProgressSubmissionView(DelegatedViewMixin, UpdateView): return response -class SubmissionDetailView(ActivityContextMixin, ProgressContextMixin, DetailView): +class UpdateLeadView(DelegatedViewMixin, UpdateView): + model = ApplicationSubmission + form_class = UpdateSubmissionLeadForm + context_name = 'lead_form' + + def form_valid(self, form): + old_lead = form.instance.lead + response = super().form_valid(form) + new_lead = form.instance.lead + Activity.actions.create( + user=self.request.user, + submission=self.kwargs['submission'], + message=f'Lead changed from {old_lead} to {new_lead}' + ) + return response + + +class SubmissionDetailView(ActivityContextMixin, DetailView): model = ApplicationSubmission form_views = { 'progress': ProgressSubmissionView, 'comment': CommentFormView, + 'update': UpdateLeadView, } def get_context_data(self, **kwargs): + forms = dict(form_view.contribute_form(self.object) for form_view in self.form_views.values()) return super().get_context_data( other_submissions=self.model.objects.filter(user=self.object.user).exclude(id=self.object.id), - **kwargs + **forms, + **kwargs, ) def post(self, request, *args, **kwargs): -- GitLab