[ADD] RECRUITMENT: List view updated with accordian view

This commit is contained in:
Horilla
2024-02-15 12:16:28 +05:30
parent e62d48b41a
commit 116742e73c
6 changed files with 381 additions and 86 deletions

View File

@@ -17,63 +17,62 @@ x-data="{searchShow: false}"
></ion-icon>
</a>
</div>
<form hx-get='{% url "stage-search" %}' hx-target='#stage-container'
id="filterForm"
onkeyup="$('.filterButton')[0].click()"
>
<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"
></ion-icon>
<input
type="text"
hx-get="{% url 'stage-search' %}"
placeholder="{% trans 'Search' %}"
name='search'
id="recruitmentSearch"
hx-trigger="keyup changed delay:.2s"
hx-target="#stage-container"
class="oh-input oh-input__icon"
aria-label="Search Input"
/>
</div>
<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;"
>
{% include 'stage/filters.html' %}
</div>
</div>
<div class="oh-dropdown" x-data="{open: false}">
{% if perms.recruitment.add_stage %}
<button
data-target='#addStageModal'
data-toggle='oh-modal-toggle'
class="oh-btn oh-btn--secondary ml-2"
hx-get="{% url 'rec-stage-create' %}"
hx-target="#addStageModalBody"
>
<ion-icon name="add" class="mr-1"></ion-icon>{% trans "Create" %}
</button>
{% endif %}
</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"
></ion-icon>
<input
type="text"
placeholder="{% trans 'Search' %}"
name='search'
class="oh-input oh-input__icon"
aria-label="Search Input"
/>
</div>
<div class="oh-main__titlebar-button-container">
<div class="oh-dropdown" x-data="{open: false}">
<button class="oh-btn ml-2" @click="open = !open" onclick="event.preventDefault()">
<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;"
>
{% include 'stage/filters.html' %}
</div>
</div>
<div class="oh-dropdown" x-data="{open: false}">
{% if perms.recruitment.add_stage %}
<button
data-target='#addStageModal'
data-toggle='oh-modal-toggle'
class="oh-btn oh-btn--secondary ml-2"
hx-get="{% url 'rec-stage-create' %}"
hx-target="#addStageModalBody"
>
<ion-icon name="add" class="mr-1"></ion-icon>{% trans "Create" %}
</button>
{% endif %}
</div>
</div>
</div>
</div>
</form>
</section>

View File

