Skip to content

Commit 3a0609c

Browse files
authored
Merge pull request #414 from devtron-labs/release-candidate-v0.23.0
release: release candidate v0.23.0
2 parents 8d6bdb3 + 3cb195d commit 3a0609c

File tree

74 files changed

+1127
-617
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+1127
-617
lines changed

.eslintignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ src/Common/BreadCrumb/BreadcrumbStore.tsx
1010
src/Common/CIPipeline.Types.ts
1111
src/Common/ChartVersionAndTypeSelector.tsx
1212
src/Common/Checkbox.tsx
13-
src/Common/ClipboardButton/ClipboardButton.tsx
1413
src/Common/ClipboardButton/__tests__/ClipboardButton.test.tsx
1514
src/Common/CodeEditor/CodeEditor.tsx
1615
src/Common/Common.service.ts

package-lock.json

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

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@devtron-labs/devtron-fe-common-lib",
3-
"version": "0.6.5-patch-1",
3+
"version": "1.1.0",
44
"description": "Supporting common component library",
55
"type": "module",
66
"main": "dist/index.js",
@@ -40,6 +40,7 @@
4040
"@testing-library/react": "^12.1.4",
4141
"@tippyjs/react": "^4.2.0",
4242
"@typeform/embed-react": "2.20.0",
43+
"@types/dompurify": "^3.0.5",
4344
"@types/react": "17.0.39",
4445
"@types/react-dom": "17.0.13",
4546
"@types/react-router-dom": "^5.3.3",
@@ -66,7 +67,7 @@
6667
"react-mde": "^11.5.0",
6768
"react-toastify": "9.1.3",
6869
"typescript": "5.5.4",
69-
"vite": "5.4.6",
70+
"vite": "5.4.11",
7071
"vite-plugin-dts": "4.0.3",
7172
"vite-plugin-lib-inject-css": "2.1.1",
7273
"vite-plugin-svgr": "^2.4.0",
@@ -109,7 +110,7 @@
109110
"monaco-editor": "0.44.0"
110111
},
111112
"vite-plugin-svgr": {
112-
"vite": "5.4.6"
113+
"vite": "5.4.11"
113114
}
114115
}
115116
}

src/Assets/Icon/ic-hash.svg

Lines changed: 3 additions & 0 deletions
Loading

src/Assets/Icon/ic-pull-request.svg

Lines changed: 2 additions & 2 deletions
Loading

src/Assets/Icon/ic-tag.svg

Lines changed: 2 additions & 3 deletions
Loading

