Skip to content

Commit

Permalink
Types + Extract Integration Util (#44433) (#44948)
Browse files Browse the repository at this point in the history
* Types + Extract Integration Util

* Missed a file

* Compensate for the TS/JS import confusion by eslint
  • Loading branch information
clintandrewhall authored Sep 6, 2019
1 parent 5554cbd commit a9b16ba
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 61 deletions.
10 changes: 10 additions & 0 deletions x-pack/legacy/plugins/canvas/__tests__/fixtures/workpads.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@
import { CanvasWorkpad, CanvasElement, CanvasPage } from '../../types';

const BaseWorkpad: CanvasWorkpad = {
'@created': '2019-02-08T18:35:23.029Z',
'@timestamp': '2019-02-08T18:35:23.029Z',
assets: {
'asset-ada763f1-295e-4188-8e08-b5bed9e006a1': {
id: 'asset-ada763f1-295e-4188-8e08-b5bed9e006a1',
'@created': '2018-01-17T19:13:09.185Z',
type: 'dataurl',
value: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciLz4=',
},
},
name: 'base workpad',
id: 'base-workpad',
width: 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,61 +8,12 @@ import { shallowEqual } from 'recompose';
import { getNodes, getSelectedPage } from '../../state/selectors/workpad';
import { addElement, removeElements, setMultiplePositions } from '../../state/actions/elements';
import { selectToplevelNodes } from '../../state/actions/transient';
import { matrixToAngle, multiply, rotateZ, translate } from '../../lib/aeroelastic/matrix';
import { matrixToAngle } from '../../lib/aeroelastic/matrix';
import { arrayToMap, flatten, identity } from '../../lib/aeroelastic/functional';
import { getLocalTransformMatrix } from '../../lib/aeroelastic/layout_functions';
import { isGroupId, elementToShape } from './positioning_utils';

export const isGroupId = id => id.startsWith('group');

const headerData = id =>
isGroupId(id)
? { id, type: 'group', subtype: 'persistentGroup' }
: { id, type: 'rectangleElement', subtype: '' };

const transformData = ({ top, left, width, height, angle }, z) =>
multiply(
translate(left + width / 2, top + height / 2, z), // painter's algo: latest item (highest z) goes to top
rotateZ((-angle / 180) * Math.PI) // minus angle as transform:matrix3d uses a left-handed coordinate system
);

const simplePosition = ({ id, position, filter }, z) => ({
...headerData(id),
width: position.width,
height: position.height,
transformMatrix: transformData(position, z),
filter,
});

export const simplePositioning = ({ elements }) => ({ elements: elements.map(simplePosition) });

/**
* elementToShape
*
* converts a `kibana-canvas` element to an `aeroelastic` shape.
*
* Shape: the layout algorithms need to deal with objects through their geometric properties, excluding other aspects,
* such as what's inside the element, eg. image or scatter plot. This representation is, at its core, a transform matrix
* that establishes a new local coordinate system https://drafts.csswg.org/css-transforms/#local-coordinate-system plus a
* size descriptor. There are two versions of the transform matrix:
* - `transformMatrix` is analogous to the SVG https://drafts.csswg.org/css-transforms/#current-transformation-matrix
* - `localTransformMatrix` is analogous to the SVG https://drafts.csswg.org/css-transforms/#transformation-matrix
*
* Element: it also needs to represent the geometry, primarily because of the need to persist it in `redux` and on the
* server, and to accept such data from the server. The redux and server representations will need to change as more general
* projections such as 3D are added. The element also needs to maintain its content, such as an image or a plot.
*
* While all elements on the current page also exist as shapes, there are shapes that are not elements: annotations.
* For example, `rotation_handle`, `border_resize_handle` and `border_connection` are modeled as shapes by the layout
* library, simply for generality.
*/

export const elementToShape = ({ id, position }, z) => ({
...headerData(id),
parent: (position && position.parent) || null,
transformMatrix: transformData(position, z),
a: position.width / 2, // we currently specify half-width, half-height as it leads to
b: position.height / 2, // more regular math (like ellipsis radii rather than diameters)
});
export * from './positioning_utils';

const shapeToElement = shape => ({
left: shape.transformMatrix[12] - shape.a,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* 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 { PositionedElement, ElementPosition } from '../../../types';
import { multiply, rotateZ, translate } from '../../lib/aeroelastic/matrix';

export const isGroupId = (id: string) => id.startsWith('group');

const headerData = (id: string) =>
isGroupId(id)
? { id, type: 'group', subtype: 'persistentGroup' }
: { id, type: 'rectangleElement', subtype: '' };

const transformData = ({ top, left, width, height, angle }: ElementPosition, z: number) =>
multiply(
translate(left + width / 2, top + height / 2, z), // painter's algo: latest item (highest z) goes to top
rotateZ((-angle / 180) * Math.PI) // minus angle as transform:matrix3d uses a left-handed coordinate system
);

/**
* elementToShape
*
* converts a `kibana-canvas` element to an `aeroelastic` shape.
*
* Shape: the layout algorithms need to deal with objects through their geometric properties, excluding other aspects,
* such as what's inside the element, eg. image or scatter plot. This representation is, at its core, a transform matrix
* that establishes a new local coordinate system https://drafts.csswg.org/css-transforms/#local-coordinate-system plus a
* size descriptor. There are two versions of the transform matrix:
* - `transformMatrix` is analogous to the SVG https://drafts.csswg.org/css-transforms/#current-transformation-matrix
* - `localTransformMatrix` is analogous to the SVG https://drafts.csswg.org/css-transforms/#transformation-matrix
*
* Element: it also needs to represent the geometry, primarily because of the need to persist it in `redux` and on the
* server, and to accept such data from the server. The redux and server representations will need to change as more general
* projections such as 3D are added. The element also needs to maintain its content, such as an image or a plot.
*
* While all elements on the current page also exist as shapes, there are shapes that are not elements: annotations.
* For example, `rotation_handle`, `border_resize_handle` and `border_connection` are modeled as shapes by the layout
* library, simply for generality.
*/

export const elementToShape = (
{ id, position }: { id: string; position: ElementPosition },
z: number
) => ({
...headerData(id),
parent: (position && position.parent) || null,
transformMatrix: transformData(position, z),
a: position.width / 2, // we currently specify half-width, half-height as it leads to
b: position.height / 2, // more regular math (like ellipsis radii rather than diameters)
});

const simplePosition = (
{ id, position, filter }: { id: string; position: ElementPosition; filter: string },
z: number
) => ({
...headerData(id),
width: position.width,
height: position.height,
transformMatrix: transformData(position, z),
filter,
});

export const simplePositioning = ({ elements }: { elements: PositionedElement[] }) => ({
elements: elements.map(simplePosition),
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

import { withProps } from 'recompose';
import { simplePositioning } from '../integration_utils';
import { simplePositioning } from '../positioning_utils';
import { StaticWorkpadPage } from './static_workpad_page';

export const StaticPage = () => withProps(simplePositioning)(StaticWorkpadPage);
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import React, { PureComponent } from 'react';
import { ElementWrapper } from '../../element_wrapper';
import { staticWorkpadPagePropTypes } from '../prop_types';
import { isGroupId } from '../integration_utils';
import { isGroupId } from '../positioning_utils';

export class StaticWorkpadPage extends PureComponent {
static propTypes = staticWorkpadPagePropTypes;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { routerProvider } from '../../lib/router_provider';
import { getDefaultPage } from '../defaults';
import * as actions from '../actions/pages';
import { getSelectedPageIndex } from '../selectors/workpad';
import { isGroupId } from '../../components/workpad_page/integration_utils';
import { isGroupId } from '../../components/workpad_page/positioning_utils';

const { set, del, insert } = immutable;

Expand Down
22 changes: 16 additions & 6 deletions x-pack/legacy/plugins/canvas/types/canvas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@

import { ElementPosition } from './elements';

export interface CanvasAsset {
'@created': string;
id: string;
type: 'dataurl';
value: string;
}

export interface CanvasElement {
id: string;
position: ElementPosition;
Expand All @@ -25,13 +32,16 @@ export interface CanvasPage {
}

export interface CanvasWorkpad {
name: string;
id: string;
width: number;
height: number;
'@created': string;
'@timestamp': string;
assets: { [id: string]: CanvasAsset };
colors: string[];
css: string;
height: number;
id: string;
isWriteable: boolean;
name: string;
page: number;
pages: CanvasPage[];
colors: string[];
isWriteable: boolean;
width: number;
}
4 changes: 4 additions & 0 deletions x-pack/legacy/plugins/canvas/types/elements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,8 @@ export interface PositionedElement {
* AST of the Canvas expression for the element
*/
ast: ExpressionAST;
/**
* Applied filter
*/
filter: string;
}

0 comments on commit a9b16ba

Please sign in to comment.