refactor: replace emoji status flags with Bootstrap icons and enable HTML rendering for system messages in discussions.

This commit is contained in:
kdeterme 2026-09-09 17:30:32 +02:00
parent 9657111a1c
commit ae540acacc
9 changed files with 113 additions and 58 deletions

View file

@ -575,8 +575,16 @@
<div class="dropdown"> <div class="dropdown">
<button class="btn btn-sm btn-outline-light py-0 px-2 rounded-pill d-flex align-items-center gap-1 border-0 bg-white bg-opacity-20 dropdown-toggle" <button class="btn btn-sm btn-outline-light py-0 px-2 rounded-pill d-flex align-items-center gap-1 border-0 bg-white bg-opacity-20 dropdown-toggle"
type="button" id="interventionDiscussionFlagBtn" data-bs-toggle="dropdown" aria-expanded="false" style="font-size: 0.75rem;"> type="button" id="interventionDiscussionFlagBtn" data-bs-toggle="dropdown" aria-expanded="false" style="font-size: 0.75rem;">
<span id="intervention-flag-icon-display"> <span id="intervention-flag-icon-display" class="d-inline-flex align-items-center">
{% if discussion.flag == 'red' %}🚩{% elif discussion.flag == 'orange' %}🟧{% elif discussion.flag == 'green' %}🟩{% else %}🏳️{% endif %} {% if discussion.flag == 'red' %}
<i class="bi bi-flag-fill text-danger"></i>
{% elif discussion.flag == 'orange' %}
<i class="bi bi-flag-fill" style="color: #fd7e14;"></i>
{% elif discussion.flag == 'green' %}
<i class="bi bi-flag-fill text-success"></i>
{% else %}
<i class="bi bi-flag text-white-50"></i>
{% endif %}
</span> </span>
<span id="intervention-flag-label-display"> <span id="intervention-flag-label-display">
{{ discussion.flag_info.label|default:_("Statut") }} {{ discussion.flag_info.label|default:_("Statut") }}
@ -585,7 +593,7 @@
<ul class="dropdown-menu dropdown-menu-end shadow-sm" aria-labelledby="interventionDiscussionFlagBtn" style="font-size: 0.8rem; z-index: 1070;"> <ul class="dropdown-menu dropdown-menu-end shadow-sm" aria-labelledby="interventionDiscussionFlagBtn" style="font-size: 0.8rem; z-index: 1070;">
<li><h6 class="dropdown-header small text-muted py-1">{% translate "Statut de suivi" %}</h6></li> <li><h6 class="dropdown-header small text-muted py-1">{% translate "Statut de suivi" %}</h6></li>
<li><button type="button" class="dropdown-item d-flex align-items-center gap-2 intervention-flag-opt" data-flag="red"><i class="bi bi-flag-fill text-danger"></i> {% translate "Important / À traiter" %}</button></li> <li><button type="button" class="dropdown-item d-flex align-items-center gap-2 intervention-flag-opt" data-flag="red"><i class="bi bi-flag-fill text-danger"></i> {% translate "Important / À traiter" %}</button></li>
<li><button type="button" class="dropdown-item d-flex align-items-center gap-2 intervention-flag-opt" data-flag="orange"><i class="bi bi-flag-fill text-warning"></i> {% translate "En cours" %}</button></li> <li><button type="button" class="dropdown-item d-flex align-items-center gap-2 intervention-flag-opt" data-flag="orange"><i class="bi bi-flag-fill" style="color: #fd7e14;"></i> {% translate "En cours" %}</button></li>
<li><button type="button" class="dropdown-item d-flex align-items-center gap-2 intervention-flag-opt" data-flag="green"><i class="bi bi-flag-fill text-success"></i> {% translate "Traité / Fait" %}</button></li> <li><button type="button" class="dropdown-item d-flex align-items-center gap-2 intervention-flag-opt" data-flag="green"><i class="bi bi-flag-fill text-success"></i> {% translate "Traité / Fait" %}</button></li>
<li><hr class="dropdown-divider my-1"></li> <li><hr class="dropdown-divider my-1"></li>
<li><button type="button" class="dropdown-item d-flex align-items-center gap-2 intervention-flag-opt text-muted" data-flag=""><i class="bi bi-flag"></i> {% translate "Aucun drapeau" %}</button></li> <li><button type="button" class="dropdown-item d-flex align-items-center gap-2 intervention-flag-opt text-muted" data-flag=""><i class="bi bi-flag"></i> {% translate "Aucun drapeau" %}</button></li>
@ -602,8 +610,8 @@
{% for msg in discussion_messages %} {% for msg in discussion_messages %}
{% if msg.is_system %} {% if msg.is_system %}
<div class="d-flex justify-content-center my-1"> <div class="d-flex justify-content-center my-1">
<span class="badge bg-light text-secondary border px-2.5 py-1 rounded-pill" style="font-size: 0.75rem; font-weight: 500;"> <span class="badge bg-light text-secondary border px-2.5 py-1 rounded-pill d-inline-flex align-items-center" style="font-size: 0.75rem; font-weight: 500;">
{{ msg.content }} {{ msg.content|safe }}
</span> </span>
</div> </div>
{% else %} {% else %}

