ats ui update

This commit is contained in:
Faheed 2025-12-24 15:25:37 +03:00
parent d98682c0e5
commit 4dd52e78b1
6 changed files with 419 additions and 922 deletions

View File

@ -4816,25 +4816,15 @@ def interview_list(request):
return render(request, "interviews/interview_list.html", context)
# from django_ratelimit.decorators import ratelimit
# @ratelimit(key='user_or_ip', rate='1/m', block=True)
from django.core.cache import cache
@login_required
@staff_user_required
def generate_ai_questions(request, slug):
"""Generate AI-powered interview questions for a scheduled interview"""
lock_key = f"ai_lock_{request.user.id}"
is_new_request = cache.add(lock_key, "locked", timeout=60)
if not is_new_request:
return JsonResponse({
"error": "Request in progress. Please wait a moment."
}, status=429)
from django_q.tasks import async_task
schedule = get_object_or_404(ScheduledInterview, slug=slug)
messages.info(request,_("Generating interview questions."))
try:
if request.method == "POST":
# Queue the AI question generation task
@ -4879,10 +4869,6 @@ def generate_ai_questions(request, slug):
# })
return redirect("interview_detail", slug=slug)
except Exception:
# If the task fails to enqueue, release the lock so they can try again
cache.delete(lock_key)
raise
@login_required

File diff suppressed because it is too large Load Diff

View File