src/Common/Api.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -192,22 +192,33 @@ function fetchInTime<T = object>(
192192
options?: APIOptions,
193193
isMultipartRequest?: boolean,
194194
): Promise<ResponseType> {
195-
const controller = new AbortController()
196-
const { signal } = controller
195+
const controller = options?.abortControllerRef?.current ?? new AbortController()
196+
const signal = options?.abortControllerRef?.current?.signal || options?.signal || controller.signal
197197
const timeoutPromise: Promise<ResponseType> = new Promise((resolve, reject) => {
198198
const requestTimeout = (window as any)?._env_?.GLOBAL_API_TIMEOUT || FALLBACK_REQUEST_TIMEOUT
199199
const timeout = options?.timeout ? options.timeout : requestTimeout
200200

201201
setTimeout(() => {
202202
controller.abort()
203+
if (options?.abortControllerRef?.current) {
204+
options.abortControllerRef.current = new AbortController()
205+
}
206+
203207
reject({
204208
code: 408,
205209
errors: [{ code: 408, internalMessage: 'Request cancelled', userMessage: 'Request Cancelled' }],
206210
})
207211
}, timeout)
208212
})
209213
return Promise.race([
210-
fetchAPI(url, type, data, options?.signal || signal, options?.preventAutoLogout || false, isMultipartRequest),
214+
fetchAPI(
215+
url,
216+
type,
217+
data,
218+
signal,
219+
options?.preventAutoLogout || false,
220+
isMultipartRequest,
221+
),
211222
timeoutPromise,
212223
]).catch((err) => {
213224
if (err instanceof ServerErrors) {
@@ -264,4 +275,4 @@ export const abortPreviousRequests = <T>(
264275
*/
265276
export const getIsRequestAborted = (error) =>
266277
// The 0 code is common for aborted and blocked requests
267-
error && error.code === 0 && error.message.search('abort|aborted')
278+
error && error.code === 0 && error.message.search('abort|aborted') > -1

src/Common/CIPipeline.Types.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,6 @@ export interface StepType {
170170
inlineStepDetail?: InlineStepDetailType
171171
pluginRefStepDetail?: PluginRefStepDetailType
172172
triggerIfParentStageFail: boolean
173-
isMandatory?: boolean
174173
}
175174

176175
export interface BuildStageType {

src/Common/ClipboardButton/ClipboardButton.tsx

Lines changed: 58 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
* limitations under the License.
1515
*/
1616

17-
import { useState, useEffect, useCallback } from 'react'
18-
import Tippy from '@tippyjs/react'
17+
import { useState, useEffect, useRef } from 'react'
18+
import Tooltip from '@Common/Tooltip/Tooltip'
1919
import { copyToClipboard, noop, stopPropagation } from '../Helper'
2020
import ClipboardProps from './types'
2121
import { ReactComponent as ICCopy } from '../../Assets/Icon/ic-copy.svg'
@@ -25,73 +25,86 @@ import { ReactComponent as Check } from '../../Assets/Icon/ic-check.svg'
2525
* @param content - Content to be copied
2626
* @param copiedTippyText - Text to be shown in the tippy when the content is copied, default 'Copied!'
2727
* @param duration - Duration for which the tippy should be shown, default 1000
28-
* @param trigger - To trigger the copy action outside the button, if set to true the content will be copied, use case being triggering the copy action from outside the component
29-
* @param setTrigger - Callback function to set the trigger outside the button
28+
* @param copyToClipboardPromise - the promise returned by copyToClipboard util function
3029
* @param rootClassName - additional classes to add to button
3130
* @param iconSize - size of svg icon to be shown, default 16 (icon-dim-16)
3231
*/
33-
export default function ClipboardButton({
32+
export const ClipboardButton = ({
3433
content,
3534
copiedTippyText = 'Copied!',
3635
duration = 1000,
37-
trigger,
38-
setTrigger = noop,
36+
copyToClipboardPromise,
3937
rootClassName = '',
4038
iconSize = 16,
41-
}: ClipboardProps) {
39+
}: ClipboardProps) => {
4240
const [copied, setCopied] = useState<boolean>(false)
43-
const [enableTippy, setEnableTippy] = useState<boolean>(false)
41+
const setCopiedFalseTimeoutRef = useRef<ReturnType<typeof setTimeout>>(-1)
4442

45-
const handleTextCopied = () => {
43+
const handleTriggerCopy = () => {
4644
setCopied(true)
45+
46+
setCopiedFalseTimeoutRef.current = setTimeout(() => {
47+
setCopied(false)
48+
49+
setCopiedFalseTimeoutRef.current = -1
50+
}, duration)
4751
}
48-
const isTriggerUndefined = typeof trigger === 'undefined'
4952

50-
const handleEnableTippy = () => setEnableTippy(true)
51-
const handleDisableTippy = () => setEnableTippy(false)
52-
const handleCopyContent = useCallback(
53-
(e?) => {
54-
if (e) stopPropagation(e)
55-
copyToClipboard(content, handleTextCopied)
56-
},
57-
[content],
58-
)
59-
const iconClassName = `icon-dim-${iconSize} dc__no-shrink`
53+
const handleAwaitCopyToClipboardPromise = async (shouldRunCopy?: boolean) => {
54+
try {
55+
if (shouldRunCopy) {
56+
await copyToClipboard(content)
57+
} else {
58+
await copyToClipboardPromise
59+
}
6060

61-
useEffect(() => {
62-
if (!copied) return
61+
handleTriggerCopy()
62+
} catch {
63+
noop()
64+
}
65+
}
6366

64-
const timeout = setTimeout(() => {
65-
setCopied(false)
66-
setTrigger(false)
67-
}, duration)
67+
const handleCopyContent = async (e?: React.MouseEvent) => {
68+
if (e) {
69+
stopPropagation(e)
70+
}
6871

69-
return () => clearTimeout(timeout)
70-
}, [copied, duration, setTrigger])
72+
await handleAwaitCopyToClipboardPromise(true)
73+
}
7174

7275
useEffect(() => {
73-
if (!isTriggerUndefined && trigger) {
74-
setCopied(true)
75-
handleCopyContent()
76+
if (!copyToClipboardPromise) {
77+
return
7678
}
77-
}, [trigger, handleCopyContent])
79+
80+
handleAwaitCopyToClipboardPromise().catch(noop)
81+
}, [copyToClipboardPromise])
82+
83+
useEffect(
84+
() => () => {
85+
if (setCopiedFalseTimeoutRef.current > -1) {
86+
clearTimeout(setCopiedFalseTimeoutRef.current)
87+
}
88+
},
89+
[],
90+
)
91+
92+
const iconClassName = `icon-dim-${iconSize} dc__no-shrink`
93+
7894
return (
79-
<Tippy
80-
className="default-tt"
81-
content={copied ? copiedTippyText : 'Copy'}
82-
placement="bottom"
83-
visible={copied || enableTippy}
84-
arrow={false}
85-
>
95+
<Tooltip content="Copy" alwaysShowTippyOnHover={!copied}>
96+
{/* TODO: semantically buttons should not be nested; fix later */}
8697
<button
8798
type="button"
8899
className={`dc__outline-none-imp p-0 flex dc__transparent--unstyled dc__no-border ${rootClassName}`}
89-
onMouseEnter={handleEnableTippy}
90-
onMouseLeave={handleDisableTippy}
91-
onClick={isTriggerUndefined && handleCopyContent}
100+
onClick={handleCopyContent}
92101
>
93-
{copied ? <Check className={iconClassName} /> : <ICCopy className={iconClassName} />}
102+
<Tooltip content={copiedTippyText} alwaysShowTippyOnHover visible={copied}>
103+
<div className="flex">
104+
{copied ? <Check className={iconClassName} /> : <ICCopy className={iconClassName} />}
105+
</div>
106+
</Tooltip>
94107
</button>
95-
</Tippy>
108+
</Tooltip>
96109
)
97110
}

src/Common/ClipboardButton/types.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ export default interface ClipboardProps {
1818
content: string
1919
copiedTippyText?: string
2020
duration?: number
21-
trigger?: boolean
22-
setTrigger?: React.Dispatch<React.SetStateAction<boolean>>
21+
copyToClipboardPromise?: Promise<void>
2322
rootClassName?: string
2423
iconSize?: number
2524
}

0 commit comments

Comments
 (0)