Skip to content

Commit 0e434cf

Browse files
authored
Merge pull request RedHatInsights#300 from apinkert/doc-link
Point API doc links to console
2 parents bb2378f + 7f0d94d commit 0e434cf

2 files changed

Lines changed: 166 additions & 5 deletions

File tree

src/components/HelpPanel/HelpPanelTabs/APIPanel.test.tsx

Lines changed: 114 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import React from 'react';
22
import { render, screen, waitFor } from '@testing-library/react';
33
import { IntlProvider } from 'react-intl';
4-
import APIPanel from './APIPanel';
4+
import APIPanel, {
5+
convertToConsoleDocsUrl,
6+
getConsoleBaseUrl,
7+
} from './APIPanel';
58
import {
69
fetchBundleInfo,
710
fetchBundles,
@@ -245,3 +248,113 @@ describe('APIPanel', () => {
245248
expect(screen.getByText('Cost-Management')).toBeInTheDocument();
246249
});
247250
});
251+
252+
describe('getConsoleBaseUrl', () => {
253+
it('returns production URL for prod environment', () => {
254+
expect(getConsoleBaseUrl('prod')).toBe('https://console.redhat.com');
255+
});
256+
257+
it('returns stage URL for stage environment', () => {
258+
expect(getConsoleBaseUrl('stage')).toBe('https://console.stage.redhat.com');
259+
});
260+
261+
it('returns stage URL for frhStage environment', () => {
262+
expect(getConsoleBaseUrl('frhStage')).toBe(
263+
'https://console.stage.redhat.com'
264+
);
265+
});
266+
267+
it('returns production URL for qa environment (default)', () => {
268+
expect(getConsoleBaseUrl('qa')).toBe('https://console.redhat.com');
269+
});
270+
271+
it('returns production URL for ci environment (default)', () => {
272+
expect(getConsoleBaseUrl('ci')).toBe('https://console.redhat.com');
273+
});
274+
});
275+
276+
describe('convertToConsoleDocsUrl', () => {
277+
it('converts API name and version to console docs URL (production)', () => {
278+
const result = convertToConsoleDocsUrl(
279+
'notifications',
280+
'https://developers.redhat.com/api-catalog/api/notifications/v2.0',
281+
'prod'
282+
);
283+
284+
expect(result).toBe('https://console.redhat.com/docs/api/notifications/v2');
285+
});
286+
287+
it('converts API name and version to console docs URL (stage)', () => {
288+
const result = convertToConsoleDocsUrl(
289+
'notifications',
290+
'https://developers.redhat.com/api-catalog/api/notifications/v2.0',
291+
'stage'
292+
);
293+
294+
expect(result).toBe(
295+
'https://console.stage.redhat.com/docs/api/notifications/v2'
296+
);
297+
});
298+
299+
it('strips API suffix from name', () => {
300+
const result = convertToConsoleDocsUrl(
301+
'notifications api',
302+
'https://developers.redhat.com/api-catalog/api/notifications/v1',
303+
'prod'
304+
);
305+
306+
expect(result).toBe('https://console.redhat.com/docs/api/notifications/v1');
307+
});
308+
309+
it('handles APIs without version numbers', () => {
310+
const result = convertToConsoleDocsUrl(
311+
'advisor api',
312+
'https://developers.redhat.com/api-catalog/api/advisor',
313+
'prod'
314+
);
315+
316+
expect(result).toBe('https://console.redhat.com/docs/api/advisor');
317+
});
318+
319+
it('extracts only major version from v1.0', () => {
320+
const result = convertToConsoleDocsUrl(
321+
'notifications',
322+
'https://developers.redhat.com/api-catalog/api/notifications/v1.0',
323+
'prod'
324+
);
325+
326+
expect(result).toBe('https://console.redhat.com/docs/api/notifications/v1');
327+
});
328+
329+
it('extracts major version from v3.1.0', () => {
330+
const result = convertToConsoleDocsUrl(
331+
'sources',
332+
'https://developers.redhat.com/api-catalog/api/sources/v3.1.0',
333+
'prod'
334+
);
335+
336+
expect(result).toBe('https://console.redhat.com/docs/api/sources/v3');
337+
});
338+
339+
it('lowercases API name', () => {
340+
const result = convertToConsoleDocsUrl(
341+
'RBAC',
342+
'https://developers.redhat.com/api-catalog/api/rbac/v1',
343+
'prod'
344+
);
345+
346+
expect(result).toBe('https://console.redhat.com/docs/api/rbac/v1');
347+
});
348+
349+
it('handles frhStage environment correctly', () => {
350+
const result = convertToConsoleDocsUrl(
351+
'notifications',
352+
'https://developers.redhat.com/api-catalog/api/notifications/v2.0',
353+
'frhStage'
354+
);
355+
356+
expect(result).toBe(
357+
'https://console.stage.redhat.com/docs/api/notifications/v2'
358+
);
359+
});
360+
});

