Skip to content
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
18 changes: 18 additions & 0 deletions portal/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,28 @@ class CustomSignupForm(SignupForm):
label="Last Name",
widget=forms.TextInput(attrs={"placeholder": "Last Name"}),
)
coc_agreement = forms.BooleanField(
required=True,
label="I agree to the Code of Conduct",
help_text="You must agree to our Code of Conduct to use this site.",
)
tos_agreement = forms.BooleanField(
required=True,
label="I agree to the Terms of Service",
help_text="You must agree to our Terms of Service to use this site.",
)

def save(self, request):
user = super().save(request)
user.first_name = self.cleaned_data["first_name"]
user.last_name = self.cleaned_data["last_name"]
user.save()

from portal_account.models import PortalProfile

portal_profile, created = PortalProfile.objects.get_or_create(user=user)
portal_profile.coc_agreement = self.cleaned_data.get("coc_agreement", False)
portal_profile.tos_agreement = self.cleaned_data.get("tos_agreement", False)
portal_profile.save()

return user
4 changes: 3 additions & 1 deletion portal_account/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ class PortalProfileAdmin(admin.ModelAdmin):
"user__last_name",
"pronouns",
"coc_agreement",
"tos_agreement",
)
search_fields = ("user__email", "user__first_name", "user__last_name")
list_filter = ("pronouns", "coc_agreement")
list_filter = ("pronouns", "coc_agreement", "tos_agreement")
readonly_fields = ("coc_agreement", "tos_agreement")


admin.site.register(PortalProfile, PortalProfileAdmin)
5 changes: 4 additions & 1 deletion portal_account/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ class PortalProfileForm(ModelForm):
first_name = forms.CharField()
last_name = forms.CharField()
email = forms.CharField(disabled=True)
coc_agreement = forms.BooleanField(disabled=True, required=False)
tos_agreement = forms.BooleanField(disabled=True, required=False)

class Meta:
model = PortalProfile
fields = ["pronouns", "profile_picture", "coc_agreement"]
fields = ["pronouns", "profile_picture", "coc_agreement", "tos_agreement"]

def clean(self):
cleaned_data = super().clean()
Expand All @@ -40,6 +42,7 @@ def __init__(self, *args, **kwargs):
"pronouns",
"profile_picture",
"coc_agreement",
"tos_agreement",
]
)

Expand Down
18 changes: 18 additions & 0 deletions portal_account/migrations/0003_portalprofile_tos_agreement.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 5.1.8 on 2025-05-08 17:41

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("portal_account", "0002_portalprofile_profile_picture"),
]

operations = [
migrations.AddField(
model_name="portalprofile",
name="tos_agreement",
field=models.BooleanField(default=False),
),
]
1 change: 1 addition & 0 deletions portal_account/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class PortalProfile(BaseModel):
user = models.OneToOneField(User, on_delete=models.CASCADE)
pronouns = models.CharField(max_length=100, blank=True, null=True)
coc_agreement = models.BooleanField(default=False)
tos_agreement = models.BooleanField(default=False)
profile_picture = models.ImageField(
upload_to="profile_pictures", blank=True, null=True
)
Expand Down
70 changes: 54 additions & 16 deletions templates/account/signup.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{% extends "account/base_entrance.html" %}
{% load allauth i18n %}
{% load django_bootstrap5 %}
{% load widget_tweaks %}
{% block head_title %}
{% trans "Signup" %}
{% endblock head_title %}
Expand All @@ -20,21 +19,60 @@
{% endelement %}
{% if not SOCIALACCOUNT_ONLY %}
{% url 'account_signup' as action_url %}

{% element form form=form method="post" action=action_url tags="entrance,signup" %}
{% slot body %}
{% csrf_token %}
{% bootstrap_form form show_help=False layout="horizontal" %}
{{ redirect_field }}
{% endslot %}
{% slot actions %}
{% element button type="submit" %}
{% trans "Sign Up" %}
{% endelement %}
{% endslot %}
{% endelement %}

