codeforlife-portal 5.33.5__py2.py3-none-any.whl → 8.9.9__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.
Files changed (391) hide show
  1. cfl_common/common/__init__.py +1 -0
  2. cfl_common/common/app_settings.py +66 -0
  3. cfl_common/common/apps.py +6 -0
  4. cfl_common/common/context_processors.py +9 -0
  5. cfl_common/common/csp_config.py +85 -0
  6. cfl_common/common/helpers/__init__.py +0 -0
  7. cfl_common/common/helpers/data_migration_loader.py +42 -0
  8. cfl_common/common/helpers/emails.py +393 -0
  9. cfl_common/common/helpers/generators.py +52 -0
  10. cfl_common/common/helpers/organisation.py +10 -0
  11. cfl_common/common/mail.py +201 -0
  12. cfl_common/common/migrations/0001_initial.py +240 -0
  13. cfl_common/common/migrations/0002_emailverification.py +55 -0
  14. cfl_common/common/migrations/0003_aimmocharacter.py +31 -0
  15. cfl_common/common/migrations/0004_add_aimmocharacters.py +17 -0
  16. cfl_common/common/migrations/0005_add_worksheets.py +8 -0
  17. cfl_common/common/migrations/0006_update_aimmo_character_image_path.py +17 -0
  18. cfl_common/common/migrations/0007_add_pdf_names_to_first_two_worksheets.py +8 -0
  19. cfl_common/common/migrations/0008_unlock_worksheet_3.py +11 -0
  20. cfl_common/common/migrations/0009_add_blocked_time_to_teacher_and_student.py +24 -0
  21. cfl_common/common/migrations/0010_remove_teacher_title.py +18 -0
  22. cfl_common/common/migrations/0011_student_login_id.py +18 -0
  23. cfl_common/common/migrations/0012_usersession.py +39 -0
  24. cfl_common/common/migrations/0013_class_school.py +42 -0
  25. cfl_common/common/migrations/0014_login_type.py +29 -0
  26. cfl_common/common/migrations/0015_dailyactivity.py +31 -0
  27. cfl_common/common/migrations/0016_joinreleasestudent.py +42 -0
  28. cfl_common/common/migrations/0017_copy_email_to_username.py +18 -0
  29. cfl_common/common/migrations/0018_update_aimmo_character_image_path.py +15 -0
  30. cfl_common/common/migrations/0019_aimmocharacter_alt.py +16 -0
  31. cfl_common/common/migrations/0020_class_is_active_and_null_access_code.py +23 -0
  32. cfl_common/common/migrations/0021_school_is_active.py +28 -0
  33. cfl_common/common/migrations/0022_school_cleanup.py +29 -0
  34. cfl_common/common/migrations/0023_userprofile_aimmo_badges.py +22 -0
  35. cfl_common/common/migrations/0024_teacher_invited_by.py +25 -0
  36. cfl_common/common/migrations/0025_schoolteacherinvitation.py +47 -0
  37. cfl_common/common/migrations/0026_teacher_remove_join_request.py +22 -0
  38. cfl_common/common/migrations/0027_class_created_by.py +25 -0
  39. cfl_common/common/migrations/0028_coding_club_downloads.py +23 -0
  40. cfl_common/common/migrations/0029_dynamicelement.py +22 -0
  41. cfl_common/common/migrations/0030_add_maintenance_banner.py +25 -0
  42. cfl_common/common/migrations/0031_improve_admin_panel.py +56 -0
  43. cfl_common/common/migrations/0032_dailyactivity_level_control_submits.py +18 -0
  44. cfl_common/common/migrations/0033_password_reset_tracking_fields.py +23 -0
  45. cfl_common/common/migrations/0034_dailyactivity_daily_school_student_lockout_reset.py +18 -0
  46. cfl_common/common/migrations/0035_rename_lockout_fields.py +27 -0
  47. cfl_common/common/migrations/0036_rename_awaiting_email_verification_userprofile_is_verified.py +17 -0
  48. cfl_common/common/migrations/0037_migrate_email_verification.py +21 -0
  49. cfl_common/common/migrations/0038_delete_emailverification.py +16 -0
  50. cfl_common/common/migrations/0039_copy_email_to_username.py +18 -0
  51. cfl_common/common/migrations/0040_school_county.py +18 -0
  52. cfl_common/common/migrations/0041_populate_gb_counties.py +27 -0
  53. cfl_common/common/migrations/0042_totalactivity.py +25 -0
  54. cfl_common/common/migrations/0043_add_total_activity.py +30 -0
  55. cfl_common/common/migrations/0044_update_activity_models.py +33 -0
  56. cfl_common/common/migrations/0045_otp.py +23 -0
  57. cfl_common/common/migrations/0046_alter_school_country.py +19 -0
  58. cfl_common/common/migrations/0047_delete_school_postcode.py +16 -0
  59. cfl_common/common/migrations/0048_unique_school_names.py +42 -0
  60. cfl_common/common/migrations/0049_anonymise_orphan_users.py +29 -0
  61. cfl_common/common/migrations/0050_anonymise_orphan_schools.py +30 -0
  62. cfl_common/common/migrations/0051_verify_returning_users.py +26 -0
  63. cfl_common/common/migrations/0052_add_cse_fields.py +68 -0
  64. cfl_common/common/migrations/0053_clean_class_data.py +24 -0
  65. cfl_common/common/migrations/0054_delete_aimmo_models.py +20 -0
  66. cfl_common/common/migrations/0055_alter_schoolteacherinvitation_token.py +18 -0
  67. cfl_common/common/migrations/0056_set_non_school_teachers_as_non_admins.py +25 -0
  68. cfl_common/common/migrations/0057_teacher_teacher__is_admin.py +19 -0
  69. cfl_common/common/migrations/0058_userprofile_google_refresh_token_and_more.py +24 -0
  70. cfl_common/common/migrations/__init__.py +0 -0
  71. cfl_common/common/models.py +557 -0
  72. cfl_common/common/permissions.py +84 -0
  73. cfl_common/common/tests/__init__.py +0 -0
  74. cfl_common/common/tests/test_migration_anonymise_orphan_schools.py +30 -0
  75. cfl_common/common/tests/test_migration_anonymise_orphan_users.py +30 -0
  76. cfl_common/common/tests/test_migration_blocked_time.py +15 -0
  77. cfl_common/common/tests/test_migration_remove_teacher_title.py +13 -0
  78. cfl_common/common/tests/test_migration_unique_school_names.py +33 -0
  79. cfl_common/common/tests/test_migration_verify_returning_users.py +59 -0
  80. cfl_common/common/tests/test_models.py +87 -0
  81. cfl_common/common/tests/utils/__init__.py +0 -0
  82. cfl_common/common/tests/utils/classes.py +38 -0
  83. cfl_common/common/tests/utils/email.py +67 -0
  84. cfl_common/common/tests/utils/organisation.py +41 -0
  85. cfl_common/common/tests/utils/student.py +123 -0
  86. cfl_common/common/tests/utils/teacher.py +73 -0
  87. cfl_common/common/tests/utils/user.py +27 -0
  88. cfl_common/common/utils.py +56 -0
  89. cfl_common/setup.py +61 -0
  90. codeforlife_portal-8.9.9.dist-info/METADATA +226 -0
  91. {codeforlife_portal-5.33.5.dist-info → codeforlife_portal-8.9.9.dist-info}/RECORD +339 -241
  92. {codeforlife_portal-5.33.5.dist-info → codeforlife_portal-8.9.9.dist-info}/WHEEL +1 -1
  93. codeforlife_portal-8.9.9.dist-info/licenses/LICENSE.md +3 -0
  94. {codeforlife_portal-5.33.5.dist-info → codeforlife_portal-8.9.9.dist-info}/top_level.txt +1 -0
  95. deploy/middleware/maintenance.py +25 -0
  96. deploy/middleware/screentime_warning.py +29 -0
  97. deploy/middleware/security.py +5 -6
  98. deploy/middleware/session_timeout.py +4 -2
  99. deploy/middleware/tmp_basic_auth.py +41 -0
  100. example_project/portal_test_settings.py +239 -0
  101. example_project/settings.py +156 -17
  102. example_project/urls.py +5 -6
  103. portal/__init__.py +1 -1
  104. portal/admin.py +142 -29
  105. portal/app_settings.py +8 -7
  106. portal/forms/dotmailer.py +6 -4
  107. portal/forms/invite_teacher.py +19 -10
  108. portal/forms/organisation.py +137 -68
  109. portal/forms/play.py +53 -98
  110. portal/forms/registration.py +70 -164
  111. portal/forms/teach.py +147 -121
  112. portal/handlers.py +1 -2
  113. portal/helpers/decorators.py +30 -10
  114. portal/helpers/password.py +86 -47
  115. portal/helpers/ratelimit.py +32 -15
  116. portal/helpers/regexes.py +5 -0
  117. portal/helpers/request_handlers.py +10 -0
  118. portal/migrations/0044_auto_20150430_0959.py +6 -2
  119. portal/mixins/__init__.py +1 -0
  120. portal/mixins/cron_mixin.py +12 -0
  121. portal/permissions/__init__.py +1 -0
  122. portal/permissions/is_cron_request_from_google.py +14 -0
  123. portal/static/portal/img/10_years_anniversary.png +0 -0
  124. portal/static/portal/img/RR_logo_grass_background.png +0 -0
  125. portal/static/portal/img/coding_club_hero.jpg +0 -0
  126. portal/static/portal/img/coding_club_python_pack.png +0 -0
  127. portal/static/portal/img/facebook.png +0 -0
  128. portal/static/portal/img/gitbook.png +0 -0
  129. portal/static/portal/img/howe_dell_1.png +0 -0
  130. portal/static/portal/img/howe_dell_2.png +0 -0
  131. portal/static/portal/img/howe_dell_3.png +0 -0
  132. portal/static/portal/img/logo_cfl.png +0 -0
  133. portal/static/portal/img/logo_cfl_powered.svg +35 -0
  134. portal/static/portal/img/logo_cfl_reminder_cards.jpg +0 -0
  135. portal/static/portal/img/logo_ocado_group.png +0 -0
  136. portal/static/portal/img/logo_python_den.svg +21 -0
  137. portal/static/portal/img/long_europe_map.png +0 -0
  138. portal/static/portal/img/python_den.png +0 -0
  139. portal/static/portal/img/python_den_banner.svg +26 -0
  140. portal/static/portal/img/rapid_router_landing_hero.png +0 -0
  141. portal/static/portal/img/rr_advanced.png +0 -0
  142. portal/static/portal/img/ten_year_map_pin.svg +1 -0
  143. portal/static/portal/img/thumbnail_educate_rapid_router.png +0 -0
  144. portal/static/portal/img/thumbnail_educate_resources.png +0 -0
  145. portal/static/portal/img/thumbnail_play_rapid_router.png +0 -0
  146. portal/static/portal/img/thumbnail_python_den.png +0 -0
  147. portal/static/portal/img/twitter.png +0 -0
  148. portal/static/portal/js/carouselCards.js +25 -0
  149. portal/static/portal/js/common.js +96 -1
  150. portal/static/portal/js/independentLogin.js +16 -0
  151. portal/static/portal/js/independentRegistration.js +86 -0
  152. portal/static/portal/js/levelControl.js +77 -0
  153. portal/static/portal/js/lib/jquery.min.js +2 -0
  154. portal/static/portal/js/organisation_manage.js +142 -14
  155. portal/static/portal/js/passwordStrength.js +154 -64
  156. portal/static/portal/js/resetPassword.js +23 -0
  157. portal/static/portal/js/riveted.min.js +238 -239
  158. portal/static/portal/js/school.js +13 -0
  159. portal/static/portal/js/studentLogin.js +16 -0
  160. portal/static/portal/js/teacherEditStudent.js +23 -0
  161. portal/static/portal/js/teacherLogin.js +16 -0
  162. portal/static/portal/js/tenYearMap.js +14 -0
  163. portal/static/portal/sass/colorbox.scss +0 -1
  164. portal/static/portal/sass/modules/_colours.scss +1 -0
  165. portal/static/portal/sass/modules/_levels.scss +1 -1
  166. portal/static/portal/sass/modules/_mixins.scss +21 -0
  167. portal/static/portal/sass/partials/_banners.scss +4 -177
  168. portal/static/portal/sass/partials/_buttons.scss +12 -15
  169. portal/static/portal/sass/partials/_carousel.scss +129 -0
  170. portal/static/portal/sass/partials/_footer.scss +21 -22
  171. portal/static/portal/sass/partials/_forms.scss +60 -5
  172. portal/static/portal/sass/partials/_grids.scss +34 -61
  173. portal/static/portal/sass/partials/_header.scss +28 -20
  174. portal/static/portal/sass/partials/_images.scss +292 -39
  175. portal/static/portal/sass/partials/_popup.scss +18 -15
  176. portal/static/portal/sass/partials/_tables.scss +12 -20
  177. portal/static/portal/sass/partials/_text.scss +6 -10
  178. portal/static/portal/sass/styles.scss +0 -1
  179. portal/static/portal/video/code for life .pdf +0 -0
  180. portal/strings/about.py +5 -0
  181. portal/strings/coding_club.py +9 -0
  182. portal/strings/play.py +6 -5
  183. portal/strings/teach.py +1 -1
  184. portal/strings/teacher_resources.py +2 -8
  185. portal/strings/ten_year_map.py +13 -0
  186. portal/templates/403.html +2 -2
  187. portal/templates/404.html +1 -1
  188. portal/templates/500.html +2 -2
  189. portal/templates/{captcha → django_recaptcha}/includes/js_v2_invisible.html +3 -3
  190. portal/templates/{captcha → django_recaptcha}/widget_v2_invisible.html +2 -2
  191. portal/templates/email.html +4 -2
  192. portal/templates/maintenance.html +34 -0
  193. portal/templates/portal/about.html +94 -62
  194. portal/templates/portal/base.html +176 -152
  195. portal/templates/portal/coding_club.html +100 -0
  196. portal/templates/portal/contribute.html +56 -52
  197. portal/templates/portal/email_invitation_sent.html +1 -1
  198. portal/templates/portal/email_style_template.html +374 -0
  199. portal/templates/portal/email_verification_failed.html +1 -1
  200. portal/templates/portal/email_verification_needed.html +9 -9
  201. portal/templates/portal/form_shapes.html +20 -8
  202. portal/templates/portal/getinvolved.html +6 -6
  203. portal/templates/portal/home.html +35 -10
  204. portal/templates/portal/home_learning.html +19 -19
  205. portal/templates/portal/locked_out.html +0 -1
  206. portal/templates/portal/locked_out_school_student.html +16 -0
  207. portal/templates/portal/login/independent_student.html +31 -15
  208. portal/templates/portal/login/student.html +10 -7
  209. portal/templates/portal/login/student_class_code.html +7 -4
  210. portal/templates/portal/login/teacher.html +34 -17
  211. portal/templates/portal/partials/banner.html +18 -4
  212. portal/templates/portal/partials/benefits.html +1 -1
  213. portal/templates/portal/partials/card_list.html +34 -24
  214. portal/templates/portal/partials/character_list.html +5 -5
  215. portal/templates/portal/partials/cookie_list.html +161 -0
  216. portal/templates/portal/partials/delete_popup.html +18 -0
  217. portal/templates/portal/partials/footer.html +57 -26
  218. portal/templates/portal/partials/header.html +118 -117
  219. portal/templates/portal/partials/hero_card.html +4 -3
  220. portal/templates/portal/partials/info_popup.html +3 -3
  221. portal/templates/portal/partials/invite_admin_teacher.html +23 -0
  222. portal/templates/portal/partials/popup.html +7 -2
  223. portal/templates/portal/partials/register_newsletter_tickbox.html +2 -5
  224. portal/templates/portal/partials/screentime_popup.html +14 -0
  225. portal/templates/portal/partials/service_unavailable_popup.html +17 -0
  226. portal/templates/portal/partials/session_popup.html +19 -0
  227. portal/templates/portal/play/student_dashboard.html +42 -29
  228. portal/templates/portal/play/student_edit_account.html +64 -9
  229. portal/templates/portal/play.html +61 -41
  230. portal/templates/portal/privacy_notice.html +697 -0
  231. portal/templates/portal/register.html +122 -92
  232. portal/templates/portal/reset_password.html +20 -40
  233. portal/templates/portal/reset_password_confirm.html +9 -4
  234. portal/templates/portal/reset_password_email_sent.html +15 -13
  235. portal/templates/portal/teach/base_registering.html +1 -1
  236. portal/templates/portal/teach/class.html +4 -6
  237. portal/templates/portal/teach/dashboard.html +212 -117
  238. portal/templates/portal/teach/invited.html +90 -0
  239. portal/templates/portal/teach/onboarding_classes.html +5 -3
  240. portal/templates/portal/teach/onboarding_print.html +1 -1
  241. portal/templates/portal/teach/onboarding_school.html +26 -139
  242. portal/templates/portal/teach/onboarding_students.html +1 -1
  243. portal/templates/portal/teach/teacher_dismiss_students.html +73 -55
  244. portal/templates/portal/teach/teacher_edit_class.html +168 -11
  245. portal/templates/portal/teach/teacher_edit_student.html +12 -5
  246. portal/templates/portal/teach/teacher_move_all_classes.html +25 -38
  247. portal/templates/portal/teach/teacher_move_students_to_class.html +1 -1
  248. portal/templates/portal/teach.html +61 -42
  249. portal/templates/portal/ten_year_map.html +147 -0
  250. portal/templates/portal/terms.html +191 -42
  251. portal/templates/two_factor/core/login.html +71 -59
  252. portal/templates/two_factor/core/setup.html +58 -49
  253. portal/templates/two_factor/profile/disable.html +1 -1
  254. portal/templates/two_factor/profile/profile.html +35 -17
  255. portal/templatetags/app_tags.py +59 -84
  256. portal/templatetags/card_list_tags.py +0 -4
  257. portal/tests/base_test.py +14 -3
  258. portal/tests/conftest.py +0 -15
  259. portal/tests/migrations/test_migration_make_portaladmin_teacher.py +2 -6
  260. portal/tests/migrations/test_migration_preview_users.py +3 -9
  261. portal/tests/migrations/test_migration_remove_guardian.py +1 -3
  262. portal/tests/migrations/test_migration_use_common_models.py +2 -6
  263. portal/tests/migrations/test_migration_verify_portaladmin.py +1 -3
  264. portal/tests/pageObjects/portal/admin/admin_base_page.py +0 -21
  265. portal/tests/pageObjects/portal/base_page.py +16 -26
  266. portal/tests/pageObjects/portal/email_verification_needed_page.py +3 -2
  267. portal/tests/pageObjects/portal/game_page.py +12 -19
  268. portal/tests/pageObjects/portal/home_page.py +13 -15
  269. portal/tests/pageObjects/portal/independent_login_page.py +13 -17
  270. portal/tests/pageObjects/portal/password_reset_form_page.py +20 -4
  271. portal/tests/pageObjects/portal/password_reset_page.py +25 -0
  272. portal/tests/pageObjects/portal/play/account_page.py +18 -27
  273. portal/tests/pageObjects/portal/play/dashboard_page.py +4 -4
  274. portal/tests/pageObjects/portal/play/join_school_or_club_page.py +8 -10
  275. portal/tests/pageObjects/portal/play/play_base_page.py +5 -3
  276. portal/tests/pageObjects/portal/signup_page.py +28 -59
  277. portal/tests/pageObjects/portal/student_login_class_code.py +6 -9
  278. portal/tests/pageObjects/portal/student_login_page.py +6 -8
  279. portal/tests/pageObjects/portal/teach/add_independent_student_to_class_page.py +3 -3
  280. portal/tests/pageObjects/portal/teach/added_independent_student_to_class_page.py +3 -1
  281. portal/tests/pageObjects/portal/teach/class_page.py +36 -13
  282. portal/tests/pageObjects/portal/teach/dashboard_page.py +43 -84
  283. portal/tests/pageObjects/portal/teach/dismiss_students_page.py +7 -5
  284. portal/tests/pageObjects/portal/teach/edit_student_page.py +10 -8
  285. portal/tests/pageObjects/portal/teach/move_class_page.py +5 -10
  286. portal/tests/pageObjects/portal/teach/move_classes_page.py +4 -2
  287. portal/tests/pageObjects/portal/teach/move_students_disambiguate_page.py +4 -2
  288. portal/tests/pageObjects/portal/teach/move_students_page.py +6 -13
  289. portal/tests/pageObjects/portal/teach/onboarding_classes_page.py +5 -3
  290. portal/tests/pageObjects/portal/teach/onboarding_organisation_page.py +11 -49
  291. portal/tests/pageObjects/portal/teach/onboarding_student_list_page.py +7 -12
  292. portal/tests/pageObjects/portal/teach/onboarding_students_page.py +4 -27
  293. portal/tests/pageObjects/portal/teach/teach_base_page.py +6 -4
  294. portal/tests/pageObjects/portal/teacher_login_page.py +10 -16
  295. portal/tests/selenium_test_case.py +3 -43
  296. portal/tests/snapshots/snap_test_partials.py +11 -165
  297. portal/tests/test_2FA.py +15 -33
  298. portal/tests/test_admin.py +15 -97
  299. portal/tests/test_api.py +212 -91
  300. portal/tests/test_captcha_forms.py +2 -2
  301. portal/tests/test_class.py +374 -24
  302. portal/tests/test_emails.py +83 -20
  303. portal/tests/{test_newsletter_footer.py → test_global_forms.py} +5 -5
  304. portal/tests/test_helper_methods.py +30 -0
  305. portal/tests/test_independent_student.py +255 -144
  306. portal/tests/test_invite_teacher.py +318 -10
  307. portal/tests/test_middleware.py +96 -9
  308. portal/tests/test_organisation.py +78 -262
  309. portal/tests/test_partials.py +0 -88
  310. portal/tests/test_ratelimit.py +218 -36
  311. portal/tests/test_school_student.py +35 -40
  312. portal/tests/test_security.py +12 -31
  313. portal/tests/test_teacher.py +425 -325
  314. portal/tests/test_teacher_student.py +103 -91
  315. portal/tests/test_views.py +900 -76
  316. portal/tests/utils/classes.py +2 -2
  317. portal/tests/utils/messages.py +13 -28
  318. portal/urls.py +235 -166
  319. portal/views/admin.py +0 -332
  320. portal/views/api.py +82 -48
  321. portal/views/cron/__init__.py +1 -0
  322. portal/views/cron/user.py +322 -0
  323. portal/views/dotmailer.py +9 -1
  324. portal/views/email.py +33 -77
  325. portal/views/google_analytics.py +28 -0
  326. portal/views/home.py +126 -97
  327. portal/views/legal.py +13 -0
  328. portal/views/login/independent_student.py +5 -5
  329. portal/views/login/student.py +51 -14
  330. portal/views/login/teacher.py +2 -6
  331. portal/views/organisation.py +20 -189
  332. portal/views/registration.py +97 -17
  333. portal/views/student/edit_account_details.py +99 -72
  334. portal/views/student/play.py +81 -62
  335. portal/views/teacher/dashboard.py +421 -149
  336. portal/views/teacher/teach.py +226 -177
  337. portal/views/two_factor/core.py +22 -19
  338. portal/views/two_factor/profile.py +2 -2
  339. codeforlife_portal-5.33.5.dist-info/LICENSE.md +0 -577
  340. codeforlife_portal-5.33.5.dist-info/METADATA +0 -38
  341. deploy/permissions.py +0 -2
  342. example_project/manage.py +0 -10
  343. portal/autoconfig.py +0 -141
  344. portal/csp_config.py +0 -60
  345. portal/forms/add_game.py +0 -33
  346. portal/helpers/location.py +0 -121
  347. portal/static/portal/img/kurono_hero.jpg +0 -0
  348. portal/static/portal/img/kurono_landing_hero.png +0 -0
  349. portal/static/portal/img/kurono_logo.svg +0 -1
  350. portal/static/portal/img/kurono_logo_grey_background.svg +0 -1
  351. portal/static/portal/img/kurono_logo_mark.svg +0 -1
  352. portal/static/portal/img/kurono_resources_hero.jpg +0 -0
  353. portal/static/portal/img/kurono_story.png +0 -0
  354. portal/static/portal/img/ocado-swirl.svg +0 -22
  355. portal/static/portal/img/thumbnail_educate_kurono.png +0 -0
  356. portal/static/portal/img/thumbnail_educate_resources_and_progress_tracking.png +0 -0
  357. portal/static/portal/img/thumbnail_kurono_resources.png +0 -0
  358. portal/static/portal/img/thumbnail_play_kurono.png +0 -0
  359. portal/static/portal/img/x_close_video.png +0 -0
  360. portal/static/portal/js/aimmoGame.js +0 -106
  361. portal/static/portal/js/deleteWorkspaces.js +0 -14
  362. portal/static/portal/js/fuzzySchoolLookup.js +0 -46
  363. portal/static/portal/js/lib/jquery-3.5.1.min.js +0 -2
  364. portal/static/portal/js/lib/jquery-ui-1.12.1.min.js +0 -13
  365. portal/static/portal/sass/partials/_videos.scss +0 -10
  366. portal/static/portal/video/aimmo_play_now_background_video.mp4 +0 -0
  367. portal/strings/student_aimmo_dashboard.py +0 -6
  368. portal/templates/portal/admin/aggregated_data.html +0 -35
  369. portal/templates/portal/admin/map.html +0 -70
  370. portal/templates/portal/mouseflow.html +0 -9
  371. portal/templates/portal/partials/aimmo_games_table.html +0 -83
  372. portal/templates/portal/partials/register_over_required_age_tickbox.html +0 -9
  373. portal/templates/portal/play/independent_student_dashboard.html +0 -64
  374. portal/templates/portal/play/student_aimmo_dashboard.html +0 -63
  375. portal/templates/portal/privacy_policy.html +0 -483
  376. portal/templates/portal/reset_password_email.html +0 -9
  377. portal/templates/portal/teach/invite.html +0 -25
  378. portal/templates/portal/teach/teacher_aimmo_dashboard.html +0 -95
  379. portal/templates/portal/teach/teacher_resources.html +0 -68
  380. portal/templatetags/character_list_tags.py +0 -16
  381. portal/tests/pageObjects/portal/kurono_teacher_dashboard_page.py +0 -49
  382. portal/tests/pageObjects/portal/student_password_reset_form_page.py +0 -23
  383. portal/tests/pageObjects/portal/teach/onboarding_revoke_request_page.py +0 -20
  384. portal/tests/pageObjects/portal/teacher_password_reset_form_page.py +0 -23
  385. portal/tests/test_aimmo_dashboards.py +0 -172
  386. portal/tests/test_location.py +0 -217
  387. portal/tests/utils/aimmo_games.py +0 -30
  388. portal/views/aimmo/dashboard.py +0 -119
  389. portal/views/privacy_policy.py +0 -9
  390. portal/views/teacher/teacher_resources.py +0 -42
  391. {portal/views/aimmo → cfl_common}/__init__.py +0 -0
