Markdown vis type np shim (#38767) (#40169)

# Conflicts:
#	src/legacy/core_plugins/vis_type_markdown/public/markdown_fn.test.ts
This commit is contained in:
Peter Pisljar 2019-07-03 09:36:10 +02:00 committed by GitHub
parent 914f2fbbfb
commit adc8db721a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 228 additions and 144 deletions

View file

@ -13,7 +13,7 @@
"kbnDocViews": "src/legacy/core_plugins/kbn_doc_views",
"embeddableApi": "src/legacy/core_plugins/embeddable_api",
"kbnVislibVisTypes": "src/legacy/core_plugins/kbn_vislib_vis_types",
"markdownVis": "src/legacy/core_plugins/markdown_vis",
"visTypeMarkdown": "src/legacy/core_plugins/vis_type_markdown",
"metricVis": "src/legacy/core_plugins/metric_vis",
"vega": "src/legacy/core_plugins/vega",
"tableVis": "src/legacy/core_plugins/table_vis",

View file

@ -1,4 +0,0 @@
{
"name": "markdown_vis",
"version": "kibana"
}

View file

@ -1,65 +0,0 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { MarkdownVisWrapper } from './markdown_vis_controller';
import { i18n } from '@kbn/i18n';
import { visFactory } from 'ui/vis/vis_factory';
import markdownVisParamsTemplate from './markdown_vis_params.html';
import { VisTypesRegistryProvider } from 'ui/registry/vis_types';
import { DefaultEditorSize } from 'ui/vis/editor_size';
// we need to load the css ourselves
// we also need to load the controller and used by the template
// register the provider with the visTypes registry so that other know it exists
VisTypesRegistryProvider.register(MarkdownVisProvider);
function MarkdownVisProvider() {
// return the visType object, which kibana will use to display and configure new
// Vis object of this type.
return visFactory.createReactVisualization({
name: 'markdown',
title: 'Markdown',
isAccessible: true,
icon: 'visText',
description: i18n.translate('markdownVis.markdownDescription', { defaultMessage: 'Create a document using markdown syntax' }),
visConfig: {
component: MarkdownVisWrapper,
defaults: {
fontSize: 12,
openLinksInNewTab: false,
markdown: '',
}
},
editorConfig: {
optionsTemplate: markdownVisParamsTemplate,
enableAutoApply: true,
defaultSize: DefaultEditorSize.LARGE,
},
options: {
showTimePicker: false,
showFilterBar: false,
},
requestHandler: 'none',
responseHandler: 'none',
});
}
// export the provider so that the visType can be required with Private()
export default MarkdownVisProvider;

View file

@ -18,19 +18,19 @@
*/
import { resolve } from 'path';
import { Legacy } from '../../../../kibana';
import { LegacyPluginApi } from '../../plugin_discovery/types';
export default function (kibana) {
return new kibana.Plugin({
// eslint-disable-next-line import/no-default-export
export default function MarkdownVisTypePlugin(kibana: LegacyPluginApi) {
const config: Legacy.PluginSpecOptions = {
id: 'vis_type_markdown',
require: ['data', 'visualizations'],
uiExports: {
visTypes: [
'plugins/markdown_vis/markdown_vis'
],
interpreter: ['plugins/markdown_vis/markdown_fn'],
styleSheetPaths: resolve(__dirname, 'public/index.scss'),
}
});
hacks: ['plugins/vis_type_markdown/index'],
},
};
return new kibana.Plugin(config);
}

View file

@ -0,0 +1,4 @@
{
"name": "vis_type_markdown",
"version": "kibana"
}

View file

@ -0,0 +1,57 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
// @ts-ignore
import { markdownVis } from './markdown_vis';
// @ts-ignore
import { kibanaMarkdown } from './markdown_fn';
// @ts-ignore
import { functionsRegistry } from '../../interpreter/public/registries';
import {
visualizations as visualizationsService,
VisualizationsSetup,
} from '../../visualizations/public';
export interface SetupDeps {
visualizations: VisualizationsSetup;
data: any;
}
class VisTypeMarkdownPlugin {
constructor() {}
public setup({ visualizations, data }: SetupDeps) {
visualizations.types.VisTypesRegistryProvider.register(() => markdownVis);
data.expressions.registerFunction(kibanaMarkdown);
}
public start() {}
public stop() {}
}
new VisTypeMarkdownPlugin().setup({
visualizations: visualizationsService,
data: {
expressions: {
registerFunction: (fn: any) => functionsRegistry.register(fn),
},
},
});

View file

@ -17,6 +17,7 @@
* under the License.
*/
// @ts-ignore
import { functionWrapper } from '../../interpreter/test_helpers';
import { kibanaMarkdown } from './markdown_fn';
@ -28,8 +29,8 @@ describe('interpreter/functions#markdown', () => {
markdown: '## hello _markdown_',
};
it('returns an object with the correct structure', () => {
const actual = fn(undefined, args);
it('returns an object with the correct structure', async () => {
const actual = await fn(undefined, args);
expect(actual).toMatchSnapshot();
});
});

View file

@ -17,37 +17,65 @@
* under the License.
*/
import { functionsRegistry } from 'plugins/interpreter/registries';
import { i18n } from '@kbn/i18n';
import { ExpressionFunction, KibanaDatatable, Render } from '../../interpreter/types';
import { Style } from '../../interpreter/public/types';
export const kibanaMarkdown = () => ({
name: 'markdownVis',
const name = 'markdownVis';
export interface Arguments {
markdown: string;
font: Style;
openLinksInNewTab: boolean;
}
export interface MarkdownVisParams {
markdown: string;
fontSize: number;
openLinksInNewTab: boolean;
}
type Return = Promise<Render<{ visType: 'markdown'; visConfig: MarkdownVisParams }>>;
export const kibanaMarkdown = (): ExpressionFunction<
typeof name,
KibanaDatatable,
Arguments,
Return
> => ({
name,
type: 'render',
context: {
types: [],
},
help: i18n.translate('markdownVis.function.help', {
defaultMessage: 'Markdown visualization'
help: i18n.translate('visTypeMarkdown.function.help', {
defaultMessage: 'Markdown visualization',
}),
args: {
markdown: {
type: ['string'],
types: ['string'],
aliases: ['_'],
required: true,
help: i18n.translate('visTypeMarkdown.function.markdown.help', {
defaultMessage: 'Markdown to render',
}),
},
font: {
types: ['style'],
help: i18n.translate('markdownVis.function.font.help', {
defaultMessage: 'Font settings.'
help: i18n.translate('visTypeMarkdown.function.font.help', {
defaultMessage: 'Font settings.',
}),
default: `{font size=12}`,
},
openLinksInNewTab: {
types: ['boolean'],
default: false,
}
help: i18n.translate('visTypeMarkdown.function.openLinksInNewTab.help', {
defaultMessage: 'Opens links in new tab',
}),
},
},
fn(context, args) {
async fn(context, args) {
return {
type: 'render',
as: 'visualization',
@ -56,11 +84,9 @@ export const kibanaMarkdown = () => ({
visConfig: {
markdown: args.markdown,
openLinksInNewTab: args.openLinksInNewTab,
fontSize: parseInt(args.font.spec.fontSize),
fontSize: parseInt(args.font.spec.fontSize || '12', 10),
},
}
},
};
}
},
});
functionsRegistry.register(kibanaMarkdown);

View file

@ -0,0 +1,54 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { i18n } from '@kbn/i18n';
import { visFactory, DefaultEditorSize } from '../../visualizations/public';
import { MarkdownVisWrapper } from './markdown_vis_controller';
import markdownVisParamsTemplate from './markdown_vis_params.html';
export const markdownVis = visFactory.createReactVisualization({
name: 'markdown',
title: 'Markdown',
isAccessible: true,
icon: 'visText',
description: i18n.translate('visTypeMarkdown.markdownDescription', {
defaultMessage: 'Create a document using markdown syntax',
}),
visConfig: {
component: MarkdownVisWrapper,
defaults: {
fontSize: 12,
openLinksInNewTab: false,
markdown: '',
},
},
editorConfig: {
optionsTemplate: markdownVisParamsTemplate,
enableAutoApply: true,
defaultSize: DefaultEditorSize.LARGE,
},
options: {
showTimePicker: false,
showFilterBar: false,
},
requestHandler: 'none',
responseHandler: 'none',
});

View file

@ -25,33 +25,40 @@ describe('markdown vis controller', () => {
it('should set html from markdown params', () => {
const vis = {
params: {
markdown: 'This is a test of the [markdown](http://daringfireball.net/projects/markdown) vis.'
}
markdown:
'This is a test of the [markdown](http://daringfireball.net/projects/markdown) vis.',
},
};
const wrapper = render(<MarkdownVisWrapper vis={vis} visParams={vis.params} renderComplete={jest.fn()}/>);
const wrapper = render(
<MarkdownVisWrapper vis={vis} visParams={vis.params} renderComplete={jest.fn()} />
);
expect(wrapper.find('a').text()).toBe('markdown');
});
it('should not render the html', () => {
const vis = {
params: {
markdown: 'Testing <a>html</a>'
}
markdown: 'Testing <a>html</a>',
},
};
const wrapper = render(<MarkdownVisWrapper vis={vis} visParams={vis.params} renderComplete={jest.fn()}/>);
const wrapper = render(
<MarkdownVisWrapper vis={vis} visParams={vis.params} renderComplete={jest.fn()} />
);
expect(wrapper.text()).toBe('Testing <a>html</a>\n');
});
it('should update the HTML when render again with changed params', () => {
const vis = {
params: {
markdown: 'Initial'
}
markdown: 'Initial',
},
};
const wrapper = mount(<MarkdownVisWrapper vis={vis} visParams={vis.params} renderComplete={jest.fn()}/>);
const wrapper = mount(
<MarkdownVisWrapper vis={vis} visParams={vis.params} renderComplete={jest.fn()} />
);
expect(wrapper.text().trim()).toBe('Initial');
vis.params.markdown = 'Updated';
wrapper.setProps({ vis });
@ -62,40 +69,50 @@ describe('markdown vis controller', () => {
it('should be called on initial rendering', () => {
const vis = {
params: {
markdown: 'test'
}
markdown: 'test',
},
};
const renderComplete = jest.fn();
mount(<MarkdownVisWrapper vis={vis} visParams={vis.params} renderComplete={renderComplete}/>);
mount(
<MarkdownVisWrapper vis={vis} visParams={vis.params} renderComplete={renderComplete} />
);
expect(renderComplete.mock.calls.length).toBe(1);
});
it('should be called on successive render when params change', () => {
const vis = {
params: {
markdown: 'test'
}
markdown: 'test',
},
};
const renderComplete = jest.fn();
mount(<MarkdownVisWrapper vis={vis} visParams={vis.params} renderComplete={renderComplete}/>);
mount(
<MarkdownVisWrapper vis={vis} visParams={vis.params} renderComplete={renderComplete} />
);
expect(renderComplete.mock.calls.length).toBe(1);
renderComplete.mockClear();
vis.params.markdown = 'changed';
mount(<MarkdownVisWrapper vis={vis} visParams={vis.params} renderComplete={renderComplete}/>);
mount(
<MarkdownVisWrapper vis={vis} visParams={vis.params} renderComplete={renderComplete} />
);
expect(renderComplete.mock.calls.length).toBe(1);
});
it('should be called on successive render even without data change', () => {
const vis = {
params: {
markdown: 'test'
}
markdown: 'test',
},
};
const renderComplete = jest.fn();
mount(<MarkdownVisWrapper vis={vis} visParams={vis.params} renderComplete={renderComplete}/>);
mount(
<MarkdownVisWrapper vis={vis} visParams={vis.params} renderComplete={renderComplete} />
);
expect(renderComplete.mock.calls.length).toBe(1);
renderComplete.mockClear();
mount(<MarkdownVisWrapper vis={vis} visParams={vis.params} renderComplete={renderComplete}/>);
mount(
<MarkdownVisWrapper vis={vis} visParams={vis.params} renderComplete={renderComplete} />
);
expect(renderComplete.mock.calls.length).toBe(1);
});
});

View file

@ -17,14 +17,18 @@
* under the License.
*/
import React, { Component } from 'react';
import React from 'react';
import { Markdown } from 'ui/markdown/markdown';
import { MarkdownVisParams } from './markdown_fn';
interface MarkdownVisComponentProps extends MarkdownVisParams {
renderComplete: () => {};
}
/**
* The MarkdownVisComponent renders markdown to HTML and presents it.
*/
class MarkdownVisComponent extends Component {
class MarkdownVisComponent extends React.Component<MarkdownVisComponentProps> {
/**
* Will be called after the first render when the component is present in the DOM.
*
@ -53,10 +57,7 @@ class MarkdownVisComponent extends Component {
*/
render() {
return (
<div
className="mkdVis"
style={{ fontSize: `${this.props.fontSize}pt` }}
>
<div className="mkdVis" style={{ fontSize: `${this.props.fontSize}pt` }}>
<Markdown
data-test-subj="markdownBody"
markdown={this.props.markdown}
@ -79,7 +80,7 @@ class MarkdownVisComponent extends Component {
* The way React works, this wrapper nearly brings no overhead, but allows us
* to use proper lifecycle methods in the actual component.
*/
export function MarkdownVisWrapper(props) {
export function MarkdownVisWrapper(props: any) {
return (
<MarkdownVisComponent
fontSize={props.visParams.fontSize}

View file

@ -6,7 +6,7 @@
<a target="_blank" href="https://help.github.com/articles/github-flavored-markdown/" rel="noreferrer noopener">
<icon aria-hidden="true" size="'s'" type="'link'"></icon>
<span
i18n-id="markdownVis.params.helpLinkLabel"
i18n-id="visTypeMarkdown.params.helpLinkLabel"
i18n-default-message="Help"
>
</span>
@ -16,7 +16,7 @@
<div class="visEditorSidebar__formRow">
<label class="visEditorSidebar__formLabel" for="markdownVisFontSize">
<span
i18n-id="markdownVis.params.fontSizeLabel"
i18n-id="visTypeMarkdown.params.fontSizeLabel"
i18n-default-message="Font Size ({fontSize}pt)"
i18n-values="{ fontSize: editorState.params.fontSize }"
>
@ -30,7 +30,7 @@
<label
class="visEditorSidebar__formLabel"
for="markdownVisOpenLinksInNewTab"
i18n-id="markdownVis.params.openLinksLabel"
i18n-id="visTypeMarkdown.params.openLinksLabel"
i18n-default-message="Open links in new tab"
>
</label>

View file

@ -21,16 +21,19 @@ import { Capabilities } from '../../../core/public';
export type InitPluginFunction = (server: Server) => void;
export interface UiExports {
injectDefaultVars: (server: Server) => { [key: string]: any };
injectDefaultVars?: (server: Server) => { [key: string]: any };
styleSheetPaths?: string;
visTypes?: string[];
interpreter?: string[];
hacks?: string[];
}
export interface PluginSpecOptions {
id: string;
require: string[];
publicDir: string;
require?: string[];
publicDir?: string;
uiExports?: UiExports;
uiCapabilities?: Capabilities;
init: InitPluginFunction;
config: any;
init?: InitPluginFunction;
config?: any;
}

View file

@ -2696,11 +2696,6 @@
"kbnVislibVisTypes.pie.pieTitle": "パイ",
"kbnVislibVisTypes.pie.segmentTitle": "スライスの分割",
"kbnVislibVisTypes.pie.splitTitle": "チャートを分割",
"markdownVis.function.help": "マークダウン ビジュアライゼーション",
"markdownVis.markdownDescription": "マークダウン構文でドキュメントを作成します。",
"markdownVis.params.fontSizeLabel": "フォントサイズ ({fontSize} pt)",
"markdownVis.params.helpLinkLabel": "ヘルプ",
"markdownVis.params.openLinksLabel": "新規タブでリンクを開く",
"metricVis.colorModes.backgroundOptionLabel": "背景",
"metricVis.colorModes.labelsOptionLabel": "ラベル",
"metricVis.colorModes.noneOptionLabel": "なし",

View file

@ -2697,11 +2697,6 @@
"kbnVislibVisTypes.pie.pieTitle": "饼图",
"kbnVislibVisTypes.pie.segmentTitle": "拆分切片",
"kbnVislibVisTypes.pie.splitTitle": "拆分图表",
"markdownVis.function.help": "Markdown 可视化",
"markdownVis.markdownDescription": "使用 Markdown 语法创建文档",
"markdownVis.params.fontSizeLabel": "字体大小({fontSize} 磅)",
"markdownVis.params.helpLinkLabel": "帮助",
"markdownVis.params.openLinksLabel": "在新标签页中打开链接",
"metricVis.colorModes.backgroundOptionLabel": "背景",
"metricVis.colorModes.labelsOptionLabel": "标签",
"metricVis.colorModes.noneOptionLabel": "无",