Skip to content

feat: add delete confirmation dialog to webhook list items#26305

Merged
romitg2 merged 27 commits intocalcom:mainfrom
KartikLabhshetwar:feat/webhook-delete-confirmation-dialog
Feb 5, 2026
Merged

feat: add delete confirmation dialog to webhook list items#26305
romitg2 merged 27 commits intocalcom:mainfrom
KartikLabhshetwar:feat/webhook-delete-confirmation-dialog

Conversation

@KartikLabhshetwar
Copy link
Copy Markdown
Contributor

@KartikLabhshetwar KartikLabhshetwar commented Dec 30, 2025

What does this PR do?

Visual Demo (For contributors especially)

Video Demo (if applicable):

before:

Screen.Recording.2025-12-30.at.4.05.09.PM.mov

after:

Screen.Recording.2025-12-30.at.4.05.31.PM.mov

Mandatory Tasks (DO NOT REMOVE)

  • I have self-reviewed the code (A decent size PR without self-review might be rejected).
  • I have updated the developer docs in /docs if this PR makes changes that would require a documentation change. If N/A, write N/A here and check the checkbox.
  • I confirm automated tests are in place that prove my fix is effective or that my feature works.

Summary by cubic

Adds a delete confirmation dialog to webhook list items (global and event-type) to prevent accidental deletions. Implements pending states, error handling, and data refresh; aligns with CAL-6996.

  • New Features
    • Use shared DeleteWebhookDialog in WebhookListItem and EventTypeWebhookListItem with localized copy.
    • Disable delete actions while the request is pending.
    • Close the dialog on success or error and show an error toast on failure.
    • Invalidate webhook and event type queries after delete to refresh the UI.

Written for commit 5b41fba. Summary will update on new commits.

@vercel
Copy link
Copy Markdown

vercel Bot commented Dec 30, 2025

@KartikLabhshetwar is attempting to deploy a commit to the cal Team on Vercel.

A member of the Team first needs to authorize it.

@graphite-app graphite-app Bot added the community Created by Linear-GitHub Sync label Dec 30, 2025
@github-actions github-actions Bot added the 🐛 bug Something isn't working label Dec 30, 2025
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

No issues found across 2 files

Copy link
Copy Markdown
Member

@dhairyashiil dhairyashiil left a comment

Choose a reason for hiding this comment

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

We should add the confirmation modal for event type webhook settings as well.

I can see {{appName}} in the confirmation message. Should we create a new message for each case or use a more generic message that covers both cases?

Please check existing confirmation dialog messages in the codebase and align with that pattern

@dhairyashiil dhairyashiil marked this pull request as draft December 30, 2025 10:59
@KartikLabhshetwar
Copy link
Copy Markdown
Contributor Author

KartikLabhshetwar commented Dec 30, 2025

We should add the confirmation modal for event type webhook settings as well.

I can see {{appName}} in the confirmation message. Should we create a new message for each case or use a more generic message that covers both cases?

Please check existing confirmation dialog messages in the codebase and align with that pattern

@dhairyashiil,

  1. i mean i have implemented confirmation dialog for event type webhook settings.
    The EventTypeWebhookListItem component (lines 162-180) already includes the confirmation dialog. This component is used in EventWebhooksTab.tsx (line 169), which is the event type webhook settings page. So the confirmation modal is already in place for event type webhook settings.

  2. The current generic message delete_webhook_confirmation_message is appropriate for both event type webhooks and general webhooks. The consequence is the same (no longer receiving meeting data), and the {{appName}} placeholder is just the app name, not context-specific. This aligns with the codebase pattern where single generic messages are used when consequences are the same (e.g., workflows, phone numbers), while different messages are used only when consequences differ significantly (e.g., managed vs regular event types).

refer code:

"delete_webhook_confirmation_message": "Are you sure you want to delete this webhook? You will no longer receive {{appName}} meeting data at a specified URL, in real-time, when an event is scheduled or canceled.",

@KartikLabhshetwar KartikLabhshetwar marked this pull request as ready for review December 30, 2025 11:11
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

No issues found across 2 files

@diffray-bot
Copy link
Copy Markdown

Changes Summary

This PR adds a confirmation dialog to webhook deletion actions in both global and event-type webhook list items to prevent accidental deletions. It implements proper error handling, loading states, and data invalidation after deletion.

