TextPanel.tsx 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. import React, { Component } from 'react';
  2. import Remarkable from 'remarkable';
  3. import { sanitize } from 'app/core/utils/text';
  4. import config from 'app/core/config';
  5. import templateSrv from 'app/features/templating/template_srv';
  6. import { debounce } from 'lodash';
  7. // Types
  8. import { TextOptions } from './types';
  9. import { PanelProps } from '@grafana/ui/src/types';
  10. interface Props extends PanelProps<TextOptions> {}
  11. interface State {
  12. html: string;
  13. }
  14. export class TextPanel extends Component<Props, State> {
  15. remarkable: Remarkable;
  16. constructor(props) {
  17. super(props);
  18. // TODO thre must be some better way to start with defualt options!
  19. let opts = props.options;
  20. if (opts && opts['options']) {
  21. opts = opts['options'];
  22. console.log('WEIRD!', opts);
  23. }
  24. this.state = {
  25. html: this.processContent(opts),
  26. };
  27. }
  28. updateHTML = debounce(() => {
  29. const html = this.processContent(this.props.options);
  30. if (html !== this.state.html) {
  31. this.setState({ html });
  32. }
  33. }, 100);
  34. componentDidUpdate(prevProps: Props) {
  35. // Since any change could be referenced in a template variable,
  36. // This needs to process everything
  37. this.updateHTML();
  38. }
  39. prepareHTML(html: string): string {
  40. const scopedVars = {}; // TODO?? = this.props.;
  41. html = config.disableSanitizeHtml ? html : sanitize(html);
  42. try {
  43. return templateSrv.replace(html, scopedVars);
  44. } catch (e) {
  45. // TODO -- put the error in the header window
  46. console.log('Text panel error: ', e);
  47. return html;
  48. }
  49. }
  50. prepareText(content: string): string {
  51. return this.prepareHTML(
  52. content
  53. .replace(/&/g, '&amp;')
  54. .replace(/>/g, '&gt;')
  55. .replace(/</g, '&lt;')
  56. .replace(/\n/g, '<br/>')
  57. );
  58. }
  59. prepareMarkdown(content: string): string {
  60. if (!this.remarkable) {
  61. this.remarkable = new Remarkable();
  62. }
  63. return this.prepareHTML(this.remarkable.render(content));
  64. }
  65. processContent(options: TextOptions): string {
  66. const { mode, content } = options;
  67. if (!content) {
  68. return '';
  69. }
  70. if (mode === 'markdown') {
  71. return this.prepareMarkdown(content);
  72. }
  73. if (mode === 'html') {
  74. return this.prepareHTML(content);
  75. }
  76. return this.prepareText(content);
  77. }
  78. render() {
  79. const { html } = this.state;
  80. return <div className="markdown-html panel-text-content" dangerouslySetInnerHTML={{ __html: html }} />;
  81. }
  82. }