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,22 +1,23 @@
1
1
  {% extends 'portal/base.html' %}
2
- {% load staticfiles %}
2
+ {% load static %}
3
3
  {% load app_tags %}
4
-
5
4
  {% block content %}
6
- <div id="signup_page"></div>
7
-
8
- <div class="container registration">
9
-
5
+ {% include "portal/partials/service_unavailable_popup.html" %}
6
+ <div id="signup_page"></div>
7
+ <div id="register-forms" class="container registration">
10
8
  <div class="form--register--text form--register form--register--teacher is-flex-item col-sm-6">
11
- <div class="form-div form">
9
+ <div id="teacher-register-form" class="form-div form">
12
10
  <h4>Teacher/Tutor</h4>
13
11
  <div class="row form--row">
14
- <p class="semi-bold">Once you've registered your personal details and logged in, you'll be able to create your school or club, or join other teachers at your institution.</p>
12
+ <p class="semi-bold">Register below to create your free account.</p>
13
+ <small class="semi-bold">You will have access to teaching resources, progress tracking and lesson plans
14
+ for Rapid Router.</small>
15
15
  </div>
16
- <form class="d-flex flex-column" method="post" id="form-reg-teacher" autocomplete="off">
17
-
16
+ <form class="d-flex flex-column"
17
+ method="post"
18
+ id="form-reg-teacher"
19
+ autocomplete="off">
18
20
  {% csrf_token %}
19
-
20
21
  {{ teacher_signup_form.non_field_errors }}
21
22
  <div class="row form--row">
22
23
  <label for="id_teacher_signup-teacher_first_name"></label>
@@ -25,26 +26,34 @@
25
26
  {{ teacher_signup_form.teacher_first_name.errors }}
26
27
  </div>
27
28
  <div class="row form--row">
28
-
29
29
  <label for="id_teacher_signup-teacher_last_name"></label>
30
30
  {{ teacher_signup_form.teacher_last_name }}
31
31
  <small>{{ teacher_signup_form.teacher_last_name.help_text }}</small>
32
32
  {{ teacher_signup_form.teacher_last_name.errors }}
33
33
  </div>
34
34
  <div class="row form--row">
35
-
36
35
  <label for="id_teacher_signup-teacher_email"></label>
37
36
  {{ teacher_signup_form.teacher_email }}
38
37
  <small>{{ teacher_signup_form.teacher_email.help_text }}</small>
39
38
  {{ teacher_signup_form.teacher_email.errors }}
40
39
  </div>
40
+ <div class="row form--row">
41
+ <div class="form__checkbox">
42
+ <div class="form__checkbox-input">{{ teacher_signup_form.consent_ticked }}</div>
43
+ <p class="semi-bold">
44
+ I am over 18 years old have read and understood the
45
+ <a href="{% url 'terms' %}" target="_blank">Terms of use</a> and the
46
+ <a href="{% url 'privacy_notice' %}" target="_blank">Privacy notice</a>.
47
+ </p>
48
+ </div>
49
+ </div>
41
50
  <div class="row form--row">
42
51
  {% include 'portal/partials/register_newsletter_tickbox.html' with newsletter_ticked=teacher_signup_form.newsletter_ticked %}
43
52
  </div>
44
53
  <div class="row form--row">
45
54
  <label for="id_teacher_signup-teacher_password"></label>
46
55
  <div class="input--icon">
47
- {{ teacher_signup_form.teacher_password }}<span class="iconify" data-icon="mdi:security"></span>
56
+ {{ teacher_signup_form.teacher_password }}<span id="teacher-password-field-icon" class="iconify" data-icon="material-symbols:visibility-off"></span>
48
57
  </div>
49
58
  <small>{{ teacher_signup_form.teacher_password.help_text }}</small>
50
59
  {{ teacher_signup_form.teacher_password.errors }}
@@ -52,115 +61,136 @@
52
61
  <div class="row form--row">
