Skip to content

Commit

Permalink
[WIP] Aero layout - code preview (kibana-canvas side) (elastic#631)
Browse files Browse the repository at this point in the history
* Chore: act on todo (raise error if there's more than one child), typos

* Refactor: remove a check no longer needed; other minor changes

* Feat - horrible and slow and glitchy but works

* Fix - removing erratic update due to autofiring keys (a browser behavior workaround)

* Chore - remove stale test code

* Refactor - move handlers out of class object

* Refactor - use recompose withState

* Refactor - use a commit callback

* Chore - use React event data instead of native event data

* Refactor - dealing with event identifiers in aeroelastic

* Chore: fix performance and other issues
Refactor: separate the page to its own directory
Chore: propTypes

* Refactor: selected

* Refactor: removing former state 1

* Refactor: removing former state 2

* Refactor: removing former state 3

* Refactor: removing former state 4

* Refactor: element_wrapper 2

* Refactor: element_wrapper 3

* Refactor: element_wrapper 4

* Refactor: element_wrapper 5

* Refactor: element_wrapper 6

* Breaking: getting rid of legacy interactable border

* Breaking: getting rid of legacy remove circle

* Breaking: getting rid of handlers?

* Chore: restoring overflow from hidden

(cherry picked from commit 69667c2)

* Refactor: new transient state to link to React store

* Feat: adding new element in react/redux now adds it to the layout

* Feat: removing new element in react/redux now removes it from the layout

* Chore: avoid unneeded selectElement call

* Feat: set position

* Feat: adding back the original borders

* Refactor: moving the border to its own component

* Feat: adding the remove element control

* Refactor - still getting stale state

* Refactor - no more stale state; selected status moved out of updater

* Refactor - do not supply props for the layout state initialization

* Refactor - don't persist selection if it was already selected

* Refactor - move layout state handling into page/index.js

* Refactor - move handlers out via recompose.withHandlers

* Chore: linting

* Refactor: moved out withLocalState

* Refactor: moved out withGlobalState

* Refactor: moved out withUpdateStates

* Refactor: other minor shuffles

* Feat: persist transform changes only when a mouse or keyboard gesture ends

* Feat: preparing for mouse rotation

(cherry picked from commit 2f8825e)

* chore: convert page into workpad_page

* chore: use the page id directly

* chore: set page isSelected based on global state

* Feat: alignment guide lines

* Chore: adding missing props after rebase

* Chore: simplifications; prep for additional layout

* Feat: separated out rotation

* chore: remove elements from props

they are unused and overwritten anyway

* chore: move aeroelastic state sync to middleware

easier to watch for actions and react to changes from both states

* chore: consolidate the WorkpadPage container

* chore: wrap aeroelastic in helper module

ensure single state, and internalize some of the selectors

* Fix: pass page for saving position change

* Feat: layout projected resize markers

* Feat: layout projected resize connector lines (blue border by section)

* Chore: post-rebase manual updates - less to scss

* Chore: post-rebase manual updates - reinstating handlers due to elastic#641

* Fix: solving various interaction and styling issues

* Feat: adopting the first round of the new visual design
Feat: Z-sorting to show up (required reload)
Fix: rotation handle shouldn't allow text selection

* Fix: the gotoPage action now also triggers a relayout (contents change)

* Fix: don't allow user-select on the workbook page, otherwise texts are selected while dragging (the element texts are not selectable anyway, because attempting to select text of an element will instead drag the element, so doesn't appear to need conditionalization)

* Fix: don't show annotations in full screen mode

* Fix: don't let mouse events start in full screen mode

* Fix: don't deselect elements while holding mousebutton down or dragging

* Fix: don't deselect elements when handling resize or rotate hotspots

* Fix: attach pointer event handlers to the global object (window) so things can be dragged outside the canvas div, the canvas DOM and even the web browser

* Fix: handle the case of deleting an element (delete interaction will eventually go away)

* Fix: select element on 1st click on initial load

* Chore: post-commit code cleanup

* Improv: round transform matrix values (works currently, as exposed functionality doesn't yet include 3D transforms)

* Fix: no editing
Chore: removed disused props

* Chore: no editing code regularization (better name)

* Fix: deselection of element works outside the canvas paper too

* Chore: reorder some lines for easier comparison to master

* Chore: remove obsolete classing

* Chore: dedicated delete handler, just for code comparison

* Fix: regression introduced with the previous 'click outside of canvas paper' commit

* Chore: calc the isSelected property similarly to preexisting master

* Fix: page preview to show all slides

* Fix: too fast page forward/backward raises an error

* Fix: all pages (and layouts) of a workbook are live simultaneously

* Chore: removed the commented-out lines that did the slide sorter view

* Perf: removed aero middleware hook for gotoPage as now the pages are preloaded, so, faster pagination

* Fix: further work on multipage support (switching workpads, adding pages)

* Fix: handle the appReady action

* Fix: image reveal drag&drop now doesn't attempt to be handled as native D & D

* Fix: don't lose the selected status if rotation handle is released away from the handle and the element

* Feat: adding deletion by Delete and Backspace keys

* Chore: removed disused props

* Chore: removed canvas__interactable-meta

* Chore: removed the remove hotspot interaction and the element_controls layer

* Chore: use the published version of aeroelastic

* Refactor: rename lib/aeroelastic to avoid ambiguity

* Refactor: move in the `aeroelastic` repo

Refactor: remove unneeded part of the repo

Refactor: aero flatten file tree

Refactor: one more thing to remove

Refactor: adopt prettier

Refactor: adopt prettier 2; remove debug line

Refactor: adopt prettier 3 - matrix ops

Refactor: adopt prettier 4 - layout

Fix: regression introduced with reduction final mapping

Chore: linting 1

Chore: linting 2

Chore: linting 3

Chore: linting 4

Chore: linting 5

Chore: linting 6
  • Loading branch information
monfera authored and Rashid Khan committed Jul 16, 2018
1 parent 9b07abb commit eba452f
Show file tree
Hide file tree
Showing 43 changed files with 2,612 additions and 685 deletions.
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -137,4 +137,4 @@
"sinon": "^4.5.0",
"through2": "^2.0.3"
}
}
}
22 changes: 22 additions & 0 deletions public/components/alignment_guide/alignment_guide.js
@@ -0,0 +1,22 @@
import React from 'react';
import PropTypes from 'prop-types';
import aero from '../../lib/aeroelastic';

