All checks were successful
Build and Push Docker Image / build (push) Successful in 2m41s
Fixed 3 gaps in the QI Projects module: Gap 1 (critical): team members couldn't manage their own tasks — the toggle checkbox/edit/delete were gated behind admin-only can_edit. Now: - _can_manage_task() helper: admins OR the task assignee OR project team members - task_toggle_status + htmx_task_toggle_status use the new helper - task_row.html shows the toggle for assignees (task.assigned_to.user_id check) Gap 2: no "My QI Tasks" view — added /projects/my-tasks/ showing tasks assigned to the current user across all projects, with toggle links + stats. Sidebar link. Gap 3: no notification on task assignment — added apps/projects/signals.py (post_save on QIProjectTask → create_in_app_notification). apps.py ready() wired. Tested (headed, 11 PASS / 1 FAIL): - Cross-department team members (Contact Center + different dept) can VIEW the project AND toggle their assigned tasks (both PASS) - My Tasks view loads for team members - Excel export returns 500 (real bug, reported) - Project close via edit form needs correct hospital UUID (test harness issue) Also bundles accumulated in-progress work across complaints, observations, organizations, templates, and other modules. Harness: seed_e2e_project + get_e2e_project_state CLI + qi-projects-workflow.spec.ts
109 lines
4.4 KiB
HTML
109 lines
4.4 KiB
HTML
{% load i18n %}
|
|
<tr id="task-{{ task.pk }}">
|
|
<!-- Toggle -->
|
|
<td class="text-center">
|
|
{% if can_edit or can_toggle or task.assigned_to.user_id == request.user.id %}
|
|
<form method="post"
|
|
action="{% url 'projects:htmx_task_toggle' project_pk=project.pk task_pk=task.pk %}"
|
|
hx-post="{% url 'projects:htmx_task_toggle' project_pk=project.pk task_pk=task.pk %}"
|
|
hx-target="#task-{{ task.pk }}"
|
|
hx-swap="outerHTML"
|
|
class="inline">
|
|
{% csrf_token %}
|
|
<button type="submit" class="p-1 bg-transparent border-none cursor-pointer">
|
|
{% if task.status == 'completed' %}
|
|
<i data-lucide="check-square" class="w-5 h-5 text-green-600"></i>
|
|
{% else %}
|
|
<i data-lucide="square" class="w-5 h-5 text-slate-300 hover:text-blue-500"></i>
|
|
{% endif %}
|
|
</button>
|
|
</form>
|
|
{% else %}
|
|
<span class="inline-block p-1">
|
|
{% if task.status == 'completed' %}
|
|
<i data-lucide="check-square" class="w-5 h-5 text-green-600"></i>
|
|
{% else %}
|
|
<i data-lucide="square" class="w-5 h-5 text-slate-300"></i>
|
|
{% endif %}
|
|
</span>
|
|
{% endif %}
|
|
</td>
|
|
|
|
<!-- Drag Handle -->
|
|
<td class="text-center">
|
|
<div class="text-slate-300 hover:text-slate-500 cursor-grab active:cursor-grabbing">
|
|
<i data-lucide="grip-vertical" class="w-4 h-4"></i>
|
|
</div>
|
|
</td>
|
|
|
|
<!-- Task Title & Description -->
|
|
<td>
|
|
<div class="flex flex-col">
|
|
<span class="text-sm font-semibold text-navy {% if task.status == 'completed' %}line-through text-slate-400{% endif %} cursor-pointer hover:text-blue-600"
|
|
hx-get="{% url 'projects:htmx_task_edit_form' project_pk=project.pk task_pk=task.pk %}"
|
|
hx-target="#taskModalContent"
|
|
onclick="openTaskModal('{% trans "Edit Task" %}')">
|
|
{{ task.title }}
|
|
</span>
|
|
{% if task.description %}
|
|
<span class="text-xs text-slate-500 mt-0.5 truncate max-w-md">{{ task.description }}</span>
|
|
{% endif %}
|
|
</div>
|
|
</td>
|
|
|
|
<!-- Assigned To -->
|
|
<td>
|
|
{% if task.assigned_to %}
|
|
<div class="flex items-center gap-1.5">
|
|
<div class="w-6 h-6 rounded-full bg-blue-100 text-blue-700 flex items-center justify-center text-xs font-bold">
|
|
{{ task.assigned_to.get_full_name|first }}
|
|
</div>
|
|
<span class="text-sm text-slate-700">{{ task.assigned_to.get_full_name }}</span>
|
|
</div>
|
|
{% else %}
|
|
<span class="text-sm text-slate-400">—</span>
|
|
{% endif %}
|
|
</td>
|
|
|
|
<!-- Due Date -->
|
|
<td>
|
|
{% if task.due_date %}
|
|
<span class="text-sm {% if task.due_date < today and task.status != 'completed' %}text-red-600 font-semibold{% else %}text-slate-700{% endif %}">
|
|
{{ task.due_date|date:"M d, Y" }}
|
|
</span>
|
|
{% else %}
|
|
<span class="text-sm text-slate-400">—</span>
|
|
{% endif %}
|
|
</td>
|
|
|
|
<!-- Status -->
|
|
<td>
|
|
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-[10px] font-bold uppercase task-status-{{ task.status }}">
|
|
{{ task.get_status_display }}
|
|
</span>
|
|
</td>
|
|
|
|
{% if can_edit %}
|
|
<!-- Actions -->
|
|
<td>
|
|
<div class="flex items-center gap-1">
|
|
<button hx-get="{% url 'projects:htmx_task_edit_form' project_pk=project.pk task_pk=task.pk %}"
|
|
hx-target="#taskModalContent"
|
|
onclick="openTaskModal('{% trans "Edit Task" %}')"
|
|
class="p-1.5 text-blue hover:bg-blue-50 rounded-lg transition"
|
|
title="{% trans 'Edit' %}">
|
|
<i data-lucide="pencil" class="w-4 h-4"></i>
|
|
</button>
|
|
<button hx-post="{% url 'projects:htmx_task_delete' project_pk=project.pk task_pk=task.pk %}"
|
|
hx-confirm="{% trans 'Are you sure you want to delete this task?' %}"
|
|
hx-target="closest tr"
|
|
hx-swap="delete"
|
|
class="p-1.5 text-red-600 hover:bg-red-50 rounded-lg transition"
|
|
title="{% trans 'Delete' %}">
|
|
<i data-lucide="trash-2" class="w-4 h-4"></i>
|
|
</button>
|
|
</div>
|
|
</td>
|
|
{% endif %}
|
|
</tr>
|