codeforlife-portal 7.2.0__tar.gz → 7.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of codeforlife-portal might be problematic. Click here for more details.

Files changed (555) hide show
  1. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/MANIFEST.in +0 -1
  2. {codeforlife-portal-7.2.0/codeforlife_portal.egg-info → codeforlife-portal-7.3.0}/PKG-INFO +2 -2
  3. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0/codeforlife_portal.egg-info}/PKG-INFO +2 -2
  4. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/codeforlife_portal.egg-info/requires.txt +4 -7
  5. codeforlife-portal-7.3.0/portal/__init__.py +1 -0
  6. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/forms/teach.py +206 -56
  7. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/teach/teacher_edit_class.html +57 -1
  8. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/views/teacher/teach.py +294 -83
  9. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/setup.py +4 -7
  10. codeforlife-portal-7.2.0/portal/__init__.py +0 -1
  11. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/LICENSE.md +0 -0
  12. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/README.md +0 -0
  13. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/codeforlife_portal.egg-info/SOURCES.txt +0 -0
  14. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/codeforlife_portal.egg-info/dependency_links.txt +0 -0
  15. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/codeforlife_portal.egg-info/not-zip-safe +0 -0
  16. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/codeforlife_portal.egg-info/top_level.txt +0 -0
  17. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/deploy/__init__.py +0 -0
  18. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/deploy/captcha.py +0 -0
  19. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/deploy/middleware/__init__.py +0 -0
  20. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/deploy/middleware/admin_access.py +0 -0
  21. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/deploy/middleware/basicauth.py +0 -0
  22. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/deploy/middleware/exceptionlogging.py +0 -0
  23. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/deploy/middleware/screentime_warning.py +0 -0
  24. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/deploy/middleware/security.py +0 -0
  25. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/deploy/middleware/session_timeout.py +0 -0
  26. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/deploy/static/apple-touch-icon-120x120.png +0 -0
  27. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/deploy/static/apple-touch-icon-152x152.png +0 -0
  28. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/deploy/static/apple-touch-icon-180x180.png +0 -0
  29. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/deploy/static/apple-touch-icon-76x76.png +0 -0
  30. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/deploy/static/apple-touch-icon.png +0 -0
  31. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/deploy/static/robots.txt +0 -0
  32. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/deploy/templates/deploy/csrf_failure.html +0 -0
  33. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/deploy/views.py +0 -0
  34. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/admin.py +0 -0
  35. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/app_settings.py +0 -0
  36. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/backends.py +0 -0
  37. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/beta.py +0 -0
  38. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/context_processors.py +0 -0
  39. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/forms/__init__.py +0 -0
  40. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/forms/admin.py +0 -0
  41. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/forms/dotmailer.py +0 -0
  42. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/forms/error_messages.py +0 -0
  43. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/forms/invite_teacher.py +0 -0
  44. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/forms/organisation.py +0 -0
  45. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/forms/play.py +0 -0
  46. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/forms/registration.py +0 -0
  47. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/handlers.py +0 -0
  48. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/helpers/__init__.py +0 -0
  49. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/helpers/captcha.py +0 -0
  50. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/helpers/decorators.py +0 -0
  51. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/helpers/password.py +0 -0
  52. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/helpers/ratelimit.py +0 -0
  53. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/helpers/regexes.py +0 -0
  54. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/helpers/request_handlers.py +0 -0
  55. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/migrations/0001_squashed_0041_new_news.py +0 -0
  56. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/migrations/0042_school_country.py +0 -0
  57. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/migrations/0043_auto_20150430_0952.py +0 -0
  58. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/migrations/0044_auto_20150430_0959.py +0 -0
  59. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/migrations/0045_auto_20150430_1446.py +0 -0
  60. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/migrations/0046_auto_20150723_1101.py +0 -0
  61. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/migrations/0047_remove_userprofile_avatar.py +0 -0
  62. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/migrations/0048_plural_management_frontnews.py +0 -0
  63. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/migrations/0049_refactor_emailverifications.py +0 -0
  64. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/migrations/0050_refactor_emailverifications_2.py +0 -0
  65. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/migrations/0051_add_missing_ev_records.py +0 -0
  66. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/migrations/0052_refactor_emailverifications_3.py +0 -0
  67. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/migrations/0053_refactor_teacher_student_1.py +0 -0
  68. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/migrations/0054_pending_join_request_can_be_blank.py +0 -0
  69. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/migrations/0055_add_preview_user.py +0 -0
  70. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/migrations/0056_remove_preview_user.py +0 -0
  71. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/migrations/0057_delete_frontpagenews.py +0 -0
  72. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/migrations/0058_move_to_common_models.py +0 -0
  73. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/migrations/0059_move_email_verifications_to_common.py +0 -0
  74. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/migrations/0060_delete_guardian.py +0 -0
  75. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/migrations/0061_make_portaladmin_teacher.py +0 -0
  76. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/migrations/0062_verify_portaladmin.py +0 -0
  77. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/migrations/__init__.py +0 -0
  78. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/mixins/__init__.py +0 -0
  79. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/mixins/cron_mixin.py +0 -0
  80. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/models.py +0 -0
  81. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/permissions/__init__.py +0 -0
  82. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/permissions/is_cron_request_from_google.py +0 -0
  83. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/pipeline_compilers/__init__.py +0 -0
  84. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/pipeline_compilers/libsass_compiler.py +0 -0
  85. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/fonts/bootstrap/glyphicons-halflings-regular.eot +0 -0
  86. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/fonts/bootstrap/glyphicons-halflings-regular.svg +0 -0
  87. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/fonts/bootstrap/glyphicons-halflings-regular.ttf +0 -0
  88. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/fonts/bootstrap/glyphicons-halflings-regular.woff +0 -0
  89. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/fonts/bootstrap/glyphicons-halflings-regular.woff2 +0 -0
  90. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/10_years_anniversary.png +0 -0
  91. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/10x_logo.png +0 -0
  92. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/RR_logo_grass_background.png +0 -0
  93. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/RR_logo_green.svg +0 -0
  94. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/RR_logo_simple.png +0 -0
  95. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/about_us_cfl.jpg +0 -0
  96. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/about_us_hero.jpg +0 -0
  97. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/about_us_ocado.jpg +0 -0
  98. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/barefoot_logo.png +0 -0
  99. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/bcs_logo.png +0 -0
  100. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/clubs.png +0 -0
  101. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/coding_club_hero.jpg +0 -0
  102. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/coding_club_python_pack.png +0 -0
  103. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/colorboxImages/border.png +0 -0
  104. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/colorboxImages/controls.png +0 -0
  105. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/colorboxImages/loading.gif +0 -0
  106. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/colorboxImages/loading_background.png +0 -0
  107. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/colorboxImages/overlay.png +0 -0
  108. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/confirmation_tick.png +0 -0
  109. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/cross.png +0 -0
  110. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/dee.png +0 -0
  111. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/facebook.png +0 -0
  112. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/favicon.ico +0 -0
  113. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/get_involved_hero.png +0 -0
  114. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/gitbook.png +0 -0
  115. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/gitbook_space.png +0 -0
  116. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/github.png +0 -0
  117. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/github_hero.png +0 -0
  118. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/gla_logo.png +0 -0
  119. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/hamburger.png +0 -0
  120. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/help_and_support_hero.jpg +0 -0
  121. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/home_educate.png +0 -0
  122. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/home_educate_hero.jpg +0 -0
  123. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/home_learning_hero.jpg +0 -0
  124. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/home_play.png +0 -0
  125. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/home_play_hero.jpg +0 -0
  126. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/hope_logo.png +0 -0
  127. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/howe_dell_1.png +0 -0
  128. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/howe_dell_2.png +0 -0
  129. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/howe_dell_3.png +0 -0
  130. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/icl_logo.png +0 -0
  131. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/icon_controller.png +0 -0
  132. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/icon_free.png +0 -0
  133. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/icon_globe.png +0 -0
  134. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/icon_piechart.png +0 -0
  135. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/icon_step_by_step.png +0 -0
  136. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/icon_tracking.png +0 -0
  137. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/icon_uk_flag.png +0 -0
  138. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/kirsty.png +0 -0
  139. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/logo_cfl.png +0 -0
  140. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/logo_cfl_powered.svg +0 -0
  141. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/logo_cfl_reminder_cards.jpg +0 -0
  142. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/logo_cfl_white_landscape.png +0 -0
  143. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/logo_ocado.png +0 -0
  144. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/logo_ocado_group.png +0 -0
  145. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/logo_ocado_group.svg +0 -0
  146. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/logo_ocado_group_white.svg +0 -0
  147. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/logo_python_den.svg +0 -0
  148. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/long_europe_map.png +0 -0
  149. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/mc_saatchi_logo.png +0 -0
  150. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/nigel.png +0 -0
  151. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/ocado-swirl.svg +0 -0
  152. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/oval_blue.svg +0 -0
  153. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/oval_pink.svg +0 -0
  154. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/oval_yellow.svg +0 -0
  155. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/paper_plane.png +0 -0
  156. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/phil.png +0 -0
  157. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/polygon_blue.svg +0 -0
  158. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/polygon_pink.svg +0 -0
  159. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/polygon_yellow.svg +0 -0
  160. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/pressure_cooker_logo.png +0 -0
  161. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/python_den.png +0 -0
  162. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/python_den_banner.svg +0 -0
  163. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/rapid_router.png +0 -0
  164. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/rapid_router_landing_hero.png +0 -0
  165. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/rapidrouter.png +0 -0
  166. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/resources_hero.jpg +0 -0
  167. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/resources_montage.jpg +0 -0
  168. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/reuben.png +0 -0
  169. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/rob.png +0 -0
  170. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/rr_advanced.png +0 -0
  171. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/rr_beginner.png +0 -0
  172. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/rr_intermediate.png +0 -0
  173. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/sadface.png +0 -0
  174. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/sharon_harrison.jpg +0 -0
  175. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/sian.png +0 -0
  176. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/teaching_resources_hero.jpg +0 -0
  177. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/ten_year_map_pin.svg +0 -0
  178. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/thumbnail_educate_rapid_router.png +0 -0
  179. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/thumbnail_educate_resources.png +0 -0
  180. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/thumbnail_intro_c4l.jpg +0 -0
  181. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/thumbnail_play_rapid_router.png +0 -0
  182. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/thumbnail_python_den.png +0 -0
  183. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/twitter.png +0 -0
  184. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/universities.png +0 -0
  185. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/wes.png +0 -0
  186. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/img/x_close_video.png +0 -0
  187. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/js/bootstrap.min.js +0 -0
  188. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/js/carouselCards.js +0 -0
  189. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/js/common.js +0 -0
  190. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/js/independentLogin.js +0 -0
  191. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/js/independentRegistration.js +0 -0
  192. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/js/join_create_game_toggle.js +0 -0
  193. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/js/jquery.placeholder.js +0 -0
  194. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/js/levelControl.js +0 -0
  195. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/js/lib/jquery-video-lightning.js +0 -0
  196. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/js/lib/jquery.colorbox.js +0 -0
  197. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/js/lib/jquery.easy-ticker.js +0 -0
  198. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/js/lib/jquery.min.js +0 -0
  199. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/js/lib/modernizr-build.js +0 -0
  200. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/js/lib/papaparse.min.js +0 -0
  201. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/js/organisation_manage.js +0 -0
  202. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/js/passwordStrength.js +0 -0
  203. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/js/play.js +0 -0
  204. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/js/resetPassword.js +0 -0
  205. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/js/riveted.min.js +0 -0
  206. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/js/school.js +0 -0
  207. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/js/sticky_subnav.js +0 -0
  208. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/js/studentLogin.js +0 -0
  209. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/js/teach_browser.js +0 -0
  210. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/js/teach_class.js +0 -0
  211. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/js/teacherEditStudent.js +0 -0
  212. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/js/teacherLogin.js +0 -0
  213. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/js/tenYearMap.js +0 -0
  214. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_alerts.scss +0 -0
  215. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_badges.scss +0 -0
  216. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_breadcrumbs.scss +0 -0
  217. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_button-groups.scss +0 -0
  218. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_buttons.scss +0 -0
  219. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_carousel.scss +0 -0
  220. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_close.scss +0 -0
  221. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_code.scss +0 -0
  222. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_component-animations.scss +0 -0
  223. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_dropdowns.scss +0 -0
  224. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_forms.scss +0 -0
  225. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_glyphicons.scss +0 -0
  226. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_grid.scss +0 -0
  227. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_input-groups.scss +0 -0
  228. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_jumbotron.scss +0 -0
  229. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_labels.scss +0 -0
  230. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_list-group.scss +0 -0
  231. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_media.scss +0 -0
  232. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_mixins.scss +0 -0
  233. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_modals.scss +0 -0
  234. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_navbar.scss +0 -0
  235. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_navs.scss +0 -0
  236. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_normalize.scss +0 -0
  237. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_pager.scss +0 -0
  238. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_pagination.scss +0 -0
  239. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_panels.scss +0 -0
  240. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_popovers.scss +0 -0
  241. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_print.scss +0 -0
  242. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_progress-bars.scss +0 -0
  243. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_responsive-embed.scss +0 -0
  244. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_responsive-utilities.scss +0 -0
  245. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_scaffolding.scss +0 -0
  246. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_tables.scss +0 -0
  247. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_theme.scss +0 -0
  248. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_thumbnails.scss +0 -0
  249. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_tooltip.scss +0 -0
  250. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_type.scss +0 -0
  251. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_utilities.scss +0 -0
  252. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_variables.scss +0 -0
  253. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/_wells.scss +0 -0
  254. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/mixins/_alerts.scss +0 -0
  255. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/mixins/_background-variant.scss +0 -0
  256. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/mixins/_border-radius.scss +0 -0
  257. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/mixins/_breakpoints.scss +0 -0
  258. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/mixins/_buttons.scss +0 -0
  259. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/mixins/_center-block.scss +0 -0
  260. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/mixins/_clearfix.scss +0 -0
  261. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/mixins/_forms.scss +0 -0
  262. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/mixins/_gradients.scss +0 -0
  263. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/mixins/_grid-framework.scss +0 -0
  264. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/mixins/_grid.scss +0 -0
  265. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/mixins/_hide-text.scss +0 -0
  266. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/mixins/_image.scss +0 -0
  267. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/mixins/_labels.scss +0 -0
  268. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/mixins/_list-group.scss +0 -0
  269. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/mixins/_nav-divider.scss +0 -0
  270. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/mixins/_nav-vertical-align.scss +0 -0
  271. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/mixins/_opacity.scss +0 -0
  272. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/mixins/_pagination.scss +0 -0
  273. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/mixins/_panels.scss +0 -0
  274. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/mixins/_progress-bar.scss +0 -0
  275. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/mixins/_reset-filter.scss +0 -0
  276. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/mixins/_reset-text.scss +0 -0
  277. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/mixins/_resize.scss +0 -0
  278. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/mixins/_responsive-visibility.scss +0 -0
  279. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/mixins/_size.scss +0 -0
  280. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/mixins/_tab-focus.scss +0 -0
  281. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/mixins/_table-row.scss +0 -0
  282. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/mixins/_text-emphasis.scss +0 -0
  283. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/mixins/_text-overflow.scss +0 -0
  284. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/mixins/_text-truncate.scss +0 -0
  285. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap/mixins/_vendor-prefixes.scss +0 -0
  286. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap.scss +0 -0
  287. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap_mixins/_all.scss +0 -0
  288. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap_mixins/_border-radius.scss +0 -0
  289. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap_mixins/_box-shadow.scss +0 -0
  290. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap_mixins/_hover.scss +0 -0
  291. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap_mixins/_nav-divider.scss +0 -0
  292. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap_partials/_dropdown.scss +0 -0
  293. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap_partials/_glyphicons.scss +0 -0
  294. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap_partials/_grid.scss +0 -0
  295. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap_partials/_variables.scss +0 -0
  296. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap_utilities/_align.scss +0 -0
  297. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap_utilities/_background.scss +0 -0
  298. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap_utilities/_borders.scss +0 -0
  299. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap_utilities/_clearfix.scss +0 -0
  300. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap_utilities/_cursor.scss +0 -0
  301. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap_utilities/_display.scss +0 -0
  302. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap_utilities/_flex.scss +0 -0
  303. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap_utilities/_float.scss +0 -0
  304. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap_utilities/_position.scss +0 -0
  305. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap_utilities/_screenreaders.scss +0 -0
  306. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap_utilities/_sizing.scss +0 -0
  307. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap_utilities/_spacing.scss +0 -0
  308. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap_utilities/_text.scss +0 -0
  309. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/bootstrap_utilities/_visibility.scss +0 -0
  310. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/colorbox.scss +0 -0
  311. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/modules/_all.scss +0 -0
  312. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/modules/_animation.scss +0 -0
  313. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/modules/_breakpoints.scss +0 -0
  314. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/modules/_card_constants.scss +0 -0
  315. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/modules/_colours.scss +0 -0
  316. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/modules/_homepage_constants.scss +0 -0
  317. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/modules/_levels.scss +0 -0
  318. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/modules/_mixins.scss +0 -0
  319. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/modules/_spacing.scss +0 -0
  320. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/partials/_banners.scss +0 -0
  321. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/partials/_base.scss +0 -0
  322. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/partials/_buttons.scss +0 -0
  323. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/partials/_carousel.scss +0 -0
  324. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/partials/_footer.scss +0 -0
  325. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/partials/_forms.scss +0 -0
  326. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/partials/_grids.scss +0 -0
  327. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/partials/_header.scss +0 -0
  328. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/partials/_images.scss +0 -0
  329. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/partials/_popup.scss +0 -0
  330. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/partials/_progress-bars.scss +0 -0
  331. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/partials/_subnavs.scss +0 -0
  332. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/partials/_tables.scss +0 -0
  333. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/partials/_text.scss +0 -0
  334. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/partials/_ui-dialog.scss +0 -0
  335. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/partials/_utils.scss +0 -0
  336. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/sass/styles.scss +0 -0
  337. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/static/portal/video/code for life .pdf +0 -0
  338. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/strings/__init__.py +0 -0
  339. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/strings/about.py +0 -0
  340. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/strings/coding_club.py +0 -0
  341. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/strings/help_and_support.py +0 -0
  342. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/strings/home_learning.py +0 -0
  343. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/strings/materials.py +0 -0
  344. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/strings/play.py +0 -0
  345. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/strings/teach.py +0 -0
  346. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/strings/teacher_resources.py +0 -0
  347. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/strings/ten_year_map.py +0 -0
  348. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/403.html +0 -0
  349. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/404.html +0 -0
  350. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/500.html +0 -0
  351. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/captcha/includes/js_v2_invisible.html +0 -0
  352. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/captcha/widget_v2_invisible.html +0 -0
  353. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/email.html +0 -0
  354. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/email.txt +0 -0
  355. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/about.html +0 -0
  356. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/base.html +0 -0
  357. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/base_no_userprofile.html +0 -0
  358. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/coding_club.html +0 -0
  359. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/contribute.html +0 -0
  360. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/dotmailer_consent_form.html +0 -0
  361. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/email_invitation_sent.html +0 -0
  362. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/email_style_template.html +0 -0
  363. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/email_verification_failed.html +0 -0
  364. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/email_verification_needed.html +0 -0
  365. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/form_shapes.html +0 -0
  366. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/getinvolved.html +0 -0
  367. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/home.html +0 -0
  368. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/home_learning.html +0 -0
  369. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/locked_out.html +0 -0
  370. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/locked_out_school_student.html +0 -0
  371. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/login/independent_student.html +0 -0
  372. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/login/student.html +0 -0
  373. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/login/student_class_code.html +0 -0
  374. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/login/teacher.html +0 -0
  375. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/mouseflow.html +0 -0
  376. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/partials/banner.html +0 -0
  377. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/partials/benefits.html +0 -0
  378. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/partials/card_list.html +0 -0
  379. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/partials/character_list.html +0 -0
  380. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/partials/delete_popup.html +0 -0
  381. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/partials/footer.html +0 -0
  382. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/partials/header.html +0 -0
  383. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/partials/headline.html +0 -0
  384. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/partials/hero_card.html +0 -0
  385. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/partials/info_popup.html +0 -0
  386. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/partials/invite_admin_teacher.html +0 -0
  387. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/partials/popup.html +0 -0
  388. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/partials/register_newsletter_tickbox.html +0 -0
  389. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/partials/screentime_popup.html +0 -0
  390. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/partials/service_unavailable_popup.html +0 -0
  391. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/partials/session_popup.html +0 -0
  392. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/partials/teacher_non_dashboard_subnav.html +0 -0
  393. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/partials/teacher_non_dashboard_subnav_account.html +0 -0
  394. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/play/student_dashboard.html +0 -0
  395. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/play/student_edit_account.html +0 -0
  396. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/play/student_join_organisation.html +0 -0
  397. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/play.html +0 -0
  398. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/privacy_notice.html +0 -0
  399. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/register.html +0 -0
  400. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/reset_password.html +0 -0
  401. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/reset_password_confirm.html +0 -0
  402. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/reset_password_done.html +0 -0
  403. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/reset_password_email_sent.html +0 -0
  404. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/tag_manager/tag_manager_body.html +0 -0
  405. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/tag_manager/tag_manager_head.html +0 -0
  406. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/teach/base_registering.html +0 -0
  407. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/teach/class.html +0 -0
  408. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/teach/dashboard.html +0 -0
  409. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/teach/invited.html +0 -0
  410. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/teach/onboarding_classes.html +0 -0
  411. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/teach/onboarding_print.html +0 -0
  412. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/teach/onboarding_school.html +0 -0
  413. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/teach/onboarding_students.html +0 -0
  414. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/teach/teacher_add_external_student.html +0 -0
  415. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/teach/teacher_added_external_student.html +0 -0
  416. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/teach/teacher_dismiss_students.html +0 -0
  417. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/teach/teacher_edit_student.html +0 -0
  418. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/teach/teacher_move_all_classes.html +0 -0
  419. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/teach/teacher_move_students.html +0 -0
  420. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/teach/teacher_move_students_to_class.html +0 -0
  421. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/teach.html +0 -0
  422. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/ten_year_map.html +0 -0
  423. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/portal/terms.html +0 -0
  424. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/two_factor/_base.html +0 -0
  425. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/two_factor/_wizard_actions.html +0 -0
  426. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/two_factor/_wizard_actions_enable_2fa.html +0 -0
  427. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/two_factor/_wizard_actions_submit.html +0 -0
  428. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/two_factor/_wizard_forms.html +0 -0
  429. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/two_factor/_wizard_forms_token.html +0 -0
  430. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/two_factor/backup_token.html +0 -0
  431. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/two_factor/core/backup_tokens.html +0 -0
  432. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/two_factor/core/login.html +0 -0
  433. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/two_factor/core/setup.html +0 -0
  434. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/two_factor/core/setup_complete.html +0 -0
  435. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/two_factor/profile/disable.html +0 -0
  436. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/two_factor/profile/profile.html +0 -0
  437. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templates/two_factor/setup_wizard_token.html +0 -0
  438. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templatetags/__init__.py +0 -0
  439. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templatetags/app_tags.py +0 -0
  440. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templatetags/banner_tags.py +0 -0
  441. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templatetags/benefits_tags.py +0 -0
  442. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templatetags/card_list_tags.py +0 -0
  443. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templatetags/future.py +0 -0
  444. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templatetags/headline_tags.py +0 -0
  445. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templatetags/hero_card_tags.py +0 -0
  446. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/templatetags/table_tags.py +0 -0
  447. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/__init__.py +0 -0
  448. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/base_test.py +0 -0
  449. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/conftest.py +0 -0
  450. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/migrations/__init__.py +0 -0
  451. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/migrations/test_migration_make_portaladmin_teacher.py +0 -0
  452. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/migrations/test_migration_preview_user_remove.py +0 -0
  453. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/migrations/test_migration_preview_users.py +0 -0
  454. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/migrations/test_migration_remove_front_page_news.py +0 -0
  455. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/migrations/test_migration_remove_guardian.py +0 -0
  456. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/migrations/test_migration_use_common_models.py +0 -0
  457. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/migrations/test_migration_verify_portaladmin.py +0 -0
  458. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/__init__.py +0 -0
  459. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/__init__.py +0 -0
  460. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/admin/__init__.py +0 -0
  461. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/admin/admin_base_page.py +0 -0
  462. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/admin/admin_data_page.py +0 -0
  463. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/admin/admin_map_page.py +0 -0
  464. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/base_page.py +0 -0
  465. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/email_verification_needed_page.py +0 -0
  466. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/forbidden_page.py +0 -0
  467. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/game_page.py +0 -0
  468. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/home_page.py +0 -0
  469. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/independent_login_page.py +0 -0
  470. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/password_reset_form_page.py +0 -0
  471. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/password_reset_page.py +0 -0
  472. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/play/__init__.py +0 -0
  473. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/play/account_page.py +0 -0
  474. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/play/dashboard_page.py +0 -0
  475. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/play/join_school_or_club_page.py +0 -0
  476. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/play/play_base_page.py +0 -0
  477. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/play_page.py +0 -0
  478. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/resources_page.py +0 -0
  479. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/signup_page.py +0 -0
  480. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/student_login_class_code.py +0 -0
  481. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/student_login_page.py +0 -0
  482. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/teach/__init__.py +0 -0
  483. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/teach/add_independent_student_to_class_page.py +0 -0
  484. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/teach/added_independent_student_to_class_page.py +0 -0
  485. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/teach/class_page.py +0 -0
  486. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/teach/dashboard_page.py +0 -0
  487. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/teach/dismiss_students_page.py +0 -0
  488. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/teach/edit_student_page.py +0 -0
  489. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/teach/move_class_page.py +0 -0
  490. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/teach/move_classes_page.py +0 -0
  491. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/teach/move_students_disambiguate_page.py +0 -0
  492. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/teach/move_students_page.py +0 -0
  493. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/teach/onboarding_classes_page.py +0 -0
  494. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/teach/onboarding_organisation_page.py +0 -0
  495. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/teach/onboarding_student_list_page.py +0 -0
  496. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/teach/onboarding_students_page.py +0 -0
  497. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/teach/teach_base_page.py +0 -0
  498. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/pageObjects/portal/teacher_login_page.py +0 -0
  499. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/selenium_test_case.py +0 -0
  500. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/snapshots/__init__.py +0 -0
  501. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/snapshots/snap_test_partials.py +0 -0
  502. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/test_2FA.py +0 -0
  503. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/test_admin.py +0 -0
  504. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/test_api.py +0 -0
  505. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/test_captcha_forms.py +0 -0
  506. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/test_class.py +0 -0
  507. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/test_daily_activities.py +0 -0
  508. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/test_emails.py +0 -0
  509. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/test_helper_methods.py +0 -0
  510. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/test_independent_student.py +0 -0
  511. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/test_invite_teacher.py +0 -0
  512. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/test_middleware.py +0 -0
  513. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/test_newsletter_footer.py +0 -0
  514. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/test_organisation.py +0 -0
  515. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/test_partials.py +0 -0
  516. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/test_ratelimit.py +0 -0
  517. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/test_school_student.py +0 -0
  518. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/test_security.py +0 -0
  519. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/test_teacher.py +0 -0
  520. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/test_teacher_student.py +0 -0
  521. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/test_views.py +0 -0
  522. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/utils/__init__.py +0 -0
  523. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/utils/classes.py +0 -0
  524. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/tests/utils/messages.py +0 -0
  525. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/urls.py +0 -0
  526. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/views/__init__.py +0 -0
  527. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/views/about.py +0 -0
  528. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/views/admin.py +0 -0
  529. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/views/api.py +0 -0
  530. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/views/cron/__init__.py +0 -0
  531. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/views/cron/user.py +0 -0
  532. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/views/dotmailer.py +0 -0
  533. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/views/email.py +0 -0
  534. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/views/home.py +0 -0
  535. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/views/legal.py +0 -0
  536. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/views/login/__init__.py +0 -0
  537. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/views/login/independent_student.py +0 -0
  538. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/views/login/student.py +0 -0
  539. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/views/login/teacher.py +0 -0
  540. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/views/organisation.py +0 -0
  541. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/views/play_landing_page.py +0 -0
  542. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/views/registration.py +0 -0
  543. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/views/student/__init__.py +0 -0
  544. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/views/student/edit_account_details.py +0 -0
  545. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/views/student/play.py +0 -0
  546. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/views/teach.py +0 -0
  547. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/views/teacher/__init__.py +0 -0
  548. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/views/teacher/dashboard.py +0 -0
  549. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/views/two_factor/__init__.py +0 -0
  550. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/views/two_factor/core.py +0 -0
  551. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/views/two_factor/form.py +0 -0
  552. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/views/two_factor/profile.py +0 -0
  553. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/portal/wsgi.py +0 -0
  554. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/pyproject.toml +0 -0
  555. {codeforlife-portal-7.2.0 → codeforlife-portal-7.3.0}/setup.cfg +0 -0
