Skip to content
Snippets Groups Projects
Commit b09246ef authored by Dan Braghis's avatar Dan Braghis
Browse files

Add streamform and fields

parent 40475ba8
No related branches found
No related tags found
No related merge requests found
......@@ -3,6 +3,7 @@ from django.utils.html import mark_safe
from wagtail.contrib.modeladmin.helpers import PermissionHelper
from wagtail.contrib.modeladmin.options import ModelAdmin, ModelAdminGroup
from opentech.apply.review.models import ReviewForm
from .admin_helpers import (
ButtonsWithPreview,
FormsFundRoundListFilter,
......@@ -67,7 +68,12 @@ class ApplicationFormAdmin(ModelAdmin):
return mark_safe('<br>'.join(rows))
class ReviewFormAdmin(ModelAdmin):
model = ReviewForm
menu_icon = 'form'
class ApplyAdminGroup(ModelAdminGroup):
menu_label = 'Apply'
menu_icon = 'folder-open-inverse'
items = (RoundAdmin, FundAdmin, LabAdmin, ApplicationFormAdmin, CategoryAdmin)
items = (RoundAdmin, FundAdmin, LabAdmin, ApplicationFormAdmin, ReviewFormAdmin, CategoryAdmin)
import json
from django import forms
from django.forms import widgets
from django.utils.translation import ugettext_lazy as _
from wagtail.core.blocks import RichTextBlock
from opentech.apply.review.options import RATE_CHOICES, RECOMMENDATION_CHOICES
from opentech.apply.stream_forms.blocks import OptionalFormFieldBlock, CharFieldBlock, TextFieldBlock
from opentech.apply.utils.blocks import CustomFormFieldsBlock, MustIncludeFieldBlock
class ScoredAnswerWidget(forms.MultiWidget):
def __init__(self, attrs=None):
text_attrs = attrs if attrs is not None else {}
text_attrs['rows'] = 5
_widgets = (
widgets.Textarea(attrs=text_attrs),
widgets.Select(attrs=attrs, choices=RATE_CHOICES),
)
super().__init__(_widgets, attrs)
def decompress(self, value):
if value:
return json.loads(value)
return [None, None]
class ScoredAnswerField(forms.MultiValueField):
widget = ScoredAnswerWidget
def __init__(self, *args, **kwargs):
fields = (
forms.CharField(),
forms.ChoiceField(choices=RATE_CHOICES),
)
super().__init__(fields=fields, *args, **kwargs)
def compress(self, data_list):
return json.dumps(data_list)
class ScoreFieldBlock(OptionalFormFieldBlock):
field_class = ScoredAnswerField
class Meta:
label = _('Score')
icon = 'order'
class ReviewMustIncludeFieldBlock(MustIncludeFieldBlock):
pass
class RecommendationBlock(ReviewMustIncludeFieldBlock):
name = 'Recommendation'
description = 'Overall recommendation'
field_class = forms.ChoiceField
class Meta:
icon = 'pick'
def get_field_kwargs(self, struct_value):
kwargs = super().get_field_kwargs(struct_value)
kwargs['choices'] = RECOMMENDATION_CHOICES
return kwargs
class RecommendationCommentsBlock(ReviewMustIncludeFieldBlock):
name = 'Comments'
description = 'Recommendation comments'
class Meta:
icon = 'openquote'
class ReviewCustomFormFieldsBlock(CustomFormFieldsBlock):
char = CharFieldBlock(group=_('Fields'))
text = TextFieldBlock(group=_('Fields'))
text_markup = RichTextBlock(group=_('Fields'), label=_('Paragraph'))
score = ScoreFieldBlock(group=_('Fields'))
required_blocks = ReviewMustIncludeFieldBlock.__subclasses__()
# Generated by Django 2.0.2 on 2018-07-19 10:50
import django.contrib.postgres.fields.jsonb
import django.core.serializers.json
from django.db import migrations, models
import wagtail.core.blocks
import wagtail.core.blocks.static_block
import wagtail.core.fields
class Migration(migrations.Migration):
dependencies = [
('review', '0004_review_is_draft'),
]
operations = [
migrations.CreateModel(
name='ReviewForm',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255)),
('form_fields', wagtail.core.fields.StreamField((('rich_text', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.core.blocks.TextBlock(label='Default value', required=False))), group='Fields')), ('char', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False)), ('format', wagtail.core.blocks.ChoiceBlock(choices=[('email', 'Email'), ('url', 'URL')], label='Format', required=False)), ('default_value', wagtail.core.blocks.CharBlock(label='Default value', required=False))), group='Fields')), ('text', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.core.blocks.TextBlock(label='Default value', required=False))), group='Fields')), ('text_markup', wagtail.core.blocks.RichTextBlock(group='Fields', label='Paragraph')), ('score', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False))), group='Fields')), ('Recommendation', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('info', wagtail.core.blocks.static_block.StaticBlock())), group='Required')), ('Comments', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('info', wagtail.core.blocks.static_block.StaticBlock())), group='Required'))))),
],
),
migrations.AddField(
model_name='review',
name='form_data',
field=django.contrib.postgres.fields.jsonb.JSONField(default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder),
),
migrations.AddField(
model_name='review',
name='form_fields',
field=wagtail.core.fields.StreamField((('rich_text', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.core.blocks.TextBlock(label='Default value', required=False))), group='Fields')), ('char', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False)), ('format', wagtail.core.blocks.ChoiceBlock(choices=[('email', 'Email'), ('url', 'URL')], label='Format', required=False)), ('default_value', wagtail.core.blocks.CharBlock(label='Default value', required=False))), group='Fields')), ('text', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False)), ('default_value', wagtail.core.blocks.TextBlock(label='Default value', required=False))), group='Fields')), ('text_markup', wagtail.core.blocks.RichTextBlock(group='Fields', label='Paragraph')), ('score', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('required', wagtail.core.blocks.BooleanBlock(label='Required', required=False))), group='Fields')), ('Recommendation', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('info', wagtail.core.blocks.static_block.StaticBlock())), group='Required')), ('Comments', wagtail.core.blocks.StructBlock((('field_label', wagtail.core.blocks.CharBlock(label='Label')), ('help_text', wagtail.core.blocks.TextBlock(label='Help text', required=False)), ('info', wagtail.core.blocks.static_block.StaticBlock())), group='Required')))),
preserve_default=False,
),
]
from django.conf import settings
from django.contrib.postgres.fields import JSONField
from django.core.serializers.json import DjangoJSONEncoder
from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.urls import reverse
from wagtail.admin.edit_handlers import FieldPanel, StreamFieldPanel
from wagtail.core.fields import StreamField
from opentech.apply.activity.models import Activity
from opentech.apply.review.options import YES, NO, MAYBE, RECOMMENDATION_CHOICES
from opentech.apply.users.models import User
from .blocks import ReviewCustomFormFieldsBlock, ReviewMustIncludeFieldBlock
class ReviewForm(models.Model):
name = models.CharField(max_length=255)
form_fields = StreamField(ReviewCustomFormFieldsBlock())
content_panels = [
FieldPanel('name'),
StreamFieldPanel('form_fields'),
]
def process_form_submission(self, form):
return Review.objects.create(
form_data=form.cleaned_data,
form_fields=self.form_fields,
)
class ReviewQuerySet(models.QuerySet):
def submitted(self):
......@@ -57,7 +76,12 @@ class Review(models.Model):
settings.AUTH_USER_MODEL,
on_delete=models.PROTECT,
)
# TODO remove when handling submissions
review = JSONField()
form_data = JSONField(default=dict, encoder=DjangoJSONEncoder)
form_fields = StreamField(ReviewCustomFormFieldsBlock())
recommendation = models.IntegerField(verbose_name="Recommendation", choices=RECOMMENDATION_CHOICES, default=0)
score = models.DecimalField(max_digits=10, decimal_places=1, default=0)
is_draft = models.BooleanField(default=False, verbose_name="Draft")
......@@ -71,10 +95,29 @@ class Review(models.Model):
return reverse('apply:reviews:review', args=(self.id,))
def __str__(self):
return f'Review for {self.submission.title} by {self.author!s}'
return f'Review for {self.page.title} by {self.author!s}'
def __repr__(self):
return f'<{self.__class__.__name__}: {str(self.review)}>'
return f'<{self.__class__.__name__}: {str(self.form_data)}>'
@property
def must_include(self):
return {
field.block.name: field.id
for field in self.form_fields
if isinstance(field.block, ReviewMustIncludeFieldBlock)
}
def clean_submission(self):
for field_name, field_id in self.must_include.items():
response = self.form_data.pop(field_id, None)
if response:
self.form_data[field_name] = response
def save(self, *args, **kwargs):
self.clean_submission()
super().save(*args, **kwargs)
@receiver(post_save, sender=Review)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment