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:
@@ -2,26 +2,37 @@ define(
|
||||
["jquery",
|
||||
"underscore",
|
||||
"slickgrid/slick.grid",
|
||||
"sources/selection/active_cell_capture",
|
||||
"sources/selection/row_selector",
|
||||
"slickgrid/slick.rowselectionmodel",
|
||||
'sources/selection/xcell_selection_model',
|
||||
|
||||
"slickgrid",
|
||||
'sources/slickgrid/pgslick.cellrangedecorator',
|
||||
'sources/slickgrid/pgslick.cellrangeselector',
|
||||
],
|
||||
function ($, _, SlickGrid, RowSelector, RowSelectionModel, Slick) {
|
||||
function ($, _, SlickGrid, ActiveCellCapture, RowSelector, XCellSelectionModel, Slick) {
|
||||
var KEY_RIGHT = 39;
|
||||
var KEY_LEFT = 37;
|
||||
var KEY_UP = 38;
|
||||
var KEY_DOWN = 40;
|
||||
describe("RowSelector", function () {
|
||||
var container, data, columnDefinitions, grid, rowSelectionModel;
|
||||
var container, data, columnDefinitions, grid, cellSelectionModel;
|
||||
|
||||
beforeEach(function () {
|
||||
container = $("<div></div>");
|
||||
container.height(9999);
|
||||
container.width(9999);
|
||||
|
||||
columnDefinitions = [{
|
||||
id: '1',
|
||||
name: 'some-column-name',
|
||||
selectable: true
|
||||
selectable: true,
|
||||
pos: 0
|
||||
}, {
|
||||
id: '2',
|
||||
name: 'second column',
|
||||
selectable: true
|
||||
selectable: true,
|
||||
pos: 1
|
||||
}];
|
||||
|
||||
var rowSelector = new RowSelector();
|
||||
@@ -29,11 +40,13 @@ define(
|
||||
for (var i = 0; i < 10; i++) {
|
||||
data.push(['some-value-' + i, 'second value ' + i]);
|
||||
}
|
||||
columnDefinitions = rowSelector.getColumnDefinitionsWithCheckboxes(columnDefinitions);
|
||||
columnDefinitions = rowSelector.getColumnDefinitions(columnDefinitions);
|
||||
grid = new SlickGrid(container, data, columnDefinitions);
|
||||
|
||||
rowSelectionModel = new RowSelectionModel();
|
||||
grid.setSelectionModel(rowSelectionModel);
|
||||
grid.registerPlugin(new ActiveCellCapture());
|
||||
cellSelectionModel = new XCellSelectionModel();
|
||||
grid.setSelectionModel(cellSelectionModel);
|
||||
|
||||
grid.registerPlugin(rowSelector);
|
||||
grid.invalidate();
|
||||
|
||||
@@ -53,9 +66,9 @@ define(
|
||||
expect(leftmostColumn.selectable).toBe(false);
|
||||
});
|
||||
|
||||
it("renders a checkbox the leftmost column", function () {
|
||||
expect(container.find('.sr').length).toBe(11);
|
||||
expect(container.find('.sr .sc:first-child input[type="checkbox"]').length).toBe(10);
|
||||
it("renders a span on the leftmost column", function () {
|
||||
expect(container.find('.slick-row').length).toBe(10);
|
||||
expect(container.find('.slick-row .slick-cell:first-child span[data-cell-type="row-header-selector"]').length).toBe(10);
|
||||
});
|
||||
|
||||
it("preserves the other attributes of column definitions", function () {
|
||||
@@ -64,44 +77,168 @@ define(
|
||||
});
|
||||
|
||||
describe("selecting rows", function () {
|
||||
describe("when the user clicks a row header checkbox", function () {
|
||||
describe("when the user clicks a row header span", function () {
|
||||
it("selects the row", function () {
|
||||
container.find('.sr .sc:first-child input[type="checkbox"]')[0].click();
|
||||
container.find('.slick-row .slick-cell:first-child span[data-cell-type="row-header-selector"]')[0].click();
|
||||
|
||||
var selectedRanges = rowSelectionModel.getSelectedRanges();
|
||||
var selectedRanges = cellSelectionModel.getSelectedRanges();
|
||||
expectOnlyTheFirstRowToBeSelected(selectedRanges);
|
||||
});
|
||||
|
||||
it("checks the checkbox", function () {
|
||||
container.find('.sr .sc:first-child input[type="checkbox"]')[5].click();
|
||||
it("add selected class to parent of the span", function () {
|
||||
container.find('.slick-row .slick-cell:first-child span[data-cell-type="row-header-selector"]')[5].click();
|
||||
|
||||
expect($(container.find('.sr .sc:first-child input[type="checkbox"]')[5])
|
||||
.is(':checked')).toBeTruthy();
|
||||
expect($(container.find('.slick-row .slick-cell:first-child ')[5])
|
||||
.hasClass('selected')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe("when the user clicks a row header", function () {
|
||||
it("selects the row", function () {
|
||||
container.find('.sr .sc:first-child')[0].click();
|
||||
beforeEach(function () {
|
||||
container.find('.slick-row .slick-cell:first-child')[1].click();
|
||||
|
||||
var selectedRanges = rowSelectionModel.getSelectedRanges();
|
||||
expectOnlyTheFirstRowToBeSelected(selectedRanges);
|
||||
});
|
||||
it("selects the row", function () {
|
||||
|
||||
var selectedRanges = cellSelectionModel.getSelectedRanges();
|
||||
var row = selectedRanges[0];
|
||||
|
||||
expect(selectedRanges.length).toEqual(1);
|
||||
expect(row.fromCell).toBe(1);
|
||||
expect(row.toCell).toBe(2);
|
||||
expect(row.fromRow).toBe(1);
|
||||
expect(row.toRow).toBe(1);
|
||||
});
|
||||
|
||||
it("checks the checkbox", function () {
|
||||
container.find('.sr .sc:first-child')[7].click();
|
||||
it("add selected class to parent of the span", function () {
|
||||
|
||||
expect($(container.find('.sr .sc:first-child input[type="checkbox"]')[7])
|
||||
.is(':checked')).toBeTruthy();
|
||||
expect($(container.find('.slick-row .slick-cell:first-child ')[1])
|
||||
.hasClass('selected')).toBeTruthy();
|
||||
});
|
||||
|
||||
describe("when the user clicks again the same row header", function () {
|
||||
it("add selected class to parent of the span", function () {
|
||||
container.find('.slick-row .slick-cell:first-child span[data-cell-type="row-header-selector"]')[1].click();
|
||||
|
||||
expect($(container.find('.slick-row .slick-cell:first-child ')[1])
|
||||
.hasClass('selected')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe("and presses shift + down-arrow", function () {
|
||||
beforeEach(function () {
|
||||
pressShiftArrow(KEY_DOWN);
|
||||
});
|
||||
|
||||
it("keeps the last row selected", function () {
|
||||
expect(cellSelectionModel.getSelectedRanges().length).toBe(1);
|
||||
});
|
||||
|
||||
it("grows the selection down", function () {
|
||||
var selectedRanges = cellSelectionModel.getSelectedRanges();
|
||||
|
||||
var row = selectedRanges[0];
|
||||
|
||||
expect(selectedRanges.length).toEqual(1);
|
||||
expect(row.fromCell).toBe(1);
|
||||
expect(row.toCell).toBe(2);
|
||||
expect(row.fromRow).toBe(1);
|
||||
expect(row.toRow).toBe(2);
|
||||
});
|
||||
|
||||
it("keeps selected class on rows 1 and 2", function () {
|
||||
expect($(container.find('.slick-row .slick-cell:first-child ')[0])
|
||||
.hasClass('selected')).toBeFalsy();
|
||||
expect($(container.find('.slick-row .slick-cell:first-child ')[1])
|
||||
.hasClass('selected')).toBeTruthy();
|
||||
expect($(container.find('.slick-row .slick-cell:first-child ')[2])
|
||||
.hasClass('selected')).toBeTruthy();
|
||||
expect($(container.find('.slick-row .slick-cell:first-child ')[3])
|
||||
.hasClass('selected')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the user clicks a cell on the current range', function () {
|
||||
beforeEach(function () {
|
||||
container.find('.slick-cell.l1.r1')[5].click();
|
||||
});
|
||||
|
||||
it('row gets deselected', function () {
|
||||
|
||||
var selectedRanges = cellSelectionModel.getSelectedRanges();
|
||||
|
||||
expect(selectedRanges.length).toBe(1);
|
||||
|
||||
var newSelection = selectedRanges[0];
|
||||
|
||||
expect(newSelection.fromCell).toBe(1);
|
||||
expect(newSelection.fromRow).toBe(5);
|
||||
expect(newSelection.toCell).toBe(1);
|
||||
expect(newSelection.toRow).toBe(5);
|
||||
});
|
||||
|
||||
it('keep select class on row header', function () {
|
||||
expect($(container.find('.slick-cell.l0.r0')[5]).hasClass('selected'))
|
||||
.toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the user clicks a cell outside the current range', function () {
|
||||
beforeEach(function () {
|
||||
container.find('.slick-cell.l2.r2')[2].click();
|
||||
});
|
||||
|
||||
it('row gets deselected', function () {
|
||||
|
||||
var selectedRanges = cellSelectionModel.getSelectedRanges();
|
||||
|
||||
expect(selectedRanges.length).toBe(1);
|
||||
|
||||
var newSelection = selectedRanges[0];
|
||||
|
||||
expect(newSelection.fromCell).toBe(2);
|
||||
expect(newSelection.fromRow).toBe(2);
|
||||
expect(newSelection.toCell).toBe(2);
|
||||
expect(newSelection.toRow).toBe(2);
|
||||
});
|
||||
|
||||
it('remove select class on "some-column-name" column header', function () {
|
||||
expect($(container.find('.slick-cell.l0.r0')[5]).hasClass('selected'))
|
||||
.toBeFalsy();
|
||||
expect($(container.find('.slick-cell.l0.r0')[2]).hasClass('selected'))
|
||||
.toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the user has a column selected', function () {
|
||||
beforeEach(function () {
|
||||
var selectedRanges = [new Slick.Range(0, 1, 9, 1)];
|
||||
cellSelectionModel.setSelectedRanges(selectedRanges);
|
||||
});
|
||||
|
||||
it('no row should have the class "selected"', function () {
|
||||
expect($(container.find('.slick-cell.l0.r0')[0]).hasClass('selected'))
|
||||
.toBeFalsy();
|
||||
expect($(container.find('.slick-cell.l0.r0')[1]).hasClass('selected'))
|
||||
.toBeFalsy();
|
||||
expect($(container.find('.slick-cell.l0.r0')[2]).hasClass('selected'))
|
||||
.toBeFalsy();
|
||||
expect($(container.find('.slick-cell.l0.r0')[3]).hasClass('selected'))
|
||||
.toBeFalsy();
|
||||
expect($(container.find('.slick-cell.l0.r0')[4]).hasClass('selected'))
|
||||
.toBeFalsy();
|
||||
expect($(container.find('.slick-cell.l0.r0')[5]).hasClass('selected'))
|
||||
.toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("when the user clicks multiple row headers", function () {
|
||||
it("selects another row", function () {
|
||||
container.find('.sr .sc:first-child')[4].click();
|
||||
container.find('.sr .sc:first-child')[0].click();
|
||||
container.find('.slick-row .slick-cell:first-child')[4].click();
|
||||
container.find('.slick-row .slick-cell:first-child')[0].click();
|
||||
|
||||
var selectedRanges = rowSelectionModel.getSelectedRanges();
|
||||
var selectedRanges = cellSelectionModel.getSelectedRanges();
|
||||
expect(selectedRanges.length).toEqual(2);
|
||||
|
||||
var row1 = selectedRanges[0];
|
||||
@@ -117,49 +254,59 @@ define(
|
||||
describe("when a column was already selected", function () {
|
||||
beforeEach(function () {
|
||||
var selectedRanges = [new Slick.Range(0, 0, 0, 1)];
|
||||
rowSelectionModel.setSelectedRanges(selectedRanges);
|
||||
cellSelectionModel.setSelectedRanges(selectedRanges);
|
||||
});
|
||||
|
||||
it("deselects the column", function () {
|
||||
container.find('.sr .sc:first-child')[0].click();
|
||||
var selectedRanges = rowSelectionModel.getSelectedRanges();
|
||||
container.find('.slick-row .slick-cell:first-child')[0].click();
|
||||
var selectedRanges = cellSelectionModel.getSelectedRanges();
|
||||
|
||||
expectOnlyTheFirstRowToBeSelected(selectedRanges);
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe("when the row is deselected through setSelectedRanges", function () {
|
||||
beforeEach(function () {
|
||||
container.find('.sr .sc:first-child')[4].click();
|
||||
container.find('.slick-row .slick-cell:first-child')[4].click();
|
||||
});
|
||||
|
||||
it("should uncheck the checkbox", function () {
|
||||
rowSelectionModel.setSelectedRanges([]);
|
||||
it("should remove the selected class", function () {
|
||||
cellSelectionModel.setSelectedRanges([]);
|
||||
|
||||
expect($(container.find('.sr .sc:first-child input[type="checkbox"]')[4])
|
||||
.is(':checked')).toBeFalsy();
|
||||
expect($(container.find('.slick-row .slick-cell:first-child span[data-cell-type="row-header-selector"]')[4])
|
||||
.hasClass('selected')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe("click a second time", function () {
|
||||
beforeEach(function () {
|
||||
container.find('.sr .sc:first-child')[1].click();
|
||||
container.find('.slick-row .slick-cell:first-child')[1].click();
|
||||
});
|
||||
|
||||
it("unchecks checkbox", function () {
|
||||
container.find('.sr .sc:first-child')[1].click();
|
||||
expect($(container.find('.sr .sc:first-child input[type="checkbox"]')[1])
|
||||
.is(':checked')).toBeFalsy();
|
||||
it("removes the selected class", function () {
|
||||
container.find('.slick-row .slick-cell:first-child')[1].click();
|
||||
expect($(container.find('.slick-row .slick-cell:first-child span[data-cell-type="row-header-selector"]')[1])
|
||||
.hasClass('selected')).toBeFalsy();
|
||||
});
|
||||
|
||||
it("unselects the row", function () {
|
||||
container.find('.sr .sc:first-child')[1].click();
|
||||
var selectedRanges = rowSelectionModel.getSelectedRanges();
|
||||
container.find('.slick-row .slick-cell:first-child')[1].click();
|
||||
var selectedRanges = cellSelectionModel.getSelectedRanges();
|
||||
|
||||
expect(selectedRanges.length).toEqual(0);
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
function pressShiftArrow(keyCode) {
|
||||
var pressEvent = new $.Event("keydown");
|
||||
pressEvent.shiftKey = true;
|
||||
pressEvent.ctrlKey = false;
|
||||
pressEvent.altKey = false;
|
||||
pressEvent.which = keyCode;
|
||||
|
||||
$(container.find('.grid-canvas')).trigger(pressEvent);
|
||||
}
|
||||
});
|
||||
|
||||
function expectOnlyTheFirstRowToBeSelected(selectedRanges) {
|
||||
|
||||
Reference in New Issue
Block a user