Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ks 2021 11 add token form to proposal list view #4020

Merged
merged 4 commits into from
Dec 3, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions meinberlin/apps/budgeting/rules.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import rules

from adhocracy4.modules import predicates as module_predicates
from adhocracy4.phases import predicates as phase_predicates

from . import models

@@ -38,3 +39,8 @@
module_predicates.is_context_moderator |
module_predicates.is_context_initiator
)

rules.add_perm(
'meinberlin_budgeting.vote_proposal',
phase_predicates.phase_allows_vote(models.Proposal)
)
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{% extends extends %}
{% load i18n discovery_tags static maps_tags react_proposals %}
{% load i18n discovery_tags static maps_tags react_proposals widget_tweaks rules %}

{% block extra_js %}
<script type="text/javascript" src="{% static 'a4maps_display_points.js' %}"></script>
@@ -18,6 +18,23 @@
{% trans 'Submit proposal' %}
</a>
{% endif %}
{% has_perm 'meinberlin_budgeting.vote_proposal' request.user module as vote_allowed %}
{% if vote_allowed %}
{% if request.session.voting_token %}
You are using token {{ request.session.voting_token }}
{% else %}
<form class="" action="{{ request.path }}" method="post">
<div class="form-group">
{% csrf_token %}
<div class="widget widget--{{ form.token|widget_type }}">
{{ token_form.token }}
</div>
{{ token_form.token.errors }}
<button type="submit" class="btn btn--full u-spacer-bottom btn--huge">{% trans 'Enter code' %}</button>
</div>
</form>
{% endif %}
{% endif %}
{% endblock %}

{% block phase_content %}
13 changes: 10 additions & 3 deletions meinberlin/apps/budgeting/templatetags/react_proposals.py
Original file line number Diff line number Diff line change
@@ -4,14 +4,21 @@
from django.urls import reverse
from django.utils.html import format_html

from adhocracy4.phases.predicates import has_feature_active
from meinberlin.apps.budgeting.models import Proposal

register = template.Library()


@register.simple_tag(takes_context=True)
def react_proposals(context, obj):
proposals_api_url = reverse('proposals-list', kwargs={'module_pk': obj.pk})
def react_proposals(context, module):
proposals_api_url = reverse('proposals-list',
kwargs={'module_pk': module.pk})
attributes = {'proposals_api_url': proposals_api_url,
'is_voting_phase': 'voting' in obj.active_phase.type}
'is_voting_phase': has_feature_active(module,
Proposal,
'vote')
}

return format_html(
'<div data-mb-widget="proposals" '
16 changes: 16 additions & 0 deletions meinberlin/apps/budgeting/views.py
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@
from meinberlin.apps.contrib import filters
from meinberlin.apps.ideas import views as idea_views
from meinberlin.apps.projects.views import ArchivedWidget
from meinberlin.apps.votes.forms import TokenForm

from . import forms
from . import models
@@ -58,6 +59,21 @@ def get_queryset(self):
.annotate_negative_rating_count() \
.annotate_comment_count()

def get_context_data(self, **kwargs):
if 'token_form' not in kwargs:
token_form = TokenForm(module_id=self.module.id)
kwargs['token_form'] = token_form
return super().get_context_data(**kwargs)

def post(self, request, *args, **kwargs):
self.object_list = self.get_queryset()
token_form = TokenForm(request.POST, module_id=self.module.id)
if token_form.is_valid():
request.session['voting_token'] = token_form.cleaned_data['token']
kwargs['token_form'] = token_form
context = super().get_context_data(**kwargs)
return self.render_to_response(context)


class ProposalDetailView(idea_views.AbstractIdeaDetailView):
model = models.Proposal
25 changes: 25 additions & 0 deletions meinberlin/apps/votes/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from django import forms
from django.utils.translation import gettext_lazy as _

from meinberlin.apps.votes.models import VotingToken


class TokenForm(forms.Form):

token = forms.CharField(max_length=40)

def __init__(self, *args, **kwargs):
self.module_id = kwargs.pop('module_id')
super().__init__(*args, **kwargs)

def clean(self):
cleaned_data = super().clean()
if 'token' in self.cleaned_data:
token_queryset = VotingToken.objects.filter(
token=self.cleaned_data['token'],
module_id=self.module_id
)
if not token_queryset:
self.add_error('token', _('This token is not valid'))

return cleaned_data
9 changes: 8 additions & 1 deletion meinberlin/apps/votes/models.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import secrets
import string

from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
@@ -13,7 +14,8 @@


def get_token():
return secrets.token_urlsafe(16)
alphabet = string.ascii_letters + string.digits
return ''.join(secrets.choice(alphabet) for i in range(12))


class VotingToken(models.Model):
@@ -78,6 +80,11 @@ def is_valid(self, model):
def is_valid_for_item(self, item):
return item.module == self.module and self.is_valid(item.__class__)

def __str__(self):
return '{}-{}-{}'.format(self.token[0:4],
self.token[4:8],
self.token[8:12])


class TokenVote(base.TimeStampedModel):
token = models.ForeignKey(
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@
"@fortawesome/fontawesome-free": "5.15.4",
"@testing-library/react-native": "^8.0.0",
"acorn": "8.6.0",
"adhocracy4": "liqd/adhocracy4#9f13ad262c2286db31c6ec095a49ee3a819fd1c7",
"adhocracy4": "liqd/adhocracy4#447210dd1fb6204bdc75261c1bfaa62de4dee3b6",
"autoprefixer": "10.4.0",
"axios": "0.24.0",
"babel-loader": "8.2.3",
2 changes: 1 addition & 1 deletion requirements/base.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# A4
git+git://github.com/liqd/adhocracy4.git@9f13ad262c2286db31c6ec095a49ee3a819fd1c7#egg=adhocracy4
git+git://github.com/liqd/adhocracy4.git@447210dd1fb6204bdc75261c1bfaa62de4dee3b6#egg=adhocracy4

# Additional requirements
bcrypt==3.2.0