@@ -5,4 +5,3 @@ graft portal/static
5
5
  graft portal/templates
6
6
  prune cfl_common
7
7
  prune example_project
8
- graft portal/frontend
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: codeforlife-portal
3
- Version: 7.2.0
3
+ Version: 7.3.0
4
4
  Classifier: Programming Language :: Python
5
- Classifier: Programming Language :: Python :: 3.8
5
+ Classifier: Programming Language :: Python :: 3.12
6
6
  Classifier: Framework :: Django
7
7
  Description-Content-Type: text/markdown
8
8
  License-File: LICENSE.md
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: codeforlife-portal
3
- Version: 7.2.0
3
+ Version: 7.3.0
4
4
  Classifier: Programming Language :: Python
5
- Classifier: Programming Language :: Python :: 3.8
5
+ Classifier: Programming Language :: Python :: 3.12
6
6
  Classifier: Framework :: Django
7
7
  Description-Content-Type: text/markdown
8
8
  License-File: LICENSE.md
@@ -1,11 +1,8 @@
1
- django==3.2.25
2
- django-countries==7.3.1
3
- djangorestframework==3.13.1
4
1
  django-pipeline==2.0.8
5
2
  django-recaptcha==2.0.6
6
- pyyaml==5.4.1
3
+ pyyaml==6.0.2
7
4
  importlib-metadata==4.13.0