Type: feature

Components Affected: WebhookListItem, EventTypeWebhookListItem

Files Changed
File Summary Change Impact
...ebhooks/components/EventTypeWebhookListItem.tsx Added confirmation dialog for webhook deletion with error handling and pending states ✏️ 🟡
...modules/webhooks/components/WebhookListItem.tsx Added confirmation dialog for webhook deletion with error handling and pending states ✏️ 🟡
Architecture Impact
  • New Patterns: Confirmation dialog pattern for destructive actions, State management for dialog visibility
  • Dependencies: added: useState hook from React, added: Dialog and ConfirmationDialogContent components
  • Coupling: Removed inline deletion logic in favor of dialog-based confirmation flow

Risk Areas: User experience during webhook deletion (requires extra confirmation step), Error handling ensures users are notified when deletion fails, Loading states prevent multiple simultaneous deletion attempts

Suggestions
  • Consider adding unit/integration tests to verify dialog behavior
  • Verify localization keys (delete_webhook, confirm_delete_webhook, delete_webhook_confirmation_message) exist in all supported languages
  • Ensure the isPending state properly disables buttons to prevent race conditions

Full review in progress... | Powered by diffray

Comment thread apps/web/modules/webhooks/components/EventTypeWebhookListItem.tsx
Comment thread apps/web/modules/webhooks/components/WebhookListItem.tsx
Comment thread apps/web/modules/webhooks/components/WebhookListItem.tsx
Comment thread apps/web/modules/webhooks/components/EventTypeWebhookListItem.tsx
Comment thread apps/web/modules/webhooks/components/EventTypeWebhookListItem.tsx
Comment thread apps/web/modules/webhooks/components/EventTypeWebhookListItem.tsx Outdated
Comment thread apps/web/modules/webhooks/components/EventTypeWebhookListItem.tsx
Comment thread apps/web/modules/webhooks/components/WebhookListItem.tsx
Comment thread apps/web/modules/webhooks/components/WebhookListItem.tsx Outdated
Comment thread apps/web/modules/webhooks/components/WebhookListItem.tsx
@diffray-bot
Copy link
Copy Markdown

Review Summary

Free public review - Want AI code reviews on your PRs? Check out diffray.ai

Validated 57 issues: 22 kept, 35 filtered

Issues Found: 22

💬 See 18 individual line comment(s) for details.

📊 12 unique issue type(s) across 22 location(s)

📋 Full issue list (click to expand)

🔴 CRITICAL - Switch onCheckedChange uses stale prop value instead of checked parameter

Agent: react

Category: bug

File: apps/web/modules/webhooks/components/EventTypeWebhookListItem.tsx:129-136

Description: The onCheckedChange callback ignores the 'checked' parameter and calculates new state from webhook.active prop. Combined with defaultChecked (uncontrolled), this causes incorrect toggle behavior when props/state diverge.

Suggestion: Change to use the checked parameter: onCheckedChange={(checked) => toggleWebhook.mutate({ id: webhook.id, active: checked, ... })}

Confidence: 95%

Rule: react_hooks_and_state_management


🟠 HIGH - Uncontrolled Switch with defaultChecked won't update on prop changes (2 occurrences)

Agent: react

Category: bug

📍 View all locations
File Description Suggestion Confidence
apps/web/modules/webhooks/components/EventTypeWebhookListItem.tsx:106-117 Switch uses defaultChecked={webhook.active} which only sets initial value on mount. If webhook.activ... Use controlled pattern: <Switch checked={webhook.active} .../> instead of defaultChecked 90%
apps/web/modules/webhooks/components/WebhookListItem.tsx:120-132 Switch uses defaultChecked={webhook.active} which only sets initial value on mount. If webhook.activ... Use controlled pattern: <Switch checked={webhook.active} .../> instead of defaultChecked 90%

Rule: react_stale_state_after_error


🟠 HIGH - New error handler lacks test coverage (6 occurrences)

Agent: testing

Category: quality

