Skip to content

Commit

Permalink
feat: update employee record list filters ui
Browse files Browse the repository at this point in the history
  • Loading branch information
hellodeloo committed May 28, 2024
1 parent 48b94a3 commit 25d2485
Show file tree
Hide file tree
Showing 10 changed files with 78 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<li>
<div class="dropdown-item">
<div class="form-check">
<input class="form-check-input" type="radio" name="{{ choice.data.name }}" id="{{ choice.id_for_label }}" value="{{ choice.data.value }}"{% if choice.data.selected %} checked="checked"{% endif %}>
<input class="form-check-input" type="radio" name="{{ choice.data.name }}" id="{{ choice.id_for_label }}" value="{{ choice.data.value }}"{% if choice.data.selected %} checked{% endif %}>
<label class="form-check-label" for="{{ choice.id_for_label }}">{{ choice.data.label }}</label>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{% load list_filters %}

<div id="employee-records-list-filters" {% if request.htmx %}hx-swap-oob="true"{% endif %}>
{% for choice, badge in form.status|zip:badges %}
<li>
<div class="dropdown-item">
<div class="form-check">
<input class="form-check-input" type="radio" name="{{ choice.data.name }}" id="{{ choice.id_for_label }}" value="{{ choice.data.value }}"{% if choice.data.selected %} checked{% endif %}>
<label class="form-check-label" for="{{ choice.id_for_label }}">
{{ choice.data.label }}
<span class="badge rounded-pill badge-xs {{ badge.1 }}">{{ badge.0 }}</span>
</label>
</div>
</div>
</li>
{% endfor %}
</div>
7 changes: 7 additions & 0 deletions itou/templates/employee_record/includes/list_counter.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{% load str_filters %}

{% with navigation_pages.paginator.count as counter %}
<h3 class="h4 m-0 me-auto" id="employee-record-list-count"{% if request.htmx %} hx-swap-oob="true"{% endif %}>
{{ counter }} résultat{{ counter|pluralizefr }}
</h3>
{% endwith %}
21 changes: 0 additions & 21 deletions itou/templates/employee_record/includes/list_form_fields.html

This file was deleted.

24 changes: 3 additions & 21 deletions itou/templates/employee_record/includes/list_results.html
Original file line number Diff line number Diff line change
@@ -1,25 +1,7 @@
{% load django_bootstrap5 %}
{% load str_filters %}

