aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main
diff options
context:
space:
mode:
authorGrégoire Aubert <gregoire.aubert@sonarsource.com>2018-01-10 17:28:51 +0100
committerGrégoire Aubert <gregoire.aubert@sonarsource.com>2018-01-25 15:16:50 +0100
commitb3a593c103415e903db6974cc293c3dce462e20f (patch)
treef14b4cd8f1b70c34120135c3112a39e3a38529f3 /server/sonar-web/src/main
parentaddc88f96fb4b873d66ea32df433e98be741d7c7 (diff)
downloadsonarqube-b3a593c103415e903db6974cc293c3dce462e20f.tar.gz
sonarqube-b3a593c103415e903db6974cc293c3dce462e20f.zip
Create a Clipboard button
Diffstat (limited to 'server/sonar-web/src/main')
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/Command.js57
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/__snapshots__/Command-test.js.snap15
-rw-r--r--server/sonar-web/src/main/js/apps/users/components/TokensFormNewToken.tsx87
-rw-r--r--server/sonar-web/src/main/js/components/controls/ClipboardButton.tsx98
-rw-r--r--server/sonar-web/src/main/js/components/controls/__tests__/ClipboardButton-test.tsx35
-rw-r--r--server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/ClipboardButton-test.tsx.snap26
6 files changed, 184 insertions, 134 deletions
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/Command.js b/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/Command.js
index efa4ee1c2e6..23d728a407e 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/Command.js
+++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/Command.js
@@ -19,9 +19,8 @@
*/
// @flow
import React from 'react';
-import Clipboard from 'clipboard';
import classNames from 'classnames';
-import Tooltip from '../../../../components/controls/Tooltip';
+import ClipboardButton from '../../../../components/controls/ClipboardButton';
import { translate } from '../../../../helpers/l10n';
/*::
@@ -31,73 +30,21 @@ type Props = {
};
*/
-/*::
-type State = {
- tooltipShown: boolean
-};
-*/
-
const s = ' \\' + '\n ';
export default class Command extends React.PureComponent {
- /*:: clipboard: Object; */
- /*:: copyButton: HTMLButtonElement; */
- /*:: mounted: boolean; */
/*:: props: Props; */
- state /*: State */ = { tooltipShown: false };
-
- componentDidMount() {
- this.mounted = true;
- this.clipboard = new Clipboard(this.copyButton);
- this.clipboard.on('success', this.showTooltip);
- }
-
- componentDidUpdate() {
- this.clipboard.destroy();
- this.clipboard = new Clipboard(this.copyButton);
- this.clipboard.on('success', this.showTooltip);
- }
-
- componentWillUnmount() {
- this.mounted = false;
- this.clipboard.destroy();
- }
-
- showTooltip = () => {
- if (this.mounted) {
- this.setState({ tooltipShown: true });
- setTimeout(this.hideTooltip, 1000);
- }
- };
-
- hideTooltip = () => {
- if (this.mounted) {
- this.setState({ tooltipShown: false });
- }
- };
render() {
const { command, isWindows } = this.props;
const commandArray = Array.isArray(command) ? command.filter(line => line != null) : [command];
const finalCommand = isWindows ? commandArray.join(' ') : commandArray.join(s);
- const button = (
- <button data-clipboard-text={finalCommand} ref={node => (this.copyButton = node)}>
- {translate('copy')}
- </button>
- );
-
return (
<div
className={classNames('onboarding-command', { 'onboarding-command-windows': isWindows })}>
<pre>{finalCommand}</pre>
- {this.state.tooltipShown ? (
- <Tooltip defaultVisible={true} placement="top" overlay="Copied!" trigger="manual">
- {button}
- </Tooltip>
- ) : (
- button
- )}
+ <ClipboardButton copyValue={finalCommand} tooltipPlacement="top" />
</div>
);
}
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/__snapshots__/Command-test.js.snap b/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/__snapshots__/Command-test.js.snap
index 63e31484c8d..2bd0aafd5b8 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/__snapshots__/Command-test.js.snap
+++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/commands/__tests__/__snapshots__/Command-test.js.snap
@@ -12,12 +12,19 @@ bar"
foo
bar
</pre>
- <button
- data-clipboard-text="foo
+ <ClipboardButton
+ copyValue="foo
bar"
+ tooltipPlacement="top"
>
- copy
- </button>
+ <button
+ className="js-copy-to-clipboard no-select"
+ data-clipboard-text="foo
+bar"
+ >
+ copy
+ </button>
+ </ClipboardButton>
</div>
</Command>
`;
diff --git a/server/sonar-web/src/main/js/apps/users/components/TokensFormNewToken.tsx b/server/sonar-web/src/main/js/apps/users/components/TokensFormNewToken.tsx
index e3bb9df6b32..f7b744e9c1f 100644
--- a/server/sonar-web/src/main/js/apps/users/components/TokensFormNewToken.tsx
+++ b/server/sonar-web/src/main/js/apps/users/components/TokensFormNewToken.tsx
@@ -18,84 +18,21 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import * as Clipboard from 'clipboard';
-import Tooltip from '../../../components/controls/Tooltip';
-import { translate, translateWithParameters } from '../../../helpers/l10n';
+import ClipboardButton from '../../../components/controls/ClipboardButton';
+import { translateWithParameters } from '../../../helpers/l10n';
interface Props {
token: { name: string; token: string };
}
-interface State {
- tooltipShown: boolean;
-}
-
-export default class TokensFormNewToken extends React.PureComponent<Props, State> {
- clipboard: Clipboard;
- copyButton: HTMLButtonElement | null;
- mounted: boolean;
- state: State = { tooltipShown: false };
-
- componentDidMount() {
- this.mounted = true;
- if (this.copyButton) {
- this.clipboard = new Clipboard(this.copyButton);
- this.clipboard.on('success', this.showTooltip);
- }
- }
-
- componentDidUpdate() {
- this.clipboard.destroy();
- if (this.copyButton) {
- this.clipboard = new Clipboard(this.copyButton);
- this.clipboard.on('success', this.showTooltip);
- }
- }
-
- componentWillUnmount() {
- this.mounted = false;
- this.clipboard.destroy();
- }
-
- showTooltip = () => {
- if (this.mounted) {
- this.setState({ tooltipShown: true });
- setTimeout(() => {
- if (this.mounted) {
- this.setState({ tooltipShown: false });
- }
- }, 1000);
- }
- };
-
- render() {
- const { name, token } = this.props.token;
- const button = (
- <button
- className="js-copy-to-clipboard no-select"
- data-clipboard-text={token}
- ref={node => (this.copyButton = node)}>
- {translate('copy')}
- </button>
- );
- return (
- <div className="panel panel-white big-spacer-top">
- <p className="alert alert-warning">
- {translateWithParameters('users.tokens.new_token_created', name)}
- </p>
- {this.state.tooltipShown ? (
- <Tooltip
- defaultVisible={true}
- placement="bottom"
- overlay={translate('users.tokens.copied')}
- trigger="manual">
- {button}
- </Tooltip>
- ) : (
- button
- )}
- <code className="big-spacer-left text-success">{token}</code>
- </div>
- );
- }
+export default function TokensFormNewToken({ token }: Props) {
+ return (
+ <div className="panel panel-white big-spacer-top">
+ <p className="alert alert-warning">
+ {translateWithParameters('users.tokens.new_token_created', token.name)}
+ </p>
+ <ClipboardButton copyValue={token.token} />
+ <code className="big-spacer-left text-success">{token.token}</code>
+ </div>
+ );
}
diff --git a/server/sonar-web/src/main/js/components/controls/ClipboardButton.tsx b/server/sonar-web/src/main/js/components/controls/ClipboardButton.tsx
new file mode 100644
index 00000000000..dc9b146d13e
--- /dev/null
+++ b/server/sonar-web/src/main/js/components/controls/ClipboardButton.tsx
@@ -0,0 +1,98 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import * as React from 'react';
+import * as classNames from 'classnames';
+import * as Clipboard from 'clipboard';
+import Tooltip from './Tooltip';
+import { translate } from '../../helpers/l10n';
+
+interface Props {
+ className?: string;
+ copyValue: string;
+ tooltipPlacement?: string;
+}
+
+interface State {
+ tooltipShown: boolean;
+}
+
+export default class ClipboardButton extends React.PureComponent<Props, State> {
+ clipboard: Clipboard;
+ copyButton: HTMLButtonElement | null;
+ mounted: boolean;
+ state: State = { tooltipShown: false };
+
+ componentDidMount() {
+ this.mounted = true;
+ if (this.copyButton) {
+ this.clipboard = new Clipboard(this.copyButton);
+ this.clipboard.on('success', this.showTooltip);
+ }
+ }
+
+ componentDidUpdate() {
+ if (this.clipboard) {
+ this.clipboard.destroy();
+ }
+ if (this.copyButton) {
+ this.clipboard = new Clipboard(this.copyButton);
+ this.clipboard.on('success', this.showTooltip);
+ }
+ }
+
+ componentWillUnmount() {
+ this.mounted = false;
+ this.clipboard.destroy();
+ }
+
+ showTooltip = () => {
+ if (this.mounted) {
+ this.setState({ tooltipShown: true });
+ setTimeout(() => {
+ if (this.mounted) {
+ this.setState({ tooltipShown: false });
+ }
+ }, 1000);
+ }
+ };
+
+ render() {
+ const button = (
+ <button
+ className={classNames('js-copy-to-clipboard no-select', this.props.className)}
+ data-clipboard-text={this.props.copyValue}
+ ref={node => (this.copyButton = node)}>
+ {translate('copy')}
+ </button>
+ );
+ if (this.state.tooltipShown) {
+ return (
+ <Tooltip
+ defaultVisible={true}
+ placement={this.props.tooltipPlacement || 'bottom'}
+ overlay={translate('copied_action')}
+ trigger="manual">
+ {button}
+ </Tooltip>
+ );
+ }
+ return button;
+ }
+}
diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/ClipboardButton-test.tsx b/server/sonar-web/src/main/js/components/controls/__tests__/ClipboardButton-test.tsx
new file mode 100644
index 00000000000..a33520ea19e
--- /dev/null
+++ b/server/sonar-web/src/main/js/components/controls/__tests__/ClipboardButton-test.tsx
@@ -0,0 +1,35 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import * as React from 'react';
+import { shallow } from 'enzyme';
+import ClipboardButton from '../ClipboardButton';
+
+jest.useFakeTimers();
+
+it('should display correctly', () => {
+ const wrapper = shallow(<ClipboardButton copyValue="foo" />);
+ expect(wrapper).toMatchSnapshot();
+ (wrapper.instance() as ClipboardButton).showTooltip();
+ wrapper.update();
+ expect(wrapper).toMatchSnapshot();
+ jest.runAllTimers();
+ wrapper.update();
+ expect(wrapper.find('Tooltip')).toHaveLength(0);
+});
diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/ClipboardButton-test.tsx.snap b/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/ClipboardButton-test.tsx.snap
new file mode 100644
index 00000000000..61870f73365
--- /dev/null
+++ b/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/ClipboardButton-test.tsx.snap
@@ -0,0 +1,26 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should display correctly 1`] = `
+<button
+ className="js-copy-to-clipboard no-select"
+ data-clipboard-text="foo"
+>
+ copy
+</button>
+`;
+
+exports[`should display correctly 2`] = `
+<Tooltip
+ defaultVisible={true}
+ overlay="copied_action"
+ placement="bottom"
+ trigger="manual"
+>
+ <button
+ className="js-copy-to-clipboard no-select"
+ data-clipboard-text="foo"
+ >
+ copy
+ </button>
+</Tooltip>
+`;