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

[Endpoint] Adding a Resolver component that lets the user click and drag to pan and pinch to zoom #53619

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
ccf0621
WIP setting up react, redux, etc
Dec 3, 2019
c88400c
WIP more
Dec 3, 2019
a07d0fd
WIP even more
Dec 3, 2019
b0203ae
wip more. about to make a component and test worldToRaster
Dec 3, 2019
3e530e6
added react-redux types. working on world to raster
Dec 3, 2019
e052cd9
passing but so wrong
Dec 3, 2019
f2d6416
this is just wrong
Dec 3, 2019
83bf9e5
getting some world to raster action
Dec 3, 2019
84474e3
just about passing
Dec 3, 2019
6280558
removed tostring junk
Dec 3, 2019
0484291
refactored tests to use toBeCloseTo
Dec 3, 2019
dadcb6d
fix issues
Dec 3, 2019
2caea42
maybe panning is working? hard to know
Dec 3, 2019
1a193a9
pan around a bit
Dec 3, 2019
138fe88
add wheel zoom, but zoom isn't working
Dec 4, 2019
c54ed96
stopped using the delta panning but it obviously didnt help. would it…
Dec 4, 2019
d3c8b1d
worldToRaster tests were failing because we limited the zoom
Dec 4, 2019
1638551
fixed tests
Dec 4, 2019
661c726
seems like pan and zoom almost works
Dec 4, 2019
27aca81
add tests for panning
Dec 4, 2019
e7323cf
add some zoom tests
Dec 4, 2019
6cd3580
Added failing (unimplemented) zoom tests
Dec 4, 2019
f4326ac
zoom works, at least in the reducer
Dec 4, 2019
9736f6b
Panning and zooming is almost done
Dec 4, 2019
b314ddb
style diagnostic dots
Dec 4, 2019
0fb78a2
refactor stuff to use vectors and matrices
Dec 5, 2019
1fa6edb
more matrices
Dec 5, 2019
5157b2d
brent made me do it
Dec 5, 2019
73b08da
mousmove is on window now
Dec 5, 2019
4b381f5
move mouseup event to window. blacklist userFocusedOnWorldCoordinates
Dec 5, 2019
d753158
fix mouseup handler
Dec 6, 2019
183528a
prevent default when handling wheel
Dec 6, 2019
1dc6683
invert wheel zoom
Dec 7, 2019
e007b38
add comments to types and stuff
Dec 17, 2019
59703e6
change camera state shape. rename projectionMatrix
Dec 17, 2019
5673312
rename projection matrix test file. also raster to world is now a matrix
Dec 17, 2019
750369c
rename inverse projection matrix
Dec 17, 2019
b074f7b
rename inverse projection matrix test file
Dec 17, 2019
daddda4
panning actions take screen coordinates
Dec 17, 2019
bc5d15f
document stuff
Dec 19, 2019
4669d77
Documenting more types
Dec 19, 2019
0a1df7d
change all the interface imports again as usual
Dec 19, 2019
52f79c6
cleanup
Dec 20, 2019
f87e2b4
move diagnostic dot to new file
Dec 20, 2019
5863434
move autoupdating client rect to new file, refactor it
Dec 20, 2019
b2950c2
move nonpassive wheel hook to new file
Dec 20, 2019
6c500e3
trying to fix dumb zoom issue but dont know whats wrong
Dec 20, 2019
9eca46e
improve types and docs for useAutoupdatingClientRect
Dec 20, 2019
f7c66d4
fix tests, imports. also remove `http` concern from Resolver for now
Jan 2, 2020
b153b8c
rename userSetPositionOfCamera
Jan 6, 2020
71399aa
remove cancel panning concept
Jan 7, 2020
48df3c3
comments
Jan 7, 2020
d163e1a
rename Resolver component?
Jan 7, 2020
1dc1e18
more comments
Jan 7, 2020
ae4b9e7
completely remove canel panning feature
Jan 8, 2020
72d575b
add comment explaining the camera
Jan 8, 2020
bfd2284
Basic layout process nodes and edges
peluja1012 Dec 23, 2019
6ed3110
Add reducer, action, tests, and refactor
peluja1012 Jan 8, 2020
df21333
add some comments, move test variables
peluja1012 Jan 8, 2020
827bba8
small changes
peluja1012 Jan 8, 2020
8340ccd
fix errors in sample data
Jan 8, 2020
5980c39
cleanup and add more tests
Jan 8, 2020
b6da356
about to replace graphableProcessPidMaps
Jan 8, 2020
8347749
tiny refactor
Jan 8, 2020
f9ac348
working on refactoring the layout code
Jan 8, 2020
feaf213
big ol refactor
Jan 9, 2020
a438da6
we are cool
Jan 9, 2020
261e0f1
megafactor
Jan 9, 2020
3d89e00
refactor edge lines
Jan 9, 2020
ee2b076
cleanup
Jan 9, 2020
7b241ae
loop unravel
Jan 9, 2020
bc26420
cleanup
Jan 9, 2020
b2d8d5b
cleanup
Jan 9, 2020
bc840fc
more elite code
Jan 9, 2020
2ae6307
more stuff
Jan 9, 2020
d78c475
just about good
Jan 9, 2020
5f37888
we must never speak of this
Jan 9, 2020
5112ed7
get isometric
Jan 9, 2020
1ebcddc
remove todo
Jan 9, 2020
1fef3b7
update snapshots to match isometric stuff
Jan 9, 2020
679fa35
remove unused function
Jan 9, 2020
57fa7f9
add some comments
peluja1012 Jan 10, 2020
2462aa2
more commints
Jan 13, 2020
015c110
do comments right
Jan 13, 2020
ce7880b
comments
Jan 13, 2020
b5df646
remove endpoint workspace
Jan 14, 2020
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
14 changes: 14 additions & 0 deletions x-pack/plugins/endpoint/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"author": "Elastic",
"name": "endpoint",
"version": "0.0.0",
"private": true,
"license": "Elastic-License",
"scripts": {},
"dependencies": {
"react-redux": "^7.1.0"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We depend on react-redux's hooks.

},
"devDependencies": {
"@types/react-redux": "^7.1.0"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { CameraAction } from './store/camera';
import { DataAction } from './store/data';

export type ResolverAction = CameraAction | DataAction;
35 changes: 18 additions & 17 deletions x-pack/plugins/endpoint/public/embeddables/resolver/embeddable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,32 @@
* you may not use this file except in compliance with the Elastic License.
*/

import {
EmbeddableInput,
IContainer,
Embeddable,
} from '../../../../../../src/plugins/embeddable/public';
import ReactDOM from 'react-dom';
import React from 'react';
import { AppRoot } from './view';
import { storeFactory } from './store';
import { Embeddable } from '../../../../../../src/plugins/embeddable/public';

export class ResolverEmbeddable extends Embeddable {
public readonly type = 'resolver';
constructor(initialInput: EmbeddableInput, parent?: IContainer) {
super(
// Input state is irrelevant to this embeddable, just pass it along.
initialInput,
// Initial output state - this embeddable does not do anything with output, so just
// pass along an empty object.
{},
// Optional parent component, this embeddable can optionally be rendered inside a container.
parent
);
}
private lastRenderTarget?: Element;

public render(node: HTMLElement) {
node.innerHTML = '<div data-test-subj="resolverEmbeddable">Welcome from Resolver</div>';
if (this.lastRenderTarget !== undefined) {
ReactDOM.unmountComponentAtNode(this.lastRenderTarget);
}
this.lastRenderTarget = node;
const { store } = storeFactory();
ReactDOM.render(<AppRoot store={store} />, node);
}

public reload(): void {
throw new Error('Method not implemented.');
}

public destroy(): void {
if (this.lastRenderTarget !== undefined) {
ReactDOM.unmountComponentAtNode(this.lastRenderTarget);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
*/

import { i18n } from '@kbn/i18n';
import { ResolverEmbeddable } from './';
import {
EmbeddableFactory,
EmbeddableInput,
IContainer,
EmbeddableInput,
} from '../../../../../../src/plugins/embeddable/public';
import { ResolverEmbeddable } from './embeddable';

export class ResolverEmbeddableFactory extends EmbeddableFactory {
public readonly type = 'resolver';
Expand All @@ -20,7 +20,7 @@ export class ResolverEmbeddableFactory extends EmbeddableFactory {
}

public async create(initialInput: EmbeddableInput, parent?: IContainer) {
return new ResolverEmbeddable(initialInput, parent);
return new ResolverEmbeddable(initialInput, {}, parent);
}

public getDisplayName() {
Expand Down
12 changes: 12 additions & 0 deletions x-pack/plugins/endpoint/public/embeddables/resolver/lib/math.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

/**
* Return `value` unless it is less than `minimum`, in which case return `minimum` or unless it is greater than `maximum`, in which case return `maximum`.
*/
export function clamp(value: number, minimum: number, maximum: number) {
return Math.max(Math.min(value, maximum), minimum);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { multiply } from './matrix3';
describe('matrix3', () => {
it('can multiply two matrix3s', () => {
expect(multiply([1, 2, 3, 4, 5, 6, 7, 8, 9], [10, 11, 12, 13, 14, 15, 16, 17, 18])).toEqual([
84,
90,
96,
201,
216,
231,
318,
342,
366,
]);
});
});
56 changes: 56 additions & 0 deletions x-pack/plugins/endpoint/public/embeddables/resolver/lib/matrix3.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { Matrix3 } from '../types';

/**
* Return a new matrix which is the product of the first and second matrix.
*/
export function multiply(
[a11, a12, a13, a21, a22, a23, a31, a32, a33]: Matrix3,
[b11, b12, b13, b21, b22, b23, b31, b32, b33]: Matrix3
): Matrix3 {
const s11 = a11 * b11 + a12 * b21 + a13 * b31;
const s12 = a11 * b12 + a12 * b22 + a13 * b32;
const s13 = a11 * b13 + a12 * b23 + a13 * b33;

const s21 = a21 * b11 + a22 * b21 + a23 * b31;
const s22 = a21 * b12 + a22 * b22 + a23 * b32;
const s23 = a21 * b13 + a22 * b23 + a23 * b33;

const s31 = a31 * b11 + a32 * b21 + a33 * b31;
const s32 = a31 * b12 + a32 * b22 + a33 * b32;
const s33 = a31 * b13 + a32 * b23 + a33 * b33;

// prettier-ignore
return [
s11, s12, s13,
s21, s22, s23,
s31, s32, s33,
];
}

/**
* Return a new matrix which is the sum of the two passed in.
*/
export function add(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since all of these seem to have name collisions between matrix v. vector addition, multiplication, etc. wondering if it makes sense to nest this export under some sort of class or named constant. Just want to avoid littering code with things like:

import { add as matrixAdd } from 'matrix3'
import { add as vectorAdd } from 'vector2'

as well as having to back reference whether we're operating on matrices, vectors, lists, etc. because we've lost all context of what add we're working with at that point...

Copy link
Contributor Author

@oatkiller oatkiller Jan 13, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a module is already a logical grouping of exports. you can:

import * as matrix3 from 'matrix3'
// ...
matrix3.add(a,b)

if ya want. also you can get context from your editor regardless of how it was imported. In this case it was imported as addMatrix:

image

[a11, a12, a13, a21, a22, a23, a31, a32, a33]: Matrix3,
[b11, b12, b13, b21, b22, b23, b31, b32, b33]: Matrix3
): Matrix3 {
return [
a11 + b11,
a12 + b12,
a13 + b13,

a21 + b21,
a22 + b22,
a23 + b23,

a31 + b31,
a32 + b32,
a33 + b33,
];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { applyMatrix3 } from './vector2';
import { scalingTransformation } from './transformation';

describe('transforms', () => {
it('applying a scale matrix to a vector2 can invert the y value', () => {
expect(applyMatrix3([1, 2], scalingTransformation([1, -1]))).toEqual([1, -2]);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { Matrix3, Vector2 } from '../types';

/**
* The inverse of `orthographicProjection`.
*/
export function inverseOrthographicProjection(
top: number,
right: number,
bottom: number,
left: number
): Matrix3 {
const m11 = (right - left) / 2;
const m13 = (right + left) / (right - left);

const m22 = (top - bottom) / 2;
const m23 = (top + bottom) / (top - bottom);

return [m11, 0, m13, 0, m22, m23, 0, 0, 0];
}

/**
* Adjust x, y to be bounded, in scale, of a clipping plane defined by top, right, bottom, left.
*
* See explanation:
* https://www.scratchapixel.com/lessons/3d-basic-rendering/perspective-and-orthographic-projection-matrix
* https://en.wikipedia.org/wiki/Orthographic_projection
*/
export function orthographicProjection(
top: number,
right: number,
bottom: number,
left: number
): Matrix3 {
const m11 = 2 / (right - left); // adjust x scale to match ndc (-1, 1) bounds
const m13 = -((right + left) / (right - left));

const m22 = 2 / (top - bottom); // adjust y scale to match ndc (-1, 1) bounds
const m23 = -((top + bottom) / (top - bottom));

return [m11, 0, m13, 0, m22, m23, 0, 0, 0];
}

/**
* Returns a 2D transformation matrix that when applied to a vector will scale the vector by `x` and `y` in their respective axises.
* See https://en.wikipedia.org/wiki/Scaling_(geometry)#Matrix_representation
*/
export function scalingTransformation([x, y]: Vector2): Matrix3 {
// prettier-ignore
return [
x, 0, 0,
0, y, 0,
0, 0, 0
]
}

/**
* Returns a 2D transformation matrix that when applied to a vector will translate by `x` and `y` in their respective axises.
* See https://en.wikipedia.org/wiki/Translation_(geometry)#Matrix_representation
*/
export function translationTransformation([x, y]: Vector2): Matrix3 {
// prettier-ignore
return [
1, 0, x,
0, 1, y,
0, 0, 1
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

/**
* Sequences a tree, yielding children returned by the `children` function. Sequencing is done in 'depth first preorder' fashion. See https://en.wikipedia.org/wiki/Tree_traversal#Pre-order_(NLR)
*/
export function* depthFirstPreorder<T>(root: T, children: (parent: T) => T[]): Iterable<T> {
const nodesToVisit = [root];
while (nodesToVisit.length !== 0) {
const currentNode = nodesToVisit.shift();
if (currentNode !== undefined) {
nodesToVisit.unshift(...(children(currentNode) || []));
yield currentNode;
}
}
}

/**
* Sequences a tree, yielding children returned by the `children` function. Sequencing is done in 'level order' fashion.
*/
export function* levelOrder<T>(root: T, children: (parent: T) => T[]): Iterable<T> {
let level = [root];
while (level.length !== 0) {
let nextLevel = [];
for (const node of level) {
yield node;
nextLevel.push(...(children(node) || []));
}
level = nextLevel;
nextLevel = [];
}
}
52 changes: 52 additions & 0 deletions x-pack/plugins/endpoint/public/embeddables/resolver/lib/vector2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { Vector2, Matrix3 } from '../types';

/**
* Returns a vector which is the sum of `a` and `b`.
*/
export function add(a: Vector2, b: Vector2): Vector2 {
return [a[0] + b[0], a[1] + b[1]];
}

/**
* Returns a vector which is the difference of `a` and `b`.
*/
export function subtract(a: Vector2, b: Vector2): Vector2 {
return [a[0] - b[0], a[1] - b[1]];
}

/**
* Returns a vector which is the quotient of `a` and `b`.
*/
export function divide(a: Vector2, b: Vector2): Vector2 {
return [a[0] / b[0], a[1] / b[1]];
}

/**
* Returns a vector which is the result of applying a 2D transformation matrix to the provided vector.
*/
export function applyMatrix3([x, y]: Vector2, [m11, m12, m13, m21, m22, m23]: Matrix3): Vector2 {
return [x * m11 + y * m12 + m13, x * m21 + y * m22 + m23];
}

/**
* Returns the distance between two vectors
*/
export function distance(a: Vector2, b: Vector2) {
const [x1, y1] = a;
const [x2, y2] = b;
return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
}

/**
* Returns the angle between two vectors
*/
export function angle(a: Vector2, b: Vector2) {
const deltaX = b[0] - a[0];
const deltaY = b[1] - a[1];
return Math.atan2(deltaY, deltaX);
}
Loading