codeforlife-portal 5.32.2__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 (393) 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.32.2.dist-info → codeforlife_portal-8.9.9.dist-info}/RECORD +341 -238
  92. {codeforlife_portal-5.32.2.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.32.2.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 +31 -0
  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 +10 -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 -73
  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 +138 -15
  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 +237 -164
  319. portal/views/admin.py +0 -332
  320. portal/views/api.py +82 -68
  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/__init__.py +0 -0
  338. portal/views/two_factor/core.py +28 -0
  339. portal/views/two_factor/form.py +7 -0
  340. portal/views/two_factor/profile.py +11 -0
  341. codeforlife_portal-5.32.2.dist-info/LICENSE.md +0 -577
  342. codeforlife_portal-5.32.2.dist-info/METADATA +0 -38
  343. deploy/permissions.py +0 -2
  344. example_project/manage.py +0 -10
  345. portal/autoconfig.py +0 -140
  346. portal/csp_config.py +0 -60
  347. portal/forms/add_game.py +0 -33
  348. portal/helpers/location.py +0 -121
  349. portal/static/portal/img/kurono_hero.jpg +0 -0
  350. portal/static/portal/img/kurono_landing_hero.png +0 -0
  351. portal/static/portal/img/kurono_logo.svg +0 -1
  352. portal/static/portal/img/kurono_logo_grey_background.svg +0 -1
  353. portal/static/portal/img/kurono_logo_mark.svg +0 -1
  354. portal/static/portal/img/kurono_resources_hero.jpg +0 -0
  355. portal/static/portal/img/kurono_story.png +0 -0
  356. portal/static/portal/img/ocado-swirl.svg +0 -22
  357. portal/static/portal/img/thumbnail_educate_kurono.png +0 -0
  358. portal/static/portal/img/thumbnail_educate_resources_and_progress_tracking.png +0 -0
  359. portal/static/portal/img/thumbnail_kurono_resources.png +0 -0
  360. portal/static/portal/img/thumbnail_play_kurono.png +0 -0
  361. portal/static/portal/img/x_close_video.png +0 -0
  362. portal/static/portal/js/aimmoGame.js +0 -106
  363. portal/static/portal/js/deleteWorkspaces.js +0 -14
  364. portal/static/portal/js/fuzzySchoolLookup.js +0 -46
  365. portal/static/portal/js/lib/jquery-3.5.1.min.js +0 -2
  366. portal/static/portal/js/lib/jquery-ui-1.12.1.min.js +0 -13
  367. portal/static/portal/sass/partials/_videos.scss +0 -10
  368. portal/static/portal/video/aimmo_play_now_background_video.mp4 +0 -0
  369. portal/strings/student_aimmo_dashboard.py +0 -6
  370. portal/templates/portal/admin/aggregated_data.html +0 -35
  371. portal/templates/portal/admin/map.html +0 -70
  372. portal/templates/portal/mouseflow.html +0 -9
  373. portal/templates/portal/partials/aimmo_games_table.html +0 -83
  374. portal/templates/portal/partials/register_over_required_age_tickbox.html +0 -9
  375. portal/templates/portal/play/independent_student_dashboard.html +0 -64
  376. portal/templates/portal/play/student_aimmo_dashboard.html +0 -63
  377. portal/templates/portal/privacy_policy.html +0 -483
  378. portal/templates/portal/reset_password_email.html +0 -9
  379. portal/templates/portal/teach/invite.html +0 -25
  380. portal/templates/portal/teach/teacher_aimmo_dashboard.html +0 -95
  381. portal/templates/portal/teach/teacher_resources.html +0 -68
  382. portal/templatetags/character_list_tags.py +0 -16
  383. portal/tests/pageObjects/portal/kurono_teacher_dashboard_page.py +0 -49
  384. portal/tests/pageObjects/portal/student_password_reset_form_page.py +0 -23
  385. portal/tests/pageObjects/portal/teach/onboarding_revoke_request_page.py +0 -20
  386. portal/tests/pageObjects/portal/teacher_password_reset_form_page.py +0 -23
  387. portal/tests/test_aimmo_dashboards.py +0 -172
  388. portal/tests/test_location.py +0 -217
  389. portal/tests/utils/aimmo_games.py +0 -30
  390. portal/views/aimmo/dashboard.py +0 -119
  391. portal/views/privacy_policy.py +0 -9
  392. portal/views/teacher/teacher_resources.py +0 -42
  393. {portal/views/aimmo → cfl_common}/__init__.py +0 -0
@@ -0,0 +1,374 @@
1
+ {% load static %}
2
+ <!DOCTYPE html
3
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
4
+ <html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml"
5
+ xmlns:o="urn:schemas-microsoft-com:office:office">
6
+
7
+ <head>
8
+ <!--[if gte mso 9]><xml><o:OfficeDocumentSettings><o:AllowPNG></o:AllowPNG><o:PixelsPerInch>96</o:PixelsPerInch></o:OfficeDocumentSettings></xml><![endif]-->
9
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
10
+ <meta name="viewport" content="width=device-width">
11
+ <link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@500&amp;display=swap" rel="stylesheet">
12
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&amp;display=swap" rel="stylesheet">
13
+ <title>$title</title>
14
+ <style type="text/css">
15
+ body,
16
+ html {
17
+ Margin: 0 !important;
18
+ padding: 0 !important;
19
+ width: 100% !important
20
+ }
21
+
22
+ h1,
23
+ h2,
24
+ h3,
25
+ h4 {
26
+ Margin: 0
27
+ }
28
+
29
+ * {
30
+ -ms-text-size-adjust: 100%;
31
+ -webkit-text-size-adjust: 100%
32
+ }
33
+
34
+ table,
35
+ td {
36
+ mso-table-lspace: 0 !important;
37
+ mso-table-rspace: 0 !important
38
+ }
39
+
40
+ table {
41
+ border-spacing: 0 !important;
42
+ border-collapse: collapse !important;
43
+ table-layout: auto !important
44
+ }
45
+
46
+ img {
47
+ -ms-interpolation-mode: bicubic
48
+ }
49
+
50
+ .mobile-link--footer a,
51
+ .email-width,
52
+ .row {
53
+ Margin: 0 auto !important
54
+ }
55
+
56
+ @media screen and (max-width:504px) {
57
+ .row .stack-column {
58
+ display: block !important;
59
+ width: 100% !important;
60
+ max-width: 100% !important;
61
+ direction: ltr !important;
62
+ min-width: 100% !important
63
+ }
64
+
65
+ body {
66
+ display: none !important
67
+ }
68
+
69
+ table {
70
+ display: table;
71
+ max-height: none;
72
+ visibility: visible;
73
+ width: 100% !important
74
+ }
75
+
76
+ .email-width {
77
+ width: 100% !important
78
+ }
79
+ }
80
+
81
+ @media only screen and (min-width:505px) {
82
+ .row .stack-column {
83
+ min-width: 0 !important
84
+ }
85
+ }
86
+
87
+ [owa] .no-stack-column,
88
+ [owa] .stack-column {
89
+ Margin: 0 -2px;
90
+ float: none;
91
+ display: inline-block !important
92
+ }
93
+
94
+ .stack-column {
95
+ min-width: 0 !important
96
+ }
97
+
98
+ .no-stack-column {
99
+ min-height: 1px
100
+ }
101
+
102
+ body .stack-column {
103
+ min-width: 100% !important
104
+ }
105
+
106
+ td.row-container {
107
+ padding: 0;
108
+ text-align: center;
109
+ height: 100%;
110
+ vertical-align: top;
111
+ width: 100%
112
+ }
113
+
114
+ .stack-col,
115
+ .stack-column {
116
+ width: 600px;
117
+ display: inline-block;
118
+ vertical-align: top
119
+ }
120
+
121
+ .no-stack-col,
122
+ .no-stack-column {
123
+ display: inline-block;
124
+ vertical-align: top;
125
+ width: 33.333333%;
126
+ }
127
+
128
+ .stack-column-row {
129
+ display: inline-block;
130
+ }
131
+
132
+ .col-font-reset,
133
+ .font-reset {
134
+ font-size: 14px;
135
+ text-align: left
136
+ }
137
+
138
+ .border-collapse {
139
+ border-collapse: collapse
140
+ }
141
+
142
+
143
+ img {
144
+ max-width: 100%
145
+ }
146
+
147
+ ul li {
148
+ margin: 0
149
+ }
150
+
151
+ body,
152
+ td {
153
+ font-family: "Inter", sans-serif;
154
+ }
155
+
156
+ .element-editable:not(img),
157
+ .element-editable td,
158
+ .element-editable p {
159
+ line-height: 25px;
160
+ Margin: 0px;
161
+ text-align: center;
162
+ }
163
+
164
+ .icons {
165
+ padding-top: 15px;
166
+ padding-right: 10px;
167
+ padding-bottom: 10px;
168
+ padding-left: 10px;
169
+ }
170
+
171
+ .icon-link {
172
+ padding-top: 0px;
173
+ padding-right: 0px;
174
+ padding-bottom: 0px;
175
+ padding-left: 0px;
176
+ color: rgb(205, 173, 37);
177
+ font-family: Arial, sans-serif;
178
+ font-size: 12px;
179
+ height: 32px;
180
+ width: 32px;
181
+ }
182
+
183
+ .footer-bg {
184
+ background: #e0004d;
185
+ table-layout: auto;
186
+ }
187
+
188
+ .footer {
189
+ position: static;
190
+ }
191
+
192
+ .footer-td {
193
+ padding-top: 40px;
194
+ padding-right: 40px;
195
+ padding-bottom: 40px;
196
+ padding-left: 40px;
197
+ }
198
+
199
+ .footer > p {
200
+ text-align: center;
201
+ color: #fff
202
+ }
203
+
204
+ .footer > p > a {
205
+ text-decoration: underline;
206
+ color: #fff;
207
+ }
208
+
209
+ .cfl-team {
210
+ color: rgb(224, 0, 77);
211
+ font-family: "Space Grotesk";
212
+ font-size: 18px;
213
+ text-align: center;
214
+ }
215
+
216
+ .middle-block {
217
+ position: relative;
218
+ max-width: 660px;
219
+ table-layout: auto;
220
+ }
221
+
222
+ .singular-icon {
223
+ padding-top: 3px;
224
+ padding-right: 15px;
225
+ padding-bottom: 3px;
226
+ padding-left: 15px;
227
+ }
228
+
229
+ .center-content {
230
+ width: 33.333333%;
231
+ max-width: 33.333333%;
232
+ min-width: 33.333333%;
233
+ }
234
+
235
+ .contact-us {
236
+ color: #fff;
237
+ }
238
+
239
+ </style>
240
+ </head>
241
+
242
+ <body>
243
+ <table cellspacing="0" cellpadding="0" border="0" width="660" align="center">
244
+ <table border="0" cellpadding="0" cellspacing="0" align="center" width="100%" class="row three-cols" style="table-layout: auto;">
245
+ <tbody>
246
+ <tr>
247
+ <td align="center" valign="top" class="row-inner element-pad" dir="ltr" style="display: flex">
248
+ <!--[if mso]><table border="0" cellspacing="0" cellpadding="0" align="center" style="width:640px;" width="640"><tr><td align="left" valign="top" style="width:213.328px;" width="213.328"><![endif]-->
249
+ <div class="no-stack-column no-stack-column-width" style="">
250
+ <table cellspacing="0" cellpadding="0" border="0" width="100%">
251
+ <tbody>
252
+ <tr>
253
+ <td dir="ltr" class="col-inner" align="left">
254
+ <table width="100%" border="0" cellpadding="0" cellspacing="0" data-title="Image">
255
+ <tbody>
256
+ <tr>
257
+ <td align="left" class="element-pad element-bord"><a href=" {{ url_prefix }}">
258
+ <img src="{{ url_prefix }}/static/portal/img/logo_cfl.png" width="81" style="min-height: auto; display: block;" alt="logo_cfl">
259
+ </a>
260
+ </td>
261
+ </tr>
262
+ </tbody>
263
+ </table>
264
+ </td>
265
+ </tr>
266
+ </tbody>
267
+ </table>
268
+ </div><!--[if mso]></td><td align="left" valign="top" style="width:213.328px;" width="213.328"><![endif]-->
269
+ <div class="no-stack-column no-stack-column-width">
270
+ <table cellspacing="0" cellpadding="0" border="0" width="100%">
271
+ <tbody>
272
+ <tr>
273
+ <td dir="ltr" class="col-inner" align="left"></td>
274
+ </tr>
275
+ </tbody>
276
+ </table>
277
+ </div><!--[if mso]></td><td align="left" valign="top" style="width:213.328px;" width="213.328"><![endif]-->
278
+ <div class="no-stack-column no-stack-column-width">
279
+ <table cellspacing="0" cellpadding="0" border="0" width="100%" style="table-layout: auto;">
280
+ <tbody>
281
+ <tr>
282
+ <td dir="ltr" class="col-inner" align="left">
283
+ <table width="100%" border="0" cellpadding="0" cing="0" data-title="Image">
284
+ <tbody>
285
+ <tr>
286
+ <td class="element-pad element-bord" align="right">
287
+ <a href="https://www.ocadogroup.com/sustainability/sustainability">
288
+ <img src="{{ url_prefix }}/static/portal/img/logo_ocado_group.png" width="122" style="min-height: auto;" alt="logo_ocado_group">
289
+ </a>
290
+ </td>
291
+ </tr>
292
+ </tbody>
293
+ </table>
294
+ </td>
295
+ </tr>
296
+ </tbody>
297
+ </table>
298
+ </div><!--[if mso]></td></tr></table><![endif]-->
299
+ </td>
300
+ </tr>
301
+ </tbody>
302
+ </table>
303
+ <table border="0" cellpadding="0" cellspacing="0" align="center" width="100%" class="row" class="middle-block">
304
+ <tbody>
305
+ <tr>
306
+ <td align="center" valign="top" class="row-inner element-pad" dir="ltr" style="padding-top: 20px; padding-right: 10px; padding-bottom: 20px; padding-left: 10px;">
307
+ <!--[if mso]><table border="0" cellspacing="0" cellpadding="0" align="center" style="width:640px;" width="640"><tr><td align="left" valign="top" style="width:640px;" width="640"><![endif]-->
308
+ <table cellspacing="0" cellpadding="0" border="0" width="100%" style="table-layout: auto;">
309
+ <tbody>
310
+ <tr>
311
+ <td dir="ltr" class="col-inner" align="left">
312
+ <table cellpadding="0" cellspacing="0" width="100%" data-title="Text">
313
+ <tbody>
314
+ <tr>
315
+ <td valign="top" align="left" class="element-pad element-bord" style="padding-top: 15px; padding-right: 15px; padding-bottom: 15px; padding-left: 15px;">
316
+ <div class="element-editable" style="text-align: center;">
317
+ <p dir="ltr">{% block email_content %} {% endblock email_content %}</p>
318
+ <p dir="ltr"><br></p>
319
+ <p dir="ltr">All the best,</p>
320
+ <p dir="ltr"><br></p>
321
+ <p dir="ltr" class="cfl-team">Code for Life team</p>
322
+ </div>
323
+ </td>
324
+ </tr>
325
+ </tbody>
326
+ </table>
327
+ </td>
328
+ </tr>
329
+ </tbody>
330
+ </table>
331
+ </td>
332
+ </tr>
333
+ </tbody>
334
+ </table>
335
+ <table align="center">
336
+ <tbody>
337
+ <tr>
338
+ <td valign="top" class="icons">
339
+ <table>
340
+ <tbody>
341
+ <tr>
342
+ <td class="singular-icon">
343
+ <a href="https://www.facebook.com/codeforlifeuk/"><img border="0" class="icon-link" height="32" width="32" src="{{ url_prefix }}/static/portal/img/facebook.png" title="Facebook" alt="facebook"></a>
344
+ </td>
345
+ <td>
346
+ <a href="https://twitter.com/codeforlifeuk"><img border="0" class="icon-link" height="32" width="32" src="{{ url_prefix }}/static/portal/img/twitter.png" title="Twitter" alt="twitter"></a>
347
+ </td>
348
+ </tr>
349
+ </tbody>
350
+ </table>
351
+ </td>
352
+ </tr>
353
+ </tbody>
354
+ </table>
355
+ <table cellpadding="0" cellspacing="0" width="100%" data-title="Text" class="footer-bg">
356
+ <tbody>
357
+ <tr>
358
+ <td valign="top" align="left" class="footer-td">
359
+ <div class="footer">
360
+ <a align="center" class="contact-us" href="mailto:codeforlife@ocado.com?subject=Contact us">
361
+ <p>Contact us</p>
362
+ </a>
363
+ <p><br></p>
364
+ <p>Ocado Innovation Limited is registered in England under registered company number 08813912 with its registered office at Buildings One & Two Trident Place, Mosquito Way, Hatfield, Hertfordshire, United Kingdom, AL10 9UL</p>
365
+ <p>You can find out about our privacy notice <a href="{{ url_prefix }}/privacy-notice" title="Privacy Notice">here</a></p>
366
+ </div>
367
+ </td>
368
+ </tr>
369
+ </tbody>
370
+ </table>
371
+ </table>
372
+ </body>
373
+
374
+ </html>
@@ -1,5 +1,5 @@
1
1
  {% extends 'portal/form_shapes.html' %}
2
- {% load staticfiles %}
2
+ {% load static %}
3
3
  {% load app_tags %}
4
4
 
5
5
  {% block form_content %}
@@ -1,19 +1,19 @@
1
1
  {% extends 'portal/form_shapes.html' %}
2
- {% load staticfiles %}
2
+ {% load static %}
3
3
  {% load app_tags %}
4
4
 
5
5
  {% block form_content %}
6
6
  <div id="emailVerificationNeeded_page"></div>
7
7
  <h4>We need to verify your email address</h4>
8
+ <h5>An email has been sent to you. Make sure to check your
9
+ <strong>spam</strong>.</h5>
8
10
  <img class="background" title="Paper Plane" alt="Verification email sent" src="{% static 'portal/img/paper_plane.png' %}">
9
- <p class="text-left">An email has been sent to the address you provided.</p>
10
- <p class="text-left">Please follow the link within the email to verify your details. This will expire in 1 hour.</p>
11
- <p class="text-left">If you don't receive the email within the next few minutes, check your spam folder.</p>
11
+ <p class="text-left">Please follow the link within the email to verify your details. This will expire in one hour.</p>
12
12
  <div>
13
- {% if usertype == "TEACHER" %}
14
- <a id="home_button" href="{% url 'home' %}" class="button button--primary button--login">Back to homepage</a>
15
- {% else %}
16
- <a id="home_button" href="{% url 'home' %}" class="button button--home">Back to homepage</a>
17
- {% endif %}
13
+ <a target="_blank" href="https://mail.google.com/mail/#search/from%3Ano-reply%40info.codeforlife.education+subject%3AEmail+Verification"
14
+ class="button button--home button-email">Open in Gmail</a>
15
+ <a target="_blank" href="https://outlook.live.com/mail/"
16
+ class="button button--home button-email">Open in Outlook</a>
18
17
  </div>
18
+ <p class="text-left"><a id="home_button" href="{% url 'home' %}">&lt; back to homepage</a></p>
19
19
  {% endblock form_content %}
@@ -4,22 +4,34 @@ as well as the right shapes. The block `form_content` can then be extended in
4
4
  other templates to add custom content. -->
5
5
 
6
6
  {% extends 'portal/base.html' %}
7
- {% load staticfiles %}
7
+ {% load static %}
8
8
  {% load app_tags %}
9
9
 
10
10
  {% block content %}
11
11
  <section class="row mx-0">
12
12
  {% if usertype == "TEACHER" %}
13
- <span class="oval-blue login-shape-left"></span>
14
- <span class="polygon-yellow login-shape-right"></span>
13
+ <span class="login-shape-left">
14
+ <img src="{% static 'portal/img/oval_blue.svg' %}" alt="Blue oval">
15
+ </span>
16
+ <span class="login-shape-right">
17
+ <img src="{% static 'portal/img/polygon_yellow.svg' %}" alt="Yellow polygon">
18
+ </span>
15
19
  <div class="form--login is-flex form--register--teacher">
16
20
  {% elif usertype == "SCHOOL_STUDENT" %}
17
- <span class="oval-yellow login-shape-left"></span>
18
- <span class="polygon-pink login-shape-right"></span>
21
+ <span class="login-shape-left">
22
+ <img src="{% static 'portal/img/oval_yellow.svg' %}" alt="Yellow oval">
23
+ </span>
24
+ <span class="login-shape-right">
25
+ <img src="{% static 'portal/img/polygon_pink.svg' %}" alt="Pink polygon">
26
+ </span>
19
27
  <div class="form--login is-flex form--register--student">
20
- {% elif usertype == "INDEP_STUDENT" %}
21
- <span class="oval-pink login-shape-left"></span>
22
- <span class="polygon-blue login-shape-right"></span>
28
+ {% else %}
29
+ <span class="login-shape-left">
30
+ <img src="{% static 'portal/img/oval_pink.svg' %}" alt="Pink oval">
31
+ </span>
32
+ <span class="login-shape-right">
33
+ <img src="{% static 'portal/img/polygon_blue.svg' %}" alt="Blue polygon">
34
+ </span>
23
35
  <div class="form--login is-flex form--register--indep-student">
24
36
  {% endif %}
25
37
  <div class="form col-xs-12 col-sm-8 col-md-8 col-lg-9 center-block">
@@ -1,5 +1,5 @@
1
1
  {% extends 'portal/base.html' %}
2
- {% load staticfiles %}
2
+ {% load static %}
3
3
  {% load app_tags %}
4
4
  {% load banner_tags %}
5
5
 
@@ -16,14 +16,14 @@
16
16
  </div>
17
17
  <div class="card__text">
18
18
  <div>
19
- <h4 class="card__title">Starting a coding club</h4>
19
+ <h4 class="card__title">Starting a coding club of your own</h4>
20
20
  <p>Become a Code for Life ambassador by starting up a coding club. Find out more about
21
- how you can get involved with this or other methods by contacting us at codeforlife@ocado.com.
21
+ how you can get involved with this by visiting our coding club page.
22
22
  </p>
23
23
  </div>
24
24
  <div>
25
- <a href="mailto:codeforlife@ocado.com" target="_blank" class="button button--primary button-right-arrow">
26
- Get in touch
25
+ <a href="{% url 'codingClub' %}" class="button button--primary button-right-arrow">
26
+ Read more
27
27
  </a>
28
28
  </div>
29
29
  </div>
@@ -56,7 +56,7 @@
56
56
  your students including: coding, user experience, data analytics and new feature design.
57
57
  </p>
58
58
  <div>
59
- <a href="mailto:codeforlife@ocado.com" target="_blank" class="button button--primary button-right-arrow">
59
+ <a href="mailto:codeforlife@ocado.com" class="button button--primary button-right-arrow">
60
60
  Get in touch
61
61
  </a>
62
62
  </div>
@@ -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 content %}
@@ -9,7 +9,12 @@
9
9
  <div class="banner--homepage banner--homepage--teacher col-sm-6">
