|
1 | | -import React, { FormEvent, PureComponent } from 'react'; |
| 1 | +import React, { FormEvent, useEffect, useState } from 'react'; |
| 2 | +import { useEffectOnce } from 'react-use'; |
2 | 3 |
|
3 | | -import { reportInteraction } from '@grafana/runtime/src'; |
| 4 | +import { RawTimeRange, TimeRange } from '@grafana/data'; |
| 5 | +import { reportInteraction } from '@grafana/runtime'; |
4 | 6 | import { ClipboardButton, Field, Modal, Switch, TextArea } from '@grafana/ui'; |
5 | 7 | import { t, Trans } from 'app/core/internationalization'; |
6 | 8 |
|
7 | 9 | import { ThemePicker } from './ThemePicker'; |
8 | 10 | import { ShareModalTabProps } from './types'; |
9 | 11 | import { buildIframeHtml } from './utils'; |
10 | 12 |
|
11 | | -interface Props extends ShareModalTabProps {} |
12 | | - |
13 | | -interface State { |
14 | | - useCurrentTimeRange: boolean; |
15 | | - selectedTheme: string; |
16 | | - iframeHtml: string; |
| 13 | +interface Props extends Omit<ShareModalTabProps, 'panel' | 'dashboard'> { |
| 14 | + panel?: { timeFrom?: string; id: number }; |
| 15 | + dashboard: { uid: string; time: RawTimeRange }; |
| 16 | + range?: TimeRange; |
| 17 | + buildIframe?: typeof buildIframeHtml; |
17 | 18 | } |
18 | 19 |
|
19 | | -export class ShareEmbed extends PureComponent<Props, State> { |
20 | | - constructor(props: Props) { |
21 | | - super(props); |
22 | | - this.state = { |
23 | | - useCurrentTimeRange: true, |
24 | | - selectedTheme: 'current', |
25 | | - iframeHtml: '', |
26 | | - }; |
27 | | - } |
| 20 | +export function ShareEmbed({ panel, dashboard, range, buildIframe = buildIframeHtml }: Props) { |
| 21 | + const [useCurrentTimeRange, setUseCurrentTimeRange] = useState(true); |
| 22 | + const [selectedTheme, setSelectedTheme] = useState('current'); |
| 23 | + const [iframeHtml, setIframeHtml] = useState(''); |
28 | 24 |
|
29 | | - componentDidMount() { |
| 25 | + useEffectOnce(() => { |
30 | 26 | reportInteraction('grafana_dashboards_embed_share_viewed'); |
31 | | - this.buildIframeHtml(); |
32 | | - } |
33 | | - |
34 | | - buildIframeHtml = () => { |
35 | | - const { panel, dashboard } = this.props; |
36 | | - const { useCurrentTimeRange, selectedTheme } = this.state; |
37 | | - |
38 | | - const iframeHtml = buildIframeHtml(useCurrentTimeRange, dashboard.uid, selectedTheme, panel); |
39 | | - this.setState({ iframeHtml }); |
40 | | - }; |
| 27 | + }); |
41 | 28 |
|
42 | | - onIframeHtmlChange = (event: FormEvent<HTMLTextAreaElement>) => { |
43 | | - this.setState({ iframeHtml: event.currentTarget.value }); |
44 | | - }; |
| 29 | + useEffect(() => { |
| 30 | + const newIframeHtml = buildIframe(useCurrentTimeRange, dashboard.uid, selectedTheme, panel, range); |
| 31 | + setIframeHtml(newIframeHtml); |
| 32 | + }, [selectedTheme, useCurrentTimeRange, dashboard, panel, range, buildIframe]); |
45 | 33 |
|
46 | | - onUseCurrentTimeRangeChange = () => { |
47 | | - this.setState( |
48 | | - { |
49 | | - useCurrentTimeRange: !this.state.useCurrentTimeRange, |
50 | | - }, |
51 | | - this.buildIframeHtml |
52 | | - ); |
| 34 | + const onIframeHtmlChange = (event: FormEvent<HTMLTextAreaElement>) => { |
| 35 | + setIframeHtml(event.currentTarget.value); |
53 | 36 | }; |
54 | 37 |
|
55 | | - onThemeChange = (value: string) => { |
56 | | - this.setState({ selectedTheme: value }, this.buildIframeHtml); |
| 38 | + const onUseCurrentTimeRangeChange = () => { |
| 39 | + setUseCurrentTimeRange((useCurTimeRange) => !useCurTimeRange); |
57 | 40 | }; |
58 | 41 |
|
59 | | - getIframeHtml = () => { |
60 | | - return this.state.iframeHtml; |
| 42 | + const onThemeChange = (value: string) => { |
| 43 | + setSelectedTheme(value); |
61 | 44 | }; |
62 | 45 |
|
63 | | - render() { |
64 | | - const { useCurrentTimeRange, selectedTheme, iframeHtml } = this.state; |
65 | | - const isRelativeTime = this.props.dashboard ? this.props.dashboard.time.to === 'now' : false; |
66 | | - |
67 | | - const timeRangeDescription = isRelativeTime |
68 | | - ? t( |
69 | | - 'share-modal.embed.time-range-description', |
70 | | - 'Transforms the current relative time range to an absolute time range' |
71 | | - ) |
72 | | - : ''; |
| 46 | + const isRelativeTime = dashboard.time.to === 'now'; |
| 47 | + const timeRangeDescription = isRelativeTime |
| 48 | + ? t( |
| 49 | + 'share-modal.embed.time-range-description', |
| 50 | + 'Transforms the current relative time range to an absolute time range' |
| 51 | + ) |
| 52 | + : ''; |
73 | 53 |
|
74 | | - return ( |
75 | | - <> |
76 | | - <p className="share-modal-info-text"> |
77 | | - <Trans i18nKey="share-modal.embed.info">Generate HTML for embedding an iframe with this panel.</Trans> |
78 | | - </p> |
79 | | - <Field label={t('share-modal.embed.time-range', 'Current time range')} description={timeRangeDescription}> |
80 | | - <Switch |
81 | | - id="share-current-time-range" |
82 | | - value={useCurrentTimeRange} |
83 | | - onChange={this.onUseCurrentTimeRangeChange} |
84 | | - /> |
85 | | - </Field> |
86 | | - <ThemePicker selectedTheme={selectedTheme} onChange={this.onThemeChange} /> |
87 | | - <Field |
88 | | - label={t('share-modal.embed.html', 'Embed HTML')} |
89 | | - description={t( |
90 | | - 'share-modal.embed.html-description', |
91 | | - 'The HTML code below can be pasted and included in another web page. Unless anonymous access is enabled, the user viewing that page need to be signed into Grafana for the graph to load.' |
92 | | - )} |
93 | | - > |
94 | | - <TextArea |
95 | | - data-testid="share-embed-html" |
96 | | - id="share-panel-embed-embed-html-textarea" |
97 | | - rows={5} |
98 | | - value={iframeHtml} |
99 | | - onChange={this.onIframeHtmlChange} |
100 | | - /> |
101 | | - </Field> |
102 | | - <Modal.ButtonRow> |
103 | | - <ClipboardButton icon="copy" variant="primary" getText={this.getIframeHtml}> |
104 | | - <Trans i18nKey="share-modal.embed.copy">Copy to clipboard</Trans> |
105 | | - </ClipboardButton> |
106 | | - </Modal.ButtonRow> |
107 | | - </> |
108 | | - ); |
109 | | - } |
| 54 | + return ( |
| 55 | + <> |
| 56 | + <p className="share-modal-info-text"> |
| 57 | + <Trans i18nKey="share-modal.embed.info">Generate HTML for embedding an iframe with this panel.</Trans> |
| 58 | + </p> |
| 59 | + <Field label={t('share-modal.embed.time-range', 'Current time range')} description={timeRangeDescription}> |
| 60 | + <Switch id="share-current-time-range" value={useCurrentTimeRange} onChange={onUseCurrentTimeRangeChange} /> |
| 61 | + </Field> |
| 62 | + <ThemePicker selectedTheme={selectedTheme} onChange={onThemeChange} /> |
| 63 | + <Field |
| 64 | + label={t('share-modal.embed.html', 'Embed HTML')} |
| 65 | + description={t( |
| 66 | + 'share-modal.embed.html-description', |
| 67 | + 'The HTML code below can be pasted and included in another web page. Unless anonymous access is enabled, the user viewing that page need to be signed into Grafana for the graph to load.' |
| 68 | + )} |
| 69 | + > |
| 70 | + <TextArea |
| 71 | + data-testid="share-embed-html" |
| 72 | + id="share-panel-embed-embed-html-textarea" |
| 73 | + rows={5} |
| 74 | + value={iframeHtml} |
| 75 | + onChange={onIframeHtmlChange} |
| 76 | + /> |
| 77 | + </Field> |
| 78 | + <Modal.ButtonRow> |
| 79 | + <ClipboardButton icon="copy" variant="primary" getText={() => iframeHtml}> |
| 80 | + <Trans i18nKey="share-modal.embed.copy">Copy to clipboard</Trans> |
| 81 | + </ClipboardButton> |
| 82 | + </Modal.ButtonRow> |
| 83 | + </> |
| 84 | + ); |
110 | 85 | } |
0 commit comments