Skip to content

Commit c69a977

Browse files
committed
Merge branch 'main' into stable-dt19-v1
2 parents 1716548 + b1eb28f commit c69a977

File tree

13 files changed

+178
-122
lines changed

13 files changed

+178
-122
lines changed

src/components/app/details/appDetails/utils.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -698,7 +698,7 @@ export const processDeploymentStatusDetailsData = (
698698
deploymentData.deploymentStatusText = 'Failed'
699699
deploymentData.deploymentStatusBreakdown.APP_HEALTH.displaySubText = 'Failed'
700700
} else if (data?.wfrStatus === 'Progressing') {
701-
deploymentData.deploymentStatus = DEPLOYMENT_STATUS.PROGRESSING
701+
deploymentData.deploymentStatus = DEPLOYMENT_STATUS.INPROGRESS
702702
deploymentData.deploymentStatusText = 'In progress'
703703
}
704704
}

src/components/external-apps/ExternalAppService.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ export interface ChartMetadata {
8181
notes?: string
8282
}
8383

84-
interface HelmReleaseStatus {
84+
export interface HelmReleaseStatus {
8585
status: string,
8686
message: string,
8787
description: string

src/components/userGroups/Group.tsx

Lines changed: 85 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
1-
import React, { useState, useEffect, useContext, useRef } from 'react';
2-
import { deepEqual } from '../common';
1+
import React, { useState, useEffect, useContext, useRef } from 'react'
2+
import { deepEqual } from '../common'
33
import { showError, Progressing, DeleteDialog, ResizableTextarea } from '@devtron-labs/devtron-fe-common-lib'
4-
import { saveGroup, deleteGroup } from './userGroup.service';
4+
import { saveGroup, deleteGroup } from './userGroup.service'
55

66
import {
77
DirectPermissionsRoleFilter,
88
ChartGroupPermissionsFilter,
99
EntityTypes,
1010
ActionTypes,
1111
CreateGroup,
12-
} from './userGroups.types';
13-
import './UserGroup.scss';
14-
import { toast } from 'react-toastify';
15-
import AppPermissions from './AppPermissions';
16-
import { ACCESS_TYPE_MAP, SERVER_MODE } from '../../config';
17-
import { mainContext } from '../common/navigation/NavigationRoutes';
12+
} from './userGroups.types'
13+
import './UserGroup.scss'
14+
import { toast } from 'react-toastify'
15+
import AppPermissions from './AppPermissions'
16+
import { ACCESS_TYPE_MAP, SERVER_MODE } from '../../config'
17+
import { mainContext } from '../common/navigation/NavigationRoutes'
1818
import { ReactComponent as Warning } from '../../assets/icons/ic-warning.svg'
19-
import { excludeKeyAndClusterValue } from './K8sObjectPermissions/K8sPermissions.utils';
19+
import { excludeKeyAndClusterValue } from './K8sObjectPermissions/K8sPermissions.utils'
2020

2121
export default function GroupForm({
2222
id = null,
@@ -28,72 +28,72 @@ export default function GroupForm({
2828
cancelCallback,
2929
}) {
3030
// id null is for create
31-
const { serverMode } = useContext(mainContext);
32-
const [directPermission, setDirectPermission] = useState<DirectPermissionsRoleFilter[]>([]);
31+
const { serverMode } = useContext(mainContext)
32+
const [directPermission, setDirectPermission] = useState<DirectPermissionsRoleFilter[]>([])
3333
const [chartPermission, setChartPermission] = useState<ChartGroupPermissionsFilter>({
3434
entity: EntityTypes.CHART_GROUP,
3535
action: ActionTypes.VIEW,
3636
entityName: [],
37-
});
38-
const [submitting, setSubmitting] = useState(false);
39-
const [k8sPermission, setK8sPermission] = useState<any[]>([]);
40-
const [name, setName] = useState({ value: '', error: '' });
41-
const [description, setDescription] = useState('');
42-
const [deleteConfirmationModal, setDeleteConfirmationModal] = useState(false);
37+
})
38+
const [submitting, setSubmitting] = useState(false)
39+
const [k8sPermission, setK8sPermission] = useState<any[]>([])
40+
const [name, setName] = useState({ value: '', error: '' })
41+
const [description, setDescription] = useState('')
42+
const [deleteConfirmationModal, setDeleteConfirmationModal] = useState(false)
4343
const currentK8sPermissionRef = useRef<any[]>([])
4444

4545
function isFormComplete(): boolean {
46-
let isComplete: boolean = true;
46+
let isComplete: boolean = true
4747
const tempPermissions = directPermission.reduce((agg, curr) => {
4848
if (curr.team && curr.entityName.length === 0) {
49-
isComplete = false;
50-
curr.entityNameError = 'Applications are mandatory';
49+
isComplete = false
50+
curr.entityNameError = 'Applications are mandatory'
5151
}
5252
if (curr.team && curr.environment.length === 0) {
53-
isComplete = false;
54-
curr.environmentError = 'Environments are mandatory';
53+
isComplete = false
54+
curr.environmentError = 'Environments are mandatory'
5555
}
56-
agg.push(curr);
57-
return agg;
58-
}, []);
56+
agg.push(curr)
57+
return agg
58+
}, [])
5959

6060
if (!isComplete) {
61-
setDirectPermission(tempPermissions);
61+
setDirectPermission(tempPermissions)
6262
}
6363

64-
return isComplete;
64+
return isComplete
6565
}
6666