@@ -1,5 +1,5 @@
1
1
  {% extends 'portal/base.html' %}
2
- {% load staticfiles %}
2
+ {% load static %}
3
3
  {% load app_tags %}
4
4
 
5
5
  {% block scripts %}
@@ -8,46 +8,22 @@
8
8
  <script>
9
9
  var CONFIRMATION_DATA = {};
10
10
 
11
- // store current hash, then remove it so the page doesn't jump to the section
12
- const currentHash = window.location.hash
13
- window.location.hash = ''
14
-
15
- function updateLocationHash(hash) {
16
- // using replaceState as changing hash directly will scroll to element
17
- history.replaceState({}, '', hash)
18
- }
19
-
20
11
  $(document).ready(function(){
21
- // select the tab based on the current location hash
22
- const tabs = $('.sub-nav [data-toggle="tab"]')
23
- const tabNames = tabs.map((index, element) => $(element).attr('href')).toArray()
24
- const currentTabIndex = tabNames.indexOf(currentHash)
25
- if (currentTabIndex < 0) {
26
- updateLocationHash(tabNames[0])
27
- }
28
- else {
29
- updateLocationHash(tabNames[currentTabIndex])
30
- tabs[currentTabIndex].click()
31
- animate($(tabNames[currentTabIndex]).offset().top - bannerHeight)
32
- }
33
-
34
- // make each tab update the current location hash on click
35
- tabs.on('shown.bs.tab', (event) => {
36
- updateLocationHash(event.target.hash)
37
- window.scrollTo(0, 0)
38
- })
39
-
40
12
  $("#update-details").on("click", () => {
41
13
  $("#tab-account").click()
42
14
  })
43
15
 
16
+ {% if delete_account_confirm %}
17
+ showDeleteAccountConfirmation("{{ delete_account_form.delete_password.value }}", "{{ delete_account_form.unsubscribe_newsletter.value }}", {{ user.new_teacher.has_class|yesno:"true,false" }});
18
+ {% endif %}
19
+
44
20
  {% if show_onboarding_complete %}
45
21
  let title = "Registration complete! 🎉";
46
22
  let text = "<div class='popup-text'><small>You have successfully completed your registration and can now access and edit all of the information for your students through the teacher dashboard.</small></div>";
47
23
 
48
24
  showInfoPopup(title, text);
49
25
  {% endif %}
50
- })
26
+ })
51
27
  </script>
