mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-28 18:46:02 +00:00
data grid - copy to clipboard
This commit is contained in:
@@ -97,6 +97,15 @@
|
|||||||
onClick: () => get(currentDataGrid).reconnect(),
|
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) {
|
function getRowCountInfo(selectedCells, grider, realColumnUniqueNames, selectedRowData, allRowCount) {
|
||||||
if (selectedCells.length > 1 && selectedCells.every(x => _.isNumber(x[0]) && _.isNumber(x[1]))) {
|
if (selectedCells.length > 1 && selectedCells.every(x => _.isNumber(x[0]) && _.isNumber(x[1]))) {
|
||||||
let sum = _.sumBy(selectedCells, cell => {
|
let sum = _.sumBy(selectedCells, cell => {
|
||||||
@@ -153,6 +162,7 @@
|
|||||||
import { nullStore } from '../stores';
|
import { nullStore } from '../stores';
|
||||||
import memberStore from '../utility/memberStore';
|
import memberStore from '../utility/memberStore';
|
||||||
import axios from '../utility/axios';
|
import axios from '../utility/axios';
|
||||||
|
import { copyTextToClipboard } from '../utility/clipboard';
|
||||||
|
|
||||||
export let loadNextData = undefined;
|
export let loadNextData = undefined;
|
||||||
export let grider = undefined;
|
export let grider = undefined;
|
||||||
@@ -259,6 +269,23 @@
|
|||||||
display.reload();
|
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 =
|
$: autofillMarkerCell =
|
||||||
selectedCells && selectedCells.length > 0 && _.uniq(selectedCells.map(x => x[0])).length == 1
|
selectedCells && selectedCells.length > 0 && _.uniq(selectedCells.map(x => x[0])).length == 1
|
||||||
? [_.max(selectedCells.map(x => x[0])), _.max(selectedCells.map(x => x[1]))]
|
? [_.max(selectedCells.map(x => x[0])), _.max(selectedCells.map(x => x[1]))]
|
||||||
@@ -662,6 +689,26 @@
|
|||||||
return [row, col];
|
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) => {
|
const [inplaceEditorState, dispatchInsplaceEditor] = createReducer((state, action) => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case 'show':
|
case 'show':
|
||||||
@@ -692,6 +739,7 @@
|
|||||||
function createMenu() {
|
function createMenu() {
|
||||||
return [
|
return [
|
||||||
{ command: 'dataGrid.refresh' },
|
{ command: 'dataGrid.refresh' },
|
||||||
|
{ command: 'dataGrid.copyToClipboard' },
|
||||||
{ divider: true },
|
{ divider: true },
|
||||||
{ command: 'dataGrid.save' },
|
{ command: 'dataGrid.save' },
|
||||||
{ command: 'dataGrid.revertRowChanges' },
|
{ command: 'dataGrid.revertRowChanges' },
|
||||||
|
|||||||
56
packages/web/src/utility/clipboard.js
Normal file
56
packages/web/src/utility/clipboard.js
Normal 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);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user