export const AlignmentGuide = ({ transformMatrix, a, b }) => {
const newStyle = {
width: a * 2,
height: b * 2,
marginLeft: -a,
marginTop: -b,
background: 'magenta',
position: 'absolute',
transform: aero.dom.matrixToCSS(transformMatrix),
};
return <div className="canvas__alignment-guide canvas__interactable" style={newStyle} />;
};

AlignmentGuide.propTypes = {
transformMatrix: PropTypes.arrayOf(PropTypes.number).isRequired,
a: PropTypes.number.isRequired,
b: PropTypes.number.isRequired,
};
4 changes: 4 additions & 0 deletions public/components/alignment_guide/alignment_guide.scss
@@ -0,0 +1,4 @@
.canvas__alignment-guide {
transform-origin: center center; /* the default, only for clarity */
transform-style: preserve-3d;
}
4 changes: 4 additions & 0 deletions public/components/alignment_guide/index.js
@@ -0,0 +1,4 @@
import { pure } from 'recompose';
import { AlignmentGuide as Component } from './alignment_guide';

export const AlignmentGuide = pure(Component);
21 changes: 21 additions & 0 deletions public/components/border_connection/border_connection.js
@@ -0,0 +1,21 @@
import React from 'react';
import PropTypes from 'prop-types';
import aero from '../../lib/aeroelastic';

export const BorderConnection = ({ transformMatrix, a, b }) => {
const newStyle = {
width: a * 2,
height: b * 2,
marginLeft: -a,
marginTop: -b,
position: 'absolute',
transform: aero.dom.matrixToCSS(transformMatrix),
};
return <div className="canvas__border-connection" style={newStyle} />;
};

BorderConnection.propTypes = {
a: PropTypes.number.isRequired,
b: PropTypes.number.isRequired,
transformMatrix: PropTypes.arrayOf(PropTypes.number).isRequired,
};
11 changes: 11 additions & 0 deletions public/components/border_connection/border_connection.scss
@@ -0,0 +1,11 @@
.canvas__border-connection {
position: absolute;
top: 0;
width: 100%;
height: 100%;
pointer-events: none;
//box-shadow: inset 0 0 1px 2px $euiColorPrimary;
border-top: $euiBorderThin;
border-left: $euiBorderThin;
border-color: #d9d9d9;
}
4 changes: 4 additions & 0 deletions public/components/border_connection/index.js
@@ -0,0 +1,4 @@
import { pure } from 'recompose';
import { BorderConnection as Component } from './border_connection';