52
28
  {% endblock scripts %}
53
29
 
@@ -55,7 +31,11 @@
55
31
  <section class="banner banner--teacher">
56
32
  <h1 class="banner__text--primary">Welcome back, {{ user|make_into_username }}</h1>
57
33
  </section>
34
+ {% if teacher.school %}
58
35
  <div class="sticky-subnav sub-nav sub-nav--teacher">
36
+ {% else %}
37
+ <div class="sticky-subnav sub-nav sub-nav--teacher" style="display: none;">
38
+ {% endif %}
59
39
  <ul class="nav is-flex" role="tablist">
60
40
  <li class="active"><a id="tab-school" class="button button--secondary button--secondary--light" data-toggle="tab" href="#school">Your school</a></li>
61
41
  <li><a id="tab-classes" class="button button--secondary button--secondary--light" data-toggle="tab" href="#classes">Your classes</a></li>
@@ -66,6 +46,8 @@
66
46
 
67
47
  {% block content %}
68
48
  {% include "portal/partials/popup.html" %}
49
+ {% include "portal/partials/delete_popup.html" %}
50
+ {% include "portal/partials/invite_admin_teacher.html" %}
69
51
 
70
52
  {% if show_onboarding_complete %}
71
53
  {% include "portal/partials/info_popup.html" %}
