diff --git a/public/app/features/dashboard/dashgrid/DashboardPanel.tsx b/public/app/features/dashboard/dashgrid/DashboardPanel.tsx index e423a96f28a..d5c97a12e90 100644 --- a/public/app/features/dashboard/dashgrid/DashboardPanel.tsx +++ b/public/app/features/dashboard/dashgrid/DashboardPanel.tsx @@ -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 { // 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(); diff --git a/public/app/features/dashboard/dashgrid/EditorTabBody.tsx b/public/app/features/dashboard/dashgrid/EditorTabBody.tsx index 530603d1ad0..86ebdf86b67 100644 --- a/public/app/features/dashboard/dashgrid/EditorTabBody.tsx +++ b/public/app/features/dashboard/dashgrid/EditorTabBody.tsx @@ -81,7 +81,7 @@ export class EditorTabBody extends PureComponent { {toolbarItems.map(item => this.renderButton(item))}
- +
{openView && this.renderOpenView(openView)} diff --git a/public/app/features/dashboard/dashgrid/PanelPluginNotFound.tsx b/public/app/features/dashboard/dashgrid/PanelPluginNotFound.tsx new file mode 100644 index 00000000000..0e1a336c16b --- /dev/null +++ b/public/app/features/dashboard/dashgrid/PanelPluginNotFound.tsx @@ -0,0 +1,64 @@ +import _ from 'lodash'; +import React, { PureComponent } from 'react'; +import { PanelPlugin, PanelProps } from 'app/types'; + +interface Props { + pluginId: string; +} + +class PanelPluginNotFound extends PureComponent { + constructor(props) { + super(props); + } + + render() { + const style = { + display: 'flex', + 'align-items': 'center', + 'text-align': 'center', + height: '100%', + }; + + return ( +
+
+ Panel plugin with id {this.props.pluginId} could not be found +
+
+ ); + } +} + +export function getPanelPluginNotFound(id: string): PanelPlugin { + const NotFound = class NotFound extends PureComponent { + render() { + return ; + } + }; + + return { + id: id, + name: id, + sort: 100, + module: '', + baseUrl: '', + info: { + author: { + name: '', + }, + description: '', + links: [], + logos: { + large: '', + small: '', + }, + screenshots: [], + updated: '', + version: '', + }, + + exports: { + PanelComponent: NotFound, + }, + }; +} diff --git a/public/app/features/dashboard/specs/AddPanelPanel.test.tsx b/public/app/features/dashboard/specs/AddPanelPanel.test.tsx index c5f66fed32a..4136883880b 100644 --- a/public/app/features/dashboard/specs/AddPanelPanel.test.tsx +++ b/public/app/features/dashboard/specs/AddPanelPanel.test.tsx @@ -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'); }); }); diff --git a/public/app/features/datasources/settings/__snapshots__/DataSourceSettings.test.tsx.snap b/public/app/features/datasources/settings/__snapshots__/DataSourceSettings.test.tsx.snap index ebb856ca354..f95055c9095 100644 --- a/public/app/features/datasources/settings/__snapshots__/DataSourceSettings.test.tsx.snap +++ b/public/app/features/datasources/settings/__snapshots__/DataSourceSettings.test.tsx.snap @@ -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", }, diff --git a/public/app/features/datasources/state/navModel.ts b/public/app/features/datasources/state/navModel.ts index 7c4ec0ace69..3f59812a522 100644 --- a/public/app/features/datasources/state/navModel.ts +++ b/public/app/features/datasources/state/navModel.ts @@ -78,7 +78,7 @@ export function getDataSourceLoadingNav(pageName: string): NavModel { large: '', small: '', }, - screenshots: '', + screenshots: [], updated: '', version: '', }, diff --git a/public/app/features/plugins/__mocks__/pluginMocks.ts b/public/app/features/plugins/__mocks__/pluginMocks.ts index 4804cbbc594..358adb112b3 100644 --- a/public/app/features/plugins/__mocks__/pluginMocks.ts +++ b/public/app/features/plugins/__mocks__/pluginMocks.ts @@ -1,4 +1,4 @@ -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', }, diff --git a/public/app/features/plugins/__snapshots__/PluginList.test.tsx.snap b/public/app/features/plugins/__snapshots__/PluginList.test.tsx.snap index 5eb82fbefb6..160c02c6e8e 100644 --- a/public/app/features/plugins/__snapshots__/PluginList.test.tsx.snap +++ b/public/app/features/plugins/__snapshots__/PluginList.test.tsx.snap @@ -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", }, diff --git a/public/app/features/plugins/plugin_component.ts b/public/app/features/plugins/plugin_component.ts index 2fe25c4666d..fc11d8d98ec 100644 --- a/public/app/features/plugins/plugin_component.ts +++ b/public/app/features/plugins/plugin_component.ts @@ -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; diff --git a/public/app/plugins/panel/unknown/module.html b/public/app/plugins/panel/unknown/module.html deleted file mode 100644 index 02c4dc97fc1..00000000000 --- a/public/app/plugins/panel/unknown/module.html +++ /dev/null @@ -1,5 +0,0 @@ -
- Unknown panel type: {{ctrl.panel.type}} -
- - diff --git a/public/app/plugins/panel/unknown/module.ts b/public/app/plugins/panel/unknown/module.ts deleted file mode 100644 index d7229913bc5..00000000000 --- a/public/app/plugins/panel/unknown/module.ts +++ /dev/null @@ -1,10 +0,0 @@ -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); - } -} diff --git a/public/app/types/index.ts b/public/app/types/index.ts index d6a6e73f06d..49c74a7de28 100644 --- a/public/app/types/index.ts +++ b/public/app/types/index.ts @@ -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, diff --git a/public/app/types/plugins.ts b/public/app/types/plugins.ts index 5dbde61d8d0..3875305ea9d 100644 --- a/public/app/types/plugins.ts +++ b/public/app/types/plugins.ts @@ -12,14 +12,13 @@ export interface PluginExports { // Panel plugin PanelCtrl?; PanelComponent?: ComponentClass; - PanelOptionsComponent: ComponentClass; + PanelOptionsComponent?: ComponentClass; } 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; }