Skip to content

Commit eb2ff7f

Browse files
committed
feat: add activate license page in dashboard
1 parent 33c4ae4 commit eb2ff7f

File tree

3 files changed

+163
-8
lines changed

3 files changed

+163
-8
lines changed

src/App.tsx

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,11 @@ import {
4242
} from './components/common'
4343
import { UPDATE_AVAILABLE_TOAST_PROGRESS_BG, URLS } from './config'
4444
import { validateToken } from './services/service'
45+
import ActivateLicense from '@Pages/License/ActivateLicense'
4546

4647
const NavigationRoutes = lazy(() => import('./components/common/navigation/NavigationRoutes'))
4748
const Login = lazy(() => import('./components/login/Login'))
4849
const GenericDirectApprovalModal = importComponentFromFELibrary('GenericDirectApprovalModal')
49-
const ActivateLicense = importComponentFromFELibrary('ActivateLicense', null, 'function')
5050

5151
export default function App() {
5252
const onlineToastRef = useRef(null)
@@ -160,7 +160,6 @@ export default function App() {
160160
}
161161

162162
useEffect(() => {
163-
164163
if (navigator.serviceWorker) {
165164
navigator.serviceWorker.addEventListener('controllerchange', handleControllerChange)
166165
}
@@ -328,7 +327,7 @@ export default function App() {
328327
<div className="full-height-width bg__tertiary">
329328
<Reload />
330329
</div>
331-
) : (
330+
) : (
332331
<ErrorBoundary>
333332
<BreadcrumbStore>
334333
<Switch>
@@ -340,11 +339,9 @@ export default function App() {
340339
/>
341340
</Route>
342341
)}
343-
{ActivateLicense && (
344-
<Route path={CommonURLS.LICENSE_AUTH}>
345-
<ActivateLicense />
346-
</Route>
347-
)}
342+
<Route path={CommonURLS.LICENSE_AUTH}>
343+
<ActivateLicense />
344+
</Route>
348345
{!window._env_.K8S_CLIENT && <Route path="/login" component={Login} />}
349346
<Route path="/" render={() => <NavigationRoutes />} />
350347
<Redirect

src/Pages/License/ActivateLicense.tsx

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
import {
2+
useTheme,
3+
LicensingErrorCodes,
4+
Button,
5+
ButtonVariantType,
6+
DevtronLicenseCard,
7+
DevtronProgressing,
8+
ENTERPRISE_SUPPORT_LINK,
9+
ErrorScreenManager,
10+
Icon,
11+
InfoBlock,
12+
LoginBanner,
13+
URLS,
14+
useAsync,
15+
getHandleOpenURL,
16+
CONTACT_SUPPORT_LINK,
17+
ActivateLicenseDialog,
18+
ICDevtronWithBorder,
19+
API_STATUS_CODES,
20+
} from '@devtron-labs/devtron-fe-common-lib'
21+
import { useEffect, useState } from 'react'
22+
import { useHistory } from 'react-router-dom'
23+
import { getDevtronLicenseInfo } from './service'
24+
25+
const ActivateLicense = () => {
26+
const history = useHistory()
27+
const [isLoading, licenseData, licenseDataError, reloadLicenseData] = useAsync(getDevtronLicenseInfo, [])
28+
const [showActivateDialog, setShowActivateDialog] = useState<boolean>(false)
29+
const { appTheme } = useTheme()
30+
31+
const redirectToLogin = () => {
32+
history.replace(URLS.LOGIN_SSO)
33+
}
34+
35+
useEffect(() => {
36+
if (isLoading) {
37+
return
38+
}
39+
40+
// licenseDataError.code === 404 means, oss and licensing does not exist
41+
// In case licenseStatusError is null, license is valid
42+
if (licenseDataError?.code === API_STATUS_CODES.NOT_FOUND || !licenseData.licenseStatusError) {
43+
redirectToLogin()
44+
return
45+
}
46+
47+
if (licenseData.licenseStatusError.code === LicensingErrorCodes.LicKeyNotFound) {
48+
setShowActivateDialog(true)
49+
}
50+
}, [isLoading, licenseData])
51+
52+
if (isLoading) {
53+
return <DevtronProgressing parentClasses="bg__primary flex full-height-width" classes="icon-dim-80" />
54+
}
55+
56+
if (licenseDataError) {
57+
return (
58+
<div className="full-height-width bg__tertiary">
59+
<ErrorScreenManager code={licenseDataError?.code} reload={reloadLicenseData} />
60+
</div>
61+
)
62+
}
63+
64+
const handleChangeLicense = () => {
65+
setShowActivateDialog(true)
66+
}
67+
68+
const renderInvalidLicenseDialog = () => (
69+
<div className="flexbox-col p-36 dc__gap-32 w-400 border__primary br-12">
70+
<div className="flexbox-col dc__gap-20">
71+
<ICDevtronWithBorder />
72+
<div className="flexbox-col dc__gap-4">
73+
<div className="fs-20 lh-1-5 fw-7 cn-9 font-merriweather dc__truncate">
74+
{licenseData.enterpriseName}
75+
</div>
76+
<div className="fs-16 lh-1-5 cr-5 fw-4">Your license key is no longer valid</div>
77+
</div>
78+
</div>
79+
{licenseData.licenseStatusError &&
80+
licenseData.licenseStatusError.code !== LicensingErrorCodes.LicenseExpired ? (
81+
<InfoBlock
82+
heading="Need help?"
83+
description={
84+
<span>
85+
For further details mail us at&nbsp;
86+
<a href={`mailto:${ENTERPRISE_SUPPORT_LINK}`}>{ENTERPRISE_SUPPORT_LINK}</a> or contact
87+
Devtron Support
88+
</span>
89+
}
90+
variant="help"
91+
buttonProps={{
92+
text: 'Contact Support',
93+
variant: ButtonVariantType.text,
94+
onClick: getHandleOpenURL(CONTACT_SUPPORT_LINK),
95+
dataTestId: 'contact-support',
96+
startIcon: <Icon name="ic-chat-circle-dots" color="B500" size={16} />,
97+
}}
98+
layout="column"
99+
/>
100+
) : (
101+
<DevtronLicenseCard
102+
enterpriseName={licenseData.enterpriseName}
103+
expiryDate={licenseData.expiryDate}
104+
ttl={licenseData.ttl}
105+
licenseStatus={licenseData.licenseStatus}
106+
isTrial={licenseData.isTrial}
107+
licenseSuffix={licenseData.licenseSuffix}
108+
appTheme={appTheme}
109+
/>
110+
)}
111+
<div className="flex dc__content-space">
112+
<span>Have another license key?</span>
113+
<Button
114+
dataTestId="change-license"
115+
text="Change license"
116+
variant={ButtonVariantType.text}
117+
onClick={handleChangeLicense}
118+
/>
119+
</div>
120+
</div>
121+
)
122+
123+
return (
124+
<div className="full-height-width bg__secondary dc__grid-half">
125+
<div className="flexbox p-16">
126+
<LoginBanner />
127+
</div>
128+
<div className="flex">
129+
{showActivateDialog ? (
130+
<ActivateLicenseDialog
131+
fingerprint={licenseData.fingerprint || ''}
132+
enterpriseName={licenseData.enterpriseName}
133+
handleLicenseActivateSuccess={redirectToLogin}
134+
/>
135+
) : (
136+
renderInvalidLicenseDialog()
137+
)}
138+
</div>
139+
</div>
140+
)
141+
}
142+
143+
export default ActivateLicense

src/Pages/License/service.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// NOTE: This API is used to check if the license is valid or not at APP.TSX level
2+
3+
import {
4+
DevtronLicenseDTO,
5+
DevtronLicenseInfo,
6+
get,
7+
parseDevtronLicenseData,
8+
ROUTES,
9+
} from '@devtron-labs/devtron-fe-common-lib'
10+
11+
// Only gives complete response if the license is invalid else return only fingerprint
12+
export const getDevtronLicenseInfo = async (): Promise<DevtronLicenseInfo> => {
13+
const { result } = await get<DevtronLicenseDTO>(ROUTES.LICENSE_DATA, { preventLicenseRedirect: true })
14+
return parseDevtronLicenseData(result)
15+
}

0 commit comments

Comments
 (0)