mirror of
https://github.com/grafana/grafana.git
synced 2025-02-10 23:55:47 -06:00
commit
9fec202668
96
public/app/core/components/PanelHelp/PluginHelp.tsx
Normal file
96
public/app/core/components/PanelHelp/PluginHelp.tsx
Normal file
@ -0,0 +1,96 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import Remarkable from 'remarkable';
|
||||
import { getBackendSrv } from '../../services/backend_srv';
|
||||
import { PluginMeta } from 'app/types';
|
||||
|
||||
interface Props {
|
||||
plugin: PluginMeta;
|
||||
type: string;
|
||||
}
|
||||
|
||||
interface State {
|
||||
isError: boolean;
|
||||
isLoading: boolean;
|
||||
help: string;
|
||||
}
|
||||
|
||||
export default class PluginHelp extends PureComponent<Props, State> {
|
||||
state = {
|
||||
isError: false,
|
||||
isLoading: false,
|
||||
help: '',
|
||||
};
|
||||
|
||||
componentDidMount(): void {
|
||||
this.loadHelp();
|
||||
}
|
||||
|
||||
constructPlaceholderInfo = () => {
|
||||
const { plugin } = this.props;
|
||||
const markdown = new Remarkable();
|
||||
|
||||
const fallBack = markdown.render(
|
||||
`## ${plugin.name} \n by _${plugin.info.author.name} (<${plugin.info.author.url}>)_\n\n${
|
||||
plugin.info.description
|
||||
}\n\n${
|
||||
plugin.info.links
|
||||
? `### Links \n ${plugin.info.links.map(link => {
|
||||
return `${link.name}: <${link.url}>\n`;
|
||||
})}`
|
||||
: ''
|
||||
}`
|
||||
);
|
||||
|
||||
return fallBack;
|
||||
};
|
||||
|
||||
loadHelp = () => {
|
||||
const { plugin, type } = this.props;
|
||||
this.setState({ isLoading: true });
|
||||
|
||||
getBackendSrv()
|
||||
.get(`/api/plugins/${plugin.id}/markdown/${type}`)
|
||||
.then(response => {
|
||||
const markdown = new Remarkable();
|
||||
const helpHtml = markdown.render(response);
|
||||
|
||||
if (response === '' && type === 'help') {
|
||||
this.setState({
|
||||
isError: false,
|
||||
isLoading: false,
|
||||
help: this.constructPlaceholderInfo(),
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
isError: false,
|
||||
isLoading: false,
|
||||
help: helpHtml,
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.setState({
|
||||
isError: true,
|
||||
isLoading: false,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { type } = this.props;
|
||||
const { isError, isLoading, help } = this.state;
|
||||
|
||||
if (isLoading) {
|
||||
return <h2>Loading help...</h2>;
|
||||
}
|
||||
|
||||
if (isError) {
|
||||
return <h3>'Error occurred when loading help'</h3>;
|
||||
}
|
||||
|
||||
if (type === 'panel_help' && help === '') {
|
||||
}
|
||||
|
||||
return <div className="markdown-html" dangerouslySetInnerHTML={{ __html: help }} />;
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
// Libraries
|
||||
import React, { SFC, PureComponent } from 'react';
|
||||
import Remarkable from 'remarkable';
|
||||
import _ from 'lodash';
|
||||
|
||||
// Components
|
||||
@ -22,6 +21,7 @@ import config from 'app/core/config';
|
||||
import { PanelModel } from '../panel_model';
|
||||
import { DashboardModel } from '../dashboard_model';
|
||||
import { DataSourceSelectItem, DataQuery } from 'app/types';
|
||||
import PluginHelp from '../../../core/components/PanelHelp/PluginHelp';
|
||||
|
||||
interface Props {
|
||||
panel: PanelModel;
|
||||
@ -128,43 +128,13 @@ export class QueriesTab extends PureComponent<Props, State> {
|
||||
});
|
||||
};
|
||||
|
||||
loadHelp = () => {
|
||||
const { currentDS } = this.state;
|
||||
const hasHelp = currentDS.meta.hasQueryHelp;
|
||||
|
||||
if (hasHelp) {
|
||||
this.setState({
|
||||
helpContent: <h3>Loading help...</h3>,
|
||||
isLoadingHelp: true,
|
||||
});
|
||||
|
||||
this.backendSrv
|
||||
.get(`/api/plugins/${currentDS.meta.id}/markdown/query_help`)
|
||||
.then(res => {
|
||||
const md = new Remarkable();
|
||||
const helpHtml = md.render(res);
|
||||
this.setState({
|
||||
helpContent: <div className="markdown-html" dangerouslySetInnerHTML={{ __html: helpHtml }} />,
|
||||
isLoadingHelp: false,
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
this.setState({
|
||||
helpContent: <h3>'Error occured when loading help'</h3>,
|
||||
isLoadingHelp: false,
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
renderQueryInspector = () => {
|
||||
const { panel } = this.props;
|
||||
return <QueryInspector panel={panel} LoadingPlaceholder={LoadingPlaceholder} />;
|
||||
};
|
||||
|
||||
renderHelp = () => {
|
||||
const { helpContent, isLoadingHelp } = this.state;
|
||||
return isLoadingHelp ? <LoadingPlaceholder text="Loading help..." /> : helpContent;
|
||||
return <PluginHelp plugin={this.state.currentDS.meta} type="query_help" />;
|
||||
};
|
||||
|
||||
onAddQuery = (query?: Partial<DataQuery>) => {
|
||||
@ -244,7 +214,6 @@ export class QueriesTab extends PureComponent<Props, State> {
|
||||
heading: 'Help',
|
||||
icon: 'fa fa-question',
|
||||
disabled: !hasQueryHelp,
|
||||
onClick: this.loadHelp,
|
||||
render: this.renderHelp,
|
||||
};
|
||||
|
||||
|
@ -3,10 +3,12 @@ import React, { PureComponent } from 'react';
|
||||
|
||||
// Utils & Services
|
||||
import { getAngularLoader, AngularComponent } from 'app/core/services/AngularLoader';
|
||||
import { getDatasourceSrv } from '../../plugins/datasource_srv';
|
||||
|
||||
// Components
|
||||
import { EditorTabBody } from './EditorTabBody';
|
||||
import { VizTypePicker } from './VizTypePicker';
|
||||
import PluginHelp from 'app/core/components/PanelHelp/PluginHelp';
|
||||
import { FadeIn } from 'app/core/components/Animations/FadeIn';
|
||||
import { PanelOptionSection } from './PanelOptionSection';
|
||||
|
||||
@ -14,6 +16,7 @@ import { PanelOptionSection } from './PanelOptionSection';
|
||||
import { PanelModel } from '../panel_model';
|
||||
import { DashboardModel } from '../dashboard_model';
|
||||
import { PanelPlugin } from 'app/types/plugins';
|
||||
import { DataSourceSelectItem } from 'app/types';
|
||||
|
||||
interface Props {
|
||||
panel: PanelModel;
|
||||
@ -24,6 +27,7 @@ interface Props {
|
||||
}
|
||||
|
||||
interface State {
|
||||
currentDataSource: DataSourceSelectItem;
|
||||
isVizPickerOpen: boolean;
|
||||
searchQuery: string;
|
||||
}
|
||||
@ -32,13 +36,16 @@ export class VisualizationTab extends PureComponent<Props, State> {
|
||||
element: HTMLElement;
|
||||
angularOptions: AngularComponent;
|
||||
searchInput: HTMLElement;
|
||||
dataSources: DataSourceSelectItem[] = getDatasourceSrv().getMetricSources();
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
const { panel } = props;
|
||||
|
||||
this.state = {
|
||||
isVizPickerOpen: false,
|
||||
searchQuery: '',
|
||||
currentDataSource: this.dataSources.find(datasource => datasource.value === panel.datasource),
|
||||
};
|
||||
}
|
||||
|
||||
@ -198,12 +205,20 @@ export class VisualizationTab extends PureComponent<Props, State> {
|
||||
}
|
||||
};
|
||||
|
||||
renderHelp = () => <PluginHelp plugin={this.state.currentDataSource.meta} type="help" />;
|
||||
|
||||
render() {
|
||||
const { plugin } = this.props;
|
||||
const { isVizPickerOpen, searchQuery } = this.state;
|
||||
|
||||
const pluginHelp = {
|
||||
heading: 'Help',
|
||||
icon: 'fa fa-question',
|
||||
render: this.renderHelp,
|
||||
};
|
||||
|
||||
return (
|
||||
<EditorTabBody heading="Visualization" renderToolbar={this.renderToolbar}>
|
||||
<EditorTabBody heading="Visualization" renderToolbar={this.renderToolbar} toolbarItems={[pluginHelp]}>
|
||||
<>
|
||||
<FadeIn in={isVizPickerOpen} duration={200} unmountOnExit={true}>
|
||||
<VizTypePicker
|
||||
|
@ -61,7 +61,10 @@ exports[`Render should render alpha info text 1`] = `
|
||||
},
|
||||
"description": "pretty decent plugin",
|
||||
"links": Array [
|
||||
"one link",
|
||||
Object {
|
||||
"name": "project",
|
||||
"url": "one link",
|
||||
},
|
||||
],
|
||||
"logos": Object {
|
||||
"large": "large/logo",
|
||||
@ -160,7 +163,10 @@ exports[`Render should render beta info text 1`] = `
|
||||
},
|
||||
"description": "pretty decent plugin",
|
||||
"links": Array [
|
||||
"one link",
|
||||
Object {
|
||||
"name": "project",
|
||||
"url": "one link",
|
||||
},
|
||||
],
|
||||
"logos": Object {
|
||||
"large": "large/logo",
|
||||
@ -254,7 +260,10 @@ exports[`Render should render component 1`] = `
|
||||
},
|
||||
"description": "pretty decent plugin",
|
||||
"links": Array [
|
||||
"one link",
|
||||
Object {
|
||||
"name": "project",
|
||||
"url": "one link",
|
||||
},
|
||||
],
|
||||
"logos": Object {
|
||||
"large": "large/logo",
|
||||
@ -353,7 +362,10 @@ exports[`Render should render is ready only message 1`] = `
|
||||
},
|
||||
"description": "pretty decent plugin",
|
||||
"links": Array [
|
||||
"one link",
|
||||
Object {
|
||||
"name": "project",
|
||||
"url": "one link",
|
||||
},
|
||||
],
|
||||
"logos": Object {
|
||||
"large": "large/logo",
|
||||
|
@ -73,7 +73,7 @@ export function getDataSourceLoadingNav(pageName: string): NavModel {
|
||||
url: '',
|
||||
},
|
||||
description: '',
|
||||
links: [''],
|
||||
links: [{ name: '', url: '' }],
|
||||
logos: {
|
||||
large: '',
|
||||
small: '',
|
||||
|
@ -70,7 +70,7 @@ export const getMockPlugin = () => {
|
||||
url: 'url/to/GrafanaLabs',
|
||||
},
|
||||
description: 'pretty decent plugin',
|
||||
links: ['one link'],
|
||||
links: [{ name: 'project', url: 'one link' }],
|
||||
logos: { small: 'small/logo', large: 'large/logo' },
|
||||
screenshots: [{ path: `screenshot` }],
|
||||
updated: '2018-09-26',
|
||||
|
@ -57,13 +57,18 @@ export interface PluginInclude {
|
||||
path: string;
|
||||
}
|
||||
|
||||
interface PluginMetaInfoLink {
|
||||
name: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
export interface PluginMetaInfo {
|
||||
author: {
|
||||
name: string;
|
||||
url?: string;
|
||||
};
|
||||
description: string;
|
||||
links: string[];
|
||||
links: PluginMetaInfoLink[];
|
||||
logos: {
|
||||
large: string;
|
||||
small: string;
|
||||
|
Loading…
Reference in New Issue
Block a user