Skip to content

feat(calendar): cascade-delete a board's events when the board is deleted#1003

Merged
renemadsen merged 9 commits into
stablefrom
feat/board-delete-cascade-events
Jun 12, 2026
Merged

feat(calendar): cascade-delete a board's events when the board is deleted#1003
renemadsen merged 9 commits into
stablefrom
feat/board-delete-cascade-events

Conversation

@renemadsen

Copy link
Copy Markdown
Member

Summary

Deleting a calendar board now cascade-deletes every event placed on that board, and the delete-confirmation dialog warns accurately (permanent deletion) with the event count. Previously DeleteBoard only soft-deleted the board, orphaning its events under a non-existent board.

Changes

  • Backend cascade (BackendConfigurationCalendarService.DeleteBoard): enumerates the board's events via CalendarConfiguration.BoardId and reuses the existing DeleteEntireSeries(arpId) per event (identical to a manual single-event delete), deleting the board last and aborting on the first event-delete failure so a partial failure leaves the board intact/recoverable. All soft-deletes (WorkflowState='Removed').
  • New read-only endpoint GET api/backend-configuration-pn/calendar/boards/{id}/event-count returning the distinct event count for the dialog.
  • Frontend: getBoardEventCount service method; the board-delete modal fetches the count and shows a permanent-deletion warning ("This will permanently delete the board and its N events. This cannot be undone."); Delete stays usable even if the count fetch errors; en/da translations added.

Tests

  • 4 NUnit/Testcontainers integration tests: count, cascade-with-delegation, other-boards-untouched, and abort-on-failure-leaves-board-intact. All passing locally.
  • A Playwright smoke spec was planned; not included here (blocked on local login during manual verification).

Notes

  • No new FK constraint added between CalendarConfiguration.BoardId and CalendarBoard (out of scope; cascade is explicit).
  • Spec + plan under docs/superpowers/.

🤖 Generated with Claude Code

renemadsen and others added 8 commits June 11, 2026 16:37
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…eted

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ails

Set countLoaded=true in the error callback of getBoardEventCount so that
a failed HTTP request does not permanently disable the Delete button.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 12, 2026 04:21

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the BackendConfiguration calendar board deletion flow so that deleting a calendar board also soft-deletes all event series placed on that board (via the existing per-series delete path), and adds a read-only API + UI wiring to show an event-count warning in the board delete confirmation dialog.

Changes:

  • Backend: DeleteBoard now enumerates distinct event series IDs on the board and calls DeleteEntireSeries for each before deleting the board; new GET .../boards/{id}/event-count endpoint added.
  • Frontend: calendar service adds getBoardEventCount; board-delete modal fetches the count and updates the dialog text; en/da translation keys added.
  • Tests/Docs: new integration tests for cascade + count; spec/plan documentation added.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
eFormAPI/Plugins/BackendConfiguration.Pn/BackendConfiguration.Pn/Services/BackendConfigurationCalendarService/IBackendConfigurationCalendarService.cs Adds service contract for board event-count lookup.
eFormAPI/Plugins/BackendConfiguration.Pn/BackendConfiguration.Pn/Services/BackendConfigurationCalendarService/BackendConfigurationCalendarService.cs Implements cascade delete in DeleteBoard and adds GetBoardEventCount.
eFormAPI/Plugins/BackendConfiguration.Pn/BackendConfiguration.Pn/Controllers/CalendarController.cs Exposes new GET boards/{id}/event-count endpoint.
eFormAPI/Plugins/BackendConfiguration.Pn/BackendConfiguration.Pn.Integration.Test/CalendarBoardDeleteCascadeTests.cs Adds integration coverage for count + cascade delete + abort-on-failure behavior.
eform-client/src/app/plugins/modules/backend-configuration-pn/services/backend-configuration-pn-calendar.service.ts Adds frontend API method to retrieve board event count.
eform-client/src/app/plugins/modules/backend-configuration-pn/modules/calendar/modals/board-delete-modal/board-delete-modal.component.ts Fetches event count on modal open for warning text.
eform-client/src/app/plugins/modules/backend-configuration-pn/modules/calendar/modals/board-delete-modal/board-delete-modal.component.html Updates confirmation copy to permanent deletion with count.
eform-client/src/app/plugins/modules/backend-configuration-pn/i18n/enUS.ts Adds translation entry for new warning string.
eform-client/src/app/plugins/modules/backend-configuration-pn/i18n/da.ts Adds Danish translation entry for new warning string.
docs/superpowers/specs/2026-06-11-board-delete-cascade-events-design.md Adds design spec for cascade-delete and count warning.
docs/superpowers/plans/2026-06-11-board-delete-cascade-events.md Adds implementation plan for backend/frontend/tests.