8
- rapid-router>=6
5
+ rapid-router>=6.3.6
9
6
  reportlab==3.6.13
10
7
  django-formtools==2.2
11
8
  django-otp==1.0.2
@@ -16,9 +13,9 @@ django-classy-tags==2.0.0
16
13
  libsass==0.23.0
17
14
  phonenumbers==8.12.12
18
15
  more-itertools==8.7.0
19
- cfl-common==7.2.0
16
+ cfl-common==7.3.0
20
17
  django-ratelimit==3.0.1
21
18
  django-preventconcurrentlogins==0.8.2
22
19
  django-csp==3.7
23
- setuptools==70.3.0
20
+ setuptools==74.0.0
24
21
  django-import-export
@@ -0,0 +1 @@
1
+ __version__ = "7.3.0"
@@ -20,25 +20,37 @@ from portal.helpers.ratelimit import clear_ratelimit_cache_for_user
20
20
  class InvitedTeacherForm(forms.Form):
21
21
  teacher_password = forms.CharField(
22
22
  help_text="Enter a password",
23
- widget=forms.PasswordInput(attrs={"autocomplete": "off", "placeholder": "Password"}),
23
+ widget=forms.PasswordInput(
24
+ attrs={"autocomplete": "off", "placeholder": "Password"}
25
+ ),
24
26
  )
