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/helpers/password.py
CHANGED
|
@@ -1,8 +1,36 @@
|
|
|
1
|
+
import hashlib
|
|
1
2
|
import re
|
|
2
3
|
from enum import Enum, auto
|
|
3
4
|
|
|
5
|
+
import requests
|
|
4
6
|
from django import forms
|
|
5
7
|
from django.contrib.auth import update_session_auth_hash
|
|
8
|
+
from django.contrib.auth.hashers import PBKDF2PasswordHasher as ph
|
|
9
|
+
from django.core.exceptions import ValidationError
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def is_password_pwned(password):
|
|
13
|
+
# Create SHA1 hash of the password
|
|
14
|
+
sha1_hash = hashlib.sha1(password.encode()).hexdigest()
|
|
15
|
+
prefix = sha1_hash[:5] # Take the first 5 characters of the hash as the prefix
|
|
16
|
+
|
|
17
|
+
# Make a request to the Pwned Passwords API
|
|
18
|
+
url = f"https://api.pwnedpasswords.com/range/{prefix}"
|
|
19
|
+
response = requests.get(url)
|
|
20
|
+
|
|
21
|
+
if response.status_code != 200:
|
|
22
|
+
return False # backend ignore this and frontend tells the user
|
|
23
|
+
# that we cannot verify this at the moment
|
|
24
|
+
|
|
25
|
+
# Check if the password's hash is found in the response body
|
|
26
|
+
hash_suffixes = response.text.split("\r\n")
|
|
27
|
+
for suffix in hash_suffixes:
|
|
28
|
+
# Compare the suffix from the hash to the api response
|
|
29
|
+
# api response is using the format of suffix:count hence
|
|
30
|
+
# we need to get rid of the ending count number
|
|
31
|
+
if sha1_hash[5:].upper() == suffix[:35].upper():
|
|
32
|
+
return True
|
|
33
|
+
return False
|
|
6
34
|
|
|
7
35
|
|
|
8
36
|
class PasswordStrength(Enum):
|
|
@@ -11,49 +39,57 @@ class PasswordStrength(Enum):
|
|
|
11
39
|
TEACHER = auto()
|
|
12
40
|
|
|
13
41
|
def password_test(self, password):
|
|
14
|
-
if
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
minimum_password_length=
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
password
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
42
|
+
if password:
|
|
43
|
+
if self is PasswordStrength.STUDENT:
|
|
44
|
+
minimum_password_length = 6
|
|
45
|
+
# Make student password case insensitive
|
|
46
|
+
password = password.lower()
|
|
47
|
+
if not password_strength_test(
|
|
48
|
+
password=password,
|
|
49
|
+
minimum_password_length=minimum_password_length,
|
|
50
|
+
upper=False,
|
|
51
|
+
lower=False,
|
|
52
|
+
numbers=False,
|
|
53
|
+
special_char=False,
|
|
54
|
+
):
|
|
55
|
+
raise forms.ValidationError(
|
|
56
|
+
f"Password not strong enough, consider using at least {minimum_password_length} characters and making it hard to guess."
|
|
57
|
+
)
|
|
58
|
+
if is_password_pwned(password):
|
|
59
|
+
raise forms.ValidationError("Password is too common, consider using a different password.")
|
|
60
|
+
elif self is PasswordStrength.INDEPENDENT:
|
|
61
|
+
minimum_password_length = 8
|
|
62
|
+
if not password_strength_test(
|
|
63
|
+
password=password,
|
|
64
|
+
minimum_password_length=minimum_password_length,
|
|
65
|
+
upper=True,
|
|
66
|
+
lower=True,
|
|
67
|
+
numbers=True,
|
|
68
|
+
special_char=False,
|
|
69
|
+
):
|
|
70
|
+
raise forms.ValidationError(
|
|
71
|
+
f"Password not strong enough, consider using at least {minimum_password_length} characters, "
|
|
72
|
+
"upper and lower case letters, and numbers and making it hard to guess."
|
|
73
|
+
)
|
|
74
|
+
if is_password_pwned(password):
|
|
75
|
+
raise forms.ValidationError("Password is too common, consider using a different password.")
|
|
76
|
+
else:
|
|
77
|
+
minimum_password_length = 10
|
|
78
|
+
if not password_strength_test(
|
|
79
|
+
password=password,
|
|
80
|
+
minimum_password_length=minimum_password_length,
|
|
81
|
+
upper=True,
|
|
82
|
+
lower=True,
|
|
83
|
+
numbers=True,
|
|
84
|
+
special_char=True,
|
|
85
|
+
):
|
|
86
|
+
raise forms.ValidationError(
|
|
87
|
+
f"Password not strong enough, consider using at least {minimum_password_length} characters, "
|
|
88
|
+
"upper and lower case letters, numbers, special characters and making it hard to guess."
|
|
89
|
+
)
|
|
90
|
+
if is_password_pwned(password):
|
|
91
|
+
raise forms.ValidationError("Password is too common, consider using a different password.")
|
|
92
|
+
|
|
57
93
|
return password
|
|
58
94
|
|
|
59
95
|
|
|
@@ -78,10 +114,7 @@ def password_strength_test(
|
|
|
78
114
|
and (not upper or re.search(r"[A-Z]", password))
|
|
79
115
|
and (not lower or re.search(r"[a-z]", password))
|
|
80
116
|
and (not numbers or re.search(r"[0-9]", password))
|
|
81
|
-
and (
|
|
82
|
-
not special_char
|
|
83
|
-
or re.search(r"[!@#$%^&*()_+\-=\[\]{};':\"\\|,.<>\/?]", password)
|
|
84
|
-
)
|
|
117
|
+
and (not special_char or re.search(r"[!@#$%^&*()_+\-=\[\]{};':\"\\|,.<>\/?]", password))
|
|
85
118
|
and (password not in most_used_passwords)
|
|
86
119
|
)
|
|
87
120
|
|
|
@@ -89,6 +122,12 @@ def password_strength_test(
|
|
|
89
122
|
def form_clean_password(self, password_field_name, strength: PasswordStrength):
|
|
90
123
|
password = self.cleaned_data.get(password_field_name, None)
|
|
91
124
|
password = strength.password_test(password)
|
|
125
|
+
if hasattr(self, "user"):
|
|
126
|
+
current_user_password = self.user.password
|
|
127
|
+
algorithm, iterations, salt, hash = current_user_password.split("$")
|
|
128
|
+
new_hashed_password = ph().encode(password, salt)
|
|
129
|
+
if new_hashed_password == current_user_password:
|
|
130
|
+
raise ValidationError(f"Please choose a password that you haven't used before")
|
|
92
131
|
return password
|
|
93
132
|
|
|
94
133
|
|
portal/helpers/ratelimit.py
CHANGED
|
@@ -36,19 +36,33 @@ from ratelimit.core import (
|
|
|
36
36
|
_make_cache_key,
|
|
37
37
|
)
|
|
38
38
|
|
|
39
|
+
from portal.helpers.regexes import EMAIL_REGEX_PATTERN
|
|
40
|
+
from portal.helpers.request_handlers import get_access_code_from_request
|
|
39
41
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
+
RATELIMIT_LOGIN_GROUP = "login"
|
|
43
|
+
RATELIMIT_LOGIN_RATE = "5/d"
|
|
44
|
+
RATELIMIT_LOGIN_RATE_SCHOOL_STUDENT = "10/d"
|
|
42
45
|
RATELIMIT_METHOD = "POST"
|
|
43
46
|
|
|
47
|
+
RATELIMIT_USER_ALREADY_REGISTERED_EMAIL_GROUP = "user_already_registered_email"
|
|
48
|
+
RATELIMIT_USER_ALREADY_REGISTERED_EMAIL_RATE = "1/d"
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def school_student_key(group, request):
|
|
52
|
+
access_code = get_access_code_from_request(request)
|
|
53
|
+
return f'{request.POST.get("username", "")},{access_code}'
|
|
54
|
+
|
|
44
55
|
|
|
45
56
|
def get_ratelimit_cache_key_for_user(user: str):
|
|
46
|
-
|
|
57
|
+
# check for email quickly
|
|
58
|
+
|
|
59
|
+
user_rate = RATELIMIT_LOGIN_RATE if EMAIL_REGEX_PATTERN.match(user) else RATELIMIT_LOGIN_RATE_SCHOOL_STUDENT
|
|
60
|
+
_, period = _split_rate(rate=user_rate)
|
|
47
61
|
window = _get_window(value=user, period=period)
|
|
48
62
|
cache_key = _make_cache_key(
|
|
49
|
-
group=
|
|
63
|
+
group=RATELIMIT_LOGIN_GROUP,
|
|
50
64
|
window=window,
|
|
51
|
-
rate=
|
|
65
|
+
rate=user_rate,
|
|
52
66
|
value=user,
|
|
53
67
|
methods=RATELIMIT_METHOD,
|
|
54
68
|
)
|
|
@@ -65,9 +79,7 @@ def clear_ratelimit_cache_for_user(user: str):
|
|
|
65
79
|
cache.delete(cache_key)
|
|
66
80
|
|
|
67
81
|
|
|
68
|
-
def is_ratelimited(
|
|
69
|
-
request, group=None, fn=None, key=None, rate=None, method=ALL, increment=False
|
|
70
|
-
):
|
|
82
|
+
def is_ratelimited(request, group=None, fn=None, key=None, rate=None, method=ALL, increment=False):
|
|
71
83
|
"""
|
|
72
84
|
As in django-ratelimit. Calls "get_usage" defined below to enable the usage of
|
|
73
85
|
the custom cache_key functionality.
|
|
@@ -79,9 +91,7 @@ def is_ratelimited(
|
|
|
79
91
|
return usage["should_limit"]
|
|
80
92
|
|
|
81
93
|
|
|
82
|
-
def get_usage(
|
|
83
|
-
request, group=None, fn=None, key=None, rate=None, method=ALL, increment=False
|
|
84
|
-
):
|
|
94
|
+
def get_usage(request, group=None, fn=None, key=None, rate=None, method=ALL, increment=False):
|
|
85
95
|
"""
|
|
86
96
|
As in django-ratelimit. Makes cache_key global so it can be called outside the scope
|
|
87
97
|
and the cache can be accessed at later times.
|
|
@@ -89,9 +99,7 @@ def get_usage(
|
|
|
89
99
|
global cache_key
|
|
90
100
|
|
|
91
101
|
if group is None and fn is None:
|
|
92
|
-
raise ImproperlyConfigured(
|
|
93
|
-
"get_usage must be called with either " "`group` or `fn` arguments"
|
|
94
|
-
)
|
|
102
|
+
raise ImproperlyConfigured("get_usage must be called with either " "`group` or `fn` arguments")
|
|
95
103
|
|
|
96
104
|
if not getattr(settings, "RATELIMIT_ENABLE", True):
|
|
97
105
|
return None
|
|
@@ -153,7 +161,16 @@ def get_usage(
|
|
|
153
161
|
|
|
154
162
|
cache_name = getattr(settings, "RATELIMIT_USE_CACHE", "default")
|
|
155
163
|
cache = caches[cache_name]
|
|
156
|
-
|
|
164
|
+
|
|
165
|
+
if value == "":
|
|
166
|
+
return {
|
|
167
|
+
"count": 0,
|
|
168
|
+
"limit": 0,
|
|
169
|
+
"should_limit": False,
|
|
170
|
+
"time_left": -1,
|
|
171
|
+
}
|
|
172
|
+
else:
|
|
173
|
+
cache_key = _make_cache_key(group, window, rate, value, method)
|
|
157
174
|
|
|
158
175
|
count = None
|
|
159
176
|
added = cache.add(cache_key, initial_value, period + EXPIRATION_FUDGE)
|
portal/helpers/regexes.py
CHANGED
|
@@ -2,3 +2,8 @@ import re
|
|
|
2
2
|
|
|
3
3
|
ACCESS_CODE_REGEX = "[a-zA-Z]{5}|[a-zA-Z]{2}[0-9]{3}"
|
|
4
4
|
ACCESS_CODE_PATTERN = re.compile(rf"^{ACCESS_CODE_REGEX}$")
|
|
5
|
+
EMAIL_REGEX = """(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])"""
|
|
6
|
+
EMAIL_REGEX_PATTERN = re.compile(EMAIL_REGEX)
|
|
7
|
+
ACCESS_CODE_FROM_URL_REGEX = "/login/student/(\w+)"
|
|
8
|
+
ACCESS_CODE_FROM_URL_PATTERN = re.compile(ACCESS_CODE_FROM_URL_REGEX)
|
|
9
|
+
JWT_REGEX = "([a-zA-Z0-9_=]+)\.([a-zA-Z0-9_=]+)\.([a-zA-Z0-9_\-\+\/=]*)"
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
from portal.helpers.regexes import ACCESS_CODE_FROM_URL_PATTERN
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def get_access_code_from_request(request):
|
|
5
|
+
try:
|
|
6
|
+
access_code = ACCESS_CODE_FROM_URL_PATTERN.search(request.get_full_path()).group(1)
|
|
7
|
+
except AttributeError:
|
|
8
|
+
access_code = ""
|
|
9
|
+
print(f"Access code not found in {request.get_full_path()}")
|
|
10
|
+
return access_code
|
|
@@ -2,7 +2,6 @@ from __future__ import unicode_literals
|
|
|
2
2
|
|
|
3
3
|
from builtins import str
|
|
4
4
|
from django.db import models, migrations
|
|
5
|
-
from portal.helpers import location
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
class Migration(migrations.Migration):
|
|
@@ -12,7 +11,12 @@ class Migration(migrations.Migration):
|
|
|
12
11
|
|
|
13
12
|
School = apps.get_model("portal", "School")
|
|
14
13
|
for school in School.objects.all():
|
|
15
|
-
|
|
14
|
+
country, town, lat, lng = (
|
|
15
|
+
"GB",
|
|
16
|
+
"0",
|
|
17
|
+
"0",
|
|
18
|
+
"0",
|
|
19
|
+
)
|
|
16
20
|
school.country = str(country)
|
|
17
21
|
school.town = town
|
|
18
22
|
school.lat = lat
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .cron_mixin import CronMixin
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from rest_framework.request import Request
|
|
2
|
+
from rest_framework.response import Response
|
|
3
|
+
|
|
4
|
+
from ..permissions import IsCronRequestFromGoogle
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class CronMixin:
|
|
8
|
+
http_method_names = ["get"]
|
|
9
|
+
permission_classes = [IsCronRequestFromGoogle]
|
|
10
|
+
|
|
11
|
+
def get(self, request: Request) -> Response:
|
|
12
|
+
raise NotImplementedError()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .is_cron_request_from_google import IsCronRequestFromGoogle
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from django.conf import settings
|
|
2
|
+
from rest_framework.permissions import BasePermission
|
|
3
|
+
from rest_framework.request import Request
|
|
4
|
+
from rest_framework.views import View
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class IsCronRequestFromGoogle(BasePermission):
|
|
8
|
+
"""
|
|
9
|
+
Validate that requests to your cron URLs are coming from App Engine and not from another source.
|
|
10
|
+
https://cloud.google.com/appengine/docs/flexible/scheduling-jobs-with-cron-yaml#securing_urls_for_cron
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
def has_permission(self, request: Request, view: View):
|
|
14
|
+
return settings.DEBUG or request.META.get("HTTP_X_APPENGINE_CRON") == "true"
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<svg width="447" height="102" viewBox="0 0 447 102" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path d="M431.385 43.1818C436.945 43.1818 441.384 47.7763 441.384 53.3057C441.384 58.8352 436.945 63.4254 431.385 63.4254C425.824 63.4254 421.393 58.7672 421.393 53.3057C421.393 47.8443 425.829 43.1818 431.385 43.1818ZM431.385 37.8394C422.638 37.8394 415.765 44.5461 415.765 53.3057C415.765 62.0654 422.638 68.7594 431.385 68.7594C440.131 68.7594 447 62.0569 447 53.3057C447 44.5546 440.131 37.8394 431.385 37.8394Z" fill="white"/>
|
|
3
|
+
<path d="M369.013 38.7064V42.0258H368.807C366.532 39.4841 362.824 37.8436 358.962 37.8436C350.211 37.8436 343.342 44.5504 343.342 53.3057C343.342 62.0611 350.211 68.7636 358.962 68.7636C362.824 68.7636 366.532 67.0721 368.807 64.5814H369.013V67.8286H374.628V38.7106H369.013V38.7064ZM359.116 63.4211C353.555 63.4211 349.12 58.763 349.12 53.3015C349.12 47.84 353.551 43.1776 359.116 43.1776C364.68 43.1776 369.115 47.772 369.115 53.3015C369.115 58.831 364.68 63.4211 359.116 63.4211Z" fill="white"/>
|
|
4
|
+
<path d="M405.136 24.7701V42.0215H404.931C402.66 39.4799 398.952 37.8394 395.09 37.8394C386.348 37.8394 379.479 44.5461 379.479 53.3015C379.479 62.0569 386.348 68.7594 395.09 68.7594C398.952 68.7594 402.66 67.0678 404.931 64.5772H405.136V67.8244H410.761V24.7743H405.136V24.7701ZM395.248 63.4212C389.688 63.4212 385.253 58.763 385.253 53.3015C385.253 47.84 389.688 43.1776 395.248 43.1776C400.808 43.1776 405.252 47.772 405.252 53.3015C405.252 58.831 400.808 63.4212 395.248 63.4212Z" fill="white"/>
|
|
5
|
+
<path d="M338.244 60.2378C336.418 62.2056 333.852 63.4594 330.973 63.4594C325.409 63.4594 320.982 58.8012 320.982 53.344C320.982 47.8868 325.413 43.2158 330.973 43.2158C333.86 43.2158 336.435 44.4611 338.244 46.429L340.964 41.35C338.278 39.1654 334.814 37.8819 330.973 37.8819C322.222 37.8819 315.358 44.5844 315.358 53.3483C315.358 62.1121 322.222 68.8062 330.973 68.8062C334.814 68.8062 338.278 67.5141 340.964 65.3338L338.244 60.2463V60.2378Z" fill="white"/>
|
|
6
|
+
<path d="M295.431 43.1818C301 43.1818 305.435 47.7763 305.435 53.3057C305.435 58.8352 301 63.4254 295.431 63.4254C289.862 63.4254 285.44 58.7672 285.44 53.3057C285.44 47.8443 289.879 43.1818 295.431 43.1818ZM295.431 37.8394C286.685 37.8394 279.82 44.5461 279.82 53.3057C279.82 62.0654 286.685 68.7594 295.431 68.7594C304.178 68.7594 311.051 62.0569 311.051 53.3057C311.051 44.5546 304.178 37.8394 295.431 37.8394Z" fill="white"/>
|
|
7
|
+
<path d="M332.123 82.6107C332.123 81.6587 332.26 80.8044 332.534 80.0436C332.808 79.2871 333.188 78.641 333.68 78.1098C334.172 77.5785 334.75 77.1747 335.417 76.89C336.084 76.6052 336.815 76.465 337.615 76.465C338.415 76.465 339.125 76.618 339.677 76.924C340.228 77.23 340.677 77.5657 341.032 77.927L340.177 78.8833C339.873 78.5688 339.527 78.3095 339.133 78.097C338.74 77.8888 338.24 77.7825 337.632 77.7825C337.025 77.7825 336.482 77.893 335.994 78.1183C335.511 78.3435 335.096 78.6623 334.758 79.0746C334.42 79.4911 334.155 79.9926 333.967 80.5834C333.779 81.1741 333.685 81.8372 333.685 82.5682C333.685 83.2992 333.774 83.9878 333.95 84.5828C334.125 85.1778 334.377 85.6878 334.715 86.1086C335.049 86.5294 335.459 86.8566 335.951 87.0819C336.443 87.3114 337.008 87.4262 337.649 87.4262C338.073 87.4262 338.475 87.3624 338.86 87.2349C339.24 87.1074 339.553 86.9374 339.796 86.7206V83.6308H337.269V82.3854H341.178V87.3709C340.789 87.7662 340.28 88.0977 339.642 88.3527C339.005 88.612 338.287 88.7395 337.487 88.7395C336.687 88.7395 335.977 88.5992 335.323 88.3229C334.668 88.0467 334.104 87.6472 333.633 87.1201C333.158 86.5974 332.791 85.9514 332.525 85.1863C332.26 84.4213 332.123 83.5585 332.123 82.5937V82.6107Z" fill="white"/>
|
|
8
|
+
<path d="M347.358 82.3047H349.356C350.288 82.3047 351.002 82.1135 351.503 81.7352C351.999 81.3569 352.247 80.7831 352.247 80.0096C352.247 79.2361 351.999 78.6793 351.503 78.3648C351.006 78.0503 350.292 77.8973 349.356 77.8973H347.358V82.3047ZM352.392 88.5355L349.518 83.533H347.354V88.5355H345.844V76.686H349.569C350.177 76.686 350.737 76.7412 351.25 76.856C351.764 76.9707 352.208 77.162 352.576 77.4255C352.944 77.689 353.235 78.0333 353.44 78.4541C353.645 78.8748 353.748 79.3933 353.748 80.0096C353.748 80.9362 353.504 81.6757 353.021 82.2325C352.538 82.785 351.888 83.1675 351.075 83.3715L354.09 88.5355H352.384H352.392Z" fill="white"/>
|
|
9
|
+
<path d="M362.627 87.4304C363.162 87.4304 363.641 87.3156 364.073 87.0861C364.505 86.8566 364.873 86.5293 365.181 86.1001C365.489 85.6751 365.728 85.1608 365.899 84.5658C366.07 83.9707 366.156 83.2992 366.156 82.5512C366.156 81.8031 366.07 81.1529 365.899 80.5663C365.728 79.9756 365.489 79.4783 365.181 79.066C364.873 78.658 364.505 78.3393 364.073 78.1182C363.645 77.8972 363.162 77.7825 362.627 77.7825C362.093 77.7825 361.614 77.893 361.182 78.1182C360.75 78.3435 360.382 78.658 360.074 79.066C359.766 79.474 359.526 79.9756 359.355 80.5663C359.184 81.1571 359.099 81.8201 359.099 82.5512C359.099 83.2822 359.184 83.9707 359.355 84.5658C359.526 85.1608 359.766 85.6751 360.074 86.1001C360.382 86.5293 360.75 86.8566 361.182 87.0861C361.609 87.3156 362.093 87.4304 362.627 87.4304ZM362.627 88.7522C361.875 88.7522 361.19 88.6077 360.566 88.3187C359.941 88.0297 359.407 87.6174 358.958 87.0819C358.508 86.5463 358.158 85.8961 357.91 85.131C357.662 84.366 357.538 83.5075 357.538 82.5554C357.538 81.6034 357.662 80.7534 357.91 80.0011C358.158 79.2488 358.508 78.6113 358.958 78.0842C359.407 77.5615 359.941 77.1619 360.566 76.8857C361.19 76.6094 361.875 76.4692 362.627 76.4692C363.38 76.4692 364.064 76.6094 364.689 76.8942C365.313 77.179 365.852 77.5827 366.305 78.1055C366.759 78.6283 367.11 79.2658 367.362 80.0181C367.61 80.7704 367.734 81.6161 367.734 82.5554C367.734 83.4947 367.61 84.366 367.362 85.131C367.114 85.8961 366.759 86.5463 366.305 87.0819C365.852 87.6174 365.313 88.0297 364.689 88.3187C364.064 88.6077 363.376 88.7522 362.627 88.7522Z" fill="white"/>
|
|
10
|
+
<path d="M372.058 76.686H373.568V83.6775C373.568 84.3873 373.641 84.9866 373.786 85.4668C373.931 85.9471 374.128 86.3339 374.376 86.6229C374.624 86.9119 374.919 87.1202 375.257 87.2477C375.595 87.3752 375.959 87.4389 376.348 87.4389C376.737 87.4389 377.118 87.3752 377.456 87.2477C377.794 87.1202 378.089 86.9119 378.345 86.6229C378.598 86.3339 378.799 85.9471 378.944 85.4668C379.09 84.9866 379.162 84.3873 379.162 83.6775V76.686H380.616V83.6393C380.616 84.5913 380.505 85.3903 380.287 86.0406C380.069 86.6909 379.77 87.2179 379.389 87.6217C379.008 88.0255 378.555 88.3145 378.037 88.4887C377.516 88.663 376.951 88.7522 376.348 88.7522C375.745 88.7522 375.176 88.663 374.65 88.4887C374.124 88.3145 373.671 88.0255 373.286 87.6217C372.905 87.2179 372.606 86.6909 372.387 86.0406C372.169 85.3903 372.058 84.5913 372.058 83.6393V76.686Z" fill="white"/>
|
|
11
|
+
<path d="M389.127 82.6107C390.167 82.6107 390.941 82.4152 391.445 82.0242C391.95 81.6332 392.202 81.0169 392.202 80.1711C392.202 79.3253 391.946 78.7218 391.437 78.3903C390.928 78.0588 390.158 77.893 389.132 77.893H387.168V82.6065H389.132L389.127 82.6107ZM385.654 76.686H389.311C389.966 76.686 390.564 76.7455 391.107 76.8687C391.655 76.9877 392.117 77.1833 392.498 77.4553C392.882 77.7273 393.178 78.0843 393.391 78.5306C393.601 78.9768 393.708 79.5251 393.708 80.1754C393.708 80.8257 393.601 81.3442 393.391 81.799C393.178 82.258 392.878 82.6362 392.493 82.938C392.104 83.2398 391.642 83.465 391.103 83.6138C390.564 83.7625 389.966 83.839 389.311 83.839H387.164V88.5355H385.654V76.686Z" fill="white"/>
|
|
12
|
+
<path d="M171.153 58.8438V49.6804H174.613C175.323 49.6804 175.918 49.8121 176.397 50.0756C176.88 50.3391 177.244 50.6962 177.492 51.1552C177.74 51.6142 177.864 52.1327 177.864 52.715C177.864 53.2973 177.74 53.8243 177.492 54.2833C177.244 54.7381 176.876 55.0993 176.388 55.3586C175.901 55.6179 175.302 55.7496 174.592 55.7496H172.3V54.3853H174.365C174.78 54.3853 175.118 54.3131 175.383 54.1728C175.648 54.0283 175.845 53.8328 175.974 53.582C176.102 53.3313 176.166 53.0423 176.166 52.7192C176.166 52.3962 176.102 52.1072 175.974 51.8607C175.845 51.6142 175.648 51.4187 175.383 51.2827C175.118 51.1467 174.776 51.0744 174.357 51.0744H172.826V58.8523H171.153V58.8438Z" fill="white"/>
|
|
13
|
+
<path d="M187.757 54.2578C187.757 55.2438 187.573 56.0896 187.201 56.7909C186.829 57.4922 186.324 58.032 185.687 58.406C185.049 58.78 184.327 58.967 183.518 58.967C182.71 58.967 181.987 58.78 181.35 58.406C180.713 58.032 180.208 57.4922 179.836 56.7909C179.464 56.0896 179.28 55.2438 179.28 54.2578C179.28 53.2717 179.464 52.426 179.836 51.7247C180.208 51.0234 180.713 50.4836 181.35 50.1096C181.987 49.7356 182.71 49.5486 183.518 49.5486C184.327 49.5486 185.049 49.7356 185.687 50.1096C186.324 50.4836 186.829 51.0192 187.201 51.7247C187.573 52.426 187.757 53.2717 187.757 54.2578ZM186.076 54.2578C186.076 53.5608 185.969 52.9742 185.751 52.4982C185.533 52.018 185.233 51.6567 184.848 51.4102C184.464 51.1637 184.023 51.0404 183.518 51.0404C183.014 51.0404 182.573 51.1637 182.188 51.4102C181.803 51.6567 181.504 52.018 181.286 52.4982C181.068 52.9785 180.961 53.565 180.961 54.2578C180.961 54.9506 181.068 55.5413 181.286 56.0174C181.504 56.4934 181.803 56.8589 182.188 57.1054C182.573 57.3519 183.014 57.4752 183.518 57.4752C184.023 57.4752 184.464 57.3519 184.848 57.1054C185.233 56.8589 185.533 56.4976 185.751 56.0174C185.969 55.5371 186.076 54.9506 186.076 54.2578Z" fill="white"/>
|
|
14
|
+
<path d="M191.234 58.8438L188.629 49.6804H190.426L192.089 56.4169H192.175L193.95 49.6804H195.584L197.363 56.4211H197.444L199.108 49.6804H200.904L198.3 58.8438H196.653L194.805 52.4132H194.733L192.881 58.8438H191.234Z" fill="white"/>
|
|
15
|
+
<path d="M202.252 58.8438V49.6804H208.252V51.0702H203.924V53.5565H207.94V54.9506H203.924V57.454H208.287V58.8438H202.252Z" fill="white"/>
|
|
16
|
+
<path d="M210.147 58.8438V49.6804H213.607C214.317 49.6804 214.912 49.8036 215.391 50.0459C215.874 50.2924 216.238 50.6324 216.486 51.0744C216.734 51.5165 216.858 52.0265 216.858 52.613C216.858 53.1995 216.734 53.7095 216.481 54.1431C216.229 54.5723 215.861 54.9081 215.378 55.1419C214.89 55.3756 214.296 55.4946 213.586 55.4946H211.122V54.1176H213.359C213.774 54.1176 214.112 54.0623 214.377 53.9433C214.642 53.8285 214.839 53.6585 214.967 53.4375C215.096 53.2165 215.16 52.9403 215.16 52.6172C215.16 52.2942 215.096 52.0137 214.967 51.7842C214.839 51.5547 214.642 51.3762 214.377 51.2572C214.112 51.1382 213.77 51.0744 213.355 51.0744H211.824V58.8523H210.151L210.147 58.8438ZM214.912 54.6871L217.196 58.8395H215.331L213.09 54.6871H214.912Z" fill="white"/>
|
|
17
|
+
<path d="M218.585 58.8438V49.6804H224.586V51.0702H220.258V53.5565H224.274V54.9506H220.258V57.454H224.62V58.8438H218.585Z" fill="white"/>
|
|
18
|
+
<path d="M229.607 58.8438H226.481V49.6804H229.672C230.587 49.6804 231.374 49.8631 232.033 50.2287C232.691 50.5942 233.2 51.1169 233.551 51.8012C233.902 52.4855 234.081 53.3015 234.081 54.2536C234.081 55.2056 233.902 56.0301 233.547 56.7144C233.192 57.3987 232.678 57.9257 232.011 58.2955C231.344 58.661 230.54 58.8438 229.603 58.8438H229.607ZM228.153 57.4072H229.526C230.168 57.4072 230.702 57.2882 231.134 57.0544C231.562 56.8207 231.887 56.4679 232.101 56.0046C232.319 55.5371 232.426 54.9548 232.426 54.2536C232.426 53.5523 232.319 52.97 232.101 52.5067C231.887 52.0435 231.566 51.695 231.143 51.4654C230.719 51.2359 230.198 51.1169 229.573 51.1169H228.149V57.4072H228.153Z" fill="white"/>
|
|
19
|
+
<path d="M239.197 58.8438V49.6804H242.729C243.397 49.6804 243.948 49.7824 244.393 49.9906C244.838 50.1989 245.167 50.4794 245.39 50.8407C245.612 51.1977 245.719 51.6057 245.719 52.0562C245.719 52.4302 245.646 52.749 245.505 53.0125C245.36 53.276 245.167 53.4885 244.923 53.6543C244.68 53.82 244.41 53.9348 244.107 54.0071V54.0963C244.436 54.1133 244.748 54.2153 245.052 54.3938C245.355 54.5723 245.599 54.8273 245.792 55.1588C245.984 55.4861 246.078 55.8856 246.078 56.3489C246.078 56.8122 245.963 57.2499 245.732 57.6282C245.501 58.0065 245.15 58.304 244.688 58.5207C244.222 58.7375 243.636 58.848 242.93 58.848H239.197V58.8438ZM240.869 53.5735H242.52C242.806 53.5735 243.067 53.5225 243.298 53.4163C243.529 53.31 243.713 53.1613 243.846 52.9658C243.978 52.7702 244.047 52.5365 244.047 52.2687C244.047 51.916 243.923 51.6227 243.67 51.3932C243.418 51.1637 243.046 51.0489 242.554 51.0489H240.865V53.5778L240.869 53.5735ZM240.869 57.454H242.665C243.273 57.454 243.709 57.3392 243.978 57.1054C244.248 56.8759 244.38 56.5784 244.38 56.2129C244.38 55.9409 244.312 55.6944 244.179 55.4776C244.042 55.2566 243.85 55.0866 243.602 54.9591C243.354 54.8316 243.054 54.7678 242.712 54.7678H240.869V57.454Z" fill="white"/>
|
|
20
|
+
<path d="M247.092 49.6761H248.978L251.236 53.7308H251.326L253.585 49.6761H255.471L252.118 55.4223V58.8395H250.449V55.4223L247.096 49.6761H247.092Z" fill="white"/>
|
|
21
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M70.9174 2.7754C75.0233 2.7754 78.9667 4.39471 81.8666 7.28058C84.7664 10.1622 86.4002 14.0809 86.4002 18.161C86.4002 22.2412 84.7707 26.1599 81.8666 29.0415C78.9667 31.9231 75.0233 33.5467 70.9174 33.5467H62.6029C62.0469 33.5467 61.6021 33.1004 61.6021 32.5521V3.77419C61.6021 3.22166 62.0511 2.77965 62.6029 2.77965H70.9174V2.7754ZM72.996 26.8186C73.552 26.8186 73.9968 26.3724 73.9968 25.8241V10.5575C73.9968 10.0049 73.5478 9.56293 72.996 9.56293H72.8036C72.2475 9.56293 71.8027 10.0092 71.8027 10.5575V25.8326C71.8027 26.3851 72.2518 26.8271 72.8036 26.8271H72.996V26.8144V26.8186Z" fill="white"/>
|
|
22
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.4828 33.5552C11.3769 33.5552 7.43346 31.9359 4.53364 29.05C1.63382 26.1684 0 22.2497 0 18.1696C0 14.0894 1.62955 10.1707 4.53364 7.2891C7.43346 4.40748 11.3769 2.78391 15.4828 2.78391H23.036C24.0155 2.78391 24.8024 3.56595 24.8024 4.53924V15.2879C24.8024 16.2612 24.0155 17.0433 23.036 17.0433H14.6146C14.0115 17.0433 13.5154 17.5363 13.5154 18.1356C13.5154 18.7348 14.0115 19.2278 14.6146 19.2278H23.036C24.0155 19.2278 24.8024 20.0099 24.8024 20.9832V31.7914C24.8024 32.7647 24.0155 33.5467 23.036 33.5467H15.4828V33.5594V33.5552Z" fill="white"/>
|
|
23
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M53.1506 52.6469C53.1506 61.4235 60.3061 68.5341 69.1381 68.5341C77.9702 68.5341 85.1256 61.4235 85.1256 52.6469C85.1256 43.8703 77.9702 36.7598 69.1381 36.7598C60.3061 36.7598 53.1506 43.8703 53.1506 52.6469ZM75.2115 46.9559C74.8266 46.5734 74.185 46.5734 73.8001 46.9559L62.9365 57.7514C62.5515 58.1339 62.5515 58.7714 62.9365 59.154L63.069 59.2857C63.454 59.6682 64.0955 59.6682 64.4805 59.2857L75.3441 48.4902C75.729 48.1077 75.729 47.4702 75.3441 47.0877L75.2115 46.9559Z" fill="white"/>
|
|
24
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M58.4714 9.30794C58.4714 8.94668 58.2789 8.62367 57.9667 8.44516L43.767 0.289069C43.4548 0.106311 43.0784 0.106311 42.7662 0.289069L28.5408 8.44516C28.2286 8.62792 28.0361 8.94668 28.0361 9.30794V25.6159C28.0361 25.9771 28.2286 26.3001 28.5408 26.4787L42.7534 34.6347C43.0656 34.8175 43.442 34.8175 43.7542 34.6347L57.9667 26.4787C58.2789 26.2959 58.4714 25.9771 58.4714 25.6159V9.30794ZM43.412 27.2479C43.968 27.2479 44.4128 26.8017 44.4128 26.2534V9.76696C44.4128 9.21444 43.9638 8.77242 43.412 8.77242H43.0741C42.5181 8.77242 42.0733 9.21869 42.0733 9.76696V26.2534C42.0733 26.8059 42.5224 27.2479 43.0741 27.2479H43.412Z" fill="white"/>
|
|
25
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M105.022 98.6678C105.48 99.1226 106.232 99.1226 106.69 98.6678L118.4 87.0309C118.738 86.6951 118.738 86.1298 118.4 85.7941L106.69 74.1571C106.232 73.7023 105.48 73.7023 105.022 74.1571C104.564 74.6119 104.564 75.3599 105.022 75.8147L114.607 85.3393C115.21 85.9386 115.21 86.9119 114.607 87.5154L105.022 97.04C104.564 97.4863 104.564 98.2173 105.022 98.6721V98.6678Z" fill="white"/>
|
|
26
|
+
<path d="M24.8025 38.1454C24.8025 37.5928 25.2516 37.1508 25.8033 37.1508H48.6084C49.1644 37.1508 49.6092 37.5971 49.6092 38.1454V44.7629C49.6092 45.3154 49.1601 45.7574 48.6084 45.7574H38.2152C37.6592 45.7574 37.2144 46.2037 37.2144 46.752V46.9432C37.2144 47.4958 37.6635 47.9378 38.2152 47.9378H48.6084C49.1644 47.9378 49.6092 48.384 49.6092 48.9323V54.4703C49.6092 55.0228 49.1601 55.4648 48.6084 55.4648H38.2281C37.672 55.4648 37.2272 55.9111 37.2272 56.4594V66.9191C37.2272 67.4716 36.7781 67.9136 36.2264 67.9136H25.8076C25.2516 67.9136 24.8068 67.4673 24.8068 66.9191V38.1326V38.1454H24.8025Z" fill="white"/>
|
|
27
|
+
<path d="M88.6709 3.76994C88.6709 3.21742 89.12 2.7754 89.6717 2.7754H112.477C113.033 2.7754 113.478 3.22167 113.478 3.76994V10.8082C113.478 11.3608 113.029 11.8028 112.477 11.8028H102.084C101.528 11.8028 101.083 12.249 101.083 12.7973V12.9886C101.083 13.5411 101.532 13.9831 102.084 13.9831H112.477C113.033 13.9831 113.478 14.4294 113.478 14.9777V21.2934C113.478 21.8459 113.029 22.288 112.477 22.288H102.084C101.528 22.288 101.083 22.7342 101.083 23.2825V23.4738C101.083 24.0263 101.532 24.4683 102.084 24.4683H112.477C113.033 24.4683 113.478 24.9146 113.478 25.4628V32.5351C113.478 33.0877 113.029 33.5297 112.477 33.5297H89.6717C89.1157 33.5297 88.6709 33.0834 88.6709 32.5351V3.74869V3.76144V3.76994Z" fill="white"/>
|
|
28
|
+
<path d="M78.1713 97.4948C81.0712 100.376 85.0146 102 89.1205 102H97.435C97.9911 102 98.4359 101.554 98.4359 101.005V93.9332C98.4359 93.3806 97.9868 92.9386 97.435 92.9386H86.3405C85.7844 92.9386 85.3396 92.4924 85.3396 91.9441V91.7528C85.3396 91.2003 85.7887 90.7583 86.3405 90.7583H97.435C97.9911 90.7583 98.4359 90.312 98.4359 89.7637V83.448C98.4359 82.8954 97.9868 82.4534 97.435 82.4534H86.3405C85.7844 82.4534 85.3396 82.0072 85.3396 81.4589V81.2676C85.3396 80.7151 85.7887 80.2731 86.3405 80.2731H97.435C97.9911 80.2731 98.4359 79.8268 98.4359 79.2785V72.2403C98.4359 71.6877 97.9868 71.2457 97.435 71.2457H89.1205C85.0146 71.2457 81.0712 72.865 78.1713 75.7509C75.2715 78.6325 73.6377 82.5512 73.6377 86.6314C73.6377 90.7115 75.2672 94.6429 78.1713 97.5203V97.5033V97.4948Z" fill="white"/>
|
|
29
|
+
<path d="M47.1115 72.032C47.1115 71.4795 47.5605 71.0375 48.1123 71.0375H70.9174C71.4734 71.0375 71.9182 71.4837 71.9182 72.032V78.6495C71.9182 79.2021 71.4691 79.6441 70.9174 79.6441H60.5242C59.9682 79.6441 59.5234 80.0904 59.5234 80.6386V80.8299C59.5234 81.3824 59.9725 81.8244 60.5242 81.8244H70.9174C71.4734 81.8244 71.9182 82.2707 71.9182 82.819V88.3314C71.9182 88.884 71.4691 89.326 70.9174 89.326H60.5242C59.9682 89.326 59.5234 89.7723 59.5234 90.3205V100.806C59.5234 101.358 59.0743 101.8 58.5225 101.8H48.1294C47.5734 101.8 47.1286 101.354 47.1286 100.806V72.0193H47.1157L47.1072 72.032H47.1115Z" fill="white"/>
|
|
30
|
+
<path d="M27.651 100.818C27.651 101.371 27.2019 101.813 26.6501 101.813H3.84507C3.28905 101.813 2.84424 101.367 2.84424 100.818V72.032C2.84424 71.4795 3.29333 71.0375 3.84507 71.0375H14.2382C14.7942 71.0375 15.239 71.4837 15.239 72.032V89.1815C15.239 89.734 15.6881 90.176 16.2399 90.176H26.633C27.189 90.176 27.6339 90.6223 27.6339 91.1706V100.814H27.651V100.818Z" fill="white"/>
|
|
31
|
+
<path d="M30.4309 72.032C30.4309 71.4795 30.88 71.0375 31.4317 71.0375H42.2611C42.8172 71.0375 43.262 71.4837 43.262 72.032V100.818C43.262 101.371 42.8129 101.813 42.2611 101.813H31.4317C30.8757 101.813 30.4309 101.367 30.4309 100.818V72.032Z" fill="white"/>
|
|
32
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M101.673 66.9276C101.673 67.4801 102.122 67.9221 102.674 67.9221H113.649C114.419 67.9221 114.906 67.0933 114.517 66.4218L109.175 57.2244C108.897 56.7442 109.064 56.1321 109.538 55.8049C110.043 55.4564 110.518 55.0738 110.95 54.6276C112.857 52.732 113.935 50.1479 113.935 47.4618C113.935 44.7757 112.862 42.2001 110.95 40.296C109.042 38.3876 106.442 37.3293 103.739 37.3293H89.6717C89.1157 37.3293 88.6709 37.7756 88.6709 38.3239V66.9063C88.6709 67.4589 89.12 67.9009 89.6717 67.9009H98.4696C99.0256 67.9009 99.4704 67.4546 99.4704 66.9063V60.6713C99.4704 60.1188 99.9195 59.6768 100.471 59.6768H100.664C101.22 59.6768 101.664 60.123 101.664 60.6713V66.9276H101.673ZM100.672 43.9299C101.228 43.9299 101.673 44.3761 101.673 44.9244V51.1594C101.673 51.7119 101.224 52.154 100.672 52.154H100.48C99.9237 52.154 99.4789 51.7077 99.4789 51.1594V44.9244C99.4789 44.3719 99.928 43.9299 100.48 43.9299H100.672Z" fill="white"/>
|
|
33
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.4752 40.3852C16.0176 39.9305 15.2648 39.9305 14.8072 40.3852L3.09668 52.0222C2.75879 52.358 2.75879 52.9232 3.09668 53.259L14.8072 64.896C15.2648 65.3508 16.0176 65.3508 16.4752 64.896C16.9328 64.4412 16.9328 63.6932 16.4752 63.2384L6.89039 53.7138C6.28733 53.1145 6.28733 52.1412 6.89039 51.5377L16.4752 42.013C16.9328 41.5838 16.9328 40.8357 16.4752 40.381V40.3852Z" fill="white"/>
|
|
34
|
+
<path d="M124.081 8.63636C123.478 8.63636 122.917 8.52586 122.391 8.3006C121.865 8.07959 121.403 7.76932 121.006 7.37405C120.608 6.97879 120.296 6.51977 120.073 5.997C119.851 5.47423 119.735 4.91745 119.735 4.31817C119.735 3.7189 119.847 3.16213 120.073 2.63936C120.3 2.11658 120.608 1.65756 121.006 1.2623C121.403 0.86703 121.865 0.55677 122.391 0.335761C122.917 0.114752 123.478 0 124.081 0C124.684 0 125.244 0.110502 125.77 0.335761C126.296 0.56102 126.758 0.86703 127.156 1.2623C127.554 1.65756 127.866 2.11658 128.088 2.63936C128.311 3.16213 128.426 3.7189 128.426 4.31817C128.426 4.91745 128.315 5.47423 128.088 5.997C127.862 6.51977 127.554 6.97879 127.156 7.37405C126.758 7.76932 126.296 8.07959 125.77 8.3006C125.244 8.52586 124.684 8.63636 124.081 8.63636ZM124.081 7.59931C124.688 7.59931 125.244 7.45056 125.74 7.1573C126.236 6.86403 126.638 6.46876 126.934 5.97149C127.229 5.47422 127.378 4.92595 127.378 4.32243C127.378 3.7189 127.229 3.16638 126.934 2.66911C126.638 2.17184 126.236 1.77657 125.74 1.48331C125.244 1.19005 124.688 1.04129 124.081 1.04129C123.473 1.04129 122.917 1.19005 122.417 1.48331C121.917 1.77657 121.519 2.17184 121.224 2.66911C120.929 3.16638 120.779 3.71465 120.779 4.32243C120.779 4.9302 120.929 5.47847 121.224 5.97149C121.519 6.46876 121.917 6.86403 122.417 7.1573C122.917 7.45056 123.469 7.59931 124.081 7.59931ZM122.558 6.26051V2.2781H124.59C124.752 2.2781 124.928 2.32484 125.12 2.4141C125.313 2.5076 125.475 2.64786 125.612 2.83487C125.749 3.02188 125.817 3.25988 125.817 3.54889C125.817 3.83791 125.745 4.08867 125.603 4.29268C125.462 4.49668 125.291 4.64969 125.09 4.75594C124.889 4.8622 124.701 4.9132 124.521 4.9132H123.054V4.26718H124.248C124.367 4.26718 124.496 4.20767 124.637 4.08867C124.778 3.96966 124.846 3.79116 124.846 3.55315C124.846 3.31514 124.778 3.14088 124.637 3.05587C124.496 2.97087 124.376 2.92837 124.269 2.92837H123.431V6.26476H122.55L122.558 6.26051ZM124.983 4.38618L125.984 6.26476H125.017L124.038 4.38618H124.983Z" fill="white"/>
|
|
35
|
+
</svg>
|
|
Binary file
|
|
Binary file
|