Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
72053d5
chore: update version to 1.21.0-beta-5 in package.json and package-lo…
AbhishekA1509 Dec 12, 2025
98fb162
Add new SVG illustrations for installation options
AbhishekA1509 Dec 15, 2025
fab5e6f
chore: bump version to 1.21.0-beta-7 in package.json and package-lock…
AbhishekA1509 Dec 15, 2025
adb0815
chore: bump version to 1.21.0-beta-8 in package.json and package-lock…
AbhishekA1509 Dec 15, 2025
28790f7
chore: bump version to 1.21.0-beta-9 in package.json and package-lock…
AbhishekA1509 Dec 16, 2025
0cec9ee
chore: bump version to 1.21.0-beta-11 in package.json and package-loc…
AbhishekA1509 Dec 16, 2025
a7ea5f8
chore: bump version to 1.21.0-beta-12 in package.json and package-loc…
AbhishekA1509 Dec 16, 2025
f5514b6
chore: bump version to 1.21.0-beta-13 in package.json and package-loc…
AbhishekA1509 Dec 16, 2025
09aee76
Merge branch 'main' of https://github.com/devtron-labs/devtron-fe-com…
AbhishekA1509 Dec 16, 2025
55f04e4
chore: bump version to 1.21.1-beta-0 in package.json and package-lock…
AbhishekA1509 Dec 16, 2025
319dac7
chore: update version to 1.21.1-beta-1 and add new celebration SVG il…
AbhishekA1509 Dec 16, 2025
db4bcbb
chore: bump version to 1.21.1-beta-2; update License component to use…
AbhishekA1509 Dec 17, 2025
a3aa6c5
chore: remove FIXME comment about hiding element in dashboard for non…
AbhishekA1509 Dec 17, 2025
bd9ca15
chore: bump version to 1.21.1-beta-3; update LicenseCard component to…
AbhishekA1509 Dec 18, 2025
6a2efd4
chore: bump version to 1.21.1-beta-5; update creationTime type in Dev…
AbhishekA1509 Dec 18, 2025
443382c
chore: bump version to 1.21.1-beta-6; update LicenseCard component to…
AbhishekA1509 Dec 19, 2025
098ee89
chore: bump version to 1.21.1-beta-7
AbhishekA1509 Dec 19, 2025
cd8ca4f
Merge branch 'main' of https://github.com/devtron-labs/devtron-fe-com…
AbhishekA1509 Dec 19, 2025
aab47cf
chore: bump version to 1.22.1
AbhishekA1509 Dec 19, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@devtron-labs/devtron-fe-common-lib",
"version": "1.22.0",
"version": "1.22.1",
"description": "Supporting common component library",
"type": "module",
"main": "dist/index.js",
Expand Down
149 changes: 149 additions & 0 deletions src/Assets/Illustration/img-celebration.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
40 changes: 40 additions & 0 deletions src/Assets/Illustration/img-install-freemium-saas.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
48 changes: 48 additions & 0 deletions src/Assets/Illustration/img-install-via-aws-marketplace.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
81 changes: 81 additions & 0 deletions src/Assets/Illustration/img-page-not-found.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions src/Shared/Components/Illustration/Illustration.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,33 @@

import CreateBackupSchedule from '@Illustrations/create-backup-schedule.webp'
import CreateBackupSnapshot from '@Illustrations/create-backup-snapshot.webp'
import { ReactComponent as ImgCelebration } from '@Illustrations/img-celebration.svg'
import ImgCode from '@Illustrations/img-code.webp'
import ImgDevtronFreemium from '@Illustrations/img-devtron-freemium.webp'
import { ReactComponent as ImgFolderEmpty } from '@Illustrations/img-folder-empty.svg'
import { ReactComponent as ImgInstallFreemiumSaas } from '@Illustrations/img-install-freemium-saas.svg'
import { ReactComponent as ImgInstallViaAwsMarketplace } from '@Illustrations/img-install-via-aws-marketplace.svg'
import ImgManOnRocket from '@Illustrations/img-man-on-rocket.webp'
import { ReactComponent as ImgMechanicalOperation } from '@Illustrations/img-mechanical-operation.svg'
import { ReactComponent as ImgNoBackupLocation } from '@Illustrations/img-no-backup-location.svg'
import { ReactComponent as ImgNoRestores } from '@Illustrations/img-no-restores.svg'
import ImgNoResult from '@Illustrations/img-no-result.webp'
import { ReactComponent as ImgPageNotFound } from '@Illustrations/img-page-not-found.svg'
import NoClusterCostEnabled from '@Illustrations/no-cluster-cost-enabled.webp'