@@ -75,25 +57,62 @@
75
57
 
76
58
  <div class="tab-content">
77
59
  <div id="school" class="tab-pane active">
78
- {% if is_admin and join_requests %}
79
- <div id="sticky-warning" class="sub-nav sub-nav--warning">
80
- <span class="iconify sub-nav--icon" data-icon="mdi:alert-outline"></span>
81
- <p><small><strong>You have pending requests from teachers wanting to join your school or club.
82
- <a id="requests_button" href="#requests">View the requests</a></strong></small></p>
83
- </div>
84
- {% endif %}
85
60
  <div class="background container">
86
61
  <section>
87
- <h4>Your school: {% if user.new_teacher.school %} {{ user.new_teacher.school.name }} ({{ user.new_teacher.school.postcode }}){% endif %}</h4>
62
+ <h4>Your school: {% if user.new_teacher.school %} {{ user.new_teacher.school.name }}{% endif %}</h4>
88
63
  </section>
89
64
  {% if is_admin %}
90
- <p>As an administrator of your school or club, you can select other teachers to whom you can provide or revoke
91
- administrative rights. You can also remove teachers from your school or club if they leave, and respond to requests from new teachers
92
- joining your organisation.</p>
93
- <section>
94
- <a href="{% url 'invite_teacher' %}" class="button button--primary button--icon" name="invite_teacher">
95
- Invite a teacher<span class="iconify" data-icon="mdi:account-plus"></span></a>
96
- </section>
65
+ <p>
66
+ As an administrator of your school or club, you can select other teachers to whom you can provide or revoke
67
+ administrative rights. You can also add and remove teachers from your school or club. As administrator, you have the ability
68
+ to see and amend other teachers' classes. Please bear this in mind when assigning admin rights to other teachers.
69
+ </p>
70
+
71
+ <h5>Invite teachers to your school</h5>
72
+ <form autocomplete="off" method="post" class="p-0" onsubmit="showMakeAdminTeacherPopup(event)">
73
+ {% csrf_token %}
74
+
75
+ {{ invite_teacher_form.non_field_errors }}
76
+
77
+ <div class="row form--row">
78
+ <div class="form--row__input col-sm-4 col-md-4">
79
+ <div class="input--icon">
80
+ {{ invite_teacher_form.teacher_first_name }}<span class="iconify" data-icon="mdi:account-outline"></span>
81
+ </div>
82
+ <small>{{ invite_teacher_form.teacher_first_name.help_text }}</small>
83
+ {{ invite_teacher_form.teacher_first_name.errors }}
84
+ </div>
85
+ <div class="form--row__input col-sm-4 col-md-4">
86
+ <div class="input--icon">
87
+ {{ invite_teacher_form.teacher_last_name }}<span class="iconify" data-icon="mdi:account-outline"></span>
88
+ </div>
89
+ <small>{{ invite_teacher_form.teacher_last_name.help_text }}</small>
90
+ {{ invite_teacher_form.teacher_last_name.errors }}
91
+ </div>
92
+ <div class="form--row__input col-sm-4 col-md-4">
93
+ <div class="input--icon">
94
+ {{ invite_teacher_form.teacher_email }}<span class="iconify" data-icon="mdi:email-outline"></span>
95
+ </div>
96
+ <small>{{ invite_teacher_form.teacher_email.help_text }}</small>
97
+ {{ invite_teacher_form.teacher_email.errors }}
98
+ </div>
99
+ </div>
100
+ <div class="row form--row">
101
+ <div class="form--row__input col-sm-12 col-md-12">
102
+ <div class="form__checkbox">
103
+ <div class="form__checkbox-input">
104
+ {{ invite_teacher_form.make_admin_ticked }}
105
+ </div>
106
+ <label for="id_{{ invite_teacher_form.make_admin_ticked.html_name }}">{{ invite_teacher_form.make_admin_ticked.label }}</label>
107
+ </div>
108
+ {{ invite_teacher_form.make_admin_ticked.errors }}
109
+ </div>
110
+ </div>
111
+ <input type="hidden" name="invite_teacher"/>
112
+ <button id="invite_teacher_button" type="submit" class="button button--primary button--icon m-0" name="invite_teacher_button">
113
+ Invite teacher<span class="iconify" data-icon="mdi:email-outline"></span>
114
+ </button>
115
+ </form>
97
116
  {% else %}
