Skip to content

Commit c97ee9a

Browse files
committed
Merge branch 'main' of https://github.com/devtron-labs/dashboard into chore/sync-explain-fix
2 parents 39ab8fa + 3646fa5 commit c97ee9a

File tree

10 files changed

+137
-64
lines changed

10 files changed

+137
-64
lines changed

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.17.0-pre-9",
7+
"@devtron-labs/devtron-fe-common-lib": "1.17.0-pre-10",
88
"@esbuild-plugins/node-globals-polyfill": "0.2.3",
99
"@rjsf/core": "^5.13.3",
1010
"@rjsf/utils": "^5.13.3",

src/assets/img/img-page-blocked.webp

19.2 KB
Binary file not shown.

src/components/ResourceBrowser/ResourceBrowser.service.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,15 @@ import {
3636
getClusterListMinWithInstalledClusters,
3737
getClusterListWithInstalledClusters,
3838
} from '@Components/ClusterNodes/clusterNodes.service'
39+
import { importComponentFromFELibrary } from '@Components/common'
3940

4041
import { Routes } from '../../config'
4142
import { SIDEBAR_KEYS } from './Constants'
4243
import { ClusterDetailBaseParams, GetResourceDataType, NodeRowDetail } from './Types'
4344
import { parseNodeList, removeDefaultForStorageClass } from './Utils'
4445

