Skip to content

Commit

Permalink
style: add bootstrap styling to tagging app (#4551)
Browse files Browse the repository at this point in the history
  • Loading branch information
AfaqShuaib09 authored Feb 3, 2025
1 parent d502b8c commit 2884cc5
Show file tree
Hide file tree
Showing 19 changed files with 283 additions and 140 deletions.
10 changes: 10 additions & 0 deletions course_discovery/apps/tagging/context_processors.py
Original file line number Diff line number Diff line change
@@ -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,
}
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
23 changes: 9 additions & 14 deletions course_discovery/apps/tagging/mixins.py
Original file line number Diff line number Diff line change
@@ -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
71 changes: 39 additions & 32 deletions course_discovery/apps/tagging/templates/partials/course_table.html
Original file line number Diff line number Diff line change
Expand Up @@ -74,36 +74,43 @@
</table>

{% if is_paginated %}
<nav>
<ul class="pagination">
{% if page_obj.has_previous %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.previous_page_number }}&search={{ request.GET.search|default:'' }}&sort={{ current_sort }}&direction={{ current_direction }}"
hx-get="?page={{ page_obj.previous_page_number }}&search={{ request.GET.search|default:'' }}&sort={{ current_sort }}&direction={{ current_direction }}"
hx-target="#course-table">
&laquo;
</a>
</li>
{% endif %}
{% for page_num in paginator.page_range %}
<li class="page-item {% if page_obj.number == page_num %}active{% endif %}">
<a class="page-link" href="?page={{ page_num }}&search={{ request.GET.search|default:'' }}&sort={{ current_sort }}&direction={{ current_direction }}"
hx-get="?page={{ page_num }}&search={{ request.GET.search|default:'' }}&sort={{ current_sort }}&direction={{ current_direction }}"
hx-target="#course-table">
{{ page_num }}
</a>
</li>
{% endfor %}
{% if page_obj.has_next %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.next_page_number }}&search={{ request.GET.search|default:'' }}&sort={{ current_sort }}&direction={{ current_direction }}"
hx-get="?page={{ page_obj.next_page_number }}&search={{ request.GET.search|default:'' }}&sort={{ current_sort }}&direction={{ current_direction }}"
hx-target="#course-table">
&raquo;
</a>
</li>
{% endif %}
</ul>
</nav>
{% endif %}
<nav>
<ul class="pagination">
{% if page_obj.has_previous %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.previous_page_number }}&search={{ request.GET.search|default:'' }}&sort={{ current_sort }}&direction={{ current_direction }}"
hx-get="?page={{ page_obj.previous_page_number }}&search={{ request.GET.search|default:'' }}&sort={{ current_sort }}&direction={{ current_direction }}"
hx-target="#course-table">
&laquo;
</a>
</li>
{% endif %}

{% for page_num in elided_page_range %}
{% if page_num == "..." %}
<li class="page-item disabled">
<span class="page-link">...</span>
</li>
{% else %}
<li class="page-item {% if page_obj.number == page_num %}active{% endif %}">
<a class="page-link" href="?page={{ page_num }}&search={{ request.GET.search|default:'' }}&sort={{ current_sort }}&direction={{ current_direction }}"
hx-get="?page={{ page_num }}&search={{ request.GET.search|default:'' }}&sort={{ current_sort }}&direction={{ current_direction }}"
hx-target="#course-table">
{{ page_num }}
</a>
</li>
{% endif %}
{% endfor %}

{% if page_obj.has_next %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.next_page_number }}&search={{ request.GET.search|default:'' }}&sort={{ current_sort }}&direction={{ current_direction }}"
hx-get="?page={{ page_obj.next_page_number }}&search={{ request.GET.search|default:'' }}&sort={{ current_sort }}&direction={{ current_direction }}"
hx-target="#course-table">
&raquo;
</a>
</li>
{% endif %}
</ul>
</nav>
{% endif %}
56 changes: 37 additions & 19 deletions course_discovery/apps/tagging/templates/tagging/base.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
Expand All @@ -7,31 +8,48 @@
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css" rel="stylesheet">
<script src="https://unpkg.com/htmx.org"></script>
<link href="{% static 'css/tagging.css' %}" rel="stylesheet">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<header class="site-header mb-3 py-3 border-bottom border-gray-300">
<div class="container">
<a class="navbar-brand" href="{% url 'tagging:course_list' %}">Course Tagging</a>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav me-auto">
<li class="nav-item">
<a class="nav-link" href="{% url 'tagging:vertical_list' %}">Verticals</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'tagging:sub_vertical_list' %}">Sub-Verticals</a>
</li>
</ul>
<ul class="navbar-nav mr-10">
{% if user.is_authenticated %}
<li class="nav-item">
<a class="nav-link text-light" href="#">{{ user.username }}</a>
</li>
{% endif %}
</ul>
<div class="d-flex justify-content-between align-items-center">
<div class="d-flex align-items-center">
<a class="navbar-brand" href="{% url 'tagging:course_list' %}">
<img src="{{ HEADER_LOGO_URL }}" alt="header logo" height="30" class="d-inline-block align-middle" />
<span class="fw-bold ml-2 me-3">Course Tagging</span>
</a>
<nav class="navbar navbar-expand-lg">
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item {% if request.resolver_match.url_name == 'vertical_list' %}active{% endif %}">
<a class="nav-link" href="{% url 'tagging:vertical_list' %}">Verticals</a>
</li>
<li class="nav-item {% if request.path == '/tagging/sub_verticals/' %}active{% endif %}">
<a class="nav-link" href="{% url 'tagging:sub_vertical_list' %}">Sub-Verticals</a>
</li>
</ul>
</div>
</nav>
</div>

