UI Extensions: Add openInNewTab property to link extensions (#114831)

feat: add `openInNewTab` property for link extensions
This commit is contained in:
Levente Balogh
2025-12-08 12:09:56 +01:00
committed by GitHub
parent 7c5457a75e
commit 5a8a730cfe
6 changed files with 20 additions and 1 deletions
@@ -30,6 +30,7 @@ export type PluginExtensionLink = PluginExtensionBase & {
onClick?: (event?: React.MouseEvent) => void;
icon?: IconName;
category?: string;
openInNewTab?: boolean;
};
export type PluginExtensionComponentMeta = Omit<PluginExtensionComponent, 'component'>;
@@ -86,6 +87,7 @@ export type PluginExtensionAddedComponentConfig<Props = {}> = PluginExtensionCon
*/
component: React.ComponentType<Props>;
};
export type PluginExtensionAddedFunctionConfig<Signature = unknown> = PluginExtensionConfigBase & {
/**
* The target extension points where the component will be added
@@ -106,6 +108,7 @@ export type PluginAddedLinksConfigureFunc<Context extends object> = (context: Re
onClick: (event: React.MouseEvent | undefined, helpers: PluginExtensionEventHelpers<Context>) => void;
icon: IconName;
category: string;
openInNewTab: boolean;
}>
| undefined;
@@ -137,6 +140,10 @@ export type PluginExtensionAddedLinkConfig<Context extends object = object> = Pl
// (Optional) A category to be used when grouping the options in the ui
category?: string;
// (Optional) If true, opens the link in a new tab (renders with target="_blank")
// (Important: this is not guaranteed, depends on the extension point if it implements it.)
openInNewTab?: boolean;
};
export type PluginExtensionExposedComponentConfig<Props = {}> = PluginExtensionConfigBase & {
@@ -95,6 +95,7 @@ describe('AddedLinksRegistry', () => {
path: `/a/${pluginId}/declare-incident`,
targets: 'plugins/myorg-basic-app/start',
configure: jest.fn().mockImplementation((context) => ({ title: context?.title })),
openInNewTab: true,
},
],
});
@@ -120,6 +121,7 @@ describe('AddedLinksRegistry', () => {
path: `/a/${pluginId}/declare-incident`,
extensionPointId: 'plugins/myorg-basic-app/start',
configure: expect.any(Function),
openInNewTab: true,
},
],
});
@@ -21,6 +21,7 @@ export type AddedLinkRegistryItem<Context extends object = object> = {
configure?: PluginAddedLinksConfigureFunc<Context>;
icon?: IconName;
category?: string;
openInNewTab?: boolean;
};
export class AddedLinksRegistry extends Registry<AddedLinkRegistryItem[], PluginExtensionAddedLinkConfig> {
@@ -40,13 +41,14 @@ export class AddedLinksRegistry extends Registry<AddedLinkRegistryItem[], Plugin
const { pluginId, configs } = item;
for (const config of configs) {
const { path, title, description, configure, onClick, targets } = config;
const { path, title, description, configure, onClick, targets, openInNewTab } = config;
const configLog = this.logger.child({
path: path ?? '',
description: description ?? '',
title,
pluginId,
onClick: typeof onClick,
openInNewTab: openInNewTab ? 'true' : 'false',
});
if (!title) {
@@ -167,6 +167,7 @@ describe('usePluginLinks()', () => {
title: '2',
description: '2',
path: `/a/${pluginId}/2`,
openInNewTab: true,
},
{
targets: 'plugins/another-extension/v1',
@@ -181,7 +182,9 @@ describe('usePluginLinks()', () => {
expect(result.current.links.length).toBe(2);
expect(result.current.links[0].title).toBe('1');
expect(result.current.links[0].openInNewTab).toBeUndefined();
expect(result.current.links[1].title).toBe('2');
expect(result.current.links[1].openInNewTab).toBe(true);
});
it('should dynamically update the extensions registered for a certain extension point', () => {
@@ -51,6 +51,7 @@ export function usePluginLinks({
title: addedLink.title,
description: addedLink.description ?? '',
onClick: typeof addedLink.onClick,
openInNewTab: addedLink.openInNewTab ? 'true' : 'false',
});
// Only limit if the `limitPerPlugin` is set
@@ -84,6 +85,7 @@ export function usePluginLinks({
description: overrides?.description || addedLink.description || '',
path: isString(path) ? getLinkExtensionPathWithTracking(pluginId, path, extensionPointId) : undefined,
category: overrides?.category || addedLink.category,
openInNewTab: overrides?.openInNewTab ?? addedLink.openInNewTab,
};
extensions.push(extension);
@@ -474,12 +474,14 @@ export function getLinkExtensionOverrides(
return undefined;
}
// Only allowing to override the following properties
let {
title = config.title,
description = config.description,
path = config.path,
icon = config.icon,
category = config.category,
openInNewTab = config.openInNewTab,
...rest
} = overrides;
@@ -504,6 +506,7 @@ export function getLinkExtensionOverrides(
path,
icon,
category,
openInNewTab,
};
} catch (error) {
if (error instanceof Error) {