* feat: add tri-state UI settings pages and auto opt-in preference
TASK 5: Tri-state UI with ToggleGroup
- Create shared TeamOrgFeaturesSettings component
- Create user features settings page (features-view.tsx)
- Create team features settings page
- Create org features settings page
TASK 6: Add auto opt-in preference
- Add autoOptInExperimentalFeatures field to User and Team models
- Add migration for new fields
- Add TRPC endpoints for auto opt-in preference (using repository pattern)
- Add auto opt-in checkboxes to settings pages
Also adds i18n keys for feature opt-in UI.
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
refactor: rename autoOptInExperimentalFeatures to autoOptInFeatures
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
refactor: apply PBAC procedure pattern to featureOptIn router
- Create createTeamPbacProcedure for team-scoped endpoints
- Create createOrgPbacProcedure for organization-scoped endpoints
- Refactor all team/org endpoints to use the new PBAC procedures
- Significantly reduces boilerplate code for permission checks
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
add features pages
implement hooks
update style
update style
rename slug to featureId
show Features page on the side bar only if OPT_IN_FEATURES.length > 0
revert unncessary renaming
revert some changes
remove some changes
* fix repository usage
* test: add unit tests for PBAC utility procedures
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* feat: add 'disabled by organization' badge for Team Level Features page
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* a little clean up
* feat: add effectiveReason to computeEffectiveStateAcrossTeams for better UI feedback
- Update computeEffectiveStateAcrossTeams to return both enabled state and reason
- Add EffectiveStateReason type with 6 possible values
- Update FeatureOptInService to include effectiveReason in resolved state
- Simplify useUserFeatureOptIn.getBlockedWarning to use effectiveReason directly
- Add feature_no_explicit_enablement_warning translation
- Invalidate feature list when auto-opt-in setting changes in all hooks
* test: add tests for FeatureOptInService.listFeaturesForTeam and refactor router to use TeamRepository
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* make it clearer about auto opt in
* move hooks to apps/web/module
* fix
* fix: move types to packages/features/feature-opt-in, fix imports and test mocks
- Move types.ts from apps/web/modules/feature-opt-in/hooks to packages/features/feature-opt-in
- Update FeaturesSettings.tsx to import types from new location
- Update hooks to import types from @calcom/features/feature-opt-in/types
- Fix organization features-view import path (~/settings/organizations -> ~/ee/organizations)
- Fix PermissionCheckService mock in util.test.ts to use class syntax
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: add validation for team ID and remove isPublic from featureOptIn handler
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: resolve biome lint errors in feature-opt-in files
- Add explicit return types to functions and methods
- Replace ternary operators with if-else statements
- Replace forEach with for...of loops to avoid useIterableCallbackReturn
- Extract helper functions to reduce function complexity
- Add explicit type annotations to variables
- Move exports to end of file to satisfy useExportsLast rule
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: resolve type errors in featureOptIn router
- Replace ctx.organizationId with ctx.user.organization.id
- Add null checks for organizationId in org procedures
- Remove incorrect type annotation from featureOptInRouter
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor: address PR feedback on feature opt-in implementation
- Refactor createMutationCallbacks to useMutationCallbacks hook with useLocale internally
- Restore comment on featureOptIn prop in FeaturesSettings.tsx
- Revert getAllTeamIds helper, use ternary operator instead
- Use ctx.user.organizationId with proper guard clauses
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix type error
* feat: disable toggle when feature is blocked by higher level
- Add isBlockedByHigherLevel function to UseFeatureOptInResult interface
- Implement blocking detection for user level (org/team disabled)
- Implement blocking detection for team level (org disabled)
- Organization level never blocked (top level)
- Update FeaturesSettings to disable ToggleGroup when blocked
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* change order of toggle buttons
* feat: add policy field (permissive/strict) to feature opt-in config
- Add OptInFeaturePolicy type with 'permissive' and 'strict' modes
- Update computeEffectiveStateAcrossTeams to handle both policies:
- Permissive: user opt-in can activate; disables only win if ALL teams disable
- Strict: user opt-in alone not enough; ANY explicit disable blocks
- Add new EffectiveStateReason values for strict policy
- Update FeatureOptInService to read policy from config
- Add unit tests for all 9 policy scenarios from spec
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor: rewrite test file with scenario tables and make policy required
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix type
* fix types
* make policy required
* disable toggle group if blocked by higher level
* refactor: move PBAC procedures to packages/trpc/server/procedures
- Move util.ts to pbacProcedures.ts in procedures folder for better reusability
- Move util.test.ts to pbacProcedures.test.ts alongside the main file
- Update imports in _router.ts to use new location
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: remove redundant null checks in featureOptIn router
The createOrgPbacProcedure middleware already validates organizationId
and throws if null. Use non-null assertion (!) instead of redundant
runtime checks since the middleware guarantees the value exists.
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor: improve middleware typing to avoid non-null assertions
Remove explicit return type from createOrgPbacProcedure to let TypeScript
infer the extended context type. This allows handlers to use ctx.organizationId
directly (typed as number) instead of ctx.user.organizationId! assertions.
The middleware validates organizationId and adds it to the context, so
downstream handlers can safely access ctx.organizationId as a number.
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* feat(pbac): use featureOptIn permissions instead of generic team/org permissions
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* feat(pbac): add PBAC to team features page and pass canEdit to views
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: add effectiveReason to IFeatureOptInService and update listFeaturesForTeam interface
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: add feature_any_team_disabled to isUserBlockedByHigherLevel check
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: add strict-policy reasons to warning helper function
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
* Copy changes
* Move search bar inline with new button
* Get rid of no more results message
* Change hidden badge to (hidden)
* Remove Cal.ai badge from sidebar
* Add dropdown to create button when there is multiple options
* Fix delete dialog
* Saved filters updates
* More string fixes
* Switch members table to use names
* Fix member spacing
* Fix routing form identifier field
* Fix routing forms stuff
* Only show SMS hint on SMS options
* Make workflow delete button minimal
* Fix padding on workflow steps
* Remove min width on workflow title
* Fix delete workflow PR
* Fix org profile buttons
* Fix org profile screen partially scrolled down
* Improve logos & banner uploads
* Personal profile fixes
* Fix settings general view stuff
* Sentence case consistency
* Fix stuff I broke
* Fix fab
* Fix hidden translation string
* Fix text fields
* Make button small for solo users too
* fix: update E2E tests to match sentence case labels in routing forms
* fix: update tests to match sentence case label changes
- insights.e2e.ts: chart titles (14 strings)
- event-types.e2e.ts: Organizer phone number location
- EditLocationDialog.test.tsx: phone number labels
* fix: address Cubic AI review feedback (confidence 9+)
- Replace hardcoded text-gray-500 with text-muted in TextField.tsx hint section
- Replace text locator with data-testid in E2E test for location select
Co-Authored-By: unknown <>
* fix: update E2E tests for sentence case label changes
- Use data-testid selectors for location options (more reliable than text)
- Update field identifiers in routing-forms tests to match new labels
- Fix Long text selector in manage-booking-questions test
* fix: replace text locator with data-testid in manage-booking-questions E2E test
Replace fragile text="Long text" locator with resilient
page.getByTestId("select-option-textarea") selector per E2E best practices.
Addresses Cubic AI review feedback (confidence 9/10).
Co-Authored-By: unknown <>
* fix: use .last() for multiple location select items
---------
Co-authored-by: Pedro Castro <pedro@cal.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: remove @calcom/web imports from packages/features to eliminate circular dependency
- Migrate UserTableUser and MemberPermissions types to packages/features/users/types/user-table.ts
- Migrate useGeo hook to packages/features/geo/GeoContext.tsx
- Migrate buildLegacyRequest to packages/lib/buildLegacyCtx.ts
- Migrate Calendar component to packages/features/calendars/weeklyview/components/
- Move test utilities (bookingScenario, fixtures) to packages/features/test/
- Update all imports in packages/features to use new locations
- Add re-exports in apps/web for backward compatibility
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: delete original implementation files and fix type issues
- Delete original calendar component files in apps/web (keep only re-export stubs)
- Migrate OutOfOfficeInSlots to packages/features/bookings/components
- Convert apps/web OutOfOfficeInSlots to re-export stub
- Fix className vs class issue in Calendar.tsx
- Fix @calcom/trpc import violation in user-table.ts by using structural type
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: add missing isGroup and contains fields to UserTableUser attributes type
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: update customRole type to match actual Prisma Role model
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix build
* fix
* fix
* cleanup weeklyview
* fix
* refactor to mv MemberPermissions to types package
* add types dependency to features
* fix
* fix
* fix
* fix
* fix
* fix
* rename
* rename
* migrate
* migrate
* migrate
* fix
* fix
* fix
* refactor: move test utilities from packages/features/test to tests/libs
- Move bookingScenario utilities to tests/libs/bookingScenario
- Move fixtures to tests/libs/fixtures
- Update all imports in packages/features test files to use new location
- Update all imports in apps/web test files to use new location
- Eliminates duplication of test utilities between packages/features and apps/web
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: correct relative import paths for tests/libs in test files
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* refactor: replace test utility implementations with re-exports to tests/libs
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: fix test import paths and move signup handler tests to apps/web
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: move buildLegacyCtx to packages/lib and restore handlers to packages/features
- Move buildLegacyCtx from apps/web/lib to packages/lib to break circular dependency
- Update apps/web/lib/buildLegacyCtx.ts to re-export from @calcom/lib
- Restore signup handlers and tests to packages/features/auth/signup/handlers
- Update handler imports to use @calcom/lib/buildLegacyCtx instead of @calcom/web/lib/buildLegacyCtx
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: update recurring-event.test.ts imports to use tests/libs path
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* refactor: delete test re-export files and update imports to use tests/libs directly
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: update remaining test imports to use tests/libs directly
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: update handleRecurringEventBooking calls to match function signature (1 arg)
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* remove
* migrate tests
* migrate tests
* refactor: update test mock imports by removing and using async for mock creators.
* fix type errors
* fix: add type assertion for MockUser in p2002.test-suite.ts
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: restore locale import in compareReminderBodyToTemplate.test.ts using relative path
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* feat: create @calcom/testing package and migrate tests from /tests directory
- Created new @calcom/testing package in /packages/testing
- Moved all files from /tests to /packages/testing
- Updated all imports across the codebase to use @calcom/testing alias
- Removed /tests directory at root level
This allows other packages like @calcom/features and @calcom/web to import
testing utilities using the @calcom/testing alias instead of relative paths.
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix
* fix
* fix: add missing useBookings export to @calcom/atoms package
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: add missing useCalendarsBusyTimes and useConnectedCalendars exports to @calcom/atoms
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* chore: add @calcom/testing as explicit devDependency to packages that use it
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* refactor: move setupVitest.ts into @calcom/testing package
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix
* chore: add biome rules to restrict @calcom/testing imports
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix
* rename libs to lib
* rename libs to lib
* add rule
* add rule
* refactor: remove @calcom/features imports from @calcom/testing
- Move mockPaymentSuccessWebhookFromStripe to fresh-booking.test.ts
- Replace ProfileRepository.generateProfileUid() with uuidv4()
- Clone Tracking type into @calcom/testing/src/lib/types.ts
- Update imports in expects.ts and getMockRequestDataForBooking.ts
- Move source files into src/ folder
- Move CalendarManager mock to @calcom/features
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: add explicit exports for nested paths in @calcom/testing
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* improve
* improve
* fix
* fix
* fix type checks
* fix type checks
* fix type checks
* fix tests
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: consistent button sizing between fab and button variants on desktop
* fix: consistent button sizing between fab and button variants on desktop
* fix(ui): align New button sizing across pages
* fix: New button sizing inconsistent between Workflows and Event Types pages
* Update Button.tsx
2026-01-06 03:08:20 +00:00
Benny JooGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- Exclude 'link' toolbar item from Editor for all workflow actions (not just SMS)
- Add replaceCloakedLinksInHtml utility to sanitize HTML and replace cloaked links with visible URLs
- Apply sanitization to email content before sending in all workflow email paths
This ensures recipients can see the actual destination of URLs, helping them identify potentially malicious links.
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* refactor: migrate UnconfirmedBookingBadge from features to apps/web
Move UnconfirmedBookingBadge.tsx from packages/features/bookings/ to
apps/web/modules/bookings/components/ as part of the architectural
refactor to remove trpc client imports from the features layer.
Also removes unused preserveBookingsQueryParams function from Navigation.tsx.
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* refactor: move shell navigation and badges to apps/web
Move shell navigation components and trpc-using badges from
packages/features to apps/web/modules to fix circular dependency:
- Move navigation folder to apps/web/modules/shell/navigation/
- Move TeamInviteBadge.tsx to apps/web/modules/shell/
- Create Shell wrapper in apps/web that provides MobileNavigationContainer
- Update all Shell imports in apps/web to use the new wrapper
- Remove MobileNavigationContainer default from features Shell.tsx
- Fix pre-existing lint warnings in touched files
This establishes the pattern for migrating React components that use
trpc hooks from the features layer to the web app layer, ensuring
proper dependency direction: apps/web imports from packages/features,
never the reverse.
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: move SideBar.tsx to apps/web to fix build error
SideBar.tsx was importing Navigation from the moved navigation folder,
causing a build error. Moving SideBar.tsx to apps/web and updating the
features Shell to not have a default SidebarContainer fixes this.
The web Shell wrapper now provides both the default SidebarContainer
and MobileNavigationContainer, maintaining the injection pattern.
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* revert
* revert
* revert
* wip
* wip
* wip
* wip
* wip
* wip
* not used anywhere
* wip
* wip
* wip
* wip
* fix
* fix
* wip
* wip
* wip
* wip
* wip
* fix
* fix
* fix
* fix
* migrate
* migrate admin-adpi
* wip
* feat: migrate organization settings components from packages/features to apps/web/modules
- Migrate profile.tsx, appearance.tsx, general.tsx, privacy.tsx, guest-notifications.tsx, delegationCredential.tsx, other-team-members-view.tsx, other-team-profile-view.tsx
- Migrate attributes directory (AttributesForm.tsx, DeleteAttributeModal.tsx, ListSkeleton.tsx, attributes-create-view.tsx, attributes-edit-view.tsx, attributes-list-view.tsx)
- Migrate admin directory (AdminOrgEditPage.tsx, AdminOrgPage.tsx, WorkspacePlatformPage.tsx)
- Update all page imports to use new paths from ~/settings/organizations/
- Update relative imports in migrated files to use @calcom/features paths
- Fix lint warnings in migrated files
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: update test import path after migration
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: remove unnecessary test-setup import (already in vitest config)
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* wip
* refactor: delete original files after migration to apps/web/modules
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* fix
* fix
* fix
* fix
* wip
* refactor more
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* mv
* update import paths
* wip
* wip
* fix
* fix
* fix
* fix
* fix
* fix
* fix
* mv
* mv
* mv
* fix
* wip
* wip
* fix
* fix
* fix
* fix: make test mocks resilient to vi.resetAllMocks()
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: fix AttributeForm test failures
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix
* fix
* refactor: move ee files to apps/web/modules/ee/ folder
- Move teams, workflows, and organizations folders to apps/web/modules/ee/
- Add LICENSE file to apps/web/modules/ee/
- Update all import paths from ~/teams/ to ~/ee/teams/
- Update all import paths from ~/settings/organizations/ to ~/ee/organizations/
- Remove duplicate MemberInvitationModal copy.tsx file
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: move useHasPaidPlan and dependent files to apps/web/modules
- Move useHasPaidPlan.ts from packages/features/billing/hooks to apps/web/modules/billing/hooks
- Move intercom files from packages/features/ee/support to apps/web/modules/ee/support
- Move ContactMenuItem.tsx and dependencies (freshchat, helpscout, zendesk) to apps/web/modules/ee/support
- Move ViewRecordingsDialog.tsx and RecordingListSkeleton to apps/web/modules/ee/video
- Move CalVideoSettings.tsx to apps/web/modules/eventtypes/components/locations
- Move CreateOrEditOutOfOfficeModal.tsx to apps/web/modules/settings/outOfOffice
- Refactor UpgradeTeamsBadge to accept props and create wrapper in apps/web/modules/billing
- Update all callers to use new file locations
- Add eslint-disable comments for pre-existing lint warnings
This fixes the tRPC server build failure caused by circular dependency where
the server build was traversing into packages/features and pulling in React
hooks that depend on @calcom/trpc/react types.
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: correct UpgradeTeamsBadge import path to use package export
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* fix
* fix
* fix
* fix
* fix
* fix
* fix
* fix: pass plan state through SelectProps to UpgradeTeamsBadge
- Add upgradeTeamsBadgeProps field to ExtendedOption type in Select component
- Update OptionComponent to spread upgradeTeamsBadgeProps to UpgradeTeamsBadge
- Update getOptions.ts to accept PlanState object and include upgradeTeamsBadgeProps
- Update WorkflowStepContainer.tsx to pass planState to getWorkflowTriggerOptions/getWorkflowTemplateOptions
- Update WorkflowDetailsPage.tsx to pass upgradeTeamsBadgeProps in transformed action options
- Update AddActionDialog.tsx interface and mapping to include upgradeTeamsBadgeProps
- Add eslint-disable comments for pre-existing React Hook dependency warnings
This fixes the UpgradeTeamsBadge refactoring issue where the badge was always showing
'upgrade' text instead of the correct text based on plan state (trial_mode, inactive_team_plan, etc.)
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: update import paths to use /ee/ folder for workflows and organizations
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: update workflow component imports to use /ee/ folder
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: add missing types.ts for LocationInput.tsx
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: extract BookingRedirectForm type to shared location
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix
* wip
* wip
* fix: update BookingRedirectForm import to use local types file
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* wip
* fix
* fix
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>