Prepare ERP source for Gitea deployment
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
{% extends "ui/templates/base/layout.html" %}
|
||||
{% block content %}
|
||||
{% if role_context == 'client' %}
|
||||
{% include "modules/clients/templates/clients/_client_tabs.html" ignore missing %}
|
||||
{% elif role_context == 'consultant' %}
|
||||
{% include "modules/consultants/templates/consultants/_consultant_tabs.html" ignore missing %}
|
||||
{% elif role_context == 'partner' %}
|
||||
{% include "modules/partners/templates/partners/_partner_tabs.html" ignore missing %}
|
||||
{% elif role_context == 'manager' %}
|
||||
{% include "modules/managers/templates/managers/_manager_tabs.html" ignore missing %}
|
||||
{% elif role_context == 'staff' %}
|
||||
{% include "modules/employees/templates/employees/_my_workspace_tabs.html" ignore missing %}
|
||||
{% endif %}
|
||||
|
||||
{% set client = engagement.client %}
|
||||
{% set catalogue = engagement.catalogue %}
|
||||
<div class="space-y-6">
|
||||
<div class="rounded-3xl border border-slate-200 bg-white p-5 shadow-soft">
|
||||
<div class="flex flex-wrap items-start justify-between gap-4">
|
||||
<div>
|
||||
<div class="text-xs font-semibold uppercase tracking-wide text-slate-500">Unified Work Details</div>
|
||||
<h2 class="mt-1 text-2xl font-semibold text-slate-900">{{ catalogue.service_name if catalogue else 'Engagement' }}</h2>
|
||||
<p class="mt-1 text-sm text-slate-500">
|
||||
{{ client.client_name if client else 'Client' }}{% if client and client.client_code %} • {{ client.client_code }}{% endif %}
|
||||
{% if engagement.financial_year %} • FY {{ engagement.financial_year }}{% endif %}
|
||||
{% if engagement.assessment_year %} • AY {{ engagement.assessment_year }}{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex flex-wrap gap-2 text-xs font-semibold">
|
||||
<span class="rounded-full bg-slate-100 px-3 py-1 text-slate-700">{{ engagement.status.replace('_',' ').title() }}</span>
|
||||
{% if engagement.current_due_date %}<span class="rounded-full bg-amber-50 px-3 py-1 text-amber-700">Due {{ engagement.current_due_date.strftime('%d-%m-%Y') }}</span>{% endif %}
|
||||
<a href="{{ access.back_url }}" class="rounded-full border border-slate-300 px-3 py-1 text-slate-700 hover:bg-slate-50">Back</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-5 grid gap-3 md:grid-cols-4">
|
||||
<div class="rounded-2xl bg-slate-50 p-4"><div class="text-xs text-slate-500">Open Tasks</div><div class="mt-1 text-2xl font-semibold">{{ open_task_count }}</div></div>
|
||||
<div class="rounded-2xl bg-slate-50 p-4"><div class="text-xs text-slate-500">Completed</div><div class="mt-1 text-2xl font-semibold">{{ completed_task_count }}</div></div>
|
||||
<div class="rounded-2xl bg-slate-50 p-4"><div class="text-xs text-slate-500">Engagement Docs</div><div class="mt-1 text-2xl font-semibold">{{ engagement_documents|length }}</div></div>
|
||||
<div class="rounded-2xl bg-slate-50 p-4"><div class="text-xs text-slate-500">Timeline Notes</div><div class="mt-1 text-2xl font-semibold">{{ timeline|length }}</div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid gap-6 xl:grid-cols-[minmax(0,1fr)_360px]">
|
||||
<div class="space-y-4">
|
||||
<div class="rounded-3xl border border-slate-200 bg-white shadow-soft">
|
||||
<div class="border-b border-slate-200 px-5 py-4">
|
||||
<h3 class="font-semibold text-slate-900">Task Board</h3>
|
||||
<p class="text-xs text-slate-500">Role-sensitive task view. Clients and consultants see only permitted action/comment options.</p>
|
||||
</div>
|
||||
<div class="divide-y divide-slate-100">
|
||||
{% for task in tasks %}
|
||||
<div class="p-5">
|
||||
<div class="flex flex-wrap items-start justify-between gap-3">
|
||||
<div>
|
||||
<div class="font-semibold text-slate-900">{{ task.sequence_no }}. {{ task.task_name }}</div>
|
||||
{% if task.description %}<div class="mt-1 text-sm text-slate-500">{{ task.description }}</div>{% endif %}
|
||||
<div class="mt-2 flex flex-wrap gap-2 text-[11px] font-semibold">
|
||||
<span class="rounded-full bg-slate-100 px-2 py-1 text-slate-700">{{ task.status_label }}</span>
|
||||
<span class="rounded-full bg-slate-100 px-2 py-1 text-slate-700">{{ task.priority_label }}</span>
|
||||
{% if task.internal_target_date %}<span class="rounded-full {% if task.is_overdue_display %}bg-red-50 text-red-700{% else %}bg-slate-100 text-slate-700{% endif %} px-2 py-1">Target {{ task.internal_target_date.strftime('%d-%m-%Y') }}</span>{% endif %}
|
||||
{% if task.assigned_to %}<span class="rounded-full bg-slate-100 px-2 py-1 text-slate-700">Assigned: {{ task.assigned_to.full_name or task.assigned_to.email }}</span>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% if access.can_update_tasks %}
|
||||
<form method="post" action="/work/tasks/{{ task.id }}/status" class="flex flex-wrap gap-2">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
||||
<select name="status" class="rounded-xl border border-slate-300 px-2 py-1 text-xs">
|
||||
{% for code, label in task_statuses %}<option value="{{ code }}" {% if task.status == code %}selected{% endif %}>{{ label }}</option>{% endfor %}
|
||||
</select>
|
||||
<select name="priority" class="rounded-xl border border-slate-300 px-2 py-1 text-xs">
|
||||
{% for code, label in task_priorities %}<option value="{{ code }}" {% if task.priority == code %}selected{% endif %}>{{ label }}</option>{% endfor %}
|
||||
</select>
|
||||
<button class="rounded-xl bg-brand-600 px-3 py-1 text-xs font-semibold text-white hover:bg-brand-700">Update</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if access.can_comment %}
|
||||
<form method="post" action="/work/tasks/{{ task.id }}/comment" class="mt-4 rounded-2xl bg-slate-50 p-3">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
||||
<div class="grid gap-2 md:grid-cols-[auto_auto_1fr_auto]">
|
||||
<select name="comment_type" class="rounded-xl border border-slate-300 px-2 py-2 text-xs">
|
||||
{% for code, label in access.allowed_comment_types %}<option value="{{ code }}">{{ label }}</option>{% endfor %}
|
||||
</select>
|
||||
<select name="visibility" class="rounded-xl border border-slate-300 px-2 py-2 text-xs">
|
||||
{% for code, label in access.allowed_visibilities %}<option value="{{ code }}">{{ label }}</option>{% endfor %}
|
||||
</select>
|
||||
<input name="message" required placeholder="Add note / clarification / submission update" class="rounded-xl border border-slate-300 px-3 py-2 text-sm">
|
||||
<button class="rounded-xl border border-slate-300 bg-white px-4 py-2 text-xs font-semibold text-slate-700 hover:bg-slate-50">Add</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="p-6 text-sm text-slate-500">No tasks have been generated for this engagement yet.</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="rounded-3xl border border-slate-200 bg-white shadow-soft">
|
||||
<div class="border-b border-slate-200 px-5 py-4"><h3 class="font-semibold text-slate-900">Communication Timeline</h3></div>
|
||||
<div class="divide-y divide-slate-100">
|
||||
{% for note in timeline %}
|
||||
<div class="p-5">
|
||||
<div class="flex flex-wrap items-center gap-2 text-xs text-slate-500">
|
||||
<span class="font-semibold text-slate-700">{{ note.comment_type.replace('_',' ').title() }}</span>
|
||||
<span>•</span><span>{{ note.visibility.replace('_',' ').title() }}</span>
|
||||
{% if note.created_by %}<span>•</span><span>{{ note.created_by.full_name or note.created_by.email }}</span>{% endif %}
|
||||
{% if note.created_at_utc %}<span>•</span><span>{{ note.created_at_utc.strftime('%d-%m-%Y %H:%M') }}</span>{% endif %}
|
||||
{% if note.task %}<span>•</span><span>{{ note.task.task_name }}</span>{% endif %}
|
||||
</div>
|
||||
<div class="mt-2 whitespace-pre-wrap text-sm text-slate-700">{{ note.message }}</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="p-6 text-sm text-slate-500">No communication yet.</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<aside class="space-y-4">
|
||||
<div class="rounded-3xl border border-slate-200 bg-white shadow-soft">
|
||||
<div class="border-b border-slate-200 px-5 py-4"><h3 class="font-semibold text-slate-900">Engagement Documents</h3></div>
|
||||
<div class="divide-y divide-slate-100">
|
||||
{% for doc in engagement_documents %}
|
||||
<div class="p-4">
|
||||
<div class="font-semibold text-slate-900">{{ doc.title }}</div>
|
||||
<div class="mt-1 text-xs text-slate-500">{{ doc.document_type }} • v{{ doc.current_version_no }}</div>
|
||||
{% if doc.versions %}<div class="mt-2 text-xs text-slate-500">Latest: {{ doc.versions[0].original_filename }}</div>{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="p-5 text-sm text-slate-500">No engagement documents uploaded.</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="rounded-3xl border border-slate-200 bg-white shadow-soft">
|
||||
<div class="border-b border-slate-200 px-5 py-4"><h3 class="font-semibold text-slate-900">Permanent Documents</h3></div>
|
||||
<div class="divide-y divide-slate-100">
|
||||
{% for doc in permanent_documents %}
|
||||
<div class="p-4">
|
||||
<div class="font-semibold text-slate-900">{{ doc.title }}</div>
|
||||
<div class="mt-1 text-xs text-slate-500">{{ doc.category }} • v{{ doc.current_version_no }}</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="p-5 text-sm text-slate-500">No permanent documents available.</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user