Add proposal form and view
This commit is contained in:
parent
8283693906
commit
9902039e3c
4 changed files with 162 additions and 7 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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">×</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 %}
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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", ""))
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue