Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: resource browser tabs clean up and add abortControllerRef in fetchInTime #404

Merged
merged 9 commits into from
Nov 18, 2024
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@devtron-labs/devtron-fe-common-lib",
"version": "1.0.5",
"version": "1.0.6",
"description": "Supporting common component library",
"type": "module",
"main": "dist/index.js",
Expand Down
17 changes: 14 additions & 3 deletions src/Common/Api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,22 +192,33 @@ function fetchInTime<T = object>(
options?: APIOptions,
isMultipartRequest?: boolean,
): Promise<ResponseType> {
const controller = new AbortController()
const { signal } = controller
const controller = options?.abortControllerRef?.current ?? new AbortController()
const signal = options?.abortControllerRef?.current?.signal || options?.signal || controller.signal
const timeoutPromise: Promise<ResponseType> = new Promise((resolve, reject) => {
const requestTimeout = (window as any)?._env_?.GLOBAL_API_TIMEOUT || FALLBACK_REQUEST_TIMEOUT
const timeout = options?.timeout ? options.timeout : requestTimeout

setTimeout(() => {
controller.abort()
if (options?.abortControllerRef?.current) {
options.abortControllerRef.current = new AbortController()
}

reject({
code: 408,
errors: [{ code: 408, internalMessage: 'Request cancelled', userMessage: 'Request Cancelled' }],
})
}, timeout)
})
return Promise.race([
fetchAPI(url, type, data, options?.signal || signal, options?.preventAutoLogout || false, isMultipartRequest),
fetchAPI(
url,
type,
data,
signal,
options?.preventAutoLogout || false,
isMultipartRequest,
),
timeoutPromise,
]).catch((err) => {
if (err instanceof ServerErrors) {
Expand Down
8 changes: 6 additions & 2 deletions src/Common/Types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

import React, { ReactNode, CSSProperties, ReactElement } from 'react'
import React, { ReactNode, CSSProperties, ReactElement, MutableRefObject } from 'react'
import { Placement } from 'tippy.js'
import { UserGroupDTO } from '@Pages/GlobalConfigurations'
import { ImageComment, ReleaseTag } from './ImageTags.Types'
Expand Down Expand Up @@ -50,7 +50,11 @@ export interface ResponseType<T = any> {

export interface APIOptions {
timeout?: number
/**
* @deprecated Use abortController instead
*/
signal?: AbortSignal
abortControllerRef?: MutableRefObject<AbortController>
preventAutoLogout?: boolean
}

Expand Down Expand Up @@ -1007,4 +1011,4 @@ export interface WidgetEventDetails {
count: number
age: string
lastSeen: string
}
}
84 changes: 78 additions & 6 deletions src/Shared/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -748,36 +748,108 @@ export interface CustomRoleAndMeta {
}

interface CommonTabArgsType {
/**
* Name for the tab.
*
* Note: Used for the title
*/
name: string
kind?: string
/**
* URL for the tab
*/
url: string
/**
* If true, the tab is selected
*/
isSelected: boolean
/**
* Title for the tab
*/
title?: string
isDeleted?: boolean
position: number
/**
* Type for the tab
*
* Note: Fixed tabs are always places before dynamic tabs
*/
type: 'fixed' | 'dynamic'
eshankvaish marked this conversation as resolved.
Show resolved Hide resolved
/**
* Path of the icon for the tab
*
* @default ''
*/
iconPath?: string
/**
* Dynamic title for the tab
*
* @default ''
*/
dynamicTitle?: string
/**
* Whether to show the tab name when selected
*
* @default false
*/
showNameOnSelect?: boolean
/**
* Would remove the title/name from tab heading, but that does not mean name is not required, since it is used in other calculations
* @default false
*/
hideName?: boolean
/**
* Indicates if showNameOnSelect tabs have been selected once
*
* @default false
*/
isAlive?: boolean
lastSyncMoment?: Dayjs
componentKey?: string
/**
* Custom tippy config for the tab
*
* This overrides the tippy being computed from tab title
*/
tippyConfig?: {
title: string
descriptions: {
info: string
value: string
}[]
}
}

export interface InitTabType extends CommonTabArgsType {
idPrefix: string
}
/**
* If true, the fixed tab remains mounted on initial load of the component
*
* Note: Not for dynamic tabs atm
*
* @default false
*/
shouldRemainMounted?: boolean
}

export type InitTabType = Omit<CommonTabArgsType, 'type'> &
(
| {
type: 'fixed'
/**
* Unique identifier for the fixed tab
*
* Note: Shouldn't contain '-'
*/
id: string
idPrefix?: never
}
| {
type: 'dynamic'
id?: never
idPrefix: string
}
)

export interface DynamicTabType extends CommonTabArgsType {
id: string
/**
* Id of the last active tab before switching to current tab
*/
lastActiveTabId: string | null
}