53
62
  <label for="id_teacher_signup-teacher_confirm_password"></label>
54
63
  <div class="input--icon">
55
- {{ teacher_signup_form.teacher_confirm_password }}<span class="iconify" data-icon="mdi:security"></span>
64
+ {{ teacher_signup_form.teacher_confirm_password }}<span id="teacher-confirm-password-field-icon" class="iconify" data-icon="material-symbols:visibility-off"></span>
56
65
  </div>
57
66
  <small>{{ teacher_signup_form.teacher_confirm_password.help_text }}</small>
58
67
  {{ teacher_signup_form.teacher_confirm_password.errors }}
59
68
  </div>
60
-
61
69
  <div class="row--under">
62
70
  <div class="password-strength-container">
63
71
  <div id="teacher-password-sign" class="password-strength-sign"></div>
64
72
  <div id="teacher-password-text" class="password-strength-text"></div>
65
73
  </div>
66
74
  </div>
67
-
68
- <div class="row">
69
- {{ teacher_signup_form.captcha }}
70
- </div>
71
- <div class="d-flex align-items-end justify-content-end form-div row">
72
- <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>
75
+ <div class="row">{{ teacher_signup_form.captcha }}</div>
76
+ <div class="d-flex justify-content-end row">
77
+ <button class="button button--home button--primary teacher--home--button button--icon"
78
+ type="submit"
79
+ name="teacher_signup">
80
+ Register<span class="iconify" data-icon="mdi:chevron-right"></span>
81
+ </button>
73
82
  </div>
74
83
  </form>
75
-
76
84
  </div>
77
85
  </div>
78
-
79
- <div class="form--register--text form--register form--register--indep-student col-sm-6">
80
- <div class="form-div">
86
+ <div class="form--register--text form--register form--register--indep-student is-flex-item col-sm-6">
87
+ <div id="independent-student-register-form" class="form-div">
81
88
  <h4>Independent learner</h4>
82
89
  <div class="row form--row">
83
- <p class="semi-bold">
84
- Register below if you are not part of a school or club.
85
- </p>
86
- <small class="semi-bold">
87
- Are you part of a school or club? If so, please log in <a href="{% url 'student_login_access_code' %}">here</a> or speak to your teacher.
88
- </small>
90
+ <p class="semi-bold">Register below if you are not part of a school or club and wish to set up a free home learning account.</p>
91
+ <small class="semi-bold">You will have access to learning resources for Rapid Router.</small>
89
92
  </div>
90
- <form id="form-signup-independent-student" method="post" autocomplete="off" class="d-flex flex-column">
91
-
93
+ <form id="form-signup-independent-student"
94
+ method="post"
95
+ autocomplete="off"
96
+ class="d-flex flex-column">
92
97
  {% csrf_token %}
93
-
94
- {{ independent_student_signup_form.non_field_errors }}
95
- <div class="row form--row">
96
-
97
- <label for="id_{{ independent_student_signup_form.name.html_name }}"></label>
98
- {{ independent_student_signup_form.name }}
99
- <small>{{ independent_student_signup_form.name.help_text }}</small>
100
- {{ independent_student_signup_form.name.errors }}
101
- </div>
102
- <div class="row form--row">
103
-
104
- <label for="id_{{ independent_student_signup_form.username.html_name }}"></label>
105
- {{ independent_student_signup_form.username }}
106
- <small>{{ independent_student_signup_form.username.help_text }}</small>
107
- {{ independent_student_signup_form.username.errors }}
108
- </div>
109
- <div class="row form--row">
110
-
111
- <label for="id_{{ independent_student_signup_form.email.html_name }}"></label>
112
- {{ independent_student_signup_form.email }}
113
- <small>{{ independent_student_signup_form.email.help_text }}</small>
114
- {{ independent_student_signup_form.email.errors }}
115
- </div>
116
98
  <div class="row form--row">
