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

More diversity questions #1724

Merged
merged 4 commits into from
Jun 9, 2024
Merged
Show file tree
Hide file tree
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
15 changes: 13 additions & 2 deletions apps/common/fields.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import json

from markupsafe import Markup
from wtforms import IntegerField, SelectField, StringField, ValidationError
from wtforms.widgets import Input, HiddenInput
from wtforms import (
IntegerField,
SelectField,
SelectMultipleField,
StringField,
ValidationError,
)
from wtforms.widgets import Input, HiddenInput, CheckboxInput, ListWidget
from wtforms.widgets.html5 import EmailInput
from wtforms.widgets.core import html_params
from email_validator import validate_email, EmailNotValidError
Expand Down Expand Up @@ -117,3 +123,8 @@ def __call__(self, field, **kwargs):

class StaticField(StringField):
widget = StaticWidget()


class MultiCheckboxField(SelectMultipleField):
widget = ListWidget(prefix_label=False)
option_widget = CheckboxInput()
41 changes: 39 additions & 2 deletions apps/common/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
from flask import current_app as app
from flask_wtf import FlaskForm

from wtforms import SelectField, BooleanField
from wtforms import SelectField, BooleanField, ValidationError
from wtforms.validators import InputRequired

from models.user import UserDiversity
from models.cfp_tag import DEFAULT_TAGS, Tag
from models.purchase import AdmissionTicket

from .fields import HiddenIntegerField
from .fields import HiddenIntegerField, MultiCheckboxField


class Form(FlaskForm):
Expand Down Expand Up @@ -42,6 +42,31 @@ class Meta(FlaskForm.Meta):
AGE_VALUES = ("0-15", "16-25", "26-35", "36-45", "46-55", "56-65", "66+")
AGE_CHOICES = tuple(OPT_OUT + [(v, v) for v in AGE_VALUES])

SEXUALITY_VALUES = (
"straight-or-heterosexual",
"gay-or-lesbian",
"bisexual-or-pansexual",
"other",
)
SEXUALITY_CHOICES = tuple(
OPT_OUT + [(v, v.capitalize().replace("-", " ")) for v in SEXUALITY_VALUES]
)


DISABILITY_CHOICES = tuple(
[
("physical", "Physical disability or mobility issue"),
("vision", "Blindness or a visual impairment not corrected by glasses"),
("hearing", "Deafness or a serious hearing impairment"),
("autism-adhd", "Autistic spectrum condition, Asperger's, or ADHD"),
("long-term", "Long-term illness"),
("mental-health", "Mental health condition"),
("other", "Another condition not mentioned here"),
("none", "None of the above"),
]
)


TOPIC_CHOICES = tuple(NULL_SELECTION + [(v, v.capitalize()) for v in DEFAULT_TAGS])

# FIXME these are matchers for transition from freetext diversity form -> select boxes
Expand Down Expand Up @@ -100,6 +125,8 @@ class DiversityForm(Form):
age = SelectField("Age", default=OPT_OUT[0], choices=AGE_CHOICES)
gender = SelectField("Gender", default=OPT_OUT[0], choices=GENDER_CHOICES)
ethnicity = SelectField("Ethnicity", default=OPT_OUT[0], choices=ETHNICITY_CHOICES)
sexuality = SelectField("Sexuality", default=OPT_OUT[0], choices=SEXUALITY_CHOICES)
disability = MultiCheckboxField("Disability", choices=DISABILITY_CHOICES)

# Track CfP reviewer tags
cfp_tag_0 = SelectField("Topic 1", choices=TOPIC_CHOICES)
Expand All @@ -123,6 +150,8 @@ def update_user(self, user):
user.diversity.age = self.age.data
user.diversity.gender = self.gender.data
user.diversity.ethnicity = self.ethnicity.data
user.diversity.sexuality = self.sexuality.data
user.diversity.disability = self.disability.data

