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.
- cfl_common/common/__init__.py +1 -0
- cfl_common/common/app_settings.py +66 -0
- cfl_common/common/apps.py +6 -0
- cfl_common/common/context_processors.py +9 -0
- cfl_common/common/csp_config.py +85 -0
- cfl_common/common/helpers/__init__.py +0 -0
- cfl_common/common/helpers/data_migration_loader.py +42 -0
- cfl_common/common/helpers/emails.py +393 -0
- cfl_common/common/helpers/generators.py +52 -0
- cfl_common/common/helpers/organisation.py +10 -0
- cfl_common/common/mail.py +201 -0
- cfl_common/common/migrations/0001_initial.py +240 -0
- cfl_common/common/migrations/0002_emailverification.py +55 -0
- cfl_common/common/migrations/0003_aimmocharacter.py +31 -0
- cfl_common/common/migrations/0004_add_aimmocharacters.py +17 -0
- cfl_common/common/migrations/0005_add_worksheets.py +8 -0
- cfl_common/common/migrations/0006_update_aimmo_character_image_path.py +17 -0
- cfl_common/common/migrations/0007_add_pdf_names_to_first_two_worksheets.py +8 -0
- cfl_common/common/migrations/0008_unlock_worksheet_3.py +11 -0
- cfl_common/common/migrations/0009_add_blocked_time_to_teacher_and_student.py +24 -0
- cfl_common/common/migrations/0010_remove_teacher_title.py +18 -0
- cfl_common/common/migrations/0011_student_login_id.py +18 -0
- cfl_common/common/migrations/0012_usersession.py +39 -0
- cfl_common/common/migrations/0013_class_school.py +42 -0
- cfl_common/common/migrations/0014_login_type.py +29 -0
- cfl_common/common/migrations/0015_dailyactivity.py +31 -0
- cfl_common/common/migrations/0016_joinreleasestudent.py +42 -0
- cfl_common/common/migrations/0017_copy_email_to_username.py +18 -0
- cfl_common/common/migrations/0018_update_aimmo_character_image_path.py +15 -0
- cfl_common/common/migrations/0019_aimmocharacter_alt.py +16 -0
- cfl_common/common/migrations/0020_class_is_active_and_null_access_code.py +23 -0
- cfl_common/common/migrations/0021_school_is_active.py +28 -0
- cfl_common/common/migrations/0022_school_cleanup.py +29 -0
- cfl_common/common/migrations/0023_userprofile_aimmo_badges.py +22 -0
- cfl_common/common/migrations/0024_teacher_invited_by.py +25 -0
- cfl_common/common/migrations/0025_schoolteacherinvitation.py +47 -0
- cfl_common/common/migrations/0026_teacher_remove_join_request.py +22 -0
- cfl_common/common/migrations/0027_class_created_by.py +25 -0
- cfl_common/common/migrations/0028_coding_club_downloads.py +23 -0
- cfl_common/common/migrations/0029_dynamicelement.py +22 -0
- cfl_common/common/migrations/0030_add_maintenance_banner.py +25 -0
- cfl_common/common/migrations/0031_improve_admin_panel.py +56 -0
- cfl_common/common/migrations/0032_dailyactivity_level_control_submits.py +18 -0
- cfl_common/common/migrations/0033_password_reset_tracking_fields.py +23 -0
- cfl_common/common/migrations/0034_dailyactivity_daily_school_student_lockout_reset.py +18 -0
- cfl_common/common/migrations/0035_rename_lockout_fields.py +27 -0
- cfl_common/common/migrations/0036_rename_awaiting_email_verification_userprofile_is_verified.py +17 -0
- cfl_common/common/migrations/0037_migrate_email_verification.py +21 -0
- cfl_common/common/migrations/0038_delete_emailverification.py +16 -0
- cfl_common/common/migrations/0039_copy_email_to_username.py +18 -0
- cfl_common/common/migrations/0040_school_county.py +18 -0
- cfl_common/common/migrations/0041_populate_gb_counties.py +27 -0
- cfl_common/common/migrations/0042_totalactivity.py +25 -0
- cfl_common/common/migrations/0043_add_total_activity.py +30 -0
- cfl_common/common/migrations/0044_update_activity_models.py +33 -0
- cfl_common/common/migrations/0045_otp.py +23 -0
- cfl_common/common/migrations/0046_alter_school_country.py +19 -0
- cfl_common/common/migrations/0047_delete_school_postcode.py +16 -0
- cfl_common/common/migrations/0048_unique_school_names.py +42 -0
- cfl_common/common/migrations/0049_anonymise_orphan_users.py +29 -0
- cfl_common/common/migrations/0050_anonymise_orphan_schools.py +30 -0
- cfl_common/common/migrations/0051_verify_returning_users.py +26 -0
- cfl_common/common/migrations/0052_add_cse_fields.py +68 -0
- cfl_common/common/migrations/0053_clean_class_data.py +24 -0
- cfl_common/common/migrations/0054_delete_aimmo_models.py +20 -0
- cfl_common/common/migrations/0055_alter_schoolteacherinvitation_token.py +18 -0
- cfl_common/common/migrations/0056_set_non_school_teachers_as_non_admins.py +25 -0
- cfl_common/common/migrations/0057_teacher_teacher__is_admin.py +19 -0
- cfl_common/common/migrations/0058_userprofile_google_refresh_token_and_more.py +24 -0
- cfl_common/common/migrations/__init__.py +0 -0
- cfl_common/common/models.py +557 -0
- cfl_common/common/permissions.py +84 -0
- cfl_common/common/tests/__init__.py +0 -0
- cfl_common/common/tests/test_migration_anonymise_orphan_schools.py +30 -0
- cfl_common/common/tests/test_migration_anonymise_orphan_users.py +30 -0
- cfl_common/common/tests/test_migration_blocked_time.py +15 -0
- cfl_common/common/tests/test_migration_remove_teacher_title.py +13 -0
- cfl_common/common/tests/test_migration_unique_school_names.py +33 -0
- cfl_common/common/tests/test_migration_verify_returning_users.py +59 -0
- cfl_common/common/tests/test_models.py +87 -0
- cfl_common/common/tests/utils/__init__.py +0 -0
- cfl_common/common/tests/utils/classes.py +38 -0
- cfl_common/common/tests/utils/email.py +67 -0
- cfl_common/common/tests/utils/organisation.py +41 -0
- cfl_common/common/tests/utils/student.py +123 -0
- cfl_common/common/tests/utils/teacher.py +73 -0
- cfl_common/common/tests/utils/user.py +27 -0
- cfl_common/common/utils.py +56 -0
- cfl_common/setup.py +61 -0
- codeforlife_portal-8.9.9.dist-info/METADATA +226 -0
- {codeforlife_portal-5.32.2.dist-info → codeforlife_portal-8.9.9.dist-info}/RECORD +341 -238
- {codeforlife_portal-5.32.2.dist-info → codeforlife_portal-8.9.9.dist-info}/WHEEL +1 -1
- codeforlife_portal-8.9.9.dist-info/licenses/LICENSE.md +3 -0
- {codeforlife_portal-5.32.2.dist-info → codeforlife_portal-8.9.9.dist-info}/top_level.txt +1 -0
- deploy/middleware/maintenance.py +25 -0
- deploy/middleware/screentime_warning.py +29 -0
- deploy/middleware/security.py +5 -6
- deploy/middleware/session_timeout.py +31 -0
- deploy/middleware/tmp_basic_auth.py +41 -0
- example_project/portal_test_settings.py +239 -0
- example_project/settings.py +156 -17
- example_project/urls.py +5 -6
- portal/__init__.py +1 -1
- portal/admin.py +142 -29
- portal/app_settings.py +10 -7
- portal/forms/dotmailer.py +6 -4
- portal/forms/invite_teacher.py +19 -10
- portal/forms/organisation.py +137 -68
- portal/forms/play.py +53 -98
- portal/forms/registration.py +70 -164
- portal/forms/teach.py +147 -121
- portal/handlers.py +1 -2
- portal/helpers/decorators.py +30 -10
- portal/helpers/password.py +86 -47
- portal/helpers/ratelimit.py +32 -15
- portal/helpers/regexes.py +5 -0
- portal/helpers/request_handlers.py +10 -0
- portal/migrations/0044_auto_20150430_0959.py +6 -2
- portal/mixins/__init__.py +1 -0
- portal/mixins/cron_mixin.py +12 -0
- portal/permissions/__init__.py +1 -0
- portal/permissions/is_cron_request_from_google.py +14 -0
- portal/static/portal/img/10_years_anniversary.png +0 -0
- portal/static/portal/img/RR_logo_grass_background.png +0 -0
- portal/static/portal/img/coding_club_hero.jpg +0 -0
- portal/static/portal/img/coding_club_python_pack.png +0 -0
- portal/static/portal/img/facebook.png +0 -0
- portal/static/portal/img/gitbook.png +0 -0
- portal/static/portal/img/howe_dell_1.png +0 -0
- portal/static/portal/img/howe_dell_2.png +0 -0
- portal/static/portal/img/howe_dell_3.png +0 -0
- portal/static/portal/img/logo_cfl.png +0 -0
- portal/static/portal/img/logo_cfl_powered.svg +35 -0
- portal/static/portal/img/logo_cfl_reminder_cards.jpg +0 -0
- portal/static/portal/img/logo_ocado_group.png +0 -0
- portal/static/portal/img/logo_python_den.svg +21 -0
- portal/static/portal/img/long_europe_map.png +0 -0
- portal/static/portal/img/python_den.png +0 -0
- portal/static/portal/img/python_den_banner.svg +26 -0
- portal/static/portal/img/rapid_router_landing_hero.png +0 -0
- portal/static/portal/img/rr_advanced.png +0 -0
- portal/static/portal/img/ten_year_map_pin.svg +1 -0
- portal/static/portal/img/thumbnail_educate_rapid_router.png +0 -0
- portal/static/portal/img/thumbnail_educate_resources.png +0 -0
- portal/static/portal/img/thumbnail_play_rapid_router.png +0 -0
- portal/static/portal/img/thumbnail_python_den.png +0 -0
- portal/static/portal/img/twitter.png +0 -0
- portal/static/portal/js/carouselCards.js +25 -0
- portal/static/portal/js/common.js +96 -1
- portal/static/portal/js/independentLogin.js +16 -0
- portal/static/portal/js/independentRegistration.js +86 -0
- portal/static/portal/js/levelControl.js +77 -0
- portal/static/portal/js/lib/jquery.min.js +2 -0
- portal/static/portal/js/organisation_manage.js +142 -14
- portal/static/portal/js/passwordStrength.js +154 -64
- portal/static/portal/js/resetPassword.js +23 -0
- portal/static/portal/js/riveted.min.js +238 -239
- portal/static/portal/js/school.js +13 -0
- portal/static/portal/js/studentLogin.js +16 -0
- portal/static/portal/js/teacherEditStudent.js +23 -0
- portal/static/portal/js/teacherLogin.js +16 -0
- portal/static/portal/js/tenYearMap.js +14 -0
- portal/static/portal/sass/colorbox.scss +0 -1
- portal/static/portal/sass/modules/_colours.scss +1 -0
- portal/static/portal/sass/modules/_levels.scss +1 -1
- portal/static/portal/sass/modules/_mixins.scss +21 -0
- portal/static/portal/sass/partials/_banners.scss +4 -177
- portal/static/portal/sass/partials/_buttons.scss +12 -15
- portal/static/portal/sass/partials/_carousel.scss +129 -0
- portal/static/portal/sass/partials/_footer.scss +21 -22
- portal/static/portal/sass/partials/_forms.scss +60 -5
- portal/static/portal/sass/partials/_grids.scss +34 -61
- portal/static/portal/sass/partials/_header.scss +28 -20
- portal/static/portal/sass/partials/_images.scss +292 -39
- portal/static/portal/sass/partials/_popup.scss +18 -15
- portal/static/portal/sass/partials/_tables.scss +12 -20
- portal/static/portal/sass/partials/_text.scss +6 -10
- portal/static/portal/sass/styles.scss +0 -1
- portal/static/portal/video/code for life .pdf +0 -0
- portal/strings/about.py +5 -0
- portal/strings/coding_club.py +9 -0
- portal/strings/play.py +6 -5
- portal/strings/teach.py +1 -1
- portal/strings/teacher_resources.py +2 -8
- portal/strings/ten_year_map.py +13 -0
- portal/templates/403.html +2 -2
- portal/templates/404.html +1 -1
- portal/templates/500.html +2 -2
- portal/templates/{captcha → django_recaptcha}/includes/js_v2_invisible.html +3 -3
- portal/templates/{captcha → django_recaptcha}/widget_v2_invisible.html +2 -2
- portal/templates/email.html +4 -2
- portal/templates/maintenance.html +34 -0
- portal/templates/portal/about.html +94 -62
- portal/templates/portal/base.html +176 -152
- portal/templates/portal/coding_club.html +100 -0
- portal/templates/portal/contribute.html +56 -52
- portal/templates/portal/email_invitation_sent.html +1 -1
- portal/templates/portal/email_style_template.html +374 -0
- portal/templates/portal/email_verification_failed.html +1 -1
- portal/templates/portal/email_verification_needed.html +9 -9
- portal/templates/portal/form_shapes.html +20 -8
- portal/templates/portal/getinvolved.html +6 -6
- portal/templates/portal/home.html +35 -10
- portal/templates/portal/home_learning.html +19 -19
- portal/templates/portal/locked_out.html +0 -1
- portal/templates/portal/locked_out_school_student.html +16 -0
- portal/templates/portal/login/independent_student.html +31 -15
- portal/templates/portal/login/student.html +10 -7
- portal/templates/portal/login/student_class_code.html +7 -4
- portal/templates/portal/login/teacher.html +34 -17
- portal/templates/portal/partials/banner.html +18 -4
- portal/templates/portal/partials/benefits.html +1 -1
- portal/templates/portal/partials/card_list.html +34 -24
- portal/templates/portal/partials/character_list.html +5 -5
- portal/templates/portal/partials/cookie_list.html +161 -0
- portal/templates/portal/partials/delete_popup.html +18 -0
- portal/templates/portal/partials/footer.html +57 -26
- portal/templates/portal/partials/header.html +118 -117
- portal/templates/portal/partials/hero_card.html +4 -3
- portal/templates/portal/partials/info_popup.html +3 -3
- portal/templates/portal/partials/invite_admin_teacher.html +23 -0
- portal/templates/portal/partials/popup.html +7 -2
- portal/templates/portal/partials/register_newsletter_tickbox.html +2 -5
- portal/templates/portal/partials/screentime_popup.html +14 -0
- portal/templates/portal/partials/service_unavailable_popup.html +17 -0
- portal/templates/portal/partials/session_popup.html +19 -0
- portal/templates/portal/play/student_dashboard.html +42 -29
- portal/templates/portal/play/student_edit_account.html +64 -9
- portal/templates/portal/play.html +61 -41
- portal/templates/portal/privacy_notice.html +697 -0
- portal/templates/portal/register.html +122 -92
- portal/templates/portal/reset_password.html +20 -40
- portal/templates/portal/reset_password_confirm.html +9 -4
- portal/templates/portal/reset_password_email_sent.html +15 -13
- portal/templates/portal/teach/base_registering.html +1 -1
- portal/templates/portal/teach/class.html +4 -6
- portal/templates/portal/teach/dashboard.html +212 -117
- portal/templates/portal/teach/invited.html +90 -0
- portal/templates/portal/teach/onboarding_classes.html +5 -3
- portal/templates/portal/teach/onboarding_print.html +1 -1
- portal/templates/portal/teach/onboarding_school.html +26 -139
- portal/templates/portal/teach/onboarding_students.html +1 -1
- portal/templates/portal/teach/teacher_dismiss_students.html +73 -55
- portal/templates/portal/teach/teacher_edit_class.html +168 -11
- portal/templates/portal/teach/teacher_edit_student.html +12 -5
- portal/templates/portal/teach/teacher_move_all_classes.html +25 -38
- portal/templates/portal/teach/teacher_move_students_to_class.html +1 -1
- portal/templates/portal/teach.html +61 -42
- portal/templates/portal/ten_year_map.html +147 -0
- portal/templates/portal/terms.html +191 -42
- portal/templates/two_factor/core/login.html +71 -59
- portal/templates/two_factor/core/setup.html +58 -49
- portal/templates/two_factor/profile/disable.html +1 -1
- portal/templates/two_factor/profile/profile.html +35 -17
- portal/templatetags/app_tags.py +59 -84
- portal/templatetags/card_list_tags.py +0 -4
- portal/tests/base_test.py +14 -3
- portal/tests/conftest.py +0 -15
- portal/tests/migrations/test_migration_make_portaladmin_teacher.py +2 -6
- portal/tests/migrations/test_migration_preview_users.py +3 -9
- portal/tests/migrations/test_migration_remove_guardian.py +1 -3
- portal/tests/migrations/test_migration_use_common_models.py +2 -6
- portal/tests/migrations/test_migration_verify_portaladmin.py +1 -3
- portal/tests/pageObjects/portal/admin/admin_base_page.py +0 -21
- portal/tests/pageObjects/portal/base_page.py +16 -26
- portal/tests/pageObjects/portal/email_verification_needed_page.py +3 -2
- portal/tests/pageObjects/portal/game_page.py +12 -19
- portal/tests/pageObjects/portal/home_page.py +13 -15
- portal/tests/pageObjects/portal/independent_login_page.py +13 -17
- portal/tests/pageObjects/portal/password_reset_form_page.py +20 -4
- portal/tests/pageObjects/portal/password_reset_page.py +25 -0
- portal/tests/pageObjects/portal/play/account_page.py +18 -27
- portal/tests/pageObjects/portal/play/dashboard_page.py +4 -4
- portal/tests/pageObjects/portal/play/join_school_or_club_page.py +8 -10
- portal/tests/pageObjects/portal/play/play_base_page.py +5 -3
- portal/tests/pageObjects/portal/signup_page.py +28 -59
- portal/tests/pageObjects/portal/student_login_class_code.py +6 -9
- portal/tests/pageObjects/portal/student_login_page.py +6 -8
- portal/tests/pageObjects/portal/teach/add_independent_student_to_class_page.py +3 -3
- portal/tests/pageObjects/portal/teach/added_independent_student_to_class_page.py +3 -1
- portal/tests/pageObjects/portal/teach/class_page.py +36 -13
- portal/tests/pageObjects/portal/teach/dashboard_page.py +43 -84
- portal/tests/pageObjects/portal/teach/dismiss_students_page.py +7 -5
- portal/tests/pageObjects/portal/teach/edit_student_page.py +10 -8
- portal/tests/pageObjects/portal/teach/move_class_page.py +5 -10
- portal/tests/pageObjects/portal/teach/move_classes_page.py +4 -2
- portal/tests/pageObjects/portal/teach/move_students_disambiguate_page.py +4 -2
- portal/tests/pageObjects/portal/teach/move_students_page.py +6 -13
- portal/tests/pageObjects/portal/teach/onboarding_classes_page.py +5 -3
- portal/tests/pageObjects/portal/teach/onboarding_organisation_page.py +11 -49
- portal/tests/pageObjects/portal/teach/onboarding_student_list_page.py +7 -12
- portal/tests/pageObjects/portal/teach/onboarding_students_page.py +4 -27
- portal/tests/pageObjects/portal/teach/teach_base_page.py +6 -4
- portal/tests/pageObjects/portal/teacher_login_page.py +10 -16
- portal/tests/selenium_test_case.py +3 -43
- portal/tests/snapshots/snap_test_partials.py +11 -165
- portal/tests/test_2FA.py +15 -33
- portal/tests/test_admin.py +15 -97
- portal/tests/test_api.py +212 -73
- portal/tests/test_captcha_forms.py +2 -2
- portal/tests/test_class.py +374 -24
- portal/tests/test_emails.py +83 -20
- portal/tests/{test_newsletter_footer.py → test_global_forms.py} +5 -5
- portal/tests/test_helper_methods.py +30 -0
- portal/tests/test_independent_student.py +255 -144
- portal/tests/test_invite_teacher.py +318 -10
- portal/tests/test_middleware.py +138 -15
- portal/tests/test_organisation.py +78 -262
- portal/tests/test_partials.py +0 -88
- portal/tests/test_ratelimit.py +218 -36
- portal/tests/test_school_student.py +35 -40
- portal/tests/test_security.py +12 -31
- portal/tests/test_teacher.py +425 -325
- portal/tests/test_teacher_student.py +103 -91
- portal/tests/test_views.py +900 -76
- portal/tests/utils/classes.py +2 -2
- portal/tests/utils/messages.py +13 -28
- portal/urls.py +237 -164
- portal/views/admin.py +0 -332
- portal/views/api.py +82 -68
- portal/views/cron/__init__.py +1 -0
- portal/views/cron/user.py +322 -0
- portal/views/dotmailer.py +9 -1
- portal/views/email.py +33 -77
- portal/views/google_analytics.py +28 -0
- portal/views/home.py +126 -97
- portal/views/legal.py +13 -0
- portal/views/login/independent_student.py +5 -5
- portal/views/login/student.py +51 -14
- portal/views/login/teacher.py +2 -6
- portal/views/organisation.py +20 -189
- portal/views/registration.py +97 -17
- portal/views/student/edit_account_details.py +99 -72
- portal/views/student/play.py +81 -62
- portal/views/teacher/dashboard.py +421 -149
- portal/views/teacher/teach.py +226 -177
- portal/views/two_factor/__init__.py +0 -0
- portal/views/two_factor/core.py +28 -0
- portal/views/two_factor/form.py +7 -0
- portal/views/two_factor/profile.py +11 -0
- codeforlife_portal-5.32.2.dist-info/LICENSE.md +0 -577
- codeforlife_portal-5.32.2.dist-info/METADATA +0 -38
- deploy/permissions.py +0 -2
- example_project/manage.py +0 -10
- portal/autoconfig.py +0 -140
- portal/csp_config.py +0 -60
- portal/forms/add_game.py +0 -33
- portal/helpers/location.py +0 -121
- portal/static/portal/img/kurono_hero.jpg +0 -0
- portal/static/portal/img/kurono_landing_hero.png +0 -0
- portal/static/portal/img/kurono_logo.svg +0 -1
- portal/static/portal/img/kurono_logo_grey_background.svg +0 -1
- portal/static/portal/img/kurono_logo_mark.svg +0 -1
- portal/static/portal/img/kurono_resources_hero.jpg +0 -0
- portal/static/portal/img/kurono_story.png +0 -0
- portal/static/portal/img/ocado-swirl.svg +0 -22
- portal/static/portal/img/thumbnail_educate_kurono.png +0 -0
- portal/static/portal/img/thumbnail_educate_resources_and_progress_tracking.png +0 -0
- portal/static/portal/img/thumbnail_kurono_resources.png +0 -0
- portal/static/portal/img/thumbnail_play_kurono.png +0 -0
- portal/static/portal/img/x_close_video.png +0 -0
- portal/static/portal/js/aimmoGame.js +0 -106
- portal/static/portal/js/deleteWorkspaces.js +0 -14
- portal/static/portal/js/fuzzySchoolLookup.js +0 -46
- portal/static/portal/js/lib/jquery-3.5.1.min.js +0 -2
- portal/static/portal/js/lib/jquery-ui-1.12.1.min.js +0 -13
- portal/static/portal/sass/partials/_videos.scss +0 -10
- portal/static/portal/video/aimmo_play_now_background_video.mp4 +0 -0
- portal/strings/student_aimmo_dashboard.py +0 -6
- portal/templates/portal/admin/aggregated_data.html +0 -35
- portal/templates/portal/admin/map.html +0 -70
- portal/templates/portal/mouseflow.html +0 -9
- portal/templates/portal/partials/aimmo_games_table.html +0 -83
- portal/templates/portal/partials/register_over_required_age_tickbox.html +0 -9
- portal/templates/portal/play/independent_student_dashboard.html +0 -64
- portal/templates/portal/play/student_aimmo_dashboard.html +0 -63
- portal/templates/portal/privacy_policy.html +0 -483
- portal/templates/portal/reset_password_email.html +0 -9
- portal/templates/portal/teach/invite.html +0 -25
- portal/templates/portal/teach/teacher_aimmo_dashboard.html +0 -95
- portal/templates/portal/teach/teacher_resources.html +0 -68
- portal/templatetags/character_list_tags.py +0 -16
- portal/tests/pageObjects/portal/kurono_teacher_dashboard_page.py +0 -49
- portal/tests/pageObjects/portal/student_password_reset_form_page.py +0 -23
- portal/tests/pageObjects/portal/teach/onboarding_revoke_request_page.py +0 -20
- portal/tests/pageObjects/portal/teacher_password_reset_form_page.py +0 -23
- portal/tests/test_aimmo_dashboards.py +0 -172
- portal/tests/test_location.py +0 -217
- portal/tests/utils/aimmo_games.py +0 -30
- portal/views/aimmo/dashboard.py +0 -119
- portal/views/privacy_policy.py +0 -9
- portal/views/teacher/teacher_resources.py +0 -42
- {portal/views/aimmo → cfl_common}/__init__.py +0 -0
portal/views/student/play.py
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
from typing import Any, Dict,
|
|
1
|
+
from typing import Any, Dict, List, Optional
|
|
2
2
|
|
|
3
|
-
from
|
|
4
|
-
from common import email_messages
|
|
5
|
-
from common.helpers.emails import NOTIFICATION_EMAIL, send_email
|
|
3
|
+
from common.mail import campaign_ids, send_dotdigital_email
|
|
6
4
|
from common.models import Student
|
|
7
5
|
from common.permissions import (
|
|
8
6
|
logged_in_as_independent_student,
|
|
@@ -12,13 +10,13 @@ from common.utils import LoginRequiredNoErrorMixin
|
|
|
12
10
|
from django.contrib import messages
|
|
13
11
|
from django.contrib.auth.decorators import login_required, user_passes_test
|
|
14
12
|
from django.contrib.auth.mixins import UserPassesTestMixin
|
|
15
|
-
from django.core.exceptions import ObjectDoesNotExist
|
|
16
13
|
from django.db.models.query import QuerySet
|
|
17
14
|
from django.http import HttpResponseRedirect
|
|
18
15
|
from django.shortcuts import render
|
|
19
16
|
from django.urls import reverse_lazy
|
|
20
17
|
from django.views.generic.base import TemplateView
|
|
21
|
-
from
|
|
18
|
+
from django.views.generic.edit import FormView
|
|
19
|
+
from game.models import Attempt, Level
|
|
22
20
|
|
|
23
21
|
from portal.forms.play import StudentJoinOrganisationForm
|
|
24
22
|
|
|
@@ -34,58 +32,65 @@ class SchoolStudentDashboard(
|
|
|
34
32
|
|
|
35
33
|
def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
|
|
36
34
|
"""
|
|
37
|
-
Gathers the context data required by the template. First, the student's
|
|
38
|
-
for the original Rapid Router levels is gathered, second,
|
|
39
|
-
for any levels shared with them by their teacher
|
|
40
|
-
Kurono game information if they have one.
|
|
35
|
+
Gathers the context data required by the template. First, the student's
|
|
36
|
+
scores for the original Rapid Router levels is gathered, second,
|
|
37
|
+
the student's scores for any levels shared with them by their teacher.
|
|
41
38
|
"""
|
|
42
39
|
# Get score data for all original levels
|
|
43
|
-
|
|
40
|
+
rapid_router_levels = Level.objects.filter(episode__pk__in=range(1, 10))
|
|
41
|
+
python_den_levels = Level.objects.filter(
|
|
42
|
+
episode__pk__in=[12, 13, 14, 15, 22]
|
|
43
|
+
)
|
|
44
44
|
student = self.request.user.new_student
|
|
45
45
|
|
|
46
|
-
context_data =
|
|
46
|
+
context_data = {
|
|
47
|
+
"rapid_router": _compute_scores(student, rapid_router_levels),
|
|
48
|
+
"python_den": _compute_scores(student, python_den_levels),
|
|
49
|
+
}
|
|
47
50
|
|
|
48
|
-
# Find any custom levels created by the teacher and shared with the
|
|
51
|
+
# Find any custom levels created by the teacher and shared with the
|
|
52
|
+
# student
|
|
49
53
|
klass = student.class_field
|
|
50
54
|
teacher = klass.teacher.user
|
|
51
55
|
custom_levels = student.new_user.shared.filter(owner=teacher)
|
|
52
56
|
|
|
53
57
|
if custom_levels:
|
|
54
|
-
custom_levels_data =
|
|
55
|
-
|
|
56
|
-
context_data["total_custom_score"] = custom_levels_data["total_score"]
|
|
57
|
-
context_data["total_custom_available_score"] = custom_levels_data[
|
|
58
|
-
"total_available_score"
|
|
59
|
-
]
|
|
58
|
+
custom_levels_data = _compute_scores(student, custom_levels)
|
|
60
59
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
active_worksheet = aimmo_game.worksheet
|
|
60
|
+
context_data["rapid_router"]["total_custom_score"] = (
|
|
61
|
+
custom_levels_data
|
|
62
|
+
)["total_score"]
|
|
65
63
|
|
|
66
|
-
context_data["
|
|
67
|
-
|
|
64
|
+
context_data["rapid_router"][
|
|
65
|
+
"total_custom_available_score"
|
|
66
|
+
] = custom_levels_data["total_available_score"]
|
|
68
67
|
|
|
69
68
|
return context_data
|
|
70
69
|
|
|
71
70
|
|
|
72
71
|
class IndependentStudentDashboard(
|
|
73
|
-
LoginRequiredNoErrorMixin, UserPassesTestMixin, TemplateView
|
|
72
|
+
LoginRequiredNoErrorMixin, UserPassesTestMixin, TemplateView, FormView
|
|
74
73
|
):
|
|
75
|
-
template_name = "portal/play/
|
|
74
|
+
template_name = "portal/play/student_dashboard.html"
|
|
76
75
|
login_url = reverse_lazy("independent_student_login")
|
|
77
76
|
|
|
78
77
|
def test_func(self) -> Optional[bool]:
|
|
79
78
|
return logged_in_as_independent_student(self.request.user)
|
|
80
79
|
|
|
81
80
|
def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
|
|
82
|
-
|
|
81
|
+
rapid_router_levels = Level.objects.filter(episode__pk__in=range(1, 10))
|
|
82
|
+
python_den_levels = Level.objects.filter(
|
|
83
|
+
episode__pk__in=[12, 13, 14, 15, 22]
|
|
84
|
+
)
|
|
83
85
|
student = self.request.user.new_student
|
|
84
86
|
|
|
85
|
-
return
|
|
87
|
+
return {
|
|
88
|
+
"rapid_router": _compute_scores(student, rapid_router_levels),
|
|
89
|
+
"python_den": _compute_scores(student, python_den_levels),
|
|
90
|
+
}
|
|
86
91
|
|
|
87
92
|
|
|
88
|
-
def
|
|
93
|
+
def _compute_scores(
|
|
89
94
|
student: Student, levels: List[Level] or QuerySet
|
|
90
95
|
) -> Dict[str, int]:
|
|
91
96
|
"""
|
|
@@ -98,7 +103,8 @@ def _compute_rapid_router_scores(
|
|
|
98
103
|
- num_completed: number of completed levels. A completed level is a level that has a
|
|
99
104
|
successful attempt (van made it to the final house) regardless of the final score.
|
|
100
105
|
- num_top_scores: number of levels that have been completed with a full final score
|
|
101
|
-
of either 10/10 or 20/20 (depending on whether the level has route score
|
|
106
|
+
of either 10/10 or 20/20 (depending on whether the level has route score
|
|
107
|
+
or algo score enabled)
|
|
102
108
|
- total_score: the addition of all the completed levels' final scores
|
|
103
109
|
- total_available_score: the addition of the maximum attainable score of all levels
|
|
104
110
|
"""
|
|
@@ -109,25 +115,22 @@ def _compute_rapid_router_scores(
|
|
|
109
115
|
level__in=levels, student=student, is_best_attempt=True
|
|
110
116
|
).select_related("level")
|
|
111
117
|
|
|
112
|
-
# Calculate total available score. A level has a max score of 20 by default unless
|
|
113
|
-
# its route score is disabled or it is a custom level (not in an episode)
|
|
114
118
|
for level in levels:
|
|
115
|
-
|
|
116
|
-
total_available_score += max_score
|
|
119
|
+
total_available_score += _get_max_score_for_level(level)
|
|
117
120
|
|
|
118
|
-
# For each level, compare best attempt's score with level's max score and
|
|
119
|
-
# variables as needed
|
|
121
|
+
# For each level, compare best attempt's score with level's max score and
|
|
122
|
+
# increment variables as needed
|
|
120
123
|
if best_attempts:
|
|
121
124
|
attempts_dict = {
|
|
122
|
-
best_attempt.level.id: best_attempt
|
|
125
|
+
best_attempt.level.id: best_attempt
|
|
126
|
+
for best_attempt in best_attempts
|
|
123
127
|
}
|
|
124
128
|
for level in levels:
|
|
125
|
-
max_score = 10 if level.disable_route_score or not level.episode else 20
|
|
126
129
|
attempt = attempts_dict.get(level.id)
|
|
127
130
|
|
|
128
131
|
if attempt and attempt.score:
|
|
129
132
|
num_completed += 1
|
|
130
|
-
if attempt.score ==
|
|
133
|
+
if attempt.score == _get_max_score_for_level(level):
|
|
131
134
|
num_top_scores += 1
|
|
132
135
|
|
|
133
136
|
total_score += attempt.score
|
|
@@ -140,6 +143,27 @@ def _compute_rapid_router_scores(
|
|
|
140
143
|
}
|
|
141
144
|
|
|
142
145
|
|
|
146
|
+
def _get_max_score_for_level(level: Level) -> int:
|
|
147
|
+
"""
|
|
148
|
+
Calculate max score. A level has a max score of 20 by default unless its
|
|
149
|
+
route score or algorithm score is disable or it is a custom level (not in an
|
|
150
|
+
episode). Levels 1-12 have a max score of 20 even if the algo score is
|
|
151
|
+
disabled.
|
|
152
|
+
:param level: The Rapid Router level to get the max score for.
|
|
153
|
+
:return: the max score of the level.
|
|
154
|
+
"""
|
|
155
|
+
return (
|
|
156
|
+
10
|
|
157
|
+
if level.id > 12
|
|
158
|
+
and (
|
|
159
|
+
level.disable_route_score
|
|
160
|
+
or level.disable_algorithm_score
|
|
161
|
+
or not level.episode
|
|
162
|
+
)
|
|
163
|
+
else 20
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
|
|
143
167
|
def username_labeller(request):
|
|
144
168
|
return request.user.username
|
|
145
169
|
|
|
@@ -150,7 +174,6 @@ def username_labeller(request):
|
|
|
150
174
|
login_url=reverse_lazy("independent_student_login"),
|
|
151
175
|
)
|
|
152
176
|
def student_join_organisation(request):
|
|
153
|
-
|
|
154
177
|
student = request.user.new_student
|
|
155
178
|
request_form = StudentJoinOrganisationForm()
|
|
156
179
|
|
|
@@ -183,38 +206,34 @@ def process_join_organisation_form(request_form, request, student):
|
|
|
183
206
|
student.pending_class_request = request_form.klass
|
|
184
207
|
student.save()
|
|
185
208
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
request_form.klass.teacher.school.name,
|
|
189
|
-
request_form.klass.access_code,
|
|
190
|
-
)
|
|
191
|
-
send_email(
|
|
192
|
-
NOTIFICATION_EMAIL,
|
|
209
|
+
send_dotdigital_email(
|
|
210
|
+
campaign_ids["student_join_request_sent"],
|
|
193
211
|
[student.new_user.email],
|
|
194
|
-
|
|
195
|
-
|
|
212
|
+
personalization_values={
|
|
213
|
+
"SCHOOL_CLUB_NAME": request_form.klass.teacher.school.name,
|
|
214
|
+
"ACCESS_CODE": request_form.klass.access_code,
|
|
215
|
+
},
|
|
196
216
|
)
|
|
197
217
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
student.new_user.username,
|
|
201
|
-
student.new_user.email,
|
|
202
|
-
student.pending_class_request.access_code,
|
|
203
|
-
)
|
|
204
|
-
send_email(
|
|
205
|
-
NOTIFICATION_EMAIL,
|
|
218
|
+
send_dotdigital_email(
|
|
219
|
+
campaign_ids["student_join_request_notification"],
|
|
206
220
|
[student.pending_class_request.teacher.new_user.email],
|
|
207
|
-
|
|
208
|
-
|
|
221
|
+
personalization_values={
|
|
222
|
+
"USERNAME": student.new_user.username,
|
|
223
|
+
"EMAIL": student.new_user.email,
|
|
224
|
+
"ACCESS_CODE": student.pending_class_request.access_code,
|
|
225
|
+
},
|
|
209
226
|
)
|
|
210
227
|
|
|
211
228
|
messages.success(
|
|
212
|
-
request,
|
|
229
|
+
request,
|
|
230
|
+
"Your request to join a school has been received successfully.",
|
|
213
231
|
)
|
|
214
232
|
|
|
215
233
|
|
|
216
234
|
def show_cancellation_message_if_student_not_in_class(student, request):
|
|
217
235
|
if not student.class_field:
|
|
218
236
|
messages.success(
|
|
219
|
-
request,
|
|
237
|
+
request,
|
|
238
|
+
"Your request to join a school has been cancelled successfully.",
|
|
220
239
|
)
|