From ca2acd1577b45a71e7cc11a40eb1a82a1f3f85ec Mon Sep 17 00:00:00 2001 From: Arun Jain Date: Wed, 13 Aug 2025 14:18:00 +0530 Subject: [PATCH 1/6] feat: add support for freemium license --- .../Components/GenericModal/constants.ts | 1 + src/Shared/Components/GenericModal/types.ts | 2 +- src/Shared/Components/Header/HelpButton.tsx | 2 +- src/Shared/Components/Header/utils.ts | 8 +- .../Components/License/DevtronLicenseCard.tsx | 112 +++++++++++++----- src/Shared/Components/License/types.ts | 4 +- src/Shared/Components/License/utils.tsx | 15 ++- src/Shared/types.ts | 2 + 8 files changed, 108 insertions(+), 38 deletions(-) diff --git a/src/Shared/Components/GenericModal/constants.ts b/src/Shared/Components/GenericModal/constants.ts index 6f821f0cc..bef8d8813 100644 --- a/src/Shared/Components/GenericModal/constants.ts +++ b/src/Shared/Components/GenericModal/constants.ts @@ -17,6 +17,7 @@ import { GenericModalProps } from './types' export const MODAL_WIDTH_TO_CLASS_NAME_MAP: Record = { + 450: 'w-450', 500: 'w-500', 600: 'w-600', 800: 'w-800', diff --git a/src/Shared/Components/GenericModal/types.ts b/src/Shared/Components/GenericModal/types.ts index 9a0e46c3d..9f3417cda 100644 --- a/src/Shared/Components/GenericModal/types.ts +++ b/src/Shared/Components/GenericModal/types.ts @@ -28,7 +28,7 @@ export interface GenericModalProps extends Partial { export const getHelpActionMenuOptions = ({ isEnterprise, - isTrial, + isTrialOrFreemium, }: { isEnterprise: boolean - isTrial: boolean + isTrialOrFreemium: boolean }): HelpButtonActionMenuProps['options'] => [ { items: COMMON_HELP_ACTION_MENU_ITEMS, @@ -56,7 +56,9 @@ export const getHelpActionMenuOptions = ({ ? [ { groupLabel: 'Enterprise Support', - items: isTrial ? ENTERPRISE_TRIAL_HELP_ACTION_MENU_ITEMS : ENTERPRISE_HELP_ACTION_MENU_ITEMS, + items: isTrialOrFreemium + ? ENTERPRISE_TRIAL_HELP_ACTION_MENU_ITEMS + : ENTERPRISE_HELP_ACTION_MENU_ITEMS, }, ] : [ diff --git a/src/Shared/Components/License/DevtronLicenseCard.tsx b/src/Shared/Components/License/DevtronLicenseCard.tsx index d463f0a8c..8f4952c92 100644 --- a/src/Shared/Components/License/DevtronLicenseCard.tsx +++ b/src/Shared/Components/License/DevtronLicenseCard.tsx @@ -23,6 +23,7 @@ import { ClipboardButton, getTTLInHumanReadableFormat } from '@Common/index' import { CONTACT_SUPPORT_LINK, ENTERPRISE_SUPPORT_LINK } from '@Shared/constants' import { AppThemeType } from '@Shared/Providers' import { getThemeOppositeThemeClass } from '@Shared/Providers/ThemeProvider/utils' +import { LicensingErrorCodes } from '@Shared/types' import { Button, ButtonComponentType, ButtonVariantType } from '../Button' import { Icon } from '../Icon' @@ -33,6 +34,69 @@ import './licenseCard.scss' const DAMPEN_FACTOR = 50 +const LicenseCardSubText = ({ + isFreemium, + licenseStatus, + licenseStatusError, +}: Pick) => { + if (licenseStatus === LicenseStatus.ACTIVE && !isFreemium) { + return null + } + + const isLicenseValid = licenseStatus !== LicenseStatus.EXPIRED && !licenseStatusError + const freemiumLimitReached = licenseStatusError?.code === LicensingErrorCodes.ClusterLimitExceeded + + return licenseStatus !== LicenseStatus.ACTIVE ? ( +
+
+ {freemiumLimitReached ? ( +
+ Multiple Clusters Detected + + Your account is connected to multiple clusters, which isn’t allowed on the freemium plan. + Upgrade to an Enterprise license or contact us. + +
+ ) : ( + + To renew your license mail us at  + {ENTERPRISE_SUPPORT_LINK} or contact your + Devtron representative. + + )} + +
+ {freemiumLimitReached && ( +
+ ) : ( +
+ Unlimited single cluster usage + +
+ ) +} + export const DevtronLicenseCard = ({ enterpriseName, licenseKey, @@ -40,14 +104,15 @@ export const DevtronLicenseCard = ({ expiryDate, licenseStatus, isTrial, + isFreemium, ttl, appTheme, handleCopySuccess, + licenseStatusError, }: DevtronLicenseCardProps) => { const { bgColor, textColor } = getLicenseColorsAccordingToStatus(licenseStatus) const remainingTime = getTTLInHumanReadableFormat(ttl) const remainingTimeString = ttl < 0 ? `Expired ${remainingTime} ago` : `${remainingTime} remaining` - const isLicenseValid = licenseStatus !== LicenseStatus.EXPIRED const isThemeDark = appTheme === AppThemeType.dark const cardRef = useRef(null) @@ -130,43 +195,30 @@ export const DevtronLicenseCard = ({ )}
- {expiryDate} - · - {remainingTimeString} + + {isFreemium ? 'VALID FOREVER' : expiryDate} + + {!isFreemium && ( + <> + · + {remainingTimeString} + + )}
- {isTrial && ( + {(isTrial || isFreemium) && ( - TRIAL LICENSE + {isFreemium ? 'FREEMIUM' : 'TRIAL'} LICENSE )} - {licenseStatus !== LicenseStatus.ACTIVE && ( -
-
- - To renew your license mail us at  - {ENTERPRISE_SUPPORT_LINK} or contact your - Devtron representative. - - -
-
- )} + ) } diff --git a/src/Shared/Components/License/types.ts b/src/Shared/Components/License/types.ts index 878971301..b4afa95b5 100644 --- a/src/Shared/Components/License/types.ts +++ b/src/Shared/Components/License/types.ts @@ -15,7 +15,7 @@ */ import { AppThemeType } from '@Shared/Providers' -import { DevtronLicenseBaseDTO, DevtronLicenseDTO } from '@Shared/types' +import { DevtronLicenseBaseDTO, DevtronLicenseDTO, LicenseErrorStruct } from '@Shared/types' export enum LicenseStatus { ACTIVE = 'ACTIVE', @@ -29,7 +29,9 @@ export type DevtronLicenseCardProps = { ttl: number licenseStatus: LicenseStatus isTrial: boolean + isFreemium: boolean appTheme: AppThemeType + licenseStatusError: LicenseErrorStruct } & ( | { licenseKey: string diff --git a/src/Shared/Components/License/utils.tsx b/src/Shared/Components/License/utils.tsx index fc6d78dcb..19e2a6bb2 100644 --- a/src/Shared/Components/License/utils.tsx +++ b/src/Shared/Components/License/utils.tsx @@ -54,8 +54,17 @@ export const parseDevtronLicenseDTOIntoLicenseCardData = , currentUserEmail?: isCentralDashboard extends true ? string : never, ): Omit => { - const { isTrial, expiry, ttl, reminderThreshold, organisationMetadata, license, claimedByUserDetails } = - licenseDTO || {} + const { + isTrial, + expiry, + ttl, + reminderThreshold, + organisationMetadata, + license, + claimedByUserDetails, + isFreemium, + licenseStatusError, + } = licenseDTO || {} return { enterpriseName: organisationMetadata?.name || 'Devtron Enterprise', @@ -63,6 +72,8 @@ export const parseDevtronLicenseDTOIntoLicenseCardData = Date: Wed, 13 Aug 2025 14:23:13 +0530 Subject: [PATCH 2/6] chore: version bump --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 70f1111b6..5c065bb28 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@devtron-labs/devtron-fe-common-lib", - "version": "1.19.0", + "version": "1.19.0-beta-3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@devtron-labs/devtron-fe-common-lib", - "version": "1.19.0", + "version": "1.19.0-beta-3", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 3740eefd6..8030f7b7c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@devtron-labs/devtron-fe-common-lib", - "version": "1.19.0", + "version": "1.19.0-beta-3", "description": "Supporting common component library", "type": "module", "main": "dist/index.js", From d2e9fbb0852e6fc8be7c8aea11833a3a7483f315 Mon Sep 17 00:00:00 2001 From: Arun Jain Date: Wed, 13 Aug 2025 15:09:08 +0530 Subject: [PATCH 3/6] chore: add css for mail button casing --- package-lock.json | 4 ++-- package.json | 2 +- .../Components/License/DevtronLicenseCard.tsx | 20 ++++++++++--------- .../Components/License/licenseCard.scss | 16 +++++++++++---- 4 files changed, 26 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5c065bb28..e9cbe0245 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@devtron-labs/devtron-fe-common-lib", - "version": "1.19.0-beta-3", + "version": "1.19.0-beta-4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@devtron-labs/devtron-fe-common-lib", - "version": "1.19.0-beta-3", + "version": "1.19.0-beta-4", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 8030f7b7c..ca856971f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@devtron-labs/devtron-fe-common-lib", - "version": "1.19.0-beta-3", + "version": "1.19.0-beta-4", "description": "Supporting common component library", "type": "module", "main": "dist/index.js", diff --git a/src/Shared/Components/License/DevtronLicenseCard.tsx b/src/Shared/Components/License/DevtronLicenseCard.tsx index 8f4952c92..3dcbc5414 100644 --- a/src/Shared/Components/License/DevtronLicenseCard.tsx +++ b/src/Shared/Components/License/DevtronLicenseCard.tsx @@ -71,14 +71,16 @@ const LicenseCardSubText = ({ /> {freemiumLimitReached && ( -