Add inline documents and messages to I1 checklist

This commit is contained in:
A R R R Associates
2026-08-08 12:55:39 +05:30
parent e1b5409bdf
commit 6b3d9fc730
6 changed files with 133 additions and 13 deletions
@@ -202,6 +202,90 @@
<span class="rounded-xl bg-slate-100 px-3 py-2 text-sm font-semibold text-slate-500">🔒 Locked</span>
{% endif %}
<details class="group w-full lg:w-auto">
<summary class="list-none cursor-pointer rounded-xl border border-violet-200 bg-violet-50 px-3 py-2 text-center text-sm font-semibold text-violet-700 hover:bg-violet-100">Documents{% if task.i1_documents %} · {{ task.i1_documents|length }}{% endif %}</summary>
<div class="mt-3 rounded-2xl border border-violet-200 bg-white p-4 lg:min-w-[620px]">
<div class="flex flex-wrap items-start justify-between gap-3">
<div>
<h5 class="font-semibold text-slate-900">Task Documents</h5>
<p class="mt-1 text-xs text-slate-500">Files stay linked to this task and engagement.</p>
</div>
<a href="/documents/tasks/{{ task.id }}?return_to=/employee/work/engagements/{{ board.engagement_id }}%3Ftask_id%3D{{ task.id }}%23task-{{ task.id }}" class="text-xs font-semibold text-violet-700 hover:underline">Open full document view</a>
</div>
{% if task.i1_documents %}
<div class="mt-3 divide-y divide-slate-100 rounded-xl border border-slate-200">
{% for doc in task.i1_documents[:5] %}
{% set latest = doc.versions[0] if doc.versions else none %}
<div class="flex flex-wrap items-center justify-between gap-2 px-3 py-2 text-sm">
<div class="min-w-0">
<div class="truncate font-medium text-slate-800">{{ doc.title }}</div>
<div class="truncate text-xs text-slate-500">{{ latest.original_filename if latest else doc.document_type }}{% if latest %} · v{{ latest.version_no }}{% endif %}</div>
</div>
{% if latest %}<a href="/documents/{{ doc.id }}/download" class="text-xs font-semibold text-brand-700 hover:underline">Download</a>{% endif %}
</div>
{% endfor %}
</div>
{% else %}
<div class="mt-3 rounded-xl border border-dashed border-slate-300 px-4 py-3 text-sm text-slate-500">No document attached yet.</div>
{% endif %}
<form method="post" action="/documents/tasks/{{ task.id }}/upload" enctype="multipart/form-data" class="mt-3 flex flex-col gap-2 sm:flex-row sm:items-end">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<input type="hidden" name="title" value="">
<input type="hidden" name="document_type" value="GENERAL">
<input type="hidden" name="return_to" value="/employee/work/engagements/{{ board.engagement_id }}?task_id={{ task.id }}#task-{{ task.id }}">
<label class="min-w-0 flex-1 text-xs font-semibold uppercase tracking-wide text-slate-500">Add file
<input type="file" name="file" required class="mt-1 w-full rounded-lg border border-slate-300 bg-white px-3 py-2 text-sm">
</label>
<button type="submit" class="rounded-lg bg-violet-600 px-4 py-2 text-sm font-semibold text-white hover:bg-violet-700">Upload</button>
</form>
</div>
</details>
<details class="group w-full lg:w-auto">
<summary class="list-none cursor-pointer rounded-xl border border-sky-200 bg-sky-50 px-3 py-2 text-center text-sm font-semibold text-sky-700 hover:bg-sky-100">Message / Clarification{% if task.i1_communications %} · {{ task.i1_communications|length }}{% endif %}</summary>
<div class="mt-3 rounded-2xl border border-sky-200 bg-white p-4 lg:min-w-[620px]">
<div class="flex flex-wrap items-start justify-between gap-3">
<div>
<h5 class="font-semibold text-slate-900">Messages / Clarifications</h5>
<p class="mt-1 text-xs text-slate-500">Add a note, clarification or client/consultant communication.</p>
</div>
<a href="/employee/work/tasks/{{ task.id }}/communication?return_to=/employee/work/engagements/{{ board.engagement_id }}%3Ftask_id%3D{{ task.id }}%23task-{{ task.id }}" class="text-xs font-semibold text-sky-700 hover:underline">Open full timeline</a>
</div>
{% if task.i1_communications %}
<div class="mt-3 max-h-52 divide-y divide-slate-100 overflow-y-auto rounded-xl border border-slate-200">
{% for item in task.i1_communications[:5] %}
<div class="px-3 py-2">
<div class="flex flex-wrap items-center justify-between gap-2 text-[11px] text-slate-500">
<span>{{ item.comment_type.replace('_',' ').title() }} · {{ item.visibility.replace('_',' ').title() }}</span>
<span>{{ item.created_at_utc }}</span>
</div>
<div class="mt-1 whitespace-pre-wrap text-sm text-slate-800">{{ item.message }}</div>
<div class="mt-1 text-[11px] text-slate-400">By {{ item.created_by.full_name if item.created_by else 'System/User' }}</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="mt-3 rounded-xl border border-dashed border-slate-300 px-4 py-3 text-sm text-slate-500">No message or clarification yet.</div>
{% endif %}
<form method="post" action="/employee/work/tasks/{{ task.id }}/communication" class="mt-3 grid gap-2 sm:grid-cols-2">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<input type="hidden" name="return_to" value="/employee/work/engagements/{{ board.engagement_id }}?task_id={{ task.id }}#task-{{ task.id }}">
<select name="comment_type" class="rounded-lg border border-slate-300 px-3 py-2 text-sm">
{% for code, label in board.communication_types %}<option value="{{ code }}">{{ label }}</option>{% endfor %}
</select>
<select name="visibility" class="rounded-lg border border-slate-300 px-3 py-2 text-sm">
{% for code, label in board.communication_visibilities %}<option value="{{ code }}">{{ label }}</option>{% endfor %}
</select>
<textarea name="message" rows="2" required class="sm:col-span-2 w-full rounded-lg border border-slate-300 px-3 py-2 text-sm" placeholder="Type message or clarification"></textarea>
<div class="sm:col-span-2 flex justify-end"><button type="submit" class="rounded-lg bg-sky-600 px-4 py-2 text-sm font-semibold text-white hover:bg-sky-700">Send</button></div>
</form>
</div>
</details>
<details class="group w-full lg:w-auto">
<summary class="list-none cursor-pointer rounded-xl border border-slate-300 bg-white px-3 py-2 text-center text-sm font-semibold text-slate-700 hover:bg-slate-50">Details</summary>
<div class="mt-3 rounded-2xl border border-slate-200 bg-slate-50 p-4 lg:min-w-[720px]">
@@ -243,10 +327,7 @@
</div>
<div class="flex flex-wrap items-center justify-between gap-2">
<div class="flex flex-wrap gap-2">
<a href="/documents/tasks/{{ task.id }}" class="rounded-lg border border-violet-200 bg-white px-3 py-2 text-sm font-semibold text-violet-700">Evidence{% if task.i1_has_evidence %} ✓{% endif %}</a>
<a href="/employee/work/tasks/{{ task.id }}/communication" class="rounded-lg border border-slate-300 bg-white px-3 py-2 text-sm font-semibold text-slate-700">Communication{% if task.comment_count %} · {{ task.comment_count }}{% endif %}</a>
</div>
<div class="text-xs text-slate-500">Documents and messages can be added directly from this checklist row.</div>
<button type="submit" class="rounded-lg bg-brand-600 px-4 py-2 text-sm font-semibold text-white">Save Details</button>
</div>
</form>
@@ -44,6 +44,7 @@
<h3 class="font-semibold text-slate-900">Add communication</h3>
<form method="post" action="{{ post_url }}" class="mt-4 space-y-4">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<input type="hidden" name="return_to" value="{{ return_to or back_url }}">
<div class="grid gap-3 md:grid-cols-2">
<label class="block text-sm font-medium text-slate-700">Type
<select name="comment_type" class="mt-1 w-full rounded-xl border border-slate-300 px-3 py-2 text-sm focus:border-brand-500 focus:outline-none focus:ring-2 focus:ring-brand-100">