diff --git a/src/Shared/Components/Textarea/Textarea.component.tsx b/src/Shared/Components/Textarea/Textarea.component.tsx
index a50374557..8a6080be6 100644
--- a/src/Shared/Components/Textarea/Textarea.component.tsx
+++ b/src/Shared/Components/Textarea/Textarea.component.tsx
@@ -82,21 +82,22 @@ const Textarea = ({
}, [])
const reInitHeight = () => {
- const currentHeight = parseInt(textareaRef.current.style.height, 10)
- let nextHeight = textareaRef.current.scrollHeight || 0
-
- if (nextHeight < currentHeight || currentHeight > AUTO_EXPANSION_MAX_HEIGHT) {
+ const textarea = textareaRef.current
+ if (!textarea) {
return
}
- if (nextHeight < MIN_HEIGHT) {
- nextHeight = MIN_HEIGHT
- }
+ textarea.style.height = 'auto'
+ let nextHeight = textarea.scrollHeight
if (nextHeight > AUTO_EXPANSION_MAX_HEIGHT) {
nextHeight = AUTO_EXPANSION_MAX_HEIGHT
+ textarea.style.overflowY = 'auto'
+ } else {
+ textarea.style.overflowY = 'hidden'
}
+ nextHeight = Math.max(MIN_HEIGHT, nextHeight)
updateRefsHeight(nextHeight)
}
diff --git a/src/Shared/Helpers.tsx b/src/Shared/Helpers.tsx
index 902bd8d9a..6f5a16c46 100644
--- a/src/Shared/Helpers.tsx
+++ b/src/Shared/Helpers.tsx
@@ -54,7 +54,7 @@ import {
ZERO_TIME_STRING,
} from '../Common'
import { getAggregator, GVKType } from '../Pages'
-import { AggregatedNodes, PodMetadatum } from './Components'
+import { AggregatedNodes } from './Components'
import { CUBIC_BEZIER_CURVE, UNSAVED_CHANGES_PROMPT_MESSAGE } from './constants'
import {
AggregationKeys,
@@ -65,6 +65,7 @@ import {
IntersectionOptions,
Node,
Nodes,
+ PodMetaData,
TargetPlatformItemDTO,
TargetPlatformsDTO,
WebhookEventNameType,
@@ -298,7 +299,7 @@ export const renderValidInputButtonTippy = (children: ReactElement) => (
)
-export function aggregateNodes(nodes: any[], podMetadata: PodMetadatum[]): AggregatedNodes {
+export function aggregateNodes(nodes: any[], podMetadata: PodMetaData[]): AggregatedNodes {
const podMetadataMap = mapByKey(podMetadata, 'name')
// group nodes
const nodesGroup = nodes.reduce((agg, curr) => {
diff --git a/src/Shared/Hooks/useGetResourceKindsOptions/index.ts b/src/Shared/Hooks/useGetResourceKindsOptions/index.ts
index 86a41c642..0a1de1da2 100644
--- a/src/Shared/Hooks/useGetResourceKindsOptions/index.ts
+++ b/src/Shared/Hooks/useGetResourceKindsOptions/index.ts
@@ -14,5 +14,6 @@
* limitations under the License.
*/
+export { getProjectOptions } from './service'
export type { UseGetResourceKindOptionsReturnType, UseGetResourceKindsOptionsProps } from './types'
export { default as useGetResourceKindsOptions } from './useGetResourceKindsOptions'
diff --git a/src/Shared/Providers/MainContextProvider/index.ts b/src/Shared/Providers/MainContextProvider/index.ts
index 8c0dd4e1d..332cee39d 100644
--- a/src/Shared/Providers/MainContextProvider/index.ts
+++ b/src/Shared/Providers/MainContextProvider/index.ts
@@ -16,4 +16,4 @@
export * from './MainContextProvider'
export type { MainContext, ReloadVersionConfigTypes, SidePanelConfig, TempAppWindowConfig } from './types'
-export { SidePanelTab } from './types'
+export { AIAgentContextSourceType, type AIAgentContextType, SidePanelTab } from './types'
diff --git a/src/Shared/Providers/MainContextProvider/types.ts b/src/Shared/Providers/MainContextProvider/types.ts
index f04949c4d..cff7ce452 100644
--- a/src/Shared/Providers/MainContextProvider/types.ts
+++ b/src/Shared/Providers/MainContextProvider/types.ts
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-import { Dispatch, MutableRefObject, ReactNode, SetStateAction } from 'react'
+import { Dispatch, FunctionComponent, MutableRefObject, ReactNode, SetStateAction } from 'react'
import { SERVER_MODE } from '../../../Common'
import {
@@ -48,11 +48,71 @@ export interface SidePanelConfig {
/** URL to documentation that should be displayed in the panel */
docLink: string | null
aiSessionId?: string
+ isExpandedView?: boolean
}
-type AIAgentContextType = {
- path: string
- context: Record
+export enum AIAgentContextSourceType {
+ APP_DETAILS = 'app-details',
+ RESOURCE_BROWSER_CLUSTER = 'resource-browser-cluster',
+}
+
+export type AIAgentAppType =
+ | 'devtronApp'
+ | 'devtronHelmChart'
+ | 'externalHelmChart'
+ | 'externalArgoApp'
+ | 'externalFluxApp'
+
+type AIAgentAppDataMasterType = {
+ appId: number | string
+ appName: string
+ envId: number
+ envName: string
+ clusterId: number
+ namespace: string
+ appType: AIAgentAppType
+ fluxAppDeploymentType: string
+}
+
+type AIAgentAppDataType = Pick<
+ AIAgentAppDataMasterType,
+ TRequiredFields
+> & {
+ [K in Exclude]?: never
+} & {
+ appType: TAppType
+}
+
+type CommonContextDataType = Record & {
+ uiMarkup?: string
+}
+
+export type AIAgentContextType =
+ | {
+ source: AIAgentContextSourceType.APP_DETAILS
+ data:
+ | AIAgentAppDataType<
+ 'devtronApp' | 'devtronHelmChart',
+ 'appId' | 'appName' | 'envId' | 'envName' | 'clusterId'
+ >
+ | AIAgentAppDataType<'externalHelmChart', 'appId' | 'appName' | 'clusterId' | 'namespace'>
+ | AIAgentAppDataType<'externalArgoApp', 'appName' | 'clusterId' | 'namespace'>
+ | (AIAgentAppDataType<
+ 'externalFluxApp',
+ 'appName' | 'clusterId' | 'namespace' | 'fluxAppDeploymentType'
+ > &
+ CommonContextDataType)
+ }
+ | {
+ source: AIAgentContextSourceType.RESOURCE_BROWSER_CLUSTER
+ data: {
+ clusterId: number
+ clusterName: string
+ } & CommonContextDataType
+ }
+
+export type DebugAgentContextType = AIAgentContextType & {
+ prompt?: string
}
export interface TempAppWindowConfig {
@@ -118,6 +178,8 @@ type CommonMainContextProps = {
setLicenseData: Dispatch>
canFetchHelmAppStatus: boolean
setIntelligenceConfig: Dispatch>
+ debugAgentContext: DebugAgentContextType | null
+ setDebugAgentContext: (aiAgentContext: DebugAgentContextType | null) => void
setAIAgentContext: (aiAgentContext: AIAgentContextType) => void
setSidePanelConfig: Dispatch>
} & Pick
@@ -152,6 +214,9 @@ export type MainContext = CommonMainContextProps &
aiAgentContext: AIAgentContextType
tempAppWindowConfig: TempAppWindowConfig
setTempAppWindowConfig: Dispatch>
+ AIRecommendations?: FunctionComponent
+ featureAskDevtronExpert: EnvironmentDataValuesDTO['featureAskDevtronExpert']
+ AskDevtronButton?: FunctionComponent
}
| {
isLicenseDashboard: true
@@ -170,6 +235,9 @@ export type MainContext = CommonMainContextProps &
aiAgentContext: null
tempAppWindowConfig: null
setTempAppWindowConfig: null
+ AIRecommendations?: null
+ featureAskDevtronExpert?: null
+ AskDevtronButton?: null
}
)
diff --git a/src/Shared/Services/types.ts b/src/Shared/Services/types.ts
index dd0ba0e8e..7a2fdf857 100644
--- a/src/Shared/Services/types.ts
+++ b/src/Shared/Services/types.ts
@@ -61,6 +61,7 @@ export interface EnvironmentDataValuesDTO extends Pick = {
[RemoteConnectionType.Direct]: 'Direct Connection',
diff --git a/src/Shared/types.ts b/src/Shared/types.ts
index 76a6859f3..1179c6df8 100644
--- a/src/Shared/types.ts
+++ b/src/Shared/types.ts
@@ -175,13 +175,24 @@ export interface iNode extends Node {
status: string
pNode?: iNode
}
+
+export interface HelmReleaseStatus {
+ status: string
+ message: string
+ description: string
+}
+
export interface ResourceTree {
- conditions: any
+ nodes: Node[]
newGenerationReplicaSet: string
- nodes: Array
- podMetadata: Array
status: string
+ podMetadata: PodMetaData[]
+ conditions?: any
+ releaseStatus?: HelmReleaseStatus
resourcesSyncResult?: Record
+ hasDrift?: boolean
+ // lastSnapshotTime and wfrId are only available for isolated
+ lastSnapshotTime?: string
wfrId?: number
}
@@ -193,12 +204,6 @@ export enum AppType {
EXTERNAL_FLUX_APP = 'external_flux_app',
}
-export interface HelmReleaseStatus {
- status: string
- message: string
- description: string
-}
-
interface MaterialInfo {
author: string
branch: string
@@ -222,7 +227,7 @@ export interface AppDetails {
appStoreChartName?: string
appStoreInstalledAppVersionId?: number
ciArtifactId?: number
- deprecated?: false
+ deprecated?: boolean
environmentId?: number
environmentName: string
installedAppId?: number
@@ -258,6 +263,12 @@ export interface AppDetails {
FluxAppStatusDetail?: FluxAppStatusDetail
isPipelineTriggered?: boolean
releaseMode?: ReleaseMode
+ cdPipelineId?: number
+ triggerType?: string
+ parentEnvironmentName?: string
+ ciPipelineId?: number
+ trafficSwitched?: boolean
+ pcoId?: number
}
export interface ConfigDriftModalProps extends Required> {
@@ -1106,18 +1117,10 @@ export interface LicenseErrorStruct {
userMessage: string
}
-export interface DevtronLicenseBaseDTO {
+export type DevtronLicenseBaseDTO = {
fingerprint: string | null
isTrial: boolean | null
isFreemium: boolean | null
- /**
- * In timestamp format
- */
- expiry: string | null
- /**
- * Can be negative, depicts time left in seconds for license to expire
- */
- ttl: number | null
/**
* Show a reminder after these many DAYS left for license to expire, i.e,
* Show if `ttl` is less than `reminderThreshold` [converted to seconds]
@@ -1128,7 +1131,31 @@ export interface DevtronLicenseBaseDTO {
domain: string | null
} | null
license: string | null
-}
+} & (
+ | {
+ isSaasInstance: true
+ /**
+ * In seconds
+ */
+ timeElapsedSinceCreation: number
+ creationTime: string
+ ttl?: never
+ expiry?: never
+ }
+ | {
+ isSaasInstance?: false
+ timeElapsedSinceCreation?: never
+ creationTime?: never
+ /**
+ * Can be negative, depicts time left in seconds for license to expire
+ */
+ ttl: number | null
+ /**
+ * In timestamp format
+ */
+ expiry: string | null
+ }
+)
export type DevtronLicenseDTO = DevtronLicenseBaseDTO &
(isCentralDashboard extends true
@@ -1141,9 +1168,14 @@ export type DevtronLicenseDTO = Devt
showLicenseData?: never
licenseStatusError?: never
moduleLimits?: never
+ instanceData: {
+ devtronUrl: string
+ devtronPassword: string
+ } | null
}
: {
claimedByUserDetails?: never
+ instanceData?: never
showLicenseData: boolean
licenseStatusError?: LicenseErrorStruct
moduleLimits: {
@@ -1327,7 +1359,7 @@ export interface DeploymentStatusDetailsBreakdownDataType {
export interface IntelligenceConfig {
clusterId: number
- metadata: Record
+ metadata: Record
prompt: string
analyticsCategory: string
}
diff --git a/src/Shared/validations.tsx b/src/Shared/validations.tsx
index 1f3d936a0..ac5d9cb75 100644
--- a/src/Shared/validations.tsx
+++ b/src/Shared/validations.tsx
@@ -561,3 +561,31 @@ export const validateCronExpression = (expression: string): ValidationResponseTy
}
}
}
+
+export const validateAppName = (value: string): Required => {
+ const re = PATTERNS.APP_NAME
+ const regExp = new RegExp(re)
+ const test = regExp.test(value)
+
+ if (value.length === 0) {
+ return { isValid: false, message: 'Please provide app name' }
+ }
+
+ if (value.length < 3) {
+ return { isValid: false, message: MESSAGES.getMinCharMessage(3) }
+ }
+
+ if (value.length > 30) {
+ return { isValid: false, message: MESSAGES.getMaxCharMessage(30) }
+ }
+
+ if (!test) {
+ return {
+ isValid: false,
+ message:
+ "Min 3 chars; Start with alphabet; End with alphanumeric; Use only lowercase; Allowed:(-); Do not use 'spaces'",
+ }
+ }
+
+ return { isValid: true, message: '' }
+}
diff --git a/src/index.ts b/src/index.ts
index fbff34eac..6ccacbbaa 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -155,7 +155,6 @@ export interface customEnv {
GATEKEEPER_URL?: string
FEATURE_AI_INTEGRATION_ENABLE?: boolean
LOGIN_PAGE_IMAGE?: string
- FEATURE_ASK_DEVTRON_EXPERT?: boolean
/**
* If true, the manage traffic feature is enabled in apps & app groups.
*
@@ -188,6 +187,9 @@ export interface customEnv {
* @default false
*/
FEATURE_STORAGE_ENABLE?: boolean
+ FEATURE_ATHENA_DEBUG_MODE_ENABLE?: boolean
+ /** Org ID for grafana */
+ GRAFANA_ORG_ID?: number
}
declare global {
interface Window {