Commit 6b2a47f2 by Torkel Ödegaard Committed by GitHub

Merge pull request #14038 from grafana/plugin-not-found

Plugin not found
parents 7a30220d e331d24a
......@@ -5,13 +5,14 @@ import { getAngularLoader, AngularComponent } from 'app/core/services/AngularLoa
import { importPluginModule } from 'app/features/plugins/plugin_loader';
import { AddPanelPanel } from './AddPanelPanel';
import { getPanelPluginNotFound } from './PanelPluginNotFound';
import { DashboardRow } from './DashboardRow';
import { PanelPlugin } from 'app/types/plugins';
import { PanelChrome } from './PanelChrome';
import { PanelEditor } from './PanelEditor';
import { PanelModel } from '../panel_model';
import { DashboardModel } from '../dashboard_model';
import { PanelPlugin } from 'app/types';
export interface Props {
panel: PanelModel;
......@@ -70,7 +71,7 @@ export class DashboardPanel extends PureComponent<Props, State> {
// handle plugin loading & changing of plugin type
if (!this.state.plugin || this.state.plugin.id !== panel.type) {
const plugin = config.panels[panel.type];
const plugin = config.panels[panel.type] || getPanelPluginNotFound(panel.type);
if (plugin.exports) {
this.cleanUpAngularPanel();
......
......@@ -81,7 +81,7 @@ export class EditorTabBody extends PureComponent<Props, State> {
{toolbarItems.map(item => this.renderButton(item))}
</div>
<div className="panel-editor__scroll">
<CustomScrollbar>
<CustomScrollbar autoHide={false}>
<div className="panel-editor__content">
<FadeIn in={openView !== null} duration={200}>
{openView && this.renderOpenView(openView)}
......
import _ from 'lodash';
import React, { PureComponent } from 'react';
import { PanelPlugin, PanelProps } from 'app/types';
interface Props {
pluginId: string;
}
class PanelPluginNotFound extends PureComponent<Props> {
constructor(props) {
super(props);
}
render() {
const style = {
display: 'flex',
'align-items': 'center',
'text-align': 'center',
height: '100%',
};
return (
<div style={style}>
<div className="alert alert-error" style={{ margin: '0 auto' }}>
Panel plugin with id {this.props.pluginId} could not be found
</div>
</div>
);
}
}
export function getPanelPluginNotFound(id: string): PanelPlugin {
const NotFound = class NotFound extends PureComponent<PanelProps> {
render() {
return <PanelPluginNotFound pluginId={id} />;
}
};
return {
id: id,
name: id,
sort: 100,
module: '',
baseUrl: '',
info: {
author: {
name: '',
},
description: '',
links: [],
logos: {
large: '',
small: '',
},
screenshots: [],
updated: '',
version: '',
},
exports: {
PanelComponent: NotFound,
},
};
}
......@@ -3,6 +3,7 @@ import { AddPanelPanel } from './../dashgrid/AddPanelPanel';
import { PanelModel } from '../panel_model';
import { shallow } from 'enzyme';
import config from '../../../core/config';
import { getPanelPlugin } from 'app/features/plugins/__mocks__/pluginMocks';
jest.mock('app/core/store', () => ({
get: key => {
......@@ -18,76 +19,11 @@ describe('AddPanelPanel', () => {
beforeEach(() => {
config.panels = [
{
id: 'singlestat',
hideFromList: false,
name: 'Singlestat',
sort: 2,
module: '',
baseUrl: '',
meta: {},
info: {
logos: {
small: '',
},
},
},
{
id: 'hidden',
hideFromList: true,
name: 'Hidden',
sort: 100,
meta: {},
module: '',
baseUrl: '',
info: {
logos: {
small: '',
},
},
},
{
id: 'graph',
hideFromList: false,
name: 'Graph',
sort: 1,
meta: {},
module: '',
baseUrl: '',
info: {
logos: {
small: '',
},
},
},
{
id: 'alexander_zabbix',
hideFromList: false,
name: 'Zabbix',
sort: 100,
meta: {},
module: '',
baseUrl: '',
info: {
logos: {
small: '',
},
},
},
{
id: 'piechart',
hideFromList: false,
name: 'Piechart',
sort: 100,
meta: {},
module: '',
baseUrl: '',
info: {
logos: {
small: '',
},
},
},
getPanelPlugin({ id: 'singlestat', sort: 2 }),
getPanelPlugin({ id: 'hidden', sort: 100, hideFromList: true }),
getPanelPlugin({ id: 'graph', sort: 1 }),
getPanelPlugin({ id: 'alexander_zabbix', sort: 100 }),
getPanelPlugin({ id: 'piechart', sort: 100 }),
];
dashboardMock = { toggleRow: jest.fn() };
......@@ -97,16 +33,14 @@ describe('AddPanelPanel', () => {
});
it('should fetch all panels sorted with core plugins first', () => {
//console.log(wrapper.debug());
//console.log(wrapper.find('.add-panel__item').get(0).props.title);
expect(wrapper.find('.add-panel__item').get(1).props.title).toBe('Singlestat');
expect(wrapper.find('.add-panel__item').get(4).props.title).toBe('Piechart');
expect(wrapper.find('.add-panel__item').get(1).props.title).toBe('singlestat');
expect(wrapper.find('.add-panel__item').get(4).props.title).toBe('piechart');
});
it('should filter', () => {
wrapper.find('input').simulate('change', { target: { value: 'p' } });
expect(wrapper.find('.add-panel__item').get(1).props.title).toBe('Piechart');
expect(wrapper.find('.add-panel__item').get(0).props.title).toBe('Graph');
expect(wrapper.find('.add-panel__item').get(1).props.title).toBe('piechart');
expect(wrapper.find('.add-panel__item').get(0).props.title).toBe('graph');
});
});
......@@ -65,7 +65,11 @@ exports[`Render should render alpha info text 1`] = `
"large": "large/logo",
"small": "small/logo",
},
"screenshots": "screenshot/1",
"screenshots": Array [
Object {
"path": "screenshot",
},
],
"updated": "2018-09-26",
"version": "1",
},
......@@ -158,7 +162,11 @@ exports[`Render should render beta info text 1`] = `
"large": "large/logo",
"small": "small/logo",
},
"screenshots": "screenshot/1",
"screenshots": Array [
Object {
"path": "screenshot",
},
],
"updated": "2018-09-26",
"version": "1",
},
......@@ -246,7 +254,11 @@ exports[`Render should render component 1`] = `
"large": "large/logo",
"small": "small/logo",
},
"screenshots": "screenshot/1",
"screenshots": Array [
Object {
"path": "screenshot",
},
],
"updated": "2018-09-26",
"version": "1",
},
......@@ -339,7 +351,11 @@ exports[`Render should render is ready only message 1`] = `
"large": "large/logo",
"small": "small/logo",
},
"screenshots": "screenshot/1",
"screenshots": Array [
Object {
"path": "screenshot",
},
],
"updated": "2018-09-26",
"version": "1",
},
......
......@@ -78,7 +78,7 @@ export function getDataSourceLoadingNav(pageName: string): NavModel {
large: '',
small: '',
},
screenshots: '',
screenshots: [],
updated: '',
version: '',
},
......
import { Plugin } from 'app/types';
import { Plugin, PanelPlugin } from 'app/types';
export const getMockPlugins = (amount: number): Plugin[] => {
const plugins = [];
......@@ -17,7 +17,7 @@ export const getMockPlugins = (amount: number): Plugin[] => {
description: 'pretty decent plugin',
links: ['one link'],
logos: { small: 'small/logo', large: 'large/logo' },
screenshots: `screenshot/${i}`,
screenshots: [{ path: `screenshot/${i}` }],
updated: '2018-09-26',
version: '1',
},
......@@ -33,6 +33,31 @@ export const getMockPlugins = (amount: number): Plugin[] => {
return plugins;
};
export const getPanelPlugin = (options: { id: string; sort?: number; hideFromList?: boolean }): PanelPlugin => {
return {
id: options.id,
name: options.id,
sort: options.sort || 1,
info: {
author: {
name: options.id + 'name',
},
description: '',
links: [],
logos: {
large: '',
small: '',
},
screenshots: [],
updated: '',
version: '',
},
hideFromList: options.hideFromList === true,
module: '',
baseUrl: '',
};
};
export const getMockPlugin = () => {
return {
defaultNavUrl: 'some/url',
......@@ -47,7 +72,7 @@ export const getMockPlugin = () => {
description: 'pretty decent plugin',
links: ['one link'],
logos: { small: 'small/logo', large: 'large/logo' },
screenshots: 'screenshot/1',
screenshots: [{ path: `screenshot` }],
updated: '2018-09-26',
version: '1',
},
......
......@@ -28,7 +28,11 @@ exports[`Render should render component 1`] = `
"large": "large/logo",
"small": "small/logo",
},
"screenshots": "screenshot/0",
"screenshots": Array [
Object {
"path": "screenshot/0",
},
],
"updated": "2018-09-26",
"version": "1",
},
......@@ -62,7 +66,11 @@ exports[`Render should render component 1`] = `
"large": "large/logo",
"small": "small/logo",
},
"screenshots": "screenshot/1",
"screenshots": Array [
Object {
"path": "screenshot/1",
},
],
"updated": "2018-09-26",
"version": "1",
},
......@@ -96,7 +104,11 @@ exports[`Render should render component 1`] = `
"large": "large/logo",
"small": "small/logo",
},
"screenshots": "screenshot/2",
"screenshots": Array [
Object {
"path": "screenshot/2",
},
],
"updated": "2018-09-26",
"version": "1",
},
......@@ -130,7 +142,11 @@ exports[`Render should render component 1`] = `
"large": "large/logo",
"small": "small/logo",
},
"screenshots": "screenshot/3",
"screenshots": Array [
Object {
"path": "screenshot/3",
},
],
"updated": "2018-09-26",
"version": "1",
},
......@@ -164,7 +180,11 @@ exports[`Render should render component 1`] = `
"large": "large/logo",
"small": "small/logo",
},
"screenshots": "screenshot/4",
"screenshots": Array [
Object {
"path": "screenshot/4",
},
],
"updated": "2018-09-26",
"version": "1",
},
......@@ -198,7 +218,11 @@ exports[`Render should render component 1`] = `
"large": "large/logo",
"small": "small/logo",
},
"screenshots": "screenshot/5",
"screenshots": Array [
Object {
"path": "screenshot/5",
},
],
"updated": "2018-09-26",
"version": "1",
},
......
......@@ -5,8 +5,6 @@ import config from 'app/core/config';
import coreModule from 'app/core/core_module';
import { importPluginModule } from './plugin_loader';
import { UnknownPanelCtrl } from 'app/plugins/panel/unknown/module';
/** @ngInject */
function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q, $http, $templateCache, $timeout) {
function getTemplate(component) {
......@@ -69,7 +67,7 @@ function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q, $http, $
};
const panelInfo = config.panels[scope.panel.type];
let panelCtrlPromise = Promise.resolve(UnknownPanelCtrl);
let panelCtrlPromise = Promise.resolve(null);
if (panelInfo) {
panelCtrlPromise = importPluginModule(panelInfo.module).then(panelModule => {
return panelModule.PanelCtrl;
......
<div class="text-center" style="padding-top: 2rem">
Unknown panel type: <strong>{{ctrl.panel.type}}</strong>
</div>
import { PanelCtrl } from 'app/features/panel/panel_ctrl';
export class UnknownPanelCtrl extends PanelCtrl {
static templateUrl = 'public/app/plugins/panel/unknown/module.html';
/** @ngInject */
constructor($scope, $injector) {
super($scope, $injector);
}
}
......@@ -21,7 +21,7 @@ import {
DataQueryOptions,
} from './series';
import { PanelProps, PanelOptionsProps } from './panel';
import { PluginDashboard, PluginMeta, Plugin, PluginsState } from './plugins';
import { PluginDashboard, PluginMeta, Plugin, PanelPlugin, PluginsState } from './plugins';
import { Organization, OrganizationPreferences, OrganizationState } from './organization';
import {
AppNotification,
......@@ -69,6 +69,7 @@ export {
UsersState,
TimeRange,
LoadingState,
PanelPlugin,
PanelProps,
PanelOptionsProps,
TimeSeries,
......
......@@ -12,14 +12,13 @@ export interface PluginExports {
// Panel plugin
PanelCtrl?;
PanelComponent?: ComponentClass<PanelProps>;
PanelOptionsComponent: ComponentClass<PanelOptionsProps>;
PanelOptionsComponent?: ComponentClass<PanelOptionsProps>;
}
export interface PanelPlugin {
id: string;
name: string;
meta: any;
hideFromList: boolean;
hideFromList?: boolean;
module: string;
baseUrl: string;
info: any;
......@@ -49,7 +48,7 @@ export interface PluginInclude {
export interface PluginMetaInfo {
author: {
name: string;
url: string;
url?: string;
};
description: string;
links: string[];
......@@ -57,7 +56,7 @@ export interface PluginMetaInfo {
large: string;
small: string;
};
screenshots: string;
screenshots: any[];
updated: string;
version: string;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment