Skip to content

Commit eb71e59

Browse files
clintandrewhallelasticmachineCorey Robertson
authored
[pre-req] Convert Page Manager, Page Preview, DOM Preview (#70370)
Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> Co-authored-by: Corey Robertson <corey.robertson@elastic.co>
1 parent 4b06a4e commit eb71e59

File tree

15 files changed

+292
-224
lines changed

15 files changed

+292
-224
lines changed

x-pack/plugins/canvas/i18n/components.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,22 @@ export const ComponentStrings = {
567567
pageNumber,
568568
},
569569
}),
570+
getAddPageTooltip: () =>
571+
i18n.translate('xpack.canvas.pageManager.addPageTooltip', {
572+
defaultMessage: 'Add a new page to this workpad',
573+
}),
574+
getConfirmRemoveTitle: () =>
575+
i18n.translate('xpack.canvas.pageManager.confirmRemoveTitle', {
576+
defaultMessage: 'Remove Page',
577+
}),
578+
getConfirmRemoveDescription: () =>
579+
i18n.translate('xpack.canvas.pageManager.confirmRemoveDescription', {
580+
defaultMessage: 'Are you sure you want to remove this page?',
581+
}),
582+
getConfirmRemoveButtonLabel: () =>
583+
i18n.translate('xpack.canvas.pageManager.removeButtonLabel', {
584+
defaultMessage: 'Remove',
585+
}),
570586
},
571587
PagePreviewPageControls: {
572588
getClonePageAriaLabel: () =>

x-pack/plugins/canvas/public/components/dom_preview/dom_preview.js renamed to x-pack/plugins/canvas/public/components/dom_preview/dom_preview.tsx

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,38 @@
44
* you may not use this file except in compliance with the Elastic License.
55
*/
66

7-
import React from 'react';
7+
import React, { PureComponent } from 'react';
88
import PropTypes from 'prop-types';
99
import { debounce } from 'lodash';
1010

11-
export class DomPreview extends React.Component {
11+
interface Props {
12+
elementId: string;
13+
height: number;
14+
}
15+
16+
export class DomPreview extends PureComponent<Props> {
1217
static propTypes = {
1318
elementId: PropTypes.string.isRequired,
1419
height: PropTypes.number.isRequired,
1520
};
1621

22+
_container: HTMLDivElement | null = null;
23+
_content: HTMLDivElement | null = null;
24+
_observer: MutationObserver | null = null;
25+
_original: Element | null = null;
26+
_updateTimeout: number = 0;
27+
1728
componentDidMount() {
1829
this.update();
1930
}
2031

2132
componentWillUnmount() {
2233
clearTimeout(this._updateTimeout);
23-
this._observer && this._observer.disconnect(); // observer not guaranteed to exist
24-
}
2534

26-
_container = null;
27-
_content = null;
28-
_observer = null;
29-
_original = null;
30-
_updateTimeout = null;
35+
if (this._observer) {
36+
this._observer.disconnect(); // observer not guaranteed to exist
37+
}
38+
}
3139

3240
update = () => {
3341
if (!this._content || !this._container) {
@@ -38,7 +46,10 @@ export class DomPreview extends React.Component {
3846
const originalChanged = currentOriginal !== this._original;
3947

4048
if (originalChanged) {
41-
this._observer && this._observer.disconnect();
49+
if (this._observer) {
50+
this._observer.disconnect();
51+
}
52+
4253
this._original = currentOriginal;
4354

4455
if (this._original) {
@@ -50,12 +61,16 @@ export class DomPreview extends React.Component {
5061
this._observer.observe(this._original, config);
5162
} else {
5263
clearTimeout(this._updateTimeout); // to avoid the assumption that we fully control when `update` is called
53-
this._updateTimeout = setTimeout(this.update, 30);
64+
this._updateTimeout = window.setTimeout(this.update, 30);
5465
return;
5566
}
5667
}
5768

58-
const thumb = this._original.cloneNode(true);
69+
if (!this._original) {
70+
return;
71+
}
72+
73+
const thumb = this._original.cloneNode(true) as HTMLDivElement;
5974
thumb.id += '-thumb';
6075

6176
const originalStyle = window.getComputedStyle(this._original, null);
@@ -66,23 +81,27 @@ export class DomPreview extends React.Component {
6681
const scale = thumbHeight / originalHeight;
6782
const thumbWidth = originalWidth * scale;
6883

69-
if (this._content.hasChildNodes()) {
84+
if (this._content.firstChild) {
7085
this._content.removeChild(this._content.firstChild);
7186
}
87+
7288
this._content.appendChild(thumb);
7389

7490
this._content.style.cssText = `transform: scale(${scale}); transform-origin: top left;`;
7591
this._container.style.cssText = `width: ${thumbWidth}px; height: ${thumbHeight}px;`;
7692

7793
// Copy canvas data
7894
const originalCanvas = this._original.querySelectorAll('canvas');
79-
const thumbCanvas = thumb.querySelectorAll('canvas');
95+
const thumbCanvas = (thumb as Element).querySelectorAll('canvas');
8096

8197
// Cloned canvas elements are blank and need to be explicitly redrawn
8298
if (originalCanvas.length > 0) {
83-
Array.from(originalCanvas).map((img, i) =>
84-
thumbCanvas[i].getContext('2d').drawImage(img, 0, 0)
85-
);
99+
Array.from(originalCanvas).map((img, i) => {
100+
const context = thumbCanvas[i].getContext('2d');
101+
if (context) {
102+
context.drawImage(img, 0, 0);
103+
}
104+
});
86105
}
87106
};
88107

x-pack/plugins/canvas/public/components/dom_preview/index.js

Lines changed: 0 additions & 9 deletions
This file was deleted.

x-pack/plugins/canvas/public/components/page_preview/index.js renamed to x-pack/plugins/canvas/public/components/dom_preview/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
* you may not use this file except in compliance with the Elastic License.
55
*/
66

7-
export { PagePreview } from './page_preview';
7+
export { DomPreview } from './dom_preview';

x-pack/plugins/canvas/public/components/link/link.js

Lines changed: 0 additions & 63 deletions
This file was deleted.
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import React, { FC, MouseEvent, useContext } from 'react';
8+
import PropTypes from 'prop-types';
9+
import { EuiLink, EuiLinkProps } from '@elastic/eui';
10+
import { RouterContext } from '../router';
11+
12+
import { ComponentStrings } from '../../../i18n';
13+
14+
const { Link: strings } = ComponentStrings;
15+
16+
const isModifiedEvent = (ev: MouseEvent) =>
17+
!!(ev.metaKey || ev.altKey || ev.ctrlKey || ev.shiftKey);
18+
19+
interface Props {
20+
name: string;
21+
params: Record<string, any>;
22+
}
23+
24+
export const Link: FC<Props & EuiLinkProps> = ({
25+
onClick,
26+
target,
27+
name,
28+
params,
29+
children,
30+
...linkArgs
31+
}) => {
32+
const router = useContext(RouterContext);
33+
34+
if (router) {
35+
const navigateTo = (ev: MouseEvent<HTMLButtonElement, globalThis.MouseEvent>) => {
36+
if (onClick) {
37+
onClick(ev);
38+
}
39+
40+
if (
41+
!ev.defaultPrevented && // onClick prevented default
42+
ev.button === 0 && // ignore everything but left clicks
43+
!target && // let browser handle "target=_blank" etc.
44+
!isModifiedEvent(ev) // ignore clicks with modifier keys
45+
) {
46+
ev.preventDefault();
47+
router.navigateTo(name, params);
48+
}
49+
};
50+
51+
try {
52+
return (
53+
<EuiLink {...linkArgs} target={target} onClick={navigateTo}>
54+
{children}
55+
</EuiLink>
56+
);
57+
} catch (e) {
58+
return <div>{strings.getErrorMessage(e.message)}</div>;
59+
}
60+
}
61+
62+
return <div>{strings.getErrorMessage('Router Undefined')}</div>;
63+
};
64+
65+
Link.contextTypes = {
66+
router: PropTypes.object,
67+
};
68+
69+
Link.propTypes = {
70+
name: PropTypes.string.isRequired,
71+
params: PropTypes.object,
72+
};

x-pack/plugins/canvas/public/components/page_manager/index.js

Lines changed: 0 additions & 37 deletions
This file was deleted.
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import { Dispatch } from 'redux';
8+
import { connect } from 'react-redux';
9+
// @ts-expect-error untyped local
10+
import * as pageActions from '../../state/actions/pages';
11+
import { canUserWrite } from '../../state/selectors/app';
12+
import { getSelectedPage, getWorkpad, getPages, isWriteable } from '../../state/selectors/workpad';
13+
import { DEFAULT_WORKPAD_CSS } from '../../../common/lib/constants';
14+
import { PageManager as Component } from './page_manager';
15+
import { State } from '../../../types';
16+
17+
const mapStateToProps = (state: State) => ({
18+
isWriteable: isWriteable(state) && canUserWrite(state),
19+
pages: getPages(state),
20+
selectedPage: getSelectedPage(state),
21+
workpadId: getWorkpad(state).id,
22+
workpadCSS: getWorkpad(state).css || DEFAULT_WORKPAD_CSS,
23+
});
24+
25+
const mapDispatchToProps = (dispatch: Dispatch) => ({
26+
onAddPage: () => dispatch(pageActions.addPage()),
27+
onMovePage: (id: string, position: number) => dispatch(pageActions.movePage(id, position)),
28+
onRemovePage: (id: string) => dispatch(pageActions.removePage(id)),
29+
});
30+
31+
export const PageManager = connect(mapStateToProps, mapDispatchToProps)(Component);

0 commit comments

Comments
 (0)