6767
function getSelectedEnvironments(permission) {
68-
if (permission.accessType === ACCESS_TYPE_MAP.DEVTRON_APPS) {
69-
return permission.environment.find((env) => env.value === '*')
70-
? ''
71-
: permission.environment.map((env) => env.value).join(',');
72-
} else {
73-
let allFutureCluster = {};
74-
let envList = '';
75-
permission.environment.forEach((element) => {
76-
if (element.clusterName === '' && element.value.startsWith('#')) {
77-
const clusterName = element.value.substring(1);
78-
allFutureCluster[clusterName] = true;
79-
envList += (envList !== '' ? ',' : '') + clusterName + '__*';
80-
} else if (element.clusterName !== '' && !allFutureCluster[element.clusterName]) {
81-
envList += (envList !== '' ? ',' : '') + element.value;
82-
}
83-
});
84-
return envList;
85-
}
86-
}
68+
if (permission.accessType === ACCESS_TYPE_MAP.DEVTRON_APPS) {
69+
return permission.environment.find((env) => env.value === '*')
70+
? ''
71+
: permission.environment.map((env) => env.value).join(',')
72+
} else {
73+
let allFutureCluster = {}
74+
let envList = ''
75+
permission.environment.forEach((element) => {
76+
if (element.clusterName === '' && element.value.startsWith('#')) {
77+
const clusterName = element.value.substring(1)
78+
allFutureCluster[clusterName] = true
79+
envList += (envList !== '' ? ',' : '') + clusterName + '__*'
80+
} else if (element.clusterName !== '' && !allFutureCluster[element.clusterName]) {
81+
envList += (envList !== '' ? ',' : '') + element.value
82+
}
83+
})
84+
return envList
85+
}
86+
}
8787

