TextPanel.tsx 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. // Libraries
  2. import React, { PureComponent } from 'react';
  3. import { debounce } from 'lodash';
  4. import { renderMarkdown } from '@grafana/data';
  5. // Utils
  6. import { sanitize } from 'app/core/utils/text';
  7. import config from 'app/core/config';
  8. // Types
  9. import { TextOptions } from './types';
  10. import { PanelProps } from '@grafana/ui/src/types';
  11. interface Props extends PanelProps<TextOptions> {}
  12. interface State {
  13. html: string;
  14. }
  15. export class TextPanel extends PureComponent<Props, State> {
  16. constructor(props: Props) {
  17. super(props);
  18. this.state = {
  19. html: this.processContent(props.options),
  20. };
  21. }
  22. updateHTML = debounce(() => {
  23. const html = this.processContent(this.props.options);
  24. if (html !== this.state.html) {
  25. this.setState({ html });
  26. }
  27. }, 150);
  28. componentDidUpdate(prevProps: Props) {
  29. // Since any change could be referenced in a template variable,
  30. // This needs to process everytime (with debounce)
  31. this.updateHTML();
  32. }
  33. prepareHTML(html: string): string {
  34. const { replaceVariables } = this.props;
  35. html = config.disableSanitizeHtml ? html : sanitize(html);
  36. return replaceVariables(html);
  37. }
  38. prepareText(content: string): string {
  39. return this.prepareHTML(
  40. content
  41. .replace(/&/g, '&amp;')
  42. .replace(/>/g, '&gt;')
  43. .replace(/</g, '&lt;')
  44. .replace(/\n/g, '<br/>')
  45. );
  46. }
  47. prepareMarkdown(content: string): string {
  48. return this.prepareHTML(renderMarkdown(content));
  49. }
  50. processContent(options: TextOptions): string {
  51. const { mode, content } = options;
  52. if (!content) {
  53. return '';
  54. }
  55. if (mode === 'markdown') {
  56. return this.prepareMarkdown(content);
  57. }
  58. if (mode === 'html') {
  59. return this.prepareHTML(content);
  60. }
  61. return this.prepareText(content);
  62. }
  63. render() {
  64. const { html } = this.state;
  65. return <div className="markdown-html panel-text-content" dangerouslySetInnerHTML={{ __html: html }} />;
  66. }
  67. }