Skip to content

Commit

Permalink
feat(votepeloclima): Implemented widget and field to inline array fil…
Browse files Browse the repository at this point in the history
…eds social media anda milestones
  • Loading branch information
sergiomario committed Jul 22, 2024
1 parent 6f8f561 commit d5c195d
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 18 deletions.
35 changes: 33 additions & 2 deletions app/org_eleicoes/votepeloclima/candidature/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from django.utils.translation import gettext_lazy as _
from django.core.exceptions import ValidationError

from django.contrib.postgres.forms import SimpleArrayField
from django_select2.forms import Select2Widget
from captcha.fields import ReCaptchaField

Expand Down Expand Up @@ -184,15 +185,45 @@ def clean(self, value):
return value.replace("on-", "")


class InlineArrayWidget(forms.TextInput):
class InlineArrayWidget(forms.MultiWidget):
template_name = "forms/widgets/inline_array.html"

def __init__(self, widget, size, attrs=None):
widgets = [widget() if isinstance(widget, type) else widget for _ in range(size)]
super().__init__(widgets, attrs)
self.size = size

@property
def media(self):
return forms.Media(
js=[
"https://code.jquery.com/jquery-3.5.1.min.js",
"js/inline-array-widget.js",
],
# css={"screen": select2_css + ["django_select2/django_select2.css"]},
)

def decompress(self, value):
if isinstance(value, list):
return value
if value is None:
return []
return [v.strip() for v in value.split(',')]

def value_from_datadict(self, data, files, name):
values = []
for key, value in data.items():
if key.startswith(f'{name}_'):
values.append(value)
return values

def get_context(self, name, value, attrs):
context = super().get_context(name, value, attrs)
context['widget'].update({'size':self.size})

return context


class InlineArrayField(SimpleArrayField):
def __init__(self, base_field, size=5, delimiter=",", max_length=None, min_length=None, **kwargs):
super().__init__(base_field, delimiter=delimiter, max_length=max_length, min_length=min_length, **kwargs)
self.widget = InlineArrayWidget(widget=base_field.widget, size=size)
14 changes: 11 additions & 3 deletions app/org_eleicoes/votepeloclima/candidature/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
StateCepField,
CityCepField,
CheckboxTextField,
InlineArrayWidget,
InlineArrayField,
)


Expand Down Expand Up @@ -62,7 +62,11 @@ class ProfileForm(DisabledMixin, forms.Form):
gender = forms.CharField(label="Gênero")
color = forms.CharField(label="Raça")
sexuality = forms.CharField(label="Sexualidade", required=False)
social_media = SimpleArrayField(forms.URLField(), widget=InlineArrayWidget())
social_media = InlineArrayField(forms.URLField(required=False), required=False)

def clean_social_media(self):
value = self.cleaned_data['social_media']
return value

class Meta:
title = "Complemente seu perfil"
Expand All @@ -72,7 +76,11 @@ class TrackForm(DisabledMixin, forms.Form):
education = forms.CharField(label="Escolaridade", required=False)
employment = forms.CharField(label="Ocupação", required=False)
short_description = forms.CharField(label="Minibio", widget=forms.Textarea())
milestones = SimpleArrayField(forms.CharField(max_length=140), widget=InlineArrayWidget())
milestones = InlineArrayField(forms.CharField(max_length=140, required=False), required=False)

def clean_milestones(self):
value = self.cleaned_data['milestones']
return value

class Meta:
title = "Sobre sua trajetória"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Generated by Django 4.2 on 2024-07-22 21:30

import django.contrib.postgres.fields
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('candidature', '0005_alter_candidatureflow_candidature_and_more'),
]

