Files
ACORE/templates/pages/tasks.html
T
lokses 87cb9de005 i18n: перевод модуля задач (tasks/task-detail/task-edit) ru/uk/en
- Task.STATUS_CHOICES/PRIORITY_CHOICES переведены на русские msgid
  (консистентно с ru-базой); миграция choices
- task_detail_view: метки ролей через gettext
- Шаблоны tasks/task-detail/task-edit размечены {% trans %}; статусы,
  приоритеты, чек-лист, комментарии, участники, кнопки действий — uk/en

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 14:55:48 +03:00

151 lines
13 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% load i18n %}
<div class="page-content">
<!-- Заголовок -->
<div style="display:flex; align-items:center; justify-content:space-between; margin-bottom:1.25rem; gap:0.75rem;">
<div>
<h1 style="font-size:1.25rem; font-weight:500; color:var(--color-foreground);">{% trans "Мои задачи" %}</h1>
<p style="font-size:0.875rem; color:var(--color-muted-foreground); margin-top:0.25rem;">{% trans "Задачи, созданные вами или назначенные вам" %}</p>
</div>
</div>
{{ department_tree|json_script:"department-tree-data" }}
{% if form_error %}
<div style="background:color-mix(in srgb, var(--color-destructive) 8%, transparent); border:1px solid color-mix(in srgb, var(--color-destructive) 30%, transparent); border-radius:0.75rem; padding:0.875rem 1.25rem; margin-bottom:1rem; font-size:0.875rem; color:var(--color-destructive);">
{{ form_error }}
</div>
{% endif %}
<!-- Створення задачі -->
<details style="margin-bottom:1.25rem;" {% if form_error or form_open %}open{% endif %}>
<summary class="btn btn-primary" style="display:inline-flex; align-items:center; gap:0.375rem; cursor:pointer; list-style:none; width:fit-content;">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="12" x2="12" y1="5" y2="19"/><line x1="5" x2="19" y1="12" y2="12"/>
</svg>
{% trans "Новая задача" %}
</summary>
<form hx-post="/tasks/" hx-target="#main-content" hx-indicator="#loader"
style="margin-top:0.75rem; background:var(--color-card); border:1px solid var(--color-border); border-radius:0.75rem; padding:1.25rem; display:flex; flex-direction:column; gap:0.875rem;">
{% csrf_token %}
<input type="text" name="title" required maxlength="250" placeholder="{% trans 'Название задачи' %}" class="input" style="width:100%; font-weight:500;">
<textarea name="description" placeholder="{% trans 'Описание задачи (необязательно)...' %}"
style="width:100%; min-height:5rem; resize:vertical; background:var(--color-card); border:1px solid var(--color-input); border-radius:var(--radius); padding:0.4375rem 0.75rem; font-size:0.875rem; color:var(--color-foreground); font-family:var(--font-sans); outline:none; box-sizing:border-box;"></textarea>
{% trans 'Ответственный' as l_resp %}{% trans '+ Добавить ответственного' as p_resp %}{% trans 'Соисполнители' as l_co %}{% trans '+ Добавить соисполнителя' as p_co %}{% trans 'Наблюдатели' as l_obs %}{% trans '+ Добавить наблюдателя' as p_obs %}
<div style="display:grid; grid-template-columns:1fr 1fr; gap:1rem;">
{% include 'partials/people-picker-field.html' with label=l_resp field_name='responsible' options=employee_options selected_ids=preselect_responsible_ids placeholder=p_resp %}
{% include 'partials/people-picker-field.html' with label=l_co field_name='co_executors' options=employee_options selected_ids=empty_ids placeholder=p_co %}
{% include 'partials/people-picker-field.html' with label=l_obs field_name='observers' options=employee_options selected_ids=empty_ids placeholder=p_obs %}
</div>
<div style="display:flex; align-items:center; gap:1rem; flex-wrap:wrap;">
<select name="priority" class="input" style="width:auto; font-size:0.8125rem;">
{% for value, label in priorities %}
<option value="{{ value }}" {% if value == 'medium' %}selected{% endif %}>{{ label }}</option>
{% endfor %}
</select>
<input type="date" name="due_date" class="input" style="width:auto; font-size:0.8125rem;">
<button type="submit" class="btn btn-primary" style="margin-left:auto;">{% trans "Создать задачу" %}</button>
</div>
</form>
</details>
<script>initPeoplePickers(document);</script>
<!-- Таби -->
<div style="display:flex; gap:0.25rem; margin-bottom:1rem; background:var(--color-muted); border-radius:var(--radius); padding:0.25rem; width:fit-content;">
{% with base="display:inline-flex; align-items:center; gap:0.375rem; padding:0.375rem 0.75rem; border-radius:calc(var(--radius) - 2px); font-size:0.8125rem; font-weight:500; text-decoration:none; cursor:pointer;" %}
<a href="/tasks/" hx-get="/tasks/" hx-target="#main-content" hx-push-url="/tasks/" hx-indicator="#loader"
style="{{ base }} {% if not active_status %}background:var(--color-primary); color:var(--color-primary-foreground);{% else %}background:transparent; color:var(--color-muted-foreground);{% endif %}">
{% trans "Все" %} <span style="background:{% if not active_status %}rgba(255,255,255,0.25){% else %}var(--color-border){% endif %}; border-radius:999px; padding:0 0.375rem; font-size:0.6875rem; line-height:1.6;">{{ counts.all }}</span>
</a>
<a href="/tasks/?status=pending" hx-get="/tasks/?status=pending" hx-target="#main-content" hx-push-url="/tasks/?status=pending" hx-indicator="#loader"
style="{{ base }} {% if active_status == 'pending' %}background:var(--color-primary); color:var(--color-primary-foreground);{% else %}background:transparent; color:var(--color-muted-foreground);{% endif %}">
{% trans "Ожидает" %} <span style="background:{% if active_status == 'pending' %}rgba(255,255,255,0.25){% else %}var(--color-border){% endif %}; border-radius:999px; padding:0 0.375rem; font-size:0.6875rem; line-height:1.6;">{{ counts.pending }}</span>
</a>
<a href="/tasks/?status=in_progress" hx-get="/tasks/?status=in_progress" hx-target="#main-content" hx-push-url="/tasks/?status=in_progress" hx-indicator="#loader"
style="{{ base }} {% if active_status == 'in_progress' %}background:var(--color-primary); color:var(--color-primary-foreground);{% else %}background:transparent; color:var(--color-muted-foreground);{% endif %}">
{% trans "В работе" %} <span style="background:{% if active_status == 'in_progress' %}rgba(255,255,255,0.25){% else %}var(--color-border){% endif %}; border-radius:999px; padding:0 0.375rem; font-size:0.6875rem; line-height:1.6;">{{ counts.in_progress }}</span>
</a>
<a href="/tasks/?status=done" hx-get="/tasks/?status=done" hx-target="#main-content" hx-push-url="/tasks/?status=done" hx-indicator="#loader"
style="{{ base }} {% if active_status == 'done' %}background:var(--color-primary); color:var(--color-primary-foreground);{% else %}background:transparent; color:var(--color-muted-foreground);{% endif %}">
{% trans "Выполнено" %} <span style="background:{% if active_status == 'done' %}rgba(255,255,255,0.25){% else %}var(--color-border){% endif %}; border-radius:999px; padding:0 0.375rem; font-size:0.6875rem; line-height:1.6;">{{ counts.done }}</span>
</a>
{% endwith %}
</div>
<!-- Список задач -->
<div style="background:var(--color-card); border-radius:0.75rem; border:1px solid var(--color-border); box-shadow:0 1px 2px rgb(0 0 0/0.05); overflow:hidden;">
{% for task in tasks %}
<div class="task-row li-hover" style="{% if not forloop.last %}border-bottom:1px solid var(--color-border);{% endif %} {% if task.status == 'done' %}background:var(--color-muted);{% endif %}">
<form hx-post="/tasks/{{ task.pk }}/toggle/" hx-target="#main-content" hx-indicator="#loader" style="margin:0; display:flex;">
{% csrf_token %}
<input type="checkbox" {% if task.status == 'done' %}checked{% endif %}
onchange="htmx.trigger(this.form, 'submit')"
style="width:1rem; height:1rem; flex-shrink:0; accent-color:var(--color-primary); cursor:pointer; margin-top:2px;">
</form>
<div style="flex:1; min-width:0; cursor:pointer;"
hx-get="/tasks/{{ task.pk }}/" hx-target="#main-content" hx-push-url="/tasks/{{ task.pk }}/" hx-indicator="#loader">
<div style="font-size:0.875rem; font-weight:500; color:{% if task.status == 'done' %}var(--color-muted-foreground); text-decoration:line-through;{% else %}var(--color-card-foreground);{% endif %}">{{ task.title }}</div>
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.0625rem;">
{% if task.description %}{{ task.description|truncatechars:90 }}{% endif %}
{% if task.display_people %}
<span style="opacity:0.8;">
→
{% for a in task.display_people %}{{ a.get_full_name }}{% if not forloop.last %}, {% endif %}{% endfor %}
</span>
{% endif %}
</div>
</div>
<div class="task-meta">
{% if task.status == 'done' %}
<span style="display:inline-flex; align-items:center; gap:0.25rem; font-size:0.75rem; color:hsl(152 55% 35%);">
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="20 6 9 17 4 12"/></svg>{% trans "Выполнено" %}
</span>
{% elif task.status == 'in_progress' %}
<span style="display:inline-flex; align-items:center; gap:0.25rem; font-size:0.75rem; color:hsl(152 55% 35%);">
<span style="width:6px; height:6px; border-radius:50%; background:hsl(152 55% 45%); flex-shrink:0;"></span>{% trans "В работе" %}
</span>
{% elif task.status == 'cancelled' %}
<span style="display:inline-flex; align-items:center; gap:0.25rem; font-size:0.75rem; color:var(--color-muted-foreground);">
<span style="width:6px; height:6px; border-radius:50%; background:var(--color-muted-foreground); flex-shrink:0;"></span>{% trans "Отменено" %}
</span>
{% else %}
<span style="display:inline-flex; align-items:center; gap:0.25rem; font-size:0.75rem; color:hsl(38 70% 35%);">
<span style="width:6px; height:6px; border-radius:50%; background:hsl(38 92% 50%); flex-shrink:0;"></span>{% trans "Ожидает" %}
</span>
{% endif %}
{% if task.due_date %}
<span class="task-date" style="display:inline-flex; align-items:center; gap:0.25rem; font-size:0.75rem; color:{% if task.is_overdue %}var(--color-destructive); font-weight:600;{% else %}var(--color-muted-foreground);{% endif %}">
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>{{ task.due_date|date:"d.m.Y" }}
</span>
{% endif %}
<span class="badge {{ task.priority_badge }}">{{ task.get_priority_display }}</span>
{% if task.can_edit %}
<a hx-get="/tasks/{{ task.pk }}/edit/" hx-target="#main-content" hx-push-url="/tasks/{{ task.pk }}/edit/" hx-indicator="#loader"
class="btn btn-ghost btn-icon" title="{% trans 'Редактировать' %}" style="padding:0.25rem; color:var(--color-muted-foreground); margin-left:auto; cursor:pointer;">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>
</a>
{% endif %}
{% if task.can_delete %}
<form hx-post="/tasks/{{ task.pk }}/delete/" hx-target="#main-content" hx-push-url="/tasks/" hx-indicator="#loader"
hx-confirm="{% trans 'Удалить задачу' %} «{{ task.title }}»?" style="margin:0; display:flex;">
{% csrf_token %}
<button type="submit" class="btn btn-ghost btn-icon" title="{% trans 'Удалить' %}" style="padding:0.25rem; color:var(--color-muted-foreground);">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2"/></svg>
</button>
</form>
{% endif %}
</div>
</div>
{% empty %}
<div style="padding:2.5rem; text-align:center; color:var(--color-muted-foreground); font-size:0.875rem;">
{% if active_status %}{% trans "Задач с таким статусом нет" %}{% else %}{% trans "Задач пока нет — создайте первую" %}{% endif %}
</div>
{% endfor %}
</div>
</div>