98
117
  <h5>You can see which other teachers in your school or club are registered here. Should you need to leave the
99
118
  school or club, you can do so below.</h5>
@@ -127,7 +146,7 @@
127
146
  Revoke admin<span class="iconify" data-icon="mdi:block"></span></button>
128
147
  {% else %}
129
148
  <button id="make_admin_button" class="button button--small button--primary button--icon"
130
- onclick="showToggleAdminConfirmation('{% url 'organisation_toggle_admin' coworker.id %}', '{{ coworker.new_user.first_name|striptags | escapejs}}')">
149
+ onclick="showToggleAdminConfirmation('{% url 'organisation_toggle_admin' coworker.id %}')">
131
150
  Make admin<span class="iconify" data-icon="mdi:plus"></span></button>
132
151
  {% endif %}
133
152
  {% if coworker.new_user|has_2FA %}
@@ -147,6 +166,37 @@
147
166
  {% endif %}
148
167
  </tr>
149
168
  {% endfor %}
169
+ {% for sent_invite in sent_invites %}
170
+ <tr>
171
+ <td>
172
+ <p>
173
+ <small>
174
+ {{ sent_invite.invited_teacher_first_name }}
175
+ {{ sent_invite.invited_teacher_last_name }}
176
+ {% if sent_invite.is_expired %}
177
+ <b>(expired)</b>
178
+ {% else %}
179
+ <b>(pending)</b>
180
+ {% endif %}
181
+ </small>
182
+ </p>
183
+ </td>
184
+ <td><p><small>{% if sent_invite.invited_teacher_is_admin %} Administrator {% else %} Standard Teacher {% endif %} ({{ sent_invite.invited_teacher_email|emaildomain }})</small></p></td>
185
+ <td class="cell-center">
186
+ {% if sent_invite.invited_teacher_is_admin %}
187
+ <button id="make_non_admin_button_invite" class='button button--small button--primary--danger button--icon'
188
+ onclick="postWithCsrf('{% url 'invite_toggle_admin' sent_invite.id %}');">
189
+ Revoke admin<span class="iconify" data-icon="mdi:block"></span></button>
190
+ {% else %}
191
+ <button id="make_admin_button_invite" class="button button--small button--primary button--icon"
192
+ onclick="showToggleAdminConfirmation('{% url 'invite_toggle_admin' sent_invite.id %}')">
193
+ Make admin<span class="iconify" data-icon="mdi:plus"></span></button>
194
+ {% endif %}
195
+ <button onclick="postWithCsrf('{% url 'resend_invite_teacher' sent_invite.token %}')" id="resend-invite" class="button button--small button--primary button--icon" >Resend invite<span class="iconify" data-icon="mdi:email-outline"></span></button>
196
+ <button onclick="postWithCsrf('{% url 'delete_teacher_invite' sent_invite.token %}')" id="delete-invite" class="button button--small button--primary--danger button--icon">Delete<span class="iconify" data-icon="mdi:delete-outline"></span></button>
197
+ </td>
198
+ </tr>
199
+ {% endfor %}
150
200
  </table>