if self.cfp_tags_required:
user.cfp_reviewer_tags = [
Expand All @@ -138,6 +167,8 @@ def set_from_user(self, user):
self.age.data = guess_age(user.diversity.age)
self.gender.data = guess_gender(user.diversity.gender)
self.ethnicity.data = guess_ethnicity(user.diversity.ethnicity)
self.sexuality.data = user.diversity.sexuality
self.disability.data = user.diversity.disability

if self.cfp_tags_required and user.cfp_reviewer_tags:
self.cfp_tag_0.data = user.cfp_reviewer_tags[0].tag
Expand All @@ -146,6 +177,12 @@ def set_from_user(self, user):

return self

def validate_disability(form, field):
if len(field.data) > 1 and "none" in field.data:
raise ValidationError("Cannot select 'no disability' and a disability")
elif len(field.data) > 1 and "" in field.data:
raise ValidationError("Cannot select 'prefer not to say' and a disability")

def validate(self, extra_validators=None):
if not super().validate(extra_validators):
return False
Expand Down
58 changes: 0 additions & 58 deletions css/_base.scss
Original file line number Diff line number Diff line change
Expand Up @@ -226,14 +226,6 @@ div.micro img {
color: #333;
}

.form-control {
background-color: $form-element;
}

.form-horizontal .form-group .help-block {
padding-left: 0.5em;
}

legend {
margin-bottom: 0px;
border-bottom: 1px solid #aaa;
Expand Down Expand Up @@ -384,17 +376,6 @@ a.collapse-toggle:hover .glyphicon { text-decoration: none; }
}
}

input[type="checkbox"].big-checkbox {
width: 20px;
height: 20px;
margin-right: 5px;
}
label.big-checkbox {
/* Increase the target area */
padding: 11px 10px 10px 40px !important;
margin: -4px 0 -10px -40px !important;
vertical-align: 4px;
}

