Skip to content

Commit 4b0c283

Browse files
Merge pull request #2725 from devtron-labs/fix/app-details-manifest-layout
fix: editor search navigation in app details manifest view
2 parents 2dce2a5 + 28c5ab6 commit 4b0c283

File tree

14 files changed

+132
-56
lines changed

14 files changed

+132
-56
lines changed

Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ RUN yarn install --frozen-lockfile --network-timeout 600000
1010
COPY . .
1111

1212
RUN echo `git rev-parse --short HEAD` > health.html && \
13+
echo "" >> .env && \
1314
echo "SENTRY_RELEASE_VERSION=dashboard@$(git rev-parse --short HEAD)" >> .env && \
1415
yarn build
1516

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"private": true,
55
"homepage": "/dashboard",
66
"dependencies": {
7-
"@devtron-labs/devtron-fe-common-lib": "1.14.1-pre-5",
7+
"@devtron-labs/devtron-fe-common-lib": "1.14.1-pre-6",
88
"@esbuild-plugins/node-globals-polyfill": "0.2.3",
99
"@rjsf/core": "^5.13.3",
1010
"@rjsf/utils": "^5.13.3",

src/components/v2/appDetails/NodeDetailComponentWrapper.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,16 @@ const NodeDetailComponentWrapper = ({
6363
.catch(noop)
6464
}, [podName, nodeType, tabId])
6565

66-
return <NodeDetailComponent key={tabId} {...nodeDetailComponentProps} updateTabUrl={handleUpdateTabUrl} />
66+
return (
67+
<NodeDetailComponent
68+
key={tabId}
69+
{...nodeDetailComponentProps}
70+
isResourceBrowserView={false}
71+
isDynamicTabsStuck={nodeDetailComponentProps.isDynamicTabsStuck}
72+
updateTabUrl={handleUpdateTabUrl}
73+
handleStickDynamicTabsToTop={nodeDetailComponentProps.handleStickDynamicTabsToTop}
74+
/>
75+
)
6776
}
6877

6978
export default NodeDetailComponentWrapper

src/components/v2/appDetails/NodeTreeDetailTab.tsx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { useEffect, useState } from 'react'
1818
import ReactGA from 'react-ga4'
1919
import { Redirect, Route, Switch, useHistory, useLocation, useRouteMatch } from 'react-router-dom'
2020

21-
import { EnvResourceType, noop, useStickyEvent } from '@devtron-labs/devtron-fe-common-lib'
21+
import { EnvResourceType, noop, smoothScrollToTop, useStickyEvent } from '@devtron-labs/devtron-fe-common-lib'
2222

2323
import { ReactComponent as ICLogs } from '@Icons/ic-logs.svg'
2424
import { ReactComponent as ICObject } from '@Icons/ic-object.svg'
@@ -73,6 +73,10 @@ const NodeTreeDetailTab = ({
7373
identifier: 'node-tree-detail-tab',
7474
})
7575

76+
const handleScrollToTop = () => {
77+
smoothScrollToTop(stickyElementRef.current.parentElement, stickyElementRef.current.offsetTop)
78+
}
79+
7680
const dynamicTabsBackgroundClass = isDynamicTabsStuck ? 'bg__tertiary' : 'bg__primary'
7781

