data grid - copy to clipboard

This commit is contained in:
Jan Prochazka 2021-03-06 20:46:07 +01:00
parent e49c0169da
commit ec2acebdc9
2 changed files with 104 additions and 0 deletions

View File

@ -97,6 +97,15 @@
onClick: () => get(currentDataGrid).reconnect(),
});
registerCommand({
id: 'dataGrid.copyToClipboard',
category: 'Data grid',
name: 'Copy to clipboard',
keyText: 'Ctrl+C',
enabledStore: derived(currentDataGrid, grid => grid != null),
onClick: () => get(currentDataGrid).copyToClipboard(),
});
function getRowCountInfo(selectedCells, grider, realColumnUniqueNames, selectedRowData, allRowCount) {
if (selectedCells.length > 1 && selectedCells.every(x => _.isNumber(x[0]) && _.isNumber(x[1]))) {
let sum = _.sumBy(selectedCells, cell => {
@ -153,6 +162,7 @@
import { nullStore } from '../stores';
import memberStore from '../utility/memberStore';
import axios from '../utility/axios';
import { copyTextToClipboard } from '../utility/clipboard';
export let loadNextData = undefined;
export let grider = undefined;
@ -259,6 +269,23 @@
display.reload();
}
export function copyToClipboard() {
const cells = cellsToRegularCells(selectedCells);
const rowIndexes = _.sortBy(_.uniq(cells.map(x => x[0])));
const lines = rowIndexes.map(rowIndex => {
let colIndexes = _.sortBy(cells.filter(x => x[0] == rowIndex).map(x => x[1]));
const rowData = grider.getRowData(rowIndex);
if (!rowData) return '';
const line = colIndexes
.map(col => realColumnUniqueNames[col])
.map(col => (rowData[col] == null ? '(NULL)' : rowData[col]))
.join('\t');
return line;
});
const text = lines.join('\r\n');
copyTextToClipboard(text);
}
$: autofillMarkerCell =
selectedCells && selectedCells.length > 0 && _.uniq(selectedCells.map(x => x[0])).length == 1
? [_.max(selectedCells.map(x => x[0])), _.max(selectedCells.map(x => x[1]))]
@ -662,6 +689,26 @@
return [row, col];
}
function cellsToRegularCells(cells) {
cells = _.flatten(
cells.map(cell => {
if (cell[1] == 'header') {
return _.range(0, columnSizes.count).map(col => [cell[0], col]);
}
return [cell];
})
);
cells = _.flatten(
cells.map(cell => {
if (cell[0] == 'header') {
return _.range(0, grider.rowCount).map(row => [row, cell[1]]);
}
return [cell];
})
);
return cells.filter(isRegularCell);
}
const [inplaceEditorState, dispatchInsplaceEditor] = createReducer((state, action) => {
switch (action.type) {
case 'show':
@ -692,6 +739,7 @@
function createMenu() {
return [
{ command: 'dataGrid.refresh' },
{ command: 'dataGrid.copyToClipboard' },
{ divider: true },
{ command: 'dataGrid.save' },
{ command: 'dataGrid.revertRowChanges' },

View File

@ -0,0 +1,56 @@
export function copyTextToClipboard(text) {
const textArea = document.createElement('textarea');
//
// *** This styling is an extra step which is likely not required. ***
//
// Why is it here? To ensure:
// 1. the element is able to have focus and selection.
// 2. if element was to flash render it has minimal visual impact.
// 3. less flakyness with selection and copying which **might** occur if
// the textarea element is not visible.
//
// The likelihood is the element won't even render, not even a flash,
// so some of these are just precautions. However in IE the element
// is visible whilst the popup box asking the user for permission for
// the web page to copy to the clipboard.
//
// Place in top-left corner of screen regardless of scroll position.
textArea.style.position = 'fixed';
textArea.style.top = '0';
textArea.style.left = '0';
// Ensure it has a small width and height. Setting to 1px / 1em
// doesn't work as this gives a negative w/h on some browsers.
textArea.style.width = '2em';
textArea.style.height = '2em';
// We don't need padding, reducing the size if it does flash render.
textArea.style.padding = '0';
// Clean up any borders.
textArea.style.border = 'none';
textArea.style.outline = 'none';
textArea.style.boxShadow = 'none';
// Avoid flash of white box if rendered for any reason.
textArea.style.background = 'transparent';
textArea.value = text;
document.body.appendChild(textArea);
textArea.select();
try {
let successful = document.execCommand('copy');
if (!successful) {
console.log('Failed copy to clipboard');
}
} catch (err) {
console.log('Failed copy to clipboard: ' + err);
}
document.body.removeChild(textArea);
}