Browse Source

react-panel: Add data source "help"

Johannes Schill 7 years ago
parent
commit
ff87cbd4db

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

@@ -12,6 +12,8 @@ export interface EditorToolBarView {
   title: string;
   title: string;
   imgSrc?: string;
   imgSrc?: string;
   icon?: string;
   icon?: string;
+  disabled?: boolean;
+  onClick?: () => void;
   render: (closeFunction: any) => JSX.Element;
   render: (closeFunction: any) => JSX.Element;
 }
 }
 
 
@@ -38,6 +40,19 @@ export class EditorTabBody extends PureComponent<Props, State> {
     this.setState({ openView: null });
     this.setState({ openView: null });
   };
   };
 
 
+  static getDerivedStateFromProps(props, state) {
+    if (state.openView) {
+      const activeToolbarItem = props.toolbarItems.find(item => item.title === state.openView.title);
+      if (activeToolbarItem) {
+        return {
+          ...state,
+          openView: activeToolbarItem,
+        };
+      }
+    }
+    return state;
+  }
+
   renderMainSelection(view: EditorToolBarView) {
   renderMainSelection(view: EditorToolBarView) {
     return (
     return (
       <div className="toolbar__main" onClick={() => this.onToggleToolBarView(view)} key={view.title}>
       <div className="toolbar__main" onClick={() => this.onToggleToolBarView(view)} key={view.title}>
@@ -49,9 +64,16 @@ export class EditorTabBody extends PureComponent<Props, State> {
   }
   }
 
 
   renderButton(view: EditorToolBarView) {
   renderButton(view: EditorToolBarView) {
+    const onClick = () => {
+      if (view.onClick) {
+        view.onClick();
+      }
+      this.onToggleToolBarView(view);
+    };
+
     return (
     return (
       <div className="nav-buttons" key={view.title}>
       <div className="nav-buttons" key={view.title}>
-        <button className="btn navbar-button" onClick={() => this.onToggleToolBarView(view)}>
+        <button className="btn navbar-button" onClick={onClick} disabled={view.disabled}>
           {view.icon && <i className={view.icon} />} {view.title}
           {view.icon && <i className={view.icon} />} {view.title}
         </button>
         </button>
       </div>
       </div>

+ 58 - 3
public/app/features/dashboard/dashgrid/QueriesTab.tsx

@@ -11,21 +11,31 @@ import config from 'app/core/config';
 
 
 // Services
 // Services
 import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
 import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
+import { getBackendSrv, BackendSrv } from 'app/core/services/backend_srv';
 import { DataSourceSelectItem } from 'app/types';
 import { DataSourceSelectItem } from 'app/types';
 
 
+import Remarkable from 'remarkable';
+
 interface Props {
 interface Props {
   panel: PanelModel;
   panel: PanelModel;
   dashboard: DashboardModel;
   dashboard: DashboardModel;
 }
 }
 
 
+interface Help {
+  isLoading: boolean;
+  helpHtml: any;
+}
+
 interface State {
 interface State {
   currentDatasource: DataSourceSelectItem;
   currentDatasource: DataSourceSelectItem;
+  help: Help;
 }
 }
 
 
 export class QueriesTab extends PureComponent<Props, State> {
 export class QueriesTab extends PureComponent<Props, State> {
   element: any;
   element: any;
   component: AngularComponent;
   component: AngularComponent;
   datasources: DataSourceSelectItem[] = getDatasourceSrv().getMetricSources();
   datasources: DataSourceSelectItem[] = getDatasourceSrv().getMetricSources();
+  backendSrv: BackendSrv = getBackendSrv();
 
 
   constructor(props) {
   constructor(props) {
     super(props);
     super(props);
@@ -33,6 +43,10 @@ export class QueriesTab extends PureComponent<Props, State> {
 
 
     this.state = {
     this.state = {
       currentDatasource: this.datasources.find(datasource => datasource.value === panel.datasource),
       currentDatasource: this.datasources.find(datasource => datasource.value === panel.datasource),
+      help: {
+        isLoading: false,
+        helpHtml: null,
+      },
     };
     };
   }
   }
 
 
@@ -42,7 +56,6 @@ export class QueriesTab extends PureComponent<Props, State> {
     }
     }
 
 
     const { panel, dashboard } = this.props;
     const { panel, dashboard } = this.props;
-
     const loader = getAngularLoader();
     const loader = getAngularLoader();
     const template = '<metrics-tab />';
     const template = '<metrics-tab />';
     const scopeProps = {
     const scopeProps = {
@@ -86,11 +99,51 @@ export class QueriesTab extends PureComponent<Props, State> {
       ...prevState,
       ...prevState,
       currentDatasource: datasource,
       currentDatasource: datasource,
     }));
     }));
-    // this.component.digest();
+  };
+
+  loadHelp = () => {
+    const { currentDatasource } = this.state;
+    const hasHelp = currentDatasource.meta.hasQueryHelp;
+
+    if (hasHelp) {
+      this.setState(prevState => ({
+        ...prevState,
+        help: {
+          helpHtml: <h2>Loading help...</h2>,
+          isLoading: true,
+        },
+      }));
+
+      this.backendSrv
+        .get(`/api/plugins/${currentDatasource.meta.id}/markdown/query_help`)
+        .then(res => {
+          const md = new Remarkable();
+          const helpHtml = md.render(res); // TODO: Clean out dangerous code? Previous: this.helpHtml = this.$sce.trustAsHtml(md.render(res));
+          this.setState(prevState => ({
+            ...prevState,
+            help: {
+              helpHtml: <div className="markdown-html" dangerouslySetInnerHTML={{ __html: helpHtml }} />,
+              isLoading: false,
+            },
+          }));
+        })
+        .catch(() => {
+          this.setState(prevState => ({
+            ...prevState,
+            help: {
+              helpHtml: 'Error occured when loading help',
+              isLoading: false,
+            },
+          }));
+        });
+    }
   };
   };
 
 
   render() {
   render() {
     const { currentDatasource } = this.state;
     const { currentDatasource } = this.state;
+    const { helpHtml } = this.state.help;
+    const { hasQueryHelp } = currentDatasource.meta;
+
     const dsInformation = {
     const dsInformation = {
       title: currentDatasource.name,
       title: currentDatasource.name,
       imgSrc: currentDatasource.meta.info.logos.small,
       imgSrc: currentDatasource.meta.info.logos.small,
@@ -113,7 +166,9 @@ export class QueriesTab extends PureComponent<Props, State> {
     const dsHelp = {
     const dsHelp = {
       title: '',
       title: '',
       icon: 'fa fa-question',
       icon: 'fa fa-question',
-      render: () => <h2>hello</h2>,
+      disabled: !hasQueryHelp,
+      onClick: this.loadHelp,
+      render: () => helpHtml,
     };
     };
 
 
     return (
     return (

+ 8 - 0
public/app/types/plugins.ts

@@ -26,6 +26,12 @@ export interface PanelPlugin {
   exports?: PluginExports;
   exports?: PluginExports;
 }
 }
 
 
+interface PluginMetaQueryOptions {
+  cacheTimeout?: boolean;
+  maxDataPoints?: boolean;
+  minInterval?: boolean;
+}
+
 export interface PluginMeta {
 export interface PluginMeta {
   id: string;
   id: string;
   name: string;
   name: string;
@@ -38,6 +44,8 @@ export interface PluginMeta {
   explore?: boolean;
   explore?: boolean;
   annotations?: boolean;
   annotations?: boolean;
   mixed?: boolean;
   mixed?: boolean;
+  hasQueryHelp?: boolean;
+  queryOptions?: PluginMetaQueryOptions;
 }
 }
 
 
 export interface PluginInclude {
 export interface PluginInclude {