Refactors event positioning and drag-and-drop
Centralizes event position calculations into `PositionUtils` for consistency and reusability across managers and renderers. Improves drag-and-drop functionality by emitting events for all-day event conversion and streamlining position calculations during drag operations. Introduces `AllDayManager` and `AllDayEventRenderer` to manage and render all-day events in the calendar header. This allows dragging events to the header to convert them to all-day events.
This commit is contained in:
parent
8b96376d1f
commit
7054c0d40a
9 changed files with 404 additions and 72 deletions
245
docs/typescript-code-review-2025.md
Normal file
245
docs/typescript-code-review-2025.md
Normal file
|
|
@ -0,0 +1,245 @@
|
|||
# TypeScript Code Review - Calendar Plantempus
|
||||
**Dato:** September 2025
|
||||
**Reviewer:** Roo
|
||||
**Fokus:** Dybdegående analyse efter TimeFormatter implementation
|
||||
|
||||
## Executive Summary
|
||||
|
||||
Efter implementering af TimeFormatter og gennemgang af codebasen, har jeg identificeret både styrker og forbedringspotentiale. Koden viser god separation of concerns og event-driven arkitektur, men har stadig områder der kan optimeres.
|
||||
|
||||
## 🟢 Styrker
|
||||
|
||||
### 1. Event-Driven Architecture
|
||||
- **Konsistent EventBus pattern** gennem hele applikationen
|
||||
- Ingen direkte dependencies mellem moduler
|
||||
- God brug af custom events for kommunikation
|
||||
|
||||
### 2. Separation of Concerns
|
||||
- **Managers**: Håndterer business logic (AllDayManager, DragDropManager, etc.)
|
||||
- **Renderers**: Fokuserer på DOM manipulation
|
||||
- **Utils**: Isolerede utility funktioner
|
||||
- **Elements**: Factory pattern for DOM element creation
|
||||
|
||||
### 3. Performance Optimering
|
||||
- **DOM Caching**: Konsistent caching af DOM elementer
|
||||
- **Throttling**: Event throttling i HeaderManager (16ms delay)
|
||||
- **Pixel-based calculations**: Fjernet komplekse time-based overlap beregninger
|
||||
|
||||
### 4. TypeScript Best Practices
|
||||
- Stærk typing med interfaces
|
||||
- Proper null/undefined checks
|
||||
- Readonly constants hvor relevant
|
||||
|
||||
## 🔴 Kritiske Issues
|
||||
|
||||
### 1. "new_" Prefix Methods (EventRenderer.ts)
|
||||
```typescript
|
||||
// PROBLEM: Midlertidige metode navne
|
||||
protected new_handleEventOverlaps()
|
||||
protected new_renderOverlappingEvents()
|
||||
protected new_applyStackStyling()
|
||||
protected new_applyColumnSharingStyling()
|
||||
```
|
||||
**Impact:** Forvirrende navngivning, indikerer ufærdig refactoring
|
||||
**Løsning:** Fjern prefix og ryd op i gamle metoder
|
||||
|
||||
### 2. Duplikeret Cache Logic
|
||||
```typescript
|
||||
// AllDayManager.ts
|
||||
private cachedAllDayContainer: HTMLElement | null = null;
|
||||
private cachedCalendarHeader: HTMLElement | null = null;
|
||||
|
||||
// HeaderManager.ts
|
||||
private cachedCalendarHeader: HTMLElement | null = null;
|
||||
|
||||
// DragDropManager.ts
|
||||
private cachedElements: CachedElements = {...}
|
||||
```
|
||||
**Impact:** 30+ linjer duplikeret kode
|
||||
**Løsning:** Opret generisk DOMCacheManager
|
||||
|
||||
### 3. Manglende Error Boundaries
|
||||
```typescript
|
||||
// SimpleEventOverlapManager.ts
|
||||
const linkData = element.dataset.stackLink;
|
||||
try {
|
||||
return JSON.parse(linkData);
|
||||
} catch (e) {
|
||||
console.warn('Failed to parse stack link data:', linkData, e);
|
||||
return null;
|
||||
}
|
||||
```
|
||||
**Impact:** Silently failing JSON parsing
|
||||
**Løsning:** Proper error handling med user feedback
|
||||
|
||||
## 🟡 Code Smells & Improvements
|
||||
|
||||
### 1. Magic Numbers
|
||||
```typescript
|
||||
// SimpleEventOverlapManager.ts
|
||||
const startDifference = Math.abs(top1 - top2);
|
||||
if (startDifference > 40) { // Magic number!
|
||||
return OverlapType.STACKING;
|
||||
}
|
||||
|
||||
// DragDropManager.ts
|
||||
private readonly dragThreshold = 5; // Should be configurable
|
||||
private readonly scrollSpeed = 10;
|
||||
private readonly scrollThreshold = 30;
|
||||
```
|
||||
**Løsning:** Flyt til configuration constants
|
||||
|
||||
### 2. Complex Method Signatures
|
||||
```typescript
|
||||
// AllDayManager.ts - 73 linjer!
|
||||
public checkAndAnimateAllDayHeight(): void {
|
||||
// Massive method doing too much
|
||||
}
|
||||
```
|
||||
**Løsning:** Split i mindre, fokuserede metoder
|
||||
|
||||
### 3. Inconsistent Naming
|
||||
```typescript
|
||||
// Mix af naming conventions
|
||||
getCalendarHeader() // get prefix
|
||||
findElements() // no prefix
|
||||
detectColumn() // action verb
|
||||
cachedElements // noun
|
||||
```
|
||||
**Løsning:** Standardiser naming convention
|
||||
|
||||
### 4. Memory Leaks Risk
|
||||
```typescript
|
||||
// DragDropManager.ts
|
||||
private boundHandlers = {
|
||||
mouseMove: this.handleMouseMove.bind(this),
|
||||
mouseDown: this.handleMouseDown.bind(this),
|
||||
mouseUp: this.handleMouseUp.bind(this)
|
||||
};
|
||||
```
|
||||
**God praksis!** Men ikke konsistent anvendt alle steder
|
||||
|
||||
## 📊 Metrics & Analysis
|
||||
|
||||
### Complexity Analysis
|
||||
| File | Lines | Cyclomatic Complexity | Maintainability |
|
||||
|------|-------|----------------------|-----------------|
|
||||
| AllDayManager.ts | 281 | Medium (8) | Good |
|
||||
| DragDropManager.ts | 521 | High (15) | Needs refactoring |
|
||||
| SimpleEventOverlapManager.ts | 473 | Very High (20) | Critical |
|
||||
| HeaderManager.ts | 119 | Low (4) | Excellent |
|
||||
| GridManager.ts | 348 | Medium (10) | Good |
|
||||
|
||||
### Code Duplication
|
||||
- **Cache management**: ~15% duplication
|
||||
- **Event handling**: ~10% duplication
|
||||
- **Position calculations**: ~8% duplication
|
||||
|
||||
## 🎯 Prioriterede Forbedringer
|
||||
|
||||
### Priority 1: Critical Fixes
|
||||
1. **Fjern "new_" prefix** fra EventRenderer metoder
|
||||
2. **Fix TimeFormatter timezone** - Håndter mock data korrekt som UTC
|
||||
3. **Implementer DOMCacheManager** - Reducer duplication
|
||||
|
||||
### Priority 2: Architecture Improvements
|
||||
1. **GridPositionCalculator** - Centralisér position beregninger
|
||||
2. **EventThrottler** - Generisk throttling utility
|
||||
3. **AllDayRowCalculator** - Udtræk kompleks logik fra AllDayManager
|
||||
|
||||
### Priority 3: Code Quality
|
||||
1. **Reduce method complexity** - Split store metoder
|
||||
2. **Standardize naming** - Konsistent naming convention
|
||||
3. **Add JSDoc** - Mangler på mange public methods
|
||||
|
||||
### Priority 4: Testing
|
||||
1. **Unit tests** for TimeFormatter
|
||||
2. **Integration tests** for overlap detection
|
||||
3. **Performance tests** for large event sets
|
||||
|
||||
## 💡 Architectural Recommendations
|
||||
|
||||
### 1. Introduce Service Layer
|
||||
```typescript
|
||||
// Forslag: EventService
|
||||
class EventService {
|
||||
private formatter: TimeFormatter;
|
||||
private calculator: GridPositionCalculator;
|
||||
private overlapManager: SimpleEventOverlapManager;
|
||||
|
||||
// Centralized event operations
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Configuration Management
|
||||
```typescript
|
||||
interface CalendarConstants {
|
||||
DRAG_THRESHOLD: number;
|
||||
SCROLL_SPEED: number;
|
||||
STACK_OFFSET: number;
|
||||
OVERLAP_THRESHOLD: number;
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Error Handling Strategy
|
||||
```typescript
|
||||
class CalendarError extends Error {
|
||||
constructor(
|
||||
message: string,
|
||||
public code: string,
|
||||
public recoverable: boolean
|
||||
) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🚀 Performance Optimizations
|
||||
|
||||
### 1. Virtual Scrolling
|
||||
For måneds-view med mange events, overvej virtual scrolling
|
||||
|
||||
### 2. Web Workers
|
||||
Flyt tunge beregninger (overlap detection) til Web Worker
|
||||
|
||||
### 3. RequestIdleCallback
|
||||
Brug for non-critical updates som analytics
|
||||
|
||||
## ✅ Positive Highlights
|
||||
|
||||
1. **TimeFormatter Implementation**: Elegant og clean
|
||||
2. **Event-driven Architecture**: Konsistent og velfungerende
|
||||
3. **TypeScript Usage**: God type safety
|
||||
4. **DOM Manipulation**: Effektiv med custom elements
|
||||
5. **Separation of Concerns**: Klar opdeling af ansvar
|
||||
|
||||
## 📋 Recommended Action Plan
|
||||
|
||||
### Immediate (1-2 dage)
|
||||
- [ ] Fjern "new_" prefix fra EventRenderer
|
||||
- [ ] Implementer DOMCacheManager
|
||||
- [ ] Fix magic numbers
|
||||
|
||||
### Short-term (3-5 dage)
|
||||
- [ ] Opret GridPositionCalculator
|
||||
- [ ] Implementer EventThrottler
|
||||
- [ ] Refactor SimpleEventOverlapManager complexity
|
||||
|
||||
### Long-term (1-2 uger)
|
||||
- [ ] Add comprehensive unit tests
|
||||
- [ ] Implement service layer
|
||||
- [ ] Performance optimizations
|
||||
|
||||
## Konklusion
|
||||
|
||||
Koden er generelt velstruktureret med god separation of concerns og konsistent event-driven arkitektur. TimeFormatter implementationen er elegant og løser timezone problemet godt.
|
||||
|
||||
Hovedudfordringerne ligger i:
|
||||
1. Ufærdig refactoring (new_ prefix)
|
||||
2. Duplikeret cache logic
|
||||
3. Høj complexity i overlap detection
|
||||
4. Manglende tests
|
||||
|
||||
Med de foreslåede forbedringer vil kodebasen blive mere maintainable, performant og robust.
|
||||
|
||||
**Overall Score: 7.5/10** - God kvalitet med plads til forbedring
|
||||
Loading…
Add table
Add a link
Reference in a new issue