Enhance task progress tracking and UI updates
- Updated SQL migration to insert default task statuses ('To Do', 'Doing', 'Done') upon project creation, improving task management.
- Enhanced socket commands to emit progress updates for subtasks, ensuring real-time synchronization of task progress.
- Refactored frontend components to handle progress calculations and updates more effectively, including improved logging for debugging.
- Removed deprecated members reports components to streamline the codebase and improve maintainability.
This commit is contained in:
@@ -13,7 +13,7 @@ import { ITaskListStatusChangeResponse } from '@/types/tasks/task-list-status.ty
|
||||
import { setTaskStatus } from '@/features/task-drawer/task-drawer.slice';
|
||||
import { useAppDispatch } from '@/hooks/useAppDispatch';
|
||||
import { updateBoardTaskStatus } from '@/features/board/board-slice';
|
||||
import { updateTaskStatus } from '@/features/tasks/tasks.slice';
|
||||
import { updateTaskProgress, updateTaskStatus } from '@/features/tasks/tasks.slice';
|
||||
import useTabSearchParam from '@/hooks/useTabSearchParam';
|
||||
|
||||
interface TaskDrawerProgressProps {
|
||||
@@ -101,11 +101,28 @@ const TaskDrawerProgress = ({ task, form }: TaskDrawerProgressProps) => {
|
||||
})
|
||||
);
|
||||
|
||||
socket?.once(SocketEvents.GET_TASK_PROGRESS.toString(), (data: any) => {
|
||||
dispatch(
|
||||
updateTaskProgress({
|
||||
taskId: task.id,
|
||||
progress: data.complete_ratio,
|
||||
totalTasksCount: data.total_tasks_count,
|
||||
completedCount: data.completed_count,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
if (task.id) {
|
||||
setTimeout(() => {
|
||||
socket?.emit(SocketEvents.GET_TASK_PROGRESS.toString(), task.id);
|
||||
}, 500);
|
||||
}
|
||||
|
||||
// If this is a subtask, request the parent's progress to be updated in UI
|
||||
if (parent_task_id) {
|
||||
setTimeout(() => {
|
||||
socket?.emit(SocketEvents.GET_TASK_PROGRESS.toString(), parent_task_id);
|
||||
}, 100);
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -28,6 +28,7 @@ import TaskDrawerPrioritySelector from './details/task-drawer-priority-selector/
|
||||
import TaskDrawerBillable from './details/task-drawer-billable/task-drawer-billable';
|
||||
import TaskDrawerProgress from './details/task-drawer-progress/task-drawer-progress';
|
||||
import { useAppSelector } from '@/hooks/useAppSelector';
|
||||
import logger from '@/utils/errorLogger';
|
||||
|
||||
interface TaskDetailsFormProps {
|
||||
taskFormViewModel?: ITaskFormViewModel | null;
|
||||
@@ -45,12 +46,12 @@ const ConditionalProgressInput = ({ task, form }: ConditionalProgressInputProps)
|
||||
const isSubTask = !!task?.parent_task_id;
|
||||
|
||||
// Add more aggressive logging and checks
|
||||
console.log(`Task ${task.id} status: hasSubTasks=${hasSubTasks}, isSubTask=${isSubTask}, modes: time=${project?.use_time_progress}, manual=${project?.use_manual_progress}, weighted=${project?.use_weighted_progress}`);
|
||||
logger.debug(`Task ${task.id} status: hasSubTasks=${hasSubTasks}, isSubTask=${isSubTask}, modes: time=${project?.use_time_progress}, manual=${project?.use_manual_progress}, weighted=${project?.use_weighted_progress}`);
|
||||
|
||||
// STRICT RULE: Never show progress input for parent tasks with subtasks
|
||||
// This is the most important check and must be done first
|
||||
if (hasSubTasks) {
|
||||
console.log(`Task ${task.id} has ${task.sub_tasks_count} subtasks. Hiding progress input.`);
|
||||
logger.debug(`Task ${task.id} has ${task.sub_tasks_count} subtasks. Hiding progress input.`);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import { ITaskLabel, ITaskLabelFilter } from '@/types/tasks/taskLabel.types';
|
||||
import { ITaskPhaseChangeResponse } from '@/types/tasks/task-phase-change-response';
|
||||
import { produce } from 'immer';
|
||||
import { tasksCustomColumnsService } from '@/api/tasks/tasks-custom-columns.service';
|
||||
import { SocketEvents } from '@/shared/socket-events';
|
||||
|
||||
export enum IGroupBy {
|
||||
STATUS = 'status',
|
||||
@@ -192,6 +193,20 @@ export const fetchSubTasks = createAsyncThunk(
|
||||
return [];
|
||||
}
|
||||
|
||||
// Request subtask progress data when expanding the task
|
||||
// This will trigger the socket to emit TASK_PROGRESS_UPDATED events for all subtasks
|
||||
try {
|
||||
// Get access to the socket from the state
|
||||
const socket = (getState() as any).socketReducer?.socket;
|
||||
if (socket?.connected) {
|
||||
// Request subtask count and progress information
|
||||
socket.emit(SocketEvents.GET_TASK_SUBTASKS_COUNT.toString(), taskId);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error requesting subtask progress:', error);
|
||||
// Non-critical error, continue with fetching subtasks
|
||||
}
|
||||
|
||||
const selectedMembers = taskReducer.taskAssignees
|
||||
.filter(member => member.selected)
|
||||
.map(member => member.id)
|
||||
@@ -577,6 +592,7 @@ const taskSlice = createSlice({
|
||||
for (const task of tasks) {
|
||||
if (task.id === taskId) {
|
||||
task.complete_ratio = progress;
|
||||
task.progress_value = progress;
|
||||
task.total_tasks_count = totalTasksCount;
|
||||
task.completed_count = completedCount;
|
||||
return true;
|
||||
|
||||
@@ -10,7 +10,7 @@ type TaskListProgressCellProps = {
|
||||
|
||||
const TaskListProgressCell = ({ task }: TaskListProgressCellProps) => {
|
||||
const { project } = useAppSelector(state => state.projectReducer);
|
||||
const isManualProgressEnabled = project?.use_manual_progress;
|
||||
const isManualProgressEnabled = (task.project_use_manual_progress || task.project_use_weighted_progress || task.project_use_time_progress);;
|
||||
const isSubtask = task.is_sub_task;
|
||||
const hasManualProgress = task.manual_progress;
|
||||
|
||||
|
||||
@@ -1548,7 +1548,6 @@ const TaskListTable: React.FC<TaskListTableProps> = ({ taskList, tableId, active
|
||||
};
|
||||
|
||||
const handleCustomColumnSettings = (columnKey: string) => {
|
||||
console.log('columnKey', columnKey);
|
||||
if (!columnKey) return;
|
||||
setEditColumnKey(columnKey);
|
||||
dispatch(setCustomColumnModalAttributes({modalType: 'edit', columnId: columnKey}));
|
||||
|
||||
@@ -90,6 +90,10 @@ export interface IProjectTask {
|
||||
isVisible?: boolean;
|
||||
estimated_string?: string;
|
||||
custom_column_values?: Record<string, any>;
|
||||
progress_value?: number;
|
||||
project_use_manual_progress?: boolean;
|
||||
project_use_time_progress?: boolean;
|
||||
project_use_weighted_progress?: boolean;
|
||||
}
|
||||
|
||||
export interface IProjectTasksViewModel {
|
||||
|
||||
Reference in New Issue
Block a user