Skip to content

Commit 5c5deb9

Browse files
authored
Merge pull request #2879 from devtron-labs/feat/git-icon-replacement
feat: git repo url handling
2 parents 9b03cad + f3a9e94 commit 5c5deb9

File tree

24 files changed

+397
-196
lines changed

24 files changed

+397
-196
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"private": true,
55
"homepage": "/dashboard",
66
"dependencies": {
7-
"@devtron-labs/devtron-fe-common-lib": "1.19.0-pre-5",
7+
"@devtron-labs/devtron-fe-common-lib": "1.19.4-pre-0",
88
"@esbuild-plugins/node-globals-polyfill": "0.2.3",
99
"@rjsf/core": "^5.13.3",
1010
"@rjsf/utils": "^5.13.3",

src/Pages/App/Configurations/WorkflowEditor/CreateCICDPipeline/CIStepperContent.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ export const CIStepperContent = ({
162162
<InfoBlock variant="success" description="Build pipeline is created" size={ComponentSizeType.medium} />
163163
)}
164164
{materials.map((material, index) => {
165-
const { id, name, type, isRegex, value, regex, gitMaterialId } = material
165+
const { id, name, type, isRegex, value, regex, gitMaterialId, url } = material
166166

167167
const isBranchRegex = type === SourceTypeMap.BranchRegex || isRegex
168168
const isBranchFixed = type === SourceTypeMap.BranchFixed && !isRegex
@@ -183,6 +183,7 @@ export const CIStepperContent = ({
183183
<Fragment key={id}>
184184
<SourceMaterialsSelector
185185
repoName={name}
186+
gitURL={url}
186187
sourceTypePickerProps={{
187188
inputId: 'ci-pipeline-sourceType',
188189
label: 'Source Type',

src/Pages/App/Configurations/WorkflowEditor/SourceMaterialsSelector/SourceMaterialsSelector.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,20 @@
1414
* limitations under the License.
1515
*/
1616

17-
import { ComponentSizeType, CustomInput, Icon, SelectPicker } from '@devtron-labs/devtron-fe-common-lib'
17+
import { ComponentSizeType, CustomInput, GitProviderIcon, SelectPicker } from '@devtron-labs/devtron-fe-common-lib'
1818

1919
import { SourceMaterialsSelectorProps } from './types'
2020

2121
export const SourceMaterialsSelector = ({
2222
repoName,
2323
sourceTypePickerProps,
2424
branchInputProps,
25+
gitURL,
2526
}: SourceMaterialsSelectorProps) => (
2627
<div className="flexbox-col dc__gap-8">
2728
{repoName && (
2829
<div className="flex left dc__gap-8">
29-
<Icon name="ic-git" color={null} size={24} />
30+
<GitProviderIcon gitRepoUrl={gitURL} size={24} />
3031
<p className="m-0 fs-13 lh-20 fw-6 cn-9 dc__truncate">{repoName}</p>
3132
</div>
3233
)}

src/Pages/App/Configurations/WorkflowEditor/SourceMaterialsSelector/types.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,9 @@
1414
* limitations under the License.
1515
*/
1616

17-
import { CustomInputProps, SelectPickerProps } from '@devtron-labs/devtron-fe-common-lib'
17+
import { CustomInputProps, MaterialType, SelectPickerProps } from '@devtron-labs/devtron-fe-common-lib'
1818

19-
export interface SourceMaterialsSelectorProps {
20-
repoName?: string
19+
type CommonSourceTypeProps = {
2120
sourceTypePickerProps: Omit<
2221
SelectPickerProps<string | number, false>,
2322
'required' | 'isClearable' | 'closeMenuOnSelect' | 'size'
@@ -26,3 +25,13 @@ export interface SourceMaterialsSelectorProps {
2625
hideInput?: boolean
2726
}
2827
}
28+
29+
export type SourceMaterialsSelectorProps =
30+
| (CommonSourceTypeProps & {
31+
repoName: string
32+
gitURL: MaterialType['url']
33+
})
34+
| (CommonSourceTypeProps & {
35+
repoName?: never
36+
gitURL?: never
37+
})

src/Pages/GlobalConfigurations/ClustersAndEnvironments/ClusterList.tsx

Lines changed: 77 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ import {
3333
GenericFilterEmptyState,
3434
getSelectPickerOptionByValue,
3535
Icon,
36-
noop,
3736
numberComparatorBySortOrder,
3837
OptionType,
3938
PaginationEnum,
@@ -55,6 +54,7 @@ import { importComponentFromFELibrary } from '@Components/common'
5554
import { URLS } from '@Config/routes'
5655
import CreateCluster from '@Pages/GlobalConfigurations/ClustersAndEnvironments/CreateCluster/CreateCluster.component'
5756
import { CreateClusterTypeEnum } from '@Pages/GlobalConfigurations/ClustersAndEnvironments/CreateCluster/types'
57+
import { UpgradeToEnterpriseDialog } from '@Pages/Shared/UpgradeToEnterprise'
5858

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

8686
const ClusterList = () => {
87-
const { isSuperAdmin } = useMainContext()
87+
const { isSuperAdmin, licenseData } = useMainContext()
8888
const isK8sClient = window._env_.K8S_CLIENT
89+
const isFreemium = licenseData?.isFreemium ?? false
8990

9091
const { push } = useHistory()
9192
const { search } = useLocation()
@@ -121,6 +122,7 @@ const ClusterList = () => {
121122
)
122123

123124
const [showUnmappedEnvs, setShowUnmappedEnvs] = useState(false)
125+
const [showUpgradeToEnterprise, setShowUpgradeToEnterprise] = useState(false)
124126

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

245247
const isEnvironmentsView = selectedTab === ClusterEnvTabs.ENVIRONMENTS
246248
const isClusterEnvListLoading = clusterListLoading || envListLoading
249+
const isClusterAdditionAllowed =
250+
!isFreemium || clusterListResult?.length < licenseData?.moduleLimits.maxAllowedClusters
247251

248252
// Early return for non super admin users
249253
if (!isK8sClient && !isSuperAdmin) {
@@ -338,15 +342,76 @@ const ClusterList = () => {
338342
)
339343
}
340344

345+
const handleOpenUpgradeDialog = () => {
346+
setShowUpgradeToEnterprise(true)
347+
}
348+
349+
const handleCloseUpgradeDialog = () => {
350+
setShowUpgradeToEnterprise(false)
351+
}
352+
353+
const renderAddEnvButton = () => (
354+
<Button
355+
dataTestId="add-environment-button"
356+
linkProps={{
357+
to: {
358+
pathname: `${URLS.GLOBAL_CONFIG_CLUSTER}${URLS.CREATE_ENVIRONMENT}`,
359+
search,
360+
},
361+
}}
362+
component={ButtonComponentType.link}
363+
startIcon={<Icon name="ic-add" color={null} />}
364+
size={ComponentSizeType.medium}
365+
text="Add Environment"
366+
/>
367+
)
368+
369+
const renderAddClusterButton = () => (
370+
<Button
371+
dataTestId="add-cluster-button"
372+
component={ButtonComponentType.link}
373+
startIcon={<Icon name="ic-link" color={null} />}
374+
size={ComponentSizeType.medium}
375+
text="Connect Cluster"
376+
{...(isClusterAdditionAllowed
377+
? {
378+
component: ButtonComponentType.link,
379+
linkProps: {
380+
to: generatePath(URLS.GLOBAL_CONFIG_CREATE_CLUSTER, {
381+
type: CreateClusterTypeEnum.CONNECT_CLUSTER,
382+
}),
383+
search,
384+
},
385+
}
386+
: {
387+
component: ButtonComponentType.button,
388+
onClick: handleOpenUpgradeDialog,
389+
})}
390+
/>
391+
)
392+
393+
const renderAddClusterRoute = () =>
394+
isClusterAdditionAllowed ? (
395+
<Route path={URLS.GLOBAL_CONFIG_CREATE_CLUSTER}>
396+
<CreateCluster
397+
handleReloadClusterList={reloadClusterList}
398+
handleRedirectOnModalClose={handleRedirectToClusterList}
399+
/>
400+
</Route>
401+
) : null
402+
341403
if (clusterListResult && !clusterListResult.length) {
342404
return (
343-
<GenericEmptyState
344-
title="Manage Clusters and Environments"
345-
subTitle="It looks like you haven't set up any Kubernetes clusters yet. Start by adding your first cluster and environment."
346-
isButtonAvailable
347-
renderButton={noop}
348-
image={NoClusterImg}
349-
/>
405+
<>
406+
<GenericEmptyState
407+
title="Manage Clusters and Environments"
408+
subTitle="It looks like you haven't set up any Kubernetes clusters yet. Start by adding your first cluster and environment."
409+
isButtonAvailable
410+
renderButton={renderAddClusterButton}
411+
image={NoClusterImg}
412+
/>
413+
{renderAddClusterRoute()}
414+
</>
350415
)
351416
}
352417

@@ -394,23 +459,7 @@ const ClusterList = () => {
394459
keyboardShortcut="/"
395460
/>
396461
{ManageCategoryButton && <ManageCategoryButton search={search} />}
397-
<Button
398-
dataTestId={isEnvironmentsView ? 'add-environment-button' : 'add-cluster-button'}
399-
linkProps={{
400-
to: {
401-
pathname: isEnvironmentsView
402-
? `${URLS.GLOBAL_CONFIG_CLUSTER}${URLS.CREATE_ENVIRONMENT}`
403-
: generatePath(URLS.GLOBAL_CONFIG_CREATE_CLUSTER, {
404-
type: CreateClusterTypeEnum.CONNECT_CLUSTER,
405-
}),
406-
search,
407-
},
408-
}}
409-
component={ButtonComponentType.link}
410-
startIcon={<Icon name={isEnvironmentsView ? 'ic-add' : 'ic-link'} color={null} />}
411-
size={ComponentSizeType.medium}
412-
text={isEnvironmentsView ? 'Add Environment' : 'Connect Cluster'}
413-
/>
462+
{isEnvironmentsView ? renderAddEnvButton() : renderAddClusterButton()}
414463
{isEnvironmentsView && (
415464
<ActionMenu
416465
id="additional-options-action-menu"
@@ -451,13 +500,9 @@ const ClusterList = () => {
451500
{/* Body */}
452501
{renderList()}
453502
{/* Modals and Routes */}
503+
<UpgradeToEnterpriseDialog open={showUpgradeToEnterprise} handleClose={handleCloseUpgradeDialog} />
454504
{ManageCategories && <ManageCategories />}
455-
<Route path={URLS.GLOBAL_CONFIG_CREATE_CLUSTER}>
456-
<CreateCluster
457-
handleReloadClusterList={reloadClusterList}
458-
handleRedirectOnModalClose={handleRedirectToClusterList}
459-
/>
460-
</Route>
505+
{renderAddClusterRoute()}
461506
<Route path={COMMON_URLS.GLOBAL_CONFIG_EDIT_CLUSTER}>
462507
<EditCluster
463508
clusterList={clusterListResult ?? []}

src/Pages/License/ActivateLicense.tsx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,12 @@ const ActivateLicense = () => {
5757

5858
// licenseDataError.code === 404 means, oss and licensing does not exist
5959
// In case licenseStatusError is null, license is valid
60-
if (licenseDataError?.code === API_STATUS_CODES.NOT_FOUND || !licenseData.licenseStatusError) {
60+
if (licenseDataError?.code === API_STATUS_CODES.NOT_FOUND || !licenseData?.licenseStatusError) {
6161
redirectToLogin()
6262
return
6363
}
6464

65-
if (licenseData?.licenseStatusError.code === LicensingErrorCodes.LicKeyNotFound) {
65+
if (licenseData?.licenseStatusError?.code === LicensingErrorCodes.LicKeyNotFound) {
6666
setShowActivateDialog(true)
6767
}
6868
}, [isLoading, licenseData])
@@ -91,11 +91,17 @@ const ActivateLicense = () => {
9191
<div className="fs-20 lh-1-5 fw-7 cn-9 font-merriweather dc__truncate">
9292
{licenseData.enterpriseName}
9393
</div>
94-
<div className="fs-16 lh-1-5 cr-5 fw-4">Your license key is no longer valid</div>
94+
<div className="fs-16 lh-1-5 cr-5 fw-4">
95+
{licenseData.isFreemium &&
96+
licenseData.licenseStatusError?.code === LicensingErrorCodes.ClusterLimitExceeded
97+
? 'Freemium Limit Reached'
98+
: 'Your license key is no longer valid'}
99+
</div>
95100
</div>
96101
</div>
97102
{licenseData.licenseStatusError &&
98-
licenseData.licenseStatusError.code !== LicensingErrorCodes.LicenseExpired ? (
103+
licenseData.licenseStatusError.code !== LicensingErrorCodes.LicenseExpired &&
104+
licenseData.licenseStatusError.code !== LicensingErrorCodes.ClusterLimitExceeded ? (
99105
<InfoBlock
100106
heading="Need help?"
101107
description={
@@ -124,7 +130,9 @@ const ActivateLicense = () => {
124130
licenseStatus={licenseData.licenseStatus}
125131
isTrial={licenseData.isTrial}
126132
licenseSuffix={licenseData.licenseSuffix}
133+
isFreemium={licenseData.isFreemium}
127134
appTheme={appTheme}
135+
licenseStatusError={licenseData.licenseStatusError}
128136
/>
129137
)}
130138
<div className="flex dc__content-space">
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import {
2+
Button,
3+
ButtonComponentType,
4+
ButtonStyleType,
5+
ButtonVariantType,
6+
ComponentSizeType,
7+
CONTACT_SALES_LINK,
8+
GenericModal,
9+
Icon,
10+
} from '@devtron-labs/devtron-fe-common-lib'
11+
12+
const ENTERPRISE_PLAN_OFFERINGS = [
13+
'Unlimited clusters',
14+
'Managed Devtron installation',
15+
'Priority support',
16+
'Contribute to our roadmap',
17+
'Early access to enterprise features & more…',
18+
]
19+
20+
const UpgradeToEnterpriseDialog = ({ open, handleClose }: { open: boolean; handleClose: () => void }) => (
21+
<GenericModal
22+
name="upgrade-to-enterprise"
23+
open={open}
24+
width={450}
25+
borderRadius={16}
26+
onClose={handleClose}
27+
onEscape={handleClose}
28+
>
29+
<GenericModal.Body>
30+
<div
31+
className="p-32 flexbox-col dc__gap-32"
32+
style={{
33+
background:
34+
'linear-gradient(183deg, var(--bg-primary) 5.64%, var(--bg-primary, #FFF) 41.13%, var(--B100) 76.62%, var(--V200) 94.36%)',
35+
}}
36+
>
37+
<div className="flexbox-col dc__gap-16">
38+
<div className="flexbox dc__content-space dc__align-start">
39+
<Icon name="ic-upgrade-enterprise" size={64} color={null} />
40+
<Button
41+
dataTestId="close-upgrade-dialog"
42+
icon={<Icon name="ic-close-large" color={null} />}
43+
variant={ButtonVariantType.secondary}
44+
style={ButtonStyleType.negativeGrey}
45+
onClick={handleClose}
46+
ariaLabel="close-upgrade-dialog"
47+
showAriaLabelInTippy={false}
48+
size={ComponentSizeType.medium}
49+
/>
50+
</div>
51+
<div className="flexbox-col dc__gap-8">
52+
<h1 className="fs-24 lh-1-5 fw-7 cn-9 m-0 font-merriweather">Upgrade to Enterprise Plan</h1>
53+
<div className="flexbox-col dc__gap-20 fs-16 fw-4 cn-9 lh-1-5">
54+
<span>
55+
Freemium plan allows managing the Devtron host cluster along with one additional
56+
cluster.
57+
</span>
58+
<span>Switch to Enterprise plan to scale without limits.</span>
59+
</div>
60+
</div>
61+
</div>
62+
<div className="flexbox-col border__primary-translucent bg__primary br-12 shadow__card--10">
63+
<div className="flexbox-col dc__gap-16 p-20">
64+
<span className="fs-15 fw-6 lh-1-5 cn-9">What’s included</span>
65+
<div className="flexbox-col dc__gap-8">
66+
{ENTERPRISE_PLAN_OFFERINGS.map((description) => (
67+
<div key={description} className="flexbox dc__gap-8 dc__align-items-center">
68+
<Icon name="ic-check" color="G500" size={20} />
69+
<span className="fs-13 lh-20 fw-4 cn-9">{description}</span>
70+
</div>
71+
))}
72+
</div>
73+
</div>
74+
<div className="divider__secondary--horizontal" />
75+
<div className="p-20 flexbox-col dc__gap-20">
76+
<div className="flexbox-col dc__gap-4">
77+
<span className="fs-15 fw-6 lh-1-5 cn-9">Unlock Devtron&apos;s Full Potential</span>
78+
<span className="fs-13 hw-4 lh-1-5 cn-9">
79+
Scale your infrastructure, accelerate your teams, and get the resources you need to
80+
grow.
81+
</span>
82+
</div>
83+
<Button
84+
dataTestId="upgrade-to-enterprise"
85+
text="Contact to upgrade"
86+
endIcon={<Icon name="ic-arrow-right" color={null} />}
87+
component={ButtonComponentType.anchor}
88+
anchorProps={{
89+
href: CONTACT_SALES_LINK,
90+
}}
91+
/>
92+
</div>
93+
</div>
94+
</div>
95+
</GenericModal.Body>
96+
</GenericModal>
97+
)
98+
99+
export default UpgradeToEnterpriseDialog
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default as UpgradeToEnterpriseDialog } from './UpgradeToEnterpriseDialog'

0 commit comments

Comments
 (0)