7882
useEffect(() => {
@@ -106,13 +110,22 @@ const NodeTreeDetailTab = ({
106110
})
107111
}
108112

113+
const handleStickDynamicTabsToTop = () => {
114+
if (isDynamicTabsStuck) {
115+
return
116+
}
117+
if (stickyElementRef.current) {
118+
handleScrollToTop()
119+
}
120+
}
121+
109122
// NOTE: don't render any of the components before tabs are initialized
110123
// this is cuz, the components mark their own corresponding tabs as the selected tabs on mount
111124
return (
112125
showContent && (
113126
<div
114127
ref={stickyElementRef}
115-
className="dc__position-sticky dc__top-0 h-100 dc__no-shrink flexbox-col node-tree-details-wrapper"
128+
className="flex-grow-1 dc__position-sticky dc__top-0 h-100 dc__no-shrink flexbox-col node-tree-details-wrapper"
116129
>
117130
<div className={`${dynamicTabsBackgroundClass} dc__transition--background pt-7 dc__no-shrink`}>
118131
<DynamicTabs
@@ -179,6 +192,9 @@ const NodeTreeDetailTab = ({
179192
setLogSearchTerms,
180193
isExternalApp,
181194
lowercaseKindToResourceGroupMap: {},
195+
isResourceBrowserView: false,
196+
isDynamicTabsStuck,
197+
handleStickDynamicTabsToTop,
182198
}}
183199
/>
184200
)}

src/components/v2/appDetails/appDetails.type.ts

Lines changed: 45 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -358,16 +358,27 @@ export interface LogAnalyzerProps extends LogSearchTermType {
358358
handleMarkLogAnalyzerTabSelected: () => void
359359
}
360360

361-
export interface NodeDetailPropsType
362-
extends LogSearchTermType,
363-
Pick<ClusterListType, 'lowercaseKindToResourceGroupMap' | 'updateTabUrl'> {
364-
loadingResources?: boolean
365-
isResourceBrowserView?: boolean
366-
selectedResource?: SelectedResourceType
367-
removeTabByIdentifier?: UseTabsReturnType['removeTabByIdentifier']
368-
clusterName?: string
369-
isExternalApp?: boolean
370-
}
361+
type ResourceBrowserSpecificProps =
362+
| {
363+
isResourceBrowserView?: false
364+
isDynamicTabsStuck: boolean
365+
handleStickDynamicTabsToTop: () => void
366+
}
367+
| {
368+
isResourceBrowserView: true
369+
isDynamicTabsStuck?: never
370+
handleStickDynamicTabsToTop?: never
371+
}
372+
373+
export type NodeDetailPropsType = LogSearchTermType &
374+
Pick<ClusterListType, 'lowercaseKindToResourceGroupMap' | 'updateTabUrl'> &
375+
ResourceBrowserSpecificProps & {
376+
loadingResources?: boolean
377+
selectedResource?: SelectedResourceType
378+
removeTabByIdentifier?: UseTabsReturnType['removeTabByIdentifier']
379+
clusterName?: string
380+
isExternalApp?: boolean
381+
}
371382

372383
export interface LogsComponentProps
373384
extends Omit<NodeDetailPropsType, 'lowercaseKindToResourceGroupMap' | 'updateTabUrl' | 'tabs'> {
@@ -425,6 +436,10 @@ export interface ResourceInfoActionPropsType {
425436
selectedResource?: SelectedResourceType
426437
clusterId: number
427438
aiWidgetEventDetails: string
439+
/**
440+
* @default true
441+
*/
442+
shouldScroll?: boolean
428443
}
429444

430445
export interface ManifestViewRefType {
@@ -452,23 +467,26 @@ export enum ManifestCodeEditorMode {
452467
CANCEL = 'cancel',
453468
}
454469

455-
export interface ManifestActionPropsType
456-
extends Omit<ResourceInfoActionPropsType, 'clusterId' | 'aiWidgetEventDetails'> {
457-
hideManagedFields: boolean
458-
toggleManagedFields: (managedFieldsExist: boolean) => void
459-
manifestViewRef: MutableRefObject<ManifestViewRefType>
460-
getComponentKey: () => string
461-
showManifestCompareView: boolean
462-
setShowManifestCompareView: Dispatch<SetStateAction<boolean>>
463-
manifestCodeEditorMode: ManifestCodeEditorMode
464-
setManifestCodeEditorMode: Dispatch<SetStateAction<ManifestCodeEditorMode>>
465-
handleSwitchToYAMLMode: () => void
466-
manifestFormConfigurationType: ConfigurationType
467-
handleUpdateUnableToParseManifest: (value: boolean) => void
468-
handleManifestGUIErrors: FormProps['onError']
469-
manifestGUIFormRef: FormProps['ref']
470-
isManifestEditable: boolean
471-
}
470+
export type ManifestActionPropsType = Omit<
471+
ResourceInfoActionPropsType,
472+
'clusterId' | 'aiWidgetEventDetails' | 'isResourceBrowserView'
473+
> &
474+
ResourceBrowserSpecificProps & {
475+
hideManagedFields: boolean
476+
toggleManagedFields: (managedFieldsExist: boolean) => void
477+
manifestViewRef: MutableRefObject<ManifestViewRefType>
478+
getComponentKey: () => string
479+
showManifestCompareView: boolean
480+
setShowManifestCompareView: Dispatch<SetStateAction<boolean>>
481+
manifestCodeEditorMode: ManifestCodeEditorMode
482+
setManifestCodeEditorMode: Dispatch<SetStateAction<ManifestCodeEditorMode>>
483+
handleSwitchToYAMLMode: () => void
484+
manifestFormConfigurationType: ConfigurationType
485+
handleUpdateUnableToParseManifest: (value: boolean) => void
486+
handleManifestGUIErrors: FormProps['onError']
487+
manifestGUIFormRef: FormProps['ref']
488+
isManifestEditable: boolean
489+
}
472490

473491
export interface NodeTreeDetailTabProps {
474492
appDetails: AppDetails

src/components/v2/appDetails/k8Resource/nodeDetail/NodeDetail.component.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ const NodeDetailComponent = ({
8989
updateTabUrl,
9090
isExternalApp,
9191
clusterName = '',
92+
isDynamicTabsStuck,
93+
handleStickDynamicTabsToTop,
9294
}: NodeDetailPropsType) => {
9395
const location = useLocation()
9496
const appDetails = IndexStore.getAppDetails()
@@ -365,7 +367,12 @@ const NodeDetailComponent = ({
365367
setManifestCodeEditorMode(ManifestCodeEditorMode.APPLY_CHANGES)
366368
}
367369

368-
const handleManifestEdit = () => setManifestCodeEditorMode(ManifestCodeEditorMode.EDIT)
370+
const handleManifestEdit = () => {
371+
if (manifestFormConfigurationType === ConfigurationType.YAML) {
372+
handleStickDynamicTabsToTop?.()
373+
}
374+
setManifestCodeEditorMode(ManifestCodeEditorMode.EDIT)
375+
}
369376

370377
const handleManifestCompareWithDesired = () => setShowManifestCompareView(true)
371378

@@ -543,7 +550,6 @@ const NodeDetailComponent = ({
543550
isDeleted={isDeleted}
544551
toggleManagedFields={toggleManagedFields}
545552
hideManagedFields={hideManagedFields}
546-
isResourceBrowserView={isResourceBrowserView}
547553
selectedResource={selectedResource}
548554
manifestViewRef={manifestViewRef}
549555
getComponentKey={getComponentKeyFromParams}
@@ -557,6 +563,9 @@ const NodeDetailComponent = ({
557563
handleManifestGUIErrors={handleManifestGUIError}
558564
manifestGUIFormRef={manifestGUIFormRef}
559565
isManifestEditable={isManifestEditable}
566+
{...(isResourceBrowserView
567+
? { isResourceBrowserView: true }
568+
: { isResourceBrowserView: false, isDynamicTabsStuck, handleStickDynamicTabsToTop })}
560569
/>
561570
</Route>
562571
<Route path={`${path}/${NodeDetailTab.EVENTS}`}>
@@ -571,6 +580,7 @@ const NodeDetailComponent = ({
571580
isResourceBrowserView ? 'AI_RB_EVENT' : 'EVENT',
572581
isResourceBrowserView ? null : appDetails.appType,
573582
)}
583+
shouldScroll={isResourceBrowserView || isDynamicTabsStuck}
574584
/>
575585
</Route>
576586
<Route path={`${path}/${NodeDetailTab.LOGS}`}>

src/components/v2/appDetails/k8Resource/nodeDetail/NodeDetailTabs/Events.component.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ const EventsComponent = ({
3434
selectedResource,
3535
clusterId,
3636
aiWidgetEventDetails,
37+
shouldScroll = true,
3738
}: ResourceInfoActionPropsType) => {
3839
const params = useParams<{
3940
actionName: string
@@ -105,7 +106,10 @@ const EventsComponent = ({
105106
}
106107

107108
return (
108-
<div className="flex-grow-1 flexbox-col dc__overflow-auto" style={{ background: 'var(--terminal-bg)' }}>
109+
<div
110+
className={`flex-grow-1 flexbox-col ${shouldScroll ? 'dc__overflow-auto' : ''}`}
111+
style={{ background: 'var(--terminal-bg)' }}
112+
>
109113
{renderContent()}
110114
</div>
111115
)

src/components/v2/appDetails/k8Resource/nodeDetail/NodeDetailTabs/EventsTable.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { importComponentFromFELibrary } from '@Components/common'
2626
import { MESSAGING_UI } from '../../../../../../config/constants'
2727
import MessageUI, { MsgUIType } from '../../../../common/message.ui'
2828
import { TERMINAL_STATUS, TERMINAL_TEXT } from './terminal/constants'
29+
import { EVENT_TABLE_ITEM_CLASS } from './constants'
2930
import { EventTableType } from './node.type'
3031

3132
const ExplainWithAIButton = importComponentFromFELibrary('ExplainWithAIButton', null, 'function')
@@ -47,6 +48,7 @@ export const EventsTable = ({
4748
reconnect,
4849
clusterId,
4950
aiWidgetAnalyticsEvent,
51+
shouldScroll = true,
5052
}: EventTableType) => {
5153
const renderEventsTable = () => {
5254
if (loading) {
@@ -64,7 +66,7 @@ export const EventsTable = ({
6466
return (
6567
<div
6668
data-testid="app-events-container"
67-
className={`text__white flex-grow-1 dc__overflow-auto bg__primary ${getComponentSpecificThemeClass(AppThemeType.dark)}`}
69+
className={`text__white flex-grow-1 bg__primary ${shouldScroll ? 'dc__overflow-auto' : ''} ${getComponentSpecificThemeClass(AppThemeType.dark)}`}
6870
>
6971
{errorValue?.status === TERMINAL_STATUS.TERMINATED && (
7072
<div className="pl-20 h-24 flex left pr-20 w-100 bcr-7 cn-0">
@@ -75,7 +77,7 @@ export const EventsTable = ({
7577
</div>
7678
)}
7779
<div
78-
className={`dc__position-sticky dc__top-0 px-16 py-8 dc__grid dc__gap-16 event-row ${ExplainWithAIButton ? 'ai-widget' : ''}`}
80+
className={`dc__zi-1 dc__position-sticky dc__top-0 px-16 py-8 dc__grid dc__gap-16 event-row ${ExplainWithAIButton ? 'ai-widget' : ''}`}
7981
>
8082
{EVENTS_TABLE_HEADERS.map((header, idx) => (
8183
// eslint-disable-next-line react/no-array-index-key
@@ -102,11 +104,11 @@ export const EventsTable = ({
102104
size={20}
103105
color={isNormalEventType ? 'B500' : null}
104106
/>
105-
<span>{reason}</span>
106-
<span>{message}</span>
107-
<span>{count}</span>
108-
<span>{age}</span>
109-
<span>{lastSeen}</span>
107+
<span className={EVENT_TABLE_ITEM_CLASS}>{reason}</span>
108+
<span className={EVENT_TABLE_ITEM_CLASS}>{message}</span>
109+
<span className={EVENT_TABLE_ITEM_CLASS}>{count}</span>
110+
<span className={EVENT_TABLE_ITEM_CLASS}>{age}</span>
111+
<span className={EVENT_TABLE_ITEM_CLASS}>{lastSeen}</span>
110112
{clusterId && ExplainWithAIButton && !isNormalEventType ? (
111113
<ExplainWithAIButton
112114
intelligenceConfig={{
@@ -116,9 +118,7 @@ export const EventsTable = ({
116118
analyticsCategory: aiWidgetAnalyticsEvent,
117119
}}
118120
/>
119-
) : (
120-
<span />
121-
)}
121+
) : null}
122122
</div>
123123
)
124124
})}

src/components/v2/appDetails/k8Resource/nodeDetail/NodeDetailTabs/Manifest.component.tsx

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,14 @@ const getLockedManifestKeys = importComponentFromFELibrary('getLockedManifestKey
8181
const ManifestGUIView = importComponentFromFELibrary('ManifestGUIView', null, 'function')
8282
const checkForIneligibleChanges = importComponentFromFELibrary('checkForIneligibleChanges', null, 'function')
8383
const ShowIneligibleChangesModal = importComponentFromFELibrary('ShowIneligibleChangesModal', null, 'function')
84+
8485
const ManifestComponent = ({
8586
selectedTab,
8687
hideManagedFields,
8788
toggleManagedFields,
8889
isDeleted,
8990
isResourceBrowserView,
91+
isDynamicTabsStuck,
9092
selectedResource,
9193
manifestViewRef,
9294
getComponentKey,
@@ -100,6 +102,7 @@ const ManifestComponent = ({
100102
handleManifestGUIErrors,
101103
manifestGUIFormRef,
102104
isManifestEditable,
105+
handleStickDynamicTabsToTop,
103106
}: ManifestActionPropsType) => {
104107
const location = useLocation()
105108
const history = useHistory()
@@ -170,6 +173,8 @@ const ManifestComponent = ({
170173

171174
const isReadOnlyView = showManifestCompareView || !isEditMode
172175

176+
const showGUIView = !isReadOnlyView && manifestFormConfigurationType === ConfigurationType.GUI
177+
173178
useEffectAfterMount(() => {
174179
// eslint-disable-next-line no-param-reassign
175180
manifestViewRef.current = {
@@ -670,8 +675,16 @@ const ManifestComponent = ({
670675
return <InfoBlock variant="error" description={errorText} {...manifestBorderConfig} />
671676
}
672677

678+
const handleStickDynamicTabsToTopWrapper = () => {
679+
if (isResourceBrowserView) {
680+
noop()
681+
}
682+
683+
handleStickDynamicTabsToTop?.()
684+
}
685+
673686
const renderContent = () => {
674-
if (!isReadOnlyView && manifestFormConfigurationType === ConfigurationType.GUI) {
687+
if (showGUIView) {
675688
return (
676689
<>
677690
{renderEditorInfo()}
@@ -698,7 +711,9 @@ const ManifestComponent = ({
698711
loading={loading}
699712
customLoader={<MessageUI msg={loadingMsg} icon={MsgUIType.LOADING} size={24} />}
700713
theme={AppThemeType.dark}
701-
height="fitToParent"
714+
height={isResourceBrowserView || isDynamicTabsStuck ? 'fitToParent' : '100%'}
715+
onSearchPanelOpen={handleStickDynamicTabsToTopWrapper}
716+
onSearchBarAction={handleStickDynamicTabsToTopWrapper}
702717
{...(showManifestCompareView
703718
? {
704719
diffView: true,
@@ -752,7 +767,7 @@ const ManifestComponent = ({
752767
</div>
753768
) : (
754769
<div
755-
className="flexbox-col flex-grow-1 dc__overflow-auto"
770+
className={`flexbox-col flex-grow-1 ${isResourceBrowserView ? 'dc__overflow-auto' : ''}`}
756771
data-testid="app-manifest-container"
757772
style={{
758773
background: 'var(--terminal-bg)',
@@ -763,7 +778,7 @@ const ManifestComponent = ({
763778
<div
764779
className={`${
765780
manifestFormConfigurationType === ConfigurationType.GUI ? 'bg__primary' : ''
766-
} flexbox-col flex-grow-1 dc__overflow-hidden`}
781+
} flexbox-col flex-grow-1 ${isResourceBrowserView ? 'dc__overflow-hidden' : ''}`}
767782
>
768783
{isResourceMissing && !loading && !showManifestCompareView ? (
769784
<MessageUI
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const EVENT_TABLE_ITEM_CLASS = 'dc__word-break mono'

0 commit comments

Comments
 (0)