Newer
Older
from django.contrib.auth.decorators import login_required
from django.core.exceptions import PermissionDenied
from django.http import HttpResponseRedirect
from django.template.response import TemplateResponse
from django.utils.decorators import method_decorator
from django.views.generic import UpdateView
from django_filters.views import FilterView
from django_tables2.views import SingleTableMixin
from opentech.apply.activity.views import (
AllActivityContextMixin,
ActivityContextMixin,
CommentFormView,
DelegatedViewMixin,
)
from opentech.apply.activity.models import Activity
from opentech.apply.users.decorators import staff_required
from opentech.apply.utils.views import DelegateableView, ViewDispatcher
from .blocks import MustIncludeFieldBlock
from .forms import ProgressSubmissionForm, UpdateSubmissionLeadForm
from .tables import AdminSubmissionsTable, SubmissionFilter, SubmissionFilterAndSearch
@method_decorator(staff_required, name='dispatch')
class SubmissionListView(AllActivityContextMixin, SingleTableMixin, FilterView):
template_name = 'funds/submissions.html'
table_class = AdminSubmissionsTable
filterset_class = SubmissionFilter
def get_queryset(self):
return self.filterset_class._meta.model.objects.current()
def get_context_data(self, **kwargs):
active_filters = self.filterset.data
return super().get_context_data(active_filters=active_filters, **kwargs)
@method_decorator(staff_required, name='dispatch')
class SubmissionSearchView(SingleTableMixin, FilterView):
template_name = 'funds/submissions_search.html'
table_class = AdminSubmissionsTable
filterset_class = SubmissionFilterAndSearch
def get_queryset(self):
return self.filterset_class._meta.model.objects.current()
def get_context_data(self, **kwargs):
search_term = self.request.GET.get('query')
# We have more data than just 'query'
active_filters = len(self.filterset.data) > 1
return super().get_context_data(
search_term=search_term,
active_filters=active_filters,
**kwargs,
)
@method_decorator(staff_required, name='dispatch')
class ProgressSubmissionView(DelegatedViewMixin, UpdateView):
model = ApplicationSubmission
form_class = ProgressSubmissionForm
context_name = 'progress_form'
def form_valid(self, form):
old_phase = form.instance.phase.name
response = super().form_valid(form)
new_phase = form.instance.phase.name
user=self.request.user,
submission=self.kwargs['submission'],
message=f'Progressed from {old_phase} to {new_phase}'
)
return response
@method_decorator(staff_required, name='dispatch')
class UpdateLeadView(DelegatedViewMixin, UpdateView):
model = ApplicationSubmission
form_class = UpdateSubmissionLeadForm
context_name = 'lead_form'
def form_valid(self, form):
# Fetch the old lead from the database
old_lead = self.get_object().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 AdminSubmissionDetailView(ActivityContextMixin, DelegateableView):
template_name_suffix = '_admin_detail'
model = ApplicationSubmission
form_views = {
'progress': ProgressSubmissionView,
'comment': CommentFormView,
def get_context_data(self, **kwargs):
other_submissions = self.model.objects.filter(user=self.object.user).current().exclude(id=self.object.id)
if self.object.next:
other_submissions = other_submissions.exclude(id=self.object.next.id)
return super().get_context_data(
other_submissions=other_submissions,
class ApplicantSubmissionDetailView(ActivityContextMixin, DelegateableView):
model = ApplicationSubmission
form_views = {
'comment': CommentFormView,
}
def dispatch(self, request, *args, **kwargs):
if self.get_object().user != request.user:
raise PermissionDenied
return super().dispatch(request, *args, **kwargs)
class SubmissionDetailView(ViewDispatcher):
admin_view = AdminSubmissionDetailView
applicant_view = ApplicantSubmissionDetailView
@method_decorator(login_required, name='dispatch')
class SubmissionEditView(UpdateView):
model = ApplicationSubmission
def dispatch(self, request, *args, **kwargs):
if request.user != self.get_object().user:
raise PermissionDenied
if not self.get_object().phase.has_perm(request.user, 'edit'):
raise PermissionDenied
return super().dispatch(request, *args, **kwargs)
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
instance = kwargs.pop('instance')
form_data = instance.form_data
# convert certain data to the correct field id
for field in self.object.form_fields:
if isinstance(field.block, MustIncludeFieldBlock):
try:
response = form_data[field.block.name]
except KeyError:
pass
else:
form_data[field.id] = response
kwargs['initial'] = form_data
return kwargs
def get_form_class(self):
return self.object.get_form_class()
def form_valid(self, form):
self.object.form_data = form.cleaned_data
self.object.save()
return HttpResponseRedirect(self.get_success_url())
workflows = [SingleStage, DoubleStage]
class BasicSubmissionForm(forms.Form):
who_are_you = forms.CharField()
def demo_workflow(request, wf_id):
logs = request.session.get('logs', list())
submission = request.session.get('submission', dict())
wf = int(wf_id)
workflow = workflow_class([BasicSubmissionForm] * wf)
current_phase = request.POST.get('current')
current = workflow.current(current_phase)
if current.stage.name not in submission:
submitted_form = current.stage.form(request.POST)
if submitted_form.is_valid():
submission[current.stage.name] = submitted_form.cleaned_data
phase = current
logs.append(
f'{phase.stage}: Form was submitted'
)
form = None
else:
form = submitted_form
else:
phase = workflow.process(current_phase, request.POST['action'])
logs.append(
f'{current.stage}: {current.name} was updated to {phase.stage}: {phase.name}'
)
submission.clear()
if phase.stage.name not in submission:
form = phase.stage.form
else:
form = None
request.session['logs'] = logs
request.session['submission'] = submission
context = {
'workflow': workflow,
'phase': phase,
'data': submission,
'form': form,
return TemplateResponse(request, 'funds/demo_workflow.html', context)