Skip to content

Commit

Permalink
Add image columns to tables (#897)
Browse files Browse the repository at this point in the history
* feat: initial set up for result images

* feat: add migration for result images field

* feat: change rendering of result image field

* feat: add extra mimetype to import formats

* feat: add helper methods for model classes

* feat: add columns to lists

* chore: change header title text
  • Loading branch information
dodumosu authored Sep 14, 2022
1 parent 00b102f commit 70354cd
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 4 deletions.
6 changes: 5 additions & 1 deletion apollo/formsframework/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def __call__(self, form, field):
and not math.isnan(data)
and (self.min is None or data >= self.min)
and (
self.max is None or self.value_is_null(data) or data <= self.max
self.max is None or self.value_is_null(data) or data <= self.max # noqa
)
):
return
Expand Down Expand Up @@ -435,6 +435,10 @@ class FormForm(SecureForm):
vote_shares = wtforms.SelectMultipleField(
_('Vote Shares'),
description=_('Questions representing election results.')) # noqa
result_images = wtforms.SelectMultipleField(
_('Result Images'),
description=_('Questions representing election result images.') # noqa
)


class FormImportForm(SecureForm):
Expand Down
10 changes: 10 additions & 0 deletions apollo/formsframework/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ class Form(Resource):
registered_voters_tag = db.Column(db.String)
blank_votes_tag = db.Column(db.String)
vote_shares = db.Column(JSONB)
result_images = db.Column(JSONB)
show_moment = db.Column(db.Boolean, default=False)
show_map = db.Column(db.Boolean, default=False)
show_progress = db.Column(db.Boolean, default=False)
Expand Down Expand Up @@ -175,6 +176,15 @@ def get_group_tags(self, group_name, field_types=FIELD_TYPES):

return tags

@property
def has_image_fields(self):
img_tags = [
tag for tag in self.tags
if self.get_field_by_tag(tag)['type'] == 'image'
]

return len(img_tags) > 0

def to_xml(self):
root = HTML_E.html()
head = HTML_E.head(HTML_E.title(self.name))
Expand Down
6 changes: 6 additions & 0 deletions apollo/formsframework/views_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,12 @@ def edit_form(view, form_id):
[(tag, tag) for tag in form.tags]
web_form.vote_shares.choices = [('', '')] + \
[(tag, tag) for tag in form.tags]
web_form.result_images.choices = [('', '')] + \
[
(tag, tag)
for tag in form.tags
if form.get_field_by_tag(tag).get('type') == 'image'
]