117
- {% include 'portal/partials/register_over_required_age_tickbox.html' with is_over_required_age=independent_student_signup_form.is_over_required_age %}
118
- </div>
119
-
120
- <div class="row form--row">
121
- {% include 'portal/partials/register_newsletter_tickbox.html' with newsletter_ticked=independent_student_signup_form.newsletter_ticked %}
99
+ <small class="semi-bold mb-4">{{ independent_student_signup_form.date_of_birth.help_text }}</small>
100
+ <div class="form__dob-input">
101
+ {{ independent_student_signup_form.date_of_birth }}
102
+ </div>
122
103
  </div>
123
-
124
- <div class="row form--row">
125
- <label for="id_{{ independent_student_signup_form.password.html_name }}"></label>
126
- <div class="input--icon">
127
- {{ independent_student_signup_form.password }} <span class="iconify" data-icon="mdi:security"></span>
104
+ {{ independent_student_signup_form.date_of_birth.errors }}
105
+ <div id="form-fields">
106
+ {{ independent_student_signup_form.non_field_errors }}
107
+ <div class="row form--row">
108
+ <label for="id_{{ independent_student_signup_form.name.html_name }}">
109
+ </label>
110
+ {{ independent_student_signup_form.name }}
111
+ <small>{{ independent_student_signup_form.name.help_text }}</small>
112
+ {{ independent_student_signup_form.name.errors }}
128
113
  </div>
114
+ <div class="row form--row">
115
+ <label for="id_{{ independent_student_signup_form.email.html_name }}">
116
+ </label>
117
+ {{ independent_student_signup_form.email }}
118
+ <small id="independent-email-help-text">{{ independent_student_signup_form.email.help_text }}</small>
119
+ {{ independent_student_signup_form.email.errors }}
120
+ </div>
121
+ <div id="independent-consent" class="row form--row">
122
+ <div class="form__checkbox">
123
+ <div class="form__checkbox-input">
124
+ {{ independent_student_signup_form.consent_ticked }}
125
+ </div>
126
+ <p id="independent-adult-legal" class="semi-bold">
127
+ I have read and understood the
128
+ <a href="{% url 'terms' %}" target="_blank">Terms of use</a> and the
129
+ <a href="{% url 'privacy_notice' %}" target="_blank">Privacy notice</a>.
130
+ </p>
131
+ <p id="independent-child-legal" class="semi-bold">
132
+ I have read and understood the
133
+ <a href="{% url 'terms' %}#terms-children" target="_blank">Terms of use</a> and the
134
+ <a href="{% url 'privacy_notice' %}#privacy-children" target="_blank">Privacy notice</a>.
135
+ </p>
136
+ </div>
137
+ </div>
138
+ <div id="independent-newsletter" class="row form--row">
139
+ {% include 'portal/partials/register_newsletter_tickbox.html' with newsletter_ticked=independent_student_signup_form.newsletter_ticked %}
140
+ </div>
141
+ <div id="independent-parent-notification" class="row form--row">
142
+ <small><strong>We will send your parent/guardian an email to ask them to activate the account
143
+ for you. Once they've done this you'll be able to log in using your name and password.</strong></small>
144
+ </div>
145
+ <div class="row form--row">
146
+ <label for="id_{{ independent_student_signup_form.password.html_name }}">
147
+ </label>
148
+ <div class="input--icon">
149
+ {{ independent_student_signup_form.password }} <span id="independent-student-password-field-icon" class="iconify" data-icon="material-symbols:visibility-off"></span>
150
+ </div>
129
151
  <small>{{ independent_student_signup_form.password.help_text }}</small>
130
- {{ independent_student_signup_form.password.errors }}
131
- </div>
132
-
133
- <div class="row form--row">
134
- <label for="id_{{ independent_student_signup_form.confirm_password.html_name }}"></label>
135
- <div class="input--icon">
136
- {{ independent_student_signup_form.confirm_password }}<span class="iconify" data-icon="mdi:security"></span>
152
+ {{ independent_student_signup_form.password.errors }}
137
153
  </div>
