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:
Sarah McAlear
2017-06-08 13:31:36 +01:00
committed by Dave Page
parent 2fddf750e6
commit 01bfa88309
62 changed files with 4513 additions and 829 deletions

View File

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