PluginSettings.tsx 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. import { cloneDeep } from 'lodash';
  2. import React, { PureComponent } from 'react';
  3. import {
  4. DataQuery,
  5. DataSourceApi,
  6. DataSourceJsonData,
  7. DataSourcePlugin,
  8. DataSourcePluginMeta,
  9. DataSourceSettings,
  10. } from '@grafana/data';
  11. import { AngularComponent, getAngularLoader } from '@grafana/runtime';
  12. export type GenericDataSourcePlugin = DataSourcePlugin<DataSourceApi<DataQuery, DataSourceJsonData>>;
  13. export interface Props {
  14. plugin: GenericDataSourcePlugin;
  15. dataSource: DataSourceSettings;
  16. dataSourceMeta: DataSourcePluginMeta;
  17. onModelChange: (dataSource: DataSourceSettings) => void;
  18. }
  19. export class PluginSettings extends PureComponent<Props> {
  20. element: HTMLDivElement | null = null;
  21. component?: AngularComponent;
  22. scopeProps: {
  23. ctrl: { datasourceMeta: DataSourcePluginMeta; current: DataSourceSettings };
  24. onModelChanged: (dataSource: DataSourceSettings) => void;
  25. };
  26. constructor(props: Props) {
  27. super(props);
  28. this.scopeProps = {
  29. ctrl: { datasourceMeta: props.dataSourceMeta, current: cloneDeep(props.dataSource) },
  30. onModelChanged: this.onModelChanged,
  31. };
  32. this.onModelChanged = this.onModelChanged.bind(this);
  33. }
  34. componentDidMount() {
  35. const { plugin } = this.props;
  36. if (!this.element) {
  37. return;
  38. }
  39. if (!plugin.components.ConfigEditor) {
  40. // React editor is not specified, let's render angular editor
  41. // How to approach this better? Introduce ReactDataSourcePlugin interface and typeguard it here?
  42. const loader = getAngularLoader();
  43. const template = '<plugin-component type="datasource-config-ctrl" />';
  44. this.component = loader.load(this.element, this.scopeProps, template);
  45. }
  46. }
  47. componentDidUpdate(prevProps: Props) {
  48. const { plugin } = this.props;
  49. if (!plugin.components.ConfigEditor && this.props.dataSource !== prevProps.dataSource) {
  50. this.scopeProps.ctrl.current = cloneDeep(this.props.dataSource);
  51. this.component?.digest();
  52. }
  53. }
  54. componentWillUnmount() {
  55. if (this.component) {
  56. this.component.destroy();
  57. }
  58. }
  59. onModelChanged = (dataSource: DataSourceSettings) => {
  60. this.props.onModelChange(dataSource);
  61. };
  62. render() {
  63. const { plugin, dataSource } = this.props;
  64. if (!plugin) {
  65. return null;
  66. }
  67. return (
  68. <div ref={(element) => (this.element = element)}>
  69. {plugin.components.ConfigEditor &&
  70. React.createElement(plugin.components.ConfigEditor, {
  71. options: dataSource,
  72. onOptionsChange: this.onModelChanged,
  73. })}
  74. </div>
  75. );
  76. }
  77. }
  78. export default PluginSettings;