138
- <small>{{ independent_student_signup_form.confirm_password.help_text }}</small>
139
- {{ independent_student_signup_form.confirm_password.errors }}
140
- </div>
141
-
142
- <div class="row--under">
143
- <div class="password-strength-container">
144
- <div id="student-password-sign" class="password-strength-sign"></div>
145
- <div id="student-password-text" class="password-strength-text"></div>
154
+ <div class="row form--row">
155
+ <label for="id_{{ independent_student_signup_form.confirm_password.html_name }}">
156
+ </label>
157
+ <div class="input--icon">
158
+ {{ independent_student_signup_form.confirm_password }}<span id="independent-student-confirm-password-field-icon" class="iconify" data-icon="material-symbols:visibility-off"></span>
159
+ </div>
160
+ <small>{{ independent_student_signup_form.confirm_password.help_text }}</small>
161
+ {{ independent_student_signup_form.confirm_password.errors }}
162
+ </div>
163
+ <div class="row--under">
164
+ <div class="password-strength-container">
165
+ <div id="student-password-sign" class="password-strength-sign">
166
+ </div>
167
+ <div id="student-password-text" class="password-strength-text">
168
+ </div>
169
+ </div>
170
+ </div>
171
+ <div class="row">
172
+ {{ independent_student_signup_form.captcha }}
173
+ </div>
174
+ <div class="d-flex justify-content-end row">
175
+ <button type="submit"
176
+ name="independent_student_signup"
177
+ class="button button--home button--icon"
178
+ value="Register">
179
+ Register<span class="iconify" data-icon="mdi:chevron-right"></span>
180
+ </button>
146
181
  </div>
147
- </div>
148
-
149
- <div class="row">
150
- {{ independent_student_signup_form.captcha }}
151
- </div>
152
- <div class="d-flex align-items-end justify-content-end row">
153
- <button type="submit" name="independent_student_signup" class="button button--home button--icon" value="Register">Register<span class="iconify" data-icon="mdi:chevron-right"></span></button>
154
182
  </div>
155
183
  </form>
156
184
  </div>
157
185
  </div>
158
- </div>
159
-
160
- <script type="text/javascript" src="{% static 'portal/js/passwordStrength.js' %}"></script>
186
+ </div>
161
187
  <script>
162
188
  var TEACHER_PASSWORD_FIELD_ID = '{{ teacher_signup_form.teacher_password.auto_id }}';
163
189
  var INDEP_STUDENT_PASSWORD_FIELD_ID = '{{ independent_student_signup_form.password.auto_id }}';
164
190
  </script>
191
+ <script type="text/javascript"
192
+ src="{% static 'portal/js/passwordStrength.js' %}"></script>
193
+ <script type="text/javascript"
194
+ src="{% static 'portal/js/independentRegistration.js' %}"></script>
165
195
 
166
196
  {% endblock content %}
@@ -2,56 +2,36 @@
2
2
  {% load static %}
3
3
 
4
4
  {% block form_content %}
5
- <!-- #TODO: Merge this if/else when we get rid of the indep username -->
6
- {% if usertype == "TEACHER" %}
7
- <div id="reset_password_teacher_page"></div>
8
- <h4 class="center-block">Reset password</h4>
9
- <h5>Please enter your email address</h5>
10
- <p class="text-left">We will send an email with a link to reset your password.</p>
11
- <form method="post" autocomplete="off">
12
- {% csrf_token %}
13
5
 
14
- {{ form.non_field_errors }}
6
+ <div id="reset_password_page"></div>
7
+ <h4 class="center-block">Reset password</h4>
8
+ <h5>Please enter your email address</h5>
9
+ <p class="text-left">We will send an email with a link to reset your password.</p>
10
+ <form method="post" autocomplete="off">
11
+ {% csrf_token %}
15
12
 