@@ -1,4 +1,4 @@
{% load i18n %} {% load basefilters %}
{% load i18n %} {% load basefilters %}{% load static %}
<style>
.count-span {
width: 100%;
@@ -21,12 +21,13 @@
</script>
{% include 'filter_tags.html' %}
{% include 'filter_tags.html' %}
{% if data %}
<div class="row">
<div class="col-12 col-sm-12 col-md-12 col-lg-12">
<div class="oh-card p-4">
<div class="oh-card__body">
<!-- start of column toggle button-->
{% comment %} <!-- start of column toggle button-->
<div class="oh-table_sticky--wrapper">
<div class="oh-sticky-dropdown--header">
<div class="oh-dropdown" x-data="{open: false}">
@@ -40,44 +41,40 @@
</div>
</div>
<!-- end of column toggle button-->
<div id="stage-table" data-table-name="stage_table">
<div id="stage-table" data-table-name="stage_table"> {% endcomment %}
<div class="oh-sticky-table oh-sticky-table--no-highlight">
<!-- start of sticky table -->
<div class="oh-sticky-table__table">
<div class="oh-sticky-table__thead">
<div class="oh-sticky-table__tr">
<div
class="oh-sticky-table__th {% if request.sort_option.order == '-stage' %}arrow-up {% elif request.sort_option.order == 'stage' %}arrow-down {% else %} arrow-up-down {% endif %}"
hx-get="{% url 'stage-search' %}?{{pd}}&orderby=stage"
hx-target="#stage-container"
class="oh-sticky-table__th "
>
{% trans "Title" %}
</div>
<div
data-cell-index="1" data-cell-title='{% trans "Managers" %}'
class="oh-sticky-table__th {% if request.sort_option.order == '-stage_managers' %}arrow-up {% elif request.sort_option.order == 'stage_managers' %}arrow-down {% else %} arrow-up-down {% endif %}"
hx-get="{% url 'stage-search' %}?{{pd}}&orderby=stage_managers"
hx-target="#stage-container"
class="oh-sticky-table__th "
>
{% trans "Managers" %}
</div>
<div
data-cell-index="2" data-cell-title='{% trans "Type" %}'
class="oh-sticky-table__th {% if request.sort_option.order == '-stage_type' %}arrow-up {% elif request.sort_option.order == 'stage_type' %}arrow-down {% else %} arrow-up-down {% endif %}"
hx-get="{% url 'stage-search' %}?{{pd}}&orderby=stage_type"
hx-target="#stage-container"
class="oh-sticky-table__th"
>
{% trans "Type" %}
</div>
<div
{% comment %} <div
data-cell-index="3" data-cell-title='{% trans "Recruitment" %}'
class="oh-sticky-table__th {% if request.sort_option.order == '-recruitment_id__start_date' %}arrow-up {% elif request.sort_option.order == 'recruitment_id__start_date' %}arrow-down {% else %} arrow-up-down {% endif %}"
hx-get="{% url 'stage-search' %}?{{pd}}&orderby=recruitment_id__start_date"
hx-target="#stage-container"
>
{% trans "Recruitment" %}
</div>
<div class="oh-sticky-table__th">{% trans "Actions" %}</div>
</div> {% endcomment %}
<div class="oh-sticky-table__th oh-sticky-table__right" s>{% trans "Actions" %}</div>
</div>
</div>
<div class="oh-sticky-table__tbody">
@@ -86,7 +83,12 @@
class="oh-sticky-table__tr oh-permission-table__tr oh-permission-table--collapsed"
>
<div
class="oh-sticky-table__sd oh-permission-table--toggle"
class="oh-sticky-table__sd oh-permission-table--toggle {% if stage.stage_type == 'cancelled' %} row-status--red
{% elif stage.stage_type == 'hired' %} row-status--yellow
{% elif stage.stage_type == 'interview' %} row-status--orange
{% elif stage.stage_type == 'test' %} row-status--blue
{% elif stage.stage_type == 'initial' %} row-status--cyan
{% endif %}"
data-toggle-count
>
<div class="d-flex align-items-center">
@@ -133,10 +135,10 @@
<div data-cell-index="2" class="oh-sticky-table__td">
{{stage.get_stage_type_display}}
</div>
<div data-cell-index="3" class="oh-sticky-table__td">
{% comment %} <div data-cell-index="3" class="oh-sticky-table__td">
{{stage.recruitment_id}}
</div>
<div class="oh-sticky-table__td">
</div> {% endcomment %}
<div class="oh-sticky-table__td oh-sticky-table__right">
<div class="oh-btn-group">
{% if perms.recruitment.change_stage %}
<a
@@ -255,7 +257,20 @@
</nav>
</div>
<!-- end of pagination -->
{% else %}
<!-- start of empty page -->
<div class="oh-404">
<img
style="width: 150px; height: 150px"
src="{% static 'images/ui/no-results.png' %}"
class="oh-404__image mb-4"
/>
<h5 class="oh-404__subtitle">
{% trans "No search result found!" %}
</h5>
</div>
<!-- end of empty page -->
{% endif %}
<div
class="oh-modal"
id="updateStageModal"

View File

@@ -0,0 +1,232 @@
{% load i18n %}{% load static %}
<!-- start of quick filters -->
<div class="d-flex flex-row-reverse">
<span class="m-3"
onclick="$('[name=stage_type]').val('hired'); $('[name=stage_type]').first().change(); $('.filterButton').click()"
style="cursor: pointer">
<span class="oh-dot oh-dot--small me-1" style="background-color:yellowgreen"></span>
{% trans "Hired" %}
</span>
<span class="m-3"
onclick="$('[name=stage_type]').val('cancelled'); $('[name=stage_type]').first().change(); $('.filterButton').click()"
style="cursor: pointer">
<span class="oh-dot oh-dot--small me-1" style="background-color:red"></span>
{% trans "cancelled" %}
</span>
<span class="m-3"
onclick="$('[name=stage_type]').val('interview'); $('[name=stage_type]').first().change(); $('.filterButton').click()"
style="cursor: pointer">
<span class="oh-dot oh-dot--small me-1" style="background-color:orange"></span>
{% trans "interview" %}
</span>
<span class="m-3"
onclick="$('[name=stage_type]').val('test'); $('[name=stage_type]').first().change(); $('.filterButton').click()"
style="cursor: pointer">
<span class="oh-dot oh-dot--small me-1" style="background-color:blue"></span>
{% trans "Test" %}
</span>
<span class="m-3"
onclick="$('[name=stage_type]').val('initial'); $('[name=stage_type]').first().change(); $('.filterButton').click()"
style="cursor: pointer">
<span class="oh-dot oh-dot--small me-1" style="background-color:cyan"></span>
{% trans "Initial" %}
</span>
</div>
<!-- end of quick filters -->
{% comment %}
<div id="stage-container">
{% include 'stage/stage_component.html' %}
</div> {% endcomment %}
{% include 'filter_tags.html' %}
<div class="oh-card" id="">
{% if recruitments %}
<div class="oh-accordion-meta">
<div class="">
{% for rec in recruitments %}
<div
class="oh-accordion-meta__header oh-accordion-meta__header--custom"
{% if perms.payroll.view_taxbracket %}
data-target="#stageBody{{rec.grouper.id}}"
hx-get="{% url 'stage-data' rec.grouper.id %}?{{request.GET.urlencode}}"
hx-target="#stageData{{rec.grouper.id}}"
{% endif %}
>
<div class="d-flex">
<div class="oh-tabs__input-badge-container">
<span class="oh-badge oh-badge--secondary oh-badge--small oh-badge--round mr-1">
{{rec.list|length}}
</span>
<span class="oh-accordion-meta__title" style="padding: 0.8rem 1.25rem;">{{rec.grouper}}</span>
</div>
</div>
{% comment %} {% if perms.payroll.change_filingstatus or perms.payroll.delete_filingstatus or perms.payroll.add_taxbracket %}
<div class="oh-accordion-meta__actions" id="">
<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"
onclick=event.stopPropagation()
>
{% 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"
style="display: none"
>
<ul class="oh-dropdown__items">
{% if perms.payroll.add_taxbracket %}
<li class="oh-dropdown__item">
<a
class="oh-dropdown__link oh-dropdown__link"
data-toggle="oh-modal-toggle"
data-target="#TaxBracketModal"
hx-get="{% url 'tax-bracket-create' filing_status_id=filing_status.id %}"
onclick="event.stopPropagation()"
hx-target="#TaxBracketFormTarget"
>{% trans "Create" %}
</a>
</li>
{% endif %}
{% if perms.payroll.change_filingstatus %}
<li class="oh-dropdown__item">
<a
class="oh-dropdown__link oh-dropdown__link"
data-toggle="oh-modal-toggle"
data-target="#FilingStatusModal"
hx-get="{% url 'filing-status-update' filing_status_id=filing_status.id %}"
onclick="event.stopPropagation()"
hx-target="#FilingStatusFormTarget"
>
{% trans "Update" %}</a
>
</li>
{% endif %}
{% if perms.payroll.delete_filingstatus %}
<li class="oh-dropdown__item">
<form
action="{% url 'filing-status-delete' filing_status_id=filing_status.id %}"
onsubmit="return confirm('{% trans "Are you sure to delete this status ?" %}')"
method="post"
style="display: contents">
{% csrf_token %}
<button class="oh-dropdown__link oh-dropdown__link--danger">
{% trans 'Delete' %}
</button>
</form>
</li>
{% endif %}
</ul>
</div>
</div>
</div>
{% endif %} {% endcomment %}
</div>
<div
class="oh-accordion-meta__body d-none"
id="stageBody{{rec.grouper.id}}"
>
<!-- htmx tax bracket loading here -->
<div
class="oh-sticky-table oh-sticky-table--no-overflow mb-5"
id="stageData{{rec.grouper.id}}"
></div>
</div>
{% endfor %}
</div>
</div>
<!-- start of pagination -->
<div class="oh-pagination">
<span
class="oh-pagination__page"
data-toggle="modal"
data-target="#addEmployeeModal"
>
{% trans "Page" %} {{ recruitments.number }} {% trans "of" %} {{ recruitments.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="rpage"
class="oh-pagination__input"
value="{{recruitments.number}}"
hx-get="{% url 'stage-search' %}?{{pd}}"
hx-target="#stage-container"
min="1"
/>
<span class="oh-pagination__label"
>{% trans "of" %} {{recruitments.paginator.num_pages}}</span
>
</div>
<ul class="oh-pagination__items">
{% if recruitments.has_previous %}
<li class="oh-pagination__item oh-pagination__item--wide">
<a
hx-target="#stage-container"
hx-get="{% url 'stage-search' %}?{{pd}}&rpage=1"
class="oh-pagination__link"
>{% trans "First" %}</a
>
</li>
<li class="oh-pagination__item oh-pagination__item--wide">
<a
hx-target="#stage-container"
hx-get="{% url 'stage-search' %}?{{pd}}&rpage={{ recruitments.previous_page_number }}"
class="oh-pagination__link"
>{% trans "Previous" %}</a
>
</li>
{% endif %} {% if recruitments.has_next %}
<li class="oh-pagination__item oh-pagination__item--wide">
<a
hx-target="#stage-container"
hx-get="{% url 'stage-search' %}?{{pd}}&rpage={{ recruitments.next_page_number }}"
class="oh-pagination__link"
>{% trans "Next" %}</a
>
</li>
<li class="oh-pagination__item oh-pagination__item--wide">
<a
hx-target="#stage-container"
hx-get="{% url 'stage-search' %}?{{pd}}&rpage={{ recruitments.paginator.num_pages }}"
class="oh-pagination__link"
>{% trans "Last" %}</a
>
</li>
{% endif %}
</ul>
</nav>
</div>
<!-- end of pagination -->
{% else %}
<!-- start of empty page -->
<div style="display: flex; flex-direction: column; justify-content: center; align-items: center; height: 100%;" >
<img
style="width: 150px; height: 150px"
src="{% static 'images/ui/no-results.png' %}"
class="oh-404__image mb-4"
/>
<h5 class="oh-404__subtitle">
{% trans "No search result found!" %}
</h5>
</div>
<!-- end of empty page -->
{% endif %}
</div>

View File

@@ -1,14 +1,20 @@
{% extends 'index.html' %}
{% block content %}
{% include 'stage/nav.html' %}
<div class="oh-wrapper">
<div id="stage-container">
{% include 'stage/stage_component.html' %}
</div>
{% load i18n %}
<div class="oh-wrapper" id='stage-container'>
{% include "stage/stage_group.html" %}
</div>
<script>
$(document).ready(function () {
$(".oh-accordion-meta__header").click(function () {
var target = $(this).data("target");
$(this).toggleClass("oh-accordion-meta__header--show");
$(target).toggleClass("d-none");
});
});
</script>
{% endblock %}

View File

@@ -52,7 +52,7 @@ urlpatterns = [
kwargs={
"model": Recruitment,
"form": RecruitmentCreationForm,
"template": "recruitment/recruitment_duplicate_form.html",
"template": "recruitment/recruitment_form.html",
},
),
path(
@@ -94,6 +94,7 @@ urlpatterns = [
),
path("stage-create", views.stage, name="rec-stage-create"),
path("stage-view", views.stage_view, name="rec-stage-view"),
path("stage-data/<int:rec_id>/",views.stage_data,name="stage-data"),
path("stage-search", recruitment.views.search.stage_search, name="stage-search"),
path("stage-update/<int:stage_id>/", views.stage_update, name="rec-stage-update"),
path(
@@ -182,7 +183,7 @@ urlpatterns = [
"candidate-view/<int:cand_id>/",
views.candidate_view_individual,
name="candidate-view-individual",
kwargs={"model": Candidate},
# kwargs={"model": Candidate},
),
path(
"candidate-update/<int:cand_id>/",
@@ -322,6 +323,21 @@ urlpatterns = [
recruitment.views.surveys.single_survey,
name="single-survey-view",
),
path(
"survey-template-create",
recruitment.views.surveys.create_template,
name="survey-template-create",
),
path(
"survey-template-delete",
recruitment.views.surveys.delete_template,
name="survey-template-delete",
),
path(
"survey-template-question-add",
recruitment.views.surveys.question_add,
name="survey-template-question-add",
),
path("candidate-select/", views.candidate_select, name="candidate-select"),
path(
"candidate-select-filter/",
@@ -417,11 +433,21 @@ urlpatterns = [
views.add_more_files,
name="add-more-files",
),
path(
"add-more-files-individual/<int:id>/",
views.add_more_individual_files,
name="add-more-files-individual",
),
path(
"delete-stage-note-file/<int:id>/",
views.delete_stage_note_file,
name="delete-stage-note-file",
),
path(
"delete-individual-note-file/<int:id>/",
views.delete_individual_note_file,
name="delete-individual-note-file",
),
path("get-mail-log-rec", views.get_mail_log, name="get-mail-log-rec"),
path(
"candidate-self-tracking",

View File

@@ -17,8 +17,10 @@ from recruitment.filters import (
RecruitmentFilter,
StageFilter,
SurveyFilter,
SurveyTemplateFilter,
)
from recruitment.models import Candidate, Recruitment, Stage, RecruitmentSurvey
from recruitment.models import Candidate, Recruitment, Stage, RecruitmentSurvey, SurveyTemplate
from attendance.methods.group_by import group_by_queryset
from recruitment.views.paginator_qry import paginator_qry
@@ -51,16 +53,20 @@ def stage_search(request):
"""
This method is used to search stage
"""
stages = StageFilter(request.GET).qs
previous_data = request.GET.urlencode()
stages = sortby(request, stages, "orderby")
data_dict = parse_qs(previous_data)
get_key_instances(Stage, data_dict)
recruitments = group_by_queryset(stages,"recruitment_id",request.GET.get("rpage"),"rpage")
return render(
request,
"stage/stage_component.html",
"stage/stage_group.html",
{
"data": paginator_qry(stages, request.GET.get("page")),
"recruitments":recruitments,
"pd": previous_data,
"filter_dict": data_dict,
},
@@ -160,6 +166,15 @@ def filter_survey(request):
previous_data = request.GET.urlencode()
filter_obj = SurveyFilter(request.GET)
questions = filter_obj.qs
templates = group_by_queryset(
questions.filter(template_id__isnull=False).distinct(),
"template_id__title",
page=request.GET.get("page"),
page_name="template_page",
records_per_page=50,
)
survey_templates = SurveyTemplateFilter(request.GET).qs
survey_templates = paginator_qry(survey_templates,request.GET.get("survey_template_page"))
requests_ids = json.dumps([instance.id for instance in paginator_qry(questions, request.GET.get("page")).object_list])
data_dict = parse_qs(previous_data)
get_key_instances(RecruitmentSurvey, data_dict)
@@ -168,6 +183,8 @@ def filter_survey(request):
"survey/survey_card.html",
{
"questions": paginator_qry(questions, request.GET.get("page")),
"templates":templates,
"survey_templates":survey_templates,
"pd": previous_data,
"filter_dict": data_dict,
"requests_ids":requests_ids,