mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
Reverting PR 42545 (for now) (#44277)
This commit is contained in:
parent
80a92a61ed
commit
910ae8dc8f
61 changed files with 198 additions and 35135 deletions
|
@ -7,29 +7,32 @@ files:
|
|||
- 'x-pack/legacy/plugins/rollup/**/*.s+(a|c)ss'
|
||||
- 'x-pack/legacy/plugins/security/**/*.s+(a|c)ss'
|
||||
- 'x-pack/legacy/plugins/canvas/**/*.s+(a|c)ss'
|
||||
ignore:
|
||||
- 'x-pack/legacy/plugins/canvas/external_runtime/**/*.s+(a|c)ss'
|
||||
rules:
|
||||
quotes:
|
||||
- 2
|
||||
- style: 'single'
|
||||
-
|
||||
style: 'single'
|
||||
# } else { style on one line, like our JS
|
||||
brace-style:
|
||||
- 2
|
||||
- style: '1tbs'
|
||||
-
|
||||
style: '1tbs'
|
||||
variable-name-format:
|
||||
- 2
|
||||
- convention: 'camelcase'
|
||||
-
|
||||
convention: 'camelcase'
|
||||
# Needs regex, right now we ignore
|
||||
class-name-format: 0
|
||||
# Order how you please
|
||||
property-sort-order: 0
|
||||
hex-notation:
|
||||
- 2
|
||||
- style: 'uppercase'
|
||||
-
|
||||
style: 'uppercase'
|
||||
mixin-name-format:
|
||||
- 2
|
||||
- allow-leading-underscore: false
|
||||
-
|
||||
allow-leading-underscore: false
|
||||
convention: 'camelcase'
|
||||
# Use none instead of 0 for no border
|
||||
border-zero:
|
||||
|
@ -44,7 +47,8 @@ rules:
|
|||
indentation: 2
|
||||
function-name-format:
|
||||
- 2
|
||||
- allow-leading-underscore: false
|
||||
-
|
||||
allow-leading-underscore: false
|
||||
convention: 'camelcase'
|
||||
# This removes the need for ::hover
|
||||
pseudo-element: 0
|
||||
|
@ -58,20 +62,23 @@ rules:
|
|||
force-attribute-nesting: 0
|
||||
no-qualifying-elements:
|
||||
- 2
|
||||
- # Allows input[type=search]
|
||||
-
|
||||
# Allows input[type=search]
|
||||
allow-element-with-attribute: 1
|
||||
# Files can end without a newline
|
||||
final-newline: 0
|
||||
# We use some rare duplicate property values for browser variance
|
||||
no-duplicate-properties:
|
||||
- 2
|
||||
- exclude:
|
||||
-
|
||||
exclude:
|
||||
- 'font-size'
|
||||
- 'word-break'
|
||||
# Put a line-break between sections of CSS, but allow quicky one-liners for legibility
|
||||
empty-line-between-blocks:
|
||||
- 2
|
||||
- allow-single-line-rulesets: 1
|
||||
-
|
||||
allow-single-line-rulesets: 1
|
||||
# Warns are nice for deprecations and development
|
||||
no-warn: 0
|
||||
# Transition all is useful in certain situations and there's no recent info to suggest slowdown
|
||||
|
|
|
@ -418,7 +418,6 @@
|
|||
"nock": "10.0.6",
|
||||
"node-sass": "^4.9.4",
|
||||
"normalize-path": "^3.0.0",
|
||||
"null-loader": "^3.0.0",
|
||||
"nyc": "^14.1.1",
|
||||
"pixelmatch": "4.0.2",
|
||||
"pkg-up": "^2.0.0",
|
||||
|
|
|
@ -577,14 +577,6 @@
|
|||
'@types/zen-observable',
|
||||
],
|
||||
},
|
||||
{
|
||||
groupSlug: 'archiver',
|
||||
groupName: 'archiver related packages',
|
||||
packageNames: [
|
||||
'archiver',
|
||||
'@types/archiver',
|
||||
],
|
||||
},
|
||||
{
|
||||
groupSlug: 'base64-js',
|
||||
groupName: 'base64-js related packages',
|
||||
|
|
|
@ -53,14 +53,6 @@ jest.mock(
|
|||
}
|
||||
);
|
||||
|
||||
// Disabling this test due to https://github.com/elastic/eui/issues/2242
|
||||
jest.mock(
|
||||
'../public/components/workpad_header/workpad_export/flyout/__examples__/external_embed_flyout.examples',
|
||||
() => {
|
||||
return 'Disabled Panel';
|
||||
}
|
||||
);
|
||||
|
||||
addSerializer(styleSheetSerializer);
|
||||
|
||||
// Initialize Storyshots and build the Jest Snapshots
|
||||
|
|
|
@ -6,16 +6,6 @@
|
|||
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,
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { RUNTIME_NAME } from '../../external_runtime/constants';
|
||||
|
||||
export const CANVAS_TYPE = 'canvas-workpad';
|
||||
export const CUSTOM_ELEMENT_TYPE = 'canvas-element';
|
||||
export const CANVAS_APP = 'canvas';
|
||||
|
@ -35,7 +33,3 @@ export const CANVAS_LAYOUT_STAGE_CONTENT_SELECTOR = `canvasLayout__stageContent`
|
|||
export const DATATABLE_COLUMN_TYPES = ['string', 'number', 'null', 'boolean', 'date'];
|
||||
export const LAUNCHED_FULLSCREEN = 'workpad-full-screen-launch';
|
||||
export const LAUNCHED_FULLSCREEN_AUTOPLAY = 'workpad-full-screen-launch-with-autoplay';
|
||||
export const API_ROUTE_SNAPSHOT_BASE = '/public/canvas';
|
||||
export const API_ROUTE_SNAPSHOT_ZIP = `${API_ROUTE_SNAPSHOT_BASE}/zip`;
|
||||
export const API_ROUTE_SNAPSHOT_RUNTIME = `${API_ROUTE_SNAPSHOT_BASE}/runtime`;
|
||||
export const API_ROUTE_SNAPSHOT_RUNTIME_DOWNLOAD = `${API_ROUTE_SNAPSHOT_BASE}/${RUNTIME_NAME}.js`;
|
||||
|
|
|
@ -15,13 +15,3 @@ export const fetch = axios.create({
|
|||
},
|
||||
timeout: FETCH_TIMEOUT,
|
||||
});
|
||||
|
||||
export const arrayBufferFetch = axios.create({
|
||||
responseType: 'arraybuffer',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'kbn-xsrf': 'professionally-crafted-string-of-text',
|
||||
},
|
||||
timeout: FETCH_TIMEOUT,
|
||||
});
|
|
@ -1,54 +0,0 @@
|
|||
# Canvas External Embeds
|
||||
|
||||