25
27
  teacher_confirm_password = forms.CharField(
26
28
  help_text="Repeat password",
27
- widget=forms.PasswordInput(attrs={"autocomplete": "off", "placeholder": "Repeat password"}),
29
+ widget=forms.PasswordInput(
30
+ attrs={"autocomplete": "off", "placeholder": "Repeat password"}
31
+ ),
28
32
  )
29
33
 
30
- consent_ticked = forms.BooleanField(widget=forms.CheckboxInput(), initial=False, required=True)
31
- newsletter_ticked = forms.BooleanField(widget=forms.CheckboxInput(), initial=False, required=False)
34
+ consent_ticked = forms.BooleanField(
35
+ widget=forms.CheckboxInput(), initial=False, required=True
36
+ )
37
+ newsletter_ticked = forms.BooleanField(
38
+ widget=forms.CheckboxInput(), initial=False, required=False
39
+ )
32
40
 
33
41
  def clean_teacher_password(self):
34
- return form_clean_password(self, "teacher_password", PasswordStrength.TEACHER)
42
+ return form_clean_password(
43
+ self, "teacher_password", PasswordStrength.TEACHER
44
+ )
35
45
 
36
46
  def clean(self):
37
47
  if any(self.errors):
38
48
  return
39
49
 
40
50
  password = self.cleaned_data.get("teacher_password", None)
