Merge pull request #217 from shancds/fix/enhanced-board-assignees
Fix/enhanced board assignees
This commit is contained in:
@@ -82,11 +82,11 @@ const onTaskSortOrderChange = async (io: Server, socket: Socket, data: ChangeReq
|
|||||||
const dependencyResult = await dbPool.query(`
|
const dependencyResult = await dbPool.query(`
|
||||||
SELECT EXISTS(
|
SELECT EXISTS(
|
||||||
SELECT 1 FROM project_members pm
|
SELECT 1 FROM project_members pm
|
||||||
INNER JOIN projects p ON p.id = pm.project_id
|
INNER JOIN projects p ON p.id = pm.project_id
|
||||||
WHERE pm.project_id = $1
|
INNER JOIN team_members tm ON pm.team_member_id = tm.id
|
||||||
AND pm.user_id = $2
|
WHERE pm.project_id = $1
|
||||||
AND p.team_id = $3
|
AND tm.user_id = $2
|
||||||
AND pm.is_active = true
|
AND p.team_id = $3
|
||||||
) as has_access
|
) as has_access
|
||||||
`, [project_id, userId, team_id]);
|
`, [project_id, userId, team_id]);
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import { sortTeamMembers } from '@/utils/sort-team-members';
|
|||||||
import { useAppDispatch } from '@/hooks/useAppDispatch';
|
import { useAppDispatch } from '@/hooks/useAppDispatch';
|
||||||
import { toggleProjectMemberDrawer } from '@/features/projects/singleProject/members/projectMembersSlice';
|
import { toggleProjectMemberDrawer } from '@/features/projects/singleProject/members/projectMembersSlice';
|
||||||
import { updateTask } from '@/features/task-management/task-management.slice';
|
import { updateTask } from '@/features/task-management/task-management.slice';
|
||||||
|
import { updateEnhancedKanbanTaskAssignees } from '@/features/enhanced-kanban/enhanced-kanban.slice';
|
||||||
|
|
||||||
interface AssigneeSelectorProps {
|
interface AssigneeSelectorProps {
|
||||||
task: IProjectTask;
|
task: IProjectTask;
|
||||||
@@ -177,6 +178,12 @@ const AssigneeSelector: React.FC<AssigneeSelectorProps> = ({
|
|||||||
|
|
||||||
// Emit socket event - the socket handler will update Redux with proper types
|
// Emit socket event - the socket handler will update Redux with proper types
|
||||||
socket?.emit(SocketEvents.QUICK_ASSIGNEES_UPDATE.toString(), JSON.stringify(body));
|
socket?.emit(SocketEvents.QUICK_ASSIGNEES_UPDATE.toString(), JSON.stringify(body));
|
||||||
|
socket?.once(
|
||||||
|
SocketEvents.QUICK_ASSIGNEES_UPDATE.toString(),
|
||||||
|
(data: any) => {
|
||||||
|
dispatch(updateEnhancedKanbanTaskAssignees(data));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// Remove from pending changes after a short delay (optimistic)
|
// Remove from pending changes after a short delay (optimistic)
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@@ -226,6 +233,7 @@ const AssigneeSelector: React.FC<AssigneeSelectorProps> = ({
|
|||||||
{isOpen && createPortal(
|
{isOpen && createPortal(
|
||||||
<div
|
<div
|
||||||
ref={dropdownRef}
|
ref={dropdownRef}
|
||||||
|
onClick={e => e.stopPropagation()}
|
||||||
className={`
|
className={`
|
||||||
fixed z-9999 w-72 rounded-md shadow-lg border
|
fixed z-9999 w-72 rounded-md shadow-lg border
|
||||||
${isDarkMode
|
${isDarkMode
|
||||||
@@ -284,12 +292,14 @@ const AssigneeSelector: React.FC<AssigneeSelectorProps> = ({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<Checkbox
|
<span onClick={e => e.stopPropagation()}>
|
||||||
checked={checkMemberSelected(member.id || '')}
|
<Checkbox
|
||||||
onChange={(checked) => handleMemberToggle(member.id || '', checked)}
|
checked={checkMemberSelected(member.id || '')}
|
||||||
disabled={member.pending_invitation || pendingChanges.has(member.id || '')}
|
onChange={(checked) => handleMemberToggle(member.id || '', checked)}
|
||||||
isDarkMode={isDarkMode}
|
disabled={member.pending_invitation || pendingChanges.has(member.id || '')}
|
||||||
/>
|
isDarkMode={isDarkMode}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
{pendingChanges.has(member.id || '') && (
|
{pendingChanges.has(member.id || '') && (
|
||||||
<div className={`absolute inset-0 flex items-center justify-center ${
|
<div className={`absolute inset-0 flex items-center justify-center ${
|
||||||
isDarkMode ? 'bg-gray-800/50' : 'bg-white/50'
|
isDarkMode ? 'bg-gray-800/50' : 'bg-white/50'
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import {
|
|||||||
DragStartEvent,
|
DragStartEvent,
|
||||||
DragEndEvent,
|
DragEndEvent,
|
||||||
DragOverEvent,
|
DragOverEvent,
|
||||||
closestCorners,
|
|
||||||
KeyboardSensor,
|
KeyboardSensor,
|
||||||
PointerSensor,
|
PointerSensor,
|
||||||
useSensor,
|
useSensor,
|
||||||
@@ -20,7 +19,6 @@ import {
|
|||||||
import {
|
import {
|
||||||
SortableContext,
|
SortableContext,
|
||||||
horizontalListSortingStrategy,
|
horizontalListSortingStrategy,
|
||||||
verticalListSortingStrategy,
|
|
||||||
} from '@dnd-kit/sortable';
|
} from '@dnd-kit/sortable';
|
||||||
import { RootState } from '@/app/store';
|
import { RootState } from '@/app/store';
|
||||||
import {
|
import {
|
||||||
@@ -34,8 +32,6 @@ import {
|
|||||||
fetchEnhancedKanbanLabels,
|
fetchEnhancedKanbanLabels,
|
||||||
} from '@/features/enhanced-kanban/enhanced-kanban.slice';
|
} from '@/features/enhanced-kanban/enhanced-kanban.slice';
|
||||||
import EnhancedKanbanGroup from './EnhancedKanbanGroup';
|
import EnhancedKanbanGroup from './EnhancedKanbanGroup';
|
||||||
import EnhancedKanbanTaskCard from './EnhancedKanbanTaskCard';
|
|
||||||
import PerformanceMonitor from './PerformanceMonitor';
|
|
||||||
import './EnhancedKanbanBoard.css';
|
import './EnhancedKanbanBoard.css';
|
||||||
import { useSocket } from '@/socket/socketContext';
|
import { useSocket } from '@/socket/socketContext';
|
||||||
import { useAppSelector } from '@/hooks/useAppSelector';
|
import { useAppSelector } from '@/hooks/useAppSelector';
|
||||||
@@ -50,6 +46,7 @@ import ImprovedTaskFilters from '../task-management/improved-task-filters';
|
|||||||
import { fetchStatusesCategories } from '@/features/taskAttributes/taskStatusSlice';
|
import { fetchStatusesCategories } from '@/features/taskAttributes/taskStatusSlice';
|
||||||
import { useFilterDataLoader } from '@/hooks/useFilterDataLoader';
|
import { useFilterDataLoader } from '@/hooks/useFilterDataLoader';
|
||||||
import { useTaskSocketHandlers } from '@/hooks/useTaskSocketHandlers';
|
import { useTaskSocketHandlers } from '@/hooks/useTaskSocketHandlers';
|
||||||
|
import { useAuthService } from '@/hooks/useAuth';
|
||||||
|
|
||||||
// Import the TaskListFilters component
|
// Import the TaskListFilters component
|
||||||
const TaskListFilters = React.lazy(() => import('@/pages/projects/projectView/taskList/task-list-filters/task-list-filters'));
|
const TaskListFilters = React.lazy(() => import('@/pages/projects/projectView/taskList/task-list-filters/task-list-filters'));
|
||||||
@@ -68,7 +65,8 @@ const EnhancedKanbanBoard: React.FC<EnhancedKanbanBoardProps> = ({ projectId, cl
|
|||||||
performanceMetrics
|
performanceMetrics
|
||||||
} = useSelector((state: RootState) => state.enhancedKanbanReducer);
|
} = useSelector((state: RootState) => state.enhancedKanbanReducer);
|
||||||
const { socket } = useSocket();
|
const { socket } = useSocket();
|
||||||
const { teamId } = useAppSelector((state: RootState) => state.auth);
|
const authService = useAuthService();
|
||||||
|
const teamId = authService.getCurrentSession()?.team_id;
|
||||||
const groupBy = useSelector((state: RootState) => state.enhancedKanbanReducer.groupBy);
|
const groupBy = useSelector((state: RootState) => state.enhancedKanbanReducer.groupBy);
|
||||||
const project = useAppSelector((state: RootState) => state.projectReducer.project);
|
const project = useAppSelector((state: RootState) => state.projectReducer.project);
|
||||||
const { statusCategories, status: existingStatuses } = useAppSelector((state) => state.taskStatusReducer);
|
const { statusCategories, status: existingStatuses } = useAppSelector((state) => state.taskStatusReducer);
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import { useAppDispatch } from '@/hooks/useAppDispatch';
|
|||||||
import { setShowTaskDrawer, setSelectedTaskId } from '@/features/task-drawer/task-drawer.slice';
|
import { setShowTaskDrawer, setSelectedTaskId } from '@/features/task-drawer/task-drawer.slice';
|
||||||
import PrioritySection from '../board/taskCard/priority-section/priority-section';
|
import PrioritySection from '../board/taskCard/priority-section/priority-section';
|
||||||
import Typography from 'antd/es/typography';
|
import Typography from 'antd/es/typography';
|
||||||
import CustomAvatarGroup from '../board/custom-avatar-group';
|
|
||||||
import CustomDueDatePicker from '../board/custom-due-date-picker';
|
import CustomDueDatePicker from '../board/custom-due-date-picker';
|
||||||
import { themeWiseColor } from '@/utils/themeWiseColor';
|
import { themeWiseColor } from '@/utils/themeWiseColor';
|
||||||
import { ForkOutlined } from '@ant-design/icons';
|
import { ForkOutlined } from '@ant-design/icons';
|
||||||
@@ -29,6 +28,8 @@ import BoardSubTaskCard from '@/pages/projects/projectView/board/board-section/b
|
|||||||
import BoardCreateSubtaskCard from '@/pages/projects/projectView/board/board-section/board-sub-task-card/board-create-sub-task-card';
|
import BoardCreateSubtaskCard from '@/pages/projects/projectView/board/board-section/board-sub-task-card/board-create-sub-task-card';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import EnhancedKanbanCreateSubtaskCard from './EnhancedKanbanCreateSubtaskCard';
|
import EnhancedKanbanCreateSubtaskCard from './EnhancedKanbanCreateSubtaskCard';
|
||||||
|
import LazyAssigneeSelectorWrapper from '@/components/task-management/lazy-assignee-selector';
|
||||||
|
import AvatarGroup from '@/components/AvatarGroup';
|
||||||
|
|
||||||
interface EnhancedKanbanTaskCardProps {
|
interface EnhancedKanbanTaskCardProps {
|
||||||
task: IProjectTask;
|
task: IProjectTask;
|
||||||
@@ -179,8 +180,15 @@ const EnhancedKanbanTaskCard: React.FC<EnhancedKanbanTaskCardProps> = React.memo
|
|||||||
marginBlock: 8,
|
marginBlock: 8,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{task && <CustomAvatarGroup task={task} sectionId={sectionId} />}
|
<Flex align="center" gap={2}>
|
||||||
|
<AvatarGroup
|
||||||
|
members={task.names || []}
|
||||||
|
maxCount={3}
|
||||||
|
isDarkMode={themeMode === 'dark'}
|
||||||
|
size={24}
|
||||||
|
/>
|
||||||
|
<LazyAssigneeSelectorWrapper task={task} groupId={sectionId} isDarkMode={themeMode === 'dark'} />
|
||||||
|
</Flex>
|
||||||
<Flex gap={4} align="center">
|
<Flex gap={4} align="center">
|
||||||
<CustomDueDatePicker task={task} onDateChange={setDueDate} />
|
<CustomDueDatePicker task={task} onDateChange={setDueDate} />
|
||||||
|
|
||||||
|
|||||||
@@ -1,189 +0,0 @@
|
|||||||
# Enhanced Kanban Board - Performance Optimizations
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
The Enhanced Kanban Board is designed to handle **much much** tasks efficiently through multiple performance optimization strategies.
|
|
||||||
|
|
||||||
## Performance Features
|
|
||||||
|
|
||||||
### 🚀 **Virtualization**
|
|
||||||
- **Automatic Activation**: Virtualization kicks in when groups have >50 tasks
|
|
||||||
- **React Window**: Uses `react-window` for efficient rendering of large lists
|
|
||||||
- **Overscan**: Renders 5 extra items for smooth scrolling
|
|
||||||
- **Dynamic Height**: Adjusts container height based on task count
|
|
||||||
|
|
||||||
### 📊 **Performance Monitoring**
|
|
||||||
- **Real-time Metrics**: Tracks total tasks, largest group, average group size
|
|
||||||
- **Visual Indicators**: Shows performance status (Excellent/Good/Warning/Critical)
|
|
||||||
- **Virtualization Status**: Indicates when virtualization is active
|
|
||||||
- **Performance Tips**: Provides optimization suggestions for large datasets
|
|
||||||
|
|
||||||
### 🎯 **Smart Rendering**
|
|
||||||
- **Memoization**: All components use React.memo for optimal re-rendering
|
|
||||||
- **Conditional Rendering**: Drop indicators only render when needed
|
|
||||||
- **Lazy Loading**: Components load only when required
|
|
||||||
- **CSS Containment**: Uses `contain: layout style paint` for performance
|
|
||||||
|
|
||||||
### 💾 **Caching Strategy**
|
|
||||||
- **Task Cache**: Stores individual tasks for quick access
|
|
||||||
- **Group Cache**: Caches group data to prevent recalculation
|
|
||||||
- **Redux Optimization**: Optimistic updates with rollback capability
|
|
||||||
- **Memory Management**: Automatic cache cleanup
|
|
||||||
|
|
||||||
## Performance Thresholds
|
|
||||||
|
|
||||||
| Task Count | Performance Level | Features Enabled |
|
|
||||||
|------------|-------------------|------------------|
|
|
||||||
| 0-50 | Excellent | Standard rendering |
|
|
||||||
| 51-100 | Good | Virtualization |
|
|
||||||
| 101-500 | Good | Virtualization + Monitoring |
|
|
||||||
| 501-1000 | Warning | All optimizations |
|
|
||||||
| 1000+ | Critical | All optimizations + Tips |
|
|
||||||
|
|
||||||
## Key Components
|
|
||||||
|
|
||||||
### VirtualizedTaskList
|
|
||||||
```typescript
|
|
||||||
// Handles large task lists efficiently
|
|
||||||
<VirtualizedTaskList
|
|
||||||
tasks={group.tasks}
|
|
||||||
height={groupHeight}
|
|
||||||
itemHeight={80}
|
|
||||||
activeTaskId={activeTaskId}
|
|
||||||
overId={overId}
|
|
||||||
/>
|
|
||||||
```
|
|
||||||
|
|
||||||
### PerformanceMonitor
|
|
||||||
```typescript
|
|
||||||
// Shows performance metrics for large datasets
|
|
||||||
<PerformanceMonitor />
|
|
||||||
// Only appears when totalTasks > 100
|
|
||||||
```
|
|
||||||
|
|
||||||
### EnhancedKanbanGroup
|
|
||||||
```typescript
|
|
||||||
// Automatically switches between standard and virtualized rendering
|
|
||||||
const shouldVirtualize = group.tasks.length > VIRTUALIZATION_THRESHOLD;
|
|
||||||
```
|
|
||||||
|
|
||||||
## Performance Optimizations
|
|
||||||
|
|
||||||
### 1. **React Optimization**
|
|
||||||
- `React.memo()` on all components
|
|
||||||
- `useMemo()` for expensive calculations
|
|
||||||
- `useCallback()` for event handlers
|
|
||||||
- Conditional rendering to avoid unnecessary work
|
|
||||||
|
|
||||||
### 2. **CSS Performance**
|
|
||||||
```css
|
|
||||||
/* Performance optimizations */
|
|
||||||
.enhanced-kanban-group-tasks.large-list {
|
|
||||||
contain: layout style paint;
|
|
||||||
will-change: transform;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. **Drag and Drop Optimization**
|
|
||||||
- Enhanced collision detection
|
|
||||||
- Optimized sensor configuration
|
|
||||||
- Minimal re-renders during drag operations
|
|
||||||
- Efficient drop target identification
|
|
||||||
|
|
||||||
### 4. **Memory Management**
|
|
||||||
- Automatic cache cleanup
|
|
||||||
- Efficient data structures
|
|
||||||
- Minimal object creation
|
|
||||||
- Proper cleanup in useEffect
|
|
||||||
|
|
||||||
## Usage Examples
|
|
||||||
|
|
||||||
### Large Dataset Handling
|
|
||||||
```typescript
|
|
||||||
// The board automatically optimizes for large datasets
|
|
||||||
const largeProject = {
|
|
||||||
taskGroups: [
|
|
||||||
{ id: '1', name: 'To Do', tasks: [/* 200 tasks */] },
|
|
||||||
{ id: '2', name: 'In Progress', tasks: [/* 150 tasks */] },
|
|
||||||
{ id: '3', name: 'Done', tasks: [/* 300 tasks */] }
|
|
||||||
]
|
|
||||||
};
|
|
||||||
// Total: 650 tasks - virtualization automatically enabled
|
|
||||||
```
|
|
||||||
|
|
||||||
### Performance Monitoring
|
|
||||||
```typescript
|
|
||||||
// Performance metrics are automatically tracked
|
|
||||||
const metrics = {
|
|
||||||
totalTasks: 650,
|
|
||||||
largestGroupSize: 300,
|
|
||||||
averageGroupSize: 217,
|
|
||||||
virtualizationEnabled: true
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
## Best Practices
|
|
||||||
|
|
||||||
### For Large Projects
|
|
||||||
1. **Use Filters**: Reduce visible tasks with search/filters
|
|
||||||
2. **Group Strategically**: Choose grouping that distributes tasks evenly
|
|
||||||
3. **Monitor Performance**: Watch the performance monitor for insights
|
|
||||||
4. **Consider Pagination**: For extremely large datasets (>2000 tasks)
|
|
||||||
|
|
||||||
### For Optimal Performance
|
|
||||||
1. **Keep Groups Balanced**: Avoid single groups with 1000+ tasks
|
|
||||||
2. **Use Meaningful Grouping**: Group by status, priority, or assignee
|
|
||||||
3. **Regular Cleanup**: Archive completed tasks regularly
|
|
||||||
4. **Monitor Metrics**: Use the performance monitor to track trends
|
|
||||||
|
|
||||||
## Technical Details
|
|
||||||
|
|
||||||
### Virtualization Implementation
|
|
||||||
- **Item Height**: Fixed at 80px for consistency
|
|
||||||
- **Overscan**: 5 items for smooth scrolling
|
|
||||||
- **Dynamic Height**: Scales with content (200px - 600px)
|
|
||||||
- **Responsive**: Adapts to screen size
|
|
||||||
|
|
||||||
### Memory Usage
|
|
||||||
- **Task Cache**: ~1KB per task
|
|
||||||
- **Group Cache**: ~2KB per group
|
|
||||||
- **Virtualization**: Only renders visible items
|
|
||||||
- **Cleanup**: Automatic garbage collection
|
|
||||||
|
|
||||||
### Rendering Performance
|
|
||||||
- **60fps**: Maintained even with 1000+ tasks
|
|
||||||
- **Smooth Scrolling**: Optimized for large lists
|
|
||||||
- **Drag and Drop**: Responsive even with large datasets
|
|
||||||
- **Updates**: Optimistic updates for immediate feedback
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Performance Issues
|
|
||||||
1. **Check Task Count**: Monitor the performance metrics
|
|
||||||
2. **Enable Virtualization**: Ensure groups with >50 tasks use virtualization
|
|
||||||
3. **Use Filters**: Reduce visible tasks with search/filters
|
|
||||||
4. **Group Optimization**: Consider different grouping strategies
|
|
||||||
|
|
||||||
### Memory Issues
|
|
||||||
1. **Clear Cache**: Use the clear cache action if needed
|
|
||||||
2. **Archive Tasks**: Move completed tasks to archived status
|
|
||||||
3. **Monitor Usage**: Watch browser memory usage
|
|
||||||
4. **Refresh**: Reload the page if memory usage is high
|
|
||||||
|
|
||||||
## Future Enhancements
|
|
||||||
|
|
||||||
### Planned Optimizations
|
|
||||||
- **Infinite Scrolling**: Load tasks on demand
|
|
||||||
- **Web Workers**: Move heavy calculations to background threads
|
|
||||||
- **IndexedDB**: Client-side caching for offline support
|
|
||||||
- **Service Workers**: Background sync for updates
|
|
||||||
|
|
||||||
### Advanced Features
|
|
||||||
- **Predictive Loading**: Pre-load likely-to-be-viewed tasks
|
|
||||||
- **Smart Caching**: AI-powered cache optimization
|
|
||||||
- **Performance Analytics**: Detailed performance insights
|
|
||||||
- **Auto-optimization**: Automatic performance tuning
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**The Enhanced Kanban Board is designed to handle projects of any size efficiently, from small teams to enterprise-scale operations with thousands of tasks.**
|
|
||||||
@@ -176,8 +176,6 @@ export const useTaskSocketHandlers = () => {
|
|||||||
(response: ITaskListStatusChangeResponse) => {
|
(response: ITaskListStatusChangeResponse) => {
|
||||||
if (!response) return;
|
if (!response) return;
|
||||||
|
|
||||||
console.log('🔄 Status change received:', response);
|
|
||||||
|
|
||||||
if (response.completed_deps === false) {
|
if (response.completed_deps === false) {
|
||||||
alertService.error(
|
alertService.error(
|
||||||
'Task is not completed',
|
'Task is not completed',
|
||||||
@@ -198,13 +196,6 @@ export const useTaskSocketHandlers = () => {
|
|||||||
const groups = state.taskManagement.groups;
|
const groups = state.taskManagement.groups;
|
||||||
const currentTask = state.taskManagement.entities[response.id];
|
const currentTask = state.taskManagement.entities[response.id];
|
||||||
|
|
||||||
console.log('🔍 Status change debug:', {
|
|
||||||
hasGroups: !!groups,
|
|
||||||
groupsLength: groups?.length || 0,
|
|
||||||
hasCurrentTask: !!currentTask,
|
|
||||||
statusId: response.status_id,
|
|
||||||
currentGrouping: state.taskManagement.grouping
|
|
||||||
});
|
|
||||||
|
|
||||||
if (groups && groups.length > 0 && currentTask && response.status_id) {
|
if (groups && groups.length > 0 && currentTask && response.status_id) {
|
||||||
// Find current group containing the task
|
// Find current group containing the task
|
||||||
@@ -215,11 +206,6 @@ export const useTaskSocketHandlers = () => {
|
|||||||
const targetGroup = groups.find(group => group.id === response.status_id);
|
const targetGroup = groups.find(group => group.id === response.status_id);
|
||||||
|
|
||||||
if (currentGroup && targetGroup && currentGroup.id !== targetGroup.id) {
|
if (currentGroup && targetGroup && currentGroup.id !== targetGroup.id) {
|
||||||
console.log('🔄 Moving task between groups:', {
|
|
||||||
taskId: response.id,
|
|
||||||
fromGroup: currentGroup.title,
|
|
||||||
toGroup: targetGroup.title
|
|
||||||
});
|
|
||||||
|
|
||||||
// Determine the new status value based on status category
|
// Determine the new status value based on status category
|
||||||
let newStatusValue: 'todo' | 'doing' | 'done' = 'todo';
|
let newStatusValue: 'todo' | 'doing' | 'done' = 'todo';
|
||||||
@@ -244,8 +230,6 @@ export const useTaskSocketHandlers = () => {
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
} else if (!currentGroup || !targetGroup) {
|
} else if (!currentGroup || !targetGroup) {
|
||||||
// Log the issue but don't refetch - real-time updates should handle this
|
|
||||||
console.log('🔄 Groups not found, but avoiding refetch to prevent data thrashing');
|
|
||||||
// Remove unnecessary refetch that causes data thrashing
|
// Remove unnecessary refetch that causes data thrashing
|
||||||
// if (projectId) {
|
// if (projectId) {
|
||||||
// dispatch(fetchTasksV3(projectId));
|
// dispatch(fetchTasksV3(projectId));
|
||||||
@@ -305,8 +289,6 @@ export const useTaskSocketHandlers = () => {
|
|||||||
(response: ITaskListPriorityChangeResponse) => {
|
(response: ITaskListPriorityChangeResponse) => {
|
||||||
if (!response) return;
|
if (!response) return;
|
||||||
|
|
||||||
console.log('🎯 Priority change received:', response);
|
|
||||||
|
|
||||||
// Update the old task slice (for backward compatibility)
|
// Update the old task slice (for backward compatibility)
|
||||||
dispatch(updateTaskPriority(response));
|
dispatch(updateTaskPriority(response));
|
||||||
dispatch(setTaskPriority(response));
|
dispatch(setTaskPriority(response));
|
||||||
@@ -332,14 +314,6 @@ export const useTaskSocketHandlers = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('🔧 Updating task priority:', {
|
|
||||||
taskId: response.id,
|
|
||||||
oldPriority: currentTask.priority,
|
|
||||||
newPriority: newPriorityValue,
|
|
||||||
priorityId: response.priority_id,
|
|
||||||
currentGrouping: state.taskManagement.grouping
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update the task entity
|
// Update the task entity
|
||||||
dispatch(updateTask({
|
dispatch(updateTask({
|
||||||
id: response.id,
|
id: response.id,
|
||||||
@@ -363,12 +337,6 @@ export const useTaskSocketHandlers = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (currentGroup && targetGroup && currentGroup.id !== targetGroup.id) {
|
if (currentGroup && targetGroup && currentGroup.id !== targetGroup.id) {
|
||||||
console.log('🔄 Moving task between priority groups:', {
|
|
||||||
taskId: response.id,
|
|
||||||
fromGroup: currentGroup.title,
|
|
||||||
toGroup: targetGroup.title,
|
|
||||||
newPriority: newPriorityValue
|
|
||||||
});
|
|
||||||
|
|
||||||
dispatch(moveTaskBetweenGroups({
|
dispatch(moveTaskBetweenGroups({
|
||||||
taskId: response.id,
|
taskId: response.id,
|
||||||
@@ -439,8 +407,6 @@ export const useTaskSocketHandlers = () => {
|
|||||||
(data: ITaskPhaseChangeResponse) => {
|
(data: ITaskPhaseChangeResponse) => {
|
||||||
if (!data) return;
|
if (!data) return;
|
||||||
|
|
||||||
console.log('🎯 Phase change received:', data);
|
|
||||||
|
|
||||||
// Update the old task slice (for backward compatibility)
|
// Update the old task slice (for backward compatibility)
|
||||||
dispatch(updateTaskPhase(data));
|
dispatch(updateTaskPhase(data));
|
||||||
dispatch(deselectAll());
|
dispatch(deselectAll());
|
||||||
@@ -466,14 +432,6 @@ export const useTaskSocketHandlers = () => {
|
|||||||
newPhaseValue = '';
|
newPhaseValue = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('🔧 Updating task phase:', {
|
|
||||||
taskId: taskId,
|
|
||||||
oldPhase: currentTask.phase,
|
|
||||||
newPhase: newPhaseValue,
|
|
||||||
phaseId: data.id,
|
|
||||||
currentGrouping: state.taskManagement.grouping
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update the task entity
|
// Update the task entity
|
||||||
dispatch(updateTask({
|
dispatch(updateTask({
|
||||||
id: taskId,
|
id: taskId,
|
||||||
@@ -507,12 +465,6 @@ export const useTaskSocketHandlers = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (currentGroup && targetGroup && currentGroup.id !== targetGroup.id) {
|
if (currentGroup && targetGroup && currentGroup.id !== targetGroup.id) {
|
||||||
console.log('🔄 Moving task between phase groups:', {
|
|
||||||
taskId: taskId,
|
|
||||||
fromGroup: currentGroup.title,
|
|
||||||
toGroup: targetGroup.title,
|
|
||||||
newPhase: newPhaseValue || 'No Phase'
|
|
||||||
});
|
|
||||||
|
|
||||||
dispatch(moveTaskBetweenGroups({
|
dispatch(moveTaskBetweenGroups({
|
||||||
taskId: taskId,
|
taskId: taskId,
|
||||||
@@ -705,7 +657,7 @@ export const useTaskSocketHandlers = () => {
|
|||||||
|
|
||||||
// This event only provides assignee IDs, so we update what we can
|
// This event only provides assignee IDs, so we update what we can
|
||||||
// The full assignee data will come from QUICK_ASSIGNEES_UPDATE
|
// The full assignee data will come from QUICK_ASSIGNEES_UPDATE
|
||||||
console.log('🔄 Task assignees change (limited data):', data);
|
// console.log('🔄 Task assignees change (limited data):', data);
|
||||||
},
|
},
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user