16
- <div class="form--row">
17
- {{ form.email }}
18
- <small>{{ form.email.help_text }}</small>
19
- {{ form.email.error }}
20
- </div>
13
+ {{ form.non_field_errors }}
14
+
15
+ <div class="form--row">
16
+ {{ form.email }}
17
+ <small>{{ form.email.help_text }}</small>
18
+ {{ form.email.error }}
19
+ </div>
21
20
 
22
- {% if should_use_recaptcha %}
23
- {{ form.captcha }}
24
- {% endif %}
21
+ {% if should_use_recaptcha %}
22
+ {{ form.captcha }}
23
+ {% endif %}
25
24
 
25
+ {% if usertype == "TEACHER" %}
26
26
  <div>
27
27
  <a id="cancel_button" class="button button--secondary button--secondary--light" href="{% url 'teacher_login' %}">Cancel</a>
28
28
  <button id="reset_button" type="submit" class="button button--primary">Reset password</button>
29
29
  </div>
30
- </form>
31
- {% else %}
32
- <div id="reset_password_student_page"></div>
33
- <h4 class="center-block">Reset password</h4>
34
- <h5>Please enter your username</h5>
35
- <p class="text-left">We will send an email with a link to reset your password.</p>
36
- <form method="post" autocomplete="off">
37
- {% csrf_token %}
38
-
39
- {{ form.non_field_errors }}
40
-
41
- <div class="form--row">
42
- {{ form.username }}
43
- <small>{{ form.username.help_text }}</small>
44
- {{ form.username.error }}
45
- </div>
46
-
47
- {% if should_use_recaptcha %}
48
- {{ form.captcha }}
49
- {% endif %}
50
-
30
+ {% else %}
51
31
  <div>
52
32
  <a id="cancel_button" class="button button--secondary button--secondary--light" href="{% url 'independent_student_login' %}">Cancel</a>
53
33
  <button id="reset_button" type="submit" class="button button--home">Reset password</button>
54
34
  </div>
55
- </form>
56
- {% endif %}
35
+ {% endif %}
36
+ </form>
57
37
  {% endblock form_content %}
@@ -8,20 +8,24 @@
8
8
  {% if validlink %}
9
9
  <p class="text-left">Please enter a new password and confirm it in the boxes below to reset your account&rsquo;s password.</p>
10
10
 
11
- <form method="post">
11
+ <form id="reset-password-form" method="post">
12
12
 
13
13
  {% csrf_token %}
14
14
 
15
15
  {{ form.non_field_errors }}
16
16
 
17
17
  <div class="form--row">
18
- {{ form.new_password1 }}
18
+ <div class="input--icon">
19
+ {{ form.new_password1 }} <span id="password-field-icon" class="iconify" data-icon="material-symbols:visibility-off"></span>
20
+ </div>
19
21
  <small>{{ form.new_password1.help_text }}</small>
20
22
  </div>
21
23
  {{ form.new_password1.errors }}
22
24
 
23
25
  <div class="form--row">
24
- {{ form.new_password2 }}
26
+ <div class="input--icon">
27
+ {{ form.new_password2 }} <span id="confirm-password-field-icon" class="iconify" data-icon="material-symbols:visibility-off"></span>
28
+ </div>
25
29
  <small>{{ form.new_password2.help_text }}</small>
26
30
  </div>
27
31
  {{ form.new_password2.errors }}
@@ -61,10 +65,11 @@
61
65
  </div>
62
66
  {% endif %}
63
67
 
64
- <script type="text/javascript" src="{% static 'portal/js/passwordStrength.js' %}"></script>
65
68
  <script>
66
69
  var TEACHER_PASSWORD_FIELD_ID = '{{ form.new_password1.auto_id }}';
67
70
  var INDEP_STUDENT_PASSWORD_FIELD_ID = '{{ form.new_password1.auto_id }}';