@ -21,27 +21,29 @@
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css" />
<link rel="stylesheet" href="{% static 'css/main.css' %}">
<script src="{% static 'js/typo.js' %}"></script>
<script src="{% static 'js/main.js' %}"></script>
<script src="{% static 'js/typo.js' %}"></script>
{% block customCSS %}{% endblock %}
</head>
<body>
<aside class="sidebar d-flex flex-column" id="sidebar">
<div class="sidebar-brand">
<img src="{% static 'image/kaauh_green1.png' %}" alt="Logo" style="width: 50px;">
<div class="text-white small mt-2 fw-bold">KAAUH ATS</div>
<div class="sidebar-brand text-center">
<img src="{% static 'image/kaauh_green1.png' %}" alt="Logo" style="width: 40px;">
<div class="text-white small mt-2 fw-bold brand-subtitle">KAAUH ATS</div>
</div>
<nav class="sidebar-nav">
{% if request.user.is_authenticated and request.user.is_staff %}
<a class="nav-link-custom {% if request.resolver_match.url_name == 'dashboard' %}active{% endif %}" href="{% url 'dashboard' %}">
<i class="fas fa-th-large me-2"></i> {% trans "Dashboard" %}
<i class="fas fa-th-large me-2"></i> <span>{% trans "Dashboard" %}</span>
</a>
<a class="nav-link-custom {% if 'message' in request.path %}active{% endif %}" href="{% url 'message_list' %}">
<i class="fas fa-envelope me-2"></i>
{% trans "Messages" %}
<span>{% trans "Messages" %}</span>
{% if request.user.get_unread_message_count > 0 %}
<span class="badge rounded-pill bg-danger ms-auto">
{{ request.user.get_unread_message_count }}
@ -50,55 +52,57 @@
</a>
<a class="nav-link-custom {% if 'job' in request.path and 'bank' not in request.path %}active{% endif %}" href="{% url 'job_list' %}">
<i class="fas fa-briefcase me-2"></i> {% trans "Jobs" %}
<i class="fas fa-briefcase me-2"></i> <span>{% trans "Jobs" %}</span>
</a>
<a class="nav-link-custom {% if 'job_bank' in request.resolver_match.url_name %}active{% endif %}" href="{% url 'job_bank' %}">
<i class="fas fa-university me-2"></i> {% trans "Job Bank" %}
<i class="fas fa-university me-2"></i> <span>{% trans "Job Bank" %}</span>
</a>
<a class="nav-link-custom {% if 'application' in request.path %}active{% endif %}" href="{% url 'application_list' %}">
<i class="fas fa-user-tie me-2"></i> {% trans "Applications" %}
<i class="fas fa-user-tie me-2"></i> <span>{% trans "Applications" %}</span>
</a>
<a class="nav-link-custom {% if 'person' in request.path %}active{% endif %}" href="{% url 'person_list' %}">
<i class="fas fa-user me-2"></i> {% trans "Applicants" %}
<i class="fas fa-user me-2"></i> <span>{% trans "Applicants" %}</span>
</a>
<a class="nav-link-custom {% if 'agency' in request.path %}active{% endif %}" href="{% url 'agency_list' %}">
<i class="fas fa-building me-2"></i> {% trans "Agencies" %}
<i class="fas fa-building me-2"></i> <span>{% trans "Agencies" %}</span>
</a>
<a class="nav-link-custom {% if 'interview' in request.path %}active{% endif %}" href="{% url 'interview_list' %}">
<i class="fas fa-calendar-alt me-2"></i> {% trans "Interviews" %}
<i class="fas fa-calendar-alt me-2"></i> <span>{% trans "Interviews" %}</span>
</a>
<a class="nav-link-custom {% if request.resolver_match.url_name == 'kaauh_career' %}active{% endif %}" href="{% url 'kaauh_career' %}">
<i class="fas fa-globe me-2"></i> {% trans "Career Page" %}
<i class="fas fa-globe me-2"></i> <span>{% trans "Career Page" %}</span>
</a>
{% endif %}
{% if request.user.is_authenticated and request.user.is_superuser %}
<div class="mt-auto">
<div class="mt-4 pt-3 border-top border-secondary mx-3">
<small class="text-white-50 px-2 uppercase">{% trans "System" %}</small>
<div class="mt-4 pt-3 border-top border-secondary mx-3 uppercase">
{% comment %} <small class="text-white-50 px-2">{% trans "System" %}</small> {% endcomment %}
</div>
<a class="nav-link-custom {% if 'settings' in request.path %}active{% endif %}" href="{% url 'settings' %}">
<i class="fas fa-cog me-2"></i> {% trans "Settings" %}
<i class="fas fa-cog me-2"></i> <span>{% trans "Settings" %}</span>
</a>
</div>
{% endif %}
</nav>
{% if request.user.is_authenticated %}
<div class="p-3 border-top border-secondary">
<div class="logout-section">
<form method="post" action="{% url 'account_logout'%}">
{% csrf_token %}
<button type="submit" class="btn btn-link text-danger text-decoration-none p-0">
<i class="fas fa-sign-out-alt me-2"></i> {% trans "Sign Out" %}
<button type="submit" class="btn btn-link text-decoration-none d-flex align-items-center">
<i class="fas fa-sign-out-alt me-2"></i> <span>{% trans "Sign Out" %}</span>
</button>
</form>
</div>
{% endif %}
<div class="mt-auto p-3 border-top border-secondary text-center">
<a href="https://tenhal.sa/" class="text-decoration-none" target="_blank">
<div class="text-white-50" style="font-size: 0.7rem; letter-spacing: 0.5px;">
{% trans "POWERED BY" %}
<span class="text-white fw-bold">TENHAL</span>
<div class="text-white-50 brand-subtitle" style="font-size: 0.7rem; letter-spacing: 0.5px;">
{% trans "POWERED BY" %} <span class="text-white fw-bold">TENHAL</span>
</div>
</a>
</div>
@ -107,9 +111,10 @@
<div class="main-wrapper">
<header class="content-header justify-content-between">
<div class="d-flex align-items-center">
<button class="btn d-lg-none me-2" onclick="document.getElementById('sidebar').classList.toggle('show')">
<button class="btn me-2" id="sidebarCollapse">
<i class="fas fa-bars"></i>
</button>
<div class="hospital-text d-none d-md-block">
<small class="text-teal fw-bold">{% trans "KAAUH Applicant Tracking System" %}</small>
</div>
@ -125,7 +130,6 @@
{% endif %}
</a>
{% if LANGUAGE_CODE == 'en' %}
<form action="{% url 'set_language' %}" method="post">{% csrf_token %}
<input name="language" type="hidden" value="ar">
@ -150,13 +154,13 @@
</div>
{% endif %}
</button>
{% if request.user.is_authenticated %}
<ul class="dropdown-menu dropdown-menu-end shadow border-0">
<li class="px-3 py-2 border-bottom">
<div class="fw-bold small">{{ user.get_full_name|default:user.username }}</div>
<div class="text-muted text-xs">{{ user.email|truncatechars:20 }}</div>
</li>
<li><a class="dropdown-item mt-1" href="{% url 'user_detail' request.user.pk %}">{% trans "Profile" %}</a></li>
{% comment %} <li><a class="dropdown-item" href="{% url 'job_bank' %}">{% trans "Job Bank" %}</a></li> {% endcomment %}
<li><hr class="dropdown-divider"></li>
<li>
<form method="post" action="{% url 'account_logout'%}">
@ -165,11 +169,12 @@
</form>
</li>
</ul>
{% endif %}
</div>
</div>
</header>
<main class="main-container">
<main class="main-container mx-3 my-3">
{% if messages %}
{% for message in messages %}
<div class="alert alert-{{ message.tags }} alert-dismissible fade show" role="alert">
@ -182,15 +187,11 @@
{% block content %}{% endblock %}
</main>
</div>
<div class="text-center mt-4 powered-by-footer">
<a href="https://tenhal.sa/" class="text-decoration-none" target="_blank">
<p class="text-muted small">
Tenhal | تنحل
</p>
<a>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/htmx.org@2.0.7/dist/htmx.min.js"></script>
{% block customJS %}{% endblock %}
</body>
</html>

