codeforlife-portal 7.3.7__py2.py3-none-any.whl → 7.4.0__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of codeforlife-portal might be problematic. Click here for more details.
- cfl_common/common/app_settings.py +0 -1
- cfl_common/common/helpers/emails.py +153 -36
- cfl_common/common/mail.py +5 -0
- {codeforlife_portal-7.3.7.dist-info → codeforlife_portal-7.4.0.dist-info}/METADATA +2 -2
- {codeforlife_portal-7.3.7.dist-info → codeforlife_portal-7.4.0.dist-info}/RECORD +30 -29
- example_project/portal_test_settings.py +1 -0
- example_project/settings.py +1 -0
- portal/__init__.py +1 -1
- portal/context_processors.py +5 -1
- portal/forms/dotmailer.py +39 -4
- portal/static/portal/img/rr_advanced.png +0 -0
- portal/static/portal/js/common.js +35 -5
- portal/static/portal/sass/modules/_colours.scss +3 -0
- portal/static/portal/sass/modules/_levels.scss +1 -1
- portal/static/portal/sass/modules/_mixins.scss +5 -0
- portal/static/portal/sass/partials/_buttons.scss +31 -3
- portal/static/portal/sass/partials/_header.scss +7 -6
- portal/static/portal/sass/partials/_popup.scss +7 -2
- portal/templates/portal/base.html +12 -3
- portal/templates/portal/home_learning.html +8 -7
- portal/templates/portal/partials/donate_popup.html +46 -0
- portal/templates/portal/partials/header.html +34 -30
- portal/tests/test_emails.py +17 -22
- portal/tests/{test_newsletter_footer.py → test_global_forms.py} +17 -1
- portal/urls.py +2 -0
- portal/views/dotmailer.py +30 -2
- portal/views/teacher/dashboard.py +174 -57
- {codeforlife_portal-7.3.7.dist-info → codeforlife_portal-7.4.0.dist-info}/LICENSE.md +0 -0
- {codeforlife_portal-7.3.7.dist-info → codeforlife_portal-7.4.0.dist-info}/WHEEL +0 -0
- {codeforlife_portal-7.3.7.dist-info → codeforlife_portal-7.4.0.dist-info}/top_level.txt +0 -0
|
@@ -8,7 +8,6 @@ DOTDIGITAL_AUTH = getattr(settings, "DOTDIGITAL_AUTH", "")
|
|
|
8
8
|
|
|
9
9
|
# Dotmailer URLs for adding users to the newsletter address book
|
|
10
10
|
DOTMAILER_CREATE_CONTACT_URL = getattr(settings, "DOTMAILER_CREATE_CONTACT_URL", "")
|
|
11
|
-
DOTMAILER_MAIN_ADDRESS_BOOK_URL = getattr(settings, "DOTMAILER_MAIN_ADDRESS_BOOK_URL", "")
|
|
12
11
|
DOTMAILER_TEACHER_ADDRESS_BOOK_URL = getattr(settings, "DOTMAILER_TEACHER_ADDRESS_BOOK_URL", "")
|
|
13
12
|
DOTMAILER_STUDENT_ADDRESS_BOOK_URL = getattr(settings, "DOTMAILER_STUDENT_ADDRESS_BOOK_URL", "")
|
|
14
13
|
DOTMAILER_NO_ACCOUNT_ADDRESS_BOOK_URL = getattr(settings, "DOTMAILER_NO_ACCOUNT_ADDRESS_BOOK_URL", "")
|
|
@@ -5,7 +5,12 @@ from uuid import uuid4
|
|
|
5
5
|
|
|
6
6
|
import jwt
|
|
7
7
|
from common import app_settings
|
|
8
|
-
from common.mail import
|
|
8
|
+
from common.mail import (
|
|
9
|
+
address_book_ids,
|
|
10
|
+
campaign_ids,
|
|
11
|
+
django_send_email,
|
|
12
|
+
send_dotdigital_email,
|
|
13
|
+
)
|
|
9
14
|
from common.models import Student, Teacher
|
|
10
15
|
from django.conf import settings
|
|
11
16
|
from django.contrib.auth.models import User
|
|
@@ -15,9 +20,15 @@ from django.utils import timezone
|
|
|
15
20
|
from requests import delete, get, post, put
|
|
16
21
|
from requests.exceptions import RequestException
|
|
17
22
|
|
|
18
|
-
NOTIFICATION_EMAIL =
|
|
19
|
-
|
|
20
|
-
|
|
23
|
+
NOTIFICATION_EMAIL = (
|
|
24
|
+
"Code For Life Notification <" + app_settings.EMAIL_ADDRESS + ">"
|
|
25
|
+
)
|
|
26
|
+
VERIFICATION_EMAIL = (
|
|
27
|
+
"Code For Life Verification <" + app_settings.EMAIL_ADDRESS + ">"
|
|
28
|
+
)
|
|
29
|
+
PASSWORD_RESET_EMAIL = (
|
|
30
|
+
"Code For Life Password Reset <" + app_settings.EMAIL_ADDRESS + ">"
|
|
31
|
+
)
|
|
21
32
|
INVITE_FROM = "Code For Life Invitation <" + app_settings.EMAIL_ADDRESS + ">"
|
|
22
33
|
|
|
23
34
|
|
|
@@ -41,7 +52,9 @@ def generate_token_for_email(email: str, new_email: str = ""):
|
|
|
41
52
|
"email": email,
|
|
42
53
|
"new_email": new_email,
|
|
43
54
|
"email_verification_token": uuid4().hex[:30],
|
|
44
|
-
"expires": (
|
|
55
|
+
"expires": (
|
|
56
|
+
timezone.now() + datetime.timedelta(hours=1)
|
|
57
|
+
).timestamp(),
|
|
45
58
|
},
|
|
46
59
|
settings.SECRET_KEY,
|
|
47
60
|
algorithm="HS256",
|
|
@@ -62,10 +75,21 @@ def send_email(
|
|
|
62
75
|
plaintext_template="email.txt",
|
|
63
76
|
html_template="email.html",
|
|
64
77
|
):
|
|
65
|
-
django_send_email(
|
|
78
|
+
django_send_email(
|
|
79
|
+
sender,
|
|
80
|
+
recipients,
|
|
81
|
+
subject,
|
|
82
|
+
text_content,
|
|
83
|
+
title,
|
|
84
|
+
replace_url,
|
|
85
|
+
plaintext_template,
|
|
86
|
+
html_template,
|
|
87
|
+
)
|
|
66
88
|
|
|
67
89
|
|
|
68
|
-
def send_verification_email(
|
|
90
|
+
def send_verification_email(
|
|
91
|
+
request, user, data, new_email=None, age=None, school=None
|
|
92
|
+
):
|
|
69
93
|
"""
|
|
70
94
|
Sends emails relating to email address verification.
|
|
71
95
|
|
|
@@ -98,18 +122,30 @@ def send_verification_email(request, user, data, new_email=None, age=None, schoo
|
|
|
98
122
|
url = f"{request.build_absolute_uri(reverse('verify_email', kwargs={'token': verification}))}"
|
|
99
123
|
|
|
100
124
|
send_dotdigital_email(
|
|
101
|
-
campaign_ids["verify_released_student"],
|
|
102
|
-
|
|
125
|
+
campaign_ids["verify_released_student"],
|
|
126
|
+
[user.email],
|
|
127
|
+
personalization_values={
|
|
128
|
+
"VERIFICATION_LINK": url,
|
|
129
|
+
"SCHOOL_NAME": school.name,
|
|
130
|
+
},
|
|
103
131
|
)
|
|
104
132
|
else:
|
|
105
133
|
url = f"{request.build_absolute_uri(reverse('verify_email', kwargs={'token': verification}))}"
|
|
106
134
|
|
|
107
135
|
send_dotdigital_email(
|
|
108
|
-
campaign_ids["verify_new_user"],
|
|
136
|
+
campaign_ids["verify_new_user"],
|
|
137
|
+
[user.email],
|
|
138
|
+
personalization_values={"VERIFICATION_LINK": url},
|
|
109
139
|
)
|
|
110
140
|
|
|
111
141
|
if _newsletter_ticked(data):
|
|
112
|
-
add_to_dotmailer(
|
|
142
|
+
add_to_dotmailer(
|
|
143
|
+
user.first_name,
|
|
144
|
+
user.last_name,
|
|
145
|
+
user.email,
|
|
146
|
+
address_book_ids["newsletter"],
|
|
147
|
+
DotmailerUserType.TEACHER,
|
|
148
|
+
)
|
|
113
149
|
# if the user is an independent student
|
|
114
150
|
else:
|
|
115
151
|
if age < 13:
|
|
@@ -117,29 +153,50 @@ def send_verification_email(request, user, data, new_email=None, age=None, schoo
|
|
|
117
153
|
send_dotdigital_email(
|
|
118
154
|
campaign_ids["verify_new_user_via_parent"],
|
|
119
155
|
[user.email],
|
|
120
|
-
personalization_values={
|
|
156
|
+
personalization_values={
|
|
157
|
+
"FIRST_NAME": user.first_name,
|
|
158
|
+
"ACTIVATION_LINK": url,
|
|
159
|
+
},
|
|
121
160
|
)
|
|
122
161
|
else:
|
|
123
162
|
url = f"{request.build_absolute_uri(reverse('verify_email', kwargs={'token': verification}))}"
|
|
124
163
|
send_dotdigital_email(
|
|
125
|
-
campaign_ids["verify_new_user"],
|
|
164
|
+
campaign_ids["verify_new_user"],
|
|
165
|
+
[user.email],
|
|
166
|
+
personalization_values={"VERIFICATION_LINK": url},
|
|
126
167
|
)
|
|
127
168
|
|
|
128
169
|
if _newsletter_ticked(data):
|
|
129
|
-
add_to_dotmailer(
|
|
170
|
+
add_to_dotmailer(
|
|
171
|
+
user.first_name,
|
|
172
|
+
user.last_name,
|
|
173
|
+
user.email,
|
|
174
|
+
address_book_ids["newsletter"],
|
|
175
|
+
DotmailerUserType.STUDENT,
|
|
176
|
+
)
|
|
130
177
|
# verifying change of email address.
|
|
131
178
|
else:
|
|
132
179
|
verification = generate_token(user, new_email)
|
|
133
180
|
url = f"{request.build_absolute_uri(reverse('verify_email', kwargs={'token': verification}))}"
|
|
134
181
|
send_dotdigital_email(
|
|
135
|
-
campaign_ids["email_change_verification"],
|
|
182
|
+
campaign_ids["email_change_verification"],
|
|
183
|
+
[new_email],
|
|
184
|
+
personalization_values={"VERIFICATION_LINK": url},
|
|
136
185
|
)
|
|
137
186
|
|
|
138
187
|
|
|
139
|
-
def add_to_dotmailer(
|
|
188
|
+
def add_to_dotmailer(
|
|
189
|
+
first_name: str,
|
|
190
|
+
last_name: str,
|
|
191
|
+
email: str,
|
|
192
|
+
address_book_id: int,
|
|
193
|
+
user_type: DotmailerUserType = None,
|
|
194
|
+
):
|
|
140
195
|
try:
|
|
141
196
|
create_contact(first_name, last_name, email)
|
|
142
|
-
add_contact_to_address_book(
|
|
197
|
+
add_contact_to_address_book(
|
|
198
|
+
first_name, last_name, email, address_book_id, user_type
|
|
199
|
+
)
|
|
143
200
|
except RequestException:
|
|
144
201
|
return HttpResponse(status=404)
|
|
145
202
|
|
|
@@ -157,15 +214,34 @@ def create_contact(first_name, last_name, email):
|
|
|
157
214
|
{"key": "FULLNAME", "value": f"{first_name} {last_name}"},
|
|
158
215
|
],
|
|
159
216
|
},
|
|
160
|
-
"consentFields": [
|
|
217
|
+
"consentFields": [
|
|
218
|
+
{
|
|
219
|
+
"fields": [
|
|
220
|
+
{
|
|
221
|
+
"key": "DATETIMECONSENTED",
|
|
222
|
+
"value": datetime.datetime.now().__str__(),
|
|
223
|
+
}
|
|
224
|
+
]
|
|
225
|
+
}
|
|
226
|
+
],
|
|
161
227
|
"preferences": app_settings.DOTMAILER_DEFAULT_PREFERENCES,
|
|
162
228
|
}
|
|
163
229
|
|
|
164
|
-
post(
|
|
230
|
+
post(
|
|
231
|
+
url,
|
|
232
|
+
json=body,
|
|
233
|
+
auth=(app_settings.DOTMAILER_USER, app_settings.DOTMAILER_PASSWORD),
|
|
234
|
+
)
|
|
165
235
|
|
|
166
236
|
|
|
167
|
-
def add_contact_to_address_book(
|
|
168
|
-
|
|
237
|
+
def add_contact_to_address_book(
|
|
238
|
+
first_name: str,
|
|
239
|
+
last_name: str,
|
|
240
|
+
email: str,
|
|
241
|
+
address_book_id: int,
|
|
242
|
+
user_type: DotmailerUserType = None,
|
|
243
|
+
):
|
|
244
|
+
main_address_book_url = f"https://r1-api.dotmailer.com/v2/address-books/{address_book_id}/contacts"
|
|
169
245
|
|
|
170
246
|
body = {
|
|
171
247
|
"email": email,
|
|
@@ -178,16 +254,31 @@ def add_contact_to_address_book(first_name: str, last_name: str, email: str, use
|
|
|
178
254
|
],
|
|
179
255
|
}
|
|
180
256
|
|
|
181
|
-
post(
|
|
182
|
-
|
|
183
|
-
|
|
257
|
+
post(
|
|
258
|
+
main_address_book_url,
|
|
259
|
+
json=body,
|
|
260
|
+
auth=(app_settings.DOTMAILER_USER, app_settings.DOTMAILER_PASSWORD),
|
|
261
|
+
)
|
|
184
262
|
|
|
185
|
-
if user_type
|
|
186
|
-
specific_address_book_url =
|
|
187
|
-
|
|
188
|
-
|
|
263
|
+
if user_type is not None:
|
|
264
|
+
specific_address_book_url = (
|
|
265
|
+
app_settings.DOTMAILER_NO_ACCOUNT_ADDRESS_BOOK_URL
|
|
266
|
+
)
|
|
189
267
|
|
|
190
|
-
|
|
268
|
+
if user_type == DotmailerUserType.TEACHER:
|
|
269
|
+
specific_address_book_url = (
|
|
270
|
+
app_settings.DOTMAILER_TEACHER_ADDRESS_BOOK_URL
|
|
271
|
+
)
|
|
272
|
+
elif user_type == DotmailerUserType.STUDENT:
|
|
273
|
+
specific_address_book_url = (
|
|
274
|
+
app_settings.DOTMAILER_STUDENT_ADDRESS_BOOK_URL
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
post(
|
|
278
|
+
specific_address_book_url,
|
|
279
|
+
json=body,
|
|
280
|
+
auth=(app_settings.DOTMAILER_USER, app_settings.DOTMAILER_PASSWORD),
|
|
281
|
+
)
|
|
191
282
|
|
|
192
283
|
|
|
193
284
|
def delete_contact(email: str):
|
|
@@ -195,8 +286,16 @@ def delete_contact(email: str):
|
|
|
195
286
|
user = get_dotmailer_user_by_email(email)
|
|
196
287
|
user_id = user.get("id")
|
|
197
288
|
if user_id:
|
|
198
|
-
url = app_settings.DOTMAILER_DELETE_USER_BY_ID_URL.replace(
|
|
199
|
-
|
|
289
|
+
url = app_settings.DOTMAILER_DELETE_USER_BY_ID_URL.replace(
|
|
290
|
+
"ID", str(user_id)
|
|
291
|
+
)
|
|
292
|
+
delete(
|
|
293
|
+
url,
|
|
294
|
+
auth=(
|
|
295
|
+
app_settings.DOTMAILER_USER,
|
|
296
|
+
app_settings.DOTMAILER_PASSWORD,
|
|
297
|
+
),
|
|
298
|
+
)
|
|
200
299
|
except RequestException:
|
|
201
300
|
return HttpResponse(status=404)
|
|
202
301
|
|
|
@@ -204,7 +303,9 @@ def delete_contact(email: str):
|
|
|
204
303
|
def get_dotmailer_user_by_email(email):
|
|
205
304
|
url = app_settings.DOTMAILER_GET_USER_BY_EMAIL_URL.replace("EMAIL", email)
|
|
206
305
|
|
|
207
|
-
response = get(
|
|
306
|
+
response = get(
|
|
307
|
+
url, auth=(app_settings.DOTMAILER_USER, app_settings.DOTMAILER_PASSWORD)
|
|
308
|
+
)
|
|
208
309
|
|
|
209
310
|
return json.loads(response.content)
|
|
210
311
|
|
|
@@ -212,7 +313,9 @@ def get_dotmailer_user_by_email(email):
|
|
|
212
313
|
def add_consent_record_to_dotmailer_user(user):
|
|
213
314
|
consent_date_time = datetime.datetime.now().__str__()
|
|
214
315
|
|
|
215
|
-
url = app_settings.DOTMAILER_PUT_CONSENT_DATA_URL.replace(
|
|
316
|
+
url = app_settings.DOTMAILER_PUT_CONSENT_DATA_URL.replace(
|
|
317
|
+
"USER_ID", str(user["id"])
|
|
318
|
+
)
|
|
216
319
|
body = {
|
|
217
320
|
"contact": {
|
|
218
321
|
"email": user["email"],
|
|
@@ -220,10 +323,20 @@ def add_consent_record_to_dotmailer_user(user):
|
|
|
220
323
|
"emailType": user["emailType"],
|
|
221
324
|
"dataFields": user["dataFields"],
|
|
222
325
|
},
|
|
223
|
-
"consentFields": [
|
|
326
|
+
"consentFields": [
|
|
327
|
+
{
|
|
328
|
+
"fields": [
|
|
329
|
+
{"key": "DATETIMECONSENTED", "value": consent_date_time}
|
|
330
|
+
]
|
|
331
|
+
}
|
|
332
|
+
],
|
|
224
333
|
}
|
|
225
334
|
|
|
226
|
-
put(
|
|
335
|
+
put(
|
|
336
|
+
url,
|
|
337
|
+
json=body,
|
|
338
|
+
auth=(app_settings.DOTMAILER_USER, app_settings.DOTMAILER_PASSWORD),
|
|
339
|
+
)
|
|
227
340
|
|
|
228
341
|
|
|
229
342
|
def send_dotmailer_consent_confirmation_email_to_user(user):
|
|
@@ -231,7 +344,11 @@ def send_dotmailer_consent_confirmation_email_to_user(user):
|
|
|
231
344
|
campaign_id = app_settings.DOTMAILER_THANKS_FOR_STAYING_CAMPAIGN_ID
|
|
232
345
|
body = {"campaignID": campaign_id, "contactIds": [str(user["id"])]}
|
|
233
346
|
|
|
234
|
-
post(
|
|
347
|
+
post(
|
|
348
|
+
url,
|
|
349
|
+
json=body,
|
|
350
|
+
auth=(app_settings.DOTMAILER_USER, app_settings.DOTMAILER_PASSWORD),
|
|
351
|
+
)
|
|
235
352
|
|
|
236
353
|
|
|
237
354
|
def update_indy_email(user, request, data):
|
cfl_common/common/mail.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: codeforlife-portal
|
|
3
|
-
Version: 7.
|
|
3
|
+
Version: 7.4.0
|
|
4
4
|
Classifier: Programming Language :: Python
|
|
5
5
|
Classifier: Programming Language :: Python :: 3.12
|
|
6
6
|
Classifier: Framework :: Django
|
|
@@ -21,7 +21,7 @@ Requires-Dist: django-classy-tags==2.0.0
|
|
|
21
21
|
Requires-Dist: libsass==0.23.0
|
|
22
22
|
Requires-Dist: phonenumbers==8.12.12
|
|
23
23
|
Requires-Dist: more-itertools==8.7.0
|
|
24
|
-
Requires-Dist: cfl-common==7.
|
|
24
|
+
Requires-Dist: cfl-common==7.4.0
|
|
25
25
|
Requires-Dist: django-ratelimit==3.0.1
|
|
26
26
|
Requires-Dist: django-preventconcurrentlogins==0.8.2
|
|
27
27
|
Requires-Dist: django-csp==3.7
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
cfl_common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
2
|
cfl_common/setup.py,sha256=5Rk-FXyWToTujXqGRYqeA0A5nJ4NC5woXxyb6NLLbpo,818
|
|
3
3
|
cfl_common/common/__init__.py,sha256=XlncBOpKp_gekbKH7Y_i6yu1qy5tJc3Y8sn8cDy-Vgk,48
|
|
4
|
-
cfl_common/common/app_settings.py,sha256=
|
|
4
|
+
cfl_common/common/app_settings.py,sha256=Bw1DXkZpNIdwUJ-cIOjZnngH5_NbMXC0koW7NgQ0pKY,2495
|
|
5
5
|
cfl_common/common/apps.py,sha256=49UXZ3bSkFKvIEOL4zM7y1sAhccQJyRtsoOg5XVd_8Y,129
|
|
6
6
|
cfl_common/common/context_processors.py,sha256=X0iuX5qu9kMWa7q8osE9CJ2LgM7pPOYQFGdjm8X3rk0,236
|
|
7
7
|
cfl_common/common/csp_config.py,sha256=9ECOLnp60ENRFAYEEIoYOMhqQzLgfKA-wkWxeUBwDrQ,2824
|
|
8
|
-
cfl_common/common/mail.py,sha256=
|
|
8
|
+
cfl_common/common/mail.py,sha256=pIRfUMVoJWxdv74UqToj_0_pTVTC51z6QlFVLI3QBOw,6874
|
|
9
9
|
cfl_common/common/models.py,sha256=yAULJtzuF4loEt6mPrgZjwHGiQH6Hqm82etE7Sofvys,15989
|
|
10
10
|
cfl_common/common/permissions.py,sha256=gC6RQGZI2QDBbglx-xr_V4Hl2C2nf1V2_uPmEuoEcJo,2416
|
|
11
11
|
cfl_common/common/utils.py,sha256=Nn2Npao9Uqad5Js_IdHwF-ow6wrPNpBLW4AO1LxoEBc,1727
|
|
12
12
|
cfl_common/common/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
13
|
cfl_common/common/helpers/data_migration_loader.py,sha256=_BhS5lPmhcuVUbryBmJytlWdHyT02KYyxPkHar32mOE,1748
|
|
14
|
-
cfl_common/common/helpers/emails.py,sha256=
|
|
14
|
+
cfl_common/common/helpers/emails.py,sha256=KyXIudPRgetggOnlNUohArF7cPBuazQI2V6dtMfKnrM,12368
|
|
15
15
|
cfl_common/common/helpers/generators.py,sha256=kTL5e91I8wgmjJ-mu4jr9vIacjccUZ5pZSAz5cUNhdM,1505
|
|
16
16
|
cfl_common/common/helpers/organisation.py,sha256=e-JKumKoXrkMTzZPv0H4ViWL8vtCt7oXJjn_zZ1ec00,427
|
|
17
17
|
cfl_common/common/migrations/0001_initial.py,sha256=Y2kt2xmdCbrmDXCgqmhXeacicNg26Zj7L7SANSsgAAI,9664
|
|
@@ -104,23 +104,23 @@ deploy/static/robots.txt,sha256=5cS4RITuQhbpNzvpk4AyDCXdlIBfmfCoBYRvCHY2VT8,24
|
|
|
104
104
|
deploy/templates/deploy/csrf_failure.html,sha256=-pBRPn4Y7nUdYHGpTHCokT9Boi-isuwuivF8V2K1SgM,412
|
|
105
105
|
example_project/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
106
106
|
example_project/manage.py,sha256=EUgybZlZ7xk2Zf2KCwBbK_z7gf7Ifqs0_bl4Kijhdgo,242
|
|
107
|
-
example_project/portal_test_settings.py,sha256=
|
|
108
|
-
example_project/settings.py,sha256=
|
|
107
|
+
example_project/portal_test_settings.py,sha256=_gI7-HMoPJ-cDGO6n5UlEIHKHuTR5SC_Xt-l5Vdbx-0,7312
|
|
108
|
+
example_project/settings.py,sha256=HgGSG0n6Xggd0NieFVoJgn8vKGqyRbCddoB3CRuoT-Y,5640
|
|
109
109
|
example_project/urls.py,sha256=3SsP5jvPAXV5xmduka4zbSZB5PbXggjsalu1ojY5KIo,434
|
|
110
110
|
example_project/wsgi.py,sha256=U1W6WzZxZaIdYZ5tks7w9fqp5WS5qvn2iThsVcskrWw,829
|
|
111
|
-
portal/__init__.py,sha256=
|
|
111
|
+
portal/__init__.py,sha256=Dbq9JbNzDz-GmfE0eozgGmdee4W8D3uVIIQv1bzHZPk,22
|
|
112
112
|
portal/admin.py,sha256=on1-zNRnZvf2cwBN6GVRVYRhkaksrCgfzX8XPWtkvz8,6062
|
|
113
113
|
portal/app_settings.py,sha256=DhWLQOwM0zVOXE3O5TNKbMM9K6agfLuCsHOdr1J7xEI,651
|
|
114
114
|
portal/backends.py,sha256=2Dss6_WoQwPuDzJUF1yEaTQTNG4eUrD12ujJQ5cp5Tc,812
|
|
115
115
|
portal/beta.py,sha256=0TCC-9_KZoM1nuzJ9FiuKR5n9JITdMYenHGQtRvn9UU,255
|
|
116
|
-
portal/context_processors.py,sha256=
|
|
116
|
+
portal/context_processors.py,sha256=Q68UhmArLPRchS2KmfVR4hKrijllXal3sO5cHYWC2Fc,222
|
|
117
117
|
portal/handlers.py,sha256=gF99OfQrGcIGDnUyONhvylZNU8sl6XHYEurwu0fuiss,422
|
|
118
118
|
portal/models.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
119
|
-
portal/urls.py,sha256=
|
|
119
|
+
portal/urls.py,sha256=4bGQQWiQI9zSG1oceVjQctUnDKggzzZsbYAxuBvijpY,18002
|
|
120
120
|
portal/wsgi.py,sha256=3yRcNxBQG30NhzrVi93bX-DrbXtsIQBc70HiW5wbOyE,401
|
|
121
121
|
portal/forms/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
122
122
|
portal/forms/admin.py,sha256=Cdl8-wvasAzvMfgUlFYzQjYeuyC7gIsSiy8V_-jMp7w,2080
|
|
123
|
-
portal/forms/dotmailer.py,sha256=
|
|
123
|
+
portal/forms/dotmailer.py,sha256=j-o9qthQc7xmOsHSQGEEoHvaEyOpzlWrj6bOnV0PpsI,1567
|
|
124
124
|
portal/forms/error_messages.py,sha256=8d3z_3e2L-5zwj5hFhnUByC5k2CEpIVVuJg2nYkCUQ8,148
|
|
125
125
|
portal/forms/invite_teacher.py,sha256=jkDNcCfkts4_lXRzhcI3xBam21Zn2yX9wMpMVhDtW1w,880
|
|
126
126
|
portal/forms/organisation.py,sha256=QcQyd7AiqBmvt4y8uQSQylguUbKOKqo2pjqWIkpWjDg,7433
|
|
@@ -243,7 +243,7 @@ portal/static/portal/img/resources_hero.jpg,sha256=7a9UD_Hz8duS4IFfXo_dspgEbJpt2
|
|
|
243
243
|
portal/static/portal/img/resources_montage.jpg,sha256=X6ahyduC1qA-Hv0J9cF33ikoyl_SW01djuDz1D-2JQ4,74159
|
|
244
244
|
portal/static/portal/img/reuben.png,sha256=sJdtrEwtB8TJNIhlzk5uES37oidpODRoZ2F7mgmJCus,93064
|
|
245
245
|
portal/static/portal/img/rob.png,sha256=7ZtcMzJ_khTflJJIhfU5YQzhgld2ceBB2QBpZX7yVKw,103324
|
|
246
|
-
portal/static/portal/img/rr_advanced.png,sha256=
|
|
246
|
+
portal/static/portal/img/rr_advanced.png,sha256=hpyfd-FWGeuuRoBiMUq2bynpcBcwvRBnO3f04czb4Os,228593
|
|
247
247
|
portal/static/portal/img/rr_beginner.png,sha256=xnLZ2bpOc5WbS-I9lu8hWcs8W8x3QaYDp21t64auMqU,55473
|
|
248
248
|
portal/static/portal/img/rr_intermediate.png,sha256=fT8CXKMoMjyX05aEBXHNS4PseuVnqdiEWSr-enNsMeI,90538
|
|
249
249
|
portal/static/portal/img/sadface.png,sha256=FU9d3XPCfe6sknfAymz8XPl_0nICp0geiqTQoOximvg,2148
|
|
@@ -267,7 +267,7 @@ portal/static/portal/img/colorboxImages/loading_background.png,sha256=lZ7Mxrcb7-
|
|
|
267
267
|
portal/static/portal/img/colorboxImages/overlay.png,sha256=qy73bf_q55z4kktuaTaMhVrxDzVRCIjgmBQ5cbOmLtE,182
|
|
268
268
|
portal/static/portal/js/bootstrap.min.js,sha256=nuL8_2cJ5NDSSwnKD8VqreErSWHtnEP9E7AySL-1ev4,39680
|
|
269
269
|
portal/static/portal/js/carouselCards.js,sha256=IByMjKk37E-TCc3vx9nfF-IJWl9BOFPNVqf4WuD75GI,778
|
|
270
|
-
portal/static/portal/js/common.js,sha256=
|
|
270
|
+
portal/static/portal/js/common.js,sha256=kVUdm0luaqMLElbDq3Mht1k5DfkYHXAmJtce1Rekogg,7554
|
|
271
271
|
portal/static/portal/js/independentLogin.js,sha256=wjjJBAF5arJ2iwW30lHTraG_f2FJ9UMGnXGpUSXwXIs,538
|
|
272
272
|
portal/static/portal/js/independentRegistration.js,sha256=YWhIzwJcl0acU9weAKB7pWK76J1dpAuAQkI7DrUm3uA,2622
|
|
273
273
|
portal/static/portal/js/join_create_game_toggle.js,sha256=eWxhMfzVKu1oft9iUFV4w8CgqMRv9-unb5P5cGi1h_4,393
|
|
@@ -394,21 +394,21 @@ portal/static/portal/sass/modules/_all.scss,sha256=k1U_FAKajqT8B3U53UT9B1Hc4jn5P
|
|
|
394
394
|
portal/static/portal/sass/modules/_animation.scss,sha256=s75-4xRmPSmqwHUuyVy0OcnbS5jreRnotMXm-CuTLkE,39
|
|
395
395
|
portal/static/portal/sass/modules/_breakpoints.scss,sha256=Nc7nrvjzQ0eK844ITuqwYcybIJxpYVFU5s30mz3BGOg,498
|
|
396
396
|
portal/static/portal/sass/modules/_card_constants.scss,sha256=FUojcT5Fs-IYErt-frahD3HnVb06A515k4SQJrqVUfQ,107
|
|
397
|
-
portal/static/portal/sass/modules/_colours.scss,sha256=
|
|
397
|
+
portal/static/portal/sass/modules/_colours.scss,sha256=Wen7UlF98ijyDjIEsLeIzLx0fcgXOLjavAVIh8PfqX0,4350
|
|
398
398
|
portal/static/portal/sass/modules/_homepage_constants.scss,sha256=GfSppJtWNxufu4hKO6vHX7YBQgmU1oB0KBonh-ltgv0,44
|
|
399
|
-
portal/static/portal/sass/modules/_levels.scss,sha256
|
|
400
|
-
portal/static/portal/sass/modules/_mixins.scss,sha256=
|
|
399
|
+
portal/static/portal/sass/modules/_levels.scss,sha256=-PrZ21k_-sQAxYZB0uJd7macz46-VVwsQdmtxYyZYnA,106
|
|
400
|
+
portal/static/portal/sass/modules/_mixins.scss,sha256=8xDWuApUG6B3pjadB4iHpJ87ehXCg0qqpabnVd2cgxU,1987
|
|
401
401
|
portal/static/portal/sass/modules/_spacing.scss,sha256=WHBcd8ZSl4UHqPAOmW_JLt_MOfww44Hj8W42dWOpTO8,31
|
|
402
402
|
portal/static/portal/sass/partials/_banners.scss,sha256=Q13Mybarzkq0GWvhStiqIuK_bgKku8wkqC6qCFIruEg,5658
|
|
403
403
|
portal/static/portal/sass/partials/_base.scss,sha256=cUvskrzNXLA-Xg1EgpL-S0wTWDnRn86AcdMbE2_aLMM,26
|
|
404
|
-
portal/static/portal/sass/partials/_buttons.scss,sha256=
|
|
404
|
+
portal/static/portal/sass/partials/_buttons.scss,sha256=UR0a6ne8nZQyyWlWzVDD5RG2vfVe8w9rM5yWLBav3qM,9572
|
|
405
405
|
portal/static/portal/sass/partials/_carousel.scss,sha256=m8N6jSuHBzeKyMUNGGc48NlNYTmotKlaiy10hwFnyWY,3500
|
|
406
406
|
portal/static/portal/sass/partials/_footer.scss,sha256=oqt-Qvz7vtUFNnpe4FkQkaZk3J3fojCy9cKCxqGTWoM,2493
|
|
407
407
|
portal/static/portal/sass/partials/_forms.scss,sha256=cbonSxhtfaHR-4R6i0u65AaIZRG_25C837CgZlLuwCI,7101
|
|
408
408
|
portal/static/portal/sass/partials/_grids.scss,sha256=pnMQht5lZ65MRB-0_nl8yn655hlKC_oWCwZopillVwc,4968
|
|
409
|
-
portal/static/portal/sass/partials/_header.scss,sha256=
|
|
409
|
+
portal/static/portal/sass/partials/_header.scss,sha256=NNb8hb66LPTeaGdL-vcsNSDJTxPljsOfpkYMI5EmOWc,7421
|
|
410
410
|
portal/static/portal/sass/partials/_images.scss,sha256=Fro4a0VfLo6FyrvGk5yjsjzzGKWVdHeMFJiVC96C7vk,6213
|
|
411
|
-
portal/static/portal/sass/partials/_popup.scss,sha256=
|
|
411
|
+
portal/static/portal/sass/partials/_popup.scss,sha256=GQ6Vtmj3vdOP4Hvsf8ZxKdEtuL8gqoClYpDgQ19kvnQ,2280
|
|
412
412
|
portal/static/portal/sass/partials/_progress-bars.scss,sha256=cTyRa9WLeIE0rETmY58Rcyf-8O6JE3iDTa_jw3mk23g,144
|
|
413
413
|
portal/static/portal/sass/partials/_subnavs.scss,sha256=6FJV1wBmHchnGBL9Yx56Ua4RR1b5P6ABTextZPTqXSs,5052
|
|
414
414
|
portal/static/portal/sass/partials/_tables.scss,sha256=XrO-I41hfyFy1Uh-STokSpoG0qifJVNlpWS4sNxDYdQ,2984
|
|
@@ -434,7 +434,7 @@ portal/templates/email.txt,sha256=z3bkT2WnkCrVa1RLVbGd-pE81cLEHlZ_QowfbSQAOvg,19
|
|
|
434
434
|
portal/templates/captcha/widget_v2_invisible.html,sha256=wPBAvvjm-qhSCrQruwJ2SSBkxFg4oUNFl26Axs1IjZw,306
|
|
435
435
|
portal/templates/captcha/includes/js_v2_invisible.html,sha256=FUyDf1RDyS7whzW2B_TnD1ovS8an9sDavCJFqAsrnmQ,1409
|
|
436
436
|
portal/templates/portal/about.html,sha256=_iD0GCP6q3-XuZ2LC-9O0KYY-mKL6c9qk3O-NRRqsRM,10321
|
|
437
|
-
portal/templates/portal/base.html,sha256=
|
|
437
|
+
portal/templates/portal/base.html,sha256=4xLACNgKmRQTdEsdNNGYhLzMozzYzWIIzk31HrLGBf0,12109
|
|
438
438
|
portal/templates/portal/base_no_userprofile.html,sha256=PlRufyYmUUGWBZ6CvbYhJWOMTqKqdcee4xnO5--AogA,447
|
|
439
439
|
portal/templates/portal/coding_club.html,sha256=aaLx9UQ8p_7Vvy3Vlh1rOufeNN0KhJ6fj4oqI6QqJcM,4518
|
|
440
440
|
portal/templates/portal/contribute.html,sha256=UIC_N3Lun9wB_6jEra0wvlT9fDiiIeMby7_onXYo6k0,4176
|
|
@@ -446,7 +446,7 @@ portal/templates/portal/email_verification_needed.html,sha256=lJvwWjBg6y-9V17gyV
|
|
|
446
446
|
portal/templates/portal/form_shapes.html,sha256=oiaQ4RKZF8STTQsoQqql184UoYVyFQ60Mwve8lJMKu0,1223
|
|
447
447
|
portal/templates/portal/getinvolved.html,sha256=jC56RTuLjDISr7eJUPA2TErz1TBcLi9G42BY-jo3Xe8,2872
|
|
448
448
|
portal/templates/portal/home.html,sha256=J10xWo7opn_BjQrdxpn0wg1bo6w4DwjpTEOJ-pkJfKY,6178
|
|
449
|
-
portal/templates/portal/home_learning.html,sha256=
|
|
449
|
+
portal/templates/portal/home_learning.html,sha256=U1_AYrTNLqCjla7-vdVkC6SOigGBAmu3kscuiYNH4rw,10070
|
|
450
450
|
portal/templates/portal/locked_out.html,sha256=JeiFHFyueFX03D54k82swjxvKY78cFG8Vre-bKKv_7Y,894
|
|
451
451
|
portal/templates/portal/locked_out_school_student.html,sha256=bcpLtu4mkHR-zILLuArtHH2OfUSjHiqntcdbTMlx5Kg,684
|
|
452
452
|
portal/templates/portal/mouseflow.html,sha256=ji9SWR86nqC59xdmivfdPNG5OzFk8gJEUeOUUh52alk,361
|
|
@@ -469,8 +469,9 @@ portal/templates/portal/partials/benefits.html,sha256=TZm4U_XimgivkPMjDXxxkV7PLf
|
|
|
469
469
|
portal/templates/portal/partials/card_list.html,sha256=yHcp4oc0WRG9H6Ek871VCHbwYkDRcwQYbZ320gtsFn8,1550
|
|
470
470
|
portal/templates/portal/partials/character_list.html,sha256=SnNFHzbIkOSaiRPIvSdplEf_B87UYgJ1pOvMltNDxLE,415
|
|
471
471
|
portal/templates/portal/partials/delete_popup.html,sha256=nEhnwgnmKoFzb6LlCwdX973Em9bVOFh6MON36RPteYs,1275
|
|
472
|
+
portal/templates/portal/partials/donate_popup.html,sha256=iPxXqIwZ-9_n4ssdUEiZ_GY3nbpes2AlcEKphL2Plno,2151
|
|
472
473
|
portal/templates/portal/partials/footer.html,sha256=m0mKlUenQN4pVCNi8Dkzer5aQ4uUmvfLjyzTMWoBiQ4,4838
|
|
473
|
-
portal/templates/portal/partials/header.html,sha256=
|
|
474
|
+
portal/templates/portal/partials/header.html,sha256=LCOppTXDr8hEYp2eBJjxw3LvqwnVR-6E9jdYGodlD5U,20373
|
|
474
475
|
portal/templates/portal/partials/headline.html,sha256=xKb-WtkT0FyQqT0smyNSKkXFvU7KQ5Czad8ca6YKQg4,89
|
|
475
476
|
portal/templates/portal/partials/hero_card.html,sha256=UN5hyxrw-McuXFsDzPBIECB9yGrv9VjsFf8SEBowwXc,786
|
|
476
477
|
portal/templates/portal/partials/info_popup.html,sha256=gzffd5MBVb7p2hGQuZMNDudThrRgs847hCu9ziT9uLE,566
|
|
@@ -536,12 +537,12 @@ portal/tests/test_api.py,sha256=Yo5s_nEGOoG35jA39yZ6nuDOUZvuCZ8o8o8XhZos61w,1381
|
|
|
536
537
|
portal/tests/test_captcha_forms.py,sha256=lirhIli-sHovun8VdrF0he7KRFTAd8DMCpkJ8cQNotg,1015
|
|
537
538
|
portal/tests/test_class.py,sha256=43g2HslNosbSuSnnMBzM6VWk4LaV0HXkWS3f8VKVRmw,15930
|
|
538
539
|
portal/tests/test_daily_activities.py,sha256=-siDCMGBD1ijjccHVk7eEmrk4bgTsvbh0B6hDoj2fo0,1803
|
|
539
|
-
portal/tests/test_emails.py,sha256=
|
|
540
|
+
portal/tests/test_emails.py,sha256=pLr06j3uMBxP1raoZQWzUTBVFvsEDFtUh85J8OnqCwE,9238
|
|
541
|
+
portal/tests/test_global_forms.py,sha256=A5JpAe4AYK-wpu0o1qU4THmeNv_wr7lhzaMbjz5czpY,1543
|
|
540
542
|
portal/tests/test_helper_methods.py,sha256=-SQCDZm2XUtyXGEp0CHIb_SSC9CPD-XOSnpnY8QclHk,890
|
|
541
543
|
portal/tests/test_independent_student.py,sha256=NrRjTEr6V4WXpCE74N8LYNVocvLSvddkjuo3dYpfAZc,27245
|
|
542
544
|
portal/tests/test_invite_teacher.py,sha256=oeOaoJV1IqJSYPlaPFjnhVXdB2mq8otCTLp_lfjuCfk,12224
|
|
543
545
|
portal/tests/test_middleware.py,sha256=b6jfNmiRZ2snqLKsyJUG-RivoX5fmrqLlQkG9MeVnqM,8034
|
|
544
|
-
portal/tests/test_newsletter_footer.py,sha256=MdVUX53mEoDTa4Krq-jg9LFNo-QyghqvTvhHeNXBGnE,838
|
|
545
546
|
portal/tests/test_organisation.py,sha256=kCMUNzLN6EzaMUBcFkqXwnqLGgOuQxQWIHHt63nhqBs,7574
|
|
546
547
|
portal/tests/test_partials.py,sha256=cSLNLjdsriROjPxkZlM3HKD3CSKDuKgpaDIdL3fPyBs,1794
|
|
547
548
|
portal/tests/test_ratelimit.py,sha256=XWq1A9XgRrlcMHibGoJ0kc4gLc5U_u5UhKHjthxCfYA,19376
|
|
@@ -608,7 +609,7 @@ portal/views/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
608
609
|
portal/views/about.py,sha256=-muXy17UhxCSKkjnMAkSLXiCvT_pBPlf2ykTYr794dI,443
|
|
609
610
|
portal/views/admin.py,sha256=4Xt3zEyQH7sUwQSrwuRtoCodWidjOzd7gJUwWU96pXY,957
|
|
610
611
|
portal/views/api.py,sha256=lCwiclR98G-yTgK55u8IjkueIH8iremeiZSa3jAvO-M,6990
|
|
611
|
-
portal/views/dotmailer.py,sha256=
|
|
612
|
+
portal/views/dotmailer.py,sha256=x49p89TtwA1MLysRLtq5yRRzVtIpzGoU__Xb5hPuHak,3208
|
|
612
613
|
portal/views/email.py,sha256=V3wXRxIjeZ4OJBVqGCQrPn-GQWKZK1PCXbR1f2Zpa_4,2174
|
|
613
614
|
portal/views/home.py,sha256=GlNTJqSST_jQi0REuaV2aI2zram-KAhedmATdC6yU58,10247
|
|
614
615
|
portal/views/legal.py,sha256=nUunsTHnhMcXBcDlg1GmUal86k9Vhinne4A2FWfq78M,342
|
|
@@ -626,14 +627,14 @@ portal/views/student/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hS
|
|
|
626
627
|
portal/views/student/edit_account_details.py,sha256=Ba-3D_zzKbX5N01NG5qqBS0ud10B8D5SN8hOpLiGa9U,8468
|
|
627
628
|
portal/views/student/play.py,sha256=GMxk65bxWOe1Ds2kb6rvuOd1GoAtt5v_9AihLNXoUL0,8768
|
|
628
629
|
portal/views/teacher/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
629
|
-
portal/views/teacher/dashboard.py,sha256=
|
|
630
|
+
portal/views/teacher/dashboard.py,sha256=pjzOOCz29d4VHukaCI5QhkDsu-RPvy7SXC9dDcPo50k,27422
|
|
630
631
|
portal/views/teacher/teach.py,sha256=MxheM_kxt_K1J7jEWlim8yZonnp63iYUTw5dCaLscLI,37056
|
|
631
632
|
portal/views/two_factor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
632
633
|
portal/views/two_factor/core.py,sha256=O_wcBeFqdPYSGNGv-pT_vbs5-Dj1Z-Jfkd6f9-E5yZI,760
|
|
633
634
|
portal/views/two_factor/form.py,sha256=lnHNKI-BMlpncTuW3zUzjPaJJNuEra2I_nOam0eOKFY,257
|
|
634
635
|
portal/views/two_factor/profile.py,sha256=tkl_ludo8arMtd5LKNmohM66vpC_YQiP-0nspTSJiJ4,383
|
|
635
|
-
codeforlife_portal-7.
|
|
636
|
-
codeforlife_portal-7.
|
|
637
|
-
codeforlife_portal-7.
|
|
638
|
-
codeforlife_portal-7.
|
|
639
|
-
codeforlife_portal-7.
|
|
636
|
+
codeforlife_portal-7.4.0.dist-info/LICENSE.md,sha256=9AbRlCDqD2D1tPibimysFv3zg3AIc49-eyv9aEsyq9w,115
|
|
637
|
+
codeforlife_portal-7.4.0.dist-info/METADATA,sha256=Nnx8oLJTfx1yuUsKVh7pTcZQDhXxkLSvr3_ehnB9X04,3317
|
|
638
|
+
codeforlife_portal-7.4.0.dist-info/WHEEL,sha256=fS9sRbCBHs7VFcwJLnLXN1MZRR0_TVTxvXKzOnaSFs8,110
|
|
639
|
+
codeforlife_portal-7.4.0.dist-info/top_level.txt,sha256=8e5pdsuIoTqEAMqpelHBjGjLbffcBtgOoggmd2q7nMw,41
|
|
640
|
+
codeforlife_portal-7.4.0.dist-info/RECORD,,
|
example_project/settings.py
CHANGED
portal/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "7.
|
|
1
|
+
__version__ = "7.4.0"
|
portal/context_processors.py
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
from portal.forms.dotmailer import NewsletterForm
|
|
1
|
+
from portal.forms.dotmailer import DonateForm, NewsletterForm
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
def process_newsletter_form(request):
|
|
5
5
|
return {"news_form": NewsletterForm()}
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def process_donate_form(request):
|
|
9
|
+
return {"donate_form": DonateForm()}
|
portal/forms/dotmailer.py
CHANGED
|
@@ -5,16 +5,51 @@ class NewsletterForm(forms.Form):
|
|
|
5
5
|
email = forms.EmailField(
|
|
6
6
|
label="Sign up to receive updates about Code for Life games and teaching resources.",
|
|
7
7
|
label_suffix="",
|
|
8
|
-
widget=forms.EmailInput(
|
|
8
|
+
widget=forms.EmailInput(
|
|
9
|
+
attrs={
|
|
10
|
+
"placeholder": "Your email address",
|
|
11
|
+
"id": "newsletter_email_field",
|
|
12
|
+
}
|
|
13
|
+
),
|
|
9
14
|
help_text="Enter email address above",
|
|
10
15
|
)
|
|
11
16
|
|
|
12
|
-
age_verification = forms.BooleanField(
|
|
17
|
+
age_verification = forms.BooleanField(
|
|
18
|
+
widget=forms.CheckboxInput(), initial=False, required=True
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class DonateForm(forms.Form):
|
|
23
|
+
email = forms.EmailField(
|
|
24
|
+
label="This data will only be used for this purpose and you will be "
|
|
25
|
+
"able to opt out anytime. Please read our privacy notice for "
|
|
26
|
+
"further details.",
|
|
27
|
+
label_suffix="",
|
|
28
|
+
widget=forms.EmailInput(
|
|
29
|
+
attrs={
|
|
30
|
+
"placeholder": "Enter your email address",
|
|
31
|
+
"id": "donate_email_field",
|
|
32
|
+
}
|
|
33
|
+
),
|
|
34
|
+
help_text="Enter your email address",
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
age_verification = forms.BooleanField(
|
|
38
|
+
widget=forms.CheckboxInput(attrs={"id": "donate_age_verification"}),
|
|
39
|
+
initial=False,
|
|
40
|
+
required=True,
|
|
41
|
+
)
|
|
13
42
|
|
|
14
43
|
|
|
15
44
|
class ConsentForm(forms.Form):
|
|
16
45
|
email = forms.EmailField(
|
|
17
|
-
label="Email",
|
|
46
|
+
label="Email",
|
|
47
|
+
label_suffix="",
|
|
48
|
+
widget=forms.EmailInput(
|
|
49
|
+
attrs={"placeholder": "your.name@yourdomain.com"}
|
|
50
|
+
),
|
|
18
51
|
)
|
|
19
52
|
|
|
20
|
-
consent_ticked = forms.BooleanField(
|
|
53
|
+
consent_ticked = forms.BooleanField(
|
|
54
|
+
widget=forms.CheckboxInput(), initial=False, required=True
|
|
55
|
+
)
|
|
Binary file
|