68
71
  </script>
72
+ <script type="text/javascript" src="{% static 'portal/js/passwordStrength.js' %}"></script>
73
+ <script type="text/javascript" src="{% static 'portal/js/resetPassword.js' %}"></script>
69
74
 
70
75
  {% endblock form_content %}
@@ -2,16 +2,18 @@
2
2
  {% load static %}
3
3
 
4
4
  {% block form_content %}
5
- <div id="reset_password_email_sent_page"></div>
6
- <h4>Thank you</h4>
7
- <img class="background" title="Paper Plane" alt="Verification email sent" src="{% static 'portal/img/paper_plane.png' %}">
8
- <p class="text-left">If you have entered a valid {% if usertype == "TEACHER" %}email address{% else %}username{% endif %},
9
- you will receive a link enabling you to reset your password.</p>
10
- <div>
11
- {% if usertype == "TEACHER" %}
12
- <a href="{% url 'home' %}" class="button button--primary button--login">Back to homepage</a>
13
- {% else %}
14
- <a href="{% url 'home' %}" class="button button--home">Back to homepage</a>
15
- {% endif %}
16
- </div>
17
- {% endblock form_content %}
5
+ <div id="reset_password_email_sent_page"></div>
6
+ <h4>Thank you</h4>
7
+ <h5>If you have entered a valid email address, you will receive a link to
8
+ reset your password. Make sure to check your <strong>spam</strong>.</h5>
9
+ <img class="background" title="Paper Plane" alt="Verification email sent"
10
+ src="{% static 'portal/img/paper_plane.png' %}">
11
+ <div>
12
+ <a target="_blank"
13
+ href="https://mail.google.com/mail/#search/from%3Ano-reply%40info.codeforlife.education+subject%3APassword+reset+request"
14
+ class="button button--home button-email">Open in Gmail</a>
15
+ <a target="_blank" href="https://outlook.live.com/mail/" class="button button--home button-email">Open in
16
+ Outlook</a>
17
+ </div>
18
+ <p class="text-left"><a id="home_button" href="{% url 'home' %}">&lt; back to homepage</a></p>
19
+ {% endblock form_content %}
@@ -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 subNav %}
@@ -1,16 +1,15 @@
1
1
  {% extends 'portal/base.html' %}
2
- {% load staticfiles %}
2
+ {% load static %}
3
3
  {% load app_tags %}
4
4
 
5
5
  {% block css %}
6
6
  {{ block.super }}
7
- <link href="{% static 'portal/css/jquery-ui.css' %}" rel="stylesheet">
7
+ <link href="https://code.jquery.com/ui/1.13.1/themes/base/jquery-ui.css" rel="stylesheet" type="text/css">
8
8
  {% endblock css %}
9
9
 
10
10
  {% block scripts %}
11
11
  {{ block.super }}
12
12
  <script type="text/javascript" src="{% static 'portal/js/teach_class.js' %}"></script>
13
- <script type="text/javascript" src="{% static 'portal/js/common.js' %}"></script>
14
13
  {% endblock scripts %}
15
14
 
16
15
  {% block subNav %}
@@ -119,9 +118,8 @@
119
118
 
120
119
  <div class="background container">
121
120
  <h4>Additional class details</h4>
122
- <p>Here you may change the name of the class, transfer the class to another teacher in the school or club, create permissions for the class to
123
- accept requests from external students, or delete classes for which there are no students. You can also create permissions for students in this class to see
124
- their classmates' progress.</p>
121
+ <p>Here you can change settings and permissions for the class and the students accessing it.
122
+ You can also delete classes and change level access.</p>
125
123
  <div class="background button-group">
126
124
  <a id="class_settings_button" href="{% url 'teacher_edit_class' class.access_code %}" class="button button--primary button--icon">Edit details
127
125
  <span class="iconify" data-icon="mdi:pencil"></span>