mirror of
https://github.com/grafana/grafana.git
synced 2025-07-29 01:22:21 +08:00
New link extension point for DatasourceTestingStatus (#107571)
This commit is contained in:

committed by
GitHub

parent
8eef17cb37
commit
d1f785c8bf
@ -561,6 +561,7 @@ export {
|
|||||||
type ComponentTypeWithExtensionMeta,
|
type ComponentTypeWithExtensionMeta,
|
||||||
type PluginExtensionFunction,
|
type PluginExtensionFunction,
|
||||||
type PluginExtensionEventHelpers,
|
type PluginExtensionEventHelpers,
|
||||||
|
type DataSourceConfigErrorStatusContext,
|
||||||
type PluginExtensionPanelContext,
|
type PluginExtensionPanelContext,
|
||||||
type PluginExtensionQueryEditorRowAdaptiveTelemetryV1Context,
|
type PluginExtensionQueryEditorRowAdaptiveTelemetryV1Context,
|
||||||
type PluginExtensionDataSourceConfigContext,
|
type PluginExtensionDataSourceConfigContext,
|
||||||
|
@ -188,6 +188,7 @@ export enum PluginExtensionPoints {
|
|||||||
CommandPalette = 'grafana/commandpalette/action',
|
CommandPalette = 'grafana/commandpalette/action',
|
||||||
DashboardPanelMenu = 'grafana/dashboard/panel/menu',
|
DashboardPanelMenu = 'grafana/dashboard/panel/menu',
|
||||||
DataSourceConfig = 'grafana/datasources/config',
|
DataSourceConfig = 'grafana/datasources/config',
|
||||||
|
DataSourceConfigErrorStatus = 'grafana/datasources/config/error-status',
|
||||||
ExploreToolbarAction = 'grafana/explore/toolbar/action',
|
ExploreToolbarAction = 'grafana/explore/toolbar/action',
|
||||||
UserProfileTab = 'grafana/user/profile/tab',
|
UserProfileTab = 'grafana/user/profile/tab',
|
||||||
TraceViewDetails = 'grafana/traceview/details',
|
TraceViewDetails = 'grafana/traceview/details',
|
||||||
@ -249,6 +250,19 @@ export type PluginExtensionResourceAttributesContext = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type DataSourceConfigErrorStatusContext = {
|
||||||
|
dataSource: {
|
||||||
|
type: string;
|
||||||
|
uid: string;
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
testingStatus: {
|
||||||
|
message?: string | null;
|
||||||
|
status?: string | null;
|
||||||
|
details?: Record<string, unknown>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
type Dashboard = {
|
type Dashboard = {
|
||||||
uid: string;
|
uid: string;
|
||||||
title: string;
|
title: string;
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen, fireEvent } from '@testing-library/react';
|
||||||
|
|
||||||
|
import { PluginExtensionTypes } from '@grafana/data';
|
||||||
|
import { setPluginLinksHook } from '@grafana/runtime';
|
||||||
|
|
||||||
import { getMockDataSource } from '../mocks/dataSourcesMocks';
|
import { getMockDataSource } from '../mocks/dataSourcesMocks';
|
||||||
|
|
||||||
import { DataSourceTestingStatus, Props } from './DataSourceTestingStatus';
|
import { DataSourceTestingStatus, Props } from './DataSourceTestingStatus';
|
||||||
|
|
||||||
|
setPluginLinksHook(() => ({ links: [], isLoading: false }));
|
||||||
|
|
||||||
const getProps = (partialProps?: Partial<Props>): Props => ({
|
const getProps = (partialProps?: Partial<Props>): Props => ({
|
||||||
testingStatus: {
|
testingStatus: {
|
||||||
status: 'success',
|
status: 'success',
|
||||||
@ -89,4 +94,106 @@ describe('<DataSourceTestingStatus />', () => {
|
|||||||
expect(() => screen.getByTestId('data-testid Alert success')).toThrow();
|
expect(() => screen.getByTestId('data-testid Alert success')).toThrow();
|
||||||
expect(() => screen.getByTestId('data-testid Alert error')).toThrow();
|
expect(() => screen.getByTestId('data-testid Alert error')).toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Plugin links', () => {
|
||||||
|
// Helper function to create mock plugin link extensions with all required properties
|
||||||
|
const createMockPluginLink = (
|
||||||
|
overrides: Partial<{
|
||||||
|
id: string;
|
||||||
|
path: string;
|
||||||
|
onClick: jest.Mock;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
pluginId: string;
|
||||||
|
}> = {}
|
||||||
|
) => ({
|
||||||
|
id: 'test-link',
|
||||||
|
type: PluginExtensionTypes.link as const,
|
||||||
|
title: 'Test Link',
|
||||||
|
description: 'Test link description',
|
||||||
|
pluginId: 'test-plugin',
|
||||||
|
path: '/test',
|
||||||
|
onClick: jest.fn(),
|
||||||
|
...overrides,
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
// Reset the hook to default empty state
|
||||||
|
setPluginLinksHook(() => ({ links: [], isLoading: false }));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render plugin links when severity is error and links exist', () => {
|
||||||
|
const mockLinks = [
|
||||||
|
createMockPluginLink({ id: 'link1', path: 'http://example.com/help', title: 'Help Documentation' }),
|
||||||
|
createMockPluginLink({ id: 'link2', path: 'http://example.com/troubleshoot', title: 'Troubleshooting Guide' }),
|
||||||
|
];
|
||||||
|
|
||||||
|
setPluginLinksHook(() => ({ links: mockLinks, isLoading: false }));
|
||||||
|
|
||||||
|
const props = getProps({
|
||||||
|
testingStatus: {
|
||||||
|
status: 'error',
|
||||||
|
message: 'Data source connection failed',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
render(<DataSourceTestingStatus {...props} />);
|
||||||
|
|
||||||
|
expect(screen.getByText('Help Documentation')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('Troubleshooting Guide')).toBeInTheDocument();
|
||||||
|
|
||||||
|
const helpLink = screen.getByText('Help Documentation').closest('a');
|
||||||
|
const troubleshootLink = screen.getByText('Troubleshooting Guide').closest('a');
|
||||||
|
|
||||||
|
expect(helpLink).toHaveAttribute('href', 'http://example.com/help');
|
||||||
|
expect(troubleshootLink).toHaveAttribute('href', 'http://example.com/troubleshoot');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call onClick handler when plugin link is clicked', () => {
|
||||||
|
const mockOnClick = jest.fn();
|
||||||
|
const mockLinks = [
|
||||||
|
createMockPluginLink({
|
||||||
|
id: 'link1',
|
||||||
|
path: 'http://example.com/help',
|
||||||
|
onClick: mockOnClick,
|
||||||
|
title: 'Help Documentation',
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
|
||||||
|
setPluginLinksHook(() => ({ links: mockLinks, isLoading: false }));
|
||||||
|
|
||||||
|
const props = getProps({
|
||||||
|
testingStatus: {
|
||||||
|
status: 'error',
|
||||||
|
message: 'Data source connection failed',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
render(<DataSourceTestingStatus {...props} />);
|
||||||
|
|
||||||
|
const helpLink = screen.getByText('Help Documentation');
|
||||||
|
fireEvent.click(helpLink);
|
||||||
|
|
||||||
|
expect(mockOnClick).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should NOT render plugin links when severity is not error even if links exist', () => {
|
||||||
|
const mockLinks = [
|
||||||
|
createMockPluginLink({ id: 'link1', path: 'http://example.com/help', title: 'Help Documentation' }),
|
||||||
|
];
|
||||||
|
|
||||||
|
setPluginLinksHook(() => ({ links: mockLinks, isLoading: false }));
|
||||||
|
|
||||||
|
const props = getProps({
|
||||||
|
testingStatus: {
|
||||||
|
status: 'success',
|
||||||
|
message: 'Data source is working',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
render(<DataSourceTestingStatus {...props} />);
|
||||||
|
|
||||||
|
expect(screen.queryByText('Help Documentation')).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import { css, cx } from '@emotion/css';
|
import { css, cx } from '@emotion/css';
|
||||||
import { HTMLAttributes } from 'react';
|
import { HTMLAttributes } from 'react';
|
||||||
|
|
||||||
import { DataSourceSettings as DataSourceSettingsType, GrafanaTheme2 } from '@grafana/data';
|
import { DataSourceSettings as DataSourceSettingsType, GrafanaTheme2, PluginExtensionPoints } from '@grafana/data';
|
||||||
|
import { sanitizeUrl } from '@grafana/data/internal';
|
||||||
import { selectors as e2eSelectors } from '@grafana/e2e-selectors';
|
import { selectors as e2eSelectors } from '@grafana/e2e-selectors';
|
||||||
import { Trans, t } from '@grafana/i18n';
|
import { Trans, t } from '@grafana/i18n';
|
||||||
import { TestingStatus, config } from '@grafana/runtime';
|
import { TestingStatus, config, usePluginLinks } from '@grafana/runtime';
|
||||||
import { AlertVariant, Alert, useTheme2, Link, useStyles2 } from '@grafana/ui';
|
import { AlertVariant, Alert, useTheme2, Link, useStyles2 } from '@grafana/ui';
|
||||||
|
|
||||||
import { contextSrv } from '../../../core/core';
|
import { contextSrv } from '../../../core/core';
|
||||||
@ -147,6 +148,18 @@ export function DataSourceTestingStatus({ testingStatus, exploreUrl, dataSource
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
const styles = useStyles2(getTestingStatusStyles);
|
const styles = useStyles2(getTestingStatusStyles);
|
||||||
|
const { links } = usePluginLinks({
|
||||||
|
extensionPointId: PluginExtensionPoints.DataSourceConfigErrorStatus,
|
||||||
|
context: {
|
||||||
|
dataSource: {
|
||||||
|
type: dataSource.type,
|
||||||
|
uid: dataSource.uid,
|
||||||
|
name: dataSource.name,
|
||||||
|
},
|
||||||
|
testingStatus,
|
||||||
|
},
|
||||||
|
limitPerPlugin: 3,
|
||||||
|
});
|
||||||
|
|
||||||
if (message) {
|
if (message) {
|
||||||
return (
|
return (
|
||||||
@ -169,6 +182,22 @@ export function DataSourceTestingStatus({ testingStatus, exploreUrl, dataSource
|
|||||||
) : null}
|
) : null}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
{severity === 'error' && links.length > 0 && (
|
||||||
|
<div className={styles.linksContainer}>
|
||||||
|
{links.map((link) => {
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
key={link.id}
|
||||||
|
href={link.path ? sanitizeUrl(link.path) : undefined}
|
||||||
|
onClick={link.onClick}
|
||||||
|
className={styles.pluginLink}
|
||||||
|
>
|
||||||
|
{link.title}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</Alert>
|
</Alert>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -184,4 +213,23 @@ const getTestingStatusStyles = (theme: GrafanaTheme2) => ({
|
|||||||
moreLink: css({
|
moreLink: css({
|
||||||
marginBlock: theme.spacing(1),
|
marginBlock: theme.spacing(1),
|
||||||
}),
|
}),
|
||||||
|
linksContainer: css({
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'flex-end',
|
||||||
|
marginTop: theme.spacing(1),
|
||||||
|
}),
|
||||||
|
pluginLink: css({
|
||||||
|
color: theme.colors.text.link,
|
||||||
|
textDecoration: 'none',
|
||||||
|
marginLeft: theme.spacing(2),
|
||||||
|
fontSize: theme.typography.bodySmall.fontSize,
|
||||||
|
fontWeight: theme.typography.fontWeightMedium,
|
||||||
|
'&:hover': {
|
||||||
|
color: theme.colors.text.primary,
|
||||||
|
textDecoration: 'underline',
|
||||||
|
},
|
||||||
|
'&:first-child': {
|
||||||
|
marginLeft: 0,
|
||||||
|
},
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
@ -3,7 +3,7 @@ import { useEffect } from 'react';
|
|||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
|
|
||||||
import { DataSourceJsonData, PluginExtensionDataSourceConfigContext, PluginState } from '@grafana/data';
|
import { DataSourceJsonData, PluginExtensionDataSourceConfigContext, PluginState } from '@grafana/data';
|
||||||
import { setPluginComponentsHook } from '@grafana/runtime';
|
import { setPluginComponentsHook, setPluginLinksHook } from '@grafana/runtime';
|
||||||
import { createComponentWithMeta } from 'app/features/plugins/extensions/usePluginComponents';
|
import { createComponentWithMeta } from 'app/features/plugins/extensions/usePluginComponents';
|
||||||
import { configureStore } from 'app/store/configureStore';
|
import { configureStore } from 'app/store/configureStore';
|
||||||
|
|
||||||
@ -27,6 +27,8 @@ jest.mock('@grafana/runtime', () => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setPluginLinksHook(() => ({ links: [], isLoading: false }));
|
||||||
|
|
||||||
const setup = (props?: Partial<ViewProps>) => {
|
const setup = (props?: Partial<ViewProps>) => {
|
||||||
const store = configureStore();
|
const store = configureStore();
|
||||||
|
|
||||||
|
@ -365,6 +365,21 @@ describe('Plugin Extension Validators', () => {
|
|||||||
expect(log.warning).toHaveBeenCalledTimes(1);
|
expect(log.warning).toHaveBeenCalledTimes(1);
|
||||||
expect(jest.mocked(log.warning).mock.calls[0][0]).toMatch('"description" doesn\'t match');
|
expect(jest.mocked(log.warning).mock.calls[0][0]).toMatch('"description" doesn\'t match');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should return FALSE with links with the same title but different targets', () => {
|
||||||
|
const log = createLogMock();
|
||||||
|
config.apps[pluginId].extensions.addedLinks.push(extensionConfig);
|
||||||
|
const extensionConfig2 = {
|
||||||
|
...extensionConfig,
|
||||||
|
targets: [PluginExtensionPoints.ExploreToolbarAction],
|
||||||
|
};
|
||||||
|
config.apps[pluginId].extensions.addedLinks.push(extensionConfig2);
|
||||||
|
|
||||||
|
const returnValue = isAddedLinkMetaInfoMissing(pluginId, extensionConfig2, log);
|
||||||
|
|
||||||
|
expect(returnValue).toBe(false);
|
||||||
|
expect(log.error).toHaveBeenCalledTimes(0);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('isAddedComponentMetaInfoMissing()', () => {
|
describe('isAddedComponentMetaInfoMissing()', () => {
|
||||||
@ -482,6 +497,21 @@ describe('Plugin Extension Validators', () => {
|
|||||||
expect(log.warning).toHaveBeenCalledTimes(1);
|
expect(log.warning).toHaveBeenCalledTimes(1);
|
||||||
expect(jest.mocked(log.warning).mock.calls[0][0]).toMatch('"description" doesn\'t match');
|
expect(jest.mocked(log.warning).mock.calls[0][0]).toMatch('"description" doesn\'t match');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should return FALSE with components with the same title but different targets', () => {
|
||||||
|
const log = createLogMock();
|
||||||
|
config.apps[pluginId].extensions.addedComponents.push(extensionConfig);
|
||||||
|
const extensionConfig2 = {
|
||||||
|
...extensionConfig,
|
||||||
|
targets: [PluginExtensionPoints.ExploreToolbarAction],
|
||||||
|
};
|
||||||
|
config.apps[pluginId].extensions.addedComponents.push(extensionConfig2);
|
||||||
|
|
||||||
|
const returnValue = isAddedComponentMetaInfoMissing(pluginId, extensionConfig2, log);
|
||||||
|
|
||||||
|
expect(returnValue).toBe(false);
|
||||||
|
expect(log.error).toHaveBeenCalledTimes(0);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('isExposedComponentMetaInfoMissing()', () => {
|
describe('isExposedComponentMetaInfoMissing()', () => {
|
||||||
@ -600,6 +630,21 @@ describe('Plugin Extension Validators', () => {
|
|||||||
expect(log.warning).toHaveBeenCalledTimes(1);
|
expect(log.warning).toHaveBeenCalledTimes(1);
|
||||||
expect(jest.mocked(log.warning).mock.calls[0][0]).toMatch('"description" doesn\'t match');
|
expect(jest.mocked(log.warning).mock.calls[0][0]).toMatch('"description" doesn\'t match');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should return FALSE with components with the same title but different targets', () => {
|
||||||
|
const log = createLogMock();
|
||||||
|
config.apps[pluginId].extensions.exposedComponents.push(exposedComponentConfig);
|
||||||
|
const exposedComponentConfig2 = {
|
||||||
|
...exposedComponentConfig,
|
||||||
|
targets: [PluginExtensionPoints.ExploreToolbarAction],
|
||||||
|
};
|
||||||
|
config.apps[pluginId].extensions.exposedComponents.push(exposedComponentConfig2);
|
||||||
|
|
||||||
|
const returnValue = isExposedComponentMetaInfoMissing(pluginId, exposedComponentConfig2, log);
|
||||||
|
|
||||||
|
expect(returnValue).toBe(false);
|
||||||
|
expect(log.error).toHaveBeenCalledTimes(0);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('isExposedComponentDependencyMissing()', () => {
|
describe('isExposedComponentDependencyMissing()', () => {
|
||||||
|
@ -155,25 +155,25 @@ export const isAddedLinkMetaInfoMissing = (
|
|||||||
) => {
|
) => {
|
||||||
const logPrefix = 'Could not register link extension. Reason:';
|
const logPrefix = 'Could not register link extension. Reason:';
|
||||||
const app = config.apps[pluginId];
|
const app = config.apps[pluginId];
|
||||||
const pluginJsonMetaInfo = app ? app.extensions.addedLinks.find(({ title }) => title === metaInfo.title) : null;
|
const pluginJsonMetaInfo = app ? app.extensions.addedLinks.filter(({ title }) => title === metaInfo.title) : null;
|
||||||
|
|
||||||
if (!app) {
|
if (!app) {
|
||||||
log.error(`${logPrefix} ${errors.APP_NOT_FOUND(pluginId)}`);
|
log.error(`${logPrefix} ${errors.APP_NOT_FOUND(pluginId)}`);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pluginJsonMetaInfo) {
|
if (!pluginJsonMetaInfo || pluginJsonMetaInfo.length === 0) {
|
||||||
log.error(`${logPrefix} ${errors.ADDED_LINK_META_INFO_MISSING}`);
|
log.error(`${logPrefix} ${errors.ADDED_LINK_META_INFO_MISSING}`);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const targets = Array.isArray(metaInfo.targets) ? metaInfo.targets : [metaInfo.targets];
|
const targets = Array.isArray(metaInfo.targets) ? metaInfo.targets : [metaInfo.targets];
|
||||||
if (!targets.every((target) => pluginJsonMetaInfo.targets.includes(target))) {
|
if (!targets.every((target) => pluginJsonMetaInfo.some(({ targets }) => targets.includes(target)))) {
|
||||||
log.error(`${logPrefix} ${errors.TARGET_NOT_MATCHING_META_INFO}`);
|
log.error(`${logPrefix} ${errors.TARGET_NOT_MATCHING_META_INFO}`);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pluginJsonMetaInfo.description !== metaInfo.description) {
|
if (pluginJsonMetaInfo.some(({ description }) => description !== metaInfo.description)) {
|
||||||
log.warning(errors.DESCRIPTION_NOT_MATCHING_META_INFO);
|
log.warning(errors.DESCRIPTION_NOT_MATCHING_META_INFO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,25 +187,25 @@ export const isAddedFunctionMetaInfoMissing = (
|
|||||||
) => {
|
) => {
|
||||||
const logPrefix = 'Could not register function extension. Reason:';
|
const logPrefix = 'Could not register function extension. Reason:';
|
||||||
const app = config.apps[pluginId];
|
const app = config.apps[pluginId];
|
||||||
const pluginJsonMetaInfo = app ? app.extensions.addedFunctions.find(({ title }) => title === metaInfo.title) : null;
|
const pluginJsonMetaInfo = app ? app.extensions.addedFunctions.filter(({ title }) => title === metaInfo.title) : null;
|
||||||
|
|
||||||
if (!app) {
|
if (!app) {
|
||||||
log.error(`${logPrefix} ${errors.APP_NOT_FOUND(pluginId)}`);
|
log.error(`${logPrefix} ${errors.APP_NOT_FOUND(pluginId)}`);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pluginJsonMetaInfo) {
|
if (!pluginJsonMetaInfo || pluginJsonMetaInfo.length === 0) {
|
||||||
log.error(`${logPrefix} ${errors.ADDED_FUNCTION_META_INFO_MISSING}`);
|
log.error(`${logPrefix} ${errors.ADDED_FUNCTION_META_INFO_MISSING}`);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const targets = Array.isArray(metaInfo.targets) ? metaInfo.targets : [metaInfo.targets];
|
const targets = Array.isArray(metaInfo.targets) ? metaInfo.targets : [metaInfo.targets];
|
||||||
if (!targets.every((target) => pluginJsonMetaInfo.targets.includes(target))) {
|
if (!targets.every((target) => pluginJsonMetaInfo.some(({ targets }) => targets.includes(target)))) {
|
||||||
log.error(`${logPrefix} ${errors.TARGET_NOT_MATCHING_META_INFO}`);
|
log.error(`${logPrefix} ${errors.TARGET_NOT_MATCHING_META_INFO}`);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pluginJsonMetaInfo.description !== metaInfo.description) {
|
if (pluginJsonMetaInfo.some(({ description }) => description !== metaInfo.description)) {
|
||||||
log.warning(errors.DESCRIPTION_NOT_MATCHING_META_INFO);
|
log.warning(errors.DESCRIPTION_NOT_MATCHING_META_INFO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,25 +219,27 @@ export const isAddedComponentMetaInfoMissing = (
|
|||||||
) => {
|
) => {
|
||||||
const logPrefix = 'Could not register component extension. Reason:';
|
const logPrefix = 'Could not register component extension. Reason:';
|
||||||
const app = config.apps[pluginId];
|
const app = config.apps[pluginId];
|
||||||
const pluginJsonMetaInfo = app ? app.extensions.addedComponents.find(({ title }) => title === metaInfo.title) : null;
|
const pluginJsonMetaInfo = app
|
||||||
|
? app.extensions.addedComponents.filter(({ title }) => title === metaInfo.title)
|
||||||
|
: null;
|
||||||
|
|
||||||
if (!app) {
|
if (!app) {
|
||||||
log.error(`${logPrefix} ${errors.APP_NOT_FOUND(pluginId)}`);
|
log.error(`${logPrefix} ${errors.APP_NOT_FOUND(pluginId)}`);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pluginJsonMetaInfo) {
|
if (!pluginJsonMetaInfo || pluginJsonMetaInfo.length === 0) {
|
||||||
log.error(`${logPrefix} ${errors.ADDED_COMPONENT_META_INFO_MISSING}`);
|
log.error(`${logPrefix} ${errors.ADDED_COMPONENT_META_INFO_MISSING}`);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const targets = Array.isArray(metaInfo.targets) ? metaInfo.targets : [metaInfo.targets];
|
const targets = Array.isArray(metaInfo.targets) ? metaInfo.targets : [metaInfo.targets];
|
||||||
if (!targets.every((target) => pluginJsonMetaInfo.targets.includes(target))) {
|
if (!targets.every((target) => pluginJsonMetaInfo.some(({ targets }) => targets.includes(target)))) {
|
||||||
log.error(`${logPrefix} ${errors.TARGET_NOT_MATCHING_META_INFO}`);
|
log.error(`${logPrefix} ${errors.TARGET_NOT_MATCHING_META_INFO}`);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pluginJsonMetaInfo.description !== metaInfo.description) {
|
if (pluginJsonMetaInfo.some(({ description }) => description !== metaInfo.description)) {
|
||||||
log.warning(errors.DESCRIPTION_NOT_MATCHING_META_INFO);
|
log.warning(errors.DESCRIPTION_NOT_MATCHING_META_INFO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,24 +253,24 @@ export const isExposedComponentMetaInfoMissing = (
|
|||||||
) => {
|
) => {
|
||||||
const logPrefix = 'Could not register exposed component extension. Reason:';
|
const logPrefix = 'Could not register exposed component extension. Reason:';
|
||||||
const app = config.apps[pluginId];
|
const app = config.apps[pluginId];
|
||||||
const pluginJsonMetaInfo = app ? app.extensions.exposedComponents.find(({ id }) => id === metaInfo.id) : null;
|
const pluginJsonMetaInfo = app ? app.extensions.exposedComponents.filter(({ id }) => id === metaInfo.id) : null;
|
||||||
|
|
||||||
if (!app) {
|
if (!app) {
|
||||||
log.error(`${logPrefix} ${errors.APP_NOT_FOUND(pluginId)}`);
|
log.error(`${logPrefix} ${errors.APP_NOT_FOUND(pluginId)}`);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pluginJsonMetaInfo) {
|
if (!pluginJsonMetaInfo || pluginJsonMetaInfo.length === 0) {
|
||||||
log.error(`${logPrefix} ${errors.EXPOSED_COMPONENT_META_INFO_MISSING}`);
|
log.error(`${logPrefix} ${errors.EXPOSED_COMPONENT_META_INFO_MISSING}`);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pluginJsonMetaInfo.title !== metaInfo.title) {
|
if (pluginJsonMetaInfo.some(({ title }) => title !== metaInfo.title)) {
|
||||||
log.error(`${logPrefix} ${errors.TITLE_NOT_MATCHING_META_INFO}`);
|
log.error(`${logPrefix} ${errors.TITLE_NOT_MATCHING_META_INFO}`);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pluginJsonMetaInfo.description !== metaInfo.description) {
|
if (pluginJsonMetaInfo.some(({ description }) => description !== metaInfo.description)) {
|
||||||
log.warning(errors.DESCRIPTION_NOT_MATCHING_META_INFO);
|
log.warning(errors.DESCRIPTION_NOT_MATCHING_META_INFO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user