solved 10 issues
This commit is contained in:
parent
52334e1990
commit
5471046f46
@ -67,6 +67,7 @@ INSTALLED_APPS = [
|
|||||||
"widget_tweaks",
|
"widget_tweaks",
|
||||||
"easyaudit",
|
"easyaudit",
|
||||||
"secured_fields",
|
"secured_fields",
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1889,12 +1889,16 @@ class RemoteInterviewForm(forms.Form):
|
|||||||
|
|
||||||
duration = forms.IntegerField(
|
duration = forms.IntegerField(
|
||||||
min_value=1,
|
min_value=1,
|
||||||
required=False,
|
required=True,
|
||||||
widget=forms.NumberInput(attrs={
|
widget=forms.NumberInput(attrs={
|
||||||
'class': 'form-control',
|
'class': 'form-control',
|
||||||
'placeholder': 'Duration in minutes'
|
'placeholder': 'Duration in minutes'
|
||||||
}),
|
}),
|
||||||
label=_('Duration (minutes)')
|
label=_('Duration (minutes)'),
|
||||||
|
error_messages={
|
||||||
|
'required': _('Please enter how long the interview will last.'),
|
||||||
|
'min_value': _('Duration must be at least 1 minute.')
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -1947,12 +1951,16 @@ class OnsiteInterviewForm(forms.Form):
|
|||||||
)
|
)
|
||||||
duration = forms.IntegerField(
|
duration = forms.IntegerField(
|
||||||
min_value=1,
|
min_value=1,
|
||||||
required=False,
|
required=True,
|
||||||
widget=forms.NumberInput(attrs={
|
widget=forms.NumberInput(attrs={
|
||||||
'class': 'form-control',
|
'class': 'form-control',
|
||||||
'placeholder': 'Duration in minutes'
|
'placeholder': 'Duration in minutes'
|
||||||
}),
|
}),
|
||||||
label=_('Duration (minutes)')
|
label=_('Duration (minutes)'),
|
||||||
|
error_messages={
|
||||||
|
'required': _('Please enter how long the interview will last.'),
|
||||||
|
'min_value': _('Duration must be at least 1 minute.')
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
class ScheduledInterviewForm(forms.Form):
|
class ScheduledInterviewForm(forms.Form):
|
||||||
@ -1975,12 +1983,16 @@ class ScheduledInterviewForm(forms.Form):
|
|||||||
)
|
)
|
||||||
duration = forms.IntegerField(
|
duration = forms.IntegerField(
|
||||||
min_value=1,
|
min_value=1,
|
||||||
required=False,
|
required=True,
|
||||||
widget=forms.NumberInput(attrs={
|
widget=forms.NumberInput(attrs={
|
||||||
'class': 'form-control',
|
'class': 'form-control',
|
||||||
'placeholder': 'Duration in minutes'
|
'placeholder': 'Duration in minutes'
|
||||||
}),
|
}),
|
||||||
label=_('Duration (minutes)')
|
label=_('Duration (minutes)'),
|
||||||
|
error_messages={
|
||||||
|
'required': _('Please enter how long the interview will last.'),
|
||||||
|
'min_value': _('Duration must be at least 1 minute.')
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
def clean_start_time(self):
|
def clean_start_time(self):
|
||||||
@ -2010,12 +2022,16 @@ class OnsiteScheduleInterviewUpdateForm(forms.Form):
|
|||||||
)
|
)
|
||||||
duration = forms.IntegerField(
|
duration = forms.IntegerField(
|
||||||
min_value=1,
|
min_value=1,
|
||||||
required=False,
|
required=True,
|
||||||
widget=forms.NumberInput(attrs={
|
widget=forms.NumberInput(attrs={
|
||||||
'class': 'form-control',
|
'class': 'form-control',
|
||||||
'placeholder': 'Duration in minutes'
|
'placeholder': 'Duration in minutes'
|
||||||
}),
|
}),
|
||||||
label=_('Duration (minutes)')
|
label=_('Duration (minutes)'),
|
||||||
|
error_messages={
|
||||||
|
'required': _('Please enter how long the interview will last.'),
|
||||||
|
'min_value': _('Duration must be at least 1 minute.')
|
||||||
|
}
|
||||||
)
|
)
|
||||||
physical_address = forms.CharField(
|
physical_address = forms.CharField(
|
||||||
max_length=255,
|
max_length=255,
|
||||||
@ -2212,20 +2228,48 @@ Job: {job.title}
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class InterviewResultForm(forms.ModelForm):
|
# class InterviewResultForm(forms.ModelForm):
|
||||||
class Meta:
|
# class Meta:
|
||||||
model = Interview
|
# model = Interview
|
||||||
|
|
||||||
fields = ['interview_result', 'result_comments']
|
# fields = ['interview_result', 'result_comments']
|
||||||
widgets = {
|
# widgets = {
|
||||||
'interview_result': forms.Select(attrs={
|
# 'interview_result': forms.Select(attrs={
|
||||||
'class': 'form-select', # Standard Bootstrap class
|
# 'class': 'form-select', # Standard Bootstrap class
|
||||||
'required': 'required'
|
# 'required': True
|
||||||
}),
|
# }),
|
||||||
'result_comments': forms.Textarea(attrs={
|
# 'result_comments': forms.Textarea(attrs={
|
||||||
|
# 'class': 'form-control',
|
||||||
|
# 'rows': 3,
|
||||||
|
# 'placeholder': 'Enter setting value',
|
||||||
|
# 'required': True
|
||||||
|
# }),
|
||||||
|
# }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
RESULT_CHOICES = (
|
||||||
|
('passed', 'Passed'),
|
||||||
|
('failed', 'Failed'),
|
||||||
|
('on_hold', 'On Hold'),
|
||||||
|
)
|
||||||
|
|
||||||
|
class InterviewResultForm(forms.Form):
|
||||||
|
|
||||||
|
interview_result = forms.ChoiceField(
|
||||||
|
choices=RESULT_CHOICES,
|
||||||
|
widget=forms.Select(attrs={
|
||||||
|
'class': 'form-select',
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
result_comments = forms.CharField(
|
||||||
|
widget=forms.Textarea(attrs={
|
||||||
'class': 'form-control',
|
'class': 'form-control',
|
||||||
'rows': 3,
|
'rows': 3,
|
||||||
'placeholder': 'Enter setting value',
|
'placeholder': 'Enter result comment',
|
||||||
'required': True
|
})
|
||||||
}),
|
)
|
||||||
}
|
|
||||||
@ -1655,8 +1655,12 @@ def generate_interview_questions(schedule_id: int) -> dict:
|
|||||||
if not questions:
|
if not questions:
|
||||||
return {"status": "error", "message": "No questions generated"}
|
return {"status": "error", "message": "No questions generated"}
|
||||||
|
|
||||||
schedule.interview_questions.update(questions)
|
if schedule.interview_questions is None:
|
||||||
|
schedule.interview_questions={}
|
||||||
|
|
||||||
|
schedule.interview_questions=questions
|
||||||
schedule.save(update_fields=["interview_questions"])
|
schedule.save(update_fields=["interview_questions"])
|
||||||
|
# schedule.save(update_fields=["interview_questions"])
|
||||||
|
|
||||||
logger.info(f"Successfully generated questions for schedule {schedule_id}")
|
logger.info(f"Successfully generated questions for schedule {schedule_id}")
|
||||||
|
|
||||||
|
|||||||
@ -246,6 +246,33 @@ class PersonCreateView(CreateView, LoginRequiredMixin, StaffOrAgencyRequiredMixi
|
|||||||
if view == "job":
|
if view == "job":
|
||||||
return redirect("application_create")
|
return redirect("application_create")
|
||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
||||||
|
def form_invalid(self, form):
|
||||||
|
"""
|
||||||
|
Re-renders the form with error messages while maintaining the UI state.
|
||||||
|
"""
|
||||||
|
messages.error(self.request, "There was an error saving the applicant. Please check the details below.")
|
||||||
|
|
||||||
|
# Optional: Add specific field errors as messages
|
||||||
|
for field, errors in form.errors.items():
|
||||||
|
for error in errors:
|
||||||
|
messages.error(self.request, f"{field.title()}: {error}")
|
||||||
|
view = self.request.POST.get("view")
|
||||||
|
agency_slug = self.request.POST.get("agency")
|
||||||
|
|
||||||
|
|
||||||
|
context = self.get_context_data(form=form)
|
||||||
|
|
||||||
|
|
||||||
|
context['view_type'] = view
|
||||||
|
context['agency_slug'] = agency_slug
|
||||||
|
|
||||||
|
|
||||||
|
if view == "portal":
|
||||||
|
|
||||||
|
return redirect('agency_portal_dashboard')
|
||||||
|
|
||||||
|
|
||||||
|
return self.render_to_response(context)
|
||||||
|
|
||||||
|
|
||||||
class PersonDetailView(DetailView, LoginRequiredMixin, StaffRequiredMixin):
|
class PersonDetailView(DetailView, LoginRequiredMixin, StaffRequiredMixin):
|
||||||
@ -4149,6 +4176,8 @@ def interview_create_onsite(request, application_slug):
|
|||||||
form.initial["topic"] = (
|
form.initial["topic"] = (
|
||||||
f"Interview for {application.job.title} - {application.name}"
|
f"Interview for {application.job.title} - {application.name}"
|
||||||
)
|
)
|
||||||
|
messages.error(request, "Please fix the highlighted errors below.")
|
||||||
|
|
||||||
|
|
||||||
form = OnsiteInterviewForm()
|
form = OnsiteInterviewForm()
|
||||||
form.initial["topic"] = (
|
form.initial["topic"] = (
|
||||||
@ -4253,14 +4282,15 @@ def cancel_interview_for_application(request, slug):
|
|||||||
def update_interview_result(request,slug):
|
def update_interview_result(request,slug):
|
||||||
interview = get_object_or_404(Interview,slug=slug)
|
interview = get_object_or_404(Interview,slug=slug)
|
||||||
schedule=interview.scheduled_interview
|
schedule=interview.scheduled_interview
|
||||||
form = InterviewResultForm(request.POST, instance=interview)
|
form = InterviewResultForm(request.POST)
|
||||||
|
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
|
interview_result=form.cleaned_data.get("interview_result")
|
||||||
|
result_comments=form.cleaned_data.get("result_comments")
|
||||||
|
interview.interview_result=interview_result
|
||||||
|
interview.result_comments=result_comments
|
||||||
interview.save(update_fields=['interview_result', 'result_comments'])
|
interview.save(update_fields=['interview_result', 'result_comments'])
|
||||||
|
|
||||||
form.save() # Saves form data
|
|
||||||
|
|
||||||
messages.success(request, _(f"Interview result updated successfully to {interview.interview_result}."))
|
messages.success(request, _(f"Interview result updated successfully to {interview.interview_result}."))
|
||||||
return redirect("interview_detail", slug=schedule.slug)
|
return redirect("interview_detail", slug=schedule.slug)
|
||||||
else:
|
else:
|
||||||
@ -4769,6 +4799,7 @@ def interview_list(request):
|
|||||||
return render(request, "interviews/interview_list.html", context)
|
return render(request, "interviews/interview_list.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
from django_ratelimit.decorators import ratelimit
|
||||||
@login_required
|
@login_required
|
||||||
@staff_user_required
|
@staff_user_required
|
||||||
def generate_ai_questions(request, slug):
|
def generate_ai_questions(request, slug):
|
||||||
@ -4776,15 +4807,18 @@ def generate_ai_questions(request, slug):
|
|||||||
from django_q.tasks import async_task
|
from django_q.tasks import async_task
|
||||||
|
|
||||||
schedule = get_object_or_404(ScheduledInterview, slug=slug)
|
schedule = get_object_or_404(ScheduledInterview, slug=slug)
|
||||||
|
messages.info(request,_("Generating interview questions."))
|
||||||
|
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
# Queue the AI question generation task
|
# Queue the AI question generation task
|
||||||
|
|
||||||
task_id = async_task(
|
task_id = async_task(
|
||||||
"recruitment.tasks.generate_interview_questions",
|
"recruitment.tasks.generate_interview_questions",
|
||||||
schedule.id,
|
schedule.id,
|
||||||
sync=True
|
sync=False
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# if request.headers.get("X-Requested-With") == "XMLHttpRequest":
|
# if request.headers.get("X-Requested-With") == "XMLHttpRequest":
|
||||||
# return JsonResponse({
|
# return JsonResponse({
|
||||||
# "status": "success",
|
# "status": "success",
|
||||||
@ -4830,7 +4864,7 @@ def interview_detail(request, slug):
|
|||||||
)
|
)
|
||||||
schedule = get_object_or_404(ScheduledInterview, slug=slug)
|
schedule = get_object_or_404(ScheduledInterview, slug=slug)
|
||||||
interview = schedule.interview
|
interview = schedule.interview
|
||||||
interview_result_form=InterviewResultForm(instance=interview)
|
interview_result_form=InterviewResultForm()
|
||||||
application = schedule.application
|
application = schedule.application
|
||||||
job = schedule.job
|
job = schedule.job
|
||||||
if interview.location_type == "Remote":
|
if interview.location_type == "Remote":
|
||||||
|
|||||||
@ -47,12 +47,16 @@ django-ckeditor-5==0.2.18
|
|||||||
django-cors-headers==4.9.0
|
django-cors-headers==4.9.0
|
||||||
django-countries==7.6.1
|
django-countries==7.6.1
|
||||||
django-crispy-forms==2.4
|
django-crispy-forms==2.4
|
||||||
django-easy-audit==1.3.7s
|
django-easy-audit==1.3.7
|
||||||
django-extensions==4.1
|
django-extensions==4.1
|
||||||
|
django-fernet-encrypted-fields==0.3.1
|
||||||
django-filter==25.1
|
django-filter==25.1
|
||||||
django-js-asset==3.1.2
|
django-js-asset==3.1.2
|
||||||
|
django-mathfilters==1.0.0
|
||||||
django-picklefield==3.3
|
django-picklefield==3.3
|
||||||
django-q2==1.8.0
|
django-q2==1.8.0
|
||||||
|
django-ratelimit==4.1.0
|
||||||
|
django-secured-fields==0.4.4
|
||||||
django-template-partials==25.2
|
django-template-partials==25.2
|
||||||
django-unfold==0.67.0
|
django-unfold==0.67.0
|
||||||
django-widget-tweaks==1.5.0
|
django-widget-tweaks==1.5.0
|
||||||
@ -136,6 +140,7 @@ Pygments==2.19.2
|
|||||||
PyJWT==2.10.1
|
PyJWT==2.10.1
|
||||||
PyMuPDF==1.26.4
|
PyMuPDF==1.26.4
|
||||||
pyparsing==3.2.5
|
pyparsing==3.2.5
|
||||||
|
pypdf==6.4.2
|
||||||
PyPDF2==3.0.1
|
PyPDF2==3.0.1
|
||||||
pypdfium2==4.30.0
|
pypdfium2==4.30.0
|
||||||
PyPrind==2.11.3
|
PyPrind==2.11.3
|
||||||
@ -206,9 +211,3 @@ wrapt==1.17.3
|
|||||||
wurst==0.4
|
wurst==0.4
|
||||||
xlrd==2.0.2
|
xlrd==2.0.2
|
||||||
xlsxwriter==3.2.9
|
xlsxwriter==3.2.9
|
||||||
locust==2.32.0
|
|
||||||
psutil==6.1.0
|
|
||||||
matplotlib==3.9.2
|
|
||||||
pandas==2.3.2
|
|
||||||
faker==37.8.0
|
|
||||||
requests==2.32.3
|
|
||||||
|
|||||||
@ -107,7 +107,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.dropdown-menu .dropdown-item:hover {
|
.dropdown-menu .dropdown-item:hover {
|
||||||
background-color: var(--kaauh-teal);
|
border-color: var(--kaauh-teal);
|
||||||
color: white;
|
color: white;
|
||||||
transform: translateX(4px);
|
transform: translateX(4px);
|
||||||
}
|
}
|
||||||
@ -369,7 +369,7 @@
|
|||||||
<span class="d-inline"></span>
|
<span class="d-inline"></span>
|
||||||
{% if user.profile_image %}
|
{% if user.profile_image %}
|
||||||
<img src="{{ user.profile_image.url }}" alt="{{ user.username }}" class="profile-avatar"
|
<img src="{{ user.profile_image.url }}" alt="{{ user.username }}" class="profile-avatar"
|
||||||
style="width: 36px; height: 36px; object-fit: cover; background-color: var(--kaauh-teal); display: inline-block; vertical-align: middle;"
|
style="width: 36px; height: 36px; object-fit: cover; display: inline-block; vertical-align: middle;"
|
||||||
title="{% trans 'Your account' %}">
|
title="{% trans 'Your account' %}">
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="profile-avatar" title="{% trans 'Your account' %}">
|
<div class="profile-avatar" title="{% trans 'Your account' %}">
|
||||||
@ -388,11 +388,11 @@
|
|||||||
<div class="me-3 d-flex align-items-center justify-content-center" style="min-width: 48px;">
|
<div class="me-3 d-flex align-items-center justify-content-center" style="min-width: 48px;">
|
||||||
{% if user.profile_image %}
|
{% if user.profile_image %}
|
||||||
<img src="{{ user.profile_image.url }}" alt="{{ user.username }}" class="profile-avatar shadow-sm border"
|
<img src="{{ user.profile_image.url }}" alt="{{ user.username }}" class="profile-avatar shadow-sm border"
|
||||||
style="width: 44px; height: 44px; object-fit: cover; background-color: var(--kaauh-teal); display: block;"
|
style="width: 44px; height: 44px; object-fit: cover; display: block;"
|
||||||
title="{% trans 'Your account' %}">
|
title="{% trans 'Your account' %}">
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="profile-avatar shadow-sm border d-flex align-items-center justify-content-center text-primary-theme"
|
<div class="profile-avatar shadow-sm border d-flex align-items-center justify-content-center text-primary-theme"
|
||||||
style="width: 44px; height: 44px; background-color: var(--kaauh-teal); font-size: 1.2rem;">
|
style="width: 44px; height: 44px; font-size: 1.2rem;">
|
||||||
{{ user.username|first|upper }}
|
{{ user.username|first|upper }}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@ -459,7 +459,7 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
form_loader();
|
//form_loader();
|
||||||
|
|
||||||
try{
|
try{
|
||||||
document.body.addEventListener('htmx:afterRequest', function(evt) {
|
document.body.addEventListener('htmx:afterRequest', function(evt) {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
<form hx-boost="true" action="{% url 'document_upload' slug %}" method="POST" enctype="multipart/form-data">
|
<form hx-boost="true" action="{% url 'document_upload' slug %}" method="POST" enctype="multipart/form-data" hx-on::after-request="this.reset()">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
|
|||||||
@ -486,10 +486,14 @@
|
|||||||
<div class="mt-3">
|
<div class="mt-3">
|
||||||
<a href="{{ interview.join_url }}"
|
<a href="{{ interview.join_url }}"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
class="btn btn-main-action btn-sm w-100">
|
class="btn btn-main-action btn-sm w-100" id="joinMeetingLink">
|
||||||
<i class="fas fa-video me-1"></i> {% trans "Join Meeting" %}
|
<i class="fas fa-video me-1"></i> {% trans "Join Meeting" %}
|
||||||
</a>
|
</a>
|
||||||
|
<button onclick="copyJoinUrl()" class="btn btn-outline-secondary btn-sm mt-2 w-100">
|
||||||
|
{% trans "Copy & share Join URL" %}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
<p id="copyMessage" style="color: green;"></p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
@ -763,7 +767,7 @@
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
{% if schedule.status == 'completed' %}
|
{% if schedule.status == 'completed' %}
|
||||||
<button type="button" class="btn btn-outline-success btn-sm w-100"
|
<button type="button" class="btn btn-outline-primary btn-sm w-100"
|
||||||
data-bs-toggle="modal"
|
data-bs-toggle="modal"
|
||||||
data-bs-target="#resultModal">
|
data-bs-target="#resultModal">
|
||||||
<i class="fas fa-check-circle me-1"></i> {% trans "Update Result" %}
|
<i class="fas fa-check-circle me-1"></i> {% trans "Update Result" %}
|
||||||
@ -772,17 +776,64 @@
|
|||||||
{% if interview.interview_result %}
|
{% if interview.interview_result %}
|
||||||
{% trans 'Interview Result : ' %}
|
{% trans 'Interview Result : ' %}
|
||||||
{% if interview.interview_result == 'passed' %}
|
{% if interview.interview_result == 'passed' %}
|
||||||
<span class="badge bg-success text-white p-1">
|
<div class="card border-success mb-3" style="max-width: 30rem;">
|
||||||
<i class="fas fa-check-circle me-1"></i> {{ interview.interview_result }}
|
<div class="card-header text-white">
|
||||||
|
<!-- Status Badge as a Pill -->
|
||||||
|
<span class="badge rounded-pill bg-white text-success p-2">
|
||||||
|
<i class="fas fa-check-circle me-1"></i>
|
||||||
|
<strong>{{ interview.interview_result|upper }}</strong>
|
||||||
</span>
|
</span>
|
||||||
|
</div>
|
||||||
|
{% if interview.result_comments %}
|
||||||
|
<div class="card-body text-success">
|
||||||
|
<h5 class="card-title">{% trans 'Result Comment:' %}</h5>
|
||||||
|
<!-- The comment text with slightly adjusted margins -->
|
||||||
|
<p class="card-text text-dark">
|
||||||
|
{{ interview.result_comments }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
{% elif interview.interview_result == 'failed' %}
|
{% elif interview.interview_result == 'failed' %}
|
||||||
<span class="badge bg-danger text-white p-1 fs-5">
|
|
||||||
<i class="fas fa-times-circle me-1"></i> {{ interview.interview_result }}
|
<div class="card border-danger mb-3" style="max-width: 30rem;">
|
||||||
|
<div class="card-header text-white">
|
||||||
|
<!-- Status Badge as a Pill -->
|
||||||
|
<span class="badge rounded-pill bg-white text-danger p-2">
|
||||||
|
<i class="fas fa-check-circle me-1"></i>
|
||||||
|
<strong>{{ interview.interview_result|upper }}</strong>
|
||||||
</span>
|
</span>
|
||||||
|
</div>
|
||||||
|
{% if interview.result_comments %}
|
||||||
|
<div class="card-body text-danger">
|
||||||
|
<h5 class="card-title">{% trans 'Result Comment:' %}</h5>
|
||||||
|
<!-- The comment text with slightly adjusted margins -->
|
||||||
|
<p class="card-text text-dark">
|
||||||
|
{{ interview.result_comments }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<span class="badge bg-info text-dark p-1">
|
|
||||||
<i class="fas fa-info-circle me-1"></i> {{ interview.interview_result }}
|
<div class="card border-info mb-3" style="max-width: 30rem;">
|
||||||
|
<div class="card-header text-white">
|
||||||
|
<!-- Status Badge as a Pill -->
|
||||||
|
<span class="badge rounded-pill bg-white text-info p-2">
|
||||||
|
<i class="fas fa-check-circle me-1"></i>
|
||||||
|
<strong>{{ interview.interview_result|upper }}</strong>
|
||||||
</span>
|
</span>
|
||||||
|
</div>
|
||||||
|
{% if interview.result_comments %}
|
||||||
|
<div class="card-body text-info">
|
||||||
|
<h5 class="card-title">{% trans 'Result Comment:' %}</h5>
|
||||||
|
<!-- The comment text with slightly adjusted margins -->
|
||||||
|
<p class="card-text text-dark">
|
||||||
|
{{ interview.result_comments }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<span class="badge rounded-pill bg-secondary text-white">
|
<span class="badge rounded-pill bg-secondary text-white">
|
||||||
@ -998,5 +1049,30 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//COPY TO Clipboard ZOOM LINK
|
||||||
|
async function copyJoinUrl(){
|
||||||
|
const joinUrlElement=document.getElementById('joinMeetingLink');
|
||||||
|
const urlToCopy=joinUrlElement.href;
|
||||||
|
const messageElement=document.getElementById('copyMessage');
|
||||||
|
|
||||||
|
console.log(urlToCopy)
|
||||||
|
try{
|
||||||
|
await navigator.clipboard.writeText(urlToCopy);
|
||||||
|
messageElement.textContent='Join URL copied successfully!';
|
||||||
|
setTimeout(()=>{
|
||||||
|
messageElement.textContent='';
|
||||||
|
|
||||||
|
},
|
||||||
|
3000
|
||||||
|
);
|
||||||
|
console.log('URL copied:', urlToCopy);
|
||||||
|
}
|
||||||
|
catch(e){
|
||||||
|
messageElement.textContent='Failed to copy Join URL.';
|
||||||
|
console.error('could not copy the URL',e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@ -72,7 +72,7 @@
|
|||||||
<!-- Search and Filters -->
|
<!-- Search and Filters -->
|
||||||
<div class="kaauh-card p-3 mb-4">
|
<div class="kaauh-card p-3 mb-4">
|
||||||
<form method="get" class="row g-3">
|
<form method="get" class="row g-3">
|
||||||
<div class="col-md-6">
|
<div class="col-md-4">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="search" class="form-label">{% trans "Search" %}</label>
|
<label for="search" class="form-label">{% trans "Search" %}</label>
|
||||||
<input type="text" class="form-control" id="search" name="q"
|
<input type="text" class="form-control" id="search" name="q"
|
||||||
@ -97,9 +97,12 @@
|
|||||||
<button type="submit" class="btn btn-outline-secondary w-100">
|
<button type="submit" class="btn btn-outline-secondary w-100">
|
||||||
<i class="fas fa-search me-1"></i> {% trans "Search" %}
|
<i class="fas fa-search me-1"></i> {% trans "Search" %}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Assignments List -->
|
<!-- Assignments List -->
|
||||||
|
|||||||
@ -271,12 +271,13 @@
|
|||||||
<option selected>
|
<option selected>
|
||||||
----------
|
----------
|
||||||
</option>
|
</option>
|
||||||
<option value="Interview">
|
|
||||||
{% trans "To Interview" %}
|
|
||||||
</option>
|
|
||||||
<option value="Offer">
|
<option value="Offer">
|
||||||
{% trans "To Offer" %}
|
{% trans "To Offer" %}
|
||||||
</option>
|
</option>
|
||||||
|
<option value="Interview">
|
||||||
|
{% trans "To Interview" %}
|
||||||
|
</option>
|
||||||
|
|
||||||
</select>
|
</select>
|
||||||
<button id="changeStage" type="submit" class="btn btn-main-action btn-sm">
|
<button id="changeStage" type="submit" class="btn btn-main-action btn-sm">
|
||||||
<i class="fas fa-arrow-right me-1"></i> {% trans "Change Stage" %}
|
<i class="fas fa-arrow-right me-1"></i> {% trans "Change Stage" %}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user