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 import forms
from django.utils import timezone
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _
import bleach import bleach
from bleach.linkifier import Linker from bleach.linkifier import Linker
from tinymce.widgets import TinyMCE from tinymce.widgets import TinyMCE
from .models import GovernmentPlan, GovernmentPlanUpdate from .models import GovernmentPlan, GovernmentPlanUpdate, PlanRating, PlanStatus
BLEACH_OPTIONS = { BLEACH_OPTIONS = {
"tags": [ "tags": [
@ -47,7 +49,9 @@ class BleachField(forms.CharField):
class GovernmentPlanForm(forms.ModelForm): 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: class Meta:
model = GovernmentPlan model = GovernmentPlan
@ -55,8 +59,74 @@ class GovernmentPlanForm(forms.ModelForm):
class GovernmentPlanUpdateForm(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: class Meta:
model = GovernmentPlanUpdate model = GovernmentPlanUpdate
fields = "__all__" 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 follow_tags %}
{% load govplan %} {% load govplan %}
{% load fds_ogimage %} {% load fds_ogimage %}
{% load form_helper %}
{% load content_helper %}
{% block title %}{{ object.title }}{% endblock %} {% block title %}{{ object.title }}{% endblock %}
@ -190,6 +192,51 @@
</div> </div>
</div> </div>
{% endfor %} {% 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>
</div> </div>
{% endblock %} {% endblock %}

View file

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

View file

@ -1,13 +1,17 @@
from django.shortcuts import get_object_or_404, render from django.contrib import messages
from django.views.generic import DetailView 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 from .models import Government, GovernmentPlan, GovernmentPlanSection
class GovernmentMixin: class GovernmentMixin:
def get(self, *args, **kwargs): def dispatch(self, *args, **kwargs):
self.get_government() self.get_government()
return super().get(*args, **kwargs) return super().dispatch(*args, **kwargs)
def get_government(self): def get_government(self):
filter_kwarg = {} filter_kwarg = {}
@ -54,6 +58,8 @@ class GovPlanDetailView(GovernmentMixin, DetailView):
"-timestamp" "-timestamp"
) )
context["section"] = self.get_section() context["section"] = self.get_section()
if self.request.user.is_authenticated:
context["update_proposal_form"] = GovernmentPlanUpdateProposalForm()
# For CMS toolbar # For CMS toolbar
self.request.govplan = self.object self.request.govplan = self.object
return context return context
@ -63,6 +69,32 @@ class GovPlanDetailOGView(GovPlanDetailView):
template_name = "froide_govplan/plan_og.html" 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): def search(request):
plans = GovernmentPlan.objects.search(request.GET.get("q", "")) plans = GovernmentPlan.objects.search(request.GET.get("q", ""))