Prechádzať zdrojové kódy

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
kay delaney 6 rokov pred
rodič
commit
d6fb48c0ff

+ 31 - 1
public/app/features/explore/QueryField.test.tsx

@@ -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');
+  });
 });

+ 20 - 5
public/app/features/explore/QueryField.tsx

@@ -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);