8888
async function handleSubmit(e) {
8989
if (!name.value) {
90-
setName((name) => ({ ...name, error: 'Group name is mandatory' }));
91-
return;
90+
setName((name) => ({ ...name, error: 'Group name is mandatory' }))
91+
return
9292
}
9393
if (!isFormComplete()) {
94-
return;
94+
return
9595
}
96-
setSubmitting(true);
96+
setSubmitting(true)
9797
const payload: CreateGroup = {
9898
id: id || 0,
9999
name: name.value,
@@ -106,72 +106,74 @@ export default function GroupForm({
106106
)
107107
.map((permission) => ({
108108
...permission,
109-
action: permission.action.value,
109+
action: permission.action.configApprover
110+
? `${permission.action.value},configApprover`
111+
: permission.action.value,
110112
team: permission.team.value,
111113
environment: getSelectedEnvironments(permission),
112114
entityName: permission.entityName.find((entity) => entity.value === '*')
113115
? ''
114116
: permission.entityName.map((entity) => entity.value).join(','),
115117
})),
116-
...k8sPermission.map((permission) => ({
117-
...permission,
118-
entity: EntityTypes.CLUSTER,
119-
action: permission.action.value,
120-
cluster: permission.cluster.label,
121-
group: permission.group.value === '*' ? '' : permission.group.value,
122-
kind: permission.kind.value === '*' ? '' : permission.kind.label,
123-
namespace: permission.namespace.value === '*' ? '' : permission.namespace.value,
124-
resource: permission.resource.find((entity) => entity.value === '*')
118+
...k8sPermission.map((permission) => ({
119+
...permission,
120+
entity: EntityTypes.CLUSTER,
121+
action: permission.action.value,
122+
cluster: permission.cluster.label,
123+
group: permission.group.value === '*' ? '' : permission.group.value,
124+
kind: permission.kind.value === '*' ? '' : permission.kind.label,
125+
namespace: permission.namespace.value === '*' ? '' : permission.namespace.value,
126+
resource: permission.resource.find((entity) => entity.value === '*')
125127
? ''
126-
: permission.resource.map((entity) => entity.value).join(',')
127-
}))
128+
: permission.resource.map((entity) => entity.value).join(','),
129+
})),
128130
],
129-
};
131+
}
130132
if (serverMode !== SERVER_MODE.EA_ONLY) {
131133
payload.roleFilters.push({
132134
...chartPermission,
133135
team: '',
134136
environment: '',
135137
entityName: chartPermission.entityName.map((entity) => entity.value).join(','),
136-
});
138+
})
137139
}
138140

139141
try {
140-
const { result } = await saveGroup(payload);
142+
const { result } = await saveGroup(payload)
141143
if (id) {
142144
currentK8sPermissionRef.current = [...k8sPermission].map(excludeKeyAndClusterValue)
143-
updateCallback(index, result);
144-
toast.success('Group updated');
145+
updateCallback(index, result)
146+
toast.success('Group updated')
145147
} else {
146-
createCallback(result);
147-
toast.success('Group createed');
148+
createCallback(result)
149+
toast.success('Group createed')
148150
}
149151
} catch (err) {
150-
showError(err);
152+
showError(err)
151153
} finally {
152-
setSubmitting(false);
154+
setSubmitting(false)
153155
}
154156
}
155157
useEffect(() => {
156-
groupData && populateDataFromAPI(groupData);
157-
}, [groupData]);
158+
groupData && populateDataFromAPI(groupData)
159+
}, [groupData])
158160

159161
async function populateDataFromAPI(data: CreateGroup) {
160-
const { id, name, description } = data;
161-
setName({ value: name, error: '' });
162-
setDescription(description);
162+
const { id, name, description } = data
163+
setName({ value: name, error: '' })
164+
setDescription(description)
163165
}
164166

165167
async function handleDelete() {
166-
setSubmitting(true);
168+
setSubmitting(true)
167169
try {
168-
await deleteGroup(id);
169-
toast.success('Group deleted');
170-
deleteCallback(index);
170+
await deleteGroup(id)
171+
toast.success('Group deleted')
172+
deleteCallback(index)
171173
} catch (err) {
172-
showError(err);
174+
showError(err)
173175
} finally {
174-
setSubmitting(false);
176+
setSubmitting(false)
175177
}
176178
}
177179
return (

src/components/v2/appDetails/AppDetails.component.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
} from '../../app/details/appDetails/appDetails.type'
2222
import { processDeploymentStatusDetailsData } from '../../app/details/appDetails/utils'
2323
import { useSharedState } from '../utils/useSharedState'
24+
import ReleaseStatusEmptyState from './ReleaseStatusEmptyState'
2425

