Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Computed UX #765

Merged
merged 2 commits into from
Oct 20, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Computed function categories
  • Loading branch information
texodus committed Oct 20, 2019
commit 5b78a38ccf95fa8a6737a9d29dcf21fbbfe9aaa1
91 changes: 66 additions & 25 deletions packages/perspective-viewer/src/js/computed_column.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import template from "../html/computed_column.html";
import style from "../less/computed_column.less";

import {dragleave} from "./viewer/dragdrop.js";
import {html, render} from "lit-html";

// Computations
const hour_of_day = function(val) {
Expand Down Expand Up @@ -78,28 +79,58 @@ const month_bucket = function(val) {
return date;
};

const year_bucket = function(val) {
let date = new Date(val);
date.setHours(0);
date.setMinutes(0);
date.setSeconds(0);
date.setDate(1);
date.setMonth(1);
return date;
};

export const COMPUTATIONS = {
hour_of_day: new Computation("hour_of_day", "datetime", "integer", hour_of_day),
day_of_week: new Computation("day_of_week", "datetime", "string", day_of_week),
month_of_year: new Computation("month_of_year", "datetime", "string", month_of_year),
second_bucket: new Computation("second_bucket", "datetime", "datetime", second_bucket),
minute_bucket: new Computation("minute_bucket", "datetime", "datetime", minute_bucket),
hour_bucket: new Computation("hour_bucket", "datetime", "datetime", hour_bucket),
day_bucket: new Computation("day_bucket", "datetime", "date", day_bucket),
week_bucket: new Computation("week_bucket", "datetime", "date", week_bucket),
month_bucket: new Computation("month_bucket", "datetime", "date", month_bucket),
uppercase: new Computation("uppercase", "string", "string", x => x.toUpperCase()),
lowercase: new Computation("lowercase", "string", "string", x => x.toLowerCase()),
length: new Computation("length", "string", "integer", x => x.length),
add: new Computation("add", "float", "float", (a, b) => a + b, 2),
subtract: new Computation("subtract", "float", "float", (a, b) => a - b, 2),
multiply: new Computation("multiply", "float", "float", (a, b) => a * b, 2),
divide: new Computation("divide", "float", "float", (a, b) => a / b, 2),
percent_a_of_b: new Computation("percent_a_of_b", "float", "float", (a, b) => (a / b) * 100, 2),
concat_space: new Computation("concat_space", "string", "string", (a, b) => a + " " + b, 2),
concat_comma: new Computation("concat_comma", "string", "string", (a, b) => a + ", " + b, 2)
hour_of_day: new Computation("hour_of_day", "datetime", "integer", hour_of_day, ["Time"]),
day_of_week: new Computation("day_of_week", "datetime", "string", day_of_week, ["Time"]),
month_of_year: new Computation("month_of_year", "datetime", "string", month_of_year, ["Time"]),
second_bucket: new Computation("second_bucket", "datetime", "datetime", second_bucket, ["Time"]),
minute_bucket: new Computation("minute_bucket", "datetime", "datetime", minute_bucket, ["Time"]),
hour_bucket: new Computation("hour_bucket", "datetime", "datetime", hour_bucket, ["Time"]),
day_bucket: new Computation("day_bucket", "datetime", "date", day_bucket, ["Time"]),
week_bucket: new Computation("week_bucket", "datetime", "date", week_bucket, ["Time"]),
month_bucket: new Computation("month_bucket", "datetime", "date", month_bucket, ["Time"]),
year_bucket: new Computation("year_bucket", "datetime", "date", year_bucket, ["Time"]),
add: new Computation("add", "float", "float", (a, b) => a + b, ["Math"], 2),
subtract: new Computation("subtract", "float", "float", (a, b) => a - b, ["Math"], 2),
multiply: new Computation("multiply", "float", "float", (a, b) => a * b, ["Math"], 2),
divide: new Computation("divide", "float", "float", (a, b) => a / b, ["Math"], 2),
percent_a_of_b: new Computation("percent_a_of_b", "float", "float", (a, b) => (a / b) * 100, ["Math"], 2),
uppercase: new Computation("uppercase", "string", "string", x => x.toUpperCase(), ["Text"]),
lowercase: new Computation("lowercase", "string", "string", x => x.toLowerCase(), ["Text"]),
length: new Computation("length", "string", "integer", x => x.length, ["Text"]),
concat_space: new Computation("concat_space", "string", "string", (a, b) => a + " " + b, ["Text"], 2),
concat_comma: new Computation("concat_comma", "string", "string", (a, b) => a + ", " + b, ["Text"], 2)
};

function _insert_tree(name, elem, tree) {
let pointer = tree;
const path = elem.category;
for (const category of path) {
pointer = pointer[category] = pointer[category] || {};
}
pointer[name] = elem;
}

function _get_tree() {
const tree = {};
for (const comp in COMPUTATIONS) {
_insert_tree(comp, COMPUTATIONS[comp], tree);
}
return tree;
}

let TREE = _get_tree();

// Eslint complains here because we don't do anything, but actually we globally
// register this class as a CustomElement
@bindTemplate(template, style) // eslint-disable-next-line no-unused-vars
Expand All @@ -126,18 +157,28 @@ class ComputedColumn extends HTMLElement {

connectedCallback() {
this._register_ids();
this._register_computations();
render(Array.from(this._selector_template()), this._computation_selector);
this._register_callbacks();
this._update_computation(null);
this._register_inputs();
}

_register_computations() {
this._computation_selector.innerHTML = "";
let iterate = true;
for (let comp of Object.keys(COMPUTATIONS)) {
this._computation_selector.innerHTML += `<option value="${comp}"${iterate ? ' selected="selected"' : ""}>${comp.replace(/_/g, " ")}</option>`;
iterate = false;
TREE = _get_tree();
render(Array.from(this._selector_template()), this._computation_selector);
}

*_selector_template(tree = TREE) {
for (const [category, comp] of Object.entries(tree)) {
if (comp.name) {
yield html`
<option value=${comp.name}>${category}</option>
`;
} else {
yield html`
<optgroup label=${category}>${Array.from(this._selector_template(comp))}</optgroup>
`;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
*/

export default class Computation {
constructor(name, input_type, return_type, func, num_params = 1) {
constructor(name, input_type, return_type, func, category, num_params = 1) {
this.category = category;
this.name = name;
this.input_type = input_type;
this.return_type = return_type;
Expand Down
1 change: 1 addition & 0 deletions packages/perspective-viewer/src/less/computed_column.less
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDIwLjAuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCA0LjkgMTAiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQuOSAxMDsiIHhtbDpzcGFjZT0icHJlc2VydmUiPgo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPgoJLnN0MHtmaWxsOiM0NDQ0NDQ7fQo8L3N0eWxlPgo8dGl0bGU+YXJyb3dzPC90aXRsZT4KPHBvbHlnb24gY2xhc3M9InN0MCIgcG9pbnRzPSIxLjQsNC43IDIuNSwzLjIgMy41LDQuNyAiLz4KPHBvbHlnb24gY2xhc3M9InN0MCIgcG9pbnRzPSIzLjUsNS4zIDIuNSw2LjggMS40LDUuMyAiLz4KPC9zdmc+Cg==)
no-repeat 95% 50%;
background-color: #fff;
outline: none;
border: none;
height: 24px;
padding: 0px 0px 0px 6px;
Expand Down