From 3a4d0d14fc1701adf1d7e1fc1d2f866c0fb23a88 Mon Sep 17 00:00:00 2001 From: mikaelGusse Date: Thu, 15 Aug 2024 14:17:14 +0300 Subject: [PATCH] Added remove option for personalized points goals and fixed issues from review --- e2e_tests/test_points_goal_set.py | 2 + .../exercise/personalized_points_goal.js | 65 ++++++++++++++++++- .../templates/exercise/_points_progress.html | 2 +- .../personalized_points_goal_modal.html | 28 ++++++-- exercise/urls.py | 3 + exercise/views.py | 13 ++++ locale/en/LC_MESSAGES/django.po | 29 +++++---- locale/fi/LC_MESSAGES/django.po | 19 ++++-- 8 files changed, 136 insertions(+), 25 deletions(-) diff --git a/e2e_tests/test_points_goal_set.py b/e2e_tests/test_points_goal_set.py index 3ce3dd01f..8d8aa9ad0 100644 --- a/e2e_tests/test_points_goal_set.py +++ b/e2e_tests/test_points_goal_set.py @@ -1,6 +1,8 @@ from playwright.sync_api import Page, expect + from e2e_tests.helpers import login + def test_points_goal_set(page: Page) -> None: login(page, "student", "student") diff --git a/exercise/static/exercise/personalized_points_goal.js b/exercise/static/exercise/personalized_points_goal.js index e875518c2..fb338be80 100644 --- a/exercise/static/exercise/personalized_points_goal.js +++ b/exercise/static/exercise/personalized_points_goal.js @@ -1,8 +1,24 @@ $(document).ready(function() { const $pointsGoalForm = $('#pointsGoalForm'); - document.getElementById('id_personalized_points_goal_input').focus(); + const $inputField = $('#id_personalized_points_goal_input'); + $inputField.focus(); $pointsGoalForm.on('submit', function(event) { event.preventDefault(); + + // Validate input + const inputValue = $inputField.val().trim(); + + const isNumber = !isNaN(inputValue) && inputValue !== ''; + const isPercentage = inputValue.endsWith('%') && !isNaN(inputValue.slice(0, -1)); + + if (!isNumber && !isPercentage) { + $('#validation-alert').show(); + setTimeout(function() { + $('#validation-errors-alert').hide(); + }, 5000); + return; + } + $.ajax({ type: 'POST', url: $pointsGoalForm.attr('action'), @@ -39,7 +55,7 @@ $(document).ready(function() { // If the span element does not exist, create it if (spanElement == null) { spanElement = doc.createElement('span'); - spanElement.className = 'personalized-points-text text-nowrap'; + spanElement.className = 'personalized-points-full-text text-nowrap'; doc.body.appendChild(spanElement); spanElement.innerHTML = "
" + $pointsGoalForm.data('personalized-points-goal-tooltip-text') + ": " + response.personalized_points_goal_points; } @@ -82,4 +98,49 @@ $(document).ready(function() { } }); }); + $('#deletePointsGoalForm').on('submit', function(event) { + event.preventDefault(); + + $.ajax({ + type: 'POST', + url: $(this).attr('action'), + data: $(this).serialize() + '&delete=true', + success: function(response) { + // Update page dynamically + const $progressElement = $('#progress-' + $pointsGoalForm.data('module-url')); + const $progressDiv = $progressElement.find('.progress'); + + // Remove goal indicator + let $goalPointsElement = $progressElement.find('.goal-points'); + $goalPointsElement.removeClass('goal-points'); + + // Update tooltip + const tooltipTitle = $progressDiv.attr('data-original-title'); + const parser = new DOMParser(); + const doc = parser.parseFromString(tooltipTitle, 'text/html'); + + let spanElement = doc.querySelector('span.personalized-points-full-text'); + spanElement.remove(); + + const updatedTooltipTitle = doc.body.innerHTML; + $progressDiv.attr('data-original-title', updatedTooltipTitle); + + // Update progress-bar style + $progressDiv.find('.progress-bar').removeClass('progress-bar-primary'); + + $('#remove-success-alert').show(); + setTimeout(function() { + $('#remove-success-alert').hide(); + }, 5000); + + }, + error: function(xhr, status, error) { + // Handle error response + $('#remove-warning-alert').show(); + setTimeout(function() { + $('#remove-warning-alert').hide(); + }, 5000); + } + }); + }); }); diff --git a/exercise/templates/exercise/_points_progress.html b/exercise/templates/exercise/_points_progress.html index fea3fda0b..154f7987e 100644 --- a/exercise/templates/exercise/_points_progress.html +++ b/exercise/templates/exercise/_points_progress.html @@ -9,7 +9,7 @@
+ -

{% translate "PERSONALIZED_POINTS_MODAL_TITLE" %} {{ module.name|parse_localization}}

+ + +

{% translate "PERSONALIZED_POINTS_MODAL_TITLE" %} "{{ module.name|parse_localization}}"

-
- -
+
+ +
+ {% csrf_token %} + +
+
+ diff --git a/exercise/urls.py b/exercise/urls.py index 94a927d1f..82fcb6458 100644 --- a/exercise/urls.py +++ b/exercise/urls.py @@ -86,6 +86,9 @@ re_path(MODULE_URL_PREFIX + r'save_points_goal_form/$', views.StudentModuleGoalFormView.as_view(), name="save_points_goal_form_view"), + re_path(MODULE_URL_PREFIX + r'delete_points_goal_form/$', + views.StudentModuleGoalFormView.as_view(), + name="delete_points_goal_form_view"), re_path(EDIT_URL_PREFIX + r'analytics/$', staff_views.AnalyticsView.as_view(), diff --git a/exercise/views.py b/exercise/views.py index 581036997..5117bf3d7 100644 --- a/exercise/views.py +++ b/exercise/views.py @@ -619,6 +619,19 @@ def post(self, request: HttpRequest, *args: Any, **kwargs: Any) -> JsonResponse: user_id = request.user.id module_slug = self.kwargs['module_slug'] points_goal = request.POST.get('personalized_points_goal_input') + delete = request.POST.get('delete') + + if delete: + student = UserProfile.objects.get(id=user_id) + module = CourseModule.objects.get(url=module_slug) + try: + StudentModuleGoal.objects.get(student=user_id, module=module.id).delete() + cached_points = CachedPoints(module.course_instance, student, True) + cached_module, _, _, _ = cached_points.find(module) + cached_points.invalidate(module.course_instance, student) + return JsonResponse({"success": "deleted"}, status=200) + except Exception as e: + return JsonResponse({"error": e}, status=404) if not points_goal.replace('%', '').isdigit() and not points_goal.isdigit(): return JsonResponse({"error": "not_a_number"}, status=400) diff --git a/locale/en/LC_MESSAGES/django.po b/locale/en/LC_MESSAGES/django.po index 5a2a81f30..040d985ed 100644 --- a/locale/en/LC_MESSAGES/django.po +++ b/locale/en/LC_MESSAGES/django.po @@ -1259,33 +1259,40 @@ msgstr "Points goal" #: exercise/templates/exercise/_user_results.html msgid "POINTS_GOAL_TOOLTIP" -msgstr "Set a personal points goal for this module. This goal is only visible to you. Once the goal has been reached, the points progress bar changes color to blue." +msgstr "Set a personal points goal for this module. This goal is only visible to you. Once the goal has been reached, the points progress bar changes colour to blue." -#: exercise/templates/exercise/save_personalized_points_goal.html +#: exercise/templates/exercise/personalized_points_goal_modal.html msgid "PERSONALIZED_POINTS_MODAL_TITLE" msgstr "Set personalized points goal for module" -#: exercise/templates/exercise/save_personalized_points_goal.html +#: exercise/templates/exercise/personalized_points_goal_modal.html msgid "LABEL_POINTS_GOAL_INPUT" -msgstr "Input personalized goal as percentage or points (e.g., 50% or 150)" +msgstr "Input personalized goal as a percentage or points (e.g., 50% or 150)" -#: exercise/templates/exercise/save_personalized_points_goal.html -msgid "REQUIRED_POINTS" -msgstr "Points required to pass for module" - -#: exercise/templates/exercise/save_personalized_points_goal.html +#: exercise/templates/exercise/personalized_points_goal_modal.html msgid "PERSONALIZED_POINTS_MODAL_SUCCESS" msgstr "Succesfully set personalized points goal" -#: exercise/templates/exercise/save_personalized_points_goal.html +#: exercise/templates/exercise/personalized_points_goal_modal.html msgid "PERSONALIZED_POINTS_MODAL_FAILURE" msgstr "Failed to set personalized points goal" +#: exercise/templates/exercise/personalized_points_goal_modal.html +msgid "PERSONALIZED_POINTS_MODAL_NOT_NUMBER" +msgstr "Input needs to be a percentage or a number (e.g., 50% or 150)" + msgid "PERSONALIZED_POINTS_GOAL" msgstr "Points goal" msgid "PERSONALIZED_POINTS_MODAL_LESS_THAN_REQUIRED" -msgstr "You cannot set the personalized points goal to be less than the points required to pass" +msgstr "You cannot set the personalized points goal to be less than the points required to pass the module" + +msgid "PERSONALIZED_POINTS_MODAL_REMOVE_SUCCESS" +msgstr "Succesfully removed personalized points goal" + +msgid "PERSONALIZED_POINTS_MODAL_REMOVE_FAILURE" +msgstr "Failed to remove personalized points goal" + #: course/templates/course/staff/_tag_remove_modal.html msgid "UNTAG_MULTIPLE_USERS" diff --git a/locale/fi/LC_MESSAGES/django.po b/locale/fi/LC_MESSAGES/django.po index 6ba86de75..d9179dc9e 100644 --- a/locale/fi/LC_MESSAGES/django.po +++ b/locale/fi/LC_MESSAGES/django.po @@ -763,11 +763,6 @@ msgstr "Aseta pistetavoite moduulille" msgid "LABEL_POINTS_GOAL_INPUT" msgstr "Anna pistetavoite prosentteina tai pisteinä (esim. 50% tai 150)" -#: exercise/templates/exercise/personalized_points_goal_modal.html -#: exercise/templates/exercise/_user_results.html -msgid "REQUIRED_POINTS" -msgstr "Vaaditut pisteet" - #: exercise/templates/exercise/personalized_points_goal_modal.html msgid "PERSONALIZED_POINTS_MODAL_SUCCESS" msgstr "Pistetavoite asetettu onnistuneesti" @@ -776,11 +771,21 @@ msgstr "Pistetavoite asetettu onnistuneesti" msgid "PERSONALIZED_POINTS_MODAL_FAILURE" msgstr "Pistetavoitteen asettaminen epäonnistui" +#: exercise/templates/exercise/personalized_points_goal_modal.html +msgid "PERSONALIZED_POINTS_MODAL_NOT_NUMBER" +msgstr "Pistetavoite tulee antaa joko prosentteina tai pisteinä (esim. 50% or 150)" + msgid "PERSONALIZED_POINTS_GOAL" msgstr "Pistetavoite" msgid "PERSONALIZED_POINTS_MODAL_LESS_THAN_REQUIRED" -msgstr "Pistetavoite ei voi olla vähemmän kuin läpipääsyyn vaaditut pisteet" +msgstr "Pistetavoite ei voi olla vähemmän kuin moduulin läpipääsyyn vaaditut pisteet" + +msgid "PERSONALIZED_POINTS_MODAL_REMOVE_SUCCESS" +msgstr "Pistetavoite poistettu onnistuneesti" + +msgid "PERSONALIZED_POINTS_MODAL_REMOVE_FAILURE" +msgstr "Pistetavoitteen poistaminen epäonnistui" #: course/models.py msgid "LABEL_MODEL_ANSWER" @@ -4478,7 +4483,7 @@ msgstr "Aloita uudelleenarviointi" #: exercise/templates/exercise/staff/_resubmit_modal.html msgid "RE-SUBMIT_TO_SERVICE" -msgstr "Lähetä arvosteltavaksi uudelleen"#: exercise/templates/exercise/_user_results.html +msgstr "Lähetä arvosteltavaksi uudelleen" #: exercise/templates/exercise/staff/_resubmit_modal.html msgid "RE-SUBMIT_TO_SERVICE_DESCRIPTION"