From 59406b38ee60c3298748567c745d7f0a49e8600d Mon Sep 17 00:00:00 2001 From: Dries Peeters Date: Wed, 12 Nov 2025 11:20:37 +0100 Subject: [PATCH] Fix: Filter out done/cancelled tasks in Dashboard Start Timer When selecting a project in the Dashboard Start Timer modal, all tasks were displayed including those marked as 'done' or 'cancelled'. This made it difficult to find active tasks in projects with many completed tasks. Changes: - Updated /api/projects//tasks endpoint to exclude tasks with status 'done' or 'cancelled' - Only returns active tasks (todo, in_progress, review) - Added test to verify the filtering behavior This improves usability by showing only actionable tasks when starting a timer, especially beneficial for larger projects with many tasks. --- app/routes/api.py | 8 +++-- tests/test_api_comprehensive.py | 62 +++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/app/routes/api.py b/app/routes/api.py index 47a719d..fa705a0 100644 --- a/app/routes/api.py +++ b/app/routes/api.py @@ -1134,14 +1134,16 @@ def get_projects(): @api_bp.route('/api/projects//tasks') @login_required def get_project_tasks(project_id): - """Get tasks for a specific project""" + """Get tasks for a specific project (excluding done and cancelled tasks)""" # Check if project exists and is active project = Project.query.filter_by(id=project_id, status='active').first() if not project: return jsonify({'error': 'Project not found or inactive'}), 404 - # Get tasks for the project - tasks = Task.query.filter_by(project_id=project_id).order_by(Task.name).all() + # Get active tasks for the project (exclude done and cancelled) + tasks = Task.query.filter_by(project_id=project_id).filter( + Task.status.in_(['todo', 'in_progress', 'review']) + ).order_by(Task.name).all() return jsonify({ 'success': True, diff --git a/tests/test_api_comprehensive.py b/tests/test_api_comprehensive.py index 15c2137..fd2bdce 100644 --- a/tests/test_api_comprehensive.py +++ b/tests/test_api_comprehensive.py @@ -183,6 +183,68 @@ def test_get_task_details(authenticated_client, task): assert response.status_code in [200, 404] +@pytest.mark.api +@pytest.mark.integration +def test_get_project_tasks_excludes_done_and_cancelled(authenticated_client, project, user, app): + """Test that /api/projects//tasks excludes done and cancelled tasks.""" + from app.models import Task + from app import db + + # Create tasks with different statuses + active_task = Task( + name='Active Task', + project_id=project.id, + status='todo', + created_by=user.id + ) + in_progress_task = Task( + name='In Progress Task', + project_id=project.id, + status='in_progress', + created_by=user.id + ) + review_task = Task( + name='Review Task', + project_id=project.id, + status='review', + created_by=user.id + ) + done_task = Task( + name='Done Task', + project_id=project.id, + status='done', + created_by=user.id + ) + cancelled_task = Task( + name='Cancelled Task', + project_id=project.id, + status='cancelled', + created_by=user.id + ) + + db.session.add_all([active_task, in_progress_task, review_task, done_task, cancelled_task]) + db.session.commit() + + # Get tasks for the project + response = authenticated_client.get(f'/api/projects/{project.id}/tasks') + + assert response.status_code == 200 + data = json.loads(response.data) + assert 'tasks' in data + assert data['success'] is True + + # Verify only active tasks are returned + task_names = [t['name'] for t in data['tasks']] + assert 'Active Task' in task_names + assert 'In Progress Task' in task_names + assert 'Review Task' in task_names + assert 'Done Task' not in task_names + assert 'Cancelled Task' not in task_names + + # Verify we got exactly 3 tasks + assert len(data['tasks']) == 3 + + # ============================================================================ # Settings API Tests # ============================================================================