mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Merge branch 'alpha-text2' of https://github.com/ryantxu/grafana into ryantxu-alpha-text2
This commit is contained in:
commit
90f8179bd2
93
public/app/plugins/panel/text2/TextPanel.tsx
Normal file
93
public/app/plugins/panel/text2/TextPanel.tsx
Normal file
@ -0,0 +1,93 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
|
||||
import Remarkable from 'remarkable';
|
||||
import { sanitize } from 'app/core/utils/text';
|
||||
import config from 'app/core/config';
|
||||
import { debounce } from 'lodash';
|
||||
|
||||
// Types
|
||||
import { TextOptions } from './types';
|
||||
import { PanelProps } from '@grafana/ui/src/types';
|
||||
|
||||
interface Props extends PanelProps<TextOptions> {}
|
||||
interface State {
|
||||
html: string;
|
||||
}
|
||||
|
||||
export class TextPanel extends PureComponent<Props, State> {
|
||||
remarkable: Remarkable;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
html: this.processContent(props.options),
|
||||
};
|
||||
}
|
||||
|
||||
updateHTML = debounce(() => {
|
||||
const html = this.processContent(this.props.options);
|
||||
if (html !== this.state.html) {
|
||||
this.setState({ html });
|
||||
}
|
||||
}, 150);
|
||||
|
||||
componentDidUpdate(prevProps: Props) {
|
||||
// Since any change could be referenced in a template variable,
|
||||
// This needs to process everytime (with debounce)
|
||||
this.updateHTML();
|
||||
}
|
||||
|
||||
prepareHTML(html: string): string {
|
||||
const { replaceVariables } = this.props;
|
||||
|
||||
html = config.disableSanitizeHtml ? html : sanitize(html);
|
||||
try {
|
||||
return replaceVariables(html);
|
||||
} catch (e) {
|
||||
// TODO -- put the error in the header window
|
||||
console.log('Text panel error: ', e);
|
||||
return html;
|
||||
}
|
||||
}
|
||||
|
||||
prepareText(content: string): string {
|
||||
return this.prepareHTML(
|
||||
content
|
||||
.replace(/&/g, '&')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/</g, '<')
|
||||
.replace(/\n/g, '<br/>')
|
||||
);
|
||||
}
|
||||
|
||||
prepareMarkdown(content: string): string {
|
||||
if (!this.remarkable) {
|
||||
this.remarkable = new Remarkable();
|
||||
}
|
||||
return this.prepareHTML(this.remarkable.render(content));
|
||||
}
|
||||
|
||||
processContent(options: TextOptions): string {
|
||||
const { mode, content } = options;
|
||||
|
||||
if (!content) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (mode === 'markdown') {
|
||||
return this.prepareMarkdown(content);
|
||||
}
|
||||
if (mode === 'html') {
|
||||
return this.prepareHTML(content);
|
||||
}
|
||||
|
||||
return this.prepareText(content);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { html } = this.state;
|
||||
|
||||
return <div className="markdown-html panel-text-content" dangerouslySetInnerHTML={{ __html: html }} />;
|
||||
}
|
||||
}
|
32
public/app/plugins/panel/text2/TextPanelEditor.tsx
Normal file
32
public/app/plugins/panel/text2/TextPanelEditor.tsx
Normal file
@ -0,0 +1,32 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { PanelEditorProps, PanelOptionsGroup, Select, SelectOptionItem } from '@grafana/ui';
|
||||
|
||||
import { TextOptions } from './types';
|
||||
|
||||
export class TextPanelEditor extends PureComponent<PanelEditorProps<TextOptions>> {
|
||||
modes: SelectOptionItem[] = [
|
||||
{ value: 'markdown', label: 'Markdown' },
|
||||
{ value: 'text', label: 'Text' },
|
||||
{ value: 'html', label: 'HTML' },
|
||||
];
|
||||
|
||||
onModeChange = (item: SelectOptionItem) => this.props.onOptionsChange({ ...this.props.options, mode: item.value });
|
||||
|
||||
onContentChange = evt => this.props.onOptionsChange({ ...this.props.options, content: (event.target as any).value });
|
||||
|
||||
render() {
|
||||
const { mode, content } = this.props.options;
|
||||
|
||||
return (
|
||||
<PanelOptionsGroup title="Text">
|
||||
<div className="gf-form">
|
||||
<span className="gf-form-label">Mode</span>
|
||||
<Select onChange={this.onModeChange} value={this.modes.find(e => mode === e.value)} options={this.modes} />
|
||||
</div>
|
||||
|
||||
{/* TODO: <code-editor */}
|
||||
<textarea value={content} onChange={this.onContentChange} className="gf-form-input" rows={10} />
|
||||
</PanelOptionsGroup>
|
||||
);
|
||||
}
|
||||
}
|
@ -1,14 +1,10 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { PanelProps, ReactPanelPlugin } from '@grafana/ui';
|
||||
import { ReactPanelPlugin } from '@grafana/ui';
|
||||
|
||||
export class Text2 extends PureComponent<PanelProps> {
|
||||
constructor(props: PanelProps) {
|
||||
super(props);
|
||||
}
|
||||
import { TextPanelEditor } from './TextPanelEditor';
|
||||
import { TextPanel } from './TextPanel';
|
||||
import { TextOptions, defaults } from './types';
|
||||
|
||||
render() {
|
||||
return <h2>Text Panel!</h2>;
|
||||
}
|
||||
}
|
||||
export const reactPanel = new ReactPanelPlugin<TextOptions>(TextPanel);
|
||||
|
||||
export const reactPanel = new ReactPanelPlugin(Text2);
|
||||
reactPanel.setEditor(TextPanelEditor);
|
||||
reactPanel.setDefaults(defaults);
|
||||
|
14
public/app/plugins/panel/text2/types.ts
Normal file
14
public/app/plugins/panel/text2/types.ts
Normal file
@ -0,0 +1,14 @@
|
||||
export interface TextOptions {
|
||||
mode: 'html' | 'markdown' | 'text';
|
||||
content: string;
|
||||
}
|
||||
|
||||
export const defaults: TextOptions = {
|
||||
mode: 'markdown',
|
||||
content: `# Title
|
||||
|
||||
For markdown syntax help: [commonmark.org/help](https://commonmark.org/help/)
|
||||
|
||||
|
||||
`,
|
||||
};
|
Loading…
Reference in New Issue
Block a user