diff --git a/opentech/apply/activity/views.py b/opentech/apply/activity/views.py index f6f3f4b4c65071c9e3c817e299859f9826a38593..c680bda9d570f291388d6425936e9c4182aa7fc9 100644 --- a/opentech/apply/activity/views.py +++ b/opentech/apply/activity/views.py @@ -22,7 +22,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) @@ -40,6 +39,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 @@ -53,3 +56,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 ce71b0b2a9120472ec6ea287442be3fa656bab1a..e74a7449e5a9b4aa3fea1ace29af62a6b96b9e8e 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 0000000000000000000000000000000000000000..8d68ac6179b435e8d6a2187c814cb6e72bed0d53 --- /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 a9fa5053b1b356419b859e95f9f098d9f2befacd..c36510831779e8db5128b3da927b7a8b58fbf82e 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 865bebbd1a6c7ebc902eedb2fcc4d6b8540b3ab6..d6a2e2805a0d886ee8e88541807e7b2cf971073e 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 0000000000000000000000000000000000000000..b6ad97907a33f678a11a2560a5927cfc96755aaf --- /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 fa5103e367ef28f135788479cf8c91447c1a2220..31b4536c2fada2df244a4cbcf9f25967c15379d5 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):