Skip to content

Commit

Permalink
Merge pull request #2172 from devtron-labs/kubecon/manifest-gui
Browse files Browse the repository at this point in the history
feat: kubecon manifest gui
  • Loading branch information
AbhishekA1509 authored Nov 7, 2024
2 parents 4429167 + 84a8dcb commit 4159b9b
Show file tree
Hide file tree
Showing 16 changed files with 437 additions and 169 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"private": true,
"homepage": "/dashboard",
"dependencies": {
"@devtron-labs/devtron-fe-common-lib": "0.6.2-beta-4",
"@devtron-labs/devtron-fe-common-lib": "0.6.0-patch-1-beta-7",
"@esbuild-plugins/node-globals-polyfill": "0.2.3",
"@rjsf/core": "^5.13.3",
"@rjsf/utils": "^5.13.3",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
OptionType,
LoadingIndicator,
GVKType,
getK8sResourceList,
EntityTypes,
} from '@devtron-labs/devtron-fe-common-lib'
import CreatableSelect from 'react-select/creatable'
Expand All @@ -42,7 +43,6 @@ import {
import {
getClusterList,
getResourceGroupList,
getResourceList,
namespaceListByClusterId,
} from '../../../../../../components/ResourceBrowser/ResourceBrowser.service'
import { K8SObjectType, ResourceListPayloadType } from '../../../../../../components/ResourceBrowser/Types'
Expand Down Expand Up @@ -152,7 +152,7 @@ const K8sListItemCard = ({
},
},
}
const { result } = await getResourceList(resourceListPayload)
const { result } = await getK8sResourceList(resourceListPayload)
if (result) {
const _data =
result.data?.map((ele) => ({ label: ele.name, value: ele.name })).sort(sortOptionsByLabel) ?? []
Expand Down
6 changes: 3 additions & 3 deletions src/components/ClusterNodes/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@

import React from 'react'
import { MultiValue } from 'react-select'
import { ResponseType, ApiResourceGroupType } from '@devtron-labs/devtron-fe-common-lib'
import { ResponseType, ApiResourceGroupType, K8sResourceDetailDataType } from '@devtron-labs/devtron-fe-common-lib'
import { LabelTag, OptionType } from '../app/types'
import { CLUSTER_PAGE_TAB, NODE_SEARCH_TEXT } from './constants'
import { EditModeType } from '../v2/appDetails/k8Resource/nodeDetail/NodeDetailTabs/terminal/constants'
import { ClusterOptionType, ResourceDetailDataType } from '../ResourceBrowser/Types'
import { ClusterOptionType } from '../ResourceBrowser/Types'
import { useTabs } from '../common/DynamicTabs'

export enum ERROR_TYPE {
Expand Down Expand Up @@ -133,7 +133,7 @@ export interface NodeListResponse extends ResponseType {
result?: NodeRowDetail[]
}

export interface PodType extends ResourceDetailDataType {
export interface PodType extends K8sResourceDetailDataType {
name: string
namespace: string
cpu: ResourceDetail
Expand Down
21 changes: 1 addition & 20 deletions src/components/ResourceBrowser/ResourceBrowser.service.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ import {
post,
ResponseType,
ApiResourceGroupType,
showError,
getIsRequestAborted,
convertJSONPointerToJSONPath,
} from '@devtron-labs/devtron-fe-common-lib'
import {
Expand All @@ -33,31 +31,14 @@ import { JSONPath } from 'jsonpath-plus'
import { SelectedResourceType } from '@Components/v2/appDetails/appDetails.type'
import { Routes } from '../../config'
import { ClusterListResponse } from '../../services/service.types'
import { CreateResourcePayload, CreateResourceResponse, ResourceListPayloadType, ResourceListResponse } from './Types'
import { CreateResourcePayload, CreateResourceResponse, ResourceListPayloadType } from './Types'
import { ALL_NAMESPACE_OPTION } from './Constants'

export const getClusterList = (): Promise<ClusterListResponse> => get(Routes.CLUSTER_LIST_PERMISSION)

export const namespaceListByClusterId = (clusterId: string): Promise<ResponseType> =>
get(`${Routes.CLUSTER_NAMESPACE}/${clusterId}`)

export const getResourceList = async (
resourceListPayload: ResourceListPayloadType,
signal?: AbortSignal,
): Promise<ResourceListResponse> => {
try {
return await post(Routes.K8S_RESOURCE_LIST, resourceListPayload, {
signal,
})
} catch (err) {
if (!getIsRequestAborted(err)) {
showError(err)
throw err
}
}
return null
}

export const getResourceGroupList = (clusterId: string, signal?: AbortSignal): Promise<ResponseType<ApiResourceType>> =>
get(`${Routes.API_RESOURCE}/${clusterId}`, {
signal,
Expand Down
33 changes: 18 additions & 15 deletions src/components/ResourceBrowser/ResourceList/K8SResourceList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ import {
useStateFilters,
ClipboardButton,
Tooltip,
getK8sResourceList,
K8sResourceDetailDataType,
K8sResourceDetailType,
showError,
BulkSelection,
useBulkSelection,
BulkOperationModalState,
Expand All @@ -55,14 +59,8 @@ import {
SEARCH_QUERY_PARAM_KEY,
DEFAULT_K8SLIST_PAGE_SIZE,
} from '../Constants'
import { deleteResource, getResourceList, getResourceListPayload, restartWorkload } from '../ResourceBrowser.service'
import {
K8SResourceListType,
ResourceDetailDataType,
ResourceDetailType,
ResourceListPayloadType,
URLParams,
} from '../Types'
import { deleteResource, getResourceListPayload, restartWorkload } from '../ResourceBrowser.service'
import { K8SResourceListType, ResourceListPayloadType, URLParams } from '../Types'
import ResourceListEmptyState from './ResourceListEmptyState'
import { EventList } from './EventList'
import ResourceFilterOptions from './ResourceFilterOptions'
Expand Down Expand Up @@ -109,7 +107,7 @@ export const K8SResourceList = ({
const [selectedNamespace, setSelectedNamespace] = useState(ALL_NAMESPACE_OPTION)
const [resourceListOffset, setResourceListOffset] = useState(0)
const [pageSize, setPageSize] = useState(DEFAULT_K8SLIST_PAGE_SIZE)
const [filteredResourceList, setFilteredResourceList] = useState<ResourceDetailType['data']>(null)
const [filteredResourceList, setFilteredResourceList] = useState<K8sResourceDetailType['data']>(null)
const [bulkOperationModalState, setBulkOperationModalState] = useState<BulkOperationModalState>('closed')

// REFS
Expand All @@ -132,21 +130,26 @@ export const K8SResourceList = ({
setIdentifiers,
isBulkSelectionApplied,
getSelectedIdentifiersCount,
} = useBulkSelection<Record<number, ResourceDetailDataType>>()
} = useBulkSelection<Record<number, K8sResourceDetailDataType>>()

const [resourceListLoader, _resourceList, _resourceListDataError, reloadResourceListData] = useAsync(
() =>
abortPreviousRequests(
() =>
getResourceList(
getK8sResourceList(
getResourceListPayload(
clusterId,
selectedNamespace.value.toLowerCase(),
selectedResource,
filters,
),
abortControllerRef.current.signal,
),
).catch((err) => {
if (!getIsRequestAborted(err)) {
showError(err)
throw err
}
}),
abortControllerRef,
),
[selectedResource, clusterId, selectedNamespace, filters],
Expand Down Expand Up @@ -223,7 +226,7 @@ export const K8SResourceList = ({
(filteredResourceList?.slice(resourceListOffset, resourceListOffset + pageSize).reduce((acc, curr) => {
acc[curr.id as number] = curr
return acc
}, {}) as Record<number, ResourceDetailDataType>) ?? {},
}, {}) as Record<number, K8sResourceDetailDataType>) ?? {},
)
}, [resourceListOffset, filteredResourceList, pageSize])

Expand Down Expand Up @@ -317,7 +320,7 @@ export const K8SResourceList = ({

const gridTemplateColumns = `350px repeat(${(resourceList?.headers.length ?? 1) - 1}, 180px)`

const getHandleCheckedForId = (resourceData: ResourceDetailDataType) => () => {
const getHandleCheckedForId = (resourceData: K8sResourceDetailDataType) => () => {
const id = Number(resourceData.id)

if (isBulkSelectionApplied) {
Expand Down Expand Up @@ -412,7 +415,7 @@ export const K8SResourceList = ({
}))
}

const renderResourceRow = (resourceData: ResourceDetailDataType): JSX.Element => (
const renderResourceRow = (resourceData: K8sResourceDetailDataType): JSX.Element => (
<div
key={`${resourceData.id}-${resourceData.name}-${bulkSelectionState[resourceData.id as number]}-${isBulkSelectionApplied}`}
className="scrollable-resource-list__row fw-4 cn-9 fs-13 dc__border-bottom-n1 hover-class h-44 dc__gap-16 dc__visible-hover dc__hover-n50"
Expand Down
32 changes: 10 additions & 22 deletions src/components/ResourceBrowser/Types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,13 @@ import {
OptionType,
ApiResourceGroupType,
GVKType,
K8sResourceDetailType,
K8sResourceDetailDataType,
} from '@devtron-labs/devtron-fe-common-lib'
import { LogSearchTermType, SelectedResourceType } from '../v2/appDetails/appDetails.type'
import { ClusterDetail } from '../ClusterNodes/types'
import { useTabs } from '../common/DynamicTabs'

export type ResourceDetailDataType = {
[key: string]: string | number | object
}

export interface ResourceDetailType {
headers: string[]
data: ResourceDetailDataType[]
}

export interface ResourceListResponse extends ResponseType {
result?: ResourceDetailType
}

export interface K8SObjectType extends K8SObjectBaseType {
child: ApiResourceGroupType[]
}
Expand Down Expand Up @@ -129,7 +118,7 @@ export interface ClusterOptionType extends OptionType {

export interface ResourceFilterOptionsProps {
selectedResource: ApiResourceGroupType
resourceList?: ResourceDetailType
resourceList?: K8sResourceDetailType
selectedCluster?: ClusterOptionType
selectedNamespace?: OptionType
setSelectedNamespace?: React.Dispatch<React.SetStateAction<OptionType>>
Expand All @@ -150,20 +139,19 @@ export interface K8SResourceListType

export interface ResourceBrowserActionMenuType {
clusterId: string
resourceData: ResourceDetailDataType
resourceData: K8sResourceDetailDataType
selectedResource: ApiResourceGroupType
handleResourceClick: (e: React.MouseEvent<HTMLButtonElement>) => void
removeTabByIdentifier?: ReturnType<typeof useTabs>['removeTabByIdentifier']
getResourceListData?: () => Promise<void>
}

export interface DeleteResourcePopupType {
clusterId: string
resourceData: ResourceDetailDataType
selectedResource: ApiResourceGroupType
export interface DeleteResourcePopupType
extends Pick<
ResourceBrowserActionMenuType,
'clusterId' | 'resourceData' | 'selectedResource' | 'getResourceListData' | 'removeTabByIdentifier'
> {
toggleDeleteDialog: () => void
removeTabByIdentifier?: ReturnType<typeof useTabs>['removeTabByIdentifier']
getResourceListData?: () => Promise<void>
}

export interface ResourceListEmptyStateType {
Expand All @@ -176,7 +164,7 @@ export interface ResourceListEmptyStateType {

export interface EventListType {
listRef: React.MutableRefObject<HTMLDivElement>
filteredData: ResourceDetailType['data']
filteredData: K8sResourceDetailType['data']
handleResourceClick: (e: React.MouseEvent<HTMLButtonElement>) => void
paginatedView: boolean
syncError: boolean
Expand Down
22 changes: 13 additions & 9 deletions src/components/ResourceBrowser/Utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@
import React from 'react'
import queryString from 'query-string'
import { useLocation } from 'react-router-dom'
import { ApiResourceGroupType, DATE_TIME_FORMAT_STRING, GVKType } from '@devtron-labs/devtron-fe-common-lib'
import {
ApiResourceGroupType,
DATE_TIME_FORMAT_STRING,
GVKType,
K8sResourceDetailDataType,
} from '@devtron-labs/devtron-fe-common-lib'
import moment from 'moment'
import { URLS, LAST_SEEN } from '../../config'
import { eventAgeComparator, processK8SObjects } from '../common'
Expand All @@ -30,7 +35,6 @@ import {
K8SObjectType,
K8sObjectOptionType,
FIXED_TABS_INDICES,
ResourceDetailDataType,
} from './Types'
import { InitTabType } from '../common/DynamicTabs/Types'
import TerminalIcon from '../../assets/icons/ic-terminal-fill.svg'
Expand Down Expand Up @@ -97,12 +101,12 @@ export const getK8SObjectMapAfterGroupHeadingClick = (
return _k8SObjectMap
}

export const sortEventListData = (eventList: ResourceDetailDataType[]): ResourceDetailDataType[] => {
export const sortEventListData = (eventList: K8sResourceDetailDataType[]): K8sResourceDetailDataType[] => {
if (!eventList?.length) {
return []
}
const warningEvents: ResourceDetailDataType[] = []
const otherEvents: ResourceDetailDataType[] = []
const warningEvents: K8sResourceDetailDataType[] = []
const otherEvents: K8sResourceDetailDataType[] = []
eventList.forEach((event) => {
if (event.type === 'Warning') {
warningEvents.push(event)
Expand All @@ -111,12 +115,12 @@ export const sortEventListData = (eventList: ResourceDetailDataType[]): Resource
}
})
return [
...warningEvents.sort(eventAgeComparator<ResourceDetailDataType>(LAST_SEEN)),
...otherEvents.sort(eventAgeComparator<ResourceDetailDataType>(LAST_SEEN)),
...warningEvents.sort(eventAgeComparator<K8sResourceDetailDataType>(LAST_SEEN)),
...otherEvents.sort(eventAgeComparator<K8sResourceDetailDataType>(LAST_SEEN)),
]
}

export const removeDefaultForStorageClass = (storageList: ResourceDetailDataType[]): ResourceDetailDataType[] =>
export const removeDefaultForStorageClass = (storageList: K8sResourceDetailDataType[]): K8sResourceDetailDataType[] =>
storageList.map((storage) =>
(storage.name as string).includes('(default)')
? {
Expand Down Expand Up @@ -341,7 +345,7 @@ export const getResourceFromK8SObjectMap = (map: ApiResourceGroupType[], nodeTyp

export const getRenderNodeButton =
(
resourceData: ResourceDetailDataType,
resourceData: K8sResourceDetailDataType,
columnName: string,
handleNodeClick: (e: React.MouseEvent<HTMLButtonElement>) => void,
) =>
Expand Down
11 changes: 9 additions & 2 deletions src/components/v2/appDetails/appDetails.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import {
Node as CommonNode,
iNode as CommoniNode,
ApiResourceGroupType,
ConfigurationType,
FormProps,
} from '@devtron-labs/devtron-fe-common-lib'
import { ExternalLink, OptionTypeWithIcon } from '../../externalLinks/ExternalLinks.type'
import { iLink } from '../utils/tabUtils/link.type'
Expand Down Expand Up @@ -470,6 +472,7 @@ export interface ManifestViewRefType {
manifest: string
activeManifestEditorData: string
modifiedManifest: string
guiSchema: Record<string, string>
}
id: string
}
Expand All @@ -481,8 +484,7 @@ export enum ManifestCodeEditorMode {
CANCEL = 'cancel',
}


export interface ManifestActionPropsType extends ResourceInfoActionPropsType {
export interface ManifestActionPropsType extends ResourceInfoActionPropsType, Pick<NodeDetailPropsType, 'isExternalApp'> {
hideManagedFields: boolean
toggleManagedFields: (managedFieldsExist: boolean) => void
manifestViewRef: MutableRefObject<ManifestViewRefType>
Expand All @@ -491,6 +493,11 @@ export interface ManifestActionPropsType extends ResourceInfoActionPropsType {
setShowManifestCompareView: Dispatch<SetStateAction<boolean>>
manifestCodeEditorMode: ManifestCodeEditorMode
setManifestCodeEditorMode: Dispatch<SetStateAction<ManifestCodeEditorMode>>
handleSwitchToYAMLMode: () => void
manifestFormConfigurationType: ConfigurationType
handleUpdateUnableToParseManifest: (value: boolean) => void
handleManifestGUIErrors: FormProps['onError']
manifestGUIFormRef: FormProps['ref']
}

export interface NodeTreeDetailTabProps {
Expand Down
Loading

0 comments on commit 4159b9b

Please sign in to comment.