diff --git a/src/Assets/IconV2/ic-new-chat.svg b/src/Assets/IconV2/ic-new-chat.svg new file mode 100644 index 000000000..a5d366419 --- /dev/null +++ b/src/Assets/IconV2/ic-new-chat.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/Common/API/CoreAPI.ts b/src/Common/API/CoreAPI.ts index c5056e8d9..0f37bc6da 100644 --- a/src/Common/API/CoreAPI.ts +++ b/src/Common/API/CoreAPI.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { API_STATUS_CODES, FALLBACK_REQUEST_TIMEOUT, Host } from '@Common/Constants' +import { API_STATUS_CODES, FALLBACK_REQUEST_TIMEOUT, Host, SERVICE_PATHS } from '@Common/Constants' import { noop } from '@Common/Helper' import { ServerErrors } from '@Common/ServerError' import { APIOptions, ResponseType } from '@Common/Types' @@ -40,6 +40,30 @@ class CoreAPI { this.handleRedirectToLicenseActivation = handleRedirectToLicenseActivation || noop } + /** + * Constructs the final URL by detecting service paths and applying appropriate routing + * @param url - The endpoint URL + * @returns The final URL with correct base path + */ + private constructUrl = (url: string): string => { + // Check if URL starts with a known service path + const isServicePath = Object.values(SERVICE_PATHS).some( + (servicePath) => url.startsWith(`${servicePath}/`) || url.startsWith(`/${servicePath}/`), + ) + + // Check if it's a non-orchestrator service path + const isNonOrchestratorService = + isServicePath && !url.startsWith('orchestrator/') && !url.startsWith('/orchestrator/') + + if (isNonOrchestratorService) { + // For service paths like 'athena/', use as-is but ensure single leading slash + return url.startsWith('/') ? url : `/${url}` + } + // For orchestrator paths or relative paths, add Host prefix + const cleanUrl = url.startsWith('/') ? url.slice(1) : url + return `${this.host}/${cleanUrl}` + } + private fetchAPI = async ({ url, type, @@ -55,11 +79,14 @@ class CoreAPI { method: type, signal, body: data ? JSON.stringify(data) : undefined, + headers: { + 'Content-Type': 'application/json', + }, } // eslint-disable-next-line dot-notation options['credentials'] = 'include' as RequestCredentials return fetch( - `${isProxyHost ? '/proxy' : this.host}/${url}`, + this.constructUrl(url), !isMultipartRequest ? options : ({ diff --git a/src/Common/Constants.ts b/src/Common/Constants.ts index da240e67b..bc833c89d 100644 --- a/src/Common/Constants.ts +++ b/src/Common/Constants.ts @@ -21,6 +21,13 @@ import { BackupAndScheduleListViewEnum, BackupLocationsTypes } from '@PagesDevtr export const FALLBACK_REQUEST_TIMEOUT = 60000 export const Host = window?.__ORCHESTRATOR_ROOT__ ?? '/orchestrator' +// Service path constants for API routing +export const SERVICE_PATHS = { + ATHENA: 'athena', + ORCHESTRATOR: 'orchestrator', + // Add other service paths as needed in the future +} as const + export const DOCUMENTATION_HOME_PAGE = 'https://docs.devtron.ai' export const DEVTRON_HOME_PAGE = 'https://devtron.ai/' export const DOCUMENTATION_VERSION = '/devtron/v1.7' diff --git a/src/Common/Markdown/MarkDown.tsx b/src/Common/Markdown/MarkDown.tsx index 8194b262a..a56f54d4f 100644 --- a/src/Common/Markdown/MarkDown.tsx +++ b/src/Common/Markdown/MarkDown.tsx @@ -80,6 +80,10 @@ const MarkDown = ({ ` renderer.heading = ({ text, depth }: Tokens.Heading) => { + // Alternative debugging - add to window object + if (typeof window !== 'undefined') { + ;(window as any).debugHeadingText = text + } const escapedText = disableEscapedText ? '' : text.toLowerCase().replace(/[^\w]+/g, '-') return ` diff --git a/src/Common/Markdown/markdown.scss b/src/Common/Markdown/markdown.scss index cf8a7af2d..4526d4c91 100644 --- a/src/Common/Markdown/markdown.scss +++ b/src/Common/Markdown/markdown.scss @@ -77,4 +77,59 @@ a.anchor { color: var(--N900); } + h1, h2, h3, h4, h5, h6 .header-link { + color: #000a14 !important; + font-size: 15px !important; + font-family: Open Sans !important; + font-weight: 600 !important; + line-height: 20px !important; + word-wrap: break-word !important; + } +} + +// custom styles +.markdown { + // Title styles + h1, h2, h3, h4, h5, h6 { + &.header-link { + color: #000a14 !important; + font-size: 15px !important; + font-family: Open Sans !important; + font-weight: 600 !important; + line-height: 20px !important; + word-wrap: break-word !important; + } + } + + // Description styles + .md-description { + font-size: 14px; + line-height: 1.6; + color: var(--N700); + margin-bottom: 20px; + } + + // List styles + ul.md-list { + margin: 12px 0; + padding-left: 24px; + + li { + color: var(--neutral-N900, #F8F8F9); + font-size: 13px; + font-family: Open Sans; + font-weight: 400; + line-height: 20px; + word-wrap: break-word; + + &::marker { + color: var(--N400); + } + } + } + + // Nested list styles + ul.md-list ul { + margin: 8px 0; + } } diff --git a/src/Shared/Components/Icon/Icon.tsx b/src/Shared/Components/Icon/Icon.tsx index 892e418dd..6d7d278b3 100644 --- a/src/Shared/Components/Icon/Icon.tsx +++ b/src/Shared/Components/Icon/Icon.tsx @@ -194,6 +194,7 @@ import { ReactComponent as ICMonitoring } from '@IconsV2/ic-monitoring.svg' import { ReactComponent as ICMoreVertical } from '@IconsV2/ic-more-vertical.svg' import { ReactComponent as ICNamespace } from '@IconsV2/ic-namespace.svg' import { ReactComponent as ICNew } from '@IconsV2/ic-new.svg' +import { ReactComponent as ICNewChat } from '@IconsV2/ic-new-chat.svg' import { ReactComponent as ICNodeScript } from '@IconsV2/ic-node-script.svg' import { ReactComponent as ICOidc } from '@IconsV2/ic-oidc.svg' import { ReactComponent as ICOpenBox } from '@IconsV2/ic-open-box.svg' @@ -474,6 +475,7 @@ export const iconMap = { 'ic-monitoring': ICMonitoring, 'ic-more-vertical': ICMoreVertical, 'ic-namespace': ICNamespace, + 'ic-new-chat': ICNewChat, 'ic-new': ICNew, 'ic-node-script': ICNodeScript, 'ic-oidc': ICOidc, diff --git a/src/Shared/Providers/MainContextProvider/types.ts b/src/Shared/Providers/MainContextProvider/types.ts index f04949c4d..0ab1831b0 100644 --- a/src/Shared/Providers/MainContextProvider/types.ts +++ b/src/Shared/Providers/MainContextProvider/types.ts @@ -48,6 +48,7 @@ export interface SidePanelConfig { /** URL to documentation that should be displayed in the panel */ docLink: string | null aiSessionId?: string + isExpandedView?: boolean } type AIAgentContextType = { diff --git a/src/index.ts b/src/index.ts index 3ffecebf1..627c7329f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -194,6 +194,7 @@ declare global { interface Window { __BASE_URL__: string __ORCHESTRATOR_ROOT__: string + __ATHENA_ROOT__: string _env_: customEnv } }