feat: add calendar cache status and actions#22532
Conversation
- Add updatedAt field to CalendarCache schema with migration - Create tRPC cacheStatus endpoint for fetching cache timestamps - Add action dropdown to CalendarSwitch for Google Calendar entries - Display formatted last updated timestamp in dropdown - Add placeholder for cache deletion functionality - Include translation strings for dropdown content The dropdown only appears for Google Calendar integrations that have active cache entries and provides cache management options for future extensibility. Co-Authored-By: zomars@cal.com <zomars@me.com>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
WalkthroughThis update introduces several new features and modifications related to calendar cache management and credential actions. A new database column ( 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎ 2 Skipped Deployments
|
|
✅ No security or compliance issues detected. Reviewed everything up to 5fd11f9. Security Overview
Detected Code Changes
Reply to this PR with |
- Remove problematic satisfies clause in selectedCalendar.ts - Add missing cacheStatus parameter to ConnectedCalendarList component - Fixes type errors that were preventing CI from passing Co-Authored-By: zomars@cal.com <zomars@me.com>
E2E results are ready! |
- Remove separate cacheStatus tRPC endpoint as requested - Return cache status as separate field in connectedCalendars response - Update UI components to use cache data from connectedCalendars - Fix Prisma type incompatibilities in repository files Co-Authored-By: zomars@cal.com <zomars@me.com>
…e status - Fix Prisma.SortOrder usage in membership.ts orderBy clauses - Remove problematic satisfies clause in selectedCalendar.ts - Fix TeamSelect type reference in team.ts - Update SelectedCalendarsSettingsWebWrapper to properly pass cacheStatus data flow Co-Authored-By: zomars@cal.com <zomars@me.com>
…ription logic - Fix timestamp HTML entity encoding with interpolation escapeValue: false - Only show dropdown for subscribed Google calendars (googleChannelId exists) - Hide delete option when no cache data exists - Include updatedAt and googleChannelId fields upstream in user repository - Update data flow to pass subscription status through components Co-Authored-By: zomars@cal.com <zomars@me.com>
…cache refresh - Add updateManyByCredentialId method to SelectedCalendarRepository - Update fetchAvailabilityAndSetCache to refresh SelectedCalendar timestamps - Ensure webhook flow updates both CalendarCache and SelectedCalendar records - Maintain proper timestamp tracking for calendar cache operations Co-Authored-By: zomars@cal.com <zomars@me.com>
Introduces test-gcal-webhooks.sh to start Tunnelmole, extract the public URL, and update GOOGLE_WEBHOOK_URL in the .env file. Handles process management, rate limits, and ensures environment configuration for Google Calendar webhooks.
Replaces 'ts-node' with 'npx tsx' in the dev:cron script for running cron-tester.ts, likely to improve compatibility or leverage tsx features.
Renamed 'last_updated' to 'cache_last_updated' in locale file for clarity and updated CalendarSwitch to use the new string. Also added dark mode text color support for cache status display.
…ove App - Create CredentialActionsDropdown component consolidating cache and app removal actions - Add deleteCache tRPC mutation for credential-level cache deletion - Update connectedCalendars handler to include cacheUpdatedAt at credential level - Move dropdown from individual CalendarSwitch to credential level in SelectedCalendarsSettingsWebWrapper - Remove cache-related props from CalendarSwitch component - Add translation strings for cache management actions - Consolidate all credential-level actions (cache management + Remove App) in one dropdown Co-Authored-By: zomars@cal.com <zomars@me.com>
- Remove duplicate cache-related keys at lines 51-56 - Keep properly positioned keys later in file - Addresses GitHub comment from zomars about duplicate keys Co-Authored-By: zomars@cal.com <zomars@me.com>
Replaces the DisconnectIntegration component with an inline confirmation dialog for removing app credentials. Adds disconnect mutation logic and updates UI to improve user experience and consistency.
There was a problem hiding this comment.
Actionable comments posted: 5
♻️ Duplicate comments (3)
apps/web/public/static/locales/en/common.json (1)
3376-3379: Potential duplicate key:cache_last_updated
A key with the same name was already introduced earlier in this file. JSON objects cannot contain duplicate keys – only the last occurrence will be retained at runtime, silently shadowing the previous one and breaking i18n calls that expect the first value.- "cache_last_updated": "Last updated: {{timestamp}}", + // 🔄 remove or rename – a key with this name already exists abovePlease deduplicate (or rename) before shipping.
packages/trpc/server/routers/viewer/calendars/deleteCache.handler.ts (2)
17-22: Use repository pattern instead of direct Prisma calls.This code violates the established architectural pattern by making direct Prisma calls outside a repository. Based on previous review feedback, all database operations should go through repositories.
Consider creating a method in a credential repository for this validation:
- const credential = await prisma.credential.findFirst({ - where: { - id: credentialId, - userId: user.id, - }, - }); + const credentialRepository = new CredentialRepository(); + const credential = await credentialRepository.findByIdAndUserId(credentialId, user.id);
28-30: Use CalendarCacheRepository for cache deletion.Direct Prisma calls should be avoided. Use the existing
CalendarCacheRepositoryfor cache operations.- await prisma.calendarCache.deleteMany({ - where: { credentialId }, - }); + const cacheRepository = new CalendarCacheRepository(); + await cacheRepository.deleteCacheByCredentialId(credentialId);Note: You may need to add the
deleteCacheByCredentialIdmethod to the repository interface and implementation.
🧹 Nitpick comments (5)
apps/web/public/static/locales/en/common.json (1)
3376-3382: Nit: group related keys for maintainability
Consider keeping the new cache-related strings together (status / last-updated / actions / confirmations) and adding a brief comment block; this makes it easier for translators to locate context in large files.packages/features/apps/components/CredentialActionsDropdown.tsx (1)
88-94: Consider using dynamic locale for date formatting.The date formatting is hardcoded to "en-US" locale. Consider using the user's locale for better internationalization support.
- {t("cache_last_updated", { - timestamp: new Intl.DateTimeFormat("en-US", { - dateStyle: "short", - timeStyle: "short", - }).format(new Date(cacheUpdatedAt)), - interpolation: { escapeValue: false }, - })} + {t("cache_last_updated", { + timestamp: new Intl.DateTimeFormat(undefined, { + dateStyle: "short", + timeStyle: "short", + }).format(new Date(cacheUpdatedAt)), + })}scripts/test-gcal-webhooks.sh (3)
4-9: Mark constants as read-only & quote interpolations
- Prefix immutable config vars with
readonlyto prevent accidental reassignment.- Quote
$TM_PORTin thepgreppattern to avoid glob/word-splitting surprises when the port is changed to a value containing spaces (unlikely but defensive).-readonly LOG_FILE="/tmp/tmole.log" -readonly ENV_FILE="../.env" -readonly TM_PORT=3000 -readonly TM_KEYWORD="https://.*\.tunnelmole\.net" -TMOLE_RUNNING=$(pgrep -f "tmole $TM_PORT") +readonly LOG_FILE="/tmp/tmole.log" +readonly ENV_FILE="../.env" +readonly TM_PORT=3000 +readonly TM_KEYWORD='https://.*\.tunnelmole\.net' +# Quote port in pattern to avoid word-splitting +TMOLE_RUNNING=$(pgrep -f "tmole ${TM_PORT}")
35-38: Quote$TM_PORTwhen invokingtmoleWithout quotes Bash will perform pathname expansion if someone sets
TM_PORTto a glob-like value, leading to a cryptic failure.- tmole $TM_PORT > "$LOG_FILE" 2>&1 & + tmole "$TM_PORT" > "$LOG_FILE" 2>&1 &
41-43: Loop indexiis unused – silence Shellcheck & intent-clarifyShellcheck SC2034 flags
ias unused. Replace with_or switch toseqfor clarity.-for i in {1..20}; do +for _ in {1..20}; do
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (18)
apps/web/package.json(1 hunks)apps/web/pages/api/integrations/[...args].ts(1 hunks)apps/web/public/static/locales/en/common.json(1 hunks)packages/app-store/googlecalendar/lib/CalendarService.ts(1 hunks)packages/features/apps/components/CredentialActionsDropdown.tsx(1 hunks)packages/features/calendar-cache/calendar-cache.repository.interface.ts(1 hunks)packages/features/calendar-cache/calendar-cache.repository.mock.ts(1 hunks)packages/features/calendar-cache/calendar-cache.repository.ts(1 hunks)packages/lib/getConnectedDestinationCalendars.ts(1 hunks)packages/lib/server/repository/selectedCalendar.ts(2 hunks)packages/lib/server/repository/user.ts(1 hunks)packages/platform/atoms/selected-calendars/wrappers/SelectedCalendarsSettingsWebWrapper.tsx(5 hunks)packages/prisma/migrations/20250715160635_add_calendar_cache_updated_at/migration.sql(1 hunks)packages/prisma/schema.prisma(1 hunks)packages/trpc/server/routers/viewer/calendars/_router.tsx(2 hunks)packages/trpc/server/routers/viewer/calendars/connectedCalendars.handler.ts(2 hunks)packages/trpc/server/routers/viewer/calendars/deleteCache.handler.ts(1 hunks)scripts/test-gcal-webhooks.sh(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
apps/web/public/static/locales/en/common.json (1)
undefined
<retrieved_learning>
Learnt from: bandhan-majumder
PR: #22359
File: packages/lib/server/locales/en/common.json:1336-1339
Timestamp: 2025-07-14T16:31:45.201Z
Learning: When making localization changes for new features, it's often safer to add new strings rather than modify existing ones to avoid breaking existing functionality that depends on the original strings. This approach allows for feature-specific customization while maintaining backward compatibility.
</retrieved_learning>
🧬 Code Graph Analysis (2)
packages/trpc/server/routers/viewer/calendars/_router.tsx (1)
packages/trpc/server/routers/viewer/calendars/deleteCache.handler.ts (1)
deleteCacheHandler(13-33)
packages/features/apps/components/CredentialActionsDropdown.tsx (1)
packages/ui/components/dropdown/Dropdown.tsx (5)
Dropdown(12-12)DropdownMenuTrigger(15-26)DropdownMenuContent(34-51)DropdownMenuItem(63-71)DropdownItem(161-181)
🪛 Shellcheck (0.10.0)
scripts/test-gcal-webhooks.sh
[warning] 41-41: i appears unused. Verify use (or export if used externally).
(SC2034)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: Production builds / Build Web App
- GitHub Check: Production builds / Build Atoms
- GitHub Check: Type check / check-types
- GitHub Check: Production builds / Build API v2
- GitHub Check: Production builds / Build API v1
- GitHub Check: Tests / Unit
- GitHub Check: Security Check
🔇 Additional comments (24)
packages/lib/server/repository/user.ts (1)
899-900: LGTM – Prisma schema includes required fieldsThe
SelectedCalendarmodel inpackages/prisma/schema.prismaalready defines both fields:
updatedAt DateTime? @updatedAtgoogleChannelId String?(with@@unique([googleChannelId, eventTypeId]))No further changes are needed here.
packages/features/calendar-cache/calendar-cache.repository.mock.ts (1)
27-30: LGTM! Consistent mock implementation.The
getCacheStatusByCredentialIdsmethod follows the established pattern in this mock class - logging the skip message and returning an appropriate default value (empty array).packages/app-store/googlecalendar/lib/CalendarService.ts (1)
1022-1024: Update selected calendar timestamps after cache refresh - looks good!This change correctly updates the
updatedAttimestamp for all selected calendars associated with the credential after successfully fetching and caching availability data. The empty update object{}will trigger Prisma's automaticupdatedAtfield update, which provides the cache status information displayed in the new UI components.Regarding the past review comment about frontend usage: Yes, this data is actively used in the frontend through the new
CredentialActionsDropdowncomponent to display cache status and enable cache management actions.apps/web/pages/api/integrations/[...args].ts (1)
74-75: Good cleanup of response handling logic.This change improves the code by removing the unnecessary return of the response object. Since the response is handled by reference and the function should complete the response handling, returning
undefinedis more appropriate than returning the response object itself.packages/features/calendar-cache/calendar-cache.repository.interface.ts (1)
30-32: Well-designed interface addition for cache status tracking.The new
getCacheStatusByCredentialIdsmethod is properly designed with:
- Clear method name indicating batch cache status retrieval
- Appropriate input type for credential ID array
- Well-structured return type with nullable
updatedAtfor missing cache entries- Consistent async/await pattern
This supports the new cache management feature effectively.
packages/trpc/server/routers/viewer/calendars/_router.tsx (2)
1-2: Necessary import addition for zod validation.The zod import is correctly added to support the input validation in the new
deleteCachemutation.
27-33: Well-implemented cache deletion mutation.The new
deleteCachemutation follows established patterns:
- Properly uses
authedProcedurefor authentication- Validates input with appropriate zod schema
- Follows the dynamic import pattern for consistency
- The corresponding handler (shown in relevant code snippets) properly validates credential ownership before deletion
packages/lib/server/repository/selectedCalendar.ts (2)
260-260: Good simplification of the findMany method.Removing the intermediate variable and
satisfiesoperator makes the code more concise while maintaining the same functionality. This is a clean improvement.
400-405: Well-implemented bulk update method.The new
updateManyByCredentialIdmethod is properly designed:
- Clear method name indicating bulk update operation
- Appropriate parameter types using Prisma types
- Correct use of
updateManyfor bulk operations- Proper filtering by credential ID
- Consistent with existing repository patterns
This method supports the cache management feature by enabling efficient bulk timestamp updates.
packages/lib/getConnectedDestinationCalendars.ts (1)
21-28: LGTM! Type extension correctly supports cache management feature.The addition of
updatedAtandgoogleChannelIdfields to theUserWithCalendarstype properly extends the interface to support the new cache status tracking functionality. This aligns well with the broader cache management feature implementation.packages/trpc/server/routers/viewer/calendars/connectedCalendars.handler.ts (2)
27-36: LGTM! Proper repository pattern usage and clean enrichment logic.The implementation correctly uses the
CalendarCacheRepositoryinstead of direct Prisma calls, addressing previous review feedback. The cache status enrichment logic is clean and efficient, properly mapping credential IDs to cache timestamps.
39-39: Good integration with cache status data.The enriched connected calendars with cache update timestamps are properly returned, enabling the UI to display cache status information.
packages/features/calendar-cache/calendar-cache.repository.ts (1)
173-188: LGTM! Efficient cache status aggregation using repository pattern.The implementation correctly uses Prisma's
groupBywith_maxaggregation to efficiently retrieve the latest cache update timestamp per credential. This follows the repository pattern properly and provides the data needed for the cache status feature.packages/platform/atoms/selected-calendars/wrappers/SelectedCalendarsSettingsWebWrapper.tsx (5)
5-5: Good component replacement for enhanced functionality.Replacing
DisconnectIntegrationwithCredentialActionsDropdownprovides a more comprehensive interface for calendar credential management, including the new cache management capabilities.
70-79: LGTM! Proper props configuration for new dropdown component.The
CredentialActionsDropdownis correctly configured with all necessary props including the newcacheUpdatedAtfield for cache status display and appropriate flags for controlling functionality.
98-98: Good explicit null handling for delegation credential ID.The explicit conversion to
nullwhendelegationCredentialIdis falsy provides better type safety and clarity.
123-132: Consistent dropdown usage in error alert.The same
CredentialActionsDropdowncomponent is properly used in the error alert case, maintaining consistency across different calendar states.
162-162: Minor formatting improvement.The blank line addition improves code readability by separating the query definition from the following logic.
packages/features/apps/components/CredentialActionsDropdown.tsx (6)
1-27: Well-structured imports and interface definition.The imports are properly organized and the
CredentialActionsDropdownPropsinterface is well-defined with appropriate optional parameters and type safety.
29-41: Proper component initialization and state management.The component correctly destructures props and manages state for dropdown visibility and modal dialogs using React hooks.
42-65: Well-implemented TRPC mutations with proper error handling.The mutations include appropriate success/error handling with toast notifications and cache invalidation to keep the UI synchronized.
67-73: Efficient conditional rendering logic.The component uses clear boolean flags and early return pattern to avoid unnecessary rendering when no actions are available.
75-128: Well-structured dropdown UI with good UX patterns.The dropdown properly displays cache status with formatted timestamps and provides clear visual separation between different action types. The destructive actions are appropriately styled with the "destructive" color variant.
130-154: Confirmation dialogs properly address destructive action concerns.Both destructive actions (cache deletion and app removal) now have confirmation dialogs with appropriate danger styling, addressing the previous review feedback about requiring confirmation for destructive actions.
packages/prisma/migrations/20250715160635_add_calendar_cache_updated_at/migration.sql
Outdated
Show resolved
Hide resolved
Added a default value of NOW() for the updatedAt column in the CalendarCache table to ensure existing and future rows have a valid timestamp. Updated the Prisma schema to reflect this change and provide compatibility for legacy data and raw inserts.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
packages/prisma/migrations/20250715160635_add_calendar_cache_updated_at/migration.sql (1)
1-6: Warning header is now stale – update for accuracy
The comment still claims the column is added “without a default value,” which is no longer true and may mislead future maintainers.- Warnings: - - - Added the required column `updatedAt` to the `CalendarCache` table without a default value. This is not possible if the table is not empty. + Note: + + - `updatedAt` is added with `DEFAULT NOW()` to back-fill existing rows safely.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
apps/web/package.json(1 hunks)apps/web/public/static/locales/en/common.json(1 hunks)packages/prisma/migrations/20250715160635_add_calendar_cache_updated_at/migration.sql(1 hunks)packages/prisma/schema.prisma(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- packages/prisma/schema.prisma
- apps/web/package.json
- apps/web/public/static/locales/en/common.json
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/app-store/office365calendar/api/webhook.ts:120-123
Timestamp: 2025-07-18T17:57:16.370Z
Learning: The office365calendar webhook handler in packages/app-store/office365calendar/api/webhook.ts is specifically designed for Office365 calendar integration, not as a generic webhook handler. Therefore, it's safe to assume that fetchAvailabilityAndSetCache method will be implemented in the Office365CalendarService, making explicit validation checks unnecessary.
packages/prisma/migrations/20250715160635_add_calendar_cache_updated_at/migration.sql (1)
Learnt from: vijayraghav-io
PR: calcom/cal.com#16579
File: packages/prisma/schema.prisma:149-153
Timestamp: 2025-07-16T07:14:49.225Z
Learning: In Cal.com's schema design, the team prefers to keep Boolean fields nullable (Boolean?) with defaults rather than making them non-nullable (Boolean) to avoid expensive database migrations that would update existing rows.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
- GitHub Check: Production builds / Build Atoms
- GitHub Check: Production builds / Build Docs
- GitHub Check: Production builds / Build API v2
- GitHub Check: Tests / Unit
- GitHub Check: Production builds / Build API v1
- GitHub Check: Linters / lint
- GitHub Check: Production builds / Build Web App
- GitHub Check: Type check / check-types
- GitHub Check: Security Check
🔇 Additional comments (1)
packages/prisma/migrations/20250715160635_add_calendar_cache_updated_at/migration.sql (1)
8-9: Fix looks good – runtime-safe column addition
Adding the column withDEFAULT NOW()resolves the previous blocker on non-empty tables. ✅
| return setDestinationCalendarHandler({ ctx, input }); | ||
| }), | ||
|
|
||
| deleteCache: authedProcedure |
There was a problem hiding this comment.
NIT I would've gone for the more standard clearCache nomeclature.
| const { user } = ctx; | ||
| const { credentialId } = input; | ||
|
|
||
| const credential = await prisma.credential.findFirst({ |
There was a problem hiding this comment.
NIT I think you tried to rectify this and try to get Devin to use the repo
emrysal
left a comment
There was a problem hiding this comment.
Few nits, but overall happy for this to go in, we should refactor repository access in a bit.
* feat: add calendar cache status dropdown - Add updatedAt field to CalendarCache schema with migration - Create tRPC cacheStatus endpoint for fetching cache timestamps - Add action dropdown to CalendarSwitch for Google Calendar entries - Display formatted last updated timestamp in dropdown - Add placeholder for cache deletion functionality - Include translation strings for dropdown content The dropdown only appears for Google Calendar integrations that have active cache entries and provides cache management options for future extensibility. Co-Authored-By: zomars@cal.com <zomars@me.com> * fix: resolve Prisma type incompatibilities in repository files - Remove problematic satisfies clause in selectedCalendar.ts - Add missing cacheStatus parameter to ConnectedCalendarList component - Fixes type errors that were preventing CI from passing Co-Authored-By: zomars@cal.com <zomars@me.com> * refactor: integrate cache status into connectedCalendars handler - Remove separate cacheStatus tRPC endpoint as requested - Return cache status as separate field in connectedCalendars response - Update UI components to use cache data from connectedCalendars - Fix Prisma type incompatibilities in repository files Co-Authored-By: zomars@cal.com <zomars@me.com> * fix: resolve Prisma type incompatibilities and fix data flow for cache status - Fix Prisma.SortOrder usage in membership.ts orderBy clauses - Remove problematic satisfies clause in selectedCalendar.ts - Fix TeamSelect type reference in team.ts - Update SelectedCalendarsSettingsWebWrapper to properly pass cacheStatus data flow Co-Authored-By: zomars@cal.com <zomars@me.com> * Discard changes to packages/lib/server/repository/membership.ts * Discard changes to packages/lib/server/repository/team.ts * fix: improve calendar cache dropdown with proper formatting and subscription logic - Fix timestamp HTML entity encoding with interpolation escapeValue: false - Only show dropdown for subscribed Google calendars (googleChannelId exists) - Hide delete option when no cache data exists - Include updatedAt and googleChannelId fields upstream in user repository - Update data flow to pass subscription status through components Co-Authored-By: zomars@cal.com <zomars@me.com> * feat: update SelectedCalendar.updatedAt when Google webhooks trigger cache refresh - Add updateManyByCredentialId method to SelectedCalendarRepository - Update fetchAvailabilityAndSetCache to refresh SelectedCalendar timestamps - Ensure webhook flow updates both CalendarCache and SelectedCalendar records - Maintain proper timestamp tracking for calendar cache operations Co-Authored-By: zomars@cal.com <zomars@me.com> * Add script to automate Tunnelmole webhook setup Introduces test-gcal-webhooks.sh to start Tunnelmole, extract the public URL, and update GOOGLE_WEBHOOK_URL in the .env file. Handles process management, rate limits, and ensures environment configuration for Google Calendar webhooks. * Update dev:cron script to use npx tsx Replaces 'ts-node' with 'npx tsx' in the dev:cron script for running cron-tester.ts, likely to improve compatibility or leverage tsx features. * Update cache status string and improve CalendarSwitch UI Renamed 'last_updated' to 'cache_last_updated' in locale file for clarity and updated CalendarSwitch to use the new string. Also added dark mode text color support for cache status display. * refactor: move cache management to credential-level dropdown with Remove App - Create CredentialActionsDropdown component consolidating cache and app removal actions - Add deleteCache tRPC mutation for credential-level cache deletion - Update connectedCalendars handler to include cacheUpdatedAt at credential level - Move dropdown from individual CalendarSwitch to credential level in SelectedCalendarsSettingsWebWrapper - Remove cache-related props from CalendarSwitch component - Add translation strings for cache management actions - Consolidate all credential-level actions (cache management + Remove App) in one dropdown Co-Authored-By: zomars@cal.com <zomars@me.com> * fix: remove duplicate translation keys in common.json - Remove duplicate cache-related keys at lines 51-56 - Keep properly positioned keys later in file - Addresses GitHub comment from zomars about duplicate keys Co-Authored-By: zomars@cal.com <zomars@me.com> * fix: rename translation key to cache_last_updated - Address GitHub comment from zomars - Rename 'last_updated' to 'cache_last_updated' for specificity - Update usage in CredentialActionsDropdown component Co-Authored-By: zomars@cal.com <zomars@me.com> * fix: remove duplicate last_updated translation key Co-Authored-By: zomars@cal.com <zomars@me.com> * fix: add confirmation dialog for cache deletion and use repository pattern - Add confirmation dialog for destructive cache deletion action - Replace direct Prisma calls with CalendarCacheRepository pattern - Add getCacheStatusByCredentialIds method to repository interface - Fix import paths for UI components - Address GitHub review comments from zomars Co-Authored-By: zomars@cal.com <zomars@me.com> * Update CredentialActionsDropdown.tsx * Update common.json * Update common.json * fix: remove nested div wrapper to resolve HTML structure error - Remove wrapping div around DisconnectIntegration component - Fixes nested <p> tag validation error preventing Remove App functionality - Maintains existing confirmation dialog patterns Co-Authored-By: zomars@cal.com <zomars@me.com> * Fix API handler response termination logic Removed unnecessary return values after setting status in the integrations API handler. This clarifies response handling and prevents returning the response object when not needed. Resolves "API handler should not return a value, received object". * fix: 400 is correct error code for computing slot for past booking (#22574) * fix * add test * chore: release v5.5.1 * Refactor credential disconnect to use confirmation dialog Replaces the DisconnectIntegration component with an inline confirmation dialog for removing app credentials. Adds disconnect mutation logic and updates UI to improve user experience and consistency. * Set default value for CalendarCache.updatedAt Added a default value of NOW() for the updatedAt column in the CalendarCache table to ensure existing and future rows have a valid timestamp. Updated the Prisma schema to reflect this change and provide compatibility for legacy data and raw inserts. --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Benny Joo <sldisek783@gmail.com> Co-authored-by: emrysal <me@alexvanandel.com>
Summary
This pull request introduces a new feature to manage calendar cache data, including the ability to view cache status and delete cached data. It also includes several supporting updates to repositories, APIs, and UI components. Below is a summary of the most important changes grouped by theme.
New Feature: Calendar Cache Management
deleteCachemutation to the TRPCcalendarsRouter, enabling users to delete cached calendar data by credential ID. ([packages/trpc/server/routers/viewer/calendars/_router.tsxR27-R33](https://github.com/calcom/cal.com/pull/22532/files#diff-9e053175cc6dfb5717313e0587a730fff132f9d3c1200204f0ce8dac53a19280R27-R33))deleteCacheHandlerto handle cache deletion logic, including validation of user access to the specified credential. ([packages/trpc/server/routers/viewer/calendars/deleteCache.handler.tsR1-R33](https://github.com/calcom/cal.com/pull/22532/files#diff-572888b8e0555167a5787847f29d5a46623eff170491acc0654e916f5b4afd18R1-R33))connectedCalendarsHandlerto enrich calendar data with cache status (cacheUpdatedAt) by querying theCalendarCacheRepository. ([packages/trpc/server/routers/viewer/calendars/connectedCalendars.handler.tsR27-R39](https://github.com/calcom/cal.com/pull/22532/files#diff-3f6a556ad60f26d0162770fcd81b5bddeb6ab0437552ac792045c3cd2608d710R27-R39))UI Enhancements
CredentialActionsDropdowncomponent to display cache status and provide options to delete cached data or disconnect integrations. ([packages/features/apps/components/CredentialActionsDropdown.tsxR1-R134](https://github.com/calcom/cal.com/pull/22532/files#diff-c78273434b95ab8276bb5eb24d9bc088b10af029388bdcd08cbe478f44269b31R1-R134))DisconnectIntegrationcomponent withCredentialActionsDropdownin theSelectedCalendarsSettingsWebWrapperUI, integrating the new cache management functionality. ([[1]](https://github.com/calcom/cal.com/pull/22532/files#diff-831b0874e07f01721f87926262c5c9674ff9d7443741dfb71ceb849656345b00L5-R5),[[2]](https://github.com/calcom/cal.com/pull/22532/files#diff-831b0874e07f01721f87926262c5c9674ff9d7443741dfb71ceb849656345b00L70-L81),[[3]](https://github.com/calcom/cal.com/pull/22532/files#diff-831b0874e07f01721f87926262c5c9674ff9d7443741dfb71ceb849656345b00L125-L135))Repository and Database Updates
getCacheStatusByCredentialIdsmethod to theCalendarCacheRepositoryand its mock implementation to fetch cache statuses for multiple credentials. ([[1]](https://github.com/calcom/cal.com/pull/22532/files#diff-b36c72c0db751ba0cafe234dfa150817672869825333c22b074c4977a6135b8dR30-R32),[[2]](https://github.com/calcom/cal.com/pull/22532/files#diff-ceffbae9ef3da413495feac73a341672e77ffaf493cf67ada0b637ead80ded38R26-R30),[[3]](https://github.com/calcom/cal.com/pull/22532/files#diff-4cf8d3089fad7b6c8fe4172d8d42147f136b65baf30b726e57b9b10d179d4a99R172-R188))updateManyByCredentialIdmethod in theSelectedCalendarRepositoryto update multiple calendars by credential ID. ([packages/lib/server/repository/selectedCalendar.tsR400-R406](https://github.com/calcom/cal.com/pull/22532/files#diff-ccb4eecfa701e5b0c7d6ba87dcc550cdf3700a63ee252849045611599ecb9273R400-R406))updatedAtcolumn to theCalendarCachetable in the database schema and Prisma model to track the last update timestamp. ([[1]](https://github.com/calcom/cal.com/pull/22532/files#diff-9f597bd98bbcfdcf4861ee7bf0c238e7dfe54b456ceb69b852aaf3979c4102cfR1-R8),[[2]](https://github.com/calcom/cal.com/pull/22532/files#diff-56fa4d384ba6fb94b130e9eb42c5cad00734b025ebd6c197f76873469725ae87R1718))Localization and Strings
[apps/web/public/static/locales/en/common.jsonR3376-R3382](https://github.com/calcom/cal.com/pull/22532/files#diff-57de4b8e5231f1d699891d98b0381d56e9e24537b0ca5420d1fba4f0597370bcR3376-R3382))Miscellaneous
package.jsonto replacets-nodewithnpx tsxfor running thedev:cronscript. ([apps/web/package.jsonL11-R11](https://github.com/calcom/cal.com/pull/22532/files#diff-14b60f636e1a2b0061da57aaf231cb1ed15a5dc0c592425ed82e58fec95d42d8L11-R11))Review & Testing Checklist for Human
🔴 High Priority (5 items)
trpc.viewer.calendars.deleteCache.useMutation()but this mutation implementation is not visible in the PR changes. Check if this endpoint exists or needs to be created.cacheUpdatedAttimestamps are correctly formatted and displayed only for Google Calendar credentials with actual cache data.getCacheStatusByCredentialIds()returns accurate data and the credential-to-cache mapping works properly in the UI.Recommended Test Plan:
/apps/installed/calendarDiagram
%%{ init : { "theme" : "default" }}%% graph TD UI["CredentialActionsDropdown.tsx<br/>(New Component)"]:::major-edit Handler["connectedCalendars.handler.ts<br/>(Updated tRPC Handler)"]:::major-edit RepoInterface["calendar-cache.repository.interface.ts<br/>(Updated Interface)"]:::minor-edit RepoImpl["calendar-cache.repository.ts<br/>(Updated Implementation)"]:::minor-edit RepoMock["calendar-cache.repository.mock.ts<br/>(Updated Mock)"]:::minor-edit Translations["common.json<br/>(Added Translation Keys)"]:::minor-edit UI -->|"Uses repository via tRPC"| Handler Handler -->|"Calls getCacheStatusByCredentialIds"| RepoImpl RepoImpl -->|"Implements"| RepoInterface RepoMock -->|"Implements"| RepoInterface UI -->|"Uses translation keys"| Translations subgraph Legend L1[Major Edit]:::major-edit L2[Minor Edit]:::minor-edit L3[Context/No Edit]:::context end classDef major-edit fill:#90EE90 classDef minor-edit fill:#87CEEB classDef context fill:#FFFFFFNotes
cacheUpdatedAtfrom CalendarCache. Consider if SelectedCalendar.updatedAt update should be removed.