Skip to content

Commit 2dfd797

Browse files
authored
Merge pull request #627 from devtron-labs/feat/license-manager
feat: add license card and license info modal
2 parents 1d47d27 + 19d35b3 commit 2dfd797

File tree

17 files changed

+270
-13
lines changed

17 files changed

+270
-13
lines changed

src/Assets/IconV2/ic-key.svg

Lines changed: 19 additions & 0 deletions
Loading

src/Assets/IconV2/ic-timer.svg

Lines changed: 19 additions & 0 deletions
Loading

src/Common/Constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,7 @@ export const DATE_TIME_FORMATS = {
400400
TWELVE_HOURS_EXPORT_FORMAT: 'DD-MMM-YYYY hh.mm A',
401401
DD_MMM_YYYY_HH_MM: 'DD MMM YYYY, hh:mm',
402402
DD_MMM_YYYY: 'DD MMM YYYY',
403+
'DD/MM/YYYY': 'DD/MM/YYYY',
403404
}
404405

405406
export const SEMANTIC_VERSION_DOCUMENTATION_LINK = 'https://semver.org/'

src/Shared/Components/ConfirmationModal/ConfirmationModal.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ const ConfirmationModalBody = ({
8484
return (
8585
<Backdrop onEscape={shouldCloseOnEscape ? handleCloseWrapper : noop}>
8686
<motion.div
87-
className={`${isLandscapeView ? 'w-500' : 'w-400'} confirmation-modal border__secondary flexbox-col br-8 bg__primary dc__m-auto mt-40 w-400`}
87+
className={`${isLandscapeView ? 'w-500' : 'w-400'} confirmation-modal border__secondary flexbox-col br-8 bg__primary dc__m-auto mt-40`}
8888
exit={{ y: 100, opacity: 0, scale: 0.75, transition: { duration: 0.35 } }}
8989
initial={{ y: 100, opacity: 0, scale: 0.75 }}
9090
animate={{ y: 0, opacity: 1, scale: 1 }}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { ClipboardButton } from '@Common/index'
2+
import { ReactComponent as ICChatSupport } from '@IconsV2/ic-chat-circle-dots.svg'
3+
import { DevtronLicenseCardProps, ENTERPRISE_SUPPORT_LINK, LicenseStatus } from '@Shared/index'
4+
import { Button, ButtonVariantType } from '../Button'
5+
import { Icon } from '../Icon'
6+
import { getLicenseColorsAccordingToStatus, getTTLInHumanReadableFormat } from './utils'
7+
import './licenseCard.scss'
8+
9+
export const DevtronLicenseCard = ({
10+
enterpriseName,
11+
licenseKey,
12+
licenseSuffix,
13+
expiryDate,
14+
licenseStatus,
15+
isTrial,
16+
ttl,
17+
}: DevtronLicenseCardProps) => {
18+
const { bgColor, textColor } = getLicenseColorsAccordingToStatus(licenseStatus)
19+
const remainingTime = getTTLInHumanReadableFormat(ttl)
20+
const remainingTimeString = ttl < 0 ? `Expired ${remainingTime} ago` : `${remainingTime} remaining`
21+
22+
return (
23+
<div className="flexbox-col p-8 br-16" style={{ backgroundColor: bgColor }}>
24+
<div className="license-card flexbox-col br-12 h-200 bg__tertiary">
25+
<div className="p-20 flexbox-col dc__content-space flex-grow-1">
26+
<div className="flexbox dc__align-items-center dc__content-space">
27+
<span className="font-merriweather cn-9 fs-16 fw-7 lh-1-5 dc__truncate">{enterpriseName}</span>
28+
<Icon name="ic-devtron" color="N900" size={24} />
29+
</div>
30+
<div className="flexbox-col dc__gap-4">
31+
<div className="flexbox dc__align-items-center dc__gap-6">
32+
<Icon name="ic-key" color={null} size={20} />
33+
<div className="flex dc__gap-4 cn-7 fs-16 fw-5 lh-1-5 font-ibm-plex-mono">
34+
<span>&bull;&bull;&bull;&bull;</span>
35+
<span>{licenseSuffix || licenseKey?.slice(-8)}</span>
36+
</div>
37+
{licenseKey && <ClipboardButton content={licenseKey} />}
38+
</div>
39+
<div className="flexbox dc__align-items-center dc__gap-4">
40+
<span>{expiryDate}</span>
41+
<span></span>
42+
<span style={{ color: textColor }}>{remainingTimeString}</span>
43+
</div>
44+
</div>
45+
</div>
46+
{isTrial && (
47+
<span className="trial-license-badge flexbox dc__align-items-center px-20 py-6 cn-9 fs-11 fw-5 lh-1-5">
48+
TRIAL LICENSE
49+
</span>
50+
)}
51+
</div>
52+
{licenseStatus !== LicenseStatus.ACTIVE && (
53+
<div className="p-16 flexbox-col dc__gap-8">
54+
<div className="flexbox dc__gap-8">
55+
<span>
56+
To renew your license mail us at&nbsp;
57+
<a href={`mailto:${ENTERPRISE_SUPPORT_LINK}`}>{ENTERPRISE_SUPPORT_LINK}</a> or contact your
58+
Devtron representative.
59+
</span>
60+
<Icon name={ttl < 0 ? 'ic-timer' : 'ic-error'} color={ttl < 0 ? 'Y500' : 'R500'} size={16} />
61+
</div>
62+
{/* TODO: Add onClick, and common out the button */}
63+
<Button
64+
dataTestId="contact-support"
65+
startIcon={<ICChatSupport />}
66+
text="Contact support"
67+
variant={ButtonVariantType.text}
68+
/>
69+
</div>
70+
)}
71+
</div>
72+
)
73+
}
74+
75+
export default DevtronLicenseCard
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default as DevtronLicenseCard } from './DevtronLicenseCard'
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
.license-card {
2+
border: 1px solid var(--border-secondary-translucent, rgba(255, 255, 255, 0.1));
3+
background: radial-gradient(340.2% 100% at 0% 0%, var(--bg-primary, #0f0f10) 0%, var(--bg-tertiary, #030303) 100%);
4+
box-shadow:
5+
0px 1px 1px 0px rgba(0, 0, 0, 0.04),
6+
0px 2px 6px 0px rgba(0, 0, 0, 0.04),
7+
0px 4px 12px 0px rgba(0, 0, 0, 0.1);
8+
9+
.trial-license-badge {
10+
background-color: var(--bg-hover);
11+
letter-spacing: 0.55px;
12+
border-bottom-left-radius: 12px;
13+
border-bottom-right-radius: 12px;
14+
}
15+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { LicenseStatus } from '@Shared/index'
2+
import moment from 'moment'
3+
4+
export const getLicenseColorsAccordingToStatus = (
5+
licenseStatus: LicenseStatus,
6+
): { bgColor: string; textColor: string } => {
7+
switch (licenseStatus) {
8+
case LicenseStatus.ACTIVE:
9+
return { bgColor: 'var(--G100)', textColor: 'var(--G500)' }
10+
case LicenseStatus.REMINDER_THRESHOLD_REACHED:
11+
return { bgColor: 'var(--Y100)', textColor: 'var(--Y700)' }
12+
default:
13+
return { bgColor: 'var(--R100)', textColor: 'var(--R500)' }
14+
}
15+
}
16+
17+
export const getTTLInHumanReadableFormat = (ttl: number): string =>
18+
moment.duration(Math.abs(ttl), 'seconds').humanize(false)

src/Shared/Components/Header/HelpNav.tsx

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { ReactComponent as Feedback } from '../../../Assets/Icon/ic-feedback.svg
2626
import { ReactComponent as Discord } from '../../../Assets/Icon/ic-discord-fill.svg'
2727
import { ReactComponent as File } from '../../../Assets/Icon/ic-file-text.svg'
2828
import { useMainContext } from '../../Providers'
29+
import { Icon } from '../Icon'
2930

3031
const HelpNav = ({
3132
className,
@@ -35,7 +36,7 @@ const HelpNav = ({
3536
setGettingStartedClicked,
3637
showHelpCard,
3738
}: HelpNavType) => {
38-
const { currentServerInfo } = useMainContext()
39+
const { currentServerInfo, handleOpenLicenseInfoDialog } = useMainContext()
3940
const isEnterprise = currentServerInfo?.serverInfo?.installationType === InstallationType.ENTERPRISE
4041
const FEEDBACK_FORM_ID = `UheGN3KJ#source=${window.location.hostname}`
4142

@@ -44,14 +45,12 @@ const HelpNav = ({
4445
name: 'View documentation',
4546
link: DOCUMENTATION_HOME_PAGE,
4647
icon: File,
47-
showSeparator: true,
4848
},
4949

5050
{
5151
name: 'Join discord community',
5252
link: DISCORD_LINK,
5353
icon: Discord,
54-
showSeparator: isEnterprise,
5554
},
5655
...(isEnterprise ? EnterpriseHelpOptions : OSSHelpOptions),
5756
]
@@ -75,7 +74,7 @@ const HelpNav = ({
7574
<div onClick={stopPropagation} className="help-card__option help-card__link flex left cn-9">
7675
<Feedback />
7776
<SliderButton
78-
className="dc__transparent help-card__option-name ml-12 cn-9 fs-14"
77+
className="dc__transparent ml-12 cn-9 fs-14"
7978
id={FEEDBACK_FORM_ID}
8079
onClose={toggleHelpCard}
8180
autoClose={2000}
@@ -92,7 +91,6 @@ const HelpNav = ({
9291

9392
const renderHelpOptions = (): JSX.Element => (
9493
<>
95-
{' '}
9694
{CommonHelpOptions.map((option, index) => (
9795
<Fragment key={option.name}>
9896
<a
@@ -105,12 +103,22 @@ const HelpNav = ({
105103
onClick={handleHelpOptions}
106104
>
107105
<option.icon />
108-
<div className="help-card__option-name ml-12 cn-9 fs-14">{option.name}</div>
106+
<div className="ml-12 cn-9 fs-14">{option.name}</div>
109107
</a>
110108
{isEnterprise && index === 1 && (
111-
<div className="help__enterprise pl-8 pb-4-imp pt-4-imp dc__gap-12 flexbox dc__align-items-center h-28">
112-
Enterprise Support
113-
</div>
109+
<>
110+
<button
111+
type="button"
112+
className="dc__transparent help-card__option flexbox dc__align-items-center cn-9 dc__gap-12 fs-14"
113+
onClick={handleOpenLicenseInfoDialog}
114+
>
115+
<Icon name="ic-devtron" color="N600" size={20} />
116+
About Devtron
117+
</button>
118+
<div className="help__enterprise pl-8 pb-4-imp pt-4-imp dc__gap-12 flexbox dc__align-items-center h-28">
119+
Enterprise Support
120+
</div>
121+
</>
114122
)}
115123
</Fragment>
116124
))}
@@ -128,7 +136,7 @@ const HelpNav = ({
128136
onClick={onClickGettingStarted}
129137
>
130138
<GettingStartedIcon className="scn-6" />
131-
<div className="help-card__option-name ml-12 cn-9 fs-14" data-testid="getting-started-link">
139+
<div className="ml-12 cn-9 fs-14" data-testid="getting-started-link">
132140
Getting started
133141
</div>
134142
</NavLink>

src/Shared/Components/Header/constants.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ export const OSSHelpOptions: HelpOptionType[] = [
3939
name: 'Chat with support',
4040
link: DISCORD_LINK,
4141
icon: Chat,
42-
showSeparator: true,
4342
},
4443

4544
{

0 commit comments

Comments
 (0)