mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Improvements to the Query Results grid:
- Improve the UI - Allow copy/paste from sets of rows, columns or arbitrary blocks of cells Patch by Matt, Shruti, Joao and Sarah @ Pivotal Fixes #2476
This commit is contained in:
18
web/pgadmin/static/js/slickgrid/cell_selector.js
Normal file
18
web/pgadmin/static/js/slickgrid/cell_selector.js
Normal file
@@ -0,0 +1,18 @@
|
||||
define(["slickgrid"], function () {
|
||||
var Slick = window.Slick;
|
||||
|
||||
return function () {
|
||||
this.init = function (grid) {
|
||||
grid.onActiveCellChanged.subscribe(function (event, slickEvent) {
|
||||
grid.getSelectionModel().setSelectedRanges([
|
||||
new Slick.Range(
|
||||
slickEvent.row,
|
||||
slickEvent.cell,
|
||||
slickEvent.row,
|
||||
slickEvent.cell
|
||||
)
|
||||
]);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,21 @@
|
||||
define([
|
||||
'sources/selection/copy_data',
|
||||
'sources/selection/range_selection_helper'
|
||||
],
|
||||
function (copyData, RangeSelectionHelper) {
|
||||
return function handleQueryOutputKeyboardEvent(event, args) {
|
||||
var KEY_C = 67;
|
||||
var KEY_A = 65;
|
||||
var modifiedKey = event.keyCode;
|
||||
var isModifierDown = event.ctrlKey || event.metaKey;
|
||||
this.slickgrid = args.grid;
|
||||
|
||||
if (isModifierDown && modifiedKey == KEY_C) {
|
||||
copyData.apply(this);
|
||||
}
|
||||
|
||||
if (isModifierDown && modifiedKey == KEY_A) {
|
||||
RangeSelectionHelper.selectAll(this.slickgrid);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,73 @@
|
||||
define([
|
||||
'jquery',
|
||||
|
||||
'slickgrid',
|
||||
], function ($) {
|
||||
/***
|
||||
* Displays an overlay on top of a given cell range.
|
||||
*
|
||||
* TODO:
|
||||
* Currently, it blocks mouse events to DOM nodes behind it.
|
||||
* Use FF and WebKit-specific "pointer-events" CSS style, or some kind of event forwarding.
|
||||
* Could also construct the borders separately using 4 individual DIVs.
|
||||
*
|
||||
* @param {Grid} grid
|
||||
* @param {Object} options
|
||||
*/
|
||||
var PGCellRangeDecorator = function (grid, options) {
|
||||
var _elem;
|
||||
var _defaults = {
|
||||
selectionCssClass: 'slick-range-decorator',
|
||||
selectionCss: {
|
||||
"zIndex": "9999",
|
||||
"border": "2px dashed red"
|
||||
}
|
||||
};
|
||||
|
||||
options = $.extend(true, {}, _defaults, options);
|
||||
|
||||
|
||||
function show(range) {
|
||||
if (!_elem) {
|
||||
_elem = $("<div></div>", {css: options.selectionCss})
|
||||
.addClass(options.selectionCssClass)
|
||||
.css("position", "absolute")
|
||||
.appendTo(grid.getCanvasNode());
|
||||
}
|
||||
|
||||
var from = grid.getCellNodeBox(range.fromRow, range.fromCell);
|
||||
var to = grid.getCellNodeBox(range.toRow, range.toCell);
|
||||
|
||||
// TODO: This is the original Slickgrid code temporary fix to solve
|
||||
// pgAdmin alignment of the selection box on the bottom right corner
|
||||
// _elem.css({
|
||||
// top: from.top - 1,
|
||||
// left: from.left - 1,
|
||||
// height: to.bottom - from.top - 2,
|
||||
// width: to.right - from.left - 2
|
||||
// });
|
||||
|
||||
_elem.css({
|
||||
top: from.top - 1,
|
||||
left: from.left - 1,
|
||||
height: to.bottom - from.top + 2,
|
||||
width: to.right - from.left + 1
|
||||
});
|
||||
|
||||
return _elem;
|
||||
}
|
||||
|
||||
function hide() {
|
||||
if (_elem) {
|
||||
_elem.remove();
|
||||
_elem = null;
|
||||
}
|
||||
}
|
||||
|
||||
$.extend(this, {
|
||||
"show": show,
|
||||
"hide": hide
|
||||
});
|
||||
};
|
||||
return PGCellRangeDecorator;
|
||||
});
|
||||
119
web/pgadmin/static/js/slickgrid/pgslick.cellrangeselector.js
Normal file
119
web/pgadmin/static/js/slickgrid/pgslick.cellrangeselector.js
Normal file
@@ -0,0 +1,119 @@
|
||||
define([
|
||||
'jquery',
|
||||
'sources/slickgrid/pgslick.cellrangedecorator',
|
||||
|
||||
'slickgrid',
|
||||
], function ($, PGCellRangeDecorator) {
|
||||
|
||||
var PGCellRangeSelector = function (options) {
|
||||
var _grid;
|
||||
var _canvas;
|
||||
var _currentlySelectedRange;
|
||||
var _dragging;
|
||||
var _decorator;
|
||||
var _self = this;
|
||||
var _handler = new Slick.EventHandler();
|
||||
var _defaults = {
|
||||
selectionCss: {
|
||||
"border": "2px dashed blue"
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function init(grid) {
|
||||
options = $.extend(true, {}, _defaults, options);
|
||||
_decorator = new PGCellRangeDecorator(grid, options);
|
||||
_grid = grid;
|
||||
_canvas = _grid.getCanvasNode();
|
||||
_handler
|
||||
.subscribe(_grid.onDragInit, handleDragInit)
|
||||
.subscribe(_grid.onDragStart, handleDragStart)
|
||||
.subscribe(_grid.onDrag, handleDrag)
|
||||
.subscribe(_grid.onDragEnd, handleDragEnd);
|
||||
}
|
||||
|
||||
function destroy() {
|
||||
_handler.unsubscribeAll();
|
||||
}
|
||||
|
||||
function handleDragInit(e, dd) {
|
||||
// prevent the grid from cancelling drag'n'drop by default
|
||||
e.stopImmediatePropagation();
|
||||
}
|
||||
|
||||
function handleDragStart(e, dd) {
|
||||
var cell = _grid.getCellFromEvent(e);
|
||||
if (_self.onBeforeCellRangeSelected.notify(cell) !== false) {
|
||||
if (_grid.canCellBeSelected(cell.row, cell.cell)) {
|
||||
_dragging = true;
|
||||
e.stopImmediatePropagation();
|
||||
}
|
||||
}
|
||||
if (!_dragging) {
|
||||
return;
|
||||
}
|
||||
|
||||
_grid.focus();
|
||||
|
||||
var start = _grid.getCellFromPoint(
|
||||
dd.startX - $(_canvas).offset().left,
|
||||
dd.startY - $(_canvas).offset().top);
|
||||
|
||||
dd.range = {start: start, end: {}};
|
||||
_currentlySelectedRange = dd.range;
|
||||
return _decorator.show(new Slick.Range(start.row, start.cell));
|
||||
}
|
||||
|
||||
function handleDrag(e, dd) {
|
||||
if (!_dragging) {
|
||||
return;
|
||||
}
|
||||
e.stopImmediatePropagation();
|
||||
|
||||
var end = _grid.getCellFromPoint(
|
||||
e.pageX - $(_canvas).offset().left,
|
||||
e.pageY - $(_canvas).offset().top);
|
||||
|
||||
if (!_grid.canCellBeSelected(end.row, end.cell)) {
|
||||
return;
|
||||
}
|
||||
|
||||
dd.range.end = end;
|
||||
_currentlySelectedRange = dd.range;
|
||||
_decorator.show(new Slick.Range(dd.range.start.row, dd.range.start.cell, end.row, end.cell));
|
||||
}
|
||||
|
||||
function handleDragEnd(e, dd) {
|
||||
if (!_dragging) {
|
||||
return;
|
||||
}
|
||||
|
||||
_dragging = false;
|
||||
e.stopImmediatePropagation();
|
||||
|
||||
_decorator.hide();
|
||||
_self.onCellRangeSelected.notify({
|
||||
range: new Slick.Range(
|
||||
dd.range.start.row,
|
||||
dd.range.start.cell,
|
||||
dd.range.end.row,
|
||||
dd.range.end.cell
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
function getCurrentRange() {
|
||||
return _currentlySelectedRange;
|
||||
}
|
||||
|
||||
$.extend(this, {
|
||||
"init": init,
|
||||
"destroy": destroy,
|
||||
"getCurrentRange": getCurrentRange,
|
||||
|
||||
"onBeforeCellRangeSelected": new Slick.Event(),
|
||||
"onCellRangeSelected": new Slick.Event()
|
||||
});
|
||||
};
|
||||
return PGCellRangeSelector;
|
||||
});
|
||||
Reference in New Issue
Block a user