Add trace files.
Some checks failed
Code Coverage / Generate Coverage Report (push) Has been cancelled
Tests / Run Tests (9.0.x) (push) Has been cancelled
Tests / Docker Build Test (push) Has been cancelled
Tests / Test Summary (push) Has been cancelled

This commit is contained in:
Yaojia Wang
2025-11-04 23:28:56 +01:00
parent 25d30295ec
commit 08b317e789
75 changed files with 26456 additions and 37017 deletions

View File

@@ -0,0 +1,111 @@
# Task 11: Integrate SignalR Real-time Updates
**Task ID**: TASK-011 | **Story**: [STORY-003](sprint_1_story_3.md) | **Sprint**: [Sprint 1](sprint_1.md)
**Estimated Hours**: 3h | **Assignee**: Frontend Developer 1 | **Priority**: P1 | **Status**: Not Started
## Task Description
Connect Kanban board to SignalR event handlers for real-time updates when Epic/Story/Task changes occur.
## Implementation
### Update KanbanBoard.tsx (2h)
```typescript
import { useEffect } from 'react';
import { useSignalRContext } from '../services/signalr/SignalRContext';
import { useQueryClient } from '@tanstack/react-query';
export const KanbanBoard: React.FC = () => {
const { projectId } = useParams();
const queryClient = useQueryClient();
const { service, isConnected } = useSignalRContext();
// Subscribe to real-time events
useEffect(() => {
if (!isConnected || !service) return;
const handlers = service.getEventHandlers();
if (!handlers) return;
// Epic events
const unsubEpicCreated = handlers.subscribe('epic:created', (event) => {
queryClient.invalidateQueries(['epics', projectId]);
});
const unsubEpicUpdated = handlers.subscribe('epic:updated', (event) => {
queryClient.setQueryData(['epics', projectId], (old: Epic[]) => {
return old.map(e => e.id === event.epicId ? { ...e, ...event } : e);
});
});
const unsubEpicDeleted = handlers.subscribe('epic:deleted', (event) => {
queryClient.setQueryData(['epics', projectId], (old: Epic[]) => {
return old.filter(e => e.id !== event.epicId);
});
});
// Story events (similar)
const unsubStoryCreated = handlers.subscribe('story:created', (event) => {
queryClient.invalidateQueries(['stories', projectId]);
});
// Task events (similar)
const unsubTaskCreated = handlers.subscribe('task:created', (event) => {
queryClient.invalidateQueries(['tasks', projectId]);
});
const unsubTaskStatusChanged = handlers.subscribe('task:statusChanged', (event) => {
// Animate card movement between columns
queryClient.setQueryData(['tasks', projectId], (old: Task[]) => {
return old.map(t => t.id === event.taskId ? { ...t, status: event.newStatus } : t);
});
});
// Cleanup subscriptions
return () => {
unsubEpicCreated();
unsubEpicUpdated();
unsubEpicDeleted();
unsubStoryCreated();
unsubTaskCreated();
unsubTaskStatusChanged();
};
}, [isConnected, service, projectId, queryClient]);
// ... rest of component
};
```
### Add Card Animation (1h)
```typescript
// Use framer-motion for smooth animations
import { motion } from 'framer-motion';
export const KanbanCard: React.FC<{ item: any }> = ({ item }) => {
return (
<motion.div
layout
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -20 }}
transition={{ duration: 0.3 }}
className="kanban-card"
>
{/* Card content */}
</motion.div>
);
};
```
## Acceptance Criteria
- [ ] Kanban updates automatically on SignalR events
- [ ] All 13 event types handled
- [ ] Card animations smooth (60 FPS)
- [ ] No duplicate cards after updates
- [ ] Optimistic updates working
## Deliverables
1. SignalR integration in KanbanBoard.tsx
2. Card animations with framer-motion
3. Integration tests (8+ scenarios)
**Status**: Not Started | **Created**: 2025-11-04