diff --git a/packages/perspective-viewer-hypergrid/src/js/PerspectiveDataModel.js b/packages/perspective-viewer-hypergrid/src/js/PerspectiveDataModel.js
index fcad8e93e8..802f4d30af 100644
--- a/packages/perspective-viewer-hypergrid/src/js/PerspectiveDataModel.js
+++ b/packages/perspective-viewer-hypergrid/src/js/PerspectiveDataModel.js
@@ -34,6 +34,10 @@ module.exports = require("datasaur-local").extend("PerspectiveDataModel", {
return this._nrows || 0;
},
+ getConfig: function() {
+ return this._view._config;
+ },
+
setRowCount: function(count) {
this._nrows = count || 0;
},
diff --git a/packages/perspective-viewer-hypergrid/src/js/perspective-plugin.js b/packages/perspective-viewer-hypergrid/src/js/perspective-plugin.js
index fe82ff932c..2b652f93ff 100644
--- a/packages/perspective-viewer-hypergrid/src/js/perspective-plugin.js
+++ b/packages/perspective-viewer-hypergrid/src/js/perspective-plugin.js
@@ -107,7 +107,55 @@ function setColumnPropsByType(column) {
// `install` makes this a Hypergrid plug-in
exports.install = function(grid) {
Object.getPrototypeOf(grid.behavior).setPSP = setPSP;
- Object.getPrototypeOf(grid.behavior).cellClicked = function(event) {
+
+ Object.getPrototypeOf(grid.behavior).cellClicked = async function(event) {
+ event.primitiveEvent.preventDefault();
+ event.handled = true;
+ const {x, y} = event.dataCell;
+ const config = this.dataModel.getConfig();
+ const row_pivots = config.row_pivot;
+ const column_pivots = config.column_pivot;
+ const start_row = y >= 0 ? y : 0;
+ const end_row = start_row + 1;
+ this.dataModel._view.to_json({start_row, end_row}).then(r => {
+ const row_paths = r.map(x => x.__ROW_PATH__);
+ const row_pivot_values = row_paths[0] || [];
+ const row_filters = row_pivots
+ .map((pivot, index) => {
+ const pivot_value = row_pivot_values[index];
+ return pivot_value ? [pivot, "==", pivot_value] : undefined;
+ })
+ .filter(x => x);
+ const column_index = row_pivots.length > 0 ? x + 1 : x;
+ const column_paths = Object.keys(r[0])[column_index];
+ let column_filters = [];
+ let column_name;
+ if (column_paths) {
+ const column_pivot_values = column_paths.split("|");
+ column_name = column_pivot_values[column_pivot_values.length - 1];
+ column_filters = column_pivots
+ .map((pivot, index) => {
+ const pivot_value = column_pivot_values[index];
+ return pivot_value ? [pivot, "==", pivot_value] : undefined;
+ })
+ .filter(x => x);
+ }
+
+ const filters = config.filter.concat(row_filters).concat(column_filters);
+
+ grid.canvas.dispatchEvent(
+ new CustomEvent("perspective-click", {
+ bubbles: true,
+ composed: true,
+ detail: {
+ config: {filters},
+ column_name,
+ row: r[0]
+ }
+ })
+ );
+ });
+
return this.dataModel.toggleRow(event.dataCell.y, event.dataCell.x, event);
};
diff --git a/packages/perspective-viewer-hypergrid/test/html/hypergrid.html b/packages/perspective-viewer-hypergrid/test/html/hypergrid.html
new file mode 100644
index 0000000000..8f05b25f97
--- /dev/null
+++ b/packages/perspective-viewer-hypergrid/test/html/hypergrid.html
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/perspective-viewer-hypergrid/test/js/hypergrid.spec.js b/packages/perspective-viewer-hypergrid/test/js/hypergrid.spec.js
new file mode 100644
index 0000000000..be8ad78773
--- /dev/null
+++ b/packages/perspective-viewer-hypergrid/test/js/hypergrid.spec.js
@@ -0,0 +1,94 @@
+/******************************************************************************
+ *
+ * Copyright (c) 2019, the Perspective Authors.
+ *
+ * This file is part of the Perspective library, distributed under the terms of
+ * the Apache License 2.0. The full license can be found in the LICENSE file.
+ *
+ */
+
+const utils = require("@jpmorganchase/perspective-viewer/test/js/utils.js");
+const path = require("path");
+
+const click_details = async page => {
+ const viewer = await page.$("perspective-viewer");
+
+ const click_event = page.evaluate(element => {
+ return new Promise(resolve => {
+ element.addEventListener("perspective-click", e => {
+ resolve(e.detail);
+ });
+ });
+ }, viewer);
+
+ await page.mouse.click(300, 300);
+ return await click_event;
+};
+
+utils.with_server({}, () => {
+ describe.page(
+ "hypergrid.html",
+ () => {
+ describe("clicking on a cell in the grid", () => {
+ describe("when no filters are present", () => {
+ test.capture("perspective dispatches perspective-click event with correct properties.", async page => {
+ await page.waitFor(100);
+ const detail = await click_details(page);
+ expect(detail.row).toEqual({
+ Category: "Technology",
+ City: "Los Angeles",
+ Country: "United States",
+ "Customer ID": "BH-11710",
+ Discount: 0.2,
+ "Order Date": 1307577600000,
+ "Order ID": "CA-2011-115812",
+ "Postal Code": 90032,
+ "Product ID": "TEC-PH-10002033",
+ Profit: 68.3568,
+ Quantity: 4,
+ Region: "West",
+ "Row ID": 12,
+ Sales: 911.424,
+ Segment: "Consumer",
+ "Ship Date": 1308009600000,
+ "Ship Mode": "Standard Class",
+ State: "California",
+ "Sub-Category": "Phones"
+ });
+ expect(detail.column_name).toEqual("Order Date");
+ expect(detail.config).toEqual({filters: []});
+ });
+ });
+
+ describe("when a filter is present", () => {
+ test.capture("perspective dispatches perspective-click event with one filter.", async page => {
+ await page.waitFor(100);
+ const viewer = await page.$("perspective-viewer");
+ page.evaluate(element => element.setAttribute("filters", '[["Segment", "==", "Consumer"]]'), viewer);
+ await page.waitForSelector("perspective-viewer:not([updating])");
+
+ const detail = await click_details(page);
+ expect(detail.config).toEqual({filters: [["Segment", "==", "Consumer"]]});
+ });
+
+ test.capture("perspective dispatches perspective-click event with filters.", async page => {
+ await page.waitFor(100);
+ const viewer = await page.$("perspective-viewer");
+ page.evaluate(element => {
+ element.setAttribute("filters", '[["Segment", "==", "Consumer"]]');
+ element.setAttribute("column-pivots", '["Region"]');
+ element.setAttribute("row-pivots", '["Country", "City"]');
+ }, viewer);
+ await page.waitForSelector("perspective-viewer:not([updating])");
+
+ const detail = await click_details(page);
+ expect(detail.config).toEqual({
+ filters: [["Segment", "==", "Consumer"], ["Country", "==", "United States"], ["City", "==", "Madison"], ["Region", "==", "Central"]]
+ });
+ });
+ });
+ });
+ },
+ {reload_page: true, root: path.join(__dirname, "..", "..")}
+ );
+});
diff --git a/packages/perspective-viewer-hypergrid/test/js/superstore.spec.js b/packages/perspective-viewer-hypergrid/test/js/superstore.spec.js
index db9b0f9e68..a3c428191f 100644
--- a/packages/perspective-viewer-hypergrid/test/js/superstore.spec.js
+++ b/packages/perspective-viewer-hypergrid/test/js/superstore.spec.js
@@ -44,7 +44,7 @@ utils.with_server({}, () => {
await page.waitForSelector("perspective-viewer:not([updating])");
});
- test.capture("handles flush().", async page => {
+ test.capture("handles flush", async page => {
const viewer = await page.$("perspective-viewer");
await page.shadow_click("perspective-viewer", "#config_button");
await page.evaluate(element => {
diff --git a/packages/perspective-viewer-hypergrid/test/results/results.json b/packages/perspective-viewer-hypergrid/test/results/results.json
index 41e8b801c1..8398752ace 100644
--- a/packages/perspective-viewer-hypergrid/test/results/results.json
+++ b/packages/perspective-viewer-hypergrid/test/results/results.json
@@ -1,22 +1,25 @@
{
+ "empty.html/empty grids do not explode": "423ca653bbcbc21a28029c149a37b8ec",
"regressions.html/regular updates": "14abd51c3cae1919119d9f88bfbc5cd3",
+ "regressions.html/saving a computed column does not interrupt update rendering": "da13afb4284b9c3da21ed57c6ba69301",
"superstore.html/shows a grid without any settings applied.": "59ecbb591317976232b7dc078b79e164",
"superstore.html/pivots by a row.": "0eab9174593f50e58b92ae047ea97068",
"superstore.html/pivots by two rows.": "5552a85a31321fe2495fc8aec3d457d9",
+ "superstore.html/pivots by a column.": "523c39ab27ca610b5ed179cbe742ec5b",
"superstore.html/pivots by a row and a column.": "404fd705b0145f4bbf31f7bd1bccebe6",
"superstore.html/pivots by two rows and two columns.": "8527820a72137b6c459a0e13a11a765d",
+ "superstore.html/sorts by a hidden column.": "042756bbc39aeb729bc4108cde465ec8",
"superstore.html/sorts by a numeric column.": "3838ecb375fe4450079c1f54969d2239",
+ "superstore.html/filters by a numeric column.": "a100080f91cae951339cf5b956b5c2cc",
+ "superstore.html/highlights invalid filter.": "e244cca8fc2278cb2477d0a46ab5331f",
"superstore.html/sorts by an alpha column.": "0c65ce1fbb1035414fd98ca6bb26c493",
"superstore.html/displays visible columns.": "5dd292347e4a969425d8c2b216e802ae",
+ "superstore.html/collapses to depth smaller than viewport": "bdd25c1c40781478bd040d5816b887a6",
"superstore.html/resets viewable area when the logical size expands.": "a5d1bad309edf83ceef190dd19d867ec",
"superstore.html/resets viewable area when the physical size expands.": "59ecbb591317976232b7dc078b79e164",
- "superstore.html/sorts by a hidden column.": "042756bbc39aeb729bc4108cde465ec8",
- "superstore.html/filters by a numeric column.": "a100080f91cae951339cf5b956b5c2cc",
- "superstore.html/pivots by a column.": "523c39ab27ca610b5ed179cbe742ec5b",
- "superstore.html/collapses to depth smaller than viewport": "bdd25c1c40781478bd040d5816b887a6",
- "regressions.html/saving a computed column does not interrupt update rendering": "da13afb4284b9c3da21ed57c6ba69301",
- "empty.html/empty grids do not explode": "423ca653bbcbc21a28029c149a37b8ec",
- "superstore.html/highlights invalid filter.": "e244cca8fc2278cb2477d0a46ab5331f",
- "superstore.html/handles flush().": "a5d1bad309edf83ceef190dd19d867ec",
- "superstore.html/replaces all rows.": "2c41d623f03b2417da7b5dcf7f31e364"
+ "superstore.html/replaces all rows.": "2c41d623f03b2417da7b5dcf7f31e364",
+ "hypergrid.html/perspective dispatches perspective-click event with correct properties.": "f5d6bf82299b2e5f403cdb69b67645fe",
+ "hypergrid.html/perspective dispatches perspective-click event with one filter.": "b7a10ece1d5084742f9a2d88bb68984d",
+ "hypergrid.html/perspective dispatches perspective-click event with filters.": "3025f83c828d468207b04d8454e94fda",
+ "superstore.html/handles flush": "a5d1bad309edf83ceef190dd19d867ec"
}
\ No newline at end of file