<div id="employee-records-container">
<div class="d-flex align-items-center">
<div class="flex-grow-1">
{% with navigation_pages.paginator.count as counter %}
<h3 class="h4 m-0">{{ counter }} résultat{{ counter|pluralizefr }}</h3>
{% endwith %}
</div>
<div>
<span class="fs-sm">Trier par :</span>
<button type="button" class="btn btn-sm btn-link dropdown-toggle p-0" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{{ ordered_by_label }}
</button>
<div class="dropdown-menu dropdown-menu-end" id="order-form-group">
{% for order_value, order_label in form.order.field.choices %}
<button class="dropdown-item {% if order_value == form.order.value %}active{% endif %}" type="button" value="{{ order_value }}">
{{ order_label }}
</button>
{% endfor %}
</div>
</div>
</div>
{# "Real" employee records objects #}
<div class="employee-records-list">
{% if employee_records_list %}
Expand All @@ -42,9 +24,9 @@ <h3 class="h4 m-0">{{ counter }} résultat{{ counter|pluralizefr }}</h3>
{% endif %}
{% include "includes/pagination.html" with page=navigation_pages boost=True boost_target="#employee-records-container" boost_indicator="#employee-records-container" %}
</div>

{% if request.htmx %}
{% include "employee_record/includes/list_status_help.html" with request=request status=form.status.value only %}
{% include "employee_record/includes/list_counter.html" %}
{% include "employee_record/includes/employee_record_filters/status.html" %}
{% include "employee_record/includes/employee_record_filters/reset.html" %}
{% endif %}
13 changes: 13 additions & 0 deletions itou/templates/employee_record/includes/list_sort.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<div>
<span class="fs-sm">Trier par :</span>
<button type="button" class="btn btn-sm btn-link dropdown-toggle p-0" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{{ ordered_by_label }}
</button>
<div class="dropdown-menu dropdown-menu-end" id="order-form-group">
{% for order_value, order_label in form.order.field.choices %}
<button class="dropdown-item {% if order_value == form.order.value %}active{% endif %}" type="button" value="{{ order_value }}">
{{ order_label }}
</button>
{% endfor %}
</div>
</div>
31 changes: 18 additions & 13 deletions itou/templates/employee_record/list.html
Original file line number Diff line number Diff line change
Expand Up @@ -57,18 +57,23 @@ <h2 class="h3">Nous transférons vos fiches salarié à l'ASP afin de vous faire
</div>
</div>
<div class="row">
<div class="col-12 col-md-4 mb-3 mb-md-5">
<aside class="c-aside-filters">
<button class="c-aside-filters__btn__collapse" data-bs-toggle="collapse" data-bs-target="#asideFiltersCollapse" aria-expanded="true" aria-controls="asideFiltersCollapse">
<i class="ri-filter-line" aria-hidden="true"></i>
<span>Filtres des fiches salarié</span>
</button>
<div class="c-aside-filters__card collapse show" id="asideFiltersCollapse">
<form hx-get="{% url 'employee_record_views:list' %}" hx-trigger="change delay:.5s" hx-indicator="#employee-records-container" hx-target="#employee-records-container" hx-swap="outerHTML" hx-push-url="true">
{% include "employee_record/includes/list_form_fields.html" %}
{# Filled via jQuery. Does not need reloading with HTMX, its content is static. #}
{{ form.order.as_hidden }}
</form>
<div class="col-12">
<form hx-get="{% url 'employee_record_views:list' %}"
hx-trigger="change delay:.5s, change from:#id_job_seekers"
hx-indicator="#employee-records-container"
hx-target="#employee-records-container"
hx-swap="outerHTML"
hx-push-url="true"
hx-include="#id_job_seekers">
<div class="btn-dropdown-filter-group mb-3 mb-md-4">
<div class="dropdown">
<button type="button" class="btn btn-dropdown-filter dropdown-toggle" data-bs-toggle="dropdown" data-bs-auto-close="outside" aria-expanded="false">
Statut
</button>
<ul class="dropdown-menu">
{% include "employee_record/includes/employee_record_filters/status.html" %}
</ul>
</div>
</div>
{# Filled via jQuery. Does not need reloading with HTMX, its content is static. #}
{{ form.order.as_hidden }}
Expand All @@ -86,7 +91,6 @@ <h2 class="h3">Nous transférons vos fiches salarié à l'ASP afin de vous faire
</div>
{% include "employee_record/includes/list_results.html" %}
</div>
<div class="col-12 col-md-8">{% include "employee_record/includes/list_results.html" %}</div>
</div>
</div>
</section>
Expand All @@ -95,6 +99,7 @@ <h2 class="h3">Nous transférons vos fiches salarié à l'ASP afin de vous faire
{% block script %}
{{ block.super }}
<script src='{% static "js/htmx_compat.js" %}'></script>
<script src='{% static "js/htmx_dropdown_filter.js" %}'></script>
<!-- Needed to use Select2MultipleWidget. -->
{{ filters_form.media.js }}
<script nonce="{{ CSP_NONCE }}">
Expand Down
8 changes: 6 additions & 2 deletions itou/www/employee_record_views/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,12 @@ class SelectEmployeeRecordStatusForm(forms.Form):
class EmployeeRecordFilterForm(forms.Form):
job_seekers = forms.MultipleChoiceField(
required=False,
label="Nom du candidat",
widget=Select2MultipleWidget,
label="Nom du salarié",
widget=Select2MultipleWidget(
attrs={
"data-placeholder": "Nom du salarié",
}
),
)

def __init__(self, job_seekers, *args, **kwargs):
Expand Down
10 changes: 5 additions & 5 deletions itou/www/employee_record_views/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,11 +193,11 @@ def list_employee_records(request, template_name="employee_record/list.html"):
len(eligible_job_applications) if status == Status.NEW else eligible_job_applications.count(),
"bg-info",
),
(employee_record_badges.get(Status.READY, 0), "bg-secondary"),
(employee_record_badges.get(Status.SENT, 0), "bg-warning"),
(employee_record_badges.get(Status.REJECTED, 0), "bg-danger"),
(employee_record_badges.get(Status.PROCESSED, 0), "bg-success"),
(employee_record_badges.get(Status.DISABLED, 0), "bg-emploi-lightest text-primary"),
(employee_record_badges.get(Status.READY, 0), "bg-emploi-lightest text-info"),
(employee_record_badges.get(Status.SENT, 0), "bg-emploi-lightest text-info"),
(employee_record_badges.get(Status.REJECTED, 0), "bg-warning"),
(employee_record_badges.get(Status.PROCESSED, 0), "bg-emploi-lightest text-info"),
(employee_record_badges.get(Status.DISABLED, 0), "bg-emploi-lightest text-info"),
]

# Employee records are created with a job application object.
Expand Down
9 changes: 8 additions & 1 deletion tests/www/employee_record_views/test_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ def test_htmx_new_employee_record_updates_badge_count(self):
response = self.client.get(self.URL, {"status": "NEW"})
simulated_page = parse_response_to_soup(response)
# This new application should update the counter badge on NEW.
JobApplicationWithApprovalNotCancellableFactory(to_company=self.company)
new_job_app = JobApplicationWithApprovalNotCancellableFactory(to_company=self.company)

[new_status] = simulated_page.find_all("input", attrs={"name": "status", "value": "NEW"})
del new_status["checked"]
Expand All @@ -523,6 +523,13 @@ def test_htmx_new_employee_record_updates_badge_count(self):

response = self.client.get(self.URL + "?status=READY")
fresh_page = parse_response_to_soup(response)
# Reloading the job seekers select2 with HTMX would change the
# select input the form listens to via hx-trigger, causing the
# form to no longer pick up change events from the select2.
# Given that options aren’t added frequently to that dropdown, wait
# until the next full page load to get new job seekers.
[new_jobseeker_opt] = fresh_page.select(f'#id_job_seekers > option[value="{new_job_app.job_seeker_id}"]')
new_jobseeker_opt.decompose()
assertSoupEqual(simulated_page, fresh_page)


Expand Down

0 comments on commit 25d2485

Please sign in to comment.