Comment on lines +3243 to +3263
public async Task<OperationDataResult<int>> GetBoardEventCount(int id)
{
try
{
var count = await backendConfigurationPnDbContext.CalendarConfigurations
.Where(x => x.WorkflowState != Constants.WorkflowStates.Removed)
.Where(x => x.BoardId == id)
.Select(x => x.AreaRulePlanningId)
.Distinct()
.CountAsync();

return new OperationDataResult<int>(true, count);
}
catch (Exception e)
{
SentrySdk.CaptureException(e);
logger.LogError(e, "BackendConfigurationCalendarService.GetBoardEventCount: {Message}", e.Message);
return new OperationDataResult<int>(false,
$"{localizationService.GetString("ErrorWhileReadingCalendarBoard")}: {e.Message}");
}
}
Comment on lines +15 to +37
export class BoardDeleteModalComponent implements OnInit {
eventCount = 0;
countLoaded = false;

constructor(
private dialogRef: MatDialogRef<BoardDeleteModalComponent>,
@Inject(MAT_DIALOG_DATA) public data: BoardDeleteModalData,
private calendarService: BackendConfigurationPnCalendarService,
) {}

ngOnInit() {
this.calendarService.getBoardEventCount(this.data.board.id).subscribe({
next: res => {
if (res && res.success) {
this.eventCount = res.model;
}
this.countLoaded = true;
},
error: () => {
this.countLoaded = true;
},
});
}
<p>{{ 'Are you sure you want to delete the board' | translate }} <strong>{{ data.board.name }}</strong>?</p>
<p>{{ 'All tasks associated with this board will lose their board association' | translate }}.</p>
<p>
{{ 'This will permanently delete the board and its {{count}} events. This cannot be undone.' | translate:{count: eventCount} }}
<div mat-dialog-actions class="d-flex flex-row justify-content-end">
<button class="btn-cancel" (click)="onCancel()">{{ 'Cancel' | translate }}</button>
<button class="btn-delete" (click)="onConfirm()">{{ 'Delete' | translate }}</button>
<button class="btn-delete" [disabled]="!countLoaded" (click)="onConfirm()">{{ 'Delete' | translate }}</button>
Comment on lines +23 to +24
[TestFixture]
public class CalendarBoardDeleteCascadeTests : TestBaseSetup
Comment on lines +5 to +7
using BackendConfiguration.Pn.Services.BackendConfigurationCalendarService;
using BackendConfiguration.Pn.Services.BackendConfigurationLocalizationService;
using BackendConfiguration.Pn.Services.BackendConfigurationTaskWizardService;
…ascade-events

# Conflicts:
#	eform-client/src/app/plugins/modules/backend-configuration-pn/i18n/da.ts
#	eform-client/src/app/plugins/modules/backend-configuration-pn/i18n/enUS.ts
@renemadsen renemadsen merged commit 3f1c4e0 into stable Jun 12, 2026
26 checks passed
@renemadsen renemadsen deleted the feat/board-delete-cascade-events branch June 12, 2026 04:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants