Files
grafana/public/app/features/dashboard/components/ShareModal/ShareLink.tsx

182 lines
6.0 KiB
TypeScript
Raw Normal View History

import React, { PureComponent } from 'react';
import { selectors as e2eSelectors } from '@grafana/e2e-selectors';
import { Alert, ClipboardButton, Field, FieldSet, Icon, Input, Switch } from '@grafana/ui';
import config from 'app/core/config';
import { t, Trans } from 'app/core/internationalization';
import { ThemePicker } from './ThemePicker';
import { trackDashboardSharingActionPerType } from './analytics';
import { ShareModalTabProps } from './types';
import { buildImageUrl, buildShareUrl, shareDashboardType } from './utils';
export interface Props extends ShareModalTabProps {}
export interface State {
useCurrentTimeRange: boolean;
Dashboard: Allow shortlink generation (#27409) * intial frontend resolution/redirection logic * backend scaffolding * enough of the frontend to actually test end to end * bugfixes * add tests * cleanup * explore too hard for now * fix build * Docs: add docs * FE test * redirect directly from backend * validate incoming uids * add last_seen_at * format documentation * more documentation feedback * very shaky migration of get route to middleware * persist unix timestamps * add id, orgId to table * fixes for orgId scoping * whoops forgot the middleware * only redirect to absolute URLs under the AppUrl domain * move lookup route to /goto/:uid, stop manually setting 404 response code * renaming things according to PR feedback * tricky deletion * sneaky readd * fix test * more BE renaming * FE updates -- no more @ts-ignore hacking :) and accounting for subpath * Simplify code Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Short URLs: Drop usage of bus Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * ShortURLService: Make injectable Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Rename file Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Add handling of url parsing and creating of full shortURL to backend * Update test, remove unused imports * Update pkg/api/short_urls.go Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com> * Add correct import * Pass context to short url service * Remove not needed error log * Rename dto and field to denote URL rather than path * Update api docs based on feedback/suggestion * Rename files to singular * Revert to send relative path to backend * Fixes after review * Return dto when creating short URL that includes the full url Use full url to provide shorten URL to the user * Fix after review * Fix relative url path when creating new short url Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com> Co-authored-by: Ivana <ivana.huckova@gmail.com> Co-authored-by: Ivana Huckova <30407135+ivanahuckova@users.noreply.github.com> Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
2020-10-14 06:48:48 -04:00
useShortUrl: boolean;
selectedTheme: string;
shareUrl: string;
imageUrl: string;
}
export class ShareLink extends PureComponent<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
useCurrentTimeRange: true,
Dashboard: Allow shortlink generation (#27409) * intial frontend resolution/redirection logic * backend scaffolding * enough of the frontend to actually test end to end * bugfixes * add tests * cleanup * explore too hard for now * fix build * Docs: add docs * FE test * redirect directly from backend * validate incoming uids * add last_seen_at * format documentation * more documentation feedback * very shaky migration of get route to middleware * persist unix timestamps * add id, orgId to table * fixes for orgId scoping * whoops forgot the middleware * only redirect to absolute URLs under the AppUrl domain * move lookup route to /goto/:uid, stop manually setting 404 response code * renaming things according to PR feedback * tricky deletion * sneaky readd * fix test * more BE renaming * FE updates -- no more @ts-ignore hacking :) and accounting for subpath * Simplify code Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Short URLs: Drop usage of bus Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * ShortURLService: Make injectable Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Rename file Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Add handling of url parsing and creating of full shortURL to backend * Update test, remove unused imports * Update pkg/api/short_urls.go Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com> * Add correct import * Pass context to short url service * Remove not needed error log * Rename dto and field to denote URL rather than path * Update api docs based on feedback/suggestion * Rename files to singular * Revert to send relative path to backend * Fixes after review * Return dto when creating short URL that includes the full url Use full url to provide shorten URL to the user * Fix after review * Fix relative url path when creating new short url Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com> Co-authored-by: Ivana <ivana.huckova@gmail.com> Co-authored-by: Ivana Huckova <30407135+ivanahuckova@users.noreply.github.com> Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
2020-10-14 06:48:48 -04:00
useShortUrl: false,
selectedTheme: 'current',
shareUrl: '',
imageUrl: '',
};
}
componentDidMount() {
this.buildUrl();
}
componentDidUpdate(prevProps: Props, prevState: State) {
const { useCurrentTimeRange, useShortUrl, selectedTheme } = this.state;
if (
prevState.useCurrentTimeRange !== useCurrentTimeRange ||
prevState.selectedTheme !== selectedTheme ||
Dashboard: Allow shortlink generation (#27409) * intial frontend resolution/redirection logic * backend scaffolding * enough of the frontend to actually test end to end * bugfixes * add tests * cleanup * explore too hard for now * fix build * Docs: add docs * FE test * redirect directly from backend * validate incoming uids * add last_seen_at * format documentation * more documentation feedback * very shaky migration of get route to middleware * persist unix timestamps * add id, orgId to table * fixes for orgId scoping * whoops forgot the middleware * only redirect to absolute URLs under the AppUrl domain * move lookup route to /goto/:uid, stop manually setting 404 response code * renaming things according to PR feedback * tricky deletion * sneaky readd * fix test * more BE renaming * FE updates -- no more @ts-ignore hacking :) and accounting for subpath * Simplify code Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Short URLs: Drop usage of bus Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * ShortURLService: Make injectable Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Rename file Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Add handling of url parsing and creating of full shortURL to backend * Update test, remove unused imports * Update pkg/api/short_urls.go Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com> * Add correct import * Pass context to short url service * Remove not needed error log * Rename dto and field to denote URL rather than path * Update api docs based on feedback/suggestion * Rename files to singular * Revert to send relative path to backend * Fixes after review * Return dto when creating short URL that includes the full url Use full url to provide shorten URL to the user * Fix after review * Fix relative url path when creating new short url Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com> Co-authored-by: Ivana <ivana.huckova@gmail.com> Co-authored-by: Ivana Huckova <30407135+ivanahuckova@users.noreply.github.com> Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
2020-10-14 06:48:48 -04:00
prevState.useShortUrl !== useShortUrl
) {
this.buildUrl();
}
}
buildUrl = async () => {
const { panel, dashboard } = this.props;
const { useCurrentTimeRange, useShortUrl, selectedTheme } = this.state;
const shareUrl = await buildShareUrl(useCurrentTimeRange, selectedTheme, panel, useShortUrl);
const imageUrl = buildImageUrl(useCurrentTimeRange, dashboard.uid, selectedTheme, panel);
Dashboard: Allow shortlink generation (#27409) * intial frontend resolution/redirection logic * backend scaffolding * enough of the frontend to actually test end to end * bugfixes * add tests * cleanup * explore too hard for now * fix build * Docs: add docs * FE test * redirect directly from backend * validate incoming uids * add last_seen_at * format documentation * more documentation feedback * very shaky migration of get route to middleware * persist unix timestamps * add id, orgId to table * fixes for orgId scoping * whoops forgot the middleware * only redirect to absolute URLs under the AppUrl domain * move lookup route to /goto/:uid, stop manually setting 404 response code * renaming things according to PR feedback * tricky deletion * sneaky readd * fix test * more BE renaming * FE updates -- no more @ts-ignore hacking :) and accounting for subpath * Simplify code Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Short URLs: Drop usage of bus Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * ShortURLService: Make injectable Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Rename file Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Add handling of url parsing and creating of full shortURL to backend * Update test, remove unused imports * Update pkg/api/short_urls.go Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com> * Add correct import * Pass context to short url service * Remove not needed error log * Rename dto and field to denote URL rather than path * Update api docs based on feedback/suggestion * Rename files to singular * Revert to send relative path to backend * Fixes after review * Return dto when creating short URL that includes the full url Use full url to provide shorten URL to the user * Fix after review * Fix relative url path when creating new short url Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com> Co-authored-by: Ivana <ivana.huckova@gmail.com> Co-authored-by: Ivana Huckova <30407135+ivanahuckova@users.noreply.github.com> Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
2020-10-14 06:48:48 -04:00
this.setState({ shareUrl, imageUrl });
};
onUseCurrentTimeRangeChange = () => {
this.setState({ useCurrentTimeRange: !this.state.useCurrentTimeRange });
};
Dashboard: Allow shortlink generation (#27409) * intial frontend resolution/redirection logic * backend scaffolding * enough of the frontend to actually test end to end * bugfixes * add tests * cleanup * explore too hard for now * fix build * Docs: add docs * FE test * redirect directly from backend * validate incoming uids * add last_seen_at * format documentation * more documentation feedback * very shaky migration of get route to middleware * persist unix timestamps * add id, orgId to table * fixes for orgId scoping * whoops forgot the middleware * only redirect to absolute URLs under the AppUrl domain * move lookup route to /goto/:uid, stop manually setting 404 response code * renaming things according to PR feedback * tricky deletion * sneaky readd * fix test * more BE renaming * FE updates -- no more @ts-ignore hacking :) and accounting for subpath * Simplify code Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Short URLs: Drop usage of bus Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * ShortURLService: Make injectable Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Rename file Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Add handling of url parsing and creating of full shortURL to backend * Update test, remove unused imports * Update pkg/api/short_urls.go Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com> * Add correct import * Pass context to short url service * Remove not needed error log * Rename dto and field to denote URL rather than path * Update api docs based on feedback/suggestion * Rename files to singular * Revert to send relative path to backend * Fixes after review * Return dto when creating short URL that includes the full url Use full url to provide shorten URL to the user * Fix after review * Fix relative url path when creating new short url Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com> Co-authored-by: Ivana <ivana.huckova@gmail.com> Co-authored-by: Ivana Huckova <30407135+ivanahuckova@users.noreply.github.com> Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
2020-10-14 06:48:48 -04:00
onUrlShorten = () => {
this.setState({ useShortUrl: !this.state.useShortUrl });
};
onThemeChange = (value: string) => {
this.setState({ selectedTheme: value });
};
getShareUrl = () => {
return this.state.shareUrl;
};
onCopy() {
trackDashboardSharingActionPerType('copy_link', shareDashboardType.link);
}
render() {
const { panel, dashboard } = this.props;
const isRelativeTime = dashboard ? dashboard.time.to === 'now' : false;
const { useCurrentTimeRange, useShortUrl, selectedTheme, shareUrl, imageUrl } = this.state;
const selectors = e2eSelectors.pages.SharePanelModal;
const isDashboardSaved = Boolean(dashboard.id);
const timeRangeLabelTranslation = t('share-modal.link.time-range-label', `Lock time range`);
const timeRangeDescriptionTranslation = t(
'share-modal.link.time-range-description',
`Transforms the current relative time range to an absolute time range`
);
const shortenURLTranslation = t('share-modal.link.shorten-url', `Shorten URL`);
const linkURLTranslation = t('share-modal.link.link-url', `Link URL`);
return (
<>
<p className="share-modal-info-text">
<Trans i18nKey="share-modal.link.info-text">
Create a direct link to this dashboard or panel, customized with the options below.
</Trans>
</p>
<FieldSet>
<Field label={timeRangeLabelTranslation} description={isRelativeTime ? timeRangeDescriptionTranslation : ''}>
<Switch
id="share-current-time-range"
value={useCurrentTimeRange}
onChange={this.onUseCurrentTimeRangeChange}
/>
</Field>
<ThemePicker selectedTheme={selectedTheme} onChange={this.onThemeChange} />
<Field label={shortenURLTranslation}>
<Switch id="share-shorten-url" value={useShortUrl} onChange={this.onUrlShorten} />
</Field>
<Field label={linkURLTranslation}>
<Input
id="link-url-input"
value={shareUrl}
readOnly
addonAfter={
<ClipboardButton icon="copy" variant="primary" getText={this.getShareUrl} onClipboardCopy={this.onCopy}>
<Trans i18nKey="share-modal.link.copy-link-button">Copy</Trans>
</ClipboardButton>
}
/>
</Field>
</FieldSet>
{panel && config.rendererAvailable && (
<>
{isDashboardSaved && (
<div className="gf-form">
<a href={imageUrl} target="_blank" rel="noreferrer" aria-label={selectors.linkToRenderedImage}>
<Icon name="camera" />
&nbsp;
<Trans i18nKey="share-modal.link.rendered-image">Direct link rendered image</Trans>
</a>
</div>
)}
{!isDashboardSaved && (
<Alert
severity="info"
title={t('share-modal.link.save-alert', 'Dashboard is not saved')}
bottomSpacing={0}
>
<Trans i18nKey="share-modal.link.save-dashboard">
To render a panel image, you must save the dashboard first.
</Trans>
</Alert>
)}
</>
)}
{panel && !config.rendererAvailable && (
<Alert
severity="info"
title={t('share-modal.link.render-alert', 'Image renderer plugin not installed')}
bottomSpacing={0}
>
<Trans i18nKey="share-modal.link.render-instructions">
To render a panel image, you must install the&nbsp;
<a
href="https://grafana.com/grafana/plugins/grafana-image-renderer"
target="_blank"
rel="noopener noreferrer"
className="external-link"
>
Grafana image renderer plugin
</a>
. Please contact your Grafana administrator to install the plugin.
</Trans>
</Alert>
)}
</>
);
}
}