10
10
  <div class="banner col-sm-11">
11
11
  <div class="banner__item">
12
- <a href="{% url 'teach' %}" class="educate-homepage"></a>
12
+ <a href="{% url 'teach' %}">
13
+ <img src="{% static 'portal/img/home_educate.png' %}" class="educate-homepage"
14
+ alt="Male teacher helping young female student"
15
+ title="Male teacher helping young female student"
16
+ >
17
+ </a>
13
18
  </div>
14
19
  <div class="banner-home-content">
15
20
  <div class="banner-home-text">
@@ -27,7 +32,12 @@
27
32
  <div class="banner--homepage banner--homepage--student col-sm-6">
28
33
  <div class="banner col-sm-11">
29
34
  <div class="banner__item">
30
- <a href="{% url 'play' %}" class="play-homepage"></a>
35
+ <a href="{% url 'play' %}">
36
+ <img src="{% static 'portal/img/home_play.png' %}" class="play-homepage"
37
+ alt="Two young boys playing on a laptop"
38
+ title="Two young boys playing on a laptop"
39
+ >
40
+ </a>
31
41
  </div>
32
42
  <div class="banner-home-content">
33
43
  <div class="banner-home-text">
@@ -63,12 +73,14 @@
63
73
  </div>
64
74
  <div class="col-sm-3">
