refactor: Extract copy functionality to utils (#11928)

* Extract copy functionality to utils

* Refactor

* Revert bind

* WIP

* Absolute path

* Fix lint

* Remove unused resolve
This commit is contained in:
Victor Malai 2020-12-05 03:04:41 +02:00 committed by GitHub
parent fa68288d61
commit 64d6fb9f6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 98 additions and 129 deletions

View File

@ -21,6 +21,7 @@ import PropTypes from 'prop-types';
import { t } from '@superset-ui/core';
import { Tooltip } from 'src/common/components/Tooltip';
import withToasts from 'src/messageToasts/enhancers/withToasts';
import copyTextToClipboard from 'src/utils/copy';
const propTypes = {
copyNode: PropTypes.node,
@ -83,40 +84,20 @@ class CopyToClipboard extends React.Component {
}
copyToClipboard(textToCopy) {
const selection = document.getSelection();
selection.removeAllRanges();
document.activeElement.blur();
const range = document.createRange();
const span = document.createElement('span');
span.textContent = textToCopy;
span.style.all = 'unset';
span.style.position = 'fixed';
span.style.top = 0;
span.style.clip = 'rect(0, 0, 0, 0)';
span.style.whiteSpace = 'pre';
document.body.appendChild(span);
range.selectNode(span);
selection.addRange(range);
try {
if (!document.execCommand('copy')) {
throw new Error(t('Not successful'));
}
} catch (err) {
this.props.addDangerToast(
t('Sorry, your browser does not support copying. Use Ctrl / Cmd + C!'),
);
}
document.body.removeChild(span);
if (selection.removeRange) {
selection.removeRange(range);
} else {
selection.removeAllRanges();
}
this.setState({ hasCopied: true });
this.props.onCopyEnd();
copyTextToClipboard(textToCopy)
.then(() => {
this.setState({ hasCopied: true });
})
.catch(() => {
this.props.addDangerToast(
t(
'Sorry, your browser does not support copying. Use Ctrl / Cmd + C!',
),
);
})
.finally(() => {
this.props.onCopyEnd();
});
}
tooltipText() {

View File

@ -0,0 +1,56 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
const copyTextToClipboard = (text: string) =>
new Promise((resolve, reject) => {
const selection: Selection | null = document.getSelection();
if (selection) {
selection.removeAllRanges();
const range = document.createRange();
const span = document.createElement('span');
span.textContent = text;
span.style.position = 'fixed';
span.style.top = '0';
span.style.clip = 'rect(0, 0, 0, 0)';
span.style.whiteSpace = 'pre';
document.body.appendChild(span);
range.selectNode(span);
selection.addRange(range);
try {
if (!document.execCommand('copy')) {
reject();
}
} catch (err) {
reject();
}
document.body.removeChild(span);
if (selection.removeRange) {
selection.removeRange(range);
} else {
selection.removeAllRanges();
}
}
resolve();
});
export default copyTextToClipboard;

View File

@ -27,6 +27,7 @@ import github from 'react-syntax-highlighter/dist/cjs/styles/hljs/github';
import SyntaxHighlighter from 'react-syntax-highlighter/dist/cjs/light';
import { ToastProps } from 'src/messageToasts/enhancers/withToasts';
import Icon from 'src/components/Icon';
import copyTextToClipboard from 'src/utils/copy';
SyntaxHighlighter.registerLanguage('sql', sqlSyntax);
SyntaxHighlighter.registerLanguage('markdown', markdownSyntax);
@ -61,41 +62,17 @@ export default function SyntaxHighlighterCopy({
language: 'sql' | 'markdown' | 'html' | 'json';
}) {
function copyToClipboard(textToCopy: string) {
const selection: Selection | null = document.getSelection();
if (selection) {
selection.removeAllRanges();
const range = document.createRange();
const span = document.createElement('span');
span.textContent = textToCopy;
span.style.position = 'fixed';
span.style.top = '0';
span.style.clip = 'rect(0, 0, 0, 0)';
span.style.whiteSpace = 'pre';
document.body.appendChild(span);
range.selectNode(span);
selection.addRange(range);
try {
if (!document.execCommand('copy')) {
throw new Error(t('Not successful'));
}
} catch (err) {
copyTextToClipboard(textToCopy)
.then(() => {
if (addDangerToast) {
addDangerToast(t('Sorry, your browser does not support copying.'));
}
}
document.body.removeChild(span);
if (selection.removeRange) {
selection.removeRange(range);
} else {
selection.removeAllRanges();
}
if (addSuccessToast) {
addSuccessToast(t('SQL Copied!'));
}
}
})
.catch(() => {
if (addSuccessToast) {
addSuccessToast(t('SQL Copied!'));
}
});
}
return (
<SyntaxHighlighterWrapper>

View File

@ -40,6 +40,7 @@ import ActionsBar, { ActionProps } from 'src/components/ListView/ActionsBar';
import { IconName } from 'src/components/Icon';
import { commonMenuData } from 'src/views/CRUD/data/common';
import { SavedQueryObject } from 'src/views/CRUD/types';
import copyTextToClipboard from 'src/utils/copy';
import SavedQueryPreviewModal from './SavedQueryPreviewModal';
const PAGE_SIZE = 25;
@ -154,39 +155,15 @@ function SavedQueryList({
const copyQueryLink = useCallback(
(id: number) => {
const selection: Selection | null = document.getSelection();
if (selection) {
selection.removeAllRanges();
const range = document.createRange();
const span = document.createElement('span');
span.textContent = `${window.location.origin}/superset/sqllab?savedQueryId=${id}`;
span.style.position = 'fixed';
span.style.top = '0';
span.style.clip = 'rect(0, 0, 0, 0)';
span.style.whiteSpace = 'pre';
document.body.appendChild(span);
range.selectNode(span);
selection.addRange(range);
try {
if (!document.execCommand('copy')) {
throw new Error(t('Not successful'));
}
} catch (err) {
copyTextToClipboard(
`${window.location.origin}/superset/sqllab?savedQueryId=${id}`,
)
.then(() => {
addSuccessToast(t('Link Copied!'));
})
.catch(() => {
addDangerToast(t('Sorry, your browser does not support copying.'));
}
document.body.removeChild(span);
if (selection.removeRange) {
selection.removeRange(range);
} else {
selection.removeAllRanges();
}
addSuccessToast(t('Link Copied!'));
}
});
},
[addDangerToast, addSuccessToast],
);

View File

@ -24,6 +24,7 @@ import { createErrorHandler } from 'src/views/CRUD/utils';
import { FetchDataConfig } from 'src/components/ListView';
import { FilterValue } from 'src/components/ListView/types';
import Chart, { Slice } from 'src/types/Chart';
import copyTextToClipboard from 'src/utils/copy';
import { FavoriteStatus } from './types';
interface ListViewResourceState<D extends object = any> {
@ -435,36 +436,13 @@ export const copyQueryLink = (
addDangerToast: (arg0: string) => void,
addSuccessToast: (arg0: string) => void,
) => {
const selection: Selection | null = document.getSelection();
if (selection) {
selection.removeAllRanges();
const range = document.createRange();
const span = document.createElement('span');
span.textContent = `${window.location.origin}/superset/sqllab?savedQueryId=${id}`;
span.style.position = 'fixed';
span.style.top = '0';
span.style.clip = 'rect(0, 0, 0, 0)';
span.style.whiteSpace = 'pre';
document.body.appendChild(span);
range.selectNode(span);
selection.addRange(range);
try {
if (!document.execCommand('copy')) {
throw new Error(t('Not successful'));
}
} catch (err) {
copyTextToClipboard(
`${window.location.origin}/superset/sqllab?savedQueryId=${id}`,
)
.then(() => {
addSuccessToast(t('Link Copied!'));
})
.catch(() => {
addDangerToast(t('Sorry, your browser does not support copying.'));
}
document.body.removeChild(span);
if (selection.removeRange) {
selection.removeRange(range);
} else {
selection.removeAllRanges();
}
addSuccessToast(t('Link Copied!'));
}
});
};