@grafana/data#PanelPluginMeta TypeScript Examples

The following examples show how to use @grafana/data#PanelPluginMeta. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: VisualizationTab.tsx    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
VisualizationTabUnconnected: FC<Props> = ({ panel, plugin, changePanelPlugin }) => {
  const theme = useTheme();
  const styles = getStyles(theme);

  if (!plugin) {
    return null;
  }

  const onPluginTypeChange = (meta: PanelPluginMeta) => {
    changePanelPlugin(panel, meta.id);
  };

  return (
    <div className={styles.wrapper}>
      <VizTypePicker current={plugin.meta} onTypeChange={onPluginTypeChange} searchQuery={''} onClose={() => {}} />
    </div>
  );
}
Example #2
Source File: PanelPluginError.tsx    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
export function getPanelPluginLoadError(meta: PanelPluginMeta, err: any): PanelPlugin {
  const LoadError = class LoadError extends PureComponent<PanelProps> {
    render() {
      const text = (
        <>
          Check the server startup logs for more information. <br />
          If this plugin was loaded from git, make sure it was compiled.
        </>
      );
      return <PanelPluginError title={`Error loading: ${meta.id}`} text={text} />;
    }
  };
  const plugin = new PanelPlugin(LoadError);
  plugin.meta = meta;
  plugin.loadError = true;
  return plugin;
}
Example #3
Source File: PanelEditor.tsx    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
refreshFromState = (meta?: PanelPluginMeta) => {
    const { refreshPanelEditor, plugin } = this.props;
    meta = meta || plugin.meta;

    refreshPanelEditor({
      hasQueriesTab: !meta.skipDataQuery,
      usesGraphPlugin: meta.id === 'graph',
      alertingEnabled: config.alertingEnabled,
    });
  };
Example #4
Source File: VizTypePicker.tsx    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
getFilteredPluginList = (): PanelPluginMeta[] => {
    const { searchQuery } = this.props;
    const regex = new RegExp(searchQuery, 'i');
    const pluginList = this.pluginList;

    const filtered = pluginList.filter(item => {
      return regex.test(item.name);
    });

    return filtered;
  };
Example #5
Source File: pluginMocks.ts    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
getPanelPlugin = (
  options: Partial<PanelPluginMeta>,
  reactPanel?: ComponentType<PanelProps>,
  angularPanel?: any
): PanelPlugin => {
  const plugin = new PanelPlugin(reactPanel);
  plugin.angularPanelCtrl = angularPanel;
  plugin.meta = {
    id: options.id,
    type: PluginType.panel,
    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: '',
  };
  return plugin;
}
Example #6
Source File: config.ts    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
panels: { [key: string]: PanelPluginMeta } = {};
Example #7
Source File: AngularPanelOptions.tsx    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
loadAngularOptions() {
    const { panel, angularPanelComponent, changePanelPlugin } = this.props;

    if (!this.element || !angularPanelComponent || this.angularOptions) {
      return;
    }

    const scope = angularPanelComponent.getScope();

    // When full page reloading in edit mode the angular panel has on fully compiled & instantiated yet
    if (!scope.$$childHead) {
      setTimeout(() => {
        this.forceUpdate();
      });
      return;
    }

    const panelCtrl: PanelCtrl = scope.$$childHead.ctrl;
    panelCtrl.initEditMode();
    panelCtrl.onPluginTypeChange = (plugin: PanelPluginMeta) => {
      changePanelPlugin(panel, plugin.id);
    };

    let template = '';
    for (let i = 0; i < panelCtrl.editorTabs.length; i++) {
      template +=
        `
      <div class="panel-options-group" ng-cloak>` +
        (i > 0
          ? `<div class="panel-options-group__header">
           <span class="panel-options-group__title">{{ctrl.editorTabs[${i}].title}}
           </span>
         </div>`
          : '') +
        `<div class="panel-options-group__body">
          <panel-editor-tab editor-tab="ctrl.editorTabs[${i}]" ctrl="ctrl"></panel-editor-tab>
        </div>
      </div>
      `;
    }

    const loader = getAngularLoader();
    const scopeProps = { ctrl: panelCtrl };

    this.angularOptions = loader.load(this.element, scopeProps, template);
  }
