* fix(form-builder): show default label when field label is only whitespace
* fix: add validation to ensure label is not empty or whitespace
* fix: enhance label validation to prevent empty or whitespace labels in FormBuilder
* fix: refactor label validation in FormBuilder to streamline whitespace checks
* chore: retrigger CI (flaky vitest worker shutdown)
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat: restore moveTeamToOrg admin endpoint for organization migration
- Add moveTeamToOrg and removeTeamFromOrg functions to orgMigration.ts
- Restore API endpoint at /api/orgMigration/moveTeamToOrg
- Restore admin UI page at /settings/admin/orgMigrations/moveTeamToOrg
- Add helper functions for team redirect management
- Support moving team members along with the team
This endpoint allows admins to migrate teams to organizations after org creation,
which is needed as a temporary solution until proper org admin permissions are implemented.
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* fix: move moveTeamToOrg to lib/orgMigration and fix redirect URL
- Move moveTeamToOrg and removeTeamFromOrg functions from playwright/lib to lib/orgMigration.ts
- Update API endpoint to import from lib/orgMigration instead of playwright/lib
- Fix redirect URL format: use / instead of /team/
- Fix import path: use ../playwright/lib/orgMigration instead of ./playwright/lib/orgMigration
- Rename unused _dbRemoveTeamFromOrg in playwright file to satisfy linter
- Remove duplicate functions from playwright/lib/orgMigration.ts
This fixes the Vercel deployment failure caused by importing from test-only directories
in production API routes, and corrects the redirect URL format to match the original implementation.
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* refactor: reuse existing createTeamsHandler for moveTeamToOrg endpoint
- Remove custom orgMigration.ts implementation
- Update API endpoint to call existing createTeamsHandler with org owner impersonation
- Remove moveMembers option from UI (always moves members by design)
- Fix Vercel deployment by removing playwright import from production code
- Use OrganizationRepository.adminFindById to fetch org owner
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* refactor: migrate moveTeamToOrg admin page and API to App Router
- Move admin page from pages/settings/admin/orgMigrations to app/(use-page-wrapper)/settings/(admin-layout)/admin/orgMigrations
- Convert API route from pages/api/orgMigration/moveTeamToOrg.ts to app/api/orgMigration/moveTeamToOrg/route.ts
- Create client view component in modules/settings/admin/org-migrations/
- Remove old pages directory files and getServerSideProps
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* fix: correct import paths for App Router compatibility
- Fix @calcom/lib/server to @calcom/lib/server/i18n for getTranslation
- Fix @calcom/ui barrel import to specific component paths
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* fix: use TFunction type for getFormSchema parameter
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* fix: use buildLegacyRequest for App Router session compatibility
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* Remove unused fn
* cleanup
* cleanup
* fix: ui
* fix: handle slug conflict error when moving team to organization
- Intercept Prisma P2002 unique constraint error when moving a team
- Convert to user-friendly CONFLICT error with clear message
- Add test case for slug conflict scenario
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* fix: use isPending instead of isLoading for tRPC mutation
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* fixes
* fix: remove PII (emails) from admin log statement
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* refactor: use instanceof pattern for Prisma error detection
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* fixes
* fix: use i18n key for slug conflict error message instead of hardcoded English string
Co-Authored-By: bot_apk <apk@cognition.ai>
* fix: narrow P2002 catch scope to only prisma.team.update call
Separates the try-catch for prisma.team.update (slug conflict) from
creditService.moveCreditsFromTeamToOrg to avoid misattributing credit
service P2002 errors as slug conflicts.
Co-Authored-By: bot_apk <apk@cognition.ai>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: bot_apk <apk@cognition.ai>
* fix: correct admin password banner message to require both password length and 2FA
The banner message incorrectly used 'or' implying only one condition was needed,
but the code requires BOTH a password of at least 15 characters AND 2FA enabled.
Updated the message to clearly state both requirements and added a hint that
users need to log out and log back in after updating their security settings.
Fixes#9527
Co-Authored-By: unknown <>
* fix: auto-sign-out INACTIVE_ADMIN users after enabling 2FA
When an INACTIVE_ADMIN user enables 2FA, automatically sign them out so
they can log back in with refreshed session role, dismissing the banner.
This matches the existing behavior for password changes.
Co-Authored-By: unknown <>
* feat: add dynamic admin banner message based on inactiveAdminReason
Co-Authored-By: unknown <>
* Remove and add various localization strings
* Update common.json
* Add cookie consent checkbox message and remove entries
* test: add unit tests for AdminPasswordBanner and inactiveAdminReason logic
Co-Authored-By: unknown <>
* fix: add expires field to session mock to fix type check
Co-Authored-By: unknown <>
* fix: wrap CALENDSO_ENCRYPTION_KEY mutations in try/finally to prevent env state leaks
Addresses Cubic AI review feedback (confidence 9/10): when a test fails
early, the CALENDSO_ENCRYPTION_KEY env var was not being restored, which
could leak state into subsequent tests. Wrapped the env mutation in
try/finally blocks to guarantee cleanup.
Co-Authored-By: bot_apk <apk@cognition.ai>
* fix: add missing 'expires' field to buildSession in AdminPasswordBanner test
The Session type requires 'expires' to be a string, but buildSession was
not providing it, causing a type error caught by CI type-check.
Co-Authored-By: bot_apk <apk@cognition.ai>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: bot_apk <apk@cognition.ai>
* feat: make source required on EventBusyDetails for Troubleshooter display
- Make source a required property on EventBusyDetails type
- Update LimitManager to accept and store source when adding busy times
- Add user-friendly source names for all busy time types:
- 'Booking Limit' for booking limit busy times
- 'Duration Limit' for duration limit busy times
- 'Team Booking Limit' for team booking limit busy times
- 'Buffer Time' for seated event buffer times
- 'Calendar' for external calendar busy times
- Ensure all entries in detailedBusyTimes have source set
- Cover includeManagedEventsInLimits and teamBookingLimits branches
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* feat: add limit value and unit metadata to busy time sources
- Include limit value and unit in source strings for Troubleshooter display
- Booking Limit: shows as 'Booking Limit: 5 per day'
- Duration Limit: shows as 'Duration Limit: 120 min per week'
- Team Booking Limit: shows as 'Team Booking Limit: 10 per month'
- Preserves existing calendar sources (e.g., 'google-calendar')
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* feat: enhance busy time management with new limit sources
- Introduced new limit sources for busy times, including event booking and duration limits, with user-friendly titles for display.
- Updated LimitManager to accept and store detailed busy time information, including title and source.
- Refactored busy time addition logic across various services to utilize the new structure, improving clarity and maintainability.
* fixes
* feat: conditionally include source and translate busy time titles
- Add withSource parameter to conditionally include/exclude source from response
- Translate busy time titles on frontend using useLocale hook
- Source is only included when withSource=true (for Troubleshooter display)
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* feat: enhance user availability service and busy time handling
- Updated LargeCalendar component to include event ID check for enabling busy times.
- Added translation for "busy" in common.json for better user experience.
- Refactored getUserAvailability service to include new method for fetching user availability with busy times from limits.
- Introduced parseLimits function to streamline booking and duration limit parsing.
- Improved error handling in user handler for better user feedback.
* refactor: remove unnecessary timeZone: undefined from addBusyTime calls
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* feat: add buffer_time and calendar translation keys for busy times
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* feat: add event source to calendar components and improve busy time handling
- Updated EventList component to include event source in data attributes for better tracking.
- Enhanced LargeCalendar component to pass event
* fix: add missing source property to Date Override calendar event
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* fix: use 'date-override' as source for Date Override calendar events
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* Avoid type assertion
* fix: pass both bookingLimits and durationLimits to getStartEndDateforLimitCheck (#27898)
* test: add unit tests for getUserAvailabilityIncludingBusyTimesFromLimits
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* fix: pass both bookingLimits and durationLimits to getStartEndDateforLimitCheck
- Fix bug where bookingLimits || durationLimits was passed as single param
- Skip getBusyTimesForLimitChecks when eventType has no limits
- Remove as never casts, use proper typing for mock dependencies
- Replace expect.any(String) with exact ISO date assertions
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* refactor: replace loose assertions with exact values in tests
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: address review feedback on busy time sources
- Fix t("busy") fallback to t("busy_time.busy") for correct translation lookup
- Add missing title property to buffer time entries for Troubleshooter display
- Use descriptive debug strings for buffer time source field
- Fix import ordering in LargeCalendar.tsx
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
Co-Authored-By: unknown <>
* fix: preserve pre-existing busyTimesFromLimitsBookings from initialData
Address review feedback from @hariombalhara (comment #30, #31):
- Initialize busyTimesFromLimitsBookings from initialData instead of []
to avoid silently overwriting pre-existing data with an empty array
- Use conditional spread to only include busyTimesFromLimitsBookings
when it has a value
- Add test verifying pre-existing busyTimesFromLimitsBookings is
preserved and passed through to _getUserAvailability
- Add test verifying busyTimesFromLimitsBookings is not passed when
there are no limits and no initialData bookings
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
Co-Authored-By: bot_apk <apk@cognition.ai>
* fix: pass fetched eventType to _getUserAvailability to avoid duplicate DB query
Addresses Devin Review comment r2863593564: the wrapper method fetches
eventType but wasn't passing it through, causing _getUserAvailability to
re-fetch the same eventType from the database.
Also adds a test verifying eventType is forwarded correctly.
Co-Authored-By: bot_apk <apk@cognition.ai>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
Co-authored-by: bot_apk <apk@cognition.ai>
* chore: pull coss ui
* refactor: migrate webhooks page to coss/ui components
Co-Authored-By: pasquale@cal.com <pasquale@cal.com>
* refactor: migrate CreateNewWebhookButton to coss/ui Menu components
Co-Authored-By: pasquale@cal.com <pasquale@cal.com>
* refactor: adjust CreateNewWebhookButton variant and align based on context
Co-Authored-By: pasquale@cal.com <pasquale@cal.com>
* feat(coss-ui): add list-item components and refactor WebhookListItem to use them
Co-Authored-By: pasquale@cal.com <pasquale@cal.com>
* refactor(webhooks): match prototype – remove docs link, flatten list, show user in item
Co-Authored-By: pasquale@cal.com <pasquale@cal.com>
* update css vars
* refactor(webhooks): migrate WebhookForm.tsx to coss-ui components
Co-Authored-By: pasquale@cal.com <pasquale@cal.com>
* fix(webhooks): add FormProvider for useFormContext in child components
Co-Authored-By: pasquale@cal.com <pasquale@cal.com>
* restore prev form
* swap form components
* mc
* use coss button everywhere
* fix ts errors
* refactor(webhooks): replace SettingsHeaderWithBackButton with coss-ui CardFrame in edit/new views
Co-Authored-By: pasquale@cal.com <pasquale@cal.com>
* refactor(webhooks): split into two CardFrames with Card/CardPanel
Co-Authored-By: pasquale@cal.com <pasquale@cal.com>
* refactor(webhooks): wrap WebhookTestDisclosure in Card/CardPanel
Co-Authored-By: pasquale@cal.com <pasquale@cal.com>
* refactor(webhooks): migrate WebhookTestDisclosure to coss-ui CardFrame
Co-Authored-By: pasquale@cal.com <pasquale@cal.com>
* mc
* mc
* refactor(webhooks): update skeletons to use coss-ui CardFrame pattern
Co-Authored-By: pasquale@cal.com <pasquale@cal.com>
* mc
* refactor(webhooks): improve new webhook skeleton to match actual UI layout
Co-Authored-By: pasquale@cal.com <pasquale@cal.com>
* imrpove form skeleton
* optimise card header
* refactor: improve base ui react-hook-form compatibility
* update string
* use coss ui alert dialog
* use coss toast
* feat(webhooks): add user filter to webhooks list
Co-Authored-By: pasquale@cal.com <pasquale@cal.com>
* fix(webhooks): resolve lint warnings in filter component
Co-Authored-By: pasquale@cal.com <pasquale@cal.com>
* refactor(webhooks): filter after new button, icon+badge only
Co-Authored-By: pasquale@cal.com <pasquale@cal.com>
* improve switch
* remove unneeded toast
* refactor(webhooks): enhance WebhooksFilter component with anchor reference
* mc
* fix(webhooks): update Switch component to use checked prop instead of defaultChecked
* fix(webhooks): prevent Suspense boundary error on webhook edit save
Co-Authored-By: pasquale@cal.com <pasquale@cal.com>
* fix(webhooks): add optimistic state for Switch toggle in WebhookListItem
Co-Authored-By: pasquale@cal.com <pasquale@cal.com>
* fix(webhooks): disable switch during pending mutation to prevent rapid-toggle race
Co-Authored-By: pasquale@cal.com <pasquale@cal.com>
* fix(webhooks): guard toggle with isPending check instead of disabled prop
Co-Authored-By: pasquale@cal.com <pasquale@cal.com>
* fix toggle
* mc
* mc
* fix(webhooks): navigate before revalidation to prevent Suspense re-suspension
Co-Authored-By: pasquale@cal.com <pasquale@cal.com>
* mc
* fix(webhooks): use render prop for Cancel button navigation
Co-Authored-By: pasquale@cal.com <pasquale@cal.com>
* fix(webhooks): simplify Cancel button with explicit conditional rendering
Co-Authored-By: pasquale@cal.com <pasquale@cal.com>
* fix(webhooks): sort list by id to prevent resorting on toggle
Co-Authored-By: pasquale@cal.com <pasquale@cal.com>
* mc
* mc
* show filter only if user is >1
* refactor(webhooks): move ListItem components to shared directory
* feat: reintroduce avatars
* remove unneeded translations
* remove unneeded useMemo
* add clickable +n badge
* mc
* mc
* add tooltips and docs link
* animated tooltips
* refactor(WebhookForm): replace hardcoded text with translation keys for better localization
* refactor(WebhookListItem): manage active state with useEffect and improve toggle error handling
* mc
* update toast position + re-pull coss ui components
* refactor: rename onEditWebhook to onEditWebhookAction to prevent warnings
* feat: enhance WebhookListItem with edit link and mobile support
* mc
* remove unneded component
* refactor: simplify webhook toggle logic in WebhookListItem component
* fix: update edit link logic in WebhookListItem and add editHref to webhooks-view
* wip
* feat: implement webhook version selection in WebhookForm
* update list item
* fix issue with delete button perrmission
* sort webhooks by ID in WebhooksList component
* mc
* refactor: enhance Webhook components with improved header and skeleton loading logic
* refactor: rename files for clarity
* display the edit button
* re-pull coss ui components
* fix ts error
* refactor: simplify permission checks in WebhookListItem component
* improve skeletons
* fix ts errors
* rename onEditWebhook
* fix: update SheetContent variant in ActiveUserBreakdown component
* fix e2e
* feat: add data-testid attribute to confirmation button in DeleteWebhookDialog
* remove unnecessary file
* refactor: allow passing the aria-label attribute to the button that removes a chip
* refactor: rename onEditWebhook to onEditWebhookAction to prevent warnings
* refactor: add webhook version select to event-type dialog and extract shared WebhookVersionCTA component
Co-Authored-By: pasquale@cal.com <pasqualevitiello@gmail.com>
* fix: restore toast notification on webhook toggle in event-types tab
Co-Authored-By: pasquale@cal.com <pasqualevitiello@gmail.com>
* implement the coss ui dialog
* refactor(webhooks): use shared WebhookListItem in event type tab and coss-ui Dialog
* remove unneeded lastItem prop
* re-pull coss ui components
* Merge remote-tracking branch 'origin/main' into style/improve-webhooks
Co-Authored-By: unknown <>
* refactor: extract AppHeader component and move page title outside CardFrame
Co-Authored-By: unknown <>
* refactor: show user header for every webhook group and remove CardFrame wrapper
Co-Authored-By: unknown <>
* fix: wrap each user webhook group in CardFrame with CardFrameHeader
Co-Authored-By: unknown <>
* fix: add dashed border to Empty state matching coss prototype
Co-Authored-By: unknown <>
* mc
* fix: only show New button in header when webhooks exist
Co-Authored-By: unknown <>
* refactor: move page title/description/back button out of CardFrame on new/edit webhook pages
Co-Authored-By: unknown <>
* refactor: render webhook form header outside flex-col gap wrapper
Co-Authored-By: unknown <>
* refactor: move header outside div wrapper in webhook form skeleton
Co-Authored-By: unknown <>
* mc
* skeleton improvements
* refactor: move AppHeader component to @coss/ui/shared/app-header
Co-Authored-By: unknown <>
* fix the webhook dialog on event-types settings
* make the webhook clickable for event types
* remove hardcoded string
---------
Co-authored-by: pasqualevitiello <pasqualevitiello@gmail.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: pasquale@cal.com <pasquale@cal.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: Keith Williams <keithwillcode@gmail.com>
2026-03-04 12:56:15 +00:00
Rajiv SahalGitHubunknown <>rajiv@cal.com <sahalrajiv6900@gmail.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: hide branding for teams
* fix: remove unused organizationId and username fields from profiles select
Addresses Cubic AI review feedback (confidence 9/10) to select only
the profile fields that are actually used. The organizationId and
username fields were fetched but never referenced in this function.
Co-Authored-By: unknown <>
* fix: unit tests
* fix: add prisma named export to test mock
Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>
* Add tests: packages/features/profile/lib/hideBranding.test.ts
Generated by Paragon from proposal for PR #27643
* chore: implement cubic feedback
* fix: merge conflicts
* fix: unit tests
* fixup
* refactor: implement DI pattern for event type service
* fix: atoms build
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat: workflow auto translation
* tests: add unit tests
* refactor: tests and workflow
* fix: type err
* fix: type err
* fix: remove redundant index on WorkflowStepTranslation
The @@index on [workflowStepId, field, targetLocale] duplicates the @@unique
constraint on the same columns. A unique index already provides efficient
lookups, so the separate @@index adds storage overhead and write latency
without benefit.
Addresses Cubic AI review feedback (confidence 9/10).
Co-Authored-By: unknown <>
* fix: correct locale mapping when translation API returns null
Map translations with their corresponding locales before filtering to
preserve correct locale-to-translation associations. Previously, filtering
out null translations would reindex the array, causing incorrect locale
mappings when any translation in the batch failed.
Also fixes pre-existing lint warnings:
- Move exports to end of file
- Add explicit return type to processTranslations
- Replace ternary with if-else for upsertMany selection
Co-Authored-By: udit@cal.com <udit222001@gmail.com>
* fix: address review feedback for workflow auto-translation
- Add change detection before creating translation tasks
- Rename userLocale to sourceLocale in task props for clarity
- Show source language in UI with new translation key
- Extract SUPPORTED_LOCALES to shared translationConstants.ts
- Fix locale mapping bug in translateEventTypeData.ts
- Add WhatsApp translation support
- Abstract translation lookup into shared translationLookup.ts helper
- Restore if-else readability for SCANNING_WORKFLOW_STEPS
Co-authored-by: Udit Takkar <udit.takkar@cal.com>
Co-Authored-By: unknown <>
* fix: update test to use sourceLocale instead of userLocale
Co-Authored-By: unknown <>
* refactor: feedback
* fix: handle first time
* fix: tests
* fix: tests
* fix: address Cubic AI review feedback (confidence 9/10 issues)
- WhatsApp translation: Apply variable substitution using getSMSMessageWithVariables
and clear contentSid when using translated body to ensure Twilio uses the
translated text instead of the original template
- update.handler.ts: Change sourceLocale assignment from ?? to || for consistency
with tasker payload behavior (line 481)
- ITranslationService.ts: Rename methods from plural to singular naming:
- getWorkflowStepTranslations -> getWorkflowStepTranslation
- getEventTypeTranslations -> getEventTypeTranslation
Updated all call sites and tests accordingly
Co-Authored-By: unknown <>
* fix: address Cubic AI review feedback (confidence 9/10+ issues)
- Fix getSMSMessageWithVariables to handle WHATSAPP_ATTENDEE action for
locale and timezone (confidence 9/10)
- Remove WhatsApp translation feature that set contentSid to undefined
since Twilio ignores body parameter for WhatsApp and requires
pre-approved Message Templates (confidence 10/10)
Co-Authored-By: unknown <>
* fix: translatio
* Add tests: packages/features/eventTypeTranslation/repositories/EventTypeTranslationRepository.test.ts
Generated by Paragon from proposal for PR #27087
* Add tests: packages/features/tasker/tasks/translateWorkflowStepData.test.ts
Generated by Paragon from proposal for PR #27087
* chore: nit
* chore: verfied atg
* fix: set sourceLocale for new steps, add shouldDirty to checkbox, remove spec docs
- Set sourceLocale fallback in addedSteps mapping to fix stale detection mismatch
- Add { shouldDirty: true } to autoTranslateEnabled checkbox onChange
- Remove specs/workflow-translation/ directory (planning docs, not for repo)
Co-authored-by: Udit Takkar <udit.07.takkar@gmail.com>
Co-Authored-By: unknown <>
* chore: add specs back
* fix: type error
* fix: type error
* fix: type err
* fix: tests
* refactor: feedback
* fix: type err
* refactor
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Udit Takkar <udit.takkar@cal.com>
Co-authored-by: Udit Takkar <udit.07.takkar@gmail.com>
* feat: add no users found fallback action for routing forms
- Add NoUsersFoundFallbackActionType enum with CustomPageMessage and ExternalRedirectUrl options
- Add noUsersFoundFallbackAction field to zodNonRouterRoute schema
- Add NoUsersFoundFallback UI component in RouteBuilder for configuring fallback action
- Update handleResponse to return noUsersFoundFallbackAction when no team members match
- Add i18n translation keys for new UI strings
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* refactor: change fallback to use same action options as main route
- Replace noUsersFoundFallbackAction with fallbackAction that has same structure as main action
- Add action dropdown and input fields to fallback attributes query builder section
- Support Event redirect, External URL, and Custom page options in fallback
- Remove separate NoUsersFoundFallback toggle component
- Update handleResponse to return fallbackAction
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: ensure fallbackAction type is always defined in onChange handlers
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: add guards for route.fallbackAction in onChange handlers
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: only return fallbackAction when no users are found
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* refactor: restructure fallback section to mirror main route structure
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: ensure backwards compatibility for existing routes with fallbackAttributesQueryValue
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: initialize fallbackAction with main event type for backwards compatibility
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: include fallbackAction in getRoutesToSave to persist changes
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: use fallbackAction in getRoutedUrl when no team members found
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: use i18n for fallback label and add tests for fallback action
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: do not trigger fallback action when CRM contact owner is found
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: prioritize fallbackAction over fallbackAttributesQueryValue
When a route has a fallbackAction configured, skip the
fallbackAttributesQueryValue to ensure the fallbackAction is triggered
when no team members are found. This maintains backwards compatibility
by only using fallbackAttributesQueryValue when fallbackAction is not set.
Also treats teamMemberIdsMatchingAttributeLogic being null (routing couldn't
run, e.g., missing orgId) the same as an empty array for the purpose of
triggering the fallbackAction.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: extract RouteActionSelector shared component for action selection UI
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: add i18n string for default custom page message
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* feat: add webhook trigger when routing form fallback route is hit
- Add ROUTING_FORM_FALLBACK_HIT to WebhookTriggerEvents enum in Prisma schema
- Add new trigger to routing-forms webhook triggers in constants
- Add translation string for the new webhook trigger
- Implement triggerFallbackWebhook function in formSubmissionUtils.ts
- Call webhook trigger from handleResponse.ts when fallback action is used
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: remove webhook object from error log to avoid exposing secrets
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* revert: remove webhook trigger changes (to be moved to separate PR)
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* feat: add webhook trigger when routing form fallback route is hit
- Add ROUTING_FORM_FALLBACK_HIT to WebhookTriggerEvents enum in Prisma schema
- Add new trigger to routing-forms webhook triggers in constants
- Add translation string for the new webhook trigger
- Implement triggerFallbackWebhook function in formSubmissionUtils.ts
- Call webhook trigger from handleResponse.ts when fallback action is used
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: remove webhook object from error log to avoid exposing secrets
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: add ROUTING_FORM_FALLBACK_HIT to PayloadBuilderFactory trigger mapping
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* style: apply biome formatting fixes
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: restore removed comments in RouteBuilder
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* chore: add prisma migration for ROUTING_FORM_FALLBACK_HIT enum value
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: add ROUTING_FORM_FALLBACK_HIT to FormTriggerEvents type union
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* test: add test coverage for triggerFallbackWebhook function
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* refactor: consolidate fallback webhook firing with form submission webhooks
Move ROUTING_FORM_FALLBACK_HIT webhooks into the same Promise.all() batch
as FORM_SUBMITTED / FORM_SUBMITTED_NO_EVENT, eliminating redundant
getWebhooks/getWebhookTargetEntity/getOrgIdFromMemberOrTeamId calls.
- Add fallbackAction parameter to _onFormSubmission and onSubmissionOfFormResponse
- Remove triggerFallbackWebhook function and all its usages/imports
- Move getFallbackAction() earlier in handleResponse.ts and pass result through
- Update all tests to verify batched webhook behavior
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* Add UI option for trigger
* feat: persist fallbackAction on queued form responses
When a routing form response is queued, the fallbackAction determined
during routing is now stored on the QueuedFormResponse record. When
the queued response is later converted to a real FormResponse, the
stored fallbackAction is passed to onSubmissionOfFormResponse so the
ROUTING_FORM_FALLBACK_HIT webhook fires correctly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: add coverage for fallbackAction in queued form response flow
Verify that fallbackAction is persisted when queuing and passed through
to onSubmissionOfFormResponse when the queued response is converted.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>