View File

@ -522,15 +522,30 @@
<h5 class="mb-0" style="color: var(--kaauh-teal-dark); font-weight: 600;">
<i class="fas fa-brain me-2"></i> {% trans "AI Generated Questions" %}
</h5>
<div class="d-flex gap-2">
<form action="{% url 'generate_ai_questions' schedule.slug %}" method="post">
<div class="dropdown">
<button class="btn btn-main-action btn-sm dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
<i class="fas fa-magic me-1"></i> {% trans "AI Actions" %}
</button>
<ul class="dropdown-menu dropdown-menu-end shadow-sm">
<li>
<div class="px-3 py-2 small text-muted" style="width: 220px;">
{% trans "This will use AI to generate questions based on the job description." %}
</div>
</li>
<li><hr class="dropdown-divider"></li>
<li>
<form action="{% url 'generate_ai_questions' schedule.slug %}" method="post" class="m-0">
{% csrf_token %}
<button type="submit" class="btn btn-main-action btn-sm">
<span id="button-text-content">
<i class="fas fa-magic me-1"></i> {% trans "Generate Interview Questions" %}
</span>
<button type="submit" class="dropdown-item text-primary-theme fw-bold py-2">
<i class="fas fa-check-circle me-2"></i> {% trans "Confirm & Generate" %}
</button>
</form>
</li>
</ul>
</div>
</div>
</div>

View File

