Browse Source

Merge branch 'alpha-text2' of https://github.com/ryantxu/grafana into ryantxu-alpha-text2

Torkel Ödegaard 6 năm trước cách đây
mục cha
commit
90f8179bd2

+ 93 - 0
public/app/plugins/panel/text2/TextPanel.tsx

@@ -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, '&amp;')
+        .replace(/>/g, '&gt;')
+        .replace(/</g, '&lt;')
+        .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 - 0
public/app/plugins/panel/text2/TextPanelEditor.tsx

@@ -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>
+    );
+  }
+}

+ 7 - 11
public/app/plugins/panel/text2/module.tsx

@@ -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 - 0
public/app/plugins/panel/text2/types.ts

@@ -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/)
+
+
+`,
+};