41
- confirm_password = self.cleaned_data.get("teacher_confirm_password", None)
51
+ confirm_password = self.cleaned_data.get(
52
+ "teacher_confirm_password", None
53
+ )
42
54
 
43
55
  check_passwords(password, confirm_password)
44
56
 
@@ -49,16 +61,22 @@ class TeacherSignupForm(InvitedTeacherForm):
49
61
  teacher_first_name = forms.CharField(
50
62
  help_text="Enter your first name",
51
63
  max_length=100,
52
- widget=forms.TextInput(attrs={"autocomplete": "off", "placeholder": "First name"}),
64
+ widget=forms.TextInput(
65
+ attrs={"autocomplete": "off", "placeholder": "First name"}
66
+ ),
53
67
  )
54
68
  teacher_last_name = forms.CharField(
55
69
  help_text="Enter your last name",
56
70
  max_length=100,
57
- widget=forms.TextInput(attrs={"autocomplete": "off", "placeholder": "Last name"}),
71
+ widget=forms.TextInput(
72
+ attrs={"autocomplete": "off", "placeholder": "Last name"}
73
+ ),
58
74
  )
59
75
  teacher_email = forms.EmailField(
60
76
  help_text="Enter your email address",
61
- widget=forms.EmailInput(attrs={"autocomplete": "off", "placeholder": "Email address"}),
77
+ widget=forms.EmailInput(
78
+ attrs={"autocomplete": "off", "placeholder": "Email address"}
79
+ ),
62
80
  )
63
81
 
64
82
  captcha = ReCaptchaField(widget=ReCaptchaV2Invisible)
@@ -67,31 +85,42 @@ class TeacherSignupForm(InvitedTeacherForm):
67
85
  class TeacherEditAccountForm(forms.Form):
68
86
  first_name = forms.CharField(
69
87
  max_length=100,
70
- widget=forms.TextInput(attrs={"placeholder": "First name", "class": "fName"}),
88
+ widget=forms.TextInput(
89
+ attrs={"placeholder": "First name", "class": "fName"}
90
+ ),
71
91
  help_text="First name",
72
92
  )
73
93
  last_name = forms.CharField(
74
94
  max_length=100,
75
- widget=forms.TextInput(attrs={"placeholder": "Last name", "class": "lName"}),
95
+ widget=forms.TextInput(
96
+ attrs={"placeholder": "Last name", "class": "lName"}
97
+ ),
76
98
  help_text="Last name",
77
99
  )
78
100
  email = forms.EmailField(
79
101
  required=False,
80
- widget=forms.EmailInput(attrs={"placeholder": "New email address (optional)"}),
102
+ widget=forms.EmailInput(
103
+ attrs={"placeholder": "New email address (optional)"}
104
+ ),
81
105
  help_text="New email address (optional)",
82
106
  )
83
107
  password = forms.CharField(
84
108
  required=False,
85
- widget=forms.PasswordInput(attrs={"placeholder": "New password (optional)"}),
109
+ widget=forms.PasswordInput(
110
+ attrs={"placeholder": "New password (optional)"}
111
+ ),
86
112
  help_text="New password (optional)",
87
113
  )
