[ADD] ONBOARDING: Onboarding pipeline filteration
This commit is contained in:
@@ -2,9 +2,10 @@
|
||||
filters.py
|
||||
Used to register filter for onboarding models
|
||||
"""
|
||||
|
||||
from django import forms
|
||||
from django_filters import filters
|
||||
from onboarding.models import Candidate
|
||||
from django_filters import filters
|
||||
from onboarding.models import Candidate, CandidateStage, OnboardingStage
|
||||
from base.filters import FilterSet
|
||||
|
||||
|
||||
@@ -22,3 +23,39 @@ class CandidateFilter(FilterSet):
|
||||
|
||||
model = Candidate
|
||||
fields = {}
|
||||
|
||||
|
||||
class OnboardingStageFilter(FilterSet):
|
||||
"""
|
||||
OnboardingStageFilter
|
||||
"""
|
||||
|
||||
search_onboarding = filters.CharFilter(field_name="stage_title", method="pipeline_search")
|
||||
|
||||
class Meta:
|
||||
model = OnboardingStage
|
||||
fields = "__all__"
|
||||
|
||||
def pipeline_search(self, queryset, _, value):
|
||||
"""
|
||||
This method is used to search recruitment
|
||||
"""
|
||||
queryset = (
|
||||
queryset.filter(stage_title__icontains=value)
|
||||
| queryset.filter(candidate__candidate_id__name__icontains=value)
|
||||
)
|
||||
return queryset.distinct()
|
||||
|
||||
|
||||
class OnboardingCandidateFilter(FilterSet):
|
||||
"""
|
||||
OnboardingStageFilter
|
||||
"""
|
||||
|
||||
search_onboarding = filters.CharFilter(
|
||||
field_name="candidate_id__name", lookup_expr="icontains"
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = CandidateStage
|
||||
fields = "__all__"
|
||||
|
||||
59
onboarding/templates/onboarding/filters.html
Normal file
59
onboarding/templates/onboarding/filters.html
Normal file
@@ -0,0 +1,59 @@
|
||||
{% load i18n %}
|
||||
{% load static %}
|
||||
<div class="oh-dropdown__filter-body">
|
||||
<div class="oh-accordion">
|
||||
<div class="oh-accordion-header">
|
||||
{% trans 'Recruitment' %}
|
||||
</div>
|
||||
<div class="oh-accordion-body">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 col-md-12 col-lg-6">
|
||||
<div class="oh-input-group">
|
||||
<label class="oh-label">{% trans 'Managers' %}</label>
|
||||
{{ rec_filter_obj.form.recruitment_managers }}
|
||||
</div>
|
||||
<div class="oh-input-group">
|
||||
<label class="oh-label">{% trans 'Start Date' %}</label>
|
||||
{{ rec_filter_obj.form.start_date }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 col-md-12 col-lg-6">
|
||||
<div class="oh-input-group">
|
||||
<label class="oh-label">{% trans 'Company' %}</label>
|
||||
{{ rec_filter_obj.form.company_id }}
|
||||
</div>
|
||||
<div class="oh-input-group">
|
||||
<label class="oh-label">{% trans 'End Date' %}</label>
|
||||
{{ rec_filter_obj.form.end_date }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="oh-accordion">
|
||||
<div class="oh-accordion-header">
|
||||
{% trans 'Advanced' %}
|
||||
</div>
|
||||
<div class="oh-accordion-body">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 col-md-12 col-lg-6">
|
||||
<div class="oh-input-group">
|
||||
<label class="oh-label">{% trans 'Start Date From' %}</label>
|
||||
{{ rec_filter_obj.form.start_from }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-12 col-lg-6">
|
||||
<div class="oh-input-group">
|
||||
<label class="oh-label">{% trans 'Till End Date' %}</label>
|
||||
{{ rec_filter_obj.form.end_till }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oh-dropdown__filter-footer">
|
||||
<button class="oh-btn oh-btn--secondary oh-btn--small w-100 filterButton" id="">{% trans 'Filter' %}</button>
|
||||
</div>
|
||||
@@ -17,137 +17,33 @@
|
||||
|
||||
|
||||
<div class="oh-wrapper">
|
||||
<section class=" oh-main__topbar" x-data="{searchShow: false}">
|
||||
<div class="oh-main__titlebar oh-main__titlebar--left">
|
||||
<div class="oh-main__titlebar-title fw-bold mb-0 text-dark" style="cursor:pointer;">{% trans "Onboarding" %}</div>
|
||||
</div>
|
||||
|
||||
<div class="oh-main__titlebar oh-main__titlebar--right">
|
||||
|
||||
<div class="oh-input-group oh-input__search-group"
|
||||
:class="searchShow ? 'oh-input__search-group--show' : ''">
|
||||
<ion-icon name="search-outline" class="oh-input-group__icon oh-input-group__icon--left md hydrated"
|
||||
role="img" aria-label="search outline"></ion-icon>
|
||||
<input type="text" id="search" placeholder="{% trans 'Search' %}" name="search"
|
||||
class="oh-input oh-input__icon" aria-label="Search Input">
|
||||
</div>
|
||||
|
||||
<div class="oh-switch ms-3" style="width: 30px;">
|
||||
<input type="checkbox" name="is_closed" data-widget="style-widget" class="style-widget oh-switch__checkbox" {% if request.GET.closed %} checked title="{% trans 'Ongoing Recruitments' %}" {% else %}title="{% trans 'Closed Recruitments' %}" {% endif %} id="is_closed" >
|
||||
</div>
|
||||
|
||||
<ul class="oh-view-types ml-2" style="margin-bottom: 0;">
|
||||
<li class="oh-view-type candidate-view-type" data-view="list" title="{% trans "List" %}">
|
||||
<a href="{% url 'onboarding-view' %}?closed={{status}}" hx-target="#section" class="oh-btn oh-btn--view "><ion-icon
|
||||
name="list-outline" role="img" class="md hydrated" aria-label="list outline"></ion-icon></a>
|
||||
</li>
|
||||
<li class="oh-view-type candidate-view-type" data-view="card" title="{% trans "Card" %}">
|
||||
<a href="{% url 'kanban-view' %}?closed={{status}}" hx-target="#section" class="oh-btn oh-btn--view oh-btn--view-active"><ion-icon
|
||||
name="grid-outline" role="img" class="md hydrated" aria-label="grid outline"></ion-icon></a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="oh-main__titlebar-button-container">
|
||||
|
||||
<div class="oh-dropdown" x-data="{open: false}">
|
||||
<button class="oh-btn ml-2" @click="open = !open">
|
||||
<ion-icon name="filter" class="mr-1"></ion-icon>{% trans "Filter" %}<div id="filterCount"></div>
|
||||
</button>
|
||||
<div class="oh-dropdown__menu oh-dropdown__menu--right oh-dropdown__filter p-4" x-show="open" @click.outside="open = false" style="display: none;" @click.>
|
||||
|
||||
<div class="mb-3 mt-3">
|
||||
<label for="job_position_id" class="oh-label">{% trans "Job position" %}</label>
|
||||
<select class="" name="job_position_id" id="job_position_id">
|
||||
<option value="">------------------</option>
|
||||
{% for job_position in job_positions %}
|
||||
<option value="{{job_position}}">{{job_position}}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-12 col-md-12 col-lg-6">
|
||||
<label class ="mb-2" for="join_date">{% trans "Join Date" %}</label>
|
||||
<input type="date" name="join_date" id="join_date" class="oh-input w-100">
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-12 col-lg-6">
|
||||
<label class ="mb-2" for="portal_stage">{% trans "Onboarding Portal Stage" %}</label>
|
||||
<select class="" name="portal_stage" id="portal_stage">
|
||||
<option value="">------------------</option>
|
||||
<option value="0">0</option>
|
||||
<option value="1">1</option>
|
||||
<option value="2">2</option>
|
||||
<option value="3">3</option>
|
||||
<option value="4">4</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oh-accordion">
|
||||
<div class="oh-accordion-header">{% trans "Advanced" %}</div>
|
||||
<div class="oh-accordion-body">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 col-md-12 col-lg-6">
|
||||
<div class="oh-input-group">
|
||||
<label class ="mb-2" for="join_date">{% trans "Join Date From" %}</label>
|
||||
<input type="date" name="join_date" id="join_date_start" class="oh-input w-100">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-12 col-lg-6">
|
||||
<div class="oh-input-group">
|
||||
<label class ="mb-2" for="join_date">{% trans "Join Date To" %}</label>
|
||||
<input type="date" name="join_date" id="join_date_end" class="oh-input w-100">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oh-tabs__action-bar mt-2" id="filter_item" x-on:click="open = false" >
|
||||
<button class="oh-btn oh-btn--small oh-btn--secondary oh-tabs__action-new-table w-100" >
|
||||
<ion-icon class="me-1 md hydrated" name="add-outline" role="img"aria-label="add outline"></ion-icon>
|
||||
{% trans "Filter" %}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
{% include "onboarding/onboarding_view_nav.html" %}
|
||||
|
||||
<div id = "stage-messages"></div>
|
||||
<div class="oh-wrapper oh-filter-tag-container filter-value" style="margin-left:-3px"></div>
|
||||
<div class="oh-tabs">
|
||||
<ul class="oh-tabs__tablist">
|
||||
{% for rec in recruitments %}
|
||||
{% if request.user|task_manages:rec or perms.onboarding.view_candidatestage %}
|
||||
<li class="oh-tabs__tab" data-target="#tab_{{rec.id}}" data-recruitment-id="{{rec.id}}" {% if request.user|recruitment_manages:rec %} style="background-color: hsl(38.08deg 100% 50% / 8%);" {% endif %}>
|
||||
{{rec.title}}
|
||||
<span
|
||||
class="oh-badge oh-badge--secondary oh-badge--small oh-badge--round ms-2 mr-2" title="{{rec.onboardingstage_set.all|length}} {% trans 'Stage' %}" onclick="event.stopPropagation()">
|
||||
{{rec.onboardingstage_set.all|length}}
|
||||
</span>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
</ul>
|
||||
{% include "onboarding/tabs.html" %}
|
||||
<div class="oh-tabs__contents">
|
||||
{% for rec in recruitments %}
|
||||
<div class="oh-tabs__content " id="tab_{{rec.id}}" data-recruitment-id="{{rec.id}}">
|
||||
<div class="oh-kanban">
|
||||
{% for stage in rec.onboarding_stage.all %}
|
||||
<div class="oh-kanban__section stage" id="b3a7bac2-2a16-40fe-9b7e-78a1101ee9d3" data-recruitment-id="{{rec.id}}" data-stage-id="{{stage.id}}" data-sequence="{{forloop.counter}}">
|
||||
<div class="oh-kanban__section-head oh-kanban__section-head--white" {% if request.user.employee_get in stage.employee_id.all %} style="background-color: hsl(38.08deg 100% 50% / 8%) !important;" {% endif %}>
|
||||
{% for stage in rec.stages %}
|
||||
|
||||
<div class="oh-kanban__section stage" id="b3a7bac2-2a16-40fe-9b7e-78a1101ee9d3" data-recruitment-id="{{rec.id}}" data-stage-id="{{stage.grouper.id}}" data-sequence="{{forloop.counter}}">
|
||||
<div class="oh-kanban__section-head oh-kanban__section-head--white" {% if request.user.employee_get in stage.grouper.employee_id.all %} style="background-color: hsl(38.08deg 100% 50% / 8%) !important;" {% endif %}>
|
||||
<div class="d-flex ">
|
||||
<span class="oh-kanban__section-title" data-type="label">
|
||||
<input
|
||||
class="oh-tabs__movable-title oh-table__editable-input"
|
||||
value="{{stage}}"
|
||||
hx-post="{% url 'stage-name-update' stage.id %}"
|
||||
value="{{stage.grouper}}"
|
||||
hx-post="{% url 'stage-name-update' stage.grouper.id %}"
|
||||
name='stage'
|
||||
hx-target="#stage-messages"
|
||||
style="width: 160px;"
|
||||
readonly=""
|
||||
/>
|
||||
</span>
|
||||
<span class="oh-badge oh-badge--secondary oh-badge--small oh-badge--round ms-2 mr-2 stage_count" title="{{stage.candidate.count}} {% trans 'Candidate' %}">{{stage.candidate.count}}</span>
|
||||
<span class="oh-badge oh-badge--secondary oh-badge--small oh-badge--round ms-2 mr-2 stage_count" title="{{stage.grouper.candidate.count}} {% trans 'Candidate' %}">{{stage.grouper.candidate.count}}</span>
|
||||
</div>
|
||||
<div class="oh-kanban__head-actions oh-kanban__dropdown">
|
||||
<button
|
||||
@@ -161,11 +57,11 @@
|
||||
<li class="oh-dropdown__item">
|
||||
<a data-toggle="oh-modal-toggle"
|
||||
data-target="#editModal3"
|
||||
hx-get="{% url 'stage-update' stage.id rec.id %}"
|
||||
hx-get="{% url 'stage-update' stage.grouper.id rec.id %}"
|
||||
hx-target="#updateStage">{% trans "Edit" %}</a>
|
||||
</li>
|
||||
<li class="oh-dropdown__item">
|
||||
<a href="{% url 'stage-delete' stage.id %}"
|
||||
<a href="{% url 'stage-delete' stage.grouper.id %}"
|
||||
onclick="return confirm('{% trans "Do you want to delete this stage?" %}')"
|
||||
class="oh-dropdown__link oh-dropdown__link--danger">{% trans "Delete" %}</a>
|
||||
</li>
|
||||
@@ -176,7 +72,7 @@
|
||||
class="oh-btn oh-btn--small oh-btn--transparent p-0"
|
||||
data-toggle="oh-modal-toggle"
|
||||
data-target="#taskModal"
|
||||
hx-get="{% url 'task-creation' %}?stage_id=stage.id"
|
||||
hx-get="{% url 'task-creation' %}?stage_id={{stage.grouper.id}}"
|
||||
hx-target = "#taskModalBody"
|
||||
|
||||
title="{% trans 'Add task' %}">
|
||||
@@ -185,8 +81,8 @@
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oh-kanban__section-body ui-sortable onboarding_items" data-stage-id="{{stage.id}}" data-recruitment-id="{{rec.id}}">
|
||||
{% for candidate in stage.candidate.all %}
|
||||
<div class="oh-kanban__section-body ui-sortable onboarding_items" data-stage-id="{{stage.grouper.id}}" data-recruitment-id="{{rec.id}}">
|
||||
{% for candidate in stage.list %}
|
||||
<div class="oh-kanban__card candidate" id="{{candidate.id}}" data-candidate="{{candidate.candidate_id}}" data-candidate-id="{{candidate.candidate_id.id}}" data-recruitment-id="{{rec.id}}" data-candidate-now = "{{stage.id}}" data-job-position = "{{candidate.candidate_id.job_position_id}}" data-portal-count="{{candidate.candidate_id.onboarding_portal.count}}" data-join-date="{{candidate.candidate_id.joining_date}}" >
|
||||
<div class="oh-kanban__card-head">
|
||||
<div class="oh-profile oh-profile--md">
|
||||
@@ -234,6 +130,45 @@
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% if stage.list.number %}
|
||||
<div class="oh-pagination">
|
||||
<nav class="oh-pagination__nav">
|
||||
<div class="oh-pagination__input-container me-3">
|
||||
<span class="oh-pagination__label me-1">{% trans "Page" %}</span>
|
||||
<input
|
||||
type="number"
|
||||
name="{{stage.dynamic_name}}"
|
||||
class="oh-pagination__input"
|
||||
value="{{stage.list.number}}"
|
||||
href="?{{pd}}"
|
||||
min="1"
|
||||
/>
|
||||
<span class="oh-pagination__label"
|
||||
>{% trans "of" %} {{stage.list.paginator.num_pages}}</span
|
||||
>
|
||||
</div>
|
||||
<ul class="oh-pagination__items">
|
||||
{% if stage.list.has_previous %}
|
||||
<li class="oh-pagination__item oh-pagination__item--wide">
|
||||
<a
|
||||
href="?{{pd}}&{{stage.dynamic_name}}={{ stage.list.previous_page_number }}"
|
||||
class="oh-pagination__link"
|
||||
>{% trans "Previous" %}</a
|
||||
>
|
||||
</li>
|
||||
{% endif %} {% if stage.list.has_next %}
|
||||
<li class="oh-pagination__item oh-pagination__item--wide">
|
||||
<a
|
||||
href="?{{pd}}&{{stage.dynamic_name}}={{ stage.list.next_page_number }}"
|
||||
class="oh-pagination__link"
|
||||
>{% trans "Next" %}</a
|
||||
>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,371 +1,406 @@
|
||||
{% load onboardingfilters %} {% load i18n %} {% load static %}
|
||||
|
||||
<style>
|
||||
.oh-accordion-meta__body .oh-sticky-table--no-overflow {
|
||||
height:300px;
|
||||
}
|
||||
.select2-container .select2-selection.select2-selection--multiple{
|
||||
padding: 5px !important;
|
||||
max-height: 70px !important;
|
||||
overflow: hidden;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
.oh-accordion-meta__body .oh-sticky-table--no-overflow {
|
||||
height:300px;
|
||||
}
|
||||
.select2-container .select2-selection.select2-selection--multiple{
|
||||
padding: 5px !important;
|
||||
max-height: 70px !important;
|
||||
overflow: hidden;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
</style>
|
||||
<script src="{% static 'htmx/htmx.min.js' %}"></script>
|
||||
|
||||
{% for stage in recruitment.onboarding_stage.all %}
|
||||
|
||||
{% for stage in recruitment.stages %}
|
||||
<div class="oh-accordion-meta" >
|
||||
<div class="oh-accordion-meta__item" id="onboarding_stage{{stage.id}}">
|
||||
<div class="oh-accordion-meta__header oh-accordion-meta__header--show" {% if request.user.employee_get in stage.employee_id.all %} style="background-color: hsl(38.08deg 100% 50% / 8%);" {% endif %}>
|
||||
<div style="display: -webkit-inline-box;"
|
||||
<div class="oh-accordion-meta__item" id="onboarding_stage{{stage.grouper.id}}">
|
||||
{% comment %} fixed {% endcomment %}
|
||||
<div class="oh-accordion-meta__header oh-accordion-meta__header--show"
|
||||
{% if request.user.employee_get in stage.grouper.employee_id.all %}
|
||||
style="background-color: hsl(38.08deg 100% 50% / 8%);"
|
||||
{% endif %}>
|
||||
<div style="display: -webkit-inline-box;"
|
||||
>
|
||||
<span class="oh-badge oh-badge--secondary oh-badge--small oh-badge--round ms-2 mr-2 stage_count" title="{{stage.list|length}} {% trans 'Candidate' %}">{{stage.list|length}}</span>
|
||||
<span class="oh-accordion-meta__title">{{stage.grouper}}</span>
|
||||
</div>
|
||||
{% if request.user|stage_manages:stage or perms.onboarding.change_onboardingstage or perms.onboarding.delete_onboardingstage %}
|
||||
<div class="oh-btn-group" style="margin-left:70%">
|
||||
{% if request.user|stage_manages:stage or perms.onboarding.change_onboardingstage %}
|
||||
<a
|
||||
onclick="event.stopPropagation();"
|
||||
hx-get="{% url 'stage-update' stage.grouper.id recruitment.id %}"
|
||||
hx-target="#updateStage"
|
||||
data-toggle="oh-modal-toggle"
|
||||
data-target="#editModal3"
|
||||
class="oh-btn oh-btn--light-bkg w-100"
|
||||
title="{% trans 'Edit' %}"
|
||||
>
|
||||
<ion-icon name="create-outline"></ion-icon
|
||||
>
|
||||
</a>
|
||||
{% else %}
|
||||
<a
|
||||
onclick="event.stopPropagation();"
|
||||
data-toggle="oh-modal-toggle"
|
||||
data-target="#editModal3"
|
||||
class="oh-btn oh-btn--light-bkg w-100 oh-btn--disabled"
|
||||
title="{% trans 'Edit' %}"
|
||||
>
|
||||
<ion-icon name="create-outline"></ion-icon
|
||||
>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if request.user|stage_manages:stage or perms.onboarding.delete_onboardingstage %}
|
||||
<form action="{% url 'stage-delete' stage.grouper.id %}"
|
||||
onsubmit="return confirm('{% trans "Do you want to delete this stage?" %}')"
|
||||
class="oh-dropdown__link oh-dropdown__link--danger"
|
||||
>
|
||||
<span class="oh-badge oh-badge--secondary oh-badge--small oh-badge--round ms-2 mr-2 stage_count" title="{{stage.candidate.count}} {% trans 'Candidate' %}">{{stage.candidate.count}}</span>
|
||||
<span class="oh-accordion-meta__title">{{stage}}</span>
|
||||
</div>
|
||||
{% if request.user|stage_manages:stage or perms.onboarding.change_onboardingstage or perms.onboarding.delete_onboardingstage %}
|
||||
<div class="oh-btn-group" style="margin-left:70%">
|
||||
{% if request.user|stage_manages:stage or perms.onboarding.change_onboardingstage %}
|
||||
<a
|
||||
onclick="event.stopPropagation();"
|
||||
hx-get="{% url 'stage-update' stage.id recruitment.id %}"
|
||||
hx-target="#updateStage"
|
||||
data-toggle="oh-modal-toggle"
|
||||
data-target="#editModal3"
|
||||
class="oh-btn oh-btn--light-bkg w-100"
|
||||
title="{% trans 'Edit' %}"
|
||||
><ion-icon name="create-outline"></ion-icon
|
||||
></a>
|
||||
{% else %}
|
||||
<a
|
||||
onclick="event.stopPropagation();"
|
||||
data-toggle="oh-modal-toggle"
|
||||
data-target="#editModal3"
|
||||
class="oh-btn oh-btn--light-bkg w-100 oh-btn--disabled"
|
||||
title="{% trans 'Edit' %}"
|
||||
><ion-icon name="create-outline"></ion-icon
|
||||
></a>
|
||||
{% endif %}
|
||||
{% if request.user|stage_manages:stage or perms.onboarding.delete_onboardingstage %}
|
||||
<form action="{% url 'stage-delete' stage.id %}"
|
||||
onsubmit="return confirm('{% trans "Do you want to delete this stage?" %}')"
|
||||
class="oh-dropdown__link oh-dropdown__link--danger"
|
||||
>
|
||||
<button
|
||||
onclick="event.stopPropagation();"
|
||||
type="submit"
|
||||
class="oh-btn oh-btn--danger-outline oh-btn--light-bkg w-100"
|
||||
title="{% trans 'Remove' %}"
|
||||
>
|
||||
<ion-icon name="trash-outline"></ion-icon>
|
||||
</button>
|
||||
</form>
|
||||
{% else %}
|
||||
<button
|
||||
onclick="event.stopPropagation();"
|
||||
type="submit"
|
||||
class="oh-btn oh-btn--danger-outline oh-btn--light-bkg w-100 oh-btn--disabled "
|
||||
title="{% trans 'Remove' %}"
|
||||
>
|
||||
<ion-icon name="trash-outline"></ion-icon>
|
||||
</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% comment %} <div class="oh-accordion-meta__actions" onclick="event.stopPropagation()">
|
||||
<div class="oh-dropdown" x-data="{open: false}">
|
||||
<button class="oh-btn oh-stop-prop oh-accordion-meta__btn" @click="open = !open"
|
||||
@click.outside="open = false"
|
||||
title="{% trans "Action" %}">
|
||||
{% trans "Actions" %}
|
||||
<ion-icon class="ms-2 oh-accordion-meta__btn-icon" name="caret-down-outline"></ion-icon>
|
||||
</button>
|
||||
<div class="oh-dropdown__menu oh-dropdown__menu--right" x-show="open">
|
||||
<ul class="oh-dropdown__items">
|
||||
{% if request.user|stage_manages:stage or perms.onboarding.change_onboardingstage %}
|
||||
<li class="oh-dropdown__item">
|
||||
<a class="oh-dropdown__link" data-toggle="oh-modal-toggle" data-target="#editModal3"
|
||||
hx-get="{% url 'stage-update' stage.id recruitment.id %}"
|
||||
hx-target="#updateStage">{% trans "Edit" %}</a>
|
||||
</li>
|
||||
{% endif %} {% endcomment %}
|
||||
{% if request.user|stage_manages:stage or perms.onboarding.change_onboardingstage %}
|
||||
{% comment %} <li class="oh-dropdown__item">
|
||||
<a class="oh-dropdown__link mb-2">{% trans "Bulk Change Stage" %}</a> {% endcomment %}
|
||||
<select id=""
|
||||
class="w-100 bulkStageChange"
|
||||
style="border: 1px solid hsl(213deg,22%,84%);
|
||||
padding: 0.3rem 0.8rem 0.3rem 0.3rem;
|
||||
border-radius: 0rem;" name="stage"
|
||||
data-stage = "#onboarding_stage{{stage.id}}"
|
||||
data-recruitment = {{recruitment.id}}
|
||||
title = "Bulk stage change"
|
||||
onchange = "bulkStageChange(this)">
|
||||
{% for on_stage in recruitment.onboarding_stage.all %}
|
||||
{% if on_stage == stage %}
|
||||
<option value="{{on_stage.id}}" selected>{{on_stage}}</option>
|
||||
{% else %}
|
||||
<option value="{{on_stage.id}}">{{on_stage}}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
{% comment %} </li> {% endcomment %}
|
||||
{% endif %}
|
||||
{% comment %} {% if request.user|stage_manages:stage or perms.onboarding.delete_onboardingstage %}
|
||||
<li class="oh-dropdown__item">
|
||||
<a href="{% url 'stage-delete' stage.id %}"
|
||||
onclick="return confirm('{% trans "Do you want to delete this stage?" %}')"
|
||||
class="oh-dropdown__link oh-dropdown__link--danger">{% trans "Delete" %}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div> {% endcomment %}
|
||||
<button
|
||||
onclick="event.stopPropagation();"
|
||||
type="submit"
|
||||
class="oh-btn oh-btn--danger-outline oh-btn--light-bkg w-100"
|
||||
title="{% trans 'Remove' %}"
|
||||
>
|
||||
<ion-icon name="trash-outline"></ion-icon>
|
||||
</button>
|
||||
</form>
|
||||
{% else %}
|
||||
<button
|
||||
onclick="event.stopPropagation();"
|
||||
type="submit"
|
||||
class="oh-btn oh-btn--danger-outline oh-btn--light-bkg w-100 oh-btn--disabled "
|
||||
title="{% trans 'Remove' %}"
|
||||
>
|
||||
<ion-icon name="trash-outline"></ion-icon>
|
||||
</button>
|
||||
{% endif %}
|
||||
{% if request.user|stage_manages:stage or perms.onboarding.change_onboardingstage %}
|
||||
<select id=""
|
||||
class="w-100 bulkStageChange"
|
||||
style="border: 1px solid hsl(213deg,22%,84%);
|
||||
padding: 0.3rem 0.8rem 0.3rem 0.3rem;
|
||||
border-radius: 0rem;" name="stage"
|
||||
data-stage = "#onboarding_stage{{stage.grouper.id}}"
|
||||
data-recruitment = {{recruitment.id}}
|
||||
title = "Bulk stage change"
|
||||
onclick="event.stopPropagation();"
|
||||
onchange = "bulkStageChange(this);">
|
||||
{% for on_stage in recruitment.onboarding_stage.all %}
|
||||
{% if on_stage == stage %}
|
||||
<option value="{{on_stage.id}}" selected>{{on_stage}}</option>
|
||||
{% else %}
|
||||
<option value="{{on_stage.id}}">{{on_stage}}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="oh-accordion-meta__body onboarding_items">
|
||||
<div class="oh-sticky-table oh-sticky-table--no-overflow mb-5">
|
||||
<div class="oh-sticky-table__table">
|
||||
<div class="oh-sticky-table__thead">
|
||||
<div class="oh-sticky-table__tr">
|
||||
<div class="oh-sticky-table__th" style="width:10px;">
|
||||
<div class="centered-div">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="oh-input payslip-checkbox oh-input__checkbox select-all"
|
||||
data-stage="#onboarding_stage{{stage.id}}"
|
||||
onclick="event.stopPropagation()"
|
||||
onchange="select_all(this)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oh-sticky-table__th">{% trans "Candidate" %}</div>
|
||||
<div class="oh-sticky-table__th">{% trans "Email" %}</div>
|
||||
<div class="oh-sticky-table__th">{% trans "Job Position" %}</div>
|
||||
<div class="oh-sticky-table__th">{% trans "Mobile" %}</div>
|
||||
<div class="oh-sticky-table__th">{% trans "Joining Date" %}</div>
|
||||
<div class="oh-sticky-table__th">{% trans "Portal Status" %}</div>
|
||||
<div class="oh-sticky-table__th">{% trans "Task Status" %}</div>
|
||||
<div class="oh-sticky-table__th">{% trans "Stage" %}</div>
|
||||
<div class="oh-sticky-table__th">{% trans "Options" %}</div>
|
||||
{% for task in stage.onboarding_task.all %}
|
||||
<div class="oh-sticky-table__th" style="width: 250px;">
|
||||
<div class="d-flex align-items-center justify-content-between">
|
||||
<span title="{{task}}">{{task|truncatechars:20}}</span>
|
||||
{% if request.user|stage_manages:stage or perms.onboarding.change_onboardingtask or perms.onboarding.delete_onboardingtask %}
|
||||
<div class="oh-dropdown" x-data="{open: false}">
|
||||
<button class="oh-btn oh-stop-prop oh-btn--transparent oh-accordion-meta__btn"
|
||||
@click="open = !open" @click.outside="open = false"
|
||||
title="{% trans "Actions" %}">
|
||||
<ion-icon name="ellipsis-vertical"></ion-icon>
|
||||
</button>
|
||||
<div class="oh-dropdown__menu oh-dropdown__menu--right" x-show="open" style="text-align:left !important">
|
||||
<ul class="oh-dropdown__items">
|
||||
{% if request.user|stage_manages:stage or perms.onboarding.change_onboardingtask %}
|
||||
<li class="oh-dropdown__item">
|
||||
<a class="oh-dropdown__link" data-toggle="oh-modal-toggle"
|
||||
data-target="#editModal4"
|
||||
hx-get="{% url 'task-update' task.id %}"
|
||||
hx-target="#updateTask">{% trans "Edit" %}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if request.user|stage_manages:stage or perms.onboarding.change_onboardingstage %}
|
||||
<li class="oh-dropdown__item">
|
||||
<a class="oh-dropdown__link mb-2">{% trans "Bulk Change Task" %}</a>
|
||||
<select id="" class="w-100 bulkTaskChange" style="
|
||||
border: 1px solid hsl(213deg,22%,84%);
|
||||
padding: 0.3rem 0.8rem 0.3rem 0.3rem;
|
||||
border-radius: 0rem;" name="stage"
|
||||
data-task = "{{task.id}}" onchange = "bulkTaskChange(this)">
|
||||
{% for choice in choices %}
|
||||
<option value="{{choice.0}}">{{choice.1}}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if request.user|stage_manages:stage or perms.onboarding.delete_onboardingtask %}
|
||||
<li class="oh-dropdown__item">
|
||||
<a class="oh-dropdown__link oh-dropdown__link--danger"
|
||||
href="{% url 'task-delete' task.id %}"
|
||||
onclick="return confirm('Do you want to delete this task?')">{% trans "Delete" %}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% if request.user|stage_manages:stage or perms.onboarding.add_onboardingtask %}
|
||||
<div class="oh-sticky-table__th">
|
||||
<button class="oh-btn oh-btn--small oh-btn--secondary oh-tabs__action-new-table"
|
||||
data-toggle="oh-modal-toggle" data-target="#editModal2"
|
||||
hx-get="{% url 'task-creation' %}?stage_id={{stage.id}}" hx-target="#taskForm">
|
||||
<ion-icon class="me-1 md hydrated" name="add-outline" role="img"
|
||||
aria-label="add outline"></ion-icon>{% trans "Task" %}
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="oh-sticky-table__tbody candidate-container">
|
||||
{% for candidate in stage.candidate.all %}
|
||||
{% if candidate.candidate_id.recruitment_id == recruitment %}
|
||||
<div class="oh-sticky-table__tr oh-multiple-table-sort__movable change-cand"
|
||||
data-candidate-id="{{candidate.candidate_id}}" data-drop="candidate"
|
||||
data-change-cand-id="{{candidate.candidate_id}}"
|
||||
data-candidate="{{candidate.candidate_id}}"
|
||||
data-job-position = "{{candidate.candidate_id.job_position_id}}"
|
||||
data-join-date="{{candidate.candidate_id.joining_date}}"
|
||||
data-portal-count="{{candidate.candidate_id.onboarding_portal.count}}"
|
||||
data-toggle="oh-modal-toggle" data-target="#tableTimeOff"
|
||||
hx-get="{% url 'candidate-single-view' candidate.candidate_id.id %}" hx-target="#singleView"
|
||||
>
|
||||
<div class="oh-sticky-table__sd" onclick="event.stopPropagation()">
|
||||
<div class="oh-profile oh-profile--md">
|
||||
<div class="centered-div">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="{{candidate.candidate_id.id}}"
|
||||
value="{{candidate.candidate_id.id}}"
|
||||
class="oh-input payslip-checkbox oh-input__checkbox checkbox-row"
|
||||
onchange="$(this).closest('.oh-sticky-table__tr').toggleClass('highlight-selected', $(this).is(':checked'))"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oh-sticky-table__td">
|
||||
<div class="oh-profile oh-profile--md">
|
||||
<div class="oh-profile__avatar mr-1">
|
||||
<img src="{{candidate.candidate_id.get_avatar}}"
|
||||
class="oh-profile__image" alt="" />
|
||||
</div>
|
||||
<span class="oh-profile__name oh-text--dark">{{candidate.candidate_id}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oh-sticky-table__td">{{candidate.candidate_id.email}}</div>
|
||||
<div class="oh-sticky-table__td">{{candidate.candidate_id.job_position_id}}</div>
|
||||
<div class="oh-sticky-table__td">{{candidate.candidate_id.mobile}}</div>
|
||||
<div class="oh-sticky-table__td dateformat_changer">{{candidate.candidate_id.joining_date}}</div>
|
||||
<div class="oh-sticky-table__td">
|
||||
<div class="oh-checkpoint-badge oh-checkpoint-badge--secondary" >
|
||||
{% if candidate.candidate_id.onboarding_portal.count %}
|
||||
{{candidate.candidate_id.onboarding_portal.count}} / 4
|
||||
{% else %}
|
||||
0 / 4
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="oh-sticky-table__td">
|
||||
<div class="oh-checkpoint-badge oh-checkpoint-badge--primary" >
|
||||
{{candidate.task_completion_ratio}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="oh-sticky-table__td" onclick="event.stopPropagation()">
|
||||
{% if request.user|stage_manages:stage or perms.onboarding.change_candidatestage %}
|
||||
<select id="" class="w-100" style="
|
||||
border: 1px solid hsl(213deg,22%,84%);
|
||||
padding: 0.3rem 0.8rem 0.3rem 0.3rem;
|
||||
border-radius: 0rem;" name="stage"
|
||||
hx-post="{% url 'candidate-stage-update' candidate.candidate_id.id recruitment.id %}"
|
||||
hx-trigger="change" hx-target="#onboardingTable{{recruitment.id}}">
|
||||
{% for stage in recruitment.onboarding_stage.all %}
|
||||
{% if candidate.onboarding_stage_id == stage %}
|
||||
<option value="{{stage.id}}" selected>{{stage}}</option>
|
||||
{% else %}
|
||||
<option value="{{stage.id}}">{{stage}}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
{% else %}
|
||||
{% for stage in recruitment.onboarding_stage.all %}
|
||||
{% if candidate.onboarding_stage_id == stage %}
|
||||
{{stage}}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="oh-sticky-table__td" onclick="event.stopPropagation()">
|
||||
<button class="oh-checkpoint-badge text-success" data-toggle="oh-modal-toggle" data-target="#sendMailModal" hx-get="{% url 'send-mail' candidate.candidate_id.id %}" hx-target="#sendMailModalBody">
|
||||
{% trans "Send mail" %}
|
||||
</button>
|
||||
</div>
|
||||
{% for task in stage.onboarding_task.all %}
|
||||
<div class="oh-sticky-table__td" onclick="event.stopPropagation()" id="task{{task.id}}{{candidate.candidate_id.id}}">
|
||||
{% if request.user|task_manager:task or perms.onboarding.change_candidatetask %}
|
||||
{% include 'onboarding/candidate_task.html' %}
|
||||
{% else %}
|
||||
{% for choice in choices %}
|
||||
{% if choice.0 == task.status %}
|
||||
{{choice.1}}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div><br>
|
||||
{% comment %} fixed {% endcomment %}
|
||||
|
||||
<div class="oh-accordion-meta__body onboarding_items">
|
||||
{% comment %} fixed {% endcomment %}
|
||||
<div class="oh-sticky-table oh-sticky-table--no-overflow mb-5">
|
||||
<div class="oh-sticky-table__table">
|
||||
<div class="oh-sticky-table__thead">
|
||||
<div class="oh-sticky-table__tr">
|
||||
<div class="oh-sticky-table__th" style="width:10px;">
|
||||
<div class="centered-div">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="oh-input payslip-checkbox oh-input__checkbox select-all"
|
||||
data-stage="#onboarding_stage{{stage.grouper.id}}"
|
||||
onclick="event.stopPropagation()"
|
||||
onchange="select_all(this)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oh-sticky-table__th">{% trans "Candidate" %}</div>
|
||||
<div class="oh-sticky-table__th">{% trans "Email" %}</div>
|
||||
<div class="oh-sticky-table__th">{% trans "Job Position" %}</div>
|
||||
<div class="oh-sticky-table__th">{% trans "Mobile" %}</div>
|
||||
<div class="oh-sticky-table__th">{% trans "Joining Date" %}</div>
|
||||
<div class="oh-sticky-table__th">{% trans "Portal Status" %}</div>
|
||||
<div class="oh-sticky-table__th">{% trans "Task Status" %}</div>
|
||||
<div class="oh-sticky-table__th">{% trans "Stage" %}</div>
|
||||
<div class="oh-sticky-table__th">{% trans "Options" %}</div>
|
||||
{% for task in stage.grouper.onboarding_task.all %}
|
||||
<div class="oh-sticky-table__th" style="width: 250px;">
|
||||
<div class="d-flex align-items-center justify-content-between">
|
||||
<span title="{{task}}">{{task|truncatechars:20}}</span>
|
||||
{% if request.user|stage_manages:stage or perms.onboarding.change_onboardingtask or perms.onboarding.delete_onboardingtask %}
|
||||
<div class="oh-dropdown" x-data="{open: false}">
|
||||
<button class="oh-btn oh-stop-prop oh-btn--transparent oh-accordion-meta__btn"
|
||||
@click="open = !open" @click.outside="open = false"
|
||||
title="{% trans "Actions" %}">
|
||||
<ion-icon name="ellipsis-vertical"></ion-icon>
|
||||
</button>
|
||||
<div class="oh-dropdown__menu oh-dropdown__menu--right" x-show="open" style="text-align:left !important">
|
||||
<ul class="oh-dropdown__items">
|
||||
{% if request.user|stage_manages:stage or perms.onboarding.change_onboardingtask %}
|
||||
<li class="oh-dropdown__item">
|
||||
<a class="oh-dropdown__link" data-toggle="oh-modal-toggle"
|
||||
data-target="#editModal4"
|
||||
hx-get="{% url 'task-update' task.id %}"
|
||||
hx-target="#updateTask">{% trans "Edit" %}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if request.user|stage_manages:stage or perms.onboarding.change_onboardingstage %}
|
||||
<li class="oh-dropdown__item">
|
||||
<a class="oh-dropdown__link mb-2">{% trans "Bulk Change Task" %}</a>
|
||||
<select id="" class="w-100 bulkTaskChange" style="
|
||||
border: 1px solid hsl(213deg,22%,84%);
|
||||
padding: 0.3rem 0.8rem 0.3rem 0.3rem;
|
||||
border-radius: 0rem;" name="stage"
|
||||
data-task = "{{task.id}}" onchange = "bulkTaskChange(this)">
|
||||
{% for choice in choices %}
|
||||
<option value="{{choice.0}}">{{choice.1}}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if request.user|stage_manages:stage or perms.onboarding.delete_onboardingtask %}
|
||||
<li class="oh-dropdown__item">
|
||||
<a class="oh-dropdown__link oh-dropdown__link--danger"
|
||||
href="{% url 'task-delete' task.id %}"
|
||||
onclick="return confirm('Do you want to delete this task?')">{% trans "Delete" %}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% if request.user|stage_manages:stage or perms.onboarding.add_onboardingtask %}
|
||||
<div class="oh-sticky-table__th">
|
||||
<button class="oh-btn oh-btn--small oh-btn--secondary oh-tabs__action-new-table"
|
||||
data-toggle="oh-modal-toggle" data-target="#editModal2"
|
||||
hx-get="{% url 'task-creation' %}?stage_id={{stage.grouper.id}}" hx-target="#taskForm">
|
||||
<ion-icon class="me-1 md hydrated" name="add-outline" role="img"
|
||||
aria-label="add outline"></ion-icon>
|
||||
{% trans "Task" %}
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="oh-sticky-table__tbody candidate-container">
|
||||
{% for candidate in stage.list %}
|
||||
{% if candidate.candidate_id.recruitment_id == recruitment %}
|
||||
<div class="oh-sticky-table__tr oh-multiple-table-sort__movable change-cand"
|
||||
data-candidate-id="{{candidate.candidate_id}}" data-drop="candidate"
|
||||
data-change-cand-id="{{candidate.candidate_id}}"
|
||||
data-candidate="{{candidate.candidate_id}}"
|
||||
data-job-position = "{{candidate.candidate_id.job_position_id}}"
|
||||
data-join-date="{{candidate.candidate_id.joining_date}}"
|
||||
data-portal-count="{{candidate.candidate_id.onboarding_portal.count}}"
|
||||
data-toggle="oh-modal-toggle" data-target="#tableTimeOff"
|
||||
hx-get="{% url 'candidate-single-view' candidate.candidate_id.id %}" hx-target="#singleView"
|
||||
>
|
||||
<div class="oh-sticky-table__sd" onclick="event.stopPropagation()">
|
||||
<div class="oh-profile oh-profile--md">
|
||||
<div class="centered-div">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="{{candidate.candidate_id.id}}"
|
||||
value="{{candidate.candidate_id.id}}"
|
||||
class="oh-input payslip-checkbox oh-input__checkbox checkbox-row"
|
||||
onchange="$(this).closest('.oh-sticky-table__tr').toggleClass('highlight-selected', $(this).is(':checked'))"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oh-sticky-table__td">
|
||||
<div class="oh-profile oh-profile--md">
|
||||
<div class="oh-profile__avatar mr-1">
|
||||
<img src="{{candidate.candidate_id.get_avatar}}"
|
||||
class="oh-profile__image" alt="" />
|
||||
</div>
|
||||
<span class="oh-profile__name oh-text--dark">{{candidate.candidate_id}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oh-sticky-table__td">{{candidate.candidate_id.email}}</div>
|
||||
<div class="oh-sticky-table__td">{{candidate.candidate_id.job_position_id}}</div>
|
||||
<div class="oh-sticky-table__td">{{candidate.candidate_id.mobile}}</div>
|
||||
<div class="oh-sticky-table__td dateformat_changer">{{candidate.candidate_id.joining_date}}</div>
|
||||
<div class="oh-sticky-table__td">
|
||||
<div class="oh-checkpoint-badge oh-checkpoint-badge--secondary" >
|
||||
{% if candidate.candidate_id.onboarding_portal.count %}
|
||||
{{candidate.candidate_id.onboarding_portal.count}} / 4
|
||||
{% else %}
|
||||
0 / 4
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="oh-sticky-table__td">
|
||||
<div class="oh-checkpoint-badge oh-checkpoint-badge--primary" >
|
||||
{{candidate.task_completion_ratio}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="oh-sticky-table__td" onclick="event.stopPropagation()">
|
||||
{% if request.user|stage_manages:stage or perms.onboarding.change_candidatestage %}
|
||||
<select id="" class="w-100" style="
|
||||
border: 1px solid hsl(213deg,22%,84%);
|
||||
padding: 0.3rem 0.8rem 0.3rem 0.3rem;
|
||||
border-radius: 0rem;" name="stage"
|
||||
hx-post="{% url 'candidate-stage-update' candidate.candidate_id.id recruitment.id %}"
|
||||
hx-trigger="change" hx-target="#onboardingTable{{recruitment.id}}">
|
||||
{% for stage in recruitment.onboarding_stage.all %}
|
||||
{% if candidate.onboarding_stage_id == stage %}
|
||||
<option value="{{stage.id}}" selected>{{stage}}</option>
|
||||
{% else %}
|
||||
<option value="{{stage.id}}">{{stage}}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
{% else %}
|
||||
{% for stage in recruitment.onboarding_stage.all %}
|
||||
{% if candidate.onboarding_stage_id == stage %}
|
||||
{{stage}}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="oh-sticky-table__td" onclick="event.stopPropagation()">
|
||||
<button class="oh-checkpoint-badge text-success" data-toggle="oh-modal-toggle" data-target="#sendMailModal" hx-get="{% url 'send-mail' candidate.candidate_id.id %}" hx-target="#sendMailModalBody">
|
||||
{% trans "Send mail" %}
|
||||
</button>
|
||||
</div>
|
||||
{% for task in stage.grouper.onboarding_task.all %}
|
||||
<div class="oh-sticky-table__td" onclick="event.stopPropagation()" id="task{{task.id}}{{candidate.candidate_id.id}}">
|
||||
{% if request.user|task_manager:task or perms.onboarding.change_candidatetask %}
|
||||
{% include 'onboarding/candidate_task.html' %}
|
||||
{% else %}
|
||||
{% for choice in choices %}
|
||||
{% if choice.0 == task.status %}
|
||||
{{choice.1}}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% comment %}till heree{% endcomment %}
|
||||
|
||||
<div class="oh-pagination">
|
||||
{% if stage.list.paginator.num_pages %}
|
||||
<span class="oh-pagination__page">
|
||||
{% trans "Page" %} {{ stage.list.number }} {% trans "of" %} {{ stage.list.paginator.num_pages }}.
|
||||
</span>
|
||||
<nav class="oh-pagination__nav">
|
||||
<div class="oh-pagination__input-container me-3">
|
||||
<span class="oh-pagination__label me-1">{% trans "Page" %}</span>
|
||||
<input
|
||||
type="number"
|
||||
name="{{stage.dynamic_name}}"
|
||||
class="oh-pagination__input"
|
||||
value="{{stage.list.number}}"
|
||||
href="?{{pd}}"
|
||||
min="1"
|
||||
/>
|
||||
<span class="oh-pagination__label"
|
||||
>{% trans "of" %} {{stage.list.paginator.num_pages}}</span
|
||||
>
|
||||
</div>
|
||||
<ul class="oh-pagination__items">
|
||||
{% if stage.list.has_previous %}
|
||||
<li class="oh-pagination__item oh-pagination__item--wide">
|
||||
<a
|
||||
href="?{{pd}}&{{stage.dynamic_name}}=1"
|
||||
class="oh-pagination__link"
|
||||
>{% trans "First" %}</a
|
||||
>
|
||||
</li>
|
||||
<li class="oh-pagination__item oh-pagination__item--wide">
|
||||
<a
|
||||
href="?{{pd}}&{{stage.dynamic_name}}={{ stage.list.previous_page_number }}"
|
||||
class="oh-pagination__link"
|
||||
>{% trans "Previous" %}</a
|
||||
>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if stage.list.has_next %}
|
||||
<li class="oh-pagination__item oh-pagination__item--wide">
|
||||
<a
|
||||
href="?{{pd}}&{{stage.dynamic_name}}={{ stage.list.next_page_number }}"
|
||||
class="oh-pagination__link"
|
||||
>{% trans "Next" %}</a
|
||||
>
|
||||
</li>
|
||||
<li class="oh-pagination__item oh-pagination__item--wide">
|
||||
<a
|
||||
href="?{{pd}}&{{stage.dynamic_name}}={{ stage.list.paginator.num_pages }}"
|
||||
class="oh-pagination__link"
|
||||
>{% trans "Last" %}</a
|
||||
>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</nav>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
<script>
|
||||
|
||||
function bulkTaskChange(element){
|
||||
let NewStatus = $(element).val();
|
||||
let Task = $(element).data("task");
|
||||
let checkbox = $("input[type='checkbox']:checked")
|
||||
let ids =[]
|
||||
checkbox.each(function(index){
|
||||
ids.push(parseInt($(this).val()))
|
||||
})
|
||||
|
||||
ids=ids.filter(value => !isNaN(value))
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: '/onboarding/candidate-task-bulk-update',
|
||||
data: {
|
||||
"ids": JSON.stringify(ids),
|
||||
"task": Task,
|
||||
"status": NewStatus,
|
||||
csrfmiddlewaretoken: getCookie("csrftoken"),
|
||||
|
||||
},
|
||||
success: function (response) {
|
||||
for (let i of ids) {
|
||||
var tasks = $(`[data-onboarding-task-id=${Task}][data-candidate-id=${i}]`);
|
||||
tasks.val(NewStatus);
|
||||
}
|
||||
var alertContainer = $('<div class="oh-alert-container">');
|
||||
var message = "{% trans 'Candidates stage updated successfully...' %}"
|
||||
var alertDiv = $('<div class="oh-alert oh-alert--animated oh-alert--info">').text(`${ids.length} ${message}`);
|
||||
alertContainer.append(alertDiv);
|
||||
$(".messages").html(alertContainer);
|
||||
function bulkTaskChange(element){
|
||||
let NewStatus = $(element).val();
|
||||
let Task = $(element).data("task");
|
||||
let checkbox = $("input[type='checkbox']:checked")
|
||||
let ids =[]
|
||||
checkbox.each(function(index){
|
||||
ids.push(parseInt($(this).val()))
|
||||
})
|
||||
|
||||
ids=ids.filter(value => !isNaN(value))
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: '/onboarding/candidate-task-bulk-update',
|
||||
data: {
|
||||
"ids": JSON.stringify(ids),
|
||||
"task": Task,
|
||||
"status": NewStatus,
|
||||
csrfmiddlewaretoken: getCookie("csrftoken"),
|
||||
|
||||
},
|
||||
error: () => {
|
||||
console.log("error")
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
$(document).ready(function() {
|
||||
|
||||
|
||||
$("select[name='stage']").on("htmx:afterRequest", function(event, xhr, data) {
|
||||
var alertContainer = $('<div class="oh-alert-container">');
|
||||
var alertDiv = $('<div class="oh-alert oh-alert--animated oh-alert--info">').text("{% trans 'Candidate task stage updated successfully..' %}")
|
||||
|
||||
alertContainer.append(alertDiv);
|
||||
$(".messages").html(alertContainer);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
success: function (response) {
|
||||
for (let i of ids) {
|
||||
var tasks = $(`[data-onboarding-task-id=${Task}][data-candidate-id=${i}]`);
|
||||
tasks.val(NewStatus);
|
||||
}
|
||||
var alertContainer = $('<div class="oh-alert-container">');
|
||||
var message = "{% trans 'Candidates stage updated successfully...' %}"
|
||||
var alertDiv = $('<div class="oh-alert oh-alert--animated oh-alert--info">').text(`${ids.length} ${message}`);
|
||||
alertContainer.append(alertDiv);
|
||||
$(".messages").html(alertContainer);
|
||||
},
|
||||
error: () => {
|
||||
console.log("error")
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
$(document).ready(function() {
|
||||
|
||||
|
||||
$("select[name='stage']").on("htmx:afterRequest", function(event, xhr, data) {
|
||||
var alertContainer = $('<div class="oh-alert-container">');
|
||||
var alertDiv = $('<div class="oh-alert oh-alert--animated oh-alert--info">').text("{% trans 'Candidate task stage updated successfully..' %}")
|
||||
|
||||
alertContainer.append(alertDiv);
|
||||
$(".messages").html(alertContainer);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@@ -43,126 +43,16 @@
|
||||
<div class="oh-alert-container messages" >
|
||||
|
||||
</div>
|
||||
<section class="oh-wrapper oh-main__topbar" x-data="{searchShow: false}">
|
||||
<div class="oh-main__titlebar oh-main__titlebar--left">
|
||||
<h1 class="oh-main__titlebar-title fw-bold">{% trans "Onboarding" %}</h1>
|
||||
<a class="oh-main__titlebar-search-toggle" role="button" aria-label="Toggle Search"
|
||||
@click="searchShow = !searchShow">
|
||||
<ion-icon name="search-outline" class="oh-main__titlebar-serach-icon"></ion-icon>
|
||||
</a>
|
||||
</div>
|
||||
<div class="oh-main__titlebar oh-main__titlebar--right">
|
||||
{% if recruitments %}
|
||||
<div class="oh-input-group oh-input__search-group" :class="searchShow ? 'oh-input__search-group--show' : ''">
|
||||
<ion-icon name="search-outline" class="oh-input-group__icon oh-input-group__icon--left"></ion-icon>
|
||||
<input type="text" id="search" name='search' class="oh-input oh-input__icon" aria-label="Search Input" placeholder="{% trans 'Search' %}" />
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="oh-switch ms-3" style="width: 30px;">
|
||||
<input type="checkbox" name="is_closed" data-widget="style-widget" class="style-widget oh-switch__checkbox" {% if request.GET.closed %} checked title="{% trans 'Switch to Ongoing Recruitments' %}" {% else %} title="{% trans 'Switch to Closed Recruitments' %}" {% endif %} id="is_closed" >
|
||||
</div>
|
||||
|
||||
{% if recruitments %}
|
||||
<ul class="oh-view-types ml-2" style="margin-bottom: 0;">
|
||||
<li class="oh-view-type candidate-view-type" data-view="list" title="{% trans "List" %}">
|
||||
<a href="{% url 'onboarding-view' %}?closed={{status}}" hx-target="#section" class="oh-btn oh-btn--view oh-btn--view-active"><ion-icon
|
||||
name="list-outline" role="img" class="md hydrated" aria-label="list outline"></ion-icon></a>
|
||||
</li>
|
||||
<li class="oh-view-type candidate-view-type" data-view="card" title="{% trans "Card" %}">
|
||||
<a href="{% url 'kanban-view' %}?closed={{status}}" hx-target="#section" class="oh-btn oh-btn--view"><ion-icon
|
||||
name="grid-outline" role="img" class="md hydrated" aria-label="grid outline"></ion-icon></a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="oh-main__titlebar-button-container">
|
||||
|
||||
<div class="oh-dropdown" x-data="{open: false}">
|
||||
<button class="oh-btn ml-2" @click="open = !open">
|
||||
<ion-icon name="filter" class="mr-1"></ion-icon>{% trans "Filter" %}
|
||||
</button>
|
||||
<div class="oh-dropdown__menu oh-dropdown__menu--right oh-dropdown__filter p-4" x-show="open" @click.outside="open = false" style="display: none;" @click.>
|
||||
|
||||
<div class="mb-3 mt-3">
|
||||
<label for="job_position_id" class="oh-label">{% trans "Job position" %}</label>
|
||||
<select class="" name="job_position_id" id="job_position_id">
|
||||
<option value="">------------------</option>
|
||||
{% for job_position in job_positions %}
|
||||
<option value="{{job_position}}">{{job_position}}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-12 col-md-12 col-lg-6">
|
||||
<label class ="mb-2" for="join_date">{% trans "Join Date" %}</label>
|
||||
<input type="date" name="join_date" id="join_date" class="oh-input w-100">
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-12 col-lg-6">
|
||||
<label class ="mb-2" for="portal_stage">{% trans "Portal Stage" %}</label>
|
||||
<select class="" name="portal_stage" id="portal_stage">
|
||||
<option value="">------------------</option>
|
||||
<option value="0">0</option>
|
||||
<option value="1">1</option>
|
||||
<option value="2">2</option>
|
||||
<option value="3">3</option>
|
||||
<option value="4">4</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oh-accordion">
|
||||
<div class="oh-accordion-header">{% trans "Advanced" %}</div>
|
||||
<div class="oh-accordion-body">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 col-md-12 col-lg-6">
|
||||
<div class="oh-input-group">
|
||||
<label class ="mb-2" for="join_date">{% trans "Join Date From" %}</label>
|
||||
<input type="date" name="join_date" id="join_date_start" class="oh-input w-100">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-12 col-lg-6">
|
||||
<div class="oh-input-group">
|
||||
<label class ="mb-2" for="join_date">{% trans "Join Date To" %}</label>
|
||||
<input type="date" name="join_date" id="join_date_end" class="oh-input w-100">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oh-tabs__action-bar mt-2" id="filter_item" x-on:click="open = false" >
|
||||
<button class="oh-btn oh-btn--small oh-btn--secondary oh-tabs__action-new-table w-100" >
|
||||
<ion-icon class="me-1 md hydrated" name="add-outline" role="img"aria-label="add outline"></ion-icon>
|
||||
{% trans "Filter" %}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</section>
|
||||
{% include "onboarding/onboarding_view_nav.html" %}
|
||||
<div class="oh-wrapper oh-filter-tag-container filter-value"></div>
|
||||
<div class="oh-wrapper">
|
||||
{% if recruitments %}
|
||||
|
||||
<div class="oh-tabs">
|
||||
<ul class="oh-tabs__tablist">
|
||||
{% for recruitment in recruitments %}
|
||||
{% if request.user|task_manages:recruitment or perms.onboarding.view_candidatestage %}
|
||||
<li class="oh-tabs__tab" {% if request.user|recruitment_manages:recruitment %} style="background-color: hsl(38.08deg 100% 50% / 8%);" {% endif %} data-target="#tab_{{recruitment.id}}">
|
||||
{{recruitment}}
|
||||
<span
|
||||
class="oh-badge oh-badge--secondary oh-badge--small oh-badge--round ms-2 mr-2" title="{{recruitment.onboarding_stage.all|length}} {% trans 'Stage' %}" style="padding-right: 0;" onclick="event.stopPropagation()">{{recruitment.onboarding_stage.all|length}}</span>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% include "onboarding/tabs.html" %}
|
||||
<div class="oh-tabs__contents">
|
||||
{% for recruitment in recruitments %}
|
||||
{% if request.user|task_manages:recruitment or perms.onboarding.view_candidatestage %}
|
||||
|
||||
{% if request.user|task_manages:recruitment or perms.onboarding.view_candidatestage %}
|
||||
<div class="oh-tabs__content" id="tab_{{recruitment.id}}">
|
||||
|
||||
<!-- End of Sticky Table -->
|
||||
<div class="oh-card">
|
||||
{% if request.user|task_manages:recruitment or perms.onboarding.add_onboardingstage %}
|
||||
<div class="oh-tabs__action-bar">
|
||||
@@ -174,11 +64,10 @@
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div id="onboardingTable{{recruitment.id}}" class="demo">
|
||||
<div id="onboardingTable{{recruitment.id}}" class="demo dd">
|
||||
{% include 'onboarding/onboarding_table.html' %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
50
onboarding/templates/onboarding/onboarding_view_nav.html
Normal file
50
onboarding/templates/onboarding/onboarding_view_nav.html
Normal file
@@ -0,0 +1,50 @@
|
||||
{% load i18n %}
|
||||
<section class="oh-wrapper oh-main__topbar" x-data="{searchShow: false}">
|
||||
<div class="oh-main__titlebar oh-main__titlebar--left">
|
||||
<h1 class="oh-main__titlebar-title fw-bold">{% trans "Onboarding" %}</h1>
|
||||
<a class="oh-main__titlebar-search-toggle" role="button" aria-label="Toggle Search"
|
||||
@click="searchShow = !searchShow">
|
||||
<ion-icon name="search-outline" class="oh-main__titlebar-serach-icon"></ion-icon>
|
||||
</a>
|
||||
</div>
|
||||
<form action="" class="oh-main__titlebar oh-main__titlebar--right">
|
||||
<div class="oh-input-group oh-input__search-group" :class="searchShow ? 'oh-input__search-group--show' : ''">
|
||||
<ion-icon name="search-outline" class="oh-input-group__icon oh-input-group__icon--left"></ion-icon>
|
||||
<input type="text" value="{{request.GET.search_onboarding}}" onkeyup="setTimeout(() => {
|
||||
$(this).closest('form').submit()
|
||||
}, 1000);" name='search_onboarding' class="oh-input oh-input__icon" aria-label="Search Input" placeholder="{% trans 'Search' %}" />
|
||||
</div>
|
||||
<ul class="oh-view-types ml-2" style="margin-bottom: 0;">
|
||||
<li class="oh-view-type candidate-view-type" data-view="list" title="{% trans "List" %}">
|
||||
<a href="{% url 'onboarding-view' %}?{{request.GET.urlencode}}" hx-target="#section" class="oh-btn oh-btn--view {% if not card %}oh-btn--view-active{% endif %} "><ion-icon
|
||||
name="list-outline" role="img" class="md hydrated" aria-label="list outline"></ion-icon></a>
|
||||
</li>
|
||||
<li class="oh-view-type candidate-view-type" data-view="card" title="{% trans "Card" %}">
|
||||
<a href="{% url 'kanban-view' %}?{{request.GET.urlencode}}" hx-target="#section" class="oh-btn oh-btn--view {% if card %}oh-btn--view-active{% endif %}"><ion-icon
|
||||
name="grid-outline" role="img" class="md hydrated" aria-label="grid outline"></ion-icon></a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="oh-main__titlebar-button-container">
|
||||
|
||||
<div class="oh-dropdown" x-data="{open: false}">
|
||||
<button type="button" class="oh-btn ml-2" @click="open = !open">
|
||||
<ion-icon name="filter" class="mr-1"></ion-icon>{% trans "Filter" %}
|
||||
</button>
|
||||
<div class="oh-dropdown__menu oh-dropdown__menu--right oh-dropdown__filter p-4" x-show="open" @click.outside="open = false">
|
||||
{% include "onboarding/filters.html" %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
{% include "filter_tags.html" %}
|
||||
<div class="d-flex flex-row-reverse oh-wrapper">
|
||||
<span onclick="$('[name=closed]').val('True'); $('[name=closed]').first().change(); $('.filterButton').click()" style="cursor: pointer;margin-left: 10px;margin-right: 10px;">
|
||||
<span class="oh-dot oh-dot--small me-1" style="background-color:orangered"></span>
|
||||
{% trans "Closed" %}
|
||||
</span>
|
||||
<span onclick="$('[name=closed]').val('');$('[name=closed]').first().change(); $('.filterButton').click()" style="cursor: pointer;margin-left: 10px;margin-right: 10px;">
|
||||
<span class="oh-dot oh-dot--small me-1" style="background-color: yellowgreen"></span>
|
||||
{% trans "Open" %}
|
||||
</span>
|
||||
</div>
|
||||
18
onboarding/templates/onboarding/tabs.html
Normal file
18
onboarding/templates/onboarding/tabs.html
Normal file
@@ -0,0 +1,18 @@
|
||||
{% load i18n %}
|
||||
{% load recruitmentfilters %}
|
||||
{% load onboardingfilters %}
|
||||
|
||||
<ul class="oh-tabs__tablist">
|
||||
{% for rec in recruitments %}
|
||||
|
||||
{% if request.user|task_manages:rec or perms.onboarding.view_candidatestage %}
|
||||
<li class="oh-tabs__tab" data-target="#tab_{{rec.id}}" data-recruitment-id="{{rec.id}}" {% if request.user|recruitment_manages:rec %} style="background-color: hsl(38.08deg 100% 50% / 8%);" {% endif %}>
|
||||
{{rec.title}}
|
||||
<span
|
||||
class="oh-badge oh-badge--secondary oh-badge--small oh-badge--round ms-2 mr-2" title="{{rec.stages|length}} {% trans 'Stages' %}" onclick="event.stopPropagation()">
|
||||
{{rec.stages|length}}
|
||||
</span>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
@@ -32,6 +32,7 @@ from horilla import settings
|
||||
from horilla.decorators import login_required, hx_request_required
|
||||
from horilla.decorators import permission_required
|
||||
from base.methods import generate_pdf, get_key_instances, get_pagination, sortby
|
||||
from onboarding.filters import OnboardingCandidateFilter, OnboardingStageFilter
|
||||
from recruitment.forms import RejectedCandidateForm
|
||||
from recruitment.models import Candidate, Recruitment, RecruitmentMailTemplate, RejectedCandidate
|
||||
from recruitment.filters import CandidateFilter, RecruitmentFilter
|
||||
@@ -58,6 +59,7 @@ from onboarding.decorators import (
|
||||
stage_manager_can_enter,
|
||||
recruitment_manager_can_enter,
|
||||
)
|
||||
from recruitment.pipeline_grouper import group_by_queryset
|
||||
|
||||
|
||||
@login_required
|
||||
@@ -677,6 +679,47 @@ def email_send(request):
|
||||
|
||||
return HttpResponse("<script>window.location.reload()</script>")
|
||||
|
||||
def onboarding_query_grouper(request,queryset):
|
||||
"""
|
||||
This method is used to make group of the onboarding records
|
||||
"""
|
||||
groups = []
|
||||
for rec in queryset:
|
||||
stages = OnboardingStageFilter(request.GET, queryset=rec.onboarding_stage.all()).qs
|
||||
all_stages_grouper = []
|
||||
for stage_in_all in stages.order_by("sequence"):
|
||||
all_stages_grouper.append({"grouper": stage_in_all, "list": []})
|
||||
data = {"recruitment": rec, "stages": []}
|
||||
for stage in stages.order_by("sequence"):
|
||||
stage_candidates = OnboardingCandidateFilter(
|
||||
request.GET,
|
||||
stage.candidate.order_by("sequence").filter(
|
||||
candidate_id__is_active=True,
|
||||
),
|
||||
).qs
|
||||
|
||||
page_name = "page" + stage.stage_title + str(rec.id)
|
||||
grouper = group_by_queryset(
|
||||
stage_candidates,
|
||||
"onboarding_stage_id",
|
||||
request.GET.get(page_name),
|
||||
page_name,
|
||||
).object_list
|
||||
data["stages"] = data["stages"] + grouper
|
||||
existing_grouper_ids = {item["grouper"].id for item in data["stages"]}
|
||||
for item in all_stages_grouper:
|
||||
if item["grouper"].id not in existing_grouper_ids:
|
||||
data["stages"].append(
|
||||
{
|
||||
"grouper": item["grouper"],
|
||||
"list": [],
|
||||
"dynamic_name": f'dynamic_page_page{item["grouper"].id}',
|
||||
}
|
||||
)
|
||||
|
||||
groups.append(data)
|
||||
return groups
|
||||
|
||||
|
||||
@login_required
|
||||
@all_manager_can_enter("onboarding.view_candidatestage")
|
||||
@@ -690,59 +733,39 @@ def onboarding_view(request):
|
||||
Returns:
|
||||
GET : return onboarding view template
|
||||
"""
|
||||
candidates = Candidate.objects.filter(hired=True, start_onboard=True)
|
||||
job_positions = JobPosition.objects.all()
|
||||
# for candidate in candidates:
|
||||
# recruitment =candidate.recruitment_id
|
||||
# if not CandidateStage.objects.filter(candidate_id=candidate).exists():
|
||||
# try:
|
||||
# onboarding_stage = OnboardingStage.objects.filter(
|
||||
# recruitment_id=candidate.recruitment_id
|
||||
# ).order_by("sequence")[0]
|
||||
# CandidateStage(
|
||||
# candidate_id=candidate, onboarding_stage_id=onboarding_stage
|
||||
# ).save()
|
||||
# except Exception:
|
||||
# messages.error(
|
||||
# request,
|
||||
# _("%(recruitment)s has no stage..")
|
||||
# % {"recruitment": candidate.recruitment_id},
|
||||
# )
|
||||
# if tasks := OnboardingTask.objects.filter(
|
||||
# recruitment_id=candidate.recruitment_id
|
||||
# ):
|
||||
# for task in tasks:
|
||||
# if not CandidateTask.objects.filter(
|
||||
# candidate_id=candidate, onboarding_task_id=task
|
||||
# ).exists():
|
||||
# CandidateTask(
|
||||
# candidate_id=candidate, onboarding_task_id=task
|
||||
# ).save()
|
||||
|
||||
recruitments = Recruitment.objects.filter(closed=False)
|
||||
status = "closed"
|
||||
if request.GET.get("closed") == "closed":
|
||||
recruitments = Recruitment.objects.filter(closed=True)
|
||||
status = "closed"
|
||||
else:
|
||||
status = ""
|
||||
filter_obj = RecruitmentFilter(request.GET)
|
||||
# is active filteration not providing on pipeline
|
||||
recruitments = filter_obj.qs.filter(is_active=True)
|
||||
|
||||
status = request.GET.get("closed")
|
||||
if not status:
|
||||
recruitments = recruitments.filter(closed=False)
|
||||
|
||||
onboarding_stages = OnboardingStage.objects.all()
|
||||
choices = CandidateTask.choice
|
||||
previous_data = request.GET.urlencode()
|
||||
filter_obj = RecruitmentFilter(request.GET, queryset=recruitments)
|
||||
paginator = Paginator(filter_obj.qs, 4)
|
||||
paginator = Paginator(recruitments, 4)
|
||||
page_number = request.GET.get("page")
|
||||
page_obj = paginator.get_page(page_number)
|
||||
|
||||
groups = onboarding_query_grouper(request,page_obj)
|
||||
for item in groups:
|
||||
setattr(item["recruitment"], "stages", item["stages"])
|
||||
filter_dict = parse_qs(request.GET.urlencode())
|
||||
if not request.GET.get("closed"):
|
||||
filter_obj.form.initial["closed"] = False
|
||||
filter_dict["closed"] = ["false"]
|
||||
for key, val in filter_dict.copy().items():
|
||||
if val[0] == "unknown" or key == "view":
|
||||
del filter_dict[key]
|
||||
return render(
|
||||
request,
|
||||
"onboarding/onboarding_view.html",
|
||||
{
|
||||
"recruitments": page_obj,
|
||||
"rec_filter_obj": filter_obj,
|
||||
"onboarding_stages": onboarding_stages,
|
||||
"choices": choices,
|
||||
"job_positions": job_positions,
|
||||
"filter_dict": filter_dict,
|
||||
"status": status,
|
||||
"pd": previous_data,
|
||||
},
|
||||
@@ -752,42 +775,13 @@ def onboarding_view(request):
|
||||
@login_required
|
||||
@all_manager_can_enter("onboarding.view_candidatestage")
|
||||
def kanban_view(request):
|
||||
candidates = Candidate.objects.filter(hired=True, start_onboard=True)
|
||||
job_positions = JobPosition.objects.all()
|
||||
# for candidate in candidates:
|
||||
# if not CandidateStage.objects.filter(candidate_id=candidate).exists():
|
||||
# try:
|
||||
# onboarding_stage = OnboardingStage.objects.filter(
|
||||
# recruitment_id=candidate.recruitment_id
|
||||
# ).order_by("sequence")[0]
|
||||
# CandidateStage(
|
||||
# candidate_id=candidate, onboarding_stage_id=onboarding_stage
|
||||
# ).save()
|
||||
# except Exception:
|
||||
# messages.error(
|
||||
# request,
|
||||
# _("%(recruitment)s has no stage..")
|
||||
# % {"recruitment": candidate.recruitment_id},
|
||||
# )
|
||||
# if tasks := OnboardingTask.objects.filter(
|
||||
# recruitment_id=candidate.recruitment_id
|
||||
# ):
|
||||
# for task in tasks:
|
||||
# if not CandidateTask.objects.filter(
|
||||
# candidate_id=candidate, onboarding_task_id=task
|
||||
# ).exists():
|
||||
# pass
|
||||
# CandidateTask(
|
||||
# candidate_id=candidate, onboarding_task_id=task
|
||||
# ).save()
|
||||
|
||||
recruitments = Recruitment.objects.filter(closed=False)
|
||||
status = "closed"
|
||||
if request.GET.get("closed") == "closed":
|
||||
recruitments = Recruitment.objects.filter(closed=True)
|
||||
status = "closed"
|
||||
else:
|
||||
status = ""
|
||||
filter_obj = RecruitmentFilter(request.GET)
|
||||
# is active filteration not providing on pipeline
|
||||
recruitments = filter_obj.qs.filter(is_active=True)
|
||||
|
||||
status = request.GET.get("closed")
|
||||
if not status:
|
||||
recruitments = recruitments.filter(closed=False)
|
||||
onboarding_stages = OnboardingStage.objects.all()
|
||||
choices = CandidateTask.choice
|
||||
stage_form = OnboardingViewStageForm()
|
||||
@@ -795,22 +789,37 @@ def kanban_view(request):
|
||||
previous_data = request.GET.urlencode()
|
||||
|
||||
filter_obj = RecruitmentFilter(request.GET, queryset=recruitments)
|
||||
paginator = Paginator(filter_obj.qs, 4)
|
||||
paginator = Paginator(recruitments, 4)
|
||||
page_number = request.GET.get("page")
|
||||
page_obj = paginator.get_page(page_number)
|
||||
groups = onboarding_query_grouper(request,page_obj)
|
||||
|
||||
for item in groups:
|
||||
setattr(item["recruitment"], "stages", item["stages"])
|
||||
filter_dict = parse_qs(request.GET.urlencode())
|
||||
if not request.GET.get("closed"):
|
||||
filter_obj.form.initial["closed"] = False
|
||||
filter_dict["closed"] = ["false"]
|
||||
for key, val in filter_dict.copy().items():
|
||||
if val[0] == "unknown" or key == "view":
|
||||
del filter_dict[key]
|
||||
|
||||
|
||||
return render(
|
||||
request,
|
||||
"onboarding/kanban/kanban.html",
|
||||
{
|
||||
"recruitments": page_obj,
|
||||
"rec_filter_obj": filter_obj,
|
||||
"onboarding_stages": onboarding_stages,
|
||||
"choices": choices,
|
||||
"job_positions": job_positions,
|
||||
"filter_dict": filter_dict,
|
||||
"stage_form": stage_form,
|
||||
"status": status,
|
||||
"choices": choices,
|
||||
"pd": previous_data,
|
||||
"card": True,
|
||||
|
||||
},
|
||||
)
|
||||
|
||||
@@ -1195,7 +1204,10 @@ def candidate_stage_update(request, candidate_id, recruitment_id):
|
||||
POST : return candidate task template
|
||||
"""
|
||||
stage_id = request.POST.get("stage")
|
||||
recruitment = Recruitment.objects.get(id=recruitment_id)
|
||||
recruitments = Recruitment.objects.filter(id=recruitment_id)
|
||||
groups = onboarding_query_grouper(request,recruitments)
|
||||
for item in groups:
|
||||
setattr(item["recruitment"], "stages", item["stages"])
|
||||
stage = OnboardingStage.objects.get(id=stage_id)
|
||||
candidate = Candidate.objects.get(id=candidate_id)
|
||||
candidate_stage = CandidateStage.objects.get(candidate_id=candidate)
|
||||
@@ -1224,7 +1236,7 @@ def candidate_stage_update(request, candidate_id, recruitment_id):
|
||||
request,
|
||||
"onboarding/onboarding_table.html",
|
||||
{
|
||||
"recruitment": recruitment,
|
||||
"recruitment": groups[0]["recruitment"],
|
||||
"onboarding_stages": onboarding_stages,
|
||||
"choices": choices,
|
||||
},
|
||||
|
||||
@@ -15,6 +15,7 @@ from recruitment.models import (
|
||||
SkillZoneCandidate,
|
||||
Stage,
|
||||
RecruitmentSurvey,
|
||||
SurveyTemplate,
|
||||
)
|
||||
from base.filters import FilterSet
|
||||
|
||||
@@ -31,7 +32,9 @@ class CandidateFilter(FilterSet):
|
||||
|
||||
name = django_filters.CharFilter(field_name="name", lookup_expr="icontains")
|
||||
# for pipeline use
|
||||
candidate_name = django_filters.CharFilter(field_name="name", lookup_expr="icontains")
|
||||
candidate_name = django_filters.CharFilter(
|
||||
field_name="name", lookup_expr="icontains"
|
||||
)
|
||||
start_date = django_filters.DateFilter(
|
||||
field_name="recruitment_id__start_date",
|
||||
widget=forms.DateInput(attrs={"type": "date"}),
|
||||
@@ -151,6 +154,12 @@ class RecruitmentFilter(FilterSet):
|
||||
FilterSet (class): custom filter set class to apply styling
|
||||
"""
|
||||
|
||||
candidate_name = django_filters.CharFilter(
|
||||
field_name="title", method="pipeline_search"
|
||||
)
|
||||
search_onboarding = django_filters.CharFilter(
|
||||
field_name="title", method="onboarding_search"
|
||||
)
|
||||
description = django_filters.CharFilter(lookup_expr="icontains")
|
||||
start_date = django_filters.DateFilter(
|
||||
field_name="start_date", widget=forms.DateInput(attrs={"type": "date"})
|
||||
@@ -226,6 +235,30 @@ class RecruitmentFilter(FilterSet):
|
||||
queryset = queryset | job_queryset
|
||||
return queryset.distinct()
|
||||
|
||||
def pipeline_search(self, queryset, _, value):
|
||||
"""
|
||||
This method is used to search recruitment
|
||||
"""
|
||||
queryset = (
|
||||
queryset.filter(title__icontains=value)
|
||||
| queryset.filter(stage_set__stage__icontains=value)
|
||||
| queryset.filter(candidate__name__icontains=value)
|
||||
)
|
||||
return queryset.distinct()
|
||||
|
||||
def onboarding_search(self, queryset, _, value):
|
||||
"""
|
||||
This method is used to search recruitment
|
||||
"""
|
||||
queryset = (
|
||||
queryset.filter(title__icontains=value)
|
||||
| queryset.filter(onboarding_stage__stage_title__icontains=value)
|
||||
| queryset.filter(
|
||||
candidate__onboarding_stage__candidate_id__name__icontains=value
|
||||
)
|
||||
)
|
||||
return queryset.distinct()
|
||||
|
||||
|
||||
class StageFilter(FilterSet):
|
||||
"""
|
||||
@@ -236,6 +269,7 @@ class StageFilter(FilterSet):
|
||||
"""
|
||||
|
||||
search = django_filters.CharFilter(method="filter_by_name")
|
||||
candidate_name = django_filters.CharFilter(method="pipeline_search")
|
||||
|
||||
class Meta:
|
||||
"""
|
||||
@@ -261,7 +295,7 @@ class StageFilter(FilterSet):
|
||||
parts = value.split()
|
||||
first_name = parts[0]
|
||||
last_name = " ".join(parts[1:]) if len(parts) > 1 else ""
|
||||
|
||||
recruitment_query = queryset.filter(recruitment_id__title__icontains=value)
|
||||
# Filter the queryset by first name and last name
|
||||
stage_queryset = queryset.filter(stage__icontains=value)
|
||||
if first_name and last_name:
|
||||
@@ -278,7 +312,17 @@ class StageFilter(FilterSet):
|
||||
stage_managers__employee_last_name__icontains=last_name
|
||||
)
|
||||
|
||||
return queryset | stage_queryset
|
||||
queryset = queryset | stage_queryset | recruitment_query
|
||||
return queryset
|
||||
|
||||
def pipeline_search(self, queryset, _, value):
|
||||
"""
|
||||
This method is used to search recruitment
|
||||
"""
|
||||
queryset = queryset.filter(stage__icontains=value) | queryset.filter(
|
||||
candidate__name__icontains=value
|
||||
)
|
||||
return queryset.distinct()
|
||||
|
||||
|
||||
class SurveyFilter(FilterSet):
|
||||
@@ -310,6 +354,20 @@ class SurveyFilter(FilterSet):
|
||||
]
|
||||
|
||||
|
||||
class SurveyTemplateFilter(django_filters.FilterSet):
|
||||
"""
|
||||
SurveyTemplateFilter
|
||||
"""
|
||||
question = django_filters.CharFilter(
|
||||
lookup_expr="icontains",
|
||||
label="Title",
|
||||
field_name="title",
|
||||
)
|
||||
class Meta:
|
||||
model = SurveyTemplate
|
||||
fields = "__all__"
|
||||
|
||||
|
||||
class CandidateReGroup:
|
||||
"""
|
||||
Class to keep the field name for group by option
|
||||
@@ -342,7 +400,6 @@ class SkillZoneFilter(FilterSet):
|
||||
"skillzonecandidate_set__candidate_id__recruitment_id",
|
||||
"skillzonecandidate_set__candidate_id__job_position_id",
|
||||
"skillzonecandidate_set__candidate_id__stage_id__stage_type",
|
||||
|
||||
]
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user