Add proposal form and view

This commit is contained in:
Stefan Wehrmeyer 2022-03-16 12:23:52 +01:00
parent 8283693906
commit 9902039e3c
4 changed files with 162 additions and 7 deletions

View file

@ -1,11 +1,13 @@
from django import forms
from django.utils import timezone
from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _
import bleach
from bleach.linkifier import Linker
from tinymce.widgets import TinyMCE
from .models import GovernmentPlan, GovernmentPlanUpdate
from .models import GovernmentPlan, GovernmentPlanUpdate, PlanRating, PlanStatus
BLEACH_OPTIONS = {
"tags": [
@ -47,7 +49,9 @@ class BleachField(forms.CharField):
class GovernmentPlanForm(forms.ModelForm):
description = BleachField(required=False, widget=TinyMCE(attrs={"cols": 80, "rows": 30}))
description = BleachField(
required=False, widget=TinyMCE(attrs={"cols": 80, "rows": 30})
)
class Meta:
model = GovernmentPlan
@ -55,8 +59,74 @@ class GovernmentPlanForm(forms.ModelForm):
class GovernmentPlanUpdateForm(forms.ModelForm):
content = BleachField(required=False, widget=TinyMCE(attrs={"cols": 80, "rows": 30}))
content = BleachField(
required=False, widget=TinyMCE(attrs={"cols": 80, "rows": 30})
)
class Meta:
model = GovernmentPlanUpdate
fields = "__all__"
class GovernmentPlanUpdateProposalForm(forms.ModelForm):
title = forms.CharField(
label=_("title"),
help_text=_("Summarize the update in a title."),
widget=forms.TextInput(
attrs={
"class": "form-control",
}
),
)
content = forms.CharField(
required=False,
label=_("details"),
help_text=_("Optionally give more details."),
widget=forms.Textarea(attrs={"class": "form-control", "rows": "3"}),
)
url = forms.URLField(
label=_("source URL"),
help_text=_("Please give provide a link."),
widget=forms.URLInput(
attrs={"class": "form-control", "placeholder": "https://"}
),
)
status = forms.ChoiceField(
label=_("status"),
help_text=_("Has the status of the plan changed?"),
choices=[("", "---")] + PlanStatus.choices,
required=False,
)
rating = forms.ChoiceField(
label=_("rating"),
help_text=_("What's your rating of the current implementation?"),
choices=[("", "---")] + PlanRating.choices,
required=False,
)
class Meta:
model = GovernmentPlanUpdate
fields = (
"title",
"content",
"url",
"status",
"rating",
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def save(self, plan, user):
"""
This doesn't save instance, but saves
the change proposal.
"""
data = self.cleaned_data
plan.proposals = plan.proposals or {}
plan.proposals[user.id] = {
"data": data,
"timestamp": timezone.now().isoformat(),
}
plan.save()
return plan

View file

@ -6,6 +6,8 @@
{% load follow_tags %}
{% load govplan %}
{% load fds_ogimage %}
{% load form_helper %}
{% load content_helper %}
{% block title %}{{ object.title }}{% endblock %}
@ -190,6 +192,51 @@
</div>
</div>
{% endfor %}
<div class="col col-12 col-lg-6 d-flex" id="update-{{ update.pk }}">
<div class="box-card border-blue shadow-blue">
<div>
<div class="box-card-header bg-blue-100 d-flex justify-content-center p-3 p-md-4 tight-margin flex-column">
<h3 class="h4">Neue Entwicklung melden</h3>
</div>
<div class="p-3 p-md-4">
{% if request.user.is_authenticated %}
<button type="button" class="btn btn-light" data-toggle="modal" data-target="#govplanupdate-proposal">
Entwicklung melden
</button>
<div class="modal" data-teleport="body" tabindex="-1" role="dialog" id="govplanupdate-proposal">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">
Neue Entwicklung melden
</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form method="post" action="{% url 'govplan:propose_planupdate' gov=object.government.slug plan=object.slug %}">
{% csrf_token %}
{% render_form update_proposal_form %}
<button type="submit" class="btn btn-primary">
Neue Entwicklung melden
</button>
</form>
</div>
</div>
</div>
</div>
{% else %}
<a class="btn btn-light" href="{{ object.get_absolute_url|make_login_redirect_url }}">
Bitte einloggen, um eine Entwicklung zu melden
</a>
{% endif %}
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View file

@ -4,6 +4,7 @@ from django.utils.translation import pgettext_lazy
from .views import (
GovPlanDetailOGView,
GovPlanDetailView,
GovPlanProposeUpdateView,
GovPlanSectionDetailView,
search,
)
@ -22,6 +23,11 @@ urlpatterns = [
GovPlanDetailOGView.as_view(),
name="plan_og",
),
path(
pgettext_lazy("url part", "<slug:gov>/plan/<slug:plan>/propose-update/"),
GovPlanProposeUpdateView.as_view(),
name="propose_planupdate",
),
path(
pgettext_lazy("url part", "<slug:gov>/<slug:section>/"),
GovPlanSectionDetailView.as_view(),

View file

@ -1,13 +1,17 @@
from django.shortcuts import get_object_or_404, render
from django.views.generic import DetailView
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.shortcuts import get_object_or_404, redirect, render
from django.utils.translation import gettext_lazy as _
from django.views.generic import DetailView, UpdateView
from .forms import GovernmentPlanUpdateProposalForm
from .models import Government, GovernmentPlan, GovernmentPlanSection
class GovernmentMixin:
def get(self, *args, **kwargs):
def dispatch(self, *args, **kwargs):
self.get_government()
return super().get(*args, **kwargs)
return super().dispatch(*args, **kwargs)
def get_government(self):
filter_kwarg = {}
@ -54,6 +58,8 @@ class GovPlanDetailView(GovernmentMixin, DetailView):
"-timestamp"
)
context["section"] = self.get_section()
if self.request.user.is_authenticated:
context["update_proposal_form"] = GovernmentPlanUpdateProposalForm()
# For CMS toolbar
self.request.govplan = self.object
return context
@ -63,6 +69,32 @@ class GovPlanDetailOGView(GovPlanDetailView):
template_name = "froide_govplan/plan_og.html"
class GovPlanProposeUpdateView(GovernmentMixin, LoginRequiredMixin, UpdateView):
template_name = "publicbody/add_proposal.html"
slug_url_kwarg = "plan"
form_class = GovernmentPlanUpdateProposalForm
def get_queryset(self):
qs = GovernmentPlan.objects.filter(government=self.government)
if self.request.user.is_authenticated and self.request.user.is_staff:
return qs
return qs.filter(public=True)
def get_success_url(self):
return self.object.get_absolute_url()
def form_valid(self, form):
form.save(self.object, self.request.user)
messages.add_message(
self.request,
messages.INFO,
_(
"Thank you for your proposal. We will send you an email when it has been approved."
),
)
return redirect(self.object)
def search(request):
plans = GovernmentPlan.objects.search(request.GET.get("q", ""))