-
-
Notifications
You must be signed in to change notification settings - Fork 286
feat: administration plans UI improvements #3152
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
""" WalkthroughThis update introduces an archiving feature for both cloud and self-hosted enterprise subscription plans, adds a new "archived" property to relevant models, and enhances the administration UI to display subscription counts and plan prices. It includes new API endpoints for archiving plans, new UI components, and updates to the data schema and type definitions. Changes
Sequence Diagram(s)sequenceDiagram
participant AdminUser as Admin User
participant UI as Admin UI
participant API as Backend API
AdminUser->>UI: Views plan list
UI->>API: Fetch plans (with archived & subscription count)
API-->>UI: Return plans data
UI->>AdminUser: Display plans with price, subscription count, archived badge
AdminUser->>UI: Clicks "Archive" on a plan
UI->>AdminUser: Shows confirmation dialog
AdminUser->>UI: Confirms archive
UI->>API: PUT /archive endpoint for plan
API-->>UI: Success response
UI->>AdminUser: Show success message, update UI (plan marked as archived)
Assessment against linked issues
Suggested reviewers
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ 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). (3)
✨ Finishing Touches
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. 🪧 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 (
|
34f4776
to
51e8a45
Compare
There was a problem hiding this 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 (4)
build.gradle (1)
96-99
: Idempotent cleanup added – mirrorignoreExitValue
in the stop task for symmetryThe extra
exec { docker rm … }
block is a welcome improvement: it prevents “container already exists” failures and keeps the task rerunnable.
For consistency (and to avoid a possible build break if the container gets removed out-of-band) consider applying the sameignoreExitValue = true
flag tostopDbChangelogContainer
.task stopDbChangelogContainer(type: Exec) { - commandLine "docker", "rm", "--force", "--volumes", dbSchemaContainerName + ignoreExitValue = true + commandLine "docker", "rm", "--force", "--volumes", dbSchemaContainerName }This keeps both start/stop tasks tolerant to missing containers and avoids noisy CI failures.
webapp/src/ee/billing/component/Plan/PlanArchivedChip.tsx (1)
8-14
: Consider making the data-cy attribute more generic.The hardcoded
data-cy="administration-cloud-plans-item-archived-badge"
appears cloud-specific but this component seems to be generic and reusable. Consider making the data-cy attribute configurable via props or using a more generic identifier.-export function PlanArchivedChip({ isArchived }: { isArchived?: boolean }) { +export function PlanArchivedChip({ + isArchived, + dataCy = "administration-plan-archived-badge" +}: { + isArchived?: boolean; + dataCy?: string; +}) { if (!isArchived) { return null; } return ( <Chip - data-cy="administration-cloud-plans-item-archived-badge" + data-cy={dataCy} size="small" label={<T keyName="administration_plan_archived_badge" />} /> ); }webapp/src/ee/billing/component/Plan/PlanSubscriptionCount.tsx (1)
5-5
: Use strict equality operator.Replace
==
with===
for the comparison to avoid potential type coercion issues.- if (count == 0) { + if (count === 0) {webapp/src/ee/billing/administration/subscriptionPlans/components/planForm/genericFields/PlanArchivedSwitch.tsx (1)
10-10
: Consider making the component more generic.The component is hardcoded to use
CloudPlanFormData
type, which limits its reusability. Since this is in agenericFields
directory, it should ideally work with both cloud and self-hosted EE plan forms.Consider making it generic:
-export const PlanArchivedSwitch: FC<{ isUpdate?: boolean }> = ({ +export const PlanArchivedSwitch: FC<{ isUpdate?: boolean }> = ({ isUpdate, }) => { - const { setFieldValue, values } = useFormikContext<CloudPlanFormData>(); + const { setFieldValue, values } = useFormikContext<{ archived: boolean }>();This would allow the component to work with any form data that has an
archived
field.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (17)
backend/api/src/main/kotlin/io/tolgee/hateoas/ee/SelfHostedEePlanModel.kt
(1 hunks)backend/api/src/main/kotlin/io/tolgee/publicBilling/PublicCloudPlanModel.kt
(1 hunks)build.gradle
(1 hunks)e2e/cypress/support/dataCyType.d.ts
(3 hunks)webapp/src/ee/billing/Subscriptions/cloud/useCloudPlans.tsx
(1 hunks)webapp/src/ee/billing/Subscriptions/selfHosted/PlansSelfHostedList.tsx
(1 hunks)webapp/src/ee/billing/administration/subscriptionPlans/components/planForm/cloud/CloudPlanForm.tsx
(2 hunks)webapp/src/ee/billing/administration/subscriptionPlans/components/planForm/cloud/types.ts
(1 hunks)webapp/src/ee/billing/administration/subscriptionPlans/components/planForm/genericFields/PlanArchivedSwitch.tsx
(1 hunks)webapp/src/ee/billing/administration/subscriptionPlans/components/planForm/selfHostedEe/SelfHostedEePlanForm.tsx
(2 hunks)webapp/src/ee/billing/administration/subscriptionPlans/viewsCloud/AdministrationCloudPlansView.tsx
(4 hunks)webapp/src/ee/billing/administration/subscriptionPlans/viewsSelfHostedEe/AdministrationEePlansView.tsx
(5 hunks)webapp/src/ee/billing/component/Plan/PlanArchivedChip.tsx
(1 hunks)webapp/src/ee/billing/component/Plan/PlanListPriceInfo.tsx
(1 hunks)webapp/src/ee/billing/component/Plan/PlanSubscriptionCount.tsx
(1 hunks)webapp/src/ee/billing/component/Price/PricePrimary.tsx
(2 hunks)webapp/src/service/billingApiSchema.generated.ts
(12 hunks)
🧰 Additional context used
🧠 Learnings (4)
build.gradle (1)
Learnt from: laz-001
PR: tolgee/tolgee-platform#0
File: :0-0
Timestamp: 2025-05-09T01:35:14.224Z
Learning: Changes to PostgreSQL container names, ports, Liquibase changelog paths, and test data directories in the Tolgee platform are often made to provide dedicated resources to parallel test groups (like `ee-test:test` and `server-app:test`), preventing resource congestion and collisions that could lead to deadlocks during testing.
webapp/src/ee/billing/administration/subscriptionPlans/viewsSelfHostedEe/AdministrationEePlansView.tsx (1)
Learnt from: Anty0
PR: tolgee/tolgee-platform#3003
File: webapp/src/ee/glossary/components/GlossaryTermTags.tsx:18-18
Timestamp: 2025-06-04T18:53:24.403Z
Learning: In React 17, use React.VFC for functional components that don't need children props, as React.FC implicitly includes `children?: React.ReactNode`. React.VFC was deprecated in React 18+ where React.FC no longer includes children by default.
webapp/src/ee/billing/administration/subscriptionPlans/components/planForm/genericFields/PlanArchivedSwitch.tsx (1)
Learnt from: Anty0
PR: tolgee/tolgee-platform#3003
File: webapp/src/ee/glossary/components/GlossaryTermTags.tsx:18-18
Timestamp: 2025-06-04T18:53:24.403Z
Learning: In React 17, use React.VFC for functional components that don't need children props, as React.FC implicitly includes `children?: React.ReactNode`. React.VFC was deprecated in React 18+ where React.FC no longer includes children by default.
webapp/src/ee/billing/administration/subscriptionPlans/viewsCloud/AdministrationCloudPlansView.tsx (1)
Learnt from: Anty0
PR: tolgee/tolgee-platform#3003
File: webapp/src/ee/glossary/components/GlossaryTermTags.tsx:18-18
Timestamp: 2025-06-04T18:53:24.403Z
Learning: In React 17, use React.VFC for functional components that don't need children props, as React.FC implicitly includes `children?: React.ReactNode`. React.VFC was deprecated in React 18+ where React.FC no longer includes children by default.
🧬 Code Graph Analysis (5)
webapp/src/ee/billing/administration/subscriptionPlans/components/planForm/cloud/CloudPlanForm.tsx (1)
webapp/src/ee/billing/administration/subscriptionPlans/components/planForm/genericFields/PlanArchivedSwitch.tsx (1)
PlanArchivedSwitch
(7-37)
webapp/src/ee/billing/component/Plan/PlanListPriceInfo.tsx (2)
webapp/src/ee/billing/component/Price/PricePrimary.tsx (1)
PricePrimary
(28-66)webapp/src/colors.tsx (1)
Tooltip
(37-40)
webapp/src/ee/billing/administration/subscriptionPlans/components/planForm/genericFields/PlanArchivedSwitch.tsx (1)
webapp/src/ee/billing/administration/subscriptionPlans/components/planForm/cloud/types.ts (1)
CloudPlanFormData
(24-27)
webapp/src/ee/billing/administration/subscriptionPlans/components/planForm/selfHostedEe/SelfHostedEePlanForm.tsx (1)
webapp/src/ee/billing/administration/subscriptionPlans/components/planForm/genericFields/PlanArchivedSwitch.tsx (1)
PlanArchivedSwitch
(7-37)
webapp/src/service/billingApiSchema.generated.ts (1)
webapp/src/service/apiSchema.generated.ts (2)
operations
(5712-22269)components
(1017-5710)
⏰ 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). (23)
- GitHub Check: E2E testing 🔎 (15, 5)
- GitHub Check: E2E testing 🔎 (15, 4)
- GitHub Check: E2E testing 🔎 (15, 14)
- GitHub Check: E2E testing 🔎 (15, 13)
- GitHub Check: E2E testing 🔎 (15, 12)
- GitHub Check: E2E testing 🔎 (15, 11)
- GitHub Check: E2E testing 🔎 (15, 1)
- GitHub Check: E2E testing 🔎 (15, 10)
- GitHub Check: BT 🔎 (data:test)
- GitHub Check: E2E testing 🔎 (15, 9)
- GitHub Check: E2E testing 🔎 (15, 3)
- GitHub Check: E2E testing 🔎 (15, 8)
- GitHub Check: BT 🔎 (server-app:runStandardTests)
- GitHub Check: E2E testing 🔎 (15, 7)
- GitHub Check: BT 🔎 (server-app:runWebsocketTests)
- GitHub Check: E2E testing 🔎 (15, 2)
- GitHub Check: E2E testing 🔎 (15, 6)
- GitHub Check: BT 🔎 (security:test)
- GitHub Check: E2E testing 🔎 (15, 0)
- GitHub Check: BT 🔎 (server-app:runContextRecreatingTests)
- GitHub Check: BT 🔎 (ee-test:test)
- GitHub Check: BT 🔎 (ktlint:test)
- GitHub Check: BT 🔎 (server-app:runWithoutEeTests)
🔇 Additional comments (27)
webapp/src/ee/billing/component/Price/PricePrimary.tsx (1)
25-25
: LGTM! Well-implemented feature addition.The
noPeriodSwitch
prop addition is correctly implemented with proper typing, default value, and backward compatibility. The logic update appropriately uses the new prop to control period switch display.Also applies to: 34-34, 39-39
webapp/src/ee/billing/component/Plan/PlanListPriceInfo.tsx (2)
16-66
: Excellent component structure and UX design.The component provides a clean interface for displaying pricing information with helpful tooltips. The use of
noPeriodSwitch={true}
is appropriate for list displays, and the tooltip content provides clear yearly and monthly pricing details.
32-32
: Incorrect concern:theme.palette.primaryText
is a valid custom theme property.
- Defined in
webapp/src/custom.d.ts
under the extendedPalette
interface.- Supplied in
webapp/src/ThemeProvider.tsx
asprimaryText: c.primaryText
.- Colors for
primaryText
are configured inwebapp/src/colors.tsx
.No changes needed.
Likely an incorrect or invalid review comment.
webapp/src/ee/billing/Subscriptions/selfHosted/PlansSelfHostedList.tsx (1)
68-68
: LGTM! Consistent archiving feature implementation.The addition of
archived: false
to the hardcoded Enterprise plan is consistent with the broader archiving feature rollout and maintains proper default state.webapp/src/ee/billing/Subscriptions/cloud/useCloudPlans.tsx (1)
64-64
: LGTM! Consistent archiving feature implementation.The addition of
archived: false
to the hardcoded Enterprise plan maintains consistency with the archiving feature across both cloud and self-hosted plans.backend/api/src/main/kotlin/io/tolgee/hateoas/ee/SelfHostedEePlanModel.kt (1)
24-24
: LGTM! Proper backend model extension.The addition of the
archived
property with a default value offalse
is correctly implemented, maintaining backward compatibility while supporting the new archiving feature.backend/api/src/main/kotlin/io/tolgee/publicBilling/PublicCloudPlanModel.kt (1)
16-16
: LGTM! Clean interface extension.The addition of the
archived
property to the interface is simple, well-typed, and consistent with the archiving functionality being implemented.webapp/src/ee/billing/administration/subscriptionPlans/components/planForm/cloud/types.ts (1)
21-21
: LGTM! Consistent interface extension.The addition of the
archived
property maintains consistency with the backend interface and follows proper TypeScript typing conventions.webapp/src/ee/billing/administration/subscriptionPlans/components/planForm/cloud/CloudPlanForm.tsx (2)
10-10
: LGTM! Proper component import.The import path is consistent with the project structure and correctly imports the PlanArchivedSwitch component.
67-70
: LGTM! Clean component integration.The PlanArchivedSwitch is properly integrated into the form with correct prop passing and logical layout using the grid display.
webapp/src/ee/billing/component/Plan/PlanArchivedChip.tsx (1)
4-7
: LGTM! Good conditional rendering pattern.The early return pattern for the null case is clean and follows React best practices.
webapp/src/ee/billing/administration/subscriptionPlans/components/planForm/selfHostedEe/SelfHostedEePlanForm.tsx (1)
15-15
: LGTM! Consistent component import.The import follows the same pattern as in CloudPlanForm, maintaining consistency across the codebase.
e2e/cypress/support/dataCyType.d.ts (1)
43-44
: LGTM! Data-cy identifiers are well-defined.The new test identifiers follow the established naming convention and comprehensively cover the archiving functionality for both cloud and self-hosted EE plans.
Also applies to: 57-57, 71-71
webapp/src/ee/billing/administration/subscriptionPlans/viewsCloud/AdministrationCloudPlansView.tsx (4)
32-36
: Good styling approach for archived plans.The styled component approach for conditional styling is clean and follows Material-UI patterns well.
48-52
: Well-structured mutation hook.The archive mutation hook is properly configured with correct endpoint, method, and cache invalidation.
60-78
: Excellent UX pattern for archiving.The archiving flow implements good UX practices:
- Confirmation dialog to prevent accidental actions
- Clear messaging about the action
- Success feedback to the user
- Proper error handling through the mutation hook
134-168
: Well-organized action buttons layout.The button layout is thoughtfully organized:
- Archive button only shown for non-archived plans
- Logical grouping of actions
- Proper spacing and alignment
- Consistent data-cy attributes for testing
webapp/src/ee/billing/administration/subscriptionPlans/viewsSelfHostedEe/AdministrationEePlansView.tsx (4)
30-31
: Good type update for enhanced plan model.The type update from
SelfHostedEePlanModel
toSelfHostedEePlanAdministrationModel
correctly reflects the schema changes that addarchived
andsubscriptionCount
properties.
33-37
: Consistent styling approach.The styled component matches the cloud plans implementation, ensuring visual consistency across both admin views.
49-79
: Consistent archiving implementation.The archiving functionality is implemented consistently with the cloud plans view, which promotes maintainability and provides a unified user experience.
141-173
: Well-implemented UI enhancements.The UI improvements are consistent with the cloud plans view:
- Subscription count display
- Price information
- Archived status indicators
- Proper action button organization
webapp/src/service/billingApiSchema.generated.ts (6)
27-29
: New archive endpoints follow consistent RESTful patternsThe addition of archive endpoints for both cloud and self-hosted plans maintains consistency with the existing API structure. Both endpoints use PUT method and follow the same path pattern.
Also applies to: 52-54
221-221
: Administration cloud plan model enhanced with archive and subscription trackingThe addition of
archived: boolean
andsubscriptionCount: number
properties provides essential functionality for plan management in the administration interface. The subscription count will be particularly useful for tracking plan usage.Also applies to: 261-262
340-340
: Cloud plan models consistently updated with archive propertyThe
archived
property is properly added to bothCloudPlanModel
andCloudPlanRequest
, ensuring consistency between read and write operations.Also applies to: 375-375
1122-1122
: Self-hosted EE plan models enhanced with archive and subscription trackingAll self-hosted enterprise plan models are consistently updated with the
archived
property and administration models includesubscriptionCount
. This maintains parity with cloud plan functionality.Also applies to: 1162-1163, 1166-1166, 1200-1200
828-829
: New error code added for LLM provider responsesThe addition of
"llm_provider_empty_response"
to the error code union expands error handling capabilities for AI/LLM integrations.
1806-1852
: Archive operation definitions are comprehensive and well-structuredBoth
archivePlan_1
andarchivePlan
operations include:
- Proper path parameters for plan identification
- Complete HTTP status code handling (200, 400, 401, 403, 404)
- Consistent error response types
- Appropriate return types matching the administration models
The operations follow the established patterns used by other plan management endpoints.
Also applies to: 2314-2360
<Box display="grid"> | ||
<PlanArchivedSwitch isUpdate={isUpdate} /> | ||
<PlanPublicSwitchField /> | ||
</Box> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Verify type compatibility of PlanArchivedSwitch with SelfHostedEePlanFormData.
The integration pattern is consistent with CloudPlanForm. However, based on the relevant code snippets, the PlanArchivedSwitch component uses useFormikContext<CloudPlanFormData>()
which may not be compatible with SelfHostedEePlanFormData
used in this form.
🏁 Script executed:
#!/bin/bash
# Description: Check if PlanArchivedSwitch component is properly typed for both form types
# Expected: The component should handle both CloudPlanFormData and SelfHostedEePlanFormData types
# Search for the PlanArchivedSwitch implementation
ast-grep --pattern 'useFormikContext<$_>()'
# Also check the form data types to see if they're compatible
ast-grep --pattern 'interface $_ {
$$$
archived: $_
$$$
}'
Length of output: 4554
I’d like to confirm the exact definitions of both form-data types. Let’s pull in the CloudPlanFormData and SelfHostedEePlanFormData interfaces:
🏁 Script executed:
#!/bin/bash
# Print CloudPlanFormData definition
sed -n '1,200p' webapp/src/ee/billing/administration/subscriptionPlans/components/planForm/cloud/types.ts
# Locate and print SelfHostedEePlanFormData definition
rg -n 'interface SelfHostedEePlanFormData' -A10 webapp/src/ee/billing/administration/subscriptionPlans/components/planForm/selfHostedEe
Length of output: 1099
I want to confirm whether SelfHostedEePlanRequest
actually includes an archived
field. Let’s locate its definition in the generated schema:
🏁 Script executed:
#!/bin/bash
# Locate the generated file(s) that define SelfHostedEePlanRequest
rg -l "SelfHostedEePlanRequest" -t ts
# For each file found, print the definition around it
for file in $(rg -l "SelfHostedEePlanRequest" -t ts); do
echo "=== $file ==="
rg -n "SelfHostedEePlanRequest" -A20 -B5 "$file"
done
Length of output: 3268
Ensure PlanArchivedSwitch supports SelfHostedEePlanFormData
PlanArchivedSwitch currently hardcodes
const { setFieldValue, values } = useFormikContext<CloudPlanFormData>();
but SelfHostedEePlanFormData is an independent generated type (components['schemas']['SelfHostedEePlanRequest']
) whose archived?: boolean
(and other fields) don’t fully match CloudPlanFormData. This mismatch will surface as a TypeScript error when embedding the switch into the SelfHostedEe form.
• File: webapp/src/ee/billing/administration/subscriptionPlans/components/planForm/genericFields/PlanArchivedSwitch.tsx
– Change the generic on useFormikContext<…>()
so it only requires an archived?: boolean
field (e.g. useFormikContext<{ archived?: boolean }>()
), or make the component generic <T extends { archived?: boolean }>
and call useFormikContext<T>()
.
• File: webapp/src/ee/billing/administration/subscriptionPlans/components/planForm/selfHostedEe/SelfHostedEePlanForm.tsx
– Ensure initialValues
includes a default for archived
(e.g. archived: false
) so the switch has a non-undefined value at runtime.
• After these changes, rerun TypeScript to confirm both CloudPlanForm and SelfHostedEePlanForm compile cleanly with the shared switch.
🤖 Prompt for AI Agents
In
webapp/src/ee/billing/administration/subscriptionPlans/components/planForm/genericFields/PlanArchivedSwitch.tsx
around lines 10-30, modify the useFormikContext hook to be generic by defining
the component as <T extends { archived?: boolean }> and calling
useFormikContext<T>() instead of hardcoding CloudPlanFormData. In
webapp/src/ee/billing/administration/subscriptionPlans/components/planForm/selfHostedEe/SelfHostedEePlanForm.tsx
around lines 40-50, update the initialValues object to include archived: false
to ensure the switch has a defined value at runtime. After these changes, run
TypeScript to verify both forms compile without errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
archived: boolean
changed to archived?: boolean
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
@dkrizan That's a good approach! Making the archived
field optional should help with type compatibility. Let me verify that this fully resolves the type compatibility issue between the forms.
🏁 Script executed:
#!/bin/bash
# Check the current type definitions to verify the change
echo "=== Checking type definitions ==="
rg -n "archived.*boolean" webapp/src/ee/billing/administration/subscriptionPlans/components/planForm/
# Check if PlanArchivedSwitch handles undefined values properly
echo "=== Checking PlanArchivedSwitch implementation ==="
cat webapp/src/ee/billing/administration/subscriptionPlans/components/planForm/genericFields/PlanArchivedSwitch.tsx
# Check the generated schema types to confirm the change
echo "=== Checking generated schema types ==="
rg -n "archived.*boolean" webapp/src/service/billingApiSchema.generated.ts
Length of output: 1876
Perfect! Making the archived
field optional is a good step toward resolving the type compatibility issue. However, there are still two remaining issues to fully address:
-
Type Compatibility: The
PlanArchivedSwitch
component is still hardcoded to useCloudPlanFormData
:const { setFieldValue, values } = useFormikContext<CloudPlanFormData>();
This means it won't work with
SelfHostedEePlanFormData
even though both types now have optionalarchived
fields. -
Undefined Value Handling: The component uses
checked={values.archived}
which could beundefined
now that the field is optional. This could cause the switch to behave unexpectedly.
To fully resolve this, you could:
Option 1 - Make PlanArchivedSwitch generic:
const { setFieldValue, values } = useFormikContext<{ archived?: boolean }>();
Option 2 - Handle undefined values properly:
checked={values.archived ?? false}
This would ensure type safety across both form types and handle undefined values gracefully. Would you like me to help implement either of these approaches?
🧬 Code Graph Analysis Results
Relevant snippets for webapp/src/ee/billing/administration/subscriptionPlans/components/planForm/selfHostedEe/SelfHostedEePlanForm.tsx
Snippet from webapp/src/ee/billing/administration/subscriptionPlans/components/planForm/cloud/types.ts
(lines 29-30)
export type SelfHostedEePlanFormData =
components['schemas']['SelfHostedEePlanRequest'];
- Defines the type
SelfHostedEePlanFormData
used as the form data type inSelfHostedEePlanForm
. - This type is an alias for the API schema type
SelfHostedEePlanRequest
. - Changes to optionality of fields like
archived
would be reflected here if the API schema changes.
Snippet from webapp/src/ee/billing/administration/subscriptionPlans/components/planForm/genericFields/PlanArchivedSwitch.tsx
(lines 7-37)
export const PlanArchivedSwitch: FC<{ isUpdate?: boolean }> = ({
isUpdate,
}) => {
const { setFieldValue, values } = useFormikContext<CloudPlanFormData>();
const { t } = useTranslate();
if (!isUpdate) {
return null;
}
return (
<>
<FormControlLabel
control={
<Switch
checked={values.archived}
onChange={() => setFieldValue('archived', !values.archived)}
/>
}
data-cy="administration-plan-field-archived"
label={t('administration_cloud_plan_field_archived')}
/>
{values.archived && (
<Alert severity="warning" sx={{ mt: 1, mb: 4 }}>
<T keyName={'admin_billing_plan_archived_warning'} />
</Alert>
)}
</>
);
};
- React functional component rendering a switch to toggle the
archived
boolean field in the form. - Uses Formik context to read and update the
archived
field value. - Only renders if
isUpdate
prop is true. - Displays a warning alert if the plan is archived.
- The
archived
field is accessed asvalues.archived
and toggled on switch change. - This component is used in
SelfHostedEePlanForm.tsx
and directly relates to thearchived
field behavior.
Snippet from webapp/src/constants/GlobalValidationSchema.tsx
(lines 44-511, excerpt)
- Contains Yup validation schemas for various forms including
EE_PLAN_FORM
. - The
EE_PLAN_FORM
schema validates fields likename
andstripeProductId
. - Although the snippet does not explicitly show validation for
archived
, this file is the central place for form validation rules. - Changes to the optionality of
archived
might require updates here ifarchived
is validated.
Summary of relevance:
- The type definition for the form data (
SelfHostedEePlanFormData
) is relevant to understand the data shape and optionality ofarchived
. - The
PlanArchivedSwitch
component is directly related to thearchived
field UI and form state management. - The global validation schema file is relevant for understanding if and how
archived
is validated in the form.
[End of relevant snippets]
🧠 Learnings used
Learnt from: Anty0
PR: tolgee/tolgee-platform#3003
File: webapp/src/ee/glossary/components/AssignedProjectsSelect.tsx:33-34
Timestamp: 2025-06-04T19:05:18.736Z
Learning: Formik has known type annotation issues where meta.error may be typed incorrectly. This has been reported in https://github.com/jaredpalmer/formik/issues/3994. When working with Formik error handling, using type guards or careful type checking is recommended to work around these type annotation limitations rather than avoiding the `any` cast entirely.
Closes https://github.com/tolgee/billing/issues/181
Summary by CodeRabbit
New Features
Bug Fixes
Chores