151
201
  <div class="row">
152
202
  <p class="col-sm-6">Select ‘Delete’ to delete a teacher from your school or club. You will be able to move any existing classes assigned to that
@@ -176,48 +226,18 @@
176
226
  {% endif %}
177
227
 
178
228
  {% if is_admin %}
179
- <div id="requests" class="background container">
180
- {% if join_requests %}
181
- <h5>These teachers have requested to join your school or club</h5>
182
- <table id="request_table" class="header-primary data-primary">
183
- <tr>
184
- <th><p>Name</p></th>
185
- <th><p>Email address</p></th>
186
- <th colspan="3"><p>Actions</p></th>
187
- </tr>
188
- {% for join_request in join_requests %}
189
- <tr>
190
- <td><p><small>{{ join_request.new_user.first_name }} {{ join_request.new_user.last_name }}</small></p></td>
191
- <td><p><small>{{ join_request.new_user.email }}</small></p></td>
192
- <td class="cell-center" colspan="3">
193
- <button id="allow_button" class="button button--small button--primary button--icon"
194
- onclick="postWithCsrf('{% url 'organisation_allow_join' join_request.id %}');">
195
- Allow<span class="iconify" data-icon="mdi:plus"></span></button>
196
- <button id="deny_button" class="button button--small button--primary--danger button--icon"
197
- onclick="postWithCsrf('{% url 'organisation_deny_join' join_request.id %}');">
198
- Deny<span class="iconify" data-icon="mdi:block"></span></button>
199
- </td>
200
- </tr>
201
- {% endfor %}
202
- </table>
203
- {% else %}
204
- <h5>No teachers have currently requested to join your school or club.</h5>
205
- {% endif %}
206
- </div>
207
229
  <div id="school-details" class="background background--primary">
208
230
  <div class="container">
209
231
  <h5>Update details of your school or club</h5>
210
- <p>Update your school or club’s name and/or postcode.</p>
211
- <strong>These details are used to allow other teachers to join your team.</strong>
212
- <form id="edit_form" method="post">
232
+ <form autocomplete="off" id="edit_form" method="post">
213
233
  {% csrf_token %}
214
234
  {{ update_school_form.non_field_errors }}
215
235
  <div class="row form--row">
216
236
  {% for field in update_school_form %}
217
- <div class="form--row__input col-sm-6 col-md-4">
237
+ <div id="form-row-{{ field.name }}" class="form--row__input col-sm-6 col-md-4">
218
238
  <div class="input--icon">
219
239
  {{ field }}
220
- {% if not field == update_school_form.country %}
240
+ {% if not field == update_school_form.country and not field == update_school_form.county %}
221
241
  <span class="iconify" data-icon="mdi:domain"></span>
222
242
  {% endif %}
223
243
  </div>
@@ -240,28 +260,44 @@
240
260
  <section>
241
261
  <h4>Your classes</h4>
242
262
  </section>
243
- <p>Below is a list of all the classes you teach. You can add a class or edit your existing classes. You can also accept or deny
244
- requests from independent students wanting to join one of your classes.</p>
263
+ <p>Below is a list of all the classes in your school, including classes of other teachers. You can add a class or edit your existing classes.
264
+ You can also accept or deny requests from independent students wanting to join one of your classes.</p>
245
265
  {% if classes %}
246
266
  <table id="classes-table" class="header-primary data-primary">
247
267
  <tr>
248
268
  <th><p>Class name</p></th>
249
269
  <th><p>Access code</p></th>
270
+ {% if is_admin %}
271
+ <th><p>Teacher</p></th>
272
+ {% endif %}
250
273
  <th><p>Action</p></th>
251
274
  </tr>
252
275
  {% for class in classes %}
253
- <tr>
254
- <td><p><small>{{ class.name }}</small></p></td>
255
- <td class="mw-0">
256
- <div class="d-flex justify-content-between">
257
- <div id="class-code-{{ class.access_code }}"><small>{{ class.access_code }}</small></div>
258
- <div>
259
- <a onclick="copyToClipboardFromElement(this, '#class-code-{{ class.access_code }}')" data-toggle="copyToClipboardTooltip">
260
- <span class="iconify" data-icon="mdi:content-copy" title="Copy to clipboard"></span>
261
- </a>
262
- </div>
276
+ <tr>
277
+ <td><p><small>{{ class.name }}</small></p></td>
278
+ <td class="mw-0">
279
+ <div class="d-flex justify-content-between">
280
+ <div id="class-code-{{ class.access_code }}"><small>{{ class.access_code }}</small></div>
281
+ <div>
282
+ <a onclick="copyToClipboardFromElement(this, '#class-code-{{ class.access_code }}')" data-toggle="copyToClipboardTooltip">
283
+ <span class="iconify" data-icon="mdi:content-copy" title="Copy to clipboard"></span>
284
+ </a>
263
285
  </div>
286
+ </div>
287
+ </td>
288
+ {% if is_admin %}
289
+ <td>
290
+ <p>
291
+ <small>
292
+ {% if user.email == class.teacher.new_user.email %}
293
+ You
294
+ {% else %}
295
+ {{ class.teacher }}
296
+ {% endif %}
297
+ </small>
298
+ </p>
264
299
  </td>
300
+ {% endif %}
265
301
  <td class="cell-center">
266
302
  <a id="class_button" href="{% url 'view_class' class.access_code %}"
267
303
  class="button button--small button--primary button--icon">
@@ -272,22 +308,14 @@
272
308
  {% endfor %}
273
309
  </table>
274
310
  {% else %}
275
- <h5>It doesn't look like you have any classes assigned to you. To create a class, use the 'New Class' box below.</h5>
311
+ <p><strong>It doesn't look like you have any classes assigned to you. Go to the section below to create a new class.</strong></p>
276
312
  {% endif %}
277
313
  <section>
278
314
  <h4>External requests to join your classes</h4>
279
315
  </section>
280
- <p>External, or independent students may request to join your classes, if the student has been given a Class Access Code, and provided you
316
+ <p>External or independent students may request to join your classes if the student has been given a Class Access Code, and provided you
281
317
  have enabled external requests for that class.</p>
282
318
  {% if requests %}
