mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
GrafanaUI: Add success state to ClipboardButton (#52069)
* User Experience: apply the same pattern feedback for all copy to clipboard buttons * add copy icon to all ClipboardButton use cases * Change primary color for copy to clipboard in create token * Add success button variant * Remove copy confirmation from TableCellInspectModal because it's in the base component now * Design tweaks to copy confirmation - Only change the icon to tick to avoid the button changing size - Change button to success green - Only show copy confirmation state for 2 seconds * revert TabelCellInspectModal text button back * revert accidental change to ShareLink Co-authored-by: joshhunt <josh@trtr.co>
This commit is contained in:
committed by
GitHub
parent
ba76be174f
commit
0633840777
@@ -5,13 +5,11 @@ import React, { useCallback, useState } from 'react';
|
||||
import { GrafanaTheme } from '@grafana/data';
|
||||
import { Stack } from '@grafana/experimental';
|
||||
import { Button, ClipboardButton, HorizontalGroup, stylesFactory, TextArea, useTheme } from '@grafana/ui';
|
||||
import { useAppNotification } from 'app/core/copy/appNotification';
|
||||
|
||||
import { SaveDashboardFormProps } from '../types';
|
||||
|
||||
export const SaveProvisionedDashboardForm: React.FC<SaveDashboardFormProps> = ({ dashboard, onCancel }) => {
|
||||
const theme = useTheme();
|
||||
const notifyApp = useAppNotification();
|
||||
const [dashboardJSON, setDashboardJson] = useState(() => {
|
||||
const clone = dashboard.getSaveModelClone();
|
||||
delete clone.id;
|
||||
@@ -25,10 +23,6 @@ export const SaveProvisionedDashboardForm: React.FC<SaveDashboardFormProps> = ({
|
||||
saveAs(blob, dashboard.title + '-' + new Date().getTime() + '.json');
|
||||
}, [dashboard.title, dashboardJSON]);
|
||||
|
||||
const onCopyToClipboardSuccess = useCallback(() => {
|
||||
notifyApp.success('Dashboard JSON copied to clipboard');
|
||||
}, [notifyApp]);
|
||||
|
||||
const styles = getStyles(theme);
|
||||
return (
|
||||
<>
|
||||
@@ -64,7 +58,7 @@ export const SaveProvisionedDashboardForm: React.FC<SaveDashboardFormProps> = ({
|
||||
<Button variant="secondary" onClick={onCancel} fill="outline">
|
||||
Cancel
|
||||
</Button>
|
||||
<ClipboardButton getText={() => dashboardJSON} onClipboardCopy={onCopyToClipboardSuccess}>
|
||||
<ClipboardButton icon="copy" getText={() => dashboardJSON}>
|
||||
Copy JSON to clipboard
|
||||
</ClipboardButton>
|
||||
<Button type="submit" onClick={saveToFile}>
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import React, { FormEvent, PureComponent } from 'react';
|
||||
|
||||
import { AppEvents, SelectableValue } from '@grafana/data';
|
||||
import { SelectableValue } from '@grafana/data';
|
||||
import { reportInteraction } from '@grafana/runtime/src';
|
||||
import { ClipboardButton, Field, Modal, RadioButtonGroup, Switch, TextArea } from '@grafana/ui';
|
||||
import { appEvents } from 'app/core/core';
|
||||
|
||||
import { ShareModalTabProps } from './types';
|
||||
import { buildIframeHtml } from './utils';
|
||||
@@ -62,10 +61,6 @@ export class ShareEmbed extends PureComponent<Props, State> {
|
||||
this.setState({ selectedTheme: value }, this.buildIframeHtml);
|
||||
};
|
||||
|
||||
onIframeHtmlCopy = () => {
|
||||
appEvents.emit(AppEvents.alertSuccess, ['Content copied to clipboard']);
|
||||
};
|
||||
|
||||
getIframeHtml = () => {
|
||||
return this.state.iframeHtml;
|
||||
};
|
||||
@@ -104,7 +99,7 @@ export class ShareEmbed extends PureComponent<Props, State> {
|
||||
/>
|
||||
</Field>
|
||||
<Modal.ButtonRow>
|
||||
<ClipboardButton variant="primary" getText={this.getIframeHtml} onClipboardCopy={this.onIframeHtmlCopy}>
|
||||
<ClipboardButton icon="copy" variant="primary" getText={this.getIframeHtml}>
|
||||
Copy to clipboard
|
||||
</ClipboardButton>
|
||||
</Modal.ButtonRow>
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
|
||||
import { AppEvents, SelectableValue } from '@grafana/data';
|
||||
import { SelectableValue } from '@grafana/data';
|
||||
import { selectors as e2eSelectors } from '@grafana/e2e-selectors';
|
||||
import { reportInteraction } from '@grafana/runtime/src';
|
||||
import { Alert, ClipboardButton, Field, FieldSet, Icon, Input, RadioButtonGroup, Switch } from '@grafana/ui';
|
||||
import config from 'app/core/config';
|
||||
import { appEvents } from 'app/core/core';
|
||||
|
||||
import { ShareModalTabProps } from './types';
|
||||
import { buildImageUrl, buildShareUrl } from './utils';
|
||||
@@ -76,10 +75,6 @@ export class ShareLink extends PureComponent<Props, State> {
|
||||
this.setState({ selectedTheme: value });
|
||||
};
|
||||
|
||||
onShareUrlCopy = () => {
|
||||
appEvents.emit(AppEvents.alertSuccess, ['Content copied to clipboard']);
|
||||
};
|
||||
|
||||
getShareUrl = () => {
|
||||
return this.state.shareUrl;
|
||||
};
|
||||
@@ -120,8 +115,8 @@ export class ShareLink extends PureComponent<Props, State> {
|
||||
value={shareUrl}
|
||||
readOnly
|
||||
addonAfter={
|
||||
<ClipboardButton variant="primary" getText={this.getShareUrl} onClipboardCopy={this.onShareUrlCopy}>
|
||||
<Icon name="copy" /> Copy
|
||||
<ClipboardButton icon="copy" variant="primary" getText={this.getShareUrl}>
|
||||
Copy
|
||||
</ClipboardButton>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
import { AppEvents } from '@grafana/data';
|
||||
import { reportInteraction } from '@grafana/runtime/src';
|
||||
import {
|
||||
Alert,
|
||||
@@ -16,7 +15,6 @@ import {
|
||||
} from '@grafana/ui';
|
||||
import { notifyApp } from 'app/core/actions';
|
||||
import { createErrorNotification } from 'app/core/copy/appNotification';
|
||||
import { appEvents } from 'app/core/core';
|
||||
import { dispatch } from 'app/store/store';
|
||||
|
||||
import {
|
||||
@@ -79,10 +77,6 @@ export const SharePublicDashboard = (props: Props) => {
|
||||
savePublicDashboardConfig(props.dashboard.uid, publicDashboard, setPublicDashboardConfig).catch();
|
||||
};
|
||||
|
||||
const onShareUrlCopy = () => {
|
||||
appEvents.emit(AppEvents.alertSuccess, ['Content copied to clipboard']);
|
||||
};
|
||||
|
||||
const onAcknowledge = useCallback(
|
||||
(field: string, checked: boolean) => {
|
||||
setAcknowledgements({ ...acknowledgements, [field]: checked });
|
||||
@@ -219,7 +213,6 @@ export const SharePublicDashboard = (props: Props) => {
|
||||
getText={() => {
|
||||
return generatePublicDashboardUrl(publicDashboard);
|
||||
}}
|
||||
onClipboardCopy={onShareUrlCopy}
|
||||
>
|
||||
Copy
|
||||
</ClipboardButton>
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
|
||||
import { AppEvents, SelectableValue } from '@grafana/data';
|
||||
import { SelectableValue } from '@grafana/data';
|
||||
import { getBackendSrv, reportInteraction } from '@grafana/runtime';
|
||||
import { Button, ClipboardButton, Field, Icon, Input, LinkButton, Modal, Select, Spinner } from '@grafana/ui';
|
||||
import { appEvents } from 'app/core/core';
|
||||
import { Button, ClipboardButton, Field, Input, LinkButton, Modal, Select, Spinner } from '@grafana/ui';
|
||||
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
||||
import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
|
||||
|
||||
@@ -198,10 +197,6 @@ export class ShareSnapshot extends PureComponent<Props, State> {
|
||||
});
|
||||
};
|
||||
|
||||
onSnapshotUrlCopy = () => {
|
||||
appEvents.emit(AppEvents.alertSuccess, ['Content copied to clipboard']);
|
||||
};
|
||||
|
||||
renderStep1() {
|
||||
const { onDismiss } = this.props;
|
||||
const { snapshotName, selectedExpireOption, timeoutSeconds, isLoading, sharingButtonText, externalEnabled } =
|
||||
@@ -262,17 +257,18 @@ export class ShareSnapshot extends PureComponent<Props, State> {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="gf-form" style={{ marginTop: '40px' }}>
|
||||
<div className="gf-form-row">
|
||||
<a href={snapshotUrl} className="large share-modal-link" target="_blank" rel="noreferrer">
|
||||
<Icon name="external-link-alt" /> {snapshotUrl}
|
||||
</a>
|
||||
<br />
|
||||
<ClipboardButton variant="secondary" getText={this.getSnapshotUrl} onClipboardCopy={this.onSnapshotUrlCopy}>
|
||||
Copy Link
|
||||
</ClipboardButton>
|
||||
</div>
|
||||
</div>
|
||||
<Field label="Snapshot URL">
|
||||
<Input
|
||||
id="snapshot-url-input"
|
||||
value={snapshotUrl}
|
||||
readOnly
|
||||
addonAfter={
|
||||
<ClipboardButton icon="copy" variant="primary" getText={this.getSnapshotUrl}>
|
||||
Copy
|
||||
</ClipboardButton>
|
||||
}
|
||||
/>
|
||||
</Field>
|
||||
|
||||
<div className="pull-right" style={{ padding: '5px' }}>
|
||||
Did you make a mistake?{' '}
|
||||
|
||||
@@ -3,10 +3,6 @@ import AutoSizer from 'react-virtualized-auto-sizer';
|
||||
|
||||
import { ClipboardButton, CodeEditor, Modal } from '@grafana/ui';
|
||||
|
||||
import { notifyApp } from '../../../../core/actions';
|
||||
import { createSuccessNotification } from '../../../../core/copy/appNotification';
|
||||
import { dispatch } from '../../../../store/store';
|
||||
|
||||
export interface ViewJsonModalProps {
|
||||
json: string;
|
||||
onDismiss: () => void;
|
||||
@@ -14,16 +10,13 @@ export interface ViewJsonModalProps {
|
||||
|
||||
export function ViewJsonModal({ json, onDismiss }: ViewJsonModalProps): JSX.Element {
|
||||
const getClipboardText = useCallback(() => json, [json]);
|
||||
const onClipboardCopy = () => {
|
||||
dispatch(notifyApp(createSuccessNotification('Content copied to clipboard')));
|
||||
};
|
||||
return (
|
||||
<Modal title="JSON" onDismiss={onDismiss} onClickBackdrop={onDismiss} isOpen>
|
||||
<AutoSizer disableHeight>
|
||||
{({ width }) => <CodeEditor value={json} language="json" showMiniMap={false} height="500px" width={width} />}
|
||||
</AutoSizer>
|
||||
<Modal.ButtonRow>
|
||||
<ClipboardButton getText={getClipboardText} onClipboardCopy={onClipboardCopy}>
|
||||
<ClipboardButton icon="copy" getText={getClipboardText}>
|
||||
Copy to Clipboard
|
||||
</ClipboardButton>
|
||||
</Modal.ButtonRow>
|
||||
|
||||
Reference in New Issue
Block a user