From 02d814b935d24be4253e5d194708cdc4abf7ea17 Mon Sep 17 00:00:00 2001 From: chamikaJ Date: Mon, 14 Jul 2025 12:04:31 +0530 Subject: [PATCH] refactor(task-list): enhance task row components with depth handling - Added depth and maxDepth props to TaskRow, TaskRowWithSubtasks, and TitleColumn components to manage nested subtasks more effectively. - Updated AddSubtaskRow to support depth for proper indentation and visual hierarchy. - Improved styling for subtasks based on their depth level, ensuring better visual distinction. - Adjusted task management slice to utilize actual subtask counts from the backend for accurate display. --- .../task-drawer-phase-selector.tsx | 14 +-- .../src/components/task-list-v2/TaskRow.tsx | 5 +- .../task-list-v2/TaskRowWithSubtasks.tsx | 97 +++++++++++++------ .../task-list-v2/components/TitleColumn.tsx | 19 ++-- .../task-list-v2/hooks/useTaskRowColumns.tsx | 5 + .../task-management/task-management.slice.ts | 2 +- 6 files changed, 96 insertions(+), 46 deletions(-) diff --git a/worklenz-frontend/src/components/task-drawer/shared/info-tab/details/task-drawer-phase-selector/task-drawer-phase-selector.tsx b/worklenz-frontend/src/components/task-drawer/shared/info-tab/details/task-drawer-phase-selector/task-drawer-phase-selector.tsx index b336f091..e7504761 100644 --- a/worklenz-frontend/src/components/task-drawer/shared/info-tab/details/task-drawer-phase-selector/task-drawer-phase-selector.tsx +++ b/worklenz-frontend/src/components/task-drawer/shared/info-tab/details/task-drawer-phase-selector/task-drawer-phase-selector.tsx @@ -1,6 +1,5 @@ import { useSocket } from '@/socket/socketContext'; import { ITaskPhase } from '@/types/tasks/taskPhase.types'; -import { IProjectTask } from '@/types/project/projectTasksViewModel.types'; import { Select } from 'antd'; import { Form } from 'antd'; @@ -27,12 +26,6 @@ const TaskDrawerPhaseSelector = ({ phases, task }: TaskDrawerPhaseSelectorProps) phase_id: value, parent_task: task.parent_task_id || null, }); - - // socket?.once(SocketEvents.TASK_PHASE_CHANGE.toString(), () => { - // if(list.getCurrentGroup().value === this.list.GROUP_BY_PHASE_VALUE && this.list.isSubtasksIncluded) { - // this.list.emitRefreshSubtasksIncluded(); - // } - // }); }; return ( @@ -41,8 +34,11 @@ const TaskDrawerPhaseSelector = ({ phases, task }: TaskDrawerPhaseSelectorProps) allowClear placeholder="Select Phase" options={phaseMenuItems} - style={{ width: 'fit-content' }} - dropdownStyle={{ width: 'fit-content' }} + styles={{ + root: { + width: 'fit-content', + }, + }} onChange={handlePhaseChange} /> diff --git a/worklenz-frontend/src/components/task-list-v2/TaskRow.tsx b/worklenz-frontend/src/components/task-list-v2/TaskRow.tsx index 24571b8b..e1dd657f 100644 --- a/worklenz-frontend/src/components/task-list-v2/TaskRow.tsx +++ b/worklenz-frontend/src/components/task-list-v2/TaskRow.tsx @@ -24,6 +24,7 @@ interface TaskRowProps { isSubtask?: boolean; isFirstInGroup?: boolean; updateTaskCustomColumnValue?: (taskId: string, columnKey: string, value: string) => void; + depth?: number; } const TaskRow: React.FC = memo(({ @@ -32,7 +33,8 @@ const TaskRow: React.FC = memo(({ visibleColumns, isSubtask = false, isFirstInGroup = false, - updateTaskCustomColumnValue + updateTaskCustomColumnValue, + depth = 0 }) => { // Get task data and selection state from Redux const task = useAppSelector(state => selectTaskById(state, taskId)); @@ -107,6 +109,7 @@ const TaskRow: React.FC = memo(({ handleTaskNameEdit, attributes, listeners, + depth, }); // Memoize style object to prevent unnecessary re-renders diff --git a/worklenz-frontend/src/components/task-list-v2/TaskRowWithSubtasks.tsx b/worklenz-frontend/src/components/task-list-v2/TaskRowWithSubtasks.tsx index 10226d03..9e450c60 100644 --- a/worklenz-frontend/src/components/task-list-v2/TaskRowWithSubtasks.tsx +++ b/worklenz-frontend/src/components/task-list-v2/TaskRowWithSubtasks.tsx @@ -22,6 +22,8 @@ interface TaskRowWithSubtasksProps { }>; isFirstInGroup?: boolean; updateTaskCustomColumnValue?: (taskId: string, columnKey: string, value: string) => void; + depth?: number; // Add depth prop to track nesting level + maxDepth?: number; // Add maxDepth prop to limit nesting } interface AddSubtaskRowProps { @@ -32,14 +34,15 @@ interface AddSubtaskRowProps { width: string; isSticky?: boolean; }>; - onSubtaskAdded: () => void; // Simplified - no rowId needed - rowId: string; // Unique identifier for this add subtask row - autoFocus?: boolean; // Whether this row should auto-focus on mount - isActive?: boolean; // Whether this row should show the input/button - onActivate?: () => void; // Simplified - no rowId needed + onSubtaskAdded: () => void; + rowId: string; + autoFocus?: boolean; + isActive?: boolean; + onActivate?: () => void; + depth?: number; // Add depth prop for proper indentation } -const AddSubtaskRow: React.FC = memo(({ +const AddSubtaskRow: React.FC = memo(({ parentTaskId, projectId, visibleColumns, @@ -47,25 +50,20 @@ const AddSubtaskRow: React.FC = memo(({ rowId, autoFocus = false, isActive = true, - onActivate + onActivate, + depth = 0 }) => { - const [isAdding, setIsAdding] = useState(autoFocus); + const { t } = useTranslation('task-list-table'); + const [isAdding, setIsAdding] = useState(false); const [subtaskName, setSubtaskName] = useState(''); const inputRef = useRef(null); - const { socket, connected } = useSocket(); - const { t } = useTranslation('task-list-table'); const dispatch = useAppDispatch(); - - // Get session data for reporter_id and team_id + const { socket, connected } = useSocket(); const currentSession = useAuthService().getCurrentSession(); - // Auto-focus when autoFocus prop is true useEffect(() => { if (autoFocus && inputRef.current) { - setIsAdding(true); - setTimeout(() => { - inputRef.current?.focus(); - }, 100); + inputRef.current.focus(); } }, [autoFocus]); @@ -142,10 +140,14 @@ const AddSubtaskRow: React.FC = memo(({
{/* Match subtask indentation pattern - tighter spacing */} -
+
+ {/* Add additional indentation for deeper levels - 16px per level */} + {Array.from({ length: depth }).map((_, i) => ( +
+ ))}
- {isActive ? ( + {isActive ? ( !isAdding ? (