283
- <p>The following users have made requests to join your classes. If you accept a request, you will be able to choose a
284
- name that is unique for the user in the class and then pass on their new login details. At this point, you will be able to manage them
285
- like any other student.</p>
286
- <p>To conform to our security policy, the requested student’s username and email will be deleted on acceptance.
287
- These details are displayed here to enable you to identify them as genuine.</p>
288
- <p>You should not accept a request from a student whose email and username you do not recognise, or if you weren’t
289
- expecting such a request.</p>
290
-
291
319
  <table id="independent_request_table" class="header-primary data-primary">
292
320
  <tr>
293
321
  <th><p>Name</p></th>
@@ -300,44 +328,66 @@
300
328
  <td><p><small>{{ join_request.new_user.first_name }}</small></p></td>
301
329
  <td><p><small>{{ join_request.new_user.email }}</small></p></td>
302
330
  <td><p><small>{{ join_request.pending_class_request.name }}
303
- ({{ join_request.pending_class_request.access_code }})</small></p></td>
331
+ {% if user.email != join_request.pending_class_request.teacher.new_user.email %}
332
+ ({{ join_request.pending_class_request.teacher.new_user.first_name }}
333
+ {{ join_request.pending_class_request.teacher.new_user.last_name}})
334
+ {% endif %}
335
+ </small></p></td>
304
336
  <td colspan="2" class="cell-center">
305
337
  <button id="allow_independent_button" class="button--small button--primary button--icon"
306
338
  onclick="postWithCsrf('{% url 'teacher_accept_student_request' join_request.id %}');">
307
339
  Add to class<span class="iconify" data-icon="mdi:plus"></span></button>
308
340
  <button id="deny_independent_button" class="button--small button--primary--danger button--icon"
309
341
  onclick="postWithCsrf('{% url 'teacher_reject_student_request' join_request.id %}');">
310
- Reject request<span class="iconify" data-icon="mdi:block"></span></button>
342
+ Reject<span class="iconify" data-icon="mdi:block"></span></button>
311
343
  </td>
312
344
  </tr>
313
345
  {% endfor %}
314
346
  </table>
315
- <br>
316
347
  {% else %}
317
- <p><strong>No students have currently requested to join your classes.</strong></p>
348
+ <p><strong>No student has currently requested to join your classes.</strong></p>
318
349
  {% endif %}
319
350
  </div>
320
351
 
321
352
  <div id="new-class" class="background background--primary">
322
353
  <div class="container">
323
354
  <h5>Create a new class</h5>
324
- <p>When you set up a new class, a unique class access code will automatically be generated, with you being identified as the teacher for that
325
- class.</p>
326
- <form method="post">
355
+ {% if is_admin %}
356
+ <p>
357
+ When you set up a new class, a unique class access code will automatically be generated for the
358
+ teacher assigned to the class.
359
+ </p>
360
+ {% else %}
361
+ <p>
362
+ When you set up a new class, a unique class access code will automatically be generated, with
363
+ you being identified as the teacher for that class.
364
+ </p>
365
+ {% endif %}
366
+
367
+ <form id="form-create-class" autocomplete="off" method="post">
327
368
 
328
369
  {% csrf_token %}
329
370
 
330
371
  {{ create_class_form.non_field_errors }}
331
372
 
332
373
  <div class="row form--row">
333
- <div class="form--row__input col-sm-6 col-md-6">
374
+ <div class="form--row__input col-sm-6 col-md-4">
334
375
  <div class="input--icon">
335
376
  {{ create_class_form.class_name }}<span class="iconify" data-icon="mdi:account-multiple"></span>
336
377
  </div>
337
378
  <small>{{ create_class_form.class_name.help_text }}</small>
338
379
  {{ create_class_form.class_name.errors }}
339
380
  </div>
340
- <div class="form--row__input col-sm-12 col-md-6">
381
+ {% if is_admin %}
382
+ <div class="form--row__input col-sm-6 col-md-4">
383
+ {{ create_class_form.teacher }}
384
+ <small>{{ create_class_form.teacher.help_text }}</small>
385
+ {{ create_class_form.teacher.errors }}
386
+ </div>
387
+ {% endif %}
388
+ </div>
389
+ <div class="row form--row">
390
+ <div class="form--row__input col-sm-12 col-md-12">
341
391
  <div class="form__checkbox">
342
392
  <div class="form__checkbox-input">
343
393
  {{ create_class_form.classmate_progress }}
@@ -359,7 +409,7 @@
359
409
  <h4>Your account</h4>
360
410
  </section>
361
411
  <p>You can update your account details below.</p>
362
- <form method="post" id="form-edit-teacher">
412
+ <form autocomplete="off" method="post" id="form-edit-teacher">
363
413
 
364
414
  {% csrf_token %}
365
415
 
@@ -393,7 +443,7 @@
393
443
  <div class="form--row__input col-sm-6 col-md-4">
394
444
  <div class="input--icon">
395
445
  {{ update_account_form.password }}
396
- <span class="iconify" data-icon="mdi:security"></span>
446
+ <span id="password-field-icon" class="iconify" data-icon="material-symbols:visibility-off"></span>
397
447
  </div>
398
448
  <small>{{ update_account_form.password.help_text }}</small>
399
449
  {{ update_account_form.password.errors }}
@@ -401,6 +451,7 @@
401
451
  <div class="form--row__input col-sm-6 col-md-4">
402
452
  <div class="input--icon">
403
453
  {{ update_account_form.confirm_password }}
454
+ <span id="confirm-password-field-icon" class="iconify" data-icon="material-symbols:visibility-off"></span>
404
455
  </div>
405
456
  <small>{{ update_account_form.confirm_password.help_text }}</small>
406
457
  {{ update_account_form.confirm_password.errors }}
@@ -408,7 +459,7 @@
408
459
  <div class="form--row__input col-sm-6 col-md-4">
409
460
  <div class="input--icon">
410
461
  {{ update_account_form.current_password }}
411
- <span class="iconify" data-icon="mdi:lock-outline"></span>
462
+ <span id="current-password-field-icon" class="iconify" data-icon="material-symbols:visibility-off"></span>
412
463
  </div>
413
464
  <small>{{ update_account_form.current_password.help_text }}</small>
414
465
  {{ update_account_form.current_password.errors }}
@@ -420,7 +471,7 @@
420
471
 
421
472
  <div class="background background--primary">
422
473
  <div class="container">
423
- <h5>Two Factor Authentication</h5>
474
+ <h5>Two factor authentication</h5>
424
475
  <p>Use your smartphone or tablet to enhance your account's security by using an authenticator app.</p>
425
476
  {% if user|has_2FA %}
426
477
  <div class="row row--regular">
@@ -441,7 +492,7 @@
441
492
  <small class="text-danger"><strong>Note: Please make sure that you store any login details in a secure place.</strong></small>
442
493
  </div>
443
494
  <div class="col-sm-6">
444
- <h6>Disable Two Factor Authentication (2FA)</h6>
495
+ <h6>Disable two factor authentication (2FA)</h6>
445
496
  <p>We recommend you to continue using 2FA, however you can disable 2FA for your account using the button below.</p>
446
497
  <div class="background">
447
498
  <a class="button button--primary button--primary--danger button--icon" href="{% url 'two_factor:disable' %}">
@@ -452,12 +503,56 @@
452
503
  {% else %}
453
504
  <div class="background">
454
505
  <a class="button button--primary"
455
- href="{% url 'two_factor:setup' %}">Setup Two Factor Authentication</a>
506
+ href="{% url 'two_factor:setup' %}">Setup two factor authentication</a>
456
507
  </div>