export const BorderConnection = pure(Component);
14 changes: 14 additions & 0 deletions public/components/border_resize_handle/border_resize_handle.js
@@ -0,0 +1,14 @@
import React from 'react';
import PropTypes from 'prop-types';
import aero from '../../lib/aeroelastic';

export const BorderResizeHandle = ({ transformMatrix }) => (
<div
className="canvas__border-resize-handle"
style={{ transform: aero.dom.matrixToCSS(transformMatrix) }}
/>
);

BorderResizeHandle.propTypes = {
transformMatrix: PropTypes.arrayOf(PropTypes.number).isRequired,
};
13 changes: 13 additions & 0 deletions public/components/border_resize_handle/border_resize_handle.scss
@@ -0,0 +1,13 @@
.canvas__border-resize-handle {
transform-origin: center center; /* the default, only for clarity */
transform-style: preserve-3d;
display: block;
position: absolute;
height: 8px;
width: 8px;
margin-left: -4px;
margin-top: -4px;
background-color: #fff;
border: 1px solid #666;
box-shadow: 0 2px 2px -1px rgba(153, 153, 153, 0.3), 0 1px 5px -2px rgba(153, 153, 153, 0.3);
}
4 changes: 4 additions & 0 deletions public/components/border_resize_handle/index.js
@@ -0,0 +1,4 @@
import { pure } from 'recompose';
import { BorderResizeHandle as Component } from './border_resize_handle';

export const BorderResizeHandle = pure(Component);
2 changes: 1 addition & 1 deletion public/components/dom_preview/dom_preview.js
Expand Up @@ -64,7 +64,7 @@ export class DomPreview extends React.Component {

this.content.style.cssText = `transform: scale(${scale}); transform-origin: top left; height: ${originalHeight}; width: ${originalWidth};`;

thumb.style.cssText = 'top: 0; left: 0;';
thumb.style.cssText = 'visibility: inherit;';
};

