mirror of
https://github.com/DRYTRIX/TimeTracker.git
synced 2026-05-17 18:38:46 -05:00
Merge pull request #607 from MacJediWizard/fix/upstream-task-service-status
fix(tasks): service-layer status validator + preview JS now kanban-aware (companion to #606)
This commit is contained in:
@@ -43,7 +43,10 @@ class TaskService:
|
||||
self.task_repo = TaskRepository()
|
||||
self.project_repo = ProjectRepository()
|
||||
|
||||
VALID_STATUSES = ("todo", "in_progress", "review", "done", "cancelled")
|
||||
# Last-ditch fallback — only used if KanbanColumn lookup fails.
|
||||
# The real validation happens via KanbanColumn.get_valid_status_keys(project_id=...)
|
||||
# so users with custom kanban columns (e.g. on_hold) aren't silently coerced to todo.
|
||||
VALID_STATUSES = ("todo", "in_progress", "review", "done", "on_hold", "cancelled")
|
||||
|
||||
def create_task(
|
||||
self,
|
||||
@@ -82,7 +85,16 @@ class TaskService:
|
||||
if not project:
|
||||
return {"success": False, "message": "Invalid project", "error": "invalid_project"}
|
||||
|
||||
task_status = status if status and status in self.VALID_STATUSES else TaskStatus.TODO.value
|
||||
# Validate status against the configured kanban columns for this project.
|
||||
# Falls back to the hardcoded VALID_STATUSES tuple if KanbanColumn is unavailable
|
||||
# (e.g. table not yet seeded during a fresh migration).
|
||||
try:
|
||||
from app.models import KanbanColumn
|
||||
|
||||
allowed = set(KanbanColumn.get_valid_status_keys(project_id=project_id) or self.VALID_STATUSES)
|
||||
except Exception:
|
||||
allowed = set(self.VALID_STATUSES)
|
||||
task_status = status if status and status in allowed else TaskStatus.TODO.value
|
||||
|
||||
# Create task
|
||||
task = self.task_repo.create(
|
||||
|
||||
@@ -81,7 +81,11 @@
|
||||
</span>
|
||||
<span id="statusPreview" class="status-badge status-{{ request.form.get('status') or request.args.get('status') or 'todo' }}">
|
||||
{% set status_preview = request.form.get('status') or request.args.get('status') or 'todo' %}
|
||||
{% if status_preview == 'in_progress' %}{{ _('In Progress') }}{% elif status_preview == 'review' %}{{ _('Review') }}{% elif status_preview == 'done' %}{{ _('Done') }}{% elif status_preview == 'cancelled' %}{{ _('Cancelled') }}{% else %}{{ _('To Do') }}{% endif %}
|
||||
{%- set _matched = namespace(label=None) -%}
|
||||
{%- for col in kanban_columns -%}
|
||||
{%- if col.key == status_preview -%}{%- set _matched.label = col.label -%}{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{{ _(_matched.label) if _matched.label else _('To Do') }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -470,11 +474,9 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
high: { text: '{{ _('High') }}', class: 'priority-high' },
|
||||
urgent: { text: '{{ _('Urgent') }}', class: 'priority-urgent' },
|
||||
} : {
|
||||
todo: { text: '{{ _('To Do') }}', class: 'status-todo' },
|
||||
in_progress: { text: '{{ _('In Progress') }}', class: 'status-in_progress' },
|
||||
review: { text: '{{ _('Review') }}', class: 'status-review' },
|
||||
done: { text: '{{ _('Done') }}', class: 'status-done' },
|
||||
cancelled: { text: '{{ _('Cancelled') }}', class: 'status-cancelled' },
|
||||
{%- for col in kanban_columns %}
|
||||
{{ col.key }}: { text: '{{ _(col.label) }}', class: 'status-{{ col.key }}' },
|
||||
{%- endfor %}
|
||||
};
|
||||
const def = map[value] || Object.values(map)[0];
|
||||
// Reset classes preserving base class
|
||||
|
||||
@@ -650,11 +650,9 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
high: { text: '{{ _('High') }}', class: 'priority-high' },
|
||||
urgent: { text: '{{ _('Urgent') }}', class: 'priority-urgent' },
|
||||
} : {
|
||||
todo: { text: '{{ _('To Do') }}', class: 'status-todo' },
|
||||
in_progress: { text: '{{ _('In Progress') }}', class: 'status-in_progress' },
|
||||
review: { text: '{{ _('Review') }}', class: 'status-review' },
|
||||
done: { text: '{{ _('Done') }}', class: 'status-done' },
|
||||
cancelled: { text: '{{ _('Cancelled') }}', class: 'status-cancelled' },
|
||||
{%- for col in kanban_columns %}
|
||||
{{ col.key }}: { text: '{{ _(col.label) }}', class: 'status-{{ col.key }}' },
|
||||
{%- endfor %}
|
||||
};
|
||||
const def = map[value] || Object.values(map)[0];
|
||||
element.className = element.className.split(' ').filter(c => !c.startsWith(type === 'priority' ? 'priority-' : 'status-')).join(' ').trim();
|
||||
|
||||
Reference in New Issue
Block a user