|
||||
|
||||
## Introduction
|
||||
|
||||
The external runtime is designed to render Canvas Workpads outside of Kibana in a different website or application. It uses the intermediate, "transient" state of a workpad, which is a JSON-blob state after element expressions are evaluated, but before the elements are rendered to the screen. This "transient" state, therefore, has no dependency or access to ES/Kibana data, making it lightweight and portable.
|
||||
|
||||
This directory contains the code necessary to build and test this external runtime.
|
||||
|
||||
## Building
|
||||
|
||||
Run `node scripts/external_runtime`. The runtime will be built and stored `external_runtime/build`.
|
||||
|
||||
## Development
|
||||
|
||||
To start the `webpack-dev-server` and test a workpad, simply run:
|
||||
|
||||
`/canvas: node scripts/external_runtime --dev --run`
|
||||
|
||||
A browser window should automatically open. If not, navigate to [`http://localhost:9001/`](http://localhost:9001).
|
||||
|
||||
### Customizing
|
||||
|
||||
The `index.html` file contains a call to the `CanvasEmbed` runtime. Currently, you can embed by object or by url:
|
||||
|
||||
```html
|
||||
<script src="kbn_canvas.js"></script>
|
||||
...
|
||||
<div kbn-canvas-embed="canvas" kbn-canvas-height="400" kbn-canvas-url="workpad.json"></div>
|
||||
<script type="text/javascript">
|
||||
KbnCanvas.embed();
|
||||
</script>
|
||||
```
|
||||
|
||||
There are two test workpads available: `/test/test.json` and `/test/austin.json`.
|
||||
|
||||
### Options
|
||||
|
||||
The [`api/embed.tsx`]('./api/embed') file contains the base class with available options to configure the embed:
|
||||
|
||||
```typescript
|
||||
height?: number;
|
||||
width?: number;
|
||||
page?: number;
|
||||
```
|
||||
|
||||
More options are available, but have not yet been exposed, (e.g. toolbar hide, etc)
|
||||
|
||||
## Testing
|
||||
|
||||
You can load a Workpad in Canvas, click "Export" and then "Embed on a website". You can then download a ZIP file with the runtime, the workpad and a sample HTML file.
|
||||
|
||||
After extracting to a directory, you can then start a small web server to load the HTML file. The easiest way, if you have `python` installed, is to run `python -m SimpleHTTPServer 8000` from the extracted directory.
|
|
@ -1,100 +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 { render } from 'react-dom';
|
||||
import { App } from '../components/app';
|
||||
import { CanvasRenderedWorkpad } from '../types';
|
||||
|
||||
export interface Options {
|
||||
/** The preferred height to scale the embedded workpad. If only `height` is
|
||||
* specified, `width` will be calculated by the workpad ratio. If both are
|
||||
* specified, the ratio will be overriden by an absolute size. */
|
||||
height?: number;
|
||||
/** The preferred width to scale the embedded workpad. If only `width` is
|
||||
* specified, `height` will be calculated by the workpad ratio. If both are
|
||||
* specified, the ratio will be overriden by an absolute size. */
|
||||
width?: number;
|
||||
/** The initial page to display. */
|
||||
page?: number;
|
||||
}
|
||||
|
||||
const PREFIX = 'kbn-canvas';
|
||||
const EMBED = `${PREFIX}-embed`;
|
||||
|
||||
const getAttributes = (element: Element, attributes: string[]) => {
|
||||
const result: { [key: string]: string } = {};
|
||||
attributes.forEach(attribute => {
|
||||
const key = `${PREFIX}-${attribute}`;
|
||||
const value = element.getAttribute(key);
|
||||
|
||||
if (value) {
|
||||
result[attribute] = value;
|
||||
element.removeAttribute(key);
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
const getWorkpad = async (url: string): Promise<CanvasRenderedWorkpad | null> => {
|
||||
const workpadResponse = await fetch(url);
|
||||
|
||||
if (workpadResponse.ok) {
|
||||
return await workpadResponse.json();
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const updateArea = async (area: Element) => {
|
||||
const { url, page: pageAttr, height: heightAttr, weight: widthAttr } = getAttributes(area, [
|
||||
'url',
|
||||
'page',
|
||||
'height',
|
||||
'width',
|
||||
]);
|
||||
|
||||
if (url) {
|
||||
const workpad = await getWorkpad(url);
|
||||
|
||||
if (workpad) {
|
||||
const page = pageAttr ? parseInt(pageAttr, 10) : null;
|
||||
let height = heightAttr ? parseInt(heightAttr, 10) : null;
|
||||
let width = widthAttr ? parseInt(widthAttr, 10) : null;
|
||||
|
||||
if (height && !width) {
|
||||
// If we have a height but no width, the width should honor the workpad ratio.
|
||||
width = workpad.width * (height / workpad.height);
|
||||
} else if (width && !height) {
|
||||
// If we have a width but no height, the height should honor the workpad ratio.
|
||||
height = workpad.height * (width / workpad.width);
|
||||
}
|
||||
|
||||
const options = {
|
||||
height: height || workpad.height,
|
||||
width: width || workpad.width,
|
||||
page: page ? page : workpad.page,
|
||||
};
|
||||
|
||||
area.classList.add('kbnCanvas');
|
||||
area.removeAttribute(EMBED);
|
||||
|
||||
render(<App workpad={workpad} {...options} />, area);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This is an abstract embedding component. It provides all of the scaling and
|
||||
* other option handling for embedding strategies.
|
||||
*/
|
||||
export const embed = () => {
|
||||
const embedAreas = document.querySelectorAll(`[${EMBED}]`);
|
||||
const validAreas = Array.from(embedAreas).filter(area => area.getAttribute(EMBED) === 'canvas');
|
||||
|
||||
validAreas.forEach(updateArea);
|
||||
};
|
|
@ -1,10 +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 'whatwg-fetch';
|
||||
import 'babel-polyfill';
|
||||
|
||||
export * from './embed';
|
|
@ -1,56 +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';
|
||||
// @ts-ignore Untyped package
|
||||
import { RenderFunctionsRegistry } from 'data/interpreter';
|
||||
import { Canvas } from './canvas';
|
||||
import {
|
||||
initialExternalEmbedState,
|
||||
ExternalEmbedStateProvider,
|
||||
ExternalEmbedState,
|
||||
} from '../context';
|
||||
// @ts-ignore Untyped local
|
||||
import { renderFunctions } from '../../canvas_plugin_src/renderers';
|
||||
import { CanvasRenderedWorkpad } from '../types';
|
||||
|
||||
interface Props {
|
||||
height: number;
|
||||
width: number;
|
||||
page: number;
|
||||
workpad: CanvasRenderedWorkpad;
|
||||
}
|
||||
|
||||
/**
|
||||
* The overall Embedded Workpad app; the highest-layer component.
|
||||
*/
|
||||
export const App = (props: Props) => {
|
||||
const { workpad, page, height, width } = props;
|
||||
|
||||
// Register all of the rendering experessions with a bespoke registry.
|
||||
const renderersRegistry = new RenderFunctionsRegistry();
|
||||
|
||||
renderFunctions.forEach((fn: Function | undefined) => {
|
||||
if (fn) {
|
||||
renderersRegistry.register(fn);
|
||||
}
|
||||
});
|
||||
|
||||
const initialState: ExternalEmbedState = {
|
||||
...initialExternalEmbedState,
|
||||
height,
|
||||
page,
|
||||
renderersRegistry,
|
||||
width,
|
||||
workpad,
|
||||
};
|
||||
|
||||
return (
|
||||
<ExternalEmbedStateProvider initialState={initialState}>
|
||||
<Canvas />
|
||||
</ExternalEmbedStateProvider>
|
||||
);
|
||||
};
|
|
@ -1,26 +0,0 @@
|
|||
:global html body .kbnCanvas {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
:global .kbnCanvas :local .root {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: height 1s;
|
||||
}
|
||||
|
||||
.container {
|
||||
composes: canvas from global;
|
||||
composes: canvasContainer from global;
|
||||
}
|
||||
|
||||
:global .kbnCanvas :local .container {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
:global .kbnCanvas :local .page {
|
||||
position: absolute;
|
||||
transform-origin: center center;
|
||||
}
|
|
@ -1,86 +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, { useState } from 'react';
|
||||
import { useExternalEmbedState, setPage, setScrubberVisible } from '../context';
|
||||
import { Page } from './page';
|
||||
import { Footer, FOOTER_HEIGHT } from './footer';
|
||||
import { getTimeInterval } from '../../public/lib/time_interval';
|
||||
|
||||
// @ts-ignore CSS Module
|
||||
import css from './canvas.module';
|
||||
|
||||
let timeout: number = 0;
|
||||
|
||||
/**
|
||||
* The "stage" for a workpad, which composes the toolbar and other components.
|
||||
*/
|
||||
export const Canvas = () => {
|
||||
const [
|
||||
{ workpad, height: containerHeight, width: containerWidth, page, settings, refs },
|
||||
dispatch,
|
||||
] = useExternalEmbedState();
|
||||
|
||||
if (!workpad) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { toolbar, autoplay } = settings;
|
||||
const { height, width, pages } = workpad;
|
||||
const ratio = Math.max(width / containerWidth, height / containerHeight);
|
||||
const transform = `scale3d(${containerHeight / (containerHeight * ratio)}, ${containerWidth /
|
||||
(containerWidth * ratio)}, 1)`;
|
||||
|
||||
const pageStyle = {
|
||||
height,
|
||||
transform,
|
||||
width,
|
||||
};
|
||||
|
||||
if (autoplay.enabled && autoplay.interval) {
|
||||
// We need to clear the timeout every time, even if it doesn't need to be or
|
||||
// it's null. Since one could select a different page from the scrubber at
|
||||
// any point, or change the interval, we need to make sure the interval is
|
||||
// killed on React re-render-- otherwise the pages will start bouncing around
|
||||
// as timeouts are accumulated.
|
||||
clearTimeout(timeout);
|
||||
|
||||
timeout = setTimeout(
|
||||
() => dispatch(setPage(page >= workpad.pages.length - 1 ? 0 : page + 1)),
|
||||
getTimeInterval(autoplay.interval)
|
||||
);
|
||||
}
|
||||
|
||||
const [toolbarHidden, setToolbarHidden] = useState(toolbar.autohide);
|
||||
const rootHeight = containerHeight + (toolbar.autohide ? 0 : FOOTER_HEIGHT);
|
||||
|
||||
const hideToolbar = (hidden: boolean) => {
|
||||
if (settings.toolbar.autohide) {
|
||||
if (hidden) {
|
||||
// Hide the scrubber if we hide the toolbar.
|
||||
dispatch(setScrubberVisible(false));
|
||||
}
|
||||
setToolbarHidden(hidden);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={css.root}
|
||||
style={{ height: rootHeight, width: containerWidth }}
|
||||
onMouseEnter={() => hideToolbar(false)}
|
||||
onMouseLeave={() => hideToolbar(true)}
|
||||
ref={refs.stage}
|
||||
>
|
||||
<div className={css.container} style={{ height: containerHeight, width: containerWidth }}>
|
||||
<div className={css.page} style={pageStyle}>
|
||||
<Page page={pages[page]} />
|
||||
</div>
|
||||
</div>
|
||||
<Footer hidden={toolbarHidden} />
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -1,27 +0,0 @@
|
|||
@import '@elastic/eui/src/global_styling/variables/_size.scss';
|
||||
@import '@elastic/eui/src/global_styling/variables/_colors.scss';
|
||||
|
||||
:global .kbnCanvas :local .root .bar {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.bar {
|
||||
composes: euiBottomBar from global;
|
||||
}
|
||||
|
||||
:global .kbnCanvas :local .bar {
|
||||
transition: bottom 0.25s;
|
||||
padding: $euiSizeM;
|
||||
}
|
||||
|
||||
:global .kbnCanvas :local .title {
|
||||
overflow: hidden;
|
||||
min-width: 0;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
:global .kbnCanvas .euiIcon__fillNegative {
|
||||
fill: $euiColorGhost !important;
|
||||
}
|
|
@ -1,61 +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 { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
import { useExternalEmbedState, setScrubberVisible } from '../../context';
|
||||
import { Scrubber } from './scrubber';
|
||||
import { Title } from './title';
|
||||
import { PageControls } from './page_controls';
|
||||
import { Settings } from './settings';
|
||||
|
||||
// @ts-ignore CSS Module
|
||||
import css from './footer.module';
|
||||
|
||||
export const FOOTER_HEIGHT = 48;
|
||||
|
||||
interface Props {
|
||||
hidden?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* The footer of the Embedded Workpad.
|
||||
*/
|
||||
export const Footer = ({ hidden = false }: Props) => {
|
||||
const [{ workpad, settings }] = useExternalEmbedState();
|
||||
if (!workpad) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { autohide } = settings.toolbar;
|
||||
|
||||
// If autohide is enabled, and the toolbar is hidden, set the scrubber
|
||||
// visibility to hidden. This is useful for state changes where one
|
||||
// sets the footer to hidden, and the scrubber would be left open with
|
||||
// no toolbar.
|
||||
if (autohide && hidden) {
|
||||
setScrubberVisible(false);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={css.root} style={{ height: FOOTER_HEIGHT }}>
|
||||
<Scrubber />
|
||||
<div className={css.bar} style={{ bottom: autohide && hidden ? -FOOTER_HEIGHT : 0 }}>
|
||||
<EuiFlexGroup gutterSize="none">
|
||||
<EuiFlexItem className={css.title}>
|
||||
<Title />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<PageControls />
|
||||
<Settings />
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -1,7 +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.
|
||||
*/
|
||||
|
||||
export * from './footer';
|
|
@ -1,62 +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 { EuiFlexGroup, EuiFlexItem, EuiButtonIcon, EuiButtonEmpty, EuiText } from '@elastic/eui';
|
||||
import { useExternalEmbedState, setScrubberVisible, setPage, setAutoplay } from '../../context';
|
||||
|
||||
/**
|
||||
* The page count and paging controls within the footer of the Embedded Workpad.
|
||||
*/
|
||||
export const PageControls = () => {
|
||||
const [{ workpad, footer, page }, dispatch] = useExternalEmbedState();
|
||||
|
||||
if (!workpad) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { isScrubberVisible } = footer;
|
||||
|
||||
const toggleScrubber = () => {
|
||||
dispatch(setAutoplay(false));
|
||||
dispatch(setScrubberVisible(!isScrubberVisible));
|
||||
};
|
||||
|
||||
const setPageNumber = (number: number) => dispatch(setPage(number));
|
||||
const currentPage = page + 1;
|
||||
const totalPages = workpad.pages.length;
|
||||
|
||||
return (
|
||||
<EuiFlexGroup alignItems="center" gutterSize="none" style={{ margin: '0 12px' }}>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButtonIcon
|
||||
color="ghost"
|
||||
onClick={() => setPageNumber(page - 1)}
|
||||
iconType="arrowLeft"
|
||||
disabled={currentPage <= 1}
|
||||
aria-label="Previous Page"
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButtonEmpty color="ghost" size="s" onClick={toggleScrubber}>
|
||||
<EuiText color="ghost" size="s">
|
||||
Page {currentPage}
|
||||
{totalPages > 1 ? ` of ${totalPages}` : null}
|
||||
</EuiText>
|
||||
</EuiButtonEmpty>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButtonIcon
|
||||
color="ghost"
|
||||
onClick={() => setPageNumber(page + 1)}
|
||||
iconType="arrowRight"
|
||||
disabled={currentPage >= totalPages}
|
||||
aria-label="Next Page"
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
};
|
|
@ -1,15 +0,0 @@
|
|||
@import '@elastic/eui/src/global_styling/variables/_size.scss';
|
||||
|
||||
:global .kbnCanvas :local .root {
|
||||
margin: 0 $euiSizeS;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
:global .kbnCanvas :local .root :global .canvasPage {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
:global .kbnCanvas :local .preview {
|
||||
pointer-events: none;
|
||||
transform-origin: top left;
|
||||
}
|
|
@ -1,55 +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 { useExternalEmbedState } from '../../context';
|
||||
import { Page } from '../page';
|
||||
import { setPage } from '../../context/actions';
|
||||
import { CanvasRenderedPage } from '../../types';
|
||||
|
||||
// @ts-ignore CSS Module
|
||||
import css from './page_preview.module';
|
||||
|
||||
interface Props {
|
||||
number: number;
|
||||
height: number;
|
||||
page: CanvasRenderedPage;
|
||||
}
|
||||
|
||||
/**
|
||||
* The small preview of the page shown within the `Scrubber`.
|
||||
*/
|
||||
export const PagePreview = ({ number, page, height }: Props) => {
|
||||
const [{ workpad }, dispatch] = useExternalEmbedState();
|
||||
if (!workpad) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const onClick = (index: number) => dispatch(setPage(index));
|
||||
const { height: workpadHeight, width: workpadWidth } = workpad;
|
||||
const scale = height / workpadHeight;
|
||||
const style = {
|
||||
height: workpadHeight * scale,
|
||||
width: workpadWidth * scale,
|
||||
};
|
||||
const transform = {
|
||||
...style,
|
||||
transform: `scale3d(${scale}, ${scale}, 1)`,
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={css.root}
|
||||
onClick={() => onClick(number)}
|
||||
onKeyPress={() => onClick(number)}
|
||||
style={style}
|
||||
>
|
||||
<div className={css.preview} style={transform}>
|
||||
<Page page={page} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -1,26 +0,0 @@
|
|||
@import '@elastic/eui/src/global_styling/variables/_size.scss';
|
||||
@import '@elastic/eui/src/global_styling/variables/_colors.scss';
|
||||
@import '@elastic/eui/src/global_styling/mixins/_helpers.scss';
|
||||
|
||||
:global .kbnCanvas :local .root {
|
||||
background: $euiColorGhost;
|
||||
position: absolute;
|
||||
bottom: -172px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: $euiSizeS 0 ($euiSizeL * 2) 0;
|
||||
transition: bottom 0.25s;
|
||||
height: 172px;
|
||||
}
|
||||
|
||||
:global .kbnCanvas :local .visible {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
:global .kbnCanvas :local .slideContainer {
|
||||
@include euiScrollBar;
|
||||
display: flex;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
width: 100%;
|
||||
}
|
|
@ -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 React from 'react';
|
||||
import classnames from 'classnames';
|
||||
import { useExternalEmbedState } from '../../context';
|
||||
import { PagePreview } from './page_preview';
|
||||
|
||||
// @ts-ignore CSS Module
|
||||
import css from './scrubber.module';
|
||||
|
||||
const THUMBNAIL_HEIGHT = 100;
|
||||
|
||||
/**
|
||||
* The panel of previews of the pages in the workpad, allowing one to select and
|
||||
* navigate to a specific page.
|
||||
*/
|
||||
export const Scrubber = () => {
|
||||
const [{ workpad, footer }] = useExternalEmbedState();
|
||||
|
||||
if (!workpad) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { pages } = workpad;
|
||||
const { isScrubberVisible } = footer;
|
||||
const className = isScrubberVisible ? classnames(css.root, css.visible) : css.root;
|
||||
|
||||
const slides = pages.map((page, index) => (
|
||||
<PagePreview key={page.id} page={page} number={index} height={THUMBNAIL_HEIGHT} />
|
||||
));
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
<div className={css.slideContainer}>{slides}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -1,38 +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 { EuiHorizontalRule, EuiSwitch } from '@elastic/eui';
|
||||
import { useExternalEmbedState, setAutoplay, setAutoplayInterval } from '../../../context';
|
||||
import { createTimeInterval } from '../../../../public/lib/time_interval';
|
||||
// @ts-ignore Untyped local
|
||||
import { CustomInterval } from '../../../../public/components/workpad_header/control_settings/custom_interval';
|
||||
|
||||
/**
|
||||
* The panel used to configure Autolay in Embedded Workpads.
|
||||
*/
|
||||
export const AutoplaySettings = () => {
|
||||
const [{ settings }, dispatch] = useExternalEmbedState();
|
||||
|
||||
const { autoplay } = settings;
|
||||
|
||||
return (
|
||||
<div style={{ padding: 16 }}>
|
||||
<EuiSwitch
|
||||
name="cycle"
|
||||
id="cycle"
|
||||
label="Cycle Slides"
|
||||
checked={autoplay.enabled}
|
||||
onChange={() => dispatch(setAutoplay(!autoplay.enabled))}
|
||||
/>
|
||||
<EuiHorizontalRule margin="m" />
|
||||
<CustomInterval
|
||||
defaultValue={autoplay.interval}
|
||||
onSubmit={(value: number) => dispatch(setAutoplayInterval(createTimeInterval(value)))}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -1,7 +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.
|
||||
*/
|
||||
|
||||
export * from './settings';
|
|
@ -1,98 +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, { useState } from 'react';
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiButtonIcon, EuiPopover, EuiContextMenu } from '@elastic/eui';
|
||||
import { useExternalEmbedState } from '../../../context';
|
||||
// @ts-ignore Untyped local
|
||||
import { CustomInterval } from '../../../../public/components/workpad_header/control_settings/custom_interval';
|
||||
import { ToolbarSettings } from './toolbar_settings';
|
||||
import { AutoplaySettings } from './autoplay_settings';
|
||||
|
||||
// @ts-ignore CSS Module
|
||||
import css from './settings.module';
|
||||
|
||||
/**
|
||||
* The Settings Popover for External Workpads.
|
||||
*/
|
||||
export const Settings = () => {
|
||||
const [{ workpad, refs }] = useExternalEmbedState();
|
||||
|
||||
if (!workpad) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const [isPopoverOpen, setPopoverOpen] = useState(false);
|
||||
const button = (
|
||||
<EuiButtonIcon
|
||||
color="ghost"
|
||||
iconType="gear"
|
||||
aria-label="Settings"
|
||||
onClick={() => setPopoverOpen(!isPopoverOpen)}
|
||||
/>
|
||||
);
|
||||
|
||||
const flattenPanelTree = (tree: any, array: any[] = []) => {
|
||||
array.push(tree);
|
||||
|
||||
if (tree.items) {
|
||||
tree.items.forEach((item: any) => {
|
||||
if (item.panel) {
|
||||
flattenPanelTree(item.panel, array);
|
||||
item.panel = item.panel.id;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return array;
|
||||
};
|
||||
|
||||
const panels = flattenPanelTree({
|
||||
id: 0,
|
||||
title: 'Settings',
|
||||
items: [
|
||||
{
|
||||
name: 'Auto Play',
|
||||
icon: 'play',
|
||||
panel: {
|
||||
id: 1,
|
||||
title: 'Auto Play',
|
||||
content: <AutoplaySettings />,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Toolbar',
|
||||
icon: 'boxesHorizontal',
|
||||
panel: {
|
||||
id: 2,
|
||||
title: 'Toolbar',
|
||||
content: <ToolbarSettings onChange={() => setPopoverOpen(false)} />,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
return (
|
||||
<EuiFlexGroup alignItems="flexEnd" justifyContent="center" direction="column" gutterSize="none">
|
||||
<EuiFlexItem grow={false}>
|
||||
{/*
|
||||
//@ts-ignore EuiPopover missing insert property */}
|
||||
<EuiPopover
|
||||
closePopover={() => setPopoverOpen(false)}
|
||||
id="settings"
|
||||
isOpen={isPopoverOpen}
|
||||
button={button}
|
||||
panelPaddingSize="none"
|
||||
withTitle
|
||||
anchorPosition="upRight"
|
||||
insert={{ sibling: refs.stage.current, position: 'after' }}
|
||||
>
|
||||
<EuiContextMenu initialPanelId={0} panels={panels} />
|
||||
</EuiPopover>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
};
|
|
@ -1,42 +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 { EuiSwitch, EuiFormRow } from '@elastic/eui';
|
||||
import { useExternalEmbedState, setToolbarAutohide } from '../../../context';
|
||||
|
||||
// @ts-ignore CSS Module
|
||||
import css from './settings.module';
|
||||
|
||||
interface Props {
|
||||
onChange?: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* The settings panel for the Toolbar of an Embedded Workpad.
|
||||
*/
|
||||
export const ToolbarSettings = ({ onChange = () => {} }: Props) => {
|
||||
const [{ settings }, dispatch] = useExternalEmbedState();
|
||||
|
||||
const { toolbar } = settings;
|
||||
|
||||
return (
|
||||
<div style={{ padding: 16 }}>
|
||||
<EuiFormRow helpText="Hide the toolbar when the mouse is not within the Canvas?">
|
||||
<EuiSwitch
|
||||
name="toolbarHide"
|
||||
id="toolbarHide"
|
||||
label="Hide Toolbar"
|
||||
checked={toolbar.autohide}
|
||||
onChange={() => {
|
||||
onChange();
|
||||
dispatch(setToolbarAutohide(!toolbar.autohide));
|
||||
}}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -1,33 +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 { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiText } from '@elastic/eui';
|
||||
import { useExternalEmbedState } from '../../context';
|
||||
|
||||
/**
|
||||
* The title of the workpad displayed in the right-hand of the footer.
|
||||
*/
|
||||
export const Title = () => {
|
||||
const [{ workpad }] = useExternalEmbedState();
|
||||
|
||||
if (!workpad) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<EuiFlexGroup gutterSize="s" justifyContent="flexStart" alignItems="center">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiIcon type="logoKibana" size="m" />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false} style={{ minWidth: 0 }}>
|
||||
<EuiText color="ghost" size="s">
|
||||
<div className="eui-textTruncate">{workpad.name}</div>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
};
|
|
@ -1,6 +0,0 @@
|
|||
.root {
|
||||
composes: canvasPage from global;
|
||||
composes: canvasInteractivePage from global;
|
||||
composes: kbn-resetFocusState from global;
|
||||
overflow: 'hidden';
|
||||
}
|
|
@ -1,37 +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 { RenderedElement } from './rendered_element';
|
||||
import { useExternalEmbedState } from '../context';
|
||||
import { CanvasRenderedPage, CanvasRenderedElement } from '../types';
|
||||
|
||||
// @ts-ignore CSS Module
|
||||
import css from './page.module';
|
||||
|
||||
interface Props {
|
||||
page: CanvasRenderedPage;
|
||||
}
|
||||
|
||||
export const Page = (props: Props) => {
|
||||
const [{ workpad }] = useExternalEmbedState();
|
||||
if (!workpad) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { height, width, id } = workpad;
|
||||
const { elements, style } = props.page;
|
||||
|
||||
const output = elements.map((element: CanvasRenderedElement, index) => (
|
||||
<RenderedElement key={element.id} element={element} number={index + 1} />
|
||||
));
|
||||
|
||||
return (
|
||||
<div id={`page-${id}`} className={css.root} style={{ height, width, ...style }}>
|
||||
{output}
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -1,19 +0,0 @@
|
|||
:global .kbnCanvas :local .root,
|
||||
:global .kbnCanvas :local .render {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.container {
|
||||
composes: canvas__element from global;
|
||||
composes: canvasElement from global;
|
||||
}
|
||||
|
||||
.content {
|
||||
composes: canvasElement__content from global;
|
||||
}
|
||||
|
||||
.renderContainer {
|
||||
composes: canvasWorkpad--element_render from global;
|
||||
composes: canvasRenderEl from global;
|
||||
}
|
|
@ -1,88 +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';
|
||||
// @ts-ignore Untyped library
|
||||
import Style from 'style-it';
|
||||
// @ts-ignore Untyped local
|
||||
import { Positionable } from '../../public/components/positionable/positionable';
|
||||
// @ts-ignore Untyped local
|
||||
import { elementToShape } from '../../public/components/workpad_page/utils';
|
||||
import { CanvasRenderedElement } from '../types';
|
||||
import { ExternalEmbedContext } from '../context';
|
||||
|
||||
// @ts-ignore CSS Module
|
||||
import css from './rendered_element.module';
|
||||
|
||||
interface Props {
|
||||
element: CanvasRenderedElement;
|
||||
number?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* A Rendered Element is different from an Element added to a Canvas Workpad. A
|
||||
* Rendered Element has actually be evaluated already to gather any data from
|
||||
* datasources, and is just a simple expression to render the result. This
|
||||
* component renders that "transient" element state.
|
||||
*/
|
||||
export class RenderedElement extends React.PureComponent<Props> {
|
||||
static contextType = ExternalEmbedContext;
|
||||
protected ref: React.RefObject<HTMLDivElement>;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.ref = React.createRef();
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const [{ renderersRegistry }] = this.context;
|
||||
const { element } = this.props;
|
||||
const { expressionRenderable } = element;
|
||||
const { value } = expressionRenderable;
|
||||
const { as } = value;
|
||||
const fn = renderersRegistry.get(as);
|
||||
|
||||
try {
|
||||
// TODO: These are stubbed, but may need implementation.
|
||||
fn.render(this.ref.current, value.value, {
|
||||
done: () => {},
|
||||
onDestroy: () => {},
|
||||
onResize: () => {},
|
||||
setFilter: () => {},
|
||||
getFilter: () => {},
|
||||
});
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(e.message);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { element, number } = this.props;
|
||||
const shape = elementToShape(element, number || 1);
|
||||
const { id, expressionRenderable, position } = element;
|
||||
const { value } = expressionRenderable;
|
||||
const { as, css: elementCSS, containerStyle } = value;
|
||||
const { height, width } = position;
|
||||
|
||||
return (
|
||||
<Positionable height={height} width={width} transformMatrix={shape.transformMatrix}>
|
||||
<div className={css.root}>
|
||||
{Style.it(
|
||||
elementCSS,
|
||||
<div className={css.container} style={{ ...containerStyle }}>
|
||||
<div className={css.content}>
|
||||
<div className={css.renderContainer}>
|
||||
<div key={id} ref={this.ref} data-renderer={as} className={css.render} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Positionable>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,13 +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.
|
||||
*/
|
||||
|
||||
export const KIBANA_ROOT: string;
|
||||
export const LIBRARY_NAME: string;
|
||||
export const RUNTIME_FILE: string;
|
||||
export const RUNTIME_NAME: string;
|
||||
export const RUNTIME_OUTPUT: string;
|
||||
export const RUNTIME_SRC: string;
|
||||
export const STATS_OUTPUT: string;
|
|
@ -1,25 +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.
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
|
||||
const LIBRARY_NAME = 'KbnCanvas';
|
||||
const RUNTIME_NAME = 'kbn_canvas';
|
||||
const KIBANA_ROOT = path.resolve(__dirname, '../../../../..');
|
||||
const RUNTIME_SRC = path.resolve(KIBANA_ROOT, 'x-pack/legacy/plugins/canvas/external_runtime');
|
||||
const RUNTIME_OUTPUT = path.resolve(RUNTIME_SRC, 'build');
|
||||
const RUNTIME_FILE = path.resolve(RUNTIME_OUTPUT, RUNTIME_NAME + '.js');
|
||||
const STATS_OUTPUT = path.resolve(RUNTIME_OUTPUT, 'webpack_stats.json');
|
||||
|
||||
module.exports = {
|
||||
KIBANA_ROOT,
|
||||
LIBRARY_NAME,
|
||||
RUNTIME_FILE,
|
||||
RUNTIME_NAME,
|
||||
RUNTIME_OUTPUT,
|
||||
RUNTIME_SRC,
|
||||
STATS_OUTPUT,
|
||||
};
|
|
@ -1,100 +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 { CanvasRenderedWorkpad } from '../types';
|
||||
|
||||
/**
|
||||
* This enumeration applies a strong type to all of the actions that can be
|
||||
* triggered from the interface.
|
||||
*/
|
||||
export enum ExternalEmbedActions {
|
||||
SET_WORKPAD = 'SET_WORKPAD',
|
||||
SET_PAGE = 'SET_PAGE',
|
||||
SET_SCRUBBER_VISIBLE = 'SET_SCRUBBER_VISIBLE',
|
||||
SET_AUTOPLAY = 'SET_AUTOPLAY',
|
||||
SET_AUTOPLAY_ANIMATE = 'SET_AUTOPLAY_ANIMATE',
|
||||
SET_AUTOPLAY_INTERVAL = 'SET_AUTOPLAY_INTERVAL',
|
||||
SET_TOOLBAR_AUTOHIDE = 'SET_TOOLBAR_AUTOHIDE',
|
||||
}
|
||||
|
||||
interface FluxAction<T, P> {
|
||||
type: T;
|
||||
payload: P;
|
||||
}
|
||||
|
||||
const createAction = <T extends ExternalEmbedActions, P>(
|
||||
type: T,
|
||||
payload: P
|
||||
): FluxAction<T, P> => ({
|
||||
type,
|
||||
payload,
|
||||
});
|
||||
|
||||
/**
|
||||
* Set the current `CanvasRenderedWorkpad`.
|
||||
* @param workpad A `CanvasRenderedWorkpad` to display.
|
||||
*/
|
||||
export const setWorkpad = (workpad: CanvasRenderedWorkpad) =>
|
||||
createAction(ExternalEmbedActions.SET_WORKPAD, { workpad });
|
||||
|
||||
/**
|
||||
* Set the current page to display
|
||||
* @param page The zero-indexed page to display.
|
||||
*/
|
||||
export const setPage = (page: number) => createAction(ExternalEmbedActions.SET_PAGE, { page });
|
||||
|
||||
/**
|
||||
* Set the visibility of the page scrubber.
|
||||
* @param visible True if it should be visible, false otherwise.
|
||||
*/
|
||||
export const setScrubberVisible = (visible: boolean) => {
|
||||
return createAction(ExternalEmbedActions.SET_SCRUBBER_VISIBLE, { visible });
|
||||
};
|
||||
|
||||
/**
|
||||
* Set whether the slides should automatically advance.
|
||||
* @param autoplay True if it should automatically advance, false otherwise.
|
||||
*/
|
||||
export const setAutoplay = (autoplay: boolean) =>
|
||||
createAction(ExternalEmbedActions.SET_AUTOPLAY, { autoplay });
|
||||
|
||||
/**
|
||||
* Set whether the slides should animate when advanced.
|
||||
* @param animate True if it should animate when advanced, false otherwise.
|
||||
*/
|
||||
export const setAutoplayAnimate = (animate: boolean) =>
|
||||
createAction(ExternalEmbedActions.SET_AUTOPLAY_ANIMATE, { animate });
|
||||
|
||||
/**
|
||||
* Set the interval in which slide will advance. This is a `string` identical to
|
||||
* that used in Canvas proper: `1m`, `2s`, etc.
|
||||
* @param autoplay The interval in which slides should advance.
|
||||
*/
|
||||
export const setAutoplayInterval = (interval: string) =>
|
||||
createAction(ExternalEmbedActions.SET_AUTOPLAY_INTERVAL, { interval });
|
||||
|
||||
/**
|
||||
* Set if the toolbar should be hidden if the mouse is not within the bounds of the
|
||||
* embedded workpad.
|
||||
* @param autohide True if the toolbar should hide, false otherwise.
|
||||
*/
|
||||
export const setToolbarAutohide = (autohide: boolean) =>
|
||||
createAction(ExternalEmbedActions.SET_TOOLBAR_AUTOHIDE, { autohide });
|
||||
|
||||
const actions = {
|
||||
setWorkpad,
|
||||
setPage,
|
||||
setScrubberVisible,
|
||||
setAutoplay,
|
||||
setAutoplayAnimate,
|
||||
setAutoplayInterval,
|
||||
setToolbarAutohide,
|
||||
};
|
||||
|
||||
/**
|
||||
* Strongly-types the correlation between an `action` and its return.
|
||||
*/
|
||||
export type ExternalEmbedAction = ReturnType<typeof actions[keyof typeof actions]>;
|
|
@ -1,8 +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.
|
||||
*/
|
||||
|
||||
export * from './state';
|
||||
export * from './actions';
|
|
@ -1,105 +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 { ExternalEmbedState } from './state';
|
||||
import { ExternalEmbedAction, ExternalEmbedActions } from './actions';
|
||||
|
||||
/**
|
||||
* The Action Reducer for the Embedded Canvas Workpad interface.
|
||||
*/
|
||||
export const reducer = (state: ExternalEmbedState, action: ExternalEmbedAction) => {
|
||||
switch (action.type) {
|
||||
case ExternalEmbedActions.SET_WORKPAD: {
|
||||
return {
|
||||
...state,
|
||||
workpad: action.payload.workpad,
|
||||
};
|
||||
}
|
||||
case ExternalEmbedActions.SET_PAGE: {
|
||||
return {
|
||||
...state,
|
||||
page: action.payload.page,
|
||||
};
|
||||
}
|
||||
case ExternalEmbedActions.SET_SCRUBBER_VISIBLE: {
|
||||
const { footer } = state;
|
||||
|
||||
return {
|
||||
...state,
|
||||
footer: {
|
||||
...footer,
|
||||
isScrubberVisible: action.payload.visible,
|
||||
},
|
||||
};
|
||||
}
|
||||
case ExternalEmbedActions.SET_AUTOPLAY: {
|
||||
const { settings } = state;
|
||||
const { autoplay } = settings;
|
||||
|
||||
return {
|
||||
...state,
|
||||
settings: {
|
||||
...settings,
|
||||
autoplay: {
|
||||
...autoplay,
|
||||
enabled: action.payload.autoplay,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
case ExternalEmbedActions.SET_AUTOPLAY_ANIMATE: {
|
||||
const { settings } = state;
|
||||
const { autoplay } = settings;
|
||||
const { animate } = action.payload;
|
||||
|
||||
return {
|
||||
...state,
|
||||
settings: {
|
||||
...settings,
|
||||
autoplay: {
|
||||
...autoplay,
|
||||
animate,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
case ExternalEmbedActions.SET_AUTOPLAY_INTERVAL: {
|
||||
const { settings } = state;
|
||||
const { autoplay } = settings;
|
||||
const { interval } = action.payload;
|
||||
|
||||
return {
|
||||
...state,
|
||||
settings: {
|
||||
...settings,
|
||||
autoplay: {
|
||||
...autoplay,
|
||||
interval,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
case ExternalEmbedActions.SET_TOOLBAR_AUTOHIDE: {
|
||||
const { settings } = state;
|
||||
const { toolbar } = settings;
|
||||
const { autohide } = action.payload;
|
||||
|
||||
return {
|
||||
...state,
|
||||
settings: {
|
||||
...settings,
|
||||
toolbar: {
|
||||
...toolbar,
|
||||
autohide,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
default: {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
};
|
|
@ -1,86 +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, {
|
||||
createContext,
|
||||
useContext,
|
||||
Dispatch,
|
||||
useReducer,
|
||||
ReactChild,
|
||||
RefObject,
|
||||
} from 'react';
|
||||
import { CanvasRenderedWorkpad } from '../types';
|
||||
import { reducer } from './reducer';
|
||||
import { ExternalEmbedAction } from './actions';
|
||||
|
||||
export interface ExternalEmbedState {
|
||||
renderersRegistry: {
|
||||
register: (fn: Function) => void;
|
||||
get: (name: string) => Function;
|
||||
} | null;
|
||||
workpad: CanvasRenderedWorkpad | null;
|
||||
page: number;
|
||||
height: number;
|
||||
width: number;
|
||||
footer: {
|
||||
isScrubberVisible: boolean;
|
||||
};
|
||||
settings: {
|
||||
autoplay: {
|
||||
enabled: boolean;
|
||||
interval: string;
|
||||
animate: boolean;
|
||||
};
|
||||
toolbar: {
|
||||
autohide: boolean;
|
||||
};
|
||||
};
|
||||
refs: {
|
||||
stage: RefObject<HTMLDivElement>;
|
||||
};
|
||||
}
|
||||
|
||||
type StateType = [ExternalEmbedState, Dispatch<ExternalEmbedAction>];
|
||||
|
||||
export const initialExternalEmbedState: ExternalEmbedState = {
|
||||
renderersRegistry: null,
|
||||
workpad: null,
|
||||
page: 0,
|
||||
height: 0,
|
||||
width: 0,
|
||||
footer: {
|
||||
isScrubberVisible: false,
|
||||
},
|
||||
settings: {
|
||||
autoplay: {
|
||||
enabled: false,
|
||||
interval: '5s',
|
||||
animate: false,
|
||||
},
|
||||
toolbar: {
|
||||
autohide: false,
|
||||
},
|
||||
},
|
||||
refs: {
|
||||
stage: React.createRef(),
|
||||
},
|
||||
};
|
||||
|
||||
export const ExternalEmbedContext = createContext<StateType>([initialExternalEmbedState, () => {}]);
|
||||
|
||||
export const ExternalEmbedStateProvider = ({
|
||||
initialState,
|
||||
children,
|
||||
}: {
|
||||
initialState: ExternalEmbedState;
|
||||
children: ReactChild;
|
||||
}) => (
|
||||
<ExternalEmbedContext.Provider value={useReducer(reducer, initialState)}>
|
||||
{children}
|
||||
</ExternalEmbedContext.Provider>
|
||||
);
|
||||
|
||||
export const useExternalEmbedState = () => useContext<StateType>(ExternalEmbedContext);
|
Binary file not shown.
Before Width: | Height: | Size: 6.3 MiB |
|
@ -1,14 +0,0 @@
|
|||
<html>
|
||||
|
||||
<head>
|
||||
<script src="kbn_canvas.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div kbn-canvas-embed="canvas" kbn-canvas-height="400" kbn-canvas-url="/test/austin.json"></div>
|
||||
</body>
|
||||
<script type="text/javascript">
|
||||
KbnCanvas.embed();
|
||||
</script>
|
||||
|
||||
</html>
|
|
@ -1,27 +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.
|
||||
*/
|
||||
|
||||
export * from './api';
|
||||
import '../../../../../built_assets/css/plugins/kibana/index.light.css';
|
||||
import '../../../../../built_assets/css/plugins/canvas/style/index.light.css';
|
||||
import '@elastic/eui/dist/eui_theme_light.css';
|
||||
import '@kbn/ui-framework/dist/kui_light.css';
|
||||
|
||||
const css = require.context(
|
||||
'../../../../../built_assets/css',
|
||||
true,
|
||||
/\.\/plugins\/(?!canvas).*light\.css/
|
||||
);
|
||||
css.keys().forEach(filename => {
|
||||
css(filename);
|
||||
});
|
||||
|
||||
const uiStyles = require.context(
|
||||
'../../../../../src/legacy/ui/public/styles',
|
||||
false,
|
||||
/[\/\\](?!mixins|variables|_|\.|bootstrap_(light|dark))[^\/\\]+\.less/
|
||||
);
|
||||
uiStyles.keys().forEach(key => uiStyles(key));
|
|
@ -1,25 +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.
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line
|
||||
const autoprefixer = require('autoprefixer');
|
||||
const prefixer = require('postcss-prefix-selector');
|
||||
|
||||
module.exports = {
|
||||
plugins: [
|
||||
prefixer({
|
||||
prefix: '.kbnCanvas',
|
||||
transform: function(prefix, selector, prefixedSelector) {
|
||||
if (selector === 'body' || selector === 'html') {
|
||||
return prefix;
|
||||
} else {
|
||||
return prefixedSelector;
|
||||
}
|
||||
},
|
||||
}),
|
||||
autoprefixer(),
|
||||
],
|
||||
};
|
|
@ -1,14 +0,0 @@
|
|||
<html>
|
||||
|
||||
<head>
|
||||
<script src="kbn_canvas.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div kbn-canvas-embed="canvas" kbn-canvas-height="400" kbn-canvas-url="workpad.json"></div>
|
||||
</body>
|
||||
<script type="text/javascript">
|
||||
KbnCanvas.embed();
|
||||
</script>
|
||||
|
||||
</html>
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load diff
|
@ -1,57 +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.
|
||||
*/
|
||||
|
||||
// @ts-ignore Unlinked Webpack Type
|
||||
import ContainerStyle from 'types/interpreter';
|
||||
import { CSSProperties } from 'react';
|
||||
import { SavedObject, SavedObjectAttributes } from 'src/core/server';
|
||||
|
||||
import { CanvasElement, CanvasPage, CanvasWorkpad } from '../types';
|
||||
|
||||
/**
|
||||
* Represents a Canvas Element whose expression has been evaluated and now
|
||||
* exists in a transient, ready-to-render state.
|
||||
*/
|
||||
export interface CanvasRenderedElement extends CanvasElement {
|
||||
expressionRenderable: CanvasRenderable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a Page within a Canvas Workpad that is made up of ready-to-
|
||||
* render Elements.
|
||||
*/
|
||||
export interface CanvasRenderedPage extends CanvasPage {
|
||||
elements: CanvasRenderedElement[];
|
||||
groups: CanvasRenderedElement[][];
|
||||
}
|
||||
|
||||
/**
|
||||
* A Canvas Workpad made up of ready-to-render Elements.
|
||||
*/
|
||||
export interface CanvasRenderedWorkpad extends CanvasWorkpad {
|
||||
pages: CanvasRenderedPage[];
|
||||
}
|
||||
|
||||
export type CanvasRenderedWorkpadSavedObject = SavedObject<
|
||||
CanvasRenderedWorkpad & SavedObjectAttributes
|
||||
>;
|
||||
|
||||
/**
|
||||
* Represents the success/failure of the initial evaluation of a Canvas
|
||||
* Element, as well as the Function and CSS necessary to render the Element
|
||||
* upon a stage.
|
||||
*/
|
||||
export interface CanvasRenderable {
|
||||
error: string;
|
||||
state: 'ready' | 'error';
|
||||
value: {
|
||||
as: string;
|
||||
containerStyle: ContainerStyle;
|
||||
css: CSSProperties;
|
||||
type: 'render';
|
||||
value: any;
|
||||
};
|
||||
}
|
|
@ -1,182 +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.
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
|
||||
const { KIBANA_ROOT, RUNTIME_OUTPUT, LIBRARY_NAME, RUNTIME_NAME } = require('./constants');
|
||||
|
||||
const isProd = process.env.NODE_ENV === 'production';
|
||||
|
||||
module.exports = {
|
||||
context: KIBANA_ROOT,
|
||||
entry: {
|
||||
[RUNTIME_NAME]: require.resolve('./index.ts'),
|
||||
},
|
||||
mode: isProd ? 'production' : 'development',
|
||||
plugins: isProd ? [new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1 })] : [],
|
||||
output: {
|
||||
path: RUNTIME_OUTPUT,
|
||||
filename: '[name].js',
|
||||
library: LIBRARY_NAME,
|
||||
},
|
||||
// Include a require alias for legacy UI code and styles
|
||||
resolve: {
|
||||
alias: {
|
||||
ui: path.resolve(KIBANA_ROOT, 'src/legacy/ui/public'),
|
||||
'data/interpreter': path.resolve(
|
||||
KIBANA_ROOT,
|
||||
'src/plugins/data/public/expressions/interpreter'
|
||||
),
|
||||
'kbn/interpreter': path.resolve(KIBANA_ROOT, 'packages/kbn-interpreter/target/common'),
|
||||
'types/interpreter': path.resolve(
|
||||
KIBANA_ROOT,
|
||||
'src/legacy/core_plugins/interpreter/public/types'
|
||||
),
|
||||
},
|
||||
extensions: ['.js', '.json', '.ts', '.tsx', '.scss'],
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
exclude: /node_modules/,
|
||||
loaders: 'babel-loader',
|
||||
options: {
|
||||
presets: [require.resolve('@kbn/babel-preset/webpack_preset')],
|
||||
},
|
||||
sideEffects: false,
|
||||
},
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
use: [
|
||||
{
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
presets: [require.resolve('@kbn/babel-preset/webpack_preset')],
|
||||
},
|
||||
},
|
||||
],
|
||||
sideEffects: false,
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
exclude: /components/,
|
||||
use: [
|
||||
{ loader: 'style-loader' },
|
||||
{ loader: 'css-loader' },
|
||||
{
|
||||
loader: 'postcss-loader',
|
||||
options: {
|
||||
config: {
|
||||
path: require.resolve('./postcss.config.js'),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: 'string-replace-loader',
|
||||
options: {
|
||||
search: '__REPLACE_WITH_PUBLIC_PATH__',
|
||||
replace: '/',
|
||||
flags: 'g',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.module\.s(a|c)ss$/,
|
||||
loader: [
|
||||
'style-loader',
|
||||
{
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
modules: true,
|
||||
localIdentName: '[name]__[local]___[hash:base64:5]',
|
||||
camelCase: true,
|
||||
sourceMap: !isProd,
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: 'postcss-loader',
|
||||
options: {
|
||||
path: path.resolve(KIBANA_ROOT, 'src/optimize/postcss.config.js'),
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: 'sass-loader',
|
||||
options: {
|
||||
sourceMap: !isProd,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.less$/,
|
||||
use: [
|
||||
{ loader: 'style-loader' },
|
||||
{ loader: 'css-loader', options: { importLoaders: 2 } },
|
||||
{
|
||||
loader: 'postcss-loader',
|
||||
options: {
|
||||
config: {
|
||||
path: require.resolve('./postcss.config.js'),
|
||||
},
|
||||
},
|
||||
},
|
||||
{ loader: 'less-loader' },
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.scss$/,
|
||||
exclude: /\.module.(s(a|c)ss)$/,
|
||||
use: [
|
||||
{ loader: 'style-loader' },
|
||||
{ loader: 'css-loader', options: { importLoaders: 2 } },
|
||||
{
|
||||
loader: 'postcss-loader',
|
||||
options: {
|
||||
config: {
|
||||
path: require.resolve('./postcss.config.js'),
|
||||
},
|
||||
},
|
||||
},
|
||||
{ loader: 'sass-loader' },
|
||||
],
|
||||
},
|
||||
{
|
||||
test: require.resolve('jquery'),
|
||||
loader: 'expose-loader?jQuery!expose-loader?$',
|
||||
},
|
||||
{
|
||||
test: /\.(woff|woff2|ttf|eot|svg|ico)(\?|$)/,
|
||||
loader: 'url-loader',
|
||||
sideEffects: false,
|
||||
},
|
||||
{
|
||||
test: /\.html$/,
|
||||
loader: 'html-loader',
|
||||
exclude: /node_modules/,
|
||||
},
|
||||
{
|
||||
test: [
|
||||
require.resolve('@elastic/eui/es/components/code_editor'),
|
||||
require.resolve('@elastic/eui/es/components/drag_and_drop'),
|
||||
require.resolve('@elastic/eui/packages/react-datepicker'),
|
||||
require.resolve('highlight.js'),
|
||||
/canvas_plugin_src\/renderers\/advanced_filter/,
|
||||
/canvas_plugin_src\/renderers\/dropdown_filter/,
|
||||
/canvas_plugin_src\/renderers\/embeddable.tsx/,
|
||||
/canvas_plugin_src\/renderers\/time_filter/,
|
||||
],
|
||||
use: 'null-loader',
|
||||
},
|
||||
],
|
||||
},
|
||||
node: {
|
||||
fs: 'empty',
|
||||
child_process: 'empty',
|
||||
},
|
||||
};
|
|
@ -1,89 +1,85 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Storyshots components/Export/WorkpadExport disabled 1`] = `
|
||||
<div>
|
||||
<div
|
||||
className="euiPopover euiPopover--anchorDownCenter"
|
||||
container={null}
|
||||
onKeyDown={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseUp={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
onTouchStart={[Function]}
|
||||
>
|
||||
<div
|
||||
className="euiPopover euiPopover--anchorDownCenter"
|
||||
container={null}
|
||||
onKeyDown={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseUp={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
onTouchStart={[Function]}
|
||||
className="euiPopover__anchor"
|
||||
>
|
||||
<div
|
||||
className="euiPopover__anchor"
|
||||
<span
|
||||
className="euiToolTipAnchor"
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
>
|
||||
<span
|
||||
className="euiToolTipAnchor"
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
<button
|
||||
aria-label="Share this workpad"
|
||||
className="euiButtonIcon euiButtonIcon--primary"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<button
|
||||
aria-label="Share this workpad"
|
||||
className="euiButtonIcon euiButtonIcon--primary"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="euiIcon euiIcon--medium euiIcon-isLoading euiButtonIcon__icon"
|
||||
focusable="false"
|
||||
height={16}
|
||||
style={null}
|
||||
viewBox="0 0 16 16"
|
||||
width={16}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
/>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="euiIcon euiIcon--medium euiIcon-isLoading euiButtonIcon__icon"
|
||||
focusable="false"
|
||||
height={16}
|
||||
style={null}
|
||||
viewBox="0 0 16 16"
|
||||
width={16}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
/>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Storyshots components/Export/WorkpadExport enabled 1`] = `
|
||||
<div>
|
||||
<div
|
||||
className="euiPopover euiPopover--anchorDownCenter"
|
||||
container={null}
|
||||
onKeyDown={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseUp={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
onTouchStart={[Function]}
|
||||
>
|
||||
<div
|
||||
className="euiPopover euiPopover--anchorDownCenter"
|
||||
container={null}
|
||||
onKeyDown={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseUp={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
onTouchStart={[Function]}
|
||||
className="euiPopover__anchor"
|
||||
>
|
||||
<div
|
||||
className="euiPopover__anchor"
|
||||
<span
|
||||
className="euiToolTipAnchor"
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
>
|
||||
<span
|
||||
className="euiToolTipAnchor"
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
<button
|
||||
aria-label="Share this workpad"
|
||||
className="euiButtonIcon euiButtonIcon--primary"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<button
|
||||
aria-label="Share this workpad"
|
||||
className="euiButtonIcon euiButtonIcon--primary"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="euiIcon euiIcon--medium euiIcon-isLoading euiButtonIcon__icon"
|
||||
focusable="false"
|
||||
height={16}
|
||||
style={null}
|
||||
viewBox="0 0 16 16"
|
||||
width={16}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
/>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="euiIcon euiIcon--medium euiIcon-isLoading euiButtonIcon__icon"
|
||||
focusable="false"
|
||||
height={16}
|
||||
style={null}
|
||||
viewBox="0 0 16 16"
|
||||
width={16}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
/>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
|
|
@ -1,32 +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 { storiesOf } from '@storybook/react';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import React from 'react';
|
||||
import { ExternalEmbedFlyout } from '../external_embed_flyout';
|
||||
|
||||
storiesOf('components/Export/ExternalEmbedFlyout', module)
|
||||
.addParameters({
|
||||
info: {
|
||||
inline: true,
|
||||
styles: {
|
||||
infoBody: {
|
||||
margin: 20,
|
||||
},
|
||||
infoStory: {
|
||||
margin: '20px 30px',
|
||||
width: '620px',
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
.add('default', () => (
|
||||
<ExternalEmbedFlyout
|
||||
onCopy={action('onCopy')}
|
||||
onExport={action('onExport')}
|
||||
onClose={action('onClose')}
|
||||
/>
|
||||
));
|
|
@ -1,191 +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 {
|
||||
EuiText,
|
||||
EuiSpacer,
|
||||
EuiCode,
|
||||
EuiCallOut,
|
||||
EuiCodeBlock,
|
||||
EuiButton,
|
||||
EuiSteps,
|
||||
EuiDescriptionList,
|
||||
EuiDescriptionListTitle,
|
||||
EuiDescriptionListDescription,
|
||||
EuiHorizontalRule,
|
||||
EuiFlyout,
|
||||
EuiFlyoutHeader,
|
||||
EuiFlyoutBody,
|
||||
EuiTitle,
|
||||
EuiLink,
|
||||
} from '@elastic/eui';
|
||||
import { OnCopyFn, OnExportFn, OnCloseFn } from '../workpad_export';
|
||||
import { Clipboard } from '../../../clipboard';
|
||||
|
||||
interface Props {
|
||||
onCopy: OnCopyFn;
|
||||
onExport: OnExportFn;
|
||||
onClose: OnCloseFn;
|
||||
}
|
||||
|
||||
const staticEmbedSteps = (onExport: OnExportFn, onCopy: OnCopyFn, onClose: OnCloseFn) => [
|
||||
{
|
||||
title: 'Download workpad',
|
||||
children: (
|
||||
<EuiText size="s">
|
||||
<p>The workpad will be exported as a single JSON file for embedding in another site.</p>
|
||||
<EuiSpacer size="s" />
|
||||
<EuiButton
|
||||
onClick={() => {
|
||||
onExport('embed');
|
||||
}}
|
||||
size="s"
|
||||
>
|
||||
Download workpad
|
||||
</EuiButton>
|
||||
</EuiText>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Download runtime',
|
||||
children: (
|
||||
<EuiText size="s">
|
||||
<p>
|
||||
In order to render the Workpad, you also need to include the Canvas Embed Runtime. You can
|
||||
skip this step if the runtime is already included on your website.
|
||||
</p>
|
||||
<EuiSpacer size="s" />
|
||||
<EuiButton
|
||||
onClick={() => {
|
||||
onExport('runtime');
|
||||
}}
|
||||
size="s"
|
||||
>
|
||||
Download runtime
|
||||
</EuiButton>
|
||||
</EuiText>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Add snippets to website',
|
||||
children: (
|
||||
<div>
|
||||
<EuiText size="s">
|
||||
<p>
|
||||
The Workpad is embedded in the HTML of the site by using an HTML placeholder. Parameters
|
||||
for the runtime are included inline. See the full list of embed parameters below. You
|
||||
can include more than one workpad on the page .
|
||||
</p>
|
||||
</EuiText>
|
||||
<EuiSpacer size="s" />
|
||||
<Clipboard
|
||||
content={HTML}
|
||||
onCopy={() => {
|
||||
onCopy('embed');
|
||||
}}
|
||||
>
|
||||
<EuiCodeBlock
|
||||
className="canvasWorkpadExport__reportingConfig"
|
||||
paddingSize="s"
|
||||
fontSize="s"
|
||||
language="html"
|
||||
>
|
||||
{HTML}
|
||||
</EuiCodeBlock>
|
||||
</Clipboard>
|
||||
<EuiSpacer />
|
||||
<EuiText>
|
||||
<h4>Embed parameters</h4>
|
||||
<p>There are a number of inline parameters to configure the embedded Workpad.</p>
|
||||
</EuiText>
|
||||
<EuiHorizontalRule />
|
||||
<EuiDescriptionList>
|
||||
<EuiDescriptionListTitle>
|
||||
<EuiCode>kbn-canvas-embed="canvas"</EuiCode> (required)
|
||||
</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription>
|
||||
The type of embed. In this case, a Canvas Workpad.
|
||||
</EuiDescriptionListDescription>
|
||||
<EuiDescriptionListTitle>
|
||||
<EuiCode>kbn-canvas-url</EuiCode> (required)
|
||||
</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription>
|
||||
The URL of the Workpad Snapshot JSON file.
|
||||
</EuiDescriptionListDescription>
|
||||
<EuiDescriptionListTitle>
|
||||
<EuiCode>kbn-canvas-height</EuiCode>
|
||||
</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription>
|
||||
The height of the Workpad. Defaults to the Workpad height.
|
||||
</EuiDescriptionListDescription>
|
||||
<EuiDescriptionListTitle>
|
||||
<EuiCode>kbn-canvas-width</EuiCode>
|
||||
</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription>
|
||||
The width of the Workpad. Defaults to the Workpad width.
|
||||
</EuiDescriptionListDescription>
|
||||
<EuiDescriptionListTitle>
|
||||
<EuiCode>kbn-canvas-page</EuiCode>
|
||||
</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription>
|
||||
The page to display. Defaults to the page specified by the Workpad.
|
||||
</EuiDescriptionListDescription>
|
||||
</EuiDescriptionList>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const HTML = `<!-- Include Runtime -->
|
||||
<script src="kbnCanvas.js"></script>
|
||||
|
||||
<!-- Placeholder -->
|
||||
<div kbn-canvas-embed="canvas" kbn-canvas-url="workpad.json" />
|
||||
|
||||
<!-- Call Runtime -->
|
||||
<script type="text/javascript">
|
||||
KbnCanvas.embed();
|
||||
</script>`;
|
||||
|
||||
export const ExternalEmbedFlyout = ({ onCopy, onExport, onClose }: Props) => (
|
||||
<EuiFlyout onClose={() => onClose('embed')} maxWidth>
|
||||
<EuiFlyoutHeader hasBorder>
|
||||
<EuiTitle size="m">
|
||||
<h2 id="flyoutTitle">Embed on a website</h2>
|
||||
</EuiTitle>
|
||||
</EuiFlyoutHeader>
|
||||
<EuiFlyoutBody>
|
||||
<EuiText size="s">
|
||||
<p>
|
||||
Follow these steps to embed a static version of this workpad on an external website. It
|
||||
will be a visual snapshot of the current workpad, and will not have access to live data.
|
||||
</p>
|
||||
</EuiText>
|
||||
<EuiSpacer />
|
||||
<EuiCallOut
|
||||
size="s"
|
||||
title={
|
||||
<div>
|
||||
To try embedding, you can{' '}
|
||||
<EuiLink
|
||||
style={{ textDecoration: 'underline' }}
|
||||
onClick={() => {
|
||||
onExport('zip');
|
||||
}}
|
||||
>
|
||||
download an example ZIP file
|
||||
</EuiLink>{' '}
|
||||
containing this workpad, the Canvas runtime, and a sample HTML file.
|
||||
</div>
|
||||
}
|
||||
iconType="iInCircle"
|
||||
></EuiCallOut>
|
||||
<EuiSpacer />
|
||||
<EuiSteps steps={staticEmbedSteps(onExport, onCopy, onClose)} />
|
||||
</EuiFlyoutBody>
|
||||
</EuiFlyout>
|
||||
);
|
|
@ -4,36 +4,24 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import chrome from 'ui/chrome';
|
||||
import { connect } from 'react-redux';
|
||||
import { compose, withProps } from 'recompose';
|
||||
import { jobCompletionNotifications } from '../../../../../reporting/public/lib/job_completion_notifications';
|
||||
// @ts-ignore Untyped local
|
||||
import { getWorkpad, getPages, getRenderedWorkpad } from '../../../state/selectors/workpad';
|
||||
import { getWorkpad, getPages } from '../../../state/selectors/workpad';
|
||||
// @ts-ignore Untyped local
|
||||
import { getReportingBrowserType } from '../../../state/selectors/app';
|
||||
// @ts-ignore Untyped local
|
||||
import { notify } from '../../../lib/notify';
|
||||
import { getWindow } from '../../../lib/get_window';
|
||||
// @ts-ignore Untyped local
|
||||
import {
|
||||
downloadWorkpad,
|
||||
downloadRenderedWorkpad,
|
||||
downloadEmbedRuntime,
|
||||
downloadZippedEmbed,
|
||||
// @ts-ignore Untyped local
|
||||
} from '../../../lib/download_workpad';
|
||||
import { downloadWorkpad } from '../../../lib/download_workpad';
|
||||
import { WorkpadExport as Component, Props as ComponentProps } from './workpad_export';
|
||||
import { getPdfUrl, createPdf } from './utils';
|
||||
import { CanvasWorkpad } from '../../../../types';
|
||||
import { CanvasRenderedWorkpad } from '../../../../external_runtime/types';
|
||||
// @ts-ignore Untyped local.
|
||||
import { fetch, arrayBufferFetch } from '../../../../common/lib/fetch';
|
||||
import { API_ROUTE_SNAPSHOT_ZIP } from '../../../../common/lib/constants';
|
||||
|
||||
const mapStateToProps = (state: any) => ({
|
||||
workpad: getWorkpad(state),
|
||||
renderedWorkpad: getRenderedWorkpad(state),
|
||||
pageCount: getPages(state).length,
|
||||
enabled: getReportingBrowserType(state) === 'chromium',
|
||||
});
|
||||
|
@ -51,7 +39,6 @@ const getAbsoluteUrl = (path: string) => {
|
|||
|
||||
interface Props {
|
||||
workpad: CanvasWorkpad;
|
||||
renderedWorkpad: CanvasRenderedWorkpad;
|
||||
pageCount: number;
|
||||
enabled: boolean;
|
||||
}
|
||||
|
@ -59,7 +46,7 @@ interface Props {
|
|||
export const WorkpadExport = compose<ComponentProps, Props>(
|
||||
connect(mapStateToProps),
|
||||
withProps(
|
||||
({ workpad, pageCount, enabled, renderedWorkpad }: Props): ComponentProps => ({
|
||||
({ workpad, pageCount, enabled }: Props): ComponentProps => ({
|
||||
enabled,
|
||||
getExportUrl: type => {
|
||||
if (type === 'pdf') {
|
||||
|
@ -76,11 +63,8 @@ export const WorkpadExport = compose<ComponentProps, Props>(
|
|||
case 'reportingConfig':
|
||||
notify.info(`Copied reporting configuration to clipboard`);
|
||||
break;
|
||||
case 'embed':
|
||||
notify.info(`Copied embed code to clipboard`);
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unknown copy type: ${type}`);
|
||||
throw new Error(`Unknown export type: ${type}`);
|
||||
}
|
||||
},
|
||||
onExport: type => {
|
||||
|
@ -100,19 +84,7 @@ export const WorkpadExport = compose<ComponentProps, Props>(
|
|||
});
|
||||
case 'json':
|
||||
downloadWorkpad(workpad.id);
|
||||
return;
|
||||
case 'embed':
|
||||
downloadRenderedWorkpad(renderedWorkpad);
|
||||
return;
|
||||
case 'runtime':
|
||||
downloadEmbedRuntime();
|
||||
return;
|
||||
case 'zip':
|
||||
const basePath = chrome.getBasePath();
|
||||
arrayBufferFetch
|
||||
.post(`${basePath}${API_ROUTE_SNAPSHOT_ZIP}`, JSON.stringify(renderedWorkpad))
|
||||
.then(blob => downloadZippedEmbed(blob.data));
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unknown export type: ${type}`);
|
||||
}
|
||||
|
|
|
@ -4,25 +4,22 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React, { FunctionComponent, useState } from 'react';
|
||||
import React, { FunctionComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { EuiButtonIcon, EuiContextMenu, EuiIcon } from '@elastic/eui';
|
||||
// @ts-ignore Untyped local
|
||||
import { Popover } from '../../popover';
|
||||
import { DisabledPanel } from './disabled_panel';
|
||||
import { PDFPanel } from './pdf_panel';
|
||||
import { ExternalEmbedFlyout } from './flyout/external_embed_flyout';
|
||||
|
||||
type ClosePopoverFn = () => void;
|
||||
|
||||
type CopyTypes = 'pdf' | 'reportingConfig' | 'embed';
|
||||
type ExportTypes = 'pdf' | 'json' | 'embed' | 'runtime' | 'zip';
|
||||
type CopyTypes = 'pdf' | 'reportingConfig';
|
||||
type ExportTypes = 'pdf' | 'json';
|
||||
type ExportUrlTypes = 'pdf';
|
||||
type CloseTypes = 'embed';
|
||||
|
||||
export type OnCopyFn = (type: CopyTypes) => void;
|
||||
export type OnExportFn = (type: ExportTypes) => void;
|
||||
export type OnCloseFn = (type: CloseTypes) => void;
|
||||
export type GetExportUrlFn = (type: ExportUrlTypes) => string;
|
||||
|
||||
export interface Props {
|
||||
|
@ -45,13 +42,6 @@ export const WorkpadExport: FunctionComponent<Props> = ({
|
|||
onExport,
|
||||
getExportUrl,
|
||||
}) => {
|
||||
const [showFlyout, setShowFlyout] = useState(false);
|
||||
|
||||
const onClose = (type: CloseTypes) => {
|
||||
if (type === 'embed') {
|
||||
setShowFlyout(false);
|
||||
}
|
||||
};
|
||||
// TODO: Fix all of this magic from EUI; this code is boilerplate from
|
||||
// EUI examples and isn't easily typed.
|
||||
const flattenPanelTree = (tree: any, array: any[] = []) => {
|
||||
|
@ -116,14 +106,6 @@ export const WorkpadExport: FunctionComponent<Props> = ({
|
|||
),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Embed on a website',
|
||||
icon: <EuiIcon type="globe" size="m" />,
|
||||
onClick: () => {
|
||||
setShowFlyout(true);
|
||||
closePopover();
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
|
@ -131,27 +113,17 @@ export const WorkpadExport: FunctionComponent<Props> = ({
|
|||
<EuiButtonIcon iconType="share" aria-label="Share this workpad" onClick={togglePopover} />
|
||||
);
|
||||
|
||||
const flyout = showFlyout ? (
|
||||
<ExternalEmbedFlyout onClose={onClose} onCopy={onCopy} onExport={onExport} />
|
||||
) : null;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Popover
|
||||
button={exportControl}
|
||||
panelPaddingSize="none"
|
||||
tooltip="Share workpad"
|
||||
tooltipPosition="bottom"
|
||||
>
|
||||
{({ closePopover }: { closePopover: ClosePopoverFn }) => (
|
||||
<EuiContextMenu
|
||||
initialPanelId={0}
|
||||
panels={flattenPanelTree(getPanelTree(closePopover))}
|
||||
/>
|
||||
)}
|
||||
</Popover>
|
||||
{flyout}
|
||||
</div>
|
||||
<Popover
|
||||
button={exportControl}
|
||||
panelPaddingSize="none"
|
||||
tooltip="Share workpad"
|
||||
tooltipPosition="bottom"
|
||||
>
|
||||
{({ closePopover }: { closePopover: ClosePopoverFn }) => (
|
||||
<EuiContextMenu initialPanelId={0} panels={flattenPanelTree(getPanelTree(closePopover))} />
|
||||
)}
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -8,11 +8,61 @@ 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 { arrayToMap, flatten, identity } from '../../lib/aeroelastic/functional';
|
||||
import { getLocalTransformMatrix } from '../../lib/aeroelastic/layout_functions';
|
||||
import { matrixToAngle } from '../../lib/aeroelastic/matrix';
|
||||
import { isGroupId, elementToShape } from './utils';
|
||||
export * from './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)
|
||||
});
|
||||
|
||||
const shapeToElement = shape => ({
|
||||
left: shape.transformMatrix[12] - shape.a,
|
||||
|
|
|
@ -1,58 +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 { multiply, rotateZ, translate } from '../../lib/aeroelastic/matrix';
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
/**
|
||||
* 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)
|
||||
});
|
||||
|
||||
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) });
|
|
@ -4,8 +4,6 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import fileSaver from 'file-saver';
|
||||
import chrome from 'ui/chrome';
|
||||
import { API_ROUTE_SNAPSHOT_RUNTIME_DOWNLOAD } from '../../common/lib/constants';
|
||||
import { notify } from './notify';
|
||||
import * as workpadService from './workpad_service';
|
||||
|
||||
|
@ -18,35 +16,3 @@ export const downloadWorkpad = async workpadId => {
|
|||
notify.error(err, { title: `Couldn't download workpad` });
|
||||
}
|
||||
};
|
||||
|
||||
export const downloadRenderedWorkpad = async renderedWorkpad => {
|
||||
try {
|
||||
const jsonBlob = new Blob([JSON.stringify(renderedWorkpad)], { type: 'application/json' });
|
||||
fileSaver.saveAs(
|
||||
jsonBlob,
|
||||
`canvas-embed-workpad-${renderedWorkpad.name}-${renderedWorkpad.id}.json`
|
||||
);
|
||||
} catch (err) {
|
||||
notify.error(err, { title: `Couldn't download rendered workpad` });
|
||||
}
|
||||
};
|
||||
|
||||
export const downloadEmbedRuntime = async () => {
|
||||
try {
|
||||
const basePath = chrome.getBasePath();
|
||||
const path = `${basePath}${API_ROUTE_SNAPSHOT_RUNTIME_DOWNLOAD}`;
|
||||
window.open(path);
|
||||
return;
|
||||
} catch (err) {
|
||||
notify.error(err, { title: `Couldn't download embed runtime` });
|
||||
}
|
||||
};
|
||||
|
||||
export const downloadZippedEmbed = async data => {
|
||||
try {
|
||||
const zip = new Blob([data], { type: 'octet/stream' });
|
||||
fileSaver.saveAs(zip, 'canvas-workpad-embed.zip');
|
||||
} catch (err) {
|
||||
notify.error(err, { title: `Couldn't download ZIP file` });
|
||||
}
|
||||
};
|
||||
|
|
|
@ -364,34 +364,3 @@ export function getRefreshInterval(state) {
|
|||
export function getAutoplay(state) {
|
||||
return get(state, 'transient.autoplay');
|
||||
}
|
||||
|
||||
export function getRenderedWorkpad(state) {
|
||||
const currentPages = getPages(state);
|
||||
const args = get(state, ['transient', 'resolvedArgs']);
|
||||
const renderedPages = currentPages.map(page => {
|
||||
const { elements, ...rest } = page;
|
||||
return {
|
||||
...rest,
|
||||
elements: elements.map(element => {
|
||||
const { id, position } = element;
|
||||
const arg = args[id];
|
||||
if (!arg) {
|
||||
return null;
|
||||
}
|
||||
const { expressionRenderable } = arg;
|
||||
|
||||
return { id, position, expressionRenderable };
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
const workpad = getWorkpad(state);
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const { pages, ...rest } = workpad;
|
||||
|
||||
return {
|
||||
pages: renderedPages,
|
||||
...rest,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,114 +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.
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { pipeline } = require('stream');
|
||||
const { promisify } = require('util');
|
||||
|
||||
const del = require('del');
|
||||
const { run } = require('@kbn/dev-utils');
|
||||
const execa = require('execa');
|
||||
|
||||
const asyncPipeline = promisify(pipeline);
|
||||
|
||||
const {
|
||||
RUNTIME_SRC,
|
||||
KIBANA_ROOT,
|
||||
STATS_OUTPUT,
|
||||
RUNTIME_FILE,
|
||||
} = require('../external_runtime/constants');
|
||||
|
||||
run(
|
||||
async ({ log, flags }) => {
|
||||
const options = {
|
||||
cwd: KIBANA_ROOT,
|
||||
stdio: ['ignore', 'inherit', 'inherit'],
|
||||
buffer: false,
|
||||
};
|
||||
|
||||
log.info('pre-req: Ensuring Kibana SCSS is built.');
|
||||
// Ensure SASS has been built completely before building the runtime.
|
||||
execa.sync(process.execPath, ['scripts/build_sass'], {
|
||||
...options,
|
||||
});
|
||||
|
||||
const webpackConfig = path.resolve(RUNTIME_SRC, 'webpack.config.js');
|
||||
|
||||
const clean = () => {
|
||||
log.info('Deleting previous build.');
|
||||
del.sync([RUNTIME_FILE], { force: true });
|
||||
};
|
||||
|
||||
if (flags.clean) {
|
||||
clean();
|
||||
}
|
||||
|
||||
const env = {};
|
||||
|
||||
if (!flags.dev) {
|
||||
env.NODE_ENV = 'production';
|
||||
}
|
||||
|
||||
if (flags.run) {
|
||||
log.info('Starting Webpack Dev Server...');
|
||||
execa.sync(
|
||||
'yarn',
|
||||
[
|
||||
'webpack-dev-server',
|
||||
'--config',
|
||||
webpackConfig,
|
||||
'--progress',
|
||||
'--hide-modules',
|
||||
'--display-entrypoints',
|
||||
'false',
|
||||
'--content-base',
|
||||
RUNTIME_SRC,
|
||||
],
|
||||
options
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (flags.stats) {
|
||||
log.info('Writing Webpack stats...');
|
||||
const output = execa(
|
||||
require.resolve('webpack/bin/webpack'),
|
||||
['--config', webpackConfig, '--profile', '--json'],
|
||||
{
|
||||
...options,
|
||||
env,
|
||||
stdio: ['ignore', 'pipe', 'inherit'],
|
||||
}
|
||||
);
|
||||
await asyncPipeline(output.stdout, fs.createWriteStream(STATS_OUTPUT));
|
||||
log.success('...output written to', STATS_OUTPUT);
|
||||
return;
|
||||
}
|
||||
|
||||
clean();
|
||||
log.info('Building Canvas Snapshot Runtime...');
|
||||
execa.sync('yarn', ['webpack', '--config', webpackConfig, '--hide-modules', '--progress'], {
|
||||
...options,
|
||||
env,
|
||||
});
|
||||
log.success('...runtime built!');
|
||||
},
|
||||
{
|
||||
description: `
|
||||
Build script for the Canvas Snapshot Runtime.
|
||||
`,
|
||||
flags: {
|
||||
boolean: ['run', 'clean', 'help', 'stats', 'dev'],
|
||||
help: `
|
||||
--run Run a server with the runtime
|
||||
--dev Build and/or create stats in development mode.
|
||||
--stats Output Webpack statistics to a stats.json file.
|
||||
--clean Delete the existing build
|
||||
`,
|
||||
},
|
||||
}
|
||||
);
|
|
@ -7,11 +7,9 @@
|
|||
import { workpad } from './workpad';
|
||||
import { esFields } from './es_fields';
|
||||
import { customElements } from './custom_elements';
|
||||
import { workpadSnapshots } from './workpad_snapshots';
|
||||
|
||||
export function routes(server) {
|
||||
customElements(server);
|
||||
esFields(server);
|
||||
workpad(server);
|
||||
workpadSnapshots(server);
|
||||
}
|
||||
|
|
|
@ -1,64 +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 { Server, RouteOptions } from 'hapi';
|
||||
import archiver from 'archiver';
|
||||
|
||||
import {
|
||||
API_ROUTE_SNAPSHOT_RUNTIME,
|
||||
API_ROUTE_SNAPSHOT_RUNTIME_DOWNLOAD,
|
||||
API_ROUTE_SNAPSHOT_ZIP,
|
||||
} from '../../common/lib/constants';
|
||||
|
||||
import { RUNTIME_FILE, RUNTIME_NAME, RUNTIME_SRC } from '../../external_runtime/constants';
|
||||
|
||||
const PUBLIC_OPTIONS: RouteOptions = {
|
||||
auth: false,
|
||||
};
|
||||
|
||||
export function workpadSnapshots(server: Server) {
|
||||
// get runtime
|
||||
server.route({
|
||||
method: 'GET',
|
||||
path: API_ROUTE_SNAPSHOT_RUNTIME,
|
||||
handler: {
|
||||
file: RUNTIME_FILE,
|
||||
},
|
||||
options: PUBLIC_OPTIONS,
|
||||
});
|
||||
|
||||
// download runtime
|
||||
server.route({
|
||||
method: 'GET',
|
||||
path: API_ROUTE_SNAPSHOT_RUNTIME_DOWNLOAD,
|
||||
handler(_request, handler) {
|
||||
// @ts-ignore No type for inert Hapi handler
|
||||
const file = handler.file(RUNTIME_FILE);
|
||||
file.type('application/octet-stream');
|
||||
return file;
|
||||
},
|
||||
options: PUBLIC_OPTIONS,
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: 'POST',
|
||||
path: API_ROUTE_SNAPSHOT_ZIP,
|
||||
handler(request, handler) {
|
||||
const workpad = request.payload;
|
||||
|
||||
const archive = archiver('zip');
|
||||
archive.append(JSON.stringify(workpad), { name: 'workpad.json' });
|
||||
archive.file(`${RUNTIME_SRC}/template.html`, { name: 'index.html' });
|
||||
archive.file(RUNTIME_FILE, { name: `${RUNTIME_NAME}.js` });
|
||||
|
||||
const response = handler.response(archive);
|
||||
response.header('content-type', 'application/zip');
|
||||
archive.finalize();
|
||||
|
||||
return response;
|
||||
},
|
||||
});
|
||||
}
|
|
@ -6,13 +6,6 @@
|
|||
|
||||
import { ElementPosition } from './elements';
|
||||
|
||||
export interface CanvasAsset {
|
||||
'@created': string;
|
||||
id: string;
|
||||
type: 'dataurl';
|
||||
value: string;
|
||||
}
|
||||
|
||||
export interface CanvasElement {
|
||||
id: string;
|
||||
position: ElementPosition;
|
||||
|
@ -32,16 +25,13 @@ export interface CanvasPage {
|
|||
}
|
||||
|
||||
export interface CanvasWorkpad {
|
||||
'@created': string;
|
||||
'@timestamp': string;
|
||||
assets: { [id: string]: CanvasAsset };
|
||||
colors: string[];
|
||||
css: string;
|
||||
height: number;
|
||||
id: string;
|
||||
isWriteable: boolean;
|
||||
name: string;
|
||||
id: string;
|
||||
width: number;
|
||||
height: number;
|
||||
css: string;
|
||||
page: number;
|
||||
pages: CanvasPage[];
|
||||
width: number;
|
||||
colors: string[];
|
||||
isWriteable: boolean;
|
||||
}
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
"@storybook/react": "^5.0.5",
|
||||
"@storybook/theming": "^5.0.5",
|
||||
"@types/angular": "1.6.50",
|
||||
"@types/archiver": "^3.0.0",
|
||||
"@types/base64-js": "^1.2.5",
|
||||
"@types/boom": "^7.2.0",
|
||||
"@types/cheerio": "^0.22.10",
|
||||
|
@ -152,7 +151,6 @@
|
|||
"mustache": "^2.3.0",
|
||||
"mutation-observer": "^1.0.3",
|
||||
"node-fetch": "^2.6.0",
|
||||
"null-loader": "^3.0.0",
|
||||
"pdf-image": "2.0.0",
|
||||
"pdfjs-dist": "^2.0.943",
|
||||
"pixelmatch": "4.0.2",
|
||||
|
@ -185,7 +183,6 @@
|
|||
"@babel/runtime": "^7.5.5",
|
||||
"@elastic/ctags-langserver": "^0.1.8",
|
||||
"@elastic/datemath": "5.0.2",
|
||||
"@elastic/filesaver": "1.1.2",
|
||||
"@elastic/eui": "13.6.1",
|
||||
"@elastic/javascript-typescript-langserver": "^0.2.2",
|
||||
"@elastic/lsp-extension": "^0.1.2",
|
||||
|
@ -220,7 +217,6 @@
|
|||
"apollo-link-state": "^0.4.1",
|
||||
"apollo-server-errors": "^2.0.2",
|
||||
"apollo-server-hapi": "^1.3.6",
|
||||
"archiver": "3.1.1",
|
||||
"axios": "^0.19.0",
|
||||
"bluebird": "3.5.5",
|
||||
"boom": "^7.2.0",
|
||||
|
@ -306,7 +302,6 @@
|
|||
"pngjs": "3.4.0",
|
||||
"polished": "^1.9.2",
|
||||
"popper.js": "^1.14.3",
|
||||
"postcss-prefix-selector": "^1.7.2",
|
||||
"prop-types": "^15.6.0",
|
||||
"proper-lockfile": "^3.2.0",
|
||||
"puid": "1.0.7",
|
||||
|
@ -367,7 +362,6 @@
|
|||
"uuid": "3.3.2",
|
||||
"venn.js": "0.2.20",
|
||||
"vscode-languageserver": "^5.2.1",
|
||||
"webpack": "4.33.0",
|
||||
"wellknown": "^0.5.0",
|
||||
"xml2js": "^0.4.19",
|
||||
"xregexp": "4.2.4"
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import execa from 'execa';
|
||||
import { resolve } from 'path';
|
||||
import { writeFileSync } from 'fs';
|
||||
import pluginHelpers from '@kbn/plugin-helpers';
|
||||
|
@ -22,13 +21,7 @@ export default (gulp, { buildTarget }) => {
|
|||
|
||||
const log = new ToolingLog({
|
||||
level: 'info',
|
||||
writeTo: process.stdout,
|
||||
});
|
||||
|
||||
execa.sync(process.execPath, ['legacy/plugins/canvas/scripts/external_runtime'], {
|
||||
cwd: resolve(__dirname, '..'),
|
||||
stdio: ['ignore', 'inherit', 'inherit'],
|
||||
buffer: false,
|
||||
writeTo: process.stdout
|
||||
});
|
||||
|
||||
writeFileSync(
|
||||
|
@ -36,7 +29,7 @@ export default (gulp, { buildTarget }) => {
|
|||
await generateNoticeFromSource({
|
||||
productName: 'Kibana X-Pack',
|
||||
log,
|
||||
directory: buildRoot,
|
||||
directory: buildRoot
|
||||
})
|
||||
);
|
||||
});
|
||||
|
|
173
yarn.lock
173
yarn.lock
|
@ -3024,13 +3024,6 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/angular/-/angular-1.6.50.tgz#8b6599088d80f68ef0cad7d3a2062248ebe72b3d"
|
||||
integrity sha512-D3KB0PdaxdwtA44yOpK+NtptTscKWgUzXmf8fiLaaVxnX+b7QQ+dUMsyeVDweCQ6VX4PMwkd6x2hJ0X+ISIsoQ==
|
||||
|
||||
"@types/archiver@^3.0.0":
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/archiver/-/archiver-3.0.0.tgz#c0a53e0ed3b7aef626ce683d081d7821d8c638b4"
|
||||
integrity sha512-orghAMOF+//wSg4ru2znk6jt0eIPvKTtMVLH7XcYcjbcRyAXRClDlh27QVdqnAvVM37yu9xDP6Nh7egRhNr8tQ==
|
||||
dependencies:
|
||||
"@types/glob" "*"
|
||||
|
||||
"@types/argparse@1.0.33":
|
||||
version "1.0.33"
|
||||
resolved "https://registry.yarnpkg.com/@types/argparse/-/argparse-1.0.33.tgz#2728669427cdd74a99e53c9f457ca2866a37c52d"
|
||||
|
@ -5215,35 +5208,6 @@ archiver-utils@^2.0.0:
|
|||
normalize-path "^3.0.0"
|
||||
readable-stream "^2.0.0"
|
||||
|
||||
archiver-utils@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/archiver-utils/-/archiver-utils-2.1.0.tgz#e8a460e94b693c3e3da182a098ca6285ba9249e2"
|
||||
integrity sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==
|
||||
dependencies:
|
||||
glob "^7.1.4"
|
||||
graceful-fs "^4.2.0"
|
||||
lazystream "^1.0.0"
|
||||
lodash.defaults "^4.2.0"
|
||||
lodash.difference "^4.5.0"
|
||||
lodash.flatten "^4.4.0"
|
||||
lodash.isplainobject "^4.0.6"
|
||||
lodash.union "^4.6.0"
|
||||
normalize-path "^3.0.0"
|
||||
readable-stream "^2.0.0"
|
||||
|
||||
archiver@3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/archiver/-/archiver-3.1.1.tgz#9db7819d4daf60aec10fe86b16cb9258ced66ea0"
|
||||
integrity sha512-5Hxxcig7gw5Jod/8Gq0OneVgLYET+oNHcxgWItq4TbhOzRLKNAFUb9edAftiMKXvXfCB0vbGrJdZDNq0dWMsxg==
|
||||
dependencies:
|
||||
archiver-utils "^2.1.0"
|
||||
async "^2.6.3"
|
||||
buffer-crc32 "^0.2.1"
|
||||
glob "^7.1.4"
|
||||
readable-stream "^3.4.0"
|
||||
tar-stream "^2.1.0"
|
||||
zip-stream "^2.1.2"
|
||||
|
||||
archiver@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/archiver/-/archiver-3.0.0.tgz#50b2628cf032adcbf35d35d111b5324db95bfb69"
|
||||
|
@ -5695,13 +5659,6 @@ async@^2.0.0, async@^2.1.4:
|
|||
dependencies:
|
||||
lodash "^4.14.0"
|
||||
|
||||
async@^2.6.3:
|
||||
version "2.6.3"
|
||||
resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff"
|
||||
integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==
|
||||
dependencies:
|
||||
lodash "^4.17.14"
|
||||
|
||||
async@~0.2.9:
|
||||
version "0.2.10"
|
||||
resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1"
|
||||
|
@ -6536,13 +6493,6 @@ bl@^1.0.0:
|
|||
dependencies:
|
||||
readable-stream "^2.0.5"
|
||||
|
||||
bl@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/bl/-/bl-3.0.0.tgz#3611ec00579fd18561754360b21e9f784500ff88"
|
||||
integrity sha512-EUAyP5UHU5hxF8BPT0LKW8gjYLhq1DQIcneOX/pL/m2Alo+OYDQAJlHq+yseMP50Os2nHXOSic6Ss3vSQeyf4A==
|
||||
dependencies:
|
||||
readable-stream "^3.0.1"
|
||||
|
||||
blob@0.0.5:
|
||||
version "0.0.5"
|
||||
resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.5.tgz#d680eeef25f8cd91ad533f5b01eed48e64caf683"
|
||||
|
@ -6965,7 +6915,7 @@ buffer-alloc@^1.2.0:
|
|||
buffer-alloc-unsafe "^1.1.0"
|
||||
buffer-fill "^1.0.0"
|
||||
|
||||
buffer-crc32@^0.2.1, buffer-crc32@^0.2.13, buffer-crc32@~0.2.3:
|
||||
buffer-crc32@^0.2.1, buffer-crc32@~0.2.3:
|
||||
version "0.2.13"
|
||||
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
|
||||
integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=
|
||||
|
@ -8385,16 +8335,6 @@ compress-commons@^1.2.0:
|
|||
normalize-path "^2.0.0"
|
||||
readable-stream "^2.0.0"
|
||||
|
||||
compress-commons@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-2.1.1.tgz#9410d9a534cf8435e3fbbb7c6ce48de2dc2f0610"
|
||||
integrity sha512-eVw6n7CnEMFzc3duyFVrQEuY1BlHR3rYsSztyG32ibGMW722i3C6IizEGMFmfMU+A+fALvBIwxN3czffTcdA+Q==
|
||||
dependencies:
|
||||
buffer-crc32 "^0.2.13"
|
||||
crc32-stream "^3.0.1"
|
||||
normalize-path "^3.0.0"
|
||||
readable-stream "^2.3.6"
|
||||
|
||||
compressible@~2.0.16:
|
||||
version "2.0.17"
|
||||
resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.17.tgz#6e8c108a16ad58384a977f3a482ca20bff2f38c1"
|
||||
|
@ -8835,14 +8775,6 @@ crc32-stream@^2.0.0:
|
|||
crc "^3.4.4"
|
||||
readable-stream "^2.0.0"
|
||||
|
||||
crc32-stream@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-3.0.1.tgz#cae6eeed003b0e44d739d279de5ae63b171b4e85"
|
||||
integrity sha512-mctvpXlbzsvK+6z8kJwSJ5crm7yBwrQMTybJzMw1O4lLGJqjlDCXY2Zw7KheiA6XBEcBmfLx1D88mjRGVJtY9w==
|
||||
dependencies:
|
||||
crc "^3.4.4"
|
||||
readable-stream "^3.4.0"
|
||||
|
||||
crc@^3.4.4:
|
||||
version "3.8.0"
|
||||
resolved "https://registry.yarnpkg.com/crc/-/crc-3.8.0.tgz#ad60269c2c856f8c299e2c4cc0de4556914056c6"
|
||||
|
@ -10735,7 +10667,7 @@ encoding@^0.1.11:
|
|||
dependencies:
|
||||
iconv-lite "~0.4.13"
|
||||
|
||||
end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1:
|
||||
end-of-stream@^1.0.0, end-of-stream@^1.1.0:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43"
|
||||
integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==
|
||||
|
@ -13864,7 +13796,7 @@ graceful-fs@^4.1.0, graceful-fs@^4.1.15, graceful-fs@^4.1.9:
|
|||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00"
|
||||
integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==
|
||||
|
||||
graceful-fs@^4.2.0, graceful-fs@^4.2.2:
|
||||
graceful-fs@^4.2.2:
|
||||
version "4.2.2"
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02"
|
||||
integrity sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==
|
||||
|
@ -18665,7 +18597,7 @@ lodash@4.17.13, lodash@4.17.15:
|
|||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.13.tgz#0bdc3a6adc873d2f4e0c4bac285df91b64fc7b93"
|
||||
integrity sha512-vm3/XWXfWtRua0FkUyEHBZy8kCPjErNBT9fJx8Zvs+U6zjqPbTUOpkaoum3O5uiA8sm+yNMHXfYkTUHFoMxFNA==
|
||||
|
||||
lodash@>4.17.4, lodash@^4.0.0, lodash@^4.0.1, lodash@^4.10.0, lodash@^4.11.1, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.16.4, lodash@^4.17.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.5.0, lodash@^4.6.1, lodash@~4.17.10, lodash@~4.17.5:
|
||||
lodash@>4.17.4, lodash@^4.0.0, lodash@^4.0.1, lodash@^4.10.0, lodash@^4.11.1, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.16.4, lodash@^4.17.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.15, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.5.0, lodash@^4.6.1, lodash@~4.17.10, lodash@~4.17.5:
|
||||
version "4.17.15"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
|
||||
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
|
||||
|
@ -20600,14 +20532,6 @@ null-check@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/null-check/-/null-check-1.0.0.tgz#977dffd7176012b9ec30d2a39db5cf72a0439edd"
|
||||
integrity sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=
|
||||
|
||||
null-loader@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/null-loader/-/null-loader-3.0.0.tgz#3e2b6c663c5bda8c73a54357d8fa0708dc61b245"
|
||||
integrity sha512-hf5sNLl8xdRho4UPBOOeoIwT3WhjYcMUQm0zj44EhD6UscMAz72o2udpoDFBgykucdEDGIcd6SXbc/G6zssbzw==
|
||||
dependencies:
|
||||
loader-utils "^1.2.3"
|
||||
schema-utils "^1.0.0"
|
||||
|
||||
num2fraction@^1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede"
|
||||
|
@ -22123,13 +22047,6 @@ postcss-modules-values@^2.0.0:
|
|||
icss-replace-symbols "^1.1.0"
|
||||
postcss "^7.0.6"
|
||||
|
||||
postcss-prefix-selector@^1.7.2:
|
||||
version "1.7.2"
|
||||
resolved "https://registry.yarnpkg.com/postcss-prefix-selector/-/postcss-prefix-selector-1.7.2.tgz#3adeed903985734298f19d8f5e0b657f9d90d43c"
|
||||
integrity sha512-ddmzjWNmGs7E/nyolJ021/Gk6oBLRQLyyXKGV4Mu+Y0gquo+XlXSDP0/Y2J8C/cad/GLyftf2H0XtuDFQZxN3w==
|
||||
dependencies:
|
||||
postcss "^7.0.0"
|
||||
|
||||
postcss-selector-parser@^6.0.0:
|
||||
version "6.0.2"
|
||||
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz#934cf799d016c83411859e09dcecade01286ec5c"
|
||||
|
@ -23967,7 +23884,7 @@ readable-stream@1.0, "readable-stream@>=1.0.33-1 <1.1.0-0", readable-stream@~1.0
|
|||
isarray "0.0.1"
|
||||
string_decoder "~0.10.x"
|
||||
|
||||
readable-stream@^3.0.1, readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0:
|
||||
readable-stream@^3.0.6, readable-stream@^3.1.1:
|
||||
version "3.4.0"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc"
|
||||
integrity sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==
|
||||
|
@ -27106,17 +27023,6 @@ tar-stream@^1.5.0:
|
|||
to-buffer "^1.1.1"
|
||||
xtend "^4.0.0"
|
||||
|
||||
tar-stream@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.1.0.tgz#d1aaa3661f05b38b5acc9b7020efdca5179a2cc3"
|
||||
integrity sha512-+DAn4Nb4+gz6WZigRzKEZl1QuJVOLtAwwF+WUxy1fJ6X63CaGaUAxJRD2KEn1OMfcbCjySTYpNC6WmfQoIEOdw==
|
||||
dependencies:
|
||||
bl "^3.0.0"
|
||||
end-of-stream "^1.4.1"
|
||||
fs-constants "^1.0.0"
|
||||
inherits "^2.0.3"
|
||||
readable-stream "^3.1.1"
|
||||
|
||||
tar@4.4.10:
|
||||
version "4.4.10"
|
||||
resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.10.tgz#946b2810b9a5e0b26140cf78bea6b0b0d689eba1"
|
||||
|
@ -29956,36 +29862,6 @@ webpack-sources@^1.4.0, webpack-sources@^1.4.1:
|
|||
source-list-map "^2.0.0"
|
||||
source-map "~0.6.1"
|
||||
|
||||
webpack@4.33.0, webpack@^4.29.0:
|
||||
version "4.33.0"
|
||||
resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.33.0.tgz#c30fc4307db432e5c5e3333aaa7c16a15a3b277e"
|
||||
integrity sha512-ggWMb0B2QUuYso6FPZKUohOgfm+Z0sVFs8WwWuSH1IAvkWs428VDNmOlAxvHGTB9Dm/qOB/qtE5cRx5y01clxw==
|
||||
dependencies:
|
||||
"@webassemblyjs/ast" "1.8.5"
|
||||
"@webassemblyjs/helper-module-context" "1.8.5"
|
||||
"@webassemblyjs/wasm-edit" "1.8.5"
|
||||
"@webassemblyjs/wasm-parser" "1.8.5"
|
||||
acorn "^6.0.5"
|
||||
acorn-dynamic-import "^4.0.0"
|
||||
ajv "^6.1.0"
|
||||
ajv-keywords "^3.1.0"
|
||||
chrome-trace-event "^1.0.0"
|
||||
enhanced-resolve "^4.1.0"
|
||||
eslint-scope "^4.0.0"
|
||||
json-parse-better-errors "^1.0.2"
|
||||
loader-runner "^2.3.0"
|
||||
loader-utils "^1.1.0"
|
||||
memory-fs "~0.4.1"
|
||||
micromatch "^3.1.8"
|
||||
mkdirp "~0.5.0"
|
||||
neo-async "^2.5.0"
|
||||
node-libs-browser "^2.0.0"
|
||||
schema-utils "^1.0.0"
|
||||
tapable "^1.1.0"
|
||||
terser-webpack-plugin "^1.1.0"
|
||||
watchpack "^1.5.0"
|
||||
webpack-sources "^1.3.0"
|
||||
|
||||
webpack@4.39.2, webpack@^4.39.2:
|
||||
version "4.39.2"
|
||||
resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.39.2.tgz#c9aa5c1776d7c309d1b3911764f0288c8c2816aa"
|
||||
|
@ -30015,6 +29891,36 @@ webpack@4.39.2, webpack@^4.39.2:
|
|||
watchpack "^1.6.0"
|
||||
webpack-sources "^1.4.1"
|
||||
|
||||
webpack@^4.29.0:
|
||||
version "4.33.0"
|
||||
resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.33.0.tgz#c30fc4307db432e5c5e3333aaa7c16a15a3b277e"
|
||||
integrity sha512-ggWMb0B2QUuYso6FPZKUohOgfm+Z0sVFs8WwWuSH1IAvkWs428VDNmOlAxvHGTB9Dm/qOB/qtE5cRx5y01clxw==
|
||||
dependencies:
|
||||
"@webassemblyjs/ast" "1.8.5"
|
||||
"@webassemblyjs/helper-module-context" "1.8.5"
|
||||
"@webassemblyjs/wasm-edit" "1.8.5"
|
||||
"@webassemblyjs/wasm-parser" "1.8.5"
|
||||
acorn "^6.0.5"
|
||||
acorn-dynamic-import "^4.0.0"
|
||||
ajv "^6.1.0"
|
||||
ajv-keywords "^3.1.0"
|
||||
chrome-trace-event "^1.0.0"
|
||||
enhanced-resolve "^4.1.0"
|
||||
eslint-scope "^4.0.0"
|
||||
json-parse-better-errors "^1.0.2"
|
||||
loader-runner "^2.3.0"
|
||||
loader-utils "^1.1.0"
|
||||
memory-fs "~0.4.1"
|
||||
micromatch "^3.1.8"
|
||||
mkdirp "~0.5.0"
|
||||
neo-async "^2.5.0"
|
||||
node-libs-browser "^2.0.0"
|
||||
schema-utils "^1.0.0"
|
||||
tapable "^1.1.0"
|
||||
terser-webpack-plugin "^1.1.0"
|
||||
watchpack "^1.5.0"
|
||||
webpack-sources "^1.3.0"
|
||||
|
||||
websocket-driver@>=0.5.1:
|
||||
version "0.7.0"
|
||||
resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.0.tgz#0caf9d2d755d93aee049d4bdd0d3fe2cca2a24eb"
|
||||
|
@ -31008,15 +30914,6 @@ zip-stream@^2.0.1:
|
|||
compress-commons "^1.2.0"
|
||||
readable-stream "^2.0.0"
|
||||
|
||||
zip-stream@^2.1.2:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-2.1.2.tgz#841efd23214b602ff49c497cba1a85d8b5fbc39c"
|
||||
integrity sha512-ykebHGa2+uzth/R4HZLkZh3XFJzivhVsjJt8bN3GvBzLaqqrUdRacu+c4QtnUgjkkQfsOuNE1JgLKMCPNmkKgg==
|
||||
dependencies:
|
||||
archiver-utils "^2.1.0"
|
||||
compress-commons "^2.1.1"
|
||||
readable-stream "^3.4.0"
|
||||
|
||||
zlib@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/zlib/-/zlib-1.0.5.tgz#6e7c972fc371c645a6afb03ab14769def114fcc0"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue