Skip to content

Conversation

@hila-f-qodo
Copy link

Evaluation PR

This PR was automatically created for evaluation purposes.

Original PR: calcom#24839

Details

  • Base commit: 02b57eb
  • Head commit: 8cfb324
  • Files changed: 4
  • Total changes: 66

Original Description

What does this PR do?

Visual Demo:

For Free Plan Users:

Screenshots:

Screenshot 2025-11-01 at 1 52 35 PM

and

P.S. We can see the ‘Rating’ template here, but it’s only visible on the local server. I guess this is because it’s self-hosted config, we return true for paid and team plans.
And I haven’t made any changes that would show this ‘Rating’ template for non-team members.
I’ve also checked the main branch, and it’s visible there as well.

Screenshot 2025-11-01 at 1 52 53 PM

Video:

Screen.Recording.2025-11-01.at.1.40.49.PM.mov

Summary by cubic

Upgrade badges are added to workflow selects and Free plan users are prevented from choosing form-based triggers and premium templates. Reminder template stays free and editable without a Team plan. Addresses CAL-6670 and calcom#24826.

  • New Features
    • Disable “Form submitted” triggers and non-Reminder templates for Free plan; show upgrade badges.
    • Make Reminder template free; enable email subject and content editing even without a Team plan.
    • Option lists now include needsTeamsUpgrade and respect hasActiveTeamPlan for gating.

Written for commit 8cfb324. Summary will update automatically on new commits.


Generated by coderabbit evaluation framework

@coderabbitai
Copy link

coderabbitai bot commented Dec 9, 2025

Walkthrough

This change implements team plan upgrade requirements for workflow features across multiple components. A new needsTeamsUpgrade property is added to trigger and action options, computed based on team plan status and feature type (form-submitted triggers and non-reminder templates require upgrades). The getWorkflowTriggerOptions function now accepts a hasPaidPlan parameter to determine upgrade flags. Components including WorkflowDetailsPage, WorkflowStepContainer, and AddActionDialog propagate this property through their option hierarchies, with UI logic updated to disable options and inputs based on upgrade requirements and template type. Trigger handling in WorkflowStepContainer is refactored to use explicit triggerValue extraction for consistent type usage.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: Upgrade badges inside workflows' directly and clearly summarizes the main change—adding upgrade badges to workflow selects to indicate premium features.
Description check ✅ Passed The description relates to the changeset by explaining the purpose of the upgrade badges, listing the key features implemented, and providing context about fixing specific issues and visual demonstrations.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch eval-8cfb324e-1765300614

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
packages/features/ee/workflows/lib/getOptions.ts (2)

44-52: Consider reusing the existing isFormTrigger helper.

The isFormSubmittedTrigger check duplicates logic that already exists in isFormTrigger from actionHelperFunctions.ts (which checks against FORM_TRIGGER_WORKFLOW_EVENTS). Consider reusing it for consistency:

-    const isFormSubmittedTrigger =
-      triggerEvent === WorkflowTriggerEvents.FORM_SUBMITTED ||
-      triggerEvent === WorkflowTriggerEvents.FORM_SUBMITTED_NO_EVENT;
+    const isFormSubmittedTrigger = isFormTrigger(triggerEvent);

65-66: Consider defining a proper return type instead of using type assertion.

The type assertion as { label: string; value: any; needsTeamsUpgrade: boolean } could be avoided by defining an explicit interface or type alias for the template option shape.

+interface TemplateOption {
+  label: string;
+  value: WorkflowTemplates;
+  needsTeamsUpgrade: boolean;
+}
+
 function convertToTemplateOptions(
   t: TFunction,
   hasPaidPlan: boolean,
   templates: readonly WorkflowTemplates[]
-) {
+): TemplateOption[] {
   return templates.map((template) => {
     return {
       label: t(`${template.toLowerCase()}`),
       value: template,
       needsTeamsUpgrade: !hasPaidPlan && template !== WorkflowTemplates.REMINDER,
-    } as { label: string; value: any; needsTeamsUpgrade: boolean };
+    };
   });
 }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5216e88 and 8cfb324.