<div class="d-flex align-items-center">
<div class="dropdown">

<button class="btn btn-link dropdown-toggle" type="button" id="dropdownMenuButton" data-bs-toggle="dropdown" aria-expanded="false" style="text-decoration: none; color: #454545;">
<i class="bi bi-person-circle fs-4 me-2"></i> <span class="fs-5">{{ user.username }}</span>
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenuButton">
<li><a class="dropdown-item" href="{% url 'logout' %}">Sign Out</a></li>
</ul>
</div>
</div>
</div>
</div>
</nav>
</header>

<main class="py-4">
{% block content %}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{% extends "tagging/base.html" %}

{% block content %}
<div class="container mt-5">
<div class="container mt-4">
<h1 class="mb-4">Courses</h1>

<form method="get" class="mb-4" hx-get="{% url 'tagging:course_list' %}" hx-target="#course-table" hx-trigger="keyup changed delay:500ms from:search">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
{% extends "tagging/base.html" %}

{% block content %}
<div class="container mt-5">
<h1 class="mb-4">Course: {{ course.title }}</h1>
<h2>Key: {{ course.key }}</h2>
<div class="container">
<div class="my-5">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<h2 class="mb-0">Course: {{ course.title }}</h2>
<h3 class="mb-0">Key: {{ course.key }}</h3>
</div>
</div>
</div>

<h3>Assign or Edit Vertical and Sub-Vertical</h3>
<form method="post" action=""
hx-post=""
hx-target="#message-container"
hx-swap="innerHTML">
{% csrf_token %}
<div class="card">
<div class="card-header">
<h3>Assign or Edit Vertical and Sub-Vertical</h3>
</div>
<div class="card-body">
<form method="post" action=""
hx-post=""
hx-target="#message-container"
hx-swap="innerHTML">
{% csrf_token %}

<div class="form-group">
<label for="vertical">Vertical</label>
<div class="form-group mb-3">
<label for="vertical" class="py-2">Vertical</label>
<select name="vertical" id="vertical" class="form-control"
hx-trigger="change"
hx-on="change: filterSubVerticals(event)">
Expand All @@ -27,8 +37,8 @@ <h3>Assign or Edit Vertical and Sub-Vertical</h3>
</select>
</div>

<div class="form-group">
<label for="sub_vertical">Sub-Vertical</label>
<div class="form-group mb-3">
<label for="sub_vertical" class="py-2">Sub-Vertical</label>
<select name="sub_vertical" id="sub_vertical" class="form-control">
<option value="">Select Sub-Vertical</option>
{% for sub_vertical in all_sub_verticals %}
Expand All @@ -47,12 +57,18 @@ <h3>Assign or Edit Vertical and Sub-Vertical</h3>
</select>
</div>

<button type="submit" class="btn btn-primary">Save</button>
<div class="d-flex justify-content-end">
<div class="me-2">
<a href="{% url 'tagging:course_list' %}" class="btn btn-secondary">Back to Courses</a>
</div>
<button type="submit" class="btn btn-primary">Save</button>
</div>
</form>

<!-- Message container for success/error -->
<div id="message-container" class="mt-3"></div>
</div>
</div>

<script>
function filterSubVerticals(event) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,36 @@
{% extends "tagging/base.html" %}

{% block content %}
<div class="container mt-5">
<div class="container mt-4">
<h1 class="mb-4">Sub-Vertical: {{ sub_vertical.name }}</h1>
<p>Parent Vertical:
<a href="{% url 'tagging:vertical_detail' slug=sub_vertical.vertical.slug %}">
{{ sub_vertical.vertical.name }}
</a>
</p>
<h2>Tagged Courses</h2>
<h3 class="my-4">Tagged Courses</h3>

{% if courses %}
<ul class="list-group">
{% for course in courses %}
<li class="list-group-item">
<a href="{% url 'tagging:course_tagging_detail' uuid=course.uuid %}">
{{ course.title }}
</a>
</li>
{% endfor %}
</ul>
<table class="table table-bordered">
<thead class="table-light">
<tr>
<th>#</th>
<th>Course Title</th>
</tr>
</thead>
<tbody>
{% for course in courses %}
<tr>
<td>{{ forloop.counter }}</td>
<td>
<a href="{% url 'tagging:course_tagging_detail' uuid=course.uuid %}">
{{ course.title }}
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p class="text-muted">No courses assigned to this sub-vertical.</p>
{% endif %}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
{% extends "tagging/base.html" %}

{% block content %}
<div class="container mt-5">
<h1>Sub-Vertical List</h1>
<table class="table table-striped">
<div class="container my-4">
<h1 class="my-3">Sub-Verticals</h1>
<table class="table table-bordered">
<thead class="table-dark">
<thead>
<tr>
<th>#</th>
<th>
<a href="?sort=name&direction={% if current_sort == 'name' and current_direction == 'asc' %}desc{% else %}asc{% endif %}">
Sub-Vertical
Expand All @@ -21,6 +23,7 @@ <h1>Sub-Vertical List</h1>
<tbody>
{% for sub_vertical in sub_verticals %}
<tr>
<td>{{ forloop.counter }}</td>
<td>
<a href="{% url 'tagging:sub_vertical_detail' slug=sub_vertical.slug %}">
{{ sub_vertical.name }}
Expand Down
Loading

0 comments on commit 2884cc5

Please sign in to comment.