Plugins: Renamed parts of the UI extension APIs (#63070)

* Renamed target -> id and href -> path after feedback.

* fixed type issues in test page.

* chore(pluginschemajson): update extensions props target -> id

* this is the final.

* fixed typings...again...

---------

Co-authored-by: Jack Westbrook <jack.westbrook@gmail.com>
This commit is contained in:
Marcus Andersson 2023-02-08 11:33:28 +01:00 committed by GitHub
parent b88206d98f
commit f46f8bdd3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 46 additions and 46 deletions

View File

@ -480,7 +480,7 @@
"type": "object",
"description": "Expose a page link that can be used by Grafana core or other plugins to navigate users to the plugin",
"additionalProperties": false,
"required": ["type", "title", "target", "path"],
"required": ["type", "title", "placement", "path"],
"properties": {
"type": {
"type": "string",
@ -491,7 +491,7 @@
"minLength": 3,
"maxLength": 22
},
"target": {
"placement": {
"type": "string",
"pattern": "^(plugins|grafana)/[a-z-/0-9]*$"
},

View File

@ -29,7 +29,7 @@ export enum PluginExtensionTypes {
}
export type PluginsExtensionLinkConfig = {
target: string;
placement: string;
type: PluginExtensionTypes.link;
title: string;
description: string;

View File

@ -13,7 +13,7 @@ describe('getPluginExtensions', () => {
type: 'link',
title: 'Declare incident',
description: 'Declaring an incident in the app',
href: `/a/${pluginId}/declare-incident`,
path: `/a/${pluginId}/declare-incident`,
key: 1,
},
],
@ -22,26 +22,26 @@ describe('getPluginExtensions', () => {
it('should return a collection of extensions to the plugin', () => {
const { extensions, error } = getPluginExtensions({
target: `plugins/${pluginId}/${linkId}`,
placement: `plugins/${pluginId}/${linkId}`,
});
expect(extensions[0].href).toBe(`/a/${pluginId}/declare-incident`);
expect(extensions[0].path).toBe(`/a/${pluginId}/declare-incident`);
expect(error).toBeUndefined();
});
it('should return a description for the requested link', () => {
const { extensions, error } = getPluginExtensions({
target: `plugins/${pluginId}/${linkId}`,
placement: `plugins/${pluginId}/${linkId}`,
});
expect(extensions[0].href).toBe(`/a/${pluginId}/declare-incident`);
expect(extensions[0].path).toBe(`/a/${pluginId}/declare-incident`);
expect(extensions[0].description).toBe('Declaring an incident in the app');
expect(error).toBeUndefined();
});
it('should return an empty array when no links can be found', () => {
const { extensions, error } = getPluginExtensions({
target: `an-unknown-app/${linkId}`,
placement: `an-unknown-app/${linkId}`,
});
expect(extensions.length).toBe(0);

View File

@ -1,7 +1,7 @@
import { getPluginsExtensionRegistry, PluginsExtension } from './registry';
export type GetPluginExtensionsOptions = {
target: string;
placement: string;
};
export type PluginExtensionsResult = {
@ -10,23 +10,23 @@ export type PluginExtensionsResult = {
};
export class PluginExtensionsMissingError extends Error {
readonly target: string;
readonly placement: string;
constructor(target: string) {
super(`Could not find extensions for '${target}'`);
this.target = target;
constructor(placement: string) {
super(`Could not find extensions for '${placement}'`);
this.placement = placement;
this.name = PluginExtensionsMissingError.name;
}
}
export function getPluginExtensions({ target }: GetPluginExtensionsOptions): PluginExtensionsResult {
export function getPluginExtensions({ placement }: GetPluginExtensionsOptions): PluginExtensionsResult {
const registry = getPluginsExtensionRegistry();
const extensions = registry[target];
const extensions = registry[placement];
if (!Array.isArray(extensions)) {
return {
extensions: [],
error: new PluginExtensionsMissingError(target),
error: new PluginExtensionsMissingError(placement),
};
}

View File

@ -2,7 +2,7 @@ export type PluginsExtensionLink = {
type: 'link';
title: string;
description: string;
href: string;
path: string;
key: number;
};

View File

@ -244,7 +244,7 @@ func TestHTTPServer_GetFrontendSettings_apps(t *testing.T) {
return &plugins.FakePluginStore{
PluginList: newPlugins("test-app", []*plugindef.ExtensionsLink{
{
Target: "core/home/menu",
Placement: "core/home/menu",
Type: plugindef.ExtensionsLinkTypeLink,
Title: "Title",
Description: "Home route of app",
@ -267,7 +267,7 @@ func TestHTTPServer_GetFrontendSettings_apps(t *testing.T) {
Version: "0.5.0",
Extensions: []*plugindef.ExtensionsLink{
{
Target: "core/home/menu",
Placement: "core/home/menu",
Type: plugindef.ExtensionsLinkTypeLink,
Title: "Title",
Description: "Home route of app",
@ -284,7 +284,7 @@ func TestHTTPServer_GetFrontendSettings_apps(t *testing.T) {
return &plugins.FakePluginStore{
PluginList: newPlugins("test-app", []*plugindef.ExtensionsLink{
{
Target: "core/home/menu",
Placement: "core/home/menu",
Type: plugindef.ExtensionsLinkTypeLink,
Title: "Title",
Description: "Home route of app",

View File

@ -502,14 +502,14 @@ func TestLoader_Load(t *testing.T) {
},
Extensions: []*plugindef.ExtensionsLink{
{
Target: "plugins/grafana-slo-app/slo-breach",
Placement: "plugins/grafana-slo-app/slo-breach",
Title: "Declare incident",
Type: plugindef.ExtensionsLinkTypeLink,
Description: "Declares a new incident",
Path: "/incidents/declare",
},
{
Target: "plugins/grafana-slo-app/slo-breach",
Placement: "plugins/grafana-slo-app/slo-breach",
Title: "Declare incident",
Type: plugindef.ExtensionsLinkTypeLink,
Description: "Declares a new incident (path without backslash)",

View File

@ -36,14 +36,14 @@
],
"extensions": [
{
"target": "plugins/grafana-slo-app/slo-breach",
"placement": "plugins/grafana-slo-app/slo-breach",
"type": "link",
"title": "Declare incident",
"description": "Declares a new incident",
"path": "/incidents/declare"
},
{
"target": "plugins/grafana-slo-app/slo-breach",
"placement": "plugins/grafana-slo-app/slo-breach",
"type": "link",
"title": "Declare incident",
"description": "Declares a new incident (path without backslash)",

View File

@ -101,7 +101,7 @@ seqs: [
component?: string
// The minimum role a user must have to see this page in the navigation menu.
role?: "Admin" | "Editor" | "Viewer"
role?: "Admin" | "Editor" | "Viewer"
// RBAC action the user must have to access the route
action?: string
@ -124,7 +124,7 @@ seqs: [
#ExtensionsLink: {
// Target where the link will be rendered
target: =~"^(plugins|grafana)\/[a-z-/0-9]*$"
placement: =~"^(plugins|grafana)\/[a-z-/0-9]*$"
// Type of extension
type: "link"
// Title that will be displayed for the rendered link

View File

@ -162,7 +162,7 @@ type ExtensionsLink struct {
Path string `json:"path"`
// Target where the link will be rendered
Target string `json:"target"`
Placement string `json:"placement"`
// Title that will be displayed for the rendered link
Title string `json:"title"`

View File

@ -7,7 +7,7 @@ describe('Plugin registry', () => {
const registry = createPluginExtensionsRegistry({
'belugacdn-app': createConfig([
{
target: 'plugins/belugacdn-app/menu',
placement: 'plugins/belugacdn-app/menu',
title: 'The title',
type: PluginExtensionTypes.link,
description: 'Incidents are occurring!',
@ -16,7 +16,7 @@ describe('Plugin registry', () => {
]),
'strava-app': createConfig([
{
target: 'plugins/strava-app/menu',
placement: 'plugins/strava-app/menu',
title: 'The title',
type: PluginExtensionTypes.link,
description: 'Incidents are occurring!',
@ -25,14 +25,14 @@ describe('Plugin registry', () => {
]),
'duplicate-links-app': createConfig([
{
target: 'plugins/duplicate-links-app/menu',
placement: 'plugins/duplicate-links-app/menu',
title: 'The title',
type: PluginExtensionTypes.link,
description: 'Incidents are occurring!',
path: '/incidents/declare',
},
{
target: 'plugins/duplicate-links-app/menu',
placement: 'plugins/duplicate-links-app/menu',
title: 'The title',
type: PluginExtensionTypes.link,
description: 'Incidents are occurring!',
@ -49,7 +49,7 @@ describe('Plugin registry', () => {
title: 'The title',
type: 'link',
description: 'Incidents are occurring!',
href: '/a/belugacdn-app/incidents/declare',
path: '/a/belugacdn-app/incidents/declare',
key: 539074708,
});
});
@ -68,7 +68,7 @@ describe('Plugin registry', () => {
title: 'The title',
type: 'link',
description: 'Incidents are occurring!',
href: '/a/belugacdn-app/incidents/declare',
path: '/a/belugacdn-app/incidents/declare',
key: 539074708,
});
@ -76,7 +76,7 @@ describe('Plugin registry', () => {
title: 'The title',
type: 'link',
description: 'Incidents are occurring!',
href: '/a/strava-app/incidents/declare',
path: '/a/strava-app/incidents/declare',
key: -1637066384,
});
});

View File

@ -17,15 +17,15 @@ export function createPluginExtensionsRegistry(apps: Record<string, AppPluginCon
}
for (const extension of extensions) {
const target = extension.target;
const placement = extension.placement;
const item = createRegistryItem(pluginId, extension);
if (!Array.isArray(registry[target])) {
registry[target] = [item];
if (!Array.isArray(registry[placement])) {
registry[placement] = [item];
continue;
}
registry[target].push(item);
registry[placement].push(item);
continue;
}
}
@ -38,14 +38,14 @@ export function createPluginExtensionsRegistry(apps: Record<string, AppPluginCon
}
function createRegistryItem(pluginId: string, extension: PluginsExtensionLinkConfig): PluginsExtensionLink {
const href = `/a/${pluginId}${extension.path}`;
const path = `/a/${pluginId}${extension.path}`;
return Object.freeze({
type: PluginExtensionTypes.link,
title: extension.title,
description: extension.description,
href: href,
key: hashKey(`${extension.title}${href}`),
path: path,
key: hashKey(`${extension.title}${path}`),
});
}

View File

@ -62,7 +62,7 @@ export const TestStuffPage = () => {
<Page navModel={{ node: node, main: node }}>
<Page.Contents>
<HorizontalGroup>
<LinkToBasicApp target="grafana/sandbox/testing" />
<LinkToBasicApp placement="grafana/sandbox/testing" />
</HorizontalGroup>
{data && (
<AutoSizer style={{ width: '100%', height: '600px' }}>
@ -148,8 +148,8 @@ export function getDefaultState(): State {
};
}
function LinkToBasicApp({ target }: { target: string }) {
const { extensions, error } = getPluginExtensions({ target });
function LinkToBasicApp({ placement }: { placement: string }) {
const { extensions, error } = getPluginExtensions({ placement });
if (error) {
return null;
@ -159,7 +159,7 @@ function LinkToBasicApp({ target }: { target: string }) {
<div>
{extensions.map((extension) => {
return (
<LinkButton href={extension.href} title={extension.description} key={extension.key}>
<LinkButton href={extension.path} title={extension.description} key={extension.key}>
{extension.title}
</LinkButton>
);