<form method="post" action="{{ action_url }}" class="entrance signup">
{% csrf_token %}

<h3 class="mb-3">Personal Information</h3>
{% bootstrap_field form.username %}
{% bootstrap_field form.email %}
{% bootstrap_field form.first_name %}
{% bootstrap_field form.last_name %}

<h3 class="mb-3">Password</h3>
{% bootstrap_field form.password1 %}
{% bootstrap_field form.password2 %}

<h3 class="mb-3">Agreements</h3>
<div class="card mb-3">
<div class="card-body">
<p>By creating an account, you are agreeing to our terms and conditions.</p>

<div class="form-check mb-3">
{{ form.coc_agreement }}
<label class="form-check-label" for="{{ form.coc_agreement.id_for_label }}">
I agree to the <a href="https://global-conference-2025.netlify.app/en/coc/" target="_blank" rel="noopener noreferrer">Code of Conduct</a>
</label>
{% if form.coc_agreement.errors %}
<div class="invalid-feedback d-block">
{{ form.coc_agreement.errors }}
</div>
{% endif %}
<div class="form-text">{{ form.coc_agreement.help_text }}</div>
</div>

<div class="form-check">
{{ form.tos_agreement }}
<label class="form-check-label" for="{{ form.tos_agreement.id_for_label }}">
I agree to the <a href="https://pyladiescon-portal-docs.netlify.app/policies/terms_of_use/" target="_blank" rel="noopener noreferrer">Terms of Service</a>
</label>
{% if form.tos_agreement.errors %}
<div class="invalid-feedback d-block">
{{ form.tos_agreement.errors }}
</div>
{% endif %}
<div class="form-text">{{ form.tos_agreement.help_text }}</div>
</div>
</div>
</div>

{{ redirect_field }}

<div class="d-grid gap-2">
<button class="btn btn-primary btn-lg" type="submit">{% trans "Sign Up" %}</button>
</div>
</form>
{% endif %}

{% if PASSKEY_SIGNUP_ENABLED %}
{% element hr %}
{% endelement %}
Expand All @@ -45,4 +83,4 @@
{% if SOCIALACCOUNT_ENABLED %}
{% include "socialaccount/snippets/login.html" with page_layout="entrance" %}
{% endif %}
{% endblock content %}
{% endblock content %}
12 changes: 12 additions & 0 deletions templates/portal_account/portalprofile_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,18 @@ <h5 class="card-title mb-0">
{% endif %}
</div>
</div>
<div class="row mb-3">
<div class="col-md-3 fw-bold">
Terms of Service Agreement:
</div>
<div class="col-md-9">
{% if object.tos_agreement %}
Agreed
{% else %}
Not agreed
{% endif %}
</div>
</div>
</div>
</div>
<div class="mt-4">
Expand Down
2 changes: 2 additions & 0 deletions tests/portal/test_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ def form_data(self):
"password2": "securepassword123",
"first_name": "Test",
"last_name": "User",
"coc_agreement": True,
"tos_agreement": True,
}

@pytest.fixture
Expand Down
2 changes: 0 additions & 2 deletions tests/portal_account/test_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ def test_profile_form_saved(self, portal_user):
"first_name": "new fname",
"last_name": "new lname",
"pronouns": "pp",
"coc_agreement": True,
}
form = PortalProfileForm(user=portal_user, data=form_data)
assert form.is_valid()
Expand All @@ -24,7 +23,6 @@ def test_profile_form_saved(self, portal_user):
portal_profile = PortalProfile.objects.get(user=portal_user)
assert portal_profile.user == portal_user
assert portal_profile.pronouns == form_data["pronouns"]
assert portal_profile.coc_agreement is True
assert portal_profile.user.first_name == form_data["first_name"]
assert portal_profile.user.last_name == form_data["last_name"]

Expand Down