[Canvas][tech-debt] Add Typescript to apps directory (#73766)
Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
parent
7dc33f9ba8
commit
c6c300e8f8
|
@ -6,8 +6,8 @@
|
|||
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
// @ts-expect-error untyped local
|
||||
import { ExportApp } from '../export_app';
|
||||
import { ExportApp } from '../export_app.component';
|
||||
import { CanvasWorkpad } from '../../../../../types';
|
||||
|
||||
jest.mock('style-it', () => ({
|
||||
it: (css: string, Component: any) => Component,
|
||||
|
@ -23,7 +23,7 @@ jest.mock('../../../../components/link', () => ({
|
|||
|
||||
describe('<ExportApp />', () => {
|
||||
test('renders as expected', () => {
|
||||
const sampleWorkpad = {
|
||||
const sampleWorkpad = ({
|
||||
id: 'my-workpad-abcd',
|
||||
css: '',
|
||||
pages: [
|
||||
|
@ -34,7 +34,7 @@ describe('<ExportApp />', () => {
|
|||
elements: [3, 4, 5, 6],
|
||||
},
|
||||
],
|
||||
};
|
||||
} as any) as CanvasWorkpad;
|
||||
|
||||
const page1 = mount(
|
||||
<ExportApp workpad={sampleWorkpad} selectedPageIndex={0} initializeWorkpad={() => {}} />
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* 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 React, { FC, useEffect } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
// @ts-expect-error untyped library
|
||||
import Style from 'style-it';
|
||||
// @ts-expect-error untyped local
|
||||
import { WorkpadPage } from '../../../components/workpad_page';
|
||||
import { Link } from '../../../components/link';
|
||||
import { CanvasWorkpad } from '../../../../types';
|
||||
|
||||
interface Props {
|
||||
workpad: CanvasWorkpad;
|
||||
selectedPageIndex: number;
|
||||
initializeWorkpad: () => void;
|
||||
}
|
||||
|
||||
export const ExportApp: FC<Props> = ({ workpad, selectedPageIndex, initializeWorkpad }) => {
|
||||
const { id, pages, height, width } = workpad;
|
||||
const activePage = pages[selectedPageIndex];
|
||||
const pageElementCount = activePage.elements.length;
|
||||
|
||||
useEffect(() => initializeWorkpad());
|
||||
|
||||
return (
|
||||
<div className="canvasExport" data-shared-page={selectedPageIndex + 1}>
|
||||
<div className="canvasExport__stage">
|
||||
<div className="canvasLayout__stageHeader">
|
||||
<Link name="loadWorkpad" params={{ id }}>
|
||||
Edit Workpad
|
||||
</Link>
|
||||
</div>
|
||||
{Style.it(
|
||||
workpad.css,
|
||||
<div className="canvasExport__stageContent" data-shared-items-count={pageElementCount}>
|
||||
<WorkpadPage
|
||||
isSelected
|
||||
key={activePage.id}
|
||||
pageId={activePage.id}
|
||||
height={height}
|
||||
width={width}
|
||||
registerLayout={() => {}}
|
||||
unregisterLayout={() => {}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
ExportApp.propTypes = {
|
||||
workpad: PropTypes.shape({
|
||||
id: PropTypes.string.isRequired,
|
||||
pages: PropTypes.array.isRequired,
|
||||
}).isRequired,
|
||||
selectedPageIndex: PropTypes.number.isRequired,
|
||||
initializeWorkpad: PropTypes.func.isRequired,
|
||||
};
|
|
@ -1,59 +0,0 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Style from 'style-it';
|
||||
import { WorkpadPage } from '../../../components/workpad_page';
|
||||
import { Link } from '../../../components/link';
|
||||
|
||||
export class ExportApp extends React.PureComponent {
|
||||
static propTypes = {
|
||||
workpad: PropTypes.shape({
|
||||
id: PropTypes.string.isRequired,
|
||||
pages: PropTypes.array.isRequired,
|
||||
}).isRequired,
|
||||
selectedPageIndex: PropTypes.number.isRequired,
|
||||
initializeWorkpad: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.props.initializeWorkpad();
|
||||
}
|
||||
|
||||
render() {
|
||||
const { workpad, selectedPageIndex } = this.props;
|
||||
const { pages, height, width } = workpad;
|
||||
const activePage = pages[selectedPageIndex];
|
||||
const pageElementCount = activePage.elements.length;
|
||||
|
||||
return (
|
||||
<div className="canvasExport" data-shared-page={selectedPageIndex + 1}>
|
||||
<div className="canvasExport__stage">
|
||||
<div className="canvasLayout__stageHeader">
|
||||
<Link name="loadWorkpad" params={{ id: this.props.workpad.id }}>
|
||||
Edit Workpad
|
||||
</Link>
|
||||
</div>
|
||||
{Style.it(
|
||||
workpad.css,
|
||||
<div className="canvasExport__stageContent" data-shared-items-count={pageElementCount}>
|
||||
<WorkpadPage
|
||||
isSelected
|
||||
key={activePage.id}
|
||||
pageId={activePage.id}
|
||||
height={height}
|
||||
width={width}
|
||||
registerLayout={() => {}}
|
||||
unregisterLayout={() => {}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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 { connect } from 'react-redux';
|
||||
import { initializeWorkpad } from '../../../state/actions/workpad';
|
||||
import { getWorkpad, getSelectedPageIndex } from '../../../state/selectors/workpad';
|
||||
import { ExportApp as Component } from './export_app.component';
|
||||
import { State } from '../../../../types';
|
||||
|
||||
export const ExportApp = connect(
|
||||
(state: State) => ({
|
||||
workpad: getWorkpad(state),
|
||||
selectedPageIndex: getSelectedPageIndex(state),
|
||||
}),
|
||||
(dispatch) => ({
|
||||
initializeWorkpad: () => dispatch(initializeWorkpad()),
|
||||
})
|
||||
)(Component);
|
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
* 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 { connect } from 'react-redux';
|
||||
import { compose, branch, renderComponent } from 'recompose';
|
||||
import { initializeWorkpad } from '../../../state/actions/workpad';
|
||||
import { getWorkpad, getSelectedPageIndex } from '../../../state/selectors/workpad';
|
||||
import { LoadWorkpad } from './load_workpad';
|
||||
import { ExportApp as Component } from './export_app';
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
workpad: getWorkpad(state),
|
||||
selectedPageIndex: getSelectedPageIndex(state),
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
initializeWorkpad() {
|
||||
dispatch(initializeWorkpad());
|
||||
},
|
||||
});
|
||||
|
||||
const branches = [branch(({ workpad }) => workpad == null, renderComponent(LoadWorkpad))];
|
||||
|
||||
export const ExportApp = compose(
|
||||
connect(mapStateToProps, mapDispatchToProps),
|
||||
...branches
|
||||
)(Component);
|
|
@ -4,6 +4,5 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
export const LoadWorkpad = () => <div>Load a workpad...</div>;
|
||||
export { ExportApp } from './export_app';
|
||||
export { ExportApp as ExportAppComponent } from './export_app.component';
|
|
@ -4,10 +4,15 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { Dispatch } from 'redux';
|
||||
// @ts-expect-error Untyped local
|
||||
import * as workpadService from '../../lib/workpad_service';
|
||||
import { setWorkpad } from '../../state/actions/workpad';
|
||||
// @ts-expect-error Untyped local
|
||||
import { fetchAllRenderables } from '../../state/actions/elements';
|
||||
// @ts-expect-error Untyped local
|
||||
import { setPage } from '../../state/actions/pages';
|
||||
// @ts-expect-error Untyped local
|
||||
import { setAssets } from '../../state/actions/assets';
|
||||
import { ExportApp } from './export';
|
||||
|
||||
|
@ -18,7 +23,13 @@ export const routes = [
|
|||
{
|
||||
name: 'exportWorkpad',
|
||||
path: '/pdf/:id/page/:page',
|
||||
action: (dispatch) => async ({ params, router }) => {
|
||||
action: (dispatch: Dispatch) => async ({
|
||||
params,
|
||||
// @ts-expect-error Fix when Router is typed.
|
||||
router,
|
||||
}: {
|
||||
params: { id: string; page: string };
|
||||
}) => {
|
||||
// load workpad if given a new id via url param
|
||||
const fetchedWorkpad = await workpadService.get(params.id);
|
||||
const pageNumber = parseInt(params.page, 10);
|
|
@ -4,12 +4,18 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, { FC } from 'react';
|
||||
import { EuiPage, EuiPageBody, EuiPageContent } from '@elastic/eui';
|
||||
// @ts-expect-error untyped local
|
||||
import { WorkpadManager } from '../../../components/workpad_manager';
|
||||
// @ts-expect-error untyped local
|
||||
import { setDocTitle } from '../../../lib/doc_title';
|
||||
|
||||
export const HomeApp = ({ onLoad = () => {} }) => {
|
||||
interface Props {
|
||||
onLoad: () => void;
|
||||
}
|
||||
|
||||
export const HomeApp: FC<Props> = ({ onLoad = () => {} }) => {
|
||||
onLoad();
|
||||
setDocTitle('Canvas');
|
||||
return (
|
|
@ -6,12 +6,10 @@
|
|||
|
||||
import { connect } from 'react-redux';
|
||||
import { resetWorkpad } from '../../../state/actions/workpad';
|
||||
import { HomeApp as Component } from './home_app';
|
||||
import { HomeApp as Component } from './home_app.component';
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
export const HomeApp = connect(null, (dispatch) => ({
|
||||
onLoad() {
|
||||
dispatch(resetWorkpad());
|
||||
},
|
||||
});
|
||||
|
||||
export const HomeApp = connect(null, mapDispatchToProps)(Component);
|
||||
}))(Component);
|
|
@ -4,6 +4,5 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
export const LoadWorkpad = () => <div>Load a workpad...</div>;
|
||||
export { HomeApp } from './home_app';
|
||||
export { HomeApp as HomeAppComponent } from './home_app.component';
|
|
@ -8,6 +8,7 @@ import * as home from './home';
|
|||
import * as workpad from './workpad';
|
||||
import * as exp from './export';
|
||||
|
||||
// @ts-expect-error Router and routes are not yet strongly typed
|
||||
export const routes = [].concat(workpad.routes, home.routes, exp.routes);
|
||||
|
||||
export const apps = [workpad.WorkpadApp, home.HomeApp, exp.ExportApp];
|
|
@ -4,17 +4,24 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { ErrorStrings } from '../../../i18n';
|
||||
import { Dispatch } from 'redux';
|
||||
// @ts-expect-error
|
||||
import * as workpadService from '../../lib/workpad_service';
|
||||
import { notifyService } from '../../services';
|
||||
import { getBaseBreadcrumb, getWorkpadBreadcrumb, setBreadcrumb } from '../../lib/breadcrumbs';
|
||||
// @ts-expect-error
|
||||
import { getDefaultWorkpad } from '../../state/defaults';
|
||||
import { setWorkpad } from '../../state/actions/workpad';
|
||||
// @ts-expect-error
|
||||
import { setAssets, resetAssets } from '../../state/actions/assets';
|
||||
// @ts-expect-error
|
||||
import { setPage } from '../../state/actions/pages';
|
||||
import { getWorkpad } from '../../state/selectors/workpad';
|
||||
// @ts-expect-error
|
||||
import { setZoomScale } from '../../state/actions/transient';
|
||||
import { ErrorStrings } from '../../../i18n';
|
||||
import { WorkpadApp } from './workpad_app';
|
||||
import { State } from '../../../types';
|
||||
|
||||
const { workpadRoutes: strings } = ErrorStrings;
|
||||
|
||||
|
@ -25,7 +32,8 @@ export const routes = [
|
|||
{
|
||||
name: 'createWorkpad',
|
||||
path: '/create',
|
||||
action: (dispatch) => async ({ router }) => {
|
||||
// @ts-expect-error Fix when Router is typed.
|
||||
action: (dispatch: Dispatch) => async ({ router }) => {
|
||||
const newWorkpad = getDefaultWorkpad();
|
||||
try {
|
||||
await workpadService.create(newWorkpad);
|
||||
|
@ -46,7 +54,13 @@ export const routes = [
|
|||
{
|
||||
name: 'loadWorkpad',
|
||||
path: '/:id(/page/:page)',
|
||||
action: (dispatch, getState) => async ({ params, router }) => {
|
||||
action: (dispatch: Dispatch, getState: () => State) => async ({
|
||||
params,
|
||||
// @ts-expect-error Fix when Router is typed.
|
||||
router,
|
||||
}: {
|
||||
params: { id: string; page?: string };
|
||||
}) => {
|
||||
// load workpad if given a new id via url param
|
||||
const state = getState();
|
||||
const currentWorkpad = getWorkpad(state);
|
||||
|
@ -70,10 +84,10 @@ export const routes = [
|
|||
|
||||
// fetch the workpad again, to get changes
|
||||
const workpad = getWorkpad(getState());
|
||||
const pageNumber = parseInt(params.page, 10);
|
||||
const pageNumber = params.page ? parseInt(params.page, 10) : null;
|
||||
|
||||
// no page provided, append current page to url
|
||||
if (isNaN(pageNumber)) {
|
||||
if (!pageNumber || isNaN(pageNumber)) {
|
||||
return router.redirectTo('loadWorkpad', { id: workpad.id, page: workpad.page + 1 });
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* 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 { connect } from 'react-redux';
|
||||
import { compose, branch, renderComponent } from 'recompose';
|
||||
import { selectToplevelNodes } from '../../../state/actions/transient';
|
||||
import { canUserWrite, getAppReady } from '../../../state/selectors/app';
|
||||
import { getWorkpad, isWriteable } from '../../../state/selectors/workpad';
|
||||
import { LoadWorkpad } from './load_workpad';
|
||||
import { WorkpadApp as Component } from './workpad_app';
|
||||
import { withElementsLoadedTelemetry } from './workpad_telemetry';
|
||||
|
||||
export { WORKPAD_CONTAINER_ID } from './workpad_app';
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
const appReady = getAppReady(state);
|
||||
|
||||
return {
|
||||
isWriteable: isWriteable(state) && canUserWrite(state),
|
||||
appReady: typeof appReady === 'object' ? appReady : { ready: appReady },
|
||||
workpad: getWorkpad(state),
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
deselectElement(ev) {
|
||||
ev && ev.stopPropagation();
|
||||
dispatch(selectToplevelNodes([]));
|
||||
},
|
||||
});
|
||||
|
||||
const branches = [branch(({ workpad }) => workpad == null, renderComponent(LoadWorkpad))];
|
||||
|
||||
export const WorkpadApp = compose(
|
||||
connect(mapStateToProps, mapDispatchToProps),
|
||||
...branches,
|
||||
withElementsLoadedTelemetry
|
||||
)(Component);
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { WorkpadApp } from './workpad_app';
|
||||
export { WorkpadApp as WorkpadAppComponent } from './workpad_app.component';
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* 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 React, { FC, MouseEventHandler, useRef } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Sidebar } from '../../../components/sidebar';
|
||||
import { Toolbar } from '../../../components/toolbar';
|
||||
// @ts-expect-error Untyped local
|
||||
import { Workpad } from '../../../components/workpad';
|
||||
import { WorkpadHeader } from '../../../components/workpad_header';
|
||||
import { CANVAS_LAYOUT_STAGE_CONTENT_SELECTOR } from '../../../../common/lib/constants';
|
||||
import { CommitFn } from '../../../../types';
|
||||
|
||||
export const WORKPAD_CONTAINER_ID = 'canvasWorkpadContainer';
|
||||
|
||||
interface Props {
|
||||
deselectElement?: MouseEventHandler;
|
||||
isWriteable: boolean;
|
||||
}
|
||||
|
||||
export const WorkpadApp: FC<Props> = ({ deselectElement, isWriteable }) => {
|
||||
const interactivePageLayout = useRef<CommitFn | null>(null); // future versions may enable editing on multiple pages => use array then
|
||||
|
||||
const registerLayout = (newLayout: CommitFn) => {
|
||||
if (interactivePageLayout.current !== newLayout) {
|
||||
interactivePageLayout.current = newLayout;
|
||||
}
|
||||
};
|
||||
|
||||
const unregisterLayout = (oldLayout: CommitFn) => {
|
||||
if (interactivePageLayout.current === oldLayout) {
|
||||
interactivePageLayout.current = null;
|
||||
}
|
||||
};
|
||||
|
||||
const commit = interactivePageLayout.current || (() => {});
|
||||
|
||||
return (
|
||||
<div className="canvasLayout">
|
||||
<div className="canvasLayout__rows">
|
||||
<div className="canvasLayout__cols">
|
||||
<div className="canvasLayout__stage">
|
||||
<div className="canvasLayout__stageHeader">
|
||||
<WorkpadHeader commit={commit} />
|
||||
</div>
|
||||
|
||||
<div
|
||||
id={CANVAS_LAYOUT_STAGE_CONTENT_SELECTOR}
|
||||
className={CANVAS_LAYOUT_STAGE_CONTENT_SELECTOR}
|
||||
onMouseDown={deselectElement}
|
||||
>
|
||||
{/* NOTE: canvasWorkpadContainer is used for exporting */}
|
||||
<div
|
||||
id={WORKPAD_CONTAINER_ID}
|
||||
className="canvasWorkpadContainer canvasLayout__stageContentOverflow"
|
||||
>
|
||||
<Workpad registerLayout={registerLayout} unregisterLayout={unregisterLayout} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{isWriteable && (
|
||||
<div className="canvasLayout__sidebar hide-for-sharing">
|
||||
<Sidebar commit={commit} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="canvasLayout__footer hide-for-sharing">
|
||||
<Toolbar />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
WorkpadApp.propTypes = {
|
||||
isWriteable: PropTypes.bool.isRequired,
|
||||
deselectElement: PropTypes.func,
|
||||
};
|
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Sidebar } from '../../../components/sidebar';
|
||||
import { Toolbar } from '../../../components/toolbar';
|
||||
import { Workpad } from '../../../components/workpad';
|
||||
import { WorkpadHeader } from '../../../components/workpad_header';
|
||||
import { CANVAS_LAYOUT_STAGE_CONTENT_SELECTOR } from '../../../../common/lib/constants';
|
||||
|
||||
export const WORKPAD_CONTAINER_ID = 'canvasWorkpadContainer';
|
||||
|
||||
export class WorkpadApp extends React.PureComponent {
|
||||
static propTypes = {
|
||||
isWriteable: PropTypes.bool.isRequired,
|
||||
deselectElement: PropTypes.func,
|
||||
};
|
||||
|
||||
interactivePageLayout = null; // future versions may enable editing on multiple pages => use array then
|
||||
|
||||
registerLayout(newLayout) {
|
||||
if (this.interactivePageLayout !== newLayout) {
|
||||
this.interactivePageLayout = newLayout;
|
||||
}
|
||||
}
|
||||
|
||||
unregisterLayout(oldLayout) {
|
||||
if (this.interactivePageLayout === oldLayout) {
|
||||
this.interactivePageLayout = null;
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { isWriteable, deselectElement } = this.props;
|
||||
|
||||
return (
|
||||
<div className="canvasLayout">
|
||||
<div className="canvasLayout__rows">
|
||||
<div className="canvasLayout__cols">
|
||||
<div className="canvasLayout__stage">
|
||||
<div className="canvasLayout__stageHeader">
|
||||
<WorkpadHeader commit={this.interactivePageLayout || (() => {})} />
|
||||
</div>
|
||||
|
||||
<div
|
||||
id={CANVAS_LAYOUT_STAGE_CONTENT_SELECTOR}
|
||||
className={CANVAS_LAYOUT_STAGE_CONTENT_SELECTOR}
|
||||
onMouseDown={deselectElement}
|
||||
>
|
||||
{/* NOTE: canvasWorkpadContainer is used for exporting */}
|
||||
<div
|
||||
id={WORKPAD_CONTAINER_ID}
|
||||
className="canvasWorkpadContainer canvasLayout__stageContentOverflow"
|
||||
>
|
||||
<Workpad
|
||||
registerLayout={this.registerLayout.bind(this)}
|
||||
unregisterLayout={this.unregisterLayout.bind(this)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{isWriteable && (
|
||||
<div className="canvasLayout__sidebar hide-for-sharing">
|
||||
<Sidebar />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="canvasLayout__footer hide-for-sharing">
|
||||
<Toolbar />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* 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 { MouseEventHandler } from 'react';
|
||||
import { Dispatch } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
// @ts-expect-error untyped local
|
||||
import { selectToplevelNodes } from '../../../state/actions/transient';
|
||||
import { canUserWrite } from '../../../state/selectors/app';
|
||||
import { getWorkpad, isWriteable } from '../../../state/selectors/workpad';
|
||||
import { WorkpadApp as Component } from './workpad_app.component';
|
||||
import { withElementsLoadedTelemetry } from './workpad_telemetry';
|
||||
import { State } from '../../../../types';
|
||||
|
||||
export { WORKPAD_CONTAINER_ID } from './workpad_app.component';
|
||||
|
||||
const mapDispatchToProps = (dispatch: Dispatch): { deselectElement: MouseEventHandler } => ({
|
||||
deselectElement: (ev) => {
|
||||
ev.stopPropagation();
|
||||
dispatch(selectToplevelNodes([]));
|
||||
},
|
||||
});
|
||||
|
||||
export const WorkpadApp = connect(
|
||||
(state: State) => ({
|
||||
isWriteable: isWriteable(state) && canUserWrite(state),
|
||||
workpad: getWorkpad(state),
|
||||
}),
|
||||
mapDispatchToProps
|
||||
)(withElementsLoadedTelemetry(Component));
|
|
@ -18,22 +18,25 @@ import { EditMenu } from './edit_menu';
|
|||
import { ElementMenu } from './element_menu';
|
||||
import { ShareMenu } from './share_menu';
|
||||
import { ViewMenu } from './view_menu';
|
||||
import { CommitFn } from '../../../types';
|
||||
|
||||
const { WorkpadHeader: strings } = ComponentStrings;
|
||||
|
||||
export interface Props {
|
||||
isWriteable: boolean;
|
||||
toggleWriteable: () => void;
|
||||
canUserWrite: boolean;
|
||||
commit: (type: string, payload: any) => any;
|
||||
commit: CommitFn;
|
||||
onSetWriteable?: (writeable: boolean) => void;
|
||||
}
|
||||
|
||||
export const WorkpadHeader: FunctionComponent<Props> = ({
|
||||
isWriteable,
|
||||
canUserWrite,
|
||||
toggleWriteable,
|
||||
commit,
|
||||
onSetWriteable = () => {},
|
||||
}) => {
|
||||
const toggleWriteable = () => onSetWriteable(!isWriteable);
|
||||
|
||||
const keyHandler = (action: string) => {
|
||||
if (action === 'EDITING') {
|
||||
toggleWriteable();
|
||||
|
@ -145,6 +148,7 @@ export const WorkpadHeader: FunctionComponent<Props> = ({
|
|||
|
||||
WorkpadHeader.propTypes = {
|
||||
isWriteable: PropTypes.bool,
|
||||
toggleWriteable: PropTypes.func,
|
||||
commit: PropTypes.func.isRequired,
|
||||
onSetWriteable: PropTypes.func,
|
||||
canUserWrite: PropTypes.bool,
|
||||
};
|
||||
|
|
|
@ -10,37 +10,16 @@ import { canUserWrite } from '../../state/selectors/app';
|
|||
import { getSelectedPage, isWriteable } from '../../state/selectors/workpad';
|
||||
import { setWriteable } from '../../state/actions/workpad';
|
||||
import { State } from '../../../types';
|
||||
import { WorkpadHeader as Component, Props as ComponentProps } from './workpad_header.component';
|
||||
import { WorkpadHeader as Component } from './workpad_header.component';
|
||||
|
||||
interface StateProps {
|
||||
isWriteable: boolean;
|
||||
canUserWrite: boolean;
|
||||
selectedPage: string;
|
||||
}
|
||||
|
||||
interface DispatchProps {
|
||||
setWriteable: (isWorkpadWriteable: boolean) => void;
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: State): StateProps => ({
|
||||
const mapStateToProps = (state: State) => ({
|
||||
isWriteable: isWriteable(state) && canUserWrite(state),
|
||||
canUserWrite: canUserWrite(state),
|
||||
selectedPage: getSelectedPage(state),
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch: Dispatch) => ({
|
||||
setWriteable: (isWorkpadWriteable: boolean) => dispatch(setWriteable(isWorkpadWriteable)),
|
||||
onSetWriteable: (isWorkpadWriteable: boolean) => dispatch(setWriteable(isWorkpadWriteable)),
|
||||
});
|
||||
|
||||
const mergeProps = (
|
||||
stateProps: StateProps,
|
||||
dispatchProps: DispatchProps,
|
||||
ownProps: ComponentProps
|
||||
): ComponentProps => ({
|
||||
...stateProps,
|
||||
...dispatchProps,
|
||||
...ownProps,
|
||||
toggleWriteable: () => dispatchProps.setWriteable(!stateProps.isWriteable),
|
||||
});
|
||||
|
||||
export const WorkpadHeader = connect(mapStateToProps, mapDispatchToProps, mergeProps)(Component);
|
||||
export const WorkpadHeader = connect(mapStateToProps, mapDispatchToProps)(Component);
|
||||
|
|
|
@ -76,3 +76,7 @@ export interface CanvasWorkpadBoundingBox {
|
|||
top: number;
|
||||
bottom: number;
|
||||
}
|
||||
|
||||
export type LayoutState = any;
|
||||
|
||||
export type CommitFn = (type: string, payload: any) => LayoutState;
|
||||
|
|
Loading…
Reference in a new issue