📒 Files selected for processing (4)
  • packages/features/ee/workflows/components/AddActionDialog.tsx (2 hunks)
  • packages/features/ee/workflows/components/WorkflowDetailsPage.tsx (3 hunks)
  • packages/features/ee/workflows/components/WorkflowStepContainer.tsx (8 hunks)
  • packages/features/ee/workflows/lib/getOptions.ts (3 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

**/*.ts: Avoid dot-suffixes like .service.ts or .repository.ts for new files; reserve .test.ts, .spec.ts, .types.ts for their specific purposes
For Prisma queries: only select data you need using select instead of include to reduce performance overhead and prevent unnecessary data exposure, especially for sensitive fields like credential.key
Never return the credential.key field from tRPC endpoints or APIs
Check if there's any O(n^2) logic in backend code; aim for O(n log n) or O(n) complexity ideally
Flag excessive Day.js use in performance-critical code. Functions like .add, .diff, .isBefore, and .isAfter are slow in timezone mode. Prefer .utc() for better performance. Where possible, use native Date and direct .valueOf() comparisons in hot paths like loops
When changes to API v2 or v1 are made, ensure there are no breaking changes on existing endpoints. Instead, create newly versioned endpoints with updated functionality while keeping old endpoints functional

Files:

  • packages/features/ee/workflows/lib/getOptions.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

**/*.{ts,tsx,js,jsx}: Prefer early returns. It is recommended to throw/return early to ensure null-checks and prevent further nesting
Check if there are circular references introduced. Never allow circular references

Files:

  • packages/features/ee/workflows/lib/getOptions.ts
  • packages/features/ee/workflows/components/WorkflowDetailsPage.tsx
  • packages/features/ee/workflows/components/AddActionDialog.tsx
  • packages/features/ee/workflows/components/WorkflowStepContainer.tsx

⚙️ CodeRabbit configuration file

Flag default exports and encourage named exports. Named exports provide better tree-shaking, easier refactoring, and clearer imports. Exempt main components like pages, layouts, and components that serve as the primary export of a module.

Files:

  • packages/features/ee/workflows/lib/getOptions.ts
  • packages/features/ee/workflows/components/WorkflowDetailsPage.tsx
  • packages/features/ee/workflows/components/AddActionDialog.tsx
  • packages/features/ee/workflows/components/WorkflowStepContainer.tsx
**/*.{ts,tsx,jsx}

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Prefer Composition over Prop Drilling. Instead of relying on prop drilling, use React's children feature

Files:

  • packages/features/ee/workflows/lib/getOptions.ts
  • packages/features/ee/workflows/components/WorkflowDetailsPage.tsx
  • packages/features/ee/workflows/components/AddActionDialog.tsx
  • packages/features/ee/workflows/components/WorkflowStepContainer.tsx
**/*.{tsx,jsx}

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Always use t() for text localization in frontend code; direct text embedding should trigger a warning

Files:

  • packages/features/ee/workflows/components/WorkflowDetailsPage.tsx
  • packages/features/ee/workflows/components/AddActionDialog.tsx
  • packages/features/ee/workflows/components/WorkflowStepContainer.tsx
🧬 Code graph analysis (2)
packages/features/ee/workflows/components/WorkflowDetailsPage.tsx (2)
packages/features/billing/hooks/useHasPaidPlan.ts (1)
  • useHasActiveTeamPlan (41-47)
packages/features/ee/workflows/lib/actionHelperFunctions.ts (1)
  • isFormTrigger (146-148)
packages/features/ee/workflows/components/AddActionDialog.tsx (1)
packages/platform/libraries/index.ts (1)
  • WorkflowActions (36-36)
🔇 Additional comments (12)
packages/features/ee/workflows/components/AddActionDialog.tsx (2)

43-43: LGTM!

The needsTeamsUpgrade optional property is correctly added to the interface, aligning with the upgrade badge feature requirements.


174-184: LGTM!

The options mapping correctly propagates needsTeamsUpgrade and the isOptionDisabled callback properly disables options requiring a team plan upgrade.

packages/features/ee/workflows/components/WorkflowDetailsPage.tsx (1)

6-6: LGTM!

The import and usage of useHasActiveTeamPlan hook is correct.

Also applies to: 47-47

packages/features/ee/workflows/lib/getOptions.ts (1)

34-34: LGTM!

The hasPaidPlan parameter with a default value of false is a safe default that ensures upgrade badges are shown when the plan status is unknown.

packages/features/ee/workflows/components/WorkflowStepContainer.tsx (8)

104-104: LGTM!

The needsTeamsUpgrade optional property correctly added to the actionOptions type within WorkflowStepProps.


375-376: LGTM!

Correctly passing hasActiveTeamPlan to getWorkflowTriggerOptions and getWorkflowTemplateOptions for proper upgrade gating.


383-386: LGTM!

The currentStepTemplate derivation from watched steps and isReminderTemplate check correctly gate editing capabilities for the free Reminder template.


540-574: LGTM!

The refactored trigger handling with explicit triggerValue extraction improves type safety and ensures consistent usage throughout the onChange handler.


594-601: LGTM!

Trigger options correctly mapped with needsTeamsUpgrade and isOptionDisabled properly disables options requiring upgrade.


1293-1304: Verify the SMS action exception for template upgrade gating.

The needsTeamsUpgrade for template options is conditionally set to false when the action is SMS (!isSMSAction(...)). Ensure this exception is intentional and that SMS actions should bypass the team plan requirement for non-Reminder templates.


1338-1338: LGTM!

The email subject TextArea is correctly disabled for users without an active team plan unless they're using the free Reminder template.


1369-1372: LGTM!

The Editor's editable state correctly allows editing when the user has an active team plan, is using SMS action, or has selected the free Reminder template.

Comment on lines +89 to +97
const needsTeamsUpgrade = isFormTrigger(form.getValues("trigger")) && !hasActiveTeamPlan;

return {
...option,
label,
creditsTeamId: teamId,
isOrganization: isOrg,
isCalAi: isCalAIAction(option.value),
needsTeamsUpgrade,
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Consider handling the loading state from useHasActiveTeamPlan.

During the initial load while isPending is true, hasActiveTeamPlan will be falsy, potentially causing a brief flash where upgrade badges appear for users who actually have an active team plan.

Consider destructuring and using isPending to avoid showing upgrade badges during loading:

- const { hasActiveTeamPlan } = useHasActiveTeamPlan();
+ const { hasActiveTeamPlan, isPending } = useHasActiveTeamPlan();
...
- const needsTeamsUpgrade = isFormTrigger(form.getValues("trigger")) && !hasActiveTeamPlan;
+ const needsTeamsUpgrade = isFormTrigger(form.getValues("trigger")) && !isPending && !hasActiveTeamPlan;

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In packages/features/ee/workflows/components/WorkflowDetailsPage.tsx around
lines 89–97, the needsTeamsUpgrade value uses hasActiveTeamPlan which is falsy
while the hook is still loading, causing a flash of upgrade badges; destructure
isPending from useHasActiveTeamPlan and only compute needsTeamsUpgrade when
loading has finished (e.g. set needsTeamsUpgrade = !isPending &&
isFormTrigger(form.getValues("trigger")) && !hasActiveTeamPlan), so while
isPending is true you avoid showing the upgrade badge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Upgrade badges inside worklfows

4 participants