📍 View all locations
File Description Suggestion Confidence
apps/web/modules/webhooks/components/EventTypeWebhookListItem.tsx:45-60 An onError handler was added to the deleteWebhook mutation to handle failures and close the dialog, ... Create a test file at apps/web/modules/webhooks/components/tests/EventTypeWebhookListItem.test.t... 85%
apps/web/modules/webhooks/components/EventTypeWebhookListItem.tsx:162-180 A new confirmation dialog feature was added to prevent accidental deletions, but there are no tests ... Add test cases to verify:
  1. Clicking delete button opens the dialog
  2. Confirming in dialog trigger... | 85% |
    | apps/web/modules/webhooks/components/EventTypeWebhookListItem.tsx:132-134 | A disabled prop based on deleteWebhook.isPending was added to prevent multiple deletion requests. Th... | Add test cases:
  3. Verify delete button is enabled when deleteWebhook.isPending is false
  4. Verify d... | 75% |
    | apps/web/modules/webhooks/components/WebhookListItem.tsx:44-58 | An onError handler was added to the deleteWebhook mutation to handle failures and close the dialog, ... | Create a test file at apps/web/modules/webhooks/components/tests/WebhookListItem.test.tsx with t... | 85% |
    | apps/web/modules/webhooks/components/WebhookListItem.tsx:186-204 | A new confirmation dialog feature was added to prevent accidental deletions, but there are no tests ... | Add test cases to verify dialog open/close behavior, confirmation triggering deletion, and permissio... | 85% |
    | apps/web/modules/webhooks/components/WebhookListItem.tsx:150-152 | A disabled prop based on deleteWebhook.isPending was added to prevent multiple deletion requests. Th... | Add test cases to verify button disabled state during pending deletion. | 75% |

Rule: test_new_parameter_coverage


🟡 MEDIUM - Error callback discards error context for debugging

Agent: react

Category: quality

File: apps/web/modules/webhooks/components/EventTypeWebhookListItem.tsx:56-59

Description: The onError callback in the deleteWebhook mutation receives an error parameter but doesn't use it. This loses critical debugging context when webhook deletion fails.

Suggestion: Accept the error parameter and log it: onError(error) { console.error('Failed to delete webhook', { webhookId: webhook.id, error }); showToast(t('something_went_wrong'), 'error'); setDeleteDialogOpen(false); }

Confidence: 75%

Rule: ts_include_error_context_in_structured_logs


🟡 MEDIUM - Error not logged in error handler

Agent: react

Category: quality

File: apps/web/modules/webhooks/components/WebhookListItem.tsx:54-57

Description: The onError callback handles the error by showing a generic toast message to the user but doesn't log the actual error details. This makes debugging production issues difficult.

Suggestion: Add error logging before showing the user-facing toast: onError(error) { console.error('Failed to delete webhook:', { webhookId: webhook.id, error }); showToast(t('something_went_wrong'), 'error'); setDeleteDialogOpen(false); }

Confidence: 75%

Rule: ts_log_errors_instead_of_failing_silently


🟡 MEDIUM - Potential undefined access on optional property canEditWebhook (2 occurrences)

Agent: bugs

Category: bug

📍 View all locations
File Description Suggestion Confidence
apps/web/modules/webhooks/components/WebhookListItem.tsx:72 The property props.permissions.canEditWebhook is optional but accessed without undefined guard. Wh... Add explicit undefined check: {props.permissions.canEditWebhook === false && ...} if the intent is... 70%
apps/web/modules/webhooks/components/WebhookListItem.tsx:123 The Switch component's disabled state checks !props.permissions.canEditWebhook without handling un... Use explicit comparison: disabled={props.permissions.canEditWebhook === false} if undefined should... 70%

Rule: bug_null_pointer


🟡 MEDIUM - Duplicated mutation success logic should be extracted (2 occurrences)

Agent: react

Category: quality

