Skip to content

Commit 27ca8bd

Browse files
committed
feat: Refactor DeployImageModal and EnvTriggerView to improve deployment handling and error messaging
1 parent 978e37d commit 27ca8bd

File tree

4 files changed

+78
-66
lines changed

4 files changed

+78
-66
lines changed

src/components/ApplicationGroup/Details/TriggerView/EnvTriggerView.tsx

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -438,12 +438,6 @@ const EnvTriggerView = ({ filteredAppIds, isVirtualEnv }: AppGroupDetailDefaultT
438438
})
439439
}
440440

441-
const closeCDModal = (): void => {
442-
history.push({
443-
search: '',
444-
})
445-
}
446-
447441
const closeApprovalModal = (e: React.MouseEvent): void => {
448442
e.stopPropagation()
449443
history.push({
@@ -597,7 +591,7 @@ const EnvTriggerView = ({ filteredAppIds, isVirtualEnv }: AppGroupDetailDefaultT
597591
envName={node?.environmentName}
598592
pipelineId={+node.id}
599593
materialType={cdMaterialType}
600-
handleClose={closeCDModal}
594+
handleClose={revertToPreviousURL}
601595
handleSuccess={getWorkflowStatusData}
602596
deploymentAppType={node?.deploymentAppType}
603597
isVirtualEnvironment={isVirtualEnv}

src/components/app/details/triggerView/DeployImageModal/DeployImageModal.tsx

Lines changed: 49 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {
66
AnimatedDeployButton,
77
API_STATUS_CODES,
88
ArtifactInfo,
9-
ButtonStyleType,
109
CDMaterialSidebarType,
1110
ConditionalWrap,
1211
DEFAULT_ROUTE_PROMPT_MESSAGE,
@@ -58,17 +57,19 @@ import DeployImageHeader from './DeployImageHeader'
5857
import MaterialListSkeleton from './MaterialListSkeleton'
5958
import RuntimeParamsSidebar from './RuntimeParamsSidebar'
6059
import { getMaterialResponseList, loadOlderImages } from './service'
61-
import { DeployImageContentProps, DeployImageModalProps, DeployViewStateType } from './types'
60+
import { DeployImageContentProps, DeployImageModalProps, DeployViewStateType, HandleDeploymentProps } from './types'
6261
import {
6362
getAllowWarningWithTippyNodeTypeProp,
6463
getCDArtifactId,
6564
getConfigToDeployValue,
6665
getDeployButtonIcon,
66+
getDeployButtonStyle,
6767
getInitialSelectedConfigToDeploy,
6868
getIsExceptionUser,
6969
getIsImageApprover,
7070
getTriggerArtifactInfoProps,
7171
handleTriggerErrorMessageForHelmManifestPush,
72+
renderDeployCTATippyData,
7273
showErrorIfNotAborted,
7374
} from './utils'
7475

@@ -177,8 +178,8 @@ const DeployImageModal = ({
177178
const canApproverDeploy = materialResponse?.canApproverDeploy ?? false
178179
const showConfigDiffView = searchParams.mode === URL_PARAM_MODE_TYPE.REVIEW_CONFIG && searchParams.deploy
179180
const isSelectImageTrigger = materialType === MATERIAL_TYPE.inputMaterialList
180-
const areSomeMaterialsPassingFilters = materialList.some(
181-
(materialDetails) => materialDetails.filterState === FilterStates.ALLOWED,
181+
const areAllImagesExcluded = materialList.every(
182+
(materialDetails) => materialDetails.filterState !== FilterStates.ALLOWED,
182183
)
183184
const selectedConfigToDeploy = getInitialSelectedConfigToDeploy(materialType, searchParams)
184185
const showPluginWarningBeforeTrigger = _showPluginWarningBeforeTrigger && isPreOrPostCD
@@ -275,7 +276,9 @@ const DeployImageModal = ({
275276
}
276277

277278
const handleClose = () => {
278-
onClickSetInitialParams(URL_PARAM_MODE_TYPE.LIST)
279+
if (isRedirectedFromAppDetails && showConfigDiffView) {
280+
onClickSetInitialParams(URL_PARAM_MODE_TYPE.LIST)
281+
}
279282
handleCloseProp?.()
280283
}
281284

@@ -323,34 +326,32 @@ const DeployImageModal = ({
323326

324327
return (
325328
!selectedImage ||
326-
!areSomeMaterialsPassingFilters ||
329+
areAllImagesExcluded ||
327330
(isRollbackTrigger && (pipelineDeploymentConfigLoading || !canDeployWithConfig())) ||
328331
(selectedConfigToDeploy.value === DeploymentWithConfigType.LATEST_TRIGGER_CONFIG && noLastDeploymentConfig)
329332
)
330333
}
331334

332335
const renderDeployCTATippyContent = () => {
333-
if (!areSomeMaterialsPassingFilters) {
334-
return (
335-
<>
336-
<h2 className="fs-12 fw-6 lh-18 m-0">No eligible images found!</h2>
337-
<p className="fs-12 fw-4 lh-18 m-0">
338-
Please select an image that passes the configured filters to deploy
339-
</p>
340-
</>
336+
const isSelectedImagePresent = materialList.some((artifact) => artifact.isSelected)
337+
338+
if (areAllImagesExcluded) {
339+
return renderDeployCTATippyData(
340+
'No eligible images found!',
341+
'Please select an image that passes the configured filters to deploy',
341342
)
342343
}
343344

344-
return (
345-
<>
346-
<h2 className="fs-12 fw-6 lh-18 m-0">Selected Config not available!</h2>
347-
<p className="fs-12 fw-4 lh-18 m-0">
348-
{selectedConfigToDeploy.value === DeploymentWithConfigType.SPECIFIC_TRIGGER_CONFIG &&
349-
noSpecificDeploymentConfig
350-
? 'Please select a different image or configuration to deploy'
351-
: 'Please select a different configuration to deploy'}
352-
</p>
353-
</>
345+
if (!isSelectedImagePresent) {
346+
return renderDeployCTATippyData('No image selected!', 'Please select an image to deploy')
347+
}
348+
349+
return renderDeployCTATippyData(
350+
'Selected Config not available!',
351+
selectedConfigToDeploy.value === DeploymentWithConfigType.SPECIFIC_TRIGGER_CONFIG &&
352+
noSpecificDeploymentConfig
353+
? 'Please select a different image or configuration to deploy'
354+
: 'Please select a different configuration to deploy',
354355
)
355356
}
356357

@@ -361,16 +362,10 @@ const DeployImageModal = ({
361362
)
362363

363364
const redirectToDeploymentStepsPage = () => {
364-
history.push(`/app/${appId}/cd-details/${envId}/${pipelineId}`)
365+
history.push(`${URLS.APP}/${appId}/${URLS.APP_CD_DETAILS}/${envId}/${pipelineId}`)
365366
}
366367

367-
const handleDeployment = (
368-
nodeType: DeploymentNodeType,
369-
_appId: number,
370-
ciArtifactId: number,
371-
deploymentWithConfig?: string,
372-
computedWfrId?: number,
373-
) => {
368+
const handleDeployment = ({ ciArtifactId, deploymentWithConfig, computedWfrId }: HandleDeploymentProps) => {
374369
const updatedRuntimeParamsErrorState = validateRuntimeParameters(runtimeParamsList)
375370
setDeployViewState((prevState) => ({
376371
...prevState,
@@ -384,15 +379,15 @@ const DeployImageModal = ({
384379
return
385380
}
386381

387-
handleAnalyticsEvent(TRIGGER_VIEW_GA_EVENTS.CDTriggered(nodeType))
382+
handleAnalyticsEvent(TRIGGER_VIEW_GA_EVENTS.CDTriggered(stageType))
388383
setIsDeploymentLoading(true)
389384

390-
if (_appId && pipelineId && ciArtifactId) {
385+
if (appId && pipelineId && ciArtifactId) {
391386
triggerCDNode({
392387
pipelineId: Number(pipelineId),
393388
ciArtifactId: Number(ciArtifactId),
394-
appId: Number(_appId),
395-
stageType: nodeType,
389+
appId: Number(appId),
390+
stageType,
396391
deploymentWithConfig,
397392
wfrId: computedWfrId,
398393
abortControllerRef: null,
@@ -408,10 +403,10 @@ const DeployImageModal = ({
408403
if (isVirtualEnvironment && deploymentAppType === DeploymentAppTypes.MANIFEST_DOWNLOAD) {
409404
const { helmPackageName } = response.result
410405
downloadManifestForVirtualEnvironment?.({
411-
appId: _appId,
406+
appId,
412407
envId,
413408
helmPackageName,
414-
cdWorkflowType: nodeType,
409+
cdWorkflowType: stageType,
415410
handleDownload,
416411
})
417412
}
@@ -444,7 +439,7 @@ const DeployImageModal = ({
444439
setIsDeploymentLoading(false)
445440
})
446441
} else {
447-
let message = _appId ? '' : 'app id missing '
442+
let message = appId ? '' : 'app id missing '
448443
message += pipelineId ? '' : 'pipeline id missing '
449444
message += ciArtifactId ? '' : 'Artifact id missing '
450445
ToastManager.showToast({
@@ -456,7 +451,7 @@ const DeployImageModal = ({
456451
}
457452

458453
const deployTrigger = (e: SyntheticEvent) => {
459-
e.stopPropagation()
454+
stopPropagation(e)
460455
handleConfirmationClose(e)
461456
// Blocking the deploy action if already deploying or config is not available
462457
if (isDeployButtonDisabled()) {
@@ -467,15 +462,21 @@ const DeployImageModal = ({
467462

468463
if (isRollbackTrigger || isSelectImageTrigger) {
469464
const computedWfrId = isRollbackTrigger ? wfrId : lastDeploymentWfrId
470-
handleDeployment(stageType, appId, artifactId, selectedConfigToDeploy.value, computedWfrId)
465+
handleDeployment({
466+
ciArtifactId: artifactId,
467+
deploymentWithConfig: selectedConfigToDeploy.value,
468+
computedWfrId,
469+
})
471470
return
472471
}
473472

474-
handleDeployment(stageType, appId, artifactId)
473+
// Not sure when this call will come into play, but keeping it for now for backward compatibility
474+
handleDeployment({ ciArtifactId: artifactId })
475475
}
476476

477-
const onClickDeploy = (e, disableDeployButton: boolean) => {
478-
e.stopPropagation()
477+
const onClickDeploy = (e: SyntheticEvent, disableDeployButton: boolean) => {
478+
stopPropagation(e)
479+
479480
if (!disableDeployButton) {
480481
if (!showPluginWarningOverlay && showPluginWarningBeforeTrigger) {
481482
setShowPluginWarningOverlay(true)
@@ -494,19 +495,8 @@ const DeployImageModal = ({
494495
}
495496
}
496497

497-
const getDeployButtonStyle = (
498-
userActionState: string,
499-
canDeployWithoutApproval: boolean,
500-
canImageApproverDeploy: boolean,
501-
): ButtonStyleType => {
502-
if (userActionState === ACTION_STATE.BLOCKED) {
503-
return ButtonStyleType.negative
504-
}
505-
if (userActionState === ACTION_STATE.PARTIAL || canDeployWithoutApproval || canImageApproverDeploy) {
506-
return ButtonStyleType.warning
507-
}
508-
return ButtonStyleType.default
509-
}
498+
const getOnClickDeploy = (disableDeployButton: boolean) => (e: SyntheticEvent) =>
499+
onClickDeploy(e, disableDeployButton)
510500

511501
const onSearchApply = (newSearchText: string) => {
512502
const newParams = new URLSearchParams({
@@ -540,7 +530,7 @@ const DeployImageModal = ({
540530
<AnimatedDeployButton
541531
dataTestId="cd-trigger-deploy-button"
542532
isLoading={isDeploymentLoading}
543-
onButtonClick={(e) => onClickDeploy(e, disableDeployButton)}
533+
onButtonClick={getOnClickDeploy(disableDeployButton)}
544534
startIcon={getDeployButtonIcon(deploymentWindowMetadata, stageType)}
545535
text={
546536
canDeployWithoutApproval
@@ -635,7 +625,7 @@ const DeployImageModal = ({
635625
consequence={consequence}
636626
configurePluginURL={configurePluginURL}
637627
showTriggerButton
638-
onTrigger={(e) => onClickDeploy(e, disableDeployButton)}
628+
onTrigger={getOnClickDeploy(disableDeployButton)}
639629
nodeType={allowWarningWithTippyNodeTypeProp}
640630
visible={showPluginWarningOverlay}
641631
onClose={handleClosePluginWarningOverlay}

src/components/app/details/triggerView/DeployImageModal/types.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,3 +250,9 @@ export interface LoadOlderImagesProps {
250250
isRollbackTrigger?: boolean
251251
appliedSearchText?: string
252252
}
253+
254+
export interface HandleDeploymentProps {
255+
ciArtifactId: number
256+
deploymentWithConfig?: string
257+
computedWfrId?: number
258+
}

src/components/app/details/triggerView/DeployImageModal/utils.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {
22
ACTION_STATE,
33
ApprovalRuntimeStateType,
44
ArtifactInfoProps,
5+
ButtonStyleType,
56
CDMaterialResponseType,
67
CDMaterialType,
78
CommonNodeAttr,
@@ -332,3 +333,24 @@ export const getAllowWarningWithTippyNodeTypeProp = (stageType: DeploymentNodeTy
332333

333334
export const getIsExceptionUser = (materialResponse: CDMaterialResponseType): boolean =>
334335
materialResponse?.deploymentApprovalInfo?.approvalConfigData?.isExceptionUser ?? false
336+
337+
export const renderDeployCTATippyData = (title: string, description: string) => (
338+
<>
339+
<h2 className="fs-12 fw-6 lh-18 m-0">{title}</h2>
340+
<p className="fs-12 fw-4 lh-18 m-0">{description}</p>
341+
</>
342+
)
343+
344+
export const getDeployButtonStyle = (
345+
userActionState: string,
346+
canDeployWithoutApproval: boolean,
347+
canImageApproverDeploy: boolean,
348+
): ButtonStyleType => {
349+
if (userActionState === ACTION_STATE.BLOCKED) {
350+
return ButtonStyleType.negative
351+
}
352+
if (userActionState === ACTION_STATE.PARTIAL || canDeployWithoutApproval || canImageApproverDeploy) {
353+
return ButtonStyleType.warning
354+
}
355+
return ButtonStyleType.default
356+
}

0 commit comments

Comments
 (0)