diff --git a/app.py b/app.py index d961b783a50..1a65aad8ec1 100644 --- a/app.py +++ b/app.py @@ -117,7 +117,7 @@ def get_locale(): ACHIEVEMENTS = achievements.Achievements(DATABASE, ACHIEVEMENTS_TRANSLATIONS) SURVEYS = surveys.SurveysModule(DATABASE) STATISTICS = statistics.StatisticsModule(DATABASE) - +FOR_TEACHERS = for_teachers.ForTeachersModule(DATABASE, ACHIEVEMENTS) TAGS = collections.defaultdict(hedy_content.NoSuchAdventure) for lang in ALL_LANGUAGES.keys(): TAGS[lang] = hedy_content.Tags(lang) @@ -635,7 +635,7 @@ def parse(): # Save this program (if the user is logged in) if username and body.get('save_name'): try: - program_logic = programs.ProgramsLogic(DATABASE, ACHIEVEMENTS, STATISTICS) + program_logic = programs.ProgramsLogic(DATABASE, ACHIEVEMENTS, FOR_TEACHERS) program = program_logic.store_user_program( user=current_user(), level=level, @@ -2797,7 +2797,7 @@ def current_user_allowed_to_see_program(program): app.register_blueprint(auth_pages.AuthModule(DATABASE)) app.register_blueprint(profile.ProfileModule(DATABASE)) -app.register_blueprint(programs.ProgramsModule(DATABASE, ACHIEVEMENTS, STATISTICS)) +app.register_blueprint(programs.ProgramsModule(DATABASE, ACHIEVEMENTS, FOR_TEACHERS)) app.register_blueprint(for_teachers.ForTeachersModule(DATABASE, ACHIEVEMENTS)) app.register_blueprint(classes.ClassModule(DATABASE, ACHIEVEMENTS)) app.register_blueprint(classes.MiscClassPages(DATABASE, ACHIEVEMENTS)) @@ -2807,7 +2807,6 @@ def current_user_allowed_to_see_program(program): app.register_blueprint(quiz.QuizModule(DATABASE, ACHIEVEMENTS, QUIZZES)) app.register_blueprint(parsons.ParsonsModule(PARSONS)) app.register_blueprint(statistics.StatisticsModule(DATABASE)) -app.register_blueprint(statistics.LiveStatisticsModule(DATABASE)) app.register_blueprint(user_activity.UserActivityModule(DATABASE)) app.register_blueprint(tags.TagsModule(DATABASE, ACHIEVEMENTS)) app.register_blueprint(public_adventures.PublicAdventuresModule(DATABASE, ACHIEVEMENTS)) diff --git a/build-tools/heroku/generate-client-messages.py b/build-tools/heroku/generate-client-messages.py index 9933cae2290..1c7dd98405f 100644 --- a/build-tools/heroku/generate-client-messages.py +++ b/build-tools/heroku/generate-client-messages.py @@ -25,7 +25,13 @@ 'disabled', 'adventures_restored', 'multiple_keywords_warning', - 'selected' + 'selected', + 'adventures_tried', + 'graph_title', + 'errors', + 'adventures_completed', + 'number_of_errors', + 'successful_runs' ] diff --git a/content/client-messages.txt b/content/client-messages.txt index be36dd58e44..1783ebf4b2d 100644 --- a/content/client-messages.txt +++ b/content/client-messages.txt @@ -7,4 +7,10 @@ gettext('directly_available') gettext('disabled') gettext('adventures_restored') gettext('multiple_keywords_warning') -gettext('selected') \ No newline at end of file +gettext('selected') +gettext('adventures_tried') +gettext('graph_title') +gettext('errors') +gettext('adventures_completed') +gettext('number_of_errors') +gettext('successful_runs') \ No newline at end of file diff --git a/messages.pot b/messages.pot index 978d00ece00..673ffbb3c43 100644 --- a/messages.pot +++ b/messages.pot @@ -176,9 +176,6 @@ msgstr "" msgid "add_students" msgstr "" -msgid "add_students_options" -msgstr "" - msgid "add_your_language" msgstr "" @@ -236,12 +233,18 @@ msgstr "" msgid "adventures" msgstr "" +msgid "adventures_completed" +msgstr "" + msgid "adventures_info" msgstr "" msgid "adventures_restored" msgstr "" +msgid "adventures_tried" +msgstr "" + msgid "ago" msgstr "" @@ -326,7 +329,7 @@ msgstr "" msgid "class_customize_success" msgstr "" -msgid "class_live" +msgid "class_graph_explanation" msgstr "" msgid "class_name_duplicate" @@ -341,7 +344,7 @@ msgstr "" msgid "class_name_prompt" msgstr "" -msgid "class_overview" +msgid "class_performance_graph" msgstr "" msgid "class_survey_description" @@ -614,6 +617,9 @@ msgstr "" msgid "error_logo_alt" msgstr "" +msgid "errors" +msgstr "" + msgid "exclamation mark" msgstr "" @@ -740,6 +746,9 @@ msgstr "" msgid "goto_profile" msgstr "" +msgid "graph_title" +msgstr "" + msgid "grid_overview" msgstr "" @@ -908,9 +917,6 @@ msgstr "" msgid "last_error" msgstr "" -msgid "last_login" -msgstr "" - msgid "last_program" msgstr "" @@ -1166,6 +1172,9 @@ msgstr "" msgid "number_lines" msgstr "" +msgid "number_of_errors" +msgstr "" + msgid "number_programs" msgstr "" @@ -1211,9 +1220,6 @@ msgstr "" msgid "owner" msgstr "" -msgid "page" -msgstr "" - msgid "page_not_found" msgstr "" @@ -1637,9 +1643,6 @@ msgstr "" msgid "student_details" msgstr "" -msgid "student_list" -msgstr "" - msgid "student_not_allowed_in_class" msgstr "" @@ -1676,6 +1679,9 @@ msgstr "" msgid "subscribe_newsletter" msgstr "" +msgid "successful_runs" +msgstr "" + msgid "suggestion_color" msgstr "" @@ -1757,12 +1763,6 @@ msgstr "" msgid "title_admin" msgstr "" -msgid "title_class grid_overview" -msgstr "" - -msgid "title_class live_statistics" -msgstr "" - msgid "title_class-overview" msgstr "" @@ -1934,6 +1934,9 @@ msgstr "" msgid "view_slides" msgstr "" +msgid "waiting_for_submit" +msgstr "" + msgid "walker_variable_role" msgstr "" diff --git a/package-lock.json b/package-lock.json index 6dd717bd960..3990d78904d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "@types/jqueryui": "^1.12.16", "autoprefixer": "^10.4.2", "chai-colors": "^1.0.1", - "chart.js": "^3.6.2", + "chart.js": "^4.4.2", "codemirror": "^6.0.1", "cypress-real-events": "^1.12.0", "dompurify": "^2.3.5", @@ -2486,6 +2486,11 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@kurkle/color": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz", + "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==" + }, "node_modules/@lezer/common": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.0.4.tgz", @@ -3434,9 +3439,15 @@ } }, "node_modules/chart.js": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.9.1.tgz", - "integrity": "sha512-Ro2JbLmvg83gXF5F4sniaQ+lTbSv18E+TIf2cOeiH1Iqd2PGFOtem+DUufMZsCJwFE7ywPOpfXFBwRTGq7dh6w==" + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.3.tgz", + "integrity": "sha512-qK1gkGSRYcJzqrrzdR6a+I0vQ4/R+SoODXyAjscQ/4mzuNzySaMCd+hyVxitSY1+L2fjPD1Gbn+ibNqRmwQeLw==", + "dependencies": { + "@kurkle/color": "^0.3.0" + }, + "engines": { + "pnpm": ">=8" + } }, "node_modules/chartjs-plugin-datalabels": { "version": "2.2.0", @@ -7369,6 +7380,11 @@ "tailwindcss": "3.3.0" } }, + "node_modules/tw-elements/node_modules/chart.js": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.9.1.tgz", + "integrity": "sha512-Ro2JbLmvg83gXF5F4sniaQ+lTbSv18E+TIf2cOeiH1Iqd2PGFOtem+DUufMZsCJwFE7ywPOpfXFBwRTGq7dh6w==" + }, "node_modules/tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", @@ -9710,6 +9726,11 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "@kurkle/color": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz", + "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==" + }, "@lezer/common": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.0.4.tgz", @@ -10456,9 +10477,12 @@ } }, "chart.js": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.9.1.tgz", - "integrity": "sha512-Ro2JbLmvg83gXF5F4sniaQ+lTbSv18E+TIf2cOeiH1Iqd2PGFOtem+DUufMZsCJwFE7ywPOpfXFBwRTGq7dh6w==" + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.3.tgz", + "integrity": "sha512-qK1gkGSRYcJzqrrzdR6a+I0vQ4/R+SoODXyAjscQ/4mzuNzySaMCd+hyVxitSY1+L2fjPD1Gbn+ibNqRmwQeLw==", + "requires": { + "@kurkle/color": "^0.3.0" + } }, "chartjs-plugin-datalabels": { "version": "2.2.0", @@ -13310,6 +13334,13 @@ "detect-autofill": "^1.1.3", "perfect-scrollbar": "^1.5.5", "tailwindcss": "3.3.0" + }, + "dependencies": { + "chart.js": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.9.1.tgz", + "integrity": "sha512-Ro2JbLmvg83gXF5F4sniaQ+lTbSv18E+TIf2cOeiH1Iqd2PGFOtem+DUufMZsCJwFE7ywPOpfXFBwRTGq7dh6w==" + } } }, "tweetnacl": { diff --git a/package.json b/package.json index 4a759b9c4d9..d2ceb62b1c3 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "@types/jqueryui": "^1.12.16", "autoprefixer": "^10.4.2", "chai-colors": "^1.0.1", - "chart.js": "^3.6.2", + "chart.js": "^4.4.2", "codemirror": "^6.0.1", "cypress-real-events": "^1.12.0", "dompurify": "^2.3.5", diff --git a/static/css/generated.full.css b/static/css/generated.full.css index 78172977cb0..ab7e4bbc7c9 100644 --- a/static/css/generated.full.css +++ b/static/css/generated.full.css @@ -8358,6 +8358,10 @@ code { height: 32px; } +.h-\[32rem\] { + height: 32rem; +} + .h-\[380px\] { height: 380px; } @@ -8612,10 +8616,6 @@ code { min-height: 1.5rem; } -.min-h-\[3\.5rem\] { - min-height: 3.5rem; -} - .min-h-\[305px\] { min-height: 305px; } @@ -16336,10 +16336,6 @@ code { grid-template-columns: 350px; } -.grid-cols-\[repeat\(3\2c _minmax\(25px\2c _1fr\)\)\] { - grid-template-columns: repeat(3, minmax(25px, 1fr)); -} - .grid-cols-none { grid-template-columns: none; } @@ -345059,21 +345055,11 @@ div[class^="ace_incorrect_hedy_code"] { border-radius: 9999px; } -.hover\:border-blue-300:hover { - --tw-border-opacity: 1; - border-color: rgb(144 205 244 / var(--tw-border-opacity)); -} - .hover\:border-blue-600:hover { --tw-border-opacity: 1; border-color: rgb(49 130 206 / var(--tw-border-opacity)); } -.hover\:border-green-400:hover { - --tw-border-opacity: 1; - border-color: rgb(104 211 145 / var(--tw-border-opacity)); -} - .hover\:\!bg-\[\#eee\]:hover { --tw-bg-opacity: 1 !important; background-color: rgb(238 238 238 / var(--tw-bg-opacity)) !important; @@ -345100,11 +345086,6 @@ div[class^="ace_incorrect_hedy_code"] { background-color: rgb(235 248 255 / var(--tw-bg-opacity)); } -.hover\:bg-blue-300:hover { - --tw-bg-opacity: 1; - background-color: rgb(144 205 244 / var(--tw-bg-opacity)); -} - .hover\:bg-blue-400:hover { --tw-bg-opacity: 1; background-color: rgb(99 179 237 / var(--tw-bg-opacity)); @@ -345115,25 +345096,10 @@ div[class^="ace_incorrect_hedy_code"] { background-color: rgb(49 130 206 / var(--tw-bg-opacity)); } -.hover\:bg-gray-300:hover { - --tw-bg-opacity: 1; - background-color: rgb(226 232 240 / var(--tw-bg-opacity)); -} - -.hover\:bg-gray-400:hover { - --tw-bg-opacity: 1; - background-color: rgb(203 213 224 / var(--tw-bg-opacity)); -} - .hover\:bg-gray-400\/50:hover { background-color: rgb(203 213 224 / 0.5); } -.hover\:bg-green-300:hover { - --tw-bg-opacity: 1; - background-color: rgb(154 230 180 / var(--tw-bg-opacity)); -} - .hover\:bg-green-400:hover { --tw-bg-opacity: 1; background-color: rgb(104 211 145 / var(--tw-bg-opacity)); @@ -346053,6 +346019,10 @@ div[class^="ace_incorrect_hedy_code"] { right: -0.25rem; } +:is([dir="ltr"] .ltr\:left-0) { + left: 0px; +} + :is([dir="ltr"] .ltr\:right-0) { right: 0px; } @@ -346139,10 +346109,6 @@ div[class^="ace_incorrect_hedy_code"] { padding-left: 2rem; } -:is([dir="ltr"] .ltr\:pr-4) { - padding-right: 1rem; -} - :is([dir="ltr"] .ltr\:pr-8) { padding-right: 2rem; } @@ -346175,6 +346141,10 @@ div[class^="ace_incorrect_hedy_code"] { left: 0px; } +:is([dir="rtl"] .rtl\:right-0) { + right: 0px; +} + :is([dir="rtl"] .rtl\:clear-left) { clear: left; } @@ -346247,10 +346217,6 @@ div[class^="ace_incorrect_hedy_code"] { --tw-divide-x-reverse: 1; } -:is([dir="rtl"] .rtl\:pl-4) { - padding-left: 1rem; -} - :is([dir="rtl"] .rtl\:pl-8) { padding-left: 2rem; } diff --git a/static/js/app.ts b/static/js/app.ts index e0c0ab47fb5..47441900638 100644 --- a/static/js/app.ts +++ b/static/js/app.ts @@ -369,8 +369,8 @@ export function initializeViewProgramPage(options: InitializeViewProgramPageOpti }); } -export function initializeHighlightedCodeBlocks(where: Element) { - const dir = $('body').attr('dir'); +export function initializeHighlightedCodeBlocks(where: Element, initializeAll?: boolean) { + const dir = $("body").attr("dir"); initializeParsons(); if (theLevel) { initializeTranslation({ @@ -386,55 +386,63 @@ export function initializeHighlightedCodeBlocks(where: Element) { .addClass('relative text-lg rounded overflow-x-hidden') // We set the language of the editor to the current keyword_language -> needed when copying to main editor .attr('lang', theKeywordLanguage); - - // Only turn into an editor if the editor scrolls into view - // Otherwise, the teacher manual Frequent Mistakes page is SUPER SLOW to load. - onElementBecomesVisible(preview, () => { - const codeNode = preview.querySelector('code') - let code: string; - // In case it has a child node - if(codeNode) { - codeNode.hidden = true - code = codeNode.innerText + // If the request comes from HTMX initialize all directly + if (initializeAll) { + convertPreviewToEditor(preview, container, dir) } else { - code = preview.textContent || ""; - preview.textContent = ""; - } + // Only turn into an editor if the editor scrolls into view + // Otherwise, the teacher manual Frequent Mistakes page is SUPER SLOW to load. + onElementBecomesVisible(preview, () => { + convertPreviewToEditor(preview, container, dir) + }); + } + } + } +} - // Create this example editor - const exampleEditor = editorCreator.initializeReadOnlyEditor(preview, dir); - // Strip trailing newline, it renders better - exampleEditor.contents = code; - exampleEditor.contents = exampleEditor.contents.trimEnd(); - // And add an overlay button to the editor if requested via a show-copy-button class, either - // on the
 itself OR on the element that has the '.turn-pre-into-ace' class.
-        if ($(preview).hasClass('show-copy-button') || $(container).hasClass('show-copy-button')) {
-          const buttonContainer = $('
').addClass('absolute ltr:right-0 rtl:left-0 top-0 mx-1 mt-1').appendTo(preview); - let symbol = "⇥"; - if (dir === "rtl") { - symbol = "⇤"; - } - const adventure = container.getAttribute('data-tabtarget') - $('