46+
const ExplainWithAIButton = importComponentFromFELibrary('ExplainWithAIButton', null, 'function')
47+
4548
export const namespaceListByClusterId = async (clusterId: string) => {
4649
const response = await get<string[]>(`${Routes.CLUSTER_NAMESPACE}/${clusterId}`)
4750

@@ -136,8 +139,11 @@ export const getResourceData = async ({
136139
? removeDefaultForStorageClass(response.result.data)
137140
: response.result.data
138141

142+
const isEventList = selectedResource.gvk.Kind === Nodes.Event
143+
139144
return {
140145
...response.result,
146+
headers: [...response.result.headers, ...(isEventList && ExplainWithAIButton ? ['explainButton'] : [])],
141147
data: data.map((entry, index) => ({
142148
...entry,
143149
id: `${idPrefix}${index}`,

src/components/ResourceBrowser/ResourceList/K8SResourceList.tsx

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
abortPreviousRequests,
2222
ErrorScreenManager,
2323
FiltersTypeEnum,
24+
GenericFilterEmptyState,
2425
getAIAnalyticsEvents,
2526
getIsRequestAborted,
2627
LARGE_PAGE_SIZE_OPTIONS,
@@ -124,7 +125,11 @@ export const K8SResourceList = ({
124125
const { clusterId } = useParams<K8sResourceListURLParams>()
125126

126127
// STATES
127-
const { selectedNamespace = 'all', ...filters } = useUrlFilters<string, K8sResourceListFilterType>({
128+
const {
129+
selectedNamespace = 'all',
130+
clearFilters,
131+
...filters
132+
} = useUrlFilters<string, K8sResourceListFilterType>({
128133
parseSearchParams: parseK8sResourceListSearchParams,
129134
})
130135

@@ -181,11 +186,13 @@ export const K8SResourceList = ({
181186
(header) =>
182187
({
183188
field: isNodeListing ? NODE_LIST_HEADERS_TO_KEY_MAP[header] : header,
184-
label: header === 'type' && isEventListing ? '' : header,
189+
label: (header === 'type' || header === 'explainButton') && isEventListing ? '' : header,
185190
size: getColumnSize(header, isEventListing),
186191
CellComponent: K8sResourceListTableCellComponent,
187192
comparator: getColumnComparator(header, isEventListing),
188-
isSortable: !isEventListing || (header !== 'message' && header !== 'type'),
193+
isSortable:
194+
!isEventListing ||
195+
(header !== 'message' && header !== 'type' && header !== 'explainButton'),
189196
horizontallySticky:
190197
header === 'name' || (isEventListing && (header === 'message' || header === 'type')),
191198
}) as TableColumnType,
@@ -241,11 +248,18 @@ export const K8SResourceList = ({
241248
if (resourceListError && !isResourceListLoadingWithoutNullState) {
242249
return (
243250
<div className="flexbox-col flex-grow-1 border__primary--left">
244-
<ErrorScreenManager
245-
code={(resourceListError as ServerErrors).code}
246-
reload={reloadResourceList}
247-
redirectURL={URLS.RESOURCE_BROWSER}
248-
/>
251+
{filters.areFiltersApplied ? (
252+
<GenericFilterEmptyState
253+
title={`No ${selectedResource?.gvk.Kind ?? 'Resource'} found`}
254+
handleClearFilters={clearFilters}
255+
/>
256+
) : (
257+
<ErrorScreenManager
258+
code={(resourceListError as ServerErrors).code}
259+
reload={reloadResourceList}
260+
redirectURL={URLS.RESOURCE_BROWSER}
261+
/>
262+
)}
249263
</div>
250264
)
251265
}

src/components/ResourceBrowser/ResourceList/K8sResourceListTableCellComponent.tsx

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import { AddEnvironmentFormPrefilledInfoType } from '@Pages/GlobalConfigurations
2727
import { ClusterEnvironmentDrawer } from '@Pages/GlobalConfigurations/ClustersAndEnvironments/ClusterEnvironmentDrawer'
2828
import { ADD_ENVIRONMENT_FORM_LOCAL_STORAGE_KEY } from '@Pages/GlobalConfigurations/ClustersAndEnvironments/constants'
2929

30-
import { AI_BUTTON_CONFIG_MAP, K8S_EMPTY_GROUP } from '../Constants'
30+
import { AI_BUTTON_CONFIG_MAP, EVENT_LIST, K8S_EMPTY_GROUP } from '../Constants'
3131
import { ClusterDetailBaseParams } from '../Types'
3232
import { getRenderInvolvedObjectButton, getRenderNodeButton, renderResourceValue } from '../Utils'
3333
import NodeActionsMenu from './NodeActionsMenu'
@@ -201,6 +201,16 @@ const K8sResourceListTableCellComponent = ({
201201
)
202202
}
203203

204+
const eventDetails = {
205+
message: resourceData.message as string,
206+
namespace: resourceData.namespace as string,
207+
object: resourceData[EVENT_LIST.dataKeys.involvedObject] as string,
208+
source: resourceData.source as string,
209+
count: resourceData.count as number,
210+
age: resourceData.age as string,
211+
lastSeen: resourceData[EVENT_LIST.dataKeys.lastSeen] as string,
212+
}
213+
204214
return (
205215
<>
206216
{columnName === 'name' ? (
@@ -296,6 +306,19 @@ const K8sResourceListTableCellComponent = ({
296306
</Tooltip>
297307
</>
298308
)}
309+
{ExplainWithAIButton &&
310+
columnName === 'explainButton' &&
311+
isEventListing &&
312+
resourceData.type === 'Warning' && (
313+
<ExplainWithAIButton
314+
intelligenceConfig={{
315+
clusterId,
316+
metadata: eventDetails,
317+
prompt: JSON.stringify(eventDetails),
318+
analyticsCategory: getAIAnalyticsEvents('RB_RESOURCE'),
319+
}}
320+
/>
321+
)}
299322
<span>
300323
{columnName === 'restarts' && Number(resourceData.restarts) !== 0 && PodRestartIcon && (
301324
<PodRestartIcon

src/components/ResourceBrowser/ResourceList/utils.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,8 @@ export const getColumnSize = (field: string, isEventListing: boolean) => {
354354
startWidth: 140,
355355
},
356356
}
357+
case 'explainButton':
358+
return { fixed: 80 }
357359
default:
358360
return {
359361
range: {

src/components/common/SidePanel/SidePanelContent.tsx

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -21,37 +21,36 @@ import { SidePanelHeaderActions } from './SidePanelHeaderActions'
2121
import { SidePanelContentProps } from './types'
2222
import { getContentWrapperClassNameForTab, renderOpenTicketButton } from './utils'
2323

24-
const AIChat = importComponentFromFELibrary(
25-
'AIChat',
26-
() => (
27-
<EnterpriseTrialDialog
28-
featureTitle="Ask Devtron Intelligence"
29-
featureDescription="Supercharge your troubleshooting! Instantly ask AI about your application or Kubernetes issues and get expert guidance at your fingertips."
30-
showBorder={false}
31-
/>
32-
),
33-
'function',
34-
)
24+
const AIChat = importComponentFromFELibrary('AIChat', null, 'function')
3525

3626
export const SidePanelContent = ({ onClose, setSidePanelConfig, sidePanelConfig }: SidePanelContentProps) => {
3727
const tab = sidePanelConfig.state as SidePanelTab
3828

3929
const renderAIChat = () => {
40-
// NOTE: even if flag is off, for oss clients need to show EnterpriseTrialDialog
41-
if (!AIChat || window._env_?.FEATURE_ASK_DEVTRON_EXPERT) {
42-
return <AIChat SidePanelHeaderActions={SidePanelHeaderActions} />
30+
if (!AIChat) {
31+
return (
32+
<EnterpriseTrialDialog
33+
featureTitle="Ask Devtron Intelligence"
34+
featureDescription="Supercharge your troubleshooting! Instantly ask AI about your application or Kubernetes issues and get expert guidance at your fingertips."
35+
showBorder={false}
36+
/>
37+
)
4338
}
4439

45-
return (
46-
<GenericEmptyState
47-
title="AI Integration not configured"
48-
subTitle="For AI-powered insights, please follow documentation or contact the Devtron team."
49-
SvgImage={ICMaintenance}
50-
imageType={ImageType.Medium}
51-
isButtonAvailable
52-
renderButton={renderOpenTicketButton}
53-
/>
54-
)
40+
if (!window._env_?.FEATURE_ASK_DEVTRON_EXPERT) {
41+
return (
42+
<GenericEmptyState
43+
title="AI Integration not configured"
44+
subTitle="For AI-powered insights, please follow documentation or contact the Devtron team."
45+
SvgImage={ICMaintenance}
46+
imageType={ImageType.Medium}
47+
isButtonAvailable
48+
renderButton={renderOpenTicketButton}
49+
/>
50+
)
51+
}
52+
53+
return <AIChat SidePanelHeaderActions={SidePanelHeaderActions} />
5554
}
5655

5756
return (

src/components/common/SidePanel/SidePanelDocumentation.tsx

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,44 @@ import {
77
ButtonVariantType,
88
ComponentSizeType,
99
DOCUMENTATION,
10+
GenericEmptyState,
1011
getUniqueId,
1112
Icon,
1213
ProgressBar,
1314
SidePanelTab,
15+
useIsSecureConnection,
1416
useMainContext,
1517
useTheme,
1618
} from '@devtron-labs/devtron-fe-common-lib'
1719

20+
import ImgPageBlocked from '@Images/img-page-blocked.webp'
21+
1822
import { SidePanelContentBaseProps } from './types'
1923

24+
const renderButton = (docLink: string) => () => (
25+
<Button
26+
dataTestId="open-in-new-tab-button"
27+
endIcon={<Icon name="ic-arrow-square-out" color={null} />}
28+
variant={ButtonVariantType.text}
29+
size={ComponentSizeType.medium}
30+
component={ButtonComponentType.anchor}
31+
text="Open in new tab"
32+
anchorProps={{
33+
href: docLink,
34+
}}
35+
/>
36+
)
37+
2038
export const SidePanelDocumentation = ({ SidePanelHeaderActions }: SidePanelContentBaseProps) => {
2139
// HOOKS
2240
const { appTheme } = useTheme()
2341
const {
2442
sidePanelConfig: { state, docLink: sidePanelDocLink, reinitialize },
2543
setSidePanelConfig,
2644
} = useMainContext()
45+
const isSecureConnection = useIsSecureConnection()
2746

28-
const [isLoading, setIsLoading] = useState(true)
47+
const [isLoading, setIsLoading] = useState(isSecureConnection)
2948

3049
const docLink = sidePanelDocLink ?? DOCUMENTATION.DOC_HOME_PAGE
3150

@@ -74,19 +93,29 @@ export const SidePanelDocumentation = ({ SidePanelHeaderActions }: SidePanelCont
7493
<div className="flex-grow-1 dc__position-rel">
7594
<ProgressBar isLoading={isLoading} />
7695

77-
{iframeSrc && (
78-
<iframe
79-
key={iframeKeyRef.current}
80-
ref={iframeRef}
81-
title="side-panel-documentation"
82-
loading="lazy"
83-
className="dc__no-border"
84-
src={iframeSrc}
85-
width="100%"
86-
height="100%"
87-
allow="clipboard-read; clipboard-write"
88-
referrerPolicy="strict-origin-when-cross-origin"
89-
onLoad={onLoad}
96+
{isSecureConnection ? (
97+
iframeSrc && (
98+
<iframe
99+
key={iframeKeyRef.current}
100+
ref={iframeRef}
101+
title="side-panel-documentation"
102+
loading="lazy"
103+
className="dc__no-border"
104+
src={iframeSrc}
105+
width="100%"
106+
height="100%"
107+
allow="clipboard-read; clipboard-write"
108+
referrerPolicy="strict-origin-when-cross-origin"
109+
onLoad={onLoad}
110+
/>
111+
)
112+
) : (
113+
<GenericEmptyState
114+
title="Unable to load docs"
115+
subTitle="Your Devtron setup isn’t secure, so the documentation can’t be displayed here."
116+
image={ImgPageBlocked}
117+
isButtonAvailable
118+
renderButton={renderButton(docLink)}
90119
/>
91120
)}
92121
</div>

src/components/v2/values/chartValuesDiff/ChartValuesView.tsx

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1539,17 +1539,6 @@ const ChartValuesView = ({
15391539
selectedChartValues={commonState.chartValues}
15401540
/>
15411541
)}
1542-
<footer className="flexbox dc__content-end dc__border-top px-16 py-12">
1543-
<AnimatedDeployButton
1544-
dataTestId="preset-save-values-button"
1545-
disabled={commonState.isUpdateInProgress || commonState.isDeleteInProgress}
1546-
onButtonClick={deployOrUpdateApplication}
1547-
isLoading={commonState.isUpdateInProgress}
1548-
text={isCreateValueView ? `Save ${chartValueId !== '0' ? 'Changes' : 'Value'}` : 'Deploy'}
1549-
{...(isCreateValueView ? {} : { startIcon: <Icon name="ic-rocket-launch" color={null} /> })}
1550-
animateStartIcon={!isCreateValueView}
1551-
/>
1552-
</footer>
15531542
</div>
15541543
)
15551544
}
@@ -1873,6 +1862,17 @@ const ChartValuesView = ({
18731862
renderChartValuesEditor()
18741863
)}
18751864
</div>
1865+
<footer className="flexbox dc__content-end dc__border-top px-16 py-12">
1866+
<AnimatedDeployButton
1867+
dataTestId="preset-save-values-button"
1868+
disabled={commonState.isUpdateInProgress || commonState.isDeleteInProgress}
1869+
onButtonClick={deployOrUpdateApplication}
1870+
isLoading={commonState.isUpdateInProgress}
1871+
text={isCreateValueView ? `Save ${chartValueId !== '0' ? 'Changes' : 'Value'}` : 'Deploy'}
1872+
{...(isCreateValueView ? {} : { startIcon: <Icon name="ic-rocket-launch" color={null} /> })}
1873+
animateStartIcon={!isCreateValueView}
1874+
/>
1875+
</footer>
18761876

18771877
{commonState.showDeleteAppConfirmationDialog && (
18781878
<DeleteChartDialog

yarn.lock

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1722,9 +1722,9 @@ __metadata:
17221722
languageName: node
17231723
linkType: hard
17241724

1725-
"@devtron-labs/devtron-fe-common-lib@npm:1.17.0-pre-9":
1726-
version: 1.17.0-pre-9
1727-
resolution: "@devtron-labs/devtron-fe-common-lib@npm:1.17.0-pre-9"
1725+
"@devtron-labs/devtron-fe-common-lib@npm:1.17.0-pre-10":
1726+
version: 1.17.0-pre-10
1727+
resolution: "@devtron-labs/devtron-fe-common-lib@npm:1.17.0-pre-10"
17281728
dependencies:
17291729
"@codemirror/autocomplete": "npm:6.18.6"
17301730
"@codemirror/lang-json": "npm:6.0.1"
@@ -1773,7 +1773,7 @@ __metadata:
17731773
react-select: 5.8.0
17741774
rxjs: ^7.8.1
17751775
yaml: ^2.4.1
1776-
checksum: 10c0/6af91748f470a02a47dc14b3214c5f498dd56abed143fec64863480077edc03a185a641420aa6cfa24f5626b833518bac7ab6d2cead8ce6ce485a74ce1ef7447
1776+
checksum: 10c0/828f5bd3714c5c9d990d1bbf0bf0267ad4b4f1354b214406bf2b2f559517bb864cf864b41a21570bfa6f8a77cc6fadf3d8e81ba5340f15fcbeb0e17d86aa48e7
17771777
languageName: node
17781778
linkType: hard
17791779

@@ -5685,7 +5685,7 @@ __metadata:
56855685
version: 0.0.0-use.local
56865686
resolution: "dashboard@workspace:."
56875687
dependencies:
5688-
"@devtron-labs/devtron-fe-common-lib": "npm:1.17.0-pre-9"
5688+
"@devtron-labs/devtron-fe-common-lib": "npm:1.17.0-pre-10"
56895689
"@esbuild-plugins/node-globals-polyfill": "npm:0.2.3"
56905690
"@playwright/test": "npm:^1.32.1"
56915691
"@rjsf/core": "npm:^5.13.3"

0 commit comments

Comments
 (0)