88
114
  confirm_password = forms.CharField(
89
115
  required=False,
90
- widget=forms.PasswordInput(attrs={"placeholder": "Confirm new password (optional)"}),
116
+ widget=forms.PasswordInput(
117
+ attrs={"placeholder": "Confirm new password (optional)"}
118
+ ),
91
119
  help_text="Confirm new password (optional)",
92
120
  )
93
121
  current_password = forms.CharField(
94
- widget=forms.PasswordInput(attrs={"placeholder": "Current password"}), help_text="Enter your current password"
122
+ widget=forms.PasswordInput(attrs={"placeholder": "Current password"}),
123
+ help_text="Enter your current password",
95
124
  )
96
125
 
97
126
  def __init__(self, user, *args, **kwargs):
@@ -113,7 +142,9 @@ class TeacherEditAccountForm(forms.Form):
113
142
 
114
143
  return self.cleaned_data
115
144
 
116
- def check_password_errors(self, password, confirm_password, current_password):
145
+ def check_password_errors(
146
+ self, password, confirm_password, current_password
147
+ ):
117
148
  check_passwords(password, confirm_password)
118
149
 
119
150
  if not self.user.check_password(current_password):
@@ -122,11 +153,15 @@ class TeacherEditAccountForm(forms.Form):
122
153
 
123
154
  class TeacherLoginForm(AuthenticationForm):
124
155
  username = forms.EmailField(
125
- widget=forms.EmailInput(attrs={"autocomplete": "off", "placeholder": "Email address"}),
156
+ widget=forms.EmailInput(
157
+ attrs={"autocomplete": "off", "placeholder": "Email address"}
158
+ ),
126
159
  help_text="Enter your email address",
127
160
  )
128
161
  password = forms.CharField(
129
- widget=forms.PasswordInput(attrs={"autocomplete": "off", "placeholder": "Password"}),
162
+ widget=forms.PasswordInput(
163
+ attrs={"autocomplete": "off", "placeholder": "Password"}
164
+ ),
130
165
  help_text="Enter your password",
131
166
  )
132
167
 
@@ -160,7 +195,9 @@ class TeacherLoginForm(AuthenticationForm):
160
195
  users = User.objects.filter(email=email)
161
196
 
162
197
  for result in users:
163
- if hasattr(result, "userprofile") and hasattr(result.userprofile, "teacher"):
198
+ if hasattr(result, "userprofile") and hasattr(
199
+ result.userprofile, "teacher"
200
+ ):
164
201
  user = result
165
202
  break
166
203
 
@@ -186,7 +223,8 @@ class TeacherLoginForm(AuthenticationForm):
186
223
 
187
224
  class ClassCreationForm(forms.Form):
188
225
  class_name = forms.CharField(
189
- widget=forms.TextInput(attrs={"placeholder": "Class name"}), help_text="Enter a class name"
226
+ widget=forms.TextInput(attrs={"placeholder": "Class name"}),
227
+ help_text="Enter a class name",
190
228
  )
191
229
  teacher = forms.ChoiceField(help_text="Select teacher", required=False)
192
230
  classmate_progress = forms.BooleanField(
@@ -201,7 +239,12 @@ class ClassCreationForm(forms.Form):
201
239
 
202
240
  if teacher is not None:
203
241
  # Place current teacher at the top
204
- teacher_choices = [(teacher.id, f"{teacher.new_user.first_name} {teacher.new_user.last_name}")]
242
+ teacher_choices = [
243
+ (
244
+ teacher.id,
245
+ f"{teacher.new_user.first_name} {teacher.new_user.last_name}",
246
+ )
247
+ ]
205
248
 
206
249
  # Get coworkers and add them to the choices if the teacher is an admin
207
250
  if teacher.is_admin:
@@ -212,7 +255,10 @@ class ClassCreationForm(forms.Form):
212
255
  )
213
256
  for coworker in coworkers:
214
257
  teacher_choices.append(
215
- (coworker.id, f"{coworker.new_user.first_name} {coworker.new_user.last_name}")
258
+ (
259
+ coworker.id,
260
+ f"{coworker.new_user.first_name} {coworker.new_user.last_name}",
261
+ )
216
262
  )
217
263
 
218
264
  self.fields["teacher"].choices = teacher_choices
@@ -231,19 +277,35 @@ class ClassEditForm(forms.Form):
231
277
  ]
232
278
  join_choices.extend(
233
279
  [
234
- (str(hours), "Allow external requests to this class for the next " + str(hours) + " hours")
280
+ (
281
+ str(hours),
282
+ "Allow external requests to this class for the next "
283
+ + str(hours)
284
+ + " hours",
285
+ )
235
286
  for hours in range(4, 28, 4)
236
287
  ]
237
288
  )
238
289
  join_choices.extend(
239
290
  [
240
- (str(days * 24), "Allow external requests to this class for the next " + str(days) + " days")
291
+ (
292
+ str(days * 24),
293
+ "Allow external requests to this class for the next "
294
+ + str(days)
295
+ + " days",
296
+ )
241
297
  for days in range(2, 5)
242
298
  ]
243
299
  )
244
- join_choices.append(("1000", "Always allow external requests to this class (not recommended)"))
300
+ join_choices.append(
301
+ (
302
+ "1000",
303
+ "Always allow external requests to this class (not recommended)",
304
+ )
305
+ )
245
306
  name = forms.CharField(
246
- widget=forms.TextInput(attrs={"placeholder": "Enter class name"}), help_text="Enter class name"
307
+ widget=forms.TextInput(attrs={"placeholder": "Enter class name"}),
308
+ help_text="Enter class name",
247
309
  )