Example #8
Source File: AngularPanelOptions.tsx    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
loadAngularOptions() {
    const { panel, angularPanelComponent, changePanelPlugin } = this.props;

    if (!this.element || !angularPanelComponent || this.angularOptions) {
      return;
    }

    const scope = angularPanelComponent.getScope();

    // When full page reloading in edit mode the angular panel has on fully compiled & instantiated yet
    if (!scope.$$childHead) {
      setTimeout(() => {
        this.forceUpdate();
      });
      return;
    }

    const panelCtrl: PanelCtrl = scope.$$childHead.ctrl;
    panelCtrl.initEditMode();
    panelCtrl.onPluginTypeChange = (plugin: PanelPluginMeta) => {
      changePanelPlugin(panel, plugin.id);
    };

    let template = '';
    for (let i = 0; i < panelCtrl.editorTabs.length; i++) {
      template +=
        `
      <div class="panel-options-group" ng-cloak>` +
        (i > 0
          ? `<div class="panel-options-group__header">
           <span class="panel-options-group__title">{{ctrl.editorTabs[${i}].title}}
           </span>
         </div>`
          : '') +
        `<div class="panel-options-group__body">
          <panel-editor-tab editor-tab="ctrl.editorTabs[${i}]" ctrl="ctrl"></panel-editor-tab>
        </div>
      </div>
      `;
    }

    const loader = getAngularLoader();
    const scopeProps = { ctrl: panelCtrl };

    this.angularOptions = loader.load(this.element, scopeProps, template);
  }
Example #9
Source File: PanelEditor.tsx    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
onPluginTypeChange = (newType: PanelPluginMeta) => {
    this.props.changePanelPlugin(this.props.panel, newType.id);
    this.refreshFromState(newType);
  };
Example #10
Source File: VisualizationTab.tsx    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
onPluginTypeChange = (plugin: PanelPluginMeta) => {
    if (plugin.id === this.props.plugin.meta.id) {
      this.setState({ isVizPickerOpen: false });
    } else {
      this.props.onPluginTypeChange(plugin);
    }
  };
Example #11
Source File: VizTypePicker.tsx    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
renderVizPlugin = (plugin: PanelPluginMeta, index: number) => {
    const { onTypeChange } = this.props;
    const isCurrent = plugin.id === this.props.current.id;

    return (
      <VizTypePickerPlugin key={plugin.id} isCurrent={isCurrent} plugin={plugin} onClick={() => onTypeChange(plugin)} />
    );
  };
Example #12
Source File: panel_ctrl.ts    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
// overriden from react
  onPluginTypeChange = (plugin: PanelPluginMeta) => {};
