Editor: Fixes issue where only entire lines were being copied (#18806)

* Editor: Fixes issue where only entire lines were being copied
Closes #18768

* Simplifies onCopy handler and factors out logic for easier testing
Also adds tests to verify behaviour
This commit is contained in:
kay delaney 2019-08-30 16:09:00 +01:00 committed by David
parent a147aedb10
commit d6fb48c0ff
2 changed files with 51 additions and 6 deletions

View File

@ -1,6 +1,5 @@
import React from 'react';
import { shallow } from 'enzyme';
import { QueryField } from './QueryField';
describe('<QueryField />', () => {
@ -28,4 +27,35 @@ describe('<QueryField />', () => {
expect(handleEnterAndTabKeySpy).toBeCalled();
expect(instance.executeOnChangeAndRunQueries).toBeCalled();
});
it('should copy selected text', () => {
const wrapper = shallow(<QueryField initialQuery="" />);
const instance = wrapper.instance() as QueryField;
const textBlocks = ['ignore this text. copy this text'];
const copiedText = instance.getCopiedText(textBlocks, 18, 32);
expect(copiedText).toBe('copy this text');
});
it('should copy selected text across 2 lines', () => {
const wrapper = shallow(<QueryField initialQuery="" />);
const instance = wrapper.instance() as QueryField;
const textBlocks = ['ignore this text. start copying here', 'lorem ipsum. stop copying here. lorem ipsum'];
const copiedText = instance.getCopiedText(textBlocks, 18, 30);
expect(copiedText).toBe('start copying here\nlorem ipsum. stop copying here');
});
it('should copy selected text across > 2 lines', () => {
const wrapper = shallow(<QueryField initialQuery="" />);
const instance = wrapper.instance() as QueryField;
const textBlocks = [
'ignore this text. start copying here',
'lorem ipsum doler sit amet',
'lorem ipsum. stop copying here. lorem ipsum',
];
const copiedText = instance.getCopiedText(textBlocks, 18, 30);
expect(copiedText).toBe('start copying here\nlorem ipsum doler sit amet\nlorem ipsum. stop copying here');
});
});

View File

@ -620,15 +620,30 @@ export class QueryField extends React.PureComponent<QueryFieldProps, QueryFieldS
);
};
handleCopy = (event: ClipboardEvent, change: Editor) => {
getCopiedText(textBlocks: string[], startOffset: number, endOffset: number) {
if (!textBlocks.length) {
return undefined;
}
const excludingLastLineLength = textBlocks.slice(0, -1).join('').length + textBlocks.length - 1;
return textBlocks.join('\n').slice(startOffset, excludingLastLineLength + endOffset);
}
handleCopy = (event: ClipboardEvent, change: Change) => {
event.preventDefault();
const selectedBlocks = change.value.document.getBlocksAtRange(change.value.selection);
event.clipboardData.setData('Text', selectedBlocks.map((block: Block) => block.text).join('\n'));
const { document, selection, startOffset, endOffset } = change.value;
const selectedBlocks = document.getBlocksAtRangeAsArray(selection).map((block: Block) => block.text);
const copiedText = this.getCopiedText(selectedBlocks, startOffset, endOffset);
if (copiedText) {
event.clipboardData.setData('Text', copiedText);
}
return true;
};
handlePaste = (event: ClipboardEvent, change: Editor) => {
handlePaste = (event: ClipboardEvent, change: Change) => {
event.preventDefault();
const pastedValue = event.clipboardData.getData('Text');
const lines = pastedValue.split('\n');
@ -643,7 +658,7 @@ export class QueryField extends React.PureComponent<QueryFieldProps, QueryFieldS
return true;
};
handleCut = (event: ClipboardEvent, change: Editor) => {
handleCut = (event: ClipboardEvent, change: Change) => {
this.handleCopy(event, change);
change.deleteAtRange(change.value.selection);