248
310
  classmate_progress = forms.BooleanField(
249
311
  label="Allow students to see their classmates' progress?",
@@ -264,7 +326,7 @@ class ClassLevelControlForm(forms.Form):
264
326
  def __init__(self, *args, **kwargs):
265
327
  super(ClassLevelControlForm, self).__init__(*args, **kwargs)
266
328
 
267
- episodes = Episode.objects.filter(pk__in=range(1, 10))
329
+ episodes = Episode.objects.filter(pk__in=range(1, 22))
268
330
 
269
331
  for episode in episodes:
270
332
  levels = []
@@ -275,27 +337,40 @@ class ClassLevelControlForm(forms.Form):
275
337
  levels_choices = [(level.id, level.name) for level in levels]
276
338
 
277
339
  self.fields[episode.name] = forms.MultipleChoiceField(
278
- choices=itertools.chain(levels_choices), widget=forms.CheckboxSelectMultiple(), required=False
340
+ choices=itertools.chain(levels_choices),
341
+ widget=forms.CheckboxSelectMultiple(),
342
+ required=False,
279
343
  )
280
344
 
281
345
 
282
346
  class ClassMoveForm(forms.Form):
283
347
  new_teacher = forms.ChoiceField(
284
- label="New teacher to take over class", help_text="Select teacher", widget=forms.Select()
348
+ label="New teacher to take over class",
349
+ help_text="Select teacher",
350
+ widget=forms.Select(),
285
351
  )
286
352
 
287
353
  def __init__(self, teachers, *args, **kwargs):
288
354
  self.teachers = teachers
289
355
  teacher_choices = []
290
356
  for teacher in teachers:
291
- teacher_choices.append((teacher.id, teacher.new_user.first_name + " " + teacher.new_user.last_name))
357
+ teacher_choices.append(
358
+ (
359
+ teacher.id,
360
+ teacher.new_user.first_name
361
+ + " "
362
+ + teacher.new_user.last_name,
363
+ )
364
+ )
292
365
  super(ClassMoveForm, self).__init__(*args, **kwargs)
293
366
  self.fields["new_teacher"].choices = teacher_choices
294
367
 
295
368
 
296
369
  class TeacherEditStudentForm(forms.Form):
297
370
  name = forms.CharField(
298
- label="Name", widget=forms.TextInput(attrs={"placeholder": "Name"}), help_text="Choose a name"
371
+ label="Name",
372
+ widget=forms.TextInput(attrs={"placeholder": "Name"}),
373
+ help_text="Choose a name",
299
374
  )
300
375
 
301
376
  def __init__(self, student, *args, **kwargs):
@@ -307,14 +382,24 @@ class TeacherEditStudentForm(forms.Form):
307
382
  name = stripStudentName(self.cleaned_data.get("name", ""))
308
383
 
309
384
  if name == "":
310
- raise forms.ValidationError("'" + self.cleaned_data.get("name", "") + "' is not a valid name")
385
+ raise forms.ValidationError(
386
+ "'"
387
+ + self.cleaned_data.get("name", "")
388
+ + "' is not a valid name"
389
+ )
311
390
 
312
391
  if re.match(re.compile("^[\w -]+$"), name) is None:
313
- raise forms.ValidationError("Names may only contain letters, numbers, dashes, underscores, and spaces.")
392
+ raise forms.ValidationError(
393
+ "Names may only contain letters, numbers, dashes, underscores, and spaces."
394
+ )
314
395
 
315
- students = Student.objects.filter(class_field=self.klass, new_user__first_name__iexact=name)
396
+ students = Student.objects.filter(
397
+ class_field=self.klass, new_user__first_name__iexact=name
398
+ )
316
399
  if students.exists() and students[0] != self.student:
317
- raise forms.ValidationError("There is already a student called '" + name + "' in this class")
400
+ raise forms.ValidationError(
401
+ "There is already a student called '" + name + "' in this class"
402
+ )
318
403
 
319
404
  return name
320
405
 
@@ -323,12 +408,16 @@ class TeacherSetStudentPass(forms.Form):
323
408
  password = forms.CharField(
324
409
  label="New password",
325
410
  help_text="Enter new password",
326
- widget=forms.PasswordInput(attrs={"autocomplete": "off", "placeholder": "Enter new password"}),
411
+ widget=forms.PasswordInput(
412
+ attrs={"autocomplete": "off", "placeholder": "Enter new password"}
413
+ ),
327
414
  )
328
415
  confirm_password = forms.CharField(
329
416
  label="Confirm new password",
330
417
  help_text="Confirm new password",
331
- widget=forms.PasswordInput(attrs={"autocomplete": "off", "placeholder": "Confirm new password"}),
418
+ widget=forms.PasswordInput(
419
+ attrs={"autocomplete": "off", "placeholder": "Confirm new password"}
420
+ ),
332
421
  )
333
422
 
334
423
  def clean_password(self):
@@ -372,19 +461,32 @@ def validateStudentNames(klass, names):
372
461
 
373
462
  def find_clashes(names, students, clashes_found, validationErrors):
374
463
  for name in names:
375
- if students.filter(new_user__first_name__iexact=name).exists() and name not in clashes_found:
464
+ if (
465
+ students.filter(new_user__first_name__iexact=name).exists()
466
+ and name not in clashes_found
467
+ ):
376
468
  validationErrors.append(
377
- forms.ValidationError("There is already a student called '" + name + "' in this class")
469
+ forms.ValidationError(
470
+ "There is already a student called '"
471
+ + name
472
+ + "' in this class"
473
+ )
378
474
  )
379
475
  clashes_found.append(name)
380
476
 
381
477
 
382
478
  def find_duplicates(names, lower_names, validationErrors):
383
479
  duplicates_found = []
384
- for duplicate in [name for name in names if lower_names.count(name.lower()) > 1]:
480
+ for duplicate in [
481
+ name for name in names if lower_names.count(name.lower()) > 1
482
+ ]:
385
483
  if duplicate not in duplicates_found:
386
484
  validationErrors.append(
387
- forms.ValidationError("You cannot add more than one student called '" + duplicate + "'")
485
+ forms.ValidationError(
486
+ "You cannot add more than one student called '"
487
+ + duplicate
488
+ + "'"
489
+ )
388
490
  )
389
491
  duplicates_found.append(duplicate)
390
492
 
@@ -403,7 +505,9 @@ def find_illegal_characters(names, validationErrors):
403
505
 
404
506
  def check_passwords(password, confirm_password):
405
507
  if password is not None and password != confirm_password:
406
- raise forms.ValidationError("The password and the confirmation password do not match")
508
+ raise forms.ValidationError(
509
+ "The password and the confirmation password do not match"
510
+ )
407
511
 
408
512
 
409
513
  class TeacherMoveStudentsDestinationForm(forms.Form):
@@ -428,28 +532,47 @@ class TeacherMoveStudentsDestinationForm(forms.Form):
428
532
  + klass.teacher.new_user.last_name,
429
533
  )
430
534
  )
431
- super(TeacherMoveStudentsDestinationForm, self).__init__(*args, **kwargs)
535
+ super(TeacherMoveStudentsDestinationForm, self).__init__(
536
+ *args, **kwargs
537
+ )
432
538
  self.fields["new_class"].choices = class_choices
433
539
 
434
540
 
435
541
  class TeacherMoveStudentDisambiguationForm(forms.Form):
436
542
  orig_name = forms.CharField(
437
543
  label="Original Name",
438
- widget=forms.TextInput(attrs={"readonly": "readonly", "placeholder": "Original Name", "type": "hidden"}),
544
+ widget=forms.TextInput(
545
+ attrs={
546
+ "readonly": "readonly",
547
+ "placeholder": "Original Name",
548
+ "type": "hidden",
549
+ }
550
+ ),
551
+ )
552
+ name = forms.CharField(
553
+ label="Name",
554
+ widget=forms.TextInput(
555
+ attrs={"placeholder": "Name", "style": "margin : 0px"}
556
+ ),
439
557
  )
440
- name = forms.CharField(label="Name", widget=forms.TextInput(attrs={"placeholder": "Name", "style": "margin : 0px"}))
441
558
 
442
559
  def clean_name(self):
443
560
  name = stripStudentName(self.cleaned_data.get("name", ""))
444
561
  if name == "":
445
- raise forms.ValidationError("'" + self.cleaned_data.get("name", "") + "' is not a valid name")
562
+ raise forms.ValidationError(
563
+ "'"
564
+ + self.cleaned_data.get("name", "")
565
+ + "' is not a valid name"
566
+ )
446
567
  return name
447
568
 
448
569
 
449
570
  class BaseTeacherMoveStudentsDisambiguationFormSet(forms.BaseFormSet):
450
571
  def __init__(self, destination, *args, **kwargs):
451
572
  self.destination = destination
452
- super(BaseTeacherMoveStudentsDisambiguationFormSet, self).__init__(*args, **kwargs)
573
+ super(BaseTeacherMoveStudentsDisambiguationFormSet, self).__init__(
574
+ *args, **kwargs
575
+ )
453
576
 
454
577
  def clean(self):
455
578
  if any(self.errors):
@@ -468,28 +591,44 @@ class BaseTeacherMoveStudentsDisambiguationFormSet(forms.BaseFormSet):
468
591
  class TeacherDismissStudentsForm(forms.Form):