if not web_form.validate_on_submit():
context = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@
<th scope="col" class="text-center"><abbr title="{{ _('Phone Confirmation') }}"><i class="fa fa-mobile-alt"></i></abbr></th>
<th scope="col" class="text-center"><abbr title="{{ _('Quarantine Status') }}"><i class="fa fa-exclamation-triangle"></i></abbr></th>
<th scope="col" class="text-center"><abbr title="{{ _('Geolocation') }}"><i class="fa fa-globe"></i></abbr></th>
{% if form.has_image_fields %}<th class="text-center" scope="col"><abbr title="{{ _('Any Image Uploaded?') }}"><i class="fa fa-camera-retro"></i></abbr></th>{% endif %}
{% if form.result_images %}<th class="text-center" scope="col"><abbr title="{{ _('Number of Results Images Uploaded') }}"><i class="fa fa-images"></i></abbr></th>{% endif %}
</tr>
{% endmacro %}
{% macro submission_items(submissions, form, form_fields, location_types, perms) %}
Expand Down Expand Up @@ -191,6 +193,18 @@
<i class="fa fa-map-marker text-black-50" aria-hidden="true" title="{{ _('No GPS') }}"></i>
{% endif %}
</td>
{% if form.has_image_fields %}
<td class="text-center">
{% if submission.has_image_data() %}
<i class="fas fa-image text-primary" aria-hidden="true" title="{{ _('One or more images uploaded') }}"></i>
{% else %}
<i class="far fa-image text-black-50" aria-hidden="true" title="{{ _('No image uploaded') }}"></i>
{% endif %}
</td>
{% endif %}
{% if form.result_images %}
<td class="text-center">{{ submission.get_result_image_count() }}</td>
{% endif %}
</tr>
{% else %}
{%- if perms.edit_submission.can() %}
Expand All @@ -200,13 +214,15 @@
{%- else %}
{%- set cspan = 9 if form.show_moment else 8 %}
{%- endif %}
{%- if form.has_image_fields %}{% set cspan = cspan + 1 %}{% endif -%}
{%- if form.result_images %}{% set cspan = cspan + 1 %}{% endif -%}
{%- set colspan = cspan + (location_types|length) + form.data.groups|length -%}
<tr class="table-warning">
<td class="text-center text-muted" colspan="{{ colspan }}">{{ _('No Data Available') }}</td>
</tr>
{% else %}
{%- set cspan = 10 if form.show_moment else 9 %}
{%- set colspan = cspan + (location_types|length) + form_fields|length -%}
{%- set colspan = cspan + (location_types|length) + form_fields|length + (1 if form.has_image_fields else 0) -%}
<tr class="table-warning">
<td class="text-center text-muted" colspan="{{ colspan }}">{{ _('No Data Available') }}</td>
</tr>
Expand All @@ -218,13 +234,15 @@
{%- else %}
{%- set cspan = 8 if form.show_moment else 7 %}
{%- endif %}
{%- if form.has_image_fields %}{% set cspan = cspan + 1 %}{% endif -%}
{%- if form.result_images %}{% set cspan = cspan + 1 %}{% endif -%}
{%- set colspan = cspan + (location_types|length) + form.data.groups|length -%}
<tr class="table-warning">
<td class="text-center text-muted" colspan="{{ colspan }}">{{ _('No Data Available') }}</td>
</tr>
{% else %}
{%- set cspan = 9 if form.show_moment else 8 %}
{%- set colspan = cspan + (location_types|length) + form_fields|length -%}
{%- set colspan = cspan + (location_types|length) + form_fields|length + (1 if form.has_image_fields else 0) -%}
<tr class="table-warning">
<td class="text-center text-muted" colspan="{{ colspan }}">{{ _('No Data Available') }}</td>
</tr>
Expand Down
1 change: 1 addition & 0 deletions apollo/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
CSV_MIMETYPES = [
"text/csv",
"application/csv",
"text/plain",
"text/x-csv",
"application/x-csv",
"text/comma-separated-values",
Expand Down
17 changes: 17 additions & 0 deletions apollo/submissions/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,23 @@ def master(self):

return self._master

def has_image_data(self):
image_field_tags = [
tag for tag in self.form.tags
if self.form.get_field_by_tag(tag).get('type') == 'image'
]

image_data = [self.data.get(tag) for tag in image_field_tags]
return any(image_data)

def get_result_image_count(self):
result_fields = self.form.result_images or []

if not result_fields:
return 0

return sum([bool(self.data.get(tag)) for tag in result_fields])


class SubmissionComment(BaseModel):
__tablename__ = 'submission_comment'
Expand Down
2 changes: 1 addition & 1 deletion apollo/templates/admin/form_edit.html
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ <h5 class="card-header">
<div class="col-8">
{%- if field.name in ['form_type', 'accredited_voters_tag', 'blank_votes_tag', 'invalid_votes_tag', 'registered_voters_tag'] %}
{{ field(class_='form-control custom-select is-invalid' if field.errors else 'form-control custom-select', **{'aria-describedby': '{}_help'.format(field.id)}) }}
{% elif field.name == 'vote_shares' %}
{% elif field.name in ['vote_shares', 'result_images'] %}
{{ field(class_='form-control select2', **{'aria-describedby': '{}_help'.format(field.id)}) }}
{% else %}
{{ field(class_='form-control is-invalid' if field.errors else 'form-control', **{'aria-describedby': '{}_help'.format(field.id)}) }}
Expand Down
35 changes: 35 additions & 0 deletions migrations/versions/690fb1fe46b4_add_result_images_field.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"""add result images field
Revision ID: 690fb1fe46b4
Revises: c4166678fb79
Create Date: 2022-09-05 08:22:51.061235
"""
import sqlalchemy as sa
from alembic import op
from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision = "690fb1fe46b4"
down_revision = "c4166678fb79"
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column(
"form",
sa.Column(
"result_images",
postgresql.JSONB(astext_type=sa.Text()),
nullable=True,
),
)
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column("form", "result_images")
# ### end Alembic commands ###

0 comments on commit 70354cd

Please sign in to comment.