Example #13
Source File: DashboardExporter.test.ts    From grafana-chinese with Apache License 2.0 4 votes vote down vote up
describe('given dashboard with repeated panels', () => {
  let dash: any, exported: any;

  beforeEach(done => {
    dash = {
      templating: {
        list: [
          {
            name: 'apps',
            type: 'query',
            datasource: 'gfdb',
            current: { value: 'Asd', text: 'Asd' },
            options: [{ value: 'Asd', text: 'Asd' }],
          },
          {
            name: 'prefix',
            type: 'constant',
            current: { value: 'collectd', text: 'collectd' },
            options: [],
          },
          {
            name: 'ds',
            type: 'datasource',
            query: 'other2',
            current: { value: 'other2', text: 'other2' },
            options: [],
          },
        ],
      },
      annotations: {
        list: [
          {
            name: 'logs',
            datasource: 'gfdb',
          },
        ],
      },
      panels: [
        { id: 6, datasource: 'gfdb', type: 'graph' },
        { id: 7 },
        {
          id: 8,
          datasource: '-- Mixed --',
          targets: [{ datasource: 'other' }],
        },
        { id: 9, datasource: '$ds' },
        {
          id: 2,
          repeat: 'apps',
          datasource: 'gfdb',
          type: 'graph',
        },
        { id: 3, repeat: null, repeatPanelId: 2 },
        {
          id: 4,
          collapsed: true,
          panels: [
            { id: 10, datasource: 'gfdb', type: 'table' },
            { id: 11 },
            {
              id: 12,
              datasource: '-- Mixed --',
              targets: [{ datasource: 'other' }],
            },
            { id: 13, datasource: '$ds' },
            {
              id: 14,
              repeat: 'apps',
              datasource: 'gfdb',
              type: 'heatmap',
            },
            { id: 15, repeat: null, repeatPanelId: 14 },
          ],
        },
      ],
    };

    config.buildInfo.version = '3.0.2';

    config.panels['graph'] = {
      id: 'graph',
      name: 'Graph',
      info: { version: '1.1.0' },
    } as PanelPluginMeta;

    config.panels['table'] = {
      id: 'table',
      name: 'Table',
      info: { version: '1.1.1' },
    } as PanelPluginMeta;

    config.panels['heatmap'] = {
      id: 'heatmap',
      name: 'Heatmap',
      info: { version: '1.1.2' },
    } as PanelPluginMeta;

    dash = new DashboardModel(dash, {});
    const exporter = new DashboardExporter();
    exporter.makeExportable(dash).then(clean => {
      exported = clean;
      done();
    });
  });

  it('should replace datasource refs', () => {
    const panel = exported.panels[0];
    expect(panel.datasource).toBe('${DS_GFDB}');
  });

  it('should replace datasource refs in collapsed row', () => {
    const panel = exported.panels[5].panels[0];
    expect(panel.datasource).toBe('${DS_GFDB}');
  });

  it('should replace datasource in variable query', () => {
    expect(exported.templating.list[0].datasource).toBe('${DS_GFDB}');
    expect(exported.templating.list[0].options.length).toBe(0);
    expect(exported.templating.list[0].current.value).toBe(undefined);
    expect(exported.templating.list[0].current.text).toBe(undefined);
  });

  it('should replace datasource in annotation query', () => {
    expect(exported.annotations.list[1].datasource).toBe('${DS_GFDB}');
  });

  it('should add datasource as input', () => {
    expect(exported.__inputs[0].name).toBe('DS_GFDB');
    expect(exported.__inputs[0].pluginId).toBe('testdb');
    expect(exported.__inputs[0].type).toBe('datasource');
  });

  it('should add datasource to required', () => {
    const require: any = _.find(exported.__requires, { name: 'TestDB' });
    expect(require.name).toBe('TestDB');
    expect(require.id).toBe('testdb');
    expect(require.type).toBe('datasource');
    expect(require.version).toBe('1.2.1');
  });

  it('should not add built in datasources to required', () => {
    const require: any = _.find(exported.__requires, { name: 'Mixed' });
    expect(require).toBe(undefined);
  });

  it('should add datasources used in mixed mode', () => {
    const require: any = _.find(exported.__requires, { name: 'OtherDB' });
    expect(require).not.toBe(undefined);
  });

  it('should add graph panel to required', () => {
    const require: any = _.find(exported.__requires, { name: 'Graph' });
    expect(require.name).toBe('Graph');
    expect(require.id).toBe('graph');
    expect(require.version).toBe('1.1.0');
  });

  it('should add table panel to required', () => {
    const require: any = _.find(exported.__requires, { name: 'Table' });
    expect(require.name).toBe('Table');
    expect(require.id).toBe('table');
    expect(require.version).toBe('1.1.1');
  });

  it('should add heatmap panel to required', () => {
    const require: any = _.find(exported.__requires, { name: 'Heatmap' });
    expect(require.name).toBe('Heatmap');
    expect(require.id).toBe('heatmap');
    expect(require.version).toBe('1.1.2');
  });

  it('should add grafana version', () => {
    const require: any = _.find(exported.__requires, { name: 'Grafana' });
    expect(require.type).toBe('grafana');
    expect(require.id).toBe('grafana');
    expect(require.version).toBe('3.0.2');
  });

  it('should add constant template variables as inputs', () => {
    const input: any = _.find(exported.__inputs, { name: 'VAR_PREFIX' });
    expect(input.type).toBe('constant');
    expect(input.label).toBe('prefix');
    expect(input.value).toBe('collectd');
  });

  it('should templatize constant variables', () => {
    const variable: any = _.find(exported.templating.list, { name: 'prefix' });
    expect(variable.query).toBe('${VAR_PREFIX}');
    expect(variable.current.text).toBe('${VAR_PREFIX}');
    expect(variable.current.value).toBe('${VAR_PREFIX}');
    expect(variable.options[0].text).toBe('${VAR_PREFIX}');
    expect(variable.options[0].value).toBe('${VAR_PREFIX}');
  });

  it('should add datasources only use via datasource variable to requires', () => {
    const require: any = _.find(exported.__requires, { name: 'OtherDB_2' });
    expect(require.id).toBe('other2');
  });
});
Example #14
Source File: DashboardExporter.ts    From grafana-chinese with Apache License 2.0 4 votes vote down vote up
makeExportable(dashboard: DashboardModel) {
    // clean up repeated rows and panels,
    // this is done on the live real dashboard instance, not on a clone
    // so we need to undo this
    // this is pretty hacky and needs to be changed
    dashboard.cleanUpRepeats();

    const saveModel = dashboard.getSaveModelClone();
    saveModel.id = null;

    // undo repeat cleanup
    dashboard.processRepeats();

    const inputs: Input[] = [];
    const requires: Requires = {};
    const datasources: DataSources = {};
    const promises: Array<Promise<void>> = [];
    const variableLookup: { [key: string]: any } = {};

    for (const variable of saveModel.getVariables()) {
      variableLookup[variable.name] = variable;
    }

    const templateizeDatasourceUsage = (obj: any) => {
      let datasource: string = obj.datasource;
      let datasourceVariable: any = null;

      // ignore data source properties that contain a variable
      if (datasource && datasource.indexOf('$') === 0) {
        datasourceVariable = variableLookup[datasource.substring(1)];
        if (datasourceVariable && datasourceVariable.current) {
          datasource = datasourceVariable.current.value;
        }
      }

      promises.push(
        getDataSourceSrv()
          .get(datasource)
          .then(ds => {
            if (ds.meta?.builtIn) {
              return;
            }

            // add data source type to require list
            requires['datasource' + ds.meta?.id] = {
              type: 'datasource',
              id: ds.meta?.id,
              name: ds.meta?.name,
              version: ds.meta?.info.version || '1.0.0',
            };

            // if used via variable we can skip templatizing usage
            if (datasourceVariable) {
              return;
            }

            const refName = 'DS_' + ds.name.replace(' ', '_').toUpperCase();
            datasources[refName] = {
              name: refName,
              label: ds.name,
              description: '',
              type: 'datasource',
              pluginId: ds.meta?.id,
              pluginName: ds.meta?.name,
            };

            obj.datasource = '${' + refName + '}';
          })
      );
    };

    const processPanel = (panel: PanelModel) => {
      if (panel.datasource !== undefined) {
        templateizeDatasourceUsage(panel);
      }

      if (panel.targets) {
        for (const target of panel.targets) {
          if (target.datasource !== undefined) {
            templateizeDatasourceUsage(target);
          }
        }
      }

      const panelDef: PanelPluginMeta = config.panels[panel.type];
      if (panelDef) {
        requires['panel' + panelDef.id] = {
          type: 'panel',
          id: panelDef.id,
          name: panelDef.name,
          version: panelDef.info.version,
        };
      }
    };

    // check up panel data sources
    for (const panel of saveModel.panels) {
      processPanel(panel);

      // handle collapsed rows
      if (panel.collapsed !== undefined && panel.collapsed === true && panel.panels) {
        for (const rowPanel of panel.panels) {
          processPanel(rowPanel);
        }
      }
    }

    // templatize template vars
    for (const variable of saveModel.getVariables()) {
      if (variable.type === 'query') {
        templateizeDatasourceUsage(variable);
        variable.options = [];
        variable.current = {};
        variable.refresh = variable.refresh > 0 ? variable.refresh : 1;
      }
    }

    // templatize annotations vars
    for (const annotationDef of saveModel.annotations.list) {
      templateizeDatasourceUsage(annotationDef);
    }

    // add grafana version
    requires['grafana'] = {
      type: 'grafana',
      id: 'grafana',
      name: 'Grafana',
      version: config.buildInfo.version,
    };

    return Promise.all(promises)
      .then(() => {
        _.each(datasources, (value: any) => {
          inputs.push(value);
        });

        // templatize constants
        for (const variable of saveModel.getVariables()) {
          if (variable.type === 'constant') {
            const refName = 'VAR_' + variable.name.replace(' ', '_').toUpperCase();
            inputs.push({
              name: refName,
              type: 'constant',
              label: variable.label || variable.name,
              value: variable.current.value,
              description: '',
            });
            // update current and option
            variable.query = '${' + refName + '}';
            variable.options[0] = variable.current = {
              value: variable.query,
              text: variable.query,
            };
          }
        }

        // make inputs and requires a top thing
        const newObj: { [key: string]: {} } = {};
        newObj['__inputs'] = inputs;
        newObj['__requires'] = _.sortBy(requires, ['id']);

        _.defaults(newObj, saveModel);
        return newObj;
      })
      .catch(err => {
        console.log('Export failed:', err);
        return {
          error: err,
        };
      });
  }
