feat(task-list): add tooltips for task indicators and enhance localization
- Introduced tooltips for subtasks, comments, attachments, subscribers, dependencies, and recurring tasks across various components to improve user experience. - Enhanced localization by adding new translation keys for these indicators in multiple languages, ensuring consistent messaging for users. - Updated components such as TaskRow, KanbanTaskCard, and EnhancedKanbanTaskCard to utilize the new tooltip functionality, improving clarity and accessibility.
This commit is contained in:
@@ -1297,93 +1297,6 @@ const ImprovedTaskFilters: React.FC<ImprovedTaskFiltersProps> = ({ position, cla
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Active Filters Pills */}
|
||||
{activeFiltersCount > 0 && (
|
||||
<div
|
||||
className={`flex flex-wrap items-center gap-1.5 mt-2 pt-2 border-t ${themeClasses.dividerBorder}`}
|
||||
>
|
||||
{searchValue && (
|
||||
<div
|
||||
className={`inline-flex items-center gap-1 px-1.5 py-0.5 text-xs font-medium rounded-full ${themeClasses.pillActiveBg} ${themeClasses.pillActiveText}`}
|
||||
>
|
||||
<SearchOutlined className="w-2.5 h-2.5" />
|
||||
<span>"{searchValue}"</span>
|
||||
<button
|
||||
onClick={() => {
|
||||
if (projectId) {
|
||||
// Cancel pending search and immediately clear
|
||||
debouncedSearchChangeRef.current?.cancel();
|
||||
if (position === 'board') {
|
||||
dispatch(setKanbanSearch(''));
|
||||
dispatch(fetchEnhancedKanbanGroups(projectId));
|
||||
} else {
|
||||
// Always use taskReducer search for list view
|
||||
dispatch(setSearch(''));
|
||||
dispatch(fetchTasksV3(projectId));
|
||||
}
|
||||
}
|
||||
}}
|
||||
className={`ml-1 rounded-full p-0.5 transition-colors duration-150 ${
|
||||
isDarkMode ? 'hover:bg-gray-800' : 'hover:bg-gray-200'
|
||||
}`}
|
||||
>
|
||||
<CloseOutlined className="w-2.5 h-2.5" />
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{filterSectionsData
|
||||
.filter(section => section.id !== 'groupBy') // <-- skip groupBy
|
||||
.flatMap(section =>
|
||||
section.selectedValues
|
||||
.map(value => {
|
||||
const option = section.options.find(opt => opt.value === value);
|
||||
if (!option) return null;
|
||||
|
||||
return (
|
||||
<div
|
||||
key={`${section.id}-${value}`}
|
||||
className={`inline-flex items-center gap-1 px-1.5 py-0.5 text-xs font-medium rounded-full ${themeClasses.pillBg} ${themeClasses.pillText}`}
|
||||
>
|
||||
{option.color && (
|
||||
<div
|
||||
className="w-2 h-2 rounded-full"
|
||||
style={{ backgroundColor: option.color }}
|
||||
/>
|
||||
)}
|
||||
<span>{option.label}</span>
|
||||
<button
|
||||
onClick={() => {
|
||||
// Update local state immediately for UI feedback
|
||||
setFilterSections(prev =>
|
||||
prev.map(s =>
|
||||
s.id === section.id
|
||||
? {
|
||||
...s,
|
||||
selectedValues: s.selectedValues.filter(v => v !== value),
|
||||
}
|
||||
: s
|
||||
)
|
||||
);
|
||||
|
||||
// Use debounced API call
|
||||
const newValues = section.selectedValues.filter(v => v !== value);
|
||||
handleSelectionChange(section.id, newValues);
|
||||
}}
|
||||
className={`ml-1 rounded-full p-0.5 transition-colors duration-150 ${
|
||||
isDarkMode ? 'hover:bg-gray-600' : 'hover:bg-gray-200'
|
||||
}`}
|
||||
>
|
||||
<CloseOutlined className="w-2.5 h-2.5" />
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
})
|
||||
.filter(Boolean)
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1017,7 +1017,7 @@ const TaskRow: React.FC<TaskRowProps> = React.memo(
|
||||
<div className="task-indicators flex items-center gap-2">
|
||||
{/* Comments indicator */}
|
||||
{(task as any).comments_count > 0 && (
|
||||
<Tooltip title={t('taskManagement.comments', 'Comments')}>
|
||||
<Tooltip title={t(`task-management:indicators.tooltips.comments${(task as any).comments_count === 1 ? '' : '_plural'}`, { count: (task as any).comments_count })}>
|
||||
<MessageOutlined
|
||||
style={{ fontSize: 14, color: isDarkMode ? '#b0b3b8' : '#888' }}
|
||||
/>
|
||||
@@ -1025,7 +1025,7 @@ const TaskRow: React.FC<TaskRowProps> = React.memo(
|
||||
)}
|
||||
{/* Attachments indicator */}
|
||||
{(task as any).attachments_count > 0 && (
|
||||
<Tooltip title={t('taskManagement.attachments', 'Attachments')}>
|
||||
<Tooltip title={t(`task-management:indicators.tooltips.attachments${(task as any).attachments_count === 1 ? '' : '_plural'}`, { count: (task as any).attachments_count })}>
|
||||
<PaperClipOutlined
|
||||
style={{ fontSize: 14, color: isDarkMode ? '#b0b3b8' : '#888' }}
|
||||
/>
|
||||
@@ -1033,7 +1033,7 @@ const TaskRow: React.FC<TaskRowProps> = React.memo(
|
||||
)}
|
||||
{/* Dependencies indicator */}
|
||||
{(task as any).has_dependencies && (
|
||||
<Tooltip title={t('taskManagement.dependencies', 'Dependencies')}>
|
||||
<Tooltip title={t('task-management:indicators.tooltips.dependencies')}>
|
||||
<MinusCircleOutlined
|
||||
style={{ fontSize: 14, color: isDarkMode ? '#b0b3b8' : '#888' }}
|
||||
/>
|
||||
@@ -1041,7 +1041,7 @@ const TaskRow: React.FC<TaskRowProps> = React.memo(
|
||||
)}
|
||||
{/* Subscribers indicator */}
|
||||
{(task as any).has_subscribers && (
|
||||
<Tooltip title={t('taskManagement.subscribers', 'Subscribers')}>
|
||||
<Tooltip title={t('task-management:indicators.tooltips.subscribers')}>
|
||||
<EyeOutlined
|
||||
style={{ fontSize: 14, color: isDarkMode ? '#b0b3b8' : '#888' }}
|
||||
/>
|
||||
@@ -1049,7 +1049,7 @@ const TaskRow: React.FC<TaskRowProps> = React.memo(
|
||||
)}
|
||||
{/* Recurring indicator */}
|
||||
{(task as any).schedule_id && (
|
||||
<Tooltip title={t('taskManagement.recurringTask', 'Recurring Task')}>
|
||||
<Tooltip title={t('task-management:indicators.tooltips.recurring')}>
|
||||
<RetweetOutlined
|
||||
style={{ fontSize: 14, color: isDarkMode ? '#b0b3b8' : '#888' }}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user