2526
let deploymentStatusTimer = null
2627
const VirtualAppDetailsEmptyState = importComponentFromFELibrary('VirtualAppDetailsEmptyState')
@@ -150,6 +151,27 @@ const AppDetailsComponent = ({
150151
if (isVirtualEnv.current && VirtualAppDetailsEmptyState) {
151152
return <VirtualAppDetailsEmptyState environmentName={appDetails.environmentName} />
152153
}
154+
if (
155+
appDetails &&
156+
!appDetails.resourceTree?.nodes?.length &&
157+
appDetails.deploymentAppType === DeploymentAppTypes.HELM &&
158+
appDetails.helmReleaseStatus &&
159+
appDetails.helmReleaseStatus.status &&
160+
(appDetails.helmReleaseStatus.status.toLowerCase() === DEPLOYMENT_STATUS.FAILED ||
161+
appDetails.helmReleaseStatus.status.toLowerCase() === DEPLOYMENT_STATUS.PROGRESSING ||
162+
appDetails.helmReleaseStatus.status.toLowerCase() === DEPLOYMENT_STATUS.UNKNOWN)
163+
) {
164+
return (
165+
<ReleaseStatusEmptyState
166+
message={appDetails.helmReleaseStatus.message}
167+
description={
168+
appDetails.helmReleaseStatus.status.toLowerCase() === DEPLOYMENT_STATUS.UNKNOWN
169+
? ''
170+
: appDetails.helmReleaseStatus.description
171+
}
172+
/>
173+
)
174+
}
153175
return (
154176
<NodeTreeDetailTab
155177
appDetails={appDetails}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import React from 'react'
2+
import { ReactComponent as InfoIcon } from '../../../assets/icons/info-filled.svg'
3+
function ReleaseStatusEmptyState({ message, description }) {
4+
return (
5+
<div className="bcn-0 flex h-100">
6+
<div className="flex column h-100 w-50">
7+
<InfoIcon className="icon-dim-24 info-icon-n6" />
8+
<span className="mt-8 cn-9 fs-13 fw-6 lh-20 dc__text-center">{message}</span>
9+
{description && <p className="mt-4 cn-7 fs-13 fw-4 lh-20 dc__text-justify">{description}</p>}
10+
</div>
11+
</div>
12+
)
13+
}
14+
15+
export default ReleaseStatusEmptyState

src/components/v2/appDetails/appDetails.type.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { ExternalLink, OptionTypeWithIcon } from '../../externalLinks/ExternalLi
33
import { iLink } from '../utils/tabUtils/link.type'
44
import { DeploymentAppTypes, OptionType } from '@devtron-labs/devtron-fe-common-lib'
55
import { EphemeralForm, EphemeralFormAdvancedType } from './k8Resource/nodeDetail/nodeDetail.type'
6+
import { HelmReleaseStatus } from '../../external-apps/ExternalAppService'
67

78
export interface ApplicationObject extends iLink {
89
selectedNode: string
@@ -180,7 +181,7 @@ export interface AppDetails {
180181
otherEnvironment?: OtherEnvironment[]
181182
projectName?: string
182183
appType?: AppType
183-
additionalData?: any
184+
helmReleaseStatus?: HelmReleaseStatus
184185
clusterId?: number
185186
notes?: string
186187
deploymentAppType?: DeploymentAppTypes

src/components/v2/appDetails/ea/EAAppDetail.component.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ function ExternalAppDetail({ appId, appName, isExternalApp }) {
8080
},
8181
appStoreAppName: helmAppDetail.chartMetadata.chartName,
8282
appStoreAppVersion: helmAppDetail.chartMetadata.chartVersion,
83-
additionalData: helmAppDetail.releaseStatus,
83+
helmReleaseStatus: helmAppDetail.releaseStatus,
8484
clusterId: helmAppDetail.environmentDetails.clusterId,
8585
notes: helmAppDetail.chartMetadata.notes,
8686
}

0 commit comments

Comments
 (0)