View file

@ -1059,10 +1059,10 @@ document.addEventListener('DOMContentLoaded', function () {
} }
if (headerIcon) { if (headerIcon) {
if (data.flag === 'red') headerIcon.textContent = '🚩'; if (data.flag === 'red') headerIcon.innerHTML = '<i class="bi bi-flag-fill text-danger"></i>';
else if (data.flag === 'orange') headerIcon.textContent = '🟧'; else if (data.flag === 'orange') headerIcon.innerHTML = '<i class="bi bi-flag-fill" style="color: #fd7e14;"></i>';
else if (data.flag === 'green') headerIcon.textContent = '🟩'; else if (data.flag === 'green') headerIcon.innerHTML = '<i class="bi bi-flag-fill text-success"></i>';
else headerIcon.textContent = '🏳️'; else headerIcon.innerHTML = '<i class="bi bi-flag text-white-50"></i>';
} }
if (headerLabel) { if (headerLabel) {
headerLabel.textContent = data.flag_info.label || '{% translate "Statut" %}'; headerLabel.textContent = data.flag_info.label || '{% translate "Statut" %}';

View file

@ -2575,8 +2575,16 @@
<div class="dropdown"> <div class="dropdown">
<button class="btn btn-sm btn-outline-light py-0 px-2 rounded-pill d-flex align-items-center gap-1 border-0 bg-white bg-opacity-20 dropdown-toggle" <button class="btn btn-sm btn-outline-light py-0 px-2 rounded-pill d-flex align-items-center gap-1 border-0 bg-white bg-opacity-20 dropdown-toggle"
type="button" id="mobDiscussionFlagBtn" data-bs-toggle="dropdown" aria-expanded="false" style="font-size: 0.75rem;"> type="button" id="mobDiscussionFlagBtn" data-bs-toggle="dropdown" aria-expanded="false" style="font-size: 0.75rem;">
<span id="mob-flag-icon-display"> <span id="mob-flag-icon-display" class="d-inline-flex align-items-center">
{% if discussion.flag == 'red' %}🚩{% elif discussion.flag == 'orange' %}🟧{% elif discussion.flag == 'green' %}🟩{% else %}🏳️{% endif %} {% if discussion.flag == 'red' %}
<i class="bi bi-flag-fill text-danger"></i>
{% elif discussion.flag == 'orange' %}
<i class="bi bi-flag-fill" style="color: #fd7e14;"></i>
{% elif discussion.flag == 'green' %}
<i class="bi bi-flag-fill text-success"></i>
{% else %}
<i class="bi bi-flag text-white-50"></i>
{% endif %}
</span> </span>
<span id="mob-flag-label-display"> <span id="mob-flag-label-display">
{{ discussion.flag_info.label|default:_("Statut") }} {{ discussion.flag_info.label|default:_("Statut") }}
@ -2585,7 +2593,7 @@
<ul class="dropdown-menu dropdown-menu-end shadow-sm" aria-labelledby="mobDiscussionFlagBtn" style="font-size: 0.8rem; z-index: 1070;"> <ul class="dropdown-menu dropdown-menu-end shadow-sm" aria-labelledby="mobDiscussionFlagBtn" style="font-size: 0.8rem; z-index: 1070;">
<li><h6 class="dropdown-header small text-muted py-1">{% translate "Statut de suivi" %}</h6></li> <li><h6 class="dropdown-header small text-muted py-1">{% translate "Statut de suivi" %}</h6></li>
<li><button type="button" class="dropdown-item d-flex align-items-center gap-2 mob-flag-opt" data-flag="red"><i class="bi bi-flag-fill text-danger"></i> {% translate "Important / À traiter" %}</button></li> <li><button type="button" class="dropdown-item d-flex align-items-center gap-2 mob-flag-opt" data-flag="red"><i class="bi bi-flag-fill text-danger"></i> {% translate "Important / À traiter" %}</button></li>
<li><button type="button" class="dropdown-item d-flex align-items-center gap-2 mob-flag-opt" data-flag="orange"><i class="bi bi-flag-fill text-warning"></i> {% translate "En cours" %}</button></li> <li><button type="button" class="dropdown-item d-flex align-items-center gap-2 mob-flag-opt" data-flag="orange"><i class="bi bi-flag-fill" style="color: #fd7e14;"></i> {% translate "En cours" %}</button></li>
<li><button type="button" class="dropdown-item d-flex align-items-center gap-2 mob-flag-opt" data-flag="green"><i class="bi bi-flag-fill text-success"></i> {% translate "Traité / Fait" %}</button></li> <li><button type="button" class="dropdown-item d-flex align-items-center gap-2 mob-flag-opt" data-flag="green"><i class="bi bi-flag-fill text-success"></i> {% translate "Traité / Fait" %}</button></li>
<li><hr class="dropdown-divider my-1"></li> <li><hr class="dropdown-divider my-1"></li>
<li><button type="button" class="dropdown-item d-flex align-items-center gap-2 mob-flag-opt text-muted" data-flag=""><i class="bi bi-flag"></i> {% translate "Aucun drapeau" %}</button></li> <li><button type="button" class="dropdown-item d-flex align-items-center gap-2 mob-flag-opt text-muted" data-flag=""><i class="bi bi-flag"></i> {% translate "Aucun drapeau" %}</button></li>
@ -2602,8 +2610,8 @@
{% for msg in discussion_messages %} {% for msg in discussion_messages %}
{% if msg.is_system %} {% if msg.is_system %}
<div class="d-flex justify-content-center my-1"> <div class="d-flex justify-content-center my-1">
<span class="badge bg-light text-secondary border px-2.5 py-1 rounded-pill" style="font-size: 0.75rem; font-weight: 500;"> <span class="badge bg-light text-secondary border px-2.5 py-1 rounded-pill d-inline-flex align-items-center" style="font-size: 0.75rem; font-weight: 500;">
{{ msg.content }} {{ msg.content|safe }}
</span> </span>
</div> </div>
{% else %} {% else %}
@ -6731,10 +6739,10 @@ document.addEventListener('DOMContentLoaded', function () {
} }
if (headerIcon) { if (headerIcon) {
if (data.flag === 'red') headerIcon.textContent = '🚩'; if (data.flag === 'red') headerIcon.innerHTML = '<i class="bi bi-flag-fill text-danger"></i>';
else if (data.flag === 'orange') headerIcon.textContent = '🟧'; else if (data.flag === 'orange') headerIcon.innerHTML = '<i class="bi bi-flag-fill" style="color: #fd7e14;"></i>';
else if (data.flag === 'green') headerIcon.textContent = '🟩'; else if (data.flag === 'green') headerIcon.innerHTML = '<i class="bi bi-flag-fill text-success"></i>';
else headerIcon.textContent = '🏳️'; else headerIcon.innerHTML = '<i class="bi bi-flag text-white-50"></i>';
} }
if (headerLabel) { if (headerLabel) {
headerLabel.textContent = data.flag_info.label || '{% translate "Statut" %}'; headerLabel.textContent = data.flag_info.label || '{% translate "Statut" %}';

View file

@ -488,20 +488,20 @@ def set_discussion_flag(discussion, flag, user=None):
if new_flag: if new_flag:
flag_label = dict(discussion.FLAG_CHOICES).get(new_flag, new_flag) flag_label = dict(discussion.FLAG_CHOICES).get(new_flag, new_flag)
if new_flag == 'red': if new_flag == 'red':
flag_icon = '🚩' flag_icon = '<i class="bi bi-flag-fill text-danger me-1"></i>'
elif new_flag == 'orange': elif new_flag == 'orange':
flag_icon = '🟧' flag_icon = '<i class="bi bi-flag-fill me-1" style="color: #fd7e14;"></i>'
elif new_flag == 'green': elif new_flag == 'green':
flag_icon = '🟩' flag_icon = '<i class="bi bi-flag-fill text-success me-1"></i>'
else: else:
flag_icon = '🏷️' flag_icon = '<i class="bi bi-flag me-1"></i>'
content = _("{icon} {user} a défini le statut : {label}").format( content = _("{icon} {user} a défini le statut : {label}").format(
icon=flag_icon, icon=flag_icon,
user=user_name, user=user_name,
label=flag_label, label=flag_label,
) )
else: else:
content = _("🏳️ {user} a retiré le drapeau de suivi.").format(user=user_name) content = _("<i class=\"bi bi-flag text-muted me-1\"></i> {user} a retiré le drapeau de suivi.").format(user=user_name)
sys_message = Message.objects.create( sys_message = Message.objects.create(
discussion=discussion, discussion=discussion,

View file

@ -13,23 +13,38 @@
{% csrf_token %} {% csrf_token %}
<div class="modal-body pt-3"> <div class="modal-body pt-3">
<div class="row g-2 mb-3"> <div class="row g-2 mb-3">
<div class="col-sm-8"> <div class="col-sm-7">
<label for="new-discussion-title" class="form-label small fw-semibold text-secondary"> <label for="new-discussion-title" class="form-label small fw-semibold text-secondary">
{% translate "Sujet / Titre (optionnel)" %} {% translate "Sujet / Titre (optionnel)" %}
</label> </label>
<input type="text" class="form-control rounded-3" id="new-discussion-title" name="title" <input type="text" class="form-control rounded-3" id="new-discussion-title" name="title"
placeholder="{% translate 'Ex: Question sur le dossier...' %}"> placeholder="{% translate 'Ex: Question sur le dossier...' %}">
</div> </div>
<div class="col-sm-4"> <div class="col-sm-5">
<label for="new-discussion-flag" class="form-label small fw-semibold text-secondary"> <label class="form-label small fw-semibold text-secondary d-block">
{% translate "Statut initial" %} {% translate "Statut initial" %}
</label> </label>
<select class="form-select rounded-3" id="new-discussion-flag" name="flag"> <div class="btn-group w-100" role="group" aria-label="{% translate 'Statut initial' %}">
<option value="">{% translate "Aucun" %}</option> <input type="radio" class="btn-check" name="flag" id="flag-init-none" value="" checked autocomplete="off">
<option value="red">🚩 {% translate "Important" %}</option> <label class="btn btn-outline-secondary btn-sm py-1.5 px-2" for="flag-init-none" title="{% translate 'Aucun drapeau' %}">
<option value="orange">🟧 {% translate "En cours" %}</option> <i class="bi bi-flag text-muted"></i>
<option value="green">🟩 {% translate "Traité" %}</option> </label>
</select>
<input type="radio" class="btn-check" name="flag" id="flag-init-red" value="red" autocomplete="off">
<label class="btn btn-outline-danger btn-sm py-1.5 px-2" for="flag-init-red" title="{% translate 'Important / À traiter' %}">
<i class="bi bi-flag-fill"></i>
</label>
<input type="radio" class="btn-check" name="flag" id="flag-init-orange" value="orange" autocomplete="off">
<label class="btn btn-outline-warning btn-sm py-1.5 px-2" for="flag-init-orange" title="{% translate 'En cours' %}">
<i class="bi bi-flag-fill" style="color: #fd7e14;"></i>
</label>
<input type="radio" class="btn-check" name="flag" id="flag-init-green" value="green" autocomplete="off">
<label class="btn btn-outline-success btn-sm py-1.5 px-2" for="flag-init-green" title="{% translate 'Traité / Fait' %}">
<i class="bi bi-flag-fill"></i>
</label>
</div>
</div> </div>
</div> </div>

View file

@ -183,9 +183,9 @@
{% for msg in thread_messages %} {% for msg in thread_messages %}
{% if msg.is_system %} {% if msg.is_system %}
<div class="d-flex justify-content-center my-2"> <div class="d-flex justify-content-center my-2">
<span class="badge bg-light text-secondary border px-3 py-1.5 rounded-pill shadow-xs" style="font-size: 0.8rem; font-weight: 500;"> <span class="badge bg-light text-secondary border px-3 py-1.5 rounded-pill shadow-xs d-inline-flex align-items-center" style="font-size: 0.8rem; font-weight: 500;">
{{ msg.content }} {{ msg.content|safe }}
<span class="ms-1 opacity-75 small">({{ msg.created_at|date:"d/m H:i" }})</span> <span class="ms-1.5 opacity-75 small">({{ msg.created_at|date:"d/m H:i" }})</span>
</span> </span>
</div> </div>
{% else %} {% else %}
@ -235,6 +235,7 @@
</div> </div>
{% endif %} {% endif %}
</div> </div>
{% endif %}
{% endfor %} {% endfor %}
</div> </div>
{% endif %} {% endif %}

View file

@ -537,13 +537,13 @@ class DiscussionFlagTests(TestCase):
self.assertIsNotNone(msg) self.assertIsNotNone(msg)
self.assertTrue(msg.is_system) self.assertTrue(msg.is_system)
self.assertIn("Alice Smith", msg.content) self.assertIn("Alice Smith", msg.content)
self.assertIn("🚩", msg.content) self.assertIn("bi-flag-fill text-danger", msg.content)
# 2. Change to green flag # 2. Change to green flag
msg2 = set_discussion_flag(self.discussion, 'green', user=self.user) msg2 = set_discussion_flag(self.discussion, 'green', user=self.user)
self.discussion.refresh_from_db() self.discussion.refresh_from_db()
self.assertEqual(self.discussion.flag, 'green') self.assertEqual(self.discussion.flag, 'green')
self.assertIn("🟩", msg2.content) self.assertIn("bi-flag-fill text-success", msg2.content)
# 3. Setting same flag returns None and doesn't create new message # 3. Setting same flag returns None and doesn't create new message
msg_noop = set_discussion_flag(self.discussion, 'green', user=self.user) msg_noop = set_discussion_flag(self.discussion, 'green', user=self.user)
@ -618,6 +618,13 @@ class DiscussionFlagTests(TestCase):
self.assertEqual(disc.flag, 'red') self.assertEqual(disc.flag, 'red')
self.assertEqual(disc.flag_set_by, self.user) self.assertEqual(disc.flag_set_by, self.user)
def test_discussion_detail_view_renders_template(self):
self.client.force_login(self.user)
from notifications.models import Message
Message.objects.create(discussion=self.discussion, author=self.user, content="Hello message")
Message.objects.create(discussion=self.discussion, author=self.user, content="🚩 System flag", is_system=True)
url = reverse('notifications:discussion_detail', args=[self.discussion.pk])
res = self.client.get(url)
self.assertEqual(res.status_code, 200)
self.assertContains(res, "Hello message")
self.assertContains(res, "System flag")

View file

@ -855,8 +855,16 @@
<div class="dropdown"> <div class="dropdown">
<button class="btn btn-sm btn-outline-secondary py-0 px-2 rounded-pill d-flex align-items-center gap-1 dropdown-toggle" <button class="btn btn-sm btn-outline-secondary py-0 px-2 rounded-pill d-flex align-items-center gap-1 dropdown-toggle"
type="button" id="obsDiscussionFlagBtn" data-bs-toggle="dropdown" aria-expanded="false" style="font-size: 0.75rem;"> type="button" id="obsDiscussionFlagBtn" data-bs-toggle="dropdown" aria-expanded="false" style="font-size: 0.75rem;">
<span id="obs-flag-icon-display"> <span id="obs-flag-icon-display" class="d-inline-flex align-items-center">
{% if discussion.flag == 'red' %}🚩{% elif discussion.flag == 'orange' %}🟧{% elif discussion.flag == 'green' %}🟩{% else %}🏳️{% endif %} {% if discussion.flag == 'red' %}
<i class="bi bi-flag-fill text-danger"></i>
{% elif discussion.flag == 'orange' %}
<i class="bi bi-flag-fill" style="color: #fd7e14;"></i>
{% elif discussion.flag == 'green' %}
<i class="bi bi-flag-fill text-success"></i>
{% else %}
<i class="bi bi-flag text-muted"></i>
{% endif %}
</span> </span>
<span id="obs-flag-label-display"> <span id="obs-flag-label-display">
{{ discussion.flag_info.label|default:_("Statut") }} {{ discussion.flag_info.label|default:_("Statut") }}
@ -865,7 +873,7 @@
<ul class="dropdown-menu dropdown-menu-end shadow-sm" aria-labelledby="obsDiscussionFlagBtn" style="font-size: 0.8rem;"> <ul class="dropdown-menu dropdown-menu-end shadow-sm" aria-labelledby="obsDiscussionFlagBtn" style="font-size: 0.8rem;">
<li><h6 class="dropdown-header small text-muted py-1">{% translate "Statut de suivi" %}</h6></li> <li><h6 class="dropdown-header small text-muted py-1">{% translate "Statut de suivi" %}</h6></li>
<li><button type="button" class="dropdown-item d-flex align-items-center gap-2 obs-flag-opt" data-flag="red"><i class="bi bi-flag-fill text-danger"></i> {% translate "Important / À traiter" %}</button></li> <li><button type="button" class="dropdown-item d-flex align-items-center gap-2 obs-flag-opt" data-flag="red"><i class="bi bi-flag-fill text-danger"></i> {% translate "Important / À traiter" %}</button></li>
<li><button type="button" class="dropdown-item d-flex align-items-center gap-2 obs-flag-opt" data-flag="orange"><i class="bi bi-flag-fill text-warning"></i> {% translate "En cours" %}</button></li> <li><button type="button" class="dropdown-item d-flex align-items-center gap-2 obs-flag-opt" data-flag="orange"><i class="bi bi-flag-fill" style="color: #fd7e14;"></i> {% translate "En cours" %}</button></li>
<li><button type="button" class="dropdown-item d-flex align-items-center gap-2 obs-flag-opt" data-flag="green"><i class="bi bi-flag-fill text-success"></i> {% translate "Traité / Fait" %}</button></li> <li><button type="button" class="dropdown-item d-flex align-items-center gap-2 obs-flag-opt" data-flag="green"><i class="bi bi-flag-fill text-success"></i> {% translate "Traité / Fait" %}</button></li>
<li><hr class="dropdown-divider my-1"></li> <li><hr class="dropdown-divider my-1"></li>
<li><button type="button" class="dropdown-item d-flex align-items-center gap-2 obs-flag-opt text-muted" data-flag=""><i class="bi bi-flag"></i> {% translate "Aucun drapeau" %}</button></li> <li><button type="button" class="dropdown-item d-flex align-items-center gap-2 obs-flag-opt text-muted" data-flag=""><i class="bi bi-flag"></i> {% translate "Aucun drapeau" %}</button></li>
@ -882,8 +890,8 @@
{% for msg in discussion_messages %} {% for msg in discussion_messages %}
{% if msg.is_system %} {% if msg.is_system %}
<div class="d-flex justify-content-center my-1"> <div class="d-flex justify-content-center my-1">
<span class="badge bg-light text-secondary border px-2.5 py-1 rounded-pill" style="font-size: 0.75rem; font-weight: 500;"> <span class="badge bg-light text-secondary border px-2.5 py-1 rounded-pill d-inline-flex align-items-center" style="font-size: 0.75rem; font-weight: 500;">
{{ msg.content }} {{ msg.content|safe }}
</span> </span>
</div> </div>
{% else %} {% else %}
@ -1899,10 +1907,10 @@ document.addEventListener('DOMContentLoaded', function() {
const headerLabel = document.getElementById('obs-flag-label-display'); const headerLabel = document.getElementById('obs-flag-label-display');
if (headerIcon) { if (headerIcon) {
if (data.flag === 'red') headerIcon.textContent = '🚩'; if (data.flag === 'red') headerIcon.innerHTML = '<i class="bi bi-flag-fill text-danger"></i>';
else if (data.flag === 'orange') headerIcon.textContent = '🟧'; else if (data.flag === 'orange') headerIcon.innerHTML = '<i class="bi bi-flag-fill" style="color: #fd7e14;"></i>';
else if (data.flag === 'green') headerIcon.textContent = '🟩'; else if (data.flag === 'green') headerIcon.innerHTML = '<i class="bi bi-flag-fill text-success"></i>';
else headerIcon.textContent = '🏳️'; else headerIcon.innerHTML = '<i class="bi bi-flag text-muted"></i>';
} }
if (headerLabel) { if (headerLabel) {
headerLabel.textContent = data.flag_info.label || '{% translate "Statut" %}'; headerLabel.textContent = data.flag_info.label || '{% translate "Statut" %}';

View file

@ -1735,8 +1735,16 @@ document.addEventListener('DOMContentLoaded', function() {
<div class="dropdown"> <div class="dropdown">
<button class="btn btn-sm btn-outline-light py-0 px-2 rounded-pill d-flex align-items-center gap-1 border-0 bg-white bg-opacity-20 dropdown-toggle" <button class="btn btn-sm btn-outline-light py-0 px-2 rounded-pill d-flex align-items-center gap-1 border-0 bg-white bg-opacity-20 dropdown-toggle"
type="button" id="poDiscussionFlagBtn" data-bs-toggle="dropdown" aria-expanded="false" style="font-size: 0.75rem;"> type="button" id="poDiscussionFlagBtn" data-bs-toggle="dropdown" aria-expanded="false" style="font-size: 0.75rem;">
<span id="po-flag-icon-display"> <span id="po-flag-icon-display" class="d-inline-flex align-items-center">
{% if discussion.flag == 'red' %}🚩{% elif discussion.flag == 'orange' %}🟧{% elif discussion.flag == 'green' %}🟩{% else %}🏳️{% endif %} {% if discussion.flag == 'red' %}
<i class="bi bi-flag-fill text-danger"></i>
{% elif discussion.flag == 'orange' %}
<i class="bi bi-flag-fill" style="color: #fd7e14;"></i>
{% elif discussion.flag == 'green' %}
<i class="bi bi-flag-fill text-success"></i>
{% else %}
<i class="bi bi-flag text-white-50"></i>
{% endif %}
</span> </span>
<span id="po-flag-label-display"> <span id="po-flag-label-display">
{{ discussion.flag_info.label|default:_("Statut") }} {{ discussion.flag_info.label|default:_("Statut") }}
@ -1745,7 +1753,7 @@ document.addEventListener('DOMContentLoaded', function() {
<ul class="dropdown-menu dropdown-menu-end shadow-sm" aria-labelledby="poDiscussionFlagBtn" style="font-size: 0.8rem; z-index: 1070;"> <ul class="dropdown-menu dropdown-menu-end shadow-sm" aria-labelledby="poDiscussionFlagBtn" style="font-size: 0.8rem; z-index: 1070;">
<li><h6 class="dropdown-header small text-muted py-1">{% translate "Statut de suivi" %}</h6></li> <li><h6 class="dropdown-header small text-muted py-1">{% translate "Statut de suivi" %}</h6></li>
<li><button type="button" class="dropdown-item d-flex align-items-center gap-2 po-flag-opt" data-flag="red"><i class="bi bi-flag-fill text-danger"></i> {% translate "Important / À traiter" %}</button></li> <li><button type="button" class="dropdown-item d-flex align-items-center gap-2 po-flag-opt" data-flag="red"><i class="bi bi-flag-fill text-danger"></i> {% translate "Important / À traiter" %}</button></li>
<li><button type="button" class="dropdown-item d-flex align-items-center gap-2 po-flag-opt" data-flag="orange"><i class="bi bi-flag-fill text-warning"></i> {% translate "En cours" %}</button></li> <li><button type="button" class="dropdown-item d-flex align-items-center gap-2 po-flag-opt" data-flag="orange"><i class="bi bi-flag-fill" style="color: #fd7e14;"></i> {% translate "En cours" %}</button></li>
<li><button type="button" class="dropdown-item d-flex align-items-center gap-2 po-flag-opt" data-flag="green"><i class="bi bi-flag-fill text-success"></i> {% translate "Traité / Fait" %}</button></li> <li><button type="button" class="dropdown-item d-flex align-items-center gap-2 po-flag-opt" data-flag="green"><i class="bi bi-flag-fill text-success"></i> {% translate "Traité / Fait" %}</button></li>
<li><hr class="dropdown-divider my-1"></li> <li><hr class="dropdown-divider my-1"></li>
<li><button type="button" class="dropdown-item d-flex align-items-center gap-2 po-flag-opt text-muted" data-flag=""><i class="bi bi-flag"></i> {% translate "Aucun drapeau" %}</button></li> <li><button type="button" class="dropdown-item d-flex align-items-center gap-2 po-flag-opt text-muted" data-flag=""><i class="bi bi-flag"></i> {% translate "Aucun drapeau" %}</button></li>
@ -1762,8 +1770,8 @@ document.addEventListener('DOMContentLoaded', function() {
{% for msg in discussion_messages %} {% for msg in discussion_messages %}
{% if msg.is_system %} {% if msg.is_system %}
<div class="d-flex justify-content-center my-1"> <div class="d-flex justify-content-center my-1">
<span class="badge bg-light text-secondary border px-2.5 py-1 rounded-pill" style="font-size: 0.75rem; font-weight: 500;"> <span class="badge bg-light text-secondary border px-2.5 py-1 rounded-pill d-inline-flex align-items-center" style="font-size: 0.75rem; font-weight: 500;">
{{ msg.content }} {{ msg.content|safe }}
</span> </span>
</div> </div>
{% else %} {% else %}
@ -2164,10 +2172,10 @@ document.addEventListener('DOMContentLoaded', function () {
} }
if (headerIcon) { if (headerIcon) {
if (data.flag === 'red') headerIcon.textContent = '🚩'; if (data.flag === 'red') headerIcon.innerHTML = '<i class="bi bi-flag-fill text-danger"></i>';
else if (data.flag === 'orange') headerIcon.textContent = '🟧'; else if (data.flag === 'orange') headerIcon.innerHTML = '<i class="bi bi-flag-fill" style="color: #fd7e14;"></i>';
else if (data.flag === 'green') headerIcon.textContent = '🟩'; else if (data.flag === 'green') headerIcon.innerHTML = '<i class="bi bi-flag-fill text-success"></i>';
else headerIcon.textContent = '🏳️'; else headerIcon.innerHTML = '<i class="bi bi-flag text-white-50"></i>';
} }
if (headerLabel) { if (headerLabel) {
headerLabel.textContent = data.flag_info.label || '{% translate "Statut" %}'; headerLabel.textContent = data.flag_info.label || '{% translate "Statut" %}';