@ -23,14 +23,16 @@
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css" />
<link rel="stylesheet" href="{% static 'css/main.css' %}">
<script src="{% static 'js/main.js' %}"></script>
<script src="{% static 'js/typo.js' %}"></script>
{% block customCSS %}{% endblock %}
</head>
<body hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'>
<aside class="sidebar d-flex flex-column" id="sidebar">
<div class="sidebar-brand">
<img src="{% static 'image/kaauh_green1.png' %}" alt="Logo" style="width: 50px;">
<div class="text-white small mt-2 fw-bold">
<div class="sidebar-brand text-center">
<img src="{% static 'image/kaauh_green1.png' %}" alt="Logo" style="width: 40px;">
<div class="text-white small mt-2 fw-bold brand-subtitle">
{% if request.user.user_type == 'agency' %}{% trans "Agency Portal" %}{% else %}{% trans "Candidate Portal" %}{% endif %}
</div>
</div>
@ -38,50 +40,53 @@
<nav class="sidebar-nav">
{% if request.user.user_type == 'agency' %}
<a class="nav-link-custom {% if 'dashboard' in request.path %}active{% endif %}" href="{% url 'agency_portal_dashboard' %}">
<i class="fas fa-th-large me-2"></i> {% trans "Dashboard" %}
<i class="fas fa-th-large me-2"></i> <span>{% trans "Dashboard" %}</span>
</a>
<a class="nav-link-custom {% if 'persons' in request.path %}active{% endif %}" href="{% url 'agency_portal_persons_list' %}">
<i class="fas fa-users me-2"></i> {% trans "Applicants" %}
<i class="fas fa-users me-2"></i> <span>{% trans "Applicants" %}</span>
</a>
{% else %}
<a class="nav-link-custom {% if 'dashboard' in request.path %}active{% endif %}" href="{% url 'applicant_portal_dashboard' %}">
<i class="fas fa-th-large me-2"></i> {% trans "Dashboard" %}
<i class="fas fa-th-large me-2"></i> <span>{% trans "Dashboard" %}</span>
</a>
<a class="nav-link-custom {% if 'career' in request.path %}active{% endif %}" href="{% url 'kaauh_career' %}">
<i class="fas fa-briefcase me-2"></i> {% trans "Careers" %}
<i class="fas fa-briefcase me-2"></i> <span>{% trans "Careers" %}</span>
</a>
{% endif %}
<a class="nav-link-custom {% if 'message' in request.path %}active{% endif %}" href="{% url 'message_list' %}">
<i class="fas fa-envelope me-2"></i> {% trans "Messages" %}
<i class="fas fa-envelope me-2"></i>
<span>{% trans "Messages" %}</span>
{% if request.user.get_unread_message_count > 0 %}
<span class="badge rounded-pill bg-danger ms-auto">{{ request.user.get_unread_message_count }}</span>
{% endif %}
</a>
<div class="mt-auto">
<div class="mt-4 pt-3 border-top border-secondary mx-3">
<div class="mt-4 pt-3 border-top border-secondary mx-3 brand-subtitle">
<small class="text-white-50 px-2 uppercase">{% trans "Account" %}</small>
</div>
<a class="nav-link-custom {% if 'profile' in request.path %}active{% endif %}" href="{% url 'user_detail' request.user.pk %}">
<i class="fas fa-user-circle me-2"></i> {% trans "My Profile" %}
<i class="fas fa-user-circle me-2"></i> <span>{% trans "My Profile" %}</span>
</a>
</div>
</nav>
<div class="p-3 border-top border-secondary">
{% if request.user.is_authenticated %}
<div class="logout-section">
<form method="post" action="{% url 'account_logout'%}">
{% csrf_token %}
<button type="submit" class="btn btn-link text-danger text-decoration-none p-0 w-100 text-start">
<i class="fas fa-sign-out-alt me-2"></i> {% trans "Sign Out" %}
<button type="submit" class="btn btn-link text-decoration-none d-flex align-items-center">
<i class="fas fa-sign-out-alt me-2"></i> <span>{% trans "Sign Out" %}</span>
</button>
</form>
</div>
{% endif %}
<div class="mt-auto p-3 border-top border-secondary text-center">
<a href="https://tenhal.sa/" class="text-decoration-none" target="_blank">
<div class="text-white-50" style="font-size: 0.7rem; letter-spacing: 0.5px;">
{% trans "POWERED BY" %}
<span class="text-white fw-bold">TENHAL</span>
<div class="text-white-50 brand-subtitle" style="font-size: 0.7rem; letter-spacing: 0.5px;">
{% trans "POWERED BY" %} <span class="text-white fw-bold">TENHAL</span>
</div>
</a>
</div>
@ -90,17 +95,13 @@
<div class="main-wrapper">
<header class="content-header justify-content-between">
<div class="d-flex align-items-center">
<button class="btn d-lg-none me-2" onclick="document.getElementById('sidebar').classList.toggle('show')">
<button class="btn me-2" id="sidebarCollapse">
<i class="fas fa-bars"></i>
</button>
<div class="hospital-text d-none d-md-block">
<small class="text-teal fw-bold">
{% if request.user.user_type == 'agency' %}
{% trans "Agency Portal" %}
{% else %}
{% trans "Applicant Portal" %}
{% endif %}
{% if request.user.user_type == 'agency' %}{% trans "Agency Portal" %}{% else %}{% trans "Applicant Portal" %}{% endif %}
<span class="text-muted mx-2">|</span>
<span class="text-secondary">KAAUH</span>
</small>
@ -108,10 +109,10 @@
</div>
<div class="d-flex align-items-center gap-3">
<a href="{% url 'message_list' %}" class="btn btn-sm btn-outline-secondary position-relative d-flex align-items-center justify-content-center" style="width: 36px; height: 36px; border-radius: 8px;">
<a href="{% url 'message_list' %}" class="btn btn-sm btn-outline-secondary position-relative d-none d-lg-block">
<i class="fas fa-envelope"></i>
{% if request.user.get_unread_message_count > 0 %}
<span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger" style="font-size: 0.65rem;">
<span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger">
{{ request.user.get_unread_message_count }}
</span>
{% endif %}
@ -132,24 +133,26 @@
{% endif %}
<div class="dropdown">
<button class="btn p-0 border-0 d-flex align-items-center" data-bs-toggle="dropdown" aria-expanded="false">
<div class="profile-avatar shadow-sm" style="width: 36px; height: 36px; font-size: 0.85rem; border: 2px solid white;">
<button class="btn p-0 border-0" data-bs-toggle="dropdown">
{% if user.profile_image %}
<img src="{{ user.profile_image.url }}" class="rounded-circle border" width="35" height="35">
{% else %}
<div class="profile-avatar" style="width: 35px; height: 35px; font-size: 0.8rem;">
{{ user.username|first|upper }}
</div>
{% endif %}
</button>
<ul class="dropdown-menu dropdown-menu-end shadow border-0 mt-2">
<ul class="dropdown-menu dropdown-menu-end shadow border-0">
<li class="px-3 py-2 border-bottom">
<div class="fw-bold small text-dark">{{ user.get_full_name|default:user.username }}</div>
<div class="text-muted" style="font-size: 0.75rem;">{{ user.email|truncatechars:22 }}</div>
<div class="fw-bold small">{{ user.get_full_name|default:user.username }}</div>
<div class="text-muted text-xs">{{ user.email|truncatechars:20 }}</div>
</li>
<li><a class="dropdown-item mt-1" href="{% url 'user_detail' request.user.pk %}"><i class="fas fa-user-circle me-2 text-muted"></i>{% trans "My Profile" %}</a></li>
<li><a class="dropdown-item mt-1" href="{% url 'user_detail' request.user.pk %}">{% trans "Profile" %}</a></li>
<li><hr class="dropdown-divider"></li>
<li>
<form method="post" action="{% url 'account_logout'%}" class="m-0">
<form method="post" action="{% url 'account_logout'%}">
{% csrf_token %}
<button type="submit" class="dropdown-item text-danger d-flex align-items-center">
<i class="fas fa-sign-out-alt me-2"></i>{% trans "Sign Out" %}
</button>
<button type="submit" class="dropdown-item text-danger">{% trans "Sign Out" %}</button>
</form>
</li>
</ul>
@ -157,7 +160,7 @@
</div>
</header>
<main class="main-container">
<main class="main-container mx-3 my-3">
{% if messages %}
{% for message in messages %}
<div class="alert alert-{{ message.tags }} alert-dismissible fade show" role="alert">
@ -171,30 +174,20 @@
</main>
<footer class="mt-auto py-3 border-top bg-white">
<div class="container-fluid px-4">
<div class="d-flex justify-content-between align-items-center small text-muted">
<span>&copy; {% now "Y" %} KAAUH. {% trans "All rights reserved." %}</span>
<div class="d-flex gap-3">
<img src="{% static 'image/vision.svg' %}" alt="Vision 2030" style="height: 25px;">
</div>
<div class="container-fluid px-4 text-center">
<div class="small text-muted">
&copy; {% now "Y" %} KAAUH. {% trans "All rights reserved." %}
</div>
</div>
</footer>
</div>
<div class="text-center mt-4 powered-by-footer">
<a href="https://tenhal.sa/" class="text-decoration-none" target="_blank">
<p class="text-muted small">
Tenhal | تنحل
</p>
<a>
</div>
{% include 'includes/delete_modal.html' %}
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/htmx.org@2.0.7/dist/htmx.min.js"></script>
{% block customJS %}{% endblock %}
</body>
</html>

View File

@ -915,7 +915,7 @@
{% if LANGUAGE_CODE == 'ar' %}
{% with data_source=application.resume_data_ar analysis_source=application.analysis_data_ar %}
<div class="container container-fluid flex-grow-1" style="max-width: 1600px; margin: 0 auto; direction: rtl; text-align: right;">
<div class="container " style="max-width: 1600px; margin: 0 auto; direction: rtl; text-align: right;">
{% include 'recruitment/partials/ai_overview_breadcromb.html' %}
@ -1264,8 +1264,7 @@
{% else %}
{% with data_source=application.resume_data_en analysis_source=application.analysis_data_en %}
<div class="container container-fluid flex-grow-1" style="max-width: 1600px; margin: 0 auto;">
<div>
{% include 'recruitment/partials/ai_overview_breadcromb.html' %}
<header class="header-box">
<div class="header-info">