Fix an issue with completed tasks in views
This commit is contained in:
parent
5f37423e51
commit
c983ba42ba
2 changed files with 106 additions and 8 deletions
|
|
@ -313,18 +313,18 @@ describe('Views Routes', () => {
|
|||
name: 'personal',
|
||||
});
|
||||
|
||||
// Create tasks with tags
|
||||
// Create tasks with tags (mix of active and completed)
|
||||
const task1 = await Task.create({
|
||||
user_id: user.id,
|
||||
name: 'Work task 1',
|
||||
status: 0,
|
||||
status: 0, // active
|
||||
});
|
||||
await task1.addTag(workTag);
|
||||
|
||||
const task2 = await Task.create({
|
||||
user_id: user.id,
|
||||
name: 'Urgent work task',
|
||||
status: 0,
|
||||
status: 0, // active
|
||||
});
|
||||
await task2.addTag(workTag);
|
||||
await task2.addTag(urgentTag);
|
||||
|
|
@ -332,9 +332,17 @@ describe('Views Routes', () => {
|
|||
const task3 = await Task.create({
|
||||
user_id: user.id,
|
||||
name: 'Personal task',
|
||||
status: 0,
|
||||
status: 0, // active
|
||||
});
|
||||
await task3.addTag(personalTag);
|
||||
|
||||
// Add completed task with work tag
|
||||
const task4 = await Task.create({
|
||||
user_id: user.id,
|
||||
name: 'Completed work task',
|
||||
status: 2, // completed (done)
|
||||
});
|
||||
await task4.addTag(workTag);
|
||||
});
|
||||
|
||||
it('should create view with tags and retrieve matching results', async () => {
|
||||
|
|
@ -365,8 +373,9 @@ describe('Views Routes', () => {
|
|||
const tasks = searchResponse.body.results.filter(
|
||||
(r) => r.type === 'Task'
|
||||
);
|
||||
expect(tasks.length).toBe(2);
|
||||
// Both tasks should have 'work' in their name (case-insensitive)
|
||||
// Should now return 3 tasks (2 active + 1 completed)
|
||||
expect(tasks.length).toBe(3);
|
||||
// All tasks should have 'work' in their name (case-insensitive)
|
||||
expect(
|
||||
tasks.every((t) => t.name.toLowerCase().includes('work'))
|
||||
).toBe(true);
|
||||
|
|
@ -422,6 +431,83 @@ describe('Views Routes', () => {
|
|||
expect(getResponse.status).toBe(200);
|
||||
expect(getResponse.body.tags).toEqual(['personal']);
|
||||
});
|
||||
|
||||
it('should return both active and completed tasks in search results', async () => {
|
||||
// Create a view with work tag
|
||||
const createResponse = await agent.post('/api/views').send({
|
||||
name: 'All Work Tasks View',
|
||||
filters: ['Task'],
|
||||
tags: ['work'],
|
||||
});
|
||||
|
||||
expect(createResponse.status).toBe(201);
|
||||
|
||||
// Search for work tasks
|
||||
const searchResponse = await agent.get('/api/search').query({
|
||||
tags: 'work',
|
||||
filters: 'Task',
|
||||
});
|
||||
|
||||
expect(searchResponse.status).toBe(200);
|
||||
const tasks = searchResponse.body.results.filter(
|
||||
(r) => r.type === 'Task'
|
||||
);
|
||||
|
||||
// Should return 3 tasks: 2 active + 1 completed
|
||||
expect(tasks.length).toBe(3);
|
||||
|
||||
// Verify we have both active and completed tasks
|
||||
const activeTasks = tasks.filter(
|
||||
(t) => t.status === 0 || t.status === 'active'
|
||||
);
|
||||
const completedTasks = tasks.filter(
|
||||
(t) => t.status === 2 || t.status === 'done'
|
||||
);
|
||||
|
||||
expect(activeTasks.length).toBe(2);
|
||||
expect(completedTasks.length).toBe(1);
|
||||
|
||||
// Verify the completed task is included
|
||||
const completedTask = tasks.find(
|
||||
(t) => t.name === 'Completed work task'
|
||||
);
|
||||
expect(completedTask).toBeDefined();
|
||||
expect(completedTask.status).toBe(2); // done status
|
||||
});
|
||||
|
||||
it('should include completed tasks with correct status values', async () => {
|
||||
// Create tasks with different completion statuses
|
||||
const archivedTask = await Task.create({
|
||||
user_id: user.id,
|
||||
name: 'Archived work task',
|
||||
status: 3, // archived
|
||||
});
|
||||
await archivedTask.addTag(workTag);
|
||||
|
||||
// Search for all work tasks
|
||||
const searchResponse = await agent.get('/api/search').query({
|
||||
tags: 'work',
|
||||
filters: 'Task',
|
||||
});
|
||||
|
||||
expect(searchResponse.status).toBe(200);
|
||||
const tasks = searchResponse.body.results.filter(
|
||||
(r) => r.type === 'Task'
|
||||
);
|
||||
|
||||
// Should now have 4 tasks (2 active, 1 done, 1 archived)
|
||||
expect(tasks.length).toBe(4);
|
||||
|
||||
// Verify different status types are present
|
||||
const statusTypes = tasks.map((t) => t.status);
|
||||
expect(statusTypes).toContain(0); // active
|
||||
expect(statusTypes).toContain(2); // done
|
||||
expect(statusTypes).toContain(3); // archived
|
||||
|
||||
// Frontend will filter these out, but backend should provide them all
|
||||
const nonActiveTasks = tasks.filter((t) => t.status >= 2);
|
||||
expect(nonActiveTasks.length).toBe(2); // done + archived
|
||||
});
|
||||
});
|
||||
|
||||
describe('User Isolation', () => {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import React, { useState, useEffect, useRef, useMemo } from 'react';
|
||||
import { useParams, useNavigate, Link } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
|
|
@ -95,6 +95,18 @@ const ViewDetail: React.FC = () => {
|
|||
}
|
||||
}, [isEditingName, editedName]);
|
||||
|
||||
// Filter out completed tasks for display count
|
||||
const activeTasks = useMemo(() => {
|
||||
return tasks.filter((task) => {
|
||||
const isCompleted =
|
||||
task.status === 'done' ||
|
||||
task.status === 'archived' ||
|
||||
task.status === 2 ||
|
||||
task.status === 3;
|
||||
return !isCompleted;
|
||||
});
|
||||
}, [tasks]);
|
||||
|
||||
const fetchViewAndResults = async () => {
|
||||
if (!uid) return;
|
||||
|
||||
|
|
@ -505,7 +517,7 @@ const ViewDetail: React.FC = () => {
|
|||
{tasks.length > 0 && (
|
||||
<div className="mb-8">
|
||||
<h3 className="text-lg font-light text-gray-900 dark:text-white mb-4">
|
||||
{t('tasks.title')} ({tasks.length})
|
||||
{t('tasks.title')} ({activeTasks.length})
|
||||
</h3>
|
||||
<TaskList
|
||||
tasks={tasks}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue