Commit Graph
724 Commits
Author SHA1 Message Date
Peer RichelsenGitHubpeer@cal.com <peer@cal.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
6f7c8bdd73 feat: add wrong assignment report dialog and webhook for routing form bookings (#25839)
Co-authored-by: peer@cal.com <peer@cal.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-22 16:44:29 +00:00
Bailey PumfleetGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>alex@cal.com <me@alexvanandel.com>
89ae748681 feat: Add download CSV button on bookings page (#27107)
* Add download CSV button on bookings page

* fix: localize CSV headers and filename using i18n

Co-Authored-By: alex@cal.com <me@alexvanandel.com>

* fix: prevent infinite loop when batch returns empty bookings during CSV download

Co-Authored-By: alex@cal.com <me@alexvanandel.com>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: alex@cal.com <me@alexvanandel.com>
2026-01-22 16:31:17 +00:00
Alex van Andel c5fbafd9fb Revert "feat: redesign team creation flow to match onboarding-v2 design (#26733)"
This reverts commit 37847c0061.
2026-01-22 11:15:43 -03:00
devin-ai-integration[bot]GitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>susan@cal.com <susan@cal.com>Rajiv Sahal
5dc5faf01f fix: update Learn More button link on teams page to cal.com/teams (#27065)
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: susan@cal.com <susan@cal.com>
Co-authored-by: Rajiv Sahal <sahalrajiv-extc@atharvacoe.ac.in>
2026-01-22 13:16:58 +00:00
Ram ShuklaandGitHub be13bdf18e fix: Matched styling of Webhooks just like api keys page. (#27116)
* fixed text issue

* fixed text issue

* matched style of api keys page
2026-01-22 10:27:20 +00:00
devin-ai-integration[bot]GitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>ali@cal.com <ali@cal.com>
2a98693dcd feat: add assigned badge to team event types (#27036)
* feat: add assigned badge to team event types

Add an 'Assigned' badge to Round Robin and Collective event types
when the current user is a host/participant of the event type.
This provides visibility to users without edit permissions that
they are included in the rotation.

Changes:
- Add isCurrentUserHost flag in getEventTypesFromGroup handler
- Display blue 'Assigned' badge in event types listing view
- Add i18n translation for 'assigned' text

Co-Authored-By: ali@cal.com <ali@cal.com>

* refactor: remove redundant isTeamEvent check for assigned badge

Co-Authored-By: ali@cal.com <ali@cal.com>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: ali@cal.com <ali@cal.com>
2026-01-22 10:16:22 +01:00
AnshumancanrockandGitHub 856deaaead fix: workflows action delete icon hover color (#27106) 2026-01-22 08:21:33 +00:00
Volnei MunhozandGitHub f7f4df6922 Fix nav tab-stick position (#27097) 2026-01-21 16:37:25 -03:00
Rajiv SahalGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>Peer RichelsenHariom Balhara
8c39210a12 fix: scroll issues in Embed (#26583)
* chore: add new view for two step slot selection for embed

* fix: make sure two step slot selection is false by default

* chore: update embed playground to showcase two step slot selection

* chore: add tests

* chore: update embed snippet generator code to include two step slot selection

* chore: update docs

* fix: back button styling

* chore: implement feedback from cubic

* fix: add missing isEnableTwoStepSlotSelectionVisible properties to test mock store

Co-Authored-By: unknown <>

* chore: implement PR feedback

* chore: update slot selection modal

* chore: add prop to hide available times header

* fix: scope two-step slot selection visibility to mobile only

Restores the isMobile check in the timeslot visibility guard to ensure
desktop embeds continue to show the booking UI when two-step slot
selection is enabled. The feature should only hide the timeslot list
on mobile devices.

Addresses Cubic AI review feedback (confidence 9/10).

Co-Authored-By: unknown <>

* fixup: use translations for loading instead of actual word

* fix: type check

* fix: add window.matchMedia mock for jsdom test environment

Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>

* fix: add window.matchMedia mock to packages/testing/src/setupVitest.ts

Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>

* fix: unit tests failing

* add a width style to the two-step slot selection embed container.

* refactor: rename enableTwoStepSlotSelection to useSlotsViewOnSmallScreen

- Rename external-facing embed config option from enableTwoStepSlotSelection to useSlotsViewOnSmallScreen
- Update URL parameter parsing in embed-iframe.ts
- Update type definitions in types.ts and index.d.ts
- Update internal variable names to slotsViewOnSmallScreen for consistency
- Update documentation, playground examples, and tests

Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>

* Add config to prefill all booking fields so that slot has confirm button along with it

* chore: implement PR feedback

* fix: move twoStepSlotSelection embed outside misc-embeds div to fix e2e test

The e2e test was failing because the misc-embeds div content was
intercepting pointer events on mobile viewport. This follows the same
pattern used for skeletonDemo - the embed is now outside misc-embeds
and the div is hidden when testing this namespace.

Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>

* fix: prevent pointer event interception in twoStepSlotSelection embed

Hide heading and note elements and set pointer-events: none on container
elements while keeping pointer-events: auto on the iframe container.
This prevents the container from intercepting clicks on the iframe
during mobile viewport e2e tests.

Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>

* fix: hide all non-essential content for twoStepSlotSelection e2e test

Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>

* fix: disable pointer-events on body for twoStepSlotSelection e2e test

Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>

* fix: remove pointer-events: auto on container to let clicks pass through to iframe

Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>

* fix: explicitly set pointer-events: none on container and inline-embed-container

Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>

* fix: also set pointer-events: none on html element to prevent interception

Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>

* fix: make .place div fill viewport for twoStepSlotSelection e2e test

Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>

* fix: failing embed tests

* fixup

* fixup fixup

* fix: failing tests

* fix: update checks for verifying prefilled date

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
2026-01-21 15:44:33 -03:00
Ram ShuklaandGitHub 5bfbec6915 made changes to the nav dropdown style to maintain the centre lining and the differentiator in the option avaialable with dropdown (#27038) 2026-01-21 18:04:12 +00:00
Peer RichelsenGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
769035b1ee feat: add Help Desk search link when KBar has no results (#27062)
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-21 17:32:58 +00:00
Hariom BalharaandGitHub 9fa245a03b getSchedule request similar to booking page needs org username instead of user.username (#27086) 2026-01-21 22:19:13 +05:30
Peer RichelsenGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>eunjae@cal.com <hey@eunjae.dev>Lauris Skraucissupalarrycubic-dev-ai[bot] <1082092+cubic-dev-ai[bot]@users.noreply.github.com>CarinaWollilauris@cal.com <lauris@cal.com>Morgan
a03722fd7f feat: add OAuth client developer settings page with approval workflow (#25556)
* feat: add OAuth client developer settings page with approval workflow

- Add new developer OAuth page at /settings/developer/oAuth for users to submit OAuth client requests
- Transform admin OAuth page into management dashboard for reviewing/approving submissions
- Add OAuthClientApprovalStatus enum (PENDING, APPROVED, REJECTED) to track submission status
- Add userId and createdAt fields to OAuthClient model for tracking submissions
- Create email notifications for admin (new submission) and user (approval)
- Add sidebar navigation link in developer section below API keys
- Add comprehensive translations for new UI strings
- Create OAuthClientRepository for data access following repository pattern

Co-Authored-By: peer@cal.com <peer@cal.com>

* fix: re-export generateSecret for backward compatibility

Co-Authored-By: peer@cal.com <peer@cal.com>

* feat: make logo mandatory and list items clickable for OAuth clients

Co-Authored-By: peer@cal.com <peer@cal.com>

* fix: add missing translation keys and remove client secret from details dialog

Co-Authored-By: peer@cal.com <peer@cal.com>

* fix: address cubic AI reviewer comments

- Remove duplicate 'there' JSON key in common.json
- Add select clause to findByUserId to avoid exposing clientSecret
- Add @@index([userId]) to OAuthClient model for query performance
- Update migration to include the index

Co-Authored-By: peer@cal.com <peer@cal.com>

* fix: address PR review comments - fix indentation and use useCopy hook

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* fix: change react-dom/server import to fix Turbopack compatibility

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* Revert "fix: change react-dom/server import to fix Turbopack compatibility"

This reverts commit c3e0b709c2d88fd221143cb4ce9cd25bb8c94277.

* fix: use email service pattern for OAuth client notifications

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* fix: add try-catch around email sending to handle Turbopack react-dom/server issue

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* Revert "fix: add try-catch around email sending to handle Turbopack react-dom/server issue"

This reverts commit fc9d47cd773505ebc5ee2696718aad4a8a98be77.

* fix: improve OAuth client UI with skeleton loaders and smaller dialog styling

- Replace 'Loading...' text with proper skeleton loaders in both developer and admin OAuth client views
- Make client_id and copy button smaller in dialogs using size='sm' and text-sm styling
- Add 'client_id' translation key to common.json for proper i18n

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* fix: improve skeleton loader to match actual OAuth client list structure

- Remove divide-y from container and use conditional border-b on rows
- Match the exact structure from oauth-clients-view.tsx L126-160
- Use proper spacing for text elements (mt-1 instead of space-y-2)

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* fix skeleton

* rename the selected oauth client dialog

* fix: address PR feedback - admin auth, dropdown styling, sidebar label

- Add defense-in-depth admin authorization check in updateClientStatus handler
- Fix broken dropdown menu by using DropdownItem with StartIcon prop
- Fix sidebar menu label from 'oAuth' to 'oauth_clients' to match developer view

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* update common.json

* feat: show client secret in approval email for confidential OAuth clients

- Add regenerateSecret method to OAuthClientRepository
- Regenerate secret when admin approves a PENDING confidential client
- Include client secret in approval notification email
- Add one-time warning message about storing the secret securely
- Only regenerate on first approval (not re-approvals)

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* feat: add Website URL field, fix logo styling, show client secret after approval

- Add Website URL field to OAuth client forms (admin and developer views)
- Fix Upload Logo section styling by wrapping in Label div with proper gap
- Display client secret in dialog after admin approves a confidential OAuth client
- Add websiteUrl field to Prisma schema with migration
- Update tRPC handlers and repository to support websiteUrl
- Add translation keys for new UI elements

Co-Authored-By: peer@cal.com <peer@cal.com>

* fix: move clientSecret variable declaration outside if block for proper scoping

Co-Authored-By: peer@cal.com <peer@cal.com>

* refactor: dont expose client secret in emails

* refactor: dont regenerate secret upon status change

* refactor: reuse existing hash function

* refactor: rename admin/oAuth to admin/oauth page

* refactor: deduplicate oauth repositories

* refactor: remove withGlobalPrisma from oauth repository

* refactor: developer oauth page

* refactor: oauth status by default accepted

* refactor: request oauth status when creating

* refactor ux

* fix: address Cubic AI code review feedback

- Add purpose field to plain text email body for accessibility
- Convert NewOAuthClientButton to inline JSX to avoid React anti-pattern
- Trigger re-approval when redirectUri changes for security
- Add e.preventDefault() for Space key to prevent page scroll
- Change default approvalStatus to PENDING for defense-in-depth
- Use oauth_clients translation key for consistency
- Add meaningful alt text to Avatar for accessibility
- Remove onClick from DialogClose to prevent double-run close effects
- Return NOT_FOUND for non-owner delete to prevent resource enumeration

Co-Authored-By: unknown <>

* common.json file

* refactor: delete all prisma migrations

* refactor: have just 1 prisma migration

* revert: some devin changes

* fix: typecheck

* test: owner OAuth crud

* test: admin OAuth approval / rejection

* fix: address Cubic AI review feedback (confidence 9/10 issues)

- schema.prisma: Remove @default("") from purpose field to make it required
- schema.prisma: Use UTC-aware timezone expression for createdAt default
- OAuthClientFormFields.tsx: Localize redirect URI placeholder using t()
- common.json: Add redirect_uri_placeholder translation key

Co-Authored-By: unknown <>

* cubic changes

* refactor: dont log sensitive info and rethrow error

* cubic feedback

* refactor: make oauth client purpose optional

* refactor: admin/oauth not allowed if not logged in

* refactor: admin view skeleton

* refactor: rename state

* refactor: get rid of redundant mapping

* refactor: remove redundant handler

* refactor: remove redundant handler

* refactor: re-usable new oauth client button

* refactor: dialogs

* refactor: modals

* refactor: handler names, dialog, skeleton

* fix: purpose being null

* refactor: rename handler and delete old oauth admin page

* fix: purpose in submission

* refactor: handler names

* refactor: rename

* refactor: update handler

* refactor: rename approvalStatus -> status

* refactor: simplify modal

* refactor: name

* dont require repproval if redirectUri changes

* fix: remove integration sync index creation

* refactor: require re-approval if redirectUri updated

* fix: flaky e2e test

* fix: flaky e2e test

* fix: flaky e2e test

* fix: remove duplicate common.json keys

* refactor: replace team@cal.com with SUPPORT_MAIL_ADDRESS

* refactor: generate client secret on handler level

* fix: authorization code only available to approved clients

* refactor: cubic review dont display exclamation

* refactor: cubic review website_url in common json

* fix: dont default in ui to approved status

* refactor: optiona logo in schema create handler

* fix: tests

* fix: tests

* fix: /authorize redirect if client not approved or show error

* test: authorize page with invalid client id

* refactor: dont allow refreshing tokens unless approved client

* fix: flaky e2e test

* fix: flaky e2e test

* fix: flaky e2e test

* fix: flaky e2e test

* fix: flaky e2e test

* fix: flaky e2e test

* chore: warn that pending client is not usable

* fix: approve and reject buttons

* fix: /authorize show error if client not approved

* refactor: info message about editing oauth client and status

* change info alert to warning

* try to fix ci test

* debug: failing e2e test

* fix: improve session propagation in oauth-client-admin E2E test

- Add navigateToAdminOAuthPage helper that waits for listClients API call
- If the API call doesn't arrive (session issue), reload page to force session refresh
- This fixes the CI flakiness where admin page wasn't loading due to session not having ADMIN role

Co-Authored-By: lauris@cal.com <lauris@cal.com>

* fix: register waitForResponse before navigating in E2E test

- Register the listClients waitForResponse promise BEFORE page.goto()
- This ensures the response isn't missed during page load
- Also register the promise before reload in the catch block

Co-Authored-By: lauris@cal.com <lauris@cal.com>

* fix: rename oAuth folder to oauth for case-sensitive filesystems

The admin OAuth page route was at /settings/admin/oAuth (capital A) but the
code references /settings/admin/oauth (lowercase). This caused 404 errors
on case-sensitive filesystems (Linux).

Also improved the E2E test navigation helper to retry with delays if the
admin page doesn't load immediately, handling session propagation timing.

Co-Authored-By: lauris@cal.com <lauris@cal.com>

* test style

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: eunjae@cal.com <hey@eunjae.dev>
Co-authored-by: Lauris Skraucis <lauris.skraucis@gmail.com>
Co-authored-by: supalarry <laurisskraucis@gmail.com>
Co-authored-by: cubic-dev-ai[bot] <1082092+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: lauris@cal.com <lauris@cal.com>
Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
2026-01-21 12:23:51 -03:00
Eunjae LeeGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
5449b8d913 refactor: store timestamp instead of boolean for feature opt-in (#27080)
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-21 15:17:32 +00:00
devin-ai-integration[bot]GitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>ali@cal.com <ali@cal.com>Syed Ali Shahbaz
cb567a91c5 feat: add option to hide duration selector in booking page for multiple durations (#27033)
* feat: add option to hide duration selector in booking page for multiple durations

- Add 'hideDurationSelectorInBookingPage' field to event type metadata schema
- Add checkbox under Default Duration select in event type settings
- Modify Duration component to hide selector when setting is enabled
- URL params can still set duration when selector is hidden
- Add i18n translation for the new checkbox label
- Add e2e tests for the new functionality

Co-Authored-By: ali@cal.com <ali@cal.com>

* fix: rename checkbox label to 'Hide duration selector'

Co-Authored-By: ali@cal.com <ali@cal.com>

* fix: replace text locator with data-testid in E2E test

Replace `text=Multiple duration` locator with `page.getByTestId("event-types").locator('a[title="Multiple duration"]')` to follow E2E test best practices.

Co-Authored-By: unknown <>

* fix: add data-testid to hide duration selector checkbox for E2E tests

Co-Authored-By: ali@cal.com <ali@cal.com>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: ali@cal.com <ali@cal.com>
Co-authored-by: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com>
2026-01-21 10:39:36 +02:00
cb6b52b334 right fix (#26963)
Co-authored-by: Anik Dhabal Babu <adhabal2002@gmail.com>
2026-01-20 15:31:43 +00:00
Udit TakkarandGitHub fd130a3fbd chore: don't use object in dependency (#26972) 2026-01-20 18:45:41 +05:30
Rajiv SahalandGitHub 72dc999108 chore: disable dashboard for creating new platform accounts (#27052)
* chore: disable dashboard for creating new platform accounts

* chore: remove page altogether
2026-01-20 12:45:47 +00:00
devin-ai-integration[bot]GitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>ali@cal.com <ali@cal.com>
1e0b0d949f feat: add 40-minute duration option for multiple duration event types (#27032)
- Add 40 minutes to the multipleDurationOptions array in EventSetupTab
- Add comprehensive tests for 40-minute slot generation including:
  - Full day slot generation
  - Correct time intervals
  - Default duration handling
  - Same day booking with time constraints
  - Multiple date ranges

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: ali@cal.com <ali@cal.com>
2026-01-20 10:43:55 +04:00
Hariom BalharaandGitHub 38a7fcfedd fix: filter segment members to only show those with host entries (#26816)
## What does this PR do?

Fixes a bug where the UI shows team members who match segment criteria even when they don't have host entries in the database. When `assignAllTeamMembers` is `true` and segment filtering is enabled, members would appear in the Assignment tab but wouldn't actually be assigned during booking because they lack host entries.

**The Problem:**
- The filtering logic in `EditWeightsForAllTeamMembers` short-circuited when `assignAllTeamMembers` was true, showing all segment-matching members regardless of whether they had host entries
- The `handleSave` function only updates hosts that already exist in the `value` array, filtering out members without host entries
- This created a misleading UI where members appeared but wouldn't be assigned

**The Fix:**
- Removed the `assignAllTeamMembers` prop from `EditWeightsForAllTeamMembers` component entirely since the filtering should always check for existing host entries
- Updated the filter in `EditWeightsForAllTeamMembers.tsx` to always check for existing host entries in the `value` array
- Added `filterMemberIds` prop to `Segment` component to filter matching team members to only show those who are hosts of the event-type
- `AddMembersWithSwitch` now passes the list of non-fixed host user IDs to the Segment component via `filterMemberIds`

## Mandatory Tasks (DO NOT REMOVE)

- [x] I have self-reviewed the code (A decent size PR without self-review might be rejected).
- [x] I have updated the developer docs in /docs if this PR makes changes that would require a [documentation change](https://cal.com/docs). N/A - no documentation changes needed.
- [ ] I confirm automated tests are in place that prove my fix is effective or that my feature works.

## How should this be tested?

1. Create a team event type with round-robin scheduling
2. Enable "Assign all team members" toggle
3. Enable segment filtering with criteria that matches some team members
4. Verify that only members who have host entries (are actually assigned to the event type) appear in the "Edit team member weights" sheet
5. Members matching segment criteria but without host entries should NOT be displayed

## Checklist

- [x] My code follows the style guidelines of this project
- [x] I have checked if my changes generate no new warnings

---

### Human Review Checklist
- [ ] Verify the filtering logic correctly shows only members with host entries in both `EditWeightsForAllTeamMembers` and `Segment` components
- [ ] Confirm this aligns with the actual booking behavior (members without host entries won't be assigned)
- [ ] Check that `filterMemberIds` prop is correctly passed through `AddMembersWithSwitch` → `MembersSegmentWithToggle` → `Segment` → `MatchingTeamMembers`
- [ ] Verify the filter `value.filter((host) => !host.isFixed).map((host) => host.userId)` correctly extracts non-fixed host IDs

---

Link to Devin run: https://app.devin.ai/sessions/3333b41226d0452e98ef7ac358511f5b
Requested by: @hariombalhara
2026-01-20 07:01:49 +05:30
Dhairyashil ShindeGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>peer@cal.com <peer@cal.com>
da91152365 feat: standalone page config to use in companion (#27018)
* feat: hide navigation when ?standalone=true URL parameter is present

Co-Authored-By: peer@cal.com <peer@cal.com>

* feat: standalone page config to use in companion

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: peer@cal.com <peer@cal.com>
2026-01-19 19:27:14 +00:00
Eunjae LeeGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
adc198b37b feat: add feature opt-in banner system (#26625)
* docs: add feature opt-in banner system plan

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* docs: iterate on feature opt-in banner plan based on feedback

- Use config.ts for feature metadata instead of TRPC response
- Consolidate localStorage dismissal into single key to avoid bloat
- Replace separate success dialog with in-dialog success state for smoother UX

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* feat: implement feature opt-in banner system

- Add checkFeatureOptInEligibility TRPC procedure to check if user can opt-in
- Create useFeatureOptInBanner hook with localStorage dismissal state
- Create FeatureOptInBanner floating component for bottom-right display
- Create FeatureOptInConfirmDialog with role-based options and success state
- Integrate banner into bookings-view.tsx as example usage

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* feat: add i18n translation keys for feature opt-in banner

* refactor: create FeatureOptInBannerWrapper for simpler consumer integration

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* refactor: use @calcom/lib/webstorage and add Zod schema for localStorage

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* refactor: address PR review comments - use PBAC, move logic to service, improve typing

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

# Conflicts:
#	packages/features/feature-opt-in/services/FeatureOptInService.ts

* test: add comprehensive tests for checkFeatureOptInEligibility method

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* fix: correct import and Checkbox type errors

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* update message

* invalidate after dialog dismiss

* feat: simulate user opt-in to determine banner eligibility

When a feature has a strict policy and org/team hasn't explicitly
enabled it, user opt-in alone won't enable the feature. This change
simulates what would happen if the user opts in and only shows the
banner if opting in would actually enable the feature.

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* fix: add early return for missing featureConfig and clarify simulation comment

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* fix repository usage

* refactor: simplify FeatureOptInConfirmDialog UI and remove unused translation

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* refactor: replace radio buttons with multi-select dropdown in FeatureOptInConfirmDialog

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* resize banner

* refactor: use AnimatedPopover pattern for team selection and rename titleI18nKey to nameI18nKey

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* fix: change 'Just for me' to 'For me', fix width clipping, remove divider

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* update style

* feat: make 'Just for me' mutually exclusive with teams/org and store opt-ins in localStorage

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* refactor: remove barrel imports and update to direct imports

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* fix: add modal prop to AnimatedPopover to fix scroll lock conflict in dialogs

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* fix: wrap Popover.Content with Portal to prevent layout interference in dialogs

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* fix: use flexbox gap instead of space-y to prevent popover wrapper from affecting layout

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* Revert "fix: use flexbox gap instead of space-y to prevent popover wrapper from affecting layout"

This reverts commit 8385adafa890c2f2674aa3ae3b10ca6e0c55ba5c.

* Revert "fix: wrap Popover.Content with Portal to prevent layout interference in dialogs"

This reverts commit e84301a35a99b3559d47c2d37316af290834ca2d.

* Revert "fix: add modal prop to AnimatedPopover to fix scroll lock conflict in dialogs"

This reverts commit b015af2f1cf31ef7087c02cb8535d96cc4a34125.

* feat: replace Radix Dialog and AnimatedPopover with coss-ui components

This migration uses @coss/ui Dialog and Popover components which are built on
Base UI instead of Radix. Base UI handles scroll locking and positioning
differently, which should fix the gap issue when opening the popover inside
the dialog.

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* refactor: replace remaining @calcom/ui components with coss-ui

- Replace Divider with Separator from @coss/ui
- Replace Label with Label from @coss/ui
- Replace CheckboxField with Checkbox + Label from @coss/ui
- Replace Icon with direct lucide-react icons (UserIcon, BuildingIcon, UsersIcon, CheckIcon)
- Replace showToast with toastManager.add() from @coss/ui

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* refactor: replace Popover with Menu component from coss-ui

- Replace Popover + FilterCheckboxField with Menu + MenuCheckboxItem
- MenuCheckboxItem provides built-in checkbox indicator and styling
- MenuSeparator provides proper menu separators
- Cleaner API with onCheckedChange callback
- Better keyboard navigation support

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* fix: align icon and text on same line in MenuCheckboxItem, widen dialog

- Wrap icon and text in flex container with items-center gap-2
- Change dialog width from sm:max-w-md to sm:max-w-lg to prevent text wrapping

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* use dimmed bg for coss dialog title

* refactor: change nameI18nKey/descriptionI18nKey to nested i18n object

- Change OptInFeatureConfig interface to use i18n: { name, description }
- Update all component usages to use featureConfig.i18n.name and featureConfig.i18n.description
- Update test mocks to use new structure

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* feat: add i18n.title to OptInFeatureConfig type definition

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* update texts

* use title instead of name

* update banner style

* refactor: split FeatureOptInConfirmDialog into separate success and confirmation dialogs

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* fix: don't record dismissed info in local storage after successful opt-in

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* fix: add checkFeatureOptInEligibility to IFeatureOptInService interface

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* update common.json

* refactor: move tRPC usage from features package to apps/web/modules

Addresses Cubic AI review feedback (confidence 9/10):
- Remove @calcom/trpc import from FeatureOptInConfirmDialog.tsx
- Add FeatureOptInMutations type for passing mutation functions via props
- Move tRPC hooks to useFeatureOptInBanner hook in apps/web/modules
- Pass mutations through FeatureOptInBannerWrapper to dialog component

This maintains the architectural constraint that packages/features
should not import from @calcom/trpc to prevent circular dependencies.

Co-Authored-By: unknown <>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-19 18:48:26 +00:00
sean-brydonGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
37847c0061 feat: redesign team creation flow to match onboarding-v3 design (#26733)
* feat: redesign team creation flow to match onboarding-v3 design

Co-Authored-By: sean@cal.com <Sean@brydon.io>

* feat: skip invite options and go directly to email invite step

Co-Authored-By: sean@cal.com <Sean@brydon.io>

* feat: invalidate teams query on submit to refresh teams list

Co-Authored-By: sean@cal.com <Sean@brydon.io>

* fix: use server action to invalidate server-side teams cache

Co-Authored-By: sean@cal.com <Sean@brydon.io>

* fix: conditionally render avatar in browser view to remove extra padding

Co-Authored-By: sean@cal.com <Sean@brydon.io>

* fix browser view

* test: update team creation E2E tests to use new onboarding-v3 flow

Co-Authored-By: sean@cal.com <Sean@brydon.io>

* test: update auth-index.e2e.ts to use new team creation flow

Co-Authored-By: sean@cal.com <Sean@brydon.io>

* test: update team-management.e2e.ts to use new team creation flow

Co-Authored-By: sean@cal.com <Sean@brydon.io>

* fix: add error handling for createTeam and improve CSV parsing for quoted fields

Co-Authored-By: sean@cal.com <Sean@brydon.io>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-19 14:53:51 +00:00
Syed Ali ShahbazandGitHub c1d0a6bb1b fix: Stores the DateRange in UTC instead of user machine that caused the bug (#26900)
* fix init

* remove comment

* fix to v2

* type fix

* edge case

* test fix to suit the date storage method

* fix for atoms

* backward compatibility

* fix test mock

* test fix?

* testing a theory

* address cubic
2026-01-19 10:41:53 +02:00
c42d60256d Fix app card action button alignment (#26954)
Co-authored-by: Deepanshu Verma <deepanshuverma186@email.com>
2026-01-17 10:24:44 +05:30
Eesh MidhaandGitHub 07fee3a0aa fix: prevent HTML encoding of forward slash in booking confirmation (#26949)
- Add interpolation: { escapeValue: false } to AttendeeRequestEmail.tsx
- Add interpolation: { escapeValue: false } to attendee-request-email.ts
- Add interpolation: { escapeValue: false } to bookings-single-view.tsx

This prevents special characters like '/' from being HTML-encoded to '&#x2F;'
in booking confirmation emails and success page dialogs.

Fixes #26938
2026-01-17 04:53:38 +00:00
Eesh MidhaGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
54af3a2939 fix: sync filter segment checkmark with button selection state (#26930)
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-16 14:05:55 +00:00
Dhairyashil ShindeandGitHub 411ca11d25 feat: pass register param directly to login page from OAuth authorize (#26922) 2026-01-16 10:25:39 +00:00
Eunjae LeeandGitHub b13e0f46ad feat: clear all filters when deselecting a segment (#26920)
## What does this PR do?

When a filter segment is selected and the user clicks it again to deselect, this PR now clears all active filters in addition to deselecting the segment.

Previously, deselecting a segment only called `setSegmentId(null)`, which removed the segment selection but left the filters in place. Now it calls `clearAll()` which clears both the segment selection and all active filters.

## Mandatory Tasks (DO NOT REMOVE)

- [x] I have self-reviewed the code (A decent size PR without self-review might be rejected).
- [x] I have updated the developer docs in /docs if this PR makes changes that would require a [documentation change](https://cal.com/docs). N/A - no documentation changes needed.
- [x] I confirm automated tests are in place that prove my fix is effective or that my feature works.

## How should this be tested?

1. Go to a page with DataTable and filter segments (e.g., Bookings page or Organization Members page)
2. Select a filter segment (e.g., "My Bookings" system segment or a user-created segment)
3. Verify filters are applied (URL contains `activeFilters`)
4. Click the same segment again to deselect it
5. Verify the segment is deselected AND all filters are cleared (URL should no longer contain `activeFilters`)

An e2e test has been added to `filter-segment.e2e.ts`:
- `Deselecting a segment clears all active filters`

## Checklist

- [x] My code follows the style guidelines of this project
- [x] I have checked if my changes generate no new warnings

## Human Review Checklist

- [ ] Verify that calling `clearAll()` instead of `setSegmentId(null)` is the intended behavior (clears both segment selection and all active filters)
- [ ] Consider if there are use cases where users might want to keep filters when deselecting a segment

---

> **Link to Devin run**: https://app.devin.ai/sessions/44f22b80d9c442bdb334d04dac2b476d
> **Requested by**: @eunjae-lee
2026-01-16 11:19:25 +01:00
Peer RichelsenGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
fc518bfdc1 feat: allow link cloaking for Organization accounts in workflow emails (#26528)
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-16 08:33:38 +00:00
Albin_BabyGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>albin-baby-2002
4d9e726fef fix: make SSR-safe and fix ESLint warning for Beacon in UserDropdown (#24275)
* fix(user-dropdown): make SSR-safe and fix ESLint warning for Beacon

* fix: added ssr guard in second useEffect and added type for beacon instead of ts-ignoring

* fix: add dependency array to Beacon useEffect

Address review feedback by adding [user?.username] dependency array
to the Beacon session-data useEffect, improving performance by
preventing unnecessary re-runs on every render.

Co-authored-by: albin-baby-2002 <albinbaby2002@gmail.com>
Co-Authored-By: unknown <>

* test: add automated tests for UserDropdown Beacon functionality

Add comprehensive tests for:
- Beacon session-data calls with correct payload
- Handling of undefined Beacon (no errors)
- Username change triggering useEffect re-run
- SSR safety (window undefined check)
- Component rendering states (loading, user available, no user)

Co-authored-by: albin-baby-2002 <albinbaby2002@gmail.com>
Co-Authored-By: unknown <>

* refactor: remove useless comments and misleading SSR test

- Remove redundant comments above vi.mock calls (per keithwillcode feedback)
- Remove SSR safety test that provided false coverage since jsdom always has window defined (per Cubic feedback)
- The 'should not throw error when Beacon is undefined' test already covers graceful handling

Co-Authored-By: unknown <>

* fix: remove unused @ts-expect-error directives

The Window interface is augmented with optional Beacon and Support properties,
so TypeScript allows deleting them without errors.

Co-Authored-By: unknown <>

* fix: handle lazy-loaded Beacon with polling

When Beacon loads lazily after component mount, the useEffect now polls
every second until Beacon becomes available, then sends session data
and clears the interval. This ensures session info is always sent even
when HelpScout loads asynchronously.

Added test to verify lazy loading behavior works correctly.

Co-Authored-By: unknown <>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: albin-baby-2002 <albinbaby2002@gmail.com>
2026-01-16 00:43:01 +00:00
Peer RichelsenGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
eb2fedf7de feat: hide 'Don't have an account?' button when register=false query param is set (#26904)
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-15 20:09:34 +00:00
22201cbc75 fix: app card description truncation (#26722)
* Fix app card description truncation

* Refactor AppCard description paragraph for line clamping

---------

Co-authored-by: Deepanshu Verma <deepanshuverma186@email.com>
Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
2026-01-15 16:55:33 +00:00
sean-brydonGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
9ea71d2ba5 refactor: migrate MembershipRole usages to PBAC permission checks (#26871)
* refactor: migrate MembershipRole usages to PBAC permission checks

- Refactor get.handler.ts to use PermissionCheckService for canUpdateTeams
- Refactor checkForInvalidAppCredentials.ts to use getTeamIdsWithPermission
- Refactor outOfOffice.utils.ts to use checkPermission for ooo.update
- Refactor checkIfOrgNeedsUpgrade.handler.ts to use organization.manageBilling
- Refactor getActiveOnOptions.handler.ts to use eventType.update permission
- Refactor WorkflowRepository.ts to use workflow.update permission
- Refactor organization.tsx to use team.update permission
- Refactor getEventTypesByViewer.ts to use eventType.update permission
- Refactor getPublicEvent.ts to use team.read permission for private teams
- Update CreateNewOutOfOfficeEntryButton.tsx to use canUpdateOOO prop

Co-Authored-By: sean@cal.com <Sean@brydon.io>

* fix: use organization.update permission instead of team.update for org management

Co-Authored-By: sean@cal.com <Sean@brydon.io>

* fix: rename teamsWithEventTypeManagePermission to teamsWithEventTypeUpdatePermission

Renamed variable to match the permission string being used (eventType.update)

Co-Authored-By: sean@cal.com <Sean@brydon.io>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-15 15:59:00 +01:00
Anik Dhabal BabuandGitHub a8d559d331 fix: hide team members details when hideOrganizerEmail is enabled (#26833)
* fix: hide organizer email

* update
2026-01-15 09:39:51 +00:00
Alex van AndelandGitHub 1dd2652080 fix: Duplicate calls syncing Calendar integrations (#26858)
* fix: Duplicate calls syncing Calendar integrations

* fix: TS error in handler

* Minor fixup

* Set cacheUpdatedAt at correct depth of array

* Import RouterOutputs
2026-01-15 00:21:40 -03:00
Volnei MunhozGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
f5cd2342c7 chore: add biome-ignore comments for dangerouslySetInnerHTML (#26848)
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-14 19:05:53 +00:00
c13fce4483 fix: changes to error on schedule name empty save (#24044)
* fix #21709: change to error on schedule name empty save

* fix comments

* minor enahncemnts

---------

Co-authored-by: Volnei Munhoz <volnei.munhoz@gmail.com>
Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
2026-01-13 18:29:58 +00:00
Eunjae LeeGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>sean-brydon
5c686d90f9 feat: add tri-state UI settings pages and auto opt-in preference (#25892)
* 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>
2026-01-13 15:37:53 +01:00
3aa6499cd4 fix: remove header bug (#26438)
* remove header and add standard pagination

* Remove unused props from OutOfOfficeEntriesList

Removed unnecessary props from the data table component.

* removed standard pagination

* fix

* Update OutOfOfficeEntriesList.tsx

* remove unnecessary padding

---------

Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
Co-authored-by: Keith Williams <keithwillcode@gmail.com>
2026-01-13 12:14:19 +00:00
Pedro CastroandGitHub 1e67f98970 fix: add Icelandic, Lithuanian, and Norwegian locale support for Booker (#25519)
- Create unified date/time formatter with Intl-first approach and dayjs fallback
- Add support for is/lt/nb locales in Booker components
- Unify date formatting across Booker (Header, dates, weekdays)
- Update translation pipeline to include is, lt, nb
- Add tests for new locales and formatter
- Add timezone support in dayjs fallback
- Add formatter caching with circuit breaker
- Use unified formatDateTime in Header.tsx
2026-01-13 08:47:39 -03:00
sean-brydonandGitHub aaf5958b7d feat: adds admin billing section (#26747)
* feat: adds admin billing section

* use loading prop

* add log on resend error

* add error log in billing portal
2026-01-13 10:34:52 +00:00
sean-brydonGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
383314d3e2 feat: add skip trial feature for teams/orgs billing page (#26584)
* feat: add skip trial feature for teams/orgs billing page

Co-Authored-By: sean@cal.com <Sean@brydon.io>

* feat: add translation strings for skip trial feature and fix lint-staged config

Co-Authored-By: sean@cal.com <Sean@brydon.io>

* fix: use IS_TEAM_BILLING_ENABLED instead of IS_SELF_HOSTED

Co-Authored-By: sean@cal.com <Sean@brydon.io>

* fix: use correct DialogHeader props in billing-view.tsx

Co-Authored-By: sean@cal.com <Sean@brydon.io>

* restore lint staged config file

* invalidate trpc cache

* fix: update role filter and error message in skipTrialForTeam handler

- Changed role filter to include both OWNER and ADMIN roles to match authorization logic
- Updated error message to reflect that both owners and admins can skip the trial

Addresses Cubic AI review feedback on PR #26584

Co-Authored-By: unknown <>

* fix: optimize skipTrialForTeam to query only specific team by ID

Address Cubic AI review feedback: Replace findAllAcceptedTeamMemberships
(which fetches all teams) with TeamRepository.findById (which fetches
only the specific team needed). Authorization is already validated
earlier in the handler, so this redundant query was inefficient.

Co-Authored-By: unknown <>

* fix static methods

* feat: use pbac

* fix: remove redundant team query in getSubscriptionStatus handler

Co-Authored-By: sean@cal.com <Sean@brydon.io>

* add pbac to skip team handler

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-13 09:17:42 +00:00
Bailey PumfleetGitHubPedro CastroDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
7c66f33de2 chore: UX Fixes (#26643)
* 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>
2026-01-13 00:56:08 -05:00
Bailey PumfleetGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
5f21f54bae feat: Add compliance page to settings (#26777)
* Add compliance page to settings

* fix: sanitize error logging in B2 download route

Avoid logging raw error objects which may expose sensitive B2 credentials
or internal information. Use sanitized error message instead.

Co-Authored-By: unknown <>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-12 21:50:09 -03:00
913eb47ff1 fix: weekly view scheduler breaking on view switch (#25891)
* fix: weekly view scheduler columns offset

* fix

* fix

---------

Co-authored-by: Anik Dhabal Babu <adhabal2002@gmail.com>
Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
2026-01-12 18:58:11 +00:00
a4d4626319 revert: "feat: rename --font-cal to --font-heading + use Cal Sans UI (#26064)" (#26759)
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2026-01-12 16:57:27 +00:00
Keith WilliamsGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
d24807e0e1 fix: make OOO team member select close after selection (#26736)
* fix: make OOO team member select close after selection

Replace the custom always-visible scrollable list with a proper Select
component that closes after selection like a normal dropdown. The Select
component uses onMenuScrollToBottom for infinite scroll and onInputChange
for search functionality.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix: also convert Team OOO member select to use Select component

Both 'Select team member' sections now use the proper Select component
that closes after selection. Removed unused useInViewObserver import.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix: add menuPlacement='bottom' to Team OOO member select

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-12 14:35:19 +00:00
77a0d69c1a fix(ui): fixing the hover bug in the dropdown component (#26257)
* fix(ui): fixing the hover bug in the dropdown component

* revert

---------

Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
2026-01-12 13:26:19 +00:00
Anik Dhabal BabuandGitHub 93cac5a1c9 fix: don't include ics for unconfirmed booking (#26718) 2026-01-12 03:48:27 +00:00