From 2884cc5cdc1c27b659b9bcadab553eaff3b95b80 Mon Sep 17 00:00:00 2001 From: Muhammad Afaq Shuaib Date: Mon, 3 Feb 2025 17:30:47 +0500 Subject: [PATCH] style: add bootstrap styling to tagging app (#4551) --- .../apps/tagging/context_processors.py | 10 ++ .../tests/test_update_course_verticals.py | 2 +- course_discovery/apps/tagging/mixins.py | 23 ++-- .../templates/partials/course_table.html | 71 ++++++------ .../apps/tagging/templates/tagging/base.html | 56 ++++++---- .../templates/tagging/course_list.html | 2 +- .../tagging/course_tagging_detail.html | 44 +++++--- .../tagging/sub_vertical_detail.html | 33 ++++-- .../templates/tagging/sub_vertical_list.html | 9 +- .../templates/tagging/vertical_detail.html | 105 +++++++++++++----- .../templates/tagging/vertical_list.html | 8 +- .../apps/tagging/tests/test_mixins.py | 7 +- .../apps/tagging/tests/test_views.py | 2 +- course_discovery/apps/tagging/views.py | 10 +- course_discovery/settings/base.py | 5 +- course_discovery/static/css/tagging.css | 31 ++++++ requirements/base.in | 1 - requirements/local.txt | 2 - requirements/production.txt | 2 - 19 files changed, 283 insertions(+), 140 deletions(-) create mode 100644 course_discovery/apps/tagging/context_processors.py create mode 100644 course_discovery/static/css/tagging.css diff --git a/course_discovery/apps/tagging/context_processors.py b/course_discovery/apps/tagging/context_processors.py new file mode 100644 index 0000000000..bbfa2c9ee1 --- /dev/null +++ b/course_discovery/apps/tagging/context_processors.py @@ -0,0 +1,10 @@ +from django.conf import settings + + +def tagging(request): + """ + Add some constants to the context. + """ + return { + 'HEADER_LOGO_URL': settings.HEADER_LOGO_URL, + } diff --git a/course_discovery/apps/tagging/management/commands/tests/test_update_course_verticals.py b/course_discovery/apps/tagging/management/commands/tests/test_update_course_verticals.py index e1a209af92..6dfdbc2f8e 100644 --- a/course_discovery/apps/tagging/management/commands/tests/test_update_course_verticals.py +++ b/course_discovery/apps/tagging/management/commands/tests/test_update_course_verticals.py @@ -35,7 +35,7 @@ def setUp(self): def build_csv(self, rows): csv_file_content = "course,vertical,subvertical\n" for row in rows: - row_content = f"{row["course"]},{row["vertical"]},{row["subvertical"]}\n" + row_content = f'{row["course"]},{row["vertical"]},{row["subvertical"]}\n' csv_file_content += row_content csv_file = SimpleUploadedFile( diff --git a/course_discovery/apps/tagging/mixins.py b/course_discovery/apps/tagging/mixins.py index 04a0635516..4fd1a87630 100644 --- a/course_discovery/apps/tagging/mixins.py +++ b/course_discovery/apps/tagging/mixins.py @@ -1,23 +1,18 @@ from django.conf import settings -from django.contrib.auth.mixins import LoginRequiredMixin -from django.core.exceptions import PermissionDenied +from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin -class VerticalTaggingAdministratorPermissionRequiredMixin(LoginRequiredMixin): +class VerticalTaggingAdministratorPermissionRequiredMixin( + LoginRequiredMixin, UserPassesTestMixin +): """ A mixin to enforce permission on VERTICALS_MANAGEMENT_GROUPS for class-based views. """ - def dispatch(self, request, *args, **kwargs): - response = super().dispatch(request, *args, **kwargs) - if response.status_code == 403: - return response - - in_vertical_management_group = request.user.groups.filter( + def test_func(self): + """ + Check if the user is in the VERTICALS_MANAGEMENT_GROUPS group or is a superuser. + """ + return self.request.user.is_superuser or self.request.user.groups.filter( name__in=settings.VERTICALS_MANAGEMENT_GROUPS ).exists() - - if not request.user.is_superuser and not in_vertical_management_group: - raise PermissionDenied("You do not have permission to access this page.") - - return response diff --git a/course_discovery/apps/tagging/templates/partials/course_table.html b/course_discovery/apps/tagging/templates/partials/course_table.html index c164032c75..e58e2f340d 100644 --- a/course_discovery/apps/tagging/templates/partials/course_table.html +++ b/course_discovery/apps/tagging/templates/partials/course_table.html @@ -74,36 +74,43 @@ {% if is_paginated %} - -{% endif %} + +{% endif %} diff --git a/course_discovery/apps/tagging/templates/tagging/base.html b/course_discovery/apps/tagging/templates/tagging/base.html index 59f357ea88..7e0c6a21b4 100644 --- a/course_discovery/apps/tagging/templates/tagging/base.html +++ b/course_discovery/apps/tagging/templates/tagging/base.html @@ -1,3 +1,4 @@ +{% load static %} @@ -7,31 +8,48 @@ + + + - +
{% block content %} diff --git a/course_discovery/apps/tagging/templates/tagging/course_list.html b/course_discovery/apps/tagging/templates/tagging/course_list.html index b7474dcd98..f6cb8d5f03 100644 --- a/course_discovery/apps/tagging/templates/tagging/course_list.html +++ b/course_discovery/apps/tagging/templates/tagging/course_list.html @@ -1,7 +1,7 @@ {% extends "tagging/base.html" %} {% block content %} -
+

Courses

diff --git a/course_discovery/apps/tagging/templates/tagging/course_tagging_detail.html b/course_discovery/apps/tagging/templates/tagging/course_tagging_detail.html index 758f194535..844a0c9571 100644 --- a/course_discovery/apps/tagging/templates/tagging/course_tagging_detail.html +++ b/course_discovery/apps/tagging/templates/tagging/course_tagging_detail.html @@ -1,19 +1,29 @@ {% extends "tagging/base.html" %} {% block content %} -
-

Course: {{ course.title }}

-

Key: {{ course.key }}

+
+
+
+
+

Course: {{ course.title }}

+

Key: {{ course.key }}

+
+
+
-

Assign or Edit Vertical and Sub-Vertical

- - {% csrf_token %} +
+
+

Assign or Edit Vertical and Sub-Vertical

+
+
+ + {% csrf_token %} -
- +
+
-
- +
+
- +
+ + +
+
{% endblock %} diff --git a/course_discovery/apps/tagging/templates/tagging/vertical_list.html b/course_discovery/apps/tagging/templates/tagging/vertical_list.html index d693e547ee..167e5b6926 100644 --- a/course_discovery/apps/tagging/templates/tagging/vertical_list.html +++ b/course_discovery/apps/tagging/templates/tagging/vertical_list.html @@ -2,10 +2,11 @@ {% block content %}
-

Verticals List

- - +

Verticals

+
+ + {% for vertical in verticals %} +
# Vertical Name @@ -20,6 +21,7 @@

Verticals List

{{ forloop.counter }} {{ vertical.name }} diff --git a/course_discovery/apps/tagging/tests/test_mixins.py b/course_discovery/apps/tagging/tests/test_mixins.py index f88eeecbd1..86d1df94e2 100644 --- a/course_discovery/apps/tagging/tests/test_mixins.py +++ b/course_discovery/apps/tagging/tests/test_mixins.py @@ -35,15 +35,14 @@ def test_user_not_authenticated(self): request = self.factory.get("/") request.user = AnonymousUser() - with self.assertRaisesMessage(PermissionDenied, "You do not have permission to access this page."): - self.view(request) + response = self.view(request) + self.assertEqual(response.status_code, 302) def test_regular_user(self): """Test that users not in the allowed group or superuser are forbidden.""" request = self.factory.get("/") request.user = self.regular_user - - with self.assertRaisesMessage(PermissionDenied, "You do not have permission to access this page."): + with self.assertRaises(PermissionDenied): self.view(request) def test_user_in_allowed_group(self): diff --git a/course_discovery/apps/tagging/tests/test_views.py b/course_discovery/apps/tagging/tests/test_views.py index 973195038b..104ad9e481 100644 --- a/course_discovery/apps/tagging/tests/test_views.py +++ b/course_discovery/apps/tagging/tests/test_views.py @@ -48,7 +48,7 @@ def test_post_valid_vertical_assignment(self): } response = self.client.post(self.url, data=mock_response_data) self.assertEqual(response.status_code, 200) - self.assertContains(response, "Vertical and Sub-Vertical assigned successfully.") + self.assertContains(response, "Course Vertical added successfully.") course_vertical = CourseVertical.objects.get(course=self.course) self.assertEqual(course_vertical.vertical, self.vertical) diff --git a/course_discovery/apps/tagging/views.py b/course_discovery/apps/tagging/views.py index 28b3bf0ffb..d478491fb2 100644 --- a/course_discovery/apps/tagging/views.py +++ b/course_discovery/apps/tagging/views.py @@ -38,13 +38,13 @@ def post(self, request, uuid): }, request) return HttpResponse(html, status=200) - CourseVertical.objects.update_or_create( + _, created = CourseVertical.objects.update_or_create( course=course, defaults={"vertical": vertical, "sub_vertical": sub_vertical} ) html = render_to_string("partials/message.html", { - "success": "Vertical and Sub-Vertical assigned successfully." + "success": "Course Vertical added successfully." if created else "Course Vertical updated successfully." }, request) return HttpResponse(html, status=200) @@ -80,8 +80,14 @@ def get_queryset(self): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) + + paginator = context["paginator"] + page_obj = context["page_obj"] + context["elided_page_range"] = paginator.get_elided_page_range(page_obj.number, on_each_side=1, on_ends=1) + context['current_sort'] = self.request.GET.get('sort', 'title') context['current_direction'] = self.request.GET.get('direction', 'asc') + return context def render_to_response(self, context, **response_kwargs): diff --git a/course_discovery/settings/base.py b/course_discovery/settings/base.py index e4abde9a1e..bb8acf77c1 100644 --- a/course_discovery/settings/base.py +++ b/course_discovery/settings/base.py @@ -68,7 +68,6 @@ 'nested_admin', 'openedx_events', 'multi_email_field', - 'django_htmx', ] ALGOLIA = { @@ -121,7 +120,6 @@ 'edx_django_utils.cache.middleware.TieredCacheMiddleware', 'edx_rest_framework_extensions.middleware.RequestMetricsMiddleware', 'edx_rest_framework_extensions.auth.jwt.middleware.EnsureJWTAuthSettingsMiddleware', - 'django_htmx.middleware.HtmxMiddleware', ) ROOT_URLCONF = 'course_discovery.urls' @@ -257,6 +255,7 @@ 'django.template.context_processors.tz', 'django.template.context_processors.request', 'django.contrib.messages.context_processors.messages', + 'course_discovery.apps.tagging.context_processors.tagging', 'course_discovery.apps.core.context_processors.core', ), 'debug': True, # Django will only display debug pages if the global DEBUG setting is set to True. @@ -265,7 +264,6 @@ ] # END TEMPLATE CONFIGURATION - # COOKIE CONFIGURATION # The purpose of customizing the cookie names is to avoid conflicts when # multiple Django services are running behind the same hostname. @@ -808,3 +806,4 @@ VERTICALS_MANAGEMENT_GROUPS = [] COURSE_VERTICALS_UPDATE_RECIPIENTS = ['user@domain.org'] +HEADER_LOGO_URL= 'https://edx-cdn.org/v3/default/logo.svg' diff --git a/course_discovery/static/css/tagging.css b/course_discovery/static/css/tagging.css new file mode 100644 index 0000000000..d2b45e8d0a --- /dev/null +++ b/course_discovery/static/css/tagging.css @@ -0,0 +1,31 @@ +.site-header .active { + border-bottom: 2px solid #454545; +} +.page-link { + color: #00262b; + transition: color 0.3s ease; +} +.page-link:hover { + color: #00404a; + background: floralwhite !important; +} +.active > .page-link, +.page-link.active { + border-color: #00262b; + background-color: #00262b; +} +.active-link { + background-color: #00404a !important; +} +.btn-primary { + background-color: #00262b !important; + transition: background-color 0.3s ease; + border: 1px solid #00262b; +} +.btn-primary:hover { + background-color: #00404a !important; + border: 1px solid #00404a; +} +a { + color: #00404a; +} diff --git a/requirements/base.in b/requirements/base.in index f7fa2dc227..e28c73844f 100644 --- a/requirements/base.in +++ b/requirements/base.in @@ -80,4 +80,3 @@ xss-utils taxonomy-connector importlib-metadata snowflake-connector-python -django-htmx diff --git a/requirements/local.txt b/requirements/local.txt index 97160bca45..7a0a857c25 100644 --- a/requirements/local.txt +++ b/requirements/local.txt @@ -266,8 +266,6 @@ django-fsm==3.0.0 # via -r requirements/base.in django-guardian==2.4.0 # via -r requirements/base.in -django-htmx==1.21.0 - # via -r requirements/base.in django-libsass==0.9 # via -r requirements/base.in django-localflavor==4.0 diff --git a/requirements/production.txt b/requirements/production.txt index 7812adb7bb..2a47e600ce 100644 --- a/requirements/production.txt +++ b/requirements/production.txt @@ -204,8 +204,6 @@ django-fsm==3.0.0 # via -r requirements/base.in django-guardian==2.4.0 # via -r requirements/base.in -django-htmx==1.21.0 - # via -r requirements/base.in django-libsass==0.9 # via -r requirements/base.in django-localflavor==4.0