Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"private": true,
"homepage": "/dashboard",
"dependencies": {
"@devtron-labs/devtron-fe-common-lib": "1.19.0",
"@devtron-labs/devtron-fe-common-lib": "1.19.0-beta-5",
"@esbuild-plugins/node-globals-polyfill": "0.2.3",
"@rjsf/core": "^5.13.3",
"@rjsf/utils": "^5.13.3",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import {
GenericFilterEmptyState,
getSelectPickerOptionByValue,
Icon,
noop,
numberComparatorBySortOrder,
OptionType,
PaginationEnum,
Expand All @@ -55,6 +54,7 @@ import { importComponentFromFELibrary } from '@Components/common'
import { URLS } from '@Config/routes'
import CreateCluster from '@Pages/GlobalConfigurations/ClustersAndEnvironments/CreateCluster/CreateCluster.component'
import { CreateClusterTypeEnum } from '@Pages/GlobalConfigurations/ClustersAndEnvironments/CreateCluster/types'
import { UpgradeToEnterpriseDialog } from '@Pages/Shared/UpgradeToEnterprise'

import { getClusterList, getEnvironmentList } from './cluster.service'
import {
Expand Down Expand Up @@ -84,8 +84,9 @@ const PodSpreadModal = importComponentFromFELibrary('PodSpreadModal', null, 'fun
const HibernationRulesModal = importComponentFromFELibrary('HibernationRulesModal', null, 'function')

const ClusterList = () => {
const { isSuperAdmin } = useMainContext()
const { isSuperAdmin, licenseData } = useMainContext()
const isK8sClient = window._env_.K8S_CLIENT
const isFreemium = licenseData?.isFreemium ?? false

const { push } = useHistory()
const { search } = useLocation()
Expand Down Expand Up @@ -121,6 +122,7 @@ const ClusterList = () => {
)

const [showUnmappedEnvs, setShowUnmappedEnvs] = useState(false)
const [showUpgradeToEnterprise, setShowUpgradeToEnterprise] = useState(false)

const clusterIdVsEnvMap: Record<number, Environment[]> = useMemo(
() =>
Expand Down Expand Up @@ -244,6 +246,8 @@ const ClusterList = () => {

const isEnvironmentsView = selectedTab === ClusterEnvTabs.ENVIRONMENTS
const isClusterEnvListLoading = clusterListLoading || envListLoading
const isClusterAdditionAllowed =
!isFreemium || clusterListResult?.length < licenseData?.moduleLimits.maxAllowedClusters

// Early return for non super admin users
if (!isK8sClient && !isSuperAdmin) {
Expand Down Expand Up @@ -338,15 +342,76 @@ const ClusterList = () => {
)
}

const handleOpenUpgradeDialog = () => {
setShowUpgradeToEnterprise(true)
}

const handleCloseUpgradeDialog = () => {
setShowUpgradeToEnterprise(false)
}

const renderAddEnvButton = () => (
<Button
dataTestId="add-environment-button"
linkProps={{
to: {
pathname: `${URLS.GLOBAL_CONFIG_CLUSTER}${URLS.CREATE_ENVIRONMENT}`,
search,
},
}}
component={ButtonComponentType.link}
startIcon={<Icon name="ic-add" color={null} />}
size={ComponentSizeType.medium}
text="Add Environment"
/>
)

const renderAddClusterButton = () => (
<Button
dataTestId="add-cluster-button"
component={ButtonComponentType.link}
startIcon={<Icon name="ic-link" color={null} />}
size={ComponentSizeType.medium}
text="Connect Cluster"
{...(isClusterAdditionAllowed
? {
component: ButtonComponentType.link,
linkProps: {
to: generatePath(URLS.GLOBAL_CONFIG_CREATE_CLUSTER, {
type: CreateClusterTypeEnum.CONNECT_CLUSTER,
}),
search,
},
}
: {
component: ButtonComponentType.button,
onClick: handleOpenUpgradeDialog,
})}
/>
)

const renderAddClusterRoute = () =>
isClusterAdditionAllowed ? (
<Route path={URLS.GLOBAL_CONFIG_CREATE_CLUSTER}>
<CreateCluster
handleReloadClusterList={reloadClusterList}
handleRedirectOnModalClose={handleRedirectToClusterList}
/>
</Route>
) : null

if (clusterListResult && !clusterListResult.length) {
return (
<GenericEmptyState
title="Manage Clusters and Environments"
subTitle="It looks like you haven't set up any Kubernetes clusters yet. Start by adding your first cluster and environment."
isButtonAvailable
renderButton={noop}
image={NoClusterImg}
/>
<>
<GenericEmptyState
title="Manage Clusters and Environments"
subTitle="It looks like you haven't set up any Kubernetes clusters yet. Start by adding your first cluster and environment."
isButtonAvailable
renderButton={renderAddClusterButton}
image={NoClusterImg}
/>
{renderAddClusterRoute()}
</>
)
}

Expand Down Expand Up @@ -394,23 +459,7 @@ const ClusterList = () => {
keyboardShortcut="/"
/>
{ManageCategoryButton && <ManageCategoryButton search={search} />}
<Button
dataTestId={isEnvironmentsView ? 'add-environment-button' : 'add-cluster-button'}
linkProps={{
to: {
pathname: isEnvironmentsView
? `${URLS.GLOBAL_CONFIG_CLUSTER}${URLS.CREATE_ENVIRONMENT}`
: generatePath(URLS.GLOBAL_CONFIG_CREATE_CLUSTER, {
type: CreateClusterTypeEnum.CONNECT_CLUSTER,
}),
search,
},
}}
component={ButtonComponentType.link}
startIcon={<Icon name={isEnvironmentsView ? 'ic-add' : 'ic-link'} color={null} />}
size={ComponentSizeType.medium}
text={isEnvironmentsView ? 'Add Environment' : 'Connect Cluster'}
/>
{isEnvironmentsView ? renderAddEnvButton() : renderAddClusterButton()}
{isEnvironmentsView && (
<ActionMenu
id="additional-options-action-menu"
Expand Down Expand Up @@ -451,13 +500,9 @@ const ClusterList = () => {
{/* Body */}
{renderList()}
{/* Modals and Routes */}
<UpgradeToEnterpriseDialog open={showUpgradeToEnterprise} handleClose={handleCloseUpgradeDialog} />
{ManageCategories && <ManageCategories />}
<Route path={URLS.GLOBAL_CONFIG_CREATE_CLUSTER}>
<CreateCluster
handleReloadClusterList={reloadClusterList}
handleRedirectOnModalClose={handleRedirectToClusterList}
/>
</Route>
{renderAddClusterRoute()}
<Route path={COMMON_URLS.GLOBAL_CONFIG_EDIT_CLUSTER}>
<EditCluster
clusterList={clusterListResult ?? []}
Expand Down
16 changes: 12 additions & 4 deletions src/Pages/License/ActivateLicense.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,12 @@ const ActivateLicense = () => {

// licenseDataError.code === 404 means, oss and licensing does not exist
// In case licenseStatusError is null, license is valid
if (licenseDataError?.code === API_STATUS_CODES.NOT_FOUND || !licenseData.licenseStatusError) {
if (licenseDataError?.code === API_STATUS_CODES.NOT_FOUND || !licenseData?.licenseStatusError) {
redirectToLogin()
return
}

if (licenseData?.licenseStatusError.code === LicensingErrorCodes.LicKeyNotFound) {
if (licenseData?.licenseStatusError?.code === LicensingErrorCodes.LicKeyNotFound) {
setShowActivateDialog(true)
}
}, [isLoading, licenseData])
Expand Down Expand Up @@ -91,11 +91,17 @@ const ActivateLicense = () => {
<div className="fs-20 lh-1-5 fw-7 cn-9 font-merriweather dc__truncate">
{licenseData.enterpriseName}
</div>
<div className="fs-16 lh-1-5 cr-5 fw-4">Your license key is no longer valid</div>
<div className="fs-16 lh-1-5 cr-5 fw-4">
{licenseData.isFreemium &&
licenseData.licenseStatusError?.code === LicensingErrorCodes.ClusterLimitExceeded
? 'Freemium Limit Reached'
: 'Your license key is no longer valid'}
</div>
</div>
</div>
{licenseData.licenseStatusError &&
licenseData.licenseStatusError.code !== LicensingErrorCodes.LicenseExpired ? (
licenseData.licenseStatusError.code !== LicensingErrorCodes.LicenseExpired &&
licenseData.licenseStatusError.code !== LicensingErrorCodes.ClusterLimitExceeded ? (
<InfoBlock
heading="Need help?"
description={
Expand Down Expand Up @@ -124,7 +130,9 @@ const ActivateLicense = () => {
licenseStatus={licenseData.licenseStatus}
isTrial={licenseData.isTrial}
licenseSuffix={licenseData.licenseSuffix}
isFreemium={licenseData.isFreemium}
appTheme={appTheme}
licenseStatusError={licenseData.licenseStatusError}
/>
)}
<div className="flex dc__content-space">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import {
Button,
ButtonStyleType,
ButtonVariantType,
GenericModal,
Icon,
noop,
} from '@devtron-labs/devtron-fe-common-lib'

import { ReactComponent as ICUpgradeToEnterprise } from './ic-upgrade-enterprise.svg'

const ENTERPRISE_PLAN_OFFERINGS = [
'Unlimited clusters',
'Managed Devtron installation',
'Priority support',
'Contribute to our roadmap',
'Early access to enterprise features & more…',
]

const UpgradeToEnterpriseDialog = ({ open, handleClose }: { open: boolean; handleClose: () => void }) => (
<GenericModal name="upgrade-to-enterprise" open={open} width={450} onClose={noop}>
<GenericModal.Body>
<div
className="p-32 flexbox-col dc__gap-32"
style={{
background:
'linear-gradient(183deg, var(--bg-primary) 5.64%, var(--bg-primary, #FFF) 41.13%, var(--B100) 76.62%, var(--V200) 94.36%)',
}}
>
<div className="flexbox-col dc__gap-16">
<div className="flexbox dc__content-space dc__align-start">
<ICUpgradeToEnterprise className="icon-dim-64" />
<Button
dataTestId="close-upgrade-dialog"
icon={<Icon name="ic-close-large" color={null} />}
variant={ButtonVariantType.secondary}
style={ButtonStyleType.negativeGrey}
onClick={handleClose}
ariaLabel="close-upgrade-dialog"
showAriaLabelInTippy={false}
/>
</div>
<div className="flexbox-col dc__gap-8">
<h1 className="fs-24 lh-1-5 fw-7 cn-9 m-0">Upgrade to Enterprise Plan</h1>
<span className="fs-16 fw-4 lh-1-5 cn-9">
Your freemium plan allows only 1 cluster. Unlock more to scale without limits.
</span>
</div>
</div>
<div className="flexbox-col border__primary-translucent br-12 shadow__card--10">
<div className="flexbox-col dc__gap-16 p-20">
<span className="fs-15 fw-6 lh-1-5 cn-9">What’s included</span>
<div className="flexbox-col dc__gap-8">
{ENTERPRISE_PLAN_OFFERINGS.map((description) => (
<div key={description} className="flexbox dc__gap-8 dc__align-items-center">
<Icon name="ic-check" color="G500" size={20} />
<span className="fs-13 lh-20 fw-4 cn-9">{description}</span>
</div>
))}
</div>
</div>
<div className="divider__primary--horizontal" />
<div className="p-20 flexbox-col dc__gap-20">
<div className="flexbox-col dc__gap-4">
<span className="fs-15 fw-6 lh-1-5 cn-9">Unlock Devtron&apos;s Full Potential</span>
<span className="fs-13 hw-4 lh-1-5 cn-9">
Scale your infrastructure, accelerate your teams, and get the resources you need to
grow.
</span>
</div>
{/* TODO: Add onClick handler */}
<Button
dataTestId="upgrade-to-enterprise"
text="Upgrade Now"
endIcon={<Icon name="ic-arrow-right" color={null} />}
/>
</div>
</div>
</div>
</GenericModal.Body>
</GenericModal>
)

export default UpgradeToEnterpriseDialog
Loading