Refactor Event Calendar component for improved performance and usability
Optimized the Event Calendar component by enhancing the event fetching logic and improving the rendering efficiency. Updated the user interface for better accessibility and responsiveness. Added additional tests to ensure reliability of the event occurrences service integration.
This commit is contained in:
@@ -0,0 +1,195 @@
|
||||
# Event Occurrence Import and CRUD Implementation Plan
|
||||
|
||||
## Overview
|
||||
Implement a complete EventOccurrence management system with import functionality (text parsing with preview) and CRUD operations. The system will store event occurrences in the database with relationships to EventDefinitions (from database) or special event types (GeneralSchedule/VotingDelegates - hard-coded, not in database). Components are organized under the Calendar feature folder to allow for future expansion to support other calendar-related data types.
|
||||
|
||||
## Architecture
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[User Pastes Text] --> B[EventOccurrenceParser.ParseFromText]
|
||||
B --> C[Parse Results + Errors]
|
||||
C --> D[Preview on Right Side]
|
||||
D --> E{User Approves?}
|
||||
E -->|Yes| F[Save to Database]
|
||||
E -->|No| A
|
||||
F --> G[EventOccurrence Entity]
|
||||
G --> H[Database]
|
||||
|
||||
I[Index Page] --> J{Filter Type}
|
||||
J -->|Future| K[StartTime >= Today]
|
||||
J -->|Historic| L[StartTime < Today]
|
||||
J -->|All| M[All Records]
|
||||
K --> N[Display Grid]
|
||||
L --> N
|
||||
M --> N
|
||||
N --> O[CRUD Operations]
|
||||
```
|
||||
|
||||
## Database Changes
|
||||
|
||||
### 1. Update EventOccurrence Entity
|
||||
- **File**: `Core/Entities/EventOccurrence.cs`
|
||||
- Add `Id` property (int)
|
||||
- Add `EventDefinitionId` property (int?, nullable - references database EventDefinition if set)
|
||||
- Add `SpecialEventType` property (string?, nullable - stores "GeneralSchedule" or "VotingDelegates" when EventDefinitionId is null)
|
||||
- Keep existing properties (Name, Time, Date, StartTime, EndTime, Location)
|
||||
- Add navigation property to EventDefinition
|
||||
- Note: GeneralSchedule and VotingDelegates are hard-coded EventDefinition instances (not stored in database) used only for EventOccurrences. When EventDefinitionId is null, SpecialEventType must be set to identify which special EventDefinition.
|
||||
|
||||
### 2. Create EventOccurrenceConfiguration
|
||||
- **File**: `Data/Configurations/EventOccurrenceConfiguration.cs`
|
||||
- Configure primary key (Id)
|
||||
- Configure EventDefinitionId as foreign key (optional/nullable)
|
||||
- Configure indexes on StartTime, EventDefinitionId, SpecialEventType
|
||||
- Set property constraints (max lengths, required fields)
|
||||
- Add check constraint or validation: Either EventDefinitionId OR SpecialEventType must be set (not both, not neither)
|
||||
|
||||
### 3. Update AppDbContext
|
||||
- **File**: `Data/AppDbContext.cs`
|
||||
- Add `DbSet<EventOccurrence> EventOccurrences { get; set; }`
|
||||
|
||||
### 4. Create Migration
|
||||
- Generate migration for EventOccurrence table
|
||||
|
||||
## Parser Service Enhancement
|
||||
|
||||
### 5. Create Parser Service Interface
|
||||
- **File**: `Core/Services/IEventOccurrenceParserService.cs`
|
||||
- Method: `ParseFromText(string text, ICollection<EventDefinition> events)` returns `ParseResult`
|
||||
- ParseResult contains: Dictionary of occurrences, List of parsing errors/warnings
|
||||
|
||||
### 6. Create ParseResult Model
|
||||
- **File**: `Core/Models/EventOccurrenceParseResult.cs`
|
||||
- Properties:
|
||||
- `IDictionary<EventDefinition, List<EventOccurrence>> Occurrences`
|
||||
- `List<string> Errors`
|
||||
- `List<string> Warnings`
|
||||
- `int TotalParsed`
|
||||
|
||||
### 7. Adapt EventOccurrenceParser
|
||||
- **File**: `Core/Parsers/EventOccurrenceParser.cs` (modify existing or create wrapper)
|
||||
- Add method `ParseFromText(string text, ICollection<EventDefinition> events)` that:
|
||||
- Creates temporary file from text
|
||||
- Uses existing Parse() logic which already handles GeneralSchedule and VotingDelegates via EventDefinition.GeneralSchedule and EventDefinition.VotingDelegates
|
||||
- When parsing returns GeneralSchedule or VotingDelegates EventDefinitions:
|
||||
- Set EventOccurrence.EventDefinitionId to null
|
||||
- Set EventOccurrence.SpecialEventType to "GeneralSchedule" or "VotingDelegates"
|
||||
- Collects parsing errors (lines that don't match, unmatched event definitions, etc.)
|
||||
- Returns ParseResult
|
||||
|
||||
## Import Page
|
||||
|
||||
### 8. Create Import Page
|
||||
- **File**: `WebApp/Components/Features/Calendar/Import.razor`
|
||||
- Route: `/calendar/event-occurrences/import`
|
||||
- Layout: Split view (MudGrid with 2 columns)
|
||||
- Left Column:
|
||||
- MudTextField (multiline) for pasting text
|
||||
- "Parse" button
|
||||
- Clear button
|
||||
- Right Column:
|
||||
- Parsed results list (MudTable or MudList)
|
||||
- Display occurrence details (Name, Date, Time, Location, EventDefinition)
|
||||
- Show errors/warnings in MudAlert components (including warnings for General Schedule/Voting Delegates lines)
|
||||
- "Save to Database" button (only enabled if parsing successful)
|
||||
- Code-behind:
|
||||
- State management for parsed text
|
||||
- Call parser service on Parse button click
|
||||
- Display results and errors
|
||||
- Save parsed occurrences to database
|
||||
|
||||
## CRUD Pages
|
||||
|
||||
### 9. Create Index Page
|
||||
- **File**: `WebApp/Components/Features/Calendar/Index.razor`
|
||||
- Route: `/calendar/event-occurrences`
|
||||
- Features:
|
||||
- MudDataGrid displaying EventOccurrences
|
||||
- Filter toggle/buttons: "Future", "Historic", "All" (default: Future)
|
||||
- Columns: Name, EventType (displays EventDefinition.Name if EventDefinitionId is set, otherwise SpecialEventType), StartTime, EndTime, Location
|
||||
- Action buttons: Create, Edit, Delete
|
||||
- Link to Import page
|
||||
- Server-side filtering based on StartTime vs DateTime.Now
|
||||
- Include EventDefinition navigation property (nullable)
|
||||
- Display logic: Show EventDefinition.Name if EventDefinitionId is set, otherwise show SpecialEventType
|
||||
|
||||
### 10. Create Service Interface and Implementation
|
||||
- **File**: `Core/Services/IEventOccurrenceService.cs`
|
||||
- **File**: `WebApp/Services/EventOccurrenceService.cs` (update existing)
|
||||
- Methods:
|
||||
- `GetAllAsync()` - Get all occurrences
|
||||
- `GetFutureAsync()` - Get occurrences with StartTime >= today
|
||||
- `GetHistoricAsync()` - Get occurrences with StartTime < today
|
||||
- `GetByIdAsync(int id)` - Get single occurrence
|
||||
- `CreateAsync(EventOccurrence occurrence)` - Create new
|
||||
- `UpdateAsync(EventOccurrence occurrence)` - Update existing
|
||||
- `DeleteAsync(int id)` - Delete
|
||||
|
||||
### 11. Create Create Page
|
||||
- **File**: `WebApp/Components/Features/Calendar/Create.razor`
|
||||
- Route: `/calendar/event-occurrences/create`
|
||||
- Form fields:
|
||||
- Name (required)
|
||||
- Event Type selection (radio or segmented control):
|
||||
- Option 1: "Regular Event" - shows EventDefinition dropdown (required)
|
||||
- Option 2: "Special Event" - shows SpecialEventType dropdown with "GeneralSchedule" and "VotingDelegates" (required)
|
||||
- StartTime (DateTime picker)
|
||||
- EndTime (DateTime picker, optional)
|
||||
- Location (string, optional)
|
||||
- Validation: Either EventDefinitionId OR SpecialEventType must be set (not both, not neither)
|
||||
- Save logic
|
||||
|
||||
### 12. Create Edit Page
|
||||
- **File**: `WebApp/Components/Features/Calendar/Edit.razor`
|
||||
- Route: `/calendar/event-occurrences/edit/{id}`
|
||||
- Similar form to Create page
|
||||
- Load existing occurrence data
|
||||
- Update logic
|
||||
|
||||
### 13. Create Delete Confirmation
|
||||
- Use MudBlazor DialogService for delete confirmation
|
||||
- Implement delete logic in service and Index page
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### Special Event Definition Handling
|
||||
- `EventDefinition.GeneralSchedule` and `EventDefinition.VotingDelegates` are static instances (not stored in database)
|
||||
- When EventOccurrence references GeneralSchedule or VotingDelegates:
|
||||
- Set `EventDefinitionId` to null
|
||||
- Set `SpecialEventType` to "GeneralSchedule" or "VotingDelegates"
|
||||
- When EventOccurrence references a regular EventDefinition:
|
||||
- Set `EventDefinitionId` to the EventDefinition.Id
|
||||
- Set `SpecialEventType` to null
|
||||
- Validation: Exactly one of EventDefinitionId or SpecialEventType must be set (mutually exclusive)
|
||||
- In UI display: Show EventDefinition.Name if EventDefinitionId is set, otherwise show SpecialEventType value
|
||||
|
||||
### Parsing Error Collection
|
||||
- Track lines that don't match regex pattern
|
||||
- Track occurrences without a matching EventDefinition
|
||||
- Track parsing errors (date parsing failures, time parsing failures)
|
||||
- Display all errors clearly to user before allowing save
|
||||
|
||||
### Date/Time Handling
|
||||
- Ensure consistent DateTime handling across timezones
|
||||
- Store as UTC or local time consistently (check existing patterns)
|
||||
- Display in user-friendly format
|
||||
|
||||
## Files to Create/Modify
|
||||
|
||||
**New Files:**
|
||||
1. `Core/Models/EventOccurrenceParseResult.cs`
|
||||
2. `Core/Services/IEventOccurrenceParserService.cs`
|
||||
3. `Core/Services/EventOccurrenceParserService.cs`
|
||||
4. `Data/Configurations/EventOccurrenceConfiguration.cs`
|
||||
5. `WebApp/Components/Features/Calendar/Import.razor`
|
||||
6. `WebApp/Components/Features/Calendar/Index.razor`
|
||||
7. `WebApp/Components/Features/Calendar/Create.razor`
|
||||
8. `WebApp/Components/Features/Calendar/Edit.razor`
|
||||
|
||||
**Modified Files:**
|
||||
1. `Core/Entities/EventOccurrence.cs` - Add Id, EventDefinitionId (nullable), SpecialEventType (nullable), navigation property
|
||||
2. `Data/AppDbContext.cs` - Add DbSet
|
||||
3. `WebApp/Services/EventOccurrenceService.cs` - Implement full CRUD operations, handle special event types in queries
|
||||
4. `Core/Parsers/EventOccurrenceParser.cs` - Add ParseFromText method (or create wrapper service), map GeneralSchedule/VotingDelegates EventDefinitions to SpecialEventType when creating EventOccurrences
|
||||
|
||||
Reference in New Issue
Block a user