refactor(task-list): update subtask and indicator visibility logic

- Modified subtask visibility conditions across TaskCard, EnhancedKanbanTaskCard, KanbanTaskCard, and TaskRow components to only display when the count is greater than 1.
- Enhanced task indicators for comments and attachments to follow the same visibility logic.
- Added new dependencies for task management types to support subscriber and attachment features.
This commit is contained in:
chamiakJ
2025-07-07 06:33:22 +05:30
parent b6efa3f37e
commit 03fc2fb7ee
7 changed files with 88 additions and 32 deletions

View File

@@ -284,7 +284,7 @@ const TaskCard: React.FC<taskProps> = ({ task }) => {
format={value => formatDate(value)} format={value => formatDate(value)}
/> />
</div> </div>
{task.sub_tasks_count && task.sub_tasks_count > 0 && ( {task.sub_tasks_count && task.sub_tasks_count > 1 && (
<Button <Button
onClick={() => setIsSubTaskShow(!isSubTaskShow)} onClick={() => setIsSubTaskShow(!isSubTaskShow)}
size="small" size="small"
@@ -306,7 +306,7 @@ const TaskCard: React.FC<taskProps> = ({ task }) => {
{isSubTaskShow && {isSubTaskShow &&
task.sub_tasks_count && task.sub_tasks_count &&
task.sub_tasks_count > 0 && task.sub_tasks_count > 1 &&
task.sub_tasks?.map(subtask => <SubTaskCard subtask={subtask} />)} task.sub_tasks?.map(subtask => <SubTaskCard subtask={subtask} />)}
</div> </div>
</div> </div>

View File

@@ -191,29 +191,31 @@ const EnhancedKanbanTaskCard: React.FC<EnhancedKanbanTaskCardProps> = React.memo
<Flex gap={4} align="center"> <Flex gap={4} align="center">
<CustomDueDatePicker task={task} onDateChange={setDueDate} /> <CustomDueDatePicker task={task} onDateChange={setDueDate} />
{/* Subtask Section */} {/* Subtask Section - only show if count > 1 */}
<Button {task.sub_tasks_count != null && Number(task.sub_tasks_count) > 1 && (
onClick={handleSubtaskButtonClick} <Button
size="small" onClick={handleSubtaskButtonClick}
style={{ size="small"
padding: 0,
}}
type="text"
>
<Tag
bordered={false}
style={{ style={{
display: 'flex', padding: 0,
alignItems: 'center',
margin: 0,
backgroundColor: themeWiseColor('white', '#1e1e1e', themeMode),
}} }}
type="text"
> >
<ForkOutlined rotate={90} /> <Tag
<span>{task.sub_tasks_count}</span> bordered={false}
{task.show_sub_tasks ? <CaretDownFilled /> : <CaretRightFilled />} style={{
</Tag> display: 'flex',
</Button> alignItems: 'center',
margin: 0,
backgroundColor: themeWiseColor('white', '#1e1e1e', themeMode),
}}
>
<ForkOutlined rotate={90} />
<span>{task.sub_tasks_count || 0}</span>
{task.show_sub_tasks ? <CaretDownFilled /> : <CaretRightFilled />}
</Tag>
</Button>
)}
</Flex> </Flex>
</Flex> </Flex>
<Flex vertical gap={8}> <Flex vertical gap={8}>

View File

@@ -195,12 +195,12 @@ const KanbanTaskCard: React.FC<TaskRowProps> = ({
<ClockCircleOutlined /> {task.time_spent_string} <ClockCircleOutlined /> {task.time_spent_string}
</span> </span>
)} )}
{task.comments_count && task.comments_count > 0 && ( {task.comments_count && task.comments_count > 1 && (
<span className="kanban-task-indicator"> <span className="kanban-task-indicator">
<MessageOutlined /> {task.comments_count} <MessageOutlined /> {task.comments_count}
</span> </span>
)} )}
{task.attachments_count && task.attachments_count > 0 && ( {task.attachments_count && task.attachments_count > 1 && (
<span className="kanban-task-indicator"> <span className="kanban-task-indicator">
<PaperClipOutlined /> {task.attachments_count} <PaperClipOutlined /> {task.attachments_count}
</span> </span>

View File

@@ -1,8 +1,8 @@
import React, { memo, useMemo, useCallback, useState } from 'react'; import React, { memo, useMemo, useCallback, useState } from 'react';
import { useSortable } from '@dnd-kit/sortable'; import { useSortable } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities'; import { CSS } from '@dnd-kit/utilities';
import { CheckCircleOutlined, HolderOutlined, CloseOutlined, DownOutlined, RightOutlined, DoubleRightOutlined, ArrowsAltOutlined } from '@ant-design/icons'; import { CheckCircleOutlined, HolderOutlined, CloseOutlined, DownOutlined, RightOutlined, DoubleRightOutlined, ArrowsAltOutlined, CommentOutlined, EyeOutlined, PaperClipOutlined, MinusCircleOutlined, RetweetOutlined } from '@ant-design/icons';
import { Checkbox, DatePicker } from 'antd'; import { Checkbox, DatePicker, Tooltip } from 'antd';
import { dayjs, taskManagementAntdConfig } from '@/shared/antd-imports'; import { dayjs, taskManagementAntdConfig } from '@/shared/antd-imports';
import { Task } from '@/types/task-management.types'; import { Task } from '@/types/task-management.types';
import { InlineMember } from '@/types/teamMembers/inlineMember.types'; import { InlineMember } from '@/types/teamMembers/inlineMember.types';
@@ -49,7 +49,6 @@ interface TaskLabelsCellProps {
} }
const TaskLabelsCell: React.FC<TaskLabelsCellProps> = memo(({ labels, isDarkMode }) => { const TaskLabelsCell: React.FC<TaskLabelsCellProps> = memo(({ labels, isDarkMode }) => {
console.log('labels', labels);
if (!labels) { if (!labels) {
return null; return null;
} }
@@ -302,7 +301,7 @@ const TaskRow: React.FC<TaskRowProps> = memo(({ taskId, projectId, visibleColumn
<button <button
onClick={handleToggleExpansion} onClick={handleToggleExpansion}
className={`flex h-4 w-4 items-center justify-center rounded-sm text-xs mr-1 hover:border hover:border-blue-500 hover:bg-blue-50 dark:hover:bg-blue-900/20 hover:scale-110 transition-all duration-300 ease-out ${ className={`flex h-4 w-4 items-center justify-center rounded-sm text-xs mr-1 hover:border hover:border-blue-500 hover:bg-blue-50 dark:hover:bg-blue-900/20 hover:scale-110 transition-all duration-300 ease-out ${
task.sub_tasks_count && Number(task.sub_tasks_count) > 0 task.sub_tasks_count != null && Number(task.sub_tasks_count) > 0
? 'opacity-100' ? 'opacity-100'
: 'opacity-0 group-hover:opacity-100' : 'opacity-0 group-hover:opacity-100'
}`} }`}
@@ -327,8 +326,8 @@ const TaskRow: React.FC<TaskRowProps> = memo(({ taskId, projectId, visibleColumn
{taskDisplayName} {taskDisplayName}
</span> </span>
{/* Subtask count indicator */} {/* Subtask count indicator - only show if count > 1 */}
{!isSubtask && task.sub_tasks_count && Number(task.sub_tasks_count) > 0 && ( {!isSubtask && task.sub_tasks_count != null && task.sub_tasks_count !== 0 && (
<div className="flex items-center gap-1 px-2 py-1 bg-blue-50 dark:bg-blue-900/20 rounded-md"> <div className="flex items-center gap-1 px-2 py-1 bg-blue-50 dark:bg-blue-900/20 rounded-md">
<span className="text-xs text-blue-600 dark:text-blue-400 font-medium"> <span className="text-xs text-blue-600 dark:text-blue-400 font-medium">
{task.sub_tasks_count} {task.sub_tasks_count}
@@ -336,6 +335,55 @@ const TaskRow: React.FC<TaskRowProps> = memo(({ taskId, projectId, visibleColumn
<DoubleRightOutlined className="text-xs text-blue-600 dark:text-blue-400" /> <DoubleRightOutlined className="text-xs text-blue-600 dark:text-blue-400" />
</div> </div>
)} )}
{/* Task indicators */}
<div className="flex items-center gap-1 ml-2">
{/* Comments count indicator - only show if count > 1 */}
{task.comments_count != null && task.comments_count !== 0 && (
<div className="flex items-center gap-1">
<CommentOutlined
className="text-gray-500 dark:text-gray-400"
style={{ fontSize: 14 }}
/>
</div>
)}
{/* Subscribers indicator */}
{task.has_subscribers && (
<EyeOutlined
className="text-gray-500 dark:text-gray-400"
style={{ fontSize: 14 }}
/>
)}
{/* Attachments count indicator - only show if count > 1 */}
{task.attachments_count != null && task.attachments_count !== 0 && (
<div className="flex items-center gap-1">
<PaperClipOutlined
className="text-gray-500 dark:text-gray-400"
style={{ fontSize: 14 }}
/>
</div>
)}
{/* Dependencies indicator */}
{task.has_dependencies && (
<MinusCircleOutlined
className="text-gray-500 dark:text-gray-400"
style={{ fontSize: 14 }}
/>
)}
{/* Recurring task indicator */}
{task.schedule_id && (
<Tooltip title="Recurring Task">
<RetweetOutlined
className="text-gray-500 dark:text-gray-400"
style={{ fontSize: 14 }}
/>
</Tooltip>
)}
</div>
</div> </div>
</div> </div>
@@ -659,6 +707,11 @@ const TaskRow: React.FC<TaskRowProps> = memo(({ taskId, projectId, visibleColumn
task, task,
task.labels, // Explicit dependency for labels updates task.labels, // Explicit dependency for labels updates
task.phase, // Explicit dependency for phase updates task.phase, // Explicit dependency for phase updates
task.comments_count, // Explicit dependency for comments count updates
task.has_subscribers, // Explicit dependency for subscribers updates
task.attachments_count, // Explicit dependency for attachments count updates
task.has_dependencies, // Explicit dependency for dependencies updates
task.schedule_id, // Explicit dependency for recurring task updates
taskDisplayName, taskDisplayName,
convertedTask, convertedTask,

View File

@@ -109,7 +109,7 @@ const AddSubtaskRow: React.FC<AddSubtaskRowProps> = memo(({
className="flex items-center gap-2 text-sm text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 transition-colors h-full" className="flex items-center gap-2 text-sm text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 transition-colors h-full"
> >
<PlusOutlined className="text-xs" /> <PlusOutlined className="text-xs" />
{t('addSubtaskText')} {t('addSubTaskText')}
</button> </button>
) : ( ) : (
<Input <Input

View File

@@ -110,7 +110,7 @@ const TaskListTaskCell = ({
}; };
const renderSubtasksCountLabel = (taskId: string, isSubTask: boolean, subTasksCount: number) => { const renderSubtasksCountLabel = (taskId: string, isSubTask: boolean, subTasksCount: number) => {
if (!taskId) return null; if (!taskId || subTasksCount <= 1) return null;
return ( return (
<Button <Button
onClick={() => handleToggleExpansion(taskId)} onClick={() => handleToggleExpansion(taskId)}

View File

@@ -36,6 +36,7 @@ export interface Task {
comments_count?: number; comments_count?: number;
attachments_count?: number; attachments_count?: number;
has_dependencies?: boolean; has_dependencies?: boolean;
has_subscribers?: boolean;
schedule_id?: string | null; schedule_id?: string | null;
order?: number; order?: number;
reporter?: string; // Reporter field reporter?: string; // Reporter field