Example #15
Source File: helpers.ts    From grafana-chinese with Apache License 2.0 4 votes vote down vote up
export function ControllerTestContext(this: any) {
  const self = this;

  this.datasource = {};
  this.$element = {};
  this.$sanitize = {};
  this.annotationsSrv = {};
  this.contextSrv = {};
  this.timeSrv = new TimeSrvStub();
  this.templateSrv = TemplateSrvStub();
  this.datasourceSrv = {
    getMetricSources: () => {},
    get: () => {
      return {
        then: (callback: (ds: any) => void) => {
          callback(self.datasource);
        },
      };
    },
  };
  this.isUtc = false;

  this.providePhase = (mocks: any) => {
    return angularMocks.module(($provide: any) => {
      $provide.value('contextSrv', self.contextSrv);
      $provide.value('datasourceSrv', self.datasourceSrv);
      $provide.value('annotationsSrv', self.annotationsSrv);
      $provide.value('timeSrv', self.timeSrv);
      $provide.value('templateSrv', self.templateSrv);
      $provide.value('$element', self.$element);
      $provide.value('$sanitize', self.$sanitize);
      each(mocks, (value: any, key: any) => {
        $provide.value(key, value);
      });
    });
  };

  this.createPanelController = (Ctrl: any) => {
    return angularMocks.inject(($controller: any, $rootScope: GrafanaRootScope, $location: any, $browser: any) => {
      self.scope = $rootScope.$new();
      self.$location = $location;
      self.$browser = $browser;
      self.panel = new PanelModel({ type: 'test' });
      self.dashboard = { meta: {} };
      self.isUtc = false;
      self.dashboard.getTimezone = () => {
        return self.isUtc ? 'utc' : 'browser';
      };
      self.dashboard.isTimezoneUtc = () => {
        return self.isUtc;
      };

      $rootScope.appEvent = sinon.spy();
      $rootScope.onAppEvent = sinon.spy();
      $rootScope.colors = [];

      for (let i = 0; i < 50; i++) {
        $rootScope.colors.push('#' + i);
      }

      config.panels['test'] = { info: {} } as PanelPluginMeta;
      self.ctrl = $controller(
        Ctrl,
        { $scope: self.scope },
        {
          panel: self.panel,
          dashboard: self.dashboard,
        }
      );
    });
  };

  this.createControllerPhase = (controllerName: string) => {
    return angularMocks.inject(($controller: any, $rootScope: GrafanaRootScope, $location: any, $browser: any) => {
      self.scope = $rootScope.$new();
      self.$location = $location;
      self.$browser = $browser;
      self.scope.contextSrv = {};
      self.scope.panel = {};
      self.scope.dashboard = { meta: {} };
      self.scope.dashboardMeta = {};
      self.scope.dashboardViewState = DashboardViewStateStub();
      self.scope.appEvent = sinon.spy();
      self.scope.onAppEvent = sinon.spy();

      $rootScope.colors = [];
      for (let i = 0; i < 50; i++) {
        $rootScope.colors.push('#' + i);
      }

      self.scope.skipDataOnInit = true;
      self.scope.skipAutoInit = true;
      self.controller = $controller(controllerName, {
        $scope: self.scope,
      });
    });
  };

  this.setIsUtc = (isUtc: any = false) => {
    self.isUtc = isUtc;
  };
}