469
592
  orig_name = forms.CharField(
470
593
  help_text="Original student name",
471
- widget=forms.TextInput(attrs={"readonly": "readonly", "placeholder": "Original Name", "class": "m-0"}),
594
+ widget=forms.TextInput(
595
+ attrs={
596
+ "readonly": "readonly",
597
+ "placeholder": "Original Name",
598
+ "class": "m-0",
599
+ }
600
+ ),
472
601
  )
473
602
  name = forms.CharField(
474
603
  help_text="New student name",
475
- widget=forms.TextInput(attrs={"placeholder": "Enter new student name", "class": "m-0"}),
604
+ widget=forms.TextInput(
605
+ attrs={"placeholder": "Enter new student name", "class": "m-0"}
606
+ ),
476
607
  )
477
608
  email = forms.EmailField(
478
609
  label="Email",
479
610
  help_text="New email address",
480
- widget=forms.EmailInput(attrs={"placeholder": "Enter email address", "class": "m-0"}),
611
+ widget=forms.EmailInput(
612
+ attrs={"placeholder": "Enter email address", "class": "m-0"}
613
+ ),
481
614
  )
482
615
  confirm_email = forms.EmailField(
483
616
  label="Confirm Email",
484
617
  help_text="Confirm email address",
485
- widget=forms.EmailInput(attrs={"placeholder": "Confirm email address", "class": "m-0"}),
618
+ widget=forms.EmailInput(
619
+ attrs={"placeholder": "Confirm email address", "class": "m-0"}
620
+ ),
486
621
  )
487
622
 
488
623
  def clean_name(self):
489
624
  name = stripStudentName(self.cleaned_data.get("name", ""))
490
625
 
491
626
  if name == "":
492
- raise forms.ValidationError("'" + self.cleaned_data.get("name", "") + "' is not a valid name")
627
+ raise forms.ValidationError(
628
+ "'"
629
+ + self.cleaned_data.get("name", "")
630
+ + "' is not a valid name"
631
+ )
493
632
 
494
633
  return name
495
634
 
@@ -547,7 +686,10 @@ class StudentCreationForm(forms.Form):
547
686
 
548
687
 
549
688
  class TeacherAddExternalStudentForm(forms.Form):
550
- name = forms.CharField(label="Student name", widget=forms.TextInput(attrs={"placeholder": "Name"}))
689
+ name = forms.CharField(
690
+ label="Student name",
691
+ widget=forms.TextInput(attrs={"placeholder": "Name"}),
692
+ )
551
693
 
552
694
  def __init__(self, klass, *args, **kwargs):
553
695
  self.klass = klass
@@ -557,9 +699,17 @@ class TeacherAddExternalStudentForm(forms.Form):
557
699
  name = stripStudentName(self.cleaned_data.get("name", ""))
558
700
 
559
701
  if name == "":
560
- raise forms.ValidationError("'" + self.cleaned_data.get("name", "") + "' is not a valid name")
702
+ raise forms.ValidationError(
703
+ "'"
704
+ + self.cleaned_data.get("name", "")
705
+ + "' is not a valid name"
706
+ )
561
707
 
562
- if Student.objects.filter(class_field=self.klass, new_user__first_name__iexact=name).exists():
563
- raise forms.ValidationError("There is already a student called '" + name + "' in this class")
708
+ if Student.objects.filter(
709
+ class_field=self.klass, new_user__first_name__iexact=name
710
+ ).exists():
711
+ raise forms.ValidationError(
712
+ "There is already a student called '" + name + "' in this class"
713
+ )
564
714
 
565
715
  return name
@@ -89,7 +89,7 @@
89
89
  </div>
90
90
 
91
91
  <div class="background container">
92
- <h5>Rapid Router access settings</h5>
92
+ <h5>Levels access settings</h5>
93
93
  <p>You may control access to levels here by selecting what you wish to display to the students.</p>
94
94
 
95
95
  <form method="post">
@@ -140,6 +140,62 @@
140
140
  </div>
141
141
  </div>
142
142
  {% endfor %}
143
+ <div class="panel-intro d-flex align-items-center justify-content-between">
144
+ <h6>Python Den levels</h6>
145
+ <label class="pr-5 mb-0 mr-5">
146
+ <input type="checkbox" id="select-all-python-levels">
147
+ </label>
148
+ </div>
149
+ {% for episode in python_episodes %}
150
+ {% if episode.levels %}
151
+ <div class="panel">
152
+ <div class="panel-header bg--{{ episode.difficulty }}" id="episode-{{episode.id}}">
153
+ <div class="d-flex align-items-center justify-content-end" data-toggle="collapse"
154
+ data-target="#collapse-{{episode.id}}" aria-expanded="false"
155
+ aria-controls="collapse-{{episode.id}}" data-parent="#episodes">
156
+ <p class="episode-title flex-grow-1">{{episode.name}}</p>
157
+ {% if episode.first_level > 1009 %}
158
+ <span>Levels {{episode.first_level|stringformat:"i"|slice:"2:4"}}-{{episode.last_level|stringformat:"i"|slice:"2:4"}}</span>
159
+ {% else %}
160
+ {% if episode.last_level > 1009 %}
161
+ <span>Levels {{episode.first_level|stringformat:"i"|slice:"3:4"}}-{{episode.last_level|stringformat:"i"|slice:"2:4"}}</span>
162
+ {% else %}
163
+ <span>Levels {{episode.first_level|stringformat:"i"|slice:"3:4"}}-{{episode.last_level|stringformat:"i"|slice:"3:4"}}</span>
164
+ {% endif %}
165
+ {% endif %}
166
+ <div class="episode_range_text collapsed d-flex align-items-center justify-content-end"
167
+ data-toggle="collapse" data-target="#collapse-{{episode.id}}"
168
+ aria-expanded="false" aria-controls="collapse-{{episode.id}}" data-parent="#episodes">
169
+ <label class="mb-0" for="select-all-episode-levels">
170
+ <input type="checkbox" value="{{ episode.name }}" id="select-all-python-levels-{{ episode.id }}">
171
+ </label>
172
+ </div>
173
+ </div>
174
+ </div>
175
+
176
+ <div id="collapse-{{episode.id}}" aria-labelledby="episode-{{episode.id}}" class="collapse">
177
+ <div class="panel-body d-flex justify-content-between">
178
+ <div class="d-flex flex-grow-1 flex-column justify-content-between">
179
+ {% for level in episode.levels %}
180
+ {% if level.name < 1010 %}
181
+ <p>{{level.name|stringformat:"i"|slice:"3:4"}}: {{level.title.strip | safe}}</p>
182
+ {% else %}
183
+ <p>{{level.name|stringformat:"i"|slice:"2:4"}}: {{level.title.strip | safe}}</p>
184
+ {% endif %}
185
+ {% endfor %}
186
+ </div>
187
+ <div class="form__checkbox flex-column justify-content-between p-0">
188
+ {% for input in level_control_form|get_dict_item:episode.name %}
189
+ <div class="form__checkbox-input p-0">
190
+ {{ input }}
191
+ </div>
192
+ {% endfor %}
193
+ </div>
194
+ </div>
195
+ </div>
196
+ </div>
197
+ {% endif %}
198
+ {% endfor %}
143
199
  </div>
144
200
 
145
201
  <div class="button-group">