📍 View all locations
File Description Suggestion Confidence
apps/web/modules/webhooks/components/EventTypeWebhookListItem.tsx:47-68 Both deleteWebhook and toggleWebhook mutations contain identical cache invalidation calls. This viol... Extract common logic: `const invalidateWebhookCaches = async () => { await utils.viewer.webhook.getB... 70%
apps/web/modules/webhooks/components/WebhookListItem.tsx:44-68 Both deleteWebhook and toggleWebhook mutations contain identical cache invalidation and revalidation... Extract common logic: `const invalidateWebhookCaches = async () => { if (webhook.eventTypeId) revali... 70%

Rule: ts_extract_duplicated_logic_into_functions


🔵 LOW - Missing error handler for toggleWebhook mutation (2 occurrences)

Agent: quality

Category: quality

📍 View all locations
File Description Suggestion Confidence
apps/web/modules/webhooks/components/EventTypeWebhookListItem.tsx:61-69 toggleWebhook has onSuccess but no onError handler. The deleteWebhook mutation (line 56-59) does hav... Add onError handler: onError() { showToast(t('something_went_wrong'), 'error'); } - matching the p... 75%
apps/web/modules/webhooks/components/WebhookListItem.tsx:59-68 toggleWebhook has onSuccess but no onError handler. The deleteWebhook mutation (line 54-57) does hav... Add onError handler: onError() { showToast(t('something_went_wrong'), 'error'); } - matching the p... 75%

Rule: quality_missing_project_pattern


🔵 LOW - Unused prop parameter

Agent: refactoring

Category: quality

File: apps/web/modules/webhooks/components/WebhookListItem.tsx:39

Description: The prop 'canEditWebhook' is declared in the component props but never read. The code uses permissions.canEditWebhook instead throughout the component.

Suggestion: Remove the unused 'canEditWebhook' prop from the props interface since it's not used anywhere in the component.

Confidence: 92%

Rule: quality_unused_variable


🔵 LOW - Redundant double negation condition

Agent: refactoring

Category: quality

File: apps/web/modules/webhooks/components/EventTypeWebhookListItem.tsx:73

Description: Using '!!props.readOnly' performs an unnecessary double negation. Since the Badge is only rendered when readOnly is truthy, a simple truthy check would be more idiomatic.

Suggestion: Replace '!!props.readOnly' with 'props.readOnly' in the conditional rendering.

Confidence: 75%

Rule: quality_redundant_condition


🔵 LOW - Incomplete destructuring of props parameter (2 occurrences)

Agent: react

Category: quality

📍 View all locations
File Description Suggestion Confidence
apps/web/modules/webhooks/components/EventTypeWebhookListItem.tsx:42-47 Only webhook is destructured while readOnly, lastItem, and onEditWebhook are accessed via dot notati... Destructure all frequently accessed props at the top of the component: `const { webhook, onEditWebho... 60%
apps/web/modules/webhooks/components/WebhookListItem.tsx:39-49 Only webhook is destructured while permissions, lastItem, and onEditWebhook are accessed via dot not... Destructure all frequently accessed props at the top of the component for better readability. 60%

Rule: ts_use_destructuring_for_function_parameter


🔵 LOW - Line exceeds 100 characters

Agent: react

Category: style

File: apps/web/modules/webhooks/components/WebhookListItem.tsx:95

Description: This line contains approximately 115 characters, which may reduce readability in code review tools and split-pane editors.

Suggestion: Break the line at a logical point, such as: 'content={t("webhook_version_docs", {
version: getWebhookVersionLabel(webhook.version)
})}'

Confidence: 60%

Rule: ts_limit_lines_to_80_characters


ℹ️ 4 issue(s) outside PR diff (click to expand)

These issues were found in lines not modified in this PR.

🟠 HIGH - Uncontrolled Switch with defaultChecked won't update on prop changes (2 occurrences)

Agent: react

Category: bug

📍 View all locations
File Description Suggestion Confidence
apps/web/modules/webhooks/components/EventTypeWebhookListItem.tsx:106-117 Switch uses defaultChecked={webhook.active} which only sets initial value on mount. If webhook.activ... Use controlled pattern: <Switch checked={webhook.active} .../> instead of defaultChecked 90%
apps/web/modules/webhooks/components/WebhookListItem.tsx:120-132 Switch uses defaultChecked={webhook.active} which only sets initial value on mount. If webhook.activ... Use controlled pattern: <Switch checked={webhook.active} .../> instead of defaultChecked 90%

Rule: react_stale_state_after_error


🟡 MEDIUM - Potential undefined access on optional property canEditWebhook

Agent: bugs

Category: bug

File: apps/web/modules/webhooks/components/WebhookListItem.tsx:123

Description: The Switch component's disabled state checks !props.permissions.canEditWebhook without handling undefined. When undefined, this evaluates to true, disabling the switch when permissions are not defined.

Suggestion: Use explicit comparison: disabled={props.permissions.canEditWebhook === false} if undefined should allow editing

Confidence: 70%

Rule: bug_null_pointer


🔵 LOW - Line exceeds 100 characters

Agent: react

Category: style

File: apps/web/modules/webhooks/components/WebhookListItem.tsx:95

Description: This line contains approximately 115 characters, which may reduce readability in code review tools and split-pane editors.

Suggestion: Break the line at a logical point, such as: 'content={t("webhook_version_docs", {
version: getWebhookVersionLabel(webhook.version)
})}'

Confidence: 60%

Rule: ts_limit_lines_to_80_characters



Review ID: 78c4b3a1-569f-4e3a-b537-8a170729bd7b
Rate it 👍 or 👎 to improve future reviews | Powered by diffray

@KartikLabhshetwar
Copy link
Copy Markdown
Contributor Author

hi @dhairyashiil can you please see the comments?

Copy link
Copy Markdown
Member

@romitg2 romitg2 left a comment

Choose a reason for hiding this comment

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

@KartikLabhshetwar Thanks for the PR! can you please resolve merge conflicts?

(making it draft until then, feel free reopen)

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Feb 4, 2026

Devin AI is resolving merge conflicts

This PR has merge conflicts with the main branch. A Devin session has been created to automatically resolve them.

View Devin Session

Devin will:

  1. Merge the latest main into this branch
  2. Resolve any conflicts intelligently
  3. Run lint/type checks to ensure validity
  4. Push the resolved changes

If you prefer to resolve conflicts manually, you can close the Devin session and handle it yourself.

@romitg2
Copy link
Copy Markdown
Member

romitg2 commented Feb 4, 2026

@cubic-bot-ai

@pull-request-size pull-request-size Bot added size/L and removed size/M labels Feb 4, 2026
@romitg2 romitg2 added ready-for-e2e run-ci Approve CI to run for external contributors labels Feb 4, 2026
@romitg2
Copy link
Copy Markdown
Member

romitg2 commented Feb 4, 2026

@cubic-dev-ai

@cubic-dev-ai
Copy link
Copy Markdown
Contributor

cubic-dev-ai Bot commented Feb 4, 2026

@cubic-dev-ai

@romitg2 I have started the AI code review. It will take a few minutes to complete.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 3 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="apps/web/playwright/webhook.e2e.ts">

<violation number="1" location="apps/web/playwright/webhook.e2e.ts:894">
P2: Rule violated: **E2E Tests Best Practices**

Avoid text locators in E2E tests; use a data-testid locator for the webhook item instead to comply with E2E Tests Best Practices.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread apps/web/playwright/webhook.e2e.ts Outdated
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

2 issues found across 4 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="apps/web/playwright/webhook.e2e.ts">

<violation number="1" location="apps/web/playwright/webhook.e2e.ts:891">
P2: Rule violated: **E2E Tests Best Practices**

Add expect(page).toHaveURL(...) after navigation so the test fails fast on unexpected redirects, as required by the E2E tests best practices.</violation>

<violation number="2" location="apps/web/playwright/webhook.e2e.ts:894">
P1: Rule violated: **E2E Tests Best Practices**

Avoid text locators in E2E tests; add a data-testid for the webhook item and use page.getByTestId instead per the E2E tests best practices.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread apps/web/playwright/webhook.e2e.ts Outdated
Comment thread apps/web/playwright/webhook.e2e.ts
@romitg2 romitg2 removed the run-ci Approve CI to run for external contributors label Feb 4, 2026
@romitg2 romitg2 enabled auto-merge (squash) February 4, 2026 23:01
@romitg2 romitg2 added the run-ci Approve CI to run for external contributors label Feb 4, 2026
romitg2
romitg2 previously approved these changes Feb 4, 2026
@romitg2 romitg2 added run-ci Approve CI to run for external contributors and removed run-ci Approve CI to run for external contributors labels Feb 4, 2026
@romitg2 romitg2 merged commit 9a5323b into calcom:main Feb 5, 2026
74 of 83 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🐛 bug Something isn't working community Created by Linear-GitHub Sync Low priority Created by Linear-GitHub Sync ready-for-e2e run-ci Approve CI to run for external contributors size/L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(webhooks): Add confirmation dialog and error handling for webhook deletion

6 participants