Просмотр исходного кода

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

Plugin not found
Torkel Ödegaard 7 лет назад
Родитель
Сommit
6b2a47f2af

+ 3 - 2
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<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();

+ 1 - 1
public/app/features/dashboard/dashgrid/EditorTabBody.tsx

@@ -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)}

+ 64 - 0
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<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,
+    },
+  };
+}

+ 10 - 76
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');
   });
 });

+ 20 - 4
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",
               },

+ 1 - 1
public/app/features/datasources/state/navModel.ts

@@ -78,7 +78,7 @@ export function getDataSourceLoadingNav(pageName: string): NavModel {
           large: '',
           small: '',
         },
-        screenshots: '',
+        screenshots: [],
         updated: '',
         version: '',
       },

+ 28 - 3
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',
     },

+ 30 - 6
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",
           },

+ 1 - 3
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;

+ 0 - 5
public/app/plugins/panel/unknown/module.html

@@ -1,5 +0,0 @@
-<div class="text-center" style="padding-top: 2rem">
-	Unknown panel type: <strong>{{ctrl.panel.type}}</strong>
-</div>
-
-

+ 0 - 10
public/app/plugins/panel/unknown/module.ts

@@ -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);
-  }
-}

+ 2 - 1
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,

+ 4 - 5
public/app/types/plugins.ts

@@ -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;
 }