codeforlife-portal 7.3.8__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.8.dist-info → codeforlife_portal-7.4.0.dist-info}/METADATA +2 -2
- {codeforlife_portal-7.3.8.dist-info → codeforlife_portal-7.4.0.dist-info}/RECORD +28 -27
- 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/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/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.8.dist-info → codeforlife_portal-7.4.0.dist-info}/LICENSE.md +0 -0
- {codeforlife_portal-7.3.8.dist-info → codeforlife_portal-7.4.0.dist-info}/WHEEL +0 -0
- {codeforlife_portal-7.3.8.dist-info → codeforlife_portal-7.4.0.dist-info}/top_level.txt +0 -0
|
@@ -63,6 +63,9 @@ $color-button-contained-disabled: $color-secondary-100;
|
|
|
63
63
|
$color-button-outlined-border: $color-secondary-600;
|
|
64
64
|
$color-button-outlined-border-active: $color-secondary-600;
|
|
65
65
|
$color-button-subnav-border: white;
|
|
66
|
+
$color-button-pill: #86ae18;
|
|
67
|
+
$color-button-pill-hover: #82a210;
|
|
68
|
+
$color-button-pill-active: #82a210;
|
|
66
69
|
// Old buttons
|
|
67
70
|
$color-button-primary-action-navigation: $color-secondary;
|
|
68
71
|
$color-button-primary-action-navigation-hover: $color-secondary;
|
|
@@ -55,6 +55,11 @@
|
|
|
55
55
|
calculate-rem($radius-bottom-left);
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
@mixin _border-radius-all($radius) {
|
|
59
|
+
border-radius: calculate-rem($radius) calculate-rem($radius)
|
|
60
|
+
calculate-rem($radius) calculate-rem($radius);
|
|
61
|
+
}
|
|
62
|
+
|
|
58
63
|
@mixin _box-shadow($h-offset, $v-offset, $blur, $spread, $color) {
|
|
59
64
|
box-shadow: calculate-rem($h-offset) calculate-rem($v-offset)
|
|
60
65
|
calculate-rem($blur) calculate-rem($spread) $color;
|
|
@@ -89,7 +89,6 @@ table {
|
|
|
89
89
|
color: $color-text-primary;
|
|
90
90
|
box-shadow: none;
|
|
91
91
|
}
|
|
92
|
-
|
|
93
92
|
}
|
|
94
93
|
|
|
95
94
|
/* Outlined button */
|
|
@@ -139,6 +138,30 @@ table {
|
|
|
139
138
|
}
|
|
140
139
|
}
|
|
141
140
|
|
|
141
|
+
/* Green button */
|
|
142
|
+
.button--tertiary {
|
|
143
|
+
@include _padding(10px, 15px, 10px, 15px);
|
|
144
|
+
background: $color-button-pill;
|
|
145
|
+
color: $color-text-secondary;
|
|
146
|
+
|
|
147
|
+
&:hover:not(.disabled){
|
|
148
|
+
@include material-shadow();
|
|
149
|
+
background: $color-button-pill-hover;
|
|
150
|
+
color: $color-text-secondary;
|
|
151
|
+
text-decoration: none;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
&:active:not(.disabled) {
|
|
155
|
+
background: $color-button-pill-active;
|
|
156
|
+
color: $color-text-secondary;
|
|
157
|
+
box-shadow: none;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.button--pill {
|
|
162
|
+
@include _border-radius-all(20px);
|
|
163
|
+
}
|
|
164
|
+
|
|
142
165
|
.button-right-arrow {
|
|
143
166
|
&:after {
|
|
144
167
|
content: "\e5e1";
|
|
@@ -172,8 +195,6 @@ table {
|
|
|
172
195
|
}
|
|
173
196
|
|
|
174
197
|
.button--menu {
|
|
175
|
-
background-color: transparent;
|
|
176
|
-
border-radius: 0;
|
|
177
198
|
text-decoration: none;
|
|
178
199
|
}
|
|
179
200
|
|
|
@@ -416,6 +437,13 @@ td .button--primary {
|
|
|
416
437
|
justify-content: center;
|
|
417
438
|
}
|
|
418
439
|
|
|
440
|
+
&.button--donate {
|
|
441
|
+
background: $color-button-pill;
|
|
442
|
+
border: 0;
|
|
443
|
+
color: $color-text-secondary;
|
|
444
|
+
justify-content: center;
|
|
445
|
+
}
|
|
446
|
+
|
|
419
447
|
&.button--header--login {
|
|
420
448
|
border: 2px solid $color-secondary-600;
|
|
421
449
|
margin: 0;
|
|
@@ -260,13 +260,14 @@
|
|
|
260
260
|
width: 100%;
|
|
261
261
|
z-index: $nav-bar-level;
|
|
262
262
|
|
|
263
|
-
.button--menu
|
|
264
|
-
|
|
263
|
+
.button--menu:hover,
|
|
264
|
+
.button--menu:focus, {
|
|
265
|
+
font-weight: normal;
|
|
266
|
+
}
|
|
265
267
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
}
|
|
268
|
+
.button--pill:hover,
|
|
269
|
+
.button--pill:focus, {
|
|
270
|
+
font-weight: 600;
|
|
270
271
|
}
|
|
271
272
|
|
|
272
273
|
.button--menu--secondary {
|
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
.popup-box {
|
|
21
21
|
background-color: $color-background-secondary;
|
|
22
22
|
box-shadow: 0 0 4 * $spacing $color-background-box-shadow;
|
|
23
|
-
margin:
|
|
23
|
+
margin: 10% auto;
|
|
24
24
|
overflow: hidden;
|
|
25
|
-
width:
|
|
25
|
+
width: 520px;
|
|
26
26
|
|
|
27
27
|
.popup-box__msg {
|
|
28
28
|
@include _padding(0px, 5 * $spacing, 5 * $spacing, 5 * $spacing);
|
|
@@ -47,6 +47,7 @@
|
|
|
47
47
|
.popup-box__title {
|
|
48
48
|
@include _padding(5 * $spacing, 5 * $spacing, 0px, 5 * $spacing);
|
|
49
49
|
background-color: $color-background-secondary;
|
|
50
|
+
color: $color-text-primary;
|
|
50
51
|
display: flex;
|
|
51
52
|
justify-content: flex-start;
|
|
52
53
|
font-family: "Space Grotesk", sans-serif;
|
|
@@ -57,6 +58,10 @@
|
|
|
57
58
|
min-width:0;
|
|
58
59
|
@include _margin(8px, 8px, 8px, 8px);
|
|
59
60
|
}
|
|
61
|
+
|
|
62
|
+
label {
|
|
63
|
+
text-align: left;
|
|
64
|
+
}
|
|
60
65
|
}
|
|
61
66
|
|
|
62
67
|
&#screentime-popup,
|
|
@@ -32,7 +32,6 @@
|
|
|
32
32
|
type="image/x-icon">
|
|
33
33
|
{% endblock css %}
|
|
34
34
|
{% include "portal/tag_manager/tag_manager_head.html" %}
|
|
35
|
-
|
|
36
35
|
<script type="text/javascript" src="{% static 'portal/js/lib/modernizr-build.js' %}"></script>
|
|
37
36
|
<script type="text/javascript" src="{% static 'portal/js/common.js' %}"></script>
|
|
38
37
|
<script type="text/javascript" src="{% static 'portal/js/jquery.placeholder.js' %}"></script>
|
|
@@ -82,6 +81,7 @@
|
|
|
82
81
|
{% include "portal/tag_manager/tag_manager_body.html" %}
|
|
83
82
|
{% render_block "js" %}
|
|
84
83
|
{% include 'portal/mouseflow.html' %}
|
|
84
|
+
{% include "portal/partials/donate_popup.html" %}
|
|
85
85
|
<div class="content-footer-wrapper">
|
|
86
86
|
{% block contentWrapper %}
|
|
87
87
|
<div {% block pageID %}id="contentWrapper"{% endblock %}>
|
|
@@ -240,16 +240,25 @@
|
|
|
240
240
|
});
|
|
241
241
|
</script>
|
|
242
242
|
<script>
|
|
243
|
-
// disable newsletter signup
|
|
243
|
+
// disable newsletter signup and donate buttons by default
|
|
244
244
|
const newsletterSubmitButton = $('#submit_newsletter');
|
|
245
245
|
newsletterSubmitButton.addClass("disabled");
|
|
246
246
|
newsletterSubmitButton.prop("disabled", true);
|
|
247
247
|
|
|
248
|
-
|
|
248
|
+
const donateSubmitButton = $('#confirm_donate_button');
|
|
249
|
+
donateSubmitButton.addClass("disabled");
|
|
250
|
+
donateSubmitButton.prop("disabled", true);
|
|
251
|
+
|
|
252
|
+
// enable them or disable them depending on age verification checkbox
|
|
249
253
|
$('#id_age_verification').on("click", function() {
|
|
250
254
|
newsletterSubmitButton.prop("disabled", !this.checked);
|
|
251
255
|
newsletterSubmitButton.toggleClass("disabled", !this.checked);
|
|
252
256
|
});
|
|
257
|
+
|
|
258
|
+
$('#donate_age_verification').on("click", function() {
|
|
259
|
+
donateSubmitButton.prop("disabled", !this.checked);
|
|
260
|
+
donateSubmitButton.toggleClass("disabled", !this.checked);
|
|
261
|
+
})
|
|
253
262
|
</script>
|
|
254
263
|
{% endblock scripts %}
|
|
255
264
|
</body>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{% load static %}
|
|
2
|
+
{% load app_tags %}
|
|
3
|
+
{# A popup with a form input for email addresses. #}
|
|
4
|
+
<section id="donate-popup" class="popup-wrapper">
|
|
5
|
+
<div class="popup-box">
|
|
6
|
+
<div>
|
|
7
|
+
<button type="button" onclick="hideDonatePopup()" class="close popup-box__close" aria-label="Close">
|
|
8
|
+
<span class="iconify" data-icon="mdi:close"></span>
|
|
9
|
+
</button>
|
|
10
|
+
</div>
|
|
11
|
+
<div class="popup-box__title"></div>
|
|
12
|
+
<div class="popup-box__msg"></div>
|
|
13
|
+
<form id="donate_form" action="{% url 'process_donate_form' %}"
|
|
14
|
+
method="post">
|
|
15
|
+
<div class="col-sm-12">
|
|
16
|
+
{{ donate_form.non_field_errors }}
|
|
17
|
+
<div class="form--row">
|
|
18
|
+
<div class="form--row__input">
|
|
19
|
+
<label><small>{{ donate_form.email.label }}</small></label>
|
|
20
|
+
<div class="input--icon">
|
|
21
|
+
{{ donate_form.email }}
|
|
22
|
+
<span class="iconify" data-icon="mdi:email-outline"></span>
|
|
23
|
+
</div>
|
|
24
|
+
{{ donate_form.email.errors }}
|
|
25
|
+
<small>{{ donate_form.email.help_text }}</small>
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
<div class="form--row justify-content-between">
|
|
29
|
+
<div class="form__checkbox">
|
|
30
|
+
<div class="form__checkbox-input">
|
|
31
|
+
{{ donate_form.age_verification }}
|
|
32
|
+
</div>
|
|
33
|
+
<p class="p-0">Please confirm that you are over 18.</p>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
<div class="popup-box__buttons">
|
|
38
|
+
<a class="button button--small button--secondary button--secondary--dark"
|
|
39
|
+
onclick="hideDonatePopup()" aria-labelledby="cancel_button">Cancel</a>
|
|
40
|
+
<button type="submit" id="confirm_donate_button"
|
|
41
|
+
class='button button--small button--primary'
|
|
42
|
+
aria-labelledby="confirm_button">Confirm</button>
|
|
43
|
+
</div>
|
|
44
|
+
</form>
|
|
45
|
+
</div>
|
|
46
|
+
</section>
|
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
<a class="button--menu button--menu--secondary button--menu--disabled">Games</a>
|
|
58
58
|
<a class="button--menu button--menu--secondary button--menu--disabled">Teaching Resources</a>
|
|
59
59
|
{% endif %}
|
|
60
|
+
<button onclick="showDonateConfirmation()" class="button--menu button--pill button--tertiary">Donate</button>
|
|
60
61
|
{% else %}
|
|
61
62
|
{% if user|is_independent_student %}
|
|
62
63
|
<div class="menu--title">Independent</div>
|
|
@@ -103,6 +104,7 @@
|
|
|
103
104
|
<div class="menu__left-side col-md-5">
|
|
104
105
|
<a href="{% url 'teach' %}" class="button--menu button--menu--primary button--menu--enabled">Teachers</a>
|
|
105
106
|
<a href="{% url 'play' %}" class="button--menu button--menu--primary button--menu--enabled">Students</a>
|
|
107
|
+
<button id="donate" onclick="showDonateConfirmation()" class="button--menu button--pill button--tertiary">Donate</button>
|
|
106
108
|
{% endif %}
|
|
107
109
|
</div>
|
|
108
110
|
{% if user|is_logged_in %}
|
|
@@ -145,36 +147,36 @@
|
|
|
145
147
|
{% endif %}
|
|
146
148
|
</ul>
|
|
147
149
|
</div>
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
150
|
+
{% else %}
|
|
151
|
+
<div class="menu__right-side col-md-5">
|
|
152
|
+
<a href="{% url 'register' %}" id="signup_button" class="button button--primary button--register register">Register</a>
|
|
153
|
+
<div class="dropdown">
|
|
154
|
+
<button id="login_dropdown" class="button--regular button--secondary button--header--login button--dropdown"
|
|
155
|
+
data-toggle="dropdown">
|
|
156
|
+
<div class="dropdown__text">Log in</div>
|
|
157
|
+
</button>
|
|
158
|
+
<ul class="dropdown-menu header__login-options-dropdown-menu">
|
|
159
|
+
<li class="dropdown-menu__option">
|
|
160
|
+
<a id="teacher_login_button" class="button--regular" aria-labelledby="Teacher" href="{% url 'teacher_login' %}">
|
|
161
|
+
<div class="dropdown-menu__option__text">Teacher</div>
|
|
162
|
+
<span data-nosnippet class="material-icons-outlined">chevron_right</span>
|
|
163
|
+
</a>
|
|
164
|
+
</li>
|
|
165
|
+
<li class="dropdown-menu__option">
|
|
166
|
+
<a id="student_login_button" class="button--regular" aria-labelledby="Student" href="{% url 'student_login_access_code' %}">
|
|
167
|
+
<div class="dropdown-menu__option__text">Student</div>
|
|
168
|
+
<span data-nosnippet class="material-icons-outlined">chevron_right</span>
|
|
169
|
+
</a>
|
|
170
|
+
</li>
|
|
171
|
+
<li class="dropdown-menu__option">
|
|
172
|
+
<a id="independent_login_button" class="button--regular" aria-labelledby="Independent" href="{% url 'independent_student_login' %}">
|
|
173
|
+
<div class="dropdown-menu__option__text">Independent</div>
|
|
174
|
+
<span data-nosnippet class="material-icons-outlined">chevron_right</span>
|
|
175
|
+
</a>
|
|
176
|
+
</li>
|
|
177
|
+
</ul>
|
|
178
|
+
</div>
|
|
179
|
+
{% endif %}
|
|
178
180
|
</div>
|
|
179
181
|
</div>
|
|
180
182
|
<div id="menu-items" class="collapse">
|
|
@@ -239,6 +241,8 @@
|
|
|
239
241
|
{% else %}
|
|
240
242
|
<a class="button button--menu__item button--register"
|
|
241
243
|
href="{% url 'register' %}">Register now</a>
|
|
244
|
+
<button onclick="showDonateConfirmation()"
|
|
245
|
+
class="button--menu__item button--donate">Donate</button>
|
|
242
246
|
<button class="button--menu__item button--menu__item--sub-header login"
|
|
243
247
|
data-toggle="collapse" data-target="#login-tabs">Log in</button>
|
|
244
248
|
<div id="login-tabs" class="collapse">
|
portal/tests/test_emails.py
CHANGED
|
@@ -10,6 +10,7 @@ from common.helpers.emails import (
|
|
|
10
10
|
send_dotmailer_consent_confirmation_email_to_user,
|
|
11
11
|
DotmailerUserType,
|
|
12
12
|
)
|
|
13
|
+
from common.mail import address_book_ids
|
|
13
14
|
from django.test import Client
|
|
14
15
|
from django.urls import reverse
|
|
15
16
|
|
|
@@ -21,7 +22,6 @@ from example_project.portal_test_settings import (
|
|
|
21
22
|
DOTMAILER_THANKS_FOR_STAYING_CAMPAIGN_ID,
|
|
22
23
|
DOTMAILER_CREATE_CONTACT_URL,
|
|
23
24
|
DOTMAILER_DELETE_USER_BY_ID_URL,
|
|
24
|
-
DOTMAILER_MAIN_ADDRESS_BOOK_URL,
|
|
25
25
|
DOTMAILER_TEACHER_ADDRESS_BOOK_URL,
|
|
26
26
|
DOTMAILER_STUDENT_ADDRESS_BOOK_URL,
|
|
27
27
|
DOTMAILER_NO_ACCOUNT_ADDRESS_BOOK_URL,
|
|
@@ -47,7 +47,11 @@ def test_newsletter_calls_correct_requests(mocker, monkeypatch):
|
|
|
47
47
|
)
|
|
48
48
|
|
|
49
49
|
add_to_dotmailer(
|
|
50
|
-
"Ray",
|
|
50
|
+
"Ray",
|
|
51
|
+
"Charles",
|
|
52
|
+
"ray.charles@example.com",
|
|
53
|
+
address_book_ids["newsletter"],
|
|
54
|
+
DotmailerUserType.TEACHER,
|
|
51
55
|
)
|
|
52
56
|
|
|
53
57
|
mocked_create_contact.assert_called_once()
|
|
@@ -121,17 +125,15 @@ def test_newsletter_sends_correct_request_data(
|
|
|
121
125
|
)
|
|
122
126
|
|
|
123
127
|
add_contact_to_address_book(
|
|
124
|
-
"Ray",
|
|
128
|
+
"Ray",
|
|
129
|
+
"Charles",
|
|
130
|
+
"ray.charles@example.com",
|
|
131
|
+
address_book_ids["newsletter"],
|
|
132
|
+
DotmailerUserType.TEACHER,
|
|
125
133
|
)
|
|
126
134
|
|
|
127
135
|
assert mocked_post.call_count == 3
|
|
128
136
|
|
|
129
|
-
mocked_post.assert_any_call(
|
|
130
|
-
DOTMAILER_MAIN_ADDRESS_BOOK_URL,
|
|
131
|
-
auth=(DOTMAILER_USER, DOTMAILER_PASSWORD),
|
|
132
|
-
json=expected_body2,
|
|
133
|
-
)
|
|
134
|
-
|
|
135
137
|
mocked_post.assert_any_call(
|
|
136
138
|
DOTMAILER_TEACHER_ADDRESS_BOOK_URL,
|
|
137
139
|
auth=(DOTMAILER_USER, DOTMAILER_PASSWORD),
|
|
@@ -141,17 +143,15 @@ def test_newsletter_sends_correct_request_data(
|
|
|
141
143
|
mocked_post.reset_mock()
|
|
142
144
|
|
|
143
145
|
add_contact_to_address_book(
|
|
144
|
-
"Ray",
|
|
146
|
+
"Ray",
|
|
147
|
+
"Charles",
|
|
148
|
+
"ray.charles@example.com",
|
|
149
|
+
address_book_ids["newsletter"],
|
|
150
|
+
DotmailerUserType.STUDENT,
|
|
145
151
|
)
|
|
146
152
|
|
|
147
153
|
assert mocked_post.call_count == 2
|
|
148
154
|
|
|
149
|
-
mocked_post.assert_any_call(
|
|
150
|
-
DOTMAILER_MAIN_ADDRESS_BOOK_URL,
|
|
151
|
-
auth=(DOTMAILER_USER, DOTMAILER_PASSWORD),
|
|
152
|
-
json=expected_body2,
|
|
153
|
-
)
|
|
154
|
-
|
|
155
155
|
mocked_post.assert_any_call(
|
|
156
156
|
DOTMAILER_STUDENT_ADDRESS_BOOK_URL,
|
|
157
157
|
auth=(DOTMAILER_USER, DOTMAILER_PASSWORD),
|
|
@@ -164,17 +164,12 @@ def test_newsletter_sends_correct_request_data(
|
|
|
164
164
|
"Ray",
|
|
165
165
|
"Charles",
|
|
166
166
|
"ray.charles@example.com",
|
|
167
|
+
address_book_ids["newsletter"],
|
|
167
168
|
DotmailerUserType.NO_ACCOUNT,
|
|
168
169
|
)
|
|
169
170
|
|
|
170
171
|
assert mocked_post.call_count == 2
|
|
171
172
|
|
|
172
|
-
mocked_post.assert_any_call(
|
|
173
|
-
DOTMAILER_MAIN_ADDRESS_BOOK_URL,
|
|
174
|
-
auth=(DOTMAILER_USER, DOTMAILER_PASSWORD),
|
|
175
|
-
json=expected_body2,
|
|
176
|
-
)
|
|
177
|
-
|
|
178
173
|
mocked_post.assert_any_call(
|
|
179
174
|
DOTMAILER_NO_ACCOUNT_ADDRESS_BOOK_URL,
|
|
180
175
|
auth=(DOTMAILER_USER, DOTMAILER_PASSWORD),
|
|
@@ -2,7 +2,7 @@ from django.urls import reverse
|
|
|
2
2
|
from django.test import TestCase, Client
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
class
|
|
5
|
+
class TestGlobalForms(TestCase):
|
|
6
6
|
def test_newsletter_signup_successful(self):
|
|
7
7
|
url = reverse("process_newsletter_form")
|
|
8
8
|
client = Client()
|
|
@@ -18,3 +18,19 @@ class TestNewsletterFooter(TestCase):
|
|
|
18
18
|
response = client.post(url, data)
|
|
19
19
|
messages = list(response.wsgi_request._messages)
|
|
20
20
|
assert len([m for m in messages if "error" in m.tags]) == 1
|
|
21
|
+
|
|
22
|
+
def test_donate_signup_successful(self):
|
|
23
|
+
url = reverse("process_donate_form")
|
|
24
|
+
client = Client()
|
|
25
|
+
data = {"email": "valid_email@example.com", "age_verification": "on"}
|
|
26
|
+
response = client.post(url, data)
|
|
27
|
+
messages = list(response.wsgi_request._messages)
|
|
28
|
+
assert len([m for m in messages if m.tags == "success"]) == 1
|
|
29
|
+
|
|
30
|
+
def test_donate_signup_fail(self):
|
|
31
|
+
url = reverse("process_donate_form")
|
|
32
|
+
client = Client()
|
|
33
|
+
data = {"email": "invalid_email", "age_verification": "on"}
|
|
34
|
+
response = client.post(url, data)
|
|
35
|
+
messages = list(response.wsgi_request._messages)
|
|
36
|
+
assert len([m for m in messages if "error" in m.tags]) == 1
|
portal/urls.py
CHANGED
|
@@ -38,6 +38,7 @@ from portal.views.api import (
|
|
|
38
38
|
)
|
|
39
39
|
from portal.views.dotmailer import (
|
|
40
40
|
dotmailer_consent_form,
|
|
41
|
+
process_donate_form,
|
|
41
42
|
process_newsletter_form,
|
|
42
43
|
)
|
|
43
44
|
from portal.views.email import verify_email
|
|
@@ -278,6 +279,7 @@ urlpatterns = [
|
|
|
278
279
|
process_newsletter_form,
|
|
279
280
|
name="process_newsletter_form",
|
|
280
281
|
),
|
|
282
|
+
url(r"^donate_signup/$", process_donate_form, name="process_donate_form"),
|
|
281
283
|
url(r"^consent_form/$", dotmailer_consent_form, name="consent_form"),
|
|
282
284
|
url(
|
|
283
285
|
r"^verify_email/$",
|
portal/views/dotmailer.py
CHANGED
|
@@ -5,13 +5,14 @@ from common.helpers.emails import (
|
|
|
5
5
|
add_consent_record_to_dotmailer_user,
|
|
6
6
|
DotmailerUserType,
|
|
7
7
|
)
|
|
8
|
+
from common.mail import address_book_ids
|
|
8
9
|
from django.contrib import messages as messages
|
|
9
10
|
from django.http import HttpResponseRedirect, HttpResponse
|
|
10
11
|
from django.shortcuts import render
|
|
11
12
|
from django.urls import reverse_lazy
|
|
12
13
|
from django.views.decorators.csrf import csrf_exempt
|
|
13
14
|
|
|
14
|
-
from portal.forms.dotmailer import NewsletterForm, ConsentForm
|
|
15
|
+
from portal.forms.dotmailer import NewsletterForm, DonateForm, ConsentForm
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
@csrf_exempt
|
|
@@ -20,7 +21,13 @@ def process_newsletter_form(request):
|
|
|
20
21
|
newsletter_form = NewsletterForm(data=request.POST)
|
|
21
22
|
if newsletter_form.is_valid():
|
|
22
23
|
user_email = newsletter_form.cleaned_data["email"]
|
|
23
|
-
add_to_dotmailer(
|
|
24
|
+
add_to_dotmailer(
|
|
25
|
+
"",
|
|
26
|
+
"",
|
|
27
|
+
user_email,
|
|
28
|
+
address_book_ids["newsletter"],
|
|
29
|
+
DotmailerUserType.NO_ACCOUNT,
|
|
30
|
+
)
|
|
24
31
|
messages.success(request, "Thank you for signing up! 🎉")
|
|
25
32
|
return HttpResponseRedirect(reverse_lazy("home"))
|
|
26
33
|
messages.error(
|
|
@@ -33,6 +40,27 @@ def process_newsletter_form(request):
|
|
|
33
40
|
return HttpResponse(status=405)
|
|
34
41
|
|
|
35
42
|
|
|
43
|
+
@csrf_exempt
|
|
44
|
+
def process_donate_form(request):
|
|
45
|
+
if request.method == "POST":
|
|
46
|
+
donate_form = DonateForm(data=request.POST)
|
|
47
|
+
if donate_form.is_valid():
|
|
48
|
+
user_email = request.POST.get("email", "")
|
|
49
|
+
add_to_dotmailer("", "", user_email, address_book_ids["donors"])
|
|
50
|
+
messages.success(
|
|
51
|
+
request, "Thank you for registering your interest! 🎉"
|
|
52
|
+
)
|
|
53
|
+
return HttpResponseRedirect(reverse_lazy("home"))
|
|
54
|
+
messages.error(
|
|
55
|
+
request,
|
|
56
|
+
"Invalid email address. Please try again.",
|
|
57
|
+
extra_tags="sub-nav--warning",
|
|
58
|
+
)
|
|
59
|
+
return HttpResponseRedirect(reverse_lazy("home"))
|
|
60
|
+
|
|
61
|
+
return HttpResponse(status=405)
|
|
62
|
+
|
|
63
|
+
|
|
36
64
|
def dotmailer_consent_form(request):
|
|
37
65
|
if request.method == "POST":
|
|
38
66
|
consent_form = ConsentForm(data=request.POST)
|