Skip to content

Commit 240c214

Browse files
authored
Merge pull request #562 from devtron-labs/feat/template-list
feat: add GenericInfoCard
2 parents 3b0c85f + 677f48c commit 240c214

File tree

6 files changed

+123
-0
lines changed

6 files changed

+123
-0
lines changed

src/Common/Constants.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ export const PATTERNS = {
5151
ALPHANUMERIC_WITH_SPECIAL_CHAR_AND_SLASH: /^[A-Za-z0-9._/-]+$/, // allow alphanumeric,(.) ,(-),(_),(/)
5252
}
5353

54+
const GLOBAL_CONFIG_TEMPLATES_DEVTRON_APP = '/global-config/templates/devtron-apps'
55+
5456
export const URLS = {
5557
LOGIN_SSO: '/login/sso',
5658
PERMISSION_GROUPS: '/global-config/auth/groups',
@@ -81,6 +83,10 @@ export const URLS = {
8183
CONFIG_DRIFT: 'config-drift',
8284
RESOURCE_BROWSER: '/resource-browser',
8385
COMPARE_CLUSTERS: '/compare-clusters',
86+
GLOBAL_CONFIG_TEMPLATES_DEVTRON_APP,
87+
GLOBAL_CONFIG_TEMPLATES_DEVTRON_APP_CREATE: `${GLOBAL_CONFIG_TEMPLATES_DEVTRON_APP}/create`,
88+
// NOTE: using appId since we are re-using AppConfig component
89+
GLOBAL_CONFIG_TEMPLATES_DEVTRON_APP_DETAIL: `${GLOBAL_CONFIG_TEMPLATES_DEVTRON_APP}/detail/:appId`,
8490
}
8591

8692
export const ROUTES = {
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { cloneElement } from 'react'
2+
import { Link } from 'react-router-dom'
3+
import { GenericInfoCardProps } from './types'
4+
import { getClassNameForBorderVariant } from './utils'
5+
6+
const GenericInfoCard = ({
7+
title,
8+
description,
9+
author,
10+
isLoading,
11+
borderVariant,
12+
Icon,
13+
onClick,
14+
linkProps,
15+
}: GenericInfoCardProps) => {
16+
const IconElement = isLoading ? <div className="shimmer" /> : Icon
17+
18+
const renderShimmerContent = () => (
19+
<>
20+
<div className="icon-dim-40 dc__no-shrink br-6">
21+
<div className="shimmer shimmer__fill-dimensions" />
22+
</div>
23+
24+
<div className="flexbox-col dc__gap-8 flex-grow-1">
25+
<div className="flexbox-col dc__gap-2">
26+
<span className={isLoading ? 'shimmer w-300' : ''} />
27+
<span className={isLoading ? 'shimmer w-150 pt-2' : ''} />
28+
</div>
29+
30+
<span className={isLoading ? 'shimmer w-600' : ''} />
31+
</div>
32+
</>
33+
)
34+
35+
const renderContent = () => (
36+
<div className={`flexbox dc__gap-16 p-12 bg__primary ${getClassNameForBorderVariant(borderVariant)}`}>
37+
{isLoading ? (
38+
renderShimmerContent()
39+
) : (
40+
<>
41+
{cloneElement(IconElement, {
42+
className: `${IconElement.props?.className ?? ''} icon-dim-40 dc__no-shrink br-6 dc__fill-available-space`,
43+
})}
44+
45+
<div className="flexbox-col dc__gap-8 flex-grow-1">
46+
<div className="flexbox-col">
47+
<h3 className="fw-6 fs-13 lh-20 cn-9 m-0">{title}</h3>
48+
<h4 className="fw-4 fs-12 lh-16 cn-7 m-0">By {author}</h4>
49+
</div>
50+
51+
<p className="fw-4 fs-12 lh-16 cn-7 m-0">{description}</p>
52+
</div>
53+
</>
54+
)}
55+
</div>
56+
)
57+
58+
if (!linkProps && !onClick) {
59+
return renderContent()
60+
}
61+
62+
if (linkProps) {
63+
return <Link {...linkProps}>{renderContent()}</Link>
64+
}
65+
66+
return (
67+
<button type="button" onClick={onClick} className="dc__unset-button-styles">
68+
{renderContent()}
69+
</button>
70+
)
71+
}
72+
73+
export default GenericInfoCard
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { type GenericInfoCardProps, GenericInfoCardBorderVariant } from './types'
2+
export { default as GenericInfoCard } from './GenericInfoCard.component'
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { MouseEventHandler, ReactElement } from 'react'
2+
import { LinkProps } from 'react-router-dom'
3+
4+
type BaseGenericInfoCardProps = {
5+
title: string
6+
description: string
7+
author: string
8+
Icon: ReactElement
9+
} & (
10+
| {
11+
onClick?: never
12+
linkProps?: Pick<LinkProps, 'to' | 'target' | 'rel'>
13+
}
14+
| {
15+
onClick?: MouseEventHandler<HTMLButtonElement>
16+
linkProps?: never
17+
}
18+
)
19+
20+
export enum GenericInfoCardBorderVariant {
21+
ROUNDED = 'rounded',
22+
NONE = 'none',
23+
}
24+
25+
export type GenericInfoCardProps = { borderVariant: GenericInfoCardBorderVariant } & (
26+
| ({
27+
isLoading: true
28+
} & Partial<BaseGenericInfoCardProps>)
29+
| ({
30+
isLoading?: boolean
31+
} & BaseGenericInfoCardProps)
32+
)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { GenericInfoCardBorderVariant } from './types'
2+
3+
export const getClassNameForBorderVariant = (variant: GenericInfoCardBorderVariant) => {
4+
if (variant === GenericInfoCardBorderVariant.NONE) {
5+
return ''
6+
}
7+
8+
return 'br-4 dc__border-n1'
9+
}

src/Shared/Components/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,4 @@ export * from './VirtualizedList'
7474
export * from './TargetPlatforms'
7575
export * from './UnsavedChanges'
7676
export * from './UnsavedChangesDialog'
77+
export * from './GenericInfoCard'

0 commit comments

Comments
 (0)