// eslint-disable-next-line no-restricted-imports
import { IllustrationBase } from './IllustrationBase'
import { IllustrationBaseProps } from './types'

export const illustrationMap = {
'img-celebration': ImgCelebration,
'img-folder-empty': ImgFolderEmpty,
'img-install-freemium-saas': ImgInstallFreemiumSaas,
'img-install-via-aws-marketplace': ImgInstallViaAwsMarketplace,
'img-mechanical-operation': ImgMechanicalOperation,
'img-no-backup-location': ImgNoBackupLocation,
'img-no-restores': ImgNoRestores,
'img-page-not-found': ImgPageNotFound,
'create-backup-schedule': CreateBackupSchedule,
'create-backup-snapshot': CreateBackupSnapshot,
'img-code': ImgCode,
Expand Down
40 changes: 30 additions & 10 deletions src/Shared/Components/License/DevtronLicenseCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { LicensingErrorCodes } from '@Shared/types'

import { Button, ButtonComponentType, ButtonVariantType } from '../Button'
import { Icon } from '../Icon'
import { DevtronLicenseCardProps, LicenseStatus } from './types'
import { DevtronLicenseCardProps, LicenseCardSubTextProps, LicenseStatus } from './types'
import { getLicenseColorsAccordingToStatus } from './utils'

import './licenseCard.scss'
Expand All @@ -49,10 +49,13 @@ const LicenseCardSubText = ({
isFreemium,
licenseStatus,
licenseStatusError,
}: Pick<DevtronLicenseCardProps, 'isFreemium' | 'licenseStatus' | 'licenseStatusError'>) => {
if (isFreemium) {
const freemiumLimitReached = licenseStatusError?.code === LicensingErrorCodes.ClusterLimitExceeded
isFreeForever,
}: LicenseCardSubTextProps) => {
const freemiumLimitReached = isFreemium && licenseStatusError?.code === LicensingErrorCodes.ClusterLimitExceeded
const showFreemiumMessage =
isFreeForever || freemiumLimitReached || (isFreemium && licenseStatus === LicenseStatus.ACTIVE)

if (showFreemiumMessage) {
return (
<div className="p-16 fs-13 lh-1-5 flexbox-col dc__gap-8">
<div className="flexbox dc__gap-8 dc__content-space fs-13 fw-4 lh-20 cn-9">
Expand Down Expand Up @@ -130,10 +133,17 @@ export const DevtronLicenseCard = ({
appTheme,
handleCopySuccess,
licenseStatusError,
isSaasInstance,
}: DevtronLicenseCardProps) => {
const { bgColor, textColor } = getLicenseColorsAccordingToStatus({ isFreemium, licenseStatus, licenseStatusError })
const remainingTime = getTTLInHumanReadableFormat(ttl)
const remainingTimeString = ttl < 0 ? `Expired ${remainingTime} ago` : `${remainingTime} remaining`
const isFreeForever = isFreemium && !isSaasInstance

const { bgColor, textColor } = getLicenseColorsAccordingToStatus({
isFreemium,
licenseStatus,
licenseStatusError,
isSaasInstance,
})

const isThemeDark = appTheme === AppThemeType.dark

const cardRef = useRef<HTMLDivElement>(null)
Expand Down Expand Up @@ -178,6 +188,15 @@ export const DevtronLicenseCard = ({
? useMotionTemplate`linear-gradient(55deg, transparent, rgba(122, 127, 131, ${sheenOpacity}) ${sheenPosition}%, transparent)`
: useMotionTemplate`linear-gradient(55deg, transparent, rgba(255, 255, 255, ${sheenOpacity}) ${sheenPosition}%, transparent)`

const getRemainingTimeString = () => {
if (isFreeForever) {
return null
}

const remainingTime = getTTLInHumanReadableFormat(ttl)
return ttl < 0 ? `Expired ${remainingTime} ago` : `${remainingTime} remaining`
}

return (
<div className="license-card-wrapper flexbox-col p-8 br-16" style={{ backgroundColor: bgColor }}>
<div style={{ perspective: '1000px' }}>
Expand Down Expand Up @@ -217,12 +236,12 @@ export const DevtronLicenseCard = ({
</div>
<div className="flexbox dc__align-items-center dc__gap-4 flex-wrap fs-12">
<span className="font-ibm-plex-mono cn-9">
{isFreemium ? 'VALID FOREVER' : expiryDate}
{isFreeForever ? 'VALID FOREVER' : expiryDate}
</span>
{!isFreemium && (
{!isFreeForever && (
<>
<span className="cn-9">·</span>
<span style={{ color: textColor }}>{remainingTimeString}</span>
<span style={{ color: textColor }}>{getRemainingTimeString()}</span>
</>
)}
</div>
Expand All @@ -239,6 +258,7 @@ export const DevtronLicenseCard = ({
isFreemium={isFreemium}
licenseStatusError={licenseStatusError}
licenseStatus={licenseStatus}
isFreeForever={isFreeForever}
/>
</div>
)
Expand Down
1 change: 1 addition & 0 deletions src/Shared/Components/License/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@
export { default as ActivateLicenseDialog } from './ActivateLicenseDialog'
export { default as DevtronLicenseCard } from './DevtronLicenseCard'
export { ICDevtronWithBorder, default as InstallationFingerprintInfo } from './License.components'
export { activateLicense } from './services'
export * from './types'
export { parseDevtronLicenseData, parseDevtronLicenseDTOIntoLicenseCardData } from './utils'
6 changes: 6 additions & 0 deletions src/Shared/Components/License/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export type DevtronLicenseCardProps = {
isFreemium: boolean
appTheme: AppThemeType
licenseStatusError: LicenseErrorStruct
isSaasInstance: boolean
} & (
| {
licenseKey: string
Expand All @@ -45,6 +46,11 @@ export type DevtronLicenseCardProps = {
}
)

export interface LicenseCardSubTextProps
extends Pick<DevtronLicenseCardProps, 'isFreemium' | 'licenseStatus' | 'licenseStatusError'> {
isFreeForever: boolean
}

export type DevtronLicenseInfo = Omit<DevtronLicenseCardProps, 'appTheme'> &
Pick<DevtronLicenseDTO, 'fingerprint' | 'showLicenseData' | 'licenseStatusError' | 'moduleLimits'>

Expand Down
27 changes: 21 additions & 6 deletions src/Shared/Components/License/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,22 @@ export const getLicenseColorsAccordingToStatus = ({
isFreemium,
licenseStatus,
licenseStatusError,
}: Pick<DevtronLicenseCardProps, 'licenseStatus' | 'isFreemium' | 'licenseStatusError'>): {
isSaasInstance,
}: Pick<DevtronLicenseCardProps, 'licenseStatus' | 'isFreemium' | 'licenseStatusError' | 'isSaasInstance'>): {
bgColor: string
textColor: string
} => {
if (isFreemium) {
const freemiumLimitReached = licenseStatusError?.code === LicensingErrorCodes.ClusterLimitExceeded
return freemiumLimitReached
? { bgColor: 'var(--R100)', textColor: 'var(--R500)' }
: { bgColor: 'var(--G100)', textColor: 'var(--G500)' }
if (freemiumLimitReached) {
return { bgColor: 'var(--R100)', textColor: 'var(--R500)' }
}

if (!isSaasInstance) {
return { bgColor: 'var(--G100)', textColor: 'var(--G500)' }
}
}

switch (licenseStatus) {
case LicenseStatus.ACTIVE:
return { bgColor: 'var(--G100)', textColor: 'var(--G500)' }
Expand Down Expand Up @@ -68,16 +74,24 @@ export const parseDevtronLicenseDTOIntoLicenseCardData = <isCentralDashboard ext
): Omit<DevtronLicenseCardProps, 'appTheme'> => {
const {
isTrial,
expiry,
ttl,
expiry: onPremExpiry,
ttl: onPremTTL,
reminderThreshold,
organisationMetadata,
license,
claimedByUserDetails,
isFreemium,
licenseStatusError,
isSaasInstance,
timeElapsedSinceCreation,
creationTime,
} = licenseDTO || {}

// In case of Saas expiry date is 30 days from creation time
const expiry = isSaasInstance && creationTime ? moment(creationTime).add(30, 'days').toISOString() : onPremExpiry
// For TTL will use timeElapsedSinceCreation to calculate remaining time for Saas license with 30 days validity, since browser time may differ from server time
const ttl = isSaasInstance && timeElapsedSinceCreation ? 30 * 24 * 60 * 60 - timeElapsedSinceCreation : onPremTTL

return {
enterpriseName: organisationMetadata?.name || 'Devtron Enterprise',
expiryDate: expiry ? moment(expiry).format(DATE_TIME_FORMATS['DD/MM/YYYY']) : '',
Expand All @@ -86,6 +100,7 @@ export const parseDevtronLicenseDTOIntoLicenseCardData = <isCentralDashboard ext
isTrial,
isFreemium,
licenseStatusError,
isSaasInstance: !!isSaasInstance,
...(currentUserEmail && currentUserEmail === claimedByUserDetails?.email
? { licenseKey: license }
: { licenseSuffix: license }),
Expand Down
Loading
Loading