/* Modals for the schedules */
.modal {
Expand All @@ -411,45 +392,6 @@ label.big-checkbox {

.role-description { display: none; }

/* Form tweakery */

fieldset legend {
margin-bottom: 10px;
}

input[type=range] {
appearance: none;
border: none;
box-shadow: none;
background: transparent;
margin-bottom: 6px;
}

input[type=range]::range-track {
appearance: none;
height: 8.4px;
cursor: pointer;
background: $main-link-hover;
border-radius: 3px;
}

input[type=range]:focus::range-track {
background: lighten($main-link-hover, 5%);
}

input[type=range]::range-thumb {
appearance: none;
box-shadow: 1px 1px 1px lighten($main-background, 50%);
border: 1px solid $main-background;
height: 30px;
width: 16px;
border-radius: 3px;
background: $highlight-3-background;
cursor: pointer;
margin-top: -11px;
}


#mailing-list-form #name-field {
display: none;
}
64 changes: 64 additions & 0 deletions css/_forms.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
@use "./_variables.scss" as *;

.form-control {
background-color: $form-element;
}

.form-horizontal .form-group .help-block {
padding-left: 0.5em;
}

input[type="checkbox"] {
width: 20px;
height: 20px;
margin-left: -25px !important;
margin-top: 4px !important;
}

fieldset legend {
margin-bottom: 10px;
}

input[type=range] {
appearance: none;
border: none;
box-shadow: none;
background: transparent;
margin-bottom: 6px;
}

input[type=range]::range-track {
appearance: none;
height: 8.4px;
cursor: pointer;
background: $main-link-hover;
border-radius: 3px;
}

input[type=range]:focus::range-track {
background: lighten($main-link-hover, 5%);
}

input[type=range]::range-thumb {
appearance: none;
box-shadow: 1px 1px 1px lighten($main-background, 50%);
border: 1px solid $main-background;
height: 30px;
width: 16px;
border-radius: 3px;
background: $highlight-3-background;
cursor: pointer;
margin-top: -11px;
}

ul.form-check-input input {
vertical-align: top;
}

ul.form-check-input li {
list-style-type: none;
}

ul.form-check-input label {
font-weight: normal;
}
1 change: 1 addition & 0 deletions css/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
@use "./_buttons.scss";
@use "./_video.scss";
@use "./_panel_grid.scss";
@use "./_forms.scss";

@use "./_about.scss";
@use "./_attendee_content.scss";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""add disability and sexuality to diversity table

Revision ID: 7249f66e2ae0
Revises: e9c68e8f78c2
Create Date: 2024-06-03 23:13:28.010124

"""

# revision identifiers, used by Alembic.
revision = '7249f66e2ae0'
down_revision = 'e9c68e8f78c2'

from alembic import op
import sqlalchemy as sa


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('diversity', sa.Column('disability', sa.String(), nullable=True))
op.add_column('diversity', sa.Column('sexuality', sa.String(), nullable=True))
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('diversity', 'sexuality')
op.drop_column('diversity', 'disability')
# ### end Alembic commands ###
16 changes: 15 additions & 1 deletion models/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -470,13 +470,17 @@ class UserDiversity(BaseModel):
age = db.Column(db.String)
gender = db.Column(db.String)
ethnicity = db.Column(db.String)
disability = db.Column(db.String)
sexuality = db.Column(db.String)

@classmethod
def get_export_data(cls):
valid_ages = []
ages = defaultdict(int)
sexes = defaultdict(int)
ethnicities = defaultdict(int)
disability = defaultdict(int)
sexuality = defaultdict(int)

for row in cls.query:
matches = re.findall(r"\b[0-9]{1,3}\b", row.age)
Expand Down Expand Up @@ -523,11 +527,21 @@ def get_export_data(cls):
else:
ethnicities["other"] += 1

# This doesn't need a matcher because it's already encoded
disability[row.disability] += 1
sexuality[row.sexuality] += 1

ages.update(bucketise(valid_ages, [0, 15, 25, 35, 45, 55, 65]))

data = {
"private": {
"diversity": {"age": ages, "sex": sexes, "ethnicity": ethnicities}
"diversity": {
"age": ages,
"sex": sexes,
"ethnicity": ethnicities,
"disability": disability,
"sexuality": sexuality,
}
},
"tables": ["diversity"],
}
Expand Down
52 changes: 27 additions & 25 deletions templates/_diversityform.html
Original file line number Diff line number Diff line change
@@ -1,29 +1,31 @@
{% from "_formhelpers.html" import render_field %}
{% from "_formhelpers.html" import render_field, render_multi_checkbox %}

{% macro render_diversity_fields(form, current_user) %}
{# Should only be rendered inside a .panel #}

<fieldset>
<div class="panel-heading">
If you're comfortable telling us a little bit about yourself, we'd appreciate it.
This information will only be summarised and compared with previous years, to find out how well we're doing with outreach.
</div>
<div class="panel-heading">
<p></p>
{{ render_field(form.age, True) }}
{{ render_field(form.gender, True) }}
{{ render_field(form.ethnicity, True) }}
{% if current_user.has_permission("cfp_reviewer") %}
<p>
Just so we know that we're reflecting our attendees' interests reasonably well:
please select the three topics that <em>most</em> interest you. Please review
everything you feel able to, this is purely so we can track if there are areas
we need to recruit more reviewers.
</p>
{{ render_field(form.cfp_tag_0, True) }}
{{ render_field(form.cfp_tag_1, True) }}
{{ render_field(form.cfp_tag_2, True) }}
{% endif %}
</div>
</fieldset>
{% if current_user.has_permission("cfp_reviewer") %}
<fieldset>
<h4>CfP reviewer survey</h4>
<p>As you're a reviewer for our Call for Participation, please select the three topics that
<em>most</em> interest you, to help us track the interests of our review panel. Please still
review everything you feel able to.</p>
{{ render_field(form.cfp_tag_0, True) }}
{{ render_field(form.cfp_tag_1, True) }}
{{ render_field(form.cfp_tag_2, True) }}
</fieldset>
{% endif %}
<fieldset>
<h4>Diversity survey</h4>
<p>
If you're comfortable telling us a little bit about yourself, we'd appreciate it if you
filled in our diversity survey. This information will be summarised and used to track how we
can improve the diversity of the community and the accessibility of EMF.
</p>
{{ render_field(form.age, True) }}
{{ render_field(form.gender, True) }}
{{ render_field(form.ethnicity, True) }}
{{ render_field(form.sexuality, True) }}
{% call render_multi_checkbox(form.disability) %}
Please select any of the following that apply to you, or "None of the above":
{% endcall %}
</fieldset>
{% endmacro %}
Loading