render() {
Expand Down
Expand Up @@ -32,6 +32,7 @@ export class ElementShareContainer extends React.PureComponent {
// dispatches a custom DOM event on the container when the element is complete
onComplete(() => {
clearTimeout(t);
if (!this.sharedItemRef) return; // without this, crazy fast forward/backward paging leads to an error
const ev = new Event('renderComplete');
this.sharedItemRef.dispatchEvent(ev);

Expand Down
63 changes: 0 additions & 63 deletions public/components/element_wrapper/element_controls.js

This file was deleted.

42 changes: 7 additions & 35 deletions public/components/element_wrapper/element_wrapper.js
@@ -1,18 +1,16 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Positionable } from '../positionable';
import { ElementControls } from './element_controls';
import { ElementContent } from '../element_content';

export class ElementWrapper extends React.PureComponent {
static propTypes = {
selectElement: PropTypes.func.isRequired,
removeElement: PropTypes.func.isRequired,
isSelected: PropTypes.bool,
state: PropTypes.string,
error: PropTypes.object,
renderable: PropTypes.object,
position: PropTypes.object.isRequired,
setPosition: PropTypes.func.isRequired,
transformMatrix: PropTypes.arrayOf(PropTypes.number).isRequired,
a: PropTypes.number.isRequired,
b: PropTypes.number.isRequired,
createHandlers: PropTypes.func.isRequired,
};

Expand All @@ -31,37 +29,11 @@ export class ElementWrapper extends React.PureComponent {
// wait until the handlers have been created
if (!this.state.handlers) return null;

const {
selectElement,
removeElement,
isSelected,
renderable,
position,
setPosition,
state,
} = this.props;
const { renderable, transformMatrix, a, b, state } = this.props;

return (
<Positionable position={position} onChange={setPosition} interact={isSelected}>
{/*
This is why we need this janky ElementControls thing:
Size will be passed to PositionableChild by Positionable
size={{ width: position.width, height: position.height }}
This keeps things fast, allowing Positionable to maintain a cache of the state without
writing it back to redux.
Its crap, I agree. I'm open to better solutions.
*/}
<ElementControls
selectElement={selectElement}
removeElement={removeElement}
isSelected={isSelected}
renderable={renderable}
state={state}
handlers={this.state.handlers}
/>
<Positionable transformMatrix={transformMatrix} a={a} b={b}>
<ElementContent renderable={renderable} state={state} handlers={this.state.handlers} />
</Positionable>
);
}
Expand Down
5 changes: 0 additions & 5 deletions public/components/element_wrapper/element_wrapper.scss
@@ -1,9 +1,4 @@
// It is up to the element to handle its overflow.
.canvas__workpad--element {
height: 100%;
width: 100%;
}

.canvas__element--content {
height: 100%;
width: 100%;
Expand Down
27 changes: 7 additions & 20 deletions public/components/element_wrapper/index.js
@@ -1,13 +1,7 @@
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { removeElement, setPosition } from '../../state/actions/elements';
import { selectElement } from '../../state/actions/transient';
import { getFullscreen, getEditing } from '../../state/selectors/app';
import {
getSelectedElementId,
getResolvedArgs,
getSelectedPage,
} from '../../state/selectors/workpad';
import { getResolvedArgs, getSelectedPage } from '../../state/selectors/workpad';
import { getState, getValue, getError } from '../../lib/resolved_arg';
import { ElementWrapper as Component } from './element_wrapper';
import { createHandlers as createHandlersWithDispatch } from './lib/handlers';
Expand All @@ -16,33 +10,27 @@ const mapStateToProps = (state, { element }) => ({
isFullscreen: getFullscreen(state),
isEditing: getEditing(state),
resolvedArg: getResolvedArgs(state, element.id, 'expressionRenderable'),
isSelected: element.id === getSelectedElementId(state),
selectedPage: getSelectedPage(state),
});

const mapDispatchToProps = (dispatch, { element }) => ({
selectElement: isInteractable => () => isInteractable && dispatch(selectElement(element.id)),
removeElement: pageId => () => dispatch(removeElement(element.id, pageId)),
setPosition: pageId => position => dispatch(setPosition(element.id, pageId, position)),
createHandlers: pageId => () => createHandlersWithDispatch(element, pageId, dispatch),
});

const mergeProps = (stateProps, dispatchProps, ownProps) => {
const { resolvedArg, selectedPage, isSelected, isFullscreen, isEditing } = stateProps;
const { resolvedArg, selectedPage } = stateProps;
const renderable = getValue(resolvedArg);
const { element } = ownProps;

return {
position: element.position,
setPosition: dispatchProps.setPosition(selectedPage),
selectElement: dispatchProps.selectElement(!isFullscreen && isEditing),
removeElement: dispatchProps.removeElement(selectedPage),
createHandlers: dispatchProps.createHandlers(selectedPage),
isSelected: isSelected,
state: getState(resolvedArg),
error: getError(resolvedArg),
renderable,
...ownProps,
transformMatrix: element.transformMatrix,
id: element.id,
a: element.a,
b: element.b,
createHandlers: dispatchProps.createHandlers(selectedPage),
};
};

Expand All @@ -51,6 +39,5 @@ export const ElementWrapper = connect(mapStateToProps, mapDispatchToProps, merge
ElementWrapper.propTypes = {
element: PropTypes.shape({
id: PropTypes.string.isRequired,
position: PropTypes.object.isRequired,
}).isRequired,
};
9 changes: 6 additions & 3 deletions public/components/page_manager/page_manager.scss
Expand Up @@ -82,9 +82,8 @@
height: ($euiSizeXXL + $euiSizeS) * 2;
}

.canvas--interactable-actions,
.canvas--interactable-meta,
.canvas--interactable-resize,
.canvas__interactable-actions,
.canvas__interactable-resize,
.canvas__element--remove-icon {
display: none;
}
Expand All @@ -101,4 +100,8 @@
color: $euiColorEmptyShade;
}
}

.canvas__positionable {
position: absolute;
}
}
6 changes: 2 additions & 4 deletions public/components/positionable/index.js
@@ -1,6 +1,4 @@
import { compose, withState } from 'recompose';
import { pure } from 'recompose';
import { Positionable as Component } from './positionable';

export const Positionable = compose(withState('position', 'setPosition', props => props.position))(
Component
);
export const Positionable = pure(Component);

0 comments on commit eba452f

Please sign in to comment.