Skip to content

Commit e6c3a61

Browse files
committed
feat: add util for common ai analytics events
1 parent a3262ee commit e6c3a61

File tree

14 files changed

+101
-51
lines changed

14 files changed

+101
-51
lines changed

src/Pages/App/CreateAppModal/UpdateTemplateConfig.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ const UpdateTemplateConfig = ({
109109
return (
110110
<>
111111
<div className="divider__secondary--horizontal" />
112-
<div className="br-8 border__secondary bg__primary p-20 pb-0-imp flexbox-col dc__gap-16">
112+
<div className="br-8 border__secondary bg__primary p-20 flexbox-col dc__gap-16">
113113
<h4 className="fs-14 fw-6 lh-20 cn-9 m-0">Code Source</h4>
114114
<MaterialList
115115
isCreateAppView

src/Shared/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './utils'

src/Shared/utils.tsx

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import moment from 'moment'
2+
3+
import { AppType } from '@devtron-labs/devtron-fe-common-lib'
4+
5+
const getAppTypeCategory = (appType: AppType) => {
6+
switch (appType) {
7+
case AppType.DEVTRON_APP:
8+
return 'DA'
9+
case AppType.DEVTRON_HELM_CHART:
10+
case AppType.EXTERNAL_HELM_CHART:
11+
return 'HA'
12+
case AppType.EXTERNAL_ARGO_APP:
13+
return 'ACD'
14+
case AppType.EXTERNAL_FLUX_APP:
15+
return 'FCD'
16+
default:
17+
return 'DA'
18+
}
19+
}
20+
21+
export const getAIAnalyticsEvents = (context: string, appType?: AppType) =>
22+
`AI_${appType ? `${getAppTypeCategory(appType)}_` : ''}${context}`
23+
24+
export const formatDurationFromNow = (timestamp: string | number | Date): string => {
25+
if (!timestamp) {
26+
return ''
27+
}
28+
const now = moment()
29+
const then = moment(timestamp)
30+
const duration = moment.duration(now.diff(then))
31+
32+
const units = [
33+
{ label: 'd', value: duration.days() },
34+
{ label: 'h', value: duration.hours() },
35+
{ label: 'm', value: duration.minutes() },
36+
{ label: 's', value: duration.seconds() },
37+
]
38+
39+
// Filter out zero values and take the first two non-zero units
40+
const nonZeroUnits = units.filter((unit) => unit.value > 0).slice(0, 2)
41+
42+
// If all units are zero, show "0s"
43+
if (nonZeroUnits.length === 0) {
44+
return '0s'
45+
}
46+
47+
return nonZeroUnits.map((unit) => `${unit.value}${unit.label}`).join(' ')
48+
}

src/components/ResourceBrowser/ResourceList/BaseResourceList.tsx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -412,9 +412,7 @@ const BaseResourceListContent = ({
412412
const aiButtonConfig = AI_BUTTON_CONFIG_MAP[gvkString]
413413
const showAIButton =
414414
!!ExplainWithAIButton &&
415-
aiButtonConfig &&
416-
columnName === aiButtonConfig.column &&
417-
getShowAIButton(aiButtonConfig, resourceData[columnName] as string)
415+
getShowAIButton(aiButtonConfig, columnName, resourceData[columnName] as string)
418416

419417
return columnName === 'name' ? (
420418
<div
@@ -562,11 +560,11 @@ const BaseResourceListContent = ({
562560
intelligenceConfig={{
563561
clusterId,
564562
metadata: {
565-
object: `${selectedResource?.gvk?.Kind}/${resourceData.name as string}`,
563+
object: `${selectedResource?.gvk?.Kind}/${resourceData.name}`,
566564
namespace: resourceData.namespace,
567565
status: resourceData.status ?? '',
568566
},
569-
prompt: `Debug what's wrong with ${resourceData.name as string}/${selectedResource?.gvk?.Kind} of ${resourceData.namespace}`,
567+
prompt: `Debug what's wrong with ${resourceData.name}/${selectedResource?.gvk?.Kind} of ${resourceData.namespace}`,
570568
analyticsCategory: 'AI_RB_RESOURCE',
571569
}}
572570
/>

src/components/ResourceBrowser/ResourceList/utils.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,10 @@ export const getFirstResourceFromKindResourceMap = (
8989
)
9090
}
9191

92-
export const getShowAIButton = (aiButtonConfig: ShowAIButtonConfig, value: string) => {
92+
export const getShowAIButton = (aiButtonConfig: ShowAIButtonConfig, columnName: string, value: string) => {
93+
if (!aiButtonConfig || columnName !== aiButtonConfig.column) {
94+
return false
95+
}
9396
if (aiButtonConfig.includeValues) {
9497
return aiButtonConfig.includeValues.has(value)
9598
}

src/components/app/details/appDetails/AppStatusCard.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,20 @@
1717
import React, { useMemo } from 'react'
1818
import Tippy from '@tippyjs/react'
1919
import ReactGA from 'react-ga4'
20-
import { AppStatus, AppType, DeploymentAppTypes } from '@devtron-labs/devtron-fe-common-lib'
20+
import { AppStatus, AppType, StatusType } from '@devtron-labs/devtron-fe-common-lib'
2121
import { ReactComponent as ICHelpOutline } from '../../../../assets/icons/ic-help-outline.svg'
2222
import { AppStatusCardType } from './appDetails.type'
2323
import LoadingCard from './LoadingCard'
2424
import './appDetails.scss'
2525
import { importComponentFromFELibrary } from '@Components/common'
26-
import { getAppTypeCategory } from './utils'
26+
import { getAIAnalyticsEvents } from 'src/Shared'
2727

2828
const ExplainWithAIButton = importComponentFromFELibrary('ExplainWithAIButton', null, 'function')
2929

3030
const AppStatusCard = ({ appDetails, status, cardLoading, setDetailed, message }: AppStatusCardType) => {
3131
const isHibernated = ['hibernating', 'hibernated'].includes(status.toLowerCase())
3232
const isFluxCDApp = appDetails?.appType === AppType.EXTERNAL_FLUX_APP
33-
const isStatusHealthy = useMemo(() => status.toLowerCase() === 'healthy', [status])
33+
const isStatusHealthy = useMemo(() => status.toLowerCase() === StatusType.HEALTHY.toLowerCase(), [status])
3434

3535
const debugNode = appDetails.resourceTree?.nodes?.find(
3636
(node) => node.kind === 'Deployment' || node.kind === 'Rollout',
@@ -66,7 +66,7 @@ const AppStatusCard = ({ appDetails, status, cardLoading, setDetailed, message }
6666
status: debugNode?.health?.status ?? appDetails.appStatus,
6767
},
6868
prompt: `Debug ${message || 'error'} ${debugNode ? `of ${debugObject}` : ''} in ${appDetails.namespace}`,
69-
analyticsCategory: `AI_${getAppTypeCategory(appDetails.appType)}_APP_STATUS`,
69+
analyticsCategory: getAIAnalyticsEvents('APP_STATUS', appDetails.appType),
7070
}}
7171
/>
7272
)}

src/components/app/details/appDetails/utils.tsx

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import {
3131
AppEnvironment,
3232
SelectPickerOptionType,
3333
IconsProps,
34-
AppType,
3534
} from '@devtron-labs/devtron-fe-common-lib'
3635
import { GetIFrameSrcParamsType } from './types'
3736

@@ -400,17 +399,3 @@ export const getEnvOptions = (env: AppEnvironment): SelectPickerOptionType<numbe
400399
label: env.environmentName,
401400
value: env.environmentId,
402401
})
403-
404-
export const getAppTypeCategory = (appType: AppType) => {
405-
switch (appType) {
406-
case AppType.DEVTRON_APP:
407-
return 'DA'
408-
case AppType.DEVTRON_HELM_CHART:
409-
case AppType.EXTERNAL_HELM_CHART:
410-
return 'HA'
411-
case AppType.EXTERNAL_ARGO_APP:
412-
return 'ACG'
413-
case AppType.EXTERNAL_FLUX_APP:
414-
return 'FCD'
415-
}
416-
}

src/components/v2/appDetails/constants.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@
1414
* limitations under the License.
1515
*/
1616

17+
import { StatusType } from '@devtron-labs/devtron-fe-common-lib/'
18+
1719
export enum ApplicationsGAEvents {
1820
REFRESH_DEVTRON_APP_RESOURCE_TREE = 'REFRESH_DEVTRON_APP_RESOURCE_TREE',
1921
REFRESH_HELM_APP_RESOURCE_TREE = 'REFRESH_HELM_APP_RESOURCE_TREE',
2022
REFRESH_ARGO_APP_RESOURCE_TREE = 'REFRESH_ARGO_APP_RESOURCE_TREE',
2123
REFRESH_FLUX_APP_RESOURCE_TREE = 'REFRESH_FLUX_APP_RESOURCE_TREE',
2224
}
2325

24-
export const EXPLAIN_AI_EXCLUDED_STATUS = new Set(['healthy', 'running', 'completed', 'ready'])
26+
export const EXPLAIN_AI_EXCLUDED_STATUS = new Set([StatusType.HEALTHY.toLowerCase(), 'running', 'completed', 'ready'])

src/components/v2/appDetails/k8Resource/k8resources.scss

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,18 @@
3131

3232
&--col-6 {
3333
grid-template-columns: 1fr 50px 100px 60px 80px 20px;
34+
35+
&.explain-ai-button {
36+
grid-template-columns: 1fr 50px 100px 60px 80px 32px 20px !important;
37+
}
3438
}
3539

3640
&--col-3 {
3741
grid-template-columns: 1fr 1fr 20px;
38-
}
3942

40-
&.explain-ai-button {
41-
grid-template-columns: 1fr 1fr 32px 20px !important;
43+
&.explain-ai-button {
44+
grid-template-columns: 1fr 1fr 32px 20px !important;
45+
}
4246
}
4347
}
4448

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

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import React, { useEffect, useMemo, useRef, useState } from 'react'
1818
import { Redirect, Route, Switch, useLocation, useParams, useRouteMatch } from 'react-router-dom'
19+
import { getAIAnalyticsEvents } from 'src/Shared'
1920

2021
import {
2122
capitalizeFirstLetter,
@@ -39,7 +40,6 @@ import {
3940
import { ReactComponent as ICArrowsLeftRight } from '@Icons/ic-arrows-left-right.svg'
4041
import { ReactComponent as ICCheck } from '@Icons/ic-check.svg'
4142
import { ReactComponent as ICPencil } from '@Icons/ic-pencil.svg'
42-
import { getAppTypeCategory } from '@Components/app/details/appDetails/utils'
4343
import { importComponentFromFELibrary } from '@Components/common'
4444
import { K8S_EMPTY_GROUP } from '@Components/ResourceBrowser/Constants'
4545
import { EDITOR_VIEW } from '@Config/constants'
@@ -567,11 +567,10 @@ const NodeDetailComponent = ({
567567
isResourceBrowserView={isResourceBrowserView}
568568
selectedResource={selectedResource}
569569
clusterId={isResourceBrowserView ? +params.clusterId : appDetails.clusterId}
570-
aiWidgetEventDetails={
571-
isResourceBrowserView
572-
? 'AI_RB_EVENT'
573-
: `AI_${getAppTypeCategory(appDetails.appType)}_EVENT`
574-
}
570+
aiWidgetEventDetails={getAIAnalyticsEvents(
571+
isResourceBrowserView ? 'AI_RB_EVENT' : 'EVENT',
572+
isResourceBrowserView ? null : appDetails.appType,
573+
)}
575574
/>
576575
</Route>
577576
<Route path={`${path}/${NodeDetailTab.LOGS}`}>

0 commit comments

Comments
 (0)