operations = [
migrations.AlterModelOptions(
name='candidature',
options={'verbose_name': 'Candidatura'},
),
migrations.AlterModelOptions(
name='candidatureflow',
options={'verbose_name': 'Formulário'},
),
migrations.AddField(
model_name='candidature',
name='milestones',
field=django.contrib.postgres.fields.ArrayField(base_field=models.CharField(blank=True, max_length=140), blank=True, null=True, size=5),
),
migrations.AddField(
model_name='candidature',
name='social_media',
field=django.contrib.postgres.fields.ArrayField(base_field=models.URLField(blank=True), blank=True, null=True, size=5),
),
]
3 changes: 3 additions & 0 deletions app/org_eleicoes/votepeloclima/candidature/models.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from django.db import models
from django.contrib.auth.models import User
from django.contrib.postgres.fields import ArrayField
from django.core.serializers.json import DjangoJSONEncoder


Expand Down Expand Up @@ -28,10 +29,12 @@ class Candidature(models.Model):
gender = models.CharField(max_length=30)
color = models.CharField(max_length=30)
sexuality = models.CharField(max_length=30, null=True, blank=True)
social_media = ArrayField(models.URLField(blank=True), size=5, null=True, blank=True)
# Step 4
education = models.CharField(max_length=50, null=True, blank=True)
employment = models.CharField(max_length=50, null=True, blank=True)
short_description = models.TextField()
milestones = ArrayField(models.CharField(max_length=140, blank=True), size=5, null=True, blank=True)
# Step 5
flags = models.JSONField(blank=True)
# Step 6
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,45 @@
(function ($) {
"use strict";
$(function () {
const maxSize = $('#inline-array-add').data('size');
const name = $('#inline-array').data('name');

function updateInlineArray() {
const totalInputs = $('#inline-array .d-flex').length;
if (totalInputs === 1) {
$('#inline-array .d-flex').find('button').hide();
} else {
$('#inline-array .d-flex').find('button').show();
}

if (totalInputs === maxSize) {
$('#inline-array-add').attr('disabled', 'disabled');
} else {
$('#inline-array-add').removeAttr('disabled');
}

$('#inline-array .d-flex').each((i, item) => {
$(item).find('input').attr('name', `${name}_${i}`)
})
}

$('#inline-array-add').click(() => {
const $div = $('#inline-array .d-flex').first().clone();
$div.find('input').val('');
$('#inline-array').append($div);
const totalInputs = $('#inline-array .d-flex').length;
if (totalInputs < maxSize) {
const $div = $('#inline-array .d-flex').first().clone();
$div.find('input').val('');
$div.find('button').show();
$('#inline-array').append($div);
updateInlineArray();
}
});

function inlineDelete(target) {
$(target).parent().remove();
updateInlineArray();
};

window.inlineDelete=inlineDelete;
updateInlineArray();
window.inlineDelete = inlineDelete;
});
}(jQuery));
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
<div id="inline-array">
<div class="d-flex">
<input type="{{widget.type}}"{% include "django/forms/widgets/attrs.html" %}/>
<button type="button" onclick="inlineDelete(this)">
Remover
</button>
</div>
<div id="inline-array" data-name="{{ widget.name }}">
{% for widget in widget.subwidgets %}
{% if widget.value or forloop.counter < 3 %}
<div class="d-flex mb-2">
<input type="{{ widget.type }}" name="{{ widget.name }}" id="{{ widget.id }}"{% if widget.value != None %} value="{{ widget.value|stringformat:'s' }}"{% endif %}{% include "django/forms/widgets/attrs.html" %}/>
<button type="button" class="btn btn-danger ml-2" onclick="inlineDelete(this)">
Remover
</button>
</div>
{% endif %}
{% endfor %}
</div>
<button type="button" id="inline-array-add">
<button type="button" id="inline-array-add" class="btn btn-primary mt-2" data-size="{{ widget.size }}">
Adicionar
</button>
<input type="hidden" name="{{ widget.name }}"{% if widget.value != None %} value="{{ widget.value|stringformat:'s' }}"{% endif %}{% include "django/forms/widgets/attrs.html" %}>

0 comments on commit d5c195d

Please sign in to comment.