65
75
  <img title="Planet" alt="Planet image" src="{% static 'portal/img/icon_globe.png' %}">
66
- <p class="col-sm-11 col-center">Code for Life has over 350,000 registered users across the world.</p>
76
+ <p class="col-sm-11 col-center">Code for Life has over 660,000 registered users across the world.</p>
67
77
  </div>
68
78
  </div>
69
79
 
70
- <div class="background">
71
- <a class="button button--primary button-right-arrow" href="{% url 'about' %}">About us</a>
80
+ <div class="background container">
81
+ <div class="d-flex justify-content-end">
82
+ <a class="button button--primary button-right-arrow" href="{% url 'about' %}">About us</a>
83
+ </div>
72
84
  </div>
73
85
 
74
86
  </section>
@@ -81,7 +93,7 @@
81
93
 
82
94
  <div class="col-sm-10 col-center image-row">
83
95
  <div class="col-sm-4">
84
- <img title="Reuben" alt="Reuben portrait" class="portrait" src="{% static 'portal/img/reuben.png' %}">
96
+ <img title="Reuben" alt="Reuben, Computer Science Teacher" class="portrait" src="{% static 'portal/img/reuben.png' %}">
85
97
  <blockquote>
86
98
  <p class="says">“My year 10's have been using Rapid Router to develop their Python skills and it has been a great transition into the Python IDE."</p>