457
508
  {% endif %}
458
509
  </div>
459
510
  </div>
511
+
512
+ <div id="delete-account" class="background">
513
+ <div class="container">
514
+ <h5>Delete account</h5>
515
+ <p>If you no longer wish to have a Code for Life account, you can delete it by confirming below.
516
+ You will receive an email to confirm this decision.
517
+ </p>
518
+ <p><b>This can't be reversed. All classes you've created will be permanently erased.</b>
519
+ </p>
520
+
521
+ <form autocomplete="off" method="post" id="form-delete-account">
522
+
523
+ {% csrf_token %}
524
+
525
+ {{ delete_account_form.non_field_errors }}
526
+
527
+ <div class="row form--row">
528
+ <div class="form--row__input col-sm-6 col-md-4">
529
+ <div class="input--icon">
530
+ {{ delete_account_form.delete_password }}
531
+ <span id="delete-password-field-icon" class="iconify" data-icon="material-symbols:visibility-off"></span>
532
+ </div>
533
+ <small>{{ delete_account_form.delete_password.help_text }}</small>
534
+ {{ delete_account_form.delete_password.errors }}
535
+ </div>
536
+ <div class="form--row__input col-sm-6 col-md-8">
537
+ <div class="form__checkbox">
538
+ <div class="form__checkbox-input">
539
+ {{ delete_account_form.unsubscribe_newsletter }}
540
+ </div>
541
+ <label for="id_{{ delete_account_form.unsubscribe_newsletter.html_name }}">{{ delete_account_form.unsubscribe_newsletter.label }}</label>
542
+ </div>
543
+ {{ delete_account_form.unsubscribe_newsletter.errors }}
544
+ </div>
545
+ </div>
546
+ <button id="delete_account_button" class="button button--primary button--primary--danger button--icon" name="delete_account">
547
+ Delete account <span class="iconify" data-icon="mdi:delete-outline"></span>
548
+ </button>
549
+ </form>
550
+ </div>
551
+ </div>
460
552
  </div>
461
553
  </div>
462
554
 
463
- {% endblock content %}
555
+ <script type="text/javascript"
556
+ src="{% static 'portal/js/school.js' %}"></script>
557
+
558
+ {% endblock content %}
@@ -0,0 +1,90 @@
1
+ {% extends 'portal/base.html' %}
2
+ {% load static %}
3
+ {% load app_tags %}
4
+
5
+ {% block content %}
6
+ <div class="container registration justify-content-center">
7
+ <div class="form--register--text form--register form--register--teacher ml-0 col-xs-6">
8
+ <div class="form-div form">
9
+ <h4>Complete registration</h4>
10
+
11
+ {% if error_message %}
12
+ <ul class="errorlist">
13
+ <li>{{ error_message }}</li>
14
+ </ul>
15
+ {% else %}
16
+ <div class="row form--row">
17
+ <p class="semi-bold">
18
+ Please create a password to complete your onboarding. It should be 10 characters long and a mix of
19
+ upper and lower case letters, numbers and special characters, making it hard to guess.
20
+ </p>
21
+ </div>
22
+
23
+ <form class="d-flex flex-column" method="post" id="teacher-register-form" autocomplete="off">
24
+
25
+ {% csrf_token %}
26
+
27
+ {{ invited_teacher_form.non_field_errors }}
28
+
29
+ <div class="row form--row">
30
+ <label for="{{ invited_teacher_form.teacher_password.auto_id }}"></label>
31
+ <div class="input--icon">
32
+ {{ invited_teacher_form.teacher_password }}
33
+ <span id="teacher-password-field-icon" class="iconify"
34
+ data-icon="material-symbols:visibility-off" ></span>
35
+ </div>
36
+ <small>{{ invited_teacher_form.teacher_password.help_text }}</small>
37
+ {{ invited_teacher_form.teacher_password.errors }}
38
+ </div>
39
+ <div class="row form--row">
40
+ <label for="{{ invited_teacher_form.teacher_confirm_password.auto_id }}"></label>
41
+ <div class="input--icon">
42
+ {{ invited_teacher_form.teacher_confirm_password }}
43
+ <span id="teacher-confirm-password-field-icon" class="iconify"
44
+ data-icon="material-symbols:visibility-off" ></span>
45
+ </div>
46
+ <small>{{ invited_teacher_form.teacher_confirm_password.help_text }}</small>
47
+ {{ invited_teacher_form.teacher_confirm_password.errors }}
48
+ </div>
49
+
50
+ <div class="row--under">
51
+ <div class="password-strength-container">
52
+ <div id="teacher-password-sign" class="password-strength-sign"></div>
53
+ <div id="teacher-password-text" class="password-strength-text"></div>
54
+ </div>
55
+ </div>
56
+
57
+ <div class="row form--row">
58
+ <div class="form__checkbox">
59
+ <div class="form__checkbox-input">
60
+ {{ invited_teacher_form.consent_ticked }}
61
+ </div>
62
+ <p class="semi-bold">I have read and understood the <a href="{% url 'terms' %}" target="_blank">Terms of use</a>
63
+ and the <a href="{% url 'privacy_notice' %}" target="_blank">Privacy Notice</a>.</p>
64
+ </div>
65
+ </div>
66
+ <div class="row form--row">
67
+ {% include 'portal/partials/register_newsletter_tickbox.html' with newsletter_ticked=invited_teacher_form.newsletter_ticked %}
68
+ </div>
69
+
70
+ <div class="d-flex justify-content-end row">
71
+ <button class="button button--home button--primary teacher--home--button button--icon" type="submit" name="teacher_signup"> Register<span class="iconify" data-icon="mdi:chevron-right"></span></button>
72
+ </div>
73
+
74
+ </form>
75
+ {% endif %}
76
+ </div>
77
+ </div>
78
+ </div>
79
+
80
+ {% include "portal/partials/service_unavailable_popup.html" %}
81
+
82
+ <script>
83
+ const password_id = '{{ invited_teacher_form.teacher_password.auto_id }}';
84
+ var TEACHER_PASSWORD_FIELD_ID = password_id;
85
+ var INDEP_STUDENT_PASSWORD_FIELD_ID = password_id;
86
+ </script>
87
+
88
+ <script type="text/javascript" src="{% static 'portal/js/passwordStrength.js' %}"></script>
89
+
90
+ {% endblock content %}
@@ -1,5 +1,5 @@
1
1
  {% extends 'portal/teach/base_registering.html' %}
2
- {% load staticfiles %}
2
+ {% load static %}
3
3
  {% load app_tags %}
4
4
 
5
5
  {% block content %}
@@ -43,7 +43,7 @@
43
43
  {{ form.non_field_errors }}
44
44
 
45
45
  <div class="row form--row">
46
- <div class="form--row__input col-sm-6 col-md-6">
46
+ <div class="form--row__input col-sm-6 col-md-4">
47
47
  <div class="input--icon">
48
48
  {{ form.class_name }}
49
49
  <span class="iconify" data-icon="mdi:account-multiple"></span>
@@ -51,7 +51,9 @@
51
51
  <small>{{ form.class_name.help_text }}</small>
52
52
  {{ form.class_name.errors }}
53
53
  </div>
54
- <div class="form--row__input col-sm-12 col-md-6">
54
+ </div>
55
+ <div class="row form--row">
56
+ <div class="form--row__input col-sm-12 col-md-12">
55
57
  <div class="form__checkbox">
56
58
  <div class="form__checkbox-input">
57
59
  {{ form.classmate_progress }}