src/components/HelpPanel/HelpPanelTabs/APIPanel.tsx

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import {
2121
ToolbarContent,
2222
ToolbarItem,
2323
} from '@patternfly/react-core';
24-
import { ExternalLinkAltIcon } from '@patternfly/react-icons';
2524
import { useChrome } from '@redhat-cloud-services/frontend-components/useChrome';
2625
import { useIntl } from 'react-intl';
2726
import messages from '../../../Messages';
@@ -134,6 +133,48 @@ const formatApiDisplayName = (name: string, url: string): string => {
134133
return version ? `${capitalizedName} ${version}` : capitalizedName;
135134
};
136135

136+
/**
137+
* Gets the base console URL based on the current environment
138+
* Uses Chrome API's getEnvironment() to determine environment
139+
* @param environment - Environment string from chrome.getEnvironment() ('prod', 'stage', 'qa', etc.)
140+
* @returns Base console URL (e.g., "https://console.redhat.com" or "https://console.stage.redhat.com")
141+
*/
142+
export const getConsoleBaseUrl = (environment: string): string => {
143+
// Stage environments (including frhStage for federal stage)
144+
if (environment === 'stage' || environment === 'frhStage') {
145+
return 'https://console.stage.redhat.com';
146+
}
147+
148+
// Production (prod and all other environments default to production console)
149+
return 'https://console.redhat.com';
150+
};
151+
152+
/**
153+
* Converts backend API URL to console docs URL (environment-aware)
154+
* @param name - The raw API name (e.g., "notifications", "rbac")
155+
* @param url - The backend URL to extract version from
156+
* @param environment - Environment string from chrome.getEnvironment()
157+
* @returns Console API docs URL (e.g., "https://console.redhat.com/docs/api/notifications/v2")
158+
*/
159+
export const convertToConsoleDocsUrl = (
160+
name: string,
161+
url: string,
162+
environment: string
163+
): string => {
164+
const nameWithoutApiSuffix = stripApiSuffix(name).toLowerCase();
165+
const version = extractVersionFromUrl(url);
166+
const baseUrl = getConsoleBaseUrl(environment);
167+
168+
if (version) {
169+
// Remove decimal points from version (v1.0 → v1, v2.0 → v2)
170+
const majorVersion = version.split('.')[0];
171+
return `${baseUrl}/docs/api/${nameWithoutApiSuffix}/${majorVersion}`;
172+
}
173+
174+
// Fallback if no version found
175+
return `${baseUrl}/docs/api/${nameWithoutApiSuffix}`;
176+
};
177+
137178
const mapBundleInfoWithTitles = async (): Promise<APIDoc[]> => {
138179
try {
139180
const [bundleInfoList, bundles] = await Promise.all([
@@ -191,8 +232,17 @@ const mapBundleInfoWithTitles = async (): Promise<APIDoc[]> => {
191232
};
192233

193234
const APIResourceItem: React.FC<{ resource: APIDoc }> = ({ resource }) => {
235+
const chrome = useChrome();
236+
194237
const handleResourceClick = () => {
195-
window.open(resource.url, '_blank', 'noopener,noreferrer');
238+
const environment = chrome.getEnvironment();
239+
const consoleDocsUrl = convertToConsoleDocsUrl(
240+
resource.name,
241+
resource.url,
242+
environment
243+
);
244+
// Navigate within the same page (keeps help panel open)
245+
window.location.href = consoleDocsUrl;
196246
};
197247

198248
return (
@@ -213,8 +263,6 @@ const APIResourceItem: React.FC<{ resource: APIDoc }> = ({ resource }) => {
213263
onClick={handleResourceClick}
214264
isInline
215265
className="pf-v6-u-text-align-left pf-v6-u-p-0"
216-
icon={<ExternalLinkAltIcon />}
217-
iconPosition="end"
218266
>
219267
{resource.displayName}
220268
</Button>

0 commit comments

Comments
 (0)