87
99
  <p><small><b>Reuben</b>
@@ -90,7 +102,7 @@
90
102
  </blockquote>
91
103
  </div>
92
104
  <div class="col-sm-4">
93
- <img title="Sian" alt="Sian portrait" class="portrait" src="{% static 'portal/img/sian.png' %}">
105
+ <img title="Sian" alt="Sian, Head of ICT" class="portrait" src="{% static 'portal/img/sian.png' %}">
94
106
  <blockquote>
95
107
  <p class="says">“I like the slow build of layers of block coding that allows students to work at their own pace and fully embed their understanding of the different blocks."</p>
96
108
  <p><small><b>Sian</b>
@@ -99,7 +111,7 @@
99
111
  </blockquote>
100
112
  </div>
101
113
  <div class="col-sm-4">
102
- <img title="Rob" alt="Rob portrait" class="portrait" src="{% static 'portal/img/rob.png' %}">
114
+ <img title="Rob" alt="Rob, ICT teacher" class="portrait" src="{% static 'portal/img/rob.png' %}">
103
115
  <blockquote>
104
116
  <p class="says">“You can hit all of the computing curriculum, in a structured way. It is perfect for teachers who are struggling."</p>
105
117
  <p><small><b>Rob</b>
@@ -109,5 +121,18 @@
109
121
  </div>
110
122
  </div>
111
123
  </section>
124
+ <section class="background container">
125
+ <h3>Want to run a Code for Life coding club?</h3>
126
+ <p class="text-left">
127
+ Take a look at our two club packs that we have put together using our Rapid Router resources. These are fast-paced, session based
128
+ clubs that can be run by anyone keen to help people learn to code. There are guides and resource links with printable cerificates
129
+ for those that complete the course.
130
+ </p>
131
+ <div class="d-flex justify-content-end">
132
+ <a id="find_out_more" href="{% url 'codingClub' %}" class="button button--primary button--icon">
133
+ Find out more<span class="iconify" data-icon="mdi:chevron-right"></span>
134
+ </a>
135
+ </div>
136
+ </section>
112
137
 
113
- {% endblock content %}
138
+ {% endblock content %}