Skip to content

Commit d69a06d

Browse files
authored
Merge pull request #579 from devtron-labs/feat/confirmation-modal-wrapper
fix: show ConfirmationModal animation in some places
2 parents aa90f22 + 3c8b635 commit d69a06d

File tree

13 files changed

+148
-101
lines changed

13 files changed

+148
-101
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@devtron-labs/devtron-fe-common-lib",
3-
"version": "1.7.4",
3+
"version": "1.7.5",
44
"description": "Supporting common component library",
55
"type": "module",
66
"main": "dist/index.js",

src/Shared/Components/BulkOperations/BulkOperations.component.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,6 @@ const BulkOperations = ({
188188
<ConfirmationModal
189189
{...confirmationModalConfig}
190190
handleClose={handleModalClose}
191-
showConfirmationModal
192191
buttonConfig={{
193192
primaryButtonConfig: {
194193
...confirmationModalConfig.buttonConfig.primaryButtonConfig,

src/Shared/Components/CICDHistory/TriggerDetails.tsx

Lines changed: 53 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -182,55 +182,59 @@ const ProgressingStatus = memo(({ stage, type, label = 'In progress' }: Progress
182182
</>
183183
)}
184184
</div>
185-
<ConfirmationModal
186-
variant={ConfirmationModalVariantType.warning}
187-
title={type === HistoryComponentType.CD ? `Abort ${stage.toLowerCase()}-deployment?` : 'Abort build?'}
188-
subtitle={
189-
type === HistoryComponentType.CD
190-
? 'Are you sure you want to abort this stage?'
191-
: 'Are you sure you want to abort this build?'
192-
}
193-
buttonConfig={{
194-
secondaryButtonConfig: {
195-
disabled: aborting,
196-
onClick: toggleAbortConfiguration,
197-
text: 'Cancel',
198-
},
199-
primaryButtonConfig: {
200-
isLoading: aborting,
201-
onClick: abortRunning,
202-
text: 'Yes, Abort',
203-
},
204-
}}
205-
showConfirmationModal={abortConfirmation}
206-
handleClose={toggleAbortConfiguration}
207-
/>
208-
<ConfirmationModal
209-
variant={ConfirmationModalVariantType.warning}
210-
title="Could not abort build!"
211-
subtitle={`Error: ${abortError.message}`}
212-
buttonConfig={{
213-
secondaryButtonConfig: {
214-
disabled: aborting,
215-
onClick: closeForceAbortModal,
216-
text: 'Cancel',
217-
},
218-
primaryButtonConfig: {
219-
isLoading: aborting,
220-
onClick: abortRunning,
221-
text: 'Force Abort',
222-
},
223-
}}
224-
showConfirmationModal={abortError.status}
225-
handleClose={closeForceAbortModal}
226-
>
227-
<div className="fs-13 fw-6 pt-12 cn-7 lh-1-54">
228-
<span>Please try to force abort</span>
229-
</div>
230-
<div className="pt-4 fw-4 cn-7 lh-1-54">
231-
<span>Some resource might get orphaned which will be cleaned up with Job-lifecycle</span>
232-
</div>
233-
</ConfirmationModal>
185+
{abortConfirmation && (
186+
<ConfirmationModal
187+
variant={ConfirmationModalVariantType.warning}
188+
title={
189+
type === HistoryComponentType.CD ? `Abort ${stage.toLowerCase()}-deployment?` : 'Abort build?'
190+
}
191+
subtitle={
192+
type === HistoryComponentType.CD
193+
? 'Are you sure you want to abort this stage?'
194+
: 'Are you sure you want to abort this build?'
195+
}
196+
buttonConfig={{
197+
secondaryButtonConfig: {
198+
disabled: aborting,
199+
onClick: toggleAbortConfiguration,
200+
text: 'Cancel',
201+
},
202+
primaryButtonConfig: {
203+
isLoading: aborting,
204+
onClick: abortRunning,
205+
text: 'Yes, Abort',
206+
},
207+
}}
208+
handleClose={toggleAbortConfiguration}
209+
/>
210+
)}
211+
{abortError.status && (
212+
<ConfirmationModal
213+
variant={ConfirmationModalVariantType.warning}
214+
title="Could not abort build!"
215+
subtitle={`Error: ${abortError.message}`}
216+
buttonConfig={{
217+
secondaryButtonConfig: {
218+
disabled: aborting,
219+
onClick: closeForceAbortModal,
220+
text: 'Cancel',
221+
},
222+
primaryButtonConfig: {
223+
isLoading: aborting,
224+
onClick: abortRunning,
225+
text: 'Force Abort',
226+
},
227+
}}
228+
handleClose={closeForceAbortModal}
229+
>
230+
<div className="fs-13 fw-6 pt-12 cn-7 lh-1-54">
231+
<span>Please try to force abort</span>
232+
</div>
233+
<div className="pt-4 fw-4 cn-7 lh-1-54">
234+
<span>Some resource might get orphaned which will be cleaned up with Job-lifecycle</span>
235+
</div>
236+
</ConfirmationModal>
237+
)}
234238
</>
235239
)
236240
})

src/Shared/Components/ConfirmationModal/CannotDeleteModal.tsx

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,7 @@
1717
import ConfirmationModal from './ConfirmationModal'
1818
import { ConfirmationModalVariantType, CannotDeleteModalProps } from './types'
1919

20-
export const CannotDeleteModal = ({
21-
title,
22-
component,
23-
subtitle,
24-
closeConfirmationModal,
25-
showCannotDeleteDialogModal,
26-
}: CannotDeleteModalProps) => (
20+
export const CannotDeleteModal = ({ title, component, subtitle, closeConfirmationModal }: CannotDeleteModalProps) => (
2721
<ConfirmationModal
2822
variant={ConfirmationModalVariantType.info}
2923
title={`Cannot delete ${component} '${title}'`}
@@ -34,7 +28,6 @@ export const CannotDeleteModal = ({
3428
onClick: closeConfirmationModal,
3529
},
3630
}}
37-
showConfirmationModal={showCannotDeleteDialogModal}
3831
handleClose={closeConfirmationModal}
3932
/>
4033
)

src/Shared/Components/ConfirmationModal/ConfirmationModal.tsx

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@ import { ButtonHTMLAttributes, ChangeEvent, cloneElement, useCallback, useEffect
1818
import { AnimatePresence, motion } from 'framer-motion'
1919
import { noop, stopPropagation, useRegisterShortcut, UseRegisterShortcutProvider } from '@Common/index'
2020
import { ComponentSizeType } from '@Shared/constants'
21+
import { getUniqueId } from '@Shared/Helpers'
2122
import { ConfirmationModalBodyProps, ConfirmationModalProps } from './types'
2223
import { getPrimaryButtonStyleFromVariant, getConfirmationLabel, getIconFromVariant } from './utils'
2324
import { Button, ButtonStyleType, ButtonVariantType } from '../Button'
24-
import './confirmationModal.scss'
2525
import { Backdrop } from '../Backdrop'
26+
import { useConfirmationModalContext } from './ConfirmationModalContext'
2627
import { CustomInput } from '../CustomInput'
28+
import './confirmationModal.scss'
2729

2830
const ConfirmationModalBody = ({
2931
title,
@@ -157,14 +159,46 @@ const ConfirmationModalBody = ({
157159
)
158160
}
159161

160-
const ConfirmationModal = ({ showConfirmationModal, ...props }: ConfirmationModalProps) => (
161-
<AnimatePresence>{showConfirmationModal ? <ConfirmationModalBody {...props} /> : null}</AnimatePresence>
162-
)
162+
export const BaseConfirmationModal = () => {
163+
const { modalKey, settersRef } = useConfirmationModalContext()
164+
const [confirmationProps, setConfirmationProps] = useState<ConfirmationModalProps | null>(null)
165+
166+
useEffect(() => {
167+
settersRef.current = {
168+
setProps: setConfirmationProps,
169+
}
170+
}, [])
171+
172+
return (
173+
<UseRegisterShortcutProvider ignoreTags={['button']}>
174+
<AnimatePresence>{!!modalKey && <ConfirmationModalBody {...confirmationProps} />}</AnimatePresence>
175+
</UseRegisterShortcutProvider>
176+
)
177+
}
178+
179+
const ConfirmationModal = (props: ConfirmationModalProps) => {
180+
const { setModalKey, settersRef } = useConfirmationModalContext()
163181

164-
const WrapWithShortcutProvider = (props: ConfirmationModalProps) => (
165-
<UseRegisterShortcutProvider ignoreTags={['button']}>
166-
<ConfirmationModal {...props} />
167-
</UseRegisterShortcutProvider>
168-
)
182+
useEffect(() => {
183+
const id = getUniqueId()
184+
setModalKey(id)
185+
186+
return () => {
187+
setModalKey((prev) => {
188+
if (prev === id) {
189+
return ''
190+
}
191+
192+
return prev
193+
})
194+
}
195+
}, [])
196+
197+
useEffect(() => {
198+
settersRef.current.setProps(props)
199+
}, [props])
200+
201+
return null
202+
}
169203

170-
export default WrapWithShortcutProvider
204+
export default ConfirmationModal
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { createContext, PropsWithChildren, useContext, useMemo, useRef, useState } from 'react'
2+
import { ConfirmationModalContextType } from './types'
3+
4+
export const ConfirmationModalContext = createContext<ConfirmationModalContextType>(null)
5+
6+
export const ConfirmationModalProvider = ({ children }: PropsWithChildren<{}>) => {
7+
const settersRef = useRef<ConfirmationModalContextType['settersRef']['current']>(null)
8+
const [modalKey, setModalKey] = useState('')
9+
10+
const value = useMemo(() => ({ modalKey, setModalKey, settersRef }), [modalKey])
11+
12+
return <ConfirmationModalContext.Provider value={value}>{children}</ConfirmationModalContext.Provider>
13+
}
14+
15+
export const useConfirmationModalContext = () => useContext(ConfirmationModalContext)

src/Shared/Components/ConfirmationModal/DeleteConfirmationModal.tsx

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ export const DeleteConfirmationModal: React.FC<DeleteConfirmationModalProps> = (
3232
isDeleting,
3333
onDelete,
3434
onError,
35-
showConfirmationModal,
3635
closeConfirmationModal,
3736
confirmationConfig,
3837
// Additional UI-related logic
@@ -70,7 +69,6 @@ export const DeleteConfirmationModal: React.FC<DeleteConfirmationModalProps> = (
7069
) {
7170
setCannotDeleteText(serverError.errors[0].userMessage as string)
7271
}
73-
closeConfirmationModal()
7472
} else if (typeof onError === 'function') {
7573
onError(serverError)
7674
} else {
@@ -80,15 +78,17 @@ export const DeleteConfirmationModal: React.FC<DeleteConfirmationModalProps> = (
8078
}
8179
}
8280

83-
const handleCloseCannotDeleteModal = () => setCannotDeleteDialogModal(false)
81+
const handleCloseCannotDeleteModal = () => {
82+
setCannotDeleteDialogModal(false)
83+
closeConfirmationModal()
84+
}
8485

8586
const handleCloseForceDeleteModal = () => setForceDeleteModal(false)
8687

8788
const renderCannotDeleteDialogModal = () => (
8889
<CannotDeleteModal
8990
title={title}
9091
subtitle={cannotDeleteText}
91-
showCannotDeleteDialogModal={showCannotDeleteDialogModal}
9292
closeConfirmationModal={handleCloseCannotDeleteModal}
9393
component={component}
9494
/>
@@ -100,7 +100,6 @@ export const DeleteConfirmationModal: React.FC<DeleteConfirmationModalProps> = (
100100
subtitle={subtitle}
101101
onDelete={onDelete}
102102
closeConfirmationModal={handleCloseForceDeleteModal}
103-
showConfirmationModal={showForceDeleteModal}
104103
/>
105104
)
106105

@@ -113,15 +112,15 @@ export const DeleteConfirmationModal: React.FC<DeleteConfirmationModalProps> = (
113112
secondaryButtonConfig: {
114113
text: 'Cancel',
115114
onClick: closeConfirmationModal,
115+
disabled: isDeleting || isLoading,
116116
},
117117
primaryButtonConfig: {
118118
text: primaryButtonText,
119119
onClick: handleDelete,
120120
isLoading: isDeleting || isLoading,
121-
disabled: isLoading || disabled,
121+
disabled,
122122
},
123123
}}
124-
showConfirmationModal={showConfirmationModal}
125124
handleClose={closeConfirmationModal}
126125
confirmationConfig={confirmationConfig}
127126
>
@@ -131,7 +130,7 @@ export const DeleteConfirmationModal: React.FC<DeleteConfirmationModalProps> = (
131130

132131
return (
133132
<>
134-
{renderDeleteModal()}
133+
{!showCannotDeleteDialogModal && !showForceDeleteModal && renderDeleteModal()}
135134
{showCannotDeleteDialogModal && renderCannotDeleteDialogModal()}
136135
{showForceDeleteModal && renderForceDeleteModal()}
137136
</>

src/Shared/Components/ConfirmationModal/ForceDeleteConfirmationModal.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ export const ForceDeleteConfirmationModal = ({
2222
subtitle,
2323
onDelete,
2424
closeConfirmationModal,
25-
showConfirmationModal,
2625
}: ForceDeleteConfirmationProps) => {
2726
const renderSubtitle = () => (
2827
<>
@@ -45,7 +44,6 @@ export const ForceDeleteConfirmationModal = ({
4544
onClick: onDelete,
4645
},
4746
}}
48-
showConfirmationModal={showConfirmationModal}
4947
handleClose={closeConfirmationModal}
5048
/>
5149
)

src/Shared/Components/ConfirmationModal/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@
1414
* limitations under the License.
1515
*/
1616

17-
export { default as ConfirmationModal } from './ConfirmationModal'
17+
export { default as ConfirmationModal, BaseConfirmationModal } from './ConfirmationModal'
1818
export { DeleteConfirmationModal } from './DeleteConfirmationModal'
1919
export { ForceDeleteConfirmationModal } from './ForceDeleteConfirmationModal'
2020
export { CannotDeleteModal } from './CannotDeleteModal'
2121
export { ConfirmationModalVariantType, type ConfirmationModalProps } from './types'
22+
export { ConfirmationModalProvider } from './ConfirmationModalContext'

0 commit comments

Comments
 (0)