Skip to content

Commit 88b7197

Browse files
committed
feat: Refactor DeployImageModal and related components to streamline state management and improve code readability
1 parent 6aef199 commit 88b7197

File tree

7 files changed

+282
-258
lines changed

7 files changed

+282
-258
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ const BranchRegexModal = ({
7272
const isRegexValueInvalid = (_cm): void => {
7373
const regExp = new RegExp(_cm.source.regex)
7474
const regVal = structuredClone(regexValue[_cm.gitMaterialId])
75-
if (!regExp.test(regVal.value)) {
75+
if (!regExp.test(regVal.value) || !regVal.value) {
7676
const _regexVal = {
7777
...regexValue,
7878
[_cm.gitMaterialId]: { value: regVal.value, isInvalid: true },

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

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,3 @@
1-
/**
2-
* Service layer requirements:
3-
* - We need to have filteredCIPipelines
4-
* - Will find the selected pipeline from filteredCIPipelines from which we will get envId [in case of job view]
5-
* - isLoading as prop for when workflows are loading
6-
* - If !isLoading and filteredCIPipelines does not contain the selected pipeline, we will show error
7-
*/
8-
91
import { useEffect, useRef, useState } from 'react'
102
import { Prompt, useHistory, useParams } from 'react-router-dom'
113

src/components/app/details/triggerView/BuildImageModal/TriggerBuildSidebar.tsx

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ const TriggerBuildSidebar = ({
7171
}
7272
}
7373

74-
const getErrorMessageFromAppDetails = (appDetails: (typeof appList)[number]): string | null => {
74+
const getErrorMessageFromAppDetails = (appDetails: (typeof appList)[number]): JSX.Element | null => {
7575
const materialListError = appDetails.materialInitialError
7676
? appDetails.materialInitialError.errors?.[0].userMessage || 'Error fetching material list'
7777
: null
@@ -84,7 +84,19 @@ const TriggerBuildSidebar = ({
8484
? 'Invalid runtime parameters'
8585
: null
8686

87-
return appDetails.errorMessage || materialListError || runtimeParamsInitialError || runtimeParamsDataError
87+
const errorMessage =
88+
appDetails.errorMessage || materialListError || runtimeParamsInitialError || runtimeParamsDataError
89+
90+
if (!errorMessage) {
91+
return null
92+
}
93+
94+
return (
95+
<span className="flexbox cr-5 fw-4 fs-12 dc__gap-4">
96+
<Icon name="ic-error" size={20} color={null} />
97+
<span className="dc__block dc__word-break lh-20 dc__truncate--clamp-6">{errorMessage}</span>
98+
</span>
99+
)
88100
}
89101

90102
const renderAppName = (appDetails: (typeof appList)[number]): JSX.Element | null => (
@@ -101,14 +113,7 @@ const TriggerBuildSidebar = ({
101113
{appDetails.warningMessage}
102114
</span>
103115
)}
104-
{appDetails.appId !== appId && !!getErrorMessageFromAppDetails(appDetails) && (
105-
<span className="flexbox cr-5 fw-4 fs-12 dc__gap-4">
106-
<Icon name="ic-error" size={20} color={null} />
107-
<span className="dc__block dc__word-break lh-20 dc__truncate--clamp-6">
108-
{getErrorMessageFromAppDetails(appDetails)}
109-
</span>
110-
</span>
111-
)}
116+
{!!getErrorMessageFromAppDetails(appDetails)}
112117
{appDetails.node?.pluginBlockState &&
113118
appDetails.node.pluginBlockState.action !== ConsequenceAction.ALLOW_FOREVER &&
114119
PolicyEnforcementMessage && (

src/components/app/details/triggerView/BuildImageModal/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ export const getTriggerBuildPayload = ({
6363

6464
const history = material.history.filter((historyItem) => historyItem.isSelected)
6565
if (!history.length) {
66-
history.push(material.history[0])
66+
return
6767
}
6868

6969
history.forEach((element) => {

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

Lines changed: 171 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useContext, useState } from 'react'
1+
import { useContext } from 'react'
22
import { useHistory } from 'react-router-dom'
33

44
import {
@@ -25,18 +25,19 @@ import {
2525
MaterialInfo,
2626
Progressing,
2727
SearchBar,
28+
SegmentedControlProps,
2829
useMainContext,
2930
} from '@devtron-labs/devtron-fe-common-lib'
3031

3132
import { importComponentFromFELibrary } from '@Components/common'
3233

3334
import { TriggerViewContext } from '../config'
3435
import { TRIGGER_VIEW_PARAMS } from '../Constants'
35-
import { TriggerViewContextType } from '../types'
36+
import { FilterConditionViews, HandleRuntimeParamChange, TriggerViewContextType } from '../types'
3637
import ImageSelectionCTA from './ImageSelectionCTA'
3738
import MaterialListEmptyState from './MaterialListEmptyState'
3839
import RuntimeParamsSidebar from './RuntimeParamsSidebar'
39-
import { DeployImageContentProps } from './types'
40+
import { DeployImageContentProps, ImageSelectionCTAProps, RuntimeParamsSidebarProps } from './types'
4041
import {
4142
getApprovedImageClass,
4243
getConsumedAndAvailableMaterialList,
@@ -71,51 +72,27 @@ const DeployImageContent = ({
7172
pipelineId,
7273
handleClose,
7374
isRedirectedFromAppDetails,
74-
isSearchApplied,
75-
searchText,
7675
onSearchApply,
77-
onSearchTextChange,
78-
filterView,
79-
showConfiguredFilters,
8076
stageType,
81-
currentSidebarTab,
82-
handleRuntimeParamsChange,
83-
runtimeParamsErrorState,
84-
handleRuntimeParamsError,
8577
uploadRuntimeParamsFile,
86-
handleSidebarTabChange,
8778
appName,
88-
materialInEditModeMap,
8979
isSecurityModuleInstalled,
9080
envName,
91-
handleShowAppliedFilters,
9281
reloadMaterials,
9382
parentEnvironmentName,
9483
isVirtualEnvironment,
95-
handleImageSelection,
96-
setAppReleaseTagNames,
97-
toggleCardMode,
98-
setTagsEditable,
99-
updateCurrentAppMaterial,
100-
handleEnableFiltersView,
101-
handleFilterTabsChange,
10284
loadOlderImages,
103-
isLoadingOlderImages,
10485
policyConsequences,
105-
handleAllImagesView,
106-
showAppliedFilters,
107-
handleDisableFiltersView,
108-
handleDisableAppliedFiltersView,
10986
triggerType,
110-
appliedFilterList,
87+
deployViewState,
88+
setDeployViewState,
89+
setMaterialResponse,
11190
}: DeployImageContentProps) => {
11291
const history = useHistory()
11392
const { isSuperAdmin } = useMainContext()
11493

11594
const { onClickApprovalNode } = useContext<TriggerViewContextType>(TriggerViewContext)
11695

117-
const [showSearchBar, setShowSearchBar] = useState<boolean>(false)
118-
11996
const isExceptionUser = materialResponse?.deploymentApprovalInfo?.approvalConfigData?.isExceptionUser ?? false
12097
const requestedUserId = materialResponse?.requestedUserId
12198
const isApprovalConfigured = getIsApprovalPolicyConfigured(
@@ -131,6 +108,22 @@ const DeployImageContent = ({
131108
const runtimeParamsList = materialResponse?.runtimeParams || []
132109
const isCDNode = stageType === DeploymentNodeType.CD
133110

111+
const {
112+
searchText,
113+
appliedSearchText,
114+
filterView,
115+
showConfiguredFilters,
116+
currentSidebarTab,
117+
runtimeParamsErrorState,
118+
materialInEditModeMap,
119+
showAppliedFilters,
120+
appliedFilterList,
121+
isLoadingOlderImages,
122+
showSearchBar,
123+
} = deployViewState
124+
125+
const isSearchApplied = !!appliedSearchText
126+
134127
const { consumedImage, materialList, eligibleImagesCount } = getConsumedAndAvailableMaterialList({
135128
isApprovalConfigured,
136129
isExceptionUser,
@@ -144,6 +137,93 @@ const DeployImageContent = ({
144137
const showActionBar = FilterActionBar && !isSearchApplied && !!resourceFilters?.length && !showConfiguredFilters
145138
const areNoMoreImagesPresent = materials.length >= materialResponse?.totalCount
146139

140+
const handleSidebarTabChange: RuntimeParamsSidebarProps['handleSidebarTabChange'] = (e) => {
141+
setDeployViewState((prevState) => ({
142+
...prevState,
143+
currentSidebarTab: e.target.value as CDMaterialSidebarType,
144+
}))
145+
}
146+
147+
const onSearchTextChange = (newSearchText: string) => {
148+
setDeployViewState((prevState) => ({
149+
...prevState,
150+
searchText: newSearchText,
151+
}))
152+
}
153+
154+
const handleAllImagesView = () => {
155+
setDeployViewState((prevState) => ({
156+
...prevState,
157+
filterView: FilterConditionViews.ALL,
158+
}))
159+
}
160+
161+
const handleFilterTabsChange: SegmentedControlProps['onChange'] = (selectedSegment) => {
162+
const { value } = selectedSegment
163+
setDeployViewState((prevState) => ({
164+
...prevState,
165+
filterView: value as FilterConditionViews,
166+
}))
167+
}
168+
169+
const handleShowConfiguredFilters = () => {
170+
setDeployViewState((prevState) => ({
171+
...prevState,
172+
showConfiguredFilters: true,
173+
}))
174+
}
175+
176+
const handleExitFiltersView = () => {
177+
setDeployViewState((prevState) => ({
178+
...prevState,
179+
showConfiguredFilters: false,
180+
}))
181+
}
182+
183+
const handleDisableAppliedFiltersView = () => {
184+
setDeployViewState((prevState) => ({
185+
...prevState,
186+
appliedFilterList: [],
187+
showAppliedFilters: false,
188+
}))
189+
}
190+
191+
const getHandleShowAppliedFilters = (materialData: CDMaterialType) => () => {
192+
setDeployViewState((prevState) => ({
193+
...prevState,
194+
appliedFilterList: materialData?.appliedFilters ?? [],
195+
showAppliedFilters: true,
196+
}))
197+
}
198+
199+
const handleShowSearchBar = () => {
200+
setDeployViewState((prevState) => ({
201+
...prevState,
202+
showSearchBar: true,
203+
}))
204+
}
205+
206+
const handleImageSelection: ImageSelectionCTAProps['handleImageSelection'] = (materialIndex) => {
207+
const updatedMaterialList = materialList.map((material, index) => ({
208+
...material,
209+
isSelected: index === materialIndex,
210+
}))
211+
212+
setMaterialResponse((prevData) => {
213+
const updatedMaterialResponse = structuredClone(prevData)
214+
updatedMaterialResponse.materials = updatedMaterialList
215+
return updatedMaterialResponse
216+
})
217+
}
218+
219+
const setAppReleaseTagNames: ImageTaggingContainerType['setAppReleaseTagNames'] = (appReleaseTagNames) => {
220+
setMaterialResponse((prevData) => {
221+
const updatedMaterialResponse = structuredClone(prevData)
222+
updatedMaterialResponse.appReleaseTagNames = appReleaseTagNames
223+
return updatedMaterialResponse
224+
})
225+
}
226+
147227
const viewAllImages = () => {
148228
if (isRedirectedFromAppDetails) {
149229
history.push({
@@ -155,10 +235,6 @@ const DeployImageContent = ({
155235
}
156236
}
157237

158-
const handleShowSearchBar = () => {
159-
setShowSearchBar(true)
160-
}
161-
162238
const renderSearch = () => (
163239
<SearchBar
164240
initialSearchText={searchText}
@@ -173,6 +249,63 @@ const DeployImageContent = ({
173249
/>
174250
)
175251

252+
const updateCurrentAppMaterial: ImageTaggingContainerType['updateCurrentAppMaterial'] = (
253+
matId,
254+
imageReleaseTags,
255+
imageComment,
256+
) => {
257+
const updatedMaterialList = materialList.map((material) => {
258+
if (+material.id === +matId) {
259+
return {
260+
...material,
261+
imageReleaseTags,
262+
imageComment,
263+
}
264+
}
265+
return material
266+
})
267+
268+
setMaterialResponse((prevData) => {
269+
const updatedMaterialResponse = structuredClone(prevData)
270+
updatedMaterialResponse.materials = updatedMaterialList
271+
return updatedMaterialResponse
272+
})
273+
}
274+
275+
const setTagsEditable: ImageTaggingContainerType['setTagsEditable'] = (tagsEditable) => {
276+
setMaterialResponse((prevData) => {
277+
const updatedMaterialResponse = structuredClone(prevData)
278+
updatedMaterialResponse.tagsEditable = tagsEditable
279+
return updatedMaterialResponse
280+
})
281+
}
282+
283+
const handleRuntimeParamsChange: HandleRuntimeParamChange = (updatedRuntimeParamsList) => {
284+
setMaterialResponse((prevData) => {
285+
const updatedMaterialResponse = structuredClone(prevData)
286+
updatedMaterialResponse.runtimeParams = updatedRuntimeParamsList
287+
return updatedMaterialResponse
288+
})
289+
}
290+
291+
const handleRuntimeParamsError = (updatedRuntimeParamsErrorState: typeof runtimeParamsErrorState) => {
292+
setDeployViewState((prevState) => ({
293+
...prevState,
294+
runtimeParamsErrorState: updatedRuntimeParamsErrorState,
295+
}))
296+
}
297+
298+
const toggleCardMode: ImageTaggingContainerType['toggleCardMode'] = (index: number) => {
299+
setDeployViewState((prevState) => {
300+
const newMaterialInEditModeMap = new Map(prevState.materialInEditModeMap)
301+
newMaterialInEditModeMap.set(index, !newMaterialInEditModeMap.get(index))
302+
return {
303+
...prevState,
304+
materialInEditModeMap: newMaterialInEditModeMap,
305+
}
306+
})
307+
}
308+
176309
const getImageTagContainerProps = (mat: CDMaterialType): ImageTaggingContainerType => ({
177310
ciPipelineId: null,
178311
artifactId: +mat.id,
@@ -229,7 +362,7 @@ const DeployImageContent = ({
229362
appliedFiltersTimestamp={handleUTCTime(materialData.appliedFiltersTimestamp)}
230363
envName={envName}
231364
// Should not use Arrow function here but seems like no choice
232-
showConfiguredFilters={() => handleShowAppliedFilters(materialData)}
365+
showConfiguredFilters={getHandleShowAppliedFilters(materialData)}
233366
filterState={materialData.appliedFiltersState}
234367
dataSource={materialData.dataSource}
235368
deploymentWindowArtifactMetadata={materialData.deploymentWindowArtifactMetadata}
@@ -361,7 +494,7 @@ const DeployImageContent = ({
361494
isFromBulkCD={isBulkTrigger}
362495
resourceFilters={showConfiguredFilters ? resourceFilters : appliedFilterList}
363496
handleDisableFiltersView={
364-
showConfiguredFilters ? handleDisableFiltersView : handleDisableAppliedFiltersView
497+
showConfiguredFilters ? handleExitFiltersView : handleDisableAppliedFiltersView
365498
}
366499
envName={envName}
367500
closeModal={handleClose}
@@ -411,7 +544,7 @@ const DeployImageContent = ({
411544
consumedImage.length,
412545
)}
413546
onChange={handleFilterTabsChange}
414-
handleEnableFiltersView={handleEnableFiltersView}
547+
handleEnableFiltersView={handleShowConfiguredFilters}
415548
initialTab={filterView}
416549
/>
417550
) : (
@@ -466,7 +599,7 @@ const DeployImageContent = ({
466599
loadOlderImages={loadOlderImages}
467600
onSearchApply={onSearchApply}
468601
eligibleImagesCount={eligibleImagesCount}
469-
handleEnableFiltersView={handleEnableFiltersView}
602+
handleEnableFiltersView={handleShowConfiguredFilters}
470603
handleAllImagesView={handleAllImagesView}
471604
/>
472605
) : (

0 commit comments

Comments
 (0)